Added a function to cache texture opacity at a pixel, and modified editor to use it.
Provides massive speedups to selecting objects, still awaiting for @MarianoGNU to do fixes to the region editor to improve performance.
This commit is contained in:
parent
cef310e0ea
commit
34e58fd831
@ -298,6 +298,11 @@ int Sprite::get_hframes() const {
|
|||||||
|
|
||||||
bool Sprite::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) 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())
|
if (texture.is_null())
|
||||||
return false;
|
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.y = 1.0f - q.y;
|
||||||
q = q * src_rect.size + src_rect.position;
|
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_repeat = texture->get_flags() & Texture::FLAG_REPEAT;
|
||||||
bool is_mirrored_repeat = texture->get_flags() & Texture::FLAG_MIRRORED_REPEAT;
|
bool is_mirrored_repeat = texture->get_flags() & Texture::FLAG_MIRRORED_REPEAT;
|
||||||
if (is_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.x = MIN(q.x, texture->get_size().width - 1);
|
||||||
q.y = MIN(q.y, texture->get_size().height - 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 {
|
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("set_region", "enabled"), &Sprite::set_region);
|
||||||
ClassDB::bind_method(D_METHOD("is_region"), &Sprite::is_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("set_region_rect", "rect"), &Sprite::set_region_rect);
|
||||||
ClassDB::bind_method(D_METHOD("get_region_rect"), &Sprite::get_region_rect);
|
ClassDB::bind_method(D_METHOD("get_region_rect"), &Sprite::get_region_rect);
|
||||||
|
|
||||||
|
@ -75,6 +75,8 @@ public:
|
|||||||
virtual bool _edit_use_pivot() const;
|
virtual bool _edit_use_pivot() const;
|
||||||
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) 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 Rect2 _edit_get_rect() const;
|
||||||
virtual bool _edit_use_rect() const;
|
virtual bool _edit_use_rect() const;
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
|
#include "bit_mask.h"
|
||||||
#include "core/method_bind_ext.gen.inc"
|
#include "core/method_bind_ext.gen.inc"
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
#include "core_string_names.h"
|
#include "core_string_names.h"
|
||||||
@ -39,6 +40,9 @@ Size2 Texture::get_size() const {
|
|||||||
return Size2(get_width(), get_height());
|
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 {
|
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();
|
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);
|
VisualServer::get_singleton()->texture_set_data(texture, p_image);
|
||||||
|
|
||||||
_change_notify();
|
_change_notify();
|
||||||
|
alpha_cache.unref();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageTexture::_resource_path_changed() {
|
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);
|
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) {
|
void ImageTexture::set_size_override(const Size2 &p_size) {
|
||||||
|
|
||||||
Size2 s = 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) {
|
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);
|
ERR_FAIL_COND_V(image.is_null(), ERR_INVALID_PARAMETER);
|
||||||
|
|
||||||
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
|
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);
|
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) {
|
void StreamTexture::set_flags(uint32_t p_flags) {
|
||||||
flags = p_flags;
|
flags = p_flags;
|
||||||
VS::get_singleton()->texture_set_flags(texture, 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;
|
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() {
|
AtlasTexture::AtlasTexture() {
|
||||||
filter_clip = false;
|
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() {
|
LargeTexture::LargeTexture() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1803,6 +1905,16 @@ Ref<Image> AnimatedTexture::get_data() const {
|
|||||||
return frames[current_frame].texture->get_data();
|
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) {
|
void AnimatedTexture::set_flags(uint32_t p_flags) {
|
||||||
}
|
}
|
||||||
uint32_t AnimatedTexture::get_flags() const {
|
uint32_t AnimatedTexture::get_flags() const {
|
||||||
|
@ -68,6 +68,8 @@ public:
|
|||||||
virtual Size2 get_size() const;
|
virtual Size2 get_size() const;
|
||||||
virtual RID get_rid() const = 0;
|
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 bool has_alpha() const = 0;
|
||||||
|
|
||||||
virtual void set_flags(uint32_t p_flags) = 0;
|
virtual void set_flags(uint32_t p_flags) = 0;
|
||||||
@ -85,6 +87,8 @@ public:
|
|||||||
|
|
||||||
VARIANT_ENUM_CAST(Texture::Flags);
|
VARIANT_ENUM_CAST(Texture::Flags);
|
||||||
|
|
||||||
|
class BitMap;
|
||||||
|
|
||||||
class ImageTexture : public Texture {
|
class ImageTexture : public Texture {
|
||||||
|
|
||||||
GDCLASS(ImageTexture, Texture);
|
GDCLASS(ImageTexture, Texture);
|
||||||
@ -105,6 +109,7 @@ private:
|
|||||||
Storage storage;
|
Storage storage;
|
||||||
Size2 size_override;
|
Size2 size_override;
|
||||||
float lossy_storage_quality;
|
float lossy_storage_quality;
|
||||||
|
mutable Ref<BitMap> alpha_cache;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void reload_from_file();
|
virtual void reload_from_file();
|
||||||
@ -144,6 +149,8 @@ public:
|
|||||||
void set_storage(Storage p_storage);
|
void set_storage(Storage p_storage);
|
||||||
Storage get_storage() const;
|
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);
|
void set_lossy_storage_quality(float p_lossy_storage_quality);
|
||||||
float get_lossy_storage_quality() const;
|
float get_lossy_storage_quality() const;
|
||||||
|
|
||||||
@ -184,6 +191,7 @@ private:
|
|||||||
Image::Format format;
|
Image::Format format;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
int w, h;
|
int w, h;
|
||||||
|
mutable Ref<BitMap> alpha_cache;
|
||||||
|
|
||||||
virtual void reload_from_file();
|
virtual void reload_from_file();
|
||||||
|
|
||||||
@ -216,6 +224,7 @@ public:
|
|||||||
|
|
||||||
virtual bool has_alpha() const;
|
virtual bool has_alpha() const;
|
||||||
virtual void set_flags(uint32_t p_flags);
|
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;
|
virtual Ref<Image> get_data() const;
|
||||||
|
|
||||||
@ -273,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 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;
|
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();
|
AtlasTexture();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -320,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(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;
|
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();
|
LargeTexture();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -670,6 +683,8 @@ public:
|
|||||||
|
|
||||||
virtual Ref<Image> get_data() const;
|
virtual Ref<Image> get_data() const;
|
||||||
|
|
||||||
|
bool is_pixel_opaque(int p_x, int p_y) const;
|
||||||
|
|
||||||
AnimatedTexture();
|
AnimatedTexture();
|
||||||
~AnimatedTexture();
|
~AnimatedTexture();
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user