references/migration-notes.md
# Migration notes: godot-theme-easter
Incremental upgrade for topics this skill covers. Apply **one hop**, stabilize/test, then next. Never skip hops.
If the project is **< 4.0**, follow [godot-version-migration](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-version-migration/SKILL.md) era bridges (legacy → 3→4) until 4.0, then these hops. Official 3→4: [Upgrading from Godot 3 to Godot 4](https://docs.godotengine.org/en/stable/tutorials/migrating/upgrading_to_godot_4.html).
## 4.0 → 4.1
Official: [Upgrading to Godot 4.1](https://docs.godotengine.org/en/stable/tutorials/migrating/upgrading_to_godot_4.1.html)
- `SubViewportContainer.mouse_filter` must be STOP/PASS for input to reach SubViewports.
- Layered SubViewportContainers needing mouse input may need Area2D replacements.
- `CodeEdit.add_code_completion_option` gains `location`; Tree `edit_selected` gains `force_edit`.
## 4.1 → 4.2
Official: [Upgrading to Godot 4.2](https://docs.godotengine.org/en/stable/tutorials/migrating/upgrading_to_godot_4.2.html)
- `PopupMenu` shortcut helpers gain `allow_echo`; `clear` gains `free_submenus`.
- GraphEdit: `arrange_nodes_button_hidden` → `show_arrange_button`; snap props renamed; `get_zoom_hbox` → `get_menu_hbox`.
- GraphNode: large API move to `GraphElement`; connection query methods removed; `comment`/`show_close` removed.
## 4.2 → 4.3
Official: [Upgrading to Godot 4.3](https://docs.godotengine.org/en/stable/tutorials/migrating/upgrading_to_godot_4.3.html)
- Default font outline color is black (was white).
- `auto_translate` deprecated for Node `auto_translate_mode` (inherit semantics).
- `AcceptDialog` register/remove helpers take LineEdit/Button specifically.
- If the genre uses TileMap, migrate to TileMapLayer nodes before relying on layer APIs.
- If the genre ships multiplayer, upgrade all peers to 4.3 together (SceneMultiplayer protocol).
## 4.3 → 4.4
Official: [Upgrading to Godot 4.4](https://docs.godotengine.org/en/stable/tutorials/migrating/upgrading_to_godot_4.4.html)
- `GraphEdit.connect_node` gains `keep_alive`; `frame_rect_changed` uses `Rect2`.
## 4.4 → 4.5
Official: [Upgrading to Godot 4.5](https://docs.godotengine.org/en/stable/tutorials/migrating/upgrading_to_godot_4.5.html)
- CanvasItem/Font/TextLine draw APIs gain optional `oversampling`.
- `TreeItem.add_button` gains `alt_text`.
## 4.5 → 4.6
Official: [Upgrading to Godot 4.6](https://docs.godotengine.org/en/stable/tutorials/migrating/upgrading_to_godot_4.6.html)
- `Control.grab_focus` / `has_focus` gain hide-focus options.
- `FileDialog.add_filter` gains `mime_type`; `SplitContainer.clamp_split_offset` gains `priority_index`.
- `EditorFileDialog` file APIs moved onto `FileDialog` base; `add_side_menu` removed.
- `PopupMenu.submenu_popup_delay` default 0.2 (was 0.3).
- Retune Environment glow/fog if the genre leans on bloom-heavy looks.
## 4.6 → 4.7
Official: [Upgrading to Godot 4.7](https://docs.godotengine.org/en/stable/tutorials/migrating/upgrading_to_godot_4.7.html)
- `Control.accessibility_live` uses `AccessibilityServer.AccessibilityLiveMode`.
- `TreeItem.select` gains `set_as_cursor`.
- `CanvasItem` no longer adds antialiasing feather that thickened lines — widen strokes if visuals relied on it.
- Confirm project stretch mode and AudioStreamPlayer area_mask after opening in 4.7.
references/seasonal-implementation-recipes.md
# Seasonal implementation recipes
Gate first — [easter_seasonal_activation_gate.gd](../scripts/easter_seasonal_activation_gate.gd).
## Custom cursor
```gdscript
func _apply_easter_cursor() -> void:
var cursor_img := preload("res://ui/easter/cursor_bunny.png")
Input.set_custom_mouse_cursor(cursor_img, Input.CURSOR_ARROW, Vector2(16, 16))
```
MANDATORY: [easter_custom_cursor_manager.gd](../scripts/easter_custom_cursor_manager.gd) for hotspot discipline.
## Themed SFX map
`Dictionary` of original name → seasonal `AudioStream` — [easter_seasonal_audio_swapper.gd](../scripts/easter_seasonal_audio_swapper.gd).
## Spring environment tween
Tween `Environment` ambient / tonemap / fog — never hard-cut mid-frame (see SKILL.md World-Environment-Override).
## Palette tokens
Import from [easter_pastel_color_palette.gd](../scripts/easter_pastel_color_palette.gd) — do not paste ad-hoc hex lists in features.
scripts/bouncy_egg_component.gd
class_name BouncyEggComponent
extends RigidBody3D
## A RigidBody that wobbles like an egg.
## Requires a collision shape.
@export var wobble_strength: float = 0.5
@export var squash_factor: float = 0.2
var _original_scale: Vector3
func _ready() -> void:
_original_scale = scale
# Offset center of mass to make it bottom-heavy (classic wobble)
center_of_mass = Vector3(0, -0.3, 0)
body_entered.connect(_on_impact)
contact_monitor = true
max_contacts_reported = 1
func _on_impact(body: Node) -> void:
# Squash and stretch on impact
var tween = create_tween()
tween.set_trans(Tween.TRANS_ELASTIC)
tween.set_ease(Tween.EASE_OUT)
# Scale down Y (squash), Scale up X/Z (stretch)
var squash_scale = _original_scale * Vector3(1.0 + squash_factor, 1.0 - squash_factor, 1.0 + squash_factor)
tween.tween_property(self, "scale", squash_scale, 0.1)
tween.tween_property(self, "scale", _original_scale, 0.4)
# =============================================================================
# GDSkills research links (agents) — does not affect runtime
# Official docs:
# - https://docs.godotengine.org/en/stable/tutorials/ui/gui_skinning.html
# - https://docs.godotengine.org/en/stable/classes/class_tween.html
# Related skills:
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ui-theming/SKILL.md — base Theme architecture
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-particles/SKILL.md — confetti/shimmer VFX
# Parent skill: https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-theme-easter/SKILL.md
# =============================================================================
scripts/easter_camera_pop_juice.gd
class_name EasterCameraPopJuice
extends Camera3D
## Expert camera juice for 'Egg Pops' or collection events.
## Pulses the FOV temporarily to emphasize the impact.
func trigger_pop_kick(strength: float = 5.0) -> void:
var base_fov := fov
var tween := create_tween().set_trans(Tween.TRANS_QUART).set_ease(Tween.EASE_OUT)
tween.tween_property(self, "fov", base_fov + strength, 0.05)
tween.tween_property(self, "fov", base_fov, 0.2)
## Rule: FOV kicks should be subtle (< 10 degrees) to avoid motion sickness.
# =============================================================================
# GDSkills research links (agents) — does not affect runtime
# Official docs:
# - https://docs.godotengine.org/en/stable/tutorials/ui/gui_skinning.html
# - https://docs.godotengine.org/en/stable/classes/class_tween.html
# Related skills:
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ui-theming/SKILL.md — base Theme architecture
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-particles/SKILL.md — confetti/shimmer VFX
# Parent skill: https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-theme-easter/SKILL.md
# =============================================================================
scripts/easter_confetti_canon_vfx.gd
class_name EasterConfettiCanonVFX
extends GPUParticles3D
## Expert confetti canon for celebratory Easter events.
## Emits multi-colored pastel flakes with gravity and rotation.
func burst() -> void:
amount = 100
one_shot = true
emitting = true
## Tip: Use 'collision_mode' on particles to have confetti land on the ground.
# =============================================================================
# GDSkills research links (agents) — does not affect runtime
# Official docs:
# - https://docs.godotengine.org/en/stable/tutorials/ui/gui_skinning.html
# - https://docs.godotengine.org/en/stable/classes/class_tween.html
# Related skills:
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ui-theming/SKILL.md — base Theme architecture
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-particles/SKILL.md — confetti/shimmer VFX
# Parent skill: https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-theme-easter/SKILL.md
# =============================================================================
scripts/easter_custom_cursor_manager.gd
extends Node
## Expert logic for swapping system mouse cursors with themed Easter icons.
func _ready() -> void:
_apply_easter_cursor()
func _apply_easter_cursor() -> void:
# Example implementation from reference
var cursor_img = preload("res://ui/easter/cursor_bunny.png")
if cursor_img:
Input.set_custom_mouse_cursor(cursor_img, Input.CURSOR_ARROW, Vector2(16, 16))
else:
push_warning("Easter cursor image not found.")
# =============================================================================
# GDSkills research links (agents) — does not affect runtime
# Official docs:
# - https://docs.godotengine.org/en/stable/tutorials/ui/gui_skinning.html
# - https://docs.godotengine.org/en/stable/classes/class_tween.html
# Related skills:
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ui-theming/SKILL.md — base Theme architecture
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-particles/SKILL.md — confetti/shimmer VFX
# Parent skill: https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-theme-easter/SKILL.md
# =============================================================================
scripts/easter_egg_collection_tracker.gd
class_name EasterEggCollectionTracker
extends Node
## Expert collection registry for hidden event items.
## Tracks total eggs found and emits signals for HUD updates.
signal egg_count_changed(found: int, total: int)
signal all_eggs_found
var total_eggs := 0
var found_eggs := 0
func register_egg() -> void:
total_eggs += 1
egg_count_changed.emit(found_eggs, total_eggs)
func collect_egg() -> void:
found_eggs += 1
egg_count_changed.emit(found_eggs, total_eggs)
if found_eggs >= total_eggs:
all_eggs_found.emit()
## Tip: Use a Global Autoload for this tracker to persist counts across scene changes.
# =============================================================================
# GDSkills research links (agents) — does not affect runtime
# Official docs:
# - https://docs.godotengine.org/en/stable/tutorials/ui/gui_skinning.html
# - https://docs.godotengine.org/en/stable/classes/class_tween.html
# Related skills:
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ui-theming/SKILL.md — base Theme architecture
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-particles/SKILL.md — confetti/shimmer VFX
# Parent skill: https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-theme-easter/SKILL.md
# =============================================================================
scripts/easter_mesh_painter_override.gd
class_name EasterMeshPainterOverride
extends Node
## Expert seasonal material swapper for 3D meshes.
## Replaces standard surface materials with Easter-themed versions.
@export var mesh_instance: MeshInstance3D
@export var easter_material: Material
func apply_easter_material() -> void:
if not mesh_instance or not easter_material: return
# Expert: Use surface override to avoid modifying the Mesh resource itself.
mesh_instance.set_surface_override_material(0, easter_material)
func remove_easter_material() -> void:
if mesh_instance:
mesh_instance.set_surface_override_material(0, null)
## Rule: Always use 'surface_override' for seasonal changes to preserve original assets.
# =============================================================================
# GDSkills research links (agents) — does not affect runtime
# Official docs:
# - https://docs.godotengine.org/en/stable/tutorials/ui/gui_skinning.html
# - https://docs.godotengine.org/en/stable/classes/class_tween.html
# Related skills:
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ui-theming/SKILL.md — base Theme architecture
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-particles/SKILL.md — confetti/shimmer VFX
# Parent skill: https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-theme-easter/SKILL.md
# =============================================================================
scripts/easter_palette_override.gd
class_name EasterPaletteOverride
extends Node
## Applies an Easter Pastel palette to all child Control nodes.
## Useful for instantly "Spring-ifying" a UI menu.
# The Palette
const COLOR_PINK = Color("FFC1CC")
const COLOR_CYAN = Color("E0FFFF")
const COLOR_YELLOW = Color("FFFFE0")
const COLOR_MINT = Color("98FF98")
@export var target_root: Control
@export var apply_on_ready: bool = true
func _ready() -> void:
if apply_on_ready:
apply_theme()
func apply_theme() -> void:
var root = target_root if target_root else get_parent()
if not root is Control:
return
_apply_to_node_recursive(root)
func _apply_to_node_recursive(node: Node) -> void:
if node is Panel:
_override_stylebox(node, "panel", COLOR_PINK)
elif node is Button:
_override_stylebox(node, "normal", COLOR_CYAN)
_override_stylebox(node, "hover", COLOR_YELLOW)
_override_stylebox(node, "pressed", COLOR_MINT)
elif node is Label:
node.add_theme_color_override("font_color", Color.WHITE)
node.add_theme_color_override("font_outline_color", COLOR_PINK)
node.add_theme_constant_override("outline_size", 4)
for child in node.get_children():
_apply_to_node_recursive(child)
func _override_stylebox(control: Control, theme_item: String, color: Color) -> void:
# We try to get the existing stylebox to preserve borders/radius
# If it's a StyleBoxFlat, we copy it. If not, we make a new one.
var existing = control.get_theme_stylebox(theme_item)
var new_style: StyleBoxFlat
# Crucial: We must duplicate the stylebox to avoid modifying the global theme
if existing is StyleBoxFlat:
new_style = existing.duplicate()
else:
new_style = StyleBoxFlat.new()
# Set some sensible defaults if we're creating from scratch
new_style.set_corner_radius_all(8)
new_style.bg_color = color
control.add_override(theme_item, new_style)
# =============================================================================
# GDSkills research links (agents) — does not affect runtime
# Official docs:
# - https://docs.godotengine.org/en/stable/tutorials/ui/gui_skinning.html
# - https://docs.godotengine.org/en/stable/classes/class_tween.html
# Related skills:
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ui-theming/SKILL.md — base Theme architecture
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-particles/SKILL.md — confetti/shimmer VFX
# Parent skill: https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-theme-easter/SKILL.md
# =============================================================================
scripts/easter_pastel_color_palette.gd
class_name EasterPastelColorPalette
extends Node
## Expert utility for curated Easter aesthetics.
## Provides static Color constants for consistent theming.
static var BLUE := Color("#E0FFFF")
static var PINK := Color("#FFC1CC")
static var YELLOW := Color("#FFFFE0")
static var MINT := Color("#98FF98")
static var PURPLE := Color("#E6E6FA")
## Rule: Stick to these 5 colors for all Easter UI for a cohesive look.
# =============================================================================
# GDSkills research links (agents) — does not affect runtime
# Official docs:
# - https://docs.godotengine.org/en/stable/tutorials/ui/gui_skinning.html
# - https://docs.godotengine.org/en/stable/classes/class_tween.html
# Related skills:
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ui-theming/SKILL.md — base Theme architecture
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-particles/SKILL.md — confetti/shimmer VFX
# Parent skill: https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-theme-easter/SKILL.md
# =============================================================================
scripts/easter_runtime_ui_themer.gd
class_name EasterRuntimeUIThemer
extends Node
## Expert runtime theme injector for mass UI customization.
## Iterates through the scene tree and applies pastel aesthetics.
const PASTEL_PINK = Color("#FFC1CC")
const PASTEL_MINT = Color("#98FF98")
func apply_easter_theme(root_node: Node) -> void:
for child in root_node.get_children():
if child is Button:
_theme_button(child)
elif child is Panel:
_theme_panel(child)
# Recursive injection
apply_easter_theme(child)
func _theme_button(btn: Button) -> void:
var style := StyleBoxFlat.new()
style.bg_color = PASTEL_PINK
style.set_corner_radius_all(12)
style.border_width_bottom = 4
style.border_color = Color.WHITE
btn.add_theme_stylebox_override("normal", style)
## Rule: Always 'duplicate()' or create 'new()' StyleBoxes to avoid global leakage.
# =============================================================================
# GDSkills research links (agents) — does not affect runtime
# Official docs:
# - https://docs.godotengine.org/en/stable/tutorials/ui/gui_skinning.html
# - https://docs.godotengine.org/en/stable/classes/class_tween.html
# Related skills:
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ui-theming/SKILL.md — base Theme architecture
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-particles/SKILL.md — confetti/shimmer VFX
# Parent skill: https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-theme-easter/SKILL.md
# =============================================================================
scripts/easter_seasonal_activation_gate.gd
class_name EasterSeasonalActivationGate
extends Node
## Expert date-aware activation manager.
## Date window + player opt-out + Dev Override (check once on ready / settings change).
signal seasonal_active_changed(active: bool)
@export var easter_content_root: Node
## Inclusive month/day window (default: April 1–30).
@export var start_month: int = 4
@export var start_day: int = 1
@export var end_month: int = 4
@export var end_day: int = 30
## Force-on for QA outside the calendar window.
@export var dev_override_force_on: bool = false
## Force-off even during the window (also respects player opt-out).
@export var dev_override_force_off: bool = false
@export var settings_path: String = "user://settings.cfg"
@export var settings_section: String = "accessibility"
@export var opt_out_key: String = "disable_seasonal_themes"
var is_active: bool = false
func _ready() -> void:
refresh_activation()
func refresh_activation() -> void:
is_active = _compute_active()
if easter_content_root:
easter_content_root.visible = is_active
easter_content_root.process_mode = (
Node.PROCESS_MODE_INHERIT if is_active else Node.PROCESS_MODE_DISABLED
)
seasonal_active_changed.emit(is_active)
func _compute_active() -> bool:
if dev_override_force_off:
return false
if _player_opted_out():
return false
if dev_override_force_on:
return true
return _in_date_window(Time.get_date_dict_from_system())
func _player_opted_out() -> bool:
var cfg := ConfigFile.new()
if cfg.load(settings_path) != OK:
return false
return bool(cfg.get_value(settings_section, opt_out_key, false))
func _in_date_window(date: Dictionary) -> bool:
var m: int = int(date.month)
var d: int = int(date.day)
var start_key := start_month * 100 + start_day
var end_key := end_month * 100 + end_day
var cur_key := m * 100 + d
if start_key <= end_key:
return cur_key >= start_key and cur_key <= end_key
# Wrap across year boundary (e.g. Dec 20 → Jan 10)
return cur_key >= start_key or cur_key <= end_key
## Rule: Always provide a 'Dev Override' flag to test seasonal content off-season.
## Rule: NEVER date-check in _process — call refresh_activation() from settings UI instead.
# =============================================================================
# GDSkills research links (agents) — does not affect runtime
# Official docs:
# - https://docs.godotengine.org/en/stable/tutorials/ui/gui_skinning.html
# - https://docs.godotengine.org/en/stable/classes/class_configfile.html
# Related skills:
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ui-theming/SKILL.md — base Theme architecture
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-particles/SKILL.md — confetti/shimmer VFX
# Parent skill: https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-theme-easter/SKILL.md
# =============================================================================
scripts/easter_seasonal_audio_swapper.gd
extends Node
## Dynamic audio resource loader that replaces standard UI sounds with seasonal variants.
@export var sound_overrides: Dictionary # String -> AudioStream
@onready var sfx_player: AudioStreamPlayer = AudioStreamPlayer.new()
var default_sounds: Dictionary = {}
func _ready() -> void:
add_child(sfx_player)
func play_seasonal_sfx(original_name: String) -> void:
var stream = sound_overrides.get(original_name, default_sounds.get(original_name))
if stream:
sfx_player.stream = stream
sfx_player.play()
else:
push_warning("Sound not found for: " + original_name)
# =============================================================================
# GDSkills research links (agents) — does not affect runtime
# Official docs:
# - https://docs.godotengine.org/en/stable/tutorials/ui/gui_skinning.html
# - https://docs.godotengine.org/en/stable/classes/class_tween.html
# Related skills:
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ui-theming/SKILL.md — base Theme architecture
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-particles/SKILL.md — confetti/shimmer VFX
# Parent skill: https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-theme-easter/SKILL.md
# =============================================================================
scripts/easter_shimmer_vfx_emitter.gd
class_name EasterShimmerVFXEmitter
extends CPUParticles2D
## Expert 'Hidden Item' shimmer effect for Easter Eggs.
## Uses additive blending and scale curves for professional sparkles.
func _ready() -> void:
amount = 8
lifetime = 1.5
explosiveness = 0.1
texture = preload("res://addons/godot-master/assets/sparkle.png") # Placeholder
emission_shape = EMISSION_SHAPE_SPHERE
emission_sphere_radius = 20.0
gravity = Vector2(0, -10) # Slow rise
scale_amount_min = 0.1
scale_amount_max = 0.3
# Shimmer pulse
color = Color(1, 1, 0.8, 1) # Warm white
## Tip: Use 'emitted' signals to trigger collection SFX when the player gets close.
# =============================================================================
# GDSkills research links (agents) — does not affect runtime
# Official docs:
# - https://docs.godotengine.org/en/stable/tutorials/ui/gui_skinning.html
# - https://docs.godotengine.org/en/stable/classes/class_tween.html
# Related skills:
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ui-theming/SKILL.md — base Theme architecture
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-particles/SKILL.md — confetti/shimmer VFX
# Parent skill: https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-theme-easter/SKILL.md
# =============================================================================
scripts/easter_squash_stretch_juice.gd
class_name EasterSquashStretchJuice
extends Node
## Expert squash and stretch 'juice' for interactive objects (Eggs).
## Uses a single Tween to generate organic physical responses.
@export var target_spatial: Node3D
func apply_impact_juice(intensity: float = 0.2) -> void:
if not target_spatial: return
var tween := create_tween().set_trans(Tween.TRANS_ELASTIC).set_ease(Tween.EASE_OUT)
# Squash: Flatten Y, Widen X/Z
tween.tween_property(target_spatial, "scale", Vector3(1.0 + intensity, 1.0 - intensity, 1.0 + intensity), 0.1)
# Snap back to normal
tween.tween_property(target_spatial, "scale", Vector3.ONE, 0.4)
## Tip: Trigger this on '_on_body_entered' or mouse click for maximum feedback.
# =============================================================================
# GDSkills research links (agents) — does not affect runtime
# Official docs:
# - https://docs.godotengine.org/en/stable/tutorials/ui/gui_skinning.html
# - https://docs.godotengine.org/en/stable/classes/class_tween.html
# Related skills:
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ui-theming/SKILL.md — base Theme architecture
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-particles/SKILL.md — confetti/shimmer VFX
# Parent skill: https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-theme-easter/SKILL.md
# =============================================================================
scripts/easter_wobble_physics_body.gd
class_name EasterWobblePhysicsBody
extends RigidBody3D
## Expert wobbly physics for 'Egg-like' interaction.
## Applies a random offset to the center of mass to create organic instability.
func _ready() -> void:
# Shift center of mass slightly to cause a wobble when it rolls
center_of_mass_mode = RigidBody3D.CENTER_OF_MASS_MODE_CUSTOM
center_of_mass = Vector3(randf_range(-0.1, 0.1), -0.2, randf_range(-0.1, 0.1))
## Tip: Low friction + Custom Center of Mass = High quality organic egg motion.
# =============================================================================
# GDSkills research links (agents) — does not affect runtime
# Official docs:
# - https://docs.godotengine.org/en/stable/tutorials/ui/gui_skinning.html
# - https://docs.godotengine.org/en/stable/classes/class_tween.html
# Related skills:
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ui-theming/SKILL.md — base Theme architecture
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-particles/SKILL.md — confetti/shimmer VFX
# Parent skill: https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-theme-easter/SKILL.md
# =============================================================================
scripts/seasonal_material_swapper.gd
class_name SeasonalMaterialSwapper
extends Node
## A utility to swap materials based on the "Season".
## Needs to be attached to a MeshInstance3D or have one assigned.
enum Season { DEFAULT, EASTER }
@export var target_mesh: MeshInstance3D
@export var default_material: Material
@export var easter_material: Material
# Could be a global singleton or local export
@export var current_season: Season = Season.DEFAULT
func _ready() -> void:
if not target_mesh:
target_mesh = get_parent() as MeshInstance3D
apply_season()
func apply_season() -> void:
if not target_mesh:
return
var mat_to_use = default_material
match current_season:
Season.EASTER:
if easter_material:
mat_to_use = easter_material
# Override surface 0 (usually the main material)
target_mesh.set_surface_override_material(0, mat_to_use)
func set_season(new_season: Season) -> void:
current_season = new_season
apply_season()
# =============================================================================
# GDSkills research links (agents) — does not affect runtime
# Official docs:
# - https://docs.godotengine.org/en/stable/tutorials/ui/gui_skinning.html
# - https://docs.godotengine.org/en/stable/classes/class_tween.html
# Related skills:
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ui-theming/SKILL.md — base Theme architecture
# - https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-particles/SKILL.md — confetti/shimmer VFX
# Parent skill: https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-theme-easter/SKILL.md
# =============================================================================
SKILL.md
---
name: godot-theme-easter
description: "Apply a Classic Easter seasonal overlay: pastel Theme/StyleBox injection, confetti/shimmer VFX, elastic juice, mesh surface_override painting, cursor/audio swaps, and a date-window activation gate with player opt-out. Use when shipping holiday skins, April events, or egg-hunt juice without mutating shared .mesh/.tres assets. Keywords: pastel, seasonal Theme, StyleBox, confetti, Easter egg, surface_override, TRANS_ELASTIC, Disable Seasonal Themes, activation gate."
---
## Overview
Seasonal "Easter-fy" toolkit: bright pastels, bouncy juice, egg/bunny iconography — gated by calendar + settings.
**MANDATORY first read:** [easter_seasonal_activation_gate.gd](scripts/easter_seasonal_activation_gate.gd) — date window, `Disable Seasonal Themes` opt-out (`user://settings.cfg`), and Dev Override. Call `refresh_activation()` when settings change; never poll the calendar in `_process`.
**Prerequisite:** Do **NOT Load** [godot-ui-theming](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ui-theming/SKILL.md) until a base `Theme` resource exists — seasonal overlays inject StyleBox overrides; they do not replace foundational Theme authoring.
## Seasonal Bootstrap (ordered)
1. **Gate** — Attach [easter_seasonal_activation_gate.gd](scripts/easter_seasonal_activation_gate.gd); call `refresh_activation()` on `_ready` and when settings change.
2. **Theme** — If gate active: **MANDATORY** [easter_runtime_ui_themer.gd](scripts/easter_runtime_ui_themer.gd) using tokens from [easter_pastel_color_palette.gd](scripts/easter_pastel_color_palette.gd).
3. **Audio** — **MANDATORY** [easter_seasonal_audio_swapper.gd](scripts/easter_seasonal_audio_swapper.gd) to map standard UI SFX → seasonal streams.
4. **Juice** — Layer confetti/shimmer/cursor/wobble scripts only after steps 1–3 pass (gate off = skip 2–4 entirely).
## Decision Tree — Alternate Painters (pick one)
| Context | Use | Do NOT also wire |
|---------|-----|------------------|
| 3D mesh seasonal tint via `surface_override` | [easter_mesh_painter_override.gd](scripts/easter_mesh_painter_override.gd) | [easter_palette_override.gd](scripts/easter_palette_override.gd) on same mesh |
| 2D/modulate or material slot swap already wired | [easter_palette_override.gd](scripts/easter_palette_override.gd) or [seasonal_material_swapper.gd](scripts/seasonal_material_swapper.gd) | mesh_painter on the same target |
## Core Components (Expert Easter Tools)
### [easter_seasonal_activation_gate.gd](scripts/easter_seasonal_activation_gate.gd)
**MANDATORY** — Date-aware manager with opt-out + Dev Override.
### [easter_pastel_color_palette.gd](scripts/easter_pastel_color_palette.gd)
**Single source of truth** for pastel Color tokens — do not hardcode hex lists in SKILL bodies or random scripts.
### [easter_runtime_ui_themer.gd](scripts/easter_runtime_ui_themer.gd)
Runtime theme injector for applying mass pastel styles across the UI tree.
### [easter_squash_stretch_juice.gd](scripts/easter_squash_stretch_juice.gd)
Expert 'Squash and Stretch' logic for organic egg-like interactions using Tweens.
### [easter_shimmer_vfx_emitter.gd](scripts/easter_shimmer_vfx_emitter.gd)
Professional 'Hidden Item' shimmer effect with additive blending and scale curves.
### [easter_egg_collection_tracker.gd](scripts/easter_egg_collection_tracker.gd)
Expert registry for tracking hidden items with signal-based progression signals.
### [easter_mesh_painter_override.gd](scripts/easter_mesh_painter_override.gd)
Seasonal 3D material swapper using surface overrides to preserve base assets.
### [easter_wobble_physics_body.gd](scripts/easter_wobble_physics_body.gd)
Instability-driven physics body for 'Egg-like' wobbly movement.
### [easter_camera_pop_juice.gd](scripts/easter_camera_pop_juice.gd)
Immersive FOV 'kick' logic to emphasize collection or pop events.
### [easter_confetti_canon_vfx.gd](scripts/easter_confetti_canon_vfx.gd)
Celebratory confetti explosion with multi-colored pastel flakes.
### [easter_custom_cursor_manager.gd](scripts/easter_custom_cursor_manager.gd)
Expert logic for swapping system mouse cursors with themed Easter icons.
### [easter_seasonal_audio_swapper.gd](scripts/easter_seasonal_audio_swapper.gd)
Dynamic audio resource loader that replaces standard UI sounds with seasonal variants.
### [easter_palette_override.gd](scripts/easter_palette_override.gd) / [seasonal_material_swapper.gd](scripts/seasonal_material_swapper.gd)
Alternate painters — see **Decision Tree — Alternate Painters** above; pick one path per target.
## Visual Guidelines
- **Colors:** Import tokens from [easter_pastel_color_palette.gd](scripts/easter_pastel_color_palette.gd) (`PINK`, `BLUE`, `YELLOW`, `MINT`, `PURPLE`) — never paste ad-hoc hex laundry lists into features.
- **Shapes:** Rounded corners (`corner_radius` > 8–12). Avoid sharp edges / high-contrast blacks.
- **VFX:** Confetti, sparkles, ribbons via confetti/shimmer scripts.
## NEVER Do (Expert Easter Rules)
### Aesthetics & Juice
- **NEVER use sharp edges or high-contrast blacks** — Easter aesthetics favor rounded corners (`corner_radius > 12`) and soft pastel tones.
- **NEVER use standard linear scaling for pops** — Linear scaling feels 'robotic.' Always use `TRANS_ELASTIC` or `TRANS_QUART` for organic eggs.
- **NEVER use billboarding for Easter particles** — In close-up UI or VR, billboard sparkles look flat. Use mesh-based particles or axial rotation.
### Logic & Performance
- **NEVER modify the original .mesh or .tres resource** — Swapping materials on a shared Resource changes it for EVERY instance in the game. Always use `surface_override` or `duplicate()`.
- **NEVER run date-checks in _process** — Checking the system calendar every frame is wasteful. Run `Time.get_date_dict_from_system()` once on `_ready` or event trigger via the activation gate.
- **NEVER ignore the 'No-Seasonal' toggle** — Some players hate seasonal overrides. Always provide a 'Disable Seasonal Themes' option in settings (wired through the gate's ConfigFile keys).
## Elite Theming Hooks
- **Dynamic Z-Ordering**: Use `RenderingServer.canvas_item_set_draw_index()` to dynamically move collected egg particles to the front of the UI stack without reparenting nodes.
- **Physics Interpolation**: When using `TRANS_ELASTIC` tweens on physics-driven eggs, invoke `RenderingServer.canvas_item_reset_physics_interpolation()` to prevent visual "jitter" on the first frame of the pop animation.
- **StyleBox Overrides**: Use `Control.add_theme_stylebox_override("panel", my_stylebox)` instead of modifying the global Theme to isolate seasonal changes to specific UI modules.
## Expert Easter Implementation
### 1. Custom-Mouse-Cursor (Juice)
**MANDATORY:** [easter_custom_cursor_manager.gd](scripts/easter_custom_cursor_manager.gd) — always set a `hotspot` (bunny-ear tip / base).
### 2. Themed-Sound-Loaders
**MANDATORY:** [easter_seasonal_audio_swapper.gd](scripts/easter_seasonal_audio_swapper.gd) — Resource map of original → seasonal `AudioStream` pairs.
### 3. World-Environment-Override (Spring Glow)
Tween `Environment` ambient/tonemap/fog during a transition — never hard-cut colors mid-frame.
```gdscript
func _apply_spring_env(env: Environment) -> void:
var tween := create_tween()
tween.tween_property(env, "ambient_light_color", EasterPastelColorPalette.YELLOW, 2.0)
tween.tween_property(env, "tonemap_exposure", 1.2, 2.0)
tween.tween_property(env, "fog_light_color", EasterPastelColorPalette.BLUE, 2.0)
```
## Deep recipes (on demand)
> LLM-ignorance rule: if a general agent would not know it before reading, it lives here or in `scripts/` — never delete, only move.
| Topic | Reference |
|-------|-----------|
| Cursor / audio / env recipes | [seasonal-implementation-recipes.md](references/seasonal-implementation-recipes.md) |
## Reference
> Progressive disclosure: open Official Documentation links only when researching a specific API;
> load Related Skills when routing work to a peer domain — do not preload the whole lattice.
### Official Documentation
- [GUI skinning](https://docs.godotengine.org/en/stable/tutorials/ui/gui_skinning.html) — Seasonal Theme swaps and StyleBox isolation.
- [Using the theme editor](https://docs.godotengine.org/en/stable/tutorials/ui/gui_using_theme_editor.html) — Author Easter Theme variants without code-only skins.
- [Theme type variations](https://docs.godotengine.org/en/stable/tutorials/ui/gui_theme_type_variations.html) — Egg/button variants without forking the whole theme.
- [Particle systems (2D)](https://docs.godotengine.org/en/stable/tutorials/2d/particle_systems_2d.html) — Confetti / shimmer VFX for collectible juice.
- [Tween](https://docs.godotengine.org/en/stable/classes/class_tween.html) — Elastic egg pops and camera punch.
- [Environment and post-processing](https://docs.godotengine.org/en/stable/tutorials/3d/environment_and_post_processing.html) — Spring WorldEnvironment glow/fog tweens.
- [Theme](https://docs.godotengine.org/en/stable/classes/class_theme.html) — Runtime seasonal Theme assignment.
- [Input](https://docs.godotengine.org/en/stable/classes/class_input.html) — Custom bunny cursor hotspots.
- [AudioStreamPlayer](https://docs.godotengine.org/en/stable/classes/class_audiostreamplayer.html) — Seasonal SFX bank playback.
- [RenderingServer](https://docs.godotengine.org/en/stable/classes/class_renderingserver.html) — Draw-index and physics-interpolation fixes for juiced eggs.
- [GPUParticles2D](https://docs.godotengine.org/en/stable/classes/class_gpuparticles2d.html) — Confetti canons and shimmer emitters.
- [Environment](https://docs.godotengine.org/en/stable/classes/class_environment.html) — Ambient/tonemap/fog seasonal overrides.
### Related Skills
#### Prerequisites
- [godot-ui-theming](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ui-theming/SKILL.md) — Base Theme architecture before seasonal overlays.
- [godot-project-foundations](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-project-foundations/SKILL.md) — Asset folders and activation gates for seasonal packs.
- [godot-resource-data-patterns](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-resource-data-patterns/SKILL.md) — Sound override maps and palette Resources.
- [godot-signal-architecture](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-signal-architecture/SKILL.md) — Collection trackers and seasonal activation events.
#### Complements
- [godot-tweening](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-tweening/SKILL.md) — Elastic TRANS pops and camera juice.
- [godot-particles](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-particles/SKILL.md) — Confetti/shimmer emitters without reinventing GPUParticles.
- [godot-audio-systems](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-audio-systems/SKILL.md) — Seasonal SFX banks and bus routing.
- [godot-2d-animation](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-2d-animation/SKILL.md) — Squash/stretch juice on collectibles.
- [godot-camera-systems](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-camera-systems/SKILL.md) — Camera pop punches on egg collect.
- [godot-3d-lighting](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-3d-lighting/SKILL.md) — Environment spring glow when the game is 3D.
#### Downstream / consumers
- [godot-genre-party](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-genre-party/SKILL.md) — Seasonal party modes often reuse this juice stack.
- [godot-genre-puzzle](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-genre-puzzle/SKILL.md) — Collectible egg hunts as light puzzle content.
- [godot-game-loop-collection](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-game-loop-collection/SKILL.md) — Collection loops that consume seasonal trackers.
- [godot-monte-carlo-balancer](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-monte-carlo-balancer/SKILL.md) — If egg rewards gate progression, validate drop economies.
#### Master
- [godot-master](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-master/SKILL.md) — Library router and mirrored module entry for seasonal themes.