@tool extends Node #### Timer func wait(duration: float) -> void: if duration <= 0: return await get_tree().create_timer(duration).timeout func timer(duration: float, callable: Callable) -> SceneTreeTimer: var t = get_tree().create_timer(duration, false) t.timeout.connect(callable) return t #### Canvas func shake_layer(layer: CanvasLayer, duration: float, delta := 2.0, fps := 20.0) -> void: var tween = layer.create_tween() # shake layer's offset var origin_offset = layer.offset var count = int(duration * fps) var delta_t = 1.0 / fps for i in range(count): var offset = Vector2(randf_range(-delta, delta), randf_range(-delta, delta)) tween.tween_property(layer, "offset", origin_offset + offset, delta_t) # tween back to origin tween.tween_property(layer, "offset", origin_offset, delta_t) ###### Dialogue func concact_content_from_lines(lines := []): if lines.is_empty(): return "" var content = "" for i in range(len(lines) - 1): var line = lines[i] as DialogueLine content += TranslationServer.tr(line.translation_key) + "\n" # last line without "\n" content += TranslationServer.tr(lines[-1].translation_key) return content func get_lines(res: DialogueResource, title: String) -> Array: var lines = [] var current_line = await res.get_next_dialogue_line(title) while current_line: lines.append(current_line) if current_line.next_id != "end": current_line = await res.get_next_dialogue_line(current_line.next_id) else: break return lines # pop os lines func generate_lines(content: String) -> Array: var text = "~ title\n" + content + "\n=> END" var res = DialogueManager.create_resource_from_text(text) return await get_lines(res, "title") #### Geometry # This function finds the closest point on the boundary or inside of a polygon # to a given point. # # @param point: The Vector2 point to test against. # @param polygon_vertices: A PackedVector2Array defining the polygon. # @return: The Vector2 coordinate of the closest point. func get_closest_point_on_polygon(point: Vector2, polygon_vertices: PackedVector2Array) -> Vector2: var vertex_count = polygon_vertices.size() if vertex_count == 0: return Vector2.ZERO # Or handle error appropriately if vertex_count == 1: return polygon_vertices[0] # First, check if the point is already inside the polygon. # If so, the point itself is the answer. if Geometry2D.is_point_in_polygon(point, polygon_vertices): return point # If the point is outside, we need to find the closest point on its edges. var closest_point_so_far: Vector2 var min_dist_sq = INF # Use infinity as the initial maximum distance # Iterate through each edge of the polygon. for i in range(vertex_count): # An edge is a segment between the current vertex and the next one. # The modulo operator (%) handles the last edge connecting the last vertex to the first. var p1 = polygon_vertices[i] var p2 = polygon_vertices[(i + 1) % vertex_count] # Get the closest point on the current line segment. var closest_point_on_segment = Geometry2D.get_closest_point_to_segment(point, p1, p2) # Calculate the squared distance. This is more efficient than using sqrt(). var dist_sq = point.distance_squared_to(closest_point_on_segment) # If this point is closer than any we've seen before, update our variables. if dist_sq < min_dist_sq: min_dist_sq = dist_sq closest_point_so_far = closest_point_on_segment return closest_point_so_far