From 8ad2fb923d0aaf2e3a31c053e3936a27d4cf2614 Mon Sep 17 00:00:00 2001 From: Nitwel Date: Thu, 11 Apr 2024 16:51:30 +0200 Subject: [PATCH] add line_charts --- app/addons/debug_draw_3d/README.md | 48 ++++++------- app/content/entities/line_chart/line_chart.gd | 40 +++++++++++ .../entities/line_chart/line_chart.tscn | 33 +++++++++ app/content/entities/number/number.tscn | 2 +- app/content/entities/sensor/sensor.gd | 20 ++++++ app/content/entities/sensor/sensor.tscn | 10 ++- app/content/main.tscn | 6 +- app/content/system/house/house.gd | 15 +++-- app/content/ui/components/button/button.gd | 2 +- .../ui/components/line_chart/axis_label.tres | 6 ++ .../ui/components/line_chart/line_chart.gd | 47 +++++++------ .../components/line_chart/line_chart.gdshader | 32 +++++++++ .../ui/components/line_chart/line_chart.tscn | 67 +++++++++++-------- .../ui/components/line_chart/x_axis.gd | 49 ++++++++++++-- .../ui/components/line_chart/x_axis.tscn | 19 ++++-- .../ui/components/line_chart/y_axis.gd | 32 +++++++++ .../ui/components/line_chart/y_axis.tscn | 19 ++++++ app/content/ui/menu/edit/edit_menu.gd | 2 + app/lib/globals/console.gd | 8 ++- app/lib/globals/home_api.gd | 10 ++- app/lib/home_apis/hass_ws/handlers/history.gd | 35 ++++++++++ app/lib/home_apis/hass_ws/hass.gd | 6 ++ app/lib/stores/house.gd | 13 ++-- app/lib/utils/entity_factory.gd | 9 ++- 24 files changed, 421 insertions(+), 109 deletions(-) create mode 100644 app/content/entities/line_chart/line_chart.gd create mode 100644 app/content/entities/line_chart/line_chart.tscn create mode 100644 app/content/ui/components/line_chart/axis_label.tres create mode 100644 app/content/ui/components/line_chart/line_chart.gdshader create mode 100644 app/content/ui/components/line_chart/y_axis.gd create mode 100644 app/content/ui/components/line_chart/y_axis.tscn create mode 100644 app/lib/home_apis/hass_ws/handlers/history.gd diff --git a/app/addons/debug_draw_3d/README.md b/app/addons/debug_draw_3d/README.md index a2c272b..5f5f49d 100644 --- a/app/addons/debug_draw_3d/README.md +++ b/app/addons/debug_draw_3d/README.md @@ -77,33 +77,33 @@ Simple test: ```gdscript func _process(delta: float) -> void: - var _time = Time.get_ticks_msec() / 1000.0 - var box_pos = Vector3(0, sin(_time * 4), 0) - var line_begin = Vector3(-1, sin(_time * 4), 0) - var line_end = Vector3(1, cos(_time * 4), 0) + var _time = Time.get_ticks_msec() / 1000.0 + var box_pos = Vector3(0, sin(_time * 4), 0) + var line_begin = Vector3(-1, sin(_time * 4), 0) + var line_end = Vector3(1, cos(_time * 4), 0) - DebugDraw3D.draw_box(box_pos, Vector3(1, 2, 1), Color(0, 1, 0)) - DebugDraw3D.draw_line(line_begin, line_end, Color(1, 1, 0)) - DebugDraw2D.set_text("Time", _time) - DebugDraw2D.set_text("Frames drawn", Engine.get_frames_drawn()) - DebugDraw2D.set_text("FPS", Engine.get_frames_per_second()) - DebugDraw2D.set_text("delta", delta) + DebugDraw3D.draw_box(box_pos, Vector3(1, 2, 1), Color(0, 1, 0)) + DebugDraw3D.draw_line(line_begin, line_end, Color(1, 1, 0)) + DebugDraw2D.set_text("Time", _time) + DebugDraw2D.set_text("Frames drawn", Engine.get_frames_drawn()) + DebugDraw2D.set_text("FPS", Engine.get_frames_per_second()) + DebugDraw2D.set_text("delta", delta) ``` ```csharp public override void _Process(float delta) { - var _time = Time.GetTicksMsec() / 1000.0f; - var box_pos = new Vector3(0, Mathf.Sin(_time * 4f), 0); - var line_begin = new Vector3(-1, Mathf.Sin(_time * 4f), 0); - var line_end = new Vector3(1, Mathf.Cos(_time * 4f), 0); + var _time = Time.GetTicksMsec() / 1000.0f; + var box_pos = new Vector3(0, Mathf.Sin(_time * 4f), 0); + var line_begin = new Vector3(-1, Mathf.Sin(_time * 4f), 0); + var line_end = new Vector3(1, Mathf.Cos(_time * 4f), 0); - DebugDraw3D.DrawBox(box_pos, new Vector3(1, 2, 1), new Color(0, 1, 0)); - DebugDraw3D.DrawLine(line_begin, line_end, new Color(1, 1, 0)); - DebugDraw2D.SetText("Time", _time); - DebugDraw2D.SetText("Frames drawn", Engine.GetFramesDrawn()); - DebugDraw2D.SetText("FPS", Engine.GetFramesPerSecond()); - DebugDraw2D.SetText("delta", delta); + DebugDraw3D.DrawBox(box_pos, new Vector3(1, 2, 1), new Color(0, 1, 0)); + DebugDraw3D.DrawLine(line_begin, line_end, new Color(1, 1, 0)); + DebugDraw2D.SetText("Time", _time); + DebugDraw2D.SetText("Frames drawn", Engine.GetFramesDrawn()); + DebugDraw2D.SetText("FPS", Engine.GetFramesPerSecond()); + DebugDraw2D.SetText("delta", delta); } ``` @@ -117,11 +117,11 @@ A list of all functions is available in the documentation inside the editor. Besides `DebugDraw2D/3D`, you can also use `Dbg2/3`. ```gdscript - DebugDraw3D.draw_box_xf(Transform3D(), Color.GREEN) - Dbg3.draw_box_xf(Transform3D(), Color.GREEN) + DebugDraw3D.draw_box_xf(Transform3D(), Color.GREEN) + Dbg3.draw_box_xf(Transform3D(), Color.GREEN) - DebugDraw2D.set_text("delta", delta) - Dbg2.set_text("delta", delta) + DebugDraw2D.set_text("delta", delta) + Dbg2.set_text("delta", delta) ``` But unfortunately at the moment `GDExtension` does not support adding documentation. diff --git a/app/content/entities/line_chart/line_chart.gd b/app/content/entities/line_chart/line_chart.gd new file mode 100644 index 0000000..4db7a87 --- /dev/null +++ b/app/content/entities/line_chart/line_chart.gd @@ -0,0 +1,40 @@ +extends Entity + +const Entity = preload ("../entity.gd") + +@onready var line_chart = $LineChart +@onready var timer = $Timer +@onready var label = $Label3D + +func _ready(): + super() + + label.text = entity_id + + if HomeApi.has_connected() == false: + await HomeApi.on_connect + request_history() + + timer.timeout.connect(request_history) + +func request_history(): + # Request history from the server + + var now = Time.get_unix_time_from_datetime_dict(Time.get_datetime_dict_from_system()) + + # 2 days ago + var two_days_ago = now - 2 * 24 * 60 * 60 + + var start = Time.get_datetime_string_from_unix_time(two_days_ago) + ".000Z" + + var result = await HomeApi.get_history(entity_id, start) + + var points = result.data.map(func(point): + # Divide by 1000 to convert milliseconds to seconds + return Vector2((point.start + point.end) / (2 * 1000), point.mean) + ) + + line_chart.points.value = points + +func get_interface(): + return "line_chart" \ No newline at end of file diff --git a/app/content/entities/line_chart/line_chart.tscn b/app/content/entities/line_chart/line_chart.tscn new file mode 100644 index 0000000..0c05b7c --- /dev/null +++ b/app/content/entities/line_chart/line_chart.tscn @@ -0,0 +1,33 @@ +[gd_scene load_steps=5 format=3 uid="uid://cltcs0gokeald"] + +[ext_resource type="Script" path="res://content/entities/line_chart/line_chart.gd" id="1_5dxim"] +[ext_resource type="PackedScene" uid="uid://cwvykoymlrrel" path="res://content/ui/components/line_chart/line_chart.tscn" id="2_k4shm"] +[ext_resource type="Script" path="res://content/functions/movable.gd" id="3_lidml"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_rmm5v"] +size = Vector3(0.5, 0.3, 0.001) + +[node name="LineChart" type="StaticBody3D" groups=["entity"]] +collision_layer = 5 +collision_mask = 0 +script = ExtResource("1_5dxim") + +[node name="LineChart" parent="." instance=ExtResource("2_k4shm")] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.25, 0.15, 0) +shape = SubResource("BoxShape3D_rmm5v") + +[node name="Movable" type="Node" parent="."] +script = ExtResource("3_lidml") + +[node name="Timer" type="Timer" parent="."] +wait_time = 60.0 +autostart = true + +[node name="Label3D" type="Label3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.25, -0.03, 0) +pixel_size = 0.001 +text = "sensor.tada" +font_size = 18 +outline_size = 4 diff --git a/app/content/entities/number/number.tscn b/app/content/entities/number/number.tscn index fd0e532..f8dba61 100644 --- a/app/content/entities/number/number.tscn +++ b/app/content/entities/number/number.tscn @@ -8,7 +8,7 @@ [sub_resource type="BoxShape3D" id="BoxShape3D_7mk8w"] size = Vector3(0.0390625, 0.114258, 0.0142822) -[node name="Number" type="StaticBody3D"] +[node name="Number" type="StaticBody3D" groups=["entity"]] script = ExtResource("1_26xwp") [node name="Slider" parent="." instance=ExtResource("2_sninv")] diff --git a/app/content/entities/sensor/sensor.gd b/app/content/entities/sensor/sensor.gd index cb82054..5f3f1c9 100644 --- a/app/content/entities/sensor/sensor.gd +++ b/app/content/entities/sensor/sensor.gd @@ -4,9 +4,11 @@ const Entity = preload ("../entity.gd") @onready var label: Label3D = $Label @onready var collision_shape = $CollisionShape3D +@onready var chart_button = $Button var sensor_data = {} var unit = null +var is_text = true # Called when the node enters the scene tree for the first time. func _ready(): @@ -19,12 +21,30 @@ func _ready(): set_text(new_state) ) + remove_child(chart_button) + + chart_button.on_button_down.connect(func(): + House.body.create_entity(entity_id, global_position, "line_chart") + remove_child(chart_button) + ) + +func _on_click(_event): + if is_text: + return + + if chart_button.is_inside_tree() == false: + add_child(chart_button) + else: + remove_child(chart_button) + func set_text(stateInfo): if stateInfo == null: return var text = stateInfo["state"] + is_text = text.is_valid_float() == false&&text.is_valid_int() == false + if stateInfo["attributes"]["friendly_name"] != null: text = stateInfo["attributes"]["friendly_name"] + "\n" + text diff --git a/app/content/entities/sensor/sensor.tscn b/app/content/entities/sensor/sensor.tscn index 024519d..65f1118 100644 --- a/app/content/entities/sensor/sensor.tscn +++ b/app/content/entities/sensor/sensor.tscn @@ -1,9 +1,10 @@ -[gd_scene load_steps=6 format=3 uid="uid://xsiy71rsqulj"] +[gd_scene load_steps=7 format=3 uid="uid://xsiy71rsqulj"] [ext_resource type="Script" path="res://content/entities/sensor/sensor.gd" id="1_57ac8"] [ext_resource type="FontVariation" uid="uid://d2ofyimg5s65q" path="res://assets/fonts/ui_font_500.tres" id="2_4np3x"] [ext_resource type="Script" path="res://content/functions/movable.gd" id="2_fpq5q"] [ext_resource type="Script" path="res://content/functions/occludable.gd" id="3_l3sp5"] +[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="5_bmtkc"] [sub_resource type="BoxShape3D" id="BoxShape3D_phuot"] resource_local_to_scene = true @@ -29,3 +30,10 @@ script = ExtResource("2_fpq5q") [node name="Occludable" type="Node" parent="."] script = ExtResource("3_l3sp5") + +[node name="Button" parent="." instance=ExtResource("5_bmtkc")] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, -0.1, 0) +label = "add_chart" +icon = true + +[node name="HoverTimer" type="Timer" parent="."] diff --git a/app/content/main.tscn b/app/content/main.tscn index 0d24577..519f72d 100644 --- a/app/content/main.tscn +++ b/app/content/main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=18 format=3 uid="uid://eecv28y6jxk4"] +[gd_scene load_steps=17 format=3 uid="uid://eecv28y6jxk4"] [ext_resource type="PackedScene" uid="uid://clc5dre31iskm" path="res://addons/godot-xr-tools/xr/start_xr.tscn" id="1_i4c04"] [ext_resource type="Script" path="res://content/main.gd" id="1_uvrd4"] @@ -12,7 +12,6 @@ [ext_resource type="PackedScene" uid="uid://lrehk38exd5n" path="res://content/system/keyboard/keyboard.tscn" id="9_e5n3p"] [ext_resource type="PackedScene" uid="uid://cbemihbxkd4ll" path="res://content/system/house/house.tscn" id="9_np6mw"] [ext_resource type="PackedScene" uid="uid://bhyddd1f0ry1x" path="res://content/ui/onboarding/onboarding.tscn" id="12_uq2nj"] -[ext_resource type="PackedScene" uid="uid://cwvykoymlrrel" path="res://content/ui/components/line_chart/line_chart.tscn" id="13_iw50x"] [sub_resource type="Sky" id="Sky_vhymk"] sky_material = ExtResource("5_wgwf8") @@ -88,7 +87,4 @@ transform = Transform3D(0.499999, -0.000139169, -6.50204e-05, 5.24307e-05, 0.353 [node name="Onboarding" parent="." instance=ExtResource("12_uq2nj")] transform = Transform3D(0.999999, -1.39632e-11, 0, 9.48097e-12, 0.999999, 0, 0, 0, 0.999999, -0.529594, 0.820154, -0.600147) -[node name="LineChart" parent="." instance=ExtResource("13_iw50x")] -transform = Transform3D(1, -7.21733e-11, 5.82077e-11, 4.42421e-11, 1, 0, 0, 9.09495e-13, 1, 0.000296143, 1, -4.5899e-06) - [editable path="XROrigin3D/XRControllerLeft"] diff --git a/app/content/system/house/house.gd b/app/content/system/house/house.gd index 92b2877..acaa35f 100644 --- a/app/content/system/house/house.gd +++ b/app/content/system/house/house.gd @@ -38,7 +38,7 @@ func update_house(): for entity_index in range(Store.house.state.entities.size()): var entity = Store.house.state.entities[entity_index] - var entity_instance = create_entity_in(entity.id, entity.room) + var entity_instance = create_entity_in(entity.id, entity.room, entity.get("interface", null)) if entity_instance == null: continue @@ -163,13 +163,13 @@ func get_level_aabb(level: int): func get_rooms(level: int): return get_level(level).get_children() -func create_entity(entity_id: String, entity_position: Vector3): +func create_entity(entity_id: String, entity_position: Vector3, type=null): var room = find_room_at(entity_position) if room == null: return null - var entity = EntityFactory.create_entity(entity_id) + var entity = EntityFactory.create_entity(entity_id, type) if entity == null: return null @@ -181,13 +181,13 @@ func create_entity(entity_id: String, entity_position: Vector3): return entity -func create_entity_in(entity_id: String, room_name: String): +func create_entity_in(entity_id: String, room_name: String, type=null): var room = find_room(room_name) if room == null: return null - var entity = EntityFactory.create_entity(entity_id) + var entity = EntityFactory.create_entity(entity_id, type) if entity == null: return null @@ -239,9 +239,12 @@ func save_all_entities(): "id": entity.entity_id, "position": entity.global_position, "rotation": entity.global_rotation, - "room": String(room.name) + "room": String(room.name), } + if entity.has_method("get_interface"): + entity_data["interface"] = entity.get_interface() + Store.house.state.entities.append(entity_data) Store.house.save_local() diff --git a/app/content/ui/components/button/button.gd b/app/content/ui/components/button/button.gd index 740f69e..5b71137 100644 --- a/app/content/ui/components/button/button.gd +++ b/app/content/ui/components/button/button.gd @@ -72,7 +72,7 @@ func _ready(): if initial_active: active = true - Update.props(self, ["active", "external_value", "icon", "label", "font_size"]) + Update.props(self, ["active", "external_value", "icon", "label", "font_size", "disabled"]) if echo: echo_timer = Timer.new() diff --git a/app/content/ui/components/line_chart/axis_label.tres b/app/content/ui/components/line_chart/axis_label.tres new file mode 100644 index 0000000..937c7d0 --- /dev/null +++ b/app/content/ui/components/line_chart/axis_label.tres @@ -0,0 +1,6 @@ +[gd_resource type="LabelSettings" format=3 uid="uid://bc8arfh1k2gd2"] + +[resource] +font_size = 80 +outline_size = 10 +outline_color = Color(0, 0, 0, 1) diff --git a/app/content/ui/components/line_chart/line_chart.gd b/app/content/ui/components/line_chart/line_chart.gd index 438b235..de81080 100644 --- a/app/content/ui/components/line_chart/line_chart.gd +++ b/app/content/ui/components/line_chart/line_chart.gd @@ -4,14 +4,17 @@ extends Node3D @onready var mesh: MeshInstance3D = $Line @onready var plane: MeshInstance3D = $Plane -@onready var x_axis: Sprite3D = $XAxis +@onready var x_axis: Control = $XAxis/SubViewport/XAxis +@onready var y_axis: Control = $YAxis/SubViewport/YAxis -const RADIUS = 0.005 +const WIDTH = 0.001 +const DEPTH = 0.0005 const STEPS = 5 @export var size: Vector2 = Vector2(0.5, 0.3) var points = R.state([]) +var show_dates = R.state(false) var minmax = R.computed(func(_arg): if points.value.size() == 0: @@ -39,13 +42,20 @@ var relative_points = R.computed(func(_arg): ) func _ready(): - for i in range(100): - points.value.append(Vector2(i, sin(i / 10.0))) + for i in range(50): + points.value.append(Vector2(i, sin(i / 8.0))) R.effect(func(_arg): mesh.mesh=generate_mesh(relative_points.value) ) + R.effect(func(_arg): + x_axis.minmax=Vector2(minmax.value[0].x, minmax.value[1].x) + y_axis.minmax=Vector2(minmax.value[0].y, minmax.value[1].y) + x_axis.queue_redraw() + y_axis.queue_redraw() + ) + plane.position = Vector3(size.x / 2, size.y / 2, -0.001) plane.mesh.size = size @@ -57,33 +67,28 @@ func generate_mesh(points: Array): sf.begin(Mesh.PRIMITIVE_TRIANGLE_STRIP) - for i in range(points.size() - 1): + for i in range(points.size()): + var prev_point = points[i - 1] if i > 0 else (points[i] + Vector2( - 1, 0)) var point = points[i] - var next_point = points[i + 1] + var next_point = points[i + 1] if i < points.size() - 1 else (points[i] + Vector2(1, 0)) - var angle = (next_point - point).angle_to(Vector2(1, 0)) + var prev_angle = (point - prev_point).angle_to(Vector2(1, 0)) + var next_angle = (next_point - point).angle_to(Vector2(1, 0)) + + var angle = (prev_angle + next_angle) / 2.0 var up = Vector2(0, 1).rotated( - angle) - var p0 = point + up * RADIUS * 2 - var p1 = point + up * - RADIUS * 2 + var p0 = (point + up * WIDTH * 2) * size + var p1 = (point + up * - WIDTH * 2) * size - sf.add_vertex(Vector3(p0.x * size.x, p0.y * size.y, 0)) - sf.add_vertex(Vector3(p1.x * size.x, p1.y * size.y, 0)) + sf.add_vertex(Vector3(p1.x, p1.y, DEPTH)) + sf.add_vertex(Vector3(p0.x, p0.y, DEPTH)) sf.index() sf.generate_normals() var _mesh = sf.commit() - sf.clear() - sf.begin(Mesh.PRIMITIVE_TRIANGLE_STRIP) - - for i in range(points.size() - 1): - var point = points[i] - - sf.add_vertex(Vector3(point.x * size.x, point.y * size.y, RADIUS)) - sf.add_vertex(Vector3(point.x * size.x, point.y * size.y, -RADIUS)) - - return sf.commit(_mesh) + return _mesh \ No newline at end of file diff --git a/app/content/ui/components/line_chart/line_chart.gdshader b/app/content/ui/components/line_chart/line_chart.gdshader new file mode 100644 index 0000000..505c6de --- /dev/null +++ b/app/content/ui/components/line_chart/line_chart.gdshader @@ -0,0 +1,32 @@ +shader_type spatial; + +render_mode cull_disabled, unshaded; + +uniform vec2 steps = vec2(10.0,10.0); +uniform vec2 size= vec2(0.002, 0.002); +uniform vec2 offset = vec2(0.001, 0.001); + +void vertex() { + // Called for every vertex the material is visible on. +} + +void fragment() { + ALBEDO = vec3(0.5, 0.5, 0.5); + vec2 parts = 1.0 / steps; + + float y_mod = mod(UV.y + offset.y, parts.y); + float x_mod = mod(UV.x + offset.x, parts.x); + + if (x_mod < size.x / 2.0 || x_mod > parts.x - size.x / 2.0 || y_mod < size.y || y_mod > parts.y - size.y / 2.0) { + + ALPHA = 0.7; + } else { + ALPHA = 0.3; + } + +} + +//void light() { + // Called for every pixel for every light affecting the material. + // Uncomment to replace the default light processing function with this one. +//} diff --git a/app/content/ui/components/line_chart/line_chart.tscn b/app/content/ui/components/line_chart/line_chart.tscn index 7fb7d52..ae95060 100644 --- a/app/content/ui/components/line_chart/line_chart.tscn +++ b/app/content/ui/components/line_chart/line_chart.tscn @@ -1,65 +1,76 @@ -[gd_scene load_steps=8 format=3 uid="uid://cwvykoymlrrel"] +[gd_scene load_steps=11 format=3 uid="uid://cwvykoymlrrel"] [ext_resource type="Script" path="res://content/ui/components/line_chart/line_chart.gd" id="1_n7fu8"] -[ext_resource type="PackedScene" uid="uid://bs5wjs1sf67il" path="res://content/ui/components/line_chart/x_axis.tscn" id="2_2ow77"] +[ext_resource type="PackedScene" uid="uid://bb3shmvedk1oh" path="res://content/ui/components/line_chart/x_axis.tscn" id="2_2ow77"] +[ext_resource type="Shader" path="res://content/ui/components/line_chart/line_chart.gdshader" id="2_ryi4h"] +[ext_resource type="PackedScene" uid="uid://bs5wjs1sf67il" path="res://content/ui/components/line_chart/y_axis.tscn" id="3_48ptx"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_20gpn"] cull_mode = 2 shading_mode = 0 +albedo_color = Color(0.109804, 0.721569, 0.262745, 1) -[sub_resource type="ArrayMesh" id="ArrayMesh_2ookd"] +[sub_resource type="ArrayMesh" id="ArrayMesh_ww3lm"] _surfaces = [{ -"aabb": AABB(-0.00490072, -0.00294936, 0, 0.504732, 0.305794, 1e-05), +"aabb": AABB(-0.000587015, -0.000596339, 0.0005, 0.501171, 0.301189, 1e-05), "format": 34359742465, -"index_count": 198, -"index_data": PackedByteArray(0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16, 0, 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24, 0, 25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0, 31, 0, 32, 0, 33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38, 0, 39, 0, 40, 0, 41, 0, 42, 0, 43, 0, 44, 0, 45, 0, 46, 0, 47, 0, 48, 0, 49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 55, 0, 56, 0, 57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, 0, 64, 0, 65, 0, 66, 0, 67, 0, 68, 0, 69, 0, 70, 0, 71, 0, 72, 0, 73, 0, 74, 0, 75, 0, 76, 0, 77, 0, 78, 0, 79, 0, 80, 0, 81, 0, 82, 0, 83, 0, 84, 0, 85, 0, 86, 0, 87, 0, 88, 0, 89, 0, 90, 0, 91, 0, 92, 0, 93, 0, 94, 0, 95, 0, 96, 0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0, 103, 0, 104, 0, 105, 0, 106, 0, 107, 0, 108, 0, 109, 0, 110, 0, 111, 0, 112, 0, 113, 0, 114, 0, 115, 0, 116, 0, 117, 0, 118, 0, 119, 0, 120, 0, 121, 0, 122, 0, 123, 0, 124, 0, 125, 0, 126, 0, 127, 0, 128, 0, 129, 0, 130, 0, 131, 0, 132, 0, 133, 0, 134, 0, 135, 0, 136, 0, 137, 0, 138, 0, 139, 0, 140, 0, 141, 0, 142, 0, 143, 0, 144, 0, 145, 0, 146, 0, 147, 0, 148, 0, 149, 0, 150, 0, 151, 0, 152, 0, 153, 0, 154, 0, 155, 0, 156, 0, 157, 0, 158, 0, 159, 0, 160, 0, 161, 0, 162, 0, 163, 0, 164, 0, 165, 0, 166, 0, 167, 0, 168, 0, 169, 0, 170, 0, 171, 0, 172, 0, 173, 0, 174, 0, 175, 0, 176, 0, 177, 0, 178, 0, 179, 0, 180, 0, 181, 0, 182, 0, 183, 0, 184, 0, 185, 0, 186, 0, 187, 0, 188, 0, 189, 0, 190, 0, 191, 0, 192, 0, 193, 0, 194, 0, 195, 0, 196, 0, 197, 0), +"index_count": 100, +"index_data": PackedByteArray(0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16, 0, 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24, 0, 25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0, 31, 0, 32, 0, 33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38, 0, 39, 0, 40, 0, 41, 0, 42, 0, 43, 0, 44, 0, 45, 0, 46, 0, 47, 0, 48, 0, 49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 55, 0, 56, 0, 57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, 0, 64, 0, 65, 0, 66, 0, 67, 0, 68, 0, 69, 0, 70, 0, 71, 0, 72, 0, 73, 0, 74, 0, 75, 0, 76, 0, 77, 0, 78, 0, 79, 0, 80, 0, 81, 0, 82, 0, 83, 0, 84, 0, 85, 0, 86, 0, 87, 0, 88, 0, 89, 0, 90, 0, 91, 0, 92, 0, 93, 0, 94, 0, 95, 0, 96, 0, 97, 0, 98, 0, 99, 0), "primitive": 4, "uv_scale": Vector4(0, 0, 0, 0), -"vertex_count": 198, -"vertex_data": PackedByteArray(51, 150, 160, 187, 107, 60, 26, 62, 0, 0, 0, 0, 51, 150, 160, 59, 137, 4, 25, 62, 0, 0, 0, 0, 160, 28, 31, 57, 135, 148, 41, 62, 0, 0, 0, 0, 66, 2, 35, 60, 159, 89, 40, 62, 0, 0, 0, 0, 170, 153, 170, 59, 252, 198, 56, 62, 0, 0, 0, 0, 149, 176, 117, 60, 228, 133, 55, 62, 0, 0, 0, 0, 118, 39, 40, 60, 27, 173, 71, 62, 0, 0, 0, 0, 85, 42, 164, 60, 91, 98, 70, 62, 0, 0, 0, 0, 188, 14, 123, 60, 18, 33, 86, 62, 0, 0, 0, 0, 12, 118, 205, 60, 179, 200, 84, 62, 0, 0, 0, 0, 70, 3, 167, 60, 94, 254, 99, 62, 0, 0, 0, 0, 126, 185, 246, 60, 163, 147, 98, 62, 0, 0, 0, 0, 142, 138, 208, 60, 45, 34, 113, 62, 0, 0, 0, 0, 201, 248, 15, 61, 62, 159, 111, 62, 0, 0, 0, 0, 71, 34, 250, 60, 219, 107, 125, 62, 0, 0, 0, 0, 152, 140, 36, 61, 48, 201, 123, 62, 0, 0, 0, 0, 129, 233, 17, 61, 177, 94, 132, 62, 0, 0, 0, 0, 233, 19, 57, 61, 121, 120, 131, 62, 0, 0, 0, 0, 243, 213, 38, 61, 250, 125, 137, 62, 0, 0, 0, 0, 37, 135, 77, 61, 236, 123, 136, 62, 0, 0, 0, 0, 190, 228, 59, 61, 87, 8, 142, 62, 0, 0, 0, 0, 6, 216, 97, 61, 115, 224, 140, 62, 0, 0, 0, 0, 208, 50, 81, 61, 214, 244, 145, 62, 0, 0, 0, 0, 162, 233, 117, 61, 41, 152, 144, 62, 0, 0, 0, 0, 181, 255, 102, 61, 162, 61, 149, 62, 0, 0, 0, 0, 54, 190, 132, 61, 86, 149, 147, 62, 0, 0, 0, 0, 122, 224, 125, 61, 247, 223, 151, 62, 0, 0, 0, 0, 169, 253, 141, 61, 179, 202, 149, 62, 0, 0, 0, 0, 34, 144, 139, 61, 144, 213, 153, 62, 0, 0, 0, 0, 154, 13, 150, 61, 33, 50, 151, 62, 0, 0, 0, 0, 106, 26, 154, 61, 224, 247, 154, 62, 0, 0, 0, 0, 42, 51, 156, 61, 147, 233, 151, 62, 0, 0, 0, 0, 139, 58, 169, 61, 191, 7, 155, 62, 0, 0, 0, 0, 223, 194, 161, 61, 117, 43, 152, 62, 0, 0, 0, 0, 211, 156, 182, 61, 242, 36, 154, 62, 0, 0, 0, 0, 109, 16, 169, 61, 50, 215, 151, 62, 0, 0, 0, 0, 169, 112, 194, 61, 47, 136, 152, 62, 0, 0, 0, 0, 111, 236, 177, 61, 47, 183, 150, 62, 0, 0, 0, 0, 117, 131, 205, 61, 84, 62, 150, 62, 0, 0, 0, 0, 121, 137, 187, 61, 140, 197, 148, 62, 0, 0, 0, 0, 101, 63, 216, 61, 21, 72, 147, 62, 0, 0, 0, 0, 95, 125, 197, 61, 109, 12, 146, 62, 0, 0, 0, 0, 138, 209, 226, 61, 18, 168, 143, 62, 0, 0, 0, 0, 18, 155, 207, 61, 186, 151, 142, 62, 0, 0, 0, 0, 191, 77, 237, 61, 84, 100, 139, 62, 0, 0, 0, 0, 179, 206, 217, 61, 134, 115, 138, 62, 0, 0, 0, 0, 129, 189, 247, 61, 192, 133, 134, 62, 0, 0, 0, 0, 199, 14, 228, 61, 110, 172, 133, 62, 0, 0, 0, 0, 219, 18, 1, 62, 129, 23, 129, 62, 0, 0, 0, 0, 107, 86, 238, 61, 244, 79, 128, 62, 0, 0, 0, 0, 133, 68, 6, 62, 73, 77, 118, 62, 0, 0, 0, 0, 234, 162, 248, 61, 71, 217, 116, 62, 0, 0, 0, 0, 139, 116, 11, 62, 156, 131, 105, 62, 0, 0, 0, 0, 91, 121, 1, 62, 58, 36, 104, 62, 0, 0, 0, 0, 100, 163, 16, 62, 234, 241, 91, 62, 0, 0, 0, 0, 110, 162, 6, 62, 5, 162, 90, 62, 0, 0, 0, 0, 92, 209, 21, 62, 101, 186, 77, 62, 0, 0, 0, 0, 96, 204, 11, 62, 187, 117, 76, 62, 0, 0, 0, 0, 163, 254, 26, 62, 14, 1, 63, 62, 0, 0, 0, 0, 5, 247, 16, 62, 249, 195, 61, 62, 0, 0, 0, 0, 85, 43, 32, 62, 82, 235, 47, 62, 0, 0, 0, 0, 63, 34, 22, 62, 142, 178, 46, 62, 0, 0, 0, 0, 128, 87, 37, 62, 172, 159, 32, 62, 0, 0, 0, 0, 254, 77, 27, 62, 38, 104, 31, 62, 0, 0, 0, 0, 42, 131, 42, 62, 44, 69, 17, 62, 0, 0, 0, 0, 64, 122, 32, 62, 230, 11, 16, 62, 0, 0, 0, 0, 77, 174, 47, 62, 41, 3, 2, 62, 0, 0, 0, 0, 9, 167, 37, 62, 11, 197, 0, 62, 0, 0, 0, 0, 213, 216, 52, 62, 155, 1, 230, 61, 0, 0, 0, 0, 107, 212, 42, 62, 11, 117, 227, 61, 0, 0, 0, 0, 166, 2, 58, 62, 123, 201, 200, 61, 0, 0, 0, 0, 134, 2, 48, 62, 29, 37, 198, 61, 0, 0, 0, 0, 141, 43, 63, 62, 110, 169, 172, 61, 0, 0, 0, 0, 139, 49, 53, 62, 131, 228, 169, 61, 0, 0, 0, 0, 53, 83, 68, 62, 134, 234, 145, 61, 0, 0, 0, 0, 205, 97, 58, 62, 100, 250, 142, 61, 0, 0, 0, 0, 30, 121, 73, 62, 156, 165, 113, 61, 0, 0, 0, 0, 208, 147, 63, 62, 235, 83, 107, 61, 0, 0, 0, 0, 107, 156, 78, 62, 179, 73, 67, 61, 0, 0, 0, 0, 111, 200, 68, 62, 38, 99, 60, 61, 0, 0, 0, 0, 159, 187, 83, 62, 20, 63, 25, 61, 0, 0, 0, 0, 37, 1, 74, 62, 88, 147, 17, 61, 0, 0, 0, 0, 4, 212, 88, 62, 177, 248, 231, 60, 0, 0, 0, 0, 172, 64, 79, 62, 237, 141, 214, 60, 0, 0, 0, 0, 66, 224, 93, 62, 154, 228, 167, 60, 0, 0, 0, 0, 90, 140, 84, 62, 246, 156, 147, 60, 0, 0, 0, 0, 2, 213, 98, 62, 129, 59, 102, 60, 0, 0, 0, 0, 132, 239, 89, 62, 19, 142, 53, 60, 0, 0, 0, 0, 64, 152, 103, 62, 42, 253, 20, 60, 0, 0, 0, 0, 50, 132, 95, 62, 97, 40, 177, 59, 0, 0, 0, 0, 23, 237, 107, 62, 190, 217, 186, 59, 0, 0, 0, 0, 71, 135, 101, 62, 41, 90, 133, 58, 0, 0, 0, 0, 156, 104, 111, 62, 214, 37, 121, 59, 0, 0, 0, 0, 172, 99, 108, 62, 123, 44, 253, 186, 0, 0, 0, 0, 76, 34, 114, 62, 26, 74, 65, 59, 0, 0, 0, 0, 232, 1, 116, 62, 26, 74, 65, 187, 0, 0, 0, 0, 214, 93, 117, 62, 203, 158, 71, 59, 0, 0, 0, 0, 74, 30, 123, 62, 169, 104, 251, 186, 0, 0, 0, 0, 120, 135, 121, 62, 64, 236, 149, 59, 0, 0, 0, 0, 73, 166, 128, 62, 32, 232, 46, 58, 0, 0, 0, 0, 3, 55, 126, 62, 248, 194, 252, 59, 0, 0, 0, 0, 120, 122, 131, 62, 52, 96, 150, 59, 0, 0, 0, 0, 105, 145, 129, 62, 49, 84, 75, 60, 0, 0, 0, 0, 135, 48, 134, 62, 103, 5, 33, 60, 0, 0, 0, 0, 84, 21, 132, 62, 58, 44, 152, 60, 0, 0, 0, 0, 146, 216, 136, 62, 228, 33, 134, 60, 0, 0, 0, 0, 88, 160, 134, 62, 102, 247, 213, 60, 0, 0, 0, 0, 132, 121, 139, 62, 9, 43, 198, 60, 0, 0, 0, 0, 68, 47, 137, 62, 28, 35, 15, 61, 0, 0, 0, 0, 142, 22, 142, 62, 213, 16, 8, 61, 0, 0, 0, 0, 127, 192, 139, 62, 131, 35, 56, 61, 0, 0, 0, 0, 73, 177, 144, 62, 169, 176, 49, 61, 0, 0, 0, 0, 44, 83, 142, 62, 14, 140, 101, 61, 0, 0, 0, 0, 144, 74, 147, 62, 119, 146, 95, 61, 0, 0, 0, 0, 208, 230, 144, 62, 167, 113, 139, 61, 0, 0, 0, 0, 226, 226, 149, 62, 28, 163, 136, 61, 0, 0, 0, 0, 33, 123, 147, 62, 188, 211, 165, 61, 0, 0, 0, 0, 135, 122, 152, 62, 45, 40, 163, 61, 0, 0, 0, 0, 239, 15, 150, 62, 145, 167, 193, 61, 0, 0, 0, 0, 175, 17, 155, 62, 213, 21, 191, 61, 0, 0, 0, 0, 31, 165, 152, 62, 29, 165, 222, 61, 0, 0, 0, 0, 117, 168, 157, 62, 122, 37, 220, 61, 0, 0, 0, 0, 158, 58, 155, 62, 176, 129, 252, 61, 0, 0, 0, 0, 236, 62, 160, 62, 84, 13, 250, 61, 0, 0, 0, 0, 98, 208, 157, 62, 72, 120, 13, 62, 0, 0, 0, 0, 28, 213, 162, 62, 156, 64, 12, 62, 0, 0, 0, 0, 104, 102, 160, 62, 226, 209, 28, 62, 0, 0, 0, 0, 12, 107, 165, 62, 181, 153, 27, 62, 0, 0, 0, 0, 176, 252, 162, 62, 100, 38, 44, 62, 0, 0, 0, 0, 186, 0, 168, 62, 171, 234, 42, 62, 0, 0, 0, 0, 64, 147, 165, 62, 179, 78, 59, 62, 0, 0, 0, 0, 32, 150, 170, 62, 60, 12, 58, 62, 0, 0, 0, 0, 36, 42, 168, 62, 61, 36, 74, 62, 0, 0, 0, 0, 50, 43, 173, 62, 126, 215, 72, 62, 0, 0, 0, 0, 113, 193, 170, 62, 99, 129, 88, 62, 0, 0, 0, 0, 217, 191, 175, 62, 71, 38, 87, 62, 0, 0, 0, 0, 74, 89, 173, 62, 223, 65, 102, 62, 0, 0, 0, 0, 246, 83, 178, 62, 132, 211, 100, 62, 0, 0, 0, 0, 228, 241, 175, 62, 58, 67, 115, 62, 0, 0, 0, 0, 82, 231, 180, 62, 135, 187, 113, 62, 0, 0, 0, 0, 152, 139, 178, 62, 51, 101, 127, 62, 0, 0, 0, 0, 148, 121, 183, 62, 74, 188, 125, 62, 0, 0, 0, 0, 251, 38, 181, 62, 34, 69, 133, 62, 0, 0, 0, 0, 39, 10, 186, 62, 201, 90, 132, 62, 0, 0, 0, 0, 26, 197, 183, 62, 29, 76, 138, 62, 0, 0, 0, 0, 254, 151, 188, 62, 130, 68, 137, 62, 0, 0, 0, 0, 243, 103, 186, 62, 125, 188, 142, 62, 0, 0, 0, 0, 25, 33, 191, 62, 240, 140, 141, 62, 0, 0, 0, 0, 163, 19, 189, 62, 197, 141, 146, 62, 0, 0, 0, 0, 95, 161, 193, 62, 62, 38, 145, 62, 0, 0, 0, 0, 77, 209, 191, 62, 183, 186, 149, 62, 0, 0, 0, 0, 171, 15, 196, 62, 181, 2, 148, 62, 0, 0, 0, 0, 119, 182, 194, 62, 203, 64, 152, 62, 0, 0, 0, 0, 119, 86, 198, 62, 106, 21, 150, 62, 0, 0, 0, 0, 254, 240, 197, 62, 18, 23, 154, 62, 0, 0, 0, 0, 230, 71, 200, 62, 138, 91, 151, 62, 0, 0, 0, 0, 131, 165, 201, 62, 122, 14, 155, 62, 0, 0, 0, 0, 87, 191, 201, 62, 51, 252, 151, 62, 0, 0, 0, 0, 87, 97, 205, 62, 108, 240, 154, 62, 0, 0, 0, 0, 119, 47, 203, 62, 234, 41, 152, 62, 0, 0, 0, 0, 52, 165, 208, 62, 209, 235, 153, 62, 0, 0, 0, 0, 144, 23, 205, 62, 155, 181, 151, 62, 0, 0, 0, 0, 28, 143, 211, 62, 191, 49, 152, 62, 0, 0, 0, 0, 158, 89, 207, 62, 244, 113, 150, 62, 0, 0, 0, 0, 227, 78, 214, 62, 221, 202, 149, 62, 0, 0, 0, 0, 205, 197, 209, 62, 245, 93, 148, 62, 0, 0, 0, 0, 146, 251, 216, 62, 201, 183, 146, 62, 0, 0, 0, 0, 20, 69, 212, 62, 118, 132, 145, 62, 0, 0, 0, 0, 240, 158, 219, 62, 188, 251, 142, 62, 0, 0, 0, 0, 172, 205, 214, 62, 101, 241, 141, 62, 0, 0, 0, 0, 87, 61, 222, 62, 70, 157, 138, 62, 0, 0, 0, 0, 57, 91, 217, 62, 230, 176, 137, 62, 0, 0, 0, 0, 229, 216, 224, 62, 179, 165, 133, 62, 0, 0, 0, 0, 161, 235, 219, 62, 184, 207, 132, 62, 0, 0, 0, 0, 180, 114, 227, 62, 136, 32, 128, 62, 0, 0, 0, 0, 200, 125, 222, 62, 9, 183, 126, 62, 0, 0, 0, 0, 97, 11, 230, 62, 54, 54, 116, 62, 0, 0, 0, 0, 17, 17, 225, 62, 21, 198, 114, 62, 0, 0, 0, 0, 71, 163, 232, 62, 154, 72, 103, 62, 0, 0, 0, 0, 33, 165, 227, 62, 39, 236, 101, 62, 0, 0, 0, 0, 159, 58, 235, 62, 148, 152, 89, 62, 0, 0, 0, 0, 191, 57, 230, 62, 217, 74, 88, 62, 0, 0, 0, 0, 138, 209, 237, 62, 170, 72, 75, 62, 0, 0, 0, 0, 200, 206, 232, 62, 133, 5, 74, 62, 0, 0, 0, 0, 32, 104, 240, 62, 36, 125, 60, 62, 0, 0, 0, 0, 40, 100, 235, 62, 2, 65, 59, 62, 0, 0, 0, 0, 110, 254, 242, 62, 161, 91, 45, 62, 0, 0, 0, 0, 208, 249, 237, 62, 72, 35, 44, 62, 0, 0, 0, 0, 121, 148, 245, 62, 188, 10, 30, 62, 0, 0, 0, 0, 187, 143, 240, 62, 32, 211, 28, 62, 0, 0, 0, 0, 67, 42, 248, 62, 155, 177, 14, 62, 0, 0, 0, 0, 231, 37, 243, 62, 189, 119, 13, 62, 0, 0, 0, 0, 200, 191, 250, 62, 35, 239, 254, 61, 0, 0, 0, 0, 88, 188, 245, 62, 165, 112, 252, 61, 0, 0, 0, 0, 253, 84, 253, 62, 118, 7, 225, 61, 0, 0, 0, 0, 23, 83, 248, 62, 114, 119, 222, 61, 0, 0, 0, 0, 212, 233, 255, 62, 52, 249, 195, 61, 0, 0, 0, 0, 54, 234, 250, 62, 4, 80, 193, 61, 0, 0, 0, 0) -}, { -"aabb": AABB(0, 0, -0.005, 0.494949, 0.3, 0.01001), -"format": 34359738369, -"primitive": 4, -"uv_scale": Vector4(0, 0, 0, 0), -"vertex_count": 198, -"vertex_data": PackedByteArray(0, 0, 0, 0, 122, 160, 25, 62, 10, 215, 163, 59, 0, 0, 0, 0, 122, 160, 25, 62, 10, 215, 163, 187, 181, 126, 165, 59, 19, 247, 40, 62, 10, 215, 163, 59, 181, 126, 165, 59, 19, 247, 40, 62, 10, 215, 163, 187, 181, 126, 37, 60, 112, 38, 56, 62, 10, 215, 163, 59, 181, 126, 37, 60, 112, 38, 56, 62, 10, 215, 163, 187, 16, 62, 120, 60, 187, 7, 71, 62, 10, 215, 163, 59, 16, 62, 120, 60, 187, 7, 71, 62, 10, 215, 163, 187, 181, 126, 165, 60, 227, 116, 85, 62, 10, 215, 163, 59, 181, 126, 165, 60, 227, 116, 85, 62, 10, 215, 163, 187, 98, 222, 206, 60, 1, 73, 99, 62, 10, 215, 163, 59, 98, 222, 206, 60, 1, 73, 99, 62, 10, 215, 163, 187, 16, 62, 248, 60, 182, 96, 112, 62, 10, 215, 163, 59, 16, 62, 248, 60, 182, 96, 112, 62, 10, 215, 163, 187, 222, 206, 16, 61, 133, 154, 124, 62, 10, 215, 163, 59, 222, 206, 16, 61, 133, 154, 124, 62, 10, 215, 163, 187, 181, 126, 37, 61, 149, 235, 131, 62, 10, 215, 163, 59, 181, 126, 37, 61, 149, 235, 131, 62, 10, 215, 163, 187, 140, 46, 58, 61, 243, 252, 136, 62, 10, 215, 163, 59, 140, 46, 58, 61, 243, 252, 136, 62, 10, 215, 163, 187, 98, 222, 78, 61, 101, 116, 141, 62, 10, 215, 163, 59, 98, 222, 78, 61, 101, 116, 141, 62, 10, 215, 163, 187, 57, 142, 99, 61, 127, 70, 145, 62, 10, 215, 163, 59, 57, 142, 99, 61, 127, 70, 145, 62, 10, 215, 163, 187, 16, 62, 120, 61, 124, 105, 148, 62, 10, 215, 163, 59, 16, 62, 120, 61, 124, 105, 148, 62, 10, 215, 163, 187, 243, 118, 134, 61, 85, 213, 150, 62, 10, 215, 163, 59, 243, 118, 134, 61, 85, 213, 150, 62, 10, 215, 163, 187, 222, 206, 144, 61, 217, 131, 152, 62, 10, 215, 163, 59, 222, 206, 144, 61, 217, 131, 152, 62, 10, 215, 163, 187, 202, 38, 155, 61, 185, 112, 153, 62, 10, 215, 163, 59, 202, 38, 155, 61, 185, 112, 153, 62, 10, 215, 163, 187, 181, 126, 165, 61, 154, 153, 153, 62, 10, 215, 163, 59, 181, 126, 165, 61, 154, 153, 153, 62, 10, 215, 163, 187, 160, 214, 175, 61, 18, 254, 152, 62, 10, 215, 163, 59, 160, 214, 175, 61, 18, 254, 152, 62, 10, 215, 163, 187, 140, 46, 186, 61, 175, 159, 151, 62, 10, 215, 163, 59, 140, 46, 186, 61, 175, 159, 151, 62, 10, 215, 163, 187, 119, 134, 196, 61, 240, 129, 149, 62, 10, 215, 163, 59, 119, 134, 196, 61, 240, 129, 149, 62, 10, 215, 163, 187, 98, 222, 206, 61, 65, 170, 146, 62, 10, 215, 163, 59, 98, 222, 206, 61, 65, 170, 146, 62, 10, 215, 163, 187, 78, 54, 217, 61, 230, 31, 143, 62, 10, 215, 163, 59, 78, 54, 217, 61, 230, 31, 143, 62, 10, 215, 163, 187, 57, 142, 227, 61, 237, 235, 138, 62, 10, 215, 163, 59, 57, 142, 227, 61, 237, 235, 138, 62, 10, 215, 163, 187, 36, 230, 237, 61, 23, 25, 134, 62, 10, 215, 163, 59, 36, 230, 237, 61, 23, 25, 134, 62, 10, 215, 163, 187, 16, 62, 248, 61, 187, 179, 128, 62, 10, 215, 163, 59, 16, 62, 248, 61, 187, 179, 128, 62, 10, 215, 163, 187, 253, 74, 1, 62, 72, 147, 117, 62, 10, 215, 163, 59, 253, 74, 1, 62, 72, 147, 117, 62, 10, 215, 163, 187, 243, 118, 6, 62, 235, 211, 104, 62, 10, 215, 163, 59, 243, 118, 6, 62, 235, 211, 104, 62, 10, 215, 163, 187, 233, 162, 11, 62, 247, 73, 91, 62, 10, 215, 163, 59, 233, 162, 11, 62, 247, 73, 91, 62, 10, 215, 163, 187, 222, 206, 16, 62, 16, 24, 77, 62, 10, 215, 163, 59, 222, 206, 16, 62, 16, 24, 77, 62, 10, 215, 163, 187, 212, 250, 21, 62, 131, 98, 62, 62, 10, 215, 163, 59, 212, 250, 21, 62, 131, 98, 62, 62, 10, 215, 163, 187, 202, 38, 27, 62, 240, 78, 47, 62, 10, 215, 163, 59, 202, 38, 27, 62, 240, 78, 47, 62, 10, 215, 163, 187, 191, 82, 32, 62, 233, 3, 32, 62, 10, 215, 163, 59, 191, 82, 32, 62, 233, 3, 32, 62, 10, 215, 163, 187, 181, 126, 37, 62, 137, 168, 16, 62, 10, 215, 163, 59, 181, 126, 37, 62, 137, 168, 16, 62, 10, 215, 163, 187, 171, 170, 42, 62, 26, 100, 1, 62, 10, 215, 163, 59, 171, 170, 42, 62, 26, 100, 1, 62, 10, 215, 163, 187, 160, 214, 47, 62, 83, 187, 228, 61, 10, 215, 163, 59, 160, 214, 47, 62, 83, 187, 228, 61, 10, 215, 163, 187, 150, 2, 53, 62, 76, 119, 199, 61, 10, 215, 163, 59, 150, 2, 53, 62, 76, 119, 199, 61, 10, 215, 163, 187, 140, 46, 58, 62, 248, 70, 171, 61, 10, 215, 163, 59, 140, 46, 58, 62, 248, 70, 171, 61, 10, 215, 163, 187, 129, 90, 63, 62, 117, 114, 144, 61, 10, 215, 163, 59, 129, 90, 63, 62, 117, 114, 144, 61, 10, 215, 163, 187, 119, 134, 68, 62, 195, 124, 110, 61, 10, 215, 163, 59, 119, 134, 68, 62, 195, 124, 110, 61, 10, 215, 163, 187, 109, 178, 73, 62, 108, 214, 63, 61, 10, 215, 163, 59, 109, 178, 73, 62, 108, 214, 63, 61, 10, 215, 163, 187, 98, 222, 78, 62, 54, 105, 21, 61, 10, 215, 163, 59, 98, 222, 78, 62, 54, 105, 21, 61, 10, 215, 163, 187, 88, 10, 84, 62, 79, 67, 223, 60, 10, 215, 163, 59, 88, 10, 84, 62, 79, 67, 223, 60, 10, 215, 163, 187, 78, 54, 89, 62, 200, 192, 157, 60, 10, 215, 163, 59, 78, 54, 89, 62, 200, 192, 157, 60, 10, 215, 163, 187, 67, 98, 94, 62, 202, 228, 77, 60, 10, 215, 163, 59, 67, 98, 94, 62, 202, 228, 77, 60, 10, 215, 163, 187, 57, 142, 99, 62, 90, 145, 237, 59, 10, 215, 163, 59, 57, 142, 99, 62, 90, 145, 237, 59, 10, 215, 163, 187, 47, 186, 104, 62, 72, 48, 92, 59, 10, 215, 163, 59, 47, 186, 104, 62, 72, 48, 92, 59, 10, 215, 163, 187, 36, 230, 109, 62, 49, 31, 117, 58, 10, 215, 163, 59, 36, 230, 109, 62, 49, 31, 117, 58, 10, 215, 163, 187, 26, 18, 115, 62, 0, 0, 0, 0, 10, 215, 163, 59, 26, 18, 115, 62, 0, 0, 0, 0, 10, 215, 163, 187, 16, 62, 120, 62, 236, 212, 19, 58, 10, 215, 163, 59, 16, 62, 120, 62, 236, 212, 19, 58, 10, 215, 163, 187, 5, 106, 125, 62, 68, 201, 43, 59, 10, 215, 163, 59, 5, 106, 125, 62, 68, 201, 43, 59, 10, 215, 163, 187, 253, 74, 129, 62, 150, 145, 201, 59, 10, 215, 163, 59, 253, 74, 129, 62, 150, 145, 201, 59, 10, 215, 163, 187, 248, 224, 131, 62, 204, 44, 54, 60, 10, 215, 163, 59, 248, 224, 131, 62, 204, 44, 54, 60, 10, 215, 163, 187, 243, 118, 134, 62, 15, 39, 143, 60, 10, 215, 163, 59, 243, 118, 134, 62, 15, 39, 143, 60, 10, 215, 163, 187, 238, 12, 137, 62, 55, 17, 206, 60, 10, 215, 163, 59, 238, 12, 137, 62, 55, 17, 206, 60, 10, 215, 163, 187, 233, 162, 139, 62, 248, 153, 11, 61, 10, 215, 163, 59, 233, 162, 139, 62, 248, 153, 11, 61, 10, 215, 163, 187, 228, 56, 142, 62, 22, 234, 52, 61, 10, 215, 163, 59, 228, 56, 142, 62, 22, 234, 52, 61, 10, 215, 163, 187, 222, 206, 144, 62, 67, 143, 98, 61, 10, 215, 163, 59, 222, 206, 144, 62, 67, 143, 98, 61, 10, 215, 163, 187, 217, 100, 147, 62, 98, 10, 138, 61, 10, 215, 163, 59, 217, 100, 147, 62, 98, 10, 138, 61, 10, 215, 163, 187, 212, 250, 149, 62, 245, 125, 164, 61, 10, 215, 163, 59, 212, 250, 149, 62, 245, 125, 164, 61, 10, 215, 163, 187, 207, 144, 152, 62, 179, 94, 192, 61, 10, 215, 163, 59, 207, 144, 152, 62, 179, 94, 192, 61, 10, 215, 163, 187, 202, 38, 155, 62, 76, 101, 221, 61, 10, 215, 163, 59, 202, 38, 155, 62, 76, 101, 221, 61, 10, 215, 163, 187, 197, 188, 157, 62, 130, 71, 251, 61, 10, 215, 163, 59, 197, 188, 157, 62, 130, 71, 251, 61, 10, 215, 163, 187, 191, 82, 160, 62, 114, 220, 12, 62, 10, 215, 163, 59, 191, 82, 160, 62, 114, 220, 12, 62, 10, 215, 163, 187, 186, 232, 162, 62, 204, 53, 28, 62, 10, 215, 163, 59, 186, 232, 162, 62, 204, 53, 28, 62, 10, 215, 163, 187, 181, 126, 165, 62, 136, 136, 43, 62, 10, 215, 163, 59, 181, 126, 165, 62, 136, 136, 43, 62, 10, 215, 163, 187, 176, 20, 168, 62, 120, 173, 58, 62, 10, 215, 163, 59, 176, 20, 168, 62, 120, 173, 58, 62, 10, 215, 163, 187, 171, 170, 170, 62, 222, 125, 73, 62, 10, 215, 163, 59, 171, 170, 170, 62, 222, 125, 73, 62, 10, 215, 163, 187, 165, 64, 173, 62, 213, 211, 87, 62, 10, 215, 163, 59, 165, 64, 173, 62, 213, 211, 87, 62, 10, 215, 163, 187, 160, 214, 175, 62, 178, 138, 101, 62, 10, 215, 163, 59, 160, 214, 175, 62, 178, 138, 101, 62, 10, 215, 163, 187, 155, 108, 178, 62, 97, 127, 114, 62, 10, 215, 163, 59, 155, 108, 178, 62, 97, 127, 114, 62, 10, 215, 163, 187, 150, 2, 181, 62, 191, 144, 126, 62, 10, 215, 163, 59, 150, 2, 181, 62, 191, 144, 126, 62, 10, 215, 163, 187, 145, 152, 183, 62, 246, 207, 132, 62, 10, 215, 163, 59, 145, 152, 183, 62, 246, 207, 132, 62, 10, 215, 163, 187, 140, 46, 186, 62, 80, 200, 137, 62, 10, 215, 163, 59, 140, 46, 186, 62, 80, 200, 137, 62, 10, 215, 163, 187, 134, 196, 188, 62, 182, 36, 142, 62, 10, 215, 163, 59, 134, 196, 188, 62, 182, 36, 142, 62, 10, 215, 163, 187, 129, 90, 191, 62, 2, 218, 145, 62, 10, 215, 163, 59, 129, 90, 191, 62, 2, 218, 145, 62, 10, 215, 163, 187, 124, 240, 193, 62, 182, 222, 148, 62, 10, 215, 163, 59, 124, 240, 193, 62, 182, 222, 148, 62, 10, 215, 163, 187, 119, 134, 196, 62, 27, 43, 151, 62, 10, 215, 163, 59, 119, 134, 196, 62, 27, 43, 151, 62, 10, 215, 163, 187, 114, 28, 199, 62, 79, 185, 152, 62, 10, 215, 163, 59, 114, 28, 199, 62, 79, 185, 152, 62, 10, 215, 163, 187, 109, 178, 201, 62, 87, 133, 153, 62, 10, 215, 163, 59, 109, 178, 201, 62, 87, 133, 153, 62, 10, 215, 163, 187, 103, 72, 204, 62, 43, 141, 153, 62, 10, 215, 163, 59, 103, 72, 204, 62, 43, 141, 153, 62, 10, 215, 163, 187, 98, 222, 206, 62, 182, 208, 152, 62, 10, 215, 163, 59, 98, 222, 206, 62, 182, 208, 152, 62, 10, 215, 163, 187, 93, 116, 209, 62, 217, 81, 151, 62, 10, 215, 163, 59, 93, 116, 209, 62, 217, 81, 151, 62, 10, 215, 163, 187, 88, 10, 212, 62, 105, 20, 149, 62, 10, 215, 163, 59, 88, 10, 212, 62, 105, 20, 149, 62, 10, 215, 163, 187, 83, 160, 214, 62, 31, 30, 146, 62, 10, 215, 163, 59, 83, 160, 214, 62, 31, 30, 146, 62, 10, 215, 163, 187, 78, 54, 217, 62, 145, 118, 142, 62, 10, 215, 163, 59, 78, 54, 217, 62, 145, 118, 142, 62, 10, 215, 163, 187, 72, 204, 219, 62, 22, 39, 138, 62, 10, 215, 163, 59, 72, 204, 219, 62, 22, 39, 138, 62, 10, 215, 163, 187, 67, 98, 222, 62, 181, 58, 133, 62, 10, 215, 163, 59, 67, 98, 222, 62, 181, 58, 133, 62, 10, 215, 163, 187, 62, 248, 224, 62, 12, 124, 127, 62, 10, 215, 163, 59, 62, 248, 224, 62, 12, 124, 127, 62, 10, 215, 163, 187, 57, 142, 227, 62, 38, 126, 115, 62, 10, 215, 163, 59, 57, 142, 227, 62, 38, 126, 115, 62, 10, 215, 163, 187, 52, 36, 230, 62, 97, 154, 102, 62, 10, 215, 163, 59, 52, 36, 230, 62, 97, 154, 102, 62, 10, 215, 163, 187, 47, 186, 232, 62, 183, 241, 88, 62, 10, 215, 163, 59, 47, 186, 232, 62, 183, 241, 88, 62, 10, 215, 163, 187, 41, 80, 235, 62, 23, 167, 74, 62, 10, 215, 163, 59, 41, 80, 235, 62, 23, 167, 74, 62, 10, 215, 163, 187, 36, 230, 237, 62, 19, 223, 59, 62, 10, 215, 163, 59, 36, 230, 237, 62, 19, 223, 59, 62, 10, 215, 163, 187, 31, 124, 240, 62, 117, 191, 44, 62, 10, 215, 163, 59, 31, 124, 240, 62, 117, 191, 44, 62, 10, 215, 163, 187, 26, 18, 243, 62, 238, 110, 29, 62, 10, 215, 163, 59, 26, 18, 243, 62, 238, 110, 29, 62, 10, 215, 163, 187, 21, 168, 245, 62, 172, 20, 14, 62, 10, 215, 163, 59, 21, 168, 245, 62, 172, 20, 14, 62, 10, 215, 163, 187, 16, 62, 248, 62, 228, 175, 253, 61, 10, 215, 163, 59, 16, 62, 248, 62, 228, 175, 253, 61, 10, 215, 163, 187, 10, 212, 250, 62, 116, 191, 223, 61, 10, 215, 163, 59, 10, 212, 250, 62, 116, 191, 223, 61, 10, 215, 163, 187, 5, 106, 253, 62, 156, 164, 194, 61, 10, 215, 163, 59, 5, 106, 253, 62, 156, 164, 194, 61, 10, 215, 163, 187) +"vertex_count": 100, +"vertex_data": PackedByteArray(229, 225, 25, 58, 64, 41, 25, 62, 111, 18, 3, 58, 229, 225, 25, 186, 236, 39, 26, 62, 111, 18, 3, 58, 129, 190, 54, 60, 26, 163, 44, 62, 111, 18, 3, 58, 137, 159, 23, 60, 148, 5, 45, 62, 111, 18, 3, 58, 255, 241, 174, 60, 49, 129, 63, 62, 111, 18, 3, 58, 11, 108, 159, 60, 208, 229, 63, 62, 111, 18, 3, 58, 119, 64, 1, 61, 133, 198, 81, 62, 111, 18, 3, 58, 33, 12, 243, 60, 223, 46, 82, 62, 111, 18, 3, 58, 120, 5, 43, 61, 238, 41, 99, 62, 111, 18, 3, 58, 146, 88, 35, 61, 223, 151, 99, 62, 111, 18, 3, 58, 5, 199, 84, 61, 177, 101, 115, 62, 111, 18, 3, 58, 137, 46, 77, 61, 133, 219, 115, 62, 111, 18, 3, 58, 99, 131, 126, 61, 74, 28, 129, 62, 111, 18, 3, 58, 173, 9, 119, 61, 159, 92, 129, 62, 111, 18, 3, 58, 188, 27, 148, 61, 98, 179, 135, 62, 111, 18, 3, 58, 142, 118, 144, 61, 30, 251, 135, 62, 111, 18, 3, 58, 181, 238, 168, 61, 96, 93, 141, 62, 111, 18, 3, 58, 85, 111, 165, 61, 60, 175, 141, 62, 111, 18, 3, 58, 245, 180, 189, 61, 17, 3, 146, 62, 111, 18, 3, 58, 215, 116, 186, 61, 197, 98, 146, 62, 111, 18, 3, 58, 117, 99, 210, 61, 86, 145, 149, 62, 111, 18, 3, 58, 25, 146, 207, 61, 125, 3, 150, 62, 111, 18, 3, 58, 153, 231, 230, 61, 103, 250, 151, 62, 111, 18, 3, 58, 181, 217, 228, 61, 122, 130, 152, 62, 111, 18, 3, 58, 204, 49, 251, 61, 57, 56, 153, 62, 111, 18, 3, 58, 68, 91, 250, 61, 47, 210, 153, 62, 111, 18, 3, 58, 203, 172, 7, 62, 242, 75, 153, 62, 111, 18, 3, 58, 157, 255, 7, 62, 66, 231, 153, 62, 111, 18, 3, 58, 77, 206, 17, 62, 216, 53, 152, 62, 111, 18, 3, 58, 253, 195, 18, 62, 202, 192, 152, 62, 111, 18, 3, 58, 198, 12, 28, 62, 88, 244, 149, 62, 111, 18, 3, 58, 100, 107, 29, 62, 72, 105, 150, 62, 111, 18, 3, 58, 210, 97, 38, 62, 87, 140, 146, 62, 111, 18, 3, 58, 56, 252, 39, 62, 56, 238, 146, 62, 111, 18, 3, 58, 196, 195, 48, 62, 189, 10, 142, 62, 111, 18, 3, 58, 40, 128, 50, 62, 51, 94, 142, 62, 111, 18, 3, 58, 157, 44, 59, 62, 12, 130, 136, 62, 111, 18, 3, 58, 47, 253, 60, 62, 243, 202, 136, 62, 111, 18, 3, 58, 68, 153, 69, 62, 245, 8, 130, 62, 111, 18, 3, 58, 104, 118, 71, 62, 38, 74, 130, 62, 111, 18, 3, 58, 36, 8, 80, 62, 145, 115, 117, 62, 111, 18, 3, 58, 106, 237, 81, 62, 163, 234, 117, 62, 111, 18, 3, 58, 98, 120, 90, 62, 14, 100, 101, 62, 111, 18, 3, 58, 12, 99, 92, 62, 232, 210, 101, 62, 111, 18, 3, 58, 137, 233, 100, 62, 247, 35, 84, 62, 111, 18, 3, 58, 197, 215, 102, 62, 243, 140, 84, 62, 111, 18, 3, 58, 86, 91, 111, 62, 123, 248, 65, 62, 111, 18, 3, 58, 218, 75, 113, 62, 127, 93, 66, 62, 111, 18, 3, 58, 158, 205, 121, 62, 92, 42, 47, 62, 111, 18, 3, 58, 114, 191, 123, 62, 8, 141, 47, 62, 111, 18, 3, 58, 40, 32, 130, 62, 211, 4, 28, 62, 111, 18, 3, 58, 80, 25, 131, 62, 158, 102, 28, 62, 111, 18, 3, 58, 178, 89, 135, 62, 102, 212, 8, 62, 111, 18, 3, 58, 182, 82, 136, 62, 179, 54, 9, 62, 111, 18, 3, 58, 111, 147, 140, 62, 111, 203, 235, 61, 111, 18, 3, 58, 233, 139, 141, 62, 237, 147, 236, 61, 111, 18, 3, 58, 104, 205, 145, 62, 169, 8, 199, 61, 111, 18, 3, 58, 226, 196, 146, 62, 45, 216, 199, 61, 111, 18, 3, 58, 172, 7, 151, 62, 5, 243, 163, 61, 111, 18, 3, 58, 142, 253, 151, 62, 47, 205, 164, 61, 111, 18, 3, 58, 90, 66, 156, 62, 46, 22, 131, 61, 111, 18, 3, 58, 208, 53, 157, 62, 111, 255, 131, 61, 111, 18, 3, 58, 164, 125, 161, 62, 93, 233, 73, 61, 111, 18, 3, 58, 118, 109, 162, 62, 116, 229, 75, 61, 111, 18, 3, 58, 230, 185, 166, 62, 132, 11, 20, 61, 111, 18, 3, 58, 36, 164, 167, 62, 106, 64, 22, 61, 111, 18, 3, 58, 204, 247, 171, 62, 132, 205, 202, 60, 111, 18, 3, 58, 46, 217, 172, 62, 181, 210, 207, 60, 111, 18, 3, 58, 162, 56, 177, 62, 171, 195, 122, 60, 111, 18, 3, 58, 74, 11, 178, 62, 173, 59, 131, 60, 111, 18, 3, 58, 238, 126, 182, 62, 17, 0, 2, 60, 111, 18, 3, 58, 238, 55, 183, 62, 21, 238, 15, 60, 111, 18, 3, 58, 30, 207, 187, 62, 8, 226, 52, 59, 111, 18, 3, 58, 174, 90, 188, 62, 94, 116, 119, 59, 111, 18, 3, 58, 156, 45, 193, 62, 117, 90, 239, 184, 111, 18, 3, 58, 32, 111, 193, 62, 240, 85, 137, 58, 111, 18, 3, 58, 75, 150, 198, 62, 166, 83, 28, 186, 111, 18, 3, 58, 97, 121, 198, 62, 166, 83, 28, 58, 111, 18, 3, 58, 35, 250, 203, 62, 36, 221, 174, 58, 111, 18, 3, 58, 121, 136, 203, 62, 44, 76, 30, 59, 111, 18, 3, 58, 184, 79, 209, 62, 104, 169, 183, 59, 111, 18, 3, 58, 214, 165, 208, 62, 228, 155, 213, 59, 111, 18, 3, 58, 82, 153, 214, 62, 185, 121, 70, 60, 111, 18, 3, 58, 44, 207, 213, 62, 37, 254, 82, 60, 111, 18, 3, 58, 238, 219, 219, 62, 247, 255, 169, 60, 111, 18, 3, 58, 128, 255, 218, 62, 1, 82, 175, 60, 111, 18, 3, 58, 202, 26, 225, 62, 1, 144, 0, 61, 111, 18, 3, 58, 148, 51, 224, 62, 245, 224, 2, 61, 111, 18, 3, 58, 153, 87, 230, 62, 73, 165, 51, 61, 111, 18, 3, 58, 181, 105, 229, 62, 231, 181, 53, 61, 111, 18, 3, 58, 55, 147, 235, 62, 131, 119, 109, 61, 111, 18, 3, 58, 7, 161, 234, 62, 7, 89, 111, 61, 111, 18, 3, 58, 28, 206, 240, 62, 40, 145, 150, 61, 111, 18, 3, 58, 20, 217, 239, 62, 189, 112, 151, 61, 111, 18, 3, 58, 134, 8, 246, 62, 143, 212, 184, 61, 111, 18, 3, 58, 154, 17, 245, 62, 216, 167, 185, 61, 111, 18, 3, 58, 154, 66, 251, 62, 171, 253, 220, 61, 111, 18, 3, 58, 118, 74, 250, 62, 144, 200, 221, 61, 111, 18, 3, 58, 75, 38, 0, 63, 1, 240, 0, 62, 111, 18, 3, 58, 107, 179, 255, 62, 76, 239, 1, 62, 111, 18, 3, 58) }] -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_f7ea3"] -transparency = 1 -cull_mode = 2 -albedo_color = Color(1, 1, 1, 0.164706) +[sub_resource type="ShaderMaterial" id="ShaderMaterial_pexqy"] +render_priority = 0 +shader = ExtResource("2_ryi4h") +shader_parameter/steps = Vector2(10, 10) +shader_parameter/size = Vector2(0.002, 0.002) +shader_parameter/offset = Vector2(0.001, 0.001) [sub_resource type="QuadMesh" id="QuadMesh_b7vce"] size = Vector2(0.5, 0.3) -[sub_resource type="ViewportTexture" id="ViewportTexture_dwm74"] +[sub_resource type="ViewportTexture" id="ViewportTexture_1fknx"] viewport_path = NodePath("XAxis/SubViewport") +[sub_resource type="ViewportTexture" id="ViewportTexture_xdri6"] +viewport_path = NodePath("YAxis/SubViewport") + [node name="LineChart" type="Node3D"] script = ExtResource("1_n7fu8") [node name="Line" type="MeshInstance3D" parent="."] material_override = SubResource("StandardMaterial3D_20gpn") -mesh = SubResource("ArrayMesh_2ookd") - -[node name="YAxis" type="MeshInstance3D" parent="."] +mesh = SubResource("ArrayMesh_ww3lm") [node name="Plane" type="MeshInstance3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.25, 0.15, -0.001) -material_override = SubResource("StandardMaterial3D_f7ea3") +material_override = SubResource("ShaderMaterial_pexqy") mesh = SubResource("QuadMesh_b7vce") [node name="XAxis" type="Sprite3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 0.965926, 0.258819, 0, -0.258819, 0.965926, 0, 0, 0) centered = false -offset = Vector2(-400, 0) +offset = Vector2(0, -400) pixel_size = 0.0001 -billboard = 2 -texture = SubResource("ViewportTexture_dwm74") +texture = SubResource("ViewportTexture_1fknx") [node name="SubViewport" type="SubViewport" parent="XAxis"] transparent_bg = true -size = Vector2i(400, 3000) +size = Vector2i(5000, 400) [node name="XAxis" parent="XAxis/SubViewport" instance=ExtResource("2_2ow77")] + +[node name="YAxis" type="Sprite3D" parent="."] +centered = false +offset = Vector2(-400, 0) +pixel_size = 0.0001 +texture = SubResource("ViewportTexture_xdri6") + +[node name="SubViewport" type="SubViewport" parent="YAxis"] +transparent_bg = true +size = Vector2i(400, 3000) + +[node name="YAxis" parent="YAxis/SubViewport" instance=ExtResource("3_48ptx")] diff --git a/app/content/ui/components/line_chart/x_axis.gd b/app/content/ui/components/line_chart/x_axis.gd index 7ad8a2c..ae7288d 100644 --- a/app/content/ui/components/line_chart/x_axis.gd +++ b/app/content/ui/components/line_chart/x_axis.gd @@ -1,10 +1,47 @@ @tool extends Control -func _draw(): - draw_line(Vector2(380, 0), Vector2(380, 3000), Color(1, 1, 1), 10) +const axil_label_theme = preload ("./axis_label.tres") - for i in range(100, 3000, 100): - draw_line(Vector2(350, i), Vector2(380, i), Color(1, 1, 1), 5) - draw_string_outline(get_theme_default_font(), Vector2(240, i + 15), str(i), HORIZONTAL_ALIGNMENT_RIGHT, 100, 40, 10, Color(0, 0, 0)) - draw_string(get_theme_default_font(), Vector2(240, i + 15), str(i), HORIZONTAL_ALIGNMENT_RIGHT, 100, 40, Color(1, 1, 1)) \ No newline at end of file +const WIDTH = 5000 +const HEIGHT = 400 + +@onready var axis_labels = $AxisLabels + +var minmax = Vector2(0, 100) +var axis_divisions = R.state(10.0) +var font_size = 80 +var border_size = 10 +var display_dates = true + +func _draw(): + var base_axis = 20 + var dash_width = 30 + var text_pos = base_axis + dash_width + + for child in axis_labels.get_children(): + child.free() + + draw_line(Vector2(0, base_axis), Vector2(WIDTH, base_axis), Color(1, 1, 1), 10) + + var y_steps = WIDTH / axis_divisions.value + + for i in range(y_steps, WIDTH, y_steps): + draw_line(Vector2(i, base_axis + dash_width), Vector2(i, base_axis), Color(1, 1, 1), 5) + + var font = get_theme_default_font() + + var relative_i = inverse_lerp(0, WIDTH, i) + + var text = "" + if display_dates: + text = Time.get_datetime_string_from_unix_time(lerp(minmax.x, minmax.y, relative_i)).substr(11, 5) + else: + text = str(round(lerp(minmax.x, minmax.y, relative_i) * 100) / 100) + + var label = Label.new() + label.text = text + label.label_settings = axil_label_theme + label.position = Vector2(i, text_pos) + + axis_labels.add_child(label) \ No newline at end of file diff --git a/app/content/ui/components/line_chart/x_axis.tscn b/app/content/ui/components/line_chart/x_axis.tscn index 65b2090..62c207d 100644 --- a/app/content/ui/components/line_chart/x_axis.tscn +++ b/app/content/ui/components/line_chart/x_axis.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=2 format=3 uid="uid://bs5wjs1sf67il"] +[gd_scene load_steps=3 format=3 uid="uid://bb3shmvedk1oh"] [ext_resource type="Script" path="res://content/ui/components/line_chart/x_axis.gd" id="1_5fiu5"] +[ext_resource type="LabelSettings" uid="uid://bc8arfh1k2gd2" path="res://content/ui/components/line_chart/axis_label.tres" id="2_tapys"] -[node name="Control" type="Control"] +[node name="XAxis" type="Control"] layout_mode = 3 anchors_preset = 15 anchor_right = 1.0 @@ -13,7 +14,15 @@ script = ExtResource("1_5fiu5") [node name="Label" type="Label" parent="."] layout_mode = 0 -offset_right = 40.0 -offset_bottom = 20.0 -theme_override_font_sizes/font_size = 50 +offset_left = 4.0 +offset_top = 43.0 +offset_right = 123.0 +offset_bottom = 93.0 text = "X Axis" +label_settings = ExtResource("2_tapys") +horizontal_alignment = 1 + +[node name="AxisLabels" type="Control" parent="."] +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 diff --git a/app/content/ui/components/line_chart/y_axis.gd b/app/content/ui/components/line_chart/y_axis.gd new file mode 100644 index 0000000..62cf8d4 --- /dev/null +++ b/app/content/ui/components/line_chart/y_axis.gd @@ -0,0 +1,32 @@ +@tool +extends Control + +const WIDTH = 400 +const HEIGHT = 3000 + +var minmax = Vector2(0, 100) +var axis_divisions = R.state(10.0) +var font_size = 80 +var border_size = 10 + +func _draw(): + var base_axis = WIDTH - 20 + var dash_width = -30 + var text_pos = base_axis + dash_width + + draw_line(Vector2(base_axis, 0), Vector2(base_axis, HEIGHT), Color(1, 1, 1), 10) + + var x_steps = HEIGHT / axis_divisions.value + + for i in range(x_steps, HEIGHT, x_steps): + draw_line(Vector2(base_axis + dash_width, i), Vector2(base_axis, i), Color(1, 1, 1), 5) + + var font = get_theme_default_font() + + var relative_i = inverse_lerp(HEIGHT, 0, i) + var text = str(round(lerp(minmax.x, minmax.y, relative_i) * 100) / 100) + + var text_size = font.get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size + border_size) + + draw_string_outline(get_theme_default_font(), Vector2(text_pos - text_size.x, i + text_size.y / 4), text, HORIZONTAL_ALIGNMENT_LEFT, text_size.x, font_size, border_size, Color(0, 0, 0)) + draw_string(get_theme_default_font(), Vector2(text_pos - text_size.x, i + text_size.y / 4), text, HORIZONTAL_ALIGNMENT_LEFT, text_size.x, font_size, Color(1, 1, 1)) \ No newline at end of file diff --git a/app/content/ui/components/line_chart/y_axis.tscn b/app/content/ui/components/line_chart/y_axis.tscn new file mode 100644 index 0000000..27e0114 --- /dev/null +++ b/app/content/ui/components/line_chart/y_axis.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=2 format=3 uid="uid://bs5wjs1sf67il"] + +[ext_resource type="Script" path="res://content/ui/components/line_chart/y_axis.gd" id="1_e83gd"] + +[node name="YAxis" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_e83gd") + +[node name="Label" type="Label" parent="."] +layout_mode = 0 +offset_right = 40.0 +offset_bottom = 20.0 +theme_override_font_sizes/font_size = 50 +text = "Y Axis" diff --git a/app/content/ui/menu/edit/edit_menu.gd b/app/content/ui/menu/edit/edit_menu.gd index 84fa240..7b46d7f 100644 --- a/app/content/ui/menu/edit/edit_menu.gd +++ b/app/content/ui/menu/edit/edit_menu.gd @@ -90,8 +90,10 @@ func render(): previous_page_button.visible = has_prev_page previous_page_button.disabled = !has_prev_page + previous_page_button.body.get_node("CollisionShape3D").disabled = !has_prev_page next_page_button.visible = has_next_page next_page_button.disabled = !has_next_page + next_page_button.body.get_node("CollisionShape3D").disabled = !has_next_page clear_menu() if selected_device == null: diff --git a/app/lib/globals/console.gd b/app/lib/globals/console.gd index bfc3199..1574eff 100644 --- a/app/lib/globals/console.gd +++ b/app/lib/globals/console.gd @@ -2,15 +2,19 @@ extends Node const console_scene = preload ("res://content/ui/console.tscn") var _console: Node3D = null +@onready var main = get_node_or_null("/root/Main") func _ready(): - get_node("/root/Main").tree_entered.connect(func(): + if main == null: + return + + main.tree_entered.connect(func(): init_console() ) func init_console(): _console = console_scene.instantiate() - get_node("/root/Main").add_child(_console) + main.add_child(_console) var camera = get_node("/root/Main/XROrigin3D/XRCamera3D") _console.global_position = camera.global_position + camera.global_transform.basis.z * - 1 diff --git a/app/lib/globals/home_api.gd b/app/lib/globals/home_api.gd index fbaa024..763a3d6 100644 --- a/app/lib/globals/home_api.gd +++ b/app/lib/globals/home_api.gd @@ -120,4 +120,12 @@ func get_voice_assistant() -> VoiceAssistant: if api.has_method("get_voice_assistant") == false: return null - return api.get_voice_assistant() \ No newline at end of file + return api.get_voice_assistant() + +func get_history(entity_id, start, end=null): + assert(has_connected(), "Not connected") + + if api.has_method("get_history") == false: + return null + + return await api.get_history(entity_id, start, end) \ No newline at end of file diff --git a/app/lib/home_apis/hass_ws/handlers/history.gd b/app/lib/home_apis/hass_ws/handlers/history.gd new file mode 100644 index 0000000..eb2f5d1 --- /dev/null +++ b/app/lib/home_apis/hass_ws/handlers/history.gd @@ -0,0 +1,35 @@ +const HASS_API = preload ("../hass.gd") + +var api: HASS_API +var integration_exists: bool = false + +func _init(hass: HASS_API): + self.api = hass + +func get_history(entity_id: String, start: String, end=null): + var meta_response = await api.send_request_packet({ + "type": "recorder/get_statistics_metadata", + "statistic_ids": [ + entity_id + ] + }) + + var data_response = await api.send_request_packet({ + "type": "recorder/statistics_during_period", + "start_time": start, + "statistic_ids": [ + entity_id + ], + "period": "5minute", + "types": [ + "state", + "mean" + ] + }) + + return { + "unit": meta_response.payload.result[0]["display_unit_of_measurement"], + "has_mean": meta_response.payload.result[0]["has_mean"], + "unit_class": meta_response.payload.result[0]["unit_class"], + "data": data_response.payload.result[entity_id] + } \ No newline at end of file diff --git a/app/lib/home_apis/hass_ws/hass.gd b/app/lib/home_apis/hass_ws/hass.gd index 675010f..b3c23d2 100644 --- a/app/lib/home_apis/hass_ws/hass.gd +++ b/app/lib/home_apis/hass_ws/hass.gd @@ -3,6 +3,7 @@ extends Node const AuthHandler = preload ("./handlers/auth.gd") const IntegrationHandler = preload ("./handlers/integration.gd") const AssistHandler = preload ("./handlers/assist.gd") +const HistoryHandler = preload ("./handlers/history.gd") signal on_connect() signal on_disconnect() @@ -27,6 +28,7 @@ var packet_callbacks := CallbackMap.new() var auth_handler: AuthHandler var integration_handler: IntegrationHandler var assist_handler: AssistHandler +var history_handler: HistoryHandler func _init(url:=self.url, token:=self.token): self.url = url @@ -35,6 +37,7 @@ func _init(url:=self.url, token:=self.token): auth_handler = AuthHandler.new(self, url, token) integration_handler = IntegrationHandler.new(self) assist_handler = AssistHandler.new(self) + history_handler = HistoryHandler.new(self) devices_template = devices_template.replace("\n", " ").replace("\t", "").replace("\r", " ") connect_ws() @@ -285,3 +288,6 @@ func update_room(room: String): func get_voice_assistant(): return assist_handler + +func get_history(entity_id, start, end=null): + return await history_handler.get_history(entity_id, start, end) \ No newline at end of file diff --git a/app/lib/stores/house.gd b/app/lib/stores/house.gd index 57de618..2f72c3c 100644 --- a/app/lib/stores/house.gd +++ b/app/lib/stores/house.gd @@ -8,15 +8,16 @@ func _init(): self.state = R.store({ ## Type Room - ## name: String - ## corners: Vec2[] - ## height: float + ## name: String + ## corners: Vec2[] + ## height: float "rooms": [], ## Type Entity ## id: String - ## position: Vec3 - ## rotation: Vec3 - ## room: String + ## position: Vec3 + ## rotation: Vec3 + ## room: String + ## interface: String "entities": [], "align_position1": Vector3(), "align_position2": Vector3() diff --git a/app/lib/utils/entity_factory.gd b/app/lib/utils/entity_factory.gd index 3c34cc5..3608632 100644 --- a/app/lib/utils/entity_factory.gd +++ b/app/lib/utils/entity_factory.gd @@ -9,10 +9,13 @@ const MediaPlayer = preload ("res://content/entities/media_player/media_player.t const Camera = preload ("res://content/entities/camera/camera.tscn") const ButtonEntity = preload ("res://content/entities/button/button.tscn") const NumberEntity = preload ("res://content/entities/number/number.tscn") +const LineGraphEntity = preload ("res://content/entities/line_chart/line_chart.tscn") -static func create_entity(id: String): +static func create_entity(id: String, type=null): var entity = null - var type = id.split(".")[0] + + if type == null: + type = id.split(".")[0] match type: "switch": @@ -29,6 +32,8 @@ static func create_entity(id: String): entity = ButtonEntity.instantiate() "number": entity = NumberEntity.instantiate() + "line_chart": + entity = LineGraphEntity.instantiate() _: return null