└── addons
└── easy_charts
├── control_charts
├── chart.gd
├── chart.gd.uid
├── chart.tscn
├── domain
│ ├── chart_axis_domain.gd
│ └── chart_axis_domain.gd.uid
└── plotters
│ ├── area_plotter.gd
│ ├── area_plotter.gd.uid
│ ├── bar_plotter.gd
│ ├── bar_plotter.gd.uid
│ ├── function_plotter.gd
│ ├── function_plotter.gd.uid
│ ├── line_plotter.gd
│ ├── line_plotter.gd.uid
│ ├── pie_plotter.gd
│ ├── pie_plotter.gd.uid
│ ├── scatter_plotter.gd
│ └── scatter_plotter.gd.uid
├── examples
├── area_chart
│ ├── area_chart_example.gd
│ ├── area_chart_example.gd.uid
│ └── area_chart_example.tscn
├── bar_chart
│ ├── bar_chart_example.gd
│ ├── bar_chart_example.gd.uid
│ └── bar_chart_example.tscn
├── line_chart
│ ├── line_chart_example.gd
│ ├── line_chart_example.gd.uid
│ └── line_chart_example.tscn
├── multiplot
│ ├── multiplot_example.gd
│ ├── multiplot_example.gd.uid
│ └── multiplot_example.tscn
├── pie_chart
│ ├── pie_chart_example.gd
│ ├── pie_chart_example.gd.uid
│ └── pie_chart_example.tscn
├── scatter_chart
│ ├── scatter_chart_example.gd
│ ├── scatter_chart_example.gd.uid
│ └── scatter_chart_example.tscn
├── scatter_chart_discrete
│ ├── scatter_chart_discrete.gd
│ ├── scatter_chart_discrete.gd.uid
│ └── scatter_chart_discrete.tscn
└── simple_chart
│ ├── simple_chart_example.gd
│ ├── simple_chart_example.gd.uid
│ └── simple_chart_example.tscn
├── icon.svg
├── plugin.cfg
├── plugin.gd
├── plugin.gd.uid
├── templates.json
└── utilities
├── assets
└── OpenSans-VariableFont_wdth,wght.ttf
├── classes
├── plotting
│ ├── bar.gd
│ ├── bar.gd.uid
│ ├── chart_properties.gd
│ ├── chart_properties.gd.uid
│ ├── function.gd
│ ├── function.gd.uid
│ ├── point.gd
│ └── point.gd.uid
└── structures
│ ├── array_operations.gd
│ ├── array_operations.gd.uid
│ ├── data_frame.gd
│ ├── data_frame.gd.uid
│ ├── matrix.gd
│ ├── matrix.gd.uid
│ ├── matrix_generator.gd
│ └── matrix_generator.gd.uid
├── containers
├── canvas
│ ├── canvas.gd
│ ├── canvas.gd.uid
│ └── plot_box
│ │ ├── grid_box.gd
│ │ ├── grid_box.gd.uid
│ │ ├── plot_box.gd
│ │ └── plot_box.gd.uid
├── data_tooltip
│ ├── data_tooltip.gd
│ ├── data_tooltip.gd.uid
│ └── data_tooltip.tscn
└── legend
│ ├── function_label.gd
│ ├── function_label.gd.uid
│ ├── function_label.tscn
│ ├── function_legend.gd
│ ├── function_legend.gd.uid
│ ├── function_legend.tscn
│ ├── function_type.gd
│ └── function_type.gd.uid
├── icons
└── linechart.svg
└── scripts
├── ec_utilities.gd
└── ec_utilities.gd.uid
/addons/easy_charts/control_charts/chart.gd:
--------------------------------------------------------------------------------
1 | @icon("res://addons/easy_charts/utilities/icons/linechart.svg")
2 | extends PanelContainer
3 | class_name Chart
4 |
5 | @onready var _canvas: Canvas = $Canvas
6 | @onready var plot_box: PlotBox = %PlotBox
7 | @onready var grid_box: GridBox = %GridBox
8 | @onready var functions_box: Control = %FunctionsBox
9 | @onready var function_legend: FunctionLegend = %FunctionLegend
10 |
11 | @onready var _tooltip: DataTooltip = %Tooltip
12 | var _function_of_tooltip: Function = null
13 |
14 | var functions: Array = []
15 | var x: Array = []
16 | var y: Array = []
17 |
18 | var x_labels_function: Callable = Callable()
19 | var y_labels_function: Callable = Callable()
20 |
21 | var x_domain: ChartAxisDomain = null
22 | var y_domain: ChartAxisDomain = null
23 |
24 | var chart_properties: ChartProperties = null
25 |
26 | ###########
27 |
28 | func _ready() -> void:
29 | if theme == null:
30 | theme = Theme.new()
31 |
32 | func plot(functions: Array[Function], properties: ChartProperties = ChartProperties.new()) -> void:
33 | self.functions = functions
34 | self.chart_properties = properties
35 |
36 | theme.set("default_font", self.chart_properties.font)
37 | _canvas.prepare_canvas(self.chart_properties)
38 | plot_box.chart_properties = self.chart_properties
39 | function_legend.chart_properties = self.chart_properties
40 |
41 | load_functions(functions)
42 |
43 | func load_functions(functions: Array[Function]) -> void:
44 | self.x = []
45 | self.y = []
46 |
47 | function_legend.clear()
48 |
49 | # Remove existing function_plotters
50 | for function_plotter in functions_box.get_children():
51 | functions_box.remove_child(function_plotter)
52 | function_plotter.queue_free()
53 |
54 | for function in functions:
55 | # Load x and y values
56 | self.x.append(function.__x)
57 | self.y.append(function.__y)
58 |
59 | # Create FunctionPlotter
60 | var function_plotter := FunctionPlotter.create_for_function(function)
61 | function_plotter.point_entered.connect(_show_tooltip)
62 | function_plotter.point_exited.connect(_hide_tooltip)
63 | functions_box.add_child(function_plotter)
64 |
65 | # Create legend
66 | match function.get_type():
67 | Function.Type.PIE:
68 | for i in function.__x.size():
69 | var interp_color: Color = function.get_gradient().sample(float(i) / float(function.__x.size()))
70 | function_legend.add_label(function.get_type(), interp_color, Function.Marker.NONE, function.__y[i])
71 | _:
72 | function_legend.add_function(function)
73 |
74 | func _draw() -> void:
75 | if (x.size() == 0) or (y.size() == 0) or (x.size() == 1 and x[0].is_empty()) or (y.size() == 1 and y[0].is_empty()):
76 | printerr("Cannot plot an empty function!")
77 | return
78 |
79 | var is_x_fixed: bool = x_domain != null && x_domain.fixed
80 | var is_y_fixed: bool = y_domain != null && y_domain.fixed
81 |
82 | # GridBox
83 | if not is_x_fixed or not is_y_fixed :
84 | if chart_properties.max_samples > 0 :
85 | var _x: Array = []
86 | var _y: Array = []
87 |
88 | _x.resize(x.size())
89 | _y.resize(y.size())
90 |
91 | for i in x.size():
92 | if not is_x_fixed:
93 | _x[i] = x[i].slice(max(0, x[i].size() - chart_properties.max_samples), x[i].size())
94 | if not is_y_fixed:
95 | _y[i] = y[i].slice(max(0, y[i].size() - chart_properties.max_samples), y[i].size())
96 |
97 | if not is_x_fixed:
98 | x_domain = ChartAxisDomain.from_values(_x, chart_properties.smooth_domain)
99 | if not is_y_fixed:
100 | y_domain = ChartAxisDomain.from_values(_y, chart_properties.smooth_domain)
101 | else:
102 | if not is_x_fixed:
103 | x_domain = ChartAxisDomain.from_values(x, chart_properties.smooth_domain)
104 | if not is_y_fixed:
105 | y_domain = ChartAxisDomain.from_values(y, chart_properties.smooth_domain)
106 |
107 | if !x_domain.is_discrete:
108 | x_domain.set_tick_count(chart_properties.x_scale)
109 |
110 | if x_labels_function:
111 | x_domain.labels_function = x_labels_function
112 |
113 | if !y_domain.is_discrete:
114 | y_domain.set_tick_count(chart_properties.y_scale)
115 |
116 | if y_labels_function:
117 | y_domain.labels_function = y_labels_function
118 |
119 | # Update values for the PlotBox in order to propagate them to the children
120 | update_plotbox(x_domain, y_domain, x_labels_function, y_labels_function)
121 |
122 | # Update GridBox
123 | update_gridbox(x_domain, y_domain, x_labels_function, y_labels_function)
124 |
125 | # Update each FunctionPlotter in FunctionsBox
126 | for function_plotter in functions_box.get_children():
127 | if function_plotter is FunctionPlotter:
128 | function_plotter.visible = function_plotter.function.get_visibility()
129 | if function_plotter.function.get_visibility():
130 | function_plotter.update_values(x_domain, y_domain)
131 |
132 | func set_x_domain(lb: Variant, ub: Variant) -> void:
133 | x_domain = ChartAxisDomain.from_bounds(lb, ub)
134 |
135 | func set_y_domain(lb: Variant, ub: Variant) -> void:
136 | y_domain = ChartAxisDomain.from_bounds(lb, ub)
137 |
138 | func update_plotbox(x_domain: ChartAxisDomain, y_domain: ChartAxisDomain, x_labels_function: Callable, y_labels_function: Callable) -> void:
139 | plot_box.box_margins = calculate_plotbox_margins(x_domain, y_domain, y_labels_function)
140 |
141 | func update_gridbox(x_domain: ChartAxisDomain, y_domain: ChartAxisDomain, x_labels_function: Callable, y_labels_function: Callable) -> void:
142 | grid_box.set_domains(x_domain, y_domain)
143 | grid_box.set_labels_functions(x_labels_function, y_labels_function)
144 | grid_box.queue_redraw()
145 |
146 | func calculate_plotbox_margins(x_domain: ChartAxisDomain, y_domain: ChartAxisDomain, y_labels_function: Callable) -> Vector2:
147 | var plotbox_margins: Vector2 = Vector2(
148 | chart_properties.x_tick_size,
149 | chart_properties.y_tick_size
150 | )
151 |
152 | if chart_properties.show_tick_labels:
153 | var x_ticklabel_size: Vector2
154 | var y_ticklabel_size: Vector2
155 |
156 | var y_max_formatted: String = y_labels_function.call(y_domain.ub) if not y_labels_function.is_null() else \
157 | ECUtilities._format_value(y_domain.ub, y_domain.has_decimals)
158 | if y_domain.lb < 0: # negative number
159 | var y_min_formatted: String = y_labels_function.call(y_domain.ub) if not y_labels_function.is_null() else \
160 | ECUtilities._format_value(y_domain.lb, y_domain.has_decimals)
161 | if y_min_formatted.length() >= y_max_formatted.length():
162 | y_ticklabel_size = chart_properties.get_string_size(y_min_formatted)
163 | else:
164 | y_ticklabel_size = chart_properties.get_string_size(y_max_formatted)
165 | else:
166 | y_ticklabel_size = chart_properties.get_string_size(y_max_formatted)
167 |
168 | plotbox_margins.x += y_ticklabel_size.x + chart_properties.x_ticklabel_space
169 | plotbox_margins.y += ThemeDB.fallback_font_size + chart_properties.y_ticklabel_space
170 |
171 | return plotbox_margins
172 |
173 | func _on_plot_box_resized() -> void:
174 | grid_box.queue_redraw()
175 | for function in functions_box.get_children():
176 | function.queue_redraw()
177 |
178 | func _show_tooltip(point: Point, function: Function, options: Dictionary = {}) -> void:
179 | var x_value: String = x_domain.get_tick_label(point.value.x, x_labels_function)
180 | var y_value: String = y_domain.get_tick_label(point.value.y, y_labels_function)
181 | var color: Color = function.get_color() if function.get_type() != Function.Type.PIE \
182 | else function.get_gradient().sample(options.interpolation_index)
183 | _tooltip.show()
184 | _tooltip.update_values(x_value, y_value, function.name, color)
185 | _tooltip.update_position(point.position)
186 | _function_of_tooltip = function
187 |
188 | func _hide_tooltip(point: Point, function: Function) -> void:
189 | if function != _function_of_tooltip:
190 | return
191 |
192 | _tooltip.hide()
193 |
--------------------------------------------------------------------------------
/addons/easy_charts/control_charts/chart.gd.uid:
--------------------------------------------------------------------------------
1 | uid://bn7n1q5r4n3jn
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/control_charts/chart.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=10 format=3 uid="uid://dlwq4kmdb3bhs"]
2 |
3 | [ext_resource type="Script" uid="uid://bn7n1q5r4n3jn" path="res://addons/easy_charts/control_charts/chart.gd" id="1"]
4 | [ext_resource type="PackedScene" uid="uid://dmesmjhiuqdo4" path="res://addons/easy_charts/utilities/containers/data_tooltip/data_tooltip.tscn" id="2"]
5 | [ext_resource type="Script" uid="uid://d3eig7fx6wtli" path="res://addons/easy_charts/utilities/containers/canvas/canvas.gd" id="3"]
6 | [ext_resource type="Script" uid="uid://8xd8yvw7lumm" path="res://addons/easy_charts/utilities/containers/canvas/plot_box/plot_box.gd" id="4"]
7 | [ext_resource type="Script" uid="uid://doelssxa0y7ap" path="res://addons/easy_charts/utilities/containers/canvas/plot_box/grid_box.gd" id="5"]
8 | [ext_resource type="PackedScene" uid="uid://c6ffuulowjw4g" path="res://addons/easy_charts/utilities/containers/legend/function_legend.tscn" id="6"]
9 |
10 | [sub_resource type="Theme" id="4"]
11 |
12 | [sub_resource type="StyleBoxEmpty" id="8"]
13 |
14 | [sub_resource type="StyleBoxFlat" id="5"]
15 | content_margin_left = 15.0
16 | content_margin_top = 15.0
17 | content_margin_right = 15.0
18 | content_margin_bottom = 15.0
19 | draw_center = false
20 |
21 | [node name="Chart" type="PanelContainer"]
22 | anchors_preset = 15
23 | anchor_right = 1.0
24 | anchor_bottom = 1.0
25 | size_flags_horizontal = 3
26 | size_flags_vertical = 3
27 | mouse_filter = 1
28 | theme = SubResource("4")
29 | theme_override_styles/panel = SubResource("8")
30 | script = ExtResource("1")
31 |
32 | [node name="Canvas" type="PanelContainer" parent="."]
33 | layout_mode = 2
34 | size_flags_horizontal = 3
35 | size_flags_vertical = 3
36 | mouse_filter = 1
37 | theme_override_styles/panel = SubResource("5")
38 | script = ExtResource("3")
39 |
40 | [node name="CanvasContainer" type="VBoxContainer" parent="Canvas"]
41 | layout_mode = 2
42 | size_flags_horizontal = 3
43 | size_flags_vertical = 3
44 | theme_override_constants/separation = 10
45 |
46 | [node name="Title" type="Label" parent="Canvas/CanvasContainer"]
47 | layout_mode = 2
48 | text = "{title}"
49 |
50 | [node name="DataContainer" type="HBoxContainer" parent="Canvas/CanvasContainer"]
51 | layout_mode = 2
52 | size_flags_horizontal = 3
53 | size_flags_vertical = 3
54 | theme_override_constants/separation = 10
55 |
56 | [node name="YLabel" type="Label" parent="Canvas/CanvasContainer/DataContainer"]
57 | layout_mode = 2
58 | text = "{ylabel}"
59 |
60 | [node name="PlotContainer" type="VBoxContainer" parent="Canvas/CanvasContainer/DataContainer"]
61 | layout_mode = 2
62 | size_flags_horizontal = 3
63 | size_flags_vertical = 3
64 |
65 | [node name="PlotBox" type="Control" parent="Canvas/CanvasContainer/DataContainer/PlotContainer"]
66 | unique_name_in_owner = true
67 | clip_contents = true
68 | layout_mode = 2
69 | size_flags_horizontal = 3
70 | size_flags_vertical = 3
71 | script = ExtResource("4")
72 |
73 | [node name="GridBox" type="Control" parent="Canvas/CanvasContainer/DataContainer/PlotContainer/PlotBox"]
74 | unique_name_in_owner = true
75 | anchors_preset = 0
76 | anchor_right = 1.0
77 | anchor_bottom = 1.0
78 | size_flags_horizontal = 3
79 | size_flags_vertical = 3
80 | mouse_filter = 2
81 | script = ExtResource("5")
82 |
83 | [node name="FunctionsBox" type="Control" parent="Canvas/CanvasContainer/DataContainer/PlotContainer/PlotBox"]
84 | unique_name_in_owner = true
85 | anchors_preset = 0
86 | anchor_right = 1.0
87 | anchor_bottom = 1.0
88 | mouse_default_cursor_shape = 3
89 |
90 | [node name="Tooltip" parent="Canvas/CanvasContainer/DataContainer/PlotContainer/PlotBox" instance=ExtResource("2")]
91 | unique_name_in_owner = true
92 | layout_mode = 0
93 | offset_left = -67.0
94 | offset_top = -33.0
95 | offset_right = -17.0
96 | offset_bottom = 30.0
97 |
98 | [node name="XLabel" type="Label" parent="Canvas/CanvasContainer/DataContainer/PlotContainer"]
99 | layout_mode = 2
100 | text = "{xlabel}"
101 |
102 | [node name="FunctionLegend" parent="Canvas/CanvasContainer/DataContainer" instance=ExtResource("6")]
103 | unique_name_in_owner = true
104 | use_parent_material = true
105 | layout_mode = 2
106 |
107 | [connection signal="resized" from="Canvas/CanvasContainer/DataContainer/PlotContainer/PlotBox" to="." method="_on_plot_box_resized"]
108 |
--------------------------------------------------------------------------------
/addons/easy_charts/control_charts/domain/chart_axis_domain.gd:
--------------------------------------------------------------------------------
1 | extends RefCounted
2 | class_name ChartAxisDomain
3 | ## Represents the domain for an axis of a chart.
4 |
5 | ## The lower bound value
6 | var lb: Variant
7 |
8 | ## The upper bound value
9 | var ub: Variant
10 |
11 | ## True if any value on the axis has decimal places
12 | var has_decimals: bool
13 |
14 | ## True if the domain has only discrete values. For now, this is only
15 | ## set to true in case the domain contains string values.
16 | var is_discrete: bool
17 |
18 | ## True if the domain was specified via from_bounds().
19 | var fixed: bool
20 |
21 | ## Callable to overwrite the label generation.
22 | var labels_function: Callable
23 |
24 | var _tick_count: int = -1
25 |
26 | var _string_values: Array
27 |
28 | static func from_bounds(lb: Variant, ub: Variant) -> ChartAxisDomain:
29 | var domain = ChartAxisDomain.new()
30 | domain.lb = lb
31 | domain.ub = ub
32 | domain.has_decimals = ECUtilities._has_decimals([[lb, ub]])
33 | domain.fixed = true
34 | domain.is_discrete = false
35 | return domain
36 |
37 | static func from_values(value_arrays: Array, smooth_domain: bool) -> ChartAxisDomain:
38 | var domain = ChartAxisDomain.new()
39 | for value_array in value_arrays:
40 | if ECUtilities._contains_string(value_array):
41 | domain.lb = 0.0
42 | domain.ub = (value_array.size())
43 | domain.has_decimals = false
44 | domain.is_discrete = true
45 | domain.fixed = false
46 | domain._string_values = value_array
47 | domain._tick_count = value_array.size()
48 | return domain
49 |
50 | var min_max: Dictionary = ECUtilities._find_min_max(value_arrays)
51 | if not smooth_domain:
52 | domain.lb = min_max.min
53 | domain.ub = min_max.max
54 | domain.has_decimals = ECUtilities._has_decimals(value_arrays)
55 | domain.is_discrete = false
56 | domain.fixed = false
57 | else:
58 | domain.lb = ECUtilities._round_min(min_max.min)
59 | domain.ub = ECUtilities._round_max(min_max.max)
60 | domain.has_decimals = ECUtilities._has_decimals(value_arrays)
61 | domain.is_discrete = false
62 | domain.fixed = false
63 |
64 | return domain
65 |
66 | func set_tick_count(tick_count: int) -> void:
67 | if is_discrete:
68 | printerr("You cannot set tick count for a discrete chart axis domain")
69 |
70 | _tick_count = tick_count
71 |
72 | func get_tick_labels() -> PackedStringArray:
73 | if !labels_function.is_null():
74 | return range(_tick_count).map(func(i) -> String:
75 | var value = lerp(lb, ub, float(i) / float(_tick_count))
76 | return labels_function.call(value)
77 | )
78 |
79 | if is_discrete:
80 | return _string_values
81 |
82 | return range(_tick_count).map(func(i) -> String:
83 | var value = lerp(lb, ub, float(i) / float(_tick_count))
84 | return ECUtilities._format_value(value, false)
85 | )
86 |
87 | func get_tick_label(value: Variant, labels_function: Callable) -> String:
88 | if !labels_function.is_null():
89 | return labels_function.call(value)
90 |
91 | if is_discrete:
92 | return value
93 |
94 | return ECUtilities._format_value(value, is_discrete)
95 |
96 | func map_to(value_index: int, function_values: Array, to_domain: ChartAxisDomain) -> Variant:
97 | if is_discrete:
98 | return ECUtilities._map_domain(value_index, self, to_domain)
99 |
100 | return ECUtilities._map_domain(function_values[value_index], self, to_domain)
101 |
--------------------------------------------------------------------------------
/addons/easy_charts/control_charts/domain/chart_axis_domain.gd.uid:
--------------------------------------------------------------------------------
1 | uid://ccuyrwofsk241
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/control_charts/plotters/area_plotter.gd:
--------------------------------------------------------------------------------
1 | extends LinePlotter
2 | class_name AreaPlotter
3 |
4 | var base_color: Color = Color.WHITE
5 |
6 | func _init(function: Function) -> void:
7 | super(function)
8 |
9 | self.base_color = function.get_color()
10 | pass
11 |
12 | func _draw_areas() -> void:
13 | var box: Rect2 = get_box()
14 | var fp_augmented: PackedVector2Array = []
15 | match function.get_interpolation():
16 | Function.Interpolation.LINEAR:
17 | fp_augmented = points_positions
18 | Function.Interpolation.STAIR:
19 | fp_augmented = _get_stair_points()
20 | Function.Interpolation.SPLINE:
21 | fp_augmented = _get_spline_points()
22 | Function.Interpolation.NONE, _:
23 | return
24 |
25 | fp_augmented.push_back(Vector2(fp_augmented[-1].x, box.end.y + 80))
26 | fp_augmented.push_back(Vector2(fp_augmented[0].x, box.end.y + 80))
27 |
28 | # Precompute the scaling factor for the remap.
29 | var end_y = box.end.y
30 | var pos_y = box.position.y
31 | var scale = 0.5 / (pos_y - end_y)
32 |
33 | # Pre-allocate the PackedColorArray based on the number of points.
34 | var point_count = fp_augmented.size()
35 | var colors = PackedColorArray()
36 | colors.resize(point_count)
37 |
38 | # Compute alpha for each point and assign the color.
39 | for i in range(point_count):
40 | var point: Vector2 = fp_augmented[i]
41 | var alpha: float = (point.y - end_y) * scale
42 | colors[i] = Color(base_color, alpha)
43 |
44 | # Draw the polygon with the computed colors.
45 | draw_polygon(fp_augmented, colors)
46 |
47 | func _draw() -> void:
48 | super._draw()
49 |
50 | #prevent error when drawing with no data.
51 | if points_positions.size() < 2:
52 | printerr("Cannot plot an area with less than two points!")
53 | return
54 |
55 | _draw_areas()
56 |
--------------------------------------------------------------------------------
/addons/easy_charts/control_charts/plotters/area_plotter.gd.uid:
--------------------------------------------------------------------------------
1 | uid://dg6thjdl36t01
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/control_charts/plotters/bar_plotter.gd:
--------------------------------------------------------------------------------
1 | extends FunctionPlotter
2 | class_name BarPlotter
3 |
4 |
5 | signal point_entered(point, function)
6 | signal point_exited(point, function)
7 |
8 | var bars: PackedVector2Array
9 | var bars_rects: Array
10 | var focused_bar_midpoint: Point
11 |
12 | var bar_size: float
13 |
14 | func _init(function: Function) -> void:
15 | super(function)
16 | self.bar_size = function.props.get("bar_size", 5.0)
17 |
18 | func _draw() -> void:
19 | super._draw()
20 | var box: Rect2 = get_box()
21 | var x_sampled_domain := ChartAxisDomain.from_bounds(box.position.x, box.end.x)
22 | var y_sampled_domain := ChartAxisDomain.from_bounds(box.end.y, box.position.y)
23 | sample(x_sampled_domain, y_sampled_domain)
24 | _draw_bars()
25 |
26 | func sample(x_sampled_domain: ChartAxisDomain, y_sampled_domain: ChartAxisDomain) -> void:
27 | bars = []
28 | bars_rects = []
29 | for i in function.__x.size():
30 | var top: Vector2 = Vector2(
31 | x_domain.map_to(i, function.__x, x_sampled_domain),
32 | y_domain.map_to(i, function.__y, y_sampled_domain)
33 | )
34 | var base: Vector2 = Vector2(top.x, ECUtilities._map_domain(0.0, y_domain, y_sampled_domain))
35 | bars.push_back(top)
36 | bars.push_back(base)
37 | bars_rects.append(Rect2(Vector2(top.x - bar_size, top.y), Vector2(bar_size * 2, base.y - top.y)))
38 |
39 | func _draw_bars() -> void:
40 | for bar in bars_rects:
41 | draw_rect(bar, function.get_color())
42 |
43 | func _input(event: InputEvent) -> void:
44 | if event is InputEventMouse:
45 | for i in bars_rects.size():
46 | if bars_rects[i].grow(5).abs().has_point(get_relative_position(event.position)):
47 | var point: Point = Point.new(bars_rects[i].get_center(), { x = function.__x[i], y = function.__y[i]})
48 | if focused_bar_midpoint == point:
49 | return
50 | else:
51 | focused_bar_midpoint = point
52 | emit_signal("point_entered", point, function)
53 | return
54 | # Mouse is not in any point's box
55 | emit_signal("point_exited", focused_bar_midpoint, function)
56 | focused_bar_midpoint = null
57 |
--------------------------------------------------------------------------------
/addons/easy_charts/control_charts/plotters/bar_plotter.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cvjd3ae0qlifn
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/control_charts/plotters/function_plotter.gd:
--------------------------------------------------------------------------------
1 | extends Control
2 | class_name FunctionPlotter
3 |
4 | var function: Function
5 | var x_domain: ChartAxisDomain
6 | var y_domain: ChartAxisDomain
7 |
8 | static func create_for_function(function: Function) -> FunctionPlotter:
9 | match function.get_type():
10 | Function.Type.LINE:
11 | return LinePlotter.new(function)
12 | Function.Type.AREA:
13 | return AreaPlotter.new(function)
14 | Function.Type.PIE:
15 | return PiePlotter.new(function)
16 | Function.Type.BAR:
17 | return BarPlotter.new(function)
18 | Function.Type.SCATTER, _:
19 | return ScatterPlotter.new(function)
20 |
21 | func _init(function: Function) -> void:
22 | self.function = function
23 |
24 | func _ready() -> void:
25 | set_process_input(get_chart_properties().interactive)
26 |
27 | func update_values(x_domain: ChartAxisDomain, y_domain: ChartAxisDomain) -> void:
28 | self.visible = self.function.get_visibility()
29 | if not self.function.get_visibility():
30 | return
31 | self.x_domain = x_domain
32 | self.y_domain = y_domain
33 | queue_redraw()
34 |
35 | func _draw() -> void:
36 | return
37 |
38 | func get_box() -> Rect2:
39 | return get_parent().get_parent().get_plot_box()
40 |
41 | func get_chart_properties() -> ChartProperties:
42 | return get_parent().get_parent().chart_properties
43 |
44 | func get_relative_position(position: Vector2) -> Vector2:
45 | return position - global_position
46 |
--------------------------------------------------------------------------------
/addons/easy_charts/control_charts/plotters/function_plotter.gd.uid:
--------------------------------------------------------------------------------
1 | uid://c88cemvig3ion
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/control_charts/plotters/line_plotter.gd:
--------------------------------------------------------------------------------
1 | extends ScatterPlotter
2 | class_name LinePlotter
3 |
4 | func _get_spline_points(density: float = 10.0, tension: float = 1) -> PackedVector2Array:
5 | var spline_points: PackedVector2Array = []
6 |
7 | var augmented_positions: PackedVector2Array = points_positions
8 | var pi: Vector2 = augmented_positions[0] - Vector2(10, -10)
9 | var pf: Vector2 = augmented_positions[augmented_positions.size() - 1] + Vector2(10, 10)
10 |
11 | augmented_positions.insert(0, pi)
12 | augmented_positions.push_back(pf)
13 |
14 | for p in range(1, augmented_positions.size() - 2, 1) : #(inclusive)
15 | for f in range(0, density + 1, 1):
16 | spline_points.append(
17 | augmented_positions[p].cubic_interpolate(
18 | augmented_positions[p + 1],
19 | augmented_positions[p - 1],
20 | augmented_positions[p + 2],
21 | f / density)
22 | )
23 |
24 | return spline_points
25 |
26 |
27 | func _get_stair_points() -> PackedVector2Array:
28 | var stair_points: PackedVector2Array = points_positions
29 |
30 | for i in range(points_positions.size() - 1, 0, -1):
31 | stair_points.insert(i, Vector2(points_positions[i].x, points_positions[i-1].y))
32 |
33 | return stair_points
34 |
35 |
36 | func _draw() -> void:
37 | super._draw()
38 |
39 | #prevent error when drawing with no data.
40 | if points_positions.size() < 2:
41 | printerr("Cannot plot a line with less than two points!")
42 | return
43 |
44 | match function.get_interpolation():
45 | Function.Interpolation.LINEAR:
46 | draw_polyline(
47 | points_positions,
48 | function.get_color(),
49 | function.get_line_width(),
50 | true
51 | )
52 | Function.Interpolation.STAIR:
53 | draw_polyline(
54 | _get_stair_points(),
55 | function.get_color(),
56 | function.get_line_width(),
57 | true
58 | )
59 | Function.Interpolation.SPLINE:
60 | draw_polyline(
61 | _get_spline_points(),
62 | function.get_color(),
63 | function.get_line_width(),
64 | true
65 | )
66 | Function.Interpolation.NONE, _:
67 | pass
68 |
--------------------------------------------------------------------------------
/addons/easy_charts/control_charts/plotters/line_plotter.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cvkgvqwi4av7q
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/control_charts/plotters/pie_plotter.gd:
--------------------------------------------------------------------------------
1 | extends FunctionPlotter
2 | class_name PiePlotter
3 |
4 | signal point_entered(slice_mid_point, function, props)
5 | signal point_exited(slice_mid_point, function)
6 |
7 | var radius_multiplayer: float = 1.0
8 |
9 | #### INTERNAL
10 | var box: Rect2
11 | var radius: float
12 |
13 | var slices: Array = []
14 | var slices_dirs: PackedVector2Array = []
15 | var slices_conc: Array[bool] = []
16 |
17 | var focused_point: Point
18 |
19 | func _draw() -> void:
20 | super._draw()
21 | box = get_box()
22 | radius = min(box.size.x, box.size.y) * 0.5 * radius_multiplayer
23 | var total: float = get_total()
24 | var ratios: PackedFloat32Array = get_ratios(total)
25 | sample(radius, box.get_center(), total, ratios)
26 | _draw_pie()
27 | _draw_labels(radius, box.get_center(), ratios)
28 |
29 | func get_total() -> float:
30 | # Calculate total and ratios
31 | var total: float = 0.0
32 | for value in function.__x:
33 | total += float(value)
34 | return total
35 |
36 | func get_ratios(total: float) -> PackedFloat32Array:
37 | var ratios: PackedFloat32Array = []
38 | for value in function.__x:
39 | ratios.push_back(value / total * 100)
40 | return ratios
41 |
42 | func sample(radius: float, center: Vector2, total: float, ratios: PackedFloat32Array) -> void:
43 | # Calculate directions
44 | slices.clear()
45 | slices_dirs = []
46 | slices_conc = []
47 |
48 | var start_angle: float = 0.0
49 | for ratio in ratios:
50 | var end_angle: float = start_angle + (2 * PI * float(ratio) * 0.01)
51 | slices.append(
52 | _calc_circle_arc_poly(
53 | center,
54 | radius,
55 | start_angle,
56 | end_angle
57 | )
58 | )
59 | slices_conc.append( abs(end_angle - start_angle) >= PI )
60 | start_angle = end_angle
61 |
62 | for i in slices.size():
63 | var slice = slices[i]
64 | var mid_point: Vector2 = (slice[-1] + slice[1]) / 2
65 | if (slices_conc[i]): mid_point = (2 * center) - mid_point
66 | draw_circle(mid_point, 1, Color.RED)
67 | slices_dirs.append(center.direction_to(mid_point))
68 |
69 | func _calc_circle_arc_poly(center: Vector2, radius: float, angle_from: float, angle_to: float) -> PackedVector2Array:
70 | var nb_points: int = 64
71 | var points_arc: PackedVector2Array = PackedVector2Array()
72 | points_arc.push_back(center)
73 |
74 | for i in range(nb_points + 1):
75 | var angle_point: float = - (PI / 2) + angle_from + i * (angle_to - angle_from) / nb_points
76 | points_arc.push_back(center + (Vector2.RIGHT.rotated(angle_point).normalized() * radius))
77 |
78 | return points_arc
79 |
80 | func _draw_pie() -> void:
81 | for i in slices.size():
82 | draw_colored_polygon(slices[i], function.get_gradient().sample(float(i) / float(slices.size() - 1)))
83 | draw_polyline(slices[i], Color.WHITE, 2.0, true)
84 |
85 | func _draw_labels(radius: float, center: Vector2, ratios: PackedFloat32Array) -> void:
86 | for i in slices_dirs.size():
87 | var ratio_lbl: String = "%.1f%%" % ratios[i]
88 | var value_lbl: String = "(%s)" % function.__x[i]
89 | var position: Vector2 = center + slices_dirs[i] * radius * 0.5
90 | var ratio_lbl_size: Vector2 = get_chart_properties().get_string_size(ratio_lbl)
91 | var value_lbl_size: Vector2 = get_chart_properties().get_string_size(value_lbl)
92 | draw_string(
93 | get_chart_properties().font,
94 | position - Vector2(ratio_lbl_size.x / 2, 0),
95 | ratio_lbl,
96 | HORIZONTAL_ALIGNMENT_CENTER,
97 | ratio_lbl_size.x,
98 | 16,
99 | Color.WHITE,
100 | 3,
101 | TextServer.DIRECTION_AUTO,
102 | TextServer.ORIENTATION_HORIZONTAL
103 | )
104 | draw_string(
105 | get_chart_properties().font,
106 | position - Vector2(value_lbl_size.x / 2, - value_lbl_size.y),
107 | value_lbl,
108 | HORIZONTAL_ALIGNMENT_CENTER,
109 | value_lbl_size.x,
110 | 16,
111 | Color.WHITE,
112 | 3,TextServer.DIRECTION_AUTO,TextServer.ORIENTATION_HORIZONTAL
113 | )
114 |
115 | func _input(event: InputEvent) -> void:
116 | if event is InputEventMouse:
117 | for i in slices.size():
118 | if Geometry2D.is_point_in_polygon(get_relative_position(event.position), slices[i]):
119 | var point: Point = Point.new(self.box.get_center() + slices_dirs[i] * self.radius * 0.5, { x = function.__x[i], y = function.__y[i] })
120 | if focused_point == point:
121 | return
122 | else:
123 | focused_point = point
124 | emit_signal("point_entered", focused_point, function, { interpolation_index = float(i) / float(slices.size() - 1)})
125 | return
126 | # Mouse is not in any slice's box
127 | emit_signal("point_exited", focused_point, function)
128 | focused_point = null
129 |
--------------------------------------------------------------------------------
/addons/easy_charts/control_charts/plotters/pie_plotter.gd.uid:
--------------------------------------------------------------------------------
1 | uid://lltln7lxbs8i
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/control_charts/plotters/scatter_plotter.gd:
--------------------------------------------------------------------------------
1 | extends FunctionPlotter
2 | class_name ScatterPlotter
3 |
4 | signal point_entered(point, function)
5 | signal point_exited(point, function)
6 |
7 | var _points: Array[Point]
8 | var points_positions: PackedVector2Array
9 | var focused_point: Point
10 |
11 | var _point_size: float
12 |
13 | func _init(function: Function):
14 | super(function)
15 | _point_size = function.props.get("point_size", 3.0)
16 |
17 | func _draw() -> void:
18 | super._draw()
19 |
20 | _sample()
21 |
22 | if function.get_marker() != Function.Marker.NONE:
23 | for point_position in points_positions:
24 | draw_function_point(point_position)
25 |
26 | func _sample() -> void:
27 | var box: Rect2 = get_box()
28 | var x_sampled_domain := ChartAxisDomain.from_bounds(box.position.x, box.end.x)
29 | var y_sampled_domain := ChartAxisDomain.from_bounds(box.end.y, box.position.y)
30 |
31 | _points = []
32 | points_positions = []
33 |
34 | var lower_bound: int = 0
35 | if get_chart_properties().max_samples > 0:
36 | lower_bound = max(0, function.__x.size() - get_chart_properties().max_samples)
37 |
38 | for i in range(lower_bound, function.__x.size()):
39 | var _position: Vector2 = Vector2(
40 | ECUtilities._map_domain(float(function.__x[i]), x_domain, x_sampled_domain),
41 | ECUtilities._map_domain(float(function.__y[i]), y_domain, y_sampled_domain)
42 | )
43 |
44 | var point = Point.new(_position, { x = function.__x[i], y = function.__y[i] })
45 |
46 | # Don't sample outside y domain upper and lower bounds
47 | if point.position.y > y_sampled_domain.lb || point.position.y < y_sampled_domain.ub:
48 | continue
49 |
50 | _points.push_back(point)
51 | points_positions.push_back(_position)
52 |
53 | func draw_function_point(point_position: Vector2) -> void:
54 | match function.get_marker():
55 | Function.Marker.SQUARE:
56 | draw_rect(
57 | Rect2(point_position - (Vector2.ONE * _point_size), (Vector2.ONE * _point_size * 2)),
58 | function.get_color(), true, 1.0
59 | )
60 | Function.Marker.TRIANGLE:
61 | draw_colored_polygon(
62 | PackedVector2Array([
63 | point_position + (Vector2.UP * _point_size * 1.3),
64 | point_position + (Vector2.ONE * _point_size * 1.3),
65 | point_position - (Vector2(1, -1) * _point_size * 1.3)
66 | ]), function.get_color(), [], null
67 | )
68 | Function.Marker.CROSS:
69 | draw_line(
70 | point_position - (Vector2.ONE * _point_size),
71 | point_position + (Vector2.ONE * _point_size),
72 | function.get_color(), _point_size, true
73 | )
74 | draw_line(
75 | point_position + (Vector2(1, -1) * _point_size),
76 | point_position + (Vector2(-1, 1) * _point_size),
77 | function.get_color(), _point_size / 2, true
78 | )
79 | Function.Marker.CIRCLE, _:
80 | draw_circle(point_position, _point_size, function.get_color())
81 |
82 | func _input(event: InputEvent) -> void:
83 | if event is InputEventMouse:
84 | for point in _points:
85 | if Geometry2D.is_point_in_circle(get_relative_position(event.position), point.position, _point_size * 4):
86 | if focused_point == point:
87 | return
88 | else:
89 | focused_point = point
90 | emit_signal("point_entered", point, function)
91 | return
92 | # Mouse is not in any point's box
93 | emit_signal("point_exited", focused_point, function)
94 | focused_point = null
95 |
--------------------------------------------------------------------------------
/addons/easy_charts/control_charts/plotters/scatter_plotter.gd.uid:
--------------------------------------------------------------------------------
1 | uid://bx0yko2nptnbh
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/area_chart/area_chart_example.gd:
--------------------------------------------------------------------------------
1 | extends Control
2 |
3 | @onready var chart: Chart = $VBoxContainer/Chart
4 |
5 | # This Chart will plot 3 different functions
6 | var f1: Function
7 |
8 | func _ready():
9 | # Let's create our @x values
10 | var x: Array = ArrayOperations.multiply_float(range(-10, 11, 1), 0.5)
11 |
12 | # And our y values. It can be an n-size array of arrays.
13 | # NOTE: `x.size() == y.size()` or `x.size() == y[n].size()`
14 | var y: Array = ArrayOperations.multiply_int(ArrayOperations.cos(x), 20)
15 |
16 | # Let's customize the chart properties, which specify how the chart
17 | # should look, plus some additional elements like labels, the scale, etc...
18 | var cp: ChartProperties = ChartProperties.new()
19 | cp.colors.frame = Color("#161a1d")
20 | cp.colors.background = Color.TRANSPARENT
21 | cp.colors.grid = Color("#283442")
22 | cp.colors.ticks = Color("#283442")
23 | cp.colors.text = Color.WHITE_SMOKE
24 | cp.draw_bounding_box = false
25 | cp.title = "Air Quality Monitoring"
26 | cp.x_label = "Time"
27 | cp.y_label = "Sensor values"
28 | cp.x_scale = 5
29 | cp.y_scale = 10
30 | cp.interactive = true # false by default, it allows the chart to create a tooltip to show point values
31 | # and interecept clicks on the plot
32 |
33 | # Let's add values to our functions
34 | f1 = Function.new(
35 | x, y, "Pressure", # This will create a function with x and y values taken by the Arrays
36 | # we have created previously. This function will also be named "Pressure"
37 | # as it contains 'pressure' values.
38 | # If set, the name of a function will be used both in the Legend
39 | # (if enabled thourgh ChartProperties) and on the Tooltip (if enabled).
40 | # Let's also provide a dictionary of configuration parameters for this specific function.
41 | {
42 | color = Color("#36a2eb"), # The color associated to this function
43 | marker = Function.Marker.NONE, # The marker that will be displayed for each drawn point (x,y)
44 | # since it is `NONE`, no marker will be shown.
45 | type = Function.Type.AREA, # This defines what kind of plotting will be used,
46 | # in this case it will be an Area Chart.
47 | }
48 | )
49 |
50 | # Now let's plot our data
51 | chart.plot([f1], cp)
52 |
53 | # Uncommenting this line will show how real time data plotting works
54 | set_process(false)
55 |
56 |
57 | var new_val: float = 4.5
58 |
59 | func _process(delta: float):
60 | # This function updates the values of a function and then updates the plot
61 | new_val += 5
62 |
63 | # we can use the `Function.add_point(x, y)` method to update a function
64 | f1.add_point(new_val, cos(new_val) * 20)
65 | chart.queue_redraw() # This will force the Chart to be updated
66 |
67 |
68 | func _on_CheckButton_pressed():
69 | set_process(not is_processing())
70 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/area_chart/area_chart_example.gd.uid:
--------------------------------------------------------------------------------
1 | uid://bcaslhu2t7xr3
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/area_chart/area_chart_example.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://c2ymglyg812ss"]
2 |
3 | [ext_resource type="Script" uid="uid://bcaslhu2t7xr3" path="res://addons/easy_charts/examples/area_chart/area_chart_example.gd" id="1"]
4 | [ext_resource type="PackedScene" uid="uid://dlwq4kmdb3bhs" path="res://addons/easy_charts/control_charts/chart.tscn" id="2"]
5 |
6 | [sub_resource type="StyleBoxFlat" id="1"]
7 | content_margin_right = 5.0
8 | content_margin_bottom = 5.0
9 | draw_center = false
10 | border_width_right = 2
11 | border_width_bottom = 2
12 | border_color = Color(0, 0, 0, 1)
13 |
14 | [node name="Control" type="Control"]
15 | layout_mode = 3
16 | anchors_preset = 15
17 | anchor_right = 1.0
18 | anchor_bottom = 1.0
19 | grow_horizontal = 2
20 | grow_vertical = 2
21 | script = ExtResource("1")
22 |
23 | [node name="VBoxContainer" type="VBoxContainer" parent="."]
24 | layout_mode = 0
25 | anchor_right = 1.0
26 | anchor_bottom = 1.0
27 |
28 | [node name="CheckButton" type="CheckButton" parent="VBoxContainer"]
29 | layout_mode = 2
30 | theme_override_colors/font_disabled_color = Color(0, 0, 0, 1)
31 | theme_override_colors/font_hover_pressed_color = Color(0, 0, 0, 1)
32 | theme_override_colors/font_hover_color = Color(0, 0, 0, 1)
33 | theme_override_colors/font_color = Color(0, 0, 0, 1)
34 | theme_override_colors/font_focus_color = Color(0, 0, 0, 1)
35 | theme_override_colors/font_pressed_color = Color(0, 0, 0, 1)
36 | text = "Start Relatime Plotting"
37 |
38 | [node name="Chart" parent="VBoxContainer" instance=ExtResource("2")]
39 | layout_mode = 2
40 |
41 | [node name="Label" type="Label" parent="VBoxContainer"]
42 | layout_mode = 2
43 | size_flags_horizontal = 8
44 | theme_override_colors/font_color = Color(0, 0, 0, 1)
45 | theme_override_styles/normal = SubResource("1")
46 | text = "Try to scale the window!"
47 |
48 | [connection signal="pressed" from="VBoxContainer/CheckButton" to="." method="_on_CheckButton_pressed"]
49 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/bar_chart/bar_chart_example.gd:
--------------------------------------------------------------------------------
1 | extends Control
2 |
3 | @onready var chart: Chart = $VBoxContainer/Chart
4 |
5 | func _ready():
6 | # Let's create our @x values
7 | var x: Array = range(0, 24).map(func(i: int) -> String: return "%d - %d h" % [i, i+1])
8 |
9 | # And our y values. It can be an n-size array of arrays.
10 | # NOTE: `x.size() == y.size()` or `x.size() == y[n].size()`
11 | var y1: Array = ArrayOperations.add_int(ArrayOperations.multiply_int(range(0, 24), 10), 4)
12 | var y2: Array = ArrayOperations.add_int(ArrayOperations.multiply_int(range(0, 24), 5), 4)
13 |
14 | # Let's customize the chart properties, which specify how the chart
15 | # should look, plus some additional elements like labels, the scale, etc...
16 | var cp: ChartProperties = ChartProperties.new()
17 | cp.colors.frame = Color("#161a1d")
18 | cp.colors.background = Color.TRANSPARENT
19 | cp.colors.grid = Color("#283442")
20 | cp.colors.ticks = Color("#283442")
21 | cp.colors.text = Color.WHITE_SMOKE
22 | cp.y_scale = 10
23 | cp.draw_origin = true
24 | cp.draw_bounding_box = false
25 | cp.draw_vertical_grid = true
26 | cp.interactive = true # false by default, it allows the chart to create a tooltip to show point values
27 | # and interecept clicks on the plot
28 |
29 | # Let's add values to our functions
30 | # This will create a function with x and y values taken by the Arrays
31 | # we have created previously. This function will also be named "Pressure"
32 | # as it contains 'pressure' values.
33 | # If set, the name of a function will be used both in the Legend
34 | # (if enabled thourgh ChartProperties) and on the Tooltip (if enabled).
35 | var f1 = Function.new(
36 | x, y1, "Users",
37 | {
38 | type = Function.Type.BAR,
39 | bar_size = 5,
40 | color = Color.SEA_GREEN,
41 | }
42 | )
43 |
44 | var f2 = Function.new(
45 | x, y2, "Impressions",
46 | {
47 | type = Function.Type.BAR,
48 | bar_size = 5,
49 | color = Color.SKY_BLUE,
50 | }
51 | )
52 |
53 | var f3 := Function.new(
54 | x, y1, "Conversions",
55 | {
56 | type = Function.Type.BAR,
57 | bar_size = 5,
58 | color = Color.YELLOW,
59 | }
60 | )
61 |
62 | var f4 := Function.new(
63 | x, y2, "Clicks",
64 | {
65 | type = Function.Type.BAR,
66 | bar_size = 5,
67 | color = Color.DARK_RED,
68 | }
69 | )
70 |
71 | # Now let's plot our data
72 | chart.plot([f1, f2, f3, f4], cp)
73 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/bar_chart/bar_chart_example.gd.uid:
--------------------------------------------------------------------------------
1 | uid://b1ioy02qwjlpe
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/bar_chart/bar_chart_example.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://dn8rdqup8ldnw"]
2 |
3 | [ext_resource type="Script" uid="uid://b1ioy02qwjlpe" path="res://addons/easy_charts/examples/bar_chart/bar_chart_example.gd" id="1"]
4 | [ext_resource type="PackedScene" uid="uid://dlwq4kmdb3bhs" path="res://addons/easy_charts/control_charts/chart.tscn" id="2"]
5 |
6 | [sub_resource type="StyleBoxFlat" id="1"]
7 | content_margin_right = 5.0
8 | content_margin_bottom = 5.0
9 | draw_center = false
10 | border_width_right = 2
11 | border_width_bottom = 2
12 | border_color = Color(0, 0, 0, 1)
13 |
14 | [node name="Control2" type="Control"]
15 | layout_mode = 3
16 | anchors_preset = 15
17 | anchor_right = 1.0
18 | anchor_bottom = 1.0
19 | grow_horizontal = 2
20 | grow_vertical = 2
21 | script = ExtResource("1")
22 |
23 | [node name="VBoxContainer" type="VBoxContainer" parent="."]
24 | layout_mode = 0
25 | anchor_right = 1.0
26 | anchor_bottom = 1.0
27 |
28 | [node name="CheckButton" type="CheckButton" parent="VBoxContainer"]
29 | layout_mode = 2
30 | theme_override_colors/font_disabled_color = Color(0, 0, 0, 1)
31 | theme_override_colors/font_hover_pressed_color = Color(0, 0, 0, 1)
32 | theme_override_colors/font_hover_color = Color(0, 0, 0, 1)
33 | theme_override_colors/font_color = Color(0, 0, 0, 1)
34 | theme_override_colors/font_focus_color = Color(0, 0, 0, 1)
35 | theme_override_colors/font_pressed_color = Color(0, 0, 0, 1)
36 | text = "Start Relatime Plotting"
37 |
38 | [node name="Chart" parent="VBoxContainer" instance=ExtResource("2")]
39 | layout_mode = 2
40 |
41 | [node name="Label" type="Label" parent="VBoxContainer"]
42 | layout_mode = 2
43 | size_flags_horizontal = 8
44 | theme_override_colors/font_color = Color(0, 0, 0, 1)
45 | theme_override_styles/normal = SubResource("1")
46 | text = "Try to scale the window!"
47 |
48 | [connection signal="pressed" from="VBoxContainer/CheckButton" to="." method="_on_CheckButton_pressed"]
49 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/line_chart/line_chart_example.gd:
--------------------------------------------------------------------------------
1 | extends Control
2 |
3 | @onready var chart: Chart = $VBoxContainer/Chart
4 |
5 | # This Chart will plot 3 different functions
6 | var f1: Function
7 |
8 | func _ready():
9 | # Let's create our @x values
10 | var x: PackedFloat32Array = ArrayOperations.multiply_float(range(-10, 11, 1), 0.5)
11 |
12 | # And our y values. It can be an n-size array of arrays.
13 | # NOTE: `x.size() == y.size()` or `x.size() == y[n].size()`
14 | var y: Array = ArrayOperations.multiply_int(ArrayOperations.cos(x), 20)
15 |
16 | # Let's customize the chart properties, which specify how the chart
17 | # should look, plus some additional elements like labels, the scale, etc...
18 | var cp: ChartProperties = ChartProperties.new()
19 | cp.colors.frame = Color("#161a1d")
20 | cp.colors.background = Color.TRANSPARENT
21 | cp.colors.grid = Color("#283442")
22 | cp.colors.ticks = Color("#283442")
23 | cp.colors.text = Color.WHITE_SMOKE
24 | cp.draw_bounding_box = false
25 | cp.title = "Air Quality Monitoring"
26 | cp.x_label = "Time"
27 | cp.y_label = "Sensor values"
28 | cp.x_scale = 5
29 | cp.y_scale = 10
30 | cp.interactive = true # false by default, it allows the chart to create a tooltip to show point values
31 | # and interecept clicks on the plot
32 |
33 | # Let's add values to our functions
34 | f1 = Function.new(
35 | x, y, "Pressure", # This will create a function with x and y values taken by the Arrays
36 | # we have created previously. This function will also be named "Pressure"
37 | # as it contains 'pressure' values.
38 | # If set, the name of a function will be used both in the Legend
39 | # (if enabled thourgh ChartProperties) and on the Tooltip (if enabled).
40 | # Let's also provide a dictionary of configuration parameters for this specific function.
41 | {
42 | color = Color("#36a2eb"), # The color associated to this function
43 | marker = Function.Marker.CIRCLE, # The marker that will be displayed for each drawn point (x,y)
44 | # since it is `NONE`, no marker will be shown.
45 | type = Function.Type.LINE, # This defines what kind of plotting will be used,
46 | # in this case it will be a Linear Chart.
47 | interpolation = Function.Interpolation.STAIR # Interpolation mode, only used for
48 | # Line Charts and Area Charts.
49 | }
50 | )
51 |
52 | # Now let's plot our data
53 | chart.plot([f1], cp)
54 |
55 | # Uncommenting this line will show how real time data plotting works
56 | set_process(false)
57 |
58 |
59 | var new_val: float = 4.5
60 |
61 | func _process(delta: float):
62 | # This function updates the values of a function and then updates the plot
63 | new_val += 5
64 |
65 | # we can use the `Function.add_point(x, y)` method to update a function
66 | f1.add_point(new_val, cos(new_val) * 20)
67 | f1.remove_point(0)
68 | chart.queue_redraw() # This will force the Chart to be updated
69 |
70 |
71 | func _on_CheckButton_pressed():
72 | set_process(not is_processing())
73 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/line_chart/line_chart_example.gd.uid:
--------------------------------------------------------------------------------
1 | uid://xafq3pfkghx0
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/line_chart/line_chart_example.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://chcj7up8k8pa8"]
2 |
3 | [ext_resource type="Script" uid="uid://xafq3pfkghx0" path="res://addons/easy_charts/examples/line_chart/line_chart_example.gd" id="1"]
4 | [ext_resource type="PackedScene" uid="uid://dlwq4kmdb3bhs" path="res://addons/easy_charts/control_charts/chart.tscn" id="2"]
5 |
6 | [sub_resource type="StyleBoxFlat" id="1"]
7 | content_margin_right = 5.0
8 | content_margin_bottom = 5.0
9 | draw_center = false
10 | border_width_right = 2
11 | border_width_bottom = 2
12 | border_color = Color(0, 0, 0, 1)
13 |
14 | [node name="Control2" type="Control"]
15 | layout_mode = 3
16 | anchors_preset = 15
17 | anchor_right = 1.0
18 | anchor_bottom = 1.0
19 | grow_horizontal = 2
20 | grow_vertical = 2
21 | script = ExtResource("1")
22 |
23 | [node name="VBoxContainer" type="VBoxContainer" parent="."]
24 | layout_mode = 0
25 | anchor_right = 1.0
26 | anchor_bottom = 1.0
27 |
28 | [node name="CheckButton" type="CheckButton" parent="VBoxContainer"]
29 | layout_mode = 2
30 | theme_override_colors/font_disabled_color = Color(0, 0, 0, 1)
31 | theme_override_colors/font_hover_pressed_color = Color(0, 0, 0, 1)
32 | theme_override_colors/font_hover_color = Color(0, 0, 0, 1)
33 | theme_override_colors/font_color = Color(0, 0, 0, 1)
34 | theme_override_colors/font_focus_color = Color(0, 0, 0, 1)
35 | theme_override_colors/font_pressed_color = Color(0, 0, 0, 1)
36 | text = "Start Relatime Plotting"
37 |
38 | [node name="Chart" parent="VBoxContainer" instance=ExtResource("2")]
39 | layout_mode = 2
40 |
41 | [node name="Label" type="Label" parent="VBoxContainer"]
42 | layout_mode = 2
43 | size_flags_horizontal = 8
44 | theme_override_colors/font_color = Color(0, 0, 0, 1)
45 | theme_override_styles/normal = SubResource("1")
46 | text = "Try to scale the window!"
47 |
48 | [connection signal="pressed" from="VBoxContainer/CheckButton" to="." method="_on_CheckButton_pressed"]
49 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/multiplot/multiplot_example.gd:
--------------------------------------------------------------------------------
1 | extends Control
2 |
3 | @onready var chart: Chart = $VBoxContainer/Chart
4 |
5 | # This Chart will plot 3 different functions
6 | var f1: Function
7 | var f2: Function
8 | var f3: Function
9 |
10 | func _ready():
11 | # Let's create our @x values
12 | var x: Array = ArrayOperations.multiply_float(range(-10, 11, 1), 0.5)
13 |
14 | # And our y values. It can be an n-size array of arrays.
15 | # NOTE: `x.size() == y.size()` or `x.size() == y[n].size()`
16 | var y: Array = ArrayOperations.multiply_int(ArrayOperations.cos(x), 20)
17 | var y2: Array = ArrayOperations.add_float(ArrayOperations.multiply_int(ArrayOperations.sin(x), 20), 20)
18 | var y3: Array = ArrayOperations.add_float(ArrayOperations.multiply_int(ArrayOperations.cos(x), -5), -3)
19 |
20 | # Let's customize the chart properties, which specify how the chart
21 | # should look, plus some additional elements like labels, the scale, etc...
22 | var cp: ChartProperties = ChartProperties.new()
23 | cp.colors.frame = Color("#161a1d")
24 | cp.colors.background = Color.TRANSPARENT
25 | cp.colors.grid = Color("#283442")
26 | cp.colors.ticks = Color("#283442")
27 | cp.colors.text = Color.WHITE_SMOKE
28 | cp.draw_bounding_box = false
29 | cp.show_legend = true
30 | cp.title = "Air Quality Monitoring"
31 | cp.x_label = "Time"
32 | cp.y_label = "Sensor values"
33 | cp.x_scale = 5
34 | cp.y_scale = 10
35 | cp.interactive = true # false by default, it allows the chart to create a tooltip to show point values
36 | # and interecept clicks on the plot
37 |
38 | # Let's add values to our functions
39 | f1 = Function.new(
40 | x, y, "Pressure", # This will create a function with x and y values taken by the Arrays
41 | # we have created previously. This function will also be named "Pressure"
42 | # as it contains 'pressure' values.
43 | # If set, the name of a function will be used both in the Legend
44 | # (if enabled thourgh ChartProperties) and on the Tooltip (if enabled).
45 | # Let's also provide a dictionary of configuration parameters for this specific function.
46 | {
47 | color = Color("#36a2eb"), # The color associated to this function
48 | marker = Function.Marker.NONE, # The marker that will be displayed for each drawn point (x,y)
49 | # since it is `NONE`, no marker will be shown.
50 | type = Function.Type.AREA, # This defines what kind of plotting will be used,
51 | # in this case it will be an Area Chart.
52 | interpolation = Function.Interpolation.STAIR # Interpolation mode, only used for
53 | # Line Charts and Area Charts.
54 | }
55 | )
56 | f2 = Function.new(x, y2, "Humidity", { color = Color("#ff6384"), marker = Function.Marker.CROSS })
57 | f3 = Function.new(x, y3, "CO2", { color = Color.GREEN, marker = Function.Marker.TRIANGLE })
58 |
59 | # Now let's plot our data
60 | chart.plot([f1, f2, f3], cp)
61 |
62 | # Uncommenting this line will show how real time data plotting works
63 | set_process(false)
64 |
65 |
66 | var new_val: float = 4.5
67 |
68 | func _process(delta: float):
69 | # This function updates the values of a function and then updates the plot
70 | new_val += 5
71 |
72 | # we can use the `Function.add_point(x, y)` method to update a function
73 | f1.add_point(new_val, cos(new_val) * 20)
74 | f2.add_point(new_val, (sin(new_val) * 20) + 20)
75 | f3.add_point(new_val, (cos(new_val) * -5) - 3)
76 | chart.queue_redraw() # This will force the Chart to be updated
77 |
78 |
79 | func _on_CheckButton_pressed():
80 | set_process(not is_processing())
81 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/multiplot/multiplot_example.gd.uid:
--------------------------------------------------------------------------------
1 | uid://ouq5e3pbw5c1
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/multiplot/multiplot_example.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://7v0v5lsl0kqe"]
2 |
3 | [ext_resource type="Script" uid="uid://ouq5e3pbw5c1" path="res://addons/easy_charts/examples/multiplot/multiplot_example.gd" id="1"]
4 | [ext_resource type="PackedScene" uid="uid://dlwq4kmdb3bhs" path="res://addons/easy_charts/control_charts/chart.tscn" id="2"]
5 |
6 | [sub_resource type="StyleBoxFlat" id="1"]
7 | content_margin_right = 5.0
8 | content_margin_bottom = 5.0
9 | draw_center = false
10 | border_width_right = 2
11 | border_width_bottom = 2
12 | border_color = Color(0, 0, 0, 1)
13 |
14 | [node name="Control2" type="Control"]
15 | layout_mode = 3
16 | anchors_preset = 15
17 | anchor_right = 1.0
18 | anchor_bottom = 1.0
19 | grow_horizontal = 2
20 | grow_vertical = 2
21 | script = ExtResource("1")
22 |
23 | [node name="VBoxContainer" type="VBoxContainer" parent="."]
24 | layout_mode = 0
25 | anchor_right = 1.0
26 | anchor_bottom = 1.0
27 |
28 | [node name="CheckButton" type="CheckButton" parent="VBoxContainer"]
29 | layout_mode = 2
30 | theme_override_colors/font_disabled_color = Color(0, 0, 0, 1)
31 | theme_override_colors/font_hover_pressed_color = Color(0, 0, 0, 1)
32 | theme_override_colors/font_hover_color = Color(0, 0, 0, 1)
33 | theme_override_colors/font_color = Color(0, 0, 0, 1)
34 | theme_override_colors/font_focus_color = Color(0, 0, 0, 1)
35 | theme_override_colors/font_pressed_color = Color(0, 0, 0, 1)
36 | text = "Start Relatime Plotting"
37 |
38 | [node name="Chart" parent="VBoxContainer" instance=ExtResource("2")]
39 | layout_mode = 2
40 |
41 | [node name="Label" type="Label" parent="VBoxContainer"]
42 | layout_mode = 2
43 | size_flags_horizontal = 8
44 | theme_override_colors/font_color = Color(0, 0, 0, 1)
45 | theme_override_styles/normal = SubResource("1")
46 | text = "Try to scale the window!"
47 |
48 | [connection signal="pressed" from="VBoxContainer/CheckButton" to="." method="_on_CheckButton_pressed"]
49 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/pie_chart/pie_chart_example.gd:
--------------------------------------------------------------------------------
1 | extends Control
2 |
3 | @onready var chart: Chart = $VBoxContainer/Chart
4 |
5 | # This Chart will plot 3 different functions
6 | var f1: Function
7 |
8 | func _ready():
9 | # Let's create our @x values
10 | var x: Array = [100, 400]
11 |
12 | # And our y values. It can be an n-size array of arrays.
13 | # NOTE: `x.size() == y.size()` or `x.size() == y[n].size()`
14 | var y: Array = ["Java", "JavaScript", "C++", "GDScript"]
15 |
16 | # Let's customize the chart properties, which specify how the chart
17 | # should look, plus some additional elements like labels, the scale, etc...
18 | var cp: ChartProperties = ChartProperties.new()
19 | cp.colors.frame = Color("#161a1d")
20 | cp.colors.background = Color.TRANSPARENT
21 | cp.colors.grid = Color("#283442")
22 | cp.colors.ticks = Color("#283442")
23 | cp.colors.text = Color.WHITE_SMOKE
24 | cp.draw_bounding_box = false
25 | cp.title = "Users preferences on programming languages"
26 | cp.draw_grid_box = false
27 | cp.show_legend = true
28 | cp.interactive = true # false by default, it allows the chart to create a tooltip to show point values
29 | # and interecept clicks on the plot
30 |
31 | var gradient: Gradient = Gradient.new()
32 | gradient.set_color(0, Color.AQUAMARINE)
33 | gradient.set_color(1, Color.DEEP_PINK)
34 |
35 | # Let's add values to our functions
36 | f1 = Function.new(
37 | x, y, "Language", # This will create a function with x and y values taken by the Arrays
38 | # we have created previously. This function will also be named "Pressure"
39 | # as it contains 'pressure' values.
40 | # If set, the name of a function will be used both in the Legend
41 | # (if enabled thourgh ChartProperties) and on the Tooltip (if enabled).
42 | {
43 | gradient = gradient,
44 | type = Function.Type.PIE
45 | }
46 | )
47 |
48 | # Now let's plot our data
49 | chart.plot([f1], cp)
50 |
51 | # Uncommenting this line will show how real time data plotting works
52 | set_process(false)
53 |
54 |
55 | var new_val: float = 4.5
56 |
57 | func _process(delta: float):
58 | # This function updates the values of a function and then updates the plot
59 | new_val += 5
60 |
61 | # we can use the `Function.add_point(x, y)` method to update a function
62 | f1.add_point(new_val, cos(new_val) * 20)
63 | chart.queue_redraw() # This will force the Chart to be updated
64 |
65 |
66 | func _on_CheckButton_pressed():
67 | set_process(not is_processing())
68 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/pie_chart/pie_chart_example.gd.uid:
--------------------------------------------------------------------------------
1 | uid://btfgl143uq8jc
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/pie_chart/pie_chart_example.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://be3nkm3rmqe7m"]
2 |
3 | [ext_resource type="Script" uid="uid://btfgl143uq8jc" path="res://addons/easy_charts/examples/pie_chart/pie_chart_example.gd" id="1"]
4 | [ext_resource type="PackedScene" uid="uid://dlwq4kmdb3bhs" path="res://addons/easy_charts/control_charts/chart.tscn" id="2"]
5 |
6 | [sub_resource type="StyleBoxFlat" id="1"]
7 | content_margin_right = 5.0
8 | content_margin_bottom = 5.0
9 | draw_center = false
10 | border_width_right = 2
11 | border_width_bottom = 2
12 | border_color = Color(0, 0, 0, 1)
13 |
14 | [node name="Control2" type="Control"]
15 | layout_mode = 3
16 | anchors_preset = 15
17 | anchor_right = 1.0
18 | anchor_bottom = 1.0
19 | grow_horizontal = 2
20 | grow_vertical = 2
21 | script = ExtResource("1")
22 |
23 | [node name="VBoxContainer" type="VBoxContainer" parent="."]
24 | layout_mode = 0
25 | anchor_right = 1.0
26 | anchor_bottom = 1.0
27 |
28 | [node name="CheckButton" type="CheckButton" parent="VBoxContainer"]
29 | layout_mode = 2
30 | theme_override_colors/font_disabled_color = Color(0, 0, 0, 1)
31 | theme_override_colors/font_hover_pressed_color = Color(0, 0, 0, 1)
32 | theme_override_colors/font_hover_color = Color(0, 0, 0, 1)
33 | theme_override_colors/font_color = Color(0, 0, 0, 1)
34 | theme_override_colors/font_focus_color = Color(0, 0, 0, 1)
35 | theme_override_colors/font_pressed_color = Color(0, 0, 0, 1)
36 | text = "Start Relatime Plotting"
37 |
38 | [node name="Chart" parent="VBoxContainer" instance=ExtResource("2")]
39 | layout_mode = 2
40 |
41 | [node name="Label" type="Label" parent="VBoxContainer"]
42 | layout_mode = 2
43 | size_flags_horizontal = 8
44 | theme_override_colors/font_color = Color(0, 0, 0, 1)
45 | theme_override_styles/normal = SubResource("1")
46 | text = "Try to scale the window!"
47 |
48 | [connection signal="pressed" from="VBoxContainer/CheckButton" to="." method="_on_CheckButton_pressed"]
49 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/scatter_chart/scatter_chart_example.gd:
--------------------------------------------------------------------------------
1 | extends Control
2 |
3 | @onready var chart: Chart = $VBoxContainer/Chart
4 |
5 | # This Chart will plot 3 different functions
6 | var f1: Function
7 | var f2: Function
8 |
9 | func _ready():
10 | # Let's create our @x values
11 | var x: Array = ArrayOperations.multiply_float(range(-10, 11, 1), 0.5)
12 |
13 | # And our y values. It can be an n-size array of arrays.
14 | # NOTE: `x.size() == y.size()` or `x.size() == y[n].size()`
15 | var y: Array = ArrayOperations.multiply_int(ArrayOperations.cos(x), 20)
16 | var y2: Array = ArrayOperations.add_float(ArrayOperations.multiply_int(ArrayOperations.sin(x), 20), 20)
17 |
18 | # Let's customize the chart properties, which specify how the chart
19 | # should look, plus some additional elements like labels, the scale, etc...
20 | var cp: ChartProperties = ChartProperties.new()
21 | cp.colors.frame = Color("#161a1d")
22 | cp.colors.background = Color.TRANSPARENT
23 | cp.colors.grid = Color("#283442")
24 | cp.colors.ticks = Color("#283442")
25 | cp.colors.text = Color.WHITE_SMOKE
26 | cp.draw_bounding_box = false
27 | cp.title = "Air Quality Monitoring"
28 | cp.x_label = "Time"
29 | cp.y_label = "Sensor values"
30 | cp.x_scale = 5
31 | cp.y_scale = 10
32 | cp.interactive = true # false by default, it allows the chart to create a tooltip to show point values
33 | # and interecept clicks on the plot
34 |
35 | # Let's add values to our functions
36 | f1 = Function.new(
37 | x, y, "Pressure", # This will create a function with x and y values taken by the Arrays
38 | # we have created previously. This function will also be named "Pressure"
39 | # as it contains 'pressure' values.
40 | # If set, the name of a function will be used both in the Legend
41 | # (if enabled thourgh ChartProperties) and on the Tooltip (if enabled).
42 | { color = Color.GREEN, marker = Function.Marker.CIRCLE }
43 | )
44 | f2 = Function.new(x, y2, "Humidity", { color = Color("#ff6384"), marker = Function.Marker.CROSS })
45 |
46 | # Now let's plot our data
47 | chart.plot([f1, f2], cp)
48 |
49 | # Uncommenting this line will show how real time data plotting works
50 | set_process(false)
51 |
52 |
53 | var new_val: float = 4.5
54 |
55 | func _process(delta: float):
56 | # This function updates the values of a function and then updates the plot
57 | new_val += 5
58 |
59 | # we can use the `Function.add_point(x, y)` method to update a function
60 | f1.add_point(new_val, cos(new_val) * 20)
61 | f2.add_point(new_val, (sin(new_val) * 20) + 20)
62 | chart.queue_redraw() # This will force the Chart to be updated
63 |
64 |
65 | func _on_CheckButton_pressed():
66 | set_process(not is_processing())
67 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/scatter_chart/scatter_chart_example.gd.uid:
--------------------------------------------------------------------------------
1 | uid://drjv3jppfmods
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/scatter_chart/scatter_chart_example.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://cekkstadxpimf"]
2 |
3 | [ext_resource type="Script" uid="uid://drjv3jppfmods" path="res://addons/easy_charts/examples/scatter_chart/scatter_chart_example.gd" id="1"]
4 | [ext_resource type="PackedScene" uid="uid://dlwq4kmdb3bhs" path="res://addons/easy_charts/control_charts/chart.tscn" id="2"]
5 |
6 | [sub_resource type="StyleBoxFlat" id="1"]
7 | content_margin_right = 5.0
8 | content_margin_bottom = 5.0
9 | draw_center = false
10 | border_width_right = 2
11 | border_width_bottom = 2
12 | border_color = Color(0, 0, 0, 1)
13 |
14 | [node name="Control2" type="Control"]
15 | layout_mode = 3
16 | anchors_preset = 15
17 | anchor_right = 1.0
18 | anchor_bottom = 1.0
19 | grow_horizontal = 2
20 | grow_vertical = 2
21 | script = ExtResource("1")
22 |
23 | [node name="VBoxContainer" type="VBoxContainer" parent="."]
24 | layout_mode = 0
25 | anchor_right = 1.0
26 | anchor_bottom = 1.0
27 |
28 | [node name="CheckButton" type="CheckButton" parent="VBoxContainer"]
29 | layout_mode = 2
30 | theme_override_colors/font_disabled_color = Color(0, 0, 0, 1)
31 | theme_override_colors/font_hover_pressed_color = Color(0, 0, 0, 1)
32 | theme_override_colors/font_hover_color = Color(0, 0, 0, 1)
33 | theme_override_colors/font_color = Color(0, 0, 0, 1)
34 | theme_override_colors/font_focus_color = Color(0, 0, 0, 1)
35 | theme_override_colors/font_pressed_color = Color(0, 0, 0, 1)
36 | text = "Start Relatime Plotting"
37 |
38 | [node name="Chart" parent="VBoxContainer" instance=ExtResource("2")]
39 | layout_mode = 2
40 |
41 | [node name="Label" type="Label" parent="VBoxContainer"]
42 | layout_mode = 2
43 | size_flags_horizontal = 8
44 | theme_override_colors/font_color = Color(0, 0, 0, 1)
45 | theme_override_styles/normal = SubResource("1")
46 | text = "Try to scale the window!"
47 |
48 | [connection signal="pressed" from="VBoxContainer/CheckButton" to="." method="_on_CheckButton_pressed"]
49 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/scatter_chart_discrete/scatter_chart_discrete.gd:
--------------------------------------------------------------------------------
1 | extends Control
2 |
3 | @onready var chart: Chart = $VBoxContainer/Chart
4 |
5 | func _ready():
6 | # X values will be the hours of the day, starting with 0 ending on 23.
7 | var x: Array = range(0, 24).map(func(i) -> String: return "%d - %d h" % [i, i+1])
8 |
9 | # Arrays contain how many animals have been seen in each hour.
10 | var blackbird_spots: Array = [0, 0, 0, 0, 0, 0, 0, 4, 5, 3, 6, 0, 0, 0, 2, 0, 0, 4, 5, 0, 0, 0, 0, 0]
11 | var nightingale_spots: Array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 2, 1, 0, 4, 4, 0, 3, 0, 0]
12 |
13 | # Let's customize the chart properties, which specify how the chart
14 | # should look, plus some additional elements like labels, the scale, etc...
15 | var cp: ChartProperties = ChartProperties.new()
16 | cp.colors.frame = Color("#161a1d")
17 | cp.colors.background = Color.TRANSPARENT
18 | cp.colors.grid = Color("#283442")
19 | cp.colors.ticks = Color("#283442")
20 | cp.colors.text = Color.WHITE_SMOKE
21 | cp.draw_bounding_box = false
22 | cp.title = "Animal spots"
23 | cp.x_label = "Time"
24 | cp.y_label = "Spots"
25 | cp.interactive = true
26 | cp.show_legend = true
27 |
28 | # Let's add values to our functions
29 | var blackbird_function = Function.new(
30 | x,
31 | blackbird_spots,
32 | "Blackbird",
33 | { color = Color.GREEN, marker = Function.Marker.CIRCLE, type = Function.Type.SCATTER }
34 | )
35 |
36 | var nightingale_function = Function.new(
37 | x,
38 | nightingale_spots,
39 | "Nightingale",
40 | { color = Color.BLUE, marker = Function.Marker.CROSS, type = Function.Type.SCATTER }
41 | )
42 |
43 | # Configure the y axis. We set the scale and domain in such
44 | # that we get ticks only on integers, not on floats.
45 | # We also configure the label function to not print decimal places.
46 | var y_max_value := 0
47 | for i in range(0, 24):
48 | if blackbird_spots[i] > y_max_value:
49 | y_max_value = blackbird_spots[i]
50 | if nightingale_spots[i] > y_max_value:
51 | y_max_value = nightingale_spots[i]
52 | # Add one or two on top so that we have some nice spacing
53 | y_max_value += 2 if (y_max_value % 2) == 0 else 1
54 | cp.y_scale = y_max_value / 2
55 | chart.set_y_domain(0, y_max_value)
56 | chart.y_labels_function = func(value: float): return str(int(value))
57 |
58 | # Now let's plot our data
59 | chart.plot([blackbird_function, nightingale_function], cp)
60 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/scatter_chart_discrete/scatter_chart_discrete.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cwjc16brbjkia
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/scatter_chart_discrete/scatter_chart_discrete.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://duq43d7ll1aah"]
2 |
3 | [ext_resource type="Script" uid="uid://cwjc16brbjkia" path="res://addons/easy_charts/examples/scatter_chart_discrete/scatter_chart_discrete.gd" id="1_3npap"]
4 | [ext_resource type="PackedScene" uid="uid://dlwq4kmdb3bhs" path="res://addons/easy_charts/control_charts/chart.tscn" id="2_pd01x"]
5 |
6 | [sub_resource type="StyleBoxFlat" id="1"]
7 | content_margin_right = 5.0
8 | content_margin_bottom = 5.0
9 | draw_center = false
10 | border_width_right = 2
11 | border_width_bottom = 2
12 | border_color = Color(0, 0, 0, 1)
13 |
14 | [node name="Control2" type="Control"]
15 | layout_mode = 3
16 | anchors_preset = 15
17 | anchor_right = 1.0
18 | anchor_bottom = 1.0
19 | grow_horizontal = 2
20 | grow_vertical = 2
21 | script = ExtResource("1_3npap")
22 |
23 | [node name="VBoxContainer" type="VBoxContainer" parent="."]
24 | layout_mode = 0
25 | anchor_right = 1.0
26 | anchor_bottom = 1.0
27 |
28 | [node name="Chart" parent="VBoxContainer" instance=ExtResource("2_pd01x")]
29 | layout_mode = 2
30 |
31 | [node name="Label" type="Label" parent="VBoxContainer"]
32 | layout_mode = 2
33 | size_flags_horizontal = 8
34 | theme_override_colors/font_color = Color(0, 0, 0, 1)
35 | theme_override_styles/normal = SubResource("1")
36 | text = "Try to scale the window!"
37 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/simple_chart/simple_chart_example.gd:
--------------------------------------------------------------------------------
1 | # This example shows how to instantiate a Chart node at runtime and plot a single function
2 |
3 | extends Control
4 |
5 | @onready var chart_scn: PackedScene = load("res://addons/easy_charts/control_charts/chart.tscn")
6 | var chart: Chart
7 |
8 | # This Chart will plot 1 function
9 | var f1: Function
10 |
11 | func _ready():
12 | chart = chart_scn.instantiate()
13 | $VBoxContainer.add_child(chart)
14 |
15 | # Let's create our @x values
16 | var x: Array = ArrayOperations.multiply_float(range(-10, 11, 1), 0.5)
17 |
18 | # And our y values. It can be an n-size array of arrays.
19 | # NOTE: `x.size() == y.size()` or `x.size() == y[n].size()`
20 | var y: Array = ArrayOperations.multiply_int(ArrayOperations.cos(x), 20)
21 |
22 | # Let's add values to our functions
23 | f1 = Function.new(x, y, "Pressure", { marker = Function.Marker.CIRCLE })
24 |
25 | # Set fixed Y domain
26 | chart.set_y_domain(-50, 50)
27 |
28 | # Now let's plot our data
29 | chart.plot([f1])
30 |
31 | # Uncommenting this line will show how real time data plotting works
32 | set_process(false)
33 |
34 |
35 | var new_val: float = 4.5
36 |
37 | func _process(delta: float):
38 | # This function updates the values of a function and then updates the plot
39 | new_val += 5
40 |
41 | # we can use the `Function.add_point(x, y)` method to update a function
42 | f1.add_point(new_val, cos(new_val) * 20)
43 | chart.queue_redraw() # This will force the Chart to be updated
44 |
45 |
46 | func _on_CheckButton_pressed():
47 | set_process(not is_processing())
48 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/simple_chart/simple_chart_example.gd.uid:
--------------------------------------------------------------------------------
1 | uid://dikwjry6sb804
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/examples/simple_chart/simple_chart_example.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://v4c2f17q8a1o"]
2 |
3 | [ext_resource type="Script" uid="uid://dikwjry6sb804" path="res://addons/easy_charts/examples/simple_chart/simple_chart_example.gd" id="1"]
4 |
5 | [sub_resource type="StyleBoxFlat" id="1"]
6 | content_margin_right = 5.0
7 | content_margin_bottom = 5.0
8 | draw_center = false
9 | border_width_right = 2
10 | border_width_bottom = 2
11 | border_color = Color(0, 0, 0, 1)
12 |
13 | [node name="Control2" type="Control"]
14 | layout_mode = 3
15 | anchors_preset = 15
16 | anchor_right = 1.0
17 | anchor_bottom = 1.0
18 | grow_horizontal = 2
19 | grow_vertical = 2
20 | script = ExtResource("1")
21 |
22 | [node name="VBoxContainer" type="VBoxContainer" parent="."]
23 | layout_mode = 0
24 | anchor_right = 1.0
25 | anchor_bottom = 1.0
26 |
27 | [node name="CheckButton" type="CheckButton" parent="VBoxContainer"]
28 | layout_mode = 2
29 | theme_override_colors/font_disabled_color = Color(0, 0, 0, 1)
30 | theme_override_colors/font_hover_pressed_color = Color(0, 0, 0, 1)
31 | theme_override_colors/font_hover_color = Color(0, 0, 0, 1)
32 | theme_override_colors/font_color = Color(0, 0, 0, 1)
33 | theme_override_colors/font_focus_color = Color(0, 0, 0, 1)
34 | theme_override_colors/font_pressed_color = Color(0, 0, 0, 1)
35 | text = "Start Relatime Plotting"
36 |
37 | [node name="Label" type="Label" parent="VBoxContainer"]
38 | layout_mode = 2
39 | size_flags_horizontal = 8
40 | theme_override_colors/font_color = Color(0, 0, 0, 1)
41 | theme_override_styles/normal = SubResource("1")
42 | text = "Try to scale the window!"
43 |
44 | [connection signal="pressed" from="VBoxContainer/CheckButton" to="." method="_on_CheckButton_pressed"]
45 |
--------------------------------------------------------------------------------
/addons/easy_charts/icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/easy_charts/plugin.cfg:
--------------------------------------------------------------------------------
1 | [plugin]
2 |
3 | name="EasyCharts"
4 | description=""
5 | author="Nicolò \"fenix\" Santilio"
6 | version="14.08.2023"
7 | script="plugin.gd"
8 |
--------------------------------------------------------------------------------
/addons/easy_charts/plugin.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends EditorPlugin
3 |
4 | func _enter_tree():
5 | pass
6 |
7 | func _exit_tree():
8 | pass
9 |
--------------------------------------------------------------------------------
/addons/easy_charts/plugin.gd.uid:
--------------------------------------------------------------------------------
1 | uid://0iisdi8dlupw
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/templates.json:
--------------------------------------------------------------------------------
1 | {
2 | "default":
3 | {
4 | "function_colors" : ["#1e1e1e","#1e1e1e","#1e1e1e","#1e1e1e"],
5 | "v_lines_color" : "#cacaca",
6 | "h_lines_color" : "#cacaca",
7 | "outline_color" : "#1e1e1e",
8 | "font_color" : "#1e1e1e"
9 | },
10 | "clean":
11 | {
12 | "function_colors" : ["#f7aa29","#f4394a","#5a6b7b","#8fbf59","#504538","#B7A99A","#00D795","#FFECCC","#FF8981"],
13 | "v_lines_color" : "#00000000",
14 | "h_lines_color" : "#3cffffff",
15 | "outline_color" : "#00000000",
16 | "font_color" : "#3cffffff"
17 | },
18 | "gradient":
19 | {
20 | "function_colors" : ["#F7AA29","#B8A806","#79A117","#2C9433","#00854C","#006571","#2F4858","#2a364f","#27294a"],
21 | "v_lines_color" : "#64ffffff",
22 | "h_lines_color" : "#64ffffff",
23 | "outline_color" : "#64ffffff",
24 | "font_color" : "#64ffffff",
25 | },
26 | "minimal":
27 | {
28 | "function_colors" : ["#1e1e1e","#1e1e1e","#1e1e1e","#1e1e1e"],
29 | "v_lines_color" : "#00000000",
30 | "h_lines_color" : "#00000000",
31 | "outline_color" : "#00000000",
32 | "font_color" : "#00000000"
33 | },
34 | "invert":
35 | {
36 | "function_colors" : ["#ffffff","#ffffff","#ffffff","#ffffff"],
37 | "v_lines_color" : "#3b3b3b",
38 | "h_lines_color" : "#3b3b3b",
39 | "outline_color" : "#ffffff",
40 | "font_color" : "#ffffff"
41 | },
42 | }
43 |
44 |
45 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/assets/OpenSans-VariableFont_wdth,wght.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fenix-hub/godot-engine.easy-charts/6cbff1d93d0e8fcc8d9cbb56f85ee641e52bed5e/addons/easy_charts/utilities/assets/OpenSans-VariableFont_wdth,wght.ttf
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/classes/plotting/bar.gd:
--------------------------------------------------------------------------------
1 | extends RefCounted
2 | class_name Bar
3 |
4 | #var rect: Rect2
5 | #var value: Pair
6 | #
7 | #func _init(rect: Rect2, value: Pair = Pair.new()) -> void:
8 | # self.value = value
9 | # self.rect = rect
10 |
11 | func _to_string() -> String:
12 | return "Value: %s\nRect: %s" % [self.value, self.rect]
13 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/classes/plotting/bar.gd.uid:
--------------------------------------------------------------------------------
1 | uid://b4nla6hrwhv7r
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/classes/plotting/chart_properties.gd:
--------------------------------------------------------------------------------
1 | extends RefCounted
2 | class_name ChartProperties
3 |
4 | var title: String
5 | var x_label: String
6 | var y_label: String
7 |
8 | ## {n}_scale defines in how many sectors the grid will be divided.
9 | ## This can only be used with non-discrete axes.
10 | var x_scale: float = 5
11 | var y_scale: float = 2
12 |
13 | var x_tick_size: float = 7
14 | var x_ticklabel_space: float = 5
15 | var y_tick_size: float = 7
16 | var y_ticklabel_space: float = 5
17 |
18 | ## Scale type, 0 = linear | 1 = logarithmic
19 | var x_scale_type: int = 0
20 | var y_scale_type: int = 0
21 |
22 | var draw_borders: bool = true
23 | var draw_frame: bool = true
24 | var draw_background: bool = true
25 | var draw_bounding_box: bool = true
26 | var draw_vertical_grid: bool = true
27 | var draw_horizontal_grid: bool = true
28 | var draw_ticks: bool = true
29 | var draw_origin: bool = false
30 | var draw_grid_box: bool = true
31 | var show_tick_labels: bool = true
32 | var show_x_label: bool = true
33 | var show_y_label: bool = true
34 | var show_title: bool = true
35 |
36 | ## If true will show the legend of your Chart on the right side of the frame.
37 | var show_legend: bool = false
38 |
39 | ## If true will make the Chart interactive, i.e. the DataTooltip will be displayed when
40 | ## hovering points with your mouse, and mouse_entered and mouse_exited signal will be emitted.
41 | var interactive: bool = false
42 |
43 | ## If true, will smooth the domain lower and upper bounds to the closest rounded value,
44 | ## instead of using precise values.
45 | var smooth_domain: bool = false
46 |
47 | ## If > 0, will limit the amount of points plotted in a Chart, discarding older values.
48 | ## [b]Note:[/b] this parameter will not make the Chart remove points from your Function objects,
49 | ## instead older points will be just ignored. This will make your Function object x and y arrays
50 | ## grow linearly, but won't interfere with your own data.
51 | ## If you instead prefer to improve performances by completely remove older data from your Function
52 | ## object, consider calling the Function.remove_point(0) method before adding a new point and plotting
53 | ## again.
54 | var max_samples: int = 100
55 |
56 | ## Dictionary of colors for all of the Chart elements.
57 | var colors: Dictionary = {
58 | frame = Color.WHITE_SMOKE,
59 | background = Color.WHITE,
60 | borders = Color.RED,
61 | bounding_box = Color.BLACK,
62 | grid = Color.GRAY,
63 | ticks = Color.BLACK,
64 | text = Color.BLACK,
65 | origin = Color.DIM_GRAY
66 | }
67 |
68 | var font: FontFile = load("res://addons/easy_charts/utilities/assets/OpenSans-VariableFont_wdth,wght.ttf")
69 | var font_size: int = 13
70 |
71 | func _init() -> void:
72 | ThemeDB.set_fallback_font(font)
73 | ThemeDB.set_fallback_font_size(font_size)
74 |
75 | func get_string_size(text: String) -> Vector2:
76 | return font.get_string_size(text)
77 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/classes/plotting/chart_properties.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cqbk7nq5ilrp4
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/classes/plotting/function.gd:
--------------------------------------------------------------------------------
1 | extends RefCounted
2 | class_name Function
3 |
4 | enum Type {
5 | SCATTER,
6 | LINE,
7 | AREA,
8 | PIE,
9 | BAR
10 | }
11 |
12 | enum Interpolation {
13 | NONE,
14 | LINEAR,
15 | STAIR,
16 | SPLINE
17 | }
18 |
19 | # TODO: add new markers, like an empty circle, an empty box, etc.
20 | enum Marker {
21 | NONE,
22 | CIRCLE,
23 | TRIANGLE,
24 | SQUARE,
25 | CROSS
26 | }
27 |
28 | var __x: Array
29 | var __y: Array
30 | var name: String
31 | var props: Dictionary = {}
32 |
33 | func _init(x: Array, y: Array, name: String = "", props: Dictionary = {}) -> void:
34 | self.__x = x.duplicate()
35 | self.__y = y.duplicate()
36 | self.name = name
37 | if not props.is_empty() and props != null:
38 | self.props = props
39 |
40 | func get_point(index: int) -> Array:
41 | return [self.__x[index], self.__y[index]]
42 |
43 | func add_point(x: float, y: float) -> void:
44 | self.__x.append(x)
45 | self.__y.append(y)
46 |
47 | func set_point(index: int, x: float, y: float) -> void:
48 | self.__x[index] = x
49 | self.__y[index] = y
50 |
51 | func remove_point(index: int) -> void:
52 | self.__x.remove_at(index)
53 | self.__y.remove_at(index)
54 |
55 | func pop_back_point() -> void:
56 | self.__x.pop_back()
57 | self.__y.pop_back()
58 |
59 | func pop_front_point() -> void:
60 | self.__x.pop_front()
61 | self.__y.pop_front()
62 |
63 | func count_points() -> int:
64 | return self.__x.size()
65 |
66 | func get_color() -> Color:
67 | return props.get("color", Color.DARK_SLATE_GRAY)
68 |
69 | func get_gradient() -> Gradient:
70 | return props.get("gradient", Gradient.new())
71 |
72 | func get_marker() -> int:
73 | return props.get("marker", Marker.NONE)
74 |
75 | func get_type() -> int:
76 | return props.get("type", Type.SCATTER)
77 |
78 | func get_interpolation() -> int:
79 | return props.get("interpolation", Interpolation.LINEAR)
80 |
81 | func get_line_width() -> float:
82 | return props.get("line_width", 2.0)
83 |
84 | func get_visibility() -> bool:
85 | return props.get("visible", true)
86 |
87 | func copy() -> Function:
88 | return Function.new(
89 | self.__x.duplicate(),
90 | self.__y.duplicate(),
91 | self.name,
92 | self.props.duplicate(true)
93 | )
94 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/classes/plotting/function.gd.uid:
--------------------------------------------------------------------------------
1 | uid://4ekebvnyr8g1
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/classes/plotting/point.gd:
--------------------------------------------------------------------------------
1 | extends RefCounted
2 | class_name Point
3 |
4 | var position: Vector2
5 | var value: Dictionary
6 |
7 | func _init(position: Vector2, value: Dictionary) -> void:
8 | self.position = position
9 | self.value = value
10 |
11 | func _to_string() -> String:
12 | return "Value: %s\nPosition: %s" % [self.value, self.position]
13 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/classes/plotting/point.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cpnbl1h6tkmbd
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/classes/structures/array_operations.gd:
--------------------------------------------------------------------------------
1 | extends RefCounted
2 | class_name ArrayOperations
3 |
4 | static func add_int(array: Array, _int: int) -> Array:
5 | var t: Array = array.duplicate(true)
6 | for ti in t.size():
7 | t[ti] = int(t[ti] + _int)
8 | return t
9 |
10 | static func add_float(array: Array, _float: float) -> Array:
11 | var t: Array = array.duplicate(true)
12 | for ti in t.size():
13 | t[ti] = float(t[ti] + _float)
14 | return t
15 |
16 | static func multiply_int(array: Array, _int: int) -> Array:
17 | var t: Array = array.duplicate(true)
18 | for ti in t.size():
19 | t[ti] = int(t[ti] * _int)
20 | return t
21 |
22 | static func multiply_float(array: Array, _float: float) -> PackedFloat32Array:
23 | var t: PackedFloat32Array = array.duplicate(true)
24 | for ti in t.size():
25 | t[ti] = float(t[ti] * _float)
26 | return t
27 |
28 | static func pow(array: Array, _int: int) -> Array:
29 | var t: Array = array.duplicate(true)
30 | for ti in t.size():
31 | t[ti] = float(pow(t[ti], _int))
32 | return t
33 |
34 | static func cos(array: Array) -> Array:
35 | var t: Array = array.duplicate(true)
36 | for val in array.size():
37 | t[val] = cos(t[val])
38 | return t
39 |
40 | static func sin(array: Array) -> Array:
41 | var t: Array = array.duplicate(true)
42 | for val in array.size():
43 | t[val] = sin(t[val])
44 | return t
45 |
46 | static func affix(array: Array, _string: String) -> Array:
47 | var t: Array = array.duplicate(true)
48 | for val in array.size():
49 | t[val] = str(t[val]) + _string
50 | return t
51 |
52 | static func suffix(array: Array, _string: String) -> Array:
53 | var t: Array = array.duplicate(true)
54 | for val in array.size():
55 | t[val] = _string + str(t[val])
56 | return t
57 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/classes/structures/array_operations.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cdmhpsxlcakle
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/classes/structures/data_frame.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends Resource
3 | class_name DataFrame
4 |
5 | var table_name : String = ""
6 | var labels : PackedStringArray = []
7 | var headers : PackedStringArray = []
8 | var datamatrix : Matrix = null
9 | var dataset : Array = []
10 |
11 | func _init(datamatrix : Matrix, headers : PackedStringArray = [], labels : PackedStringArray = [] , table_name : String = "") -> void:
12 | if datamatrix.is_empty(): datamatrix.resize(labels.size(), headers.size())
13 | if labels.is_empty() : for label in range(datamatrix.get_size().x) : labels.append(label as String)
14 | if headers.is_empty() : for header in range(datamatrix.get_size().y) : headers.append(MatrixGenerator.get_letter_index(header))
15 | build_dataframe(datamatrix, headers, labels, table_name)
16 |
17 | func build_dataframe(datamatrix : Matrix, headers : PackedStringArray = [], labels : PackedStringArray = [] , table_name : String = "") -> void:
18 | self.datamatrix = datamatrix
19 | self.headers = headers
20 | self.labels = labels
21 | self.table_name = table_name
22 | self.dataset = build_dataset_from_matrix(datamatrix, headers, labels)
23 |
24 | func build_dataset_from_matrix(datamatrix : Matrix, headers : PackedStringArray, labels : PackedStringArray) -> Array:
25 | var data : Array = datamatrix.to_array()
26 | return build_dataset(data, headers, labels)
27 |
28 | func build_dataset(data : Array, headers : PackedStringArray, labels : PackedStringArray) -> Array:
29 | var dataset : Array = [Array([" "]) + Array(headers)]
30 | for row_i in range(labels.size()): dataset.append(([labels[row_i]] + data[row_i]) if not data.is_empty() else [labels[row_i]])
31 | return dataset
32 |
33 | func insert_column(column : Array, header : String = "", index : int = dataset[0].size() - 1) -> void:
34 | assert(column.size() == (datamatrix.rows() if not datamatrix.is_empty() else labels.size())) #,"error: the column size must match the dataset column size")
35 | headers.insert(index, header if header != "" else MatrixGenerator.get_letter_index(index))
36 | datamatrix.insert_column(column, index)
37 | dataset = build_dataset_from_matrix(datamatrix, headers, labels)
38 |
39 | func insert_row(row : Array, label : String = "", index : int = dataset.size() - 1) -> PackedStringArray:
40 | assert(row.size() == (datamatrix.columns() if not datamatrix.is_empty() else headers.size())) #,"error: the row size must match the dataset row size")
41 | labels.insert(index, label if label != "" else str(index))
42 | datamatrix.insert_row(row, index)
43 | dataset = build_dataset_from_matrix(datamatrix, headers, labels)
44 | return PackedStringArray([label] + row)
45 |
46 | func get_datamatrix() -> Matrix:
47 | return datamatrix
48 |
49 | func get_dataset() -> Array:
50 | return dataset
51 |
52 | func get_labels() -> PackedStringArray:
53 | return labels
54 |
55 | func transpose():
56 | build_dataframe(MatrixGenerator.transpose(datamatrix), labels, headers, table_name)
57 |
58 | func _to_string() -> String:
59 | var last_string_len : int
60 | for row in dataset:
61 | for column in row:
62 | var string_len : int = str(column).length()
63 | last_string_len = string_len if string_len > last_string_len else last_string_len
64 | var string : String = ""
65 | for row_i in dataset.size():
66 | for column_i in dataset[row_i].size():
67 | string+="%*s" % [last_string_len+1, dataset[row_i][column_i]]
68 | string+="\n"
69 | string+="\n['{table_name}' : {rows} rows x {columns} columns]\n".format({
70 | rows = datamatrix.rows(),
71 | columns = datamatrix.columns(),
72 | table_name = table_name})
73 | return string
74 |
75 | # ...............................................................................
76 |
77 | # Return a list of headers corresponding to a list of indexes
78 | func get_headers_names(indexes : PackedInt32Array) -> PackedStringArray:
79 | var headers : PackedStringArray = []
80 | for index in indexes:
81 | headers.append(dataset[0][index])
82 | return headers
83 |
84 | # Returns the index of an header
85 | func get_column_index(header : String) -> int:
86 | for headers_ix in range(dataset[0].size()):
87 | if dataset[0][headers_ix] == header:
88 | return headers_ix
89 | return -1
90 |
91 | # Get a column by its header
92 | func get_column(header : String) -> Array:
93 | var headers_i : int = get_column_index(header)
94 | if headers_i!=-1:
95 | return datamatrix.get_column(headers_i)
96 | else:
97 | return []
98 |
99 | # Get a list of columns by their headers
100 | func columns(headers : PackedStringArray) -> Matrix:
101 | var values : Array = []
102 | for header in headers:
103 | values.append(get_column(header))
104 | return MatrixGenerator.transpose(Matrix.new(values))
105 |
106 |
107 | # Get a column by its index
108 | func get_icolumn(index : int) -> Array:
109 | return datamatrix.get_column(index)
110 |
111 | # Get a list of columns by their indexes
112 | func get_icolumns(indexes : PackedInt32Array) -> Array:
113 | var values : Array = []
114 | for index in indexes:
115 | values.append(datamatrix.get_column(index))
116 | return values
117 |
118 | # Returns the list of labels corresponding to the list of indexes
119 | func get_labels_names(indexes : PackedInt32Array) -> PackedStringArray:
120 | var headers : PackedStringArray = []
121 | for index in indexes:
122 | headers.append(dataset[index][0])
123 | return headers
124 |
125 | # Returns the index of a label
126 | func get_row_index(label : String) -> int:
127 | for row in dataset.size():
128 | if dataset[row][0] == label:
129 | return row
130 | return -1
131 |
132 | # Get a row by its label
133 | func get_row(label : String) -> Array:
134 | var index : int = get_row_index(label)
135 | if index == -1 :
136 | return []
137 | else:
138 | return datamatrix.get_row(index)
139 |
140 | # Get a list of rows by their labels
141 | func rows(labels : Array) -> Matrix:
142 | var values : Array = []
143 | for label in labels:
144 | values.append(get_row(label))
145 | return Matrix.new(values)
146 |
147 | # Get a row by its index
148 | func get_irow(index : int) -> Array:
149 | return datamatrix.get_row(index)
150 |
151 | # Get a list of rows by their indexes
152 | func get_irows(indexes : PackedInt32Array) -> Array:
153 | var values : Array = []
154 | for index in indexes:
155 | values.append(datamatrix.get_row(index))
156 | return values
157 |
158 | # Returns a a group of rows or a group of columns, using indexes or names
159 | # dataset["0;5"] ---> Returns an array containing all rows from the 1st to the 4th
160 | # dataset["0:5"] ---> Returns an array containing all columns from the 1st to the 4th
161 | # dataset["label0;label5"] ---> Returns an array containing all row from the one with label == "label0" to the one with label == "label5"
162 | # dataset["header0:header0"] ---> Returns an array containing all columns from the one with label == "label0" to the one with label == "label5"
163 | func _get(_property : StringName):
164 | # ":" --> Columns
165 | if ":" in _property:
166 | var property : PackedStringArray = _property.split(":")
167 | if (property[0]).is_valid_int():
168 | if property[1] == "*":
169 | return get_icolumns(range(property[0] as int, headers.size()-1))
170 | else:
171 | return get_icolumns(range(property[0] as int, property[1] as int +1))
172 | else:
173 | if property[1] == "*":
174 | return get_icolumns(range(get_column_index(property[0]), headers.size()-1))
175 | else:
176 | return get_icolumns(range(get_column_index(property[0]), get_column_index(property[1])))
177 | # ";" --> Rows
178 | elif ";" in _property:
179 | var property : PackedStringArray = _property.split(";")
180 | if (property[0]).is_valid_int():
181 | return get_irows(range(property[0] as int, property[1] as int + 1 ))
182 | else:
183 | return get_irows(range(get_row_index(property[0]), get_row_index(property[1])))
184 | elif "," in _property:
185 | var property : PackedStringArray = _property.split(",")
186 | else:
187 | if (_property as String).is_valid_int():
188 | return get_icolumn(int(_property))
189 | else:
190 | return get_column(_property)
191 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/classes/structures/data_frame.gd.uid:
--------------------------------------------------------------------------------
1 | uid://bbr722edegy4c
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/classes/structures/matrix.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends Resource
3 | class_name Matrix
4 |
5 | var values : Array = []
6 |
7 | func _init(matrix : Array = [], size : int = 0) -> void:
8 | values = matrix
9 |
10 | func insert_row(row : Array, index : int = values.size()) -> void:
11 | if rows() != 0:
12 | assert(row.size() == columns()) #,"the row size must match matrix row size")
13 | values.insert(index, row)
14 |
15 | func update_row(row : Array, index : int) -> void:
16 | assert(rows() > index) #,"the row size must match matrix row size")
17 | values[index] = row
18 |
19 | func remove_row(index: int) -> void:
20 | assert(rows() > index) #,"the row size must match matrix row size")
21 | values.remove_at(index)
22 |
23 | func insert_column(column : Array, index : int = values[0].size()) -> void:
24 | if columns() != 0:
25 | assert(column.size() == rows()) #,"the column size must match matrix column size")
26 | for row_idx in column.size():
27 | values[row_idx].insert(index, column[row_idx])
28 |
29 | func update_column(column : Array, index : int) -> void:
30 | assert(columns() > index) #,"the column size must match matrix column size")
31 | for row_idx in column.size():
32 | values[row_idx][index] = column[row_idx]
33 |
34 | func remove_column(index: int) -> void:
35 | assert(columns() > index) #,"the column index must be at least equals to the rows count")
36 | for row in get_rows():
37 | row.remove(index)
38 |
39 | func resize(rows: int, columns: int) -> void:
40 | for row in range(rows):
41 | var row_column: Array = []
42 | row_column.resize(columns)
43 | values.append(row_column)
44 |
45 | func to_array() -> Array:
46 | return values.duplicate(true)
47 |
48 | func get_size() -> Vector2:
49 | return Vector2(rows(), columns())
50 |
51 | func rows() -> int:
52 | return values.size()
53 |
54 | func columns() -> int:
55 | return values[0].size() if rows() != 0 else 0
56 |
57 | func value(row: int, column: int) -> float:
58 | return values[row][column]
59 |
60 | func set_value(value: float, row: int, column: int) -> void:
61 | values[row][column] = value
62 |
63 | func get_column(column : int) -> Array:
64 | assert(column < columns()) #,"index of the column requested (%s) exceedes matrix columns (%s)"%[column, columns()])
65 | var column_array : Array = []
66 | for row in values:
67 | column_array.append(row[column])
68 | return column_array
69 |
70 | func get_columns(from : int = 0, to : int = columns()-1) -> Array:
71 | var values : Array = []
72 | for column in range(from, to):
73 | values.append(get_column(column))
74 | return values
75 | # return MatrixGenerator.from_array(values)
76 |
77 | func get_row(row : int) -> Array:
78 | assert(row < rows()) #,"index of the row requested (%s) exceedes matrix rows (%s)"%[row, rows()])
79 | return values[row]
80 |
81 | func get_rows(from : int = 0, to : int = rows()-1) -> Array:
82 | return values.slice(from, to)
83 | # return MatrixGenerator.from_array(values)
84 |
85 | func is_empty() -> bool:
86 | return rows() == 0 and columns() == 0
87 |
88 |
89 | func is_square() -> bool:
90 | return columns() == rows()
91 |
92 |
93 | func is_diagonal() -> bool:
94 | if not is_square():
95 | return false
96 |
97 | for i in rows():
98 | for j in columns():
99 | if i != j and values[i][j] != 0:
100 | return false
101 |
102 | return true
103 |
104 |
105 | func is_upper_triangular() -> bool:
106 | if not is_square():
107 | return false
108 |
109 | for i in rows():
110 | for j in columns():
111 | if i > j and values[i][j] != 0:
112 | return false
113 |
114 | return true
115 |
116 |
117 | func is_lower_triangular() -> bool:
118 | if not is_square():
119 | return false
120 |
121 | for i in rows():
122 | for j in columns():
123 | if i < j and values[i][j] != 0:
124 | return false
125 |
126 | return true
127 |
128 |
129 | func is_triangular() -> bool:
130 | return is_upper_triangular() or is_lower_triangular()
131 |
132 |
133 | func is_identity() -> bool:
134 | if not is_diagonal():
135 | return false
136 |
137 | for i in rows():
138 | if values[i][i] != 1:
139 | return false
140 |
141 | return true
142 |
143 | func _to_string() -> String:
144 | var last_string_len : int
145 | for row in values:
146 | for column in row:
147 | var string_len : int = str(column).length()
148 | last_string_len = string_len if string_len > last_string_len else last_string_len
149 | var string : String = "\n"
150 | for row_i in values.size():
151 | for column_i in values[row_i].size():
152 | string+="%*s" % [last_string_len+1 if column_i!=0 else last_string_len, values[row_i][column_i]]
153 | string+="\n"
154 | return string
155 |
156 | # ----
157 | func set(position: StringName, value: Variant) -> void:
158 | var t_pos: Array = position.split(",")
159 | values[t_pos[0]][t_pos[1]] = value
160 |
161 | # --------------
162 | func _get(_property : StringName):
163 | # ":" --> Columns
164 | if ":" in _property:
165 | var property : PackedStringArray = _property.split(":")
166 | var from : PackedStringArray = property[0].split(",")
167 | var to : PackedStringArray = property[1].split(",")
168 | elif "," in _property:
169 | var property : PackedStringArray = _property.split(",")
170 | if property.size() == 2:
171 | return get_row(property[0] as int)[property[1] as int]
172 | else:
173 | if (_property as String).is_valid_int():
174 | return get_row(int(_property))
175 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/classes/structures/matrix.gd.uid:
--------------------------------------------------------------------------------
1 | uid://divbwqjaxgmeh
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/classes/structures/matrix_generator.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends RefCounted
3 | class_name MatrixGenerator
4 |
5 | static func zeros(rows: int, columns: int) -> Matrix:
6 | var zeros: Array = []
7 | var t_rows: Array = []
8 | t_rows.resize(columns)
9 | t_rows.fill(0.0)
10 | for row in rows:
11 | zeros.append(t_rows.duplicate())
12 | return Matrix.new(zeros)
13 |
14 | # Generates a Matrix with random values between [from; to] with a given @size (rows, columns)
15 | static func random_float_range(from : float, to : float, size : Vector2, _seed : int = 1234) -> Matrix:
16 | seed(_seed)
17 | randomize()
18 | var array : Array = []
19 | for row in range(size.x):
20 | var matrix_row : Array = []
21 | for column in range(size.y): matrix_row.append(randf_range(from,to))
22 | array.append(matrix_row)
23 | return Matrix.new(array)
24 |
25 | # Generates a Matrix giving an Array (Array must by Array[Array])
26 | static func from_array(array : Array = []) -> Matrix:
27 | var matrix : Array = []
28 | matrix.append(array)
29 | return Matrix.new(matrix)
30 |
31 | # Generates a sub-Matrix giving a Matrix, a @from Array [row_i, column_i] and a @to Array [row_j, column_j]
32 | static func sub_matrix(_matrix : Matrix, from : PackedInt32Array, to : PackedInt32Array) -> Matrix:
33 | assert( not (to[0] > _matrix.rows() or to[1] > _matrix.columns()),
34 | "%s is not an acceptable size for the submatrix, giving a matrix of size %s"%[to, _matrix.get_size()])
35 | var array : Array = []
36 | var rows : Array = _matrix.get_rows(from[0], to[0])
37 | for row in rows:
38 | array.append(row.slice(from[1], to[1]))
39 | return Matrix.new(array)
40 |
41 | # Duplicates a given Matrix
42 | static func duplicate(_matrix : Matrix) -> Matrix:
43 | return Matrix.new(_matrix.to_array().duplicate())
44 |
45 | # Calculate the determinant of a matrix
46 | static func determinant(matrix: Matrix) -> float:
47 | assert(matrix.is_square()) #,"Expected square matrix")
48 |
49 | var determinant: float = 0.0
50 |
51 | if matrix.rows() == 2 :
52 | determinant = (matrix.value(0, 0) * matrix.value(1, 1)) - (matrix.value(0, 1) * matrix.value(1, 0))
53 | elif matrix.is_diagonal() or matrix.is_triangular() :
54 | for i in matrix.rows():
55 | determinant *= matrix.value(i, i)
56 | elif matrix.is_identity() :
57 | determinant = 1.0
58 | else:
59 | # Laplace expansion
60 | var multiplier: float = -1.0
61 | var submatrix: Matrix = sub_matrix(matrix, [1, 0], [matrix.rows(), matrix.columns()])
62 | for j in matrix.columns() :
63 | var cofactor: Matrix = copy(submatrix)
64 | cofactor.remove_column(j)
65 | multiplier *= -1.0
66 | determinant += multiplier * matrix.value(0, j) * determinant(cofactor)
67 |
68 | return determinant
69 |
70 |
71 | # Calculate the inverse of a Matrix
72 | static func inverse(matrix: Matrix) -> Matrix:
73 | var inverse: Matrix
74 |
75 | # Minors and Cofactors
76 | var minors_cofactors: Matrix = zeros(matrix.rows(), matrix.columns())
77 | var multiplier: float = -1.0
78 |
79 | for i in minors_cofactors.rows():
80 | for j in minors_cofactors.columns():
81 | var t_minor: Matrix = copy(matrix)
82 | t_minor.remove_row(i)
83 | t_minor.remove_column(j)
84 | multiplier *= -1.0
85 | minors_cofactors.set_value(multiplier * determinant(t_minor), i, j)
86 |
87 | var transpose: Matrix = transpose(minors_cofactors)
88 | var determinant: float = determinant(matrix)
89 |
90 | inverse = multiply_float(transpose, 1 / determinant)
91 |
92 | return inverse
93 |
94 | # Transpose a given Matrix
95 | static func transpose(_matrix : Matrix) -> Matrix:
96 | var array : Array = []
97 | array.resize(_matrix.get_size().y)
98 | var row : Array = []
99 | row.resize(_matrix.get_size().x)
100 | for x in array.size():
101 | array[x] = row.duplicate()
102 | for i in range(_matrix.get_size().x):
103 | for j in range(_matrix.get_size().y):
104 | array[j][i] = (_matrix.to_array()[i][j])
105 | return Matrix.new(array)
106 |
107 | # Calculates the dot product (A*B) matrix between two Matrixes
108 | static func dot(_matrix1 : Matrix, _matrix2 : Matrix) -> Matrix:
109 | if _matrix1.get_size().y != _matrix2.get_size().x:
110 | printerr("matrix1 number of columns: %s must be the same as matrix2 number of rows: %s"%[_matrix1.get_size().y, _matrix2.get_size().x])
111 | return Matrix.new()
112 | var array : Array = []
113 | for x in range(_matrix1.get_size().x):
114 | var row : Array = []
115 | for y in range(_matrix2.get_size().y):
116 | var sum : float
117 | for k in range(_matrix1.get_size().y):
118 | sum += (_matrix1.to_array()[x][k]*_matrix2.to_array()[k][y])
119 | row.append(sum)
120 | array.append(row)
121 | return Matrix.new(array)
122 |
123 | # Calculates the hadamard (element-wise product) between two Matrixes
124 | static func hadamard(_matrix1 : Matrix, _matrix2 : Matrix) -> Matrix:
125 | if _matrix1.get_size() != _matrix2.get_size():
126 | printerr("matrix1 size: %s must be the same as matrix2 size: %s"%[_matrix1.get_size(), _matrix2.get_size()])
127 | return Matrix.new()
128 | var array : Array = []
129 | for x in range(_matrix1.to_array().size()):
130 | var row : Array = []
131 | for y in range(_matrix1.to_array()[x].size()):
132 | assert(typeof(_matrix1.to_array()[x][y]) != TYPE_STRING and typeof(_matrix2.to_array()[x][y]) != TYPE_STRING) #,"can't apply operations over a Matrix of Strings")
133 | row.append(_matrix1.to_array()[x][y] * _matrix2.to_array()[x][y])
134 | array.append(row)
135 | return Matrix.new(array)
136 |
137 | # Multiply a given Matrix for an int value
138 | static func multiply_int(_matrix1 : Matrix, _int : int) -> Matrix:
139 | var array : Array = _matrix1.to_array().duplicate()
140 | for x in range(_matrix1.to_array().size()):
141 | for y in range(_matrix1.to_array()[x].size()):
142 | array[x][y]*=_int
143 | array[x][y] = int(array[x][y])
144 | return Matrix.new(array)
145 |
146 | # Multiply a given Matrix for a float value
147 | static func multiply_float(_matrix1 : Matrix, _float : float) -> Matrix:
148 | var array : Array = _matrix1.to_array().duplicate()
149 | for x in range(_matrix1.to_array().size()):
150 | for y in range(_matrix1.to_array()[x].size()):
151 | array[x][y]*=_float
152 | return Matrix.new(array)
153 |
154 |
155 | static func copy(matrix: Matrix) -> Matrix:
156 | return Matrix.new(matrix.values.duplicate(true))
157 |
158 | # ------------------------------------------------------------
159 | static func get_letter_index(index : int) -> String:
160 | return "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z".split(" ")[index]
161 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/classes/structures/matrix_generator.gd.uid:
--------------------------------------------------------------------------------
1 | uid://814r3hcgvci3
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/containers/canvas/canvas.gd:
--------------------------------------------------------------------------------
1 | extends Control
2 | class_name Canvas
3 |
4 | @onready var _title_lbl: Label = $CanvasContainer/Title
5 | @onready var _x_lbl: Label = $CanvasContainer/DataContainer/PlotContainer/XLabel
6 | @onready var _y_lbl: Label = $CanvasContainer/DataContainer/YLabel
7 | @onready var _legend: FunctionLegend = $CanvasContainer/DataContainer/FunctionLegend
8 |
9 | func _ready():
10 | pass # Replace with function body.
11 |
12 | func prepare_canvas(chart_properties: ChartProperties) -> void:
13 |
14 | if chart_properties.draw_frame:
15 | set_color(chart_properties.colors.frame)
16 | set_frame_visible(true)
17 | else:
18 | set_frame_visible(false)
19 |
20 | if chart_properties.show_title:
21 | update_title(chart_properties.title, chart_properties.colors.text)
22 | else:
23 | _title_lbl.hide()
24 |
25 | if chart_properties.show_x_label:
26 | update_x_label(chart_properties.x_label, chart_properties.colors.text)
27 | else:
28 | _x_lbl.hide()
29 |
30 | if chart_properties.show_y_label:
31 | update_y_label(chart_properties.y_label, chart_properties.colors.text, -90)
32 | else:
33 | _y_lbl.hide()
34 |
35 | if chart_properties.show_legend:
36 | _legend.show()
37 | else:
38 | hide_legend()
39 |
40 | func update_title(text: String, color: Color, rotation: float = 0.0) -> void:
41 | _title_lbl.show()
42 | _update_canvas_label(_title_lbl, text, color, rotation)
43 |
44 | func update_y_label(text: String, color: Color, rotation: float = 0.0) -> void:
45 | _y_lbl.show()
46 | _update_canvas_label(_y_lbl, text, color, rotation)
47 |
48 | func update_x_label(text: String, color: Color, rotation: float = 0.0) -> void:
49 | _x_lbl.show()
50 | _update_canvas_label(_x_lbl, text, color, rotation)
51 |
52 | func _update_canvas_label(canvas_label: Label, text: String, color: Color, rotation: float = 0.0) -> void:
53 | canvas_label.set_text(text)
54 | canvas_label.modulate = color
55 | canvas_label.rotation = rotation
56 |
57 | func hide_legend() -> void:
58 | _legend.hide()
59 |
60 | func set_color(color: Color) -> void:
61 | get("theme_override_styles/panel").set("bg_color", color)
62 |
63 | func set_frame_visible(visible: bool) -> void:
64 | get("theme_override_styles/panel").set("draw_center", visible)
65 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/containers/canvas/canvas.gd.uid:
--------------------------------------------------------------------------------
1 | uid://d3eig7fx6wtli
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/containers/canvas/plot_box/grid_box.gd:
--------------------------------------------------------------------------------
1 | extends Control
2 | class_name GridBox
3 |
4 | var x_domain: ChartAxisDomain = null
5 | var x_labels_function: Callable = Callable()
6 |
7 | var y_domain: ChartAxisDomain = null
8 | var y_labels_function: Callable = Callable()
9 |
10 | var box: Rect2
11 | var plot_box: Rect2
12 |
13 | # Called when the node enters the scene tree for the first time.
14 | func _ready():
15 | pass # Replace with function body.
16 |
17 | func set_domains(x_domain: ChartAxisDomain, y_domain: ChartAxisDomain) -> void:
18 | self.x_domain = x_domain
19 | self.y_domain = y_domain
20 |
21 | func set_labels_functions(x_labels_function: Callable, y_labels_function: Callable) -> void:
22 | self.x_labels_function = x_labels_function
23 | self.y_labels_function = y_labels_function
24 |
25 | func _draw() -> void:
26 | if get_parent().chart_properties == null:
27 | printerr("Cannot draw GridBox without ChartProperties!")
28 | return
29 |
30 | self.box = get_parent().get_box()
31 | self.plot_box = get_parent().get_plot_box()
32 |
33 | if get_parent().chart_properties.draw_background:
34 | _draw_background()
35 |
36 | if get_parent().chart_properties.draw_grid_box:
37 | _draw_x_ticks()
38 | _draw_y_ticks()
39 |
40 | if get_parent().chart_properties.draw_origin:
41 | _draw_origin()
42 |
43 | if get_parent().chart_properties.draw_bounding_box:
44 | _draw_bounding_box()
45 |
46 | func _draw_background() -> void:
47 | draw_rect(self.box, get_parent().chart_properties.colors.background, true)# false) TODOGODOT4 Antialiasing argument is missing
48 |
49 | func _draw_bounding_box() -> void:
50 | var box: Rect2 = self.box
51 | box.position.y += 1
52 | draw_rect(box, get_parent().chart_properties.colors.bounding_box, false, 1)# true) TODOGODOT4 Antialiasing argument is missing
53 |
54 | func _draw_origin() -> void:
55 | var xorigin: float = ECUtilities._map_domain(0.0, x_domain, ChartAxisDomain.from_bounds(self.plot_box.position.x, self.plot_box.end.x))
56 | var yorigin: float = ECUtilities._map_domain(0.0, y_domain, ChartAxisDomain.from_bounds(self.plot_box.end.y, self.plot_box.position.y))
57 |
58 | draw_line(Vector2(xorigin, self.plot_box.position.y), Vector2(xorigin, self.plot_box.position.y + self.plot_box.size.y), get_parent().chart_properties.colors.origin, 1)
59 | draw_line(Vector2(self.plot_box.position.x, yorigin), Vector2(self.plot_box.position.x + self.plot_box.size.x, yorigin), get_parent().chart_properties.colors.origin, 1)
60 | draw_string(
61 | get_parent().chart_properties.font, Vector2(xorigin, yorigin) - Vector2(15, -15), "O", HORIZONTAL_ALIGNMENT_CENTER, -1,
62 | ThemeDB.fallback_font_size, get_parent().chart_properties.colors.text, TextServer.JUSTIFICATION_NONE, TextServer.DIRECTION_AUTO, TextServer.ORIENTATION_HORIZONTAL
63 | )
64 |
65 |
66 | func _draw_x_ticks() -> void:
67 | var labels = x_domain.get_tick_labels()
68 | var tick_count = labels.size()
69 |
70 | var x_pixel_dist: float = self.plot_box.size.x / tick_count
71 |
72 | var vertical_grid: PackedVector2Array = []
73 | var vertical_ticks: PackedVector2Array = []
74 |
75 | for i in range(tick_count):
76 | var x_position: float = (i * x_pixel_dist) + self.plot_box.position.x
77 |
78 | var top: Vector2 = Vector2(x_position, self.box.position.y)
79 | var bottom: Vector2 = Vector2(x_position, self.box.end.y)
80 |
81 | vertical_grid.append(top)
82 | vertical_grid.append(bottom)
83 |
84 | vertical_ticks.append(bottom)
85 | vertical_ticks.append(bottom + Vector2(0, get_parent().chart_properties.x_tick_size))
86 |
87 | # Draw x tick labels
88 | if get_parent().chart_properties.show_tick_labels:
89 | var label: String = labels[i]
90 | draw_string(
91 | get_parent().chart_properties.font,
92 | _get_x_tick_label_position(bottom, label),
93 | label,
94 | HORIZONTAL_ALIGNMENT_CENTER,
95 | -1,
96 | ThemeDB.fallback_font_size,
97 | get_parent().chart_properties.colors.text,
98 | TextServer.JUSTIFICATION_NONE,
99 | TextServer.DIRECTION_AUTO,
100 | TextServer.ORIENTATION_HORIZONTAL
101 | )
102 |
103 | # Draw x grid
104 | if get_parent().chart_properties.draw_vertical_grid:
105 | draw_multiline(vertical_grid, get_parent().chart_properties.colors.grid, 1)
106 |
107 | # Draw x ticks
108 | if get_parent().chart_properties.draw_ticks:
109 | draw_multiline(vertical_ticks, get_parent().chart_properties.colors.ticks, 1)
110 |
111 | func _draw_y_ticks() -> void:
112 | var labels = y_domain.get_tick_labels()
113 | var tick_count = labels.size()
114 | var y_pixel_dist: float = self.plot_box.size.y / tick_count
115 |
116 | var horizontal_grid: PackedVector2Array = []
117 | var horizontal_ticks: PackedVector2Array = []
118 |
119 | for i in range(tick_count):
120 | var y_sampled_val: float = self.plot_box.size.y - (i * y_pixel_dist) + self.plot_box.position.y
121 |
122 | var left: Vector2 = Vector2(self.box.position.x, y_sampled_val)
123 | var right: Vector2 = Vector2(self.box.end.x, y_sampled_val)
124 |
125 | horizontal_grid.append(left)
126 | horizontal_grid.append(right)
127 |
128 | horizontal_ticks.append(left)
129 | horizontal_ticks.append(left - Vector2(get_parent().chart_properties.y_tick_size, 0))
130 |
131 | # Draw y tick labels
132 | if get_parent().chart_properties.show_tick_labels:
133 | var label: String = labels[i]
134 | draw_string(
135 | get_parent().chart_properties.font,
136 | _get_y_tick_label_position(left, label),
137 | label,
138 | HORIZONTAL_ALIGNMENT_CENTER,
139 | -1,
140 | ThemeDB.fallback_font_size,
141 | get_parent().chart_properties.colors.text,
142 | TextServer.JUSTIFICATION_NONE,
143 | TextServer.DIRECTION_AUTO,
144 | TextServer.ORIENTATION_HORIZONTAL
145 | )
146 |
147 | # Draw y grid
148 | if get_parent().chart_properties.draw_horizontal_grid:
149 | draw_multiline(horizontal_grid, get_parent().chart_properties.colors.grid, 1)
150 |
151 | # Draw y ticks
152 | if get_parent().chart_properties.draw_ticks:
153 | draw_multiline(horizontal_ticks, get_parent().chart_properties.colors.ticks, 1)
154 |
155 |
156 | func _get_x_tick_label_position(base_position: Vector2, text: String) -> Vector2:
157 | return base_position + Vector2(
158 | - get_parent().chart_properties.font.get_string_size(text).x / 2,
159 | ThemeDB.fallback_font_size + get_parent().chart_properties.x_tick_size
160 | )
161 |
162 | func _get_y_tick_label_position(base_position: Vector2, text: String) -> Vector2:
163 | return base_position - Vector2(
164 | get_parent().chart_properties.font.get_string_size(text).x + get_parent().chart_properties.y_tick_size + get_parent().chart_properties.x_ticklabel_space,
165 | - ThemeDB.fallback_font_size * 0.35
166 | )
167 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/containers/canvas/plot_box/grid_box.gd.uid:
--------------------------------------------------------------------------------
1 | uid://doelssxa0y7ap
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/containers/canvas/plot_box/plot_box.gd:
--------------------------------------------------------------------------------
1 | extends Control
2 | class_name PlotBox
3 |
4 | # TODO: These signals have been removed. If anyone needs them, we can bring
5 | # them back, but from the Chart, not from the PlotBox.
6 | #signal function_point_entered(point, function)
7 | #signal function_point_exited(point, function)
8 |
9 | var focused_point: Point
10 | var focused_function: Function
11 |
12 | var box_margins: Vector2 # Margins relative to this rect, in order to make space for ticks and tick_labels
13 | var plot_inner_offset: Vector2 = Vector2(15, 15) # How many pixels from the broders should the plot be
14 |
15 | # TODO: Remove
16 | var chart_properties: ChartProperties
17 |
18 | func get_box() -> Rect2:
19 | var box: Rect2 = get_rect()
20 | box.position.x += box_margins.x
21 | # box.position.y += box_margins.y
22 | box.end.x -= box_margins.x
23 | box.end.y -= box_margins.y
24 | return box
25 |
26 | func get_plot_box() -> Rect2:
27 | var inner_box: Rect2 = get_box()
28 | inner_box.position.x += plot_inner_offset.x
29 | inner_box.position.y += plot_inner_offset.y
30 | inner_box.end.x -= plot_inner_offset.x * 2
31 | inner_box.end.y -= plot_inner_offset.y * 2
32 | return inner_box
33 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/containers/canvas/plot_box/plot_box.gd.uid:
--------------------------------------------------------------------------------
1 | uid://8xd8yvw7lumm
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/containers/data_tooltip/data_tooltip.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends PanelContainer
3 | class_name DataTooltip
4 |
5 | var gap: float = 15
6 |
7 | @onready var x_lbl : Label = $PointData/x
8 | @onready var y_lbl : Label = $PointData/Value/y
9 | @onready var func_lbl : Label = $PointData/Value/Function
10 | @onready var color_rect: Panel = $PointData/Value/Color
11 |
12 | func _ready():
13 | hide()
14 | update_size()
15 |
16 | func update_position(position: Vector2) -> void:
17 | if (position.x + gap + size.x) > get_parent().size.x:
18 | self.position = position - Vector2(size.x + gap, (get_rect().size.y / 2))
19 | else:
20 | self.position = position + Vector2(15, - (get_rect().size.y / 2))
21 |
22 | func set_font(font: FontFile) -> void:
23 | theme.set("default_font", font)
24 |
25 | func update_values(x: String, y: String, function_name: String, color: Color):
26 | x_lbl.set_text(x)
27 | y_lbl.set_text(y)
28 | func_lbl.set_text(function_name)
29 | color_rect.get("theme_override_styles/panel").set("bg_color", color)
30 |
31 | func update_size():
32 | x_lbl.set_text("")
33 | y_lbl.set_text("")
34 | func_lbl.set_text("")
35 | size = Vector2.ZERO
36 |
37 | func _on_DataTooltip_visibility_changed():
38 | if not visible:
39 | update_size()
40 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/containers/data_tooltip/data_tooltip.gd.uid:
--------------------------------------------------------------------------------
1 | uid://bsvy31fx78e5l
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/containers/data_tooltip/data_tooltip.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=5 format=3 uid="uid://dmesmjhiuqdo4"]
2 |
3 | [ext_resource type="Script" uid="uid://bsvy31fx78e5l" path="res://addons/easy_charts/utilities/containers/data_tooltip/data_tooltip.gd" id="1"]
4 |
5 | [sub_resource type="StyleBoxFlat" id="1"]
6 | content_margin_left = 10.0
7 | content_margin_top = 8.0
8 | content_margin_right = 10.0
9 | content_margin_bottom = 8.0
10 | bg_color = Color(0.101961, 0.101961, 0.101961, 0.784314)
11 | border_color = Color(1, 1, 1, 1)
12 | corner_radius_top_left = 8
13 | corner_radius_top_right = 8
14 | corner_radius_bottom_right = 8
15 | corner_radius_bottom_left = 8
16 | corner_detail = 20
17 | anti_aliasing_size = 0.65
18 |
19 | [sub_resource type="StyleBoxFlat" id="2"]
20 | corner_radius_top_left = 5
21 | corner_radius_top_right = 5
22 | corner_radius_bottom_right = 5
23 | corner_radius_bottom_left = 5
24 | corner_detail = 20
25 | anti_aliasing_size = 0.7
26 |
27 | [sub_resource type="StyleBoxEmpty" id="3"]
28 |
29 | [node name="DataTooltip" type="PanelContainer"]
30 | visible = false
31 | offset_right = 20.0
32 | offset_bottom = 16.0
33 | mouse_filter = 2
34 | theme_override_styles/panel = SubResource("1")
35 | script = ExtResource("1")
36 |
37 | [node name="PointData" type="VBoxContainer" parent="."]
38 | offset_left = 10.0
39 | offset_top = 8.0
40 | offset_right = 37.0
41 | offset_bottom = 42.0
42 | grow_horizontal = 2
43 | size_flags_horizontal = 3
44 | theme_override_constants/separation = 1
45 | alignment = 1
46 | __meta__ = {
47 | "_edit_use_anchors_": false
48 | }
49 |
50 | [node name="x" type="Label" parent="PointData"]
51 | offset_top = 2.0
52 | offset_bottom = 16.0
53 | size_flags_horizontal = 0
54 | theme_override_colors/font_color = Color(1, 1, 1, 1)
55 | valign = 1
56 |
57 | [node name="Value" type="HBoxContainer" parent="PointData"]
58 | offset_top = 17.0
59 | offset_right = 27.0
60 | offset_bottom = 31.0
61 | grow_horizontal = 2
62 | size_flags_horizontal = 7
63 | theme_override_constants/separation = 1
64 |
65 | [node name="Color" type="Panel" parent="PointData/Value"]
66 | offset_top = 2.0
67 | offset_right = 10.0
68 | offset_bottom = 12.0
69 | custom_minimum_size = Vector2(10, 10)
70 | size_flags_horizontal = 4
71 | size_flags_vertical = 4
72 | theme_override_styles/panel = SubResource("2")
73 |
74 | [node name="VSeparator" type="VSeparator" parent="PointData/Value"]
75 | offset_left = 11.0
76 | offset_right = 15.0
77 | offset_bottom = 14.0
78 | theme_override_constants/separation = 4
79 | theme_override_styles/separator = SubResource("3")
80 |
81 | [node name="Function" type="Label" parent="PointData/Value"]
82 | offset_left = 16.0
83 | offset_right = 16.0
84 | offset_bottom = 14.0
85 | size_flags_horizontal = 0
86 | size_flags_vertical = 5
87 | valign = 1
88 |
89 | [node name="sep" type="Label" parent="PointData/Value"]
90 | offset_left = 17.0
91 | offset_right = 21.0
92 | offset_bottom = 14.0
93 | size_flags_horizontal = 0
94 | size_flags_vertical = 5
95 | text = ":"
96 | valign = 1
97 |
98 | [node name="VSeparator2" type="VSeparator" parent="PointData/Value"]
99 | offset_left = 22.0
100 | offset_right = 26.0
101 | offset_bottom = 14.0
102 | theme_override_constants/separation = 4
103 | theme_override_styles/separator = SubResource("3")
104 |
105 | [node name="y" type="Label" parent="PointData/Value"]
106 | offset_left = 27.0
107 | offset_right = 27.0
108 | offset_bottom = 14.0
109 | size_flags_horizontal = 0
110 | size_flags_vertical = 5
111 | theme_override_colors/font_color = Color(1, 1, 1, 1)
112 | valign = 1
113 |
114 | [connection signal="visibility_changed" from="." to="." method="_on_DataTooltip_visibility_changed"]
115 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/containers/legend/function_label.gd:
--------------------------------------------------------------------------------
1 | extends HBoxContainer
2 | class_name FunctionLabel
3 |
4 | @onready var type_lbl: FunctionTypeLabel = $FunctionType
5 | @onready var name_lbl: Label = $FunctionName
6 |
7 | # Called when the node enters the scene tree for the first time.
8 | func _ready():
9 | pass # Replace with function body.
10 |
11 | func init_label(function: Function) -> void:
12 | type_lbl.type = function.get_type()
13 | type_lbl.color = function.get_color()
14 | type_lbl.marker = function.get_marker()
15 | name_lbl.set_text(function.name)
16 | name_lbl.set("theme_override_colors/font_color", get_parent().chart_properties.colors.text)
17 |
18 | func init_clabel(type: int, color: Color, marker: int, name: String) -> void:
19 | type_lbl.type = type
20 | type_lbl.color = color
21 | type_lbl.marker = marker
22 | name_lbl.set_text(name)
23 | name_lbl.set("theme_override_colors/font_color", get_parent().chart_properties.colors.text)
24 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/containers/legend/function_label.gd.uid:
--------------------------------------------------------------------------------
1 | uid://ckinjw2oipoxc
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/containers/legend/function_label.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://k2bgv6cwudd0"]
2 |
3 | [ext_resource type="Script" uid="uid://cphcx5cm4i2yx" path="res://addons/easy_charts/utilities/containers/legend/function_type.gd" id="1"]
4 | [ext_resource type="Script" uid="uid://ckinjw2oipoxc" path="res://addons/easy_charts/utilities/containers/legend/function_label.gd" id="2"]
5 |
6 | [node name="FunctionLabel" type="HBoxContainer"]
7 | anchor_right = 1.0
8 | anchor_bottom = 1.0
9 | theme_override_constants/separation = 5
10 | script = ExtResource("2")
11 |
12 | [node name="FunctionType" type="Label" parent="."]
13 | offset_top = 293.0
14 | offset_right = 20.0
15 | offset_bottom = 307.0
16 | custom_minimum_size = Vector2(20, 0)
17 | script = ExtResource("1")
18 |
19 | [node name="FunctionName" type="Label" parent="."]
20 | offset_left = 25.0
21 | offset_top = 293.0
22 | offset_right = 25.0
23 | offset_bottom = 307.0
24 | theme_override_colors/font_color = Color(0, 0, 0, 1)
25 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/containers/legend/function_legend.gd:
--------------------------------------------------------------------------------
1 | extends VBoxContainer
2 | class_name FunctionLegend
3 |
4 | @onready var f_label_scn: PackedScene = preload("res://addons/easy_charts/utilities/containers/legend/function_label.tscn")
5 |
6 | var chart_properties: ChartProperties
7 |
8 | func _ready() -> void:
9 | pass
10 |
11 | func clear() -> void:
12 | for label in get_children():
13 | label.queue_free()
14 |
15 | func add_function(function: Function) -> void:
16 | var f_label: FunctionLabel = f_label_scn.instantiate()
17 | add_child(f_label)
18 | f_label.init_label(function)
19 |
20 | func add_label(type: int, color: Color, marker: int, name: String) -> void:
21 | var f_label: FunctionLabel = f_label_scn.instantiate()
22 | add_child(f_label)
23 | f_label.init_clabel(type, color, marker, name)
24 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/containers/legend/function_legend.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cqfq31uiw71sk
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/containers/legend/function_legend.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=2 format=3 uid="uid://c6ffuulowjw4g"]
2 |
3 | [ext_resource type="Script" uid="uid://cqfq31uiw71sk" path="res://addons/easy_charts/utilities/containers/legend/function_legend.gd" id="1"]
4 |
5 | [node name="FunctionLegend" type="VBoxContainer"]
6 | offset_right = 80.0
7 | offset_bottom = 26.0
8 | script = ExtResource("1")
9 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/containers/legend/function_type.gd:
--------------------------------------------------------------------------------
1 | extends Label
2 | class_name FunctionTypeLabel
3 |
4 | var type: int
5 | var marker: int
6 | var color: Color
7 |
8 | func _draw() -> void:
9 | var center: Vector2 = get_rect().get_center()
10 |
11 | match self.type:
12 | Function.Type.LINE:
13 | draw_line(
14 | Vector2(get_rect().position.x, center.y),
15 | Vector2(get_rect().end.x, center.y),
16 | color, 3
17 | )
18 | Function.Type.AREA:
19 | var c2: Color = color
20 | c2.a = 0.3
21 | draw_rect(
22 | Rect2(
23 | Vector2(get_rect().position.x, center.y),
24 | Vector2(get_rect().end.x, get_rect().end.y / 2)
25 | ),
26 | c2, 3
27 | )
28 | draw_line(
29 | Vector2(get_rect().position.x, center.y),
30 | Vector2(get_rect().end.x, center.y),
31 | color, 3
32 | )
33 | Function.Type.PIE:
34 | draw_rect(
35 | Rect2(center - (Vector2.ONE * 3), (Vector2.ONE * 3 * 2)),
36 | color, 1.0
37 | )
38 | Function.Type.SCATTER, _:
39 | pass
40 |
41 | match self.marker:
42 | Function.Marker.NONE:
43 | pass
44 | Function.Marker.SQUARE:
45 | draw_rect(
46 | Rect2(center - (Vector2.ONE * 3), (Vector2.ONE * 3 * 2)),
47 | color, 1.0
48 | )
49 | Function.Marker.TRIANGLE:
50 | draw_colored_polygon(
51 | PackedVector2Array([
52 | center + (Vector2.UP * 3 * 1.3),
53 | center + (Vector2.ONE * 3 * 1.3),
54 | center - (Vector2(1, -1) * 3 * 1.3)
55 | ]), color, [], null
56 | )
57 | Function.Marker.CROSS:
58 | draw_line(
59 | center - (Vector2.ONE * 3),
60 | center + (Vector2.ONE * 3),
61 | color, 3, true
62 | )
63 | draw_line(
64 | center + (Vector2(1, -1) * 3),
65 | center + (Vector2(-1, 1) * 3),
66 | color, 3 / 2, true
67 | )
68 | Function.Marker.CIRCLE, _:
69 | draw_circle(center, 3, color)
70 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/containers/legend/function_type.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cphcx5cm4i2yx
2 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/icons/linechart.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/scripts/ec_utilities.gd:
--------------------------------------------------------------------------------
1 | extends RefCounted
2 | class_name ECUtilities
3 |
4 | var alphabet : String = "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"
5 |
6 | func _ready():
7 | pass
8 |
9 | static func _map_domain(value: float, from_domain: ChartAxisDomain, to_domain: ChartAxisDomain) -> float:
10 | return remap(value, from_domain.lb, from_domain.ub, to_domain.lb, to_domain.ub)
11 |
12 | static func _format_value(value: float, is_decimal: bool) -> String:
13 | return ("%.2f" if is_decimal else "%s") % snapped(value, 0.01)
14 |
15 | ### Utility Inner functions ###
16 |
17 | static func _contains_string(array: Array) -> bool:
18 | for value in array:
19 | if value is String:
20 | return true
21 | return false
22 |
23 | static func _is_decimal(value: float) -> bool:
24 | return abs(fmod(value, 1)) > 0.0
25 |
26 | static func _has_decimals(values: Array) -> bool:
27 | var temp: Array = values.duplicate(true)
28 |
29 | for dim in temp:
30 | for val in dim:
31 | if val is String:
32 | return false
33 | if abs(fmod(val, 1)) > 0.0:
34 | return true
35 |
36 | return false
37 |
38 | static func _find_min_max(values: Array) -> Dictionary:
39 | var temp: Array = values.duplicate(true)
40 | var _min: float
41 | var _max: float
42 |
43 | var min_ts: Array
44 | var max_ts: Array
45 | for dim in temp:
46 | min_ts.append(dim.min())
47 | max_ts.append(dim.max())
48 | _min = min_ts.min()
49 | _max = max_ts.max()
50 |
51 | return { min = _min, max = _max }
52 |
53 | static func _sample_values(values: Array, from_domain: ChartAxisDomain, to_domain: ChartAxisDomain) -> PackedFloat32Array:
54 | if values.is_empty():
55 | printerr("Trying to plot an empty dataset!")
56 | return PackedFloat32Array()
57 |
58 | # We are not considering String values here!!!
59 |
60 | var sampled: PackedFloat32Array = []
61 |
62 | for value in values:
63 | sampled.push_back(_map_domain(value, from_domain, to_domain))
64 |
65 | return sampled
66 |
67 | static func _round_min(val: float) -> float:
68 | return round(val) if abs(val) < 10 else floor(val / 10.0) * 10.0
69 |
70 | static func _round_max(val: float) -> float:
71 | return round(val) if abs(val) < 10 else ceil(val / 10.0) * 10.0
72 |
--------------------------------------------------------------------------------
/addons/easy_charts/utilities/scripts/ec_utilities.gd.uid:
--------------------------------------------------------------------------------
1 | uid://v8s4a52cq83s
2 |
--------------------------------------------------------------------------------