summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/canvas_item.h2
-rw-r--r--scene/2d/collision_object_2d.cpp4
-rw-r--r--scene/2d/physics_body_2d.cpp41
-rw-r--r--scene/2d/physics_body_2d.h1
-rw-r--r--scene/2d/remote_transform_2d.cpp7
-rw-r--r--scene/2d/sprite.cpp38
-rw-r--r--scene/2d/sprite.h2
-rw-r--r--scene/3d/camera.cpp3
-rw-r--r--scene/3d/remote_transform.cpp4
-rw-r--r--scene/animation/animation_blend_tree.cpp11
-rw-r--r--scene/animation/animation_blend_tree.h1
-rw-r--r--scene/animation/animation_node_state_machine.cpp1
-rw-r--r--scene/animation/animation_tree.cpp45
-rw-r--r--scene/animation/animation_tree.h11
-rw-r--r--scene/main/canvas_layer.cpp19
-rw-r--r--scene/main/canvas_layer.h1
-rw-r--r--scene/resources/texture.cpp145
-rw-r--r--scene/resources/texture.h19
18 files changed, 254 insertions, 101 deletions
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index 85f8564ac2..1e6a251c9c 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -139,8 +139,6 @@ class CanvasItem : public Node {
GDCLASS(CanvasItem, Node);
- friend class CanvasLayer;
-
public:
enum BlendMode {
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp
index 52d04ac10a..1e2184bd41 100644
--- a/scene/2d/collision_object_2d.cpp
+++ b/scene/2d/collision_object_2d.cpp
@@ -38,7 +38,7 @@ void CollisionObject2D::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
- Transform2D global_transform = get_global_transform_with_canvas();
+ Transform2D global_transform = get_global_transform();
if (area)
Physics2DServer::get_singleton()->area_set_transform(rid, global_transform);
@@ -64,7 +64,7 @@ void CollisionObject2D::_notification(int p_what) {
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
- Transform2D global_transform = get_global_transform_with_canvas();
+ Transform2D global_transform = get_global_transform();
if (only_update_transform_changes && global_transform == last_transform) {
return;
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 66686f10a8..02213e07d0 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -35,6 +35,19 @@
#include "engine.h"
#include "math_funcs.h"
#include "scene/scene_string_names.h"
+void PhysicsBody2D::_notification(int p_what) {
+
+ /*
+ switch(p_what) {
+
+ case NOTIFICATION_TRANSFORM_CHANGED: {
+
+ Physics2DServer::get_singleton()->body_set_state(get_rid(),Physics2DServer::BODY_STATE_TRANSFORM,get_global_transform());
+
+ } break;
+ }
+ */
+}
void PhysicsBody2D::_set_layers(uint32_t p_mask) {
@@ -423,7 +436,7 @@ bool RigidBody2D::_test_motion(const Vector2 &p_motion, bool p_infinite_inertia,
Physics2DServer::MotionResult *r = NULL;
if (p_result.is_valid())
r = p_result->get_result_ptr();
- return Physics2DServer::get_singleton()->body_test_motion(get_rid(), get_global_transform_with_canvas(), p_motion, p_infinite_inertia, p_margin, r);
+ return Physics2DServer::get_singleton()->body_test_motion(get_rid(), get_global_transform(), p_motion, p_infinite_inertia, p_margin, r);
}
void RigidBody2D::_direct_state_changed(Object *p_state) {
@@ -436,7 +449,7 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
set_block_transform_notify(true); // don't want notify (would feedback loop)
if (mode != MODE_KINEMATIC)
- set_global_transform(get_canvas_transform().affine_inverse() * state->get_transform());
+ set_global_transform(state->get_transform());
linear_velocity = state->get_linear_velocity();
angular_velocity = state->get_angular_velocity();
if (sleeping != state->is_sleeping()) {
@@ -1131,7 +1144,7 @@ bool KinematicBody2D::separate_raycast_shapes(bool p_infinite_inertia, Collision
Physics2DServer::SeparationResult sep_res[8]; //max 8 rays
- Transform2D gt = get_global_transform_with_canvas();
+ Transform2D gt = get_global_transform();
Vector2 recover;
int hits = Physics2DServer::get_singleton()->body_test_ray_separation(get_rid(), gt, p_infinite_inertia, recover, sep_res, 8, margin);
@@ -1145,7 +1158,7 @@ bool KinematicBody2D::separate_raycast_shapes(bool p_infinite_inertia, Collision
}
gt.elements[2] += recover;
- set_global_transform(get_canvas_transform().affine_inverse() * gt);
+ set_global_transform(gt);
if (deepest != -1) {
r_collision.collider = sep_res[deepest].collider_id;
@@ -1166,7 +1179,7 @@ bool KinematicBody2D::separate_raycast_shapes(bool p_infinite_inertia, Collision
bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes, bool p_test_only) {
- Transform2D gt = get_global_transform_with_canvas();
+ Transform2D gt = get_global_transform();
Physics2DServer::MotionResult result;
bool colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, margin, &result, p_exclude_raycast_shapes);
@@ -1185,7 +1198,7 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_
if (!p_test_only) {
gt.elements[2] += result.motion;
- set_global_transform(get_canvas_transform().affine_inverse() * gt);
+ set_global_transform(gt);
}
return colliding;
@@ -1259,9 +1272,9 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
if (p_stop_on_slope) {
if (Vector2() == lv_n + p_floor_direction) {
- Transform2D gt = get_global_transform_with_canvas();
+ Transform2D gt = get_global_transform();
gt.elements[2] -= collision.travel;
- set_global_transform(get_canvas_transform().affine_inverse() * gt);
+ set_global_transform(gt);
return Vector2();
}
}
@@ -1310,7 +1323,7 @@ Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci
}
Collision col;
- Transform2D gt = get_global_transform_with_canvas();
+ Transform2D gt = get_global_transform();
if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) {
gt.elements[2] += col.travel;
@@ -1319,7 +1332,7 @@ Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci
on_floor_body = col.collider_rid;
floor_velocity = col.collider_vel;
}
- set_global_transform(get_canvas_transform().affine_inverse() * gt);
+ set_global_transform(gt);
}
return ret;
@@ -1416,22 +1429,22 @@ void KinematicBody2D::_direct_state_changed(Object *p_state) {
last_valid_transform = state->get_transform();
set_notify_local_transform(false);
- set_global_transform(get_canvas_transform().affine_inverse() * last_valid_transform);
+ set_global_transform(last_valid_transform);
set_notify_local_transform(true);
}
void KinematicBody2D::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
- last_valid_transform = get_global_transform_with_canvas();
+ last_valid_transform = get_global_transform();
}
if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
//used by sync to physics, send the new transform to the physics
- Transform2D new_transform = get_global_transform_with_canvas();
+ Transform2D new_transform = get_global_transform();
Physics2DServer::get_singleton()->body_set_state(get_rid(), Physics2DServer::BODY_STATE_TRANSFORM, new_transform);
//but then revert changes
set_notify_local_transform(false);
- set_global_transform(get_canvas_transform().affine_inverse() * last_valid_transform);
+ set_global_transform(last_valid_transform);
set_notify_local_transform(true);
}
}
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index 0900438e3c..852963a721 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -49,6 +49,7 @@ class PhysicsBody2D : public CollisionObject2D {
uint32_t _get_layers() const;
protected:
+ void _notification(int p_what);
PhysicsBody2D(Physics2DServer::BodyMode p_mode);
static void _bind_methods();
diff --git a/scene/2d/remote_transform_2d.cpp b/scene/2d/remote_transform_2d.cpp
index 63c3d78dfd..f0274e5206 100644
--- a/scene/2d/remote_transform_2d.cpp
+++ b/scene/2d/remote_transform_2d.cpp
@@ -67,7 +67,7 @@ void RemoteTransform2D::_update_remote() {
} else {
Transform2D n_trans = n->get_global_transform();
Transform2D our_trans = get_global_transform();
- Vector2 n_scale = n->get_global_scale();
+ Vector2 n_scale = n->get_scale();
if (!update_remote_position)
our_trans.set_origin(n_trans.get_origin());
@@ -131,8 +131,10 @@ void RemoteTransform2D::_notification(int p_what) {
void RemoteTransform2D::set_remote_node(const NodePath &p_remote_node) {
remote_node = p_remote_node;
- if (is_inside_tree())
+ if (is_inside_tree()) {
_update_cache();
+ _update_remote();
+ }
update_configuration_warning();
}
@@ -144,6 +146,7 @@ NodePath RemoteTransform2D::get_remote_node() const {
void RemoteTransform2D::set_use_global_coordinates(const bool p_enable) {
use_global_coordinates = p_enable;
+ _update_remote();
}
bool RemoteTransform2D::get_use_global_coordinates() const {
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index ebe0e81f6e..bb5990fa79 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -298,6 +298,11 @@ int Sprite::get_hframes() const {
bool Sprite::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
+ return is_pixel_opaque(p_point);
+}
+
+bool Sprite::is_pixel_opaque(const Point2 &p_point) const {
+
if (texture.is_null())
return false;
@@ -316,32 +321,6 @@ bool Sprite::_edit_is_selected_on_click(const Point2 &p_point, double p_toleranc
q.y = 1.0f - q.y;
q = q * src_rect.size + src_rect.position;
- Ref<Image> image;
- Ref<AtlasTexture> atlasTexture = texture;
- if (atlasTexture.is_null()) {
- image = texture->get_data();
- } else {
- ERR_FAIL_COND_V(atlasTexture->get_atlas().is_null(), false);
-
- image = atlasTexture->get_atlas()->get_data();
-
- Rect2 region = atlasTexture->get_region();
- Rect2 margin = atlasTexture->get_margin();
-
- q -= margin.position;
-
- if ((q.x > region.size.width) || (q.y > region.size.height)) {
- return false;
- }
-
- q += region.position;
- }
-
- ERR_FAIL_COND_V(image.is_null(), false);
- if (image->is_compressed()) {
- return dst_rect.has_point(p_point);
- }
-
bool is_repeat = texture->get_flags() & Texture::FLAG_REPEAT;
bool is_mirrored_repeat = texture->get_flags() & Texture::FLAG_MIRRORED_REPEAT;
if (is_repeat) {
@@ -363,11 +342,8 @@ bool Sprite::_edit_is_selected_on_click(const Point2 &p_point, double p_toleranc
q.x = MIN(q.x, texture->get_size().width - 1);
q.y = MIN(q.y, texture->get_size().height - 1);
}
- image->lock();
- const Color c = image->get_pixel((int)q.x, (int)q.y);
- image->unlock();
- return c.a > 0.01;
+ return texture->is_pixel_opaque((int)q.x, (int)q.y);
}
Rect2 Sprite::get_rect() const {
@@ -437,6 +413,8 @@ void Sprite::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_region", "enabled"), &Sprite::set_region);
ClassDB::bind_method(D_METHOD("is_region"), &Sprite::is_region);
+ ClassDB::bind_method(D_METHOD("is_pixel_opaque", "pos"), &Sprite::is_pixel_opaque);
+
ClassDB::bind_method(D_METHOD("set_region_rect", "rect"), &Sprite::set_region_rect);
ClassDB::bind_method(D_METHOD("get_region_rect"), &Sprite::get_region_rect);
diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h
index 0a5ff002cd..ab444f89fc 100644
--- a/scene/2d/sprite.h
+++ b/scene/2d/sprite.h
@@ -75,6 +75,8 @@ public:
virtual bool _edit_use_pivot() const;
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
+ bool is_pixel_opaque(const Point2 &p_point) const;
+
virtual Rect2 _edit_get_rect() const;
virtual bool _edit_use_rect() const;
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index bcd015875b..a4582b7d7d 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -867,6 +867,9 @@ void ClippedCamera::_bind_methods() {
ADD_GROUP("Clip To", "clip_to");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_to_areas", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_clip_to_areas", "is_clip_to_areas_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_to_bodies", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_clip_to_bodies", "is_clip_to_bodies_enabled");
+
+ BIND_ENUM_CONSTANT(CLIP_PROCESS_PHYSICS);
+ BIND_ENUM_CONSTANT(CLIP_PROCESS_IDLE);
}
ClippedCamera::ClippedCamera() {
margin = 0;
diff --git a/scene/3d/remote_transform.cpp b/scene/3d/remote_transform.cpp
index 2156e24cd0..c12e49fb47 100644
--- a/scene/3d/remote_transform.cpp
+++ b/scene/3d/remote_transform.cpp
@@ -124,8 +124,10 @@ void RemoteTransform::_notification(int p_what) {
void RemoteTransform::set_remote_node(const NodePath &p_remote_node) {
remote_node = p_remote_node;
- if (is_inside_tree())
+ if (is_inside_tree()) {
_update_cache();
+ _update_remote();
+ }
update_configuration_warning();
}
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index 66a9c5babd..10bab3ce38 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -987,17 +987,6 @@ void AnimationNodeBlendTree::disconnect_node(const StringName &p_node, int p_inp
nodes[p_node].connections.write[p_input_index] = StringName();
}
-float AnimationNodeBlendTree::get_connection_activity(const StringName &p_input_node, int p_input_index) const {
-
- ERR_FAIL_COND_V(!nodes.has(p_input_node), 0);
-
- Ref<AnimationNode> input = nodes[p_input_node].node;
- ERR_FAIL_INDEX_V(p_input_index, nodes[p_input_node].connections.size(), 0);
-
- //return input->get_input_activity(p_input_index);
- return 0;
-}
-
AnimationNodeBlendTree::ConnectionError AnimationNodeBlendTree::can_connect_node(const StringName &p_input_node, int p_input_index, const StringName &p_output_node) const {
if (!nodes.has(p_output_node) || p_output_node == SceneStringNames::get_singleton()->output) {
diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h
index 37bd45c74a..7bf2917c1e 100644
--- a/scene/animation/animation_blend_tree.h
+++ b/scene/animation/animation_blend_tree.h
@@ -349,7 +349,6 @@ public:
void connect_node(const StringName &p_input_node, int p_input_index, const StringName &p_output_node);
void disconnect_node(const StringName &p_node, int p_input_index);
- float get_connection_activity(const StringName &p_input_node, int p_input_index) const;
struct NodeConnection {
StringName input_node;
diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp
index c28e918a16..09c36eb081 100644
--- a/scene/animation/animation_node_state_machine.cpp
+++ b/scene/animation/animation_node_state_machine.cpp
@@ -124,7 +124,6 @@ void AnimationNodeStateMachinePlayback::start(const StringName &p_state) {
start_request_travel = false;
start_request = p_state;
stop_request = false;
- print_line("wants start");
}
void AnimationNodeStateMachinePlayback::stop() {
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 1513010a8a..76f0ee9359 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -109,8 +109,16 @@ float AnimationNode::blend_input(int p_input, float p_time, bool p_seek, float p
Ref<AnimationNode> node = blend_tree->get_node(node_name);
//inputs.write[p_input].last_pass = state->last_pass;
- float activity;
- return _blend_node(node_name, blend_tree->get_node_connection_array(node_name), NULL, node, p_time, p_seek, p_blend, p_filter, p_optimize, &activity);
+ float activity=0;
+ float ret = _blend_node(node_name, blend_tree->get_node_connection_array(node_name), NULL, node, p_time, p_seek, p_blend, p_filter, p_optimize, &activity);
+
+ Vector<AnimationTree::Activity> *activity_ptr = state->tree->input_activity_map.getptr(base_path);
+
+ if (activity_ptr && p_input<activity_ptr->size()) {
+ activity_ptr->write[p_input].last_pass = state->last_pass;
+ activity_ptr->write[p_input].activity = activity;
+ }
+ return ret;
}
float AnimationNode::blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, float p_time, bool p_seek, float p_blend, FilterAction p_filter, bool p_optimize) {
@@ -1285,6 +1293,18 @@ void AnimationTree::_update_properties_for_node(const String &p_base_path, Ref<A
property_parent_map[p_base_path] = HashMap<StringName, StringName>();
}
+ if (node->get_input_count() && !input_activity_map.has(p_base_path)) {
+
+ Vector<Activity> activity;
+ for(int i=0;i<node->get_input_count();i++) {
+ Activity a;
+ a.last_pass=0;
+ activity.push_back(a);
+ }
+ input_activity_map[p_base_path] = activity;
+ input_activity_map_get[String(p_base_path).substr(0,String(p_base_path).length()-1)]=&input_activity_map[p_base_path];
+ }
+
List<PropertyInfo> plist;
node->get_parameter_list(&plist);
for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
@@ -1317,6 +1337,8 @@ void AnimationTree::_update_properties() {
properties.clear();
property_parent_map.clear();
+ input_activity_map.clear();
+ input_activity_map_get.clear();
if (root.is_valid()) {
_update_properties_for_node(SceneStringNames::get_singleton()->parameters_base_path, root);
@@ -1380,6 +1402,25 @@ void AnimationTree::rename_parameter(const String &p_base, const String &p_new_b
_update_properties();
}
+float AnimationTree::get_connection_activity(const StringName& p_path,int p_connection) const {
+
+ if (!input_activity_map_get.has(p_path)) {
+ return 0;
+ }
+ const Vector<Activity> *activity = input_activity_map_get[p_path];
+
+ if (!activity || p_connection<0 || p_connection>=activity->size()) {
+ return 0;
+ }
+
+ if ((*activity)[p_connection].last_pass != process_pass) {
+ return 0;
+ }
+
+ return (*activity)[p_connection].activity;
+}
+
+
void AnimationTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_active", "active"), &AnimationTree::set_active);
ClassDB::bind_method(D_METHOD("is_active"), &AnimationTree::is_active);
diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h
index 3c615b2f92..70f3932f21 100644
--- a/scene/animation/animation_tree.h
+++ b/scene/animation/animation_tree.h
@@ -55,7 +55,7 @@ public:
Vector<float> blends;
State *state;
- String path;
+
float _pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, float p_time, bool p_seek, const Vector<StringName> &p_connections);
void _pre_update_animations(HashMap<NodePath, int> *track_map);
@@ -256,6 +256,14 @@ private:
HashMap<StringName, HashMap<StringName, StringName> > property_parent_map;
HashMap<StringName, Variant> property_map;
+ struct Activity {
+ uint64_t last_pass;
+ float activity;
+ };
+
+ HashMap<StringName, Vector<Activity> > input_activity_map;
+ HashMap<StringName, Vector<Activity> *> input_activity_map_get;
+
void _update_properties_for_node(const String &p_base_path, Ref<AnimationNode> node);
protected:
@@ -289,6 +297,7 @@ public:
Transform get_root_motion_transform() const;
+ float get_connection_activity(const StringName &p_path, int p_connection) const;
void advance(float p_time);
void rename_parameter(const String &p_base, const String &p_new_base);
diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp
index c044443b51..a2e890e7a7 100644
--- a/scene/main/canvas_layer.cpp
+++ b/scene/main/canvas_layer.cpp
@@ -29,7 +29,6 @@
/*************************************************************************/
#include "canvas_layer.h"
-#include "scene/2d/canvas_item.h"
#include "viewport.h"
void CanvasLayer::set_layer(int p_xform) {
@@ -63,24 +62,6 @@ void CanvasLayer::_update_xform() {
transform.set_origin(ofs);
if (viewport.is_valid())
VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform);
-
- if (!is_inside_tree())
- return;
-
- _notify_xform(this);
-}
-
-void CanvasLayer::_notify_xform(Node *p_node) {
-
- for (int i = 0; i < p_node->get_child_count(); i++) {
-
- CanvasItem *ci = Object::cast_to<CanvasItem>(p_node->get_child(i));
- if (ci) {
- ci->_notify_transform(ci);
- } else {
- _notify_xform(p_node->get_child(i));
- }
- }
}
void CanvasLayer::_update_locrotscale() {
diff --git a/scene/main/canvas_layer.h b/scene/main/canvas_layer.h
index fd347c4739..aae23fbb12 100644
--- a/scene/main/canvas_layer.h
+++ b/scene/main/canvas_layer.h
@@ -56,7 +56,6 @@ class CanvasLayer : public Node {
int sort_index;
void _update_xform();
- void _notify_xform(Node *p_node);
void _update_locrotscale();
protected:
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index d8efbeba17..c763c9bc79 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "texture.h"
+#include "bit_mask.h"
#include "core/method_bind_ext.gen.inc"
#include "core/os/os.h"
#include "core_string_names.h"
@@ -39,6 +40,9 @@ Size2 Texture::get_size() const {
return Size2(get_width(), get_height());
}
+bool Texture::is_pixel_opaque(int p_x, int p_y) const {
+ return true;
+}
void Texture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const {
RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID();
@@ -234,6 +238,7 @@ void ImageTexture::set_data(const Ref<Image> &p_image) {
VisualServer::get_singleton()->texture_set_data(texture, p_image);
_change_notify();
+ alpha_cache.unref();
}
void ImageTexture::_resource_path_changed() {
@@ -288,6 +293,41 @@ void ImageTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, cons
VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid, p_clip_uv);
}
+bool ImageTexture::is_pixel_opaque(int p_x, int p_y) const {
+
+ if (!alpha_cache.is_valid()) {
+ Ref<Image> img = get_data();
+ if (img.is_valid()) {
+ if (img->is_compressed()) { //must decompress, if compressed
+ Ref<Image> decom = img->duplicate();
+ decom->decompress();
+ img = decom;
+ }
+ alpha_cache.instance();
+ alpha_cache->create_from_image_alpha(img);
+ }
+ }
+
+ if (alpha_cache.is_valid()) {
+
+ int aw = int(alpha_cache->get_size().width);
+ int ah = int(alpha_cache->get_size().height);
+ if (aw == 0 || ah == 0) {
+ return true;
+ }
+
+ int x = p_x * aw / w;
+ int y = p_y * ah / h;
+
+ x = CLAMP(x, 0, aw);
+ y = CLAMP(y, 0, aw);
+
+ return alpha_cache->get_bit(Point2(x, y));
+ }
+
+ return true;
+}
+
void ImageTexture::set_size_override(const Size2 &p_size) {
Size2 s = p_size;
@@ -421,6 +461,8 @@ Image::Format StreamTexture::get_format() const {
Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &flags, Ref<Image> &image, int p_size_limit) {
+ alpha_cache.unref();
+
ERR_FAIL_COND_V(image.is_null(), ERR_INVALID_PARAMETER);
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
@@ -709,6 +751,40 @@ Ref<Image> StreamTexture::get_data() const {
return VS::get_singleton()->texture_get_data(texture);
}
+bool StreamTexture::is_pixel_opaque(int p_x, int p_y) const {
+
+ if (!alpha_cache.is_valid()) {
+ Ref<Image> img = get_data();
+ if (img.is_valid()) {
+ if (img->is_compressed()) { //must decompress, if compressed
+ Ref<Image> decom = img->duplicate();
+ decom->decompress();
+ img = decom;
+ }
+ alpha_cache.instance();
+ alpha_cache->create_from_image_alpha(img);
+ }
+ }
+
+ if (alpha_cache.is_valid()) {
+
+ int aw = int(alpha_cache->get_size().width);
+ int ah = int(alpha_cache->get_size().height);
+ if (aw == 0 || ah == 0) {
+ return true;
+ }
+
+ int x = p_x * aw / w;
+ int y = p_y * ah / h;
+
+ x = CLAMP(x, 0, aw);
+ y = CLAMP(y, 0, aw);
+
+ return alpha_cache->get_bit(Point2(x, y));
+ }
+
+ return true;
+}
void StreamTexture::set_flags(uint32_t p_flags) {
flags = p_flags;
VS::get_singleton()->texture_set_flags(texture, flags);
@@ -1007,6 +1083,15 @@ bool AtlasTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect,
return true;
}
+bool AtlasTexture::is_pixel_opaque(int p_x, int p_y) const {
+
+ if (atlas.is_valid()) {
+ return atlas->is_pixel_opaque(p_x + region.position.x + margin.position.x, p_x + region.position.y + margin.position.y);
+ }
+
+ return true;
+}
+
AtlasTexture::AtlasTexture() {
filter_clip = false;
}
@@ -1184,6 +1269,23 @@ void LargeTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, cons
}
}
+bool LargeTexture::is_pixel_opaque(int p_x, int p_y) const {
+
+ for (int i = 0; i < pieces.size(); i++) {
+
+ // TODO
+ if (!pieces[i].texture.is_valid())
+ continue;
+
+ Rect2 rect(pieces[i].offset, pieces[i].texture->get_size());
+ if (rect.has_point(Point2(p_x, p_y))) {
+ return pieces[i].texture->is_pixel_opaque(p_x - rect.position.x, p_y - rect.position.y);
+ }
+ }
+
+ return true;
+}
+
LargeTexture::LargeTexture() {
}
@@ -1666,7 +1768,7 @@ ProxyTexture::~ProxyTexture() {
void AnimatedTexture::_update_proxy() {
- _THREAD_SAFE_METHOD_
+ RWLockRead r(rw_lock);
float delta;
if (prev_ticks == 0) {
@@ -1712,7 +1814,7 @@ void AnimatedTexture::_update_proxy() {
void AnimatedTexture::set_frames(int p_frames) {
ERR_FAIL_COND(p_frames < 1 || p_frames > MAX_FRAMES);
- _THREAD_SAFE_METHOD_
+ RWLockWrite r(rw_lock);
frame_count = p_frames;
}
@@ -1723,14 +1825,14 @@ int AnimatedTexture::get_frames() const {
void AnimatedTexture::set_frame_texture(int p_frame, const Ref<Texture> &p_texture) {
ERR_FAIL_INDEX(p_frame, MAX_FRAMES);
- _THREAD_SAFE_METHOD_
+ RWLockWrite w(rw_lock);
frames[p_frame].texture = p_texture;
}
Ref<Texture> AnimatedTexture::get_frame_texture(int p_frame) const {
ERR_FAIL_INDEX_V(p_frame, MAX_FRAMES, Ref<Texture>());
- _THREAD_SAFE_METHOD_
+ RWLockRead r(rw_lock);
return frames[p_frame].texture;
}
@@ -1738,14 +1840,14 @@ Ref<Texture> AnimatedTexture::get_frame_texture(int p_frame) const {
void AnimatedTexture::set_frame_delay(int p_frame, float p_delay_sec) {
ERR_FAIL_INDEX(p_frame, MAX_FRAMES);
- _THREAD_SAFE_METHOD_
+ RWLockRead r(rw_lock);
frames[p_frame].delay_sec = p_delay_sec;
}
float AnimatedTexture::get_frame_delay(int p_frame) const {
ERR_FAIL_INDEX_V(p_frame, MAX_FRAMES, 0);
- _THREAD_SAFE_METHOD_
+ RWLockRead r(rw_lock);
return frames[p_frame].delay_sec;
}
@@ -1760,8 +1862,7 @@ float AnimatedTexture::get_fps() const {
}
int AnimatedTexture::get_width() const {
-
- _THREAD_SAFE_METHOD_
+ RWLockRead r(rw_lock);
if (!frames[current_frame].texture.is_valid()) {
return 1;
@@ -1770,8 +1871,7 @@ int AnimatedTexture::get_width() const {
return frames[current_frame].texture->get_width();
}
int AnimatedTexture::get_height() const {
-
- _THREAD_SAFE_METHOD_
+ RWLockRead r(rw_lock);
if (!frames[current_frame].texture.is_valid()) {
return 1;
@@ -1785,7 +1885,7 @@ RID AnimatedTexture::get_rid() const {
bool AnimatedTexture::has_alpha() const {
- _THREAD_SAFE_METHOD_
+ RWLockRead r(rw_lock);
if (!frames[current_frame].texture.is_valid()) {
return false;
@@ -1796,7 +1896,7 @@ bool AnimatedTexture::has_alpha() const {
Ref<Image> AnimatedTexture::get_data() const {
- _THREAD_SAFE_METHOD_
+ RWLockRead r(rw_lock);
if (!frames[current_frame].texture.is_valid()) {
return Ref<Image>();
@@ -1805,11 +1905,21 @@ Ref<Image> AnimatedTexture::get_data() const {
return frames[current_frame].texture->get_data();
}
+bool AnimatedTexture::is_pixel_opaque(int p_x, int p_y) const {
+
+ RWLockRead r(rw_lock);
+
+ if (frames[current_frame].texture.is_valid()) {
+ return frames[current_frame].texture->is_pixel_opaque(p_x, p_y);
+ }
+ return true;
+}
+
void AnimatedTexture::set_flags(uint32_t p_flags) {
}
uint32_t AnimatedTexture::get_flags() const {
- _THREAD_SAFE_METHOD_
+ RWLockRead r(rw_lock);
if (!frames[current_frame].texture.is_valid()) {
return 0;
@@ -1862,10 +1972,19 @@ AnimatedTexture::AnimatedTexture() {
prev_ticks = 0;
current_frame = 0;
VisualServer::get_singleton()->connect("frame_pre_draw", this, "_update_proxy");
+
+#ifndef NO_THREADS
+ rw_lock = RWLock::create();
+#else
+ rw_lock = NULL;
+#endif
}
AnimatedTexture::~AnimatedTexture() {
VS::get_singleton()->free(proxy);
+ if (rw_lock) {
+ memdelete(rw_lock);
+ }
}
///////////////////////////////
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index c1331fb3fe..79e6d2cdf9 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -34,6 +34,7 @@
#include "curve.h"
#include "io/resource_loader.h"
#include "os/mutex.h"
+#include "os/rw_lock.h"
#include "os/thread_safe.h"
#include "rect2.h"
#include "resource.h"
@@ -67,6 +68,8 @@ public:
virtual Size2 get_size() const;
virtual RID get_rid() const = 0;
+ virtual bool is_pixel_opaque(int p_x, int p_y) const;
+
virtual bool has_alpha() const = 0;
virtual void set_flags(uint32_t p_flags) = 0;
@@ -84,6 +87,8 @@ public:
VARIANT_ENUM_CAST(Texture::Flags);
+class BitMap;
+
class ImageTexture : public Texture {
GDCLASS(ImageTexture, Texture);
@@ -104,6 +109,7 @@ private:
Storage storage;
Size2 size_override;
float lossy_storage_quality;
+ mutable Ref<BitMap> alpha_cache;
protected:
virtual void reload_from_file();
@@ -143,6 +149,8 @@ public:
void set_storage(Storage p_storage);
Storage get_storage() const;
+ bool is_pixel_opaque(int p_x, int p_y) const;
+
void set_lossy_storage_quality(float p_lossy_storage_quality);
float get_lossy_storage_quality() const;
@@ -183,6 +191,7 @@ private:
Image::Format format;
uint32_t flags;
int w, h;
+ mutable Ref<BitMap> alpha_cache;
virtual void reload_from_file();
@@ -215,6 +224,7 @@ public:
virtual bool has_alpha() const;
virtual void set_flags(uint32_t p_flags);
+ bool is_pixel_opaque(int p_x, int p_y) const;
virtual Ref<Image> get_data() const;
@@ -272,6 +282,8 @@ public:
virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const;
virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const;
+ bool is_pixel_opaque(int p_x, int p_y) const;
+
AtlasTexture();
};
@@ -319,6 +331,8 @@ public:
virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const;
virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const;
+ bool is_pixel_opaque(int p_x, int p_y) const;
+
LargeTexture();
};
@@ -609,7 +623,8 @@ public:
class AnimatedTexture : public Texture {
GDCLASS(AnimatedTexture, Texture)
- _THREAD_SAFE_CLASS_
+ //use readers writers lock for this, since its far more times read than written to
+ RWLock *rw_lock;
private:
enum {
@@ -668,6 +683,8 @@ public:
virtual Ref<Image> get_data() const;
+ bool is_pixel_opaque(int p_x, int p_y) const;
+
AnimatedTexture();
~AnimatedTexture();
};