Collapse contextual building actions
This commit is contained in:
parent
1c9ac62e8c
commit
d79c756d5b
4 changed files with 110 additions and 34 deletions
|
|
@ -19,6 +19,7 @@ extends Node2D
|
||||||
@onready var world_map: Control = get_node("../UI/WorldMap")
|
@onready var world_map: Control = get_node("../UI/WorldMap")
|
||||||
@onready var build_button: IconButton = get_node("../UI/BuildButton")
|
@onready var build_button: IconButton = get_node("../UI/BuildButton")
|
||||||
@onready var action_button: IconButton = get_node("../UI/BuildActionButton")
|
@onready var action_button: IconButton = get_node("../UI/BuildActionButton")
|
||||||
|
@onready var building_action_button: IconButton = get_node("../UI/BuildingActionButton")
|
||||||
|
|
||||||
@onready var build_menu: Control = get_node("../UI/BuildMenu")
|
@onready var build_menu: Control = get_node("../UI/BuildMenu")
|
||||||
@onready var build_mothership_button: IconButton = get_node("../UI/BuildMenu/MothershipButton")
|
@onready var build_mothership_button: IconButton = get_node("../UI/BuildMenu/MothershipButton")
|
||||||
|
|
@ -209,6 +210,7 @@ var transfer_building_id: int = 0
|
||||||
var current_building: Node2D = null
|
var current_building: Node2D = null
|
||||||
var pending_building: Node2D = null
|
var pending_building: Node2D = null
|
||||||
var pending_time: float = 0.0
|
var pending_time: float = 0.0
|
||||||
|
var context_actions_expanded: bool = false
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
|
@ -230,7 +232,8 @@ func _ready() -> void:
|
||||||
info_close_button.pressed.connect(_close_info)
|
info_close_button.pressed.connect(_close_info)
|
||||||
info_build_button.pressed.connect(_confirm_build)
|
info_build_button.pressed.connect(_confirm_build)
|
||||||
|
|
||||||
action_button.pressed.connect(_on_action_pressed)
|
action_button.pressed.connect(_on_context_action_pressed)
|
||||||
|
building_action_button.pressed.connect(_on_action_pressed)
|
||||||
|
|
||||||
craft_interceptor_button.pressed.connect(_on_craft_interceptor)
|
craft_interceptor_button.pressed.connect(_on_craft_interceptor)
|
||||||
craft_transporter_button.pressed.connect(_on_craft_transporter)
|
craft_transporter_button.pressed.connect(_on_craft_transporter)
|
||||||
|
|
@ -266,6 +269,7 @@ func _ready() -> void:
|
||||||
lab_menu.visible = false
|
lab_menu.visible = false
|
||||||
transfer_menu.visible = false
|
transfer_menu.visible = false
|
||||||
action_button.visible = false
|
action_button.visible = false
|
||||||
|
building_action_button.visible = false
|
||||||
transfer_button.visible = false
|
transfer_button.visible = false
|
||||||
hangar_button.visible = false
|
hangar_button.visible = false
|
||||||
hangar_menu.visible = false
|
hangar_menu.visible = false
|
||||||
|
|
@ -281,6 +285,12 @@ func is_showing_building_prompt() -> bool:
|
||||||
|
|
||||||
|
|
||||||
func _unhandled_input(event: InputEvent) -> void:
|
func _unhandled_input(event: InputEvent) -> void:
|
||||||
|
if context_actions_expanded and (event is InputEventScreenTouch and event.pressed \
|
||||||
|
or event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT):
|
||||||
|
# Buttons consume their own touch; reaching this handler means the tap
|
||||||
|
# landed somewhere else, which dismisses an expanded action list.
|
||||||
|
_collapse_context_actions()
|
||||||
|
|
||||||
# The formation editor and the skill tree are driven from here rather than
|
# The formation editor and the skill tree are driven from here rather than
|
||||||
# via _gui_input, for the same reason as the joystick: a Control that
|
# via _gui_input, for the same reason as the joystick: a Control that
|
||||||
# consumes touches through the GUI system swallows them before they get
|
# consumes touches through the GUI system swallows them before they get
|
||||||
|
|
@ -337,8 +347,10 @@ func _process(delta: float) -> void:
|
||||||
current_building = null
|
current_building = null
|
||||||
pending_building = null
|
pending_building = null
|
||||||
action_button.visible = false
|
action_button.visible = false
|
||||||
|
building_action_button.visible = false
|
||||||
transfer_button.visible = false
|
transfer_button.visible = false
|
||||||
hangar_button.visible = false
|
hangar_button.visible = false
|
||||||
|
context_actions_expanded = false
|
||||||
return
|
return
|
||||||
|
|
||||||
# Debounced exactly like the enter-atmosphere prompt, so the action
|
# Debounced exactly like the enter-atmosphere prompt, so the action
|
||||||
|
|
@ -355,7 +367,7 @@ func _process(delta: float) -> void:
|
||||||
return
|
return
|
||||||
|
|
||||||
current_building = pending_building
|
current_building = pending_building
|
||||||
action_button.visible = current_building != null
|
context_actions_expanded = false
|
||||||
# The hangar is where finished vessels are delivered (#23), so it belongs
|
# The hangar is where finished vessels are delivered (#23), so it belongs
|
||||||
# at the mothership and nowhere else.
|
# at the mothership and nowhere else.
|
||||||
hangar_button.visible = current_building != null \
|
hangar_button.visible = current_building != null \
|
||||||
|
|
@ -363,26 +375,68 @@ func _process(delta: float) -> void:
|
||||||
# Every building can hold ore, so the transfer button rides alongside the
|
# Every building can hold ore, so the transfer button rides alongside the
|
||||||
# action button rather than being one of the things the action button
|
# action button rather than being one of the things the action button
|
||||||
# turns into - the two are independent choices at the same structure.
|
# turns into - the two are independent choices at the same structure.
|
||||||
transfer_button.visible = current_building != null
|
transfer_button.visible = false
|
||||||
|
building_action_button.visible = false
|
||||||
|
action_button.visible = current_building != null
|
||||||
if current_building != null:
|
if current_building != null:
|
||||||
action_button.icon = _action_icon_for(current_building.building_type)
|
var actions: Array = _context_action_buttons()
|
||||||
|
building_action_button.icon = _action_icon_for(current_building.building_type)
|
||||||
|
building_action_button.queue_redraw()
|
||||||
|
action_button.icon = building_action_button.icon if actions.size() == 1 else IconButton.Icon.ACTION_MENU
|
||||||
action_button.queue_redraw()
|
action_button.queue_redraw()
|
||||||
_layout_context_buttons()
|
_layout_context_buttons()
|
||||||
|
|
||||||
|
|
||||||
func _layout_context_buttons() -> void:
|
func _layout_context_buttons() -> void:
|
||||||
# Every contextual action uses a distinct, fixed berth above Build. This
|
# Build is permanently under the resource counter. The contextual berth
|
||||||
# replaces the old hand-picked offsets where Hangar overlapped Action at a
|
# directly below it is compact until it has more than one real choice.
|
||||||
# mothership (#25).
|
action_button.offset_top = 324
|
||||||
var buttons: Array = [action_button, transfer_button]
|
action_button.offset_bottom = 472
|
||||||
if hangar_button.visible:
|
var buttons: Array = _context_action_buttons()
|
||||||
buttons.append(hangar_button)
|
if not context_actions_expanded:
|
||||||
|
for button in buttons:
|
||||||
|
button.visible = false
|
||||||
|
return
|
||||||
for i in range(buttons.size()):
|
for i in range(buttons.size()):
|
||||||
var button: Control = buttons[i]
|
var button: Control = buttons[i]
|
||||||
button.offset_top = -720 + i * 164
|
button.visible = true
|
||||||
|
button.offset_top = 488 + i * 164
|
||||||
button.offset_bottom = button.offset_top + 148
|
button.offset_bottom = button.offset_top + 148
|
||||||
|
|
||||||
|
|
||||||
|
func _context_action_buttons() -> Array:
|
||||||
|
if current_building == null:
|
||||||
|
return []
|
||||||
|
var actions: Array = [transfer_button]
|
||||||
|
if current_building.building_type in [GameState.BUILDING_MOTHERSHIP, GameState.BUILDING_SHIP_CRAFTER,
|
||||||
|
GameState.BUILDING_SHIP_LAB, GameState.BUILDING_COMMAND_CENTER]:
|
||||||
|
actions.push_front(building_action_button)
|
||||||
|
if current_building.building_type == GameState.BUILDING_MOTHERSHIP:
|
||||||
|
actions.append(hangar_button)
|
||||||
|
return actions
|
||||||
|
|
||||||
|
|
||||||
|
func _on_context_action_pressed() -> void:
|
||||||
|
if current_building == null:
|
||||||
|
return
|
||||||
|
var actions: Array = _context_action_buttons()
|
||||||
|
if actions.size() == 1:
|
||||||
|
if actions[0] == transfer_button:
|
||||||
|
_on_transfer_pressed()
|
||||||
|
else:
|
||||||
|
_on_action_pressed()
|
||||||
|
return
|
||||||
|
context_actions_expanded = not context_actions_expanded
|
||||||
|
_layout_context_buttons()
|
||||||
|
|
||||||
|
|
||||||
|
func _collapse_context_actions() -> void:
|
||||||
|
if not context_actions_expanded:
|
||||||
|
return
|
||||||
|
context_actions_expanded = false
|
||||||
|
_layout_context_buttons()
|
||||||
|
|
||||||
|
|
||||||
func _action_icon_for(type: String) -> int:
|
func _action_icon_for(type: String) -> int:
|
||||||
match type:
|
match type:
|
||||||
GameState.BUILDING_SHIP_CRAFTER:
|
GameState.BUILDING_SHIP_CRAFTER:
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ enum Icon {
|
||||||
UPGRADE_DAMAGE, UPGRADE_RATE, UPGRADE_RANGE, UPGRADE_THRUSTERS,
|
UPGRADE_DAMAGE, UPGRADE_RATE, UPGRADE_RANGE, UPGRADE_THRUSTERS,
|
||||||
UPGRADE_SHIELD_HITS, UPGRADE_SHIELD_RECHARGE, UPGRADE_CARGO,
|
UPGRADE_SHIELD_HITS, UPGRADE_SHIELD_RECHARGE, UPGRADE_CARGO,
|
||||||
UPGRADE_ENGINES, UPGRADE_UNLOCK_SHIELD,
|
UPGRADE_ENGINES, UPGRADE_UNLOCK_SHIELD,
|
||||||
|
ACTION_MENU,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Size the glyphs were originally drawn against. Every glyph dimension is
|
# Size the glyphs were originally drawn against. Every glyph dimension is
|
||||||
|
|
@ -176,6 +177,8 @@ func _draw() -> void:
|
||||||
_draw_upgrade_engines(center, pulse, s)
|
_draw_upgrade_engines(center, pulse, s)
|
||||||
Icon.UPGRADE_UNLOCK_SHIELD:
|
Icon.UPGRADE_UNLOCK_SHIELD:
|
||||||
_draw_upgrade_unlock_shield(center, pulse, s)
|
_draw_upgrade_unlock_shield(center, pulse, s)
|
||||||
|
Icon.ACTION_MENU:
|
||||||
|
_draw_action_menu(center, pulse, s)
|
||||||
|
|
||||||
|
|
||||||
func _draw_close(center: Vector2, pulse: float, s: float) -> void:
|
func _draw_close(center: Vector2, pulse: float, s: float) -> void:
|
||||||
|
|
@ -300,6 +303,17 @@ func _draw_upgrade_unlock_shield(center: Vector2, pulse: float, s: float) -> voi
|
||||||
NeonDraw.draw_glowing_line(self, center + Vector2(0, -4) * s, center + Vector2(0, 4) * s, _active_color(), pulse, 0.45 * s, core_color)
|
NeonDraw.draw_glowing_line(self, center + Vector2(0, -4) * s, center + Vector2(0, 4) * s, _active_color(), pulse, 0.45 * s, core_color)
|
||||||
|
|
||||||
|
|
||||||
|
func _draw_action_menu(center: Vector2, pulse: float, s: float) -> void:
|
||||||
|
# A small, intentionally neutral stack of choices. It marks a button that
|
||||||
|
# opens context actions rather than carrying out one particular action.
|
||||||
|
for y in [-8.0, 0.0, 8.0]:
|
||||||
|
NeonDraw.draw_glowing_line(self, center + Vector2(-10, y) * s, center + Vector2(10, y) * s, _active_color(), pulse, 0.42 * s, core_color)
|
||||||
|
NeonDraw.draw_glowing_polygon(self, PackedVector2Array([
|
||||||
|
center + Vector2(-15, y - 2) * s, center + Vector2(-11, y) * s,
|
||||||
|
center + Vector2(-15, y + 2) * s,
|
||||||
|
]), _active_color(), pulse, core_color)
|
||||||
|
|
||||||
|
|
||||||
func _draw_build(center: Vector2, pulse: float, s: float) -> void:
|
func _draw_build(center: Vector2, pulse: float, s: float) -> void:
|
||||||
# A plus inside a frame - "add a structure".
|
# A plus inside a frame - "add a structure".
|
||||||
var r: float = 11.0 * s
|
var r: float = 11.0 * s
|
||||||
|
|
|
||||||
33
Main.tscn
33
Main.tscn
|
|
@ -121,46 +121,47 @@ script = ExtResource("10")
|
||||||
icon = 3
|
icon = 3
|
||||||
|
|
||||||
[node name="BuildButton" type="Control" parent="UI"]
|
[node name="BuildButton" type="Control" parent="UI"]
|
||||||
anchor_top = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
offset_left = 24
|
offset_left = 24
|
||||||
offset_right = 172
|
offset_right = 172
|
||||||
offset_top = -890
|
offset_top = 160
|
||||||
offset_bottom = -742
|
offset_bottom = 308
|
||||||
script = ExtResource("10")
|
script = ExtResource("10")
|
||||||
icon = 5
|
icon = 5
|
||||||
|
|
||||||
[node name="BuildActionButton" type="Control" parent="UI"]
|
[node name="BuildActionButton" type="Control" parent="UI"]
|
||||||
visible = false
|
visible = false
|
||||||
anchor_top = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
offset_left = 24
|
offset_left = 24
|
||||||
offset_right = 172
|
offset_right = 172
|
||||||
offset_top = -720
|
offset_top = 324
|
||||||
offset_bottom = -572
|
offset_bottom = 472
|
||||||
|
script = ExtResource("10")
|
||||||
|
icon = 2
|
||||||
|
|
||||||
|
[node name="BuildingActionButton" type="Control" parent="UI"]
|
||||||
|
visible = false
|
||||||
|
offset_left = 24
|
||||||
|
offset_right = 172
|
||||||
|
offset_top = 488
|
||||||
|
offset_bottom = 636
|
||||||
script = ExtResource("10")
|
script = ExtResource("10")
|
||||||
icon = 2
|
icon = 2
|
||||||
|
|
||||||
[node name="HangarButton" type="Control" parent="UI"]
|
[node name="HangarButton" type="Control" parent="UI"]
|
||||||
visible = false
|
visible = false
|
||||||
anchor_top = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
offset_left = 24
|
offset_left = 24
|
||||||
offset_right = 172
|
offset_right = 172
|
||||||
offset_top = -776
|
offset_top = 488
|
||||||
offset_bottom = -628
|
offset_bottom = 636
|
||||||
script = ExtResource("10")
|
script = ExtResource("10")
|
||||||
icon = 2
|
icon = 2
|
||||||
glow_color = Color(0.45, 0.9, 0.55, 1)
|
glow_color = Color(0.45, 0.9, 0.55, 1)
|
||||||
|
|
||||||
[node name="TransferButton" type="Control" parent="UI"]
|
[node name="TransferButton" type="Control" parent="UI"]
|
||||||
visible = false
|
visible = false
|
||||||
anchor_top = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
offset_left = 24
|
offset_left = 24
|
||||||
offset_right = 172
|
offset_right = 172
|
||||||
offset_top = -600
|
offset_top = 488
|
||||||
offset_bottom = -452
|
offset_bottom = 636
|
||||||
script = ExtResource("10")
|
script = ExtResource("10")
|
||||||
icon = 14
|
icon = 14
|
||||||
glow_color = Color(1, 0.78, 0.25, 1)
|
glow_color = Color(1, 0.78, 0.25, 1)
|
||||||
|
|
|
||||||
|
|
@ -63,18 +63,25 @@ func _process(delta: float) -> bool:
|
||||||
_fail("hangar allowed the last deployed ship to be stored")
|
_fail("hangar allowed the last deployed ship to be stored")
|
||||||
return true
|
return true
|
||||||
|
|
||||||
# #25: all three contextual controls have non-overlapping vertical
|
# Context actions are compact until expanded. A mothership has three
|
||||||
# rectangles when the mothership exposes Action, Transfer and Hangar.
|
# choices: research, transfer cargo and hangar, which must receive
|
||||||
controller.action_button.visible = true
|
# their own non-overlapping berth only after expansion.
|
||||||
controller.transfer_button.visible = true
|
var mothership: Node2D = load("res://Building.tscn").instantiate()
|
||||||
controller.hangar_button.visible = true
|
mothership.set("building_type", GameState.BUILDING_MOTHERSHIP)
|
||||||
|
controller.current_building = mothership
|
||||||
|
controller.context_actions_expanded = true
|
||||||
controller._layout_context_buttons()
|
controller._layout_context_buttons()
|
||||||
var buttons: Array = [controller.action_button, controller.transfer_button, controller.hangar_button]
|
var buttons: Array = [controller.building_action_button, controller.transfer_button, controller.hangar_button]
|
||||||
for i in range(buttons.size() - 1):
|
for i in range(buttons.size() - 1):
|
||||||
if buttons[i].offset_bottom > buttons[i + 1].offset_top:
|
if buttons[i].offset_bottom > buttons[i + 1].offset_top:
|
||||||
_fail("context buttons %d and %d overlap" % [i, i + 1])
|
_fail("context buttons %d and %d overlap" % [i, i + 1])
|
||||||
return true
|
return true
|
||||||
print("hangar crews and stores typed vessels; contextual buttons have separate berths")
|
controller._collapse_context_actions()
|
||||||
|
if controller.building_action_button.visible or controller.transfer_button.visible or controller.hangar_button.visible:
|
||||||
|
_fail("collapsing the context button left an action visible")
|
||||||
|
return true
|
||||||
|
mothership.free()
|
||||||
|
print("hangar crews and stores typed vessels; contextual actions expand and collapse")
|
||||||
print("TEST_HANGAR_MANAGEMENT: PASS")
|
print("TEST_HANGAR_MANAGEMENT: PASS")
|
||||||
quit(0)
|
quit(0)
|
||||||
return true
|
return true
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue