summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ISSUE_TEMPLATE.md18
-rw-r--r--core/bind/core_bind.cpp6
-rw-r--r--core/bind/core_bind.h2
-rw-r--r--core/io/resource_format_binary.cpp3
-rw-r--r--core/math/a_star.cpp18
-rw-r--r--core/math/a_star.h8
-rw-r--r--core/math/audio_frame.h33
-rw-r--r--core/math/bsp_tree.cpp30
-rw-r--r--core/math/bsp_tree.h8
-rw-r--r--core/math/camera_matrix.cpp64
-rw-r--r--core/math/camera_matrix.h24
-rw-r--r--core/math/face3.cpp56
-rw-r--r--core/math/face3.h22
-rw-r--r--core/math/geometry.cpp22
-rw-r--r--core/math/geometry.h120
-rw-r--r--core/math/math_2d.cpp6
-rw-r--r--core/math/math_funcs.cpp64
-rw-r--r--core/math/math_funcs.h229
-rw-r--r--core/math/matrix3.cpp20
-rw-r--r--core/math/octree.h2
-rw-r--r--core/math/plane.h2
-rw-r--r--core/math/quat.cpp18
-rw-r--r--core/math/quat.h4
-rw-r--r--core/math/quick_hull.cpp6
-rw-r--r--core/math/rect3.cpp10
-rw-r--r--core/math/rect3.h24
-rw-r--r--core/math/triangle_mesh.cpp4
-rw-r--r--core/math/triangulate.cpp24
-rw-r--r--core/math/triangulate.h10
-rw-r--r--core/math/vector3.cpp74
-rw-r--r--core/math/vector3.h16
-rw-r--r--core/method_ptrcall.h16
-rw-r--r--core/os/input.cpp3
-rw-r--r--core/os/input.h3
-rw-r--r--core/os/os.h3
-rw-r--r--core/resource.cpp1
-rw-r--r--core/ustring.cpp11
-rw-r--r--core/ustring.h1
-rw-r--r--core/variant_parser.cpp10
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp8
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp2
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp25
-rw-r--r--main/input_default.cpp2
-rw-r--r--main/main.cpp1
-rw-r--r--modules/gdscript/gd_functions.cpp64
-rw-r--r--modules/gdscript/gd_parser.cpp13
-rw-r--r--modules/gdscript/gd_tokenizer.cpp2
-rw-r--r--modules/gdscript/gd_tokenizer.h1
-rw-r--r--modules/stb_vorbis/SCsub10
-rw-r--r--modules/stb_vorbis/audio_stream_ogg_vorbis.cpp236
-rw-r--r--modules/stb_vorbis/audio_stream_ogg_vorbis.h84
-rw-r--r--modules/stb_vorbis/config.py7
-rw-r--r--modules/stb_vorbis/register_types.cpp (renamed from scene/resources/audio_stream.cpp)37
-rw-r--r--modules/stb_vorbis/register_types.h30
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.cpp62
-rw-r--r--platform/android/build.gradle.template3
-rw-r--r--platform/windows/os_windows.cpp41
-rw-r--r--platform/windows/os_windows.h1
-rw-r--r--platform/x11/os_x11.cpp60
-rw-r--r--platform/x11/os_x11.h2
-rw-r--r--scene/2d/collision_polygon_2d.cpp1
-rw-r--r--scene/2d/collision_shape_2d.cpp1
-rw-r--r--scene/2d/particles_2d.cpp6
-rw-r--r--scene/2d/physics_body_2d.cpp4
-rw-r--r--scene/3d/baked_light_instance.cpp8
-rw-r--r--scene/3d/gi_probe.cpp8
-rw-r--r--scene/3d/spatial.cpp2
-rw-r--r--scene/animation/animation_player.cpp23
-rw-r--r--scene/animation/animation_player.h2
-rw-r--r--scene/audio/audio_player.cpp301
-rw-r--r--scene/audio/audio_player.h75
-rw-r--r--scene/gui/button.cpp15
-rw-r--r--scene/gui/range.cpp10
-rw-r--r--scene/gui/spin_box.cpp2
-rw-r--r--scene/gui/texture_progress.cpp5
-rw-r--r--scene/gui/texture_rect.cpp2
-rw-r--r--scene/gui/tree.cpp30
-rw-r--r--scene/gui/tree.h5
-rw-r--r--scene/gui/video_player.cpp1
-rw-r--r--scene/main/viewport.cpp101
-rw-r--r--scene/main/viewport.h2
-rw-r--r--scene/register_scene_types.cpp9
-rw-r--r--scene/resources/audio_stream_resampled.h2
-rw-r--r--scene/resources/capsule_shape.cpp4
-rw-r--r--scene/resources/curve.cpp6
-rw-r--r--scene/resources/default_theme/theme_data.h6
-rw-r--r--scene/resources/default_theme/vslider_grabber.pngbin554 -> 394 bytes
-rw-r--r--scene/resources/default_theme/vslider_grabber_hl.pngbin701 -> 439 bytes
-rw-r--r--scene/resources/material.cpp2
-rw-r--r--scene/resources/scene_format_text.cpp13
-rw-r--r--scene/resources/sphere_shape.cpp4
-rw-r--r--servers/audio/SCsub2
-rw-r--r--servers/audio/audio_effect.h2
-rw-r--r--servers/audio/audio_filter_sw.cpp4
-rw-r--r--servers/audio/audio_filter_sw.h2
-rw-r--r--servers/audio/audio_stream.cpp86
-rw-r--r--servers/audio/audio_stream.h (renamed from scene/resources/audio_stream.h)60
-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_server.cpp980
-rw-r--r--servers/audio_server.h185
-rw-r--r--servers/physics_2d/broad_phase_2d_hash_grid.cpp8
-rw-r--r--servers/register_server_types.cpp51
-rw-r--r--thirdparty/stb_vorbis/stb_vorbis.c5399
-rw-r--r--tools/editor/animation_editor.cpp16
-rw-r--r--tools/editor/editor_audio_buses.cpp1192
-rw-r--r--tools/editor/editor_audio_buses.h186
-rw-r--r--tools/editor/editor_import_export.cpp16
-rw-r--r--tools/editor/editor_node.cpp185
-rw-r--r--tools/editor/editor_node.h5
-rw-r--r--tools/editor/editor_plugin.cpp10
-rw-r--r--tools/editor/editor_settings.cpp2
-rw-r--r--tools/editor/filesystem_dock.cpp27
-rw-r--r--tools/editor/filesystem_dock.h6
-rw-r--r--tools/editor/icons/2x/icon_anchor.pngbin816 -> 828 bytes
-rw-r--r--tools/editor/icons/2x/icon_animation.pngbin907 -> 912 bytes
-rw-r--r--tools/editor/icons/2x/icon_area.pngbin231 -> 209 bytes
-rw-r--r--tools/editor/icons/2x/icon_auto_play.pngbin696 -> 699 bytes
-rw-r--r--tools/editor/icons/2x/icon_bitmap_font.pngbin255 -> 191 bytes
-rw-r--r--tools/editor/icons/2x/icon_canvas_layer.pngbin857 -> 860 bytes
-rw-r--r--tools/editor/icons/2x/icon_canvas_modulate.pngbin536 -> 273 bytes
-rw-r--r--tools/editor/icons/2x/icon_copy_node_path.pngbin0 -> 356 bytes
-rw-r--r--tools/editor/icons/2x/icon_create_new_scene_from.pngbin613 -> 639 bytes
-rw-r--r--tools/editor/icons/2x/icon_dynamic_font_data.pngbin358 -> 379 bytes
-rw-r--r--tools/editor/icons/2x/icon_error.pngbin100 -> 155 bytes
-rw-r--r--tools/editor/icons/2x/icon_fixed_spatial_material.pngbin1619 -> 768 bytes
-rw-r--r--tools/editor/icons/2x/icon_key_next.pngbin534 -> 579 bytes
-rw-r--r--tools/editor/icons/2x/icon_material_shader.pngbin768 -> 342 bytes
-rw-r--r--tools/editor/icons/2x/icon_reparent.pngbin631 -> 741 bytes
-rw-r--r--tools/editor/icons/2x/icon_script_remove.pngbin0 -> 787 bytes
-rw-r--r--tools/editor/icons/2x/icon_shader.pngbin768 -> 342 bytes
-rw-r--r--tools/editor/icons/2x/icon_shader_material.pngbin768 -> 342 bytes
-rw-r--r--tools/editor/icons/2x/icon_spot_light.pngbin714 -> 669 bytes
-rw-r--r--tools/editor/icons/2x/icon_tab_container.pngbin330 -> 334 bytes
-rw-r--r--tools/editor/icons/2x/icon_tabs.pngbin210 -> 222 bytes
-rw-r--r--tools/editor/icons/2x/icon_track_add_key.pngbin125 -> 127 bytes
-rw-r--r--tools/editor/icons/2x/icon_track_add_key_hl.pngbin126 -> 128 bytes
-rw-r--r--tools/editor/icons/2x/icon_transparent.pngbin0 -> 177 bytes
-rw-r--r--tools/editor/icons/2x/icon_viewport_container.pngbin527 -> 528 bytes
-rw-r--r--tools/editor/icons/2x/icon_warning.pngbin100 -> 154 bytes
-rw-r--r--tools/editor/icons/icon_accept_dialog.pngbin336 -> 338 bytes
-rw-r--r--tools/editor/icons/icon_anchor.pngbin441 -> 451 bytes
-rw-r--r--tools/editor/icons/icon_animation.pngbin398 -> 399 bytes
-rw-r--r--tools/editor/icons/icon_area.pngbin196 -> 176 bytes
-rw-r--r--tools/editor/icons/icon_audio_effect_amplify.pngbin0 -> 379 bytes
-rw-r--r--tools/editor/icons/icon_auto_play.pngbin375 -> 370 bytes
-rw-r--r--tools/editor/icons/icon_bitmap_font.pngbin218 -> 160 bytes
-rw-r--r--tools/editor/icons/icon_bus_vu_db.pngbin0 -> 1136 bytes
-rw-r--r--tools/editor/icons/icon_bus_vu_empty.pngbin0 -> 1631 bytes
-rw-r--r--tools/editor/icons/icon_bus_vu_frozen.pngbin0 -> 267 bytes
-rw-r--r--tools/editor/icons/icon_bus_vu_full.pngbin0 -> 2463 bytes
-rw-r--r--tools/editor/icons/icon_canvas_layer.pngbin478 -> 474 bytes
-rw-r--r--tools/editor/icons/icon_canvas_modulate.pngbin348 -> 213 bytes
-rw-r--r--tools/editor/icons/icon_copy_node_path.pngbin0 -> 248 bytes
-rw-r--r--tools/editor/icons/icon_create_new_scene_from.pngbin322 -> 349 bytes
-rw-r--r--tools/editor/icons/icon_dynamic_font_data.pngbin237 -> 246 bytes
-rw-r--r--tools/editor/icons/icon_error.pngbin95 -> 121 bytes
-rw-r--r--tools/editor/icons/icon_fixed_spatial_material.pngbin681 -> 409 bytes
-rw-r--r--tools/editor/icons/icon_key_next.pngbin302 -> 321 bytes
-rw-r--r--tools/editor/icons/icon_material_shader.pngbin409 -> 254 bytes
-rw-r--r--tools/editor/icons/icon_reparent.pngbin320 -> 390 bytes
-rw-r--r--tools/editor/icons/icon_script_remove.pngbin0 -> 411 bytes
-rw-r--r--tools/editor/icons/icon_shader.pngbin409 -> 254 bytes
-rw-r--r--tools/editor/icons/icon_shader_material.pngbin409 -> 254 bytes
-rw-r--r--tools/editor/icons/icon_spot_light.pngbin359 -> 341 bytes
-rw-r--r--tools/editor/icons/icon_tab_container.pngbin215 -> 214 bytes
-rw-r--r--tools/editor/icons/icon_tabs.pngbin147 -> 146 bytes
-rw-r--r--tools/editor/icons/icon_track_add_key.pngbin113 -> 113 bytes
-rw-r--r--tools/editor/icons/icon_track_add_key_hl.pngbin113 -> 113 bytes
-rw-r--r--tools/editor/icons/icon_transparent.pngbin0 -> 158 bytes
-rw-r--r--tools/editor/icons/icon_viewport_container.pngbin304 -> 284 bytes
-rw-r--r--tools/editor/icons/icon_vu_db.pngbin0 -> 1015 bytes
-rw-r--r--tools/editor/icons/icon_warning.pngbin95 -> 120 bytes
-rw-r--r--tools/editor/icons/source/icon_accept_dialog.svg14
-rw-r--r--tools/editor/icons/source/icon_add_track.svg28
-rw-r--r--tools/editor/icons/source/icon_anchor.svg27
-rw-r--r--tools/editor/icons/source/icon_animation.svg53
-rw-r--r--tools/editor/icons/source/icon_area.svg99
-rw-r--r--tools/editor/icons/source/icon_area_2d.svg99
-rw-r--r--tools/editor/icons/source/icon_arrow_left.svg32
-rw-r--r--tools/editor/icons/source/icon_arrow_right.svg11
-rw-r--r--tools/editor/icons/source/icon_auto_play.svg45
-rw-r--r--tools/editor/icons/source/icon_back_buffer_copy.svg61
-rw-r--r--tools/editor/icons/source/icon_bake.svg22
-rw-r--r--tools/editor/icons/source/icon_baked_light.svg24
-rw-r--r--tools/editor/icons/source/icon_baked_light_instance.svg20
-rw-r--r--tools/editor/icons/source/icon_baked_light_sampler.svg18
-rw-r--r--tools/editor/icons/source/icon_bitmap_font.svg66
-rw-r--r--tools/editor/icons/source/icon_canvas_layer.svg38
-rw-r--r--tools/editor/icons/source/icon_canvas_modulate.svg102
-rw-r--r--tools/editor/icons/source/icon_connect.svg58
-rw-r--r--tools/editor/icons/source/icon_connection_and_groups.svg101
-rw-r--r--tools/editor/icons/source/icon_copy_node_path.svg98
-rw-r--r--tools/editor/icons/source/icon_create_new_scene_from.svg29
-rw-r--r--tools/editor/icons/source/icon_dynamic_font_data.svg10
-rw-r--r--tools/editor/icons/source/icon_error.svg7
-rw-r--r--tools/editor/icons/source/icon_fixed_spatial_material.svg148
-rw-r--r--tools/editor/icons/source/icon_key_next.svg31
-rw-r--r--tools/editor/icons/source/icon_reparent.svg57
-rw-r--r--tools/editor/icons/source/icon_script_remove.svg99
-rw-r--r--tools/editor/icons/source/icon_shader.svg15
-rw-r--r--tools/editor/icons/source/icon_spot_light.svg50
-rw-r--r--tools/editor/icons/source/icon_static_body.svg66
-rw-r--r--tools/editor/icons/source/icon_static_body_2d.svg43
-rw-r--r--tools/editor/icons/source/icon_tab_container.svg28
-rw-r--r--tools/editor/icons/source/icon_tabs.svg46
-rw-r--r--tools/editor/icons/source/icon_text_edit.svg27
-rw-r--r--tools/editor/icons/source/icon_track_add_key.svg6
-rw-r--r--tools/editor/icons/source/icon_track_add_key_hl.svg15
-rw-r--r--tools/editor/icons/source/icon_viewport_container.svg12
-rw-r--r--tools/editor/icons/source/icon_warning.svg17
-rw-r--r--tools/editor/io_plugins/editor_font_import_plugin.cpp2
-rw-r--r--tools/editor/io_plugins/editor_sample_import_plugin.cpp2
-rw-r--r--tools/editor/plugins/canvas_item_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/multimesh_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/spatial_editor_plugin.cpp2
-rw-r--r--tools/editor/property_editor.cpp30
-rw-r--r--tools/editor/property_editor.h1
-rw-r--r--tools/editor/scene_tree_dock.cpp8
-rw-r--r--tools/editor/scene_tree_editor.cpp36
-rw-r--r--tools/editor/script_editor_debugger.cpp2
-rw-r--r--tools/editor/spatial_editor_gizmos.cpp28
251 files changed, 14610 insertions, 2149 deletions
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
index 294acd5bae..93ded6c954 100644
--- a/ISSUE_TEMPLATE.md
+++ b/ISSUE_TEMPLATE.md
@@ -1,19 +1,17 @@
-vvv Remove me vvv
-
-*NOTE:* If you using the current master branch / 3.0-alpha version, do note that
-breakage is *expected*. Projects from Godot 2.x are expected not to work. Please
-wait for the upcoming stabilisation period to report bugs regarding recent changes.
-
-^^^ Remove me ^^^
-
+<!--
+README: Incompatibilities and broken features in the current master branch / 3.0-alpha
+are known and expected due to important refactoring work, so no need to report them for now. Thanks!
+-->
**Operating system or device - Godot version:**
-**Issue description** (what happened, and what was expected):
+**Issue description:**
+<!-- What happened, and what was expected. -->
**Steps to reproduce:**
-**Link to minimal example project** (optional but very welcome):
+**Link to minimal example project:**
+<!-- Optional but very welcome. You can drag and drop a zip archive to upload it. -->:
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index bec46bc7df..80adafe092 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -1732,6 +1732,11 @@ Variant _File::get_var() const {
return v;
}
+uint64_t _File::get_modified_time(const String &p_file) const {
+
+ return FileAccess::get_modified_time(p_file);
+}
+
void _File::_bind_methods() {
@@ -1780,6 +1785,7 @@ void _File::_bind_methods() {
ClassDB::bind_method(_MD("get_pascal_string"),&_File::get_pascal_string);
ClassDB::bind_method(_MD("file_exists","path"),&_File::file_exists);
+ ClassDB::bind_method(_MD("get_modified_time", "file"),&_File::get_modified_time);
BIND_CONSTANT( READ );
BIND_CONSTANT( WRITE );
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 4d4b16369f..13081fc867 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -440,6 +440,8 @@ public:
bool file_exists(const String& p_name) const; ///< return true if a file exists
+ uint64_t get_modified_time(const String& p_file) const;
+
_File();
virtual ~_File();
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 4af3503434..8f8fce0891 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -80,7 +80,8 @@ enum {
OBJECT_EXTERNAL_RESOURCE=1,
OBJECT_INTERNAL_RESOURCE=2,
OBJECT_EXTERNAL_RESOURCE_INDEX=3,
- FORMAT_VERSION=1,
+ //version 2: added 64 bits support for float and int
+ FORMAT_VERSION=2,
FORMAT_VERSION_CAN_RENAME_DEPS=1
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index 2c45009a60..a1f471ebe3 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -39,7 +39,7 @@ int AStar::get_available_point_id() const {
return points.back()->key()+1;
}
-void AStar::add_point(int p_id, const Vector3 &p_pos, float p_weight_scale) {
+void AStar::add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale) {
ERR_FAIL_COND(p_id<0);
if (!points.has(p_id)) {
Point *pt = memnew( Point );
@@ -62,7 +62,7 @@ Vector3 AStar::get_point_pos(int p_id) const{
return points[p_id]->pos;
}
-float AStar::get_point_weight_scale(int p_id) const{
+real_t AStar::get_point_weight_scale(int p_id) const{
ERR_FAIL_COND_V(!points.has(p_id),0);
@@ -145,11 +145,11 @@ void AStar::clear(){
int AStar::get_closest_point(const Vector3& p_point) const{
int closest_id=-1;
- float closest_dist=1e20;
+ real_t closest_dist=1e20;
for (const Map<int,Point*>::Element *E=points.front();E;E=E->next()) {
- float d = p_point.distance_squared_to(E->get()->pos);
+ real_t d = p_point.distance_squared_to(E->get()->pos);
if (closest_id<0 || d<closest_dist) {
closest_dist=d;
closest_id=E->key();
@@ -162,7 +162,7 @@ int AStar::get_closest_point(const Vector3& p_point) const{
}
Vector3 AStar::get_closest_pos_in_segment(const Vector3& p_point) const {
- float closest_dist = 1e20;
+ real_t closest_dist = 1e20;
bool found=false;
Vector3 closest_point;
@@ -175,7 +175,7 @@ Vector3 AStar::get_closest_pos_in_segment(const Vector3& p_point) const {
};
Vector3 p = Geometry::get_closest_point_to_segment(p_point,segment);
- float d = p_point.distance_squared_to(p);
+ real_t d = p_point.distance_squared_to(p);
if (!found || d<closest_dist) {
closest_point=p;
@@ -220,14 +220,14 @@ bool AStar::_solve(Point* begin_point, Point* end_point) {
//check open list
SelfList<Point> *least_cost_point=NULL;
- float least_cost=1e30;
+ real_t least_cost=1e30;
//this could be faster (cache previous results)
for (SelfList<Point> *E=open_list.first();E;E=E->next()) {
Point *p=E->self();
- float cost=p->distance;
+ real_t cost=p->distance;
cost+=p->pos.distance_to(end_point->pos);
cost*=p->weight_scale;
@@ -249,7 +249,7 @@ bool AStar::_solve(Point* begin_point, Point* end_point) {
Point* e=p->neighbours[i];
- float distance = p->pos.distance_to(e->pos) + p->distance;
+ real_t distance = p->pos.distance_to(e->pos) + p->distance;
distance*=e->weight_scale;
diff --git a/core/math/a_star.h b/core/math/a_star.h
index 35e6ead226..c4c955ed2d 100644
--- a/core/math/a_star.h
+++ b/core/math/a_star.h
@@ -48,14 +48,14 @@ class AStar: public Reference {
int id;
Vector3 pos;
- float weight_scale;
+ real_t weight_scale;
uint64_t last_pass;
Vector<Point*> neighbours;
//used for pathfinding
Point *prev_point;
- float distance;
+ real_t distance;
Point() : list(this) {}
};
@@ -98,9 +98,9 @@ public:
int get_available_point_id() const;
- void add_point(int p_id,const Vector3& p_pos,float p_weight_scale=1);
+ void add_point(int p_id,const Vector3& p_pos,real_t p_weight_scale=1);
Vector3 get_point_pos(int p_id) const;
- float get_point_weight_scale(int p_id) const;
+ real_t get_point_weight_scale(int p_id) const;
void remove_point(int p_id);
void connect_points(int p_id,int p_with_id);
diff --git a/core/math/audio_frame.h b/core/math/audio_frame.h
index dbababf762..acd74903bb 100644
--- a/core/math/audio_frame.h
+++ b/core/math/audio_frame.h
@@ -3,8 +3,25 @@
#include "typedefs.h"
+
+static inline float undenormalise(volatile float f)
+{
+ union {
+ uint32_t i;
+ float f;
+ } v;
+
+ v.f = f;
+
+ // original: return (v.i & 0x7f800000) == 0 ? 0.0f : f;
+ // version from Tim Blechmann:
+ return (v.i & 0x7f800000) < 0x08000000 ? 0.0f : f;
+}
+
+
struct AudioFrame {
+ //left and right samples
float l,r;
_ALWAYS_INLINE_ const float& operator[](int idx) const { return idx==0?l:r; }
@@ -15,14 +32,30 @@ struct AudioFrame {
_ALWAYS_INLINE_ AudioFrame operator*(const AudioFrame& p_frame) const { return AudioFrame(l*p_frame.l,r*p_frame.r); }
_ALWAYS_INLINE_ AudioFrame operator/(const AudioFrame& p_frame) const { return AudioFrame(l/p_frame.l,r/p_frame.r); }
+ _ALWAYS_INLINE_ AudioFrame operator+(float p_sample) const { return AudioFrame(l+p_sample,r+p_sample); }
+ _ALWAYS_INLINE_ AudioFrame operator-(float p_sample) const { return AudioFrame(l-p_sample,r-p_sample); }
+ _ALWAYS_INLINE_ AudioFrame operator*(float p_sample) const { return AudioFrame(l*p_sample,r*p_sample); }
+ _ALWAYS_INLINE_ AudioFrame operator/(float p_sample) const { return AudioFrame(l/p_sample,r/p_sample); }
+
_ALWAYS_INLINE_ void operator+=(const AudioFrame& p_frame) { l+=p_frame.l; r+=p_frame.r; }
_ALWAYS_INLINE_ void operator-=(const AudioFrame& p_frame) { l-=p_frame.l; r-=p_frame.r; }
_ALWAYS_INLINE_ void operator*=(const AudioFrame& p_frame) { l*=p_frame.l; r*=p_frame.r; }
_ALWAYS_INLINE_ void operator/=(const AudioFrame& p_frame) { l/=p_frame.l; r/=p_frame.r; }
+ _ALWAYS_INLINE_ void operator+=(float p_sample) { l+=p_sample; r+=p_sample; }
+ _ALWAYS_INLINE_ void operator-=(float p_sample) { l-=p_sample; r-=p_sample; }
+ _ALWAYS_INLINE_ void operator*=(float p_sample) { l*=p_sample; r*=p_sample; }
+ _ALWAYS_INLINE_ void operator/=(float p_sample) { l/=p_sample; r/=p_sample; }
+
+ _ALWAYS_INLINE_ void undenormalise() {
+ l = ::undenormalise(l);
+ r = ::undenormalise(r);
+ }
+
_ALWAYS_INLINE_ AudioFrame(float p_l, float p_r) {l=p_l; r=p_r;}
_ALWAYS_INLINE_ AudioFrame(const AudioFrame& p_frame) {l=p_frame.l; r=p_frame.r;}
+ _ALWAYS_INLINE_ AudioFrame() {}
};
#endif
diff --git a/core/math/bsp_tree.cpp b/core/math/bsp_tree.cpp
index e2526f5134..1ca6385032 100644
--- a/core/math/bsp_tree.cpp
+++ b/core/math/bsp_tree.cpp
@@ -87,8 +87,8 @@ int BSP_Tree::_get_points_inside(int p_node,const Vector3* p_points,int *p_indic
max+=p_center;
min+=p_center;
- float dist_min = p.distance_to(min);
- float dist_max = p.distance_to(max);
+ real_t dist_min = p.distance_to(min);
+ real_t dist_max = p.distance_to(max);
if ((dist_min * dist_max) < CMP_EPSILON ) { //intersection, test point by point
@@ -290,13 +290,13 @@ bool BSP_Tree::point_is_inside(const Vector3& p_point) const {
}
-static int _bsp_find_best_half_plane(const Face3* p_faces,const Vector<int>& p_indices,float p_tolerance) {
+static int _bsp_find_best_half_plane(const Face3* p_faces,const Vector<int>& p_indices,real_t p_tolerance) {
int ic = p_indices.size();
const int*indices=p_indices.ptr();
int best_plane = -1;
- float best_plane_cost = 1e20;
+ real_t best_plane_cost = 1e20;
// Loop to find the polygon that best divides the set.
@@ -317,7 +317,7 @@ static int _bsp_find_best_half_plane(const Face3* p_faces,const Vector<int>& p_i
for(int k=0;k<3;k++) {
- float d = p.distance_to(g.vertex[j]);
+ real_t d = p.distance_to(g.vertex[j]);
if (Math::abs(d)>p_tolerance) {
@@ -340,13 +340,13 @@ static int _bsp_find_best_half_plane(const Face3* p_faces,const Vector<int>& p_i
- //double split_cost = num_spanning / (double) face_count;
- double relation = Math::abs(num_over-num_under) / (double) ic;
+ //real_t split_cost = num_spanning / (real_t) face_count;
+ real_t relation = Math::abs(num_over-num_under) / (real_t) ic;
// being honest, i never found a way to add split cost to the mix in a meaninguful way
// in this engine, also, will likely be ignored anyway
- double plane_cost = /*split_cost +*/ relation;
+ real_t plane_cost = /*split_cost +*/ relation;
//printf("plane %i, %i over, %i under, %i spanning, cost is %g\n",i,num_over,num_under,num_spanning,plane_cost);
if (plane_cost<best_plane_cost) {
@@ -362,7 +362,7 @@ static int _bsp_find_best_half_plane(const Face3* p_faces,const Vector<int>& p_i
}
-static int _bsp_create_node(const Face3 *p_faces,const Vector<int>& p_indices,Vector<Plane> &p_planes, Vector<BSP_Tree::Node> &p_nodes,float p_tolerance) {
+static int _bsp_create_node(const Face3 *p_faces,const Vector<int>& p_indices,Vector<Plane> &p_planes, Vector<BSP_Tree::Node> &p_nodes,real_t p_tolerance) {
ERR_FAIL_COND_V( p_nodes.size() == BSP_Tree::MAX_NODES, -1 );
@@ -400,7 +400,7 @@ static int _bsp_create_node(const Face3 *p_faces,const Vector<int>& p_indices,Ve
for(int j=0;j<3;j++) {
- float d = divisor_plane.distance_to(f.vertex[j]);
+ real_t d = divisor_plane.distance_to(f.vertex[j]);
if (Math::abs(d)>p_tolerance) {
if (d > 0)
@@ -473,7 +473,7 @@ BSP_Tree::operator Variant() const {
Dictionary d;
d["error_radius"]=error_radius;
- Vector<float> plane_values;
+ Vector<real_t> plane_values;
plane_values.resize(planes.size()*4);
for(int i=0;i<planes.size();i++) {
@@ -522,13 +522,13 @@ BSP_Tree::BSP_Tree(const Variant& p_variant) {
if (d["planes"].get_type()==Variant::POOL_REAL_ARRAY) {
- PoolVector<float> src_planes=d["planes"];
+ PoolVector<real_t> src_planes=d["planes"];
int plane_count=src_planes.size();
ERR_FAIL_COND(plane_count%4);
planes.resize(plane_count/4);
if (plane_count) {
- PoolVector<float>::Read r = src_planes.read();
+ PoolVector<real_t>::Read r = src_planes.read();
for(int i=0;i<plane_count/4;i++) {
planes[i].normal.x=r[i*4+0];
@@ -562,7 +562,7 @@ BSP_Tree::BSP_Tree(const Variant& p_variant) {
}
-BSP_Tree::BSP_Tree(const PoolVector<Face3>& p_faces,float p_error_radius) {
+BSP_Tree::BSP_Tree(const PoolVector<Face3>& p_faces,real_t p_error_radius) {
// compute aabb
@@ -615,7 +615,7 @@ BSP_Tree::BSP_Tree(const PoolVector<Face3>& p_faces,float p_error_radius) {
error_radius=p_error_radius;
}
-BSP_Tree::BSP_Tree(const Vector<Node> &p_nodes, const Vector<Plane> &p_planes, const Rect3& p_aabb,float p_error_radius) {
+BSP_Tree::BSP_Tree(const Vector<Node> &p_nodes, const Vector<Plane> &p_planes, const Rect3& p_aabb,real_t p_error_radius) {
nodes=p_nodes;
planes=p_planes;
diff --git a/core/math/bsp_tree.h b/core/math/bsp_tree.h
index a64fffcb78..c0071438db 100644
--- a/core/math/bsp_tree.h
+++ b/core/math/bsp_tree.h
@@ -66,7 +66,7 @@ private:
Vector<Node> nodes;
Vector<Plane> planes;
Rect3 aabb;
- float error_radius;
+ real_t error_radius;
int _get_points_inside(int p_node,const Vector3* p_points,int *p_indices, const Vector3& p_center,const Vector3& p_half_extents,int p_indices_count) const;
@@ -91,8 +91,8 @@ public:
BSP_Tree();
BSP_Tree(const Variant& p_variant);
- BSP_Tree(const PoolVector<Face3>& p_faces,float p_error_radius=0);
- BSP_Tree(const Vector<Node> &p_nodes, const Vector<Plane> &p_planes, const Rect3& p_aabb,float p_error_radius=0);
+ BSP_Tree(const PoolVector<Face3>& p_faces,real_t p_error_radius=0);
+ BSP_Tree(const Vector<Node> &p_nodes, const Vector<Plane> &p_planes, const Rect3& p_aabb,real_t p_error_radius=0);
~BSP_Tree();
};
@@ -110,7 +110,7 @@ bool BSP_Tree::_test_convex(const Node* p_nodes, const Plane* p_planes,int p_cur
const Plane& p=p_planes[n.plane];
- float min,max;
+ real_t min,max;
p_convex.project_range(p.normal,min,max);
bool go_under = min < p.d;
diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp
index 7669356f5e..3b47a75c65 100644
--- a/core/math/camera_matrix.cpp
+++ b/core/math/camera_matrix.cpp
@@ -65,15 +65,15 @@ Plane CameraMatrix::xform4(const Plane& p_vec4) const {
return ret;
}
-void CameraMatrix::set_perspective(float p_fovy_degrees, float p_aspect, float p_z_near, float p_z_far,bool p_flip_fov) {
+void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far,bool p_flip_fov) {
if (p_flip_fov) {
p_fovy_degrees=get_fovy(p_fovy_degrees,1.0/p_aspect);
}
- float sine, cotangent, deltaZ;
- float radians = p_fovy_degrees / 2.0 * Math_PI / 180.0;
+ real_t sine, cotangent, deltaZ;
+ real_t radians = p_fovy_degrees / 2.0 * Math_PI / 180.0;
deltaZ = p_z_far - p_z_near;
sine = Math::sin(radians);
@@ -94,7 +94,7 @@ void CameraMatrix::set_perspective(float p_fovy_degrees, float p_aspect, float p
}
-void CameraMatrix::set_orthogonal(float p_left, float p_right, float p_bottom, float p_top, float p_znear, float p_zfar) {
+void CameraMatrix::set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) {
set_identity();
@@ -109,7 +109,7 @@ void CameraMatrix::set_orthogonal(float p_left, float p_right, float p_bottom, f
}
-void CameraMatrix::set_orthogonal(float p_size, float p_aspect, float p_znear, float p_zfar,bool p_flip_fov) {
+void CameraMatrix::set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar,bool p_flip_fov) {
if (!p_flip_fov) {
p_size*=p_aspect;
@@ -120,7 +120,7 @@ void CameraMatrix::set_orthogonal(float p_size, float p_aspect, float p_znear, f
-void CameraMatrix::set_frustum(float p_left, float p_right, float p_bottom, float p_top, float p_near, float p_far) {
+void CameraMatrix::set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) {
#if 0
///@TODO, give a check to this. I'm not sure if it's working.
set_identity();
@@ -134,14 +134,14 @@ void CameraMatrix::set_frustum(float p_left, float p_right, float p_bottom, floa
matrix[3][2]=-1;
matrix[3][3]=0;
#else
- float *te = &matrix[0][0];
- float x = 2 * p_near / ( p_right - p_left );
- float y = 2 * p_near / ( p_top - p_bottom );
+ real_t *te = &matrix[0][0];
+ real_t x = 2 * p_near / ( p_right - p_left );
+ real_t y = 2 * p_near / ( p_top - p_bottom );
- float a = ( p_right + p_left ) / ( p_right - p_left );
- float b = ( p_top + p_bottom ) / ( p_top - p_bottom );
- float c = - ( p_far + p_near ) / ( p_far - p_near );
- float d = - 2 * p_far * p_near / ( p_far - p_near );
+ real_t a = ( p_right + p_left ) / ( p_right - p_left );
+ real_t b = ( p_top + p_bottom ) / ( p_top - p_bottom );
+ real_t c = - ( p_far + p_near ) / ( p_far - p_near );
+ real_t d = - 2 * p_far * p_near / ( p_far - p_near );
te[0] = x;
te[1] = 0;
@@ -166,9 +166,9 @@ void CameraMatrix::set_frustum(float p_left, float p_right, float p_bottom, floa
-float CameraMatrix::get_z_far() const {
+real_t CameraMatrix::get_z_far() const {
- const float * matrix = (const float*)this->matrix;
+ const real_t * matrix = (const real_t*)this->matrix;
Plane new_plane=Plane(matrix[ 3] - matrix[ 2],
matrix[ 7] - matrix[ 6],
matrix[11] - matrix[10],
@@ -179,9 +179,9 @@ float CameraMatrix::get_z_far() const {
return new_plane.d;
}
-float CameraMatrix::get_z_near() const {
+real_t CameraMatrix::get_z_near() const {
- const float * matrix = (const float*)this->matrix;
+ const real_t * matrix = (const real_t*)this->matrix;
Plane new_plane=Plane(matrix[ 3] + matrix[ 2],
matrix[ 7] + matrix[ 6],
matrix[11] + matrix[10],
@@ -191,9 +191,9 @@ float CameraMatrix::get_z_near() const {
return new_plane.d;
}
-void CameraMatrix::get_viewport_size(float& r_width, float& r_height) const {
+void CameraMatrix::get_viewport_size(real_t& r_width, real_t& r_height) const {
- const float * matrix = (const float*)this->matrix;
+ const real_t * matrix = (const real_t*)this->matrix;
///////--- Near Plane ---///////
Plane near_plane=Plane(matrix[ 3] + matrix[ 2],
matrix[ 7] + matrix[ 6],
@@ -223,7 +223,7 @@ void CameraMatrix::get_viewport_size(float& r_width, float& r_height) const {
bool CameraMatrix::get_endpoints(const Transform& p_transform, Vector3 *p_8points) const {
- const float * matrix = (const float*)this->matrix;
+ const real_t * matrix = (const real_t*)this->matrix;
///////--- Near Plane ---///////
Plane near_plane=Plane(matrix[ 3] + matrix[ 2],
@@ -284,7 +284,7 @@ Vector<Plane> CameraMatrix::get_projection_planes(const Transform& p_transform)
Vector<Plane> planes;
- const float * matrix = (const float*)this->matrix;
+ const real_t * matrix = (const real_t*)this->matrix;
Plane new_plane;
@@ -377,9 +377,9 @@ void CameraMatrix::invert() {
int i,j,k;
int pvt_i[4], pvt_j[4]; /* Locations of pivot matrix */
- float pvt_val; /* Value of current pivot element */
- float hold; /* Temporary storage */
- float determinat; /* Determinant */
+ real_t pvt_val; /* Value of current pivot element */
+ real_t hold; /* Temporary storage */
+ real_t determinat; /* Determinant */
determinat = 1.0;
for (k=0; k<4; k++) {
@@ -492,7 +492,7 @@ CameraMatrix CameraMatrix::operator*(const CameraMatrix& p_matrix) const {
void CameraMatrix::set_light_bias() {
- float *m=&matrix[0][0];
+ real_t *m=&matrix[0][0];
m[0]=0.5,
m[1]=0.0,
@@ -515,7 +515,7 @@ void CameraMatrix::set_light_bias() {
void CameraMatrix::set_light_atlas_rect(const Rect2& p_rect) {
- float *m=&matrix[0][0];
+ real_t *m=&matrix[0][0];
m[0]=p_rect.size.width,
m[1]=0.0,
@@ -545,9 +545,9 @@ CameraMatrix::operator String() const {
return str;
}
-float CameraMatrix::get_aspect() const {
+real_t CameraMatrix::get_aspect() const {
- float w,h;
+ real_t w,h;
get_viewport_size(w,h);
return w/h;
}
@@ -561,8 +561,8 @@ int CameraMatrix::get_pixels_per_meter(int p_for_pixel_width) const {
}
-float CameraMatrix::get_fov() const {
- const float * matrix = (const float*)this->matrix;
+real_t CameraMatrix::get_fov() const {
+ const real_t * matrix = (const real_t*)this->matrix;
Plane right_plane=Plane(matrix[ 3] - matrix[ 0],
matrix[ 7] - matrix[ 4],
@@ -613,7 +613,7 @@ void CameraMatrix::scale_translate_to_fit(const Rect3& p_aabb) {
CameraMatrix::operator Transform() const {
Transform tr;
- const float *m=&matrix[0][0];
+ const real_t *m=&matrix[0][0];
tr.basis.elements[0][0]=m[0];
tr.basis.elements[1][0]=m[1];
@@ -637,7 +637,7 @@ CameraMatrix::operator Transform() const {
CameraMatrix::CameraMatrix(const Transform& p_transform) {
const Transform &tr = p_transform;
- float *m=&matrix[0][0];
+ real_t *m=&matrix[0][0];
m[0]=tr.basis.elements[0][0];
m[1]=tr.basis.elements[1][0];
diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h
index 952f1e8fb2..c96f8259b5 100644
--- a/core/math/camera_matrix.h
+++ b/core/math/camera_matrix.h
@@ -48,32 +48,32 @@ struct CameraMatrix {
PLANE_BOTTOM
};
- float matrix[4][4];
+ real_t matrix[4][4];
void set_identity();
void set_zero();
void set_light_bias();
void set_light_atlas_rect(const Rect2& p_rect);
- void set_perspective(float p_fovy_degrees, float p_aspect, float p_z_near, float p_z_far,bool p_flip_fov=false);
- void set_orthogonal(float p_left, float p_right, float p_bottom, float p_top, float p_znear, float p_zfar);
- void set_orthogonal(float p_size, float p_aspect, float p_znear, float p_zfar,bool p_flip_fov=false);
- void set_frustum(float p_left, float p_right, float p_bottom, float p_top, float p_near, float p_far);
+ void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far,bool p_flip_fov=false);
+ void set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar);
+ void set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar,bool p_flip_fov=false);
+ void set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far);
- static float get_fovy(float p_fovx,float p_aspect) {
+ static real_t get_fovy(real_t p_fovx,real_t p_aspect) {
return Math::rad2deg(Math::atan(p_aspect * Math::tan(Math::deg2rad(p_fovx) * 0.5))*2.0);
}
- float get_z_far() const;
- float get_z_near() const;
- float get_aspect() const;
- float get_fov() const;
+ real_t get_z_far() const;
+ real_t get_z_near() const;
+ real_t get_aspect() const;
+ real_t get_fov() const;
Vector<Plane> get_projection_planes(const Transform& p_transform) const;
bool get_endpoints(const Transform& p_transform,Vector3 *p_8points) const;
- void get_viewport_size(float& r_width, float& r_height) const;
+ void get_viewport_size(real_t& r_width, real_t& r_height) const;
void invert();
CameraMatrix inverse() const;
@@ -102,7 +102,7 @@ Vector3 CameraMatrix::xform(const Vector3& p_vec3) const {
ret.x = matrix[0][0] * p_vec3.x + matrix[1][0] * p_vec3.y + matrix[2][0] * p_vec3.z + matrix[3][0];
ret.y = matrix[0][1] * p_vec3.x + matrix[1][1] * p_vec3.y + matrix[2][1] * p_vec3.z + matrix[3][1];
ret.z = matrix[0][2] * p_vec3.x + matrix[1][2] * p_vec3.y + matrix[2][2] * p_vec3.z + matrix[3][2];
- float w = matrix[0][3] * p_vec3.x + matrix[1][3] * p_vec3.y + matrix[2][3] * p_vec3.z + matrix[3][3];
+ real_t w = matrix[0][3] * p_vec3.x + matrix[1][3] * p_vec3.y + matrix[2][3] * p_vec3.z + matrix[3][3];
return ret/w;
}
diff --git a/core/math/face3.cpp b/core/math/face3.cpp
index faf124593e..60fab6748a 100644
--- a/core/math/face3.cpp
+++ b/core/math/face3.cpp
@@ -168,8 +168,8 @@ Face3::Side Face3::get_side_of(const Face3& p_face,ClockDirection p_clock_dir) c
Vector3 Face3::get_random_point_inside() const {
- float a=Math::random(0,1);
- float b=Math::random(0,1);
+ real_t a=Math::random(0,1);
+ real_t b=Math::random(0,1);
if (a>b) {
SWAP(a,b);
}
@@ -215,9 +215,9 @@ bool Face3::intersects_aabb(const Rect3& p_aabb) const {
#define TEST_AXIS(m_ax)\
{\
- float aabb_min=p_aabb.pos.m_ax;\
- float aabb_max=p_aabb.pos.m_ax+p_aabb.size.m_ax;\
- float tri_min,tri_max;\
+ real_t aabb_min=p_aabb.pos.m_ax;\
+ real_t aabb_max=p_aabb.pos.m_ax+p_aabb.size.m_ax;\
+ real_t tri_min,tri_max;\
for (int i=0;i<3;i++) {\
if (i==0 || vertex[i].m_ax > tri_max)\
tri_max=vertex[i].m_ax;\
@@ -255,7 +255,7 @@ bool Face3::intersects_aabb(const Rect3& p_aabb) const {
continue; // coplanar
axis.normalize();
- float minA,maxA,minB,maxB;
+ real_t minA,maxA,minB,maxB;
p_aabb.project_range_in_plane(Plane(axis,0),minA,maxA);
project_range(axis,Transform(),minB,maxB);
@@ -272,12 +272,12 @@ Face3::operator String() const {
return String()+vertex[0]+", "+vertex[1]+", "+vertex[2];
}
-void Face3::project_range(const Vector3& p_normal,const Transform& p_transform,float& r_min, float& r_max) const {
+void Face3::project_range(const Vector3& p_normal,const Transform& p_transform,real_t& r_min, real_t& r_max) const {
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;
@@ -316,11 +316,11 @@ void Face3::get_support(const Vector3& p_normal,const Transform& p_transform,Vec
/** 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;
@@ -336,7 +336,7 @@ void Face3::get_support(const Vector3& p_normal,const Transform& p_transform,Vec
continue;
// check if edge is valid as a support
- float dot=(vertex[i]-vertex[(i+1)%3]).normalized().dot(n);
+ real_t dot=(vertex[i]-vertex[(i+1)%3]).normalized().dot(n);
dot=ABS(dot);
if (dot < _EDGE_IS_VALID_SUPPORT_TRESHOLD) {
@@ -362,15 +362,15 @@ Vector3 Face3::get_closest_point_to(const Vector3& p_point) const {
Vector3 edge1 = vertex[2] - vertex[0];
Vector3 v0 = vertex[0] - p_point;
- float a = edge0.dot( edge0 );
- float b = edge0.dot( edge1 );
- float c = edge1.dot( edge1 );
- float d = edge0.dot( v0 );
- float e = edge1.dot( v0 );
+ real_t a = edge0.dot( edge0 );
+ real_t b = edge0.dot( edge1 );
+ real_t c = edge1.dot( edge1 );
+ real_t d = edge0.dot( v0 );
+ real_t e = edge1.dot( v0 );
- float det = a*c - b*b;
- float s = b*e - c*d;
- float t = b*d - a*e;
+ real_t det = a*c - b*b;
+ real_t s = b*e - c*d;
+ real_t t = b*d - a*e;
if ( s + t < det )
{
@@ -402,7 +402,7 @@ Vector3 Face3::get_closest_point_to(const Vector3& p_point) const {
}
else
{
- float invDet = 1.f / det;
+ real_t invDet = 1.f / det;
s *= invDet;
t *= invDet;
}
@@ -411,12 +411,12 @@ Vector3 Face3::get_closest_point_to(const Vector3& p_point) const {
{
if ( s < 0.f )
{
- float tmp0 = b+d;
- float tmp1 = c+e;
+ real_t tmp0 = b+d;
+ real_t tmp1 = c+e;
if ( tmp1 > tmp0 )
{
- float numer = tmp1 - tmp0;
- float denom = a-2*b+c;
+ real_t numer = tmp1 - tmp0;
+ real_t denom = a-2*b+c;
s = CLAMP( numer/denom, 0.f, 1.f );
t = 1-s;
}
@@ -430,8 +430,8 @@ Vector3 Face3::get_closest_point_to(const Vector3& p_point) const {
{
if ( a+d > b+e )
{
- float numer = c+e-b-d;
- float denom = a-2*b+c;
+ real_t numer = c+e-b-d;
+ real_t denom = a-2*b+c;
s = CLAMP( numer/denom, 0.f, 1.f );
t = 1-s;
}
@@ -443,8 +443,8 @@ Vector3 Face3::get_closest_point_to(const Vector3& p_point) const {
}
else
{
- float numer = c+e-b-d;
- float denom = a-2*b+c;
+ real_t numer = c+e-b-d;
+ real_t denom = a-2*b+c;
s = CLAMP( numer/denom, 0.f, 1.f );
t = 1.f - s;
}
diff --git a/core/math/face3.h b/core/math/face3.h
index e957f64320..a0da588ea5 100644
--- a/core/math/face3.h
+++ b/core/math/face3.h
@@ -76,7 +76,7 @@ public:
ClockDirection get_clock_dir() const; ///< todo, test if this is returning the proper clockwisity
void get_support(const Vector3& p_normal,const Transform& p_transform,Vector3 *p_vertices,int* p_count,int p_max) const;
- void project_range(const Vector3& p_normal,const Transform& p_transform,float& r_min, float& r_max) const;
+ void project_range(const Vector3& p_normal,const Transform& p_transform,real_t& r_min, real_t& r_max) const;
Rect3 get_aabb() const {
@@ -109,9 +109,9 @@ bool Face3::intersects_aabb2(const Rect3& p_aabb) const {
(perp.z>0) ? -half_extents.z : half_extents.z
);
- float d = perp.dot(vertex[0]);
- float dist_a = perp.dot(ofs+sup)-d;
- float dist_b = perp.dot(ofs-sup)-d;
+ real_t d = perp.dot(vertex[0]);
+ real_t dist_a = perp.dot(ofs+sup)-d;
+ real_t dist_b = perp.dot(ofs-sup)-d;
if (dist_a*dist_b > 0)
return false; //does not intersect the plane
@@ -119,9 +119,9 @@ bool Face3::intersects_aabb2(const Rect3& p_aabb) const {
#define TEST_AXIS(m_ax)\
{\
- float aabb_min=p_aabb.pos.m_ax;\
- float aabb_max=p_aabb.pos.m_ax+p_aabb.size.m_ax;\
- float tri_min,tri_max;\
+ real_t aabb_min=p_aabb.pos.m_ax;\
+ real_t aabb_max=p_aabb.pos.m_ax+p_aabb.size.m_ax;\
+ real_t tri_min,tri_max;\
for (int i=0;i<3;i++) {\
if (i==0 || vertex[i].m_ax > tri_max)\
tri_max=vertex[i].m_ax;\
@@ -236,16 +236,16 @@ bool Face3::intersects_aabb2(const Rect3& p_aabb) const {
(axis.z>0) ? -half_extents.z : half_extents.z
);
- float maxB = axis.dot(ofs+sup2);
- float minB = axis.dot(ofs-sup2);
+ real_t maxB = axis.dot(ofs+sup2);
+ real_t minB = axis.dot(ofs-sup2);
if (minB>maxB) {
SWAP(maxB,minB);
}
- float minT=1e20,maxT=-1e20;
+ real_t minT=1e20,maxT=-1e20;
for (int k=0;k<3;k++) {
- float d=axis.dot(vertex[k]);
+ real_t d=axis.dot(vertex[k]);
if (d > maxT)
maxT=d;
diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp
index bf3364a052..6570dfe672 100644
--- a/core/math/geometry.cpp
+++ b/core/math/geometry.cpp
@@ -580,7 +580,7 @@ static inline void _build_faces(uint8_t*** p_cell_status,int x,int y,int z,int l
}
-PoolVector< Face3 > Geometry::wrap_geometry( PoolVector< Face3 > p_array,float *p_error ) {
+PoolVector< Face3 > Geometry::wrap_geometry( PoolVector< Face3 > p_array,real_t *p_error ) {
#define _MIN_SIZE 1.0
#define _MAX_LENGTH 20
@@ -755,7 +755,7 @@ Geometry::MeshData Geometry::build_convex_mesh(const PoolVector<Plane> &p_planes
#define SUBPLANE_SIZE 1024.0
- float subplane_size = 1024.0; // should compute this from the actual plane
+ real_t subplane_size = 1024.0; // should compute this from the actual plane
for (int i=0;i<p_planes.size();i++) {
Plane p =p_planes[i];
@@ -910,7 +910,7 @@ PoolVector<Plane> Geometry::build_box_planes(const Vector3& p_extents) {
return planes;
}
-PoolVector<Plane> Geometry::build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis) {
+PoolVector<Plane> Geometry::build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis) {
PoolVector<Plane> planes;
@@ -933,7 +933,7 @@ PoolVector<Plane> Geometry::build_cylinder_planes(float p_radius, float p_height
}
-PoolVector<Plane> Geometry::build_sphere_planes(float p_radius, int p_lats,int p_lons, Vector3::Axis p_axis) {
+PoolVector<Plane> Geometry::build_sphere_planes(real_t p_radius, int p_lats,int p_lons, Vector3::Axis p_axis) {
PoolVector<Plane> planes;
@@ -957,7 +957,7 @@ PoolVector<Plane> Geometry::build_sphere_planes(float p_radius, int p_lats,int p
for (int j=1;j<=p_lats;j++) {
//todo this is stupid, fix
- Vector3 angle = normal.linear_interpolate(axis,j/(float)p_lats).normalized();
+ Vector3 angle = normal.linear_interpolate(axis,j/(real_t)p_lats).normalized();
Vector3 pos = angle*p_radius;
planes.push_back( Plane( pos, angle ) );
planes.push_back( Plane( pos * axis_neg, angle * axis_neg) );
@@ -969,7 +969,7 @@ PoolVector<Plane> Geometry::build_sphere_planes(float p_radius, int p_lats,int p
}
-PoolVector<Plane> Geometry::build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis) {
+PoolVector<Plane> Geometry::build_capsule_planes(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis) {
PoolVector<Plane> planes;
@@ -991,7 +991,7 @@ PoolVector<Plane> Geometry::build_capsule_planes(float p_radius, float p_height,
for (int j=1;j<=p_lats;j++) {
- Vector3 angle = normal.linear_interpolate(axis,j/(float)p_lats).normalized();
+ Vector3 angle = normal.linear_interpolate(axis,j/(real_t)p_lats).normalized();
Vector3 pos = axis*p_height*0.5 + angle*p_radius;
planes.push_back( Plane( pos, angle ) );
planes.push_back( Plane( pos * axis_neg, angle * axis_neg) );
@@ -1108,13 +1108,13 @@ void Geometry::make_atlas(const Vector<Size2i>& p_rects,Vector<Point2i>& r_resul
//find the result with the best aspect ratio
int best=-1;
- float best_aspect=1e20;
+ real_t best_aspect=1e20;
for(int i=0;i<results.size();i++) {
- float h = nearest_power_of_2(results[i].max_h);
- float w = nearest_power_of_2(results[i].max_w);
- float aspect = h>w ? h/w : w/h;
+ real_t h = nearest_power_of_2(results[i].max_h);
+ real_t w = nearest_power_of_2(results[i].max_w);
+ real_t aspect = h>w ? h/w : w/h;
if (aspect < best_aspect) {
best=i;
best_aspect=aspect;
diff --git a/core/math/geometry.h b/core/math/geometry.h
index 25f5e11fcf..13cbbdce6f 100644
--- a/core/math/geometry.h
+++ b/core/math/geometry.h
@@ -48,15 +48,15 @@ public:
- static float get_closest_points_between_segments( const Vector2& p1,const Vector2& q1, const Vector2& p2,const Vector2& q2, Vector2& c1, Vector2& c2) {
+ static real_t get_closest_points_between_segments( const Vector2& p1,const Vector2& q1, const Vector2& p2,const Vector2& q2, Vector2& c1, Vector2& c2) {
Vector2 d1 = q1 - p1; // Direction vector of segment S1
Vector2 d2 = q2 - p2; // Direction vector of segment S2
Vector2 r = p1 - p2;
- float a = d1.dot(d1); // Squared length of segment S1, always nonnegative
- float e = d2.dot(d2); // Squared length of segment S2, always nonnegative
- float f = d2.dot(r);
- float s,t;
+ real_t a = d1.dot(d1); // Squared length of segment S1, always nonnegative
+ real_t e = d2.dot(d2); // Squared length of segment S2, always nonnegative
+ real_t f = d2.dot(r);
+ real_t s,t;
// Check if either or both segments degenerate into points
if (a <= CMP_EPSILON && e <= CMP_EPSILON) {
// Both segments degenerate into points
@@ -66,25 +66,25 @@ public:
}
if (a <= CMP_EPSILON) {
// First segment degenerates into a point
- s = 0.0f;
+ s = 0.0;
t = f / e; // s = 0 => t = (b*s + f) / e = f / e
- t = CLAMP(t, 0.0f, 1.0f);
+ t = CLAMP(t, 0.0, 1.0);
} else {
- float c = d1.dot(r);
+ real_t c = d1.dot(r);
if (e <= CMP_EPSILON) {
// Second segment degenerates into a point
- t = 0.0f;
- s = CLAMP(-c / a, 0.0f, 1.0f); // t = 0 => s = (b*t - c) / a = -c / a
+ t = 0.0;
+ s = CLAMP(-c / a, 0.0, 1.0); // t = 0 => s = (b*t - c) / a = -c / a
} else {
// The general nondegenerate case starts here
- float b = d1.dot(d2);
- float denom = a*e-b*b; // Always nonnegative
+ real_t b = d1.dot(d2);
+ real_t denom = a*e-b*b; // Always nonnegative
// If segments not parallel, compute closest point on L1 to L2 and
// clamp to segment S1. Else pick arbitrary s (here 0)
- if (denom != 0.0f) {
- s = CLAMP((b*f - c*e) / denom, 0.0f, 1.0f);
+ if (denom != 0.0) {
+ s = CLAMP((b*f - c*e) / denom, 0.0, 1.0);
} else
- s = 0.0f;
+ s = 0.0;
// Compute point on L2 closest to S1(s) using
// t = Dot((P1 + D1*s) - P2,D2) / Dot(D2,D2) = (b*s + f) / e
t = (b*s + f) / e;
@@ -92,12 +92,12 @@ public:
//If t in [0,1] done. Else clamp t, recompute s for the new value
// of t using s = Dot((P2 + D2*t) - P1,D1) / Dot(D1,D1)= (t*b - c) / a
// and clamp s to [0, 1]
- if (t < 0.0f) {
- t = 0.0f;
- s = CLAMP(-c / a, 0.0f, 1.0f);
- } else if (t > 1.0f) {
- t = 1.0f;
- s = CLAMP((b - c) / a, 0.0f, 1.0f);
+ if (t < 0.0) {
+ t = 0.0;
+ s = CLAMP(-c / a, 0.0, 1.0);
+ } else if (t > 1.0) {
+ t = 1.0;
+ s = CLAMP((b - c) / a, 0.0, 1.0);
}
}
}
@@ -113,8 +113,8 @@ public:
#define d_of(m,n,o,p) ( (m.x - n.x) * (o.x - p.x) + (m.y - n.y) * (o.y - p.y) + (m.z - n.z) * (o.z - p.z) )
//caluclate the parpametric position on the 2 curves, mua and mub
- float mua = ( d_of(p1,q1,q2,q1) * d_of(q2,q1,p2,p1) - d_of(p1,q1,p2,p1) * d_of(q2,q1,q2,q1) ) / ( d_of(p2,p1,p2,p1) * d_of(q2,q1,q2,q1) - d_of(q2,q1,p2,p1) * d_of(q2,q1,p2,p1) );
- float mub = ( d_of(p1,q1,q2,q1) + mua * d_of(q2,q1,p2,p1) ) / d_of(q2,q1,q2,q1);
+ real_t mua = ( d_of(p1,q1,q2,q1) * d_of(q2,q1,p2,p1) - d_of(p1,q1,p2,p1) * d_of(q2,q1,q2,q1) ) / ( d_of(p2,p1,p2,p1) * d_of(q2,q1,q2,q1) - d_of(q2,q1,p2,p1) * d_of(q2,q1,p2,p1) );
+ real_t mub = ( d_of(p1,q1,q2,q1) + mua * d_of(q2,q1,p2,p1) ) / d_of(q2,q1,q2,q1);
//clip the value between [0..1] constraining the solution to lie on the original curves
if (mua < 0) mua = 0;
@@ -125,7 +125,7 @@ public:
c2 = q1.linear_interpolate(q2,mub);
}
- static float get_closest_distance_between_segments( const Vector3& p_from_a,const Vector3& p_to_a, const Vector3& p_from_b,const Vector3& p_to_b) {
+ static real_t get_closest_distance_between_segments( const Vector3& p_from_a,const Vector3& p_to_a, const Vector3& p_from_b,const Vector3& p_to_b) {
Vector3 u = p_to_a - p_from_a;
Vector3 v = p_to_b - p_from_b;
Vector3 w = p_from_a - p_to_a;
@@ -273,22 +273,22 @@ public:
Vector3 sphere_pos=p_sphere_pos-p_from;
Vector3 rel=(p_to-p_from);
- float rel_l=rel.length();
+ real_t rel_l=rel.length();
if (rel_l<CMP_EPSILON)
return false; // both points are the same
Vector3 normal=rel/rel_l;
- float sphere_d=normal.dot(sphere_pos);
+ real_t sphere_d=normal.dot(sphere_pos);
//Vector3 ray_closest=normal*sphere_d;
- float ray_distance=sphere_pos.distance_to(normal*sphere_d);
+ real_t ray_distance=sphere_pos.distance_to(normal*sphere_d);
if (ray_distance>=p_sphere_radius)
return false;
- float inters_d2=p_sphere_radius*p_sphere_radius - ray_distance*ray_distance;
- float inters_d=sphere_d;
+ real_t inters_d2=p_sphere_radius*p_sphere_radius - ray_distance*ray_distance;
+ real_t inters_d=sphere_d;
if (inters_d2>=CMP_EPSILON)
inters_d-=Math::sqrt(inters_d2);
@@ -307,17 +307,17 @@ public:
return true;
}
- static inline bool segment_intersects_cylinder( const Vector3& p_from, const Vector3& p_to, float p_height,float p_radius,Vector3* r_res=0,Vector3 *r_norm=0) {
+ static inline bool segment_intersects_cylinder( const Vector3& p_from, const Vector3& p_to, real_t p_height,real_t p_radius,Vector3* r_res=0,Vector3 *r_norm=0) {
Vector3 rel=(p_to-p_from);
- float rel_l=rel.length();
+ real_t rel_l=rel.length();
if (rel_l<CMP_EPSILON)
return false; // both points are the same
// first check if they are parallel
Vector3 normal=(rel/rel_l);
Vector3 crs = normal.cross(Vector3(0,0,1));
- float crs_l=crs.length();
+ real_t crs_l=crs.length();
Vector3 z_dir;
@@ -328,13 +328,13 @@ public:
z_dir=crs/crs_l;
}
- float dist=z_dir.dot(p_from);
+ real_t dist=z_dir.dot(p_from);
if (dist>=p_radius)
return false; // too far away
// convert to 2D
- float w2=p_radius*p_radius-dist*dist;
+ real_t w2=p_radius*p_radius-dist*dist;
if (w2<CMP_EPSILON)
return false; //avoid numerical error
Size2 size(Math::sqrt(w2),p_height*0.5);
@@ -344,7 +344,7 @@ public:
Vector2 from2D(x_dir.dot(p_from),p_from.z);
Vector2 to2D(x_dir.dot(p_to),p_to.z);
- float min=0,max=1;
+ real_t min=0,max=1;
int axis=-1;
@@ -464,12 +464,12 @@ public:
Vector3 p=p_point-p_segment[0];
Vector3 n=p_segment[1]-p_segment[0];
- float l =n.length();
+ real_t l =n.length();
if (l<1e-10)
return p_segment[0]; // both points are the same, just give any
n/=l;
- float d=n.dot(p);
+ real_t d=n.dot(p);
if (d<=0.0)
return p_segment[0]; // before first point
@@ -483,12 +483,12 @@ public:
Vector3 p=p_point-p_segment[0];
Vector3 n=p_segment[1]-p_segment[0];
- float l =n.length();
+ real_t l =n.length();
if (l<1e-10)
return p_segment[0]; // both points are the same, just give any
n/=l;
- float d=n.dot(p);
+ real_t d=n.dot(p);
return p_segment[0]+n*d; // inside
}
@@ -497,12 +497,12 @@ public:
Vector2 p=p_point-p_segment[0];
Vector2 n=p_segment[1]-p_segment[0];
- float l =n.length();
+ real_t l =n.length();
if (l<1e-10)
return p_segment[0]; // both points are the same, just give any
n/=l;
- float d=n.dot(p);
+ real_t d=n.dot(p);
if (d<=0.0)
return p_segment[0]; // before first point
@@ -529,12 +529,12 @@ public:
Vector2 p=p_point-p_segment[0];
Vector2 n=p_segment[1]-p_segment[0];
- float l =n.length();
+ real_t l =n.length();
if (l<1e-10)
return p_segment[0]; // both points are the same, just give any
n/=l;
- float d=n.dot(p);
+ real_t d=n.dot(p);
return p_segment[0]+n*d; // inside
}
@@ -555,7 +555,7 @@ public:
if ((C.y<0 && D.y<0) || (C.y>=0 && D.y>=0))
return false;
- float ABpos=D.x+(C.x-D.x)*D.y/(D.y-C.y);
+ real_t ABpos=D.x+(C.x-D.x)*D.y/(D.y-C.y);
// Fail if segment C-D crosses line A-B outside of segment A-B.
if (ABpos<0 || ABpos>1.0)
@@ -595,7 +595,7 @@ public:
static inline bool triangle_sphere_intersection_test(const Vector3 *p_triangle,const Vector3& p_normal,const Vector3& p_sphere_pos, real_t p_sphere_radius,Vector3& r_triangle_contact,Vector3& r_sphere_contact) {
- float d=p_normal.dot(p_sphere_pos)-p_normal.dot(p_triangle[0]);
+ real_t d=p_normal.dot(p_sphere_pos)-p_normal.dot(p_triangle[0]);
if (d > p_sphere_radius || d < -p_sphere_radius) // not touching the plane of the face, return
return false;
@@ -629,7 +629,7 @@ public:
Vector3 axis =n1.cross(n2).cross(n1);
axis.normalize(); // ugh
- float ad=axis.dot(n2);
+ real_t ad=axis.dot(n2);
if (ABS(ad)>p_sphere_radius) {
// no chance with this edge, too far away
@@ -639,7 +639,7 @@ public:
// check point within edge capsule cylinder
/** 4th TEST INSIDE EDGE POINTS **/
- float sphere_at = n1.dot(n2);
+ real_t sphere_at = n1.dot(n2);
if (sphere_at>=0 && sphere_at<n1.dot(n1)) {
@@ -650,7 +650,7 @@ public:
return true;
}
- float r2=p_sphere_radius*p_sphere_radius;
+ real_t r2=p_sphere_radius*p_sphere_radius;
if (n2.length_squared()<r2) {
@@ -726,8 +726,8 @@ public:
int outside_count = 0;
for (int a = 0; a < polygon.size(); a++) {
- //float p_plane.d = (*this) * polygon[a];
- float dist = p_plane.distance_to(polygon[a]);
+ //real_t p_plane.d = (*this) * polygon[a];
+ real_t dist = p_plane.distance_to(polygon[a]);
if (dist <-CMP_POINT_IN_PLANE_EPSILON) {
location_cache[a] = LOC_INSIDE;
inside_count++;
@@ -761,8 +761,8 @@ public:
const Vector3& v2 = polygon[index];
Vector3 segment= v1 - v2;
- double den=p_plane.normal.dot( segment );
- double dist=p_plane.distance_to( v1 ) / den;
+ real_t den=p_plane.normal.dot( segment );
+ real_t dist=p_plane.distance_to( v1 ) / den;
dist=-dist;
clipped.push_back( v1 + segment * dist );
}
@@ -771,8 +771,8 @@ public:
if ((loc == LOC_INSIDE) && (location_cache[previous] == LOC_OUTSIDE)) {
const Vector3& v2 = polygon[previous];
Vector3 segment= v1 - v2;
- double den=p_plane.normal.dot( segment );
- double dist=p_plane.distance_to( v1 ) / den;
+ real_t den=p_plane.normal.dot( segment );
+ real_t dist=p_plane.distance_to( v1 ) / den;
dist=-dist;
clipped.push_back( v1 + segment * dist );
}
@@ -808,7 +808,7 @@ public:
static PoolVector< PoolVector< Face3 > > separate_objects( PoolVector< Face3 > p_array );
- static PoolVector< Face3 > wrap_geometry( PoolVector< Face3 > p_array, float *p_error=NULL ); ///< create a "wrap" that encloses the given geometry
+ static PoolVector< Face3 > wrap_geometry( PoolVector< Face3 > p_array, real_t *p_error=NULL ); ///< create a "wrap" that encloses the given geometry
struct MeshData {
@@ -884,9 +884,9 @@ public:
}
- static double vec2_cross(const Point2 &O, const Point2 &A, const Point2 &B)
+ static real_t vec2_cross(const Point2 &O, const Point2 &A, const Point2 &B)
{
- return (double)(A.x - O.x) * (B.y - O.y) - (double)(A.y - O.y) * (B.x - O.x);
+ return (real_t)(A.x - O.x) * (B.y - O.y) - (real_t)(A.y - O.y) * (B.x - O.x);
}
// Returns a list of points on the convex hull in counter-clockwise order.
@@ -918,10 +918,10 @@ public:
}
static MeshData build_convex_mesh(const PoolVector<Plane> &p_planes);
- static PoolVector<Plane> build_sphere_planes(float p_radius, int p_lats, int p_lons, Vector3::Axis p_axis=Vector3::AXIS_Z);
+ static PoolVector<Plane> build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis=Vector3::AXIS_Z);
static PoolVector<Plane> build_box_planes(const Vector3& p_extents);
- static PoolVector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis=Vector3::AXIS_Z);
- static PoolVector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis=Vector3::AXIS_Z);
+ static PoolVector<Plane> build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis=Vector3::AXIS_Z);
+ static PoolVector<Plane> build_capsule_planes(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis=Vector3::AXIS_Z);
static void make_atlas(const Vector<Size2i>& p_rects,Vector<Point2i>& r_result, Size2i& r_size);
diff --git a/core/math/math_2d.cpp b/core/math/math_2d.cpp
index c6860ba2e8..76eeece688 100644
--- a/core/math/math_2d.cpp
+++ b/core/math/math_2d.cpp
@@ -239,10 +239,10 @@ Vector2 Vector2::cubic_interpolate(const Vector2& p_b,const Vector2& p_pre_a, co
real_t t3 = t2 * t;
Vector2 out;
- out = 0.5f * ( ( p1 * 2.0f) +
+ out = 0.5 * ( ( p1 * 2.0) +
( -p0 + p2 ) * t +
- ( 2.0f * p0 - 5.0f * p1 + 4 * p2 - p3 ) * t2 +
- ( -p0 + 3.0f * p1 - 3.0f * p2 + p3 ) * t3 );
+ ( 2.0 * p0 - 5.0 * p1 + 4 * p2 - p3 ) * t2 +
+ ( -p0 + 3.0 * p1 - 3.0 * p2 + p3 ) * t3 );
return out;
/*
diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp
index ef8c1ec539..c730b4fa30 100644
--- a/core/math/math_funcs.cpp
+++ b/core/math/math_funcs.cpp
@@ -27,12 +27,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "math_funcs.h"
-
#include "core/os/os.h"
-#include "float.h"
-#include "pcg.h"
-
pcg32_random_t Math::default_pcg = {1, PCG_DEFAULT_INC_64};
#define PHI 0x9e3779b9
@@ -63,35 +59,8 @@ uint32_t Math::rand() {
return pcg32_random_r(&default_pcg);
}
-double Math::randf() {
-
- return (double)rand() / (double)Math::RANDOM_MAX;
-}
-
-
-double Math::round(double p_val) {
-
- if (p_val>=0) {
- return ::floor(p_val+0.5);
- } else {
- p_val=-p_val;
- return -::floor(p_val+0.5);
- }
-}
-
-double Math::dectime(double p_value,double p_amount, double p_step) {
-
- float sgn = p_value < 0 ? -1.0 : 1.0;
- float val = absf(p_value);
- val-=p_amount*p_step;
- if (val<0.0)
- val=0.0;
- return val*sgn;
-}
-
int Math::step_decimals(double p_step) {
-
static const int maxn=9;
static const double sd[maxn]={
0.9999, // somehow compensate for floating point error
@@ -105,7 +74,7 @@ int Math::step_decimals(double p_step) {
0.000000009999
};
- double as=absf(p_step);
+ double as=Math::abs(p_step);
for(int i=0;i<maxn;i++) {
if (as>=sd[i]) {
return i;
@@ -115,8 +84,16 @@ int Math::step_decimals(double p_step) {
return maxn;
}
-double Math::ease(double p_x, double p_c) {
+double Math::dectime(double p_value,double p_amount, double p_step) {
+ double sgn = p_value < 0 ? -1.0 : 1.0;
+ double val = Math::abs(p_value);
+ val-=p_amount*p_step;
+ if (val<0.0)
+ val=0.0;
+ return val*sgn;
+}
+double Math::ease(double p_x, double p_c) {
if (p_x<0)
p_x=0;
else if (p_x>1.0)
@@ -137,20 +114,16 @@ double Math::ease(double p_x, double p_c) {
}
} else
return 0; // no ease (raw)
-
}
double Math::stepify(double p_value,double p_step) {
-
if (p_step!=0) {
-
- p_value=floor( p_value / p_step + 0.5 ) * p_step;
+ p_value=Math::floor( p_value / p_step + 0.5 ) * p_step;
}
return p_value;
}
-
uint32_t Math::larger_prime(uint32_t p_val) {
static const uint32_t primes[] = {
@@ -199,22 +172,15 @@ uint32_t Math::larger_prime(uint32_t p_val) {
}
double Math::random(double from, double to) {
-
unsigned int r = Math::rand();
double ret = (double)r/(double)RANDOM_MAX;
return (ret)*(to-from) + from;
}
-double Math::pow(double x, double y) {
-
- return ::pow(x,y);
+float Math::random(float from, float to) {
+ unsigned int r = Math::rand();
+ float ret = (float)r/(float)RANDOM_MAX;
+ return (ret)*(to-from) + from;
}
-double Math::log(double x) {
-
- return ::log(x);
-}
-double Math::exp(double x) {
- return ::exp(x);
-}
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index e81646b1ca..511af91835 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -33,12 +33,12 @@
#include "math_defs.h"
#include "pcg.h"
-#ifndef NO_MATH_H
#include <math.h>
-#endif
-
+#include <float.h>
+
#define Math_PI 3.14159265358979323846
#define Math_SQRT12 0.7071067811865475244008443621048490
+#define Math_LN2 0.693147180559945309417
class Math {
@@ -52,149 +52,122 @@ public:
};
- static _ALWAYS_INLINE_ double sin(double p_x) {
-
- return ::sin(p_x);
-
- }
-
- static _ALWAYS_INLINE_ double cos(double p_x) {
-
- return ::cos(p_x);
-
- }
-
- static _ALWAYS_INLINE_ double tan(double p_x) {
-
- return ::tan(p_x);
+ static _ALWAYS_INLINE_ double sin(double p_x) { return ::sin(p_x); }
+ static _ALWAYS_INLINE_ float sin(float p_x) { return ::sinf(p_x); }
- }
- static _ALWAYS_INLINE_ double sinh(double p_x) {
-
- return ::sinh(p_x);
- }
+ static _ALWAYS_INLINE_ double cos(double p_x) { return ::cos(p_x); }
+ static _ALWAYS_INLINE_ float cos(float p_x) { return ::cosf(p_x); }
- static _ALWAYS_INLINE_ double cosh(double p_x) {
+ static _ALWAYS_INLINE_ double tan(double p_x) { return ::tan(p_x); }
+ static _ALWAYS_INLINE_ float tan(float p_x) { return ::tanf(p_x); }
- return ::cosh(p_x);
- }
-
- static _ALWAYS_INLINE_ double tanh(double p_x) {
+ static _ALWAYS_INLINE_ double sinh(double p_x) { return ::sinh(p_x); }
+ static _ALWAYS_INLINE_ float sinh(float p_x) { return ::sinhf(p_x); }
- return ::tanh(p_x);
- }
-
-
- static _ALWAYS_INLINE_ double asin(double p_x) {
-
- return ::asin(p_x);
-
- }
+ static _ALWAYS_INLINE_ double cosh(double p_x) { return ::cosh(p_x); }
+ static _ALWAYS_INLINE_ float cosh(float p_x) { return ::coshf(p_x); }
- static _ALWAYS_INLINE_ double acos(double p_x) {
+ static _ALWAYS_INLINE_ double tanh(double p_x) { return ::tanh(p_x); }
+ static _ALWAYS_INLINE_ float tanh(float p_x) { return ::tanhf(p_x); }
- return ::acos(p_x);
- }
+ static _ALWAYS_INLINE_ double asin(double p_x) { return ::asin(p_x); }
+ static _ALWAYS_INLINE_ float asin(float p_x) { return ::asinf(p_x); }
- static _ALWAYS_INLINE_ double atan(double p_x) {
+ static _ALWAYS_INLINE_ double acos(double p_x) { return ::acos(p_x); }
+ static _ALWAYS_INLINE_ float acos(float p_x) { return ::acosf(p_x); }
- return ::atan(p_x);
- }
+ static _ALWAYS_INLINE_ double atan(double p_x) { return ::atan(p_x); }
+ static _ALWAYS_INLINE_ float atan(float p_x) { return ::atanf(p_x); }
- static _ALWAYS_INLINE_ double atan2(double p_y, double p_x) {
+ static _ALWAYS_INLINE_ double atan2(double p_y, double p_x) { return ::atan2(p_y,p_x); }
+ static _ALWAYS_INLINE_ float atan2(float p_y, float p_x) { return ::atan2f(p_y,p_x); }
- return ::atan2(p_y,p_x);
+ static _ALWAYS_INLINE_ double sqrt(double p_x) { return ::sqrt(p_x); }
+ static _ALWAYS_INLINE_ float sqrt(float p_x) { return ::sqrtf(p_x); }
- }
+ static _ALWAYS_INLINE_ double fmod(double p_x,double p_y) { return ::fmod(p_x,p_y); }
+ static _ALWAYS_INLINE_ float fmod(float p_x,float p_y) { return ::fmodf(p_x,p_y); }
- static _ALWAYS_INLINE_ double deg2rad(double p_y) {
+ static _ALWAYS_INLINE_ double floor(double p_x) { return ::floor(p_x); }
+ static _ALWAYS_INLINE_ float floor(float p_x) { return ::floorf(p_x); }
- return p_y*Math_PI/180.0;
- }
+ static _ALWAYS_INLINE_ double ceil(double p_x) { return ::ceil(p_x); }
+ static _ALWAYS_INLINE_ float ceil(float p_x) { return ::ceilf(p_x); }
- static _ALWAYS_INLINE_ double rad2deg(double p_y) {
+ static _ALWAYS_INLINE_ double pow(double p_x, double p_y) { return ::pow(p_x,p_y); }
+ static _ALWAYS_INLINE_ float pow(float p_x, float p_y) { return ::powf(p_x,p_y); }
- return p_y*180.0/Math_PI;
- }
+ static _ALWAYS_INLINE_ double log(double p_x) { return ::log(p_x); }
+ static _ALWAYS_INLINE_ float log(float p_x) { return ::logf(p_x); }
+ static _ALWAYS_INLINE_ double exp(double p_x) { return ::exp(p_x); }
+ static _ALWAYS_INLINE_ float exp(float p_x) { return ::expf(p_x); }
- static _ALWAYS_INLINE_ double sqrt(double p_x) {
+ static _ALWAYS_INLINE_ bool is_nan(double p_val) { return (p_val!=p_val); }
+ static _ALWAYS_INLINE_ bool is_nan(float p_val) { return (p_val!=p_val); }
- return ::sqrt(p_x);
+ static _ALWAYS_INLINE_ bool is_inf(double p_val) {
+ #ifdef _MSC_VER
+ return !_finite(p_val);
+ #else
+ return isinf(p_val);
+ #endif
}
-
- static _ALWAYS_INLINE_ double fmod(double p_x,double p_y) {
-
- return ::fmod(p_x,p_y);
+
+ static _ALWAYS_INLINE_ bool is_inf(float p_val) {
+ #ifdef _MSC_VER
+ return !_finite(p_val);
+ #else
+ return isinf(p_val);
+ #endif
}
+
+ static _ALWAYS_INLINE_ double abs(double g) { return absd(g); }
+ static _ALWAYS_INLINE_ float abs(float g) { return absf(g); }
+ static _ALWAYS_INLINE_ int abs(int g) { return g > 0 ? g : -g; }
- static _ALWAYS_INLINE_ double fposmod(double p_x,double p_y) {
-
- if (p_x>=0) {
-
- return fmod(p_x,p_y);
-
- } else {
-
- return p_y-fmod(-p_x,p_y);
- }
+ static _ALWAYS_INLINE_ double fposmod(double p_x,double p_y) { return (p_x>=0) ? Math::fmod(p_x,p_y) : p_y-Math::fmod(-p_x,p_y); }
+ static _ALWAYS_INLINE_ float fposmod(float p_x,float p_y) { return (p_x>=0) ? Math::fmod(p_x,p_y) : p_y-Math::fmod(-p_x,p_y); }
- }
- static _ALWAYS_INLINE_ double floor(double p_x) {
+ static _ALWAYS_INLINE_ double deg2rad(double p_y) { return p_y*Math_PI/180.0; }
+ static _ALWAYS_INLINE_ float deg2rad(float p_y) { return p_y*Math_PI/180.0; }
- return ::floor(p_x);
- }
+ static _ALWAYS_INLINE_ double rad2deg(double p_y) { return p_y*180.0/Math_PI; }
+ static _ALWAYS_INLINE_ float rad2deg(float p_y) { return p_y*180.0/Math_PI; }
- static _ALWAYS_INLINE_ double ceil(double p_x) {
+ static _ALWAYS_INLINE_ double lerp(double a, double b, double c) { return a+(b-a)*c; }
+ static _ALWAYS_INLINE_ float lerp(float a, float b, float c) { return a+(b-a)*c; }
- return ::ceil(p_x);
- }
+ static _ALWAYS_INLINE_ double linear2db(double p_linear) { return Math::log( p_linear ) * 8.6858896380650365530225783783321; }
+ static _ALWAYS_INLINE_ float linear2db(float p_linear) { return Math::log( p_linear ) * 8.6858896380650365530225783783321; }
+ static _ALWAYS_INLINE_ double db2linear(double p_db) { return Math::exp( p_db * 0.11512925464970228420089957273422 ); }
+ static _ALWAYS_INLINE_ float db2linear(float p_db) { return Math::exp( p_db * 0.11512925464970228420089957273422 ); }
- static uint32_t rand_from_seed(uint64_t *seed);
+ static _ALWAYS_INLINE_ double round(double p_val) { return (p_val>=0) ? Math::floor(p_val+0.5) : -Math::floor(-p_val+0.5); }
+ static _ALWAYS_INLINE_ float round(float p_val) { return (p_val>=0) ? Math::floor(p_val+0.5) : -Math::floor(-p_val+0.5); }
+ // double only, as these functions are mainly used by the editor and not performance-critical,
static double ease(double p_x, double p_c);
static int step_decimals(double p_step);
static double stepify(double p_value,double p_step);
- static void seed(uint64_t x=0);
- static void randomize();
- static uint32_t larger_prime(uint32_t p_val);
static double dectime(double p_value,double p_amount, double p_step);
+ static uint32_t larger_prime(uint32_t p_val);
- static inline double linear2db(double p_linear) {
-
- return Math::log( p_linear ) * 8.6858896380650365530225783783321;
- }
-
- static inline double db2linear(double p_db) {
-
- return Math::exp( p_db * 0.11512925464970228420089957273422 );
- }
-
- static _ALWAYS_INLINE_ bool is_nan(double p_val) {
-
- return (p_val!=p_val);
- }
-
- static _ALWAYS_INLINE_ bool is_inf(double p_val) {
-
- #ifdef _MSC_VER
- return !_finite(p_val);
- #else
- return isinf(p_val);
- #endif
-
- }
-
+ static void seed(uint64_t x=0);
+ static void randomize();
+ static uint32_t rand_from_seed(uint64_t *seed);
static uint32_t rand();
- static double randf();
-
- static double round(double p_val);
+ static _ALWAYS_INLINE_ double randf() { return (double)rand() / (double)Math::RANDOM_MAX; }
+ static _ALWAYS_INLINE_ float randd() { return (float)rand() / (float)Math::RANDOM_MAX; }
static double random(double from, double to);
+ static float random(float from, float to);
+ static real_t random(int from, int to) { return (real_t)random((real_t)from, (real_t)to); }
+
- static _FORCE_INLINE_ bool isequal_approx(real_t a, real_t b) {
+ static _ALWAYS_INLINE_ bool isequal_approx(real_t a, real_t b) {
// TODO: Comparing floats for approximate-equality is non-trivial.
// Using epsilon should cover the typical cases in Godot (where a == b is used to compare two reals), such as matrix and vector comparison operators.
// A proper implementation in terms of ULPs should eventually replace the contents of this function.
@@ -204,18 +177,7 @@ public:
}
- static _FORCE_INLINE_ real_t abs(real_t g) {
-
-#ifdef REAL_T_IS_DOUBLE
-
- return absd(g);
-#else
-
- return absf(g);
-#endif
- }
-
- static _FORCE_INLINE_ float absf(float g) {
+ static _ALWAYS_INLINE_ float absf(float g) {
union {
float f;
@@ -227,7 +189,7 @@ public:
return u.f;
}
- static _FORCE_INLINE_ double absd(double g) {
+ static _ALWAYS_INLINE_ double absd(double g) {
union {
double d;
@@ -239,12 +201,12 @@ public:
}
//this function should be as fast as possible and rounding mode should not matter
- static _FORCE_INLINE_ int fast_ftoi(float a) {
+ static _ALWAYS_INLINE_ int fast_ftoi(float a) {
static int b;
#if (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0603) || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP // windows 8 phone?
- b = (int)((a>0.0f) ? (a + 0.5f):(a -0.5f));
+ b = (int)((a>0.0) ? (a + 0.5):(a -0.5));
#elif defined(_MSC_VER) && _MSC_VER < 1800
__asm fld a
@@ -267,23 +229,16 @@ public:
#if defined(__GNUC__)
- static _FORCE_INLINE_ int64_t dtoll(double p_double) { return (int64_t)p_double; } ///@TODO OPTIMIZE
+ static _ALWAYS_INLINE_ int64_t dtoll(double p_double) { return (int64_t)p_double; } ///@TODO OPTIMIZE
+ static _ALWAYS_INLINE_ int64_t dtoll(float p_float) { return (int64_t)p_float; } ///@TODO OPTIMIZE and rename
#else
- static _FORCE_INLINE_ int64_t dtoll(double p_double) { return (int64_t)p_double; } ///@TODO OPTIMIZE
+ static _ALWAYS_INLINE_ int64_t dtoll(double p_double) { return (int64_t)p_double; } ///@TODO OPTIMIZE
+ static _ALWAYS_INLINE_ int64_t dtoll(float p_float) { return (int64_t)p_float; } ///@TODO OPTIMIZE and rename
#endif
- static _FORCE_INLINE_ float lerp(float a, float b, float c) {
-
- return a+(b-a)*c;
- }
-
- static double pow(double x, double y);
- static double log(double x);
- static double exp(double x);
-
- static _FORCE_INLINE_ uint32_t halfbits_to_floatbits(uint16_t h)
+ static _ALWAYS_INLINE_ uint32_t halfbits_to_floatbits(uint16_t h)
{
uint16_t h_exp, h_sig;
uint32_t f_sgn, f_exp, f_sig;
@@ -315,7 +270,7 @@ public:
}
}
- static _FORCE_INLINE_ float halfptr_to_float(const uint16_t *h) {
+ static _ALWAYS_INLINE_ float halfptr_to_float(const uint16_t *h) {
union {
uint32_t u32;
@@ -326,7 +281,7 @@ public:
return u.f32;
}
- static _FORCE_INLINE_ uint16_t make_half_float(float f) {
+ static _ALWAYS_INLINE_ uint16_t make_half_float(float f) {
union {
float fv;
diff --git a/core/math/matrix3.cpp b/core/math/matrix3.cpp
index e9c3442582..1fabfbbd4c 100644
--- a/core/math/matrix3.cpp
+++ b/core/math/matrix3.cpp
@@ -504,9 +504,9 @@ void Basis::get_axis_and_angle(Vector3 &r_axis,real_t& r_angle) const {
ERR_FAIL_COND(is_rotation() == false);
- double angle,x,y,z; // variables for result
- double epsilon = 0.01; // margin to allow for rounding errors
- double epsilon2 = 0.1; // margin to distinguish between 0 and 180 degrees
+ real_t angle,x,y,z; // variables for result
+ real_t epsilon = 0.01; // margin to allow for rounding errors
+ real_t epsilon2 = 0.1; // margin to distinguish between 0 and 180 degrees
if ( (Math::abs(elements[1][0]-elements[0][1])< epsilon)
&& (Math::abs(elements[2][0]-elements[0][2])< epsilon)
@@ -525,12 +525,12 @@ void Basis::get_axis_and_angle(Vector3 &r_axis,real_t& r_angle) const {
}
// otherwise this singularity is angle = 180
angle = Math_PI;
- double xx = (elements[0][0]+1)/2;
- double yy = (elements[1][1]+1)/2;
- double zz = (elements[2][2]+1)/2;
- double xy = (elements[1][0]+elements[0][1])/4;
- double xz = (elements[2][0]+elements[0][2])/4;
- double yz = (elements[2][1]+elements[1][2])/4;
+ real_t xx = (elements[0][0]+1)/2;
+ real_t yy = (elements[1][1]+1)/2;
+ real_t zz = (elements[2][2]+1)/2;
+ real_t xy = (elements[1][0]+elements[0][1])/4;
+ real_t xz = (elements[2][0]+elements[0][2])/4;
+ real_t yz = (elements[2][1]+elements[1][2])/4;
if ((xx > yy) && (xx > zz)) { // elements[0][0] is the largest diagonal term
if (xx< epsilon) {
x = 0;
@@ -567,7 +567,7 @@ void Basis::get_axis_and_angle(Vector3 &r_axis,real_t& r_angle) const {
return;
}
// as we have reached here there are no singularities so we can handle normally
- double s = Math::sqrt((elements[1][2] - elements[2][1])*(elements[1][2] - elements[2][1])
+ real_t s = Math::sqrt((elements[1][2] - elements[2][1])*(elements[1][2] - elements[2][1])
+(elements[2][0] - elements[0][2])*(elements[2][0] - elements[0][2])
+(elements[0][1] - elements[1][0])*(elements[0][1] - elements[1][0])); // s=|axis||sin(angle)|, used to normalise
diff --git a/core/math/octree.h b/core/math/octree.h
index 3630922d10..e566df6a4f 100644
--- a/core/math/octree.h
+++ b/core/math/octree.h
@@ -435,7 +435,7 @@ int Octree<T,use_pairs,AL>::get_subindex(OctreeElementID p_id) const {
template<class T,bool use_pairs,class AL>
void Octree<T,use_pairs,AL>::_insert_element(Element *p_element,Octant *p_octant) {
- float element_size = p_element->aabb.get_longest_axis_size() * 1.01; // avoid precision issues
+ real_t element_size = p_element->aabb.get_longest_axis_size() * 1.01; // avoid precision issues
if (p_octant->aabb.size.x/OCTREE_DIVISOR < element_size) {
//if (p_octant->aabb.size.x*0.5 < element_size) {
diff --git a/core/math/plane.h b/core/math/plane.h
index f746ea2067..8235c59135 100644
--- a/core/math/plane.h
+++ b/core/math/plane.h
@@ -99,7 +99,7 @@ real_t Plane::distance_to(const Vector3 &p_point) const {
bool Plane::has_point(const Vector3 &p_point,real_t _epsilon) const {
- float dist=normal.dot(p_point) - d;
+ real_t dist=normal.dot(p_point) - d;
dist=ABS(dist);
return ( dist <= _epsilon);
diff --git a/core/math/quat.cpp b/core/math/quat.cpp
index 055e2b7c35..4085f9b84a 100644
--- a/core/math/quat.cpp
+++ b/core/math/quat.cpp
@@ -124,8 +124,8 @@ Quat Quat::slerp(const Quat& q, const real_t& t) const {
// Standard case (slerp)
real_t sine = Math::sqrt(1 - cosine*cosine);
real_t angle = Math::atan2(sine, cosine);
- real_t inv_sine = 1.0f / sine;
- real_t coeff_0 = Math::sin((1.0f - t) * angle) * inv_sine;
+ real_t inv_sine = 1.0 / sine;
+ real_t coeff_0 = Math::sin((1.0 - t) * angle) * inv_sine;
real_t coeff_1 = Math::sin(t * angle) * inv_sine;
Quat ret= src * coeff_0 + dst * coeff_1;
@@ -137,7 +137,7 @@ Quat Quat::slerp(const Quat& q, const real_t& t) const {
// 2. "rkP" and "q" are almost invedste of each other (cosine ~= -1), there
// are an infinite number of possibilities interpolation. but we haven't
// have method to fix this case, so just use linear interpolation here.
- Quat ret = src * (1.0f - t) + dst *t;
+ Quat ret = src * (1.0 - t) + dst *t;
// taking the complement requires renormalisation
ret.normalize();
return ret;
@@ -194,14 +194,14 @@ Quat Quat::slerpni(const Quat& q, const real_t& t) const {
const Quat &from = *this;
- float dot = from.dot(q);
+ real_t dot = from.dot(q);
- if (Math::absf(dot) > 0.9999f) return from;
+ if (Math::absf(dot) > 0.9999) return from;
- float theta = Math::acos(dot),
- sinT = 1.0f / Math::sin(theta),
+ real_t theta = Math::acos(dot),
+ sinT = 1.0 / Math::sin(theta),
newFactor = Math::sin(t * theta) * sinT,
- invFactor = Math::sin((1.0f - t) * theta) * sinT;
+ invFactor = Math::sin((1.0 - t) * theta) * sinT;
return Quat(invFactor * from.x + newFactor * q.x,
invFactor * from.y + newFactor * q.y,
@@ -259,7 +259,7 @@ Quat Quat::slerpni(const Quat& q, const real_t& t) const {
Quat Quat::cubic_slerp(const Quat& q, const Quat& prep, const Quat& postq,const real_t& t) const {
//the only way to do slerp :|
- float t2 = (1.0-t)*t*2;
+ real_t t2 = (1.0-t)*t*2;
Quat sp = this->slerp(q,t);
Quat sq = prep.slerpni(postq,t);
return sp.slerpni(sq,t2);
diff --git a/core/math/quat.h b/core/math/quat.h
index 43c2cab9e6..d3a50343a3 100644
--- a/core/math/quat.h
+++ b/core/math/quat.h
@@ -119,8 +119,8 @@ public:
w=0;
} else {
- real_t s = Math::sqrt((1.0f + d) * 2.0f);
- real_t rs = 1.0f / s;
+ real_t s = Math::sqrt((1.0 + d) * 2.0);
+ real_t rs = 1.0 / s;
x=c.x*rs;
y=c.y*rs;
diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp
index 756e48d0b4..32fc0e01e8 100644
--- a/core/math/quick_hull.cpp
+++ b/core/math/quick_hull.cpp
@@ -86,7 +86,7 @@ Error QuickHull::build(const Vector<Vector3>& p_points, Geometry::MeshData &r_me
if (!valid_points[i])
continue;
- float d = p_points[i][longest_axis];
+ real_t d = p_points[i][longest_axis];
if (i==0 || d < min) {
simplex[0]=i;
@@ -105,7 +105,7 @@ Error QuickHull::build(const Vector<Vector3>& p_points, Geometry::MeshData &r_me
{
- float maxd;
+ real_t maxd;
Vector3 rel12 = p_points[simplex[0]] - p_points[simplex[1]];
for(int i=0;i<p_points.size();i++) {
@@ -127,7 +127,7 @@ Error QuickHull::build(const Vector<Vector3>& p_points, Geometry::MeshData &r_me
//fourth vertex is the one most further away from the plane
{
- float maxd;
+ real_t maxd;
Plane p(p_points[simplex[0]],p_points[simplex[1]],p_points[simplex[2]]);
for(int i=0;i<p_points.size();i++) {
diff --git a/core/math/rect3.cpp b/core/math/rect3.cpp
index e0b0646505..d3f95b89e8 100644
--- a/core/math/rect3.cpp
+++ b/core/math/rect3.cpp
@@ -30,7 +30,7 @@
#include "print_string.h"
-float Rect3::get_area() const {
+real_t Rect3::get_area() const {
return size.x*size.y*size.z;
@@ -114,8 +114,8 @@ bool Rect3::intersects_ray(const Vector3& p_from, const Vector3& p_dir,Vector3*
Vector3 c1, c2;
Vector3 end = pos+size;
- float near=-1e20;
- float far=1e20;
+ real_t near=-1e20;
+ real_t far=1e20;
int axis=0;
for (int i=0;i<3;i++){
@@ -159,7 +159,7 @@ bool Rect3::intersects_segment(const Vector3& p_from, const Vector3& p_to,Vector
real_t min=0,max=1;
int axis=0;
- float sign=0;
+ real_t sign=0;
for(int i=0;i<3;i++) {
real_t seg_from=p_from[i];
@@ -167,7 +167,7 @@ bool Rect3::intersects_segment(const Vector3& p_from, const Vector3& p_to,Vector
real_t box_begin=pos[i];
real_t box_end=box_begin+size[i];
real_t cmin,cmax;
- float csign;
+ real_t csign;
if (seg_from < seg_to) {
diff --git a/core/math/rect3.h b/core/math/rect3.h
index 80c67200f4..902592b02c 100644
--- a/core/math/rect3.h
+++ b/core/math/rect3.h
@@ -33,6 +33,8 @@
#include "vector3.h"
#include "plane.h"
+#include "math_defs.h"
+
/**
* AABB / AABB (Axis Aligned Bounding Box)
* This is implemented by a point (pos) and the box size
@@ -45,7 +47,7 @@ public:
Vector3 pos;
Vector3 size;
- float get_area() const; /// get area
+ real_t get_area() const; /// get area
_FORCE_INLINE_ bool has_no_area() const {
return (size.x<=CMP_EPSILON || size.y<=CMP_EPSILON || size.z<=CMP_EPSILON);
@@ -74,7 +76,7 @@ public:
Rect3 intersection(const Rect3& p_aabb) const; ///get box where two intersect, empty if no intersection occurs
bool intersects_segment(const Vector3& p_from, const Vector3& p_to,Vector3* r_clip=NULL,Vector3* r_normal=NULL) const;
bool intersects_ray(const Vector3& p_from, const Vector3& p_dir,Vector3* r_clip=NULL,Vector3* r_normal=NULL) const;
- _FORCE_INLINE_ bool smits_intersect_ray(const Vector3 &from,const Vector3& p_dir, float t0, float t1) const;
+ _FORCE_INLINE_ bool smits_intersect_ray(const Vector3 &from,const Vector3& p_dir, real_t t0, real_t t1) const;
_FORCE_INLINE_ bool intersects_convex_shape(const Plane *p_plane, int p_plane_count) const;
bool intersects_plane(const Plane &p_plane) const;
@@ -98,7 +100,7 @@ public:
_FORCE_INLINE_ Vector3 get_endpoint(int p_point) const;
Rect3 expand(const Vector3& p_vector) const;
- _FORCE_INLINE_ void project_range_in_plane(const Plane& p_plane,float &r_min,float& r_max) const;
+ _FORCE_INLINE_ void project_range_in_plane(const Plane& p_plane,real_t &r_min,real_t& r_max) const;
_FORCE_INLINE_ void expand_to(const Vector3& p_vector); /** expand to contain a point if necesary */
operator String() const;
@@ -293,13 +295,13 @@ inline void Rect3::expand_to(const Vector3& p_vector) {
size=end-begin;
}
-void Rect3::project_range_in_plane(const Plane& p_plane,float &r_min,float& r_max) const {
+void Rect3::project_range_in_plane(const Plane& p_plane,real_t &r_min,real_t& r_max) const {
Vector3 half_extents( size.x * 0.5, size.y * 0.5, size.z * 0.5 );
Vector3 center( pos.x + half_extents.x, pos.y + half_extents.y, pos.z + half_extents.z );
- float length = p_plane.normal.abs().dot(half_extents);
- float distance = p_plane.distance_to( center );
+ real_t length = p_plane.normal.abs().dot(half_extents);
+ real_t distance = p_plane.distance_to( center );
r_min = distance - length;
r_max = distance + length;
}
@@ -334,14 +336,14 @@ inline real_t Rect3::get_shortest_axis_size() const {
return max_size;
}
-bool Rect3::smits_intersect_ray(const Vector3 &from,const Vector3& dir, float t0, float t1) const {
+bool Rect3::smits_intersect_ray(const Vector3 &from,const Vector3& dir, real_t t0, real_t t1) const {
- float divx=1.0/dir.x;
- float divy=1.0/dir.y;
- float divz=1.0/dir.z;
+ real_t divx=1.0/dir.x;
+ real_t divy=1.0/dir.y;
+ real_t divz=1.0/dir.z;
Vector3 upbound=pos+size;
- float tmin, tmax, tymin, tymax, tzmin, tzmax;
+ real_t tmin, tmax, tymin, tymax, tzmin, tzmax;
if (dir.x >= 0) {
tmin = (pos.x - from.x) * divx;
tmax = (upbound.x - from.x) * divx;
diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp
index 86f8bf29e7..247cb90a48 100644
--- a/core/math/triangle_mesh.cpp
+++ b/core/math/triangle_mesh.cpp
@@ -340,7 +340,7 @@ bool TriangleMesh::intersect_segment(const Vector3& p_begin,const Vector3& p_end
if (f3.intersects_segment(p_begin,p_end,&res)) {
- float nd = n.dot(res);
+ real_t nd = n.dot(res);
if (nd<d) {
d=nd;
@@ -462,7 +462,7 @@ bool TriangleMesh::intersect_ray(const Vector3& p_begin,const Vector3& p_dir,Vec
if (f3.intersects_ray(p_begin,p_dir,&res)) {
- float nd = n.dot(res);
+ real_t nd = n.dot(res);
if (nd<d) {
d=nd;
diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp
index 82b49be7f3..128b6ca331 100644
--- a/core/math/triangulate.cpp
+++ b/core/math/triangulate.cpp
@@ -28,19 +28,19 @@
/*************************************************************************/
#include "triangulate.h"
-float Triangulate::get_area(const Vector<Vector2> &contour)
+real_t Triangulate::get_area(const Vector<Vector2> &contour)
{
int n = contour.size();
const Vector2 *c=&contour[0];
- float A=0.0f;
+ real_t A=0.0;
for(int p=n-1,q=0; q<n; p=q++)
{
A+= c[p].cross(c[q]);
}
- return A*0.5f;
+ return A*0.5;
}
/*
@@ -48,14 +48,14 @@ float Triangulate::get_area(const Vector<Vector2> &contour)
defined by A, B, C.
*/
-bool Triangulate::is_inside_triangle(float Ax, float Ay,
- float Bx, float By,
- float Cx, float Cy,
- float Px, float Py)
+bool Triangulate::is_inside_triangle(real_t Ax, real_t Ay,
+ real_t Bx, real_t By,
+ real_t Cx, real_t Cy,
+ real_t Px, real_t Py)
{
- float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
- float cCROSSap, bCROSScp, aCROSSbp;
+ real_t ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
+ real_t cCROSSap, bCROSScp, aCROSSbp;
ax = Cx - Bx; ay = Cy - By;
bx = Ax - Cx; by = Ay - Cy;
@@ -68,13 +68,13 @@ bool Triangulate::is_inside_triangle(float Ax, float Ay,
cCROSSap = cx*apy - cy*apx;
bCROSScp = bx*cpy - by*cpx;
- return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
+ return ((aCROSSbp >= 0.0) && (bCROSScp >= 0.0) && (cCROSSap >= 0.0));
};
bool Triangulate::snip(const Vector<Vector2> &p_contour,int u,int v,int w,int n,const Vector<int>& V)
{
int p;
- float Ax, Ay, Bx, By, Cx, Cy, Px, Py;
+ real_t Ax, Ay, Bx, By, Cx, Cy, Px, Py;
const Vector2 *contour=&p_contour[0];
Ax = contour[V[u]].x;
@@ -112,7 +112,7 @@ bool Triangulate::triangulate(const Vector<Vector2> &contour,Vector<int> &result
/* we want a counter-clockwise polygon in V */
- if ( 0.0f < get_area(contour) )
+ if ( 0.0 < get_area(contour) )
for (int v=0; v<n; v++) V[v] = v;
else
for(int v=0; v<n; v++) V[v] = (n-1)-v;
diff --git a/core/math/triangulate.h b/core/math/triangulate.h
index d22677a8b8..ce77334519 100644
--- a/core/math/triangulate.h
+++ b/core/math/triangulate.h
@@ -45,14 +45,14 @@ public:
static bool triangulate(const Vector< Vector2 > &contour, Vector<int> &result);
// compute area of a contour/polygon
- static float get_area(const Vector< Vector2 > &contour);
+ static real_t get_area(const Vector< Vector2 > &contour);
// decide if point Px/Py is inside triangle defined by
// (Ax,Ay) (Bx,By) (Cx,Cy)
- static bool is_inside_triangle(float Ax, float Ay,
- float Bx, float By,
- float Cx, float Cy,
- float Px, float Py);
+ static bool is_inside_triangle(real_t Ax, real_t Ay,
+ real_t Bx, real_t By,
+ real_t Cx, real_t Cy,
+ real_t Px, real_t Py);
private:
diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp
index 3eb978333d..2ab5fa0465 100644
--- a/core/math/vector3.cpp
+++ b/core/math/vector3.cpp
@@ -30,12 +30,12 @@
#include "matrix3.h"
-void Vector3::rotate(const Vector3& p_axis,float p_phi) {
+void Vector3::rotate(const Vector3& p_axis,real_t p_phi) {
*this=Basis(p_axis,p_phi).xform(*this);
}
-Vector3 Vector3::rotated(const Vector3& p_axis,float p_phi) const {
+Vector3 Vector3::rotated(const Vector3& p_axis,real_t p_phi) const {
Vector3 r = *this;
r.rotate(p_axis,p_phi);
@@ -63,13 +63,13 @@ int Vector3::max_axis() const {
}
-void Vector3::snap(float p_val) {
+void Vector3::snap(real_t p_val) {
x=Math::stepify(x,p_val);
y=Math::stepify(y,p_val);
z=Math::stepify(z,p_val);
}
-Vector3 Vector3::snapped(float p_val) const {
+Vector3 Vector3::snapped(real_t p_val) const {
Vector3 v=*this;
v.snap(p_val);
@@ -77,7 +77,7 @@ Vector3 Vector3::snapped(float p_val) const {
}
-Vector3 Vector3::cubic_interpolaten(const Vector3& p_b,const Vector3& p_pre_a, const Vector3& p_post_b,float p_t) const {
+Vector3 Vector3::cubic_interpolaten(const Vector3& p_b,const Vector3& p_pre_a, const Vector3& p_post_b,real_t p_t) const {
Vector3 p0=p_pre_a;
Vector3 p1=*this;
@@ -87,9 +87,9 @@ Vector3 Vector3::cubic_interpolaten(const Vector3& p_b,const Vector3& p_pre_a, c
{
//normalize
- float ab = p0.distance_to(p1);
- float bc = p1.distance_to(p2);
- float cd = p2.distance_to(p3);
+ real_t ab = p0.distance_to(p1);
+ real_t bc = p1.distance_to(p2);
+ real_t cd = p2.distance_to(p3);
if (ab>0)
p0 = p1+(p0-p1)*(bc/ab);
@@ -98,41 +98,41 @@ Vector3 Vector3::cubic_interpolaten(const Vector3& p_b,const Vector3& p_pre_a, c
}
- float t = p_t;
- float t2 = t * t;
- float t3 = t2 * t;
+ real_t t = p_t;
+ real_t t2 = t * t;
+ real_t t3 = t2 * t;
Vector3 out;
- out = 0.5f * ( ( p1 * 2.0f) +
+ out = 0.5 * ( ( p1 * 2.0) +
( -p0 + p2 ) * t +
- ( 2.0f * p0 - 5.0f * p1 + 4 * p2 - p3 ) * t2 +
- ( -p0 + 3.0f * p1 - 3.0f * p2 + p3 ) * t3 );
+ ( 2.0 * p0 - 5.0 * p1 + 4 * p2 - p3 ) * t2 +
+ ( -p0 + 3.0 * p1 - 3.0 * p2 + p3 ) * t3 );
return out;
}
-Vector3 Vector3::cubic_interpolate(const Vector3& p_b,const Vector3& p_pre_a, const Vector3& p_post_b,float p_t) const {
+Vector3 Vector3::cubic_interpolate(const Vector3& p_b,const Vector3& p_pre_a, const Vector3& p_post_b,real_t p_t) const {
Vector3 p0=p_pre_a;
Vector3 p1=*this;
Vector3 p2=p_b;
Vector3 p3=p_post_b;
- float t = p_t;
- float t2 = t * t;
- float t3 = t2 * t;
+ real_t t = p_t;
+ real_t t2 = t * t;
+ real_t t3 = t2 * t;
Vector3 out;
- out = 0.5f * ( ( p1 * 2.0f) +
+ out = 0.5 * ( ( p1 * 2.0) +
( -p0 + p2 ) * t +
- ( 2.0f * p0 - 5.0f * p1 + 4 * p2 - p3 ) * t2 +
- ( -p0 + 3.0f * p1 - 3.0f * p2 + p3 ) * t3 );
+ ( 2.0 * p0 - 5.0 * p1 + 4 * p2 - p3 ) * t2 +
+ ( -p0 + 3.0 * p1 - 3.0 * p2 + p3 ) * t3 );
return out;
}
#if 0
-Vector3 Vector3::cubic_interpolate(const Vector3& p_b,const Vector3& p_pre_a, const Vector3& p_post_b,float p_t) const {
+Vector3 Vector3::cubic_interpolate(const Vector3& p_b,const Vector3& p_pre_a, const Vector3& p_post_b,real_t p_t) const {
Vector3 p0=p_pre_a;
Vector3 p1=*this;
@@ -141,9 +141,9 @@ Vector3 Vector3::cubic_interpolate(const Vector3& p_b,const Vector3& p_pre_a, co
if (true) {
- float ab = p0.distance_to(p1);
- float bc = p1.distance_to(p2);
- float cd = p2.distance_to(p3);
+ real_t ab = p0.distance_to(p1);
+ real_t bc = p1.distance_to(p2);
+ real_t cd = p2.distance_to(p3);
//if (ab>bc) {
if (ab>0)
@@ -156,23 +156,23 @@ Vector3 Vector3::cubic_interpolate(const Vector3& p_b,const Vector3& p_pre_a, co
//}
}
- float t = p_t;
- float t2 = t * t;
- float t3 = t2 * t;
+ real_t t = p_t;
+ real_t t2 = t * t;
+ real_t t3 = t2 * t;
Vector3 out;
- out.x = 0.5f * ( ( 2.0f * p1.x ) +
+ out.x = 0.5 * ( ( 2.0 * p1.x ) +
( -p0.x + p2.x ) * t +
- ( 2.0f * p0.x - 5.0f * p1.x + 4 * p2.x - p3.x ) * t2 +
- ( -p0.x + 3.0f * p1.x - 3.0f * p2.x + p3.x ) * t3 );
- out.y = 0.5f * ( ( 2.0f * p1.y ) +
+ ( 2.0 * p0.x - 5.0 * p1.x + 4 * p2.x - p3.x ) * t2 +
+ ( -p0.x + 3.0 * p1.x - 3.0 * p2.x + p3.x ) * t3 );
+ out.y = 0.5 * ( ( 2.0 * p1.y ) +
( -p0.y + p2.y ) * t +
- ( 2.0f * p0.y - 5.0f * p1.y + 4 * p2.y - p3.y ) * t2 +
- ( -p0.y + 3.0f * p1.y - 3.0f * p2.y + p3.y ) * t3 );
- out.z = 0.5f * ( ( 2.0f * p1.z ) +
+ ( 2.0 * p0.y - 5.0 * p1.y + 4 * p2.y - p3.y ) * t2 +
+ ( -p0.y + 3.0 * p1.y - 3.0 * p2.y + p3.y ) * t3 );
+ out.z = 0.5 * ( ( 2.0 * p1.z ) +
( -p0.z + p2.z ) * t +
- ( 2.0f * p0.z - 5.0f * p1.z + 4 * p2.z - p3.z ) * t2 +
- ( -p0.z + 3.0f * p1.z - 3.0f * p2.z + p3.z ) * t3 );
+ ( 2.0 * p0.z - 5.0 * p1.z + 4 * p2.z - p3.z ) * t2 +
+ ( -p0.z + 3.0 * p1.z - 3.0 * p2.z + p3.z ) * t3 );
return out;
}
# endif
diff --git a/core/math/vector3.h b/core/math/vector3.h
index 9ae9b69dfa..a289f9bf4c 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -79,17 +79,17 @@ struct Vector3 {
_FORCE_INLINE_ void zero();
- void snap(float p_val);
- Vector3 snapped(float p_val) const;
+ void snap(real_t p_val);
+ Vector3 snapped(real_t p_val) const;
- void rotate(const Vector3& p_axis,float p_phi);
- Vector3 rotated(const Vector3& p_axis,float p_phi) const;
+ void rotate(const Vector3& p_axis,real_t p_phi);
+ Vector3 rotated(const Vector3& p_axis,real_t p_phi) const;
/* Static Methods between 2 vector3s */
- _FORCE_INLINE_ Vector3 linear_interpolate(const Vector3& p_b,float p_t) const;
- Vector3 cubic_interpolate(const Vector3& p_b,const Vector3& p_pre_a, const Vector3& p_post_b,float p_t) const;
- Vector3 cubic_interpolaten(const Vector3& p_b,const Vector3& p_pre_a, const Vector3& p_post_b,float p_t) const;
+ _FORCE_INLINE_ Vector3 linear_interpolate(const Vector3& p_b,real_t p_t) const;
+ Vector3 cubic_interpolate(const Vector3& p_b,const Vector3& p_pre_a, const Vector3& p_post_b,real_t p_t) const;
+ Vector3 cubic_interpolaten(const Vector3& p_b,const Vector3& p_pre_a, const Vector3& p_post_b,real_t p_t) const;
_FORCE_INLINE_ Vector3 cross(const Vector3& p_b) const;
_FORCE_INLINE_ real_t dot(const Vector3& p_b) const;
@@ -195,7 +195,7 @@ Vector3 Vector3::ceil() const {
return Vector3( Math::ceil(x), Math::ceil(y), Math::ceil(z) );
}
-Vector3 Vector3::linear_interpolate(const Vector3& p_b,float p_t) const {
+Vector3 Vector3::linear_interpolate(const Vector3& p_b,real_t p_t) const {
return Vector3(
x+(p_t * (p_b.x-x)),
diff --git a/core/method_ptrcall.h b/core/method_ptrcall.h
index 36b42c84f3..a35e44b66c 100644
--- a/core/method_ptrcall.h
+++ b/core/method_ptrcall.h
@@ -74,7 +74,7 @@ MAKE_PTRARG(Vector3);
MAKE_PTRARG(Transform2D);
MAKE_PTRARG(Plane);
MAKE_PTRARG(Quat);
-MAKE_PTRARG(AABB);
+MAKE_PTRARG(Rect3);
MAKE_PTRARG(Basis);
MAKE_PTRARG(Transform);
MAKE_PTRARG(Color);
@@ -84,13 +84,13 @@ MAKE_PTRARG(RID);
MAKE_PTRARG(InputEvent);
MAKE_PTRARG(Dictionary);
MAKE_PTRARG(Array);
-MAKE_PTRARG(ByteArray);
-MAKE_PTRARG(IntArray);
-MAKE_PTRARG(RealArray);
-MAKE_PTRARG(StringArray);
-MAKE_PTRARG(Vector2Array);
-MAKE_PTRARG(Vector3Array);
-MAKE_PTRARG(ColorArray);
+MAKE_PTRARG(PoolByteArray);
+MAKE_PTRARG(PoolIntArray);
+MAKE_PTRARG(PoolRealArray);
+MAKE_PTRARG(PoolStringArray);
+MAKE_PTRARG(PoolVector2Array);
+MAKE_PTRARG(PoolVector3Array);
+MAKE_PTRARG(PoolColorArray);
MAKE_PTRARG(Variant);
diff --git a/core/os/input.cpp b/core/os/input.cpp
index e53aa82b13..4e7b037453 100644
--- a/core/os/input.cpp
+++ b/core/os/input.cpp
@@ -38,7 +38,7 @@ Input *Input::get_singleton() {
}
void Input::set_mouse_mode(MouseMode p_mode) {
- ERR_FAIL_INDEX(p_mode,3);
+ ERR_FAIL_INDEX(p_mode,4);
OS::get_singleton()->set_mouse_mode((OS::MouseMode)p_mode);
}
@@ -87,6 +87,7 @@ void Input::_bind_methods() {
BIND_CONSTANT( MOUSE_MODE_VISIBLE );
BIND_CONSTANT( MOUSE_MODE_HIDDEN );
BIND_CONSTANT( MOUSE_MODE_CAPTURED );
+ BIND_CONSTANT( MOUSE_MODE_CONFINED );
ADD_SIGNAL( MethodInfo("joy_connection_changed", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "connected")) );
}
diff --git a/core/os/input.h b/core/os/input.h
index 82c7a80d3f..2cea154a50 100644
--- a/core/os/input.h
+++ b/core/os/input.h
@@ -47,7 +47,8 @@ public:
enum MouseMode {
MOUSE_MODE_VISIBLE,
MOUSE_MODE_HIDDEN,
- MOUSE_MODE_CAPTURED
+ MOUSE_MODE_CAPTURED,
+ MOUSE_MODE_CONFINED
};
void set_mouse_mode(MouseMode p_mode);
diff --git a/core/os/os.h b/core/os/os.h
index ea03481a92..42c7c18b0c 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -131,7 +131,8 @@ public:
enum MouseMode {
MOUSE_MODE_VISIBLE,
MOUSE_MODE_HIDDEN,
- MOUSE_MODE_CAPTURED
+ MOUSE_MODE_CAPTURED,
+ MOUSE_MODE_CONFINED
};
virtual void set_mouse_mode(MouseMode p_mode);
diff --git a/core/resource.cpp b/core/resource.cpp
index 4b09a506ff..6e8d9a8b17 100644
--- a/core/resource.cpp
+++ b/core/resource.cpp
@@ -486,6 +486,7 @@ Resource::Resource() {
#endif
subindex=0;
+ local_to_scene=false;
local_scene=NULL;
}
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 478c427fb9..a0d26ea0af 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -3410,8 +3410,17 @@ String String::c_escape() const {
escaped=escaped.replace("\t","\\t");
escaped=escaped.replace("\v","\\v");
escaped=escaped.replace("\'","\\'");
- escaped=escaped.replace("\"","\\\"");
escaped=escaped.replace("\?","\\?");
+ escaped=escaped.replace("\"","\\\"");
+
+ return escaped;
+}
+
+String String::c_escape_multiline() const {
+
+ String escaped=*this;
+ escaped=escaped.replace("\\","\\\\");
+ escaped=escaped.replace("\"","\\\"");
return escaped;
}
diff --git a/core/ustring.h b/core/ustring.h
index 426762a9e1..5665a23112 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -218,6 +218,7 @@ public:
String http_escape() const;
String http_unescape() const;
String c_escape() const;
+ String c_escape_multiline() const;
String c_unescape() const;
String json_escape() const;
String word_wrap(int p_chars_per_line) const;
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
index a833a275df..1e938b4899 100644
--- a/core/variant_parser.cpp
+++ b/core/variant_parser.cpp
@@ -1873,7 +1873,7 @@ Error VariantWriter::write(const Variant& p_variant, StoreStringFunc p_store_str
String str=p_variant;
- str="\""+str.c_escape()+"\"";
+ str="\""+str.c_escape_multiline()+"\"";
p_store_string_func(p_store_string_ud, str );
} break;
case Variant::VECTOR2: {
@@ -2091,7 +2091,7 @@ Error VariantWriter::write(const Variant& p_variant, StoreStringFunc p_store_str
dict.get_key_list(&keys);
keys.sort();
- p_store_string_func(p_store_string_ud,"{ ");
+ p_store_string_func(p_store_string_ud,"{\n");
for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
/*
@@ -2099,14 +2099,14 @@ Error VariantWriter::write(const Variant& p_variant, StoreStringFunc p_store_str
continue;
*/
write(E->get(),p_store_string_func,p_store_string_ud,p_encode_res_func,p_encode_res_ud);
- p_store_string_func(p_store_string_ud,":");
+ p_store_string_func(p_store_string_ud,": ");
write(dict[E->get()],p_store_string_func,p_store_string_ud,p_encode_res_func,p_encode_res_ud);
if (E->next())
- p_store_string_func(p_store_string_ud,", ");
+ p_store_string_func(p_store_string_ud,",\n");
}
- p_store_string_func(p_store_string_ud," }");
+ p_store_string_func(p_store_string_ud,"\n}");
} break;
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index f47fcfcd9b..b972c6a877 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -166,7 +166,7 @@ void RasterizerSceneGLES3::shadow_atlas_set_quadrant_subdivision(RID p_atlas,int
subdiv<<=1;
}
- subdiv=int(Math::sqrt(subdiv));
+ subdiv=int(Math::sqrt((float)subdiv));
//obtain the number that will be x*x
@@ -568,7 +568,7 @@ void RasterizerSceneGLES3::reflection_atlas_set_subdivision(RID p_ref_atlas,int
subdiv<<=1;
}
- subdiv=int(Math::sqrt(subdiv));
+ subdiv=int(Math::sqrt((float)subdiv));
if (reflection_atlas->subdiv==subdiv)
return;
@@ -4567,7 +4567,7 @@ static _FORCE_INLINE_ Vector3 ImportanceSampleGGX(Vector2 Xi, float Roughness, V
// Compute distribution direction
float Phi = 2.0f * Math_PI * Xi.x;
- float CosTheta = Math::sqrt((1.0f - Xi.y) / (1.0f + (a*a - 1.0f) * Xi.y));
+ float CosTheta = Math::sqrt((float)(1.0f - Xi.y) / (1.0f + (a*a - 1.0f) * Xi.y));
float SinTheta = Math::sqrt((float)Math::abs(1.0f - CosTheta * CosTheta));
// Convert to spherical direction
@@ -4615,7 +4615,7 @@ void RasterizerSceneGLES3::_generate_brdf() {
float NoV = float(i+1)/(brdf_size); //avoid storing nov0
Vector3 V;
- V.x = Math::sqrt( 1.0 - NoV * NoV );
+ V.x = Math::sqrt( 1.0f - NoV * NoV );
V.y = 0.0;
V.z = NoV;
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 9f1ff396f1..96befee869 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -5256,7 +5256,7 @@ void RasterizerStorageGLES3::update_particles() {
shaders.particles.set_uniform(ParticlesShaderGLES3::ORIGIN,particles->origin);
- float new_phase = Math::fmod(particles->phase+(frame.delta/particles->lifetime),1.0);
+ float new_phase = Math::fmod((float)particles->phase+(frame.delta/particles->lifetime),(float)1.0);
shaders.particles.set_uniform(ParticlesShaderGLES3::SYSTEM_PHASE,new_phase);
shaders.particles.set_uniform(ParticlesShaderGLES3::PREV_SYSTEM_PHASE,particles->phase);
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index 14b1b229b2..5f0e647545 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -65,15 +65,15 @@ Error AudioDriverPulseAudio::init() {
int error_code;
pulse = pa_simple_new( NULL, // default server
- "Godot", // application name
- PA_STREAM_PLAYBACK,
- NULL, // default device
- "Sound", // stream description
- &spec,
- NULL, // use default channel map
- &attr, // use buffering attributes from above
- &error_code
- );
+ "Godot", // application name
+ PA_STREAM_PLAYBACK,
+ NULL, // default device
+ "Sound", // stream description
+ &spec,
+ NULL, // use default channel map
+ &attr, // use buffering attributes from above
+ &error_code
+ );
if (pulse == NULL) {
fprintf(stderr, "PulseAudio ERR: %s\n", pa_strerror(error_code));\
@@ -103,6 +103,7 @@ float AudioDriverPulseAudio::get_latency() {
void AudioDriverPulseAudio::thread_func(void* p_udata) {
+ print_line("thread");
AudioDriverPulseAudio* ad = (AudioDriverPulseAudio*)p_udata;
while (!ad->exit_thread) {
@@ -121,9 +122,9 @@ void AudioDriverPulseAudio::thread_func(void* p_udata) {
for (unsigned int i=0; i < ad->buffer_size * ad->channels;i ++) {
ad->samples_out[i] = ad->samples_in[i] >> 16;
}
- }
+ }
- // pa_simple_write always consumes the entire buffer
+ // pa_simple_write always consumes the entire buffer
int error_code;
int byte_size = ad->buffer_size * sizeof(int16_t) * ad->channels;
@@ -134,7 +135,7 @@ void AudioDriverPulseAudio::thread_func(void* p_udata) {
ad->exit_thread = true;
break;
}
- }
+ }
ad->thread_exited = true;
}
diff --git a/main/input_default.cpp b/main/input_default.cpp
index ea4e3f9505..82dec86067 100644
--- a/main/input_default.cpp
+++ b/main/input_default.cpp
@@ -486,7 +486,7 @@ Point2 InputDefault::get_last_mouse_speed() const {
int InputDefault::get_mouse_button_mask() const {
- return OS::get_singleton()->get_mouse_button_state();
+ return mouse_button_mask;// do not trust OS implementaiton, should remove it - OS::get_singleton()->get_mouse_button_state();
}
void InputDefault::warp_mouse_pos(const Vector2& p_to) {
diff --git a/main/main.cpp b/main/main.cpp
index 559f5e359b..22223fe2c4 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -1046,6 +1046,7 @@ Error Main::setup2() {
translation_server->load_translations();
+ audio_server->load_default_bus_layout();
if (use_debug_profiler && script_debugger) {
script_debugger->profiling_start();
diff --git a/modules/gdscript/gd_functions.cpp b/modules/gdscript/gd_functions.cpp
index 4f3516c097..d0fc241734 100644
--- a/modules/gdscript/gd_functions.cpp
+++ b/modules/gdscript/gd_functions.cpp
@@ -159,85 +159,85 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
case MATH_SIN: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::sin(*p_args[0]);
+ r_ret=Math::sin((double)*p_args[0]);
} break;
case MATH_COS: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::cos(*p_args[0]);
+ r_ret=Math::cos((double)*p_args[0]);
} break;
case MATH_TAN: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::tan(*p_args[0]);
+ r_ret=Math::tan((double)*p_args[0]);
} break;
case MATH_SINH: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::sinh(*p_args[0]);
+ r_ret=Math::sinh((double)*p_args[0]);
} break;
case MATH_COSH: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::cosh(*p_args[0]);
+ r_ret=Math::cosh((double)*p_args[0]);
} break;
case MATH_TANH: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::tanh(*p_args[0]);
+ r_ret=Math::tanh((double)*p_args[0]);
} break;
case MATH_ASIN: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::asin(*p_args[0]);
+ r_ret=Math::asin((double)*p_args[0]);
} break;
case MATH_ACOS: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::acos(*p_args[0]);
+ r_ret=Math::acos((double)*p_args[0]);
} break;
case MATH_ATAN: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::atan(*p_args[0]);
+ r_ret=Math::atan((double)*p_args[0]);
} break;
case MATH_ATAN2: {
VALIDATE_ARG_COUNT(2);
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
- r_ret=Math::atan2(*p_args[0],*p_args[1]);
+ r_ret=Math::atan2((double)*p_args[0],(double)*p_args[1]);
} break;
case MATH_SQRT: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::sqrt(*p_args[0]);
+ r_ret=Math::sqrt((double)*p_args[0]);
} break;
case MATH_FMOD: {
VALIDATE_ARG_COUNT(2);
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
- r_ret=Math::fmod(*p_args[0],*p_args[1]);
+ r_ret=Math::fmod((double)*p_args[0],(double)*p_args[1]);
} break;
case MATH_FPOSMOD: {
VALIDATE_ARG_COUNT(2);
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
- r_ret=Math::fposmod(*p_args[0],*p_args[1]);
+ r_ret=Math::fposmod((double)*p_args[0],(double)*p_args[1]);
} break;
case MATH_FLOOR: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::floor(*p_args[0]);
+ r_ret=Math::floor((double)*p_args[0]);
} break;
case MATH_CEIL: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::ceil(*p_args[0]);
+ r_ret=Math::ceil((double)*p_args[0]);
} break;
case MATH_ROUND: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::round(*p_args[0]);
+ r_ret=Math::round((double)*p_args[0]);
} break;
case MATH_ABS: {
VALIDATE_ARG_COUNT(1);
@@ -247,7 +247,7 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
r_ret=ABS(i);
} else if (p_args[0]->get_type()==Variant::REAL) {
- real_t r = *p_args[0];
+ double r = *p_args[0];
r_ret=Math::abs(r);
} else {
@@ -279,58 +279,58 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
VALIDATE_ARG_COUNT(2);
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
- r_ret=Math::pow(*p_args[0],*p_args[1]);
+ r_ret=Math::pow((double)*p_args[0],(double)*p_args[1]);
} break;
case MATH_LOG: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::log(*p_args[0]);
+ r_ret=Math::log((double)*p_args[0]);
} break;
case MATH_EXP: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::exp(*p_args[0]);
+ r_ret=Math::exp((double)*p_args[0]);
} break;
case MATH_ISNAN: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::is_nan(*p_args[0]);
+ r_ret=Math::is_nan((double)*p_args[0]);
} break;
case MATH_ISINF: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::is_inf(*p_args[0]);
+ r_ret=Math::is_inf((double)*p_args[0]);
} break;
case MATH_EASE: {
VALIDATE_ARG_COUNT(2);
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
- r_ret=Math::ease(*p_args[0],*p_args[1]);
+ r_ret=Math::ease((double)*p_args[0],(double)*p_args[1]);
} break;
case MATH_DECIMALS: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::step_decimals(*p_args[0]);
+ r_ret=Math::step_decimals((double)*p_args[0]);
} break;
case MATH_STEPIFY: {
VALIDATE_ARG_COUNT(2);
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
- r_ret=Math::stepify(*p_args[0],*p_args[1]);
+ r_ret=Math::stepify((double)*p_args[0],(double)*p_args[1]);
} break;
case MATH_LERP: {
VALIDATE_ARG_COUNT(3);
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
VALIDATE_ARG_NUM(2);
- r_ret=Math::lerp(*p_args[0],*p_args[1],*p_args[2]);
+ r_ret=Math::lerp((double)*p_args[0],(double)*p_args[1],(double)*p_args[2]);
} break;
case MATH_DECTIME: {
VALIDATE_ARG_COUNT(3);
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
VALIDATE_ARG_NUM(2);
- r_ret=Math::dectime(*p_args[0],*p_args[1],*p_args[2]);
+ r_ret=Math::dectime((double)*p_args[0],(double)*p_args[1],(double)*p_args[2]);
} break;
case MATH_RANDOMIZE: {
Math::randomize();
@@ -346,7 +346,7 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
VALIDATE_ARG_COUNT(2);
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
- r_ret=Math::random(*p_args[0],*p_args[1]);
+ r_ret=Math::random((double)*p_args[0],(double)*p_args[1]);
} break;
case MATH_SEED: {
VALIDATE_ARG_COUNT(1);
@@ -369,22 +369,22 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
case MATH_DEG2RAD: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::deg2rad(*p_args[0]);
+ r_ret=Math::deg2rad((double)*p_args[0]);
} break;
case MATH_RAD2DEG: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::rad2deg(*p_args[0]);
+ r_ret=Math::rad2deg((double)*p_args[0]);
} break;
case MATH_LINEAR2DB: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::linear2db(*p_args[0]);
+ r_ret=Math::linear2db((double)*p_args[0]);
} break;
case MATH_DB2LINEAR: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::db2linear(*p_args[0]);
+ r_ret=Math::db2linear((double)*p_args[0]);
} break;
case LOGIC_MAX: {
VALIDATE_ARG_COUNT(2);
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp
index 70659326e5..34c39c8024 100644
--- a/modules/gdscript/gd_parser.cpp
+++ b/modules/gdscript/gd_parser.cpp
@@ -1704,7 +1704,7 @@ GDParser::PatternNode *GDParser::_parse_pattern(bool p_static)
}
switch (token) {
- // dictionary
+ // array
case GDTokenizer::TK_BRACKET_OPEN: {
tokenizer->advance();
pattern->pt_type = GDParser::PatternNode::PT_ARRAY;
@@ -1759,7 +1759,7 @@ GDParser::PatternNode *GDParser::_parse_pattern(bool p_static)
pattern->bind = tokenizer->get_token_identifier();
tokenizer->advance();
} break;
- // array
+ // dictionary
case GDTokenizer::TK_CURLY_BRACKET_OPEN: {
tokenizer->advance();
pattern->pt_type = GDParser::PatternNode::PT_DICTIONARY;
@@ -1826,17 +1826,16 @@ GDParser::PatternNode *GDParser::_parse_pattern(bool p_static)
}
}
} break;
+ case GDTokenizer::TK_WILDCARD: {
+ tokenizer->advance();
+ pattern->pt_type = PatternNode::PT_WILDCARD;
+ } break;
// all the constants like strings and numbers
default: {
Node *value = _parse_and_reduce_expression(pattern, p_static);
if (error_set) {
return NULL;
}
- if (value->type == Node::TYPE_IDENTIFIER && static_cast<IdentifierNode*>(value)->name == "_") {
- // wildcard pattern
- pattern->pt_type = PatternNode::PT_WILDCARD;
- break;
- }
if (value->type != Node::TYPE_IDENTIFIER && value->type != Node::TYPE_CONSTANT) {
_set_error("Only constant expressions or variables allowed in a pattern");
diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp
index 70fc991bcc..5be2a2beae 100644
--- a/modules/gdscript/gd_tokenizer.cpp
+++ b/modules/gdscript/gd_tokenizer.cpp
@@ -119,6 +119,7 @@ const char* GDTokenizer::token_names[TK_MAX]={
"':'",
"'\\n'",
"PI",
+"_",
"Error",
"EOF",
"Cursor"};
@@ -899,6 +900,7 @@ void GDTokenizerText::_advance() {
{TK_CF_PASS,"pass"},
{TK_SELF,"self"},
{TK_CONST_PI,"PI"},
+ {TK_WILDCARD,"_"},
{TK_ERROR,NULL}
};
diff --git a/modules/gdscript/gd_tokenizer.h b/modules/gdscript/gd_tokenizer.h
index 9a6f4df9c4..5d955ff1ae 100644
--- a/modules/gdscript/gd_tokenizer.h
+++ b/modules/gdscript/gd_tokenizer.h
@@ -127,6 +127,7 @@ public:
TK_DOLLAR,
TK_NEWLINE,
TK_CONST_PI,
+ TK_WILDCARD,
TK_ERROR,
TK_EOF,
TK_CURSOR, //used for code completion
diff --git a/modules/stb_vorbis/SCsub b/modules/stb_vorbis/SCsub
new file mode 100644
index 0000000000..897d05961c
--- /dev/null
+++ b/modules/stb_vorbis/SCsub
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+
+Import('env')
+Import('env_modules')
+
+# Thirdparty source files
+
+env_stb_vorbis = env_modules.Clone()
+
+env_stb_vorbis.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
new file mode 100644
index 0000000000..31bf5ac292
--- /dev/null
+++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
@@ -0,0 +1,236 @@
+
+#include "audio_stream_ogg_vorbis.h"
+#include "thirdparty/stb_vorbis/stb_vorbis.c"
+#include "os/file_access.h"
+
+
+void AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame* p_buffer,int p_frames) {
+
+ ERR_FAIL_COND(!active);
+
+ int todo=p_frames;
+
+ while(todo) {
+
+ int mixed = stb_vorbis_get_samples_float_interleaved(ogg_stream,2,(float*)p_buffer,todo*2);
+ todo-=mixed;
+
+ if (todo) {
+ //end of file!
+ if (false) {
+ //loop
+ seek_pos(0);
+ loops++;
+ } else {
+ for(int i=mixed;i<p_frames;i++) {
+ p_buffer[i]=AudioFrame(0,0);
+ }
+ active=false;
+ }
+ }
+ }
+
+
+}
+
+float AudioStreamPlaybackOGGVorbis::get_stream_sampling_rate() {
+
+ return vorbis_stream->sample_rate;
+}
+
+
+void AudioStreamPlaybackOGGVorbis::start(float p_from_pos) {
+
+ seek_pos(p_from_pos);
+ active=true;
+ loops=0;
+ _begin_resample();
+
+
+}
+
+void AudioStreamPlaybackOGGVorbis::stop() {
+
+ active=false;
+}
+bool AudioStreamPlaybackOGGVorbis::is_playing() const {
+
+ return active;
+}
+
+int AudioStreamPlaybackOGGVorbis::get_loop_count() const {
+
+ return loops;
+}
+
+float AudioStreamPlaybackOGGVorbis::get_pos() const {
+
+ return float(frames_mixed)/vorbis_stream->sample_rate;
+}
+void AudioStreamPlaybackOGGVorbis::seek_pos(float p_time) {
+
+ if (!active)
+ return;
+
+ stb_vorbis_seek(ogg_stream, uint32_t(p_time*vorbis_stream->sample_rate));
+}
+
+float AudioStreamPlaybackOGGVorbis::get_length() const {
+
+ return vorbis_stream->length;
+}
+
+AudioStreamPlaybackOGGVorbis::~AudioStreamPlaybackOGGVorbis() {
+ if (ogg_alloc.alloc_buffer) {
+ AudioServer::get_singleton()->audio_data_free(ogg_alloc.alloc_buffer);
+ stb_vorbis_close(ogg_stream);
+ }
+}
+
+Ref<AudioStreamPlayback> AudioStreamOGGVorbis::instance_playback() {
+
+
+
+ Ref<AudioStreamPlaybackOGGVorbis> ovs;
+ printf("instance at %p, data %p\n",this,data);
+
+ ERR_FAIL_COND_V(data==NULL,ovs);
+
+ ovs.instance();
+ ovs->vorbis_stream=Ref<AudioStreamOGGVorbis>(this);
+ ovs->ogg_alloc.alloc_buffer=(char*)AudioServer::get_singleton()->audio_data_alloc(decode_mem_size);
+ ovs->ogg_alloc.alloc_buffer_length_in_bytes=decode_mem_size;
+ ovs->frames_mixed=0;
+ ovs->active=false;
+ ovs->loops=0;
+ int error ;
+ ovs->ogg_stream = stb_vorbis_open_memory( (const unsigned char*)data, data_len, &error, &ovs->ogg_alloc );
+ if (!ovs->ogg_stream) {
+
+ AudioServer::get_singleton()->audio_data_free(ovs->ogg_alloc.alloc_buffer);
+ ovs->ogg_alloc.alloc_buffer=NULL;
+ ERR_FAIL_COND_V(!ovs->ogg_stream,Ref<AudioStreamPlaybackOGGVorbis>());
+ }
+
+ return ovs;
+}
+
+String AudioStreamOGGVorbis::get_stream_name() const {
+
+ return "";//return stream_name;
+}
+
+Error AudioStreamOGGVorbis::setup(const uint8_t *p_data,uint32_t p_data_len) {
+
+
+#define MAX_TEST_MEM (1<<20)
+
+ uint32_t alloc_try=1024;
+ PoolVector<char> alloc_mem;
+ PoolVector<char>::Write w;
+ stb_vorbis * ogg_stream=NULL;
+ stb_vorbis_alloc ogg_alloc;
+
+ while(alloc_try<MAX_TEST_MEM) {
+
+ alloc_mem.resize(alloc_try);
+ w = alloc_mem.write();
+
+ ogg_alloc.alloc_buffer=w.ptr();
+ ogg_alloc.alloc_buffer_length_in_bytes=alloc_try;
+
+ int error;
+ ogg_stream = stb_vorbis_open_memory( (const unsigned char*)p_data, p_data_len, &error, &ogg_alloc );
+
+ if (!ogg_stream && error==VORBIS_outofmem) {
+ w = PoolVector<char>::Write();
+ alloc_try*=2;
+ } else {
+ break;
+ }
+ }
+ ERR_FAIL_COND_V(alloc_try==MAX_TEST_MEM,ERR_OUT_OF_MEMORY);
+ ERR_FAIL_COND_V(ogg_stream==NULL,ERR_FILE_CORRUPT);
+
+ stb_vorbis_info info = stb_vorbis_get_info(ogg_stream);
+
+ channels = info.channels;
+ sample_rate = info.sample_rate;
+ decode_mem_size = alloc_try;
+ //does this work? (it's less mem..)
+ //decode_mem_size = ogg_alloc.alloc_buffer_length_in_bytes + info.setup_memory_required + info.temp_memory_required + info.max_frame_size;
+
+ //print_line("succeded "+itos(ogg_alloc.alloc_buffer_length_in_bytes)+" setup "+itos(info.setup_memory_required)+" setup temp "+itos(info.setup_temp_memory_required)+" temp "+itos(info.temp_memory_required)+" maxframe"+itos(info.max_frame_size));
+
+ length=stb_vorbis_stream_length_in_seconds(ogg_stream);
+ stb_vorbis_close(ogg_stream);
+
+ data = AudioServer::get_singleton()->audio_data_alloc(p_data_len,p_data);
+ data_len=p_data_len;
+
+ printf("create at %p, data %p\n",this,data);
+ return OK;
+}
+
+AudioStreamOGGVorbis::AudioStreamOGGVorbis() {
+
+
+ data=NULL;
+ length=0;
+ sample_rate=1;
+ channels=1;
+ decode_mem_size=0;
+}
+
+
+
+
+RES ResourceFormatLoaderAudioStreamOGGVorbis::load(const String &p_path, const String& p_original_path, Error *r_error) {
+ if (r_error)
+ *r_error=OK;
+
+ FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
+ if (!f) {
+ *r_error=ERR_CANT_OPEN;
+ ERR_FAIL_COND_V(!f,RES());
+ }
+
+ size_t len = f->get_len();
+
+ PoolVector<uint8_t> data;
+ data.resize(len);
+ PoolVector<uint8_t>::Write w = data.write();
+
+ f->get_buffer(w.ptr(),len);
+
+ memdelete(f);
+
+ Ref<AudioStreamOGGVorbis> ogg_stream;
+ ogg_stream.instance();
+
+ Error err = ogg_stream->setup(w.ptr(),len);
+
+ if (err!=OK) {
+ *r_error=err;
+ ogg_stream.unref();
+ ERR_FAIL_V(RES());
+ }
+
+ return ogg_stream;
+}
+
+void ResourceFormatLoaderAudioStreamOGGVorbis::get_recognized_extensions(List<String> *p_extensions) const {
+
+ p_extensions->push_back("ogg");
+}
+String ResourceFormatLoaderAudioStreamOGGVorbis::get_resource_type(const String &p_path) const {
+
+ if (p_path.get_extension().to_lower()=="ogg")
+ return "AudioStreamOGGVorbis";
+ return "";
+}
+
+bool ResourceFormatLoaderAudioStreamOGGVorbis::handles_type(const String& p_type) const {
+ return (p_type=="AudioStream" || p_type=="AudioStreamOGG" || p_type=="AudioStreamOGGVorbis");
+}
+
diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.h b/modules/stb_vorbis/audio_stream_ogg_vorbis.h
new file mode 100644
index 0000000000..4555423f85
--- /dev/null
+++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.h
@@ -0,0 +1,84 @@
+#ifndef AUDIO_STREAM_STB_VORBIS_H
+#define AUDIO_STREAM_STB_VORBIS_H
+
+#include "servers/audio/audio_stream.h"
+#include "io/resource_loader.h"
+
+#define STB_VORBIS_HEADER_ONLY
+#include "thirdparty/stb_vorbis/stb_vorbis.c"
+#undef STB_VORBIS_HEADER_ONLY
+
+
+class AudioStreamOGGVorbis;
+
+class AudioStreamPlaybackOGGVorbis : public AudioStreamPlaybackResampled {
+
+ GDCLASS( AudioStreamPlaybackOGGVorbis, AudioStreamPlaybackResampled )
+
+ stb_vorbis * ogg_stream;
+ stb_vorbis_alloc ogg_alloc;
+ uint32_t frames_mixed;
+ bool active;
+ int loops;
+
+friend class AudioStreamOGGVorbis;
+
+ Ref<AudioStreamOGGVorbis> vorbis_stream;
+protected:
+
+ virtual void _mix_internal(AudioFrame* p_buffer, int p_frames);
+ virtual float get_stream_sampling_rate();
+
+public:
+ virtual void start(float p_from_pos=0.0);
+ virtual void stop();
+ virtual bool is_playing() const;
+
+ virtual int get_loop_count() const; //times it looped
+
+ virtual float get_pos() const;
+ virtual void seek_pos(float p_time);
+
+ virtual float get_length() const; //if supported, otherwise return 0
+
+ AudioStreamPlaybackOGGVorbis() { }
+ ~AudioStreamPlaybackOGGVorbis();
+};
+
+class AudioStreamOGGVorbis : public AudioStream {
+
+ GDCLASS( AudioStreamOGGVorbis, AudioStream )
+ OBJ_SAVE_TYPE( AudioStream ) //children are all saved as AudioStream, so they can be exchanged
+
+friend class AudioStreamPlaybackOGGVorbis;
+
+ void *data;
+ uint32_t data_len;
+
+ int decode_mem_size;
+ float sample_rate;
+ int channels;
+ float length;
+
+public:
+
+
+ virtual Ref<AudioStreamPlayback> instance_playback();
+ virtual String get_stream_name() const;
+
+ Error setup(const uint8_t *p_data, uint32_t p_data_len);
+
+ AudioStreamOGGVorbis();
+};
+
+class ResourceFormatLoaderAudioStreamOGGVorbis : public ResourceFormatLoader {
+public:
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String& p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+};
+
+
+
+#endif
diff --git a/modules/stb_vorbis/config.py b/modules/stb_vorbis/config.py
new file mode 100644
index 0000000000..fb920482f5
--- /dev/null
+++ b/modules/stb_vorbis/config.py
@@ -0,0 +1,7 @@
+
+def can_build(platform):
+ return True
+
+
+def configure(env):
+ pass
diff --git a/scene/resources/audio_stream.cpp b/modules/stb_vorbis/register_types.cpp
index 7c269de007..143ad6f47e 100644
--- a/scene/resources/audio_stream.cpp
+++ b/modules/stb_vorbis/register_types.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* audio_stream.cpp */
+/* register_types.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -26,36 +26,19 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "audio_stream.h"
+#include "register_types.h"
+#include "audio_stream_ogg_vorbis.h"
-//////////////////////////////
-
-
-void AudioStreamPlayback::_bind_methods() {
-
- ClassDB::bind_method(_MD("play","from_pos_sec"),&AudioStreamPlayback::play,DEFVAL(0));
- ClassDB::bind_method(_MD("stop"),&AudioStreamPlayback::stop);
- ClassDB::bind_method(_MD("is_playing"),&AudioStreamPlayback::is_playing);
-
- ClassDB::bind_method(_MD("set_loop","enabled"),&AudioStreamPlayback::set_loop);
- ClassDB::bind_method(_MD("has_loop"),&AudioStreamPlayback::has_loop);
-
- ClassDB::bind_method(_MD("get_loop_count"),&AudioStreamPlayback::get_loop_count);
-
- ClassDB::bind_method(_MD("seek_pos","pos"),&AudioStreamPlayback::seek_pos);
- ClassDB::bind_method(_MD("get_pos"),&AudioStreamPlayback::get_pos);
-
- ClassDB::bind_method(_MD("get_length"),&AudioStreamPlayback::get_length);
- ClassDB::bind_method(_MD("get_channels"),&AudioStreamPlayback::get_channels);
- ClassDB::bind_method(_MD("get_mix_rate"),&AudioStreamPlayback::get_mix_rate);
- ClassDB::bind_method(_MD("get_minimum_buffer_size"),&AudioStreamPlayback::get_minimum_buffer_size);
+static ResourceFormatLoaderAudioStreamOGGVorbis *vorbis_stream_loader = NULL;
+void register_stb_vorbis_types() {
+ vorbis_stream_loader = memnew( ResourceFormatLoaderAudioStreamOGGVorbis );
+ ResourceLoader::add_resource_format_loader(vorbis_stream_loader);
+ ClassDB::register_class<AudioStreamOGGVorbis>();
}
+void unregister_stb_vorbis_types() {
-void AudioStream::_bind_methods() {
-
-
+ memdelete( vorbis_stream_loader );
}
-
diff --git a/modules/stb_vorbis/register_types.h b/modules/stb_vorbis/register_types.h
new file mode 100644
index 0000000000..2824aa9f0c
--- /dev/null
+++ b/modules/stb_vorbis/register_types.h
@@ -0,0 +1,30 @@
+/*************************************************************************/
+/* register_types.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* 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 */
+/* "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. */
+/*************************************************************************/
+void register_stb_vorbis_types();
+void unregister_stb_vorbis_types();
diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp
index 169af6fbec..a0f23a511f 100644
--- a/modules/visual_script/visual_script_builtin_funcs.cpp
+++ b/modules/visual_script/visual_script_builtin_funcs.cpp
@@ -610,85 +610,85 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func,const Variant** p_inp
case VisualScriptBuiltinFunc::MATH_SIN: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::sin(*p_inputs[0]);
+ *r_return=Math::sin((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_COS: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::cos(*p_inputs[0]);
+ *r_return=Math::cos((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_TAN: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::tan(*p_inputs[0]);
+ *r_return=Math::tan((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_SINH: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::sinh(*p_inputs[0]);
+ *r_return=Math::sinh((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_COSH: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::cosh(*p_inputs[0]);
+ *r_return=Math::cosh((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_TANH: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::tanh(*p_inputs[0]);
+ *r_return=Math::tanh((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_ASIN: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::asin(*p_inputs[0]);
+ *r_return=Math::asin((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_ACOS: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::acos(*p_inputs[0]);
+ *r_return=Math::acos((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_ATAN: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::atan(*p_inputs[0]);
+ *r_return=Math::atan((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_ATAN2: {
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
- *r_return=Math::atan2(*p_inputs[0],*p_inputs[1]);
+ *r_return=Math::atan2((double)*p_inputs[0],(double)*p_inputs[1]);
} break;
case VisualScriptBuiltinFunc::MATH_SQRT: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::sqrt(*p_inputs[0]);
+ *r_return=Math::sqrt((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_FMOD: {
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
- *r_return=Math::fmod(*p_inputs[0],*p_inputs[1]);
+ *r_return=Math::fmod((double)*p_inputs[0],(double)*p_inputs[1]);
} break;
case VisualScriptBuiltinFunc::MATH_FPOSMOD: {
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
- *r_return=Math::fposmod(*p_inputs[0],*p_inputs[1]);
+ *r_return=Math::fposmod((double)*p_inputs[0],(double)*p_inputs[1]);
} break;
case VisualScriptBuiltinFunc::MATH_FLOOR: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::floor(*p_inputs[0]);
+ *r_return=Math::floor((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_CEIL: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::ceil(*p_inputs[0]);
+ *r_return=Math::ceil((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_ROUND: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::round(*p_inputs[0]);
+ *r_return=Math::round((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_ABS: {
@@ -730,58 +730,58 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func,const Variant** p_inp
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
- *r_return=Math::pow(*p_inputs[0],*p_inputs[1]);
+ *r_return=Math::pow((double)*p_inputs[0],(double)*p_inputs[1]);
} break;
case VisualScriptBuiltinFunc::MATH_LOG: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::log(*p_inputs[0]);
+ *r_return=Math::log((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_EXP: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::exp(*p_inputs[0]);
+ *r_return=Math::exp((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_ISNAN: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::is_nan(*p_inputs[0]);
+ *r_return=Math::is_nan((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_ISINF: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::is_inf(*p_inputs[0]);
+ *r_return=Math::is_inf((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_EASE: {
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
- *r_return=Math::ease(*p_inputs[0],*p_inputs[1]);
+ *r_return=Math::ease((double)*p_inputs[0],(double)*p_inputs[1]);
} break;
case VisualScriptBuiltinFunc::MATH_DECIMALS: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::step_decimals(*p_inputs[0]);
+ *r_return=Math::step_decimals((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_STEPIFY: {
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
- *r_return=Math::stepify(*p_inputs[0],*p_inputs[1]);
+ *r_return=Math::stepify((double)*p_inputs[0],(double)*p_inputs[1]);
} break;
case VisualScriptBuiltinFunc::MATH_LERP: {
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
VALIDATE_ARG_NUM(2);
- *r_return=Math::lerp(*p_inputs[0],*p_inputs[1],*p_inputs[2]);
+ *r_return=Math::lerp((double)*p_inputs[0],(double)*p_inputs[1],(double)*p_inputs[2]);
} break;
case VisualScriptBuiltinFunc::MATH_DECTIME: {
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
VALIDATE_ARG_NUM(2);
- *r_return=Math::dectime(*p_inputs[0],*p_inputs[1],*p_inputs[2]);
+ *r_return=Math::dectime((double)*p_inputs[0],(double)*p_inputs[1],(double)*p_inputs[2]);
} break;
case VisualScriptBuiltinFunc::MATH_RANDOMIZE: {
Math::randomize();
@@ -797,7 +797,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func,const Variant** p_inp
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
- *r_return=Math::random(*p_inputs[0],*p_inputs[1]);
+ *r_return=Math::random((double)*p_inputs[0],(double)*p_inputs[1]);
} break;
case VisualScriptBuiltinFunc::MATH_SEED: {
@@ -820,22 +820,22 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func,const Variant** p_inp
case VisualScriptBuiltinFunc::MATH_DEG2RAD: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::deg2rad(*p_inputs[0]);
+ *r_return=Math::deg2rad((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_RAD2DEG: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::rad2deg(*p_inputs[0]);
+ *r_return=Math::rad2deg((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_LINEAR2DB: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::linear2db(*p_inputs[0]);
+ *r_return=Math::linear2db((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_DB2LINEAR: {
VALIDATE_ARG_NUM(0);
- *r_return=Math::db2linear(*p_inputs[0]);
+ *r_return=Math::db2linear((double)*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::LOGIC_MAX: {
diff --git a/platform/android/build.gradle.template b/platform/android/build.gradle.template
index 873eef0566..c46a15bd12 100644
--- a/platform/android/build.gradle.template
+++ b/platform/android/build.gradle.template
@@ -52,11 +52,10 @@ android {
java.srcDirs = ['src'
$$GRADLE_JAVA_DIRS$$
]
- resources.srcDirs = [
+ res.srcDirs = [
'res'
$$GRADLE_RES_DIRS$$
]
- res.srcDirs = ['res']
// libs.srcDirs = ['libs']
aidl.srcDirs = [
'aidl'
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index d1d769adf7..b230dda9cb 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -254,6 +254,25 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) // Check For Windows Messages
{
+ case WM_SETFOCUS:
+ {
+ window_has_focus = true;
+ // Re-capture cursor if we're in one of the capture modes
+ if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED) {
+ SetCapture(hWnd);
+ }
+ break;
+ }
+ case WM_KILLFOCUS:
+ {
+ window_has_focus = false;
+
+ // Release capture if we're in one of the capture modes
+ if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED) {
+ ReleaseCapture();
+ }
+ break;
+ }
case WM_ACTIVATE: // Watch For Window Activate Message
{
minimized = HIWORD(wParam) != 0;
@@ -266,19 +285,17 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
alt_mem=false;
control_mem=false;
shift_mem=false;
- if (mouse_mode==MOUSE_MODE_CAPTURED) {
+ if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED) {
RECT clipRect;
GetClientRect(hWnd, &clipRect);
ClientToScreen(hWnd, (POINT*) &clipRect.left);
ClientToScreen(hWnd, (POINT*) &clipRect.right);
ClipCursor(&clipRect);
SetCapture(hWnd);
-
}
} else {
main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
alt_mem=false;
-
};
return 0; // Return To The Message Loop
@@ -345,6 +362,9 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
}
+ // Don't calculate relative mouse movement if we don't have focus in CAPTURED mode.
+ if (!window_has_focus && mouse_mode==MOUSE_MODE_CAPTURED)
+ break;
/*
LPARAM extra = GetMessageExtraInfo();
if (IsPenEvent(extra)) {
@@ -376,7 +396,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
mm.button_mask|=(wParam&MK_XBUTTON2)?(1<<6):0;*/
mm.x=GET_X_LPARAM(lParam);
mm.y=GET_Y_LPARAM(lParam);
-
+
if (mouse_mode==MOUSE_MODE_CAPTURED) {
Point2i c(video_mode.width/2,video_mode.height/2);
@@ -410,7 +430,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
mm.relative_y=mm.y-old_y;
old_x=mm.x;
old_y=mm.y;
- if (main_loop)
+ if (window_has_focus && main_loop)
input->parse_input_event(event);
@@ -714,9 +734,8 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
joypad->probe_joypads();
} break;
case WM_SETCURSOR: {
-
if(LOWORD(lParam) == HTCLIENT) {
- if(mouse_mode == MOUSE_MODE_HIDDEN || mouse_mode == MOUSE_MODE_CAPTURED) {
+ if(window_has_focus && (mouse_mode == MOUSE_MODE_HIDDEN || mouse_mode == MOUSE_MODE_CAPTURED)) {
//Hide the cursor
if(hCursor == NULL)
hCursor = SetCursor(NULL);
@@ -948,7 +967,7 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_
main_loop=NULL;
outside=true;
-
+ window_has_focus=true;
WNDCLASSEXW wc;
video_mode=p_desired;
@@ -1326,17 +1345,17 @@ void OS_Windows::set_mouse_mode(MouseMode p_mode) {
if (mouse_mode==p_mode)
return;
mouse_mode=p_mode;
- if (p_mode==MOUSE_MODE_CAPTURED) {
+ if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED) {
RECT clipRect;
GetClientRect(hWnd, &clipRect);
ClientToScreen(hWnd, (POINT*) &clipRect.left);
ClientToScreen(hWnd, (POINT*) &clipRect.right);
ClipCursor(&clipRect);
- SetCapture(hWnd);
center=Point2i(video_mode.width/2,video_mode.height/2);
POINT pos = { (int) center.x, (int) center.y };
ClientToScreen(hWnd, &pos);
- SetCursorPos(pos.x, pos.y);
+ if (mouse_mode==MOUSE_MODE_CAPTURED)
+ SetCursorPos(pos.x, pos.y);
} else {
ReleaseCapture();
ClipCursor(NULL);
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index a5c8ecbe1b..2c8fa64f8e 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -118,6 +118,7 @@ class OS_Windows : public OS {
bool control_mem;
bool meta_mem;
bool force_quit;
+ bool window_has_focus;
uint32_t last_button_state;
CursorShape cursor_shape;
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 41746c2431..38f7233c78 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -295,6 +295,7 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
}
+
ERR_FAIL_COND(!visual_server);
ERR_FAIL_COND(x11_window==0);
@@ -449,6 +450,8 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
physics_2d_server->init();
input = memnew( InputDefault );
+
+ window_has_focus = true; // Set focus to true at init
#ifdef JOYDEV_ENABLED
joypad = memnew( JoypadLinux(input));
#endif
@@ -517,17 +520,21 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) {
if (p_mode==mouse_mode)
return;
- if (mouse_mode==MOUSE_MODE_CAPTURED)
+ if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED)
XUngrabPointer(x11_display, CurrentTime);
- if (mouse_mode!=MOUSE_MODE_VISIBLE && p_mode==MOUSE_MODE_VISIBLE)
- XUndefineCursor(x11_display,x11_window);
- if (p_mode!=MOUSE_MODE_VISIBLE && mouse_mode==MOUSE_MODE_VISIBLE) {
- XDefineCursor(x11_display,x11_window,null_cursor);
+
+ // The only modes that show a cursor are VISIBLE and CONFINED
+ bool showCursor = (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED);
+
+ if (showCursor) {
+ XUndefineCursor(x11_display,x11_window); // show cursor
+ } else {
+ XDefineCursor(x11_display,x11_window,null_cursor); // hide cursor
}
mouse_mode=p_mode;
- if (mouse_mode==MOUSE_MODE_CAPTURED) {
+ if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED) {
while(true) {
//flush pending motion events
@@ -1253,6 +1260,10 @@ void OS_X11::process_xevents() {
do_mouse_warp=false;
+
+ // Is the current mouse mode one where it needs to be grabbed.
+ bool mouse_mode_grab = mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED;
+
while (XPending(x11_display) > 0) {
XEvent event;
XNextEvent(x11_display, &event);
@@ -1271,35 +1282,45 @@ void OS_X11::process_xevents() {
minimized = (visibility->state == VisibilityFullyObscured);
} break;
case LeaveNotify: {
-
- if (main_loop && mouse_mode!=MOUSE_MODE_CAPTURED)
+ if (main_loop && !mouse_mode_grab)
main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT);
if (input)
input->set_mouse_in_window(false);
} break;
case EnterNotify: {
-
- if (main_loop && mouse_mode!=MOUSE_MODE_CAPTURED)
+ if (main_loop && !mouse_mode_grab)
main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
if (input)
input->set_mouse_in_window(true);
} break;
case FocusIn:
minimized = false;
+ window_has_focus = true;
main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
- if (mouse_mode==MOUSE_MODE_CAPTURED) {
+ if (mouse_mode_grab) {
+ // Show and update the cursor if confined and the window regained focus.
+ if (mouse_mode==MOUSE_MODE_CONFINED)
+ XUndefineCursor(x11_display, x11_window);
+ else if (mouse_mode==MOUSE_MODE_CAPTURED) // or re-hide it in captured mode
+ XDefineCursor(x11_display, x11_window, null_cursor);
+
XGrabPointer(
- x11_display, x11_window, True,
+ x11_display, x11_window, True,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync, x11_window, None, CurrentTime);
}
break;
case FocusOut:
+ window_has_focus = false;
main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
- if (mouse_mode==MOUSE_MODE_CAPTURED) {
+ if (mouse_mode_grab) {
//dear X11, I try, I really try, but you never work, you do whathever you want.
+ if (mouse_mode==MOUSE_MODE_CAPTURED) {
+ // Show the cursor if we're in captured mode so it doesn't look weird.
+ XUndefineCursor(x11_display, x11_window);
+ }
XUngrabPointer(x11_display, CurrentTime);
}
break;
@@ -1319,7 +1340,7 @@ void OS_X11::process_xevents() {
/* exit in case of a mouse button press */
last_timestamp=event.xbutton.time;
- if (mouse_mode==MOUSE_MODE_CAPTURED) {
+ if (mouse_mode == MOUSE_MODE_CAPTURED) {
event.xbutton.x=last_mouse_pos.x;
event.xbutton.y=last_mouse_pos.y;
}
@@ -1342,7 +1363,6 @@ void OS_X11::process_xevents() {
mouse_event.mouse_button.pressed=(event.type==ButtonPress);
-
if (event.type==ButtonPress && event.xbutton.button==1) {
uint64_t diff = get_ticks_usec()/1000 - last_click_ms;
@@ -1376,7 +1396,6 @@ void OS_X11::process_xevents() {
// PLEASE DO ME A FAVOR AND DIE DROWNED IN A FECAL
// MOUNTAIN BECAUSE THAT'S WHERE YOU BELONG.
-
while(true) {
if (mouse_mode==MOUSE_MODE_CAPTURED && event.xmotion.x==current_videomode.width/2 && event.xmotion.y==current_videomode.height/2) {
//this is likely the warp event since it was warped here
@@ -1418,7 +1437,7 @@ void OS_X11::process_xevents() {
Point2i new_center = pos;
pos = last_mouse_pos + ( pos - center );
center=new_center;
- do_mouse_warp=true;
+ do_mouse_warp=window_has_focus; // warp the cursor if we're focused in
#else
//Dear X11, thanks for making my life miserable
@@ -1461,8 +1480,11 @@ void OS_X11::process_xevents() {
last_mouse_pos=pos;
// printf("rel: %d,%d\n", rel.x, rel.y );
-
- input->parse_input_event( motion_event);
+ // Don't propagate the motion event unless we have focus
+ // this is so that the relative motion doesn't get messed up
+ // after we regain focus.
+ if (window_has_focus || !mouse_mode_grab)
+ input->parse_input_event( motion_event);
} break;
case KeyPress:
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index 3245df32c6..3ec358f103 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -134,7 +134,7 @@ class OS_X11 : public OS_Unix {
bool force_quit;
bool minimized;
-
+ bool window_has_focus;
bool do_mouse_warp;
const char *cursor_theme;
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp
index 04f096f229..4364e5f1fc 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/scene/2d/collision_polygon_2d.cpp
@@ -243,6 +243,7 @@ void CollisionPolygon2D::set_polygon(const Vector<Point2>& p_polygon) {
_update_parent();
}
update();
+ update_configuration_warning();
}
Vector<Point2> CollisionPolygon2D::get_polygon() const {
diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp
index a92065d6fb..45fc734aef 100644
--- a/scene/2d/collision_shape_2d.cpp
+++ b/scene/2d/collision_shape_2d.cpp
@@ -159,6 +159,7 @@ void CollisionShape2D::set_shape(const Ref<Shape2D>& p_shape) {
if (shape.is_valid())
shape->connect("changed",this,"_shape_changed");
+ update_configuration_warning();
}
Ref<Shape2D> CollisionShape2D::get_shape() const {
diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp
index cd99f30f6d..1051d3f5ff 100644
--- a/scene/2d/particles_2d.cpp
+++ b/scene/2d/particles_2d.cpp
@@ -364,7 +364,7 @@ void Particles2D::_process_particles(float p_delta) {
p.rot=Math::deg2rad(param[PARAM_INITIAL_ANGLE]+param[PARAM_INITIAL_ANGLE]*randomness[PARAM_INITIAL_ANGLE]*_rand_from_seed(&rand_seed));
active_count++;
- p.frame=Math::fmod(param[PARAM_ANIM_INITIAL_POS]+randomness[PARAM_ANIM_INITIAL_POS]*_rand_from_seed(&rand_seed),1.0);
+ p.frame=Math::fmod(param[PARAM_ANIM_INITIAL_POS]+randomness[PARAM_ANIM_INITIAL_POS]*_rand_from_seed(&rand_seed),1.0f);
} else {
@@ -438,7 +438,7 @@ void Particles2D::_process_particles(float p_delta) {
p.pos+=p.velocity*frame_time;
p.rot+=Math::lerp(param[PARAM_SPIN_VELOCITY],param[PARAM_SPIN_VELOCITY]*randomness[PARAM_SPIN_VELOCITY]*_rand_from_seed(&rand_seed),randomness[PARAM_SPIN_VELOCITY])*frame_time;
float anim_spd=param[PARAM_ANIM_SPEED_SCALE]+param[PARAM_ANIM_SPEED_SCALE]*randomness[PARAM_ANIM_SPEED_SCALE]*_rand_from_seed(&rand_seed);
- p.frame=Math::fposmod(p.frame+(frame_time/lifetime)*anim_spd,1.0);
+ p.frame=Math::fposmod(p.frame+(frame_time/lifetime)*anim_spd,1.0f);
active_count++;
@@ -555,7 +555,7 @@ void Particles2D::_notification(int p_what) {
float a=color.a;
//float preh=h;
h+=huerot;
- h=Math::abs(Math::fposmod(h,1.0));
+ h=Math::abs(Math::fposmod(h,1.0f));
//print_line("rand: "+rtos(randomness[PARAM_HUE_VARIATION])+" rand: "+rtos(huerand));
//print_line(itos(i)+":hue: "+rtos(preh)+" + "+rtos(huerot)+" = "+rtos(h));
color.set_hsv(h,s,v);
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index feecbd9e20..96d90a1de6 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -1262,7 +1262,7 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2& p_linear_velocity,const V
//all is a wall
move_and_slide_on_wall=true;
} else {
- if ( get_collision_normal().dot(p_floor_direction) > Math::cos(Math::deg2rad(45))) { //floor
+ if ( get_collision_normal().dot(p_floor_direction) > Math::cos(Math::deg2rad((float)45))) { //floor
move_and_slide_on_floor=true;
@@ -1272,7 +1272,7 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2& p_linear_velocity,const V
revert_motion();
return Vector2();
}
- } else if ( get_collision_normal().dot(p_floor_direction) < Math::cos(Math::deg2rad(45))) { //ceiling
+ } else if ( get_collision_normal().dot(p_floor_direction) < Math::cos(Math::deg2rad((float)45))) { //ceiling
move_and_slide_on_ceiling=true;
} else {
move_and_slide_on_wall=true;
diff --git a/scene/3d/baked_light_instance.cpp b/scene/3d/baked_light_instance.cpp
index 514c73a488..b67b75d48f 100644
--- a/scene/3d/baked_light_instance.cpp
+++ b/scene/3d/baked_light_instance.cpp
@@ -389,8 +389,8 @@ void BakedLight::_plot_face(int p_idx, int p_level, const Vector3 *p_vtx, const
Vector2 uv = get_uv(intersection,p_vtx,p_uv);
- int uv_x = CLAMP(Math::fposmod(uv.x,1.0)*bake_texture_size,0,bake_texture_size-1);
- int uv_y = CLAMP(Math::fposmod(uv.y,1.0)*bake_texture_size,0,bake_texture_size-1);
+ int uv_x = CLAMP(Math::fposmod(uv.x,1.0f)*bake_texture_size,0,bake_texture_size-1);
+ int uv_y = CLAMP(Math::fposmod(uv.y,1.0f)*bake_texture_size,0,bake_texture_size-1);
int ofs = uv_y*bake_texture_size+uv_x;
albedo_accum.r+=p_material.albedo[ofs].r;
@@ -415,8 +415,8 @@ void BakedLight::_plot_face(int p_idx, int p_level, const Vector3 *p_vtx, const
Vector2 uv = get_uv(inters,p_vtx,p_uv);
- int uv_x = CLAMP(Math::fposmod(uv.x,1.0)*bake_texture_size,0,bake_texture_size-1);
- int uv_y = CLAMP(Math::fposmod(uv.y,1.0)*bake_texture_size,0,bake_texture_size-1);
+ int uv_x = CLAMP(Math::fposmod(uv.x,1.0f)*bake_texture_size,0,bake_texture_size-1);
+ int uv_y = CLAMP(Math::fposmod(uv.y,1.0f)*bake_texture_size,0,bake_texture_size-1);
int ofs = uv_y*bake_texture_size+uv_x;
diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp
index 8035ce1cc7..b29ae211de 100644
--- a/scene/3d/gi_probe.cpp
+++ b/scene/3d/gi_probe.cpp
@@ -510,8 +510,8 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V
Vector2 uv = get_uv(intersection,p_vtx,p_uv);
- int uv_x = CLAMP(Math::fposmod(uv.x,1.0)*bake_texture_size,0,bake_texture_size-1);
- int uv_y = CLAMP(Math::fposmod(uv.y,1.0)*bake_texture_size,0,bake_texture_size-1);
+ int uv_x = CLAMP(Math::fposmod(uv.x,1.0f)*bake_texture_size,0,bake_texture_size-1);
+ int uv_y = CLAMP(Math::fposmod(uv.y,1.0f)*bake_texture_size,0,bake_texture_size-1);
int ofs = uv_y*bake_texture_size+uv_x;
albedo_accum.r+=p_material.albedo[ofs].r;
@@ -539,8 +539,8 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V
Vector2 uv = get_uv(inters,p_vtx,p_uv);
- int uv_x = CLAMP(Math::fposmod(uv.x,1.0)*bake_texture_size,0,bake_texture_size-1);
- int uv_y = CLAMP(Math::fposmod(uv.y,1.0)*bake_texture_size,0,bake_texture_size-1);
+ int uv_x = CLAMP(Math::fposmod(uv.x,1.0f)*bake_texture_size,0,bake_texture_size-1);
+ int uv_y = CLAMP(Math::fposmod(uv.y,1.0f)*bake_texture_size,0,bake_texture_size-1);
int ofs = uv_y*bake_texture_size+uv_x;
diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp
index 6843a7e9b3..69706a6039 100644
--- a/scene/3d/spatial.cpp
+++ b/scene/3d/spatial.cpp
@@ -620,7 +620,7 @@ void Spatial::set_visible(bool p_visible) {
bool Spatial::is_visible() const {
- return !data.visible;
+ return data.visible;
}
void Spatial::rotate(const Vector3& p_normal,float p_radians) {
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 7fa8458fe9..e02b2b2b41 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -118,17 +118,20 @@ bool AnimationPlayer::_get(const StringName& p_name,Variant &r_ret) const {
} else if (name=="blend_times") {
- Array array;
-
- array.resize(blend_times.size()*3);
- int idx=0;
+ Vector<BlendKey> keys;
for(Map<BlendKey, float >::Element *E=blend_times.front();E;E=E->next()) {
- array.set(idx*3+0,E->key().from);
- array.set(idx*3+1,E->key().to);
- array.set(idx*3+2,E->get());
- idx++;
+ keys.ordered_insert(E->key());
}
+
+ Array array;
+ for(int i=0;i<keys.size();i++) {
+
+ array.push_back(keys[i].from);
+ array.push_back(keys[i].to);
+ array.push_back(blend_times[keys[i]]);
+ }
+
r_ret=array;
} else if (name=="autoplay") {
r_ret=autoplay;
@@ -476,7 +479,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData* p_anim,float p
}
#endif
- static_cast<Node2D*>(pa->object)->set_rotation(Math::deg2rad(value));
+ static_cast<Node2D*>(pa->object)->set_rotation(Math::deg2rad((double)value));
} break;
case SP_NODE2D_SCALE: {
#ifdef DEBUG_ENABLED
@@ -690,7 +693,7 @@ void AnimationPlayer::_animation_update_transforms() {
}
#endif
- static_cast<Node2D*>(pa->object)->set_rotation(Math::deg2rad(pa->value_accum));
+ static_cast<Node2D*>(pa->object)->set_rotation(Math::deg2rad((double)pa->value_accum));
} break;
case SP_NODE2D_SCALE: {
#ifdef DEBUG_ENABLED
diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h
index 41bae6c928..7fab651213 100644
--- a/scene/animation/animation_player.h
+++ b/scene/animation/animation_player.h
@@ -142,7 +142,7 @@ private:
StringName from;
StringName to;
- bool operator<(const BlendKey& bk) const { return from==bk.from?to<bk.to:from<bk.from; }
+ bool operator<(const BlendKey& bk) const { return from==bk.from?String(to)<String(bk.to):String(from)<String(bk.from); }
};
diff --git a/scene/audio/audio_player.cpp b/scene/audio/audio_player.cpp
new file mode 100644
index 0000000000..9fd005e6fb
--- /dev/null
+++ b/scene/audio/audio_player.cpp
@@ -0,0 +1,301 @@
+#include "audio_player.h"
+
+
+void AudioPlayer::_mix_audio() {
+
+ if (!stream_playback.is_valid()) {
+ return;
+ }
+
+ if (!active) {
+ return;
+ }
+
+ if (setseek>=0.0) {
+ stream_playback->start(setseek);
+ setseek=-1.0; //reset seek
+
+ }
+
+ int bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus);
+
+ //get data
+ AudioFrame *buffer = mix_buffer.ptr();
+ int buffer_size = mix_buffer.size();
+
+ //mix
+ stream_playback->mix(buffer,1.0,buffer_size);
+
+ //multiply volume interpolating to avoid clicks if this changes
+ float vol = Math::db2linear(mix_volume_db);
+ float vol_inc = (Math::db2linear(volume_db) - vol)/float(buffer_size);
+
+ for(int i=0;i<buffer_size;i++) {
+ buffer[i]*=vol;
+ vol+=vol_inc;
+ }
+ //set volume for next mix
+ mix_volume_db = volume_db;
+
+ AudioFrame * targets[3]={NULL,NULL,NULL};
+
+ if (AudioServer::get_singleton()->get_speaker_mode()==AudioServer::SPEAKER_MODE_STEREO) {
+ targets[0] = AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index,0);
+ } else {
+ switch(mix_target) {
+ case MIX_TARGET_STEREO: {
+ targets[0]=AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index,1);
+ } break;
+ case MIX_TARGET_SURROUND: {
+ targets[0]=AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index,1);
+ targets[1]=AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index,2);
+ if (AudioServer::get_singleton()->get_speaker_mode()==AudioServer::SPEAKER_SURROUND_71) {
+ targets[2]=AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index,3);
+ }
+ } break;
+ case MIX_TARGET_CENTER: {
+ targets[0]=AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index,0);
+ } break;
+
+ }
+ }
+
+ for(int c=0;c<3;c++) {
+ if (!targets[c])
+ break;
+ for(int i=0;i<buffer_size;i++) {
+ targets[c][i]+=buffer[i];
+ }
+ }
+
+
+}
+
+void AudioPlayer::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ AudioServer::get_singleton()->add_callback(_mix_audios,this);
+ if (autoplay && !get_tree()->is_editor_hint()) {
+ play();
+ }
+ }
+
+ if (p_what==NOTIFICATION_EXIT_TREE) {
+
+ AudioServer::get_singleton()->remove_callback(_mix_audios,this);
+
+ }
+}
+
+void AudioPlayer::set_stream(Ref<AudioStream> p_stream) {
+
+ AudioServer::get_singleton()->lock();
+
+ mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size());
+
+ if (stream_playback.is_valid()) {
+ stream_playback.unref();
+ stream.unref();
+ active=false;
+ setseek=-1;
+ }
+
+ stream=p_stream;
+ stream_playback=p_stream->instance_playback();
+
+ if (stream_playback.is_null()) {
+ stream.unref();
+ ERR_FAIL_COND(stream_playback.is_null());
+ }
+
+ AudioServer::get_singleton()->unlock();
+
+}
+
+Ref<AudioStream> AudioPlayer::get_stream() const {
+
+ return stream;
+}
+
+void AudioPlayer::set_volume_db(float p_volume) {
+
+ volume_db=p_volume;
+}
+float AudioPlayer::get_volume_db() const {
+
+ return volume_db;
+}
+
+void AudioPlayer::play(float p_from_pos) {
+
+ if (stream_playback.is_valid()) {
+ mix_volume_db=volume_db; //reset volume ramp
+ setseek=p_from_pos;
+ active=true;
+ }
+}
+
+void AudioPlayer::seek(float p_seconds) {
+
+ if (stream_playback.is_valid()) {
+ setseek=p_seconds;
+ }
+}
+
+void AudioPlayer::stop() {
+
+ if (stream_playback.is_valid()) {
+ active=false;
+ }
+
+
+}
+
+bool AudioPlayer::is_playing() const {
+
+ if (stream_playback.is_valid()) {
+ return active && stream_playback->is_playing();
+ }
+
+ return false;
+}
+
+float AudioPlayer::get_pos() {
+
+ if (stream_playback.is_valid()) {
+ return stream_playback->get_pos();
+ }
+
+ return 0;
+}
+
+void AudioPlayer::set_bus(const StringName& p_bus) {
+
+ //if audio is active, must lock this
+ AudioServer::get_singleton()->lock();
+ bus=p_bus;
+ AudioServer::get_singleton()->unlock();
+
+}
+StringName AudioPlayer::get_bus() const {
+
+ for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) {
+ if (AudioServer::get_singleton()->get_bus_name(i)==bus) {
+ return bus;
+ }
+ }
+ return "Master";
+}
+
+void AudioPlayer::set_autoplay(bool p_enable) {
+
+ autoplay=p_enable;
+}
+bool AudioPlayer::is_autoplay_enabled() {
+
+ return autoplay;
+}
+
+void AudioPlayer::set_mix_target(MixTarget p_target) {
+
+ mix_target=p_target;
+}
+
+AudioPlayer::MixTarget AudioPlayer::get_mix_target() const{
+
+ return mix_target;
+}
+
+void AudioPlayer::_set_playing(bool p_enable) {
+
+ if (p_enable)
+ play();
+ else
+ stop();
+}
+bool AudioPlayer::_is_active() const {
+
+ return active;
+}
+
+
+void AudioPlayer::_validate_property(PropertyInfo& property) const {
+
+ if (property.name=="bus") {
+
+ String options;
+ for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) {
+ if (i>0)
+ options+=",";
+ String name = AudioServer::get_singleton()->get_bus_name(i);
+ options+=name;
+ }
+
+ property.hint_string=options;
+ }
+}
+
+void AudioPlayer::_bus_layout_changed() {
+
+ _change_notify();
+}
+
+void AudioPlayer::_bind_methods() {
+
+ ClassDB::bind_method(_MD("set_stream","stream:AudioStream"),&AudioPlayer::set_stream);
+ ClassDB::bind_method(_MD("get_stream"),&AudioPlayer::get_stream);
+
+ ClassDB::bind_method(_MD("set_volume_db","volume_db"),&AudioPlayer::set_volume_db);
+ ClassDB::bind_method(_MD("get_volume_db"),&AudioPlayer::get_volume_db);
+
+ ClassDB::bind_method(_MD("play","from_pos"),&AudioPlayer::play,DEFVAL(0.0));
+ ClassDB::bind_method(_MD("seek","to_pos"),&AudioPlayer::seek);
+ ClassDB::bind_method(_MD("stop"),&AudioPlayer::stop);
+
+ ClassDB::bind_method(_MD("is_playing"),&AudioPlayer::is_playing);
+ ClassDB::bind_method(_MD("get_pos"),&AudioPlayer::get_pos);
+
+ ClassDB::bind_method(_MD("set_bus","bus"),&AudioPlayer::set_bus);
+ ClassDB::bind_method(_MD("get_bus"),&AudioPlayer::get_bus);
+
+ ClassDB::bind_method(_MD("set_autoplay","enable"),&AudioPlayer::set_autoplay);
+ ClassDB::bind_method(_MD("is_autoplay_enabled"),&AudioPlayer::is_autoplay_enabled);
+
+ ClassDB::bind_method(_MD("set_mix_target","mix_target"),&AudioPlayer::set_mix_target);
+ ClassDB::bind_method(_MD("get_mix_target"),&AudioPlayer::get_mix_target);
+
+ ClassDB::bind_method(_MD("_set_playing","enable"),&AudioPlayer::_set_playing);
+ ClassDB::bind_method(_MD("_is_active"),&AudioPlayer::_is_active);
+
+ ClassDB::bind_method(_MD("_bus_layout_changed"),&AudioPlayer::_bus_layout_changed);
+
+
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"stream",PROPERTY_HINT_RESOURCE_TYPE,"AudioStream"),_SCS("set_stream"),_SCS("get_stream") );
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"volume_db",PROPERTY_HINT_RANGE,"-80,24"),_SCS("set_volume_db"),_SCS("get_volume_db") );
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"playing",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR),_SCS("_set_playing"),_SCS("_is_active" ));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"autoplay"),_SCS("set_autoplay"),_SCS("is_autoplay_enabled") );
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"mix_target",PROPERTY_HINT_ENUM,"Stereo,Surround,Center"),_SCS("set_mix_target"),_SCS("get_mix_target"));
+ ADD_PROPERTY( PropertyInfo(Variant::STRING,"bus",PROPERTY_HINT_ENUM,""),_SCS("set_bus"),_SCS("get_bus"));
+
+}
+
+AudioPlayer::AudioPlayer() {
+
+ mix_volume_db=0;
+ volume_db=0;
+ autoplay=false;
+ setseek=-1;
+ active=false;
+ mix_target=MIX_TARGET_STEREO;
+
+ AudioServer::get_singleton()->connect("bus_layout_changed",this,"_bus_layout_changed");
+}
+
+
+
+AudioPlayer::~AudioPlayer() {
+
+
+}
+
diff --git a/scene/audio/audio_player.h b/scene/audio/audio_player.h
new file mode 100644
index 0000000000..249e5d0381
--- /dev/null
+++ b/scene/audio/audio_player.h
@@ -0,0 +1,75 @@
+#ifndef AUDIOPLAYER_H
+#define AUDIOPLAYER_H
+
+#include "scene/main/node.h"
+#include "servers/audio/audio_stream.h"
+
+
+class AudioPlayer : public Node {
+
+ GDCLASS( AudioPlayer, Node )
+
+public:
+
+ enum MixTarget {
+ MIX_TARGET_STEREO,
+ MIX_TARGET_SURROUND,
+ MIX_TARGET_CENTER
+ };
+private:
+ Ref<AudioStreamPlayback> stream_playback;
+ Ref<AudioStream> stream;
+ Vector<AudioFrame> mix_buffer;
+
+ volatile float setseek;
+ volatile bool active;
+
+ float mix_volume_db;
+ float volume_db;
+ bool autoplay;
+ StringName bus;
+
+ MixTarget mix_target;
+
+ void _mix_audio();
+ static void _mix_audios(void *self) { reinterpret_cast<AudioPlayer*>(self)->_mix_audio(); }
+
+ void _set_playing(bool p_enable);
+ bool _is_active() const;
+
+ void _bus_layout_changed();
+
+protected:
+
+ void _validate_property(PropertyInfo& property) const;
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void set_stream(Ref<AudioStream> p_stream);
+ Ref<AudioStream> get_stream() const;
+
+ void set_volume_db(float p_volume);
+ float get_volume_db() const;
+
+ void play(float p_from_pos=0.0);
+ void seek(float p_seconds);
+ void stop();
+ bool is_playing() const;
+ float get_pos();
+
+ void set_bus(const StringName& p_bus);
+ StringName get_bus() const;
+
+ void set_autoplay(bool p_enable);
+ bool is_autoplay_enabled();
+
+ void set_mix_target(MixTarget p_target);
+ MixTarget get_mix_target() const;
+
+ AudioPlayer();
+ ~AudioPlayer();
+};
+
+VARIANT_ENUM_CAST(AudioPlayer::MixTarget)
+#endif // AUDIOPLAYER_H
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index f28595b622..2d1d437668 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -74,17 +74,21 @@ void Button::_notification(int p_what) {
//print_line(get_text()+": "+itos(is_flat())+" hover "+itos(get_draw_mode()));
+ Ref<StyleBox> style = get_stylebox("normal");
+
switch( get_draw_mode() ) {
case DRAW_NORMAL: {
+ style = get_stylebox("normal");
if (!flat)
- get_stylebox("normal" )->draw( ci, Rect2(Point2(0,0), size) );
+ style->draw( ci, Rect2(Point2(0,0), size) );
color=get_color("font_color");
} break;
case DRAW_PRESSED: {
- get_stylebox("pressed" )->draw( ci, Rect2(Point2(0,0), size) );
+ style = get_stylebox("pressed");
+ style->draw( ci, Rect2(Point2(0,0), size) );
if (has_color("font_color_pressed"))
color=get_color("font_color_pressed");
else
@@ -93,13 +97,15 @@ void Button::_notification(int p_what) {
} break;
case DRAW_HOVER: {
- get_stylebox("hover" )->draw( ci, Rect2(Point2(0,0), size) );
+ style = get_stylebox("hover");
+ style->draw( ci, Rect2(Point2(0,0), size) );
color=get_color("font_color_hover");
} break;
case DRAW_DISABLED: {
- get_stylebox("disabled" )->draw( ci, Rect2(Point2(0,0), size) );
+ style = get_stylebox("disabled");
+ style->draw( ci, Rect2(Point2(0,0), size) );
color=get_color("font_color_disabled");
} break;
@@ -111,7 +117,6 @@ void Button::_notification(int p_what) {
style->draw(ci,Rect2(Point2(),size));
}
- Ref<StyleBox> style = get_stylebox("normal" );
Ref<Font> font=get_font("font");
Ref<Texture> _icon;
if (icon.is_null() && has_icon("icon"))
diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp
index d5c1034c9c..5ecafccaca 100644
--- a/scene/gui/range.cpp
+++ b/scene/gui/range.cpp
@@ -141,8 +141,8 @@ void Range::set_as_ratio(double p_value) {
if (shared->exp_ratio && get_min()>0) {
- double exp_min = Math::log(get_min())/Math::log(2);
- double exp_max = Math::log(get_max())/Math::log(2);
+ double exp_min = Math::log(get_min())/Math::log((double)2);
+ double exp_max = Math::log(get_max())/Math::log((double)2);
v = Math::pow(2,exp_min+(exp_max-exp_min)*p_value);
} else {
@@ -160,9 +160,9 @@ double Range::get_as_ratio() const {
if (shared->exp_ratio && get_min()>0) {
- double exp_min = Math::log(get_min())/Math::log(2);
- double exp_max = Math::log(get_max())/Math::log(2);
- double v = Math::log(get_value())/Math::log(2);
+ double exp_min = Math::log(get_min())/Math::log((double)2);
+ double exp_max = Math::log(get_max())/Math::log((double)2);
+ double v = Math::log(get_value())/Math::log((double)2);
return (v - exp_min) / (exp_max - exp_min);
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index ec6be0d19d..8920f8f056 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -162,7 +162,7 @@ void SpinBox::_gui_input(const InputEvent& p_event) {
if (drag.enabled) {
float diff_y = drag.mouse_pos.y - cpos.y;
- diff_y=Math::pow(ABS(diff_y),1.8)*SGN(diff_y);
+ diff_y=Math::pow(ABS(diff_y),1.8f)*SGN(diff_y);
diff_y*=0.1;
drag.mouse_pos=cpos;
diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp
index f6a33b5643..7d8373976b 100644
--- a/scene/gui/texture_progress.cpp
+++ b/scene/gui/texture_progress.cpp
@@ -46,7 +46,9 @@ void TextureProgress::set_over_texture(const Ref<Texture>& p_texture) {
over=p_texture;
update();
- minimum_size_changed();
+ if (under.is_null()) {
+ minimum_size_changed();
+ }
}
Ref<Texture> TextureProgress::get_over_texture() const{
@@ -302,4 +304,5 @@ TextureProgress::TextureProgress()
rad_init_angle=0;
rad_center_off=Point2();
rad_max_degrees=360;
+ set_mouse_filter(MOUSE_FILTER_PASS);
}
diff --git a/scene/gui/texture_rect.cpp b/scene/gui/texture_rect.cpp
index cbb077ef5d..6a4b59c5ec 100644
--- a/scene/gui/texture_rect.cpp
+++ b/scene/gui/texture_rect.cpp
@@ -160,7 +160,7 @@ TextureRect::TextureRect() {
expand=false;
- set_mouse_filter(MOUSE_FILTER_IGNORE);
+ set_mouse_filter(MOUSE_FILTER_PASS);
stretch_mode=STRETCH_SCALE_ON_EXPAND;
}
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 2cfebb7c1e..1a7392f27e 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -943,7 +943,7 @@ void Tree::draw_item_rect(const TreeItem::Cell& p_cell,const Rect2i& p_rect,cons
bmsize.width=p_cell.icon_max_w;
}
- p_cell.draw_icon(ci,rect.pos + Size2i(0,Math::floor((rect.size.y-bmsize.y)/2)),bmsize);
+ p_cell.draw_icon(ci,rect.pos + Size2i(0,Math::floor((real_t)(rect.size.y-bmsize.y)/2)),bmsize);
rect.pos.x+=bmsize.x+cache.hseparation;
rect.size.x-=bmsize.x+cache.hseparation;
@@ -1008,7 +1008,7 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2&
/* Draw label, if height fits */
- bool skip=(p_item==root && hide_root);
+ bool skip=(p_item==root && hide_root);
if (!skip && (p_pos.y+label_h-cache.offset.y)>0) {
@@ -1173,7 +1173,7 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2&
Ref<Texture> checked = cache.checked;
Ref<Texture> unchecked = cache.unchecked;
Point2i check_ofs=item_rect.pos;
- check_ofs.y+=Math::floor((item_rect.size.y-checked->get_height())/2);
+ check_ofs.y+=Math::floor((real_t)(item_rect.size.y-checked->get_height())/2);
if (p_item->cells[i].checked) {
@@ -1711,8 +1711,15 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_
case TreeItem::CELL_MODE_CHECK: {
bring_up_editor=false; //checkboxes are not edited with editor
- p_item->set_checked(col, !c.checked);
- item_edited(col, p_item);
+ if (force_edit_checkbox_only_on_checkbox) {
+ if (x < cache.checked->get_width()) {
+ p_item->set_checked(col, !c.checked);
+ item_edited(col, p_item);
+ }
+ } else {
+ p_item->set_checked(col, !c.checked);
+ item_edited(col, p_item);
+ }
click_handled = true;
//p_item->edited_signal.call(col);
@@ -2321,7 +2328,7 @@ void Tree::_gui_input(InputEvent p_event) {
TreeItem::Cell &c=popup_edited_item->cells[popup_edited_item_col];
float diff_y = -b.relative_y;
- diff_y=Math::pow(ABS(diff_y),1.8)*SGN(diff_y);
+ diff_y=Math::pow(ABS(diff_y),1.8f)*SGN(diff_y);
diff_y*=0.1;
range_drag_base=CLAMP(range_drag_base + c.step * diff_y, c.min, c.max);
popup_edited_item->set_range(popup_edited_item_col,range_drag_base);
@@ -3555,6 +3562,16 @@ bool Tree::get_single_select_cell_editing_only_when_already_selected() const {
return force_select_on_already_selected;
}
+void Tree::set_edit_checkbox_cell_only_when_checkbox_is_pressed(bool p_enable) {
+
+ force_edit_checkbox_only_on_checkbox=p_enable;
+}
+
+bool Tree::get_edit_checkbox_cell_only_when_checkbox_is_pressed() const {
+
+ return force_edit_checkbox_only_on_checkbox;
+}
+
void Tree::set_allow_rmb_select(bool p_allow) {
@@ -3733,6 +3750,7 @@ Tree::Tree() {
force_select_on_already_selected=false;
allow_rmb_select=false;
+ force_edit_checkbox_only_on_checkbox=false;
set_clip_contents(true);
}
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index d715ff4772..351cc4cb50 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -452,6 +452,7 @@ friend class TreeItem;
bool scrolling;
bool force_select_on_already_selected;
+ bool force_edit_checkbox_only_on_checkbox;
bool hide_folding;
@@ -531,6 +532,10 @@ public:
void set_single_select_cell_editing_only_when_already_selected(bool p_enable);
bool get_single_select_cell_editing_only_when_already_selected() const;
+ void set_edit_checkbox_cell_only_when_checkbox_is_pressed(bool p_enable);
+ bool get_edit_checkbox_cell_only_when_checkbox_is_pressed() const;
+
+
void set_allow_rmb_select(bool p_allow);
bool get_allow_rmb_select() const;
diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp
index 907b5a771f..46c0eeca65 100644
--- a/scene/gui/video_player.cpp
+++ b/scene/gui/video_player.cpp
@@ -28,6 +28,7 @@
/*************************************************************************/
#include "video_player.h"
#include "os/os.h"
+#include "servers/audio_server.h"
/*
int VideoPlayer::InternalStream::get_channel_count() const {
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 14acf9583d..989c048682 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -1796,6 +1796,42 @@ Control* Viewport::_gui_find_control_at_pos(CanvasItem* p_node,const Point2& p_g
return NULL;
}
+bool Viewport::_gui_drop(Control *p_at_control,Point2 p_at_pos,bool p_just_check) {
+
+
+ { //attempt grab, try parent controls too
+ CanvasItem *ci=p_at_control;
+ while(ci) {
+
+ Control *control = ci->cast_to<Control>();
+ if (control) {
+
+
+ if (control->can_drop_data(p_at_pos,gui.drag_data)) {
+ if (!p_just_check) {
+ control->drop_data(p_at_pos,gui.drag_data);
+ }
+
+ return true;
+ }
+
+ if (control->data.mouse_filter==Control::MOUSE_FILTER_STOP)
+ break;
+ }
+
+ p_at_pos = ci->get_transform().xform(p_at_pos);
+
+ if (ci->is_set_as_toplevel())
+ break;
+
+ ci=ci->get_parent_item();
+ }
+ }
+
+ return false;
+}
+
+
void Viewport::_gui_input_event(InputEvent p_event) {
@@ -1901,9 +1937,28 @@ void Viewport::_gui_input_event(InputEvent p_event) {
}*/
#endif
- if (gui.mouse_focus->get_focus_mode()!=Control::FOCUS_NONE && gui.mouse_focus!=gui.key_focus && p_event.mouse_button.button_index==BUTTON_LEFT) {
- // also get keyboard focus
- gui.mouse_focus->grab_focus();
+ if (p_event.mouse_button.button_index==BUTTON_LEFT) { //assign focus
+ CanvasItem *ci=gui.mouse_focus;
+ while(ci) {
+
+ Control *control = ci->cast_to<Control>();
+ if (control) {
+ if (control->get_focus_mode()!=Control::FOCUS_NONE) {
+ if (control!=gui.key_focus) {
+ control->grab_focus();
+ }
+ break;
+ }
+
+ if (control->data.mouse_filter==Control::MOUSE_FILTER_STOP)
+ break;
+ }
+
+ if (ci->is_set_as_toplevel())
+ break;
+
+ ci=ci->get_parent_item();
+ }
}
@@ -1918,8 +1973,8 @@ void Viewport::_gui_input_event(InputEvent p_event) {
if (gui.drag_data.get_type()!=Variant::NIL && p_event.mouse_button.button_index==BUTTON_LEFT) {
//alternate drop use (when using force_drag(), as proposed by #5342
- if (gui.mouse_focus && gui.mouse_focus->can_drop_data(pos,gui.drag_data)) {
- gui.mouse_focus->drop_data(pos,gui.drag_data);
+ if (gui.mouse_focus) {
+ _gui_drop(gui.mouse_focus,pos,false);
}
gui.drag_data=Variant();
@@ -1946,9 +2001,9 @@ void Viewport::_gui_input_event(InputEvent p_event) {
if (gui.mouse_over) {
Size2 pos = mpos;
pos = gui.focus_inv_xform.xform(pos);
- if (gui.mouse_over->can_drop_data(pos,gui.drag_data)) {
- gui.mouse_over->drop_data(pos,gui.drag_data);
- }
+
+ _gui_drop(gui.mouse_over,pos,false);
+
}
if (gui.drag_preview && p_event.mouse_button.button_index==BUTTON_LEFT) {
@@ -2009,11 +2064,33 @@ void Viewport::_gui_input_event(InputEvent p_event) {
gui.drag_accum+=Point2(p_event.mouse_motion.relative_x,p_event.mouse_motion.relative_y);
float len = gui.drag_accum.length();
if (len>10) {
- gui.drag_data=gui.mouse_focus->get_drag_data(gui.focus_inv_xform.xform(mpos)-gui.drag_accum);
- if (gui.drag_data.get_type()!=Variant::NIL) {
- gui.mouse_focus=NULL;
+ { //attempt grab, try parent controls too
+ CanvasItem *ci=gui.mouse_focus;
+ while(ci) {
+
+ Control *control = ci->cast_to<Control>();
+ if (control) {
+
+ gui.drag_data=control->get_drag_data(control->get_global_transform_with_canvas().affine_inverse().xform(mpos)-gui.drag_accum);
+ if (gui.drag_data.get_type()!=Variant::NIL) {
+
+ gui.mouse_focus=NULL;
+ }
+
+ if (control->data.mouse_filter==Control::MOUSE_FILTER_STOP)
+ break;
+ }
+
+ if (ci->is_set_as_toplevel())
+ break;
+
+ ci=ci->get_parent_item();
+ }
}
+
+
+
gui.drag_attempted=true;
if (gui.drag_data.get_type()!=Variant::NIL) {
@@ -2140,7 +2217,7 @@ void Viewport::_gui_input_event(InputEvent p_event) {
if (gui.drag_data.get_type()!=Variant::NIL && p_event.mouse_motion.button_mask&BUTTON_MASK_LEFT) {
- bool can_drop = over->can_drop_data(pos,gui.drag_data);
+ bool can_drop = _gui_drop(over,pos,true);
if (!can_drop) {
OS::get_singleton()->set_cursor_shape( OS::CURSOR_FORBIDDEN );
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 2831d177c9..59e34d5c62 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -306,6 +306,8 @@ friend class Control;
Vector2 _get_window_offset() const;
+ bool _gui_drop(Control *p_at_control,Point2 p_at_pos,bool p_just_check);
+
friend class Listener;
void _listener_transform_changed_notify();
void _listener_set(Listener* p_listener);
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 1932f9cbf6..7e8a033c40 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -139,7 +139,7 @@
#include "scene/main/timer.h"
-//#include "scene/audio/stream_player.h"
+#include "scene/audio/audio_player.h"
//#include "scene/audio/event_player.h"
//#include "scene/audio/sound_room_params.h"
#include "scene/resources/sphere_shape.h"
@@ -177,7 +177,7 @@
#include "scene/resources/world_2d.h"
//#include "scene/resources/sample_library.h"
-#include "scene/resources/audio_stream.h"
+//#include "scene/resources/audio_stream.h"
#include "scene/resources/gibberish_stream.h"
#include "scene/resources/bit_mask.h"
#include "scene/resources/color_ramp.h"
@@ -592,10 +592,7 @@ void register_scene_types() {
OS::get_singleton()->yield(); //may take time to init
- ClassDB::register_virtual_class<AudioStream>();
- ClassDB::register_virtual_class<AudioStreamPlayback>();
-//TODO: Adapt to the new AudioStream API or drop (GH-3307)
- //ClassDB::register_type<AudioStreamGibberish>();
+ ClassDB::register_class<AudioPlayer>();
ClassDB::register_virtual_class<VideoStream>();
OS::get_singleton()->yield(); //may take time to init
diff --git a/scene/resources/audio_stream_resampled.h b/scene/resources/audio_stream_resampled.h
index 761643b027..7ceb6cef84 100644
--- a/scene/resources/audio_stream_resampled.h
+++ b/scene/resources/audio_stream_resampled.h
@@ -29,7 +29,7 @@
#ifndef AUDIO_STREAM_RESAMPLED_H
#define AUDIO_STREAM_RESAMPLED_H
-#include "scene/resources/audio_stream.h"
+//#include "scene/resources/audio_stream.h"
#if 0
diff --git a/scene/resources/capsule_shape.cpp b/scene/resources/capsule_shape.cpp
index db83a20f38..23538c1957 100644
--- a/scene/resources/capsule_shape.cpp
+++ b/scene/resources/capsule_shape.cpp
@@ -42,8 +42,8 @@ Vector<Vector3> CapsuleShape::_gen_debug_mesh_lines() {
Vector3 d(0,0,height*0.5);
for(int i=0;i<360;i++) {
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+1);
+ float ra=Math::deg2rad((float)i);
+ float rb=Math::deg2rad((float)i+1);
Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*radius;
Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*radius;
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index e201cb16ac..3392c68e75 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -498,7 +498,7 @@ Vector2 Curve2D::interpolatef(real_t p_findex) const {
else if (p_findex>=points.size())
p_findex=points.size();
- return interpolate((int)p_findex,Math::fmod(p_findex,1.0));
+ return interpolate((int)p_findex,Math::fmod(p_findex,(real_t)1.0));
}
@@ -653,7 +653,7 @@ Vector2 Curve2D::interpolate_baked(float p_offset,bool p_cubic) const{
return r[bpc-1];
int idx = Math::floor((double)p_offset/(double)bake_interval);
- float frac = Math::fmod(p_offset,bake_interval);
+ float frac = Math::fmod(p_offset,(float)bake_interval);
if (idx>=bpc-1) {
return r[bpc-1];
@@ -974,7 +974,7 @@ Vector3 Curve3D::interpolatef(real_t p_findex) const {
else if (p_findex>=points.size())
p_findex=points.size();
- return interpolate((int)p_findex,Math::fmod(p_findex,1.0));
+ return interpolate((int)p_findex,Math::fmod(p_findex,(real_t)1.0));
}
diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h
index 46fd770a27..5b5868ba14 100644
--- a/scene/resources/default_theme/theme_data.h
+++ b/scene/resources/default_theme/theme_data.h
@@ -45,7 +45,7 @@ static const unsigned char button_normal_png[]={
static const unsigned char button_pressed_png[]={
-0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x93,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x31,0x2f,0x37,0x46,0x43,0x4f,0x47,0x44,0x50,0x55,0x52,0x5f,0x55,0x52,0x60,0x3d,0x3a,0x45,0x56,0x52,0x60,0x56,0x52,0x60,0x43,0x40,0x4c,0x42,0x40,0x4b,0x3a,0x38,0x41,0x36,0x34,0x3d,0x44,0x42,0x4e,0x36,0x34,0x3e,0x46,0x42,0x4f,0x38,0x35,0x3f,0x47,0x45,0x50,0x39,0x37,0x40,0x49,0x46,0x53,0x3a,0x38,0x42,0x4a,0x47,0x54,0x3b,0x39,0x43,0x4b,0x49,0x55,0x3c,0x3a,0x44,0x4e,0x4a,0x58,0x3e,0x3b,0x46,0x50,0x4d,0x5a,0x3f,0x3d,0x48,0x3f,0x3d,0x47,0x45,0x42,0x4d,0x41,0x3e,0x49,0x40,0x3e,0x48,0x52,0x4e,0x5c,0x51,0x4e,0x5b,0xff,0xff,0xff,0x32,0xd2,0xb4,0xc,0x0,0x0,0x0,0x16,0x74,0x52,0x4e,0x53,0x4,0xa,0x11,0x19,0x1f,0x22,0x24,0x15,0x25,0x34,0x3f,0x46,0x47,0x48,0x77,0xef,0xef,0xef,0xef,0x77,0xef,0xed,0x6b,0x28,0x52,0x7a,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x30,0xae,0xdc,0x2d,0xe4,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x95,0x49,0x44,0x41,0x54,0x18,0xd3,0x65,0xcf,0xdb,0x12,0x42,0x50,0x14,0x6,0xe0,0xb5,0x8f,0xf6,0x11,0xa5,0x24,0x9,0x49,0x22,0xd2,0xfb,0xbf,0x5d,0x9b,0x31,0xfb,0xa2,0xbe,0xcb,0x7f,0x66,0x1d,0x7e,0x0,0x84,0x9,0x65,0xdc,0x61,0x94,0x60,0x4,0x80,0x2,0x21,0x95,0x36,0xd6,0x1a,0xad,0xa4,0x8,0x10,0x60,0x11,0x46,0xe9,0x69,0x95,0x46,0xa1,0xc0,0x40,0x64,0x9c,0x9d,0x37,0x59,0x2c,0x9,0x50,0x95,0x5f,0xbc,0x5c,0x51,0x60,0xba,0xb8,0x7a,0x85,0x66,0xc0,0x4d,0x59,0x79,0xa5,0xe1,0xc0,0x6d,0x7d,0xf3,0x6a,0xbb,0x4,0xcd,0xdd,0x6b,0x96,0xc0,0xb4,0xf,0xaf,0x75,0x23,0x4c,0x77,0x4f,0xaf,0x73,0x4b,0xa9,0xea,0x87,0xd7,0x66,0xe8,0xdd,0x59,0x22,0x77,0xe3,0xf4,0x5e,0x4d,0xe3,0xde,0x3d,0x86,0x45,0x72,0x98,0x3f,0xab,0xf9,0x98,0xb8,0xd7,0xff,0xca,0xfd,0xd6,0xff,0x2,0x86,0xd,0x15,0x51,0x39,0x7d,0xa8,0x8e,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x7,0x1c,0xc,0x14,0x2b,0xf9,0x77,0x52,0x64,0x0,0x0,0x1,0x92,0x49,0x44,0x41,0x54,0x38,0xcb,0x8d,0x93,0x4d,0x4e,0x1b,0x41,0x10,0x85,0xbf,0xea,0xaa,0x1e,0x20,0x83,0xf9,0x9,0x36,0xb2,0x85,0x72,0x84,0x8,0x65,0x11,0xe5,0xc,0x9c,0x80,0x73,0x10,0xee,0xc1,0x41,0x38,0x1,0xab,0xec,0xa3,0x2c,0x2,0x8a,0xe0,0x2,0x51,0xc2,0x48,0x46,0x42,0x64,0xc6,0x91,0x21,0xf4,0x74,0x16,0x2e,0xb0,0x71,0x2,0xf2,0x93,0x9e,0xba,0x16,0xdd,0xaf,0x5e,0xa9,0x5f,0x9,0x60,0x40,0x1,0x2c,0x1,0xcb,0x5e,0x2b,0x10,0x78,0x8a,0x16,0x48,0xc0,0x1d,0x30,0x6,0x6e,0x81,0x3b,0xf3,0x87,0x25,0xb0,0x9,0xac,0x7b,0xbd,0xc,0x88,0x13,0x20,0x3b,0xc7,0xc0,0x8,0xb8,0x1,0xae,0x81,0x91,0xf9,0xe5,0xad,0x77,0xbb,0x1f,0xf6,0x7b,0xdd,0xfe,0x41,0x4a,0x69,0x2d,0x93,0xf9,0x1f,0x4,0x41,0x55,0x7f,0xd,0xaf,0xaa,0xa3,0xaf,0x67,0x9f,0x8f,0x81,0x64,0xde,0xb1,0xbb,0xdd,0x1b,0x7c,0xac,0x9b,0x9b,0xce,0xd9,0xb7,0x2f,0xfc,0xf3,0x5e,0xa6,0xe5,0xee,0xdb,0xf7,0x6b,0xdb,0xbd,0xc1,0x21,0xf0,0x9,0x18,0x5,0x60,0x5,0xd8,0x48,0x6d,0xdb,0x39,0xbf,0x38,0xc5,0x34,0x62,0x36,0x47,0x9d,0xf2,0xfc,0xe2,0x94,0xd4,0xb6,0x1d,0x60,0x3,0x58,0x31,0x20,0x2,0x65,0x40,0x88,0x31,0x92,0xbd,0xbb,0x8,0xe4,0x3c,0x39,0x67,0x91,0x33,0x84,0x89,0xa5,0x12,0x88,0xf,0x3f,0x10,0x45,0x5,0xb3,0xc8,0x73,0x10,0x11,0xb2,0xab,0x8b,0xa,0xde,0xb8,0x30,0x9f,0xb0,0x8,0xa2,0xc4,0x58,0xb0,0x8,0x82,0x28,0xde,0x58,0xcc,0xff,0x5c,0x45,0x64,0x61,0x1,0x99,0xcc,0xa5,0x80,0x4e,0x5,0xc2,0xcb,0x2,0xe2,0x41,0x10,0x40,0xc2,0x53,0x81,0xc,0xa8,0x8a,0x52,0x2c,0xe8,0x40,0x27,0x23,0x28,0x90,0xcd,0xe3,0x79,0x1b,0x34,0x50,0x14,0x4b,0xf0,0x4c,0x88,0x66,0xbd,0x4,0xd,0x78,0x94,0x93,0x79,0x3c,0x9b,0x18,0x63,0x7a,0xbd,0xb9,0xa5,0xcd,0xa8,0x7e,0xb4,0x3a,0x2f,0x15,0x10,0xca,0x72,0x95,0x18,0x8b,0x4,0x34,0xc0,0xd8,0x80,0x1a,0x18,0x56,0xd5,0xcf,0x93,0x41,0x7f,0x67,0xaf,0xb3,0xba,0x1e,0x5e,0x8a,0xb2,0x99,0xb5,0x97,0xd5,0x8f,0x13,0x60,0x8,0xd4,0x2,0x74,0x9d,0x6f,0x80,0xbe,0x2f,0x55,0xe9,0x26,0xc2,0xcc,0x26,0x66,0x5f,0xa4,0x6b,0xa0,0x2,0xbe,0x3,0x57,0xe6,0x56,0x1e,0x66,0x1a,0x2,0xaf,0x3c,0x24,0x36,0x67,0xe0,0x1e,0xf8,0x3,0xfc,0xf6,0x6d,0xac,0x81,0xe6,0x2f,0x7c,0x22,0x6d,0x74,0x25,0xb,0xb3,0xa2,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
};
@@ -540,12 +540,12 @@ static const unsigned char vslider_bg_png[]={
static const unsigned char vslider_grabber_png[]={
-0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xf8,0x49,0x44,0x41,0x54,0x28,0xcf,0xbd,0x90,0xaf,0x4b,0x43,0x51,0x18,0x86,0x9f,0xf3,0x43,0xcf,0x76,0xae,0xde,0xb9,0xc9,0x1c,0x82,0x86,0xa1,0x16,0x15,0x87,0xc3,0x20,0x68,0x30,0x58,0xb4,0x5a,0x6c,0x62,0x37,0x88,0xff,0x81,0xc5,0xe4,0x5f,0x70,0x8b,0x75,0x45,0xb3,0xc1,0xa6,0x41,0x4,0x19,0xc,0x19,0x18,0x4,0x8d,0xb,0x82,0xdb,0xd8,0x81,0x29,0xf7,0x1e,0x8b,0x6e,0x43,0x30,0xea,0x93,0x5e,0xf8,0x5e,0x5e,0x78,0x3e,0xf8,0x73,0xc4,0x40,0x92,0x18,0x46,0x9,0x18,0xc6,0xd3,0xa1,0x89,0x23,0xee,0x17,0x86,0xc8,0x14,0xa7,0x97,0x57,0x4a,0xdb,0xe1,0xa2,0xc9,0x4b,0xdf,0xac,0x3d,0x9d,0x47,0x15,0x5e,0x89,0x5,0x20,0xb0,0x23,0xc5,0x83,0xc3,0xc2,0xa6,0x99,0xea,0xaa,0xf,0x62,0xc0,0xa0,0x1b,0xf,0x27,0xd1,0x19,0x6d,0x8d,0x66,0x6c,0x75,0x6d,0xf7,0x54,0xcd,0x3a,0x1c,0xc9,0xd7,0x60,0x8c,0x2d,0xcc,0xec,0x70,0x41,0x5b,0x63,0x8e,0xf6,0xe6,0x8f,0xdf,0x82,0x4e,0xef,0x8,0xe0,0xe9,0x92,0x5d,0x22,0x0,0x89,0x48,0x59,0xd4,0xef,0x16,0x8a,0xe4,0xba,0xde,0xaa,0x2e,0x94,0x53,0xb9,0x4,0x8f,0xef,0x29,0xa5,0x71,0x77,0x57,0x15,0x5a,0x8a,0x4,0xf7,0xfc,0x72,0x73,0x39,0xc7,0xf8,0x44,0x90,0x11,0x2,0x24,0x92,0x34,0xba,0xf1,0x18,0xdd,0xdf,0xf2,0xde,0xd7,0xc,0x75,0x7e,0x6b,0x7d,0x63,0x5f,0x4c,0x9a,0x9c,0xfa,0xa1,0xf9,0x8d,0xc4,0x12,0x62,0xd1,0x83,0x8f,0xfa,0x7,0x3e,0x1,0x87,0xd0,0x4a,0x12,0xcf,0xee,0xfb,0xd8,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xb7,0xff,0x88,0x5,0x1d,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe1,0x1,0x12,0x1,0x36,0x8,0x50,0xb9,0xa7,0x53,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xf6,0x49,0x44,0x41,0x54,0x28,0xcf,0xbd,0x90,0xb1,0x4a,0x42,0x51,0x0,0x86,0xbf,0x73,0x8e,0x71,0xe5,0x9a,0x5c,0x41,0xd0,0x66,0x6b,0x33,0x1c,0x7c,0x80,0xa0,0xa5,0x17,0x8,0xa2,0x2d,0x84,0xf0,0x1,0xa2,0x25,0xf1,0x9,0x9a,0x1c,0xda,0x5b,0xb2,0x47,0xa8,0xa5,0xc1,0xa0,0x51,0x88,0xa2,0x29,0xa,0xc1,0x84,0x8,0x43,0xf4,0x96,0x17,0xcf,0xed,0xde,0x73,0x9c,0xcc,0x5c,0xda,0xea,0x9f,0x3f,0xfe,0x9f,0xef,0x87,0x3f,0x8f,0x0,0x40,0xe1,0xe2,0x91,0x42,0x10,0x32,0xe6,0x3,0x8d,0xc1,0xce,0x1,0x45,0xb6,0xba,0xbb,0xba,0xed,0x95,0x8c,0xd0,0x7d,0xff,0xe1,0xee,0xe2,0xb6,0xdd,0x79,0x61,0xc4,0xd7,0xc,0x48,0x57,0x2b,0xeb,0xb5,0x28,0xaf,0x1,0xc5,0x12,0x4e,0xac,0x7b,0x6f,0x57,0x27,0x8d,0xcf,0xe,0x1,0x56,0x1,0xb9,0x9d,0xba,0x28,0x6,0x18,0xc,0x31,0x21,0x5a,0xda,0x4c,0xb6,0xbc,0xb9,0x35,0x7c,0xea,0xbd,0x13,0x4a,0x20,0xe5,0x95,0xf4,0x6c,0x12,0x30,0x84,0xf8,0x44,0x6b,0xfb,0xcd,0x83,0x3d,0x1c,0xf9,0x8b,0x80,0x4a,0xba,0x88,0x4,0x30,0x1e,0xdd,0x3b,0x1b,0xf1,0x77,0x87,0x24,0x81,0x8b,0x79,0x3e,0x3b,0x6a,0x5d,0x33,0x51,0x80,0x2d,0x38,0x2b,0x65,0xb5,0x6c,0x91,0x28,0x92,0xa4,0xad,0xec,0x76,0xcf,0x8f,0xf,0x1f,0xdb,0xc,0x31,0xb,0x9a,0xb1,0xd0,0x3,0xfb,0xda,0x3a,0xbd,0xbc,0x89,0xfa,0xf8,0x73,0xcd,0x9f,0x47,0x45,0x4,0xf8,0x4,0x18,0xfe,0x2f,0x53,0x8,0x62,0x5c,0xcf,0x1f,0x5f,0xcb,0x2c,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
};
static const unsigned char vslider_grabber_hl_png[]={
-0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0xc6,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x17,0x2a,0x29,0x3a,0x69,0x69,0x5b,0xa6,0xa5,0x61,0xb3,0xbc,0x63,0xb7,0xc8,0x65,0xbb,0xca,0x60,0xaf,0xb1,0x48,0x83,0x83,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0xf,0xf,0x55,0x9b,0x9a,0x60,0xb2,0xbd,0x5e,0xb1,0xcd,0x61,0xb3,0xc2,0x0,0x0,0x0,0x27,0x48,0x47,0x62,0xb4,0xbd,0x51,0x93,0x92,0x68,0xc0,0xcf,0x0,0x0,0x0,0x56,0x9d,0x9c,0x68,0xc1,0xcf,0x2d,0x52,0x52,0x63,0xb7,0xbf,0x52,0x96,0x95,0x62,0xb3,0xbf,0x5e,0xb0,0xcd,0x0,0x0,0x0,0x3,0x5,0x5,0x36,0x63,0x63,0x63,0xb4,0xb6,0x60,0xb1,0xbc,0x63,0xb7,0xc7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x55,0xa3,0xc8,0x4f,0x98,0xc4,0x4b,0x93,0xc2,0x4c,0x94,0xc2,0x54,0xa2,0xc8,0x5a,0xab,0xcb,0x4e,0x97,0xc4,0x49,0x8f,0xc0,0x47,0x8c,0xbf,0x48,0x8e,0xc0,0x52,0x9e,0xc6,0x51,0x9d,0xc6,0x5a,0xac,0xcc,0x53,0x9f,0xc7,0x4d,0x96,0xc3,0x4b,0x92,0xc2,0xff,0xff,0xff,0xec,0x37,0x7,0xf6,0x0,0x0,0x0,0x31,0x74,0x52,0x4e,0x53,0x0,0x1,0x3,0xa,0x17,0x22,0x28,0x27,0x1c,0xd,0x5,0x14,0x31,0x65,0xaf,0xdb,0xf0,0xef,0xc1,0x6e,0x16,0xb,0x2c,0x9c,0xe0,0xfc,0xe8,0x4,0x4f,0xdb,0x73,0xf4,0xc,0x7d,0xf7,0x55,0xdc,0x95,0xe0,0xfe,0x13,0x28,0x64,0xc5,0xde,0xf0,0x2,0x1a,0x24,0x77,0x58,0x79,0x88,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x41,0x89,0xde,0x6c,0x4e,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x7d,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x60,0x20,0xf,0x30,0x32,0x31,0xb3,0xb0,0xb2,0xb1,0x73,0x70,0x32,0x41,0xf8,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc,0x2,0x82,0x42,0xc2,0x22,0x20,0x11,0x46,0x51,0x31,0x71,0x9,0x49,0x43,0x23,0x63,0x13,0x53,0x29,0x61,0x4e,0x6,0x6,0x69,0x6e,0x19,0x59,0x33,0x73,0xb,0x4b,0x20,0xb0,0x32,0x15,0xe2,0x60,0x60,0x10,0x95,0x93,0xb7,0x6,0x73,0x81,0xc0,0x44,0x90,0x9d,0x81,0x41,0x41,0x51,0xc9,0x6,0x45,0x40,0x5a,0x44,0x59,0xc5,0x16,0x59,0xb,0x3,0xa3,0x82,0x98,0xaa,0x9a,0xba,0x9d,0xbd,0x3,0xd4,0x50,0x90,0xb5,0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x30,0x6b,0x41,0x40,0x4f,0x41,0xdf,0x0,0xc9,0x61,0x24,0x2,0x0,0x9d,0x96,0x10,0xf9,0x6,0xb2,0x58,0x28,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0xc3,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x17,0x2a,0x29,0x3a,0x69,0x69,0x5b,0xa6,0xa5,0x61,0xb3,0xbc,0x63,0xb7,0xc8,0x65,0xbb,0xca,0x60,0xaf,0xb1,0x48,0x83,0x83,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0xf,0xf,0x55,0x9b,0x9a,0x60,0xb2,0xbd,0x5e,0xb1,0xcd,0x61,0xb3,0xc2,0x0,0x0,0x0,0x27,0x48,0x47,0x62,0xb4,0xbd,0x51,0x93,0x92,0x68,0xc0,0xcf,0x0,0x0,0x0,0x56,0x9d,0x9c,0x68,0xc1,0xcf,0x2d,0x52,0x52,0x63,0xb7,0xbf,0x52,0x96,0x95,0x62,0xb3,0xbf,0x5e,0xb0,0xcd,0x0,0x0,0x0,0x3,0x5,0x5,0x36,0x63,0x63,0x63,0xb4,0xb6,0x60,0xb1,0xbc,0x63,0xb7,0xc7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x55,0xa3,0xc8,0x4f,0x98,0xc4,0x4b,0x93,0xc2,0x4c,0x94,0xc2,0x54,0xa2,0xc8,0x5a,0xab,0xcb,0x4e,0x97,0xc4,0x49,0x8f,0xc0,0x47,0x8c,0xbf,0x48,0x8e,0xc0,0x52,0x9e,0xc6,0x51,0x9d,0xc6,0x5a,0xac,0xcc,0x53,0x9f,0xc7,0x4d,0x96,0xc3,0x4b,0x92,0xc2,0xff,0xff,0xff,0x76,0xbd,0x27,0x7a,0x0,0x0,0x0,0x1,0x74,0x52,0x4e,0x53,0x0,0x40,0xe6,0xd8,0x66,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x0,0x88,0x5,0x1d,0x48,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe1,0x1,0x12,0x1,0x36,0x11,0x34,0xd2,0xf,0x93,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x48,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x60,0xa0,0x12,0x10,0x14,0xe0,0xe7,0xe3,0x45,0xe2,0x4b,0x9a,0x18,0x1b,0x19,0x1a,0x48,0x88,0x8b,0xc1,0xe4,0x4d,0x2c,0x2d,0x80,0xc0,0xdc,0xcc,0x54,0x6,0x22,0x20,0x60,0x6c,0x1,0x1,0xe6,0x56,0x72,0x68,0x2,0xd6,0x8a,0xa8,0x5a,0x6c,0x94,0x11,0x86,0xda,0xdb,0xd9,0xaa,0xa9,0xaa,0x20,0x59,0xab,0xa3,0xad,0xc5,0x40,0x3d,0x0,0x0,0xbf,0x8e,0xc,0xed,0xed,0xc7,0x67,0x72,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
};
diff --git a/scene/resources/default_theme/vslider_grabber.png b/scene/resources/default_theme/vslider_grabber.png
index a61a6a57c9..afc490be45 100644
--- a/scene/resources/default_theme/vslider_grabber.png
+++ b/scene/resources/default_theme/vslider_grabber.png
Binary files differ
diff --git a/scene/resources/default_theme/vslider_grabber_hl.png b/scene/resources/default_theme/vslider_grabber_hl.png
index 548dbbbff8..548972e115 100644
--- a/scene/resources/default_theme/vslider_grabber_hl.png
+++ b/scene/resources/default_theme/vslider_grabber_hl.png
Binary files differ
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 112ecaae2f..e2e79970f9 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -732,7 +732,7 @@ Ref<Texture> FixedSpatialMaterial::get_texture(TextureParam p_param) const {
void FixedSpatialMaterial::_validate_feature(const String& text, Feature feature,PropertyInfo& property) const {
- if (property.name.begins_with(text) && property.name!=text+"/enabled" && !features[feature]) {
+ if (property.name.begins_with(text) && property.name!=text+"_enabled" && !features[feature]) {
property.usage=0;
}
diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp
index a913687e7f..9719f321d6 100644
--- a/scene/resources/scene_format_text.cpp
+++ b/scene/resources/scene_format_text.cpp
@@ -32,7 +32,8 @@
#include "version.h"
#include "os/dir_access.h"
-#define FORMAT_VERSION 1
+//version 2: changed names for basis, rect3, poolvectors, etc.
+#define FORMAT_VERSION 2
#include "version.h"
#include "os/dir_access.h"
@@ -1158,7 +1159,7 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant& p_variant,b
static String _valprop(const String& p_name) {
if (p_name.find("\"")!=-1 || p_name.find("=")!=-1 || p_name.find(" ")!=-1)
- return "\""+p_name.c_escape()+"\"";
+ return "\""+p_name.c_escape_multiline()+"\"";
return p_name;
}
@@ -1360,13 +1361,11 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_re
}
if (groups.size()) {
- String sgroups=" groups=[ ";
+ String sgroups=" groups=[\n";
for(int j=0;j<groups.size();j++) {
- if (j>0)
- sgroups+=", ";
- sgroups+="\""+groups[j].operator String().c_escape()+"\"";
+ sgroups+="\""+String(groups[j]).c_escape()+"\",\n";
}
- sgroups+=" ]";
+ sgroups+="]";
header+=sgroups;
}
diff --git a/scene/resources/sphere_shape.cpp b/scene/resources/sphere_shape.cpp
index bcfb164b4c..c7c4d94aad 100644
--- a/scene/resources/sphere_shape.cpp
+++ b/scene/resources/sphere_shape.cpp
@@ -37,8 +37,8 @@ Vector<Vector3> SphereShape::_gen_debug_mesh_lines() {
for(int i=0;i<=360;i++) {
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+1);
+ float ra=Math::deg2rad((float)i);
+ float rb=Math::deg2rad((float)i+1);
Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
diff --git a/servers/audio/SCsub b/servers/audio/SCsub
index ccc76e823f..afaffcfe93 100644
--- a/servers/audio/SCsub
+++ b/servers/audio/SCsub
@@ -5,3 +5,5 @@ Import('env')
env.add_source_files(env.servers_sources, "*.cpp")
Export('env')
+
+SConscript("effects/SCsub")
diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h
index 2fcd22251b..02eb258f99 100644
--- a/servers/audio/audio_effect.h
+++ b/servers/audio/audio_effect.h
@@ -10,7 +10,7 @@ class AudioEffectInstance : public Reference {
public:
- virtual void process(AudioFrame *p_frames,int p_frame_count)=0;
+ virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count)=0;
};
diff --git a/servers/audio/audio_filter_sw.cpp b/servers/audio/audio_filter_sw.cpp
index cdfe1a29f0..e97eb75d04 100644
--- a/servers/audio/audio_filter_sw.cpp
+++ b/servers/audio/audio_filter_sw.cpp
@@ -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 0f3e2410fd..b711944ca8 100644
--- a/servers/audio/audio_filter_sw.h
+++ b/servers/audio/audio_filter_sw.h
@@ -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_stream.cpp b/servers/audio/audio_stream.cpp
new file mode 100644
index 0000000000..f4214838a1
--- /dev/null
+++ b/servers/audio/audio_stream.cpp
@@ -0,0 +1,86 @@
+/*************************************************************************/
+/* audio_stream.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* 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 */
+/* "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_stream.h"
+
+//////////////////////////////
+
+
+
+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;
+
+ while ( (mix_offset >> FP_BITS) >= INTERNAL_BUFFER_LEN ) {
+
+ 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/scene/resources/audio_stream.h b/servers/audio/audio_stream.h
index b79707cd32..d08fedb084 100644
--- a/scene/resources/audio_stream.h
+++ b/servers/audio/audio_stream.h
@@ -34,47 +34,65 @@
class AudioStreamPlayback : public Reference {
- GDCLASS( AudioStreamPlayback, Reference );
-protected:
- static void _bind_methods();
-public:
+ GDCLASS( AudioStreamPlayback, Reference )
+public:
- virtual void play(float p_from_pos=0)=0;
+ virtual void start(float p_from_pos=0.0)=0;
virtual void stop()=0;
virtual bool is_playing() const=0;
- virtual void set_loop(bool p_enable)=0;
- virtual bool has_loop() const=0;
-
- virtual void set_loop_restart_time(float p_time)=0;
-
- virtual int get_loop_count() const=0;
+ virtual int get_loop_count() const=0; //times it looped
virtual float get_pos() const=0;
virtual void seek_pos(float p_time)=0;
- virtual int mix(int16_t* p_bufer,int p_frames)=0;
+ virtual void mix(AudioFrame* p_bufer,float p_rate_scale,int p_frames)=0;
- virtual float get_length() const=0;
- virtual String get_stream_name() const=0;
+ virtual float get_length() const=0; //if supported, otherwise return 0
- virtual int get_channels() const=0;
- virtual int get_mix_rate() const=0;
- virtual int get_minimum_buffer_size() const=0;
};
-class AudioStream : public Resource {
+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
+ };
- GDCLASS( AudioStream, Resource );
- OBJ_SAVE_TYPE( AudioStream ); //children are all saved as AudioStream, so they can be exchanged
+ AudioFrame internal_buffer[INTERNAL_BUFFER_LEN+CUBIC_INTERP_HISTORY];
+ uint64_t mix_offset;
protected:
- static void _bind_methods();
+ 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;
};
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..d723f8d2fe
--- /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(_MD("set_volume_db","volume"),&AudioEffectAmplify::set_volume_db);
+ ClassDB::bind_method(_MD("get_volume_db"),&AudioEffectAmplify::get_volume_db);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"volume_db",PROPERTY_HINT_RANGE,"-80,24,0.01"),_SCS("set_volume_db"),_SCS("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..d3105343ae
--- /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(_MD("set_voice_count","voices"),&AudioEffectChorus::set_voice_count);
+ ClassDB::bind_method(_MD("get_voice_count"),&AudioEffectChorus::get_voice_count);
+
+
+ ClassDB::bind_method(_MD("set_voice_delay_ms","voice_idx","delay_ms"),&AudioEffectChorus::set_voice_delay_ms);
+ ClassDB::bind_method(_MD("get_voice_delay_ms","voice_idx"),&AudioEffectChorus::get_voice_delay_ms);
+
+ ClassDB::bind_method(_MD("set_voice_rate_hz","voice_idx","rate_hz"),&AudioEffectChorus::set_voice_rate_hz);
+ ClassDB::bind_method(_MD("get_voice_rate_hz","voice_idx"),&AudioEffectChorus::get_voice_rate_hz);
+
+ ClassDB::bind_method(_MD("set_voice_depth_ms","voice_idx","depth_ms"),&AudioEffectChorus::set_voice_depth_ms);
+ ClassDB::bind_method(_MD("get_voice_depth_ms","voice_idx"),&AudioEffectChorus::get_voice_depth_ms);
+
+ ClassDB::bind_method(_MD("set_voice_level_db","voice_idx","level_db"),&AudioEffectChorus::set_voice_level_db);
+ ClassDB::bind_method(_MD("get_voice_level_db","voice_idx"),&AudioEffectChorus::get_voice_level_db);
+
+ ClassDB::bind_method(_MD("set_voice_cutoff_hz","voice_idx","cutoff_hz"),&AudioEffectChorus::set_voice_cutoff_hz);
+ ClassDB::bind_method(_MD("get_voice_cutoff_hz","voice_idx"),&AudioEffectChorus::get_voice_cutoff_hz);
+
+ ClassDB::bind_method(_MD("set_voice_pan","voice_idx","pan"),&AudioEffectChorus::set_voice_pan);
+ ClassDB::bind_method(_MD("get_voice_pan","voice_idx"),&AudioEffectChorus::get_voice_pan);
+
+ ClassDB::bind_method(_MD("set_wet","amount"),&AudioEffectChorus::set_wet);
+ ClassDB::bind_method(_MD("get_wet"),&AudioEffectChorus::get_wet);
+
+ ClassDB::bind_method(_MD("set_dry","amount"),&AudioEffectChorus::set_dry);
+ ClassDB::bind_method(_MD("get_dry"),&AudioEffectChorus::get_dry);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"voice_count",PROPERTY_HINT_RANGE,"1,4,1"),_SCS("set_voice_count"),_SCS("get_voice_count"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"dry",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_dry"),_SCS("get_dry"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"wet",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_wet"),_SCS("get_wet"));
+
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),_SCS("set_voice_delay_ms"),_SCS("get_voice_delay_ms"),0);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),_SCS("set_voice_rate_hz"),_SCS("get_voice_rate_hz"),0);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),_SCS("set_voice_depth_ms"),_SCS("get_voice_depth_ms"),0);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),_SCS("set_voice_level_db"),_SCS("get_voice_level_db"),0);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),_SCS("set_voice_cutoff_hz"),_SCS("get_voice_cutoff_hz"),0);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_voice_pan"),_SCS("get_voice_pan"),0);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),_SCS("set_voice_delay_ms"),_SCS("get_voice_delay_ms"),1);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),_SCS("set_voice_rate_hz"),_SCS("get_voice_rate_hz"),1);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),_SCS("set_voice_depth_ms"),_SCS("get_voice_depth_ms"),1);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),_SCS("set_voice_level_db"),_SCS("get_voice_level_db"),1);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),_SCS("set_voice_cutoff_hz"),_SCS("get_voice_cutoff_hz"),1);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_voice_pan"),_SCS("get_voice_pan"),1);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),_SCS("set_voice_delay_ms"),_SCS("get_voice_delay_ms"),2);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),_SCS("set_voice_rate_hz"),_SCS("get_voice_rate_hz"),2);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),_SCS("set_voice_depth_ms"),_SCS("get_voice_depth_ms"),2);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),_SCS("set_voice_level_db"),_SCS("get_voice_level_db"),2);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),_SCS("set_voice_cutoff_hz"),_SCS("get_voice_cutoff_hz"),2);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_voice_pan"),_SCS("get_voice_pan"),2);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),_SCS("set_voice_delay_ms"),_SCS("get_voice_delay_ms"),3);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),_SCS("set_voice_rate_hz"),_SCS("get_voice_rate_hz"),3);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),_SCS("set_voice_depth_ms"),_SCS("get_voice_depth_ms"),3);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),_SCS("set_voice_level_db"),_SCS("get_voice_level_db"),3);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),_SCS("set_voice_cutoff_hz"),_SCS("get_voice_cutoff_hz"),3);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_voice_pan"),_SCS("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..5d116a9543
--- /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(_MD("set_treshold","treshold"),&AudioEffectCompressor::set_treshold);
+ ClassDB::bind_method(_MD("get_treshold"),&AudioEffectCompressor::get_treshold);
+
+ ClassDB::bind_method(_MD("set_ratio","ratio"),&AudioEffectCompressor::set_ratio);
+ ClassDB::bind_method(_MD("get_ratio"),&AudioEffectCompressor::get_ratio);
+
+ ClassDB::bind_method(_MD("set_gain","gain"),&AudioEffectCompressor::set_gain);
+ ClassDB::bind_method(_MD("get_gain"),&AudioEffectCompressor::get_gain);
+
+ ClassDB::bind_method(_MD("set_attack_us","attack_us"),&AudioEffectCompressor::set_attack_us);
+ ClassDB::bind_method(_MD("get_attack_us"),&AudioEffectCompressor::get_attack_us);
+
+ ClassDB::bind_method(_MD("set_release_ms","release_ms"),&AudioEffectCompressor::set_release_ms);
+ ClassDB::bind_method(_MD("get_release_ms"),&AudioEffectCompressor::get_release_ms);
+
+ ClassDB::bind_method(_MD("set_mix","mix"),&AudioEffectCompressor::set_mix);
+ ClassDB::bind_method(_MD("get_mix"),&AudioEffectCompressor::get_mix);
+
+ ClassDB::bind_method(_MD("set_sidechain","sidechain"),&AudioEffectCompressor::set_sidechain);
+ ClassDB::bind_method(_MD("get_sidechain"),&AudioEffectCompressor::get_sidechain);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"treshold",PROPERTY_HINT_RANGE,"-60,0,0.1"),_SCS("set_treshold"),_SCS("get_treshold"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"ratio",PROPERTY_HINT_RANGE,"1,48,0.1"),_SCS("set_ratio"),_SCS("get_ratio"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"gain",PROPERTY_HINT_RANGE,"-20,20,0.1"),_SCS("set_gain"),_SCS("get_gain"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"attack_us",PROPERTY_HINT_RANGE,"20,2000,1"),_SCS("set_attack_us"),_SCS("get_attack_us"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"release_ms",PROPERTY_HINT_RANGE,"20,2000,1"),_SCS("set_release_ms"),_SCS("get_release_ms"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"mix",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_mix"),_SCS("get_mix"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"sidechain",PROPERTY_HINT_ENUM),_SCS("set_sidechain"),_SCS("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..aae2657a63
--- /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(_MD("set_dry","amount"),&AudioEffectDelay::set_dry);
+ ClassDB::bind_method(_MD("get_dry"),&AudioEffectDelay::get_dry);
+
+ ClassDB::bind_method(_MD("set_tap1_active","amount"),&AudioEffectDelay::set_tap1_active);
+ ClassDB::bind_method(_MD("is_tap1_active"),&AudioEffectDelay::is_tap1_active);
+
+ ClassDB::bind_method(_MD("set_tap1_delay_ms","amount"),&AudioEffectDelay::set_tap1_delay_ms);
+ ClassDB::bind_method(_MD("get_tap1_delay_ms"),&AudioEffectDelay::get_tap1_delay_ms);
+
+ ClassDB::bind_method(_MD("set_tap1_level_db","amount"),&AudioEffectDelay::set_tap1_level_db);
+ ClassDB::bind_method(_MD("get_tap1_level_db"),&AudioEffectDelay::get_tap1_level_db);
+
+ ClassDB::bind_method(_MD("set_tap1_pan","amount"),&AudioEffectDelay::set_tap1_pan);
+ ClassDB::bind_method(_MD("get_tap1_pan"),&AudioEffectDelay::get_tap1_pan);
+
+ ClassDB::bind_method(_MD("set_tap2_active","amount"),&AudioEffectDelay::set_tap2_active);
+ ClassDB::bind_method(_MD("is_tap2_active"),&AudioEffectDelay::is_tap2_active);
+
+ ClassDB::bind_method(_MD("set_tap2_delay_ms","amount"),&AudioEffectDelay::set_tap2_delay_ms);
+ ClassDB::bind_method(_MD("get_tap2_delay_ms"),&AudioEffectDelay::get_tap2_delay_ms);
+
+ ClassDB::bind_method(_MD("set_tap2_level_db","amount"),&AudioEffectDelay::set_tap2_level_db);
+ ClassDB::bind_method(_MD("get_tap2_level_db"),&AudioEffectDelay::get_tap2_level_db);
+
+ ClassDB::bind_method(_MD("set_tap2_pan","amount"),&AudioEffectDelay::set_tap2_pan);
+ ClassDB::bind_method(_MD("get_tap2_pan"),&AudioEffectDelay::get_tap2_pan);
+
+
+ ClassDB::bind_method(_MD("set_feedback_active","amount"),&AudioEffectDelay::set_feedback_active);
+ ClassDB::bind_method(_MD("is_feedback_active"),&AudioEffectDelay::is_feedback_active);
+
+ ClassDB::bind_method(_MD("set_feedback_delay_ms","amount"),&AudioEffectDelay::set_feedback_delay_ms);
+ ClassDB::bind_method(_MD("get_feedback_delay_ms"),&AudioEffectDelay::get_feedback_delay_ms);
+
+ ClassDB::bind_method(_MD("set_feedback_level_db","amount"),&AudioEffectDelay::set_feedback_level_db);
+ ClassDB::bind_method(_MD("get_feedback_level_db"),&AudioEffectDelay::get_feedback_level_db);
+
+ ClassDB::bind_method(_MD("set_feedback_lowpass","amount"),&AudioEffectDelay::set_feedback_lowpass);
+ ClassDB::bind_method(_MD("get_feedback_lowpass"),&AudioEffectDelay::get_feedback_lowpass);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"dry",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_dry"),_SCS("get_dry"));
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"tap1/active"),_SCS("set_tap1_active"),_SCS("is_tap1_active"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap1/delay_ms",PROPERTY_HINT_RANGE,"0,1500,1"),_SCS("set_tap1_delay_ms"),_SCS("get_tap1_delay_ms"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap1/level_db",PROPERTY_HINT_RANGE,"-60,0,0.01"),_SCS("set_tap1_level_db"),_SCS("get_tap1_level_db"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap1/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_tap1_pan"),_SCS("get_tap1_pan"));
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"tap2/active"),_SCS("set_tap2_active"),_SCS("is_tap2_active"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap2/delay_ms",PROPERTY_HINT_RANGE,"0,1500,1"),_SCS("set_tap2_delay_ms"),_SCS("get_tap2_delay_ms"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap2/level_db",PROPERTY_HINT_RANGE,"-60,0,0.01"),_SCS("set_tap2_level_db"),_SCS("get_tap2_level_db"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap2/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_tap2_pan"),_SCS("get_tap2_pan"));
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"feedback/active"),_SCS("set_feedback_active"),_SCS("is_feedback_active"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback/delay_ms",PROPERTY_HINT_RANGE,"0,1500,1"),_SCS("set_feedback_delay_ms"),_SCS("get_feedback_delay_ms"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback/level_db",PROPERTY_HINT_RANGE,"-60,0,0.01"),_SCS("set_feedback_level_db"),_SCS("get_feedback_level_db"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback/lowpass",PROPERTY_HINT_RANGE,"1,16000,1"),_SCS("set_feedback_lowpass"),_SCS("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..3ba409b0a5
--- /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(_MD("set_mode","mode"),&AudioEffectDistortion::set_mode);
+ ClassDB::bind_method(_MD("get_mode"),&AudioEffectDistortion::get_mode);
+
+ ClassDB::bind_method(_MD("set_pre_gain","pre_gain"),&AudioEffectDistortion::set_pre_gain);
+ ClassDB::bind_method(_MD("get_pre_gain"),&AudioEffectDistortion::get_pre_gain);
+
+ ClassDB::bind_method(_MD("set_keep_hf_hz","keep_hf_hz"),&AudioEffectDistortion::set_keep_hf_hz);
+ ClassDB::bind_method(_MD("get_keep_hf_hz"),&AudioEffectDistortion::get_keep_hf_hz);
+
+ ClassDB::bind_method(_MD("set_drive","drive"),&AudioEffectDistortion::set_drive);
+ ClassDB::bind_method(_MD("get_drive"),&AudioEffectDistortion::get_drive);
+
+
+ ClassDB::bind_method(_MD("set_post_gain","post_gain"),&AudioEffectDistortion::set_post_gain);
+ ClassDB::bind_method(_MD("get_post_gain"),&AudioEffectDistortion::get_post_gain);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Clip,ATan,LoFi,Overdrive,WaveShape"),_SCS("set_mode"),_SCS("get_mode"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"pre_gain",PROPERTY_HINT_RANGE,"-60,60,0.01"),_SCS("set_pre_gain"),_SCS("get_pre_gain"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"keep_hf_hz",PROPERTY_HINT_RANGE,"1,20000,1"),_SCS("set_keep_hf_hz"),_SCS("get_keep_hf_hz"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"drive",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_drive"),_SCS("get_drive"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"post_gain",PROPERTY_HINT_RANGE,"-80,24,0.01"),_SCS("set_post_gain"),_SCS("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..3c6a684224
--- /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(_MD("set_band_gain_db","band_idx","volume_db"),&AudioEffectEQ::set_band_gain_db);
+ ClassDB::bind_method(_MD("get_band_gain_db","band_idx"),&AudioEffectEQ::get_band_gain_db);
+ ClassDB::bind_method(_MD("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..4e54ea1f3e
--- /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(_MD("set_cutoff","freq"),&AudioEffectFilter::set_cutoff);
+ ClassDB::bind_method(_MD("get_cutoff"),&AudioEffectFilter::get_cutoff);
+
+ ClassDB::bind_method(_MD("set_resonance","amount"),&AudioEffectFilter::set_resonance);
+ ClassDB::bind_method(_MD("get_resonance"),&AudioEffectFilter::get_resonance);
+
+ ClassDB::bind_method(_MD("set_gain","amount"),&AudioEffectFilter::set_gain);
+ ClassDB::bind_method(_MD("get_gain"),&AudioEffectFilter::get_gain);
+
+ ClassDB::bind_method(_MD("set_db","amount"),&AudioEffectFilter::set_db);
+ ClassDB::bind_method(_MD("get_db"),&AudioEffectFilter::get_db);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"cutoff_hz",PROPERTY_HINT_RANGE,"1,40000,0.1"),_SCS("set_cutoff"),_SCS("get_cutoff"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"resonance",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_resonance"),_SCS("get_resonance"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"gain",PROPERTY_HINT_RANGE,"0,4,0.01"),_SCS("set_gain"),_SCS("get_gain"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"dB",PROPERTY_HINT_ENUM,"6db,12db,18db,24db"),_SCS("set_db"),_SCS("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..5cd02682ab
--- /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(_MD("set_ceiling_db","ceiling"),&AudioEffectLimiter::set_ceiling_db);
+ ClassDB::bind_method(_MD("get_ceiling_db"),&AudioEffectLimiter::get_ceiling_db);
+
+ ClassDB::bind_method(_MD("set_treshold_db","treshold"),&AudioEffectLimiter::set_treshold_db);
+ ClassDB::bind_method(_MD("get_treshold_db"),&AudioEffectLimiter::get_treshold_db);
+
+ ClassDB::bind_method(_MD("set_soft_clip_db","soft_clip"),&AudioEffectLimiter::set_soft_clip_db);
+ ClassDB::bind_method(_MD("get_soft_clip_db"),&AudioEffectLimiter::get_soft_clip_db);
+
+ ClassDB::bind_method(_MD("set_soft_clip_ratio","soft_clip"),&AudioEffectLimiter::set_soft_clip_ratio);
+ ClassDB::bind_method(_MD("get_soft_clip_ratio"),&AudioEffectLimiter::get_soft_clip_ratio);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"ceiling_db",PROPERTY_HINT_RANGE,"-20,-0.1,0.1"),_SCS("set_ceiling_db"),_SCS("get_ceiling_db"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"treshold_db",PROPERTY_HINT_RANGE,"-30,0,0.1"),_SCS("set_treshold_db"),_SCS("get_treshold_db"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"soft_clip_db",PROPERTY_HINT_RANGE,"0,6,0.1"),_SCS("set_soft_clip_db"),_SCS("get_soft_clip_db"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"soft_clip_ratio",PROPERTY_HINT_RANGE,"3,20,0.1"),_SCS("set_soft_clip_ratio"),_SCS("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..e296b0d998
--- /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(_MD("set_pan","cpanume"),&AudioEffectPanner::set_pan);
+ ClassDB::bind_method(_MD("get_pan"),&AudioEffectPanner::get_pan);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_pan"),_SCS("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..bfce608603
--- /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(_MD("set_range_min_hz","hz"),&AudioEffectPhaser::set_range_min_hz);
+ ClassDB::bind_method(_MD("get_range_min_hz"),&AudioEffectPhaser::get_range_min_hz);
+
+ ClassDB::bind_method(_MD("set_range_max_hz","hz"),&AudioEffectPhaser::set_range_max_hz);
+ ClassDB::bind_method(_MD("get_range_max_hz"),&AudioEffectPhaser::get_range_max_hz);
+
+ ClassDB::bind_method(_MD("set_rate_hz","hz"),&AudioEffectPhaser::set_rate_hz);
+ ClassDB::bind_method(_MD("get_rate_hz"),&AudioEffectPhaser::get_rate_hz);
+
+ ClassDB::bind_method(_MD("set_feedback","fbk"),&AudioEffectPhaser::set_feedback);
+ ClassDB::bind_method(_MD("get_feedback"),&AudioEffectPhaser::get_feedback);
+
+ ClassDB::bind_method(_MD("set_depth","depth"),&AudioEffectPhaser::set_depth);
+ ClassDB::bind_method(_MD("get_depth"),&AudioEffectPhaser::get_depth);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"range_min_hz",PROPERTY_HINT_RANGE,"10,10000"),_SCS("set_range_min_hz"),_SCS("get_range_min_hz"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"range_max_hz",PROPERTY_HINT_RANGE,"10,10000"),_SCS("set_range_max_hz"),_SCS("get_range_max_hz"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"rate_hz",PROPERTY_HINT_RANGE,"0.01,20"),_SCS("set_rate_hz"),_SCS("get_rate_hz"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback",PROPERTY_HINT_RANGE,"0.1,0.9,0.1"),_SCS("set_feedback"),_SCS("get_feedback"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"depth",PROPERTY_HINT_RANGE,"0.1,4,0.1"),_SCS("set_depth"),_SCS("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..49a14cda04
--- /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(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(_MD("set_pitch_scale","rate"),&AudioEffectPitchShift::set_pitch_scale);
+ ClassDB::bind_method(_MD("get_pitch_scale"),&AudioEffectPitchShift::get_pitch_scale);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"pitch_scale",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_pitch_scale"),_SCS("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..749814fd76
--- /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(_MD("set_predelay_msec","msec"),&AudioEffectReverb::set_predelay_msec);
+ ClassDB::bind_method(_MD("get_predelay_msec"),&AudioEffectReverb::get_predelay_msec);
+
+ ClassDB::bind_method(_MD("set_predelay_feedback","feedback"),&AudioEffectReverb::set_predelay_feedback);
+ ClassDB::bind_method(_MD("get_predelay_feedback"),&AudioEffectReverb::get_predelay_feedback);
+
+ ClassDB::bind_method(_MD("set_room_size","size"),&AudioEffectReverb::set_room_size);
+ ClassDB::bind_method(_MD("get_room_size"),&AudioEffectReverb::get_room_size);
+
+ ClassDB::bind_method(_MD("set_damping","amount"),&AudioEffectReverb::set_damping);
+ ClassDB::bind_method(_MD("get_damping"),&AudioEffectReverb::get_damping);
+
+ ClassDB::bind_method(_MD("set_spread","amount"),&AudioEffectReverb::set_spread);
+ ClassDB::bind_method(_MD("get_spread"),&AudioEffectReverb::get_spread);
+
+ ClassDB::bind_method(_MD("set_dry","amount"),&AudioEffectReverb::set_dry);
+ ClassDB::bind_method(_MD("get_dry"),&AudioEffectReverb::get_dry);
+
+ ClassDB::bind_method(_MD("set_wet","amount"),&AudioEffectReverb::set_wet);
+ ClassDB::bind_method(_MD("get_wet"),&AudioEffectReverb::get_wet);
+
+ ClassDB::bind_method(_MD("set_hpf","amount"),&AudioEffectReverb::set_hpf);
+ ClassDB::bind_method(_MD("get_hpf"),&AudioEffectReverb::get_hpf);
+
+
+ ADD_GROUP("Predelay","predelay_");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"predelay_msec",PROPERTY_HINT_RANGE,"20,500,1"),_SCS("set_predelay_msec"),_SCS("get_predelay_msec"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"predelay_feedback",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_predelay_msec"),_SCS("get_predelay_msec"));
+ ADD_GROUP("","");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"room_size",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_room_size"),_SCS("get_room_size"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"damping",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_damping"),_SCS("get_damping"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"spread",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_spread"),_SCS("get_spread"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"hipass",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_hpf"),_SCS("get_hpf"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"dry",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_dry"),_SCS("get_dry"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"wet",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_wet"),_SCS("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..c5968aa772
--- /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(_MD("set_pan_pullout","amount"),&AudioEffectStereoEnhance::set_pan_pullout);
+ ClassDB::bind_method(_MD("get_pan_pullout"),&AudioEffectStereoEnhance::get_pan_pullout);
+
+ ClassDB::bind_method(_MD("set_time_pullout","amount"),&AudioEffectStereoEnhance::set_time_pullout);
+ ClassDB::bind_method(_MD("get_time_pullout"),&AudioEffectStereoEnhance::get_time_pullout);
+
+ ClassDB::bind_method(_MD("set_surround","amount"),&AudioEffectStereoEnhance::set_surround);
+ ClassDB::bind_method(_MD("get_surround"),&AudioEffectStereoEnhance::get_surround);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"pan_pullout",PROPERTY_HINT_RANGE,"0,4,0.01"),_SCS("set_pan_pullout"),_SCS("get_pan_pullout"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"time_pullout_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),_SCS("set_time_pullout"),_SCS("get_time_pullout"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"surround",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_surround"),_SCS("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..a6499a66b4
--- /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_server.cpp b/servers/audio_server.cpp
index 9b938a7f86..8a8b9ebf76 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -29,6 +29,19 @@
#include "audio_server.h"
#include "globals.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
+
+#define MARK_EDITED set_edited(true);
+
+#else
+
+#define MARK_EDITED
+
+#endif
+
AudioDriver *AudioDriver::singleton=NULL;
AudioDriver *AudioDriver::get_singleton() {
@@ -42,12 +55,16 @@ void AudioDriver::set_singleton() {
void AudioDriver::audio_server_process(int p_frames,int32_t *p_buffer,bool p_update_mix_time) {
- AudioServer * audio_server = static_cast<AudioServer*>(AudioServer::get_singleton());
+
if (p_update_mix_time)
update_mix_time(p_frames);
-// audio_server->driver_process(p_frames,p_buffer);
+
+ 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;
@@ -74,7 +91,6 @@ AudioDriver *AudioDriverManager::drivers[MAX_DRIVERS];
int AudioDriverManager::driver_count=0;
-
void AudioDriverManager::add_driver(AudioDriver *p_driver) {
ERR_FAIL_COND(driver_count>=MAX_DRIVERS);
@@ -97,62 +113,548 @@ AudioDriver *AudioDriverManager::get_driver(int p_driver) {
//////////////////////////////////////////////
//////////////////////////////////////////////
+void AudioServer::_driver_process(int p_frames,int32_t* p_buffer) {
+
+ int todo=p_frames;
+
+ while(todo) {
+
+ if (to_mix==0) {
+ _mix_step();
+ }
+
+ int to_copy = MIN(to_mix,todo);
+
+ Bus *master = buses[0];
+
+ int from = buffer_size-to_mix;
+ int from_buf=p_frames-todo;
+
+ //master master, send to output
+ int cs = master->channels.size();
+ for(int k=0;k<cs;k++) {
+
+ 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;
+ }
+ }
+
+ }
+
+ 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");
}
-int AudioServer::get_bus_count() const {
- return buses.size();
+void AudioServer::remove_bus(int p_index) {
+
+ ERR_FAIL_INDEX(p_index,buses.size());
+ ERR_FAIL_COND(p_index==0);
+
+ MARK_EDITED
+
+ lock();
+ bus_map.erase(buses[p_index]->name);
+ memdelete(buses[p_index]);
+ buses.remove(p_index);
+ unlock();
}
-void AudioServer::set_bus_mode(int p_bus,BusMode p_mode) {
+void AudioServer::add_bus(int p_at_pos) {
- ERR_FAIL_INDEX(p_bus,buses.size());
+ 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);
}
-AudioServer::BusMode AudioServer::get_bus_mode(int p_bus) const {
- ERR_FAIL_INDEX_V(p_bus,buses.size(),BUS_MODE_STEREO);
+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;
- return buses[p_bus].mode;
+ 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());
- buses[p_bus].name=p_name;
+ 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;
+ 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());
- buses[p_bus].volume_db=p_volume_db;
+
+ 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;
+ 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;
@@ -160,12 +662,14 @@ void AudioServer::add_bus_effect(int p_bus,const Ref<AudioEffect>& p_effect,int
//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);
+ 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);
+ buses[p_bus]->effects.insert(p_at_pos,fx);
}
+ _update_bus_effects(p_bus);
+
unlock();
}
@@ -174,9 +678,13 @@ 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);
+ buses[p_bus]->effects.remove(p_effect);
+ _update_bus_effects(p_bus);
unlock();
}
@@ -185,52 +693,131 @@ int AudioServer::get_bus_effect_count(int p_bus) {
ERR_FAIL_INDEX_V(p_bus,buses.size(),0);
- return buses[p_bus].effects.size();
+ 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>());
+ ERR_FAIL_INDEX_V(p_effect,buses[p_bus]->effects.size(),Ref<AudioEffect>());
- return buses[p_bus].effects[p_effect].effect;
+ 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());
+ 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] );
+ 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());
- buses[p_bus].effects[p_effect].enabled=p_enabled;
+ 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;
+ 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;
+ }
+
+ 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");
+
+
+ if (AudioDriver::get_singleton())
+ AudioDriver::get_singleton()->start();
+#ifdef TOOLS_ENABLED
+ set_edited(false); //avoid editors from thinking this was edited
+#endif
+
+}
+
+void AudioServer::load_default_bus_layout() {
+
+ 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);
+ }
+ }
+
}
+
void AudioServer::finish() {
+ for(int i=0;i<buses.size();i++) {
+ memdelete(buses[i]);
+ }
+
buses.clear();
}
void AudioServer::update() {
@@ -282,18 +869,353 @@ double AudioServer::get_output_delay() const {
AudioServer* AudioServer::singleton=NULL;
-void AudioServer::_bind_methods() {
+
+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(_MD("set_bus_count","amount"),&AudioServer::set_bus_count);
+ ClassDB::bind_method(_MD("get_bus_count"),&AudioServer::get_bus_count);
+
+ ClassDB::bind_method(_MD("remove_bus","index"),&AudioServer::remove_bus);
+ ClassDB::bind_method(_MD("add_bus","at_pos"),&AudioServer::add_bus,DEFVAL(-1));
+ ClassDB::bind_method(_MD("move_bus","index","to_index"),&AudioServer::move_bus);
+
+ ClassDB::bind_method(_MD("set_bus_name","bus_idx","name"),&AudioServer::set_bus_name);
+ ClassDB::bind_method(_MD("get_bus_name","bus_idx"),&AudioServer::get_bus_name);
+
+ ClassDB::bind_method(_MD("set_bus_volume_db","bus_idx","volume_db"),&AudioServer::set_bus_volume_db);
+ ClassDB::bind_method(_MD("get_bus_volume_db","bus_idx"),&AudioServer::get_bus_volume_db);
+
+ ClassDB::bind_method(_MD("set_bus_send","bus_idx","send"),&AudioServer::set_bus_send);
+ ClassDB::bind_method(_MD("get_bus_send","bus_idx"),&AudioServer::get_bus_send);
+
+ ClassDB::bind_method(_MD("set_bus_solo","bus_idx","enable"),&AudioServer::set_bus_solo);
+ ClassDB::bind_method(_MD("is_bus_solo","bus_idx"),&AudioServer::is_bus_solo);
+
+ ClassDB::bind_method(_MD("set_bus_mute","bus_idx","enable"),&AudioServer::set_bus_mute);
+ ClassDB::bind_method(_MD("is_bus_mute","bus_idx"),&AudioServer::is_bus_mute);
+
+ ClassDB::bind_method(_MD("set_bus_bypass_effects","bus_idx","enable"),&AudioServer::set_bus_bypass_effects);
+ ClassDB::bind_method(_MD("is_bus_bypassing_effects","bus_idx"),&AudioServer::is_bus_bypassing_effects);
+
+ ClassDB::bind_method(_MD("add_bus_effect","bus_idx","effect:AudioEffect"),&AudioServer::add_bus_effect,DEFVAL(-1));
+ ClassDB::bind_method(_MD("remove_bus_effect","bus_idx","effect_idx"),&AudioServer::remove_bus_effect);
+
+ ClassDB::bind_method(_MD("get_bus_effect_count","bus_idx"),&AudioServer::add_bus_effect);
+ ClassDB::bind_method(_MD("get_bus_effect:AudioEffect","bus_idx","effect_idx"),&AudioServer::get_bus_effect);
+ ClassDB::bind_method(_MD("swap_bus_effects","bus_idx","effect_idx","by_effect_idx"),&AudioServer::swap_bus_effects);
+
+ ClassDB::bind_method(_MD("set_bus_effect_enabled","bus_idx","effect_idx","enabled"),&AudioServer::set_bus_effect_enabled);
+ ClassDB::bind_method(_MD("is_bus_effect_enabled","bus_idx","effect_idx"),&AudioServer::is_bus_effect_enabled);
+
+ ClassDB::bind_method(_MD("get_bus_peak_volume_left_db","bus_idx","channel"),&AudioServer::get_bus_peak_volume_left_db);
+ ClassDB::bind_method(_MD("get_bus_peak_volume_right_db","bus_idx","channel"),&AudioServer::get_bus_peak_volume_right_db);
+
+ ClassDB::bind_method(_MD("lock"),&AudioServer::lock);
+ ClassDB::bind_method(_MD("unlock"),&AudioServer::unlock);
+
+ ClassDB::bind_method(_MD("get_speaker_mode"),&AudioServer::get_speaker_mode);
+ ClassDB::bind_method(_MD("get_mix_rate"),&AudioServer::get_mix_rate);
+
+ ClassDB::bind_method(_MD("set_state","state:AudioServerState"),&AudioServer::set_bus_layout);
+ ClassDB::bind_method(_MD("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 77aca39760..88849bb591 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -100,56 +100,131 @@ public:
};
+class AudioBusLayout;
+
class AudioServer : public Object {
GDCLASS( AudioServer, Object )
public:
- enum BusMode {
- BUS_MODE_STEREO,
- BUS_MODE_SURROUND
- };
-
//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
+ };
+
+ typedef void (*AudioCallback)(void* p_userdata);
+
private:
uint32_t buffer_size;
+ uint64_t mix_count;
+ uint64_t mix_frames;
+
+ float channel_disable_treshold_db;
+ uint32_t channel_disable_frames;
+
+ int to_mix;
struct Bus {
- String name;
- BusMode mode;
- Vector<AudioFrame> buffer;
+ StringName name;
+ bool solo;
+ bool mute;
+ bool bypass;
+
+ //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;
+
struct Effect {
Ref<AudioEffect> effect;
- Ref<AudioEffectInstance> instance;
bool enabled;
};
Vector<Effect> effects;
-
float volume_db;
+ StringName send;
+ int index_cache;
};
- Vector<Bus> buses;
+ Vector< Vector<AudioFrame> >temp_buffer; //temp_buffer for each level
+ Vector<Bus*> buses;
+ Map<StringName,Bus*> bus_map;
+ _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;
+
+ }
+ ERR_FAIL_V(1);
+ }
+
+
+ void _update_bus_effects(int p_bus);
- static void _bind_methods();
static AudioServer* singleton;
+
+ // TODO create an audiodata pool to optimize memory
+
+
+ Map<void*,uint32_t> audio_data;
+ size_t audio_data_total_mem;
+ size_t audio_data_max_mem;
+
+ Mutex *audio_data_lock;
+
+ void _mix_step();
+
+ struct CallbackItem {
+
+ AudioCallback callback;
+ void *userdata;
+
+ bool operator<(const CallbackItem& p_item) const {
+ return (callback==p_item.callback ? userdata < p_item.userdata : callback < p_item.callback);
+ }
+ };
+
+ Set<CallbackItem> callbacks;
+
+friend class AudioDriver;
+ void _driver_process(int p_frames, int32_t *p_buffer);
+protected:
+
+ static void _bind_methods();
public:
+ //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);
+
void set_bus_count(int p_count);
int get_bus_count() const;
- void set_bus_mode(int p_bus,BusMode p_mode);
- BusMode get_bus_mode(int p_bus) const;
+ void remove_bus(int p_index);
+ void add_bus(int p_at_pos=-1);
+
+ void move_bus(int p_bus,int p_to_pos);
void set_bus_name(int p_bus,const String& p_name);
String get_bus_name(int p_bus) const;
@@ -157,6 +232,19 @@ public:
void set_bus_volume_db(int p_bus,float p_volume_db);
float get_bus_volume_db(int p_bus) const;
+
+ void set_bus_send(int p_bus,const StringName& p_send);
+ StringName get_bus_send(int p_bus) const;
+
+ 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);
@@ -168,9 +256,15 @@ public:
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 */
@@ -188,13 +282,74 @@ public:
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::BusMode )
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;
diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.cpp b/servers/physics_2d/broad_phase_2d_hash_grid.cpp
index d2b37319ad..8b7a410b3d 100644
--- a/servers/physics_2d/broad_phase_2d_hash_grid.cpp
+++ b/servers/physics_2d/broad_phase_2d_hash_grid.cpp
@@ -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);
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 8b831f4ff6..01f8ffa504 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -35,6 +35,21 @@
#include "physics_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) {
@@ -67,6 +82,42 @@ void register_server_types() {
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>();
diff --git a/thirdparty/stb_vorbis/stb_vorbis.c b/thirdparty/stb_vorbis/stb_vorbis.c
new file mode 100644
index 0000000000..c4f24d5898
--- /dev/null
+++ b/thirdparty/stb_vorbis/stb_vorbis.c
@@ -0,0 +1,5399 @@
+// Ogg Vorbis audio decoder - v1.09 - public domain
+// http://nothings.org/stb_vorbis/
+//
+// Original version written by Sean Barrett in 2007.
+//
+// Originally sponsored by RAD Game Tools. Seeking sponsored
+// by Phillip Bennefall, Marc Andersen, Aaron Baker, Elias Software,
+// Aras Pranckevicius, and Sean Barrett.
+//
+// LICENSE
+//
+// This software is dual-licensed to the public domain and under the following
+// license: you are granted a perpetual, irrevocable license to copy, modify,
+// publish, and distribute this file as you see fit.
+//
+// No warranty for any purpose is expressed or implied by the author (nor
+// by RAD Game Tools). Report bugs and send enhancements to the author.
+//
+// Limitations:
+//
+// - floor 0 not supported (used in old ogg vorbis files pre-2004)
+// - lossless sample-truncation at beginning ignored
+// - cannot concatenate multiple vorbis streams
+// - sample positions are 32-bit, limiting seekable 192Khz
+// files to around 6 hours (Ogg supports 64-bit)
+//
+// Feature contributors:
+// Dougall Johnson (sample-exact seeking)
+//
+// Bugfix/warning contributors:
+// Terje Mathisen Niklas Frykholm Andy Hill
+// Casey Muratori John Bolton Gargaj
+// Laurent Gomila Marc LeBlanc Ronny Chevalier
+// Bernhard Wodo Evan Balster alxprd@github
+// Tom Beaumont Ingo Leitgeb Nicolas Guillemot
+// Phillip Bennefall Rohit Thiago Goulart
+// manxorist@github saga musix
+//
+// Partial history:
+// 1.09 - 2016/04/04 - back out 'truncation of last frame' fix from previous version
+// 1.08 - 2016/04/02 - warnings; setup memory leaks; truncation of last frame
+// 1.07 - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const
+// 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson)
+// some crash fixes when out of memory or with corrupt files
+// fix some inappropriately signed shifts
+// 1.05 - 2015/04/19 - don't define __forceinline if it's redundant
+// 1.04 - 2014/08/27 - fix missing const-correct case in API
+// 1.03 - 2014/08/07 - warning fixes
+// 1.02 - 2014/07/09 - declare qsort comparison as explicitly _cdecl in Windows
+// 1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float (interleaved was correct)
+// 1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in >2-channel;
+// (API change) report sample rate for decode-full-file funcs
+//
+// See end of file for full version history.
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// HEADER BEGINS HERE
+//
+
+#ifndef STB_VORBIS_INCLUDE_STB_VORBIS_H
+#define STB_VORBIS_INCLUDE_STB_VORBIS_H
+
+#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO)
+#define STB_VORBIS_NO_STDIO 1
+#endif
+
+#ifndef STB_VORBIS_NO_STDIO
+#include <stdio.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/////////// THREAD SAFETY
+
+// Individual stb_vorbis* handles are not thread-safe; you cannot decode from
+// them from multiple threads at the same time. However, you can have multiple
+// stb_vorbis* handles and decode from them independently in multiple thrads.
+
+
+/////////// MEMORY ALLOCATION
+
+// normally stb_vorbis uses malloc() to allocate memory at startup,
+// and alloca() to allocate temporary memory during a frame on the
+// stack. (Memory consumption will depend on the amount of setup
+// data in the file and how you set the compile flags for speed
+// vs. size. In my test files the maximal-size usage is ~150KB.)
+//
+// You can modify the wrapper functions in the source (setup_malloc,
+// setup_temp_malloc, temp_malloc) to change this behavior, or you
+// can use a simpler allocation model: you pass in a buffer from
+// which stb_vorbis will allocate _all_ its memory (including the
+// temp memory). "open" may fail with a VORBIS_outofmem if you
+// do not pass in enough data; there is no way to determine how
+// much you do need except to succeed (at which point you can
+// query get_info to find the exact amount required. yes I know
+// this is lame).
+//
+// If you pass in a non-NULL buffer of the type below, allocation
+// will occur from it as described above. Otherwise just pass NULL
+// to use malloc()/alloca()
+
+typedef struct
+{
+ char *alloc_buffer;
+ int alloc_buffer_length_in_bytes;
+} stb_vorbis_alloc;
+
+
+/////////// FUNCTIONS USEABLE WITH ALL INPUT MODES
+
+typedef struct stb_vorbis stb_vorbis;
+
+typedef struct
+{
+ unsigned int sample_rate;
+ int channels;
+
+ unsigned int setup_memory_required;
+ unsigned int setup_temp_memory_required;
+ unsigned int temp_memory_required;
+
+ int max_frame_size;
+} stb_vorbis_info;
+
+// get general information about the file
+extern stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f);
+
+// get the last error detected (clears it, too)
+extern int stb_vorbis_get_error(stb_vorbis *f);
+
+// close an ogg vorbis file and free all memory in use
+extern void stb_vorbis_close(stb_vorbis *f);
+
+// this function returns the offset (in samples) from the beginning of the
+// file that will be returned by the next decode, if it is known, or -1
+// otherwise. after a flush_pushdata() call, this may take a while before
+// it becomes valid again.
+// NOT WORKING YET after a seek with PULLDATA API
+extern int stb_vorbis_get_sample_offset(stb_vorbis *f);
+
+// returns the current seek point within the file, or offset from the beginning
+// of the memory buffer. In pushdata mode it returns 0.
+extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f);
+
+/////////// PUSHDATA API
+
+#ifndef STB_VORBIS_NO_PUSHDATA_API
+
+// this API allows you to get blocks of data from any source and hand
+// them to stb_vorbis. you have to buffer them; stb_vorbis will tell
+// you how much it used, and you have to give it the rest next time;
+// and stb_vorbis may not have enough data to work with and you will
+// need to give it the same data again PLUS more. Note that the Vorbis
+// specification does not bound the size of an individual frame.
+
+extern stb_vorbis *stb_vorbis_open_pushdata(
+ const unsigned char * datablock, int datablock_length_in_bytes,
+ int *datablock_memory_consumed_in_bytes,
+ int *error,
+ const stb_vorbis_alloc *alloc_buffer);
+// create a vorbis decoder by passing in the initial data block containing
+// the ogg&vorbis headers (you don't need to do parse them, just provide
+// the first N bytes of the file--you're told if it's not enough, see below)
+// on success, returns an stb_vorbis *, does not set error, returns the amount of
+// data parsed/consumed on this call in *datablock_memory_consumed_in_bytes;
+// on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed
+// if returns NULL and *error is VORBIS_need_more_data, then the input block was
+// incomplete and you need to pass in a larger block from the start of the file
+
+extern int stb_vorbis_decode_frame_pushdata(
+ stb_vorbis *f,
+ const unsigned char *datablock, int datablock_length_in_bytes,
+ int *channels, // place to write number of float * buffers
+ float ***output, // place to write float ** array of float * buffers
+ int *samples // place to write number of output samples
+ );
+// decode a frame of audio sample data if possible from the passed-in data block
+//
+// return value: number of bytes we used from datablock
+//
+// possible cases:
+// 0 bytes used, 0 samples output (need more data)
+// N bytes used, 0 samples output (resynching the stream, keep going)
+// N bytes used, M samples output (one frame of data)
+// note that after opening a file, you will ALWAYS get one N-bytes,0-sample
+// frame, because Vorbis always "discards" the first frame.
+//
+// Note that on resynch, stb_vorbis will rarely consume all of the buffer,
+// instead only datablock_length_in_bytes-3 or less. This is because it wants
+// to avoid missing parts of a page header if they cross a datablock boundary,
+// without writing state-machiney code to record a partial detection.
+//
+// The number of channels returned are stored in *channels (which can be
+// NULL--it is always the same as the number of channels reported by
+// get_info). *output will contain an array of float* buffers, one per
+// channel. In other words, (*output)[0][0] contains the first sample from
+// the first channel, and (*output)[1][0] contains the first sample from
+// the second channel.
+
+extern void stb_vorbis_flush_pushdata(stb_vorbis *f);
+// inform stb_vorbis that your next datablock will not be contiguous with
+// previous ones (e.g. you've seeked in the data); future attempts to decode
+// frames will cause stb_vorbis to resynchronize (as noted above), and
+// once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it
+// will begin decoding the _next_ frame.
+//
+// if you want to seek using pushdata, you need to seek in your file, then
+// call stb_vorbis_flush_pushdata(), then start calling decoding, then once
+// decoding is returning you data, call stb_vorbis_get_sample_offset, and
+// if you don't like the result, seek your file again and repeat.
+#endif
+
+
+////////// PULLING INPUT API
+
+#ifndef STB_VORBIS_NO_PULLDATA_API
+// This API assumes stb_vorbis is allowed to pull data from a source--
+// either a block of memory containing the _entire_ vorbis stream, or a
+// FILE * that you or it create, or possibly some other reading mechanism
+// if you go modify the source to replace the FILE * case with some kind
+// of callback to your code. (But if you don't support seeking, you may
+// just want to go ahead and use pushdata.)
+
+#if !defined(STB_VORBIS_NO_STDIO) && !defined(STB_VORBIS_NO_INTEGER_CONVERSION)
+extern int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output);
+#endif
+#if !defined(STB_VORBIS_NO_INTEGER_CONVERSION)
+extern int stb_vorbis_decode_memory(const unsigned char *mem, int len, int *channels, int *sample_rate, short **output);
+#endif
+// decode an entire file and output the data interleaved into a malloc()ed
+// buffer stored in *output. The return value is the number of samples
+// decoded, or -1 if the file could not be opened or was not an ogg vorbis file.
+// When you're done with it, just free() the pointer returned in *output.
+
+extern stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len,
+ int *error, const stb_vorbis_alloc *alloc_buffer);
+// create an ogg vorbis decoder from an ogg vorbis stream in memory (note
+// this must be the entire stream!). on failure, returns NULL and sets *error
+
+#ifndef STB_VORBIS_NO_STDIO
+extern stb_vorbis * stb_vorbis_open_filename(const char *filename,
+ int *error, const stb_vorbis_alloc *alloc_buffer);
+// create an ogg vorbis decoder from a filename via fopen(). on failure,
+// returns NULL and sets *error (possibly to VORBIS_file_open_failure).
+
+extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,
+ int *error, const stb_vorbis_alloc *alloc_buffer);
+// create an ogg vorbis decoder from an open FILE *, looking for a stream at
+// the _current_ seek point (ftell). on failure, returns NULL and sets *error.
+// note that stb_vorbis must "own" this stream; if you seek it in between
+// calls to stb_vorbis, it will become confused. Morever, if you attempt to
+// perform stb_vorbis_seek_*() operations on this file, it will assume it
+// owns the _entire_ rest of the file after the start point. Use the next
+// function, stb_vorbis_open_file_section(), to limit it.
+
+extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close,
+ int *error, const stb_vorbis_alloc *alloc_buffer, unsigned int len);
+// create an ogg vorbis decoder from an open FILE *, looking for a stream at
+// the _current_ seek point (ftell); the stream will be of length 'len' bytes.
+// on failure, returns NULL and sets *error. note that stb_vorbis must "own"
+// this stream; if you seek it in between calls to stb_vorbis, it will become
+// confused.
+#endif
+
+extern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number);
+extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number);
+// these functions seek in the Vorbis file to (approximately) 'sample_number'.
+// after calling seek_frame(), the next call to get_frame_*() will include
+// the specified sample. after calling stb_vorbis_seek(), the next call to
+// stb_vorbis_get_samples_* will start with the specified sample. If you
+// do not need to seek to EXACTLY the target sample when using get_samples_*,
+// you can also use seek_frame().
+
+extern void stb_vorbis_seek_start(stb_vorbis *f);
+// this function is equivalent to stb_vorbis_seek(f,0)
+
+extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f);
+extern float stb_vorbis_stream_length_in_seconds(stb_vorbis *f);
+// these functions return the total length of the vorbis stream
+
+extern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output);
+// decode the next frame and return the number of samples. the number of
+// channels returned are stored in *channels (which can be NULL--it is always
+// the same as the number of channels reported by get_info). *output will
+// contain an array of float* buffers, one per channel. These outputs will
+// be overwritten on the next call to stb_vorbis_get_frame_*.
+//
+// You generally should not intermix calls to stb_vorbis_get_frame_*()
+// and stb_vorbis_get_samples_*(), since the latter calls the former.
+
+#ifndef STB_VORBIS_NO_INTEGER_CONVERSION
+extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts);
+extern int stb_vorbis_get_frame_short (stb_vorbis *f, int num_c, short **buffer, int num_samples);
+#endif
+// decode the next frame and return the number of *samples* per channel.
+// Note that for interleaved data, you pass in the number of shorts (the
+// size of your array), but the return value is the number of samples per
+// channel, not the total number of samples.
+//
+// The data is coerced to the number of channels you request according to the
+// channel coercion rules (see below). You must pass in the size of your
+// buffer(s) so that stb_vorbis will not overwrite the end of the buffer.
+// The maximum buffer size needed can be gotten from get_info(); however,
+// the Vorbis I specification implies an absolute maximum of 4096 samples
+// per channel.
+
+// Channel coercion rules:
+// Let M be the number of channels requested, and N the number of channels present,
+// and Cn be the nth channel; let stereo L be the sum of all L and center channels,
+// and stereo R be the sum of all R and center channels (channel assignment from the
+// vorbis spec).
+// M N output
+// 1 k sum(Ck) for all k
+// 2 * stereo L, stereo R
+// k l k > l, the first l channels, then 0s
+// k l k <= l, the first k channels
+// Note that this is not _good_ surround etc. mixing at all! It's just so
+// you get something useful.
+
+extern int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats);
+extern int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples);
+// gets num_samples samples, not necessarily on a frame boundary--this requires
+// buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES.
+// Returns the number of samples stored per channel; it may be less than requested
+// at the end of the file. If there are no more samples in the file, returns 0.
+
+#ifndef STB_VORBIS_NO_INTEGER_CONVERSION
+extern int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts);
+extern int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int num_samples);
+#endif
+// gets num_samples samples, not necessarily on a frame boundary--this requires
+// buffering so you have to supply the buffers. Applies the coercion rules above
+// to produce 'channels' channels. Returns the number of samples stored per channel;
+// it may be less than requested at the end of the file. If there are no more
+// samples in the file, returns 0.
+
+#endif
+
+//////// ERROR CODES
+
+enum STBVorbisError
+{
+ VORBIS__no_error,
+
+ VORBIS_need_more_data=1, // not a real error
+
+ VORBIS_invalid_api_mixing, // can't mix API modes
+ VORBIS_outofmem, // not enough memory
+ VORBIS_feature_not_supported, // uses floor 0
+ VORBIS_too_many_channels, // STB_VORBIS_MAX_CHANNELS is too small
+ VORBIS_file_open_failure, // fopen() failed
+ VORBIS_seek_without_length, // can't seek in unknown-length file
+
+ VORBIS_unexpected_eof=10, // file is truncated?
+ VORBIS_seek_invalid, // seek past EOF
+
+ // decoding errors (corrupt/invalid stream) -- you probably
+ // don't care about the exact details of these
+
+ // vorbis errors:
+ VORBIS_invalid_setup=20,
+ VORBIS_invalid_stream,
+
+ // ogg errors:
+ VORBIS_missing_capture_pattern=30,
+ VORBIS_invalid_stream_structure_version,
+ VORBIS_continued_packet_flag_invalid,
+ VORBIS_incorrect_stream_serial_number,
+ VORBIS_invalid_first_page,
+ VORBIS_bad_packet_type,
+ VORBIS_cant_find_last_page,
+ VORBIS_seek_failed
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // STB_VORBIS_INCLUDE_STB_VORBIS_H
+//
+// HEADER ENDS HERE
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef STB_VORBIS_HEADER_ONLY
+
+// global configuration settings (e.g. set these in the project/makefile),
+// or just set them in this file at the top (although ideally the first few
+// should be visible when the header file is compiled too, although it's not
+// crucial)
+
+// STB_VORBIS_NO_PUSHDATA_API
+// does not compile the code for the various stb_vorbis_*_pushdata()
+// functions
+// #define STB_VORBIS_NO_PUSHDATA_API
+
+// STB_VORBIS_NO_PULLDATA_API
+// does not compile the code for the non-pushdata APIs
+// #define STB_VORBIS_NO_PULLDATA_API
+
+// STB_VORBIS_NO_STDIO
+// does not compile the code for the APIs that use FILE *s internally
+// or externally (implied by STB_VORBIS_NO_PULLDATA_API)
+// #define STB_VORBIS_NO_STDIO
+
+// STB_VORBIS_NO_INTEGER_CONVERSION
+// does not compile the code for converting audio sample data from
+// float to integer (implied by STB_VORBIS_NO_PULLDATA_API)
+// #define STB_VORBIS_NO_INTEGER_CONVERSION
+
+// STB_VORBIS_NO_FAST_SCALED_FLOAT
+// does not use a fast float-to-int trick to accelerate float-to-int on
+// most platforms which requires endianness be defined correctly.
+//#define STB_VORBIS_NO_FAST_SCALED_FLOAT
+
+
+// STB_VORBIS_MAX_CHANNELS [number]
+// globally define this to the maximum number of channels you need.
+// The spec does not put a restriction on channels except that
+// the count is stored in a byte, so 255 is the hard limit.
+// Reducing this saves about 16 bytes per value, so using 16 saves
+// (255-16)*16 or around 4KB. Plus anything other memory usage
+// I forgot to account for. Can probably go as low as 8 (7.1 audio),
+// 6 (5.1 audio), or 2 (stereo only).
+#ifndef STB_VORBIS_MAX_CHANNELS
+#define STB_VORBIS_MAX_CHANNELS 16 // enough for anyone?
+#endif
+
+// STB_VORBIS_PUSHDATA_CRC_COUNT [number]
+// after a flush_pushdata(), stb_vorbis begins scanning for the
+// next valid page, without backtracking. when it finds something
+// that looks like a page, it streams through it and verifies its
+// CRC32. Should that validation fail, it keeps scanning. But it's
+// possible that _while_ streaming through to check the CRC32 of
+// one candidate page, it sees another candidate page. This #define
+// determines how many "overlapping" candidate pages it can search
+// at once. Note that "real" pages are typically ~4KB to ~8KB, whereas
+// garbage pages could be as big as 64KB, but probably average ~16KB.
+// So don't hose ourselves by scanning an apparent 64KB page and
+// missing a ton of real ones in the interim; so minimum of 2
+#ifndef STB_VORBIS_PUSHDATA_CRC_COUNT
+#define STB_VORBIS_PUSHDATA_CRC_COUNT 4
+#endif
+
+// STB_VORBIS_FAST_HUFFMAN_LENGTH [number]
+// sets the log size of the huffman-acceleration table. Maximum
+// supported value is 24. with larger numbers, more decodings are O(1),
+// but the table size is larger so worse cache missing, so you'll have
+// to probe (and try multiple ogg vorbis files) to find the sweet spot.
+#ifndef STB_VORBIS_FAST_HUFFMAN_LENGTH
+#define STB_VORBIS_FAST_HUFFMAN_LENGTH 10
+#endif
+
+// STB_VORBIS_FAST_BINARY_LENGTH [number]
+// sets the log size of the binary-search acceleration table. this
+// is used in similar fashion to the fast-huffman size to set initial
+// parameters for the binary search
+
+// STB_VORBIS_FAST_HUFFMAN_INT
+// The fast huffman tables are much more efficient if they can be
+// stored as 16-bit results instead of 32-bit results. This restricts
+// the codebooks to having only 65535 possible outcomes, though.
+// (At least, accelerated by the huffman table.)
+#ifndef STB_VORBIS_FAST_HUFFMAN_INT
+#define STB_VORBIS_FAST_HUFFMAN_SHORT
+#endif
+
+// STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH
+// If the 'fast huffman' search doesn't succeed, then stb_vorbis falls
+// back on binary searching for the correct one. This requires storing
+// extra tables with the huffman codes in sorted order. Defining this
+// symbol trades off space for speed by forcing a linear search in the
+// non-fast case, except for "sparse" codebooks.
+// #define STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH
+
+// STB_VORBIS_DIVIDES_IN_RESIDUE
+// stb_vorbis precomputes the result of the scalar residue decoding
+// that would otherwise require a divide per chunk. you can trade off
+// space for time by defining this symbol.
+// #define STB_VORBIS_DIVIDES_IN_RESIDUE
+
+// STB_VORBIS_DIVIDES_IN_CODEBOOK
+// vorbis VQ codebooks can be encoded two ways: with every case explicitly
+// stored, or with all elements being chosen from a small range of values,
+// and all values possible in all elements. By default, stb_vorbis expands
+// this latter kind out to look like the former kind for ease of decoding,
+// because otherwise an integer divide-per-vector-element is required to
+// unpack the index. If you define STB_VORBIS_DIVIDES_IN_CODEBOOK, you can
+// trade off storage for speed.
+//#define STB_VORBIS_DIVIDES_IN_CODEBOOK
+
+#ifdef STB_VORBIS_CODEBOOK_SHORTS
+#error "STB_VORBIS_CODEBOOK_SHORTS is no longer supported as it produced incorrect results for some input formats"
+#endif
+
+// STB_VORBIS_DIVIDE_TABLE
+// this replaces small integer divides in the floor decode loop with
+// table lookups. made less than 1% difference, so disabled by default.
+
+// STB_VORBIS_NO_INLINE_DECODE
+// disables the inlining of the scalar codebook fast-huffman decode.
+// might save a little codespace; useful for debugging
+// #define STB_VORBIS_NO_INLINE_DECODE
+
+// STB_VORBIS_NO_DEFER_FLOOR
+// Normally we only decode the floor without synthesizing the actual
+// full curve. We can instead synthesize the curve immediately. This
+// requires more memory and is very likely slower, so I don't think
+// you'd ever want to do it except for debugging.
+// #define STB_VORBIS_NO_DEFER_FLOOR
+
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+#ifdef STB_VORBIS_NO_PULLDATA_API
+ #define STB_VORBIS_NO_INTEGER_CONVERSION
+ #define STB_VORBIS_NO_STDIO
+#endif
+
+#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO)
+ #define STB_VORBIS_NO_STDIO 1
+#endif
+
+#ifndef STB_VORBIS_NO_INTEGER_CONVERSION
+#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT
+
+ // only need endianness for fast-float-to-int, which we don't
+ // use for pushdata
+
+ #ifndef STB_VORBIS_BIG_ENDIAN
+ #define STB_VORBIS_ENDIAN 0
+ #else
+ #define STB_VORBIS_ENDIAN 1
+ #endif
+
+#endif
+#endif
+
+
+#ifndef STB_VORBIS_NO_STDIO
+#include <stdio.h>
+#endif
+
+#ifndef STB_VORBIS_NO_CRT
+ #include <stdlib.h>
+ #include <string.h>
+ #include <assert.h>
+ #include <math.h>
+
+ // find definition of alloca if it's not in stdlib.h:
+ #ifdef _MSC_VER
+ #include <malloc.h>
+ #endif
+ #if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__)
+ #include <alloca.h>
+ #endif
+#else // STB_VORBIS_NO_CRT
+ #define NULL 0
+ #define malloc(s) 0
+ #define free(s) ((void) 0)
+ #define realloc(s) 0
+#endif // STB_VORBIS_NO_CRT
+
+#include <limits.h>
+
+#ifdef __MINGW32__
+ // eff you mingw:
+ // "fixed":
+ // http://sourceforge.net/p/mingw-w64/mailman/message/32882927/
+ // "no that broke the build, reverted, who cares about C":
+ // http://sourceforge.net/p/mingw-w64/mailman/message/32890381/
+ #ifdef __forceinline
+ #undef __forceinline
+ #endif
+ #define __forceinline
+#elif !defined(_MSC_VER)
+ #if __GNUC__
+ #define __forceinline inline
+ #else
+ #define __forceinline
+ #endif
+#endif
+
+#if STB_VORBIS_MAX_CHANNELS > 256
+#error "Value of STB_VORBIS_MAX_CHANNELS outside of allowed range"
+#endif
+
+#if STB_VORBIS_FAST_HUFFMAN_LENGTH > 24
+#error "Value of STB_VORBIS_FAST_HUFFMAN_LENGTH outside of allowed range"
+#endif
+
+
+#if 0
+#include <crtdbg.h>
+#define CHECK(f) _CrtIsValidHeapPointer(f->channel_buffers[1])
+#else
+#define CHECK(f) ((void) 0)
+#endif
+
+#define MAX_BLOCKSIZE_LOG 13 // from specification
+#define MAX_BLOCKSIZE (1 << MAX_BLOCKSIZE_LOG)
+
+
+typedef unsigned char uint8;
+typedef signed char int8;
+typedef unsigned short uint16;
+typedef signed short int16;
+typedef unsigned int uint32;
+typedef signed int int32;
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+typedef float codetype;
+
+// @NOTE
+//
+// Some arrays below are tagged "//varies", which means it's actually
+// a variable-sized piece of data, but rather than malloc I assume it's
+// small enough it's better to just allocate it all together with the
+// main thing
+//
+// Most of the variables are specified with the smallest size I could pack
+// them into. It might give better performance to make them all full-sized
+// integers. It should be safe to freely rearrange the structures or change
+// the sizes larger--nothing relies on silently truncating etc., nor the
+// order of variables.
+
+#define FAST_HUFFMAN_TABLE_SIZE (1 << STB_VORBIS_FAST_HUFFMAN_LENGTH)
+#define FAST_HUFFMAN_TABLE_MASK (FAST_HUFFMAN_TABLE_SIZE - 1)
+
+typedef struct
+{
+ int dimensions, entries;
+ uint8 *codeword_lengths;
+ float minimum_value;
+ float delta_value;
+ uint8 value_bits;
+ uint8 lookup_type;
+ uint8 sequence_p;
+ uint8 sparse;
+ uint32 lookup_values;
+ codetype *multiplicands;
+ uint32 *codewords;
+ #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT
+ int16 fast_huffman[FAST_HUFFMAN_TABLE_SIZE];
+ #else
+ int32 fast_huffman[FAST_HUFFMAN_TABLE_SIZE];
+ #endif
+ uint32 *sorted_codewords;
+ int *sorted_values;
+ int sorted_entries;
+} Codebook;
+
+typedef struct
+{
+ uint8 order;
+ uint16 rate;
+ uint16 bark_map_size;
+ uint8 amplitude_bits;
+ uint8 amplitude_offset;
+ uint8 number_of_books;
+ uint8 book_list[16]; // varies
+} Floor0;
+
+typedef struct
+{
+ uint8 partitions;
+ uint8 partition_class_list[32]; // varies
+ uint8 class_dimensions[16]; // varies
+ uint8 class_subclasses[16]; // varies
+ uint8 class_masterbooks[16]; // varies
+ int16 subclass_books[16][8]; // varies
+ uint16 Xlist[31*8+2]; // varies
+ uint8 sorted_order[31*8+2];
+ uint8 neighbors[31*8+2][2];
+ uint8 floor1_multiplier;
+ uint8 rangebits;
+ int values;
+} Floor1;
+
+typedef union
+{
+ Floor0 floor0;
+ Floor1 floor1;
+} Floor;
+
+typedef struct
+{
+ uint32 begin, end;
+ uint32 part_size;
+ uint8 classifications;
+ uint8 classbook;
+ uint8 **classdata;
+ int16 (*residue_books)[8];
+} Residue;
+
+typedef struct
+{
+ uint8 magnitude;
+ uint8 angle;
+ uint8 mux;
+} MappingChannel;
+
+typedef struct
+{
+ uint16 coupling_steps;
+ MappingChannel *chan;
+ uint8 submaps;
+ uint8 submap_floor[15]; // varies
+ uint8 submap_residue[15]; // varies
+} Mapping;
+
+typedef struct
+{
+ uint8 blockflag;
+ uint8 mapping;
+ uint16 windowtype;
+ uint16 transformtype;
+} Mode;
+
+typedef struct
+{
+ uint32 goal_crc; // expected crc if match
+ int bytes_left; // bytes left in packet
+ uint32 crc_so_far; // running crc
+ int bytes_done; // bytes processed in _current_ chunk
+ uint32 sample_loc; // granule pos encoded in page
+} CRCscan;
+
+typedef struct
+{
+ uint32 page_start, page_end;
+ uint32 last_decoded_sample;
+} ProbedPage;
+
+struct stb_vorbis
+{
+ // user-accessible info
+ unsigned int sample_rate;
+ int channels;
+
+ unsigned int setup_memory_required;
+ unsigned int temp_memory_required;
+ unsigned int setup_temp_memory_required;
+
+ // input config
+#ifndef STB_VORBIS_NO_STDIO
+ FILE *f;
+ uint32 f_start;
+ int close_on_free;
+#endif
+
+ uint8 *stream;
+ uint8 *stream_start;
+ uint8 *stream_end;
+
+ uint32 stream_len;
+
+ uint8 push_mode;
+
+ uint32 first_audio_page_offset;
+
+ ProbedPage p_first, p_last;
+
+ // memory management
+ stb_vorbis_alloc alloc;
+ int setup_offset;
+ int temp_offset;
+
+ // run-time results
+ int eof;
+ enum STBVorbisError error;
+
+ // user-useful data
+
+ // header info
+ int blocksize[2];
+ int blocksize_0, blocksize_1;
+ int codebook_count;
+ Codebook *codebooks;
+ int floor_count;
+ uint16 floor_types[64]; // varies
+ Floor *floor_config;
+ int residue_count;
+ uint16 residue_types[64]; // varies
+ Residue *residue_config;
+ int mapping_count;
+ Mapping *mapping;
+ int mode_count;
+ Mode mode_config[64]; // varies
+
+ uint32 total_samples;
+
+ // decode buffer
+ float *channel_buffers[STB_VORBIS_MAX_CHANNELS];
+ float *outputs [STB_VORBIS_MAX_CHANNELS];
+
+ float *previous_window[STB_VORBIS_MAX_CHANNELS];
+ int previous_length;
+
+ #ifndef STB_VORBIS_NO_DEFER_FLOOR
+ int16 *finalY[STB_VORBIS_MAX_CHANNELS];
+ #else
+ float *floor_buffers[STB_VORBIS_MAX_CHANNELS];
+ #endif
+
+ uint32 current_loc; // sample location of next frame to decode
+ int current_loc_valid;
+
+ // per-blocksize precomputed data
+
+ // twiddle factors
+ float *A[2],*B[2],*C[2];
+ float *window[2];
+ uint16 *bit_reverse[2];
+
+ // current page/packet/segment streaming info
+ uint32 serial; // stream serial number for verification
+ int last_page;
+ int segment_count;
+ uint8 segments[255];
+ uint8 page_flag;
+ uint8 bytes_in_seg;
+ uint8 first_decode;
+ int next_seg;
+ int last_seg; // flag that we're on the last segment
+ int last_seg_which; // what was the segment number of the last seg?
+ uint32 acc;
+ int valid_bits;
+ int packet_bytes;
+ int end_seg_with_known_loc;
+ uint32 known_loc_for_packet;
+ int discard_samples_deferred;
+ uint32 samples_output;
+
+ // push mode scanning
+ int page_crc_tests; // only in push_mode: number of tests active; -1 if not searching
+#ifndef STB_VORBIS_NO_PUSHDATA_API
+ CRCscan scan[STB_VORBIS_PUSHDATA_CRC_COUNT];
+#endif
+
+ // sample-access
+ int channel_buffer_start;
+ int channel_buffer_end;
+};
+
+#if defined(STB_VORBIS_NO_PUSHDATA_API)
+ #define IS_PUSH_MODE(f) FALSE
+#elif defined(STB_VORBIS_NO_PULLDATA_API)
+ #define IS_PUSH_MODE(f) TRUE
+#else
+ #define IS_PUSH_MODE(f) ((f)->push_mode)
+#endif
+
+typedef struct stb_vorbis vorb;
+
+static int error(vorb *f, enum STBVorbisError e)
+{
+ f->error = e;
+ if (!f->eof && e != VORBIS_need_more_data) {
+ f->error=e; // breakpoint for debugging
+ }
+ return 0;
+}
+
+
+// these functions are used for allocating temporary memory
+// while decoding. if you can afford the stack space, use
+// alloca(); otherwise, provide a temp buffer and it will
+// allocate out of those.
+
+#define array_size_required(count,size) (count*(sizeof(void *)+(size)))
+
+#define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : alloca(size))
+#ifdef dealloca
+#define temp_free(f,p) (f->alloc.alloc_buffer ? 0 : dealloca(size))
+#else
+#define temp_free(f,p) 0
+#endif
+#define temp_alloc_save(f) ((f)->temp_offset)
+#define temp_alloc_restore(f,p) ((f)->temp_offset = (p))
+
+#define temp_block_array(f,count,size) make_block_array(temp_alloc(f,array_size_required(count,size)), count, size)
+
+// given a sufficiently large block of memory, make an array of pointers to subblocks of it
+static void *make_block_array(void *mem, int count, int size)
+{
+ int i;
+ void ** p = (void **) mem;
+ char *q = (char *) (p + count);
+ for (i=0; i < count; ++i) {
+ p[i] = q;
+ q += size;
+ }
+ return p;
+}
+
+static void *setup_malloc(vorb *f, int sz)
+{
+ sz = (sz+3) & ~3;
+ f->setup_memory_required += sz;
+ if (f->alloc.alloc_buffer) {
+ void *p = (char *) f->alloc.alloc_buffer + f->setup_offset;
+ if (f->setup_offset + sz > f->temp_offset) return NULL;
+ f->setup_offset += sz;
+ return p;
+ }
+ return sz ? malloc(sz) : NULL;
+}
+
+static void setup_free(vorb *f, void *p)
+{
+ if (f->alloc.alloc_buffer) return; // do nothing; setup mem is a stack
+ free(p);
+}
+
+static void *setup_temp_malloc(vorb *f, int sz)
+{
+ sz = (sz+3) & ~3;
+ if (f->alloc.alloc_buffer) {
+ if (f->temp_offset - sz < f->setup_offset) return NULL;
+ f->temp_offset -= sz;
+ return (char *) f->alloc.alloc_buffer + f->temp_offset;
+ }
+ return malloc(sz);
+}
+
+static void setup_temp_free(vorb *f, void *p, int sz)
+{
+ if (f->alloc.alloc_buffer) {
+ f->temp_offset += (sz+3)&~3;
+ return;
+ }
+ free(p);
+}
+
+#define CRC32_POLY 0x04c11db7 // from spec
+
+static uint32 crc_table[256];
+static void crc32_init(void)
+{
+ int i,j;
+ uint32 s;
+ for(i=0; i < 256; i++) {
+ for (s=(uint32) i << 24, j=0; j < 8; ++j)
+ s = (s << 1) ^ (s >= (1U<<31) ? CRC32_POLY : 0);
+ crc_table[i] = s;
+ }
+}
+
+static __forceinline uint32 crc32_update(uint32 crc, uint8 byte)
+{
+ return (crc << 8) ^ crc_table[byte ^ (crc >> 24)];
+}
+
+
+// used in setup, and for huffman that doesn't go fast path
+static unsigned int bit_reverse(unsigned int n)
+{
+ n = ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1);
+ n = ((n & 0xCCCCCCCC) >> 2) | ((n & 0x33333333) << 2);
+ n = ((n & 0xF0F0F0F0) >> 4) | ((n & 0x0F0F0F0F) << 4);
+ n = ((n & 0xFF00FF00) >> 8) | ((n & 0x00FF00FF) << 8);
+ return (n >> 16) | (n << 16);
+}
+
+static float square(float x)
+{
+ return x*x;
+}
+
+// this is a weird definition of log2() for which log2(1) = 1, log2(2) = 2, log2(4) = 3
+// as required by the specification. fast(?) implementation from stb.h
+// @OPTIMIZE: called multiple times per-packet with "constants"; move to setup
+static int ilog(int32 n)
+{
+ static signed char log2_4[16] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 };
+
+ // 2 compares if n < 16, 3 compares otherwise (4 if signed or n > 1<<29)
+ if (n < (1 << 14))
+ if (n < (1 << 4)) return 0 + log2_4[n ];
+ else if (n < (1 << 9)) return 5 + log2_4[n >> 5];
+ else return 10 + log2_4[n >> 10];
+ else if (n < (1 << 24))
+ if (n < (1 << 19)) return 15 + log2_4[n >> 15];
+ else return 20 + log2_4[n >> 20];
+ else if (n < (1 << 29)) return 25 + log2_4[n >> 25];
+ else if (n < (1 << 31)) return 30 + log2_4[n >> 30];
+ else return 0; // signed n returns 0
+}
+
+#ifndef M_PI
+ #define M_PI 3.14159265358979323846264f // from CRC
+#endif
+
+// code length assigned to a value with no huffman encoding
+#define NO_CODE 255
+
+/////////////////////// LEAF SETUP FUNCTIONS //////////////////////////
+//
+// these functions are only called at setup, and only a few times
+// per file
+
+static float float32_unpack(uint32 x)
+{
+ // from the specification
+ uint32 mantissa = x & 0x1fffff;
+ uint32 sign = x & 0x80000000;
+ uint32 exp = (x & 0x7fe00000) >> 21;
+ double res = sign ? -(double)mantissa : (double)mantissa;
+ return (float) ldexp((float)res, exp-788);
+}
+
+
+// zlib & jpeg huffman tables assume that the output symbols
+// can either be arbitrarily arranged, or have monotonically
+// increasing frequencies--they rely on the lengths being sorted;
+// this makes for a very simple generation algorithm.
+// vorbis allows a huffman table with non-sorted lengths. This
+// requires a more sophisticated construction, since symbols in
+// order do not map to huffman codes "in order".
+static void add_entry(Codebook *c, uint32 huff_code, int symbol, int count, int len, uint32 *values)
+{
+ if (!c->sparse) {
+ c->codewords [symbol] = huff_code;
+ } else {
+ c->codewords [count] = huff_code;
+ c->codeword_lengths[count] = len;
+ values [count] = symbol;
+ }
+}
+
+static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)
+{
+ int i,k,m=0;
+ uint32 available[32];
+
+ memset(available, 0, sizeof(available));
+ // find the first entry
+ for (k=0; k < n; ++k) if (len[k] < NO_CODE) break;
+ if (k == n) { assert(c->sorted_entries == 0); return TRUE; }
+ // add to the list
+ add_entry(c, 0, k, m++, len[k], values);
+ // add all available leaves
+ for (i=1; i <= len[k]; ++i)
+ available[i] = 1U << (32-i);
+ // note that the above code treats the first case specially,
+ // but it's really the same as the following code, so they
+ // could probably be combined (except the initial code is 0,
+ // and I use 0 in available[] to mean 'empty')
+ for (i=k+1; i < n; ++i) {
+ uint32 res;
+ int z = len[i], y;
+ if (z == NO_CODE) continue;
+ // find lowest available leaf (should always be earliest,
+ // which is what the specification calls for)
+ // note that this property, and the fact we can never have
+ // more than one free leaf at a given level, isn't totally
+ // trivial to prove, but it seems true and the assert never
+ // fires, so!
+ while (z > 0 && !available[z]) --z;
+ if (z == 0) { return FALSE; }
+ res = available[z];
+ assert(z >= 0 && z < 32);
+ available[z] = 0;
+ add_entry(c, bit_reverse(res), i, m++, len[i], values);
+ // propogate availability up the tree
+ if (z != len[i]) {
+ assert(len[i] >= 0 && len[i] < 32);
+ for (y=len[i]; y > z; --y) {
+ assert(available[y] == 0);
+ available[y] = res + (1 << (32-y));
+ }
+ }
+ }
+ return TRUE;
+}
+
+// accelerated huffman table allows fast O(1) match of all symbols
+// of length <= STB_VORBIS_FAST_HUFFMAN_LENGTH
+static void compute_accelerated_huffman(Codebook *c)
+{
+ int i, len;
+ for (i=0; i < FAST_HUFFMAN_TABLE_SIZE; ++i)
+ c->fast_huffman[i] = -1;
+
+ len = c->sparse ? c->sorted_entries : c->entries;
+ #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT
+ if (len > 32767) len = 32767; // largest possible value we can encode!
+ #endif
+ for (i=0; i < len; ++i) {
+ if (c->codeword_lengths[i] <= STB_VORBIS_FAST_HUFFMAN_LENGTH) {
+ uint32 z = c->sparse ? bit_reverse(c->sorted_codewords[i]) : c->codewords[i];
+ // set table entries for all bit combinations in the higher bits
+ while (z < FAST_HUFFMAN_TABLE_SIZE) {
+ c->fast_huffman[z] = i;
+ z += 1 << c->codeword_lengths[i];
+ }
+ }
+ }
+}
+
+#ifdef _MSC_VER
+#define STBV_CDECL __cdecl
+#else
+#define STBV_CDECL
+#endif
+
+static int STBV_CDECL uint32_compare(const void *p, const void *q)
+{
+ uint32 x = * (uint32 *) p;
+ uint32 y = * (uint32 *) q;
+ return x < y ? -1 : x > y;
+}
+
+static int include_in_sort(Codebook *c, uint8 len)
+{
+ if (c->sparse) { assert(len != NO_CODE); return TRUE; }
+ if (len == NO_CODE) return FALSE;
+ if (len > STB_VORBIS_FAST_HUFFMAN_LENGTH) return TRUE;
+ return FALSE;
+}
+
+// if the fast table above doesn't work, we want to binary
+// search them... need to reverse the bits
+static void compute_sorted_huffman(Codebook *c, uint8 *lengths, uint32 *values)
+{
+ int i, len;
+ // build a list of all the entries
+ // OPTIMIZATION: don't include the short ones, since they'll be caught by FAST_HUFFMAN.
+ // this is kind of a frivolous optimization--I don't see any performance improvement,
+ // but it's like 4 extra lines of code, so.
+ if (!c->sparse) {
+ int k = 0;
+ for (i=0; i < c->entries; ++i)
+ if (include_in_sort(c, lengths[i]))
+ c->sorted_codewords[k++] = bit_reverse(c->codewords[i]);
+ assert(k == c->sorted_entries);
+ } else {
+ for (i=0; i < c->sorted_entries; ++i)
+ c->sorted_codewords[i] = bit_reverse(c->codewords[i]);
+ }
+
+ qsort(c->sorted_codewords, c->sorted_entries, sizeof(c->sorted_codewords[0]), uint32_compare);
+ c->sorted_codewords[c->sorted_entries] = 0xffffffff;
+
+ len = c->sparse ? c->sorted_entries : c->entries;
+ // now we need to indicate how they correspond; we could either
+ // #1: sort a different data structure that says who they correspond to
+ // #2: for each sorted entry, search the original list to find who corresponds
+ // #3: for each original entry, find the sorted entry
+ // #1 requires extra storage, #2 is slow, #3 can use binary search!
+ for (i=0; i < len; ++i) {
+ int huff_len = c->sparse ? lengths[values[i]] : lengths[i];
+ if (include_in_sort(c,huff_len)) {
+ uint32 code = bit_reverse(c->codewords[i]);
+ int x=0, n=c->sorted_entries;
+ while (n > 1) {
+ // invariant: sc[x] <= code < sc[x+n]
+ int m = x + (n >> 1);
+ if (c->sorted_codewords[m] <= code) {
+ x = m;
+ n -= (n>>1);
+ } else {
+ n >>= 1;
+ }
+ }
+ assert(c->sorted_codewords[x] == code);
+ if (c->sparse) {
+ c->sorted_values[x] = values[i];
+ c->codeword_lengths[x] = huff_len;
+ } else {
+ c->sorted_values[x] = i;
+ }
+ }
+ }
+}
+
+// only run while parsing the header (3 times)
+static int vorbis_validate(uint8 *data)
+{
+ static uint8 vorbis[6] = { 'v', 'o', 'r', 'b', 'i', 's' };
+ return memcmp(data, vorbis, 6) == 0;
+}
+
+// called from setup only, once per code book
+// (formula implied by specification)
+static int lookup1_values(int entries, int dim)
+{
+ int r = (int) floor(exp((float) log((float) entries) / dim));
+ if ((int) floor(pow((float) r+1, dim)) <= entries) // (int) cast for MinGW warning;
+ ++r; // floor() to avoid _ftol() when non-CRT
+ assert(pow((float) r+1, dim) > entries);
+ assert((int) floor(pow((float) r, dim)) <= entries); // (int),floor() as above
+ return r;
+}
+
+// called twice per file
+static void compute_twiddle_factors(int n, float *A, float *B, float *C)
+{
+ int n4 = n >> 2, n8 = n >> 3;
+ int k,k2;
+
+ for (k=k2=0; k < n4; ++k,k2+=2) {
+ A[k2 ] = (float) cos(4*k*M_PI/n);
+ A[k2+1] = (float) -sin(4*k*M_PI/n);
+ B[k2 ] = (float) cos((k2+1)*M_PI/n/2) * 0.5f;
+ B[k2+1] = (float) sin((k2+1)*M_PI/n/2) * 0.5f;
+ }
+ for (k=k2=0; k < n8; ++k,k2+=2) {
+ C[k2 ] = (float) cos(2*(k2+1)*M_PI/n);
+ C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n);
+ }
+}
+
+static void compute_window(int n, float *window)
+{
+ int n2 = n >> 1, i;
+ for (i=0; i < n2; ++i)
+ window[i] = (float) sin(0.5 * M_PI * square((float) sin((i - 0 + 0.5) / n2 * 0.5 * M_PI)));
+}
+
+static void compute_bitreverse(int n, uint16 *rev)
+{
+ int ld = ilog(n) - 1; // ilog is off-by-one from normal definitions
+ int i, n8 = n >> 3;
+ for (i=0; i < n8; ++i)
+ rev[i] = (bit_reverse(i) >> (32-ld+3)) << 2;
+}
+
+static int init_blocksize(vorb *f, int b, int n)
+{
+ int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3;
+ f->A[b] = (float *) setup_malloc(f, sizeof(float) * n2);
+ f->B[b] = (float *) setup_malloc(f, sizeof(float) * n2);
+ f->C[b] = (float *) setup_malloc(f, sizeof(float) * n4);
+ if (!f->A[b] || !f->B[b] || !f->C[b]) return error(f, VORBIS_outofmem);
+ compute_twiddle_factors(n, f->A[b], f->B[b], f->C[b]);
+ f->window[b] = (float *) setup_malloc(f, sizeof(float) * n2);
+ if (!f->window[b]) return error(f, VORBIS_outofmem);
+ compute_window(n, f->window[b]);
+ f->bit_reverse[b] = (uint16 *) setup_malloc(f, sizeof(uint16) * n8);
+ if (!f->bit_reverse[b]) return error(f, VORBIS_outofmem);
+ compute_bitreverse(n, f->bit_reverse[b]);
+ return TRUE;
+}
+
+static void neighbors(uint16 *x, int n, int *plow, int *phigh)
+{
+ int low = -1;
+ int high = 65536;
+ int i;
+ for (i=0; i < n; ++i) {
+ if (x[i] > low && x[i] < x[n]) { *plow = i; low = x[i]; }
+ if (x[i] < high && x[i] > x[n]) { *phigh = i; high = x[i]; }
+ }
+}
+
+// this has been repurposed so y is now the original index instead of y
+typedef struct
+{
+ uint16 x,y;
+} Point;
+
+static int STBV_CDECL point_compare(const void *p, const void *q)
+{
+ Point *a = (Point *) p;
+ Point *b = (Point *) q;
+ return a->x < b->x ? -1 : a->x > b->x;
+}
+
+//
+/////////////////////// END LEAF SETUP FUNCTIONS //////////////////////////
+
+
+#if defined(STB_VORBIS_NO_STDIO)
+ #define USE_MEMORY(z) TRUE
+#else
+ #define USE_MEMORY(z) ((z)->stream)
+#endif
+
+static uint8 get8(vorb *z)
+{
+ if (USE_MEMORY(z)) {
+ if (z->stream >= z->stream_end) { z->eof = TRUE; return 0; }
+ return *z->stream++;
+ }
+
+ #ifndef STB_VORBIS_NO_STDIO
+ {
+ int c = fgetc(z->f);
+ if (c == EOF) { z->eof = TRUE; return 0; }
+ return c;
+ }
+ #endif
+}
+
+static uint32 get32(vorb *f)
+{
+ uint32 x;
+ x = get8(f);
+ x += get8(f) << 8;
+ x += get8(f) << 16;
+ x += (uint32) get8(f) << 24;
+ return x;
+}
+
+static int getn(vorb *z, uint8 *data, int n)
+{
+ if (USE_MEMORY(z)) {
+ if (z->stream+n > z->stream_end) { z->eof = 1; return 0; }
+ memcpy(data, z->stream, n);
+ z->stream += n;
+ return 1;
+ }
+
+ #ifndef STB_VORBIS_NO_STDIO
+ if (fread(data, n, 1, z->f) == 1)
+ return 1;
+ else {
+ z->eof = 1;
+ return 0;
+ }
+ #endif
+}
+
+static void skip(vorb *z, int n)
+{
+ if (USE_MEMORY(z)) {
+ z->stream += n;
+ if (z->stream >= z->stream_end) z->eof = 1;
+ return;
+ }
+ #ifndef STB_VORBIS_NO_STDIO
+ {
+ long x = ftell(z->f);
+ fseek(z->f, x+n, SEEK_SET);
+ }
+ #endif
+}
+
+static int set_file_offset(stb_vorbis *f, unsigned int loc)
+{
+ #ifndef STB_VORBIS_NO_PUSHDATA_API
+ if (f->push_mode) return 0;
+ #endif
+ f->eof = 0;
+ if (USE_MEMORY(f)) {
+ if (f->stream_start + loc >= f->stream_end || f->stream_start + loc < f->stream_start) {
+ f->stream = f->stream_end;
+ f->eof = 1;
+ return 0;
+ } else {
+ f->stream = f->stream_start + loc;
+ return 1;
+ }
+ }
+ #ifndef STB_VORBIS_NO_STDIO
+ if (loc + f->f_start < loc || loc >= 0x80000000) {
+ loc = 0x7fffffff;
+ f->eof = 1;
+ } else {
+ loc += f->f_start;
+ }
+ if (!fseek(f->f, loc, SEEK_SET))
+ return 1;
+ f->eof = 1;
+ fseek(f->f, f->f_start, SEEK_END);
+ return 0;
+ #endif
+}
+
+
+static uint8 ogg_page_header[4] = { 0x4f, 0x67, 0x67, 0x53 };
+
+static int capture_pattern(vorb *f)
+{
+ if (0x4f != get8(f)) return FALSE;
+ if (0x67 != get8(f)) return FALSE;
+ if (0x67 != get8(f)) return FALSE;
+ if (0x53 != get8(f)) return FALSE;
+ return TRUE;
+}
+
+#define PAGEFLAG_continued_packet 1
+#define PAGEFLAG_first_page 2
+#define PAGEFLAG_last_page 4
+
+static int start_page_no_capturepattern(vorb *f)
+{
+ uint32 loc0,loc1,n;
+ // stream structure version
+ if (0 != get8(f)) return error(f, VORBIS_invalid_stream_structure_version);
+ // header flag
+ f->page_flag = get8(f);
+ // absolute granule position
+ loc0 = get32(f);
+ loc1 = get32(f);
+ // @TODO: validate loc0,loc1 as valid positions?
+ // stream serial number -- vorbis doesn't interleave, so discard
+ get32(f);
+ //if (f->serial != get32(f)) return error(f, VORBIS_incorrect_stream_serial_number);
+ // page sequence number
+ n = get32(f);
+ f->last_page = n;
+ // CRC32
+ get32(f);
+ // page_segments
+ f->segment_count = get8(f);
+ if (!getn(f, f->segments, f->segment_count))
+ return error(f, VORBIS_unexpected_eof);
+ // assume we _don't_ know any the sample position of any segments
+ f->end_seg_with_known_loc = -2;
+ if (loc0 != ~0U || loc1 != ~0U) {
+ int i;
+ // determine which packet is the last one that will complete
+ for (i=f->segment_count-1; i >= 0; --i)
+ if (f->segments[i] < 255)
+ break;
+ // 'i' is now the index of the _last_ segment of a packet that ends
+ if (i >= 0) {
+ f->end_seg_with_known_loc = i;
+ f->known_loc_for_packet = loc0;
+ }
+ }
+ if (f->first_decode) {
+ int i,len;
+ ProbedPage p;
+ len = 0;
+ for (i=0; i < f->segment_count; ++i)
+ len += f->segments[i];
+ len += 27 + f->segment_count;
+ p.page_start = f->first_audio_page_offset;
+ p.page_end = p.page_start + len;
+ p.last_decoded_sample = loc0;
+ f->p_first = p;
+ }
+ f->next_seg = 0;
+ return TRUE;
+}
+
+static int start_page(vorb *f)
+{
+ if (!capture_pattern(f)) return error(f, VORBIS_missing_capture_pattern);
+ return start_page_no_capturepattern(f);
+}
+
+static int start_packet(vorb *f)
+{
+ while (f->next_seg == -1) {
+ if (!start_page(f)) return FALSE;
+ if (f->page_flag & PAGEFLAG_continued_packet)
+ return error(f, VORBIS_continued_packet_flag_invalid);
+ }
+ f->last_seg = FALSE;
+ f->valid_bits = 0;
+ f->packet_bytes = 0;
+ f->bytes_in_seg = 0;
+ // f->next_seg is now valid
+ return TRUE;
+}
+
+static int maybe_start_packet(vorb *f)
+{
+ if (f->next_seg == -1) {
+ int x = get8(f);
+ if (f->eof) return FALSE; // EOF at page boundary is not an error!
+ if (0x4f != x ) return error(f, VORBIS_missing_capture_pattern);
+ if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern);
+ if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern);
+ if (0x53 != get8(f)) return error(f, VORBIS_missing_capture_pattern);
+ if (!start_page_no_capturepattern(f)) return FALSE;
+ if (f->page_flag & PAGEFLAG_continued_packet) {
+ // set up enough state that we can read this packet if we want,
+ // e.g. during recovery
+ f->last_seg = FALSE;
+ f->bytes_in_seg = 0;
+ return error(f, VORBIS_continued_packet_flag_invalid);
+ }
+ }
+ return start_packet(f);
+}
+
+static int next_segment(vorb *f)
+{
+ int len;
+ if (f->last_seg) return 0;
+ if (f->next_seg == -1) {
+ f->last_seg_which = f->segment_count-1; // in case start_page fails
+ if (!start_page(f)) { f->last_seg = 1; return 0; }
+ if (!(f->page_flag & PAGEFLAG_continued_packet)) return error(f, VORBIS_continued_packet_flag_invalid);
+ }
+ len = f->segments[f->next_seg++];
+ if (len < 255) {
+ f->last_seg = TRUE;
+ f->last_seg_which = f->next_seg-1;
+ }
+ if (f->next_seg >= f->segment_count)
+ f->next_seg = -1;
+ assert(f->bytes_in_seg == 0);
+ f->bytes_in_seg = len;
+ return len;
+}
+
+#define EOP (-1)
+#define INVALID_BITS (-1)
+
+static int get8_packet_raw(vorb *f)
+{
+ if (!f->bytes_in_seg) { // CLANG!
+ if (f->last_seg) return EOP;
+ else if (!next_segment(f)) return EOP;
+ }
+ assert(f->bytes_in_seg > 0);
+ --f->bytes_in_seg;
+ ++f->packet_bytes;
+ return get8(f);
+}
+
+static int get8_packet(vorb *f)
+{
+ int x = get8_packet_raw(f);
+ f->valid_bits = 0;
+ return x;
+}
+
+static void flush_packet(vorb *f)
+{
+ while (get8_packet_raw(f) != EOP);
+}
+
+// @OPTIMIZE: this is the secondary bit decoder, so it's probably not as important
+// as the huffman decoder?
+static uint32 get_bits(vorb *f, int n)
+{
+ uint32 z;
+
+ if (f->valid_bits < 0) return 0;
+ if (f->valid_bits < n) {
+ if (n > 24) {
+ // the accumulator technique below would not work correctly in this case
+ z = get_bits(f, 24);
+ z += get_bits(f, n-24) << 24;
+ return z;
+ }
+ if (f->valid_bits == 0) f->acc = 0;
+ while (f->valid_bits < n) {
+ int z = get8_packet_raw(f);
+ if (z == EOP) {
+ f->valid_bits = INVALID_BITS;
+ return 0;
+ }
+ f->acc += z << f->valid_bits;
+ f->valid_bits += 8;
+ }
+ }
+ if (f->valid_bits < 0) return 0;
+ z = f->acc & ((1 << n)-1);
+ f->acc >>= n;
+ f->valid_bits -= n;
+ return z;
+}
+
+// @OPTIMIZE: primary accumulator for huffman
+// expand the buffer to as many bits as possible without reading off end of packet
+// it might be nice to allow f->valid_bits and f->acc to be stored in registers,
+// e.g. cache them locally and decode locally
+static __forceinline void prep_huffman(vorb *f)
+{
+ if (f->valid_bits <= 24) {
+ if (f->valid_bits == 0) f->acc = 0;
+ do {
+ int z;
+ if (f->last_seg && !f->bytes_in_seg) return;
+ z = get8_packet_raw(f);
+ if (z == EOP) return;
+ f->acc += (unsigned) z << f->valid_bits;
+ f->valid_bits += 8;
+ } while (f->valid_bits <= 24);
+ }
+}
+
+enum
+{
+ VORBIS_packet_id = 1,
+ VORBIS_packet_comment = 3,
+ VORBIS_packet_setup = 5
+};
+
+static int codebook_decode_scalar_raw(vorb *f, Codebook *c)
+{
+ int i;
+ prep_huffman(f);
+
+ if (c->codewords == NULL && c->sorted_codewords == NULL)
+ return -1;
+
+ // cases to use binary search: sorted_codewords && !c->codewords
+ // sorted_codewords && c->entries > 8
+ if (c->entries > 8 ? c->sorted_codewords!=NULL : !c->codewords) {
+ // binary search
+ uint32 code = bit_reverse(f->acc);
+ int x=0, n=c->sorted_entries, len;
+
+ while (n > 1) {
+ // invariant: sc[x] <= code < sc[x+n]
+ int m = x + (n >> 1);
+ if (c->sorted_codewords[m] <= code) {
+ x = m;
+ n -= (n>>1);
+ } else {
+ n >>= 1;
+ }
+ }
+ // x is now the sorted index
+ if (!c->sparse) x = c->sorted_values[x];
+ // x is now sorted index if sparse, or symbol otherwise
+ len = c->codeword_lengths[x];
+ if (f->valid_bits >= len) {
+ f->acc >>= len;
+ f->valid_bits -= len;
+ return x;
+ }
+
+ f->valid_bits = 0;
+ return -1;
+ }
+
+ // if small, linear search
+ assert(!c->sparse);
+ for (i=0; i < c->entries; ++i) {
+ if (c->codeword_lengths[i] == NO_CODE) continue;
+ if (c->codewords[i] == (f->acc & ((1 << c->codeword_lengths[i])-1))) {
+ if (f->valid_bits >= c->codeword_lengths[i]) {
+ f->acc >>= c->codeword_lengths[i];
+ f->valid_bits -= c->codeword_lengths[i];
+ return i;
+ }
+ f->valid_bits = 0;
+ return -1;
+ }
+ }
+
+ error(f, VORBIS_invalid_stream);
+ f->valid_bits = 0;
+ return -1;
+}
+
+#ifndef STB_VORBIS_NO_INLINE_DECODE
+
+#define DECODE_RAW(var, f,c) \
+ if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH) \
+ prep_huffman(f); \
+ var = f->acc & FAST_HUFFMAN_TABLE_MASK; \
+ var = c->fast_huffman[var]; \
+ if (var >= 0) { \
+ int n = c->codeword_lengths[var]; \
+ f->acc >>= n; \
+ f->valid_bits -= n; \
+ if (f->valid_bits < 0) { f->valid_bits = 0; var = -1; } \
+ } else { \
+ var = codebook_decode_scalar_raw(f,c); \
+ }
+
+#else
+
+static int codebook_decode_scalar(vorb *f, Codebook *c)
+{
+ int i;
+ if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH)
+ prep_huffman(f);
+ // fast huffman table lookup
+ i = f->acc & FAST_HUFFMAN_TABLE_MASK;
+ i = c->fast_huffman[i];
+ if (i >= 0) {
+ f->acc >>= c->codeword_lengths[i];
+ f->valid_bits -= c->codeword_lengths[i];
+ if (f->valid_bits < 0) { f->valid_bits = 0; return -1; }
+ return i;
+ }
+ return codebook_decode_scalar_raw(f,c);
+}
+
+#define DECODE_RAW(var,f,c) var = codebook_decode_scalar(f,c);
+
+#endif
+
+#define DECODE(var,f,c) \
+ DECODE_RAW(var,f,c) \
+ if (c->sparse) var = c->sorted_values[var];
+
+#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
+ #define DECODE_VQ(var,f,c) DECODE_RAW(var,f,c)
+#else
+ #define DECODE_VQ(var,f,c) DECODE(var,f,c)
+#endif
+
+
+
+
+
+
+// CODEBOOK_ELEMENT_FAST is an optimization for the CODEBOOK_FLOATS case
+// where we avoid one addition
+#define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off])
+#define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off])
+#define CODEBOOK_ELEMENT_BASE(c) (0)
+
+static int codebook_decode_start(vorb *f, Codebook *c)
+{
+ int z = -1;
+
+ // type 0 is only legal in a scalar context
+ if (c->lookup_type == 0)
+ error(f, VORBIS_invalid_stream);
+ else {
+ DECODE_VQ(z,f,c);
+ if (c->sparse) assert(z < c->sorted_entries);
+ if (z < 0) { // check for EOP
+ if (!f->bytes_in_seg)
+ if (f->last_seg)
+ return z;
+ error(f, VORBIS_invalid_stream);
+ }
+ }
+ return z;
+}
+
+static int codebook_decode(vorb *f, Codebook *c, float *output, int len)
+{
+ int i,z = codebook_decode_start(f,c);
+ if (z < 0) return FALSE;
+ if (len > c->dimensions) len = c->dimensions;
+
+#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK
+ if (c->lookup_type == 1) {
+ float last = CODEBOOK_ELEMENT_BASE(c);
+ int div = 1;
+ for (i=0; i < len; ++i) {
+ int off = (z / div) % c->lookup_values;
+ float val = CODEBOOK_ELEMENT_FAST(c,off) + last;
+ output[i] += val;
+ if (c->sequence_p) last = val + c->minimum_value;
+ div *= c->lookup_values;
+ }
+ return TRUE;
+ }
+#endif
+
+ z *= c->dimensions;
+ if (c->sequence_p) {
+ float last = CODEBOOK_ELEMENT_BASE(c);
+ for (i=0; i < len; ++i) {
+ float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last;
+ output[i] += val;
+ last = val + c->minimum_value;
+ }
+ } else {
+ float last = CODEBOOK_ELEMENT_BASE(c);
+ for (i=0; i < len; ++i) {
+ output[i] += CODEBOOK_ELEMENT_FAST(c,z+i) + last;
+ }
+ }
+
+ return TRUE;
+}
+
+static int codebook_decode_step(vorb *f, Codebook *c, float *output, int len, int step)
+{
+ int i,z = codebook_decode_start(f,c);
+ float last = CODEBOOK_ELEMENT_BASE(c);
+ if (z < 0) return FALSE;
+ if (len > c->dimensions) len = c->dimensions;
+
+#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK
+ if (c->lookup_type == 1) {
+ int div = 1;
+ for (i=0; i < len; ++i) {
+ int off = (z / div) % c->lookup_values;
+ float val = CODEBOOK_ELEMENT_FAST(c,off) + last;
+ output[i*step] += val;
+ if (c->sequence_p) last = val;
+ div *= c->lookup_values;
+ }
+ return TRUE;
+ }
+#endif
+
+ z *= c->dimensions;
+ for (i=0; i < len; ++i) {
+ float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last;
+ output[i*step] += val;
+ if (c->sequence_p) last = val;
+ }
+
+ return TRUE;
+}
+
+static int codebook_decode_deinterleave_repeat(vorb *f, Codebook *c, float **outputs, int ch, int *c_inter_p, int *p_inter_p, int len, int total_decode)
+{
+ int c_inter = *c_inter_p;
+ int p_inter = *p_inter_p;
+ int i,z, effective = c->dimensions;
+
+ // type 0 is only legal in a scalar context
+ if (c->lookup_type == 0) return error(f, VORBIS_invalid_stream);
+
+ while (total_decode > 0) {
+ float last = CODEBOOK_ELEMENT_BASE(c);
+ DECODE_VQ(z,f,c);
+ #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
+ assert(!c->sparse || z < c->sorted_entries);
+ #endif
+ if (z < 0) {
+ if (!f->bytes_in_seg)
+ if (f->last_seg) return FALSE;
+ return error(f, VORBIS_invalid_stream);
+ }
+
+ // if this will take us off the end of the buffers, stop short!
+ // we check by computing the length of the virtual interleaved
+ // buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter),
+ // and the length we'll be using (effective)
+ if (c_inter + p_inter*ch + effective > len * ch) {
+ effective = len*ch - (p_inter*ch - c_inter);
+ }
+
+ #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK
+ if (c->lookup_type == 1) {
+ int div = 1;
+ for (i=0; i < effective; ++i) {
+ int off = (z / div) % c->lookup_values;
+ float val = CODEBOOK_ELEMENT_FAST(c,off) + last;
+ if (outputs[c_inter])
+ outputs[c_inter][p_inter] += val;
+ if (++c_inter == ch) { c_inter = 0; ++p_inter; }
+ if (c->sequence_p) last = val;
+ div *= c->lookup_values;
+ }
+ } else
+ #endif
+ {
+ z *= c->dimensions;
+ if (c->sequence_p) {
+ for (i=0; i < effective; ++i) {
+ float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last;
+ if (outputs[c_inter])
+ outputs[c_inter][p_inter] += val;
+ if (++c_inter == ch) { c_inter = 0; ++p_inter; }
+ last = val;
+ }
+ } else {
+ for (i=0; i < effective; ++i) {
+ float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last;
+ if (outputs[c_inter])
+ outputs[c_inter][p_inter] += val;
+ if (++c_inter == ch) { c_inter = 0; ++p_inter; }
+ }
+ }
+ }
+
+ total_decode -= effective;
+ }
+ *c_inter_p = c_inter;
+ *p_inter_p = p_inter;
+ return TRUE;
+}
+
+static int predict_point(int x, int x0, int x1, int y0, int y1)
+{
+ int dy = y1 - y0;
+ int adx = x1 - x0;
+ // @OPTIMIZE: force int division to round in the right direction... is this necessary on x86?
+ int err = abs(dy) * (x - x0);
+ int off = err / adx;
+ return dy < 0 ? y0 - off : y0 + off;
+}
+
+// the following table is block-copied from the specification
+static float inverse_db_table[256] =
+{
+ 1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f,
+ 1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f,
+ 1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.1287530e-07f,
+ 2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f,
+ 2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f,
+ 3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f,
+ 4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f,
+ 6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f,
+ 7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f,
+ 1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f,
+ 1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f,
+ 1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f,
+ 2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f,
+ 2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f,
+ 3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f,
+ 4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f,
+ 5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f,
+ 7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f,
+ 9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f,
+ 1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f,
+ 1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f,
+ 2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f,
+ 2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f,
+ 3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f,
+ 4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f,
+ 5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f,
+ 7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f,
+ 9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f,
+ 0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f,
+ 0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f,
+ 0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f,
+ 0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f,
+ 0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f,
+ 0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f,
+ 0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f,
+ 0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f,
+ 0.00092223983f, 0.00098217216f, 0.0010459992f, 0.0011139742f,
+ 0.0011863665f, 0.0012634633f, 0.0013455702f, 0.0014330129f,
+ 0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f,
+ 0.0019632195f, 0.0020908006f, 0.0022266726f, 0.0023713743f,
+ 0.0025254795f, 0.0026895994f, 0.0028643847f, 0.0030505286f,
+ 0.0032487691f, 0.0034598925f, 0.0036847358f, 0.0039241906f,
+ 0.0041792066f, 0.0044507950f, 0.0047400328f, 0.0050480668f,
+ 0.0053761186f, 0.0057254891f, 0.0060975636f, 0.0064938176f,
+ 0.0069158225f, 0.0073652516f, 0.0078438871f, 0.0083536271f,
+ 0.0088964928f, 0.009474637f, 0.010090352f, 0.010746080f,
+ 0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f,
+ 0.014722068f, 0.015678791f, 0.016697687f, 0.017782797f,
+ 0.018938423f, 0.020169149f, 0.021479854f, 0.022875735f,
+ 0.024362330f, 0.025945531f, 0.027631618f, 0.029427276f,
+ 0.031339626f, 0.033376252f, 0.035545228f, 0.037855157f,
+ 0.040315199f, 0.042935108f, 0.045725273f, 0.048696758f,
+ 0.051861348f, 0.055231591f, 0.058820850f, 0.062643361f,
+ 0.066714279f, 0.071049749f, 0.075666962f, 0.080584227f,
+ 0.085821044f, 0.091398179f, 0.097337747f, 0.10366330f,
+ 0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f,
+ 0.14201813f, 0.15124727f, 0.16107617f, 0.17154380f,
+ 0.18269168f, 0.19456402f, 0.20720788f, 0.22067342f,
+ 0.23501402f, 0.25028656f, 0.26655159f, 0.28387361f,
+ 0.30232132f, 0.32196786f, 0.34289114f, 0.36517414f,
+ 0.38890521f, 0.41417847f, 0.44109412f, 0.46975890f,
+ 0.50028648f, 0.53279791f, 0.56742212f, 0.60429640f,
+ 0.64356699f, 0.68538959f, 0.72993007f, 0.77736504f,
+ 0.82788260f, 0.88168307f, 0.9389798f, 1.0f
+};
+
+
+// @OPTIMIZE: if you want to replace this bresenham line-drawing routine,
+// note that you must produce bit-identical output to decode correctly;
+// this specific sequence of operations is specified in the spec (it's
+// drawing integer-quantized frequency-space lines that the encoder
+// expects to be exactly the same)
+// ... also, isn't the whole point of Bresenham's algorithm to NOT
+// have to divide in the setup? sigh.
+#ifndef STB_VORBIS_NO_DEFER_FLOOR
+#define LINE_OP(a,b) a *= b
+#else
+#define LINE_OP(a,b) a = b
+#endif
+
+#ifdef STB_VORBIS_DIVIDE_TABLE
+#define DIVTAB_NUMER 32
+#define DIVTAB_DENOM 64
+int8 integer_divide_table[DIVTAB_NUMER][DIVTAB_DENOM]; // 2KB
+#endif
+
+static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y1, int n)
+{
+ int dy = y1 - y0;
+ int adx = x1 - x0;
+ int ady = abs(dy);
+ int base;
+ int x=x0,y=y0;
+ int err = 0;
+ int sy;
+
+#ifdef STB_VORBIS_DIVIDE_TABLE
+ if (adx < DIVTAB_DENOM && ady < DIVTAB_NUMER) {
+ if (dy < 0) {
+ base = -integer_divide_table[ady][adx];
+ sy = base-1;
+ } else {
+ base = integer_divide_table[ady][adx];
+ sy = base+1;
+ }
+ } else {
+ base = dy / adx;
+ if (dy < 0)
+ sy = base - 1;
+ else
+ sy = base+1;
+ }
+#else
+ base = dy / adx;
+ if (dy < 0)
+ sy = base - 1;
+ else
+ sy = base+1;
+#endif
+ ady -= abs(base) * adx;
+ if (x1 > n) x1 = n;
+ if (x < x1) {
+ LINE_OP(output[x], inverse_db_table[y]);
+ for (++x; x < x1; ++x) {
+ err += ady;
+ if (err >= adx) {
+ err -= adx;
+ y += sy;
+ } else
+ y += base;
+ LINE_OP(output[x], inverse_db_table[y]);
+ }
+ }
+}
+
+static int residue_decode(vorb *f, Codebook *book, float *target, int offset, int n, int rtype)
+{
+ int k;
+ if (rtype == 0) {
+ int step = n / book->dimensions;
+ for (k=0; k < step; ++k)
+ if (!codebook_decode_step(f, book, target+offset+k, n-offset-k, step))
+ return FALSE;
+ } else {
+ for (k=0; k < n; ) {
+ if (!codebook_decode(f, book, target+offset, n-k))
+ return FALSE;
+ k += book->dimensions;
+ offset += book->dimensions;
+ }
+ }
+ return TRUE;
+}
+
+static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int rn, uint8 *do_not_decode)
+{
+ int i,j,pass;
+ Residue *r = f->residue_config + rn;
+ int rtype = f->residue_types[rn];
+ int c = r->classbook;
+ int classwords = f->codebooks[c].dimensions;
+ int n_read = r->end - r->begin;
+ int part_read = n_read / r->part_size;
+ int temp_alloc_point = temp_alloc_save(f);
+ #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
+ uint8 ***part_classdata = (uint8 ***) temp_block_array(f,f->channels, part_read * sizeof(**part_classdata));
+ #else
+ int **classifications = (int **) temp_block_array(f,f->channels, part_read * sizeof(**classifications));
+ #endif
+
+ CHECK(f);
+
+ for (i=0; i < ch; ++i)
+ if (!do_not_decode[i])
+ memset(residue_buffers[i], 0, sizeof(float) * n);
+
+ if (rtype == 2 && ch != 1) {
+ for (j=0; j < ch; ++j)
+ if (!do_not_decode[j])
+ break;
+ if (j == ch)
+ goto done;
+
+ for (pass=0; pass < 8; ++pass) {
+ int pcount = 0, class_set = 0;
+ if (ch == 2) {
+ while (pcount < part_read) {
+ int z = r->begin + pcount*r->part_size;
+ int c_inter = (z & 1), p_inter = z>>1;
+ if (pass == 0) {
+ Codebook *c = f->codebooks+r->classbook;
+ int q;
+ DECODE(q,f,c);
+ if (q == EOP) goto done;
+ #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
+ part_classdata[0][class_set] = r->classdata[q];
+ #else
+ for (i=classwords-1; i >= 0; --i) {
+ classifications[0][i+pcount] = q % r->classifications;
+ q /= r->classifications;
+ }
+ #endif
+ }
+ for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) {
+ int z = r->begin + pcount*r->part_size;
+ #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
+ int c = part_classdata[0][class_set][i];
+ #else
+ int c = classifications[0][pcount];
+ #endif
+ int b = r->residue_books[c][pass];
+ if (b >= 0) {
+ Codebook *book = f->codebooks + b;
+ #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK
+ if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))
+ goto done;
+ #else
+ // saves 1%
+ if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))
+ goto done;
+ #endif
+ } else {
+ z += r->part_size;
+ c_inter = z & 1;
+ p_inter = z >> 1;
+ }
+ }
+ #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
+ ++class_set;
+ #endif
+ }
+ } else if (ch == 1) {
+ while (pcount < part_read) {
+ int z = r->begin + pcount*r->part_size;
+ int c_inter = 0, p_inter = z;
+ if (pass == 0) {
+ Codebook *c = f->codebooks+r->classbook;
+ int q;
+ DECODE(q,f,c);
+ if (q == EOP) goto done;
+ #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
+ part_classdata[0][class_set] = r->classdata[q];
+ #else
+ for (i=classwords-1; i >= 0; --i) {
+ classifications[0][i+pcount] = q % r->classifications;
+ q /= r->classifications;
+ }
+ #endif
+ }
+ for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) {
+ int z = r->begin + pcount*r->part_size;
+ #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
+ int c = part_classdata[0][class_set][i];
+ #else
+ int c = classifications[0][pcount];
+ #endif
+ int b = r->residue_books[c][pass];
+ if (b >= 0) {
+ Codebook *book = f->codebooks + b;
+ if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))
+ goto done;
+ } else {
+ z += r->part_size;
+ c_inter = 0;
+ p_inter = z;
+ }
+ }
+ #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
+ ++class_set;
+ #endif
+ }
+ } else {
+ while (pcount < part_read) {
+ int z = r->begin + pcount*r->part_size;
+ int c_inter = z % ch, p_inter = z/ch;
+ if (pass == 0) {
+ Codebook *c = f->codebooks+r->classbook;
+ int q;
+ DECODE(q,f,c);
+ if (q == EOP) goto done;
+ #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
+ part_classdata[0][class_set] = r->classdata[q];
+ #else
+ for (i=classwords-1; i >= 0; --i) {
+ classifications[0][i+pcount] = q % r->classifications;
+ q /= r->classifications;
+ }
+ #endif
+ }
+ for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) {
+ int z = r->begin + pcount*r->part_size;
+ #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
+ int c = part_classdata[0][class_set][i];
+ #else
+ int c = classifications[0][pcount];
+ #endif
+ int b = r->residue_books[c][pass];
+ if (b >= 0) {
+ Codebook *book = f->codebooks + b;
+ if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))
+ goto done;
+ } else {
+ z += r->part_size;
+ c_inter = z % ch;
+ p_inter = z / ch;
+ }
+ }
+ #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
+ ++class_set;
+ #endif
+ }
+ }
+ }
+ goto done;
+ }
+ CHECK(f);
+
+ for (pass=0; pass < 8; ++pass) {
+ int pcount = 0, class_set=0;
+ while (pcount < part_read) {
+ if (pass == 0) {
+ for (j=0; j < ch; ++j) {
+ if (!do_not_decode[j]) {
+ Codebook *c = f->codebooks+r->classbook;
+ int temp;
+ DECODE(temp,f,c);
+ if (temp == EOP) goto done;
+ #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
+ part_classdata[j][class_set] = r->classdata[temp];
+ #else
+ for (i=classwords-1; i >= 0; --i) {
+ classifications[j][i+pcount] = temp % r->classifications;
+ temp /= r->classifications;
+ }
+ #endif
+ }
+ }
+ }
+ for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) {
+ for (j=0; j < ch; ++j) {
+ if (!do_not_decode[j]) {
+ #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
+ int c = part_classdata[j][class_set][i];
+ #else
+ int c = classifications[j][pcount];
+ #endif
+ int b = r->residue_books[c][pass];
+ if (b >= 0) {
+ float *target = residue_buffers[j];
+ int offset = r->begin + pcount * r->part_size;
+ int n = r->part_size;
+ Codebook *book = f->codebooks + b;
+ if (!residue_decode(f, book, target, offset, n, rtype))
+ goto done;
+ }
+ }
+ }
+ }
+ #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
+ ++class_set;
+ #endif
+ }
+ }
+ done:
+ CHECK(f);
+ #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
+ temp_free(f,part_classdata);
+ #else
+ temp_free(f,classifications);
+ #endif
+ temp_alloc_restore(f,temp_alloc_point);
+}
+
+
+#if 0
+// slow way for debugging
+void inverse_mdct_slow(float *buffer, int n)
+{
+ int i,j;
+ int n2 = n >> 1;
+ float *x = (float *) malloc(sizeof(*x) * n2);
+ memcpy(x, buffer, sizeof(*x) * n2);
+ for (i=0; i < n; ++i) {
+ float acc = 0;
+ for (j=0; j < n2; ++j)
+ // formula from paper:
+ //acc += n/4.0f * x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1));
+ // formula from wikipedia
+ //acc += 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5));
+ // these are equivalent, except the formula from the paper inverts the multiplier!
+ // however, what actually works is NO MULTIPLIER!?!
+ //acc += 64 * 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5));
+ acc += x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1));
+ buffer[i] = acc;
+ }
+ free(x);
+}
+#elif 0
+// same as above, but just barely able to run in real time on modern machines
+void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype)
+{
+ float mcos[16384];
+ int i,j;
+ int n2 = n >> 1, nmask = (n << 2) -1;
+ float *x = (float *) malloc(sizeof(*x) * n2);
+ memcpy(x, buffer, sizeof(*x) * n2);
+ for (i=0; i < 4*n; ++i)
+ mcos[i] = (float) cos(M_PI / 2 * i / n);
+
+ for (i=0; i < n; ++i) {
+ float acc = 0;
+ for (j=0; j < n2; ++j)
+ acc += x[j] * mcos[(2 * i + 1 + n2)*(2*j+1) & nmask];
+ buffer[i] = acc;
+ }
+ free(x);
+}
+#elif 0
+// transform to use a slow dct-iv; this is STILL basically trivial,
+// but only requires half as many ops
+void dct_iv_slow(float *buffer, int n)
+{
+ float mcos[16384];
+ float x[2048];
+ int i,j;
+ int n2 = n >> 1, nmask = (n << 3) - 1;
+ memcpy(x, buffer, sizeof(*x) * n);
+ for (i=0; i < 8*n; ++i)
+ mcos[i] = (float) cos(M_PI / 4 * i / n);
+ for (i=0; i < n; ++i) {
+ float acc = 0;
+ for (j=0; j < n; ++j)
+ acc += x[j] * mcos[((2 * i + 1)*(2*j+1)) & nmask];
+ buffer[i] = acc;
+ }
+}
+
+void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype)
+{
+ int i, n4 = n >> 2, n2 = n >> 1, n3_4 = n - n4;
+ float temp[4096];
+
+ memcpy(temp, buffer, n2 * sizeof(float));
+ dct_iv_slow(temp, n2); // returns -c'-d, a-b'
+
+ for (i=0; i < n4 ; ++i) buffer[i] = temp[i+n4]; // a-b'
+ for ( ; i < n3_4; ++i) buffer[i] = -temp[n3_4 - i - 1]; // b-a', c+d'
+ for ( ; i < n ; ++i) buffer[i] = -temp[i - n3_4]; // c'+d
+}
+#endif
+
+#ifndef LIBVORBIS_MDCT
+#define LIBVORBIS_MDCT 0
+#endif
+
+#if LIBVORBIS_MDCT
+// directly call the vorbis MDCT using an interface documented
+// by Jeff Roberts... useful for performance comparison
+typedef struct
+{
+ int n;
+ int log2n;
+
+ float *trig;
+ int *bitrev;
+
+ float scale;
+} mdct_lookup;
+
+extern void mdct_init(mdct_lookup *lookup, int n);
+extern void mdct_clear(mdct_lookup *l);
+extern void mdct_backward(mdct_lookup *init, float *in, float *out);
+
+mdct_lookup M1,M2;
+
+void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
+{
+ mdct_lookup *M;
+ if (M1.n == n) M = &M1;
+ else if (M2.n == n) M = &M2;
+ else if (M1.n == 0) { mdct_init(&M1, n); M = &M1; }
+ else {
+ if (M2.n) __asm int 3;
+ mdct_init(&M2, n);
+ M = &M2;
+ }
+
+ mdct_backward(M, buffer, buffer);
+}
+#endif
+
+
+// the following were split out into separate functions while optimizing;
+// they could be pushed back up but eh. __forceinline showed no change;
+// they're probably already being inlined.
+static void imdct_step3_iter0_loop(int n, float *e, int i_off, int k_off, float *A)
+{
+ float *ee0 = e + i_off;
+ float *ee2 = ee0 + k_off;
+ int i;
+
+ assert((n & 3) == 0);
+ for (i=(n>>2); i > 0; --i) {
+ float k00_20, k01_21;
+ k00_20 = ee0[ 0] - ee2[ 0];
+ k01_21 = ee0[-1] - ee2[-1];
+ ee0[ 0] += ee2[ 0];//ee0[ 0] = ee0[ 0] + ee2[ 0];
+ ee0[-1] += ee2[-1];//ee0[-1] = ee0[-1] + ee2[-1];
+ ee2[ 0] = k00_20 * A[0] - k01_21 * A[1];
+ ee2[-1] = k01_21 * A[0] + k00_20 * A[1];
+ A += 8;
+
+ k00_20 = ee0[-2] - ee2[-2];
+ k01_21 = ee0[-3] - ee2[-3];
+ ee0[-2] += ee2[-2];//ee0[-2] = ee0[-2] + ee2[-2];
+ ee0[-3] += ee2[-3];//ee0[-3] = ee0[-3] + ee2[-3];
+ ee2[-2] = k00_20 * A[0] - k01_21 * A[1];
+ ee2[-3] = k01_21 * A[0] + k00_20 * A[1];
+ A += 8;
+
+ k00_20 = ee0[-4] - ee2[-4];
+ k01_21 = ee0[-5] - ee2[-5];
+ ee0[-4] += ee2[-4];//ee0[-4] = ee0[-4] + ee2[-4];
+ ee0[-5] += ee2[-5];//ee0[-5] = ee0[-5] + ee2[-5];
+ ee2[-4] = k00_20 * A[0] - k01_21 * A[1];
+ ee2[-5] = k01_21 * A[0] + k00_20 * A[1];
+ A += 8;
+
+ k00_20 = ee0[-6] - ee2[-6];
+ k01_21 = ee0[-7] - ee2[-7];
+ ee0[-6] += ee2[-6];//ee0[-6] = ee0[-6] + ee2[-6];
+ ee0[-7] += ee2[-7];//ee0[-7] = ee0[-7] + ee2[-7];
+ ee2[-6] = k00_20 * A[0] - k01_21 * A[1];
+ ee2[-7] = k01_21 * A[0] + k00_20 * A[1];
+ A += 8;
+ ee0 -= 8;
+ ee2 -= 8;
+ }
+}
+
+static void imdct_step3_inner_r_loop(int lim, float *e, int d0, int k_off, float *A, int k1)
+{
+ int i;
+ float k00_20, k01_21;
+
+ float *e0 = e + d0;
+ float *e2 = e0 + k_off;
+
+ for (i=lim >> 2; i > 0; --i) {
+ k00_20 = e0[-0] - e2[-0];
+ k01_21 = e0[-1] - e2[-1];
+ e0[-0] += e2[-0];//e0[-0] = e0[-0] + e2[-0];
+ e0[-1] += e2[-1];//e0[-1] = e0[-1] + e2[-1];
+ e2[-0] = (k00_20)*A[0] - (k01_21) * A[1];
+ e2[-1] = (k01_21)*A[0] + (k00_20) * A[1];
+
+ A += k1;
+
+ k00_20 = e0[-2] - e2[-2];
+ k01_21 = e0[-3] - e2[-3];
+ e0[-2] += e2[-2];//e0[-2] = e0[-2] + e2[-2];
+ e0[-3] += e2[-3];//e0[-3] = e0[-3] + e2[-3];
+ e2[-2] = (k00_20)*A[0] - (k01_21) * A[1];
+ e2[-3] = (k01_21)*A[0] + (k00_20) * A[1];
+
+ A += k1;
+
+ k00_20 = e0[-4] - e2[-4];
+ k01_21 = e0[-5] - e2[-5];
+ e0[-4] += e2[-4];//e0[-4] = e0[-4] + e2[-4];
+ e0[-5] += e2[-5];//e0[-5] = e0[-5] + e2[-5];
+ e2[-4] = (k00_20)*A[0] - (k01_21) * A[1];
+ e2[-5] = (k01_21)*A[0] + (k00_20) * A[1];
+
+ A += k1;
+
+ k00_20 = e0[-6] - e2[-6];
+ k01_21 = e0[-7] - e2[-7];
+ e0[-6] += e2[-6];//e0[-6] = e0[-6] + e2[-6];
+ e0[-7] += e2[-7];//e0[-7] = e0[-7] + e2[-7];
+ e2[-6] = (k00_20)*A[0] - (k01_21) * A[1];
+ e2[-7] = (k01_21)*A[0] + (k00_20) * A[1];
+
+ e0 -= 8;
+ e2 -= 8;
+
+ A += k1;
+ }
+}
+
+static void imdct_step3_inner_s_loop(int n, float *e, int i_off, int k_off, float *A, int a_off, int k0)
+{
+ int i;
+ float A0 = A[0];
+ float A1 = A[0+1];
+ float A2 = A[0+a_off];
+ float A3 = A[0+a_off+1];
+ float A4 = A[0+a_off*2+0];
+ float A5 = A[0+a_off*2+1];
+ float A6 = A[0+a_off*3+0];
+ float A7 = A[0+a_off*3+1];
+
+ float k00,k11;
+
+ float *ee0 = e +i_off;
+ float *ee2 = ee0+k_off;
+
+ for (i=n; i > 0; --i) {
+ k00 = ee0[ 0] - ee2[ 0];
+ k11 = ee0[-1] - ee2[-1];
+ ee0[ 0] = ee0[ 0] + ee2[ 0];
+ ee0[-1] = ee0[-1] + ee2[-1];
+ ee2[ 0] = (k00) * A0 - (k11) * A1;
+ ee2[-1] = (k11) * A0 + (k00) * A1;
+
+ k00 = ee0[-2] - ee2[-2];
+ k11 = ee0[-3] - ee2[-3];
+ ee0[-2] = ee0[-2] + ee2[-2];
+ ee0[-3] = ee0[-3] + ee2[-3];
+ ee2[-2] = (k00) * A2 - (k11) * A3;
+ ee2[-3] = (k11) * A2 + (k00) * A3;
+
+ k00 = ee0[-4] - ee2[-4];
+ k11 = ee0[-5] - ee2[-5];
+ ee0[-4] = ee0[-4] + ee2[-4];
+ ee0[-5] = ee0[-5] + ee2[-5];
+ ee2[-4] = (k00) * A4 - (k11) * A5;
+ ee2[-5] = (k11) * A4 + (k00) * A5;
+
+ k00 = ee0[-6] - ee2[-6];
+ k11 = ee0[-7] - ee2[-7];
+ ee0[-6] = ee0[-6] + ee2[-6];
+ ee0[-7] = ee0[-7] + ee2[-7];
+ ee2[-6] = (k00) * A6 - (k11) * A7;
+ ee2[-7] = (k11) * A6 + (k00) * A7;
+
+ ee0 -= k0;
+ ee2 -= k0;
+ }
+}
+
+static __forceinline void iter_54(float *z)
+{
+ float k00,k11,k22,k33;
+ float y0,y1,y2,y3;
+
+ k00 = z[ 0] - z[-4];
+ y0 = z[ 0] + z[-4];
+ y2 = z[-2] + z[-6];
+ k22 = z[-2] - z[-6];
+
+ z[-0] = y0 + y2; // z0 + z4 + z2 + z6
+ z[-2] = y0 - y2; // z0 + z4 - z2 - z6
+
+ // done with y0,y2
+
+ k33 = z[-3] - z[-7];
+
+ z[-4] = k00 + k33; // z0 - z4 + z3 - z7
+ z[-6] = k00 - k33; // z0 - z4 - z3 + z7
+
+ // done with k33
+
+ k11 = z[-1] - z[-5];
+ y1 = z[-1] + z[-5];
+ y3 = z[-3] + z[-7];
+
+ z[-1] = y1 + y3; // z1 + z5 + z3 + z7
+ z[-3] = y1 - y3; // z1 + z5 - z3 - z7
+ z[-5] = k11 - k22; // z1 - z5 + z2 - z6
+ z[-7] = k11 + k22; // z1 - z5 - z2 + z6
+}
+
+static void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A, int base_n)
+{
+ int a_off = base_n >> 3;
+ float A2 = A[0+a_off];
+ float *z = e + i_off;
+ float *base = z - 16 * n;
+
+ while (z > base) {
+ float k00,k11;
+
+ k00 = z[-0] - z[-8];
+ k11 = z[-1] - z[-9];
+ z[-0] = z[-0] + z[-8];
+ z[-1] = z[-1] + z[-9];
+ z[-8] = k00;
+ z[-9] = k11 ;
+
+ k00 = z[ -2] - z[-10];
+ k11 = z[ -3] - z[-11];
+ z[ -2] = z[ -2] + z[-10];
+ z[ -3] = z[ -3] + z[-11];
+ z[-10] = (k00+k11) * A2;
+ z[-11] = (k11-k00) * A2;
+
+ k00 = z[-12] - z[ -4]; // reverse to avoid a unary negation
+ k11 = z[ -5] - z[-13];
+ z[ -4] = z[ -4] + z[-12];
+ z[ -5] = z[ -5] + z[-13];
+ z[-12] = k11;
+ z[-13] = k00;
+
+ k00 = z[-14] - z[ -6]; // reverse to avoid a unary negation
+ k11 = z[ -7] - z[-15];
+ z[ -6] = z[ -6] + z[-14];
+ z[ -7] = z[ -7] + z[-15];
+ z[-14] = (k00+k11) * A2;
+ z[-15] = (k00-k11) * A2;
+
+ iter_54(z);
+ iter_54(z-8);
+ z -= 16;
+ }
+}
+
+static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
+{
+ int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l;
+ int ld;
+ // @OPTIMIZE: reduce register pressure by using fewer variables?
+ int save_point = temp_alloc_save(f);
+ float *buf2 = (float *) temp_alloc(f, n2 * sizeof(*buf2));
+ float *u=NULL,*v=NULL;
+ // twiddle factors
+ float *A = f->A[blocktype];
+
+ // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio"
+ // See notes about bugs in that paper in less-optimal implementation 'inverse_mdct_old' after this function.
+
+ // kernel from paper
+
+
+ // merged:
+ // copy and reflect spectral data
+ // step 0
+
+ // note that it turns out that the items added together during
+ // this step are, in fact, being added to themselves (as reflected
+ // by step 0). inexplicable inefficiency! this became obvious
+ // once I combined the passes.
+
+ // so there's a missing 'times 2' here (for adding X to itself).
+ // this propogates through linearly to the end, where the numbers
+ // are 1/2 too small, and need to be compensated for.
+
+ {
+ float *d,*e, *AA, *e_stop;
+ d = &buf2[n2-2];
+ AA = A;
+ e = &buffer[0];
+ e_stop = &buffer[n2];
+ while (e != e_stop) {
+ d[1] = (e[0] * AA[0] - e[2]*AA[1]);
+ d[0] = (e[0] * AA[1] + e[2]*AA[0]);
+ d -= 2;
+ AA += 2;
+ e += 4;
+ }
+
+ e = &buffer[n2-3];
+ while (d >= buf2) {
+ d[1] = (-e[2] * AA[0] - -e[0]*AA[1]);
+ d[0] = (-e[2] * AA[1] + -e[0]*AA[0]);
+ d -= 2;
+ AA += 2;
+ e -= 4;
+ }
+ }
+
+ // now we use symbolic names for these, so that we can
+ // possibly swap their meaning as we change which operations
+ // are in place
+
+ u = buffer;
+ v = buf2;
+
+ // step 2 (paper output is w, now u)
+ // this could be in place, but the data ends up in the wrong
+ // place... _somebody_'s got to swap it, so this is nominated
+ {
+ float *AA = &A[n2-8];
+ float *d0,*d1, *e0, *e1;
+
+ e0 = &v[n4];
+ e1 = &v[0];
+
+ d0 = &u[n4];
+ d1 = &u[0];
+
+ while (AA >= A) {
+ float v40_20, v41_21;
+
+ v41_21 = e0[1] - e1[1];
+ v40_20 = e0[0] - e1[0];
+ d0[1] = e0[1] + e1[1];
+ d0[0] = e0[0] + e1[0];
+ d1[1] = v41_21*AA[4] - v40_20*AA[5];
+ d1[0] = v40_20*AA[4] + v41_21*AA[5];
+
+ v41_21 = e0[3] - e1[3];
+ v40_20 = e0[2] - e1[2];
+ d0[3] = e0[3] + e1[3];
+ d0[2] = e0[2] + e1[2];
+ d1[3] = v41_21*AA[0] - v40_20*AA[1];
+ d1[2] = v40_20*AA[0] + v41_21*AA[1];
+
+ AA -= 8;
+
+ d0 += 4;
+ d1 += 4;
+ e0 += 4;
+ e1 += 4;
+ }
+ }
+
+ // step 3
+ ld = ilog(n) - 1; // ilog is off-by-one from normal definitions
+
+ // optimized step 3:
+
+ // the original step3 loop can be nested r inside s or s inside r;
+ // it's written originally as s inside r, but this is dumb when r
+ // iterates many times, and s few. So I have two copies of it and
+ // switch between them halfway.
+
+ // this is iteration 0 of step 3
+ imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*0, -(n >> 3), A);
+ imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*1, -(n >> 3), A);
+
+ // this is iteration 1 of step 3
+ imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*0, -(n >> 4), A, 16);
+ imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*1, -(n >> 4), A, 16);
+ imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*2, -(n >> 4), A, 16);
+ imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*3, -(n >> 4), A, 16);
+
+ l=2;
+ for (; l < (ld-3)>>1; ++l) {
+ int k0 = n >> (l+2), k0_2 = k0>>1;
+ int lim = 1 << (l+1);
+ int i;
+ for (i=0; i < lim; ++i)
+ imdct_step3_inner_r_loop(n >> (l+4), u, n2-1 - k0*i, -k0_2, A, 1 << (l+3));
+ }
+
+ for (; l < ld-6; ++l) {
+ int k0 = n >> (l+2), k1 = 1 << (l+3), k0_2 = k0>>1;
+ int rlim = n >> (l+6), r;
+ int lim = 1 << (l+1);
+ int i_off;
+ float *A0 = A;
+ i_off = n2-1;
+ for (r=rlim; r > 0; --r) {
+ imdct_step3_inner_s_loop(lim, u, i_off, -k0_2, A0, k1, k0);
+ A0 += k1*4;
+ i_off -= 8;
+ }
+ }
+
+ // iterations with count:
+ // ld-6,-5,-4 all interleaved together
+ // the big win comes from getting rid of needless flops
+ // due to the constants on pass 5 & 4 being all 1 and 0;
+ // combining them to be simultaneous to improve cache made little difference
+ imdct_step3_inner_s_loop_ld654(n >> 5, u, n2-1, A, n);
+
+ // output is u
+
+ // step 4, 5, and 6
+ // cannot be in-place because of step 5
+ {
+ uint16 *bitrev = f->bit_reverse[blocktype];
+ // weirdly, I'd have thought reading sequentially and writing
+ // erratically would have been better than vice-versa, but in
+ // fact that's not what my testing showed. (That is, with
+ // j = bitreverse(i), do you read i and write j, or read j and write i.)
+
+ float *d0 = &v[n4-4];
+ float *d1 = &v[n2-4];
+ while (d0 >= v) {
+ int k4;
+
+ k4 = bitrev[0];
+ d1[3] = u[k4+0];
+ d1[2] = u[k4+1];
+ d0[3] = u[k4+2];
+ d0[2] = u[k4+3];
+
+ k4 = bitrev[1];
+ d1[1] = u[k4+0];
+ d1[0] = u[k4+1];
+ d0[1] = u[k4+2];
+ d0[0] = u[k4+3];
+
+ d0 -= 4;
+ d1 -= 4;
+ bitrev += 2;
+ }
+ }
+ // (paper output is u, now v)
+
+
+ // data must be in buf2
+ assert(v == buf2);
+
+ // step 7 (paper output is v, now v)
+ // this is now in place
+ {
+ float *C = f->C[blocktype];
+ float *d, *e;
+
+ d = v;
+ e = v + n2 - 4;
+
+ while (d < e) {
+ float a02,a11,b0,b1,b2,b3;
+
+ a02 = d[0] - e[2];
+ a11 = d[1] + e[3];
+
+ b0 = C[1]*a02 + C[0]*a11;
+ b1 = C[1]*a11 - C[0]*a02;
+
+ b2 = d[0] + e[ 2];
+ b3 = d[1] - e[ 3];
+
+ d[0] = b2 + b0;
+ d[1] = b3 + b1;
+ e[2] = b2 - b0;
+ e[3] = b1 - b3;
+
+ a02 = d[2] - e[0];
+ a11 = d[3] + e[1];
+
+ b0 = C[3]*a02 + C[2]*a11;
+ b1 = C[3]*a11 - C[2]*a02;
+
+ b2 = d[2] + e[ 0];
+ b3 = d[3] - e[ 1];
+
+ d[2] = b2 + b0;
+ d[3] = b3 + b1;
+ e[0] = b2 - b0;
+ e[1] = b1 - b3;
+
+ C += 4;
+ d += 4;
+ e -= 4;
+ }
+ }
+
+ // data must be in buf2
+
+
+ // step 8+decode (paper output is X, now buffer)
+ // this generates pairs of data a la 8 and pushes them directly through
+ // the decode kernel (pushing rather than pulling) to avoid having
+ // to make another pass later
+
+ // this cannot POSSIBLY be in place, so we refer to the buffers directly
+
+ {
+ float *d0,*d1,*d2,*d3;
+
+ float *B = f->B[blocktype] + n2 - 8;
+ float *e = buf2 + n2 - 8;
+ d0 = &buffer[0];
+ d1 = &buffer[n2-4];
+ d2 = &buffer[n2];
+ d3 = &buffer[n-4];
+ while (e >= v) {
+ float p0,p1,p2,p3;
+
+ p3 = e[6]*B[7] - e[7]*B[6];
+ p2 = -e[6]*B[6] - e[7]*B[7];
+
+ d0[0] = p3;
+ d1[3] = - p3;
+ d2[0] = p2;
+ d3[3] = p2;
+
+ p1 = e[4]*B[5] - e[5]*B[4];
+ p0 = -e[4]*B[4] - e[5]*B[5];
+
+ d0[1] = p1;
+ d1[2] = - p1;
+ d2[1] = p0;
+ d3[2] = p0;
+
+ p3 = e[2]*B[3] - e[3]*B[2];
+ p2 = -e[2]*B[2] - e[3]*B[3];
+
+ d0[2] = p3;
+ d1[1] = - p3;
+ d2[2] = p2;
+ d3[1] = p2;
+
+ p1 = e[0]*B[1] - e[1]*B[0];
+ p0 = -e[0]*B[0] - e[1]*B[1];
+
+ d0[3] = p1;
+ d1[0] = - p1;
+ d2[3] = p0;
+ d3[0] = p0;
+
+ B -= 8;
+ e -= 8;
+ d0 += 4;
+ d2 += 4;
+ d1 -= 4;
+ d3 -= 4;
+ }
+ }
+
+ temp_free(f,buf2);
+ temp_alloc_restore(f,save_point);
+}
+
+#if 0
+// this is the original version of the above code, if you want to optimize it from scratch
+void inverse_mdct_naive(float *buffer, int n)
+{
+ float s;
+ float A[1 << 12], B[1 << 12], C[1 << 11];
+ int i,k,k2,k4, n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l;
+ int n3_4 = n - n4, ld;
+ // how can they claim this only uses N words?!
+ // oh, because they're only used sparsely, whoops
+ float u[1 << 13], X[1 << 13], v[1 << 13], w[1 << 13];
+ // set up twiddle factors
+
+ for (k=k2=0; k < n4; ++k,k2+=2) {
+ A[k2 ] = (float) cos(4*k*M_PI/n);
+ A[k2+1] = (float) -sin(4*k*M_PI/n);
+ B[k2 ] = (float) cos((k2+1)*M_PI/n/2);
+ B[k2+1] = (float) sin((k2+1)*M_PI/n/2);
+ }
+ for (k=k2=0; k < n8; ++k,k2+=2) {
+ C[k2 ] = (float) cos(2*(k2+1)*M_PI/n);
+ C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n);
+ }
+
+ // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio"
+ // Note there are bugs in that pseudocode, presumably due to them attempting
+ // to rename the arrays nicely rather than representing the way their actual
+ // implementation bounces buffers back and forth. As a result, even in the
+ // "some formulars corrected" version, a direct implementation fails. These
+ // are noted below as "paper bug".
+
+ // copy and reflect spectral data
+ for (k=0; k < n2; ++k) u[k] = buffer[k];
+ for ( ; k < n ; ++k) u[k] = -buffer[n - k - 1];
+ // kernel from paper
+ // step 1
+ for (k=k2=k4=0; k < n4; k+=1, k2+=2, k4+=4) {
+ v[n-k4-1] = (u[k4] - u[n-k4-1]) * A[k2] - (u[k4+2] - u[n-k4-3])*A[k2+1];
+ v[n-k4-3] = (u[k4] - u[n-k4-1]) * A[k2+1] + (u[k4+2] - u[n-k4-3])*A[k2];
+ }
+ // step 2
+ for (k=k4=0; k < n8; k+=1, k4+=4) {
+ w[n2+3+k4] = v[n2+3+k4] + v[k4+3];
+ w[n2+1+k4] = v[n2+1+k4] + v[k4+1];
+ w[k4+3] = (v[n2+3+k4] - v[k4+3])*A[n2-4-k4] - (v[n2+1+k4]-v[k4+1])*A[n2-3-k4];
+ w[k4+1] = (v[n2+1+k4] - v[k4+1])*A[n2-4-k4] + (v[n2+3+k4]-v[k4+3])*A[n2-3-k4];
+ }
+ // step 3
+ ld = ilog(n) - 1; // ilog is off-by-one from normal definitions
+ for (l=0; l < ld-3; ++l) {
+ int k0 = n >> (l+2), k1 = 1 << (l+3);
+ int rlim = n >> (l+4), r4, r;
+ int s2lim = 1 << (l+2), s2;
+ for (r=r4=0; r < rlim; r4+=4,++r) {
+ for (s2=0; s2 < s2lim; s2+=2) {
+ u[n-1-k0*s2-r4] = w[n-1-k0*s2-r4] + w[n-1-k0*(s2+1)-r4];
+ u[n-3-k0*s2-r4] = w[n-3-k0*s2-r4] + w[n-3-k0*(s2+1)-r4];
+ u[n-1-k0*(s2+1)-r4] = (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1]
+ - (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1+1];
+ u[n-3-k0*(s2+1)-r4] = (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1]
+ + (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1+1];
+ }
+ }
+ if (l+1 < ld-3) {
+ // paper bug: ping-ponging of u&w here is omitted
+ memcpy(w, u, sizeof(u));
+ }
+ }
+
+ // step 4
+ for (i=0; i < n8; ++i) {
+ int j = bit_reverse(i) >> (32-ld+3);
+ assert(j < n8);
+ if (i == j) {
+ // paper bug: original code probably swapped in place; if copying,
+ // need to directly copy in this case
+ int i8 = i << 3;
+ v[i8+1] = u[i8+1];
+ v[i8+3] = u[i8+3];
+ v[i8+5] = u[i8+5];
+ v[i8+7] = u[i8+7];
+ } else if (i < j) {
+ int i8 = i << 3, j8 = j << 3;
+ v[j8+1] = u[i8+1], v[i8+1] = u[j8 + 1];
+ v[j8+3] = u[i8+3], v[i8+3] = u[j8 + 3];
+ v[j8+5] = u[i8+5], v[i8+5] = u[j8 + 5];
+ v[j8+7] = u[i8+7], v[i8+7] = u[j8 + 7];
+ }
+ }
+ // step 5
+ for (k=0; k < n2; ++k) {
+ w[k] = v[k*2+1];
+ }
+ // step 6
+ for (k=k2=k4=0; k < n8; ++k, k2 += 2, k4 += 4) {
+ u[n-1-k2] = w[k4];
+ u[n-2-k2] = w[k4+1];
+ u[n3_4 - 1 - k2] = w[k4+2];
+ u[n3_4 - 2 - k2] = w[k4+3];
+ }
+ // step 7
+ for (k=k2=0; k < n8; ++k, k2 += 2) {
+ v[n2 + k2 ] = ( u[n2 + k2] + u[n-2-k2] + C[k2+1]*(u[n2+k2]-u[n-2-k2]) + C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2;
+ v[n-2 - k2] = ( u[n2 + k2] + u[n-2-k2] - C[k2+1]*(u[n2+k2]-u[n-2-k2]) - C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2;
+ v[n2+1+ k2] = ( u[n2+1+k2] - u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2;
+ v[n-1 - k2] = (-u[n2+1+k2] + u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2;
+ }
+ // step 8
+ for (k=k2=0; k < n4; ++k,k2 += 2) {
+ X[k] = v[k2+n2]*B[k2 ] + v[k2+1+n2]*B[k2+1];
+ X[n2-1-k] = v[k2+n2]*B[k2+1] - v[k2+1+n2]*B[k2 ];
+ }
+
+ // decode kernel to output
+ // determined the following value experimentally
+ // (by first figuring out what made inverse_mdct_slow work); then matching that here
+ // (probably vorbis encoder premultiplies by n or n/2, to save it on the decoder?)
+ s = 0.5; // theoretically would be n4
+
+ // [[[ note! the s value of 0.5 is compensated for by the B[] in the current code,
+ // so it needs to use the "old" B values to behave correctly, or else
+ // set s to 1.0 ]]]
+ for (i=0; i < n4 ; ++i) buffer[i] = s * X[i+n4];
+ for ( ; i < n3_4; ++i) buffer[i] = -s * X[n3_4 - i - 1];
+ for ( ; i < n ; ++i) buffer[i] = -s * X[i - n3_4];
+}
+#endif
+
+static float *get_window(vorb *f, int len)
+{
+ len <<= 1;
+ if (len == f->blocksize_0) return f->window[0];
+ if (len == f->blocksize_1) return f->window[1];
+ assert(0);
+ return NULL;
+}
+
+#ifndef STB_VORBIS_NO_DEFER_FLOOR
+typedef int16 YTYPE;
+#else
+typedef int YTYPE;
+#endif
+static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *finalY, uint8 *step2_flag)
+{
+ int n2 = n >> 1;
+ int s = map->chan[i].mux, floor;
+ floor = map->submap_floor[s];
+ if (f->floor_types[floor] == 0) {
+ return error(f, VORBIS_invalid_stream);
+ } else {
+ Floor1 *g = &f->floor_config[floor].floor1;
+ int j,q;
+ int lx = 0, ly = finalY[0] * g->floor1_multiplier;
+ for (q=1; q < g->values; ++q) {
+ j = g->sorted_order[q];
+ #ifndef STB_VORBIS_NO_DEFER_FLOOR
+ if (finalY[j] >= 0)
+ #else
+ if (step2_flag[j])
+ #endif
+ {
+ int hy = finalY[j] * g->floor1_multiplier;
+ int hx = g->Xlist[j];
+ if (lx != hx)
+ draw_line(target, lx,ly, hx,hy, n2);
+ CHECK(f);
+ lx = hx, ly = hy;
+ }
+ }
+ if (lx < n2) {
+ // optimization of: draw_line(target, lx,ly, n,ly, n2);
+ for (j=lx; j < n2; ++j)
+ LINE_OP(target[j], inverse_db_table[ly]);
+ CHECK(f);
+ }
+ }
+ return TRUE;
+}
+
+// The meaning of "left" and "right"
+//
+// For a given frame:
+// we compute samples from 0..n
+// window_center is n/2
+// we'll window and mix the samples from left_start to left_end with data from the previous frame
+// all of the samples from left_end to right_start can be output without mixing; however,
+// this interval is 0-length except when transitioning between short and long frames
+// all of the samples from right_start to right_end need to be mixed with the next frame,
+// which we don't have, so those get saved in a buffer
+// frame N's right_end-right_start, the number of samples to mix with the next frame,
+// has to be the same as frame N+1's left_end-left_start (which they are by
+// construction)
+
+static int vorbis_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode)
+{
+ Mode *m;
+ int i, n, prev, next, window_center;
+ f->channel_buffer_start = f->channel_buffer_end = 0;
+
+ retry:
+ if (f->eof) return FALSE;
+ if (!maybe_start_packet(f))
+ return FALSE;
+ // check packet type
+ if (get_bits(f,1) != 0) {
+ if (IS_PUSH_MODE(f))
+ return error(f,VORBIS_bad_packet_type);
+ while (EOP != get8_packet(f));
+ goto retry;
+ }
+
+ if (f->alloc.alloc_buffer)
+ assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset);
+
+ i = get_bits(f, ilog(f->mode_count-1));
+ if (i == EOP) return FALSE;
+ if (i >= f->mode_count) return FALSE;
+ *mode = i;
+ m = f->mode_config + i;
+ if (m->blockflag) {
+ n = f->blocksize_1;
+ prev = get_bits(f,1);
+ next = get_bits(f,1);
+ } else {
+ prev = next = 0;
+ n = f->blocksize_0;
+ }
+
+// WINDOWING
+
+ window_center = n >> 1;
+ if (m->blockflag && !prev) {
+ *p_left_start = (n - f->blocksize_0) >> 2;
+ *p_left_end = (n + f->blocksize_0) >> 2;
+ } else {
+ *p_left_start = 0;
+ *p_left_end = window_center;
+ }
+ if (m->blockflag && !next) {
+ *p_right_start = (n*3 - f->blocksize_0) >> 2;
+ *p_right_end = (n*3 + f->blocksize_0) >> 2;
+ } else {
+ *p_right_start = window_center;
+ *p_right_end = n;
+ }
+
+ return TRUE;
+}
+
+static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, int left_end, int right_start, int right_end, int *p_left)
+{
+ Mapping *map;
+ int i,j,k,n,n2;
+ int zero_channel[256];
+ int really_zero_channel[256];
+
+// WINDOWING
+
+ n = f->blocksize[m->blockflag];
+ map = &f->mapping[m->mapping];
+
+// FLOORS
+ n2 = n >> 1;
+
+ CHECK(f);
+
+ for (i=0; i < f->channels; ++i) {
+ int s = map->chan[i].mux, floor;
+ zero_channel[i] = FALSE;
+ floor = map->submap_floor[s];
+ if (f->floor_types[floor] == 0) {
+ return error(f, VORBIS_invalid_stream);
+ } else {
+ Floor1 *g = &f->floor_config[floor].floor1;
+ if (get_bits(f, 1)) {
+ short *finalY;
+ uint8 step2_flag[256];
+ static int range_list[4] = { 256, 128, 86, 64 };
+ int range = range_list[g->floor1_multiplier-1];
+ int offset = 2;
+ finalY = f->finalY[i];
+ finalY[0] = get_bits(f, ilog(range)-1);
+ finalY[1] = get_bits(f, ilog(range)-1);
+ for (j=0; j < g->partitions; ++j) {
+ int pclass = g->partition_class_list[j];
+ int cdim = g->class_dimensions[pclass];
+ int cbits = g->class_subclasses[pclass];
+ int csub = (1 << cbits)-1;
+ int cval = 0;
+ if (cbits) {
+ Codebook *c = f->codebooks + g->class_masterbooks[pclass];
+ DECODE(cval,f,c);
+ }
+ for (k=0; k < cdim; ++k) {
+ int book = g->subclass_books[pclass][cval & csub];
+ cval = cval >> cbits;
+ if (book >= 0) {
+ int temp;
+ Codebook *c = f->codebooks + book;
+ DECODE(temp,f,c);
+ finalY[offset++] = temp;
+ } else
+ finalY[offset++] = 0;
+ }
+ }
+ if (f->valid_bits == INVALID_BITS) goto error; // behavior according to spec
+ step2_flag[0] = step2_flag[1] = 1;
+ for (j=2; j < g->values; ++j) {
+ int low, high, pred, highroom, lowroom, room, val;
+ low = g->neighbors[j][0];
+ high = g->neighbors[j][1];
+ //neighbors(g->Xlist, j, &low, &high);
+ pred = predict_point(g->Xlist[j], g->Xlist[low], g->Xlist[high], finalY[low], finalY[high]);
+ val = finalY[j];
+ highroom = range - pred;
+ lowroom = pred;
+ if (highroom < lowroom)
+ room = highroom * 2;
+ else
+ room = lowroom * 2;
+ if (val) {
+ step2_flag[low] = step2_flag[high] = 1;
+ step2_flag[j] = 1;
+ if (val >= room)
+ if (highroom > lowroom)
+ finalY[j] = val - lowroom + pred;
+ else
+ finalY[j] = pred - val + highroom - 1;
+ else
+ if (val & 1)
+ finalY[j] = pred - ((val+1)>>1);
+ else
+ finalY[j] = pred + (val>>1);
+ } else {
+ step2_flag[j] = 0;
+ finalY[j] = pred;
+ }
+ }
+
+#ifdef STB_VORBIS_NO_DEFER_FLOOR
+ do_floor(f, map, i, n, f->floor_buffers[i], finalY, step2_flag);
+#else
+ // defer final floor computation until _after_ residue
+ for (j=0; j < g->values; ++j) {
+ if (!step2_flag[j])
+ finalY[j] = -1;
+ }
+#endif
+ } else {
+ error:
+ zero_channel[i] = TRUE;
+ }
+ // So we just defer everything else to later
+
+ // at this point we've decoded the floor into buffer
+ }
+ }
+ CHECK(f);
+ // at this point we've decoded all floors
+
+ if (f->alloc.alloc_buffer)
+ assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset);
+
+ // re-enable coupled channels if necessary
+ memcpy(really_zero_channel, zero_channel, sizeof(really_zero_channel[0]) * f->channels);
+ for (i=0; i < map->coupling_steps; ++i)
+ if (!zero_channel[map->chan[i].magnitude] || !zero_channel[map->chan[i].angle]) {
+ zero_channel[map->chan[i].magnitude] = zero_channel[map->chan[i].angle] = FALSE;
+ }
+
+ CHECK(f);
+// RESIDUE DECODE
+ for (i=0; i < map->submaps; ++i) {
+ float *residue_buffers[STB_VORBIS_MAX_CHANNELS];
+ int r;
+ uint8 do_not_decode[256];
+ int ch = 0;
+ for (j=0; j < f->channels; ++j) {
+ if (map->chan[j].mux == i) {
+ if (zero_channel[j]) {
+ do_not_decode[ch] = TRUE;
+ residue_buffers[ch] = NULL;
+ } else {
+ do_not_decode[ch] = FALSE;
+ residue_buffers[ch] = f->channel_buffers[j];
+ }
+ ++ch;
+ }
+ }
+ r = map->submap_residue[i];
+ decode_residue(f, residue_buffers, ch, n2, r, do_not_decode);
+ }
+
+ if (f->alloc.alloc_buffer)
+ assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset);
+ CHECK(f);
+
+// INVERSE COUPLING
+ for (i = map->coupling_steps-1; i >= 0; --i) {
+ int n2 = n >> 1;
+ float *m = f->channel_buffers[map->chan[i].magnitude];
+ float *a = f->channel_buffers[map->chan[i].angle ];
+ for (j=0; j < n2; ++j) {
+ float a2,m2;
+ if (m[j] > 0)
+ if (a[j] > 0)
+ m2 = m[j], a2 = m[j] - a[j];
+ else
+ a2 = m[j], m2 = m[j] + a[j];
+ else
+ if (a[j] > 0)
+ m2 = m[j], a2 = m[j] + a[j];
+ else
+ a2 = m[j], m2 = m[j] - a[j];
+ m[j] = m2;
+ a[j] = a2;
+ }
+ }
+ CHECK(f);
+
+ // finish decoding the floors
+#ifndef STB_VORBIS_NO_DEFER_FLOOR
+ for (i=0; i < f->channels; ++i) {
+ if (really_zero_channel[i]) {
+ memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2);
+ } else {
+ do_floor(f, map, i, n, f->channel_buffers[i], f->finalY[i], NULL);
+ }
+ }
+#else
+ for (i=0; i < f->channels; ++i) {
+ if (really_zero_channel[i]) {
+ memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2);
+ } else {
+ for (j=0; j < n2; ++j)
+ f->channel_buffers[i][j] *= f->floor_buffers[i][j];
+ }
+ }
+#endif
+
+// INVERSE MDCT
+ CHECK(f);
+ for (i=0; i < f->channels; ++i)
+ inverse_mdct(f->channel_buffers[i], n, f, m->blockflag);
+ CHECK(f);
+
+ // this shouldn't be necessary, unless we exited on an error
+ // and want to flush to get to the next packet
+ flush_packet(f);
+
+ if (f->first_decode) {
+ // assume we start so first non-discarded sample is sample 0
+ // this isn't to spec, but spec would require us to read ahead
+ // and decode the size of all current frames--could be done,
+ // but presumably it's not a commonly used feature
+ f->current_loc = -n2; // start of first frame is positioned for discard
+ // we might have to discard samples "from" the next frame too,
+ // if we're lapping a large block then a small at the start?
+ f->discard_samples_deferred = n - right_end;
+ f->current_loc_valid = TRUE;
+ f->first_decode = FALSE;
+ } else if (f->discard_samples_deferred) {
+ if (f->discard_samples_deferred >= right_start - left_start) {
+ f->discard_samples_deferred -= (right_start - left_start);
+ left_start = right_start;
+ *p_left = left_start;
+ } else {
+ left_start += f->discard_samples_deferred;
+ *p_left = left_start;
+ f->discard_samples_deferred = 0;
+ }
+ } else if (f->previous_length == 0 && f->current_loc_valid) {
+ // we're recovering from a seek... that means we're going to discard
+ // the samples from this packet even though we know our position from
+ // the last page header, so we need to update the position based on
+ // the discarded samples here
+ // but wait, the code below is going to add this in itself even
+ // on a discard, so we don't need to do it here...
+ }
+
+ // check if we have ogg information about the sample # for this packet
+ if (f->last_seg_which == f->end_seg_with_known_loc) {
+ // if we have a valid current loc, and this is final:
+ if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) {
+ uint32 current_end = f->known_loc_for_packet - (n-right_end);
+ // then let's infer the size of the (probably) short final frame
+ if (current_end < f->current_loc + (right_end-left_start)) {
+ if (current_end < f->current_loc) {
+ // negative truncation, that's impossible!
+ *len = 0;
+ } else {
+ *len = current_end - f->current_loc;
+ }
+ *len += left_start;
+ if (*len > right_end) *len = right_end; // this should never happen
+ f->current_loc += *len;
+ return TRUE;
+ }
+ }
+ // otherwise, just set our sample loc
+ // guess that the ogg granule pos refers to the _middle_ of the
+ // last frame?
+ // set f->current_loc to the position of left_start
+ f->current_loc = f->known_loc_for_packet - (n2-left_start);
+ f->current_loc_valid = TRUE;
+ }
+ if (f->current_loc_valid)
+ f->current_loc += (right_start - left_start);
+
+ if (f->alloc.alloc_buffer)
+ assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset);
+ *len = right_end; // ignore samples after the window goes to 0
+ CHECK(f);
+
+ return TRUE;
+}
+
+static int vorbis_decode_packet(vorb *f, int *len, int *p_left, int *p_right)
+{
+ int mode, left_end, right_end;
+ if (!vorbis_decode_initial(f, p_left, &left_end, p_right, &right_end, &mode)) return 0;
+ return vorbis_decode_packet_rest(f, len, f->mode_config + mode, *p_left, left_end, *p_right, right_end, p_left);
+}
+
+static int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right)
+{
+ int prev,i,j;
+ // we use right&left (the start of the right- and left-window sin()-regions)
+ // to determine how much to return, rather than inferring from the rules
+ // (same result, clearer code); 'left' indicates where our sin() window
+ // starts, therefore where the previous window's right edge starts, and
+ // therefore where to start mixing from the previous buffer. 'right'
+ // indicates where our sin() ending-window starts, therefore that's where
+ // we start saving, and where our returned-data ends.
+
+ // mixin from previous window
+ if (f->previous_length) {
+ int i,j, n = f->previous_length;
+ float *w = get_window(f, n);
+ for (i=0; i < f->channels; ++i) {
+ for (j=0; j < n; ++j)
+ f->channel_buffers[i][left+j] =
+ f->channel_buffers[i][left+j]*w[ j] +
+ f->previous_window[i][ j]*w[n-1-j];
+ }
+ }
+
+ prev = f->previous_length;
+
+ // last half of this data becomes previous window
+ f->previous_length = len - right;
+
+ // @OPTIMIZE: could avoid this copy by double-buffering the
+ // output (flipping previous_window with channel_buffers), but
+ // then previous_window would have to be 2x as large, and
+ // channel_buffers couldn't be temp mem (although they're NOT
+ // currently temp mem, they could be (unless we want to level
+ // performance by spreading out the computation))
+ for (i=0; i < f->channels; ++i)
+ for (j=0; right+j < len; ++j)
+ f->previous_window[i][j] = f->channel_buffers[i][right+j];
+
+ if (!prev)
+ // there was no previous packet, so this data isn't valid...
+ // this isn't entirely true, only the would-have-overlapped data
+ // isn't valid, but this seems to be what the spec requires
+ return 0;
+
+ // truncate a short frame
+ if (len < right) right = len;
+
+ f->samples_output += right-left;
+
+ return right - left;
+}
+
+static void vorbis_pump_first_frame(stb_vorbis *f)
+{
+ int len, right, left;
+ if (vorbis_decode_packet(f, &len, &left, &right))
+ vorbis_finish_frame(f, len, left, right);
+}
+
+#ifndef STB_VORBIS_NO_PUSHDATA_API
+static int is_whole_packet_present(stb_vorbis *f, int end_page)
+{
+ // make sure that we have the packet available before continuing...
+ // this requires a full ogg parse, but we know we can fetch from f->stream
+
+ // instead of coding this out explicitly, we could save the current read state,
+ // read the next packet with get8() until end-of-packet, check f->eof, then
+ // reset the state? but that would be slower, esp. since we'd have over 256 bytes
+ // of state to restore (primarily the page segment table)
+
+ int s = f->next_seg, first = TRUE;
+ uint8 *p = f->stream;
+
+ if (s != -1) { // if we're not starting the packet with a 'continue on next page' flag
+ for (; s < f->segment_count; ++s) {
+ p += f->segments[s];
+ if (f->segments[s] < 255) // stop at first short segment
+ break;
+ }
+ // either this continues, or it ends it...
+ if (end_page)
+ if (s < f->segment_count-1) return error(f, VORBIS_invalid_stream);
+ if (s == f->segment_count)
+ s = -1; // set 'crosses page' flag
+ if (p > f->stream_end) return error(f, VORBIS_need_more_data);
+ first = FALSE;
+ }
+ for (; s == -1;) {
+ uint8 *q;
+ int n;
+
+ // check that we have the page header ready
+ if (p + 26 >= f->stream_end) return error(f, VORBIS_need_more_data);
+ // validate the page
+ if (memcmp(p, ogg_page_header, 4)) return error(f, VORBIS_invalid_stream);
+ if (p[4] != 0) return error(f, VORBIS_invalid_stream);
+ if (first) { // the first segment must NOT have 'continued_packet', later ones MUST
+ if (f->previous_length)
+ if ((p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream);
+ // if no previous length, we're resynching, so we can come in on a continued-packet,
+ // which we'll just drop
+ } else {
+ if (!(p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream);
+ }
+ n = p[26]; // segment counts
+ q = p+27; // q points to segment table
+ p = q + n; // advance past header
+ // make sure we've read the segment table
+ if (p > f->stream_end) return error(f, VORBIS_need_more_data);
+ for (s=0; s < n; ++s) {
+ p += q[s];
+ if (q[s] < 255)
+ break;
+ }
+ if (end_page)
+ if (s < n-1) return error(f, VORBIS_invalid_stream);
+ if (s == n)
+ s = -1; // set 'crosses page' flag
+ if (p > f->stream_end) return error(f, VORBIS_need_more_data);
+ first = FALSE;
+ }
+ return TRUE;
+}
+#endif // !STB_VORBIS_NO_PUSHDATA_API
+
+static int start_decoder(vorb *f)
+{
+ uint8 header[6], x,y;
+ int len,i,j,k, max_submaps = 0;
+ int longest_floorlist=0;
+
+ // first page, first packet
+
+ if (!start_page(f)) return FALSE;
+ // validate page flag
+ if (!(f->page_flag & PAGEFLAG_first_page)) return error(f, VORBIS_invalid_first_page);
+ if (f->page_flag & PAGEFLAG_last_page) return error(f, VORBIS_invalid_first_page);
+ if (f->page_flag & PAGEFLAG_continued_packet) return error(f, VORBIS_invalid_first_page);
+ // check for expected packet length
+ if (f->segment_count != 1) return error(f, VORBIS_invalid_first_page);
+ if (f->segments[0] != 30) return error(f, VORBIS_invalid_first_page);
+ // read packet
+ // check packet header
+ if (get8(f) != VORBIS_packet_id) return error(f, VORBIS_invalid_first_page);
+ if (!getn(f, header, 6)) return error(f, VORBIS_unexpected_eof);
+ if (!vorbis_validate(header)) return error(f, VORBIS_invalid_first_page);
+ // vorbis_version
+ if (get32(f) != 0) return error(f, VORBIS_invalid_first_page);
+ f->channels = get8(f); if (!f->channels) return error(f, VORBIS_invalid_first_page);
+ if (f->channels > STB_VORBIS_MAX_CHANNELS) return error(f, VORBIS_too_many_channels);
+ f->sample_rate = get32(f); if (!f->sample_rate) return error(f, VORBIS_invalid_first_page);
+ get32(f); // bitrate_maximum
+ get32(f); // bitrate_nominal
+ get32(f); // bitrate_minimum
+ x = get8(f);
+ {
+ int log0,log1;
+ log0 = x & 15;
+ log1 = x >> 4;
+ f->blocksize_0 = 1 << log0;
+ f->blocksize_1 = 1 << log1;
+ if (log0 < 6 || log0 > 13) return error(f, VORBIS_invalid_setup);
+ if (log1 < 6 || log1 > 13) return error(f, VORBIS_invalid_setup);
+ if (log0 > log1) return error(f, VORBIS_invalid_setup);
+ }
+
+ // framing_flag
+ x = get8(f);
+ if (!(x & 1)) return error(f, VORBIS_invalid_first_page);
+
+ // second packet!
+ if (!start_page(f)) return FALSE;
+
+ if (!start_packet(f)) return FALSE;
+ do {
+ len = next_segment(f);
+ skip(f, len);
+ f->bytes_in_seg = 0;
+ } while (len);
+
+ // third packet!
+ if (!start_packet(f)) return FALSE;
+
+ #ifndef STB_VORBIS_NO_PUSHDATA_API
+ if (IS_PUSH_MODE(f)) {
+ if (!is_whole_packet_present(f, TRUE)) {
+ // convert error in ogg header to write type
+ if (f->error == VORBIS_invalid_stream)
+ f->error = VORBIS_invalid_setup;
+ return FALSE;
+ }
+ }
+ #endif
+
+ crc32_init(); // always init it, to avoid multithread race conditions
+
+ if (get8_packet(f) != VORBIS_packet_setup) return error(f, VORBIS_invalid_setup);
+ for (i=0; i < 6; ++i) header[i] = get8_packet(f);
+ if (!vorbis_validate(header)) return error(f, VORBIS_invalid_setup);
+
+ // codebooks
+
+ f->codebook_count = get_bits(f,8) + 1;
+ f->codebooks = (Codebook *) setup_malloc(f, sizeof(*f->codebooks) * f->codebook_count);
+ if (f->codebooks == NULL) return error(f, VORBIS_outofmem);
+ memset(f->codebooks, 0, sizeof(*f->codebooks) * f->codebook_count);
+ for (i=0; i < f->codebook_count; ++i) {
+ uint32 *values;
+ int ordered, sorted_count;
+ int total=0;
+ uint8 *lengths;
+ Codebook *c = f->codebooks+i;
+ CHECK(f);
+ x = get_bits(f, 8); if (x != 0x42) return error(f, VORBIS_invalid_setup);
+ x = get_bits(f, 8); if (x != 0x43) return error(f, VORBIS_invalid_setup);
+ x = get_bits(f, 8); if (x != 0x56) return error(f, VORBIS_invalid_setup);
+ x = get_bits(f, 8);
+ c->dimensions = (get_bits(f, 8)<<8) + x;
+ x = get_bits(f, 8);
+ y = get_bits(f, 8);
+ c->entries = (get_bits(f, 8)<<16) + (y<<8) + x;
+ ordered = get_bits(f,1);
+ c->sparse = ordered ? 0 : get_bits(f,1);
+
+ if (c->dimensions == 0 && c->entries != 0) return error(f, VORBIS_invalid_setup);
+
+ if (c->sparse)
+ lengths = (uint8 *) setup_temp_malloc(f, c->entries);
+ else
+ lengths = c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries);
+
+ if (!lengths) return error(f, VORBIS_outofmem);
+
+ if (ordered) {
+ int current_entry = 0;
+ int current_length = get_bits(f,5) + 1;
+ while (current_entry < c->entries) {
+ int limit = c->entries - current_entry;
+ int n = get_bits(f, ilog(limit));
+ if (current_entry + n > (int) c->entries) { return error(f, VORBIS_invalid_setup); }
+ memset(lengths + current_entry, current_length, n);
+ current_entry += n;
+ ++current_length;
+ }
+ } else {
+ for (j=0; j < c->entries; ++j) {
+ int present = c->sparse ? get_bits(f,1) : 1;
+ if (present) {
+ lengths[j] = get_bits(f, 5) + 1;
+ ++total;
+ if (lengths[j] == 32)
+ return error(f, VORBIS_invalid_setup);
+ } else {
+ lengths[j] = NO_CODE;
+ }
+ }
+ }
+
+ if (c->sparse && total >= c->entries >> 2) {
+ // convert sparse items to non-sparse!
+ if (c->entries > (int) f->setup_temp_memory_required)
+ f->setup_temp_memory_required = c->entries;
+
+ c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries);
+ if (c->codeword_lengths == NULL) return error(f, VORBIS_outofmem);
+ memcpy(c->codeword_lengths, lengths, c->entries);
+ setup_temp_free(f, lengths, c->entries); // note this is only safe if there have been no intervening temp mallocs!
+ lengths = c->codeword_lengths;
+ c->sparse = 0;
+ }
+
+ // compute the size of the sorted tables
+ if (c->sparse) {
+ sorted_count = total;
+ } else {
+ sorted_count = 0;
+ #ifndef STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH
+ for (j=0; j < c->entries; ++j)
+ if (lengths[j] > STB_VORBIS_FAST_HUFFMAN_LENGTH && lengths[j] != NO_CODE)
+ ++sorted_count;
+ #endif
+ }
+
+ c->sorted_entries = sorted_count;
+ values = NULL;
+
+ CHECK(f);
+ if (!c->sparse) {
+ c->codewords = (uint32 *) setup_malloc(f, sizeof(c->codewords[0]) * c->entries);
+ if (!c->codewords) return error(f, VORBIS_outofmem);
+ } else {
+ unsigned int size;
+ if (c->sorted_entries) {
+ c->codeword_lengths = (uint8 *) setup_malloc(f, c->sorted_entries);
+ if (!c->codeword_lengths) return error(f, VORBIS_outofmem);
+ c->codewords = (uint32 *) setup_temp_malloc(f, sizeof(*c->codewords) * c->sorted_entries);
+ if (!c->codewords) return error(f, VORBIS_outofmem);
+ values = (uint32 *) setup_temp_malloc(f, sizeof(*values) * c->sorted_entries);
+ if (!values) return error(f, VORBIS_outofmem);
+ }
+ size = c->entries + (sizeof(*c->codewords) + sizeof(*values)) * c->sorted_entries;
+ if (size > f->setup_temp_memory_required)
+ f->setup_temp_memory_required = size;
+ }
+
+ if (!compute_codewords(c, lengths, c->entries, values)) {
+ if (c->sparse) setup_temp_free(f, values, 0);
+ return error(f, VORBIS_invalid_setup);
+ }
+
+ if (c->sorted_entries) {
+ // allocate an extra slot for sentinels
+ c->sorted_codewords = (uint32 *) setup_malloc(f, sizeof(*c->sorted_codewords) * (c->sorted_entries+1));
+ if (c->sorted_codewords == NULL) return error(f, VORBIS_outofmem);
+ // allocate an extra slot at the front so that c->sorted_values[-1] is defined
+ // so that we can catch that case without an extra if
+ c->sorted_values = ( int *) setup_malloc(f, sizeof(*c->sorted_values ) * (c->sorted_entries+1));
+ if (c->sorted_values == NULL) return error(f, VORBIS_outofmem);
+ ++c->sorted_values;
+ c->sorted_values[-1] = -1;
+ compute_sorted_huffman(c, lengths, values);
+ }
+
+ if (c->sparse) {
+ setup_temp_free(f, values, sizeof(*values)*c->sorted_entries);
+ setup_temp_free(f, c->codewords, sizeof(*c->codewords)*c->sorted_entries);
+ setup_temp_free(f, lengths, c->entries);
+ c->codewords = NULL;
+ }
+
+ compute_accelerated_huffman(c);
+
+ CHECK(f);
+ c->lookup_type = get_bits(f, 4);
+ if (c->lookup_type > 2) return error(f, VORBIS_invalid_setup);
+ if (c->lookup_type > 0) {
+ uint16 *mults;
+ c->minimum_value = float32_unpack(get_bits(f, 32));
+ c->delta_value = float32_unpack(get_bits(f, 32));
+ c->value_bits = get_bits(f, 4)+1;
+ c->sequence_p = get_bits(f,1);
+ if (c->lookup_type == 1) {
+ c->lookup_values = lookup1_values(c->entries, c->dimensions);
+ } else {
+ c->lookup_values = c->entries * c->dimensions;
+ }
+ if (c->lookup_values == 0) return error(f, VORBIS_invalid_setup);
+ mults = (uint16 *) setup_temp_malloc(f, sizeof(mults[0]) * c->lookup_values);
+ if (mults == NULL) return error(f, VORBIS_outofmem);
+ for (j=0; j < (int) c->lookup_values; ++j) {
+ int q = get_bits(f, c->value_bits);
+ if (q == EOP) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_invalid_setup); }
+ mults[j] = q;
+ }
+
+#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
+ if (c->lookup_type == 1) {
+ int len, sparse = c->sparse;
+ float last=0;
+ // pre-expand the lookup1-style multiplicands, to avoid a divide in the inner loop
+ if (sparse) {
+ if (c->sorted_entries == 0) goto skip;
+ c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->sorted_entries * c->dimensions);
+ } else
+ c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->entries * c->dimensions);
+ if (c->multiplicands == NULL) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); }
+ len = sparse ? c->sorted_entries : c->entries;
+ for (j=0; j < len; ++j) {
+ unsigned int z = sparse ? c->sorted_values[j] : j;
+ unsigned int div=1;
+ for (k=0; k < c->dimensions; ++k) {
+ int off = (z / div) % c->lookup_values;
+ float val = mults[off];
+ val = mults[off]*c->delta_value + c->minimum_value + last;
+ c->multiplicands[j*c->dimensions + k] = val;
+ if (c->sequence_p)
+ last = val;
+ if (k+1 < c->dimensions) {
+ if (div > UINT_MAX / (unsigned int) c->lookup_values) {
+ setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values);
+ return error(f, VORBIS_invalid_setup);
+ }
+ div *= c->lookup_values;
+ }
+ }
+ }
+ c->lookup_type = 2;
+ }
+ else
+#endif
+ {
+ float last=0;
+ CHECK(f);
+ c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values);
+ if (c->multiplicands == NULL) { setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); }
+ for (j=0; j < (int) c->lookup_values; ++j) {
+ float val = mults[j] * c->delta_value + c->minimum_value + last;
+ c->multiplicands[j] = val;
+ if (c->sequence_p)
+ last = val;
+ }
+ }
+#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
+ skip:;
+#endif
+ setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values);
+
+ CHECK(f);
+ }
+ CHECK(f);
+ }
+
+ // time domain transfers (notused)
+
+ x = get_bits(f, 6) + 1;
+ for (i=0; i < x; ++i) {
+ uint32 z = get_bits(f, 16);
+ if (z != 0) return error(f, VORBIS_invalid_setup);
+ }
+
+ // Floors
+ f->floor_count = get_bits(f, 6)+1;
+ f->floor_config = (Floor *) setup_malloc(f, f->floor_count * sizeof(*f->floor_config));
+ if (f->floor_config == NULL) return error(f, VORBIS_outofmem);
+ for (i=0; i < f->floor_count; ++i) {
+ f->floor_types[i] = get_bits(f, 16);
+ if (f->floor_types[i] > 1) return error(f, VORBIS_invalid_setup);
+ if (f->floor_types[i] == 0) {
+ Floor0 *g = &f->floor_config[i].floor0;
+ g->order = get_bits(f,8);
+ g->rate = get_bits(f,16);
+ g->bark_map_size = get_bits(f,16);
+ g->amplitude_bits = get_bits(f,6);
+ g->amplitude_offset = get_bits(f,8);
+ g->number_of_books = get_bits(f,4) + 1;
+ for (j=0; j < g->number_of_books; ++j)
+ g->book_list[j] = get_bits(f,8);
+ return error(f, VORBIS_feature_not_supported);
+ } else {
+ Point p[31*8+2];
+ Floor1 *g = &f->floor_config[i].floor1;
+ int max_class = -1;
+ g->partitions = get_bits(f, 5);
+ for (j=0; j < g->partitions; ++j) {
+ g->partition_class_list[j] = get_bits(f, 4);
+ if (g->partition_class_list[j] > max_class)
+ max_class = g->partition_class_list[j];
+ }
+ for (j=0; j <= max_class; ++j) {
+ g->class_dimensions[j] = get_bits(f, 3)+1;
+ g->class_subclasses[j] = get_bits(f, 2);
+ if (g->class_subclasses[j]) {
+ g->class_masterbooks[j] = get_bits(f, 8);
+ if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup);
+ }
+ for (k=0; k < 1 << g->class_subclasses[j]; ++k) {
+ g->subclass_books[j][k] = get_bits(f,8)-1;
+ if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup);
+ }
+ }
+ g->floor1_multiplier = get_bits(f,2)+1;
+ g->rangebits = get_bits(f,4);
+ g->Xlist[0] = 0;
+ g->Xlist[1] = 1 << g->rangebits;
+ g->values = 2;
+ for (j=0; j < g->partitions; ++j) {
+ int c = g->partition_class_list[j];
+ for (k=0; k < g->class_dimensions[c]; ++k) {
+ g->Xlist[g->values] = get_bits(f, g->rangebits);
+ ++g->values;
+ }
+ }
+ // precompute the sorting
+ for (j=0; j < g->values; ++j) {
+ p[j].x = g->Xlist[j];
+ p[j].y = j;
+ }
+ qsort(p, g->values, sizeof(p[0]), point_compare);
+ for (j=0; j < g->values; ++j)
+ g->sorted_order[j] = (uint8) p[j].y;
+ // precompute the neighbors
+ for (j=2; j < g->values; ++j) {
+ int low,hi;
+ neighbors(g->Xlist, j, &low,&hi);
+ g->neighbors[j][0] = low;
+ g->neighbors[j][1] = hi;
+ }
+
+ if (g->values > longest_floorlist)
+ longest_floorlist = g->values;
+ }
+ }
+
+ // Residue
+ f->residue_count = get_bits(f, 6)+1;
+ f->residue_config = (Residue *) setup_malloc(f, f->residue_count * sizeof(f->residue_config[0]));
+ if (f->residue_config == NULL) return error(f, VORBIS_outofmem);
+ memset(f->residue_config, 0, f->residue_count * sizeof(f->residue_config[0]));
+ for (i=0; i < f->residue_count; ++i) {
+ uint8 residue_cascade[64];
+ Residue *r = f->residue_config+i;
+ f->residue_types[i] = get_bits(f, 16);
+ if (f->residue_types[i] > 2) return error(f, VORBIS_invalid_setup);
+ r->begin = get_bits(f, 24);
+ r->end = get_bits(f, 24);
+ if (r->end < r->begin) return error(f, VORBIS_invalid_setup);
+ r->part_size = get_bits(f,24)+1;
+ r->classifications = get_bits(f,6)+1;
+ r->classbook = get_bits(f,8);
+ if (r->classbook >= f->codebook_count) return error(f, VORBIS_invalid_setup);
+ for (j=0; j < r->classifications; ++j) {
+ uint8 high_bits=0;
+ uint8 low_bits=get_bits(f,3);
+ if (get_bits(f,1))
+ high_bits = get_bits(f,5);
+ residue_cascade[j] = high_bits*8 + low_bits;
+ }
+ r->residue_books = (short (*)[8]) setup_malloc(f, sizeof(r->residue_books[0]) * r->classifications);
+ if (r->residue_books == NULL) return error(f, VORBIS_outofmem);
+ for (j=0; j < r->classifications; ++j) {
+ for (k=0; k < 8; ++k) {
+ if (residue_cascade[j] & (1 << k)) {
+ r->residue_books[j][k] = get_bits(f, 8);
+ if (r->residue_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup);
+ } else {
+ r->residue_books[j][k] = -1;
+ }
+ }
+ }
+ // precompute the classifications[] array to avoid inner-loop mod/divide
+ // call it 'classdata' since we already have r->classifications
+ r->classdata = (uint8 **) setup_malloc(f, sizeof(*r->classdata) * f->codebooks[r->classbook].entries);
+ if (!r->classdata) return error(f, VORBIS_outofmem);
+ memset(r->classdata, 0, sizeof(*r->classdata) * f->codebooks[r->classbook].entries);
+ for (j=0; j < f->codebooks[r->classbook].entries; ++j) {
+ int classwords = f->codebooks[r->classbook].dimensions;
+ int temp = j;
+ r->classdata[j] = (uint8 *) setup_malloc(f, sizeof(r->classdata[j][0]) * classwords);
+ if (r->classdata[j] == NULL) return error(f, VORBIS_outofmem);
+ for (k=classwords-1; k >= 0; --k) {
+ r->classdata[j][k] = temp % r->classifications;
+ temp /= r->classifications;
+ }
+ }
+ }
+
+ f->mapping_count = get_bits(f,6)+1;
+ f->mapping = (Mapping *) setup_malloc(f, f->mapping_count * sizeof(*f->mapping));
+ if (f->mapping == NULL) return error(f, VORBIS_outofmem);
+ memset(f->mapping, 0, f->mapping_count * sizeof(*f->mapping));
+ for (i=0; i < f->mapping_count; ++i) {
+ Mapping *m = f->mapping + i;
+ int mapping_type = get_bits(f,16);
+ if (mapping_type != 0) return error(f, VORBIS_invalid_setup);
+ m->chan = (MappingChannel *) setup_malloc(f, f->channels * sizeof(*m->chan));
+ if (m->chan == NULL) return error(f, VORBIS_outofmem);
+ if (get_bits(f,1))
+ m->submaps = get_bits(f,4)+1;
+ else
+ m->submaps = 1;
+ if (m->submaps > max_submaps)
+ max_submaps = m->submaps;
+ if (get_bits(f,1)) {
+ m->coupling_steps = get_bits(f,8)+1;
+ for (k=0; k < m->coupling_steps; ++k) {
+ m->chan[k].magnitude = get_bits(f, ilog(f->channels-1));
+ m->chan[k].angle = get_bits(f, ilog(f->channels-1));
+ if (m->chan[k].magnitude >= f->channels) return error(f, VORBIS_invalid_setup);
+ if (m->chan[k].angle >= f->channels) return error(f, VORBIS_invalid_setup);
+ if (m->chan[k].magnitude == m->chan[k].angle) return error(f, VORBIS_invalid_setup);
+ }
+ } else
+ m->coupling_steps = 0;
+
+ // reserved field
+ if (get_bits(f,2)) return error(f, VORBIS_invalid_setup);
+ if (m->submaps > 1) {
+ for (j=0; j < f->channels; ++j) {
+ m->chan[j].mux = get_bits(f, 4);
+ if (m->chan[j].mux >= m->submaps) return error(f, VORBIS_invalid_setup);
+ }
+ } else
+ // @SPECIFICATION: this case is missing from the spec
+ for (j=0; j < f->channels; ++j)
+ m->chan[j].mux = 0;
+
+ for (j=0; j < m->submaps; ++j) {
+ get_bits(f,8); // discard
+ m->submap_floor[j] = get_bits(f,8);
+ m->submap_residue[j] = get_bits(f,8);
+ if (m->submap_floor[j] >= f->floor_count) return error(f, VORBIS_invalid_setup);
+ if (m->submap_residue[j] >= f->residue_count) return error(f, VORBIS_invalid_setup);
+ }
+ }
+
+ // Modes
+ f->mode_count = get_bits(f, 6)+1;
+ for (i=0; i < f->mode_count; ++i) {
+ Mode *m = f->mode_config+i;
+ m->blockflag = get_bits(f,1);
+ m->windowtype = get_bits(f,16);
+ m->transformtype = get_bits(f,16);
+ m->mapping = get_bits(f,8);
+ if (m->windowtype != 0) return error(f, VORBIS_invalid_setup);
+ if (m->transformtype != 0) return error(f, VORBIS_invalid_setup);
+ if (m->mapping >= f->mapping_count) return error(f, VORBIS_invalid_setup);
+ }
+
+ flush_packet(f);
+
+ f->previous_length = 0;
+
+ for (i=0; i < f->channels; ++i) {
+ f->channel_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1);
+ f->previous_window[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2);
+ f->finalY[i] = (int16 *) setup_malloc(f, sizeof(int16) * longest_floorlist);
+ if (f->channel_buffers[i] == NULL || f->previous_window[i] == NULL || f->finalY[i] == NULL) return error(f, VORBIS_outofmem);
+ #ifdef STB_VORBIS_NO_DEFER_FLOOR
+ f->floor_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2);
+ if (f->floor_buffers[i] == NULL) return error(f, VORBIS_outofmem);
+ #endif
+ }
+
+ if (!init_blocksize(f, 0, f->blocksize_0)) return FALSE;
+ if (!init_blocksize(f, 1, f->blocksize_1)) return FALSE;
+ f->blocksize[0] = f->blocksize_0;
+ f->blocksize[1] = f->blocksize_1;
+
+#ifdef STB_VORBIS_DIVIDE_TABLE
+ if (integer_divide_table[1][1]==0)
+ for (i=0; i < DIVTAB_NUMER; ++i)
+ for (j=1; j < DIVTAB_DENOM; ++j)
+ integer_divide_table[i][j] = i / j;
+#endif
+
+ // compute how much temporary memory is needed
+
+ // 1.
+ {
+ uint32 imdct_mem = (f->blocksize_1 * sizeof(float) >> 1);
+ uint32 classify_mem;
+ int i,max_part_read=0;
+ for (i=0; i < f->residue_count; ++i) {
+ Residue *r = f->residue_config + i;
+ int n_read = r->end - r->begin;
+ int part_read = n_read / r->part_size;
+ if (part_read > max_part_read)
+ max_part_read = part_read;
+ }
+ #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
+ classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(uint8 *));
+ #else
+ classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *));
+ #endif
+
+ f->temp_memory_required = classify_mem;
+ if (imdct_mem > f->temp_memory_required)
+ f->temp_memory_required = imdct_mem;
+ }
+
+ f->first_decode = TRUE;
+
+ if (f->alloc.alloc_buffer) {
+ assert(f->temp_offset == f->alloc.alloc_buffer_length_in_bytes);
+ // check if there's enough temp memory so we don't error later
+ if (f->setup_offset + sizeof(*f) + f->temp_memory_required > (unsigned) f->temp_offset)
+ return error(f, VORBIS_outofmem);
+ }
+
+ f->first_audio_page_offset = stb_vorbis_get_file_offset(f);
+
+ return TRUE;
+}
+
+static void vorbis_deinit(stb_vorbis *p)
+{
+ int i,j;
+ if (p->residue_config) {
+ for (i=0; i < p->residue_count; ++i) {
+ Residue *r = p->residue_config+i;
+ if (r->classdata) {
+ for (j=0; j < p->codebooks[r->classbook].entries; ++j)
+ setup_free(p, r->classdata[j]);
+ setup_free(p, r->classdata);
+ }
+ setup_free(p, r->residue_books);
+ }
+ }
+
+ if (p->codebooks) {
+ CHECK(p);
+ for (i=0; i < p->codebook_count; ++i) {
+ Codebook *c = p->codebooks + i;
+ setup_free(p, c->codeword_lengths);
+ setup_free(p, c->multiplicands);
+ setup_free(p, c->codewords);
+ setup_free(p, c->sorted_codewords);
+ // c->sorted_values[-1] is the first entry in the array
+ setup_free(p, c->sorted_values ? c->sorted_values-1 : NULL);
+ }
+ setup_free(p, p->codebooks);
+ }
+ setup_free(p, p->floor_config);
+ setup_free(p, p->residue_config);
+ if (p->mapping) {
+ for (i=0; i < p->mapping_count; ++i)
+ setup_free(p, p->mapping[i].chan);
+ setup_free(p, p->mapping);
+ }
+ CHECK(p);
+ for (i=0; i < p->channels && i < STB_VORBIS_MAX_CHANNELS; ++i) {
+ setup_free(p, p->channel_buffers[i]);
+ setup_free(p, p->previous_window[i]);
+ #ifdef STB_VORBIS_NO_DEFER_FLOOR
+ setup_free(p, p->floor_buffers[i]);
+ #endif
+ setup_free(p, p->finalY[i]);
+ }
+ for (i=0; i < 2; ++i) {
+ setup_free(p, p->A[i]);
+ setup_free(p, p->B[i]);
+ setup_free(p, p->C[i]);
+ setup_free(p, p->window[i]);
+ setup_free(p, p->bit_reverse[i]);
+ }
+ #ifndef STB_VORBIS_NO_STDIO
+ if (p->close_on_free) fclose(p->f);
+ #endif
+}
+
+void stb_vorbis_close(stb_vorbis *p)
+{
+ if (p == NULL) return;
+ vorbis_deinit(p);
+ setup_free(p,p);
+}
+
+static void vorbis_init(stb_vorbis *p, const stb_vorbis_alloc *z)
+{
+ memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start
+ if (z) {
+ p->alloc = *z;
+ p->alloc.alloc_buffer_length_in_bytes = (p->alloc.alloc_buffer_length_in_bytes+3) & ~3;
+ p->temp_offset = p->alloc.alloc_buffer_length_in_bytes;
+ }
+ p->eof = 0;
+ p->error = VORBIS__no_error;
+ p->stream = NULL;
+ p->codebooks = NULL;
+ p->page_crc_tests = -1;
+ #ifndef STB_VORBIS_NO_STDIO
+ p->close_on_free = FALSE;
+ p->f = NULL;
+ #endif
+}
+
+int stb_vorbis_get_sample_offset(stb_vorbis *f)
+{
+ if (f->current_loc_valid)
+ return f->current_loc;
+ else
+ return -1;
+}
+
+stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f)
+{
+ stb_vorbis_info d;
+ d.channels = f->channels;
+ d.sample_rate = f->sample_rate;
+ d.setup_memory_required = f->setup_memory_required;
+ d.setup_temp_memory_required = f->setup_temp_memory_required;
+ d.temp_memory_required = f->temp_memory_required;
+ d.max_frame_size = f->blocksize_1 >> 1;
+ return d;
+}
+
+int stb_vorbis_get_error(stb_vorbis *f)
+{
+ int e = f->error;
+ f->error = VORBIS__no_error;
+ return e;
+}
+
+static stb_vorbis * vorbis_alloc(stb_vorbis *f)
+{
+ stb_vorbis *p = (stb_vorbis *) setup_malloc(f, sizeof(*p));
+ return p;
+}
+
+#ifndef STB_VORBIS_NO_PUSHDATA_API
+
+void stb_vorbis_flush_pushdata(stb_vorbis *f)
+{
+ f->previous_length = 0;
+ f->page_crc_tests = 0;
+ f->discard_samples_deferred = 0;
+ f->current_loc_valid = FALSE;
+ f->first_decode = FALSE;
+ f->samples_output = 0;
+ f->channel_buffer_start = 0;
+ f->channel_buffer_end = 0;
+}
+
+static int vorbis_search_for_page_pushdata(vorb *f, uint8 *data, int data_len)
+{
+ int i,n;
+ for (i=0; i < f->page_crc_tests; ++i)
+ f->scan[i].bytes_done = 0;
+
+ // if we have room for more scans, search for them first, because
+ // they may cause us to stop early if their header is incomplete
+ if (f->page_crc_tests < STB_VORBIS_PUSHDATA_CRC_COUNT) {
+ if (data_len < 4) return 0;
+ data_len -= 3; // need to look for 4-byte sequence, so don't miss
+ // one that straddles a boundary
+ for (i=0; i < data_len; ++i) {
+ if (data[i] == 0x4f) {
+ if (0==memcmp(data+i, ogg_page_header, 4)) {
+ int j,len;
+ uint32 crc;
+ // make sure we have the whole page header
+ if (i+26 >= data_len || i+27+data[i+26] >= data_len) {
+ // only read up to this page start, so hopefully we'll
+ // have the whole page header start next time
+ data_len = i;
+ break;
+ }
+ // ok, we have it all; compute the length of the page
+ len = 27 + data[i+26];
+ for (j=0; j < data[i+26]; ++j)
+ len += data[i+27+j];
+ // scan everything up to the embedded crc (which we must 0)
+ crc = 0;
+ for (j=0; j < 22; ++j)
+ crc = crc32_update(crc, data[i+j]);
+ // now process 4 0-bytes
+ for ( ; j < 26; ++j)
+ crc = crc32_update(crc, 0);
+ // len is the total number of bytes we need to scan
+ n = f->page_crc_tests++;
+ f->scan[n].bytes_left = len-j;
+ f->scan[n].crc_so_far = crc;
+ f->scan[n].goal_crc = data[i+22] + (data[i+23] << 8) + (data[i+24]<<16) + (data[i+25]<<24);
+ // if the last frame on a page is continued to the next, then
+ // we can't recover the sample_loc immediately
+ if (data[i+27+data[i+26]-1] == 255)
+ f->scan[n].sample_loc = ~0;
+ else
+ f->scan[n].sample_loc = data[i+6] + (data[i+7] << 8) + (data[i+ 8]<<16) + (data[i+ 9]<<24);
+ f->scan[n].bytes_done = i+j;
+ if (f->page_crc_tests == STB_VORBIS_PUSHDATA_CRC_COUNT)
+ break;
+ // keep going if we still have room for more
+ }
+ }
+ }
+ }
+
+ for (i=0; i < f->page_crc_tests;) {
+ uint32 crc;
+ int j;
+ int n = f->scan[i].bytes_done;
+ int m = f->scan[i].bytes_left;
+ if (m > data_len - n) m = data_len - n;
+ // m is the bytes to scan in the current chunk
+ crc = f->scan[i].crc_so_far;
+ for (j=0; j < m; ++j)
+ crc = crc32_update(crc, data[n+j]);
+ f->scan[i].bytes_left -= m;
+ f->scan[i].crc_so_far = crc;
+ if (f->scan[i].bytes_left == 0) {
+ // does it match?
+ if (f->scan[i].crc_so_far == f->scan[i].goal_crc) {
+ // Houston, we have page
+ data_len = n+m; // consumption amount is wherever that scan ended
+ f->page_crc_tests = -1; // drop out of page scan mode
+ f->previous_length = 0; // decode-but-don't-output one frame
+ f->next_seg = -1; // start a new page
+ f->current_loc = f->scan[i].sample_loc; // set the current sample location
+ // to the amount we'd have decoded had we decoded this page
+ f->current_loc_valid = f->current_loc != ~0U;
+ return data_len;
+ }
+ // delete entry
+ f->scan[i] = f->scan[--f->page_crc_tests];
+ } else {
+ ++i;
+ }
+ }
+
+ return data_len;
+}
+
+// return value: number of bytes we used
+int stb_vorbis_decode_frame_pushdata(
+ stb_vorbis *f, // the file we're decoding
+ const uint8 *data, int data_len, // the memory available for decoding
+ int *channels, // place to write number of float * buffers
+ float ***output, // place to write float ** array of float * buffers
+ int *samples // place to write number of output samples
+ )
+{
+ int i;
+ int len,right,left;
+
+ if (!IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing);
+
+ if (f->page_crc_tests >= 0) {
+ *samples = 0;
+ return vorbis_search_for_page_pushdata(f, (uint8 *) data, data_len);
+ }
+
+ f->stream = (uint8 *) data;
+ f->stream_end = (uint8 *) data + data_len;
+ f->error = VORBIS__no_error;
+
+ // check that we have the entire packet in memory
+ if (!is_whole_packet_present(f, FALSE)) {
+ *samples = 0;
+ return 0;
+ }
+
+ if (!vorbis_decode_packet(f, &len, &left, &right)) {
+ // save the actual error we encountered
+ enum STBVorbisError error = f->error;
+ if (error == VORBIS_bad_packet_type) {
+ // flush and resynch
+ f->error = VORBIS__no_error;
+ while (get8_packet(f) != EOP)
+ if (f->eof) break;
+ *samples = 0;
+ return (int) (f->stream - data);
+ }
+ if (error == VORBIS_continued_packet_flag_invalid) {
+ if (f->previous_length == 0) {
+ // we may be resynching, in which case it's ok to hit one
+ // of these; just discard the packet
+ f->error = VORBIS__no_error;
+ while (get8_packet(f) != EOP)
+ if (f->eof) break;
+ *samples = 0;
+ return (int) (f->stream - data);
+ }
+ }
+ // if we get an error while parsing, what to do?
+ // well, it DEFINITELY won't work to continue from where we are!
+ stb_vorbis_flush_pushdata(f);
+ // restore the error that actually made us bail
+ f->error = error;
+ *samples = 0;
+ return 1;
+ }
+
+ // success!
+ len = vorbis_finish_frame(f, len, left, right);
+ for (i=0; i < f->channels; ++i)
+ f->outputs[i] = f->channel_buffers[i] + left;
+
+ if (channels) *channels = f->channels;
+ *samples = len;
+ *output = f->outputs;
+ return (int) (f->stream - data);
+}
+
+stb_vorbis *stb_vorbis_open_pushdata(
+ const unsigned char *data, int data_len, // the memory available for decoding
+ int *data_used, // only defined if result is not NULL
+ int *error, const stb_vorbis_alloc *alloc)
+{
+ stb_vorbis *f, p;
+ vorbis_init(&p, alloc);
+ p.stream = (uint8 *) data;
+ p.stream_end = (uint8 *) data + data_len;
+ p.push_mode = TRUE;
+ if (!start_decoder(&p)) {
+ if (p.eof)
+ *error = VORBIS_need_more_data;
+ else
+ *error = p.error;
+ return NULL;
+ }
+ f = vorbis_alloc(&p);
+ if (f) {
+ *f = p;
+ *data_used = (int) (f->stream - data);
+ *error = 0;
+ return f;
+ } else {
+ vorbis_deinit(&p);
+ return NULL;
+ }
+}
+#endif // STB_VORBIS_NO_PUSHDATA_API
+
+unsigned int stb_vorbis_get_file_offset(stb_vorbis *f)
+{
+ #ifndef STB_VORBIS_NO_PUSHDATA_API
+ if (f->push_mode) return 0;
+ #endif
+ if (USE_MEMORY(f)) return (unsigned int) (f->stream - f->stream_start);
+ #ifndef STB_VORBIS_NO_STDIO
+ return (unsigned int) (ftell(f->f) - f->f_start);
+ #endif
+}
+
+#ifndef STB_VORBIS_NO_PULLDATA_API
+//
+// DATA-PULLING API
+//
+
+static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last)
+{
+ for(;;) {
+ int n;
+ if (f->eof) return 0;
+ n = get8(f);
+ if (n == 0x4f) { // page header candidate
+ unsigned int retry_loc = stb_vorbis_get_file_offset(f);
+ int i;
+ // check if we're off the end of a file_section stream
+ if (retry_loc - 25 > f->stream_len)
+ return 0;
+ // check the rest of the header
+ for (i=1; i < 4; ++i)
+ if (get8(f) != ogg_page_header[i])
+ break;
+ if (f->eof) return 0;
+ if (i == 4) {
+ uint8 header[27];
+ uint32 i, crc, goal, len;
+ for (i=0; i < 4; ++i)
+ header[i] = ogg_page_header[i];
+ for (; i < 27; ++i)
+ header[i] = get8(f);
+ if (f->eof) return 0;
+ if (header[4] != 0) goto invalid;
+ goal = header[22] + (header[23] << 8) + (header[24]<<16) + (header[25]<<24);
+ for (i=22; i < 26; ++i)
+ header[i] = 0;
+ crc = 0;
+ for (i=0; i < 27; ++i)
+ crc = crc32_update(crc, header[i]);
+ len = 0;
+ for (i=0; i < header[26]; ++i) {
+ int s = get8(f);
+ crc = crc32_update(crc, s);
+ len += s;
+ }
+ if (len && f->eof) return 0;
+ for (i=0; i < len; ++i)
+ crc = crc32_update(crc, get8(f));
+ // finished parsing probable page
+ if (crc == goal) {
+ // we could now check that it's either got the last
+ // page flag set, OR it's followed by the capture
+ // pattern, but I guess TECHNICALLY you could have
+ // a file with garbage between each ogg page and recover
+ // from it automatically? So even though that paranoia
+ // might decrease the chance of an invalid decode by
+ // another 2^32, not worth it since it would hose those
+ // invalid-but-useful files?
+ if (end)
+ *end = stb_vorbis_get_file_offset(f);
+ if (last) {
+ if (header[5] & 0x04)
+ *last = 1;
+ else
+ *last = 0;
+ }
+ set_file_offset(f, retry_loc-1);
+ return 1;
+ }
+ }
+ invalid:
+ // not a valid page, so rewind and look for next one
+ set_file_offset(f, retry_loc);
+ }
+ }
+}
+
+
+#define SAMPLE_unknown 0xffffffff
+
+// seeking is implemented with a binary search, which narrows down the range to
+// 64K, before using a linear search (because finding the synchronization
+// pattern can be expensive, and the chance we'd find the end page again is
+// relatively high for small ranges)
+//
+// two initial interpolation-style probes are used at the start of the search
+// to try to bound either side of the binary search sensibly, while still
+// working in O(log n) time if they fail.
+
+static int get_seek_page_info(stb_vorbis *f, ProbedPage *z)
+{
+ uint8 header[27], lacing[255];
+ int i,len;
+
+ // record where the page starts
+ z->page_start = stb_vorbis_get_file_offset(f);
+
+ // parse the header
+ getn(f, header, 27);
+ if (header[0] != 'O' || header[1] != 'g' || header[2] != 'g' || header[3] != 'S')
+ return 0;
+ getn(f, lacing, header[26]);
+
+ // determine the length of the payload
+ len = 0;
+ for (i=0; i < header[26]; ++i)
+ len += lacing[i];
+
+ // this implies where the page ends
+ z->page_end = z->page_start + 27 + header[26] + len;
+
+ // read the last-decoded sample out of the data
+ z->last_decoded_sample = header[6] + (header[7] << 8) + (header[8] << 16) + (header[9] << 24);
+
+ // restore file state to where we were
+ set_file_offset(f, z->page_start);
+ return 1;
+}
+
+// rarely used function to seek back to the preceeding page while finding the
+// start of a packet
+static int go_to_page_before(stb_vorbis *f, unsigned int limit_offset)
+{
+ unsigned int previous_safe, end;
+
+ // now we want to seek back 64K from the limit
+ if (limit_offset >= 65536 && limit_offset-65536 >= f->first_audio_page_offset)
+ previous_safe = limit_offset - 65536;
+ else
+ previous_safe = f->first_audio_page_offset;
+
+ set_file_offset(f, previous_safe);
+
+ while (vorbis_find_page(f, &end, NULL)) {
+ if (end >= limit_offset && stb_vorbis_get_file_offset(f) < limit_offset)
+ return 1;
+ set_file_offset(f, end);
+ }
+
+ return 0;
+}
+
+// implements the search logic for finding a page and starting decoding. if
+// the function succeeds, current_loc_valid will be true and current_loc will
+// be less than or equal to the provided sample number (the closer the
+// better).
+static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
+{
+ ProbedPage left, right, mid;
+ int i, start_seg_with_known_loc, end_pos, page_start;
+ uint32 delta, stream_length, padding;
+ double offset, bytes_per_sample;
+ int probe = 0;
+
+ // find the last page and validate the target sample
+ stream_length = stb_vorbis_stream_length_in_samples(f);
+ if (stream_length == 0) return error(f, VORBIS_seek_without_length);
+ if (sample_number > stream_length) return error(f, VORBIS_seek_invalid);
+
+ // this is the maximum difference between the window-center (which is the
+ // actual granule position value), and the right-start (which the spec
+ // indicates should be the granule position (give or take one)).
+ padding = ((f->blocksize_1 - f->blocksize_0) >> 2);
+ if (sample_number < padding)
+ sample_number = 0;
+ else
+ sample_number -= padding;
+
+ left = f->p_first;
+ while (left.last_decoded_sample == ~0U) {
+ // (untested) the first page does not have a 'last_decoded_sample'
+ set_file_offset(f, left.page_end);
+ if (!get_seek_page_info(f, &left)) goto error;
+ }
+
+ right = f->p_last;
+ assert(right.last_decoded_sample != ~0U);
+
+ // starting from the start is handled differently
+ if (sample_number <= left.last_decoded_sample) {
+ stb_vorbis_seek_start(f);
+ return 1;
+ }
+
+ while (left.page_end != right.page_start) {
+ assert(left.page_end < right.page_start);
+ // search range in bytes
+ delta = right.page_start - left.page_end;
+ if (delta <= 65536) {
+ // there's only 64K left to search - handle it linearly
+ set_file_offset(f, left.page_end);
+ } else {
+ if (probe < 2) {
+ if (probe == 0) {
+ // first probe (interpolate)
+ double data_bytes = right.page_end - left.page_start;
+ bytes_per_sample = data_bytes / right.last_decoded_sample;
+ offset = left.page_start + bytes_per_sample * (sample_number - left.last_decoded_sample);
+ } else {
+ // second probe (try to bound the other side)
+ double error = ((double) sample_number - mid.last_decoded_sample) * bytes_per_sample;
+ if (error >= 0 && error < 8000) error = 8000;
+ if (error < 0 && error > -8000) error = -8000;
+ offset += error * 2;
+ }
+
+ // ensure the offset is valid
+ if (offset < left.page_end)
+ offset = left.page_end;
+ if (offset > right.page_start - 65536)
+ offset = right.page_start - 65536;
+
+ set_file_offset(f, (unsigned int) offset);
+ } else {
+ // binary search for large ranges (offset by 32K to ensure
+ // we don't hit the right page)
+ set_file_offset(f, left.page_end + (delta / 2) - 32768);
+ }
+
+ if (!vorbis_find_page(f, NULL, NULL)) goto error;
+ }
+
+ for (;;) {
+ if (!get_seek_page_info(f, &mid)) goto error;
+ if (mid.last_decoded_sample != ~0U) break;
+ // (untested) no frames end on this page
+ set_file_offset(f, mid.page_end);
+ assert(mid.page_start < right.page_start);
+ }
+
+ // if we've just found the last page again then we're in a tricky file,
+ // and we're close enough.
+ if (mid.page_start == right.page_start)
+ break;
+
+ if (sample_number < mid.last_decoded_sample)
+ right = mid;
+ else
+ left = mid;
+
+ ++probe;
+ }
+
+ // seek back to start of the last packet
+ page_start = left.page_start;
+ set_file_offset(f, page_start);
+ if (!start_page(f)) return error(f, VORBIS_seek_failed);
+ end_pos = f->end_seg_with_known_loc;
+ assert(end_pos >= 0);
+
+ for (;;) {
+ for (i = end_pos; i > 0; --i)
+ if (f->segments[i-1] != 255)
+ break;
+
+ start_seg_with_known_loc = i;
+
+ if (start_seg_with_known_loc > 0 || !(f->page_flag & PAGEFLAG_continued_packet))
+ break;
+
+ // (untested) the final packet begins on an earlier page
+ if (!go_to_page_before(f, page_start))
+ goto error;
+
+ page_start = stb_vorbis_get_file_offset(f);
+ if (!start_page(f)) goto error;
+ end_pos = f->segment_count - 1;
+ }
+
+ // prepare to start decoding
+ f->current_loc_valid = FALSE;
+ f->last_seg = FALSE;
+ f->valid_bits = 0;
+ f->packet_bytes = 0;
+ f->bytes_in_seg = 0;
+ f->previous_length = 0;
+ f->next_seg = start_seg_with_known_loc;
+
+ for (i = 0; i < start_seg_with_known_loc; i++)
+ skip(f, f->segments[i]);
+
+ // start decoding (optimizable - this frame is generally discarded)
+ vorbis_pump_first_frame(f);
+ return 1;
+
+error:
+ // try to restore the file to a valid state
+ stb_vorbis_seek_start(f);
+ return error(f, VORBIS_seek_failed);
+}
+
+// the same as vorbis_decode_initial, but without advancing
+static int peek_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode)
+{
+ int bits_read, bytes_read;
+
+ if (!vorbis_decode_initial(f, p_left_start, p_left_end, p_right_start, p_right_end, mode))
+ return 0;
+
+ // either 1 or 2 bytes were read, figure out which so we can rewind
+ bits_read = 1 + ilog(f->mode_count-1);
+ if (f->mode_config[*mode].blockflag)
+ bits_read += 2;
+ bytes_read = (bits_read + 7) / 8;
+
+ f->bytes_in_seg += bytes_read;
+ f->packet_bytes -= bytes_read;
+ skip(f, -bytes_read);
+ if (f->next_seg == -1)
+ f->next_seg = f->segment_count - 1;
+ else
+ f->next_seg--;
+ f->valid_bits = 0;
+
+ return 1;
+}
+
+int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number)
+{
+ uint32 max_frame_samples;
+
+ if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing);
+
+ // fast page-level search
+ if (!seek_to_sample_coarse(f, sample_number))
+ return 0;
+
+ assert(f->current_loc_valid);
+ assert(f->current_loc <= sample_number);
+
+ // linear search for the relevant packet
+ max_frame_samples = (f->blocksize_1*3 - f->blocksize_0) >> 2;
+ while (f->current_loc < sample_number) {
+ int left_start, left_end, right_start, right_end, mode, frame_samples;
+ if (!peek_decode_initial(f, &left_start, &left_end, &right_start, &right_end, &mode))
+ return error(f, VORBIS_seek_failed);
+ // calculate the number of samples returned by the next frame
+ frame_samples = right_start - left_start;
+ if (f->current_loc + frame_samples > sample_number) {
+ return 1; // the next frame will contain the sample
+ } else if (f->current_loc + frame_samples + max_frame_samples > sample_number) {
+ // there's a chance the frame after this could contain the sample
+ vorbis_pump_first_frame(f);
+ } else {
+ // this frame is too early to be relevant
+ f->current_loc += frame_samples;
+ f->previous_length = 0;
+ maybe_start_packet(f);
+ flush_packet(f);
+ }
+ }
+ // the next frame will start with the sample
+ assert(f->current_loc == sample_number);
+ return 1;
+}
+
+int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number)
+{
+ if (!stb_vorbis_seek_frame(f, sample_number))
+ return 0;
+
+ if (sample_number != f->current_loc) {
+ int n;
+ uint32 frame_start = f->current_loc;
+ stb_vorbis_get_frame_float(f, &n, NULL);
+ assert(sample_number > frame_start);
+ assert(f->channel_buffer_start + (int) (sample_number-frame_start) <= f->channel_buffer_end);
+ f->channel_buffer_start += (sample_number - frame_start);
+ }
+
+ return 1;
+}
+
+void stb_vorbis_seek_start(stb_vorbis *f)
+{
+ if (IS_PUSH_MODE(f)) { error(f, VORBIS_invalid_api_mixing); return; }
+ set_file_offset(f, f->first_audio_page_offset);
+ f->previous_length = 0;
+ f->first_decode = TRUE;
+ f->next_seg = -1;
+ vorbis_pump_first_frame(f);
+}
+
+unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f)
+{
+ unsigned int restore_offset, previous_safe;
+ unsigned int end, last_page_loc;
+
+ if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing);
+ if (!f->total_samples) {
+ unsigned int last;
+ uint32 lo,hi;
+ char header[6];
+
+ // first, store the current decode position so we can restore it
+ restore_offset = stb_vorbis_get_file_offset(f);
+
+ // now we want to seek back 64K from the end (the last page must
+ // be at most a little less than 64K, but let's allow a little slop)
+ if (f->stream_len >= 65536 && f->stream_len-65536 >= f->first_audio_page_offset)
+ previous_safe = f->stream_len - 65536;
+ else
+ previous_safe = f->first_audio_page_offset;
+
+ set_file_offset(f, previous_safe);
+ // previous_safe is now our candidate 'earliest known place that seeking
+ // to will lead to the final page'
+
+ if (!vorbis_find_page(f, &end, &last)) {
+ // if we can't find a page, we're hosed!
+ f->error = VORBIS_cant_find_last_page;
+ f->total_samples = 0xffffffff;
+ goto done;
+ }
+
+ // check if there are more pages
+ last_page_loc = stb_vorbis_get_file_offset(f);
+
+ // stop when the last_page flag is set, not when we reach eof;
+ // this allows us to stop short of a 'file_section' end without
+ // explicitly checking the length of the section
+ while (!last) {
+ set_file_offset(f, end);
+ if (!vorbis_find_page(f, &end, &last)) {
+ // the last page we found didn't have the 'last page' flag
+ // set. whoops!
+ break;
+ }
+ previous_safe = last_page_loc+1;
+ last_page_loc = stb_vorbis_get_file_offset(f);
+ }
+
+ set_file_offset(f, last_page_loc);
+
+ // parse the header
+ getn(f, (unsigned char *)header, 6);
+ // extract the absolute granule position
+ lo = get32(f);
+ hi = get32(f);
+ if (lo == 0xffffffff && hi == 0xffffffff) {
+ f->error = VORBIS_cant_find_last_page;
+ f->total_samples = SAMPLE_unknown;
+ goto done;
+ }
+ if (hi)
+ lo = 0xfffffffe; // saturate
+ f->total_samples = lo;
+
+ f->p_last.page_start = last_page_loc;
+ f->p_last.page_end = end;
+ f->p_last.last_decoded_sample = lo;
+
+ done:
+ set_file_offset(f, restore_offset);
+ }
+ return f->total_samples == SAMPLE_unknown ? 0 : f->total_samples;
+}
+
+float stb_vorbis_stream_length_in_seconds(stb_vorbis *f)
+{
+ return stb_vorbis_stream_length_in_samples(f) / (float) f->sample_rate;
+}
+
+
+
+int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output)
+{
+ int len, right,left,i;
+ if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing);
+
+ if (!vorbis_decode_packet(f, &len, &left, &right)) {
+ f->channel_buffer_start = f->channel_buffer_end = 0;
+ return 0;
+ }
+
+ len = vorbis_finish_frame(f, len, left, right);
+ for (i=0; i < f->channels; ++i)
+ f->outputs[i] = f->channel_buffers[i] + left;
+
+ f->channel_buffer_start = left;
+ f->channel_buffer_end = left+len;
+
+ if (channels) *channels = f->channels;
+ if (output) *output = f->outputs;
+ return len;
+}
+
+#ifndef STB_VORBIS_NO_STDIO
+
+stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc, unsigned int length)
+{
+ stb_vorbis *f, p;
+ vorbis_init(&p, alloc);
+ p.f = file;
+ p.f_start = (uint32) ftell(file);
+ p.stream_len = length;
+ p.close_on_free = close_on_free;
+ if (start_decoder(&p)) {
+ f = vorbis_alloc(&p);
+ if (f) {
+ *f = p;
+ vorbis_pump_first_frame(f);
+ return f;
+ }
+ }
+ if (error) *error = p.error;
+ vorbis_deinit(&p);
+ return NULL;
+}
+
+stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc)
+{
+ unsigned int len, start;
+ start = (unsigned int) ftell(file);
+ fseek(file, 0, SEEK_END);
+ len = (unsigned int) (ftell(file) - start);
+ fseek(file, start, SEEK_SET);
+ return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len);
+}
+
+stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc)
+{
+ FILE *f = fopen(filename, "rb");
+ if (f)
+ return stb_vorbis_open_file(f, TRUE, error, alloc);
+ if (error) *error = VORBIS_file_open_failure;
+ return NULL;
+}
+#endif // STB_VORBIS_NO_STDIO
+
+stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc)
+{
+ stb_vorbis *f, p;
+ if (data == NULL) return NULL;
+ vorbis_init(&p, alloc);
+ p.stream = (uint8 *) data;
+ p.stream_end = (uint8 *) data + len;
+ p.stream_start = (uint8 *) p.stream;
+ p.stream_len = len;
+ p.push_mode = FALSE;
+ if (start_decoder(&p)) {
+ f = vorbis_alloc(&p);
+ if (f) {
+ *f = p;
+ vorbis_pump_first_frame(f);
+ return f;
+ }
+ }
+ if (error) *error = p.error;
+ vorbis_deinit(&p);
+ return NULL;
+}
+
+#ifndef STB_VORBIS_NO_INTEGER_CONVERSION
+#define PLAYBACK_MONO 1
+#define PLAYBACK_LEFT 2
+#define PLAYBACK_RIGHT 4
+
+#define L (PLAYBACK_LEFT | PLAYBACK_MONO)
+#define C (PLAYBACK_LEFT | PLAYBACK_RIGHT | PLAYBACK_MONO)
+#define R (PLAYBACK_RIGHT | PLAYBACK_MONO)
+
+static int8 channel_position[7][6] =
+{
+ { 0 },
+ { C },
+ { L, R },
+ { L, C, R },
+ { L, R, L, R },
+ { L, C, R, L, R },
+ { L, C, R, L, R, C },
+};
+
+
+#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT
+ typedef union {
+ float f;
+ int i;
+ } float_conv;
+ typedef char stb_vorbis_float_size_test[sizeof(float)==4 && sizeof(int) == 4];
+ #define FASTDEF(x) float_conv x
+ // add (1<<23) to convert to int, then divide by 2^SHIFT, then add 0.5/2^SHIFT to round
+ #define MAGIC(SHIFT) (1.5f * (1 << (23-SHIFT)) + 0.5f/(1 << SHIFT))
+ #define ADDEND(SHIFT) (((150-SHIFT) << 23) + (1 << 22))
+ #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) (temp.f = (x) + MAGIC(s), temp.i - ADDEND(s))
+ #define check_endianness()
+#else
+ #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) ((int) ((x) * (1 << (s))))
+ #define check_endianness()
+ #define FASTDEF(x)
+#endif
+
+static void copy_samples(short *dest, float *src, int len)
+{
+ int i;
+ check_endianness();
+ for (i=0; i < len; ++i) {
+ FASTDEF(temp);
+ int v = FAST_SCALED_FLOAT_TO_INT(temp, src[i],15);
+ if ((unsigned int) (v + 32768) > 65535)
+ v = v < 0 ? -32768 : 32767;
+ dest[i] = v;
+ }
+}
+
+static void compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len)
+{
+ #define BUFFER_SIZE 32
+ float buffer[BUFFER_SIZE];
+ int i,j,o,n = BUFFER_SIZE;
+ check_endianness();
+ for (o = 0; o < len; o += BUFFER_SIZE) {
+ memset(buffer, 0, sizeof(buffer));
+ if (o + n > len) n = len - o;
+ for (j=0; j < num_c; ++j) {
+ if (channel_position[num_c][j] & mask) {
+ for (i=0; i < n; ++i)
+ buffer[i] += data[j][d_offset+o+i];
+ }
+ }
+ for (i=0; i < n; ++i) {
+ FASTDEF(temp);
+ int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15);
+ if ((unsigned int) (v + 32768) > 65535)
+ v = v < 0 ? -32768 : 32767;
+ output[o+i] = v;
+ }
+ }
+}
+
+static void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len)
+{
+ #define BUFFER_SIZE 32
+ float buffer[BUFFER_SIZE];
+ int i,j,o,n = BUFFER_SIZE >> 1;
+ // o is the offset in the source data
+ check_endianness();
+ for (o = 0; o < len; o += BUFFER_SIZE >> 1) {
+ // o2 is the offset in the output data
+ int o2 = o << 1;
+ memset(buffer, 0, sizeof(buffer));
+ if (o + n > len) n = len - o;
+ for (j=0; j < num_c; ++j) {
+ int m = channel_position[num_c][j] & (PLAYBACK_LEFT | PLAYBACK_RIGHT);
+ if (m == (PLAYBACK_LEFT | PLAYBACK_RIGHT)) {
+ for (i=0; i < n; ++i) {
+ buffer[i*2+0] += data[j][d_offset+o+i];
+ buffer[i*2+1] += data[j][d_offset+o+i];
+ }
+ } else if (m == PLAYBACK_LEFT) {
+ for (i=0; i < n; ++i) {
+ buffer[i*2+0] += data[j][d_offset+o+i];
+ }
+ } else if (m == PLAYBACK_RIGHT) {
+ for (i=0; i < n; ++i) {
+ buffer[i*2+1] += data[j][d_offset+o+i];
+ }
+ }
+ }
+ for (i=0; i < (n<<1); ++i) {
+ FASTDEF(temp);
+ int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15);
+ if ((unsigned int) (v + 32768) > 65535)
+ v = v < 0 ? -32768 : 32767;
+ output[o2+i] = v;
+ }
+ }
+}
+
+static void convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples)
+{
+ int i;
+ if (buf_c != data_c && buf_c <= 2 && data_c <= 6) {
+ static int channel_selector[3][2] = { {0}, {PLAYBACK_MONO}, {PLAYBACK_LEFT, PLAYBACK_RIGHT} };
+ for (i=0; i < buf_c; ++i)
+ compute_samples(channel_selector[buf_c][i], buffer[i]+b_offset, data_c, data, d_offset, samples);
+ } else {
+ int limit = buf_c < data_c ? buf_c : data_c;
+ for (i=0; i < limit; ++i)
+ copy_samples(buffer[i]+b_offset, data[i]+d_offset, samples);
+ for ( ; i < buf_c; ++i)
+ memset(buffer[i]+b_offset, 0, sizeof(short) * samples);
+ }
+}
+
+int stb_vorbis_get_frame_short(stb_vorbis *f, int num_c, short **buffer, int num_samples)
+{
+ float **output;
+ int len = stb_vorbis_get_frame_float(f, NULL, &output);
+ if (len > num_samples) len = num_samples;
+ if (len)
+ convert_samples_short(num_c, buffer, 0, f->channels, output, 0, len);
+ return len;
+}
+
+static void convert_channels_short_interleaved(int buf_c, short *buffer, int data_c, float **data, int d_offset, int len)
+{
+ int i;
+ check_endianness();
+ if (buf_c != data_c && buf_c <= 2 && data_c <= 6) {
+ assert(buf_c == 2);
+ for (i=0; i < buf_c; ++i)
+ compute_stereo_samples(buffer, data_c, data, d_offset, len);
+ } else {
+ int limit = buf_c < data_c ? buf_c : data_c;
+ int j;
+ for (j=0; j < len; ++j) {
+ for (i=0; i < limit; ++i) {
+ FASTDEF(temp);
+ float f = data[i][d_offset+j];
+ int v = FAST_SCALED_FLOAT_TO_INT(temp, f,15);//data[i][d_offset+j],15);
+ if ((unsigned int) (v + 32768) > 65535)
+ v = v < 0 ? -32768 : 32767;
+ *buffer++ = v;
+ }
+ for ( ; i < buf_c; ++i)
+ *buffer++ = 0;
+ }
+ }
+}
+
+int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts)
+{
+ float **output;
+ int len;
+ if (num_c == 1) return stb_vorbis_get_frame_short(f,num_c,&buffer, num_shorts);
+ len = stb_vorbis_get_frame_float(f, NULL, &output);
+ if (len) {
+ if (len*num_c > num_shorts) len = num_shorts / num_c;
+ convert_channels_short_interleaved(num_c, buffer, f->channels, output, 0, len);
+ }
+ return len;
+}
+
+int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts)
+{
+ float **outputs;
+ int len = num_shorts / channels;
+ int n=0;
+ int z = f->channels;
+ if (z > channels) z = channels;
+ while (n < len) {
+ int k = f->channel_buffer_end - f->channel_buffer_start;
+ if (n+k >= len) k = len - n;
+ if (k)
+ convert_channels_short_interleaved(channels, buffer, f->channels, f->channel_buffers, f->channel_buffer_start, k);
+ buffer += k*channels;
+ n += k;
+ f->channel_buffer_start += k;
+ if (n == len) break;
+ if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break;
+ }
+ return n;
+}
+
+int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int len)
+{
+ float **outputs;
+ int n=0;
+ int z = f->channels;
+ if (z > channels) z = channels;
+ while (n < len) {
+ int k = f->channel_buffer_end - f->channel_buffer_start;
+ if (n+k >= len) k = len - n;
+ if (k)
+ convert_samples_short(channels, buffer, n, f->channels, f->channel_buffers, f->channel_buffer_start, k);
+ n += k;
+ f->channel_buffer_start += k;
+ if (n == len) break;
+ if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break;
+ }
+ return n;
+}
+
+#ifndef STB_VORBIS_NO_STDIO
+int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output)
+{
+ int data_len, offset, total, limit, error;
+ short *data;
+ stb_vorbis *v = stb_vorbis_open_filename(filename, &error, NULL);
+ if (v == NULL) return -1;
+ limit = v->channels * 4096;
+ *channels = v->channels;
+ if (sample_rate)
+ *sample_rate = v->sample_rate;
+ offset = data_len = 0;
+ total = limit;
+ data = (short *) malloc(total * sizeof(*data));
+ if (data == NULL) {
+ stb_vorbis_close(v);
+ return -2;
+ }
+ for (;;) {
+ int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset);
+ if (n == 0) break;
+ data_len += n;
+ offset += n * v->channels;
+ if (offset + limit > total) {
+ short *data2;
+ total *= 2;
+ data2 = (short *) realloc(data, total * sizeof(*data));
+ if (data2 == NULL) {
+ free(data);
+ stb_vorbis_close(v);
+ return -2;
+ }
+ data = data2;
+ }
+ }
+ *output = data;
+ stb_vorbis_close(v);
+ return data_len;
+}
+#endif // NO_STDIO
+
+int stb_vorbis_decode_memory(const uint8 *mem, int len, int *channels, int *sample_rate, short **output)
+{
+ int data_len, offset, total, limit, error;
+ short *data;
+ stb_vorbis *v = stb_vorbis_open_memory(mem, len, &error, NULL);
+ if (v == NULL) return -1;
+ limit = v->channels * 4096;
+ *channels = v->channels;
+ if (sample_rate)
+ *sample_rate = v->sample_rate;
+ offset = data_len = 0;
+ total = limit;
+ data = (short *) malloc(total * sizeof(*data));
+ if (data == NULL) {
+ stb_vorbis_close(v);
+ return -2;
+ }
+ for (;;) {
+ int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset);
+ if (n == 0) break;
+ data_len += n;
+ offset += n * v->channels;
+ if (offset + limit > total) {
+ short *data2;
+ total *= 2;
+ data2 = (short *) realloc(data, total * sizeof(*data));
+ if (data2 == NULL) {
+ free(data);
+ stb_vorbis_close(v);
+ return -2;
+ }
+ data = data2;
+ }
+ }
+ *output = data;
+ stb_vorbis_close(v);
+ return data_len;
+}
+#endif // STB_VORBIS_NO_INTEGER_CONVERSION
+
+int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats)
+{
+ float **outputs;
+ int len = num_floats / channels;
+ int n=0;
+ int z = f->channels;
+ if (z > channels) z = channels;
+ while (n < len) {
+ int i,j;
+ int k = f->channel_buffer_end - f->channel_buffer_start;
+ if (n+k >= len) k = len - n;
+ for (j=0; j < k; ++j) {
+ for (i=0; i < z; ++i)
+ *buffer++ = f->channel_buffers[i][f->channel_buffer_start+j];
+ for ( ; i < channels; ++i)
+ *buffer++ = 0;
+ }
+ n += k;
+ f->channel_buffer_start += k;
+ if (n == len)
+ break;
+ if (!stb_vorbis_get_frame_float(f, NULL, &outputs))
+ break;
+ }
+ return n;
+}
+
+int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples)
+{
+ float **outputs;
+ int n=0;
+ int z = f->channels;
+ if (z > channels) z = channels;
+ while (n < num_samples) {
+ int i;
+ int k = f->channel_buffer_end - f->channel_buffer_start;
+ if (n+k >= num_samples) k = num_samples - n;
+ if (k) {
+ for (i=0; i < z; ++i)
+ memcpy(buffer[i]+n, f->channel_buffers[i]+f->channel_buffer_start, sizeof(float)*k);
+ for ( ; i < channels; ++i)
+ memset(buffer[i]+n, 0, sizeof(float) * k);
+ }
+ n += k;
+ f->channel_buffer_start += k;
+ if (n == num_samples)
+ break;
+ if (!stb_vorbis_get_frame_float(f, NULL, &outputs))
+ break;
+ }
+ return n;
+}
+#endif // STB_VORBIS_NO_PULLDATA_API
+
+/* Version history
+ 1.09 - 2016/04/04 - back out 'avoid discarding last frame' fix from previous version
+ 1.08 - 2016/04/02 - fixed multiple warnings; fix setup memory leaks;
+ avoid discarding last frame of audio data
+ 1.07 - 2015/01/16 - fixed some warnings, fix mingw, const-correct API
+ some more crash fixes when out of memory or with corrupt files
+ 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson)
+ some crash fixes when out of memory or with corrupt files
+ 1.05 - 2015/04/19 - don't define __forceinline if it's redundant
+ 1.04 - 2014/08/27 - fix missing const-correct case in API
+ 1.03 - 2014/08/07 - Warning fixes
+ 1.02 - 2014/07/09 - Declare qsort compare function _cdecl on windows
+ 1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float
+ 1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in multichannel
+ (API change) report sample rate for decode-full-file funcs
+ 0.99996 - bracket #include <malloc.h> for macintosh compilation by Laurent Gomila
+ 0.99995 - use union instead of pointer-cast for fast-float-to-int to avoid alias-optimization problem
+ 0.99994 - change fast-float-to-int to work in single-precision FPU mode, remove endian-dependence
+ 0.99993 - remove assert that fired on legal files with empty tables
+ 0.99992 - rewind-to-start
+ 0.99991 - bugfix to stb_vorbis_get_samples_short by Bernhard Wodo
+ 0.9999 - (should have been 0.99990) fix no-CRT support, compiling as C++
+ 0.9998 - add a full-decode function with a memory source
+ 0.9997 - fix a bug in the read-from-FILE case in 0.9996 addition
+ 0.9996 - query length of vorbis stream in samples/seconds
+ 0.9995 - bugfix to another optimization that only happened in certain files
+ 0.9994 - bugfix to one of the optimizations that caused significant (but inaudible?) errors
+ 0.9993 - performance improvements; runs in 99% to 104% of time of reference implementation
+ 0.9992 - performance improvement of IMDCT; now performs close to reference implementation
+ 0.9991 - performance improvement of IMDCT
+ 0.999 - (should have been 0.9990) performance improvement of IMDCT
+ 0.998 - no-CRT support from Casey Muratori
+ 0.997 - bugfixes for bugs found by Terje Mathisen
+ 0.996 - bugfix: fast-huffman decode initialized incorrectly for sparse codebooks; fixing gives 10% speedup - found by Terje Mathisen
+ 0.995 - bugfix: fix to 'effective' overrun detection - found by Terje Mathisen
+ 0.994 - bugfix: garbage decode on final VQ symbol of a non-multiple - found by Terje Mathisen
+ 0.993 - bugfix: pushdata API required 1 extra byte for empty page (failed to consume final page if empty) - found by Terje Mathisen
+ 0.992 - fixes for MinGW warning
+ 0.991 - turn fast-float-conversion on by default
+ 0.990 - fix push-mode seek recovery if you seek into the headers
+ 0.98b - fix to bad release of 0.98
+ 0.98 - fix push-mode seek recovery; robustify float-to-int and support non-fast mode
+ 0.97 - builds under c++ (typecasting, don't use 'class' keyword)
+ 0.96 - somehow MY 0.95 was right, but the web one was wrong, so here's my 0.95 rereleased as 0.96, fixes a typo in the clamping code
+ 0.95 - clamping code for 16-bit functions
+ 0.94 - not publically released
+ 0.93 - fixed all-zero-floor case (was decoding garbage)
+ 0.92 - fixed a memory leak
+ 0.91 - conditional compiles to omit parts of the API and the infrastructure to support them: STB_VORBIS_NO_PULLDATA_API, STB_VORBIS_NO_PUSHDATA_API, STB_VORBIS_NO_STDIO, STB_VORBIS_NO_INTEGER_CONVERSION
+ 0.90 - first public release
+*/
+
+#endif // STB_VORBIS_HEADER_ONLY
diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp
index 759d33dea8..f256e351ae 100644
--- a/tools/editor/animation_editor.cpp
+++ b/tools/editor/animation_editor.cpp
@@ -179,12 +179,12 @@ private:
bool sg = val < 0;
val = Math::absf(val);
- val = Math::log(val)/Math::log(2);
+ val = Math::log(val)/Math::log((float)2.0);
//logspace
val+=rel*0.05;
//
- val = Math::pow(2,val);
+ val = Math::pow((float)2.0,val);
if (sg)
val=-val;
@@ -1055,9 +1055,9 @@ float AnimationKeyEditor::_get_zoom_scale() const {
float zv = zoom->get_value();
if (zv<1) {
zv = 1.0-zv;
- return Math::pow(1.0+zv,8.0)*100;
+ return Math::pow(1.0f+zv,8.0f)*100;
} else {
- return 1.0/Math::pow(zv,8.0)*100;
+ return 1.0/Math::pow(zv,8.0f)*100;
}
}
@@ -1487,8 +1487,8 @@ void AnimationKeyEditor::_track_editor_draw() {
//draw the keys;
int tt = animation->track_get_type(idx);
- float key_vofs = Math::floor((h - type_icon[tt]->get_height())/2);
- float key_hofs = -Math::floor(type_icon[tt]->get_height()/2);
+ float key_vofs = Math::floor((float)(h - type_icon[tt]->get_height())/2);
+ float key_hofs = -Math::floor((float)type_icon[tt]->get_height()/2);
int kc=animation->track_get_key_count(idx);
bool first=true;
@@ -1592,8 +1592,8 @@ void AnimationKeyEditor::_track_editor_draw() {
continue;
int y = h+i*h+sep;
- float key_vofs = Math::floor((h - type_selected->get_height())/2);
- float key_hofs = -Math::floor(type_selected->get_height()/2);
+ float key_vofs = Math::floor((float)(h - type_selected->get_height())/2);
+ float key_hofs = -Math::floor((float)type_selected->get_height()/2);
float time = animation->track_get_key_time(idx,E->key().key);
float diff = time-from_t;
diff --git a/tools/editor/editor_audio_buses.cpp b/tools/editor/editor_audio_buses.cpp
new file mode 100644
index 0000000000..6ee18f08d8
--- /dev/null
+++ b/tools/editor/editor_audio_buses.cpp
@@ -0,0 +1,1192 @@
+#include "editor_audio_buses.h"
+#include "editor_node.h"
+#include "servers/audio_server.h"
+#include "os/keyboard.h"
+#include "io/resource_saver.h"
+#include "filesystem_dock.h"
+
+void EditorAudioBus::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_READY) {
+
+ vu_l->set_under_texture(get_icon("BusVuEmpty","EditorIcons"));
+ vu_l->set_progress_texture(get_icon("BusVuFull","EditorIcons"));
+ vu_r->set_under_texture(get_icon("BusVuEmpty","EditorIcons"));
+ vu_r->set_progress_texture(get_icon("BusVuFull","EditorIcons"));
+ scale->set_texture( get_icon("BusVuDb","EditorIcons"));
+
+ disabled_vu = get_icon("BusVuFrozen","EditorIcons");
+
+ prev_active=true;
+ update_bus();
+ set_process(true);
+ }
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+ if (has_focus()) {
+ draw_style_box(get_stylebox("focus","Button"),Rect2(Vector2(),get_size()));
+ }
+ }
+
+ if (p_what==NOTIFICATION_PROCESS) {
+
+ float real_peak[2]={-100,-100};
+ bool activity_found=false;
+
+ int cc;
+ switch(AudioServer::get_singleton()->get_speaker_mode()) {
+ case AudioServer::SPEAKER_MODE_STEREO: cc = 1; break;
+ case AudioServer::SPEAKER_SURROUND_51: cc = 4; break;
+ case AudioServer::SPEAKER_SURROUND_71: cc = 5; break;
+ }
+
+ for(int i=0;i<cc;i++) {
+ if (AudioServer::get_singleton()->is_bus_channel_active(get_index(),i)) {
+ activity_found=true;
+ real_peak[0]=MAX(real_peak[0],AudioServer::get_singleton()->get_bus_peak_volume_left_db(get_index(),i));
+ real_peak[1]=MAX(real_peak[1],AudioServer::get_singleton()->get_bus_peak_volume_right_db(get_index(),i));
+ }
+ }
+
+
+ if (real_peak[0]>peak_l) {
+ peak_l = real_peak[0];
+ } else {
+ peak_l-=get_process_delta_time()*60.0;
+ }
+
+ if (real_peak[1]>peak_r) {
+ peak_r = real_peak[1];
+ } else {
+ peak_r-=get_process_delta_time()*60.0;
+
+ }
+
+ vu_l->set_value(peak_l);
+ vu_r->set_value(peak_r);
+
+ if (activity_found!=prev_active) {
+ if (activity_found) {
+ vu_l->set_over_texture(Ref<Texture>());
+ vu_r->set_over_texture(Ref<Texture>());
+ } else {
+ vu_l->set_over_texture(disabled_vu);
+ vu_r->set_over_texture(disabled_vu);
+
+ }
+
+ prev_active=activity_found;
+ }
+
+ }
+
+ if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
+
+ peak_l=-100;
+ peak_r=-100;
+ prev_active=true;
+
+ set_process(is_visible_in_tree());
+ }
+
+}
+
+void EditorAudioBus::update_send() {
+
+ send->clear();
+ if (get_index()==0) {
+ send->set_disabled(true);
+ send->set_text("Speakers");
+ } else {
+ send->set_disabled(false);
+ StringName current_send = AudioServer::get_singleton()->get_bus_send(get_index());
+ int current_send_index=0; //by default to master
+
+ for(int i=0;i<get_index();i++) {
+ StringName send_name = AudioServer::get_singleton()->get_bus_name(i);
+ send->add_item(send_name);
+ if (send_name==current_send) {
+ current_send_index=i;
+ }
+ }
+
+ send->select(current_send_index);
+ }
+}
+
+void EditorAudioBus::update_bus() {
+
+ if (updating_bus)
+ return;
+
+ updating_bus=true;
+
+ int index = get_index();
+
+ slider->set_value(AudioServer::get_singleton()->get_bus_volume_db(index));
+ track_name->set_text(AudioServer::get_singleton()->get_bus_name(index));
+ if (get_index()==0)
+ track_name->set_editable(false);
+
+ solo->set_pressed( AudioServer::get_singleton()->is_bus_solo(index));
+ mute->set_pressed( AudioServer::get_singleton()->is_bus_mute(index));
+ bypass->set_pressed( AudioServer::get_singleton()->is_bus_bypassing_effects(index));
+ // effects..
+ effects->clear();
+
+ TreeItem *root = effects->create_item();
+ for(int i=0;i<AudioServer::get_singleton()->get_bus_effect_count(index);i++) {
+
+ Ref<AudioEffect> afx = AudioServer::get_singleton()->get_bus_effect(index,i);
+
+ TreeItem *fx = effects->create_item(root);
+ fx->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
+ fx->set_editable(0,true);
+ fx->set_checked(0,AudioServer::get_singleton()->is_bus_effect_enabled(index,i));
+ fx->set_text(0,afx->get_name());
+ fx->set_metadata(0,i);
+
+ }
+
+ TreeItem *add = effects->create_item(root);
+ add->set_cell_mode(0,TreeItem::CELL_MODE_CUSTOM);
+ add->set_editable(0,true);
+ add->set_selectable(0,false);
+ add->set_text(0,"Add Effect");
+
+ update_send();
+
+ updating_bus=false;
+
+}
+
+
+void EditorAudioBus::_name_changed(const String& p_new_name) {
+
+ if (p_new_name==AudioServer::get_singleton()->get_bus_name(get_index()))
+ return;
+
+ String attempt=p_new_name;
+ int attempts=1;
+
+ while(true) {
+
+ bool name_free=true;
+ for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) {
+
+ if (AudioServer::get_singleton()->get_bus_name(i)==attempt) {
+ name_free=false;
+ break;
+ }
+ }
+
+ if (name_free) {
+ break;
+ }
+
+ attempts++;
+ attempt=p_new_name+" "+itos(attempts);
+ }
+ updating_bus=true;
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+ StringName current = AudioServer::get_singleton()->get_bus_name(get_index());
+ ur->create_action("Rename Audio Bus");
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_name",get_index(),attempt);
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_name",get_index(),current);
+
+ for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) {
+ if (AudioServer::get_singleton()->get_bus_send(i)==current) {
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_send",i,attempt);
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_send",i,current);
+ }
+ }
+
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+
+
+ ur->add_do_method(buses,"_update_sends");
+ ur->add_undo_method(buses,"_update_sends");
+ ur->commit_action();
+
+ updating_bus=false;
+
+}
+
+void EditorAudioBus::_volume_db_changed(float p_db){
+
+ if (updating_bus)
+ return;
+
+ updating_bus=true;
+
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change Audio Bus Volume",UndoRedo::MERGE_ENDS);
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_volume_db",get_index(),p_db);
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_volume_db",get_index(),AudioServer::get_singleton()->get_bus_volume_db(get_index()));
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ ur->commit_action();
+
+ updating_bus=false;
+
+}
+void EditorAudioBus::_solo_toggled(){
+
+ updating_bus=true;
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Toggle Audio Bus Solo");
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_solo",get_index(),solo->is_pressed());
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_solo",get_index(),AudioServer::get_singleton()->is_bus_solo(get_index()));
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ ur->commit_action();
+
+ updating_bus=false;
+
+}
+void EditorAudioBus::_mute_toggled(){
+
+ updating_bus=true;
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Toggle Audio Bus Mute");
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_mute",get_index(),mute->is_pressed());
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_mute",get_index(),AudioServer::get_singleton()->is_bus_mute(get_index()));
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ ur->commit_action();
+
+ updating_bus=false;
+
+}
+void EditorAudioBus::_bypass_toggled(){
+
+ updating_bus=true;
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Toggle Audio Bus Bypass Effects");
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_bypass_effects",get_index(),bypass->is_pressed());
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_bypass_effects",get_index(),AudioServer::get_singleton()->is_bus_bypassing_effects(get_index()));
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ ur->commit_action();
+
+ updating_bus=false;
+
+
+}
+
+void EditorAudioBus::_send_selected(int p_which) {
+
+ updating_bus=true;
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Select Audio Bus Send");
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_send",get_index(),send->get_item_text(p_which));
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_send",get_index(),AudioServer::get_singleton()->get_bus_send(get_index()));
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ ur->commit_action();
+
+ updating_bus=false;
+}
+
+void EditorAudioBus::_effect_selected() {
+
+ TreeItem *effect = effects->get_selected();
+ if (!effect)
+ return;
+ updating_bus=true;
+
+ if (effect->get_metadata(0)!=Variant()) {
+
+ int index = effect->get_metadata(0);
+ Ref<AudioEffect> effect = AudioServer::get_singleton()->get_bus_effect(get_index(),index);
+ if (effect.is_valid()) {
+ EditorNode::get_singleton()->push_item(effect.ptr());
+ }
+ }
+
+ updating_bus=false;
+
+}
+
+void EditorAudioBus::_effect_edited() {
+
+ if (updating_bus)
+ return;
+
+ TreeItem *effect = effects->get_edited();
+ if (!effect)
+ return;
+
+ if (effect->get_metadata(0)==Variant()) {
+ Rect2 area = effects->get_item_rect(effect);
+
+ effect_options->set_pos(effects->get_global_pos()+area.pos+Vector2(0,area.size.y));
+ effect_options->popup();
+ //add effect
+ } else {
+ int index = effect->get_metadata(0);
+ updating_bus=true;
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Select Audio Bus Send");
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_effect_enabled",get_index(),index,effect->is_checked(0));
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_effect_enabled",get_index(),index,AudioServer::get_singleton()->is_bus_effect_enabled(get_index(),index));
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ ur->commit_action();
+
+ updating_bus=false;
+
+ }
+
+}
+
+void EditorAudioBus::_effect_add(int p_which) {
+
+ if (updating_bus)
+ return;
+
+ StringName name = effect_options->get_item_metadata(p_which);
+
+ Object *fx = ClassDB::instance(name);
+ ERR_FAIL_COND(!fx);
+ AudioEffect *afx = fx->cast_to<AudioEffect>();
+ ERR_FAIL_COND(!afx);
+ Ref<AudioEffect> afxr = Ref<AudioEffect>(afx);
+
+ afxr->set_name(effect_options->get_item_text(p_which));
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Add Audio Bus Effect");
+ ur->add_do_method(AudioServer::get_singleton(),"add_bus_effect",get_index(),afxr,-1);
+ ur->add_undo_method(AudioServer::get_singleton(),"remove_bus_effect",get_index(),AudioServer::get_singleton()->get_bus_effect_count(get_index()));
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ ur->commit_action();
+}
+
+void EditorAudioBus::_gui_input(const InputEvent& p_event) {
+
+ if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && !p_event.key.echo) {
+ accept_event();
+ emit_signal("delete_request");
+ }
+ if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==2 && p_event.mouse_button.pressed) {
+
+ Vector2 pos = Vector2(p_event.mouse_button.x,p_event.mouse_button.y);
+ delete_popup->set_pos(get_global_pos()+pos);
+ delete_popup->popup();
+ }
+}
+
+void EditorAudioBus::_delete_pressed(int p_option) {
+
+ if (p_option==1) {
+ emit_signal("delete_request");
+ } else if (p_option==0) {
+ //duplicate
+ emit_signal("duplicate_request",get_index());
+ }
+
+}
+
+
+Variant EditorAudioBus::get_drag_data(const Point2& p_point) {
+
+ if (get_index()==0) {
+ return Variant();
+ }
+
+ Control *c = memnew(Control);
+ Panel *p = memnew( Panel );
+ c->add_child(p);
+ p->add_style_override("panel",get_stylebox("focus","Button"));
+ p->set_size(get_size());
+ p->set_pos(-p_point);
+ set_drag_preview(c);
+ Dictionary d;
+ d["type"]="move_audio_bus";
+ d["index"]=get_index();
+ emit_signal("drop_end_request");
+ return d;
+}
+
+bool EditorAudioBus::can_drop_data(const Point2& p_point,const Variant& p_data) const {
+
+ if (get_index()==0)
+ return false;
+ Dictionary d=p_data;
+ if (d.has("type") && String(d["type"])=="move_audio_bus") {
+ return true;
+ }
+
+ return false;
+}
+void EditorAudioBus::drop_data(const Point2& p_point,const Variant& p_data) {
+
+ Dictionary d=p_data;
+ emit_signal("dropped",d["index"],get_index());
+
+}
+
+Variant EditorAudioBus::get_drag_data_fw(const Point2& p_point,Control* p_from) {
+
+ print_line("drag fw");
+ TreeItem *item = effects->get_item_at_pos(p_point);
+ if (!item) {
+ print_line("no item");
+ return Variant();
+ }
+
+ Variant md = item->get_metadata(0);
+
+ if (md.get_type()==Variant::INT) {
+ Dictionary fxd;
+ fxd["type"]="audio_bus_effect";
+ fxd["bus"]=get_index();
+ fxd["effect"]=md;
+
+ Label *l = memnew( Label );
+ l->set_text(item->get_text(0));
+ effects->set_drag_preview(l);
+
+ return fxd;
+ }
+
+ return Variant();
+
+}
+
+bool EditorAudioBus::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
+
+ Dictionary d = p_data;
+ if (!d.has("type") || String(d["type"])!="audio_bus_effect")
+ return false;
+
+ TreeItem *item = effects->get_item_at_pos(p_point);
+ if (!item)
+ return false;
+
+ effects->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
+
+ return true;
+}
+
+void EditorAudioBus::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
+
+ Dictionary d = p_data;
+
+ TreeItem *item = effects->get_item_at_pos(p_point);
+ if (!item)
+ return;
+ int pos=effects->get_drop_section_at_pos(p_point);
+ Variant md = item->get_metadata(0);
+
+ int paste_at;
+ int bus = d["bus"];
+ int effect = d["effect"];
+
+ if (md.get_type()==Variant::INT) {
+ paste_at=md;
+ if (pos>0)
+ paste_at++;
+
+ if (bus==get_index() && paste_at >effect) {
+ paste_at--;
+ }
+ } else {
+ paste_at=-1;
+ }
+
+
+ bool enabled = AudioServer::get_singleton()->is_bus_effect_enabled(bus,effect);
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Move Bus Effect");
+ ur->add_do_method(AudioServer::get_singleton(),"remove_bus_effect",bus,effect);
+ ur->add_do_method(AudioServer::get_singleton(),"add_bus_effect",get_index(),AudioServer::get_singleton()->get_bus_effect(bus,effect),paste_at);
+
+ if (paste_at==-1) {
+ paste_at = AudioServer::get_singleton()->get_bus_effect_count(get_index());
+ if (bus==get_index()) {
+ paste_at--;
+ }
+ }
+ if (!enabled) {
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_effect_enabled",get_index(),paste_at,false);
+ }
+
+ ur->add_undo_method(AudioServer::get_singleton(),"remove_bus_effect",get_index(),paste_at);
+ ur->add_undo_method(AudioServer::get_singleton(),"add_bus_effect",bus,AudioServer::get_singleton()->get_bus_effect(bus,effect),effect);
+ if (!enabled) {
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_effect_enabled",bus,effect,false);
+ }
+
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ if (get_index()!=bus) {
+ ur->add_do_method(buses,"_update_bus",bus);
+ ur->add_undo_method(buses,"_update_bus",bus);
+ }
+ ur->commit_action();
+
+
+
+}
+
+void EditorAudioBus::_delete_effect_pressed(int p_option) {
+
+ TreeItem * item = effects->get_selected();
+ if (!item)
+ return;
+
+ if (item->get_metadata(0).get_type()!=Variant::INT)
+ return;
+
+ int index = item->get_metadata(0);
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Delete Bus Effect");
+ ur->add_do_method(AudioServer::get_singleton(),"remove_bus_effect",get_index(),index);
+ ur->add_undo_method(AudioServer::get_singleton(),"add_bus_effect",get_index(),AudioServer::get_singleton()->get_bus_effect(get_index(),index),index);
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_effect_enabled",get_index(),index,AudioServer::get_singleton()->is_bus_effect_enabled(get_index(),index));
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ ur->commit_action();
+
+
+}
+
+void EditorAudioBus::_effect_rmb(const Vector2& p_pos) {
+
+ TreeItem * item = effects->get_selected();
+ if (!item)
+ return;
+
+ if (item->get_metadata(0).get_type()!=Variant::INT)
+ return;
+
+ delete_effect_popup->set_pos(get_global_mouse_pos());
+ delete_effect_popup->popup();
+}
+
+void EditorAudioBus::_bind_methods() {
+
+ ClassDB::bind_method("update_bus",&EditorAudioBus::update_bus);
+ ClassDB::bind_method("update_send",&EditorAudioBus::update_send);
+ ClassDB::bind_method("_name_changed",&EditorAudioBus::_name_changed);
+ ClassDB::bind_method("_volume_db_changed",&EditorAudioBus::_volume_db_changed);
+ ClassDB::bind_method("_solo_toggled",&EditorAudioBus::_solo_toggled);
+ ClassDB::bind_method("_mute_toggled",&EditorAudioBus::_mute_toggled);
+ ClassDB::bind_method("_bypass_toggled",&EditorAudioBus::_bypass_toggled);
+ ClassDB::bind_method("_name_focus_exit",&EditorAudioBus::_name_focus_exit);
+ ClassDB::bind_method("_send_selected",&EditorAudioBus::_send_selected);
+ ClassDB::bind_method("_effect_edited",&EditorAudioBus::_effect_edited);
+ ClassDB::bind_method("_effect_selected",&EditorAudioBus::_effect_selected);
+ ClassDB::bind_method("_effect_add",&EditorAudioBus::_effect_add);
+ ClassDB::bind_method("_gui_input",&EditorAudioBus::_gui_input);
+ ClassDB::bind_method("_delete_pressed",&EditorAudioBus::_delete_pressed);
+ ClassDB::bind_method("get_drag_data_fw",&EditorAudioBus::get_drag_data_fw);
+ ClassDB::bind_method("can_drop_data_fw",&EditorAudioBus::can_drop_data_fw);
+ ClassDB::bind_method("drop_data_fw",&EditorAudioBus::drop_data_fw);
+ ClassDB::bind_method("_delete_effect_pressed",&EditorAudioBus::_delete_effect_pressed);
+ ClassDB::bind_method("_effect_rmb",&EditorAudioBus::_effect_rmb);
+
+
+
+ ADD_SIGNAL(MethodInfo("duplicate_request"));
+ ADD_SIGNAL(MethodInfo("delete_request"));
+ ADD_SIGNAL(MethodInfo("drop_end_request"));
+ ADD_SIGNAL(MethodInfo("dropped"));
+
+}
+
+EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses) {
+
+ buses=p_buses;
+ updating_bus=false;
+
+ VBoxContainer *vb = memnew( VBoxContainer );
+ add_child(vb);
+
+ set_v_size_flags(SIZE_EXPAND_FILL);
+
+ track_name = memnew( LineEdit );
+ vb->add_child(track_name);
+ track_name->connect("text_entered",this,"_name_changed");
+ track_name->connect("focus_exited",this,"_name_focus_exit");
+
+ HBoxContainer *hbc = memnew( HBoxContainer);
+ vb->add_child(hbc);
+ hbc->add_spacer();
+ solo = memnew( ToolButton );
+ solo->set_text("S");
+ solo->set_toggle_mode(true);
+ solo->set_modulate(Color(0.8,1.2,0.8));
+ solo->set_focus_mode(FOCUS_NONE);
+ solo->connect("pressed",this,"_solo_toggled");
+ hbc->add_child(solo);
+ mute = memnew( ToolButton );
+ mute->set_text("M");
+ mute->set_toggle_mode(true);
+ mute->set_modulate(Color(1.2,0.8,0.8));
+ mute->set_focus_mode(FOCUS_NONE);
+ mute->connect("pressed",this,"_mute_toggled");
+ hbc->add_child(mute);
+ bypass = memnew( ToolButton );
+ bypass->set_text("B");
+ bypass->set_toggle_mode(true);
+ bypass->set_modulate(Color(1.1,1.1,0.8));
+ bypass->set_focus_mode(FOCUS_NONE);
+ bypass->connect("pressed",this,"_bypass_toggled");
+ hbc->add_child(bypass);
+ hbc->add_spacer();
+
+ HBoxContainer *hb = memnew( HBoxContainer );
+ vb->add_child(hb);
+ slider = memnew( VSlider );
+ slider->set_min(-80);
+ slider->set_max(24);
+ slider->set_step(0.1);
+
+ slider->connect("value_changed",this,"_volume_db_changed");
+ hb->add_child(slider);
+ vu_l = memnew( TextureProgress );
+ vu_l->set_fill_mode(TextureProgress::FILL_BOTTOM_TO_TOP);
+ hb->add_child(vu_l);
+ vu_l->set_min(-80);
+ vu_l->set_max(24);
+ vu_l->set_step(0.1);
+
+ vu_r = memnew( TextureProgress );
+ vu_r->set_fill_mode(TextureProgress::FILL_BOTTOM_TO_TOP);
+ hb->add_child(vu_r);
+ vu_r->set_min(-80);
+ vu_r->set_max(24);
+ vu_r->set_step(0.1);
+
+ scale = memnew( TextureRect );
+ hb->add_child(scale);
+
+ //add_child(hb);
+
+ effects = memnew( Tree );
+ effects->set_hide_root(true);
+ effects->set_custom_minimum_size(Size2(0,90)*EDSCALE);
+ effects->set_hide_folding(true);
+ vb->add_child(effects);
+ effects->connect("item_edited",this,"_effect_edited");
+ effects->connect("cell_selected",this,"_effect_selected");
+ effects->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true);
+ effects->set_drag_forwarding(this);
+ effects->connect("item_rmb_selected",this,"_effect_rmb");
+ effects->set_allow_rmb_select(true);
+
+ send = memnew( OptionButton );
+ send->set_clip_text(true);
+ send->connect("item_selected",this,"_send_selected");
+ vb->add_child(send);
+
+ set_focus_mode(FOCUS_CLICK);
+
+ effect_options = memnew( PopupMenu );
+ effect_options->connect("index_pressed",this,"_effect_add");
+ add_child(effect_options);
+ List<StringName> effects;
+ ClassDB::get_inheriters_from_class("AudioEffect",&effects);
+ effects.sort_custom<StringName::AlphCompare>();
+ for (List<StringName>::Element *E=effects.front();E;E=E->next()) {
+ if (!ClassDB::can_instance(E->get()))
+ continue;
+
+ Ref<Texture> icon;
+ if (has_icon(E->get(),"EditorIcons")) {
+ icon = get_icon(E->get(),"EditorIcons");
+ }
+ String name = E->get().operator String().replace("AudioEffect","");
+ effect_options->add_item(name);
+ effect_options->set_item_metadata(effect_options->get_item_count()-1,E->get());
+ effect_options->set_item_icon(effect_options->get_item_count()-1,icon);
+ }
+
+ delete_popup = memnew( PopupMenu );
+ delete_popup->add_item("Duplicate");
+ delete_popup->add_item("Delete");
+ add_child(delete_popup);
+ delete_popup->connect("index_pressed",this,"_delete_pressed");
+
+ delete_effect_popup = memnew( PopupMenu );
+ delete_effect_popup->add_item("Delete Effect");
+ add_child(delete_effect_popup);
+ delete_effect_popup->connect("index_pressed",this,"_delete_effect_pressed");
+
+}
+
+
+
+bool EditorAudioBusDrop::can_drop_data(const Point2& p_point,const Variant& p_data) const {
+
+ Dictionary d=p_data;
+ if (d.has("type") && String(d["type"])=="move_audio_bus") {
+ return true;
+ }
+
+ return false;
+}
+void EditorAudioBusDrop::drop_data(const Point2& p_point,const Variant& p_data){
+
+ Dictionary d=p_data;
+ emit_signal("dropped",d["index"],-1);
+
+}
+
+void EditorAudioBusDrop::_bind_methods() {
+
+ ADD_SIGNAL(MethodInfo("dropped"));
+}
+
+EditorAudioBusDrop::EditorAudioBusDrop() {
+
+
+}
+
+
+void EditorAudioBuses::_update_buses() {
+
+ while(bus_hb->get_child_count()>0) {
+ memdelete(bus_hb->get_child(0));
+ }
+
+ drop_end=NULL;
+
+ for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) {
+
+ EditorAudioBus *audio_bus = memnew( EditorAudioBus(this) );
+ if (i==0) {
+ audio_bus->set_self_modulate(Color(1,0.9,0.9));
+ }
+ bus_hb->add_child(audio_bus);
+ audio_bus->connect("delete_request",this,"_delete_bus",varray(audio_bus),CONNECT_DEFERRED);
+ audio_bus->connect("duplicate_request",this,"_duplicate_bus",varray(),CONNECT_DEFERRED);
+ audio_bus->connect("drop_end_request",this,"_request_drop_end");
+ audio_bus->connect("dropped",this,"_drop_at_index",varray(),CONNECT_DEFERRED);
+
+
+
+ }
+}
+
+EditorAudioBuses *EditorAudioBuses::register_editor() {
+
+ EditorAudioBuses * audio_buses = memnew( EditorAudioBuses );
+ EditorNode::get_singleton()->add_bottom_panel_item("Audio",audio_buses);
+ return audio_buses;
+}
+
+void EditorAudioBuses::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_READY) {
+ _update_buses();
+ }
+
+ if (p_what==NOTIFICATION_DRAG_END) {
+ if (drop_end) {
+ drop_end->queue_delete();
+ drop_end=NULL;
+ }
+ }
+
+ if (p_what==NOTIFICATION_PROCESS) {
+
+ //check if anything was edited
+ bool edited = AudioServer::get_singleton()->is_edited();
+ for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) {
+ for(int j=0;j<AudioServer::get_singleton()->get_bus_effect_count(i);j++) {
+ Ref<AudioEffect> effect = AudioServer::get_singleton()->get_bus_effect(i,j);
+ if (effect->is_edited()) {
+ edited=true;
+ effect->set_edited(false);
+ }
+ }
+ }
+
+ AudioServer::get_singleton()->set_edited(false);
+
+ if (edited) {
+
+ save_timer->start();
+ }
+ }
+
+}
+
+
+void EditorAudioBuses::_add_bus() {
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+ //need to simulate new name, so we can undi :(
+ ur->create_action("Add Audio Bus");
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_count",AudioServer::get_singleton()->get_bus_count()+1);
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_count",AudioServer::get_singleton()->get_bus_count());
+ ur->add_do_method(this,"_update_buses");
+ ur->add_undo_method(this,"_update_buses");
+ ur->commit_action();
+
+}
+
+void EditorAudioBuses::_update_bus(int p_index) {
+
+ if (p_index>=bus_hb->get_child_count())
+ return;
+
+ bus_hb->get_child(p_index)->call("update_bus");
+}
+
+void EditorAudioBuses::_update_sends() {
+
+ for(int i=0;i<bus_hb->get_child_count();i++) {
+ bus_hb->get_child(i)->call("update_send");
+ }
+}
+
+void EditorAudioBuses::_delete_bus(Object* p_which) {
+
+ EditorAudioBus *bus = p_which->cast_to<EditorAudioBus>();
+ int index = bus->get_index();
+ if (index==0) {
+ EditorNode::get_singleton()->show_warning("Master bus can't be deleted!");
+ return;
+ }
+
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+ ur->create_action("Delete Audio Bus");
+ ur->add_do_method(AudioServer::get_singleton(),"remove_bus",index);
+ ur->add_undo_method(AudioServer::get_singleton(),"add_bus",index);
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_name",index,AudioServer::get_singleton()->get_bus_name(index));
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_volume_db",index,AudioServer::get_singleton()->get_bus_volume_db(index));
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_send",index,AudioServer::get_singleton()->get_bus_send(index));
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_solo",index,AudioServer::get_singleton()->is_bus_solo(index));
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_mute",index,AudioServer::get_singleton()->is_bus_mute(index));
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_bypass_effects",index,AudioServer::get_singleton()->is_bus_bypassing_effects(index));
+ for(int i=0;i<AudioServer::get_singleton()->get_bus_effect_count(index);i++) {
+
+ ur->add_undo_method(AudioServer::get_singleton(),"add_bus_effect",index,AudioServer::get_singleton()->get_bus_effect(index,i));
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_effect_enabled",index,i,AudioServer::get_singleton()->is_bus_effect_enabled(index,i));
+ }
+ ur->add_do_method(this,"_update_buses");
+ ur->add_undo_method(this,"_update_buses");
+ ur->commit_action();
+
+}
+
+
+void EditorAudioBuses::_duplicate_bus(int p_which) {
+
+ int add_at_pos = p_which+1;
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Duplicate Audio Bus");
+ ur->add_do_method(AudioServer::get_singleton(),"add_bus",add_at_pos);
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_name",add_at_pos,AudioServer::get_singleton()->get_bus_name(p_which)+" Copy");
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_volume_db",add_at_pos,AudioServer::get_singleton()->get_bus_volume_db(p_which));
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_send",add_at_pos,AudioServer::get_singleton()->get_bus_send(p_which));
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_solo",add_at_pos,AudioServer::get_singleton()->is_bus_solo(p_which));
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_mute",add_at_pos,AudioServer::get_singleton()->is_bus_mute(p_which));
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_bypass_effects",add_at_pos,AudioServer::get_singleton()->is_bus_bypassing_effects(p_which));
+ for(int i=0;i<AudioServer::get_singleton()->get_bus_effect_count(p_which);i++) {
+
+ ur->add_do_method(AudioServer::get_singleton(),"add_bus_effect",add_at_pos,AudioServer::get_singleton()->get_bus_effect(p_which,i));
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_effect_enabled",add_at_pos,i,AudioServer::get_singleton()->is_bus_effect_enabled(p_which,i));
+ }
+ ur->add_undo_method(AudioServer::get_singleton(),"remove_bus",add_at_pos);
+ ur->add_do_method(this,"_update_buses");
+ ur->add_undo_method(this,"_update_buses");
+ ur->commit_action();
+
+}
+
+void EditorAudioBuses::_request_drop_end() {
+
+ if (!drop_end && bus_hb->get_child_count()) {
+ drop_end = memnew( EditorAudioBusDrop );
+
+ bus_hb->add_child(drop_end);
+ drop_end->set_custom_minimum_size(bus_hb->get_child(0)->cast_to<Control>()->get_size());
+ drop_end->connect("dropped",this,"_drop_at_index",varray(),CONNECT_DEFERRED);
+ }
+}
+
+void EditorAudioBuses::_drop_at_index(int p_bus,int p_index) {
+
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+ //need to simulate new name, so we can undi :(
+ ur->create_action("Move Audio Bus");
+ ur->add_do_method(AudioServer::get_singleton(),"move_bus",p_bus,p_index);
+ int final_pos;
+ if (p_index==p_bus) {
+ final_pos=p_bus;
+ } else if (p_index==-1) {
+ final_pos = AudioServer::get_singleton()->get_bus_count()-1;
+ } else if (p_index<p_bus) {
+ final_pos = p_index;
+ } else {
+ final_pos = p_index -1;
+ }
+ ur->add_undo_method(AudioServer::get_singleton(),"move_bus",final_pos,p_bus);
+
+ ur->add_do_method(this,"_update_buses");
+ ur->add_undo_method(this,"_update_buses");
+ ur->commit_action();
+}
+
+void EditorAudioBuses::_server_save() {
+
+ Ref<AudioBusLayout> state = AudioServer::get_singleton()->generate_bus_layout();
+ ResourceSaver::save(edited_path,state);
+
+}
+
+void EditorAudioBuses::_select_layout() {
+
+ EditorNode::get_singleton()->get_filesystem_dock()->select_file(edited_path);
+}
+
+void EditorAudioBuses::_save_as_layout() {
+
+ file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ file_dialog->set_title(TTR("Save Audio Bus Layout As.."));
+ file_dialog->set_current_path(edited_path);
+ file_dialog->popup_centered_ratio();
+ new_layout=false;
+}
+
+
+void EditorAudioBuses::_new_layout() {
+
+ file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ file_dialog->set_title(TTR("Location for New Layout.."));
+ file_dialog->set_current_path(edited_path);
+ file_dialog->popup_centered_ratio();
+ new_layout=true;
+}
+
+void EditorAudioBuses::_load_layout() {
+
+ file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ file_dialog->set_title(TTR("Open Audio Bus Layout"));
+ file_dialog->set_current_path(edited_path);
+ file_dialog->popup_centered_ratio();
+ new_layout=false;
+}
+
+
+void EditorAudioBuses::_load_default_layout() {
+
+
+ Ref<AudioBusLayout> state = ResourceLoader::load("res://default_bus_layout.tres");
+ if (state.is_null()) {
+ EditorNode::get_singleton()->show_warning("There is no 'res://default_bus_layout.tres' file.");
+ return;
+ }
+
+ edited_path="res://default_bus_layout.tres";
+ file->set_text(edited_path.get_file());
+ AudioServer::get_singleton()->set_bus_layout(state);
+ _update_buses();
+ EditorNode::get_singleton()->get_undo_redo()->clear_history();
+ call_deferred("_select_layout");
+}
+
+void EditorAudioBuses::_file_dialog_callback(const String& p_string) {
+
+ if (file_dialog->get_mode()==EditorFileDialog::MODE_OPEN_FILE) {
+ Ref<AudioBusLayout> state = ResourceLoader::load(p_string);
+ if (state.is_null()) {
+ EditorNode::get_singleton()->show_warning("Invalid file, not an audio bus layout.");
+ return;
+ }
+
+ edited_path=p_string;
+ file->set_text(p_string.get_file());
+ AudioServer::get_singleton()->set_bus_layout(state);
+ _update_buses();
+ EditorNode::get_singleton()->get_undo_redo()->clear_history();
+ call_deferred("_select_layout");
+
+ } else if (file_dialog->get_mode()==EditorFileDialog::MODE_SAVE_FILE) {
+
+ if (new_layout) {
+ Ref<AudioBusLayout> empty_state;
+ empty_state.instance();
+ AudioServer::get_singleton()->set_bus_layout(empty_state);
+ }
+
+ Error err = ResourceSaver::save(p_string,AudioServer::get_singleton()->generate_bus_layout());
+
+ if (err!=OK) {
+ EditorNode::get_singleton()->show_warning("Error saving file: "+p_string);
+ return;
+ }
+
+ edited_path=p_string;
+ file->set_text(p_string.get_file());
+ _update_buses();
+ EditorNode::get_singleton()->get_undo_redo()->clear_history();
+ call_deferred("_select_layout");
+ }
+
+}
+
+void EditorAudioBuses::_bind_methods() {
+
+ ClassDB::bind_method("_add_bus",&EditorAudioBuses::_add_bus);
+ ClassDB::bind_method("_update_buses",&EditorAudioBuses::_update_buses);
+ ClassDB::bind_method("_update_bus",&EditorAudioBuses::_update_bus);
+ ClassDB::bind_method("_update_sends",&EditorAudioBuses::_update_sends);
+ ClassDB::bind_method("_delete_bus",&EditorAudioBuses::_delete_bus);
+ ClassDB::bind_method("_request_drop_end",&EditorAudioBuses::_request_drop_end);
+ ClassDB::bind_method("_drop_at_index",&EditorAudioBuses::_drop_at_index);
+ ClassDB::bind_method("_server_save",&EditorAudioBuses::_server_save);
+ ClassDB::bind_method("_select_layout",&EditorAudioBuses::_select_layout);
+ ClassDB::bind_method("_save_as_layout",&EditorAudioBuses::_save_as_layout);
+ ClassDB::bind_method("_load_layout",&EditorAudioBuses::_load_layout);
+ ClassDB::bind_method("_load_default_layout",&EditorAudioBuses::_load_default_layout);
+ ClassDB::bind_method("_new_layout",&EditorAudioBuses::_new_layout);
+ ClassDB::bind_method("_duplicate_bus",&EditorAudioBuses::_duplicate_bus);
+
+ ClassDB::bind_method("_file_dialog_callback",&EditorAudioBuses::_file_dialog_callback);
+}
+
+EditorAudioBuses::EditorAudioBuses()
+{
+
+ drop_end = NULL;
+ top_hb = memnew( HBoxContainer );
+ add_child(top_hb);
+
+ add = memnew( Button );
+ top_hb->add_child(add);;
+ add->set_text(TTR("Add Bus"));
+
+ add->connect("pressed",this,"_add_bus");
+
+
+
+ top_hb->add_spacer();
+
+ file = memnew( ToolButton );
+ file->set_text("default_bus_layout.tres");
+ top_hb->add_child(file);
+ file->connect("pressed",this,"_select_layout");
+
+ load = memnew( Button );
+ load->set_text(TTR("Load"));
+ top_hb->add_child(load);
+ load->connect("pressed",this,"_load_layout");
+
+ save_as = memnew( Button );
+ save_as->set_text(TTR("Save As"));
+ top_hb->add_child(save_as);
+ save_as->connect("pressed",this,"_save_as_layout");
+
+ _default = memnew( Button );
+ _default->set_text(TTR("Default"));
+ top_hb->add_child(_default);
+ _default->connect("pressed",this,"_load_default_layout");
+
+ _new = memnew( Button );
+ _new->set_text(TTR("Create"));
+ top_hb->add_child(_new);
+ _new->connect("pressed",this,"_new_layout");
+
+ bus_scroll = memnew( ScrollContainer );
+ bus_scroll->set_v_size_flags(SIZE_EXPAND_FILL);
+ bus_scroll->set_enable_h_scroll(true);
+ bus_scroll->set_enable_v_scroll(false);
+ add_child(bus_scroll);
+ bus_hb = memnew( HBoxContainer );
+ bus_scroll->add_child(bus_hb);
+
+ save_timer=memnew(Timer);
+ save_timer->set_wait_time(0.8);
+ save_timer->set_one_shot(true);
+ add_child(save_timer);
+ save_timer->connect("timeout",this,"_server_save");
+
+ set_v_size_flags(SIZE_EXPAND_FILL);
+
+
+ edited_path = "res://default_bus_layout.tres";
+
+ file_dialog = memnew( EditorFileDialog );
+ List<String> ext;
+ ResourceLoader::get_recognized_extensions_for_type("AudioServerState",&ext);
+ for (List<String>::Element *E=ext.front();E;E=E->next()) {
+ file_dialog->add_filter("*."+E->get()+"; Audio Bus State");
+ }
+ add_child(file_dialog);
+ file_dialog->connect("file_selected",this,"_file_dialog_callback");
+
+ set_process(true);
+
+}
+void EditorAudioBuses::open_layout(const String& p_path) {
+
+ EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
+
+ Ref<AudioBusLayout> state = ResourceLoader::load(p_path);
+ if (state.is_null()) {
+ EditorNode::get_singleton()->show_warning("Invalid file, not an audio bus layout.");
+ return;
+ }
+
+ edited_path=p_path;
+ file->set_text(p_path.get_file());
+ AudioServer::get_singleton()->set_bus_layout(state);
+ _update_buses();
+ EditorNode::get_singleton()->get_undo_redo()->clear_history();
+ call_deferred("_select_layout");
+}
+
+void AudioBusesEditorPlugin::edit(Object *p_node) {
+
+ if (p_node->cast_to<AudioBusLayout>()) {
+
+ String path = p_node->cast_to<AudioBusLayout>()->get_path();
+ if (path.is_resource_file()) {
+ audio_bus_editor->open_layout(path);
+ }
+ }
+}
+
+bool AudioBusesEditorPlugin::handles(Object *p_node) const {
+
+ return (p_node->cast_to<AudioBusLayout>()!=NULL);
+}
+
+void AudioBusesEditorPlugin::make_visible(bool p_visible){
+
+
+}
+
+AudioBusesEditorPlugin::AudioBusesEditorPlugin(EditorAudioBuses *p_node) {
+
+ audio_bus_editor=p_node;
+}
+
+AudioBusesEditorPlugin::~AudioBusesEditorPlugin() {
+
+}
diff --git a/tools/editor/editor_audio_buses.h b/tools/editor/editor_audio_buses.h
new file mode 100644
index 0000000000..e44f8cd579
--- /dev/null
+++ b/tools/editor/editor_audio_buses.h
@@ -0,0 +1,186 @@
+#ifndef EDITORAUDIOBUSES_H
+#define EDITORAUDIOBUSES_H
+
+
+#include "scene/gui/box_container.h"
+#include "scene/gui/button.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/scroll_container.h"
+#include "scene/gui/panel_container.h"
+#include "scene/gui/slider.h"
+#include "scene/gui/texture_progress.h"
+#include "scene/gui/texture_rect.h"
+#include "scene/gui/line_edit.h"
+#include "scene/gui/tree.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/panel.h"
+#include "tools/editor/editor_file_dialog.h"
+#include "editor_plugin.h"
+
+class EditorAudioBuses;
+
+class EditorAudioBus : public PanelContainer {
+
+ GDCLASS( EditorAudioBus, PanelContainer )
+
+ bool prev_active;
+ float peak_l;
+ float peak_r;
+
+ Ref<Texture> disabled_vu;
+ LineEdit *track_name;
+ VSlider *slider;
+ TextureProgress *vu_l;
+ TextureProgress *vu_r;
+ TextureRect *scale;
+ OptionButton *send;
+
+ PopupMenu *effect_options;
+ PopupMenu *delete_popup;
+ PopupMenu *delete_effect_popup;
+
+ Button *solo;
+ Button *mute;
+ Button *bypass;
+
+ Tree *effects;
+
+ bool updating_bus;
+
+ void _gui_input(const InputEvent& p_event);
+ void _delete_pressed(int p_option);
+
+ void _name_changed(const String& p_new_name);
+ void _name_focus_exit() { _name_changed(track_name->get_text()); }
+ void _volume_db_changed(float p_db);
+ void _solo_toggled();
+ void _mute_toggled();
+ void _bypass_toggled();
+ void _send_selected(int p_which);
+ void _effect_edited();
+ void _effect_add(int p_which);
+ void _effect_selected();
+ void _delete_effect_pressed(int p_option);
+ void _effect_rmb(const Vector2& p_pos);
+
+
+ virtual Variant get_drag_data(const Point2& p_point);
+ virtual bool can_drop_data(const Point2& p_point,const Variant& p_data) const;
+ virtual void drop_data(const Point2& p_point,const Variant& p_data);
+
+
+ Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
+ bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
+ void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
+
+friend class EditorAudioBuses;
+
+ EditorAudioBuses *buses;
+
+protected:
+
+ static void _bind_methods();
+ void _notification(int p_what);
+public:
+
+ void update_bus();
+ void update_send();
+
+ EditorAudioBus(EditorAudioBuses *p_buses=NULL);
+};
+
+
+class EditorAudioBusDrop : public Panel {
+
+ GDCLASS(EditorAudioBusDrop,Panel);
+
+ virtual bool can_drop_data(const Point2& p_point,const Variant& p_data) const;
+ virtual void drop_data(const Point2& p_point,const Variant& p_data);
+protected:
+
+ static void _bind_methods();
+public:
+
+ EditorAudioBusDrop();
+};
+
+class EditorAudioBuses : public VBoxContainer {
+
+ GDCLASS(EditorAudioBuses,VBoxContainer)
+
+ HBoxContainer *top_hb;
+
+ Button *add;
+ ScrollContainer *bus_scroll;
+ HBoxContainer *bus_hb;
+
+ EditorAudioBusDrop *drop_end;
+
+ Button *file;
+ Button *load;
+ Button *save_as;
+ Button *_default;
+ Button *_new;
+
+ Timer *save_timer;
+ String edited_path;
+
+ void _add_bus();
+ void _update_buses();
+ void _update_bus(int p_index);
+ void _update_sends();
+
+ void _delete_bus(Object* p_which);
+ void _duplicate_bus(int p_which);
+
+
+ void _request_drop_end();
+ void _drop_at_index(int p_bus,int p_index);
+
+ void _server_save();
+
+ void _select_layout();
+ void _load_layout();
+ void _save_as_layout();
+ void _load_default_layout();
+ void _new_layout();
+
+ EditorFileDialog *file_dialog;
+ bool new_layout;
+
+ void _file_dialog_callback(const String& p_string);
+
+protected:
+
+ static void _bind_methods();
+ void _notification(int p_what);
+public:
+
+ void open_layout(const String& p_path);
+
+ static EditorAudioBuses* register_editor();
+
+ EditorAudioBuses();
+};
+
+
+
+class AudioBusesEditorPlugin : public EditorPlugin {
+
+ GDCLASS( AudioBusesEditorPlugin, EditorPlugin );
+
+ EditorAudioBuses *audio_bus_editor;
+public:
+
+ virtual String get_name() const { return "SampleLibrary"; }
+ bool has_main_screen() const { return false; }
+ virtual void edit(Object *p_node);
+ virtual bool handles(Object *p_node) const;
+ virtual void make_visible(bool p_visible);
+
+ AudioBusesEditorPlugin(EditorAudioBuses *p_node);
+ ~AudioBusesEditorPlugin();
+
+};
+
+#endif // EDITORAUDIOBUSES_H
diff --git a/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp
index a94604743c..6ef238920d 100644
--- a/tools/editor/editor_import_export.cpp
+++ b/tools/editor/editor_import_export.cpp
@@ -2094,13 +2094,21 @@ void EditorImportExport::save_config() {
if (image_groups.size() && image_group_files.size()){
- Vector<String> igfsave;
- igfsave.resize(image_group_files.size()*2);
+ Vector<String> igfkeys;
+ igfkeys.resize(image_group_files.size());
int idx=0;
for (Map<StringName,StringName>::Element *E=image_group_files.front();E;E=E->next()) {
+ igfkeys[idx++]=E->key();
+ }
+ igfkeys.sort();
+
+ Vector<String> igfsave;
+ igfsave.resize(image_group_files.size()*2);
+ idx=0;
+ for (int i=0;i<igfkeys.size();++i) {
- igfsave[idx++]=E->key();
- igfsave[idx++]=E->get();
+ igfsave[idx++]=igfkeys[i];
+ igfsave[idx++]=image_group_files[igfkeys[i]];
}
cf->set_value("image_group_files","files",igfsave);
}
diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp
index 0c8d786f03..bd54eaceb6 100644
--- a/tools/editor/editor_node.cpp
+++ b/tools/editor/editor_node.cpp
@@ -55,7 +55,7 @@
#include "animation_editor.h"
#include "io/stream_peer_ssl.h"
#include "main/input_default.h"
-
+#include "os/input.h"
// plugins
#include "plugins/sprite_frames_editor_plugin.h"
#include "plugins/texture_region_editor_plugin.h"
@@ -115,6 +115,7 @@
#include "plugins/editor_preview_plugins.h"
#include "editor_initialize_ssl.h"
+#include "editor_audio_buses.h"
#include "script_editor_debugger.h"
EditorNode *EditorNode::singleton=NULL;
@@ -189,6 +190,9 @@ void EditorNode::_unhandled_input(const InputEvent& p_event) {
next_tab = next_tab >= 0 ? next_tab : editor_data.get_edited_scene_count() - 1;
_scene_tab_changed(next_tab);
}
+ if (ED_IS_SHORTCUT("editor/filter_files", p_event)) {
+ filesystem_dock->focus_on_filter();
+ }
switch(p_event.key.scancode) {
@@ -1924,17 +1928,17 @@ void EditorNode::_run(bool p_current,const String& p_custom) {
editor_data.save_editor_external_data();
}
- if (bool(EDITOR_DEF("run/always_clear_output_on_play", true))) {
+ if (bool(EDITOR_DEF("run/output/always_clear_output_on_play", true))) {
log->clear();
}
- if (bool(EDITOR_DEF("run/always_open_output_on_play", true))) {
+ if (bool(EDITOR_DEF("run/output/always_open_output_on_play", true))) {
make_bottom_panel_item_visible(log);
}
List<String> breakpoints;
editor_data.get_editor_breakpoints(&breakpoints);
-
+
args = GlobalConfig::get_singleton()->get("editor/main_run_args");
Error error = editor_run.run(run_filename,args,breakpoints,current_filename);
@@ -2075,14 +2079,6 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
quick_open->set_title(TTR("Quick Open Script.."));
} break;
- case FILE_QUICK_OPEN_FILE: {
-
-
- //quick_open->popup("Resource", false, true);
- //quick_open->set_title("Quick Search File..");
- scenes_dock->focus_on_filter();
-
- } break;
case FILE_RUN_SCRIPT: {
file_script->popup_centered_ratio();
@@ -2409,8 +2405,12 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
case EDIT_UNDO: {
- if (OS::get_singleton()->get_mouse_button_state())
+
+
+ if (Input::get_singleton()->get_mouse_button_mask()&0x7) {
+ print_line("no because state");
break; // can't undo while mouse buttons are pressed
+ }
String action = editor_data.get_undo_redo().get_current_action_name();
if (action!="")
@@ -2420,7 +2420,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
} break;
case EDIT_REDO: {
- if (OS::get_singleton()->get_mouse_button_state())
+ if (Input::get_singleton()->get_mouse_button_mask()&0x7)
break; // can't redo while mouse buttons are pressed
editor_data.get_undo_redo().redo();
@@ -2807,10 +2807,10 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
update_menu->get_popup()->set_item_checked(1,true);
OS::get_singleton()->set_low_processor_usage_mode(true);
} break;
- case SETTINGS_UPDATE_SPINNER_HIDE: {
+ case SETTINGS_UPDATE_SPINNER_HIDE: {
update_menu->set_icon(gui_base->get_icon("Collapse","EditorIcons"));
- update_menu->get_popup()->toggle_item_checked(3);
- } break;
+ update_menu->get_popup()->toggle_item_checked(3);
+ } break;
case SETTINGS_PREFERENCES: {
settings_config_dialog->popup_edit_settings();
@@ -2935,16 +2935,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
default: {
- if (p_option>=TOOL_MENU_BASE) {
- int idx = p_option - TOOL_MENU_BASE;
-
- if (tool_menu_items[idx].submenu != "")
- break;
-
- Object *handler = ObjectDB::get_instance(tool_menu_items[idx].handler);
- ERR_FAIL_COND(!handler);
- handler->call(tool_menu_items[idx].callback, tool_menu_items[idx].ud);
- } else if (p_option>=OBJECT_METHOD_BASE) {
+ if (p_option>=OBJECT_METHOD_BASE) {
ERR_FAIL_COND(!current);
@@ -3861,9 +3852,9 @@ void EditorNode::request_instance_scenes(const Vector<String>& p_files) {
scene_tree_dock->instance_scenes(p_files);
}
-FileSystemDock *EditorNode::get_scenes_dock() {
+FileSystemDock *EditorNode::get_filesystem_dock() {
- return scenes_dock;
+ return filesystem_dock;
}
SceneTreeDock *EditorNode::get_scene_tree_dock() {
@@ -4523,6 +4514,8 @@ void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String& p
}
}
+ p_layout->set_value(p_section,"dock_filesystem_split",filesystem_dock->get_split_offset());
+
VSplitContainer*splits[DOCK_SLOT_MAX/2]={
left_l_vsplit,
left_r_vsplit,
@@ -4699,6 +4692,12 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String&
}
}
+ int fs_split_ofs = 0;
+ if (p_layout->has_section_key(p_section,"dock_filesystem_split")) {
+ fs_split_ofs = p_layout->get_value(p_section,"dock_filesystem_split");
+ }
+ filesystem_dock->set_split_offset(fs_split_ofs);
+
VSplitContainer*splits[DOCK_SLOT_MAX/2]={
left_l_vsplit,
left_r_vsplit,
@@ -5187,7 +5186,7 @@ Variant EditorNode::drag_files_and_dirs(const Vector<String>& p_files, Control *
void EditorNode::_dropped_files(const Vector<String>& p_files,int p_screen) {
- String cur_path = scenes_dock->get_current_path();
+ String cur_path = filesystem_dock->get_current_path();
for(int i=0;i<EditorImportExport::get_singleton()->get_import_plugin_count();i++) {
EditorImportExport::get_singleton()->get_import_plugin(i)->import_from_drop(p_files,cur_path);
}
@@ -5279,100 +5278,6 @@ void EditorNode::add_plugin_init_callback(EditorPluginInitializeCallback p_callb
EditorPluginInitializeCallback EditorNode::plugin_init_callbacks[EditorNode::MAX_INIT_CALLBACKS];
-void EditorNode::_tool_menu_insert_item(const ToolMenuItem& p_item) {
-
- int idx = tool_menu_items.size();
-
- String cat;
- if (p_item.name.find("/") >= 0) {
- cat = p_item.name.get_slice("/", 0);
- } else {
- idx = 0;
- cat = "";
- }
-
- for (int i = tool_menu_items.size() - 1; i >= 0; i--) {
- String name = tool_menu_items[i].name;
-
- if (name.begins_with(cat) && (cat != "" || name.find("/") < 0)) {
- idx = i + 1;
- break;
- }
- }
-
- tool_menu_items.insert(idx, p_item);
-}
-
-void EditorNode::_rebuild_tool_menu() const {
-
- if (_initializing_tool_menu)
- return;
-
- PopupMenu *menu = tool_menu->get_popup();
- menu->clear();
-
- for (int i = 0; i < tool_menu_items.size(); i++) {
- menu->add_item(tool_menu_items[i].name.get_slice("/", 1), TOOL_MENU_BASE + i);
-
- if (tool_menu_items[i].submenu != "")
- menu->set_item_submenu(i, tool_menu_items[i].submenu);
- }
-}
-
-void EditorNode::add_tool_menu_item(const String& p_name, Object *p_handler, const String& p_callback, const Variant& p_ud) {
-
- ERR_FAIL_COND(!p_handler);
-
- ToolMenuItem tmi;
- tmi.name = p_name;
- tmi.submenu = "";
- tmi.ud = p_ud;
- tmi.handler = p_handler->get_instance_ID();
- tmi.callback = p_callback;
- _tool_menu_insert_item(tmi);
-
- _rebuild_tool_menu();
-}
-
-void EditorNode::add_tool_submenu_item(const String& p_name, PopupMenu *p_submenu) {
-
- ERR_FAIL_COND(!p_submenu);
- ERR_FAIL_COND(p_submenu->get_parent() != NULL);
-
- ToolMenuItem tmi;
- tmi.name = p_name;
- tmi.submenu = p_submenu->get_name();
- tmi.ud = Variant();
- tmi.handler = -1;
- tmi.callback = "";
- _tool_menu_insert_item(tmi);
-
- tool_menu->get_popup()->add_child(p_submenu);
-
- _rebuild_tool_menu();
-}
-
-void EditorNode::remove_tool_menu_item(const String& p_name) {
-
- for (int i = 0; i < tool_menu_items.size(); i++) {
- if (tool_menu_items[i].name == p_name) {
- String submenu = tool_menu_items[i].submenu;
-
- if (submenu != "") {
- Node *n = tool_menu->get_popup()->get_node(submenu);
-
- if (n) {
- tool_menu->get_popup()->remove_child(n);
- memdelete(n);
- }
- }
-
- tool_menu_items.remove(i);
- }
- }
-
- _rebuild_tool_menu();
-}
int EditorNode::build_callback_count=0;
@@ -5516,8 +5421,6 @@ EditorNode::EditorNode() {
docks_visible = true;
- _initializing_tool_menu = true;
-
FileAccess::set_backup_save(true);
PathRemap::get_singleton()->clear_remaps(); //editor uses no remaps
@@ -5860,6 +5763,7 @@ EditorNode::EditorNode() {
ED_SHORTCUT("editor/next_tab", TTR("Next tab"), KEY_MASK_CMD+KEY_TAB);
ED_SHORTCUT("editor/prev_tab", TTR("Previous tab"), KEY_MASK_CMD+KEY_MASK_SHIFT+KEY_TAB);
+ ED_SHORTCUT("editor/filter_files", TTR("Filter Files.."), KEY_MASK_ALT+KEY_MASK_CMD+KEY_P);
file_menu->set_tooltip(TTR("Operations with scene files."));
@@ -5879,7 +5783,6 @@ EditorNode::EditorNode() {
p->add_separator();
p->add_shortcut(ED_SHORTCUT("editor/quick_open_scene",TTR("Quick Open Scene.."),KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_O),FILE_QUICK_OPEN_SCENE);
p->add_shortcut(ED_SHORTCUT("editor/quick_open_script",TTR("Quick Open Script.."),KEY_MASK_ALT+KEY_MASK_CMD+KEY_O),FILE_QUICK_OPEN_SCRIPT);
- p->add_shortcut(ED_SHORTCUT("editor/quick_filter_files",TTR("Quick Filter Files.."),KEY_MASK_ALT+KEY_MASK_CMD+KEY_P),FILE_QUICK_OPEN_FILE);
p->add_separator();
PopupMenu *pm_export = memnew(PopupMenu );
@@ -5977,9 +5880,10 @@ EditorNode::EditorNode() {
//tool_menu->set_icon(gui_base->get_icon("Save","EditorIcons"));
left_menu_hb->add_child( tool_menu );
- tool_menu->get_popup()->connect("id_pressed", this, "_menu_option");
- add_tool_menu_item(TTR("Orphan Resource Explorer"), this, "_menu_option", TOOLS_ORPHAN_RESOURCES);
+ p=tool_menu->get_popup();
+ p->connect("id_pressed",this,"_menu_option");
+ p->add_item(TTR("Orphan Resource Explorer"),TOOLS_ORPHAN_RESOURCES);
export_button = memnew( ToolButton );
export_button->set_tooltip(TTR("Export the project to many platforms."));
@@ -6376,21 +6280,21 @@ EditorNode::EditorNode() {
dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(node_dock);
}
- scenes_dock = memnew( FileSystemDock(this) );
- scenes_dock->set_name(TTR("FileSystem"));
- scenes_dock->set_display_mode(int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode")));
+ filesystem_dock = memnew( FileSystemDock(this) );
+ filesystem_dock->set_name(TTR("FileSystem"));
+ filesystem_dock->set_display_mode(int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode")));
if (use_single_dock_column) {
- dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(scenes_dock);
+ dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(filesystem_dock);
left_r_vsplit->hide();
dock_slot[DOCK_SLOT_LEFT_UR]->hide();
dock_slot[DOCK_SLOT_LEFT_BR]->hide();
} else {
- dock_slot[DOCK_SLOT_LEFT_UR]->add_child(scenes_dock);
+ dock_slot[DOCK_SLOT_LEFT_UR]->add_child(filesystem_dock);
}
- //prop_pallete->add_child(scenes_dock);
- scenes_dock->connect("open",this,"open_request");
- scenes_dock->connect("instance",this,"_instance_request");
+ //prop_pallete->add_child(filesystem_dock);
+ filesystem_dock->connect("open",this,"open_request");
+ filesystem_dock->connect("instance",this,"_instance_request");
const String docks_section = "docks";
@@ -6663,6 +6567,9 @@ EditorNode::EditorNode() {
add_editor_plugin( memnew( SpatialEditorPlugin(this) ) );
add_editor_plugin( memnew( ScriptEditorPlugin(this) ) );
+
+ EditorAudioBuses *audio_bus_editor = EditorAudioBuses::register_editor();
+
ScriptTextEditor::register_editor(); //register one for text scripts
if (StreamPeerSSL::is_available()) {
@@ -6710,6 +6617,7 @@ EditorNode::EditorNode() {
add_editor_plugin( memnew( ColorRampEditorPlugin(this) ) );
add_editor_plugin( memnew( CollisionShape2DEditorPlugin(this) ) );
add_editor_plugin( memnew( TextureEditorPlugin(this) ) );
+ add_editor_plugin( memnew( AudioBusesEditorPlugin(audio_bus_editor) ) );
//add_editor_plugin( memnew( MaterialEditorPlugin(this) ) );
//add_editor_plugin( memnew( MeshEditorPlugin(this) ) );
@@ -6860,8 +6768,7 @@ EditorNode::EditorNode() {
_initializing_addons=false;
}
- _initializing_tool_menu = false;
- _rebuild_tool_menu();
+
_load_docks();
diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h
index 2baa9091ff..fbba7ae7a9 100644
--- a/tools/editor/editor_node.h
+++ b/tools/editor/editor_node.h
@@ -139,7 +139,6 @@ private:
FILE_OPEN_OLD_SCENE,
FILE_QUICK_OPEN_SCENE,
FILE_QUICK_OPEN_SCRIPT,
- FILE_QUICK_OPEN_FILE,
FILE_RUN_SCRIPT,
FILE_OPEN_PREV,
FILE_CLOSE,
@@ -280,7 +279,7 @@ private:
PropertyEditor *property_editor;
NodeDock *node_dock;
VBoxContainer *prop_editor_vb;
- FileSystemDock *scenes_dock;
+ FileSystemDock *filesystem_dock;
EditorRunNative *run_native;
HBoxContainer *search_bar;
@@ -706,7 +705,7 @@ public:
void request_instance_scene(const String &p_path);
void request_instance_scenes(const Vector<String>& p_files);
- FileSystemDock *get_scenes_dock();
+ FileSystemDock *get_filesystem_dock();
SceneTreeDock *get_scene_tree_dock();
static UndoRedo* get_undo_redo() { return &singleton->editor_data.get_undo_redo(); }
diff --git a/tools/editor/editor_plugin.cpp b/tools/editor/editor_plugin.cpp
index 69be7f8a4d..2f59b0bd07 100644
--- a/tools/editor/editor_plugin.cpp
+++ b/tools/editor/editor_plugin.cpp
@@ -136,7 +136,7 @@ void EditorPlugin::add_control_to_container(CustomControlContainer p_location,Co
void EditorPlugin::add_tool_menu_item(const String& p_name, Object *p_handler, const String& p_callback, const Variant& p_ud) {
- EditorNode::get_singleton()->add_tool_menu_item(p_name, p_handler, p_callback, p_ud);
+ //EditorNode::get_singleton()->add_tool_menu_item(p_name, p_handler, p_callback, p_ud);
}
void EditorPlugin::add_tool_submenu_item(const String& p_name, Object *p_submenu) {
@@ -144,12 +144,12 @@ void EditorPlugin::add_tool_submenu_item(const String& p_name, Object *p_submenu
ERR_FAIL_NULL(p_submenu);
PopupMenu *submenu = p_submenu->cast_to<PopupMenu>();
ERR_FAIL_NULL(submenu);
- EditorNode::get_singleton()->add_tool_submenu_item(p_name, submenu);
+ //EditorNode::get_singleton()->add_tool_submenu_item(p_name, submenu);
}
void EditorPlugin::remove_tool_menu_item(const String& p_name) {
- EditorNode::get_singleton()->remove_tool_menu_item(p_name);
+ //EditorNode::get_singleton()->remove_tool_menu_item(p_name);
}
Ref<SpatialEditorGizmo> EditorPlugin::create_spatial_gizmo(Spatial* p_spatial) {
@@ -371,9 +371,9 @@ void EditorPlugin::_bind_methods() {
ClassDB::bind_method(_MD("add_control_to_dock","slot","control:Control"),&EditorPlugin::add_control_to_dock);
ClassDB::bind_method(_MD("remove_control_from_docks","control:Control"),&EditorPlugin::remove_control_from_docks);
ClassDB::bind_method(_MD("remove_control_from_bottom_panel","control:Control"),&EditorPlugin::remove_control_from_bottom_panel);
- ClassDB::bind_method(_MD("add_tool_menu_item", "name", "handler", "callback", "ud"),&EditorPlugin::add_tool_menu_item,DEFVAL(Variant()));
+ //ClassDB::bind_method(_MD("add_tool_menu_item", "name", "handler", "callback", "ud"),&EditorPlugin::add_tool_menu_item,DEFVAL(Variant()));
ClassDB::bind_method(_MD("add_tool_submenu_item", "name", "submenu:PopupMenu"),&EditorPlugin::add_tool_submenu_item);
- ClassDB::bind_method(_MD("remove_tool_menu_item", "name"),&EditorPlugin::remove_tool_menu_item);
+ //ClassDB::bind_method(_MD("remove_tool_menu_item", "name"),&EditorPlugin::remove_tool_menu_item);
ClassDB::bind_method(_MD("add_custom_type","type","base","script:Script","icon:Texture"),&EditorPlugin::add_custom_type);
ClassDB::bind_method(_MD("remove_custom_type","type"),&EditorPlugin::remove_custom_type);
ClassDB::bind_method(_MD("get_editor_viewport:Control"), &EditorPlugin::get_editor_viewport);
diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp
index 27aeaeb5b6..822497fcab 100644
--- a/tools/editor/editor_settings.cpp
+++ b/tools/editor/editor_settings.cpp
@@ -653,6 +653,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
set("run/auto_save/save_before_running",true);
+ set("run/output/always_clear_output_on_play",true);
+ set("run/output/always_open_output_on_play",true);
set("filesystem/resources/save_compressed_resources",true);
set("filesystem/resources/auto_reload_modified_images",true);
diff --git a/tools/editor/filesystem_dock.cpp b/tools/editor/filesystem_dock.cpp
index b85bd6dfdb..021d5c4eb9 100644
--- a/tools/editor/filesystem_dock.cpp
+++ b/tools/editor/filesystem_dock.cpp
@@ -170,7 +170,7 @@ void FileSystemDock::_notification(int p_what) {
_update_tree(); //maybe it finished already
if (EditorFileSystem::get_singleton()->is_scanning()) {
- _set_scannig_mode();
+ _set_scanning_mode();
}
} break;
@@ -662,7 +662,7 @@ void FileSystemDock::_fs_changed() {
set_process(false);
}
-void FileSystemDock::_set_scannig_mode() {
+void FileSystemDock::_set_scanning_mode() {
split_box->hide();
button_hist_prev->set_disabled(true);
@@ -1174,7 +1174,7 @@ void FileSystemDock::_search_changed(const String& p_text) {
void FileSystemDock::_rescan() {
- _set_scannig_mode();
+ _set_scanning_mode();
EditorFileSystem::get_singleton()->scan();
}
@@ -1186,6 +1186,14 @@ void FileSystemDock::fix_dependencies(const String& p_for_file) {
void FileSystemDock::focus_on_filter() {
+ if (!search_box->is_visible_in_tree()) {
+ // Tree mode, switch to files list with search box
+ tree->hide();
+ file_list_vb->show();
+ button_favorite->hide();
+ }
+
+ search_box->grab_focus();
}
void FileSystemDock::set_display_mode(int p_mode) {
@@ -1618,6 +1626,19 @@ void FileSystemDock::_files_list_rmb_select(int p_item,const Vector2& p_pos) {
}
+void FileSystemDock::select_file(const String& p_file) {
+
+ _go_to_dir(p_file.get_base_dir());
+ for(int i=0;i<files->get_item_count();i++) {
+ if (files->get_item_metadata(i)==p_file) {
+ files->select(i);
+ files->ensure_current_is_visible();
+ break;
+ }
+ }
+
+}
+
void FileSystemDock::_bind_methods() {
ClassDB::bind_method(_MD("_update_tree"),&FileSystemDock::_update_tree);
diff --git a/tools/editor/filesystem_dock.h b/tools/editor/filesystem_dock.h
index ccd43847d6..73265657e5 100644
--- a/tools/editor/filesystem_dock.h
+++ b/tools/editor/filesystem_dock.h
@@ -153,7 +153,7 @@ private:
void _dir_selected();
void _update_tree();
void _rescan();
- void _set_scannig_mode();
+ void _set_scanning_mode();
void _favorites_pressed();
@@ -199,6 +199,10 @@ public:
void set_display_mode(int p_mode);
+ int get_split_offset() { return split_box->get_split_offset(); }
+ void set_split_offset(int p_offset) { split_box->set_split_offset(p_offset); }
+ void select_file(const String& p_file);
+
FileSystemDock(EditorNode *p_editor);
~FileSystemDock();
};
diff --git a/tools/editor/icons/2x/icon_anchor.png b/tools/editor/icons/2x/icon_anchor.png
index db964fd910..7e9e259c13 100644
--- a/tools/editor/icons/2x/icon_anchor.png
+++ b/tools/editor/icons/2x/icon_anchor.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_animation.png b/tools/editor/icons/2x/icon_animation.png
index 5b21e99e43..ef18959a74 100644
--- a/tools/editor/icons/2x/icon_animation.png
+++ b/tools/editor/icons/2x/icon_animation.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_area.png b/tools/editor/icons/2x/icon_area.png
index ff332bf748..d9cefe8fc4 100644
--- a/tools/editor/icons/2x/icon_area.png
+++ b/tools/editor/icons/2x/icon_area.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_auto_play.png b/tools/editor/icons/2x/icon_auto_play.png
index 9a50d1c030..ec31dee958 100644
--- a/tools/editor/icons/2x/icon_auto_play.png
+++ b/tools/editor/icons/2x/icon_auto_play.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_bitmap_font.png b/tools/editor/icons/2x/icon_bitmap_font.png
index df6d2a5081..c533b5f40e 100644
--- a/tools/editor/icons/2x/icon_bitmap_font.png
+++ b/tools/editor/icons/2x/icon_bitmap_font.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_canvas_layer.png b/tools/editor/icons/2x/icon_canvas_layer.png
index 9861d3ef45..8a4b31cd7d 100644
--- a/tools/editor/icons/2x/icon_canvas_layer.png
+++ b/tools/editor/icons/2x/icon_canvas_layer.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_canvas_modulate.png b/tools/editor/icons/2x/icon_canvas_modulate.png
index 07ee8a0570..6cc15e2655 100644
--- a/tools/editor/icons/2x/icon_canvas_modulate.png
+++ b/tools/editor/icons/2x/icon_canvas_modulate.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_copy_node_path.png b/tools/editor/icons/2x/icon_copy_node_path.png
new file mode 100644
index 0000000000..056748d20b
--- /dev/null
+++ b/tools/editor/icons/2x/icon_copy_node_path.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_create_new_scene_from.png b/tools/editor/icons/2x/icon_create_new_scene_from.png
index 15b2c89dc5..cc3be48033 100644
--- a/tools/editor/icons/2x/icon_create_new_scene_from.png
+++ b/tools/editor/icons/2x/icon_create_new_scene_from.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_dynamic_font_data.png b/tools/editor/icons/2x/icon_dynamic_font_data.png
index 397a849b4f..6d76303c81 100644
--- a/tools/editor/icons/2x/icon_dynamic_font_data.png
+++ b/tools/editor/icons/2x/icon_dynamic_font_data.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_error.png b/tools/editor/icons/2x/icon_error.png
index b577182044..a6d79ab41b 100644
--- a/tools/editor/icons/2x/icon_error.png
+++ b/tools/editor/icons/2x/icon_error.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_fixed_spatial_material.png b/tools/editor/icons/2x/icon_fixed_spatial_material.png
index b95e78d6cc..65509a590e 100644
--- a/tools/editor/icons/2x/icon_fixed_spatial_material.png
+++ b/tools/editor/icons/2x/icon_fixed_spatial_material.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_key_next.png b/tools/editor/icons/2x/icon_key_next.png
index cb2c4eae4b..d35b52d3c7 100644
--- a/tools/editor/icons/2x/icon_key_next.png
+++ b/tools/editor/icons/2x/icon_key_next.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_material_shader.png b/tools/editor/icons/2x/icon_material_shader.png
index 65509a590e..f8c2e15fcb 100644
--- a/tools/editor/icons/2x/icon_material_shader.png
+++ b/tools/editor/icons/2x/icon_material_shader.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_reparent.png b/tools/editor/icons/2x/icon_reparent.png
index 2473a3b362..3063da4b43 100644
--- a/tools/editor/icons/2x/icon_reparent.png
+++ b/tools/editor/icons/2x/icon_reparent.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_script_remove.png b/tools/editor/icons/2x/icon_script_remove.png
new file mode 100644
index 0000000000..f9a1bb19a4
--- /dev/null
+++ b/tools/editor/icons/2x/icon_script_remove.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_shader.png b/tools/editor/icons/2x/icon_shader.png
index 65509a590e..f8c2e15fcb 100644
--- a/tools/editor/icons/2x/icon_shader.png
+++ b/tools/editor/icons/2x/icon_shader.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_shader_material.png b/tools/editor/icons/2x/icon_shader_material.png
index 65509a590e..f8c2e15fcb 100644
--- a/tools/editor/icons/2x/icon_shader_material.png
+++ b/tools/editor/icons/2x/icon_shader_material.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_spot_light.png b/tools/editor/icons/2x/icon_spot_light.png
index e50c7b6135..e7aa35cbbf 100644
--- a/tools/editor/icons/2x/icon_spot_light.png
+++ b/tools/editor/icons/2x/icon_spot_light.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_tab_container.png b/tools/editor/icons/2x/icon_tab_container.png
index 086be0c5ba..93b7161a69 100644
--- a/tools/editor/icons/2x/icon_tab_container.png
+++ b/tools/editor/icons/2x/icon_tab_container.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_tabs.png b/tools/editor/icons/2x/icon_tabs.png
index ade8071b7f..6c317010c8 100644
--- a/tools/editor/icons/2x/icon_tabs.png
+++ b/tools/editor/icons/2x/icon_tabs.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_track_add_key.png b/tools/editor/icons/2x/icon_track_add_key.png
index 9cf0314270..9b7bd14fb4 100644
--- a/tools/editor/icons/2x/icon_track_add_key.png
+++ b/tools/editor/icons/2x/icon_track_add_key.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_track_add_key_hl.png b/tools/editor/icons/2x/icon_track_add_key_hl.png
index 7d170725f6..0763836c3a 100644
--- a/tools/editor/icons/2x/icon_track_add_key_hl.png
+++ b/tools/editor/icons/2x/icon_track_add_key_hl.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_transparent.png b/tools/editor/icons/2x/icon_transparent.png
new file mode 100644
index 0000000000..627607039b
--- /dev/null
+++ b/tools/editor/icons/2x/icon_transparent.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_viewport_container.png b/tools/editor/icons/2x/icon_viewport_container.png
index e44dbc23d3..c43e53c34e 100644
--- a/tools/editor/icons/2x/icon_viewport_container.png
+++ b/tools/editor/icons/2x/icon_viewport_container.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_warning.png b/tools/editor/icons/2x/icon_warning.png
index 7359a798ee..5d807065e7 100644
--- a/tools/editor/icons/2x/icon_warning.png
+++ b/tools/editor/icons/2x/icon_warning.png
Binary files differ
diff --git a/tools/editor/icons/icon_accept_dialog.png b/tools/editor/icons/icon_accept_dialog.png
index 1ba2ce8db3..7530127f82 100644
--- a/tools/editor/icons/icon_accept_dialog.png
+++ b/tools/editor/icons/icon_accept_dialog.png
Binary files differ
diff --git a/tools/editor/icons/icon_anchor.png b/tools/editor/icons/icon_anchor.png
index 9c20808bdc..7b02eb448e 100644
--- a/tools/editor/icons/icon_anchor.png
+++ b/tools/editor/icons/icon_anchor.png
Binary files differ
diff --git a/tools/editor/icons/icon_animation.png b/tools/editor/icons/icon_animation.png
index 2bc13f0b4c..b333f82711 100644
--- a/tools/editor/icons/icon_animation.png
+++ b/tools/editor/icons/icon_animation.png
Binary files differ
diff --git a/tools/editor/icons/icon_area.png b/tools/editor/icons/icon_area.png
index ea7af5f9ac..31b4473d17 100644
--- a/tools/editor/icons/icon_area.png
+++ b/tools/editor/icons/icon_area.png
Binary files differ
diff --git a/tools/editor/icons/icon_audio_effect_amplify.png b/tools/editor/icons/icon_audio_effect_amplify.png
new file mode 100644
index 0000000000..9af3227d40
--- /dev/null
+++ b/tools/editor/icons/icon_audio_effect_amplify.png
Binary files differ
diff --git a/tools/editor/icons/icon_auto_play.png b/tools/editor/icons/icon_auto_play.png
index fcd3bedcda..a6be64a1d1 100644
--- a/tools/editor/icons/icon_auto_play.png
+++ b/tools/editor/icons/icon_auto_play.png
Binary files differ
diff --git a/tools/editor/icons/icon_bitmap_font.png b/tools/editor/icons/icon_bitmap_font.png
index 2739248796..5334c335dc 100644
--- a/tools/editor/icons/icon_bitmap_font.png
+++ b/tools/editor/icons/icon_bitmap_font.png
Binary files differ
diff --git a/tools/editor/icons/icon_bus_vu_db.png b/tools/editor/icons/icon_bus_vu_db.png
new file mode 100644
index 0000000000..52507cae52
--- /dev/null
+++ b/tools/editor/icons/icon_bus_vu_db.png
Binary files differ
diff --git a/tools/editor/icons/icon_bus_vu_empty.png b/tools/editor/icons/icon_bus_vu_empty.png
new file mode 100644
index 0000000000..6fc3143a55
--- /dev/null
+++ b/tools/editor/icons/icon_bus_vu_empty.png
Binary files differ
diff --git a/tools/editor/icons/icon_bus_vu_frozen.png b/tools/editor/icons/icon_bus_vu_frozen.png
new file mode 100644
index 0000000000..cf128afa91
--- /dev/null
+++ b/tools/editor/icons/icon_bus_vu_frozen.png
Binary files differ
diff --git a/tools/editor/icons/icon_bus_vu_full.png b/tools/editor/icons/icon_bus_vu_full.png
new file mode 100644
index 0000000000..9e3d7a93e3
--- /dev/null
+++ b/tools/editor/icons/icon_bus_vu_full.png
Binary files differ
diff --git a/tools/editor/icons/icon_canvas_layer.png b/tools/editor/icons/icon_canvas_layer.png
index cae31fe3bc..bb32d6d3ad 100644
--- a/tools/editor/icons/icon_canvas_layer.png
+++ b/tools/editor/icons/icon_canvas_layer.png
Binary files differ
diff --git a/tools/editor/icons/icon_canvas_modulate.png b/tools/editor/icons/icon_canvas_modulate.png
index 711ebbae5f..b76e532268 100644
--- a/tools/editor/icons/icon_canvas_modulate.png
+++ b/tools/editor/icons/icon_canvas_modulate.png
Binary files differ
diff --git a/tools/editor/icons/icon_copy_node_path.png b/tools/editor/icons/icon_copy_node_path.png
new file mode 100644
index 0000000000..d777f132d8
--- /dev/null
+++ b/tools/editor/icons/icon_copy_node_path.png
Binary files differ
diff --git a/tools/editor/icons/icon_create_new_scene_from.png b/tools/editor/icons/icon_create_new_scene_from.png
index 908c82626c..45df9b1e25 100644
--- a/tools/editor/icons/icon_create_new_scene_from.png
+++ b/tools/editor/icons/icon_create_new_scene_from.png
Binary files differ
diff --git a/tools/editor/icons/icon_dynamic_font_data.png b/tools/editor/icons/icon_dynamic_font_data.png
index 8f36106b61..5cff86c40c 100644
--- a/tools/editor/icons/icon_dynamic_font_data.png
+++ b/tools/editor/icons/icon_dynamic_font_data.png
Binary files differ
diff --git a/tools/editor/icons/icon_error.png b/tools/editor/icons/icon_error.png
index 0fdf5facbf..7a9bed43aa 100644
--- a/tools/editor/icons/icon_error.png
+++ b/tools/editor/icons/icon_error.png
Binary files differ
diff --git a/tools/editor/icons/icon_fixed_spatial_material.png b/tools/editor/icons/icon_fixed_spatial_material.png
index 2e52c45a46..f26ac3be37 100644
--- a/tools/editor/icons/icon_fixed_spatial_material.png
+++ b/tools/editor/icons/icon_fixed_spatial_material.png
Binary files differ
diff --git a/tools/editor/icons/icon_key_next.png b/tools/editor/icons/icon_key_next.png
index ed7a20637f..288161d245 100644
--- a/tools/editor/icons/icon_key_next.png
+++ b/tools/editor/icons/icon_key_next.png
Binary files differ
diff --git a/tools/editor/icons/icon_material_shader.png b/tools/editor/icons/icon_material_shader.png
index f26ac3be37..568a45d938 100644
--- a/tools/editor/icons/icon_material_shader.png
+++ b/tools/editor/icons/icon_material_shader.png
Binary files differ
diff --git a/tools/editor/icons/icon_reparent.png b/tools/editor/icons/icon_reparent.png
index b3235e60c5..135ccee4ad 100644
--- a/tools/editor/icons/icon_reparent.png
+++ b/tools/editor/icons/icon_reparent.png
Binary files differ
diff --git a/tools/editor/icons/icon_script_remove.png b/tools/editor/icons/icon_script_remove.png
new file mode 100644
index 0000000000..c200b01690
--- /dev/null
+++ b/tools/editor/icons/icon_script_remove.png
Binary files differ
diff --git a/tools/editor/icons/icon_shader.png b/tools/editor/icons/icon_shader.png
index f26ac3be37..568a45d938 100644
--- a/tools/editor/icons/icon_shader.png
+++ b/tools/editor/icons/icon_shader.png
Binary files differ
diff --git a/tools/editor/icons/icon_shader_material.png b/tools/editor/icons/icon_shader_material.png
index f26ac3be37..568a45d938 100644
--- a/tools/editor/icons/icon_shader_material.png
+++ b/tools/editor/icons/icon_shader_material.png
Binary files differ
diff --git a/tools/editor/icons/icon_spot_light.png b/tools/editor/icons/icon_spot_light.png
index 89b0b28aa3..f52570a5cd 100644
--- a/tools/editor/icons/icon_spot_light.png
+++ b/tools/editor/icons/icon_spot_light.png
Binary files differ
diff --git a/tools/editor/icons/icon_tab_container.png b/tools/editor/icons/icon_tab_container.png
index dd661c5ab6..7ff3081ec1 100644
--- a/tools/editor/icons/icon_tab_container.png
+++ b/tools/editor/icons/icon_tab_container.png
Binary files differ
diff --git a/tools/editor/icons/icon_tabs.png b/tools/editor/icons/icon_tabs.png
index cc7e08a835..bef0f60660 100644
--- a/tools/editor/icons/icon_tabs.png
+++ b/tools/editor/icons/icon_tabs.png
Binary files differ
diff --git a/tools/editor/icons/icon_track_add_key.png b/tools/editor/icons/icon_track_add_key.png
index fb86b37963..02d92439a3 100644
--- a/tools/editor/icons/icon_track_add_key.png
+++ b/tools/editor/icons/icon_track_add_key.png
Binary files differ
diff --git a/tools/editor/icons/icon_track_add_key_hl.png b/tools/editor/icons/icon_track_add_key_hl.png
index c1bfee736a..0e857f5fe2 100644
--- a/tools/editor/icons/icon_track_add_key_hl.png
+++ b/tools/editor/icons/icon_track_add_key_hl.png
Binary files differ
diff --git a/tools/editor/icons/icon_transparent.png b/tools/editor/icons/icon_transparent.png
new file mode 100644
index 0000000000..07e9b52b5c
--- /dev/null
+++ b/tools/editor/icons/icon_transparent.png
Binary files differ
diff --git a/tools/editor/icons/icon_viewport_container.png b/tools/editor/icons/icon_viewport_container.png
index 52fb65b1ac..c70dee3698 100644
--- a/tools/editor/icons/icon_viewport_container.png
+++ b/tools/editor/icons/icon_viewport_container.png
Binary files differ
diff --git a/tools/editor/icons/icon_vu_db.png b/tools/editor/icons/icon_vu_db.png
new file mode 100644
index 0000000000..405a929e2a
--- /dev/null
+++ b/tools/editor/icons/icon_vu_db.png
Binary files differ
diff --git a/tools/editor/icons/icon_warning.png b/tools/editor/icons/icon_warning.png
index 0928062938..451beba820 100644
--- a/tools/editor/icons/icon_warning.png
+++ b/tools/editor/icons/icon_warning.png
Binary files differ
diff --git a/tools/editor/icons/source/icon_accept_dialog.svg b/tools/editor/icons/source/icon_accept_dialog.svg
index 8d2c307691..9f82b30c94 100644
--- a/tools/editor/icons/source/icon_accept_dialog.svg
+++ b/tools/editor/icons/source/icon_accept_dialog.svg
@@ -28,9 +28,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="32"
- inkscape:cx="6.0807642"
- inkscape:cy="9.1331382"
+ inkscape:zoom="45.254834"
+ inkscape:cx="8.3712909"
+ inkscape:cy="7.2310094"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -59,7 +59,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -70,8 +70,10 @@
transform="translate(0,-1036.3622)">
<path
style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="M 3 1 C 1.89543 1 1 1.8954 1 3 L 1 4 L 15 4 L 15 3 C 15 1.8954 14.104569 1 13 1 L 3 1 z M 12 2 L 13 2 L 13 3 L 12 3 L 12 2 z M 1 5 L 1 13 C 1 14.1046 1.89543 15 3 15 L 13 15 C 14.104569 15 15 14.1046 15 13 L 15 5 L 1 5 z M 10.474609 6.6367188 L 11.888672 8.0507812 L 8.3535156 11.585938 L 6.9394531 13 L 5.5253906 11.585938 L 4.1113281 10.171875 L 5.5253906 8.7578125 L 6.9394531 10.171875 L 10.474609 6.6367188 z "
+ d="M 3,1 C 1.89543,1 1,1.8954 1,3 L 1,4 15,4 15,3 C 15,1.8954 14.104569,1 13,1 Z m 9,1 1,0 0,1 -1,0 z M 1,5 1,13 c 0,1.1046 0.89543,2 2,2 l 10,0 c 1.104569,0 2,-0.8954 2,-2 L 15,5 Z M 10.474609,6.6367188 11.888672,8.0507812 6.9394531,13 4.1113281,10.171875 5.5253906,8.7578125 6.9394531,10.171875 Z"
transform="translate(0,1036.3622)"
- id="rect4140" />
+ id="rect4140"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ssccsssccccccssssccccccccc" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_add_track.svg b/tools/editor/icons/source/icon_add_track.svg
index 916199d29e..d19448efb0 100644
--- a/tools/editor/icons/source/icon_add_track.svg
+++ b/tools/editor/icons/source/icon_add_track.svg
@@ -18,7 +18,7 @@
inkscape:export-filename="/home/djrm/Projects/godot/tools/editor/icons/icon_add_track.png"
inkscape:export-xdpi="45"
inkscape:export-ydpi="45"
- sodipodi:docname="icon_add_track (copy).svg">
+ sodipodi:docname="icon_add_track.svg">
<defs
id="defs4" />
<sodipodi:namedview
@@ -28,9 +28,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="32.000001"
- inkscape:cx="4.2247291"
- inkscape:cy="8.9595523"
+ inkscape:zoom="45.254835"
+ inkscape:cx="6.9909025"
+ inkscape:cy="7.4569962"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -59,7 +59,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -68,20 +68,10 @@
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
- <rect
+ <path
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect4137"
- width="14"
- height="1.9999478"
- x="1"
- y="1043.3622" />
- <rect
- y="-9"
- x="1037.3622"
- height="2.0000017"
- width="13.999966"
- id="rect4158"
- style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- transform="matrix(0,1,-1,0,0,0)" />
+ d="M 7 1 L 7 7 L 1 7 L 1 9 L 7 9 L 7 15 L 9 15 L 9 9 L 15 9 L 15 7 L 9 7 L 9 1 L 7 1 z "
+ transform="translate(0,1036.3622)"
+ id="rect4137" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_anchor.svg b/tools/editor/icons/source/icon_anchor.svg
index ff43271224..6b10be040b 100644
--- a/tools/editor/icons/source/icon_anchor.svg
+++ b/tools/editor/icons/source/icon_anchor.svg
@@ -18,7 +18,7 @@
inkscape:export-filename="/home/djrm/Projects/godot/tools/editor/icons/icon_anchor.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
- sodipodi:docname="icon_anchor (copy).svg">
+ sodipodi:docname="icon_anchor.svg">
<defs
id="defs4" />
<sodipodi:namedview
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
- inkscape:cx="5.8188721"
- inkscape:cy="10.181863"
+ inkscape:cx="12.991456"
+ inkscape:cy="8.2347656"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -70,27 +70,8 @@
transform="translate(0,-1036.3622)">
<path
style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="M 8 1 A 3 3.0000043 0 0 0 5 4 A 3 3.0000043 0 0 0 8 7 A 3 3.0000043 0 0 0 11 4 A 3 3.0000043 0 0 0 8 1 z M 8 3 A 1.000016 1.0000174 0 0 1 9 4 A 1.000016 1.0000174 0 0 1 8 5 A 1.000016 1.0000174 0 0 1 7 4 A 1.000016 1.0000174 0 0 1 8 3 z "
+ d="M 8 1 A 3 3.0000043 0 0 0 5 4 A 3 3.0000043 0 0 0 7 6.8261719 L 7 7 L 5 7 L 5 9 L 7 9 L 7 12.898438 A 5.0000172 5.0000172 0 0 1 3.171875 9.2949219 L 1.2382812 9.8125 A 7 7 0 0 0 8 15 A 7 7 0 0 0 14.761719 9.8125 L 12.824219 9.2929688 A 5.0000172 5.0000172 0 0 1 9 12.896484 L 9 9 L 11 9 L 11 7 L 9 7 L 9 6.8242188 A 3 3.0000043 0 0 0 11 4 A 3 3.0000043 0 0 0 8 1 z M 8 3 A 1.000016 1.0000174 0 0 1 9 4 A 1.000016 1.0000174 0 0 1 8 5 A 1.000016 1.0000174 0 0 1 7 4 A 1.000016 1.0000174 0 0 1 8 3 z "
transform="translate(0,1036.3622)"
id="path4142" />
- <rect
- y="1042.3622"
- x="7"
- height="7.0000172"
- width="2"
- id="rect4148"
- style="fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <path
- style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="M 12.824219 9.2929688 A 5.0000172 5.0000172 0 0 1 8 13 A 5.0000172 5.0000172 0 0 1 3.171875 9.2949219 L 1.2382812 9.8125 A 7 7 0 0 0 8 15 A 7 7 0 0 0 14.761719 9.8125 L 12.824219 9.2929688 z "
- transform="translate(0,1036.3622)"
- id="path4150" />
- <rect
- style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4155"
- width="6"
- height="2"
- x="5"
- y="1043.3622" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_animation.svg b/tools/editor/icons/source/icon_animation.svg
index 38d73cf5bb..371979345f 100644
--- a/tools/editor/icons/source/icon_animation.svg
+++ b/tools/editor/icons/source/icon_animation.svg
@@ -28,9 +28,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="64"
- inkscape:cx="10.327464"
- inkscape:cy="2.5689331"
+ inkscape:zoom="22.627417"
+ inkscape:cx="9.2543315"
+ inkscape:cy="5.9550306"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -70,49 +70,8 @@
transform="translate(0,-1036.3622)">
<path
style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="M 8 2 A 6 6 0 0 0 2 8 A 6 6 0 0 0 8 14 A 6 6 0 0 0 14 8 A 6 6 0 0 0 8 2 z M 8 3 A 1 1 0 0 1 9 4 A 1 1 0 0 1 8 5 A 1 1 0 0 1 7 4 A 1 1 0 0 1 8 3 z M 11.441406 5 A 1 1 0 0 1 12.330078 5.5 A 1 1 0 0 1 11.964844 6.8652344 A 1 1 0 0 1 10.597656 6.5 A 1 1 0 0 1 10.964844 5.1347656 A 1 1 0 0 1 11.441406 5 z M 4.4882812 5.0019531 A 1 1 0 0 1 5.0351562 5.1347656 A 1 1 0 0 1 5.4023438 6.5 A 1 1 0 0 1 4.0351562 6.8652344 A 1 1 0 0 1 3.6699219 5.5 A 1 1 0 0 1 4.4882812 5.0019531 z M 4.5117188 9 A 1 1 0 0 1 5.4023438 9.5 A 1 1 0 0 1 5.0351562 10.865234 A 1 1 0 0 1 3.6699219 10.5 A 1 1 0 0 1 4.0351562 9.1347656 A 1 1 0 0 1 4.5117188 9 z M 11.416016 9.0019531 A 1 1 0 0 1 11.964844 9.1347656 A 1 1 0 0 1 12.330078 10.5 A 1 1 0 0 1 10.964844 10.865234 A 1 1 0 0 1 10.597656 9.5 A 1 1 0 0 1 11.416016 9.0019531 z M 8 11 A 1 1 0 0 1 9 12 A 1 1 0 0 1 8 13 A 1 1 0 0 1 7 12 A 1 1 0 0 1 8 11 z "
- transform="translate(0,1036.3622)"
- id="path4140" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="M 13 8 L 13 14 A 1 1 0 0 0 14 15 L 15 15 L 15 14 L 14 14 L 14 13 L 14 8 L 13 8 z "
- transform="translate(0,1036.3622)"
- id="rect4202" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="M 14 13.5 L 14 14 L 14.5 14 A 0.5 0.4999913 0 0 1 14 13.5 z "
- transform="translate(0,1036.3622)"
- id="rect4215" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="rect4137"
- width="1"
- height="3.0000174"
- x="12"
- y="1047.3622" />
- <path
- id="path4139"
- transform="translate(0,1036.3622)"
- d="M 13 8 L 13 14 A 1 1 0 0 0 14 15 L 15 15 L 15 14 L 14 14 L 14 13 L 14 8 L 13 8 z "
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <rect
- y="1050.3622"
- x="14"
- height="2"
- width="1"
- id="rect4141"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="path4145"
- sodipodi:type="arc"
- sodipodi:cx="14"
- sodipodi:cy="1050.3622"
- sodipodi:rx="2"
- sodipodi:ry="2"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m 14,1052.3622 a 2,2 0 0 1 -1.732051,-1 2,2 0 0 1 0,-2 2,2 0 0 1 1.732051,-1"
- sodipodi:open="true" />
+ d="M 8 2 A 6 6 0 0 0 2 8 A 6 6 0 0 0 8 14 A 6 6 0 0 0 12 12.464844 L 12 14 L 12.001953 14 A 2 2 0 0 0 12.267578 15 A 2 2 0 0 0 14 16 L 15 16 L 15 15 L 15 14 L 14.5 14 A 0.5 0.4999913 0 0 1 14 13.5 L 14 13 L 14 8 A 6 6 0 0 0 8 2 z M 8 3 A 1 1 0 0 1 9 4 A 1 1 0 0 1 8 5 A 1 1 0 0 1 7 4 A 1 1 0 0 1 8 3 z M 11.441406 5 A 1 1 0 0 1 12.330078 5.5 A 1 1 0 0 1 11.964844 6.8652344 A 1 1 0 0 1 10.597656 6.5 A 1 1 0 0 1 10.964844 5.1347656 A 1 1 0 0 1 11.441406 5 z M 4.4882812 5.0019531 A 1 1 0 0 1 5.0351562 5.1347656 A 1 1 0 0 1 5.4023438 6.5 A 1 1 0 0 1 4.0351562 6.8652344 A 1 1 0 0 1 3.6699219 5.5 A 1 1 0 0 1 4.4882812 5.0019531 z M 4.5117188 9 A 1 1 0 0 1 5.4023438 9.5 A 1 1 0 0 1 5.0351562 10.865234 A 1 1 0 0 1 3.6699219 10.5 A 1 1 0 0 1 4.0351562 9.1347656 A 1 1 0 0 1 4.5117188 9 z M 11.416016 9.0019531 A 1 1 0 0 1 11.964844 9.1347656 A 1 1 0 0 1 12.330078 10.5 A 1 1 0 0 1 10.964844 10.865234 A 1 1 0 0 1 10.597656 9.5 A 1 1 0 0 1 11.416016 9.0019531 z M 8 11 A 1 1 0 0 1 9 12 A 1 1 0 0 1 8 13 A 1 1 0 0 1 7 12 A 1 1 0 0 1 8 11 z "
+ id="path4140"
+ transform="translate(0,1036.3622)" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_area.svg b/tools/editor/icons/source/icon_area.svg
index d56043cf3b..d16ad26e23 100644
--- a/tools/editor/icons/source/icon_area.svg
+++ b/tools/editor/icons/source/icon_area.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
- inkscape:cx="5.5000497"
- inkscape:cy="8.7464605"
+ inkscape:cx="-2.7642608"
+ inkscape:cy="8.6580722"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -68,97 +68,10 @@
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
- <rect
+ <path
style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4148"
- width="2"
- height="4"
- x="1"
- y="1047.3622" />
- <rect
- y="1049.3622"
- x="1"
- height="1.9999304"
- width="4"
- id="rect4150"
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <rect
- y="1040.3622"
- x="4"
- height="8.0000172"
- width="2"
- id="rect4152"
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <rect
- y="-1041.3622"
- x="1"
- height="4"
- width="2"
- id="rect4154"
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="scale(1,-1)" />
- <rect
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4156"
- width="4"
- height="1.9999304"
- x="1"
- y="-1039.3622"
- transform="scale(1,-1)" />
- <rect
- transform="scale(-1,-1)"
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4158"
- width="2"
- height="4"
- x="-15"
- y="-1041.3622" />
- <rect
- transform="scale(-1,-1)"
- y="-1039.3622"
- x="-15"
- height="1.9999304"
- width="4"
- id="rect4160"
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <rect
- y="1047.3623"
- x="-15"
- height="4"
- width="2"
- id="rect4162"
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="scale(-1,1)" />
- <rect
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4164"
- width="4"
- height="1.9999304"
- x="-15"
- y="1049.3623"
- transform="scale(-1,1)" />
- <rect
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4168"
- width="8"
- height="1.9999998"
- x="4"
- y="1046.3622" />
- <rect
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4170"
- width="2"
- height="8.0000172"
- x="-12"
- y="-1048.3622"
- transform="scale(-1,-1)" />
- <rect
- y="-1042.3622"
- x="-12"
- height="1.9999998"
- width="8"
- id="rect4172"
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="scale(-1,-1)" />
+ d="M 1 1 L 1 3 L 1 5 L 3 5 L 3 3 L 5 3 L 5 1 L 1 1 z M 11 1 L 11 3 L 13 3 L 13 5 L 15 5 L 15 1 L 11 1 z M 4 4 L 4 6 L 4 10 L 4 12 L 12 12 L 12 10 L 12 4 L 4 4 z M 6 6 L 10 6 L 10 10 L 6 10 L 6 6 z M 1 11 L 1 13 L 1 15 L 3 15 L 5 15 L 5 13 L 3 13 L 3 11 L 1 11 z M 13 11 L 13 13 L 11 13 L 11 15 L 15 15 L 15 13 L 15 11 L 13 11 z "
+ transform="translate(0,1036.3622)"
+ id="rect4148" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_area_2d.svg b/tools/editor/icons/source/icon_area_2d.svg
index 1373d9f0e4..ef7b16dd06 100644
--- a/tools/editor/icons/source/icon_area_2d.svg
+++ b/tools/editor/icons/source/icon_area_2d.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.313709"
- inkscape:cx="14.936968"
- inkscape:cy="11.331549"
+ inkscape:cx="-1.5916523"
+ inkscape:cy="11.154772"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -68,97 +68,10 @@
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
- <rect
+ <path
style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4148"
- width="2"
- height="4"
- x="1"
- y="1047.3622" />
- <rect
- y="1049.3622"
- x="1"
- height="1.9999304"
- width="4"
- id="rect4150"
- style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <rect
- y="1040.3622"
- x="4"
- height="8.0000172"
- width="2"
- id="rect4152"
- style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <rect
- y="-1041.3622"
- x="1"
- height="4"
- width="2"
- id="rect4154"
- style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="scale(1,-1)" />
- <rect
- style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4156"
- width="4"
- height="1.9999304"
- x="1"
- y="-1039.3622"
- transform="scale(1,-1)" />
- <rect
- transform="scale(-1,-1)"
- style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4158"
- width="2"
- height="4"
- x="-15"
- y="-1041.3622" />
- <rect
- transform="scale(-1,-1)"
- y="-1039.3622"
- x="-15"
- height="1.9999304"
- width="4"
- id="rect4160"
- style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <rect
- y="1047.3623"
- x="-15"
- height="4"
- width="2"
- id="rect4162"
- style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="scale(-1,1)" />
- <rect
- style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4164"
- width="4"
- height="1.9999304"
- x="-15"
- y="1049.3623"
- transform="scale(-1,1)" />
- <rect
- style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4168"
- width="8"
- height="1.9999998"
- x="4"
- y="1046.3622" />
- <rect
- style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4170"
- width="2"
- height="8.0000172"
- x="-12"
- y="-1048.3622"
- transform="scale(-1,-1)" />
- <rect
- y="-1042.3622"
- x="-12"
- height="1.9999998"
- width="8"
- id="rect4172"
- style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="scale(-1,-1)" />
+ d="M 1 1 L 1 3 L 1 5 L 3 5 L 3 3 L 5 3 L 5 1 L 1 1 z M 11 1 L 11 3 L 13 3 L 13 5 L 15 5 L 15 1 L 11 1 z M 4 4 L 4 6 L 4 10 L 4 12 L 12 12 L 12 10 L 12 4 L 4 4 z M 6 6 L 10 6 L 10 10 L 6 10 L 6 6 z M 1 11 L 1 13 L 1 15 L 3 15 L 5 15 L 5 13 L 3 13 L 3 11 L 1 11 z M 13 11 L 13 13 L 11 13 L 11 15 L 15 15 L 15 13 L 15 11 L 13 11 z "
+ transform="translate(0,1036.3622)"
+ id="rect4148" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_arrow_left.svg b/tools/editor/icons/source/icon_arrow_left.svg
index 7af9be05d8..75a9ef0d68 100644
--- a/tools/editor/icons/source/icon_arrow_left.svg
+++ b/tools/editor/icons/source/icon_arrow_left.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
- inkscape:cx="5.5903114"
- inkscape:cy="9.1977698"
+ inkscape:cx="-0.2534386"
+ inkscape:cy="9.1352698"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -68,30 +68,10 @@
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
- <rect
- style="fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect4352"
- width="9"
- height="2.0000174"
- x="6"
- y="1043.3622" />
<path
- transform="matrix(0,1.2810265,0.92450034,0,964.29952,1037.9571)"
- inkscape:transform-center-y="-9.6789057e-05"
- d="m 8.122499,-1036.5594 -3.122499,0 -3.122499,0 1.5612495,-2.7042 L 5,-1041.9677 l 1.5612495,2.7041 z"
- inkscape:randomized="0"
- inkscape:rounded="0"
- inkscape:flatsided="false"
- sodipodi:arg2="1.5707963"
- sodipodi:arg1="0.52359878"
- sodipodi:r2="1.8027756"
- sodipodi:r1="3.6055512"
- sodipodi:cy="-1038.3622"
- sodipodi:cx="5"
- sodipodi:sides="3"
- id="path4435"
- style="fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-linecap:round;stroke-opacity:1"
- sodipodi:type="star"
- inkscape:transform-center-x="1.1667546" />
+ style="fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 6 4 L 3.5 6 L 1 8 L 3.5 10 L 6 12 L 6 9 L 15 9 L 15 7 L 6 7 L 6 4 z "
+ transform="translate(0,1036.3622)"
+ id="rect4352" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_arrow_right.svg b/tools/editor/icons/source/icon_arrow_right.svg
index 860a6f1481..a7600699f7 100644
--- a/tools/editor/icons/source/icon_arrow_right.svg
+++ b/tools/editor/icons/source/icon_arrow_right.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
- inkscape:cx="6.7465614"
- inkscape:cy="9.3227698"
+ inkscape:cx="0.9028114"
+ inkscape:cy="9.2602698"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -59,7 +59,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -70,8 +70,9 @@
transform="translate(0,-1036.3622)">
<path
style="fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 10,1048.3622 2.5,-2 2.5,-2 -2.5,-2 -2.5,-2 0,3 -9,0 0,2 9,0 0,3 z"
+ d="m 10,1048.3622 5,-4 -5,-4 0,3 -9,0 0,2 9,0 z"
id="rect4352"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_auto_play.svg b/tools/editor/icons/source/icon_auto_play.svg
index 00bc96aac5..d4e1068ebf 100644
--- a/tools/editor/icons/source/icon_auto_play.svg
+++ b/tools/editor/icons/source/icon_auto_play.svg
@@ -28,9 +28,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="64"
- inkscape:cx="6.4431479"
- inkscape:cy="7.7277865"
+ inkscape:zoom="32"
+ inkscape:cx="9.592521"
+ inkscape:cy="9.4268437"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -60,7 +60,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -70,40 +70,9 @@
id="layer1"
transform="translate(0,-1036.3622)">
<path
- style="fill:none;fill-rule:evenodd;stroke:#e0e0e0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
- d="m 2,1049.3622 0,-10 8,0 4,5 -4,5 z"
- id="path4164"
- inkscape:connector-curvature="0" />
- <rect
- y="1043.3622"
- x="4"
- height="3.9999824"
- width="1"
- id="rect4162"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <path
- style="fill:#e0e0e0;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
- d="m 11,1044.3622 -2,-2 0,4 z"
- id="path4166"
- inkscape:connector-curvature="0" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4168"
- width="1"
- height="3.9999824"
- x="7"
- y="1043.3622" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4170"
- width="2"
- height="0.99994755"
- x="5"
- y="1044.3622" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="M 6 5 C 4.8954305 5 4 5.8954 4 7 L 5 7 A 1 1 0 0 1 6 6 A 1 1 0 0 1 7 7 L 8 7 C 8 5.8954 7.1045695 5 6 5 z "
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#e0e0e0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ d="M 2 2 A 1.0001 1.0001 0 0 0 1 3 L 1 13 A 1.0001 1.0001 0 0 0 2 14 L 10 14 A 1.0001 1.0001 0 0 0 10.78125 13.625 L 14.78125 8.625 A 1.0001 1.0001 0 0 0 14.78125 7.3769531 L 10.78125 2.3769531 A 1.0001 1.0001 0 0 0 10 2 L 2 2 z M 3 4 L 9.5195312 4 L 12.71875 8 L 9.5195312 12 L 3 12 L 3 4 z M 6 5 C 4.8954305 5 4 5.8954 4 7 L 4 11 L 5 11 L 5 9 L 7 9 L 7 11 L 8 11 L 8 7 C 8 5.8954 7.1045695 5 6 5 z M 6 6 A 1 1 0 0 1 7 7 L 7 8 L 5 8 L 5 7 A 1 1 0 0 1 6 6 z M 9 6 L 9 10 L 11 8 L 9 6 z "
transform="translate(0,1036.3622)"
- id="path4172" />
+ id="path4164" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_back_buffer_copy.svg b/tools/editor/icons/source/icon_back_buffer_copy.svg
index 150421d7dd..17d83ed73f 100644
--- a/tools/editor/icons/source/icon_back_buffer_copy.svg
+++ b/tools/editor/icons/source/icon_back_buffer_copy.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
- inkscape:cx="12.102474"
- inkscape:cy="8.4888344"
+ inkscape:cx="3.8381635"
+ inkscape:cy="8.4004461"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -59,7 +59,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -68,57 +68,10 @@
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
- <rect
+ <path
style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4146"
- width="2"
- height="9"
- x="1"
- y="1037.3622" />
- <rect
- y="1037.3622"
- x="1"
- height="2.0000174"
- width="8"
- id="rect4148"
- style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <rect
- y="-1051.3622"
- x="-15"
- height="9"
- width="2"
- id="rect4150"
- style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="scale(-1,-1)" />
- <rect
- style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4152"
- width="7"
- height="2.0000174"
- x="-15"
- y="-1051.3622"
- transform="scale(-1,-1)" />
- <rect
- transform="scale(-1,-1)"
- style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4154"
- width="2"
- height="9"
- x="-9"
- y="-1051.3622" />
- <rect
- style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4156"
- width="8"
- height="2.0000174"
- x="7"
- y="1040.3622" />
- <rect
- style="opacity:1;fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4158"
- width="5"
- height="2.0000174"
- x="1"
- y="1046.3622" />
+ d="M 1 1 L 1 3 L 1 10 L 1 12 L 6 12 L 6 10 L 3 10 L 3 3 L 9 3 L 9 1 L 3 1 L 1 1 z M 7 4 L 7 6 L 7 15 L 9 15 L 15 15 L 15 13 L 15 6 L 15 4 L 7 4 z M 9 6 L 13 6 L 13 13 L 9 13 L 9 6 z "
+ transform="translate(0,1036.3622)"
+ id="rect4146" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_bake.svg b/tools/editor/icons/source/icon_bake.svg
index 7f1e9b4ae8..ca07bca379 100644
--- a/tools/editor/icons/source/icon_bake.svg
+++ b/tools/editor/icons/source/icon_bake.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
- inkscape:cx="4.5449307"
- inkscape:cy="12.981869"
+ inkscape:cx="-3.7193798"
+ inkscape:cy="12.893481"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -60,7 +60,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -71,22 +71,8 @@
transform="translate(0,-1036.3622)">
<path
style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="M 1 4 L 1 13 A 2 2.0000174 0 0 0 3 15 L 13 15 A 2 2.0000174 0 0 0 15 13 L 15 4 L 1 4 z M 3 5 L 4 5 L 4 6 L 3 6 L 3 5 z M 6 5 L 7 5 L 7 6 L 6 6 L 6 5 z M 9 5 L 10 5 L 10 6 L 9 6 L 9 5 z M 12 5 L 13 5 L 13 6 L 12 6 L 12 5 z M 3 7 L 13 7 L 13 13 L 3 13 L 3 7 z "
+ d="M 2 1 L 2 3 L 14 3 L 14 1 L 2 1 z M 1 4 L 1 13 A 2 2.0000174 0 0 0 3 15 L 13 15 A 2 2.0000174 0 0 0 15 13 L 15 4 L 1 4 z M 3 5 L 4 5 L 4 6 L 3 6 L 3 5 z M 6 5 L 7 5 L 7 6 L 6 6 L 6 5 z M 9 5 L 10 5 L 10 6 L 9 6 L 9 5 z M 12 5 L 13 5 L 13 6 L 12 6 L 12 5 z M 3 7 L 13 7 L 13 13 L 3 13 L 3 7 z M 6 8 L 6 9 L 10 9 L 10 8 L 6 8 z "
transform="translate(0,1036.3622)"
id="rect4155" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4173"
- width="12"
- height="2.0000174"
- x="2"
- y="1037.3622" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4159"
- width="4"
- height="1.0000174"
- x="6"
- y="1044.3622" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_baked_light.svg b/tools/editor/icons/source/icon_baked_light.svg
index 7f1e9b4ae8..98dc3135f6 100644
--- a/tools/editor/icons/source/icon_baked_light.svg
+++ b/tools/editor/icons/source/icon_baked_light.svg
@@ -18,7 +18,7 @@
inkscape:export-filename="/home/djrm/Projects/godot/tools/editor/icons/icon_bone.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
- sodipodi:docname="icon_bake.svg">
+ sodipodi:docname="icon_baked_light.svg">
<defs
id="defs4" />
<sodipodi:namedview
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
- inkscape:cx="4.5449307"
- inkscape:cy="12.981869"
+ inkscape:cx="6.1801151"
+ inkscape:cy="10.551189"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -60,7 +60,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -71,22 +71,8 @@
transform="translate(0,-1036.3622)">
<path
style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="M 1 4 L 1 13 A 2 2.0000174 0 0 0 3 15 L 13 15 A 2 2.0000174 0 0 0 15 13 L 15 4 L 1 4 z M 3 5 L 4 5 L 4 6 L 3 6 L 3 5 z M 6 5 L 7 5 L 7 6 L 6 6 L 6 5 z M 9 5 L 10 5 L 10 6 L 9 6 L 9 5 z M 12 5 L 13 5 L 13 6 L 12 6 L 12 5 z M 3 7 L 13 7 L 13 13 L 3 13 L 3 7 z "
+ d="M 2 1 L 2 3 L 14 3 L 14 1 L 2 1 z M 1 4 L 1 13 A 2 2.0000174 0 0 0 3 15 L 13 15 A 2 2.0000174 0 0 0 15 13 L 15 4 L 1 4 z M 3 5 L 4 5 L 4 6 L 3 6 L 3 5 z M 6 5 L 7 5 L 7 6 L 6 6 L 6 5 z M 9 5 L 10 5 L 10 6 L 9 6 L 9 5 z M 12 5 L 13 5 L 13 6 L 12 6 L 12 5 z M 3 7 L 13 7 L 13 13 L 3 13 L 3 7 z M 6 8 L 6 9 L 10 9 L 10 8 L 6 8 z "
transform="translate(0,1036.3622)"
id="rect4155" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4173"
- width="12"
- height="2.0000174"
- x="2"
- y="1037.3622" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4159"
- width="4"
- height="1.0000174"
- x="6"
- y="1044.3622" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_baked_light_instance.svg b/tools/editor/icons/source/icon_baked_light_instance.svg
index 434bf0f6fc..d854378f12 100644
--- a/tools/editor/icons/source/icon_baked_light_instance.svg
+++ b/tools/editor/icons/source/icon_baked_light_instance.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
- inkscape:cx="-3.1006614"
- inkscape:cy="12.893481"
+ inkscape:cx="10.864698"
+ inkscape:cy="11.302491"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -71,22 +71,8 @@
transform="translate(0,-1036.3622)">
<path
style="opacity:1;fill:#fc9c9c;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="M 1 4 L 1 13 A 2 2.0000174 0 0 0 3 15 L 13 15 A 2 2.0000174 0 0 0 15 13 L 15 4 L 1 4 z M 3 5 L 4 5 L 4 6 L 3 6 L 3 5 z M 6 5 L 7 5 L 7 6 L 6 6 L 6 5 z M 9 5 L 10 5 L 10 6 L 9 6 L 9 5 z M 12 5 L 13 5 L 13 6 L 12 6 L 12 5 z M 3 7 L 13 7 L 13 13 L 3 13 L 3 7 z "
+ d="M 2 1 L 2 3 L 14 3 L 14 1 L 2 1 z M 1 4 L 1 13 A 2 2.0000174 0 0 0 3 15 L 13 15 A 2 2.0000174 0 0 0 15 13 L 15 4 L 1 4 z M 3 5 L 4 5 L 4 6 L 3 6 L 3 5 z M 6 5 L 7 5 L 7 6 L 6 6 L 6 5 z M 9 5 L 10 5 L 10 6 L 9 6 L 9 5 z M 12 5 L 13 5 L 13 6 L 12 6 L 12 5 z M 3 7 L 13 7 L 13 13 L 3 13 L 3 7 z M 6 8 L 6 9 L 10 9 L 10 8 L 6 8 z "
transform="translate(0,1036.3622)"
id="rect4155" />
- <rect
- style="opacity:1;fill:#fc9c9c;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4173"
- width="12"
- height="2.0000174"
- x="2"
- y="1037.3622" />
- <rect
- style="opacity:1;fill:#fc9c9c;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4159"
- width="4"
- height="1.0000174"
- x="6"
- y="1044.3622" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_baked_light_sampler.svg b/tools/editor/icons/source/icon_baked_light_sampler.svg
index aa6e6e26d0..2dc7c39621 100644
--- a/tools/editor/icons/source/icon_baked_light_sampler.svg
+++ b/tools/editor/icons/source/icon_baked_light_sampler.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
- inkscape:cx="3.5600026"
- inkscape:cy="5.9708001"
+ inkscape:cx="9.2162526"
+ inkscape:cy="7.9395501"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -71,20 +71,8 @@
transform="translate(0,-1036.3622)">
<path
style="opacity:1;fill:#fc9c9c;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="M 1 4 L 1 13 A 2 2.0000174 0 0 0 3 15 L 7 15 L 7 13 L 3 13 L 3 7 L 7 7 L 13 7 L 15 7 L 15 4 L 1 4 z M 3 5 L 4 5 L 4 6 L 3 6 L 3 5 z M 6 5 L 7 5 L 7 6 L 6 6 L 6 5 z M 9 5 L 10 5 L 10 6 L 9 6 L 9 5 z M 12 5 L 13 5 L 13 6 L 12 6 L 12 5 z M 6 8 L 6 9 L 7 9 L 7 8 L 6 8 z "
+ d="M 2 1 L 2 3 L 14 3 L 14 1 L 2 1 z M 1 4 L 1 13 A 2 2.0000174 0 0 0 3 15 L 7 15 L 7 13 L 3 13 L 3 7 L 7 7 L 13 7 L 15 7 L 15 4 L 1 4 z M 3 5 L 4 5 L 4 6 L 3 6 L 3 5 z M 6 5 L 7 5 L 7 6 L 6 6 L 6 5 z M 9 5 L 10 5 L 10 6 L 9 6 L 9 5 z M 12 5 L 13 5 L 13 6 L 12 6 L 12 5 z M 6 8 L 6 9 L 7 9 L 7 8 L 6 8 z M 10 9 A 1 1 0 0 0 9 10 L 9 14 A 1 1 0 0 0 10 15 L 14 15 A 1 1 0 0 0 15 14 L 15 10 A 1 1 0 0 0 14 9 L 10 9 z M 13 10 A 1 1 0 0 1 14 11 A 1 1 0 0 1 13 12 A 1 1 0 0 1 12 11 A 1 1 0 0 1 13 10 z M 11 12 A 1 1 0 0 1 12 13 A 1 1 0 0 1 11 14 A 1 1 0 0 1 10 13 A 1 1 0 0 1 11 12 z "
transform="translate(0,1036.3622)"
id="rect4155" />
- <rect
- style="opacity:1;fill:#fc9c9c;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4173"
- width="12"
- height="2.0000174"
- x="2"
- y="1037.3622" />
- <path
- style="opacity:1;fill:#fc9c9c;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="M 10 9 A 1 1 0 0 0 9 10 L 9 14 A 1 1 0 0 0 10 15 L 14 15 A 1 1 0 0 0 15 14 L 15 10 A 1 1 0 0 0 14 9 L 10 9 z M 13 10 A 1 1 0 0 1 14 11 A 1 1 0 0 1 13 12 A 1 1 0 0 1 12 11 A 1 1 0 0 1 13 10 z M 11 12 A 1 1 0 0 1 12 13 A 1 1 0 0 1 11 14 A 1 1 0 0 1 10 13 A 1 1 0 0 1 11 12 z "
- transform="translate(0,1036.3622)"
- id="rect4156" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_bitmap_font.svg b/tools/editor/icons/source/icon_bitmap_font.svg
index fa9fdaf5c5..70749923d5 100644
--- a/tools/editor/icons/source/icon_bitmap_font.svg
+++ b/tools/editor/icons/source/icon_bitmap_font.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
- inkscape:cx="10.302728"
- inkscape:cy="7.9861624"
+ inkscape:cx="5.619442"
+ inkscape:cy="6.940754"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -60,7 +60,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -69,62 +69,10 @@
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="rect4212"
- width="14"
- height="2"
- x="1"
- y="1037.3622" />
- <rect
- y="1037.3622"
- x="7"
- height="14.000017"
- width="2"
- id="rect4214"
- style="opacity:1;fill:#fcef9c;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843" />
- <rect
- style="opacity:1;fill:#fcef9c;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="rect4216"
- width="6"
- height="0.99999976"
- x="5"
- y="1050.3622" />
- <path
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- d="M 1 1 L 1 3 L 1 5 L 2 5 L 2 4 L 3 4 L 3 3 L 4 3 L 4 1 L 2 1 L 1 1 z "
- transform="translate(0,1036.3622)"
- id="rect4218" />
<path
- style="opacity:1;fill:#be9cfc;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- d="M 12 1 L 12 3 L 13 3 L 13 4 L 14 4 L 14 5 L 15 5 L 15 3 L 15 1 L 14 1 L 12 1 z "
- transform="translate(0,1036.3622)"
- id="rect4220" />
- <rect
- style="opacity:1;fill:#fcef9c;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="rect4259"
- width="1"
- height="1"
- x="9"
- y="1049.3622" />
- <rect
- y="1049.3622"
- x="6"
- height="1"
- width="1"
- id="rect4261"
- style="opacity:1;fill:#fcef9c;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843" />
- <path
- style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- d="M 4 1 L 4 3 L 7 3 L 7 6 L 9 6 L 9 3 L 12 3 L 12 1 L 4 1 z "
- transform="translate(0,1036.3622)"
- id="rect4276" />
- <rect
- style="opacity:1;fill:#a5b7f8;fill-opacity:0.98823529;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="rect4307"
- width="2"
- height="5"
- x="7"
- y="1042.3622" />
+ style="opacity:1;fill:#84c2ff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
+ d="m 1,1037.3622 0,2 0,2 1,0 0,-1 1,0 0,-1 4,0 0,3 0,5 0,2 -1,0 0,1 -1,0 0,1 6,0 0,-1 -1,0 0,-1 -1,0 0,-10 4,0 0,1 1,0 0,1 1,0 0,-2 0,-2 -13,0 -1,0 z"
+ id="rect4212"
+ inkscape:connector-curvature="0" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_canvas_layer.svg b/tools/editor/icons/source/icon_canvas_layer.svg
index a26edd7d6d..794d832eea 100644
--- a/tools/editor/icons/source/icon_canvas_layer.svg
+++ b/tools/editor/icons/source/icon_canvas_layer.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
- inkscape:cx="-3.1074492"
- inkscape:cy="10.973033"
+ inkscape:cx="-2.2677599"
+ inkscape:cy="10.08915"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -64,7 +64,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -74,35 +74,9 @@
id="layer1"
transform="translate(0,-1036.3622)">
<path
- sodipodi:nodetypes="cscsccccsssc"
- inkscape:connector-curvature="0"
- id="path4146"
- d="m 2.920797,1046.3957 c -0.2637264,0.3 -0.4203983,0.7296 -0.4203983,1.2383 0,1.6277 -3.13814186,-0.1781 -0.337569,2.6703 0.8838207,0.899 2.6543881,0.6701 3.538224,-0.2288 0.8838352,-0.899 0.8838163,-2.3565 0,-3.2554 -1.1002211,-1.1191 -2.200058,-1.0845 -2.7802567,-0.4244 z m 2.3801743,-1.6103 2.4004918,2.4416 6.8013899,-6.9177 c 0.662863,-0.6742 0.662863,-1.7673 0,-2.4415 -0.662877,-0.6741 -1.737613,-0.6741 -2.400491,0 z"
- style="fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="M 3 1 A 2 2 0 0 0 1 3 L 2 3 A 1.0000174 1.0000174 0 0 1 3 2 L 3 1 z "
+ style="fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 3 1 A 2 2 0 0 0 1 3 L 1 9 L 2 9 L 2 3 A 1.0000174 1.0000174 0 0 1 3 2 L 9 2 L 9 1 L 3 1 z M 13.302734 1 C 12.868331 1 12.433001 1.1688094 12.101562 1.5058594 L 5.3007812 8.4238281 L 7.7011719 10.865234 L 14.501953 3.9472656 C 15.164816 3.2730656 15.164816 2.1800594 14.501953 1.5058594 C 14.170515 1.1688094 13.737138 1 13.302734 1 z M 14 7 L 14 13 A 1.0000174 1.0000174 0 0 1 13 14 L 7 14 L 7 15 L 13 15 A 2 2 0 0 0 15 13 L 15 7 L 14 7 z M 4.1152344 9.578125 C 3.6302227 9.5294 3.2100212 9.7031531 2.9199219 10.033203 C 2.6561955 10.333203 2.5 10.762784 2.5 11.271484 C 2.5 12.899184 -0.63846349 11.093006 2.1621094 13.941406 C 3.0459301 14.840406 4.817336 14.611791 5.7011719 13.712891 C 6.5850071 12.813891 6.5849882 11.355931 5.7011719 10.457031 C 5.1510613 9.8974813 4.6002461 9.62685 4.1152344 9.578125 z "
transform="translate(0,1036.3622)"
- id="path4160" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4164"
- width="6"
- height="1"
- x="3"
- y="1037.3622" />
- <rect
- y="-2"
- x="1039.3622"
- height="1"
- width="6"
- id="rect4166"
- style="opacity:1;fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="matrix(0,1,-1,0,0,0)" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="m 13,1051.3622 a 2,2 0 0 0 2,-2 l 0,-6 -1,0 0,6 a 1.0000174,1.0000174 0 0 1 -1,1 l -6,0 0,1 6,0 z"
- id="path4169"
- inkscape:connector-curvature="0" />
+ id="path4146" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_canvas_modulate.svg b/tools/editor/icons/source/icon_canvas_modulate.svg
index 450823e005..8f8bd55f82 100644
--- a/tools/editor/icons/source/icon_canvas_modulate.svg
+++ b/tools/editor/icons/source/icon_canvas_modulate.svg
@@ -20,7 +20,44 @@
inkscape:export-ydpi="90"
sodipodi:docname="icon_canvas_modulate.svg">
<defs
- id="defs4" />
+ id="defs4">
+ <clipPath
+ id="clipPath4253"
+ clipPathUnits="userSpaceOnUse">
+ <path
+ inkscape:connector-curvature="0"
+ id="path4255"
+ d="m 16.458984,1024.37 a 12.000027,12.000027 0 0 0 -3.564453,0.4004 12.000027,12.000027 0 0 0 -8.4863279,14.6973 12.000027,12.000027 0 0 0 14.6972659,8.4863 12.000027,12.000027 0 0 0 8.486328,-14.6973 12.000027,12.000027 0 0 0 -11.132813,-8.8867 z M 16.25,1029.8212 a 6.5451717,6.5451717 0 0 1 6.072266,4.8476 6.5451717,6.5451717 0 0 1 -4.628907,8.0157 6.5451717,6.5451717 0 0 1 -8.0156246,-4.6289 6.5451717,6.5451717 0 0 1 4.6289066,-8.0157 6.5451717,6.5451717 0 0 1 1.943359,-0.2187 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </clipPath>
+ <clipPath
+ id="clipPath4199"
+ clipPathUnits="userSpaceOnUse">
+ <path
+ style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="m 16.5,1025.8622 a 11.8125,10.499999 0 0 0 -11.8125001,10.5 11.8125,10.499999 0 0 0 11.8125001,10.5 11.8125,10.499999 0 0 0 11.8125,-10.5 11.8125,10.499999 0 0 0 -11.8125,-10.5 z m -3.375,3 a 3.375,2.9999997 0 0 1 3.375,3 3.375,2.9999997 0 0 1 -3.375,3 3.375,2.9999997 0 0 1 -3.3750001,-3 3.375,2.9999997 0 0 1 3.3750001,-3 z"
+ id="path4201"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath4392">
+ <path
+ style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 8.072266,1041.3622 a 5,5 0 0 0 -3.607422,1.4648 5,5 0 0 0 0,7.0704 5,5 0 0 0 7.070312,0 l -1.416015,-1.4161 A 3,3 0 0 1 8,1049.3622 a 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 2.119141,0.8809 l 1.416015,-1.4161 a 5,5 0 0 0 -3.46289,-1.4648 z"
+ id="path4394"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ id="clipPath4196"
+ clipPathUnits="userSpaceOnUse">
+ <path
+ inkscape:connector-curvature="0"
+ id="path4198"
+ d="m 8.0624999,1025.8622 a 3.375,2.9999997 0 0 0 -3.375,3 3.375,2.9999997 0 0 0 1.6875,2.5957 l 0,9.8115 a 3.375,2.9999997 0 0 0 -1.6875,2.5928 3.375,2.9999997 0 0 0 3.375,3 3.375,2.9999997 0 0 0 3.3750001,-3 3.375,2.9999997 0 0 0 -1.6875001,-2.5957 l 0,-8.7832 11.9311511,10.6054 a 3.375,2.9999997 0 0 0 -0.118651,0.7735 3.375,2.9999997 0 0 0 3.375,3 3.375,2.9999997 0 0 0 3.375,-3 3.375,2.9999997 0 0 0 -3.375,-3 3.375,2.9999997 0 0 0 -0.873413,0.1025 l -11.927857,-10.6025 9.884399,0 a 3.375,2.9999997 0 0 0 2.916871,1.5 3.375,2.9999997 0 0 0 3.375,-3 3.375,2.9999997 0 0 0 -3.375,-3 3.375,2.9999997 0 0 0 -2.920166,1.5 l -11.037964,0 a 3.375,2.9999997 0 0 0 -2.9168701,-1.5 z"
+ style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ </clipPath>
+ </defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
@@ -28,9 +65,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="16"
- inkscape:cx="7.3785882"
- inkscape:cy="11.139886"
+ inkscape:zoom="45.254834"
+ inkscape:cx="10.091501"
+ inkscape:cy="9.4358129"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -46,7 +83,10 @@
inkscape:window-height="1016"
inkscape:window-x="0"
inkscape:window-y="27"
- inkscape:window-maximized="1">
+ inkscape:window-maximized="1"
+ inkscape:snap-midpoints="true"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:object-nodes="true">
<inkscape:grid
type="xygrid"
id="grid3336"
@@ -60,7 +100,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -69,39 +109,29 @@
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
- <rect
- style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect4159"
- width="10"
- height="10.000017"
- x="3"
- y="1039.3622" />
<path
style="fill:#a5b7f1;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 1,1037.3622 0,2 0,12 2,0 12,0 0,-2 0,-12 -2,0 -10,0 z m 2,2 10,0 0,10 -10,0 z"
+ d="m 1,1037.3622 0,14 14,0 0,-14 z m 2,2 10,0 0,10 -10,0 z"
id="rect4280"
inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccccccccccc" />
- <ellipse
- style="fill:#ff0000;fill-opacity:0.78431373;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path4153"
- cx="6.5"
- cy="1045.8622"
- rx="2.5"
- ry="2.4999871" />
- <ellipse
- style="fill:#0000ff;fill-opacity:0.78431373;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="ellipse4157"
- cx="8"
- cy="1042.8622"
- rx="2.5"
- ry="2.4999938" />
- <ellipse
- ry="2.4999936"
- rx="2.5"
- cy="1045.8622"
- cx="9.5"
- id="ellipse4155"
- style="fill:#00ff00;fill-opacity:0.78431373;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4183"
+ d="m 12,1048.3622 -5,0 5,-5 z"
+ style="fill:#70bfff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="fill:#ff7070;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 4,1040.3622 5,0 -5,5 z"
+ id="path4185"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0"
+ id="path4187"
+ d="m 4,1048.3622 0,-3 5,-5 3,0 0,3 -5,5 z"
+ style="fill:#7aff70;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_connect.svg b/tools/editor/icons/source/icon_connect.svg
index 2261765bdf..745d3cc436 100644
--- a/tools/editor/icons/source/icon_connect.svg
+++ b/tools/editor/icons/source/icon_connect.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.627418"
- inkscape:cx="9.0509434"
- inkscape:cy="11.261328"
+ inkscape:cx="0.78663326"
+ inkscape:cy="12.940707"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -59,7 +59,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -68,52 +68,10 @@
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
- <rect
- y="1043.3622"
- x="1"
- height="1.9999478"
- width="5"
- id="rect4155"
- style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4157"
- width="4"
- height="12"
- x="7"
- y="1038.3622" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4159"
- width="3"
- height="2"
- x="11"
- y="1040.3622" />
- <rect
- y="1046.3622"
- x="11"
- height="2"
- width="3"
- id="rect4161"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <circle
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4163"
- cx="7"
- cy="1040.3622"
- r="2" />
- <rect
- y="1040.3622"
- x="5"
- height="8.0000172"
- width="4"
- id="rect4165"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <circle
- r="2"
- cy="1048.3622"
- cx="7"
- id="circle4167"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 7 2 A 2 2 0 0 0 5 4 L 5 7 L 1 7 L 1 9 L 5 9 L 5 12 A 2 2 0 0 0 7 14 L 11 14 L 11 12 L 14 12 L 14 10 L 11 10 L 11 6 L 14 6 L 14 4 L 11 4 L 11 2 L 7 2 z "
+ transform="translate(0,1036.3622)"
+ id="rect4155" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_connection_and_groups.svg b/tools/editor/icons/source/icon_connection_and_groups.svg
index 97f615d9bc..5468312b4b 100644
--- a/tools/editor/icons/source/icon_connection_and_groups.svg
+++ b/tools/editor/icons/source/icon_connection_and_groups.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.627418"
- inkscape:cx="4.8878469"
- inkscape:cy="12.667351"
+ inkscape:cx="-3.3764632"
+ inkscape:cy="12.578963"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -68,97 +68,10 @@
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
- <rect
- y="1048.3622"
- x="2"
- height="0.99993038"
- width="6"
- id="rect4155"
- style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4157"
- width="2"
- height="6.9999485"
- x="10"
- y="1045.3622" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4159"
- width="2"
- height="0.9999826"
- x="12"
- y="1046.3622" />
- <rect
- y="1050.3622"
- x="12"
- height="0.9999826"
- width="2"
- id="rect4161"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <ellipse
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4163"
- cx="10"
- cy="1047.3622"
- rx="2"
- ry="1.9999913" />
- <circle
- r="2"
- cy="1050.3622"
- cx="10"
- id="circle4167"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <rect
- y="1047.3623"
- x="8"
- height="2.9998953"
- width="2"
- id="rect4201"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4203"
- width="12"
- height="1"
- x="2"
- y="1036.3622" />
- <rect
- y="1042.3622"
- x="2"
- height="1"
- width="12"
- id="rect4205"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <rect
- y="-3"
- x="1036.3622"
- height="1"
- width="6.0000348"
- id="rect4207"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="matrix(0,1,-1,0,0,0)" />
- <rect
- transform="matrix(0,1,-1,0,0,0)"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4209"
- width="6.0000348"
- height="1"
- x="1036.3622"
- y="-14" />
- <ellipse
- ry="1.5000032"
- rx="1.5"
- cy="1039.8622"
- cx="5.5"
- id="ellipse4214"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <ellipse
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="ellipse4216"
- cx="10.5"
- cy="1039.8622"
- rx="1.5"
- ry="1.5000032" />
+ <path
+ style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 2 0 L 2 1 L 2 6 L 2 7 L 14 7 L 14 6 L 14 0 L 3 0 L 2 0 z M 3 1 L 13 1 L 13 6 L 3 6 L 3 1 z M 5.5 2 A 1.5 1.5000032 0 0 0 4 3.5 A 1.5 1.5000032 0 0 0 5.5 5 A 1.5 1.5000032 0 0 0 7 3.5 A 1.5 1.5000032 0 0 0 5.5 2 z M 10.5 2 A 1.5 1.5000032 0 0 0 9 3.5 A 1.5 1.5000032 0 0 0 10.5 5 A 1.5 1.5000032 0 0 0 12 3.5 A 1.5 1.5000032 0 0 0 10.5 2 z M 10 9 A 2 1.9999913 0 0 0 8 11 L 8 12 L 2 12 L 2 13 L 8 13 L 8 14 A 2 2 0 0 0 10 16 L 12 16 L 12 15 L 14 15 L 14 14 L 12 14 L 12 11 L 14 11 L 14 10 L 12 10 L 12 9 L 10 9 z "
+ transform="translate(0,1036.3622)"
+ id="rect4155" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_copy_node_path.svg b/tools/editor/icons/source/icon_copy_node_path.svg
new file mode 100644
index 0000000000..9f33c5e54d
--- /dev/null
+++ b/tools/editor/icons/source/icon_copy_node_path.svg
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ viewBox="0 0 16 16"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ inkscape:export-filename="/home/godotengine/godot/tools/editor/icons/con_script_create.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ sodipodi:docname="icon_copy_node_path.svg">
+ <defs
+ id="defs4">
+ <clipPath
+ id="clipPath4253"
+ clipPathUnits="userSpaceOnUse">
+ <path
+ inkscape:connector-curvature="0"
+ id="path4255"
+ d="m 16.458984,1024.37 a 12.000027,12.000027 0 0 0 -3.564453,0.4004 12.000027,12.000027 0 0 0 -8.4863279,14.6973 12.000027,12.000027 0 0 0 14.6972659,8.4863 12.000027,12.000027 0 0 0 8.486328,-14.6973 12.000027,12.000027 0 0 0 -11.132813,-8.8867 z M 16.25,1029.8212 a 6.5451717,6.5451717 0 0 1 6.072266,4.8476 6.5451717,6.5451717 0 0 1 -4.628907,8.0157 6.5451717,6.5451717 0 0 1 -8.0156246,-4.6289 6.5451717,6.5451717 0 0 1 4.6289066,-8.0157 6.5451717,6.5451717 0 0 1 1.943359,-0.2187 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </clipPath>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="21.189633"
+ inkscape:cx="12.640765"
+ inkscape:cy="9.6848443"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ units="px"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:snap-object-midpoints="true"
+ inkscape:snap-center="true"
+ inkscape:window-width="1920"
+ inkscape:window-height="1016"
+ inkscape:window-x="0"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1"
+ showguides="false"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:object-nodes="true">
+ <inkscape:grid
+ type="xygrid"
+ id="grid3336"
+ empspacing="4" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <circle
+ cy="1048.3622"
+ cx="3"
+ id="ellipse4234"
+ style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
+ ry="1.0000174"
+ rx="1" />
+ <path
+ style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 2 1 C 1.4477381 1.0001 1.0000552 1.4477 1 2 L 1 14 C 1.0000552 14.5523 1.4477381 14.9999 2 15 L 14 15 C 14.552262 14.9999 14.999945 14.5523 15 14 L 15 6 L 10 1 L 2 1 z M 3 3 L 9 3 L 9 6 C 9 6.554 9.4459905 7 10 7 L 13 7 L 13 13 L 3 13 L 3 3 z M 6 8 L 4 12 L 6 12 L 8 8 L 6 8 z M 10 8 L 8 12 L 10 12 L 12 8 L 10 8 z "
+ transform="translate(0,1036.3622)"
+ id="rect4178" />
+ </g>
+</svg>
diff --git a/tools/editor/icons/source/icon_create_new_scene_from.svg b/tools/editor/icons/source/icon_create_new_scene_from.svg
index f5a456773c..529553bbd3 100644
--- a/tools/editor/icons/source/icon_create_new_scene_from.svg
+++ b/tools/editor/icons/source/icon_create_new_scene_from.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
- inkscape:cx="4.1061535"
- inkscape:cy="9.360052"
+ inkscape:cx="-3.7255471"
+ inkscape:cy="8.1847434"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -46,7 +46,10 @@
inkscape:window-height="1016"
inkscape:window-x="0"
inkscape:window-y="27"
- inkscape:window-maximized="1">
+ inkscape:window-maximized="1"
+ inkscape:snap-midpoints="true"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:object-nodes="true">
<inkscape:grid
type="xygrid"
id="grid3336" />
@@ -59,7 +62,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -70,9 +73,11 @@
transform="translate(0,-1036.3622)">
<path
style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="M 1 7 L 1 13 A 2 2 0 0 0 3 15 L 15 15 L 15 7 L 1 7 z M 4 9 L 5 9 L 5 11 L 7 11 L 7 12 L 5 12 L 5 14 L 4 14 L 4 12 L 2 12 L 2 11 L 4 11 L 4 9 z "
+ d="m 1,7 0,6 c 0,1.104569 0.8954305,2 2,2 l 7,0 0,-1 -2,0 0,-4 2,0 0,-2 4,0 0,2 1,0 0,-3 z"
transform="translate(0,1036.3622)"
- id="rect4136" />
+ id="rect4136"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cssccccccccccc" />
<path
style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 0.7112932,1040.3831 1,1042.3622 l 2.2438279,-0.3273 -0.8182578,-1.9018 -1.7142769,0.25 z m 3.6933293,-0.5387 0.8182578,1.9018 1.9790524,-0.2887 -0.8182579,-1.9018 -1.9790523,0.2887 z m 3.9581047,-0.5775 0.8182579,1.9018 1.9790519,-0.2887 -0.818257,-1.9018 -1.9790528,0.2887 z m 3.9581048,-0.5774 0.818258,1.9018 1.714277,-0.25 -0.288707,-1.9791 -2.243828,0.3273 z"
@@ -80,5 +85,17 @@
inkscape:connector-curvature="0"
inkscape:transform-center-x="-6.7823301"
inkscape:transform-center-y="-2" />
+ <circle
+ r="0"
+ cy="1047.3622"
+ cx="-14"
+ id="ellipse4234"
+ style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843" />
+ <path
+ sodipodi:nodetypes="ccccccccccccc"
+ inkscape:connector-curvature="0"
+ id="path4155"
+ d="m 13,1049.3622 2,0 0,-2 -2,0 0,-2 -2,0 0,2 -2,0 0,2 2,0 0,2 2,0 z"
+ style="fill:#84ffb1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_dynamic_font_data.svg b/tools/editor/icons/source/icon_dynamic_font_data.svg
index 468b472d7e..9f06172fef 100644
--- a/tools/editor/icons/source/icon_dynamic_font_data.svg
+++ b/tools/editor/icons/source/icon_dynamic_font_data.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
- inkscape:cx="1.442498"
- inkscape:cy="7.5824259"
+ inkscape:cx="6.4667889"
+ inkscape:cy="8.2902868"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -69,10 +69,10 @@
id="layer1"
transform="translate(0,-1036.3622)">
<path
- id="path4246"
- d="m 1,1037.3622 0,2 0,1 1,0 a 1,1 0 0 1 1,-1 l 2,0 0,6 a 1,1 0 0 1 -1,1 l 0,1 1,0 2,0 1,0 0,-1 a 1,1 0 0 1 -1,-1 l 0,-6 2,0 a 1,1 0 0 1 1,1 l 1,0 0,-1 0,-2 -4,0 -2,0 -4,0 z"
style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:connector-curvature="0" />
+ d="M 1 1 L 1 3 L 1 4 L 2 4 A 1 1 0 0 1 3 3 L 5 3 L 5 9 A 1 1 0 0 1 4 10 L 4 11 L 5 11 L 7 11 L 8 11 L 8 10 A 1 1 0 0 1 7 9 L 7 3 L 9 3 A 1 1 0 0 1 10 4 L 11 4 L 11 3 L 11 1 L 7 1 L 5 1 L 1 1 z M 1 6 L 1 8 L 3 8 L 3 6 L 1 6 z M 1 9 L 1 11 L 3 11 L 3 9 L 1 9 z M 1 12 L 1 14 L 3 14 L 3 12 L 1 12 z M 4 12 L 4 14 L 6 14 L 6 12 L 4 12 z "
+ transform="translate(0,1036.3622)"
+ id="path4246" />
<path
style="opacity:1;fill:#ff8484;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 4 5 L 4 7 L 4 8 L 5 8 A 1 1 0 0 1 6 7 L 8 7 L 8 13 A 1 1 0 0 1 7 14 L 7 15 L 8 15 L 10 15 L 11 15 L 11 14 A 1 1 0 0 1 10 13 L 10 7 L 12 7 A 1 1 0 0 1 13 8 L 14 8 L 14 7 L 14 5 L 10 5 L 8 5 L 4 5 z "
diff --git a/tools/editor/icons/source/icon_error.svg b/tools/editor/icons/source/icon_error.svg
index 831bac859a..a0b04a98cb 100644
--- a/tools/editor/icons/source/icon_error.svg
+++ b/tools/editor/icons/source/icon_error.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.627416"
- inkscape:cx="-12.047246"
- inkscape:cy="6.3485985"
+ inkscape:cx="5.542036"
+ inkscape:cy="14.568715"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -75,6 +75,7 @@
width="8"
height="8"
x="2.220446e-16"
- y="1044.3622" />
+ y="1044.3622"
+ ry="1.0000174" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_fixed_spatial_material.svg b/tools/editor/icons/source/icon_fixed_spatial_material.svg
index 575b0d06c6..7ae0f93ffc 100644
--- a/tools/editor/icons/source/icon_fixed_spatial_material.svg
+++ b/tools/editor/icons/source/icon_fixed_spatial_material.svg
@@ -7,7 +7,6 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
@@ -22,38 +21,6 @@
sodipodi:docname="icon_fixed_spatial_material.svg">
<defs
id="defs4">
- <linearGradient
- inkscape:collect="always"
- id="linearGradient4257">
- <stop
- style="stop-color:#ff70ac;stop-opacity:1"
- offset="0"
- id="stop4259" />
- <stop
- id="stop4273"
- offset="0.17862372"
- style="stop-color:#9f70ff;stop-opacity:1" />
- <stop
- id="stop4271"
- offset="0.3572498"
- style="stop-color:#70deff;stop-opacity:1" />
- <stop
- id="stop4269"
- offset="0.53587586"
- style="stop-color:#70ffb9;stop-opacity:1" />
- <stop
- id="stop4267"
- offset="0.71450192"
- style="stop-color:#9dff70;stop-opacity:1" />
- <stop
- id="stop4265"
- offset="0.89312798"
- style="stop-color:#ffeb70;stop-opacity:1" />
- <stop
- style="stop-color:#ff7070;stop-opacity:1"
- offset="1"
- id="stop4261" />
- </linearGradient>
<clipPath
id="clipPath4189"
clipPathUnits="userSpaceOnUse">
@@ -63,17 +30,33 @@
d="m 6.3750001,1025.8622 a 1.6876688,1.5001498 0 0 0 -1.6875,1.5 l 0,18 a 1.6876688,1.5001498 0 0 0 1.6875,1.5 l 10.1217039,0 c -0.747392,-0.8796 -1.304338,-1.8888 -1.562256,-3 l -6.8719479,0 0,-15 16.8749999,0 0,3.3486 a 3.4281247,3.0472216 0 0 1 1.282105,1.1279 c 0.537834,0.828 1.294284,1.677 2.092895,2.5723 l 0,-8.5488 a 1.6876688,1.5001498 0 0 0 -1.6875,-1.5 l -20.2499999,0 z m 11.8124999,4.5 0,1.5 -1.6875,0 0,1.5 -3.375,0 0,1.5 -1.6875,0 0,1.5 -1.6874999,0 0,1.5 3.3749999,0 3.375,0 0.02637,0 c 0.246127,-0.317 0.496441,-0.6239 0.738282,-0.9053 1.145331,-1.3327 2.270672,-2.4711 3.015746,-3.6182 a 3.4281247,3.0472216 0 0 1 1.282105,-1.1279 l 0,-0.3486 -1.6875,0 0,-1.5 -1.6875,0 z m 5.0625,4.5 c -1.948558,3 -5.0625,5.0146 -5.0625,7.5 0,2.4853 2.266559,4.5 5.0625,4.5 2.795941,0 5.0625,-2.0147 5.0625,-4.5 0,-2.4854 -3.113942,-4.5 -5.0625,-7.5 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
</clipPath>
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4257"
- id="radialGradient4263"
- cx="13.333239"
- cy="1043.3622"
- fx="13.333239"
- fy="1043.3622"
- r="7"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(-0.93305925,0.79975529,-0.85714494,-0.99999821,914.75331,2076.0592)" />
+ <clipPath
+ id="clipPath4253"
+ clipPathUnits="userSpaceOnUse">
+ <path
+ inkscape:connector-curvature="0"
+ id="path4255"
+ d="m 16.458984,1024.37 a 12.000027,12.000027 0 0 0 -3.564453,0.4004 12.000027,12.000027 0 0 0 -8.4863279,14.6973 12.000027,12.000027 0 0 0 14.6972659,8.4863 12.000027,12.000027 0 0 0 8.486328,-14.6973 12.000027,12.000027 0 0 0 -11.132813,-8.8867 z M 16.25,1029.8212 a 6.5451717,6.5451717 0 0 1 6.072266,4.8476 6.5451717,6.5451717 0 0 1 -4.628907,8.0157 6.5451717,6.5451717 0 0 1 -8.0156246,-4.6289 6.5451717,6.5451717 0 0 1 4.6289066,-8.0157 6.5451717,6.5451717 0 0 1 1.943359,-0.2187 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath4208">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 4.6875001,1042.3622 11.8124999,4.5 11.8125,-4.5 0,-12 -11.8125,-4.5 -11.8124999,4.5 z"
+ id="path4210"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath4199">
+ <path
+ inkscape:connector-curvature="0"
+ id="path4201"
+ d="m 16.5,1025.8622 a 11.8125,10.499999 0 0 0 -11.8125001,10.5 11.8125,10.499999 0 0 0 11.8125001,10.5 11.8125,10.499999 0 0 0 11.8125,-10.5 11.8125,10.499999 0 0 0 -11.8125,-10.5 z m -3.375,3 a 3.375,2.9999997 0 0 1 3.375,3 3.375,2.9999997 0 0 1 -3.375,3 3.375,2.9999997 0 0 1 -3.3750001,-3 3.375,2.9999997 0 0 1 3.3750001,-3 z"
+ style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ </clipPath>
</defs>
<sodipodi:namedview
id="base"
@@ -83,8 +66,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
- inkscape:cx="12.314693"
- inkscape:cy="10.250946"
+ inkscape:cx="11.899872"
+ inkscape:cy="11.262807"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -118,7 +101,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -127,21 +110,60 @@
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
- <path
- inkscape:connector-curvature="0"
- style="fill:url(#radialGradient4263);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 8,1037.3622 -7,3 0,8 7,3 7,-3 0,-8 -7,-3 z"
- id="path4151" />
- <path
- style="fill:#ffffff;fill-opacity:0.72222221;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 1,1040.3622 7,3 7,-3 -7,-3 z"
- id="path4149"
- inkscape:connector-curvature="0" />
- <path
- inkscape:connector-curvature="0"
- id="path4145"
- d="m 8,1051.3622 7,-3 0,-8 -7,3 z"
- style="fill:#000000;fill-opacity:0.46969697;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- sodipodi:nodetypes="ccccc" />
+ <g
+ id="g4181"
+ mask="none"
+ clip-path="url(#clipPath4199)"
+ transform="matrix(0.59259259,0,0,0.66666674,-1.7777777,353.454)">
+ <rect
+ y="1025.8622"
+ x="3"
+ height="3.0000043"
+ width="27"
+ id="rect4159"
+ style="fill:#ff7070;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ style="fill:#ffeb70;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect4161"
+ width="27"
+ height="3.0000041"
+ x="3"
+ y="1028.8622" />
+ <rect
+ style="fill:#9dff70;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect4163"
+ width="27"
+ height="2.9999995"
+ x="3"
+ y="1031.8622" />
+ <rect
+ y="1034.8622"
+ x="3"
+ height="3.0000031"
+ width="27"
+ id="rect4165"
+ style="fill:#70ffb9;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ y="1037.8622"
+ x="3"
+ height="3.0000029"
+ width="27"
+ id="rect4167"
+ style="fill:#70deff;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ style="fill:#ff70ac;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect4169"
+ width="27"
+ height="2.9999976"
+ x="3"
+ y="1043.8622" />
+ <rect
+ style="fill:#9f70ff;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect4146"
+ width="27"
+ height="3.0000029"
+ x="3"
+ y="1040.8622" />
+ </g>
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_key_next.svg b/tools/editor/icons/source/icon_key_next.svg
index 4155255434..942245305c 100644
--- a/tools/editor/icons/source/icon_key_next.svg
+++ b/tools/editor/icons/source/icon_key_next.svg
@@ -28,9 +28,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="32"
- inkscape:cx="3.6318496"
- inkscape:cy="7.8283625"
+ inkscape:zoom="45.254834"
+ inkscape:cx="8.9672408"
+ inkscape:cy="7.1977527"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -59,7 +59,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -69,23 +69,14 @@
id="layer1"
transform="translate(0,-1036.3622)">
<path
+ style="opacity:1;fill:#84ffb1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 11 9 L 11 11 L 9 11 L 9 13 L 11 13 L 11 15 L 13 15 L 13 13 L 15 13 L 15 11 L 13 11 L 13 9 L 11 9 z "
+ transform="translate(0,1036.3622)"
+ id="rect4156" />
+ <path
style="opacity:1;fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="M 11 1 A 4 4.0000024 0 0 0 7.1308594 4 L 1 4 L 1 6 L 2 6 L 2 8 L 5 8 L 5 6 L 7.1328125 6 A 4 4.0000024 0 0 0 9 8.4589844 L 9 7 L 11 7 A 2.0000174 2.0000174 0 0 1 9 5 A 2.0000174 2.0000174 0 0 1 11 3 A 2.0000174 2.0000174 0 0 1 13 5 A 2.0000174 2.0000174 0 0 1 11 7 L 14.458984 7 A 4 4.0000024 0 0 0 15 5 A 4 4.0000024 0 0 0 11 1 z "
+ d="M 11 1 A 4 4.0000024 0 0 0 7.1308594 4 L 1 4 L 1 6 L 2 6 L 2 8 L 5 8 L 5 6 L 7.1328125 6 A 4 4.0000024 0 0 0 10 8.8691406 L 10 8 L 13.638672 8 A 4 4.0000024 0 0 0 15 5 A 4 4.0000024 0 0 0 11 1 z M 11 3 A 2.0000174 2.0000174 0 0 1 13 5 A 2.0000174 2.0000174 0 0 1 11 7 A 2.0000174 2.0000174 0 0 1 9 5 A 2.0000174 2.0000174 0 0 1 11 3 z "
transform="translate(0,1036.3622)"
- id="path4137" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4156"
- width="2"
- height="5.9999828"
- x="11"
- y="1045.3622" />
- <rect
- y="1047.3622"
- x="9"
- height="2.0000174"
- width="6"
- id="rect4158"
- style="opacity:1;fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ id="path4137-6" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_reparent.svg b/tools/editor/icons/source/icon_reparent.svg
index 65f101c8f7..79543fe066 100644
--- a/tools/editor/icons/source/icon_reparent.svg
+++ b/tools/editor/icons/source/icon_reparent.svg
@@ -28,9 +28,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="11.313708"
- inkscape:cx="-1.4011549"
- inkscape:cy="8.7567876"
+ inkscape:zoom="22.627416"
+ inkscape:cx="11.980115"
+ inkscape:cy="8.5519429"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -46,7 +46,10 @@
inkscape:window-height="1016"
inkscape:window-x="0"
inkscape:window-y="27"
- inkscape:window-maximized="1">
+ inkscape:window-maximized="1"
+ inkscape:snap-midpoints="true"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:object-nodes="true">
<inkscape:grid
type="xygrid"
id="grid3336" />
@@ -59,7 +62,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -68,45 +71,15 @@
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
- <circle
- r="2"
- cy="1049.3622"
- cx="3"
- id="circle4277"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <circle
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="circle4279"
- cx="3"
- cy="1039.3622"
- r="2" />
- <circle
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="circle4281"
- cx="13"
- cy="1049.3622"
- r="2" />
<path
- style="fill:none;fill-rule:evenodd;stroke:#e0e0e0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
- d="m 3,1039.3622 0,10 10,0"
- id="path4287"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="m 9,1038.3622 0,2 a 3,3 0 0 1 3,3 l 2,0 a 5.0000172,5.0000172 0 0 0 -5,-5 z"
- id="path4289"
- inkscape:connector-curvature="0" />
- <rect
style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4294"
- width="2"
- height="2"
- x="12"
- y="1043.3622" />
+ d="M 3 2 A 2 2 0 0 0 1 4 A 2 2 0 0 0 2 5.7304688 L 2 11.271484 A 2 2 0 0 0 1 13 A 2 2 0 0 0 3 15 A 2 2 0 0 0 4.7304688 14 L 11.271484 14 A 2 2 0 0 0 13 15 A 2 2 0 0 0 15 13 A 2 2 0 0 0 13 11 A 2 2 0 0 0 11.269531 12 L 4.7285156 12 A 2 2 0 0 0 4 11.269531 L 4 5.7285156 A 2 2 0 0 0 5 4 A 2 2 0 0 0 3 2 z "
+ transform="translate(0,1036.3622)"
+ id="circle4277" />
<path
- style="fill:#e0e0e0;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
- d="m 9,1037.3622 0,4 -3,-2 z"
- id="path4296"
- inkscape:connector-curvature="0" />
+ style="opacity:1;fill:#84ffb1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 9 1 L 5 4 L 9 7 L 9 5 A 3 3 0 0 1 12 8 L 12 10 L 14 10 L 14 8 A 5.0000172 5.0000172 0 0 0 9 3 L 9 1 z "
+ transform="translate(0,1036.3622)"
+ id="path4289" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_script_remove.svg b/tools/editor/icons/source/icon_script_remove.svg
new file mode 100644
index 0000000000..1a0a0eebe3
--- /dev/null
+++ b/tools/editor/icons/source/icon_script_remove.svg
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ viewBox="0 0 16 16"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ inkscape:export-filename="/home/godotengine/godot/tools/editor/icons/con_script_create.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ sodipodi:docname="icon_script_remove.svg">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="42.379266"
+ inkscape:cx="6.774667"
+ inkscape:cy="6.9870579"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ units="px"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:snap-object-midpoints="true"
+ inkscape:snap-center="true"
+ inkscape:window-width="1920"
+ inkscape:window-height="1016"
+ inkscape:window-x="0"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1"
+ showguides="false"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:object-nodes="true">
+ <inkscape:grid
+ type="xygrid"
+ id="grid3336"
+ empspacing="4" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <path
+ style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
+ d="M 6 1 L 6 2 C 5.4477153 2 5 2.4477153 5 3 L 5 13 L 4 13 L 4 11 L 2 11 L 2 13 C 2.0002826 13.356983 2.1908437 13.686743 2.5 13.865234 C 2.6519425 13.953279 2.8243914 13.999759 3 14 L 3 15 L 8.6347656 15 L 7.0507812 13.416016 L 8.4648438 12.001953 L 7.0507812 10.585938 L 10.585938 7.0507812 L 12 8.4648438 L 12 8 L 12 5 L 15 5 L 15 3 C 15 1.8954305 14.104569 1 13 1 L 6 1 z "
+ transform="translate(0,1036.3622)"
+ id="rect4255" />
+ <path
+ style="opacity:1;fill:#b4b4b4;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
+ d="M 6 1 C 4.8954305 1 4 1.8954305 4 3 L 4 10 L 2 10 L 1 10 L 1 11 L 1 13 C 1 14.104569 1.8954305 15 3 15 C 4.1045695 15 5 14.104569 5 13 L 5 3 C 5 2.4477153 5.4477153 2 6 2 C 6.5522847 2 7 2.4477153 7 3 L 7 4 L 7 5 L 7 6 L 8 6 L 12 6 L 12 5 L 8 5 L 8 4 L 8 3 C 8 1.8954305 7.1045695 1 6 1 z M 2 11 L 4 11 L 4 13 C 4 13.552285 3.5522847 14 3 14 C 2.4477153 14 2 13.552285 2 13 L 2 11 z "
+ id="path4265"
+ transform="translate(0,1036.3622)" />
+ <circle
+ cy="1048.3622"
+ cx="3"
+ id="ellipse4234"
+ style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
+ ry="1.0000174"
+ rx="1" />
+ <path
+ style="fill:#ff8484;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 13.414214,1048.3622 1.414213,-1.4142 -1.414213,-1.4142 L 12,1046.948 l -1.414214,-1.4142 -1.4142131,1.4142 1.4142131,1.4142 -1.4142131,1.4142 1.4142131,1.4142 1.414214,-1.4142 1.414214,1.4142 1.414213,-1.4142 z"
+ id="path8069"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccc" />
+ </g>
+</svg>
diff --git a/tools/editor/icons/source/icon_shader.svg b/tools/editor/icons/source/icon_shader.svg
index ba12b007ad..1a2393fec2 100644
--- a/tools/editor/icons/source/icon_shader.svg
+++ b/tools/editor/icons/source/icon_shader.svg
@@ -32,12 +32,13 @@
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
- id="clipPath4199">
+ id="clipPath4207">
<path
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ d="m 6.3749999,1025.8622 c -0.931942,10e-5 -1.6874069,0.6715 -1.6875,1.5 l 0,18 c 9.31e-5,0.8284 0.755558,1.4998 1.6875,1.5 l 20.2500001,0 c 0.931942,-2e-4 1.687407,-0.6716 1.6875,-1.5 l 0,-12 -8.4375,-7.5 z m 1.6875,3 10.1250001,0 0,4.5 c 0,0.831 0.752609,1.5 1.6875,1.5 l 5.0625,0 0,9 -16.8750001,0 z"
+ id="path4209"
inkscape:connector-curvature="0"
- id="path4201"
- d="m 16.5,1025.8622 a 11.8125,10.499999 0 0 0 -11.8125001,10.5 11.8125,10.499999 0 0 0 11.8125001,10.5 11.8125,10.499999 0 0 0 11.8125,-10.5 11.8125,10.499999 0 0 0 -11.8125,-10.5 z m -3.375,3 a 3.375,2.9999997 0 0 1 3.375,3 3.375,2.9999997 0 0 1 -3.375,3 3.375,2.9999997 0 0 1 -3.3750001,-3 3.375,2.9999997 0 0 1 3.3750001,-3 z"
- style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ sodipodi:nodetypes="ccccccccccccccccc" />
</clipPath>
</defs>
<sodipodi:namedview
@@ -48,8 +49,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="31.999999"
- inkscape:cx="6.7591143"
- inkscape:cy="9.6862321"
+ inkscape:cx="20.042938"
+ inkscape:cy="7.6712905"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -95,7 +96,7 @@
<g
id="g4181"
mask="none"
- clip-path="url(#clipPath4199)"
+ clip-path="url(#clipPath4207)"
transform="matrix(0.59259259,0,0,0.66666674,-1.7777777,353.454)">
<rect
y="1025.8622"
diff --git a/tools/editor/icons/source/icon_spot_light.svg b/tools/editor/icons/source/icon_spot_light.svg
index b9130eff37..04f5b42f4d 100644
--- a/tools/editor/icons/source/icon_spot_light.svg
+++ b/tools/editor/icons/source/icon_spot_light.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="31.999999"
- inkscape:cx="5.5818635"
- inkscape:cy="8.6161108"
+ inkscape:cx="-0.26188668"
+ inkscape:cy="8.5536108"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -60,7 +60,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -71,48 +71,8 @@
transform="translate(0,-1036.3622)">
<path
style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- d="m 14,1046.3622 -12,0 c 0,-2.7614 2.6862915,-5 6,-5 3.313708,0 6,2.2386 6,5 z"
- id="path4155"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccsc" />
- <path
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- d="M 6 1 A 1 1 0 0 0 5 2 L 5 7 L 11 7 L 11 2 A 1 1 0 0 0 10 1 L 6 1 z "
+ d="M 6 1 A 1 1 0 0 0 5 2 L 5 5.6933594 C 3.2138662 6.5594405 2 8.153847 2 10 L 6 10 A 2 2 0 0 0 8 12 A 2 2 0 0 0 10 10 L 14 10 C 14 8.153847 12.786134 6.5594405 11 5.6933594 L 11 2 A 1 1 0 0 0 10 1 L 6 1 z M 4.9023438 10.634766 L 3.1699219 11.634766 L 4.1699219 13.365234 L 5.9023438 12.365234 L 4.9023438 10.634766 z M 11.097656 10.634766 L 10.097656 12.365234 L 11.830078 13.365234 L 12.830078 11.634766 L 11.097656 10.634766 z M 7 13 L 7 15 L 9 15 L 9 13 L 7 13 z "
transform="translate(0,1036.3622)"
- id="rect4158" />
- <circle
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="path4160"
- cx="8"
- cy="1046.3622"
- r="2" />
- <rect
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="rect4162"
- width="2"
- height="2"
- x="7"
- y="1049.3622"
- inkscape:transform-center-y="3.9999826" />
- <rect
- inkscape:transform-center-y="2.0000217"
- y="533.10931"
- x="-903.17627"
- height="2"
- width="2"
- id="rect4164"
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- transform="matrix(0.5,-0.8660254,0.8660254,0.5,0,0)"
- inkscape:transform-center-x="-3.4640975" />
- <rect
- inkscape:transform-center-x="3.4641473"
- transform="matrix(0.5,0.8660254,-0.8660254,0.5,0,0)"
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="rect4166"
- width="2"
- height="2"
- x="909.17621"
- y="519.25293"
- inkscape:transform-center-y="1.9999799" />
+ id="path4155" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_static_body.svg b/tools/editor/icons/source/icon_static_body.svg
index af1ebc8900..fcaa2b7d3e 100644
--- a/tools/editor/icons/source/icon_static_body.svg
+++ b/tools/editor/icons/source/icon_static_body.svg
@@ -28,9 +28,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="22.627417"
- inkscape:cx="7.2543819"
- inkscape:cy="7.4903504"
+ inkscape:zoom="11.313709"
+ inkscape:cx="10.872202"
+ inkscape:cy="6.7990901"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -72,67 +72,9 @@
id="layer1"
transform="translate(0,-1036.3622)">
<path
- style="fill:#a5b7f5;fill-opacity:0.98823529;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 25 3 C 22 3 21 6 21 6 C 20.879708 6.3608765 20.803605 6.6663233 20.707031 7 L 21 7 A 1 1 0 0 0 22 8 A 1 1 0 0 0 23 7 L 24 7 A 1 1 0 0 0 25 8 A 1 1 0 0 0 26 7 L 27 7 A 1 1 0 0 0 28 8 A 1 1 0 0 0 29 7 L 29.292969 7 C 29.196395 6.6663233 29.120292 6.3608765 29 6 C 29 6 28 3 25 3 z M 20.369141 8.1542969 C 19.864457 10.037394 19.478832 11.521168 18 13 L 32 13 C 30.521168 11.521168 30.135543 10.037394 29.630859 8.1542969 A 2 2 0 0 1 29 8.7324219 A 2 2 0 0 1 27 8.7324219 A 2 2 0 0 1 26.5 8.3203125 A 2 2 0 0 1 26 8.7324219 A 2 2 0 0 1 24 8.7324219 A 2 2 0 0 1 23.5 8.3203125 A 2 2 0 0 1 23 8.7324219 A 2 2 0 0 1 21 8.7324219 A 2 2 0 0 1 20.369141 8.1542969 z "
- transform="translate(0,1036.3622)"
- id="path4161" />
- <rect
- style="opacity:1;fill:#fefeff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="rect4175"
- width="1"
- height="1"
- x="20"
- y="1042.3622" />
- <rect
- y="1042.3622"
- x="29"
- height="1"
- width="1"
- id="rect4177"
- style="opacity:1;fill:#fefeff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843" />
- <path
style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- d="M 3 1 A 2 2 0 0 0 1.5859375 1.5859375 A 2 2 0 0 0 1 3 L 1 13 A 2 2 0 0 0 1.5859375 14.414062 A 2 2 0 0 0 3 15 L 13 15 A 2 2 0 0 0 15 13 L 15 3 A 2 2 0 0 0 13 1 L 3 1 z M 3 2 L 13 2 A 1.0000174 1.0000174 0 0 1 14 3 L 14 13 A 1.0000174 1.0000174 0 0 1 13 14 L 3 14 A 1.0000174 1.0000174 0 0 1 2 13 L 2 3 A 1.0000174 1.0000174 0 0 1 3 2 z "
+ d="M 3 1 A 2 2 0 0 0 1.5859375 1.5859375 A 2 2 0 0 0 1 3 L 1 13 A 2 2 0 0 0 1.5859375 14.414062 A 2 2 0 0 0 3 15 L 13 15 A 2 2 0 0 0 15 13 L 15 3 A 2 2 0 0 0 13 1 L 3 1 z M 3 2 L 13 2 A 1.0000174 1.0000174 0 0 1 14 3 L 14 13 A 1.0000174 1.0000174 0 0 1 13 14 L 3 14 A 1.0000174 1.0000174 0 0 1 2 13 L 2 3 A 1.0000174 1.0000174 0 0 1 3 2 z M 3 3 L 3 5 L 5 5 L 5 3 L 3 3 z M 11 3 L 11 5 L 13 5 L 13 3 L 11 3 z M 3 11 L 3 13 L 5 13 L 5 11 L 3 11 z M 11 11 L 11 13 L 13 13 L 13 11 L 11 11 z "
transform="translate(0,1036.3622)"
id="rect4179" />
- <rect
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="rect4195"
- width="2"
- height="2"
- x="3"
- y="1039.3622" />
- <rect
- y="1047.3622"
- x="3"
- height="2"
- width="2"
- id="rect4197"
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843" />
- <rect
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="rect4199"
- width="2"
- height="2"
- x="11"
- y="1047.3622" />
- <rect
- y="1039.3622"
- x="11"
- height="2"
- width="2"
- id="rect4201"
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843" />
- <g
- id="layer1-1"
- inkscape:label="Layer 1"
- transform="translate(-23.644738,-1.9878833)">
- <path
- id="path4139"
- transform="translate(0,1036.3622)"
- d="M 8,1 A 7,7 0 0 0 1,8 7,7 0 0 0 8,15 7,7 0 0 0 15,8 7,7 0 0 0 8,1 Z M 4,6 A 1,1 0 0 1 5,7 1,1 0 0 1 4,8 1,1 0 0 1 3,7 1,1 0 0 1 4,6 Z m 8,0 a 1,1 0 0 1 1,1 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 z m -7,3 6,0 a 3,3 0 0 1 -1.5,2.597656 3,3 0 0 1 -3,0 A 3,3 0 0 1 5,9 Z"
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:connector-curvature="0" />
- </g>
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_static_body_2d.svg b/tools/editor/icons/source/icon_static_body_2d.svg
index d47e924e37..0ed3ef7cf0 100644
--- a/tools/editor/icons/source/icon_static_body_2d.svg
+++ b/tools/editor/icons/source/icon_static_body_2d.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
- inkscape:cx="7.2543819"
- inkscape:cy="7.4903504"
+ inkscape:cx="-1.0099286"
+ inkscape:cy="7.4019621"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -62,7 +62,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -72,13 +72,6 @@
id="layer1"
transform="translate(0,-1036.3622)">
<rect
- style="opacity:1;fill:#fefeff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="rect4175"
- width="1"
- height="1"
- x="20"
- y="1042.3622" />
- <rect
y="1042.3622"
x="29"
height="1"
@@ -87,36 +80,8 @@
style="opacity:1;fill:#fefeff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843" />
<path
style="opacity:1;fill:#a5b7f6;fill-opacity:0.98823529;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- d="M 3 1 A 2 2 0 0 0 1.5859375 1.5859375 A 2 2 0 0 0 1 3 L 1 13 A 2 2 0 0 0 1.5859375 14.414062 A 2 2 0 0 0 3 15 L 13 15 A 2 2 0 0 0 15 13 L 15 3 A 2 2 0 0 0 13 1 L 3 1 z M 3 2 L 13 2 A 1.0000174 1.0000174 0 0 1 14 3 L 14 13 A 1.0000174 1.0000174 0 0 1 13 14 L 3 14 A 1.0000174 1.0000174 0 0 1 2 13 L 2 3 A 1.0000174 1.0000174 0 0 1 3 2 z "
+ d="M 3 1 A 2 2 0 0 0 1.5859375 1.5859375 A 2 2 0 0 0 1 3 L 1 13 A 2 2 0 0 0 1.5859375 14.414062 A 2 2 0 0 0 3 15 L 13 15 A 2 2 0 0 0 15 13 L 15 3 A 2 2 0 0 0 13 1 L 3 1 z M 3 2 L 13 2 A 1.0000174 1.0000174 0 0 1 14 3 L 14 13 A 1.0000174 1.0000174 0 0 1 13 14 L 3 14 A 1.0000174 1.0000174 0 0 1 2 13 L 2 3 A 1.0000174 1.0000174 0 0 1 3 2 z M 3 3 L 3 5 L 5 5 L 5 3 L 3 3 z M 11 3 L 11 5 L 13 5 L 13 3 L 11 3 z M 3 11 L 3 13 L 5 13 L 5 11 L 3 11 z M 11 11 L 11 13 L 13 13 L 13 11 L 11 11 z "
transform="translate(0,1036.3622)"
id="rect4179" />
- <rect
- style="opacity:1;fill:#a5b7f6;fill-opacity:0.98823529;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="rect4195"
- width="2"
- height="2"
- x="3"
- y="1039.3622" />
- <rect
- y="1047.3622"
- x="3"
- height="2"
- width="2"
- id="rect4197"
- style="opacity:1;fill:#a5b7f6;fill-opacity:0.98823529;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843" />
- <rect
- style="opacity:1;fill:#a5b7f6;fill-opacity:0.98823529;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="rect4199"
- width="2"
- height="2"
- x="11"
- y="1047.3622" />
- <rect
- y="1039.3622"
- x="11"
- height="2"
- width="2"
- id="rect4201"
- style="opacity:1;fill:#a5b7f6;fill-opacity:0.98823529;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_tab_container.svg b/tools/editor/icons/source/icon_tab_container.svg
index b53747bf1c..6c197a86f6 100644
--- a/tools/editor/icons/source/icon_tab_container.svg
+++ b/tools/editor/icons/source/icon_tab_container.svg
@@ -28,9 +28,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="32"
- inkscape:cx="4.8125618"
- inkscape:cy="8.9338072"
+ inkscape:zoom="45.254834"
+ inkscape:cx="3.8596634"
+ inkscape:cy="10.446251"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -62,7 +62,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -73,24 +73,8 @@
transform="translate(0,-1036.3622)">
<path
style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="M 3,1 C 1.8954305,1 1,1.8954305 1,3 l 0,10 c 0,1.104569 0.8954305,2 2,2 l 10,0 c 1.104569,0 2,-0.895431 2,-2 L 15,3 C 15,1.8954305 14.104569,1 13,1 Z m 0,2 10,0 0,10 -10,0 z"
+ d="M 3 1 C 1.8954305 1 1 1.8954305 1 3 L 1 13 C 1 14.104569 1.8954305 15 3 15 L 13 15 C 14.104569 15 15 14.104569 15 13 L 15 3 C 15 1.8954305 14.104569 1 13 1 L 3 1 z M 3 3 L 8 3 L 8 5 L 8 7 L 13 7 L 13 13 L 3 13 L 3 3 z M 10 3 L 13 3 L 13 5 L 10 5 L 10 3 z "
transform="translate(0,1036.3622)"
- id="rect4140"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="sssssssssccccc" />
- <rect
- style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="rect4158"
- width="10"
- height="2"
- x="3"
- y="1041.3622" />
- <rect
- y="1039.3622"
- x="8"
- height="2"
- width="5"
- id="rect4170"
- style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843" />
+ id="rect4140" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_tabs.svg b/tools/editor/icons/source/icon_tabs.svg
index 1b389fc30c..79ed1e5910 100644
--- a/tools/editor/icons/source/icon_tabs.svg
+++ b/tools/editor/icons/source/icon_tabs.svg
@@ -28,9 +28,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="32"
- inkscape:cx="3.2506704"
- inkscape:cy="11.363584"
+ inkscape:zoom="22.627417"
+ inkscape:cx="11.687421"
+ inkscape:cy="9.3335226"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -75,21 +75,21 @@
style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4156"
width="1"
- height="4.9999828"
+ height="9.0000172"
x="1"
- y="1042.3622" />
+ y="1040.3622" />
<rect
y="-8"
- x="1041.3622"
+ x="1039.3622"
height="6"
width="1"
id="rect4159"
style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
transform="matrix(0,1,-1,0,0,0)" />
<rect
- y="1042.3622"
- x="8"
- height="4.9999828"
+ y="1040.3622"
+ x="7"
+ height="3.0000174"
width="1"
id="rect4161"
style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
@@ -98,38 +98,26 @@
id="path4163"
sodipodi:type="arc"
sodipodi:cx="2"
- sodipodi:cy="1042.3622"
+ sodipodi:cy="1040.3622"
sodipodi:rx="1"
sodipodi:ry="1"
sodipodi:start="1.5707963"
sodipodi:end="0"
- d="m 2,1043.3622 a 1,1 0 0 1 -0.9238795,-0.6173 1,1 0 0 1 0.2167727,-1.0898 1,1 0 0 1 1.0897902,-0.2168 A 1,1 0 0 1 3,1042.3622 l -1,0 z" />
- <path
- d="m -8,1043.3622 a 1,1 0 0 1 -0.9238795,-0.6173 1,1 0 0 1 0.2167727,-1.0898 1,1 0 0 1 1.0897902,-0.2168 A 1,1 0 0 1 -7,1042.3622 l -1,0 z"
- sodipodi:end="0"
- sodipodi:start="1.5707963"
- sodipodi:ry="1"
- sodipodi:rx="1"
- sodipodi:cy="1042.3622"
- sodipodi:cx="-8"
- sodipodi:type="arc"
- id="path4165"
- style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="scale(-1,1)" />
+ d="m 2,1041.3622 a 1,1 0 0 1 -0.9238795,-0.6173 1,1 0 0 1 0.2167727,-1.0898 1,1 0 0 1 1.0897902,-0.2168 A 1,1 0 0 1 3,1040.3622 l -1,0 z" />
<rect
style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4167"
width="1"
- height="4.9999828"
+ height="9.0000172"
x="14"
- y="1042.3622" />
+ y="1040.3622" />
<rect
transform="matrix(0,1,-1,0,0,0)"
style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4169"
width="1"
height="6"
- x="1041.3622"
+ x="1039.3622"
y="-14" />
<path
transform="scale(-1,1)"
@@ -137,19 +125,19 @@
id="path4171"
sodipodi:type="arc"
sodipodi:cx="-14"
- sodipodi:cy="1042.3622"
+ sodipodi:cy="1040.3622"
sodipodi:rx="1"
sodipodi:ry="1"
sodipodi:start="1.5707963"
sodipodi:end="0"
- d="m -14,1043.3622 a 1,1 0 0 1 -0.92388,-0.6173 1,1 0 0 1 0.216773,-1.0898 1,1 0 0 1 1.08979,-0.2168 1,1 0 0 1 0.617317,0.9239 l -1,0 z" />
+ d="m -14,1041.3622 a 1,1 0 0 1 -0.92388,-0.6173 1,1 0 0 1 0.216773,-1.0898 1,1 0 0 1 1.08979,-0.2168 1,1 0 0 1 0.617317,0.9239 l -1,0 z" />
<rect
transform="matrix(0,1,-1,0,0,0)"
style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4173"
width="1"
height="13"
- x="1046.3622"
+ x="1042.3622"
y="-15" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_text_edit.svg b/tools/editor/icons/source/icon_text_edit.svg
index 1daf1ac75a..4d08e9e3b2 100644
--- a/tools/editor/icons/source/icon_text_edit.svg
+++ b/tools/editor/icons/source/icon_text_edit.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
- inkscape:cx="13.881612"
- inkscape:cy="11.594783"
+ inkscape:cx="5.6173015"
+ inkscape:cy="11.506395"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -72,31 +72,16 @@
id="layer1"
transform="translate(0,-1036.3622)">
<rect
- style="opacity:1;fill:#fefeff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="rect4175"
- width="1"
- height="1"
- x="20"
- y="1042.3622" />
- <rect
y="1042.3622"
x="29"
height="1"
width="1"
id="rect4177"
style="opacity:1;fill:#fefeff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843" />
- <rect
- style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
- id="rect4173"
- width="1"
- height="4"
- x="4"
- y="1040.3622" />
<path
- style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="m 3,1037.3622 c -1.1045695,0 -2,0.8954 -2,2 l 0,10 c 0,1.1046 0.8954305,2 2,2 l 10,0 c 1.104569,0 2,-0.8954 2,-2 l 0,-10 c 0,-1.1046 -0.895431,-2 -2,-2 z m 0,2 10,0 0,10 -10,0 z"
- id="rect4140"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="sssssssssccccc" />
+ style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
+ d="M 3 1 C 1.8954305 1 1 1.8954 1 3 L 1 13 C 1 14.1046 1.8954305 15 3 15 L 13 15 C 14.104569 15 15 14.1046 15 13 L 15 3 C 15 1.8954 14.104569 1 13 1 L 3 1 z M 3 3 L 13 3 L 13 13 L 3 13 L 3 3 z M 4 4 L 4 8 L 5 8 L 5 4 L 4 4 z "
+ transform="translate(0,1036.3622)"
+ id="rect4173" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_track_add_key.svg b/tools/editor/icons/source/icon_track_add_key.svg
index 96761526a8..f550f922bb 100644
--- a/tools/editor/icons/source/icon_track_add_key.svg
+++ b/tools/editor/icons/source/icon_track_add_key.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="45.254834"
- inkscape:cx="6.0361164"
- inkscape:cy="4.9218153"
+ inkscape:cx="10.389243"
+ inkscape:cy="3.816961"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -69,7 +69,7 @@
id="layer1"
transform="translate(0,-1044.3622)">
<path
- style="fill:#a9e100;fill-opacity:0.99607843;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ style="fill:#84ffb1;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 3 0 L 3 3 L 0 3 L 0 5 L 3 5 L 3 8 L 5 8 L 5 5 L 8 5 L 8 3 L 5 3 L 5 0 L 3 0 z "
transform="translate(0,1044.3622)"
id="rect4137" />
diff --git a/tools/editor/icons/source/icon_track_add_key_hl.svg b/tools/editor/icons/source/icon_track_add_key_hl.svg
index 79e566dde6..1b45cf8c4a 100644
--- a/tools/editor/icons/source/icon_track_add_key_hl.svg
+++ b/tools/editor/icons/source/icon_track_add_key_hl.svg
@@ -28,9 +28,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="45.254834"
- inkscape:cx="5.3806528"
- inkscape:cy="6.0126016"
+ inkscape:zoom="32"
+ inkscape:cx="-4.0417082"
+ inkscape:cy="5.5439904"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -69,9 +69,14 @@
id="layer1"
transform="translate(0,-1044.3622)">
<path
- style="fill:#e3fe03;fill-opacity:0.98823529;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ style="fill:#84ffb1;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 3 0 L 3 3 L 0 3 L 0 5 L 3 5 L 3 8 L 5 8 L 5 5 L 8 5 L 8 3 L 5 3 L 5 0 L 3 0 z "
+ id="rect4137"
+ transform="translate(0,1044.3622)" />
+ <path
transform="translate(0,1044.3622)"
- id="rect4137" />
+ id="path4143"
+ d="M 3 0 L 3 3 L 0 3 L 0 5 L 3 5 L 3 8 L 5 8 L 5 5 L 8 5 L 8 3 L 5 3 L 5 0 L 3 0 z "
+ style="fill:#ffffff;fill-opacity:0.42424244;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_viewport_container.svg b/tools/editor/icons/source/icon_viewport_container.svg
index c132820316..300b8390c4 100644
--- a/tools/editor/icons/source/icon_viewport_container.svg
+++ b/tools/editor/icons/source/icon_viewport_container.svg
@@ -29,8 +29,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
- inkscape:cx="11.29493"
- inkscape:cy="16.378302"
+ inkscape:cx="13.216634"
+ inkscape:cy="7.7987238"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -62,7 +62,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -73,8 +73,10 @@
transform="translate(0,-1036.3622)">
<path
style="opacity:1;fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="M 3 1 C 1.8954305 1 1 1.8954305 1 3 L 3 3 L 3 1 z M 5 1 L 5 3 L 7 3 L 7 1 L 5 1 z M 9 1 L 9 3 L 11 3 L 11 1 L 9 1 z M 13 1 L 13 3 L 15 3 C 15 1.8954305 14.104569 1 13 1 z M 6 4 C 5.469598 4.0001 4.9609495 4.2108375 4.5859375 4.5859375 C 4.2108465 4.9609375 4.00008 5.4696 4 6 L 4 10 C 4.00008 10.5304 4.2108475 11.039062 4.5859375 11.414062 C 4.9609485 11.789162 5.469598 11.9999 6 12 L 10 12 C 11.104569 12 12 11.1046 12 10 L 12 6 C 12 4.8954 11.104569 4 10 4 L 6 4 z M 1 5 L 1 7 L 3 7 L 3 5 L 1 5 z M 6 5 L 10 5 C 10.552281 5 10.99999 5.4477 11 6 L 11 10 C 10.99999 10.5523 10.552281 11 10 11 L 6 11 C 5.447719 11 5.00001 10.5523 5 10 L 5 6 C 5.00001 5.4477 5.447719 5 6 5 z M 13 5 L 13 7 L 15 7 L 15 5 L 13 5 z M 1 9 L 1 11 L 3 11 L 3 9 L 1 9 z M 13 9 L 13 11 L 15 11 L 15 9 L 13 9 z M 1 13 C 1 14.104569 1.8954305 15 3 15 L 3 13 L 1 13 z M 5 13 L 5 15 L 7 15 L 7 13 L 5 13 z M 9 13 L 9 15 L 11 15 L 11 13 L 9 13 z M 13 13 L 13 15 C 14.104569 15 15 14.104569 15 13 L 13 13 z "
+ d="M 3,1 C 1.8954305,1 1,1.8954305 1,3 l 0,10 c 0,1.104569 0.8954305,2 2,2 l 10,0 c 1.104569,0 2,-0.895431 2,-2 L 15,3 C 15,1.8954305 14.104569,1 13,1 Z M 3,3 13,3 13,13 3,13 Z M 6,4 C 5.469598,4.0001 4.9609495,4.2108375 4.5859375,4.5859375 4.2108465,4.9609375 4.00008,5.4696 4,6 l 0,4 c 8e-5,0.5304 0.2108475,1.039063 0.5859375,1.414062 C 4.9609485,11.789162 5.469598,11.9999 6,12 l 4,0 c 1.104569,0 2,-0.8954 2,-2 L 12,6 C 12,4.8954 11.104569,4 10,4 Z m 0,1 4,0 c 0.552281,0 0.99999,0.4477 1,1 l 0,4 c -10e-6,0.5523 -0.447719,1 -1,1 L 6,11 C 5.447719,11 5.00001,10.5523 5,10 L 5,6 C 5.00001,5.4477 5.447719,5 6,5 Z"
transform="translate(0,1036.3622)"
- id="rect4140" />
+ id="rect4140"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccccccccccsssscssccssccs" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_warning.svg b/tools/editor/icons/source/icon_warning.svg
index ee89f3ec99..4d39141a58 100644
--- a/tools/editor/icons/source/icon_warning.svg
+++ b/tools/editor/icons/source/icon_warning.svg
@@ -28,9 +28,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="22.627416"
- inkscape:cx="1.5203658"
- inkscape:cy="5.6414917"
+ inkscape:zoom="45.254832"
+ inkscape:cx="2.2320862"
+ inkscape:cy="6.41947"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -60,7 +60,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -70,11 +70,12 @@
id="layer1"
transform="translate(0,-1044.3622)">
<rect
- style="opacity:1;fill:#ffd684;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4154"
+ style="opacity:1;fill:#ffd684;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect4142"
width="8"
height="8"
- x="2.220446e-16"
- y="1044.3622" />
+ x="0"
+ y="1044.3622"
+ ry="1" />
</g>
</svg>
diff --git a/tools/editor/io_plugins/editor_font_import_plugin.cpp b/tools/editor/io_plugins/editor_font_import_plugin.cpp
index ada6000d82..0deb5cbbfa 100644
--- a/tools/editor/io_plugins/editor_font_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_font_import_plugin.cpp
@@ -1473,7 +1473,7 @@ Ref<BitmapFont> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMe
sum+=w2[ofs_l];
}
- wa[ofs]=Math::pow(float(sum/(r*2+1))/255.0,tr)*255.0;
+ wa[ofs]=Math::pow(float(sum/(r*2+1))/255.0f,tr)*255.0f;
}
}
diff --git a/tools/editor/io_plugins/editor_sample_import_plugin.cpp b/tools/editor/io_plugins/editor_sample_import_plugin.cpp
index ca873cab72..631291ec1b 100644
--- a/tools/editor/io_plugins/editor_sample_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_sample_import_plugin.cpp
@@ -541,7 +541,7 @@ Error EditorSampleImportPlugin::import(const String& p_path, const Ref<ResourceI
int first=0;
int last=(len*chans)-1;
bool found=false;
- float limit = Math::db2linear(-30);
+ float limit = Math::db2linear((float)-30);
for(int i=0;i<data.size();i++) {
float amp = Math::abs(data[i]);
diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp
index 9dbd2513a0..bec7956b8c 100644
--- a/tools/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp
@@ -2354,7 +2354,7 @@ void CanvasItemEditor::_find_canvas_items_span(Node *p_node, Rect2& r_rect, cons
- if (c) {
+ if (c && c->is_visible_in_tree()) {
Rect2 rect = c->get_item_rect();
Transform2D xform = p_xform * c->get_transform();
diff --git a/tools/editor/plugins/multimesh_editor_plugin.cpp b/tools/editor/plugins/multimesh_editor_plugin.cpp
index 80765be6c0..6259ddf473 100644
--- a/tools/editor/plugins/multimesh_editor_plugin.cpp
+++ b/tools/editor/plugins/multimesh_editor_plugin.cpp
@@ -216,7 +216,7 @@ void MultiMeshEditor::_populate() {
for(int i=0;i<instance_count;i++) {
- float areapos = Math::random(0,area_accum);
+ float areapos = Math::random(0.0f,area_accum);
Map<float,int>::Element *E = triangle_area_map.find_closest(areapos);
ERR_FAIL_COND(!E)
diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp
index 4b67df3a98..9f8367ff1d 100644
--- a/tools/editor/plugins/spatial_editor_plugin.cpp
+++ b/tools/editor/plugins/spatial_editor_plugin.cpp
@@ -3437,7 +3437,7 @@ void SpatialEditor::_instance_scene() {
#if 0
EditorNode *en = get_scene()->get_root_node()->cast_to<EditorNode>();
ERR_FAIL_COND(!en);
- String path = en->get_scenes_dock()->get_selected_path();
+ String path = en->get_filesystem_dock()->get_selected_path();
if (path=="") {
set_message(TTR("No scene selected to instance!"));
return;
diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp
index fc1fe43cef..e5dce0524f 100644
--- a/tools/editor/property_editor.cpp
+++ b/tools/editor/property_editor.cpp
@@ -1503,12 +1503,12 @@ void CustomPropertyEditor::_drag_easing(const InputEvent& p_ev) {
bool sg = val < 0;
val = Math::absf(val);
- val = Math::log(val)/Math::log(2);
+ val = Math::log(val)/Math::log((float)2.0);
//logspace
val+=rel*0.05;
//
- val = Math::pow(2,val);
+ val = Math::pow(2.0f,val);
if (sg)
val=-val;
@@ -2431,7 +2431,7 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String& p
} break;
case Variant::COLOR: {
- p_item->set_custom_bg_color(1,obj->get(p_name));
+ tree->update();
//p_item->set_text(1,obj->get(p_name));
} break;
@@ -3708,7 +3708,7 @@ void PropertyEditor::update_tree() {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
item->set_editable( 1, !read_only );
//item->set_text(1,obj->get(p.name));
- item->set_custom_bg_color(1,obj->get(p.name));
+ item->set_custom_draw(1,this,"_draw_transparency");
if (show_type_icons)
item->set_icon( 0,get_icon("Color","EditorIcons") );
@@ -3731,7 +3731,7 @@ void PropertyEditor::update_tree() {
item->set_cell_mode(1, TreeItem::CELL_MODE_STRING);
item->set_editable( 1, !read_only );
item->set_text(1,obj->get(p.name));
- item->add_button(1, get_icon("Collapse", "EditorIcons"));
+ item->add_button(1, get_icon("CopyNodePath", "EditorIcons"));
} break;
case Variant::OBJECT: {
@@ -3856,6 +3856,25 @@ void PropertyEditor::update_tree() {
}
}
+void PropertyEditor::_draw_transparency(Object *t, const Rect2& p_rect) {
+
+ TreeItem *ti=t->cast_to<TreeItem>();
+ if (!ti)
+ return;
+
+ Color color=obj->get(ti->get_metadata(1));
+ Ref<Texture> arrow=tree->get_icon("select_arrow");
+
+ // make a little space between consecutive color fields
+ Rect2 area=p_rect;
+ area.pos.y+=1;
+ area.size.height-=2;
+ area.size.width-=arrow->get_size().width+5;
+ tree->draw_texture_rect(get_icon("Transparent", "EditorIcons"), area, true);
+ tree->draw_rect(area, color);
+
+}
+
void PropertyEditor::_item_selected() {
@@ -4366,6 +4385,7 @@ void PropertyEditor::_bind_methods() {
ClassDB::bind_method( "update_tree",&PropertyEditor::update_tree);
ClassDB::bind_method( "_resource_preview_done",&PropertyEditor::_resource_preview_done);
ClassDB::bind_method( "refresh",&PropertyEditor::refresh);
+ ClassDB::bind_method( "_draw_transparency",&PropertyEditor::_draw_transparency);
ClassDB::bind_method(_MD("get_drag_data_fw"), &PropertyEditor::get_drag_data_fw);
ClassDB::bind_method(_MD("can_drop_data_fw"), &PropertyEditor::can_drop_data_fw);
diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h
index 900d06497f..3f8d071a01 100644
--- a/tools/editor/property_editor.h
+++ b/tools/editor/property_editor.h
@@ -245,6 +245,7 @@ friend class ProjectExportDialog;
void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
void _resource_preview_done(const String& p_path,const Ref<Texture>& p_preview,Variant p_ud);
+ void _draw_transparency(Object *t, const Rect2& p_rect);
UndoRedo *undo_redo;
protected:
diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp
index 6247a9b578..b3e4c8ed70 100644
--- a/tools/editor/scene_tree_dock.cpp
+++ b/tools/editor/scene_tree_dock.cpp
@@ -711,7 +711,7 @@ void SceneTreeDock::_notification(int p_what) {
button_add->set_icon(get_icon("Add","EditorIcons"));
button_instance->set_icon(get_icon("Instance","EditorIcons"));
button_create_script->set_icon(get_icon("ScriptCreate","EditorIcons"));
- button_clear_script->set_icon(get_icon("Remove", "EditorIcons"));
+ button_clear_script->set_icon(get_icon("ScriptRemove", "EditorIcons"));
filter_icon->set_texture(get_icon("Zoom","EditorIcons"));
@@ -1808,7 +1808,7 @@ void SceneTreeDock::_tree_rmb(const Vector2& p_menu_pos) {
//menu->add_icon_item(get_icon("Connect","EditorIcons"),TTR("Edit Connections"),TOOL_CONNECT);
menu->add_separator();
menu->add_icon_shortcut(get_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT);
- menu->add_icon_shortcut(get_icon("Remove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT);
+ menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT);
menu->add_separator();
}
@@ -1820,9 +1820,9 @@ void SceneTreeDock::_tree_rmb(const Vector2& p_menu_pos) {
if (selection.size()==1) {
menu->add_separator();
menu->add_icon_shortcut(get_icon("Blend","EditorIcons"),ED_GET_SHORTCUT("scene_tree/merge_from_scene"), TOOL_MERGE_FROM_SCENE);
- menu->add_icon_shortcut(get_icon("Save","EditorIcons"),ED_GET_SHORTCUT("scene_tree/save_branch_as_scene"), TOOL_NEW_SCENE_FROM);
+ menu->add_icon_shortcut(get_icon("CreateNewSceneFrom","EditorIcons"),ED_GET_SHORTCUT("scene_tree/save_branch_as_scene"), TOOL_NEW_SCENE_FROM);
menu->add_separator();
- menu->add_icon_shortcut(get_icon("Duplicate","EditorIcons"), ED_GET_SHORTCUT("scene_tree/copy_node_path"), TOOL_COPY_NODE_PATH);
+ menu->add_icon_shortcut(get_icon("CopyNodePath","EditorIcons"), ED_GET_SHORTCUT("scene_tree/copy_node_path"), TOOL_COPY_NODE_PATH);
}
menu->add_separator();
menu->add_icon_shortcut(get_icon("Remove","EditorIcons"), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), KEY_DELETE), TOOL_ERASE);
diff --git a/tools/editor/scene_tree_editor.cpp b/tools/editor/scene_tree_editor.cpp
index 77640b9c80..dd1fdeb400 100644
--- a/tools/editor/scene_tree_editor.cpp
+++ b/tools/editor/scene_tree_editor.cpp
@@ -208,14 +208,15 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item,int p_column,int p_id)
if (n->is_class("Spatial")) {
- bool v = !bool(n->call("is_hidden"));
+ bool v = bool(n->call("is_visible"));
undo_redo->create_action(TTR("Toggle Spatial Visible"));
- undo_redo->add_do_method(n,"_set_visible_",!v);
- undo_redo->add_undo_method(n,"_set_visible_",v);
+ undo_redo->add_do_method(n,"set_visible",!v);
+ undo_redo->add_undo_method(n,"set_visible",v);
undo_redo->commit_action();
+
} else if (n->is_class("CanvasItem")) {
- bool v = !bool(n->call("is_hidden"));
+ bool v = bool(n->call("is_visible"));
undo_redo->create_action(TTR("Toggle CanvasItem Visible"));
undo_redo->add_do_method(n,v?"hide":"show");
undo_redo->add_undo_method(n,v?"show":"hide");
@@ -393,11 +394,11 @@ bool SceneTreeEditor::_add_nodes(Node *p_node,TreeItem *p_parent) {
if (is_grouped)
item->add_button(0,get_icon("Group", "EditorIcons"), BUTTON_GROUP);
- bool h = p_node->call("is_hidden");
- if (h)
- item->add_button(0,get_icon("Hidden","EditorIcons"),BUTTON_VISIBILITY);
- else
+ bool v = p_node->call("is_visible");
+ if (v)
item->add_button(0,get_icon("Visible","EditorIcons"),BUTTON_VISIBILITY);
+ else
+ item->add_button(0,get_icon("Hidden","EditorIcons"),BUTTON_VISIBILITY);
if (!p_node->is_connected("visibility_changed",this,"_node_visibility_changed"))
p_node->connect("visibility_changed",this,"_node_visibility_changed",varray(p_node));
@@ -405,11 +406,11 @@ bool SceneTreeEditor::_add_nodes(Node *p_node,TreeItem *p_parent) {
_update_visibility_color(p_node, item);
} else if (p_node->is_class("Spatial")) {
- bool h = p_node->call("is_hidden");
- if (h)
- item->add_button(0,get_icon("Hidden","EditorIcons"),BUTTON_VISIBILITY);
- else
+ bool v = p_node->call("is_visible");
+ if (v)
item->add_button(0,get_icon("Visible","EditorIcons"),BUTTON_VISIBILITY);
+ else
+ item->add_button(0,get_icon("Hidden","EditorIcons"),BUTTON_VISIBILITY);
if (!p_node->is_connected("visibility_changed",this,"_node_visibility_changed"))
p_node->connect("visibility_changed",this,"_node_visibility_changed",varray(p_node));
@@ -470,15 +471,16 @@ void SceneTreeEditor::_node_visibility_changed(Node *p_node) {
bool visible=false;
if (p_node->is_class("CanvasItem")) {
- visible = !p_node->call("is_hidden");
+ visible = p_node->call("is_visible");
+ CanvasItemEditor::get_singleton()->get_viewport_control()->update();
} else if (p_node->is_class("Spatial")) {
- visible = !p_node->call("is_hidden");
+ visible = p_node->call("is_visible");
}
- if (!visible)
- item->set_button(0,idx,get_icon("Hidden","EditorIcons"));
- else
+ if (visible)
item->set_button(0,idx,get_icon("Visible","EditorIcons"));
+ else
+ item->set_button(0,idx,get_icon("Hidden","EditorIcons"));
_update_visibility_color(p_node, item);
}
diff --git a/tools/editor/script_editor_debugger.cpp b/tools/editor/script_editor_debugger.cpp
index 42ab234d4b..d5cca06820 100644
--- a/tools/editor/script_editor_debugger.cpp
+++ b/tools/editor/script_editor_debugger.cpp
@@ -826,7 +826,7 @@ void ScriptEditorDebugger::_performance_draw() {
Ref<StyleBox> graph_sb = get_stylebox("normal","TextEdit");
Ref<Font> graph_font = get_font("font","TextEdit");
- int cols = Math::ceil(Math::sqrt(which.size()));
+ int cols = Math::ceil(Math::sqrt((float)which.size()));
int rows = (which.size()+1)/cols;
if (which.size()==1)
rows=1;
diff --git a/tools/editor/spatial_editor_gizmos.cpp b/tools/editor/spatial_editor_gizmos.cpp
index adbac4b12b..c670245282 100644
--- a/tools/editor/spatial_editor_gizmos.cpp
+++ b/tools/editor/spatial_editor_gizmos.cpp
@@ -839,8 +839,8 @@ void LightSpatialGizmo::redraw() {
for(int i=0;i<=360;i++) {
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+1);
+ float ra=Math::deg2rad((float)i);
+ float rb=Math::deg2rad((float)i+1);
Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
@@ -881,8 +881,8 @@ void LightSpatialGizmo::redraw() {
for(int i=0;i<360;i++) {
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+1);
+ float ra=Math::deg2rad((float)i);
+ float rb=Math::deg2rad((float)i+1);
Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w;
Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w;
@@ -1519,8 +1519,8 @@ void VehicleWheelSpatialGizmo::redraw() {
const int skip=10;
for(int i=0;i<=360;i+=skip) {
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+skip);
+ float ra=Math::deg2rad((float)i);
+ float rb=Math::deg2rad((float)i+skip);
Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
@@ -1826,8 +1826,8 @@ void CollisionShapeSpatialGizmo::redraw(){
for(int i=0;i<=360;i++) {
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+1);
+ float ra=Math::deg2rad((float)i);
+ float rb=Math::deg2rad((float)i+1);
Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
@@ -1907,8 +1907,8 @@ void CollisionShapeSpatialGizmo::redraw(){
Vector3 d(0,0,height*0.5);
for(int i=0;i<360;i++) {
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+1);
+ float ra=Math::deg2rad((float)i);
+ float rb=Math::deg2rad((float)i+1);
Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*radius;
Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*radius;
@@ -2844,8 +2844,8 @@ void ConeTwistJointSpatialGizmo::redraw() {
//swing
for(int i=0;i<360;i+=10) {
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+10);
+ float ra=Math::deg2rad((float)i);
+ float rb=Math::deg2rad((float)i+10);
Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w;
Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w;
@@ -2876,8 +2876,8 @@ void ConeTwistJointSpatialGizmo::redraw() {
for(int i=0;i<int(ts);i+=5) {
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+5);
+ float ra=Math::deg2rad((float)i);
+ float rb=Math::deg2rad((float)i+5);
float c = i/720.0;
float cn = (i+5)/720.0;
Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w*c;