From 009488b43b75ff85de92a1f1b098e83f8f0c27ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Santilio?= Date: Tue, 26 May 2020 23:52:45 +0200 Subject: [PATCH] *added*- radar chart- better charts implementation- `chart` and `chart2D` classes to identify each chart- `function_names_index` as parameter to determine what's the index of the function names (both rows or columns) --- .gitignore | 1 + README.md | 5 +- addons/easy_charts/BarChart/BarChart.gd | 18 +- addons/easy_charts/BarChart/BarChart.tscn | 1 + addons/easy_charts/BarChart2D/BarChart2D.gd | 42 +- addons/easy_charts/LineChart/LineChart.gd | 19 +- addons/easy_charts/LineChart2D/LineChart2D.gd | 43 +- addons/easy_charts/RadarChart/RadarChart.gd | 377 ++++++++++++++++++ addons/easy_charts/RadarChart/RadarChart.tscn | 59 +++ .../easy_charts/ScatterChart/ScatterChart.gd | 20 +- .../ScatterChart2D/ScatterChart2D.gd | 49 ++- .../ScatterChart3D/ScatterChart3D.gd | 306 +++++++++++++- .../ScatterChart3D/ScatterChart3D.tscn | 8 +- .../Utilities/Containers/.gdignore | 0 .../Utilities/Containers/ChartContainer.gd | 40 ++ .../Utilities/Containers/ChartContainer2D.gd | 40 ++ addons/easy_charts/Utilities/Point/Point.gd | 6 +- .../easy_charts/Utilities/Point/PointData.gd | 1 + addons/easy_charts/Utilities/Rect/.gdignore | 0 addons/easy_charts/Utilities/Scripts/Chart.gd | 5 + .../easy_charts/Utilities/Scripts/Chart2D.gd | 9 + .../Utilities/Scripts/utilities.gd | 23 ++ addons/easy_charts/Utilities/icons/.gdignore | 0 addons/easy_charts/file.samples/.gdignore | 0 addons/easy_charts/file.samples/radar.csv | 4 + addons/easy_charts/plugin.cfg | 2 +- addons/easy_charts/plugin.gd | 11 +- 27 files changed, 1002 insertions(+), 87 deletions(-) create mode 100644 addons/easy_charts/RadarChart/RadarChart.gd create mode 100644 addons/easy_charts/RadarChart/RadarChart.tscn create mode 100644 addons/easy_charts/Utilities/Containers/.gdignore create mode 100644 addons/easy_charts/Utilities/Containers/ChartContainer.gd create mode 100644 addons/easy_charts/Utilities/Containers/ChartContainer2D.gd create mode 100644 addons/easy_charts/Utilities/Rect/.gdignore create mode 100644 addons/easy_charts/Utilities/Scripts/Chart.gd create mode 100644 addons/easy_charts/Utilities/Scripts/Chart2D.gd create mode 100644 addons/easy_charts/Utilities/Scripts/utilities.gd create mode 100644 addons/easy_charts/Utilities/icons/.gdignore create mode 100644 addons/easy_charts/file.samples/.gdignore create mode 100644 addons/easy_charts/file.samples/radar.csv diff --git a/.gitignore b/.gitignore index 680f0b7..270c39f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.import *.png + diff --git a/README.md b/README.md index 26c69dc..7a7e0e0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![version](https://img.shields.io/badge/plugin%20version-0.1.5-blue)](https://github.com/fenix-hub/godot-engine.easy-charts) +[![version](https://img.shields.io/badge/plugin%20version-0.2.1-blue)](https://github.com/fenix-hub/godot-engine.easy-charts) [![updates](https://img.shields.io/badge/plugin%20updates-on%20discord-purple)](https://discord.gg/JNrcucg) [![paypal](https://img.shields.io/badge/donations-PayPal-cyan)](https://paypal.me/NSantilio?locale.x=it_IT) @@ -9,7 +9,7 @@ Check my **[Discord](https://discord.gg/KnJGY9S)** to stay updated on this repos A library of Charts plotted in Control, 2D and 3D nodes to visualize general purpose datasets. Author: *"Nicolo (fenix) Santilio"* -Version: *0.1.5* +Version: *0.2.1* Wiki: *[wip]* Godot Version: *3.2stable* @@ -153,3 +153,4 @@ I don't assume any responsibility for possible corruptions of your project. It i + diff --git a/addons/easy_charts/BarChart/BarChart.gd b/addons/easy_charts/BarChart/BarChart.gd index 49aadb2..c043c2a 100644 --- a/addons/easy_charts/BarChart/BarChart.gd +++ b/addons/easy_charts/BarChart/BarChart.gd @@ -1,5 +1,5 @@ tool -extends Control +extends Chart """ [BarChart] - General purpose node for Bar Charts @@ -93,7 +93,7 @@ export (float,0,10,0.5) var column_gap : float = 2 export (float,0.1,10.0) var x_decim : float = 5.0 export (float,0.1,10.0) var y_decim : float = 5.0 -export (int,"Dot,Triangle,Square") var point_shape : int = 0 +export (point_shapes) var point_shape : int = 0 export (PoolColorArray) var function_colors = [Color("#1e1e1e")] export (Color) var v_lines_color : Color = Color("#cacaca") @@ -104,7 +104,7 @@ export (Color) var box_color : Color = Color("#1e1e1e") export (Font) var font : Font export (Font) var bold_font : Font export (Color) var font_color : Color = Color("#1e1e1e") -export (String,"Default","Clean","Gradient","Minimal","Invert") var template : String = "Default" setget apply_template +export (templates_names) var template : int = Chart.templates_names.Default setget apply_template export (bool) var invert_chart : bool = false var templates : Dictionary = {} @@ -169,7 +169,7 @@ func plot(): emit_signal("chart_plotted") func clear_points(): - if Points.get_children(): + if Points.get_children().size(): for function in Points.get_children(): function.queue_free() for legend in Legend.get_children(): @@ -189,6 +189,7 @@ func point_pressed(point : Point): func _enter_tree(): templates = Utilities._load_templates() + _ready() func read_datas(source : String, delimiter : String): var file : File = File.new() @@ -481,14 +482,15 @@ func create_legend(): function_legend.create_legend(f_name,function_colors[function],bold_font,font_color) legend.append(function_legend) -func apply_template(template_name : String): +func apply_template(template_name : int): template = template_name templates = Utilities._load_templates() - if template_name!=null and template_name!="": - var custom_template = templates[template.to_lower()] - function_colors = custom_template.function_colors + if template_name!=null: + var custom_template = templates.get(templates.keys()[template_name]) + function_colors = custom_template.function_colors as PoolColorArray v_lines_color = Color(custom_template.v_lines_color) h_lines_color = Color(custom_template.h_lines_color) box_color = Color(custom_template.outline_color) font_color = Color(custom_template.font_color) property_list_changed_notify() + diff --git a/addons/easy_charts/BarChart/BarChart.tscn b/addons/easy_charts/BarChart/BarChart.tscn index 1878f33..f99479b 100644 --- a/addons/easy_charts/BarChart/BarChart.tscn +++ b/addons/easy_charts/BarChart/BarChart.tscn @@ -12,6 +12,7 @@ rect_min_size = Vector2( 70, 50 ) mouse_filter = 2 script = ExtResource( 2 ) __meta__ = { +"The file you want to use as a source for your chart. It must be a *.CSV file, or a plain *.TXT file formatted in the right way.": "", "_edit_use_anchors_": false, "_editor_description_": "[BarChart] - General purpose node for Bar Charts diff --git a/addons/easy_charts/BarChart2D/BarChart2D.gd b/addons/easy_charts/BarChart2D/BarChart2D.gd index 92a9a96..2735f15 100644 --- a/addons/easy_charts/BarChart2D/BarChart2D.gd +++ b/addons/easy_charts/BarChart2D/BarChart2D.gd @@ -1,5 +1,5 @@ tool -extends Node2D +extends Chart2D """ [BarChart2D] - General purpose node for Bar Charts @@ -16,13 +16,13 @@ values of more than one measured variable. / source : Wikipedia / """ -onready var OutlinesTween : Tween = $OutlinesTween -onready var FunctionsTween : Tween = $FunctionsTween -onready var Functions : Node2D = $Functions -onready var GridTween : Tween = $GridTween -onready var PointData = $PointData/PointData -onready var Outlines : Line2D = $Outlines -onready var Grid : Node2D = $Grid +var OutlinesTween : Tween +var FunctionsTween +var Functions : Node2D +var GridTween : Tween +var PointData : PointData +var Outlines : Line2D +var Grid : Node2D var point_node : PackedScene = preload("../Utilities/Point/Point.tscn") var FunctionLegend : PackedScene = preload("../Utilities/Legend/FunctionLegend.tscn") @@ -96,7 +96,7 @@ export (float,0,10,0.5) var column_gap : float = 2 export (float,0.1,10.0) var x_decim : float = 5.0 export (float,0.1,10.0) var y_decim : float = 5.0 -export (int,"Dot,Triangle,Square") var point_shape : int = 0 +export (point_shapes) var point_shape : int = 0 export (PoolColorArray) var function_colors = [Color("#1e1e1e")] export (Color) var v_lines_color : Color = Color("#cacaca") export (Color) var h_lines_color : Color = Color("#cacaca") @@ -106,7 +106,7 @@ export (Color) var box_color : Color = Color("#1e1e1e") export (Font) var font : Font export (Font) var bold_font : Font export (Color) var font_color : Color = Color("#1e1e1e") -export (String,"Default","Clean","Gradient","Minimal","Invert") var template : String = "Default" setget apply_template +export (templates_names) var template : int = Chart.templates_names.Default setget apply_template export (float,0.1,1) var drawing_duration : float = 0.5 export (bool) var invert_chart : bool = false @@ -119,7 +119,15 @@ func _point_plotted(): pass func _ready(): - pass + _get_children() + +func _get_children(): + OutlinesTween = $OutlinesTween + Functions = $Functions + GridTween = $GridTween + PointData = $PointData/PointData + Outlines = $Outlines + Grid = $Grid func _set_size(size : Vector2): SIZE = size @@ -536,12 +544,12 @@ func create_legend(): function_legend.create_legend(f_name,function_colors[function],bold_font,font_color) legend.append(function_legend) -func apply_template(template_name : String): +func apply_template(template_name : int): template = template_name templates = Utilities._load_templates() - if template_name!=null and template_name!="": - var custom_template = templates[template.to_lower()] - function_colors = custom_template.function_colors + if template_name!=null: + var custom_template = templates.get(templates.keys()[template_name]) + function_colors = custom_template.function_colors as PoolColorArray v_lines_color = Color(custom_template.v_lines_color) h_lines_color = Color(custom_template.h_lines_color) box_color = Color(custom_template.outline_color) @@ -549,6 +557,10 @@ func apply_template(template_name : String): property_list_changed_notify() if Engine.editor_hint: + _get_children() Outlines.set_default_color(box_color) Grid.get_node("VLine").set_default_color(v_lines_color) Grid.get_node("HLine").set_default_color(h_lines_color) + +func _enter_tree(): + _ready() diff --git a/addons/easy_charts/LineChart/LineChart.gd b/addons/easy_charts/LineChart/LineChart.gd index d72c05c..e30a065 100644 --- a/addons/easy_charts/LineChart/LineChart.gd +++ b/addons/easy_charts/LineChart/LineChart.gd @@ -1,5 +1,5 @@ tool -extends Control +extends Chart """ [Linechart] - General purpose node for Line Charts @@ -93,7 +93,7 @@ export(bool) var show_x_values_as_labels : bool = true export (float,0.1,10.0) var x_decim : float = 5.0 export (float,0.1,10.0) var y_decim : float = 5.0 -export (int,"Dot,Triangle,Square") var point_shape : int = 0 +export (point_shapes) var point_shape : int = 0 export (PoolColorArray) var function_colors = [Color("#1e1e1e")] export (Color) var v_lines_color : Color = Color("#cacaca") export (Color) var h_lines_color : Color = Color("#cacaca") @@ -103,7 +103,7 @@ export (Color) var box_color : Color = Color("#1e1e1e") export (Font) var font : Font export (Font) var bold_font : Font export (Color) var font_color : Color = Color("#1e1e1e") -export (String,"Default","Clean","Gradient","Minimal","Invert") var template : String = "Default" setget apply_template +export (templates_names) var template : int = Chart.templates_names.Default setget apply_template export (bool) var invert_chart : bool = false @@ -114,7 +114,7 @@ signal point_pressed(point) func _ready(): - apply_template(template) + pass func _plot(source_ : String, delimiter_ : String, are_values_columns_ : bool, x_values_index_ : int, invert_chart_ : bool = false): randomize() @@ -502,14 +502,17 @@ func count_functions(): else: functions = datas.size()-1 -func apply_template(template_name : String): +func apply_template(template_name : int): template = template_name templates = Utilities._load_templates() - if template_name!=null and template_name!="": - var custom_template = templates[template.to_lower()] - function_colors = custom_template.function_colors + if template_name!=null: + var custom_template = templates.get(templates.keys()[template_name]) + function_colors = custom_template.function_colors as PoolColorArray v_lines_color = Color(custom_template.v_lines_color) h_lines_color = Color(custom_template.h_lines_color) box_color = Color(custom_template.outline_color) font_color = Color(custom_template.font_color) property_list_changed_notify() + +func _enter_tree(): + _ready() diff --git a/addons/easy_charts/LineChart2D/LineChart2D.gd b/addons/easy_charts/LineChart2D/LineChart2D.gd index 941b5d8..7bd9765 100644 --- a/addons/easy_charts/LineChart2D/LineChart2D.gd +++ b/addons/easy_charts/LineChart2D/LineChart2D.gd @@ -1,5 +1,5 @@ tool -extends Node2D +extends Chart2D """ [Linechart2D] - General purpose node for Line Charts @@ -16,13 +16,13 @@ In these cases they are known as run charts. """ -onready var OutlinesTween : Tween = $OutlinesTween -onready var FunctionsTween : Tween = $FunctionsTween -onready var Functions : Node2D = $Functions -onready var GridTween : Tween = $GridTween -onready var PointData = $PointData/PointData -onready var Outlines : Line2D = $Outlines -onready var Grid : Node2D = $Grid +var OutlinesTween : Tween +var FunctionsTween : Tween +var Functions : Node2D +var GridTween : Tween +var PointData : PointData +var Outlines : Line2D +var Grid : Node2D var point_node : PackedScene = preload("../Utilities/Point/Point.tscn") var FunctionLegend : PackedScene = preload("../Utilities/Legend/FunctionLegend.tscn") @@ -96,7 +96,7 @@ export(bool) var show_x_values_as_labels : bool = true export (float,0.1,10.0) var x_decim : float = 5.0 export (float,0.1,10.0) var y_decim : float = 5.0 -export (int,"Dot,Triangle,Square") var point_shape : int = 0 +export (point_shapes) var point_shape : int = 0 export (PoolColorArray) var function_colors = [Color("#1e1e1e")] export (Color) var v_lines_color : Color = Color("#cacaca") export (Color) var h_lines_color : Color = Color("#cacaca") @@ -106,7 +106,7 @@ export (Color) var box_color : Color = Color("#1e1e1e") export (Font) var font : Font export (Font) var bold_font : Font export (Color) var font_color : Color = Color("#1e1e1e") -export (String,"Default","Clean","Gradient","Minimal","Invert") var template : String = "Default" setget apply_template +export (templates_names) var template : int = Chart.templates_names.Default setget apply_template export (float,0.1,1) var drawing_duration : float = 0.5 export (bool) var invert_chart : bool = false @@ -119,12 +119,21 @@ func _point_plotted(): pass func _ready(): - pass + _get_children() + +func _get_children(): + OutlinesTween = $OutlinesTween + Functions = $Functions + GridTween = $GridTween + PointData = $PointData/PointData + Outlines = $Outlines + Grid = $Grid func _set_size(size : Vector2): SIZE = size build_chart() if Engine.editor_hint: + _get_children() Outlines.set_point_position(0,Vector2(origin.x,0)) Outlines.set_point_position(1,Vector2(SIZE.x,0)) Outlines.set_point_position(2,Vector2(SIZE.x,origin.y)) @@ -533,12 +542,12 @@ func create_legend(): function_legend.create_legend(f_name,function_colors[function],bold_font,font_color) legend.append(function_legend) -func apply_template(template_name : String): +func apply_template(template_name : int): template = template_name templates = Utilities._load_templates() - if template_name!=null and template_name!="": - var custom_template = templates[template.to_lower()] - function_colors = custom_template.function_colors + if template_name!=null: + var custom_template = templates.get(templates.keys()[template_name]) + function_colors = custom_template.function_colors as PoolColorArray v_lines_color = Color(custom_template.v_lines_color) h_lines_color = Color(custom_template.h_lines_color) box_color = Color(custom_template.outline_color) @@ -546,6 +555,10 @@ func apply_template(template_name : String): property_list_changed_notify() if Engine.editor_hint: + _get_children() Outlines.set_default_color(box_color) Grid.get_node("VLine").set_default_color(v_lines_color) Grid.get_node("HLine").set_default_color(h_lines_color) + +func _enter_tree(): + _ready() diff --git a/addons/easy_charts/RadarChart/RadarChart.gd b/addons/easy_charts/RadarChart/RadarChart.gd new file mode 100644 index 0000000..c80acd7 --- /dev/null +++ b/addons/easy_charts/RadarChart/RadarChart.gd @@ -0,0 +1,377 @@ +tool +extends Chart + +""" +[RadarChart] - General purpose node for Radar Charts +A radar chart is a graphical method of displaying multivariate data in the form +of a two-dimensional chart of three or more quantitative variables represented on axes +starting from the same point. The relative position and angle of the axes is typically +uninformative, but various heuristics, such as algorithms that plot data as the maximal +total area, can be applied to sort the variables (axes) into relative positions that reveal +distinct correlations, trade-offs, and a multitude of other comparative measures. + +/ source : Wikipedia / +""" + +onready var PointData = $PointData/PointData +onready var Points = $Points +onready var Legend = $Legend + +var point_node : PackedScene = preload("../Utilities/Point/Point.tscn") +var FunctionLegend : PackedScene = preload("../Utilities/Legend/FunctionLegend.tscn") + +var font_size : float = 16 +var const_height : float = font_size/2*font_size/20 +var const_width : float = font_size/2 + +var OFFSET : Vector2 = Vector2(0,0) + +#-------------------------------------------------------------------------# +var origin : Vector2 + +# actual distance between x and y values +var x_pass : float +var y_pass : float + +# vertical distance between y consecutive points used for intervals +var v_dist : float +var h_dist : float + +# quantization, representing the interval in which values will be displayed + + +# define values on x an y axis +var x_chors : Array +var y_chors : Array + +# actual coordinates of points (in pixel) +var x_coordinates : Array +var y_coordinates : Array + +# datas contained in file +var datas : Array + +# amount of functions to represent +var functions : int = 0 + + +# database values +var x_datas : Array +var y_datas : Array + +# labels displayed on chart +var x_label : String + +var x_labels : Array +var y_labels : Array + +var x_margin_min : int = 0 +var y_margin_min : int = 0 + +# actual values of point, from the database +var point_values : Array + +# actual position of points in pixel +var point_positions : Array + +var legend : Array setget set_legend,get_legend + +# --------------------- +var SIZE : Vector2 = Vector2() +export (String, FILE, "*.txt, *.csv") var source : String = "" setget set_source +export (String) var delimiter : String = ";" +#export (bool) var origin_at_zero : bool = true + +export (bool) var are_values_columns : bool = false +export (int,-1,100) var labels_index : int = 0 +export (int,-1,100) var function_names_index : int = 0 +#export(bool) var show_x_values_as_labels : bool = true + +#export (float,1,20,0.5) var column_width : float = 10 +#export (float,0,10,0.5) var column_gap : float = 2 +export (bool) var use_height_as_radius : bool = false +export (float) var radius : float = 150.0 + +#export (float,0.1,10.0) var x_decim : float = 5.0 +#export (float,0.1,10.0) var y_decim : float = 5.0 +export (float,0.1,100) var full_scale : float = 1.0 + +export (point_shapes) var point_shape : int = 0 +export (PoolColorArray) var function_colors = [Color("#1e1e1e")] +export (Color) var outline_color : Color = Color("#1e1e1e") +export (Color) var grid_color : Color = Color("#1e1e1e") +export (Font) var font : Font +export (Font) var bold_font : Font +export (Color) var font_color : Color = Color("#1e1e1e") + +export (templates_names) var template : int = Chart.templates_names.Default setget apply_template +#export (bool) var invert_chart : bool = false +export (float,0,360) var rotation : float = 0 + +var templates : Dictionary = {} + +signal chart_plotted(chart) +signal point_pressed(point) + + +func _ready(): + pass + +func _plot(source_ : String, delimiter_ : String, are_values_columns_ : bool, x_values_index_ : int, invert_chart_ : bool = false): + randomize() + + load_font() + PointData.hide() + + datas = read_datas(source_,delimiter_) + structure_datas(datas,are_values_columns_,x_values_index_) + build_chart() + count_functions() + calculate_pass() + calculate_coordinates() + calculate_colors() + create_legend() + emit_signal("chart_plotted") + +func plot(): + randomize() + + load_font() + PointData.hide() + + if source == "" or source == null: + Utilities._print_message("Can't plot a chart without a Source file. Please, choose it in editor, or use the custom function _plot().",1) + return + datas = read_datas(source,delimiter) + structure_datas(datas,are_values_columns,labels_index) + build_chart() + count_functions() + calculate_pass() + calculate_coordinates() + calculate_colors() + create_legend() + emit_signal("chart_plotted") + +func calculate_colors(): + if function_colors.empty() or function_colors.size() < functions: + for function in functions: + function_colors.append(Color("#1e1e1e")) + +func load_font(): + if font != null: + font_size = font.get_height() + var theme : Theme = Theme.new() + theme.set_default_font(font) + PointData.set_theme(theme) + else: + var lbl = Label.new() + font = lbl.get_font("") + lbl.free() + if bold_font != null: + PointData.Data.set("custom_fonts/font",bold_font) + +func read_datas(source : String, delimiter : String): + var file : File = File.new() + file.open(source,File.READ) + var content : Array + while not file.eof_reached(): + var line : PoolStringArray = file.get_csv_line(delimiter) + content.append(line) + file.close() + for data in content: + if data.size() < 2 or data.empty(): + content.erase(data) + return content + +func structure_datas(database : Array, are_values_columns : bool, labels_index : int): + # @x_values_index can be either a column or a row relative to x values + # @y_values can be either a column or a row relative to y values + self.labels_index = labels_index + self.are_values_columns = are_values_columns + match are_values_columns: + true: + for row in database.size(): + if row == labels_index: + x_labels = database[row] as PoolStringArray + else: + if database[row].empty() or database[row].size() < 2: + continue + x_datas.append(PoolRealArray(database[row] as Array)) + + for column in database[row].size(): + if column == function_names_index: + y_labels.append(database[row][column]) + false: + for row in database.size(): + if row == function_names_index: + y_labels = database[row] as PoolStringArray + + var x_temp_datas : PoolRealArray = [] + for column in database[row].size(): + if column == labels_index: + x_labels.append(database[row][column] as String) + else: + x_temp_datas.append(database[row][column] as float) + x_datas.append(x_temp_datas) + + if labels_index == -1 : + for data in x_datas[0].size(): + x_labels.append("Element %s" % data) + + if function_names_index == -1 : + for data in x_datas.size(): + y_labels.append("Function %s" % data) + +func build_chart(): + SIZE = get_size() + origin = OFFSET + SIZE/2 + +var radar_polygon : Array + +func calculate_pass() : + var ordered_max : Array + for data in x_datas : + var ordered_data : Array = (data as Array) + ordered_data.sort() + ordered_max.append(ordered_data.pop_back()) + ordered_max.sort() + var max_value : float = ordered_max.pop_back() + var dist = full_scale * pow(10.0,str(max_value).length()-2) + var multi = 0 + var value = dist * multi + x_chors.append(value as String) + while value < max_value: + multi+=1 + value = dist * multi + x_chors.append(value as String) + +func calculate_coordinates(): + for chor in x_chors.size(): + var inner_polyline : PoolVector2Array + var scalar_factor : float = (x_chors[chor] as float/x_chors.back() as float) + for function in functions: + var angle : float = ((2 * PI * function) / functions) - PI /2 + deg2rad(rotation) + var x_coordinate : float = (radius if not use_height_as_radius else SIZE.y/2) * scalar_factor * cos(angle) + origin.x + var y_coordinate : float = (radius if not use_height_as_radius else SIZE.y/2) * scalar_factor * sin(angle) + origin.y + inner_polyline.append(Vector2(x_coordinate, y_coordinate)) + inner_polyline.append(inner_polyline[0]) + radar_polygon.append(inner_polyline) + + for datas in x_datas: + var function_positions : PoolVector2Array + var function_values : Array + for data in datas.size(): + var scalar_factor : float = datas[data] /( x_chors.back() as float) + var angle : float = ((2 * PI * data) / datas.size()) - PI/2 + deg2rad(rotation) + var x_coordinate : float = (radius if not use_height_as_radius else SIZE.y/2) * scalar_factor * cos(angle) + origin.x + var y_coordinate : float = (radius if not use_height_as_radius else SIZE.y/2) * scalar_factor * sin(angle) + origin.y + function_positions.append(Vector2(x_coordinate,y_coordinate)) + function_values.append([x_labels[data], datas[data]]) + function_positions.append(function_positions[0]) + point_positions.append(function_positions) + point_values.append(function_values) + +func redraw(): + build_chart() + calculate_pass() + calculate_coordinates() + update() + +func _draw(): + if Engine.editor_hint: + return + + clear_points() + draw_grid() + + for function in point_positions.size(): + var function_color : Color = function_colors[function] + draw_polygon(point_positions[function], [Color(function_color.r, function_color.g, function_color.b, 0.2)],[],null,null,true) + draw_polyline(point_positions[function], function_color, 2,true) + + for _function in point_values.size(): + var PointContainer : Control = Control.new() + Points.add_child(PointContainer) + + for function_point in point_values[_function].size(): + var point : Point = point_node.instance() + point.connect("_point_pressed",self,"point_pressed") + point.connect("_mouse_entered",self,"show_data") + point.connect("_mouse_exited",self,"hide_data") + + point.create_point(point_shape, function_colors[_function], + Color.white, point_positions[_function][function_point], + point.format_value(point_values[_function][function_point], false, false), + y_labels[_function]) +# str("Function %s"%_function)) + + PointContainer.add_child(point) + +func draw_grid(): + for polyline in radar_polygon: + draw_polyline(polyline, grid_color, 1, true) + var text : String = x_chors[radar_polygon.find(polyline)] as String + draw_string(font, polyline[0] - Vector2(font.get_string_size(text).x/2,-5), text, font_color) + + if not radar_polygon.empty(): + draw_polyline(radar_polygon[radar_polygon.size()-1], outline_color, 1, true) + + for label in x_labels.size(): + var point_array : PoolVector2Array = radar_polygon[radar_polygon.size()-1] + draw_line(origin, point_array[label], grid_color, 1, true) + draw_string(font, point_array[label] - (Vector2(font.get_string_size(x_labels[label]).x/2,0) if point_array[label].x < origin.x else - Vector2(5,0)), x_labels[label], font_color) + + + +func create_legend(): + legend.clear() + for function in functions: + var function_legend = FunctionLegend.instance() + var f_name : String = x_labels[function] + var legend_font : Font + if font != null: + legend_font = font + if bold_font != null: + legend_font = bold_font + function_legend.create_legend(f_name,function_colors[function],bold_font,font_color) + legend.append(function_legend) + +func show_data(point): + PointData.update_datas(point) + PointData.show() + +func hide_data(): + PointData.hide() + +func clear_points(): + if Points.get_children(): + for function in Points.get_children(): + function.queue_free() + for legend in Legend.get_children(): + legend.queue_free() + +func set_legend(l : Array): + legend = l + +func get_legend(): + return legend + +func count_functions(): + self.functions = x_labels.size() + +func apply_template(template_name : int): + template = template_name + templates = Utilities._load_templates() + if template_name!=null: + var custom_template = templates.get(templates.keys()[template_name]) + function_colors = custom_template.function_colors as PoolColorArray + outline_color = Color(custom_template.outline_color) + grid_color = Color(custom_template.v_lines_color) + font_color = Color(custom_template.font_color) + property_list_changed_notify() + +func _enter_tree(): + _ready() + +func set_source(source_file : String): + source = source_file diff --git a/addons/easy_charts/RadarChart/RadarChart.tscn b/addons/easy_charts/RadarChart/RadarChart.tscn new file mode 100644 index 0000000..196ae44 --- /dev/null +++ b/addons/easy_charts/RadarChart/RadarChart.tscn @@ -0,0 +1,59 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://addons/easy_charts/Utilities/Point/PointData.tscn" type="PackedScene" id=1] +[ext_resource path="res://addons/easy_charts/RadarChart/RadarChart.gd" type="Script" id=2] + +[sub_resource type="Theme" id=1] + +[node name="RadarChart" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +rect_min_size = Vector2( 70, 50 ) +mouse_filter = 2 +script = ExtResource( 2 ) +__meta__ = { +"_edit_use_anchors_": false, +"_editor_description_": "[RadarChart] - General purpose node for Radar Charts +A radar chart is a graphical method of displaying multivariate data in the form +of a two-dimensional chart of three or more quantitative variables represented on axes +starting from the same point. The relative position and angle of the axes is typically +uninformative, but various heuristics, such as algorithms that plot data as the maximal +total area, can be applied to sort the variables (axes) into relative positions that reveal +distinct correlations, trade-offs, and a multitude of other comparative measures." +} +function_colors = PoolColorArray( 0.117647, 0.117647, 0.117647, 1, 0.117647, 0.117647, 0.117647, 1, 0.117647, 0.117647, 0.117647, 1, 0.117647, 0.117647, 0.117647, 1 ) +grid_color = Color( 0.792157, 0.792157, 0.792157, 1 ) + +[node name="Background" type="ColorRect" parent="."] +visible = false +show_behind_parent = true +anchor_right = 1.0 +anchor_bottom = 1.0 +color = Color( 0.882353, 0.882353, 0.882353, 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Points" type="Control" parent="."] +margin_right = 40.0 +margin_bottom = 40.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Legend" type="HBoxContainer" parent="."] +visible = false +margin_right = 1024.0 +margin_bottom = 64.0 +alignment = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="PointData" parent="." instance=ExtResource( 1 )] + +[node name="PointData" parent="PointData" index="0"] +visible = false +theme = SubResource( 1 ) + +[editable path="PointData"] diff --git a/addons/easy_charts/ScatterChart/ScatterChart.gd b/addons/easy_charts/ScatterChart/ScatterChart.gd index 17d23af..754e619 100644 --- a/addons/easy_charts/ScatterChart/ScatterChart.gd +++ b/addons/easy_charts/ScatterChart/ScatterChart.gd @@ -1,5 +1,5 @@ tool -extends Control +extends Chart """ [ScatterChart] - General purpose node for Scatter Charts @@ -91,7 +91,7 @@ export(bool) var show_x_values_as_labels : bool = true export (float,0.1,10.0) var x_decim : float = 5.0 export (float,0.1,10.0) var y_decim : float = 5.0 -export (int,"Dot,Triangle,Square") var point_shape : int = 0 +export (point_shapes) var point_shape : int = 0 export (PoolColorArray) var function_colors = [Color("#1e1e1e")] export (Color) var v_lines_color : Color = Color("#cacaca") export (Color) var h_lines_color : Color = Color("#cacaca") @@ -101,7 +101,7 @@ export (Color) var box_color : Color = Color("#1e1e1e") export (Font) var font : Font export (Font) var bold_font : Font export (Color) var font_color : Color = Color("#1e1e1e") -export (String,"Default","Clean","Gradient","Minimal","Invert") var template : String = "Default" setget apply_template +export (templates_names) var template : int = templates_names.Default setget apply_template export (bool) var invert_chart : bool = false @@ -112,7 +112,7 @@ signal point_pressed(point) func _ready(): - apply_template(template) + pass func _plot(source_ : String, delimiter_ : String, are_values_columns_ : bool, x_values_index_ : int, invert_chart_ : bool = false): randomize() @@ -495,14 +495,18 @@ func count_functions(): else: functions = datas.size()-1 -func apply_template(template_name : String): +func apply_template(template_name : int): template = template_name templates = Utilities._load_templates() - if template_name!=null and template_name!="": - var custom_template = templates[template.to_lower()] - function_colors = custom_template.function_colors + if template_name!=null: + var custom_template = templates.get(templates.keys()[template_name]) + function_colors = custom_template.function_colors as PoolColorArray v_lines_color = Color(custom_template.v_lines_color) h_lines_color = Color(custom_template.h_lines_color) box_color = Color(custom_template.outline_color) font_color = Color(custom_template.font_color) property_list_changed_notify() + +func _enter_tree(): + templates = Utilities._load_templates() + _ready() diff --git a/addons/easy_charts/ScatterChart2D/ScatterChart2D.gd b/addons/easy_charts/ScatterChart2D/ScatterChart2D.gd index 5e028b9..0c31c79 100644 --- a/addons/easy_charts/ScatterChart2D/ScatterChart2D.gd +++ b/addons/easy_charts/ScatterChart2D/ScatterChart2D.gd @@ -1,5 +1,5 @@ tool -extends Node2D +extends Chart2D """ [ScatterChart2D] - General purpose node for Scatter Charts @@ -13,13 +13,13 @@ the horizontal axis and the value of the other variable determining the position / source : Wikipedia / """ -onready var OutlinesTween : Tween = $OutlinesTween -onready var PointTween : Tween = $PointTween -onready var Functions : Node2D = $Functions -onready var GridTween : Tween = $GridTween -onready var PointData = $PointData/PointData -onready var Outlines : Line2D = $Outlines -onready var Grid : Node2D = $Grid +var OutlinesTween : Tween +var PointTween : Tween +var Functions : Node2D +var GridTween : Tween +var PointData : PointData +var Outlines : Line2D +var Grid : Node2D var point_node : PackedScene = preload("../Utilities/Point/Point.tscn") var FunctionLegend : PackedScene = preload("../Utilities/Legend/FunctionLegend.tscn") @@ -93,8 +93,8 @@ export(bool) var show_x_values_as_labels : bool = true export (float,0.1,10.0) var x_decim : float = 5.0 export (float,0.1,10.0) var y_decim : float = 5.0 -export (int,"Dot,Triangle,Square") var point_shape : int = 0 -export (PoolColorArray) var function_colors = [Color("#1e1e1e")] +export (point_shapes) var point_shape : int = 0 +export (PoolColorArray) var function_colors = [Color("#1e1e1e")] as PoolColorArray export (Color) var v_lines_color : Color = Color("#cacaca") export (Color) var h_lines_color : Color = Color("#cacaca") @@ -103,7 +103,7 @@ export (Color) var box_color : Color = Color("#1e1e1e") export (Font) var font : Font export (Font) var bold_font : Font export (Color) var font_color : Color = Color("#1e1e1e") -export (String,"Default","Clean","Gradient","Minimal","Invert") var template : String = "Default" setget apply_template +export (templates_names) var template : int = templates_names.Default setget apply_template export (float,0.1,1) var drawing_duration : float = 0.5 export (bool) var invert_chart : bool = false @@ -116,12 +116,22 @@ func _point_plotted(): pass func _ready(): - pass + _get_children() + +func _get_children(): + OutlinesTween = $OutlinesTween + PointTween = $PointTween + Functions = $Functions + GridTween = $GridTween + PointData = $PointData/PointData + Outlines = $Outlines + Grid = $Grid func _set_size(size : Vector2): SIZE = size build_chart() if Engine.editor_hint: + _get_children() Outlines.set_point_position(0,Vector2(origin.x,0)) Outlines.set_point_position(1,Vector2(SIZE.x,0)) Outlines.set_point_position(2,Vector2(SIZE.x,origin.y)) @@ -197,7 +207,7 @@ func plot(): func calculate_colors(): if function_colors.empty() or function_colors.size() < functions: for function in functions: - function_colors.append(Color("#1e1e1e")) + function_colors.append(Color("#1e1e1e") as Color) func draw_chart(): draw_outlines() @@ -513,12 +523,12 @@ func create_legend(): function_legend.create_legend(f_name,function_colors[function],bold_font,font_color) legend.append(function_legend) -func apply_template(template_name : String): +func apply_template(template_name : int): template = template_name templates = Utilities._load_templates() - if template_name!=null and template_name!="": - var custom_template = templates[template.to_lower()] - function_colors = custom_template.function_colors + if template_name!=null: + var custom_template = templates.get(templates.keys()[template_name]) + function_colors = custom_template.function_colors as PoolColorArray v_lines_color = Color(custom_template.v_lines_color) h_lines_color = Color(custom_template.h_lines_color) box_color = Color(custom_template.outline_color) @@ -526,6 +536,11 @@ func apply_template(template_name : String): property_list_changed_notify() if Engine.editor_hint: + _get_children() Outlines.set_default_color(box_color) Grid.get_node("VLine").set_default_color(v_lines_color) Grid.get_node("HLine").set_default_color(h_lines_color) + + +func _enter_tree(): + _ready() diff --git a/addons/easy_charts/ScatterChart3D/ScatterChart3D.gd b/addons/easy_charts/ScatterChart3D/ScatterChart3D.gd index e09715a..8c79d05 100644 --- a/addons/easy_charts/ScatterChart3D/ScatterChart3D.gd +++ b/addons/easy_charts/ScatterChart3D/ScatterChart3D.gd @@ -1,10 +1,308 @@ +tool extends Spatial -onready var Point = $Chart/Point +""" +[ScatterChart] - General purpose node for Scatter Charts +A scatter plot (also called a scatterplot, scatter graph, scatter chart, scattergram, or scatter diagram) + is a type of plot or mathematical diagram using Cartesian coordinates to display values for typically two variables +for a set of data. If the points are coded (color/shape/size), one additional variable can be displayed. +The data are displayed as a collection of points, each having the value of one variable determining the position on +the horizontal axis and the value of the other variable determining the position on the vertical axis. + +/ source : Wikipedia / +""" + +onready var PlaceholderPoint = $Chart/Point +onready var Space = $ImmediateGeometry +onready var PointData = $PointData/PointData + +var point_node : PackedScene = preload("../Utilities/Point/Point.tscn") +var FunctionLegend : PackedScene = preload("../Utilities/Legend/FunctionLegend.tscn") + +var font_size : float = 16 +var const_height : float = font_size/2*font_size/20 +var const_width : float = font_size/2 + +var OFFSET : Vector2 = Vector2(0,0) + +#-------------------------------------------------------------------------# +var origin : Vector2 + +# actual distance between x and y values +var x_pass : float +var y_pass : float + +# vertical distance between y consecutive points used for intervals +var v_dist : float +var h_dist : float + +# quantization, representing the interval in which values will be displayed + +# define values on x an y axis +var x_chors : Array +var y_chors : Array + +# actual coordinates of points (in pixel) +var x_coordinates : Array +var y_coordinates : Array + +# datas contained in file +var datas : Array + +# amount of functions to represent +var functions : int = 0 + +var x_label : String +var z_label : String + +# database values +var x_datas : Array +var z_datas : Array +var y_datas : Array + +# labels displayed on chart +var x_labels : Array +var y_labels : Array + +var x_margin_min : int = 0 +var y_margin_min : int = 0 + +# actual values of point, from the database +var point_values : Array + +# actual position of points in pixel +var point_positions : Array + +var legend : Array setget set_legend,get_legend + +# --------------------- +export (Vector2) var SIZE : Vector2 = Vector2() setget _set_size +export (String, FILE, "*.txt, *.csv") var source : String = "" +export (String) var delimiter : String = ";" +export (bool) var origin_at_zero : bool = true + +export (bool) var are_values_columns : bool = false +export (int,0,100) var x_values_index : int = 0 +export (int,0,100) var z_values_index : int = 0 +export(bool) var show_x_values_as_labels : bool = true + +#export (float,1,20,0.5) var column_width : float = 10 +#export (float,0,10,0.5) var column_gap : float = 2 + +export (float,0.1,10.0) var x_decim : float = 5.0 +export (float,0.1,10.0) var y_decim : float = 5.0 +export (int,"Dot,Triangle,Square") var point_shape : int = 0 +export (PoolColorArray) var function_colors = [Color("#1e1e1e")] +export (Color) var v_lines_color : Color = Color("#cacaca") +export (Color) var h_lines_color : Color = Color("#cacaca") + +export (bool) var boxed : bool = true +export (Color) var box_color : Color = Color("#1e1e1e") +export (Font) var font : Font +export (Font) var bold_font : Font +export (Color) var font_color : Color = Color("#1e1e1e") +export (String,"Default","Clean","Gradient","Minimal","Invert") var template : String = "Default" setget apply_template +export (float,0.1,1) var drawing_duration : float = 0.5 +export (bool) var invert_chart : bool = false + +var templates : Dictionary = {} + +signal chart_plotted(chart) +signal point_pressed(point) + +func _point_plotted(): + pass func _ready(): -# var p : MeshInstance = Point.duplicate() -# p.transform.origin = Vector3(1,0,1) -# add_child(p) pass + +func _set_size(size : Vector2): + SIZE = size +# build_chart() + +func clear(): + pass + +func load_font(): + if font != null: + font_size = font.get_height() + var theme : Theme = Theme.new() + theme.set_default_font(font) + PointData.set_theme(theme) + else: + var lbl = Label.new() + font = lbl.get_font("") + lbl.free() + if bold_font != null: + PointData.Data.set("custom_fonts/font",bold_font) + +func _plot(source_ : String, delimiter_ : String, are_values_columns_ : bool, x_values_index_ : int): + randomize() + + clear() + + load_font() + PointData.hide() + + datas = read_datas(source_,delimiter_) +# count_functions() + structure_datas(datas,are_values_columns_,x_values_index_) +# build_chart() +# calculate_pass() +# calculate_coordinates() +# calculate_colors() +# draw_chart() +# +# create_legend() + emit_signal("chart_plotted", self) + +func plot(): + randomize() + + clear() + + load_font() + PointData.hide() + + if source == "" or source == null: + Utilities._print_message("Can't plot a chart without a Source file. Please, choose it in editor, or use the custom function _plot().",1) + return + datas = read_datas(source,delimiter) +# count_functions() + structure_datas(datas,are_values_columns,x_values_index) +# build_chart() +# calculate_pass() +# calculate_coordinates() +# calculate_colors() +# draw_chart() + +# create_legend() + emit_signal("chart_plotted", self) + + +func read_datas(source : String, delimiter : String): + var file : File = File.new() + file.open(source,File.READ) + var content : Array + while not file.eof_reached(): + var line : PoolStringArray = file.get_csv_line(delimiter) + content.append(line) + file.close() + for data in content: + if data.size() < 2: + content.erase(data) + return content + +func structure_datas(database : Array, are_values_columns : bool, x_values_index : int): + # @x_values_index can be either a column or a row relative to x values + # @y_values can be either a column or a row relative to y values + self.are_values_columns = are_values_columns + match are_values_columns: + true: + for row in database.size(): + var t_vals : Array + for column in database[row].size(): + if column == x_values_index: + var x_data = database[row][column] + if x_data.is_valid_float() or x_data.is_valid_integer(): + x_datas.append(x_data as float) + else: + x_datas.append(x_data.replace(",",".") as float) + elif column == z_values_index: + var z_data = database[row][column] + if z_data.is_valid_float() or z_data.is_valid_integer(): + z_datas.append(z_data as float) + else: + z_datas.append(z_data.replace(",",".") as float) + else: + if row != 0: + var y_data = database[row][column] + if y_data.is_valid_float() or y_data.is_valid_integer(): + t_vals.append(y_data as float) + else: + t_vals.append(y_data.replace(",",".") as float) + else: + y_labels.append(str(database[row][column])) + if not t_vals.empty(): + y_datas.append(t_vals) + x_label = str(x_datas.pop_front()) + z_label = str(z_datas.pop_front()) + false: + for row in database.size(): + if row == x_values_index: + x_datas = (database[row]) + x_label = x_datas.pop_front() as String + else: + var values = database[row] as Array + y_labels.append(values.pop_front() as String) + y_datas.append(values) + for data in y_datas: + for value in data.size(): + data[value] = data[value] as float + + # draw y labels + var to_order : Array + var to_order_min : Array + for cluster in y_datas.size(): + # define x_chors and y_chors + var ordered_cluster = y_datas[cluster] as Array + ordered_cluster.sort() + ordered_cluster = PoolIntArray(ordered_cluster) + var margin_max = ordered_cluster[ordered_cluster.size()-1] + var margin_min = ordered_cluster[0] + to_order.append(margin_max) + to_order_min.append(margin_min) + + to_order.sort() + to_order_min.sort() + var margin = to_order.pop_back() + if not origin_at_zero: + y_margin_min = to_order_min.pop_front() + v_dist = y_decim * pow(10.0,str(margin).length()-2) + var multi = 0 + var p = (v_dist*multi) + ((y_margin_min) if not origin_at_zero else 0) + y_chors.append(p as String) + while p < margin: + multi+=1 + p = (v_dist*multi) + ((y_margin_min) if not origin_at_zero else 0) + y_chors.append(p as String) + + # draw x_labels + if not show_x_values_as_labels: + to_order.clear() + to_order = x_datas as PoolIntArray + + to_order.sort() + margin = to_order.pop_back() + if not origin_at_zero: + x_margin_min = to_order.pop_front() + h_dist = x_decim * pow(10.0,str(margin).length()-2) + multi = 0 + p = (h_dist*multi) + ((x_margin_min) if not origin_at_zero else 0) + x_labels.append(p as String) + while p < margin: + multi+=1 + p = (h_dist*multi) + ((x_margin_min) if not origin_at_zero else 0) + x_labels.append(p as String) + +func set_legend(l : Array): + legend = l + +func get_legend(): + return legend + +func apply_template(template_name : String): + template = template_name + templates = Utilities._load_templates() + if template_name!=null and template_name!="": + var custom_template = templates[template.to_lower()] + function_colors = custom_template.function_colors + v_lines_color = Color(custom_template.v_lines_color) + h_lines_color = Color(custom_template.h_lines_color) + box_color = Color(custom_template.outline_color) + font_color = Color(custom_template.font_color) + property_list_changed_notify() + +func _enter_tree(): + _ready() diff --git a/addons/easy_charts/ScatterChart3D/ScatterChart3D.tscn b/addons/easy_charts/ScatterChart3D/ScatterChart3D.tscn index 76f3f26..8e31beb 100644 --- a/addons/easy_charts/ScatterChart3D/ScatterChart3D.tscn +++ b/addons/easy_charts/ScatterChart3D/ScatterChart3D.tscn @@ -1,11 +1,10 @@ [gd_scene load_steps=7 format=2] [ext_resource path="res://addons/easy_charts/ScatterChart3D/ScatterChart3D.gd" type="Script" id=1] -[ext_resource path="res://d4hj068-433f5832-3c04-42db-9c2e-173a26a6970a.png" type="Texture" id=2] +[ext_resource path="res://addons/easy_charts/Utilities/Point/PointData.tscn" type="PackedScene" id=2] [sub_resource type="SpatialMaterial" id=1] flags_unshaded = true -albedo_texture = ExtResource( 2 ) [sub_resource type="PlaneMesh" id=2] material = SubResource( 1 ) @@ -18,6 +17,7 @@ albedo_color = Color( 0, 1, 0.156863, 1 ) [node name="ScatterChart3D" type="Spatial"] script = ExtResource( 1 ) +function_colors = [ "#1e1e1e", "#1e1e1e", "#1e1e1e", "#1e1e1e" ] [node name="MeshInstance" type="MeshInstance" parent="."] transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0 ) @@ -39,3 +39,7 @@ near = 0.01 [node name="OmniLight" type="OmniLight" parent="."] transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 9, 0 ) + +[node name="PointData" parent="." instance=ExtResource( 2 )] + +[editable path="PointData"] diff --git a/addons/easy_charts/Utilities/Containers/.gdignore b/addons/easy_charts/Utilities/Containers/.gdignore new file mode 100644 index 0000000..e69de29 diff --git a/addons/easy_charts/Utilities/Containers/ChartContainer.gd b/addons/easy_charts/Utilities/Containers/ChartContainer.gd new file mode 100644 index 0000000..53f283e --- /dev/null +++ b/addons/easy_charts/Utilities/Containers/ChartContainer.gd @@ -0,0 +1,40 @@ +tool +extends Container + +var LineChart = preload("LineChart/LineChart.tscn") + +export (String,"None","LineChart","BoxChart") var chart_type : String setget set_type,get_type +var chart : Control setget set_chart,get_chart +var templates : Dictionary + +# Called when the node enters the scene tree for the first time. +func _ready(): + set_chart(get_child(0)) + var template_file : File = File.new() + template_file.open("res://addons/easy_charts/templates.json",File.READ) + templates = JSON.parse(template_file.get_as_text()).get_result() + template_file.close() + +func set_type(type : String): + chart_type = type + var new_node + if get_children().size(): + for child in get_children(): + child.queue_free() + if Engine.editor_hint: + match type: + "LineChart": + new_node = LineChart.instance() + add_child(new_node) + new_node.set_owner(owner) + "None": + set_chart(null) + +func get_type(): + return chart_type + +func set_chart(ch : Control): + chart = ch + +func get_chart(): + return chart diff --git a/addons/easy_charts/Utilities/Containers/ChartContainer2D.gd b/addons/easy_charts/Utilities/Containers/ChartContainer2D.gd new file mode 100644 index 0000000..5fec906 --- /dev/null +++ b/addons/easy_charts/Utilities/Containers/ChartContainer2D.gd @@ -0,0 +1,40 @@ +tool +extends Node2D + +var LineChart = preload("LineChart2D/LineChart2D.tscn") +var ColumnChart = preload("BarChart2D/BarChart2D.tscn") + +export (String,"None","LineChart2D","BarChart2D") var chart_type : String setget set_type,get_type +var chart : Node2D setget set_chart,get_chart + +# Called when the node enters the scene tree for the first time. +func _ready(): + set_chart(get_child(0)) + +func set_type(type : String): + chart_type = type + var new_node + if get_children().size(): + for child in get_children(): + child.queue_free() + if Engine.editor_hint: + match type: + "LineChart2D": + new_node = LineChart.instance() + add_child(new_node) + new_node.set_owner(owner) + "ColumnChart2D": + new_node = ColumnChart.instance() + add_child(new_node) + new_node.set_owner(owner) + "None": + set_chart(null) + +func get_type(): + return chart_type + +func set_chart(ch : Node2D): + chart = ch + +func get_chart(): + return chart diff --git a/addons/easy_charts/Utilities/Point/Point.gd b/addons/easy_charts/Utilities/Point/Point.gd index 536721b..6e65650 100644 --- a/addons/easy_charts/Utilities/Point/Point.gd +++ b/addons/easy_charts/Utilities/Point/Point.gd @@ -11,7 +11,7 @@ var function : String setget set_function, get_function var mouse_entered : bool = false enum SHAPES { - DOT, TRIANGLE, SQUARE + DOT, TRIANGLE, SQUARE, CROSS } var shape : int = 0 setget set_shape, get_shape @@ -44,6 +44,10 @@ func draw_point(size : float, color : Color): draw_colored_polygon([ OFFSET-Vector2(1,1)*size/2, OFFSET-Vector2(-1,1)*size/2, OFFSET+Vector2(1,1)*size/2, OFFSET-Vector2(1,-1)*size/2 ], color,[],null,null,false) + SHAPES.CROSS: + size+=2 + draw_line(OFFSET-Vector2(size,0), OFFSET+Vector2(size,0), color, size-5, true) + draw_line(OFFSET-Vector2(0,size), OFFSET+Vector2(0,size), color, size-5, true) func create_point(shape : int, color : Color, color_outline : Color, position : Vector2, value : Array, function : String): self.shape = shape diff --git a/addons/easy_charts/Utilities/Point/PointData.gd b/addons/easy_charts/Utilities/Point/PointData.gd index fb94dac..22459f4 100644 --- a/addons/easy_charts/Utilities/Point/PointData.gd +++ b/addons/easy_charts/Utilities/Point/PointData.gd @@ -1,4 +1,5 @@ extends PanelContainer +class_name PointData var value : String = "" var position : Vector2 = Vector2() diff --git a/addons/easy_charts/Utilities/Rect/.gdignore b/addons/easy_charts/Utilities/Rect/.gdignore new file mode 100644 index 0000000..e69de29 diff --git a/addons/easy_charts/Utilities/Scripts/Chart.gd b/addons/easy_charts/Utilities/Scripts/Chart.gd new file mode 100644 index 0000000..b9cc393 --- /dev/null +++ b/addons/easy_charts/Utilities/Scripts/Chart.gd @@ -0,0 +1,5 @@ +extends Control +class_name Chart + +enum point_shapes { Dot, Triangle, Square, Cross } +enum templates_names { Default, Clean, Gradient, Minimal, Invert } diff --git a/addons/easy_charts/Utilities/Scripts/Chart2D.gd b/addons/easy_charts/Utilities/Scripts/Chart2D.gd new file mode 100644 index 0000000..a4c3f59 --- /dev/null +++ b/addons/easy_charts/Utilities/Scripts/Chart2D.gd @@ -0,0 +1,9 @@ +extends Node2D +class_name Chart2D + +enum point_shapes { Dot, Triangle, Square, Cross } +enum templates_names { Default, Clean, Gradient, Minimal, Invert } + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. diff --git a/addons/easy_charts/Utilities/Scripts/utilities.gd b/addons/easy_charts/Utilities/Scripts/utilities.gd new file mode 100644 index 0000000..3323bd9 --- /dev/null +++ b/addons/easy_charts/Utilities/Scripts/utilities.gd @@ -0,0 +1,23 @@ +tool +extends Node + +var plugin_name : String = "Easy Charts" +var templates : Dictionary = {} + +func _ready(): + templates = _load_templates() + _print_message("Templates loaded") + +func _print_message(message : String, type : int = 0): + match type: + 0: + print("[%s] => %s" % [plugin_name, message]) + 1: + printerr("ERROR: [%s] => %s" % [plugin_name, message]) + +func _load_templates() -> Dictionary: + var template_file : File = File.new() + template_file.open("res://addons/easy_charts/templates.json",File.READ) + var templates = JSON.parse(template_file.get_as_text()).get_result() + template_file.close() + return templates diff --git a/addons/easy_charts/Utilities/icons/.gdignore b/addons/easy_charts/Utilities/icons/.gdignore new file mode 100644 index 0000000..e69de29 diff --git a/addons/easy_charts/file.samples/.gdignore b/addons/easy_charts/file.samples/.gdignore new file mode 100644 index 0000000..e69de29 diff --git a/addons/easy_charts/file.samples/radar.csv b/addons/easy_charts/file.samples/radar.csv new file mode 100644 index 0000000..db3cae2 --- /dev/null +++ b/addons/easy_charts/file.samples/radar.csv @@ -0,0 +1,4 @@ +Eating;Drinking;Running;Sleeping;Coding +30;50;40;100;95 +90;34;100;50;23 + diff --git a/addons/easy_charts/plugin.cfg b/addons/easy_charts/plugin.cfg index 6fc27ec..e6e689e 100644 --- a/addons/easy_charts/plugin.cfg +++ b/addons/easy_charts/plugin.cfg @@ -3,5 +3,5 @@ name="EasyCharts" description="" author="Nicolò \"fenix\" Santilio" -version="1.0" +version="0.2.1" script="plugin.gd" diff --git a/addons/easy_charts/plugin.gd b/addons/easy_charts/plugin.gd index c37c821..f4e3b47 100644 --- a/addons/easy_charts/plugin.gd +++ b/addons/easy_charts/plugin.gd @@ -2,12 +2,11 @@ tool extends EditorPlugin func _enter_tree(): - add_autoload_singleton("Utilities","res://addons/easy_charts/Utilities/utilities.gd") -# Containers are not really that useful -# add_custom_type("ChartContainer", "Container", load("Utilities/ChartContainer.gd"), load("Utilities/icons/linechart.svg")) -# add_custom_type("ChartContainer2D", "Node2D", load("Utilities/ChartContainer2D.gd"), load("Utilities/icons/linechart2d.svg")) + add_autoload_singleton("Utilities","res://addons/easy_charts/Utilities/Scripts/utilities.gd") + add_custom_type("Chart","Control", load("res://addons/easy_charts/Utilities/Scripts/Chart.gd"), preload("Utilities/icons/linechart.svg")) + add_custom_type("Chart2D","Node2D", preload("Utilities/Scripts/Chart2D.gd"), preload("Utilities/icons/linechart2d.svg")) func _exit_tree(): -# remove_custom_type("ChartContainer") -# remove_custom_type("ChartContainer2D") + remove_custom_type("Chart") + remove_custom_type("Chart2D") remove_autoload_singleton("Utilities")