Add compact generated icon button surfaces
This commit is contained in:
@@ -2994,6 +2994,8 @@ func _check_generated_button_textures(failures: Array[String]) -> void:
|
||||
var button_keys := ["normal", "hover", "pressed", "disabled"]
|
||||
for button_key in button_keys:
|
||||
_check_button_texture_path(failures, "res://art/ui/buttons/button_%s.png" % button_key, "button texture %s" % button_key)
|
||||
for button_key in button_keys:
|
||||
_check_icon_button_texture_path(failures, "res://art/ui/buttons/button_icon_%s.png" % button_key, "icon button texture %s" % button_key)
|
||||
|
||||
|
||||
func _check_generated_tile_marker_textures(failures: Array[String]) -> void:
|
||||
@@ -4134,12 +4136,26 @@ func _check_button_uses_generated_surface(failures: Array[String], button: Butto
|
||||
if style.texture == null:
|
||||
failures.append("%s generated button style is missing its texture" % context)
|
||||
return
|
||||
if style.texture.get_width() < 512 or style.texture.get_height() < 192:
|
||||
failures.append("%s generated button texture should keep high-resolution source pixels: %dx%d" % [context, style.texture.get_width(), style.texture.get_height()])
|
||||
if style.texture_margin_left < 48 or style.texture_margin_top < 24:
|
||||
failures.append("%s generated button texture should define visible frame slice margins" % context)
|
||||
if style.content_margin_left < 8 or style.content_margin_top < 5:
|
||||
failures.append("%s generated button texture should reserve readable content margins" % context)
|
||||
if bool(button.get_meta("icon_only", false)):
|
||||
if not bool(button.get_meta("generated_icon_button_texture", false)):
|
||||
failures.append("%s icon-only button should use the generated compact icon surface" % context)
|
||||
if style.texture.get_width() < 256 or style.texture.get_height() < 256:
|
||||
failures.append("%s generated icon button texture should keep high-resolution source pixels: %dx%d" % [context, style.texture.get_width(), style.texture.get_height()])
|
||||
if abs(style.texture.get_width() - style.texture.get_height()) > 4:
|
||||
failures.append("%s generated icon button texture should be square or near-square: %dx%d" % [context, style.texture.get_width(), style.texture.get_height()])
|
||||
if style.texture_margin_left < 48 or style.texture_margin_top < 48:
|
||||
failures.append("%s generated icon button texture should define visible frame slice margins" % context)
|
||||
if style.content_margin_left < 5 or style.content_margin_top < 5:
|
||||
failures.append("%s generated icon button texture should reserve icon content margins" % context)
|
||||
else:
|
||||
if bool(button.get_meta("generated_icon_button_texture", false)):
|
||||
failures.append("%s text button should keep the wide generated button surface" % context)
|
||||
if style.texture.get_width() < 512 or style.texture.get_height() < 192:
|
||||
failures.append("%s generated button texture should keep high-resolution source pixels: %dx%d" % [context, style.texture.get_width(), style.texture.get_height()])
|
||||
if style.texture_margin_left < 48 or style.texture_margin_top < 24:
|
||||
failures.append("%s generated button texture should define visible frame slice margins" % context)
|
||||
if style.content_margin_left < 8 or style.content_margin_top < 5:
|
||||
failures.append("%s generated button texture should reserve readable content margins" % context)
|
||||
|
||||
|
||||
func _check_local_command_icon_button(failures: Array[String], button: Button, expected_label: String, expected_icon: String) -> void:
|
||||
@@ -5489,6 +5505,64 @@ func _check_button_texture_path(failures: Array[String], path: String, context:
|
||||
failures.append("%s should avoid a dominant yellow UI cast: %s (warm bias %.3f)" % [context, path, warm_bias])
|
||||
|
||||
|
||||
func _check_icon_button_texture_path(failures: Array[String], path: String, context: String) -> void:
|
||||
if path.is_empty():
|
||||
failures.append("%s has an empty icon button path" % context)
|
||||
return
|
||||
if not path.begins_with("res://"):
|
||||
failures.append("%s must use a res:// path: %s" % [context, path])
|
||||
return
|
||||
if not FileAccess.file_exists(path):
|
||||
failures.append("%s references missing icon button texture: %s" % [context, path])
|
||||
return
|
||||
var image := Image.new()
|
||||
var err := image.load(path)
|
||||
if err != OK:
|
||||
failures.append("%s references unreadable icon button texture: %s" % [context, path])
|
||||
return
|
||||
if image.get_width() < 256 or image.get_height() < 256:
|
||||
failures.append("%s should keep high-resolution compact source pixels: %s (%dx%d)" % [context, path, image.get_width(), image.get_height()])
|
||||
return
|
||||
if abs(image.get_width() - image.get_height()) > 4:
|
||||
failures.append("%s should be a square compact icon surface: %s (%dx%d)" % [context, path, image.get_width(), image.get_height()])
|
||||
return
|
||||
for corner in [Vector2i(0, 0), Vector2i(image.get_width() - 1, 0), Vector2i(0, image.get_height() - 1), Vector2i(image.get_width() - 1, image.get_height() - 1)]:
|
||||
if image.get_pixelv(corner).a > 0.01:
|
||||
failures.append("%s should have transparent corners: %s" % [context, path])
|
||||
return
|
||||
var opaque_samples := 0
|
||||
var transparent_samples := 0
|
||||
var green_fringe_samples := 0
|
||||
var luma_min := 999.0
|
||||
var luma_max := -999.0
|
||||
var total_samples := 0
|
||||
for y in range(0, image.get_height(), 8):
|
||||
for x in range(0, image.get_width(), 8):
|
||||
total_samples += 1
|
||||
var pixel := image.get_pixel(x, y)
|
||||
if pixel.a <= 0.01:
|
||||
transparent_samples += 1
|
||||
continue
|
||||
if pixel.a >= 0.80:
|
||||
opaque_samples += 1
|
||||
if pixel.g > 0.80 and pixel.r < 0.18 and pixel.b < 0.18:
|
||||
green_fringe_samples += 1
|
||||
var luma := pixel.r * 0.299 + pixel.g * 0.587 + pixel.b * 0.114
|
||||
luma_min = minf(luma_min, luma)
|
||||
luma_max = maxf(luma_max, luma)
|
||||
if transparent_samples < int(total_samples * 0.08):
|
||||
failures.append("%s should retain transparent compact button padding: %s (%d/%d sampled pixels)" % [context, path, transparent_samples, total_samples])
|
||||
if opaque_samples < int(total_samples * 0.42):
|
||||
failures.append("%s should contain substantial generated compact button artwork: %s (%d/%d sampled pixels)" % [context, path, opaque_samples, total_samples])
|
||||
if green_fringe_samples > 0:
|
||||
failures.append("%s should not keep chroma-key green pixels: %s (%d sampled)" % [context, path, green_fringe_samples])
|
||||
if luma_max - luma_min < 0.08:
|
||||
failures.append("%s should contain visible material contrast: %s" % [context, path])
|
||||
var warm_bias := _image_visible_warm_bias(image, 8)
|
||||
if warm_bias > 0.12:
|
||||
failures.append("%s should avoid a dominant yellow UI cast: %s (warm bias %.3f)" % [context, path, warm_bias])
|
||||
|
||||
|
||||
func _image_visible_warm_bias(image: Image, sample_step: int) -> float:
|
||||
var total_bias := 0.0
|
||||
var visible_samples := 0
|
||||
|
||||
Reference in New Issue
Block a user