godot-engine.easy-charts icon indicating copy to clipboard operation
godot-engine.easy-charts copied to clipboard

Implement "visibility flag" for Charts

Open fenix-hub opened this issue 3 years ago • 0 comments

A visibility_flag should allow users to hide/show functions on charts that plot multiple functions simultaneously.

Details
Let us consider a LineChart plotting the following DataFrame
Godot_v3 2 4-rc3_win64_6eVOJmryb8 Godot_v3 2 4-rc3_win64_z2quanJ5q3 Which plots 3 different functions on the same chart.
Implement the ability to hide one or more functions on the chart from code/inspector.\

We want to achieve the current functionality (let's use the above dataframe as an example structure)\

Chart.function_visibility("temperature", false)  # Hides all points and connections corresponding to the "temperature" row
Chart.function_visibility("humidity", true)     # Shows all points and connections corresponding to the "humidity" row

Idea of implementation
Implementing this feature requires an additional level of logic for plotting, which is "function grouping".
Currently functions are only identified by actual rows/columns, and each row/column will be used to differentiate propeties among functions at draw time (different color, point shapes, connections).
Once drawn functions are not identified anymore.
Grouping points and connections inside own containers would make functions interactable.
The steps to group functions could be these:

  1. Create a FunctionContainer (Control) for each function (row) in the dataset
  2. Add points to relative FunctionContainers
  3. Add connections to relative FunctionContainers

Steps details

  1. This step is already done actually, but just for Points. Each FunctionContainer will have its name as the function' name (label of the row, index if there's no label). This naming convention should allow to directly call functions on a FunctionContainer by the name's node, so hiding a function should end up with get_node("function").set_visible(bool).
  2. Already done
  3. To achieve this step it will be necessary to move the draw_line call inside the main container of the chart inside each single FunctionContainer.

Current state:

func draw_lines():
    var _function = 0
    for PointContainer in Points.get_children(): #Each function is stored in a different PointContainer
        for function_point in range(1, PointContainer.get_children().size()):
            draw_line(
                    point_positions[_function][function_point - 1],
                    point_positions[_function][function_point],
                    function_colors[_function],
                    2,
                    false)
        _function += 1

Possible solution:

for function_container in range(0, Functions.get_children()):
    function_container.update()

In function_container.gd


func _draw_connections():
    for point in range(1, get_children().size()):
        draw_line(
             get_child(point).rect_position,
             get_child(point+1).rect_position,
             function_color, #to be assigned when instancing the FunctionContainer
             2,
             false
        )

func _draw():
    _draw_connections()

Once everything is implemented, Chart could have a function like this:

func set_function_visibility(function : String, visibility : bool) -> void:
    for child in functions.get_children():
        if child.name == function:
            functions.get_node(function).set_visible(visibility)
            return
     printerr("'%s' is not defined as a function. Assign this name as a Label to a Row or use 'set_ifunction_visibility()' instead." % function)

func set_ifunction_visibility(index : int, visibility : bool) -> void:
     index = abs(index)
     if index < functions.get_children().size():
         functions.get_child(index).set_visible(visibility)
     else:
         printerr("%s is not a valid index: this chart only has %s functions." % [index, functions.get_children().size()])

fenix-hub avatar Mar 07 '21 00:03 fenix-hub