Last active
July 22, 2024 13:12
-
-
Save Shilo/812c6ac61059e37d91af0132cf5055f6 to your computer and use it in GitHub Desktop.
Dynamic circle polygon shape with start and end angles. (Godot 4)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@tool | |
class_name Circle2D extends Polygon2D | |
@export_range(0.0, 360.0, 0.001, "or_greater", "or_less") var start_degree: float = 0.0: | |
set(value): | |
start_degree = _wrap_degree(value) | |
queue_update() | |
@export_range(0.0, 360.0, 0.001, "or_greater", "or_less") var end_degree: float = 360.0: | |
set(value): | |
end_degree = _wrap_degree(value) | |
queue_update() | |
@export_range(0.0, 1_000.0, 0.001, "or_greater") var radius: float = 50.0: | |
set(value): | |
radius = value | |
queue_update() | |
@export_range(3, 1_000.0) var circle_segments: int = 64: | |
set(value): | |
circle_segments = value | |
queue_update() | |
@export var border_line_2d: Line2D: | |
set(value): | |
border_line_2d = value | |
if border_line_2d: | |
queue_update() | |
var segments: int: | |
get: | |
return max(ceili(circle_segments * (abs(degree) / 360.0)), 1) | |
var degree: float: | |
get: | |
return end_degree - start_degree | |
var angle: float: | |
get: | |
return deg_to_rad(degree) | |
var start_angle: float: | |
get: | |
return deg_to_rad(start_degree) | |
var end_angle: float: | |
get: | |
return deg_to_rad(end_degree) | |
var _pending_update: bool = false | |
func _ready() -> void: | |
queue_update() | |
func queue_update() -> void: | |
if _pending_update: | |
return | |
_pending_update = true | |
_update.call_deferred() | |
func _update() -> void: | |
var points := PackedVector2Array() | |
points.resize(segments + 2) | |
points[0] = Vector2.ZERO | |
var angle_step: float = angle / segments | |
var initial_angle: float = start_angle | |
for point_index in segments + 1: | |
var point_angle: float = initial_angle + angle_step * point_index | |
points[point_index + 1] = Vector2(cos(point_angle) * radius, sin(point_angle) * radius) | |
polygon = points | |
if border_line_2d: | |
border_line_2d.closed = true | |
border_line_2d.points = polygon | |
_pending_update = false | |
func _wrap_degree(deg: float) -> float: | |
if deg < 0.0: | |
deg = fposmod(deg, 360.0) | |
elif degree > 360.0: | |
deg = fmod(deg, 360.0) | |
return deg |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment