Add StageBackgroundView and related tests for plain background functionality
- Implemented StageBackgroundView class for managing sky and plain backgrounds in the stage. - Added functionality to set background type and color, bind camera, and apply themes. - Created test_phase19_plain_background.gd to validate plain background behavior and migration. - Developed test_phase19_starter_chooser_layout.gd to ensure proper layout and functionality of the starter chooser. - Included visual capture tests for UI elements and interactions.
This commit is contained in:
@@ -50,7 +50,7 @@ const STAGE_MODAL_VIEWS_SCRIPT := preload("res://scripts/editors/stage/stage_mod
|
||||
const STAGE_THEME_CONTROLLER_SCRIPT := preload("res://scripts/editors/stage/stage_theme_controller.gd")
|
||||
const STAGE_TARGET_CAPTURE_SCRIPT := preload("res://scripts/editors/stage/stage_target_capture_session.gd")
|
||||
const STAGE_SCENERY_CONTROLLER_SCRIPT := preload("res://scripts/editors/stage/stage_scenery_controller.gd")
|
||||
const STAGE_SKY_VIEW_SCRIPT := preload("res://scripts/stage/scenery/stage_sky_view.gd")
|
||||
const STAGE_BACKGROUND_VIEW_SCRIPT := preload("res://scripts/stage/scenery/stage_background_view.gd")
|
||||
const STAGE_DRAW_ORDER_SCRIPT := preload("res://scripts/stage/stage_draw_order.gd")
|
||||
const STAGE_WALL_PANEL_SCRIPT := preload("res://scripts/stage/scenery/stage_wall_panel.gd")
|
||||
const STAGE_BACKGROUND_GROUND_SCRIPT := preload("res://scripts/stage/scenery/stage_background_ground.gd")
|
||||
@@ -258,13 +258,21 @@ var _spawner: StageSpawner
|
||||
var _selection: StageSelection
|
||||
var _gizmos: StageGizmos
|
||||
var _stage_input_ready: bool = false
|
||||
var _startup_scene_applied: bool = false
|
||||
var _startup_starter_chooser_pending: bool = false
|
||||
var _startup_starter_chooser_shown: bool = false
|
||||
var _grid: StageGrid
|
||||
var _spatial_index: StageSpatialIndex
|
||||
var _terrain_painter: StageTerrainPainter
|
||||
var _scenery_controller: StageSceneryController
|
||||
var _sky_layer: CanvasLayer
|
||||
var _sky_view: StageSkyView
|
||||
var _background_view: StageBackgroundView
|
||||
var _sky_id: StringName = &"sky_neutral"
|
||||
var _background_kind: StringName = &"sky"
|
||||
var _plain_color: Color = Color("#F5EFE0")
|
||||
var _plain_color_draft_active: bool = false
|
||||
var _plain_color_draft: Color = Color("#F5EFE0")
|
||||
var _new_ground_finish: StringName = &"finish_ground_grass"
|
||||
var _hosted_prop_editor: PropEditor
|
||||
var _hosted_artwork_path: String = ""
|
||||
@@ -1850,6 +1858,8 @@ func set_mode(mode: StageMode) -> void:
|
||||
_show_toast("Finish or cancel speech editing first.")
|
||||
_sync_mode_buttons()
|
||||
return
|
||||
if _plain_color_draft_active:
|
||||
_close_selector()
|
||||
_cancel_surface_color_preview()
|
||||
if _scenery_controller != null:
|
||||
if _scenery_controller.is_group_preview_pending():
|
||||
@@ -2513,6 +2523,74 @@ func _mark_scene_dirty() -> void:
|
||||
_paused_edit_autosave_remaining = 1.0
|
||||
|
||||
|
||||
func _refresh_background_view() -> void:
|
||||
if _background_view != null:
|
||||
var displayed_color: Color = _plain_color_draft if _plain_color_draft_active else _plain_color
|
||||
_background_view.set_background(_background_kind, _sky_id, displayed_color)
|
||||
_sky_view = _background_view.get_sky_view()
|
||||
_update_grid_background_style()
|
||||
|
||||
|
||||
func _commit_background_kind(kind: StringName, sky_id: StringName = &"") -> void:
|
||||
var next_kind: StringName = &"plain" if kind == &"plain" else &"sky"
|
||||
var next_sky: StringName = sky_id if not sky_id.is_empty() else _sky_id
|
||||
var changed: bool = _background_kind != next_kind or _sky_id != next_sky
|
||||
_background_kind = next_kind
|
||||
_sky_id = next_sky
|
||||
_refresh_background_view()
|
||||
if _asset_browser != null:
|
||||
_asset_browser.set_background_state(_background_kind, _sky_id, _plain_color)
|
||||
if changed:
|
||||
_mark_scene_dirty()
|
||||
|
||||
|
||||
func _preview_plain_color(color: Color) -> void:
|
||||
_plain_color_draft = _opaque_stage_color(color)
|
||||
_plain_color_draft_active = true
|
||||
_refresh_background_view()
|
||||
|
||||
|
||||
func _cancel_plain_color_preview() -> void:
|
||||
if not _plain_color_draft_active:
|
||||
return
|
||||
_plain_color_draft_active = false
|
||||
_plain_color_draft = _plain_color
|
||||
_refresh_background_view()
|
||||
|
||||
|
||||
func _commit_plain_color(color: Color) -> void:
|
||||
var next_color: Color = _opaque_stage_color(color)
|
||||
var changed: bool = _canonical_surface_color(_plain_color) != _canonical_surface_color(next_color)
|
||||
_plain_color = next_color
|
||||
_plain_color_draft = next_color
|
||||
_plain_color_draft_active = false
|
||||
_refresh_background_view()
|
||||
_record_recent_surface_color(next_color)
|
||||
if _asset_browser != null:
|
||||
_asset_browser.set_background_state(_background_kind, _sky_id, _plain_color)
|
||||
if changed:
|
||||
_mark_scene_dirty()
|
||||
|
||||
|
||||
func _opaque_stage_color(color: Color) -> Color:
|
||||
return Color(color.r, color.g, color.b, 1.0)
|
||||
|
||||
|
||||
func _update_grid_background_style() -> void:
|
||||
if _grid == null:
|
||||
return
|
||||
var displayed_color: Color = _plain_color_draft if _plain_color_draft_active else _plain_color
|
||||
var plain_active: bool = _background_kind == &"plain"
|
||||
_grid.set_background_treatment(
|
||||
plain_active,
|
||||
displayed_color,
|
||||
_sandbox_theme.color("grid.plain_light_minor", Color("#11182120")) if _sandbox_theme != null else Color("#11182120"),
|
||||
_sandbox_theme.color("grid.plain_light_major", Color("#11182148")) if _sandbox_theme != null else Color("#11182148"),
|
||||
_sandbox_theme.color("grid.plain_dark_minor", Color("#FFFFFF25")) if _sandbox_theme != null else Color("#FFFFFF25"),
|
||||
_sandbox_theme.color("grid.plain_dark_major", Color("#FFFFFF58")) if _sandbox_theme != null else Color("#FFFFFF58")
|
||||
)
|
||||
|
||||
|
||||
func _set_scene_dirty(value: bool) -> void:
|
||||
if _document != null:
|
||||
_document.set_dirty(value)
|
||||
@@ -2533,6 +2611,8 @@ func _collect_scene_data(is_autosave: bool = false) -> Dictionary:
|
||||
var document_metadata: Dictionary = {
|
||||
"scene_name": _scene_name,
|
||||
"sky_id": String(_sky_id),
|
||||
"background_kind": String(_background_kind),
|
||||
"plain_color": _canonical_surface_color(_plain_color),
|
||||
"metadata": _document.metadata_for_snapshot(is_autosave),
|
||||
}
|
||||
return _scene_adapter.collect(_world, _authored, _event_rules, camera_state, document_metadata)
|
||||
@@ -2613,6 +2693,7 @@ func _validate_queues_for_save() -> String:
|
||||
|
||||
func _reset_scene_content() -> void:
|
||||
set_mode(StageMode.EDIT)
|
||||
_cancel_plain_color_preview()
|
||||
_cancel_surface_color_preview()
|
||||
if _scenery_erase_piece_dialog != null:
|
||||
_scenery_erase_piece_dialog.hide()
|
||||
@@ -2622,8 +2703,9 @@ func _reset_scene_content() -> void:
|
||||
_cancel_scenery_repair_preview()
|
||||
_scenery_repair_target = null
|
||||
_sky_id = &"sky_neutral"
|
||||
if _sky_view != null:
|
||||
_sky_view.set_sky(_sky_id)
|
||||
_background_kind = &"sky"
|
||||
_plain_color = Color("#F5EFE0")
|
||||
_refresh_background_view()
|
||||
if _scenery_controller != null:
|
||||
_scenery_controller.exit_tool()
|
||||
_scenery_controller.cancel_group()
|
||||
@@ -2655,11 +2737,19 @@ func _apply_scene_data(data: Dictionary, source_path: String, is_recovery: bool)
|
||||
source_path = CONTENT_PATHS.canonicalize(source_path)
|
||||
if _scene_adapter == null:
|
||||
return false
|
||||
if _plain_color_draft_active:
|
||||
_close_selector()
|
||||
_cancel_plain_color_preview()
|
||||
var was_suppressed: bool = _suppress_dirty
|
||||
_suppress_dirty = true
|
||||
_reset_scene_content()
|
||||
var adapter_result: Dictionary = _scene_adapter.apply(data, _world, _spawner)
|
||||
_sky_id = StringName(String(adapter_result.get("sky_id", "sky_neutral")))
|
||||
_background_kind = StringName(String(adapter_result.get("background_kind", "sky")))
|
||||
_plain_color = STAGE_SCENE_IO.color_from_data(
|
||||
adapter_result.get("plain_color", STAGE_SCENE_IO.DEFAULT_PLAIN_COLOR),
|
||||
Color("#F5EFE0")
|
||||
)
|
||||
var loaded_nodes: Array[Node2D] = adapter_result.get("loaded_nodes", [])
|
||||
for node: Node2D in loaded_nodes:
|
||||
_finalize_placed_node(node)
|
||||
@@ -2683,8 +2773,7 @@ func _apply_scene_data(data: Dictionary, source_path: String, is_recovery: bool)
|
||||
var camera_data: Dictionary = raw_camera as Dictionary if raw_camera is Dictionary else {}
|
||||
_camera.global_position = STAGE_SCENE_IO.data_to_vector(camera_data.get("position"), DEFAULT_CAMERA_POSITION)
|
||||
_camera.zoom = Vector2.ONE * clampf(float(camera_data.get("zoom", DEFAULT_CAMERA_ZOOM)), min_zoom, max_zoom)
|
||||
if _sky_view != null:
|
||||
_sky_view.set_sky(_sky_id)
|
||||
_refresh_background_view()
|
||||
var raw_metadata: Variant = data.get("metadata", {})
|
||||
var metadata: Dictionary = raw_metadata as Dictionary if raw_metadata is Dictionary else {}
|
||||
if _document != null:
|
||||
@@ -2712,6 +2801,7 @@ func _apply_scene_data(data: Dictionary, source_path: String, is_recovery: bool)
|
||||
_add_recent_scene(source_path)
|
||||
if _document != null:
|
||||
_document.remove_autosave()
|
||||
_startup_scene_applied = true
|
||||
return true
|
||||
|
||||
func _show_scene_load_warnings(warnings: Array[String]) -> void:
|
||||
@@ -2782,20 +2872,79 @@ func _update_scene_chrome() -> void:
|
||||
_refresh_status()
|
||||
|
||||
|
||||
func _check_autosave_recovery() -> void:
|
||||
func _check_autosave_recovery(show_starter_chooser_after_discard: bool = false) -> void:
|
||||
if _document == null:
|
||||
if show_starter_chooser_after_discard:
|
||||
_queue_startup_starter_chooser()
|
||||
return
|
||||
var inspection: Dictionary = _document.inspect_autosave()
|
||||
if not bool(inspection.get("available", false)):
|
||||
if show_starter_chooser_after_discard:
|
||||
_queue_startup_starter_chooser()
|
||||
return
|
||||
var autosave_data: Dictionary = inspection.get("data", {}) as Dictionary
|
||||
var dialog := ConfirmationDialog.new()
|
||||
dialog.name = "AutosaveRecoveryDialog"; dialog.title = "Recover Sandbox Scene?"; dialog.dialog_text = "A previous Play session was not closed cleanly. Recover it?"
|
||||
dialog.confirmed.connect(func() -> void: _apply_scene_data(autosave_data, AUTOSAVE_PATH, true); dialog.queue_free())
|
||||
dialog.canceled.connect(func() -> void: _document.remove_autosave(); dialog.queue_free())
|
||||
dialog.canceled.connect(func() -> void:
|
||||
_document.remove_autosave()
|
||||
dialog.queue_free()
|
||||
if show_starter_chooser_after_discard:
|
||||
_queue_startup_starter_chooser()
|
||||
)
|
||||
get_node(NodePath("UI")).add_child(dialog); _apply_dialog_theme(dialog); dialog.popup_centered()
|
||||
|
||||
|
||||
func _queue_startup_starter_chooser() -> void:
|
||||
if _startup_starter_chooser_pending or _startup_starter_chooser_shown:
|
||||
return
|
||||
_startup_starter_chooser_pending = true
|
||||
call_deferred("_present_startup_starter_chooser")
|
||||
|
||||
|
||||
func _present_startup_starter_chooser() -> void:
|
||||
while _startup_starter_chooser_pending and is_inside_tree():
|
||||
if not _stage_input_ready or _startup_modal_is_visible():
|
||||
await get_tree().process_frame
|
||||
continue
|
||||
if get_tree().current_scene != self or _startup_scene_applied or current_mode != StageMode.EDIT or not _current_scene_path.is_empty() or _hosted_prop_editor != null:
|
||||
_startup_starter_chooser_pending = false
|
||||
return
|
||||
_startup_starter_chooser_pending = false
|
||||
_startup_starter_chooser_shown = true
|
||||
_open_selector("starters")
|
||||
return
|
||||
_startup_starter_chooser_pending = false
|
||||
|
||||
|
||||
func _startup_modal_is_visible() -> bool:
|
||||
if _selector_open or _speech_composer_is_open():
|
||||
return true
|
||||
var ui_layer: CanvasLayer = _chrome.get_canvas_layer() if _chrome != null else null
|
||||
if ui_layer != null:
|
||||
for child: Node in ui_layer.get_children():
|
||||
var window := child as Window
|
||||
if window != null and window.visible:
|
||||
return true
|
||||
for dialog: Window in [
|
||||
_cli_error_dialog,
|
||||
_speech_recovery_dialog,
|
||||
_speech_save_gate_dialog,
|
||||
_scene_open_dialog,
|
||||
_scene_save_dialog,
|
||||
_unsaved_changes_dialog,
|
||||
_rename_scene_dialog,
|
||||
_missing_assets_dialog,
|
||||
_missing_scenery_dialog,
|
||||
_scenery_repair_confirm_dialog,
|
||||
_group_preview_save_dialog,
|
||||
_confirm_dialog,
|
||||
]:
|
||||
if dialog != null and is_instance_valid(dialog) and dialog.visible:
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func _handle_cli_startup(args: Array) -> void:
|
||||
if OS.get_environment("STICKMAN_WALK_DEBUG") == "1":
|
||||
print("[WalkDebug] CLI_STARTUP args=%s" % [args])
|
||||
@@ -2806,7 +2955,7 @@ func _handle_cli_startup(args: Array) -> void:
|
||||
return
|
||||
var scene_path := String(result.get("scene_path", ""))
|
||||
if scene_path.is_empty():
|
||||
_check_autosave_recovery()
|
||||
_check_autosave_recovery(true)
|
||||
return
|
||||
if _document != null and _document.has_autosave():
|
||||
_document.remove_autosave()
|
||||
@@ -3085,6 +3234,9 @@ func _build_ui() -> void:
|
||||
|
||||
_asset_browser.asset_selected_requested.connect(_on_asset_selected)
|
||||
_asset_browser.selector_cancel_requested.connect(_on_selector_cancelled)
|
||||
_asset_browser.plain_color_preview_requested.connect(_preview_plain_color)
|
||||
_asset_browser.plain_color_commit_requested.connect(_commit_plain_color)
|
||||
_asset_browser.plain_color_preview_cancel_requested.connect(_cancel_plain_color_preview)
|
||||
_asset_browser.asset_load_failed.connect(func(kind: String, path: String) -> void:
|
||||
if _scenery_repair_target != null and is_instance_valid(_scenery_repair_target):
|
||||
_show_toast("Could not open that artwork. Try another file.")
|
||||
@@ -3097,6 +3249,7 @@ func _build_ui() -> void:
|
||||
_asset_browser.edit_scenery_requested.connect(_enter_scenery_edit_mode)
|
||||
_asset_browser.surface_color_confirmed.connect(_record_recent_surface_color)
|
||||
_asset_browser.set_surface_color_history(_recent_surface_colors)
|
||||
_asset_browser.set_background_state(_background_kind, _sky_id, _plain_color)
|
||||
_build_ground_finish_popup(ui)
|
||||
|
||||
_modal_views.build_file_dialogs(ui)
|
||||
@@ -4510,6 +4663,8 @@ func _build_gizmo_layer() -> void:
|
||||
_gizmos = STAGE_GIZMOS.new()
|
||||
_gizmos.name = "GizmoLayer"
|
||||
_gizmos.camera = _camera
|
||||
if _sandbox_theme != null:
|
||||
_gizmos.apply_theme(_sandbox_theme as SandboxTheme)
|
||||
_gizmos.transform_committed.connect(_on_transform_committed)
|
||||
_gizmos.transform_started.connect(_on_gizmo_transform_started)
|
||||
_gizmos.transform_updated.connect(_on_gizmo_transform_updated)
|
||||
@@ -4522,6 +4677,7 @@ func _build_grid_layer() -> void:
|
||||
_grid.camera = _camera
|
||||
add_child(_grid)
|
||||
move_child(_grid, 0)
|
||||
_update_grid_background_style()
|
||||
|
||||
|
||||
func _build_ghost_holder() -> void:
|
||||
@@ -4542,15 +4698,19 @@ func _build_scenery_controller() -> void:
|
||||
|
||||
func _build_sky_layer() -> void:
|
||||
_sky_layer = CanvasLayer.new()
|
||||
_sky_layer.name = "StageSkyLayer"
|
||||
_sky_layer.name = "StageBackgroundLayer"
|
||||
_sky_layer.layer = -1
|
||||
_sky_view = STAGE_SKY_VIEW_SCRIPT.new() as StageSkyView
|
||||
_sky_view.name = "StageSkyView"
|
||||
_sky_view.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
_sky_view.set_sky(_sky_id)
|
||||
_sky_layer.add_child(_sky_view)
|
||||
_background_view = STAGE_BACKGROUND_VIEW_SCRIPT.new() as StageBackgroundView
|
||||
_background_view.name = "StageBackgroundView"
|
||||
_background_view.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
_background_view.set_background(_background_kind, _sky_id, _plain_color)
|
||||
_sky_layer.add_child(_background_view)
|
||||
add_child(_sky_layer)
|
||||
_sky_view.bind_camera(_camera)
|
||||
_background_view.bind_camera(_camera)
|
||||
_sky_view = _background_view.get_sky_view()
|
||||
if _sandbox_theme != null:
|
||||
_background_view.apply_theme(_sandbox_theme as SandboxTheme)
|
||||
_update_grid_background_style()
|
||||
|
||||
|
||||
func _build_placement_overlay() -> void:
|
||||
@@ -4912,7 +5072,13 @@ func _open_selector(kind: String) -> void:
|
||||
(_palette_buttons[pid] as Button).set_pressed_no_signal(pid == kind)
|
||||
if kind == "scenery":
|
||||
_asset_browser.set_surface_color_history(_recent_surface_colors)
|
||||
var selector_state: Dictionary = _asset_browser.open_selector(kind, _spawner.get_selected_stickman_path(), _sky_id)
|
||||
var selector_state: Dictionary = _asset_browser.open_selector(
|
||||
kind,
|
||||
_spawner.get_selected_stickman_path(),
|
||||
_sky_id,
|
||||
_background_kind,
|
||||
_plain_color
|
||||
)
|
||||
if kind == "stickman":
|
||||
var selected_stickman_path: String = String(selector_state.get("selected_stickman_path", _spawner.get_selected_stickman_path()))
|
||||
if selected_stickman_path != _spawner.get_selected_stickman_path():
|
||||
@@ -4940,12 +5106,14 @@ func _on_asset_selected(entry: Dictionary) -> void:
|
||||
return
|
||||
var background_kind: String = String(entry.get("background_kind", ""))
|
||||
if background_kind == "sky":
|
||||
_sky_id = StringName(String(entry.get("id", "sky_neutral")))
|
||||
_sky_view.set_sky(_sky_id)
|
||||
var scenery_selector: AssetSelector = _asset_browser.get_selector()
|
||||
if scenery_selector != null:
|
||||
scenery_selector.set_current_sky(_sky_id)
|
||||
_mark_scene_dirty()
|
||||
_commit_background_kind(&"sky", StringName(String(entry.get("id", "sky_neutral"))))
|
||||
_refresh_scenery_capture_bar()
|
||||
return
|
||||
if background_kind == "plain":
|
||||
_commit_background_kind(&"plain")
|
||||
var plain_selector: AssetSelector = _asset_browser.get_selector()
|
||||
if plain_selector != null:
|
||||
plain_selector.open_plain_background_choices(_plain_color)
|
||||
_refresh_scenery_capture_bar()
|
||||
return
|
||||
if background_kind == "wall":
|
||||
@@ -5774,8 +5942,15 @@ func _handle_scenery_edit_motion(world_position: Vector2) -> void:
|
||||
|
||||
|
||||
func _close_selector() -> void:
|
||||
var closing_kind: String = _selector_kind
|
||||
_cancel_plain_color_preview()
|
||||
if _asset_browser != null:
|
||||
_asset_browser.close()
|
||||
if closing_kind == "scenery":
|
||||
# Scenery is a chooser entry; the capture bar communicates active drawing tools.
|
||||
var scenery_button: Button = _palette_buttons.get("scenery") as Button
|
||||
if scenery_button != null:
|
||||
scenery_button.set_pressed_no_signal(false)
|
||||
|
||||
|
||||
func _on_selector_cancelled() -> void:
|
||||
@@ -5783,7 +5958,7 @@ func _on_selector_cancelled() -> void:
|
||||
return
|
||||
var kind: String = _selector_kind
|
||||
_close_selector()
|
||||
if kind != "scenery" and kind != "starters":
|
||||
if kind != "starters":
|
||||
set_placement_mode("")
|
||||
|
||||
|
||||
@@ -7900,8 +8075,12 @@ func _load_font(path: String) -> Font:
|
||||
return _theme_controller.load_font(path)
|
||||
|
||||
func _apply_theme_to_visuals() -> void:
|
||||
if _sky_view != null and _sandbox_theme != null:
|
||||
_sky_view.apply_theme(_sandbox_theme as SandboxTheme)
|
||||
if _background_view != null and _sandbox_theme != null:
|
||||
_background_view.apply_theme(_sandbox_theme as SandboxTheme)
|
||||
if _grid != null:
|
||||
_update_grid_background_style()
|
||||
if _gizmos != null and _sandbox_theme != null:
|
||||
_gizmos.apply_theme(_sandbox_theme as SandboxTheme)
|
||||
if _director_visuals != null:
|
||||
_director_visuals.set_style(_theme)
|
||||
_director_visuals.completed_path_alpha = _sandbox_theme.number("overlays.completed_path_alpha", 0.20, 0.0, 1.0) if _sandbox_theme != null else 0.20
|
||||
|
||||
@@ -9,6 +9,9 @@ signal refresh_requested
|
||||
signal make_artwork_requested
|
||||
signal edit_scenery_requested
|
||||
signal surface_color_confirmed(color: Color)
|
||||
signal plain_color_preview_requested(color: Color)
|
||||
signal plain_color_commit_requested(color: Color)
|
||||
signal plain_color_preview_cancel_requested()
|
||||
|
||||
const ASSET_SELECTOR_SCENE := preload("res://scenes/stage/asset_selector.tscn")
|
||||
const STICKMAN_LIBRARY_SCRIPT := preload("res://scripts/characters/stickman/stickman_library.gd")
|
||||
@@ -32,6 +35,9 @@ var browse_dialog: FileDialog
|
||||
var thumbnail_queue: Array[Dictionary] = []
|
||||
var thumbnail_busy: bool = false
|
||||
var thumbnail_generation: int = 0
|
||||
var _current_background_kind: StringName = &"sky"
|
||||
var _current_sky_id: StringName = &"sky_neutral"
|
||||
var _current_plain_color: Color = Color("#F5EFE0")
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
@@ -62,6 +68,10 @@ func build_ui(ui_layer: CanvasLayer, ui_font: Font, emoji_font: Font, sandbox_th
|
||||
selector.make_artwork_requested.connect(func() -> void: make_artwork_requested.emit())
|
||||
selector.edit_scenery_requested.connect(func() -> void: edit_scenery_requested.emit())
|
||||
selector.surface_color_confirmed.connect(func(color: Color) -> void: surface_color_confirmed.emit(color))
|
||||
selector.plain_color_preview_requested.connect(func(color: Color) -> void: plain_color_preview_requested.emit(color))
|
||||
selector.plain_color_commit_requested.connect(func(color: Color) -> void: plain_color_commit_requested.emit(color))
|
||||
selector.plain_color_preview_cancel_requested.connect(func() -> void: plain_color_preview_cancel_requested.emit())
|
||||
selector.stage_preview_dimming_changed.connect(_on_selector_stage_preview_dimming_changed)
|
||||
ui_layer.add_child(selector)
|
||||
# apply_font AFTER add_child so the selector's @onready nodes resolve first.
|
||||
selector.apply_font(ui_font, emoji_font)
|
||||
@@ -92,12 +102,28 @@ func set_surface_color_history(colors: Array[Color]) -> void:
|
||||
selector.set_surface_color_history(colors)
|
||||
|
||||
|
||||
func set_background_state(kind: StringName, sky_id: StringName, plain_color: Color) -> void:
|
||||
_current_background_kind = &"plain" if kind == &"plain" else &"sky"
|
||||
_current_sky_id = sky_id
|
||||
_current_plain_color = Color(plain_color.r, plain_color.g, plain_color.b, 1.0)
|
||||
if selector != null:
|
||||
selector.set_background_state(_current_background_kind, _current_sky_id, _current_plain_color)
|
||||
|
||||
|
||||
func _starter_scene_entries() -> Array[Dictionary]:
|
||||
return [
|
||||
{
|
||||
"id": "starter_plain_background",
|
||||
"name": "Plain Background",
|
||||
"description": "An empty stage with one color. Choose a new color whenever you like.",
|
||||
"category": "Make your own",
|
||||
"path": "res://content/stages/starters/plain_background.scene",
|
||||
"icon": "🎨",
|
||||
},
|
||||
{
|
||||
"id": "starter_blank_scene",
|
||||
"name": "Blank Scene",
|
||||
"description": "Start fresh with an open stage and a clear sky.",
|
||||
"name": "Open Sky",
|
||||
"description": "An empty stage with a soft sky. Sun and clouds, ready for your story.",
|
||||
"category": "Make your own",
|
||||
"path": "res://content/stages/starters/blank.scene",
|
||||
"icon": "✨",
|
||||
@@ -129,7 +155,16 @@ func make_browse_entry(kind: String, path: String) -> Dictionary:
|
||||
return stickman_library.make_entry(path)
|
||||
|
||||
|
||||
func open_selector(kind: String, current_stickman_path: String, current_sky_id: StringName = &"") -> Dictionary:
|
||||
func open_selector(
|
||||
kind: String,
|
||||
current_stickman_path: String,
|
||||
current_sky_id: StringName = &"",
|
||||
background_kind: StringName = &"sky",
|
||||
plain_color: Color = Color("#F5EFE0")
|
||||
) -> Dictionary:
|
||||
_current_background_kind = &"plain" if background_kind == &"plain" else &"sky"
|
||||
_current_sky_id = current_sky_id if not current_sky_id.is_empty() else &"sky_neutral"
|
||||
_current_plain_color = Color(plain_color.r, plain_color.g, plain_color.b, 1.0)
|
||||
set_selector_kind(kind)
|
||||
var entries: Array[Dictionary] = scan_entries(kind)
|
||||
if kind == "starters":
|
||||
@@ -142,7 +177,7 @@ func open_selector(kind: String, current_stickman_path: String, current_sky_id:
|
||||
selected_stickman_path = String(entries[0].get("path", ""))
|
||||
var auto_selection: Dictionary = entries[0] if kind == "stickman" and entries.size() == 1 else {}
|
||||
if auto_selection.is_empty():
|
||||
open(kind, entries, current_sky_id)
|
||||
open(kind, entries, _current_sky_id)
|
||||
return {
|
||||
"entries": entries,
|
||||
"selected_stickman_path": selected_stickman_path,
|
||||
@@ -152,6 +187,7 @@ func open_selector(kind: String, current_stickman_path: String, current_sky_id:
|
||||
|
||||
func _scenery_background_entries() -> Array[Dictionary]:
|
||||
return [
|
||||
{"id": "plain_background", "name": "Plain Background", "category": "Scene background", "gallery_tab": "backgrounds", "background_kind": "plain", "plain_color": _current_plain_color, "icon": "🎨"},
|
||||
{"id": "sky_clear_day", "name": "Clear Day", "category": "Sky", "gallery_tab": "backgrounds", "background_kind": "sky", "icon": "☀️"},
|
||||
{"id": "sky_cloudy_day", "name": "Cloudy Day", "category": "Sky", "gallery_tab": "backgrounds", "background_kind": "sky", "icon": "☁️"},
|
||||
{"id": "sky_sunset", "name": "Sunset", "category": "Sky", "gallery_tab": "backgrounds", "background_kind": "sky", "icon": "🌅"},
|
||||
@@ -170,8 +206,9 @@ func open(kind: String, entries: Array[Dictionary], current_sky_id: StringName =
|
||||
selector_open = true
|
||||
if selector_dim != null:
|
||||
selector_dim.visible = true
|
||||
selector_dim.color = Color(0.0, 0.0, 0.0, SELECTOR_DIM_ALPHA)
|
||||
if selector != null:
|
||||
selector.open(kind, entries, String(current_sky_id))
|
||||
selector.open(kind, entries, String(current_sky_id), String(_current_background_kind), _current_plain_color)
|
||||
load_or_enqueue_thumbnails(kind, entries)
|
||||
|
||||
|
||||
@@ -206,6 +243,8 @@ func set_entries(entries: Array[Dictionary]) -> void:
|
||||
|
||||
func refresh_selector_entries() -> Array[Dictionary]:
|
||||
var entries: Array[Dictionary] = scan_entries(selector_kind)
|
||||
if selector_kind == "scenery":
|
||||
entries.append_array(_scenery_background_entries())
|
||||
set_entries(entries)
|
||||
return entries
|
||||
|
||||
@@ -282,6 +321,13 @@ func _on_selector_cancelled() -> void:
|
||||
selector_cancel_requested.emit()
|
||||
|
||||
|
||||
func _on_selector_stage_preview_dimming_changed(should_dim: bool) -> void:
|
||||
if selector_dim == null:
|
||||
return
|
||||
selector_dim.color = Color(0.0, 0.0, 0.0, SELECTOR_DIM_ALPHA if should_dim else 0.0)
|
||||
selector_dim.visible = selector_open
|
||||
|
||||
|
||||
func _on_selector_popup_hide() -> void:
|
||||
if not selector_open:
|
||||
return
|
||||
|
||||
@@ -130,6 +130,8 @@ func collect(
|
||||
"version": STAGE_SCENE_IO.FILE_VERSION,
|
||||
"scene_name": scene_name,
|
||||
"sky_id": String(document_metadata.get("sky_id", "sky_neutral")),
|
||||
"background_kind": String(document_metadata.get("background_kind", "sky")),
|
||||
"plain_color": String(document_metadata.get("plain_color", STAGE_SCENE_IO.DEFAULT_PLAIN_COLOR)),
|
||||
"camera": {"position": STAGE_SCENE_IO.vector_to_data(camera_position), "zoom": camera_zoom},
|
||||
"objects": objects,
|
||||
"event_rules": rules_result["rules"],
|
||||
@@ -299,6 +301,8 @@ func apply(data: Dictionary, world: Node2D, spawner: StageSpawner) -> Dictionary
|
||||
"missing_paths": missing_paths,
|
||||
"decoded_rules": decoded_rules,
|
||||
"sky_id": String(data.get("sky_id", "sky_neutral")),
|
||||
"background_kind": String(data.get("background_kind", "sky")),
|
||||
"plain_color": String(data.get("plain_color", STAGE_SCENE_IO.DEFAULT_PLAIN_COLOR)),
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user