Batching - Protection against zero and small sized ninepatches
Although the minimum size of ninepatches is set to the sum of the margins in normal use (through gdscript etc) it turns out that it is possible to programmatically create ninepatches that are small than this minimum - in particular zero size is used in sliders to not draw items. This PR deals with zero sized ninepatches by not drawing anything, and has some basic protection for ninepatches smaller than the margins. Whether these occur in the wild is not clear but is put in for completeness.
This commit is contained in:
parent
fd6b3060c1
commit
2d6cb3e208
1 changed files with 27 additions and 10 deletions
|
@ -1357,6 +1357,22 @@ template <bool SEND_LIGHT_ANGLES>
|
||||||
bool C_PREAMBLE::_prefill_ninepatch(RasterizerCanvas::Item::CommandNinePatch *p_np, FillState &r_fill_state, int &r_command_start, int command_num, int command_count, RasterizerCanvas::Item *p_item, bool multiply_final_modulate) {
|
bool C_PREAMBLE::_prefill_ninepatch(RasterizerCanvas::Item::CommandNinePatch *p_np, FillState &r_fill_state, int &r_command_start, int command_num, int command_count, RasterizerCanvas::Item *p_item, bool multiply_final_modulate) {
|
||||||
typename T_STORAGE::Texture *tex = get_storage()->texture_owner.getornull(p_np->texture);
|
typename T_STORAGE::Texture *tex = get_storage()->texture_owner.getornull(p_np->texture);
|
||||||
|
|
||||||
|
if (!tex) {
|
||||||
|
// FIXME: Handle textureless ninepatch gracefully
|
||||||
|
WARN_PRINT("NinePatch without texture not supported yet, skipping.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (tex->width == 0 || tex->height == 0) {
|
||||||
|
WARN_PRINT("Cannot set empty texture to NinePatch.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cope with ninepatch of zero area. These cannot be created by the user interface or gdscript, but can
|
||||||
|
// be created programmatically from c++, e.g. by the Godot UI for sliders. We will just not draw these.
|
||||||
|
if ((p_np->rect.size.x * p_np->rect.size.y) <= 0.0f) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// conditions for creating a new batch
|
// conditions for creating a new batch
|
||||||
if (r_fill_state.curr_batch->type != RasterizerStorageCommon::BT_RECT) {
|
if (r_fill_state.curr_batch->type != RasterizerStorageCommon::BT_RECT) {
|
||||||
|
|
||||||
|
@ -1368,16 +1384,6 @@ bool C_PREAMBLE::_prefill_ninepatch(RasterizerCanvas::Item::CommandNinePatch *p_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tex) {
|
|
||||||
// FIXME: Handle textureless ninepatch gracefully
|
|
||||||
WARN_PRINT("NinePatch without texture not supported yet in GLES2 backend, skipping.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (tex->width == 0 || tex->height == 0) {
|
|
||||||
WARN_PRINT("Cannot set empty texture to NinePatch.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// first check there are enough verts for this to complete successfully
|
// first check there are enough verts for this to complete successfully
|
||||||
if (bdata.vertices.size() + (4 * 9) > bdata.vertices.max_size()) {
|
if (bdata.vertices.size() + (4 * 9) > bdata.vertices.max_size()) {
|
||||||
// return where we got to
|
// return where we got to
|
||||||
|
@ -1446,6 +1452,17 @@ bool C_PREAMBLE::_prefill_ninepatch(RasterizerCanvas::Item::CommandNinePatch *p_
|
||||||
v[3] = v[0] + source.size.y;
|
v[3] = v[0] + source.size.y;
|
||||||
v[2] = v[3] - tex_margin_bottom;
|
v[2] = v[3] - tex_margin_bottom;
|
||||||
|
|
||||||
|
// Some protection for the use of ninepatches with rect size smaller than margin size.
|
||||||
|
// Note these cannot be produced by the UI, only programmatically, and the results
|
||||||
|
// are somewhat undefined, because the margins overlap.
|
||||||
|
// Ninepatch get_minimum_size() forces minimum size to be the sum of the margins.
|
||||||
|
// So this should occur very rarely if ever. Consider commenting these 4 lines out for higher speed
|
||||||
|
// in ninepatches.
|
||||||
|
x[1] = MIN(x[1], x[3]);
|
||||||
|
x[2] = MIN(x[2], x[3]);
|
||||||
|
y[1] = MIN(y[1], y[3]);
|
||||||
|
y[2] = MIN(y[2], y[3]);
|
||||||
|
|
||||||
// temporarily override to prevent single rect fallback
|
// temporarily override to prevent single rect fallback
|
||||||
bool single_rect_fallback = bdata.settings_use_single_rect_fallback;
|
bool single_rect_fallback = bdata.settings_use_single_rect_fallback;
|
||||||
bdata.settings_use_single_rect_fallback = false;
|
bdata.settings_use_single_rect_fallback = false;
|
||||||
|
|
Loading…
Reference in a new issue