Преглед на файлове

app: add reset/default button

darkfi преди 1 година
родител
ревизия
d9ff0595d3
променени са 6 файла, в които са добавени 576 реда и са изтрити 303 реда
  1. 163 0
      bin/app/data/reset.obj
  2. 285 301
      bin/app/src/app/schema/settings.rs
  3. 14 2
      bin/app/src/prop/mod.rs
  4. 10 0
      bin/app/src/scene.rs
  5. 3 0
      bin/app/src/shape/mod.rs
  6. 101 0
      bin/app/src/shape/reset.rs

+ 163 - 0
bin/app/data/reset.obj

@@ -0,0 +1,163 @@
+# Blender 4.0.2
+# www.blender.org
+mtllib reset.mtl
+o Circle
+v -0.998539 0.000000 -0.013554
+v -0.943221 0.000000 0.319850
+v -0.862653 0.000000 0.497547
+v -0.748859 0.000000 0.656365
+v -0.627199 0.000000 0.772373
+v -0.442289 0.000000 0.891786
+v -0.260726 0.000000 0.960204
+v -0.109272 0.000000 0.988958
+v 0.130526 0.000000 0.991445
+v 0.321439 0.000000 0.946930
+v 0.500000 0.000000 0.866025
+v 0.659346 0.000000 0.751840
+v 0.793353 0.000000 0.608762
+v 0.896873 0.000000 0.442289
+v 0.965926 0.000000 0.258819
+v 0.997859 0.000000 0.065403
+v 0.991445 0.000000 -0.130526
+v 0.946930 0.000000 -0.321439
+v 0.866025 0.000000 -0.500000
+v 0.751840 0.000000 -0.659346
+v 0.608762 0.000000 -0.793353
+v 0.442289 0.000000 -0.896873
+v 0.258819 0.000000 -0.965926
+v 0.065403 0.000000 -0.997859
+v -0.130526 0.000000 -0.991445
+v -0.321439 0.000000 -0.946930
+v -0.500000 0.000000 -0.866025
+v -0.656697 0.000000 -0.751310
+v -0.788055 0.000000 -0.608762
+v -0.892104 0.000000 -0.442289
+v -0.795385 0.000000 -0.449426
+v -0.671606 0.000000 -0.580689
+v -0.481700 0.000000 -0.634431
+v -0.400000 0.000000 -0.692820
+v -0.257151 0.000000 -0.757544
+v -0.104421 0.000000 -0.793156
+v 0.052323 0.000000 -0.798287
+v 0.207055 0.000000 -0.772741
+v 0.353831 0.000000 -0.717498
+v 0.487009 0.000000 -0.634683
+v 0.601472 0.000000 -0.527477
+v 0.692820 0.000000 -0.400000
+v 0.757544 0.000000 -0.257151
+v 0.793156 0.000000 -0.104421
+v 0.798287 0.000000 0.052323
+v 0.772741 0.000000 0.207055
+v 0.717498 0.000000 0.353831
+v 0.634683 0.000000 0.487009
+v 0.527477 0.000000 0.601472
+v 0.400000 0.000000 0.692820
+v 0.257152 0.000000 0.757544
+v 0.104421 0.000000 0.793156
+v -0.163584 0.000000 0.793582
+v -0.308589 0.000000 0.771626
+v -0.457404 0.000000 0.716377
+v -0.586841 0.000000 0.648433
+v -0.750937 0.000000 0.532477
+v -0.861636 0.000000 0.423030
+v -0.820416 0.000000 -0.177486
+v -0.647226 0.000000 -0.175467
+v 0.151993 0.000000 -0.418944
+v -0.405869 0.000000 -0.119132
+v -0.951622 0.000000 -0.287706
+v -0.912832 0.000000 -0.122410
+v -0.024370 0.000000 -0.360761
+v -0.697090 0.000000 0.713458
+v -0.694715 0.000000 0.576998
+v -0.838847 0.000000 0.539945
+v -0.832561 0.000000 0.447650
+v -0.554577 0.000000 0.831641
+v -0.565199 0.000000 0.666385
+v -0.382321 0.000000 0.923269
+v -0.349690 0.000000 0.758206
+v -0.000801 0.000000 0.999738
+v -0.001275 0.000000 0.800807
+v -0.025913 0.000000 -0.275497
+v -0.198952 0.000000 -0.191694
+v -0.180252 0.000000 -0.356309
+vn -0.0000 -1.0000 -0.0000
+vt 0.000000 0.000000
+s 0
+f 12/1/1 48/1/1 13/1/1
+f 25/1/1 35/1/1 26/1/1
+f 16/1/1 44/1/1 17/1/1
+f 11/1/1 49/1/1 12/1/1
+f 29/1/1 31/1/1 30/1/1
+f 24/1/1 36/1/1 25/1/1
+f 3/1/1 2/1/1 58/1/1
+f 8/1/1 75/1/1 74/1/1
+f 11/1/1 51/1/1 50/1/1
+f 16/1/1 46/1/1 45/1/1
+f 24/1/1 38/1/1 37/1/1
+f 28/1/1 32/1/1 29/1/1
+f 20/1/1 40/1/1 21/1/1
+f 9/1/1 51/1/1 10/1/1
+f 6/1/1 73/1/1 72/1/1
+f 22/1/1 38/1/1 23/1/1
+f 14/1/1 46/1/1 15/1/1
+f 19/1/1 41/1/1 20/1/1
+f 21/1/1 39/1/1 22/1/1
+f 28/1/1 34/1/1 33/1/1
+f 5/1/1 71/1/1 70/1/1
+f 18/1/1 42/1/1 19/1/1
+f 14/1/1 48/1/1 47/1/1
+f 26/1/1 34/1/1 27/1/1
+f 17/1/1 43/1/1 18/1/1
+f 1/1/1 63/1/1 64/1/1
+f 32/1/1 62/1/1 60/1/1
+f 60/1/1 31/1/1 32/1/1
+f 30/1/1 31/1/1 59/1/1
+f 78/1/1 76/1/1 77/1/1
+f 66/1/1 56/1/1 5/1/1
+f 68/1/1 57/1/1 4/1/1
+f 72/1/1 54/1/1 7/1/1
+f 9/1/1 75/1/1 52/1/1
+f 12/1/1 49/1/1 48/1/1
+f 25/1/1 36/1/1 35/1/1
+f 16/1/1 45/1/1 44/1/1
+f 11/1/1 50/1/1 49/1/1
+f 29/1/1 32/1/1 31/1/1
+f 24/1/1 37/1/1 36/1/1
+f 8/1/1 53/1/1 75/1/1
+f 11/1/1 10/1/1 51/1/1
+f 16/1/1 15/1/1 46/1/1
+f 24/1/1 23/1/1 38/1/1
+f 28/1/1 33/1/1 32/1/1
+f 20/1/1 41/1/1 40/1/1
+f 9/1/1 52/1/1 51/1/1
+f 6/1/1 55/1/1 73/1/1
+f 22/1/1 39/1/1 38/1/1
+f 14/1/1 47/1/1 46/1/1
+f 19/1/1 42/1/1 41/1/1
+f 21/1/1 40/1/1 39/1/1
+f 28/1/1 27/1/1 34/1/1
+f 5/1/1 56/1/1 71/1/1
+f 18/1/1 43/1/1 42/1/1
+f 14/1/1 13/1/1 48/1/1
+f 26/1/1 35/1/1 34/1/1
+f 17/1/1 44/1/1 43/1/1
+f 32/1/1 33/1/1 62/1/1
+f 60/1/1 59/1/1 31/1/1
+f 78/1/1 62/1/1 33/1/1
+f 59/1/1 64/1/1 63/1/1
+f 63/1/1 30/1/1 59/1/1
+f 66/1/1 67/1/1 56/1/1
+f 68/1/1 69/1/1 57/1/1
+f 72/1/1 73/1/1 54/1/1
+f 9/1/1 74/1/1 75/1/1
+f 7/1/1 53/1/1 8/1/1
+f 55/1/1 70/1/1 71/1/1
+f 67/1/1 4/1/1 57/1/1
+f 69/1/1 3/1/1 58/1/1
+f 76/1/1 65/1/1 61/1/1
+f 78/1/1 65/1/1 76/1/1
+f 78/1/1 77/1/1 62/1/1
+f 7/1/1 54/1/1 53/1/1
+f 55/1/1 6/1/1 70/1/1
+f 67/1/1 66/1/1 4/1/1
+f 69/1/1 68/1/1 3/1/1

+ 285 - 301
bin/app/src/app/schema/settings.rs

@@ -16,23 +16,20 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use darkfi::net::settings;
-use sled_overlay::sled;
-
 use crate::{
     app::{
         node::{create_button, create_editbox, create_layer, create_text, create_vector_art},
         App,
     },
     expr::{self, Compiler},
-    prop::{Property, PropertyAtomicGuard, PropertyFloat32, PropertyStr, PropertyValue, Role},
+    prop::{PropertyAtomicGuard, PropertyFloat32, PropertyStr, PropertyValue, Role},
     scene::{SceneNodePtr, Slot},
     shape,
-    ui::{Button, EditBox, Layer, OnModify, ShapeVertex, Text, VectorArt, VectorShape},
+    ui::{Button, EditBox, Layer, ShapeVertex, Text, VectorArt, VectorShape},
     ExecutorPtr,
 };
 
-use super::{ColorScheme, CHANNELS, COLOR_SCHEME};
+use super::{ColorScheme, COLOR_SCHEME};
 
 use std::{
     collections::BTreeMap,
@@ -43,7 +40,6 @@ mod android_ui_consts {
     pub const SETTING_LABEL_X: f32 = 40.;
     pub const SETTING_LABEL_LINESPACE: f32 = 140.;
     pub const SETTING_LABEL_BASELINE: f32 = 82.;
-    pub const SUBTITLE_LABEL_FONTSIZE: f32 = 36.;
     pub const SETTING_LABEL_FONTSIZE: f32 = 24.;
     pub const SETTING_EDIT_FONTSIZE: f32 = 24.;
     pub const SETTING_TITLE_X: f32 = 150.;
@@ -80,7 +76,6 @@ mod ui_consts {
     pub const SETTING_LABEL_X: f32 = 20.;
     pub const SETTING_LABEL_LINESPACE: f32 = 60.;
     pub const SETTING_LABEL_BASELINE: f32 = 37.;
-    pub const SUBTITLE_LABEL_FONTSIZE: f32 = 16.;
     pub const SETTING_LABEL_FONTSIZE: f32 = 14.;
     pub const SETTING_EDIT_FONTSIZE: f32 = 14.;
     pub const SETTING_TITLE_X: f32 = 100.;
@@ -126,9 +121,19 @@ impl Setting {
     fn get_value(&self) -> PropertyValue {
         self.node.get_property("value").unwrap().get_value(0).ok().unwrap()
     }
+    fn get_default(&self) -> PropertyValue {
+        self.node.get_property("default").unwrap().get_value(0).ok().unwrap()
+    }
+    fn is_default(&self) -> bool {
+        self.get_value() == self.get_default()
+    }
+    fn reset(&self) {
+        let prop = self.node.get_property("value").unwrap();
+        prop.set_raw_value(Role::App, 0, self.get_default()).unwrap();
+    }
 }
 
-pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
+pub async fn make(app: &App, window: SceneNodePtr, _ex: ExecutorPtr) {
     let mut cc = Compiler::new();
     cc.add_const_f32("BORDER_RIGHT_SCALE", BORDER_RIGHT_SCALE);
     cc.add_const_f32("SEARCH_PADDING_X", SEARCH_PADDING_X);
@@ -266,19 +271,7 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
     node.set_property_f32(atom, Role::App, "baseline", SETTING_TITLE_BASELINE).unwrap();
     node.set_property_f32(atom, Role::App, "font_size", SETTING_TITLE_FONTSIZE).unwrap();
     node.set_property_str(atom, Role::App, "text", "SETTINGS").unwrap();
-    //node.set_property_str(atom, Role::App, "text", "anon1").unwrap();
-    let prop = node.get_property("text_color").unwrap();
-    if COLOR_SCHEME == ColorScheme::DarkMode {
-        prop.clone().set_f32(atom, Role::App, 0, 1.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 1, 1.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 2, 1.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
-    } else if COLOR_SCHEME == ColorScheme::PaperLight {
-        prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 2, 0.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
-    }
+    node.set_property_f32_vec(atom, Role::App, "text_color", vec![1., 1., 1., 1.]).unwrap();
     node.set_property_u32(atom, Role::App, "z_index", 1).unwrap();
 
     let node = node
@@ -331,18 +324,7 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
         .set_expr(atom, Role::App, 2, cc.compile("w - SEARCH_PADDING_X*2").unwrap())
         .unwrap();
     prop.clone().set_f32(atom, Role::App, 3, SETTING_LABEL_LINESPACE).unwrap();
-    let prop = editbox_node.get_property("text_color").unwrap();
-    if COLOR_SCHEME == ColorScheme::DarkMode {
-        prop.clone().set_f32(atom, Role::App, 0, 1.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 1, 1.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 2, 1.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
-    } else if COLOR_SCHEME == ColorScheme::PaperLight {
-        prop.clone().set_f32(atom, Role::App, 0, 1.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 1, 1.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 2, 1.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
-    }
+    editbox_node.set_property_f32_vec(atom, Role::App, "text_color", vec![1., 1., 1., 1.]).unwrap();
     let prop = editbox_node.get_property("cursor_color").unwrap();
     prop.clone().set_f32(atom, Role::App, 0, 0.5).unwrap();
     prop.clone().set_f32(atom, Role::App, 1, 0.5).unwrap();
@@ -352,18 +334,9 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
     editbox_node.set_property_f32(atom, Role::App, "cursor_descent", CURSOR_DESCENT).unwrap();
     editbox_node.set_property_f32(atom, Role::App, "select_ascent", SELECT_ASCENT).unwrap();
     editbox_node.set_property_f32(atom, Role::App, "select_descent", SELECT_DESCENT).unwrap();
-    let prop = editbox_node.get_property("hi_bg_color").unwrap();
-    if COLOR_SCHEME == ColorScheme::DarkMode {
-        prop.clone().set_f32(atom, Role::App, 0, 0.5).unwrap();
-        prop.clone().set_f32(atom, Role::App, 1, 0.5).unwrap();
-        prop.clone().set_f32(atom, Role::App, 2, 0.5).unwrap();
-        prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
-    } else if COLOR_SCHEME == ColorScheme::PaperLight {
-        prop.clone().set_f32(atom, Role::App, 0, 1.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 1, 1.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 2, 1.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 3, 0.5).unwrap();
-    }
+    editbox_node
+        .set_property_f32_vec(atom, Role::App, "hi_bg_color", vec![0.5, 0.5, 0.5, 1.])
+        .unwrap();
     let prop = editbox_node.get_property("selected").unwrap();
     prop.clone().set_null(atom, Role::App, 0).unwrap();
     prop.clone().set_null(atom, Role::App, 1).unwrap();
@@ -400,18 +373,7 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
     node.set_property_f32(atom, Role::App, "baseline", 16.).unwrap();
     node.set_property_f32(atom, Role::App, "font_size", 16.).unwrap();
     node.set_property_str(atom, Role::App, "text", "SEARCH...").unwrap();
-    let prop = node.get_property("text_color").unwrap();
-    if COLOR_SCHEME == ColorScheme::DarkMode {
-        prop.clone().set_f32(atom, Role::App, 0, 1.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 1, 1.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 2, 1.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 3, 0.45).unwrap();
-    } else if COLOR_SCHEME == ColorScheme::PaperLight {
-        prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 2, 0.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
-    }
+    node.set_property_f32_vec(atom, Role::App, "text_color", vec![1., 1., 1., 0.45]).unwrap();
     node.set_property_u32(atom, Role::App, "z_index", 1).unwrap();
 
     let node = node
@@ -438,18 +400,7 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
     node.set_property_f32(atom, Role::App, "baseline", 16.).unwrap();
     node.set_property_f32(atom, Role::App, "font_size", 16.).unwrap();
     node.set_property_str(atom, Role::App, "text", "").unwrap();
-    let prop = node.get_property("text_color").unwrap();
-    if COLOR_SCHEME == ColorScheme::DarkMode {
-        prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 1, 0.94).unwrap();
-        prop.clone().set_f32(atom, Role::App, 2, 1.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
-    } else if COLOR_SCHEME == ColorScheme::PaperLight {
-        prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 2, 0.).unwrap();
-        prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
-    }
+    node.set_property_f32_vec(atom, Role::App, "text_color", vec![0., 0.94, 1., 1.]).unwrap();
     node.set_property_u32(atom, Role::App, "z_index", 1).unwrap();
 
     let node = node
@@ -466,7 +417,6 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
     layer_node.clone().link(node);
 
     let sg_root3 = app.sg_root.clone();
-    let mut cc2 = cc.clone();
     let search = move || {
         let atom = &mut PropertyAtomicGuard::new();
 
@@ -519,7 +469,7 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
     // Handle searching
     let search_text = editbox_node.get_property("text").unwrap();
     let search_text_sub = search_text.subscribe_modify();
-    let mut search2 = search.clone();
+    let search2 = search.clone();
     let listen_search_text = app.ex.spawn(async move {
         while let Ok(_) = search_text_sub.receive().await {
             search2();
@@ -670,7 +620,7 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
     layer_node.clone().link(settings_layer_node.clone());
 
     // Iterate over the map and process each setting
-    for (key, setting) in settings_map {
+    for setting in settings_map.values() {
         let setting_clone = setting.clone();
         let setting_name = setting_clone.name.clone();
         let is_bool = matches!(setting_clone.get_value(), PropertyValue::Bool(_));
@@ -946,17 +896,14 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
             .set_property_f32(atom, Role::App, "font_size", SETTING_LABEL_FONTSIZE)
             .unwrap();
         label_value_node.set_property_str(atom, Role::App, "text", setting_name.clone()).unwrap();
-        let prop = label_value_node.get_property("text_color").unwrap();
-        if COLOR_SCHEME == ColorScheme::DarkMode {
-            prop.clone().set_f32(atom, Role::App, 0, 0.65).unwrap();
-            prop.clone().set_f32(atom, Role::App, 1, 0.87).unwrap();
-            prop.clone().set_f32(atom, Role::App, 2, 0.83).unwrap();
-            prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
-        } else if COLOR_SCHEME == ColorScheme::PaperLight {
-            prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
-            prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
-            prop.clone().set_f32(atom, Role::App, 2, 0.).unwrap();
-            prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
+        if setting.is_default() {
+            label_value_node
+                .set_property_f32_vec(atom, Role::App, "text_color", vec![0.65, 0.87, 0.83, 1.])
+                .unwrap();
+        } else {
+            label_value_node
+                .set_property_f32_vec(atom, Role::App, "text_color", vec![1., 1., 1., 1.])
+                .unwrap();
         }
         label_value_node.set_property_u32(atom, Role::App, "z_index", 1).unwrap();
 
@@ -988,39 +935,19 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
         prop.clone().set_f32(atom, Role::App, 3, SETTING_LABEL_LINESPACE).unwrap();
         editbox_node.set_property_f32(atom, Role::App, "baseline", SETTING_LABEL_BASELINE).unwrap();
         editbox_node.set_property_f32(atom, Role::App, "font_size", SETTING_EDIT_FONTSIZE).unwrap();
-        let prop = editbox_node.get_property("text_color").unwrap();
-        if COLOR_SCHEME == ColorScheme::DarkMode {
-            prop.clone().set_f32(atom, Role::App, 0, 0.7).unwrap();
-            prop.clone().set_f32(atom, Role::App, 1, 0.7).unwrap();
-            prop.clone().set_f32(atom, Role::App, 2, 0.7).unwrap();
-            prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
-        } else if COLOR_SCHEME == ColorScheme::PaperLight {
-            prop.clone().set_f32(atom, Role::App, 0, 1.).unwrap();
-            prop.clone().set_f32(atom, Role::App, 1, 1.).unwrap();
-            prop.clone().set_f32(atom, Role::App, 2, 1.).unwrap();
-            prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
-        }
-        let prop = editbox_node.get_property("cursor_color").unwrap();
-        prop.clone().set_f32(atom, Role::App, 0, 0.5).unwrap();
-        prop.clone().set_f32(atom, Role::App, 1, 0.5).unwrap();
-        prop.clone().set_f32(atom, Role::App, 2, 0.5).unwrap();
-        prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
         editbox_node.set_property_f32(atom, Role::App, "cursor_ascent", CURSOR_ASCENT).unwrap();
         editbox_node.set_property_f32(atom, Role::App, "cursor_descent", CURSOR_DESCENT).unwrap();
         editbox_node.set_property_f32(atom, Role::App, "select_ascent", SELECT_ASCENT).unwrap();
         editbox_node.set_property_f32(atom, Role::App, "select_descent", SELECT_DESCENT).unwrap();
-        let prop = editbox_node.get_property("hi_bg_color").unwrap();
-        if COLOR_SCHEME == ColorScheme::DarkMode {
-            prop.clone().set_f32(atom, Role::App, 0, 0.5).unwrap();
-            prop.clone().set_f32(atom, Role::App, 1, 0.5).unwrap();
-            prop.clone().set_f32(atom, Role::App, 2, 0.5).unwrap();
-            prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
-        } else if COLOR_SCHEME == ColorScheme::PaperLight {
-            prop.clone().set_f32(atom, Role::App, 0, 1.).unwrap();
-            prop.clone().set_f32(atom, Role::App, 1, 1.).unwrap();
-            prop.clone().set_f32(atom, Role::App, 2, 1.).unwrap();
-            prop.clone().set_f32(atom, Role::App, 3, 0.5).unwrap();
-        }
+        editbox_node
+            .set_property_f32_vec(atom, Role::App, "text_color", vec![0.7, 0.7, 0.7, 1.])
+            .unwrap();
+        editbox_node
+            .set_property_f32_vec(atom, Role::App, "cursor_color", vec![0.5, 0.5, 0.5, 1.])
+            .unwrap();
+        editbox_node
+            .set_property_f32_vec(atom, Role::App, "hi_bg_color", vec![0.5, 0.5, 0.5, 1.])
+            .unwrap();
         let prop = editbox_node.get_property("selected").unwrap();
         prop.clone().set_null(atom, Role::App, 0).unwrap();
         prop.clone().set_null(atom, Role::App, 1).unwrap();
@@ -1036,7 +963,7 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
             let (slot, recvr) = Slot::new("setting_enter_pressed");
             editbox_node.register("enter_pressed", slot).unwrap();
             let setting2 = setting.clone();
-            let sg_root2 = app.sg_root.clone();
+            let sg_root2 = setting_layer_node.clone();
             let active_setting2 = active_setting.clone();
             let editz_text2 = editz_text.clone();
             let listen_enter = app.ex.spawn(async move {
@@ -1048,6 +975,7 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
                         editz_text2.clone(),
                     )
                     .await;
+                    refresh_setting(setting2.clone(), sg_root2.clone());
                 }
             });
             app.tasks.lock().unwrap().push(listen_enter);
@@ -1159,17 +1087,24 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
                 value_node
                     .set_property_str(atom, Role::App, "text", setting_clone.value_as_string())
                     .unwrap();
-                let prop = value_node.get_property("text_color").unwrap();
                 if matches!(setting_clone.get_value(), PropertyValue::Bool(false)) {
-                    prop.clone().set_f32(atom, Role::App, 0, 0.9).unwrap();
-                    prop.clone().set_f32(atom, Role::App, 1, 0.4).unwrap();
-                    prop.clone().set_f32(atom, Role::App, 2, 0.4).unwrap();
-                    prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
+                    value_node
+                        .set_property_f32_vec(
+                            atom,
+                            Role::App,
+                            "text_color",
+                            vec![0.9, 0.4, 0.4, 1.],
+                        )
+                        .unwrap();
                 } else {
-                    prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
-                    prop.clone().set_f32(atom, Role::App, 1, 0.94).unwrap();
-                    prop.clone().set_f32(atom, Role::App, 2, 1.).unwrap();
-                    prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
+                    value_node
+                        .set_property_f32_vec(
+                            atom,
+                            Role::App,
+                            "text_color",
+                            vec![0.0, 0.94, 1., 1.],
+                        )
+                        .unwrap();
                 }
                 value_node.set_property_u32(atom, Role::App, "z_index", 2).unwrap();
 
@@ -1212,18 +1147,9 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
                 value_node
                     .set_property_str(atom, Role::App, "text", setting_clone.value_as_string())
                     .unwrap();
-                let prop = value_node.get_property("text_color").unwrap();
-                if COLOR_SCHEME == ColorScheme::DarkMode {
-                    prop.clone().set_f32(atom, Role::App, 0, 1.).unwrap();
-                    prop.clone().set_f32(atom, Role::App, 1, 1.).unwrap();
-                    prop.clone().set_f32(atom, Role::App, 2, 1.).unwrap();
-                    prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
-                } else if COLOR_SCHEME == ColorScheme::PaperLight {
-                    prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
-                    prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
-                    prop.clone().set_f32(atom, Role::App, 2, 0.).unwrap();
-                    prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
-                }
+                value_node
+                    .set_property_f32_vec(atom, Role::App, "text_color", vec![1., 1., 1., 1.])
+                    .unwrap();
                 value_node.set_property_u32(atom, Role::App, "z_index", 2).unwrap();
 
                 let node = value_node
@@ -1251,10 +1177,12 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
                 .unwrap();
             prop.clone().set_f32(atom, Role::App, 3, SETTING_LABEL_LINESPACE).unwrap();
 
-            let sg_root = app.sg_root.clone();
+            let sg_root2 = app.sg_root.clone();
+            let setting_clone2 = setting_clone.clone();
+            let setting_root2 = setting_layer_node.clone();
             let select = move || {
                 let atom = &mut PropertyAtomicGuard::new();
-                let sg_root = sg_root.clone();
+                let sg_root = sg_root2.clone();
                 let mut lock = cloned_active_setting.lock().unwrap();
 
                 let path = "/window/settings_layer/search_input";
@@ -1263,37 +1191,39 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
                 node.set_property_bool(atom, Role::App, "is_focused", false).unwrap();
 
                 let was_active = if let Some(s) = lock.as_ref() {
-                    let _was_active = s.name == setting_clone.clone().name;
+                    let path = format!("/window/settings_layer/settings/{}", &s.name);
+                    let old_node = sg_root.clone().lookup_node(&path).unwrap();
+
+                    let _was_active = s.name == setting_clone2.clone().name;
 
-                    // Hide the selected setting value label (set its text empty)
+                    // Show the selected setting value label
                     // of the selected setting, if there's one
-                    let path = format!("/window/settings_layer/settings/{}/value_label", &s.name);
-                    let node = sg_root.clone().lookup_node(&path).unwrap();
+                    let node = old_node.clone().lookup_node("/value_label").unwrap();
                     let text = PropertyStr::wrap(&node, Role::App, "text", 0).unwrap();
                     text.set(atom, &s.value_as_string());
 
-                    // Hide the selected setting value label (set its text empty)
+                    // Hide the selected setting editbox
                     // of the selected setting, if there's one
                     if !_was_active {
-                        let path =
-                            format!("/window/settings_layer/settings/{}/value_editbox", &s.name);
-                        let node = sg_root.clone().lookup_node(&path).unwrap();
+                        let node = old_node.clone().lookup_node("/value_editbox").unwrap();
                         node.set_property_bool(atom, Role::App, "is_active", false).unwrap();
                         node.set_property_bool(atom, Role::App, "is_focused", false).unwrap();
                         node.set_property_f32(atom, Role::App, "font_size", 0.).unwrap();
                         node.set_property_str(atom, Role::App, "text", "").unwrap();
                     }
 
-                    // Hide confirm button
+                    // Hide conftrm button
                     // (Bool settings don't have a confirm button so we have to check for it to
                     // not panic)
                     let is_bool =
                         matches!(lock.clone().unwrap().get_value(), PropertyValue::Bool(_));
                     if !is_bool {
-                        let path =
-                            format!("/window/settings_layer/settings/{}/confirm_btn_bg", &s.name);
-                        let node = sg_root.clone().lookup_node(&path).unwrap();
-                        node.set_property_bool(atom, Role::App, "is_visible", false).unwrap();
+                        old_node
+                            .clone()
+                            .lookup_node("/confirm_btn_bg")
+                            .unwrap()
+                            .set_property_bool(atom, Role::App, "is_visible", false)
+                            .unwrap();
                     }
 
                     _was_active
@@ -1302,132 +1232,107 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
                 };
 
                 // Update what setting active_setting points to
-                *lock = Some(setting_clone.clone());
+                *lock = Some(setting_clone2.clone());
                 debug!("active setting set to: {}", lock.clone().unwrap().name);
 
-                let is_bool = matches!(lock.clone().unwrap().get_value(), PropertyValue::Bool(_));
                 if is_bool {
                     // Hide the setting value label (set its text empty)
-                    let label_path = format!(
-                        "/window/settings_layer/settings/{}/value_label",
-                        &setting_clone.name
-                    );
-                    let editbox = sg_root.clone().lookup_node(&label_path).unwrap();
+                    let editbox = setting_root2.clone().lookup_node("/value_label").unwrap();
                     let label_text = PropertyStr::wrap(&editbox, Role::App, "text", 0).unwrap();
-                    let value = &lock.clone().unwrap().get_value();
-
-                    let path = format!(
-                        "/window/settings_layer/settings/{}/value_bg_bool_true",
-                        &setting_clone.name
-                    );
-                    let node = sg_root.clone().lookup_node(&path).unwrap();
-                    let _ = node.set_property_bool(atom, Role::App, "is_visible", false);
-
-                    let path = format!(
-                        "/window/settings_layer/settings/{}/value_bg_bool_false",
-                        &setting_clone.name
-                    );
-                    let node = sg_root.clone().lookup_node(&path).unwrap();
-                    let _ = node.set_property_bool(atom, Role::App, "is_visible", false);
-
-                    let path = format!(
-                        "/window/settings_layer/settings/{}/bool_icon_bg_true",
-                        &setting_clone.name
-                    );
-                    let node = sg_root.clone().lookup_node(&path).unwrap();
-                    let _ = node.set_property_bool(atom, Role::App, "is_visible", false);
-
-                    let path = format!(
-                        "/window/settings_layer/settings/{}/bool_icon_bg_false",
-                        &setting_clone.name
-                    );
-                    let node = sg_root.clone().lookup_node(&path).unwrap();
-                    let _ = node.set_property_bool(atom, Role::App, "is_visible", false);
+
+                    let value = setting_clone2.get_value();
+
+                    setting_root2
+                        .clone()
+                        .lookup_node("/value_bg_bool_true")
+                        .unwrap()
+                        .set_property_bool(atom, Role::App, "is_visible", false)
+                        .unwrap();
+                    setting_root2
+                        .clone()
+                        .lookup_node("/value_bg_bool_false")
+                        .unwrap()
+                        .set_property_bool(atom, Role::App, "is_visible", false)
+                        .unwrap();
+                    setting_root2
+                        .clone()
+                        .lookup_node("/bool_icon_bg_true")
+                        .unwrap()
+                        .set_property_bool(atom, Role::App, "is_visible", false)
+                        .unwrap();
+                    setting_root2
+                        .clone()
+                        .lookup_node("/bool_icon_bg_false")
+                        .unwrap()
+                        .set_property_bool(atom, Role::App, "is_visible", false)
+                        .unwrap();
 
                     if matches!(value, PropertyValue::Bool(false)) {
-                        &lock.clone().unwrap().node.set_property_bool(
-                            atom,
-                            Role::User,
-                            "value",
-                            true,
-                        );
+                        setting_clone2
+                            .node
+                            .set_property_bool(atom, Role::User, "value", true)
+                            .unwrap();
                         label_text.set(atom, "TRUE");
 
-                        let path = format!(
-                            "/window/settings_layer/settings/{}/value_bg_bool_true",
-                            &setting_clone.name
-                        );
-                        let node = sg_root.clone().lookup_node(&path).unwrap();
-                        let _ = node.set_property_bool(atom, Role::App, "is_visible", true);
-
-                        let path = format!(
-                            "/window/settings_layer/settings/{}/bool_icon_bg_true",
-                            &setting_clone.name
-                        );
-                        let node = sg_root.clone().lookup_node(&path).unwrap();
-                        let _ = node.set_property_bool(atom, Role::App, "is_visible", true);
-
-                        let path = format!(
-                            "/window/settings_layer/settings/{}/value_label",
-                            &setting_clone.name
-                        );
-                        let node = sg_root.clone().lookup_node(&path).unwrap();
-                        let prop = node.get_property("text_color").unwrap();
-                        prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
-                        prop.clone().set_f32(atom, Role::App, 1, 0.94).unwrap();
-                        prop.clone().set_f32(atom, Role::App, 2, 1.).unwrap();
-                        prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
-                    } else {
-                        &lock.clone().unwrap().node.set_property_bool(
+                        setting_root2
+                            .clone()
+                            .lookup_node("/value_bg_bool_true")
+                            .unwrap()
+                            .set_property_bool(atom, Role::App, "is_visible", true)
+                            .unwrap();
+                        setting_root2
+                            .clone()
+                            .lookup_node("/bool_icon_bg_true")
+                            .unwrap()
+                            .set_property_bool(atom, Role::App, "is_visible", true)
+                            .unwrap();
+
+                        let node = setting_root2.clone().lookup_node("/value_label").unwrap();
+                        node.set_property_f32_vec(
                             atom,
-                            Role::User,
-                            "value",
-                            false,
-                        );
+                            Role::App,
+                            "text_color",
+                            vec![0., 0.94, 1., 1.],
+                        )
+                        .unwrap();
+                    } else {
+                        setting_clone2
+                            .node
+                            .set_property_bool(atom, Role::User, "value", false)
+                            .unwrap();
                         label_text.set(atom, "FALSE");
 
-                        let path = format!(
-                            "/window/settings_layer/settings/{}/value_bg_bool_false",
-                            &setting_clone.name
-                        );
-                        let node = sg_root.clone().lookup_node(&path).unwrap();
-                        let _ = node.set_property_bool(atom, Role::App, "is_visible", true);
-
-                        let path = format!(
-                            "/window/settings_layer/settings/{}/bool_icon_bg_false",
-                            &setting_clone.name
-                        );
-                        let node = sg_root.clone().lookup_node(&path).unwrap();
-                        let _ = node.set_property_bool(atom, Role::App, "is_visible", true);
-
-                        let path = format!(
-                            "/window/settings_layer/settings/{}/value_label",
-                            &setting_clone.name
-                        );
-                        let node = sg_root.clone().lookup_node(&path).unwrap();
-                        let prop = node.get_property("text_color").unwrap();
-                        prop.clone().set_f32(atom, Role::App, 0, 0.9).unwrap();
-                        prop.clone().set_f32(atom, Role::App, 1, 0.4).unwrap();
-                        prop.clone().set_f32(atom, Role::App, 2, 0.4).unwrap();
-                        prop.clone().set_f32(atom, Role::App, 3, 1.).unwrap();
+                        setting_root2
+                            .clone()
+                            .lookup_node("/value_bg_bool_false")
+                            .unwrap()
+                            .set_property_bool(atom, Role::App, "is_visible", true)
+                            .unwrap();
+                        setting_root2
+                            .clone()
+                            .lookup_node("/bool_icon_bg_false")
+                            .unwrap()
+                            .set_property_bool(atom, Role::App, "is_visible", true)
+                            .unwrap();
+
+                        let node = setting_root2.clone().lookup_node("/value_label").unwrap();
+                        node.set_property_f32_vec(
+                            atom,
+                            Role::App,
+                            "text_color",
+                            vec![0.9, 0.4, 0.4, 1.],
+                        )
+                        .unwrap();
                     }
                 } else {
                     // Hide the setting value label (set its text empty)
                     // TODO?: Visilibity property on labels
-                    let label_path = format!(
-                        "/window/settings_layer/settings/{}/value_label",
-                        &setting_clone.name
-                    );
-                    let editbox = sg_root.clone().lookup_node(&label_path).unwrap();
+                    let editbox = setting_root2.clone().lookup_node("/value_label").unwrap();
                     let label_text = PropertyStr::wrap(&editbox, Role::App, "text", 0).unwrap();
                     label_text.set(atom, "");
 
                     // Show the editbox
-                    let path = format!(
-                        "/window/settings_layer/settings/{}/value_editbox",
-                        &setting_clone.name
-                    );
-                    let node = sg_root.clone().lookup_node(&path).unwrap();
+                    let node = setting_root2.clone().lookup_node("/value_editbox").unwrap();
                     node.set_property_bool(atom, Role::App, "is_active", true).unwrap();
                     node.set_property_bool(atom, Role::App, "is_focused", true).unwrap();
                     node.set_property_f32(atom, Role::App, "font_size", 16.).unwrap();
@@ -1436,33 +1341,37 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
                             atom,
                             Role::App,
                             "text",
-                            setting_clone.value_as_string(),
+                            setting_clone2.value_as_string(),
                         )
                         .unwrap();
                     }
 
                     // Show confirm button
-                    let path = format!(
-                        "/window/settings_layer/settings/{}/confirm_btn_bg",
-                        &setting_clone.name
-                    );
-                    let node = sg_root.clone().lookup_node(&path).unwrap();
-                    let _ = node.set_property_bool(atom, Role::App, "is_visible", true);
+                    setting_root2
+                        .clone()
+                        .lookup_node("/confirm_btn_bg")
+                        .unwrap()
+                        .set_property_bool(atom, Role::App, "is_visible", true)
+                        .unwrap();
                 }
+
+                refresh_setting(setting_clone2.clone(), setting_root2.clone());
             };
 
-            let (slot, recvr) = Slot::new("back_clicked");
-            node.register("click", slot).unwrap();
-            let select2 = select.clone();
-            let listen_click = app.ex.spawn(async move {
-                while let Ok(_) = recvr.recv().await {
-                    select2();
-                }
-            });
-            app.tasks.lock().unwrap().push(listen_click);
+            {
+                let (slot, recvr) = Slot::new("select_clicked");
+                node.register("click", slot).unwrap();
+                let select2 = select.clone();
+                let listen_click = app.ex.spawn(async move {
+                    while let Ok(_) = recvr.recv().await {
+                        select2();
+                    }
+                });
+                app.tasks.lock().unwrap().push(listen_click);
 
-            let node = node.setup(|me| Button::new(me, app.ex.clone())).await;
-            setting_layer_node.clone().link(node.clone());
+                let node = node.setup(|me| Button::new(me, app.ex.clone())).await;
+                setting_layer_node.clone().link(node.clone());
+            }
         }
 
         if is_bool {
@@ -1514,7 +1423,7 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
                 let (slot, recvr) = Slot::new("confirm_clicked");
                 node.register("click", slot).unwrap();
                 let setting2 = setting.clone();
-                let sg_root2 = app.sg_root.clone();
+                let sg_root2 = setting_layer_node.clone();
                 let active_setting2 = active_setting.clone();
                 let editz_text2 = editz_text.clone();
                 let listen_click = app.ex.spawn(async move {
@@ -1527,35 +1436,118 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
                             editz_text2.clone(),
                         )
                         .await;
+                        refresh_setting(setting2.clone(), sg_root2.clone());
                     }
                 });
                 app.tasks.lock().unwrap().push(listen_click);
             }
         }
+
+        // Reset icon
+        let node = create_vector_art("reset_btn_bg");
+        let prop = node.get_property("rect").unwrap();
+        prop.clone().set_expr(atom, Role::App, 0, cc.compile("w - 100").unwrap()).unwrap();
+        prop.clone().set_f32(atom, Role::App, 1, SETTING_LABEL_LINESPACE / 2.).unwrap();
+        prop.clone().set_f32(atom, Role::App, 2, 0.).unwrap();
+        prop.clone().set_f32(atom, Role::App, 3, 0.).unwrap();
+        node.set_property_bool(atom, Role::App, "is_visible", !setting.is_default()).unwrap();
+        node.set_property_u32(atom, Role::App, "z_index", 1).unwrap();
+
+        let shape = shape::create_reset([0., 0.94, 1., 1.]).scaled(15.);
+        let node = node
+            .setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone()))
+            .await;
+        setting_layer_node.clone().link(node);
+
+        let node = create_button("reset_btn");
+        node.set_property_bool(atom, Role::App, "is_active", !setting.is_default()).unwrap();
+        let prop = node.get_property("rect").unwrap();
+        prop.clone().set_expr(atom, Role::App, 0, cc.compile("w - 115").unwrap()).unwrap();
+        prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
+        prop.clone().set_f32(atom, Role::App, 2, 50.).unwrap();
+        prop.clone().set_f32(atom, Role::App, 3, SETTING_LABEL_LINESPACE).unwrap();
+        node.set_property_u32(atom, Role::App, "z_index", 3).unwrap();
+
+        let node = node.setup(|me| Button::new(me, app.ex.clone())).await;
+        setting_layer_node.clone().link(node.clone());
+
+        // Handle reset button click
+        {
+            let (slot, recvr) = Slot::new("reset_clicked");
+            node.register("click", slot).unwrap();
+            let setting2 = setting.clone();
+            let sg_root2 = setting_layer_node.clone();
+            let active_setting2 = active_setting.clone();
+            let editz_text2 = editz_text.clone();
+            let listen_click = app.ex.spawn(async move {
+                while let Ok(_) = recvr.recv().await {
+                    info!("reset clicked");
+                    setting2.reset();
+
+                    let atom = &mut PropertyAtomicGuard::new();
+
+                    // Show the selected setting value label (set its text empty)
+                    // of the selected setting, if there's one
+                    let node = sg_root2.clone().lookup_node("/value_label").unwrap();
+                    let text = PropertyStr::wrap(&node, Role::App, "text", 0).unwrap();
+                    text.set(atom, setting2.value_as_string());
+
+                    let node = sg_root2.clone().lookup_node("/value_editbox").unwrap();
+                    node.set_property_str(atom, Role::App, "text", setting2.value_as_string())
+                        .unwrap();
+
+                    update_setting(
+                        setting2.clone(),
+                        sg_root2.clone(),
+                        active_setting2.clone(),
+                        editz_text2.clone(),
+                    )
+                    .await;
+                    refresh_setting(setting2.clone(), sg_root2.clone());
+                }
+            });
+            app.tasks.lock().unwrap().push(listen_click);
+        }
     }
 
     let settings_node = app.sg_root.clone().lookup_node("/window/settings_layer").unwrap();
     settings_node.set_property_bool(atom, Role::App, "is_visible", false).unwrap();
 
-    let path = "/window/settings_layer/settings";
-    let node = app.sg_root.clone().lookup_node(path.to_string()).unwrap();
+    // Searchbar results count
+    let node = app.sg_root.clone().lookup_node("/window/settings_layer/settings").unwrap();
     let counter_text = node.get_children().len().to_string();
-    let path = "/window/settings_layer/search_count";
-    let node = app.sg_root.clone().lookup_node(path.to_string()).unwrap();
-    let _ = node.set_property_str(atom, Role::App, "text", &counter_text).unwrap();
+    let node = app.sg_root.clone().lookup_node("/window/settings_layer/search_count").unwrap();
+    node.set_property_str(atom, Role::App, "text", &counter_text).unwrap();
+}
+
+fn refresh_setting(setting: Arc<Setting>, sn: SceneNodePtr) {
+    let atom = &mut PropertyAtomicGuard::new();
+    let is_bool = matches!(setting.get_value(), PropertyValue::Bool(_));
+
+    let node = sn.clone().lookup_node("/key_label").unwrap();
+    if setting.clone().is_default() {
+        node.set_property_f32_vec(atom, Role::App, "text_color", vec![0.65, 0.87, 0.83, 1.])
+            .unwrap();
+    } else {
+        node.set_property_f32_vec(atom, Role::App, "text_color", vec![1., 1., 1., 1.]).unwrap();
+    }
+
+    let node = sn.clone().lookup_node("/reset_btn_bg").unwrap();
+    node.set_property_bool(atom, Role::App, "is_visible", !setting.clone().is_default()).unwrap();
+    let node = sn.clone().lookup_node("/reset_btn").unwrap();
+    node.set_property_bool(atom, Role::App, "is_active", !is_bool && !setting.clone().is_default())
+        .unwrap();
 }
 
 async fn update_setting(
     setting: Arc<Setting>,
-    sg_root: SceneNodePtr,
+    sn: SceneNodePtr,
     active_setting: Arc<Mutex<Option<Arc<Setting>>>>,
     editz_text: PropertyStr,
 ) {
     let atom = &mut PropertyAtomicGuard::new();
-    let setting_name = &setting.clone().name;
 
-    let path = format!("/window/settings_layer/settings/{}/value_editbox", setting_name);
-    if let Some(node) = sg_root.clone().lookup_node(path) {
+    if let Some(node) = sn.clone().lookup_node("/value_editbox") {
         node.set_property_f32(atom, Role::App, "font_size", 0.).unwrap();
         node.set_property_bool(atom, Role::App, "is_active", false).unwrap();
         node.set_property_bool(atom, Role::App, "is_focused", false).unwrap();
@@ -1566,16 +1558,13 @@ async fn update_setting(
             let value_str = editz_text.get();
             let parsed = value_str.parse::<u32>();
             if let Ok(value) = parsed {
-                let path = format!("/window/settings_layer/settings/{}/value_label", setting_name);
-                if let Some(node) = sg_root.clone().lookup_node(path) {
+                if let Some(node) = sn.clone().lookup_node("/value_label") {
                     node.set_property_str(atom, Role::App, "text", value_str).unwrap();
                 }
-                let path =
-                    format!("/window/settings_layer/settings/{}/confirm_btn_bg", setting_name);
-                if let Some(node) = sg_root.clone().lookup_node(path) {
+                if let Some(node) = sn.clone().lookup_node("/confirm_btn_bg") {
                     node.set_property_bool(atom, Role::App, "is_visible", false).unwrap();
                 }
-                setting.node.set_property_u32(atom, Role::User, "value", value);
+                setting.node.set_property_u32(atom, Role::User, "value", value).unwrap();
                 let mut active_setting_value = active_setting.lock().unwrap();
                 *active_setting_value = None;
             }
@@ -1584,31 +1573,26 @@ async fn update_setting(
             let value_str = editz_text.get();
             let parsed = value_str.parse::<f32>();
             if let Ok(value) = parsed {
-                let path = format!("/window/settings_layer/settings/{}/value_label", setting_name);
-                if let Some(node) = sg_root.clone().lookup_node(path) {
+                if let Some(node) = sn.clone().lookup_node("/value_label") {
                     node.set_property_str(atom, Role::App, "text", value_str).unwrap();
                 }
-                let path =
-                    format!("/window/settings_layer/settings/{}/confirm_btn_bg", setting_name);
-                if let Some(node) = sg_root.clone().lookup_node(path) {
+                if let Some(node) = sn.clone().lookup_node("/confirm_btn_bg") {
                     node.set_property_bool(atom, Role::App, "is_visible", false).unwrap();
                 }
-                setting.node.set_property_f32(atom, Role::User, "value", value);
+                setting.node.set_property_f32(atom, Role::User, "value", value).unwrap();
                 let mut active_setting_value = active_setting.lock().unwrap();
                 *active_setting_value = None;
             }
         }
         PropertyValue::Str(_) => {
             let value_str = editz_text.get();
-            let path = format!("/window/settings_layer/settings/{}/value_label", setting_name);
-            if let Some(node) = sg_root.clone().lookup_node(path) {
+            if let Some(node) = sn.clone().lookup_node("/value_label") {
                 node.set_property_str(atom, Role::App, "text", &value_str).unwrap();
             }
-            let path = format!("/window/settings_layer/{}/confirm_btn_bg", setting_name);
-            if let Some(node) = sg_root.clone().lookup_node(path) {
+            if let Some(node) = sn.clone().lookup_node("/confirm_btn_bg") {
                 node.set_property_bool(atom, Role::App, "is_visible", false).unwrap();
             }
-            setting.node.set_property_str(atom, Role::User, "value", value_str);
+            setting.node.set_property_str(atom, Role::User, "value", value_str).unwrap();
             let mut active_setting_value = active_setting.lock().unwrap();
             *active_setting_value = None;
         }

+ 14 - 2
bin/app/src/prop/mod.rs

@@ -84,7 +84,7 @@ pub enum Role {
     Ignored = 3,
 }
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq)]
 pub enum PropertyValue {
     Unset,
     Null,
@@ -371,7 +371,7 @@ impl Property {
         self.on_modify.notify((role, ModifyAction::Clear));
     }
 
-    fn set_raw_value(&self, role: Role, i: usize, val: PropertyValue) -> Result<()> {
+    pub fn set_raw_value(&self, role: Role, i: usize, val: PropertyValue) -> Result<()> {
         if self.typ != val.as_type() {
             return Err(Error::PropertyWrongType)
         }
@@ -540,6 +540,18 @@ impl Property {
         Ok(())
     }
 
+    pub fn set_f32_vec(
+        self: Arc<Self>,
+        atom: &mut PropertyAtomicGuard,
+        role: Role,
+        val: Vec<f32>,
+    ) -> Result<()> {
+        for (i, &val) in val.iter().enumerate() {
+            self.clone().set_f32(atom, role, i, val)?;
+        }
+        Ok(())
+    }
+
     fn set_cache(&self, role: Role, i: usize, val: PropertyValue) -> Result<()> {
         if self.typ != val.as_type() {
             return Err(Error::PropertyWrongType)

+ 10 - 0
bin/app/src/scene.rs

@@ -288,6 +288,16 @@ impl SceneNode {
         self.get_property(name).ok_or(Error::PropertyNotFound)?.set_node_id(atom, role, 0, val)
     }
 
+    pub fn set_property_f32_vec(
+        &self,
+        atom: &mut PropertyAtomicGuard,
+        role: Role,
+        name: &str,
+        val: Vec<f32>,
+    ) -> Result<()> {
+        self.get_property(name).ok_or(Error::PropertyNotFound)?.set_f32_vec(atom, role, val)
+    }
+
     pub fn add_signal<S: Into<String>>(
         &mut self,
         name: S,

+ 3 - 0
bin/app/src/shape/mod.rs

@@ -49,3 +49,6 @@ pub use circle::create_circle;
 
 mod logo;
 pub use logo::create_logo;
+
+mod reset;
+pub use reset::create_reset;

+ 101 - 0
bin/app/src/shape/reset.rs

@@ -0,0 +1,101 @@
+use crate::{
+    mesh::Color,
+    ui::{ShapeVertex, VectorShape},
+};
+pub fn create_reset(color: Color) -> VectorShape {
+    VectorShape {
+        verts: vec![
+            ShapeVertex::from_xy(-0.998539, -0.013554, color),
+            ShapeVertex::from_xy(-0.943221, 0.31985, color),
+            ShapeVertex::from_xy(-0.862653, 0.497547, color),
+            ShapeVertex::from_xy(-0.748859, 0.656365, color),
+            ShapeVertex::from_xy(-0.627199, 0.772373, color),
+            ShapeVertex::from_xy(-0.442289, 0.891786, color),
+            ShapeVertex::from_xy(-0.260726, 0.960204, color),
+            ShapeVertex::from_xy(-0.109272, 0.988958, color),
+            ShapeVertex::from_xy(0.130526, 0.991445, color),
+            ShapeVertex::from_xy(0.321439, 0.94693, color),
+            ShapeVertex::from_xy(0.5, 0.866025, color),
+            ShapeVertex::from_xy(0.659346, 0.75184, color),
+            ShapeVertex::from_xy(0.793353, 0.608762, color),
+            ShapeVertex::from_xy(0.896873, 0.442289, color),
+            ShapeVertex::from_xy(0.965926, 0.258819, color),
+            ShapeVertex::from_xy(0.997859, 0.065403, color),
+            ShapeVertex::from_xy(0.991445, -0.130526, color),
+            ShapeVertex::from_xy(0.94693, -0.321439, color),
+            ShapeVertex::from_xy(0.866025, -0.5, color),
+            ShapeVertex::from_xy(0.75184, -0.659346, color),
+            ShapeVertex::from_xy(0.608762, -0.793353, color),
+            ShapeVertex::from_xy(0.442289, -0.896873, color),
+            ShapeVertex::from_xy(0.258819, -0.965926, color),
+            ShapeVertex::from_xy(0.065403, -0.997859, color),
+            ShapeVertex::from_xy(-0.130526, -0.991445, color),
+            ShapeVertex::from_xy(-0.321439, -0.94693, color),
+            ShapeVertex::from_xy(-0.5, -0.866025, color),
+            ShapeVertex::from_xy(-0.656697, -0.75131, color),
+            ShapeVertex::from_xy(-0.788055, -0.608762, color),
+            ShapeVertex::from_xy(-0.892104, -0.442289, color),
+            ShapeVertex::from_xy(-0.795385, -0.449426, color),
+            ShapeVertex::from_xy(-0.671606, -0.580689, color),
+            ShapeVertex::from_xy(-0.4817, -0.634431, color),
+            ShapeVertex::from_xy(-0.4, -0.69282, color),
+            ShapeVertex::from_xy(-0.257151, -0.757544, color),
+            ShapeVertex::from_xy(-0.104421, -0.793156, color),
+            ShapeVertex::from_xy(0.052323, -0.798287, color),
+            ShapeVertex::from_xy(0.207055, -0.772741, color),
+            ShapeVertex::from_xy(0.353831, -0.717498, color),
+            ShapeVertex::from_xy(0.487009, -0.634683, color),
+            ShapeVertex::from_xy(0.601472, -0.527477, color),
+            ShapeVertex::from_xy(0.69282, -0.4, color),
+            ShapeVertex::from_xy(0.757544, -0.257151, color),
+            ShapeVertex::from_xy(0.793156, -0.104421, color),
+            ShapeVertex::from_xy(0.798287, 0.052323, color),
+            ShapeVertex::from_xy(0.772741, 0.207055, color),
+            ShapeVertex::from_xy(0.717498, 0.353831, color),
+            ShapeVertex::from_xy(0.634683, 0.487009, color),
+            ShapeVertex::from_xy(0.527477, 0.601472, color),
+            ShapeVertex::from_xy(0.4, 0.69282, color),
+            ShapeVertex::from_xy(0.257152, 0.757544, color),
+            ShapeVertex::from_xy(0.104421, 0.793156, color),
+            ShapeVertex::from_xy(-0.163584, 0.793582, color),
+            ShapeVertex::from_xy(-0.308589, 0.771626, color),
+            ShapeVertex::from_xy(-0.457404, 0.716377, color),
+            ShapeVertex::from_xy(-0.586841, 0.648433, color),
+            ShapeVertex::from_xy(-0.750937, 0.532477, color),
+            ShapeVertex::from_xy(-0.861636, 0.42303, color),
+            ShapeVertex::from_xy(-0.820416, -0.177486, color),
+            ShapeVertex::from_xy(-0.647226, -0.175467, color),
+            ShapeVertex::from_xy(0.151993, -0.418944, color),
+            ShapeVertex::from_xy(-0.405869, -0.119132, color),
+            ShapeVertex::from_xy(-0.951622, -0.287706, color),
+            ShapeVertex::from_xy(-0.912832, -0.12241, color),
+            ShapeVertex::from_xy(-0.02437, -0.360761, color),
+            ShapeVertex::from_xy(-0.69709, 0.713458, color),
+            ShapeVertex::from_xy(-0.694715, 0.576998, color),
+            ShapeVertex::from_xy(-0.838847, 0.539945, color),
+            ShapeVertex::from_xy(-0.832561, 0.44765, color),
+            ShapeVertex::from_xy(-0.554577, 0.831641, color),
+            ShapeVertex::from_xy(-0.565199, 0.666385, color),
+            ShapeVertex::from_xy(-0.382321, 0.923269, color),
+            ShapeVertex::from_xy(-0.34969, 0.758206, color),
+            ShapeVertex::from_xy(-0.000801, 0.999738, color),
+            ShapeVertex::from_xy(-0.001275, 0.800807, color),
+            ShapeVertex::from_xy(-0.025913, -0.275497, color),
+            ShapeVertex::from_xy(-0.198952, -0.191694, color),
+            ShapeVertex::from_xy(-0.180252, -0.356309, color),
+        ],
+        indices: vec![
+            11, 47, 12, 24, 34, 25, 15, 43, 16, 10, 48, 11, 28, 30, 29, 23, 35, 24, 2, 1, 57, 7,
+            74, 73, 10, 50, 49, 15, 45, 44, 23, 37, 36, 27, 31, 28, 19, 39, 20, 8, 50, 9, 5, 72,
+            71, 21, 37, 22, 13, 45, 14, 18, 40, 19, 20, 38, 21, 27, 33, 32, 4, 70, 69, 17, 41, 18,
+            13, 47, 46, 25, 33, 26, 16, 42, 17, 0, 62, 63, 31, 61, 59, 59, 30, 31, 29, 30, 58, 77,
+            75, 76, 65, 55, 4, 67, 56, 3, 71, 53, 6, 8, 74, 51, 11, 48, 47, 24, 35, 34, 15, 44, 43,
+            10, 49, 48, 28, 31, 30, 23, 36, 35, 7, 52, 74, 10, 9, 50, 15, 14, 45, 23, 22, 37, 27,
+            32, 31, 19, 40, 39, 8, 51, 50, 5, 54, 72, 21, 38, 37, 13, 46, 45, 18, 41, 40, 20, 39,
+            38, 27, 26, 33, 4, 55, 70, 17, 42, 41, 13, 12, 47, 25, 34, 33, 16, 43, 42, 31, 32, 61,
+            59, 58, 30, 77, 61, 32, 58, 63, 62, 62, 29, 58, 65, 66, 55, 67, 68, 56, 71, 72, 53, 8,
+            73, 74, 6, 52, 7, 54, 69, 70, 66, 3, 56, 68, 2, 57, 75, 64, 60, 77, 64, 75, 77, 76, 61,
+            6, 53, 52, 54, 5, 69, 66, 65, 3, 68, 67, 2,
+        ],
+    }
+}