summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/SCsub3
-rw-r--r--servers/arvr/SCsub2
-rw-r--r--servers/arvr/arvr_interface.cpp16
-rw-r--r--servers/arvr/arvr_interface.h9
-rw-r--r--servers/arvr/arvr_positional_tracker.cpp21
-rw-r--r--servers/arvr/arvr_positional_tracker.h13
-rw-r--r--servers/arvr_server.cpp16
-rw-r--r--servers/arvr_server.h6
-rw-r--r--servers/audio/SCsub2
-rw-r--r--servers/audio/audio_driver_dummy.cpp4
-rw-r--r--servers/audio/audio_driver_dummy.h4
-rw-r--r--servers/audio/audio_effect.cpp4
-rw-r--r--servers/audio/audio_effect.h9
-rw-r--r--servers/audio/audio_filter_sw.cpp6
-rw-r--r--servers/audio/audio_filter_sw.h4
-rw-r--r--servers/audio/audio_rb_resampler.cpp33
-rw-r--r--servers/audio/audio_rb_resampler.h4
-rw-r--r--servers/audio/audio_stream.cpp76
-rw-r--r--servers/audio/audio_stream.h22
-rw-r--r--servers/audio/effects/SCsub2
-rw-r--r--servers/audio/effects/audio_effect_amplify.cpp4
-rw-r--r--servers/audio/effects/audio_effect_amplify.h8
-rw-r--r--servers/audio/effects/audio_effect_chorus.cpp12
-rw-r--r--servers/audio/effects/audio_effect_chorus.h8
-rw-r--r--servers/audio/effects/audio_effect_compressor.cpp4
-rw-r--r--servers/audio/effects/audio_effect_compressor.h8
-rw-r--r--servers/audio/effects/audio_effect_delay.cpp4
-rw-r--r--servers/audio/effects/audio_effect_delay.h8
-rw-r--r--servers/audio/effects/audio_effect_distortion.cpp6
-rw-r--r--servers/audio/effects/audio_effect_distortion.h9
-rw-r--r--servers/audio/effects/audio_effect_eq.cpp4
-rw-r--r--servers/audio/effects/audio_effect_eq.h17
-rw-r--r--servers/audio/effects/audio_effect_filter.cpp6
-rw-r--r--servers/audio/effects/audio_effect_filter.h40
-rw-r--r--servers/audio/effects/audio_effect_limiter.cpp4
-rw-r--r--servers/audio/effects/audio_effect_limiter.h8
-rw-r--r--servers/audio/effects/audio_effect_panner.cpp4
-rw-r--r--servers/audio/effects/audio_effect_panner.h8
-rw-r--r--servers/audio/effects/audio_effect_phaser.cpp4
-rw-r--r--servers/audio/effects/audio_effect_phaser.h8
-rw-r--r--servers/audio/effects/audio_effect_pitch_shift.cpp48
-rw-r--r--servers/audio/effects/audio_effect_pitch_shift.h30
-rw-r--r--servers/audio/effects/audio_effect_record.cpp78
-rw-r--r--servers/audio/effects/audio_effect_record.h19
-rw-r--r--servers/audio/effects/audio_effect_reverb.cpp4
-rw-r--r--servers/audio/effects/audio_effect_reverb.h8
-rw-r--r--servers/audio/effects/audio_effect_spectrum_analyzer.cpp287
-rw-r--r--servers/audio/effects/audio_effect_spectrum_analyzer.h107
-rw-r--r--servers/audio/effects/audio_effect_stereo_enhance.cpp4
-rw-r--r--servers/audio/effects/audio_effect_stereo_enhance.h8
-rw-r--r--servers/audio/effects/audio_stream_generator.cpp212
-rw-r--r--servers/audio/effects/audio_stream_generator.h96
-rw-r--r--servers/audio/effects/eq.cpp4
-rw-r--r--servers/audio/effects/eq.h4
-rw-r--r--servers/audio/effects/reverb.cpp28
-rw-r--r--servers/audio/effects/reverb.h4
-rw-r--r--servers/audio/reverb_sw.cpp29
-rw-r--r--servers/audio/reverb_sw.h6
-rw-r--r--servers/audio/voice_rb_sw.h7
-rw-r--r--servers/audio_server.cpp196
-rw-r--r--servers/audio_server.h60
-rw-r--r--servers/camera/SCsub7
-rw-r--r--servers/camera/camera_feed.cpp266
-rw-r--r--servers/camera/camera_feed.h115
-rw-r--r--servers/camera_server.cpp169
-rw-r--r--servers/camera_server.h96
-rw-r--r--servers/physics/SCsub2
-rw-r--r--servers/physics/area_pair_sw.cpp8
-rw-r--r--servers/physics/area_pair_sw.h4
-rw-r--r--servers/physics/area_sw.cpp6
-rw-r--r--servers/physics/area_sw.h4
-rw-r--r--servers/physics/body_pair_sw.cpp4
-rw-r--r--servers/physics/body_pair_sw.h5
-rw-r--r--servers/physics/body_sw.cpp27
-rw-r--r--servers/physics/body_sw.h4
-rw-r--r--servers/physics/broad_phase_basic.cpp4
-rw-r--r--servers/physics/broad_phase_basic.h4
-rw-r--r--servers/physics/broad_phase_octree.cpp6
-rw-r--r--servers/physics/broad_phase_octree.h4
-rw-r--r--servers/physics/broad_phase_sw.cpp4
-rw-r--r--servers/physics/broad_phase_sw.h4
-rw-r--r--servers/physics/collision_object_sw.cpp14
-rw-r--r--servers/physics/collision_object_sw.h25
-rw-r--r--servers/physics/collision_solver_sat.cpp31
-rw-r--r--servers/physics/collision_solver_sat.h4
-rw-r--r--servers/physics/collision_solver_sw.cpp9
-rw-r--r--servers/physics/collision_solver_sw.h4
-rw-r--r--servers/physics/constraint_sw.h4
-rw-r--r--servers/physics/gjk_epa.cpp9
-rw-r--r--servers/physics/gjk_epa.h9
-rw-r--r--servers/physics/joints/SCsub2
-rw-r--r--servers/physics/joints/cone_twist_joint_sw.cpp16
-rw-r--r--servers/physics/joints/cone_twist_joint_sw.h4
-rw-r--r--servers/physics/joints/generic_6dof_joint_sw.cpp79
-rw-r--r--servers/physics/joints/generic_6dof_joint_sw.h10
-rw-r--r--servers/physics/joints/hinge_joint_sw.cpp15
-rw-r--r--servers/physics/joints/hinge_joint_sw.h4
-rw-r--r--servers/physics/joints/jacobian_entry_sw.h4
-rw-r--r--servers/physics/joints/pin_joint_sw.cpp4
-rw-r--r--servers/physics/joints/pin_joint_sw.h4
-rw-r--r--servers/physics/joints/slider_joint_sw.cpp8
-rw-r--r--servers/physics/joints/slider_joint_sw.h4
-rw-r--r--servers/physics/joints_sw.h4
-rw-r--r--servers/physics/physics_server_sw.cpp51
-rw-r--r--servers/physics/physics_server_sw.h19
-rw-r--r--servers/physics/shape_sw.cpp22
-rw-r--r--servers/physics/shape_sw.h4
-rw-r--r--servers/physics/space_sw.cpp84
-rw-r--r--servers/physics/space_sw.h5
-rw-r--r--servers/physics/step_sw.cpp4
-rw-r--r--servers/physics/step_sw.h4
-rw-r--r--servers/physics_2d/area_2d_sw.cpp4
-rw-r--r--servers/physics_2d/area_2d_sw.h4
-rw-r--r--servers/physics_2d/area_pair_2d_sw.cpp8
-rw-r--r--servers/physics_2d/area_pair_2d_sw.h4
-rw-r--r--servers/physics_2d/body_2d_sw.cpp76
-rw-r--r--servers/physics_2d/body_2d_sw.h5
-rw-r--r--servers/physics_2d/body_pair_2d_sw.cpp10
-rw-r--r--servers/physics_2d/body_pair_2d_sw.h4
-rw-r--r--servers/physics_2d/broad_phase_2d_basic.cpp4
-rw-r--r--servers/physics_2d/broad_phase_2d_basic.h4
-rw-r--r--servers/physics_2d/broad_phase_2d_hash_grid.cpp10
-rw-r--r--servers/physics_2d/broad_phase_2d_hash_grid.h4
-rw-r--r--servers/physics_2d/broad_phase_2d_sw.cpp4
-rw-r--r--servers/physics_2d/broad_phase_2d_sw.h4
-rw-r--r--servers/physics_2d/collision_object_2d_sw.cpp55
-rw-r--r--servers/physics_2d/collision_object_2d_sw.h42
-rw-r--r--servers/physics_2d/collision_solver_2d_sat.cpp31
-rw-r--r--servers/physics_2d/collision_solver_2d_sat.h4
-rw-r--r--servers/physics_2d/collision_solver_2d_sw.cpp6
-rw-r--r--servers/physics_2d/collision_solver_2d_sw.h4
-rw-r--r--servers/physics_2d/constraint_2d_sw.h4
-rw-r--r--servers/physics_2d/joints_2d_sw.cpp10
-rw-r--r--servers/physics_2d/joints_2d_sw.h4
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp127
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h28
-rw-r--r--servers/physics_2d/physics_2d_server_wrap_mt.cpp6
-rw-r--r--servers/physics_2d/physics_2d_server_wrap_mt.h26
-rw-r--r--servers/physics_2d/shape_2d_sw.cpp54
-rw-r--r--servers/physics_2d/shape_2d_sw.h4
-rw-r--r--servers/physics_2d/space_2d_sw.cpp296
-rw-r--r--servers/physics_2d/space_2d_sw.h8
-rw-r--r--servers/physics_2d/step_2d_sw.cpp6
-rw-r--r--servers/physics_2d/step_2d_sw.h4
-rw-r--r--servers/physics_2d_server.cpp41
-rw-r--r--servers/physics_2d_server.h44
-rw-r--r--servers/physics_server.cpp19
-rw-r--r--servers/physics_server.h38
-rw-r--r--servers/register_server_types.cpp44
-rw-r--r--servers/register_server_types.h4
-rw-r--r--servers/server_wrap_mt_common.h6
-rw-r--r--servers/visual/SCsub2
-rw-r--r--servers/visual/default_mouse_cursor.xpm23
-rw-r--r--servers/visual/rasterizer.cpp4
-rw-r--r--servers/visual/rasterizer.h50
-rw-r--r--servers/visual/shader_language.cpp2592
-rw-r--r--servers/visual/shader_language.h242
-rw-r--r--servers/visual/shader_types.cpp19
-rw-r--r--servers/visual/shader_types.h4
-rw-r--r--servers/visual/visual_server_canvas.cpp175
-rw-r--r--servers/visual/visual_server_canvas.h36
-rw-r--r--servers/visual/visual_server_globals.cpp (renamed from servers/visual/visual_server_global.cpp)8
-rw-r--r--servers/visual/visual_server_globals.h (renamed from servers/visual/visual_server_global.h)12
-rw-r--r--servers/visual/visual_server_light_baker.cpp4
-rw-r--r--servers/visual/visual_server_light_baker.h4
-rw-r--r--servers/visual/visual_server_raster.cpp23
-rw-r--r--servers/visual/visual_server_raster.h34
-rw-r--r--servers/visual/visual_server_scene.cpp374
-rw-r--r--servers/visual/visual_server_scene.h38
-rw-r--r--servers/visual/visual_server_viewport.cpp167
-rw-r--r--servers/visual/visual_server_viewport.h31
-rw-r--r--servers/visual/visual_server_wrap_mt.cpp4
-rw-r--r--servers/visual/visual_server_wrap_mt.h32
-rw-r--r--servers/visual_server.cpp71
-rw-r--r--servers/visual_server.h38
175 files changed, 5674 insertions, 2245 deletions
diff --git a/servers/SCsub b/servers/SCsub
index 252a18ffd3..34ba70b8cb 100644
--- a/servers/SCsub
+++ b/servers/SCsub
@@ -5,9 +5,8 @@ Import('env')
env.servers_sources = []
env.add_source_files(env.servers_sources, "*.cpp")
-Export('env')
-
SConscript('arvr/SCsub')
+SConscript('camera/SCsub')
SConscript('physics/SCsub')
SConscript('physics_2d/SCsub')
SConscript('visual/SCsub')
diff --git a/servers/arvr/SCsub b/servers/arvr/SCsub
index ccc76e823f..d730144861 100644
--- a/servers/arvr/SCsub
+++ b/servers/arvr/SCsub
@@ -3,5 +3,3 @@
Import('env')
env.add_source_files(env.servers_sources, "*.cpp")
-
-Export('env')
diff --git a/servers/arvr/arvr_interface.cpp b/servers/arvr/arvr_interface.cpp
index 29478ee994..e1b7611354 100644
--- a/servers/arvr/arvr_interface.cpp
+++ b/servers/arvr/arvr_interface.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -56,6 +56,7 @@ void ARVRInterface::_bind_methods() {
// but we do have properties specific to AR....
ClassDB::bind_method(D_METHOD("get_anchor_detection_is_enabled"), &ARVRInterface::get_anchor_detection_is_enabled);
ClassDB::bind_method(D_METHOD("set_anchor_detection_is_enabled", "enable"), &ARVRInterface::set_anchor_detection_is_enabled);
+ ClassDB::bind_method(D_METHOD("get_camera_feed_id"), &ARVRInterface::get_camera_feed_id);
ADD_GROUP("AR", "ar_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ar_is_anchor_detection_enabled"), "set_anchor_detection_is_enabled", "get_anchor_detection_is_enabled");
@@ -123,6 +124,11 @@ ARVRInterface::ARVRInterface() {
ARVRInterface::~ARVRInterface(){};
+// optional render to external texture which enhances performance on those platforms that require us to submit our end result into special textures.
+unsigned int ARVRInterface::get_external_texture_for_eye(ARVRInterface::Eyes p_eye) {
+ return 0;
+};
+
/** these will only be implemented on AR interfaces, so we want dummies for VR **/
bool ARVRInterface::get_anchor_detection_is_enabled() const {
return false;
@@ -131,3 +137,9 @@ bool ARVRInterface::get_anchor_detection_is_enabled() const {
void ARVRInterface::set_anchor_detection_is_enabled(bool p_enable){
// don't do anything here, this needs to be implemented on AR interface to enable/disable things like plane detection etc.
};
+
+int ARVRInterface::get_camera_feed_id() {
+ // don't do anything here, this needs to be implemented on AR interface to enable/disable things like plane detection etc.
+
+ return 0;
+};
diff --git a/servers/arvr/arvr_interface.h b/servers/arvr/arvr_interface.h
index b26ee6cb1b..85556b2757 100644
--- a/servers/arvr/arvr_interface.h
+++ b/servers/arvr/arvr_interface.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -39,7 +39,7 @@
/**
@author Bastiaan Olij <mux213@gmail.com>
- The ARVR interface is a template class ontop of which we build interface to differt AR, VR and tracking SDKs.
+ The ARVR interface is a template class ontop of which we build interface to different AR, VR and tracking SDKs.
The idea is that we subclass this class, implement the logic, and then instantiate a singleton of each interface
when Godot starts. These instances do not initialize themselves but register themselves with the AR/VR server.
@@ -101,6 +101,7 @@ public:
/** specific to AR **/
virtual bool get_anchor_detection_is_enabled() const;
virtual void set_anchor_detection_is_enabled(bool p_enable);
+ virtual int get_camera_feed_id();
/** rendering and internal **/
@@ -108,9 +109,11 @@ public:
virtual bool is_stereo() = 0; /* returns true if this interface requires stereo rendering (for VR HMDs) or mono rendering (for mobile AR) */
virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform) = 0; /* get each eyes camera transform, also implement EYE_MONO */
virtual CameraMatrix get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) = 0; /* get each eyes projection matrix */
+ virtual unsigned int get_external_texture_for_eye(ARVRInterface::Eyes p_eye); /* if applicable return external texture to render to */
virtual void commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) = 0; /* output the left or right eye */
virtual void process() = 0;
+ virtual void notification(int p_what) = 0;
ARVRInterface();
~ARVRInterface();
diff --git a/servers/arvr/arvr_positional_tracker.cpp b/servers/arvr/arvr_positional_tracker.cpp
index c12d0bbc15..cbda3556c5 100644
--- a/servers/arvr/arvr_positional_tracker.cpp
+++ b/servers/arvr/arvr_positional_tracker.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -46,6 +46,7 @@ void ARVRPositionalTracker::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_position"), &ARVRPositionalTracker::get_position);
ClassDB::bind_method(D_METHOD("get_hand"), &ARVRPositionalTracker::get_hand);
ClassDB::bind_method(D_METHOD("get_transform", "adjust_by_reference_frame"), &ARVRPositionalTracker::get_transform);
+ ClassDB::bind_method(D_METHOD("get_mesh"), &ARVRPositionalTracker::get_mesh);
// these functions we don't want to expose to normal users but do need to be callable from GDNative
ClassDB::bind_method(D_METHOD("_set_type", "type"), &ARVRPositionalTracker::set_type);
@@ -53,7 +54,7 @@ void ARVRPositionalTracker::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_joy_id", "joy_id"), &ARVRPositionalTracker::set_joy_id);
ClassDB::bind_method(D_METHOD("_set_orientation", "orientation"), &ARVRPositionalTracker::set_orientation);
ClassDB::bind_method(D_METHOD("_set_rw_position", "rw_position"), &ARVRPositionalTracker::set_rw_position);
-
+ ClassDB::bind_method(D_METHOD("_set_mesh", "mesh"), &ARVRPositionalTracker::set_mesh);
ClassDB::bind_method(D_METHOD("get_rumble"), &ARVRPositionalTracker::get_rumble);
ClassDB::bind_method(D_METHOD("set_rumble", "rumble"), &ARVRPositionalTracker::set_rumble);
@@ -78,7 +79,7 @@ ARVRServer::TrackerType ARVRPositionalTracker::get_type() const {
return type;
};
-void ARVRPositionalTracker::set_name(const String p_name) {
+void ARVRPositionalTracker::set_name(const String &p_name) {
name = p_name;
};
@@ -154,6 +155,18 @@ Vector3 ARVRPositionalTracker::get_rw_position() const {
return rw_position;
};
+void ARVRPositionalTracker::set_mesh(const Ref<Mesh> &p_mesh) {
+ _THREAD_SAFE_METHOD_
+
+ mesh = p_mesh;
+};
+
+Ref<Mesh> ARVRPositionalTracker::get_mesh() const {
+ _THREAD_SAFE_METHOD_
+
+ return mesh;
+};
+
ARVRPositionalTracker::TrackerHand ARVRPositionalTracker::get_hand() const {
return hand;
};
diff --git a/servers/arvr/arvr_positional_tracker.h b/servers/arvr/arvr_positional_tracker.h
index 69b89f11d3..775579b089 100644
--- a/servers/arvr/arvr_positional_tracker.h
+++ b/servers/arvr/arvr_positional_tracker.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,6 +32,7 @@
#define ARVR_POSITIONAL_TRACKER_H
#include "core/os/thread_safe.h"
+#include "scene/resources/mesh.h"
#include "servers/arvr_server.h"
/**
@@ -40,9 +41,6 @@
The positional tracker object as an object that represents the position and orientation of a tracked object like a controller or headset.
An AR/VR Interface will registered the trackers it manages with our AR/VR server and update its position and orientation.
This is where potentially additional AR/VR interfaces may be active as there are AR/VR SDKs that solely deal with positional tracking.
-
- @TODO:
- - create subclass of spatial node that uses one of our positional trackers to automatically determine its position
*/
class ARVRPositionalTracker : public Object {
@@ -65,6 +63,7 @@ private:
Basis orientation; // our orientation
bool tracks_position; // do we track position?
Vector3 rw_position; // our position "in the real world, so without world_scale applied"
+ Ref<Mesh> mesh; // when available, a mesh that can be used to render this tracker
TrackerHand hand; // if known, the hand this tracker is held in
real_t rumble; // rumble strength, 0.0 is off, 1.0 is maximum, note that we only record here, arvr_interface is responsible for execution
@@ -74,7 +73,7 @@ protected:
public:
void set_type(ARVRServer::TrackerType p_type);
ARVRServer::TrackerType get_type() const;
- void set_name(const String p_name);
+ void set_name(const String &p_name);
StringName get_name() const;
int get_tracker_id() const;
void set_joy_id(int p_joy_id);
@@ -91,6 +90,8 @@ public:
void set_hand(const ARVRPositionalTracker::TrackerHand p_hand);
real_t get_rumble() const;
void set_rumble(real_t p_rumble);
+ void set_mesh(const Ref<Mesh> &p_mesh);
+ Ref<Mesh> get_mesh() const;
Transform get_transform(bool p_adjust_by_reference_frame) const;
diff --git a/servers/arvr_server.cpp b/servers/arvr_server.cpp
index 55f8ea8f5b..f7ce1d3c5d 100644
--- a/servers/arvr_server.cpp
+++ b/servers/arvr_server.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -87,11 +87,11 @@ real_t ARVRServer::get_world_scale() const {
};
void ARVRServer::set_world_scale(real_t p_world_scale) {
- if (world_scale < 0.01) {
- world_scale = 0.01;
- } else if (world_scale > 1000.0) {
- world_scale = 1000.0;
- };
+ if (p_world_scale < 0.01) {
+ p_world_scale = 0.01;
+ } else if (p_world_scale > 1000.0) {
+ p_world_scale = 1000.0;
+ }
world_scale = p_world_scale;
};
@@ -100,7 +100,7 @@ Transform ARVRServer::get_world_origin() const {
return world_origin;
};
-void ARVRServer::set_world_origin(const Transform p_world_origin) {
+void ARVRServer::set_world_origin(const Transform &p_world_origin) {
world_origin = p_world_origin;
};
diff --git a/servers/arvr_server.h b/servers/arvr_server.h
index a28b91c225..c0301ebaab 100644
--- a/servers/arvr_server.h
+++ b/servers/arvr_server.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -123,7 +123,7 @@ public:
and in the virtual world out of sync
*/
Transform get_world_origin() const;
- void set_world_origin(const Transform p_world_origin);
+ void set_world_origin(const Transform &p_world_origin);
/*
center_on_hmd calculates a new reference frame. This ensures the HMD is positioned to 0,0,0 facing 0,0,-1 (need to verify this direction)
diff --git a/servers/audio/SCsub b/servers/audio/SCsub
index afaffcfe93..3c18c18043 100644
--- a/servers/audio/SCsub
+++ b/servers/audio/SCsub
@@ -4,6 +4,4 @@ Import('env')
env.add_source_files(env.servers_sources, "*.cpp")
-Export('env')
-
SConscript("effects/SCsub")
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp
index 512ff5da7b..c151326e5e 100644
--- a/servers/audio/audio_driver_dummy.cpp
+++ b/servers/audio/audio_driver_dummy.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h
index ba4f69edf4..1a2839d9cb 100644
--- a/servers/audio/audio_driver_dummy.h
+++ b/servers/audio/audio_driver_dummy.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/audio_effect.cpp b/servers/audio/audio_effect.cpp
index b061dad259..dc73596952 100644
--- a/servers/audio/audio_effect.cpp
+++ b/servers/audio/audio_effect.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h
index bbabedbc30..8ae716db20 100644
--- a/servers/audio/audio_effect.h
+++ b/servers/audio/audio_effect.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,7 +35,7 @@
#include "core/resource.h"
class AudioEffectInstance : public Reference {
- GDCLASS(AudioEffectInstance, Reference)
+ GDCLASS(AudioEffectInstance, Reference);
public:
virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) = 0;
@@ -43,7 +43,8 @@ public:
};
class AudioEffect : public Resource {
- GDCLASS(AudioEffect, Resource)
+ GDCLASS(AudioEffect, Resource);
+
public:
virtual Ref<AudioEffectInstance> instance() = 0;
AudioEffect();
diff --git a/servers/audio/audio_filter_sw.cpp b/servers/audio/audio_filter_sw.cpp
index 551ca01109..ca033f6079 100644
--- a/servers/audio/audio_filter_sw.cpp
+++ b/servers/audio/audio_filter_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -154,7 +154,6 @@ void AudioFilterSW::prepare_coefficients(Coeffs *p_coeffs) {
double tmpq = Math::sqrt(Q);
if (tmpq <= 0)
tmpq = 0.001;
- alpha = sin_v / (2 * tmpq);
double beta = Math::sqrt(tmpgain) / tmpq;
a0 = (tmpgain + 1.0) + (tmpgain - 1.0) * cos_v + beta * sin_v;
@@ -169,7 +168,6 @@ void AudioFilterSW::prepare_coefficients(Coeffs *p_coeffs) {
double tmpq = Math::sqrt(Q);
if (tmpq <= 0)
tmpq = 0.001;
- alpha = sin_v / (2 * tmpq);
double beta = Math::sqrt(tmpgain) / tmpq;
a0 = (tmpgain + 1.0) - (tmpgain - 1.0) * cos_v + beta * sin_v;
diff --git a/servers/audio/audio_filter_sw.h b/servers/audio/audio_filter_sw.h
index d137ed8ff9..6b51a1d9ef 100644
--- a/servers/audio/audio_filter_sw.h
+++ b/servers/audio/audio_filter_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp
index 3ae897c299..ad5bcde382 100644
--- a/servers/audio/audio_rb_resampler.cpp
+++ b/servers/audio/audio_rb_resampler.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -79,42 +79,27 @@ uint32_t AudioRBResampler::_resample(AudioFrame *p_dest, int p_todo, int32_t p_i
p_dest[i] = AudioFrame(v0, v1);
}
- // For now, channels higher than stereo are almost ignored
+ // This will probably never be used, but added anyway
if (C == 4) {
float v0 = rb[(pos << 2) + 0];
float v1 = rb[(pos << 2) + 1];
- float v2 = rb[(pos << 2) + 2];
- float v3 = rb[(pos << 2) + 3];
float v0n = rb[(pos_next << 2) + 0];
float v1n = rb[(pos_next << 2) + 1];
- float v2n = rb[(pos_next << 2) + 2];
- float v3n = rb[(pos_next << 2) + 3];
-
v0 += (v0n - v0) * frac;
v1 += (v1n - v1) * frac;
- v2 += (v2n - v2) * frac;
- v3 += (v3n - v3) * frac;
p_dest[i] = AudioFrame(v0, v1);
}
if (C == 6) {
- // FIXME: Lot of unused assignments here, but it seems like intermediate calculations
- // should be done as for C == 2 (C == 4 also has some unused assignments).
float v0 = rb[(pos * 6) + 0];
float v1 = rb[(pos * 6) + 1];
- float v2 = rb[(pos * 6) + 2];
- float v3 = rb[(pos * 6) + 3];
- float v4 = rb[(pos * 6) + 4];
- float v5 = rb[(pos * 6) + 5];
float v0n = rb[(pos_next * 6) + 0];
float v1n = rb[(pos_next * 6) + 1];
- float v2n = rb[(pos_next * 6) + 2];
- float v3n = rb[(pos_next * 6) + 3];
- float v4n = rb[(pos_next * 6) + 4];
- float v5n = rb[(pos_next * 6) + 5];
+ v0 += (v0n - v0) * frac;
+ v1 += (v1n - v1) * frac;
p_dest[i] = AudioFrame(v0, v1);
}
}
@@ -153,7 +138,7 @@ bool AudioRBResampler::mix(AudioFrame *p_dest, int p_frames) {
}
// Fill zeros (silence) for the rest of frames
- for (uint32_t i = target_todo; i < p_frames; i++) {
+ for (int i = target_todo; i < p_frames; i++) {
p_dest[i] = AudioFrame(0, 0);
}
}
@@ -216,10 +201,8 @@ void AudioRBResampler::clear() {
return;
//should be stopped at this point but just in case
- if (rb) {
- memdelete_arr(rb);
- memdelete_arr(read_buf);
- }
+ memdelete_arr(rb);
+ memdelete_arr(read_buf);
rb = NULL;
offset = 0;
rb_read_pos = 0;
diff --git a/servers/audio/audio_rb_resampler.h b/servers/audio/audio_rb_resampler.h
index b21c480fc4..5b945cd953 100644
--- a/servers/audio/audio_rb_resampler.h
+++ b/servers/audio/audio_rb_resampler.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index 7de0695e8c..c651c177b5 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,6 +30,7 @@
#include "audio_stream.h"
#include "core/os/os.h"
+#include "core/project_settings.h"
//////////////////////////////
@@ -48,8 +49,9 @@ void AudioStreamPlaybackResampled::_begin_resample() {
void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
float target_rate = AudioServer::get_singleton()->get_mix_rate();
+ float global_rate_scale = AudioServer::get_singleton()->get_global_rate_scale();
- uint64_t mix_increment = uint64_t(((get_stream_sampling_rate() * p_rate_scale) / double(target_rate)) * double(FP_LEN));
+ uint64_t mix_increment = uint64_t(((get_stream_sampling_rate() * p_rate_scale) / double(target_rate * global_rate_scale)) * double(FP_LEN));
for (int i = 0; i < p_frames; i++) {
@@ -82,8 +84,8 @@ void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
_mix_internal(internal_buffer + 4, INTERNAL_BUFFER_LEN);
} else {
//fill with silence, not playing
- for (int i = 0; i < INTERNAL_BUFFER_LEN; ++i) {
- internal_buffer[i + 4] = AudioFrame(0, 0);
+ for (int j = 0; j < INTERNAL_BUFFER_LEN; ++j) {
+ internal_buffer[j + 4] = AudioFrame(0, 0);
}
}
mix_offset -= (INTERNAL_BUFFER_LEN << FP_BITS);
@@ -132,27 +134,31 @@ AudioStreamMicrophone::AudioStreamMicrophone() {
void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_frames) {
- AudioDriver::get_singleton()->lock();
+ AudioServer::get_singleton()->lock();
- Vector<int32_t> buf = AudioDriver::get_singleton()->get_input_buffer();
- unsigned int input_size = AudioDriver::get_singleton()->get_input_size();
+ PoolVector<int32_t> capture_buffer = AudioServer::get_singleton()->get_capture_buffer();
+ unsigned int capture_size = AudioServer::get_singleton()->get_capture_size();
+ int mix_rate = AudioServer::get_singleton()->get_mix_rate();
+ unsigned int playback_delay = MIN(((50 * mix_rate) / 1000) * 2, capture_buffer.size() >> 1);
+#ifdef DEBUG_ENABLED
+ unsigned int capture_position = AudioServer::get_singleton()->get_capture_position();
+#endif
- // p_frames is multiplied by two since an AudioFrame is stereo
- if ((p_frames + MICROPHONE_PLAYBACK_DELAY * 2) > input_size) {
+ if (playback_delay > capture_size) {
for (int i = 0; i < p_frames; i++) {
p_buffer[i] = AudioFrame(0.0f, 0.0f);
}
- input_ofs = 0;
+ capture_ofs = 0;
} else {
for (int i = 0; i < p_frames; i++) {
- if (input_size >= input_ofs) {
- float l = (buf[input_ofs++] >> 16) / 32768.f;
- if (input_ofs >= buf.size()) {
- input_ofs = 0;
+ if (capture_size > capture_ofs && (int)capture_ofs < capture_buffer.size()) {
+ float l = (capture_buffer[capture_ofs++] >> 16) / 32768.f;
+ if ((int)capture_ofs >= capture_buffer.size()) {
+ capture_ofs = 0;
}
- float r = (buf[input_ofs++] >> 16) / 32768.f;
- if (input_ofs >= buf.size()) {
- input_ofs = 0;
+ float r = (capture_buffer[capture_ofs++] >> 16) / 32768.f;
+ if ((int)capture_ofs >= capture_buffer.size()) {
+ capture_ofs = 0;
}
p_buffer[i] = AudioFrame(l, r);
@@ -162,7 +168,13 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr
}
}
- AudioDriver::get_singleton()->unlock();
+#ifdef DEBUG_ENABLED
+ if (capture_ofs > capture_position && (int)(capture_ofs - capture_position) < (p_frames * 2)) {
+ print_verbose(String(get_class_name()) + " buffer underrun: capture_position=" + itos(capture_position) + " capture_ofs=" + itos(capture_ofs) + " capture_size=" + itos(capture_size));
+ }
+#endif
+
+ AudioServer::get_singleton()->unlock();
}
void AudioStreamPlaybackMicrophone::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
@@ -174,17 +186,29 @@ float AudioStreamPlaybackMicrophone::get_stream_sampling_rate() {
}
void AudioStreamPlaybackMicrophone::start(float p_from_pos) {
- input_ofs = 0;
- AudioDriver::get_singleton()->capture_start();
+ if (active) {
+ return;
+ }
+
+ if (!GLOBAL_GET("audio/enable_audio_input")) {
+ WARN_PRINTS("Need to enable Project settings > Audio > Enable Audio Input option to use capturing.");
+ return;
+ }
+
+ capture_ofs = 0;
- active = true;
- _begin_resample();
+ if (AudioServer::get_singleton()->capture_start() == OK) {
+ active = true;
+ _begin_resample();
+ }
}
void AudioStreamPlaybackMicrophone::stop() {
- AudioDriver::get_singleton()->capture_stop();
- active = false;
+ if (active) {
+ AudioServer::get_singleton()->capture_stop();
+ active = false;
+ }
}
bool AudioStreamPlaybackMicrophone::is_playing() const {
@@ -200,7 +224,7 @@ float AudioStreamPlaybackMicrophone::get_playback_position() const {
}
void AudioStreamPlaybackMicrophone::seek(float p_time) {
- return; // Can't seek a microphone input
+ // Can't seek a microphone input
}
AudioStreamPlaybackMicrophone::~AudioStreamPlaybackMicrophone() {
diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h
index c7763890fc..4548f8f036 100644
--- a/servers/audio/audio_stream.h
+++ b/servers/audio/audio_stream.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -38,7 +38,7 @@
class AudioStreamPlayback : public Reference {
- GDCLASS(AudioStreamPlayback, Reference)
+ GDCLASS(AudioStreamPlayback, Reference);
public:
virtual void start(float p_from_pos = 0.0) = 0;
@@ -55,7 +55,7 @@ public:
class AudioStreamPlaybackResampled : public AudioStreamPlayback {
- GDCLASS(AudioStreamPlaybackResampled, AudioStreamPlayback)
+ GDCLASS(AudioStreamPlaybackResampled, AudioStreamPlayback);
enum {
FP_BITS = 16, //fixed point used for resampling
@@ -81,7 +81,7 @@ public:
class AudioStream : public Resource {
- GDCLASS(AudioStream, Resource)
+ GDCLASS(AudioStream, Resource);
OBJ_SAVE_TYPE(AudioStream) //children are all saved as AudioStream, so they can be exchanged
protected:
@@ -100,7 +100,7 @@ class AudioStreamPlaybackMicrophone;
class AudioStreamMicrophone : public AudioStream {
- GDCLASS(AudioStreamMicrophone, AudioStream)
+ GDCLASS(AudioStreamMicrophone, AudioStream);
friend class AudioStreamPlaybackMicrophone;
Set<AudioStreamPlaybackMicrophone *> playbacks;
@@ -119,13 +119,11 @@ public:
class AudioStreamPlaybackMicrophone : public AudioStreamPlaybackResampled {
- GDCLASS(AudioStreamPlaybackMicrophone, AudioStreamPlayback)
+ GDCLASS(AudioStreamPlaybackMicrophone, AudioStreamPlaybackResampled);
friend class AudioStreamMicrophone;
- const int MICROPHONE_PLAYBACK_DELAY = 256;
-
bool active;
- unsigned int input_ofs;
+ unsigned int capture_ofs;
Ref<AudioStreamMicrophone> microphone;
@@ -155,7 +153,7 @@ class AudioStreamPlaybackRandomPitch;
class AudioStreamRandomPitch : public AudioStream {
- GDCLASS(AudioStreamRandomPitch, AudioStream)
+ GDCLASS(AudioStreamRandomPitch, AudioStream);
friend class AudioStreamPlaybackRandomPitch;
Set<AudioStreamPlaybackRandomPitch *> playbacks;
@@ -182,7 +180,7 @@ public:
class AudioStreamPlaybackRandomPitch : public AudioStreamPlayback {
- GDCLASS(AudioStreamPlaybackRandomPitch, AudioStreamPlayback)
+ GDCLASS(AudioStreamPlaybackRandomPitch, AudioStreamPlayback);
friend class AudioStreamRandomPitch;
Ref<AudioStreamRandomPitch> random_pitch;
diff --git a/servers/audio/effects/SCsub b/servers/audio/effects/SCsub
index ccc76e823f..d730144861 100644
--- a/servers/audio/effects/SCsub
+++ b/servers/audio/effects/SCsub
@@ -3,5 +3,3 @@
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
index 9c8dfa8cb9..21a09297b2 100644
--- a/servers/audio/effects/audio_effect_amplify.cpp
+++ b/servers/audio/effects/audio_effect_amplify.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/effects/audio_effect_amplify.h b/servers/audio/effects/audio_effect_amplify.h
index 1096dc04df..4a98196d94 100644
--- a/servers/audio/effects/audio_effect_amplify.h
+++ b/servers/audio/effects/audio_effect_amplify.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,7 +36,7 @@
class AudioEffectAmplify;
class AudioEffectAmplifyInstance : public AudioEffectInstance {
- GDCLASS(AudioEffectAmplifyInstance, AudioEffectInstance)
+ GDCLASS(AudioEffectAmplifyInstance, AudioEffectInstance);
friend class AudioEffectAmplify;
Ref<AudioEffectAmplify> base;
@@ -47,7 +47,7 @@ public:
};
class AudioEffectAmplify : public AudioEffect {
- GDCLASS(AudioEffectAmplify, AudioEffect)
+ GDCLASS(AudioEffectAmplify, AudioEffect);
friend class AudioEffectAmplifyInstance;
float volume_db;
diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp
index 3c88d050f6..216a0a4aa6 100644
--- a/servers/audio/effects/audio_effect_chorus.cpp
+++ b/servers/audio/effects/audio_effect_chorus.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -333,28 +333,28 @@ void AudioEffectChorus::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/1/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 0);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/1/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 0);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/1/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 0);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/1/cutoff_hz", PROPERTY_HINT_RANGE, "1,16000,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 0);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/1/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 0);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/1/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 0);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/2/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 1);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/2/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 1);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/2/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 1);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/2/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 1);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/2/cutoff_hz", PROPERTY_HINT_RANGE, "1,16000,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 1);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/2/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 1);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/2/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 1);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/3/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 2);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/3/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 2);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/3/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 2);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/3/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 2);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/3/cutoff_hz", PROPERTY_HINT_RANGE, "1,16000,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 2);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/3/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 2);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/3/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 2);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/4/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 3);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/4/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 3);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/4/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 3);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/4/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 3);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/4/cutoff_hz", PROPERTY_HINT_RANGE, "1,16000,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 3);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/4/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 3);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "voice/4/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 3);
}
diff --git a/servers/audio/effects/audio_effect_chorus.h b/servers/audio/effects/audio_effect_chorus.h
index a4646df7d7..417cc0c035 100644
--- a/servers/audio/effects/audio_effect_chorus.h
+++ b/servers/audio/effects/audio_effect_chorus.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,7 +36,7 @@
class AudioEffectChorus;
class AudioEffectChorusInstance : public AudioEffectInstance {
- GDCLASS(AudioEffectChorusInstance, AudioEffectInstance)
+ GDCLASS(AudioEffectChorusInstance, AudioEffectInstance);
friend class AudioEffectChorus;
Ref<AudioEffectChorus> base;
@@ -54,7 +54,7 @@ public:
};
class AudioEffectChorus : public AudioEffect {
- GDCLASS(AudioEffectChorus, AudioEffect)
+ GDCLASS(AudioEffectChorus, AudioEffect);
friend class AudioEffectChorusInstance;
diff --git a/servers/audio/effects/audio_effect_compressor.cpp b/servers/audio/effects/audio_effect_compressor.cpp
index 8c70b51f8d..10f883d16c 100644
--- a/servers/audio/effects/audio_effect_compressor.cpp
+++ b/servers/audio/effects/audio_effect_compressor.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/effects/audio_effect_compressor.h b/servers/audio/effects/audio_effect_compressor.h
index ef11249415..0fe956f60b 100644
--- a/servers/audio/effects/audio_effect_compressor.h
+++ b/servers/audio/effects/audio_effect_compressor.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,7 +36,7 @@
class AudioEffectCompressor;
class AudioEffectCompressorInstance : public AudioEffectInstance {
- GDCLASS(AudioEffectCompressorInstance, AudioEffectInstance)
+ GDCLASS(AudioEffectCompressorInstance, AudioEffectInstance);
friend class AudioEffectCompressor;
Ref<AudioEffectCompressor> base;
@@ -49,7 +49,7 @@ public:
};
class AudioEffectCompressor : public AudioEffect {
- GDCLASS(AudioEffectCompressor, AudioEffect)
+ GDCLASS(AudioEffectCompressor, AudioEffect);
friend class AudioEffectCompressorInstance;
float threshold;
diff --git a/servers/audio/effects/audio_effect_delay.cpp b/servers/audio/effects/audio_effect_delay.cpp
index abc10ee096..8d34d46313 100644
--- a/servers/audio/effects/audio_effect_delay.cpp
+++ b/servers/audio/effects/audio_effect_delay.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/effects/audio_effect_delay.h b/servers/audio/effects/audio_effect_delay.h
index f173bd6dfc..ee778c70dc 100644
--- a/servers/audio/effects/audio_effect_delay.h
+++ b/servers/audio/effects/audio_effect_delay.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,7 +36,7 @@
class AudioEffectDelay;
class AudioEffectDelayInstance : public AudioEffectInstance {
- GDCLASS(AudioEffectDelayInstance, AudioEffectInstance)
+ GDCLASS(AudioEffectDelayInstance, AudioEffectInstance);
friend class AudioEffectDelay;
Ref<AudioEffectDelay> base;
@@ -58,7 +58,7 @@ public:
};
class AudioEffectDelay : public AudioEffect {
- GDCLASS(AudioEffectDelay, AudioEffect)
+ GDCLASS(AudioEffectDelay, AudioEffect);
friend class AudioEffectDelayInstance;
enum {
diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp
index 0422083363..278647c304 100644
--- a/servers/audio/effects/audio_effect_distortion.cpp
+++ b/servers/audio/effects/audio_effect_distortion.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -173,7 +173,7 @@ void AudioEffectDistortion::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Clip,ATan,LoFi,Overdrive,WaveShape"), "set_mode", "get_mode");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "pre_gain", PROPERTY_HINT_RANGE, "-60,60,0.01"), "set_pre_gain", "get_pre_gain");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "keep_hf_hz", PROPERTY_HINT_RANGE, "1,20000,1"), "set_keep_hf_hz", "get_keep_hf_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "keep_hf_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_keep_hf_hz", "get_keep_hf_hz");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "drive", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drive", "get_drive");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "post_gain", PROPERTY_HINT_RANGE, "-80,24,0.01"), "set_post_gain", "get_post_gain");
diff --git a/servers/audio/effects/audio_effect_distortion.h b/servers/audio/effects/audio_effect_distortion.h
index 8d9ff1c03f..0b5ad0ec9e 100644
--- a/servers/audio/effects/audio_effect_distortion.h
+++ b/servers/audio/effects/audio_effect_distortion.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,7 +36,7 @@
class AudioEffectDistortion;
class AudioEffectDistortionInstance : public AudioEffectInstance {
- GDCLASS(AudioEffectDistortionInstance, AudioEffectInstance)
+ GDCLASS(AudioEffectDistortionInstance, AudioEffectInstance);
friend class AudioEffectDistortion;
Ref<AudioEffectDistortion> base;
float h[2];
@@ -46,7 +46,8 @@ public:
};
class AudioEffectDistortion : public AudioEffect {
- GDCLASS(AudioEffectDistortion, AudioEffect)
+ GDCLASS(AudioEffectDistortion, AudioEffect);
+
public:
enum Mode {
MODE_CLIP,
diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp
index cf8f7d3e16..150f9db78f 100644
--- a/servers/audio/effects/audio_effect_eq.cpp
+++ b/servers/audio/effects/audio_effect_eq.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/effects/audio_effect_eq.h b/servers/audio/effects/audio_effect_eq.h
index c45fb753ea..dc75e566e7 100644
--- a/servers/audio/effects/audio_effect_eq.h
+++ b/servers/audio/effects/audio_effect_eq.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,7 +37,7 @@
class AudioEffectEQ;
class AudioEffectEQInstance : public AudioEffectInstance {
- GDCLASS(AudioEffectEQInstance, AudioEffectInstance)
+ GDCLASS(AudioEffectEQInstance, AudioEffectInstance);
friend class AudioEffectEQ;
Ref<AudioEffectEQ> base;
@@ -49,7 +49,7 @@ public:
};
class AudioEffectEQ : public AudioEffect {
- GDCLASS(AudioEffectEQ, AudioEffect)
+ GDCLASS(AudioEffectEQ, AudioEffect);
friend class AudioEffectEQInstance;
@@ -75,21 +75,24 @@ public:
};
class AudioEffectEQ6 : public AudioEffectEQ {
- GDCLASS(AudioEffectEQ6, AudioEffectEQ)
+ GDCLASS(AudioEffectEQ6, AudioEffectEQ);
+
public:
AudioEffectEQ6() :
AudioEffectEQ(EQ::PRESET_6_BANDS) {}
};
class AudioEffectEQ10 : public AudioEffectEQ {
- GDCLASS(AudioEffectEQ10, AudioEffectEQ)
+ GDCLASS(AudioEffectEQ10, AudioEffectEQ);
+
public:
AudioEffectEQ10() :
AudioEffectEQ(EQ::PRESET_10_BANDS) {}
};
class AudioEffectEQ21 : public AudioEffectEQ {
- GDCLASS(AudioEffectEQ21, AudioEffectEQ)
+ GDCLASS(AudioEffectEQ21, AudioEffectEQ);
+
public:
AudioEffectEQ21() :
AudioEffectEQ(EQ::PRESET_21_BANDS) {}
diff --git a/servers/audio/effects/audio_effect_filter.cpp b/servers/audio/effects/audio_effect_filter.cpp
index 75a43d2d41..3841f2b5a0 100644
--- a/servers/audio/effects/audio_effect_filter.cpp
+++ b/servers/audio/effects/audio_effect_filter.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -156,7 +156,7 @@ void AudioEffectFilter::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_db", "amount"), &AudioEffectFilter::set_db);
ClassDB::bind_method(D_METHOD("get_db"), &AudioEffectFilter::get_db);
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "cutoff_hz", PROPERTY_HINT_RANGE, "1,40000,0.1"), "set_cutoff", "get_cutoff");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_cutoff", "get_cutoff");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "resonance", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_resonance", "get_resonance");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "gain", PROPERTY_HINT_RANGE, "0,4,0.01"), "set_gain", "get_gain");
ADD_PROPERTY(PropertyInfo(Variant::INT, "db", PROPERTY_HINT_ENUM, "6 dB,12 dB,18 dB,24 dB"), "set_db", "get_db");
diff --git a/servers/audio/effects/audio_effect_filter.h b/servers/audio/effects/audio_effect_filter.h
index 11978882bc..bb0d451522 100644
--- a/servers/audio/effects/audio_effect_filter.h
+++ b/servers/audio/effects/audio_effect_filter.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,7 +37,7 @@
class AudioEffectFilter;
class AudioEffectFilterInstance : public AudioEffectInstance {
- GDCLASS(AudioEffectFilterInstance, AudioEffectInstance)
+ GDCLASS(AudioEffectFilterInstance, AudioEffectInstance);
friend class AudioEffectFilter;
Ref<AudioEffectFilter> base;
@@ -55,7 +55,8 @@ public:
};
class AudioEffectFilter : public AudioEffect {
- GDCLASS(AudioEffectFilter, AudioEffect)
+ GDCLASS(AudioEffectFilter, AudioEffect);
+
public:
enum FilterDB {
FILTER_6DB,
@@ -95,49 +96,66 @@ public:
VARIANT_ENUM_CAST(AudioEffectFilter::FilterDB)
class AudioEffectLowPassFilter : public AudioEffectFilter {
- GDCLASS(AudioEffectLowPassFilter, AudioEffectFilter)
+ GDCLASS(AudioEffectLowPassFilter, AudioEffectFilter);
+
+ void _validate_property(PropertyInfo &property) const {
+ if (property.name == "gain") property.usage = 0;
+ }
+
public:
AudioEffectLowPassFilter() :
AudioEffectFilter(AudioFilterSW::LOWPASS) {}
};
class AudioEffectHighPassFilter : public AudioEffectFilter {
- GDCLASS(AudioEffectHighPassFilter, AudioEffectFilter)
+ GDCLASS(AudioEffectHighPassFilter, AudioEffectFilter);
+ void _validate_property(PropertyInfo &property) const {
+ if (property.name == "gain") property.usage = 0;
+ }
+
public:
AudioEffectHighPassFilter() :
AudioEffectFilter(AudioFilterSW::HIGHPASS) {}
};
class AudioEffectBandPassFilter : public AudioEffectFilter {
- GDCLASS(AudioEffectBandPassFilter, AudioEffectFilter)
+ GDCLASS(AudioEffectBandPassFilter, AudioEffectFilter);
+ void _validate_property(PropertyInfo &property) const {
+ if (property.name == "gain") property.usage = 0;
+ }
+
public:
AudioEffectBandPassFilter() :
AudioEffectFilter(AudioFilterSW::BANDPASS) {}
};
class AudioEffectNotchFilter : public AudioEffectFilter {
- GDCLASS(AudioEffectNotchFilter, AudioEffectFilter)
+ GDCLASS(AudioEffectNotchFilter, AudioEffectFilter);
+
public:
AudioEffectNotchFilter() :
AudioEffectFilter(AudioFilterSW::NOTCH) {}
};
class AudioEffectBandLimitFilter : public AudioEffectFilter {
- GDCLASS(AudioEffectBandLimitFilter, AudioEffectFilter)
+ GDCLASS(AudioEffectBandLimitFilter, AudioEffectFilter);
+
public:
AudioEffectBandLimitFilter() :
AudioEffectFilter(AudioFilterSW::BANDLIMIT) {}
};
class AudioEffectLowShelfFilter : public AudioEffectFilter {
- GDCLASS(AudioEffectLowShelfFilter, AudioEffectFilter)
+ GDCLASS(AudioEffectLowShelfFilter, AudioEffectFilter);
+
public:
AudioEffectLowShelfFilter() :
AudioEffectFilter(AudioFilterSW::LOWSHELF) {}
};
class AudioEffectHighShelfFilter : public AudioEffectFilter {
- GDCLASS(AudioEffectHighShelfFilter, AudioEffectFilter)
+ GDCLASS(AudioEffectHighShelfFilter, AudioEffectFilter);
+
public:
AudioEffectHighShelfFilter() :
AudioEffectFilter(AudioFilterSW::HIGHSHELF) {}
diff --git a/servers/audio/effects/audio_effect_limiter.cpp b/servers/audio/effects/audio_effect_limiter.cpp
index 77454dc57b..9eaab11106 100644
--- a/servers/audio/effects/audio_effect_limiter.cpp
+++ b/servers/audio/effects/audio_effect_limiter.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/effects/audio_effect_limiter.h b/servers/audio/effects/audio_effect_limiter.h
index 8077d2da23..bf7167e3f4 100644
--- a/servers/audio/effects/audio_effect_limiter.h
+++ b/servers/audio/effects/audio_effect_limiter.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,7 +36,7 @@
class AudioEffectLimiter;
class AudioEffectLimiterInstance : public AudioEffectInstance {
- GDCLASS(AudioEffectLimiterInstance, AudioEffectInstance)
+ GDCLASS(AudioEffectLimiterInstance, AudioEffectInstance);
friend class AudioEffectLimiter;
Ref<AudioEffectLimiter> base;
@@ -47,7 +47,7 @@ public:
};
class AudioEffectLimiter : public AudioEffect {
- GDCLASS(AudioEffectLimiter, AudioEffect)
+ GDCLASS(AudioEffectLimiter, AudioEffect);
friend class AudioEffectLimiterInstance;
float threshold;
diff --git a/servers/audio/effects/audio_effect_panner.cpp b/servers/audio/effects/audio_effect_panner.cpp
index 6b6ca405e0..95212fee78 100644
--- a/servers/audio/effects/audio_effect_panner.cpp
+++ b/servers/audio/effects/audio_effect_panner.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/effects/audio_effect_panner.h b/servers/audio/effects/audio_effect_panner.h
index cdab11c445..7bd5a09fc6 100644
--- a/servers/audio/effects/audio_effect_panner.h
+++ b/servers/audio/effects/audio_effect_panner.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,7 +36,7 @@
class AudioEffectPanner;
class AudioEffectPannerInstance : public AudioEffectInstance {
- GDCLASS(AudioEffectPannerInstance, AudioEffectInstance)
+ GDCLASS(AudioEffectPannerInstance, AudioEffectInstance);
friend class AudioEffectPanner;
Ref<AudioEffectPanner> base;
@@ -45,7 +45,7 @@ public:
};
class AudioEffectPanner : public AudioEffect {
- GDCLASS(AudioEffectPanner, AudioEffect)
+ GDCLASS(AudioEffectPanner, AudioEffect);
friend class AudioEffectPannerInstance;
float pan;
diff --git a/servers/audio/effects/audio_effect_phaser.cpp b/servers/audio/effects/audio_effect_phaser.cpp
index 3151111ec8..b8768501e9 100644
--- a/servers/audio/effects/audio_effect_phaser.cpp
+++ b/servers/audio/effects/audio_effect_phaser.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/effects/audio_effect_phaser.h b/servers/audio/effects/audio_effect_phaser.h
index 96ba2b0abf..b76d6bb29c 100644
--- a/servers/audio/effects/audio_effect_phaser.h
+++ b/servers/audio/effects/audio_effect_phaser.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,7 +36,7 @@
class AudioEffectPhaser;
class AudioEffectPhaserInstance : public AudioEffectInstance {
- GDCLASS(AudioEffectPhaserInstance, AudioEffectInstance)
+ GDCLASS(AudioEffectPhaserInstance, AudioEffectInstance);
friend class AudioEffectPhaser;
Ref<AudioEffectPhaser> base;
@@ -70,7 +70,7 @@ public:
};
class AudioEffectPhaser : public AudioEffect {
- GDCLASS(AudioEffectPhaser, AudioEffect)
+ GDCLASS(AudioEffectPhaser, AudioEffect);
friend class AudioEffectPhaserInstance;
float range_min;
diff --git a/servers/audio/effects/audio_effect_pitch_shift.cpp b/servers/audio/effects/audio_effect_pitch_shift.cpp
index f5ca8f2da4..ec3182685f 100644
--- a/servers/audio/effects/audio_effect_pitch_shift.cpp
+++ b/servers/audio/effects/audio_effect_pitch_shift.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -70,7 +70,7 @@
* 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.
+* ANY KIND. See https://dspguru.com/wide-open-license/ for more information.
*
*****************************************************************************/
@@ -293,14 +293,16 @@ void AudioEffectPitchShiftInstance::process(const AudioFrame *p_src_frames, Audi
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);
+ shift_l.PitchShift(base->pitch_scale, p_frame_count, fft_size, base->oversampling, sample_rate, in_l, out_l, 2);
+ shift_r.PitchShift(base->pitch_scale, p_frame_count, fft_size, base->oversampling, sample_rate, in_r, out_r, 2);
}
Ref<AudioEffectInstance> AudioEffectPitchShift::instance() {
Ref<AudioEffectPitchShiftInstance> ins;
ins.instance();
ins->base = Ref<AudioEffectPitchShift>(this);
+ static const int fft_sizes[FFT_SIZE_MAX] = { 256, 512, 1024, 2048, 4096 };
+ ins->fft_size = fft_sizes[fft_size];
return ins;
}
@@ -315,14 +317,50 @@ float AudioEffectPitchShift::get_pitch_scale() const {
return pitch_scale;
}
+void AudioEffectPitchShift::set_oversampling(int p_oversampling) {
+ ERR_FAIL_COND(p_oversampling < 4);
+ oversampling = p_oversampling;
+}
+
+int AudioEffectPitchShift::get_oversampling() const {
+
+ return oversampling;
+}
+
+void AudioEffectPitchShift::set_fft_size(FFT_Size p_fft_size) {
+ ERR_FAIL_INDEX(p_fft_size, FFT_SIZE_MAX);
+ fft_size = p_fft_size;
+}
+
+AudioEffectPitchShift::FFT_Size AudioEffectPitchShift::get_fft_size() const {
+ return fft_size;
+}
+
void AudioEffectPitchShift::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_pitch_scale", "rate"), &AudioEffectPitchShift::set_pitch_scale);
ClassDB::bind_method(D_METHOD("get_pitch_scale"), &AudioEffectPitchShift::get_pitch_scale);
+ ClassDB::bind_method(D_METHOD("set_oversampling", "amount"), &AudioEffectPitchShift::set_oversampling);
+ ClassDB::bind_method(D_METHOD("get_oversampling"), &AudioEffectPitchShift::get_oversampling);
+
+ ClassDB::bind_method(D_METHOD("set_fft_size", "size"), &AudioEffectPitchShift::set_fft_size);
+ ClassDB::bind_method(D_METHOD("get_fft_size"), &AudioEffectPitchShift::get_fft_size);
+
ADD_PROPERTY(PropertyInfo(Variant::REAL, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_pitch_scale", "get_pitch_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "oversampling", PROPERTY_HINT_RANGE, "4,32,1"), "set_oversampling", "get_oversampling");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "fft_size", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096"), "set_fft_size", "get_fft_size");
+
+ BIND_ENUM_CONSTANT(FFT_SIZE_256);
+ BIND_ENUM_CONSTANT(FFT_SIZE_512);
+ BIND_ENUM_CONSTANT(FFT_SIZE_1024);
+ BIND_ENUM_CONSTANT(FFT_SIZE_2048);
+ BIND_ENUM_CONSTANT(FFT_SIZE_4096);
+ BIND_ENUM_CONSTANT(FFT_SIZE_MAX);
}
AudioEffectPitchShift::AudioEffectPitchShift() {
pitch_scale = 1.0;
+ oversampling = 4;
+ fft_size = FFT_SIZE_2048;
}
diff --git a/servers/audio/effects/audio_effect_pitch_shift.h b/servers/audio/effects/audio_effect_pitch_shift.h
index 78f92a0261..2028496ebf 100644
--- a/servers/audio/effects/audio_effect_pitch_shift.h
+++ b/servers/audio/effects/audio_effect_pitch_shift.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -72,10 +72,11 @@ public:
class AudioEffectPitchShift;
class AudioEffectPitchShiftInstance : public AudioEffectInstance {
- GDCLASS(AudioEffectPitchShiftInstance, AudioEffectInstance)
+ GDCLASS(AudioEffectPitchShiftInstance, AudioEffectInstance);
friend class AudioEffectPitchShift;
Ref<AudioEffectPitchShift> base;
+ int fft_size;
SMBPitchShift shift_l;
SMBPitchShift shift_r;
@@ -84,12 +85,23 @@ public:
};
class AudioEffectPitchShift : public AudioEffect {
- GDCLASS(AudioEffectPitchShift, AudioEffect)
+ GDCLASS(AudioEffectPitchShift, AudioEffect);
+public:
friend class AudioEffectPitchShiftInstance;
+ enum FFT_Size {
+ FFT_SIZE_256,
+ FFT_SIZE_512,
+ FFT_SIZE_1024,
+ FFT_SIZE_2048,
+ FFT_SIZE_4096,
+ FFT_SIZE_MAX
+ };
+
float pitch_scale;
- int window_size;
+ int oversampling;
+ FFT_Size fft_size;
float wet;
float dry;
bool filter;
@@ -103,7 +115,15 @@ public:
void set_pitch_scale(float p_pitch_scale);
float get_pitch_scale() const;
+ void set_oversampling(int p_oversampling);
+ int get_oversampling() const;
+
+ void set_fft_size(FFT_Size);
+ FFT_Size get_fft_size() const;
+
AudioEffectPitchShift();
};
+VARIANT_ENUM_CAST(AudioEffectPitchShift::FFT_Size);
+
#endif // AUDIO_EFFECT_PITCH_SHIFT_H
diff --git a/servers/audio/effects/audio_effect_record.cpp b/servers/audio/effects/audio_effect_record.cpp
index 78ba658ed8..1390ab55c4 100644
--- a/servers/audio/effects/audio_effect_record.cpp
+++ b/servers/audio/effects/audio_effect_record.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,6 +32,9 @@
void AudioEffectRecordInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
if (!is_recording) {
+ for (int i = 0; i < p_frame_count; i++) {
+ p_dst_frames[i] = p_src_frames[i];
+ }
return;
}
@@ -39,39 +42,41 @@ void AudioEffectRecordInstance::process(const AudioFrame *p_src_frames, AudioFra
const AudioFrame *src = p_src_frames;
AudioFrame *rb_buf = ring_buffer.ptrw();
for (int i = 0; i < p_frame_count; i++) {
+ p_dst_frames[i] = p_src_frames[i];
rb_buf[ring_buffer_pos & ring_buffer_mask] = src[i];
ring_buffer_pos++;
}
}
-bool AudioEffectRecordInstance::process_silence() {
+void AudioEffectRecordInstance::_update_buffer() {
+ //Case: Frames are remaining in the buffer
+ while (ring_buffer_read_pos < ring_buffer_pos) {
+ //Read from the buffer into recording_data
+ _io_store_buffer();
+ }
+}
+
+void AudioEffectRecordInstance::_update(void *userdata) {
+ AudioEffectRecordInstance *ins = (AudioEffectRecordInstance *)userdata;
+ ins->_update_buffer();
+}
+
+bool AudioEffectRecordInstance::process_silence() const {
return true;
}
void AudioEffectRecordInstance::_io_thread_process() {
-
- //Reset recorder status
thread_active = true;
- ring_buffer_pos = 0;
- ring_buffer_read_pos = 0;
-
- //We start a new recording
- recording_data.resize(0); //Clear data completely and reset length
- is_recording = true;
while (is_recording) {
//Check: The current recording has been requested to stop
- if (is_recording && !base->recording_active) {
+ if (!base->recording_active) {
is_recording = false;
}
- //Case: Frames are remaining in the buffer
- if (ring_buffer_read_pos < ring_buffer_pos) {
- //Read from the buffer into recording_data
- _io_store_buffer();
- }
- //Case: The buffer is empty
- else if (is_recording) {
+ _update_buffer();
+
+ if (is_recording) {
//Wait to avoid too much busy-wait
OS::get_singleton()->delay_usec(500);
}
@@ -103,7 +108,35 @@ void AudioEffectRecordInstance::_thread_callback(void *_instance) {
}
void AudioEffectRecordInstance::init() {
+ //Reset recorder status
+ ring_buffer_pos = 0;
+ ring_buffer_read_pos = 0;
+
+ //We start a new recording
+ recording_data.resize(0); //Clear data completely and reset length
+ is_recording = true;
+
+#ifdef NO_THREADS
+ AudioServer::get_singleton()->add_update_callback(&AudioEffectRecordInstance::_update, this);
+#else
io_thread = Thread::create(_thread_callback, this);
+#endif
+}
+
+void AudioEffectRecordInstance::finish() {
+
+#ifdef NO_THREADS
+ AudioServer::get_singleton()->remove_update_callback(&AudioEffectRecordInstance::_update, this);
+#else
+ if (thread_active) {
+ Thread::wait_to_finish(io_thread);
+ }
+#endif
+}
+
+AudioEffectRecordInstance::~AudioEffectRecordInstance() {
+
+ finish();
}
Ref<AudioEffectInstance> AudioEffectRecord::instance() {
@@ -145,8 +178,8 @@ Ref<AudioEffectInstance> AudioEffectRecord::instance() {
void AudioEffectRecord::ensure_thread_stopped() {
recording_active = false;
- if (current_instance != 0 && current_instance->thread_active) {
- Thread::wait_to_finish(current_instance->io_thread);
+ if (current_instance != 0) {
+ current_instance->finish();
}
}
@@ -183,6 +216,9 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
PoolVector<uint8_t> dst_data;
+ ERR_FAIL_COND_V(current_instance.is_null(), NULL);
+ ERR_FAIL_COND_V(current_instance->recording_data.size() == 0, NULL);
+
if (dst_format == AudioStreamSample::FORMAT_8_BITS) {
int data_size = current_instance->recording_data.size();
dst_data.resize(data_size);
diff --git a/servers/audio/effects/audio_effect_record.h b/servers/audio/effects/audio_effect_record.h
index 5f5c7802b4..d9bf39eb5f 100644
--- a/servers/audio/effects/audio_effect_record.h
+++ b/servers/audio/effects/audio_effect_record.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -43,13 +43,13 @@
class AudioEffectRecord;
class AudioEffectRecordInstance : public AudioEffectInstance {
- GDCLASS(AudioEffectRecordInstance, AudioEffectInstance)
+ GDCLASS(AudioEffectRecordInstance, AudioEffectInstance);
friend class AudioEffectRecord;
Ref<AudioEffectRecord> base;
bool is_recording;
Thread *io_thread;
- bool thread_active = false;
+ bool thread_active;
Vector<AudioFrame> ring_buffer;
Vector<float> recording_data;
@@ -62,15 +62,22 @@ class AudioEffectRecordInstance : public AudioEffectInstance {
void _io_store_buffer();
static void _thread_callback(void *_instance);
void _init_recording();
+ void _update_buffer();
+ static void _update(void *userdata);
public:
void init();
+ void finish();
virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count);
- virtual bool process_silence();
+ virtual bool process_silence() const;
+
+ AudioEffectRecordInstance() :
+ thread_active(false) {}
+ ~AudioEffectRecordInstance();
};
class AudioEffectRecord : public AudioEffect {
- GDCLASS(AudioEffectRecord, AudioEffect)
+ GDCLASS(AudioEffectRecord, AudioEffect);
friend class AudioEffectRecordInstance;
diff --git a/servers/audio/effects/audio_effect_reverb.cpp b/servers/audio/effects/audio_effect_reverb.cpp
index 162c0a1445..003ac452d2 100644
--- a/servers/audio/effects/audio_effect_reverb.cpp
+++ b/servers/audio/effects/audio_effect_reverb.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/effects/audio_effect_reverb.h b/servers/audio/effects/audio_effect_reverb.h
index 5646fd2238..31a796bf98 100644
--- a/servers/audio/effects/audio_effect_reverb.h
+++ b/servers/audio/effects/audio_effect_reverb.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,7 +37,7 @@
class AudioEffectReverb;
class AudioEffectReverbInstance : public AudioEffectInstance {
- GDCLASS(AudioEffectReverbInstance, AudioEffectInstance)
+ GDCLASS(AudioEffectReverbInstance, AudioEffectInstance);
Ref<AudioEffectReverb> base;
@@ -54,7 +54,7 @@ public:
};
class AudioEffectReverb : public AudioEffect {
- GDCLASS(AudioEffectReverb, AudioEffect)
+ GDCLASS(AudioEffectReverb, AudioEffect);
friend class AudioEffectReverbInstance;
diff --git a/servers/audio/effects/audio_effect_spectrum_analyzer.cpp b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp
new file mode 100644
index 0000000000..bb1daf04a4
--- /dev/null
+++ b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp
@@ -0,0 +1,287 @@
+/*************************************************************************/
+/* audio_effect_spectrum_analyzer.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "audio_effect_spectrum_analyzer.h"
+#include "servers/audio_server.h"
+
+static void smbFft(float *fftBuffer, long fftFrameSize, long sign)
+/*
+ FFT routine, (C)1996 S.M.Bernsee. Sign = -1 is FFT, 1 is iFFT (inverse)
+ Fills fftBuffer[0...2*fftFrameSize-1] with the Fourier transform of the
+ time domain data in fftBuffer[0...2*fftFrameSize-1]. The FFT array takes
+ and returns the cosine and sine parts in an interleaved manner, ie.
+ fftBuffer[0] = cosPart[0], fftBuffer[1] = sinPart[0], asf. fftFrameSize
+ must be a power of 2. It expects a complex input signal (see footnote 2),
+ ie. when working with 'common' audio signals our input signal has to be
+ passed as {in[0],0.,in[1],0.,in[2],0.,...} asf. In that case, the transform
+ of the frequencies of interest is in fftBuffer[0...fftFrameSize].
+*/
+{
+ float wr, wi, arg, *p1, *p2, temp;
+ float tr, ti, ur, ui, *p1r, *p1i, *p2r, *p2i;
+ long i, bitm, j, le, le2, k;
+
+ for (i = 2; i < 2 * fftFrameSize - 2; i += 2) {
+ for (bitm = 2, j = 0; bitm < 2 * fftFrameSize; bitm <<= 1) {
+ if (i & bitm) j++;
+ j <<= 1;
+ }
+ if (i < j) {
+ p1 = fftBuffer + i;
+ p2 = fftBuffer + j;
+ temp = *p1;
+ *(p1++) = *p2;
+ *(p2++) = temp;
+ temp = *p1;
+ *p1 = *p2;
+ *p2 = temp;
+ }
+ }
+ for (k = 0, le = 2; k < (long)(log((double)fftFrameSize) / log(2.) + .5); k++) {
+ le <<= 1;
+ le2 = le >> 1;
+ ur = 1.0;
+ ui = 0.0;
+ arg = Math_PI / (le2 >> 1);
+ wr = cos(arg);
+ wi = sign * sin(arg);
+ for (j = 0; j < le2; j += 2) {
+ p1r = fftBuffer + j;
+ p1i = p1r + 1;
+ p2r = p1r + le2;
+ p2i = p2r + 1;
+ for (i = j; i < 2 * fftFrameSize; i += le) {
+ tr = *p2r * ur - *p2i * ui;
+ ti = *p2r * ui + *p2i * ur;
+ *p2r = *p1r - tr;
+ *p2i = *p1i - ti;
+ *p1r += tr;
+ *p1i += ti;
+ p1r += le;
+ p1i += le;
+ p2r += le;
+ p2i += le;
+ }
+ tr = ur * wr - ui * wi;
+ ui = ur * wi + ui * wr;
+ ur = tr;
+ }
+ }
+}
+void AudioEffectSpectrumAnalyzerInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
+
+ uint64_t time = OS::get_singleton()->get_ticks_usec();
+
+ //copy everything over first, since this only really does capture
+ for (int i = 0; i < p_frame_count; i++) {
+ p_dst_frames[i] = p_src_frames[i];
+ }
+
+ //capture spectrum
+ while (p_frame_count) {
+ int to_fill = fft_size * 2 - temporal_fft_pos;
+ to_fill = MIN(to_fill, p_frame_count);
+
+ float *fftw = temporal_fft.ptrw();
+ for (int i = 0; i < to_fill; i++) { //left and right buffers
+ float window = -0.5 * Math::cos(2.0 * Math_PI * (double)i / (double)to_fill) + 0.5;
+ fftw[(i + temporal_fft_pos) * 2] = window * p_src_frames[i].l;
+ fftw[(i + temporal_fft_pos) * 2 + 1] = 0;
+ fftw[(i + temporal_fft_pos + fft_size * 2) * 2] = window * p_src_frames[i].r;
+ fftw[(i + temporal_fft_pos + fft_size * 2) * 2 + 1] = 0;
+ }
+
+ p_src_frames += to_fill;
+ temporal_fft_pos += to_fill;
+ p_frame_count -= to_fill;
+
+ if (temporal_fft_pos == fft_size * 2) {
+ //time to do a FFT
+ smbFft(fftw, fft_size * 2, -1);
+ smbFft(fftw + fft_size * 4, fft_size * 2, -1);
+ int next = (fft_pos + 1) % fft_count;
+
+ AudioFrame *hw = (AudioFrame *)fft_history[next].ptr(); //do not use write, avoid cow
+
+ for (int i = 0; i < fft_size; i++) {
+ //abs(vec)/fft_size normalizes each frequency
+ float window = 1.0; //-.5 * Math::cos(2. * Math_PI * (double)i / (double)fft_size) + .5;
+ hw[i].l = window * Vector2(fftw[i * 2], fftw[i * 2 + 1]).length() / float(fft_size);
+ hw[i].r = window * Vector2(fftw[fft_size * 4 + i * 2], fftw[fft_size * 4 + i * 2 + 1]).length() / float(fft_size);
+ }
+
+ fft_pos = next; //swap
+ temporal_fft_pos = 0;
+ }
+ }
+
+ //determine time of capture
+ double remainer_sec = (temporal_fft_pos / mix_rate); //subtract remainder from mix time
+ last_fft_time = time - uint64_t(remainer_sec * 1000000.0);
+}
+
+void AudioEffectSpectrumAnalyzerInstance::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("get_magnitude_for_frequency_range", "from_hz", "to_hz", "mode"), &AudioEffectSpectrumAnalyzerInstance::get_magnitude_for_frequency_range, DEFVAL(MAGNITUDE_MAX));
+ BIND_ENUM_CONSTANT(MAGNITUDE_AVERAGE);
+ BIND_ENUM_CONSTANT(MAGNITUDE_MAX);
+}
+
+Vector2 AudioEffectSpectrumAnalyzerInstance::get_magnitude_for_frequency_range(float p_begin, float p_end, MagnitudeMode p_mode) const {
+
+ if (last_fft_time == 0) {
+ return Vector2();
+ }
+ uint64_t time = OS::get_singleton()->get_ticks_usec();
+ float diff = double(time - last_fft_time) / 1000000.0 + base->get_tap_back_pos();
+ diff -= AudioServer::get_singleton()->get_output_latency();
+ float fft_time_size = float(fft_size) / mix_rate;
+
+ int fft_index = fft_pos;
+
+ while (diff > fft_time_size) {
+ diff -= fft_time_size;
+ fft_index -= 1;
+ if (fft_index < 0) {
+ fft_index = fft_count - 1;
+ }
+ }
+
+ int begin_pos = p_begin * fft_size / (mix_rate * 0.5);
+ int end_pos = p_end * fft_size / (mix_rate * 0.5);
+
+ begin_pos = CLAMP(begin_pos, 0, fft_size - 1);
+ end_pos = CLAMP(end_pos, 0, fft_size - 1);
+
+ if (begin_pos > end_pos) {
+ SWAP(begin_pos, end_pos);
+ }
+ const AudioFrame *r = fft_history[fft_index].ptr();
+
+ if (p_mode == MAGNITUDE_AVERAGE) {
+ Vector2 avg;
+
+ for (int i = begin_pos; i <= end_pos; i++) {
+ avg += Vector2(r[i]);
+ }
+
+ avg /= float(end_pos - begin_pos + 1);
+
+ return avg;
+ } else {
+
+ Vector2 max;
+
+ for (int i = begin_pos; i <= end_pos; i++) {
+ max.x = MAX(max.x, r[i].l);
+ max.y = MAX(max.y, r[i].r);
+ }
+
+ return max;
+ }
+}
+
+Ref<AudioEffectInstance> AudioEffectSpectrumAnalyzer::instance() {
+
+ Ref<AudioEffectSpectrumAnalyzerInstance> ins;
+ ins.instance();
+ ins->base = Ref<AudioEffectSpectrumAnalyzer>(this);
+ static const int fft_sizes[FFT_SIZE_MAX] = { 256, 512, 1024, 2048, 4096 };
+ ins->fft_size = fft_sizes[fft_size];
+ ins->mix_rate = AudioServer::get_singleton()->get_mix_rate();
+ ins->fft_count = (buffer_length / (float(ins->fft_size) / ins->mix_rate)) + 1;
+ ins->fft_pos = 0;
+ ins->last_fft_time = 0;
+ ins->fft_history.resize(ins->fft_count);
+ ins->temporal_fft.resize(ins->fft_size * 8); //x2 stereo, x2 amount of samples for freqs, x2 for input
+ ins->temporal_fft_pos = 0;
+ for (int i = 0; i < ins->fft_count; i++) {
+ ins->fft_history.write[i].resize(ins->fft_size); //only magnitude matters
+ for (int j = 0; j < ins->fft_size; j++) {
+ ins->fft_history.write[i].write[j] = AudioFrame(0, 0);
+ }
+ }
+ return ins;
+}
+
+void AudioEffectSpectrumAnalyzer::set_buffer_length(float p_seconds) {
+ buffer_length = p_seconds;
+}
+
+float AudioEffectSpectrumAnalyzer::get_buffer_length() const {
+
+ return buffer_length;
+}
+
+void AudioEffectSpectrumAnalyzer::set_tap_back_pos(float p_seconds) {
+ tapback_pos = p_seconds;
+}
+
+float AudioEffectSpectrumAnalyzer::get_tap_back_pos() const {
+ return tapback_pos;
+}
+
+void AudioEffectSpectrumAnalyzer::set_fft_size(FFT_Size p_fft_size) {
+ ERR_FAIL_INDEX(p_fft_size, FFT_SIZE_MAX);
+ fft_size = p_fft_size;
+}
+
+AudioEffectSpectrumAnalyzer::FFT_Size AudioEffectSpectrumAnalyzer::get_fft_size() const {
+ return fft_size;
+}
+
+void AudioEffectSpectrumAnalyzer::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_buffer_length", "seconds"), &AudioEffectSpectrumAnalyzer::set_buffer_length);
+ ClassDB::bind_method(D_METHOD("get_buffer_length"), &AudioEffectSpectrumAnalyzer::get_buffer_length);
+
+ ClassDB::bind_method(D_METHOD("set_tap_back_pos", "seconds"), &AudioEffectSpectrumAnalyzer::set_tap_back_pos);
+ ClassDB::bind_method(D_METHOD("get_tap_back_pos"), &AudioEffectSpectrumAnalyzer::get_tap_back_pos);
+
+ ClassDB::bind_method(D_METHOD("set_fft_size", "size"), &AudioEffectSpectrumAnalyzer::set_fft_size);
+ ClassDB::bind_method(D_METHOD("get_fft_size"), &AudioEffectSpectrumAnalyzer::get_fft_size);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "buffer_length", PROPERTY_HINT_RANGE, "0.1,4,0.1"), "set_buffer_length", "get_buffer_length");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "tap_back_pos", PROPERTY_HINT_RANGE, "0.1,4,0.1"), "set_tap_back_pos", "get_tap_back_pos");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "fft_size", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096"), "set_fft_size", "get_fft_size");
+
+ BIND_ENUM_CONSTANT(FFT_SIZE_256);
+ BIND_ENUM_CONSTANT(FFT_SIZE_512);
+ BIND_ENUM_CONSTANT(FFT_SIZE_1024);
+ BIND_ENUM_CONSTANT(FFT_SIZE_2048);
+ BIND_ENUM_CONSTANT(FFT_SIZE_4096);
+ BIND_ENUM_CONSTANT(FFT_SIZE_MAX);
+}
+
+AudioEffectSpectrumAnalyzer::AudioEffectSpectrumAnalyzer() {
+ buffer_length = 2;
+ tapback_pos = 0.01;
+ fft_size = FFT_SIZE_1024;
+}
diff --git a/servers/audio/effects/audio_effect_spectrum_analyzer.h b/servers/audio/effects/audio_effect_spectrum_analyzer.h
new file mode 100644
index 0000000000..27eb88d29f
--- /dev/null
+++ b/servers/audio/effects/audio_effect_spectrum_analyzer.h
@@ -0,0 +1,107 @@
+/*************************************************************************/
+/* audio_effect_spectrum_analyzer.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef AUDIO_EFFECT_SPECTRUM_ANALYZER_H
+#define AUDIO_EFFECT_SPECTRUM_ANALYZER_H
+
+#include "servers/audio/audio_effect.h"
+
+class AudioEffectSpectrumAnalyzer;
+
+class AudioEffectSpectrumAnalyzerInstance : public AudioEffectInstance {
+ GDCLASS(AudioEffectSpectrumAnalyzerInstance, AudioEffectInstance);
+
+public:
+ enum MagnitudeMode {
+ MAGNITUDE_AVERAGE,
+ MAGNITUDE_MAX,
+ };
+
+private:
+ friend class AudioEffectSpectrumAnalyzer;
+ Ref<AudioEffectSpectrumAnalyzer> base;
+
+ Vector<Vector<AudioFrame> > fft_history;
+ Vector<float> temporal_fft;
+ int temporal_fft_pos;
+ int fft_size;
+ int fft_count;
+ int fft_pos;
+ float mix_rate;
+ uint64_t last_fft_time;
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count);
+ Vector2 get_magnitude_for_frequency_range(float p_begin, float p_end, MagnitudeMode p_mode = MAGNITUDE_MAX) const;
+};
+
+VARIANT_ENUM_CAST(AudioEffectSpectrumAnalyzerInstance::MagnitudeMode)
+
+class AudioEffectSpectrumAnalyzer : public AudioEffect {
+ GDCLASS(AudioEffectSpectrumAnalyzer, AudioEffect);
+
+public:
+ enum FFT_Size {
+ FFT_SIZE_256,
+ FFT_SIZE_512,
+ FFT_SIZE_1024,
+ FFT_SIZE_2048,
+ FFT_SIZE_4096,
+ FFT_SIZE_MAX
+ };
+
+public:
+ friend class AudioEffectSpectrumAnalyzerInstance;
+ float buffer_length;
+ float tapback_pos;
+ FFT_Size fft_size;
+
+protected:
+ static void _bind_methods();
+
+public:
+ Ref<AudioEffectInstance> instance();
+ void set_buffer_length(float p_seconds);
+ float get_buffer_length() const;
+ void set_tap_back_pos(float p_seconds);
+ float get_tap_back_pos() const;
+
+ void set_fft_size(FFT_Size);
+ FFT_Size get_fft_size() const;
+
+ AudioEffectSpectrumAnalyzer();
+};
+
+VARIANT_ENUM_CAST(AudioEffectSpectrumAnalyzer::FFT_Size);
+
+#endif // AUDIO_EFFECT_SPECTRUM_ANALYZER_H
diff --git a/servers/audio/effects/audio_effect_stereo_enhance.cpp b/servers/audio/effects/audio_effect_stereo_enhance.cpp
index cf5228f8b6..8945675e07 100644
--- a/servers/audio/effects/audio_effect_stereo_enhance.cpp
+++ b/servers/audio/effects/audio_effect_stereo_enhance.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/effects/audio_effect_stereo_enhance.h b/servers/audio/effects/audio_effect_stereo_enhance.h
index 13dd4ac042..44b7d3eb5c 100644
--- a/servers/audio/effects/audio_effect_stereo_enhance.h
+++ b/servers/audio/effects/audio_effect_stereo_enhance.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,7 +36,7 @@
class AudioEffectStereoEnhance;
class AudioEffectStereoEnhanceInstance : public AudioEffectInstance {
- GDCLASS(AudioEffectStereoEnhanceInstance, AudioEffectInstance)
+ GDCLASS(AudioEffectStereoEnhanceInstance, AudioEffectInstance);
friend class AudioEffectStereoEnhance;
Ref<AudioEffectStereoEnhance> base;
@@ -56,7 +56,7 @@ public:
};
class AudioEffectStereoEnhance : public AudioEffect {
- GDCLASS(AudioEffectStereoEnhance, AudioEffect)
+ GDCLASS(AudioEffectStereoEnhance, AudioEffect);
friend class AudioEffectStereoEnhanceInstance;
float volume_db;
diff --git a/servers/audio/effects/audio_stream_generator.cpp b/servers/audio/effects/audio_stream_generator.cpp
new file mode 100644
index 0000000000..49af63e82a
--- /dev/null
+++ b/servers/audio/effects/audio_stream_generator.cpp
@@ -0,0 +1,212 @@
+/*************************************************************************/
+/* audio_stream_generator.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "audio_stream_generator.h"
+
+void AudioStreamGenerator::set_mix_rate(float p_mix_rate) {
+ mix_rate = p_mix_rate;
+}
+
+float AudioStreamGenerator::get_mix_rate() const {
+
+ return mix_rate;
+}
+
+void AudioStreamGenerator::set_buffer_length(float p_seconds) {
+
+ buffer_len = p_seconds;
+}
+float AudioStreamGenerator::get_buffer_length() const {
+
+ return buffer_len;
+}
+
+Ref<AudioStreamPlayback> AudioStreamGenerator::instance_playback() {
+
+ Ref<AudioStreamGeneratorPlayback> playback;
+ playback.instance();
+ playback->generator = this;
+ int target_buffer_size = mix_rate * buffer_len;
+ playback->buffer.resize(nearest_shift(target_buffer_size));
+ playback->buffer.clear();
+ return playback;
+}
+String AudioStreamGenerator::get_stream_name() const {
+
+ return "UserFeed";
+}
+
+float AudioStreamGenerator::get_length() const {
+ return 0;
+}
+
+void AudioStreamGenerator::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_mix_rate", "hz"), &AudioStreamGenerator::set_mix_rate);
+ ClassDB::bind_method(D_METHOD("get_mix_rate"), &AudioStreamGenerator::get_mix_rate);
+
+ ClassDB::bind_method(D_METHOD("set_buffer_length", "seconds"), &AudioStreamGenerator::set_buffer_length);
+ ClassDB::bind_method(D_METHOD("get_buffer_length"), &AudioStreamGenerator::get_buffer_length);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "mix_rate", PROPERTY_HINT_RANGE, "20,192000,1"), "set_mix_rate", "get_mix_rate");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "buffer_length", PROPERTY_HINT_RANGE, "0.01,10,0.01"), "set_buffer_length", "get_buffer_length");
+}
+
+AudioStreamGenerator::AudioStreamGenerator() {
+ mix_rate = 44100;
+ buffer_len = 0.5;
+}
+
+////////////////
+
+bool AudioStreamGeneratorPlayback::push_frame(const Vector2 &p_frame) {
+ if (buffer.space_left() < 1) {
+ return false;
+ }
+
+ AudioFrame f = p_frame;
+
+ buffer.write(&f, 1);
+ return true;
+}
+
+bool AudioStreamGeneratorPlayback::can_push_buffer(int p_frames) const {
+ return buffer.space_left() >= p_frames;
+}
+bool AudioStreamGeneratorPlayback::push_buffer(const PoolVector2Array &p_frames) {
+
+ int to_write = p_frames.size();
+ if (buffer.space_left() < to_write) {
+ return false;
+ }
+
+ PoolVector2Array::Read r = p_frames.read();
+ if (sizeof(real_t) == 4) {
+ //write directly
+ buffer.write((const AudioFrame *)r.ptr(), to_write);
+ } else {
+ //convert from double
+ AudioFrame buf[2048];
+ int ofs = 0;
+ while (to_write) {
+
+ int w = MIN(to_write, 2048);
+ for (int i = 0; i < w; i++) {
+ buf[i] = r[i + ofs];
+ }
+ buffer.write(buf, w);
+ ofs += w;
+ to_write -= w;
+ }
+ }
+ return true;
+}
+
+int AudioStreamGeneratorPlayback::get_frames_available() const {
+ return buffer.space_left();
+}
+
+int AudioStreamGeneratorPlayback::get_skips() const {
+ return skips;
+}
+
+void AudioStreamGeneratorPlayback::clear_buffer() {
+ ERR_FAIL_COND(active);
+ buffer.clear();
+ mixed = 0;
+}
+
+void AudioStreamGeneratorPlayback::_mix_internal(AudioFrame *p_buffer, int p_frames) {
+
+ int read_amount = buffer.data_left();
+ if (p_frames < read_amount) {
+ read_amount = p_frames;
+ }
+
+ buffer.read(p_buffer, read_amount);
+
+ if (read_amount < p_frames) {
+ //skipped, not ideal
+ for (int i = read_amount; i < p_frames; i++) {
+ p_buffer[i] = AudioFrame(0, 0);
+ }
+
+ skips++;
+ }
+
+ mixed += p_frames / generator->get_mix_rate();
+}
+float AudioStreamGeneratorPlayback::get_stream_sampling_rate() {
+ return generator->get_mix_rate();
+}
+
+void AudioStreamGeneratorPlayback::start(float p_from_pos) {
+
+ if (mixed == 0.0) {
+ _begin_resample();
+ }
+ skips = 0;
+ active = true;
+ mixed = 0.0;
+}
+
+void AudioStreamGeneratorPlayback::stop() {
+ active = false;
+}
+bool AudioStreamGeneratorPlayback::is_playing() const {
+
+ return active; //always playing, can't be stopped
+}
+
+int AudioStreamGeneratorPlayback::get_loop_count() const {
+ return 0;
+}
+
+float AudioStreamGeneratorPlayback::get_playback_position() const {
+ return mixed;
+}
+void AudioStreamGeneratorPlayback::seek(float p_time) {
+ //no seek possible
+}
+
+void AudioStreamGeneratorPlayback::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("push_frame", "frame"), &AudioStreamGeneratorPlayback::push_frame);
+ ClassDB::bind_method(D_METHOD("can_push_buffer", "amount"), &AudioStreamGeneratorPlayback::can_push_buffer);
+ ClassDB::bind_method(D_METHOD("push_buffer", "frames"), &AudioStreamGeneratorPlayback::push_buffer);
+ ClassDB::bind_method(D_METHOD("get_frames_available"), &AudioStreamGeneratorPlayback::get_frames_available);
+ ClassDB::bind_method(D_METHOD("get_skips"), &AudioStreamGeneratorPlayback::get_skips);
+ ClassDB::bind_method(D_METHOD("clear_buffer"), &AudioStreamGeneratorPlayback::clear_buffer);
+}
+
+AudioStreamGeneratorPlayback::AudioStreamGeneratorPlayback() {
+ generator = NULL;
+ skips = 0;
+ active = false;
+ mixed = 0;
+}
diff --git a/servers/audio/effects/audio_stream_generator.h b/servers/audio/effects/audio_stream_generator.h
new file mode 100644
index 0000000000..33839d3db8
--- /dev/null
+++ b/servers/audio/effects/audio_stream_generator.h
@@ -0,0 +1,96 @@
+/*************************************************************************/
+/* audio_stream_generator.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef AUDIO_STREAM_GENERATOR_H
+#define AUDIO_STREAM_GENERATOR_H
+
+#include "core/ring_buffer.h"
+#include "servers/audio/audio_stream.h"
+
+class AudioStreamGenerator : public AudioStream {
+ GDCLASS(AudioStreamGenerator, AudioStream);
+
+ float mix_rate;
+ float buffer_len;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_mix_rate(float p_mix_rate);
+ float get_mix_rate() const;
+
+ void set_buffer_length(float p_seconds);
+ float get_buffer_length() const;
+
+ virtual Ref<AudioStreamPlayback> instance_playback();
+ virtual String get_stream_name() const;
+
+ virtual float get_length() const;
+ AudioStreamGenerator();
+};
+
+class AudioStreamGeneratorPlayback : public AudioStreamPlaybackResampled {
+
+ GDCLASS(AudioStreamGeneratorPlayback, AudioStreamPlaybackResampled);
+ friend class AudioStreamGenerator;
+ RingBuffer<AudioFrame> buffer;
+ int skips;
+ bool active;
+ float mixed;
+ AudioStreamGenerator *generator;
+
+protected:
+ virtual void _mix_internal(AudioFrame *p_buffer, int p_frames);
+ virtual float get_stream_sampling_rate();
+
+ static void _bind_methods();
+
+public:
+ virtual void start(float p_from_pos = 0.0);
+ virtual void stop();
+ virtual bool is_playing() const;
+
+ virtual int get_loop_count() const; //times it looped
+
+ virtual float get_playback_position() const;
+ virtual void seek(float p_time);
+
+ bool push_frame(const Vector2 &p_frame);
+ bool can_push_buffer(int p_frames) const;
+ bool push_buffer(const PoolVector2Array &p_frames);
+ int get_frames_available() const;
+ int get_skips() const;
+
+ void clear_buffer();
+
+ AudioStreamGeneratorPlayback();
+};
+#endif // AUDIO_STREAM_GENERATOR_H
diff --git a/servers/audio/effects/eq.cpp b/servers/audio/effects/eq.cpp
index 70ac70a5a8..e8f247d3bc 100644
--- a/servers/audio/effects/eq.cpp
+++ b/servers/audio/effects/eq.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/effects/eq.h b/servers/audio/effects/eq.h
index c06f1f8bf8..2c407ee60e 100644
--- a/servers/audio/effects/eq.h
+++ b/servers/audio/effects/eq.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/effects/reverb.cpp b/servers/audio/effects/reverb.cpp
index ef23e4aaf3..1f9fa23763 100644
--- a/servers/audio/effects/reverb.cpp
+++ b/servers/audio/effects/reverb.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,22 +36,22 @@
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
+ 0.025306122448979593f,
+ 0.026938775510204082f,
+ 0.028956916099773241f,
+ 0.03074829931972789f,
+ 0.032244897959183672f,
+ 0.03380952380952381f,
+ 0.035306122448979592f,
+ 0.036666666666666667f
};
const float Reverb::allpass_tunings[MAX_ALLPASS] = {
//freeverb allpass tunings
- 0.0051020408163265302,
- 0.007732426303854875,
- 0.01,
- 0.012607709750566893
+ 0.0051020408163265302f,
+ 0.007732426303854875f,
+ 0.01f,
+ 0.012607709750566893f
};
void Reverb::process(float *p_src, float *p_dst, int p_frames) {
diff --git a/servers/audio/effects/reverb.h b/servers/audio/effects/reverb.h
index 03cf197456..6a2e291466 100644
--- a/servers/audio/effects/reverb.h
+++ b/servers/audio/effects/reverb.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/reverb_sw.cpp b/servers/audio/reverb_sw.cpp
index 13742d5db5..63bf1a7eaa 100644
--- a/servers/audio/reverb_sw.cpp
+++ b/servers/audio/reverb_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,33 +29,18 @@
/*************************************************************************/
#include "reverb_sw.h"
-#include "core/print_string.h"
-#include "stdlib.h"
-#define SETMIN(x, y) (x) = MIN((x), (y))
-#define rangeloop(c, min, max) \
- for ((c) = (min); (c) < (max); (c)++)
-#define ABSDIFF(x, y) \
- (((x) < (y)) ? ((y) - (x)) : ((x) - (y)))
+#include "core/print_string.h"
-#ifdef bleh_MSC_VER
+#include <stdlib.h>
-#if _MSC_VER >= 1400
-_FORCE_INLINE_ int32_tMULSHIFT_S32(
- int32_t Factor1,
- int32_t Factor2,
- uint8_t Bits) {
+#define SETMIN(x, y) (x) = MIN((x), (y))
- return __ll_rshift(
- __emul(Factor1, Factor2),
- Bits);
-}
-#endif
+#define rangeloop(c, min, max) \
+ for ((c) = (min); (c) < (max); (c)++)
-#else
#define MULSHIFT_S32(Factor1, Factor2, Bits) \
((int)(((int64_t)(Factor1) * (Factor2)) >> (Bits)))
-#endif
struct ReverbParamsSW {
unsigned int BufferSize; // Required buffer size
diff --git a/servers/audio/reverb_sw.h b/servers/audio/reverb_sw.h
index 26b3fa5166..1a2e2e2bb8 100644
--- a/servers/audio/reverb_sw.h
+++ b/servers/audio/reverb_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,7 +34,7 @@
#include "core/os/memory.h"
#include "core/typedefs.h"
-class ReverbParamsSW;
+struct ReverbParamsSW;
class ReverbSW {
public:
diff --git a/servers/audio/voice_rb_sw.h b/servers/audio/voice_rb_sw.h
index fc02cc1827..1f0c88ed30 100644
--- a/servers/audio/voice_rb_sw.h
+++ b/servers/audio/voice_rb_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -125,8 +125,7 @@ public:
if (full) {
#ifdef DEBUG_ENABLED
if (OS::get_singleton()->is_stdout_verbose()) {
- ERR_EXPLAIN("Audio Ring Buffer Full (too many commands");
- ERR_FAIL_COND(((write_pos + 1) % VOICE_RB_SIZE) == read_pos);
+ ERR_FAIL_COND_MSG(((write_pos + 1) % VOICE_RB_SIZE) == read_pos, "Audio ring buffer full (too many commands).");
}
#endif
return;
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 070099a3d8..2cf6a67bef 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -68,26 +68,43 @@ void AudioDriver::audio_server_process(int p_frames, int32_t *p_buffer, bool p_u
void AudioDriver::update_mix_time(int p_frames) {
- _mix_amount += p_frames;
+ _last_mix_frames = p_frames;
if (OS::get_singleton())
_last_mix_time = OS::get_singleton()->get_ticks_usec();
}
-double AudioDriver::get_mix_time() const {
+double AudioDriver::get_time_since_last_mix() const {
+
+ return (OS::get_singleton()->get_ticks_usec() - _last_mix_time) / 1000000.0;
+}
+
+double AudioDriver::get_time_to_next_mix() const {
double total = (OS::get_singleton()->get_ticks_usec() - _last_mix_time) / 1000000.0;
- total += _mix_amount / (double)get_mix_rate();
- return total;
+ double mix_buffer = _last_mix_frames / (double)get_mix_rate();
+ return mix_buffer - total;
}
-void AudioDriver::input_buffer_write(int32_t sample) {
+void AudioDriver::capture_buffer_init(int driver_buffer_frames) {
- input_buffer.write[input_position++] = sample;
- if (input_position >= input_buffer.size()) {
- input_position = 0;
- }
- if (input_size < input_buffer.size()) {
- input_size++;
+ const int capture_buffer_channels = 2;
+ capture_buffer.resize(driver_buffer_frames * capture_buffer_channels * 4);
+ capture_position = 0;
+ capture_size = 0;
+}
+
+void AudioDriver::capture_buffer_write(int32_t sample) {
+
+ if ((int)capture_position < capture_buffer.size()) {
+ capture_buffer.write()[capture_position++] = sample;
+ if ((int)capture_position >= capture_buffer.size()) {
+ capture_position = 0;
+ }
+ if ((int)capture_size < capture_buffer.size()) {
+ capture_size++;
+ }
+ } else {
+ WARN_PRINTS("capture_buffer_write: Invalid capture_position=" + itos(capture_position) + " capture_buffer.size()=" + itos(capture_buffer.size()));
}
}
@@ -136,7 +153,9 @@ Array AudioDriver::capture_get_device_list() {
AudioDriver::AudioDriver() {
_last_mix_time = 0;
- _mix_amount = 0;
+ _last_mix_frames = 0;
+ capture_position = 0;
+ capture_size = 0;
#ifdef DEBUG_ENABLED
prof_time = 0;
@@ -164,6 +183,7 @@ int AudioDriverManager::get_driver_count() {
}
void AudioDriverManager::initialize(int p_driver) {
+ GLOBAL_DEF_RST("audio/enable_audio_input", false);
int failed_driver = -1;
// Check if there is a selected driver
@@ -189,7 +209,7 @@ void AudioDriverManager::initialize(int p_driver) {
}
}
- if (driver_count > 1 && AudioDriver::get_singleton()->get_name() == "Dummy") {
+ if (driver_count > 1 && String(AudioDriver::get_singleton()->get_name()) == "Dummy") {
WARN_PRINT("All audio drivers failed, falling back to the dummy driver.");
}
}
@@ -244,11 +264,13 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) {
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;
+ int32_t vl2 = (vl < 0 ? -1 : 1) * (ABS(vl) << 11);
+ p_buffer[(from_buf + j) * (cs * 2) + k * 2 + 0] = vl2;
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;
+ int32_t vr2 = (vr < 0 ? -1 : 1) * (ABS(vr) << 11);
+ p_buffer[(from_buf + j) * (cs * 2) + k * 2 + 1] = vr2;
}
} else {
@@ -264,13 +286,6 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) {
to_mix -= to_copy;
}
- // Calculate latency for Performance.AUDIO_OUTPUT_LATENCY
- if (OS::get_singleton()) {
- uint64_t ticks = OS::get_singleton()->get_ticks_usec();
- output_latency = (ticks - output_latency_ticks) / 1000000.f;
- output_latency_ticks = ticks;
- }
-
#ifdef DEBUG_ENABLED
prof_time += OS::get_singleton()->get_ticks_usec() - prof_ticks;
#endif
@@ -323,6 +338,8 @@ void AudioServer::_mix_step() {
E->get().callback(E->get().userdata);
}
+ emit_signal("audio_mix_callback");
+
for (int i = buses.size() - 1; i >= 0; i--) {
//go bus by bus
Bus *bus = buses[i];
@@ -452,6 +469,14 @@ void AudioServer::_mix_step() {
to_mix = buffer_size;
}
+bool AudioServer::thread_has_channel_mix_buffer(int p_bus, int p_buffer) const {
+ if (p_bus < 0 || p_bus >= buses.size())
+ return false;
+ if (p_buffer < 0 || p_buffer >= buses[p_bus]->channels.size())
+ return false;
+ return true;
+}
+
AudioFrame *AudioServer::thread_get_channel_mix_buffer(int p_bus, int p_buffer) {
ERR_FAIL_INDEX_V(p_bus, buses.size(), NULL);
@@ -721,6 +746,12 @@ float AudioServer::get_bus_volume_db(int p_bus) const {
return buses[p_bus]->volume_db;
}
+int AudioServer::get_bus_channels(int p_bus) const {
+
+ ERR_FAIL_INDEX_V(p_bus, buses.size(), 0);
+ return buses[p_bus]->channels.size();
+}
+
void AudioServer::set_bus_send(int p_bus, const StringName &p_send) {
ERR_FAIL_INDEX(p_bus, buses.size());
@@ -845,6 +876,15 @@ int AudioServer::get_bus_effect_count(int p_bus) {
return buses[p_bus]->effects.size();
}
+Ref<AudioEffectInstance> AudioServer::get_bus_effect_instance(int p_bus, int p_effect, int p_channel) {
+
+ ERR_FAIL_INDEX_V(p_bus, buses.size(), Ref<AudioEffectInstance>());
+ ERR_FAIL_INDEX_V(p_effect, buses[p_bus]->effects.size(), Ref<AudioEffectInstance>());
+ ERR_FAIL_INDEX_V(p_channel, buses[p_bus]->channels.size(), Ref<AudioEffectInstance>());
+
+ return buses[p_bus]->channels[p_channel].effect_instances[p_effect];
+}
+
Ref<AudioEffect> AudioServer::get_bus_effect(int p_bus, int p_effect) {
ERR_FAIL_INDEX_V(p_bus, buses.size(), Ref<AudioEffect>());
@@ -906,6 +946,15 @@ bool AudioServer::is_bus_channel_active(int p_bus, int p_channel) const {
return buses[p_bus]->channels[p_channel].active;
}
+void AudioServer::set_global_rate_scale(float p_scale) {
+
+ global_rate_scale = p_scale;
+}
+float AudioServer::get_global_rate_scale() const {
+
+ return global_rate_scale;
+}
+
void AudioServer::init_channels_and_buffers() {
channel_count = get_channel_count();
temp_buffer.resize(channel_count);
@@ -926,6 +975,7 @@ void AudioServer::init() {
channel_disable_threshold_db = GLOBAL_DEF_RST("audio/channel_disable_threshold_db", -60.0);
channel_disable_frames = float(GLOBAL_DEF_RST("audio/channel_disable_time", 2.0)) * get_mix_rate();
+ ProjectSettings::get_singleton()->set_custom_property_info("audio/channel_disable_time", PropertyInfo(Variant::REAL, "audio/channel_disable_time", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"));
buffer_size = 1024; //hardcoded for now
init_channels_and_buffers();
@@ -953,7 +1003,7 @@ void AudioServer::update() {
uint64_t driver_time = AudioDriver::get_singleton()->get_profiling_time();
uint64_t server_time = prof_time;
- // Substract the server time from the driver time
+ // Subtract the server time from the driver time
if (driver_time > server_time)
driver_time -= server_time;
@@ -971,7 +1021,7 @@ void AudioServer::update() {
values.push_back(String(bus->name) + bus->effects[j].effect->get_name());
values.push_back(USEC_TO_SEC(bus->effects[j].prof_time));
- // Substract the effect time from the driver and server times
+ // Subtract the effect time from the driver and server times
if (driver_time > bus->effects[j].prof_time)
driver_time -= bus->effects[j].prof_time;
if (server_time > bus->effects[j].prof_time)
@@ -1004,12 +1054,21 @@ void AudioServer::update() {
AudioDriver::get_singleton()->reset_profiling_time();
prof_time = 0;
#endif
+
+ for (Set<CallbackItem>::Element *E = update_callbacks.front(); E; E = E->next()) {
+
+ E->get().callback(E->get().userdata);
+ }
+
+ emit_signal("audio_update_callback");
}
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");
+ String layout_path = ProjectSettings::get_singleton()->get("audio/default_bus_layout");
+
+ if (ResourceLoader::exists(layout_path)) {
+ Ref<AudioBusLayout> default_layout = ResourceLoader::load(layout_path);
if (default_layout.is_valid()) {
set_bus_layout(default_layout);
}
@@ -1059,13 +1118,19 @@ AudioServer *AudioServer::get_singleton() {
return singleton;
}
-double AudioServer::get_mix_time() const {
+double AudioServer::get_output_latency() const {
- return 0;
+ return AudioDriver::get_singleton()->get_latency();
}
-double AudioServer::get_output_delay() const {
- return 0;
+double AudioServer::get_time_to_next_mix() const {
+
+ return AudioDriver::get_singleton()->get_time_to_next_mix();
+}
+
+double AudioServer::get_time_since_last_mix() const {
+
+ return AudioDriver::get_singleton()->get_time_since_last_mix();
}
AudioServer *AudioServer::singleton = NULL;
@@ -1129,6 +1194,25 @@ void AudioServer::remove_callback(AudioCallback p_callback, void *p_userdata) {
unlock();
}
+void AudioServer::add_update_callback(AudioCallback p_callback, void *p_userdata) {
+ lock();
+ CallbackItem ci;
+ ci.callback = p_callback;
+ ci.userdata = p_userdata;
+ update_callbacks.insert(ci);
+ unlock();
+}
+
+void AudioServer::remove_update_callback(AudioCallback p_callback, void *p_userdata) {
+
+ lock();
+ CallbackItem ci;
+ ci.callback = p_callback;
+ ci.userdata = p_userdata;
+ update_callbacks.erase(ci);
+ unlock();
+}
+
void AudioServer::set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout) {
ERR_FAIL_COND(p_bus_layout.is_null() || p_bus_layout->buses.size() == 0);
@@ -1222,6 +1306,14 @@ void AudioServer::set_device(String device) {
AudioDriver::get_singleton()->set_device(device);
}
+Error AudioServer::capture_start() {
+ return AudioDriver::get_singleton()->capture_start();
+}
+
+Error AudioServer::capture_stop() {
+ return AudioDriver::get_singleton()->capture_stop();
+}
+
Array AudioServer::capture_get_device_list() {
return AudioDriver::get_singleton()->capture_get_device_list();
@@ -1237,6 +1329,18 @@ void AudioServer::capture_set_device(const String &p_name) {
AudioDriver::get_singleton()->capture_set_device(p_name);
}
+PoolVector<int32_t> AudioServer::get_capture_buffer() {
+ return AudioDriver::get_singleton()->get_capture_buffer();
+}
+
+unsigned int AudioServer::get_capture_position() {
+ return AudioDriver::get_singleton()->get_capture_position();
+}
+
+unsigned int AudioServer::get_capture_size() {
+ return AudioDriver::get_singleton()->get_capture_size();
+}
+
void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bus_count", "amount"), &AudioServer::set_bus_count);
@@ -1250,6 +1354,8 @@ void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_bus_name", "bus_idx"), &AudioServer::get_bus_name);
ClassDB::bind_method(D_METHOD("get_bus_index", "bus_name"), &AudioServer::get_bus_index);
+ ClassDB::bind_method(D_METHOD("get_bus_channels", "bus_idx"), &AudioServer::get_bus_channels);
+
ClassDB::bind_method(D_METHOD("set_bus_volume_db", "bus_idx", "volume_db"), &AudioServer::set_bus_volume_db);
ClassDB::bind_method(D_METHOD("get_bus_volume_db", "bus_idx"), &AudioServer::get_bus_volume_db);
@@ -1270,6 +1376,7 @@ void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_bus_effect_count", "bus_idx"), &AudioServer::get_bus_effect_count);
ClassDB::bind_method(D_METHOD("get_bus_effect", "bus_idx", "effect_idx"), &AudioServer::get_bus_effect);
+ ClassDB::bind_method(D_METHOD("get_bus_effect_instance", "bus_idx", "effect_idx", "channel"), &AudioServer::get_bus_effect_instance, DEFVAL(0));
ClassDB::bind_method(D_METHOD("swap_bus_effects", "bus_idx", "effect_idx", "by_effect_idx"), &AudioServer::swap_bus_effects);
ClassDB::bind_method(D_METHOD("set_bus_effect_enabled", "bus_idx", "effect_idx", "enabled"), &AudioServer::set_bus_effect_enabled);
@@ -1278,6 +1385,9 @@ void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_bus_peak_volume_left_db", "bus_idx", "channel"), &AudioServer::get_bus_peak_volume_left_db);
ClassDB::bind_method(D_METHOD("get_bus_peak_volume_right_db", "bus_idx", "channel"), &AudioServer::get_bus_peak_volume_right_db);
+ ClassDB::bind_method(D_METHOD("set_global_rate_scale", "scale"), &AudioServer::set_global_rate_scale);
+ ClassDB::bind_method(D_METHOD("get_global_rate_scale"), &AudioServer::get_global_rate_scale);
+
ClassDB::bind_method(D_METHOD("lock"), &AudioServer::lock);
ClassDB::bind_method(D_METHOD("unlock"), &AudioServer::unlock);
@@ -1287,16 +1397,35 @@ void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_device"), &AudioServer::get_device);
ClassDB::bind_method(D_METHOD("set_device", "device"), &AudioServer::set_device);
+ ClassDB::bind_method(D_METHOD("get_time_to_next_mix"), &AudioServer::get_time_to_next_mix);
+ ClassDB::bind_method(D_METHOD("get_time_since_last_mix"), &AudioServer::get_time_since_last_mix);
+ ClassDB::bind_method(D_METHOD("get_output_latency"), &AudioServer::get_output_latency);
+
+ ClassDB::bind_method(D_METHOD("capture_start"), &AudioServer::capture_start);
+ ClassDB::bind_method(D_METHOD("capture_stop"), &AudioServer::capture_stop);
+
ClassDB::bind_method(D_METHOD("capture_get_device_list"), &AudioServer::capture_get_device_list);
ClassDB::bind_method(D_METHOD("capture_get_device"), &AudioServer::capture_get_device);
ClassDB::bind_method(D_METHOD("capture_set_device", "name"), &AudioServer::capture_set_device);
+ ClassDB::bind_method(D_METHOD("get_capture_buffer"), &AudioServer::get_capture_buffer);
+ ClassDB::bind_method(D_METHOD("get_capture_position"), &AudioServer::get_capture_position);
+ ClassDB::bind_method(D_METHOD("get_capture_size"), &AudioServer::get_capture_size);
+
ClassDB::bind_method(D_METHOD("set_bus_layout", "bus_layout"), &AudioServer::set_bus_layout);
ClassDB::bind_method(D_METHOD("generate_bus_layout"), &AudioServer::generate_bus_layout);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "bus_count"), "set_bus_count", "get_bus_count");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "device"), "set_device", "get_device");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "capture_device"), "capture_set_device", "capture_get_device");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "global_rate_scale"), "set_global_rate_scale", "get_global_rate_scale");
+
ADD_SIGNAL(MethodInfo("bus_layout_changed"));
+ ADD_SIGNAL(MethodInfo("audio_mix_callback"));
+ ADD_SIGNAL(MethodInfo("audio_update_callback"));
BIND_ENUM_CONSTANT(SPEAKER_MODE_STEREO);
+ BIND_ENUM_CONSTANT(SPEAKER_SURROUND_31);
BIND_ENUM_CONSTANT(SPEAKER_SURROUND_51);
BIND_ENUM_CONSTANT(SPEAKER_SURROUND_71);
}
@@ -1315,6 +1444,9 @@ AudioServer::AudioServer() {
#ifdef DEBUG_ENABLED
prof_time = 0;
#endif
+ mix_time = 0;
+ mix_size = 0;
+ global_rate_scale = 1;
}
AudioServer::~AudioServer() {
diff --git a/servers/audio_server.h b/servers/audio_server.h
index ba6569eb38..72bb6faf42 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -45,7 +45,7 @@ class AudioDriver {
static AudioDriver *singleton;
uint64_t _last_mix_time;
- uint64_t _mix_amount;
+ uint64_t _last_mix_frames;
#ifdef DEBUG_ENABLED
uint64_t prof_ticks;
@@ -53,13 +53,14 @@ class AudioDriver {
#endif
protected:
- Vector<int32_t> input_buffer;
- unsigned int input_position;
- unsigned int input_size;
+ PoolVector<int32_t> capture_buffer;
+ unsigned int capture_position;
+ unsigned int capture_size;
void audio_server_process(int p_frames, int32_t *p_buffer, bool p_update_mix_time = true);
void update_mix_time(int p_frames);
- void input_buffer_write(int32_t sample);
+ void capture_buffer_init(int driver_buffer_frames);
+ void capture_buffer_write(int32_t sample);
#ifdef DEBUG_ENABLED
_FORCE_INLINE_ void start_counting_ticks() { prof_ticks = OS::get_singleton()->get_ticks_usec(); }
@@ -70,7 +71,8 @@ protected:
#endif
public:
- double get_mix_time() const; //useful for video -> audio sync
+ double get_time_since_last_mix() const; //useful for video -> audio sync
+ double get_time_to_next_mix() const;
enum SpeakerMode {
SPEAKER_MODE_STEREO,
@@ -109,9 +111,9 @@ public:
SpeakerMode get_speaker_mode_by_total_channels(int p_channels) const;
int get_total_channels_by_speaker_mode(SpeakerMode) const;
- Vector<int32_t> get_input_buffer() { return input_buffer; }
- unsigned int get_input_position() { return input_position; }
- unsigned int get_input_size() { return input_size; }
+ PoolVector<int32_t> get_capture_buffer() { return capture_buffer; }
+ unsigned int get_capture_position() { return capture_position; }
+ unsigned int get_capture_size() { return capture_size; }
#ifdef DEBUG_ENABLED
uint64_t get_profiling_time() const { return prof_time; }
@@ -145,9 +147,10 @@ class AudioBusLayout;
class AudioServer : public Object {
- GDCLASS(AudioServer, Object)
+ GDCLASS(AudioServer, Object);
+
public:
- //re-expose this her, as AudioDriver is not exposed to script
+ //re-expose this here, as AudioDriver is not exposed to script
enum SpeakerMode {
SPEAKER_MODE_STEREO,
SPEAKER_SURROUND_31,
@@ -162,6 +165,9 @@ public:
typedef void (*AudioCallback)(void *p_userdata);
private:
+ uint64_t mix_time;
+ int mix_size;
+
uint32_t buffer_size;
uint64_t mix_count;
uint64_t mix_frames;
@@ -175,6 +181,8 @@ private:
int channel_count;
int to_mix;
+ float global_rate_scale;
+
struct Bus {
StringName name;
@@ -262,6 +270,7 @@ private:
};
Set<CallbackItem> callbacks;
+ Set<CallbackItem> update_callbacks;
friend class AudioDriver;
void _driver_process(int p_frames, int32_t *p_buffer);
@@ -281,6 +290,7 @@ public:
}
//do not use from outside audio thread
+ bool thread_has_channel_mix_buffer(int p_bus, int p_buffer) const;
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);
@@ -297,6 +307,8 @@ public:
String get_bus_name(int p_bus) const;
int get_bus_index(const StringName &p_bus_name) const;
+ int get_bus_channels(int p_bus) const;
+
void set_bus_volume_db(int p_bus, float p_volume_db);
float get_bus_volume_db(int p_bus) const;
@@ -317,6 +329,7 @@ public:
int get_bus_effect_count(int p_bus);
Ref<AudioEffect> get_bus_effect(int p_bus, int p_effect);
+ Ref<AudioEffectInstance> get_bus_effect_instance(int p_bus, int p_effect, int p_channel = 0);
void swap_bus_effects(int p_bus, int p_effect, int p_by_effect);
@@ -328,6 +341,9 @@ public:
bool is_bus_channel_active(int p_bus, int p_channel) const;
+ void set_global_rate_scale(float p_scale);
+ float get_global_rate_scale() const;
+
virtual void init();
virtual void finish();
virtual void update();
@@ -345,8 +361,9 @@ public:
static AudioServer *get_singleton();
- virtual double get_mix_time() const; //useful for video -> audio sync
- virtual double get_output_delay() const;
+ virtual double get_output_latency() const;
+ virtual double get_time_to_next_mix() const;
+ virtual double get_time_since_last_mix() const;
void *audio_data_alloc(uint32_t p_data_len, const uint8_t *p_from_data = NULL);
void audio_data_free(void *p_data);
@@ -357,6 +374,9 @@ public:
void add_callback(AudioCallback p_callback, void *p_userdata);
void remove_callback(AudioCallback p_callback, void *p_userdata);
+ void add_update_callback(AudioCallback p_callback, void *p_userdata);
+ void remove_update_callback(AudioCallback p_callback, void *p_userdata);
+
void set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout);
Ref<AudioBusLayout> generate_bus_layout() const;
@@ -364,11 +384,17 @@ public:
String get_device();
void set_device(String device);
+ Error capture_start();
+ Error capture_stop();
+
Array capture_get_device_list();
String capture_get_device();
void capture_set_device(const String &p_name);
- float get_output_latency() { return output_latency; }
+ PoolVector<int32_t> get_capture_buffer();
+ unsigned int get_capture_position();
+ unsigned int get_capture_size();
+
AudioServer();
virtual ~AudioServer();
};
@@ -377,7 +403,7 @@ VARIANT_ENUM_CAST(AudioServer::SpeakerMode)
class AudioBusLayout : public Resource {
- GDCLASS(AudioBusLayout, Resource)
+ GDCLASS(AudioBusLayout, Resource);
friend class AudioServer;
diff --git a/servers/camera/SCsub b/servers/camera/SCsub
new file mode 100644
index 0000000000..ccc76e823f
--- /dev/null
+++ b/servers/camera/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/camera/camera_feed.cpp b/servers/camera/camera_feed.cpp
new file mode 100644
index 0000000000..094c83cd7c
--- /dev/null
+++ b/servers/camera/camera_feed.cpp
@@ -0,0 +1,266 @@
+/*************************************************************************/
+/* camera_feed.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "camera_feed.h"
+#include "servers/visual_server.h"
+
+void CameraFeed::_bind_methods() {
+ // The setters prefixed with _ are only exposed so we can have feeds through GDNative!
+ // They should not be called by the end user.
+
+ ClassDB::bind_method(D_METHOD("get_id"), &CameraFeed::get_id);
+ ClassDB::bind_method(D_METHOD("get_name"), &CameraFeed::get_name);
+ ClassDB::bind_method(D_METHOD("_set_name", "name"), &CameraFeed::set_name);
+
+ ClassDB::bind_method(D_METHOD("is_active"), &CameraFeed::is_active);
+ ClassDB::bind_method(D_METHOD("set_active", "active"), &CameraFeed::set_active);
+
+ ClassDB::bind_method(D_METHOD("get_position"), &CameraFeed::get_position);
+ ClassDB::bind_method(D_METHOD("_set_position", "position"), &CameraFeed::set_position);
+
+ // Note, for transform some feeds may override what the user sets (such as ARKit)
+ ClassDB::bind_method(D_METHOD("get_transform"), &CameraFeed::get_transform);
+ ClassDB::bind_method(D_METHOD("set_transform", "transform"), &CameraFeed::set_transform);
+
+ ClassDB::bind_method(D_METHOD("_set_RGB_img", "rgb_img"), &CameraFeed::set_RGB_img);
+ ClassDB::bind_method(D_METHOD("_set_YCbCr_img", "ycbcr_img"), &CameraFeed::set_YCbCr_img);
+ ClassDB::bind_method(D_METHOD("_set_YCbCr_imgs", "y_img", "cbcr_img"), &CameraFeed::set_YCbCr_imgs);
+ ClassDB::bind_method(D_METHOD("_allocate_texture", "width", "height", "format", "texture_type", "data_type"), &CameraFeed::allocate_texture);
+
+ ADD_GROUP("Feed", "feed_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "feed_is_active"), "set_active", "is_active");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "feed_transform"), "set_transform", "get_transform");
+
+ BIND_ENUM_CONSTANT(FEED_NOIMAGE);
+ BIND_ENUM_CONSTANT(FEED_RGB);
+ BIND_ENUM_CONSTANT(FEED_YCBCR);
+ BIND_ENUM_CONSTANT(FEED_YCBCR_SEP);
+
+ BIND_ENUM_CONSTANT(FEED_UNSPECIFIED);
+ BIND_ENUM_CONSTANT(FEED_FRONT);
+ BIND_ENUM_CONSTANT(FEED_BACK);
+}
+
+int CameraFeed::get_id() const {
+ return id;
+}
+
+bool CameraFeed::is_active() const {
+ return active;
+}
+
+void CameraFeed::set_active(bool p_is_active) {
+ if (p_is_active == active) {
+ // all good
+ } else if (p_is_active) {
+ // attempt to activate this feed
+ if (activate_feed()) {
+ print_line("Activate " + name);
+ active = true;
+ }
+ } else {
+ // just deactivate it
+ deactivate_feed();
+ print_line("Deactivate " + name);
+ active = false;
+ }
+}
+
+String CameraFeed::get_name() const {
+ return name;
+}
+
+void CameraFeed::set_name(String p_name) {
+ name = p_name;
+}
+
+int CameraFeed::get_base_width() const {
+ return base_width;
+}
+
+int CameraFeed::get_base_height() const {
+ return base_height;
+}
+
+CameraFeed::FeedDataType CameraFeed::get_datatype() const {
+ return datatype;
+}
+
+CameraFeed::FeedPosition CameraFeed::get_position() const {
+ return position;
+}
+
+void CameraFeed::set_position(CameraFeed::FeedPosition p_position) {
+ position = p_position;
+}
+
+Transform2D CameraFeed::get_transform() const {
+ return transform;
+}
+
+void CameraFeed::set_transform(const Transform2D &p_transform) {
+ transform = p_transform;
+}
+
+RID CameraFeed::get_texture(CameraServer::FeedImage p_which) {
+ return texture[p_which];
+}
+
+CameraFeed::CameraFeed() {
+ // initialize our feed
+ id = CameraServer::get_singleton()->get_free_id();
+ name = "???";
+ active = false;
+ datatype = CameraFeed::FEED_RGB;
+ position = CameraFeed::FEED_UNSPECIFIED;
+ transform = Transform2D(1.0, 0.0, 0.0, -1.0, 0.0, 1.0);
+
+ // create a texture object
+ VisualServer *vs = VisualServer::get_singleton();
+ texture[CameraServer::FEED_Y_IMAGE] = vs->texture_create(); // also used for RGBA
+ texture[CameraServer::FEED_CBCR_IMAGE] = vs->texture_create();
+}
+
+CameraFeed::CameraFeed(String p_name, FeedPosition p_position) {
+ // initialize our feed
+ id = CameraServer::get_singleton()->get_free_id();
+ base_width = 0;
+ base_height = 0;
+ name = p_name;
+ active = false;
+ datatype = CameraFeed::FEED_NOIMAGE;
+ position = p_position;
+ transform = Transform2D(1.0, 0.0, 0.0, -1.0, 0.0, 1.0);
+
+ // create a texture object
+ VisualServer *vs = VisualServer::get_singleton();
+ texture[CameraServer::FEED_Y_IMAGE] = vs->texture_create(); // also used for RGBA
+ texture[CameraServer::FEED_CBCR_IMAGE] = vs->texture_create();
+}
+
+CameraFeed::~CameraFeed() {
+ // Free our textures
+ VisualServer *vs = VisualServer::get_singleton();
+ vs->free(texture[CameraServer::FEED_Y_IMAGE]);
+ vs->free(texture[CameraServer::FEED_CBCR_IMAGE]);
+}
+
+void CameraFeed::set_RGB_img(Ref<Image> p_rgb_img) {
+ if (active) {
+ VisualServer *vs = VisualServer::get_singleton();
+
+ int new_width = p_rgb_img->get_width();
+ int new_height = p_rgb_img->get_height();
+
+ if ((base_width != new_width) || (base_height != new_height)) {
+ // We're assuming here that our camera image doesn't change around formats etc, allocate the whole lot...
+ base_width = new_width;
+ base_height = new_height;
+
+ vs->texture_allocate(texture[CameraServer::FEED_RGBA_IMAGE], new_width, new_height, 0, Image::FORMAT_RGB8, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAGS_DEFAULT);
+ }
+
+ vs->texture_set_data(texture[CameraServer::FEED_RGBA_IMAGE], p_rgb_img);
+ datatype = CameraFeed::FEED_RGB;
+ }
+}
+
+void CameraFeed::set_YCbCr_img(Ref<Image> p_ycbcr_img) {
+ if (active) {
+ VisualServer *vs = VisualServer::get_singleton();
+
+ int new_width = p_ycbcr_img->get_width();
+ int new_height = p_ycbcr_img->get_height();
+
+ if ((base_width != new_width) || (base_height != new_height)) {
+ // We're assuming here that our camera image doesn't change around formats etc, allocate the whole lot...
+ base_width = new_width;
+ base_height = new_height;
+
+ vs->texture_allocate(texture[CameraServer::FEED_RGBA_IMAGE], new_width, new_height, 0, Image::FORMAT_RGB8, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAGS_DEFAULT);
+ }
+
+ vs->texture_set_data(texture[CameraServer::FEED_RGBA_IMAGE], p_ycbcr_img);
+ datatype = CameraFeed::FEED_YCBCR;
+ }
+}
+
+void CameraFeed::set_YCbCr_imgs(Ref<Image> p_y_img, Ref<Image> p_cbcr_img) {
+ if (active) {
+ VisualServer *vs = VisualServer::get_singleton();
+
+ ///@TODO investigate whether we can use thirdparty/misc/yuv2rgb.h here to convert our YUV data to RGB, our shader approach is potentially faster though..
+ // Wondering about including that into multiple projects, may cause issues.
+ // That said, if we convert to RGB, we could enable using texture resources again...
+
+ int new_y_width = p_y_img->get_width();
+ int new_y_height = p_y_img->get_height();
+ int new_cbcr_width = p_cbcr_img->get_width();
+ int new_cbcr_height = p_cbcr_img->get_height();
+
+ if ((base_width != new_y_width) || (base_height != new_y_height)) {
+ // We're assuming here that our camera image doesn't change around formats etc, allocate the whole lot...
+ base_width = new_y_width;
+ base_height = new_y_height;
+
+ vs->texture_allocate(texture[CameraServer::FEED_Y_IMAGE], new_y_width, new_y_height, 0, Image::FORMAT_R8, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_USED_FOR_STREAMING);
+
+ ///@TODO GLES2 doesn't support FORMAT_RG8, need to do some form of conversion
+ vs->texture_allocate(texture[CameraServer::FEED_CBCR_IMAGE], new_cbcr_width, new_cbcr_height, 0, Image::FORMAT_RG8, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_USED_FOR_STREAMING);
+ }
+
+ vs->texture_set_data(texture[CameraServer::FEED_Y_IMAGE], p_y_img);
+ vs->texture_set_data(texture[CameraServer::FEED_CBCR_IMAGE], p_cbcr_img);
+ datatype = CameraFeed::FEED_YCBCR_SEP;
+ }
+}
+
+void CameraFeed::allocate_texture(int p_width, int p_height, Image::Format p_format, VisualServer::TextureType p_texture_type, FeedDataType p_data_type) {
+ VisualServer *vs = VisualServer::get_singleton();
+
+ if ((base_width != p_width) || (base_height != p_height)) {
+ // We're assuming here that our camera image doesn't change around formats etc, allocate the whole lot...
+ base_width = p_width;
+ base_height = p_height;
+
+ vs->texture_allocate(texture[0], p_width, p_height, 0, p_format, p_texture_type, VS::TEXTURE_FLAGS_DEFAULT);
+ }
+
+ datatype = p_data_type;
+}
+
+bool CameraFeed::activate_feed() {
+ // nothing to do here
+ return true;
+}
+
+void CameraFeed::deactivate_feed() {
+ // nothing to do here
+}
diff --git a/servers/camera/camera_feed.h b/servers/camera/camera_feed.h
new file mode 100644
index 0000000000..0c53ff9309
--- /dev/null
+++ b/servers/camera/camera_feed.h
@@ -0,0 +1,115 @@
+/*************************************************************************/
+/* camera_feed.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef CAMERA_FEED_H
+#define CAMERA_FEED_H
+
+#include "core/image.h"
+#include "core/math/transform_2d.h"
+#include "servers/camera_server.h"
+#include "servers/visual_server.h"
+
+/**
+ @author Bastiaan Olij <mux213@gmail.com>
+
+ The camera server is a singleton object that gives access to the various
+ camera feeds that can be used as the background for our environment.
+**/
+
+class CameraFeed : public Reference {
+ GDCLASS(CameraFeed, Reference);
+
+public:
+ enum FeedDataType {
+ FEED_NOIMAGE, // we don't have an image yet
+ FEED_RGB, // our texture will contain a normal RGB texture that can be used directly
+ FEED_YCBCR, // our texture will contain a YCbCr texture that needs to be converted to RGB before output
+ FEED_YCBCR_SEP // our camera is split into two textures, first plane contains Y data, second plane contains CbCr data
+ };
+
+ enum FeedPosition {
+ FEED_UNSPECIFIED, // we have no idea
+ FEED_FRONT, // this is a camera on the front of the device
+ FEED_BACK // this is a camera on the back of the device
+ };
+
+private:
+ int id; // unique id for this, for internal use in case feeds are removed
+ int base_width;
+ int base_height;
+
+protected:
+ String name; // name of our camera feed
+ FeedDataType datatype; // type of texture data stored
+ FeedPosition position; // position of camera on the device
+ Transform2D transform; // display transform
+
+ bool active; // only when active do we actually update the camera texture each frame
+ RID texture[CameraServer::FEED_IMAGES]; // texture images needed for this
+
+ static void _bind_methods();
+
+public:
+ int get_id() const;
+ bool is_active() const;
+ void set_active(bool p_is_active);
+
+ String get_name() const;
+ void set_name(String p_name);
+
+ int get_base_width() const;
+ int get_base_height() const;
+
+ FeedPosition get_position() const;
+ void set_position(FeedPosition p_position);
+
+ Transform2D get_transform() const;
+ void set_transform(const Transform2D &p_transform);
+
+ RID get_texture(CameraServer::FeedImage p_which);
+
+ CameraFeed();
+ CameraFeed(String p_name, FeedPosition p_position = CameraFeed::FEED_UNSPECIFIED);
+ virtual ~CameraFeed();
+
+ FeedDataType get_datatype() const;
+ void set_RGB_img(Ref<Image> p_rgb_img);
+ void set_YCbCr_img(Ref<Image> p_ycbcr_img);
+ void set_YCbCr_imgs(Ref<Image> p_y_img, Ref<Image> p_cbcr_img);
+ void allocate_texture(int p_width, int p_height, Image::Format p_format, VisualServer::TextureType p_texture_type, FeedDataType p_data_type);
+
+ virtual bool activate_feed();
+ virtual void deactivate_feed();
+};
+
+VARIANT_ENUM_CAST(CameraFeed::FeedDataType);
+VARIANT_ENUM_CAST(CameraFeed::FeedPosition);
+
+#endif /* !CAMERA_FEED_H */
diff --git a/servers/camera_server.cpp b/servers/camera_server.cpp
new file mode 100644
index 0000000000..0f93221072
--- /dev/null
+++ b/servers/camera_server.cpp
@@ -0,0 +1,169 @@
+/*************************************************************************/
+/* camera_server.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "camera_server.h"
+#include "servers/camera/camera_feed.h"
+#include "visual_server.h"
+
+////////////////////////////////////////////////////////
+// CameraServer
+
+void CameraServer::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_feed", "index"), &CameraServer::get_feed);
+ ClassDB::bind_method(D_METHOD("get_feed_count"), &CameraServer::get_feed_count);
+ ClassDB::bind_method(D_METHOD("feeds"), &CameraServer::get_feeds);
+
+ ClassDB::bind_method(D_METHOD("add_feed", "feed"), &CameraServer::add_feed);
+ ClassDB::bind_method(D_METHOD("remove_feed", "feed"), &CameraServer::remove_feed);
+
+ ADD_SIGNAL(MethodInfo("camera_feed_added", PropertyInfo(Variant::INT, "id")));
+ ADD_SIGNAL(MethodInfo("camera_feed_removed", PropertyInfo(Variant::INT, "id")));
+
+ BIND_ENUM_CONSTANT(FEED_RGBA_IMAGE);
+ BIND_ENUM_CONSTANT(FEED_YCBCR_IMAGE);
+ BIND_ENUM_CONSTANT(FEED_Y_IMAGE);
+ BIND_ENUM_CONSTANT(FEED_CBCR_IMAGE);
+};
+
+CameraServer *CameraServer::singleton = NULL;
+
+CameraServer *CameraServer::get_singleton() {
+ return singleton;
+};
+
+int CameraServer::get_free_id() {
+ bool id_exists = true;
+ int newid = 0;
+
+ // find a free id
+ while (id_exists) {
+ newid++;
+ id_exists = false;
+ for (int i = 0; i < feeds.size() && !id_exists; i++) {
+ if (feeds[i]->get_id() == newid) {
+ id_exists = true;
+ };
+ };
+ };
+
+ return newid;
+};
+
+int CameraServer::get_feed_index(int p_id) {
+ for (int i = 0; i < feeds.size(); i++) {
+ if (feeds[i]->get_id() == p_id) {
+ return i;
+ };
+ };
+
+ return -1;
+};
+
+Ref<CameraFeed> CameraServer::get_feed_by_id(int p_id) {
+ int index = get_feed_index(p_id);
+
+ if (index == -1) {
+ return NULL;
+ } else {
+ return feeds[index];
+ }
+};
+
+void CameraServer::add_feed(const Ref<CameraFeed> &p_feed) {
+ // add our feed
+ feeds.push_back(p_feed);
+
+// record for debugging
+#ifdef DEBUG_ENABLED
+ print_line("Registered camera " + p_feed->get_name() + " with id " + itos(p_feed->get_id()) + " position " + itos(p_feed->get_position()) + " at index " + itos(feeds.size() - 1));
+#endif
+
+ // let whomever is interested know
+ emit_signal("camera_feed_added", p_feed->get_id());
+};
+
+void CameraServer::remove_feed(const Ref<CameraFeed> &p_feed) {
+ for (int i = 0; i < feeds.size(); i++) {
+ if (feeds[i] == p_feed) {
+ int feed_id = p_feed->get_id();
+
+// record for debugging
+#ifdef DEBUG_ENABLED
+ print_line("Removed camera " + p_feed->get_name() + " with id " + itos(feed_id) + " position " + itos(p_feed->get_position()));
+#endif
+
+ // remove it from our array, if this results in our feed being unreferenced it will be destroyed
+ feeds.remove(i);
+
+ // let whomever is interested know
+ emit_signal("camera_feed_removed", feed_id);
+ return;
+ };
+ };
+};
+
+Ref<CameraFeed> CameraServer::get_feed(int p_index) {
+ ERR_FAIL_INDEX_V(p_index, feeds.size(), NULL);
+
+ return feeds[p_index];
+};
+
+int CameraServer::get_feed_count() {
+ return feeds.size();
+};
+
+Array CameraServer::get_feeds() {
+ Array return_feeds;
+ int cc = get_feed_count();
+ return_feeds.resize(cc);
+
+ for (int i = 0; i < feeds.size(); i++) {
+ return_feeds[i] = get_feed(i);
+ };
+
+ return return_feeds;
+};
+
+RID CameraServer::feed_texture(int p_id, CameraServer::FeedImage p_texture) {
+ int index = get_feed_index(p_id);
+ ERR_FAIL_COND_V(index == -1, RID());
+
+ Ref<CameraFeed> feed = get_feed(index);
+
+ return feed->get_texture(p_texture);
+};
+
+CameraServer::CameraServer() {
+ singleton = this;
+};
+
+CameraServer::~CameraServer() {
+ singleton = NULL;
+};
diff --git a/servers/camera_server.h b/servers/camera_server.h
new file mode 100644
index 0000000000..c76d046e58
--- /dev/null
+++ b/servers/camera_server.h
@@ -0,0 +1,96 @@
+/*************************************************************************/
+/* camera_server.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef CAMERA_SERVER_H
+#define CAMERA_SERVER_H
+
+#include "core/object.h"
+#include "core/os/thread_safe.h"
+#include "core/reference.h"
+#include "core/rid.h"
+#include "core/variant.h"
+
+/**
+ @author Bastiaan Olij <mux213@gmail.com>
+
+ The camera server is a singleton object that gives access to the various
+ camera feeds that can be used as the background for our environment.
+**/
+
+class CameraFeed;
+
+class CameraServer : public Object {
+ GDCLASS(CameraServer, Object);
+ _THREAD_SAFE_CLASS_
+
+public:
+ enum FeedImage {
+ FEED_RGBA_IMAGE = 0,
+ FEED_YCBCR_IMAGE = 0,
+ FEED_Y_IMAGE = 0,
+ FEED_CBCR_IMAGE = 1,
+ FEED_IMAGES = 2
+ };
+
+private:
+protected:
+ Vector<Ref<CameraFeed> > feeds;
+
+ static CameraServer *singleton;
+
+ static void _bind_methods();
+
+public:
+ static CameraServer *get_singleton();
+
+ // Right now we identify our feed by it's ID when it's used in the background.
+ // May see if we can change this to purely relying on CameraFeed objects or by name.
+ int get_free_id();
+ int get_feed_index(int p_id);
+ Ref<CameraFeed> get_feed_by_id(int p_id);
+
+ // add and remove feeds
+ void add_feed(const Ref<CameraFeed> &p_feed);
+ void remove_feed(const Ref<CameraFeed> &p_feed);
+
+ // get our feeds
+ Ref<CameraFeed> get_feed(int p_index);
+ int get_feed_count();
+ Array get_feeds();
+
+ RID feed_texture(int p_id, FeedImage p_texture);
+
+ CameraServer();
+ ~CameraServer();
+};
+
+VARIANT_ENUM_CAST(CameraServer::FeedImage);
+
+#endif /* CAMERA_SERVER_H */
diff --git a/servers/physics/SCsub b/servers/physics/SCsub
index c0ee2cc739..c5cc889112 100644
--- a/servers/physics/SCsub
+++ b/servers/physics/SCsub
@@ -4,6 +4,4 @@ Import('env')
env.add_source_files(env.servers_sources, "*.cpp")
-Export('env')
-
SConscript("joints/SCsub")
diff --git a/servers/physics/area_pair_sw.cpp b/servers/physics/area_pair_sw.cpp
index d2fef0ab77..fed24e0b58 100644
--- a/servers/physics/area_pair_sw.cpp
+++ b/servers/physics/area_pair_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -147,10 +147,10 @@ Area2PairSW::~Area2PairSW() {
if (colliding) {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable())
+ if (area_b->has_area_monitor_callback())
area_b->remove_area_from_query(area_a, shape_a, shape_b);
- if (area_a->has_area_monitor_callback() && area_b->is_monitorable())
+ if (area_a->has_area_monitor_callback())
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}
diff --git a/servers/physics/area_pair_sw.h b/servers/physics/area_pair_sw.h
index b66599dd11..48113d0580 100644
--- a/servers/physics/area_pair_sw.h
+++ b/servers/physics/area_pair_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/area_sw.cpp b/servers/physics/area_sw.cpp
index 8f9d4075b8..ad3e40916d 100644
--- a/servers/physics/area_sw.cpp
+++ b/servers/physics/area_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -250,7 +250,7 @@ AreaSW::AreaSW() :
gravity_is_point = false;
gravity_distance_scale = 0;
point_attenuation = 1;
- angular_damp = 1.0;
+ angular_damp = 0.1;
linear_damp = 0.1;
priority = 0;
set_ray_pickable(false);
diff --git a/servers/physics/area_sw.h b/servers/physics/area_sw.h
index 63a4db5d02..9b14055507 100644
--- a/servers/physics/area_sw.h
+++ b/servers/physics/area_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/body_pair_sw.cpp b/servers/physics/body_pair_sw.cpp
index 357fc05355..dbe4fbd700 100644
--- a/servers/physics/body_pair_sw.cpp
+++ b/servers/physics/body_pair_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/body_pair_sw.h b/servers/physics/body_pair_sw.h
index fd85d77718..cd2355d5a1 100644
--- a/servers/physics/body_pair_sw.h
+++ b/servers/physics/body_pair_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -76,7 +76,6 @@ class BodyPairSW : public ConstraintSW {
Contact contacts[MAX_CONTACTS];
int contact_count;
bool collided;
- int cc;
static void _contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata);
diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp
index cc9681193c..a3bb581cb5 100644
--- a/servers/physics/body_sw.cpp
+++ b/servers/physics/body_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -87,6 +87,10 @@ void BodySW::update_inertias() {
for (int i = 0; i < get_shape_count(); i++) {
+ if (is_shape_disabled(i)) {
+ continue;
+ }
+
const ShapeSW *shape = get_shape(i);
real_t area = get_shape_area(i);
@@ -192,7 +196,8 @@ void BodySW::set_param(PhysicsServer::BodyParameter p_param, real_t p_value) {
angular_damp = p_value;
} break;
- default: {}
+ default: {
+ }
}
}
@@ -222,7 +227,8 @@ real_t BodySW::get_param(PhysicsServer::BodyParameter p_param) const {
return angular_damp;
} break;
- default: {}
+ default: {
+ }
}
return 0;
@@ -260,6 +266,7 @@ void BodySW::set_mode(PhysicsServer::BodyMode p_mode) {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
_set_static(false);
+ angular_velocity = Vector3();
} break;
}
@@ -340,8 +347,7 @@ void BodySW::set_state(PhysicsServer::BodyState p_state, const Variant &p_varian
//biased_angular_velocity=Vector3();
set_active(false);
} else {
- if (mode != PhysicsServer::BODY_MODE_STATIC)
- set_active(true);
+ set_active(true);
}
} break;
case PhysicsServer::BODY_STATE_CAN_SLEEP: {
@@ -470,7 +476,8 @@ void BodySW::integrate_forces(real_t p_step) {
_compute_area_gravity_and_dampenings(aa[i].area);
stopped = mode == PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE;
} break;
- default: {}
+ default: {
+ }
}
}
}
@@ -648,7 +655,7 @@ void BodySW::simulate_motion(const Transform& p_xform,real_t p_step) {
linear_velocity=(p_xform.origin - get_transform().origin)/p_step;
//compute a FAKE angular velocity, not so easy
- Matrix3 rot=get_transform().basis.orthonormalized().transposed() * p_xform.basis.orthonormalized();
+ Basis rot=get_transform().basis.orthonormalized().transposed() * p_xform.basis.orthonormalized();
Vector3 axis;
real_t angle;
@@ -755,10 +762,10 @@ void BodySW::set_kinematic_margin(real_t p_margin) {
BodySW::BodySW() :
CollisionObjectSW(TYPE_BODY),
+ locked_axis(0),
active_list(this),
inertia_update_list(this),
- direct_state_query_list(this),
- locked_axis(0) {
+ direct_state_query_list(this) {
mode = PhysicsServer::BODY_MODE_RIGID;
active = true;
diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h
index 0f7797254e..05c61639de 100644
--- a/servers/physics/body_sw.h
+++ b/servers/physics/body_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/broad_phase_basic.cpp b/servers/physics/broad_phase_basic.cpp
index d55951b39a..13b91f2be9 100644
--- a/servers/physics/broad_phase_basic.cpp
+++ b/servers/physics/broad_phase_basic.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/broad_phase_basic.h b/servers/physics/broad_phase_basic.h
index 500b8544a1..3d63a70074 100644
--- a/servers/physics/broad_phase_basic.h
+++ b/servers/physics/broad_phase_basic.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/broad_phase_octree.cpp b/servers/physics/broad_phase_octree.cpp
index 7f43fbdb6a..1b59779bd6 100644
--- a/servers/physics/broad_phase_octree.cpp
+++ b/servers/physics/broad_phase_octree.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -45,7 +45,7 @@ void BroadPhaseOctree::move(ID p_id, const AABB &p_aabb) {
void BroadPhaseOctree::set_static(ID p_id, bool p_static) {
CollisionObjectSW *it = octree.get(p_id);
- octree.set_pairable(p_id, p_static ? false : true, 1 << it->get_type(), p_static ? 0 : 0xFFFFF); //pair everything, don't care 1?
+ octree.set_pairable(p_id, !p_static, 1 << it->get_type(), p_static ? 0 : 0xFFFFF); //pair everything, don't care 1?
}
void BroadPhaseOctree::remove(ID p_id) {
diff --git a/servers/physics/broad_phase_octree.h b/servers/physics/broad_phase_octree.h
index c4b8ecb299..f4b5d3f2a7 100644
--- a/servers/physics/broad_phase_octree.h
+++ b/servers/physics/broad_phase_octree.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/broad_phase_sw.cpp b/servers/physics/broad_phase_sw.cpp
index 2a490c3e80..f90520d373 100644
--- a/servers/physics/broad_phase_sw.cpp
+++ b/servers/physics/broad_phase_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/broad_phase_sw.h b/servers/physics/broad_phase_sw.h
index 2db1c1dd06..9ffbd8986b 100644
--- a/servers/physics/broad_phase_sw.h
+++ b/servers/physics/broad_phase_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/collision_object_sw.cpp b/servers/physics/collision_object_sw.cpp
index 09f72ff39b..39de440da2 100644
--- a/servers/physics/collision_object_sw.cpp
+++ b/servers/physics/collision_object_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,13 +32,14 @@
#include "servers/physics/physics_server_sw.h"
#include "space_sw.h"
-void CollisionObjectSW::add_shape(ShapeSW *p_shape, const Transform &p_transform) {
+void CollisionObjectSW::add_shape(ShapeSW *p_shape, const Transform &p_transform, bool p_disabled) {
Shape s;
s.shape = p_shape;
s.xform = p_transform;
s.xform_inv = s.xform.affine_inverse();
s.bpid = 0; //needs update
+ s.disabled = p_disabled;
shapes.push_back(s);
p_shape->add_owner(this);
@@ -75,6 +76,13 @@ void CollisionObjectSW::set_shape_transform(int p_index, const Transform &p_tran
//_shapes_changed();
}
+void CollisionObjectSW::set_shape_as_disabled(int p_idx, bool p_enable) {
+ shapes.write[p_idx].disabled = p_enable;
+ if (!pending_shape_update_list.in_list()) {
+ PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list);
+ }
+}
+
void CollisionObjectSW::remove_shape(ShapeSW *p_shape) {
//remove a shape, all the times it appears
diff --git a/servers/physics/collision_object_sw.h b/servers/physics/collision_object_sw.h
index 993799ee10..08708e2f60 100644
--- a/servers/physics/collision_object_sw.h
+++ b/servers/physics/collision_object_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -86,13 +86,9 @@ protected:
void _unregister_shapes();
_FORCE_INLINE_ void _set_transform(const Transform &p_transform, bool p_update_shapes = true) {
-
#ifdef DEBUG_ENABLED
- if (p_transform.origin.length_squared() > MAX_OBJECT_DISTANCE_X2) {
- ERR_EXPLAIN("Object went too far away (more than " + itos(MAX_OBJECT_DISTANCE) + "mts from origin).");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(p_transform.origin.length_squared() > MAX_OBJECT_DISTANCE_X2, "Object went too far away (more than '" + itos(MAX_OBJECT_DISTANCE) + "' units from origin).");
#endif
transform = p_transform;
@@ -118,15 +114,19 @@ public:
void _shape_changed();
_FORCE_INLINE_ Type get_type() const { return type; }
- void add_shape(ShapeSW *p_shape, const Transform &p_transform = Transform());
+ void add_shape(ShapeSW *p_shape, const Transform &p_transform = Transform(), bool p_disabled = false);
void set_shape(int p_index, ShapeSW *p_shape);
void set_shape_transform(int p_index, const Transform &p_transform);
_FORCE_INLINE_ int get_shape_count() const { return shapes.size(); }
+ _FORCE_INLINE_ bool is_shape_disabled(int p_index) const {
+ CRASH_BAD_INDEX(p_index, shapes.size());
+ return shapes[p_index].disabled;
+ }
_FORCE_INLINE_ ShapeSW *get_shape(int p_index) const { return shapes[p_index].shape; }
_FORCE_INLINE_ const Transform &get_shape_transform(int p_index) const { return shapes[p_index].xform; }
_FORCE_INLINE_ const Transform &get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; }
_FORCE_INLINE_ const AABB &get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; }
- _FORCE_INLINE_ const real_t get_shape_area(int p_index) const { return shapes[p_index].area_cache; }
+ _FORCE_INLINE_ real_t get_shape_area(int p_index) const { return shapes[p_index].area_cache; }
_FORCE_INLINE_ Transform get_transform() const { return transform; }
_FORCE_INLINE_ Transform get_inv_transform() const { return inv_transform; }
@@ -135,8 +135,11 @@ public:
_FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable = p_enable; }
_FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; }
- _FORCE_INLINE_ void set_shape_as_disabled(int p_idx, bool p_enable) { shapes.write[p_idx].disabled = p_enable; }
- _FORCE_INLINE_ bool is_shape_set_as_disabled(int p_idx) const { return shapes[p_idx].disabled; }
+ void set_shape_as_disabled(int p_idx, bool p_enable);
+ _FORCE_INLINE_ bool is_shape_set_as_disabled(int p_idx) const {
+ CRASH_BAD_INDEX(p_idx, shapes.size());
+ return shapes[p_idx].disabled;
+ }
_FORCE_INLINE_ void set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; }
_FORCE_INLINE_ uint32_t get_collision_layer() const { return collision_layer; }
diff --git a/servers/physics/collision_solver_sat.cpp b/servers/physics/collision_solver_sat.cpp
index 087ae570fb..a13fa65009 100644
--- a/servers/physics/collision_solver_sat.cpp
+++ b/servers/physics/collision_solver_sat.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -98,8 +98,7 @@ static void _generate_contacts_edge_edge(const Vector3 *p_points_A, int p_point_
Vector3 c = rel_A.cross(rel_B).cross(rel_B);
- //if ( Math::abs(rel_A.dot(c) )<_EDGE_IS_VALID_SUPPORT_TRESHOLD ) {
- if (Math::abs(rel_A.dot(c)) < CMP_EPSILON) {
+ if (Math::is_zero_approx(rel_A.dot(c))) {
// should handle somehow..
//ERR_PRINT("TODO FIX");
@@ -539,8 +538,6 @@ static void _collision_sphere_capsule(const ShapeSW *p_a, const Transform &p_tra
template <bool withMargin>
static void _collision_sphere_cylinder(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
-
- return;
}
template <bool withMargin>
@@ -679,7 +676,7 @@ static void _collision_box_box(const ShapeSW *p_a, const Transform &p_transform_
Vector3 axis = p_transform_a.basis.get_axis(i).cross(p_transform_b.basis.get_axis(j));
- if (axis.length_squared() < CMP_EPSILON)
+ if (Math::is_zero_approx(axis.length_squared()))
continue;
axis.normalize();
@@ -768,7 +765,7 @@ static void _collision_box_capsule(const ShapeSW *p_a, const Transform &p_transf
// cylinder
Vector3 box_axis = p_transform_a.basis.get_axis(i);
Vector3 axis = box_axis.cross(cyl_axis);
- if (axis.length_squared() < CMP_EPSILON)
+ if (Math::is_zero_approx(axis.length_squared()))
continue;
if (!separator.test_axis(axis.normalized()))
@@ -822,9 +819,9 @@ static void _collision_box_capsule(const ShapeSW *p_a, const Transform &p_transf
// test edges of A
- for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
- Vector3 axis = point_axis.cross(p_transform_a.basis.get_axis(i)).cross(p_transform_a.basis.get_axis(i)).normalized();
+ Vector3 axis = point_axis.cross(p_transform_a.basis.get_axis(j)).cross(p_transform_a.basis.get_axis(j)).normalized();
if (!separator.test_axis(axis))
return;
@@ -836,8 +833,6 @@ static void _collision_box_capsule(const ShapeSW *p_a, const Transform &p_transf
template <bool withMargin>
static void _collision_box_cylinder(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
-
- return;
}
template <bool withMargin>
@@ -1118,8 +1113,6 @@ static void _collision_capsule_capsule(const ShapeSW *p_a, const Transform &p_tr
template <bool withMargin>
static void _collision_capsule_cylinder(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
-
- return;
}
template <bool withMargin>
@@ -1244,20 +1237,14 @@ static void _collision_capsule_face(const ShapeSW *p_a, const Transform &p_trans
template <bool withMargin>
static void _collision_cylinder_cylinder(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
-
- return;
}
template <bool withMargin>
static void _collision_cylinder_convex_polygon(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
-
- return;
}
template <bool withMargin>
static void _collision_cylinder_face(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
-
- return;
}
template <bool withMargin>
@@ -1338,7 +1325,7 @@ static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a, const T
return;
}
}
- //edge-vertex( hsell)
+ //edge-vertex (shell)
for (int i = 0; i < edge_count_A; i++) {
@@ -1439,7 +1426,7 @@ static void _collision_convex_polygon_face(const ShapeSW *p_a, const Transform &
return;
}
}
- //edge-vertex( hsell)
+ //edge-vertex (shell)
for (int i = 0; i < edge_count; i++) {
diff --git a/servers/physics/collision_solver_sat.h b/servers/physics/collision_solver_sat.h
index 1d83d9889d..1bbe1de9be 100644
--- a/servers/physics/collision_solver_sat.h
+++ b/servers/physics/collision_solver_sat.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/collision_solver_sw.cpp b/servers/physics/collision_solver_sw.cpp
index 2f2f6d2908..d970dd39fb 100644
--- a/servers/physics/collision_solver_sw.cpp
+++ b/servers/physics/collision_solver_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,7 +31,6 @@
#include "collision_solver_sw.h"
#include "collision_solver_sat.h"
-#include "collision_solver_sat.h"
#include "gjk_epa.h"
#define collision_solver sat_calculate_penetration
@@ -234,8 +233,6 @@ bool CollisionSolverSW::solve_static(const ShapeSW *p_shape_A, const Transform &
return collision_solver(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, r_sep_axis, p_margin_A, p_margin_B);
}
-
- return false;
}
void CollisionSolverSW::concave_distance_callback(void *p_userdata, ShapeSW *p_convex) {
@@ -372,6 +369,4 @@ bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A, const Transform
return gjk_epa_calculate_distance(p_shape_A, p_transform_A, p_shape_B, p_transform_B, r_point_A, r_point_B); //should pass sepaxis..
}
-
- return false;
}
diff --git a/servers/physics/collision_solver_sw.h b/servers/physics/collision_solver_sw.h
index cbcb6b850a..0a8a17e5e2 100644
--- a/servers/physics/collision_solver_sw.h
+++ b/servers/physics/collision_solver_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/constraint_sw.h b/servers/physics/constraint_sw.h
index 41789600f6..e92c2c08fa 100644
--- a/servers/physics/constraint_sw.h
+++ b/servers/physics/constraint_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/gjk_epa.cpp b/servers/physics/gjk_epa.cpp
index a42b7ed82b..1d5ca42838 100644
--- a/servers/physics/gjk_epa.cpp
+++ b/servers/physics/gjk_epa.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -722,7 +722,10 @@ struct GJK
append(m_stock,face);
return(0);
}
- m_status=m_stock.root?eStatus::OutOfVertices:eStatus::OutOfFaces;
+ // -- GODOT start --
+ //m_status=m_stock.root?eStatus::OutOfVertices:eStatus::OutOfFaces;
+ m_status=eStatus::OutOfFaces;
+ // -- GODOT end --
return(0);
}
sFace* findbest()
diff --git a/servers/physics/gjk_epa.h b/servers/physics/gjk_epa.h
index f6d052608e..d3fa192804 100644
--- a/servers/physics/gjk_epa.h
+++ b/servers/physics/gjk_epa.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,11 +31,8 @@
#ifndef GJK_EPA_H
#define GJK_EPA_H
-#include "shape_sw.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
#include "collision_solver_sw.h"
+#include "shape_sw.h"
bool gjk_epa_calculate_penetration(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, CollisionSolverSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false);
bool gjk_epa_calculate_distance(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B);
diff --git a/servers/physics/joints/SCsub b/servers/physics/joints/SCsub
index ccc76e823f..d730144861 100644
--- a/servers/physics/joints/SCsub
+++ b/servers/physics/joints/SCsub
@@ -3,5 +3,3 @@
Import('env')
env.add_source_files(env.servers_sources, "*.cpp")
-
-Export('env')
diff --git a/servers/physics/joints/cone_twist_joint_sw.cpp b/servers/physics/joints/cone_twist_joint_sw.cpp
index c06f27cc57..1b3de3e913 100644
--- a/servers/physics/joints/cone_twist_joint_sw.cpp
+++ b/servers/physics/joints/cone_twist_joint_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -127,10 +127,10 @@ bool ConeTwistJointSW::setup(real_t p_timestep) {
Vector3 relPos = pivotBInW - pivotAInW;
Vector3 normal[3];
- if (relPos.length_squared() > CMP_EPSILON) {
- normal[0] = relPos.normalized();
- } else {
+ if (Math::is_zero_approx(relPos.length_squared())) {
normal[0] = Vector3(real_t(1.0), 0, 0);
+ } else {
+ normal[0] = relPos.normalized();
}
plane_space(normal[0], normal[1], normal[2]);
@@ -205,9 +205,9 @@ bool ConeTwistJointSW::setup(real_t p_timestep) {
// Twist limits
if (m_twistSpan >= real_t(0.)) {
- Vector3 b2Axis2 = B->get_transform().basis.xform(this->m_rbBFrame.basis.get_axis(1));
+ Vector3 b2Axis22 = B->get_transform().basis.xform(this->m_rbBFrame.basis.get_axis(1));
Quat rotationArc = Quat(b2Axis1, b1Axis1);
- Vector3 TwistRef = rotationArc.xform(b2Axis2);
+ Vector3 TwistRef = rotationArc.xform(b2Axis22);
real_t twist = atan2fast(TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2));
real_t lockedFreeFactor = (m_twistSpan > real_t(0.05f)) ? m_limitSoftness : real_t(0.);
@@ -332,6 +332,7 @@ void ConeTwistJointSW::set_param(PhysicsServer::ConeTwistJointParam p_param, rea
m_relaxationFactor = p_value;
} break;
+ case PhysicsServer::CONE_TWIST_MAX: break; // Can't happen, but silences warning
}
}
@@ -358,6 +359,7 @@ real_t ConeTwistJointSW::get_param(PhysicsServer::ConeTwistJointParam p_param) c
return m_relaxationFactor;
} break;
+ case PhysicsServer::CONE_TWIST_MAX: break; // Can't happen, but silences warning
}
return 0;
diff --git a/servers/physics/joints/cone_twist_joint_sw.h b/servers/physics/joints/cone_twist_joint_sw.h
index 3213562c3f..62ae310f35 100644
--- a/servers/physics/joints/cone_twist_joint_sw.h
+++ b/servers/physics/joints/cone_twist_joint_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/joints/generic_6dof_joint_sw.cpp b/servers/physics/joints/generic_6dof_joint_sw.cpp
index c95e5cef32..a9fe045856 100644
--- a/servers/physics/joints/generic_6dof_joint_sw.cpp
+++ b/servers/physics/joints/generic_6dof_joint_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -83,7 +83,7 @@ int G6DOFRotationalLimitMotorSW::testLimitValue(real_t test_value) {
real_t G6DOFRotationalLimitMotorSW::solveAngularLimits(
real_t timeStep, Vector3 &axis, real_t jacDiagABInv,
BodySW *body0, BodySW *body1) {
- if (needApplyTorques() == false) return 0.0f;
+ if (!needApplyTorques()) return 0.0f;
real_t target_velocity = m_targetVelocity;
real_t maxMotorForce = m_maxMotorForce;
@@ -107,7 +107,7 @@ real_t G6DOFRotationalLimitMotorSW::solveAngularLimits(
// correction velocity
real_t motor_relvel = m_limitSoftness * (target_velocity - m_damping * rel_vel);
- if (motor_relvel < CMP_EPSILON && motor_relvel > -CMP_EPSILON) {
+ if (Math::is_zero_approx(motor_relvel)) {
return 0.0f; //no need for applying force
}
@@ -421,7 +421,6 @@ void Generic6DOFJointSW::calcAnchorPos(void) {
const Vector3 &pA = m_calculatedTransformA.origin;
const Vector3 &pB = m_calculatedTransformB.origin;
m_AnchorPos = pA * weight + pB * (real_t(1.0) - weight);
- return;
} // Generic6DOFJointSW::calcAnchorPos()
void Generic6DOFJointSW::set_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisParam p_param, real_t p_value) {
@@ -497,6 +496,31 @@ void Generic6DOFJointSW::set_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJoi
m_angularLimits[p_axis].m_maxLimitForce = p_value;
} break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_MAX: break; // Can't happen, but silences warning
}
}
@@ -572,6 +596,31 @@ real_t Generic6DOFJointSW::get_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJ
return m_angularLimits[p_axis].m_maxMotorForce;
} break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_MAX: break; // Can't happen, but silences warning
}
return 0;
}
@@ -593,6 +642,16 @@ void Generic6DOFJointSW::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJoin
m_angularLimits[p_axis].m_enableMotor = p_value;
} break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_MAX: break; // Can't happen, but silences warning
}
}
bool Generic6DOFJointSW::get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag) const {
@@ -611,6 +670,16 @@ bool Generic6DOFJointSW::get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJoin
return m_angularLimits[p_axis].m_enableMotor;
} break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_MAX: break; // Can't happen, but silences warning
}
return 0;
diff --git a/servers/physics/joints/generic_6dof_joint_sw.h b/servers/physics/joints/generic_6dof_joint_sw.h
index b350546c5d..d4a36f1610 100644
--- a/servers/physics/joints/generic_6dof_joint_sw.h
+++ b/servers/physics/joints/generic_6dof_joint_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -118,14 +118,12 @@ public:
//! Is limited
bool isLimited() {
- if (m_loLimit >= m_hiLimit) return false;
- return true;
+ return (m_loLimit < m_hiLimit);
}
//! Need apply correction
bool needApplyTorques() {
- if (m_currentLimit == 0 && m_enableMotor == false) return false;
- return true;
+ return (m_enableMotor || m_currentLimit != 0);
}
//! calculates error
diff --git a/servers/physics/joints/hinge_joint_sw.cpp b/servers/physics/joints/hinge_joint_sw.cpp
index 368a349632..209cddda5e 100644
--- a/servers/physics/joints/hinge_joint_sw.cpp
+++ b/servers/physics/joints/hinge_joint_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -167,10 +167,10 @@ bool HingeJointSW::setup(real_t p_step) {
Vector3 relPos = pivotBInW - pivotAInW;
Vector3 normal[3];
- if (relPos.length_squared() > CMP_EPSILON) {
- normal[0] = relPos.normalized();
- } else {
+ if (Math::is_zero_approx(relPos.length_squared())) {
normal[0] = Vector3(real_t(1.0), 0, 0);
+ } else {
+ normal[0] = relPos.normalized();
}
plane_space(normal[0], normal[1], normal[2]);
@@ -198,7 +198,6 @@ bool HingeJointSW::setup(real_t p_step) {
plane_space(m_rbAFrame.basis.get_axis(2), jointAxis0local, jointAxis1local);
- A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(2));
Vector3 jointAxis0 = A->get_transform().basis.xform(jointAxis0local);
Vector3 jointAxis1 = A->get_transform().basis.xform(jointAxis1local);
Vector3 hingeAxisWorld = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(2));
@@ -409,6 +408,7 @@ void HingeJointSW::set_param(PhysicsServer::HingeJointParam p_param, real_t p_va
case PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION: m_relaxationFactor = p_value; break;
case PhysicsServer::HINGE_JOINT_MOTOR_TARGET_VELOCITY: m_motorTargetVelocity = p_value; break;
case PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE: m_maxMotorImpulse = p_value; break;
+ case PhysicsServer::HINGE_JOINT_MAX: break; // Can't happen, but silences warning
}
}
@@ -424,6 +424,7 @@ real_t HingeJointSW::get_param(PhysicsServer::HingeJointParam p_param) const {
case PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION: return m_relaxationFactor;
case PhysicsServer::HINGE_JOINT_MOTOR_TARGET_VELOCITY: return m_motorTargetVelocity;
case PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE: return m_maxMotorImpulse;
+ case PhysicsServer::HINGE_JOINT_MAX: break; // Can't happen, but silences warning
}
return 0;
@@ -434,6 +435,7 @@ void HingeJointSW::set_flag(PhysicsServer::HingeJointFlag p_flag, bool p_value)
switch (p_flag) {
case PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT: m_useLimit = p_value; break;
case PhysicsServer::HINGE_JOINT_FLAG_ENABLE_MOTOR: m_enableAngularMotor = p_value; break;
+ case PhysicsServer::HINGE_JOINT_FLAG_MAX: break; // Can't happen, but silences warning
}
}
bool HingeJointSW::get_flag(PhysicsServer::HingeJointFlag p_flag) const {
@@ -441,6 +443,7 @@ bool HingeJointSW::get_flag(PhysicsServer::HingeJointFlag p_flag) const {
switch (p_flag) {
case PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT: return m_useLimit;
case PhysicsServer::HINGE_JOINT_FLAG_ENABLE_MOTOR: return m_enableAngularMotor;
+ case PhysicsServer::HINGE_JOINT_FLAG_MAX: break; // Can't happen, but silences warning
}
return false;
diff --git a/servers/physics/joints/hinge_joint_sw.h b/servers/physics/joints/hinge_joint_sw.h
index cc8af3b370..b94baffc29 100644
--- a/servers/physics/joints/hinge_joint_sw.h
+++ b/servers/physics/joints/hinge_joint_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/joints/jacobian_entry_sw.h b/servers/physics/joints/jacobian_entry_sw.h
index 4bc1255a9a..a7b437e449 100644
--- a/servers/physics/joints/jacobian_entry_sw.h
+++ b/servers/physics/joints/jacobian_entry_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/joints/pin_joint_sw.cpp b/servers/physics/joints/pin_joint_sw.cpp
index a094e6c5ae..5d30678fd6 100644
--- a/servers/physics/joints/pin_joint_sw.cpp
+++ b/servers/physics/joints/pin_joint_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/joints/pin_joint_sw.h b/servers/physics/joints/pin_joint_sw.h
index 7d843f053c..95de733a0a 100644
--- a/servers/physics/joints/pin_joint_sw.h
+++ b/servers/physics/joints/pin_joint_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/joints/slider_joint_sw.cpp b/servers/physics/joints/slider_joint_sw.cpp
index c0e9660b22..61894f7dc9 100644
--- a/servers/physics/joints/slider_joint_sw.cpp
+++ b/servers/physics/joints/slider_joint_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -404,6 +404,8 @@ void SliderJointSW::set_param(PhysicsServer::SliderJointParam p_param, real_t p_
case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS: m_softnessOrthoAng = p_value; break;
case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION: m_restitutionOrthoAng = p_value; break;
case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING: m_dampingOrthoAng = p_value; break;
+
+ case PhysicsServer::SLIDER_JOINT_MAX: break; // Can't happen, but silences warning
}
}
@@ -433,6 +435,8 @@ real_t SliderJointSW::get_param(PhysicsServer::SliderJointParam p_param) const {
case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS: return m_softnessOrthoAng;
case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION: return m_restitutionOrthoAng;
case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING: return m_dampingOrthoAng;
+
+ case PhysicsServer::SLIDER_JOINT_MAX: break; // Can't happen, but silences warning
}
return 0;
diff --git a/servers/physics/joints/slider_joint_sw.h b/servers/physics/joints/slider_joint_sw.h
index 4df632d75f..813eaae097 100644
--- a/servers/physics/joints/slider_joint_sw.h
+++ b/servers/physics/joints/slider_joint_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/joints_sw.h b/servers/physics/joints_sw.h
index af27b1c25b..d79fb0750a 100644
--- a/servers/physics/joints_sw.h
+++ b/servers/physics/joints_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp
index 76a6138817..09872977b6 100644
--- a/servers/physics/physics_server_sw.cpp
+++ b/servers/physics/physics_server_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -40,6 +40,9 @@
#include "joints/pin_joint_sw.h"
#include "joints/slider_joint_sw.h"
+#define FLUSH_QUERY_CHECK(m_object) \
+ ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead.");
+
RID PhysicsServerSW::shape_create(ShapeType p_shape) {
ShapeSW *shape = NULL;
@@ -67,8 +70,7 @@ RID PhysicsServerSW::shape_create(ShapeType p_shape) {
} break;
case SHAPE_CYLINDER: {
- ERR_EXPLAIN("CylinderShape is not supported in GodotPhysics. Please switch to Bullet in the Project Settings.");
- ERR_FAIL_V(RID());
+ ERR_FAIL_V_MSG(RID(), "CylinderShape is not supported in GodotPhysics. Please switch to Bullet in the Project Settings.");
} break;
case SHAPE_CONVEX_POLYGON: {
@@ -194,11 +196,7 @@ PhysicsDirectSpaceState *PhysicsServerSW::space_get_direct_state(RID p_space) {
SpaceSW *space = space_owner.get(p_space);
ERR_FAIL_COND_V(!space, NULL);
- if (!doing_sync || space->is_locked()) {
-
- ERR_EXPLAIN("Space state is inaccessible right now, wait for iteration or physics process notification.");
- ERR_FAIL_V(NULL);
- }
+ ERR_FAIL_COND_V_MSG(!doing_sync || space->is_locked(), NULL, "Space state is inaccessible right now, wait for iteration or physics process notification.");
return space->get_direct_state();
}
@@ -277,7 +275,7 @@ PhysicsServer::AreaSpaceOverrideMode PhysicsServerSW::area_get_space_override_mo
return area->get_space_override_mode();
}
-void PhysicsServerSW::area_add_shape(RID p_area, RID p_shape, const Transform &p_transform) {
+void PhysicsServerSW::area_add_shape(RID p_area, RID p_shape, const Transform &p_transform, bool p_disabled) {
AreaSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
@@ -285,7 +283,7 @@ void PhysicsServerSW::area_add_shape(RID p_area, RID p_shape, const Transform &p
ShapeSW *shape = shape_owner.get(p_shape);
ERR_FAIL_COND(!shape);
- area->add_shape(shape, p_transform);
+ area->add_shape(shape, p_transform, p_disabled);
}
void PhysicsServerSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) {
@@ -355,10 +353,11 @@ void PhysicsServerSW::area_set_shape_disabled(RID p_area, int p_shape_idx, bool
AreaSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
ERR_FAIL_INDEX(p_shape_idx, area->get_shape_count());
+ FLUSH_QUERY_CHECK(area);
area->set_shape_as_disabled(p_shape_idx, p_disabled);
}
-void PhysicsServerSW::area_attach_object_instance_id(RID p_area, ObjectID p_ID) {
+void PhysicsServerSW::area_attach_object_instance_id(RID p_area, ObjectID p_id) {
if (space_owner.owns(p_area)) {
SpaceSW *space = space_owner.get(p_area);
@@ -366,7 +365,7 @@ void PhysicsServerSW::area_attach_object_instance_id(RID p_area, ObjectID p_ID)
}
AreaSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
- area->set_instance_id(p_ID);
+ area->set_instance_id(p_id);
}
ObjectID PhysicsServerSW::area_get_object_instance_id(RID p_area) const {
@@ -437,6 +436,7 @@ void PhysicsServerSW::area_set_monitorable(RID p_area, bool p_monitorable) {
AreaSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
+ FLUSH_QUERY_CHECK(area);
area->set_monitorable(p_monitorable);
}
@@ -532,7 +532,7 @@ PhysicsServer::BodyMode PhysicsServerSW::body_get_mode(RID p_body) const {
return body->get_mode();
};
-void PhysicsServerSW::body_add_shape(RID p_body, RID p_shape, const Transform &p_transform) {
+void PhysicsServerSW::body_add_shape(RID p_body, RID p_shape, const Transform &p_transform, bool p_disabled) {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
@@ -540,7 +540,7 @@ void PhysicsServerSW::body_add_shape(RID p_body, RID p_shape, const Transform &p
ShapeSW *shape = shape_owner.get(p_shape);
ERR_FAIL_COND(!shape);
- body->add_shape(shape, p_transform);
+ body->add_shape(shape, p_transform, p_disabled);
}
void PhysicsServerSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) {
@@ -585,6 +585,8 @@ void PhysicsServerSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
+ FLUSH_QUERY_CHECK(body);
+
body->set_shape_as_disabled(p_shape_idx, p_disabled);
}
@@ -663,12 +665,12 @@ uint32_t PhysicsServerSW::body_get_collision_mask(RID p_body) const {
return body->get_collision_mask();
}
-void PhysicsServerSW::body_attach_object_instance_id(RID p_body, uint32_t p_ID) {
+void PhysicsServerSW::body_attach_object_instance_id(RID p_body, uint32_t p_id) {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
- body->set_instance_id(p_ID);
+ body->set_instance_id(p_id);
};
uint32_t PhysicsServerSW::body_get_object_instance_id(RID p_body) const {
@@ -977,12 +979,7 @@ PhysicsDirectBodyState *PhysicsServerSW::body_get_direct_state(RID p_body) {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body, NULL);
-
- if (!doing_sync || body->get_space()->is_locked()) {
-
- ERR_EXPLAIN("Body state is inaccessible right now, wait for iteration or physics process notification.");
- ERR_FAIL_V(NULL);
- }
+ ERR_FAIL_COND_V_MSG(!doing_sync || body->get_space()->is_locked(), NULL, "Body state is inaccessible right now, wait for iteration or physics process notification.");
direct_state->body = body;
return direct_state;
@@ -1400,8 +1397,7 @@ void PhysicsServerSW::free(RID p_rid) {
} else {
- ERR_EXPLAIN("Invalid ID");
- ERR_FAIL();
+ ERR_FAIL_MSG("Invalid ID.");
}
};
@@ -1459,6 +1455,8 @@ void PhysicsServerSW::flush_queries() {
doing_sync = true;
+ flushing_queries = true;
+
uint64_t time_beg = OS::get_singleton()->get_ticks_usec();
for (Set<const SpaceSW *>::Element *E = active_spaces.front(); E; E = E->next()) {
@@ -1467,6 +1465,8 @@ void PhysicsServerSW::flush_queries() {
space->call_queries();
}
+ flushing_queries = false;
+
if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_profiling()) {
uint64_t total_time[SpaceSW::ELAPSED_TIME_MAX];
@@ -1580,6 +1580,7 @@ PhysicsServerSW::PhysicsServerSW() {
collision_pairs = 0;
active = true;
+ flushing_queries = false;
};
PhysicsServerSW::~PhysicsServerSW(){
diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h
index 4131c5e248..b593e9b5f1 100644
--- a/servers/physics/physics_server_sw.h
+++ b/servers/physics/physics_server_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -51,6 +51,8 @@ class PhysicsServerSW : public PhysicsServer {
int active_objects;
int collision_pairs;
+ bool flushing_queries;
+
StepSW *stepper;
Set<const SpaceSW *> active_spaces;
@@ -117,7 +119,7 @@ public:
virtual void area_set_space(RID p_area, RID p_space);
virtual RID area_get_space(RID p_area) const;
- virtual void area_add_shape(RID p_area, RID p_shape, const Transform &p_transform = Transform());
+ virtual void area_add_shape(RID p_area, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false);
virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape);
virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform);
@@ -130,7 +132,7 @@ public:
virtual void area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled);
- virtual void area_attach_object_instance_id(RID p_area, ObjectID p_ID);
+ virtual void area_attach_object_instance_id(RID p_area, ObjectID p_id);
virtual ObjectID area_get_object_instance_id(RID p_area) const;
virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value);
@@ -161,7 +163,7 @@ public:
virtual void body_set_mode(RID p_body, BodyMode p_mode);
virtual BodyMode body_get_mode(RID p_body) const;
- virtual void body_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform());
+ virtual void body_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false);
virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape);
virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform);
@@ -174,7 +176,7 @@ public:
virtual void body_remove_shape(RID p_body, int p_shape_idx);
virtual void body_clear_shapes(RID p_body);
- virtual void body_attach_object_instance_id(RID p_body, uint32_t p_ID);
+ virtual void body_attach_object_instance_id(RID p_body, uint32_t p_id);
virtual uint32_t body_get_object_instance_id(RID p_body) const;
virtual void body_set_enable_continuous_collision_detection(RID p_body, bool p_enable);
@@ -346,6 +348,9 @@ public:
virtual void generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag, bool p_enable);
virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag);
+ virtual void generic_6dof_joint_set_precision(RID p_joint, int precision) {}
+ virtual int generic_6dof_joint_get_precision(RID p_joint) { return 0; }
+
virtual JointType joint_get_type(RID p_joint) const;
virtual void joint_set_solver_priority(RID p_joint, int p_priority);
@@ -365,6 +370,8 @@ public:
virtual void flush_queries();
virtual void finish();
+ virtual bool is_flushing_queries() const { return flushing_queries; }
+
int get_process_info(ProcessInfo p_info);
PhysicsServerSW();
diff --git a/servers/physics/shape_sw.cpp b/servers/physics/shape_sw.cpp
index e1c985f44f..f01caefdce 100644
--- a/servers/physics/shape_sw.cpp
+++ b/servers/physics/shape_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,7 +32,7 @@
#include "core/math/geometry.h"
#include "core/math/quick_hull.h"
-#include "core/sort.h"
+#include "core/sort_array.h"
#define _POINT_SNAP 0.001953125
#define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.0002
@@ -543,16 +543,6 @@ void CapsuleShapeSW::project_range(const Vector3 &p_normal, const Transform &p_t
r_max = p_normal.dot(p_transform.xform(n));
r_min = p_normal.dot(p_transform.xform(-n));
- return;
-
- n = p_transform.basis.xform(n);
-
- real_t distance = p_normal.dot(p_transform.origin);
- real_t length = Math::abs(p_normal.dot(n));
- r_min = distance - length;
- r_max = distance + length;
-
- ERR_FAIL_COND(r_max < r_min);
}
Vector3 CapsuleShapeSW::get_support(const Vector3 &p_normal) const {
@@ -1047,7 +1037,7 @@ void FaceShapeSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_su
/** FIND SUPPORT VERTEX **/
int vert_support_idx = -1;
- real_t support_max;
+ real_t support_max = 0;
for (int i = 0; i < 3; i++) {
@@ -1524,8 +1514,8 @@ void ConcavePolygonShapeSW::_setup(PoolVector<Vector3> p_faces) {
_aabb.merge_with(bvh_arrayw[i].aabb);
}
- w = PoolVector<Face>::Write();
- vw = PoolVector<Vector3>::Write();
+ w.release();
+ vw.release();
int count = 0;
_VolumeSW_BVH *bvh_tree = _volume_sw_build_bvh(bvh_arrayw, src_face_count, count);
diff --git a/servers/physics/shape_sw.h b/servers/physics/shape_sw.h
index 073d19e317..6af1224b38 100644
--- a/servers/physics/shape_sw.h
+++ b/servers/physics/shape_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp
index 731749b8ce..410b6e59a0 100644
--- a/servers/physics/space_sw.cpp
+++ b/servers/physics/space_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -118,7 +118,7 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3 &p_from, const Vecto
if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas))
continue;
- if (p_pick_ray && !(static_cast<CollisionObjectSW *>(space->intersection_query_results[i])->is_ray_pickable()))
+ if (p_pick_ray && !(space->intersection_query_results[i]->is_ray_pickable()))
continue;
if (p_exclude.has(space->intersection_query_results[i]->get_self()))
@@ -277,7 +277,7 @@ bool PhysicsDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform
real_t hi = 1;
Vector3 mnormal = p_motion.normalized();
- for (int i = 0; i < 8; i++) { //steps should be customizable..
+ for (int j = 0; j < 8; j++) { //steps should be customizable..
real_t ofs = (low + hi) * 0.5;
@@ -348,13 +348,9 @@ bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform &p_sh
cbk.max = p_result_max;
cbk.amount = 0;
cbk.ptr = r_results;
- CollisionSolverSW::CallbackResult cbkres = NULL;
+ CollisionSolverSW::CallbackResult cbkres = PhysicsServerSW::_shape_col_cbk;
- PhysicsServerSW::CollCbkData *cbkptr = NULL;
- if (p_result_max > 0) {
- cbkptr = &cbk;
- cbkres = PhysicsServerSW::_shape_col_cbk;
- }
+ PhysicsServerSW::CollCbkData *cbkptr = &cbk;
for (int i = 0; i < amount; i++) {
@@ -387,6 +383,7 @@ struct _RestCallbackData {
Vector3 best_contact;
Vector3 best_normal;
real_t best_len;
+ real_t min_allowed_depth;
};
static void _rest_cbk_result(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) {
@@ -395,6 +392,8 @@ static void _rest_cbk_result(const Vector3 &p_point_A, const Vector3 &p_point_B,
Vector3 contact_rel = p_point_B - p_point_A;
real_t len = contact_rel.length();
+ if (len < rd->min_allowed_depth)
+ return;
if (len <= rd->best_len)
return;
@@ -418,6 +417,7 @@ bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform &p_shape_
rcd.best_len = 0;
rcd.best_object = NULL;
rcd.best_shape = 0;
+ rcd.min_allowed_depth = space->test_motion_min_contact_depth;
for (int i = 0; i < amount; i++) {
@@ -437,7 +437,7 @@ bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform &p_shape_
continue;
}
- if (rcd.best_len == 0)
+ if (rcd.best_len == 0 || !rcd.best_object)
return false;
r_info->collider_id = rcd.best_object->get_instance_id();
@@ -544,14 +544,24 @@ int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transfo
AABB body_aabb;
+ bool shapes_found = false;
+
for (int i = 0; i < p_body->get_shape_count(); i++) {
- if (i == 0)
+ if (p_body->is_shape_set_as_disabled(i))
+ continue;
+
+ if (!shapes_found) {
body_aabb = p_body->get_shape_aabb(i);
- else
+ shapes_found = true;
+ } else {
body_aabb = body_aabb.merge(p_body->get_shape_aabb(i));
+ }
}
+ if (!shapes_found) {
+ return 0;
+ }
// Undo the currently transform the physics server is aware of and apply the provided one
body_aabb = p_transform.xform(p_body->get_inv_transform().xform(body_aabb));
body_aabb = body_aabb.grow(p_margin);
@@ -583,7 +593,6 @@ int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transfo
bool collided = false;
int amount = _cull_aabb_for_body(p_body, body_aabb);
- int ray_index = 0;
for (int j = 0; j < p_body->get_shape_count(); j++) {
if (p_body->is_shape_set_as_disabled(j))
@@ -617,7 +626,19 @@ int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transfo
collided = true;
}
- if (ray_index < p_result_max) {
+ int ray_index = -1; //reuse shape
+ for (int k = 0; k < rays_found; k++) {
+ if (r_results[k].collision_local_shape == j) {
+ ray_index = k;
+ }
+ }
+
+ if (ray_index == -1 && rays_found < p_result_max) {
+ ray_index = rays_found;
+ rays_found++;
+ }
+
+ if (ray_index != -1) {
PhysicsServer::SeparationResult &result = r_results[ray_index];
for (int k = 0; k < cbk.amount; k++) {
@@ -632,9 +653,10 @@ int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transfo
result.collision_depth = depth;
result.collision_point = b;
result.collision_normal = (b - a).normalized();
- result.collision_local_shape = shape_idx;
+ result.collision_local_shape = j;
result.collider = col_obj->get_self();
result.collider_id = col_obj->get_instance_id();
+ result.collider_shape = shape_idx;
//result.collider_metadata = col_obj->get_shape_metadata(shape_idx);
if (col_obj->get_type() == CollisionObjectSW::TYPE_BODY) {
BodySW *body = (BodySW *)col_obj;
@@ -648,12 +670,8 @@ int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transfo
}
}
}
-
- ray_index++;
}
- rays_found = MAX(ray_index, rays_found);
-
if (!collided || recover_motion == Vector3()) {
break;
}
@@ -691,13 +709,28 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve
r_result->collider_shape = 0;
}
AABB body_aabb;
+ bool shapes_found = false;
for (int i = 0; i < p_body->get_shape_count(); i++) {
- if (i == 0)
+ if (p_body->is_shape_set_as_disabled(i))
+ continue;
+
+ if (!shapes_found) {
body_aabb = p_body->get_shape_aabb(i);
- else
+ shapes_found = true;
+ } else {
body_aabb = body_aabb.merge(p_body->get_shape_aabb(i));
+ }
+ }
+
+ if (!shapes_found) {
+ if (r_result) {
+ *r_result = PhysicsServer::MotionResult();
+ r_result->motion = p_motion;
+ }
+
+ return false;
}
// Undo the currently transform the physics server is aware of and apply the provided one
@@ -835,7 +868,7 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve
real_t hi = 1;
Vector3 mnormal = p_motion.normalized();
- for (int i = 0; i < 8; i++) { //steps should be customizable..
+ for (int k = 0; k < 8; k++) { //steps should be customizable..
real_t ofs = (low + hi) * 0.5;
@@ -904,6 +937,7 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve
rcd.best_len = 0;
rcd.best_object = NULL;
rcd.best_shape = 0;
+ rcd.min_allowed_depth = test_motion_min_contact_depth;
Transform body_shape_xform = ugt * p_body->get_shape_transform(best_shape);
ShapeSW *body_shape = p_body->get_shape(best_shape);
@@ -1128,6 +1162,7 @@ void SpaceSW::set_param(PhysicsServer::SpaceParameter p_param, real_t p_value) {
case PhysicsServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: body_time_to_sleep = p_value; break;
case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: body_angular_velocity_damp_ratio = p_value; break;
case PhysicsServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: constraint_bias = p_value; break;
+ case PhysicsServer::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: test_motion_min_contact_depth = p_value; break;
}
}
@@ -1143,6 +1178,7 @@ real_t SpaceSW::get_param(PhysicsServer::SpaceParameter p_param) const {
case PhysicsServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: return body_time_to_sleep;
case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: return body_angular_velocity_damp_ratio;
case PhysicsServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: return constraint_bias;
+ case PhysicsServer::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: return test_motion_min_contact_depth;
}
return 0;
}
@@ -1178,11 +1214,13 @@ SpaceSW::SpaceSW() {
contact_recycle_radius = 0.01;
contact_max_separation = 0.05;
contact_max_allowed_penetration = 0.01;
+ test_motion_min_contact_depth = 0.00001;
constraint_bias = 0.01;
body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_linear", 0.1);
body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_angular", (8.0 / 180.0 * Math_PI));
body_time_to_sleep = GLOBAL_DEF("physics/3d/time_before_sleep", 0.5);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/time_before_sleep", PropertyInfo(Variant::REAL, "physics/3d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"));
body_angular_velocity_damp_ratio = 10;
broadphase = BroadPhaseSW::create_func();
diff --git a/servers/physics/space_sw.h b/servers/physics/space_sw.h
index d550b374e3..3aaa552845 100644
--- a/servers/physics/space_sw.h
+++ b/servers/physics/space_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -96,6 +96,7 @@ private:
real_t contact_max_separation;
real_t contact_max_allowed_penetration;
real_t constraint_bias;
+ real_t test_motion_min_contact_depth;
enum {
diff --git a/servers/physics/step_sw.cpp b/servers/physics/step_sw.cpp
index 5238f24b20..4082956747 100644
--- a/servers/physics/step_sw.cpp
+++ b/servers/physics/step_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/step_sw.h b/servers/physics/step_sw.h
index 25e9fedf79..c291190fe4 100644
--- a/servers/physics/step_sw.h
+++ b/servers/physics/step_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp
index 037c92bac6..9ec1eacd29 100644
--- a/servers/physics_2d/area_2d_sw.cpp
+++ b/servers/physics_2d/area_2d_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h
index 90e30f68bc..371ad94c22 100644
--- a/servers/physics_2d/area_2d_sw.h
+++ b/servers/physics_2d/area_2d_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/area_pair_2d_sw.cpp
index 9d515d2183..7401dbfa89 100644
--- a/servers/physics_2d/area_pair_2d_sw.cpp
+++ b/servers/physics_2d/area_pair_2d_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -147,10 +147,10 @@ Area2Pair2DSW::~Area2Pair2DSW() {
if (colliding) {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable())
+ if (area_b->has_area_monitor_callback())
area_b->remove_area_from_query(area_a, shape_a, shape_b);
- if (area_a->has_area_monitor_callback() && area_b->is_monitorable())
+ if (area_a->has_area_monitor_callback())
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}
diff --git a/servers/physics_2d/area_pair_2d_sw.h b/servers/physics_2d/area_pair_2d_sw.h
index 243b99a79c..6972bcd0f5 100644
--- a/servers/physics_2d/area_pair_2d_sw.h
+++ b/servers/physics_2d/area_pair_2d_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp
index aa063d6c1e..6ba159ca0a 100644
--- a/servers/physics_2d/body_2d_sw.cpp
+++ b/servers/physics_2d/body_2d_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -47,8 +47,10 @@ void Body2DSW::update_inertias() {
case Physics2DServer::BODY_MODE_RIGID: {
- if (user_inertia) break;
-
+ if (user_inertia) {
+ _inv_inertia = inertia > 0 ? (1.0 / inertia) : 0;
+ break;
+ }
//update tensor for allshapes, not the best way but should be somehow OK. (inspired from bullet)
real_t total_area = 0;
@@ -57,10 +59,14 @@ void Body2DSW::update_inertias() {
total_area += get_shape_aabb(i).get_area();
}
- real_t _inertia = 0;
+ inertia = 0;
for (int i = 0; i < get_shape_count(); i++) {
+ if (is_shape_disabled(i)) {
+ continue;
+ }
+
const Shape2DSW *shape = get_shape(i);
real_t area = get_shape_aabb(i).get_area();
@@ -69,15 +75,10 @@ void Body2DSW::update_inertias() {
Transform2D mtx = get_shape_transform(i);
Vector2 scale = mtx.get_scale();
- _inertia += shape->get_moment_of_inertia(mass, scale) + mass * mtx.get_origin().length_squared();
- //Rect2 ab = get_shape_aabb(i);
- //_inertia+=mass*ab.size.dot(ab.size)/12.0f;
+ inertia += shape->get_moment_of_inertia(mass, scale) + mass * mtx.get_origin().length_squared();
}
- if (_inertia != 0)
- _inv_inertia = 1.0 / _inertia;
- else
- _inv_inertia = 0.0; //wathever
+ _inv_inertia = inertia > 0 ? (1.0 / inertia) : 0;
if (mass)
_inv_mass = 1.0 / mass;
@@ -156,6 +157,7 @@ void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, real_t p_value)
_update_inertia();
} else {
user_inertia = true;
+ inertia = p_value;
_inv_inertia = 1.0 / p_value;
}
} break;
@@ -170,7 +172,8 @@ void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, real_t p_value)
angular_damp = p_value;
} break;
- default: {}
+ default: {
+ }
}
}
@@ -180,29 +183,30 @@ real_t Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const {
case Physics2DServer::BODY_PARAM_BOUNCE: {
return bounce;
- } break;
+ }
case Physics2DServer::BODY_PARAM_FRICTION: {
return friction;
- } break;
+ }
case Physics2DServer::BODY_PARAM_MASS: {
return mass;
- } break;
+ }
case Physics2DServer::BODY_PARAM_INERTIA: {
- return _inv_inertia == 0 ? 0 : 1.0 / _inv_inertia;
- } break;
+ return inertia;
+ }
case Physics2DServer::BODY_PARAM_GRAVITY_SCALE: {
return gravity_scale;
- } break;
+ }
case Physics2DServer::BODY_PARAM_LINEAR_DAMP: {
return linear_damp;
- } break;
+ }
case Physics2DServer::BODY_PARAM_ANGULAR_DAMP: {
return angular_damp;
- } break;
- default: {}
+ }
+ default: {
+ }
}
return 0;
@@ -220,6 +224,7 @@ void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) {
_set_inv_transform(get_transform().affine_inverse());
_inv_mass = 0;
+ _inv_inertia = 0;
_set_static(p_mode == Physics2DServer::BODY_MODE_STATIC);
set_active(p_mode == Physics2DServer::BODY_MODE_KINEMATIC && contacts.size());
linear_velocity = Vector2();
@@ -231,17 +236,21 @@ void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) {
case Physics2DServer::BODY_MODE_RIGID: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
+ _inv_inertia = inertia > 0 ? (1.0 / inertia) : 0;
_set_static(false);
} break;
case Physics2DServer::BODY_MODE_CHARACTER: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
+ _inv_inertia = 0;
_set_static(false);
+ angular_velocity = 0;
} break;
}
-
- _update_inertia();
+ if (p_mode == Physics2DServer::BODY_MODE_RIGID && _inv_inertia == 0) {
+ _update_inertia();
+ }
/*
if (get_space())
_update_queries();
@@ -337,19 +346,19 @@ Variant Body2DSW::get_state(Physics2DServer::BodyState p_state) const {
switch (p_state) {
case Physics2DServer::BODY_STATE_TRANSFORM: {
return get_transform();
- } break;
+ }
case Physics2DServer::BODY_STATE_LINEAR_VELOCITY: {
return linear_velocity;
- } break;
+ }
case Physics2DServer::BODY_STATE_ANGULAR_VELOCITY: {
return angular_velocity;
- } break;
+ }
case Physics2DServer::BODY_STATE_SLEEPING: {
return !is_active();
- } break;
+ }
case Physics2DServer::BODY_STATE_CAN_SLEEP: {
return can_sleep;
- } break;
+ }
}
return Variant();
@@ -439,7 +448,8 @@ void Body2DSW::integrate_forces(real_t p_step) {
_compute_area_gravity_and_dampenings(aa[i].area);
stopped = mode == Physics2DServer::AREA_SPACE_OVERRIDE_REPLACE;
} break;
- default: {}
+ default: {
+ }
}
}
}
@@ -511,8 +521,7 @@ void Body2DSW::integrate_forces(real_t p_step) {
if (continuous_cd_mode != Physics2DServer::CCD_MODE_DISABLED) {
- motion = new_transform.get_origin() - get_transform().get_origin();
- //linear_velocity*p_step;
+ motion = linear_velocity * p_step;
do_motion = true;
}
}
@@ -602,7 +611,7 @@ void Body2DSW::call_queries() {
set_force_integration_callback(0, StringName());
} else {
Variant::CallError ce;
- if (fi_callback->callback_udata.get_type()) {
+ if (fi_callback->callback_udata.get_type() != Variant::NIL) {
obj->call(fi_callback->method, vp, 2, ce);
@@ -662,6 +671,7 @@ Body2DSW::Body2DSW() :
angular_velocity = 0;
biased_angular_velocity = 0;
mass = 1;
+ inertia = 0;
user_inertia = false;
_inv_inertia = 0;
_inv_mass = 1;
diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h
index 97dff69a20..5df184c894 100644
--- a/servers/physics_2d/body_2d_sw.h
+++ b/servers/physics_2d/body_2d_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -52,6 +52,7 @@ class Body2DSW : public CollisionObject2DSW {
real_t gravity_scale;
real_t mass;
+ real_t inertia;
real_t bounce;
real_t friction;
diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp
index 2633edf7bb..46ea0fd65d 100644
--- a/servers/physics_2d/body_pair_2d_sw.cpp
+++ b/servers/physics_2d/body_pair_2d_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -138,7 +138,7 @@ void BodyPair2DSW::_validate_contacts() {
Contact &c = contacts[i];
bool erase = false;
- if (c.reused == false) {
+ if (!c.reused) {
//was left behind in previous frame
erase = true;
} else {
@@ -303,7 +303,7 @@ bool BodyPair2DSW::setup(real_t p_step) {
Contact &c = contacts[i];
if (!c.reused)
continue;
- if (c.normal.dot(direction) < 0)
+ if (c.normal.dot(direction) > 0) //greater (normal inverted)
continue;
valid = true;
@@ -326,7 +326,7 @@ bool BodyPair2DSW::setup(real_t p_step) {
Contact &c = contacts[i];
if (!c.reused)
continue;
- if (c.normal.dot(direction) < 0)
+ if (c.normal.dot(direction) < 0) //less (normal ok)
continue;
valid = true;
diff --git a/servers/physics_2d/body_pair_2d_sw.h b/servers/physics_2d/body_pair_2d_sw.h
index e54a32fb46..a5c07aac05 100644
--- a/servers/physics_2d/body_pair_2d_sw.h
+++ b/servers/physics_2d/body_pair_2d_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/broad_phase_2d_basic.cpp b/servers/physics_2d/broad_phase_2d_basic.cpp
index 067d86f474..6a9c9f783c 100644
--- a/servers/physics_2d/broad_phase_2d_basic.cpp
+++ b/servers/physics_2d/broad_phase_2d_basic.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/broad_phase_2d_basic.h b/servers/physics_2d/broad_phase_2d_basic.h
index da5dc38b8e..595c5d411a 100644
--- a/servers/physics_2d/broad_phase_2d_basic.h
+++ b/servers/physics_2d/broad_phase_2d_basic.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.cpp b/servers/physics_2d/broad_phase_2d_hash_grid.cpp
index 950f0f9d24..6dd19c2868 100644
--- a/servers/physics_2d/broad_phase_2d_hash_grid.cpp
+++ b/servers/physics_2d/broad_phase_2d_hash_grid.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -635,11 +635,15 @@ BroadPhase2DSW *BroadPhase2DHashGrid::_create() {
BroadPhase2DHashGrid::BroadPhase2DHashGrid() {
hash_table_size = GLOBAL_DEF("physics/2d/bp_hash_table_size", 4096);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/bp_hash_table_size", PropertyInfo(Variant::INT, "physics/2d/bp_hash_table_size", PROPERTY_HINT_RANGE, "0,8192,1,or_greater"));
hash_table_size = Math::larger_prime(hash_table_size);
hash_table = memnew_arr(PosBin *, hash_table_size);
cell_size = GLOBAL_DEF("physics/2d/cell_size", 128);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/cell_size", PropertyInfo(Variant::INT, "physics/2d/cell_size", PROPERTY_HINT_RANGE, "0,512,1,or_greater"));
+
large_object_min_surface = GLOBAL_DEF("physics/2d/large_object_surface_threshold_in_cells", 512);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/large_object_surface_threshold_in_cells", PropertyInfo(Variant::INT, "physics/2d/large_object_surface_threshold_in_cells", PROPERTY_HINT_RANGE, "0,1024,1,or_greater"));
for (uint32_t i = 0; i < hash_table_size; i++)
hash_table[i] = NULL;
@@ -669,7 +673,7 @@ public IEnumerable<Point3D> GetCellsOnRay(Ray ray, int maxDepth)
// "A Fast Voxel Traversal Algorithm for Ray Tracing"
// John Amanatides, Andrew Woo
// http://www.cse.yorku.ca/~amana/research/grid.pdf
- // http://www.devmaster.net/articles/raytracing_series/A%20faster%20voxel%20traversal%20algorithm%20for%20ray%20tracing.pdf
+ // https://web.archive.org/web/20100616193049/http://www.devmaster.net/articles/raytracing_series/A%20faster%20voxel%20traversal%20algorithm%20for%20ray%20tracing.pdf
// NOTES:
// * This code assumes that the ray's position and direction are in 'cell coordinates', which means
diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.h b/servers/physics_2d/broad_phase_2d_hash_grid.h
index 0ecb915a7b..61fe5dbcf6 100644
--- a/servers/physics_2d/broad_phase_2d_hash_grid.h
+++ b/servers/physics_2d/broad_phase_2d_hash_grid.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/broad_phase_2d_sw.cpp b/servers/physics_2d/broad_phase_2d_sw.cpp
index 6e3dce000f..20250c5113 100644
--- a/servers/physics_2d/broad_phase_2d_sw.cpp
+++ b/servers/physics_2d/broad_phase_2d_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/broad_phase_2d_sw.h b/servers/physics_2d/broad_phase_2d_sw.h
index 5b512dac76..1ba8e24cff 100644
--- a/servers/physics_2d/broad_phase_2d_sw.h
+++ b/servers/physics_2d/broad_phase_2d_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp
index 4dd5b2040f..f556638db1 100644
--- a/servers/physics_2d/collision_object_2d_sw.cpp
+++ b/servers/physics_2d/collision_object_2d_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,21 +29,27 @@
/*************************************************************************/
#include "collision_object_2d_sw.h"
+#include "servers/physics_2d/physics_2d_server_sw.h"
#include "space_2d_sw.h"
-void CollisionObject2DSW::add_shape(Shape2DSW *p_shape, const Transform2D &p_transform) {
+void CollisionObject2DSW::add_shape(Shape2DSW *p_shape, const Transform2D &p_transform, bool p_disabled) {
Shape s;
s.shape = p_shape;
s.xform = p_transform;
s.xform_inv = s.xform.affine_inverse();
s.bpid = 0; //needs update
- s.disabled = false;
+ s.disabled = p_disabled;
s.one_way_collision = false;
+ s.one_way_collision_margin = 0;
shapes.push_back(s);
p_shape->add_owner(this);
- _update_shapes();
- _shapes_changed();
+
+ if (!pending_shape_update_list.in_list()) {
+ Physics2DServerSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ }
+ // _update_shapes();
+ // _shapes_changed();
}
void CollisionObject2DSW::set_shape(int p_index, Shape2DSW *p_shape) {
@@ -53,8 +59,12 @@ void CollisionObject2DSW::set_shape(int p_index, Shape2DSW *p_shape) {
shapes.write[p_index].shape = p_shape;
p_shape->add_owner(this);
- _update_shapes();
- _shapes_changed();
+
+ if (!pending_shape_update_list.in_list()) {
+ Physics2DServerSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ }
+ // _update_shapes();
+ // _shapes_changed();
}
void CollisionObject2DSW::set_shape_metadata(int p_index, const Variant &p_metadata) {
@@ -69,8 +79,12 @@ void CollisionObject2DSW::set_shape_transform(int p_index, const Transform2D &p_
shapes.write[p_index].xform = p_transform;
shapes.write[p_index].xform_inv = p_transform.affine_inverse();
- _update_shapes();
- _shapes_changed();
+
+ if (!pending_shape_update_list.in_list()) {
+ Physics2DServerSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ }
+ // _update_shapes();
+ // _shapes_changed();
}
void CollisionObject2DSW::set_shape_as_disabled(int p_idx, bool p_disabled) {
@@ -88,9 +102,15 @@ void CollisionObject2DSW::set_shape_as_disabled(int p_idx, bool p_disabled) {
if (p_disabled && shape.bpid != 0) {
space->get_broadphase()->remove(shape.bpid);
shape.bpid = 0;
- _update_shapes();
+ if (!pending_shape_update_list.in_list()) {
+ Physics2DServerSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ }
+ //_update_shapes();
} else if (!p_disabled && shape.bpid == 0) {
- _update_shapes(); // automatically adds shape with bpid == 0
+ if (!pending_shape_update_list.in_list()) {
+ Physics2DServerSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ }
+ //_update_shapes(); // automatically adds shape with bpid == 0
}
}
@@ -121,8 +141,11 @@ void CollisionObject2DSW::remove_shape(int p_index) {
shapes[p_index].shape->remove_owner(this);
shapes.remove(p_index);
- _update_shapes();
- _shapes_changed();
+ if (!pending_shape_update_list.in_list()) {
+ Physics2DServerSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ }
+ // _update_shapes();
+ // _shapes_changed();
}
void CollisionObject2DSW::_set_static(bool p_static) {
@@ -238,12 +261,14 @@ void CollisionObject2DSW::_shape_changed() {
_shapes_changed();
}
-CollisionObject2DSW::CollisionObject2DSW(Type p_type) {
+CollisionObject2DSW::CollisionObject2DSW(Type p_type) :
+ pending_shape_update_list(this) {
_static = true;
type = p_type;
space = NULL;
instance_id = 0;
+ canvas_instance_id = 0;
collision_mask = 1;
collision_layer = 1;
pickable = true;
diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h
index c3b9e4b713..ed59469878 100644
--- a/servers/physics_2d/collision_object_2d_sw.h
+++ b/servers/physics_2d/collision_object_2d_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -49,6 +49,7 @@ private:
Type type;
RID self;
ObjectID instance_id;
+ ObjectID canvas_instance_id;
bool pickable;
struct Shape {
@@ -61,9 +62,11 @@ private:
Variant metadata;
bool disabled;
bool one_way_collision;
+ float one_way_collision_margin;
Shape() {
disabled = false;
one_way_collision = false;
+ one_way_collision_margin = 0;
}
};
@@ -75,6 +78,8 @@ private:
uint32_t collision_layer;
bool _static;
+ SelfList<CollisionObject2DSW> pending_shape_update_list;
+
void _update_shapes();
protected:
@@ -102,33 +107,40 @@ public:
_FORCE_INLINE_ void set_instance_id(const ObjectID &p_instance_id) { instance_id = p_instance_id; }
_FORCE_INLINE_ ObjectID get_instance_id() const { return instance_id; }
+ _FORCE_INLINE_ void set_canvas_instance_id(const ObjectID &p_canvas_instance_id) { canvas_instance_id = p_canvas_instance_id; }
+ _FORCE_INLINE_ ObjectID get_canvas_instance_id() const { return canvas_instance_id; }
+
void _shape_changed();
_FORCE_INLINE_ Type get_type() const { return type; }
- void add_shape(Shape2DSW *p_shape, const Transform2D &p_transform = Transform2D());
+ void add_shape(Shape2DSW *p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false);
void set_shape(int p_index, Shape2DSW *p_shape);
void set_shape_transform(int p_index, const Transform2D &p_transform);
void set_shape_metadata(int p_index, const Variant &p_metadata);
_FORCE_INLINE_ int get_shape_count() const { return shapes.size(); }
+ _FORCE_INLINE_ bool is_shape_disabled(int p_index) const {
+ CRASH_BAD_INDEX(p_index, shapes.size());
+ return shapes[p_index].disabled;
+ }
_FORCE_INLINE_ Shape2DSW *get_shape(int p_index) const {
- ERR_FAIL_INDEX_V(p_index, shapes.size(), NULL);
+ CRASH_BAD_INDEX(p_index, shapes.size());
return shapes[p_index].shape;
}
_FORCE_INLINE_ const Transform2D &get_shape_transform(int p_index) const {
- ERR_FAIL_INDEX_V(p_index, shapes.size(), Transform2D());
+ CRASH_BAD_INDEX(p_index, shapes.size());
return shapes[p_index].xform;
}
_FORCE_INLINE_ const Transform2D &get_shape_inv_transform(int p_index) const {
- ERR_FAIL_INDEX_V(p_index, shapes.size(), Transform2D());
+ CRASH_BAD_INDEX(p_index, shapes.size());
return shapes[p_index].xform_inv;
}
_FORCE_INLINE_ const Rect2 &get_shape_aabb(int p_index) const {
- ERR_FAIL_INDEX_V(p_index, shapes.size(), Rect2());
+ CRASH_BAD_INDEX(p_index, shapes.size());
return shapes[p_index].aabb_cache;
}
_FORCE_INLINE_ const Variant &get_shape_metadata(int p_index) const {
- ERR_FAIL_INDEX_V(p_index, shapes.size(), Variant());
+ CRASH_BAD_INDEX(p_index, shapes.size());
return shapes[p_index].metadata;
}
@@ -138,19 +150,25 @@ public:
void set_shape_as_disabled(int p_idx, bool p_disabled);
_FORCE_INLINE_ bool is_shape_set_as_disabled(int p_idx) const {
- ERR_FAIL_INDEX_V(p_idx, shapes.size(), false);
+ CRASH_BAD_INDEX(p_idx, shapes.size());
return shapes[p_idx].disabled;
}
- _FORCE_INLINE_ void set_shape_as_one_way_collision(int p_idx, bool p_one_way_collision) {
- ERR_FAIL_INDEX(p_idx, shapes.size());
+ _FORCE_INLINE_ void set_shape_as_one_way_collision(int p_idx, bool p_one_way_collision, float p_margin) {
+ CRASH_BAD_INDEX(p_idx, shapes.size());
shapes.write[p_idx].one_way_collision = p_one_way_collision;
+ shapes.write[p_idx].one_way_collision_margin = p_margin;
}
_FORCE_INLINE_ bool is_shape_set_as_one_way_collision(int p_idx) const {
- ERR_FAIL_INDEX_V(p_idx, shapes.size(), false);
+ CRASH_BAD_INDEX(p_idx, shapes.size());
return shapes[p_idx].one_way_collision;
}
+ _FORCE_INLINE_ float get_shape_one_way_collision_margin(int p_idx) const {
+ CRASH_BAD_INDEX(p_idx, shapes.size());
+ return shapes[p_idx].one_way_collision_margin;
+ }
+
void set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; }
_FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; }
diff --git a/servers/physics_2d/collision_solver_2d_sat.cpp b/servers/physics_2d/collision_solver_2d_sat.cpp
index 0f32f2ec85..19e4b8c1d9 100644
--- a/servers/physics_2d/collision_solver_2d_sat.cpp
+++ b/servers/physics_2d/collision_solver_2d_sat.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -172,8 +172,8 @@ static void _generate_contacts_from_supports(const Vector2 *p_points_A, int p_po
points_B = p_points_B;
}
- int version_A = (pointcount_A > 3 ? 3 : pointcount_A) - 1;
- int version_B = (pointcount_B > 3 ? 3 : pointcount_B) - 1;
+ int version_A = (pointcount_A > 2 ? 2 : pointcount_A) - 1;
+ int version_B = (pointcount_B > 2 ? 2 : pointcount_B) - 1;
GenerateContactsFunc contacts_func = generate_contacts_func_table[version_A][version_B];
ERR_FAIL_COND(!contacts_func);
@@ -237,8 +237,8 @@ public:
Vector2 axis = p_axis;
- if (Math::abs(axis.x) < CMP_EPSILON &&
- Math::abs(axis.y) < CMP_EPSILON) {
+ if (Math::is_zero_approx(axis.x) &&
+ Math::is_zero_approx(axis.y)) {
// strange case, try an upwards separator
axis = Vector2(0.0, 1.0);
}
@@ -313,10 +313,12 @@ public:
if (best_axis == Vector2(0.0, 0.0))
return;
- callback->collided = true;
+ if (callback) {
+ callback->collided = true;
- if (!callback->callback)
- return; //only collide, no callback
+ if (!callback->callback)
+ return; //only collide, no callback
+ }
static const int max_supports = 2;
Vector2 supports_A[max_supports];
@@ -354,12 +356,13 @@ public:
supports_B[i] += best_axis * margin_B;
}
}
+ if (callback) {
+ callback->normal = best_axis;
+ _generate_contacts_from_supports(supports_A, support_count_A, supports_B, support_count_B, callback);
- callback->normal = best_axis;
- _generate_contacts_from_supports(supports_A, support_count_A, supports_B, support_count_B, callback);
-
- if (callback && callback->sep_axis && *callback->sep_axis != Vector2())
- *callback->sep_axis = Vector2(); //invalidate previous axis (no test)
+ if (callback->sep_axis && *callback->sep_axis != Vector2())
+ *callback->sep_axis = Vector2(); //invalidate previous axis (no test)
+ }
}
_FORCE_INLINE_ SeparatorAxisTest2D(const ShapeA *p_shape_A, const Transform2D &p_transform_a, const ShapeB *p_shape_B, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_A = Vector2(), const Vector2 &p_motion_B = Vector2(), real_t p_margin_A = 0, real_t p_margin_B = 0) {
diff --git a/servers/physics_2d/collision_solver_2d_sat.h b/servers/physics_2d/collision_solver_2d_sat.h
index ba35c63fbc..ecf09151e5 100644
--- a/servers/physics_2d/collision_solver_2d_sat.h
+++ b/servers/physics_2d/collision_solver_2d_sat.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/collision_solver_2d_sw.cpp
index b03a193d97..03c0fd5981 100644
--- a/servers/physics_2d/collision_solver_2d_sw.cpp
+++ b/servers/physics_2d/collision_solver_2d_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -249,6 +249,4 @@ bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p
return collision_solver(p_shape_A, p_transform_A, p_motion_A, p_shape_B, p_transform_B, p_motion_B, p_result_callback, p_userdata, false, sep_axis, margin_A, margin_B);
}
-
- return false;
}
diff --git a/servers/physics_2d/collision_solver_2d_sw.h b/servers/physics_2d/collision_solver_2d_sw.h
index 6faa166115..0c5ac5245c 100644
--- a/servers/physics_2d/collision_solver_2d_sw.h
+++ b/servers/physics_2d/collision_solver_2d_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/constraint_2d_sw.h b/servers/physics_2d/constraint_2d_sw.h
index c1954935d3..582b92ad46 100644
--- a/servers/physics_2d/constraint_2d_sw.h
+++ b/servers/physics_2d/constraint_2d_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/joints_2d_sw.cpp
index 517dce0043..acdaa6e6df 100644
--- a/servers/physics_2d/joints_2d_sw.cpp
+++ b/servers/physics_2d/joints_2d_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -92,7 +92,7 @@ normal_relative_velocity(Body2DSW *a, Body2DSW *b, Vector2 rA, Vector2 rB, Vecto
bool PinJoint2DSW::setup(real_t p_step) {
Space2DSW *space = A->get_space();
- ERR_FAIL_COND_V(!space, false;)
+ ERR_FAIL_COND_V(!space, false);
rA = A->get_transform().basis_xform(anchor_A);
rB = B ? B->get_transform().basis_xform(anchor_B) : anchor_B;
@@ -299,9 +299,7 @@ bool GrooveJoint2DSW::setup(real_t p_step) {
Vector2 delta = (B->get_transform().get_origin() + rB) - (A->get_transform().get_origin() + rA);
- // FIXME: We used to do this assignment and then override it with 0.001 right after. Investigate why.
- //real_t _b = get_bias();
- real_t _b = 0.001;
+ real_t _b = get_bias();
gbias = (delta * -(_b == 0 ? space->get_constraint_bias() : _b) * (1.0 / p_step)).clamped(get_max_bias());
// apply accumulated impulse
diff --git a/servers/physics_2d/joints_2d_sw.h b/servers/physics_2d/joints_2d_sw.h
index e2002eef0d..981d80328b 100644
--- a/servers/physics_2d/joints_2d_sw.h
+++ b/servers/physics_2d/joints_2d_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp
index 000e38c4a2..80e204087a 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,6 +36,9 @@
#include "core/project_settings.h"
#include "core/script_language.h"
+#define FLUSH_QUERY_CHECK(m_object) \
+ ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead.");
+
RID Physics2DServerSW::_shape_create(ShapeType p_shape) {
Shape2DSW *shape = NULL;
@@ -169,7 +172,9 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &
cbk->invalid_by_dir++;
return;
}
- if (cbk->valid_dir.dot((p_point_A - p_point_B).normalized()) < 0.7071) {
+ Vector2 rel_dir = (p_point_A - p_point_B).normalized();
+
+ if (cbk->valid_dir.dot(rel_dir) < 0.7071) { //sqrt(2)/2.0 - 45 degrees
cbk->invalid_by_dir++;
/*
@@ -201,12 +206,14 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &
return;
cbk->ptr[min_depth_idx * 2 + 0] = p_point_A;
cbk->ptr[min_depth_idx * 2 + 1] = p_point_B;
+ cbk->passed++;
} else {
cbk->ptr[cbk->amount * 2 + 0] = p_point_A;
cbk->ptr[cbk->amount * 2 + 1] = p_point_B;
cbk->amount++;
+ cbk->passed++;
}
}
@@ -225,6 +232,7 @@ bool Physics2DServerSW::shape_collide(RID p_shape_A, const Transform2D &p_xform_
CollCbkData cbk;
cbk.max = p_result_max;
cbk.amount = 0;
+ cbk.passed = 0;
cbk.ptr = r_results;
bool res = CollisionSolver2DSW::solve(shape_A, p_xform_A, p_motion_A, shape_B, p_xform_B, p_motion_B, _shape_col_cbk, &cbk);
@@ -305,11 +313,7 @@ Physics2DDirectSpaceState *Physics2DServerSW::space_get_direct_state(RID p_space
Space2DSW *space = space_owner.get(p_space);
ERR_FAIL_COND_V(!space, NULL);
- if ((using_threads && !doing_sync) || space->is_locked()) {
-
- ERR_EXPLAIN("Space state is inaccessible right now, wait for iteration or physics process notification.");
- ERR_FAIL_V(NULL);
- }
+ ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || space->is_locked(), NULL, "Space state is inaccessible right now, wait for iteration or physics process notification.");
return space->get_direct_state();
}
@@ -367,7 +371,7 @@ Physics2DServer::AreaSpaceOverrideMode Physics2DServerSW::area_get_space_overrid
return area->get_space_override_mode();
}
-void Physics2DServerSW::area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform) {
+void Physics2DServerSW::area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform, bool p_disabled) {
Area2DSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
@@ -375,7 +379,7 @@ void Physics2DServerSW::area_add_shape(RID p_area, RID p_shape, const Transform2
Shape2DSW *shape = shape_owner.get(p_shape);
ERR_FAIL_COND(!shape);
- area->add_shape(shape, p_transform);
+ area->add_shape(shape, p_transform, p_disabled);
}
void Physics2DServerSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) {
@@ -401,8 +405,9 @@ void Physics2DServerSW::area_set_shape_disabled(RID p_area, int p_shape, bool p_
Area2DSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
-
ERR_FAIL_INDEX(p_shape, area->get_shape_count());
+ FLUSH_QUERY_CHECK(area);
+
area->set_shape_as_disabled(p_shape, p_disabled);
}
@@ -448,7 +453,7 @@ void Physics2DServerSW::area_clear_shapes(RID p_area) {
area->remove_shape(0);
}
-void Physics2DServerSW::area_attach_object_instance_id(RID p_area, ObjectID p_ID) {
+void Physics2DServerSW::area_attach_object_instance_id(RID p_area, ObjectID p_id) {
if (space_owner.owns(p_area)) {
Space2DSW *space = space_owner.get(p_area);
@@ -456,7 +461,7 @@ void Physics2DServerSW::area_attach_object_instance_id(RID p_area, ObjectID p_ID
}
Area2DSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
- area->set_instance_id(p_ID);
+ area->set_instance_id(p_id);
}
ObjectID Physics2DServerSW::area_get_object_instance_id(RID p_area) const {
@@ -469,6 +474,27 @@ ObjectID Physics2DServerSW::area_get_object_instance_id(RID p_area) const {
return area->get_instance_id();
}
+void Physics2DServerSW::area_attach_canvas_instance_id(RID p_area, ObjectID p_id) {
+
+ if (space_owner.owns(p_area)) {
+ Space2DSW *space = space_owner.get(p_area);
+ p_area = space->get_default_area()->get_self();
+ }
+ Area2DSW *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+ area->set_canvas_instance_id(p_id);
+}
+ObjectID Physics2DServerSW::area_get_canvas_instance_id(RID p_area) const {
+
+ if (space_owner.owns(p_area)) {
+ Space2DSW *space = space_owner.get(p_area);
+ p_area = space->get_default_area()->get_self();
+ }
+ Area2DSW *area = area_owner.get(p_area);
+ ERR_FAIL_COND_V(!area, 0);
+ return area->get_canvas_instance_id();
+}
+
void Physics2DServerSW::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) {
if (space_owner.owns(p_area)) {
@@ -518,6 +544,7 @@ void Physics2DServerSW::area_set_monitorable(RID p_area, bool p_monitorable) {
Area2DSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
+ FLUSH_QUERY_CHECK(area);
area->set_monitorable(p_monitorable);
}
@@ -596,6 +623,7 @@ void Physics2DServerSW::body_set_mode(RID p_body, BodyMode p_mode) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
+ FLUSH_QUERY_CHECK(body);
body->set_mode(p_mode);
};
@@ -608,7 +636,7 @@ Physics2DServer::BodyMode Physics2DServerSW::body_get_mode(RID p_body) const {
return body->get_mode();
};
-void Physics2DServerSW::body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform) {
+void Physics2DServerSW::body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform, bool p_disabled) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
@@ -616,7 +644,7 @@ void Physics2DServerSW::body_add_shape(RID p_body, RID p_shape, const Transform2
Shape2DSW *shape = shape_owner.get(p_shape);
ERR_FAIL_COND(!shape);
- body->add_shape(shape, p_transform);
+ body->add_shape(shape, p_transform, p_disabled);
}
void Physics2DServerSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) {
@@ -698,19 +726,19 @@ void Physics2DServerSW::body_set_shape_disabled(RID p_body, int p_shape_idx, boo
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
-
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
+ FLUSH_QUERY_CHECK(body);
body->set_shape_as_disabled(p_shape_idx, p_disabled);
}
-void Physics2DServerSW::body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable) {
+void Physics2DServerSW::body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, float p_margin) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
-
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
+ FLUSH_QUERY_CHECK(body);
- body->set_shape_as_one_way_collision(p_shape_idx, p_enable);
+ body->set_shape_as_one_way_collision(p_shape_idx, p_enable, p_margin);
}
void Physics2DServerSW::body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode) {
@@ -728,12 +756,12 @@ Physics2DServerSW::CCDMode Physics2DServerSW::body_get_continuous_collision_dete
return body->get_continuous_collision_detection_mode();
}
-void Physics2DServerSW::body_attach_object_instance_id(RID p_body, uint32_t p_ID) {
+void Physics2DServerSW::body_attach_object_instance_id(RID p_body, uint32_t p_id) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
- body->set_instance_id(p_ID);
+ body->set_instance_id(p_id);
};
uint32_t Physics2DServerSW::body_get_object_instance_id(RID p_body) const {
@@ -744,6 +772,22 @@ uint32_t Physics2DServerSW::body_get_object_instance_id(RID p_body) const {
return body->get_instance_id();
};
+void Physics2DServerSW::body_attach_canvas_instance_id(RID p_body, uint32_t p_id) {
+
+ Body2DSW *body = body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_canvas_instance_id(p_id);
+};
+
+uint32_t Physics2DServerSW::body_get_canvas_instance_id(RID p_body) const {
+
+ Body2DSW *body = body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_canvas_instance_id();
+};
+
void Physics2DServerSW::body_set_collision_layer(RID p_body, uint32_t p_layer) {
Body2DSW *body = body_owner.get(p_body);
@@ -851,6 +895,8 @@ void Physics2DServerSW::body_apply_torque_impulse(RID p_body, real_t p_torque) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
+ _update_shapes();
+
body->apply_torque_impulse(p_torque);
}
@@ -859,6 +905,8 @@ void Physics2DServerSW::body_apply_impulse(RID p_body, const Vector2 &p_pos, con
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
+ _update_shapes();
+
body->apply_impulse(p_pos, p_impulse);
body->wakeup();
};
@@ -893,6 +941,8 @@ void Physics2DServerSW::body_set_axis_velocity(RID p_body, const Vector2 &p_axis
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
+ _update_shapes();
+
Vector2 v = body->get_linear_velocity();
Vector2 axis = p_axis_velocity.normalized();
v -= axis * axis.dot(v);
@@ -1001,6 +1051,8 @@ bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from,
ERR_FAIL_COND_V(!body->get_space(), false);
ERR_FAIL_COND_V(body->get_space()->is_locked(), false);
+ _update_shapes();
+
return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes);
}
@@ -1016,22 +1068,15 @@ int Physics2DServerSW::body_test_ray_separation(RID p_body, const Transform2D &p
Physics2DDirectBodyState *Physics2DServerSW::body_get_direct_state(RID p_body) {
- if ((using_threads && !doing_sync)) {
- ERR_EXPLAIN("Body state is inaccessible right now, wait for iteration or physics process notification.");
- ERR_FAIL_V(NULL);
- }
+ ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), NULL, "Body state is inaccessible right now, wait for iteration or physics process notification.");
if (!body_owner.owns(p_body))
return NULL;
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body, NULL);
-
- if (body->get_space()->is_locked()) {
-
- ERR_EXPLAIN("Body state is inaccessible right now, wait for iteration or physics process notification.");
- ERR_FAIL_V(NULL);
- }
+ ERR_FAIL_COND_V(!body->get_space(), NULL);
+ ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), NULL, "Body state is inaccessible right now, wait for iteration or physics process notification.");
direct_state->body = body;
return direct_state;
@@ -1186,6 +1231,8 @@ Physics2DServer::JointType Physics2DServerSW::joint_get_type(RID p_joint) const
void Physics2DServerSW::free(RID p_rid) {
+ _update_shapes(); // just in case
+
if (shape_owner.owns(p_rid)) {
Shape2DSW *shape = shape_owner.get(p_rid);
@@ -1259,8 +1306,7 @@ void Physics2DServerSW::free(RID p_rid) {
} else {
- ERR_EXPLAIN("Invalid ID");
- ERR_FAIL();
+ ERR_FAIL_MSG("Invalid ID.");
}
};
@@ -1283,6 +1329,8 @@ void Physics2DServerSW::step(real_t p_step) {
if (!active)
return;
+ _update_shapes();
+
doing_sync = false;
last_step = p_step;
@@ -1309,6 +1357,8 @@ void Physics2DServerSW::flush_queries() {
if (!active)
return;
+ flushing_queries = true;
+
uint64_t time_beg = OS::get_singleton()->get_ticks_usec();
for (Set<const Space2DSW *>::Element *E = active_spaces.front(); E; E = E->next()) {
@@ -1317,6 +1367,8 @@ void Physics2DServerSW::flush_queries() {
space->call_queries();
}
+ flushing_queries = false;
+
if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_profiling()) {
uint64_t total_time[Space2DSW::ELAPSED_TIME_MAX];
@@ -1362,6 +1414,14 @@ void Physics2DServerSW::finish() {
memdelete(direct_state);
};
+void Physics2DServerSW::_update_shapes() {
+
+ while (pending_shape_update_list.first()) {
+ pending_shape_update_list.first()->self()->_shape_changed();
+ pending_shape_update_list.remove(pending_shape_update_list.first());
+ }
+}
+
int Physics2DServerSW::get_process_info(ProcessInfo p_info) {
switch (p_info) {
@@ -1395,6 +1455,7 @@ Physics2DServerSW::Physics2DServerSW() {
active_objects = 0;
collision_pairs = 0;
using_threads = int(ProjectSettings::get_singleton()->get("physics/2d/thread_model")) == 2;
+ flushing_queries = false;
};
Physics2DServerSW::~Physics2DServerSW(){
diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h
index d4fc44b1d7..72625c397c 100644
--- a/servers/physics_2d/physics_2d_server_sw.h
+++ b/servers/physics_2d/physics_2d_server_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -54,6 +54,8 @@ class Physics2DServerSW : public Physics2DServer {
bool using_threads;
+ bool flushing_queries;
+
Step2DSW *stepper;
Set<const Space2DSW *> active_spaces;
@@ -68,6 +70,9 @@ class Physics2DServerSW : public Physics2DServer {
static Physics2DServerSW *singletonsw;
//void _clear_query(Query2DSW *p_query);
+ friend class CollisionObject2DSW;
+ SelfList<CollisionObject2DSW>::List pending_shape_update_list;
+ void _update_shapes();
RID _shape_create(ShapeType p_shape);
@@ -78,6 +83,7 @@ public:
real_t valid_depth;
int max;
int amount;
+ int passed;
int invalid_by_dir;
Vector2 *ptr;
};
@@ -128,7 +134,7 @@ public:
virtual void area_set_space(RID p_area, RID p_space);
virtual RID area_get_space(RID p_area) const;
- virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform = Transform2D());
+ virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false);
virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape);
virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform);
@@ -141,9 +147,12 @@ public:
virtual void area_remove_shape(RID p_area, int p_shape_idx);
virtual void area_clear_shapes(RID p_area);
- virtual void area_attach_object_instance_id(RID p_area, ObjectID p_ID);
+ virtual void area_attach_object_instance_id(RID p_area, ObjectID p_id);
virtual ObjectID area_get_object_instance_id(RID p_area) const;
+ virtual void area_attach_canvas_instance_id(RID p_area, ObjectID p_id);
+ virtual ObjectID area_get_canvas_instance_id(RID p_area) const;
+
virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value);
virtual void area_set_transform(RID p_area, const Transform2D &p_transform);
@@ -169,7 +178,7 @@ public:
virtual void body_set_mode(RID p_body, BodyMode p_mode);
virtual BodyMode body_get_mode(RID p_body) const;
- virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform = Transform2D());
+ virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false);
virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape);
virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform);
virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant &p_metadata);
@@ -183,11 +192,14 @@ public:
virtual void body_clear_shapes(RID p_body);
virtual void body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled);
- virtual void body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable);
+ virtual void body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, float p_margin);
- virtual void body_attach_object_instance_id(RID p_body, uint32_t p_ID);
+ virtual void body_attach_object_instance_id(RID p_body, uint32_t p_id);
virtual uint32_t body_get_object_instance_id(RID p_body) const;
+ virtual void body_attach_canvas_instance_id(RID p_body, uint32_t p_id);
+ virtual uint32_t body_get_canvas_instance_id(RID p_body) const;
+
virtual void body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode);
virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const;
@@ -272,6 +284,8 @@ public:
virtual void end_sync();
virtual void finish();
+ virtual bool is_flushing_queries() const { return flushing_queries; }
+
int get_process_info(ProcessInfo p_info);
Physics2DServerSW();
diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.cpp b/servers/physics_2d/physics_2d_server_wrap_mt.cpp
index 3ded4b717a..c698290fd9 100644
--- a/servers/physics_2d/physics_2d_server_wrap_mt.cpp
+++ b/servers/physics_2d/physics_2d_server_wrap_mt.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -54,8 +54,6 @@ void Physics2DServerWrapMT::thread_loop() {
server_thread = Thread::get_caller_id();
- OS::get_singleton()->make_rendering_thread();
-
physics_2d_server->init();
exit = false;
diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h
index 5f5fd3866f..33a184ba3f 100644
--- a/servers/physics_2d/physics_2d_server_wrap_mt.h
+++ b/servers/physics_2d/physics_2d_server_wrap_mt.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -140,7 +140,7 @@ public:
FUNC2(area_set_space_override_mode, RID, AreaSpaceOverrideMode);
FUNC1RC(AreaSpaceOverrideMode, area_get_space_override_mode, RID);
- FUNC3(area_add_shape, RID, RID, const Transform2D &);
+ FUNC4(area_add_shape, RID, RID, const Transform2D &, bool);
FUNC3(area_set_shape, RID, int, RID);
FUNC3(area_set_shape_transform, RID, int, const Transform2D &);
FUNC3(area_set_shape_disabled, RID, int, bool);
@@ -154,6 +154,9 @@ public:
FUNC2(area_attach_object_instance_id, RID, ObjectID);
FUNC1RC(ObjectID, area_get_object_instance_id, RID);
+ FUNC2(area_attach_canvas_instance_id, RID, ObjectID);
+ FUNC1RC(ObjectID, area_get_canvas_instance_id, RID);
+
FUNC3(area_set_param, RID, AreaParameter, const Variant &);
FUNC2(area_set_transform, RID, const Transform2D &);
@@ -180,7 +183,7 @@ public:
FUNC2(body_set_mode, RID, BodyMode);
FUNC1RC(BodyMode, body_get_mode, RID);
- FUNC3(body_add_shape, RID, RID, const Transform2D &);
+ FUNC4(body_add_shape, RID, RID, const Transform2D &, bool);
FUNC3(body_set_shape, RID, int, RID);
FUNC3(body_set_shape_transform, RID, int, const Transform2D &);
FUNC3(body_set_shape_metadata, RID, int, const Variant &);
@@ -191,7 +194,7 @@ public:
FUNC2RC(RID, body_get_shape, RID, int);
FUNC3(body_set_shape_disabled, RID, int, bool);
- FUNC3(body_set_shape_as_one_way_collision, RID, int, bool);
+ FUNC4(body_set_shape_as_one_way_collision, RID, int, bool, float);
FUNC2(body_remove_shape, RID, int);
FUNC1(body_clear_shapes, RID);
@@ -199,6 +202,9 @@ public:
FUNC2(body_attach_object_instance_id, RID, uint32_t);
FUNC1RC(uint32_t, body_get_object_instance_id, RID);
+ FUNC2(body_attach_canvas_instance_id, RID, uint32_t);
+ FUNC1RC(uint32_t, body_get_canvas_instance_id, RID);
+
FUNC2(body_set_continuous_collision_detection_mode, RID, CCDMode);
FUNC1RC(CCDMode, body_get_continuous_collision_detection_mode, RID);
@@ -306,6 +312,10 @@ public:
virtual void flush_queries();
virtual void finish();
+ virtual bool is_flushing_queries() const {
+ return physics_2d_server->is_flushing_queries();
+ }
+
int get_process_info(ProcessInfo p_info) {
return physics_2d_server->get_process_info(p_info);
}
@@ -317,11 +327,11 @@ public:
static Physics2DServer *init_server() {
int tm = GLOBAL_DEF("physics/2d/thread_model", 1);
- if (tm == 0) //single unsafe
+ if (tm == 0) // single unsafe
return memnew(T);
- else if (tm == 1) //single saef
+ else if (tm == 1) // single safe
return memnew(Physics2DServerWrapMT(memnew(T), false));
- else //single unsafe
+ else // multi threaded
return memnew(Physics2DServerWrapMT(memnew(T), true));
}
diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp
index 94b0a0a0c7..48799a56fb 100644
--- a/servers/physics_2d/shape_2d_sw.cpp
+++ b/servers/physics_2d/shape_2d_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,7 +31,7 @@
#include "shape_2d_sw.h"
#include "core/math/geometry.h"
-#include "core/sort.h"
+#include "core/sort_array.h"
void Shape2DSW::configure(const Rect2 &p_aabb) {
aabb = p_aabb;
@@ -240,12 +240,7 @@ bool SegmentShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &
real_t SegmentShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
- Vector2 s[2] = { a * p_scale, b * p_scale };
-
- real_t l = s[1].distance_to(s[0]);
- Vector2 ofs = (s[0] + s[1]) * 0.5;
-
- return p_mass * (l * l / 12.0 + ofs.length_squared());
+ return p_mass * ((a * p_scale).distance_squared_to(b * p_scale)) / 12;
}
void SegmentShape2DSW::set_data(const Variant &p_data) {
@@ -318,7 +313,9 @@ bool CircleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p
real_t CircleShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
- return (radius * radius) * (p_scale.x * 0.5 + p_scale.y * 0.5);
+ real_t a = radius * p_scale.x;
+ real_t b = radius * p_scale.y;
+ return p_mass * (a * a + b * b) / 4;
}
void CircleShape2DSW::set_data(const Variant &p_data) {
@@ -369,8 +366,11 @@ void RectangleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_suppor
}
bool RectangleShape2DSW::contains_point(const Vector2 &p_point) const {
-
- return Math::abs(p_point.x) < half_extents.x && Math::abs(p_point.y) < half_extents.y;
+ float x = p_point.x;
+ float y = p_point.y;
+ float edge_x = half_extents.x;
+ float edge_y = half_extents.y;
+ return (x >= -edge_x) && (x < edge_x) && (y >= -edge_y) && (y < edge_y);
}
bool RectangleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
@@ -583,7 +583,7 @@ bool ConvexPolygonShape2DSW::contains_point(const Vector2 &p_point) const {
in = true;
}
- return (in && !out) || (!in && out);
+ return in != out;
}
bool ConvexPolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
@@ -634,7 +634,7 @@ real_t ConvexPolygonShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2
aabb.expand_to(points[i].pos * p_scale);
}
- return p_mass * aabb.size.dot(aabb.size) / 12.0 + p_mass * (aabb.position + aabb.size * 0.5).length_squared();
+ return p_mass * aabb.size.dot(aabb.size) / 12.0;
}
void ConvexPolygonShape2DSW::set_data(const Variant &p_data) {
@@ -775,22 +775,22 @@ bool ConcavePolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Ve
while (true) {
uint32_t node = stack[level] & NODE_IDX_MASK;
- const BVH &b = bvhptr[node];
+ const BVH &bvh = bvhptr[node];
bool done = false;
switch (stack[level] >> VISITED_BIT_SHIFT) {
case TEST_AABB_BIT: {
- bool valid = b.aabb.intersects_segment(p_begin, p_end);
+ bool valid = bvh.aabb.intersects_segment(p_begin, p_end);
if (!valid) {
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
} else {
- if (b.left < 0) {
+ if (bvh.left < 0) {
- const Segment &s = segmentptr[b.right];
+ const Segment &s = segmentptr[bvh.right];
Vector2 a = pointptr[s.points[0]];
Vector2 b = pointptr[s.points[1]];
@@ -820,14 +820,14 @@ bool ConcavePolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Ve
case VISIT_LEFT_BIT: {
stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.left | TEST_AABB_BIT;
+ stack[level + 1] = bvh.left | TEST_AABB_BIT;
level++;
}
continue;
case VISIT_RIGHT_BIT: {
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.right | TEST_AABB_BIT;
+ stack[level + 1] = bvh.right | TEST_AABB_BIT;
level++;
}
continue;
@@ -986,7 +986,7 @@ Variant ConcavePolygonShape2DSW::get_data() const {
w[(i << 1) + 1] = points[segments[i].points[1]];
}
- w = PoolVector<Vector2>::Write();
+ w.release();
return rsegments;
}
@@ -1025,21 +1025,21 @@ void ConcavePolygonShape2DSW::cull(const Rect2 &p_local_aabb, Callback p_callbac
while (true) {
uint32_t node = stack[level] & NODE_IDX_MASK;
- const BVH &b = bvhptr[node];
+ const BVH &bvh = bvhptr[node];
switch (stack[level] >> VISITED_BIT_SHIFT) {
case TEST_AABB_BIT: {
- bool valid = p_local_aabb.intersects(b.aabb);
+ bool valid = p_local_aabb.intersects(bvh.aabb);
if (!valid) {
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
} else {
- if (b.left < 0) {
+ if (bvh.left < 0) {
- const Segment &s = segmentptr[b.right];
+ const Segment &s = segmentptr[bvh.right];
Vector2 a = pointptr[s.points[0]];
Vector2 b = pointptr[s.points[1]];
@@ -1058,14 +1058,14 @@ void ConcavePolygonShape2DSW::cull(const Rect2 &p_local_aabb, Callback p_callbac
case VISIT_LEFT_BIT: {
stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.left | TEST_AABB_BIT;
+ stack[level + 1] = bvh.left | TEST_AABB_BIT;
level++;
}
continue;
case VISIT_RIGHT_BIT: {
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.right | TEST_AABB_BIT;
+ stack[level + 1] = bvh.right | TEST_AABB_BIT;
level++;
}
continue;
diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h
index d937301f3c..632032cc23 100644
--- a/servers/physics_2d/shape_2d_sw.h
+++ b/servers/physics_2d/shape_2d_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index f36328c985..2778775446 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,9 +31,9 @@
#include "space_2d_sw.h"
#include "collision_solver_2d_sw.h"
+#include "core/os/os.h"
#include "core/pair.h"
#include "physics_2d_server_sw.h"
-
_FORCE_INLINE_ static bool _can_collide_with(CollisionObject2DSW *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (!(p_object->get_collision_layer() & p_collision_mask)) {
@@ -49,7 +49,7 @@ _FORCE_INLINE_ static bool _can_collide_with(CollisionObject2DSW *p_object, uint
return true;
}
-int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) {
+int Physics2DDirectSpaceStateSW::_intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas, ObjectID p_canvas_instance_id) {
if (p_result_max <= 0)
return 0;
@@ -75,6 +75,9 @@ int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeRe
if (p_pick_point && !col_obj->is_pickable())
continue;
+ if (p_filter_by_canvas && col_obj->get_canvas_instance_id() != p_canvas_instance_id)
+ continue;
+
int shape_idx = space->intersection_query_subindex_results[i];
Shape2DSW *shape = col_obj->get_shape(shape_idx);
@@ -100,6 +103,16 @@ int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeRe
return cc;
}
+int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) {
+
+ return _intersect_point_impl(p_point, r_results, p_result_max, p_exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas, p_pick_point);
+}
+
+int Physics2DDirectSpaceStateSW::intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) {
+
+ return _intersect_point_impl(p_point, r_results, p_result_max, p_exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas, p_pick_point, true, p_canvas_instance_id);
+}
+
bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
ERR_FAIL_COND_V(space->locked, false);
@@ -267,7 +280,7 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transfor
real_t hi = 1;
Vector2 mnormal = p_motion.normalized();
- for (int i = 0; i < 8; i++) { //steps should be customizable..
+ for (int j = 0; j < 8; j++) { //steps should be customizable..
real_t ofs = (low + hi) * 0.5;
@@ -315,14 +328,11 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D &
Physics2DServerSW::CollCbkData cbk;
cbk.max = p_result_max;
cbk.amount = 0;
+ cbk.passed = 0;
cbk.ptr = r_results;
- CollisionSolver2DSW::CallbackResult cbkres = NULL;
+ CollisionSolver2DSW::CallbackResult cbkres = Physics2DServerSW::_shape_col_cbk;
- Physics2DServerSW::CollCbkData *cbkptr = NULL;
- if (p_result_max > 0) {
- cbkptr = &cbk;
- cbkres = Physics2DServerSW::_shape_col_cbk;
- }
+ Physics2DServerSW::CollCbkData *cbkptr = &cbk;
for (int i = 0; i < amount; i++) {
@@ -339,7 +349,7 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D &
cbk.valid_depth = 0;
if (CollisionSolver2DSW::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, NULL, p_margin)) {
- collided = p_result_max == 0 || cbk.amount > 0;
+ collided = cbk.amount > 0;
}
}
@@ -352,6 +362,8 @@ struct _RestCallbackData2D {
const CollisionObject2DSW *object;
const CollisionObject2DSW *best_object;
+ int local_shape;
+ int best_local_shape;
int shape;
int best_shape;
Vector2 best_contact;
@@ -359,6 +371,7 @@ struct _RestCallbackData2D {
real_t best_len;
Vector2 valid_dir;
real_t valid_depth;
+ real_t min_allowed_depth;
};
static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) {
@@ -374,6 +387,10 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B,
Vector2 contact_rel = p_point_B - p_point_A;
real_t len = contact_rel.length();
+
+ if (len < rd->min_allowed_depth)
+ return;
+
if (len <= rd->best_len)
return;
@@ -382,6 +399,7 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B,
rd->best_normal = contact_rel / len;
rd->best_object = rd->object;
rd->best_shape = rd->shape;
+ rd->best_local_shape = rd->local_shape;
}
bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
@@ -399,6 +417,7 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_sh
rcd.best_len = 0;
rcd.best_object = NULL;
rcd.best_shape = 0;
+ rcd.min_allowed_depth = space->test_motion_min_contact_depth;
for (int i = 0; i < amount; i++) {
@@ -415,12 +434,13 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_sh
rcd.valid_depth = 0;
rcd.object = col_obj;
rcd.shape = shape_idx;
+ rcd.local_shape = 0;
bool sc = CollisionSolver2DSW::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, NULL, p_margin);
if (!sc)
continue;
}
- if (rcd.best_len == 0)
+ if (rcd.best_len == 0 || !rcd.best_object)
return false;
r_info->collider_id = rcd.best_object->get_instance_id();
@@ -487,12 +507,26 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
Rect2 body_aabb;
+ bool shapes_found = false;
+
for (int i = 0; i < p_body->get_shape_count(); i++) {
- if (i == 0)
+ if (p_body->is_shape_set_as_disabled(i))
+ continue;
+
+ if (p_body->get_shape(i)->get_type() != Physics2DServer::SHAPE_RAY)
+ continue;
+
+ if (!shapes_found) {
body_aabb = p_body->get_shape_aabb(i);
- else
+ shapes_found = true;
+ } else {
body_aabb = body_aabb.merge(p_body->get_shape_aabb(i));
+ }
+ }
+
+ if (!shapes_found) {
+ return 0;
}
// Undo the currently transform the physics server is aware of and apply the provided one
@@ -526,7 +560,6 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
bool collided = false;
int amount = _cull_aabb_for_body(p_body, body_aabb);
- int ray_index = 0;
for (int j = 0; j < p_body->get_shape_count(); j++) {
if (p_body->is_shape_set_as_disabled(j))
@@ -545,6 +578,7 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
int shape_idx = intersection_query_subindex_results[i];
cbk.amount = 0;
+ cbk.passed = 0;
cbk.ptr = sr;
cbk.invalid_by_dir = 0;
@@ -555,25 +589,49 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
}
}
+ Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
+
+ /*
+ * There is no point in supporting one way collisions with ray shapes, as they will always collide in the desired
+ * direction. Use a short ray shape if you want to achieve a similar effect.
+ *
if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
- cbk.valid_dir = body_shape_xform.get_axis(1).normalized();
+ cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
cbk.valid_depth = p_margin; //only valid depth is the collision margin
cbk.invalid_by_dir = 0;
} else {
- cbk.valid_dir = Vector2();
- cbk.valid_depth = 0;
- cbk.invalid_by_dir = 0;
+*/
+
+ cbk.valid_dir = Vector2();
+ cbk.valid_depth = 0;
+ cbk.invalid_by_dir = 0;
+
+ /*
}
+ */
Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
- if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, NULL, p_margin)) {
+ if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, NULL, p_margin)) {
if (cbk.amount > 0) {
collided = true;
}
- if (ray_index < p_result_max) {
+ int ray_index = -1; //reuse shape
+ for (int k = 0; k < rays_found; k++) {
+ if (r_results[ray_index].collision_local_shape == j) {
+ ray_index = k;
+ }
+ }
+
+ if (ray_index == -1 && rays_found < p_result_max) {
+ ray_index = rays_found;
+ rays_found++;
+ }
+
+ if (ray_index != -1) {
+
Physics2DServer::SeparationResult &result = r_results[ray_index];
for (int k = 0; k < cbk.amount; k++) {
@@ -588,7 +646,8 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
result.collision_depth = depth;
result.collision_point = b;
result.collision_normal = (b - a).normalized();
- result.collision_local_shape = shape_idx;
+ result.collision_local_shape = j;
+ result.collider_shape = shape_idx;
result.collider = col_obj->get_self();
result.collider_id = col_obj->get_instance_id();
result.collider_metadata = col_obj->get_shape_metadata(shape_idx);
@@ -603,12 +662,8 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
}
}
}
-
- ray_index++;
}
- rays_found = MAX(ray_index, rays_found);
-
if (!collided || recover_motion == Vector2()) {
break;
}
@@ -647,12 +702,30 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
Rect2 body_aabb;
+ bool shapes_found = false;
+
for (int i = 0; i < p_body->get_shape_count(); i++) {
- if (i == 0)
+ if (p_body->is_shape_set_as_disabled(i))
+ continue;
+
+ if (p_exclude_raycast_shapes && p_body->get_shape(i)->get_type() == Physics2DServer::SHAPE_RAY)
+ continue;
+
+ if (!shapes_found) {
body_aabb = p_body->get_shape_aabb(i);
- else
+ shapes_found = true;
+ } else {
body_aabb = body_aabb.merge(p_body->get_shape_aabb(i));
+ }
+ }
+
+ if (!shapes_found) {
+ if (r_result) {
+ *r_result = Physics2DServer::MotionResult();
+ r_result->motion = p_motion;
+ }
+ return false;
}
// Undo the currently transform the physics server is aware of and apply the provided one
@@ -663,6 +736,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
ExcludedShapeSW excluded_shape_pairs[max_excluded_shape_pairs];
int excluded_shape_pair_count = 0;
+ float separation_margin = MIN(p_margin, MAX(0.0, p_motion.length() - CMP_EPSILON)); //don't separate by more than the intended motion
+
Transform2D body_transform = p_from;
{
@@ -677,6 +752,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
Physics2DServerSW::CollCbkData cbk;
cbk.max = max_results;
cbk.amount = 0;
+ cbk.passed = 0;
cbk.ptr = sr;
cbk.invalid_by_dir = 0;
excluded_shape_pair_count = 0; //last step is the one valid
@@ -710,24 +786,43 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
}
+ Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
+
if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
- cbk.valid_dir = body_shape_xform.get_axis(1).normalized();
- cbk.valid_depth = p_margin; //only valid depth is the collision margin
+ cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
+
+ float owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx);
+ cbk.valid_depth = MAX(owc_margin, p_margin); //user specified, but never less than actual margin or it won't work
cbk.invalid_by_dir = 0;
+ if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
+ const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
+ if (b->get_mode() == Physics2DServer::BODY_MODE_KINEMATIC || b->get_mode() == Physics2DServer::BODY_MODE_RIGID) {
+ //fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction
+ Vector2 lv = b->get_linear_velocity();
+ //compute displacement from linear velocity
+ Vector2 motion = lv * Physics2DDirectBodyStateSW::singleton->step;
+ float motion_len = motion.length();
+ motion.normalize();
+ cbk.valid_depth += motion_len * MAX(motion.dot(-cbk.valid_dir), 0.0);
+ }
+ }
} else {
cbk.valid_dir = Vector2();
cbk.valid_depth = 0;
cbk.invalid_by_dir = 0;
}
+ int current_passed = cbk.passed; //save how many points passed collision
+ bool did_collide = false;
+
Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
- if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, NULL, p_margin)) {
- collided = cbk.amount > 0;
+ if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, NULL, separation_margin)) {
+ did_collide = cbk.passed > current_passed; //more passed, so collision actually existed
}
- if (!collided && cbk.invalid_by_dir > 0) {
+ if (!did_collide && cbk.invalid_by_dir > 0) {
//this shape must be excluded
if (excluded_shape_pair_count < max_excluded_shape_pairs) {
ExcludedShapeSW esp;
@@ -737,6 +832,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
excluded_shape_pairs[excluded_shape_pair_count++] = esp;
}
}
+
+ if (did_collide) {
+ collided = true;
+ }
}
}
@@ -824,14 +923,14 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
continue;
}
- Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(col_shape_idx);
+ Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(col_shape_idx);
//test initial overlap, does it collide if going all the way?
- if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion, against_shape, col_obj_xform, Vector2(), NULL, NULL, NULL, 0)) {
+ if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion, against_shape, col_obj_shape_xform, Vector2(), NULL, NULL, NULL, 0)) {
continue;
}
//test initial overlap
- if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_xform, Vector2(), NULL, NULL, NULL, 0)) {
+ if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), NULL, NULL, NULL, 0)) {
if (col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) {
continue;
@@ -851,7 +950,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
real_t ofs = (low + hi) * 0.5;
Vector2 sep = mnormal; //important optimization for this to work fast enough
- bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * ofs, against_shape, col_obj_xform, Vector2(), NULL, NULL, &sep, 0);
+ bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * ofs, against_shape, col_obj_shape_xform, Vector2(), NULL, NULL, &sep, 0);
if (collided) {
@@ -868,13 +967,14 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
Physics2DServerSW::CollCbkData cbk;
cbk.max = 1;
cbk.amount = 0;
+ cbk.passed = 0;
cbk.ptr = cd;
- cbk.valid_dir = body_shape_xform.get_axis(1).normalized();
+ cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
cbk.valid_depth = 10e20;
Vector2 sep = mnormal; //important optimization for this to work fast enough
- bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_xform, Vector2(), Physics2DServerSW::_shape_col_cbk, &cbk, &sep, 0);
+ bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_shape_xform, Vector2(), Physics2DServerSW::_shape_col_cbk, &cbk, &sep, 0);
if (!collided || cbk.amount == 0) {
continue;
}
@@ -907,16 +1007,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
bool collided = false;
if (safe >= 1) {
- //not collided
- collided = false;
- if (r_result) {
-
- r_result->motion = p_motion;
- r_result->remainder = Vector2();
- r_result->motion += (body_transform.get_origin() - p_from.get_origin());
- }
+ best_shape = -1; //no best shape with cast, reset to -1
+ }
- } else {
+ {
//it collided, let's get the rest info in unsafe advance
Transform2D ugt = body_transform;
@@ -926,53 +1020,71 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
rcd.best_len = 0;
rcd.best_object = NULL;
rcd.best_shape = 0;
+ rcd.min_allowed_depth = test_motion_min_contact_depth;
- Transform2D body_shape_xform = ugt * p_body->get_shape_transform(best_shape);
- Shape2DSW *body_shape = p_body->get_shape(best_shape);
+ //optimization
+ int from_shape = best_shape != -1 ? best_shape : 0;
+ int to_shape = best_shape != -1 ? best_shape + 1 : p_body->get_shape_count();
- body_aabb.position += p_motion * unsafe;
+ for (int j = from_shape; j < to_shape; j++) {
- int amount = _cull_aabb_for_body(p_body, body_aabb);
+ if (p_body->is_shape_set_as_disabled(j))
+ continue;
- for (int i = 0; i < amount; i++) {
+ Transform2D body_shape_xform = ugt * p_body->get_shape_transform(j);
+ Shape2DSW *body_shape = p_body->get_shape(j);
- const CollisionObject2DSW *col_obj = intersection_query_results[i];
- int shape_idx = intersection_query_subindex_results[i];
+ if (p_exclude_raycast_shapes && body_shape->get_type() == Physics2DServer::SHAPE_RAY) {
+ continue;
+ }
- if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) {
- const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
- if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) {
- continue;
+ body_aabb.position += p_motion * unsafe;
+
+ int amount = _cull_aabb_for_body(p_body, body_aabb);
+
+ for (int i = 0; i < amount; i++) {
+
+ const CollisionObject2DSW *col_obj = intersection_query_results[i];
+ int shape_idx = intersection_query_subindex_results[i];
+
+ if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) {
+ const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
+ if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) {
+ continue;
+ }
}
- }
- Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
+ Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
- bool excluded = false;
- for (int k = 0; k < excluded_shape_pair_count; k++) {
+ bool excluded = false;
+ for (int k = 0; k < excluded_shape_pair_count; k++) {
- if (excluded_shape_pairs[k].local_shape == body_shape && excluded_shape_pairs[k].against_object == col_obj && excluded_shape_pairs[k].against_shape_index == shape_idx) {
- excluded = true;
- break;
+ if (excluded_shape_pairs[k].local_shape == body_shape && excluded_shape_pairs[k].against_object == col_obj && excluded_shape_pairs[k].against_shape_index == shape_idx) {
+ excluded = true;
+ break;
+ }
}
- }
- if (excluded)
- continue;
+ if (excluded)
+ continue;
- if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
+ Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
- rcd.valid_dir = body_shape_xform.get_axis(1).normalized();
- rcd.valid_depth = 10e20;
- } else {
- rcd.valid_dir = Vector2();
- rcd.valid_depth = 0;
- }
+ if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
- rcd.object = col_obj;
- rcd.shape = shape_idx;
- bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, NULL, p_margin);
- if (!sc)
- continue;
+ rcd.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
+ rcd.valid_depth = 10e20;
+ } else {
+ rcd.valid_dir = Vector2();
+ rcd.valid_depth = 0;
+ }
+
+ rcd.object = col_obj;
+ rcd.shape = shape_idx;
+ rcd.local_shape = j;
+ bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), _rest_cbk_result, &rcd, NULL, p_margin);
+ if (!sc)
+ continue;
+ }
}
if (rcd.best_len != 0) {
@@ -981,7 +1093,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
r_result->collider = rcd.best_object->get_self();
r_result->collider_id = rcd.best_object->get_instance_id();
r_result->collider_shape = rcd.best_shape;
- r_result->collision_local_shape = best_shape;
+ r_result->collision_local_shape = rcd.best_local_shape;
r_result->collision_normal = rcd.best_normal;
r_result->collision_point = rcd.best_contact;
r_result->collider_metadata = rcd.best_object->get_shape_metadata(rcd.best_shape);
@@ -996,16 +1108,14 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
collided = true;
- } else {
- if (r_result) {
+ }
+ }
- r_result->motion = p_motion;
- r_result->remainder = Vector2();
- r_result->motion += (body_transform.get_origin() - p_from.get_origin());
- }
+ if (!collided && r_result) {
- collided = false;
- }
+ r_result->motion = p_motion;
+ r_result->remainder = Vector2();
+ r_result->motion += (body_transform.get_origin() - p_from.get_origin());
}
return collided;
@@ -1178,6 +1288,7 @@ void Space2DSW::set_param(Physics2DServer::SpaceParameter p_param, real_t p_valu
case Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: body_angular_velocity_sleep_threshold = p_value; break;
case Physics2DServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: body_time_to_sleep = p_value; break;
case Physics2DServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: constraint_bias = p_value; break;
+ case Physics2DServer::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: test_motion_min_contact_depth = p_value; break;
}
}
@@ -1192,6 +1303,7 @@ real_t Space2DSW::get_param(Physics2DServer::SpaceParameter p_param) const {
case Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: return body_angular_velocity_sleep_threshold;
case Physics2DServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: return body_time_to_sleep;
case Physics2DServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: return constraint_bias;
+ case Physics2DServer::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: return test_motion_min_contact_depth;
}
return 0;
}
@@ -1228,11 +1340,13 @@ Space2DSW::Space2DSW() {
contact_recycle_radius = 1.0;
contact_max_separation = 1.5;
contact_max_allowed_penetration = 0.3;
+ test_motion_min_contact_depth = 0.005;
constraint_bias = 0.2;
body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_linear", 2.0);
body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_angular", (8.0 / 180.0 * Math_PI));
body_time_to_sleep = GLOBAL_DEF("physics/2d/time_before_sleep", 0.5);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/time_before_sleep", PropertyInfo(Variant::REAL, "physics/2d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"));
broadphase = BroadPhase2DSW::create_func();
broadphase->set_pair_callback(_broadphase_pair, this);
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index c894eb9c40..14c24959b7 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -45,10 +45,13 @@ class Physics2DDirectSpaceStateSW : public Physics2DDirectSpaceState {
GDCLASS(Physics2DDirectSpaceStateSW, Physics2DDirectSpaceState);
+ int _intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = 0);
+
public:
Space2DSW *space;
virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false);
+ virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false);
virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
@@ -101,6 +104,7 @@ private:
real_t contact_max_separation;
real_t contact_max_allowed_penetration;
real_t constraint_bias;
+ real_t test_motion_min_contact_depth;
enum {
diff --git a/servers/physics_2d/step_2d_sw.cpp b/servers/physics_2d/step_2d_sw.cpp
index 0fb7af0c94..6c23160cb7 100644
--- a/servers/physics_2d/step_2d_sw.cpp
+++ b/servers/physics_2d/step_2d_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -222,7 +222,7 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) {
Constraint2DSW *prev_ci = NULL;
while (ci) {
- if (_setup_island(ci, p_delta) == true) {
+ if (_setup_island(ci, p_delta)) {
//removed the root from the island graph because it is not to be processed
diff --git a/servers/physics_2d/step_2d_sw.h b/servers/physics_2d/step_2d_sw.h
index 4aa669d3a7..23385f6950 100644
--- a/servers/physics_2d/step_2d_sw.h
+++ b/servers/physics_2d/step_2d_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp
index 3ca6e29f0b..dadadf68fd 100644
--- a/servers/physics_2d_server.cpp
+++ b/servers/physics_2d_server.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -328,7 +328,7 @@ Array Physics2DDirectSpaceState::_cast_motion(const Ref<Physics2DShapeQueryParam
return ret;
}
-Array Physics2DDirectSpaceState::_intersect_point(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) {
+Array Physics2DDirectSpaceState::_intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas, ObjectID p_canvas_instance_id) {
Set<RID> exclude;
for (int i = 0; i < p_exclude.size(); i++)
@@ -337,7 +337,12 @@ Array Physics2DDirectSpaceState::_intersect_point(const Vector2 &p_point, int p_
Vector<ShapeResult> ret;
ret.resize(p_max_results);
- int rc = intersect_point(p_point, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas);
+ int rc;
+ if (p_filter_by_canvas)
+ rc = intersect_point(p_point, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas);
+ else
+ rc = intersect_point_on_canvas(p_point, p_canvas_instance_id, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas);
+
if (rc == 0)
return Array();
@@ -356,6 +361,16 @@ Array Physics2DDirectSpaceState::_intersect_point(const Vector2 &p_point, int p_
return r;
}
+Array Physics2DDirectSpaceState::_intersect_point(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) {
+
+ return _intersect_point_impl(p_point, p_max_results, p_exclude, p_layers, p_collide_with_bodies, p_collide_with_areas);
+}
+
+Array Physics2DDirectSpaceState::_intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_intance_id, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) {
+
+ return _intersect_point_impl(p_point, p_max_results, p_exclude, p_layers, p_collide_with_bodies, p_collide_with_areas, true, p_canvas_intance_id);
+}
+
Array Physics2DDirectSpaceState::_collide_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query, int p_max_results) {
ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
@@ -400,6 +415,7 @@ Physics2DDirectSpaceState::Physics2DDirectSpaceState() {
void Physics2DDirectSpaceState::_bind_methods() {
ClassDB::bind_method(D_METHOD("intersect_point", "point", "max_results", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &Physics2DDirectSpaceState::_intersect_point, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("intersect_point_on_canvas", "point", "canvas_instance_id", "max_results", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &Physics2DDirectSpaceState::_intersect_point_on_canvas, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &Physics2DDirectSpaceState::_intersect_ray, DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &Physics2DDirectSpaceState::_intersect_shape, DEFVAL(32));
ClassDB::bind_method(D_METHOD("cast_motion", "shape"), &Physics2DDirectSpaceState::_cast_motion);
@@ -551,10 +567,10 @@ void Physics2DServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("area_set_space_override_mode", "area", "mode"), &Physics2DServer::area_set_space_override_mode);
ClassDB::bind_method(D_METHOD("area_get_space_override_mode", "area"), &Physics2DServer::area_get_space_override_mode);
- ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform"), &Physics2DServer::area_add_shape, DEFVAL(Transform2D()));
+ ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &Physics2DServer::area_add_shape, DEFVAL(Transform2D()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &Physics2DServer::area_set_shape);
ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &Physics2DServer::area_set_shape_transform);
- ClassDB::bind_method(D_METHOD("area_set_shape_disabled", "area", "shape_idx", "disable"), &Physics2DServer::area_set_shape_disabled);
+ ClassDB::bind_method(D_METHOD("area_set_shape_disabled", "area", "shape_idx", "disabled"), &Physics2DServer::area_set_shape_disabled);
ClassDB::bind_method(D_METHOD("area_get_shape_count", "area"), &Physics2DServer::area_get_shape_count);
ClassDB::bind_method(D_METHOD("area_get_shape", "area", "shape_idx"), &Physics2DServer::area_get_shape);
@@ -575,6 +591,9 @@ void Physics2DServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("area_attach_object_instance_id", "area", "id"), &Physics2DServer::area_attach_object_instance_id);
ClassDB::bind_method(D_METHOD("area_get_object_instance_id", "area"), &Physics2DServer::area_get_object_instance_id);
+ ClassDB::bind_method(D_METHOD("area_attach_canvas_instance_id", "area", "id"), &Physics2DServer::area_attach_canvas_instance_id);
+ ClassDB::bind_method(D_METHOD("area_get_canvas_instance_id", "area"), &Physics2DServer::area_get_canvas_instance_id);
+
ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "receiver", "method"), &Physics2DServer::area_set_monitor_callback);
ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "receiver", "method"), &Physics2DServer::area_set_area_monitor_callback);
ClassDB::bind_method(D_METHOD("area_set_monitorable", "area", "monitorable"), &Physics2DServer::area_set_monitorable);
@@ -587,7 +606,7 @@ void Physics2DServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_mode", "body", "mode"), &Physics2DServer::body_set_mode);
ClassDB::bind_method(D_METHOD("body_get_mode", "body"), &Physics2DServer::body_get_mode);
- ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform"), &Physics2DServer::body_add_shape, DEFVAL(Transform2D()));
+ ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform", "disabled"), &Physics2DServer::body_add_shape, DEFVAL(Transform2D()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("body_set_shape", "body", "shape_idx", "shape"), &Physics2DServer::body_set_shape);
ClassDB::bind_method(D_METHOD("body_set_shape_transform", "body", "shape_idx", "transform"), &Physics2DServer::body_set_shape_transform);
ClassDB::bind_method(D_METHOD("body_set_shape_metadata", "body", "shape_idx", "metadata"), &Physics2DServer::body_set_shape_metadata);
@@ -600,12 +619,15 @@ void Physics2DServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_remove_shape", "body", "shape_idx"), &Physics2DServer::body_remove_shape);
ClassDB::bind_method(D_METHOD("body_clear_shapes", "body"), &Physics2DServer::body_clear_shapes);
- ClassDB::bind_method(D_METHOD("body_set_shape_disabled", "body", "shape_idx", "disable"), &Physics2DServer::body_set_shape_disabled);
- ClassDB::bind_method(D_METHOD("body_set_shape_as_one_way_collision", "body", "shape_idx", "enable"), &Physics2DServer::body_set_shape_as_one_way_collision);
+ ClassDB::bind_method(D_METHOD("body_set_shape_disabled", "body", "shape_idx", "disabled"), &Physics2DServer::body_set_shape_disabled);
+ ClassDB::bind_method(D_METHOD("body_set_shape_as_one_way_collision", "body", "shape_idx", "enable", "margin"), &Physics2DServer::body_set_shape_as_one_way_collision);
ClassDB::bind_method(D_METHOD("body_attach_object_instance_id", "body", "id"), &Physics2DServer::body_attach_object_instance_id);
ClassDB::bind_method(D_METHOD("body_get_object_instance_id", "body"), &Physics2DServer::body_get_object_instance_id);
+ ClassDB::bind_method(D_METHOD("body_attach_canvas_instance_id", "body", "id"), &Physics2DServer::body_attach_canvas_instance_id);
+ ClassDB::bind_method(D_METHOD("body_get_canvas_instance_id", "body"), &Physics2DServer::body_get_canvas_instance_id);
+
ClassDB::bind_method(D_METHOD("body_set_continuous_collision_detection_mode", "body", "mode"), &Physics2DServer::body_set_continuous_collision_detection_mode);
ClassDB::bind_method(D_METHOD("body_get_continuous_collision_detection_mode", "body"), &Physics2DServer::body_get_continuous_collision_detection_mode);
@@ -671,6 +693,7 @@ void Physics2DServer::_bind_methods() {
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD);
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP);
BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS);
+ BIND_ENUM_CONSTANT(SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH);
BIND_ENUM_CONSTANT(SHAPE_LINE);
BIND_ENUM_CONSTANT(SHAPE_RAY);
diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h
index fc2a228723..46b22d6777 100644
--- a/servers/physics_2d_server.h
+++ b/servers/physics_2d_server.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -147,8 +147,9 @@ class Physics2DDirectSpaceState : public Object {
GDCLASS(Physics2DDirectSpaceState, Object);
Dictionary _intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
-
Array _intersect_point(const Vector2 &p_point, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
+ Array _intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_intance_id, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
+ Array _intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclud, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = 0);
Array _intersect_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query, int p_max_results = 32);
Array _cast_motion(const Ref<Physics2DShapeQueryParameters> &p_shape_query);
Array _collide_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query, int p_max_results = 32);
@@ -181,6 +182,7 @@ public:
};
virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0;
+ virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0;
virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
@@ -287,6 +289,7 @@ public:
SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD,
SPACE_PARAM_BODY_TIME_TO_SLEEP,
SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS,
+ SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH,
};
virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0;
@@ -332,7 +335,7 @@ public:
virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) = 0;
virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const = 0;
- virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform = Transform2D()) = 0;
+ virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false) = 0;
virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) = 0;
virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform) = 0;
@@ -345,9 +348,12 @@ public:
virtual void area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) = 0;
- virtual void area_attach_object_instance_id(RID p_area, ObjectID p_ID) = 0;
+ virtual void area_attach_object_instance_id(RID p_area, ObjectID p_id) = 0;
virtual ObjectID area_get_object_instance_id(RID p_area) const = 0;
+ virtual void area_attach_canvas_instance_id(RID p_area, ObjectID p_id) = 0;
+ virtual ObjectID area_get_canvas_instance_id(RID p_area) const = 0;
+
virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) = 0;
virtual void area_set_transform(RID p_area, const Transform2D &p_transform) = 0;
@@ -372,7 +378,6 @@ public:
BODY_MODE_KINEMATIC,
BODY_MODE_RIGID,
BODY_MODE_CHARACTER
- //BODY_MODE_SOFT ??
};
virtual RID body_create() = 0;
@@ -383,7 +388,7 @@ public:
virtual void body_set_mode(RID p_body, BodyMode p_mode) = 0;
virtual BodyMode body_get_mode(RID p_body) const = 0;
- virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform = Transform2D()) = 0;
+ virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false) = 0;
virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape) = 0;
virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform) = 0;
virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant &p_metadata) = 0;
@@ -394,14 +399,17 @@ public:
virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const = 0;
virtual void body_set_shape_disabled(RID p_body, int p_shape, bool p_disabled) = 0;
- virtual void body_set_shape_as_one_way_collision(RID p_body, int p_shape, bool p_enabled) = 0;
+ virtual void body_set_shape_as_one_way_collision(RID p_body, int p_shape, bool p_enabled, float p_margin = 0) = 0;
virtual void body_remove_shape(RID p_body, int p_shape_idx) = 0;
virtual void body_clear_shapes(RID p_body) = 0;
- virtual void body_attach_object_instance_id(RID p_body, uint32_t p_ID) = 0;
+ virtual void body_attach_object_instance_id(RID p_body, uint32_t p_id) = 0;
virtual uint32_t body_get_object_instance_id(RID p_body) const = 0;
+ virtual void body_attach_canvas_instance_id(RID p_body, uint32_t p_id) = 0;
+ virtual uint32_t body_get_canvas_instance_id(RID p_body) const = 0;
+
enum CCDMode {
CCD_MODE_DISABLED,
CCD_MODE_CAST_RAY,
@@ -497,6 +505,12 @@ public:
RID collider;
int collider_shape;
Variant collider_metadata;
+
+ MotionResult() {
+ collision_local_shape = 0;
+ collider_shape = 0;
+ collider_id = 0;
+ }
};
virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin = 0.001, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true) = 0;
@@ -577,13 +591,13 @@ public:
virtual void end_sync() = 0;
virtual void finish() = 0;
+ virtual bool is_flushing_queries() const = 0;
+
enum ProcessInfo {
INFO_ACTIVE_OBJECTS,
INFO_COLLISION_PAIRS,
- INFO_ISLAND_COUNT,
- INFO_STEP_TIME,
- INFO_BROAD_PHASE_TIME
+ INFO_ISLAND_COUNT
};
virtual int get_process_info(ProcessInfo p_info) = 0;
@@ -639,6 +653,12 @@ class Physics2DServerManager {
ClassInfo(const ClassInfo &p_ci) :
name(p_ci.name),
create_callback(p_ci.create_callback) {}
+
+ ClassInfo operator=(const ClassInfo &p_ci) {
+ name = p_ci.name;
+ create_callback = p_ci.create_callback;
+ return *this;
+ }
};
static Vector<ClassInfo> physics_2d_servers;
diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp
index 0660c84d09..fe8c644f0b 100644
--- a/servers/physics_server.cpp
+++ b/servers/physics_server.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -427,9 +427,10 @@ void PhysicsServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("area_set_space_override_mode", "area", "mode"), &PhysicsServer::area_set_space_override_mode);
ClassDB::bind_method(D_METHOD("area_get_space_override_mode", "area"), &PhysicsServer::area_get_space_override_mode);
- ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform"), &PhysicsServer::area_add_shape, DEFVAL(Transform()));
+ ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &PhysicsServer::area_add_shape, DEFVAL(Transform()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &PhysicsServer::area_set_shape);
ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &PhysicsServer::area_set_shape_transform);
+ ClassDB::bind_method(D_METHOD("area_set_shape_disabled", "area", "shape_idx", "disabled"), &PhysicsServer::area_set_shape_disabled);
ClassDB::bind_method(D_METHOD("area_get_shape_count", "area"), &PhysicsServer::area_get_shape_count);
ClassDB::bind_method(D_METHOD("area_get_shape", "area", "shape_idx"), &PhysicsServer::area_get_shape);
@@ -471,9 +472,10 @@ void PhysicsServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_collision_mask", "body", "mask"), &PhysicsServer::body_set_collision_mask);
ClassDB::bind_method(D_METHOD("body_get_collision_mask", "body"), &PhysicsServer::body_get_collision_mask);
- ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform"), &PhysicsServer::body_add_shape, DEFVAL(Transform()));
+ ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform", "disabled"), &PhysicsServer::body_add_shape, DEFVAL(Transform()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("body_set_shape", "body", "shape_idx", "shape"), &PhysicsServer::body_set_shape);
ClassDB::bind_method(D_METHOD("body_set_shape_transform", "body", "shape_idx", "transform"), &PhysicsServer::body_set_shape_transform);
+ ClassDB::bind_method(D_METHOD("body_set_shape_disabled", "body", "shape_idx", "disabled"), &PhysicsServer::body_set_shape_disabled);
ClassDB::bind_method(D_METHOD("body_get_shape_count", "body"), &PhysicsServer::body_get_shape_count);
ClassDB::bind_method(D_METHOD("body_get_shape", "body", "shape_idx"), &PhysicsServer::body_get_shape);
@@ -678,7 +680,6 @@ void PhysicsServer::_bind_methods() {
BIND_ENUM_CONSTANT(BODY_MODE_STATIC);
BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC);
BIND_ENUM_CONSTANT(BODY_MODE_RIGID);
- BIND_ENUM_CONSTANT(BODY_MODE_SOFT);
BIND_ENUM_CONSTANT(BODY_MODE_CHARACTER);
BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE);
@@ -710,6 +711,8 @@ void PhysicsServer::_bind_methods() {
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP);
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO);
BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS);
+ BIND_ENUM_CONSTANT(SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH);
+
BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_X);
BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_Y);
BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_Z);
@@ -738,11 +741,11 @@ const String PhysicsServerManager::setting_property_name("physics/3d/physics_eng
void PhysicsServerManager::on_servers_changed() {
- String physics_servers("DEFAULT");
+ String physics_servers2("DEFAULT");
for (int i = get_servers_count() - 1; 0 <= i; --i) {
- physics_servers += "," + get_server_name(i);
+ physics_servers2 += "," + get_server_name(i);
}
- ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers));
+ ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers2));
}
void PhysicsServerManager::register_server(const String &p_name, CreatePhysicsServerCallback p_creat_callback) {
diff --git a/servers/physics_server.h b/servers/physics_server.h
index d0d2ec16f0..5e5964ca8d 100644
--- a/servers/physics_server.h
+++ b/servers/physics_server.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -274,6 +274,7 @@ public:
SPACE_PARAM_BODY_TIME_TO_SLEEP,
SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO,
SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS,
+ SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH
};
virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0;
@@ -319,7 +320,7 @@ public:
virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) = 0;
virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const = 0;
- virtual void area_add_shape(RID p_area, RID p_shape, const Transform &p_transform = Transform()) = 0;
+ virtual void area_add_shape(RID p_area, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false) = 0;
virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) = 0;
virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform) = 0;
@@ -332,7 +333,7 @@ public:
virtual void area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) = 0;
- virtual void area_attach_object_instance_id(RID p_area, ObjectID p_ID) = 0;
+ virtual void area_attach_object_instance_id(RID p_area, ObjectID p_id) = 0;
virtual ObjectID area_get_object_instance_id(RID p_area) const = 0;
virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) = 0;
@@ -360,7 +361,6 @@ public:
BODY_MODE_STATIC,
BODY_MODE_KINEMATIC,
BODY_MODE_RIGID,
- BODY_MODE_SOFT,
BODY_MODE_CHARACTER
};
@@ -372,7 +372,7 @@ public:
virtual void body_set_mode(RID p_body, BodyMode p_mode) = 0;
virtual BodyMode body_get_mode(RID p_body) const = 0;
- virtual void body_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform()) = 0;
+ virtual void body_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false) = 0;
virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape) = 0;
virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) = 0;
@@ -385,7 +385,7 @@ public:
virtual void body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) = 0;
- virtual void body_attach_object_instance_id(RID p_body, uint32_t p_ID) = 0;
+ virtual void body_attach_object_instance_id(RID p_body, uint32_t p_id) = 0;
virtual uint32_t body_get_object_instance_id(RID p_body) const = 0;
virtual void body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) = 0;
@@ -493,6 +493,11 @@ public:
RID collider;
int collider_shape;
Variant collider_metadata;
+ MotionResult() {
+ collision_local_shape = 0;
+ collider_id = 0;
+ collider_shape = 0;
+ }
};
virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true) = 0;
@@ -698,6 +703,9 @@ public:
G6DOF_JOINT_LINEAR_DAMPING,
G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY,
G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT,
+ G6DOF_JOINT_LINEAR_SPRING_STIFFNESS,
+ G6DOF_JOINT_LINEAR_SPRING_DAMPING,
+ G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT,
G6DOF_JOINT_ANGULAR_LOWER_LIMIT,
G6DOF_JOINT_ANGULAR_UPPER_LIMIT,
G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS,
@@ -707,6 +715,9 @@ public:
G6DOF_JOINT_ANGULAR_ERP,
G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY,
G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT,
+ G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS,
+ G6DOF_JOINT_ANGULAR_SPRING_DAMPING,
+ G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT,
G6DOF_JOINT_MAX
};
@@ -714,6 +725,8 @@ public:
G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT,
G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT,
+ G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING,
+ G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING,
G6DOF_JOINT_FLAG_ENABLE_MOTOR,
G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR,
G6DOF_JOINT_FLAG_MAX
@@ -727,6 +740,9 @@ public:
virtual void generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag, bool p_enable) = 0;
virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag) = 0;
+ virtual void generic_6dof_joint_set_precision(RID p_joint, int precision) = 0;
+ virtual int generic_6dof_joint_get_precision(RID p_joint) = 0;
+
/* QUERY API */
enum AreaBodyStatus {
@@ -745,6 +761,8 @@ public:
virtual void flush_queries() = 0;
virtual void finish() = 0;
+ virtual bool is_flushing_queries() const = 0;
+
enum ProcessInfo {
INFO_ACTIVE_OBJECTS,
@@ -776,6 +794,12 @@ class PhysicsServerManager {
ClassInfo(const ClassInfo &p_ci) :
name(p_ci.name),
create_callback(p_ci.create_callback) {}
+
+ ClassInfo operator=(const ClassInfo &p_ci) {
+ name = p_ci.name;
+ create_callback = p_ci.create_callback;
+ return *this;
+ }
};
static Vector<ClassInfo> physics_servers;
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 7deeec676b..f7cec6a378 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -50,8 +50,12 @@
#include "audio/effects/audio_effect_pitch_shift.h"
#include "audio/effects/audio_effect_record.h"
#include "audio/effects/audio_effect_reverb.h"
+#include "audio/effects/audio_effect_spectrum_analyzer.h"
#include "audio/effects/audio_effect_stereo_enhance.h"
+#include "audio/effects/audio_stream_generator.h"
#include "audio_server.h"
+#include "camera/camera_feed.h"
+#include "camera_server.h"
#include "core/script_debugger_remote.h"
#include "physics/physics_server_sw.h"
#include "physics_2d/physics_2d_server_sw.h"
@@ -73,7 +77,11 @@ static void _debugger_get_resource_usage(List<ScriptDebuggerRemote::ResourceUsag
usage.vram = E->get().bytes;
usage.id = E->get().texture;
usage.type = "Texture";
- usage.format = itos(E->get().width) + "x" + itos(E->get().height) + " " + Image::get_format_name(E->get().format);
+ if (E->get().depth == 0) {
+ usage.format = itos(E->get().width) + "x" + itos(E->get().height) + " " + Image::get_format_name(E->get().format);
+ } else {
+ usage.format = itos(E->get().width) + "x" + itos(E->get().height) + "x" + itos(E->get().depth) + " " + Image::get_format_name(E->get().format);
+ }
r_usage->push_back(usage);
}
}
@@ -81,7 +89,6 @@ static void _debugger_get_resource_usage(List<ScriptDebuggerRemote::ResourceUsag
ShaderTypes *shader_types = NULL;
PhysicsServer *_createGodotPhysicsCallback() {
- WARN_PRINT("The GodotPhysics 3D physics engine is deprecated and will be removed in Godot 3.2. You should use the Bullet physics engine instead (configurable in your project settings).");
return memnew(PhysicsServerSW);
}
@@ -89,13 +96,27 @@ Physics2DServer *_createGodotPhysics2DCallback() {
return Physics2DServerWrapMT::init_server<Physics2DServerSW>();
}
+static bool has_server_feature_callback(const String &p_feature) {
+
+ if (VisualServer::get_singleton()) {
+ if (VisualServer::get_singleton()->has_os_feature(p_feature)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void register_server_types() {
+ OS::get_singleton()->set_has_server_feature_callback(has_server_feature_callback);
+
ClassDB::register_virtual_class<VisualServer>();
ClassDB::register_class<AudioServer>();
ClassDB::register_virtual_class<PhysicsServer>();
ClassDB::register_virtual_class<Physics2DServer>();
ClassDB::register_class<ARVRServer>();
+ ClassDB::register_class<CameraServer>();
shader_types = memnew(ShaderTypes);
@@ -104,13 +125,18 @@ void register_server_types() {
ClassDB::register_virtual_class<AudioStream>();
ClassDB::register_virtual_class<AudioStreamPlayback>();
+ ClassDB::register_virtual_class<AudioStreamPlaybackResampled>();
ClassDB::register_class<AudioStreamMicrophone>();
ClassDB::register_class<AudioStreamRandomPitch>();
ClassDB::register_virtual_class<AudioEffect>();
+ ClassDB::register_virtual_class<AudioEffectInstance>();
ClassDB::register_class<AudioEffectEQ>();
ClassDB::register_class<AudioEffectFilter>();
ClassDB::register_class<AudioBusLayout>();
+ ClassDB::register_class<AudioStreamGenerator>();
+ ClassDB::register_virtual_class<AudioStreamGeneratorPlayback>();
+
{
//audio effects
ClassDB::register_class<AudioEffectAmplify>();
@@ -140,9 +166,14 @@ void register_server_types() {
ClassDB::register_class<AudioEffectLimiter>();
ClassDB::register_class<AudioEffectPitchShift>();
ClassDB::register_class<AudioEffectPhaser>();
+
ClassDB::register_class<AudioEffectRecord>();
+ ClassDB::register_class<AudioEffectSpectrumAnalyzer>();
+ ClassDB::register_virtual_class<AudioEffectSpectrumAnalyzerInstance>();
}
+ ClassDB::register_class<CameraFeed>();
+
ClassDB::register_virtual_class<Physics2DDirectBodyState>();
ClassDB::register_virtual_class<Physics2DDirectSpaceState>();
ClassDB::register_virtual_class<Physics2DShapeQueryResult>();
@@ -167,8 +198,8 @@ void register_server_types() {
GLOBAL_DEF(PhysicsServerManager::setting_property_name, "DEFAULT");
ProjectSettings::get_singleton()->set_custom_property_info(PhysicsServerManager::setting_property_name, PropertyInfo(Variant::STRING, PhysicsServerManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT"));
- PhysicsServerManager::register_server("GodotPhysics - deprecated", &_createGodotPhysicsCallback);
- PhysicsServerManager::set_default_server("GodotPhysics - deprecated");
+ PhysicsServerManager::register_server("GodotPhysics", &_createGodotPhysicsCallback);
+ PhysicsServerManager::set_default_server("GodotPhysics");
}
void unregister_server_types() {
@@ -182,4 +213,5 @@ void register_server_singletons() {
Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer", PhysicsServer::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("Physics2DServer", Physics2DServer::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("ARVRServer", ARVRServer::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("CameraServer", CameraServer::get_singleton()));
}
diff --git a/servers/register_server_types.h b/servers/register_server_types.h
index 0af41ae424..f42a5e7afc 100644
--- a/servers/register_server_types.h
+++ b/servers/register_server_types.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/server_wrap_mt_common.h b/servers/server_wrap_mt_common.h
index 843773e5b1..a6f595d776 100644
--- a/servers/server_wrap_mt_common.h
+++ b/servers/server_wrap_mt_common.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -50,7 +50,7 @@
} \
void m_type##_free_cached_ids() { \
while (m_type##_id_pool.size()) { \
- free(m_type##_id_pool.front()->get()); \
+ server_name->free(m_type##_id_pool.front()->get()); \
m_type##_id_pool.pop_front(); \
} \
} \
diff --git a/servers/visual/SCsub b/servers/visual/SCsub
index ccc76e823f..d730144861 100644
--- a/servers/visual/SCsub
+++ b/servers/visual/SCsub
@@ -3,5 +3,3 @@
Import('env')
env.add_source_files(env.servers_sources, "*.cpp")
-
-Export('env')
diff --git a/servers/visual/default_mouse_cursor.xpm b/servers/visual/default_mouse_cursor.xpm
deleted file mode 100644
index 37d437dd15..0000000000
--- a/servers/visual/default_mouse_cursor.xpm
+++ /dev/null
@@ -1,23 +0,0 @@
-/* XPM */
-static const char * default_mouse_cursor_xpm[] = {
-"16 16 4 1",
-" c None",
-". c #000000",
-"+ c #FF00FF",
-"@ c #FFFFFF",
-"...+++++++++++++",
-".@...+++++++++++",
-".@@@...+++++++++",
-".@@@@@....++++++",
-".@@@@@@@@...++++",
-".@@@@@@@@@@...++",
-".@@@@@@@@@@@@..+",
-".@@@@@@@@@@@@@..",
-".@@@@@@@@@@@@..+",
-".@@@@@@@@@@@..++",
-".@@@@@@@@@...+++",
-".@@@.....@@..+++",
-".....+++.@@@..++",
-"++++++++..@@@..+",
-"+++++++++..@@@.+",
-"++++++++++.....+"};
diff --git a/servers/visual/rasterizer.cpp b/servers/visual/rasterizer.cpp
index 6c04d1de63..5e02238e85 100644
--- a/servers/visual/rasterizer.cpp
+++ b/servers/visual/rasterizer.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 6eeaf12dfc..9aaebefd80 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -55,14 +55,16 @@ public:
virtual void environment_set_background(RID p_env, VS::EnvironmentBG p_bg) = 0;
virtual void environment_set_sky(RID p_env, RID p_sky) = 0;
virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0;
+ virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0;
virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0;
virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0;
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;
virtual void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0) = 0;
+ virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0;
virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) = 0;
virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) = 0;
- virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, bool p_bicubic_upscale) = 0;
+ virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) = 0;
virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) = 0;
virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) = 0;
@@ -73,7 +75,7 @@ public:
virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) = 0;
virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) = 0;
- virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0;
+ virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0;
virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0;
virtual bool is_environment(RID p_env) = 0;
@@ -120,9 +122,7 @@ public:
Vector<Color> lightmap_capture_data; //in a array (12 values) to avoid wasting space if unused. Alpha is unused, but needed to send to shader
virtual void base_removed() = 0;
- virtual void base_changed() = 0;
- virtual void base_material_changed() = 0;
-
+ virtual void base_changed(bool p_aabb, bool p_materials) = 0;
InstanceBase() :
dependency_item(this) {
@@ -142,6 +142,7 @@ public:
virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) = 0;
virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0) = 0;
virtual void light_instance_mark_visible(RID p_light_instance) = 0;
+ virtual bool light_instances_can_render_shadow_cube() const { return true; }
virtual RID reflection_atlas_create() = 0;
virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_size) = 0;
@@ -204,6 +205,7 @@ public:
virtual uint32_t texture_get_height(RID p_texture) const = 0;
virtual uint32_t texture_get_depth(RID p_texture) const = 0;
virtual void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth_3d) = 0;
+ virtual void texture_bind(RID p_texture, uint32_t p_texture_no) = 0;
virtual void texture_set_path(RID p_texture, const String &p_path) = 0;
virtual String texture_get_path(RID p_texture) const = 0;
@@ -221,6 +223,7 @@ public:
virtual void textures_keep_original(bool p_enable) = 0;
virtual void texture_set_proxy(RID p_proxy, RID p_base) = 0;
+ virtual Size2 texture_size_with_proxy(RID p_texture) const = 0;
virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0;
/* SKY API */
@@ -371,6 +374,7 @@ public:
virtual void light_set_negative(RID p_light, bool p_enable) = 0;
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0;
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0;
+ virtual void light_set_use_gi(RID p_light, bool p_enable) = 0;
virtual void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) = 0;
virtual void light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail) = 0;
@@ -390,6 +394,7 @@ public:
virtual AABB light_get_aabb(RID p_light) const = 0;
virtual float light_get_param(RID p_light, VS::LightParam p_param) = 0;
virtual Color light_get_color(RID p_light) = 0;
+ virtual bool light_get_use_gi(RID p_light) = 0;
virtual uint64_t light_get_version(RID p_light) const = 0;
/* PROBE API */
@@ -397,6 +402,7 @@ public:
virtual RID reflection_probe_create() = 0;
virtual void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode) = 0;
+ virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) = 0;
virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) = 0;
virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) = 0;
@@ -519,6 +525,8 @@ public:
virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0;
virtual void particles_restart(RID p_particles) = 0;
+ virtual bool particles_is_inactive(RID p_particles) const = 0;
+
virtual void particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order) = 0;
virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0;
@@ -543,12 +551,15 @@ public:
RENDER_TARGET_NO_SAMPLING,
RENDER_TARGET_HDR,
RENDER_TARGET_KEEP_3D_LINEAR,
+ RENDER_TARGET_DIRECT_TO_SCREEN,
RENDER_TARGET_FLAG_MAX
};
virtual RID render_target_create() = 0;
+ virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0;
virtual void render_target_set_size(RID p_render_target, int p_width, int p_height) = 0;
virtual RID render_target_get_texture(RID p_render_target) const = 0;
+ virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0;
virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0;
virtual bool render_target_was_used(RID p_render_target) = 0;
virtual void render_target_clear_used(RID p_render_target) = 0;
@@ -654,7 +665,7 @@ public:
next_ptr = NULL;
mask_next_ptr = NULL;
filter_next_ptr = NULL;
- shadow_buffer_size = 256;
+ shadow_buffer_size = 2048;
shadow_gradient_length = 0;
shadow_filter = VS::CANVAS_LIGHT_FILTER_NONE;
shadow_smooth = 0.0;
@@ -783,6 +794,8 @@ public:
RID mesh;
RID texture;
RID normal_map;
+ Transform2D transform;
+ Color modulate;
CommandMesh() { type = TYPE_MESH; }
};
@@ -799,8 +812,6 @@ public:
RID particles;
RID texture;
RID normal_map;
- int h_frames;
- int v_frames;
CommandParticles() { type = TYPE_PARTICLES; }
};
@@ -868,7 +879,7 @@ public:
Rect2 global_rect_cache;
const Rect2 &get_rect() const {
- if (custom_rect || !rect_dirty)
+ if (custom_rect || (!rect_dirty && !update_when_visible))
return rect;
//must update rect
@@ -938,9 +949,8 @@ public:
const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(c);
r.position = primitive->points[0];
- for (int i = 1; i < primitive->points.size(); i++) {
-
- r.expand_to(primitive->points[i]);
+ for (int j = 1; j < primitive->points.size(); j++) {
+ r.expand_to(primitive->points[j]);
}
} break;
case Item::Command::TYPE_POLYGON: {
@@ -949,9 +959,8 @@ public:
int l = polygon->points.size();
const Point2 *pp = &polygon->points[0];
r.position = pp[0];
- for (int i = 1; i < l; i++) {
-
- r.expand_to(pp[i]);
+ for (int j = 1; j < l; j++) {
+ r.expand_to(pp[j]);
}
} break;
case Item::Command::TYPE_MESH: {
@@ -1095,17 +1104,20 @@ public:
virtual RasterizerCanvas *get_canvas() = 0;
virtual RasterizerScene *get_scene() = 0;
- virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale) = 0;
+ virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) = 0;
virtual void initialize() = 0;
virtual void begin_frame(double frame_step) = 0;
virtual void set_current_render_target(RID p_render_target) = 0;
- virtual void restore_render_target() = 0;
+ virtual void restore_render_target(bool p_3d) = 0;
virtual void clear_render_target(const Color &p_color) = 0;
virtual void blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect, int p_screen = 0) = 0;
+ virtual void output_lens_distorted_to_screen(RID p_render_target, const Rect2 &p_screen_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) = 0;
virtual void end_frame(bool p_swap_buffers) = 0;
virtual void finalize() = 0;
+ virtual bool is_low_end() const = 0;
+
virtual ~Rasterizer() {}
};
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 417617fa5b..3b549afb02 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -131,8 +131,8 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"TYPE_USAMPLER3D",
"TYPE_SAMPLERCUBE",
"INTERPOLATION_FLAT",
- "INTERPOLATION_NO_PERSPECTIVE",
"INTERPOLATION_SMOOTH",
+ "CONST",
"PRECISION_LOW",
"PRECISION_MID",
"PRECISION_HIGH",
@@ -271,8 +271,8 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_TYPE_USAMPLER3D, "usampler3D" },
{ TK_TYPE_SAMPLERCUBE, "samplerCube" },
{ TK_INTERPOLATION_FLAT, "flat" },
- { TK_INTERPOLATION_NO_PERSPECTIVE, "noperspective" },
{ TK_INTERPOLATION_SMOOTH, "smooth" },
+ { TK_CONST, "const" },
{ TK_PRECISION_LOW, "lowp" },
{ TK_PRECISION_MID, "mediump" },
{ TK_PRECISION_HIGH, "highp" },
@@ -283,6 +283,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_CF_DO, "do" },
{ TK_CF_SWITCH, "switch" },
{ TK_CF_CASE, "case" },
+ { TK_CF_DEFAULT, "default" },
{ TK_CF_BREAK, "break" },
{ TK_CF_CONTINUE, "continue" },
{ TK_CF_RETURN, "return" },
@@ -527,7 +528,6 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
bool exponent_found = false;
bool hexa_found = false;
bool sign_found = false;
- bool minus_exponent_found = false;
bool float_suffix_found = false;
String str;
@@ -559,8 +559,6 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
if (sign_found)
return _make_token(TK_ERROR, "Invalid numeric constant");
sign_found = true;
- if (GETCHAR(i) == '-')
- minus_exponent_found = true;
} else
break;
@@ -573,7 +571,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
if (hexa_found) {
//hex integers eg."0xFF" or "0x12AB", etc - NOT supported yet
return _make_token(TK_ERROR, "Invalid (hexadecimal) numeric constant - Not supported");
- } else if (period_found || float_suffix_found) {
+ } else if (period_found || exponent_found || float_suffix_found) {
//floats
if (period_found) {
if (float_suffix_found) {
@@ -616,12 +614,12 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
char_idx += str.length();
Token tk;
- if (period_found || minus_exponent_found || float_suffix_found)
+ if (period_found || exponent_found || float_suffix_found)
tk.type = TK_REAL_CONSTANT;
else
tk.type = TK_INT_CONSTANT;
- tk.constant = str.to_double(); //wont work with hex
+ tk.constant = str.to_double(); //won't work with hex
tk.line = tk_line;
return tk;
@@ -691,6 +689,30 @@ String ShaderLanguage::token_debug(const String &p_code) {
return output;
}
+bool ShaderLanguage::is_token_variable_datatype(TokenType p_type) {
+ return (
+ p_type == TK_TYPE_VOID ||
+ p_type == TK_TYPE_BOOL ||
+ p_type == TK_TYPE_BVEC2 ||
+ p_type == TK_TYPE_BVEC3 ||
+ p_type == TK_TYPE_BVEC4 ||
+ p_type == TK_TYPE_INT ||
+ p_type == TK_TYPE_IVEC2 ||
+ p_type == TK_TYPE_IVEC3 ||
+ p_type == TK_TYPE_IVEC4 ||
+ p_type == TK_TYPE_UINT ||
+ p_type == TK_TYPE_UVEC2 ||
+ p_type == TK_TYPE_UVEC3 ||
+ p_type == TK_TYPE_UVEC4 ||
+ p_type == TK_TYPE_FLOAT ||
+ p_type == TK_TYPE_VEC2 ||
+ p_type == TK_TYPE_VEC3 ||
+ p_type == TK_TYPE_VEC4 ||
+ p_type == TK_TYPE_MAT2 ||
+ p_type == TK_TYPE_MAT3 ||
+ p_type == TK_TYPE_MAT4);
+}
+
bool ShaderLanguage::is_token_datatype(TokenType p_type) {
return (
@@ -735,7 +757,6 @@ bool ShaderLanguage::is_token_interpolation(TokenType p_type) {
return (
p_type == TK_INTERPOLATION_FLAT ||
- p_type == TK_INTERPOLATION_NO_PERSPECTIVE ||
p_type == TK_INTERPOLATION_SMOOTH);
}
@@ -743,8 +764,6 @@ ShaderLanguage::DataInterpolation ShaderLanguage::get_token_interpolation(TokenT
if (p_type == TK_INTERPOLATION_FLAT)
return INTERPOLATION_FLAT;
- else if (p_type == TK_INTERPOLATION_NO_PERSPECTIVE)
- return INTERPOLATION_NO_PERSPECTIVE;
else
return INTERPOLATION_SMOOTH;
}
@@ -767,6 +786,17 @@ ShaderLanguage::DataPrecision ShaderLanguage::get_token_precision(TokenType p_ty
return PRECISION_MEDIUMP;
}
+String ShaderLanguage::get_precision_name(DataPrecision p_type) {
+ switch (p_type) {
+ case PRECISION_LOWP: return "lowp";
+ case PRECISION_MEDIUMP: return "mediump";
+ case PRECISION_HIGHP: return "highp";
+ default:
+ break;
+ }
+ return "";
+}
+
String ShaderLanguage::get_datatype_name(DataType p_type) {
switch (p_type) {
@@ -831,7 +861,7 @@ void ShaderLanguage::clear() {
}
}
-bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type) {
+bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size) {
if (p_builtin_types.has(p_identifier)) {
@@ -853,6 +883,12 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Map<String
if (r_data_type) {
*r_data_type = p_block->variables[p_identifier].type;
}
+ if (r_is_const) {
+ *r_is_const = p_block->variables[p_identifier].is_const;
+ }
+ if (r_array_size) {
+ *r_array_size = p_block->variables[p_identifier].array_size;
+ }
if (r_type) {
*r_type = IDENTIFIER_LOCAL_VAR;
}
@@ -888,6 +924,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Map<String
if (r_data_type) {
*r_data_type = shader->varyings[p_identifier].type;
}
+ if (r_array_size) {
+ *r_array_size = shader->varyings[p_identifier].array_size;
+ }
if (r_type) {
*r_type = IDENTIFIER_VARYING;
}
@@ -904,6 +943,16 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Map<String
return true;
}
+ if (shader->constants.has(p_identifier)) {
+ if (r_data_type) {
+ *r_data_type = shader->constants[p_identifier].type;
+ }
+ if (r_type) {
+ *r_type = IDENTIFIER_CONSTANT;
+ }
+ return true;
+ }
+
for (int i = 0; i < shader->functions.size(); i++) {
if (!shader->functions[i].callable)
@@ -916,6 +965,7 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Map<String
if (r_type) {
*r_type = IDENTIFIER_FUNCTION;
}
+ return true;
}
}
@@ -925,7 +975,7 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Map<String
bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type) {
bool valid = false;
- DataType ret_type;
+ DataType ret_type = TYPE_VOID;
switch (p_op->op) {
case OP_EQUAL:
@@ -1196,6 +1246,15 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
} else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_MAT4 && nb == TYPE_VEC4) {
valid = true;
ret_type = TYPE_MAT4;
+ } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC2 && nb == TYPE_MAT2) {
+ valid = true;
+ ret_type = TYPE_VEC2;
+ } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC3 && nb == TYPE_MAT3) {
+ valid = true;
+ ret_type = TYPE_VEC3;
+ } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC4 && nb == TYPE_MAT4) {
+ valid = true;
+ ret_type = TYPE_VEC4;
}
} break;
case OP_ASSIGN_BIT_AND:
@@ -1291,742 +1350,750 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
//constructors
- { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID } },
- { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_VOID } },
- { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_BOOL, TYPE_VOID } },
- { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_VOID } },
- { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_VOID } },
- { "bvec3", TYPE_BVEC3, { TYPE_BVEC2, TYPE_BOOL, TYPE_VOID } },
- { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_BVEC2, TYPE_VOID } },
- { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_VOID } },
- { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_VOID } },
- { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BVEC2, TYPE_BOOL, TYPE_VOID } },
- { "bvec4", TYPE_BVEC4, { TYPE_BVEC2, TYPE_BOOL, TYPE_BOOL, TYPE_VOID } },
- { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BOOL, TYPE_BVEC2, TYPE_VOID } },
- { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BVEC3, TYPE_VOID } },
- { "bvec4", TYPE_BVEC4, { TYPE_BVEC3, TYPE_BOOL, TYPE_VOID } },
- { "bvec4", TYPE_BVEC4, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID } },
-
- { "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "vec2", TYPE_VEC2, { TYPE_FLOAT, TYPE_VOID } },
- { "vec2", TYPE_VEC2, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
- { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_VOID } },
- { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
- { "vec3", TYPE_VEC3, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
- { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID } },
- { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VOID } },
- { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
- { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
- { "vec4", TYPE_VEC4, { TYPE_VEC2, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
- { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC2, TYPE_VOID } },
- { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID } },
- { "vec4", TYPE_VEC4, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "vec4", TYPE_VEC4, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
-
- { "int", TYPE_INT, { TYPE_INT, TYPE_VOID } },
- { "ivec2", TYPE_IVEC2, { TYPE_INT, TYPE_VOID } },
- { "ivec2", TYPE_IVEC2, { TYPE_INT, TYPE_INT, TYPE_VOID } },
- { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_VOID } },
- { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID } },
- { "ivec3", TYPE_IVEC3, { TYPE_IVEC2, TYPE_INT, TYPE_VOID } },
- { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_IVEC2, TYPE_VOID } },
- { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_VOID } },
- { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID } },
- { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_IVEC2, TYPE_INT, TYPE_VOID } },
- { "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID } },
- { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_INT, TYPE_IVEC2, TYPE_VOID } },
- { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_IVEC3, TYPE_VOID } },
- { "ivec4", TYPE_IVEC4, { TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
- { "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID } },
-
- { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID } },
- { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_VOID } },
- { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_UINT, TYPE_VOID } },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_VOID } },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID } },
- { "uvec3", TYPE_UVEC3, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID } },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UVEC2, TYPE_VOID } },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_VOID } },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID } },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC2, TYPE_UINT, TYPE_VOID } },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID } },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UVEC2, TYPE_VOID } },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC3, TYPE_VOID } },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID } },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID } },
-
- { "mat2", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "mat3", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "mat4", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
-
- { "mat2", TYPE_MAT2, { TYPE_FLOAT, TYPE_VOID } },
- { "mat3", TYPE_MAT3, { TYPE_FLOAT, TYPE_VOID } },
- { "mat4", TYPE_MAT4, { TYPE_FLOAT, TYPE_VOID } },
+ { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec3", TYPE_BVEC3, { TYPE_BVEC2, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BVEC2, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec4", TYPE_BVEC4, { TYPE_BVEC2, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BOOL, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec4", TYPE_BVEC4, { TYPE_BVEC3, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec4", TYPE_BVEC4, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL },
+
+ { "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "vec2", TYPE_VEC2, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "vec2", TYPE_VEC2, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "vec3", TYPE_VEC3, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "vec4", TYPE_VEC4, { TYPE_VEC2, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "vec4", TYPE_VEC4, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "vec4", TYPE_VEC4, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+
+ { "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec2", TYPE_IVEC2, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec2", TYPE_IVEC2, { TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec3", TYPE_IVEC3, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_INT, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec4", TYPE_IVEC4, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+
+ { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec3", TYPE_UVEC3, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL },
+
+ { "mat2", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "mat3", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "mat4", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "mat2", TYPE_MAT2, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "mat3", TYPE_MAT3, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "mat4", TYPE_MAT4, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
//conversion scalars
- { "int", TYPE_INT, { TYPE_BOOL, TYPE_VOID } },
- { "int", TYPE_INT, { TYPE_INT, TYPE_VOID } },
- { "int", TYPE_INT, { TYPE_UINT, TYPE_VOID } },
- { "int", TYPE_INT, { TYPE_FLOAT, TYPE_VOID } },
+ { "int", TYPE_INT, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL },
+ { "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "int", TYPE_INT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "int", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
- { "float", TYPE_FLOAT, { TYPE_BOOL, TYPE_VOID } },
- { "float", TYPE_FLOAT, { TYPE_INT, TYPE_VOID } },
- { "float", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID } },
- { "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
+ { "float", TYPE_FLOAT, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL },
+ { "float", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "float", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
- { "uint", TYPE_UINT, { TYPE_BOOL, TYPE_VOID } },
- { "uint", TYPE_UINT, { TYPE_INT, TYPE_VOID } },
- { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID } },
- { "uint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID } },
+ { "uint", TYPE_UINT, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL },
+ { "uint", TYPE_UINT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "uint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
- { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID } },
- { "bool", TYPE_BOOL, { TYPE_INT, TYPE_VOID } },
- { "bool", TYPE_BOOL, { TYPE_UINT, TYPE_VOID } },
- { "bool", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID } },
+ { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL },
+ { "bool", TYPE_BOOL, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "bool", TYPE_BOOL, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "bool", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
//conversion vectors
- { "ivec2", TYPE_IVEC2, { TYPE_BVEC2, TYPE_VOID } },
- { "ivec2", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID } },
- { "ivec2", TYPE_IVEC2, { TYPE_UVEC2, TYPE_VOID } },
- { "ivec2", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID } },
-
- { "vec2", TYPE_VEC2, { TYPE_BVEC2, TYPE_VOID } },
- { "vec2", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID } },
- { "vec2", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID } },
- { "vec2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
-
- { "uvec2", TYPE_UVEC2, { TYPE_BVEC2, TYPE_VOID } },
- { "uvec2", TYPE_UVEC2, { TYPE_IVEC2, TYPE_VOID } },
- { "uvec2", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID } },
- { "uvec2", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID } },
-
- { "bvec2", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID } },
- { "bvec2", TYPE_BVEC2, { TYPE_IVEC2, TYPE_VOID } },
- { "bvec2", TYPE_BVEC2, { TYPE_UVEC2, TYPE_VOID } },
- { "bvec2", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID } },
-
- { "ivec3", TYPE_IVEC3, { TYPE_BVEC3, TYPE_VOID } },
- { "ivec3", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID } },
- { "ivec3", TYPE_IVEC3, { TYPE_UVEC3, TYPE_VOID } },
- { "ivec3", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID } },
-
- { "vec3", TYPE_VEC3, { TYPE_BVEC3, TYPE_VOID } },
- { "vec3", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID } },
- { "vec3", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID } },
- { "vec3", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
-
- { "uvec3", TYPE_UVEC3, { TYPE_BVEC3, TYPE_VOID } },
- { "uvec3", TYPE_UVEC3, { TYPE_IVEC3, TYPE_VOID } },
- { "uvec3", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID } },
- { "uvec3", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID } },
-
- { "bvec3", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID } },
- { "bvec3", TYPE_BVEC3, { TYPE_IVEC3, TYPE_VOID } },
- { "bvec3", TYPE_BVEC3, { TYPE_UVEC3, TYPE_VOID } },
- { "bvec3", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID } },
-
- { "ivec4", TYPE_IVEC4, { TYPE_BVEC4, TYPE_VOID } },
- { "ivec4", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID } },
- { "ivec4", TYPE_IVEC4, { TYPE_UVEC4, TYPE_VOID } },
- { "ivec4", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "vec4", TYPE_VEC4, { TYPE_BVEC4, TYPE_VOID } },
- { "vec4", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID } },
- { "vec4", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID } },
- { "vec4", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "uvec4", TYPE_UVEC4, { TYPE_BVEC4, TYPE_VOID } },
- { "uvec4", TYPE_UVEC4, { TYPE_IVEC4, TYPE_VOID } },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID } },
- { "uvec4", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "bvec4", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID } },
- { "bvec4", TYPE_BVEC4, { TYPE_IVEC4, TYPE_VOID } },
- { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID } },
- { "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID } },
+ { "ivec2", TYPE_IVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec2", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec2", TYPE_IVEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec2", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+
+ { "vec2", TYPE_VEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "vec2", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "vec2", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "vec2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+
+ { "uvec2", TYPE_UVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec2", TYPE_UVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec2", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec2", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+
+ { "bvec2", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec2", TYPE_BVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec2", TYPE_BVEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec2", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+
+ { "ivec3", TYPE_IVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec3", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec3", TYPE_IVEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec3", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+
+ { "vec3", TYPE_VEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "vec3", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "vec3", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "vec3", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+
+ { "uvec3", TYPE_UVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec3", TYPE_UVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec3", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec3", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+
+ { "bvec3", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec3", TYPE_BVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec3", TYPE_BVEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec3", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+
+ { "ivec4", TYPE_IVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec4", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec4", TYPE_IVEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "ivec4", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "vec4", TYPE_VEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "vec4", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "vec4", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "vec4", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "uvec4", TYPE_UVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec4", TYPE_UVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "uvec4", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "bvec4", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec4", TYPE_BVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
//conversion between matrixes
- { "mat2", TYPE_MAT2, { TYPE_MAT3, TYPE_VOID } },
- { "mat2", TYPE_MAT2, { TYPE_MAT4, TYPE_VOID } },
- { "mat3", TYPE_MAT3, { TYPE_MAT2, TYPE_VOID } },
- { "mat3", TYPE_MAT3, { TYPE_MAT4, TYPE_VOID } },
- { "mat4", TYPE_MAT4, { TYPE_MAT2, TYPE_VOID } },
- { "mat4", TYPE_MAT4, { TYPE_MAT3, TYPE_VOID } },
+ { "mat2", TYPE_MAT2, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL },
+ { "mat2", TYPE_MAT2, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL },
+ { "mat3", TYPE_MAT3, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL },
+ { "mat3", TYPE_MAT3, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL },
+ { "mat4", TYPE_MAT4, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL },
+ { "mat4", TYPE_MAT4, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL },
//builtins - trigonometry
- { "radians", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "radians", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "radians", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "radians", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "degrees", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "degrees", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "degrees", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "degrees", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "sin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "sin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "sin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "sin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "cos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "cos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "cos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "cos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "tan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "tan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "tan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "tan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "asin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "asin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "asin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "asin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "acos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "acos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "acos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "acos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
- { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
- { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
-
- { "sinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "sinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "sinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "sinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "cosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "cosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "cosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "cosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "tanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "tanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "tanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "tanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "asinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "asinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "asinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "asinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "acosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "acosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "acosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "acosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "atanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "atanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "atanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "atanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
+ { "radians", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "radians", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "radians", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "radians", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "degrees", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "degrees", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "degrees", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "degrees", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "sin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "sin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "sin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "sin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "cos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "cos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "cos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "cos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "tan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "tan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "tan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "tan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "asin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "asin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "asin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "asin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "acos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "acos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "acos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "acos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "sinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "sinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "sinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "sinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "cosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "cosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "cosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "cosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "tanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "tanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "tanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "tanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "asinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "asinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "asinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "asinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "acosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "acosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "acosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "acosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "atanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "atanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "atanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "atanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
//builtins - exponential
- { "pow", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
- { "pow", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "pow", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "pow", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
- { "exp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "exp", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "exp", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "exp", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
- { "log", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "log", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "log", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "log", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
- { "exp2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "exp2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "exp2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "exp2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
- { "log2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "log2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "log2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "log2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
- { "sqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "sqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "sqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "sqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
- { "inversesqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "inversesqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "inversesqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "inversesqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
+ { "pow", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "pow", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "pow", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "pow", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "exp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "exp", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "exp", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "exp", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "log", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "log", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "log", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "log", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "exp2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "exp2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "exp2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "exp2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "log2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "log2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "log2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "log2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "sqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "sqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "sqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "sqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "inversesqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "inversesqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "inversesqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "inversesqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
//builtins - common
- { "abs", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "abs", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "abs", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "abs", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "abs", TYPE_INT, { TYPE_INT, TYPE_VOID } },
- { "abs", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID } },
- { "abs", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID } },
- { "abs", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID } },
-
- { "sign", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "sign", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "sign", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "sign", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "sign", TYPE_INT, { TYPE_INT, TYPE_VOID } },
- { "sign", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID } },
- { "sign", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID } },
- { "sign", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID } },
-
- { "floor", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "floor", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "floor", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "floor", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
- { "trunc", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "trunc", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "trunc", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "trunc", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
- { "round", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "round", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "round", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "round", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
- { "roundEven", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "roundEven", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "roundEven", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "roundEven", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
- { "ceil", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "ceil", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "ceil", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "ceil", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
- { "fract", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "fract", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "fract", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "fract", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "mod", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
- { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
- { "mod", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "mod", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
- { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
-
- { "modf", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
- { "modf", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "modf", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "modf", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
-
- { "min", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
- { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
- { "min", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "min", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "min", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
- { "min", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
-
- { "min", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID } },
- { "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID } },
- { "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID } },
- { "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID } },
- { "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
- { "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID } },
- { "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID } },
-
- { "min", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID } },
- { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID } },
- { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID } },
- { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID } },
- { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID } },
- { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID } },
- { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID } },
-
- { "max", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
- { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
- { "max", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "max", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "max", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
- { "max", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
-
- { "max", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID } },
- { "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID } },
- { "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID } },
- { "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID } },
- { "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
- { "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID } },
- { "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID } },
-
- { "max", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID } },
- { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID } },
- { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID } },
- { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID } },
- { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID } },
- { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID } },
- { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID } },
-
- { "clamp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
- { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "clamp", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
- { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
- { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
- { "clamp", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
-
- { "clamp", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID } },
- { "clamp", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID } },
- { "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID } },
- { "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID } },
- { "clamp", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID } },
- { "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID } },
- { "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID } },
-
- { "clamp", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID } },
- { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID } },
- { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID } },
- { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID } },
- { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID } },
- { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_UINT, TYPE_VOID } },
- { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_UINT, TYPE_VOID } },
-
- { "mix", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
- { "mix", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_BOOL, TYPE_VOID } },
- { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
- { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_BOOL, TYPE_VOID } },
- { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_BVEC2, TYPE_VOID } },
- { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_BOOL, TYPE_VOID } },
- { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_BVEC3, TYPE_VOID } },
- { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
- { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BOOL, TYPE_VOID } },
- { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BVEC4, TYPE_VOID } },
- { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
-
- { "step", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
- { "step", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "step", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "step", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
- { "step", TYPE_VEC2, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID } },
- { "step", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID } },
- { "step", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC4, TYPE_VOID } },
- { "smoothstep", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
- { "smoothstep", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "smoothstep", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "smoothstep", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
- { "smoothstep", TYPE_VEC2, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC2, TYPE_VOID } },
- { "smoothstep", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC3, TYPE_VOID } },
- { "smoothstep", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC4, TYPE_VOID } },
-
- { "isnan", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID } },
- { "isnan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID } },
- { "isnan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID } },
- { "isnan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "isinf", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID } },
- { "isinf", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID } },
- { "isinf", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID } },
- { "isinf", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID } },
- { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID } },
- { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID } },
- { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID } },
- { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID } },
- { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID } },
- { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID } },
- { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID } },
- { "intBitsToFloat", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID } },
- { "intBitsToFloat", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID } },
-
- { "uintBitsToFloat", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID } },
- { "uintBitsToFloat", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID } },
- { "uintBitsToFloat", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID } },
- { "uintBitsToFloat", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID } },
+ { "abs", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "abs", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "abs", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "abs", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "abs", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "abs", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "abs", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "abs", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "sign", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "sign", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "sign", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "sign", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "sign", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "sign", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "sign", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "sign", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "floor", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "floor", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "floor", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "floor", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "trunc", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "trunc", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "trunc", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "trunc", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "round", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "round", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "round", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "round", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "roundEven", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "roundEven", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "roundEven", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "roundEven", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "ceil", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "ceil", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "ceil", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "ceil", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "fract", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "fract", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "fract", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "fract", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "mod", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "mod", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "mod", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "modf", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "modf", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "modf", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "modf", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "min", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "min", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "min", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "max", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "max", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "max", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "clamp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "clamp", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "clamp", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "mix", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "step", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "step", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "step", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "step", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "step", TYPE_VEC2, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "step", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "step", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "smoothstep", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "smoothstep", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "smoothstep", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "smoothstep", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "smoothstep", TYPE_VEC2, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "smoothstep", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "smoothstep", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "isnan", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "isnan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "isnan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "isnan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "isinf", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "isinf", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "isinf", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "isinf", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "intBitsToFloat", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "intBitsToFloat", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "uintBitsToFloat", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL },
+ { "uintBitsToFloat", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "uintBitsToFloat", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "uintBitsToFloat", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL },
//builtins - geometric
- { "length", TYPE_FLOAT, { TYPE_VEC2, TYPE_VOID } },
- { "length", TYPE_FLOAT, { TYPE_VEC3, TYPE_VOID } },
- { "length", TYPE_FLOAT, { TYPE_VEC4, TYPE_VOID } },
- { "distance", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "distance", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "distance", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
- { "dot", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "dot", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "dot", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
- { "cross", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "normalize", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "normalize", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "normalize", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
- { "reflect", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "refract", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
-
- { "faceforward", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "faceforward", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "faceforward", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
-
- { "matrixCompMult", TYPE_MAT2, { TYPE_MAT2, TYPE_MAT2, TYPE_VOID } },
- { "matrixCompMult", TYPE_MAT3, { TYPE_MAT3, TYPE_MAT3, TYPE_VOID } },
- { "matrixCompMult", TYPE_MAT4, { TYPE_MAT4, TYPE_MAT4, TYPE_VOID } },
-
- { "outerProduct", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "outerProduct", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "outerProduct", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
-
- { "transpose", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID } },
- { "transpose", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID } },
- { "transpose", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID } },
-
- { "determinant", TYPE_FLOAT, { TYPE_MAT2, TYPE_VOID } },
- { "determinant", TYPE_FLOAT, { TYPE_MAT3, TYPE_VOID } },
- { "determinant", TYPE_FLOAT, { TYPE_MAT4, TYPE_VOID } },
-
- { "inverse", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID } },
- { "inverse", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID } },
- { "inverse", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID } },
-
- { "lessThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "lessThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "lessThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
-
- { "lessThan", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID } },
- { "lessThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID } },
- { "lessThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID } },
-
- { "lessThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID } },
- { "lessThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID } },
- { "lessThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID } },
-
- { "greaterThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "greaterThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "greaterThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
-
- { "greaterThan", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID } },
- { "greaterThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID } },
- { "greaterThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID } },
-
- { "greaterThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID } },
- { "greaterThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID } },
- { "greaterThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID } },
-
- { "lessThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "lessThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "lessThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
-
- { "lessThanEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID } },
- { "lessThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID } },
- { "lessThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID } },
-
- { "lessThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID } },
- { "lessThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID } },
- { "lessThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID } },
-
- { "greaterThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "greaterThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "greaterThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
-
- { "greaterThanEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID } },
- { "greaterThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID } },
- { "greaterThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID } },
-
- { "greaterThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID } },
- { "greaterThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID } },
- { "greaterThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID } },
-
- { "equal", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "equal", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "equal", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
-
- { "equal", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID } },
- { "equal", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID } },
- { "equal", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID } },
-
- { "equal", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID } },
- { "equal", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID } },
- { "equal", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID } },
-
- { "equal", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID } },
- { "equal", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID } },
- { "equal", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID } },
-
- { "notEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "notEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "notEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
-
- { "notEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID } },
- { "notEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID } },
- { "notEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID } },
+ { "length", TYPE_FLOAT, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "length", TYPE_FLOAT, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "length", TYPE_FLOAT, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "distance", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "distance", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "distance", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "dot", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "dot", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "dot", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "cross", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "normalize", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "normalize", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "normalize", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "reflect", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "refract", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "faceforward", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "faceforward", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "faceforward", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "matrixCompMult", TYPE_MAT2, { TYPE_MAT2, TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL },
+ { "matrixCompMult", TYPE_MAT3, { TYPE_MAT3, TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL },
+ { "matrixCompMult", TYPE_MAT4, { TYPE_MAT4, TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "outerProduct", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "outerProduct", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "outerProduct", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "transpose", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL },
+ { "transpose", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL },
+ { "transpose", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "determinant", TYPE_FLOAT, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL },
+ { "determinant", TYPE_FLOAT, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL },
+ { "determinant", TYPE_FLOAT, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "inverse", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL },
+ { "inverse", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL },
+ { "inverse", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "lessThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "lessThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "lessThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "lessThan", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "lessThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "lessThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "lessThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "lessThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "lessThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "greaterThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "greaterThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "greaterThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "greaterThan", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "greaterThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "greaterThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "greaterThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "greaterThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "greaterThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "lessThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "lessThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "lessThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "lessThanEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "lessThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "lessThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "lessThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "lessThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "lessThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "greaterThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "greaterThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "greaterThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "greaterThanEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "greaterThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "greaterThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "greaterThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "greaterThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "greaterThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "equal", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "equal", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "equal", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "equal", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "equal", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "equal", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "equal", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "equal", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "equal", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "equal", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "equal", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "equal", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "notEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "notEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "notEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ { "notEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "notEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "notEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL },
- { "notEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID } },
- { "notEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID } },
- { "notEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID } },
+ { "notEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "notEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "notEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL },
- { "notEqual", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID } },
- { "notEqual", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID } },
- { "notEqual", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID } },
+ { "notEqual", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "notEqual", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "notEqual", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL },
- { "any", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID } },
- { "any", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID } },
- { "any", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID } },
+ { "any", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "any", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "any", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL },
- { "all", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID } },
- { "all", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID } },
- { "all", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID } },
+ { "all", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "all", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "all", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL },
- { "not", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID } },
- { "not", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID } },
- { "not", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID } },
+ { "not", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "not", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "not", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL },
//builtins - texture
- { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID } },
- { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID } },
- { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID } },
- { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID } },
- { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID } },
- { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID } },
- { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID } },
- { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID } },
- { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID } },
- { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID } },
-
- { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID } },
- { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
-
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID } },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
-
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID } },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
-
- { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID } },
- { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
-
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID } },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
-
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID } },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
-
- { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID } },
- { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
-
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID } },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
-
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID } },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
-
- { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID } },
- { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
-
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID } },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID } },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
-
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VOID } },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_VOID } },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
-
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VOID } },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_VOID } },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
-
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID } },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
-
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID } },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
-
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID } },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
-
- { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
- { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
-
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID } },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID } },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID } },
-
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
-
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
-
- { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
-
- { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
-
- { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
-
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+
+ { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
- { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
+ { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "dFdy", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
- { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "dFdy", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
-
- { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
- { "fwidth", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
- { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
- { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
+ { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL },
+ { "fwidth", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL },
+ { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL },
+ { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL },
+
+ //sub-functions
- { NULL, TYPE_VOID, { TYPE_VOID } }
+ //array
+ { "length", TYPE_INT, { TYPE_VOID }, TAG_ARRAY },
+ { NULL, TYPE_VOID, { TYPE_VOID }, TAG_GLOBAL }
+
+};
+
+const ShaderLanguage::BuiltinFuncOutArgs ShaderLanguage::builtin_func_out_args[] = {
+ //constructors
+ { "modf", 1 },
+ { NULL, 0 }
};
bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type) {
- ERR_FAIL_COND_V(p_func->op != OP_CALL && p_func->op != OP_CONSTRUCT, NULL);
+ ERR_FAIL_COND_V(p_func->op != OP_CALL && p_func->op != OP_CONSTRUCT, false);
Vector<DataType> args;
- ERR_FAIL_COND_V(p_func->arguments[0]->type != Node::TYPE_VARIABLE, NULL);
+ ERR_FAIL_COND_V(p_func->arguments[0]->type != Node::TYPE_VARIABLE, false);
StringName name = static_cast<VariableNode *>(p_func->arguments[0])->name.operator String();
- bool all_const = true;
for (int i = 1; i < p_func->arguments.size(); i++) {
- if (p_func->arguments[i]->type != Node::TYPE_CONSTANT)
- all_const = false;
args.push_back(p_func->arguments[i]->get_datatype());
}
@@ -2040,6 +2107,11 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
while (builtin_func_defs[idx].name) {
+ if (completion_class != builtin_func_defs[idx].tag) {
+ idx++;
+ continue;
+ }
+
if (name == builtin_func_defs[idx].name) {
failed_builtin = true;
@@ -2047,7 +2119,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
for (int i = 0; i < argcount; i++) {
if (get_scalar_type(args[i]) == args[i] && p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[i + 1]), builtin_func_defs[idx].args[i])) {
- //all good
+ //all good, but needs implicit conversion later
} else if (args[i] != builtin_func_defs[idx].args[i]) {
fail = true;
break;
@@ -2059,6 +2131,59 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
if (!fail) {
+ //make sure its not an out argument used in the wrong way
+ int outarg_idx = 0;
+ while (builtin_func_out_args[outarg_idx].name) {
+
+ if (String(name) == builtin_func_out_args[outarg_idx].name) {
+ int arg_idx = builtin_func_out_args[outarg_idx].argument;
+
+ if (arg_idx < argcount) {
+
+ if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE) {
+ _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable");
+ return false;
+ }
+ StringName var_name = static_cast<const VariableNode *>(p_func->arguments[arg_idx + 1])->name;
+
+ const BlockNode *b = p_block;
+ bool valid = false;
+ while (b) {
+ if (b->variables.has(var_name)) {
+ valid = true;
+ break;
+ }
+ b = b->parent_block;
+ }
+
+ if (!valid) {
+ _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable");
+ return false;
+ }
+ }
+ }
+
+ outarg_idx++;
+ }
+ //implicitly convert values if possible
+ for (int i = 0; i < argcount; i++) {
+
+ if (get_scalar_type(args[i]) != args[i] || args[i] == builtin_func_defs[idx].args[i] || p_func->arguments[i + 1]->type != Node::TYPE_CONSTANT) {
+ //can't do implicit conversion here
+ continue;
+ }
+
+ //this is an implicit conversion
+ ConstantNode *constant = static_cast<ConstantNode *>(p_func->arguments[i + 1]);
+ ConstantNode *conversion = alloc_node<ConstantNode>();
+
+ conversion->datatype = builtin_func_defs[idx].args[i];
+ conversion->values.resize(1);
+
+ convert_constant(constant, builtin_func_defs[idx].args[i], conversion->values.ptrw());
+ p_func->arguments.write[i + 1] = conversion;
+ }
+
if (r_ret_type)
*r_ret_type = builtin_func_defs[idx].rettype;
@@ -2121,17 +2246,37 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
bool fail = false;
- for (int i = 0; i < args.size(); i++) {
+ for (int j = 0; j < args.size(); j++) {
- if (get_scalar_type(args[i]) == args[i] && p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[i + 1]), pfunc->arguments[i].type)) {
- //all good
- } else if (args[i] != pfunc->arguments[i].type) {
+ if (get_scalar_type(args[j]) == args[j] && p_func->arguments[j + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[j + 1]), pfunc->arguments[j].type)) {
+ //all good, but it needs implicit conversion later
+ } else if (args[j] != pfunc->arguments[j].type) {
fail = true;
break;
}
}
if (!fail) {
+
+ //implicitly convert values if possible
+ for (int k = 0; k < args.size(); k++) {
+
+ if (get_scalar_type(args[k]) != args[k] || args[k] == pfunc->arguments[k].type || p_func->arguments[k + 1]->type != Node::TYPE_CONSTANT) {
+ //can't do implicit conversion here
+ continue;
+ }
+
+ //this is an implicit conversion
+ ConstantNode *constant = static_cast<ConstantNode *>(p_func->arguments[k + 1]);
+ ConstantNode *conversion = alloc_node<ConstantNode>();
+
+ conversion->datatype = pfunc->arguments[k].type;
+ conversion->values.resize(1);
+
+ convert_constant(constant, pfunc->arguments[k].type, conversion->values.ptrw());
+ p_func->arguments.write[k + 1] = conversion;
+ }
+
if (r_ret_type)
*r_ret_type = pfunc->return_type;
return true;
@@ -2291,7 +2436,7 @@ bool ShaderLanguage::is_sampler_type(DataType p_type) {
p_type == TYPE_SAMPLERCUBE;
}
-Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type) {
+Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) {
if (p_value.size() > 0) {
Variant value;
switch (p_type) {
@@ -2335,7 +2480,11 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
value = Variant(Vector3(p_value[0].real, p_value[1].real, p_value[2].real));
break;
case ShaderLanguage::TYPE_VEC4:
- value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ value = Variant(Color(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ } else {
+ value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ }
break;
case ShaderLanguage::TYPE_MAT2:
value = Variant(Transform2D(p_value[0].real, p_value[2].real, p_value[1].real, p_value[3].real, 0.0, 0.0));
@@ -2369,6 +2518,21 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
value = Variant(t);
break;
}
+ case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_ISAMPLER2D:
+ case ShaderLanguage::TYPE_ISAMPLER3D:
+ case ShaderLanguage::TYPE_SAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_SAMPLER2D:
+ case ShaderLanguage::TYPE_SAMPLER3D:
+ case ShaderLanguage::TYPE_USAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_USAMPLER2D:
+ case ShaderLanguage::TYPE_USAMPLER3D:
+ case ShaderLanguage::TYPE_SAMPLERCUBE: {
+ // Texture types, likely not relevant here.
+ break;
+ }
+ case ShaderLanguage::TYPE_VOID:
+ break;
}
return value;
}
@@ -2486,7 +2650,7 @@ bool ShaderLanguage::_get_completable_identifier(BlockNode *p_block, CompletionT
identifier = StringName();
- TkPos pos;
+ TkPos pos = { 0, 0 };
Token tk = _get_token();
@@ -2579,9 +2743,32 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltI
return false;
}
+ if (shader->constants.has(var->name) || var->is_const) {
+ if (r_message)
+ *r_message = RTR("Constants cannot be modified.");
+ return false;
+ }
+
if (!(p_builtin_types.has(var->name) && p_builtin_types[var->name].constant)) {
return true;
}
+ } else if (p_node->type == Node::TYPE_ARRAY) {
+
+ ArrayNode *arr = static_cast<ArrayNode *>(p_node);
+
+ if (arr->is_const) {
+ if (r_message)
+ *r_message = RTR("Constants cannot be modified.");
+ return false;
+ }
+
+ if (shader->varyings.has(arr->name) && current_function != String("vertex")) {
+ if (r_message)
+ *r_message = RTR("Varyings can only be assigned in vertex function.");
+ return false;
+ }
+
+ return true;
}
if (r_message)
@@ -2592,6 +2779,7 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltI
ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types) {
Vector<Expression> expression;
+
//Vector<TokenType> operators;
while (true) {
@@ -2700,7 +2888,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
_set_error("No matching constructor found for: '" + String(funcname->name) + "'");
return NULL;
}
- //validate_Function_call()
expr = _reduce_expression(p_block, func);
@@ -2756,6 +2943,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
_set_error("No matching function found for: '" + String(funcname->name) + "'");
return NULL;
}
+ completion_class = TAG_GLOBAL; // reset sub-class
expr = func;
@@ -2766,8 +2954,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
DataType data_type;
IdentifierType ident_type;
+ bool is_const = false;
+ int array_size = 0;
- if (!_find_identifier(p_block, p_builtin_types, identifier, &data_type, &ident_type)) {
+ if (!_find_identifier(p_block, p_builtin_types, identifier, &data_type, &ident_type, &is_const, &array_size)) {
_set_error("Unknown identifier in expression: " + String(identifier));
return NULL;
}
@@ -2777,10 +2967,70 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return NULL;
}
- VariableNode *varname = alloc_node<VariableNode>();
- varname->name = identifier;
- varname->datatype_cache = data_type;
- expr = varname;
+ Node *index_expression = NULL;
+ Node *call_expression = NULL;
+
+ if (array_size > 0) {
+ tk = _get_token();
+
+ if (tk.type != TK_BRACKET_OPEN && tk.type != TK_PERIOD) {
+ _set_error("Expected '[' or '.'");
+ return NULL;
+ }
+
+ if (tk.type == TK_PERIOD) {
+ completion_class = TAG_ARRAY;
+ call_expression = _parse_and_reduce_expression(p_block, p_builtin_types);
+ if (!call_expression)
+ return NULL;
+ data_type = call_expression->get_datatype();
+ } else { // indexing
+
+ index_expression = _parse_and_reduce_expression(p_block, p_builtin_types);
+ if (!index_expression)
+ return NULL;
+
+ if (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT) {
+ _set_error("Only integer expressions are allowed for indexing");
+ return NULL;
+ }
+
+ if (index_expression->type == Node::TYPE_CONSTANT) {
+ ConstantNode *cnode = (ConstantNode *)index_expression;
+ if (cnode) {
+ if (!cnode->values.empty()) {
+ int value = cnode->values[0].sint;
+ if (value < 0 || value >= array_size) {
+ _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1));
+ return NULL;
+ }
+ }
+ }
+ }
+
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return NULL;
+ }
+ }
+
+ ArrayNode *arrname = alloc_node<ArrayNode>();
+ arrname->name = identifier;
+ arrname->datatype_cache = data_type;
+ arrname->index_expression = index_expression;
+ arrname->call_expression = call_expression;
+ arrname->is_const = is_const;
+ expr = arrname;
+
+ } else {
+
+ VariableNode *varname = alloc_node<VariableNode>();
+ varname->name = identifier;
+ varname->datatype_cache = data_type;
+ varname->is_const = is_const;
+ expr = varname;
+ }
}
} else if (tk.type == TK_OP_ADD) {
@@ -2815,7 +3065,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
/* OK now see what's NEXT to the operator.. */
while (true) {
- TkPos pos = _get_tkpos();
+ TkPos pos2 = _get_tkpos();
tk = _get_token();
if (tk.type == TK_CURSOR) {
@@ -2831,12 +3081,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
_set_error("Expected identifier as member");
return NULL;
}
-
DataType dt = expr->get_datatype();
String ident = identifier;
bool ok = true;
- DataType member_type;
+ DataType member_type = TYPE_VOID;
switch (dt) {
case TYPE_BVEC2:
case TYPE_IVEC2:
@@ -2848,6 +3097,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
member_type = DataType(dt - 1);
} else if (l == 2) {
member_type = dt;
+ } else if (l == 3) {
+ member_type = DataType(dt + 1);
+ } else if (l == 4) {
+ member_type = DataType(dt + 2);
} else {
ok = false;
break;
@@ -2881,6 +3134,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
member_type = DataType(dt - 1);
} else if (l == 3) {
member_type = dt;
+ } else if (l == 4) {
+ member_type = DataType(dt + 1);
} else {
ok = false;
break;
@@ -3008,6 +3263,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
case TYPE_IVEC2: member_type = TYPE_INT; break;
case TYPE_UVEC2: member_type = TYPE_UINT; break;
case TYPE_MAT2: member_type = TYPE_VEC2; break;
+ default: break;
}
break;
@@ -3033,6 +3289,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
case TYPE_IVEC3: member_type = TYPE_INT; break;
case TYPE_UVEC3: member_type = TYPE_UINT; break;
case TYPE_MAT3: member_type = TYPE_VEC3; break;
+ default: break;
}
break;
case TYPE_BVEC4:
@@ -3057,6 +3314,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
case TYPE_IVEC4: member_type = TYPE_INT; break;
case TYPE_UVEC4: member_type = TYPE_UINT; break;
case TYPE_MAT4: member_type = TYPE_VEC4; break;
+ default: break;
}
break;
default: {
@@ -3096,7 +3354,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expr = op;
} else {
- _set_tkpos(pos);
+ _set_tkpos(pos2);
break;
}
}
@@ -3289,10 +3547,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (!_validate_operator(op, &op->return_cache)) {
String at;
- for (int i = 0; i < op->arguments.size(); i++) {
- if (i > 0)
+ for (int j = 0; j < op->arguments.size(); j++) {
+ if (j > 0)
at += " and ";
- at += get_datatype_name(op->arguments[i]->get_datatype());
+ at += get_datatype_name(op->arguments[j]->get_datatype());
}
_set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at);
return NULL;
@@ -3491,12 +3749,14 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
nv.sint = -cn->values[i].sint;
} break;
case TYPE_UINT: {
+ // FIXME: This can't work on uint
nv.uint = -cn->values[i].uint;
} break;
case TYPE_FLOAT: {
nv.real = -cn->values[i].real;
} break;
- default: {}
+ default: {
+ }
}
values.push_back(nv);
@@ -3528,6 +3788,14 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
TkPos pos = _get_tkpos();
Token tk = _get_token();
+
+ if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_SWITCH) {
+ if (tk.type != TK_CF_CASE && tk.type != TK_CF_DEFAULT && tk.type != TK_CURLY_BRACKET_CLOSE) {
+ _set_error("Switch may contains only case and default blocks");
+ return ERR_PARSE_ERROR;
+ }
+ }
+
if (tk.type == TK_CURLY_BRACKET_CLOSE) { //end of block
if (p_just_one) {
_set_error("Unexpected '}'");
@@ -3536,7 +3804,15 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
return OK;
- } else if (is_token_precision(tk.type) || is_token_nonvoid_datatype(tk.type)) {
+ } else if (tk.type == TK_CONST || is_token_precision(tk.type) || is_token_nonvoid_datatype(tk.type)) {
+
+ bool is_const = false;
+
+ if (tk.type == TK_CONST) {
+ is_const = true;
+ tk = _get_token();
+ }
+
DataPrecision precision = PRECISION_DEFAULT;
if (is_token_precision(tk.type)) {
precision = get_token_precision(tk.type);
@@ -3547,15 +3823,16 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
}
}
+ if (!is_token_variable_datatype(tk.type)) {
+ _set_error("Invalid data type for variable (samplers not allowed)");
+ return ERR_PARSE_ERROR;
+ }
+
DataType type = get_token_datatype(tk.type);
tk = _get_token();
- VariableDeclarationNode *vardecl = alloc_node<VariableDeclarationNode>();
- vardecl->datatype = type;
- vardecl->precision = precision;
-
- p_block->statements.push_back(vardecl);
+ Node *vardecl = NULL;
while (true) {
@@ -3574,15 +3851,213 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
var.type = type;
var.precision = precision;
var.line = tk_line;
+ var.array_size = 0;
+ var.is_const = is_const;
- VariableDeclarationNode::Declaration decl;
+ tk = _get_token();
- decl.name = name;
- decl.initializer = NULL;
+ if (tk.type == TK_BRACKET_OPEN) {
+ bool unknown_size = false;
- tk = _get_token();
+ ArrayDeclarationNode *node = alloc_node<ArrayDeclarationNode>();
+ node->datatype = type;
+ node->precision = precision;
+ node->is_const = is_const;
+ vardecl = (Node *)node;
+
+ ArrayDeclarationNode::Declaration decl;
+ decl.name = name;
+ decl.size = 0U;
+
+ tk = _get_token();
+
+ if (tk.type == TK_BRACKET_CLOSE) {
+ unknown_size = true;
+ } else {
+
+ if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
+ _set_error("Expected integer constant > 0 or ']'");
+ return ERR_PARSE_ERROR;
+ }
+
+ decl.size = ((uint32_t)tk.constant);
+ tk = _get_token();
+
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ }
+ var.array_size = decl.size;
+ }
+
+ bool full_def = false;
+
+ tk = _get_token();
+ if (tk.type == TK_OP_ASSIGN) {
+ tk = _get_token();
+
+ if (tk.type != TK_CURLY_BRACKET_OPEN) {
+
+ if (unknown_size) {
+ _set_error("Expected '{'");
+ return ERR_PARSE_ERROR;
+ }
+
+ full_def = true;
+
+ DataPrecision precision2 = PRECISION_DEFAULT;
+ if (is_token_precision(tk.type)) {
+ precision2 = get_token_precision(tk.type);
+ tk = _get_token();
+ if (!is_token_nonvoid_datatype(tk.type)) {
+ _set_error("Expected datatype after precision");
+ return ERR_PARSE_ERROR;
+ }
+ }
+ if (!is_token_variable_datatype(tk.type)) {
+ _set_error("Invalid data type for array");
+ return ERR_PARSE_ERROR;
+ }
+ DataType type2 = get_token_datatype(tk.type);
+
+ int array_size2 = 0;
+
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_OPEN) {
+ Node *n = _parse_and_reduce_expression(p_block, p_builtin_types);
+ if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+
+ ConstantNode *cnode = (ConstantNode *)n;
+ if (cnode->values.size() == 1) {
+ array_size2 = cnode->values[0].sint;
+ if (array_size2 <= 0) {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']");
+ return ERR_PARSE_ERROR;
+ } else {
+ tk = _get_token();
+ }
+ } else {
+ _set_error("Expected '[");
+ return ERR_PARSE_ERROR;
+ }
+
+ if (precision != precision2 || type != type2 || var.array_size != array_size2) {
+ String error_str = "Cannot convert from '";
+ if (precision2 != PRECISION_DEFAULT) {
+ error_str += get_precision_name(precision2);
+ error_str += " ";
+ }
+ error_str += get_datatype_name(type2);
+ error_str += "[";
+ error_str += itos(array_size2);
+ error_str += "]'";
+ error_str += " to '";
+ if (precision != PRECISION_DEFAULT) {
+ error_str += get_precision_name(precision);
+ error_str += " ";
+ }
+ error_str += get_datatype_name(type);
+ error_str += "[";
+ error_str += itos(var.array_size);
+ error_str += "]'";
+ _set_error(error_str);
+ return ERR_PARSE_ERROR;
+ }
+ }
+
+ bool curly = tk.type == TK_CURLY_BRACKET_OPEN;
+
+ if (unknown_size) {
+ if (!curly) {
+ _set_error("Expected '{'");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ if (full_def) {
+ if (curly) {
+ _set_error("Expected '('");
+ return ERR_PARSE_ERROR;
+ }
+ }
+ }
+
+ if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization
+ while (true) {
+
+ Node *n = _parse_and_reduce_expression(p_block, p_builtin_types);
+ if (!n) {
+ return ERR_PARSE_ERROR;
+ }
+
+ if (var.type != n->get_datatype()) {
+ _set_error("Invalid assignment of '" + get_datatype_name(n->get_datatype()) + "' to '" + get_datatype_name(var.type) + "'");
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = _get_token();
+ if (tk.type == TK_COMMA) {
+ decl.initializer.push_back(n);
+ continue;
+ } else if (!curly && tk.type == TK_PARENTHESIS_CLOSE) {
+ decl.initializer.push_back(n);
+ break;
+ } else if (curly && tk.type == TK_CURLY_BRACKET_CLOSE) {
+ decl.initializer.push_back(n);
+ break;
+ } else {
+ if (curly)
+ _set_error("Expected '}' or ','");
+ else
+ _set_error("Expected ')' or ','");
+ return ERR_PARSE_ERROR;
+ }
+ }
+ if (unknown_size) {
+ decl.size = decl.initializer.size();
+ var.array_size = decl.initializer.size();
+ } else if (decl.initializer.size() != var.array_size) {
+ _set_error("Array size mismatch");
+ return ERR_PARSE_ERROR;
+ }
+ tk = _get_token();
+ }
+ } else {
+ if (unknown_size) {
+ _set_error("Expected array initialization");
+ return ERR_PARSE_ERROR;
+ }
+ if (is_const) {
+ _set_error("Expected initialization of constant");
+ return ERR_PARSE_ERROR;
+ }
+ }
+
+ node->declarations.push_back(decl);
+ } else if (tk.type == TK_OP_ASSIGN) {
+
+ VariableDeclarationNode *node = alloc_node<VariableDeclarationNode>();
+ node->datatype = type;
+ node->precision = precision;
+ node->is_const = is_const;
+ vardecl = (Node *)node;
+
+ VariableDeclarationNode::Declaration decl;
+ decl.name = name;
+ decl.initializer = NULL;
- if (tk.type == TK_OP_ASSIGN) {
//variable created with assignment! must parse an expression
Node *n = _parse_and_reduce_expression(p_block, p_builtin_types);
if (!n)
@@ -3595,11 +4070,27 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
return ERR_PARSE_ERROR;
}
tk = _get_token();
+ node->declarations.push_back(decl);
+ } else {
+ if (is_const) {
+ _set_error("Expected initialization of constant");
+ return ERR_PARSE_ERROR;
+ }
+
+ VariableDeclarationNode *node = alloc_node<VariableDeclarationNode>();
+ node->datatype = type;
+ node->precision = precision;
+ vardecl = (Node *)node;
+
+ VariableDeclarationNode::Declaration decl;
+ decl.name = name;
+ decl.initializer = NULL;
+ node->declarations.push_back(decl);
}
- p_block->variables[name] = var;
+ p_block->statements.push_back(vardecl);
- vardecl->declarations.push_back(decl);
+ p_block->variables[name] = var;
if (tk.type == TK_COMMA) {
tk = _get_token();
@@ -3659,37 +4150,250 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
} else {
_set_tkpos(pos); //rollback
}
- } else if (tk.type == TK_CF_WHILE) {
- //if () {}
+ } else if (tk.type == TK_CF_SWITCH) {
+ // switch() {}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_OPEN) {
- _set_error("Expected '(' after while");
+ _set_error("Expected '(' after switch");
return ERR_PARSE_ERROR;
}
-
ControlFlowNode *cf = alloc_node<ControlFlowNode>();
- cf->flow_op = FLOW_OP_WHILE;
+ cf->flow_op = FLOW_OP_SWITCH;
Node *n = _parse_and_reduce_expression(p_block, p_builtin_types);
if (!n)
return ERR_PARSE_ERROR;
-
+ if (n->get_datatype() != TYPE_INT) {
+ _set_error("Expected integer expression");
+ return ERR_PARSE_ERROR;
+ }
tk = _get_token();
if (tk.type != TK_PARENTHESIS_CLOSE) {
_set_error("Expected ')' after expression");
return ERR_PARSE_ERROR;
}
+ tk = _get_token();
+ if (tk.type != TK_CURLY_BRACKET_OPEN) {
+ _set_error("Expected '{' after switch statement");
+ return ERR_PARSE_ERROR;
+ }
+ BlockNode *switch_block = alloc_node<BlockNode>();
+ switch_block->block_type = BlockNode::BLOCK_TYPE_SWITCH;
+ switch_block->parent_block = p_block;
+ cf->expressions.push_back(n);
+ cf->blocks.push_back(switch_block);
+ p_block->statements.push_back(cf);
- BlockNode *block = alloc_node<BlockNode>();
- block->parent_block = p_block;
+ int prev_type = TK_CF_CASE;
+ while (true) { // Go-through multiple cases.
+
+ if (_parse_block(switch_block, p_builtin_types, true, true, false) != OK) {
+ return ERR_PARSE_ERROR;
+ }
+ pos = _get_tkpos();
+ tk = _get_token();
+ if (tk.type == TK_CF_CASE || tk.type == TK_CF_DEFAULT) {
+ if (prev_type == TK_CF_DEFAULT) {
+ if (tk.type == TK_CF_CASE) {
+ _set_error("Cases must be defined before default case.");
+ return ERR_PARSE_ERROR;
+ } else if (prev_type == TK_CF_DEFAULT) {
+ _set_error("Default case must be defined only once.");
+ return ERR_PARSE_ERROR;
+ }
+ }
+ prev_type = tk.type;
+ _set_tkpos(pos);
+ continue;
+ } else {
+ Set<int> constants;
+ for (int i = 0; i < switch_block->statements.size(); i++) { // Checks for duplicates.
+ ControlFlowNode *flow = (ControlFlowNode *)switch_block->statements[i];
+ if (flow) {
+ if (flow->flow_op == FLOW_OP_CASE) {
+ ConstantNode *n2 = static_cast<ConstantNode *>(flow->expressions[0]);
+ if (!n2) {
+ return ERR_PARSE_ERROR;
+ }
+ if (n2->values.empty()) {
+ return ERR_PARSE_ERROR;
+ }
+ if (constants.has(n2->values[0].sint)) {
+ _set_error("Duplicated case label: '" + itos(n2->values[0].sint) + "'");
+ return ERR_PARSE_ERROR;
+ }
+ constants.insert(n2->values[0].sint);
+ } else if (flow->flow_op == FLOW_OP_DEFAULT) {
+ continue;
+ } else {
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ return ERR_PARSE_ERROR;
+ }
+ }
+ break;
+ }
+ }
+
+ } else if (tk.type == TK_CF_CASE) {
+ // case x : break; | return;
+
+ if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_CASE) {
+ _set_tkpos(pos);
+ return OK;
+ }
+
+ if (!p_block || (p_block->block_type != BlockNode::BLOCK_TYPE_SWITCH)) {
+ _set_error("case must be placed within switch block");
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = _get_token();
+
+ int sign = 1;
+
+ if (tk.type == TK_OP_SUB) {
+ sign = -1;
+ tk = _get_token();
+ }
+
+ if (tk.type != TK_INT_CONSTANT) {
+ _set_error("Expected integer constant");
+ return ERR_PARSE_ERROR;
+ }
+
+ int constant = (int)tk.constant * sign;
+
+ tk = _get_token();
+
+ if (tk.type != TK_COLON) {
+ _set_error("Expected ':'");
+ return ERR_PARSE_ERROR;
+ }
+
+ ControlFlowNode *cf = alloc_node<ControlFlowNode>();
+ cf->flow_op = FLOW_OP_CASE;
+
+ ConstantNode *n = alloc_node<ConstantNode>();
+ ConstantNode::Value v;
+ v.sint = constant;
+ n->values.push_back(v);
+ n->datatype = TYPE_INT;
+
+ BlockNode *case_block = alloc_node<BlockNode>();
+ case_block->block_type = BlockNode::BLOCK_TYPE_CASE;
+ case_block->parent_block = p_block;
cf->expressions.push_back(n);
- cf->blocks.push_back(block);
+ cf->blocks.push_back(case_block);
p_block->statements.push_back(cf);
- Error err = _parse_block(block, p_builtin_types, true, true, true);
+ Error err = _parse_block(case_block, p_builtin_types, false, true, false);
+ if (err)
+ return err;
+
+ return OK;
+
+ } else if (tk.type == TK_CF_DEFAULT) {
+
+ if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_CASE) {
+ _set_tkpos(pos);
+ return OK;
+ }
+
+ if (!p_block || (p_block->block_type != BlockNode::BLOCK_TYPE_SWITCH)) {
+ _set_error("default must be placed within switch block");
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = _get_token();
+
+ if (tk.type != TK_COLON) {
+ _set_error("Expected ':'");
+ return ERR_PARSE_ERROR;
+ }
+
+ ControlFlowNode *cf = alloc_node<ControlFlowNode>();
+ cf->flow_op = FLOW_OP_DEFAULT;
+
+ BlockNode *default_block = alloc_node<BlockNode>();
+ default_block->block_type = BlockNode::BLOCK_TYPE_DEFAULT;
+ default_block->parent_block = p_block;
+ cf->blocks.push_back(default_block);
+ p_block->statements.push_back(cf);
+
+ Error err = _parse_block(default_block, p_builtin_types, false, true, false);
if (err)
return err;
+
+ return OK;
+
+ } else if (tk.type == TK_CF_DO || tk.type == TK_CF_WHILE) {
+ // do {} while()
+ // while() {}
+ bool is_do = tk.type == TK_CF_DO;
+
+ BlockNode *do_block = NULL;
+ if (is_do) {
+
+ do_block = alloc_node<BlockNode>();
+ do_block->parent_block = p_block;
+
+ Error err = _parse_block(do_block, p_builtin_types, true, true, true);
+ if (err)
+ return err;
+
+ tk = _get_token();
+ if (tk.type != TK_CF_WHILE) {
+ _set_error("Expected while after do");
+ return ERR_PARSE_ERROR;
+ }
+ }
+ tk = _get_token();
+
+ if (tk.type != TK_PARENTHESIS_OPEN) {
+ _set_error("Expected '(' after while");
+ return ERR_PARSE_ERROR;
+ }
+
+ ControlFlowNode *cf = alloc_node<ControlFlowNode>();
+ if (is_do) {
+ cf->flow_op = FLOW_OP_DO;
+ } else {
+ cf->flow_op = FLOW_OP_WHILE;
+ }
+ Node *n = _parse_and_reduce_expression(p_block, p_builtin_types);
+ if (!n)
+ return ERR_PARSE_ERROR;
+
+ tk = _get_token();
+ if (tk.type != TK_PARENTHESIS_CLOSE) {
+ _set_error("Expected ')' after expression");
+ return ERR_PARSE_ERROR;
+ }
+ if (!is_do) {
+ BlockNode *block = alloc_node<BlockNode>();
+ block->parent_block = p_block;
+ cf->expressions.push_back(n);
+ cf->blocks.push_back(block);
+ p_block->statements.push_back(cf);
+
+ Error err = _parse_block(block, p_builtin_types, true, true, true);
+ if (err)
+ return err;
+ } else {
+
+ cf->expressions.push_back(n);
+ cf->blocks.push_back(do_block);
+ p_block->statements.push_back(cf);
+
+ tk = _get_token();
+ if (tk.type != TK_SEMICOLON) {
+ _set_error("Expected ';'");
+ return ERR_PARSE_ERROR;
+ }
+ }
} else if (tk.type == TK_CF_FOR) {
- //if () {}
+ // for() {}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_OPEN) {
_set_error("Expected '(' after for");
@@ -3790,6 +4494,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
}
p_block->statements.push_back(flow);
+ if (p_block->block_type == BlockNode::BLOCK_TYPE_CASE || p_block->block_type == BlockNode::BLOCK_TYPE_DEFAULT) {
+ return OK;
+ }
} else if (tk.type == TK_CF_DISCARD) {
//check return type
@@ -3836,9 +4543,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
}
p_block->statements.push_back(flow);
+ if (p_block->block_type == BlockNode::BLOCK_TYPE_CASE || p_block->block_type == BlockNode::BLOCK_TYPE_DEFAULT) {
+ return OK;
+ }
+
} else if (tk.type == TK_CF_CONTINUE) {
- if (!p_can_break) {
+ if (!p_can_continue) {
//all is good
_set_error("Continuing is not allowed here");
}
@@ -3857,7 +4568,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
} else {
- //nothng else, so expression
+ //nothing else, so expression
_set_tkpos(pos); //rollback
Node *expr = _parse_and_reduce_expression(p_block, p_builtin_types);
if (!expr)
@@ -3993,7 +4704,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
if (!uniform && (type < TYPE_FLOAT || type > TYPE_MAT4)) {
- _set_error("Invalid type for varying, only float,vec2,vec3,vec4,mat2,mat3,mat4 allowed.");
+ _set_error("Invalid type for varying, only float,vec2,vec3,vec4,mat2,mat3,mat4 or array of these types allowed.");
return ERR_PARSE_ERROR;
}
@@ -4012,17 +4723,17 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (uniform) {
- ShaderNode::Uniform uniform;
+ ShaderNode::Uniform uniform2;
if (is_sampler_type(type)) {
- uniform.texture_order = texture_uniforms++;
- uniform.order = -1;
+ uniform2.texture_order = texture_uniforms++;
+ uniform2.order = -1;
} else {
- uniform.texture_order = -1;
- uniform.order = uniforms++;
+ uniform2.texture_order = -1;
+ uniform2.order = uniforms++;
}
- uniform.type = type;
- uniform.precission = precision;
+ uniform2.type = type;
+ uniform2.precision = precision;
//todo parse default value
@@ -4033,26 +4744,26 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_HINT_WHITE_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_WHITE;
+ uniform2.hint = ShaderNode::Uniform::HINT_WHITE;
} else if (tk.type == TK_HINT_BLACK_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_BLACK;
+ uniform2.hint = ShaderNode::Uniform::HINT_BLACK;
} else if (tk.type == TK_HINT_NORMAL_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_NORMAL;
+ uniform2.hint = ShaderNode::Uniform::HINT_NORMAL;
} else if (tk.type == TK_HINT_ANISO_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_ANISO;
+ uniform2.hint = ShaderNode::Uniform::HINT_ANISO;
} else if (tk.type == TK_HINT_ALBEDO_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_ALBEDO;
+ uniform2.hint = ShaderNode::Uniform::HINT_ALBEDO;
} else if (tk.type == TK_HINT_BLACK_ALBEDO_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_BLACK_ALBEDO;
+ uniform2.hint = ShaderNode::Uniform::HINT_BLACK_ALBEDO;
} else if (tk.type == TK_HINT_COLOR) {
if (type != TYPE_VEC4) {
_set_error("Color hint is for vec4 only");
return ERR_PARSE_ERROR;
}
- uniform.hint = ShaderNode::Uniform::HINT_COLOR;
+ uniform2.hint = ShaderNode::Uniform::HINT_COLOR;
} else if (tk.type == TK_HINT_RANGE) {
- uniform.hint = ShaderNode::Uniform::HINT_RANGE;
+ uniform2.hint = ShaderNode::Uniform::HINT_RANGE;
if (type != TYPE_FLOAT && type != TYPE_INT) {
_set_error("Range hint is for float and int only");
return ERR_PARSE_ERROR;
@@ -4078,8 +4789,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- uniform.hint_range[0] = tk.constant;
- uniform.hint_range[0] *= sign;
+ uniform2.hint_range[0] = tk.constant;
+ uniform2.hint_range[0] *= sign;
tk = _get_token();
@@ -4102,8 +4813,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- uniform.hint_range[1] = tk.constant;
- uniform.hint_range[1] *= sign;
+ uniform2.hint_range[1] = tk.constant;
+ uniform2.hint_range[1] *= sign;
tk = _get_token();
@@ -4115,13 +4826,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- uniform.hint_range[2] = tk.constant;
+ uniform2.hint_range[2] = tk.constant;
tk = _get_token();
} else {
if (type == TYPE_INT) {
- uniform.hint_range[2] = 1;
+ uniform2.hint_range[2] = 1;
} else {
- uniform.hint_range[2] = 0.001;
+ uniform2.hint_range[2] = 0.001;
}
}
@@ -4134,7 +4845,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error("Expected valid type hint after ':'.");
}
- if (uniform.hint != ShaderNode::Uniform::HINT_RANGE && uniform.hint != ShaderNode::Uniform::HINT_NONE && uniform.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) {
+ if (uniform2.hint != ShaderNode::Uniform::HINT_RANGE && uniform2.hint != ShaderNode::Uniform::HINT_NONE && uniform2.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) {
_set_error("This hint is only for sampler types");
return ERR_PARSE_ERROR;
}
@@ -4154,16 +4865,16 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
ConstantNode *cn = static_cast<ConstantNode *>(expr);
- uniform.default_value.resize(cn->values.size());
+ uniform2.default_value.resize(cn->values.size());
- if (!convert_constant(cn, uniform.type, uniform.default_value.ptrw())) {
- _set_error("Can't convert constant to " + get_datatype_name(uniform.type));
+ if (!convert_constant(cn, uniform2.type, uniform2.default_value.ptrw())) {
+ _set_error("Can't convert constant to " + get_datatype_name(uniform2.type));
return ERR_PARSE_ERROR;
}
tk = _get_token();
}
- shader->uniforms[name] = uniform;
+ shader->uniforms[name] = uniform2;
if (tk.type != TK_SEMICOLON) {
_set_error("Expected ';'");
@@ -4173,37 +4884,79 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
ShaderNode::Varying varying;
varying.type = type;
- varying.precission = precision;
+ varying.precision = precision;
varying.interpolation = interpolation;
- shader->varyings[name] = varying;
tk = _get_token();
- if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ';'");
+ if (tk.type != TK_SEMICOLON && tk.type != TK_BRACKET_OPEN) {
+ _set_error("Expected ';' or '['");
return ERR_PARSE_ERROR;
}
+
+ if (tk.type == TK_BRACKET_OPEN) {
+ tk = _get_token();
+ if (tk.type == TK_INT_CONSTANT && tk.constant > 0) {
+ varying.array_size = (int)tk.constant;
+
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_CLOSE) {
+ tk = _get_token();
+ if (tk.type != TK_SEMICOLON) {
+ _set_error("Expected ';'");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+ }
+
+ shader->varyings[name] = varying;
}
} break;
default: {
- //function
+ //function or constant variable
+ bool is_constant = false;
DataPrecision precision = PRECISION_DEFAULT;
DataType type;
StringName name;
+ if (tk.type == TK_CONST) {
+ is_constant = true;
+ tk = _get_token();
+ }
+
if (is_token_precision(tk.type)) {
precision = get_token_precision(tk.type);
tk = _get_token();
}
if (!is_token_datatype(tk.type)) {
- _set_error("Expected function, uniform or varying ");
+ _set_error("Expected constant, function, uniform or varying ");
+ return ERR_PARSE_ERROR;
+ }
+
+ if (!is_token_variable_datatype(tk.type)) {
+ _set_error("Invalid data type for constants or function return (samplers not allowed)");
return ERR_PARSE_ERROR;
}
type = get_token_datatype(tk.type);
+ TkPos prev_pos = _get_tkpos();
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_OPEN) {
+ _set_error("Cannot use arrays as return types");
+ return ERR_PARSE_ERROR;
+ }
+ _set_tkpos(prev_pos);
+
_get_completable_identifier(NULL, COMPLETION_MAIN_FUNCTION, name);
if (name == StringName()) {
@@ -4218,8 +4971,73 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type != TK_PARENTHESIS_OPEN) {
- _set_error("Expected '(' after identifier");
- return ERR_PARSE_ERROR;
+ if (type == TYPE_VOID) {
+ _set_error("Expected '(' after function identifier");
+ return ERR_PARSE_ERROR;
+ }
+
+ //variable
+
+ while (true) {
+ ShaderNode::Constant constant;
+ constant.type = type;
+ constant.precision = precision;
+ constant.initializer = NULL;
+
+ if (tk.type == TK_OP_ASSIGN) {
+
+ if (!is_constant) {
+ _set_error("Expected 'const' keyword before constant definition");
+ return ERR_PARSE_ERROR;
+ }
+
+ //variable created with assignment! must parse an expression
+ Node *expr = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>());
+ if (!expr)
+ return ERR_PARSE_ERROR;
+
+ if (expr->type != Node::TYPE_CONSTANT) {
+ _set_error("Expected constant expression after '='");
+ return ERR_PARSE_ERROR;
+ }
+
+ constant.initializer = static_cast<ConstantNode *>(expr);
+
+ if (type != expr->get_datatype()) {
+ _set_error("Invalid assignment of '" + get_datatype_name(expr->get_datatype()) + "' to '" + get_datatype_name(type) + "'");
+ return ERR_PARSE_ERROR;
+ }
+ tk = _get_token();
+ } else {
+ _set_error("Expected initialization of constant");
+ return ERR_PARSE_ERROR;
+ }
+
+ shader->constants[name] = constant;
+ if (tk.type == TK_COMMA) {
+ tk = _get_token();
+ if (tk.type != TK_IDENTIFIER) {
+ _set_error("Expected identifier after type");
+ return ERR_PARSE_ERROR;
+ }
+
+ name = tk.text;
+ if (_find_identifier(NULL, Map<StringName, BuiltInInfo>(), name)) {
+ _set_error("Redefinition of '" + String(name) + "'");
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = _get_token();
+
+ } else if (tk.type == TK_SEMICOLON) {
+ break;
+ } else {
+ _set_error("Expected ',' or ';' after constant");
+ return ERR_PARSE_ERROR;
+ }
+ }
+
+ break;
}
Map<StringName, BuiltInInfo> builtin_types;
@@ -4292,6 +5110,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
+ if (tk.type == TK_BRACKET_OPEN) {
+ _set_error("Arrays as parameters are not implemented yet");
+ return ERR_PARSE_ERROR;
+ }
if (tk.type != TK_IDENTIFIER) {
_set_error("Expected identifier for argument name");
return ERR_PARSE_ERROR;
@@ -4312,6 +5134,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
func_node->arguments.push_back(arg);
tk = _get_token();
+ if (tk.type == TK_BRACKET_OPEN) {
+ _set_error("Arrays as parameters are not implemented yet");
+ return ERR_PARSE_ERROR;
+ }
if (tk.type == TK_COMMA) {
tk = _get_token();
@@ -4347,6 +5173,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (err)
return err;
+ if (func_node->return_type != DataType::TYPE_VOID) {
+
+ BlockNode *block = func_node->body;
+ if (_find_last_flow_op_in_block(block, FlowOperation::FLOW_OP_RETURN) != OK) {
+ _set_error("Expected at least one return statement in a non-void function.");
+ return ERR_PARSE_ERROR;
+ }
+ }
current_function = StringName();
}
}
@@ -4357,6 +5191,57 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return OK;
}
+Error ShaderLanguage::_find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op) {
+
+ bool found = false;
+
+ for (int i = p_flow->blocks.size() - 1; i >= 0; i--) {
+ if (p_flow->blocks[i]->type == Node::TYPE_BLOCK) {
+ BlockNode *last_block = (BlockNode *)p_flow->blocks[i];
+ if (_find_last_flow_op_in_block(last_block, p_op) == OK) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found) {
+ return OK;
+ }
+ return FAILED;
+}
+
+Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op) {
+
+ bool found = false;
+
+ for (int i = p_block->statements.size() - 1; i >= 0; i--) {
+
+ if (p_block->statements[i]->type == Node::TYPE_CONTROL_FLOW) {
+ ControlFlowNode *flow = (ControlFlowNode *)p_block->statements[i];
+ if (flow->flow_op == p_op) {
+ found = true;
+ break;
+ } else {
+ if (_find_last_flow_op_in_op(flow, p_op) == OK) {
+ found = true;
+ break;
+ }
+ }
+ } else if (p_block->statements[i]->type == Node::TYPE_BLOCK) {
+ BlockNode *block = (BlockNode *)p_block->statements[i];
+ if (_find_last_flow_op_in_block(block, p_op) == OK) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (found) {
+ return OK;
+ }
+ return FAILED;
+}
+
// skips over whitespace and /* */ and // comments
static int _get_first_ident_pos(const String &p_code) {
@@ -4454,7 +5339,7 @@ Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Functi
return OK;
}
-Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, List<String> *r_options, String &r_call_hint) {
+Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint) {
clear();
@@ -4463,9 +5348,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
nodes = NULL;
shader = alloc_node<ShaderNode>();
- Error err = _parse_shader(p_functions, p_render_modes, p_shader_types);
- if (err != OK)
- ERR_PRINT("Failed to parse shader");
+ _parse_shader(p_functions, p_render_modes, p_shader_types);
switch (completion_type) {
@@ -4475,8 +5358,8 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
} break;
case COMPLETION_RENDER_MODE: {
for (int i = 0; i < p_render_modes.size(); i++) {
-
- r_options->push_back(p_render_modes[i]);
+ ScriptCodeCompletionOption option(p_render_modes[i], ScriptCodeCompletionOption::KIND_ENUM);
+ r_options->push_back(option);
}
return OK;
@@ -4484,8 +5367,8 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
case COMPLETION_MAIN_FUNCTION: {
for (const Map<StringName, FunctionInfo>::Element *E = p_functions.front(); E; E = E->next()) {
-
- r_options->push_back(E->key());
+ ScriptCodeCompletionOption option(E->key(), ScriptCodeCompletionOption::KIND_FUNCTION);
+ r_options->push_back(option);
}
return OK;
@@ -4494,70 +5377,86 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
case COMPLETION_FUNCTION_CALL: {
bool comp_ident = completion_type == COMPLETION_IDENTIFIER;
- Set<String> matches;
-
+ Map<String, ScriptCodeCompletionOption::Kind> matches;
StringName skip_function;
-
BlockNode *block = completion_block;
- while (block) {
-
- if (comp_ident) {
- for (const Map<StringName, BlockNode::Variable>::Element *E = block->variables.front(); E; E = E->next()) {
+ if (completion_class == TAG_GLOBAL) {
+ while (block) {
+ if (comp_ident) {
+ for (const Map<StringName, BlockNode::Variable>::Element *E = block->variables.front(); E; E = E->next()) {
- if (E->get().line < completion_line) {
- matches.insert(E->key());
+ if (E->get().line < completion_line) {
+ matches.insert(E->key(), ScriptCodeCompletionOption::KIND_VARIABLE);
+ }
}
}
- }
- if (block->parent_function) {
- if (comp_ident) {
- for (int i = 0; i < block->parent_function->arguments.size(); i++) {
- matches.insert(block->parent_function->arguments[i].name);
+ if (block->parent_function) {
+ if (comp_ident) {
+ for (int i = 0; i < block->parent_function->arguments.size(); i++) {
+ matches.insert(block->parent_function->arguments[i].name, ScriptCodeCompletionOption::KIND_FUNCTION);
+ }
}
+ skip_function = block->parent_function->name;
}
- skip_function = block->parent_function->name;
+ block = block->parent_block;
}
- block = block->parent_block;
- }
- if (comp_ident && skip_function != StringName() && p_functions.has(skip_function)) {
+ if (comp_ident && skip_function != StringName() && p_functions.has(skip_function)) {
- for (Map<StringName, BuiltInInfo>::Element *E = p_functions[skip_function].built_ins.front(); E; E = E->next()) {
- matches.insert(E->key());
+ for (Map<StringName, BuiltInInfo>::Element *E = p_functions[skip_function].built_ins.front(); E; E = E->next()) {
+ ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
+ if (E->get().constant) {
+ kind = ScriptCodeCompletionOption::KIND_CONSTANT;
+ }
+ matches.insert(E->key(), kind);
+ }
}
- }
- if (comp_ident) {
- for (const Map<StringName, ShaderNode::Varying>::Element *E = shader->varyings.front(); E; E = E->next()) {
- matches.insert(E->key());
+ if (comp_ident) {
+ for (const Map<StringName, ShaderNode::Varying>::Element *E = shader->varyings.front(); E; E = E->next()) {
+ matches.insert(E->key(), ScriptCodeCompletionOption::KIND_VARIABLE);
+ }
+ for (const Map<StringName, ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) {
+ matches.insert(E->key(), ScriptCodeCompletionOption::KIND_MEMBER);
+ }
}
- for (const Map<StringName, ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) {
- matches.insert(E->key());
+
+ for (int i = 0; i < shader->functions.size(); i++) {
+ if (!shader->functions[i].callable || shader->functions[i].name == skip_function)
+ continue;
+ matches.insert(String(shader->functions[i].name), ScriptCodeCompletionOption::KIND_FUNCTION);
}
- }
- for (int i = 0; i < shader->functions.size(); i++) {
- if (!shader->functions[i].callable || shader->functions[i].name == skip_function)
- continue;
- matches.insert(String(shader->functions[i].name) + "(");
- }
+ int idx = 0;
- int idx = 0;
+ while (builtin_func_defs[idx].name) {
- while (builtin_func_defs[idx].name) {
+ matches.insert(String(builtin_func_defs[idx].name), ScriptCodeCompletionOption::KIND_FUNCTION);
+ idx++;
+ }
- matches.insert(String(builtin_func_defs[idx].name) + "(");
- idx++;
+ } else { // sub-class
+ int idx = 0;
+
+ while (builtin_func_defs[idx].name) {
+ if (builtin_func_defs[idx].tag == completion_class) {
+ matches.insert(String(builtin_func_defs[idx].name), ScriptCodeCompletionOption::KIND_FUNCTION);
+ }
+ idx++;
+ }
}
- for (Set<String>::Element *E = matches.front(); E; E = E->next()) {
- r_options->push_back(E->get());
+ for (Map<String, ScriptCodeCompletionOption::Kind>::Element *E = matches.front(); E; E = E->next()) {
+ ScriptCodeCompletionOption option(E->key(), E->value());
+ if (E->value() == ScriptCodeCompletionOption::KIND_FUNCTION) {
+ option.insert_text += "(";
+ }
+ r_options->push_back(option);
}
return OK;
-
} break;
case COMPLETION_CALL_ARGUMENTS: {
@@ -4610,6 +5509,11 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
if (completion_function == builtin_func_defs[idx].name) {
+ if (builtin_func_defs[idx].tag != completion_class) {
+ idx++;
+ continue;
+ }
+
if (calltip.length())
calltip += "\n";
@@ -4688,12 +5592,13 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
case TYPE_MAT2: limit = 2; break;
case TYPE_MAT3: limit = 3; break;
case TYPE_MAT4: limit = 4; break;
- default: {}
+ default: {
+ }
}
for (int i = 0; i < limit; i++) {
- r_options->push_back(String::chr(colv[i]));
- r_options->push_back(String::chr(coordv[i]));
+ r_options->push_back(ScriptCodeCompletionOption(String::chr(colv[i]), ScriptCodeCompletionOption::KIND_PLAIN_TEXT));
+ r_options->push_back(ScriptCodeCompletionOption(String::chr(coordv[i]), ScriptCodeCompletionOption::KIND_PLAIN_TEXT));
}
} break;
@@ -4720,6 +5625,7 @@ ShaderLanguage::ShaderNode *ShaderLanguage::get_shader() {
ShaderLanguage::ShaderLanguage() {
nodes = NULL;
+ completion_class = TAG_GLOBAL;
}
ShaderLanguage::~ShaderLanguage() {
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index 08c4d06992..3a5630ef42 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,7 +33,8 @@
#include "core/list.h"
#include "core/map.h"
-#include "core/string_db.h"
+#include "core/script_language.h"
+#include "core/string_name.h"
#include "core/typedefs.h"
#include "core/ustring.h"
#include "core/variant.h"
@@ -42,7 +43,6 @@ class ShaderLanguage {
public:
enum TokenType {
-
TK_EMPTY,
TK_IDENTIFIER,
TK_TRUE,
@@ -80,8 +80,8 @@ public:
TK_TYPE_USAMPLER3D,
TK_TYPE_SAMPLERCUBE,
TK_INTERPOLATION_FLAT,
- TK_INTERPOLATION_NO_PERSPECTIVE,
TK_INTERPOLATION_SMOOTH,
+ TK_CONST,
TK_PRECISION_LOW,
TK_PRECISION_MID,
TK_PRECISION_HIGH,
@@ -125,6 +125,7 @@ public:
TK_CF_DO,
TK_CF_SWITCH,
TK_CF_CASE,
+ TK_CF_DEFAULT,
TK_CF_BREAK,
TK_CF_CONTINUE,
TK_CF_RETURN,
@@ -210,7 +211,6 @@ public:
enum DataInterpolation {
INTERPOLATION_FLAT,
- INTERPOLATION_NO_PERSPECTIVE,
INTERPOLATION_SMOOTH,
};
@@ -267,20 +267,19 @@ public:
FLOW_OP_DO,
FLOW_OP_BREAK,
FLOW_OP_SWITCH,
+ FLOW_OP_CASE,
+ FLOW_OP_DEFAULT,
FLOW_OP_CONTINUE,
FLOW_OP_DISCARD
-
};
enum ArgumentQualifier {
ARGUMENT_QUALIFIER_IN,
ARGUMENT_QUALIFIER_OUT,
ARGUMENT_QUALIFIER_INOUT,
-
};
struct Node {
-
Node *next;
enum Type {
@@ -292,13 +291,17 @@ public:
TYPE_CONSTANT,
TYPE_OPERATOR,
TYPE_CONTROL_FLOW,
- TYPE_MEMBER
+ TYPE_MEMBER,
+ TYPE_ARRAY,
+ TYPE_ARRAY_DECLARATION,
};
Type type;
virtual DataType get_datatype() const { return TYPE_VOID; }
-
+ Node(Type t) :
+ next(NULL),
+ type(t) {}
virtual ~Node() {}
};
@@ -313,38 +316,37 @@ public:
Node *nodes;
struct OperatorNode : public Node {
-
DataType return_cache;
DataPrecision return_precision_cache;
Operator op;
Vector<Node *> arguments;
virtual DataType get_datatype() const { return return_cache; }
- OperatorNode() {
- type = TYPE_OPERATOR;
- return_cache = TYPE_VOID;
- return_precision_cache = PRECISION_DEFAULT;
- }
+ OperatorNode() :
+ Node(TYPE_OPERATOR),
+ return_cache(TYPE_VOID),
+ return_precision_cache(PRECISION_DEFAULT),
+ op(OP_EQUAL) {}
};
struct VariableNode : public Node {
DataType datatype_cache;
StringName name;
virtual DataType get_datatype() const { return datatype_cache; }
+ bool is_const;
- VariableNode() {
- type = TYPE_VARIABLE;
- datatype_cache = TYPE_VOID;
- }
+ VariableNode() :
+ Node(TYPE_VARIABLE),
+ datatype_cache(TYPE_VOID),
+ is_const(false) {}
};
struct VariableDeclarationNode : public Node {
-
DataPrecision precision;
DataType datatype;
+ bool is_const;
struct Declaration {
-
StringName name;
Node *initializer;
};
@@ -352,13 +354,52 @@ public:
Vector<Declaration> declarations;
virtual DataType get_datatype() const { return datatype; }
- VariableDeclarationNode() {
- type = TYPE_VARIABLE_DECLARATION;
- }
+ VariableDeclarationNode() :
+ Node(TYPE_VARIABLE_DECLARATION),
+ precision(PRECISION_DEFAULT),
+ datatype(TYPE_VOID),
+ is_const(false) {}
};
- struct ConstantNode : public Node {
+ struct ArrayNode : public Node {
+ DataType datatype_cache;
+ StringName name;
+ Node *index_expression;
+ Node *call_expression;
+ bool is_const;
+
+ virtual DataType get_datatype() const { return datatype_cache; }
+
+ ArrayNode() :
+ Node(TYPE_ARRAY),
+ datatype_cache(TYPE_VOID),
+ index_expression(NULL),
+ call_expression(NULL),
+ is_const(false) {}
+ };
+
+ struct ArrayDeclarationNode : public Node {
+ DataPrecision precision;
+ DataType datatype;
+ bool is_const;
+
+ struct Declaration {
+ StringName name;
+ uint32_t size;
+ Vector<Node *> initializer;
+ };
+ Vector<Declaration> declarations;
+ virtual DataType get_datatype() const { return datatype; }
+
+ ArrayDeclarationNode() :
+ Node(TYPE_ARRAY_DECLARATION),
+ precision(PRECISION_DEFAULT),
+ datatype(TYPE_VOID),
+ is_const(false) {}
+ };
+
+ struct ConstantNode : public Node {
DataType datatype;
union Value {
@@ -371,7 +412,9 @@ public:
Vector<Value> values;
virtual DataType get_datatype() const { return datatype; }
- ConstantNode() { type = TYPE_CONSTANT; }
+ ConstantNode() :
+ Node(TYPE_CONSTANT),
+ datatype(TYPE_VOID) {}
};
struct FunctionNode;
@@ -380,48 +423,62 @@ public:
FunctionNode *parent_function;
BlockNode *parent_block;
+ enum BlockType {
+ BLOCK_TYPE_STANDART,
+ BLOCK_TYPE_SWITCH,
+ BLOCK_TYPE_CASE,
+ BLOCK_TYPE_DEFAULT,
+ };
+
+ int block_type;
+
struct Variable {
DataType type;
DataPrecision precision;
int line; //for completion
+ int array_size;
+ bool is_const;
};
Map<StringName, Variable> variables;
List<Node *> statements;
bool single_statement;
- BlockNode() {
- type = TYPE_BLOCK;
- parent_block = NULL;
- parent_function = NULL;
- single_statement = false;
- }
+
+ BlockNode() :
+ Node(TYPE_BLOCK),
+ parent_function(NULL),
+ parent_block(NULL),
+ block_type(BLOCK_TYPE_STANDART),
+ single_statement(false) {}
};
struct ControlFlowNode : public Node {
-
FlowOperation flow_op;
Vector<Node *> expressions;
Vector<BlockNode *> blocks;
- ControlFlowNode() {
- type = TYPE_CONTROL_FLOW;
- flow_op = FLOW_OP_IF;
- }
+
+ ControlFlowNode() :
+ Node(TYPE_CONTROL_FLOW),
+ flow_op(FLOW_OP_IF) {}
};
struct MemberNode : public Node {
-
DataType basetype;
DataType datatype;
StringName name;
Node *owner;
+
virtual DataType get_datatype() const { return datatype; }
- MemberNode() { type = TYPE_MEMBER; }
+
+ MemberNode() :
+ Node(TYPE_MEMBER),
+ basetype(TYPE_VOID),
+ datatype(TYPE_VOID),
+ owner(NULL) {}
};
struct FunctionNode : public Node {
-
struct Argument {
-
ArgumentQualifier qualifier;
StringName name;
DataType type;
@@ -435,16 +492,22 @@ public:
BlockNode *body;
bool can_discard;
- FunctionNode() {
- type = TYPE_FUNCTION;
- return_type = TYPE_VOID;
- return_precision = PRECISION_DEFAULT;
- can_discard = false;
- }
+ FunctionNode() :
+ Node(TYPE_FUNCTION),
+ return_type(TYPE_VOID),
+ return_precision(PRECISION_DEFAULT),
+ body(NULL),
+ can_discard(false) {}
};
struct ShaderNode : public Node {
+ struct Constant {
+ DataType type;
+ DataPrecision precision;
+ ConstantNode *initializer;
+ };
+
struct Function {
StringName name;
FunctionNode *function;
@@ -455,7 +518,14 @@ public:
struct Varying {
DataType type;
DataInterpolation interpolation;
- DataPrecision precission;
+ DataPrecision precision;
+ int array_size;
+
+ Varying() :
+ type(TYPE_VOID),
+ interpolation(INTERPOLATION_FLAT),
+ precision(PRECISION_DEFAULT),
+ array_size(0) {}
};
struct Uniform {
@@ -475,30 +545,35 @@ public:
int order;
int texture_order;
DataType type;
- DataPrecision precission;
+ DataPrecision precision;
Vector<ConstantNode::Value> default_value;
Hint hint;
float hint_range[3];
- Uniform() {
- hint = HINT_NONE;
- hint_range[0] = 0;
- hint_range[1] = 1;
- hint_range[2] = 0.001;
+ Uniform() :
+ order(0),
+ texture_order(0),
+ type(TYPE_VOID),
+ precision(PRECISION_DEFAULT),
+ hint(HINT_NONE) {
+ hint_range[0] = 0.0f;
+ hint_range[1] = 1.0f;
+ hint_range[2] = 0.001f;
}
};
+ Map<StringName, Constant> constants;
Map<StringName, Varying> varyings;
Map<StringName, Uniform> uniforms;
Vector<StringName> render_modes;
Vector<Function> functions;
- ShaderNode() { type = TYPE_SHADER; }
+ ShaderNode() :
+ Node(TYPE_SHADER) {}
};
struct Expression {
-
bool is_op;
union {
Operator op;
@@ -507,7 +582,6 @@ public:
};
struct VarInfo {
-
StringName name;
DataType type;
};
@@ -523,7 +597,6 @@ public:
};
struct Token {
-
TokenType type;
StringName text;
double constant;
@@ -534,11 +607,13 @@ public:
static String get_token_text(Token p_token);
static bool is_token_datatype(TokenType p_type);
+ static bool is_token_variable_datatype(TokenType p_type);
static DataType get_token_datatype(TokenType p_type);
static bool is_token_interpolation(TokenType p_type);
static DataInterpolation get_token_interpolation(TokenType p_type);
static bool is_token_precision(TokenType p_type);
static DataPrecision get_token_precision(TokenType p_type);
+ static String get_precision_name(DataPrecision p_type);
static String get_datatype_name(DataType p_type);
static bool is_token_nonvoid_datatype(TokenType p_type);
static bool is_token_operator(TokenType p_type);
@@ -548,7 +623,7 @@ public:
static int get_cardinality(DataType p_type);
static bool is_scalar_type(DataType p_type);
static bool is_sampler_type(DataType p_type);
- static Variant constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type);
+ static Variant constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint = ShaderLanguage::ShaderNode::Uniform::HINT_NONE);
static void get_keyword_list(List<String> *r_keywords);
static void get_builtin_funcs(List<String> *r_keywords);
@@ -556,11 +631,14 @@ public:
struct BuiltInInfo {
DataType type;
bool constant;
- BuiltInInfo() {}
- BuiltInInfo(DataType p_type, bool p_constant = false) {
- type = p_type;
- constant = p_constant;
- }
+
+ BuiltInInfo() :
+ type(TYPE_VOID),
+ constant(false) {}
+
+ BuiltInInfo(DataType p_type, bool p_constant = false) :
+ type(p_type),
+ constant(p_constant) {}
};
struct FunctionInfo {
@@ -573,6 +651,7 @@ private:
TokenType token;
const char *text;
};
+
static const KeyWord keyword_list[];
bool error_set;
@@ -625,46 +704,57 @@ private:
IDENTIFIER_FUNCTION_ARGUMENT,
IDENTIFIER_LOCAL_VAR,
IDENTIFIER_BUILTIN_VAR,
+ IDENTIFIER_CONSTANT,
};
- bool _find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL);
-
+ bool _find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL, bool *r_is_const = NULL, int *r_array_size = NULL);
bool _is_operator_assign(Operator p_op) const;
bool _validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message = NULL);
-
bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = NULL);
- struct BuiltinFuncDef {
+ enum SubClassTag {
+ TAG_GLOBAL,
+ TAG_ARRAY
+ };
+ struct BuiltinFuncDef {
enum { MAX_ARGS = 5 };
const char *name;
DataType rettype;
const DataType args[MAX_ARGS];
+ SubClassTag tag;
+ };
+
+ struct BuiltinFuncOutArgs { //arguments used as out in built in functions
+ const char *name;
+ int argument;
};
CompletionType completion_type;
int completion_line;
BlockNode *completion_block;
DataType completion_base;
+ SubClassTag completion_class;
StringName completion_function;
int completion_argument;
bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
-
static const BuiltinFuncDef builtin_func_defs[];
- bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type);
+ static const BuiltinFuncOutArgs builtin_func_out_args[];
+ bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type);
bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL);
Node *_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
-
ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node);
- Node *_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
+ Node *_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
Error _parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false);
-
Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types);
+ Error _find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op);
+ Error _find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op);
+
public:
//static void get_keyword_list(ShaderType p_type,List<String> *p_keywords);
@@ -672,7 +762,7 @@ public:
static String get_shader_type(const String &p_code);
Error compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types);
- Error complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, List<String> *r_options, String &r_call_hint);
+ Error complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint);
String get_error_text();
int get_error_line();
diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp
index 57e8d86468..019f477362 100644
--- a/servers/visual/shader_types.cpp
+++ b/servers/visual/shader_types.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -60,6 +60,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["TANGENT"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["BINORMAL"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["POSITION"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["UV2"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
@@ -75,7 +76,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
@@ -86,6 +87,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TANGENT"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["BINORMAL"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2);
@@ -109,6 +111,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_SCISSOR"] = ShaderLanguage::TYPE_FLOAT;
@@ -117,6 +120,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
@@ -125,6 +129,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
@@ -132,6 +137,8 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["NORMAL"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["UV2"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["VIEW"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
@@ -142,6 +149,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["DIFFUSE_LIGHT"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["SPECULAR_LIGHT"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["light"].can_discard = true;
@@ -182,6 +190,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].modes.push_back("shadows_disabled");
shader_modes[VS::SHADER_SPATIAL].modes.push_back("ambient_light_disabled");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("shadow_to_opacity");
shader_modes[VS::SHADER_SPATIAL].modes.push_back("vertex_lighting");
@@ -198,6 +207,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].can_discard = false;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
@@ -225,9 +235,10 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_VEC"] = ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SHADOW_VEC"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_HEIGHT"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_COLOR"] = ShaderLanguage::TYPE_VEC4;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_UV"] = ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SHADOW_COLOR"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
diff --git a/servers/visual/shader_types.h b/servers/visual/shader_types.h
index e195b6ea20..149c9b5e1f 100644
--- a/servers/visual/shader_types.h
+++ b/servers/visual/shader_types.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
index 16cda0326d..f5a1276c27 100644
--- a/servers/visual/visual_server_canvas.cpp
+++ b/servers/visual/visual_server_canvas.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,15 +29,13 @@
/*************************************************************************/
#include "visual_server_canvas.h"
-#include "visual_server_global.h"
+#include "visual_server_globals.h"
#include "visual_server_raster.h"
#include "visual_server_viewport.h"
-void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights) {
+static const int z_range = VS::CANVAS_ITEM_Z_MAX - VS::CANVAS_ITEM_Z_MIN + 1;
- static const int z_range = VS::CANVAS_ITEM_Z_MAX - VS::CANVAS_ITEM_Z_MIN + 1;
- RasterizerCanvas::Item *z_list[z_range];
- RasterizerCanvas::Item *z_last_list[z_range];
+void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights) {
memset(z_list, 0, z_range * sizeof(RasterizerCanvas::Item *));
memset(z_last_list, 0, z_range * sizeof(RasterizerCanvas::Item *));
@@ -51,6 +49,38 @@ void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Tra
}
}
+void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item *p_material_owner, const Color p_modulate, VisualServerCanvas::Item **r_items, int &r_index) {
+ int child_item_count = p_canvas_item->child_items.size();
+ VisualServerCanvas::Item **child_items = p_canvas_item->child_items.ptrw();
+ for (int i = 0; i < child_item_count; i++) {
+ if (child_items[i]->visible) {
+ if (r_items) {
+ r_items[r_index] = child_items[i];
+ child_items[i]->ysort_modulate = p_modulate;
+ child_items[i]->ysort_xform = p_transform;
+ child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]);
+ child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : NULL;
+ }
+
+ r_index++;
+
+ if (child_items[i]->sort_y)
+ _collect_ysort_children(child_items[i],
+ p_transform * child_items[i]->xform,
+ child_items[i]->use_parent_material ? p_material_owner : child_items[i],
+ p_modulate * child_items[i]->modulate,
+ r_items, r_index);
+ }
+ }
+}
+
+void _mark_ysort_dirty(VisualServerCanvas::Item *ysort_owner, RID_Owner<VisualServerCanvas::Item> &canvas_item_owner) {
+ while (ysort_owner && ysort_owner->sort_y) {
+ ysort_owner->ysort_children_count = -1;
+ ysort_owner = canvas_item_owner.owns(ysort_owner->parent) ? canvas_item_owner.getornull(ysort_owner->parent) : NULL;
+ }
+}
+
void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner) {
Item *ci = p_canvas_item;
@@ -58,10 +88,10 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
if (!ci->visible)
return;
- if (p_canvas_item->children_order_dirty) {
+ if (ci->children_order_dirty) {
- p_canvas_item->child_items.sort_custom<ItemIndexSort>();
- p_canvas_item->children_order_dirty = false;
+ ci->child_items.sort_custom<ItemIndexSort>();
+ ci->children_order_dirty = false;
}
Rect2 rect = ci->get_rect();
@@ -82,8 +112,7 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
return;
int child_item_count = ci->child_items.size();
- Item **child_items = (Item **)alloca(child_item_count * sizeof(Item *));
- copymem(child_items, ci->child_items.ptr(), child_item_count * sizeof(Item *));
+ Item **child_items = ci->child_items.ptrw();
if (ci->clip) {
if (p_canvas_clip != NULL) {
@@ -99,6 +128,17 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
if (ci->sort_y) {
+ if (ci->ysort_children_count == -1) {
+ ci->ysort_children_count = 0;
+ _collect_ysort_children(ci, Transform2D(), p_material_owner, Color(1, 1, 1, 1), NULL, ci->ysort_children_count);
+ }
+
+ child_item_count = ci->ysort_children_count;
+ child_items = (Item **)alloca(child_item_count * sizeof(Item *));
+
+ int i = 0;
+ _collect_ysort_children(ci, Transform2D(), p_material_owner, Color(1, 1, 1, 1), child_items, i);
+
SortArray<Item *, ItemPtrSort> sorter;
sorter.sort(child_items, child_item_count);
}
@@ -110,9 +150,13 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
for (int i = 0; i < child_item_count; i++) {
- if (!child_items[i]->behind)
+ if (!child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y))
continue;
- _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
+ if (ci->sort_y) {
+ _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate * child_items[i]->ysort_modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner);
+ } else {
+ _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
+ }
}
if (ci->copy_back_buffer) {
@@ -148,9 +192,13 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
for (int i = 0; i < child_item_count; i++) {
- if (child_items[i]->behind)
+ if (child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y))
continue;
- _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
+ if (ci->sort_y) {
+ _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate * child_items[i]->ysort_modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner);
+ } else {
+ _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
+ }
}
}
@@ -225,24 +273,24 @@ void VisualServerCanvas::render_canvas(Canvas *p_canvas, const Transform2D &p_tr
for (int i = 0; i < l; i++) {
- const Canvas::ChildItem &ci = p_canvas->child_items[i];
- _render_canvas_item_tree(ci.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights);
+ const Canvas::ChildItem &ci2 = p_canvas->child_items[i];
+ _render_canvas_item_tree(ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights);
//mirroring (useful for scrolling backgrounds)
- if (ci.mirror.x != 0) {
+ if (ci2.mirror.x != 0) {
- Transform2D xform2 = p_transform * Transform2D(0, Vector2(ci.mirror.x, 0));
- _render_canvas_item_tree(ci.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
+ Transform2D xform2 = p_transform * Transform2D(0, Vector2(ci2.mirror.x, 0));
+ _render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
}
- if (ci.mirror.y != 0) {
+ if (ci2.mirror.y != 0) {
- Transform2D xform2 = p_transform * Transform2D(0, Vector2(0, ci.mirror.y));
- _render_canvas_item_tree(ci.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
+ Transform2D xform2 = p_transform * Transform2D(0, Vector2(0, ci2.mirror.y));
+ _render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
}
- if (ci.mirror.y != 0 && ci.mirror.x != 0) {
+ if (ci2.mirror.y != 0 && ci2.mirror.x != 0) {
- Transform2D xform2 = p_transform * Transform2D(0, ci.mirror);
- _render_canvas_item_tree(ci.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
+ Transform2D xform2 = p_transform * Transform2D(0, ci2.mirror);
+ _render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
}
}
}
@@ -277,6 +325,19 @@ void VisualServerCanvas::canvas_set_modulate(RID p_canvas, const Color &p_color)
canvas->modulate = p_color;
}
+void VisualServerCanvas::canvas_set_disable_scale(bool p_disable) {
+ disable_scale = p_disable;
+}
+
+void VisualServerCanvas::canvas_set_parent(RID p_canvas, RID p_parent, float p_scale) {
+
+ Canvas *canvas = canvas_owner.get(p_canvas);
+ ERR_FAIL_COND(!canvas);
+
+ canvas->parent = p_parent;
+ canvas->parent_scale = p_scale;
+}
+
RID VisualServerCanvas::canvas_item_create() {
Item *canvas_item = memnew(Item);
@@ -300,6 +361,8 @@ void VisualServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) {
Item *item_owner = canvas_item_owner.get(canvas_item->parent);
item_owner->child_items.erase(canvas_item);
+
+ _mark_ysort_dirty(item_owner, canvas_item_owner);
}
canvas_item->parent = RID();
@@ -319,10 +382,11 @@ void VisualServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) {
item_owner->child_items.push_back(canvas_item);
item_owner->children_order_dirty = true;
+ _mark_ysort_dirty(item_owner, canvas_item_owner);
+
} else {
- ERR_EXPLAIN("Invalid parent");
- ERR_FAIL();
+ ERR_FAIL_MSG("Invalid parent.");
}
}
@@ -334,6 +398,10 @@ void VisualServerCanvas::canvas_item_set_visible(RID p_item, bool p_visible) {
ERR_FAIL_COND(!canvas_item);
canvas_item->visible = p_visible;
+
+ if (canvas_item->parent.is_valid() && canvas_item_owner.owns(canvas_item->parent)) {
+ _mark_ysort_dirty(canvas_item_owner.get(canvas_item->parent), canvas_item_owner);
+ }
}
void VisualServerCanvas::canvas_item_set_light_mask(RID p_item, int p_mask) {
@@ -570,7 +638,7 @@ void VisualServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2 &p
if (p_tile) {
rect->flags |= RasterizerCanvas::CANVAS_RECT_TILE;
rect->flags |= RasterizerCanvas::CANVAS_RECT_REGION;
- rect->source = Rect2(0, 0, p_rect.size.width, p_rect.size.height);
+ rect->source = Rect2(0, 0, fabsf(p_rect.size.width), fabsf(p_rect.size.height));
}
if (p_rect.size.x < 0) {
@@ -685,12 +753,7 @@ void VisualServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Point2
ERR_FAIL_COND(uv_size != 0 && (uv_size != pointcount));
#endif
Vector<int> indices = Geometry::triangulate_polygon(p_points);
-
- if (indices.empty()) {
-
- ERR_EXPLAIN("Bad Polygon!");
- ERR_FAIL_V();
- }
+ ERR_FAIL_COND_MSG(indices.empty(), "Invalid polygon data, triangulation failed.");
Item::CommandPolygon *polygon = memnew(Item::CommandPolygon);
ERR_FAIL_COND(!polygon);
@@ -712,21 +775,22 @@ void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
- int ps = p_points.size();
- ERR_FAIL_COND(!p_colors.empty() && p_colors.size() != ps && p_colors.size() != 1);
- ERR_FAIL_COND(!p_uvs.empty() && p_uvs.size() != ps);
- ERR_FAIL_COND(!p_bones.empty() && p_bones.size() != ps * 4);
- ERR_FAIL_COND(!p_weights.empty() && p_weights.size() != ps * 4);
+ int vertex_count = p_points.size();
+ ERR_FAIL_COND(vertex_count == 0);
+ ERR_FAIL_COND(!p_colors.empty() && p_colors.size() != vertex_count && p_colors.size() != 1);
+ ERR_FAIL_COND(!p_uvs.empty() && p_uvs.size() != vertex_count);
+ ERR_FAIL_COND(!p_bones.empty() && p_bones.size() != vertex_count * 4);
+ ERR_FAIL_COND(!p_weights.empty() && p_weights.size() != vertex_count * 4);
- Vector<int> indices = p_indices;
+ const Vector<int> &indices = p_indices;
int count = p_count * 3;
if (indices.empty()) {
- ERR_FAIL_COND(ps % 3 != 0);
+ ERR_FAIL_COND(vertex_count % 3 != 0);
if (p_count == -1)
- count = ps;
+ count = vertex_count;
} else {
ERR_FAIL_COND(indices.size() % 3 != 0);
@@ -763,7 +827,7 @@ void VisualServerCanvas::canvas_item_add_set_transform(RID p_item, const Transfo
canvas_item->commands.push_back(tr);
}
-void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture, RID p_normal_map) {
+void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform, const Color &p_modulate, RID p_texture, RID p_normal_map) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -773,10 +837,12 @@ void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID
m->mesh = p_mesh;
m->texture = p_texture;
m->normal_map = p_normal_map;
+ m->transform = p_transform;
+ m->modulate = p_modulate;
canvas_item->commands.push_back(m);
}
-void VisualServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal, int p_h_frames, int p_v_frames) {
+void VisualServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -786,8 +852,6 @@ void VisualServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles,
part->particles = p_particles;
part->texture = p_texture;
part->normal_map = p_normal;
- part->h_frames = p_h_frames;
- part->v_frames = p_v_frames;
//take the chance and request processing for them, at least once until they become visible again
VSG::storage->particles_request_process(p_particles);
@@ -828,6 +892,8 @@ void VisualServerCanvas::canvas_item_set_sort_children_by_y(RID p_item, bool p_e
ERR_FAIL_COND(!canvas_item);
canvas_item->sort_y = p_enable;
+
+ _mark_ysort_dirty(canvas_item, canvas_item_owner);
}
void VisualServerCanvas::canvas_item_set_z_index(RID p_item, int p_z) {
@@ -1304,6 +1370,8 @@ bool VisualServerCanvas::free(RID p_rid) {
Item *item_owner = canvas_item_owner.get(canvas_item->parent);
item_owner->child_items.erase(canvas_item);
+
+ _mark_ysort_dirty(item_owner, canvas_item_owner);
}
}
@@ -1385,4 +1453,15 @@ bool VisualServerCanvas::free(RID p_rid) {
}
VisualServerCanvas::VisualServerCanvas() {
+
+ z_list = (RasterizerCanvas::Item **)memalloc(z_range * sizeof(RasterizerCanvas::Item *));
+ z_last_list = (RasterizerCanvas::Item **)memalloc(z_range * sizeof(RasterizerCanvas::Item *));
+
+ disable_scale = false;
+}
+
+VisualServerCanvas::~VisualServerCanvas() {
+
+ memfree(z_list);
+ memfree(z_last_list);
}
diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h
index 966b51d341..822e3f8ce3 100644
--- a/servers/visual/visual_server_canvas.h
+++ b/servers/visual/visual_server_canvas.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -48,6 +48,10 @@ public:
bool use_parent_material;
int index;
bool children_order_dirty;
+ int ysort_children_count;
+ Color ysort_modulate;
+ Transform2D ysort_xform;
+ Vector2 ysort_pos;
Vector<Item *> child_items;
@@ -61,6 +65,9 @@ public:
use_parent_material = false;
z_relative = true;
index = 0;
+ ysort_children_count = -1;
+ ysort_xform = Transform2D();
+ ysort_pos = Vector2();
}
};
@@ -76,10 +83,10 @@ public:
_FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const {
- if (Math::abs(p_left->xform.elements[2].y - p_right->xform.elements[2].y) < CMP_EPSILON)
- return p_left->xform.elements[2].x < p_right->xform.elements[2].x;
- else
- return p_left->xform.elements[2].y < p_right->xform.elements[2].y;
+ if (Math::is_equal_approx(p_left->ysort_pos.y, p_right->ysort_pos.y))
+ return p_left->ysort_pos.x < p_right->ysort_pos.x;
+
+ return p_left->ysort_pos.y < p_right->ysort_pos.y;
}
};
@@ -120,6 +127,8 @@ public:
bool children_order_dirty;
Vector<ChildItem> child_items;
Color modulate;
+ RID parent;
+ float parent_scale;
int find_item(Item *p_item) {
for (int i = 0; i < child_items.size(); i++) {
@@ -137,24 +146,32 @@ public:
Canvas() {
modulate = Color(1, 1, 1, 1);
children_order_dirty = true;
+ parent_scale = 1.0;
}
};
- RID_Owner<Canvas> canvas_owner;
+ mutable RID_Owner<Canvas> canvas_owner;
RID_Owner<Item> canvas_item_owner;
RID_Owner<RasterizerCanvas::Light> canvas_light_owner;
+ bool disable_scale;
+
private:
void _render_canvas_item_tree(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights);
void _render_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner);
void _light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, RasterizerCanvas::Light *p_masked_lights);
+ RasterizerCanvas::Item **z_list;
+ RasterizerCanvas::Item **z_last_list;
+
public:
void render_canvas(Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect);
RID canvas_create();
void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring);
void canvas_set_modulate(RID p_canvas, const Color &p_color);
+ void canvas_set_parent(RID p_canvas, RID p_parent, float p_scale);
+ void canvas_set_disable_scale(bool p_disable);
RID canvas_item_create();
void canvas_item_set_parent(RID p_item, RID p_parent);
@@ -184,9 +201,9 @@ public:
void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID());
void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false);
void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID());
- void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture = RID(), RID p_normal_map = RID());
+ void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID());
void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID());
- void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal, int p_h_frames, int p_v_frames);
+ void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal);
void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform);
void canvas_item_add_clip_ignore(RID p_item, bool p_ignore);
void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable);
@@ -241,6 +258,7 @@ public:
bool free(RID p_rid);
VisualServerCanvas();
+ ~VisualServerCanvas();
};
#endif // VISUALSERVERCANVAS_H
diff --git a/servers/visual/visual_server_global.cpp b/servers/visual/visual_server_globals.cpp
index 61a8951f75..5c247c7f0f 100644
--- a/servers/visual/visual_server_global.cpp
+++ b/servers/visual/visual_server_globals.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* visual_server_global.cpp */
+/* visual_server_globals.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "visual_server_global.h"
+#include "visual_server_globals.h"
RasterizerStorage *VisualServerGlobals::storage = NULL;
RasterizerCanvas *VisualServerGlobals::canvas_render = NULL;
diff --git a/servers/visual/visual_server_global.h b/servers/visual/visual_server_globals.h
index b4888dfd50..04d52aa1eb 100644
--- a/servers/visual/visual_server_global.h
+++ b/servers/visual/visual_server_globals.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* visual_server_global.h */
+/* visual_server_globals.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef VISUALSERVERGLOBAL_H
-#define VISUALSERVERGLOBAL_H
+#ifndef VISUAL_SERVER_GLOBALS_H
+#define VISUAL_SERVER_GLOBALS_H
#include "rasterizer.h"
@@ -51,4 +51,4 @@ public:
#define VSG VisualServerGlobals
-#endif // VISUALSERVERGLOBAL_H
+#endif // VISUAL_SERVER_GLOBALS_H
diff --git a/servers/visual/visual_server_light_baker.cpp b/servers/visual/visual_server_light_baker.cpp
index ed87e84a03..5626a72283 100644
--- a/servers/visual/visual_server_light_baker.cpp
+++ b/servers/visual/visual_server_light_baker.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual/visual_server_light_baker.h b/servers/visual/visual_server_light_baker.h
index 77472d0994..6e1148d622 100644
--- a/servers/visual/visual_server_light_baker.h
+++ b/servers/visual/visual_server_light_baker.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index ea63ae5013..7aded4e816 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,10 +33,9 @@
#include "core/io/marshalls.h"
#include "core/os/os.h"
#include "core/project_settings.h"
-#include "core/sort.h"
-#include "default_mouse_cursor.xpm"
+#include "core/sort_array.h"
#include "visual_server_canvas.h"
-#include "visual_server_global.h"
+#include "visual_server_globals.h"
#include "visual_server_scene.h"
// careful, these may run in different threads than the visual server
@@ -78,6 +77,8 @@ void VisualServerRaster::free(RID p_rid) {
return;
if (VSG::scene->free(p_rid))
return;
+ if (VSG::scene_render->free(p_rid))
+ return;
}
/* EVENT QUEUING */
@@ -124,7 +125,6 @@ void VisualServerRaster::draw(bool p_swap_buffers, double frame_step) {
frame_drawn_callbacks.pop_front();
}
-
VS::get_singleton()->emit_signal("frame_post_draw");
}
void VisualServerRaster::sync() {
@@ -155,10 +155,10 @@ int VisualServerRaster::get_render_info(RenderInfo p_info) {
/* TESTING */
-void VisualServerRaster::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale) {
+void VisualServerRaster::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {
redraw_request();
- VSG::rasterizer->set_boot_image(p_image, p_color, p_scale);
+ VSG::rasterizer->set_boot_image(p_image, p_color, p_scale, p_use_filter);
}
void VisualServerRaster::set_default_clear_color(const Color &p_color) {
VSG::viewport->set_default_clear_color(p_color);
@@ -190,6 +190,9 @@ void VisualServerRaster::call_set_use_vsync(bool p_enable) {
OS::get_singleton()->_set_use_vsync(p_enable);
}
+bool VisualServerRaster::is_low_end() const {
+ return VSG::rasterizer->is_low_end();
+}
VisualServerRaster::VisualServerRaster() {
VSG::canvas = memnew(VisualServerCanvas);
@@ -200,8 +203,10 @@ VisualServerRaster::VisualServerRaster() {
VSG::canvas_render = VSG::rasterizer->get_canvas();
VSG::scene_render = VSG::rasterizer->get_scene();
- for (int i = 0; i < 4; i++)
+ for (int i = 0; i < 4; i++) {
black_margin[i] = 0;
+ black_image[i] = RID();
+ }
}
VisualServerRaster::~VisualServerRaster() {
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index b54e150656..0df228457e 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,17 +31,13 @@
#ifndef VISUAL_SERVER_RASTER_H
#define VISUAL_SERVER_RASTER_H
-#include "core/allocators.h"
#include "core/math/octree.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual_server.h"
#include "visual_server_canvas.h"
-#include "visual_server_global.h"
+#include "visual_server_globals.h"
#include "visual_server_scene.h"
#include "visual_server_viewport.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
class VisualServerRaster : public VisualServer {
@@ -59,7 +55,6 @@ class VisualServerRaster : public VisualServer {
};
static int changes;
- bool draw_extra_frame;
RID test_cube;
int black_margin[4];
@@ -161,6 +156,7 @@ public:
BIND1RC(uint32_t, texture_get_height, RID)
BIND1RC(uint32_t, texture_get_depth, RID)
BIND4(texture_set_size_override, RID, int, int, int)
+ BIND2(texture_bind, RID, uint32_t)
BIND3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *)
BIND3(texture_set_detect_srgb_callback, RID, TextureDetectCallback, void *)
@@ -313,6 +309,7 @@ public:
BIND2(light_set_negative, RID, bool)
BIND2(light_set_cull_mask, RID, uint32_t)
BIND2(light_set_reverse_cull_face_mode, RID, bool)
+ BIND2(light_set_use_gi, RID, bool)
BIND2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
BIND2(light_omni_set_shadow_detail, RID, LightOmniShadowDetail)
@@ -337,6 +334,7 @@ public:
BIND2(reflection_probe_set_enable_box_projection, RID, bool)
BIND2(reflection_probe_set_enable_shadows, RID, bool)
BIND2(reflection_probe_set_cull_mask, RID, uint32_t)
+ BIND2(reflection_probe_set_resolution, RID, int)
/* BAKED LIGHT API */
@@ -430,6 +428,7 @@ public:
BIND0R(RID, camera_create)
BIND4(camera_set_perspective, RID, float, float, float)
BIND4(camera_set_orthogonal, RID, float, float, float)
+ BIND5(camera_set_frustum, RID, float, Vector2, float, float)
BIND2(camera_set_transform, RID, const Transform &)
BIND2(camera_set_cull_mask, RID, uint32_t)
BIND2(camera_set_environment, RID, RID)
@@ -452,6 +451,7 @@ public:
BIND2(viewport_set_clear_mode, RID, ViewportClearMode)
BIND3(viewport_attach_to_screen, RID, const Rect2 &, int)
+ BIND2(viewport_set_render_direct_to_screen, RID, bool)
BIND1(viewport_detach, RID)
BIND2(viewport_set_update_mode, RID, ViewportUpdateMode)
@@ -474,7 +474,7 @@ public:
BIND2(viewport_set_transparent_background, RID, bool)
BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &)
- BIND3(viewport_set_canvas_layer, RID, RID, int)
+ BIND4(viewport_set_canvas_stacking, RID, RID, int, int)
BIND2(viewport_set_shadow_atlas_size, RID, int)
BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
BIND2(viewport_set_msaa, RID, ViewportMSAA)
@@ -495,23 +495,25 @@ public:
BIND2(environment_set_background, RID, EnvironmentBG)
BIND2(environment_set_sky, RID, RID)
BIND2(environment_set_sky_custom_fov, RID, float)
+ BIND2(environment_set_sky_orientation, RID, const Basis &)
BIND2(environment_set_bg_color, RID, const Color &)
BIND2(environment_set_bg_energy, RID, float)
BIND2(environment_set_canvas_max_layer, RID, int)
BIND4(environment_set_ambient_light, RID, const Color &, float, float)
+ BIND2(environment_set_camera_feed_id, RID, int)
BIND7(environment_set_ssr, RID, bool, int, float, float, float, bool)
BIND13(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, const Color &, EnvironmentSSAOQuality, EnvironmentSSAOBlur, float)
BIND6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
BIND6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
- BIND10(environment_set_glow, RID, bool, int, float, float, float, EnvironmentGlowBlendMode, float, float, bool)
+ BIND11(environment_set_glow, RID, bool, int, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool)
BIND9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
BIND6(environment_set_adjustment, RID, bool, float, float, float, RID)
BIND5(environment_set_fog, RID, bool, const Color &, const Color &, float)
- BIND6(environment_set_fog_depth, RID, bool, float, float, bool, float)
+ BIND7(environment_set_fog_depth, RID, bool, float, float, float, bool, float)
BIND5(environment_set_fog_height, RID, bool, float, float, float)
/* SCENARIO API */
@@ -568,6 +570,8 @@ public:
BIND0R(RID, canvas_create)
BIND3(canvas_set_item_mirroring, RID, RID, const Point2 &)
BIND2(canvas_set_modulate, RID, const Color &)
+ BIND3(canvas_set_parent, RID, RID, float)
+ BIND1(canvas_set_disable_scale, bool)
BIND0R(RID, canvas_item_create)
BIND2(canvas_item_set_parent, RID, RID)
@@ -597,9 +601,9 @@ public:
BIND7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID)
BIND7(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, bool)
BIND10(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID)
- BIND4(canvas_item_add_mesh, RID, const RID &, RID, RID)
+ BIND6(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID)
BIND4(canvas_item_add_multimesh, RID, RID, RID, RID)
- BIND6(canvas_item_add_particles, RID, RID, RID, RID, int, int)
+ BIND4(canvas_item_add_particles, RID, RID, RID, RID)
BIND2(canvas_item_add_set_transform, RID, const Transform2D &)
BIND2(canvas_item_add_clip_ignore, RID, bool)
BIND2(canvas_item_set_sort_children_by_y, RID, bool)
@@ -679,7 +683,7 @@ public:
/* TESTING */
- virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale);
+ virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true);
virtual void set_default_clear_color(const Color &p_color);
virtual bool has_feature(Features p_feature) const;
@@ -689,6 +693,8 @@ public:
virtual void call_set_use_vsync(bool p_enable);
+ virtual bool is_low_end() const;
+
VisualServerRaster();
~VisualServerRaster();
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index eacb5f671c..7c100be0f2 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,8 +30,9 @@
#include "visual_server_scene.h"
#include "core/os/os.h"
-#include "visual_server_global.h"
+#include "visual_server_globals.h"
#include "visual_server_raster.h"
+#include <new>
/* CAMERA API */
RID VisualServerScene::camera_create() {
@@ -60,6 +61,16 @@ void VisualServerScene::camera_set_orthogonal(RID p_camera, float p_size, float
camera->zfar = p_z_far;
}
+void VisualServerScene::camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) {
+ Camera *camera = camera_owner.get(p_camera);
+ ERR_FAIL_COND(!camera);
+ camera->type = Camera::FRUSTUM;
+ camera->size = p_size;
+ camera->offset = p_offset;
+ camera->znear = p_z_near;
+ camera->zfar = p_z_far;
+}
+
void VisualServerScene::camera_set_transform(RID p_camera, const Transform &p_transform) {
Camera *camera = camera_owner.get(p_camera);
@@ -398,6 +409,8 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
VSG::scene_render->free(gi_probe->probe_instance);
} break;
+ default: {
+ }
}
if (instance->base_data) {
@@ -443,6 +456,9 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
InstanceGeometryData *geom = memnew(InstanceGeometryData);
instance->base_data = geom;
+ if (instance->base_type == VS::INSTANCE_MESH) {
+ instance->blend_values.resize(VSG::storage->mesh_get_blend_shape_count(p_base));
+ }
} break;
case VS::INSTANCE_REFLECTION_PROBE: {
@@ -471,6 +487,8 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
gi_probe->probe_instance = VSG::scene_render->gi_probe_instance_create();
} break;
+ default: {
+ }
}
VSG::storage->instance_add_dependency(p_base, instance);
@@ -518,6 +536,8 @@ void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario) {
gi_probe_update_list.remove(&gi_probe->update_element);
}
} break;
+ default: {
+ }
}
instance->scenario = NULL;
@@ -549,6 +569,8 @@ void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario) {
gi_probe_update_list.add(&gi_probe->update_element);
}
} break;
+ default: {
+ }
}
_instance_queue_update(instance, true, true);
@@ -569,15 +591,28 @@ void VisualServerScene::instance_set_transform(RID p_instance, const Transform &
if (instance->transform == p_transform)
return; //must be checked to avoid worst evil
+#ifdef DEBUG_ENABLED
+
+ for (int i = 0; i < 4; i++) {
+ const Vector3 &v = i < 3 ? p_transform.basis.elements[i] : p_transform.origin;
+ ERR_FAIL_COND(Math::is_inf(v.x));
+ ERR_FAIL_COND(Math::is_nan(v.x));
+ ERR_FAIL_COND(Math::is_inf(v.y));
+ ERR_FAIL_COND(Math::is_nan(v.y));
+ ERR_FAIL_COND(Math::is_inf(v.z));
+ ERR_FAIL_COND(Math::is_nan(v.z));
+ }
+
+#endif
instance->transform = p_transform;
_instance_queue_update(instance, true);
}
-void VisualServerScene::instance_attach_object_instance_id(RID p_instance, ObjectID p_ID) {
+void VisualServerScene::instance_attach_object_instance_id(RID p_instance, ObjectID p_id) {
Instance *instance = instance_owner.get(p_instance);
ERR_FAIL_COND(!instance);
- instance->object_ID = p_ID;
+ instance->object_id = p_id;
}
void VisualServerScene::instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) {
@@ -597,8 +632,9 @@ void VisualServerScene::instance_set_surface_material(RID p_instance, int p_surf
Instance *instance = instance_owner.get(p_instance);
ERR_FAIL_COND(!instance);
- if (instance->update_item.in_list()) {
- _update_dirty_instance(instance);
+ if (instance->base_type == VS::INSTANCE_MESH) {
+ //may not have been updated yet
+ instance->materials.resize(VSG::storage->mesh_get_surface_count(instance->base));
}
ERR_FAIL_INDEX(p_surface, instance->materials.size());
@@ -607,7 +643,7 @@ void VisualServerScene::instance_set_surface_material(RID p_instance, int p_surf
VSG::storage->material_remove_instance_owner(instance->materials[p_surface], instance);
}
instance->materials.write[p_surface] = p_material;
- instance->base_material_changed();
+ instance->base_changed(false, true);
if (instance->materials[p_surface].is_valid()) {
VSG::storage->material_add_instance_owner(instance->materials[p_surface], instance);
@@ -649,6 +685,8 @@ void VisualServerScene::instance_set_visible(RID p_instance, bool p_visible) {
}
} break;
+ default: {
+ }
}
}
inline bool is_geometry_instance(VisualServer::InstanceType p_type) {
@@ -753,10 +791,10 @@ Vector<ObjectID> VisualServerScene::instances_cull_aabb(const AABB &p_aabb, RID
Instance *instance = cull[i];
ERR_CONTINUE(!instance);
- if (instance->object_ID == 0)
+ if (instance->object_id == 0)
continue;
- instances.push_back(instance->object_ID);
+ instances.push_back(instance->object_id);
}
return instances;
@@ -775,10 +813,10 @@ Vector<ObjectID> VisualServerScene::instances_cull_ray(const Vector3 &p_from, co
for (int i = 0; i < culled; i++) {
Instance *instance = cull[i];
ERR_CONTINUE(!instance);
- if (instance->object_ID == 0)
+ if (instance->object_id == 0)
continue;
- instances.push_back(instance->object_ID);
+ instances.push_back(instance->object_id);
}
return instances;
@@ -799,10 +837,10 @@ Vector<ObjectID> VisualServerScene::instances_cull_convex(const Vector<Plane> &p
Instance *instance = cull[i];
ERR_CONTINUE(!instance);
- if (instance->object_ID == 0)
+ if (instance->object_id == 0)
continue;
- instances.push_back(instance->object_ID);
+ instances.push_back(instance->object_id);
}
return instances;
@@ -825,6 +863,8 @@ void VisualServerScene::instance_geometry_set_flag(RID p_instance, VS::InstanceF
instance->redraw_if_visible = p_enabled;
} break;
+ default: {
+ }
}
}
void VisualServerScene::instance_geometry_set_cast_shadows_setting(RID p_instance, VS::ShadowCastingSetting p_shadow_casting_setting) {
@@ -833,7 +873,7 @@ void VisualServerScene::instance_geometry_set_cast_shadows_setting(RID p_instanc
ERR_FAIL_COND(!instance);
instance->cast_shadows = p_shadow_casting_setting;
- instance->base_material_changed(); // to actually compute if shadows are visible or not
+ instance->base_changed(false, true); // to actually compute if shadows are visible or not
}
void VisualServerScene::instance_geometry_set_material_override(RID p_instance, RID p_material) {
@@ -844,7 +884,7 @@ void VisualServerScene::instance_geometry_set_material_override(RID p_instance,
VSG::storage->material_remove_instance_owner(instance->material_override, instance);
}
instance->material_override = p_material;
- instance->base_material_changed();
+ instance->base_changed(false, true);
if (instance->material_override.is_valid()) {
VSG::storage->material_add_instance_owner(instance->material_override, instance);
@@ -902,7 +942,7 @@ void VisualServerScene::_update_instance(Instance *p_instance) {
_update_instance_lightmap_captures(p_instance);
} else {
if (!p_instance->lightmap_capture_data.empty()) {
- !p_instance->lightmap_capture_data.resize(0); //not in use, clear capture data
+ p_instance->lightmap_capture_data.resize(0); //not in use, clear capture data
}
}
}
@@ -1016,8 +1056,8 @@ void VisualServerScene::_update_instance_aabb(Instance *p_instance) {
new_aabb = VSG::storage->lightmap_capture_get_bounds(p_instance->base);
} break;
-
- default: {}
+ default: {
+ }
}
// <Zylann> This is why I didn't re-use Instance::aabb to implement custom AABBs
@@ -1234,7 +1274,9 @@ void VisualServerScene::_update_instance_lightmap_captures(Instance *p_instance)
//print_line("update captures for pos: " + p_instance->transform.origin);
- zeromem(p_instance->lightmap_capture_data.ptrw(), 12 * sizeof(Color));
+ for (int i = 0; i < 12; i++)
+ new (&p_instance->lightmap_capture_data.ptrw()[i]) Color;
+
//this could use some sort of blending..
for (List<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) {
const PoolVector<RasterizerStorage::LightmapCaptureOctree> *octree = VSG::storage->lightmap_capture_get_octree_ptr(E->get()->base);
@@ -1258,13 +1300,15 @@ void VisualServerScene::_update_instance_lightmap_captures(Instance *p_instance)
}
}
-void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario) {
+bool VisualServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario) {
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
Transform light_transform = p_instance->transform;
light_transform.orthonormalize(); //scale does not count on lights
+ bool animated_material_found = false;
+
switch (VSG::storage->light_get_type(p_instance->base)) {
case VS::LIGHT_DIRECTIONAL: {
@@ -1297,6 +1341,10 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
continue;
}
+ if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+ animated_material_found = true;
+ }
+
float max, min;
instance->transformed_aabb.project_range_in_plane(base, min, max);
@@ -1378,9 +1426,12 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
float y_min = 0.f, y_max = 0.f;
float z_min = 0.f, z_max = 0.f;
+ // FIXME: z_max_cam is defined, computed, but not used below when setting up
+ // ortho_camera. Commented out for now to fix warnings but should be investigated.
float x_min_cam = 0.f, x_max_cam = 0.f;
float y_min_cam = 0.f, y_max_cam = 0.f;
- float z_min_cam = 0.f, z_max_cam = 0.f;
+ float z_min_cam = 0.f;
+ //float z_max_cam = 0.f;
float bias_scale = 1.0;
@@ -1442,7 +1493,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
x_min_cam = x_vec.dot(center) - radius;
y_max_cam = y_vec.dot(center) + radius;
y_min_cam = y_vec.dot(center) - radius;
- z_max_cam = z_vec.dot(center) + radius;
+ //z_max_cam = z_vec.dot(center) + radius;
z_min_cam = z_vec.dot(center) - radius;
if (depth_range_mode == VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE) {
@@ -1520,99 +1571,102 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
VS::LightOmniShadowMode shadow_mode = VSG::storage->light_omni_get_shadow_mode(p_instance->base);
- switch (shadow_mode) {
- case VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID: {
-
- for (int i = 0; i < 2; i++) {
-
- //using this one ensures that raster deferred will have it
+ if (shadow_mode == VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !VSG::scene_render->light_instances_can_render_shadow_cube()) {
- float radius = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_RANGE);
+ for (int i = 0; i < 2; i++) {
- float z = i == 0 ? -1 : 1;
- Vector<Plane> planes;
- planes.resize(5);
- planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius));
- planes.write[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius));
- planes.write[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius));
- planes.write[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius));
- planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius));
+ //using this one ensures that raster deferred will have it
- int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK);
- Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z);
-
- for (int j = 0; j < cull_count; j++) {
+ float radius = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_RANGE);
- Instance *instance = instance_shadow_cull_result[j];
- if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
- cull_count--;
- SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
- j--;
- } else {
- instance->depth = near_plane.distance_to(instance->transform.origin);
- instance->depth_layer = 0;
+ float z = i == 0 ? -1 : 1;
+ Vector<Plane> planes;
+ planes.resize(5);
+ planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius));
+ planes.write[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius));
+ planes.write[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius));
+ planes.write[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius));
+ planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius));
+
+ int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK);
+ Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z);
+
+ for (int j = 0; j < cull_count; j++) {
+
+ Instance *instance = instance_shadow_cull_result[j];
+ if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
+ cull_count--;
+ SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
+ j--;
+ } else {
+ if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+ animated_material_found = true;
}
- }
- VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i);
- VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
+ instance->depth = near_plane.distance_to(instance->transform.origin);
+ instance->depth_layer = 0;
+ }
}
- } break;
- case VS::LIGHT_OMNI_SHADOW_CUBE: {
-
- float radius = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_RANGE);
- CameraMatrix cm;
- cm.set_perspective(90, 1, 0.01, radius);
- for (int i = 0; i < 6; i++) {
-
- //using this one ensures that raster deferred will have it
-
- static const Vector3 view_normals[6] = {
- Vector3(-1, 0, 0),
- Vector3(+1, 0, 0),
- Vector3(0, -1, 0),
- Vector3(0, +1, 0),
- Vector3(0, 0, -1),
- Vector3(0, 0, +1)
- };
- static const Vector3 view_up[6] = {
- Vector3(0, -1, 0),
- Vector3(0, -1, 0),
- Vector3(0, 0, -1),
- Vector3(0, 0, +1),
- Vector3(0, -1, 0),
- Vector3(0, -1, 0)
- };
-
- Transform xform = light_transform * Transform().looking_at(view_normals[i], view_up[i]);
-
- Vector<Plane> planes = cm.get_projection_planes(xform);
+ VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i);
+ VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
+ }
+ } else { //shadow cube
- int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK);
+ float radius = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_RANGE);
+ CameraMatrix cm;
+ cm.set_perspective(90, 1, 0.01, radius);
- Plane near_plane(xform.origin, -xform.basis.get_axis(2));
- for (int j = 0; j < cull_count; j++) {
+ for (int i = 0; i < 6; i++) {
- Instance *instance = instance_shadow_cull_result[j];
- if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
- cull_count--;
- SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
- j--;
- } else {
- instance->depth = near_plane.distance_to(instance->transform.origin);
- instance->depth_layer = 0;
+ //using this one ensures that raster deferred will have it
+
+ static const Vector3 view_normals[6] = {
+ Vector3(-1, 0, 0),
+ Vector3(+1, 0, 0),
+ Vector3(0, -1, 0),
+ Vector3(0, +1, 0),
+ Vector3(0, 0, -1),
+ Vector3(0, 0, +1)
+ };
+ static const Vector3 view_up[6] = {
+ Vector3(0, -1, 0),
+ Vector3(0, -1, 0),
+ Vector3(0, 0, -1),
+ Vector3(0, 0, +1),
+ Vector3(0, -1, 0),
+ Vector3(0, -1, 0)
+ };
+
+ Transform xform = light_transform * Transform().looking_at(view_normals[i], view_up[i]);
+
+ Vector<Plane> planes = cm.get_projection_planes(xform);
+
+ int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK);
+
+ Plane near_plane(xform.origin, -xform.basis.get_axis(2));
+ for (int j = 0; j < cull_count; j++) {
+
+ Instance *instance = instance_shadow_cull_result[j];
+ if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
+ cull_count--;
+ SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
+ j--;
+ } else {
+ if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+ animated_material_found = true;
}
+ instance->depth = near_plane.distance_to(instance->transform.origin);
+ instance->depth_layer = 0;
}
-
- VSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i);
- VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
}
- //restore the regular DP matrix
- VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0);
+ VSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i);
+ VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
+ }
- } break;
+ //restore the regular DP matrix
+ VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0);
}
} break;
@@ -1636,6 +1690,9 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
j--;
} else {
+ if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+ animated_material_found = true;
+ }
instance->depth = near_plane.distance_to(instance->transform.origin);
instance->depth_layer = 0;
}
@@ -1646,6 +1703,8 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
} break;
}
+
+ return animated_material_found;
}
void VisualServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
@@ -1681,6 +1740,17 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_view
ortho = false;
} break;
+ case Camera::FRUSTUM: {
+
+ camera_matrix.set_frustum(
+ camera->size,
+ p_viewport_size.width / (float)p_viewport_size.height,
+ camera->offset,
+ camera->znear,
+ camera->zfar,
+ camera->vaspect);
+ ortho = false;
+ } break;
}
_prepare_scene(camera->transform, camera_matrix, ortho, camera->env, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
@@ -1822,7 +1892,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
//failure
} else if (ins->base_type == VS::INSTANCE_LIGHT && ins->visible) {
- if (ins->visible && light_cull_count < MAX_LIGHTS_CULLED) {
+ if (light_cull_count < MAX_LIGHTS_CULLED) {
InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data);
@@ -1839,7 +1909,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
}
} else if (ins->base_type == VS::INSTANCE_REFLECTION_PROBE && ins->visible) {
- if (ins->visible && reflection_probe_cull_count < MAX_REFLECTION_PROBES_CULLED) {
+ if (reflection_probe_cull_count < MAX_REFLECTION_PROBES_CULLED) {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(ins->base_data);
@@ -1885,9 +1955,14 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
if (ins->base_type == VS::INSTANCE_PARTICLES) {
//particles visible? process them
- VSG::storage->particles_request_process(ins->base);
- //particles visible? request redraw
- VisualServerRaster::redraw_request();
+ if (VSG::storage->particles_is_inactive(ins->base)) {
+ //but if nothing is going on, don't do it.
+ keep = false;
+ } else {
+ VSG::storage->particles_request_process(ins->base);
+ //particles visible? request redraw
+ VisualServerRaster::redraw_request();
+ }
}
if (geom->lighting_dirty) {
@@ -2087,7 +2162,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
if (redraw) {
//must redraw!
- _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario);
+ light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario);
}
}
}
@@ -2133,6 +2208,8 @@ bool VisualServerScene::_render_reflection_probe_step(Instance *p_instance, int
Scenario *scenario = p_instance->scenario;
ERR_FAIL_COND_V(!scenario, true);
+ VisualServerRaster::redraw_request(); //update, so it updates in editor
+
if (p_step == 0) {
if (!VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) {
@@ -2319,7 +2396,7 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) {
mipmap.resize(size);
PoolVector<uint8_t>::Write w = mipmap.write();
zeromem(w.ptr(), size);
- w = PoolVector<uint8_t>::Write();
+ w.release();
probe->dynamic.mipmaps_3d.push_back(mipmap);
@@ -2434,7 +2511,7 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) {
uint32_t a = uint32_t(alpha_block[x][y]) - min_alpha;
//convert range to 3 bits
a = int((a * 7.0 / (max_alpha - min_alpha)) + 0.5);
- a = CLAMP(a, 0, 7); //just to be sure
+ a = MIN(a, 7); //just to be sure
a = 7 - a; //because range is inverted in this mode
if (a == 0) {
//do none, remain
@@ -2577,7 +2654,7 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co
for (int i = 0; i < 3; i++) {
- if (ABS(light_axis[i]) < CMP_EPSILON)
+ if (Math::is_zero_approx(light_axis[i]))
continue;
clip[clip_planes].normal[i] = 1.0;
@@ -2712,7 +2789,7 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co
for (int c = 0; c < 3; c++) {
- if (ABS(light_axis[c]) < CMP_EPSILON)
+ if (Math::is_zero_approx(light_axis[c]))
continue;
clip[clip_planes].normal[c] = 1.0;
@@ -2821,7 +2898,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) {
RID rid = E->key();
const InstanceGIProbeData::LightCache &lc = E->get();
- if ((!probe_data->dynamic.light_cache_changes.has(rid) || !(probe_data->dynamic.light_cache_changes[rid] == lc)) && lc.visible) {
+ if ((!probe_data->dynamic.light_cache_changes.has(rid) || probe_data->dynamic.light_cache_changes[rid] != lc) && lc.visible) {
//erase light data
_bake_gi_probe_light(header, cells, local_data, leaves, leaf_count, lc, -1);
@@ -2834,7 +2911,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) {
RID rid = E->key();
const InstanceGIProbeData::LightCache &lc = E->get();
- if ((!probe_data->dynamic.light_cache.has(rid) || !(probe_data->dynamic.light_cache[rid] == lc)) && lc.visible) {
+ if ((!probe_data->dynamic.light_cache.has(rid) || probe_data->dynamic.light_cache[rid] != lc) && lc.visible) {
//add light data
_bake_gi_probe_light(header, cells, local_data, leaves, leaf_count, lc, 1);
@@ -2870,7 +2947,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) {
uint32_t idx = level_cells[j];
- uint32_t r = (uint32_t(local_data[idx].energy[0]) / probe_data->dynamic.bake_dynamic_range) >> 2;
+ uint32_t r2 = (uint32_t(local_data[idx].energy[0]) / probe_data->dynamic.bake_dynamic_range) >> 2;
uint32_t g = (uint32_t(local_data[idx].energy[1]) / probe_data->dynamic.bake_dynamic_range) >> 2;
uint32_t b = (uint32_t(local_data[idx].energy[2]) / probe_data->dynamic.bake_dynamic_range) >> 2;
uint32_t a = (cells[idx].level_alpha >> 8) & 0xFF;
@@ -2878,10 +2955,10 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) {
uint32_t mm_ofs = sizes[0] * sizes[1] * (local_data[idx].pos[2]) + sizes[0] * (local_data[idx].pos[1]) + (local_data[idx].pos[0]);
mm_ofs *= 4; //for RGBA (4 bytes)
- mipmapw[mm_ofs + 0] = uint8_t(CLAMP(r, 0, 255));
- mipmapw[mm_ofs + 1] = uint8_t(CLAMP(g, 0, 255));
- mipmapw[mm_ofs + 2] = uint8_t(CLAMP(b, 0, 255));
- mipmapw[mm_ofs + 3] = uint8_t(CLAMP(a, 0, 255));
+ mipmapw[mm_ofs + 0] = uint8_t(MIN(r2, 255));
+ mipmapw[mm_ofs + 1] = uint8_t(MIN(g, 255));
+ mipmapw[mm_ofs + 2] = uint8_t(MIN(b, 255));
+ mipmapw[mm_ofs + 3] = uint8_t(MIN(a, 255));
}
}
} else if (probe_data->dynamic.compression == RasterizerStorage::GI_PROBE_S3TC) {
@@ -3040,6 +3117,9 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) {
for (List<Instance *>::Element *E = p_gi_probe->scenario->directional_lights.front(); E; E = E->next()) {
+ if (!VSG::storage->light_get_use_gi(E->get()->base))
+ continue;
+
InstanceGIProbeData::LightCache lc;
lc.type = VSG::storage->light_get_type(E->get()->base);
lc.color = VSG::storage->light_get_color(E->get()->base);
@@ -3051,7 +3131,7 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) {
lc.transform = probe_data->dynamic.light_to_cell_xform * E->get()->transform;
lc.visible = E->get()->visible;
- if (!probe_data->dynamic.light_cache.has(E->get()->self) || !(probe_data->dynamic.light_cache[E->get()->self] == lc)) {
+ if (!probe_data->dynamic.light_cache.has(E->get()->self) || probe_data->dynamic.light_cache[E->get()->self] != lc) {
all_equal = false;
}
@@ -3060,6 +3140,9 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) {
for (Set<Instance *>::Element *E = probe_data->lights.front(); E; E = E->next()) {
+ if (!VSG::storage->light_get_use_gi(E->get()->base))
+ continue;
+
InstanceGIProbeData::LightCache lc;
lc.type = VSG::storage->light_get_type(E->get()->base);
lc.color = VSG::storage->light_get_color(E->get()->base);
@@ -3071,7 +3154,7 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) {
lc.transform = probe_data->dynamic.light_to_cell_xform * E->get()->transform;
lc.visible = E->get()->visible;
- if (!probe_data->dynamic.light_cache.has(E->get()->self) || !(probe_data->dynamic.light_cache[E->get()->self] == lc)) {
+ if (!probe_data->dynamic.light_cache.has(E->get()->self) || probe_data->dynamic.light_cache[E->get()->self] != lc) {
all_equal = false;
}
@@ -3154,7 +3237,7 @@ void VisualServerScene::render_probes() {
force_lighting = true;
}
- if (probe->invalid == false && probe->dynamic.enabled) {
+ if (!probe->invalid && probe->dynamic.enabled) {
switch (probe->dynamic.updating_stage) {
case GI_UPDATE_STAGE_CHECK: {
@@ -3233,11 +3316,13 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
bool can_cast_shadows = true;
+ bool is_animated = false;
if (p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_OFF) {
can_cast_shadows = false;
} else if (p_instance->material_override.is_valid()) {
can_cast_shadows = VSG::storage->material_casts_shadows(p_instance->material_override);
+ is_animated = VSG::storage->material_is_animated(p_instance->material_override);
} else {
if (p_instance->base_type == VS::INSTANCE_MESH) {
@@ -3252,12 +3337,15 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
if (!mat.is_valid()) {
cast_shadows = true;
- break;
- }
+ } else {
- if (VSG::storage->material_casts_shadows(mat)) {
- cast_shadows = true;
- break;
+ if (VSG::storage->material_casts_shadows(mat)) {
+ cast_shadows = true;
+ }
+
+ if (VSG::storage->material_is_animated(mat)) {
+ is_animated = true;
+ }
}
}
@@ -3279,12 +3367,15 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
if (!mat.is_valid()) {
cast_shadows = true;
- break;
- }
- if (VSG::storage->material_casts_shadows(mat)) {
- cast_shadows = true;
- break;
+ } else {
+
+ if (VSG::storage->material_casts_shadows(mat)) {
+ cast_shadows = true;
+ }
+ if (VSG::storage->material_is_animated(mat)) {
+ is_animated = true;
+ }
}
}
@@ -3296,10 +3387,10 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
RID mat = VSG::storage->immediate_get_material(p_instance->base);
- if (!mat.is_valid() || VSG::storage->material_casts_shadows(mat)) {
- can_cast_shadows = true;
- } else {
- can_cast_shadows = false;
+ can_cast_shadows = !mat.is_valid() || VSG::storage->material_casts_shadows(mat);
+
+ if (mat.is_valid() && VSG::storage->material_is_animated(mat)) {
+ is_animated = true;
}
} else if (p_instance->base_type == VS::INSTANCE_PARTICLES) {
@@ -3320,12 +3411,15 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
if (!mat.is_valid()) {
cast_shadows = true;
- break;
- }
+ } else {
- if (VSG::storage->material_casts_shadows(mat)) {
- cast_shadows = true;
- break;
+ if (VSG::storage->material_casts_shadows(mat)) {
+ cast_shadows = true;
+ }
+
+ if (VSG::storage->material_is_animated(mat)) {
+ is_animated = true;
+ }
}
}
}
@@ -3345,6 +3439,8 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
geom->can_cast_shadows = can_cast_shadows;
}
+
+ geom->material_is_animated = is_animated;
}
}
diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h
index 87e19bc6b0..629d66c6cb 100644
--- a/servers/visual/visual_server_scene.h
+++ b/servers/visual/visual_server_scene.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,7 +33,6 @@
#include "servers/visual/rasterizer.h"
-#include "core/allocators.h"
#include "core/math/geometry.h"
#include "core/math/octree.h"
#include "core/os/semaphore.h"
@@ -78,12 +77,14 @@ public:
enum Type {
PERSPECTIVE,
- ORTHOGONAL
+ ORTHOGONAL,
+ FRUSTUM
};
Type type;
float fov;
float znear, zfar;
float size;
+ Vector2 offset;
uint32_t visible_layers;
bool vaspect;
RID env;
@@ -98,6 +99,7 @@ public:
znear = 0.05;
zfar = 100;
size = 1.0;
+ offset = Vector2();
vaspect = false;
}
};
@@ -107,6 +109,7 @@ public:
virtual RID camera_create();
virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far);
virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far);
+ virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far);
virtual void camera_set_transform(RID p_camera, const Transform &p_transform);
virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers);
virtual void camera_set_environment(RID p_camera, RID p_env);
@@ -120,7 +123,6 @@ public:
VS::ScenarioDebugMode debug;
RID self;
- // well wtf, balloon allocator is slower?
Octree<Instance, true> octree;
@@ -172,7 +174,7 @@ public:
AABB transformed_aabb;
AABB *custom_aabb; // <Zylann> would using aabb directly with a bool be better?
float extra_margin;
- uint32_t object_ID;
+ uint32_t object_id;
float lod_begin;
float lod_end;
@@ -192,14 +194,9 @@ public:
singleton->instance_set_base(self, RID());
}
- virtual void base_changed() {
+ virtual void base_changed(bool p_aabb, bool p_materials) {
- singleton->_instance_queue_update(this, true, true);
- }
-
- virtual void base_material_changed() {
-
- singleton->_instance_queue_update(this, false, true);
+ singleton->_instance_queue_update(this, p_aabb, p_materials);
}
Instance() :
@@ -214,7 +211,7 @@ public:
extra_margin = 0;
- object_ID = 0;
+ object_id = 0;
visible = true;
lod_begin = 0;
@@ -247,6 +244,7 @@ public:
List<Instance *> lighting;
bool lighting_dirty;
bool can_cast_shadows;
+ bool material_is_animated;
List<Instance *> reflection_probes;
bool reflection_dirty;
@@ -261,6 +259,7 @@ public:
lighting_dirty = false;
reflection_dirty = true;
can_cast_shadows = true;
+ material_is_animated = true;
gi_probes_dirty = true;
}
};
@@ -355,6 +354,11 @@ public:
visible == p_cache.visible);
}
+ bool operator!=(const LightCache &p_cache) {
+
+ return !operator==(p_cache);
+ }
+
LightCache() {
type = VS::LIGHT_DIRECTIONAL;
@@ -453,7 +457,7 @@ public:
virtual void instance_set_scenario(RID p_instance, RID p_scenario); // from can be mesh, light, poly, area and portal so far.
virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask);
virtual void instance_set_transform(RID p_instance, const Transform &p_transform);
- virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_ID);
+ virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id);
virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight);
virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material);
virtual void instance_set_visible(RID p_instance, bool p_visible);
@@ -483,7 +487,7 @@ public:
_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
- _FORCE_INLINE_ void _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario);
+ _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario);
void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe);
void _render_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
@@ -544,7 +548,7 @@ public:
bool free(RID p_rid);
VisualServerScene();
- ~VisualServerScene();
+ virtual ~VisualServerScene();
};
#endif // VISUALSERVERSCENE_H
diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp
index b286533590..f515af4d91 100644
--- a/servers/visual/visual_server_viewport.cpp
+++ b/servers/visual/visual_server_viewport.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,9 +32,49 @@
#include "core/project_settings.h"
#include "visual_server_canvas.h"
-#include "visual_server_global.h"
+#include "visual_server_globals.h"
#include "visual_server_scene.h"
+static Transform2D _canvas_get_transform(VisualServerViewport::Viewport *p_viewport, VisualServerCanvas::Canvas *p_canvas, VisualServerViewport::Viewport::CanvasData *p_canvas_data, const Vector2 &p_vp_size) {
+
+ Transform2D xf = p_viewport->global_transform;
+
+ float scale = 1.0;
+ if (p_viewport->canvas_map.has(p_canvas->parent)) {
+ xf = xf * p_viewport->canvas_map[p_canvas->parent].transform;
+ scale = p_canvas->parent_scale;
+ }
+
+ xf = xf * p_canvas_data->transform;
+
+ if (scale != 1.0 && !VSG::canvas->disable_scale) {
+ Vector2 pivot = p_vp_size * 0.5;
+ Transform2D xfpivot;
+ xfpivot.set_origin(pivot);
+ Transform2D xfscale;
+ xfscale.scale(Vector2(scale, scale));
+
+ xf = xfpivot.affine_inverse() * xf;
+ xf = xfscale * xf;
+ xf = xfpivot * xf;
+ }
+
+ return xf;
+}
+
+void VisualServerViewport::_draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye) {
+ Ref<ARVRInterface> arvr_interface;
+ if (ARVRServer::get_singleton() != NULL) {
+ arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
+ }
+
+ if (p_viewport->use_arvr && arvr_interface.is_valid()) {
+ VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
+ } else {
+ VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
+ }
+}
+
void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye) {
/* Camera should always be BEFORE any other 3D */
@@ -45,6 +85,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
if (!p_viewport->hide_canvas && !p_viewport->disable_environment && VSG::scene->scenario_owner.owns(p_viewport->scenario)) {
VisualServerScene::Scenario *scenario = VSG::scene->scenario_owner.get(p_viewport->scenario);
+ ERR_FAIL_COND(!scenario);
if (VSG::scene_render->is_environment(scenario->environment)) {
scenario_draw_canvas_bg = VSG::scene_render->environment_get_background(scenario->environment) == VS::ENV_BG_CANVAS;
@@ -62,13 +103,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
}
if (!scenario_draw_canvas_bg && can_draw_3d) {
- Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
-
- if (p_viewport->use_arvr && arvr_interface.is_valid()) {
- VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
- } else {
- VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
- }
+ _draw_3d(p_viewport, p_eye);
}
if (!p_viewport->hide_canvas) {
@@ -86,10 +121,10 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {
- Transform2D xf = p_viewport->global_transform * E->get().transform;
-
VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas *>(E->get().canvas);
+ Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size);
+
//find lights in canvas
for (Set<RasterizerCanvas::Light *>::Element *F = canvas->lights.front(); F; F = F->next()) {
@@ -97,7 +132,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
RasterizerCanvas::Light *cl = F->get();
if (cl->enabled && cl->texture.is_valid()) {
//not super efficient..
- Size2 tsize(VSG::storage->texture_get_width(cl->texture), VSG::storage->texture_get_height(cl->texture));
+ Size2 tsize = VSG::storage->texture_size_with_proxy(cl->texture);
tsize *= cl->scale;
Vector2 offset = tsize / 2.0;
@@ -137,7 +172,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
}
}
- canvas_map[Viewport::CanvasKey(E->key(), E->get().layer)] = &E->get();
+ canvas_map[Viewport::CanvasKey(E->key(), E->get().layer, E->get().sublayer)] = &E->get();
}
if (lights_with_shadow) {
@@ -167,24 +202,20 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
RasterizerCanvas::Light *light = lights_with_shadow;
while (light) {
- VSG::canvas_render->canvas_light_shadow_buffer_update(light->shadow_buffer, light->xform_cache.affine_inverse(), light->item_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders, &light->shadow_matrix_cache);
+ VSG::canvas_render->canvas_light_shadow_buffer_update(light->shadow_buffer, light->xform_cache.affine_inverse(), light->item_shadow_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders, &light->shadow_matrix_cache);
light = light->shadows_next_ptr;
}
//VSG::canvas_render->reset_canvas();
}
- VSG::rasterizer->restore_render_target();
-
- if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().layer > scenario_canvas_max_layer) {
- Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
+ VSG::rasterizer->restore_render_target(!scenario_draw_canvas_bg && can_draw_3d);
+ if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) {
if (!can_draw_3d) {
VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas);
- } else if (p_viewport->use_arvr && arvr_interface.is_valid()) {
- VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
} else {
- VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
+ _draw_3d(p_viewport, p_eye);
}
scenario_draw_canvas_bg = false;
}
@@ -193,7 +224,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas *>(E->get()->canvas);
- Transform2D xform = p_viewport->global_transform * E->get()->transform;
+ Transform2D xform = _canvas_get_transform(p_viewport, canvas, E->get(), clip_rect.size);
RasterizerCanvas::Light *canvas_lights = NULL;
@@ -209,15 +240,11 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
VSG::canvas->render_canvas(canvas, xform, canvas_lights, lights_with_mask, clip_rect);
i++;
- if (scenario_draw_canvas_bg && E->key().layer >= scenario_canvas_max_layer) {
- Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
-
+ if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) {
if (!can_draw_3d) {
VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas);
- } else if (p_viewport->use_arvr && arvr_interface.is_valid()) {
- VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
} else {
- VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
+ _draw_3d(p_viewport, p_eye);
}
scenario_draw_canvas_bg = false;
@@ -225,17 +252,11 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
}
if (scenario_draw_canvas_bg) {
- Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
-
if (!can_draw_3d) {
VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas);
- } else if (p_viewport->use_arvr && arvr_interface.is_valid()) {
- VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
} else {
- VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
+ _draw_3d(p_viewport, p_eye);
}
-
- scenario_draw_canvas_bg = false;
}
//VSG::canvas_render->canvas_debug_viewport_shadows(lights_with_shadow);
@@ -243,11 +264,16 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
}
void VisualServerViewport::draw_viewports() {
+
// get our arvr interface in case we need it
- Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
+ Ref<ARVRInterface> arvr_interface;
+
+ if (ARVRServer::get_singleton() != NULL) {
+ arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
- // process all our active interfaces
- ARVRServer::get_singleton()->_process();
+ // process all our active interfaces
+ ARVRServer::get_singleton()->_process();
+ }
if (Engine::get_singleton()->is_editor_hint()) {
clear_color = GLOBAL_GET("rendering/environment/default_clear_color");
@@ -276,17 +302,27 @@ void VisualServerViewport::draw_viewports() {
if (vp->use_arvr && arvr_interface.is_valid()) {
// override our size, make sure it matches our required size
- Size2 size = arvr_interface->get_render_targetsize();
- VSG::storage->render_target_set_size(vp->render_target, size.x, size.y);
+ vp->size = arvr_interface->get_render_targetsize();
+ VSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y);
// render mono or left eye first
ARVRInterface::Eyes leftOrMono = arvr_interface->is_stereo() ? ARVRInterface::EYE_LEFT : ARVRInterface::EYE_MONO;
+
+ // check for an external texture destination for our left eye/mono
+ VSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(leftOrMono));
+
+ // set our render target as current
VSG::rasterizer->set_current_render_target(vp->render_target);
+
+ // and draw left eye/mono
_draw_viewport(vp, leftOrMono);
arvr_interface->commit_for_eye(leftOrMono, vp->render_target, vp->viewport_to_screen_rect);
// render right eye
if (leftOrMono == ARVRInterface::EYE_LEFT) {
+ // check for an external texture destination for our right eye
+ VSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(ARVRInterface::EYE_RIGHT));
+
// commit for eye may have changed the render target
VSG::rasterizer->set_current_render_target(vp->render_target);
@@ -297,6 +333,7 @@ void VisualServerViewport::draw_viewports() {
// and for our frame timing, mark when we've finished committing our eyes
ARVRServer::get_singleton()->_mark_commit();
} else {
+ VSG::storage->render_target_set_external_texture(vp->render_target, 0);
VSG::rasterizer->set_current_render_target(vp->render_target);
VSG::scene_render->set_debug_draw_mode(vp->debug_draw);
@@ -313,7 +350,7 @@ void VisualServerViewport::draw_viewports() {
vp->render_info[VS::VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_SURFACE_CHANGES_IN_FRAME);
vp->render_info[VS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_DRAW_CALLS_IN_FRAME);
- if (vp->viewport_to_screen_rect != Rect2()) {
+ if (vp->viewport_to_screen_rect != Rect2() && (!vp->viewport_render_direct_to_screen || !VSG::rasterizer->is_low_end())) {
//copy to screen if set as such
VSG::rasterizer->set_current_render_target(RID());
VSG::rasterizer->blit_render_target_to_screen(vp->render_target, vp->viewport_to_screen_rect, vp->viewport_to_screen);
@@ -338,6 +375,7 @@ RID VisualServerViewport::viewport_create() {
viewport->hide_canvas = false;
viewport->render_target = VSG::storage->render_target_create();
viewport->shadow_atlas = VSG::scene_render->shadow_atlas_create();
+ viewport->viewport_render_direct_to_screen = false;
return rid;
}
@@ -394,14 +432,55 @@ void VisualServerViewport::viewport_attach_to_screen(RID p_viewport, const Rect2
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
+ // If using GLES2 we can optimize this operation by rendering directly to system_fbo
+ // instead of rendering to fbo and copying to system_fbo after
+ if (VSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
+
+ VSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y);
+ VSG::storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y);
+ }
+
viewport->viewport_to_screen_rect = p_rect;
viewport->viewport_to_screen = p_screen;
}
+
+void VisualServerViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) {
+ Viewport *viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ if (p_enable == viewport->viewport_render_direct_to_screen)
+ return;
+
+ // if disabled, reset render_target size and position
+ if (!p_enable) {
+
+ VSG::storage->render_target_set_position(viewport->render_target, 0, 0);
+ VSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y);
+ }
+
+ VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable);
+ viewport->viewport_render_direct_to_screen = p_enable;
+
+ // if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unnecessary buffer allocation
+ if (VSG::rasterizer->is_low_end() && viewport->viewport_to_screen_rect != Rect2() && p_enable) {
+
+ VSG::storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y);
+ VSG::storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y);
+ }
+}
+
void VisualServerViewport::viewport_detach(RID p_viewport) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
+ // if render_direct_to_screen was used, reset size and position
+ if (VSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
+
+ VSG::storage->render_target_set_position(viewport->render_target, 0, 0);
+ VSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y);
+ }
+
viewport->viewport_to_screen_rect = Rect2();
viewport->viewport_to_screen = 0;
}
@@ -496,6 +575,7 @@ void VisualServerViewport::viewport_attach_canvas(RID p_viewport, RID p_canvas)
canvas->viewports.insert(p_viewport);
viewport->canvas_map[p_canvas] = Viewport::CanvasData();
viewport->canvas_map[p_canvas].layer = 0;
+ viewport->canvas_map[p_canvas].sublayer = 0;
viewport->canvas_map[p_canvas].canvas = canvas;
}
@@ -534,13 +614,14 @@ void VisualServerViewport::viewport_set_global_canvas_transform(RID p_viewport,
viewport->global_transform = p_transform;
}
-void VisualServerViewport::viewport_set_canvas_layer(RID p_viewport, RID p_canvas, int p_layer) {
+void VisualServerViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas));
viewport->canvas_map[p_canvas].layer = p_layer;
+ viewport->canvas_map[p_canvas].sublayer = p_sublayer;
}
void VisualServerViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size) {
diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h
index 978d6ae4ae..bdd4c1d4f2 100644
--- a/servers/visual/visual_server_viewport.h
+++ b/servers/visual/visual_server_viewport.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -58,6 +58,7 @@ public:
int viewport_to_screen;
Rect2 viewport_to_screen_rect;
+ bool viewport_render_direct_to_screen;
bool hide_scenario;
bool hide_canvas;
@@ -78,17 +79,22 @@ public:
struct CanvasKey {
- int layer;
+ int64_t stacking;
RID canvas;
bool operator<(const CanvasKey &p_canvas) const {
- if (layer == p_canvas.layer) return canvas < p_canvas.canvas;
- return layer < p_canvas.layer;
+ if (stacking == p_canvas.stacking)
+ return canvas < p_canvas.canvas;
+ return stacking < p_canvas.stacking;
+ }
+ CanvasKey() {
+ stacking = 0;
}
- CanvasKey() { layer = 0; }
- CanvasKey(const RID &p_canvas, int p_layer) {
+ CanvasKey(const RID &p_canvas, int p_layer, int p_sublayer) {
canvas = p_canvas;
- layer = p_layer;
+ int64_t sign = p_layer < 0 ? -1 : 1;
+ stacking = sign * (((int64_t)ABS(p_layer)) << 32) + p_sublayer;
}
+ int get_layer() const { return stacking >> 32; }
};
struct CanvasData {
@@ -96,6 +102,7 @@ public:
CanvasBase *canvas;
Transform2D transform;
int layer;
+ int sublayer;
};
Transform2D global_transform;
@@ -131,9 +138,8 @@ public:
if (left_to_screen == right_to_screen) {
return p_left->parent == p_right->self;
- } else {
- return right_to_screen;
}
+ return right_to_screen;
}
};
@@ -141,6 +147,7 @@ public:
private:
Color clear_color;
+ void _draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye);
void _draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye = ARVRInterface::EYE_MONO);
public:
@@ -151,6 +158,7 @@ public:
void viewport_set_size(RID p_viewport, int p_width, int p_height);
void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), int p_screen = 0);
+ void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable);
void viewport_detach(RID p_viewport);
void viewport_set_active(RID p_viewport, bool p_active);
@@ -176,7 +184,7 @@ public:
void viewport_set_transparent_background(RID p_viewport, bool p_enabled);
void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform);
- void viewport_set_canvas_layer(RID p_viewport, RID p_canvas, int p_layer);
+ void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer);
void viewport_set_shadow_atlas_size(RID p_viewport, int p_size);
void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv);
@@ -194,6 +202,7 @@ public:
bool free(RID p_rid);
VisualServerViewport();
+ virtual ~VisualServerViewport() {}
};
#endif // VISUALSERVERVIEWPORT_H
diff --git a/servers/visual/visual_server_wrap_mt.cpp b/servers/visual/visual_server_wrap_mt.cpp
index f59d8af9cb..79e4d8cbba 100644
--- a/servers/visual/visual_server_wrap_mt.cpp
+++ b/servers/visual/visual_server_wrap_mt.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index b8f86d7123..273cf728c1 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,9 +35,6 @@
#include "core/os/thread.h"
#include "servers/visual_server.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
class VisualServerWrapMT : public VisualServer {
// the real visual server
@@ -95,6 +92,7 @@ public:
FUNC1RC(uint32_t, texture_get_height, RID)
FUNC1RC(uint32_t, texture_get_depth, RID)
FUNC4(texture_set_size_override, RID, int, int, int)
+ FUNC2(texture_bind, RID, uint32_t)
FUNC3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *)
FUNC3(texture_set_detect_srgb_callback, RID, TextureDetectCallback, void *)
@@ -247,6 +245,7 @@ public:
FUNC2(light_set_negative, RID, bool)
FUNC2(light_set_cull_mask, RID, uint32_t)
FUNC2(light_set_reverse_cull_face_mode, RID, bool)
+ FUNC2(light_set_use_gi, RID, bool)
FUNC2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
FUNC2(light_omni_set_shadow_detail, RID, LightOmniShadowDetail)
@@ -271,6 +270,7 @@ public:
FUNC2(reflection_probe_set_enable_box_projection, RID, bool)
FUNC2(reflection_probe_set_enable_shadows, RID, bool)
FUNC2(reflection_probe_set_cull_mask, RID, uint32_t)
+ FUNC2(reflection_probe_set_resolution, RID, int)
/* BAKED LIGHT API */
@@ -358,6 +358,7 @@ public:
FUNCRID(camera)
FUNC4(camera_set_perspective, RID, float, float, float)
FUNC4(camera_set_orthogonal, RID, float, float, float)
+ FUNC5(camera_set_frustum, RID, float, Vector2, float, float)
FUNC2(camera_set_transform, RID, const Transform &)
FUNC2(camera_set_cull_mask, RID, uint32_t)
FUNC2(camera_set_environment, RID, RID)
@@ -377,6 +378,7 @@ public:
FUNC2(viewport_set_clear_mode, RID, ViewportClearMode)
FUNC3(viewport_attach_to_screen, RID, const Rect2 &, int)
+ FUNC2(viewport_set_render_direct_to_screen, RID, bool)
FUNC1(viewport_detach, RID)
FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode)
@@ -399,7 +401,7 @@ public:
FUNC2(viewport_set_transparent_background, RID, bool)
FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
- FUNC3(viewport_set_canvas_layer, RID, RID, int)
+ FUNC4(viewport_set_canvas_stacking, RID, RID, int, int)
FUNC2(viewport_set_shadow_atlas_size, RID, int)
FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
FUNC2(viewport_set_msaa, RID, ViewportMSAA)
@@ -420,23 +422,25 @@ public:
FUNC2(environment_set_background, RID, EnvironmentBG)
FUNC2(environment_set_sky, RID, RID)
FUNC2(environment_set_sky_custom_fov, RID, float)
+ FUNC2(environment_set_sky_orientation, RID, const Basis &)
FUNC2(environment_set_bg_color, RID, const Color &)
FUNC2(environment_set_bg_energy, RID, float)
FUNC2(environment_set_canvas_max_layer, RID, int)
FUNC4(environment_set_ambient_light, RID, const Color &, float, float)
+ FUNC2(environment_set_camera_feed_id, RID, int)
FUNC7(environment_set_ssr, RID, bool, int, float, float, float, bool)
FUNC13(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, const Color &, EnvironmentSSAOQuality, EnvironmentSSAOBlur, float)
FUNC6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
FUNC6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
- FUNC10(environment_set_glow, RID, bool, int, float, float, float, EnvironmentGlowBlendMode, float, float, bool)
+ FUNC11(environment_set_glow, RID, bool, int, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool)
FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
FUNC6(environment_set_adjustment, RID, bool, float, float, float, RID)
FUNC5(environment_set_fog, RID, bool, const Color &, const Color &, float)
- FUNC6(environment_set_fog_depth, RID, bool, float, float, bool, float)
+ FUNC7(environment_set_fog_depth, RID, bool, float, float, float, bool, float)
FUNC5(environment_set_fog_height, RID, bool, float, float, float)
FUNCRID(scenario)
@@ -484,6 +488,8 @@ public:
FUNCRID(canvas)
FUNC3(canvas_set_item_mirroring, RID, RID, const Point2 &)
FUNC2(canvas_set_modulate, RID, const Color &)
+ FUNC3(canvas_set_parent, RID, RID, float)
+ FUNC1(canvas_set_disable_scale, bool)
FUNCRID(canvas_item)
FUNC2(canvas_item_set_parent, RID, RID)
@@ -513,9 +519,9 @@ public:
FUNC7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID)
FUNC7(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, bool)
FUNC10(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID)
- FUNC4(canvas_item_add_mesh, RID, const RID &, RID, RID)
+ FUNC6(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID)
FUNC4(canvas_item_add_multimesh, RID, RID, RID, RID)
- FUNC6(canvas_item_add_particles, RID, RID, RID, RID, int, int)
+ FUNC4(canvas_item_add_particles, RID, RID, RID, RID)
FUNC2(canvas_item_add_set_transform, RID, const Transform2D &)
FUNC2(canvas_item_add_clip_ignore, RID, bool)
FUNC2(canvas_item_set_sort_children_by_y, RID, bool)
@@ -594,7 +600,7 @@ public:
return visual_server->get_render_info(p_info);
}
- FUNC3(set_boot_image, const Ref<Image> &, const Color &, bool)
+ FUNC4(set_boot_image, const Ref<Image> &, const Color &, bool, bool)
FUNC1(set_default_clear_color, const Color &)
FUNC0R(RID, get_test_cube)
@@ -608,6 +614,10 @@ public:
static void set_use_vsync_callback(bool p_enable);
+ virtual bool is_low_end() const {
+ return visual_server->is_low_end();
+ }
+
VisualServerWrapMT(VisualServer *p_contained, bool p_create_thread);
~VisualServerWrapMT();
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index 18a239b019..2e1f524362 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -343,7 +343,7 @@ RID VisualServer::get_white_texture() {
#define SMALL_VEC2 Vector2(0.00001, 0.00001)
#define SMALL_VEC3 Vector3(0.00001, 0.00001, 0.00001)
-Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> r_bone_aabb) {
+Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> &r_bone_aabb) {
PoolVector<uint8_t>::Write vw = r_vertex_array.write();
@@ -776,7 +776,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
continue; //break;
ERR_FAIL_INDEX_V(idx, total_bones, ERR_INVALID_DATA);
- if (bptr->size.x < 0) {
+ if (bptr[idx].size.x < 0) {
//first
bptr[idx] = AABB(v, SMALL_VEC3);
any_valid = true;
@@ -917,7 +917,7 @@ uint32_t VisualServer::mesh_surface_make_offsets_from_format(uint32_t p_format,
}
r_offsets[i] = elem_size;
continue;
- } break;
+ }
default: {
ERR_FAIL_V(0);
}
@@ -953,15 +953,12 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
switch (var.get_type()) {
case Variant::POOL_VECTOR2_ARRAY: {
PoolVector<Vector2> v2 = var;
- array_len = v2.size();
} break;
case Variant::POOL_VECTOR3_ARRAY: {
PoolVector<Vector3> v3 = var;
- array_len = v3.size();
} break;
default: {
Array v = var;
- array_len = v.size();
} break;
}
@@ -1121,7 +1118,7 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
}
offsets[i] = elem_size;
continue;
- } break;
+ }
default: {
ERR_FAIL();
}
@@ -1148,11 +1145,7 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
Vector<AABB> bone_aabb;
Error err = _surface_set_data(p_arrays, format, offsets, total_elem_size, vertex_array, array_len, index_array, index_array_len, aabb, bone_aabb);
-
- if (err) {
- ERR_EXPLAIN("Invalid array format for surface");
- ERR_FAIL_COND(err != OK);
- }
+ ERR_FAIL_COND_MSG(err, "Invalid array format for surface.");
Vector<PoolVector<uint8_t> > blend_shape_data;
@@ -1163,12 +1156,9 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
PoolVector<uint8_t> noindex;
AABB laabb;
- Error err = _surface_set_data(p_blend_shapes[i], format & ~ARRAY_FORMAT_INDEX, offsets, total_elem_size, vertex_array_shape, array_len, noindex, 0, laabb, bone_aabb);
+ Error err2 = _surface_set_data(p_blend_shapes[i], format & ~ARRAY_FORMAT_INDEX, offsets, total_elem_size, vertex_array_shape, array_len, noindex, 0, laabb, bone_aabb);
aabb.merge_with(laabb);
- if (err) {
- ERR_EXPLAIN("Invalid blend shape array format for surface");
- ERR_FAIL_COND(err != OK);
- }
+ ERR_FAIL_COND_MSG(err2 != OK, "Invalid blend shape array format for surface.");
blend_shape_data.push_back(vertex_array_shape);
}
@@ -1289,7 +1279,7 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
}
offsets[i] = elem_size;
continue;
- } break;
+ }
default: {
ERR_FAIL_V(Array());
}
@@ -1676,6 +1666,7 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("texture_set_path", "texture", "path"), &VisualServer::texture_set_path);
ClassDB::bind_method(D_METHOD("texture_get_path", "texture"), &VisualServer::texture_get_path);
ClassDB::bind_method(D_METHOD("texture_set_shrink_all_x2_on_set_data", "shrink"), &VisualServer::texture_set_shrink_all_x2_on_set_data);
+ ClassDB::bind_method(D_METHOD("texture_bind", "texture", "number"), &VisualServer::texture_bind);
ClassDB::bind_method(D_METHOD("texture_debug_usage"), &VisualServer::_texture_debug_usage_bind);
ClassDB::bind_method(D_METHOD("textures_keep_original", "enable"), &VisualServer::textures_keep_original);
@@ -1780,6 +1771,7 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("light_set_negative", "light", "enable"), &VisualServer::light_set_negative);
ClassDB::bind_method(D_METHOD("light_set_cull_mask", "light", "mask"), &VisualServer::light_set_cull_mask);
ClassDB::bind_method(D_METHOD("light_set_reverse_cull_face_mode", "light", "enabled"), &VisualServer::light_set_reverse_cull_face_mode);
+ ClassDB::bind_method(D_METHOD("light_set_use_gi", "light", "enabled"), &VisualServer::light_set_use_gi);
ClassDB::bind_method(D_METHOD("light_omni_set_shadow_mode", "light", "mode"), &VisualServer::light_omni_set_shadow_mode);
ClassDB::bind_method(D_METHOD("light_omni_set_shadow_detail", "light", "detail"), &VisualServer::light_omni_set_shadow_detail);
@@ -1863,6 +1855,7 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("camera_create"), &VisualServer::camera_create);
ClassDB::bind_method(D_METHOD("camera_set_perspective", "camera", "fovy_degrees", "z_near", "z_far"), &VisualServer::camera_set_perspective);
ClassDB::bind_method(D_METHOD("camera_set_orthogonal", "camera", "size", "z_near", "z_far"), &VisualServer::camera_set_orthogonal);
+ ClassDB::bind_method(D_METHOD("camera_set_frustum", "camera", "size", "offset", "z_near", "z_far"), &VisualServer::camera_set_frustum);
ClassDB::bind_method(D_METHOD("camera_set_transform", "camera", "transform"), &VisualServer::camera_set_transform);
ClassDB::bind_method(D_METHOD("camera_set_cull_mask", "camera", "layers"), &VisualServer::camera_set_cull_mask);
ClassDB::bind_method(D_METHOD("camera_set_environment", "camera", "env"), &VisualServer::camera_set_environment);
@@ -1874,6 +1867,7 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_set_active", "viewport", "active"), &VisualServer::viewport_set_active);
ClassDB::bind_method(D_METHOD("viewport_set_parent_viewport", "viewport", "parent_viewport"), &VisualServer::viewport_set_parent_viewport);
ClassDB::bind_method(D_METHOD("viewport_attach_to_screen", "viewport", "rect", "screen"), &VisualServer::viewport_attach_to_screen, DEFVAL(Rect2()), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("viewport_set_render_direct_to_screen", "viewport", "enabled"), &VisualServer::viewport_set_render_direct_to_screen);
ClassDB::bind_method(D_METHOD("viewport_detach", "viewport"), &VisualServer::viewport_detach);
ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &VisualServer::viewport_set_update_mode);
ClassDB::bind_method(D_METHOD("viewport_set_vflip", "viewport", "enabled"), &VisualServer::viewport_set_vflip);
@@ -1890,7 +1884,7 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_set_canvas_transform", "viewport", "canvas", "offset"), &VisualServer::viewport_set_canvas_transform);
ClassDB::bind_method(D_METHOD("viewport_set_transparent_background", "viewport", "enabled"), &VisualServer::viewport_set_transparent_background);
ClassDB::bind_method(D_METHOD("viewport_set_global_canvas_transform", "viewport", "transform"), &VisualServer::viewport_set_global_canvas_transform);
- ClassDB::bind_method(D_METHOD("viewport_set_canvas_layer", "viewport", "canvas", "layer"), &VisualServer::viewport_set_canvas_layer);
+ ClassDB::bind_method(D_METHOD("viewport_set_canvas_stacking", "viewport", "canvas", "layer", "sublayer"), &VisualServer::viewport_set_canvas_stacking);
ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size"), &VisualServer::viewport_set_shadow_atlas_size);
ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &VisualServer::viewport_set_shadow_atlas_quadrant_subdivision);
ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &VisualServer::viewport_set_msaa);
@@ -1903,25 +1897,28 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("environment_set_background", "env", "bg"), &VisualServer::environment_set_background);
ClassDB::bind_method(D_METHOD("environment_set_sky", "env", "sky"), &VisualServer::environment_set_sky);
ClassDB::bind_method(D_METHOD("environment_set_sky_custom_fov", "env", "scale"), &VisualServer::environment_set_sky_custom_fov);
+ ClassDB::bind_method(D_METHOD("environment_set_sky_orientation", "env", "orientation"), &VisualServer::environment_set_sky_orientation);
ClassDB::bind_method(D_METHOD("environment_set_bg_color", "env", "color"), &VisualServer::environment_set_bg_color);
ClassDB::bind_method(D_METHOD("environment_set_bg_energy", "env", "energy"), &VisualServer::environment_set_bg_energy);
ClassDB::bind_method(D_METHOD("environment_set_canvas_max_layer", "env", "max_layer"), &VisualServer::environment_set_canvas_max_layer);
ClassDB::bind_method(D_METHOD("environment_set_ambient_light", "env", "color", "energy", "sky_contibution"), &VisualServer::environment_set_ambient_light, DEFVAL(1.0), DEFVAL(0.0));
ClassDB::bind_method(D_METHOD("environment_set_dof_blur_near", "env", "enable", "distance", "transition", "far_amount", "quality"), &VisualServer::environment_set_dof_blur_near);
ClassDB::bind_method(D_METHOD("environment_set_dof_blur_far", "env", "enable", "distance", "transition", "far_amount", "quality"), &VisualServer::environment_set_dof_blur_far);
- ClassDB::bind_method(D_METHOD("environment_set_glow", "env", "enable", "level_flags", "intensity", "strength", "bloom_threshold", "blend_mode", "hdr_bleed_threshold", "hdr_bleed_scale", "bicubic_upscale"), &VisualServer::environment_set_glow);
+ ClassDB::bind_method(D_METHOD("environment_set_glow", "env", "enable", "level_flags", "intensity", "strength", "bloom_threshold", "blend_mode", "hdr_bleed_threshold", "hdr_bleed_scale", "hdr_luminance_cap", "bicubic_upscale"), &VisualServer::environment_set_glow);
ClassDB::bind_method(D_METHOD("environment_set_tonemap", "env", "tone_mapper", "exposure", "white", "auto_exposure", "min_luminance", "max_luminance", "auto_exp_speed", "auto_exp_grey"), &VisualServer::environment_set_tonemap);
ClassDB::bind_method(D_METHOD("environment_set_adjustment", "env", "enable", "brightness", "contrast", "saturation", "ramp"), &VisualServer::environment_set_adjustment);
ClassDB::bind_method(D_METHOD("environment_set_ssr", "env", "enable", "max_steps", "fade_in", "fade_out", "depth_tolerance", "roughness"), &VisualServer::environment_set_ssr);
ClassDB::bind_method(D_METHOD("environment_set_ssao", "env", "enable", "radius", "intensity", "radius2", "intensity2", "bias", "light_affect", "ao_channel_affect", "color", "quality", "blur", "bilateral_sharpness"), &VisualServer::environment_set_ssao);
ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "color", "sun_color", "sun_amount"), &VisualServer::environment_set_fog);
- ClassDB::bind_method(D_METHOD("environment_set_fog_depth", "env", "enable", "depth_begin", "depth_curve", "transmit", "transmit_curve"), &VisualServer::environment_set_fog_depth);
+
+ ClassDB::bind_method(D_METHOD("environment_set_fog_depth", "env", "enable", "depth_begin", "depth_end", "depth_curve", "transmit", "transmit_curve"), &VisualServer::environment_set_fog_depth);
+
ClassDB::bind_method(D_METHOD("environment_set_fog_height", "env", "enable", "min_height", "max_height", "height_curve"), &VisualServer::environment_set_fog_height);
ClassDB::bind_method(D_METHOD("scenario_create"), &VisualServer::scenario_create);
ClassDB::bind_method(D_METHOD("scenario_set_debug", "scenario", "debug_mode"), &VisualServer::scenario_set_debug);
ClassDB::bind_method(D_METHOD("scenario_set_environment", "scenario", "environment"), &VisualServer::scenario_set_environment);
- ClassDB::bind_method(D_METHOD("scenario_set_reflection_atlas_size", "scenario", "p_size", "subdiv"), &VisualServer::scenario_set_reflection_atlas_size);
+ ClassDB::bind_method(D_METHOD("scenario_set_reflection_atlas_size", "scenario", "size", "subdiv"), &VisualServer::scenario_set_reflection_atlas_size);
ClassDB::bind_method(D_METHOD("scenario_set_fallback_environment", "scenario", "environment"), &VisualServer::scenario_set_fallback_environment);
#ifndef _3D_DISABLED
@@ -1976,9 +1973,9 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width", "normal_map"), &VisualServer::canvas_item_add_primitive, DEFVAL(1.0), DEFVAL(RID()));
ClassDB::bind_method(D_METHOD("canvas_item_add_polygon", "item", "points", "colors", "uvs", "texture", "normal_map", "antialiased"), &VisualServer::canvas_item_add_polygon, DEFVAL(Vector<Point2>()), DEFVAL(RID()), DEFVAL(RID()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_triangle_array", "item", "indices", "points", "colors", "uvs", "bones", "weights", "texture", "count", "normal_map"), &VisualServer::canvas_item_add_triangle_array, DEFVAL(Vector<Point2>()), DEFVAL(Vector<int>()), DEFVAL(Vector<float>()), DEFVAL(RID()), DEFVAL(-1), DEFVAL(RID()));
- ClassDB::bind_method(D_METHOD("canvas_item_add_mesh", "item", "mesh", "texture", "normal_map"), &VisualServer::canvas_item_add_mesh, DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_mesh", "item", "mesh", "transform", "modulate", "texture", "normal_map"), &VisualServer::canvas_item_add_mesh, DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1)), DEFVAL(RID()), DEFVAL(RID()));
ClassDB::bind_method(D_METHOD("canvas_item_add_multimesh", "item", "mesh", "texture", "normal_map"), &VisualServer::canvas_item_add_multimesh, DEFVAL(RID()));
- ClassDB::bind_method(D_METHOD("canvas_item_add_particles", "item", "particles", "texture", "normal_map", "h_frames", "v_frames"), &VisualServer::canvas_item_add_particles);
+ ClassDB::bind_method(D_METHOD("canvas_item_add_particles", "item", "particles", "texture", "normal_map"), &VisualServer::canvas_item_add_particles);
ClassDB::bind_method(D_METHOD("canvas_item_add_set_transform", "item", "transform"), &VisualServer::canvas_item_add_set_transform);
ClassDB::bind_method(D_METHOD("canvas_item_add_clip_ignore", "item", "ignore"), &VisualServer::canvas_item_add_clip_ignore);
ClassDB::bind_method(D_METHOD("canvas_item_set_sort_children_by_y", "item", "enabled"), &VisualServer::canvas_item_set_sort_children_by_y);
@@ -2041,7 +2038,7 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_test_texture"), &VisualServer::get_test_texture);
ClassDB::bind_method(D_METHOD("get_white_texture"), &VisualServer::get_white_texture);
- ClassDB::bind_method(D_METHOD("set_boot_image", "image", "color", "scale"), &VisualServer::set_boot_image);
+ ClassDB::bind_method(D_METHOD("set_boot_image", "image", "color", "scale", "use_filter"), &VisualServer::set_boot_image, DEFVAL(true));
ClassDB::bind_method(D_METHOD("set_default_clear_color", "color"), &VisualServer::set_default_clear_color);
ClassDB::bind_method(D_METHOD("has_feature", "feature"), &VisualServer::has_feature);
@@ -2257,6 +2254,9 @@ void VisualServer::_bind_methods() {
BIND_ENUM_CONSTANT(MULTIMESH_COLOR_NONE);
BIND_ENUM_CONSTANT(MULTIMESH_COLOR_8BIT);
BIND_ENUM_CONSTANT(MULTIMESH_COLOR_FLOAT);
+ BIND_ENUM_CONSTANT(MULTIMESH_CUSTOM_DATA_NONE);
+ BIND_ENUM_CONSTANT(MULTIMESH_CUSTOM_DATA_8BIT);
+ BIND_ENUM_CONSTANT(MULTIMESH_CUSTOM_DATA_FLOAT);
BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ONCE);
BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ALWAYS);
@@ -2283,7 +2283,7 @@ void VisualServer::_bind_methods() {
BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_REPLACE);
BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_LINEAR);
- BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_REINHARDT);
+ BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_REINHARD);
BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_FILMIC);
BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_ACES);
@@ -2362,14 +2362,15 @@ VisualServer::VisualServer() {
//ERR_FAIL_COND(singleton);
singleton = this;
- GLOBAL_DEF("rendering/vram_compression/import_bptc", false);
- GLOBAL_DEF("rendering/vram_compression/import_s3tc", true);
- GLOBAL_DEF("rendering/vram_compression/import_etc", false);
- GLOBAL_DEF("rendering/vram_compression/import_etc2", true);
- GLOBAL_DEF("rendering/vram_compression/import_pvrtc", false);
+ GLOBAL_DEF_RST("rendering/vram_compression/import_bptc", false);
+ GLOBAL_DEF_RST("rendering/vram_compression/import_s3tc", true);
+ GLOBAL_DEF_RST("rendering/vram_compression/import_etc", false);
+ GLOBAL_DEF_RST("rendering/vram_compression/import_etc2", true);
+ GLOBAL_DEF_RST("rendering/vram_compression/import_pvrtc", false);
GLOBAL_DEF("rendering/quality/directional_shadow/size", 4096);
GLOBAL_DEF("rendering/quality/directional_shadow/size.mobile", 2048);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/directional_shadow/size", PropertyInfo(Variant::INT, "rendering/quality/directional_shadow/size", PROPERTY_HINT_RANGE, "256,16384"));
GLOBAL_DEF("rendering/quality/shadow_atlas/size", 4096);
GLOBAL_DEF("rendering/quality/shadow_atlas/size.mobile", 2048);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/size", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/size", PROPERTY_HINT_RANGE, "256,16384"));
@@ -2399,7 +2400,9 @@ VisualServer::VisualServer() {
GLOBAL_DEF("rendering/quality/shading/force_blinn_over_ggx.mobile", true);
GLOBAL_DEF("rendering/quality/depth_prepass/enable", true);
- GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno");
+ GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple");
+
+ GLOBAL_DEF("rendering/quality/filters/use_nearest_mipmap_filter", false);
}
VisualServer::~VisualServer() {
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 6a1f2c3550..5e6c4d9b1e 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -39,9 +39,6 @@
#include "core/rid.h"
#include "core/variant.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
class VisualServer : public Object {
GDCLASS(VisualServer, Object);
@@ -61,7 +58,7 @@ protected:
RID white_texture;
RID test_material;
- Error _surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> r_bone_aabb);
+ Error _surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> &r_bone_aabb);
static VisualServer *(*create_func)();
static void _bind_methods();
@@ -140,6 +137,7 @@ public:
virtual uint32_t texture_get_height(RID p_texture) const = 0;
virtual uint32_t texture_get_depth(RID p_texture) const = 0;
virtual void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth_3d) = 0;
+ virtual void texture_bind(RID p_texture, uint32_t p_texture_no) = 0;
virtual void texture_set_path(RID p_texture, const String &p_path) = 0;
virtual String texture_get_path(RID p_texture) const = 0;
@@ -434,6 +432,7 @@ public:
virtual void light_set_negative(RID p_light, bool p_enable) = 0;
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0;
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0;
+ virtual void light_set_use_gi(RID p_light, bool p_enable) = 0;
// omni light
enum LightOmniShadowMode {
@@ -490,6 +489,7 @@ public:
virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0;
virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0;
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
+ virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
/* GI PROBE API */
@@ -582,6 +582,7 @@ public:
virtual RID camera_create() = 0;
virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) = 0;
virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) = 0;
+ virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) = 0;
virtual void camera_set_transform(RID p_camera, const Transform &p_transform) = 0;
virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers) = 0;
virtual void camera_set_environment(RID p_camera, RID p_env) = 0;
@@ -606,6 +607,7 @@ public:
virtual void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) = 0;
virtual void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), int p_screen = 0) = 0;
+ virtual void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) = 0;
virtual void viewport_detach(RID p_viewport) = 0;
enum ViewportUpdateMode {
@@ -643,7 +645,7 @@ public:
virtual void viewport_set_transparent_background(RID p_viewport, bool p_enabled) = 0;
virtual void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) = 0;
- virtual void viewport_set_canvas_layer(RID p_viewport, RID p_canvas, int p_layer) = 0;
+ virtual void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) = 0;
virtual void viewport_set_shadow_atlas_size(RID p_viewport, int p_size) = 0;
virtual void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) = 0;
@@ -702,16 +704,19 @@ public:
ENV_BG_COLOR_SKY,
ENV_BG_CANVAS,
ENV_BG_KEEP,
+ ENV_BG_CAMERA_FEED,
ENV_BG_MAX
};
virtual void environment_set_background(RID p_env, EnvironmentBG p_bg) = 0;
virtual void environment_set_sky(RID p_env, RID p_sky) = 0;
virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0;
+ virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0;
virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0;
virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0;
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;
virtual void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0) = 0;
+ virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0;
//set default SSAO options
//set default SSR options
@@ -732,11 +737,11 @@ public:
GLOW_BLEND_MODE_SOFTLIGHT,
GLOW_BLEND_MODE_REPLACE,
};
- virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, bool p_bicubic_upscale) = 0;
+ virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) = 0;
enum EnvironmentToneMapper {
ENV_TONE_MAPPER_LINEAR,
- ENV_TONE_MAPPER_REINHARDT,
+ ENV_TONE_MAPPER_REINHARD,
ENV_TONE_MAPPER_FILMIC,
ENV_TONE_MAPPER_ACES
};
@@ -762,7 +767,7 @@ public:
virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, EnvironmentSSAOQuality p_quality, EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0;
virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) = 0;
- virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0;
+ virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0;
virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0;
/* SCENARIO API */
@@ -809,7 +814,7 @@ public:
virtual void instance_set_scenario(RID p_instance, RID p_scenario) = 0; // from can be mesh, light, poly, area and portal so far.
virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask) = 0;
virtual void instance_set_transform(RID p_instance, const Transform &p_transform) = 0;
- virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_ID) = 0;
+ virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id) = 0;
virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) = 0;
virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material) = 0;
virtual void instance_set_visible(RID p_instance, bool p_visible) = 0;
@@ -857,6 +862,9 @@ public:
virtual RID canvas_create() = 0;
virtual void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring) = 0;
virtual void canvas_set_modulate(RID p_canvas, const Color &p_color) = 0;
+ virtual void canvas_set_parent(RID p_canvas, RID p_parent, float p_scale) = 0;
+
+ virtual void canvas_set_disable_scale(bool p_disable) = 0;
virtual RID canvas_item_create() = 0;
virtual void canvas_item_set_parent(RID p_item, RID p_parent) = 0;
@@ -892,9 +900,9 @@ public:
virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID()) = 0;
virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false) = 0;
virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID()) = 0;
- virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture = RID(), RID p_normal_map = RID()) = 0;
+ virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID()) = 0;
virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID()) = 0;
- virtual void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map, int p_h_frames, int p_v_frames) = 0;
+ virtual void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map) = 0;
virtual void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) = 0;
virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore) = 0;
virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) = 0;
@@ -1020,7 +1028,7 @@ public:
virtual void mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry::MeshData &p_mesh_data);
virtual void mesh_add_surface_from_planes(RID p_mesh, const PoolVector<Plane> &p_planes);
- virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale) = 0;
+ virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) = 0;
virtual void set_default_clear_color(const Color &p_color) = 0;
enum Features {
@@ -1036,6 +1044,8 @@ public:
virtual void call_set_use_vsync(bool p_enable) = 0;
+ virtual bool is_low_end() const = 0;
+
VisualServer();
virtual ~VisualServer();
};