scatter chart feature complete

This commit is contained in:
fenix-hub 2023-01-11 23:09:45 +01:00
parent 38225536d1
commit 274c32f15e
7 changed files with 97 additions and 126 deletions

View File

@ -2,7 +2,11 @@ extends Chart
class_name ScatterChart class_name ScatterChart
signal point_entered(point) signal point_entered(point)
signal point_exited(point)
var focused_point: Point = null
var points: Array = []
var _point_box_rad: int = 10
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
@ -20,16 +24,76 @@ func plot(x: Array, y: Array, drawing_options: DrawingOptions = null, chart_prop
update() update()
func _clear_points() -> void:
points = []
func _get_point_box(point: Point, rad: int) -> Rect2:
return Rect2(point.position - (Vector2.ONE * rad), (Vector2.ONE * rad * 2))
func _move_tooltip(position: Vector2) -> void:
$Label.set_position(position + (Vector2.ONE * 15))
func _show_tooltip(position: Vector2, text: String) -> void:
_move_tooltip(position)
$Label.show()
$Label.set_text(text)
$Label.set_size(Vector2.ZERO)
func _hide_tooltip() -> void:
$Label.hide()
$Label.set_text("")
$Label.set_size(Vector2.ZERO)
func _input(event: InputEvent):
if event is InputEventMouse:
for point in points:
if _get_point_box(point, _point_box_rad).abs().has_point(event.position):
if focused_point == point:
_move_tooltip(event.position)
return
else:
focused_point = point
_show_tooltip(event.position, str(focused_point.value))
emit_signal("point_entered", point)
return
# Mouse is not in any point's box
focused_point = null
_hide_tooltip()
func _draw_point(point: Point, function_index: int) -> void: func _draw_point(point: Point, function_index: int) -> void:
var point_container: PointContainer = point_container_scene.instance() points.append(point)
$Points.add_child(point_container)
point_container.set_point( match drawing_options.get_point_shape(function_index):
point, Point.Shape.CIRCLE:
drawing_options.get_function_color(function_index), draw_circle(point.position, drawing_options.point_radius, drawing_options.get_function_color(function_index))
drawing_options.get_point_shape(function_index) Point.Shape.SQUARE:
) draw_rect(_get_point_box(point, drawing_options.point_radius), drawing_options.get_function_color(function_index), true, 1.0, false)
point_container.connect("point_entered", self, "_on_point_entered") Point.Shape.TRIANGLE:
point_container.connect("point_exited", self, "_on_point_exited") draw_colored_polygon(
PoolVector2Array([
point.position + (Vector2.UP * drawing_options.point_radius * 1.3),
point.position + (Vector2.ONE * drawing_options.point_radius * 1.3),
point.position - (Vector2(1, -1) * drawing_options.point_radius * 1.3)
]), drawing_options.get_function_color(function_index), [], null, null, false
)
Point.Shape.CROSS:
draw_line(
point.position - (Vector2.ONE * drawing_options.point_radius),
point.position + (Vector2.ONE * drawing_options.point_radius),
drawing_options.get_function_color(function_index), drawing_options.point_radius, true
)
draw_line(
point.position + (Vector2(1, -1) * drawing_options.point_radius),
point.position + (Vector2(-1, 1) * drawing_options.point_radius),
drawing_options.get_function_color(function_index), drawing_options.point_radius / 2, true
)
# # (debug)
# draw_rect(
# _get_point_box(point, _point_box_rad),
# Color.red,
# false, 1, true
# )
func _draw_points() -> void: func _draw_points() -> void:
var validation: int = _validate_sampled_axis(x_sampled, y_sampled) var validation: int = _validate_sampled_axis(x_sampled, y_sampled)
@ -50,9 +114,3 @@ func _draw_points() -> void:
var sampled_point_pos: Vector2 = Vector2(x_sampled.values[i], y_sampled.values[i]) var sampled_point_pos: Vector2 = Vector2(x_sampled.values[i], y_sampled.values[i])
var point: Point = Point.news(sampled_point_pos, real_point_val) var point: Point = Point.news(sampled_point_pos, real_point_val)
_draw_point(point, i) _draw_point(point, i)
func _on_point_entered(point: Point) -> void:
emit_signal("point_entered", point)
func _on_point_exited(point: Point) -> void:
emit_signal("point_exited", point)

View File

@ -1,7 +1,10 @@
[gd_scene load_steps=2 format=2] [gd_scene load_steps=3 format=2]
[ext_resource path="res://addons/easy_charts/control_charts/ScatterChart/scatter_chart.gd" type="Script" id=1] [ext_resource path="res://addons/easy_charts/control_charts/ScatterChart/scatter_chart.gd" type="Script" id=1]
[sub_resource type="StyleBoxFlat" id=1]
bg_color = Color( 1, 1, 1, 1 )
[node name="ScatterChart" type="Control"] [node name="ScatterChart" type="Control"]
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
@ -10,13 +13,13 @@ __meta__ = {
"_edit_use_anchors_": true "_edit_use_anchors_": true
} }
[node name="Points" type="Control" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
__meta__ = {
"_edit_use_anchors_": true
}
[node name="Canvas" type="Control" parent="."] [node name="Canvas" type="Control" parent="."]
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
[node name="Label" type="Label" parent="."]
visible = false
margin_right = 40.0
margin_bottom = 14.0
custom_colors/font_color = Color( 0, 0, 0, 1 )
custom_styles/normal = SubResource( 1 )

View File

@ -47,10 +47,6 @@ var _x_ticklabel_size: Vector2 # offset only on the X axis
var _x_ticklabel_offset: int = 5 # offset only on the X axis var _x_ticklabel_offset: int = 5 # offset only on the X axis
var _x_tick_size: int = 7 var _x_tick_size: int = 7
var point_container_scene: PackedScene = preload("res://addons/easy_charts/utilities/containers/point_container/point_container.tscn")
########### ###########
func plot(x: Array, y: Array, drawing_options: DrawingOptions = DrawingOptions.new(), chart_properties: ChartProperties = ChartProperties.new()) -> void: func plot(x: Array, y: Array, drawing_options: DrawingOptions = DrawingOptions.new(), chart_properties: ChartProperties = ChartProperties.new()) -> void:
pass pass
@ -342,8 +338,9 @@ func _draw_title() -> void:
) )
func _clear_points() -> void: func _clear_points() -> void:
for point in $Points.get_children(): pass
point.queue_free() # for point in $Points.get_children():
# point.queue_free()
func _clear_canvas_labels() -> void: func _clear_canvas_labels() -> void:
for label in $Canvas.get_children(): for label in $Canvas.get_children():

View File

@ -16,7 +16,7 @@ var colors: Dictionary = {
functions = [Color.red, Color.green, Color.blue, Color.black] functions = [Color.red, Color.green, Color.blue, Color.black]
} }
var shapes: Array = [PointContainer.PointShape.CIRCLE, PointContainer.PointShape.SQUARE, PointContainer.PointShape.TRIANGLE, PointContainer.PointShape.CROSS] var shapes: Array = [Point.Shape.CIRCLE, Point.Shape.SQUARE, Point.Shape.TRIANGLE, Point.Shape.CROSS]
var point_radius: float = 3.0 var point_radius: float = 3.0
var font: BitmapFont = Label.new().get_font("") var font: BitmapFont = Label.new().get_font("")
@ -24,4 +24,4 @@ func get_function_color(function_index: int) -> Color:
return colors.functions[function_index] if function_index < colors.functions.size() else Color.black return colors.functions[function_index] if function_index < colors.functions.size() else Color.black
func get_point_shape(function_index: int) -> int: func get_point_shape(function_index: int) -> int:
return shapes[function_index] if function_index < shapes.size() else PointContainer.PointShape.CIRCLE return shapes[function_index] if function_index < shapes.size() else Point.Shape.CIRCLE

View File

@ -2,6 +2,13 @@ tool
extends Reference extends Reference
class_name Point class_name Point
enum Shape {
CIRCLE,
TRIANGLE,
SQUARE,
CROSS
}
var position: Vector2 var position: Vector2
var value: Pair var value: Pair

View File

@ -1,81 +0,0 @@
extends Control
class_name PointContainer
signal point_entered(point)
signal point_exited(point)
enum PointShape {
CIRCLE,
TRIANGLE,
SQUARE,
CROSS
}
var point: Point
var color: Color
var radius: float
var shape: int
var label: String
func _ready():
pass
func set_point(point: Point, color: Color = Color.black, shape: int = PointShape.CIRCLE, radius: float = 3.0) -> void:
self.point = point
self.color = color
self.shape = shape
self.radius = radius
auto_pos(self.point.position)
func auto_pos(pos: Vector2) -> void:
self.rect_position += pos
func _draw_bounding_box() -> void:
var t_gr: Rect2 = get_global_rect()
draw_rect(Rect2(Vector2.ZERO, get_rect().size), Color.black, false, 1, true)
func _draw_label() -> void:
var lbl: Label = Label.new()
add_child(lbl)
lbl.rect_position += self.rect_size
lbl.text = str(label)
func _draw_point() -> void:
var point_rel_pos: Vector2 = self.rect_size * 0.5
match self.shape:
PointShape.CIRCLE:
draw_circle(point_rel_pos, self.radius, self.color)
PointShape.SQUARE:
draw_rect(Rect2(point_rel_pos * 0.5, point_rel_pos), self.color, true, 1.0, false)
PointShape.TRIANGLE:
draw_colored_polygon(
PoolVector2Array([
point_rel_pos + (Vector2.UP * self.radius * 1.5),
point_rel_pos + (Vector2.ONE * self.radius * 1.5),
point_rel_pos - (Vector2(1, -1) * self.radius * 1.5)
]), self.color, [], null, null, false
)
PointShape.CROSS:
draw_line(
point_rel_pos - (Vector2.ONE * self.radius),
point_rel_pos + (Vector2.ONE * self.radius),
self.color, self.radius, true
)
draw_line(
point_rel_pos + (Vector2(1, -1) * self.radius),
point_rel_pos + (Vector2(-1, 1) * self.radius),
self.color, self.radius / 2, true
)
func _draw():
# _draw_bounding_box()
_draw_point()
# _draw_label()
func _on_PointContainer_mouse_entered():
emit_signal("point_entered", self.point)
func _on_PointContainer_mouse_exited():
emit_signal("point_exited", self.point)

View File

@ -1,13 +0,0 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/easy_charts/utilities/containers/point_container/point_container.gd" type="Script" id=1]
[node name="PointContainer" type="Control"]
margin_left = -8.0
margin_top = -8.0
margin_right = 8.0
margin_bottom = 8.0
script = ExtResource( 1 )
[connection signal="mouse_entered" from="." to="." method="_on_PointContainer_mouse_entered"]
[connection signal="mouse_exited" from="." to="." method="_on_PointContainer_mouse_exited"]