summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/audio_server.cpp9
-rw-r--r--servers/audio_server.h5
-rw-r--r--servers/physics_2d/collision_solver_2d_sw.cpp11
-rw-r--r--servers/physics_2d/collision_solver_2d_sw.h2
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp24
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h3
-rw-r--r--servers/physics_2d/physics_2d_server_wrap_mt.h10
-rw-r--r--servers/physics_2d/space_2d_sw.cpp163
-rw-r--r--servers/physics_2d/space_2d_sw.h3
-rw-r--r--servers/physics_2d_server.h17
-rw-r--r--servers/visual/rasterizer.h1
-rw-r--r--servers/visual/shader_language.cpp20
-rw-r--r--servers/visual/shader_language.h6
-rw-r--r--servers/visual/shader_types.cpp83
-rw-r--r--servers/visual/shader_types.h6
-rw-r--r--servers/visual/visual_server_raster.cpp5
-rw-r--r--servers/visual/visual_server_raster.h2
-rw-r--r--servers/visual/visual_server_wrap_mt.h2
-rw-r--r--servers/visual_server.h1
19 files changed, 301 insertions, 72 deletions
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index f2df7119e7..69c1318a48 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -234,6 +234,13 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) {
todo -= to_copy;
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;
+ }
}
void AudioServer::_mix_step() {
@@ -1178,6 +1185,8 @@ AudioServer::AudioServer() {
mix_frames = 0;
channel_count = 0;
to_mix = 0;
+ output_latency = 0;
+ output_latency_ticks = 0;
}
AudioServer::~AudioServer() {
diff --git a/servers/audio_server.h b/servers/audio_server.h
index b7fcd9c093..f928acc7b5 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -190,6 +190,9 @@ private:
Mutex *audio_data_lock;
+ float output_latency;
+ uint64_t output_latency_ticks;
+
void init_channels_and_buffers();
void _mix_step();
@@ -306,6 +309,8 @@ public:
String get_device();
void set_device(String device);
+ float get_output_latency() { return output_latency; }
+
AudioServer();
virtual ~AudioServer();
};
diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/collision_solver_2d_sw.cpp
index efee98a35a..6ce019f36e 100644
--- a/servers/physics_2d/collision_solver_2d_sw.cpp
+++ b/servers/physics_2d/collision_solver_2d_sw.cpp
@@ -72,7 +72,7 @@ bool CollisionSolver2DSW::solve_static_line(const Shape2DSW *p_shape_A, const Tr
return found;
}
-bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis) {
+bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis) {
const RayShape2DSW *ray = static_cast<const RayShape2DSW *>(p_shape_A);
if (p_shape_B->get_type() == Physics2DServer::SHAPE_RAY)
@@ -80,6 +80,11 @@ bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A, const Transf
Vector2 from = p_transform_A.get_origin();
Vector2 to = from + p_transform_A[1] * ray->get_length();
+ if (p_motion_A != Vector2()) {
+ //not the best but should be enough
+ Vector2 normal = (to - from).normalized();
+ to += normal * MAX(0.0, normal.dot(p_motion_A));
+ }
Vector2 support_A = to;
Transform2D invb = p_transform_B.affine_inverse();
@@ -270,9 +275,9 @@ bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p
}
if (swap) {
- return solve_raycast(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, sep_axis);
+ return solve_raycast(p_shape_B, p_motion_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, sep_axis);
} else {
- return solve_raycast(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, sep_axis);
+ return solve_raycast(p_shape_A, p_motion_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, sep_axis);
}
} else if (concave_B) {
diff --git a/servers/physics_2d/collision_solver_2d_sw.h b/servers/physics_2d/collision_solver_2d_sw.h
index e39c41fb75..6faa166115 100644
--- a/servers/physics_2d/collision_solver_2d_sw.h
+++ b/servers/physics_2d/collision_solver_2d_sw.h
@@ -41,7 +41,7 @@ private:
static bool solve_static_line(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
static void concave_callback(void *p_userdata, Shape2DSW *p_convex);
static bool solve_concave(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis = NULL, real_t p_margin_A = 0, real_t p_margin_B = 0);
- static bool solve_raycast(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis = NULL);
+ static bool solve_raycast(const Shape2DSW *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis = NULL);
public:
static bool solve(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, Vector2 *sep_axis = NULL, real_t p_margin_A = 0, real_t p_margin_B = 0);
diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp
index a14fed8184..a473e0beb2 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -962,22 +962,40 @@ void Physics2DServerSW::body_set_pickable(RID p_body, bool p_pickable) {
body->set_pickable(p_pickable);
}
-bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, MotionResult *r_result) {
+bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, MotionResult *r_result, bool p_exclude_raycast_shapes) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
ERR_FAIL_COND_V(body->get_space()->is_locked(), false);
- return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result);
+ return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes);
+}
+
+int Physics2DServerSW::body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin) {
+
+ Body2DSW *body = body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, false);
+ ERR_FAIL_COND_V(!body->get_space(), false);
+ ERR_FAIL_COND_V(body->get_space()->is_locked(), false);
+
+ return body->get_space()->test_body_ray_separation(body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin);
}
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);
+ }
+
+ if (!body_owner.owns(p_body))
+ return NULL;
+
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body, NULL);
- if ((using_threads && !doing_sync) || body->get_space()->is_locked()) {
+ 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);
diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h
index 036eb934e1..e5961b9011 100644
--- a/servers/physics_2d/physics_2d_server_sw.h
+++ b/servers/physics_2d/physics_2d_server_sw.h
@@ -232,7 +232,8 @@ public:
virtual void body_set_pickable(RID p_body, bool p_pickable);
- virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL);
+ virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true);
+ virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001);
// this function only works on physics process, errors and returns null otherwise
virtual Physics2DDirectBodyState *body_get_direct_state(RID p_body);
diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h
index a15e8bde8b..3119b930d7 100644
--- a/servers/physics_2d/physics_2d_server_wrap_mt.h
+++ b/servers/physics_2d/physics_2d_server_wrap_mt.h
@@ -245,10 +245,16 @@ public:
FUNC2(body_set_pickable, RID, bool);
- bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL) {
+ bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true) {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
- return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result);
+ return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes);
+ }
+
+ int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001) {
+
+ ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
+ return physics_2d_server->body_test_ray_separation(p_body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin);
}
// this function only works on physics process, errors and returns null otherwise
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 0e1f74d8d0..6e45951f42 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -487,7 +487,156 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) {
return amount;
}
-bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, Physics2DServer::MotionResult *r_result) {
+int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, Physics2DServer::SeparationResult *r_results, int p_result_max, real_t p_margin) {
+
+ Rect2 body_aabb;
+
+ for (int i = 0; i < p_body->get_shape_count(); i++) {
+
+ if (i == 0)
+ body_aabb = p_body->get_shape_aabb(i);
+ else
+ body_aabb = body_aabb.merge(p_body->get_shape_aabb(i));
+ }
+
+ // 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);
+
+ Transform2D body_transform = p_transform;
+
+ for (int i = 0; i < p_result_max; i++) {
+ //reset results
+ r_results[i].collision_depth = 0;
+ }
+
+ int rays_found = 0;
+
+ {
+ // raycast AND separate
+
+ const int max_results = 32;
+ int recover_attempts = 4;
+ Vector2 sr[max_results * 2];
+ Physics2DServerSW::CollCbkData cbk;
+ cbk.max = max_results;
+ Physics2DServerSW::CollCbkData *cbkptr = &cbk;
+ CollisionSolver2DSW::CallbackResult cbkres = Physics2DServerSW::_shape_col_cbk;
+
+ do {
+
+ Vector2 recover_motion;
+
+ 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))
+ continue;
+
+ Shape2DSW *body_shape = p_body->get_shape(j);
+
+ if (body_shape->get_type() != Physics2DServer::SHAPE_RAY)
+ continue;
+
+ Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j);
+
+ for (int i = 0; i < amount; i++) {
+
+ const CollisionObject2DSW *col_obj = intersection_query_results[i];
+ int shape_idx = intersection_query_subindex_results[i];
+
+ cbk.amount = 0;
+ cbk.ptr = sr;
+ cbk.invalid_by_dir = 0;
+
+ 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;
+ }
+ }
+
+ 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.invalid_by_dir = 0;
+
+ } else {
+ 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 (cbk.amount > 0) {
+ collided = true;
+ }
+
+ if (ray_index < p_result_max) {
+ Physics2DServer::SeparationResult &result = r_results[ray_index];
+
+ for (int k = 0; k < cbk.amount; k++) {
+ Vector2 a = sr[k * 2 + 0];
+ Vector2 b = sr[k * 2 + 1];
+
+ recover_motion += (b - a) * 0.4;
+
+ float depth = a.distance_to(b);
+ if (depth > result.collision_depth) {
+
+ result.collision_depth = depth;
+ result.collision_point = b;
+ result.collision_normal = (b - a).normalized();
+ result.collision_local_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);
+ if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
+ Body2DSW *body = (Body2DSW *)col_obj;
+
+ Vector2 rel_vec = b - body->get_transform().get_origin();
+ result.collider_velocity = Vector2(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ray_index++;
+ }
+
+ rays_found = MAX(ray_index, rays_found);
+
+ if (!collided || recover_motion == Vector2()) {
+ break;
+ }
+
+ body_transform.elements[2] += recover_motion;
+ body_aabb.position += recover_motion;
+
+ recover_attempts--;
+ } while (recover_attempts);
+ }
+
+ //optimize results (remove non colliding)
+ for (int i = 0; i < rays_found; i++) {
+ if (r_results[i].collision_depth == 0) {
+ rays_found--;
+ SWAP(r_results[i], r_results[rays_found]);
+ }
+ }
+
+ r_recover_motion = body_transform.elements[2] - p_transform.elements[2];
+ return rays_found;
+}
+
+bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, Physics2DServer::MotionResult *r_result, bool p_exclude_raycast_shapes) {
//give me back regular physics engine logic
//this is madness
@@ -547,8 +696,12 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
if (p_body->is_shape_set_as_disabled(j))
continue;
- Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j);
Shape2DSW *body_shape = p_body->get_shape(j);
+ if (p_exclude_raycast_shapes && body_shape->get_type() == Physics2DServer::SHAPE_RAY) {
+ continue;
+ }
+
+ Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j);
for (int i = 0; i < amount; i++) {
const CollisionObject2DSW *col_obj = intersection_query_results[i];
@@ -635,8 +788,12 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
if (p_body->is_shape_set_as_disabled(body_shape_idx))
continue;
- Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(body_shape_idx);
Shape2DSW *body_shape = p_body->get_shape(body_shape_idx);
+ if (p_exclude_raycast_shapes && body_shape->get_type() == Physics2DServer::SHAPE_RAY) {
+ continue;
+ }
+
+ Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(body_shape_idx);
bool stuck = false;
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index 79349c46f3..959e15e12d 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -182,7 +182,8 @@ public:
int get_collision_pairs() const { return collision_pairs; }
- bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, Physics2DServer::MotionResult *r_result);
+ bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, Physics2DServer::MotionResult *r_result, bool p_exclude_raycast_shapes = true);
+ int test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, Physics2DServer::SeparationResult *r_results, int p_result_max, real_t p_margin);
void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); }
_FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.empty(); }
diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h
index ba5232f7fe..1d04fbc5c6 100644
--- a/servers/physics_2d_server.h
+++ b/servers/physics_2d_server.h
@@ -479,7 +479,22 @@ public:
Variant collider_metadata;
};
- 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) = 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;
+
+ struct SeparationResult {
+
+ float collision_depth;
+ Vector2 collision_point;
+ Vector2 collision_normal;
+ Vector2 collider_velocity;
+ int collision_local_shape;
+ ObjectID collider_id;
+ RID collider;
+ int collider_shape;
+ Variant collider_metadata;
+ };
+
+ virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001) = 0;
/* JOINT API */
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 3245e7be70..0b37d266e7 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -201,6 +201,7 @@ public:
virtual void textures_keep_original(bool p_enable) = 0;
virtual void texture_set_proxy(RID p_proxy, RID p_base) = 0;
+ virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0;
/* SKY API */
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 2069e64c43..fd1eb77143 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -2545,7 +2545,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
TkPos pos = _get_tkpos();
tk = _get_token();
- if (tk.type == TK_PERIOD) {
+ if (tk.type == TK_CURSOR) {
+ //do nothing
+ } else if (tk.type == TK_PERIOD) {
StringName identifier;
if (_get_completable_identifier(p_block, COMPLETION_INDEX, identifier)) {
@@ -3583,7 +3585,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
return OK;
}
-Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types) {
+Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types) {
Token tk = _get_token();
@@ -3642,7 +3644,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- if (!p_render_modes.has(mode)) {
+ if (p_render_modes.find(mode) == -1) {
_set_error("Invalid render mode: '" + String(mode) + "'");
return ERR_PARSE_ERROR;
}
@@ -4097,7 +4099,7 @@ String ShaderLanguage::get_shader_type(const String &p_code) {
return String();
}
-Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types) {
+Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types) {
clear();
@@ -4114,7 +4116,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 Set<String> &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<String> *r_options, String &r_call_hint) {
clear();
@@ -4130,13 +4132,13 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
switch (completion_type) {
case COMPLETION_NONE: {
- //do none
- return ERR_PARSE_ERROR;
+ //do nothing
+ return OK;
} break;
case COMPLETION_RENDER_MODE: {
- for (const Set<String>::Element *E = p_render_modes.front(); E; E = E->next()) {
+ for (int i = 0; i < p_render_modes.size(); i++) {
- r_options->push_back(E->get());
+ r_options->push_back(p_render_modes[i]);
}
return OK;
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index 720511e18d..9b84c5f195 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -650,7 +650,7 @@ private:
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 Set<String> &p_render_modes, const Set<String> &p_shader_types);
+ Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types);
public:
//static void get_keyword_list(ShaderType p_type,List<String> *p_keywords);
@@ -658,8 +658,8 @@ public:
void clear();
static String get_shader_type(const String &p_code);
- Error compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types);
- Error complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types, List<String> *r_options, String &r_call_hint);
+ 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);
String get_error_text();
int get_error_line();
diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp
index a92e1b06d2..92786ea740 100644
--- a/servers/visual/shader_types.cpp
+++ b/servers/visual/shader_types.cpp
@@ -35,7 +35,7 @@ const Map<StringName, ShaderLanguage::FunctionInfo> &ShaderTypes::get_functions(
return shader_modes[p_mode].functions;
}
-const Set<String> &ShaderTypes::get_modes(VS::ShaderMode p_mode) {
+const Vector<StringName> &ShaderTypes::get_modes(VS::ShaderMode p_mode) {
return shader_modes[p_mode].modes;
}
@@ -140,43 +140,44 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["light"].can_discard = true;
- shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_mix");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_add");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_sub");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_mul");
+ //order used puts first enum mode (default) first
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("blend_mix");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("blend_add");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("blend_sub");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("blend_mul");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_opaque");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_always");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_never");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_alpha_prepass");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_draw_opaque");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_draw_always");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_draw_never");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_draw_alpha_prepass");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_test_disable");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_test_disable");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_front");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_back");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_disabled");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("cull_back");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("cull_front");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("cull_disabled");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("unshaded");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("unshaded");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_lambert");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_lambert_wrap");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_oren_nayar");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_burley");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_toon");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("diffuse_lambert");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("diffuse_lambert_wrap");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("diffuse_oren_nayar");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("diffuse_burley");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("diffuse_toon");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("specular_schlick_ggx");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("specular_blinn");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("specular_phong");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("specular_toon");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("specular_disabled");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("specular_schlick_ggx");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("specular_blinn");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("specular_phong");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("specular_toon");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("specular_disabled");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("skip_vertex_transform");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("world_vertex_coords");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("ensure_correct_normals");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("skip_vertex_transform");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("world_vertex_coords");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("ensure_correct_normals");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("shadows_disabled");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("shadows_disabled");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("vertex_lighting");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("vertex_lighting");
/************ CANVAS ITEM **************************/
@@ -227,17 +228,17 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].can_discard = true;
- shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("skip_vertex_transform");
+ shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("skip_vertex_transform");
- shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_mix");
- shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_add");
- shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_sub");
- shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_mul");
- shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_premul_alpha");
- shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_disabled");
+ shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_mix");
+ shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_add");
+ shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_sub");
+ shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_mul");
+ shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_premul_alpha");
+ shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_disabled");
- shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("unshaded");
- shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("light_only");
+ shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("unshaded");
+ shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("light_only");
/************ PARTICLES **************************/
@@ -257,9 +258,9 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[VS::SHADER_PARTICLES].functions["vertex"].can_discard = false;
- shader_modes[VS::SHADER_PARTICLES].modes.insert("disable_force");
- shader_modes[VS::SHADER_PARTICLES].modes.insert("disable_velocity");
- shader_modes[VS::SHADER_PARTICLES].modes.insert("keep_data");
+ shader_modes[VS::SHADER_PARTICLES].modes.push_back("disable_force");
+ shader_modes[VS::SHADER_PARTICLES].modes.push_back("disable_velocity");
+ shader_modes[VS::SHADER_PARTICLES].modes.push_back("keep_data");
shader_types.insert("spatial");
shader_types.insert("canvas_item");
diff --git a/servers/visual/shader_types.h b/servers/visual/shader_types.h
index 1f43ff9c92..0680ec8242 100644
--- a/servers/visual/shader_types.h
+++ b/servers/visual/shader_types.h
@@ -31,14 +31,16 @@
#ifndef SHADERTYPES_H
#define SHADERTYPES_H
+#include "ordered_hash_map.h"
#include "servers/visual_server.h"
#include "shader_language.h"
+
class ShaderTypes {
struct Type {
Map<StringName, ShaderLanguage::FunctionInfo> functions;
- Set<String> modes;
+ Vector<StringName> modes;
};
Map<VS::ShaderMode, Type> shader_modes;
@@ -51,7 +53,7 @@ public:
static ShaderTypes *get_singleton() { return singleton; }
const Map<StringName, ShaderLanguage::FunctionInfo> &get_functions(VS::ShaderMode p_mode);
- const Set<String> &get_modes(VS::ShaderMode p_mode);
+ const Vector<StringName> &get_modes(VS::ShaderMode p_mode);
const Set<String> &get_types();
ShaderTypes();
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index 163aa9bb07..5f207b1d3f 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -95,10 +95,11 @@ void VisualServerRaster::request_frame_drawn_callback(Object *p_where, const Str
void VisualServerRaster::draw(bool p_swap_buffers) {
- changes = 0;
-
+ //needs to be done before changes is reset to 0, to not force the editor to redraw
VS::get_singleton()->emit_signal("frame_pre_draw");
+ changes = 0;
+
VSG::rasterizer->begin_frame();
VSG::scene->update_dirty_instances(); //update scene stuff
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index c03005592f..ec0d02ed2a 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -173,6 +173,8 @@ public:
BIND2(texture_set_proxy, RID, RID)
+ BIND2(texture_set_force_redraw_if_visible, RID, bool)
+
/* SKY API */
BIND0R(RID, sky_create)
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index 54fcd166c9..48f0ec46f3 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -107,6 +107,8 @@ public:
FUNC2(texture_set_proxy, RID, RID)
+ FUNC2(texture_set_force_redraw_if_visible, RID, bool)
+
/* SKY API */
FUNCRID(sky)
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 5027009634..968cb852ed 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -144,6 +144,7 @@ public:
virtual void textures_keep_original(bool p_enable) = 0;
virtual void texture_set_proxy(RID p_proxy, RID p_base) = 0;
+ virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0;
/* SKY API */