diff --git a/addons/TweenFX/TweenFX.gd b/addons/TweenFX/TweenFX.gd new file mode 100644 index 0000000..f2a5213 --- /dev/null +++ b/addons/TweenFX/TweenFX.gd @@ -0,0 +1,1096 @@ +@icon("res://addons/TweenFX/icon.png") +## TweenFX — A juicy tween animation library for Godot 4. +## [br][br] +## Provides one-shot and looping animations for CanvasItem nodes. +## Call any animation directly, stop it explicitly, or await its completion. +## [br][br] +## All animations are tracked automatically. Use [method stop] and [method stop_all] +## to interrupt running animations, and [method is_playing] to check their state. +## [br][br] +## [b]Basic usage:[/b] +## [codeblock] +## TweenFX.shake(node) +## TweenFX.shake(node, 0.5, 20.0, 8) +## await TweenFX.shake(node).finished +## [/codeblock] +extends Node +const TweenManager = preload("res://addons/TweenFX/TweenManager.gd") + +#region ENUM +## Some animations support [b]PlayState[/b] for interactive use. +## [b]ENTER[/b] and [b]EXIT[/b] are designed as pairs.[br] +## [i]Pass the target property explicitly so TweenFX always knows where to go regardless of the node's current state. +enum PlayState { + FULL, # play complete animation + ENTER, # animate to target state and hold + EXIT # animate back to original +} + +enum Animations { + POP_IN, + POP_OUT, + PUNCH_IN, + PUNCH_OUT, + FADE_IN, + FADE_OUT, + DROP_IN, + DROP_OUT, + JUMP_SCARE, + SPIN, + SKEW, + VANISH, + SHAKE, + PULSATE, + JITTER, + JELLY, + FLIP, + HOP, + BLINK, + SQUASH, + STRETCH, + SNAP, + COLOR_CYCLE, + HEARTBEAT, + SWING, + CHARGE_UP, + RICOCHET, + GLITCH, + SPOTLIGHT, + WAVE_DISTORT, + WIGGLE, + FLOAT_BOB, + GLOW_PULSE, + TWIST, + ROTATE_HOP, + EXPLODE, + BLACK_HOLE, + MELT, + TV_SHUTDOWN, + MAD_HELICO, + SPIN_BOUNCE, + IDLE_RUBBER, + BUBBLE_ASCEND, + CREEP_OUT, + RUBBER_BAND, + FIDGET, + DEFLATE, + DRUNK, + IMPACT_LAND, + BREATHE, + SWAY, + FLICKER, + CRITICAL_HIT, + UPGRADE, + FOLD_IN, + FOLD_OUT, + ALARM, + POINT, + TADA, + GHOST, + ATTRACT, + ORBIT, + PRESS, + PRESS_ROTATE, + MAGNETIC_PULL, + HEADSHAKE +} + +enum AnimationType { + ONE_SHOT, + LOOPING +} + +enum NodeRequirement { + CANVAS_ITEM, + NODE_2D +} + +#endregion + +#region DICT +const ANIMATION_TYPES: Dictionary = { + Animations.POP_IN: AnimationType.ONE_SHOT, + Animations.POP_OUT: AnimationType.ONE_SHOT, + Animations.PUNCH_IN: AnimationType.ONE_SHOT, + Animations.PUNCH_OUT: AnimationType.ONE_SHOT, + Animations.FADE_IN: AnimationType.ONE_SHOT, + Animations.FADE_OUT: AnimationType.ONE_SHOT, + Animations.DROP_IN: AnimationType.ONE_SHOT, + Animations.DROP_OUT: AnimationType.ONE_SHOT, + Animations.JUMP_SCARE: AnimationType.ONE_SHOT, + Animations.SPIN: AnimationType.ONE_SHOT, + Animations.SKEW: AnimationType.ONE_SHOT, + Animations.VANISH: AnimationType.ONE_SHOT, + Animations.SHAKE: AnimationType.ONE_SHOT, + Animations.PULSATE: AnimationType.ONE_SHOT, + Animations.JITTER: AnimationType.ONE_SHOT, + Animations.JELLY: AnimationType.ONE_SHOT, + Animations.FLIP: AnimationType.ONE_SHOT, + Animations.HOP: AnimationType.ONE_SHOT, + Animations.BLINK: AnimationType.ONE_SHOT, + Animations.SQUASH: AnimationType.ONE_SHOT, + Animations.STRETCH: AnimationType.ONE_SHOT, + Animations.SNAP: AnimationType.ONE_SHOT, + Animations.CHARGE_UP: AnimationType.ONE_SHOT, + Animations.RICOCHET: AnimationType.ONE_SHOT, + Animations.GLITCH: AnimationType.ONE_SHOT, + Animations.SPOTLIGHT: AnimationType.ONE_SHOT, + Animations.TWIST: AnimationType.ONE_SHOT, + Animations.EXPLODE: AnimationType.ONE_SHOT, + Animations.BLACK_HOLE: AnimationType.ONE_SHOT, + Animations.TV_SHUTDOWN: AnimationType.ONE_SHOT, + Animations.CREEP_OUT: AnimationType.ONE_SHOT, + Animations.RUBBER_BAND: AnimationType.ONE_SHOT, + Animations.FIDGET: AnimationType.ONE_SHOT, + Animations.DEFLATE: AnimationType.ONE_SHOT, + Animations.DRUNK: AnimationType.ONE_SHOT, + Animations.IMPACT_LAND: AnimationType.ONE_SHOT, + Animations.CRITICAL_HIT: AnimationType.ONE_SHOT, + Animations.UPGRADE: AnimationType.ONE_SHOT, + Animations.FOLD_IN: AnimationType.ONE_SHOT, + Animations.FOLD_OUT: AnimationType.ONE_SHOT, + Animations.POINT: AnimationType.ONE_SHOT, + Animations.TADA: AnimationType.ONE_SHOT, + Animations.PRESS: AnimationType.ONE_SHOT, + Animations.PRESS_ROTATE: AnimationType.ONE_SHOT, + Animations.MAGNETIC_PULL: AnimationType.ONE_SHOT, + Animations.HEADSHAKE: AnimationType.ONE_SHOT, + + Animations.COLOR_CYCLE: AnimationType.LOOPING, + Animations.HEARTBEAT: AnimationType.LOOPING, + Animations.SWING: AnimationType.LOOPING, + Animations.WAVE_DISTORT: AnimationType.LOOPING, + Animations.WIGGLE: AnimationType.LOOPING, + Animations.FLOAT_BOB: AnimationType.LOOPING, + Animations.GLOW_PULSE: AnimationType.LOOPING, + Animations.ROTATE_HOP: AnimationType.LOOPING, + Animations.SPIN_BOUNCE: AnimationType.LOOPING, + Animations.MAD_HELICO: AnimationType.LOOPING, + Animations.MELT: AnimationType.LOOPING, + Animations.IDLE_RUBBER: AnimationType.LOOPING, + Animations.BUBBLE_ASCEND: AnimationType.LOOPING, + Animations.BREATHE: AnimationType.LOOPING, + Animations.SWAY: AnimationType.LOOPING, + Animations.FLICKER: AnimationType.LOOPING, + Animations.ALARM: AnimationType.LOOPING, + Animations.GHOST: AnimationType.LOOPING, + Animations.ATTRACT: AnimationType.LOOPING, + Animations.ORBIT: AnimationType.LOOPING, +} + +const ANIMATION_REQUIREMENTS: Dictionary = { + Animations.WAVE_DISTORT: NodeRequirement.NODE_2D, + Animations.SKEW: NodeRequirement.NODE_2D, +} +#endregion + +#region LOGIC +## Stops a specific animation running on the node. +func stop(node: CanvasItem, anim: Animations) -> void: + TweenManager.stop(node, anim) + +## Stops all animations currently running on the node. +func stop_all(node: CanvasItem) -> void: + TweenManager.stop_all(node) + +## Returns true if the given animation is currently playing on the node. +func is_playing(node: CanvasItem, anim: Animations) -> bool: + return TweenManager.is_playing(node, anim) + +## Returns true if the animation loops indefinitely until stopped. +func is_looping_type(anim: Animations) -> bool: + return ANIMATION_TYPES.get(anim, AnimationType.ONE_SHOT) == AnimationType.LOOPING + +## Returns true if the animation requires a Node2D target instead of CanvasItem. +func requires_node2d(anim: Animations) -> bool: + return ANIMATION_REQUIREMENTS.get(anim, NodeRequirement.CANVAS_ITEM) == NodeRequirement.NODE_2D +#endregion + +#region TWEEN ANIMATIONS + + #region Looping +## Goes through the colors. +func color_cycle(node: CanvasItem, duration: float = 3.0, saturation: float = 1.0, value: float = 1.0) -> Tween: + TweenManager.stop(node, Animations.COLOR_CYCLE) + var tween := node.create_tween() + tween.set_loops() + tween.set_ease(Tween.EASE_IN_OUT) + tween.set_trans(Tween.TRANS_SINE) + var colors = [ + Color.from_hsv(0.0, saturation, value), + Color.from_hsv(0.17, saturation, value), + Color.from_hsv(0.33, saturation, value), + Color.from_hsv(0.5, saturation, value), + Color.from_hsv(0.67, saturation, value), + Color.from_hsv(0.83, saturation, value), + Color.from_hsv(1.0, saturation, value), + ] + for color in colors: + tween.tween_property(node, "modulate", color, duration / colors.size()) + TweenManager.track(node, Animations.COLOR_CYCLE, tween) + return tween + +## Simulates a heartbeat with two rhythmic pulses. +func heartbeat(node: CanvasItem, duration: float = 1.0, strength: float = 0.2) -> Tween: + TweenManager.stop(node, Animations.HEARTBEAT) + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + tween.set_loops() + tween.tween_property(node, "scale", original_scale * (1 + strength), 0.15).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "scale", original_scale, 0.15).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_IN) + tween.tween_property(node, "scale", original_scale, 0.1) + tween.tween_property(node, "scale", original_scale * (1 + strength * 0.6), 0.1).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "scale", original_scale, 0.1).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_IN) + tween.tween_property(node, "scale", original_scale, duration - 0.6) + TweenManager.track(node, Animations.HEARTBEAT, tween) + return tween + +## Rotates the node back and forth like a pendulum. +func swing(node: CanvasItem, duration: float = 1.0, angle: float = 30.0) -> Tween: + TweenManager.stop(node, Animations.SWING) + var original_rotation : float = node.rotation_degrees + var tween := node.create_tween() + tween.set_loops() + tween.set_ease(Tween.EASE_IN_OUT) + tween.set_trans(Tween.TRANS_SINE) + tween.tween_property(node, "rotation_degrees", original_rotation + angle, duration * 0.5) + tween.tween_property(node, "rotation_degrees", original_rotation - angle, duration) + tween.tween_property(node, "rotation_degrees", original_rotation, duration * 0.5) + TweenManager.track(node, Animations.SWING, tween) + return tween + +## Applies a wave-like distortion effect to the node. +func wave_distort(node: Node2D, duration: float = 1.0, amplitude: float = 0.1) -> Tween: + TweenManager.stop(node, Animations.WAVE_DISTORT) + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + tween.set_loops() + tween.set_ease(Tween.EASE_IN_OUT) + tween.set_trans(Tween.TRANS_SINE) + tween.tween_property(node, "scale:x", original_scale.x * (1 + amplitude), duration * 0.25) + tween.parallel().tween_property(node, "scale:y", original_scale.y * (1 - amplitude/2), duration * 0.25) + tween.parallel().tween_property(node, "skew", amplitude/2, duration * 0.25) + tween.tween_property(node, "scale:x", original_scale.x * (1 - amplitude/2), duration * 0.25) + tween.parallel().tween_property(node, "scale:y", original_scale.y * (1 + amplitude), duration * 0.25) + tween.parallel().tween_property(node, "skew", -amplitude/2, duration * 0.25) + tween.tween_property(node, "scale:x", original_scale.x * (1 - amplitude), duration * 0.25) + tween.parallel().tween_property(node, "scale:y", original_scale.y * (1 - amplitude/2), duration * 0.25) + tween.parallel().tween_property(node, "skew", amplitude/2, duration * 0.25) + tween.tween_property(node, "scale:x", original_scale.x, duration * 0.25) + tween.parallel().tween_property(node, "scale:y", original_scale.y, duration * 0.25) + tween.parallel().tween_property(node, "skew", 0.0, duration * 0.25) + TweenManager.track(node, Animations.WAVE_DISTORT, tween) + return tween + +## Slightly rotates the node back and forth. +func wiggle(node: CanvasItem, duration: float = 1.2) -> Tween: + TweenManager.stop(node, Animations.WIGGLE) + var tween := node.create_tween() + tween.set_loops() + tween.tween_property(node, "rotation_degrees", 5.0, duration * 0.25).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "rotation_degrees", -5.0, duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "rotation_degrees", 0.0, duration * 0.25).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + TweenManager.track(node, Animations.WIGGLE, tween) + return tween + +## Makes the node float up and down in a looping motion. +func float_bob(node: CanvasItem, duration: float = 2.0, height: float = 5.0) -> Tween: + TweenManager.stop(node, Animations.FLOAT_BOB) + var original_pos: Vector2 = node.position + var tween := node.create_tween() + tween.set_loops() + tween.tween_property(node, "position:y", original_pos.y - height, duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "position:y", original_pos.y + height, duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + TweenManager.track(node, Animations.FLOAT_BOB, tween) + return tween + +## Gently pulses the node's scale and opacity in a loop. +func glow_pulse(node: CanvasItem, duration: float = 1.2, scale_amt: float = 0.05, alpha_amt: float = 0.3) -> Tween: + TweenManager.stop(node, Animations.GLOW_PULSE) + var original_scale: Vector2 = node.scale + var original_alpha: float = node.modulate.a + var tween := node.create_tween() + tween.set_loops() + tween.tween_property(node, "scale", original_scale * (1.0 + scale_amt), duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.parallel().tween_property(node, "modulate:a", original_alpha * (1.0 - alpha_amt), duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "scale", original_scale, duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.parallel().tween_property(node, "modulate:a", original_alpha, duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + TweenManager.track(node, Animations.GLOW_PULSE, tween) + return tween + +## Rotates a bit while doing a mini-hop. Good for idle feedback. +func rotate_hop(node: CanvasItem, duration: float = 0.4, angle: float = 15.0, height: float = 10.0) -> Tween: + TweenManager.stop(node, Animations.ROTATE_HOP) + var start_pos = node.position + var tween := node.create_tween() + tween.set_loops() + tween.tween_property(node, "rotation_degrees", angle, duration * 0.25) + tween.parallel().tween_property(node, "position:y", start_pos.y - height, duration * 0.25) + tween.tween_property(node, "rotation_degrees", -angle, duration * 0.25) + tween.parallel().tween_property(node, "position:y", start_pos.y + height, duration * 0.25) + tween.tween_property(node, "rotation_degrees", 0, duration * 0.25) + tween.parallel().tween_property(node, "position:y", start_pos.y, duration * 0.25) + TweenManager.track(node, Animations.ROTATE_HOP, tween) + return tween + +## Pure entropy: spin, random jitter, squash-stretch bounce. +func spin_bounce(node: CanvasItem, duration: float = 0.6, bounce_scale: float = 0.2, spin_speed: float = 180.0) -> Tween: + TweenManager.stop(node, Animations.SPIN_BOUNCE) + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + tween.set_loops() + tween.parallel().tween_property(node, "rotation_degrees", node.rotation_degrees + spin_speed, duration).set_trans(Tween.TRANS_LINEAR) + tween.parallel().tween_property(node, "scale", original_scale * Vector2(1.0 + randf_range(-bounce_scale, bounce_scale), 1.0 + randf_range(-bounce_scale, bounce_scale)), duration * 0.5) + tween.tween_property(node, "scale", original_scale, duration * 0.5) + TweenManager.track(node, Animations.SPIN_BOUNCE, tween) + return tween + +## Makes the object look like it's trying to fly off in a panic. +func mad_helico(node: CanvasItem, duration: float = 0.6, spin_speed: float = 1080.0, bob_height: float = 5.0) -> Tween: + TweenManager.stop(node, Animations.MAD_HELICO) + var original_pos: Vector2 = node.position + var tween := node.create_tween() + tween.set_loops() + tween.parallel().tween_property(node, "rotation_degrees", node.rotation_degrees + spin_speed, duration).set_trans(Tween.TRANS_LINEAR) + tween.tween_property(node, "position:y", original_pos.y - bob_height, duration * 0.3).set_trans(Tween.TRANS_SINE) + tween.tween_property(node, "position:y", original_pos.y + bob_height, duration * 0.3).set_trans(Tween.TRANS_SINE) + tween.tween_property(node, "position:y", original_pos.y, duration * 0.3).set_trans(Tween.TRANS_SINE) + TweenManager.track(node, Animations.MAD_HELICO, tween) + return tween + +## Makes objects drip down slowly and squash — like they're melting. +func melt(node: CanvasItem, duration: float = 2.0, melt_distance: float = 20.0) -> Tween: + TweenManager.stop(node, Animations.MELT) + var original_pos: Vector2 = node.position + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + tween.set_loops() + tween.parallel().tween_property(node, "position:y", original_pos.y + melt_distance, duration * 0.5).set_trans(Tween.TRANS_LINEAR) + tween.parallel().tween_property(node, "scale:y", original_scale.y * 1.3, duration * 0.5) + tween.tween_property(node, "position:y", original_pos.y, duration * 0.5) + tween.tween_property(node, "scale:y", original_scale.y, duration * 0.5) + TweenManager.track(node, Animations.MELT, tween) + return tween + +## Gives the object rubbery springy movement. +func idle_rubber(node: CanvasItem, duration: float = 0.6, strength: float = 0.1) -> Tween: + TweenManager.stop(node, Animations.IDLE_RUBBER) + var original_pos: Vector2 = node.position + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + tween.set_loops() + tween.tween_property(node, "position:x", original_pos.x + 6, duration * 0.3) + tween.parallel().tween_property(node, "scale", original_scale * Vector2(1.1, 0.9), duration * 0.3) + tween.tween_property(node, "position:x", original_pos.x - 6, duration * 0.3) + tween.parallel().tween_property(node, "scale", original_scale * Vector2(0.9, 1.1), duration * 0.3) + tween.tween_property(node, "position:x", original_pos.x, duration * 0.3) + tween.parallel().tween_property(node, "scale", original_scale, duration * 0.3) + TweenManager.track(node, Animations.IDLE_RUBBER, tween) + return tween + +## Floats upward with a bit of distortion. +func bubble_ascend(node: CanvasItem, duration: float = 2.0, height: float = 15.0) -> Tween: + TweenManager.stop(node, Animations.BUBBLE_ASCEND) + var original_pos: Vector2 = node.position + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + tween.set_loops() + tween.tween_property(node, "position:y", original_pos.y - height, duration * 0.6).set_trans(Tween.TRANS_SINE) + tween.parallel().tween_property(node, "scale:y", original_scale.y * 0.95, duration * 0.3) + tween.tween_property(node, "position:y", original_pos.y, duration * 0.4).set_trans(Tween.TRANS_SINE) + tween.parallel().tween_property(node, "scale", original_scale, duration * 0.2) + TweenManager.track(node, Animations.BUBBLE_ASCEND, tween) + return tween + +## Very subtle slow scale pulse. Good for alive/idle state. +func breathe(node: CanvasItem, duration: float = 3.0, strength: float = 0.1) -> Tween: + TweenManager.stop(node, Animations.BREATHE) + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + tween.set_loops() + tween.tween_property(node, "scale", original_scale * (1.0 + strength), duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "scale", original_scale, duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + TweenManager.track(node, Animations.BREATHE, tween) + return tween + +## Slowly fades to low alpha and back, ethereal feel. +func ghost(node: CanvasItem, duration: float = 2.0, min_alpha: float = 0.2) -> Tween: + TweenManager.stop(node, Animations.GHOST) + var original_alpha: float = node.modulate.a + var tween := node.create_tween() + tween.set_loops() + tween.tween_property(node, "modulate:a", min_alpha, duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "modulate:a", original_alpha, duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + TweenManager.track(node, Animations.GHOST, tween) + return tween + +## Grows slightly then pulses to draw attention. +func attract(node: CanvasItem, duration: float = 1.2, strength: float = 0.12) -> Tween: + TweenManager.stop(node, Animations.ATTRACT) + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + tween.set_loops() + tween.tween_property(node, "scale", original_scale * (1.0 + strength), duration * 0.3).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "scale", original_scale * (1.0 + strength * 0.5), duration * 0.2).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "scale", original_scale * (1.0 + strength), duration * 0.2).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "scale", original_scale, duration * 0.3).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN) + TweenManager.track(node, Animations.ATTRACT, tween) + return tween + +## Orbits the node in a circle around its original position. +func orbit(node: CanvasItem, duration: float = 2.0, radius: float = 30.0, start_angle: float = 0.0) -> Tween: + TweenManager.stop(node, Animations.ORBIT) + var original_pos: Vector2 = node.position + var tween := node.create_tween() + tween.set_loops() + var steps = 60 + for i in range(steps + 1): + var angle = start_angle + (float(i) / steps) * TAU + var offset = Vector2(cos(angle), sin(angle)) * radius + tween.tween_property(node, "position", original_pos + offset, duration / steps).set_trans(Tween.TRANS_LINEAR) + TweenManager.track(node, Animations.ORBIT, tween) + return tween + +## Gentle organic sway like a plant in wind. +func sway(node: CanvasItem, duration: float = 2.0, angle: float = 8.0) -> Tween: + TweenManager.stop(node, Animations.SWAY) + var tween := node.create_tween() + tween.set_loops() + tween.tween_property(node, "rotation_degrees", angle, duration * 0.4).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "rotation_degrees", -angle * 0.6, duration * 0.4).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "rotation_degrees", angle * 0.3, duration * 0.1).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "rotation_degrees", 0.0, duration * 0.1).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + TweenManager.track(node, Animations.SWAY, tween) + return tween + +## Random opacity flicker like a candle or broken light. +func flicker(node: CanvasItem, duration: float = 0.08, min_alpha: float = 0.4, steps: int = 8) -> Tween: + TweenManager.stop(node, Animations.FLICKER) + var original_alpha: float = node.modulate.a + var tween := node.create_tween() + tween.set_loops() + for i in range(steps): + var alpha = randf_range(min_alpha, original_alpha) + tween.tween_property(node, "modulate:a", alpha, duration * randf_range(0.5, 1.5)) + TweenManager.track(node, Animations.FLICKER, tween) + return tween + +## Rapid red flash loop, urgent warning. +func alarm(node: CanvasItem, duration: float = 0.3, color : Color = Color(2.0, 0.2, 0.2, 1.0)) -> Tween: + TweenManager.stop(node, Animations.ALARM) + var original_color: Color = node.modulate + var tween := node.create_tween() + tween.set_loops() + tween.tween_property(node, "modulate", color, duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN) + tween.tween_property(node, "modulate", original_color, duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.ALARM, tween) + return tween + #endregion + + #region One-Shot +## Object fades into the dark and shrinks away. +func creep_out(node: CanvasItem, duration: float = 1.0) -> Tween: + TweenManager.stop(node, Animations.CREEP_OUT) + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + tween.tween_property(node, "modulate", Color(0.2, 0.2, 0.2, 1), duration * 0.5) + tween.tween_property(node, "scale", original_scale * 0.8, duration * 0.5) + tween.tween_property(node, "modulate:a", 0.0, duration * 0.3) + TweenManager.track(node, Animations.CREEP_OUT, tween) + return tween + +## Makes the object look like it's being shut down like a cartoon TV. +func tv_shutdown(node: CanvasItem, duration: float = 0.5) -> Tween: + TweenManager.stop(node, Animations.TV_SHUTDOWN) + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + tween.tween_property(node, "scale", original_scale * Vector2(1.3, 0.7), duration * 0.25).set_trans(Tween.TRANS_ELASTIC) + tween.tween_property(node, "scale", original_scale * Vector2(0.7, 1.3), duration * 0.25).set_trans(Tween.TRANS_ELASTIC) + tween.tween_property(node, "scale", Vector2.ZERO, duration * 0.2).set_trans(Tween.TRANS_BOUNCE).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.TV_SHUTDOWN, tween) + return tween + +## Spins and collapses into nothingness. +func black_hole(node: CanvasItem, duration: float = 0.8) -> Tween: + TweenManager.stop(node, Animations.BLACK_HOLE) + var tween := node.create_tween() + tween.parallel().tween_property(node, "scale", Vector2.ZERO, duration).set_trans(Tween.TRANS_EXPO).set_ease(Tween.EASE_IN) + tween.parallel().tween_property(node, "modulate:a", 0.0, duration) + tween.parallel().tween_property(node, "rotation_degrees", node.rotation_degrees + 720, duration) + TweenManager.track(node, Animations.BLACK_HOLE, tween) + return tween + +## Boom! +func explode(node: CanvasItem, duration: float = 0.4, scale_amt: float = 1.8) -> Tween: + TweenManager.stop(node, Animations.EXPLODE) + var tween := node.create_tween() + tween.tween_property(node, "scale", Vector2.ONE * scale_amt, duration * 0.3).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + tween.parallel().tween_property(node, "rotation_degrees", randf_range(-10, 10), duration * 0.2) + tween.tween_property(node, "scale", Vector2.ONE * 0.5, duration * 0.4).set_trans(Tween.TRANS_EXPO).set_ease(Tween.EASE_IN) + tween.parallel().tween_property(node, "modulate:a", 0.0, duration * 0.4).set_trans(Tween.TRANS_LINEAR) + TweenManager.track(node, Animations.EXPLODE, tween) + return tween + +## Builds up energy visually before a release. +func charge_up(node: CanvasItem, duration: float = 1.0) -> Tween: + TweenManager.stop(node, Animations.CHARGE_UP) + var original_scale: Vector2 = node.scale + var original_color: Color = node.modulate + var tween := node.create_tween() + tween.tween_property(node, "scale", original_scale * 0.8, duration * 0.4).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN) + tween.parallel().tween_property(node, "modulate", Color(1.5, 1.5, 0.5, 1.0), duration * 0.4).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN) + for i in range(3): + var pulse_scale = 0.05 * (i + 1) + tween.tween_property(node, "scale", original_scale * (0.8 + pulse_scale), duration * 0.1) + tween.tween_property(node, "scale", original_scale * 0.8, duration * 0.1) + tween.tween_property(node, "scale", original_scale * 1.5, duration * 0.2).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + tween.parallel().tween_property(node, "modulate", Color(2.0, 2.0, 1.0, 1.0), duration * 0.2) + tween.tween_property(node, "scale", original_scale, duration * 0.2).set_trans(Tween.TRANS_ELASTIC).set_ease(Tween.EASE_OUT) + tween.parallel().tween_property(node, "modulate", original_color, duration * 0.2).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.CHARGE_UP, tween) + return tween + +## Shrinks and wobbles like it took a hit. +func punch_out(node: CanvasItem, duration: float = 0.5, min_scale: float = 0.5) -> Tween: + TweenManager.stop(node, Animations.PUNCH_OUT) + var original_scale: Vector2 = node.scale + var original_pos: Vector2 = node.position + var tween := node.create_tween() + tween.tween_property(node, "scale", original_scale * min_scale, duration * 0.2).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN) + for i in range(3): + var jitter = Vector2(randf_range(-1, 1), randf_range(-1, 1)) * 5.0 + tween.tween_property(node, "position", original_pos + jitter, duration * 0.1) + tween.tween_property(node, "scale", original_scale, duration * 0.5).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT) + tween.parallel().tween_property(node, "position", original_pos, duration * 0.1) + TweenManager.track(node, Animations.PUNCH_OUT, tween) + return tween + +## Bounces around as if hitting walls. +func ricochet(node: CanvasItem, duration: float = 0.8, strength: float = 30.0, bounces: int = 4) -> Tween: + TweenManager.stop(node, Animations.RICOCHET) + var original_pos: Vector2 = node.position + var tween := node.create_tween() + for i in range(bounces): + var random_dir = Vector2(randf_range(-1, 1), randf_range(-1, 1)).normalized() + var target_pos = original_pos + random_dir * strength + tween.tween_property(node, "position", target_pos, (duration / bounces) * 0.8).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "position", original_pos, duration * 0.2).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.RICOCHET, tween) + return tween + +## Simulates a digital glitch with color and position jitter. +func glitch(node: CanvasItem, duration: float = 1.0, intensity: float = 10.0, frames: int = 12) -> Tween: + TweenManager.stop(node, Animations.GLITCH) + var original_pos: Vector2 = node.position + var original_color: Color = node.modulate + var tween := node.create_tween() + for i in range(frames): + var offset = Vector2(randf_range(-1, 1), randf_range(-1, 1)) * intensity + var color_shift = Color(randf_range(0.8, 1.2), randf_range(0.8, 1.2), randf_range(0.8, 1.2), 1.0) + var glitch_time = duration / frames * 0.5 + tween.tween_property(node, "position", original_pos + offset, glitch_time) + tween.parallel().tween_property(node, "modulate", color_shift, glitch_time) + tween.tween_property(node, "position", original_pos, glitch_time) + tween.parallel().tween_property(node, "modulate", original_color, glitch_time) + tween.tween_property(node, "position", original_pos, 0.1) + tween.parallel().tween_property(node, "modulate", original_color, 0.1) + TweenManager.track(node, Animations.GLITCH, tween) + return tween + +## A fast zoom and shake for a startling impact. +func jump_scare(node: CanvasItem, duration: float = 0.4, intensity: float = 1.3) -> Tween: + TweenManager.stop(node, Animations.JUMP_SCARE) + var original_scale: Vector2 = node.scale + var original_pos: Vector2 = node.position + var tween := node.create_tween() + tween.tween_property(node, "scale", original_scale * intensity, duration * 0.3).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + for i in range(6): + var shake_offset = Vector2(randf_range(-1, 1), randf_range(-1, 1)).normalized() * 10.0 + tween.parallel().tween_property(node, "position", original_pos + shake_offset, duration * 0.05) + tween.tween_property(node, "position", original_pos, duration * 0.05) + tween.parallel().tween_property(node, "scale", original_scale, duration * 0.7).set_trans(Tween.TRANS_ELASTIC).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.JUMP_SCARE, tween) + return tween + +## Highlights the node with a glowing effect. Supports PlayState for hold/release. +func spotlight(node: CanvasItem, duration: float = 1.0, glow: Color = Color(1.5, 1.5, 1.5, 1.0), state: PlayState = PlayState.FULL, use_self_modulate : bool = false) -> Tween: + TweenManager.stop(node, Animations.SPOTLIGHT) + var original_color: Color = node.modulate if not use_self_modulate else node.self_modulate + var node_modulate_property: String = "modulate" if not use_self_modulate else "self_modulate" + var tween := node.create_tween() + match state: + PlayState.ENTER: + tween.tween_property(node, node_modulate_property, glow, duration * 0.3).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN) + PlayState.EXIT: + tween.tween_property(node, node_modulate_property, glow, duration * 0.3).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT) + PlayState.FULL: + tween.tween_property(node, node_modulate_property, glow, duration * 0.3).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN) + tween.tween_property(node, node_modulate_property, glow, duration * 0.4) + tween.tween_property(node, node_modulate_property, original_color, duration * 0.3).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.SPOTLIGHT, tween) + return tween + +## Flips the node along the given axis. +func flip(node: CanvasItem, duration: float = 0.4, axis: String = "x", flips: int = 1) -> Tween: + TweenManager.stop(node, Animations.FLIP) + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + for i in range(flips): + tween.tween_property(node, "scale:" + axis, -original_scale[axis], duration * 0.5 / flips).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN) + tween.tween_property(node, "scale:" + axis, original_scale[axis], duration * 0.5 / flips).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.FLIP, tween) + return tween + +## Makes the node hop in a given direction and land back. +func hop(node: CanvasItem, duration: float = 0.4, height: float = 20.0, direction: Vector2 = Vector2.UP) -> Tween: + TweenManager.stop(node, Animations.HOP) + var original_pos: Vector2 = node.position + var offset = direction.normalized() * height + var tween := node.create_tween() + tween.tween_property(node, "position", original_pos + offset, duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "position", original_pos, duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN) + TweenManager.track(node, Animations.HOP, tween) + return tween + +## Rapidly blinks the node's opacity. +func blink(node: CanvasItem, duration: float = 0.1, times: int = 3, from: float = 0.0, to: float = 1.0) -> Tween: + TweenManager.stop(node, Animations.BLINK) + var tween := node.create_tween() + for i in range(times): + tween.tween_property(node, "modulate:a", from, duration) + tween.tween_property(node, "modulate:a", to, duration) + TweenManager.track(node, Animations.BLINK, tween) + return tween + +## Squashes the node along one axis and stretches the other, then returns. +func squash(node: CanvasItem, duration: float = 0.2, amount: float = 0.3, horizontal: bool = true) -> Tween: + TweenManager.stop(node, Animations.SQUASH) + var original_scale: Vector2 = node.scale + var target = Vector2(original_scale.x * (1 + amount), original_scale.y * (1 - amount)) if horizontal else Vector2(original_scale.x * (1 - amount), original_scale.y * (1 + amount)) + var tween := node.create_tween() + tween.tween_property(node, "scale", target, duration * 0.5).set_trans(Tween.TRANS_SINE) + tween.tween_property(node, "scale", original_scale, duration * 0.5).set_trans(Tween.TRANS_SINE) + TweenManager.track(node, Animations.SQUASH, tween) + return tween + +## Stretches the node vertically, then returns to original scale. +func stretch(node: CanvasItem, duration: float = 0.2, amount: float = 0.3) -> Tween: + TweenManager.stop(node, Animations.STRETCH) + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + tween.tween_property(node, "scale", Vector2(original_scale.x * (1 - amount), original_scale.y * (1 + amount)), duration * 0.5).set_trans(Tween.TRANS_SINE) + tween.tween_property(node, "scale", original_scale, duration * 0.5).set_trans(Tween.TRANS_SINE) + TweenManager.track(node, Animations.STRETCH, tween) + return tween + +## Scales the node up quickly, then resets. Supports PlayState for hold/release. +func snap(node: CanvasItem, duration: float = 0.1, scale: Vector2 = Vector2(1.3, 1.3), state: PlayState = PlayState.FULL) -> Tween: + TweenManager.stop(node, Animations.SNAP) + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + match state: + PlayState.ENTER: + tween.tween_property(node, "scale", scale, duration).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + PlayState.EXIT: + tween.tween_property(node, "scale", scale, duration).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_IN) + PlayState.FULL: + tween.tween_property(node, "scale", scale, duration).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "scale", original_scale, duration).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_IN) + TweenManager.track(node, Animations.SNAP, tween) + return tween + +## Quickly flashes the node's opacity. +func flash(node: CanvasItem, duration: float = 0.1, flashes: int = 3) -> Tween: + TweenManager.stop(node, Animations.BLINK) + var tween := node.create_tween() + for i in range(flashes): + tween.tween_property(node, "modulate", Color(1, 1, 1, 0), duration) + tween.tween_property(node, "modulate", Color(1, 1, 1, 1), duration) + TweenManager.track(node, Animations.BLINK, tween) + return tween + +## Fades the node in from transparent. +func fade_in(node: CanvasItem, duration: float = 0.5) -> Tween: + TweenManager.stop(node, Animations.FADE_IN) + node.modulate.a = 0.0 + var tween := node.create_tween() + tween.tween_property(node, "modulate:a", 1.0, duration).set_trans(Tween.TRANS_LINEAR).set_ease(Tween.EASE_IN) + TweenManager.track(node, Animations.FADE_IN, tween) + return tween + +## Fades the node out to transparent. +func fade_out(node: CanvasItem, duration: float = 0.5) -> Tween: + TweenManager.stop(node, Animations.FADE_OUT) + var tween := node.create_tween() + tween.tween_property(node, "modulate:a", 0.0, duration).set_trans(Tween.TRANS_LINEAR).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.FADE_OUT, tween) + return tween + +## Twists the node in place with a quick rotation. +func twist(node: CanvasItem, duration: float = 0.4, angle: float = 30.0) -> Tween: + TweenManager.stop(node, Animations.TWIST) + var start = node.rotation_degrees + var tween := node.create_tween() + tween.tween_property(node, "rotation_degrees", start + angle, duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "rotation_degrees", start, duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN) + TweenManager.track(node, Animations.TWIST, tween) + return tween + +## Expands and contracts the node once. +func pulsate(node: CanvasItem, duration: float = 0.5, scale_factor: float = 1.2) -> Tween: + TweenManager.stop(node, Animations.PULSATE) + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + tween.tween_property(node, "scale", original_scale * scale_factor, duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "scale", original_scale, duration * 0.5).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + TweenManager.track(node, Animations.PULSATE, tween) + return tween + +## Rapid nervous jitter with rotation and scale micro-variations. +func jitter(node: CanvasItem, duration: float = 0.5, amount: float = 5.0, times: int = 8) -> Tween: + TweenManager.stop(node, Animations.JITTER) + var original_position : Vector2 = node.position + var original_rotation : float = node.rotation_degrees + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + for i in range(times): + var offset = Vector2(randf_range(-amount, amount), randf_range(-amount, amount)) + var rot = randf_range(-3.0, 3.0) + var scl = original_scale * Vector2(randf_range(0.95, 1.05), randf_range(0.95, 1.05)) + tween.tween_property(node, "position", original_position + offset, duration / times) + tween.parallel().tween_property(node, "rotation_degrees", original_rotation + rot, duration / times) + tween.parallel().tween_property(node, "scale", scl, duration / times) + tween.tween_property(node, "position", original_position, 0.05) + tween.parallel().tween_property(node, "rotation_degrees", original_rotation, 0.05) + tween.parallel().tween_property(node, "scale", original_scale, 0.05) + TweenManager.track(node, Animations.JITTER, tween) + return tween + +## Alternates between squash and stretch repeatedly, like jelly wobbling. +func jelly(node: CanvasItem, duration: float = 0.6, amount: float = 0.3, cycles: int = 2) -> Tween: + TweenManager.stop(node, Animations.JELLY) + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + for i in range(cycles): + tween.tween_property(node, "scale", original_scale * Vector2(1.0 + amount, 1.0 - amount), duration * 0.25 / cycles).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "scale", original_scale * Vector2(1.0 - amount, 1.0 + amount), duration * 0.25 / cycles).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "scale", original_scale, duration * 0.2).set_trans(Tween.TRANS_ELASTIC).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.JELLY, tween) + return tween + +## Rotates the node one or more full revolutions. +func spin(node: CanvasItem, duration: float = 0.5, revolutions: float = 1.0, clockwise: bool = true) -> Tween: + TweenManager.stop(node, Animations.SPIN) + var original_rotation : float = node.rotation_degrees + var direction = 1.0 if clockwise else -1.0 + var tween := node.create_tween() + tween.tween_property(node, "rotation_degrees", original_rotation + 360.0 * revolutions * direction, duration).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "rotation_degrees", original_rotation, 0.0) + TweenManager.track(node, Animations.SPIN, tween) + return tween + +## Scales in from zero with a slight overshoot. +func pop_in(node: CanvasItem, duration: float = 0.3, overshoot: float = 0.1) -> Tween: + TweenManager.stop(node, Animations.POP_IN) + var original_scale: Vector2 = node.scale + var original_alpha := node.modulate.a + node.scale = Vector2.ZERO + node.modulate.a = 0.0 + var tween := node.create_tween() + tween.tween_property(node, "scale", original_scale * (1.0 + overshoot), duration).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "scale", original_scale, duration * 0.33) + tween.parallel().tween_property(node, "modulate:a", original_alpha, duration * 0.66) + TweenManager.track(node, Animations.POP_IN, tween) + return tween + +## Scales out to zero with a slight pull in before vanishing. +func pop_out(node: CanvasItem, duration: float = 0.3, overshoot: float = 0.1) -> Tween: + TweenManager.stop(node, Animations.POP_OUT) + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + tween.tween_property(node, "scale", original_scale * (1.0 + overshoot), duration * 0.2).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "scale", Vector2.ZERO, duration * 0.8).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_IN) + tween.parallel().tween_property(node, "modulate:a", 0.0, duration * 0.8) + TweenManager.track(node, Animations.POP_OUT, tween) + return tween + +## Skews the node along X and Y axes temporarily. +func skew(node: Node2D, duration: float = 0.3, skew_x: float = 0.5, skew_y: float = 0.5) -> Tween: + TweenManager.stop(node, Animations.SKEW) + var original_scale: Vector2 = node.scale + var target_scale := original_scale * Vector2(1.0 + skew_x, 1.0 + skew_y) + var tween := node.create_tween() + tween.tween_property(node, "scale", target_scale, duration).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "scale", original_scale, duration).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN_OUT).set_delay(duration) + TweenManager.track(node, Animations.SKEW, tween) + return tween + +## Fades out and scales down the node. +func vanish(node: CanvasItem, duration: float = 0.4) -> Tween: + TweenManager.stop(node, Animations.VANISH) + var tween := node.create_tween() + tween.tween_property(node, "modulate:a", 0.0, duration) + tween.parallel().tween_property(node, "scale", Vector2(0.0, 0.0), duration).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_IN) + TweenManager.track(node, Animations.VANISH, tween) + return tween + +## Quickly scales the node in with a slight bounce. +func punch_in(node: CanvasItem, duration: float = 0.15, strength: float = 0.3) -> Tween: + TweenManager.stop(node, Animations.PUNCH_IN) + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + tween.tween_property(node, "scale", original_scale * (1 + strength), duration).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "scale", original_scale, duration).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN) + TweenManager.track(node, Animations.PUNCH_IN, tween) + return tween + +## Moves the node back and forth rapidly. +## axis: Vector2.RIGHT for horizontal only, Vector2.DOWN for vertical only, Vector2.ONE for both. +func shake(node: CanvasItem, duration: float = 0.3, amount: float = 10.0, shakes: int = 5, axis: Vector2 = Vector2.ONE) -> Tween: + TweenManager.stop(node, Animations.SHAKE) + var original_pos: Vector2 = node.position + var tween := node.create_tween() + for i in range(shakes): + var offset = Vector2( + randf_range(-amount, amount) * axis.x, + randf_range(-amount, amount) * axis.y + ) + tween.tween_property(node, "position", original_pos + offset, duration / (shakes * 2)) + tween.tween_property(node, "position", original_pos, duration / (shakes * 2)) + TweenManager.track(node, Animations.SHAKE, tween) + return tween + +## Drops the node from above into its position. +func drop_in(node: CanvasItem, duration: float = 0.5, drop_height: float = 100.0, scale_distort: Vector2 = Vector2(1.2, 0.8)) -> Tween: + TweenManager.stop(node, Animations.DROP_IN) + var original_pos: Vector2 = node.position + var original_scale: Vector2 = node.scale + var original_alpha: float = node.modulate.a + node.position = original_pos - Vector2(0, drop_height) + node.scale = scale_distort + node.modulate.a = 0.0 + var tween := node.create_tween() + tween.tween_property(node, "position", original_pos, duration).set_trans(Tween.TRANS_BOUNCE).set_ease(Tween.EASE_OUT) + tween.parallel().tween_property(node, "scale", original_scale, duration * 0.6).set_trans(Tween.TRANS_ELASTIC).set_ease(Tween.EASE_OUT) + tween.parallel().tween_property(node, "modulate:a", original_alpha, duration * 0.4) + TweenManager.track(node, Animations.DROP_IN, tween) + return tween + +## Drops the node downward and fades out. +func drop_out(node: CanvasItem, duration: float = 0.5, drop_height: float = 100.0) -> Tween: + TweenManager.stop(node, Animations.DROP_OUT) + var original_pos: Vector2 = node.position + var tween := node.create_tween() + tween.tween_property(node, "position", original_pos + Vector2(0, drop_height), duration).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_IN) + tween.parallel().tween_property(node, "modulate:a", 0.0, duration * 0.6) + TweenManager.track(node, Animations.DROP_OUT, tween) + return tween + +## Stretches in one direction then snaps back with overshoot. +func rubber_band(node: CanvasItem, duration: float = 0.5, strength: float = 0.4) -> Tween: + TweenManager.stop(node, Animations.RUBBER_BAND) + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + tween.tween_property(node, "scale", original_scale * Vector2(1.0 + strength, 1.0 - strength * 0.5), duration * 0.3).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "scale", original_scale * Vector2(0.9, 1.1), duration * 0.2).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "scale", original_scale * Vector2(1.05, 0.97), duration * 0.2).set_trans(Tween.TRANS_SINE) + tween.tween_property(node, "scale", original_scale, duration * 0.3).set_trans(Tween.TRANS_ELASTIC).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.RUBBER_BAND, tween) + return tween + +## Rapidly cycles random rotations then snaps to original. Good for randomness feedback. +func fidget(node: CanvasItem, duration: float = 0.8, spins: int = 6) -> Tween: + TweenManager.stop(node, Animations.FIDGET) + var original_rotation : float = node.rotation_degrees + var tween := node.create_tween() + for i in range(spins): + var random_rot = randf_range(-25.0, 25.0) + tween.tween_property(node, "rotation_degrees", original_rotation + random_rot, duration / spins).set_trans(Tween.TRANS_SINE) + tween.tween_property(node, "rotation_degrees", original_rotation, duration * 0.2).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.FIDGET, tween) + return tween + +## Slowly shrinks Y while expanding X, like air leaving a balloon. +func deflate(node: CanvasItem, duration: float = 0.6) -> Tween: + TweenManager.stop(node, Animations.DEFLATE) + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + tween.tween_property(node, "scale", original_scale * Vector2(1.3, 0.2), duration * 0.6).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_IN) + tween.tween_property(node, "scale", original_scale * Vector2(1.1, 0.15), duration * 0.2).set_trans(Tween.TRANS_SINE) + tween.tween_property(node, "scale", original_scale, duration * 0.4).set_trans(Tween.TRANS_ELASTIC).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.DEFLATE, tween) + return tween + +## Slow random wobble on position and rotation. Good for status effects. +func drunk(node: CanvasItem, duration: float = 0.8) -> Tween: + TweenManager.stop(node, Animations.DRUNK) + var original_pos: Vector2 = node.position + var original_rot = node.rotation_degrees + var tween := node.create_tween() + for i in range(4): + var offset = Vector2(randf_range(-8, 8), randf_range(-5, 5)) + var rot = randf_range(-8, 8) + tween.tween_property(node, "position", original_pos + offset, duration * 0.25).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.parallel().tween_property(node, "rotation_degrees", original_rot + rot, duration * 0.25).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "position", original_pos, duration * 0.2).set_trans(Tween.TRANS_SINE) + tween.parallel().tween_property(node, "rotation_degrees", original_rot, duration * 0.2).set_trans(Tween.TRANS_SINE) + TweenManager.track(node, Animations.DRUNK, tween) + return tween + +## Squash on hit, bounce up, then settle. Classic landing feel. +func impact_land(node: CanvasItem, duration: float = 0.5) -> Tween: + TweenManager.stop(node, Animations.IMPACT_LAND) + var original_scale: Vector2 = node.scale + var original_pos: Vector2 = node.position + var tween := node.create_tween() + tween.tween_property(node, "scale", original_scale * Vector2(1.4, 0.6), duration * 0.15).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "scale", original_scale * Vector2(0.85, 1.2), duration * 0.2).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + tween.parallel().tween_property(node, "position:y", original_pos.y - 12, duration * 0.2) + tween.tween_property(node, "scale", original_scale * Vector2(1.05, 0.97), duration * 0.15).set_trans(Tween.TRANS_SINE) + tween.parallel().tween_property(node, "position:y", original_pos.y, duration * 0.15) + tween.tween_property(node, "scale", original_scale, duration * 0.2).set_trans(Tween.TRANS_SINE) + TweenManager.track(node, Animations.IMPACT_LAND, tween) + return tween + +## Big scale punch with chromatic color shift. Classic critical hit feedback. +func critical_hit(node: CanvasItem, duration: float = 0.5, color: Color = Color(2.0, 0.3, 0.3, 1.0), scale_amount: float = 1.6) -> Tween: + TweenManager.stop(node, Animations.CRITICAL_HIT) + var original_scale: Vector2 = node.scale + var original_color: Color = node.modulate + var secondary_color = Color(color.r, clampf(color.g + 0.8, 0.0, 2.0), 0.2, 1.0) + var tween := node.create_tween() + if scale_amount != 1.0: + tween.tween_property(node, "scale", original_scale * scale_amount, duration * 0.1).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + tween.parallel().tween_property(node, "modulate", color, duration * 0.1) + tween.tween_property(node, "scale", original_scale * 0.85, duration * 0.15).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_IN) + tween.parallel().tween_property(node, "modulate", secondary_color, duration * 0.15) + tween.tween_property(node, "scale", original_scale * scale_amount * 0.69, duration * 0.1).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "scale", original_scale, duration * 0.3).set_trans(Tween.TRANS_ELASTIC).set_ease(Tween.EASE_OUT) + tween.parallel().tween_property(node, "modulate", original_color, duration * 0.3) + else: + tween.tween_property(node, "modulate", color, duration * 0.1) + tween.tween_property(node, "modulate", secondary_color, duration * 0.15) + tween.tween_property(node, "modulate", original_color, duration * 0.3) + TweenManager.track(node, Animations.CRITICAL_HIT, tween) + return tween + +## Scale up, glow, then settle. Celebratory upgrade feedback. +func upgrade(node: CanvasItem, duration: float = 0.8, glow: Color = Color(2.0, 1.8, 0.2, 1.0), scale_amount: float = 1.5) -> Tween: + TweenManager.stop(node, Animations.UPGRADE) + var original_scale: Vector2 = node.scale + var original_color: Color = node.modulate + var secondary_color : Color = Color(glow.r * 0.9, glow.g * 0.9, glow.b + 0.3, 1.0) + var tween := node.create_tween() + if scale_amount != 1.0: + tween.tween_property(node, "scale", original_scale * 0.8, duration * 0.1).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN) + tween.tween_property(node, "scale", original_scale * scale_amount, duration * 0.2).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + tween.parallel().tween_property(node, "modulate", glow, duration * 0.2) + tween.tween_property(node, "scale", original_scale * (scale_amount * 0.8), duration * 0.15).set_trans(Tween.TRANS_SINE) + tween.parallel().tween_property(node, "modulate", secondary_color, duration * 0.15) + tween.tween_property(node, "scale", original_scale * (scale_amount * 0.9), duration * 0.1).set_trans(Tween.TRANS_SINE) + tween.tween_property(node, "scale", original_scale, duration * 0.3).set_trans(Tween.TRANS_ELASTIC).set_ease(Tween.EASE_OUT) + tween.parallel().tween_property(node, "modulate", original_color, duration * 0.3) + else: + tween.tween_property(node, "modulate", glow, duration * 0.2) + tween.tween_property(node, "modulate", secondary_color, duration * 0.15) + tween.tween_property(node, "modulate", original_color, duration * 0.3) + TweenManager.track(node, Animations.UPGRADE, tween) + return tween + +## Unfolds the node by scaling Y from 0 to full size. +func fold_in(node: CanvasItem, duration: float = 0.3) -> Tween: + TweenManager.stop(node, Animations.FOLD_IN) + var original_scale: Vector2 = node.scale + node.scale.y = 0.0 + var tween := node.create_tween() + tween.tween_property(node, "scale:y", original_scale.y, duration).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.FOLD_IN, tween) + return tween + +## Folds the node away by scaling Y to 0. +func fold_out(node: CanvasItem, duration: float = 0.3) -> Tween: + TweenManager.stop(node, Animations.FOLD_OUT) + var tween := node.create_tween() + tween.tween_property(node, "scale:y", 0.0, duration).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_IN) + TweenManager.track(node, Animations.FOLD_OUT, tween) + return tween + +## Quick nudge in one direction then back, like pointing at something. +func point(node: CanvasItem, duration: float = 0.5, direction: Vector2 = Vector2.RIGHT, amount: float = 24.0) -> Tween: + TweenManager.stop(node, Animations.POINT) + var original_pos: Vector2 = node.position + var tween := node.create_tween() + tween.tween_property(node, "position", original_pos + direction.normalized() * amount, duration * 0.3).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "position", original_pos, duration * 0.7).set_trans(Tween.TRANS_ELASTIC).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.POINT, tween) + return tween + +## Scale up, slight rotation, then settle. Celebratory reveal. +func tada(node: CanvasItem, duration: float = 0.6) -> Tween: + TweenManager.stop(node, Animations.TADA) + var original_scale: Vector2 = node.scale + var original_rotation : float = node.rotation_degrees + var tween := node.create_tween() + tween.tween_property(node, "scale", original_scale * 0.8, duration * 0.1).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN) + tween.tween_property(node, "scale", original_scale * 1.4, duration * 0.2).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + tween.parallel().tween_property(node, "rotation_degrees", original_rotation - 8.0, duration * 0.2) + tween.tween_property(node, "rotation_degrees", original_rotation + 8.0, duration * 0.15).set_trans(Tween.TRANS_SINE) + tween.tween_property(node, "rotation_degrees", original_rotation, duration * 0.15).set_trans(Tween.TRANS_SINE) + tween.tween_property(node, "scale", original_scale, duration * 0.3).set_trans(Tween.TRANS_ELASTIC).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.TADA, tween) + return tween + + #endregion + + #region NEW +## Squash on press, bounce back with overshoot, then settle. +func press(node: CanvasItem, duration: float = 0.3) -> Tween: + TweenManager.stop(node, Animations.PRESS) + var original_scale: Vector2 = node.scale + var tween := node.create_tween() + tween.tween_property(node, "scale", original_scale * 0.8, duration * 0.24).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "scale", original_scale * 1.1, duration * 0.45).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "scale", original_scale, duration * 0.30).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.PRESS, tween) + return tween + +## Scale + rotation wiggle on press. +func press_rotate(node: CanvasItem, duration: float = 0.3) -> Tween: + TweenManager.stop(node, Animations.PRESS_ROTATE) + var original_scale: Vector2 = node.scale + var original_rotation : float = node.rotation + var tween := node.create_tween() + tween.set_parallel(true) + tween.tween_property(node, "scale", original_scale * 0.85, duration * 0.33).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + tween.tween_property(node, "scale", original_scale, duration * 0.66).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT).set_delay(duration * 0.33) + tween.tween_property(node, "rotation", original_rotation + deg_to_rad(5), duration * 0.33).set_trans(Tween.TRANS_SINE) + tween.tween_property(node, "rotation", original_rotation - deg_to_rad(5), duration * 0.33).set_trans(Tween.TRANS_SINE).set_delay(duration * 0.33) + tween.tween_property(node, "rotation", original_rotation, duration * 0.33).set_trans(Tween.TRANS_SINE).set_delay(duration * 0.66) + TweenManager.track(node, Animations.PRESS_ROTATE, tween) + return tween + +## Moves toward a target point and snaps back. Magnetic pull feel. +func magnetic_pull(node: CanvasItem, duration: float = 0.5, target: Vector2 = Vector2.ZERO, strength: float = 0.4) -> Tween: + TweenManager.stop(node, Animations.MAGNETIC_PULL) + var original_pos: Vector2 = node.position + var pull_pos = original_pos.lerp(target, strength) + var tween := node.create_tween() + tween.tween_property(node, "position", pull_pos, duration * 0.4).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_IN) + tween.tween_property(node, "position", original_pos, duration * 0.6).set_trans(Tween.TRANS_ELASTIC).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.MAGNETIC_PULL, tween) + return tween + +## Shake left-right — denial, wrong answer, access refused, refusal/no gesture. +func headshake(node: CanvasItem, duration: float = 0.5, amount: float = 8.0, times: int = 3) -> Tween: + TweenManager.stop(node, Animations.HEADSHAKE) + var original_rotation : float = node.rotation_degrees + var tween := node.create_tween() + for i in range(times): + var dir = 1.0 if i % 2 == 0 else -1.0 + tween.tween_property(node, "rotation_degrees", original_rotation + amount * dir, duration * 0.3 / times).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(node, "rotation_degrees", original_rotation, duration * 0.25).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + TweenManager.track(node, Animations.HEADSHAKE, tween) + return tween + #endregion + +#endregion diff --git a/addons/TweenFX/TweenFX.gd.uid b/addons/TweenFX/TweenFX.gd.uid new file mode 100644 index 0000000..0eaf7cf --- /dev/null +++ b/addons/TweenFX/TweenFX.gd.uid @@ -0,0 +1 @@ +uid://d2n10rw2dnx8o diff --git a/addons/TweenFX/TweenManager.gd b/addons/TweenFX/TweenManager.gd new file mode 100644 index 0000000..fba4725 --- /dev/null +++ b/addons/TweenFX/TweenManager.gd @@ -0,0 +1,43 @@ +## Internal tracking system for TweenFX. +## [br][br] +## Manages active tweens per node, handles cleanup when nodes are freed, +## and provides stop/query methods. Not intended for direct use — +## access through [TweenFX] instead. + +static var _active: Dictionary = {} # { node: { TweenFX.Animations.X: tween } } + +static func track(node: CanvasItem, anim: TweenFX.Animations, tween: Tween) -> void: + if not _active.has(node): + _active[node] = {} + if not node.tree_exiting.is_connected(_on_node_exiting): + node.tree_exiting.connect(_on_node_exiting.bind(node), CONNECT_ONE_SHOT) + _active[node][anim] = tween + tween.finished.connect(_on_tween_finished.bind(node, anim), CONNECT_ONE_SHOT) + +static func stop(node: CanvasItem, anim: TweenFX.Animations) -> void: + if not _active.has(node) or not _active[node].has(anim): + return + _active[node][anim].kill() + _active[node].erase(anim) + if _active[node].is_empty(): + _active.erase(node) + +static func stop_all(node: CanvasItem) -> void: + if not _active.has(node): + return + for tween in _active[node].values(): + tween.kill() + _active.erase(node) + +static func is_playing(node: CanvasItem, anim: TweenFX.Animations) -> bool: + return _active.has(node) and _active[node].has(anim) + +static func _on_tween_finished(node: CanvasItem, anim: TweenFX.Animations) -> void: + if not _active.has(node): + return + _active[node].erase(anim) + if _active[node].is_empty(): + _active.erase(node) + +static func _on_node_exiting(node: CanvasItem) -> void: + _active.erase(node) diff --git a/addons/TweenFX/TweenManager.gd.uid b/addons/TweenFX/TweenManager.gd.uid new file mode 100644 index 0000000..d1a6a86 --- /dev/null +++ b/addons/TweenFX/TweenManager.gd.uid @@ -0,0 +1 @@ +uid://bc8i1qm1d8hrv diff --git a/addons/TweenFX/icon.png b/addons/TweenFX/icon.png new file mode 100644 index 0000000..f24cdb8 Binary files /dev/null and b/addons/TweenFX/icon.png differ diff --git a/addons/TweenFX/icon.png.import b/addons/TweenFX/icon.png.import new file mode 100644 index 0000000..919c393 --- /dev/null +++ b/addons/TweenFX/icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://chf2ss61jydw3" +path="res://.godot/imported/icon.png-1df28cd6ae5654ad60ac96bf24b7c782.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/TweenFX/icon.png" +dest_files=["res://.godot/imported/icon.png-1df28cd6ae5654ad60ac96bf24b7c782.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/TweenFX/plugin.cfg b/addons/TweenFX/plugin.cfg new file mode 100644 index 0000000..8a0edd8 --- /dev/null +++ b/addons/TweenFX/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] +name="TweenFX"+ +icon="res://addons/TweenFX/icon.png" +description= "A simple, juicy tween animation library for Godot" +author="EvilBunnyMan" +version="1.2" +script="plugin.gd" diff --git a/addons/TweenFX/plugin.gd b/addons/TweenFX/plugin.gd new file mode 100644 index 0000000..3e05128 --- /dev/null +++ b/addons/TweenFX/plugin.gd @@ -0,0 +1,10 @@ +@tool +extends EditorPlugin + +func _enable_plugin(): + add_autoload_singleton("TweenFX", "res://addons/TweenFX/TweenFX.gd") + print("[TweenFX] Enabled") + +func _disable_plugin(): + remove_autoload_singleton("TweenFX") + print("[TweenFX] Disabled") diff --git a/addons/TweenFX/plugin.gd.uid b/addons/TweenFX/plugin.gd.uid new file mode 100644 index 0000000..8523b4a --- /dev/null +++ b/addons/TweenFX/plugin.gd.uid @@ -0,0 +1 @@ +uid://wu3r36bvv8u diff --git a/core/game_menu/arrow_button.gd b/core/game_menu/arrow_button.gd index ee19c1f..96a47d9 100644 --- a/core/game_menu/arrow_button.gd +++ b/core/game_menu/arrow_button.gd @@ -1,10 +1,8 @@ @tool -extends Control +extends Button class_name ArrowButton -signal on_pressed - @export var image: Texture: set(value): image = value @@ -24,6 +22,18 @@ func _ready(): $%Texture.flip_h = flip_h -func _on_gui_input(event: InputEvent) -> void: - if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed: - on_pressed.emit() +func _on_pressed() -> void: + if TweenFX.is_playing(self, TweenFX.Animations.PUNCH_IN): + return + TweenFX.punch_in(self) + + +func _on_mouse_entered() -> void: + if TweenFX.is_playing(self, TweenFX.Animations.BREATHE): + return + TweenFX.breathe(self, 1) + + +func _on_mouse_exited() -> void: + TweenFX.stop(self, TweenFX.Animations.BREATHE) + scale = Vector2(1, 1) diff --git a/core/game_menu/arrow_button.tscn b/core/game_menu/arrow_button.tscn index cb46358..d843c36 100644 --- a/core/game_menu/arrow_button.tscn +++ b/core/game_menu/arrow_button.tscn @@ -2,37 +2,44 @@ [ext_resource type="Texture2D" uid="uid://cm7fok7lhrano" path="res://core/game_menu/assets/page_1/freccetta.png" id="1_vbu0v"] [ext_resource type="Script" uid="uid://3uxuhvua1036" path="res://core/game_menu/arrow_button.gd" id="2_xq7pl"] -[ext_resource type="PackedScene" uid="uid://dxun0jk5t0n6" path="res://core/game_menu/hoover_tween.tscn" id="3_hu4cn"] -[node name="ArrowButton" type="Control" unique_id=1696751730] +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_xq7pl"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_hu4cn"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_fttf3"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_05bm2"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_kc324"] + +[node name="ArrowButton" type="Button" unique_id=579258112] custom_minimum_size = Vector2(101, 124) -layout_mode = 3 +anchors_preset = -1 +anchor_right = 0.052604165 +anchor_bottom = 0.11481482 +pivot_offset_ratio = Vector2(0.5, 0.5) +theme_override_styles/normal = SubResource("StyleBoxEmpty_xq7pl") +theme_override_styles/pressed = SubResource("StyleBoxEmpty_hu4cn") +theme_override_styles/hover = SubResource("StyleBoxEmpty_fttf3") +theme_override_styles/disabled = SubResource("StyleBoxEmpty_05bm2") +theme_override_styles/focus = SubResource("StyleBoxEmpty_kc324") +script = ExtResource("2_xq7pl") +image = ExtResource("1_vbu0v") +metadata/_edit_use_anchors_ = true + +[node name="Texture" type="TextureRect" parent="." unique_id=91599097] +unique_name_in_owner = true +layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -pivot_offset = Vector2(0.5, 0.5) -script = ExtResource("2_xq7pl") -image = ExtResource("1_vbu0v") - -[node name="Texture" type="TextureRect" parent="." unique_id=91599097] -unique_name_in_owner = true -layout_mode = 1 -anchors_preset = -1 -anchor_left = 0.47369793 -anchor_top = 0.4425926 -anchor_right = 0.5263021 -anchor_bottom = 0.5574074 -grow_horizontal = 2 -grow_vertical = 2 pivot_offset_ratio = Vector2(0.5, 0.5) mouse_filter = 2 texture = ExtResource("1_vbu0v") -metadata/_edit_use_anchors_ = true -[node name="HooverTween" parent="." unique_id=2115829120 node_paths=PackedStringArray("detector_node", "visual_node") instance=ExtResource("3_hu4cn")] -detector_node = NodePath("..") -visual_node = NodePath("../Texture") - -[connection signal="gui_input" from="." to="." method="_on_gui_input"] +[connection signal="mouse_entered" from="." to="." method="_on_mouse_entered"] +[connection signal="mouse_exited" from="." to="." method="_on_mouse_exited"] +[connection signal="pressed" from="." to="." method="_on_pressed"] diff --git a/core/game_menu/audio_option.tscn b/core/game_menu/audio_option.tscn index e3a3953..c6140cd 100644 --- a/core/game_menu/audio_option.tscn +++ b/core/game_menu/audio_option.tscn @@ -32,6 +32,7 @@ texture = ExtResource("2_vudub") stretch_mode = 5 [node name="HSlider" type="HSlider" parent="." unique_id=1286896253] +process_mode = 3 layout_mode = 2 theme_override_icons/grabber = ExtResource("3_vf41c") theme_override_icons/grabber_highlight = ExtResource("3_vf41c") diff --git a/core/game_menu/biome_picker.gd b/core/game_menu/biome_picker.gd index 1a9c42f..a6abcd4 100644 --- a/core/game_menu/biome_picker.gd +++ b/core/game_menu/biome_picker.gd @@ -1,5 +1,5 @@ @tool -extends Control +extends Button @export var locked: bool = true @export var image: Texture: @@ -13,10 +13,16 @@ extends Control func _ready(): if image != null and has_node("%Texture"): $%Texture.texture = image - if has_node("%TextureRect") and has_node("%HooverTween"): + if has_node("%TextureRect"): if locked: $%TextureRect.show() - $%HooverTween.queue_free() else: $%TextureRect.hide() + TweenFX.breathe(self, 1) + + +func _on_pressed() -> void: + if TweenFX.is_playing(self, TweenFX.Animations.PRESS_ROTATE): + return + TweenFX.press_rotate(self) diff --git a/core/game_menu/biome_picker.tscn b/core/game_menu/biome_picker.tscn index 9f0752d..100bfb5 100644 --- a/core/game_menu/biome_picker.tscn +++ b/core/game_menu/biome_picker.tscn @@ -1,51 +1,82 @@ [gd_scene format=3 uid="uid://wckwvvnk8bt4"] [ext_resource type="Script" uid="uid://c7q3d823b1v1h" path="res://core/game_menu/biome_picker.gd" id="1_jqji0"] +[ext_resource type="Texture2D" uid="uid://dc0sl04wem136" path="res://core/game_menu/assets/page_1/color_main_biome.png" id="2_8s4h5"] [ext_resource type="Texture2D" uid="uid://dj6pt25w5i4jq" path="res://core/game_menu/assets/page_1/lucchetto.png" id="2_jqji0"] -[ext_resource type="PackedScene" uid="uid://dxun0jk5t0n6" path="res://core/game_menu/hoover_tween.tscn" id="4_8s4h5"] -[node name="BiomePicker" type="Control" unique_id=52821564] -layout_mode = 3 +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_jqji0"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_8s4h5"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ntcky"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_aj0ly"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_sqe3j"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_0slqm"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_idpud"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_7dp31"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_le5rt"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_rs8ck"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_6gubq"] + +[node name="BiomePicker" type="Button" unique_id=913478047] +custom_minimum_size = Vector2(161, 343) +anchors_preset = -1 +anchor_right = 0.08385417 +anchor_bottom = 0.3175926 +offset_right = -153.0 +offset_bottom = -335.0 +pivot_offset_ratio = Vector2(0.5, 0.5) +theme_override_styles/normal = SubResource("StyleBoxEmpty_jqji0") +theme_override_styles/normal_mirrored = SubResource("StyleBoxEmpty_8s4h5") +theme_override_styles/pressed = SubResource("StyleBoxEmpty_ntcky") +theme_override_styles/pressed_mirrored = SubResource("StyleBoxEmpty_aj0ly") +theme_override_styles/hover = SubResource("StyleBoxEmpty_sqe3j") +theme_override_styles/hover_mirrored = SubResource("StyleBoxEmpty_0slqm") +theme_override_styles/hover_pressed = SubResource("StyleBoxEmpty_idpud") +theme_override_styles/hover_pressed_mirrored = SubResource("StyleBoxEmpty_7dp31") +theme_override_styles/disabled = SubResource("StyleBoxEmpty_le5rt") +theme_override_styles/disabled_mirrored = SubResource("StyleBoxEmpty_rs8ck") +theme_override_styles/focus = SubResource("StyleBoxEmpty_6gubq") +script = ExtResource("1_jqji0") +image = ExtResource("2_8s4h5") +metadata/_edit_use_anchors_ = true + +[node name="Texture" type="TextureRect" parent="." unique_id=606844933] +unique_name_in_owner = true +custom_minimum_size = Vector2(161, 343) +layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -script = ExtResource("1_jqji0") - -[node name="Texture" type="TextureRect" parent="." unique_id=606844933] -unique_name_in_owner = true -layout_mode = 1 -anchors_preset = -1 -anchor_left = 0.47161457 -anchor_top = 0.39027777 -anchor_right = 0.5283854 -anchor_bottom = 0.6097222 -grow_horizontal = 2 -grow_vertical = 2 pivot_offset_ratio = Vector2(0.5, 0.5) +texture = ExtResource("2_8s4h5") stretch_mode = 3 -metadata/_edit_use_anchors_ = true [node name="TextureRect" type="TextureRect" parent="Texture" unique_id=288045010] unique_name_in_owner = true layout_mode = 1 -anchors_preset = 8 -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -offset_left = -20.0 -offset_top = -20.0 -offset_right = 20.0 -offset_bottom = 20.0 +anchors_preset = -1 +anchor_left = 0.36645964 +anchor_top = 0.41690964 +anchor_right = 0.6335404 +anchor_bottom = 0.58309036 +offset_left = 1.5 +offset_top = 8.5 +offset_right = -1.5 +offset_bottom = -8.5 grow_horizontal = 2 grow_vertical = 2 mouse_filter = 2 texture = ExtResource("2_jqji0") -[node name="HooverTween" parent="." unique_id=160227524 node_paths=PackedStringArray("detector_node", "visual_node") instance=ExtResource("4_8s4h5")] -unique_name_in_owner = true -detector_node = NodePath("..") -visual_node = NodePath("../Texture") -scale_amount = Vector2(1.05, 1.05) +[connection signal="pressed" from="." to="." method="_on_pressed"] diff --git a/core/game_menu/biome_selector.tscn b/core/game_menu/biome_selector.tscn index 40c1288..e6936ad 100644 --- a/core/game_menu/biome_selector.tscn +++ b/core/game_menu/biome_selector.tscn @@ -1,56 +1,60 @@ [gd_scene format=3 uid="uid://bc60gon7fmvbr"] [ext_resource type="PackedScene" uid="uid://dm3skv22c60tm" path="res://core/game_menu/arrow_button.tscn" id="1_16l2d"] +[ext_resource type="Texture2D" uid="uid://dqqnfnero7ckl" path="res://core/game_menu/assets/page_1/chooseyourbiome_text.png" id="1_wyms5"] [ext_resource type="PackedScene" uid="uid://wckwvvnk8bt4" path="res://core/game_menu/biome_picker.tscn" id="2_q1k23"] [ext_resource type="Texture2D" uid="uid://cin3kt42e6w3u" path="res://core/game_menu/assets/page_1/color_sx_biome.png" id="2_xjika"] -[ext_resource type="Texture2D" uid="uid://dc0sl04wem136" path="res://core/game_menu/assets/page_1/color_main_biome.png" id="3_0noye"] [ext_resource type="Texture2D" uid="uid://c3qcivnwuisju" path="res://core/game_menu/assets/page_1/color_dx_biome.png" id="4_0noye"] +[ext_resource type="PackedScene" uid="uid://dxun0jk5t0n6" path="res://core/tween/container_tween.tscn" id="6_hjy5b"] -[node name="BiomeSelector" type="HBoxContainer" unique_id=291322067] -offset_right = 700.0 -offset_bottom = 400.0 +[node name="VBoxContainer" type="VBoxContainer" unique_id=1692688717] +offset_right = 685.0 +offset_bottom = 418.0 + +[node name="ChooseYourBiomeTexture" type="TextureRect" parent="." unique_id=1769445385] +layout_mode = 2 +texture = ExtResource("1_wyms5") +stretch_mode = 3 + +[node name="Spacer" type="Control" parent="." unique_id=1648681786] +custom_minimum_size = Vector2(0, 30) +layout_mode = 2 + +[node name="BiomeSelector" type="HBoxContainer" parent="." unique_id=291322067] +layout_mode = 2 theme_override_constants/separation = 0 alignment = 1 -[node name="ArrowButtonLeft" parent="." unique_id=1696751730 instance=ExtResource("1_16l2d")] +[node name="ArrowButtonLeft" parent="BiomeSelector" unique_id=1696751730 instance=ExtResource("1_16l2d")] layout_mode = 2 size_flags_vertical = 4 flip_h = true -[node name="HBoxContainer2" type="HBoxContainer" parent="." unique_id=1117886768] +[node name="HBoxContainer2" type="HBoxContainer" parent="BiomeSelector" unique_id=1117886768] layout_mode = 2 size_flags_horizontal = 3 theme_override_constants/separation = 0 alignment = 1 -[node name="BiomePicker1" parent="HBoxContainer2" unique_id=477354740 instance=ExtResource("2_q1k23")] +[node name="BiomePicker1" parent="BiomeSelector/HBoxContainer2" unique_id=477354740 instance=ExtResource("2_q1k23")] layout_mode = 2 size_flags_horizontal = 3 image = ExtResource("2_xjika") -[node name="BiomePicker2" parent="HBoxContainer2" unique_id=52821564 instance=ExtResource("2_q1k23")] -custom_minimum_size = Vector2(200, 400) +[node name="BiomePicker2" parent="BiomeSelector/HBoxContainer2" unique_id=52821564 instance=ExtResource("2_q1k23")] layout_mode = 2 size_flags_horizontal = 3 locked = false -image = ExtResource("3_0noye") -[node name="Texture" parent="HBoxContainer2/BiomePicker2" index="0" unique_id=606844933] -texture = ExtResource("3_0noye") - -[node name="TextureRect" parent="HBoxContainer2/BiomePicker2/Texture" index="0" unique_id=288045010] -visible = false - -[node name="HooverTween" parent="HBoxContainer2/BiomePicker2" index="1" unique_id=160227524] -always_active = true - -[node name="BiomePicker3" parent="HBoxContainer2" unique_id=1567545303 instance=ExtResource("2_q1k23")] +[node name="BiomePicker3" parent="BiomeSelector/HBoxContainer2" unique_id=1567545303 instance=ExtResource("2_q1k23")] layout_mode = 2 size_flags_horizontal = 3 image = ExtResource("4_0noye") -[node name="ArrowButtonRight" parent="." unique_id=1741162553 instance=ExtResource("1_16l2d")] +[node name="ArrowButtonRight" parent="BiomeSelector" unique_id=1741162553 instance=ExtResource("1_16l2d")] layout_mode = 2 size_flags_vertical = 4 -[editable path="HBoxContainer2/BiomePicker2"] +[node name="ContainerTween" parent="." unique_id=160227524 node_paths=PackedStringArray("targets") instance=ExtResource("6_hjy5b")] +unique_name_in_owner = true +targets = [NodePath("../BiomeSelector/ArrowButtonLeft"), NodePath("../BiomeSelector/HBoxContainer2/BiomePicker1"), NodePath("../BiomeSelector/HBoxContainer2/BiomePicker2"), NodePath("../BiomeSelector/HBoxContainer2/BiomePicker3"), NodePath("../BiomeSelector/ArrowButtonRight")] diff --git a/core/game_menu/collectible_gallery.tscn b/core/game_menu/collectible_gallery.tscn index d3fe77c..764b721 100644 --- a/core/game_menu/collectible_gallery.tscn +++ b/core/game_menu/collectible_gallery.tscn @@ -2,6 +2,7 @@ [ext_resource type="Script" uid="uid://dq3qtcrdnikl7" path="res://core/game_menu/collectible_gallery.gd" id="1_67tug"] [ext_resource type="PackedScene" uid="uid://dp7dvfauh5rpx" path="res://core/game_menu/collectible_ui.tscn" id="2_or234"] +[ext_resource type="PackedScene" uid="uid://dxun0jk5t0n6" path="res://core/tween/container_tween.tscn" id="3_cvqb8"] [node name="CollectibleGallery" type="Control" unique_id=354419843] layout_mode = 3 @@ -46,3 +47,6 @@ layout_mode = 2 [node name="CollectibleUI6" parent="ScrollContainer/CollectibleGrid" unique_id=1566830281 instance=ExtResource("2_or234")] layout_mode = 2 + +[node name="ContainerTween" parent="." unique_id=160227524 node_paths=PackedStringArray("runtime_target_parent") instance=ExtResource("3_cvqb8")] +runtime_target_parent = NodePath("../ScrollContainer/CollectibleGrid") diff --git a/core/game_menu/color_picker.gd b/core/game_menu/color_picker.gd index 78481a2..7de5759 100644 --- a/core/game_menu/color_picker.gd +++ b/core/game_menu/color_picker.gd @@ -1,10 +1,8 @@ @tool -extends Control +extends Button class_name TrainColorPicker -signal on_color_selected(color_picker: TrainColorPicker) - @export var image: Texture: set(value): image = value @@ -23,18 +21,31 @@ func _ready(): color = img.get_pixel(0, 0) else: color = Color.BLACK - - -func _on_gui_input(event: InputEvent) -> void: - if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed: - on_color_selected.emit(self) + $%Border.color.a = 0 func select() -> void: + if selected: + return selected = true $%Border.color.a = 1 + TweenFX.press_rotate(self) func deselect() -> void: + if !selected: + return selected = false $%Border.color.a = 0 + + +func _on_mouse_entered() -> void: + if TweenFX.is_playing(self, TweenFX.Animations.BREATHE): + return + TweenFX.breathe(self, 1) + + +func _on_mouse_exited() -> void: + TweenFX.stop(self, TweenFX.Animations.BREATHE) + scale = Vector2(1, 1) + diff --git a/core/game_menu/color_picker.tscn b/core/game_menu/color_picker.tscn index ac772ff..3abdb12 100644 --- a/core/game_menu/color_picker.tscn +++ b/core/game_menu/color_picker.tscn @@ -2,56 +2,74 @@ [ext_resource type="Texture2D" uid="uid://cdjwvwst3f10a" path="res://core/game_menu/assets/page_1/customizecolor-1.png" id="1_us0rx"] [ext_resource type="Script" uid="uid://crfw5whcjs0du" path="res://core/game_menu/color_picker.gd" id="2_323rd"] -[ext_resource type="PackedScene" uid="uid://dxun0jk5t0n6" path="res://core/game_menu/hoover_tween.tscn" id="3_264kt"] -[node name="ColorPicker" type="Control" unique_id=409505029] -custom_minimum_size = Vector2(53, 53) -layout_mode = 3 +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_323rd"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_264kt"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_1folt"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_tcqrg"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_kbu6n"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_dk0pr"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_f16cj"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_s4jbd"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_2ocph"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_5386i"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_6pmjh"] + +[node name="ColorPicker" type="Button" unique_id=1664685328] +custom_minimum_size = Vector2(60, 60) +anchors_preset = -1 +anchor_right = 0.03125 +anchor_bottom = 0.055555556 +pivot_offset_ratio = Vector2(0.5, 0.5) +theme_override_styles/normal = SubResource("StyleBoxEmpty_323rd") +theme_override_styles/normal_mirrored = SubResource("StyleBoxEmpty_264kt") +theme_override_styles/pressed = SubResource("StyleBoxEmpty_1folt") +theme_override_styles/pressed_mirrored = SubResource("StyleBoxEmpty_tcqrg") +theme_override_styles/hover = SubResource("StyleBoxEmpty_kbu6n") +theme_override_styles/hover_mirrored = SubResource("StyleBoxEmpty_dk0pr") +theme_override_styles/hover_pressed = SubResource("StyleBoxEmpty_f16cj") +theme_override_styles/hover_pressed_mirrored = SubResource("StyleBoxEmpty_s4jbd") +theme_override_styles/disabled = SubResource("StyleBoxEmpty_2ocph") +theme_override_styles/disabled_mirrored = SubResource("StyleBoxEmpty_5386i") +theme_override_styles/focus = SubResource("StyleBoxEmpty_6pmjh") +script = ExtResource("2_323rd") +image = ExtResource("1_us0rx") +metadata/_edit_use_anchors_ = true + +[node name="Border" type="ColorRect" parent="." unique_id=1774696864] +unique_name_in_owner = true +layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -script = ExtResource("2_323rd") -image = ExtResource("1_us0rx") - -[node name="Border" type="ColorRect" parent="." unique_id=1774696864] -unique_name_in_owner = true -layout_mode = 1 -anchors_preset = 8 -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -offset_left = -30.0 -offset_top = -30.0 -offset_right = 30.0 -offset_bottom = 30.0 -grow_horizontal = 2 -grow_vertical = 2 -pivot_offset_ratio = Vector2(0.5, 0.5) mouse_filter = 2 [node name="Texture" type="TextureRect" parent="Border" unique_id=329703623] unique_name_in_owner = true layout_mode = 1 -anchors_preset = 8 -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -offset_left = -26.5 -offset_top = -26.5 -offset_right = 26.5 -offset_bottom = 26.5 +anchors_preset = -1 +anchor_left = 0.058333334 +anchor_top = 0.058333334 +anchor_right = 0.94166666 +anchor_bottom = 0.94166666 grow_horizontal = 2 grow_vertical = 2 -pivot_offset_ratio = Vector2(0.5, 0.5) mouse_filter = 2 texture = ExtResource("1_us0rx") +metadata/_edit_use_anchors_ = true -[node name="HooverTween" parent="." unique_id=160227524 node_paths=PackedStringArray("detector_node", "visual_node") instance=ExtResource("3_264kt")] -detector_node = NodePath("..") -visual_node = NodePath("../Border") - -[connection signal="gui_input" from="." to="." method="_on_gui_input"] +[connection signal="mouse_entered" from="." to="." method="_on_mouse_entered"] +[connection signal="mouse_exited" from="." to="." method="_on_mouse_exited"] +[connection signal="pressed" from="." to="." method="_on_pressed"] diff --git a/core/game_menu/game_menu.gd b/core/game_menu/game_menu.gd index e3e47af..34b9df0 100644 --- a/core/game_menu/game_menu.gd +++ b/core/game_menu/game_menu.gd @@ -1,7 +1,8 @@ extends Control @onready var tabs: Array[GameMenuTab] = [$%Tab1, $%Tab2, $%Tab3] -@onready var pages: Array[Control] = [$%Page1, $%Page2, $%Page3] +@onready var pages: Array[GameMenuPage] = [$%Page1, $%Page2, $%Page3] + func _ready() -> void: for tab: GameMenuTab in tabs: @@ -11,7 +12,7 @@ func _ready() -> void: func on_tab_pressed(index: int, disable_animation: bool = false) -> void: for page in pages: - page.hide() + page.hide_page() for tab in tabs: if tab.index == index: @@ -25,7 +26,4 @@ func on_tab_pressed(index: int, disable_animation: bool = false) -> void: else: tab.deselect() - pages[index].show() - -func _on_resume_button_on_button_pressed() -> void: - hide() + pages[index].show_page() diff --git a/core/game_menu/game_menu.tscn b/core/game_menu/game_menu.tscn index 1f94771..c4c3faa 100644 --- a/core/game_menu/game_menu.tscn +++ b/core/game_menu/game_menu.tscn @@ -17,17 +17,10 @@ anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 +pivot_offset_ratio = Vector2(0.5, 0.5) mouse_filter = 2 script = ExtResource("1_57vaj") -[node name="Panel" type="Panel" parent="." unique_id=992567199] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 - [node name="Tabs" type="HBoxContainer" parent="." unique_id=1745270897] layout_mode = 1 offset_left = 1138.0 @@ -84,7 +77,5 @@ unique_name_in_owner = true visible = false layout_mode = 1 -[connection signal="on_button_pressed" from="Pages/Page3/OptionMenu/VBoxContainer/ResumeButton" to="." method="_on_resume_button_on_button_pressed"] - [editable path="Pages/Page3"] [editable path="Pages/Page3/OptionMenu"] diff --git a/core/game_menu/game_menu_tab.gd b/core/game_menu/game_menu_tab.gd index b1b8dd2..0f6de57 100644 --- a/core/game_menu/game_menu_tab.gd +++ b/core/game_menu/game_menu_tab.gd @@ -25,6 +25,8 @@ func _ready(): func _on_gui_input(event: InputEvent) -> void: if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed: + if is_selected: + return on_tab_selected.emit(index) func select(): diff --git a/core/game_menu/highlighted_photo.gd b/core/game_menu/highlighted_photo.gd index ac75b98..11d1258 100644 --- a/core/game_menu/highlighted_photo.gd +++ b/core/game_menu/highlighted_photo.gd @@ -3,16 +3,21 @@ extends Control @onready var photo: Photo = $%Photo @onready var panel: Panel = $%Panel + + func _ready() -> void: GameState.on_photo_highlighted.connect(_on_photo_highlighted) func _on_photo_highlighted(texture: Texture) -> void: if texture != photo.texture_rect.texture: show() + photo.scale = Vector2.ONE + TweenFX.fold_in(photo) photo.setup(texture) func _on_panel_gui_input(event: InputEvent) -> void: if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed: + await TweenFX.fold_out(photo).finished photo.texture_rect.texture = null hide() diff --git a/core/game_menu/highlighted_photo.tscn b/core/game_menu/highlighted_photo.tscn index 6a8a9ce..7deb519 100644 --- a/core/game_menu/highlighted_photo.tscn +++ b/core/game_menu/highlighted_photo.tscn @@ -24,20 +24,14 @@ grow_vertical = 2 [node name="Photo" parent="." unique_id=201865221 instance=ExtResource("1_x7ou0")] unique_name_in_owner = true layout_mode = 1 -anchors_preset = -1 anchor_left = 0.3625 anchor_top = 0.14351852 anchor_right = 0.6375 anchor_bottom = 0.8564815 mouse_filter = 2 -metadata/_edit_use_anchors_ = true [node name="ColorRect" parent="Photo" index="0" unique_id=1208008621] anchors_preset = 15 -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 1.0 -anchor_bottom = 1.0 offset_left = 0.0 offset_top = 0.0 offset_right = 0.0 diff --git a/core/game_menu/hoover_tween.gd b/core/game_menu/hoover_tween.gd deleted file mode 100644 index 61449c9..0000000 --- a/core/game_menu/hoover_tween.gd +++ /dev/null @@ -1,44 +0,0 @@ -extends Node - - -@export_group("Settings") -@export var always_active: bool = false -@export var detector_node: Control -@export var visual_node: Control -@export var scale_amount: Vector2 = Vector2(1.1, 1.1) -@export var duration: float = 0.5 - -var hover_tween: Tween - -func _ready(): - if not detector_node or not visual_node: - return - - if always_active: - _start_tween() - return - - detector_node.mouse_entered.connect(_on_mouse_entered) - detector_node.mouse_exited.connect(_on_mouse_exited) - - -func _on_mouse_entered(): - if hover_tween: hover_tween.kill() - - _start_tween() - -func _on_mouse_exited(): - if hover_tween: hover_tween.kill() - - _stop_tween() - - -func _start_tween() -> void: - hover_tween = create_tween().set_loops() - hover_tween.tween_property(visual_node, "scale", scale_amount, duration).set_trans(Tween.TRANS_SINE) - hover_tween.tween_property(visual_node, "scale", Vector2.ONE, duration).set_trans(Tween.TRANS_SINE) - -func _stop_tween() -> void: - var exit_tween = create_tween() - exit_tween.tween_property(visual_node, "scale", Vector2.ONE, 0.2).set_trans(Tween.TRANS_QUAD) - diff --git a/core/game_menu/hoover_tween.tscn b/core/game_menu/hoover_tween.tscn deleted file mode 100644 index 4abaa61..0000000 --- a/core/game_menu/hoover_tween.tscn +++ /dev/null @@ -1,6 +0,0 @@ -[gd_scene format=3 uid="uid://dxun0jk5t0n6"] - -[ext_resource type="Script" uid="uid://ryxh3nm7ayvf" path="res://core/game_menu/hoover_tween.gd" id="1_gmaf4"] - -[node name="HooverTween" type="Node" unique_id=160227524] -script = ExtResource("1_gmaf4") diff --git a/core/game_menu/option_menu.gd b/core/game_menu/option_menu.gd index 23bf26c..83ffeb1 100644 --- a/core/game_menu/option_menu.gd +++ b/core/game_menu/option_menu.gd @@ -1,16 +1,31 @@ extends Control -@onready var play_button: Control = $%PlayButton -@onready var resume_button: Control = $%ResumeButton +@onready var play_button: Button = $%PlayButton +@onready var resume_button: Button = $%ResumeButton +@onready var settings_button: Button = $%SettingsButton +@onready var save_button: Button = $%SaveButton +@onready var quit_button: Button = $%QuitButton +@onready var show_container_tween: ContainerTween = $%ShowContainerTween +@onready var hide_container_tween: ContainerTween = $%HideContainerTween +func _ready() -> void: + play_button.pressed.connect(_on_play_button_pressed) + settings_button.pressed.connect(_on_settings_button_pressed) + save_button.pressed.connect(_on_save_button_pressed) + quit_button.pressed.connect(_on_quit_button_pressed) -func _on_resume_button_on_button_pressed() -> void: - GameState.resume_game() +func _on_play_button_pressed() -> void: + SceneManager.change_scene(SceneConfig.SceneName.GAME) - -func _on_save_button_on_button_pressed() -> void: +func _on_save_button_pressed() -> void: GameState.save_game() -func _on_quit_button_on_button_pressed() -> void: +func _on_quit_button_pressed() -> void: GameState.quit_game() + +func _on_settings_button_pressed() -> void: + if $%SettingsMenu.visible: + hide_container_tween.start_tween() + else: + show_container_tween.start_tween() diff --git a/core/game_menu/option_menu.tscn b/core/game_menu/option_menu.tscn index 88ee16a..556dee3 100644 --- a/core/game_menu/option_menu.tscn +++ b/core/game_menu/option_menu.tscn @@ -6,6 +6,7 @@ [ext_resource type="Texture2D" uid="uid://cmhx3mscwrwft" path="res://core/game_menu/assets/page_3/save_button.png" id="3_vwpol"] [ext_resource type="Texture2D" uid="uid://cu8e7pl0y4owq" path="res://core/game_menu/assets/page_3/settings_button.png" id="4_8w45m"] [ext_resource type="Texture2D" uid="uid://v7e7467fkdec" path="res://core/game_menu/assets/page_3/quit_button.png" id="4_cd2sv"] +[ext_resource type="PackedScene" uid="uid://dxun0jk5t0n6" path="res://core/tween/container_tween.tscn" id="7_n7rb8"] [node name="OptionMenu" type="Control" unique_id=1055457221] layout_mode = 3 @@ -61,6 +62,5 @@ custom_minimum_size = Vector2(310, 100) layout_mode = 2 image = ExtResource("4_cd2sv") -[connection signal="on_button_pressed" from="VBoxContainer/ResumeButton" to="." method="_on_resume_button_on_button_pressed"] -[connection signal="on_button_pressed" from="VBoxContainer/SaveButton" to="." method="_on_save_button_on_button_pressed"] -[connection signal="on_button_pressed" from="VBoxContainer/QuitButton" to="." method="_on_quit_button_on_button_pressed"] +[node name="ContainerTween" parent="." unique_id=160227524 node_paths=PackedStringArray("targets") instance=ExtResource("7_n7rb8")] +targets = [NodePath("../VBoxContainer/PlayButton"), NodePath("../VBoxContainer/ResumeButton"), NodePath("../VBoxContainer/SettingsButton"), NodePath("../VBoxContainer/SaveButton"), NodePath("../VBoxContainer/QuitButton")] diff --git a/core/game_menu/option_menu_button.gd b/core/game_menu/option_menu_button.gd index 7dcf811..064df73 100644 --- a/core/game_menu/option_menu_button.gd +++ b/core/game_menu/option_menu_button.gd @@ -1,7 +1,5 @@ @tool -extends Control - -signal on_button_pressed +extends Button @export var image: Texture: set(value): @@ -13,6 +11,19 @@ func _ready(): if image != null and has_node("%Texture"): $%Texture.texture = image -func _on_gui_input(event: InputEvent) -> void: - if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed: - on_button_pressed.emit() + +func _on_pressed() -> void: + if TweenFX.is_playing(self, TweenFX.Animations.PUNCH_IN): + return + TweenFX.punch_in(self) + + +func _on_mouse_entered() -> void: + if TweenFX.is_playing(self, TweenFX.Animations.BREATHE): + return + TweenFX.breathe(self, 1) + + +func _on_mouse_exited() -> void: + TweenFX.stop(self, TweenFX.Animations.BREATHE) + scale = Vector2(1, 1) diff --git a/core/game_menu/option_menu_button.tscn b/core/game_menu/option_menu_button.tscn index 08bf5a9..0022b4a 100644 --- a/core/game_menu/option_menu_button.tscn +++ b/core/game_menu/option_menu_button.tscn @@ -2,17 +2,50 @@ [ext_resource type="Texture2D" uid="uid://b4nymq3n3468g" path="res://core/game_menu/assets/page_3/play_button.png" id="1_movd1"] [ext_resource type="Script" uid="uid://bbhe65f3517m8" path="res://core/game_menu/option_menu_button.gd" id="2_nghpi"] -[ext_resource type="PackedScene" uid="uid://dxun0jk5t0n6" path="res://core/game_menu/hoover_tween.tscn" id="3_am666"] -[node name="OptionMenuButton" type="Control" unique_id=635721927] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_nghpi"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_am666"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_nxt2x"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_r4tfe"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_1kmlt"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_51x11"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_8eh6p"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_w4k7x"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_wra0p"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_8dgkg"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ev2fk"] + +[node name="OptionMenuButton" type="Button" unique_id=600844315] +process_mode = 3 +custom_minimum_size = Vector2(302, 90) +anchors_preset = -1 +anchor_right = 0.15729167 +anchor_bottom = 0.083333336 +pivot_offset_ratio = Vector2(0.5, 0.5) +theme_override_styles/normal = SubResource("StyleBoxEmpty_nghpi") +theme_override_styles/normal_mirrored = SubResource("StyleBoxEmpty_am666") +theme_override_styles/pressed = SubResource("StyleBoxEmpty_nxt2x") +theme_override_styles/pressed_mirrored = SubResource("StyleBoxEmpty_r4tfe") +theme_override_styles/hover = SubResource("StyleBoxEmpty_1kmlt") +theme_override_styles/hover_mirrored = SubResource("StyleBoxEmpty_51x11") +theme_override_styles/hover_pressed = SubResource("StyleBoxEmpty_8eh6p") +theme_override_styles/hover_pressed_mirrored = SubResource("StyleBoxEmpty_w4k7x") +theme_override_styles/disabled = SubResource("StyleBoxEmpty_wra0p") +theme_override_styles/disabled_mirrored = SubResource("StyleBoxEmpty_8dgkg") +theme_override_styles/focus = SubResource("StyleBoxEmpty_ev2fk") script = ExtResource("2_nghpi") image = ExtResource("1_movd1") +metadata/_edit_use_anchors_ = true [node name="Texture" type="TextureRect" parent="." unique_id=1177880405] unique_name_in_owner = true @@ -29,8 +62,6 @@ mouse_filter = 2 texture = ExtResource("1_movd1") metadata/_edit_use_anchors_ = true -[node name="HooverTween" parent="." unique_id=160227524 node_paths=PackedStringArray("detector_node", "visual_node") instance=ExtResource("3_am666")] -detector_node = NodePath("..") -visual_node = NodePath("../Texture") - -[connection signal="gui_input" from="." to="." method="_on_gui_input"] +[connection signal="mouse_entered" from="." to="." method="_on_mouse_entered"] +[connection signal="mouse_exited" from="." to="." method="_on_mouse_exited"] +[connection signal="pressed" from="." to="." method="_on_pressed"] diff --git a/core/game_menu/page.gd b/core/game_menu/page.gd new file mode 100644 index 0000000..a6b83a5 --- /dev/null +++ b/core/game_menu/page.gd @@ -0,0 +1,14 @@ +extends Control + +class_name GameMenuPage + + +func show_page() -> void: + var tweens = find_children("*", "ContainerTween", true, false) + for tween in tweens: + tween.start_tween() + show() + + +func hide_page() -> void: + hide() diff --git a/core/game_menu/page.gd.uid b/core/game_menu/page.gd.uid new file mode 100644 index 0000000..12b9da8 --- /dev/null +++ b/core/game_menu/page.gd.uid @@ -0,0 +1 @@ +uid://dup0tdvb3eghp diff --git a/core/game_menu/page.tscn b/core/game_menu/page.tscn index 4f5522c..f0e8f83 100644 --- a/core/game_menu/page.tscn +++ b/core/game_menu/page.tscn @@ -1,5 +1,6 @@ [gd_scene format=3 uid="uid://id854u4gh12f"] +[ext_resource type="Script" uid="uid://dup0tdvb3eghp" path="res://core/game_menu/page.gd" id="1_21t5y"] [ext_resource type="Texture2D" uid="uid://bs56pdbywm4uh" path="res://core/game_menu/assets/page_1/quad_main.png" id="1_jwl25"] [node name="Page" type="Control" unique_id=2037261222] @@ -7,6 +8,7 @@ layout_mode = 3 anchors_preset = 0 offset_right = 40.0 offset_bottom = 40.0 +script = ExtResource("1_21t5y") [node name="Background" type="TextureRect" parent="." unique_id=1203110384] visible = false diff --git a/core/game_menu/page_1.tscn b/core/game_menu/page_1.tscn index 5b3b698..60b0a32 100644 --- a/core/game_menu/page_1.tscn +++ b/core/game_menu/page_1.tscn @@ -2,8 +2,6 @@ [ext_resource type="PackedScene" uid="uid://id854u4gh12f" path="res://core/game_menu/page.tscn" id="1_uxih6"] [ext_resource type="PackedScene" uid="uid://bh1kxsp5jyxfx" path="res://core/game_menu/train_selector.tscn" id="3_ijm38"] -[ext_resource type="Texture2D" uid="uid://bjqp8kmb5y7px" path="res://core/game_menu/assets/page_1/chooseyourtrain_text.png" id="3_t5hmd"] -[ext_resource type="Texture2D" uid="uid://dqqnfnero7ckl" path="res://core/game_menu/assets/page_1/chooseyourbiome_text.png" id="11_3chbu"] [ext_resource type="PackedScene" uid="uid://bc60gon7fmvbr" path="res://core/game_menu/biome_selector.tscn" id="12_7yi8x"] [node name="Page1" unique_id=2037261222 instance=ExtResource("1_uxih6")] @@ -16,33 +14,16 @@ grow_horizontal = 2 grow_vertical = 2 mouse_filter = 2 -[node name="ChooseyourtrainText" type="TextureRect" parent="." index="1" unique_id=1883940124] -layout_mode = 0 -offset_left = 350.0 -offset_top = 365.0 -offset_right = 758.0 -offset_bottom = 445.0 -texture = ExtResource("3_t5hmd") - -[node name="TrainSelector" parent="." index="2" unique_id=1039769375 instance=ExtResource("3_ijm38")] +[node name="TrainSelector" parent="." index="1" unique_id=1039769375 instance=ExtResource("3_ijm38")] layout_mode = 0 offset_left = 211.0 -offset_top = 469.0 -offset_right = 871.0 -offset_bottom = 778.0 - -[node name="ChooseyourbiomeText" type="TextureRect" parent="." index="3" unique_id=1133714914] -layout_mode = 0 -offset_left = 1184.0 offset_top = 365.0 -offset_right = 1579.0 -offset_bottom = 436.0 -texture = ExtResource("11_3chbu") -stretch_mode = 3 +offset_right = 871.0 +offset_bottom = 758.0 -[node name="BiomeSelector" parent="." index="4" unique_id=1957954960 instance=ExtResource("12_7yi8x")] +[node name="BiomeSelector" parent="." index="2" unique_id=1957954960 instance=ExtResource("12_7yi8x")] layout_mode = 0 offset_left = 1038.0 -offset_top = 437.0 +offset_top = 365.0 offset_right = 1738.0 -offset_bottom = 837.0 +offset_bottom = 783.0 diff --git a/core/game_menu/page_2.tscn b/core/game_menu/page_2.tscn index d3765dd..76e5faf 100644 --- a/core/game_menu/page_2.tscn +++ b/core/game_menu/page_2.tscn @@ -17,9 +17,6 @@ grow_horizontal = 2 grow_vertical = 2 mouse_filter = 2 -[node name="Background" parent="." index="0" unique_id=1203110384] -mouse_filter = 2 - [node name="PhotoCollectionText" type="TextureRect" parent="." index="1" unique_id=240014191] layout_mode = 0 offset_left = 350.0 @@ -43,7 +40,7 @@ layout_mode = 1 offset_left = 244.0 offset_top = 410.0 offset_right = 844.0 -offset_bottom = 810.0 +offset_bottom = 850.0 [node name="CollectibleGallery" parent="." index="4" unique_id=708445500 instance=ExtResource("5_w0bcg")] layout_mode = 1 diff --git a/core/game_menu/photo.gd b/core/game_menu/photo.gd index b1f48cd..ac83eba 100644 --- a/core/game_menu/photo.gd +++ b/core/game_menu/photo.gd @@ -1,4 +1,4 @@ -extends Control +extends Button class_name Photo @@ -11,6 +11,20 @@ func setup(texture: Texture) -> void: texture_rect.texture = texture -func _on_gui_input(event: InputEvent) -> void: - if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed: - GameState.on_photo_highlighted.emit(texture_rect.texture) +func _on_pressed() -> void: + if TweenFX.is_playing(self, TweenFX.Animations.PUNCH_IN): + return + TweenFX.punch_in(self) + GameState.on_photo_highlighted.emit(texture_rect.texture) + + + +func _on_mouse_entered() -> void: + if TweenFX.is_playing(self, TweenFX.Animations.BREATHE): + return + TweenFX.breathe(self, 1) + + +func _on_mouse_exited() -> void: + TweenFX.stop(self, TweenFX.Animations.BREATHE) + scale = Vector2(1, 1) diff --git a/core/game_menu/photo.tscn b/core/game_menu/photo.tscn index 0c07fd1..130b3e8 100644 --- a/core/game_menu/photo.tscn +++ b/core/game_menu/photo.tscn @@ -1,29 +1,26 @@ [gd_scene format=3 uid="uid://cvus62qkop3qi"] [ext_resource type="Script" uid="uid://dsey5dvc11vpq" path="res://core/game_menu/photo.gd" id="1_u0arp"] -[ext_resource type="PackedScene" uid="uid://dxun0jk5t0n6" path="res://core/game_menu/hoover_tween.tscn" id="2_62vvn"] -[node name="Photo" type="Control" unique_id=201865221] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 +[node name="Photo" type="Button" unique_id=1451980505] +custom_minimum_size = Vector2(132, 154) +anchors_preset = -1 +anchor_right = 0.06875 +anchor_bottom = 0.1425926 +pivot_offset_ratio = Vector2(0.5, 0.5) script = ExtResource("1_u0arp") +metadata/_edit_use_anchors_ = true [node name="ColorRect" type="ColorRect" parent="." unique_id=1208008621] custom_minimum_size = Vector2(132, 154) layout_mode = 1 anchors_preset = -1 -anchor_left = 0.465625 -anchor_top = 0.4287037 -anchor_right = 0.534375 -anchor_bottom = 0.5712963 -offset_left = 66.0 -offset_top = 77.0 -offset_right = -66.0 -offset_bottom = -77.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 127.462494 +offset_top = 143.02037 +offset_right = -127.4625 +offset_bottom = -143.02037 grow_horizontal = 2 grow_vertical = 2 pivot_offset_ratio = Vector2(0.5, 0.5) @@ -50,8 +47,6 @@ mouse_filter = 2 expand_mode = 1 stretch_mode = 6 -[node name="HooverTween" parent="." unique_id=160227524 node_paths=PackedStringArray("detector_node", "visual_node") instance=ExtResource("2_62vvn")] -detector_node = NodePath("..") -visual_node = NodePath("../ColorRect") - -[connection signal="gui_input" from="." to="." method="_on_gui_input"] +[connection signal="mouse_entered" from="." to="." method="_on_mouse_entered"] +[connection signal="mouse_exited" from="." to="." method="_on_mouse_exited"] +[connection signal="pressed" from="." to="." method="_on_pressed"] diff --git a/core/game_menu/photo_gallery.tscn b/core/game_menu/photo_gallery.tscn index 4f58395..15c353a 100644 --- a/core/game_menu/photo_gallery.tscn +++ b/core/game_menu/photo_gallery.tscn @@ -2,12 +2,13 @@ [ext_resource type="Script" uid="uid://k4iqrlkbjppl" path="res://core/game_menu/photo_gallery.gd" id="1_bp5uf"] [ext_resource type="PackedScene" uid="uid://cvus62qkop3qi" path="res://core/game_menu/photo.tscn" id="2_45wok"] +[ext_resource type="PackedScene" uid="uid://dxun0jk5t0n6" path="res://core/tween/container_tween.tscn" id="3_ht2y6"] [node name="PhotoGallery" type="Control" unique_id=354419843] layout_mode = 3 anchors_preset = 0 offset_right = 600.0 -offset_bottom = 420.0 +offset_bottom = 440.0 mouse_filter = 2 script = ExtResource("1_bp5uf") photo_scene = ExtResource("2_45wok") @@ -21,35 +22,40 @@ grow_horizontal = 2 grow_vertical = 2 draw_focus_border = true -[node name="PhotoGrid" type="GridContainer" parent="ScrollContainer" unique_id=1187865988] -unique_name_in_owner = true +[node name="MarginContainer" type="MarginContainer" parent="ScrollContainer" unique_id=934979837] layout_mode = 2 size_flags_horizontal = 6 size_flags_vertical = 6 +theme_override_constants/margin_left = 32 +theme_override_constants/margin_top = 32 +theme_override_constants/margin_right = 32 +theme_override_constants/margin_bottom = 33 + +[node name="PhotoGrid" type="GridContainer" parent="ScrollContainer/MarginContainer" unique_id=1187865988] +unique_name_in_owner = true +layout_mode = 2 theme_override_constants/h_separation = 44 theme_override_constants/v_separation = 54 columns = 3 -[node name="Photo" parent="ScrollContainer/PhotoGrid" unique_id=201865221 instance=ExtResource("2_45wok")] -custom_minimum_size = Vector2(132, 154) +[node name="Photo" parent="ScrollContainer/MarginContainer/PhotoGrid" unique_id=201865221 instance=ExtResource("2_45wok")] layout_mode = 2 -[node name="Photo2" parent="ScrollContainer/PhotoGrid" unique_id=427039285 instance=ExtResource("2_45wok")] -custom_minimum_size = Vector2(132, 154) +[node name="Photo2" parent="ScrollContainer/MarginContainer/PhotoGrid" unique_id=427039285 instance=ExtResource("2_45wok")] layout_mode = 2 -[node name="Photo3" parent="ScrollContainer/PhotoGrid" unique_id=800591401 instance=ExtResource("2_45wok")] -custom_minimum_size = Vector2(132, 154) +[node name="Photo3" parent="ScrollContainer/MarginContainer/PhotoGrid" unique_id=800591401 instance=ExtResource("2_45wok")] layout_mode = 2 -[node name="Photo4" parent="ScrollContainer/PhotoGrid" unique_id=1895298585 instance=ExtResource("2_45wok")] -custom_minimum_size = Vector2(132, 154) +[node name="Photo4" parent="ScrollContainer/MarginContainer/PhotoGrid" unique_id=1895298585 instance=ExtResource("2_45wok")] layout_mode = 2 -[node name="Photo5" parent="ScrollContainer/PhotoGrid" unique_id=2093353381 instance=ExtResource("2_45wok")] -custom_minimum_size = Vector2(132, 154) +[node name="Photo5" parent="ScrollContainer/MarginContainer/PhotoGrid" unique_id=2093353381 instance=ExtResource("2_45wok")] layout_mode = 2 -[node name="Photo6" parent="ScrollContainer/PhotoGrid" unique_id=316021755 instance=ExtResource("2_45wok")] -custom_minimum_size = Vector2(132, 154) +[node name="Photo6" parent="ScrollContainer/MarginContainer/PhotoGrid" unique_id=316021755 instance=ExtResource("2_45wok")] layout_mode = 2 + +[node name="ContainerTween" parent="." unique_id=160227524 node_paths=PackedStringArray("runtime_target_parent") instance=ExtResource("3_ht2y6")] +unique_name_in_owner = true +runtime_target_parent = NodePath("../ScrollContainer/MarginContainer/PhotoGrid") diff --git a/core/game_menu/settings_menu.tscn b/core/game_menu/settings_menu.tscn index 13f901e..decbdb9 100644 --- a/core/game_menu/settings_menu.tscn +++ b/core/game_menu/settings_menu.tscn @@ -4,20 +4,30 @@ [ext_resource type="PackedScene" uid="uid://cescrovsjlwke" path="res://core/game_menu/audio_option.tscn" id="1_hwcco"] [ext_resource type="Texture2D" uid="uid://0t00kjvrw206" path="res://core/game_menu/assets/page_3/music_volume_button.png" id="3_kgdba"] [ext_resource type="Texture2D" uid="uid://dvergpy6qgggn" path="res://core/game_menu/assets/page_3/sfx_volume_button.png" id="4_ugk4n"] +[ext_resource type="PackedScene" uid="uid://dxun0jk5t0n6" path="res://core/tween/container_tween.tscn" id="5_p0gqk"] [node name="SettingsMenu" type="Control" unique_id=1639777294] +custom_minimum_size = Vector2(327, 512) layout_mode = 3 -anchors_preset = 0 -offset_right = 600.0 -offset_bottom = 420.0 +anchor_right = 0.1703125 +anchor_bottom = 0.47407407 +offset_right = -327.0 +offset_bottom = -512.0 +pivot_offset_ratio = Vector2(0.5, 0.5) script = ExtResource("1_4lekq") +metadata/_edit_use_anchors_ = true [node name="AudioOptionsContainer" type="VBoxContainer" parent="." unique_id=743642398] unique_name_in_owner = true -layout_mode = 0 -offset_right = 327.0 -offset_bottom = 512.0 +custom_minimum_size = Vector2(327, 512) +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 theme_override_constants/separation = 12 +alignment = 1 [node name="MasterVolume_AudioOption" parent="AudioOptionsContainer" unique_id=1509773712 instance=ExtResource("1_hwcco")] layout_mode = 2 @@ -31,3 +41,6 @@ bus_name = &"Music" layout_mode = 2 image = ExtResource("4_ugk4n") bus_name = &"SFX" + +[node name="ContainerTween" parent="." unique_id=160227524 node_paths=PackedStringArray("targets") instance=ExtResource("5_p0gqk")] +targets = [NodePath("../AudioOptionsContainer/MasterVolume_AudioOption"), NodePath("../AudioOptionsContainer/MusicVolume_AudioOption"), NodePath("../AudioOptionsContainer/SFXVolume_AudioOption")] diff --git a/core/game_menu/train_selector.gd b/core/game_menu/train_selector.gd index 9812be8..56f3070 100644 --- a/core/game_menu/train_selector.gd +++ b/core/game_menu/train_selector.gd @@ -3,19 +3,20 @@ extends VBoxContainer @onready var color_pickers: Array[TrainColorPicker] = [$%ColorPicker1, $%ColorPicker2, $%ColorPicker3, $%ColorPicker4, $%ColorPicker5, $%ColorPicker6] @onready var left_arrow: ArrowButton = $%ArrowButtonLeft @onready var right_arrow: ArrowButton = $%ArrowButtonRight + var selected_color: Color var selected_color_index: int = 0 func _ready() -> void: for color_picker in color_pickers: - color_picker.on_color_selected.connect(_on_color_selected) + color_picker.pressed.connect(_on_color_selected.bind(color_picker)) color_picker.deselect() selected_color = color_pickers[0].color color_pickers[0].select() - left_arrow.on_pressed.connect(_select_prev_color) - right_arrow.on_pressed.connect(_select_next_color) + left_arrow.pressed.connect(_select_prev_color) + right_arrow.pressed.connect(_select_next_color) func _on_color_selected(selected_color_picker: TrainColorPicker) -> void: for i in range(color_pickers.size()): diff --git a/core/game_menu/train_selector.tscn b/core/game_menu/train_selector.tscn index 5eb27c6..7591d3c 100644 --- a/core/game_menu/train_selector.tscn +++ b/core/game_menu/train_selector.tscn @@ -2,6 +2,7 @@ [ext_resource type="Script" uid="uid://8k1msabobhks" path="res://core/game_menu/train_selector.gd" id="1_puip6"] [ext_resource type="Texture2D" uid="uid://cqvani6n2h3fw" path="res://core/game_menu/assets/page_1/train_texture.png" id="1_wfiis"] +[ext_resource type="Texture2D" uid="uid://bjqp8kmb5y7px" path="res://core/game_menu/assets/page_1/chooseyourtrain_text.png" id="2_cfvtr"] [ext_resource type="PackedScene" uid="uid://dm3skv22c60tm" path="res://core/game_menu/arrow_button.tscn" id="2_puip6"] [ext_resource type="PackedScene" uid="uid://ch1st1oryjoio" path="res://core/game_menu/color_picker.tscn" id="3_i2rs1"] [ext_resource type="Texture2D" uid="uid://b5arobd7gl4u4" path="res://core/game_menu/assets/page_1/customizecolor-3.png" id="4_cfvtr"] @@ -9,19 +10,31 @@ [ext_resource type="Texture2D" uid="uid://bv07xhpe3kh0r" path="res://core/game_menu/assets/page_1/customizecolor-5.png" id="6_dxnpq"] [ext_resource type="Texture2D" uid="uid://cryqbi1av2x1c" path="res://core/game_menu/assets/page_1/customizecolor.png" id="7_d1sdr"] [ext_resource type="Texture2D" uid="uid://d4l5ih723j3md" path="res://core/game_menu/assets/page_1/customizecolor-2.png" id="8_tuh6m"] +[ext_resource type="PackedScene" uid="uid://dxun0jk5t0n6" path="res://core/tween/container_tween.tscn" id="10_i2rs1"] [node name="TrainSelector" type="VBoxContainer" unique_id=1039769375] offset_right = 625.0 offset_bottom = 309.0 +alignment = 1 script = ExtResource("1_puip6") -[node name="TrainTexture" type="TextureRect" parent="." unique_id=2095010706] +[node name="ChooseYourTrainTexture" type="TextureRect" parent="." unique_id=2095010706] +layout_mode = 2 +texture = ExtResource("2_cfvtr") +stretch_mode = 3 + +[node name="Spacer" type="Control" parent="." unique_id=685700140] +custom_minimum_size = Vector2(0, 30) +layout_mode = 2 + +[node name="TrainTexture" type="TextureRect" parent="." unique_id=1674220600] layout_mode = 2 texture = ExtResource("1_wfiis") stretch_mode = 3 [node name="HBoxContainer2" type="HBoxContainer" parent="." unique_id=607833319] layout_mode = 2 +alignment = 1 [node name="ArrowButtonLeft" parent="HBoxContainer2" unique_id=103192648 instance=ExtResource("2_puip6")] unique_name_in_owner = true @@ -31,44 +44,39 @@ flip_h = true [node name="HBoxContainer" type="HBoxContainer" parent="HBoxContainer2" unique_id=1364417494] layout_mode = 2 theme_override_constants/separation = 18 +alignment = 1 [node name="ColorPicker1" parent="HBoxContainer2/HBoxContainer" unique_id=59169767 instance=ExtResource("3_i2rs1")] unique_name_in_owner = true -custom_minimum_size = Vector2(60, 60) layout_mode = 2 size_flags_vertical = 4 image = ExtResource("4_cfvtr") [node name="ColorPicker2" parent="HBoxContainer2/HBoxContainer" unique_id=584054476 instance=ExtResource("3_i2rs1")] unique_name_in_owner = true -custom_minimum_size = Vector2(60, 60) layout_mode = 2 size_flags_vertical = 4 image = ExtResource("5_jnto8") [node name="ColorPicker3" parent="HBoxContainer2/HBoxContainer" unique_id=889429149 instance=ExtResource("3_i2rs1")] unique_name_in_owner = true -custom_minimum_size = Vector2(60, 60) layout_mode = 2 size_flags_vertical = 4 image = ExtResource("6_dxnpq") [node name="ColorPicker4" parent="HBoxContainer2/HBoxContainer" unique_id=466686411 instance=ExtResource("3_i2rs1")] unique_name_in_owner = true -custom_minimum_size = Vector2(60, 60) layout_mode = 2 size_flags_vertical = 4 image = ExtResource("7_d1sdr") [node name="ColorPicker5" parent="HBoxContainer2/HBoxContainer" unique_id=675841518 instance=ExtResource("3_i2rs1")] unique_name_in_owner = true -custom_minimum_size = Vector2(60, 60) layout_mode = 2 size_flags_vertical = 4 [node name="ColorPicker6" parent="HBoxContainer2/HBoxContainer" unique_id=1698412911 instance=ExtResource("3_i2rs1")] unique_name_in_owner = true -custom_minimum_size = Vector2(60, 60) layout_mode = 2 size_flags_vertical = 4 image = ExtResource("8_tuh6m") @@ -76,3 +84,7 @@ image = ExtResource("8_tuh6m") [node name="ArrowButtonRight" parent="HBoxContainer2" unique_id=68298624 instance=ExtResource("2_puip6")] unique_name_in_owner = true layout_mode = 2 + +[node name="ContainerTween" parent="." unique_id=160227524 node_paths=PackedStringArray("targets") instance=ExtResource("10_i2rs1")] +unique_name_in_owner = true +targets = [NodePath("../HBoxContainer2/ArrowButtonLeft"), NodePath("../HBoxContainer2/HBoxContainer/ColorPicker1"), NodePath("../HBoxContainer2/HBoxContainer/ColorPicker2"), NodePath("../HBoxContainer2/HBoxContainer/ColorPicker3"), NodePath("../HBoxContainer2/HBoxContainer/ColorPicker4"), NodePath("../HBoxContainer2/HBoxContainer/ColorPicker5"), NodePath("../HBoxContainer2/HBoxContainer/ColorPicker6"), NodePath("../HBoxContainer2/ArrowButtonRight")] diff --git a/core/main_menu/main_menu.gd b/core/main_menu/main_menu.gd deleted file mode 100644 index 4a6611a..0000000 --- a/core/main_menu/main_menu.gd +++ /dev/null @@ -1,10 +0,0 @@ -extends Control - -@onready var settings_menu: Control = $%SettingsMenu - -func _on_play_button_on_button_pressed() -> void: - SceneManager.change_scene(SceneConfig.SceneName.GAME) - - -func _on_settings_button_on_button_pressed() -> void: - $%SettingsMenu.visible = !$%SettingsMenu.visible diff --git a/core/main_menu/main_menu.gd.uid b/core/main_menu/main_menu.gd.uid deleted file mode 100644 index 4851987..0000000 --- a/core/main_menu/main_menu.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://csqxuftsnv1br diff --git a/core/main_menu/main_menu.tscn b/core/main_menu/main_menu.tscn index df9ac6d..dcf4205 100644 --- a/core/main_menu/main_menu.tscn +++ b/core/main_menu/main_menu.tscn @@ -1,9 +1,9 @@ [gd_scene format=3 uid="uid://btcpge7cj2041"] -[ext_resource type="Script" uid="uid://csqxuftsnv1br" path="res://core/main_menu/main_menu.gd" id="1_g1whv"] [ext_resource type="PackedScene" uid="uid://cxf8s80ivwj1p" path="res://core/game_menu/option_menu.tscn" id="1_uvy4f"] [ext_resource type="Texture2D" uid="uid://buy4x63u237np" path="res://core/main_menu/assets/main_menu_background.png" id="2_mloc8"] [ext_resource type="PackedScene" uid="uid://caqf471x0kttc" path="res://core/game_menu/settings_menu.tscn" id="3_26agx"] +[ext_resource type="PackedScene" uid="uid://dxun0jk5t0n6" path="res://core/tween/container_tween.tscn" id="4_mloc8"] [node name="MainMenu" type="Control" unique_id=889720172] layout_mode = 3 @@ -12,7 +12,6 @@ anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -script = ExtResource("1_g1whv") [node name="TextureRect" type="TextureRect" parent="." unique_id=11805511] layout_mode = 1 @@ -25,15 +24,13 @@ texture = ExtResource("2_mloc8") [node name="OptionMenu" parent="." unique_id=1055457221 instance=ExtResource("1_uvy4f")] layout_mode = 1 -anchors_preset = 8 -anchor_left = 0.5 +anchors_preset = 6 +anchor_left = 1.0 anchor_top = 0.5 -anchor_right = 0.5 anchor_bottom = 0.5 -offset_left = 492.0 -offset_top = 274.0 -offset_right = 492.0 -offset_bottom = 274.0 +offset_left = -294.0 +offset_right = -294.0 +grow_horizontal = 0 [node name="VBoxContainer" parent="OptionMenu" index="0" unique_id=508055524] anchor_top = 0.3037037 @@ -51,12 +48,26 @@ visible = false unique_name_in_owner = true visible = false layout_mode = 1 -offset_left = 639.0 -offset_top = 566.0 -offset_right = 639.0 -offset_bottom = 566.0 +anchors_preset = 4 +anchor_top = 0.5 +anchor_right = 0.0 +anchor_bottom = 0.5 +offset_left = 225.0 +offset_top = -256.0 +offset_right = 552.0 +offset_bottom = 256.0 +grow_vertical = 2 -[connection signal="on_button_pressed" from="OptionMenu/VBoxContainer/PlayButton" to="." method="_on_play_button_on_button_pressed"] -[connection signal="on_button_pressed" from="OptionMenu/VBoxContainer/SettingsButton" to="." method="_on_settings_button_on_button_pressed"] +[node name="ShowContainerTween" parent="." unique_id=160227524 node_paths=PackedStringArray("targets") instance=ExtResource("4_mloc8")] +unique_name_in_owner = true +targets = [NodePath("../SettingsMenu")] +tween_types = Array[String](["fold_in"]) +show_on_start = true + +[node name="HideContainerTween" parent="." unique_id=570405239 node_paths=PackedStringArray("targets") instance=ExtResource("4_mloc8")] +unique_name_in_owner = true +targets = [NodePath("../SettingsMenu")] +tween_types = Array[String](["fold_out"]) +hide_on_finish = true [editable path="OptionMenu"] diff --git a/core/main_scene_ui/audio_player.gd b/core/main_scene_ui/audio_player.gd index 6259ef2..551a021 100644 --- a/core/main_scene_ui/audio_player.gd +++ b/core/main_scene_ui/audio_player.gd @@ -3,8 +3,18 @@ extends Control @export var radio: Radio @onready var track_label: Label = $%TrackLabel +@onready var prev_track_icon_button: Button = $%PrevTrackIconButton +@onready var play_pause_icon_button: Button = $%PlayPauseIconButton +@onready var next_track_icon_button: Button = $%NextTrackIconButton +@onready var increase_volume_icon_button: Button = $%IncreaseVolumeIconButton +@onready var decrease_volume_icon_button: Button = $%DecreaseVolumeIconButton func _ready() -> void: + prev_track_icon_button.pressed.connect(_on_prev_track_icon_button_pressed) + play_pause_icon_button.pressed.connect(_on_play_pause_icon_button_pressed) + next_track_icon_button.pressed.connect(_on_next_track_icon_button_pressed) + increase_volume_icon_button.pressed.connect(_on_increase_volume_icon_button_pressed) + decrease_volume_icon_button.pressed.connect(_on_decrease_volume_icon_button_pressed) if radio: radio.track_changed.connect(_on_radio_track_changed) if radio.stream and radio.stream.resource_path: @@ -15,29 +25,25 @@ func _ready() -> void: func _on_radio_track_changed(track_name: String) -> void: track_label.text = track_name -func _on_prev_track_icon_button_on_pressed() -> void: +func _on_prev_track_icon_button_pressed() -> void: if radio: radio.prev_track() - -func _on_play_pause_icon_button_on_pressed() -> void: +func _on_play_pause_icon_button_pressed() -> void: radio.toggle_pause() #if radio.stream_paused: #button_pause_resume.text = "Resume" #else: #button_pause_resume.text = "Pause" - -func _on_next_track_icon_button_on_pressed() -> void: +func _on_next_track_icon_button_pressed() -> void: if radio: radio.next_track() - -func _on_increase_volume_icon_button_on_pressed() -> void: +func _on_increase_volume_icon_button_pressed() -> void: var current_vol = AudioManager.get_audio_bus_volume("Music", 1.0) AudioManager.set_audio_bus_volume("Music", current_vol + 0.1) - -func _on_decrease_volume_icon_button_on_pressed() -> void: +func _on_decrease_volume_icon_button_pressed() -> void: var current_vol = AudioManager.get_audio_bus_volume("Music", 1.0) AudioManager.set_audio_bus_volume("Music", current_vol - 0.1) diff --git a/core/main_scene_ui/audio_player.tscn b/core/main_scene_ui/audio_player.tscn index 5aff572..7a2680a 100644 --- a/core/main_scene_ui/audio_player.tscn +++ b/core/main_scene_ui/audio_player.tscn @@ -89,6 +89,7 @@ layout_mode = 2 size_flags_vertical = 4 [node name="IncreaseVolumeIconButton" parent="HBoxContainer/VBoxContainer2" unique_id=1788399963 instance=ExtResource("1_ucnyb")] +unique_name_in_owner = true custom_minimum_size = Vector2(40, 40) layout_mode = 2 size_flags_horizontal = 0 @@ -106,6 +107,7 @@ offset_right = -96.666664 offset_bottom = -92.64813 [node name="DecreaseVolumeIconButton" parent="HBoxContainer/VBoxContainer2" unique_id=399629327 instance=ExtResource("1_ucnyb")] +unique_name_in_owner = true custom_minimum_size = Vector2(40, 40) layout_mode = 2 size_flags_horizontal = 0 @@ -122,12 +124,6 @@ offset_top = 92.64813 offset_right = -96.666664 offset_bottom = -92.64813 -[connection signal="on_pressed" from="HBoxContainer/VBoxContainer/IconButtonsRow/PrevTrackIconButton" to="." method="_on_prev_track_icon_button_on_pressed"] -[connection signal="on_pressed" from="HBoxContainer/VBoxContainer/IconButtonsRow/PlayPauseIconButton" to="." method="_on_play_pause_icon_button_on_pressed"] -[connection signal="on_pressed" from="HBoxContainer/VBoxContainer/IconButtonsRow/NextTrackIconButton" to="." method="_on_next_track_icon_button_on_pressed"] -[connection signal="on_pressed" from="HBoxContainer/VBoxContainer2/IncreaseVolumeIconButton" to="." method="_on_increase_volume_icon_button_on_pressed"] -[connection signal="on_pressed" from="HBoxContainer/VBoxContainer2/DecreaseVolumeIconButton" to="." method="_on_decrease_volume_icon_button_on_pressed"] - [editable path="HBoxContainer/VBoxContainer/IconButtonsRow/PrevTrackIconButton"] [editable path="HBoxContainer/VBoxContainer/IconButtonsRow/PlayPauseIconButton"] [editable path="HBoxContainer/VBoxContainer/IconButtonsRow/NextTrackIconButton"] diff --git a/core/main_scene_ui/icon_button.gd b/core/main_scene_ui/icon_button.gd index a64dfe0..ade9c95 100644 --- a/core/main_scene_ui/icon_button.gd +++ b/core/main_scene_ui/icon_button.gd @@ -1,9 +1,8 @@ @tool -extends Control +extends Button class_name IconButton -signal on_pressed @export var data: String @export var image: Texture: @@ -16,8 +15,20 @@ signal on_pressed func _ready(): if image != null and has_node("%Texture"): $%Texture.texture = image - -func _on_gui_input(event: InputEvent) -> void: - if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed: - on_pressed.emit() + + +func _on_mouse_entered() -> void: + if TweenFX.is_playing(self, TweenFX.Animations.BREATHE): + return + TweenFX.breathe(self, 1) + + +func _on_mouse_exited() -> void: + TweenFX.stop(self, TweenFX.Animations.BREATHE) + scale = Vector2(1, 1) + +func _on_pressed() -> void: + if TweenFX.is_playing(self, TweenFX.Animations.PRESS_ROTATE): + return + TweenFX.press_rotate(self) diff --git a/core/main_scene_ui/icon_button.tscn b/core/main_scene_ui/icon_button.tscn index 4ad70a6..0c0d5cb 100644 --- a/core/main_scene_ui/icon_button.tscn +++ b/core/main_scene_ui/icon_button.tscn @@ -3,34 +3,61 @@ [ext_resource type="Script" uid="uid://bpbgecvan0a5k" path="res://core/main_scene_ui/icon_button.gd" id="1_r8gxt"] [ext_resource type="Texture2D" uid="uid://dldg826x1kkoe" path="res://core/main_scene_ui/assets/weather_test.png" id="1_upldh"] -[node name="IconButton" type="Control" unique_id=1750448019] +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_r8gxt"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_6q6an"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_60w2f"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_4xtsh"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_305hl"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_jurvi"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_xxros"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_3kui7"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ogiom"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_4beq1"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_cxhgx"] + +[node name="IconButton" type="Button" unique_id=1621140689] custom_minimum_size = Vector2(160, 160) -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 +anchors_preset = -1 +anchor_right = 0.083333336 +anchor_bottom = 0.14814815 +pivot_offset_ratio = Vector2(0.5, 0.5) +theme_override_styles/normal = SubResource("StyleBoxEmpty_r8gxt") +theme_override_styles/normal_mirrored = SubResource("StyleBoxEmpty_6q6an") +theme_override_styles/pressed = SubResource("StyleBoxEmpty_60w2f") +theme_override_styles/pressed_mirrored = SubResource("StyleBoxEmpty_4xtsh") +theme_override_styles/hover = SubResource("StyleBoxEmpty_305hl") +theme_override_styles/hover_mirrored = SubResource("StyleBoxEmpty_jurvi") +theme_override_styles/hover_pressed = SubResource("StyleBoxEmpty_xxros") +theme_override_styles/hover_pressed_mirrored = SubResource("StyleBoxEmpty_3kui7") +theme_override_styles/disabled = SubResource("StyleBoxEmpty_ogiom") +theme_override_styles/disabled_mirrored = SubResource("StyleBoxEmpty_4beq1") +theme_override_styles/focus = SubResource("StyleBoxEmpty_cxhgx") script = ExtResource("1_r8gxt") image = ExtResource("1_upldh") +metadata/_edit_use_anchors_ = true [node name="Texture" type="TextureRect" parent="." unique_id=1071359322] unique_name_in_owner = true custom_minimum_size = Vector2(160, 160) layout_mode = 1 -anchors_preset = -1 -anchor_left = 0.45833334 -anchor_top = 0.42592594 -anchor_right = 0.5416667 -anchor_bottom = 0.5740741 -offset_left = 80.0 -offset_top = 79.99997 -offset_right = -80.0 -offset_bottom = -80.0 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 texture = ExtResource("1_upldh") expand_mode = 1 -metadata/_edit_use_anchors_ = true -[connection signal="gui_input" from="." to="." method="_on_gui_input"] +[connection signal="mouse_entered" from="." to="." method="_on_mouse_entered"] +[connection signal="mouse_exited" from="." to="." method="_on_mouse_exited"] +[connection signal="pressed" from="." to="." method="_on_pressed"] diff --git a/core/main_scene_ui/icon_buttons_row.gd b/core/main_scene_ui/icon_buttons_row.gd index 628c2a9..67f78f8 100644 --- a/core/main_scene_ui/icon_buttons_row.gd +++ b/core/main_scene_ui/icon_buttons_row.gd @@ -4,19 +4,23 @@ signal on_option_changed(data: String) @onready var current_icon_button: IconButton @onready var icon_buttons_options: Array[IconButton] +@onready var show_container_tween: ContainerTween = $%ShowContainerTween +@onready var hide_container_tween: ContainerTween = $%HideContainerTween var is_menu_open: bool = false func _ready() -> void: for i in range(get_child_count()): + if get_child(i) is not Control: + continue var icon_button: IconButton = get_child(i) if i == 0: current_icon_button = icon_button - icon_button.on_pressed.connect(on_current_icon_button_pressed) + icon_button.pressed.connect(on_current_icon_button_pressed) else: icon_buttons_options.append(icon_button) - icon_button.on_pressed.connect(_on_icon_pressed_changed.bind(icon_button)) + icon_button.pressed.connect(_on_icon_pressed_changed.bind(icon_button)) func _on_icon_pressed_changed(in_icon_button: IconButton): @@ -30,6 +34,9 @@ func _on_icon_pressed_changed(in_icon_button: IconButton): func on_current_icon_button_pressed() -> void: + if show_container_tween.is_running or hide_container_tween.is_running: + return + if is_menu_open: hide_options() else: @@ -37,12 +44,15 @@ func on_current_icon_button_pressed() -> void: func show_options() -> void: - for icon_button in icon_buttons_options: - icon_button.show() + #for icon_button in icon_buttons_options: + #icon_button.show() + show_container_tween.start_tween() is_menu_open = true func hide_options() -> void: - for icon_button in icon_buttons_options: - icon_button.hide() + #for icon_button in icon_buttons_options: + #icon_button.hide() + hide_container_tween.start_tween() + await hide_container_tween.finished is_menu_open = false diff --git a/core/main_scene_ui/icon_buttons_row.tscn b/core/main_scene_ui/icon_buttons_row.tscn index 99b64be..0cfbc0a 100644 --- a/core/main_scene_ui/icon_buttons_row.tscn +++ b/core/main_scene_ui/icon_buttons_row.tscn @@ -2,6 +2,7 @@ [ext_resource type="PackedScene" uid="uid://2tqofxxxnvhv" path="res://core/main_scene_ui/icon_button.tscn" id="1_lnxme"] [ext_resource type="Script" uid="uid://cpf5rwmd0kaa6" path="res://core/main_scene_ui/icon_buttons_row.gd" id="1_xq3mw"] +[ext_resource type="PackedScene" uid="uid://dxun0jk5t0n6" path="res://core/tween/container_tween.tscn" id="3_58qdb"] [node name="IconButtonsRow" type="HBoxContainer" unique_id=1734127019] custom_minimum_size = Vector2(800, 0) @@ -41,3 +42,15 @@ visible = false layout_mode = 2 size_flags_horizontal = 0 size_flags_vertical = 3 + +[node name="ShowContainerTween" parent="." unique_id=160227524 node_paths=PackedStringArray("targets") instance=ExtResource("3_58qdb")] +unique_name_in_owner = true +targets = [NodePath("../IconButton2"), NodePath("../IconButton3"), NodePath("../IconButton4"), NodePath("../IconButton5")] +tween_types = Array[String](["impact_land"]) +show_on_start = true + +[node name="HideContainerTween" parent="." unique_id=1169748375 node_paths=PackedStringArray("targets") instance=ExtResource("3_58qdb")] +unique_name_in_owner = true +targets = [NodePath("../IconButton5"), NodePath("../IconButton4"), NodePath("../IconButton3"), NodePath("../IconButton2")] +tween_types = Array[String](["impact_land"]) +hide_on_finish = true diff --git a/core/main_scene_ui/main_menu_ui.gd b/core/main_scene_ui/main_menu_ui.gd deleted file mode 100644 index 773a09e..0000000 --- a/core/main_scene_ui/main_menu_ui.gd +++ /dev/null @@ -1,49 +0,0 @@ -extends Control - -enum Weather {RAIN, SNOW} - -@onready var game_menu: Control = $%GameMenu - -func _on_menu_icon_button_on_pressed() -> void: - GameState.pause_game() - game_menu.show() - - -func _on_photo_icon_button_on_pressed() -> void: - GameState.on_enable_photo_mode_request.emit() - - -func _on_collectible_icon_button_on_pressed() -> void: - GameState.pause_game() - game_menu.on_tab_pressed(1, true) - game_menu.show() - - -func _on_time_of_day_row_on_option_changed(data: String) -> void: - match data: - "Sunrise": - UIEvents.time_option_item_changed.emit(0) - "Day": - UIEvents.time_option_item_changed.emit(1) - "Sunset": - UIEvents.time_option_item_changed.emit(2) - "Night": - UIEvents.time_option_item_changed.emit(3) - _: - pass - - -func _on_weather_row_on_option_changed(data: String) -> void: - match data: - "Snow": - UIEvents.toggle_snow.emit(true) - "Rain": - UIEvents.toggle_rain.emit(true) - "Storm": - UIEvents.toggle_storm.emit(true) - "Wind": - UIEvents.toggle_wind.emit(true) - "Random": - pass - _: - pass diff --git a/core/main_scene_ui/main_scene_ui.gd b/core/main_scene_ui/main_scene_ui.gd new file mode 100644 index 0000000..d6c7951 --- /dev/null +++ b/core/main_scene_ui/main_scene_ui.gd @@ -0,0 +1,67 @@ +extends Control + +enum Weather {RAIN, SNOW} + +@onready var game_menu: Control = $%GameMenu +@onready var game_menu_panel: Control = $%GameMenuPanel +@onready var menu_icon_button: Button = $%MenuIconButton +@onready var photo_icon_button: Button = $%PhotoIconButton +@onready var collectible_icon_button: Button = $%CollectibleIconButton +@onready var resume_button: Button = $GameMenuPanel/GameMenu/Pages/Page3/OptionMenu/VBoxContainer/ResumeButton +@onready var show_container_tween: ContainerTween = $%ShowContainerTween +@onready var hide_container_tween: ContainerTween = $%HideContainerTween + +func _ready() -> void: + menu_icon_button.pressed.connect(_on_menu_icon_button_pressed) + photo_icon_button.pressed.connect(_on_photo_icon_button_pressed) + collectible_icon_button.pressed.connect(_on_collectible_icon_button_pressed) + resume_button.pressed.connect(_on_resume_button_pressed) + + +func _on_menu_icon_button_pressed() -> void: + GameState.pause_game() + game_menu_panel.show() + show_container_tween.start_tween() + +func _on_photo_icon_button_pressed() -> void: + GameState.on_enable_photo_mode_request.emit() + +func _on_collectible_icon_button_pressed() -> void: + GameState.pause_game() + game_menu.on_tab_pressed(1, true) + game_menu_panel.show() + show_container_tween.start_tween() + +func _on_resume_button_pressed() -> void: + hide_container_tween.start_tween() + await hide_container_tween.finished + game_menu_panel.hide() + GameState.resume_game() + +func _on_time_of_day_row_on_option_changed(data: String) -> void: + match data: + "Sunrise": + UIEvents.time_option_item_changed.emit(0) + "Day": + UIEvents.time_option_item_changed.emit(1) + "Sunset": + UIEvents.time_option_item_changed.emit(2) + "Night": + UIEvents.time_option_item_changed.emit(3) + _: + pass + +func _on_weather_row_on_option_changed(data: String) -> void: + match data: + "Snow": + UIEvents.toggle_snow.emit(true) + "Rain": + UIEvents.toggle_rain.emit(true) + "Storm": + UIEvents.toggle_storm.emit(true) + "Wind": + UIEvents.toggle_wind.emit(true) + "Random": + pass + _: + pass diff --git a/core/main_scene_ui/main_menu_ui.gd.uid b/core/main_scene_ui/main_scene_ui.gd.uid similarity index 100% rename from core/main_scene_ui/main_menu_ui.gd.uid rename to core/main_scene_ui/main_scene_ui.gd.uid diff --git a/core/main_scene_ui/main_menu_ui.tscn b/core/main_scene_ui/main_scene_ui.tscn similarity index 52% rename from core/main_scene_ui/main_menu_ui.tscn rename to core/main_scene_ui/main_scene_ui.tscn index 2ddbff5..7dcc6a6 100644 --- a/core/main_scene_ui/main_menu_ui.tscn +++ b/core/main_scene_ui/main_scene_ui.tscn @@ -1,21 +1,23 @@ [gd_scene format=3 uid="uid://bei7fscn77p1p"] -[ext_resource type="PackedScene" uid="uid://ir8nke8o6ssm" path="res://core/main_scene_ui/icon_buttons_row.tscn" id="1_87dkt"] -[ext_resource type="Script" uid="uid://bhad1id8jr8jw" path="res://core/main_scene_ui/main_menu_ui.gd" id="1_aurcl"] -[ext_resource type="PackedScene" uid="uid://2tqofxxxnvhv" path="res://core/main_scene_ui/icon_button.tscn" id="1_fjauj"] -[ext_resource type="PackedScene" uid="uid://dqqm4o8j45tr6" path="res://core/game_menu/game_menu.tscn" id="4_7q818"] -[ext_resource type="PackedScene" uid="uid://cpeyt1dgrtglc" path="res://core/radio/radio.tscn" id="5_21kh1"] -[ext_resource type="PackedScene" uid="uid://dg4f3v0ukpmay" path="res://core/main_scene_ui/audio_player.tscn" id="6_1h1a0"] -[ext_resource type="AudioStream" uid="uid://70cc8she43re" path="res://docs/gyms/radio/lofi_01.ogg" id="6_vhlrw"] +[ext_resource type="Script" uid="uid://bhad1id8jr8jw" path="res://core/main_scene_ui/main_scene_ui.gd" id="1_h43jo"] +[ext_resource type="PackedScene" uid="uid://ir8nke8o6ssm" path="res://core/main_scene_ui/icon_buttons_row.tscn" id="2_4cc8f"] +[ext_resource type="PackedScene" uid="uid://2tqofxxxnvhv" path="res://core/main_scene_ui/icon_button.tscn" id="3_t1xop"] +[ext_resource type="PackedScene" uid="uid://dqqm4o8j45tr6" path="res://core/game_menu/game_menu.tscn" id="4_jh36j"] +[ext_resource type="PackedScene" uid="uid://cpeyt1dgrtglc" path="res://core/radio/radio.tscn" id="5_nevjt"] +[ext_resource type="AudioStream" uid="uid://70cc8she43re" path="res://docs/gyms/radio/lofi_01.ogg" id="6_kd244"] +[ext_resource type="PackedScene" uid="uid://dg4f3v0ukpmay" path="res://core/main_scene_ui/audio_player.tscn" id="7_lapqe"] +[ext_resource type="PackedScene" uid="uid://dxun0jk5t0n6" path="res://core/tween/container_tween.tscn" id="8_msh61"] -[node name="MainMenuUi" type="Control" unique_id=1359391222] +[node name="MainSceneUi" type="Control" unique_id=1359391222] +process_mode = 3 layout_mode = 3 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -script = ExtResource("1_aurcl") +script = ExtResource("1_h43jo") [node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=2071886807] custom_minimum_size = Vector2(160, 320) @@ -27,7 +29,7 @@ offset_top = -320.0 offset_right = 160.0 grow_vertical = 0 -[node name="TimeOfDayRow" parent="VBoxContainer" unique_id=1734127019 instance=ExtResource("1_87dkt")] +[node name="TimeOfDayRow" parent="VBoxContainer" unique_id=1734127019 instance=ExtResource("2_4cc8f")] layout_mode = 2 [node name="IconButton2" parent="VBoxContainer/TimeOfDayRow" index="1" unique_id=638856991] @@ -42,7 +44,13 @@ data = "Sunset" [node name="IconButton5" parent="VBoxContainer/TimeOfDayRow" index="4" unique_id=315412403] data = "Night" -[node name="WeatherRow" parent="VBoxContainer" unique_id=1803637359 instance=ExtResource("1_87dkt")] +[node name="ShowContainerTween" parent="VBoxContainer/TimeOfDayRow" index="5" unique_id=160227524] +tween_types = Array[String](["impact_land", "fade_in"]) + +[node name="HideContainerTween" parent="VBoxContainer/TimeOfDayRow" index="6" unique_id=1169748375] +tween_types = Array[String](["impact_land", "fade_out"]) + +[node name="WeatherRow" parent="VBoxContainer" unique_id=1803637359 instance=ExtResource("2_4cc8f")] layout_mode = 2 [node name="IconButton2" parent="VBoxContainer/WeatherRow" index="1" unique_id=638856991] @@ -57,7 +65,15 @@ data = "Storm" [node name="IconButton5" parent="VBoxContainer/WeatherRow" index="4" unique_id=315412403] data = "Wind" -[node name="IconButton6" parent="VBoxContainer/WeatherRow" unique_id=218253485 instance=ExtResource("1_fjauj")] +[node name="ShowContainerTween" parent="VBoxContainer/WeatherRow" index="5" unique_id=160227524 node_paths=PackedStringArray("targets")] +targets = [NodePath("../IconButton2"), NodePath("../IconButton3"), NodePath("../IconButton4"), NodePath("../IconButton5"), NodePath("../IconButton6")] +tween_types = Array[String](["impact_land", "fade_in"]) + +[node name="HideContainerTween" parent="VBoxContainer/WeatherRow" index="6" unique_id=1169748375 node_paths=PackedStringArray("targets")] +targets = [NodePath("../IconButton6"), NodePath("../IconButton5"), NodePath("../IconButton4"), NodePath("../IconButton3"), NodePath("../IconButton2")] +tween_types = Array[String](["impact_land", "fade_out"]) + +[node name="IconButton6" parent="VBoxContainer/WeatherRow" unique_id=218253485 instance=ExtResource("3_t1xop")] unique_name_in_owner = true visible = false layout_mode = 2 @@ -65,15 +81,15 @@ size_flags_horizontal = 0 size_flags_vertical = 3 data = "Random" -[node name="MenuIconButton" parent="." unique_id=707872474 instance=ExtResource("1_fjauj")] +[node name="MenuIconButton" parent="." unique_id=707872474 instance=ExtResource("3_t1xop")] +unique_name_in_owner = true layout_mode = 1 anchors_preset = 1 anchor_left = 1.0 +anchor_right = 1.0 anchor_bottom = 0.0 offset_left = -160.0 -offset_bottom = 160.0 grow_horizontal = 0 -grow_vertical = 1 [node name="CollectionOptions" type="VBoxContainer" parent="." unique_id=542153805] layout_mode = 1 @@ -88,21 +104,32 @@ offset_bottom = 20.0 grow_horizontal = 0 grow_vertical = 2 -[node name="PhotoIconButton" parent="CollectionOptions" unique_id=1863476241 instance=ExtResource("1_fjauj")] +[node name="PhotoIconButton" parent="CollectionOptions" unique_id=1863476241 instance=ExtResource("3_t1xop")] +unique_name_in_owner = true layout_mode = 2 -[node name="CollectibleIconButton" parent="CollectionOptions" unique_id=520235552 instance=ExtResource("1_fjauj")] +[node name="CollectibleIconButton" parent="CollectionOptions" unique_id=520235552 instance=ExtResource("3_t1xop")] +unique_name_in_owner = true layout_mode = 2 -[node name="GameMenu" parent="." unique_id=2124096517 instance=ExtResource("4_7q818")] +[node name="GameMenuPanel" type="Panel" parent="." unique_id=846120687] unique_name_in_owner = true visible = false layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 -[node name="Radio" parent="." unique_id=1234112225 instance=ExtResource("5_21kh1")] -playlist = Array[AudioStream]([ExtResource("6_vhlrw")]) +[node name="GameMenu" parent="GameMenuPanel" unique_id=2124096517 instance=ExtResource("4_jh36j")] +unique_name_in_owner = true +layout_mode = 1 -[node name="AudioPlayer" parent="." unique_id=425192018 node_paths=PackedStringArray("radio") instance=ExtResource("6_1h1a0")] +[node name="Radio" parent="." unique_id=1234112225 instance=ExtResource("5_nevjt")] +playlist = Array[AudioStream]([ExtResource("6_kd244")]) + +[node name="AudioPlayer" parent="." unique_id=425192018 node_paths=PackedStringArray("radio") instance=ExtResource("7_lapqe")] layout_mode = 1 anchors_preset = 3 anchor_left = 1.0 @@ -117,11 +144,23 @@ grow_horizontal = 0 grow_vertical = 0 radio = NodePath("../Radio") +[node name="ShowContainerTween" parent="." unique_id=902285649 node_paths=PackedStringArray("targets") instance=ExtResource("8_msh61")] +unique_name_in_owner = true +targets = [NodePath("../GameMenuPanel/GameMenu")] +tween_types = Array[String](["fold_in"]) +show_on_start = true + +[node name="HideContainerTween" parent="." unique_id=1041880010 node_paths=PackedStringArray("targets") instance=ExtResource("8_msh61")] +unique_name_in_owner = true +targets = [NodePath("../GameMenuPanel/GameMenu")] +tween_types = Array[String](["fold_out"]) +hide_on_finish = true + [connection signal="on_option_changed" from="VBoxContainer/TimeOfDayRow" to="." method="_on_time_of_day_row_on_option_changed"] [connection signal="on_option_changed" from="VBoxContainer/WeatherRow" to="." method="_on_weather_row_on_option_changed"] -[connection signal="on_pressed" from="MenuIconButton" to="." method="_on_menu_icon_button_on_pressed"] -[connection signal="on_pressed" from="CollectionOptions/PhotoIconButton" to="." method="_on_photo_icon_button_on_pressed"] -[connection signal="on_pressed" from="CollectionOptions/CollectibleIconButton" to="." method="_on_collectible_icon_button_on_pressed"] [editable path="VBoxContainer/TimeOfDayRow"] [editable path="VBoxContainer/WeatherRow"] +[editable path="GameMenuPanel/GameMenu"] +[editable path="GameMenuPanel/GameMenu/Pages/Page3"] +[editable path="GameMenuPanel/GameMenu/Pages/Page3/OptionMenu"] diff --git a/core/scene_manager/scene_manager.tscn b/core/scene_manager/scene_manager.tscn index 2370a3f..0df7e87 100644 --- a/core/scene_manager/scene_manager.tscn +++ b/core/scene_manager/scene_manager.tscn @@ -4,6 +4,7 @@ [ext_resource type="Resource" uid="uid://dr612tmciq8pg" path="res://core/scene_manager/scene_config.tres" id="2_vtdwt"] [node name="SceneManager" type="CanvasLayer" unique_id=399843239] +process_mode = 3 layer = 100 script = ExtResource("1_7resu") config = ExtResource("2_vtdwt") diff --git a/core/tween/container_tween.gd b/core/tween/container_tween.gd new file mode 100644 index 0000000..4699ce1 --- /dev/null +++ b/core/tween/container_tween.gd @@ -0,0 +1,86 @@ +extends Node +class_name ContainerTween + +signal finished + +enum AnimateOrder { + AS_IS, + TOP_TO_BOTTOM, + BOTTOM_TO_TOP, + LEFT_TO_RIGHT, + RIGHT_TO_LEFT +} + +@export_group("Settings") +@export var targets: Array[Control] +@export var runtime_target_parent: Control +@export var tween_types: Array[String] = ["punch_in"] +@export var order: AnimateOrder = AnimateOrder.AS_IS +@export var stagger_delay: float = 0.05 +@export var show_on_start: bool = false +@export var hide_on_finish: bool = false +@export var reset_state_on_start: bool = true + +var _tween_generation: int = 0 +var is_running: bool = false + + +func start_tween() -> void: + if is_running: + return + + is_running = true + _tween_generation += 1 + var current_gen = _tween_generation + + var sorted_targets = targets.duplicate() if !targets.is_empty() else runtime_target_parent.get_children().duplicate() + + match order: + AnimateOrder.TOP_TO_BOTTOM: + sorted_targets.sort_custom(func(a, b): return a.global_position.y < b.global_position.y) + AnimateOrder.BOTTOM_TO_TOP: + sorted_targets.sort_custom(func(a, b): return a.global_position.y > b.global_position.y) + AnimateOrder.LEFT_TO_RIGHT: + sorted_targets.sort_custom(func(a, b): return a.global_position.x < b.global_position.x) + AnimateOrder.RIGHT_TO_LEFT: + sorted_targets.sort_custom(func(a, b): return a.global_position.x > b.global_position.x) + + var last_tween: Tween = null + for target in sorted_targets: + if current_gen != _tween_generation: + return + + if is_instance_valid(target): + if reset_state_on_start: + target.scale = Vector2.ONE + target.modulate.a = 1.0 + + if show_on_start: + target.show() + + for type in tween_types: + var tween = TweenFX.call(type, target) + if tween is Tween: + last_tween = tween + + if hide_on_finish and tween is Tween: + tween.tween_callback(target.hide) + + if stagger_delay > 0.0: + await get_tree().create_timer(stagger_delay).timeout + + if is_instance_valid(last_tween) and last_tween.is_running(): + await last_tween.finished + + if current_gen == _tween_generation: + is_running = false + finished.emit() + + +func stop_tween() -> void: + is_running = false + _tween_generation += 1 + var current_targets = targets if !targets.is_empty() else runtime_target_parent.get_children() + for target in current_targets: + if is_instance_valid(target): + TweenFX.stop_all(target) diff --git a/core/game_menu/hoover_tween.gd.uid b/core/tween/container_tween.gd.uid similarity index 100% rename from core/game_menu/hoover_tween.gd.uid rename to core/tween/container_tween.gd.uid diff --git a/core/tween/container_tween.tscn b/core/tween/container_tween.tscn new file mode 100644 index 0000000..ffb2cae --- /dev/null +++ b/core/tween/container_tween.tscn @@ -0,0 +1,7 @@ +[gd_scene format=3 uid="uid://dxun0jk5t0n6"] + +[ext_resource type="Script" uid="uid://ryxh3nm7ayvf" path="res://core/tween/container_tween.gd" id="1_qfild"] + +[node name="ContainerTween" type="Node" unique_id=160227524] +process_mode = 3 +script = ExtResource("1_qfild") diff --git a/project.godot b/project.godot index 130d920..d5d1ef6 100644 --- a/project.godot +++ b/project.godot @@ -24,6 +24,7 @@ CollectionManager="*uid://22orqdm34hfm" AudioManager="*uid://dcttbbavtwtsg" SceneManager="*uid://bw8hwkw55j675" ShaderWarmup="res://core/shader_warmup.gd" +TweenFX="*uid://d2n10rw2dnx8o" [display] @@ -34,7 +35,7 @@ window/stretch/aspect="expand" [editor_plugins] -enabled=PackedStringArray() +enabled=PackedStringArray("res://addons/TweenFX/plugin.cfg") [global_group] diff --git a/tgcc/chunk/prop/fields/carrot/carrot.res b/tgcc/chunk/prop/fields/carrot/carrot.res index f17c9db..16c28a8 100644 Binary files a/tgcc/chunk/prop/fields/carrot/carrot.res and b/tgcc/chunk/prop/fields/carrot/carrot.res differ diff --git a/tgcc/chunk/prop/fields/potato/potato.res b/tgcc/chunk/prop/fields/potato/potato.res index 754b2dc..f8cc51b 100644 Binary files a/tgcc/chunk/prop/fields/potato/potato.res and b/tgcc/chunk/prop/fields/potato/potato.res differ diff --git a/tgcc/chunk/prop/tree/bambù/Bambu.res b/tgcc/chunk/prop/tree/bambù/Bambu.res index 70c60b2..54263e3 100644 Binary files a/tgcc/chunk/prop/tree/bambù/Bambu.res and b/tgcc/chunk/prop/tree/bambù/Bambu.res differ diff --git a/tgcc/main_scene.tscn b/tgcc/main_scene.tscn index 5c58461..6e4ba32 100644 --- a/tgcc/main_scene.tscn +++ b/tgcc/main_scene.tscn @@ -6,33 +6,33 @@ [ext_resource type="Script" uid="uid://brcimd12tx3dm" path="res://core/daynight/edge_detection_compositor.gd" id="4_lpdy6"] [ext_resource type="PackedScene" uid="uid://ujv2f1l4d2ps" path="res://core/biome_generator/biome_generator.tscn" id="5_islkt"] [ext_resource type="Script" uid="uid://wv6kcqkibium" path="res://core/biome_generator/biome.gd" id="6_jfe74"] -[ext_resource type="PackedScene" uid="uid://b8blm6bwintf7" path="res://tgcc/chunk/countryside/scene/chunk_country_empty_01.tscn" id="7_5lqbd"] -[ext_resource type="PackedScene" uid="uid://cjv1e8pc6gde1" path="res://tgcc/chunk/countryside/scene/chunk_country_corner_01.tscn" id="8_aiwf5"] -[ext_resource type="PackedScene" uid="uid://dqoai3665vb0a" path="res://tgcc/chunk/countryside/scene/chunk_country_corner_02.tscn" id="9_0gakq"] -[ext_resource type="PackedScene" uid="uid://crlk31ecl480n" path="res://tgcc/chunk/countryside/scene/chunk_country_corner_03.tscn" id="10_8taq1"] -[ext_resource type="PackedScene" uid="uid://brpp7fe5noq8v" path="res://tgcc/chunk/countryside/scene/chunk_country_cross_3_01.tscn" id="11_bx28o"] -[ext_resource type="PackedScene" uid="uid://qmt8bkiksgj3" path="res://tgcc/chunk/countryside/scene/chunk_country_cross_3_02.tscn" id="12_e3o1y"] -[ext_resource type="PackedScene" uid="uid://d1tfkhuktwthn" path="res://tgcc/chunk/countryside/scene/chunk_country_cross_3_03.tscn" id="13_pesa5"] -[ext_resource type="PackedScene" uid="uid://b002wu5ltuqi4" path="res://tgcc/chunk/countryside/scene/chunk_country_end_01.tscn" id="14_d5byn"] -[ext_resource type="PackedScene" uid="uid://dtfmvcbninrcu" path="res://tgcc/chunk/countryside/scene/chunk_country_end_02.tscn" id="15_vk128"] -[ext_resource type="PackedScene" uid="uid://h6xj43vo84uf" path="res://tgcc/chunk/countryside/scene/chunk_country_straight_01.tscn" id="16_0l4fn"] -[ext_resource type="PackedScene" uid="uid://cu2chsjh8wuvp" path="res://tgcc/chunk/countryside/scene/chunk_country_straight_02.tscn" id="17_0l3s0"] -[ext_resource type="PackedScene" uid="uid://pxmcy0lhne5d" path="res://tgcc/chunk/countryside/scene/chunk_country_straight_03.tscn" id="18_0mfe6"] -[ext_resource type="PackedScene" uid="uid://bs3dkwcc8w2uk" path="res://tgcc/chunk/river/scene/chunk_river_curve_1.tscn" id="19_8ws46"] -[ext_resource type="PackedScene" uid="uid://btipd6wev016d" path="res://tgcc/chunk/river/scene/chunk_river_straight_1.tscn" id="20_fv7f0"] -[ext_resource type="PackedScene" uid="uid://deaxxlxdipqvx" path="res://tgcc/chunk/river/scene/chunk_river_end_1.tscn" id="21_psqnm"] -[ext_resource type="PackedScene" uid="uid://ct3084nflycla" path="res://tgcc/chunk/river/scene/chunk_river_mix1_1.tscn" id="22_j4kwo"] -[ext_resource type="PackedScene" uid="uid://bhvmmw8d8vns5" path="res://tgcc/chunk/river/scene/chunk_river_mix2_1.tscn" id="23_53r6v"] -[ext_resource type="PackedScene" uid="uid://cqe4t842io22i" path="res://tgcc/chunk/river/scene/chunk_river_cross_1.tscn" id="24_esnpb"] -[ext_resource type="PackedScene" uid="uid://rjvefmcd4bpo" path="res://tgcc/chunk/river/scene/chunk_river_mix3_1.tscn" id="25_6ik1i"] -[ext_resource type="PackedScene" uid="uid://c6vpwol3k384y" path="res://tgcc/chunk/river/scene/chunk_river_mix4_1.tscn" id="26_x7bpo"] -[ext_resource type="PackedScene" uid="uid://cd3iyj71hkgcr" path="res://tgcc/chunk/river/scene/chunk_river_mix5_1.tscn" id="27_e6m8d"] -[ext_resource type="PackedScene" uid="uid://bh8kbw07bsu6n" path="res://tgcc/chunk/river/scene/chunk_river_mix6_1.tscn" id="28_jdvk1"] -[ext_resource type="PackedScene" uid="uid://ce6qvpb27fdpo" path="res://tgcc/chunk/river/scene/chunk_river_curve_2.tscn" id="29_otsi4"] -[ext_resource type="PackedScene" uid="uid://7063xk3bwboc" path="res://tgcc/chunk/river/scene/chunk_river_straight_4.tscn" id="30_pvks6"] -[ext_resource type="PackedScene" uid="uid://ccgd3uy68r88h" path="res://tgcc/chunk/river/scene/chunk_river_curve_3.tscn" id="31_36ld5"] -[ext_resource type="PackedScene" uid="uid://mpgyaho52lii" path="res://tgcc/chunk/river/scene/chunk_river_straight_5.tscn" id="32_4i5nu"] -[ext_resource type="PackedScene" uid="uid://q26mkh3cupic" path="res://tgcc/chunk/river/scene/chunk_river_cross_2.tscn" id="33_3gjue"] +[ext_resource type="PackedScene" uid="uid://b8blm6bwintf7" path="res://tgcc/chunk/countryside/scene/rice/chunk_country_empty_01.tscn" id="7_5lqbd"] +[ext_resource type="PackedScene" uid="uid://cjv1e8pc6gde1" path="res://tgcc/chunk/countryside/scene/rice/chunk_country_corner_01.tscn" id="8_aiwf5"] +[ext_resource type="PackedScene" uid="uid://dqoai3665vb0a" path="res://tgcc/chunk/countryside/scene/rice/chunk_country_corner_02.tscn" id="9_0gakq"] +[ext_resource type="PackedScene" uid="uid://crlk31ecl480n" path="res://tgcc/chunk/countryside/scene/rice/chunk_country_corner_03.tscn" id="10_8taq1"] +[ext_resource type="PackedScene" uid="uid://brpp7fe5noq8v" path="res://tgcc/chunk/countryside/scene/rice/chunk_country_cross_3_01.tscn" id="11_bx28o"] +[ext_resource type="PackedScene" uid="uid://qmt8bkiksgj3" path="res://tgcc/chunk/countryside/scene/rice/chunk_country_cross_3_02.tscn" id="12_e3o1y"] +[ext_resource type="PackedScene" uid="uid://d1tfkhuktwthn" path="res://tgcc/chunk/countryside/scene/rice/chunk_country_cross_3_03.tscn" id="13_pesa5"] +[ext_resource type="PackedScene" uid="uid://b002wu5ltuqi4" path="res://tgcc/chunk/countryside/scene/rice/chunk_country_end_01.tscn" id="14_d5byn"] +[ext_resource type="PackedScene" uid="uid://dtfmvcbninrcu" path="res://tgcc/chunk/countryside/scene/rice/chunk_country_end_02.tscn" id="15_vk128"] +[ext_resource type="PackedScene" uid="uid://h6xj43vo84uf" path="res://tgcc/chunk/countryside/scene/rice/chunk_country_straight_01.tscn" id="16_0l4fn"] +[ext_resource type="PackedScene" uid="uid://cu2chsjh8wuvp" path="res://tgcc/chunk/countryside/scene/rice/chunk_country_straight_02.tscn" id="17_0l3s0"] +[ext_resource type="PackedScene" uid="uid://pxmcy0lhne5d" path="res://tgcc/chunk/countryside/scene/rice/chunk_country_straight_03.tscn" id="18_0mfe6"] +[ext_resource type="PackedScene" uid="uid://bs3dkwcc8w2uk" path="res://tgcc/chunk/countryside/scene/rice/river/scene/chunk_river_curve_1.tscn" id="19_8ws46"] +[ext_resource type="PackedScene" uid="uid://btipd6wev016d" path="res://tgcc/chunk/countryside/scene/rice/river/scene/chunk_river_straight_1.tscn" id="20_fv7f0"] +[ext_resource type="PackedScene" uid="uid://deaxxlxdipqvx" path="res://tgcc/chunk/countryside/scene/rice/river/scene/chunk_river_end_1.tscn" id="21_psqnm"] +[ext_resource type="PackedScene" uid="uid://ct3084nflycla" path="res://tgcc/chunk/countryside/scene/rice/river/scene/chunk_river_mix1_1.tscn" id="22_j4kwo"] +[ext_resource type="PackedScene" uid="uid://bhvmmw8d8vns5" path="res://tgcc/chunk/countryside/scene/rice/river/scene/chunk_river_mix2_1.tscn" id="23_53r6v"] +[ext_resource type="PackedScene" uid="uid://cqe4t842io22i" path="res://tgcc/chunk/countryside/scene/rice/river/scene/chunk_river_cross_1.tscn" id="24_esnpb"] +[ext_resource type="PackedScene" uid="uid://rjvefmcd4bpo" path="res://tgcc/chunk/countryside/scene/rice/river/scene/chunk_river_mix3_1.tscn" id="25_6ik1i"] +[ext_resource type="PackedScene" uid="uid://c6vpwol3k384y" path="res://tgcc/chunk/countryside/scene/rice/river/scene/chunk_river_mix4_1.tscn" id="26_x7bpo"] +[ext_resource type="PackedScene" uid="uid://cd3iyj71hkgcr" path="res://tgcc/chunk/countryside/scene/rice/river/scene/chunk_river_mix5_1.tscn" id="27_e6m8d"] +[ext_resource type="PackedScene" uid="uid://bh8kbw07bsu6n" path="res://tgcc/chunk/countryside/scene/rice/river/scene/chunk_river_mix6_1.tscn" id="28_jdvk1"] +[ext_resource type="PackedScene" uid="uid://ce6qvpb27fdpo" path="res://tgcc/chunk/countryside/scene/rice/river/scene/chunk_river_curve_2.tscn" id="29_otsi4"] +[ext_resource type="PackedScene" uid="uid://7063xk3bwboc" path="res://tgcc/chunk/countryside/scene/rice/river/scene/chunk_river_straight_4.tscn" id="30_pvks6"] +[ext_resource type="PackedScene" uid="uid://ccgd3uy68r88h" path="res://tgcc/chunk/countryside/scene/rice/river/scene/chunk_river_curve_3.tscn" id="31_36ld5"] +[ext_resource type="PackedScene" uid="uid://mpgyaho52lii" path="res://tgcc/chunk/countryside/scene/rice/river/scene/chunk_river_straight_5.tscn" id="32_4i5nu"] +[ext_resource type="PackedScene" uid="uid://q26mkh3cupic" path="res://tgcc/chunk/countryside/scene/rice/river/scene/chunk_river_cross_2.tscn" id="33_3gjue"] [ext_resource type="Resource" uid="uid://cmd6s6thq4f7r" path="res://core/biome_generator/entities_pool.tres" id="34_a2cst"] [ext_resource type="PackedScene" uid="uid://cv5xmnow451kl" path="res://core/camera.tscn" id="35_f2l8p"] [ext_resource type="PackedScene" uid="uid://cmuvmmp7xam4o" path="res://core/daynight/environment_management.tscn" id="36_qwsp8"] @@ -44,12 +44,12 @@ [ext_resource type="AudioStream" uid="uid://elrjw0smm0cj" path="res://core/daynight/sounds/rain_3.mp3" id="42_mh642"] [ext_resource type="PackedScene" uid="uid://1c1ion0qnho4" path="res://tgcc/map/map_1/map_1.tscn" id="43_ysd85"] [ext_resource type="Script" uid="uid://dboerd4a6dwj7" path="res://core/biome_generator/rails.gd" id="44_rcqo0"] -[ext_resource type="PackedScene" uid="uid://dvk3bytqn3m5s" path="res://tgcc/train/main_train.tscn" id="45_c0jxs"] +[ext_resource type="PackedScene" uid="uid://dvk3bytqn3m5s" path="res://tgcc/train/test/Train_test.tscn" id="45_c0jxs"] [ext_resource type="Resource" uid="uid://bjnytgwt8tmf4" path="res://core/biome_generator/wagon_pool.tres" id="46_exdk1"] [ext_resource type="PackedScene" uid="uid://0kgjaqijaqku" path="res://docs/museums/biome_generator/rails.tscn" id="46_lbmv2"] [ext_resource type="PackedScene" uid="uid://dn1btv0e0ses7" path="res://core/fireworks.tscn" id="47_q7p65"] [ext_resource type="Script" uid="uid://cx2tlvxhvatj5" path="res://docs/museums/daynight/control.gd" id="48_r5xyi"] -[ext_resource type="PackedScene" uid="uid://bei7fscn77p1p" path="res://core/main_scene_ui/main_menu_ui.tscn" id="49_exdk1"] +[ext_resource type="PackedScene" uid="uid://bei7fscn77p1p" path="res://core/main_scene_ui/main_scene_ui.tscn" id="49_exdk1"] [ext_resource type="PackedScene" uid="uid://vni5kjalum6d" path="res://core/photo_mode/runtime/photo_mode_controller.tscn" id="50_57hhv"] [sub_resource type="FastNoiseLite" id="FastNoiseLite_wjpfq"] @@ -454,7 +454,7 @@ theme_override_colors/font_hover_pressed_color = Color(1, 1, 1, 1) theme_override_colors/font_outline_color = Color(1, 1, 1, 1) text = "Update Rails" -[node name="MainMenuUi" parent="." unique_id=1359391222 instance=ExtResource("49_exdk1")] +[node name="MainSceneUi" parent="." unique_id=1359391222 instance=ExtResource("49_exdk1")] mouse_filter = 2 [connection signal="toggled" from="Control/Snow" to="Control" method="_on_snow_toggled"] diff --git a/tgcc/train/rail/rail.res b/tgcc/train/rail/rail.res index 4057f63..f8a71d7 100644 Binary files a/tgcc/train/rail/rail.res and b/tgcc/train/rail/rail.res differ