mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2024-12-22 11:56:49 +01:00
Ported: Fix 2D MultiMesh hierarchical culling
Fixes updating local bounds for MultiMeshes used in canvas items by introducing a back link.
- lawnjelly
ad577e3c7e
This commit is contained in:
parent
17fa82ac02
commit
26bb16d86e
@ -448,6 +448,7 @@ public:
|
|||||||
AABB _multimesh_get_aabb(RID p_multimesh) const { return AABB(); }
|
AABB _multimesh_get_aabb(RID p_multimesh) const { return AABB(); }
|
||||||
|
|
||||||
MMInterpolator *_multimesh_get_interpolator(RID p_multimesh) const { return nullptr; }
|
MMInterpolator *_multimesh_get_interpolator(RID p_multimesh) const { return nullptr; }
|
||||||
|
void multimesh_attach_canvas_item(RID p_multimesh, RID p_canvas_item, bool p_attach) {}
|
||||||
|
|
||||||
/* IMMEDIATE API */
|
/* IMMEDIATE API */
|
||||||
|
|
||||||
|
@ -3388,6 +3388,24 @@ RasterizerStorage::MMInterpolator *RasterizerStorageGLES2::_multimesh_get_interp
|
|||||||
return &multimesh->interpolator;
|
return &multimesh->interpolator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageGLES2::multimesh_attach_canvas_item(RID p_multimesh, RID p_canvas_item, bool p_attach) {
|
||||||
|
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
|
||||||
|
ERR_FAIL_NULL(multimesh);
|
||||||
|
ERR_FAIL_COND(!p_canvas_item.is_valid());
|
||||||
|
|
||||||
|
if (p_attach) {
|
||||||
|
int64_t found = multimesh->linked_canvas_items.find(p_canvas_item);
|
||||||
|
if (found == -1) {
|
||||||
|
multimesh->linked_canvas_items.push_back(p_canvas_item);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int64_t found = multimesh->linked_canvas_items.find(p_canvas_item);
|
||||||
|
if (found != -1) {
|
||||||
|
multimesh->linked_canvas_items.remove_unordered(found);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RasterizerStorageGLES2::update_dirty_multimeshes() {
|
void RasterizerStorageGLES2::update_dirty_multimeshes() {
|
||||||
while (multimesh_update_list.first()) {
|
while (multimesh_update_list.first()) {
|
||||||
MultiMesh *multimesh = multimesh_update_list.first()->self();
|
MultiMesh *multimesh = multimesh_update_list.first()->self();
|
||||||
@ -3457,6 +3475,14 @@ void RasterizerStorageGLES2::update_dirty_multimeshes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
multimesh->aabb = aabb;
|
multimesh->aabb = aabb;
|
||||||
|
|
||||||
|
// Inform any linked canvas items that bounds have changed
|
||||||
|
// (for hierarchical culling).
|
||||||
|
int num_linked = multimesh->linked_canvas_items.size();
|
||||||
|
for (int n = 0; n < num_linked; n++) {
|
||||||
|
const RID &rid = multimesh->linked_canvas_items[n];
|
||||||
|
RSG::canvas->_canvas_item_invalidate_local_bound(rid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
multimesh->dirty_aabb = false;
|
multimesh->dirty_aabb = false;
|
||||||
@ -4129,7 +4155,7 @@ void RasterizerStorageGLES2::update_dirty_skeletons() {
|
|||||||
int num_linked = skeleton->linked_canvas_items.size();
|
int num_linked = skeleton->linked_canvas_items.size();
|
||||||
for (int n = 0; n < num_linked; n++) {
|
for (int n = 0; n < num_linked; n++) {
|
||||||
const RID &rid = skeleton->linked_canvas_items[n];
|
const RID &rid = skeleton->linked_canvas_items[n];
|
||||||
RSG::canvas->_canvas_item_skeleton_moved(rid);
|
RSG::canvas->_canvas_item_invalidate_local_bound(rid);
|
||||||
}
|
}
|
||||||
|
|
||||||
ele = ele->next();
|
ele = ele->next();
|
||||||
@ -5700,6 +5726,14 @@ bool RasterizerStorageGLES2::free(RID p_rid) {
|
|||||||
_interpolation_data.notify_free_multimesh(p_rid);
|
_interpolation_data.notify_free_multimesh(p_rid);
|
||||||
|
|
||||||
MultiMesh *multimesh = multimesh_owner.get(p_rid);
|
MultiMesh *multimesh = multimesh_owner.get(p_rid);
|
||||||
|
|
||||||
|
// remove any references in linked canvas items
|
||||||
|
int num_linked = multimesh->linked_canvas_items.size();
|
||||||
|
for (int n = 0; n < num_linked; n++) {
|
||||||
|
const RID &rid = multimesh->linked_canvas_items[n];
|
||||||
|
RSG::canvas->_canvas_item_remove_references(rid, p_rid);
|
||||||
|
}
|
||||||
|
|
||||||
multimesh->instance_remove_deps();
|
multimesh->instance_remove_deps();
|
||||||
|
|
||||||
if (multimesh->mesh.is_valid()) {
|
if (multimesh->mesh.is_valid()) {
|
||||||
|
@ -787,6 +787,7 @@ public:
|
|||||||
bool dirty_data;
|
bool dirty_data;
|
||||||
|
|
||||||
MMInterpolator interpolator;
|
MMInterpolator interpolator;
|
||||||
|
LocalVector<RID> linked_canvas_items;
|
||||||
|
|
||||||
MultiMesh() :
|
MultiMesh() :
|
||||||
size(0),
|
size(0),
|
||||||
@ -833,6 +834,7 @@ public:
|
|||||||
|
|
||||||
virtual AABB _multimesh_get_aabb(RID p_multimesh) const;
|
virtual AABB _multimesh_get_aabb(RID p_multimesh) const;
|
||||||
virtual MMInterpolator *_multimesh_get_interpolator(RID p_multimesh) const;
|
virtual MMInterpolator *_multimesh_get_interpolator(RID p_multimesh) const;
|
||||||
|
virtual void multimesh_attach_canvas_item(RID p_multimesh, RID p_canvas_item, bool p_attach);
|
||||||
|
|
||||||
void update_dirty_multimeshes();
|
void update_dirty_multimeshes();
|
||||||
|
|
||||||
|
@ -376,6 +376,7 @@ public:
|
|||||||
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible);
|
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible);
|
||||||
virtual int multimesh_get_visible_instances(RID p_multimesh) const;
|
virtual int multimesh_get_visible_instances(RID p_multimesh) const;
|
||||||
virtual AABB multimesh_get_aabb(RID p_multimesh) const;
|
virtual AABB multimesh_get_aabb(RID p_multimesh) const;
|
||||||
|
virtual void multimesh_attach_canvas_item(RID p_multimesh, RID p_canvas_item, bool p_attach) = 0;
|
||||||
|
|
||||||
virtual RID _multimesh_create() = 0;
|
virtual RID _multimesh_create() = 0;
|
||||||
virtual void _multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, RS::MultimeshColorFormat p_color_format, RS::MultimeshCustomDataFormat p_data = RS::MULTIMESH_CUSTOM_DATA_NONE) = 0;
|
virtual void _multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, RS::MultimeshColorFormat p_color_format, RS::MultimeshCustomDataFormat p_data = RS::MULTIMESH_CUSTOM_DATA_NONE) = 0;
|
||||||
@ -681,6 +682,8 @@ public:
|
|||||||
TYPE_MULTIRECT,
|
TYPE_MULTIRECT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
virtual bool contains_reference(const RID &p_rid) const { return false; }
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
virtual ~Command() {}
|
virtual ~Command() {}
|
||||||
};
|
};
|
||||||
@ -813,7 +816,17 @@ public:
|
|||||||
RID multimesh;
|
RID multimesh;
|
||||||
RID texture;
|
RID texture;
|
||||||
RID normal_map;
|
RID normal_map;
|
||||||
|
RID canvas_item;
|
||||||
|
virtual bool contains_reference(const RID &p_rid) const { return multimesh == p_rid; }
|
||||||
|
|
||||||
CommandMultiMesh() { type = TYPE_MULTIMESH; }
|
CommandMultiMesh() { type = TYPE_MULTIMESH; }
|
||||||
|
|
||||||
|
virtual ~CommandMultiMesh() {
|
||||||
|
// Remove any backlinks from multimesh to canvas item.
|
||||||
|
if (multimesh.is_valid()) {
|
||||||
|
RasterizerStorage::base_singleton->multimesh_attach_canvas_item(multimesh, canvas_item, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CommandCircle : public Command {
|
struct CommandCircle : public Command {
|
||||||
@ -1052,6 +1065,20 @@ public:
|
|||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void remove_references(const RID &p_rid) {
|
||||||
|
for (int i = commands.size() - 1; i >= 0; i--) {
|
||||||
|
if (commands[i]->contains_reference(p_rid)) {
|
||||||
|
memdelete(commands[i]);
|
||||||
|
|
||||||
|
// This could possibly be unordered if occurring close
|
||||||
|
// to canvas_item deletion, but is
|
||||||
|
// unlikely to make much performance difference,
|
||||||
|
// and is safer.
|
||||||
|
commands.remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
for (int i = 0; i < commands.size(); i++) {
|
for (int i = 0; i < commands.size(); i++) {
|
||||||
memdelete(commands[i]);
|
memdelete(commands[i]);
|
||||||
|
@ -1417,10 +1417,17 @@ void RenderingServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh, RI
|
|||||||
mm->multimesh = p_mesh;
|
mm->multimesh = p_mesh;
|
||||||
mm->texture = p_texture;
|
mm->texture = p_texture;
|
||||||
mm->normal_map = p_normal_map;
|
mm->normal_map = p_normal_map;
|
||||||
|
mm->canvas_item = p_item;
|
||||||
|
|
||||||
canvas_item->rect_dirty = true;
|
canvas_item->rect_dirty = true;
|
||||||
canvas_item->commands.push_back(mm);
|
canvas_item->commands.push_back(mm);
|
||||||
_make_bound_dirty(canvas_item);
|
_make_bound_dirty(canvas_item);
|
||||||
|
|
||||||
|
// Attach to multimesh a backlink to enable updating
|
||||||
|
// the canvas item local bound when the multimesh changes.
|
||||||
|
if (p_mesh.is_valid()) {
|
||||||
|
RSG::storage->multimesh_attach_canvas_item(p_mesh, p_item, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingServerCanvas::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) {
|
void RenderingServerCanvas::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) {
|
||||||
@ -1584,7 +1591,16 @@ void RenderingServerCanvas::canvas_item_attach_skeleton(RID p_item, RID p_skelet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingServerCanvas::_canvas_item_skeleton_moved(RID p_item) {
|
// Canvas items may contain references to other resources (such as MultiMesh).
|
||||||
|
// If the resources are deleted first, and the canvas_item retains references, it
|
||||||
|
// will crash / error when it tries to access these.
|
||||||
|
void RenderingServerCanvas::_canvas_item_remove_references(RID p_item, RID p_rid) {
|
||||||
|
Item *canvas_item = canvas_item_owner.getornull(p_item);
|
||||||
|
ERR_FAIL_COND(!canvas_item);
|
||||||
|
canvas_item->remove_references(p_rid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderingServerCanvas::_canvas_item_invalidate_local_bound(RID p_item) {
|
||||||
Item *canvas_item = canvas_item_owner.getornull(p_item);
|
Item *canvas_item = canvas_item_owner.getornull(p_item);
|
||||||
ERR_FAIL_COND(!canvas_item);
|
ERR_FAIL_COND(!canvas_item);
|
||||||
_make_bound_dirty(canvas_item);
|
_make_bound_dirty(canvas_item);
|
||||||
|
@ -256,7 +256,6 @@ public:
|
|||||||
void canvas_item_set_use_parent_material(RID p_item, bool p_enable);
|
void canvas_item_set_use_parent_material(RID p_item, bool p_enable);
|
||||||
|
|
||||||
void canvas_item_attach_skeleton(RID p_item, RID p_skeleton);
|
void canvas_item_attach_skeleton(RID p_item, RID p_skeleton);
|
||||||
void _canvas_item_skeleton_moved(RID p_item);
|
|
||||||
void canvas_item_set_skeleton_relative_xform(RID p_item, Transform2D p_relative_xform);
|
void canvas_item_set_skeleton_relative_xform(RID p_item, Transform2D p_relative_xform);
|
||||||
Rect2 _debug_canvas_item_get_rect(RID p_item);
|
Rect2 _debug_canvas_item_get_rect(RID p_item);
|
||||||
Rect2 _debug_canvas_item_get_local_bound(RID p_item);
|
Rect2 _debug_canvas_item_get_local_bound(RID p_item);
|
||||||
@ -265,6 +264,9 @@ public:
|
|||||||
void canvas_item_reset_physics_interpolation(RID p_item);
|
void canvas_item_reset_physics_interpolation(RID p_item);
|
||||||
void canvas_item_transform_physics_interpolation(RID p_item, Transform2D p_transform);
|
void canvas_item_transform_physics_interpolation(RID p_item, Transform2D p_transform);
|
||||||
|
|
||||||
|
void _canvas_item_invalidate_local_bound(RID p_item);
|
||||||
|
void _canvas_item_remove_references(RID p_item, RID p_rid);
|
||||||
|
|
||||||
RID canvas_light_create();
|
RID canvas_light_create();
|
||||||
void canvas_light_attach_to_canvas(RID p_light, RID p_canvas);
|
void canvas_light_attach_to_canvas(RID p_light, RID p_canvas);
|
||||||
void canvas_light_set_enabled(RID p_light, bool p_enabled);
|
void canvas_light_set_enabled(RID p_light, bool p_enabled);
|
||||||
|
Loading…
Reference in New Issue
Block a user