PlayerCamera2 WIP
This commit is contained in:
parent
7641aa5d3e
commit
d343c458a2
9 changed files with 147 additions and 30 deletions
|
@ -190,4 +190,3 @@ func _on_filter_text_changed() -> void:
|
||||||
var sf = get_node(stat_filter)
|
var sf = get_node(stat_filter)
|
||||||
for child in categories.get_children():
|
for child in categories.get_children():
|
||||||
child.visible = child.name.contains(sf.text) || sf.text == ""
|
child.visible = child.name.contains(sf.text) || sf.text == ""
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,10 @@
|
||||||
extends Node2D
|
extends Node2D
|
||||||
class_name CameraProperties
|
class_name CameraProperties
|
||||||
|
|
||||||
|
## In the camera stack, all these values have to be set at some point.
|
||||||
|
|
||||||
## x: transition time, y: completeness of transition (0.0 to 1.0)
|
## x: transition time, y: completeness of transition (0.0 to 1.0)
|
||||||
@export var transform_curve: Curve = null
|
@export var transform_curve: Curve = null
|
||||||
## x: transition time, y: completeness of transition (0.0 to 1.0)
|
@export var limits: Limits = null
|
||||||
@export var limits_curve: Curve = null
|
@export var smoothing : Float = null
|
||||||
## x: transition time, y: completeness of transition (0.0 to 1.0)
|
|
||||||
@export var smoothing_curve: Curve = null
|
|
||||||
|
|
||||||
## The leftomost point of the screen will not pass this coordinate
|
|
||||||
@export var limit_left := -10000000
|
|
||||||
## -||-
|
|
||||||
@export var limit_right := 10000000
|
|
||||||
## -||-
|
|
||||||
@export var limit_top := -10000000
|
|
||||||
## -||-
|
|
||||||
@export var limit_bottom := 10000000
|
|
||||||
|
|
||||||
## The smoothing of the camera.
|
|
||||||
@export var smoothing := 8.0
|
|
||||||
|
|
||||||
|
|
19
project2-godot/global/camera/Limits.gd
Normal file
19
project2-godot/global/camera/Limits.gd
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
extends Resource
|
||||||
|
class_name Limits
|
||||||
|
|
||||||
|
@export var left: float
|
||||||
|
@export var right: float
|
||||||
|
@export var top: float
|
||||||
|
@export var bottom: float
|
||||||
|
|
||||||
|
func _init(
|
||||||
|
p_left = -10000000,
|
||||||
|
p_right = 10000000,
|
||||||
|
p_top = - 10000000,
|
||||||
|
p_bottom = 10000000
|
||||||
|
):
|
||||||
|
left = p_left
|
||||||
|
right = p_right
|
||||||
|
top = p_top
|
||||||
|
bottom = p_bottom
|
||||||
|
|
1
project2-godot/global/camera/Limits.gd.uid
Normal file
1
project2-godot/global/camera/Limits.gd.uid
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uid://dbhp6ek2kwibq
|
|
@ -1,7 +1,6 @@
|
||||||
extends Node2D
|
extends Node2D
|
||||||
|
|
||||||
# TODO make "original properties" into "previous targets" for more natural
|
@export var original_properties: NodePath
|
||||||
# transitions.
|
|
||||||
|
|
||||||
## If enabled, takes control of viewport transform.
|
## If enabled, takes control of viewport transform.
|
||||||
@export var enabled := false
|
@export var enabled := false
|
||||||
|
@ -49,7 +48,6 @@ var example_properties := {
|
||||||
@onready var camera_stack : Array[CameraProperties] = [ get_node(fallback_properties) ]
|
@onready var camera_stack : Array[CameraProperties] = [ get_node(fallback_properties) ]
|
||||||
## Schema: { <property_name>: <property_progress> (seconds) }
|
## Schema: { <property_name>: <property_progress> (seconds) }
|
||||||
var property_progress := {}
|
var property_progress := {}
|
||||||
var original_properties := {}
|
|
||||||
## Used for smoothing
|
## Used for smoothing
|
||||||
## Schema: { <property_name>: <reference to node> }
|
## Schema: { <property_name>: <reference to node> }
|
||||||
var current_properties := {}
|
var current_properties := {}
|
||||||
|
@ -99,7 +97,7 @@ func _reset(op):
|
||||||
if p_to_c[key] != new_p_to_c[key]:
|
if p_to_c[key] != new_p_to_c[key]:
|
||||||
# reset timer
|
# reset timer
|
||||||
property_progress[key] = 0.0
|
property_progress[key] = 0.0
|
||||||
original_properties[key] = p_to_c[key]
|
get_node(original_properties)[key] = p_to_c[key]
|
||||||
|
|
||||||
func remove_camera(c):
|
func remove_camera(c):
|
||||||
var op = func(): camera_stack.erase(c)
|
var op = func(): camera_stack.erase(c)
|
||||||
|
@ -134,6 +132,9 @@ func reset_smoothing():
|
||||||
for p in properties:
|
for p in properties:
|
||||||
original_properties[p] = _get_camera(p)
|
original_properties[p] = _get_camera(p)
|
||||||
|
|
||||||
|
func _clamp_with_limits(value: Vector2, limits_node) -> Vector2:
|
||||||
|
pass
|
||||||
|
|
||||||
func _process(delta: float):
|
func _process(delta: float):
|
||||||
# Lookaside (x-pan)
|
# Lookaside (x-pan)
|
||||||
var target_pos = look_aside if looking_right else - look_aside
|
var target_pos = look_aside if looking_right else - look_aside
|
||||||
|
@ -155,18 +156,16 @@ func _process(delta: float):
|
||||||
)
|
)
|
||||||
var smoothing = current_properties["smoothing"]
|
var smoothing = current_properties["smoothing"]
|
||||||
_property_step("limits", func(fraction, old, target_node):
|
_property_step("limits", func(fraction, old, target_node):
|
||||||
var intermediate_left = lerpf(old.limit_left, target_node.limit_left, fraction)
|
current_properties["limits"]["left"] = target_node.limit_left
|
||||||
current_properties["limits"]["left"] = lerpf(current_properties["limits"]["left"], intermediate_left, smoothing * delta)
|
current_properties["limits"]["right"] = target_node.limit_right
|
||||||
var intermediate_right = lerpf(old.limit_right, target_node.limit_right, fraction)
|
current_properties["limits"]["top"] = target_node.limit_top
|
||||||
current_properties["limits"]["right"] = lerpf(current_properties["limits"]["right"], intermediate_right, smoothing * delta)
|
current_properties["limits"]["bottom"] = target_node.limit_bottom
|
||||||
var intermediate_top = lerpf(old.limit_top, target_node.limit_top, fraction)
|
|
||||||
current_properties["limits"]["top"] = lerpf(current_properties["limits"]["top"], intermediate_top, smoothing * delta)
|
|
||||||
var intermediate_bottom = lerpf(old.limit_bottom, target_node.limit_bottom, fraction)
|
|
||||||
current_properties["limits"]["bottom"] = lerpf(current_properties["limits"]["bottom"], intermediate_bottom, smoothing * delta)
|
|
||||||
)
|
)
|
||||||
_property_step("transform", func(fraction, old, target_node):
|
_property_step("transform", func(fraction, old, target_node):
|
||||||
# We are not interested in inherited transform properties except for position
|
# We are not interested in inherited transform properties except for position
|
||||||
var end_target = target_node.transform.translated(target_node.global_transform.origin)
|
var end_target_pos = _clamp_with_limits(target_node.transform.global_transform, _get_camera("limits"))
|
||||||
|
var end_target = target_node.transform.translated(end_target_pos)
|
||||||
|
|
||||||
var old_target = old.transform.translated(old.global_transform.origin)
|
var old_target = old.transform.translated(old.global_transform.origin)
|
||||||
|
|
||||||
var intermediate_target: Transform2D = old_target.interpolate_with(end_target, fraction)
|
var intermediate_target: Transform2D = old_target.interpolate_with(end_target, fraction)
|
||||||
|
|
101
project2-godot/global/camera/PlayerCamera2.gd
Normal file
101
project2-godot/global/camera/PlayerCamera2.gd
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
## If enabled, takes control of viewport transform.
|
||||||
|
@export var enabled := false
|
||||||
|
|
||||||
|
## Enables outputting debug info for this camera. Shows center of camera gizmo if gizmos are turned on.
|
||||||
|
## Outputs properties to debug screen.
|
||||||
|
@export var debug_show := false
|
||||||
|
|
||||||
|
var properties := ["transform", "smoothing", "limits"]
|
||||||
|
|
||||||
|
## The default camera properties.
|
||||||
|
@export var fallback_properties: NodePath
|
||||||
|
|
||||||
|
## Used to store nodes of properties of A during transition A -> B.
|
||||||
|
var _original_properties := {}
|
||||||
|
|
||||||
|
|
||||||
|
## Stack of references to CamerProperties
|
||||||
|
@onready var _camera_stack : Array[CameraProperties] = [ get_node(fallback_properties) ]
|
||||||
|
|
||||||
|
var _transition_progress := 1.0
|
||||||
|
var _current_transform: Transform2D = Transform2D.IDENTITY
|
||||||
|
|
||||||
|
func reset_smoothing():
|
||||||
|
_transition_progress = 1.0
|
||||||
|
|
||||||
|
|
||||||
|
## Finds the active CameraProperties for a given property.
|
||||||
|
## depth can be specified to get the camera of second/third/... priority.
|
||||||
|
func _get_camera(property: String, depth: int = 0):
|
||||||
|
var current_depth := depth
|
||||||
|
|
||||||
|
for i in _camera_stack.size():
|
||||||
|
var index = _camera_stack.size() -1 -i
|
||||||
|
var c = _camera_stack[index]
|
||||||
|
# Clean up destroyed cameras
|
||||||
|
if c == null:
|
||||||
|
_camera_stack.remove_at(index)
|
||||||
|
else:
|
||||||
|
var null_check_name = "transform_curve" if property == "transform" else property
|
||||||
|
if c[null_check_name] != null:
|
||||||
|
if current_depth <= 0:
|
||||||
|
return c
|
||||||
|
else:
|
||||||
|
current_depth -= 1
|
||||||
|
# there wasn't a camera with this depth? try getting one with higher priority
|
||||||
|
return _get_camera(property, depth - 1)
|
||||||
|
|
||||||
|
|
||||||
|
## Set timers and original properties on properites that changed after operation "op".
|
||||||
|
func _reset(op):
|
||||||
|
var p_to_c := {}
|
||||||
|
# get list of destination cameras for every property
|
||||||
|
for p in properties:
|
||||||
|
p_to_c[p] = _get_camera(p)
|
||||||
|
# remove/add camera
|
||||||
|
op.call()
|
||||||
|
# get list of destination cameras for every property
|
||||||
|
var new_p_to_c := {}
|
||||||
|
for p in properties:
|
||||||
|
new_p_to_c[p] = _get_camera(p)
|
||||||
|
# reset transition timer
|
||||||
|
if p_to_c["transform"] != new_p_to_c["transform"]:
|
||||||
|
_transition_progress = 1.0
|
||||||
|
# set original properties
|
||||||
|
for key in p_to_c:
|
||||||
|
if p_to_c[key] != new_p_to_c[key]:
|
||||||
|
_original_properties[key] = p_to_c[key]
|
||||||
|
|
||||||
|
func _clamp_with_limits(value: Vector2, limits: Limits, middle_offset: Vector2) -> Vector2:
|
||||||
|
return Vector2(
|
||||||
|
clampf(value.x, limits.left + middle_offset.x, limits.right - middle_offset.x),
|
||||||
|
clampf(value.y, limits.top + middle_offset.y, limits.bottom - middle_offset.y)
|
||||||
|
)
|
||||||
|
|
||||||
|
func _process(delta: float):
|
||||||
|
if enabled:
|
||||||
|
# the offset of the viewport to account for the screen size
|
||||||
|
var middle_offset: Vector2 = get_viewport().content_scale_size / 2
|
||||||
|
|
||||||
|
# update position
|
||||||
|
var target_node = _get_camera("transform")
|
||||||
|
var target_pos = _clamp_with_limits(target_node.transform.global_transform, _get_camera("limits").limits, middle_offset)
|
||||||
|
var target_transform = target_node.transform.translated(target_pos)
|
||||||
|
|
||||||
|
var original_node = _original_properties["transform"]
|
||||||
|
var original_pos = _clamp_with_limits(target_node.transform.global_transform, _original_properties["limits"].limits, middle_offset)
|
||||||
|
var original_transform = original_node.transform.translated(original_pos)
|
||||||
|
|
||||||
|
var intermediate_fraction = _get_camera("transform").transform_curve.sample(_transition_progress)
|
||||||
|
var intermediate_transform: Transform2D = original_transform.interpolate_with(target_transform, intermediate_fraction)
|
||||||
|
|
||||||
|
var smoothing = _get_camera("smoothing").smoothing.value
|
||||||
|
|
||||||
|
# interpolate between _current_transform and intermediate_transform
|
||||||
|
_current_transform.interpolate_with(intermediate_transform, smoothing * delta)
|
||||||
|
|
||||||
|
# apply to viewport
|
||||||
|
get_viewport().canvas_transform = _current_transform.inverse().translated(middle_offset)
|
||||||
|
|
1
project2-godot/global/camera/PlayerCamera2.gd.uid
Normal file
1
project2-godot/global/camera/PlayerCamera2.gd.uid
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uid://60wby2r3n4tx
|
8
project2-godot/global/hacks/Float.gd
Normal file
8
project2-godot/global/hacks/Float.gd
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
extends Resource
|
||||||
|
class_name Float
|
||||||
|
|
||||||
|
@export var val: float = 0.0
|
||||||
|
|
||||||
|
func _init(p_val = 0.0):
|
||||||
|
val = p_val
|
||||||
|
|
1
project2-godot/global/hacks/Float.gd.uid
Normal file
1
project2-godot/global/hacks/Float.gd.uid
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uid://bmuu0n34auwaq
|
Loading…
Add table
Add a link
Reference in a new issue