luboslenco 1 anno fa
parent
commit
6f27383e2c
46 ha cambiato i file con 871 aggiunte e 489 eliminazioni
  1. BIN
      armorforge/Assets/default_brush.arm
  2. BIN
      armorforge/Assets/default_material.arm
  3. 24 4
      armorforge/Sources/tab_objects.ts
  4. BIN
      armorlab/Assets/default_brush.arm
  5. 5 5
      armorlab/Sources/nodes/image_texture_node.ts
  6. 8 2
      armorlab/Sources/nodes/inpaint_node.ts
  7. 4 4
      armorlab/Sources/nodes/photo_to_pbr_node.ts
  8. 1 1
      armorlab/Sources/nodes/text_to_photo_node.ts
  9. 7 2
      armorlab/Sources/nodes/tiling_node.ts
  10. 1 1
      armorlab/Sources/nodes/variance_node.ts
  11. BIN
      armorpaint/Assets/default_brush.arm
  12. BIN
      armorpaint/Assets/default_material.arm
  13. 1 1
      armorpaint/Sources/import_folder.ts
  14. 8 8
      armorpaint/Sources/nodes/brush_output_node.ts
  15. 2 2
      armorpaint/Sources/nodes/input_node.ts
  16. 5 5
      armorpaint/Sources/nodes/tex_image_node.ts
  17. BIN
      armorsculpt/Assets/default_brush.arm
  18. BIN
      armorsculpt/Assets/default_material.arm
  19. 7 7
      armorsculpt/Sources/tab_layers.ts
  20. 25 5
      base/Sources/box_export.ts
  21. 221 50
      base/Sources/box_preferences.ts
  22. 14 9
      base/Sources/context.ts
  23. 2 2
      base/Sources/export_arm.ts
  24. 2 2
      base/Sources/import_arm.ts
  25. 17 17
      base/Sources/import_blend_material.ts
  26. 2 2
      base/Sources/nodes/float_node.ts
  27. 6 6
      base/Sources/nodes/math_node.ts
  28. 3 3
      base/Sources/nodes/random_node.ts
  29. 3 3
      base/Sources/nodes/separate_vector_node.ts
  30. 3 3
      base/Sources/nodes/time_node.ts
  31. 3 3
      base/Sources/nodes/vector_math_node.ts
  32. 3 3
      base/Sources/nodes/vector_node.ts
  33. 119 119
      base/Sources/nodes_material.ts
  34. 14 15
      base/Sources/parser_logic.ts
  35. 30 24
      base/Sources/parser_material.ts
  36. 17 4
      base/Sources/project.ts
  37. 56 20
      base/Sources/tab_materials.ts
  38. 4 4
      base/Sources/tab_textures.ts
  39. 88 23
      base/Sources/ui_header.ts
  40. 29 7
      base/Sources/ui_menu.ts
  41. 4 2
      base/Sources/ui_menubar.ts
  42. 55 13
      base/Sources/ui_nodes.ts
  43. 20 4
      base/Sources/ui_view2d.ts
  44. 0 35
      misc/pad/Assets/themes/dark.json
  45. 57 68
      misc/pad/Sources/main.ts
  46. 1 1
      misc/pad/project.js

BIN
armorforge/Assets/default_brush.arm


BIN
armorforge/Assets/default_material.arm


+ 24 - 4
armorforge/Sources/tab_objects.ts

@@ -66,7 +66,11 @@ function tab_objects_draw_list(ui: zui_t, list_handle: zui_handle_t, current_obj
 
 	if (current_object.children.length > 0) {
 		zui_row([1 / 13, 12 / 13]);
-		b = zui_panel(zui_nest(list_handle, tab_objects_line_counter, {selected: true}), "", true, false, false);
+		let h: zui_handle_t = zui_nest(list_handle, tab_objects_line_counter);
+		if (h.init) {
+			h.selected = true;
+		}
+		b = zui_panel(h, "", true, false, false);
 		zui_text(current_object.name);
 	}
 	else {
@@ -120,7 +124,12 @@ function tab_objects_draw(htab: zui_handle_t) {
 		}
 		zui_end_sticky();
 
-		if (zui_panel(zui_handle(__ID__, {selected: true}), "Outliner")) {
+		let outliner_handle: zui_handle_t = zui_handle(__ID__);
+		if (outliner_handle.init) {
+			outliner_handle.selected = true;
+		}
+
+		if (zui_panel(outliner_handle, "Outliner")) {
 			// ui.indent();
 			ui._y -= zui_ELEMENT_OFFSET(ui);
 
@@ -134,7 +143,12 @@ function tab_objects_draw(htab: zui_handle_t) {
 			// ui.unindent();
 		}
 
-		if (zui_panel(zui_handle(__ID__, {selected: true}), "Properties")) {
+		let properties_handle: zui_handle_t = zui_handle(__ID__);
+		if (properties_handle.init) {
+			properties_handle.selected = true;
+		}
+
+		if (zui_panel(properties_handle, "Properties")) {
 			// ui.indent();
 
 			if (context_raw.selected_object != null) {
@@ -263,7 +277,13 @@ function tab_objects_draw(htab: zui_handle_t) {
 
 				if (context_raw.selected_object.name == "Scene") {
 					let p = scene_world;
-					p.strength = zui_slider(zui_handle(__ID__, {value: p.strength}), "Environment", 0.0, 5.0, true);
+
+					let p_handle: zui_handle_t = zui_handle(__ID__);
+					if (p_handle.init) {
+						p_handle.value = p.strength;
+					}
+
+					p.strength = zui_slider(p_handle, "Environment", 0.0, 5.0, true);
 				}
 				else if (context_raw.selected_object.ext_type == "light_object_t") {
 					let light = context_raw.selected_object.ext;

BIN
armorlab/Assets/default_brush.arm


+ 5 - 5
armorlab/Sources/nodes/image_texture_node.ts

@@ -64,7 +64,7 @@ let image_texture_node_def: zui_node_t = {
 			name: _tr("Alpha"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 1.0,
+			default_value: f32_array_create_x(1.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -76,8 +76,8 @@ let image_texture_node_def: zui_node_t = {
 			name: _tr("file"),
 			type: "ENUM",
 			output: -1,
-			default_value: 0,
-			data: "",
+			default_value: f32_array_create_x(0),
+			data: u8_array_create_from_string(""),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -87,8 +87,8 @@ let image_texture_node_def: zui_node_t = {
 			name: _tr("color_space"),
 			type: "ENUM",
 			output: -1,
-			default_value: 0,
-			data: ["linear", "srgb"],
+			default_value: f32_array_create_x(0),
+			data: u8_array_create_from_string("linear\0srgb"),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,

+ 8 - 2
armorlab/Sources/nodes/inpaint_node.ts

@@ -51,7 +51,13 @@ function inpaint_node_init() {
 function inpaint_node_buttons(ui: zui_t, nodes: zui_nodes_t, node: zui_node_t) {
 	inpaint_node_auto = node.buttons[0].default_value == 0 ? false : true;
 	if (!inpaint_node_auto) {
-		inpaint_node_strength = zui_slider(zui_handle(__ID__, { value: inpaint_node_strength }), tr("strength"), 0, 1, true);
+
+		let inpaint_node_strength_handle: zui_handle_t = zui_handle(__ID__);
+		if (inpaint_node_strength_handle.init) {
+			inpaint_node_strength_handle.value = inpaint_node_strength;
+		}
+
+		inpaint_node_strength = zui_slider(inpaint_node_strength_handle, tr("strength"), 0, 1, true);
 		inpaint_node_prompt = zui_text_area(zui_handle(__ID__), zui_align_t.LEFT, true, tr("prompt"), true);
 		node.buttons[1].height = 1 + string_split(inpaint_node_prompt, "\n").length;
 	}
@@ -223,7 +229,7 @@ let inpaint_node_def: zui_node_t = {
 			name: _tr("auto"),
 			type: "BOOL",
 			output: 0,
-			default_value: true,
+			default_value: f32_array_create_x(1),
 			data: null,
 			min: 0.0,
 			max: 1.0,

+ 4 - 4
armorlab/Sources/nodes/photo_to_pbr_node.ts

@@ -217,7 +217,7 @@ let photo_to_pbr_node_def: zui_node_t = {
 			name: _tr("Occlusion"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 1.0,
+			default_value: f32_array_create_x(1.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -229,7 +229,7 @@ let photo_to_pbr_node_def: zui_node_t = {
 			name: _tr("Roughness"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 1.0,
+			default_value: f32_array_create_x(1.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -241,7 +241,7 @@ let photo_to_pbr_node_def: zui_node_t = {
 			name: _tr("Metallic"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.0,
+			default_value: f32_array_create_x(0.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -265,7 +265,7 @@ let photo_to_pbr_node_def: zui_node_t = {
 			name: _tr("Height"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 1.0,
+			default_value: f32_array_create_x(1.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,

+ 1 - 1
armorlab/Sources/nodes/text_to_photo_node.ts

@@ -277,7 +277,7 @@ let text_to_photo_node_def: zui_node_t = {
 			name: _tr("tiling"),
 			type: "BOOL",
 			output: 0,
-			default_value: false,
+			default_value: f32_array_create_x(0),
 			data: null,
 			min: 0.0,
 			max: 1.0,

+ 7 - 2
armorlab/Sources/nodes/tiling_node.ts

@@ -27,7 +27,12 @@ function tiling_node_init() {
 function tiling_node_buttons(ui: zui_t, nodes: zui_nodes_t, node: zui_node_t) {
 	tiling_node_auto = node.buttons[0].default_value == 0 ? false : true;
 	if (!tiling_node_auto) {
-		tiling_node_strength = zui_slider(zui_handle(__ID__, { value: tiling_node_strength }), tr("strength"), 0, 1, true);
+		let tiling_node_strength_handle: zui_handle_t = zui_handle(__ID__);
+		if (tiling_node_strength_handle.init) {
+			tiling_node_strength_handle.value = tiling_node_strength;
+		}
+
+		tiling_node_strength = zui_slider(tiling_node_strength_handle, tr("strength"), 0, 1, true);
 		tiling_node_prompt = zui_text_area(zui_handle(__ID__), zui_align_t.LEFT, true, tr("prompt"), true);
 		node.buttons[1].height = 1 + string_split(tiling_node_prompt, "\n").length;
 	}
@@ -136,7 +141,7 @@ let tiling_node_def: zui_node_t = {
 			name: _tr("auto"),
 			type: "BOOL",
 			output: 0,
-			default_value: true,
+			default_value: f32_array_create_x(1),
 			data: null,
 			min: 0.0,
 			max: 1.0,

+ 1 - 1
armorlab/Sources/nodes/variance_node.ts

@@ -106,7 +106,7 @@ let variance_node_def: zui_node_t = {
 			name: _tr("Strength"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.5,
+			default_value: f32_array_create_x(0.5),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,

BIN
armorpaint/Assets/default_brush.arm


BIN
armorpaint/Assets/default_material.arm


+ 1 - 1
armorpaint/Sources/import_folder.ts

@@ -125,7 +125,7 @@ function import_folder_run(path: string) {
 
 function import_folder_place_image_node(nodes: zui_nodes_t, canvas: zui_node_canvas_t, asset: string, ny: i32, to_id: i32, to_socket: i32) {
 	let n: zui_node_t = nodes_material_create_node("TEX_IMAGE");
-	n.buttons[0].default_value = base_get_asset_index(asset);
+	n.buttons[0].default_value = f32_array_create_x(base_get_asset_index(asset));
 	n.x = 72;
 	n.y = ny;
 	let l: zui_node_link_t = { id: zui_get_link_id(canvas.links), from_id: n.id, from_socket: 0, to_id: to_id, to_socket: to_socket };

+ 8 - 8
armorpaint/Sources/nodes/brush_output_node.ts

@@ -155,7 +155,7 @@ function brush_output_node_run(self: brush_output_node_t, from: i32) {
 // 			name: _tr("Position"),
 // 			type: "VECTOR",
 // 			color: 0xff63c763,
-// 			default_value: f32([0.0, 0.0, 0.0]),
+// 			default_value: f32_array_create_xyz(0.0, 0.0, 0.0),
 //			min: 0.0,
 //			max: 1.0,
 //			precision: 100,
@@ -167,7 +167,7 @@ function brush_output_node_run(self: brush_output_node_t, from: i32) {
 // 			name: _tr("Radius"),
 // 			type: "VALUE",
 // 			color: 0xffa1a1a1,
-// 			default_value: 1.0,
+// 			default_value: f32_array_create_x(1.0),
 //			min: 0.0,
 //			max: 1.0,
 //			precision: 100,
@@ -179,7 +179,7 @@ function brush_output_node_run(self: brush_output_node_t, from: i32) {
 // 			name: _tr("Scale"),
 // 			type: "VALUE",
 // 			color: 0xffa1a1a1,
-// 			default_value: 1.0,
+// 			default_value: f32_array_create_x(1.0),
 //			min: 0.0,
 //			max: 1.0,
 //			precision: 100,
@@ -191,7 +191,7 @@ function brush_output_node_run(self: brush_output_node_t, from: i32) {
 // 			name: _tr("Angle"),
 // 			type: "VALUE",
 // 			color: 0xffa1a1a1,
-// 			default_value: 0.0,
+// 			default_value: f32_array_create_x(0.0),
 //			min: 0.0,
 //			max: 1.0,
 //			precision: 100,
@@ -203,7 +203,7 @@ function brush_output_node_run(self: brush_output_node_t, from: i32) {
 // 			name: _tr("Opacity"),
 // 			type: "VALUE",
 // 			color: 0xffa1a1a1,
-// 			default_value: 1.0,
+// 			default_value: f32_array_create_x(1.0),
 //			min: 0.0,
 //			max: 1.0,
 //			precision: 100,
@@ -215,7 +215,7 @@ function brush_output_node_run(self: brush_output_node_t, from: i32) {
 // 			name: _tr("Hardness"),
 // 			type: "VALUE",
 // 			color: 0xffa1a1a1,
-// 			default_value: 1.0,
+// 			default_value: f32_array_create_x(1.0),
 //			min: 0.0,
 //			max: 1.0,
 //			precision: 100,
@@ -227,7 +227,7 @@ function brush_output_node_run(self: brush_output_node_t, from: i32) {
 // 			name: _tr("Stencil"),
 // 			type: "VALUE",
 // 			color: 0xffa1a1a1,
-// 			default_value: 1.0,
+// 			default_value: f32_array_create_x(1.0),
 //			min: 0.0,
 //			max: 1.0,
 //			precision: 100,
@@ -240,7 +240,7 @@ function brush_output_node_run(self: brush_output_node_t, from: i32) {
 // 			name: _tr("Directional"),
 // 			type: "BOOL",
 // 			output: 0,
-// 			default_value: false,
+// 			default_value: f32_array_create_x(0),
 //			data: null,
 //			min: 0.0,
 //			max: 1.0,

+ 2 - 2
armorpaint/Sources/nodes/input_node.ts

@@ -141,7 +141,7 @@ let input_node_def: zui_node_t = {
 			name: _tr("Lazy Radius"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.0,
+			default_value: f32_array_create_x(0.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -153,7 +153,7 @@ let input_node_def: zui_node_t = {
 			name: _tr("Lazy Step"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.0,
+			default_value: f32_array_create_x(0.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,

+ 5 - 5
armorpaint/Sources/nodes/tex_image_node.ts

@@ -63,7 +63,7 @@ let tex_image_node_def: zui_node_t = {
 			name: _tr("Alpha"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 1.0,
+			default_value: f32_array_create_x(1.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -75,8 +75,8 @@ let tex_image_node_def: zui_node_t = {
 			name: _tr("file"),
 			type: "ENUM",
 			output: -1,
-			default_value: 0,
-			data: "",
+			default_value: f32_array_create_x(0),
+			data: u8_array_create_from_string(""),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -86,8 +86,8 @@ let tex_image_node_def: zui_node_t = {
 			name: _tr("color_space"),
 			type: "ENUM",
 			output: -1,
-			default_value: 0,
-			data: ["linear", "srgb"],
+			default_value: f32_array_create_x(0),
+			data: u8_array_create_from_string("linear\0srgb"),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,

BIN
armorsculpt/Assets/default_brush.arm


BIN
armorsculpt/Assets/default_material.arm


+ 7 - 7
armorsculpt/Sources/tab_layers.ts

@@ -318,9 +318,9 @@ function tab_layers_draw_layer_slot_full(l: slot_layer_t, i: i32) {
 
 	if (hasPanel) {
 		ui._y += center;
-		let layerPanel = zui_nest(zui_handle(__ID__), l.id);
-		layerPanel.selected = l.show_panel;
-		l.show_panel = zui_panel(layerPanel, "", true, false, false);
+		let layer_panel = zui_nest(zui_handle(__ID__), l.id);
+		layer_panel.selected = l.show_panel;
+		l.show_panel = zui_panel(layer_panel, "", true, false, false);
 		ui._y -= center;
 	}
 
@@ -352,10 +352,10 @@ function tab_layers_draw_layer_slot_full(l: slot_layer_t, i: i32) {
 
 function tab_layers_combo_object(ui: zui_t, l: slot_layer_t, label: bool = false): zui_handle_t {
 	let ar = [tr("Shared")];
-	let objectHandle = zui_nest(zui_handle(__ID__), l.id);
-	objectHandle.position = l.object_mask;
-	l.object_mask = zui_combo(objectHandle, ar, tr("Object"), label, zui_align_t.LEFT);
-	return objectHandle;
+	let object_handle = zui_nest(zui_handle(__ID__), l.id);
+	object_handle.position = l.object_mask;
+	l.object_mask = zui_combo(object_handle, ar, tr("Object"), label, zui_align_t.LEFT);
+	return object_handle;
 }
 
 function tab_layers_layer_toggle_visible(l: slot_layer_t) {

+ 25 - 5
base/Sources/box_export.ts

@@ -100,14 +100,26 @@ function box_export_tab_export_textures(ui: zui_t, title: string, bake_material:
 
 		zui_row([0.5, 0.5]);
 		if (base_bits_handle.position == texture_bits_t.BITS8) {
-			context_raw.format_type = zui_combo(zui_handle(__ID__, { position: context_raw.format_type }), ["png", "jpg"], tr("Format"), true);
+			let h: zui_handle_t = zui_handle(__ID__);
+			if (h.init) {
+				h.position = context_raw.format_type;
+			}
+			context_raw.format_type = zui_combo(h, ["png", "jpg"], tr("Format"), true);
 		}
 		else {
-			context_raw.format_type = zui_combo(zui_handle(__ID__, { position: context_raw.format_type }), ["exr"], tr("Format"), true);
+			let h: zui_handle_t = zui_handle(__ID__);
+			if (h.init) {
+				h.position = context_raw.format_type;
+			}
+			context_raw.format_type = zui_combo(h, ["exr"], tr("Format"), true);
 		}
 
 		ui.enabled = context_raw.format_type == texture_ldr_format_t.JPG && base_bits_handle.position == texture_bits_t.BITS8;
-		context_raw.format_quality = zui_slider(zui_handle(__ID__, { value: context_raw.format_quality }), tr("Quality"), 0.0, 100.0, true, 1);
+		let h_quality: zui_handle_t = zui_handle(__ID__);
+		if (h_quality.init) {
+			h_quality.value = context_raw.format_quality;
+		}
+		context_raw.format_quality = zui_slider(h_quality, tr("Quality"), 0.0, 100.0, true, 1);
 		ui.enabled = true;
 
 		///if is_paint
@@ -189,7 +201,11 @@ function box_export_tab_presets(ui: zui_t) {
 				let tab_vertical: bool = config_raw.touch_ui;
 				if (zui_tab(zui_handle(__ID__), tr("New Preset"), tab_vertical)) {
 					zui_row([0.5, 0.5]);
-					let preset_name: string = zui_text_input(zui_handle(__ID__, { text: "new_preset" }), tr("Name"));
+					let h_preset: zui_handle_t = zui_handle(__ID__);
+					if (h_preset.init) {
+						h_preset.text = "new_preset";
+					}
+					let preset_name: string = zui_text_input(h_preset, tr("Name"));
 					if (zui_button(tr("OK")) || ui.is_return_down) {
 						box_export_new_preset(preset_name);
 						box_export_fetch_presets();
@@ -338,7 +354,11 @@ function box_export_tab_export_mesh(ui: zui_t, htab: zui_handle_t) {
 
 		zui_row([1 / 2, 1 / 2]);
 
-		context_raw.export_mesh_format = zui_combo(zui_handle(__ID__, { position: context_raw.export_mesh_format }), ["obj", "arm"], tr("Format"), true);
+		let h_export_mesh_format: zui_handle_t = zui_handle(__ID__);
+		if (h_export_mesh_format.init) {
+			h_export_mesh_format.position = context_raw.export_mesh_format;
+		}
+		context_raw.export_mesh_format = zui_combo(h_export_mesh_format, ["obj", "arm"], tr("Format"), true);
 
 		let ar: string[] = [tr("All")];
 		for (let i: i32 = 0; i < project_paint_objects.length; ++i) {

+ 221 - 50
base/Sources/box_preferences.ts

@@ -16,7 +16,10 @@ function box_preferences_show() {
 				box_preferences_locales = translator_get_supported_locales();
 			}
 
-			let locale_handle: zui_handle_t = zui_handle(__ID__, { position: array_index_of(box_preferences_locales, config_raw.locale) });
+			let locale_handle: zui_handle_t = zui_handle(__ID__);
+			if (locale_handle.init) {
+				locale_handle.position = array_index_of(box_preferences_locales, config_raw.locale);
+			}
 			zui_combo(locale_handle, box_preferences_locales, tr("Language"), true);
 			if (locale_handle.changed) {
 				let locale_code: string = box_preferences_locales[locale_handle.position];
@@ -25,7 +28,10 @@ function box_preferences_show() {
 				ui_base_tag_ui_redraw();
 			}
 
-			let hscale: zui_handle_t = zui_handle(__ID__, { value: config_raw.window_scale });
+			let hscale: zui_handle_t = zui_handle(__ID__);
+			if (hscale.init) {
+				hscale.value = config_raw.window_scale;
+			}
 			zui_slider(hscale, tr("UI Scale"), 1.0, 4.0, true, 10);
 			if (context_raw.hscale_was_changed && !ui.input_down) {
 				context_raw.hscale_was_changed = false;
@@ -39,37 +45,65 @@ function box_preferences_show() {
 				context_raw.hscale_was_changed = true;
 			}
 
-			let hspeed: zui_handle_t = zui_handle(__ID__, { value: config_raw.camera_zoom_speed });
+			let hspeed: zui_handle_t = zui_handle(__ID__);
+			if (hspeed.init) {
+				hspeed.value = config_raw.camera_zoom_speed;
+			}
 			config_raw.camera_zoom_speed = zui_slider(hspeed, tr("Camera Zoom Speed"), 0.1, 4.0, true);
 
-			hspeed = zui_handle(__ID__, { value: config_raw.camera_rotation_speed });
+			hspeed = zui_handle(__ID__);
+			if (hspeed.init) {
+				hspeed.value = config_raw.camera_rotation_speed;
+			}
 			config_raw.camera_rotation_speed = zui_slider(hspeed, tr("Camera Rotation Speed"), 0.1, 4.0, true);
 
-			hspeed = zui_handle(__ID__, { value: config_raw.camera_pan_speed });
+			hspeed = zui_handle(__ID__);
+			if (hspeed.init) {
+				hspeed.value = config_raw.camera_pan_speed;
+			}
 			config_raw.camera_pan_speed = zui_slider(hspeed, tr("Camera Pan Speed"), 0.1, 4.0, true);
 
-			let zoom_direction_handle: zui_handle_t = zui_handle(__ID__, { position: config_raw.zoom_direction });
+			let zoom_direction_handle: zui_handle_t = zui_handle(__ID__);
+			if (zoom_direction_handle.init) {
+				zoom_direction_handle.position = config_raw.zoom_direction;
+			}
 			zui_combo(zoom_direction_handle, [tr("Vertical"), tr("Vertical Inverted"), tr("Horizontal"), tr("Horizontal Inverted"), tr("Vertical and Horizontal"), tr("Vertical and Horizontal Inverted")], tr("Direction to Zoom"), true);
 			if (zoom_direction_handle.changed) {
 				config_raw.zoom_direction = zoom_direction_handle.position;
 			}
 
-			config_raw.wrap_mouse = zui_check(zui_handle(__ID__, { selected: config_raw.wrap_mouse }), tr("Wrap Mouse"));
+			let h_wrap_mouse: zui_handle_t = zui_handle(__ID__);
+			if (h_wrap_mouse.init) {
+				h_wrap_mouse.selected = config_raw.wrap_mouse;
+			}
+			config_raw.wrap_mouse = zui_check(h_wrap_mouse, tr("Wrap Mouse"));
 			if (ui.is_hovered) {
 				zui_tooltip(tr("Wrap mouse around view boundaries during camera control"));
 			}
 
-			config_raw.node_preview = zui_check(zui_handle(__ID__, { selected: config_raw.node_preview }), tr("Show Node Preview"));
+			let h_node_preview: zui_handle_t = zui_handle(__ID__);
+			if (h_node_preview.init) {
+				h_node_preview.selected = config_raw.node_preview;
+			}
+			config_raw.node_preview = zui_check(h_node_preview, tr("Show Node Preview"));
 
 			ui.changed = false;
-			config_raw.show_asset_names = zui_check(zui_handle(__ID__, { selected: config_raw.show_asset_names }), tr("Show Asset Names"));
+			let h_show_asset_names: zui_handle_t = zui_handle(__ID__);
+			if (h_show_asset_names.init) {
+				h_show_asset_names.selected = config_raw.show_asset_names;
+			}
+			config_raw.show_asset_names = zui_check(h_show_asset_names, tr("Show Asset Names"));
 			if (ui.changed) {
 				ui_base_tag_ui_redraw();
 			}
 
 			///if !(krom_android || krom_ios)
 			ui.changed = false;
-			config_raw.touch_ui = zui_check(zui_handle(__ID__, { selected: config_raw.touch_ui }), tr("Touch UI"));
+			let h_touch_ui: zui_handle_t = zui_handle(__ID__);
+			if (h_touch_ui.init) {
+				h_touch_ui.selected = config_raw.touch_ui;
+			}
+			config_raw.touch_ui = zui_check(h_touch_ui, tr("Touch UI"));
 			if (ui.changed) {
 				zui_set_touch_scroll(config_raw.touch_ui);
 				zui_set_touch_hold(config_raw.touch_ui);
@@ -80,9 +114,13 @@ function box_preferences_show() {
 			}
 			///end
 
-			config_raw.splash_screen = zui_check(zui_handle(__ID__, { selected: config_raw.splash_screen }), tr("Splash Screen"));
+			let h_splash_screen: zui_handle_t = zui_handle(__ID__);
+			if (h_splash_screen.init) {
+				h_splash_screen.selected = config_raw.splash_screen;
+			}
+			config_raw.splash_screen = zui_check(h_splash_screen, tr("Splash Screen"));
 
-			// Zui.text("Node Editor");
+			// zui_text("Node Editor");
 			// let grid_snap: bool = Zui.check(Zui.handle("boxpreferences_11", { selected: false }), "Grid Snap");
 
 			zui_end_element();
@@ -136,7 +174,10 @@ function box_preferences_show() {
 			if (box_preferences_themes == null) {
 				box_preferences_fetch_themes();
 			}
-			box_preferences_theme_handle = zui_handle(__ID__, { position: box_preferences_get_theme_index() });
+			box_preferences_theme_handle = zui_handle(__ID__);
+			if (box_preferences_theme_handle.init) {
+				box_preferences_theme_handle.position = box_preferences_get_theme_index();
+			}
 
 			zui_begin_sticky();
 			zui_row([1 / 4, 1 / 4, 1 / 4, 1 / 4]);
@@ -151,7 +192,11 @@ function box_preferences_show() {
 				ui_box_show_custom(function (ui: zui_t) {
 					if (zui_tab(zui_handle(__ID__), tr("New Theme"))) {
 						zui_row([0.5, 0.5]);
-						let theme_name: string = zui_text_input(zui_handle(__ID__, { text: "new_theme" }), tr("Name"));
+						let h: zui_handle_t = zui_handle(__ID__);
+						if (h.init) {
+							h.text = "new_theme";
+						}
+						let theme_name: string = zui_text_input(h, tr("Name"));
 						if (zui_button(tr("OK")) || ui.is_return_down) {
 							let template: string = json_stringify(base_theme);
 							if (!ends_with(theme_name, ".json")) {
@@ -193,7 +238,10 @@ function box_preferences_show() {
 			let hlist: zui_handle_t = zui_handle(__ID__);
 
 			// Viewport color
-			let h: zui_handle_t = zui_nest(hlist, i++, { color: box_preferences_world_color });
+			let h: zui_handle_t = zui_nest(hlist, i++);
+			if (h.init) {
+				h.color = box_preferences_world_color;
+			}
 			zui_row([1 / 8, 7 / 8]);
 			zui_text("", 0, h.color);
 			if (ui.is_hovered && ui.input_released) {
@@ -294,7 +342,10 @@ function box_preferences_show() {
 		}
 
 		if (zui_tab(box_preferences_htab, tr("Usage"), true)) {
-			context_raw.undo_handle = zui_handle(__ID__, { value: config_raw.undo_steps });
+			context_raw.undo_handle = zui_handle(__ID__);
+			if (context_raw.undo_handle.init) {
+				context_raw.undo_handle.value = config_raw.undo_steps;
+			}
 			config_raw.undo_steps = math_floor(zui_slider(context_raw.undo_handle, tr("Undo Steps"), 1, 64, false, 1));
 			if (config_raw.undo_steps < 1) {
 				config_raw.undo_steps = math_floor(context_raw.undo_handle.value = 1);
@@ -319,12 +370,19 @@ function box_preferences_show() {
 			}
 
 			///if is_paint
-			config_raw.dilate_radius = math_floor(zui_slider(zui_handle(__ID__, { value: config_raw.dilate_radius }), tr("Dilate Radius"), 0.0, 16.0, true, 1));
+			let h_dilate_radius: zui_handle_t = zui_handle(__ID__);
+			if (h_dilate_radius.init) {
+				h_dilate_radius.value = config_raw.dilate_radius;
+			}
+			config_raw.dilate_radius = math_floor(zui_slider(h_dilate_radius, tr("Dilate Radius"), 0.0, 16.0, true, 1));
 			if (ui.is_hovered) {
 				zui_tooltip(tr("Dilate painted textures to prevent seams"));
 			}
 
-			let dilate_handle: zui_handle_t = zui_handle(__ID__, { position: config_raw.dilate });
+			let dilate_handle: zui_handle_t = zui_handle(__ID__);
+			if (dilate_handle.init) {
+				dilate_handle.position = config_raw.dilate;
+			}
 			zui_combo(dilate_handle, [tr("Instant"), tr("Delayed")], tr("Dilate"), true);
 			if (dilate_handle.changed) {
 				config_raw.dilate = dilate_handle.position;
@@ -332,20 +390,29 @@ function box_preferences_show() {
 			///end
 
 			///if is_lab
-			let workspace_handle: zui_handle_t = zui_handle(__ID__, { position: config_raw.workspace });
+			let workspace_handle: zui_handle_t = zui_handle(__ID__);
+			if (workspace_handle.init) {
+				workspace_handle.position = config_raw.workspace;
+			}
 			zui_combo(workspace_handle, [tr("3D View"), tr("2D View")], tr("Default Workspace"), true);
 			if (workspace_handle.changed) {
 				config_raw.workspace = workspace_handle.position;
 			}
 			///end
 
-			let camera_controls_handle: zui_handle_t = zui_handle(__ID__, { position: config_raw.camera_controls });
+			let camera_controls_handle: zui_handle_t = zui_handle(__ID__);
+			if (camera_controls_handle.init) {
+				camera_controls_handle.position = config_raw.camera_controls;
+			}
 			zui_combo(camera_controls_handle, [tr("Orbit"), tr("Rotate"), tr("Fly")], tr("Default Camera Controls"), true);
 			if (camera_controls_handle.changed) {
 				config_raw.camera_controls = camera_controls_handle.position;
 			}
 
-			let layer_res_handle: zui_handle_t = zui_handle(__ID__, { position: config_raw.layer_res });
+			let layer_res_handle: zui_handle_t = zui_handle(__ID__);
+			if (layer_res_handle.init) {
+				layer_res_handle.position = config_raw.layer_res;
+			}
 
 			///if is_paint
 			///if (krom_android || krom_ios)
@@ -367,17 +434,26 @@ function box_preferences_show() {
 				config_raw.layer_res = layer_res_handle.position;
 			}
 
-			let server_handle: zui_handle_t = zui_handle(__ID__, { text: config_raw.server });
+			let server_handle: zui_handle_t = zui_handle(__ID__);
+			if (server_handle.init) {
+				server_handle.text = config_raw.server;
+			}
 			config_raw.server = zui_text_input(server_handle, tr("Cloud Server"));
 
 			///if (is_paint || is_sculpt)
-			let material_live_handle: zui_handle_t = zui_handle(__ID__, {selected: config_raw.material_live });
+			let material_live_handle: zui_handle_t = zui_handle(__ID__);
+			if (material_live_handle.init) {
+				material_live_handle.selected = config_raw.material_live;
+			}
 			config_raw.material_live = zui_check(material_live_handle, tr("Live Material Preview"));
 			if (ui.is_hovered) {
 				zui_tooltip(tr("Instantly update material preview on node change"));
 			}
 
-			let brush_live_handle: zui_handle_t = zui_handle(__ID__, { selected: config_raw.brush_live });
+			let brush_live_handle: zui_handle_t = zui_handle(__ID__);
+			if (brush_live_handle.init) {
+				brush_live_handle.selected = config_raw.brush_live;
+			}
 			config_raw.brush_live = zui_check(brush_live_handle, tr("Live Brush Preview"));
 			if (ui.is_hovered) {
 				zui_tooltip(tr("Draw live brush preview in viewport"));
@@ -386,14 +462,20 @@ function box_preferences_show() {
 				context_raw.ddirty = 2;
 			}
 
-			let brush_3d_handle: zui_handle_t = zui_handle(__ID__, { selected: config_raw.brush_3d });
+			let brush_3d_handle: zui_handle_t = zui_handle(__ID__);
+			if (brush_3d_handle.init) {
+				brush_3d_handle.selected = config_raw.brush_3d;
+			}
 			config_raw.brush_3d = zui_check(brush_3d_handle, tr("3D Cursor"));
 			if (brush_3d_handle.changed) {
 				make_material_parse_paint_material();
 			}
 
 			ui.enabled = config_raw.brush_3d;
-			let brush_depth_reject_handle: zui_handle_t = zui_handle(__ID__, { selected: config_raw.brush_depth_reject });
+			let brush_depth_reject_handle: zui_handle_t = zui_handle(__ID__);
+			if (brush_depth_reject_handle.init) {
+				brush_depth_reject_handle.selected = config_raw.brush_depth_reject;
+			}
 			config_raw.brush_depth_reject = zui_check(brush_depth_reject_handle, tr("Depth Reject"));
 			if (brush_depth_reject_handle.changed) {
 				make_material_parse_paint_material();
@@ -401,14 +483,20 @@ function box_preferences_show() {
 
 			zui_row([0.5, 0.5]);
 
-			let brush_angle_reject_handle: zui_handle_t = zui_handle(__ID__, { selected: config_raw.brush_angle_reject });
+			let brush_angle_reject_handle: zui_handle_t = zui_handle(__ID__);
+			if (brush_angle_reject_handle.init) {
+				brush_angle_reject_handle.selected = config_raw.brush_angle_reject;
+			}
 			config_raw.brush_angle_reject = zui_check(brush_angle_reject_handle, tr("Angle Reject"));
 			if (brush_angle_reject_handle.changed) {
 				make_material_parse_paint_material();
 			}
 
 			if (!config_raw.brush_angle_reject) ui.enabled = false;
-			let angle_dot_handle: zui_handle_t = zui_handle(__ID__, { value: context_raw.brush_angle_reject_dot });
+			let angle_dot_handle: zui_handle_t = zui_handle(__ID__);
+			if (angle_dot_handle.init) {
+				angle_dot_handle.value = context_raw.brush_angle_reject_dot;
+			}
 			context_raw.brush_angle_reject_dot = zui_slider(angle_dot_handle, tr("Angle"), 0.0, 1.0, true);
 			if (angle_dot_handle.changed) {
 				make_material_parse_paint_material();
@@ -417,7 +505,11 @@ function box_preferences_show() {
 			///end
 
 			///if is_lab
-			config_raw.gpu_inference = zui_check(zui_handle(__ID__, { selected: config_raw.gpu_inference }), tr("Use GPU"));
+			let h_gpu_inference: zui_handle_t = zui_handle(__ID__);
+			if (h_gpu_inference.init) {
+				h_gpu_inference.selected = config_raw.gpu_inference;
+			}
+			config_raw.gpu_inference = zui_check(h_gpu_inference, tr("Use GPU"));
 			if (ui.is_hovered) {
 				zui_tooltip(tr("Use GPU to accelerate node graph processing"));
 			}
@@ -433,12 +525,36 @@ function box_preferences_show() {
 
 		if (zui_tab(box_preferences_htab, pen_name, true)) {
 			zui_text(tr("Pressure controls"));
-			config_raw.pressure_radius = zui_check(zui_handle(__ID__, { selected: config_raw.pressure_radius }), tr("Brush Radius"));
-			config_raw.pressure_sensitivity = zui_slider(zui_handle(__ID__, { value: config_raw.pressure_sensitivity }), tr("Sensitivity"), 0.0, 10.0, true);
+			let h_pressure_radius: zui_handle_t = zui_handle(__ID__);
+			if (h_pressure_radius.init) {
+				h_pressure_radius.selected = config_raw.pressure_radius;
+			}
+			config_raw.pressure_radius = zui_check(h_pressure_radius, tr("Brush Radius"));
+
+			let h_pressure_sensitivity: zui_handle_t = zui_handle(__ID__);
+			if (h_pressure_sensitivity.init) {
+				h_pressure_sensitivity.value = config_raw.pressure_sensitivity;
+			}
+			config_raw.pressure_sensitivity = zui_slider(h_pressure_sensitivity, tr("Sensitivity"), 0.0, 10.0, true);
+
 			///if (is_paint || is_sculpt)
-			config_raw.pressure_hardness = zui_check(zui_handle(__ID__, { selected: config_raw.pressure_hardness }), tr("Brush Hardness"));
-			config_raw.pressure_opacity = zui_check(zui_handle(__ID__, { selected: config_raw.pressure_opacity }), tr("Brush Opacity"));
-			config_raw.pressure_angle = zui_check(zui_handle(__ID__, { selected: config_raw.pressure_angle }), tr("Brush Angle"));
+			let h_pressure_hardness: zui_handle_t = zui_handle(__ID__);
+			if (h_pressure_hardness.init) {
+				h_pressure_hardness.selected = config_raw.pressure_hardness;
+			}
+			config_raw.pressure_hardness = zui_check(h_pressure_hardness, tr("Brush Hardness"));
+
+			let h_pressure_opacity: zui_handle_t = zui_handle(__ID__);
+			if (h_pressure_opacity.init) {
+				h_pressure_opacity.selected = config_raw.pressure_opacity;
+			}
+			config_raw.pressure_opacity = zui_check(h_pressure_opacity, tr("Brush Opacity"));
+
+			let h_pressure_angle: zui_handle_t = zui_handle(__ID__);
+			if (h_pressure_angle.init) {
+				h_pressure_angle.selected = config_raw.pressure_angle;
+			}
+			config_raw.pressure_angle = zui_check(h_pressure_angle, tr("Brush Angle"));
 			///end
 
 			zui_end_element();
@@ -453,15 +569,38 @@ function box_preferences_show() {
 			}
 		}
 
-		context_raw.hssao = zui_handle(__ID__, { selected: config_raw.rp_ssao });
-		context_raw.hssr = zui_handle(__ID__, { selected: config_raw.rp_ssr });
-		context_raw.hbloom = zui_handle(__ID__, { selected: config_raw.rp_bloom });
-		context_raw.hsupersample = zui_handle(__ID__, { position: config_get_super_sample_quality(config_raw.rp_supersample) });
-		context_raw.hvxao = zui_handle(__ID__, { selected: config_raw.rp_gi });
+		context_raw.hssao = zui_handle(__ID__);
+		if (context_raw.hssao.init) {
+			context_raw.hssao.selected = config_raw.rp_ssao;
+		}
+
+		context_raw.hssr = zui_handle(__ID__);
+		if (context_raw.hssr.init) {
+			context_raw.hssr.selected = config_raw.rp_ssr;
+		}
+
+		context_raw.hbloom = zui_handle(__ID__);
+		if (context_raw.hbloom.init) {
+			context_raw.hbloom.selected = config_raw.rp_bloom;
+		}
+
+		context_raw.hsupersample = zui_handle(__ID__);
+		if (context_raw.hsupersample.init) {
+			context_raw.hsupersample.position = config_get_super_sample_quality(config_raw.rp_supersample);
+		}
+
+		context_raw.hvxao = zui_handle(__ID__);
+		if (context_raw.hvxao.init) {
+			context_raw.hvxao.selected = config_raw.rp_gi;
+		}
+
 		if (zui_tab(box_preferences_htab, tr("Viewport"), true)) {
 			///if (krom_direct3d12 || krom_vulkan || krom_metal)
 
-			let hpathtrace_mode: zui_handle_t = zui_handle(__ID__, { position: context_raw.pathtrace_mode });
+			let hpathtrace_mode: zui_handle_t = zui_handle(__ID__);
+			if (hpathtrace_mode.init) {
+				hpathtrace_mode.position = context_raw.pathtrace_mode;
+			}
 			context_raw.pathtrace_mode = zui_combo(hpathtrace_mode, [tr("Core"), tr("Full")], tr("Path Tracer"), true);
 			if (hpathtrace_mode.changed) {
 				render_path_raytrace_ready = false;
@@ -469,7 +608,10 @@ function box_preferences_show() {
 
 			///end
 
-			let hrender_mode: zui_handle_t = zui_handle(__ID__, { position: context_raw.render_mode });
+			let hrender_mode: zui_handle_t = zui_handle(__ID__);
+			if (hrender_mode.init) {
+				hrender_mode.position = context_raw.render_mode;
+			}
 			context_raw.render_mode = zui_combo(hrender_mode, [tr("Full"), tr("Mobile")], tr("Renderer"), true);
 			if (hrender_mode.changed) {
 				context_set_render_path();
@@ -491,12 +633,18 @@ function box_preferences_show() {
 				}
 
 				ui.enabled = context_raw.hvxao.selected;
-				let h: zui_handle_t = zui_handle(__ID__, { value: context_raw.vxao_offset });
+				let h: zui_handle_t = zui_handle(__ID__);
+				if (h.init) {
+					h.value = context_raw.vxao_offset;
+				}
 				context_raw.vxao_offset = zui_slider(h, tr("Cone Offset"), 1.0, 4.0, true);
 				if (h.changed) {
 					context_raw.ddirty = 2;
 				}
-				h = zui_handle(__ID__, { value: context_raw.vxao_aperture });
+				h = zui_handle(__ID__);
+				if (h.init) {
+					h.value = context_raw.vxao_aperture;
+				}
 				context_raw.vxao_aperture = zui_slider(h, tr("Aperture"), 1.0, 4.0, true);
 				if (h.changed) {
 					context_raw.ddirty = 2;
@@ -518,13 +666,19 @@ function box_preferences_show() {
 				}
 			}
 
-			let h: zui_handle_t = zui_handle(__ID__, { value: config_raw.rp_vignette });
+			let h: zui_handle_t = zui_handle(__ID__);
+			if (h.init) {
+				h.value = config_raw.rp_vignette;
+			}
 			config_raw.rp_vignette = zui_slider(h, tr("Vignette"), 0.0, 1.0, true);
 			if (h.changed) {
 				context_raw.ddirty = 2;
 			}
 
-			h = zui_handle(__ID__, { value: config_raw.rp_grain });
+			h = zui_handle(__ID__);
+			if (h.init) {
+				h.value = config_raw.rp_grain;
+			}
 			config_raw.rp_grain = zui_slider(h, tr("Noise Grain"), 0.0, 1.0, true);
 			if (h.changed) {
 				context_raw.ddirty = 2;
@@ -546,7 +700,10 @@ function box_preferences_show() {
 				camera_object_build_proj(cam);
 			}
 
-			let disp_handle: zui_handle_t = zui_handle(__ID__, { value: config_raw.displace_strength });
+			let disp_handle: zui_handle_t = zui_handle(__ID__);
+			if (disp_handle.init) {
+				disp_handle.value = config_raw.displace_strength;
+			}
 			config_raw.displace_strength = zui_slider(disp_handle, tr("Displacement Strength"), 0.0, 10.0, true);
 			if (disp_handle.changed) {
 				context_raw.ddirty = 2;
@@ -562,7 +719,10 @@ function box_preferences_show() {
 			zui_begin_sticky();
 			zui_row([1 / 4, 1 / 4, 1 / 4, 1 / 4]);
 
-			box_preferences_preset_handle = zui_handle(__ID__, { position: box_preferences_get_preset_index() });
+			box_preferences_preset_handle = zui_handle(__ID__);
+			if (box_preferences_preset_handle.init) {
+				box_preferences_preset_handle.position = box_preferences_get_preset_index();
+			}
 			zui_combo(box_preferences_preset_handle, box_preferences_files_keymap, tr("Preset"));
 			if (box_preferences_preset_handle.changed) {
 				config_raw.keymap = box_preferences_files_keymap[box_preferences_preset_handle.position] + ".json";
@@ -574,7 +734,11 @@ function box_preferences_show() {
 				ui_box_show_custom(function (ui: zui_t) {
 					if (zui_tab(zui_handle(__ID__), tr("New Keymap"))) {
 						zui_row([0.5, 0.5]);
-						let keymap_name: string = zui_text_input(zui_handle(__ID__, { text: "new_keymap" }), tr("Name"));
+						let h: zui_handle_t = zui_handle(__ID__);
+						if (h.init) {
+							h.text = "new_keymap";
+						}
+						let keymap_name: string = zui_text_input(h, tr("Name"));
 						if (zui_button(tr("OK")) || ui.is_return_down) {
 							let template: string = json_stringify(base_get_default_keymap());
 							if (!ends_with(keymap_name, ".json")) {
@@ -634,7 +798,11 @@ function box_preferences_show() {
 				ui_box_show_custom(function (ui: zui_t) {
 					if (zui_tab(zui_handle(__ID__), tr("New Plugin"))) {
 						zui_row([0.5, 0.5]);
-						let plugin_name: string = zui_text_input(zui_handle(__ID__, { text: "new_plugin" }), tr("Name"));
+						let h: zui_handle_t = zui_handle(__ID__);
+						if (h.init) {
+							h.text = "new_plugin";
+						}
+						let plugin_name: string = zui_text_input(h, tr("Name"));
 						if (zui_button(tr("OK")) || ui.is_return_down) {
 							let template: string =
 "let plugin = create();\
@@ -674,7 +842,10 @@ plugin.draw_ui = function (ui) {\
 			if (config_raw.plugins == null) {
 				config_raw.plugins = [];
 			}
-			let h: zui_handle_t = zui_handle(__ID__, { selected: false });
+			let h: zui_handle_t = zui_handle(__ID__);
+			if (h.init) {
+				h.selected = false;
+			}
 			for (let i: i32 = 0; i < box_preferences_files_plugin.length; ++i) {
 				let f: string = box_preferences_files_plugin[i];
 				let is_js: bool = ends_with(f, ".js");

+ 14 - 9
base/Sources/context.ts

@@ -317,9 +317,9 @@ function context_create(): context_t {
 	c.picked_color = make_swatch();
 	c.envmap_loaded = false;
 	c.show_envmap = false;
-	c.show_envmap_handle = zui_handle_create({ selected: false });
+	c.show_envmap_handle = zui_handle_create();
 	c.show_envmap_blur = false;
-	c.show_envmap_blur_handle = zui_handle_create({ selected: false });
+	c.show_envmap_blur_handle = zui_handle_create();
 	c.envmap_angle = 0.0;
 	c.light_angle = 0.0;
 	c.cull_backfaces = true;
@@ -409,9 +409,9 @@ function context_create(): context_t {
 	c.nory_picked = 0.0;
 	c.norz_picked = 0.0;
 	c.draw_wireframe = false;
-	c.wireframe_handle = zui_handle_create({ selected: false });
+	c.wireframe_handle = zui_handle_create();
 	c.draw_texels = false;
-	c.texels_handle = zui_handle_create({ selected: false });
+	c.texels_handle = zui_handle_create();
 	c.colorid_handle = zui_handle_create();
 	c.layers_export = export_mode_t.VISIBLE;
 	c.decal_preview = false;
@@ -457,17 +457,22 @@ function context_create(): context_t {
 	c.brush_nodes_hardness = 1.0;
 	c.brush_directional = false;
 	c.brush_radius = 0.5;
-	c.brush_radius_handle = zui_handle_create({ value: 0.5 });
+	c.brush_radius_handle = zui_handle_create();
+	c.brush_radius_handle.value = 0.5;
 	c.brush_scale_x = 1.0;
 	c.brush_decal_mask_radius = 0.5;
-	c.brush_decal_mask_radius_handle = zui_handle_create({ value: 0.5 });
-	c.brush_scale_x_handle = zui_handle_create({ value: 1.0 });
+	c.brush_decal_mask_radius_handle = zui_handle_create();
+	c.brush_decal_mask_radius_handle.value = 0.5;
+	c.brush_scale_x_handle = zui_handle_create();
+	c.brush_scale_x_handle.value = 1.0;
 	c.brush_blending = blend_type_t.MIX;
 	c.brush_opacity = 1.0;
-	c.brush_opacity_handle = zui_handle_create({ value: 1.0 });
+	c.brush_opacity_handle = zui_handle_create();
+	c.brush_opacity_handle.value = 1.0;
 	c.brush_scale = 1.0;
 	c.brush_angle = 0.0;
-	c.brush_angle_handle = zui_handle_create({ value: 0.0 });
+	c.brush_angle_handle = zui_handle_create();
+	c.brush_angle_handle.value = 0.0;
 	///if is_paint
 	c.brush_hardness = 0.8;
 	///end

+ 2 - 2
base/Sources/export_arm.ts

@@ -228,8 +228,8 @@ function export_arm_texture_node_name(): string {
 
 function export_arm_export_node(n: zui_node_t, assets: asset_t[] = null) {
 	if (n.type == export_arm_texture_node_name()) {
-		let index: i32 = n.buttons[0].default_value;
-		n.buttons[0].data = base_enum_texts(n.type)[index];
+		let index: i32 = n.buttons[0].default_value[0];
+		n.buttons[0].data = u8_array_create_from_string(base_enum_texts(n.type)[index]);
 
 		if (assets != null) {
 			let asset: asset_t = project_assets[index];

+ 2 - 2
base/Sources/import_arm.ts

@@ -625,8 +625,8 @@ function import_arm_init_nodes(nodes: zui_node_t[]) {
 	for (let i: i32 = 0; i < nodes.length; ++i) {
 		let node: zui_node_t = nodes[i];
 		if (node.type == import_arm_texture_node_name()) {
-			node.buttons[0].default_value = base_get_asset_index(node.buttons[0].data);
-			node.buttons[0].data = "";
+			node.buttons[0].default_value = f32_array_create_x(base_get_asset_index(u8_array_to_string(node.buttons[0].data)));
+			node.buttons[0].data = u8_array_create_from_string("");
 		}
 	}
 }

+ 17 - 17
base/Sources/import_blend_material.ts

@@ -127,27 +127,27 @@ function import_blend_material_run(path: string) {
 					import_texture_run(file);
 					let ar: string[] = string_split(file, path_sep);
 					let filename: string = ar[ar.length - 1];
-					n.buttons[0].default_value = base_get_asset_index(filename);
+					n.buttons[0].default_value = f32_array_create_x(base_get_asset_index(filename));
 				}
 				else if (search == "valtorgb") {
-					let ramp: any = bl_handle_get(node, "storage", 0, "ColorBand");
-					n.buttons[0].data = bl_handle_get(ramp, "ipotype") == 0 ? 0 : 1; // Linear / Constant
-					let elems: f32[][] = n.buttons[0].default_value;
-					for (let i: i32 = 0; i < bl_handle_get(ramp, "tot"); ++i) {
-						if (i >= elems.length) {
-							array_push(elems, [1.0, 1.0, 1.0, 1.0, 0.0]);
-						}
-						let cbdata: any = bl_handle_get(ramp, "data", i, "CBData");
-						elems[i][0] = math_floor(bl_handle_get(cbdata, "r") * 100) / 100;
-						elems[i][1] = math_floor(bl_handle_get(cbdata, "g") * 100) / 100;
-						elems[i][2] = math_floor(bl_handle_get(cbdata, "b") * 100) / 100;
-						elems[i][3] = math_floor(bl_handle_get(cbdata, "a") * 100) / 100;
-						elems[i][4] = math_floor(bl_handle_get(cbdata, "pos") * 100) / 100;
-					}
+					// let ramp: any = bl_handle_get(node, "storage", 0, "ColorBand");
+					// n.buttons[0].data = bl_handle_get(ramp, "ipotype") == 0 ? 0 : 1; // Linear / Constant
+					// let elems: f32[][] = n.buttons[0].default_value;
+					// for (let i: i32 = 0; i < bl_handle_get(ramp, "tot"); ++i) {
+					// 	if (i >= elems.length) {
+					// 		array_push(elems, [1.0, 1.0, 1.0, 1.0, 0.0]);
+					// 	}
+					// 	let cbdata: any = bl_handle_get(ramp, "data", i, "CBData");
+					// 	elems[i][0] = math_floor(bl_handle_get(cbdata, "r") * 100) / 100;
+					// 	elems[i][1] = math_floor(bl_handle_get(cbdata, "g") * 100) / 100;
+					// 	elems[i][2] = math_floor(bl_handle_get(cbdata, "b") * 100) / 100;
+					// 	elems[i][3] = math_floor(bl_handle_get(cbdata, "a") * 100) / 100;
+					// 	elems[i][4] = math_floor(bl_handle_get(cbdata, "pos") * 100) / 100;
+					// }
 				}
 				else if (search == "mixrgb" || search == "math") {
-					n.buttons[0].default_value = bl_handle_get(node, "custom1");
-					n.buttons[1].default_value = bl_handle_get(node, "custom2") & 2;
+					n.buttons[0].default_value = f32_array_create_x(bl_handle_get(node, "custom1"));
+					n.buttons[1].default_value = f32_array_create_x(bl_handle_get(node, "custom2") & 2);
 				}
 				else if (search == "mapping") {
 					let storage: any = bl_handle_get(node, "storage", 0, "TexMapping");

+ 2 - 2
base/Sources/nodes/float_node.ts

@@ -65,7 +65,7 @@ let float_node_def: zui_node_t = {
 			name: _tr("Value"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.5,
+			default_value: f32_array_create_x(0.5),
 			min: 0.0,
 			max: 10.0,
 			precision: 100,
@@ -79,7 +79,7 @@ let float_node_def: zui_node_t = {
 			name: _tr("Value"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.5,
+			default_value: f32_array_create_x(0.5),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,

+ 6 - 6
base/Sources/nodes/math_node.ts

@@ -145,7 +145,7 @@ let math_node_def: zui_node_t = {
 			name: _tr("Value"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.5,
+			default_value: f32_array_create_x(0.5),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -157,7 +157,7 @@ let math_node_def: zui_node_t = {
 			name: _tr("Value"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.5,
+			default_value: f32_array_create_x(0.5),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -171,7 +171,7 @@ let math_node_def: zui_node_t = {
 			name: _tr("Value"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.0,
+			default_value: f32_array_create_x(0.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -183,8 +183,8 @@ let math_node_def: zui_node_t = {
 			name: _tr("operation"),
 			type: "ENUM",
 			output: 0,
-			default_value: 0,
-			data: ["Add", "Subtract", "Multiply", "Divide", "Power", "Logarithm", "Square Root", "Inverse Square Root", "Absolute", "Exponent", "Minimum", "Maximum", "Less Than", "Greater Than", "Sign", "Round", "Floor", "Ceil", "Truncate", "Fraction", "Modulo", "Snap", "Ping-Pong", "Sine", "Cosine", "Tangent", "Arcsine", "Arccosine", "Arctangent", "Arctan2", "Hyperbolic Sine", "Hyperbolic Cosine", "Hyperbolic Tangent", "To Radians", "To Degrees"],
+			default_value: f32_array_create_x(0),
+			data: u8_array_create_from_string("Add\0Subtract\0Multiply\0Divide\0Power\0Logarithm\0Square Root\0Inverse Square Root\0Absolute\0Exponent\0Minimum\0Maximum\0Less Than\0Greater Than\0Sign\0Round\0Floor\0Ceil\0Truncate\0Fraction\0Modulo\0Snap\0Ping-Pong\0Sine\0Cosine\0Tangent\0Arcsine\0Arccosine\0Arctangent\0Arctan2\0Hyperbolic Sine\0Hyperbolic Cosine\0Hyperbolic Tangent\0To Radians\0To Degrees"),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -194,7 +194,7 @@ let math_node_def: zui_node_t = {
 			name: _tr("use_clamp"),
 			type: "BOOL",
 			output: 0,
-			default_value: false,
+			default_value: f32_array_create_x(0),
 			data: null,
 			min: 0.0,
 			max: 1.0,

+ 3 - 3
base/Sources/nodes/random_node.ts

@@ -70,7 +70,7 @@ let random_node_def: zui_node_t = {
 			name: _tr("Min"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.0,
+			default_value: f32_array_create_x(0.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -82,7 +82,7 @@ let random_node_def: zui_node_t = {
 			name: _tr("Max"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 1.0,
+			default_value: f32_array_create_x(1.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -96,7 +96,7 @@ let random_node_def: zui_node_t = {
 			name: _tr("Value"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.5,
+			default_value: f32_array_create_x(0.5),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,

+ 3 - 3
base/Sources/nodes/separate_vector_node.ts

@@ -54,7 +54,7 @@ let separate_vector_node_def: zui_node_t = {
 			name: _tr("X"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.0,
+			default_value: f32_array_create_x(0.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -66,7 +66,7 @@ let separate_vector_node_def: zui_node_t = {
 			name: _tr("Y"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.0,
+			default_value: f32_array_create_x(0.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -78,7 +78,7 @@ let separate_vector_node_def: zui_node_t = {
 			name: _tr("Z"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.0,
+			default_value: f32_array_create_x(0.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,

+ 3 - 3
base/Sources/nodes/time_node.ts

@@ -40,7 +40,7 @@ let time_node_def: zui_node_t = {
 			name: _tr("Time"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.0,
+			default_value: f32_array_create_x(0.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -52,7 +52,7 @@ let time_node_def: zui_node_t = {
 			name: _tr("Delta"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.0,
+			default_value: f32_array_create_x(0.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -64,7 +64,7 @@ let time_node_def: zui_node_t = {
 			name: _tr("Brush"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.0,
+			default_value: f32_array_create_x(0.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,

+ 3 - 3
base/Sources/nodes/vector_math_node.ts

@@ -192,7 +192,7 @@ let vector_math_node_def: zui_node_t = {
 			name: _tr("Value"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.0,
+			default_value: f32_array_create_x(0.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -204,8 +204,8 @@ let vector_math_node_def: zui_node_t = {
 			name: _tr("operation"),
 			type: "ENUM",
 			output: 0,
-			default_value: 0,
-			data: ["Add", "Subtract", "Multiply", "Divide", "Average", "Cross Product", "Project", "Reflect", "Dot Product", "Distance", "Length", "Scale", "Normalize", "Absolute", "Minimum", "Maximum", "Floor", "Ceil", "Fraction", "Modulo", "Snap", "Sine", "Cosine", "Tangent"],
+			default_value: f32_array_create_x(0),
+			data: u8_array_create_from_string("Add\0Subtract\0Multiply\0Divide\0Average\0Cross Product\0Project\0Reflect\0Dot Product\0Distance\0Length\0Scale\0Normalize\0Absolute\0Minimum\0Maximum\0Floor\0Ceil\0Fraction\0Modulo\0Snap\0Sine\0Cosine\0Tangent"),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,

+ 3 - 3
base/Sources/nodes/vector_node.ts

@@ -70,7 +70,7 @@ let vector_node_def: zui_node_t = {
 			name: _tr("X"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.0,
+			default_value: f32_array_create_x(0.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -82,7 +82,7 @@ let vector_node_def: zui_node_t = {
 			name: _tr("Y"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.0,
+			default_value: f32_array_create_x(0.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,
@@ -94,7 +94,7 @@ let vector_node_def: zui_node_t = {
 			name: _tr("Z"),
 			type: "VALUE",
 			color: 0xffa1a1a1,
-			default_value: 0.0,
+			default_value: f32_array_create_x(0.0),
 			min: 0.0,
 			max: 1.0,
 			precision: 100,

File diff suppressed because it is too large
+ 119 - 119
base/Sources/nodes_material.ts


+ 14 - 15
base/Sources/parser_logic.ts

@@ -111,18 +111,17 @@ function parser_logic_build_node(node: zui_node_t): string {
 	map_set(parser_logic_raw_map, v, node);
 
 	// Expose button values in node
-	for (let i: i32 = 0; i < node.buttons.length; ++i) {
-		let b: zui_node_button_t = node.buttons[i];
-		if (b.type == "ENUM") {
-			// let array_data: bool = is_array(b.data);
-			let array_data: bool = b.data.length > 1;
-			let texts: string[] = array_data ? b.data : zui_enum_texts_js(node.type);
-			v[b.name] = texts[b.default_value];
-		}
-		else {
-			v[b.name] = b.default_value;
-		}
-	}
+	// for (let i: i32 = 0; i < node.buttons.length; ++i) {
+	// 	let b: zui_node_button_t = node.buttons[i];
+	// 	if (b.type == "ENUM") {
+	// 		let array_data: bool = b.data.length > 1;
+	// 		let texts: string[] = array_data ? b.data : zui_enum_texts_js(node.type);
+	// 		v[b.name] = texts[b.default_value];
+	// 	}
+	// 	else {
+	// 		v[b.name] = b.default_value;
+	// 	}
+	// }
 
 	// Create inputs
 	let inp_node: logic_node_t = null;
@@ -193,19 +192,19 @@ function parser_logic_build_default_node(inp: zui_node_socket_t): logic_node_t {
 
 	if (inp.type == "VECTOR") {
 		if (inp.default_value == null) {
-			inp.default_value = [0, 0, 0]; // TODO
+			inp.default_value = f32_array_create_xyz(0, 0, 0);
 		}
 		v = parser_logic_create_node_instance("vector_node", inp.default_value);
 	}
 	else if (inp.type == "RGBA") {
 		if (inp.default_value == null) {
-			inp.default_value = [0, 0, 0, 0]; // TODO
+			inp.default_value = f32_array_create_xyzw(0, 0, 0, 0);
 		}
 		v = parser_logic_create_node_instance("color_node", inp.default_value);
 	}
 	else if (inp.type == "RGB") {
 		if (inp.default_value == null) {
-			inp.default_value = [0, 0, 0, 0]; // TODO
+			inp.default_value = f32_array_create_xyzw(0, 0, 0, 0);
 		}
 		v = parser_logic_create_node_instance("color_node", inp.default_value);
 	}

+ 30 - 24
base/Sources/parser_material.ts

@@ -446,7 +446,7 @@ function parser_material_parse_vector_input(inp: zui_node_socket_t): string {
 	}
 	else {
 		if (inp.type == "VALUE") { // Unlinked reroute
-			return parser_material_vec3([0.0, 0.0, 0.0]);
+			return parser_material_vec3(f32_array_create_xyz(0.0, 0.0, 0.0));
 		}
 		else {
 			return parser_material_vec3(inp.default_value);
@@ -511,7 +511,7 @@ function parser_material_parse_vector(node: zui_node_t, socket: zui_node_socket_
 	else if (node.type == "TEX_GRADIENT") {
 		let co: string = parser_material_get_coord(node);
 		let but: zui_node_button_t = node.buttons[0]; //gradient_type;
-		let grad: string = but.data[but.default_value].toUpperCase();
+		let grad: string = to_upper_case(u8_array_string_at(but.data, but.default_value[0]));
 		grad = string_replace_all(grad, " ", "_");
 		let f: string = parser_material_get_gradient(grad, co);
 		let res: string = parser_material_to_vec3("clamp(" + f + ", 0.0, 1.0)");
@@ -526,7 +526,7 @@ function parser_material_parse_vector(node: zui_node_t, socket: zui_node_socket_
 		let tex_name: string = parser_material_node_name(node);
 		let tex: bind_tex_t = parser_material_make_texture(node, tex_name);
 		if (tex != null) {
-			let color_space: i32 = node.buttons[1].default_value;
+			let color_space: i32 = node.buttons[1].default_value[0];
 			let texstore: string = parser_material_texture_store(node, tex, tex_name, color_space);
 			return texstore + ".rgb";
 		}
@@ -556,7 +556,7 @@ function parser_material_parse_vector(node: zui_node_t, socket: zui_node_socket_
 		let co: string = parser_material_get_coord(node);
 		let scale: string = parser_material_parse_value_input(node.inputs[1]);
 		let but: zui_node_button_t = node.buttons[0]; //coloring;
-		let coloring: string = but.data[but.default_value].toUpperCase();
+		let coloring: string = to_upper_case(u8_array_string_at(but.data, but.default_value[0]));
 		coloring = string_replace_all(coloring, " ", "_");
 		let res: string = "";
 		if (coloring == "INTENSITY") {
@@ -642,9 +642,9 @@ function parser_material_parse_vector(node: zui_node_t, socket: zui_node_socket_
 		let col1: string = parser_material_parse_vector_input(node.inputs[1]);
 		let col2: string = parser_material_parse_vector_input(node.inputs[2]);
 		let but: zui_node_button_t = node.buttons[0]; // blend_type
-		let blend: string = but.data[but.default_value].toUpperCase();
+		let blend: string = to_upper_case(u8_array_string_at(but.data, but.default_value[0]));
 		blend = string_replace_all(blend, " ", "_");
-		let use_clamp: bool = node.buttons[1].default_value == true;
+		let use_clamp: bool = node.buttons[1].default_value[0] > 0;
 		let out_col: string = "";
 		if (blend == "MIX") {
 			out_col = "mix(" + col1 + ", " + col2 + ", " + fac_var + ")";
@@ -724,16 +724,16 @@ function parser_material_parse_vector(node: zui_node_t, socket: zui_node_socket_
 	}
 	else if (node.type == "VALTORGB") { // ColorRamp
 		let fac: string = parser_material_parse_value_input(node.inputs[0]);
-		let interp: string = node.buttons[0].data == 0 ? "LINEAR" : "CONSTANT";
-		let elems: f32[][] = node.buttons[0].default_value;
+		let interp: string = node.buttons[0].data[0] == 0 ? "LINEAR" : "CONSTANT";
+		let elems: f32[][] = null; //node.buttons[0].default_value;
 		if (elems.length == 1) {
-			return parser_material_vec3(elems[0]);
+			// return parser_material_vec3(elems[0]);
 		}
 		// Write cols array
 		let cols_var: string = parser_material_node_name(node) + "_cols";
 		node_shader_write(parser_material_curshader, "vec3 " + cols_var + "[" + elems.length + "];"); // TODO: Make const
 		for (let i: i32 = 0; i < elems.length; ++i) {
-			node_shader_write(parser_material_curshader, cols_var + "[" + i + "] = " + parser_material_vec3(elems[i]) + ";");
+			// node_shader_write(parser_material_curshader, cols_var + "[" + i + "] = " + parser_material_vec3(elems[i]) + ";");
 		}
 		// Get index
 		let fac_var: string = parser_material_node_name(node) + "_fac";
@@ -1001,7 +1001,7 @@ function parser_material_parse_vector(node: zui_node_t, socket: zui_node_socket_
 		let nm1: string = parser_material_parse_vector_input(node.inputs[0]);
 		let nm2: string = parser_material_parse_vector_input(node.inputs[1]);
 		let but: zui_node_button_t = node.buttons[0];
-		let blend: string = but.data[but.default_value].toUpperCase(); // blend_type
+		let blend: string = to_upper_case(u8_array_string_at(but.data, but.default_value[0])); // blend_type
 		blend = string_replace_all(blend, " ", "_");
 		let store: string = parser_material_store_var_name(node);
 
@@ -1040,7 +1040,7 @@ function parser_material_parse_vector(node: zui_node_t, socket: zui_node_socket_
 		let vec1: string = parser_material_parse_vector_input(node.inputs[0]);
 		let vec2: string = parser_material_parse_vector_input(node.inputs[1]);
 		let but: zui_node_button_t = node.buttons[0]; //operation;
-		let op: string = but.data[but.default_value].toUpperCase();
+		let op: string = to_upper_case(u8_array_string_at(but.data, but.default_value[0]));
 		op = string_replace_all(op, " ", "_");
 		if (op == "ADD") {
 			return "(" + vec1 + " + " + vec2 + ")";
@@ -1170,7 +1170,7 @@ function parser_material_parse_value_input(inp: zui_node_socket_t, vector_as_gra
 		}
 	}
 	else {
-		return parser_material_vec1(inp.default_value);
+		return parser_material_vec1(inp.default_value[0]);
 	}
 }
 
@@ -1351,7 +1351,7 @@ function parser_material_parse_value(node: zui_node_t, socket: zui_node_socket_t
 		}
 	}
 	else if (node.type == "VALUE") {
-		return parser_material_vec1(node.outputs[0].default_value);
+		return parser_material_vec1(node.outputs[0].default_value[0]);
 	}
 	else if (node.type == "TEX_BRICK") {
 		node_shader_add_function(parser_material_curshader, str_tex_brick);
@@ -1370,7 +1370,7 @@ function parser_material_parse_value(node: zui_node_t, socket: zui_node_socket_t
 	else if (node.type == "TEX_GRADIENT") {
 		let co: string = parser_material_get_coord(node);
 		let but: zui_node_button_t = node.buttons[0]; //gradient_type;
-		let grad: string = but.data[but.default_value].toUpperCase();
+		let grad: string = to_upper_case(u8_array_string_at(but.data, but.default_value[0]));
 		grad = string_replace_all(grad, " ", "_");
 		let f: string = parser_material_get_gradient(grad, co);
 		let res: string = "(clamp(" + f + ", 0.0, 1.0))";
@@ -1385,7 +1385,7 @@ function parser_material_parse_value(node: zui_node_t, socket: zui_node_socket_t
 		let tex_name: string = parser_material_node_name(node);
 		let tex: bind_tex_t = parser_material_make_texture(node, tex_name);
 		if (tex != null) {
-			let color_space: i32 = node.buttons[1].default_value;
+			let color_space: i32 = node.buttons[1].default_value[0];
 			let texstore: string = parser_material_texture_store(node, tex, tex_name, color_space);
 			return texstore + ".a";
 		}
@@ -1417,7 +1417,7 @@ function parser_material_parse_value(node: zui_node_t, socket: zui_node_socket_t
 		let co: string = parser_material_get_coord(node);
 		let scale: string = parser_material_parse_value_input(node.inputs[1]);
 		let but: zui_node_button_t = node.buttons[0]; // coloring
-		let coloring: string = but.data[but.default_value].toUpperCase();
+		let coloring: string = to_upper_case(u8_array_string_at(but.data, but.default_value[0]));
 		coloring = string_replace_all(coloring, " ", "_");
 		let res: string = "";
 		if (coloring == "INTENSITY") {
@@ -1464,9 +1464,9 @@ function parser_material_parse_value(node: zui_node_t, socket: zui_node_socket_t
 		let val1: string = parser_material_parse_value_input(node.inputs[0]);
 		let val2: string = parser_material_parse_value_input(node.inputs[1]);
 		let but: zui_node_button_t = node.buttons[0]; // operation
-		let op: string = but.data[but.default_value].toUpperCase();
+		let op: string = to_upper_case(u8_array_string_at(but.data, but.default_value[0]));
 		op = string_replace_all(op, " ", "_");
-		let use_clamp: bool = node.buttons[1].default_value == true;
+		let use_clamp: bool = node.buttons[1].default_value[0] > 0;
 		let out_val: string = "";
 		if (op == "ADD") {
 			out_val = "(" + val1 + " + " + val2 + ")";
@@ -1640,7 +1640,7 @@ function parser_material_parse_value(node: zui_node_t, socket: zui_node_socket_t
 		let vec1: string = parser_material_parse_vector_input(node.inputs[0]);
 		let vec2: string = parser_material_parse_vector_input(node.inputs[1]);
 		let but: zui_node_button_t = node.buttons[0]; //operation;
-		let op: string = but.data[but.default_value].toUpperCase();
+		let op: string = to_upper_case(u8_array_string_at(but.data, but.default_value[0]));
 		op = string_replace_all(op, " ", "_");
 		if (op == "DOT_PRODUCT") {
 			return "dot(" + vec1 + ", " + vec2 + ")";
@@ -1660,7 +1660,7 @@ function parser_material_parse_value(node: zui_node_t, socket: zui_node_socket_t
 		let min: string = parser_material_parse_value_input(node.inputs[1]);
 		let max: string = parser_material_parse_value_input(node.inputs[2]);
 		let but: zui_node_button_t = node.buttons[0]; //operation;
-		let op: string = but.data[but.default_value].toUpperCase();
+		let op: string = to_upper_case(u8_array_string_at(but.data, but.default_value[0]));
 		op = string_replace_all(op, " ", "_");
 
 		if (op == "MIN_MAX") {
@@ -1677,7 +1677,7 @@ function parser_material_parse_value(node: zui_node_t, socket: zui_node_socket_t
 		let tmin: string = parser_material_parse_value_input(node.inputs[3]);
 		let tmax: string = parser_material_parse_value_input(node.inputs[4]);
 
-		let use_clamp: bool = node.buttons[0].default_value == true;
+		let use_clamp: bool = node.buttons[0].default_value[0] > 0;
 
 		let a: string = "((" + tmin + " - " + tmax + ") / (" + fmin + " - " + fmax + "))";
 		let out_val: string = "(" + a + " * " + val + " + " + tmin + " - " + a + " * " + fmin + ")";
@@ -1858,7 +1858,7 @@ function parser_material_vec1(v: f32): string {
 	///end
 }
 
-function parser_material_vec3(v: f32[]): string {
+function parser_material_vec3(v: f32_array_t): string {
 	///if krom_android
 	return "vec3(float(" + v[0] + "), float(" + v[1] + "), float(" + v[2] + "))";
 	///else
@@ -1937,7 +1937,7 @@ function parser_material_enum_data(s: string): string {
 }
 
 function parser_material_make_texture(image_node: zui_node_t, tex_name: string, matname: string = null): bind_tex_t {
-	let filepath: string = parser_material_enum_data(base_enum_texts(image_node.type)[image_node.buttons[0].default_value]);
+	let filepath: string = parser_material_enum_data(base_enum_texts(image_node.type)[image_node.buttons[0].default_value[0]]);
 	if (filepath == "" || string_index_of(filepath, ".") == -1) {
 		return null;
 	}
@@ -1981,6 +1981,12 @@ function parser_material_safestr(s: string): string {
 	return s;
 }
 
+function u8_array_string_at(a: u8_array_t, i: i32): string {
+	let s: string = u8_array_to_string(a);
+	let ss: string[] = string_split(s, "\0");
+	return ss[i];
+}
+
 type shader_out_t = {
 	out_basecol?: string;
 	out_roughness?: string;

+ 17 - 4
base/Sources/project.ts

@@ -103,8 +103,17 @@ function project_new_box() {
 			}
 
 			zui_row([0.5, 0.5]);
-			context_raw.project_type = zui_combo(zui_handle(__ID__, { position: context_raw.project_type }), project_mesh_list, tr("Template"), true);
-			context_raw.project_aspect_ratio = zui_combo(zui_handle(__ID__, { position: context_raw.project_aspect_ratio }), ["1:1", "2:1", "1:2"], tr("Aspect Ratio"), true);
+			let h_project_type: zui_handle_t = zui_handle(__ID__);
+			if (h_project_type.init) {
+				h_project_type.position = context_raw.project_type;
+			}
+			context_raw.project_type = zui_combo(h_project_type, project_mesh_list, tr("Template"), true);
+
+			let h_project_aspect_ratio: zui_handle_t = zui_handle(__ID__);
+			if (h_project_aspect_ratio.init) {
+				h_project_aspect_ratio.position = context_raw.project_aspect_ratio;
+			}
+			context_raw.project_aspect_ratio = zui_combo(h_project_aspect_ratio, ["1:1", "2:1", "1:2"], tr("Aspect Ratio"), true);
 
 			zui_end_element();
 			zui_row([0.5, 0.5]);
@@ -358,7 +367,7 @@ function project_import_brush() {
 			let n: zui_node_t = nodes_brush_create_node("TEX_IMAGE");
 			n.x = 83;
 			n.y = 340;
-			n.buttons[0].default_value = asset_index;
+			n.buttons[0].default_value = f32_array_create_x(asset_index);
 			let links: zui_node_link_t[] = context_raw.brush.canvas.links;
 			array_push(links, {
 				id: zui_get_link_id(links),
@@ -439,7 +448,11 @@ function project_import_mesh_box(path: string, replace_existing: bool = true, cl
 			///if (is_paint || is_sculpt)
 			// if (ends_with(to_lower_case(path), ".fbx") || ends_with(to_lower_case(path), ".blend")) {
 			if (ends_with(to_lower_case(path), ".blend")) {
-				context_raw.parse_vcols = zui_check(zui_handle(__ID__, { selected: context_raw.parse_vcols }), tr("Parse Vertex Colors"));
+				let h: zui_handle_t = zui_handle(__ID__);
+				if (h.init) {
+					h.selected = context_raw.parse_vcols;
+				}
+				context_raw.parse_vcols = zui_check(h, tr("Parse Vertex Colors"));
 				if (ui.is_hovered) {
 					zui_tooltip(tr("Import vertex color data"));
 				}

+ 56 - 20
base/Sources/tab_materials.ts

@@ -193,15 +193,51 @@ function tab_materials_draw_slots(mini: bool) {
 						tab_materials_delete_material(m);
 					}
 
-					let base_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id, {selected: m.paint_base});
-					let opac_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id, {selected: m.paint_opac});
-					let nor_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id, {selected: m.paint_nor});
-					let occ_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id, {selected: m.paint_occ});
-					let rough_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id, {selected: m.paint_rough});
-					let met_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id, {selected: m.paint_met});
-					let height_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id, {selected: m.paint_height});
-					let emis_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id, {selected: m.paint_emis});
-					let subs_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id, {selected: m.paint_subs});
+					let base_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id);
+					if (base_handle.init) {
+						base_handle.selected = m.paint_base;
+					}
+
+					let opac_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id);
+					if (opac_handle.init) {
+						opac_handle.selected = m.paint_opac;
+					}
+
+					let nor_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id);
+					if (nor_handle.init) {
+						nor_handle.selected = m.paint_nor;
+					}
+
+					let occ_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id);
+					if (occ_handle.init) {
+						occ_handle.selected = m.paint_occ;
+					}
+
+					let rough_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id);
+					if (rough_handle.init) {
+						rough_handle.selected = m.paint_rough;
+					}
+
+					let met_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id);
+					if (met_handle.init) {
+						met_handle.selected = m.paint_met;
+					}
+
+					let height_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id);
+					if (height_handle.init) {
+						height_handle.selected = m.paint_height;
+					}
+
+					let emis_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id);
+					if (emis_handle.init) {
+						emis_handle.selected = m.paint_emis;
+					}
+
+					let subs_handle: zui_handle_t = zui_nest(zui_handle(__ID__), m.id);
+					if (subs_handle.init) {
+						subs_handle.selected = m.paint_subs;
+					}
+
 					ui_menu_fill(ui);
 					m.paint_base = zui_check(base_handle, tr("Base Color"));
 					ui_menu_fill(ui);
@@ -306,11 +342,11 @@ function tab_materials_update_material_pointers(nodes: zui_node_t[], i: i32) {
 	for (let i: i32 = 0; i < nodes.length; ++i) {
 		let n: zui_node_t = nodes[i];
 		if (n.type == "MATERIAL") {
-			if (n.buttons[0].default_value == i) {
-				n.buttons[0].default_value = 9999; // Material deleted
+			if (n.buttons[0].default_value[0] == i) {
+				n.buttons[0].default_value[0] = 9999; // Material deleted
 			}
-			else if (n.buttons[0].default_value > i) {
-				n.buttons[0].default_value--; // Offset by deleted material
+			else if (n.buttons[0].default_value[0] > i) {
+				n.buttons[0].default_value[0]--; // Offset by deleted material
 			}
 		}
 	}
@@ -321,19 +357,19 @@ function tab_materials_accept_swatch_drag(swatch: swatch_color_t) {
 	for (let i: i32 = 0; i < context_raw.material.canvas.nodes.length; ++i) {
 		let node: zui_node_t = context_raw.material.canvas.nodes[i];
 		if (node.type == "RGB" ) {
-			node.outputs[0].default_value = [
+			node.outputs[0].default_value = f32_array_create_xyzw(
 				color_get_rb(swatch.base) / 255,
 				color_get_gb(swatch.base) / 255,
 				color_get_bb(swatch.base) / 255,
 				color_get_ab(swatch.base) / 255
-			];
+			);
 		}
 		else if (node.type == "OUTPUT_MATERIAL_PBR") {
-			node.inputs[1].default_value = swatch.opacity;
-			node.inputs[2].default_value = swatch.occlusion;
-			node.inputs[3].default_value = swatch.roughness;
-			node.inputs[4].default_value = swatch.metallic;
-			node.inputs[7].default_value = swatch.height;
+			node.inputs[1].default_value[0] = swatch.opacity;
+			node.inputs[2].default_value[0] = swatch.occlusion;
+			node.inputs[3].default_value[0] = swatch.roughness;
+			node.inputs[4].default_value[0] = swatch.metallic;
+			node.inputs[7].default_value[0] = swatch.height;
 		}
 	}
 	array_push(project_materials, context_raw.material);

+ 4 - 4
base/Sources/tab_textures.ts

@@ -253,11 +253,11 @@ function tab_textures_update_texture_pointers(nodes: zui_node_t[], i: i32) {
 	for (let i: i32 = 0; i < nodes.length; ++i) {
 		let n: zui_node_t = nodes[i];
 		if (n.type == "TEX_IMAGE") {
-			if (n.buttons[0].default_value == i) {
-				n.buttons[0].default_value = 9999; // Texture deleted, use pink now
+			if (n.buttons[0].default_value[0] == i) {
+				n.buttons[0].default_value[0] = 9999; // Texture deleted, use pink now
 			}
-			else if (n.buttons[0].default_value > i) {
-				n.buttons[0].default_value--; // Offset by deleted texture
+			else if (n.buttons[0].default_value[0] > i) {
+				n.buttons[0].default_value[0]--; // Offset by deleted texture
 			}
 		}
 	}

+ 88 - 23
base/Sources/ui_header.ts

@@ -1,11 +1,11 @@
 
 let ui_header_default_h: i32 = 28;
 let ui_header_h: i32 = ui_header_default_h;
-let ui_header_handle: zui_handle_t = zui_handle_create({ layout: zui_layout_t.HORIZONTAL });
+let ui_header_handle: zui_handle_t = zui_handle_create();
 let ui_header_worktab: zui_handle_t = zui_handle_create();
 
 function ui_header_init() {
-
+	ui_header_handle.layout = zui_layout_t.HORIZONTAL;
 }
 
 function ui_header_render_ui() {
@@ -171,7 +171,11 @@ function ui_header_draw_tool_properties(ui: zui_t) {
 		zui_text(tr("Metallic") + " (" + metallic_picked + ")");
 		zui_text(tr("Height") + " (" + height_picked + ")");
 		zui_text(tr("Opacity") + " (" + opacity_picked + ")");
-		context_raw.picker_select_material = zui_check(zui_handle(__ID__, { selected: context_raw.picker_select_material }), tr("Select Material"));
+		let h_select_mat: zui_handle_t = zui_handle(__ID__);
+		if (h_select_mat.init) {
+			h_select_mat.selected = context_raw.picker_select_material;
+		}
+		context_raw.picker_select_material = zui_check(h_select_mat, tr("Select Material"));
 		zui_combo(context_raw.picker_mask_handle, [tr("None"), tr("Material")], tr("Mask"), true);
 		if (context_raw.picker_mask_handle.changed) {
 			make_material_parse_paint_material();
@@ -205,7 +209,10 @@ function ui_header_draw_tool_properties(ui: zui_t) {
 			///end
 		}
 
-		let bake_handle: zui_handle_t = zui_handle(__ID__, { position: context_raw.bake_type });
+		let bake_handle: zui_handle_t = zui_handle(__ID__);
+		if (bake_handle.init) {
+			bake_handle.position = context_raw.bake_type;
+		}
 		let bakes: string[] = [
 			tr("AO"),
 			tr("Curvature"),
@@ -240,25 +247,43 @@ function ui_header_draw_tool_properties(ui: zui_t) {
 
 		///if (krom_direct3d12 || krom_vulkan || krom_metal)
 		if (rt_bake) {
-			let samples_handle: zui_handle_t = zui_handle(__ID__, { value: context_raw.bake_samples });
+			let samples_handle: zui_handle_t = zui_handle(__ID__);
+			if (samples_handle.init) {
+				samples_handle.value = context_raw.bake_samples;
+			}
 			context_raw.bake_samples = math_floor(zui_slider(samples_handle, tr("Samples"), 1, 512, true, 1));
 		}
 		///end
 
 		if (context_raw.bake_type == bake_type_t.NORMAL_OBJECT || context_raw.bake_type == bake_type_t.POSITION || context_raw.bake_type == bake_type_t.BENT_NORMAL) {
-			let bake_up_axis_handle: zui_handle_t = zui_handle(__ID__, { position: context_raw.bake_up_axis });
+			let bake_up_axis_handle: zui_handle_t = zui_handle(__ID__);
+			if (bake_up_axis_handle.init) {
+				bake_up_axis_handle.position = context_raw.bake_up_axis;
+			}
 			context_raw.bake_up_axis = zui_combo(bake_up_axis_handle, [tr("Z"), tr("Y")], tr("Up Axis"), true);
 		}
 		if (context_raw.bake_type == bake_type_t.AO || context_raw.bake_type == bake_type_t.CURVATURE) {
-			let bake_axis_handle: zui_handle_t = zui_handle(__ID__, { position: context_raw.bake_axis });
+			let bake_axis_handle: zui_handle_t = zui_handle(__ID__);
+			if (bake_axis_handle.init) {
+				bake_axis_handle.position = context_raw.bake_axis;
+			}
 			context_raw.bake_axis = zui_combo(bake_axis_handle, [tr("XYZ"), tr("X"), tr("Y"), tr("Z"), tr("-X"), tr("-Y"), tr("-Z")], tr("Axis"), true);
 		}
 		if (context_raw.bake_type == bake_type_t.AO) {
-			let strength_handle: zui_handle_t = zui_handle(__ID__, { value: context_raw.bake_ao_strength });
+			let strength_handle: zui_handle_t = zui_handle(__ID__);
+			if (strength_handle.init) {
+				strength_handle.value = context_raw.bake_ao_strength;
+			}
 			context_raw.bake_ao_strength = zui_slider(strength_handle, tr("Strength"), 0.0, 2.0, true);
-			let radius_handle: zui_handle_t = zui_handle(__ID__, { value: context_raw.bake_ao_radius });
+			let radius_handle: zui_handle_t = zui_handle(__ID__);
+			if (radius_handle.init) {
+				radius_handle.value = context_raw.bake_ao_radius;
+			}
 			context_raw.bake_ao_radius = zui_slider(radius_handle, tr("Radius"), 0.0, 2.0, true);
-			let offset_handle: zui_handle_t = zui_handle(__ID__, { value: context_raw.bake_ao_offset });
+			let offset_handle: zui_handle_t = zui_handle(__ID__);
+			if (offset_handle.init) {
+				offset_handle.value = context_raw.bake_ao_offset;
+			}
 			context_raw.bake_ao_offset = zui_slider(offset_handle, tr("Offset"), 0.0, 2.0, true);
 		}
 		///if (krom_direct3d12 || krom_vulkan || krom_metal)
@@ -277,13 +302,25 @@ function ui_header_draw_tool_properties(ui: zui_t) {
 		}
 		///end
 		if (context_raw.bake_type == bake_type_t.CURVATURE) {
-			let strength_handle: zui_handle_t = zui_handle(__ID__, { value: context_raw.bake_curv_strength });
+			let strength_handle: zui_handle_t = zui_handle(__ID__);
+			if (strength_handle.init) {
+				strength_handle.value = context_raw.bake_curv_strength;
+			}
 			context_raw.bake_curv_strength = zui_slider(strength_handle, tr("Strength"), 0.0, 2.0, true);
-			let radius_handle: zui_handle_t = zui_handle(__ID__, { value: context_raw.bake_curv_radius });
+			let radius_handle: zui_handle_t = zui_handle(__ID__);
+			if (radius_handle.init) {
+				radius_handle.value = context_raw.bake_curv_radius;
+			}
 			context_raw.bake_curv_radius = zui_slider(radius_handle, tr("Radius"), 0.0, 2.0, true);
-			let offset_handle: zui_handle_t = zui_handle(__ID__, { value: context_raw.bake_curv_offset });
+			let offset_handle: zui_handle_t = zui_handle(__ID__);
+			if (offset_handle.init) {
+				offset_handle.value = context_raw.bake_curv_offset;
+			}
 			context_raw.bake_curv_offset = zui_slider(offset_handle, tr("Offset"), -2.0, 2.0, true);
-			let smooth_handle: zui_handle_t = zui_handle(__ID__, { value: context_raw.bake_curv_smooth });
+			let smooth_handle: zui_handle_t = zui_handle(__ID__);
+			if (smooth_handle.init) {
+				smooth_handle.value = context_raw.bake_curv_smooth;
+			}
 			context_raw.bake_curv_smooth = math_floor(zui_slider(smooth_handle, tr("Smooth"), 0, 5, false, 1));
 		}
 		if (context_raw.bake_type == bake_type_t.NORMAL || context_raw.bake_type == bake_type_t.HEIGHT || context_raw.bake_type == bake_type_t.DERIVATIVE) {
@@ -292,7 +329,10 @@ function ui_header_draw_tool_properties(ui: zui_t) {
 				let p: mesh_object_t = project_paint_objects[i];
 				array_push(ar, p.base.name);
 			}
-			let poly_handle: zui_handle_t = zui_handle(__ID__, { position: context_raw.bake_high_poly });
+			let poly_handle: zui_handle_t = zui_handle(__ID__);
+			if (poly_handle.init) {
+				poly_handle.position = context_raw.bake_high_poly;
+			}
 			context_raw.bake_high_poly = zui_combo(poly_handle, ar, tr("High Poly"));
 		}
 		if (ui.changed) {
@@ -342,7 +382,10 @@ function ui_header_draw_tool_properties(ui: zui_t) {
 			context_raw.tool == workspace_tool_t.FILL   ||
 			context_raw.tool == workspace_tool_t.DECAL  ||
 			context_raw.tool == workspace_tool_t.TEXT) {
-			let brush_scale_handle: zui_handle_t = zui_handle(__ID__, { value: context_raw.brush_scale });
+			let brush_scale_handle: zui_handle_t = zui_handle(__ID__);
+			if (brush_scale_handle.init) {
+				brush_scale_handle.value = context_raw.brush_scale;
+			}
 			context_raw.brush_scale = zui_slider(brush_scale_handle, tr("UV Scale"), 0.01, 5.0, true);
 			if (brush_scale_handle.changed) {
 				if (context_raw.tool == workspace_tool_t.DECAL || context_raw.tool == workspace_tool_t.TEXT) {
@@ -373,11 +416,18 @@ function ui_header_draw_tool_properties(ui: zui_t) {
 		}
 
 		if (context_raw.tool == workspace_tool_t.BRUSH || context_raw.tool == workspace_tool_t.ERASER || context_raw.tool == workspace_tool_t.CLONE || decal_mask) {
-			context_raw.brush_hardness = zui_slider(zui_handle(__ID__, { value: context_raw.brush_hardness }), tr("Hardness"), 0.0, 1.0, true);
+			let h: zui_handle_t = zui_handle(__ID__);
+			if (h.init) {
+				h.value = context_raw.brush_hardness;
+			}
+			context_raw.brush_hardness = zui_slider(h, tr("Hardness"), 0.0, 1.0, true);
 		}
 
 		if (context_raw.tool != workspace_tool_t.ERASER) {
-			let brush_blending_handle: zui_handle_t = zui_handle(__ID__, { value: context_raw.brush_blending });
+			let brush_blending_handle: zui_handle_t = zui_handle(__ID__);
+			if (brush_blending_handle.init) {
+				brush_blending_handle.value = context_raw.brush_blending;
+			}
 			context_raw.brush_blending = zui_combo(brush_blending_handle, [
 				tr("Mix"),
 				tr("Darken"),
@@ -454,15 +504,27 @@ function ui_header_draw_tool_properties(ui: zui_t) {
 			}
 			ui._w = math_floor((touch_header ? 54 : 60) * sc);
 
-			let xray_handle: zui_handle_t = zui_handle(__ID__, { selected: context_raw.xray });
+			let xray_handle: zui_handle_t = zui_handle(__ID__);
+			if (xray_handle.init) {
+				xray_handle.selected = context_raw.xray;
+			}
 			context_raw.xray = zui_check(xray_handle, tr("X-Ray"));
 			if (xray_handle.changed) {
 				make_material_parse_paint_material();
 			}
 
-			let sym_x_handle: zui_handle_t = zui_handle(__ID__, { selected: false });
-			let sym_y_handle: zui_handle_t = zui_handle(__ID__, { selected: false });
-			let sym_z_handle: zui_handle_t = zui_handle(__ID__, { selected: false });
+			let sym_x_handle: zui_handle_t = zui_handle(__ID__);
+			if (sym_x_handle.init) {
+				sym_x_handle.selected = false;
+			}
+			let sym_y_handle: zui_handle_t = zui_handle(__ID__);
+			if (sym_y_handle.init) {
+				sym_y_handle.selected = false;
+			}
+			let sym_z_handle: zui_handle_t = zui_handle(__ID__);
+			if (sym_z_handle.init) {
+				sym_z_handle.selected = false;
+			}
 
 			if (config_raw.layout[layout_size_t.HEADER] == 1) {
 				if (config_raw.touch_ui) {
@@ -502,7 +564,10 @@ function ui_header_draw_tool_properties(ui: zui_t) {
 		///if arm_physics
 		if (context_raw.tool == workspace_tool_t.PARTICLE) {
 			ui._x += 10 * zui_SCALE(ui);
-			let phys_handle: zui_handle_t = zui_handle(__ID__, { selected: false });
+			let phys_handle: zui_handle_t = zui_handle(__ID__);
+			if (phys_handle.init) {
+				phys_handle.selected = false;
+			}
 			context_raw.particle_physics = zui_check(phys_handle, tr("Physics"));
 			if (phys_handle.changed) {
 				util_particle_init_physics();

+ 29 - 7
base/Sources/ui_menu.ts

@@ -245,7 +245,10 @@ function ui_menu_render() {
 
 			///if (is_paint || is_sculpt)
 			ui_menu_fill(ui);
-			let split_view_handle: zui_handle_t = zui_handle(__ID__, { selected: context_raw.split_view });
+			let split_view_handle = zui_handle(__ID__);
+			if (split_view_handle.init) {
+				split_view_handle.selected = context_raw.split_view;
+			}
 			context_raw.split_view = zui_check(split_view_handle, " " + tr("Split View"));
 			if (split_view_handle.changed) {
 				base_resize();
@@ -254,7 +257,10 @@ function ui_menu_render() {
 
 			///if is_lab
 			ui_menu_fill(ui);
-			let brush_scale_handle: zui_handle_t = zui_handle(__ID__, { value: context_raw.brush_scale });
+			let brush_scale_handle: zui_handle_t = zui_handle(__ID__);
+			if (brush_scale_handle.init) {
+				brush_scale_handle.value = context_raw.brush_scale;
+			}
 			ui_menu_align(ui);
 			context_raw.brush_scale = zui_slider(brush_scale_handle, tr("UV Scale"), 0.01, 5.0, true);
 			if (brush_scale_handle.changed) {
@@ -267,14 +273,20 @@ function ui_menu_render() {
 			///end
 
 			ui_menu_fill(ui);
-			let cull_handle: zui_handle_t = zui_handle(__ID__, { selected: context_raw.cull_backfaces });
+			let cull_handle: zui_handle_t = zui_handle(__ID__);
+			if (cull_handle.init) {
+				cull_handle.selected = context_raw.cull_backfaces;
+			}
 			context_raw.cull_backfaces = zui_check(cull_handle, " " + tr("Cull Backfaces"));
 			if (cull_handle.changed) {
 				make_material_parse_mesh_material();
 			}
 
 			ui_menu_fill(ui);
-			let filter_handle: zui_handle_t = zui_handle(__ID__, { selected: context_raw.texture_filter });
+			let filter_handle: zui_handle_t = zui_handle(__ID__);
+			if (filter_handle.init) {
+				filter_handle.selected = context_raw.texture_filter;
+			}
 			context_raw.texture_filter = zui_check(filter_handle, " " + tr("Filter Textures"));
 			if (filter_handle.changed) {
 				make_material_parse_paint_material();
@@ -302,7 +314,10 @@ function ui_menu_render() {
 			///end
 
 			ui_menu_fill(ui);
-			let compass_handle: zui_handle_t = zui_handle(__ID__, { selected: context_raw.show_compass });
+			let compass_handle: zui_handle_t = zui_handle(__ID__);
+			if (compass_handle.init) {
+				compass_handle.selected = context_raw.show_compass;
+			}
 			context_raw.show_compass = zui_check(compass_handle, " " + tr("Compass"));
 			if (compass_handle.changed) {
 				context_raw.ddirty = 2;
@@ -430,7 +445,10 @@ function ui_menu_render() {
 
 			ui_menu_fill(ui);
 			let cam: camera_object_t = scene_camera;
-			context_raw.fov_handle = zui_handle(__ID__, { value: math_floor(cam.data.fov * 100) / 100 });
+			context_raw.fov_handle = zui_handle(__ID__);
+			if (context_raw.fov_handle.init) {
+				context_raw.fov_handle.value = math_floor(cam.data.fov * 100) / 100;
+			}
 			ui_menu_align(ui);
 			cam.data.fov = zui_slider(context_raw.fov_handle, tr("FoV"), 0.3, 1.4, true);
 			if (context_raw.fov_handle.changed) {
@@ -570,7 +588,11 @@ function ui_menu_render() {
 						zui_image(img);
 						zui_end_element();
 
-						zui_text_area(zui_handle(__ID__, { text: _ui_menu_render_msg }), zui_align_t.LEFT, false);
+						let h: zui_handle_t = zui_handle(__ID__);
+						if (h.init) {
+							h.text = _ui_menu_render_msg;
+						}
+						zui_text_area(h, zui_align_t.LEFT, false);
 
 						zui_row([1 / 3, 1 / 3, 1 / 3]);
 

+ 4 - 2
base/Sources/ui_menubar.ts

@@ -1,7 +1,7 @@
 
 let ui_menubar_default_w: i32 = 330;
-let ui_menubar_workspace_handle: zui_handle_t = zui_handle_create({ layout: zui_layout_t.HORIZONTAL });
-let ui_menubar_menu_handle: zui_handle_t = zui_handle_create({ layout: zui_layout_t.HORIZONTAL });
+let ui_menubar_workspace_handle: zui_handle_t = zui_handle_create();
+let ui_menubar_menu_handle: zui_handle_t = zui_handle_create();
 let ui_menubar_w: i32 = ui_menubar_default_w;
 
 ///if is_lab
@@ -10,6 +10,8 @@ let _ui_menubar_plane: mesh_object_t = null;
 ///end
 
 function ui_menubar_init() {
+	ui_menubar_workspace_handle.layout = zui_layout_t.HORIZONTAL;
+	ui_menubar_menu_handle.layout = zui_layout_t.HORIZONTAL;
 }
 
 function ui_menubar_render_ui() {

+ 55 - 13
base/Sources/ui_nodes.ts

@@ -149,7 +149,7 @@ function ui_nodes_on_socket_released(socket_id: i32) {
 							}
 						}
 						else {
-							_ui_nodes_hval0.value = socket.default_value;
+							_ui_nodes_hval0.value = socket.default_value[0];
 						}
 
 						app_notify_on_next_frame(function () {
@@ -1308,7 +1308,7 @@ function ui_nodes_accept_asset_drag(index: i32) {
 	let n: zui_node_t = nodes_brush_create_node("ImageTextureNode");
 	///end
 
-	n.buttons[0].default_value = index;
+	n.buttons[0].default_value[0] = index;
 	ui_nodes_get_nodes().nodes_selected_id = [n.id];
 
 	///if is_lab
@@ -1324,7 +1324,7 @@ function ui_nodes_accept_layer_drag(index: i32) {
 	}
 	let g: node_group_t = ui_nodes_group_stack.length > 0 ? ui_nodes_group_stack[ui_nodes_group_stack.length - 1] : null;
 	let n: zui_node_t = nodes_material_create_node(slot_layer_is_mask(context_raw.layer) ? "LAYER_MASK" : "LAYER", g);
-	n.buttons[0].default_value = index;
+	n.buttons[0].default_value[0] = index;
 	ui_nodes_get_nodes().nodes_selected_id = [n.id];
 }
 
@@ -1332,7 +1332,7 @@ function ui_nodes_accept_material_drag(index: i32) {
 	ui_nodes_push_undo();
 	let g: node_group_t = ui_nodes_group_stack.length > 0 ? ui_nodes_group_stack[ui_nodes_group_stack.length - 1] : null;
 	let n: zui_node_t = nodes_material_create_node("MATERIAL", g);
-	n.buttons[0].default_value = index;
+	n.buttons[0].default_value[0] = index;
 	ui_nodes_get_nodes().nodes_selected_id = [n.id];
 }
 ///end
@@ -1342,34 +1342,76 @@ function ui_nodes_accept_swatch_drag(swatch: swatch_color_t) {
 	ui_nodes_push_undo();
 	let g: node_group_t = ui_nodes_group_stack.length > 0 ? ui_nodes_group_stack[ui_nodes_group_stack.length - 1] : null;
 	let n: zui_node_t = nodes_material_create_node("RGB", g);
-	n.outputs[0].default_value = [
+	n.outputs[0].default_value = f32_array_create_xyzw(
 		color_get_rb(swatch.base) / 255,
 		color_get_gb(swatch.base) / 255,
 		color_get_bb(swatch.base) / 255,
 		color_get_ab(swatch.base) / 255
-	];
+	);
 	ui_nodes_get_nodes().nodes_selected_id = [n.id];
 	///end
 }
 
 function ui_nodes_make_node(n: zui_node_t, nodes: zui_nodes_t, canvas: zui_node_canvas_t): zui_node_t {
-	let node: zui_node_t = json_parse(json_stringify(n));
+	let node: zui_node_t = {};
 	node.id = zui_get_node_id(canvas.nodes);
+	node.name = n.name;
+	node.type = n.type;
 	node.x = ui_nodes_get_node_x();
 	node.y = ui_nodes_get_node_y();
+	node.color = n.color;
+	node.inputs = [];
+	node.outputs = [];
+	node.buttons = [];
+	node.width = 0;
+
 	let count: i32 = 0;
-	for (let i: i32 = 0; i < node.inputs.length; ++i) {
-		let soc: zui_node_socket_t = node.inputs[i];
+	for (let i: i32 = 0; i < n.inputs.length; ++i) {
+		let soc: zui_node_socket_t = {}
 		soc.id = zui_get_socket_id(canvas.nodes) + count;
-		soc.node_id = node.id;
 		count++;
+		soc.node_id = node.id;
+		soc.name = n.inputs[i].name;
+		soc.type = n.inputs[i].type;
+		soc.color = n.inputs[i].color;
+		soc.default_value = n.inputs[i].default_value;
+		soc.min = n.inputs[i].min;
+		soc.max = n.inputs[i].max;
+		soc.precision = n.inputs[i].precision;
+		soc.display = n.inputs[i].display;
+		array_push(node.inputs, soc);
 	}
-	for (let i: i32 = 0; i < node.outputs.length; ++i) {
-		let soc: zui_node_socket_t = node.outputs[i];
+
+	for (let i: i32 = 0; i < n.outputs.length; ++i) {
+		let soc: zui_node_socket_t = {};
 		soc.id = zui_get_socket_id(canvas.nodes) + count;
-		soc.node_id = node.id;
 		count++;
+		soc.node_id = node.id;
+		soc.name = n.outputs[i].name;
+		soc.type = n.outputs[i].type;
+		soc.color = n.outputs[i].color;
+		soc.default_value = n.outputs[i].default_value;
+		soc.min = n.outputs[i].min;
+		soc.max = n.outputs[i].max;
+		soc.precision = n.outputs[i].precision;
+		soc.display = n.outputs[i].display;
+		array_push(node.outputs, soc);
 	}
+
+	for (let i: i32 = 0; i < n.buttons.length; ++i) {
+		let but: zui_node_button_t = {};
+		but.name = n.buttons[i].name;
+		but.type = n.buttons[i].type;
+		but.output = n.buttons[i].output;
+		but.default_value = n.buttons[i].default_value;
+		but.data = n.buttons[i].data;
+		but.min = n.buttons[i].min;
+		but.max = n.buttons[i].max;
+		but.precision = n.buttons[i].precision;
+		but.height = n.buttons[i].height;
+		array_push(node.buttons, but);
+	}
+
 	return node;
 }
 

+ 20 - 4
base/Sources/ui_view2d.ts

@@ -351,7 +351,11 @@ function ui_view2d_render() {
 
 		///if (is_paint || is_sculpt)
 		if (ui_view2d_type == view_2d_type_t.LAYER) {
-			ui_view2d_layer_mode = zui_combo(zui_handle(__ID__, { position: ui_view2d_layer_mode }), [
+			let h_layer_mode: zui_handle_t = zui_handle(__ID__);
+			if (h_layer_mode.init) {
+				h_layer_mode.position = ui_view2d_layer_mode;
+			}
+			ui_view2d_layer_mode = zui_combo(h_layer_mode, [
 				tr("Visible"),
 				tr("Selected"),
 			], tr("Layers"));
@@ -359,7 +363,11 @@ function ui_view2d_render() {
 			ui_view2d_ui._y = 2 + start_y;
 
 			if (!slot_layer_is_mask(context_raw.layer)) {
-				ui_view2d_tex_type = zui_combo(zui_handle(__ID__, { position: ui_view2d_tex_type }), [
+				let h_tex_type: zui_handle_t = zui_handle(__ID__);
+				if (h_tex_type.init) {
+					h_tex_type.position = ui_view2d_tex_type;
+				}
+				ui_view2d_tex_type = zui_combo(h_tex_type, [
 					tr("Base Color"),
 					tr("Normal Map"),
 					tr("Occlusion"),
@@ -373,13 +381,21 @@ function ui_view2d_render() {
 			}
 
 			ui_view2d_ui._w = math_floor(ew * 0.7 + 3);
-			ui_view2d_uvmap_show = zui_check(zui_handle(__ID__, { selected: ui_view2d_uvmap_show }), tr("UV Map"));
+			let h_uvmap_show: zui_handle_t = zui_handle(__ID__);
+			if (h_uvmap_show.init) {
+				h_uvmap_show.selected = ui_view2d_uvmap_show;
+			}
+			ui_view2d_uvmap_show = zui_check(h_uvmap_show, tr("UV Map"));
 			ui_view2d_ui._x += ew * 0.7 + 3;
 			ui_view2d_ui._y = 2 + start_y;
 		}
 		///end
 
-		ui_view2d_tiled_show = zui_check(zui_handle(__ID__, { selected: ui_view2d_tiled_show }), tr("Tiled"));
+		let h_tiled_show: zui_handle_t = zui_handle(__ID__);
+		if (h_tiled_show.init) {
+			h_tiled_show.selected = ui_view2d_tiled_show;
+		}
+		ui_view2d_tiled_show = zui_check(h_tiled_show, tr("Tiled"));
 		ui_view2d_ui._x += ew * 0.7 + 3;
 		ui_view2d_ui._y = 2 + start_y;
 

+ 0 - 35
misc/pad/Assets/themes/dark.json

@@ -1,35 +0,0 @@
-{
-	"WINDOW_BG_COL": 4278190080,
-	"WINDOW_TINT_COL": 4294967295,
-	"ACCENT_COL": 4282598211,
-	"ACCENT_HOVER_COL": 4282598211,
-	"ACCENT_SELECT_COL": 4283453520,
-	"BUTTON_COL": 4278190080,
-	"BUTTON_TEXT_COL": 4293453797,
-	"BUTTON_HOVER_COL": 4282992969,
-	"BUTTON_PRESSED_COL": 4279966491,
-	"TEXT_COL": 4293453797,
-	"LABEL_COL": 4291348680,
-	"SEPARATOR_COL": 4278519045,
-	"HIGHLIGHT_COL": 4282992969,
-	"CONTEXT_COL": 4280427042,
-	"PANEL_BG_COL": 4278190080,
-	"FONT_SIZE": 24,
-	"ELEMENT_W": 100,
-	"ELEMENT_H": 24,
-	"ELEMENT_OFFSET": 4,
-	"ARROW_SIZE": 5,
-	"BUTTON_H": 22,
-	"CHECK_SIZE": 15,
-	"CHECK_SELECT_SIZE": 8,
-	"SCROLL_W": 9,
-	"SCROLL_MINI_W": 3,
-	"TEXT_OFFSET": 8,
-	"TAB_W": 16,
-	"FILL_WINDOW_BG": true,
-	"FILL_BUTTON_BG": false,
-	"FILL_ACCENT_BG": false,
-	"LINK_STYLE": 0,
-	"FULL_TABS": false,
-	"ROUND_CORNERS": false
-}

+ 57 - 68
misc/pad/Sources/main.ts

@@ -13,6 +13,7 @@ type storage_t = {
 };
 
 let ui: zui_t;
+let theme: zui_theme_t;
 let text_handle: zui_handle_t = zui_handle_create();
 let sidebar_handle: zui_handle_t = zui_handle_create();
 let editor_handle: zui_handle_t = zui_handle_create();
@@ -31,14 +32,13 @@ function drop_files(path: string) {
 }
 
 function shutdown() {
-	krom_file_save_bytes(krom_save_path() + "/config.json", sys_string_to_buffer(json_stringify(storage)));
+	let storage_string: string = sys_string_to_buffer(json_stringify(storage));
+	krom_file_save_bytes(krom_save_path() + "/config.json", storage_string, 0);
 }
 
 function main() {
-	zui_set_text_area_line_numbers(true);
-	zui_set_text_area_scroll_past_end(true);
-
 	krom_set_app_name("ArmorPad");
+
 	let blob_storage: buffer_t = krom_load_blob(krom_save_path() + "/config.json");
 	if (blob_storage == null) {
 		storage = {};
@@ -59,47 +59,37 @@ function main() {
 
 	text_handle.text = storage.text;
 
-	let ops: kinc_sys_ops_t = {};
-	ops.title = "ArmorPad";
-	ops.x = storage.window_x;
-	ops.y = storage.window_y;
-	ops.width = storage.window_w;
-	ops.height = storage.window_h;
-	ops.features = window_features_t.RESIZABLE | window_features_t.MAXIMIZABLE | window_features_t.MINIMIZABLE;
-	ops.mode = window_mode_t.WINDOWED;
-	ops.frequency = 60;
-	ops.vsync = true;
+	let ops: kinc_sys_ops_t = {
+		title: "ArmorPad",
+		x: storage.window_x,
+		y: storage.window_y,
+		width: storage.window_w,
+		height: storage.window_h,
+		features: window_features_t.RESIZABLE |
+				  window_features_t.MAXIMIZABLE |
+				  window_features_t.MINIMIZABLE,
+		mode: window_mode_t.WINDOWED,
+		frequency: 60,
+		vsync: true,
+	};
 	sys_start(ops);
 
 	let font: g2_font_t = data_get_font("font_mono.ttf");
-	let blob_theme: buffer_t = data_get_blob("themes/dark.json");
-	let blob_coloring: buffer_t = data_get_blob("text_coloring.json");
-	let parsed: any = json_parse(sys_buffer_to_string(blob_theme));
-	let theme: any = zui_theme_create();
-	for (let key of Object.getOwnPropertyNames(theme_t.prototype)) {
-		if (key == "constructor") {
-			continue;
-		}
-		theme[key] = parsed[key];
-	}
-
 	g2_font_init(font);
-	let zui_ops: zui_ops_t = {};
-	zui_ops.theme = theme;
-	zui_ops.font = font;
-	zui_ops.scaleFactor = 1.0;
-	zui_ops.color_wheel = null;
-	zui_ops.black_white_gradient = null;
+
+	theme = {};
+	zui_theme_default(theme);
+
+	let zui_ops: zui_options_t = { scale_factor: 1.0, theme: theme, font: font.font_ };
 	ui = zui_create(zui_ops);
-	zui_set_on_border_hover(on_border_hover);
-	zui_set_on_text_hover(on_text_hover);
 
+	let blob_coloring: buffer_t = data_get_blob("text_coloring.json");
 	let text_coloring: zui_text_coloring_t = json_parse(sys_buffer_to_string(blob_coloring));
-	text_coloring.default_color = math_floor(text_coloring.default_color);
-	for (let coloring of text_coloring.colorings) {
-		coloring.color = math_floor(coloring.color);
-	}
-	zui_set_text_area_coloring(text_coloring);
+	zui_text_area_coloring = text_coloring;
+	zui_on_border_hover = on_border_hover;
+	zui_on_text_hover = on_text_hover;
+	zui_text_area_line_numbers = true;
+	zui_text_area_scroll_past_end = true;
 
 	sys_notify_on_frames(render);
 	krom_set_drop_files_callback(drop_files);
@@ -116,7 +106,7 @@ function list_folder(path: string) {
 
 		// Active file
 		if (abs == storage.file) {
-			zui_fill(0, 1, ui._w - 1, zui_ELEMENT_H(ui) - 1, ui.t.BUTTON_PRESSED_COL);
+			zui_fill(0, 1, ui._w - 1, ZUI_ELEMENT_H() - 1, theme.BUTTON_PRESSED_COL);
 		}
 
 		let prefix: string = "";
@@ -124,7 +114,7 @@ function list_folder(path: string) {
 			prefix = is_expanded ? "- " : "+ ";
 		}
 
-		if (zui_button(prefix + f, Align.Left)) {
+		if (zui_button(prefix + f, ZUI_ALIGN_LEFT, "")) {
 			// Open file
 			if (is_file) {
 				storage.file = abs;
@@ -142,9 +132,7 @@ function list_folder(path: string) {
 		}
 
 		if (is_expanded) {
-			// ui.indent(false);
 			list_folder(abs);
-			// ui.unindent(false);
 		}
 	}
 }
@@ -161,41 +149,46 @@ function render() {
 	zui_begin(ui);
 
 	if (zui_window(sidebar_handle, 0, 0, storage.sidebar_w, sys_height(), false)) {
-		let _BUTTON_TEXT_COL: i32 = ui.t.BUTTON_TEXT_COL;
-		ui.t.BUTTON_TEXT_COL = ui.t.ACCENT_COL;
+		let _BUTTON_TEXT_COL: i32 = theme.BUTTON_TEXT_COL;
+		theme.BUTTON_TEXT_COL = theme.ACCENT_COL;
 		if (storage.project != "") {
 			list_folder(storage.project);
 		}
 		else {
-			zui_button("Drop folder here", Align.Left);
+			zui_button("Drop folder here", ZUI_ALIGN_LEFT, "");
 		}
-		ui.t.BUTTON_TEXT_COL = _BUTTON_TEXT_COL;
+		theme.BUTTON_TEXT_COL = _BUTTON_TEXT_COL;
 	}
 
-	zui_fill(sys_width() - minimap_w, 0, minimap_w, zui_ELEMENT_H(ui) + zui_ELEMENT_OFFSET(ui) + 1, ui.t.SEPARATOR_COL);
-	zui_fill(storage.sidebar_w, 0, 1, sys_height(), ui.t.SEPARATOR_COL);
+	zui_fill(sys_width() - minimap_w, 0, minimap_w, ZUI_ELEMENT_H() + ZUI_ELEMENT_OFFSET() + 1, theme.SEPARATOR_COL);
+	zui_fill(storage.sidebar_w, 0, 1, sys_height(), theme.SEPARATOR_COL);
 
 	let editor_updated: bool = false;
 
 	if (zui_window(editor_handle, storage.sidebar_w + 1, 0, sys_width() - storage.sidebar_w - minimap_w, sys_height(), false)) {
 		editor_updated = true;
-		let htab: zui_handle_t = zui_handle("main_0", { position: 0 });
-		let file_name: string = substring(storage.file, string_last_index_of(storage.file, "/") + 1);
+		let htab: zui_handle_t = zui_handle(__ID__);
+		let file_name: string = substring(storage.file, string_last_index_of(storage.file, "/") + 1, storage.file.length);
 		let file_names: string[] = [file_name];
 
-		for (let file_name of file_names) {
-			if (zui_tab(htab, file_name + (storage.modified ? "*" : ""))) {
+		for (let i: i32 = 0; i < file_names.length; ++i) {
+			let tab_name: string = file_names[i];
+			if (storage.modified) {
+				tab_name += "*";
+			}
+			if (zui_tab(htab, tab_name, false, -1)) {
 				// File modified
 				if (ui.is_key_pressed) {
 					storage.modified = true;
 				}
 
 				// Save
-				if (ui.is_ctrl_down && ui.key == key_code_t.S) {
+				if (ui.is_ctrl_down && ui.key_code == key_code_t.S) {
 					save_file();
 				}
 
-				storage.text = zui_text_area(text_handle);
+				// storage.text = zui_text_area(text_handle, ZUI_ALIGN_LEFT, true, "", false);
+				zui_text_area(text_handle, ZUI_ALIGN_LEFT, true, "", false);
 			}
 		}
 
@@ -220,18 +213,16 @@ function render() {
 		minimap_scrolling = false;
 	}
 	if (minimap_scrolling) {
-		// editor_handle.scroll_offset -= ui.input_dy * zui_ELEMENT_H(ui) / 2;
-		// // editor_handle.scroll_offset = -((ui.input_y - minimap_y - minimap_box_h / 2) * zui_ELEMENT_H(ui) / 2);
 		redraw = true;
 	}
 
 	// Build project
-	if (ui.is_ctrl_down && ui.key == key_code_t.B) {
+	if (ui.is_ctrl_down && ui.key_code == key_code_t.B) {
 		save_file();
 		build_project();
 	}
 
-	zui_end();
+	zui_end(false);
 
 	if (redraw) {
 		editor_handle.redraws = 2;
@@ -251,16 +242,16 @@ function render() {
 function save_file() {
 	// Trim
 	let lines: string[] = string_split(storage.text, "\n");
-	for (let i = 0; i < lines.length; ++i) {
+	for (let i: i32 = 0; i < lines.length; ++i) {
 		lines[i] = trim_end(lines[i]);
 	}
-	storage.text = lines.join("\n");
+	storage.text = string_array_join(lines, "\n");
 	// Spaces to tabs
 	storage.text = string_replace_all(storage.text, "    ", "\t");
 	text_handle.text = storage.text;
 	// Write bytes
-	let bytes = ends_with(storage.file, ".arm") ? armpack_encode(json_parse(storage.text)) : sys_string_to_buffer(storage.text);
-	krom_file_save_bytes(storage.file, bytes, buffer_size(bytes));
+	// let bytes: buffer_t = ends_with(storage.file, ".arm") ? armpack_encode(json_parse(storage.text)) : sys_string_to_buffer(storage.text);
+	// krom_file_save_bytes(storage.file, bytes, buffer_size(bytes));
 	storage.modified = false;
 }
 
@@ -273,7 +264,7 @@ function build_file(): string {
 }
 
 function build_project() {
-	krom_sys_command(storage.project + build_file() + " " + storage.project);
+	krom_sys_command(storage.project + build_file() + " " + storage.project, null);
 }
 
 function draw_minimap() {
@@ -286,11 +277,11 @@ function draw_minimap() {
 	}
 
 	g2_begin(minimap);
-	g2_clear(ui.t.SEPARATOR_COL);
+	g2_clear(theme.SEPARATOR_COL);
 	g2_set_color(0xff333333);
 	let lines: string[] = string_split(storage.text, "\n");
 	let minimap_full_h: i32 = lines.length * 2;
-	let scroll_progress: f32 = -editor_handle.scroll_offset / (lines.length * zui_ELEMENT_H(ui));
+	let scroll_progress: f32 = -editor_handle.scroll_offset / (lines.length * ZUI_ELEMENT_H());
 	let out_of_screen: i32 = minimap_full_h - minimap_h;
 	if (out_of_screen < 0) {
 		out_of_screen = 0;
@@ -314,7 +305,7 @@ function draw_minimap() {
 	// Current position
 	let visible_area: i32 = out_of_screen > 0 ? minimap_h : minimap_full_h;
 	g2_set_color(0x11ffffff);
-	minimap_box_h = math_floor((sys_height() - window_header_h) / zui_ELEMENT_H(ui) * 2);
+	minimap_box_h = math_floor((sys_height() - window_header_h) / ZUI_ELEMENT_H() * 2);
 	g2_fill_rect(0, scroll_progress * visible_area, minimap_w, minimap_box_h);
 	g2_end();
 }
@@ -341,5 +332,3 @@ function on_border_hover(handle: zui_handle_t, side: i32) {
 function on_text_hover() {
 	krom_set_mouse_cursor(2); // I-cursor
 }
-
-main();

+ 1 - 1
misc/pad/project.js

@@ -2,6 +2,7 @@
 let flags = globalThis.flags;
 flags.name = 'ArmorPad';
 flags.package = 'org.armorpad';
+flags.with_minits = true;
 flags.with_nfd = true;
 flags.with_tinydir = true;
 flags.with_g2 = true;
@@ -14,7 +15,6 @@ flags.on_c_project_created = function(c_project, platform, graphics) {
 let project = new Project("ArmorPad");
 let root = "../../";
 project.addSources("Sources");
-project.addAssets("Assets/themes/*.json", { destination: "data/themes/{name}" });
 project.addShaders(root + "armorcore/Shaders/*.glsl",);
 project.addAssets(root + "base/Assets/font_mono.ttf", { destination: "data/{name}" });
 project.addAssets(root + "base/Assets/text_coloring.json", { destination: "data/{name}" });

Some files were not shown because too many files changed in this diff