diff --git a/manager/scene/scene_manager.gd b/manager/scene/scene_manager.gd index 1647706b..68b4a7ff 100644 --- a/manager/scene/scene_manager.gd +++ b/manager/scene/scene_manager.gd @@ -175,10 +175,10 @@ func checkout_prop_inventory(character: String) -> void: else: printerr("checkout_prop_inventory: PropHud node not found") - -func get_current_prop(must_selected: bool) -> String: +# 无效参数 +func get_current_prop(_must_selected = null) -> String: var prop_hud = get_prop_hud() - if prop_hud and (not must_selected or prop_hud.selected): + if prop_hud: return prop_hud.inventory.current_item_key() return "" diff --git a/scene/ux/prop_hud.gd b/scene/ux/prop_hud.gd index ef04a7dd..6f161531 100644 --- a/scene/ux/prop_hud.gd +++ b/scene/ux/prop_hud.gd @@ -3,6 +3,14 @@ class_name PropHud extends Control signal current_item_changed(prop_key: String) +# 常量定义 +const PROP_CONTAINER_X = 130.0 +const PROP_CONTROL_X = 110.0 +const TWEEN_DURATION = 0.5 +const SHAKE_FPS = 15.0 +const SHAKE_DURATION = 0.8 +const SHAKE_DELTA = 12.0 + @export_group("DebugItem") @export var enable_item := false: set(value): @@ -10,12 +18,18 @@ signal current_item_changed(prop_key: String) enable_item = false enable_prop_item(item_key) @export var item_key: String + @export_group("Inventory") @export var inventory: PropInventory: set(value): + if inventory == value: + return + if inventory and inventory.current_item_changed.is_connected(_emit_changed): + inventory.current_item_changed.disconnect(_emit_changed) inventory = value if inventory and not inventory.current_item_changed.is_connected(_emit_changed): inventory.current_item_changed.connect(_emit_changed) + @export_group("UI-UX") @export var display_time := 2.5 # 不包含渐入渐出(约 0.6s)的时长 @export var locked := false: @@ -45,10 +59,8 @@ signal current_item_changed(prop_key: String) @onready var props_bag_scroll = %PropsBagScroll as ScrollContainer @onready var props_bag = %PropsBag as HBoxContainer @onready var select_mark = %SelectMark as TextureRect -var prop_containers = [] #CenterContainer -const PROP_CONTAINER_X = 130.0 -const PROP_CONTROL_X = 110.0 +var prop_containers: Array[CenterContainer] = [] var items_dict := {} var items_description_dict = {} # 从配置文件加载 prop items @@ -62,10 +74,16 @@ var displaying = false var timer := Timer.new() var display_tween: Tween var container_tween: Tween +var prop_blink: Tween +var tween_scroll: Tween +var shake_tween: Tween # hud 是否监听快捷键 var listening_hotkey = true +# 缓存的占位符纹理 +var placeholder_texture: Texture2D + func _emit_changed(prop_key := ""): if not selected: @@ -77,33 +95,43 @@ func _emit_changed(prop_key := ""): func _ready() -> void: if Engine.is_editor_hint(): return + + # 初始化占位符纹理 + placeholder_texture = preload("res://asset/art/ui/hud/placeholder.png") + # read prop containers for id in range(props_bag.get_child_count()): var container = props_bag.get_child(id) prop_containers.append(container) - container.get_child(0).get_child(0).gui_input.connect(_on_prop_gui_input.bind(id)) + var button = container.get_child(0).get_child(0) + if button: + button.gui_input.connect(_on_prop_gui_input.bind(id)) + display_prop.gui_input.connect(_on_prop_gui_input.bind(-1)) + _load_items_config_to_dict("ImportantPropItems") _load_items_config_to_dict("PropItems") _reload_cache_and_realign_display() + selecting_bg.modulate.a = 0.0 prop_scroll.scroll_horizontal = PROP_CONTAINER_X props_bag_scroll.scroll_horizontal = 0.0 props_bag_scroll.custom_minimum_size.x = 0.0 - # focus_exited.connect(_on_focus_exited) + # 存档更新时,从存档加载 prop ArchiveManager.archive_loaded.connect(_reload_cache_and_realign_display) + # tween timer timer.wait_time = display_time timer.one_shot = true timer.autostart = false timer.timeout.connect(_on_timer_timeout) add_child(timer) + # connect signals left_btn.pressed.connect(on_left_pressed) right_btn.pressed.connect(on_right_pressed) title_label.modulate.a = 0.0 - # _toggle_btn_ability(false) left_btn.modulate.a = 0.5 right_btn.modulate.a = 0.5 mouse_entered.connect(_on_mouse_entered) @@ -111,51 +139,36 @@ func _ready() -> void: func _load_items_config_to_dict(title: String): + if not item_config_res or not item_config_res.titles.has(title): + return + var id = item_config_res.titles[title] - var current_line = item_config_res.lines[id] + var current_line = item_config_res.lines.get(id) + while current_line: if current_line.has("tags") and current_line.has("translation_key"): - var wrapped_texture := "texture=" - var wrapped_inspect := "inspect=" var texture_path = "" var inspect_path = "" - for t in current_line.tags: - if t.begins_with(wrapped_texture): - texture_path = t.replace(wrapped_texture, "").strip_edges() - elif t.begins_with(wrapped_inspect): - inspect_path = t.replace(wrapped_inspect, "").strip_edges() + + for tag in current_line.tags: + if tag.begins_with("texture="): + texture_path = tag.substr(8).strip_edges() + elif tag.begins_with("inspect="): + inspect_path = tag.substr(8).strip_edges() + var item = PropItem.new() item.key = current_line.translation_key if texture_path: item.texture_path = path_prefix + texture_path if inspect_path: item.inspect_path = path_prefix + inspect_path + items_dict[item.key] = item - # # 检查是否是重要物品,如果是,则添加到 items_description_dict items_description_dict[item.key] = tr(item.key + "_说明").replace("{br}", "\n") - # if item_config_res.titles.has(item.key): - # var important_item_line_id = item_config_res.titles[item.key] - # items_description_dict[item.key] = get_import_item_content(important_item_line_id) if not current_line.has("next_id") or current_line.next_id == "end": break - current_line = item_config_res.lines[current_line.next_id] - - -# func get_import_item_content(line_id) -> String: -# var current_line = item_config_res.lines[line_id] -# var content = "" -# while current_line: -# if current_line.has("text"): -# if current_line.has("translation_key"): -# content += tr(current_line.translation_key) + "\n" -# else: -# content += current_line.text + "\n" -# if not current_line.has("next_id") or current_line.next_id == "end": -# break -# current_line = item_config_res.lines[current_line.next_id] -# content.replace("{br}", "\n") -# return content + current_line = item_config_res.lines.get(current_line.next_id) func _reload_cache_and_realign_display() -> void: @@ -174,57 +187,90 @@ func checkout_inventory(character: String) -> void: _reload_cache_and_realign_display() -func hide_hud(): - # 隐藏 hud 并静音 - hide() +const HUD_FADE_DURATION = 0.3 + +# 在变量定义区域添加 +var hud_visibility_tween: Tween + +func hide_hud(duration: float = HUD_FADE_DURATION): + if not visible: + return listening_hotkey = false + # 清理之前的补间动画 + if hud_visibility_tween and hud_visibility_tween.is_running(): + hud_visibility_tween.kill() + # 创建渐变动画 + hud_visibility_tween = create_tween() + hud_visibility_tween.tween_property(self, "modulate:a", 0.0, duration) + hud_visibility_tween.tween_callback(hide) -func display_hud(): - # 显示 hud 并取消静音 - show() - listening_hotkey = true +func display_hud(duration: float = HUD_FADE_DURATION): + if visible and modulate.a >= 1.0: + return + # 清理之前的补间动画 + if hud_visibility_tween and hud_visibility_tween.is_running(): + hud_visibility_tween.kill() + # 确保节点可见但透明 + if not visible: + modulate.a = 0.0 + show() + # 创建渐变动画 + hud_visibility_tween = create_tween() + hud_visibility_tween.tween_property(self, "modulate:a", 1.0, duration) + hud_visibility_tween.tween_callback(func(): listening_hotkey = true) func _load_texture_cache() -> void: if not inventory: return + + # 移除无效纹理 + var keys_to_remove = [] for k in cached_inventory_textures: - # remove invalid textures if not k in inventory.enabled_items: - cached_inventory_textures.erase(k) + keys_to_remove.append(k) + + for k in keys_to_remove: + cached_inventory_textures.erase(k) + + # 加载新纹理 for key in inventory.enabled_items: if cached_inventory_textures.has(key): continue - # 以 items_dict 为准,如果 enabled_items 中的 key 不存在,则删除 - if not key in items_dict: + + if not items_dict.has(key): inventory.disable_item(key) printerr( "PropHud _load_texture_cache: key not found in items_dict:", key, ". remove item." ) continue + var path = items_dict[key].texture_path if not path: - var placeholder = preload("res://asset/art/ui/hud/placeholder.png") - cached_inventory_textures[key] = placeholder + cached_inventory_textures[key] = placeholder_texture print("Cache load prop placeholder key=", key) continue + var texture = load(path) as Texture2D if texture: if GlobalConfig.DEBUG: print("Cache load prop texture key=", key) cached_inventory_textures[key] = texture + # wrap index - inventory.current_index = wrapi(inventory.current_index, 0, inventory.enabled_items.size()) + if inventory.enabled_items.size() > 0: + inventory.current_index = wrapi(inventory.current_index, 0, inventory.enabled_items.size()) func _update_prop_display_with_texture(): if not inventory: return + var key = "" # 在没有道具时,展示空手 placeholder if inventory.enabled_items.is_empty(): - display_prop.texture_normal = preload("res://asset/art/ui/hud/placeholder.png") + display_prop.texture_normal = placeholder_texture display_prop.size = Vector2(PROP_CONTROL_X, PROP_CONTROL_X) display_prop.scale = Vector2(1.0, 1.0) title_label.text = tr("prop_空手") @@ -232,36 +278,48 @@ func _update_prop_display_with_texture(): key = inventory.current_item_key() _display_texture_by_key(display_prop, key) title_label.text = tr(key) + # 如果当前是 prop_小猫玩具完整,尝试点亮玩家的灯效;否则无需点亮 var player = SceneManager.get_player() if player: player.set_catty_light(key == "prop_小猫玩具完整") + if GlobalConfig.DEBUG: print("[PropHud] current display prop:", key) - # 选中标记 select_mark; 如果被 free 掉,则重新创建 - if select_mark and is_instance_valid(select_mark): - var parent = select_mark.get_parent() - if parent: - parent.remove_child(select_mark) - else: - select_mark = TextureRect.new() - select_mark.custom_minimum_size = Vector2(PROP_CONTAINER_X, PROP_CONTAINER_X) - select_mark.texture = preload("res://asset/art/ui/hud/select_mark.png") - # bag + + # 选中标记处理 + _update_select_mark() + + # bag更新 for i in range(inventory.enabled_items.size()): var id = wrapi(i, 0, inventory.enabled_items.size()) var k = inventory.enabled_items[id] - var button = prop_containers[i].get_child(0).get_child(0) as TextureButton + var container = prop_containers[i] + var button = container.get_child(0).get_child(0) as TextureButton _display_texture_by_key(button, k) if id == inventory.current_index: - prop_containers[i].get_child(0).add_child(select_mark) + container.get_child(0).add_child(select_mark) + prop_scroll.scroll_horizontal = PROP_CONTAINER_X - # props_bag_scroll.scroll_horizontal = 0.0 -func _display_texture_by_key(button, key) -> void: - if not key: - button.texture_normal = null +func _update_select_mark(): + if not is_instance_valid(select_mark): + select_mark = TextureRect.new() + select_mark.custom_minimum_size = Vector2(PROP_CONTAINER_X, PROP_CONTAINER_X) + select_mark.texture = preload("res://asset/art/ui/hud/select_mark.png") + else: + var parent = select_mark.get_parent() + if parent: + parent.remove_child(select_mark) + + +func _display_texture_by_key(button: TextureButton, key: String) -> void: + if not key or not button: + if button: + button.texture_normal = null + return + if not items_dict.has(key): return var item = items_dict[key] var texture = cached_inventory_textures.get(item.key) @@ -270,14 +328,15 @@ func _display_texture_by_key(button, key) -> void: texture = load(item.texture_path) as Texture2D if not texture: printerr("PropHud _display_texture_by_key: No texture found for item:", item) + return else: cached_inventory_textures[item.key] = texture button.texture_normal = texture - var t_size = button.texture_normal.get_size() - var max_x = max(t_size.x, t_size.y) + var t_size = texture.get_size() + var max_dimension = max(t_size.x, t_size.y) var p_scale = min(PROP_CONTROL_X / t_size.x, PROP_CONTROL_X / t_size.y) button.scale = Vector2(p_scale, p_scale) - button.size = Vector2(max_x, max_x) + button.size = Vector2(max_dimension, max_dimension) func on_left_pressed() -> void: @@ -305,34 +364,37 @@ func on_right_pressed() -> void: func _tween_container(left_to_right := true) -> void: if container_tween and container_tween.is_running(): container_tween.kill() + container_tween = create_tween() - if left_to_right: - prop_scroll.scroll_horizontal = 2 * PROP_CONTAINER_X - else: - prop_scroll.scroll_horizontal = 0.0 - # 通过 Head 与 Tail 占位符,实现滚动效果;否则会导致卡在边界上,无法滚动 + prop_scroll.scroll_horizontal = 2 * PROP_CONTAINER_X if left_to_right else 0.0 container_tween.tween_property(prop_scroll, "scroll_horizontal", PROP_CONTAINER_X, 0.2) -func _on_prop_gui_input(event: InputEvent, id) -> void: - if locked: +func _on_prop_gui_input(event: InputEvent, id: int) -> void: + if locked or not event is InputEventMouseButton: return - if event is InputEventMouseButton and event.is_pressed(): - event = event as InputEventMouseButton - if event.button_index == MOUSE_BUTTON_LEFT: + + var mouse_event = event as InputEventMouseButton + if not mouse_event.is_pressed(): + return + + match mouse_event.button_index: + MOUSE_BUTTON_LEFT: _on_prop_pressed(id) - elif event.button_index == MOUSE_BUTTON_RIGHT: + MOUSE_BUTTON_RIGHT: _on_prop_inspected(id) func _on_prop_inspected(id := 0) -> void: if locked: return + var prop_key = "" - if id >= 0: + if id >= 0 and id < inventory.enabled_items.size(): prop_key = inventory.enabled_items[id] else: prop_key = inventory.current_item_key() + if prop_key: sfx_inspect.play() print("[PropHud] inspect prop:", prop_key) @@ -342,37 +404,37 @@ func _on_prop_inspected(id := 0) -> void: func _on_prop_pressed(id := 0) -> void: if locked: return + sfx_click.play() if GlobalConfig.DEBUG: print("PropHUD Panel pressed.") + focus_mode = FOCUS_ALL grab_focus() selected = true - if id >= 0: + + if id >= 0 and id < inventory.enabled_items.size(): inventory.current_index = id + _update_prop_display_with_texture() _mouse_moved_on_listening(true) -var prop_blink: Tween -var tween_scroll: Tween - - func _toggle_scroll(fold := true) -> void: if prop_blink and prop_blink.is_running(): prop_blink.kill() if tween_scroll and tween_scroll.is_running(): tween_scroll.kill() - # PROP_CONTAINER_X + 10. 为hud的两侧留出的空间 + if fold: # kill blink select_mark.modulate.a = 1.0 selecting_bg.modulate.a = 0.0 # fold tween_scroll = create_tween() - tween_scroll.tween_property(props_bag_scroll, "custom_minimum_size:x", 0.0, 0.5) + tween_scroll.tween_property(props_bag_scroll, "custom_minimum_size:x", 0.0, TWEEN_DURATION) tween_scroll.parallel().tween_property( - hud_rect, "custom_minimum_size:x", PROP_CONTAINER_X + 10., 0.5 + hud_rect, "custom_minimum_size:x", PROP_CONTAINER_X + 10., TWEEN_DURATION ) else: # blink @@ -388,12 +450,17 @@ func _toggle_scroll(fold := true) -> void: prop_blink.parallel().tween_property(selecting_bg, "modulate:a", .6, 1.).set_ease( Tween.EASE_IN_OUT ) + # unfold var bag_x = prop_containers.size() * PROP_CONTAINER_X var hud_x = bag_x + PROP_CONTAINER_X + 10. tween_scroll = create_tween() - tween_scroll.tween_property(props_bag_scroll, "custom_minimum_size:x", bag_x, 0.5) - tween_scroll.parallel().tween_property(hud_rect, "custom_minimum_size:x", hud_x, 0.5) + tween_scroll.tween_property( + props_bag_scroll, "custom_minimum_size:x", bag_x, TWEEN_DURATION + ) + tween_scroll.parallel().tween_property( + hud_rect, "custom_minimum_size:x", hud_x, TWEEN_DURATION + ) func _on_mouse_entered() -> void: @@ -410,9 +477,11 @@ func _on_mouse_exited() -> void: func _mouse_moved_on_listening(unfold_scroll := false) -> void: if unfold_scroll: _toggle_scroll(false) + if not displaying: _toggle_details(true) return + timer.start(display_time) @@ -424,6 +493,7 @@ func _on_timer_timeout() -> void: func _unhandled_input(event: InputEvent) -> void: if locked or not listening_hotkey: return + if event.is_action_pressed("prop_left"): on_left_pressed() get_viewport().set_input_as_handled() @@ -431,17 +501,21 @@ func _unhandled_input(event: InputEvent) -> void: on_right_pressed() get_viewport().set_input_as_handled() elif event is InputEventMouseButton: - if event.button_index == MOUSE_BUTTON_WHEEL_DOWN and event.pressed: - on_left_pressed() - get_viewport().set_input_as_handled() - elif event.button_index == MOUSE_BUTTON_WHEEL_UP and event.pressed: - on_right_pressed() - get_viewport().set_input_as_handled() + var mouse_event = event as InputEventMouseButton + if mouse_event.pressed: + match mouse_event.button_index: + MOUSE_BUTTON_WHEEL_DOWN: + on_left_pressed() + get_viewport().set_input_as_handled() + MOUSE_BUTTON_WHEEL_UP: + on_right_pressed() + get_viewport().set_input_as_handled() func _input(event: InputEvent) -> void: if locked: return + if listen_mouse and (event is InputEventMouseMotion or event is InputEventScreenTouch): _mouse_moved_on_listening() @@ -462,7 +536,6 @@ func _toggle_details(display := true) -> void: display_tween.parallel().tween_property(title_label, "modulate:a", 0.0, 0.6) display_tween.parallel().tween_property(left_btn, "modulate:a", 0.5, 0.5) display_tween.parallel().tween_property(right_btn, "modulate:a", 0.5, 0.5) - # display_tween.tween_callback(_toggle_btn_ability.bind(false)) timer.stop() @@ -474,11 +547,14 @@ func _toggle_btn_ability(v: bool) -> void: func enable_important_item(prop_key: String, display_inspector: bool) -> void: if not inventory or not prop_key: return + if not items_dict.has(prop_key): push_error("ImportantPropItem not found! key=" + prop_key) return + inventory.enable_important_item(prop_key) SceneManager.pop_notification("ui_notify_important_item_update") + if display_inspector: sfx_inspect.play() inspect_item(prop_key, true, true) @@ -488,13 +564,17 @@ func enable_prop_item(prop_key: String, inspect := true) -> void: if not inventory or not prop_key: printerr("PropHUD Enable prop item: No inventory or prop_key provided.") return + if not items_dict.has(prop_key): push_error("PropItem not found! key=" + prop_key) return + inventory.enable_item(prop_key) _reload_cache_and_realign_display() + if GlobalConfig.DEBUG: print("PropHUD Enable prop item:", prop_key) + if inspect: sfx_new_prop.play() inspect_item(prop_key) @@ -502,27 +582,31 @@ func enable_prop_item(prop_key: String, inspect := true) -> void: func inspect_item(prop_key: String, display_obtained := true, as_important_item := false): var inspector = SceneManager.get_inspector() - if inspector: - var texture_path = items_dict[prop_key].texture_path - var inspect_path = items_dict[prop_key].inspect_path - # 是否有独立的 inspect 图片 - if inspect_path: - var texture = load(inspect_path) as Texture2D - inspector.pop_prop_inspection( - prop_key, texture, false, display_obtained, as_important_item - ) - else: - var texture = cached_inventory_textures.get(prop_key) - if not texture: - texture = load(texture_path) as Texture2D - if texture: - cached_inventory_textures[prop_key] = texture - else: - printerr("prophud inspect_item invalid texture_path:", texture_path) - return - inspector.pop_prop_inspection( - prop_key, texture, true, display_obtained, as_important_item - ) + if not inspector or not items_dict.has(prop_key): + return + + var item = items_dict[prop_key] + var texture: Texture2D = null + var is_inspect_texture = false + + # 检查是否有独立的 inspect 图片 + if item.inspect_path: + texture = load(item.inspect_path) as Texture2D + is_inspect_texture = true + else: + texture = cached_inventory_textures.get(prop_key) + if not texture and item.texture_path: + texture = load(item.texture_path) as Texture2D + if texture: + cached_inventory_textures[prop_key] = texture + + if not texture: + printerr("prophud inspect_item invalid texture for key:", prop_key) + return + + inspector.pop_prop_inspection( + prop_key, texture, not is_inspect_texture, display_obtained, as_important_item + ) func disable_prop_item(prop_key: String) -> void: @@ -533,16 +617,21 @@ func disable_prop_item(prop_key: String) -> void: func _align_container_size() -> void: - # 判断是否需要添加新的 prop container + if not inventory: + return + + # 添加新容器 while inventory.enabled_items.size() > prop_containers.size(): append_prop_container() - # 判断是否需要删除 prop container,不保留余数 + + # 删除多余容器 while inventory.enabled_items.size() < prop_containers.size(): remove_prop_container() + if displaying: _mouse_moved_on_listening() # 如果正在展示,则更新 scroll 长度 - if displaying and props_bag_scroll.custom_minimum_size.x > 0.0: + if props_bag_scroll.custom_minimum_size.x > 0.0: _toggle_scroll(false) @@ -550,58 +639,65 @@ func append_prop_container() -> void: var container = CenterContainer.new() container.custom_minimum_size = Vector2(PROP_CONTAINER_X, PROP_CONTAINER_X) container.set_anchors_preset(Control.PRESET_FULL_RECT) - prop_containers.append(container) + var control = Control.new() control.custom_minimum_size = Vector2(PROP_CONTROL_X, PROP_CONTROL_X) control.set_anchors_preset(Control.PRESET_FULL_RECT) container.add_child(control) + var prop = TextureButton.new() prop.stretch_mode = TextureButton.STRETCH_KEEP_ASPECT_CENTERED control.add_child(prop) - # 添加到 hbox: container -> control -> prop + props_bag.add_child(container) - prop.gui_input.connect(_on_prop_gui_input.bind(prop_containers.size() - 1)) + prop_containers.append(container) + + var index = prop_containers.size() - 1 + prop.gui_input.connect(_on_prop_gui_input.bind(index)) func remove_prop_container() -> void: - if prop_containers.size() == 0: + if prop_containers.is_empty(): return + var container = prop_containers.pop_back() - props_bag.remove_child(container) - container.queue_free() + if container and is_instance_valid(container): + props_bag.remove_child(container) + container.queue_free() -var shake_tween - - -# 使用无效道具,抖动提示 func on_toggle_invalid_prop(): if not inventory or not inventory.current_item_key(): return + if GlobalConfig.DEBUG: print("使用无效道具. invalid_prop shake. current prop:", inventory.current_item_key()) - if shake_tween: + + if shake_tween and shake_tween.is_running(): shake_tween.kill() - # 抖动效果,逐渐减弱 + + # 抖动效果 shake_tween = create_tween() - var fps := 15.0 - var duration := 0.8 - var delta := 12.0 + var count = int(SHAKE_DURATION * SHAKE_FPS) + var delta_t = 1.0 / SHAKE_FPS var origin_pos = Vector2.ZERO - var count = int(duration * fps) - var delta_t = 1.0 / fps var prop = display_prop - # var prop = prop_containers[0].get_child(0) + prop.modulate = Color(1.0, 0.6, 0.6, 1.0) + for i in range(count): - var offset = Vector2(randf_range(-delta, delta), randf_range(-delta, delta)) * exp(-i) + var decay = exp(-i) + var offset = Vector2( + randf_range(-SHAKE_DELTA, SHAKE_DELTA) * decay, + randf_range(-SHAKE_DELTA, SHAKE_DELTA) * decay + ) shake_tween.tween_property(prop, "position", origin_pos + offset, delta_t).set_trans( Tween.TRANS_CUBIC ) + shake_tween.tween_callback(_reset_prop_modulate) func _reset_prop_modulate(): - var prop = display_prop - # var prop = prop_containers[0].get_child(0) - prop.modulate = Color(1.0, 1.0, 1.0, 1.0) + if display_prop: + display_prop.modulate = Color.WHITE