Add lever and jump pad components with activation logic
This commit is contained in:
208
addons/rmsmartshape/shapes/shape_anchor.gd
Normal file
208
addons/rmsmartshape/shapes/shape_anchor.gd
Normal file
@@ -0,0 +1,208 @@
|
||||
@tool
|
||||
@icon("../assets/Anchor.svg")
|
||||
extends Node2D
|
||||
class_name SS2D_Shape_Anchor
|
||||
|
||||
const DEBUG_DRAW_LINE_LENGTH := 128.0
|
||||
|
||||
@export var shape_path: NodePath : set = set_shape_path
|
||||
@export var shape_point_index: int = 0 : set = set_shape_point_index
|
||||
@export_range (0.0, 1.0) var shape_point_offset: float = 0.0 : set = set_shape_point_offset
|
||||
@export_range (0, 3.14) var child_rotation: float = 3.14 : set = set_child_rotation
|
||||
@export var use_shape_scale: bool = false : set = set_use_shape_scale
|
||||
|
||||
@export var debug_draw: bool = false : set = set_debug_draw
|
||||
|
||||
var cached_shape_transform: Transform2D = Transform2D.IDENTITY
|
||||
var shape: SS2D_Shape = null
|
||||
|
||||
|
||||
###########
|
||||
#-SETTERS-#
|
||||
###########
|
||||
|
||||
func set_shape_path(value: NodePath) -> void:
|
||||
# Assign path value
|
||||
shape_path = value
|
||||
set_shape()
|
||||
|
||||
notify_property_list_changed()
|
||||
refresh()
|
||||
|
||||
|
||||
func set_shape() -> void:
|
||||
# Disconnect old shape
|
||||
if shape != null:
|
||||
disconnect_shape(shape)
|
||||
|
||||
# Set shape if path is valid and connect
|
||||
shape = null
|
||||
if has_node(shape_path):
|
||||
var new_node: Node = get_node(shape_path)
|
||||
if not new_node is SS2D_Shape:
|
||||
push_error("Shape Path isn't a valid subtype of SS2D_Shape! Aborting...")
|
||||
return
|
||||
shape = new_node
|
||||
connect_shape(shape)
|
||||
shape_point_index = get_shape_index_range(shape, shape_point_index)
|
||||
|
||||
|
||||
func get_shape_index_range(s: SS2D_Shape, idx: int) -> int:
|
||||
var point_count: int = s.get_point_count()
|
||||
# Subtract 2;
|
||||
# 'point_count' is out of bounds; subtract 1
|
||||
# cannot use final idx as starting point_index; subtract another 1
|
||||
var final_idx: int = point_count - 2
|
||||
if idx < 0:
|
||||
idx = final_idx
|
||||
idx = idx % (final_idx + 1)
|
||||
return idx
|
||||
|
||||
|
||||
func set_shape_point_index(value: int) -> void:
|
||||
if value == shape_point_index:
|
||||
return
|
||||
|
||||
if shape == null:
|
||||
shape_point_index = value
|
||||
return
|
||||
|
||||
shape_point_index = get_shape_index_range(shape, value)
|
||||
#notify_property_list_changed()
|
||||
refresh()
|
||||
|
||||
|
||||
func set_shape_point_offset(value: float) -> void:
|
||||
shape_point_offset = value
|
||||
#notify_property_list_changed()
|
||||
refresh()
|
||||
|
||||
|
||||
func set_use_shape_scale(value: bool) -> void:
|
||||
use_shape_scale = value
|
||||
#notify_property_list_changed()
|
||||
refresh()
|
||||
|
||||
|
||||
func set_child_rotation(value: float) -> void:
|
||||
child_rotation = value
|
||||
#notify_property_list_changed()
|
||||
refresh()
|
||||
|
||||
|
||||
func set_debug_draw(v: bool) -> void:
|
||||
debug_draw = v
|
||||
#notify_property_list_changed()
|
||||
refresh()
|
||||
|
||||
|
||||
##########
|
||||
#-EVENTS-#
|
||||
##########
|
||||
func _process(_delta: float) -> void:
|
||||
if shape == null:
|
||||
set_shape()
|
||||
return
|
||||
if shape.is_queued_for_deletion():
|
||||
return
|
||||
if shape.get_global_transform() != cached_shape_transform:
|
||||
cached_shape_transform = shape.get_global_transform()
|
||||
refresh()
|
||||
|
||||
|
||||
func _monitored_node_leaving() -> void:
|
||||
pass
|
||||
|
||||
|
||||
func _handle_point_change() -> void:
|
||||
refresh()
|
||||
|
||||
|
||||
#########
|
||||
#LOGIC-#
|
||||
#########
|
||||
func _cubic_bezier(p0: Vector2, p1: Vector2, p2: Vector2, p3: Vector2, t: float) -> Vector2:
|
||||
var q0 := p0.lerp(p1, t)
|
||||
var q1 := p1.lerp(p2, t)
|
||||
var q2 := p2.lerp(p3, t)
|
||||
|
||||
var r0 := q0.lerp(q1, t)
|
||||
var r1 := q1.lerp(q2, t)
|
||||
|
||||
var s := r0.lerp(r1, t)
|
||||
return s
|
||||
|
||||
|
||||
func disconnect_shape(s: SS2D_Shape) -> void:
|
||||
s.disconnect("points_modified", self._handle_point_change)
|
||||
s.disconnect("tree_exiting", self._monitored_node_leaving)
|
||||
|
||||
|
||||
func connect_shape(s: SS2D_Shape) -> void:
|
||||
s.connect("points_modified", self._handle_point_change)
|
||||
s.connect("tree_exiting", self._monitored_node_leaving)
|
||||
|
||||
|
||||
func refresh() -> void:
|
||||
if shape == null:
|
||||
return
|
||||
if not is_instance_valid(shape):
|
||||
return
|
||||
if shape.is_queued_for_deletion():
|
||||
disconnect_shape(shape)
|
||||
shape = null
|
||||
return
|
||||
|
||||
# Subtract one, cannot use final point as starting index
|
||||
# var point_count: int = shape.get_point_count() - 1
|
||||
|
||||
var pt_a_index: int = shape_point_index
|
||||
var pt_b_index: int = shape_point_index + 1
|
||||
var pt_a_key: int = shape.get_point_key_at_index(pt_a_index)
|
||||
var pt_b_key: int = shape.get_point_key_at_index(pt_b_index)
|
||||
|
||||
var pt_a: Vector2 = shape.global_transform * shape.get_point_position(pt_a_key)
|
||||
var pt_b: Vector2 = shape.global_transform * shape.get_point_position(pt_b_key)
|
||||
|
||||
var pt_a_handle: Vector2
|
||||
var pt_b_handle: Vector2
|
||||
|
||||
var n_pt: Vector2
|
||||
var n_pt_a: Vector2
|
||||
var n_pt_b: Vector2
|
||||
|
||||
var angle := 0.0
|
||||
|
||||
pt_a_handle = shape.global_transform * (
|
||||
shape.get_point_position(pt_a_key) + shape.get_point_out(pt_a_key)
|
||||
)
|
||||
pt_b_handle = shape.global_transform * (
|
||||
shape.get_point_position(pt_b_key) + shape.get_point_in(pt_b_key)
|
||||
)
|
||||
|
||||
# If this segment uses no bezier curve, use linear interpolation instead
|
||||
if pt_a_handle != pt_a or pt_b_handle != pt_b:
|
||||
n_pt = _cubic_bezier(pt_a, pt_a_handle, pt_b_handle, pt_b, shape_point_offset)
|
||||
else:
|
||||
n_pt = pt_a.lerp(pt_b, shape_point_offset)
|
||||
|
||||
n_pt_a = _cubic_bezier(
|
||||
pt_a, pt_a_handle, pt_b_handle, pt_b, clampf(shape_point_offset - 0.1, 0.0, 1.0)
|
||||
)
|
||||
n_pt_b = _cubic_bezier(
|
||||
pt_a, pt_a_handle, pt_b_handle, pt_b, clampf(shape_point_offset + 0.1, 0.0, 1.0)
|
||||
)
|
||||
|
||||
angle = atan2(n_pt_a.y - n_pt_b.y, n_pt_a.x - n_pt_b.x)
|
||||
|
||||
self.global_transform = Transform2D(angle + child_rotation, n_pt)
|
||||
|
||||
if use_shape_scale:
|
||||
self.scale = shape.scale
|
||||
|
||||
queue_redraw()
|
||||
|
||||
|
||||
func _draw() -> void:
|
||||
if Engine.is_editor_hint() and debug_draw:
|
||||
draw_line(Vector2.ZERO, Vector2(0, -DEBUG_DRAW_LINE_LENGTH), self.modulate)
|
||||
Reference in New Issue
Block a user