diff --git a/bin/app/data/circle.obj b/bin/app/data/circle.obj
new file mode 100644
index 000000000..9a281d3c1
--- /dev/null
+++ b/bin/app/data/circle.obj
@@ -0,0 +1,69 @@
+# Blender 4.0.2
+# www.blender.org
+mtllib circle.mtl
+o Circle
+v 0.000000 0.000000 -1.000000
+v -0.195090 0.000000 -0.980785
+v -0.382683 0.000000 -0.923880
+v -0.555570 0.000000 -0.831470
+v -0.707107 0.000000 -0.707107
+v -0.831470 0.000000 -0.555570
+v -0.923880 0.000000 -0.382683
+v -0.980785 0.000000 -0.195090
+v -1.000000 0.000000 0.000000
+v -0.980785 0.000000 0.195090
+v -0.923880 0.000000 0.382683
+v -0.831470 0.000000 0.555570
+v -0.707107 0.000000 0.707107
+v -0.555570 0.000000 0.831470
+v -0.382683 0.000000 0.923880
+v -0.195090 0.000000 0.980785
+v 0.000000 0.000000 1.000000
+v 0.195090 0.000000 0.980785
+v 0.382683 0.000000 0.923880
+v 0.555570 0.000000 0.831470
+v 0.707107 0.000000 0.707107
+v 0.831470 0.000000 0.555570
+v 0.923880 0.000000 0.382683
+v 0.980785 0.000000 0.195090
+v 1.000000 0.000000 0.000000
+v 0.980785 0.000000 -0.195090
+v 0.923880 0.000000 -0.382683
+v 0.831470 0.000000 -0.555570
+v 0.707107 0.000000 -0.707107
+v 0.555570 0.000000 -0.831470
+v 0.382683 0.000000 -0.923880
+v 0.195090 0.000000 -0.980785
+vn -0.0000 1.0000 -0.0000
+vt 0.000000 0.000000
+s 0
+f 17/1/1 25/1/1 1/1/1
+f 1/1/1 2/1/1 5/1/1
+f 2/1/1 3/1/1 5/1/1
+f 3/1/1 4/1/1 5/1/1
+f 5/1/1 6/1/1 7/1/1
+f 7/1/1 8/1/1 5/1/1
+f 8/1/1 9/1/1 5/1/1
+f 9/1/1 10/1/1 13/1/1
+f 10/1/1 11/1/1 13/1/1
+f 11/1/1 12/1/1 13/1/1
+f 13/1/1 14/1/1 15/1/1
+f 15/1/1 16/1/1 13/1/1
+f 16/1/1 17/1/1 13/1/1
+f 17/1/1 18/1/1 21/1/1
+f 18/1/1 19/1/1 21/1/1
+f 19/1/1 20/1/1 21/1/1
+f 21/1/1 22/1/1 23/1/1
+f 23/1/1 24/1/1 21/1/1
+f 24/1/1 25/1/1 21/1/1
+f 25/1/1 26/1/1 29/1/1
+f 26/1/1 27/1/1 29/1/1
+f 27/1/1 28/1/1 29/1/1
+f 29/1/1 30/1/1 31/1/1
+f 31/1/1 32/1/1 29/1/1
+f 32/1/1 1/1/1 29/1/1
+f 1/1/1 5/1/1 9/1/1
+f 9/1/1 13/1/1 17/1/1
+f 17/1/1 21/1/1 25/1/1
+f 25/1/1 29/1/1 1/1/1
+f 1/1/1 9/1/1 17/1/1
diff --git a/bin/app/data/logo.obj b/bin/app/data/logo.obj
new file mode 100644
index 000000000..4d43522bc
--- /dev/null
+++ b/bin/app/data/logo.obj
@@ -0,0 +1,448 @@
+# Blender 4.0.2
+# www.blender.org
+mtllib logo.mtl
+o Curve.009
+v 0.000154 0.000000 -0.009673
+v -0.000705 0.000000 -0.009615
+v -0.001529 0.000000 -0.009448
+v -0.002310 0.000000 -0.009177
+v -0.003040 0.000000 -0.008812
+v -0.003712 0.000000 -0.008358
+v -0.004319 0.000000 -0.007825
+v -0.004853 0.000000 -0.007218
+v -0.005306 0.000000 -0.006546
+v -0.005672 0.000000 -0.005816
+v -0.005942 0.000000 -0.005035
+v -0.006110 0.000000 -0.004212
+v -0.006168 0.000000 -0.003352
+v -0.006110 0.000000 -0.002493
+v -0.005942 0.000000 -0.001669
+v -0.005672 0.000000 -0.000889
+v -0.005306 0.000000 -0.000159
+v -0.004853 0.000000 0.000513
+v -0.004319 0.000000 0.001120
+v -0.003712 0.000000 0.001654
+v -0.003040 0.000000 0.002107
+v -0.002310 0.000000 0.002473
+v -0.001529 0.000000 0.002743
+v -0.000705 0.000000 0.002911
+v 0.000154 0.000000 0.002968
+v 0.001014 0.000000 0.002911
+v 0.001838 0.000000 0.002743
+v 0.002618 0.000000 0.002473
+v 0.003349 0.000000 0.002107
+v 0.004021 0.000000 0.001654
+v 0.004627 0.000000 0.001120
+v 0.005161 0.000000 0.000513
+v 0.005615 0.000000 -0.000159
+v 0.005980 0.000000 -0.000889
+v 0.006251 0.000000 -0.001669
+v 0.006419 0.000000 -0.002493
+v 0.006476 0.000000 -0.003352
+v 0.006419 0.000000 -0.004212
+v 0.006251 0.000000 -0.005035
+v 0.005980 0.000000 -0.005816
+v 0.005615 0.000000 -0.006546
+v 0.005161 0.000000 -0.007218
+v 0.004627 0.000000 -0.007825
+v 0.004021 0.000000 -0.008358
+v 0.003349 0.000000 -0.008812
+v 0.002618 0.000000 -0.009177
+v 0.001838 0.000000 -0.009448
+v 0.001014 0.000000 -0.009615
+v 0.000154 0.000000 -0.000474
+v -0.000234 0.000000 -0.000500
+v -0.000606 0.000000 -0.000576
+v -0.000958 0.000000 -0.000697
+v -0.001287 0.000000 -0.000862
+v -0.001590 0.000000 -0.001066
+v -0.001864 0.000000 -0.001307
+v -0.002104 0.000000 -0.001580
+v -0.002309 0.000000 -0.001883
+v -0.002473 0.000000 -0.002212
+v -0.002595 0.000000 -0.002564
+v -0.002670 0.000000 -0.002936
+v -0.002696 0.000000 -0.003324
+v -0.002670 0.000000 -0.003712
+v -0.002595 0.000000 -0.004084
+v -0.002473 0.000000 -0.004436
+v -0.002309 0.000000 -0.004765
+v -0.002104 0.000000 -0.005068
+v -0.001864 0.000000 -0.005342
+v -0.001590 0.000000 -0.005582
+v -0.001287 0.000000 -0.005786
+v -0.000958 0.000000 -0.005951
+v -0.000606 0.000000 -0.006073
+v -0.000234 0.000000 -0.006148
+v 0.000154 0.000000 -0.006174
+v 0.000542 0.000000 -0.006148
+v 0.000914 0.000000 -0.006073
+v 0.001266 0.000000 -0.005951
+v 0.001596 0.000000 -0.005786
+v 0.001899 0.000000 -0.005582
+v 0.002172 0.000000 -0.005342
+v 0.002413 0.000000 -0.005068
+v 0.002617 0.000000 -0.004765
+v 0.002782 0.000000 -0.004436
+v 0.002903 0.000000 -0.004084
+v 0.002979 0.000000 -0.003712
+v 0.003005 0.000000 -0.003324
+v 0.002979 0.000000 -0.002936
+v 0.002903 0.000000 -0.002564
+v 0.002782 0.000000 -0.002212
+v 0.002617 0.000000 -0.001883
+v 0.002413 0.000000 -0.001580
+v 0.002172 0.000000 -0.001307
+v 0.001899 0.000000 -0.001066
+v 0.001596 0.000000 -0.000862
+v 0.001266 0.000000 -0.000697
+v 0.000914 0.000000 -0.000576
+v 0.000542 0.000000 -0.000500
+v -0.029000 0.000000 -0.020508
+v 0.000154 0.000000 0.030000
+v 0.029308 0.000000 -0.020508
+v 0.000154 0.000000 0.005677
+v -0.001246 0.000000 0.005586
+v -0.002605 0.000000 0.005322
+v -0.003918 0.000000 0.004901
+v -0.005180 0.000000 0.004339
+v -0.006386 0.000000 0.003652
+v -0.007530 0.000000 0.002855
+v -0.008606 0.000000 0.001964
+v -0.009611 0.000000 0.000995
+v -0.010538 0.000000 -0.000037
+v -0.011382 0.000000 -0.001116
+v -0.012138 0.000000 -0.002226
+v -0.012800 0.000000 -0.003352
+v -0.012138 0.000000 -0.004478
+v -0.011382 0.000000 -0.005589
+v -0.010538 0.000000 -0.006668
+v -0.009611 0.000000 -0.007700
+v -0.008606 0.000000 -0.008669
+v -0.007530 0.000000 -0.009560
+v -0.006386 0.000000 -0.010357
+v -0.005180 0.000000 -0.011044
+v -0.003918 0.000000 -0.011606
+v -0.002605 0.000000 -0.012026
+v -0.001246 0.000000 -0.012290
+v 0.000154 0.000000 -0.012382
+v 0.001554 0.000000 -0.012290
+v 0.002913 0.000000 -0.012026
+v 0.004226 0.000000 -0.011606
+v 0.005488 0.000000 -0.011044
+v 0.006694 0.000000 -0.010357
+v 0.007838 0.000000 -0.009560
+v 0.008915 0.000000 -0.008669
+v 0.009919 0.000000 -0.007700
+v 0.010846 0.000000 -0.006668
+v 0.011690 0.000000 -0.005589
+v 0.012446 0.000000 -0.004478
+v 0.013108 0.000000 -0.003352
+v 0.012447 0.000000 -0.002226
+v 0.011692 0.000000 -0.001116
+v 0.010850 0.000000 -0.000037
+v 0.009926 0.000000 0.000995
+v 0.008923 0.000000 0.001964
+v 0.007848 0.000000 0.002855
+v 0.006706 0.000000 0.003652
+v 0.005501 0.000000 0.004339
+v 0.004238 0.000000 0.004901
+v 0.002923 0.000000 0.005322
+v 0.001560 0.000000 0.005586
+vn -0.0000 1.0000 -0.0000
+vt 0.664384 0.000000
+vt 0.760274 0.000000
+vt 0.657534 0.000000
+vt 0.767123 0.000000
+vt 0.773973 0.000000
+vt 0.780822 0.000000
+vt 0.787671 0.000000
+vt 0.794521 0.000000
+vt 0.801370 0.000000
+vt 0.808219 0.000000
+vt 0.815068 0.000000
+vt 0.821918 0.000000
+vt 0.828767 0.000000
+vt 0.671233 0.000000
+vt 0.835616 0.000000
+vt 0.842466 0.000000
+vt 0.849315 0.000000
+vt 0.856164 0.000000
+vt 0.863014 0.000000
+vt 0.869863 0.000000
+vt 0.876712 0.000000
+vt 0.883562 0.000000
+vt 0.890411 0.000000
+vt 0.897260 0.000000
+vt 0.904110 0.000000
+vt 0.910959 0.000000
+vt 0.917808 0.000000
+vt 0.924658 0.000000
+vt 0.006849 0.000000
+vt 0.321918 0.000000
+vt 0.000000 0.000000
+vt 0.013699 0.000000
+vt 0.315068 0.000000
+vt 0.020548 0.000000
+vt 0.308219 0.000000
+vt 0.027397 0.000000
+vt 0.301370 0.000000
+vt 0.034247 0.000000
+vt 0.294521 0.000000
+vt 0.041096 0.000000
+vt 0.287671 0.000000
+vt 0.047945 0.000000
+vt 0.280822 0.000000
+vt 0.054795 0.000000
+vt 0.273973 0.000000
+vt 0.061644 0.000000
+vt 0.493151 0.000000
+vt 0.267123 0.000000
+vt 0.486301 0.000000
+vt 0.500000 0.000000
+vt 0.479452 0.000000
+vt 0.506849 0.000000
+vt 0.472603 0.000000
+vt 0.513699 0.000000
+vt 0.465753 0.000000
+vt 0.520548 0.000000
+vt 0.068493 0.000000
+vt 0.260274 0.000000
+vt 0.458904 0.000000
+vt 0.527397 0.000000
+vt 0.452055 0.000000
+vt 0.534247 0.000000
+vt 0.445205 0.000000
+vt 0.541096 0.000000
+vt 0.438356 0.000000
+vt 0.547945 0.000000
+vt 0.075342 0.000000
+vt 0.253425 0.000000
+vt 0.431507 0.000000
+vt 0.554795 0.000000
+vt 0.424658 0.000000
+vt 0.561644 0.000000
+vt 0.082192 0.000000
+vt 0.246575 0.000000
+vt 0.417808 0.000000
+vt 0.568493 0.000000
+vt 0.410959 0.000000
+vt 0.575342 0.000000
+vt 0.753425 0.000000
+vt 0.089041 0.000000
+vt 0.239726 0.000000
+vt 0.931507 0.000000
+vt 0.404110 0.000000
+vt 0.582192 0.000000
+vt 0.397260 0.000000
+vt 0.589041 0.000000
+vt 0.390411 0.000000
+vt 0.595890 0.000000
+vt 0.095890 0.000000
+vt 0.232877 0.000000
+vt 0.938356 0.000000
+vt 0.746575 0.000000
+vt 0.383562 0.000000
+vt 0.602740 0.000000
+vt 0.376712 0.000000
+vt 0.609589 0.000000
+vt 0.102740 0.000000
+vt 0.226027 0.000000
+vt 0.369863 0.000000
+vt 0.616438 0.000000
+vt 0.363014 0.000000
+vt 0.623288 0.000000
+vt 0.945205 0.000000
+vt 0.739726 0.000000
+vt 0.356164 0.000000
+vt 0.630137 0.000000
+vt 0.219178 0.000000
+vt 0.109589 0.000000
+vt 0.349315 0.000000
+vt 0.636986 0.000000
+vt 0.342466 0.000000
+vt 0.643836 0.000000
+vt 0.335616 0.000000
+vt 0.650685 0.000000
+vt 0.328767 0.000000
+vt 0.212329 0.000000
+vt 0.116438 0.000000
+vt 0.952055 0.000000
+vt 0.732877 0.000000
+vt 0.205479 0.000000
+vt 0.123288 0.000000
+vt 0.958904 0.000000
+vt 0.726027 0.000000
+vt 0.198630 0.000000
+vt 0.130137 0.000000
+vt 0.191781 0.000000
+vt 0.136986 0.000000
+vt 0.965753 0.000000
+vt 0.719178 0.000000
+vt 0.184932 0.000000
+vt 0.143836 0.000000
+vt 0.178082 0.000000
+vt 0.150685 0.000000
+vt 0.171233 0.000000
+vt 0.157534 0.000000
+vt 0.972603 0.000000
+vt 0.712329 0.000000
+vt 0.164384 0.000000
+vt 0.979452 0.000000
+vt 0.705479 0.000000
+vt 0.986301 0.000000
+vt 0.698630 0.000000
+vt 0.993151 0.000000
+vt 0.691781 0.000000
+vt 1.000000 0.000000
+vt 0.684932 0.000000
+vt 0.678082 0.000000
+s 0
+usemtl SVGMat
+f 98/1/1 112/2/1 97/3/1
+f 112/2/1 113/4/1 97/3/1
+f 113/4/1 114/5/1 97/3/1
+f 114/5/1 115/6/1 97/3/1
+f 115/6/1 116/7/1 97/3/1
+f 116/7/1 117/8/1 97/3/1
+f 117/8/1 118/9/1 97/3/1
+f 118/9/1 119/10/1 97/3/1
+f 119/10/1 120/11/1 97/3/1
+f 120/11/1 121/12/1 97/3/1
+f 121/12/1 122/13/1 97/3/1
+f 122/13/1 99/14/1 97/3/1
+f 122/13/1 123/15/1 99/14/1
+f 123/15/1 124/16/1 99/14/1
+f 124/16/1 125/17/1 99/14/1
+f 125/17/1 126/18/1 99/14/1
+f 126/18/1 127/19/1 99/14/1
+f 127/19/1 128/20/1 99/14/1
+f 128/20/1 129/21/1 99/14/1
+f 129/21/1 130/22/1 99/14/1
+f 130/22/1 131/23/1 99/14/1
+f 131/23/1 132/24/1 99/14/1
+f 132/24/1 133/25/1 99/14/1
+f 133/25/1 134/26/1 99/14/1
+f 134/26/1 135/27/1 99/14/1
+f 135/27/1 136/28/1 99/14/1
+f 136/28/1 98/1/1 99/14/1
+f 2/29/1 48/30/1 1/31/1
+f 3/32/1 48/30/1 2/29/1
+f 3/32/1 47/33/1 48/30/1
+f 4/34/1 47/33/1 3/32/1
+f 4/34/1 46/35/1 47/33/1
+f 5/36/1 46/35/1 4/34/1
+f 5/36/1 45/37/1 46/35/1
+f 6/38/1 45/37/1 5/36/1
+f 6/38/1 44/39/1 45/37/1
+f 7/40/1 44/39/1 6/38/1
+f 7/40/1 43/41/1 44/39/1
+f 8/42/1 43/41/1 7/40/1
+f 8/42/1 42/43/1 43/41/1
+f 9/44/1 42/43/1 8/42/1
+f 9/44/1 41/45/1 42/43/1
+f 10/46/1 41/45/1 9/44/1
+f 10/46/1 73/47/1 41/45/1
+f 73/47/1 40/48/1 41/45/1
+f 10/46/1 72/49/1 73/47/1
+f 74/50/1 40/48/1 73/47/1
+f 10/46/1 71/51/1 72/49/1
+f 75/52/1 40/48/1 74/50/1
+f 10/46/1 70/53/1 71/51/1
+f 76/54/1 40/48/1 75/52/1
+f 10/46/1 69/55/1 70/53/1
+f 77/56/1 40/48/1 76/54/1
+f 11/57/1 69/55/1 10/46/1
+f 77/56/1 39/58/1 40/48/1
+f 11/57/1 68/59/1 69/55/1
+f 78/60/1 39/58/1 77/56/1
+f 11/57/1 67/61/1 68/59/1
+f 79/62/1 39/58/1 78/60/1
+f 11/57/1 66/63/1 67/61/1
+f 80/64/1 39/58/1 79/62/1
+f 11/57/1 65/65/1 66/63/1
+f 81/66/1 39/58/1 80/64/1
+f 12/67/1 65/65/1 11/57/1
+f 81/66/1 38/68/1 39/58/1
+f 12/67/1 64/69/1 65/65/1
+f 82/70/1 38/68/1 81/66/1
+f 12/67/1 63/71/1 64/69/1
+f 83/72/1 38/68/1 82/70/1
+f 13/73/1 63/71/1 12/67/1
+f 83/72/1 37/74/1 38/68/1
+f 13/73/1 62/75/1 63/71/1
+f 84/76/1 37/74/1 83/72/1
+f 13/73/1 61/77/1 62/75/1
+f 85/78/1 37/74/1 84/76/1
+f 98/1/1 111/79/1 112/2/1
+f 14/80/1 61/77/1 13/73/1
+f 85/78/1 36/81/1 37/74/1
+f 137/82/1 98/1/1 136/28/1
+f 14/80/1 60/83/1 61/77/1
+f 86/84/1 36/81/1 85/78/1
+f 14/80/1 59/85/1 60/83/1
+f 87/86/1 36/81/1 86/84/1
+f 14/80/1 58/87/1 59/85/1
+f 88/88/1 36/81/1 87/86/1
+f 15/89/1 58/87/1 14/80/1
+f 88/88/1 35/90/1 36/81/1
+f 138/91/1 98/1/1 137/82/1
+f 98/1/1 110/92/1 111/79/1
+f 15/89/1 57/93/1 58/87/1
+f 89/94/1 35/90/1 88/88/1
+f 15/89/1 56/95/1 57/93/1
+f 90/96/1 35/90/1 89/94/1
+f 16/97/1 56/95/1 15/89/1
+f 90/96/1 34/98/1 35/90/1
+f 16/97/1 55/99/1 56/95/1
+f 91/100/1 34/98/1 90/96/1
+f 16/97/1 54/101/1 55/99/1
+f 92/102/1 34/98/1 91/100/1
+f 139/103/1 98/1/1 138/91/1
+f 98/1/1 109/104/1 110/92/1
+f 16/97/1 53/105/1 54/101/1
+f 93/106/1 34/98/1 92/102/1
+f 93/106/1 33/107/1 34/98/1
+f 17/108/1 53/105/1 16/97/1
+f 17/108/1 52/109/1 53/105/1
+f 94/110/1 33/107/1 93/106/1
+f 17/108/1 51/111/1 52/109/1
+f 95/112/1 33/107/1 94/110/1
+f 17/108/1 50/113/1 51/111/1
+f 96/114/1 33/107/1 95/112/1
+f 17/108/1 49/115/1 50/113/1
+f 49/115/1 33/107/1 96/114/1
+f 17/108/1 33/107/1 49/115/1
+f 17/108/1 32/116/1 33/107/1
+f 18/117/1 32/116/1 17/108/1
+f 140/118/1 98/1/1 139/103/1
+f 98/1/1 108/119/1 109/104/1
+f 18/117/1 31/120/1 32/116/1
+f 19/121/1 31/120/1 18/117/1
+f 141/122/1 98/1/1 140/118/1
+f 98/1/1 107/123/1 108/119/1
+f 19/121/1 30/124/1 31/120/1
+f 20/125/1 30/124/1 19/121/1
+f 20/125/1 29/126/1 30/124/1
+f 21/127/1 29/126/1 20/125/1
+f 142/128/1 98/1/1 141/122/1
+f 98/1/1 106/129/1 107/123/1
+f 21/127/1 28/130/1 29/126/1
+f 22/131/1 28/130/1 21/127/1
+f 22/131/1 27/132/1 28/130/1
+f 23/133/1 27/132/1 22/131/1
+f 23/133/1 26/134/1 27/132/1
+f 24/135/1 26/134/1 23/133/1
+f 143/136/1 98/1/1 142/128/1
+f 98/1/1 105/137/1 106/129/1
+f 24/135/1 25/138/1 26/134/1
+f 144/139/1 98/1/1 143/136/1
+f 98/1/1 104/140/1 105/137/1
+f 145/141/1 98/1/1 144/139/1
+f 98/1/1 103/142/1 104/140/1
+f 146/143/1 98/1/1 145/141/1
+f 98/1/1 102/144/1 103/142/1
+f 147/145/1 98/1/1 146/143/1
+f 98/1/1 101/146/1 102/144/1
+f 100/147/1 98/1/1 147/145/1
+f 98/1/1 100/147/1 101/146/1
diff --git a/bin/app/data/settings_right_border.obj b/bin/app/data/settings_right_border.obj
new file mode 100644
index 000000000..e54e53085
--- /dev/null
+++ b/bin/app/data/settings_right_border.obj
@@ -0,0 +1,27 @@
+# Blender 4.0.2
+# www.blender.org
+mtllib settings_right_border.mtl
+o Plane.004
+v -0.400000 0.000000 1.000000
+v 0.500000 0.000000 0.000000
+v -0.400000 0.000000 -1.000000
+v -0.500000 0.000000 1.000000
+v -0.500000 0.000000 0.000000
+v -0.500000 0.000000 -1.000000
+v 0.100000 0.000000 1.000000
+v 1.000000 0.000000 0.000000
+v 0.100000 0.000000 -1.000000
+v -0.100000 0.000000 1.000000
+v 0.800000 0.000000 0.000000
+v -0.100000 0.000000 -1.000000
+vn -0.0000 1.0000 -0.0000
+vt 0.000000 0.000000
+s 0
+f 3/1/1 5/1/1 2/1/1
+f 1/1/1 5/1/1 4/1/1
+f 3/1/1 6/1/1 5/1/1
+f 1/1/1 2/1/1 5/1/1
+f 9/1/1 11/1/1 8/1/1
+f 7/1/1 11/1/1 10/1/1
+f 9/1/1 12/1/1 11/1/1
+f 7/1/1 8/1/1 11/1/1
diff --git a/bin/app/src/app/mod.rs b/bin/app/src/app/mod.rs
index 0678a8cec..15f0a424b 100644
--- a/bin/app/src/app/mod.rs
+++ b/bin/app/src/app/mod.rs
@@ -169,8 +169,6 @@ impl App {
}
};
- let atom = &mut PropertyAtomicGuard::new();
-
let mut window = SceneNode3::new("window", SceneNodeType3::Window);
let mut prop = Property::new("screen_size", PropertyType::Float32, PropertySubType::Pixel);
@@ -180,13 +178,26 @@ impl App {
let setting_root = Arc::new(SceneNode3::new("setting", SceneNodeType3::SettingRoot));
let settings_tree = db.open_tree("settings").unwrap();
- let settings = PluginSettings {
+ let settings = Arc::new(PluginSettings {
setting_root: setting_root.clone(),
sled_tree: settings_tree,
- };
+ });
settings.add_setting("scale", PropertyValue::Float32(1.));
settings.load_settings();
+
+ // Save app settings in sled when they change
+ for setting_node in settings.setting_root.get_children().iter() {
+ let setting_sub = setting_node.get_property("value").unwrap().subscribe_modify();
+ let settings2 = settings.clone();
+ let setting_task = self.ex.spawn(async move {
+ while let Ok(_) = setting_sub.receive().await {
+ settings2.save_settings();
+ }
+ });
+ self.tasks.lock().unwrap().push(setting_task);
+ }
+
let window = window.setup(|me| Window::new(me, self.render_api.clone(), setting_root.clone())).await;
self.sg_root.clone().link(window.clone());
diff --git a/bin/app/src/app/schema/settings.rs b/bin/app/src/app/schema/settings.rs
index 233cc6fc0..bcdc15c4e 100644
--- a/bin/app/src/app/schema/settings.rs
+++ b/bin/app/src/app/schema/settings.rs
@@ -16,6 +16,7 @@
* along with this program. If not, see .
*/
+use darkfi::net::settings;
use sled_overlay::sled;
@@ -53,11 +54,17 @@ mod android_ui_consts {
pub const SETTING_TITLE_X: f32 = 150.;
pub const SETTING_TITLE_FONTSIZE: f32 = 40.;
pub const SETTING_TITLE_BASELINE: f32 = 82.;
- pub const BORDER_RIGHT_SCALE: f32 = 15.;
+ pub const SEARCH_PADDING_X: f32 = 120.;
+ pub const BORDER_RIGHT_SCALE: f32 = 5.;
+ pub const CURSOR_ASCENT: f32 = 50.;
+ pub const CURSOR_DESCENT: f32 = 20.;
+ pub const SELECT_ASCENT: f32 = 50.;
+ pub const SELECT_DESCENT: f32 = 20.;
pub const BACKARROW_SCALE: f32 = 30.;
pub const BACKARROW_X: f32 = 50.;
pub const BACKARROW_Y: f32 = 70.;
+ pub const BACKARROW_BG_W: f32 = 120.;
}
#[cfg(target_os = "android")]
@@ -84,11 +91,17 @@ mod ui_consts {
pub const SETTING_TITLE_X: f32 = 100.;
pub const SETTING_TITLE_FONTSIZE: f32 = 20.;
pub const SETTING_TITLE_BASELINE: f32 = 37.;
- pub const BORDER_RIGHT_SCALE: f32 = 30.;
+ pub const SEARCH_PADDING_X: f32 = 80.;
+ pub const BORDER_RIGHT_SCALE: f32 = 10.;
+ pub const CURSOR_ASCENT: f32 = 24.;
+ pub const CURSOR_DESCENT: f32 = 8.;
+ pub const SELECT_ASCENT: f32 = 30.;
+ pub const SELECT_DESCENT: f32 = 10.;
pub const BACKARROW_SCALE: f32 = 15.;
pub const BACKARROW_X: f32 = 38.;
pub const BACKARROW_Y: f32 = 26.;
+ pub const BACKARROW_BG_W: f32 = 80.;
}
use ui_consts::*;
@@ -106,9 +119,9 @@ impl Setting {
PropertyValue::Uint32(i) => i.to_string(),
PropertyValue::Bool(b) => {
if *b {
- "true".to_string()
+ "TRUE".to_string()
} else {
- "false".to_string()
+ "FALSE".to_string()
}
}
PropertyValue::Float32(fl) => fl.to_string(),
@@ -123,7 +136,8 @@ impl Setting {
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("X_RATIO", 1./3.);
+ cc.add_const_f32("SEARCH_PADDING_X", SEARCH_PADDING_X);
+ cc.add_const_f32("X_RATIO", 1./2.);
let window_scale = PropertyFloat32::wrap(&app.sg_root.clone().lookup_node("/setting/scale").unwrap(), Role::Internal, "value", 0).unwrap();
let atom = &mut PropertyAtomicGuard::new();
@@ -142,6 +156,46 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
let mut setting_y = 0.;
+ // Create the toolbar bg
+ let node = create_vector_art("toolbar_bg");
+ let prop = node.get_property("rect").unwrap();
+ prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
+ prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
+ prop.clone().set_expr(atom, Role::App, 2, expr::load_var("w")).unwrap();
+ prop.clone().set_f32(atom, Role::App, 3, SETTING_LABEL_LINESPACE).unwrap();
+ node.set_property_u32(atom, Role::App, "z_index", 2).unwrap();
+
+ let (bg_color, sep_color) = match COLOR_SCHEME {
+ ColorScheme::DarkMode => ([0., 0.11, 0.11, 1.], [0.41, 0.6, 0.65, 1.]),
+ ColorScheme::PaperLight => ([1., 1., 1., 1.], [0., 0.6, 0.65, 1.]),
+ };
+ let mut shape = VectorShape::new();
+ shape.add_filled_box(
+ expr::const_f32(0.),
+ expr::const_f32(0.),
+ expr::const_f32(BACKARROW_BG_W),
+ expr::load_var("h"),
+ bg_color,
+ );
+ shape.add_filled_box(
+ expr::const_f32(BACKARROW_BG_W),
+ expr::const_f32(0.),
+ expr::const_f32(BACKARROW_BG_W + 1.),
+ expr::load_var("h"),
+ sep_color,
+ );
+ shape.add_filled_box(
+ expr::const_f32(0.),
+ expr::load_var("h"),
+ expr::load_var("w"),
+ cc.compile("h + 1").unwrap(),
+ sep_color,
+ );
+
+ let node =
+ node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
+ layer_node.clone().link(node);
+
// Create the back button
let node = create_vector_art("back_btn_bg");
let prop = node.get_property("rect").unwrap();
@@ -162,8 +216,8 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
let prop = node.get_property("rect").unwrap();
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, 100.).unwrap();
- prop.clone().set_f32(atom, Role::App, 3, 100.).unwrap();
+ prop.clone().set_f32(atom, Role::App, 2, BACKARROW_BG_W).unwrap();
+ prop.clone().set_f32(atom, Role::App, 3, SETTING_LABEL_LINESPACE).unwrap();
let sg_root = app.sg_root.clone();
let goback = move || {
@@ -240,7 +294,333 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
.await;
layer_node.clone().link(node);
- setting_y += 20.;
+
+ // Search Bar Background
+ let node = create_vector_art("emoji_picker_bg");
+ let prop = node.get_property("rect").unwrap();
+ prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
+ let code = cc.compile("100").unwrap();
+ prop.clone().set_expr(atom, Role::App, 1, code).unwrap();
+ prop.clone().set_expr(atom, Role::App, 2, expr::load_var("w")).unwrap();
+ prop.clone().set_expr(atom, Role::App, 3, expr::load_var("50")).unwrap();
+ //prop.add_depend(&emoji_dynamic_h_prop, 0, "dynamic_h");
+ node.set_property_u32(atom, Role::App, "z_index", 4).unwrap();
+
+ let mut shape = VectorShape::new();
+
+ // Top line
+ shape.add_filled_box(
+ expr::const_f32(0.),
+ expr::const_f32(80.),
+ expr::load_var("w"),
+ expr::const_f32(1.),
+ [0.41, 0.6, 0.65, 1.],
+ );
+
+ let node =
+ node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
+ layer_node.clone().link(node);
+
+ // Search Bar Input
+ let editbox_node = create_editbox("search_input");
+ editbox_node.set_property_bool(atom, Role::App, "is_active", true).unwrap();
+ editbox_node.set_property_bool(atom, Role::App, "is_focused", true).unwrap();
+ let prop = editbox_node.get_property("rect").unwrap();
+ prop.clone().set_f32(atom, Role::App, 0, SEARCH_PADDING_X).unwrap();
+ prop.clone().set_expr(atom, Role::App, 1, cc.compile("60 + 20").unwrap()).unwrap();
+ prop.clone().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();
+ }
+ 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();
+ }
+ 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();
+ editbox_node.set_property_u32(atom, Role::App, "z_index", 2).unwrap();
+ editbox_node.set_property_bool(atom, Role::App, "is_active", true).unwrap();
+ editbox_node.set_property_bool(atom, Role::App, "is_focused", true).unwrap();
+ editbox_node.set_property_f32(atom, Role::App, "font_size", 16.).unwrap();
+ editbox_node.set_property_f32(atom, Role::App, "baseline", 16.).unwrap();
+
+ // Search icon
+ let node = create_vector_art("search_icon");
+ let prop = node.get_property("rect").unwrap();
+ prop.clone().set_f32(atom, Role::App, 0, BACKARROW_X).unwrap();
+ prop.clone().set_f32(atom, Role::App, 1, SETTING_LABEL_LINESPACE + 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_u32(atom, Role::App, "z_index", 3).unwrap();
+
+ let shape = shape::create_logo([1., 1., 1., 1.]).scaled(500.);
+ let node =
+ node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
+ layer_node.clone().link(node);
+
+ // Search placeholder
+ let node = create_text("search_label");
+ let prop = node.get_property("rect").unwrap();
+ prop.clone().set_f32(atom, Role::App, 0, SEARCH_PADDING_X).unwrap();
+ prop.clone().set_expr(atom, Role::App, 1, cc.compile("60 + 20").unwrap()).unwrap();
+ prop.clone().set_f32(atom, Role::App, 2, 1000.).unwrap();
+ prop.clone().set_f32(atom, Role::App, 3, 200.).unwrap();
+ node.set_property_u32(atom, Role::App, "z_index", 1).unwrap();
+ 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_u32(atom, Role::App, "z_index", 1).unwrap();
+
+ let node = node
+ .setup(|me| {
+ Text::new(
+ me,
+ window_scale.clone(),
+ app.render_api.clone(),
+ app.text_shaper.clone(),
+ app.ex.clone(),
+ )
+ })
+ .await;
+ layer_node.clone().link(node);
+
+ // Search settings counter
+ let node = create_text("search_count");
+ let prop = node.get_property("rect").unwrap();
+ prop.clone().set_expr(atom, Role::App, 0, cc.compile("w - 50").unwrap()).unwrap();
+ prop.clone().set_expr(atom, Role::App, 1, cc.compile("60 + 20").unwrap()).unwrap();
+ prop.clone().set_f32(atom, Role::App, 2, 1000.).unwrap();
+ prop.clone().set_f32(atom, Role::App, 3, 200.).unwrap();
+ node.set_property_u32(atom, Role::App, "z_index", 1).unwrap();
+ 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_u32(atom, Role::App, "z_index", 1).unwrap();
+
+ let node = node
+ .setup(|me| {
+ Text::new(
+ me,
+ window_scale.clone(),
+ app.render_api.clone(),
+ app.text_shaper.clone(),
+ app.ex.clone(),
+ )
+ })
+ .await;
+ 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();
+
+ let path = "/window/settings_layer/search_input";
+ let node = sg_root3.clone().lookup_node(path.to_string()).unwrap();
+ let search_string = node.get_property_str("text").unwrap();
+
+ let path = "/window/settings_layer/search_label";
+ let search_label_node = sg_root3.clone().lookup_node(path.to_string()).unwrap();
+
+ if search_string.len() > 0 {
+ let _ = search_label_node.set_property_f32(atom, Role::App, "font_size", 0.);
+ } else {
+ let _ = search_label_node.set_property_f32(atom, Role::App, "font_size", 16.);
+ }
+
+
+ let path = "/window/settings_layer/settings";
+ let node = sg_root3.clone().lookup_node(path.to_string()).unwrap();
+ let setting_nodes = node.get_children();
+ let mut found_nodes = Vec::new();
+
+ // Iterate through the nodes
+ for node in setting_nodes.iter() {
+ // Hide all nodes initially, no matter what
+ let _ = node.set_property_bool(atom, Role::App, "is_visible", false);
+
+ // Check if the node matches the search string
+ if node.name.contains(&search_string.to_string()) {
+ found_nodes.push(node); // Store matching nodes
+ if let Err(e) = node.set_property_bool(atom, Role::App, "is_visible", true) {
+ debug!("Failed to set property 'is_visible' on node: {:?}", e);
+ }
+ }
+ }
+
+ // Set the `rect` property for each found node
+ for (i, node) in found_nodes.iter().enumerate() {
+ let prop = node.get_property("rect").unwrap();
+ let y = i as f32 * 60. + 60. + 60.;
+ prop.set_f32(atom, Role::App, 1, y).unwrap();
+ }
+
+ // Update the counter
+ let counter_text = found_nodes.len().to_string();
+ let path = "/window/settings_layer/search_count";
+ let node = sg_root3.clone().lookup_node(path.to_string()).unwrap();
+ let _ = node.set_property_str(atom, Role::App, "text", &counter_text).unwrap();
+ };
+
+ // 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 listen_search_text = app.ex.spawn(async move {
+ while let Ok(_) = search_text_sub.receive().await {
+ search2();
+ }
+ });
+ app.tasks.lock().unwrap().push(listen_search_text);
+
+ let node = editbox_node
+ .setup(|me| {
+ EditBox::new(
+ me,
+ window_scale.clone(),
+ app.render_api.clone(),
+ app.text_shaper.clone(),
+ app.ex.clone(),
+ )
+ })
+ .await;
+ layer_node.clone().link(node);
+
+ // Search background
+ let node = create_vector_art("search_bg");
+ let prop = node.get_property("rect").unwrap();
+ prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
+ prop.clone().set_f32(atom, Role::App, 1, 60.).unwrap();
+ prop.clone().set_expr(atom, Role::App, 2, cc.compile("w * 100").unwrap()).unwrap();
+ prop.clone().set_f32(atom, Role::App, 3, SETTING_LABEL_LINESPACE).unwrap();
+ node.set_property_u32(atom, Role::App, "z_index", 0).unwrap();
+
+ let mut shape = VectorShape::new();
+
+ let x1 = expr::const_f32(0.);
+ let y1 = expr::const_f32(0.);
+ let x2 = expr::load_var("w");
+ let y2 = expr::const_f32(SETTING_LABEL_LINESPACE);
+ let (color1, color2) = match COLOR_SCHEME {
+ ColorScheme::DarkMode => ([0., 0.11, 0.11, 0.4], [0., 0.11, 0.11, 0.5]),
+ ColorScheme::PaperLight => ([1., 1., 1., 1.], [1., 1., 1., 1.]),
+ };
+ let mut verts = vec![
+ ShapeVertex::new(x1.clone(), y1.clone(), color1),
+ ShapeVertex::new(x2.clone(), y1.clone(), color1),
+ ShapeVertex::new(x1.clone(), y2.clone(), color2),
+ ShapeVertex::new(x2, y2, color2),
+ ];
+ let mut indices = vec![0, 2, 1, 1, 2, 3];
+ shape.verts.append(&mut verts);
+ shape.indices.append(&mut indices);
+
+ shape.add_filled_box(
+ expr::const_f32(0.),
+ expr::const_f32(SETTING_LABEL_LINESPACE - 1.),
+ expr::load_var("w"),
+ expr::const_f32(SETTING_LABEL_LINESPACE),
+ [0.15, 0.2, 0.19, 1.],
+ //[0., 0.11, 0.11, 0.4],
+ );
+
+ let node =
+ node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
+ layer_node.clone().link(node);
+
+ let node = create_vector_art("search_bg2");
+ let prop = node.get_property("rect").unwrap();
+ prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
+ prop.clone().set_f32(atom, Role::App, 1, 60.).unwrap();
+ prop.clone().set_expr(atom, Role::App, 2, cc.compile("w * 100").unwrap()).unwrap();
+ prop.clone().set_f32(atom, Role::App, 3, SETTING_LABEL_LINESPACE/3.5).unwrap();
+ node.set_property_u32(atom, Role::App, "z_index", 0).unwrap();
+
+ let mut shape = VectorShape::new();
+
+ let x1 = expr::const_f32(0.);
+ let y1 = expr::const_f32(0.);
+ let x2 = expr::load_var("w");
+ let y2 = expr::const_f32(SETTING_LABEL_LINESPACE);
+
+ let (color1, color2) = match COLOR_SCHEME {
+ ColorScheme::DarkMode => ([0., 0.94, 1., 0.4], [0., 0.3, 0.25, 0.0]),
+ ColorScheme::PaperLight => ([0., 0.94, 1., 0.4], [0., 0.3, 0.25, 0.0]),
+ };
+
+ let mut verts = vec![
+ ShapeVertex::new(x1.clone(), y1.clone(), color1),
+ ShapeVertex::new(x2.clone(), y1.clone(), color1),
+ ShapeVertex::new(x1.clone(), y2.clone(), color2),
+ ShapeVertex::new(x2, y2, color2),
+ ];
+ let mut indices = vec![0, 2, 1, 1, 2, 3];
+ shape.verts.append(&mut verts);
+ shape.indices.append(&mut indices);
+
+ shape.add_filled_box(
+ expr::const_f32(0.),
+ expr::const_f32(SETTING_LABEL_LINESPACE - 1.),
+ expr::load_var("w"),
+ expr::const_f32(SETTING_LABEL_LINESPACE),
+ [0.15, 0.2, 0.19, 1.],
+ );
+
+ let node =
+ node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
+ layer_node.clone().link(node);
// Create a BTreeMap to store settings
let mut settings_map: BTreeMap> = BTreeMap::new();
@@ -283,18 +663,47 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
// Setting currently being edited
let active_setting: Arc>>> = Arc::new(Mutex::new(None));
+ // Setting Layer
+ // Contain a setting
+ let settings_layer_node = create_layer("settings");
+ let prop = settings_layer_node.get_property("rect").unwrap();
+ prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
+ prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
+ prop.clone().set_expr(atom, Role::App, 2, expr::load_var("w")).unwrap();
+ prop.clone().set_f32(atom, Role::App, 3, 0.).unwrap();
+ settings_layer_node.set_property_bool(atom, Role::App, "is_visible", true).unwrap();
+ settings_layer_node.set_property_u32(atom, Role::App, "z_index", 0).unwrap();
+ let settings_layer_node =
+ settings_layer_node.setup(|me| Layer::new(me, app.render_api.clone(), app.ex.clone())).await;
+ layer_node.clone().link(settings_layer_node.clone());
+
// Iterate over the map and process each setting
for (key, setting) in settings_map {
let setting_clone = setting.clone();
let setting_name = setting_clone.name.clone();
+ let is_bool = matches!(setting_clone.get_value(), PropertyValue::Bool(_));
setting_y += SETTING_LABEL_LINESPACE;
+ // Setting Layer
+ // Contain a setting
+ let setting_layer_node = create_layer(&setting_name.to_string());
+ let prop = setting_layer_node.get_property("rect").unwrap();
+ prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
+ prop.clone().set_f32(atom, Role::App, 1, setting_y + 60.).unwrap();
+ prop.clone().set_expr(atom, Role::App, 2, expr::load_var("w")).unwrap();
+ prop.clone().set_f32(atom, Role::App, 3, SETTING_LABEL_LINESPACE).unwrap();
+ setting_layer_node.set_property_bool(atom, Role::App, "is_visible", true).unwrap();
+ setting_layer_node.set_property_u32(atom, Role::App, "z_index", 0).unwrap();
+ let setting_layer_node =
+ setting_layer_node.setup(|me| Layer::new(me, app.render_api.clone(), app.ex.clone())).await;
+ settings_layer_node.clone().link(setting_layer_node.clone());
+
// Background Label
- let node = create_vector_art("settings_label_bg");
+ let node = create_vector_art("key_bg");
let prop = node.get_property("rect").unwrap();
prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
- prop.clone().set_f32(atom, Role::App, 1, setting_y).unwrap();
+ prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
prop.clone().set_expr(atom, Role::App, 2, cc.compile("w * X_RATIO - BORDER_RIGHT_SCALE").unwrap()).unwrap();
prop.clone().set_f32(atom, Role::App, 3, SETTING_LABEL_LINESPACE).unwrap();
node.set_property_u32(atom, Role::App, "z_index", 0).unwrap();
@@ -306,7 +715,8 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
let x2 = expr::load_var("w");
let y2 = expr::const_f32(SETTING_LABEL_LINESPACE);
let (color1, color2) = match COLOR_SCHEME {
- ColorScheme::DarkMode => ([0., 0.11, 0.11, 1.], [0., 0.11, 0.11, 1.]),
+ //ColorScheme::DarkMode => ([0., 0.11, 0.11, 1.], [0., 0.11, 0.11, 1.]),
+ ColorScheme::DarkMode => ([0., 0.11, 0.11, 0.4], [0., 0.11, 0.11, 0.5]),
ColorScheme::PaperLight => ([1., 1., 1., 1.], [1., 1., 1., 1.]),
};
let mut verts = vec![
@@ -329,68 +739,153 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
let node =
node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
- layer_node.clone().link(node);
+ setting_layer_node.clone().link(node);
- // Border right arrow
- let node = create_vector_art("right_arrow");
- let prop = node.get_property("rect").unwrap();
- prop.clone().set_expr(atom, Role::App, 0, cc.compile("w * X_RATIO - BORDER_RIGHT_SCALE/2").unwrap()).unwrap();
- prop.clone().set_f32(atom, Role::App, 1, setting_y+30.).unwrap();
- prop.clone().set_f32(atom, Role::App, 2, 0.).unwrap();
- prop.clone().set_f32(atom, Role::App, 3, 0.).unwrap();
- node.set_property_u32(atom, Role::App, "z_index", 3).unwrap();
- let shape = shape::create_right_border([0., 0.11, 0.11, 1.]).scaled(30.);
- let node =
- node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
- layer_node.clone().link(node);
+ if is_bool {
+ // Background Value: Bool FALSE
+ let node = create_vector_art("value_bg_bool_false");
+ let prop = node.get_property("rect").unwrap();
+ prop.clone().set_expr(atom, Role::App, 0, cc.compile("w * X_RATIO - BORDER_RIGHT_SCALE").unwrap()).unwrap();
+ prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
+ prop.clone().set_expr(atom, Role::App, 2, cc.compile("w * (1-X_RATIO) + BORDER_RIGHT_SCALE").unwrap()).unwrap();
+ prop.clone().set_f32(atom, Role::App, 3, SETTING_LABEL_LINESPACE).unwrap();
+ node.set_property_u32(atom, Role::App, "z_index", 0).unwrap();
+ node.set_property_bool(atom, Role::App, "is_visible", matches!(setting_clone.get_value(), PropertyValue::Bool(false))).unwrap();
- // Background Value
- let node = create_vector_art(&(setting_name.to_string() + "_settings_value_bg"));
- let prop = node.get_property("rect").unwrap();
- prop.clone().set_expr(atom, Role::App, 0, cc.compile("w * X_RATIO - BORDER_RIGHT_SCALE/2").unwrap()).unwrap();
- prop.clone().set_f32(atom, Role::App, 1, setting_y).unwrap();
- prop.clone().set_expr(atom, Role::App, 2, cc.compile("w * (1-X_RATIO) + BORDER_RIGHT_SCALE/2").unwrap()).unwrap();
- prop.clone().set_f32(atom, Role::App, 3, SETTING_LABEL_LINESPACE).unwrap();
- node.set_property_u32(atom, Role::App, "z_index", 0).unwrap();
- node.set_property_bool(atom, Role::App, "is_visible", false).unwrap();
+ let mut shape = VectorShape::new();
- let mut shape = VectorShape::new();
+ let x1 = expr::const_f32(0.);
+ let y1 = expr::const_f32(0.);
+ let x2 = expr::load_var("w");
+ let y2 = expr::const_f32(SETTING_LABEL_LINESPACE);
- let x1 = expr::const_f32(0.);
- let y1 = expr::const_f32(0.);
- let x2 = expr::load_var("w");
- let y2 = expr::const_f32(SETTING_LABEL_LINESPACE);
- let (color1, color2) = match COLOR_SCHEME {
- ColorScheme::DarkMode => ([0., 0.11, 0.11, 1.], [0., 0.11, 0.11, 1.]),
- ColorScheme::PaperLight => ([1., 1., 1., 1.], [1., 1., 1., 1.]),
- };
- let mut verts = vec![
- ShapeVertex::new(x1.clone(), y1.clone(), color1),
- ShapeVertex::new(x2.clone(), y1.clone(), color1),
- ShapeVertex::new(x1.clone(), y2.clone(), color2),
- ShapeVertex::new(x2, y2, color2),
- ];
- let mut indices = vec![0, 2, 1, 1, 2, 3];
- shape.verts.append(&mut verts);
- shape.indices.append(&mut indices);
+ let (color1, color2) = match COLOR_SCHEME {
+ //ColorScheme::DarkMode => ([0., 0.11, 0.11, 1.], [0., 0.11, 0.11, 1.]),
+ ColorScheme::DarkMode => ([0.0, 0.04, 0.04, 0.0], [0.7, 0.0, 0.0, 0.15]),
+ ColorScheme::PaperLight => ([0.0, 0.04, 0.04, 0.0], [0.7, 0.0, 0.0, 0.15]),
+ };
- shape.add_filled_box(
- expr::const_f32(0.),
- expr::const_f32(SETTING_LABEL_LINESPACE - 1.),
- expr::load_var("w"),
- expr::const_f32(SETTING_LABEL_LINESPACE),
- [0.15, 0.2, 0.19, 1.],
- );
+ let mut verts = vec![
+ ShapeVertex::new(x1.clone(), y1.clone(), color1),
+ ShapeVertex::new(x2.clone(), y1.clone(), color1),
+ ShapeVertex::new(x1.clone(), y2.clone(), color2),
+ ShapeVertex::new(x2, y2, color2),
+ ];
+ let mut indices = vec![0, 2, 1, 1, 2, 3];
+ shape.verts.append(&mut verts);
+ shape.indices.append(&mut indices);
- let node =
- node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
- layer_node.clone().link(node);
+ shape.add_filled_box(
+ expr::const_f32(0.),
+ expr::const_f32(SETTING_LABEL_LINESPACE - 1.),
+ expr::load_var("w"),
+ expr::const_f32(SETTING_LABEL_LINESPACE),
+ [0.15, 0.2, 0.19, 1.],
+ );
- // Label: "SETTINGS" title
- let label_value_node = create_text(&(setting_name.to_string() + "_settings_label"));
+ let node =
+ node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
+ setting_layer_node.clone().link(node);
+
+
+ // Background Value: Bool TRUE
+ let node = create_vector_art("value_bg_bool_true");
+ let prop = node.get_property("rect").unwrap();
+ prop.clone().set_expr(atom, Role::App, 0, cc.compile("w * X_RATIO - BORDER_RIGHT_SCALE").unwrap()).unwrap();
+ prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
+ prop.clone().set_expr(atom, Role::App, 2, cc.compile("w * (1-X_RATIO) + BORDER_RIGHT_SCALE").unwrap()).unwrap();
+ prop.clone().set_f32(atom, Role::App, 3, SETTING_LABEL_LINESPACE).unwrap();
+ node.set_property_u32(atom, Role::App, "z_index", 0).unwrap();
+ node.set_property_bool(atom, Role::App, "is_visible", matches!(setting_clone.get_value(), PropertyValue::Bool(true))).unwrap();
+
+ let mut shape = VectorShape::new();
+
+ let x1 = expr::const_f32(0.);
+ let y1 = expr::const_f32(0.);
+ let x2 = expr::load_var("w");
+ let y2 = expr::const_f32(SETTING_LABEL_LINESPACE);
+
+ let (color1, color2) = match COLOR_SCHEME {
+ //ColorScheme::DarkMode => ([0., 0.11, 0.11, 1.], [0., 0.11, 0.11, 1.]),
+ ColorScheme::DarkMode => ([0., 0.3, 0.25, 0.0], [0., 0.3, 0.25, 0.5]),
+ ColorScheme::PaperLight => ([0., 0.3, 0.25, 0.0], [0., 0.3, 0.25, 0.5]),
+ };
+
+ let mut verts = vec![
+ ShapeVertex::new(x1.clone(), y1.clone(), color1),
+ ShapeVertex::new(x2.clone(), y1.clone(), color1),
+ ShapeVertex::new(x1.clone(), y2.clone(), color2),
+ ShapeVertex::new(x2, y2, color2),
+ ];
+ let mut indices = vec![0, 2, 1, 1, 2, 3];
+ shape.verts.append(&mut verts);
+ shape.indices.append(&mut indices);
+
+ shape.add_filled_box(
+ expr::const_f32(0.),
+ expr::const_f32(SETTING_LABEL_LINESPACE - 1.),
+ expr::load_var("w"),
+ expr::const_f32(SETTING_LABEL_LINESPACE),
+ [0.15, 0.2, 0.19, 1.],
+ );
+
+ let node =
+ node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
+ setting_layer_node.clone().link(node);
+ } else {
+ // Background Value
+ let node = create_vector_art("value_bg");
+ let prop = node.get_property("rect").unwrap();
+ prop.clone().set_expr(atom, Role::App, 0, cc.compile("w * X_RATIO - BORDER_RIGHT_SCALE").unwrap()).unwrap();
+ prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
+ prop.clone().set_expr(atom, Role::App, 2, cc.compile("w * (1-X_RATIO) + BORDER_RIGHT_SCALE").unwrap()).unwrap();
+ prop.clone().set_f32(atom, Role::App, 3, SETTING_LABEL_LINESPACE).unwrap();
+ node.set_property_u32(atom, Role::App, "z_index", 0).unwrap();
+ node.set_property_bool(atom, Role::App, "is_visible", true).unwrap();
+
+ let mut shape = VectorShape::new();
+
+ let x1 = expr::const_f32(0.);
+ let y1 = expr::const_f32(0.);
+ let x2 = expr::load_var("w");
+ let y2 = expr::const_f32(SETTING_LABEL_LINESPACE);
+
+ let (color1, color2) = match COLOR_SCHEME {
+ //ColorScheme::DarkMode => ([0., 0.11, 0.11, 1.], [0., 0.11, 0.11, 1.]),
+ ColorScheme::DarkMode => ([0., 0.02, 0.02, 0.5], [0., 0.04, 0.04, 0.7]),
+ ColorScheme::PaperLight => ([1., 1., 1., 1.], [1., 1., 1., 1.]),
+ };
+
+ let mut verts = vec![
+ ShapeVertex::new(x1.clone(), y1.clone(), color1),
+ ShapeVertex::new(x2.clone(), y1.clone(), color1),
+ ShapeVertex::new(x1.clone(), y2.clone(), color2),
+ ShapeVertex::new(x2, y2, color2),
+ ];
+ let mut indices = vec![0, 2, 1, 1, 2, 3];
+ shape.verts.append(&mut verts);
+ shape.indices.append(&mut indices);
+
+ shape.add_filled_box(
+ expr::const_f32(0.),
+ expr::const_f32(SETTING_LABEL_LINESPACE - 1.),
+ expr::load_var("w"),
+ expr::const_f32(SETTING_LABEL_LINESPACE),
+ [0.15, 0.2, 0.19, 1.],
+ );
+
+ let node =
+ node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
+ setting_layer_node.clone().link(node);
+ }
+
+
+
+ // Label Key
+ let label_value_node = create_text("key_label");
let prop = label_value_node.get_property("rect").unwrap();
prop.clone().set_f32(atom, Role::App, 0, SETTING_LABEL_X).unwrap();
- prop.clone().set_f32(atom, Role::App, 1, setting_y).unwrap();
+ prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
prop.clone().set_expr(atom, Role::App, 2, cc.compile("w * X_RATIO").unwrap()).unwrap();
prop.clone().set_f32(atom, Role::App, 3, 100.).unwrap();
label_value_node.set_property_u32(atom, Role::App, "z_index", 1).unwrap();
@@ -422,18 +917,18 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
)
})
.await;
- layer_node.clone().link(label_value_node);
+ setting_layer_node.clone().link(label_value_node);
// Text edit
- let editbox_node = create_editbox(&(setting_name.to_string() + "_editz"));
+ let editbox_node = create_editbox("value_editbox");
editbox_node.set_property_bool(atom, Role::App, "is_active", true).unwrap();
editbox_node.set_property_bool(atom, Role::App, "is_focused", true).unwrap();
let prop = editbox_node.get_property("rect").unwrap();
prop.clone().set_expr(atom, Role::App, 0, cc.compile("w * X_RATIO + BORDER_RIGHT_SCALE").unwrap()).unwrap();
- prop.clone().set_f32(atom, Role::App, 1, setting_y + 15. ).unwrap();
+ prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
prop.clone().set_expr(atom, Role::App, 2, cc.compile("w * X_RATIO - BORDER_RIGHT_SCALE").unwrap()).unwrap();
prop.clone().set_f32(atom, Role::App, 3, SETTING_LABEL_LINESPACE).unwrap();
- editbox_node.set_property_f32(atom, Role::App, "baseline", 16.).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 {
@@ -452,10 +947,10 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
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", SETTING_EDIT_FONTSIZE).unwrap();
- editbox_node.set_property_f32(atom, Role::App, "cursor_descent", SETTING_EDIT_FONTSIZE).unwrap();
- editbox_node.set_property_f32(atom, Role::App, "select_ascent", SETTING_EDIT_FONTSIZE).unwrap();
- editbox_node.set_property_f32(atom, Role::App, "select_descent", SETTING_EDIT_FONTSIZE).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();
@@ -505,7 +1000,7 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
)
})
.await;
- layer_node.clone().link(node);
+ setting_layer_node.clone().link(node);
// Is this setting the one that is currently active
let cloned_active_setting = active_setting.clone();
@@ -513,53 +1008,128 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
Some(active) => Arc::ptr_eq(active, &setting),
None => false,
};
- let is_bool = matches!(setting_clone.get_value(), PropertyValue::Bool(_));
if !is_active_setting {
- // Label showing the setting's current value
- let value_node = create_text(&(setting_name.to_string() + "_settings_value_label"));
- let prop = value_node.get_property("rect").unwrap();
- prop.clone().set_expr(atom, Role::App, 0, cc.compile("w * X_RATIO + BORDER_RIGHT_SCALE").unwrap()).unwrap();
- prop.clone().set_f32(atom, Role::App, 1, setting_y).unwrap();
- prop.clone().set_expr(atom, Role::App, 2, cc.compile("w * X_RATIO").unwrap()).unwrap();
- prop.clone().set_f32(atom, Role::App, 3, 100.).unwrap();
- value_node.set_property_u32(atom, Role::App, "z_index", 1).unwrap();
- value_node.set_property_f32(atom, Role::App, "baseline", SETTING_LABEL_BASELINE).unwrap();
- value_node.set_property_f32(atom, Role::App, "font_size", SETTING_LABEL_FONTSIZE).unwrap();
- 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_u32(atom, Role::App, "z_index", 2).unwrap();
- let node = value_node
- .setup(|me| {
- Text::new(
- me,
- window_scale.clone(),
- app.render_api.clone(),
- app.text_shaper.clone(),
- app.ex.clone(),
- )
- })
- .await;
- layer_node.clone().link(node);
+ if is_bool {
+
+ // Bool circle: FALSE
+ let node = create_vector_art("bool_icon_bg_false");
+ let prop = node.get_property("rect").unwrap();
+ prop.clone().set_expr(atom, Role::App, 0, cc.compile("w * X_RATIO + BORDER_RIGHT_SCALE + 6").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_u32(atom, Role::App, "z_index", 1).unwrap();
+ node.set_property_bool(atom, Role::App, "is_visible", matches!(setting_clone.get_value(), PropertyValue::Bool(false))).unwrap();
+
+ let shape = shape::create_circle([0.9, 0.4, 0.4, 0.7]).scaled(5.);
+ let node =
+ node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
+ setting_layer_node.clone().link(node);
+
+ // Bool circle: TRUE
+ let node = create_vector_art("bool_icon_bg_true");
+ let prop = node.get_property("rect").unwrap();
+ prop.clone().set_expr(atom, Role::App, 0, cc.compile("w * X_RATIO + BORDER_RIGHT_SCALE + 6").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_u32(atom, Role::App, "z_index", 1).unwrap();
+ node.set_property_bool(atom, Role::App, "is_visible", matches!(setting_clone.get_value(), PropertyValue::Bool(true))).unwrap();
+
+ let shape = shape::create_circle([0., 0.94, 1., 1.]).scaled(5.);
+ let node =
+ node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
+ setting_layer_node.clone().link(node);
+
+ // Label showing the setting's current value
+ let value_node = create_text("value_label");
+ let prop = value_node.get_property("rect").unwrap();
+ prop.clone().set_expr(atom, Role::App, 0, cc.compile("w * X_RATIO + BORDER_RIGHT_SCALE + 20 + 6").unwrap()).unwrap();
+ prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
+ prop.clone().set_expr(atom, Role::App, 2, cc.compile("w * X_RATIO").unwrap()).unwrap();
+ prop.clone().set_f32(atom, Role::App, 3, 100.).unwrap();
+ value_node.set_property_u32(atom, Role::App, "z_index", 1).unwrap();
+ value_node.set_property_f32(atom, Role::App, "baseline", SETTING_LABEL_BASELINE).unwrap();
+ value_node.set_property_f32(atom, Role::App, "font_size", SETTING_LABEL_FONTSIZE).unwrap();
+ 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();
+ } 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_u32(atom, Role::App, "z_index", 2).unwrap();
+
+ let node = value_node
+ .setup(|me| {
+ Text::new(
+ me,
+ window_scale.clone(),
+ app.render_api.clone(),
+ app.text_shaper.clone(),
+ app.ex.clone(),
+ )
+ })
+ .await;
+ setting_layer_node.clone().link(node);
+
+ } else {
+
+ // Label showing the setting's current value
+ let value_node = create_text("value_label");
+ let prop = value_node.get_property("rect").unwrap();
+ prop.clone().set_expr(atom, Role::App, 0, cc.compile("w * X_RATIO + BORDER_RIGHT_SCALE").unwrap()).unwrap();
+ prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
+ prop.clone().set_expr(atom, Role::App, 2, cc.compile("w * X_RATIO").unwrap()).unwrap();
+ prop.clone().set_f32(atom, Role::App, 3, 100.).unwrap();
+ value_node.set_property_u32(atom, Role::App, "z_index", 1).unwrap();
+ value_node.set_property_f32(atom, Role::App, "baseline", SETTING_LABEL_BASELINE).unwrap();
+ value_node.set_property_f32(atom, Role::App, "font_size", SETTING_LABEL_FONTSIZE).unwrap();
+ 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_u32(atom, Role::App, "z_index", 2).unwrap();
+
+ let node = value_node
+ .setup(|me| {
+ Text::new(
+ me,
+ window_scale.clone(),
+ app.render_api.clone(),
+ app.text_shaper.clone(),
+ app.ex.clone(),
+ )
+ })
+ .await;
+ setting_layer_node.clone().link(node);
+ }
+
+
// A wide button useful to select the current setting
- let node = create_button("setting_selector_btn");
+ let node = create_button("selector_btn");
node.set_property_bool(atom, Role::App, "is_active", true).unwrap();
let prop = node.get_property("rect").unwrap();
prop.clone().set_expr(atom, Role::App, 0, cc.compile("w * X_RATIO").unwrap()).unwrap();
- prop.clone().set_f32(atom, Role::App, 1, setting_y).unwrap();
+ prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
prop.clone().set_expr(atom, Role::App, 2, cc.compile("w * (1-X_RATIO)").unwrap()).unwrap();
prop.clone().set_f32(atom, Role::App, 3, SETTING_LABEL_LINESPACE).unwrap();
@@ -569,12 +1139,17 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
let sg_root = sg_root.clone();
let mut lock = cloned_active_setting.lock().unwrap();
+ let path = "/window/settings_layer/search_input";
+ let node = sg_root.clone().lookup_node(path).unwrap();
+ //node.set_property_bool(atom, Role::App, "is_active", false).unwrap();
+ 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;
// Hide the selected setting value label (set its text empty)
// of the selected setting, if there's one
- let path = format!("/window/settings_layer/{}_settings_value_label", &s.name);
+ let path = format!("/window/settings_layer/settings/{}/value_label", &s.name);
let node = sg_root.clone().lookup_node(&path).unwrap();
let text = PropertyStr::wrap(&node, Role::App, "text", 0).unwrap();
text.set(atom, &s.value_as_string());
@@ -582,7 +1157,7 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
// Hide the selected setting value label (set its text empty)
// of the selected setting, if there's one
if !_was_active {
- let path = format!("/window/settings_layer/{}_editz", &s.name);
+ let path = format!("/window/settings_layer/settings/{}/value_editbox", &s.name);
let node = sg_root.clone().lookup_node(&path).unwrap();
node.set_property_bool(atom, Role::App, "is_active", false).unwrap();
node.set_property_bool(atom, Role::App, "is_focused", false).unwrap();
@@ -595,11 +1170,12 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
// not panic)
let is_bool = matches!(lock.clone().unwrap().get_value(), PropertyValue::Bool(_));
if !is_bool {
- let path = format!("/window/settings_layer/{}_confirm_btn_bg", &s.name);
+ 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();
}
+
_was_active
} else {
false
@@ -612,27 +1188,77 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
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 label_path = format!("/window/settings_layer/settings/{}/value_label", &setting_clone.name);
let editbox = sg_root.clone().lookup_node(&label_path).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);
+
+
if matches!(value, PropertyValue::Bool(false)) {
&lock.clone().unwrap().node.set_property_bool(atom, Role::User, "value", true);
- label_text.set(atom, "true");
+ 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(atom, Role::User, "value", false);
- label_text.set(atom, "false");
+ 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();
}
} 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 label_path = format!("/window/settings_layer/settings/{}/value_label", &setting_clone.name);
let editbox = sg_root.clone().lookup_node(&label_path).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/{}_editz", &setting_clone.name);
+ let path = format!("/window/settings_layer/settings/{}/value_editbox", &setting_clone.name);
let node = sg_root.clone().lookup_node(&path).unwrap();
node.set_property_bool(atom, Role::App, "is_active", true).unwrap();
node.set_property_bool(atom, Role::App, "is_focused", true).unwrap();
@@ -642,14 +1268,10 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
}
// Show confirm button
- let path = format!("/window/settings_layer/{}_confirm_btn_bg", &setting_clone.name);
+ 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);
- // Hide the value background
- let path = format!("/window/settings_layer/{}_settings_value_bg", &setting_clone.name);
- let node = sg_root.clone().lookup_node(&path).unwrap();
- let _ = node.set_property_bool(atom, Role::App, "is_visible", false);
}
};
@@ -664,15 +1286,15 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
app.tasks.lock().unwrap().push(listen_click);
let node = node.setup(|me| Button::new(me, app.ex.clone())).await;
- layer_node.clone().link(node.clone());
+ setting_layer_node.clone().link(node.clone());
}
if is_bool {
// Switch icon
- let node = create_vector_art(&(setting_name.to_string() + "_switch_btn_bg"));
+ let node = create_vector_art("switch_btn_bg");
let prop = node.get_property("rect").unwrap();
prop.clone().set_expr(atom, Role::App, 0, cc.compile("w - 50").unwrap()).unwrap();
- prop.clone().set_f32(atom, Role::App, 1, setting_y + SETTING_LABEL_LINESPACE / 2.).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_u32(atom, Role::App, "z_index", 1).unwrap();
@@ -680,13 +1302,13 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
let shape = shape::create_switch([0., 0.94, 1., 1.]).scaled(10.);
let node =
node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
- layer_node.clone().link(node);
+ setting_layer_node.clone().link(node);
} else {
// Confirm button
- let node = create_vector_art(&(setting_name.to_string() + "_confirm_btn_bg"));
+ let node = create_vector_art("confirm_btn_bg");
let prop = node.get_property("rect").unwrap();
prop.clone().set_expr(atom, Role::App, 0, cc.compile("w - 50").unwrap()).unwrap();
- prop.clone().set_f32(atom, Role::App, 1, setting_y + SETTING_LABEL_LINESPACE / 2.).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_u32(atom, Role::App, "z_index", 3).unwrap();
@@ -695,19 +1317,19 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
let shape = shape::create_confirm([0., 0.94, 1., 1.]).scaled(10.);
let node =
node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
- layer_node.clone().link(node.clone());
+ setting_layer_node.clone().link(node.clone());
let node = create_button("confirm_btn");
node.set_property_bool(atom, Role::App, "is_active", true).unwrap();
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_y).unwrap();
+ prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
prop.clone().set_f32(atom, Role::App, 2, 100.).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;
- layer_node.clone().link(node.clone());
+ setting_layer_node.clone().link(node.clone());
// Handle confirm button click
{
@@ -730,13 +1352,20 @@ pub async fn make(app: &App, window: SceneNodePtr, ex: ExecutorPtr) {
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();
+ 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();
}
async fn update_setting(setting: Arc, sg_root: SceneNodePtr, active_setting: Arc>>>, editz_text: PropertyStr) {
let atom = &mut PropertyAtomicGuard::new();
let setting_name = &setting.clone().name;
- let path = format!("/window/settings_layer/{}_editz", setting_name);
+ let path = format!("/window/settings_layer/settings/{}/value_editbox", setting_name);
if let Some(node) = sg_root.clone().lookup_node(path) {
node.set_property_f32(atom, Role::App, "font_size", 0.).unwrap();
node.set_property_bool(atom, Role::App, "is_active", false).unwrap();
@@ -748,11 +1377,11 @@ async fn update_setting(setting: Arc, sg_root: SceneNodePtr, active_set
let value_str = editz_text.get();
let parsed = value_str.parse::();
if let Ok(value) = parsed {
- let path = format!("/window/settings_layer/{}_settings_value_label", setting_name);
+ let path = format!("/window/settings_layer/settings/{}/value_label", setting_name);
if let Some(node) = sg_root.clone().lookup_node(path) {
node.set_property_str(atom, Role::App, "text", value_str).unwrap();
}
- let path = format!("/window/settings_layer/{}_confirm_btn_bg", setting_name);
+ let path = format!("/window/settings_layer/settings/{}/confirm_btn_bg", setting_name);
if let Some(node) = sg_root.clone().lookup_node(path) {
node.set_property_bool(atom, Role::App, "is_visible", false).unwrap();
}
@@ -765,11 +1394,11 @@ async fn update_setting(setting: Arc, sg_root: SceneNodePtr, active_set
let value_str = editz_text.get();
let parsed = value_str.parse::();
if let Ok(value) = parsed {
- let path = format!("/window/settings_layer/{}_settings_value_label", setting_name);
+ let path = format!("/window/settings_layer/settings/{}/value_label", setting_name);
if let Some(node) = sg_root.clone().lookup_node(path) {
node.set_property_str(atom, Role::App, "text", value_str).unwrap();
}
- let path = format!("/window/settings_layer/{}_confirm_btn_bg", setting_name);
+ let path = format!("/window/settings_layer/settings/{}/confirm_btn_bg", setting_name);
if let Some(node) = sg_root.clone().lookup_node(path) {
node.set_property_bool(atom, Role::App, "is_visible", false).unwrap();
}
@@ -780,11 +1409,11 @@ async fn update_setting(setting: Arc, sg_root: SceneNodePtr, active_set
},
PropertyValue::Str(_) => {
let value_str = editz_text.get();
- let path = format!("/window/settings_layer/{}_settings_value_label", setting_name);
+ let path = format!("/window/settings_layer/settings/{}/value_label", setting_name);
if let Some(node) = sg_root.clone().lookup_node(path) {
node.set_property_str(atom, Role::App, "text", &value_str).unwrap();
}
- let path = format!("/window/settings_layer/{}_confirm_btn_bg", setting_name);
+ let path = format!("/window/settings_layer/{}/confirm_btn_bg", setting_name);
if let Some(node) = sg_root.clone().lookup_node(path) {
node.set_property_bool(atom, Role::App, "is_visible", false).unwrap();
}
@@ -794,4 +1423,4 @@ async fn update_setting(setting: Arc, sg_root: SceneNodePtr, active_set
},
_ => {},
};
-}
\ No newline at end of file
+}
diff --git a/bin/app/src/expr/compile.rs b/bin/app/src/expr/compile.rs
index bc43857cc..e6e1f440d 100644
--- a/bin/app/src/expr/compile.rs
+++ b/bin/app/src/expr/compile.rs
@@ -66,6 +66,7 @@ impl Token {
}
}
+#[derive(Clone)]
pub struct Compiler {
table: HashMap,
}
diff --git a/bin/app/src/shape/circle.rs b/bin/app/src/shape/circle.rs
new file mode 100644
index 000000000..2cab83b30
--- /dev/null
+++ b/bin/app/src/shape/circle.rs
@@ -0,0 +1,40 @@
+use crate::{mesh::Color, ui::{VectorShape, ShapeVertex}};
+pub fn create_circle(color: Color) -> VectorShape {
+ VectorShape {
+ verts: vec![
+ ShapeVertex::from_xy(0.0, -1.0, color),
+ ShapeVertex::from_xy(-0.19509, -0.980785, color),
+ ShapeVertex::from_xy(-0.382683, -0.92388, color),
+ ShapeVertex::from_xy(-0.55557, -0.83147, color),
+ ShapeVertex::from_xy(-0.707107, -0.707107, color),
+ ShapeVertex::from_xy(-0.83147, -0.55557, color),
+ ShapeVertex::from_xy(-0.92388, -0.382683, color),
+ ShapeVertex::from_xy(-0.980785, -0.19509, color),
+ ShapeVertex::from_xy(-1.0, 0.0, color),
+ ShapeVertex::from_xy(-0.980785, 0.19509, color),
+ ShapeVertex::from_xy(-0.92388, 0.382683, color),
+ ShapeVertex::from_xy(-0.83147, 0.55557, color),
+ ShapeVertex::from_xy(-0.707107, 0.707107, color),
+ ShapeVertex::from_xy(-0.55557, 0.83147, color),
+ ShapeVertex::from_xy(-0.382683, 0.92388, color),
+ ShapeVertex::from_xy(-0.19509, 0.980785, color),
+ ShapeVertex::from_xy(0.0, 1.0, color),
+ ShapeVertex::from_xy(0.19509, 0.980785, color),
+ ShapeVertex::from_xy(0.382683, 0.92388, color),
+ ShapeVertex::from_xy(0.55557, 0.83147, color),
+ ShapeVertex::from_xy(0.707107, 0.707107, color),
+ ShapeVertex::from_xy(0.83147, 0.55557, color),
+ ShapeVertex::from_xy(0.92388, 0.382683, color),
+ ShapeVertex::from_xy(0.980785, 0.19509, color),
+ ShapeVertex::from_xy(1.0, 0.0, color),
+ ShapeVertex::from_xy(0.980785, -0.19509, color),
+ ShapeVertex::from_xy(0.92388, -0.382683, color),
+ ShapeVertex::from_xy(0.83147, -0.55557, color),
+ ShapeVertex::from_xy(0.707107, -0.707107, color),
+ ShapeVertex::from_xy(0.55557, -0.83147, color),
+ ShapeVertex::from_xy(0.382683, -0.92388, color),
+ ShapeVertex::from_xy(0.19509, -0.980785, color),
+ ],
+ indices: vec![16, 24, 0, 0, 1, 4, 1, 2, 4, 2, 3, 4, 4, 5, 6, 6, 7, 4, 7, 8, 4, 8, 9, 12, 9, 10, 12, 10, 11, 12, 12, 13, 14, 14, 15, 12, 15, 16, 12, 16, 17, 20, 17, 18, 20, 18, 19, 20, 20, 21, 22, 22, 23, 20, 23, 24, 20, 24, 25, 28, 25, 26, 28, 26, 27, 28, 28, 29, 30, 30, 31, 28, 31, 0, 28, 0, 4, 8, 8, 12, 16, 16, 20, 24, 24, 28, 0, 0, 8, 16]
+ }
+}
diff --git a/bin/app/src/shape/logo.rs b/bin/app/src/shape/logo.rs
new file mode 100644
index 000000000..d59df3624
--- /dev/null
+++ b/bin/app/src/shape/logo.rs
@@ -0,0 +1,155 @@
+use crate::{mesh::Color, ui::{VectorShape, ShapeVertex}};
+pub fn create_logo(color: Color) -> VectorShape {
+ VectorShape {
+ verts: vec![
+ ShapeVertex::from_xy(0.000154, -0.009673, color),
+ ShapeVertex::from_xy(-0.000705, -0.009615, color),
+ ShapeVertex::from_xy(-0.001529, -0.009448, color),
+ ShapeVertex::from_xy(-0.00231, -0.009177, color),
+ ShapeVertex::from_xy(-0.00304, -0.008812, color),
+ ShapeVertex::from_xy(-0.003712, -0.008358, color),
+ ShapeVertex::from_xy(-0.004319, -0.007825, color),
+ ShapeVertex::from_xy(-0.004853, -0.007218, color),
+ ShapeVertex::from_xy(-0.005306, -0.006546, color),
+ ShapeVertex::from_xy(-0.005672, -0.005816, color),
+ ShapeVertex::from_xy(-0.005942, -0.005035, color),
+ ShapeVertex::from_xy(-0.00611, -0.004212, color),
+ ShapeVertex::from_xy(-0.006168, -0.003352, color),
+ ShapeVertex::from_xy(-0.00611, -0.002493, color),
+ ShapeVertex::from_xy(-0.005942, -0.001669, color),
+ ShapeVertex::from_xy(-0.005672, -0.000889, color),
+ ShapeVertex::from_xy(-0.005306, -0.000159, color),
+ ShapeVertex::from_xy(-0.004853, 0.000513, color),
+ ShapeVertex::from_xy(-0.004319, 0.00112, color),
+ ShapeVertex::from_xy(-0.003712, 0.001654, color),
+ ShapeVertex::from_xy(-0.00304, 0.002107, color),
+ ShapeVertex::from_xy(-0.00231, 0.002473, color),
+ ShapeVertex::from_xy(-0.001529, 0.002743, color),
+ ShapeVertex::from_xy(-0.000705, 0.002911, color),
+ ShapeVertex::from_xy(0.000154, 0.002968, color),
+ ShapeVertex::from_xy(0.001014, 0.002911, color),
+ ShapeVertex::from_xy(0.001838, 0.002743, color),
+ ShapeVertex::from_xy(0.002618, 0.002473, color),
+ ShapeVertex::from_xy(0.003349, 0.002107, color),
+ ShapeVertex::from_xy(0.004021, 0.001654, color),
+ ShapeVertex::from_xy(0.004627, 0.00112, color),
+ ShapeVertex::from_xy(0.005161, 0.000513, color),
+ ShapeVertex::from_xy(0.005615, -0.000159, color),
+ ShapeVertex::from_xy(0.00598, -0.000889, color),
+ ShapeVertex::from_xy(0.006251, -0.001669, color),
+ ShapeVertex::from_xy(0.006419, -0.002493, color),
+ ShapeVertex::from_xy(0.006476, -0.003352, color),
+ ShapeVertex::from_xy(0.006419, -0.004212, color),
+ ShapeVertex::from_xy(0.006251, -0.005035, color),
+ ShapeVertex::from_xy(0.00598, -0.005816, color),
+ ShapeVertex::from_xy(0.005615, -0.006546, color),
+ ShapeVertex::from_xy(0.005161, -0.007218, color),
+ ShapeVertex::from_xy(0.004627, -0.007825, color),
+ ShapeVertex::from_xy(0.004021, -0.008358, color),
+ ShapeVertex::from_xy(0.003349, -0.008812, color),
+ ShapeVertex::from_xy(0.002618, -0.009177, color),
+ ShapeVertex::from_xy(0.001838, -0.009448, color),
+ ShapeVertex::from_xy(0.001014, -0.009615, color),
+ ShapeVertex::from_xy(0.000154, -0.000474, color),
+ ShapeVertex::from_xy(-0.000234, -0.0005, color),
+ ShapeVertex::from_xy(-0.000606, -0.000576, color),
+ ShapeVertex::from_xy(-0.000958, -0.000697, color),
+ ShapeVertex::from_xy(-0.001287, -0.000862, color),
+ ShapeVertex::from_xy(-0.00159, -0.001066, color),
+ ShapeVertex::from_xy(-0.001864, -0.001307, color),
+ ShapeVertex::from_xy(-0.002104, -0.00158, color),
+ ShapeVertex::from_xy(-0.002309, -0.001883, color),
+ ShapeVertex::from_xy(-0.002473, -0.002212, color),
+ ShapeVertex::from_xy(-0.002595, -0.002564, color),
+ ShapeVertex::from_xy(-0.00267, -0.002936, color),
+ ShapeVertex::from_xy(-0.002696, -0.003324, color),
+ ShapeVertex::from_xy(-0.00267, -0.003712, color),
+ ShapeVertex::from_xy(-0.002595, -0.004084, color),
+ ShapeVertex::from_xy(-0.002473, -0.004436, color),
+ ShapeVertex::from_xy(-0.002309, -0.004765, color),
+ ShapeVertex::from_xy(-0.002104, -0.005068, color),
+ ShapeVertex::from_xy(-0.001864, -0.005342, color),
+ ShapeVertex::from_xy(-0.00159, -0.005582, color),
+ ShapeVertex::from_xy(-0.001287, -0.005786, color),
+ ShapeVertex::from_xy(-0.000958, -0.005951, color),
+ ShapeVertex::from_xy(-0.000606, -0.006073, color),
+ ShapeVertex::from_xy(-0.000234, -0.006148, color),
+ ShapeVertex::from_xy(0.000154, -0.006174, color),
+ ShapeVertex::from_xy(0.000542, -0.006148, color),
+ ShapeVertex::from_xy(0.000914, -0.006073, color),
+ ShapeVertex::from_xy(0.001266, -0.005951, color),
+ ShapeVertex::from_xy(0.001596, -0.005786, color),
+ ShapeVertex::from_xy(0.001899, -0.005582, color),
+ ShapeVertex::from_xy(0.002172, -0.005342, color),
+ ShapeVertex::from_xy(0.002413, -0.005068, color),
+ ShapeVertex::from_xy(0.002617, -0.004765, color),
+ ShapeVertex::from_xy(0.002782, -0.004436, color),
+ ShapeVertex::from_xy(0.002903, -0.004084, color),
+ ShapeVertex::from_xy(0.002979, -0.003712, color),
+ ShapeVertex::from_xy(0.003005, -0.003324, color),
+ ShapeVertex::from_xy(0.002979, -0.002936, color),
+ ShapeVertex::from_xy(0.002903, -0.002564, color),
+ ShapeVertex::from_xy(0.002782, -0.002212, color),
+ ShapeVertex::from_xy(0.002617, -0.001883, color),
+ ShapeVertex::from_xy(0.002413, -0.00158, color),
+ ShapeVertex::from_xy(0.002172, -0.001307, color),
+ ShapeVertex::from_xy(0.001899, -0.001066, color),
+ ShapeVertex::from_xy(0.001596, -0.000862, color),
+ ShapeVertex::from_xy(0.001266, -0.000697, color),
+ ShapeVertex::from_xy(0.000914, -0.000576, color),
+ ShapeVertex::from_xy(0.000542, -0.0005, color),
+ ShapeVertex::from_xy(-0.029, -0.020508, color),
+ ShapeVertex::from_xy(0.000154, 0.03, color),
+ ShapeVertex::from_xy(0.029308, -0.020508, color),
+ ShapeVertex::from_xy(0.000154, 0.005677, color),
+ ShapeVertex::from_xy(-0.001246, 0.005586, color),
+ ShapeVertex::from_xy(-0.002605, 0.005322, color),
+ ShapeVertex::from_xy(-0.003918, 0.004901, color),
+ ShapeVertex::from_xy(-0.00518, 0.004339, color),
+ ShapeVertex::from_xy(-0.006386, 0.003652, color),
+ ShapeVertex::from_xy(-0.00753, 0.002855, color),
+ ShapeVertex::from_xy(-0.008606, 0.001964, color),
+ ShapeVertex::from_xy(-0.009611, 0.000995, color),
+ ShapeVertex::from_xy(-0.010538, -3.7e-05, color),
+ ShapeVertex::from_xy(-0.011382, -0.001116, color),
+ ShapeVertex::from_xy(-0.012138, -0.002226, color),
+ ShapeVertex::from_xy(-0.0128, -0.003352, color),
+ ShapeVertex::from_xy(-0.012138, -0.004478, color),
+ ShapeVertex::from_xy(-0.011382, -0.005589, color),
+ ShapeVertex::from_xy(-0.010538, -0.006668, color),
+ ShapeVertex::from_xy(-0.009611, -0.0077, color),
+ ShapeVertex::from_xy(-0.008606, -0.008669, color),
+ ShapeVertex::from_xy(-0.00753, -0.00956, color),
+ ShapeVertex::from_xy(-0.006386, -0.010357, color),
+ ShapeVertex::from_xy(-0.00518, -0.011044, color),
+ ShapeVertex::from_xy(-0.003918, -0.011606, color),
+ ShapeVertex::from_xy(-0.002605, -0.012026, color),
+ ShapeVertex::from_xy(-0.001246, -0.01229, color),
+ ShapeVertex::from_xy(0.000154, -0.012382, color),
+ ShapeVertex::from_xy(0.001554, -0.01229, color),
+ ShapeVertex::from_xy(0.002913, -0.012026, color),
+ ShapeVertex::from_xy(0.004226, -0.011606, color),
+ ShapeVertex::from_xy(0.005488, -0.011044, color),
+ ShapeVertex::from_xy(0.006694, -0.010357, color),
+ ShapeVertex::from_xy(0.007838, -0.00956, color),
+ ShapeVertex::from_xy(0.008915, -0.008669, color),
+ ShapeVertex::from_xy(0.009919, -0.0077, color),
+ ShapeVertex::from_xy(0.010846, -0.006668, color),
+ ShapeVertex::from_xy(0.01169, -0.005589, color),
+ ShapeVertex::from_xy(0.012446, -0.004478, color),
+ ShapeVertex::from_xy(0.013108, -0.003352, color),
+ ShapeVertex::from_xy(0.012447, -0.002226, color),
+ ShapeVertex::from_xy(0.011692, -0.001116, color),
+ ShapeVertex::from_xy(0.01085, -3.7e-05, color),
+ ShapeVertex::from_xy(0.009926, 0.000995, color),
+ ShapeVertex::from_xy(0.008923, 0.001964, color),
+ ShapeVertex::from_xy(0.007848, 0.002855, color),
+ ShapeVertex::from_xy(0.006706, 0.003652, color),
+ ShapeVertex::from_xy(0.005501, 0.004339, color),
+ ShapeVertex::from_xy(0.004238, 0.004901, color),
+ ShapeVertex::from_xy(0.002923, 0.005322, color),
+ ShapeVertex::from_xy(0.00156, 0.005586, color),
+ ],
+ indices: vec![97, 111, 96, 111, 112, 96, 112, 113, 96, 113, 114, 96, 114, 115, 96, 115, 116, 96, 116, 117, 96, 117, 118, 96, 118, 119, 96, 119, 120, 96, 120, 121, 96, 121, 98, 96, 121, 122, 98, 122, 123, 98, 123, 124, 98, 124, 125, 98, 125, 126, 98, 126, 127, 98, 127, 128, 98, 128, 129, 98, 129, 130, 98, 130, 131, 98, 131, 132, 98, 132, 133, 98, 133, 134, 98, 134, 135, 98, 135, 97, 98, 1, 47, 0, 2, 47, 1, 2, 46, 47, 3, 46, 2, 3, 45, 46, 4, 45, 3, 4, 44, 45, 5, 44, 4, 5, 43, 44, 6, 43, 5, 6, 42, 43, 7, 42, 6, 7, 41, 42, 8, 41, 7, 8, 40, 41, 9, 40, 8, 9, 72, 40, 72, 39, 40, 9, 71, 72, 73, 39, 72, 9, 70, 71, 74, 39, 73, 9, 69, 70, 75, 39, 74, 9, 68, 69, 76, 39, 75, 10, 68, 9, 76, 38, 39, 10, 67, 68, 77, 38, 76, 10, 66, 67, 78, 38, 77, 10, 65, 66, 79, 38, 78, 10, 64, 65, 80, 38, 79, 11, 64, 10, 80, 37, 38, 11, 63, 64, 81, 37, 80, 11, 62, 63, 82, 37, 81, 12, 62, 11, 82, 36, 37, 12, 61, 62, 83, 36, 82, 12, 60, 61, 84, 36, 83, 97, 110, 111, 13, 60, 12, 84, 35, 36, 136, 97, 135, 13, 59, 60, 85, 35, 84, 13, 58, 59, 86, 35, 85, 13, 57, 58, 87, 35, 86, 14, 57, 13, 87, 34, 35, 137, 97, 136, 97, 109, 110, 14, 56, 57, 88, 34, 87, 14, 55, 56, 89, 34, 88, 15, 55, 14, 89, 33, 34, 15, 54, 55, 90, 33, 89, 15, 53, 54, 91, 33, 90, 138, 97, 137, 97, 108, 109, 15, 52, 53, 92, 33, 91, 92, 32, 33, 16, 52, 15, 16, 51, 52, 93, 32, 92, 16, 50, 51, 94, 32, 93, 16, 49, 50, 95, 32, 94, 16, 48, 49, 48, 32, 95, 16, 32, 48, 16, 31, 32, 17, 31, 16, 139, 97, 138, 97, 107, 108, 17, 30, 31, 18, 30, 17, 140, 97, 139, 97, 106, 107, 18, 29, 30, 19, 29, 18, 19, 28, 29, 20, 28, 19, 141, 97, 140, 97, 105, 106, 20, 27, 28, 21, 27, 20, 21, 26, 27, 22, 26, 21, 22, 25, 26, 23, 25, 22, 142, 97, 141, 97, 104, 105, 23, 24, 25, 143, 97, 142, 97, 103, 104, 144, 97, 143, 97, 102, 103, 145, 97, 144, 97, 101, 102, 146, 97, 145, 97, 100, 101, 99, 97, 146, 97, 99, 100]
+ }
+}
diff --git a/bin/app/src/shape/mod.rs b/bin/app/src/shape/mod.rs
index d97cd31c6..7c096a2d2 100644
--- a/bin/app/src/shape/mod.rs
+++ b/bin/app/src/shape/mod.rs
@@ -44,3 +44,9 @@ pub use switch::create_switch;
mod confirm;
pub use confirm::create_confirm;
+
+mod circle;
+pub use circle::create_circle;
+
+mod logo;
+pub use logo::create_logo;