Skip to content

Instantly share code, notes, and snippets.

@Shilo
Last active July 22, 2024 13:12
Show Gist options
  • Save Shilo/812c6ac61059e37d91af0132cf5055f6 to your computer and use it in GitHub Desktop.
Save Shilo/812c6ac61059e37d91af0132cf5055f6 to your computer and use it in GitHub Desktop.
Dynamic circle polygon shape with start and end angles. (Godot 4)
@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