|
|
|
|
@@ -4,23 +4,36 @@ class_name ESCCamera
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Reference to the tween node for animating camera movements
|
|
|
|
|
var tween
|
|
|
|
|
var _tween: Tween
|
|
|
|
|
|
|
|
|
|
# Target position of the camera
|
|
|
|
|
var target: Vector2 = Vector2()
|
|
|
|
|
var _target: Vector2 = Vector2()
|
|
|
|
|
|
|
|
|
|
# The object to follow
|
|
|
|
|
var follow_target: Node = null
|
|
|
|
|
var _follow_target: Node = null
|
|
|
|
|
|
|
|
|
|
# Target zoom of the camera
|
|
|
|
|
var zoom_target: Vector2
|
|
|
|
|
|
|
|
|
|
# Time of zoom
|
|
|
|
|
var zoom_time
|
|
|
|
|
var _zoom_target: Vector2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# This is needed to adjust dialog positions and such, see dialog_instance.gd
|
|
|
|
|
var zoom_transform
|
|
|
|
|
# Prepare the tween
|
|
|
|
|
func _ready():
|
|
|
|
|
_tween = Tween.new()
|
|
|
|
|
add_child(_tween)
|
|
|
|
|
_tween.connect("tween_all_completed", self, "_target_reached")
|
|
|
|
|
escoria.object_manager.register_object(
|
|
|
|
|
ESCObject.new(
|
|
|
|
|
"_camera",
|
|
|
|
|
self
|
|
|
|
|
),
|
|
|
|
|
true
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Update the position if the followed target is moving
|
|
|
|
|
func _process(_delta):
|
|
|
|
|
if is_instance_valid(_follow_target) and not _tween.is_active() and _follow_target.has_moved():
|
|
|
|
|
self.global_position = _follow_target.global_position
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Sets camera limits so it doesn't go out of the scene
|
|
|
|
|
@@ -35,30 +48,34 @@ func set_limits(limits: ESCCameraLimits):
|
|
|
|
|
self.limit_bottom = limits.limit_bottom
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Resolve the correct position and zoom of the target object
|
|
|
|
|
#
|
|
|
|
|
# #### Parameters
|
|
|
|
|
# - p_target: The target to resolve
|
|
|
|
|
func _resolve_target_and_zoom(p_target) -> void:
|
|
|
|
|
target = Vector2()
|
|
|
|
|
zoom_target = Vector2()
|
|
|
|
|
follow_target = null
|
|
|
|
|
_target = Vector2()
|
|
|
|
|
_zoom_target = Vector2()
|
|
|
|
|
_follow_target = null
|
|
|
|
|
|
|
|
|
|
if p_target is Node and "is_movable" in p_target and p_target.is_movable:
|
|
|
|
|
_follow_target = p_target
|
|
|
|
|
|
|
|
|
|
if p_target is Vector2:
|
|
|
|
|
target = p_target
|
|
|
|
|
elif p_target is Array:
|
|
|
|
|
_target = p_target
|
|
|
|
|
elif p_target is Array and p_target.size() > 0:
|
|
|
|
|
var target_pos = Vector2()
|
|
|
|
|
|
|
|
|
|
for obj in p_target:
|
|
|
|
|
target_pos += obj.get_camera_pos()
|
|
|
|
|
|
|
|
|
|
# Let the error in if an empty array was passed (divzero)
|
|
|
|
|
target = target_pos / p_target.size()
|
|
|
|
|
elif p_target is Node and p_target.has_node("camera_pos") and \
|
|
|
|
|
p_target.get_node("camera_pos") is Camera2D:
|
|
|
|
|
target = p_target.get_node("camera_pos").global_position
|
|
|
|
|
zoom_target = p_target.get_node("camera_pos").zoom
|
|
|
|
|
elif p_target is Node and "is_movable" in p_target and p_target.is_movable:
|
|
|
|
|
follow_target = p_target
|
|
|
|
|
elif p_target.has_method("get_camera_pos"):
|
|
|
|
|
target = p_target.get_camera_pos()
|
|
|
|
|
_target = target_pos / p_target.size()
|
|
|
|
|
elif p_target.has_method("get_camera_node"):
|
|
|
|
|
if "global_position" in p_target.get_camera_node():
|
|
|
|
|
_target = p_target.get_camera_node().global_position
|
|
|
|
|
if "zoom" in p_target.get_camera_node():
|
|
|
|
|
_zoom_target = p_target.get_camera_node().zoom
|
|
|
|
|
else:
|
|
|
|
|
target = p_target.global_position
|
|
|
|
|
_target = p_target.global_position
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func set_drag_margin_enabled(p_dm_h_enabled, p_dm_v_enabled):
|
|
|
|
|
@@ -66,147 +83,192 @@ func set_drag_margin_enabled(p_dm_h_enabled, p_dm_v_enabled):
|
|
|
|
|
self.drag_margin_v_enabled = p_dm_v_enabled
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the target for the camera
|
|
|
|
|
#
|
|
|
|
|
# #### Parameters
|
|
|
|
|
# - p_target: Object to target
|
|
|
|
|
# - p_speed: Number of seconds for the camera to reach the target
|
|
|
|
|
func set_target(p_target, p_speed : float = 0.0):
|
|
|
|
|
var speed = p_speed
|
|
|
|
|
|
|
|
|
|
_resolve_target_and_zoom(p_target)
|
|
|
|
|
|
|
|
|
|
if not follow_target == null:
|
|
|
|
|
target = follow_target.global_position
|
|
|
|
|
|
|
|
|
|
escoria.logger.info("Current camera position = " + str(self.global_position))
|
|
|
|
|
escoria.logger.info(
|
|
|
|
|
"Current camera position = %s " % str(self.global_position)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if speed == 0.0:
|
|
|
|
|
self.global_position = target
|
|
|
|
|
self.global_position = _target
|
|
|
|
|
else:
|
|
|
|
|
var time = self.global_position.distance_to(target) / speed
|
|
|
|
|
var time = self.global_position.distance_to(_target) / speed
|
|
|
|
|
|
|
|
|
|
if tween.is_active():
|
|
|
|
|
var tweenstat = String(tween.tell()) + "/" + String(tween.get_runtime())
|
|
|
|
|
escoria.logger.report_warnings("camera.gd:set_target()",
|
|
|
|
|
["Tween still active running camera_set_target: " + tweenstat])
|
|
|
|
|
tween.emit_signal("tween_completed")
|
|
|
|
|
if _tween.is_active():
|
|
|
|
|
escoria.logger.report_warnings(
|
|
|
|
|
"esc_camera.gd:set_target()",
|
|
|
|
|
[
|
|
|
|
|
"Tween is still active: %f/%f" % [
|
|
|
|
|
_tween.tell(),
|
|
|
|
|
_tween.get_runtime()
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
_tween.emit_signal("tween_completed")
|
|
|
|
|
|
|
|
|
|
tween.interpolate_property(
|
|
|
|
|
_tween.interpolate_property(
|
|
|
|
|
self,
|
|
|
|
|
"global_position",
|
|
|
|
|
self.global_position,
|
|
|
|
|
target,
|
|
|
|
|
_target,
|
|
|
|
|
time,
|
|
|
|
|
Tween.TRANS_LINEAR,
|
|
|
|
|
Tween.EASE_IN_OUT
|
|
|
|
|
)
|
|
|
|
|
tween.start()
|
|
|
|
|
_tween.start()
|
|
|
|
|
|
|
|
|
|
func set_camera_zoom(p_zoom_level, p_time):
|
|
|
|
|
|
|
|
|
|
# Set the camera zoom level
|
|
|
|
|
#
|
|
|
|
|
# #### Parameters
|
|
|
|
|
# - p_zoom_level: Zoom level to set
|
|
|
|
|
# - p_time: Number of seconds for the camera to reach the zoom level
|
|
|
|
|
func set_camera_zoom(p_zoom_level: float, p_time: float):
|
|
|
|
|
if p_zoom_level <= 0.0:
|
|
|
|
|
escoria.logger.report_errors("camera.gd:set_camera_zoom()",
|
|
|
|
|
["Tried to set negative or zero zoom level"])
|
|
|
|
|
escoria.logger.report_errors(
|
|
|
|
|
"camera.gd:set_camera_zoom()",
|
|
|
|
|
["Tried to set negative or zero zoom level"]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
zoom_time = p_time
|
|
|
|
|
zoom_target = Vector2(1, 1) * p_zoom_level
|
|
|
|
|
_zoom_target = Vector2(1, 1) * p_zoom_level
|
|
|
|
|
|
|
|
|
|
if zoom_time == 0:
|
|
|
|
|
self.zoom = zoom_target
|
|
|
|
|
if p_time == 0:
|
|
|
|
|
self.zoom = _zoom_target
|
|
|
|
|
else:
|
|
|
|
|
if tween.is_active():
|
|
|
|
|
var tweenstat = String(tween.tell()) + "/" + String(tween.get_runtime())
|
|
|
|
|
escoria.logger.report_warnings("camera",
|
|
|
|
|
["Tween still active running camera_set_zoom: " + tweenstat])
|
|
|
|
|
tween.emit_signal("tween_completed")
|
|
|
|
|
if _tween.is_active():
|
|
|
|
|
escoria.logger.report_warnings(
|
|
|
|
|
"esc_camera.gd:set_camera_zoom()",
|
|
|
|
|
[
|
|
|
|
|
"Tween is still active: %f/%f" % [
|
|
|
|
|
_tween.tell(),
|
|
|
|
|
_tween.get_runtime()
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
_tween.emit_signal("tween_completed")
|
|
|
|
|
|
|
|
|
|
tween.interpolate_property(self, "zoom", self.zoom, zoom_target,
|
|
|
|
|
zoom_time, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
|
|
|
|
|
tween.start()
|
|
|
|
|
_tween.interpolate_property(
|
|
|
|
|
self,
|
|
|
|
|
"zoom",
|
|
|
|
|
self.zoom,
|
|
|
|
|
_zoom_target,
|
|
|
|
|
p_time,
|
|
|
|
|
Tween.TRANS_LINEAR,
|
|
|
|
|
Tween.EASE_IN_OUT
|
|
|
|
|
)
|
|
|
|
|
_tween.start()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func push(p_target, p_time, p_type):
|
|
|
|
|
var time = float(p_time)
|
|
|
|
|
var type = "TRANS_" + p_type
|
|
|
|
|
|
|
|
|
|
# Push the camera towards the target in terms of position and zoom level
|
|
|
|
|
# using a given transition type and time.
|
|
|
|
|
# See
|
|
|
|
|
# https://docs.godotengine.org/en/stable/classes/class_tween.html#enumerations
|
|
|
|
|
#
|
|
|
|
|
# #### Parameters
|
|
|
|
|
# - p_target: Target to push to
|
|
|
|
|
# - p_time: Number of seconds for the transition to take
|
|
|
|
|
# - p_type: Tween transition type
|
|
|
|
|
func push(p_target, p_time: float = 0.0, p_type: int = 0):
|
|
|
|
|
_resolve_target_and_zoom(p_target)
|
|
|
|
|
|
|
|
|
|
var push_target = null
|
|
|
|
|
|
|
|
|
|
if follow_target != null:
|
|
|
|
|
if _follow_target != null:
|
|
|
|
|
push_target = p_target.position
|
|
|
|
|
else:
|
|
|
|
|
push_target = target
|
|
|
|
|
push_target = _target
|
|
|
|
|
|
|
|
|
|
if time == 0:
|
|
|
|
|
if p_time == 0:
|
|
|
|
|
self.global_position = push_target
|
|
|
|
|
if zoom_target != Vector2():
|
|
|
|
|
self.zoom = zoom_target
|
|
|
|
|
if _zoom_target != Vector2():
|
|
|
|
|
self.zoom = _zoom_target
|
|
|
|
|
else:
|
|
|
|
|
if tween.is_active():
|
|
|
|
|
var tweenstat = String(tween.tell()) + "/" + String(tween.get_runtime())
|
|
|
|
|
escoria.logger.report_warnings("camera",
|
|
|
|
|
["Tween still active running camera_push: " + tweenstat])
|
|
|
|
|
tween.emit_signal("tween_completed", null, null)
|
|
|
|
|
if _tween.is_active():
|
|
|
|
|
escoria.logger.report_warnings(
|
|
|
|
|
"esc_camera.gd:push()",
|
|
|
|
|
[
|
|
|
|
|
"Tween is still active:" % [
|
|
|
|
|
_tween.tell(),
|
|
|
|
|
_tween.get_runtime()
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
_tween.emit_signal("tween_completed", null, null)
|
|
|
|
|
|
|
|
|
|
if zoom_target != Vector2():
|
|
|
|
|
tween.interpolate_property(
|
|
|
|
|
if _zoom_target != Vector2():
|
|
|
|
|
_tween.interpolate_property(
|
|
|
|
|
self,
|
|
|
|
|
"zoom",
|
|
|
|
|
self.zoom,
|
|
|
|
|
zoom_target,
|
|
|
|
|
time,
|
|
|
|
|
tween.get(type),
|
|
|
|
|
_zoom_target,
|
|
|
|
|
p_time,
|
|
|
|
|
p_type,
|
|
|
|
|
Tween.EASE_IN_OUT
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
tween.interpolate_property(
|
|
|
|
|
_tween.interpolate_property(
|
|
|
|
|
self,
|
|
|
|
|
"global_position",
|
|
|
|
|
self.global_position,
|
|
|
|
|
push_target,
|
|
|
|
|
time,
|
|
|
|
|
tween.get(type),
|
|
|
|
|
p_time,
|
|
|
|
|
p_type,
|
|
|
|
|
Tween.EASE_IN_OUT
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
tween.start()
|
|
|
|
|
_tween.start()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func shift(p_x, p_y, p_time, p_type):
|
|
|
|
|
follow_target = null
|
|
|
|
|
var x = int(p_x)
|
|
|
|
|
var y = int(p_y)
|
|
|
|
|
var time = float(p_time)
|
|
|
|
|
var type = "TRANS_" + p_type
|
|
|
|
|
# Shift the camera by the given vector in a given time and using a specific
|
|
|
|
|
# Tween transition type.
|
|
|
|
|
#
|
|
|
|
|
# See
|
|
|
|
|
# https://docs.godotengine.org/en/stable/classes/class_tween.html#enumerations
|
|
|
|
|
#
|
|
|
|
|
# #### Parameters
|
|
|
|
|
# - p_target: Vector to shift the camera by
|
|
|
|
|
# - p_time: Number of seconds for the transition to take
|
|
|
|
|
# - p_type: Tween transition type
|
|
|
|
|
func shift(p_target: Vector2, p_time: float, p_type: int):
|
|
|
|
|
_follow_target = null
|
|
|
|
|
|
|
|
|
|
var new_pos = self.global_position + Vector2(x, y)
|
|
|
|
|
target = new_pos
|
|
|
|
|
var new_pos = self.global_position + p_target
|
|
|
|
|
_target = new_pos
|
|
|
|
|
|
|
|
|
|
if tween.is_active():
|
|
|
|
|
var tweenstat = String(tween.tell()) + "/" + String(tween.get_runtime())
|
|
|
|
|
escoria.logger.report_warnings("camera",
|
|
|
|
|
["Tween still active running camera_shift: " + tweenstat])
|
|
|
|
|
tween.emit_signal("tween_completed")
|
|
|
|
|
if _tween.is_active():
|
|
|
|
|
escoria.logger.report_warnings(
|
|
|
|
|
"esc_camera.gd:set_camera_zoom()",
|
|
|
|
|
[
|
|
|
|
|
"Tween is still active: %f/%f" % [
|
|
|
|
|
_tween.tell(),
|
|
|
|
|
_tween.get_runtime()
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
_tween.emit_signal("tween_completed")
|
|
|
|
|
|
|
|
|
|
tween.interpolate_property(self, "global_position", self.global_position,
|
|
|
|
|
new_pos, float(time), tween.get(type), Tween.EASE_IN_OUT)
|
|
|
|
|
tween.start()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func target_reached():
|
|
|
|
|
tween.stop_all()
|
|
|
|
|
|
|
|
|
|
func _process(_delta):
|
|
|
|
|
zoom_transform = self.get_canvas_transform()
|
|
|
|
|
|
|
|
|
|
if is_instance_valid(follow_target) and not tween.is_active() and follow_target.has_moved():
|
|
|
|
|
self.global_position = follow_target.global_position
|
|
|
|
|
|
|
|
|
|
func _ready():
|
|
|
|
|
tween = Tween.new()
|
|
|
|
|
add_child(tween)
|
|
|
|
|
tween.connect("tween_all_completed", self, "target_reached")
|
|
|
|
|
escoria.object_manager.register_object(
|
|
|
|
|
ESCObject.new(
|
|
|
|
|
"_camera",
|
|
|
|
|
self
|
|
|
|
|
),
|
|
|
|
|
true
|
|
|
|
|
_tween.interpolate_property(
|
|
|
|
|
self,
|
|
|
|
|
"global_position",
|
|
|
|
|
self.global_position,
|
|
|
|
|
new_pos,
|
|
|
|
|
p_time,
|
|
|
|
|
p_type,
|
|
|
|
|
Tween.EASE_IN_OUT
|
|
|
|
|
)
|
|
|
|
|
_tween.start()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _target_reached():
|
|
|
|
|
_tween.stop_all()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|