luboslenco 1 年之前
父節點
當前提交
73b3948643
共有 100 個文件被更改,包括 1062 次插入8146 次删除
  1. 二進制
      armorforge/Assets/Scene.arm
  2. 8 8
      armorforge/Sources/TabObjects.ts
  3. 二進制
      armorlab/Assets/Scene.arm
  4. 6 6
      armorlab/Sources/MakeMesh.ts
  5. 1 1
      armorlab/Sources/NodesBrush.ts
  6. 7 7
      armorlab/Sources/RenderPathPaint.ts
  7. 6 6
      armorlab/Sources/UINodesExt.ts
  8. 8 8
      armorlab/Sources/nodes/InpaintNode.ts
  9. 20 20
      armorlab/Sources/nodes/PhotoToPBRNode.ts
  10. 12 12
      armorlab/Sources/nodes/TextToPhotoNode.ts
  11. 1 1
      armorlab/Sources/nodes/TilingNode.ts
  12. 10 10
      armorlab/Sources/nodes/UpscaleNode.ts
  13. 4 4
      armorlab/Sources/nodes/VarianceNode.ts
  14. 二進制
      armorpaint/Assets/Scene.arm
  15. 2 2
      armorpaint/Sources/ImportFolder.ts
  16. 3 3
      armorpaint/Sources/MakeBake.ts
  17. 1 1
      armorpaint/Sources/MakeBrush.ts
  18. 2 2
      armorpaint/Sources/MakeColorIdPicker.ts
  19. 24 23
      armorpaint/Sources/MakeMaterial.ts
  20. 6 6
      armorpaint/Sources/MakeMesh.ts
  21. 5 5
      armorpaint/Sources/MakeMeshPreview.ts
  22. 2 2
      armorpaint/Sources/MakePaint.ts
  23. 1 1
      armorpaint/Sources/NodesBrush.ts
  24. 15 15
      armorpaint/Sources/RenderPathPaint.ts
  25. 8 8
      armorpaint/Sources/RenderPathPreview.ts
  26. 5 5
      armorpaint/Sources/SlotLayer.ts
  27. 1 1
      armorpaint/Sources/SlotMaterial.ts
  28. 90 90
      armorpaint/Sources/TabLayers.ts
  29. 3 3
      armorpaint/Sources/nodes/BrushOutputNode.ts
  30. 2 2
      armorpaint/Sources/nodes/InputNode.ts
  31. 二進制
      armorsculpt/Assets/Scene.arm
  32. 7 7
      armorsculpt/Sources/ExportObj.ts
  33. 7 7
      armorsculpt/Sources/ImportMesh.ts
  34. 14 13
      armorsculpt/Sources/MakeMaterial.ts
  35. 6 6
      armorsculpt/Sources/MakeMesh.ts
  36. 5 5
      armorsculpt/Sources/MakeMeshPreview.ts
  37. 1 1
      armorsculpt/Sources/MakeSculpt.ts
  38. 21 21
      armorsculpt/Sources/TabLayers.ts
  39. 2 2
      armorsculpt/Sources/nodes/BrushOutputNode.ts
  40. 28 28
      base/Sources/BoxExport.ts
  41. 56 56
      base/Sources/BoxPreferences.ts
  42. 20 19
      base/Sources/BoxProjects.ts
  43. 1 1
      base/Sources/ContextFormat.ts
  44. 9 9
      base/Sources/ExportArm.ts
  45. 10 10
      base/Sources/ExportObj.ts
  46. 10 10
      base/Sources/ExportTexture.ts
  47. 18 18
      base/Sources/ImportArm.ts
  48. 8 8
      base/Sources/ImportAsset.ts
  49. 16 16
      base/Sources/ImportBlendMaterial.ts
  50. 56 56
      base/Sources/ImportBlendMesh.ts
  51. 7 7
      base/Sources/ImportEnvmap.ts
  52. 2 2
      base/Sources/ImportFont.ts
  53. 11 11
      base/Sources/ImportMesh.ts
  54. 12 12
      base/Sources/ImportObj.ts
  55. 1 1
      base/Sources/ImportTexture.ts
  56. 1 1
      base/Sources/NodeShader.ts
  57. 11 11
      base/Sources/NodesMaterial.ts
  58. 1 1
      base/Sources/ParserBlend.ts
  59. 7 7
      base/Sources/ParserLogic.ts
  60. 32 32
      base/Sources/ParserMaterial.ts
  61. 6 6
      base/Sources/PhysicsBody.ts
  62. 1 1
      base/Sources/PhysicsWorld.ts
  63. 5 5
      base/Sources/RenderPathBase.ts
  64. 1 1
      base/Sources/RenderPathRaytrace.ts
  65. 0 524
      base/Sources/ShaderFunctions.ts
  66. 22 22
      base/Sources/TabBrowser.ts
  67. 16 16
      base/Sources/TabBrushes.ts
  68. 5 5
      base/Sources/TabConsole.ts
  69. 17 17
      base/Sources/TabFonts.ts
  70. 1 1
      base/Sources/TabHistory.ts
  71. 34 34
      base/Sources/TabMaterials.ts
  72. 32 32
      base/Sources/TabMeshes.ts
  73. 1 1
      base/Sources/TabPlugins.ts
  74. 9 9
      base/Sources/TabScript.ts
  75. 19 19
      base/Sources/TabSwatches.ts
  76. 30 30
      base/Sources/TabTextures.ts
  77. 0 1533
      base/Sources/UIBase.ts
  78. 0 187
      base/Sources/UIBox.ts
  79. 0 387
      base/Sources/UIFiles.ts
  80. 0 502
      base/Sources/UIHeader.ts
  81. 0 625
      base/Sources/UIMenu.ts
  82. 0 187
      base/Sources/UIMenubar.ts
  83. 0 1291
      base/Sources/UINodes.ts
  84. 0 51
      base/Sources/UIStatus.ts
  85. 0 207
      base/Sources/UIToolbar.ts
  86. 0 459
      base/Sources/UIView2D.ts
  87. 0 380
      base/Sources/UtilMesh.ts
  88. 0 116
      base/Sources/UtilParticle.ts
  89. 0 451
      base/Sources/UtilRender.ts
  90. 0 190
      base/Sources/UtilUV.ts
  91. 3 3
      base/Sources/args.ts
  92. 105 104
      base/Sources/base.ts
  93. 6 6
      base/Sources/camera.ts
  94. 16 15
      base/Sources/config.ts
  95. 1 1
      base/Sources/console.ts
  96. 40 39
      base/Sources/context.ts
  97. 5 5
      base/Sources/file.ts
  98. 22 22
      base/Sources/geom.ts
  99. 7 7
      base/Sources/gizmo.ts
  100. 25 25
      base/Sources/history.ts

二進制
armorforge/Assets/Scene.arm


+ 8 - 8
armorforge/Sources/TabObjects.ts

@@ -4,12 +4,12 @@ class TabObjects {
 	static materialId = 0;
 
 	static roundfp = (f: f32, precision = 2): f32 => {
-		f *= Math.pow(10, precision);
-		return Math.round(f) / Math.pow(10, precision);
+		f *= math_pow(10, precision);
+		return math_round(f) / math_pow(10, precision);
 	}
 
 	static draw = (htab: zui_handle_t) => {
-		let ui = UIBase.ui;
+		let ui = ui_base_ui;
 		if (zui_tab(htab, tr("Objects"))) {
 			zui_begin_sticky();
 			zui_row([1 / 4]);
@@ -72,13 +72,13 @@ class TabObjects {
 					}
 
 					if (ui.is_hovered && ui.input_released_r) {
-						UIMenu.draw((ui: zui_t) => {
-							if (UIMenu.menu_button(ui, "Assign Material")) {
+						ui_menu_draw((ui: zui_t) => {
+							if (ui_menu_button(ui, "Assign Material")) {
 								TabObjects.materialId++;
 
 								for (let sh of _scene_raw.shader_datas) {
 									if (sh.name == "Material_data") {
-										let s: shader_data_t = JSON.parse(JSON.stringify(sh));
+										let s: shader_data_t = json_parse(json_stringify(sh));
 										s.name = "TempMaterial_data" + TabObjects.materialId;
 										_scene_raw.shader_datas.push(s);
 										break;
@@ -87,7 +87,7 @@ class TabObjects {
 
 								for (let mat of _scene_raw.material_datas) {
 									if (mat.name == "Material") {
-										let m: material_data_t = JSON.parse(JSON.stringify(mat));
+										let m: material_data_t = json_parse(json_stringify(mat));
 										m.name = "TempMaterial" + TabObjects.materialId;
 										m.shader = "TempMaterial_data" + TabObjects.materialId;
 										_scene_raw.material_datas.push(m);
@@ -238,7 +238,7 @@ class TabObjects {
 					else if (context_context_raw.selected_object.ext_type == "camera_object_t") {
 						let cam = context_context_raw.selected_object.ext;
 						let fovHandle = zui_handle("tabobjects_18");
-						fovHandle.value = Math.floor(cam.data.fov * 100) / 100;
+						fovHandle.value = math_floor(cam.data.fov * 100) / 100;
 						cam.data.fov = zui_slider(fovHandle, "FoV", 0.3, 2.0, true);
 						if (fovHandle.changed) {
 							camera_object_build_proj(cam);

二進制
armorlab/Assets/Scene.arm


+ 6 - 6
armorlab/Sources/MakeMesh.ts

@@ -48,9 +48,9 @@ class MakeMesh {
 
 		NodeShader.add_out(frag, 'vec4 fragColor[3]');
 		frag.n = true;
-		NodeShader.add_function(frag, ShaderFunctions.str_packFloatInt16);
-		NodeShader.add_function(frag, ShaderFunctions.str_octahedronWrap);
-		NodeShader.add_function(frag, ShaderFunctions.str_cotangentFrame);
+		NodeShader.add_function(frag, str_packFloatInt16);
+		NodeShader.add_function(frag, str_octahedronWrap);
+		NodeShader.add_function(frag, str_cotangentFrame);
 
 		NodeShader.write(frag, 'vec3 basecol = vec3(0.0, 0.0, 0.0);');
 		NodeShader.write(frag, 'float roughness = 0.0;');
@@ -155,13 +155,13 @@ class MakeMesh {
 				NodeShader.add_uniform(frag, 'vec4 envmapData', '_envmapData'); // angle, sin(angle), cos(angle), strength
 				NodeShader.write(frag, 'vec3 wreflect = reflect(-vVec, n);');
 				NodeShader.write(frag, 'float envlod = roughness * float(envmapNumMipmaps);');
-				NodeShader.add_function(frag, ShaderFunctions.str_envMapEquirect);
+				NodeShader.add_function(frag, str_envMapEquirect);
 				NodeShader.write(frag, 'vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(wreflect, envmapData.x), envlod).rgb;');
 				NodeShader.add_uniform(frag, 'vec3 lightArea0', '_light_area0');
 				NodeShader.add_uniform(frag, 'vec3 lightArea1', '_light_area1');
 				NodeShader.add_uniform(frag, 'vec3 lightArea2', '_light_area2');
 				NodeShader.add_uniform(frag, 'vec3 lightArea3', '_light_area3');
-				NodeShader.add_function(frag, ShaderFunctions.str_ltcEvaluate);
+				NodeShader.add_function(frag, str_ltcEvaluate);
 				NodeShader.add_uniform(frag, 'vec3 lightPos', '_point_pos');
 				NodeShader.add_uniform(frag, 'vec3 lightColor', '_point_color');
 				NodeShader.write(frag, 'float ldist = distance(wposition, lightPos);');
@@ -181,7 +181,7 @@ class MakeMesh {
 				NodeShader.write(frag, 'direct *= lightColor * (1.0 / (ldist * ldist));');
 
 				NodeShader.add_uniform(frag, 'vec4 shirr[7]', '_envmap_irradiance');
-				NodeShader.add_function(frag, ShaderFunctions.str_shIrradiance);
+				NodeShader.add_function(frag, str_shIrradiance);
 				NodeShader.write(frag, 'vec3 indirect = albedo * (shIrradiance(vec3(n.x * envmapData.z - n.y * envmapData.y, n.x * envmapData.y + n.y * envmapData.z, n.z), shirr) / 3.14159265);');
 				NodeShader.write(frag, 'indirect += prefilteredColor * (f0 * envBRDF.x + envBRDF.y) * 1.5;');
 				NodeShader.write(frag, 'indirect *= envmapData.w * occlusion;');

+ 1 - 1
armorlab/Sources/NodesBrush.ts

@@ -32,7 +32,7 @@ class NodesBrush {
 				if (n.type == nodeType) {
 					let canvas = project_canvas;
 					let nodes = project_nodes;
-					let node = UINodes.makeNode(n, nodes, canvas);
+					let node = ui_nodes_makeNode(n, nodes, canvas);
 					canvas.nodes.push(node);
 					return node;
 				}

+ 7 - 7
armorlab/Sources/RenderPathPaint.ts

@@ -82,7 +82,7 @@ class RenderPathPaint {
 					render_path_bind_target("texpaint_nor" + tid, "texpaint_nor");
 					render_path_bind_target("texpaint_pack" + tid, "texpaint_pack");
 					render_path_draw_meshes("paint");
-					UIHeader.headerHandle.redraws = 2;
+					ui_header_headerHandle.redraws = 2;
 
 					let texpaint_picker = render_path_render_targets.get("texpaint_picker")._image;
 					let texpaint_nor_picker = render_path_render_targets.get("texpaint_nor_picker")._image;
@@ -163,8 +163,8 @@ class RenderPathPaint {
 			return;
 		}
 
-		let nodes = UINodes.getNodes();
-		let canvas = UINodes.getCanvas(true);
+		let nodes = ui_nodes_getNodes();
+		let canvas = ui_nodes_getCanvas(true);
 		let inpaint = nodes.nodesSelectedId.length > 0 && zui_get_node(canvas.nodes, nodes.nodesSelectedId[0]).type == "InpaintNode";
 
 		if (!base_uiEnabled || base_isDragging || !inpaint) {
@@ -252,8 +252,8 @@ class RenderPathPaint {
 
 	static bindLayers = () => {
 		let image: image_t = null;
-		let nodes = UINodes.getNodes();
-		let canvas = UINodes.getCanvas(true);
+		let nodes = ui_nodes_getNodes();
+		let canvas = ui_nodes_getCanvas(true);
 		if (nodes.nodesSelectedId.length > 0) {
 			let node = zui_get_node(canvas.nodes, nodes.nodesSelectedId[0]);
 			let brushNode = ParserLogic.getLogicNode(node);
@@ -283,8 +283,8 @@ class RenderPathPaint {
 			render_path_bind_target("texpaint_nor_empty", "texpaint_nor");
 			render_path_bind_target("texpaint_pack_empty", "texpaint_pack");
 
-			let nodes = UINodes.getNodes();
-			let canvas = UINodes.getCanvas(true);
+			let nodes = ui_nodes_getNodes();
+			let canvas = ui_nodes_getCanvas(true);
 			let node = zui_get_node(canvas.nodes, nodes.nodesSelectedId[0]);
 			let inpaint = node.type == "InpaintNode";
 			if (inpaint) {

+ 6 - 6
armorlab/Sources/UINodesExt.ts

@@ -4,7 +4,7 @@ class UINodesExt {
 	static lastVertices: DataView = null; // Before displacement
 
 	static drawButtons = (ew: f32, startY: f32) => {
-		let ui = UINodes.ui;
+		let ui = ui_nodes_ui;
 		if (zui_button(tr("Run"))) {
 			console_progress(tr("Processing"));
 
@@ -84,7 +84,7 @@ class UINodesExt {
 						g4_draw();
 						g4_end();
 
-						if (UIHeader.worktab.position == SpaceType.Space3D &&
+						if (ui_header_worktab.position == SpaceType.Space3D &&
 							BrushOutputNode.inst.inputs[ChannelType.ChannelHeight].node.constructor != FloatNode) {
 
 							// Make copy of vertices before displacement
@@ -93,12 +93,12 @@ class UINodesExt {
 							let vertices = g4_vertex_buffer_lock(g._.vertex_buffer);
 							if (UINodesExt.lastVertices == null || UINodesExt.lastVertices.byteLength != vertices.byteLength) {
 								UINodesExt.lastVertices = new DataView(new ArrayBuffer(vertices.byteLength));
-								for (let i = 0; i < Math.floor(vertices.byteLength / 2); ++i) {
+								for (let i = 0; i < math_floor(vertices.byteLength / 2); ++i) {
 									UINodesExt.lastVertices.setInt16(i * 2, vertices.getInt16(i * 2, true), true);
 								}
 							}
 							else {
-								for (let i = 0; i < Math.floor(vertices.byteLength / 2); ++i) {
+								for (let i = 0; i < math_floor(vertices.byteLength / 2); ++i) {
 									vertices.setInt16(i * 2, UINodesExt.lastVertices.getInt16(i * 2, true), true);
 								}
 							}
@@ -111,8 +111,8 @@ class UINodesExt {
 									console_progress(tr("Apply Displacement"));
 									base_notifyOnNextFrame(() => {
 										let uv_scale = scene_meshes[0].data.scale_tex * context_raw.brushScale;
-										UtilMesh.applyDisplacement(texpaint_pack, 0.05 * config_raw.displace_strength, uv_scale);
-										UtilMesh.calcNormals();
+										util_mesh_applyDisplacement(texpaint_pack, 0.05 * config_raw.displace_strength, uv_scale);
+										util_mesh_calcNormals();
 										taskDone();
 									});
 								});

+ 8 - 8
armorlab/Sources/nodes/InpaintNode.ts

@@ -107,16 +107,16 @@ class InpaintNode extends LogicNode {
 		let f32mask = new Float32Array(4 * 64 * 64);
 
 		let vae_encoder_blob: ArrayBuffer = data_get_blob("models/sd_vae_encoder.quant.onnx");
-		// for (let x = 0; x < Math.floor(image.width / 512); ++x) {
-			// for (let y = 0; y < Math.floor(image.height / 512); ++y) {
+		// for (let x = 0; x < math_floor(image.width / 512); ++x) {
+			// for (let y = 0; y < math_floor(image.height / 512); ++y) {
 				let x = 0;
 				let y = 0;
 
 				for (let xx = 0; xx < 64; ++xx) {
 					for (let yy = 0; yy < 64; ++yy) {
-						// let step = Math.floor(512 / 64);
+						// let step = math_floor(512 / 64);
 						// let j = (yy * step * mask.width + xx * step) + (y * 512 * mask.width + x * 512);
-						let step = Math.floor(mask.width / 64);
+						let step = math_floor(mask.width / 64);
 						let j = (yy * step * mask.width + xx * step);
 						let f = u8[j] / 255.0;
 						let i = yy * 64 + xx;
@@ -149,14 +149,14 @@ class InpaintNode extends LogicNode {
 				let latents_orig = latents.slice(0);
 
 				let noise = new Float32Array(latents.length);
-				for (let i = 0; i < noise.length; ++i) noise[i] = Math.cos(2.0 * 3.14 * RandomNode.getFloat()) * Math.sqrt(-2.0 * Math.log(RandomNode.getFloat()));
+				for (let i = 0; i < noise.length; ++i) noise[i] = math_cos(2.0 * 3.14 * RandomNode.getFloat()) * math_sqrt(-2.0 * math_log(RandomNode.getFloat()));
 
 				let num_inference_steps = 50;
-				let init_timestep = Math.floor(num_inference_steps * InpaintNode.strength);
+				let init_timestep = math_floor(num_inference_steps * InpaintNode.strength);
 				let timestep = TextToPhotoNode.timesteps[num_inference_steps - init_timestep];
 				let alphas_cumprod = TextToPhotoNode.alphas_cumprod;
-				let sqrt_alpha_prod = Math.pow(alphas_cumprod[timestep], 0.5);
-				let sqrt_one_minus_alpha_prod = Math.pow(1.0 - alphas_cumprod[timestep], 0.5);
+				let sqrt_alpha_prod = math_pow(alphas_cumprod[timestep], 0.5);
+				let sqrt_one_minus_alpha_prod = math_pow(1.0 - alphas_cumprod[timestep], 0.5);
 				for (let i = 0; i < latents.length; ++i) {
 					latents[i] = sqrt_alpha_prod * latents[i] + sqrt_one_minus_alpha_prod * noise[i];
 				}

+ 20 - 20
armorlab/Sources/nodes/PhotoToPBRNode.ts

@@ -41,12 +41,12 @@ class PhotoToPBRNode extends LogicNode {
 			console_progress(tr("Processing") + " - " + tr("Photo to PBR"));
 			base_notifyOnNextFrame(() => {
 				let tileFloats: Float32Array[] = [];
-				let tilesX = Math.floor(config_getTextureResX() / PhotoToPBRNode.tileW);
-				let tilesY = Math.floor(config_getTextureResY() / PhotoToPBRNode.tileW);
+				let tilesX = math_floor(config_getTextureResX() / PhotoToPBRNode.tileW);
+				let tilesY = math_floor(config_getTextureResY() / PhotoToPBRNode.tileW);
 				let numTiles = tilesX * tilesY;
 				for (let i = 0; i < numTiles; ++i) {
 					let x = i % tilesX;
-					let y = Math.floor(i / tilesX);
+					let y = math_floor(i / tilesX);
 
 					g2_begin(PhotoToPBRNode.temp);
 					g2_draw_scaled_image(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW, -config_getTextureResX(), config_getTextureResY());
@@ -75,10 +75,10 @@ class PhotoToPBRNode extends LogicNode {
 					let offsetB = (from == ChannelType.ChannelBaseColor || from == ChannelType.ChannelNormalMap) ? PhotoToPBRNode.tileWithBorderW * PhotoToPBRNode.tileWithBorderW * 2 : 0;
 					for (let i = 0; i < (PhotoToPBRNode.tileW * PhotoToPBRNode.tileW); ++i) {
 						let x = PhotoToPBRNode.borderW + i % PhotoToPBRNode.tileW;
-						let y = PhotoToPBRNode.borderW + Math.floor(i / PhotoToPBRNode.tileW);
-						u8a[i * 4    ] = Math.floor((ar[y * PhotoToPBRNode.tileWithBorderW + x          ] * 0.5 + 0.5) * 255);
-						u8a[i * 4 + 1] = Math.floor((ar[y * PhotoToPBRNode.tileWithBorderW + x + offsetG] * 0.5 + 0.5) * 255);
-						u8a[i * 4 + 2] = Math.floor((ar[y * PhotoToPBRNode.tileWithBorderW + x + offsetB] * 0.5 + 0.5) * 255);
+						let y = PhotoToPBRNode.borderW + math_floor(i / PhotoToPBRNode.tileW);
+						u8a[i * 4    ] = math_floor((ar[y * PhotoToPBRNode.tileWithBorderW + x          ] * 0.5 + 0.5) * 255);
+						u8a[i * 4 + 1] = math_floor((ar[y * PhotoToPBRNode.tileWithBorderW + x + offsetG] * 0.5 + 0.5) * 255);
+						u8a[i * 4 + 2] = math_floor((ar[y * PhotoToPBRNode.tileWithBorderW + x + offsetB] * 0.5 + 0.5) * 255);
 						u8a[i * 4 + 3] = 255;
 					}
 					tileFloats.push(ar);
@@ -94,15 +94,15 @@ class PhotoToPBRNode extends LogicNode {
 									let b = u8a[i * 4 + 1];
 									let c = u8a[i * 4 + 2];
 
-									let aa = Math.floor((ar[(PhotoToPBRNode.borderW + yy) * PhotoToPBRNode.tileWithBorderW + PhotoToPBRNode.borderW + PhotoToPBRNode.tileW + xx          ] * 0.5 + 0.5) * 255);
-									let bb = Math.floor((ar[(PhotoToPBRNode.borderW + yy) * PhotoToPBRNode.tileWithBorderW + PhotoToPBRNode.borderW + PhotoToPBRNode.tileW + xx + offsetG] * 0.5 + 0.5) * 255);
-									let cc = Math.floor((ar[(PhotoToPBRNode.borderW + yy) * PhotoToPBRNode.tileWithBorderW + PhotoToPBRNode.borderW + PhotoToPBRNode.tileW + xx + offsetB] * 0.5 + 0.5) * 255);
+									let aa = math_floor((ar[(PhotoToPBRNode.borderW + yy) * PhotoToPBRNode.tileWithBorderW + PhotoToPBRNode.borderW + PhotoToPBRNode.tileW + xx          ] * 0.5 + 0.5) * 255);
+									let bb = math_floor((ar[(PhotoToPBRNode.borderW + yy) * PhotoToPBRNode.tileWithBorderW + PhotoToPBRNode.borderW + PhotoToPBRNode.tileW + xx + offsetG] * 0.5 + 0.5) * 255);
+									let cc = math_floor((ar[(PhotoToPBRNode.borderW + yy) * PhotoToPBRNode.tileWithBorderW + PhotoToPBRNode.borderW + PhotoToPBRNode.tileW + xx + offsetB] * 0.5 + 0.5) * 255);
 
 									let f = xx / PhotoToPBRNode.borderW;
 									let invf = 1.0 - f;
-									a = Math.floor(a * f + aa * invf);
-									b = Math.floor(b * f + bb * invf);
-									c = Math.floor(c * f + cc * invf);
+									a = math_floor(a * f + aa * invf);
+									b = math_floor(b * f + bb * invf);
+									c = math_floor(c * f + cc * invf);
 
 									u8a[i * 4    ] = a;
 									u8a[i * 4 + 1] = b;
@@ -119,15 +119,15 @@ class PhotoToPBRNode extends LogicNode {
 									let b = u8a[i * 4 + 1];
 									let c = u8a[i * 4 + 2];
 
-									let aa = Math.floor((ar[(PhotoToPBRNode.borderW + PhotoToPBRNode.tileW + yy) * PhotoToPBRNode.tileWithBorderW + PhotoToPBRNode.borderW + xx          ] * 0.5 + 0.5) * 255);
-									let bb = Math.floor((ar[(PhotoToPBRNode.borderW + PhotoToPBRNode.tileW + yy) * PhotoToPBRNode.tileWithBorderW + PhotoToPBRNode.borderW + xx + offsetG] * 0.5 + 0.5) * 255);
-									let cc = Math.floor((ar[(PhotoToPBRNode.borderW + PhotoToPBRNode.tileW + yy) * PhotoToPBRNode.tileWithBorderW + PhotoToPBRNode.borderW + xx + offsetB] * 0.5 + 0.5) * 255);
+									let aa = math_floor((ar[(PhotoToPBRNode.borderW + PhotoToPBRNode.tileW + yy) * PhotoToPBRNode.tileWithBorderW + PhotoToPBRNode.borderW + xx          ] * 0.5 + 0.5) * 255);
+									let bb = math_floor((ar[(PhotoToPBRNode.borderW + PhotoToPBRNode.tileW + yy) * PhotoToPBRNode.tileWithBorderW + PhotoToPBRNode.borderW + xx + offsetG] * 0.5 + 0.5) * 255);
+									let cc = math_floor((ar[(PhotoToPBRNode.borderW + PhotoToPBRNode.tileW + yy) * PhotoToPBRNode.tileWithBorderW + PhotoToPBRNode.borderW + xx + offsetB] * 0.5 + 0.5) * 255);
 
 									let f = yy / PhotoToPBRNode.borderW;
 									let invf = 1.0 - f;
-									a = Math.floor(a * f + aa * invf);
-									b = Math.floor(b * f + bb * invf);
-									c = Math.floor(c * f + cc * invf);
+									a = math_floor(a * f + aa * invf);
+									b = math_floor(b * f + bb * invf);
+									c = math_floor(c * f + cc * invf);
 
 									u8a[i * 4    ] = a;
 									u8a[i * 4 + 1] = b;
@@ -158,7 +158,7 @@ class PhotoToPBRNode extends LogicNode {
 	///if (krom_metal || krom_vulkan)
 	static bgraSwap = (buffer: ArrayBuffer) => {
 		let u8a = new Uint8Array(buffer);
-		for (let i = 0; i < Math.floor(buffer.byteLength / 4); ++i) {
+		for (let i = 0; i < math_floor(buffer.byteLength / 4); ++i) {
 			let r = u8a[i * 4];
 			u8a[i * 4] = u8a[i * 4 + 2];
 			u8a[i * 4 + 2] = r;

+ 12 - 12
armorlab/Sources/nodes/TextToPhotoNode.ts

@@ -69,9 +69,9 @@ class TextToPhotoNode extends LogicNode {
 
 			let width = 512;
 			let height = 512;
-			let latents = new Float32Array(1 * 4 * Math.floor(height / 8) * Math.floor(width / 8));
+			let latents = new Float32Array(1 * 4 * math_floor(height / 8) * math_floor(width / 8));
 			if (inpaintLatents == null) {
-				for (let i = 0; i < latents.length; ++i) latents[i] = Math.cos(2.0 * 3.14 * RandomNode.getFloat()) * Math.sqrt(-2.0 * Math.log(RandomNode.getFloat()));
+				for (let i = 0; i < latents.length; ++i) latents[i] = math_cos(2.0 * 3.14 * RandomNode.getFloat()) * math_sqrt(-2.0 * math_log(RandomNode.getFloat()));
 			}
 			else {
 				for (let i = 0; i < latents.length; ++i) latents[i] = inpaintLatents[i];
@@ -113,14 +113,14 @@ class TextToPhotoNode extends LogicNode {
 				noise_pred[i] = noise_pred_uncond[i] + guidance_scale * (noise_pred_text[i] - noise_pred_uncond[i]);
 			}
 
-			let prev_timestep = Math.floor(Math.max(timestep - Math.floor(num_train_timesteps / num_inference_steps), 0));
+			let prev_timestep = math_floor(math_max(timestep - math_floor(num_train_timesteps / num_inference_steps), 0));
 
 			if (counter != 1) {
 				ets.push(noise_pred);
 			}
 			else {
 				prev_timestep = timestep;
-				timestep = timestep + Math.floor(num_train_timesteps / num_inference_steps);
+				timestep = timestep + math_floor(num_train_timesteps / num_inference_steps);
 			}
 
 			if (ets.length == 1 && counter == 0) {
@@ -161,8 +161,8 @@ class TextToPhotoNode extends LogicNode {
 			let alpha_prod_t_prev = TextToPhotoNode.alphas_cumprod[prev_timestep + 1];
 			let beta_prod_t = 1 - alpha_prod_t;
 			let beta_prod_t_prev = 1 - alpha_prod_t_prev;
-			let latents_coeff = Math.pow(alpha_prod_t_prev / alpha_prod_t, (0.5));
-			let noise_pred_denom_coeff = alpha_prod_t * Math.pow(beta_prod_t_prev, (0.5)) + Math.pow(alpha_prod_t * beta_prod_t * alpha_prod_t_prev, (0.5));
+			let latents_coeff = math_pow(alpha_prod_t_prev / alpha_prod_t, (0.5));
+			let noise_pred_denom_coeff = alpha_prod_t * math_pow(beta_prod_t_prev, (0.5)) + math_pow(alpha_prod_t * beta_prod_t * alpha_prod_t_prev, (0.5));
 			for (let i = 0; i < latents.length; ++i) {
 				latents[i] = (latents_coeff * latents[i] - (alpha_prod_t_prev - alpha_prod_t) * noise_pred[i] / noise_pred_denom_coeff);
 			}
@@ -170,9 +170,9 @@ class TextToPhotoNode extends LogicNode {
 
 			if (mask != null) {
 				let noise = new Float32Array(latents.length);
-				for (let i = 0; i < noise.length; ++i) noise[i] = Math.cos(2.0 * 3.14 * RandomNode.getFloat()) * Math.sqrt(-2.0 * Math.log(RandomNode.getFloat()));
-				let sqrt_alpha_prod = Math.pow(TextToPhotoNode.alphas_cumprod[timestep], 0.5);
-				let sqrt_one_minus_alpha_prod = Math.pow(1.0 - TextToPhotoNode.alphas_cumprod[timestep], 0.5);
+				for (let i = 0; i < noise.length; ++i) noise[i] = math_cos(2.0 * 3.14 * RandomNode.getFloat()) * math_sqrt(-2.0 * math_log(RandomNode.getFloat()));
+				let sqrt_alpha_prod = math_pow(TextToPhotoNode.alphas_cumprod[timestep], 0.5);
+				let sqrt_one_minus_alpha_prod = math_pow(1.0 - TextToPhotoNode.alphas_cumprod[timestep], 0.5);
 
 				let init_latents_proper = new Float32Array(latents.length);
 				for (let i = 0; i < init_latents_proper.length; ++i) {
@@ -210,9 +210,9 @@ class TextToPhotoNode extends LogicNode {
 
 			let u8a = new Uint8Array(4 * 512 * 512);
 			for (let i = 0; i < (512 * 512); ++i) {
-				u8a[i * 4    ] = Math.floor(pyimage[i                ] * 255);
-				u8a[i * 4 + 1] = Math.floor(pyimage[i + 512 * 512    ] * 255);
-				u8a[i * 4 + 2] = Math.floor(pyimage[i + 512 * 512 * 2] * 255);
+				u8a[i * 4    ] = math_floor(pyimage[i                ] * 255);
+				u8a[i * 4 + 1] = math_floor(pyimage[i + 512 * 512    ] * 255);
+				u8a[i * 4 + 2] = math_floor(pyimage[i + 512 * 512 * 2] * 255);
 				u8a[i * 4 + 3] = 255;
 			}
 			let image = image_from_bytes(u8a.buffer, 512, 512);

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

@@ -62,7 +62,7 @@ class TilingNode extends LogicNode {
 		let u8a = new Uint8Array(512 * 512);
 		for (let i = 0; i < 512 * 512; ++i) {
 			let x = i % 512;
-			let y = Math.floor(i / 512);
+			let y = math_floor(i / 512);
 			let l = y < 256 ? y : (511 - y);
 			u8a[i] = (x > 256 - l && x < 256 + l) ? 0 : 255;
 		}

+ 10 - 10
armorlab/Sources/nodes/UpscaleNode.ts

@@ -44,8 +44,8 @@ class UpscaleNode extends LogicNode {
 		let result: image_t = null;
 		let size1w = source.width;
 		let size1h = source.height;
-		let size2w = Math.floor(size1w * 2);
-		let size2h = Math.floor(size1h * 2);
+		let size2w = math_floor(size1w * 2);
+		let size2h = math_floor(size1h * 2);
 		if (UpscaleNode.temp != null) {
 			image_unload(UpscaleNode.temp);
 		}
@@ -72,9 +72,9 @@ class UpscaleNode extends LogicNode {
 
 		u8a = new Uint8Array(4 * size2w * size2h);
 		for (let i = 0; i < (size2w * size2h); ++i) {
-			u8a[i * 4    ] = Math.floor(esrgan2x[i                      ] * 255);
-			u8a[i * 4 + 1] = Math.floor(esrgan2x[i + size2w * size2w    ] * 255);
-			u8a[i * 4 + 2] = Math.floor(esrgan2x[i + size2w * size2w * 2] * 255);
+			u8a[i * 4    ] = math_floor(esrgan2x[i                      ] * 255);
+			u8a[i * 4 + 1] = math_floor(esrgan2x[i + size2w * size2w    ] * 255);
+			u8a[i * 4 + 2] = math_floor(esrgan2x[i + size2w * size2w * 2] * 255);
 			u8a[i * 4 + 3] = 255;
 		}
 
@@ -87,15 +87,15 @@ class UpscaleNode extends LogicNode {
 		let size1w = source.width;
 		let size1h = source.height;
 		let tileSize = 512;
-		let tileSize2x = Math.floor(tileSize * 2);
+		let tileSize2x = math_floor(tileSize * 2);
 
 		if (size1w >= tileSize2x || size1h >= tileSize2x) { // Split into tiles
-			let size2w = Math.floor(size1w * 2);
-			let size2h = Math.floor(size1h * 2);
+			let size2w = math_floor(size1w * 2);
+			let size2h = math_floor(size1h * 2);
 			result = image_create_render_target(size2w, size2h);
 			let tileSource = image_create_render_target(tileSize + 32 * 2, tileSize + 32 * 2);
-			for (let x = 0; x < Math.floor(size1w / tileSize); ++x) {
-				for (let y = 0; y < Math.floor(size1h / tileSize); ++y) {
+			for (let x = 0; x < math_floor(size1w / tileSize); ++x) {
+				for (let y = 0; y < math_floor(size1h / tileSize); ++y) {
 					g2_begin(tileSource);
 					g2_draw_scaled_image(source, 32 - x * tileSize, 32 - y * tileSize, -source.width, source.height);
 					g2_draw_scaled_image(source, 32 - x * tileSize, 32 - y * tileSize, source.width, -source.height);

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

@@ -50,13 +50,13 @@ class VarianceNode extends LogicNode {
 				}
 
 				let noise = new Float32Array(latents.length);
-				for (let i = 0; i < noise.length; ++i) noise[i] = Math.cos(2.0 * 3.14 * RandomNode.getFloat()) * Math.sqrt(-2.0 * Math.log(RandomNode.getFloat()));
+				for (let i = 0; i < noise.length; ++i) noise[i] = math_cos(2.0 * 3.14 * RandomNode.getFloat()) * math_sqrt(-2.0 * math_log(RandomNode.getFloat()));
 				let num_inference_steps = 50;
-				let init_timestep = Math.floor(num_inference_steps * strength);
+				let init_timestep = math_floor(num_inference_steps * strength);
 				let timesteps = TextToPhotoNode.timesteps[num_inference_steps - init_timestep];
 				let alphas_cumprod = TextToPhotoNode.alphas_cumprod;
-				let sqrt_alpha_prod = Math.pow(alphas_cumprod[timesteps], 0.5);
-				let sqrt_one_minus_alpha_prod = Math.pow(1.0 - alphas_cumprod[timesteps], 0.5);
+				let sqrt_alpha_prod = math_pow(alphas_cumprod[timesteps], 0.5);
+				let sqrt_one_minus_alpha_prod = math_pow(1.0 - alphas_cumprod[timesteps], 0.5);
 				for (let i = 0; i < latents.length; ++i) {
 					latents[i] = sqrt_alpha_prod * latents[i] + sqrt_one_minus_alpha_prod * noise[i];
 				}

二進制
armorpaint/Assets/Scene.arm


+ 2 - 2
armorpaint/Sources/ImportFolder.ts

@@ -115,8 +115,8 @@ class ImportFolder {
 		}
 
 		MakeMaterial.parse_paint_material();
-		UtilRender.make_material_preview();
-		UIBase.hwnds[1].redraws = 2;
+		util_render_make_material_preview();
+		ui_base_hwnds[1].redraws = 2;
 		history_new_material();
 	}
 

+ 3 - 3
armorpaint/Sources/MakeBake.ts

@@ -8,7 +8,7 @@ class MakeBake {
 			frag.wposition = true;
 			frag.n = true;
 			frag.vvec = true;
-			NodeShader.add_function(frag, ShaderFunctions.str_cotangent_frame);
+			NodeShader.add_function(frag, str_cotangent_frame);
 			///if krom_direct3d11
 			NodeShader.write(frag, 'mat3 TBN = cotangentFrame(n, vVec, texCoord);');
 			///else
@@ -21,7 +21,7 @@ class MakeBake {
 			NodeShader.write(frag, MakeMaterial.voxelgi_half_extents());
 			NodeShader.write(frag, 'vec3 voxpos = wposition / voxelgiHalfExtents;');
 			NodeShader.add_uniform(frag, 'sampler3D voxels');
-			NodeShader.add_function(frag, ShaderFunctions.str_trace_ao);
+			NodeShader.add_function(frag, str_trace_ao);
 			frag.n = true;
 			let strength: f32 = context_raw.bake_ao_strength;
 			let radius: f32 = context_raw.bake_ao_radius;
@@ -58,7 +58,7 @@ class MakeBake {
 			frag.n = true;
 			NodeShader.add_uniform(frag, 'sampler2D texpaint_undo', '_texpaint_undo'); // Baked high-poly normals
 			NodeShader.write(frag, 'vec3 n0 = textureLod(texpaint_undo, texCoord, 0.0).rgb * vec3(2.0, 2.0, 2.0) - vec3(1.0, 1.0, 1.0);');
-			NodeShader.add_function(frag, ShaderFunctions.str_cotangent_frame);
+			NodeShader.add_function(frag, str_cotangent_frame);
 			NodeShader.write(frag, 'mat3 invTBN = transpose(cotangentFrame(n, n, texCoord));');
 			NodeShader.write(frag, 'vec3 res = normalize(mul(n0, invTBN)) * vec3(0.5, 0.5, 0.5) + vec3(0.5, 0.5, 0.5);');
 			NodeShader.write(frag, 'fragColor[0] = vec4(res, 1.0);');

+ 1 - 1
armorpaint/Sources/MakeBrush.ts

@@ -25,7 +25,7 @@ class MakeBrush {
 			frag.wposition = true;
 
 			if (config_raw.brush_angle_reject || context_raw.xray) {
-				NodeShader.add_function(frag, ShaderFunctions.str_octahedron_wrap);
+				NodeShader.add_function(frag, str_octahedron_wrap);
 				NodeShader.add_uniform(frag, 'sampler2D gbuffer0');
 				///if (krom_direct3d11 || krom_direct3d12 || krom_metal || krom_vulkan)
 				NodeShader.write(frag, 'vec2 g0 = textureLod(gbuffer0, inp.xy, 0.0).rg;');

+ 2 - 2
armorpaint/Sources/MakeColorIdPicker.ts

@@ -26,8 +26,8 @@ class MakeColorIdPicker {
 				NodeShader.add_out(frag, 'vec4 fragColor[2]');
 				NodeShader.add_uniform(frag, 'sampler2D gbufferD');
 				NodeShader.add_uniform(frag, 'mat4 invVP', '_inv_view_proj_matrix');
-				NodeShader.add_function(frag, ShaderFunctions.str_get_pos_from_depth);
-				NodeShader.add_function(frag, ShaderFunctions.str_get_nor_from_depth);
+				NodeShader.add_function(frag, str_get_pos_from_depth);
+				NodeShader.add_function(frag, str_get_nor_from_depth);
 				NodeShader.write(frag, 'fragColor[0] = vec4(get_pos_from_depth(vec2(inp.x, 1.0 - inp.y), invVP, texturePass(gbufferD)), texCoordInp.x);');
 				NodeShader.write(frag, 'fragColor[1] = vec4(get_nor_from_depth(fragColor[0].rgb, vec2(inp.x, 1.0 - inp.y), invVP, vec2(1.0, 1.0) / gbufferSize, texturePass(gbufferD)), texCoordInp.y);');
 			}

+ 24 - 23
armorpaint/Sources/MakeMaterial.ts

@@ -9,7 +9,7 @@ class MakeMaterial {
 	static subs_used = false;
 
 	static get_mout = (): bool => {
-		for (let n of UINodes.get_canvas_material().nodes) if (n.type == "OUTPUT_MATERIAL_PBR") return true;
+		for (let n of ui_nodes_get_canvas_material().nodes) if (n.type == "OUTPUT_MATERIAL_PBR") return true;
 		return false;
 	}
 
@@ -180,9 +180,10 @@ class MakeMaterial {
 
 		if (bake_previews) {
 			let current: image_t = _g2_current;
-			if (current != null) g2_end();
+			let g2_in_use: bool = _g2_in_use;
+			if (g2_in_use) g2_end();
 			MakeMaterial.bake_node_previews();
-			if (current != null) g2_begin(current);
+			if (g2_in_use) g2_begin(current);
 		}
 
 		let m: material_data_t = project_materials[0].data;
@@ -204,7 +205,7 @@ class MakeMaterial {
 			}
 		}
 
-		let sdata: material_t = { name: "Material", canvas: UINodes.get_canvas_material() };
+		let sdata: material_t = { name: "Material", canvas: ui_nodes_get_canvas_material() };
 		let tmcon: material_context_t = { name: "paint", bind_textures: [] };
 		let con: NodeShaderContextRaw = MakePaint.run(sdata, tmcon);
 
@@ -229,8 +230,8 @@ class MakeMaterial {
 
 	static bake_node_previews = () => {
 		context_raw.node_previews_used = [];
-		if (context_raw.node_previews == null) context_raw.node_previews = new Map();
-		MakeMaterial.traverse_nodes(UINodes.get_canvas_material().nodes, null, []);
+		if (context_raw.node_previews == null) context_raw.node_previews = map_create();
+		MakeMaterial.traverse_nodes(ui_nodes_get_canvas_material().nodes, null, []);
 		for (let key of context_raw.node_previews.keys()) {
 			if (context_raw.node_previews_used.indexOf(key) == -1) {
 				let image: image_t = context_raw.node_previews.get(key);
@@ -261,8 +262,8 @@ class MakeMaterial {
 			let id: string = ParserMaterial.node_name(node, parents);
 			let image: image_t = context_raw.node_previews.get(id);
 			context_raw.node_previews_used.push(id);
-			let resX: i32 = Math.floor(config_get_texture_res_x() / 4);
-			let resY: i32 = Math.floor(config_get_texture_res_y() / 4);
+			let resX: i32 = math_floor(config_get_texture_res_x() / 4);
+			let resY: i32 = math_floor(config_get_texture_res_y() / 4);
 			if (image == null || image.width != resX || image.height != resY) {
 				if (image != null) image_unload(image);
 				image = image_create_render_target(resX, resY);
@@ -270,15 +271,15 @@ class MakeMaterial {
 			}
 
 			ParserMaterial.blur_passthrough = true;
-			UtilRender.make_node_preview(UINodes.get_canvas_material(), node, image, group, parents);
+			util_render_make_node_preview(ui_nodes_get_canvas_material(), node, image, group, parents);
 			ParserMaterial.blur_passthrough = false;
 		}
 		else if (node.type == "DIRECT_WARP") {
 			let id: string = ParserMaterial.node_name(node, parents);
 			let image: image_t = context_raw.node_previews.get(id);
 			context_raw.node_previews_used.push(id);
-			let resX: i32 = Math.floor(config_get_texture_res_x());
-			let resY: i32 = Math.floor(config_get_texture_res_y());
+			let resX: i32 = math_floor(config_get_texture_res_x());
+			let resY: i32 = math_floor(config_get_texture_res_y());
 			if (image == null || image.width != resX || image.height != resY) {
 				if (image != null) image_unload(image);
 				image = image_create_render_target(resX, resY);
@@ -286,15 +287,15 @@ class MakeMaterial {
 			}
 
 			ParserMaterial.warp_passthrough = true;
-			UtilRender.make_node_preview(UINodes.get_canvas_material(), node, image, group, parents);
+			util_render_make_node_preview(ui_nodes_get_canvas_material(), node, image, group, parents);
 			ParserMaterial.warp_passthrough = false;
 		}
 		else if (node.type == "BAKE_CURVATURE") {
 			let id: string = ParserMaterial.node_name(node, parents);
 			let image: image_t = context_raw.node_previews.get(id);
 			context_raw.node_previews_used.push(id);
-			let resX: i32 = Math.floor(config_get_texture_res_x());
-			let resY: i32 = Math.floor(config_get_texture_res_y());
+			let resX: i32 = math_floor(config_get_texture_res_x());
+			let resY: i32 = math_floor(config_get_texture_res_y());
 			if (image == null || image.width != resX || image.height != resY) {
 				if (image != null) image_unload(image);
 				image = image_create_render_target(resX, resY, tex_format_t.R8);
@@ -305,10 +306,10 @@ class MakeMaterial {
 				RenderPathPaint.live_layer = SlotLayer.create("_live");
 			}
 
-			let _space: i32 = UIHeader.worktab.position;
+			let _space: i32 = ui_header_worktab.position;
 			let _tool: workspace_tool_t = context_raw.tool;
 			let _bake_type: bake_type_t = context_raw.bake_type;
-			UIHeader.worktab.position = space_type_t.SPACE3D;
+			ui_header_worktab.position = space_type_t.SPACE3D;
 			context_raw.tool = workspace_tool_t.BAKE;
 			context_raw.bake_type = bake_type_t.CURVATURE;
 
@@ -328,12 +329,12 @@ class MakeMaterial {
 			RenderPathPaint.use_live_layer(false);
 			context_raw.pdirty = 0;
 
-			UIHeader.worktab.position = _space;
+			ui_header_worktab.position = _space;
 			context_raw.tool = _tool;
 			context_raw.bake_type = _bake_type;
 			MakeMaterial.parse_paint_material(false);
 
-			let rts: Map<string, render_target_t> = render_path_render_targets;
+			let rts: map_t<string, render_target_t> = render_path_render_targets;
 			let texpaint_live: render_target_t = rts.get("texpaint_live");
 
 			g2_begin(image);
@@ -344,7 +345,7 @@ class MakeMaterial {
 
 	static parse_node_preview_material = (node: zui_node_t, group: zui_node_canvas_t = null, parents: zui_node_t[] = null): { scon: shader_context_t, mcon: material_context_t } => {
 		if (node.outputs.length == 0) return null;
-		let sdata: material_t = { name: "Material", canvas: UINodes.get_canvas_material() };
+		let sdata: material_t = { name: "Material", canvas: ui_nodes_get_canvas_material() };
 		let mcon_raw: material_context_t = { name: "mesh", bind_textures: [] };
 		let con: NodeShaderContextRaw = MakeNodePreview.run(sdata, mcon_raw, node, group, parents);
 		let compile_error: bool = false;
@@ -409,19 +410,19 @@ class MakeMaterial {
 			return `vec3(1.0 - ${opac}, 1.0 - ${opac}, 1.0 - ${opac}) * ${cola} + vec3(${opac}, ${opac}, ${opac}) * ${cola} / ${colb}`;
 		}
 		else if (blending == blend_type_t.HUE) {
-			NodeShader.add_function(frag, ShaderFunctions.str_hue_sat);
+			NodeShader.add_function(frag, str_hue_sat);
 			return `mix(${cola}, hsv_to_rgb(vec3(rgb_to_hsv(${colb}).r, rgb_to_hsv(${cola}).g, rgb_to_hsv(${cola}).b)), ${opac})`;
 		}
 		else if (blending == blend_type_t.SATURATION) {
-			NodeShader.add_function(frag, ShaderFunctions.str_hue_sat);
+			NodeShader.add_function(frag, str_hue_sat);
 			return `mix(${cola}, hsv_to_rgb(vec3(rgb_to_hsv(${cola}).r, rgb_to_hsv(${colb}).g, rgb_to_hsv(${cola}).b)), ${opac})`;
 		}
 		else if (blending == blend_type_t.COLOR) {
-			NodeShader.add_function(frag, ShaderFunctions.str_hue_sat);
+			NodeShader.add_function(frag, str_hue_sat);
 			return `mix(${cola}, hsv_to_rgb(vec3(rgb_to_hsv(${colb}).r, rgb_to_hsv(${colb}).g, rgb_to_hsv(${cola}).b)), ${opac})`;
 		}
 		else { // BlendValue
-			NodeShader.add_function(frag, ShaderFunctions.str_hue_sat);
+			NodeShader.add_function(frag, str_hue_sat);
 			return `mix(${cola}, hsv_to_rgb(vec3(rgb_to_hsv(${cola}).r, rgb_to_hsv(${cola}).g, rgb_to_hsv(${colb}).b)), ${opac})`;
 		}
 	}

+ 6 - 6
armorpaint/Sources/MakeMesh.ts

@@ -64,7 +64,7 @@ class MakeMesh {
 
 		NodeShader.add_out(frag, 'vec4 fragColor[3]');
 		frag.n = true;
-		NodeShader.add_function(frag, ShaderFunctions.str_pack_float_int16);
+		NodeShader.add_function(frag, str_pack_float_int16);
 
 		if (context_raw.tool == workspace_tool_t.COLORID) {
 			texture_count++;
@@ -74,8 +74,8 @@ class MakeMesh {
 			NodeShader.write(frag, 'fragColor[1] = vec4(idcol.rgb, 1.0);'); // occ
 		}
 		else {
-			NodeShader.add_function(frag, ShaderFunctions.str_octahedron_wrap);
-			NodeShader.add_function(frag, ShaderFunctions.str_cotangent_frame);
+			NodeShader.add_function(frag, str_octahedron_wrap);
+			NodeShader.add_function(frag, str_cotangent_frame);
 			if (layerPass > 0) {
 				NodeShader.add_uniform(frag, 'sampler2D gbuffer0');
 				NodeShader.add_uniform(frag, 'sampler2D gbuffer1');
@@ -348,13 +348,13 @@ class MakeMesh {
 					NodeShader.add_uniform(frag, 'vec4 envmapData', '_envmapData'); // angle, sin(angle), cos(angle), strength
 					NodeShader.write(frag, 'vec3 wreflect = reflect(-vVec, n);');
 					NodeShader.write(frag, 'float envlod = roughness * float(envmapNumMipmaps);');
-					NodeShader.add_function(frag, ShaderFunctions.str_envmap_equirect);
+					NodeShader.add_function(frag, str_envmap_equirect);
 					NodeShader.write(frag, 'vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(wreflect, envmapData.x), envlod).rgb;');
 					NodeShader.add_uniform(frag, 'vec3 lightArea0', '_light_area0');
 					NodeShader.add_uniform(frag, 'vec3 lightArea1', '_light_area1');
 					NodeShader.add_uniform(frag, 'vec3 lightArea2', '_light_area2');
 					NodeShader.add_uniform(frag, 'vec3 lightArea3', '_light_area3');
-					NodeShader.add_function(frag, ShaderFunctions.str_ltc_evaluate);
+					NodeShader.add_function(frag, str_ltc_evaluate);
 					NodeShader.add_uniform(frag, 'vec3 lightPos', '_point_pos');
 					NodeShader.add_uniform(frag, 'vec3 lightColor', '_point_color');
 					// NodeShader.write(frag, 'float dotNL = max(dot(n, normalize(lightPos - wposition)), 0.0);');
@@ -376,7 +376,7 @@ class MakeMesh {
 					NodeShader.write(frag, 'direct *= lightColor * (1.0 / (ldist * ldist));');
 
 					NodeShader.add_uniform(frag, 'vec4 shirr[7]', '_envmap_irradiance');
-					NodeShader.add_function(frag, ShaderFunctions.str_sh_irradiance);
+					NodeShader.add_function(frag, str_sh_irradiance());
 					NodeShader.write(frag, 'vec3 indirect = albedo * (shIrradiance(vec3(n.x * envmapData.z - n.y * envmapData.y, n.x * envmapData.y + n.y * envmapData.z, n.z), shirr) / 3.14159265);');
 					NodeShader.write(frag, 'indirect += prefilteredColor * (f0 * envBRDF.x + envBRDF.y) * 1.5;');
 					NodeShader.write(frag, 'indirect *= envmapData.w * occlusion;');

+ 5 - 5
armorpaint/Sources/MakeMeshPreview.ts

@@ -26,7 +26,7 @@ class MakeMeshPreview {
 			pos = "spos";
 			NodeShaderContext.add_elem(con_mesh, "bone", 'short4norm');
 			NodeShaderContext.add_elem(con_mesh, "weight", 'short4norm');
-			NodeShader.add_function(vert, ShaderFunctions.str_get_skinning_dual_quat);
+			NodeShader.add_function(vert, str_get_skinning_dual_quat);
 			NodeShader.add_uniform(vert, 'vec4 skinBones[128 * 2]', '_skin_bones');
 			NodeShader.add_uniform(vert, 'float posUnpack', '_pos_unpack');
 			NodeShader.write_attrib(vert, 'vec4 skinA;');
@@ -52,7 +52,7 @@ class MakeMeshPreview {
 		ParserMaterial.sample_uv_scale = brush_scale;
 		ParserMaterial.parse_height = MakeMaterial.height_used;
 		ParserMaterial.parse_height_as_channel = true;
-		let sout: shader_out_t = ParserMaterial.parse(UINodes.get_canvas_material(), con_mesh, vert, frag, matcon);
+		let sout: shader_out_t = ParserMaterial.parse(ui_nodes_get_canvas_material(), con_mesh, vert, frag, matcon);
 		ParserMaterial.parse_height = false;
 		ParserMaterial.parse_height_as_channel = false;
 		ParserMaterial.sample_keep_aspect = false;
@@ -95,9 +95,9 @@ class MakeMeshPreview {
 		NodeShader.add_out(frag, 'vec4 fragColor[3]');
 		frag.n = true;
 
-		NodeShader.add_function(frag, ShaderFunctions.str_pack_float_int16);
-		NodeShader.add_function(frag, ShaderFunctions.str_cotangent_frame);
-		NodeShader.add_function(frag, ShaderFunctions.str_octahedron_wrap);
+		NodeShader.add_function(frag, str_pack_float_int16);
+		NodeShader.add_function(frag, str_cotangent_frame);
+		NodeShader.add_function(frag, str_octahedron_wrap);
 
 		if (MakeMaterial.height_used) {
 			NodeShader.write(frag, 'if (height > 0.0) {');

+ 2 - 2
armorpaint/Sources/MakePaint.ts

@@ -138,7 +138,7 @@ class MakePaint {
 			NodeShader.write(frag, 'float dist = 0.0;');
 			let angle_fill: bool = context_raw.tool == workspace_tool_t.FILL && context_raw.fill_type_handle.position == fill_type_t.ANGLE;
 			if (angle_fill) {
-				NodeShader.add_function(frag, ShaderFunctions.str_octahedron_wrap);
+				NodeShader.add_function(frag, str_octahedron_wrap);
 				NodeShader.add_uniform(frag, 'sampler2D gbuffer0');
 				NodeShader.write(frag, 'vec2 g0 = textureLod(gbuffer0, inp.xy, 0.0).rg;');
 				NodeShader.write(frag, 'vec3 wn;');
@@ -202,7 +202,7 @@ class MakePaint {
 			ParserMaterial.triplanar = uv_type == uv_type_t.TRIPLANAR && !decal;
 			ParserMaterial.sample_keep_aspect = decal;
 			ParserMaterial.sample_uv_scale = 'brushScale';
-			let sout: shader_out_t = ParserMaterial.parse(UINodes.get_canvas_material(), con_paint, vert, frag, matcon);
+			let sout: shader_out_t = ParserMaterial.parse(ui_nodes_get_canvas_material(), con_paint, vert, frag, matcon);
 			ParserMaterial.parse_emission = false;
 			ParserMaterial.parse_subsurface = false;
 			ParserMaterial.parse_height_as_channel = false;

+ 1 - 1
armorpaint/Sources/NodesBrush.ts

@@ -32,7 +32,7 @@ class NodesBrush {
 				if (n.type == nodeType) {
 					let canvas: zui_node_canvas_t = context_raw.brush.canvas;
 					let nodes: zui_nodes_t = context_raw.brush.nodes;
-					let node: zui_node_t = UINodes.make_node(n, nodes, canvas);
+					let node: zui_node_t = ui_nodes_make_node(n, nodes, canvas);
 					canvas.nodes.push(node);
 					return node;
 				}

+ 15 - 15
armorpaint/Sources/RenderPathPaint.ts

@@ -139,7 +139,7 @@ class RenderPathPaint {
 				render_path_clear_target(0xff000000);
 				render_path_bind_target("gbuffer2", "gbuffer2");
 				render_path_draw_meshes("paint");
-				UIHeader.header_handle.redraws = 2;
+				ui_header_handle.redraws = 2;
 			}
 			else if (context_raw.tool == workspace_tool_t.PICKER || context_raw.tool == workspace_tool_t.MATERIAL) {
 				if (context_raw.pick_pos_nor_tex) {
@@ -175,8 +175,8 @@ class RenderPathPaint {
 					render_path_bind_target("texpaint_pack" + tid, "texpaint_pack");
 					render_path_draw_meshes("paint");
 					if (use_live_layer) RenderPathPaint.use_live_layer(false);
-					UIHeader.header_handle.redraws = 2;
-					UIBase.hwnds[2].redraws = 2;
+					ui_header_handle.redraws = 2;
+					ui_base_hwnds[2].redraws = 2;
 
 					let texpaint_picker: image_t = render_path_render_targets.get("texpaint_picker")._image;
 					let texpaint_nor_picker: image_t = render_path_render_targets.get("texpaint_nor_picker")._image;
@@ -218,7 +218,7 @@ class RenderPathPaint {
 					// Pick material
 					if (context_raw.picker_select_material && context_raw.color_picker_callback == null) {
 						// matid % 3 == 0 - normal, 1 - emission, 2 - subsurface
-						let matid: i32 = Math.floor((b.getUint8(3) - (b.getUint8(3) % 3)) / 3);
+						let matid: i32 = math_floor((b.getUint8(3) - (b.getUint8(3) % 3)) / 3);
 						for (let m of project_materials) {
 							if (m.id == matid) {
 								context_set_material(m);
@@ -301,12 +301,12 @@ class RenderPathPaint {
 					if (render_path_render_targets.get("texpaint_blur") == null) {
 						let t = render_target_create();
 						t.name = "texpaint_blur";
-						t.width = Math.floor(config_get_texture_res_x() * 0.95);
-						t.height = Math.floor(config_get_texture_res_y() * 0.95);
+						t.width = math_floor(config_get_texture_res_x() * 0.95);
+						t.height = math_floor(config_get_texture_res_y() * 0.95);
 						t.format = "RGBA32";
 						render_path_create_render_target(t);
 					}
-					let blurs: i32 = Math.round(context_raw.bake_curv_smooth);
+					let blurs: i32 = math_round(context_raw.bake_curv_smooth);
 					for (let i: i32 = 0; i < blurs; ++i) {
 						render_path_set_target("texpaint_blur");
 						render_path_bind_target(texpaint, "tex");
@@ -432,7 +432,7 @@ class RenderPathPaint {
 
 		RenderPathPaint.live_layer_drawn = 2;
 
-		UIView2D.hwnd.redraws = 2;
+		ui_view2d_hwnd.redraws = 2;
 		let _x: f32 = context_raw.paint_vec.x;
 		let _y: f32 = context_raw.paint_vec.y;
 		if (context_raw.brush_locked) {
@@ -741,7 +741,7 @@ class RenderPathPaint {
 				///if (krom_direct3d12 || krom_vulkan || krom_metal)
 				else if (is_raytraced_bake) {
 					let dirty: bool = RenderPathRaytraceBake.commands(MakeMaterial.parse_paint_material);
-					if (dirty) UIHeader.header_handle.redraws = 2;
+					if (dirty) ui_header_handle.redraws = 2;
 					if (config_raw.dilate == dilate_type_t.INSTANT) { // && raw.pdirty == 1
 						RenderPathPaint.dilate(true, false);
 					}
@@ -803,9 +803,9 @@ class RenderPathPaint {
 		camera_object_build_proj(cam);
 		camera_object_build_mat(cam);
 
-		let tw: f32 = 0.95 * UIView2D.pan_scale;
-		let tx: f32 = UIView2D.pan_x / UIView2D.ww;
-		let ty: f32 = UIView2D.pan_y / app_h();
+		let tw: f32 = 0.95 * ui_view2d_pan_scale;
+		let tx: f32 = ui_view2d_pan_x / ui_view2d_ww;
+		let ty: f32 = ui_view2d_pan_y / app_h();
 		mat4_set_identity(m);
 		mat4_scale(m, vec4_create(tw, tw, 1));
 		mat4_set_loc(m, vec4_create(tx, ty, 0));
@@ -813,7 +813,7 @@ class RenderPathPaint {
 		mat4_get_inv(m2, scene_camera.vp);
 		mat4_mult_mat(m, m2);
 
-		let tiled: bool = UIView2D.tiled_show;
+		let tiled: bool = ui_view2d_tiled_show;
 		if (tiled && scene_get_child(".PlaneTiled") == null) {
 			// 3x3 planes
 			let posa: i32[] = [32767,0,-32767,0,10922,0,-10922,0,10922,0,-32767,0,10922,0,-10922,0,-10922,0,10922,0,-10922,0,-10922,0,-10922,0,10922,0,-32767,0,32767,0,-32767,0,10922,0,10922,0,10922,0,-10922,0,32767,0,-10922,0,10922,0,32767,0,10922,0,10922,0,32767,0,10922,0,10922,0,-10922,0,-10922,0,-32767,0,10922,0,-32767,0,-10922,0,32767,0,-10922,0,10922,0,10922,0,10922,0,-10922,0,-10922,0,-32767,0,-32767,0,-10922,0,-32767,0,-32767,0,10922,0,-32767,0,-10922,0,-10922,0,-10922,0,-32767,0,32767,0,-32767,0,32767,0,-10922,0,10922,0,-10922,0,10922,0,-10922,0,10922,0,10922,0,-10922,0,10922,0,-10922,0,10922,0,-10922,0,32767,0,-32767,0,32767,0,10922,0,10922,0,10922,0,32767,0,-10922,0,32767,0,32767,0,10922,0,32767,0,32767,0,10922,0,32767,0,-10922,0,-10922,0,-10922,0,10922,0,-32767,0,10922,0,32767,0,-10922,0,32767,0,10922,0,10922,0,10922,0,-10922,0,-32767,0,-10922,0,-10922,0,-32767,0,-10922,0,10922,0,-32767,0,10922,0,-10922,0,-10922,0,-10922,0];
@@ -845,7 +845,7 @@ class RenderPathPaint {
 
 		let v: vec4_t = vec4_create();
 		let sx: f32 = vec4_len(vec4_set(v, m.m[0], m.m[1], m.m[2]));
-		quat_from_euler(RenderPathPaint.planeo.base.transform.rot, -Math.PI / 2, 0, 0);
+		quat_from_euler(RenderPathPaint.planeo.base.transform.rot, -math_pi() / 2, 0, 0);
 		vec4_set(RenderPathPaint.planeo.base.transform.scale, sx, 1.0, sx);
 		RenderPathPaint.planeo.base.transform.scale.z *= config_get_texture_res_y() / config_get_texture_res_x();
 		vec4_set(RenderPathPaint.planeo.base.transform.loc, m.m[12], -m.m[13], 0.0);
@@ -903,7 +903,7 @@ class RenderPathPaint {
 	static dilate = (base: bool, nor_pack: bool) => {
 		///if is_paint
 		if (config_raw.dilate_radius > 0 && !context_raw.paint2d) {
-			UtilUV.cache_dilate_map();
+			util_uv_cache_dilate_map();
 			base_make_temp_img();
 			let tid: i32 = context_raw.layer.id;
 			if (base) {

+ 8 - 8
armorpaint/Sources/RenderPathPreview.ts

@@ -25,8 +25,8 @@ class RenderPathPreview {
 		{
 			let t: render_target_t = render_target_create();
 			t.name = "mtex";
-			t.width = Math.floor(UtilRender.material_preview_size * 2.0);
-			t.height = Math.floor(UtilRender.material_preview_size * 2.0);
+			t.width = math_floor(util_render_material_preview_size * 2.0);
+			t.height = math_floor(util_render_material_preview_size * 2.0);
 			t.format = "RGBA64";
 			t.scale = RenderPathBase.get_super_sampling();
 			///if krom_opengl
@@ -38,8 +38,8 @@ class RenderPathPreview {
 		{
 			let t: render_target_t = render_target_create();
 			t.name = "mgbuffer0";
-			t.width = Math.floor(UtilRender.material_preview_size * 2.0);
-			t.height = Math.floor(UtilRender.material_preview_size * 2.0);
+			t.width = math_floor(util_render_material_preview_size * 2.0);
+			t.height = math_floor(util_render_material_preview_size * 2.0);
 			t.format = "RGBA64";
 			t.scale = RenderPathBase.get_super_sampling();
 			t.depth_buffer = "mmain";
@@ -49,8 +49,8 @@ class RenderPathPreview {
 		{
 			let t: render_target_t = render_target_create();
 			t.name = "mgbuffer1";
-			t.width = Math.floor(UtilRender.material_preview_size * 2.0);
-			t.height = Math.floor(UtilRender.material_preview_size * 2.0);
+			t.width = math_floor(util_render_material_preview_size * 2.0);
+			t.height = math_floor(util_render_material_preview_size * 2.0);
 			t.format = "RGBA64";
 			t.scale = RenderPathBase.get_super_sampling();
 			render_path_create_render_target(t);
@@ -59,8 +59,8 @@ class RenderPathPreview {
 		{
 			let t: render_target_t = render_target_create();
 			t.name = "mgbuffer2";
-			t.width = Math.floor(UtilRender.material_preview_size * 2.0);
-			t.height = Math.floor(UtilRender.material_preview_size * 2.0);
+			t.width = math_floor(util_render_material_preview_size * 2.0);
+			t.height = math_floor(util_render_material_preview_size * 2.0);
 			t.format = "RGBA64";
 			t.scale = RenderPathBase.get_super_sampling();
 			render_path_create_render_target(t);

+ 5 - 5
armorpaint/Sources/SlotLayer.ts

@@ -89,7 +89,7 @@ class SlotLayer {
 				raw.texpaint_pack = render_path_create_render_target(t)._image;
 			}
 
-			raw.texpaint_preview = image_create_render_target(UtilRender.layer_preview_size, UtilRender.layer_preview_size, tex_format_t.RGBA32);
+			raw.texpaint_preview = image_create_render_target(util_render_layer_preview_size, util_render_layer_preview_size, tex_format_t.RGBA32);
 			///end
 		}
 
@@ -108,7 +108,7 @@ class SlotLayer {
 				raw.texpaint = render_path_create_render_target(t)._image;
 			}
 
-			raw.texpaint_preview = image_create_render_target(UtilRender.layer_preview_size, UtilRender.layer_preview_size, tex_format_t.RGBA32);
+			raw.texpaint_preview = image_create_render_target(util_render_layer_preview_size, util_render_layer_preview_size, tex_format_t.RGBA32);
 		}
 		///end
 
@@ -408,7 +408,7 @@ class SlotLayer {
 		let _next = () => {
 			MakeMaterial.parse_paint_material();
 			context_raw.layer_preview_dirty = true;
-			UIBase.hwnds[tab_area_t.SIDEBAR0].redraws = 2;
+			ui_base_hwnds[tab_area_t.SIDEBAR0].redraws = 2;
 		}
 		base_notify_on_next_frame(_next);
 	}
@@ -418,7 +418,7 @@ class SlotLayer {
 		raw.fill_layer = null;
 		MakeMaterial.parse_paint_material();
 		context_raw.layer_preview_dirty = true;
-		UIBase.hwnds[tab_area_t.SIDEBAR0].redraws = 2;
+		ui_base_hwnds[tab_area_t.SIDEBAR0].redraws = 2;
 	}
 
 	static is_visible = (raw: SlotLayerRaw): bool => {
@@ -631,7 +631,7 @@ class SlotLayer {
 
 		context_set_layer(raw);
 		history_order_layers(to);
-		UIBase.hwnds[tab_area_t.SIDEBAR0].redraws = 2;
+		ui_base_hwnds[tab_area_t.SIDEBAR0].redraws = 2;
 
 		array_remove(project_layers, raw);
 		project_layers.splice(to, 0, raw);

+ 1 - 1
armorpaint/Sources/SlotMaterial.ts

@@ -27,7 +27,7 @@ class SlotMaterial {
 		for (let mat of project_materials) if (mat.id >= raw.id) raw.id = mat.id + 1;
 		raw.data = m;
 
-		let w: i32 = UtilRender.material_preview_size;
+		let w: i32 = util_render_material_preview_size;
 		let w_icon: i32 = 50;
 		raw.image = image_create_render_target(w, w);
 		raw.image_icon = image_create_render_target(w_icon, w_icon);

+ 90 - 90
armorpaint/Sources/TabLayers.ts

@@ -6,16 +6,16 @@ class TabLayers {
 	static show_context_menu: bool = false;
 
 	static draw = (htab: zui_handle_t) => {
-		let mini: bool = config_raw.layout[layout_size_t.SIDEBAR_W] <= UIBase.sidebar_mini_w;
+		let mini: bool = config_raw.layout[layout_size_t.SIDEBAR_W] <= ui_base_sidebar_mini_w;
 		mini ? TabLayers.draw_mini(htab) : TabLayers.draw_full(htab);
 	}
 
 	static draw_mini = (htab: zui_handle_t) => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 		zui_set_hovered_tab_name(tr("Layers"));
 
 		let _ELEMENT_H: i32 = ui.t.ELEMENT_H;
-		ui.t.ELEMENT_H = Math.floor(UIBase.sidebar_mini_w / 2 / zui_SCALE(ui));
+		ui.t.ELEMENT_H = math_floor(ui_base_sidebar_mini_w / 2 / zui_SCALE(ui));
 
 		zui_begin_sticky();
 		zui_separator(5);
@@ -34,7 +34,7 @@ class TabLayers {
 	}
 
 	static draw_full = (htab: zui_handle_t) => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 		if (zui_tab(htab, tr("Layers"))) {
 			zui_begin_sticky();
 			zui_row([1 / 4, 1 / 4, 1 / 2]);
@@ -52,9 +52,9 @@ class TabLayers {
 	}
 
 	static button_2d_view = () => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 		if (zui_button(tr("2D View"))) {
-			UIBase.show_2d_view(view_2d_type_t.LAYER);
+			ui_base_show_2d_view(view_2d_type_t.LAYER);
 		}
 		else if (ui.is_hovered) zui_tooltip(tr("Show 2D View") + ` (${config_keymap.toggle_2d_view})`);
 	}
@@ -69,10 +69,10 @@ class TabLayers {
 	}
 
 	static highlight_odd_lines = () => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 		let step: i32 = ui.t.ELEMENT_H * 2;
-		let full_h: i32 = ui._window_h - UIBase.hwnds[0].scroll_offset;
-		for (let i: i32 = 0; i < Math.floor(full_h / step); ++i) {
+		let full_h: i32 = ui._window_h - ui_base_hwnds[0].scroll_offset;
+		for (let i: i32 = 0; i < math_floor(full_h / step); ++i) {
 			if (i % 2 == 0) {
 				zui_fill(0, i * step, (ui._w / zui_SCALE(ui) - 2), step, ui.t.WINDOW_BG_COL - 0x00040404);
 			}
@@ -81,19 +81,19 @@ class TabLayers {
 
 	static button_new = (text: string) => {
 		if (zui_button(text)) {
-			UIMenu.draw((ui: zui_t) => {
+			ui_menu_draw((ui: zui_t) => {
 				let l: SlotLayerRaw = context_raw.layer;
-				if (UIMenu.menu_button(ui, tr("Paint Layer"))) {
+				if (ui_menu_button(ui, tr("Paint Layer"))) {
 					base_new_layer();
 					history_new_layer();
 				}
-				if (UIMenu.menu_button(ui, tr("Fill Layer"))) {
+				if (ui_menu_button(ui, tr("Fill Layer"))) {
 					base_create_fill_layer(uv_type_t.UVMAP);
 				}
-				if (UIMenu.menu_button(ui, tr("Decal Layer"))) {
+				if (ui_menu_button(ui, tr("Decal Layer"))) {
 					base_create_fill_layer(uv_type_t.PROJECT);
 				}
-				if (UIMenu.menu_button(ui, tr("Black Mask"))) {
+				if (ui_menu_button(ui, tr("Black Mask"))) {
 					if (SlotLayer.is_mask(l)) context_set_layer(l.parent);
 					// let l: SlotLayerRaw = raw.layer;
 
@@ -106,7 +106,7 @@ class TabLayers {
 					history_new_black_mask();
 					base_update_fill_layers();
 				}
-				if (UIMenu.menu_button(ui, tr("White Mask"))) {
+				if (ui_menu_button(ui, tr("White Mask"))) {
 					if (SlotLayer.is_mask(l)) context_set_layer(l.parent);
 					// let l: SlotLayerRaw = raw.layer;
 
@@ -119,7 +119,7 @@ class TabLayers {
 					history_new_white_mask();
 					base_update_fill_layers();
 				}
-				if (UIMenu.menu_button(ui, tr("Fill Mask"))) {
+				if (ui_menu_button(ui, tr("Fill Mask"))) {
 					if (SlotLayer.is_mask(l)) context_set_layer(l.parent);
 					// let l: SlotLayerRaw = raw.layer;
 
@@ -133,7 +133,7 @@ class TabLayers {
 					base_update_fill_layers();
 				}
 				ui.enabled = !SlotLayer.is_group(context_raw.layer) && !SlotLayer.is_in_group(context_raw.layer);
-				if (UIMenu.menu_button(ui, tr("Group"))) {
+				if (ui_menu_button(ui, tr("Group"))) {
 					if (SlotLayer.is_group(l) || SlotLayer.is_in_group(l)) return;
 
 					if (SlotLayer.is_layer_mask(l)) l = l.parent;
@@ -166,15 +166,15 @@ class TabLayers {
 				p.base.visible = context_raw.layer_filter == 0 || p.base.name == ar[context_raw.layer_filter] || project_is_atlas_object(p);
 			}
 			if (context_raw.layer_filter == 0 && context_raw.merged_object_is_atlas) { // All
-				UtilMesh.merge_mesh();
+				util_mesh_merge();
 			}
 			else if (context_raw.layer_filter > project_paint_objects.length) { // Atlas
 				let visibles: mesh_object_t[] = [];
 				for (let p of project_paint_objects) if (p.base.visible) visibles.push(p);
-				UtilMesh.merge_mesh(visibles);
+				util_mesh_merge(visibles);
 			}
 			base_set_object_mask();
-			UtilUV.uvmap_cached = false;
+			util_uv_uvmap_cached = false;
 			context_raw.ddirty = 2;
 			///if (krom_direct3d12 || krom_vulkan || krom_metal)
 			RenderPathRaytrace.ready = false;
@@ -182,7 +182,7 @@ class TabLayers {
 		}
 	}
 
-	static remap_layer_pointers = (nodes: zui_node_t[], pointerMap: Map<i32, i32>) => {
+	static remap_layer_pointers = (nodes: zui_node_t[], pointerMap: map_t<i32, i32>) => {
 		for (let n of nodes) {
 			if (n.type == "LAYER" || n.type == "LAYER_MASK") {
 				let i: any = n.buttons[0].default_value;
@@ -193,14 +193,14 @@ class TabLayers {
 		}
 	}
 
-	static init_layer_map = (): Map<SlotLayerRaw, i32> => {
-		let res: Map<SlotLayerRaw, i32> = new Map();
+	static init_layer_map = (): map_t<SlotLayerRaw, i32> => {
+		let res: map_t<SlotLayerRaw, i32> = map_create();
 		for (let i: i32 = 0; i < project_layers.length; ++i) res.set(project_layers[i], i);
 		return res;
 	}
 
-	static fill_layer_map = (map: Map<SlotLayerRaw, i32>): Map<i32, i32> => {
-		let res: Map<i32, i32> = new Map();
+	static fill_layer_map = (map: map_t<SlotLayerRaw, i32>): map_t<i32, i32> => {
+		let res: map_t<i32, i32> = map_create();
 		for (let l of map.keys()) res.set(map.get(l), project_layers.indexOf(l) > -1 ? project_layers.indexOf(l) : 9999);
 		return res;
 	}
@@ -213,7 +213,7 @@ class TabLayers {
 	}
 
 	static draw_layer_slot = (l: SlotLayerRaw, i: i32, mini: bool) => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 
 		if (context_raw.layer_filter > 0 &&
 			SlotLayer.get_object_mask(l) > 0 &&
@@ -278,7 +278,7 @@ class TabLayers {
 	}
 
 	static draw_layer_slot_mini = (l: SlotLayerRaw, i: i32) => {
-		let ui = UIBase.ui;
+		let ui = ui_base_ui;
 
 		zui_row([1, 1]);
 		let uix: f32 = ui._x;
@@ -292,7 +292,7 @@ class TabLayers {
 	}
 
 	static draw_layer_slot_full = (l: SlotLayerRaw, i: i32) => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 
 		let step: i32 = ui.t.ELEMENT_H;
 
@@ -504,12 +504,12 @@ class TabLayers {
 
 	static layer_toggle_visible = (l: SlotLayerRaw) => {
 		l.visible = !l.visible;
-		UIView2D.hwnd.redraws = 2;
+		ui_view2d_hwnd.redraws = 2;
 		MakeMaterial.parse_mesh_material();
 	}
 
 	static draw_layer_highlight = (l: SlotLayerRaw, mini: bool) => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 		let step: i32 = ui.t.ELEMENT_H;
 
 		// Separator line
@@ -527,7 +527,7 @@ class TabLayers {
 	}
 
 	static handle_layer_icon_state = (l: SlotLayerRaw, i: i32, state: zui_state_t, uix: f32, uiy: f32) => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 
 		///if is_paint
 		let texpaint_preview: image_t = l.texpaint_preview;
@@ -563,7 +563,7 @@ class TabLayers {
 		}
 		else if (state == zui_state_t.RELEASED) {
 			if (time_time() - context_raw.select_time < 0.2) {
-				UIBase.show_2d_view(view_2d_type_t.LAYER);
+				ui_base_show_2d_view(view_2d_type_t.LAYER);
 			}
 			if (time_time() - context_raw.select_time > 0.2) {
 				context_raw.select_time = time_time();
@@ -573,7 +573,7 @@ class TabLayers {
 	}
 
 	static draw_layer_icon = (l: SlotLayerRaw, i: i32, uix: f32, uiy: f32, mini: bool) => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 		let icons: image_t = resource_get("icons.k");
 		let icon_h: i32 = (zui_ELEMENT_H(ui) - (mini ? 2 : 3)) * 2;
 
@@ -612,11 +612,11 @@ class TabLayers {
 				ui._w = _w;
 			}
 			if (l.fill_layer == null && SlotLayer.is_mask(l)) {
-				g2_set_pipeline(UIView2D.pipe);
+				g2_set_pipeline(ui_view2d_pipe);
 				///if krom_opengl
-				krom_g4_set_pipeline(UIView2D.pipe.pipeline_);
+				krom_g4_set_pipeline(ui_view2d_pipe.pipeline_);
 				///end
-				krom_g4_set_int(UIView2D.channel_location, 1);
+				krom_g4_set_int(ui_view2d_channel_loc, 1);
 			}
 
 			let state: zui_state_t = zui_image(icon, 0xffffffff, icon_h);
@@ -626,7 +626,7 @@ class TabLayers {
 			}
 
 			// Draw layer numbers when selecting a layer via keyboard shortcut
-			let is_typing: bool = ui.is_typing || UIView2D.ui.is_typing || UINodes.ui.is_typing;
+			let is_typing: bool = ui.is_typing || ui_view2d_ui.is_typing || ui_nodes_ui.is_typing;
 			if (!is_typing) {
 				if (i < 9 && operator_shortcut(config_keymap.select_layer, shortcut_type_t.DOWN)) {
 					let number: string = String(i + 1) ;
@@ -676,36 +676,36 @@ class TabLayers {
 		}
 		let menu_elements: i32 = SlotLayer.is_group(l) ? 7 : (19 + add);
 
-		UIMenu.draw((ui: zui_t) => {
+		ui_menu_draw((ui: zui_t) => {
 
 			if (mini) {
 				let visible_handle: zui_handle_t = zui_handle("tablayers_4");
 				visible_handle.selected = l.visible;
-				UIMenu.menu_fill(ui);
+				ui_menu_fill(ui);
 				zui_check(visible_handle, tr("Visible"));
 				if (visible_handle.changed) {
 					TabLayers.layer_toggle_visible(l);
-					UIMenu.keep_open = true;
+					ui_menu_keep_open = true;
 				}
 
 				if (!SlotLayer.is_group(l)) {
-					UIMenu.menu_fill(ui);
+					ui_menu_fill(ui);
 					if (TabLayers.combo_blending(ui, l, true).changed) {
-						UIMenu.keep_open = true;
+						ui_menu_keep_open = true;
 					}
 				}
 				if (SlotLayer.is_layer(l)) {
-					UIMenu.menu_fill(ui);
+					ui_menu_fill(ui);
 					if (TabLayers.combo_object(ui, l, true).changed) {
-						UIMenu.keep_open = true;
+						ui_menu_keep_open = true;
 					}
 				}
 			}
 
-			if (UIMenu.menu_button(ui, tr("Export"))) {
+			if (ui_menu_button(ui, tr("Export"))) {
 				if (SlotLayer.is_mask(l)) {
-					UIFiles.show("png", true, false, (path: string) => {
-						let f: string = UIFiles.filename;
+					ui_files_show("png", true, false, (path: string) => {
+						let f: string = ui_files_filename;
 						if (f == "") f = tr("untitled");
 						if (!f.endsWith(".png")) f += ".png";
 						krom_write_png(path + path_sep + f, image_get_pixels(l.texpaint), l.texpaint.width, l.texpaint.height, 3); // RRR1
@@ -723,14 +723,14 @@ class TabLayers {
 				let to_fill_string: string = SlotLayer.is_layer(l) ? tr("To Fill Layer") : tr("To Fill Mask");
 				let to_paint_string: string = SlotLayer.is_layer(l) ? tr("To Paint Layer") : tr("To Paint Mask");
 
-				if (l.fill_layer == null && UIMenu.menu_button(ui, to_fill_string)) {
+				if (l.fill_layer == null && ui_menu_button(ui, to_fill_string)) {
 					let _init = () => {
 						SlotLayer.is_layer(l) ? history_to_fill_layer() : history_to_fill_mask();
 						SlotLayer.to_fill_layer(l);
 					}
 					app_notify_on_init(_init);
 				}
-				if (l.fill_layer != null && UIMenu.menu_button(ui, to_paint_string)) {
+				if (l.fill_layer != null && ui_menu_button(ui, to_paint_string)) {
 					let _init = () => {
 						SlotLayer.is_layer(l) ? history_to_paint_layer() : history_to_paint_mask();
 						SlotLayer.to_paint_layer(l);
@@ -740,7 +740,7 @@ class TabLayers {
 			}
 
 			ui.enabled = TabLayers.can_delete(l);
-			if (UIMenu.menu_button(ui, tr("Delete"), "delete")) {
+			if (ui_menu_button(ui, tr("Delete"), "delete")) {
 				let _init = () => {
 					TabLayers.delete_layer(context_raw.layer);
 				}
@@ -748,7 +748,7 @@ class TabLayers {
 			}
 			ui.enabled = true;
 
-			if (l.fill_layer == null && UIMenu.menu_button(ui, tr("Clear"))) {
+			if (l.fill_layer == null && ui_menu_button(ui, tr("Clear"))) {
 				context_set_layer(l);
 				let _init = () => {
 					if (!SlotLayer.is_group(l)) {
@@ -767,7 +767,7 @@ class TabLayers {
 				}
 				app_notify_on_init(_init);
 			}
-			if (SlotLayer.is_mask(l) && l.fill_layer == null && UIMenu.menu_button(ui, tr("Invert"))) {
+			if (SlotLayer.is_mask(l) && l.fill_layer == null && ui_menu_button(ui, tr("Invert"))) {
 				let _init = () => {
 					context_set_layer(l);
 					history_invert_mask();
@@ -775,7 +775,7 @@ class TabLayers {
 				}
 				app_notify_on_init(_init);
 			}
-			if (SlotLayer.is_mask(l) && UIMenu.menu_button(ui, tr("Apply"))) {
+			if (SlotLayer.is_mask(l) && ui_menu_button(ui, tr("Apply"))) {
 				let _init = () => {
 					context_raw.layer = l;
 					history_apply_mask();
@@ -786,14 +786,14 @@ class TabLayers {
 				}
 				app_notify_on_init(_init);
 			}
-			if (SlotLayer.is_group(l) && UIMenu.menu_button(ui, tr("Merge Group"))) {
+			if (SlotLayer.is_group(l) && ui_menu_button(ui, tr("Merge Group"))) {
 				let _init = () => {
 					base_merge_group(l);
 				}
 				app_notify_on_init(_init);
 			}
 			ui.enabled = TabLayers.can_merge_down(l);
-			if (UIMenu.menu_button(ui, tr("Merge Down"))) {
+			if (ui_menu_button(ui, tr("Merge Down"))) {
 				let _init = () => {
 					context_set_layer(l);
 					history_merge_layers();
@@ -803,7 +803,7 @@ class TabLayers {
 				app_notify_on_init(_init);
 			}
 			ui.enabled = true;
-			if (UIMenu.menu_button(ui, tr("Duplicate"))) {
+			if (ui_menu_button(ui, tr("Duplicate"))) {
 				let _init = () => {
 					context_set_layer(l);
 					history_duplicate_layer();
@@ -812,8 +812,8 @@ class TabLayers {
 				app_notify_on_init(_init);
 			}
 
-			UIMenu.menu_fill(ui);
-			UIMenu.menu_align(ui);
+			ui_menu_fill(ui);
+			ui_menu_align(ui);
 			let layer_opac_handle: zui_handle_t = zui_nest(zui_handle("tablayers_5"), l.id);
 			layer_opac_handle.value = l.mask_opacity;
 			zui_slider(layer_opac_handle, tr("Opacity"), 0.0, 1.0, true);
@@ -821,12 +821,12 @@ class TabLayers {
 				if (ui.input_started) history_layer_opacity();
 				l.mask_opacity = layer_opac_handle.value;
 				MakeMaterial.parse_mesh_material();
-				UIMenu.keep_open = true;
+				ui_menu_keep_open = true;
 			}
 
 			if (!SlotLayer.is_group(l)) {
-				UIMenu.menu_fill(ui);
-				UIMenu.menu_align(ui);
+				ui_menu_fill(ui);
+				ui_menu_align(ui);
 				let res_handle_changed_last: bool = base_res_handle.changed;
 				///if (krom_android || krom_ios)
 				let ar: string[] = ["128", "256", "512", "1K", "2K", "4K"];
@@ -835,9 +835,9 @@ class TabLayers {
 				///end
 				let _y: i32 = ui._y;
 				base_res_handle.value = base_res_handle.position;
-				base_res_handle.position = Math.floor(zui_slider(base_res_handle, ar[base_res_handle.position], 0, ar.length - 1, false, 1, false, zui_align_t.LEFT, false));
+				base_res_handle.position = math_floor(zui_slider(base_res_handle, ar[base_res_handle.position], 0, ar.length - 1, false, 1, false, zui_align_t.LEFT, false));
 				if (base_res_handle.changed) {
-					UIMenu.keep_open = true;
+					ui_menu_keep_open = true;
 				}
 				if (res_handle_changed_last && !base_res_handle.changed) {
 					base_on_layers_resized();
@@ -846,8 +846,8 @@ class TabLayers {
 				zui_draw_string(tr("Res"), null, 0, zui_align_t.RIGHT);
 				zui_end_element();
 
-				UIMenu.menu_fill(ui);
-				UIMenu.menu_align(ui);
+				ui_menu_fill(ui);
+				ui_menu_align(ui);
 				///if (krom_android || krom_ios)
 				zui_inline_radio(base_bits_handle, ["8bit"]);
 				///else
@@ -855,13 +855,13 @@ class TabLayers {
 				///end
 				if (base_bits_handle.changed) {
 					app_notify_on_init(base_set_layer_bits);
-					UIMenu.keep_open = true;
+					ui_menu_keep_open = true;
 				}
 			}
 
 			if (l.fill_layer != null) {
-				UIMenu.menu_fill(ui);
-				UIMenu.menu_align(ui);
+				ui_menu_fill(ui);
+				ui_menu_align(ui);
 				let scale_handle: zui_handle_t = zui_nest(zui_handle("tablayers_6"), l.id);
 				scale_handle.value = l.scale;
 				l.scale = zui_slider(scale_handle, tr("UV Scale"), 0.0, 5.0, true);
@@ -872,11 +872,11 @@ class TabLayers {
 						base_update_fill_layers();
 					}
 					app_notify_on_init(_init);
-					UIMenu.keep_open = true;
+					ui_menu_keep_open = true;
 				}
 
-				UIMenu.menu_fill(ui);
-				UIMenu.menu_align(ui);
+				ui_menu_fill(ui);
+				ui_menu_align(ui);
 				let angle_handle: zui_handle_t = zui_nest(zui_handle("tablayers_7"), l.id);
 				angle_handle.value = l.angle;
 				l.angle = zui_slider(angle_handle, tr("Angle"), 0.0, 360, true, 1);
@@ -888,11 +888,11 @@ class TabLayers {
 						base_update_fill_layers();
 					}
 					app_notify_on_init(_init);
-					UIMenu.keep_open = true;
+					ui_menu_keep_open = true;
 				}
 
-				UIMenu.menu_fill(ui);
-				UIMenu.menu_align(ui);
+				ui_menu_fill(ui);
+				ui_menu_align(ui);
 				let uv_type_handle: zui_handle_t = zui_nest(zui_handle("tablayers_8"), l.id);
 				uv_type_handle.position = l.uv_type;
 				l.uv_type = zui_inline_radio(uv_type_handle, [tr("UV Map"), tr("Triplanar"), tr("Project")], zui_align_t.LEFT);
@@ -904,7 +904,7 @@ class TabLayers {
 						base_update_fill_layers();
 					}
 					app_notify_on_init(_init);
-					UIMenu.keep_open = true;
+					ui_menu_keep_open = true;
 				}
 			}
 
@@ -931,27 +931,27 @@ class TabLayers {
 				height_blend_handle.selected = l.paint_height_blend;
 				emis_handle.selected = l.paint_emis;
 				subs_handle.selected = l.paint_subs;
-				UIMenu.menu_fill(ui);
+				ui_menu_fill(ui);
 				l.paint_base = zui_check(base_handle, tr("Base Color"));
-				UIMenu.menu_fill(ui);
+				ui_menu_fill(ui);
 				l.paint_opac = zui_check(opac_handle, tr("Opacity"));
-				UIMenu.menu_fill(ui);
+				ui_menu_fill(ui);
 				l.paint_nor = zui_check(nor_handle, tr("Normal"));
-				UIMenu.menu_fill(ui);
+				ui_menu_fill(ui);
 				l.paint_nor_blend = zui_check(nor_blend_handle, tr("Normal Blending"));
-				UIMenu.menu_fill(ui);
+				ui_menu_fill(ui);
 				l.paint_occ = zui_check(occ_handle, tr("Occlusion"));
-				UIMenu.menu_fill(ui);
+				ui_menu_fill(ui);
 				l.paint_rough = zui_check(rough_handle, tr("Roughness"));
-				UIMenu.menu_fill(ui);
+				ui_menu_fill(ui);
 				l.paint_met = zui_check(met_handle, tr("Metallic"));
-				UIMenu.menu_fill(ui);
+				ui_menu_fill(ui);
 				l.paint_height = zui_check(height_handle, tr("Height"));
-				UIMenu.menu_fill(ui);
+				ui_menu_fill(ui);
 				l.paint_height_blend = zui_check(height_blend_handle, tr("Height Blending"));
-				UIMenu.menu_fill(ui);
+				ui_menu_fill(ui);
 				l.paint_emis = zui_check(emis_handle, tr("Emission"));
-				UIMenu.menu_fill(ui);
+				ui_menu_fill(ui);
 				l.paint_subs = zui_check(subs_handle, tr("Subsurface"));
 				if (base_handle.changed ||
 					opac_handle.changed ||
@@ -965,7 +965,7 @@ class TabLayers {
 					emis_handle.changed ||
 					subs_handle.changed) {
 					MakeMaterial.parse_mesh_material();
-					UIMenu.keep_open = true;
+					ui_menu_keep_open = true;
 				}
 			}
 		}, menu_elements);
@@ -974,15 +974,15 @@ class TabLayers {
 	static make_mask_preview_rgba32 = (l: SlotLayerRaw) => {
 		///if is_paint
 		if (context_raw.mask_preview_rgba32 == null) {
-			context_raw.mask_preview_rgba32 = image_create_render_target(UtilRender.layer_preview_size, UtilRender.layer_preview_size);
+			context_raw.mask_preview_rgba32 = image_create_render_target(util_render_layer_preview_size, util_render_layer_preview_size);
 		}
 		// Convert from R8 to RGBA32 for tooltip display
 		if (context_raw.mask_preview_last != l) {
 			context_raw.mask_preview_last = l;
 			app_notify_on_init(() => {
 				g2_begin(context_raw.mask_preview_rgba32);
-				g2_set_pipeline(UIView2D.pipe);
-				g4_set_int(UIView2D.channel_location, 1);
+				g2_set_pipeline(ui_view2d_pipe);
+				g4_set_int(ui_view2d_channel_loc, 1);
 				g2_draw_image(l.texpaint_preview, 0, 0);
 				g2_end();
 				g2_set_pipeline(null);

+ 3 - 3
armorpaint/Sources/nodes/BrushOutputNode.ts

@@ -81,7 +81,7 @@ class BrushOutputNode extends LogicNode {
 		let right: f32 = 1.0;
 		if (context_raw.paint2d) {
 			left = 1.0;
-			right = (context_raw.split_view ? 2.0 : 1.0) + UIView2D.ww / base_w();
+			right = (context_raw.split_view ? 2.0 : 1.0) + ui_view2d_ww / base_w();
 		}
 
 		// First time init
@@ -104,7 +104,7 @@ class BrushOutputNode extends LogicNode {
 			!fill_layer &&
 			!group_layer &&
 			(SlotLayer.is_visible(context_raw.layer) || context_raw.paint2d) &&
-			!UIBase.ui.is_hovered &&
+			!ui_base_ui.is_hovered &&
 			!base_is_dragging &&
 			!base_is_resizing &&
 			!base_is_scrolling() &&
@@ -114,7 +114,7 @@ class BrushOutputNode extends LogicNode {
 			let down: bool = mouse_down() || pen_down();
 			if (down && context_raw.tool == workspace_tool_t.COLORID && project_assets.length > 0) {
 				context_raw.colorid_picked = true;
-				UIToolbar.toolbar_handle.redraws = 1;
+				ui_toolbar_handle.redraws = 1;
 			}
 
 			// Prevent painting the same spot

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

@@ -72,8 +72,8 @@ class InputNode extends LogicNode {
 		}
 
 		if (InputNode.lock_begin) {
-			let dx: f32 = Math.abs(InputNode.lock_start_x - mouse_view_x());
-			let dy: f32 = Math.abs(InputNode.lock_start_y - mouse_view_y());
+			let dx: f32 = math_abs(InputNode.lock_start_x - mouse_view_x());
+			let dy: f32 = math_abs(InputNode.lock_start_y - mouse_view_y());
 			if (dx > 1 || dy > 1) {
 				InputNode.lock_begin = false;
 				dx > dy ? InputNode.lock_y = true : InputNode.lock_x = true;

二進制
armorsculpt/Assets/Scene.arm


+ 7 - 7
armorsculpt/Sources/ExportObj.ts

@@ -20,9 +20,9 @@ class ExportObj {
 		let posa = new Int16Array(inda.length * 4);
 		for (let i = 0; i < inda.length; ++i) {
 			let index = inda[i];
-			posa[index * 4    ] = Math.floor(pixelsView.getFloat32(i * 16    , true) * 32767);
-			posa[index * 4 + 1] = Math.floor(pixelsView.getFloat32(i * 16 + 4, true) * 32767);
-			posa[index * 4 + 2] = Math.floor(pixelsView.getFloat32(i * 16 + 8, true) * 32767);
+			posa[index * 4    ] = math_floor(pixelsView.getFloat32(i * 16    , true) * 32767);
+			posa[index * 4 + 1] = math_floor(pixelsView.getFloat32(i * 16 + 4, true) * 32767);
+			posa[index * 4 + 2] = math_floor(pixelsView.getFloat32(i * 16 + 8, true) * 32767);
 		}
 
 		let poff = 0;
@@ -32,12 +32,12 @@ class ExportObj {
 			let inv = 1 / 32767;
 			let sc = p.data.scale_pos * inv;
 			// let posa = mesh.vertex_arrays[0].values;
-			let len = Math.floor(posa.length / 4);
-			// let len = Math.floor(inda.length);
+			let len = math_floor(posa.length / 4);
+			// let len = math_floor(inda.length);
 
 			// Merge shared vertices and remap indices
 			let posa2 = new Int16Array(len * 3);
-			let posmap = new Map<i32, i32>();
+			let posmap = new map_t<i32, i32>();
 
 			let pi = 0;
 			for (let i = 0; i < len; ++i) {
@@ -75,7 +75,7 @@ class ExportObj {
 			}
 
 			// let inda = mesh.index_arrays[0].values;
-			for (let i = 0; i < Math.floor(inda.length / 3); ++i) {
+			for (let i = 0; i < math_floor(inda.length / 3); ++i) {
 				let pi1 = posmap.get(inda[i * 3    ]) + 1 + poff;
 				let pi2 = posmap.get(inda[i * 3 + 1]) + 1 + poff;
 				let pi3 = posmap.get(inda[i * 3 + 2]) + 1 + poff;

+ 7 - 7
armorsculpt/Sources/ImportMesh.ts

@@ -51,7 +51,7 @@ class ImportMesh {
 
 			// No mask by default
 			for (let p of project_paintObjects) p.base.visible = true;
-			if (context_raw.mergedObject == null) UtilMesh.mergeMesh();
+			if (context_raw.mergedObject == null) util_mesh_mergeMesh();
 			context_raw.paintObject.skip_context = "paint";
 			context_raw.mergedObject.base.visible = true;
 		}
@@ -62,7 +62,7 @@ class ImportMesh {
 		MakeMaterial.parsePaintMaterial();
 		MakeMaterial.parseMeshMaterial();
 
-		UIView2D.hwnd.redraws = 2;
+		ui_view2d_hwnd.redraws = 2;
 
 		///if arm_physics
 		context_raw.paintBody = null;
@@ -112,15 +112,15 @@ class ImportMesh {
 			data_cached_meshes.set(md._.handle, md);
 
 			context_raw.ddirty = 4;
-			UIBase.hwnds[TabArea.TabSidebar0].redraws = 2;
-			UIBase.hwnds[TabArea.TabSidebar1].redraws = 2;
+			ui_base_hwnds[TabArea.TabSidebar0].redraws = 2;
+			ui_base_hwnds[TabArea.TabSidebar1].redraws = 2;
 
 			// Wait for addMesh calls to finish
 			app_notify_on_init(ImportMesh.finishImport);
 
 			base_notifyOnNextFrame(() => {
 				let f32 = new Float32Array(config_getTextureResX() * config_getTextureResY() * 4);
-				for (let i = 0; i < Math.floor(mesh.inda.length); ++i) {
+				for (let i = 0; i < math_floor(mesh.inda.length); ++i) {
 					let index = mesh.inda[i];
 					f32[i * 4]     = mesh.posa[index * 4]     / 32767;
 					f32[i * 4 + 1] = mesh.posa[index * 4 + 1] / 32767;
@@ -167,14 +167,14 @@ class ImportMesh {
 			data_cached_meshes.set(md._.handle, md);
 
 			context_raw.ddirty = 4;
-			UIBase.hwnds[TabArea.TabSidebar0].redraws = 2;
+			ui_base_hwnds[TabArea.TabSidebar0].redraws = 2;
 		}
 
 		_addMesh();
 	}
 
 	static rawMesh = (mesh: any): mesh_data_t => {
-		let posa = new Int16Array(Math.floor(mesh.inda.length * 4));
+		let posa = new Int16Array(math_floor(mesh.inda.length * 4));
 		for (let i = 0; i < posa.length; ++i) posa[i] = 32767;
 		let inda = new Uint32Array(mesh.inda.length);
 		for (let i = 0; i < inda.length; ++i) inda[i] = i;

+ 14 - 13
armorsculpt/Sources/MakeMaterial.ts

@@ -9,7 +9,7 @@ class MakeMaterial {
 	static subsUsed = false;
 
 	static getMOut = (): bool => {
-		for (let n of UINodes.getCanvasMaterial().nodes) if (n.type == "OUTPUT_MATERIAL_PBR") return true;
+		for (let n of ui_nodes_getCanvasMaterial().nodes) if (n.type == "OUTPUT_MATERIAL_PBR") return true;
 		return false;
 	}
 
@@ -174,9 +174,10 @@ class MakeMaterial {
 
 		if (bakePreviews) {
 			let current = _g2_current;
-			if (current != null) g2_end();
+			let g2_in_use: bool = _g2_in_use;
+			if (g2_in_use) g2_end();
 			MakeMaterial.bakeNodePreviews();
-			if (current != null) g2_begin(current);
+			if (g2_in_use) g2_begin(current);
 		}
 
 		let m = project_materials[0].data;
@@ -198,7 +199,7 @@ class MakeMaterial {
 			}
 		}
 
-		let sdata: TMaterial = { name: "Material", canvas: UINodes.getCanvasMaterial() };
+		let sdata: TMaterial = { name: "Material", canvas: ui_nodes_getCanvasMaterial() };
 		let mcon2: material_context_t = { name: "paint", bind_textures: [] };
 		let con = MakeSculpt.run(sdata, mcon2);
 
@@ -224,8 +225,8 @@ class MakeMaterial {
 
 	static bakeNodePreviews = () => {
 		context_raw.nodePreviewsUsed = [];
-		if (context_raw.nodePreviews == null) context_raw.nodePreviews = new Map();
-		MakeMaterial.traverseNodes(UINodes.getCanvasMaterial().nodes, null, []);
+		if (context_raw.nodePreviews == null) context_raw.nodePreviews = map_create();
+		MakeMaterial.traverseNodes(ui_nodes_getCanvasMaterial().nodes, null, []);
 		for (let key of context_raw.nodePreviews.keys()) {
 			if (context_raw.nodePreviewsUsed.indexOf(key) == -1) {
 				let image = context_raw.nodePreviews.get(key);
@@ -256,8 +257,8 @@ class MakeMaterial {
 			let id = ParserMaterial.node_name(node, parents);
 			let image = context_raw.nodePreviews.get(id);
 			context_raw.nodePreviewsUsed.push(id);
-			let resX = Math.floor(config_getTextureResX() / 4);
-			let resY = Math.floor(config_getTextureResY() / 4);
+			let resX = math_floor(config_getTextureResX() / 4);
+			let resY = math_floor(config_getTextureResY() / 4);
 			if (image == null || image.width != resX || image.height != resY) {
 				if (image != null) image_unload(image);
 				image = image_create_render_target(resX, resY);
@@ -265,15 +266,15 @@ class MakeMaterial {
 			}
 
 			ParserMaterial.blur_passthrough = true;
-			UtilRender.makeNodePreview(UINodes.getCanvasMaterial(), node, image, group, parents);
+			UtilRender.makeNodePreview(ui_nodes_getCanvasMaterial(), node, image, group, parents);
 			ParserMaterial.blur_passthrough = false;
 		}
 		else if (node.type == "DIRECT_WARP") {
 			let id = ParserMaterial.node_name(node, parents);
 			let image = context_raw.nodePreviews.get(id);
 			context_raw.nodePreviewsUsed.push(id);
-			let resX = Math.floor(config_getTextureResX());
-			let resY = Math.floor(config_getTextureResY());
+			let resX = math_floor(config_getTextureResX());
+			let resY = math_floor(config_getTextureResY());
 			if (image == null || image.width != resX || image.height != resY) {
 				if (image != null) image_unload(image);
 				image = image_create_render_target(resX, resY);
@@ -281,14 +282,14 @@ class MakeMaterial {
 			}
 
 			ParserMaterial.warp_passthrough = true;
-			UtilRender.makeNodePreview(UINodes.getCanvasMaterial(), node, image, group, parents);
+			UtilRender.makeNodePreview(ui_nodes_getCanvasMaterial(), node, image, group, parents);
 			ParserMaterial.warp_passthrough = false;
 		}
 	}
 
 	static parseNodePreviewMaterial = (node: zui_node_t, group: zui_node_canvas_t = null, parents: zui_node_t[] = null): { scon: shader_context_t, mcon: material_context_t } => {
 		if (node.outputs.length == 0) return null;
-		let sdata: TMaterial = { name: "Material", canvas: UINodes.getCanvasMaterial() };
+		let sdata: TMaterial = { name: "Material", canvas: ui_nodes_getCanvasMaterial() };
 		let mcon_raw: material_context_t = { name: "mesh", bind_textures: [] };
 		let con = MakeNodePreview.run(sdata, mcon_raw, node, group, parents);
 		let compileError = false;

+ 6 - 6
armorsculpt/Sources/MakeMesh.ts

@@ -53,9 +53,9 @@ class MakeMesh {
 		NodeShader.write_attrib(vert, 'wnormal = mul(meshnor, N);');
 		NodeShader.write_attrib(frag, 'vec3 n = normalize(wnormal);');
 
-		NodeShader.add_function(frag, ShaderFunctions.str_packFloatInt16);
-		NodeShader.add_function(frag, ShaderFunctions.str_octahedronWrap);
-		NodeShader.add_function(frag, ShaderFunctions.str_cotangentFrame);
+		NodeShader.add_function(frag, str_packFloatInt16);
+		NodeShader.add_function(frag, str_octahedronWrap);
+		NodeShader.add_function(frag, str_cotangentFrame);
 		if (layerPass > 0) {
 			NodeShader.add_uniform(frag, 'sampler2D gbuffer0');
 			NodeShader.add_uniform(frag, 'sampler2D gbuffer1');
@@ -255,13 +255,13 @@ class MakeMesh {
 					NodeShader.add_uniform(frag, 'vec4 envmapData', '_envmapData'); // angle, sin(angle), cos(angle), strength
 					NodeShader.write(frag, 'vec3 wreflect = reflect(-vVec, n);');
 					NodeShader.write(frag, 'float envlod = roughness * float(envmapNumMipmaps);');
-					NodeShader.add_function(frag, ShaderFunctions.str_envMapEquirect);
+					NodeShader.add_function(frag, str_envMapEquirect);
 					NodeShader.write(frag, 'vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(wreflect, envmapData.x), envlod).rgb;');
 					NodeShader.add_uniform(frag, 'vec3 lightArea0', '_light_area0');
 					NodeShader.add_uniform(frag, 'vec3 lightArea1', '_light_area1');
 					NodeShader.add_uniform(frag, 'vec3 lightArea2', '_light_area2');
 					NodeShader.add_uniform(frag, 'vec3 lightArea3', '_light_area3');
-					NodeShader.add_function(frag, ShaderFunctions.str_ltcEvaluate);
+					NodeShader.add_function(frag, str_ltcEvaluate);
 					NodeShader.add_uniform(frag, 'vec3 lightPos', '_point_pos');
 					NodeShader.add_uniform(frag, 'vec3 lightColor', '_point_color');
 					NodeShader.write(frag, 'float ldist = distance(wposition, lightPos);');
@@ -281,7 +281,7 @@ class MakeMesh {
 					NodeShader.write(frag, 'direct *= lightColor * (1.0 / (ldist * ldist));');
 
 					NodeShader.add_uniform(frag, 'vec4 shirr[7]', '_envmap_irradiance');
-					NodeShader.add_function(frag, ShaderFunctions.str_shIrradiance);
+					NodeShader.add_function(frag, str_shIrradiance);
 					NodeShader.write(frag, 'vec3 indirect = albedo * (shIrradiance(vec3(n.x * envmapData.z - n.y * envmapData.y, n.x * envmapData.y + n.y * envmapData.z, n.z), shirr) / 3.14159265);');
 					NodeShader.write(frag, 'indirect += prefilteredColor * (f0 * envBRDF.x + envBRDF.y) * 1.5;');
 					NodeShader.write(frag, 'indirect *= envmapData.w * occlusion;');

+ 5 - 5
armorsculpt/Sources/MakeMeshPreview.ts

@@ -26,7 +26,7 @@ class MakeMeshPreview {
 			pos = "spos";
 			NodeShadercontext_add_elem(con_mesh, "bone", 'short4norm');
 			NodeShadercontext_add_elem(con_mesh, "weight", 'short4norm');
-			NodeShader.add_function(vert, ShaderFunctions.str_getSkinningDualQuat);
+			NodeShader.add_function(vert, str_getSkinningDualQuat);
 			NodeShader.add_uniform(vert, 'vec4 skinBones[128 * 2]', '_skin_bones');
 			NodeShader.add_uniform(vert, 'float posUnpack', '_pos_unpack');
 			NodeShader.write_attrib(vert, 'vec4 skinA;');
@@ -52,7 +52,7 @@ class MakeMeshPreview {
 		ParserMaterial.sample_uv_scale = brushScale;
 		ParserMaterial.parse_height = MakeMaterial.heightUsed;
 		ParserMaterial.parse_height_as_channel = true;
-		// let sout = ParserMaterial.parse(UINodes.getCanvasMaterial(), con_mesh, vert, frag, matcon);
+		// let sout = ParserMaterial.parse(ui_nodes_getCanvasMaterial(), con_mesh, vert, frag, matcon);
 		ParserMaterial.parse_height = false;
 		ParserMaterial.parse_height_as_channel = false;
 		ParserMaterial.sample_keep_aspect = false;
@@ -95,9 +95,9 @@ class MakeMeshPreview {
 		NodeShader.add_out(frag, 'vec4 fragColor[3]');
 		frag.n = true;
 
-		NodeShader.add_function(frag, ShaderFunctions.str_packFloatInt16);
-		NodeShader.add_function(frag, ShaderFunctions.str_cotangentFrame);
-		NodeShader.add_function(frag, ShaderFunctions.str_octahedronWrap);
+		NodeShader.add_function(frag, str_packFloatInt16);
+		NodeShader.add_function(frag, str_cotangentFrame);
+		NodeShader.add_function(frag, str_octahedronWrap);
 
 		if (MakeMaterial.heightUsed) {
 			NodeShader.write(frag, 'if (height > 0.0) {');

+ 1 - 1
armorsculpt/Sources/MakeSculpt.ts

@@ -69,7 +69,7 @@ class MakeSculpt {
 
 		NodeShader.write(frag, 'if (sample_undo.r == 0 && sample_undo.g == 0 && sample_undo.b == 0) discard;');
 
-		NodeShader.add_function(frag, ShaderFunctions.str_octahedronWrap);
+		NodeShader.add_function(frag, str_octahedronWrap);
 		NodeShader.add_uniform(frag, 'sampler2D gbuffer0_undo');
 		NodeShader.write(frag, 'vec2 g0_undo = textureLod(gbuffer0_undo, inp.xy, 0.0).rg;');
 		NodeShader.write(frag, 'vec3 wn;');

+ 21 - 21
armorsculpt/Sources/TabLayers.ts

@@ -6,16 +6,16 @@ class TabLayers {
 	static showContextMenu = false;
 
 	static draw = (htab: zui_handle_t) => {
-		let mini = config_config_raw.layout[layout_size_t.SIDEBAR_W] <= UIBase.sidebar_mini_w;
+		let mini = config_config_raw.layout[layout_size_t.SIDEBAR_W] <= ui_base_ui_base_sidebar_mini_w;
 		mini ? TabLayers.draw_mini(htab) : TabLayers.draw_full(htab);
 	}
 
 	static drawMini = (htab: zui_handle_t) => {
-		let ui = UIBase.ui;
+		let ui = ui_base_ui_base_ui;
 		zui_set_hovered_tab_name(tr("Layers"));
 
 		let _ELEMENT_H = ui.t.ELEMENT_H;
-		ui.t.ELEMENT_H = Math.floor(UIBase.sidebar_mini_w / 2 / zui_SCALE(ui));
+		ui.t.ELEMENT_H = math_floor(ui_base_ui_base_sidebar_mini_w / 2 / zui_SCALE(ui));
 
 		zui_begin_sticky();
 		zui_separator(5);
@@ -33,7 +33,7 @@ class TabLayers {
 	}
 
 	static drawFull = (htab: zui_handle_t) => {
-		let ui = UIBase.ui;
+		let ui = ui_base_ui_base_ui;
 		if (zui_tab(htab, tr("Layers"))) {
 			zui_begin_sticky();
 			zui_row([1 / 4, 3 / 4]);
@@ -59,10 +59,10 @@ class TabLayers {
 	}
 
 	static highlightOddLines = () => {
-		let ui = UIBase.ui;
+		let ui = ui_base_ui_base_ui;
 		let step = ui.t.ELEMENT_H * 2;
-		let fullH = ui._window_h - UIBase.hwnds[0].scroll_offset;
-		for (let i = 0; i < Math.floor(fullH / step); ++i) {
+		let fullH = ui._window_h - ui_base_ui_base_hwnds[0].scroll_offset;
+		for (let i = 0; i < math_floor(fullH / step); ++i) {
 			if (i % 2 == 0) {
 				zui_fill(0, i * step, (ui._w / zui_SCALE(ui) - 2), step, ui.t.WINDOW_BG_COL - 0x00040404);
 			}
@@ -70,11 +70,11 @@ class TabLayers {
 	}
 
 	static buttonNew = (text: string) => {
-		let ui = UIBase.ui;
+		let ui = ui_base_ui_base_ui;
 		if (zui_button(text)) {
-			UIMenu.draw((ui: zui_t) => {
+			ui_menu_draw((ui: zui_t) => {
 				let l = context_context_raw.layer;
-				if (UIMenu.menu_button(ui, tr("Paint Layer"))) {
+				if (ui_menu_button(ui, tr("Paint Layer"))) {
 					base_base_new_layer();
 					history_new_layer();
 				}
@@ -83,14 +83,14 @@ class TabLayers {
 	}
 
 	static comboFilter = () => {
-		let ui = UIBase.ui;
+		let ui = ui_base_ui_base_ui;
 		let ar = [tr("All")];
 		let filterHandle = zui_handle("tablayers_0");
 		filterHandle.position = context_context_raw.layer_filter;
 		context_context_raw.layer_filter = zui_combo(filterHandle, ar, tr("Filter"), false, zui_align_t.LEFT);
 	}
 
-	static remapLayerPointers = (nodes: zui_node_t[], pointerMap: Map<i32, i32>) => {
+	static remapLayerPointers = (nodes: zui_node_t[], pointerMap: map_t<i32, i32>) => {
 		for (let n of nodes) {
 			if (n.type == "LAYER" || n.type == "LAYER_MASK") {
 				let i = n.buttons[0].default_value;
@@ -101,14 +101,14 @@ class TabLayers {
 		}
 	}
 
-	static initLayerMap = (): Map<SlotLayerRaw, i32> => {
-		let res: Map<SlotLayerRaw, i32> = new Map();
+	static initLayerMap = (): map_t<SlotLayerRaw, i32> => {
+		let res: map_t<SlotLayerRaw, i32> = map_create();
 		for (let i = 0; i < project_project_layers.length; ++i) res.set(project_project_layers[i], i);
 		return res;
 	}
 
-	static fillLayerMap = (map: Map<SlotLayerRaw, i32>): Map<i32, i32> => {
-		let res: Map<i32, i32> = new Map();
+	static fillLayerMap = (map: map_t<SlotLayerRaw, i32>): map_t<i32, i32> => {
+		let res: map_t<i32, i32> = map_create();
 		for (let l of map.keys()) res.set(map.get(l), project_project_layers.indexOf(l) > -1 ? project_project_layers.indexOf(l) : 9999);
 		return res;
 	}
@@ -121,7 +121,7 @@ class TabLayers {
 	}
 
 	static drawLayerSlot = (l: SlotLayerRaw, i: i32, mini: bool) => {
-		let ui = UIBase.ui;
+		let ui = ui_base_ui_base_ui;
 
 		if (context_context_raw.layer_filter > 0 &&
 			SlotLayer.get_object_mask(l) > 0 &&
@@ -186,7 +186,7 @@ class TabLayers {
 	}
 
 	static drawLayerSlotMini = (l: SlotLayerRaw, i: i32) => {
-		let ui = UIBase.ui;
+		let ui = ui_base_ui_base_ui;
 
 		zui_row([1, 1]);
 		let uix = ui._x;
@@ -199,7 +199,7 @@ class TabLayers {
 	}
 
 	static drawLayerSlotFull = (l: SlotLayerRaw, i: i32) => {
-		let ui = UIBase.ui;
+		let ui = ui_base_ui_base_ui;
 
 		let step = ui.t.ELEMENT_H;
 
@@ -345,12 +345,12 @@ class TabLayers {
 
 	static layerToggleVisible = (l: SlotLayerRaw) => {
 		l.visible = !l.visible;
-		UIView2D.hwnd.redraws = 2;
+		ui_view2d_ui_view2d_hwnd.redraws = 2;
 		MakeMaterial.parse_mesh_material();
 	}
 
 	static drawLayerHighlight = (l: SlotLayerRaw, mini: bool) => {
-		let ui = UIBase.ui;
+		let ui = ui_base_ui_base_ui;
 		let step = ui.t.ELEMENT_H;
 
 		// Separator line

+ 2 - 2
armorsculpt/Sources/nodes/BrushOutputNode.ts

@@ -75,7 +75,7 @@ class BrushOutputNode extends LogicNode {
 		let right = 1.0;
 		if (context_raw.paint2d) {
 			left = 1.0;
-			right = (context_raw.splitView ? 2.0 : 1.0) + UIView2D.ww / base_w();
+			right = (context_raw.splitView ? 2.0 : 1.0) + ui_view2d_ww / base_w();
 		}
 
 		// First time init
@@ -98,7 +98,7 @@ class BrushOutputNode extends LogicNode {
 			!fillLayer &&
 			!groupLayer &&
 			(SlotLayer.isVisible(context_raw.layer) || context_raw.paint2d) &&
-			!UIBase.ui.is_hovered &&
+			!ui_base_ui.is_hovered &&
 			!base_isDragging &&
 			!base_isResizing &&
 			!base_isScrolling() &&

+ 28 - 28
base/Sources/BoxExport.ts

@@ -14,7 +14,7 @@ class BoxExport {
 
 	///if (is_paint || is_lab)
 	static show_textures = () => {
-		UIBox.show_custom((ui: zui_t) => {
+		ui_box_show_custom((ui: zui_t) => {
 
 			if (BoxExport.files == null) {
 				BoxExport.fetch_presets();
@@ -41,7 +41,7 @@ class BoxExport {
 
 	///if is_paint
 	static show_bake_material = () => {
-		UIBox.show_custom((ui: zui_t) => {
+		ui_box_show_custom((ui: zui_t) => {
 
 			if (BoxExport.files == null) {
 				BoxExport.fetch_presets();
@@ -130,10 +130,10 @@ class BoxExport {
 
 			zui_row([0.5, 0.5]);
 			if (zui_button(tr("Cancel"))) {
-				UIBox.hide();
+				ui_box_hide();
 			}
 			if (zui_button(tr("Export"))) {
-				UIBox.hide();
+				ui_box_hide();
 				if (context_raw.layers_destination == export_destination_t.PACKED) {
 					context_raw.texture_export_path = "/";
 					let _init = () => {
@@ -148,7 +148,7 @@ class BoxExport {
 				}
 				else {
 					let filters = base_bits_handle.position != texture_bits_t.BITS8 ? "exr" : context_raw.format_type == texture_ldr_format_t.PNG ? "png" : "jpg";
-					UIFiles.show(filters, true, false, (path: string) => {
+					ui_files_show(filters, true, false, (path: string) => {
 						context_raw.texture_export_path = path;
 						let doExport = () => {
 							let _init = () => {
@@ -185,7 +185,7 @@ class BoxExport {
 			if (BoxExport.hpreset.changed) BoxExport.preset = null;
 
 			if (zui_button(tr("New"))) {
-				UIBox.show_custom((ui: zui_t) => {
+				ui_box_show_custom((ui: zui_t) => {
 					let tab_vertical: bool = config_raw.touch_ui;
 					if (zui_tab(zui_handle("boxexport_5"), tr("New Preset"), tab_vertical)) {
 						zui_row([0.5, 0.5]);
@@ -195,7 +195,7 @@ class BoxExport {
 							BoxExport.fetch_presets();
 							BoxExport.preset = null;
 							BoxExport.hpreset.position = BoxExport.files.indexOf(preset_name);
-							UIBox.hide();
+							ui_box_hide();
 							BoxExport.htab.position = 1; // Presets
 							BoxExport.show_textures();
 						}
@@ -204,7 +204,7 @@ class BoxExport {
 			}
 
 			if (zui_button(tr("Import"))) {
-				UIFiles.show("json", false, false, (path: string) => {
+				ui_files_show("json", false, false, (path: string) => {
 					path = path.toLowerCase();
 					if (path.endsWith(".json")) {
 						let filename: string = path.substr(path.lastIndexOf(path_sep) + 1);
@@ -242,8 +242,8 @@ class BoxExport {
 				t.name = zui_text_input(htex);
 
 				if (ui.is_hovered && ui.input_released_r) {
-					UIMenu.draw((ui: zui_t) => {
-						if (UIMenu.menu_button(ui, tr("Delete"))) {
+					ui_menu_draw((ui: zui_t) => {
+						if (ui_menu_button(ui, tr("Delete"))) {
 							array_remove(BoxExport.preset.textures, t);
 							BoxExport.save_preset();
 						}
@@ -313,7 +313,7 @@ class BoxExport {
 
 	static show_mesh = () => {
 		BoxExport.export_mesh_handle.position = context_raw.export_mesh_index;
-		UIBox.show_custom((ui: zui_t) => {
+		ui_box_show_custom((ui: zui_t) => {
 			let htab: zui_handle_t = zui_handle("boxexport_8");
 			BoxExport.tab_export_mesh(ui, htab);
 		});
@@ -338,22 +338,22 @@ class BoxExport {
 			let paint_objects: mesh_object_t[] = pos == 0 ? project_paint_objects : [project_paint_objects[pos - 1]];
 			for (let po of paint_objects) {
 				for (let inda of po.data.index_arrays) {
-					tris += Math.floor(inda.values.length / 3);
+					tris += math_floor(inda.values.length / 3);
 				}
 			}
 			zui_text(tris + " " + tr("triangles"));
 
 			zui_row([0.5, 0.5]);
 			if (zui_button(tr("Cancel"))) {
-				UIBox.hide();
+				ui_box_hide();
 			}
 			if (zui_button(tr("Export"))) {
-				UIBox.hide();
-				UIFiles.show(context_raw.export_mesh_format == mesh_format_t.OBJ ? "obj" : "arm", true, false, (path: string) => {
+				ui_box_hide();
+				ui_files_show(context_raw.export_mesh_format == mesh_format_t.OBJ ? "obj" : "arm", true, false, (path: string) => {
 					///if (krom_android || krom_ios)
 					let f: string = sys_title();
 					///else
-					let f: string = UIFiles.filename;
+					let f: string = ui_files_filename;
 					///end
 					if (f == "") f = tr("untitled");
 					let doExport = () => {
@@ -374,7 +374,7 @@ class BoxExport {
 
 	///if (is_paint || is_sculpt)
 	static show_material = () => {
-		UIBox.show_custom((ui: zui_t) => {
+		ui_box_show_custom((ui: zui_t) => {
 			let htab: zui_handle_t = zui_handle("boxexport_11");
 			let tab_vertical: bool = config_raw.touch_ui;
 			if (zui_tab(htab, tr("Export Material"), tab_vertical)) {
@@ -386,12 +386,12 @@ class BoxExport {
 				context_raw.write_icon_on_export = zui_check(h2, tr("Export Icon"));
 				zui_row([0.5, 0.5]);
 				if (zui_button(tr("Cancel"))) {
-					UIBox.hide();
+					ui_box_hide();
 				}
 				if (zui_button(tr("Export"))) {
-					UIBox.hide();
-					UIFiles.show("arm", true, false, (path: string) => {
-						let f: string = UIFiles.filename;
+					ui_box_hide();
+					ui_files_show("arm", true, false, (path: string) => {
+						let f: string = ui_files_filename;
 						if (f == "") f = tr("untitled");
 						app_notify_on_init(() => {
 							ExportArm.run_material(path + path_sep + f);
@@ -403,7 +403,7 @@ class BoxExport {
 	}
 
 	static show_brush = () => {
-		UIBox.show_custom((ui: zui_t) => {
+		ui_box_show_custom((ui: zui_t) => {
 			let htab: zui_handle_t = zui_handle("boxexport_14");
 			let tab_vertical: bool = config_raw.touch_ui;
 			if (zui_tab(htab, tr("Export Brush"), tab_vertical)) {
@@ -415,12 +415,12 @@ class BoxExport {
 				context_raw.write_icon_on_export = zui_check(h2, tr("Export Icon"));
 				zui_row([0.5, 0.5]);
 				if (zui_button(tr("Cancel"))) {
-					UIBox.hide();
+					ui_box_hide();
 				}
 				if (zui_button(tr("Export"))) {
-					UIBox.hide();
-					UIFiles.show("arm", true, false, (path: string) => {
-						let f: string = UIFiles.filename;
+					ui_box_hide();
+					ui_files_show("arm", true, false, (path: string) => {
+						let f: string = ui_files_filename;
 						if (f == "") f = tr("untitled");
 						app_notify_on_init(() => {
 							ExportArm.run_brush(path + path_sep + f);
@@ -443,7 +443,7 @@ class BoxExport {
 	static parse_preset = () => {
 		let file: string = "export_presets/" + BoxExport.files[BoxExport.hpreset.position] + ".json";
 		let blob: ArrayBuffer = data_get_blob(file);
-		BoxExport.preset = JSON.parse(sys_buffer_to_string(blob));
+		BoxExport.preset = json_parse(sys_buffer_to_string(blob));
 		data_delete_blob("export_presets/" + file);
 	}
 
@@ -464,7 +464,7 @@ class BoxExport {
 		let name: string = BoxExport.files[BoxExport.hpreset.position];
 		if (name == "generic") return; // generic is const
 		let path: string = path_data() + path_sep + "export_presets" + path_sep + name + ".json";
-		krom_file_save_bytes(path, sys_string_to_buffer(JSON.stringify(BoxExport.preset)));
+		krom_file_save_bytes(path, sys_string_to_buffer(json_stringify(BoxExport.preset)));
 	}
 	///end
 }

+ 56 - 56
base/Sources/BoxPreferences.ts

@@ -12,7 +12,7 @@ class BoxPreferences {
 
 	static show = () => {
 
-		UIBox.show_custom((ui: zui_t) => {
+		ui_box_show_custom((ui: zui_t) => {
 			if (zui_tab(BoxPreferences.htab, tr("Interface"), true)) {
 
 				if (BoxPreferences.locales == null) {
@@ -25,7 +25,7 @@ class BoxPreferences {
 					let locale_code: string = BoxPreferences.locales[locale_handle.position];
 					config_raw.locale = locale_code;
 					translator_load_translations(locale_code);
-					UIBase.tag_ui_redraw();
+					ui_base_tag_ui_redraw();
 				}
 
 				let hscale: zui_handle_t = zui_handle("boxpreferences_1", { value: config_raw.window_scale });
@@ -61,7 +61,7 @@ class BoxPreferences {
 				ui.changed = false;
 				config_raw.show_asset_names = zui_check(zui_handle("boxpreferences_8", { selected: config_raw.show_asset_names }), tr("Show Asset Names"));
 				if (ui.changed) {
-					UIBase.tag_ui_redraw();
+					ui_base_tag_ui_redraw();
 				}
 
 				///if !(krom_android || krom_ios)
@@ -73,7 +73,7 @@ class BoxPreferences {
 					zui_set_touch_tooltip(config_raw.touch_ui);
 					config_load_theme(config_raw.theme);
 					BoxPreferences.set_scale();
-					UIBase.tag_ui_redraw();
+					ui_base_tag_ui_redraw();
 				}
 				///end
 
@@ -84,9 +84,9 @@ class BoxPreferences {
 
 				zui_end_element();
 				zui_row([0.5, 0.5]);
-				if (zui_button(tr("Restore")) && !UIMenu.show) {
-					UIMenu.draw((ui: zui_t) => {
-						if (UIMenu.menu_button(ui, tr("Confirm"))) {
+				if (zui_button(tr("Restore")) && !ui_menu_show) {
+					ui_menu_draw((ui: zui_t) => {
+						if (ui_menu_button(ui, tr("Confirm"))) {
 							app_notify_on_init(() => {
 								ui.t.ELEMENT_H = base_default_element_h;
 								config_restore();
@@ -98,10 +98,10 @@ class BoxPreferences {
 								MakeMaterial.parse_paint_material();
 							});
 						}
-						if (UIMenu.menu_button(ui, tr("Import..."))) {
-							UIFiles.show("json", false, false, (path: string) => {
+						if (ui_menu_button(ui, tr("Import..."))) {
+							ui_files_show("json", false, false, (path: string) => {
 								let b: ArrayBuffer = data_get_blob(path);
-								let raw: config_t = JSON.parse(sys_buffer_to_string(b));
+								let raw: config_t = json_parse(sys_buffer_to_string(b));
 								app_notify_on_init(() => {
 									ui.t.ELEMENT_H = base_default_element_h;
 									config_import_from(raw);
@@ -113,9 +113,9 @@ class BoxPreferences {
 						}
 					}, 2);
 				}
-				if (zui_button(tr("Reset Layout")) && !UIMenu.show) {
-					UIMenu.draw((ui: zui_t) => {
-						if (UIMenu.menu_button(ui, tr("Confirm"))) {
+				if (zui_button(tr("Reset Layout")) && !ui_menu_show) {
+					ui_menu_draw((ui: zui_t) => {
+						if (ui_menu_button(ui, tr("Confirm"))) {
 							base_init_layout();
 							config_save();
 						}
@@ -140,19 +140,19 @@ class BoxPreferences {
 				}
 
 				if (zui_button(tr("New"))) {
-					UIBox.show_custom((ui: zui_t) => {
+					ui_box_show_custom((ui: zui_t) => {
 						if (zui_tab(zui_handle("boxpreferences_13"), tr("New Theme"))) {
 							zui_row([0.5, 0.5]);
 							let theme_name: string = zui_text_input(zui_handle("boxpreferences_14", { text: "new_theme" }), tr("Name"));
 							if (zui_button(tr("OK")) || ui.is_return_down) {
-								let template: string = JSON.stringify(base_theme);
+								let template: string = json_stringify(base_theme);
 								if (!theme_name.endsWith(".json")) theme_name += ".json";
 								let path: string = path_data() + path_sep + "themes" + path_sep + theme_name;
 								krom_file_save_bytes(path, sys_string_to_buffer(template));
 								BoxPreferences.fetch_themes(); // Refresh file list
 								config_raw.theme = theme_name;
 								BoxPreferences.theme_handle.position = BoxPreferences.get_theme_index();
-								UIBox.hide();
+								ui_box_hide();
 								BoxPreferences.htab.position = 1; // Themes
 								BoxPreferences.show();
 							}
@@ -161,16 +161,16 @@ class BoxPreferences {
 				}
 
 				if (zui_button(tr("Import"))) {
-					UIFiles.show("json", false, false, (path: string) => {
+					ui_files_show("json", false, false, (path: string) => {
 						ImportTheme.run(path);
 					});
 				}
 
 				if (zui_button(tr("Export"))) {
-					UIFiles.show("json", true, false, (path: string) => {
-						path += path_sep + UIFiles.filename;
+					ui_files_show("json", true, false, (path: string) => {
+						path += path_sep + ui_files_filename;
 						if (!path.endsWith(".json")) path += ".json";
-						krom_file_save_bytes(path, sys_string_to_buffer(JSON.stringify(base_theme)));
+						krom_file_save_bytes(path, sys_string_to_buffer(json_stringify(base_theme)));
 					});
 				}
 
@@ -185,10 +185,10 @@ class BoxPreferences {
 				zui_row([1 / 8, 7 / 8]);
 				zui_text("", 0, h.color);
 				if (ui.is_hovered && ui.input_released) {
-					UIMenu.draw((ui) => {
+					ui_menu_draw((ui) => {
 						ui.changed = false;
 						zui_color_wheel(h, false, null, 11 * ui.t.ELEMENT_H * zui_SCALE(ui), true);
-						if (ui.changed) UIMenu.keep_open = true;
+						if (ui.changed) ui_menu_keep_open = true;
 					}, 11);
 				}
 				let val: i32 = h.color;
@@ -226,11 +226,11 @@ class BoxPreferences {
 						zui_text("", 0, val);
 						if (ui.is_hovered && ui.input_released) {
 							h.color = theme[key];
-							UIMenu.draw((ui) => {
+							ui_menu_draw((ui) => {
 								ui.changed = false;
 								let color: i32 = zui_color_wheel(h, false, null, 11 * ui.t.ELEMENT_H * zui_SCALE(ui), true);
 								theme[key] = color;
-								if (ui.changed) UIMenu.keep_open = true;
+								if (ui.changed) ui_menu_keep_open = true;
 							}, 11);
 						}
 					}
@@ -265,9 +265,9 @@ class BoxPreferences {
 
 			if (zui_tab(BoxPreferences.htab, tr("Usage"), true)) {
 				context_raw.undo_handle = zui_handle("boxpreferences_16", { value: config_raw.undo_steps });
-				config_raw.undo_steps = Math.floor(zui_slider(context_raw.undo_handle, tr("Undo Steps"), 1, 64, false, 1));
+				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);
+					config_raw.undo_steps = math_floor(context_raw.undo_handle.value = 1);
 				}
 				if (context_raw.undo_handle.changed) {
 					let current: image_t = _g2_current;
@@ -289,7 +289,7 @@ class BoxPreferences {
 				}
 
 				///if is_paint
-				config_raw.dilate_radius = Math.floor(zui_slider(zui_handle("boxpreferences_17", { value: config_raw.dilate_radius }), tr("Dilate Radius"), 0.0, 16.0, true, 1));
+				config_raw.dilate_radius = math_floor(zui_slider(zui_handle("boxpreferences_17", { value: config_raw.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("boxpreferences_18", { position: config_raw.dilate });
@@ -474,8 +474,8 @@ class BoxPreferences {
 				let cam_raw: camera_data_t = cam.data;
 				let near_handle: zui_handle_t = zui_handle("boxpreferences_47");
 				let far_handle: zui_handle_t = zui_handle("boxpreferences_48");
-				near_handle.value = Math.floor(cam_raw.near_plane * 1000) / 1000;
-				far_handle.value = Math.floor(cam_raw.far_plane * 100) / 100;
+				near_handle.value = math_floor(cam_raw.near_plane * 1000) / 1000;
+				far_handle.value = math_floor(cam_raw.far_plane * 100) / 100;
 				cam_raw.near_plane = zui_slider(near_handle, tr("Clip Start"), 0.001, 1.0, true);
 				cam_raw.far_plane = zui_slider(far_handle, tr("Clip End"), 50.0, 100.0, true);
 				if (near_handle.changed || far_handle.changed) {
@@ -507,19 +507,19 @@ class BoxPreferences {
 				}
 
 				if (zui_button(tr("New"))) {
-					UIBox.show_custom((ui: zui_t) => {
+					ui_box_show_custom((ui: zui_t) => {
 						if (zui_tab(zui_handle("boxpreferences_51"), tr("New Keymap"))) {
 							zui_row([0.5, 0.5]);
 							let keymap_name: string = zui_text_input(zui_handle("boxpreferences_52", { text: "new_keymap" }), tr("Name"));
 							if (zui_button(tr("OK")) || ui.is_return_down) {
-								let template: string = JSON.stringify(base_default_keymap);
+								let template: string = json_stringify(base_default_keymap);
 								if (!keymap_name.endsWith(".json")) keymap_name += ".json";
 								let path: string = path_data() + path_sep + "keymap_presets" + path_sep + keymap_name;
 								krom_file_save_bytes(path, sys_string_to_buffer(template));
 								BoxPreferences.fetch_keymaps(); // Refresh file list
 								config_raw.keymap = keymap_name;
 								BoxPreferences.preset_handle.position = BoxPreferences.get_preset_index();
-								UIBox.hide();
+								ui_box_hide();
 								BoxPreferences.htab.position = 5; // Keymap
 								BoxPreferences.show();
 							}
@@ -528,15 +528,15 @@ class BoxPreferences {
 				}
 
 				if (zui_button(tr("Import"))) {
-					UIFiles.show("json", false, false, (path: string) => {
+					ui_files_show("json", false, false, (path: string) => {
 						ImportKeymap.run(path);
 					});
 				}
 				if (zui_button(tr("Export"))) {
-					UIFiles.show("json", true, false, (dest: string) => {
-						if (!UIFiles.filename.endsWith(".json")) UIFiles.filename += ".json";
+					ui_files_show("json", true, false, (dest: string) => {
+						if (!ui_files_filename.endsWith(".json")) ui_files_filename += ".json";
 						let path: string = path_data() + path_sep + "keymap_presets" + path_sep + config_raw.keymap;
-						file_copy(path, dest + path_sep + UIFiles.filename);
+						file_copy(path, dest + path_sep + ui_files_filename);
 					});
 				}
 
@@ -561,7 +561,7 @@ class BoxPreferences {
 				zui_begin_sticky();
 				zui_row([1 / 4, 1 / 4]);
 				if (zui_button(tr("New"))) {
-					UIBox.show_custom((ui: zui_t) => {
+					ui_box_show_custom((ui: zui_t) => {
 						if (zui_tab(zui_handle("boxpreferences_54"), tr("New Plugin"))) {
 							zui_row([0.5, 0.5]);
 							let plugin_name: string = zui_text_input(zui_handle("boxpreferences_55", { text: "new_plugin" }), tr("Name"));
@@ -581,7 +581,7 @@ plugin.drawUI = (ui) { =>
 								let path: string = path_data() + path_sep + "plugins" + path_sep + plugin_name;
 								krom_file_save_bytes(path, sys_string_to_buffer(template));
 								BoxPreferences.files_plugin = null; // Refresh file list
-								UIBox.hide();
+								ui_box_hide();
 								BoxPreferences.htab.position = 6; // Plugins
 								BoxPreferences.show();
 							}
@@ -589,7 +589,7 @@ plugin.drawUI = (ui) { =>
 					});
 				}
 				if (zui_button(tr("Import"))) {
-					UIFiles.show("js,zip", false, false, (path: string) => {
+					ui_files_show("js,zip", false, false, (path: string) => {
 						ImportPlugin.run(path);
 					});
 				}
@@ -613,24 +613,24 @@ plugin.drawUI = (ui) { =>
 						base_redraw_ui();
 					}
 					if (ui.is_hovered && ui.input_released_r) {
-						UIMenu.draw((ui: zui_t) => {
+						ui_menu_draw((ui: zui_t) => {
 							let path: string = path_data() + path_sep + "plugins" + path_sep + f;
-							if (UIMenu.menu_button(ui, tr("Edit in Text Editor"))) {
+							if (ui_menu_button(ui, tr("Edit in Text Editor"))) {
 								file_start(path);
 							}
-							if (UIMenu.menu_button(ui, tr("Edit in Script Tab"))) {
+							if (ui_menu_button(ui, tr("Edit in Script Tab"))) {
 								let blob: ArrayBuffer = data_get_blob("plugins/" + f);
 								TabScript.hscript.text = sys_buffer_to_string(blob);
 								data_delete_blob("plugins/" + f);
 								console_info(tr("Script opened"));
 							}
-							if (UIMenu.menu_button(ui, tr("Export"))) {
-								UIFiles.show("js", true, false, (dest: string) => {
-									if (!UIFiles.filename.endsWith(".js")) UIFiles.filename += ".js";
-									file_copy(path, dest + path_sep + UIFiles.filename);
+							if (ui_menu_button(ui, tr("Export"))) {
+								ui_files_show("js", true, false, (dest: string) => {
+									if (!ui_files_filename.endsWith(".js")) ui_files_filename += ".js";
+									file_copy(path, dest + path_sep + ui_files_filename);
 								});
 							}
-							if (UIMenu.menu_button(ui, tr("Delete"))) {
+							if (ui_menu_button(ui, tr("Delete"))) {
 								if (config_raw.plugins.indexOf(f) >= 0) {
 									array_remove(config_raw.plugins, f);
 									plugin_stop(f);
@@ -674,19 +674,19 @@ plugin.drawUI = (ui) { =>
 
 	static set_scale = () => {
 		let scale: f32 = config_raw.window_scale;
-		zui_set_scale(UIBase.ui, scale);
-		UIHeader.headerh = Math.floor(UIHeader.default_header_h * scale);
-		config_raw.layout[layout_size_t.STATUS_H] = Math.floor(UIStatus.default_status_h * scale);
-		UIMenubar.menubarw = Math.floor(UIMenubar.default_menubar_w * scale);
-		UIBase.set_icon_scale();
-		zui_set_scale(UINodes.ui, scale);
-		zui_set_scale(UIView2D.ui, scale);
+		zui_set_scale(ui_base_ui, scale);
+		ui_header_h = math_floor(ui_header_default_h * scale);
+		config_raw.layout[layout_size_t.STATUS_H] = math_floor(ui_status_default_status_h * scale);
+		ui_menubar_w = math_floor(ui_menubar_default_w * scale);
+		ui_base_set_icon_scale();
+		zui_set_scale(ui_nodes_ui, scale);
+		zui_set_scale(ui_view2d_ui, scale);
 		zui_set_scale(base_ui_box, scale);
 		zui_set_scale(base_ui_menu, scale);
 		base_resize();
 		///if (is_paint || is_sculpt)
-		config_raw.layout[layout_size_t.SIDEBAR_W] = Math.floor(UIBase.default_sidebar_w * scale);
-		UIToolbar.toolbar_w = Math.floor(UIToolbar.default_toolbar_w * scale);
+		config_raw.layout[layout_size_t.SIDEBAR_W] = math_floor(ui_base_default_sidebar_w * scale);
+		ui_toolbar_w = math_floor(ui_toolbar_default_w * scale);
 		///end
 	}
 }

+ 20 - 19
base/Sources/BoxProjects.ts

@@ -3,7 +3,7 @@ class BoxProjects {
 
 	static htab: zui_handle_t = zui_handle_create();
 	static hsearch: zui_handle_t = zui_handle_create();
-	static icon_map: Map<string, image_t> = null;
+	static icon_map: map_t<string, image_t> = null;
 
 	static show = () => {
 		if (BoxProjects.icon_map != null) {
@@ -20,7 +20,7 @@ class BoxProjects {
 		draggable = true;
 		///end
 
-		UIBox.show_custom((ui: zui_t) => {
+		ui_box_show_custom((ui: zui_t) => {
 			///if (krom_android || krom_ios)
 			BoxProjects.align_to_fullscreen();
 			///end
@@ -44,7 +44,7 @@ class BoxProjects {
 			if (zui_button(tr("New"))) {
 				project_new();
 				viewport_scale_to_bounds();
-				UIBox.hide();
+				ui_box_hide();
 				// Pick unique name
 				let i: i32 = 0;
 				let j: i32 = 0;
@@ -64,12 +64,12 @@ class BoxProjects {
 			zui_end_sticky();
 			zui_separator(3, false);
 
-			let slotw: i32 = Math.floor(150 * zui_SCALE(ui));
-			let num: i32 = Math.floor(sys_width() / slotw);
+			let slotw: i32 = math_floor(150 * zui_SCALE(ui));
+			let num: i32 = math_floor(sys_width() / slotw);
 			let recent_projects: string[] = config_raw.recent_projects;
 			let show_asset_names: bool = true;
 
-			for (let row: i32 = 0; row < Math.ceil(recent_projects.length / num); ++row) {
+			for (let row: i32 = 0; row < math_ceil(recent_projects.length / num); ++row) {
 				let mult = show_asset_names ? 2 : 1;
 				let ar: f32[] = [];
 				for (let i: i32 = 0; i < num * mult; ++i) ar.push(1 / num);
@@ -80,7 +80,7 @@ class BoxProjects {
 				if (row > 0) ui._y += off;
 
 				for (let j: i32 = 0; j < num; ++j) {
-					let imgw: i32 = Math.floor(128 * zui_SCALE(ui));
+					let imgw: i32 = math_floor(128 * zui_SCALE(ui));
 					let i: i32 = j + row * num;
 					if (i >= recent_projects.length) {
 						zui_end_element(imgw);
@@ -97,7 +97,7 @@ class BoxProjects {
 					///end
 
 					let icon_path: string = path.substr(0, path.length - 4) + "_icon.png";
-					if (BoxProjects.icon_map == null) BoxProjects.icon_map = new Map();
+					if (BoxProjects.icon_map == null) BoxProjects.icon_map = map_create();
 					let icon: image_t = BoxProjects.icon_map.get(icon_path);
 					if (icon == null) {
 						let image: image_t = data_get_image(icon_path);
@@ -117,7 +117,7 @@ class BoxProjects {
 							ui._x = _uix;
 							let doImport = () => {
 								app_notify_on_init(() => {
-									UIBox.hide();
+									ui_box_hide();
 									ImportArm.run_project(path);
 								});
 							}
@@ -134,9 +134,9 @@ class BoxProjects {
 
 						let name: string = path.substring(path.lastIndexOf(path_sep) + 1, path.lastIndexOf("."));
 						if (ui.is_hovered && ui.input_released_r) {
-							UIMenu.draw((ui: zui_t) => {
-								// if (UIMenu.menuButton(ui, tr("Duplicate"))) {}
-								if (UIMenu.menu_button(ui, tr("Delete"))) {
+							ui_menu_draw((ui: zui_t) => {
+								// if (menuButton(ui, tr("Duplicate"))) {}
+								if (ui_menu_button(ui, tr("Delete"))) {
 									app_notify_on_init(() => {
 										file_delete(path);
 										file_delete(icon_path);
@@ -193,12 +193,13 @@ class BoxProjects {
 
 				if (zui_button(file, zui_align_t.LEFT) && file_exists(path)) {
 					let current: image_t = _g2_current;
-					if (current != null) g2_end();
+					let g2_in_use: bool = _g2_in_use;
+					if (g2_in_use) g2_end();
 
 					ImportArm.run_project(path);
 
-					if (current != null) g2_begin(current);
-					UIBox.hide();
+					if (g2_in_use) g2_begin(current);
+					ui_box_hide();
 				}
 				if (ui.is_hovered) zui_tooltip(path);
 			}
@@ -237,13 +238,13 @@ class BoxProjects {
 	}
 
 	static align_to_fullscreen = () => {
-		UIBox.modalw = Math.floor(sys_width() / zui_SCALE(base_ui_box));
-		UIBox.modalh = Math.floor(sys_height() / zui_SCALE(base_ui_box));
+		ui_box_modalw = math_floor(sys_width() / zui_SCALE(base_ui_box));
+		ui_box_modalh = math_floor(sys_height() / zui_SCALE(base_ui_box));
 		let appw: i32 = sys_width();
 		let apph: i32 = sys_height();
 		let mw: i32 = appw;
 		let mh: i32 = apph;
-		UIBox.hwnd.drag_x = Math.floor(-appw / 2 + mw / 2);
-		UIBox.hwnd.drag_y = Math.floor(-apph / 2 + mh / 2);
+		ui_box_hwnd.drag_x = math_floor(-appw / 2 + mw / 2);
+		ui_box_hwnd.drag_y = math_floor(-apph / 2 + mh / 2);
 	}
 }

+ 1 - 1
base/Sources/ContextFormat.ts

@@ -127,7 +127,7 @@ class context_t {
 	layers_preview_dirty?: bool = false;
 	node_preview_dirty?: bool = false;
 	node_preview?: image_t = null;
-	node_previews?: Map<string, image_t> = null;
+	node_previews?: map_t<string, image_t> = null;
 	node_previews_used?: string[] = null;
 	node_preview_name?: string = "";
 	mask_preview_rgba32?: image_t = null;

+ 9 - 9
base/Sources/ExportArm.ts

@@ -14,7 +14,7 @@ class ExportArm {
 		///if (is_paint || is_sculpt)
 		let mnodes: zui_node_canvas_t[] = [];
 		for (let m of project_materials) {
-			let c: zui_node_canvas_t = JSON.parse(JSON.stringify(m.canvas));
+			let c: zui_node_canvas_t = json_parse(json_stringify(m.canvas));
 			for (let n of c.nodes) ExportArm.export_node(n);
 			mnodes.push(c);
 		}
@@ -24,7 +24,7 @@ class ExportArm {
 		///end
 
 		///if is_lab
-		let c: zui_node_canvas_t = JSON.parse(JSON.stringify(project_canvas));
+		let c: zui_node_canvas_t = json_parse(json_stringify(project_canvas));
 		for (let n of c.nodes) ExportArm.export_node(n);
 		///end
 
@@ -32,7 +32,7 @@ class ExportArm {
 		if (project_material_groups.length > 0) {
 			mgroups = [];
 			for (let g of project_material_groups) {
-				let c: zui_node_canvas_t = JSON.parse(JSON.stringify(g.canvas));
+				let c: zui_node_canvas_t = json_parse(json_stringify(g.canvas));
 				for (let n of c.nodes) ExportArm.export_node(n);
 				mgroups.push(c);
 			}
@@ -156,7 +156,7 @@ class ExportArm {
 		let mesh_icon_pixels: buffer_t = image_get_pixels(mesh_icon);
 		let u8a: Uint8Array = new Uint8Array(mesh_icon_pixels);
 		for (let i: i32 = 0; i < 256 * 256 * 4; ++i) {
-			u8a[i] = Math.floor(Math.pow(u8a[i] / 255, 1.0 / 2.2) * 255);
+			u8a[i] = math_floor(math_pow(u8a[i] / 255, 1.0 / 2.2) * 255);
 		}
 		///if (krom_metal || krom_vulkan)
 		ExportArm.bgra_swap(mesh_icon_pixels);
@@ -229,11 +229,11 @@ class ExportArm {
 		let mnodes: zui_node_canvas_t[] = [];
 		let mgroups: zui_node_canvas_t[] = null;
 		let m: SlotMaterialRaw = context_raw.material;
-		let c: zui_node_canvas_t = JSON.parse(JSON.stringify(m.canvas));
+		let c: zui_node_canvas_t = json_parse(json_stringify(m.canvas));
 		let assets: asset_t[] = [];
-		if (UINodes.has_group(c)) {
+		if (ui_nodes_has_group(c)) {
 			mgroups = [];
-			UINodes.traverse_group(mgroups, c);
+			ui_nodes_traverse_group(mgroups, c);
 			for (let gc of mgroups) for (let n of gc.nodes) ExportArm.export_node(n, assets);
 		}
 		for (let n of c.nodes) ExportArm.export_node(n, assets);
@@ -280,7 +280,7 @@ class ExportArm {
 	///if (krom_metal || krom_vulkan)
 	static bgra_swap = (buffer: ArrayBuffer) => {
 		let view: DataView = new DataView(buffer);
-		for (let i: i32 = 0; i < Math.floor(buffer.byteLength / 4); ++i) {
+		for (let i: i32 = 0; i < math_floor(buffer.byteLength / 4); ++i) {
 			let r: i32 = view.getUint8(i * 4);
 			view.setUint8(i * 4, view.getUint8(i * 4 + 2));
 			view.setUint8(i * 4 + 2, r);
@@ -294,7 +294,7 @@ class ExportArm {
 		if (!path.endsWith(".arm")) path += ".arm";
 		let bnodes: zui_node_canvas_t[] = [];
 		let b: SlotBrushRaw = context_raw.brush;
-		let c: zui_node_canvas_t = JSON.parse(JSON.stringify(b.canvas));
+		let c: zui_node_canvas_t = json_parse(json_stringify(b.canvas));
 		let assets: asset_t[] = [];
 		for (let n of c.nodes) ExportArm.export_node(n, assets);
 		bnodes.push(c);

+ 10 - 10
base/Sources/ExportObj.ts

@@ -21,15 +21,15 @@ class ExportObj {
 			let posa: i16_array_t = mesh.vertex_arrays[0].values;
 			let nora: i16_array_t = mesh.vertex_arrays[1].values;
 			let texa: i16_array_t = mesh.vertex_arrays[2].values;
-			let len: i32 = Math.floor(posa.length / 4);
+			let len: i32 = math_floor(posa.length / 4);
 
 			// Merge shared vertices and remap indices
 			let posa2: Int16Array = new Int16Array(len * 3);
 			let nora2: Int16Array = new Int16Array(len * 3);
 			let texa2: Int16Array = new Int16Array(len * 2);
-			let posmap: Map<i32, i32> = new Map();
-			let normap: Map<i32, i32> = new Map();
-			let texmap: Map<i32, i32> = new Map();
+			let posmap: map_t<i32, i32> = map_create();
+			let normap: map_t<i32, i32> = map_create();
+			let texmap: map_t<i32, i32> = map_create();
 
 			let pi: i32 = 0;
 			let ni: i32 = 0;
@@ -93,12 +93,12 @@ class ExportObj {
 				// let res: i32 = layers[0].texpaint_pack.width;
 				// let strength: f32 = 0.1;
 				// for (let i: i32 = 0; i < len; ++i) {
-				// 	let x: i32 = Math.floor(texa2[i * 2    ] / 32767 * res);
-				// 	let y: i32 = Math.floor((1.0 - texa2[i * 2 + 1] / 32767) * res);
+				// 	let x: i32 = math_floor(texa2[i * 2    ] / 32767 * res);
+				// 	let y: i32 = math_floor((1.0 - texa2[i * 2 + 1] / 32767) * res);
 				// 	let h: f32 = (1.0 - height.get((y * res + x) * 4 + 3) / 255) * strength;
-				// 	posa2[i * 3    ] -= Math.floor(nora2[i * 3    ] * inv * h / sc);
-				// 	posa2[i * 3 + 1] -= Math.floor(nora2[i * 3 + 1] * inv * h / sc);
-				// 	posa2[i * 3 + 2] -= Math.floor(nora2[i * 3 + 2] * inv * h / sc);
+				// 	posa2[i * 3    ] -= math_floor(nora2[i * 3    ] * inv * h / sc);
+				// 	posa2[i * 3 + 1] -= math_floor(nora2[i * 3 + 1] * inv * h / sc);
+				// 	posa2[i * 3 + 2] -= math_floor(nora2[i * 3 + 2] * inv * h / sc);
 				// }
 			}
 
@@ -130,7 +130,7 @@ class ExportObj {
 			}
 
 			let inda: u32_array_t = mesh.index_arrays[0].values;
-			for (let i: i32 = 0; i < Math.floor(inda.length / 3); ++i) {
+			for (let i: i32 = 0; i < math_floor(inda.length / 3); ++i) {
 				let pi1: i32 = posmap.get(inda[i * 3    ]) + 1 + poff;
 				let pi2: i32 = posmap.get(inda[i * 3 + 1]) + 1 + poff;
 				let pi3: i32 = posmap.get(inda[i * 3 + 2]) + 1 + poff;

+ 10 - 10
base/Sources/ExportTexture.ts

@@ -81,7 +81,7 @@ class ExportTexture {
 		///else
 		console_info(tr("Textures exported"));
 		///end
-		UIFiles.last_path = "";
+		ui_files_last_path = "";
 	}
 
 	///if is_paint
@@ -124,7 +124,7 @@ class ExportTexture {
 		///if (krom_android || krom_ios)
 		let f: string = sys_title();
 		///else
-		let f: string = UIFiles.filename;
+		let f: string = ui_files_filename;
 		///end
 		if (f == "") f = tr("untitled");
 		let format_type: texture_ldr_format_t = context_raw.format_type;
@@ -316,7 +316,7 @@ class ExportTexture {
 				ExportTexture.write_texture(path + path_sep + f + tex_name + ext, pixpaint, 2, 3);
 			}
 			else {
-				if (pix == null) pix = new ArrayBuffer(texture_size_x * texture_size_y * 4 * Math.floor(bits / 8));
+				if (pix == null) pix = new ArrayBuffer(texture_size_x * texture_size_y * 4 * math_floor(bits / 8));
 				for (let i: i32 = 0; i < 4; ++i) {
 					let c: string = t.channels[i];
 					if      (c == "base_r") ExportTexture.copy_channel(new DataView(pixpaint), 0, new DataView(pix), i, t.color_space == "linear");
@@ -378,7 +378,7 @@ class ExportTexture {
 			krom_write_png(file, pixels, res_x, res_y, format);
 		}
 		else if (bits == 8 && context_raw.format_type == texture_ldr_format_t.JPG) {
-			krom_write_jpg(file, pixels, res_x, res_y, format, Math.floor(context_raw.format_quality));
+			krom_write_jpg(file, pixels, res_x, res_y, format, math_floor(context_raw.format_quality));
 		}
 		else { // Exr
 			let b: ArrayBuffer = ParserExr.run(res_x, res_y, pixels, bits, type, off);
@@ -387,36 +387,36 @@ class ExportTexture {
 	}
 
 	static copy_channel = (from: DataView, fromChannel: i32, to: DataView, toChannel: i32, linear: bool = true) => {
-		for (let i: i32 = 0; i < Math.floor(to.byteLength / 4); ++i) {
+		for (let i: i32 = 0; i < math_floor(to.byteLength / 4); ++i) {
 			to.setUint8(i * 4 + toChannel, from.getUint8(i * 4 + fromChannel));
 		}
 		if (!linear) ExportTexture.to_srgb(to, toChannel);
 	}
 
 	static copy_channel_inv = (from: DataView, fromChannel: i32, to: DataView, toChannel: i32, linear: bool = true) => {
-		for (let i: i32 = 0; i < Math.floor(to.byteLength / 4); ++i) {
+		for (let i: i32 = 0; i < math_floor(to.byteLength / 4); ++i) {
 			to.setUint8(i * 4 + toChannel, 255 - from.getUint8(i * 4 + fromChannel));
 		}
 		if (!linear) ExportTexture.to_srgb(to, toChannel);
 	}
 
 	static extract_channel = (from: DataView, fromChannel: i32, to: DataView, toChannel: i32, step: i32, mask: i32, linear: bool = true) => {
-		for (let i: i32 = 0; i < Math.floor(to.byteLength / 4); ++i) {
+		for (let i: i32 = 0; i < math_floor(to.byteLength / 4); ++i) {
 			to.setUint8(i * 4 + toChannel, from.getUint8(i * 4 + fromChannel) % step == mask ? 255 : 0);
 		}
 		if (!linear) ExportTexture.to_srgb(to, toChannel);
 	}
 
 	static set_channel = (value: i32, to: DataView, toChannel: i32, linear: bool = true) => {
-		for (let i: i32 = 0; i < Math.floor(to.byteLength / 4); ++i) {
+		for (let i: i32 = 0; i < math_floor(to.byteLength / 4); ++i) {
 			to.setUint8(i * 4 + toChannel, value);
 		}
 		if (!linear) ExportTexture.to_srgb(to, toChannel);
 	}
 
 	static to_srgb = (to: DataView, toChannel: i32) => {
-		for (let i: i32 = 0; i < Math.floor(to.byteLength / 4); ++i) {
-			to.setUint8(i * 4 + toChannel, Math.floor(Math.pow(to.getUint8(i * 4 + toChannel) / 255, ExportTexture.gamma) * 255));
+		for (let i: i32 = 0; i < math_floor(to.byteLength / 4); ++i) {
+			to.setUint8(i * 4 + toChannel, math_floor(math_pow(to.getUint8(i * 4 + toChannel) / 255, ExportTexture.gamma) * 255));
 		}
 	}
 }

+ 18 - 18
base/Sources/ImportArm.ts

@@ -33,11 +33,11 @@ class ImportArm {
 
 		project_new(import_as_mesh);
 		project_filepath = path;
-		UIFiles.filename = path.substring(path.lastIndexOf(path_sep) + 1, path.lastIndexOf("."));
+		ui_files_filename = path.substring(path.lastIndexOf(path_sep) + 1, path.lastIndexOf("."));
 		///if (krom_android || krom_ios)
-		sys_title_set(UIFiles.filename);
+		sys_title_set(ui_files_filename);
 		///else
-		sys_title_set(UIFiles.filename + " - " + manifest_title);
+		sys_title_set(ui_files_filename + " - " + manifest_title);
 		///end
 
 		///if (is_paint || is_sculpt)
@@ -66,7 +66,7 @@ class ImportArm {
 		base_res_handle.position = config_get_texture_res_pos(l0.res);
 		let bits_pos: texture_bits_t = l0.bpp == 8 ? texture_bits_t.BITS8 : l0.bpp == 16 ? texture_bits_t.BITS16 : texture_bits_t.BITS32;
 		base_bits_handle.position = bits_pos;
-		let bytes_per_pixel: i32 = Math.floor(l0.bpp / 8);
+		let bytes_per_pixel: i32 = math_floor(l0.bpp / 8);
 		let format: tex_format_t = l0.bpp == 8 ? tex_format_t.RGBA32 : l0.bpp == 16 ? tex_format_t.RGBA64 : tex_format_t.RGBA128;
 		///end
 
@@ -160,7 +160,7 @@ class ImportArm {
 		///end
 
 		// No mask by default
-		if (context_raw.merged_object == null) UtilMesh.merge_mesh();
+		if (context_raw.merged_object == null) util_mesh_merge();
 		///end
 
 		context_select_paint_object(context_main_object());
@@ -306,8 +306,8 @@ class ImportArm {
 		}
 		///end
 
-		UINodes.hwnd.redraws = 2;
-		UINodes.group_stack = [];
+		ui_nodes_hwnd.redraws = 2;
+		ui_nodes_group_stack = [];
 		project_material_groups = [];
 		if (project.material_groups != null) {
 			for (let g of project.material_groups) project_material_groups.push({ canvas: g, nodes: zui_nodes_create() });
@@ -317,7 +317,7 @@ class ImportArm {
 		for (let m of project_materials) {
 			context_raw.material = m;
 			MakeMaterial.parse_paint_material();
-			UtilRender.make_material_preview();
+			util_render_make_material_preview();
 		}
 
 		project_brushes = [];
@@ -326,7 +326,7 @@ class ImportArm {
 			context_raw.brush = SlotBrush.create(n);
 			project_brushes.push(context_raw.brush);
 			MakeMaterial.parse_brush();
-			UtilRender.make_brush_preview();
+			util_render_make_brush_preview();
 		}
 
 		// Fill layers
@@ -339,8 +339,8 @@ class ImportArm {
 			}
 		}
 
-		UIBase.hwnds[tab_area_t.SIDEBAR0].redraws = 2;
-		UIBase.hwnds[tab_area_t.SIDEBAR1].redraws = 2;
+		ui_base_hwnds[tab_area_t.SIDEBAR0].redraws = 2;
+		ui_base_hwnds[tab_area_t.SIDEBAR1].redraws = 2;
 		///end
 
 		///if is_lab
@@ -374,7 +374,7 @@ class ImportArm {
 			transform_build_matrix(object.base.transform);
 			object.base.name = md.name;
 			project_paint_objects.push(object);
-			UtilMesh.merge_mesh();
+			util_mesh_merge();
 			viewport_scale_to_bounds();
 		}
 		app_notify_on_init(base_init_layers);
@@ -432,13 +432,13 @@ class ImportArm {
 			for (let m of imported) {
 				context_set_material(m);
 				MakeMaterial.parse_paint_material();
-				UtilRender.make_material_preview();
+				util_render_make_material_preview();
 			}
 		}
 		app_notify_on_init(_init);
 
-		UINodes.group_stack = [];
-		UIBase.hwnds[tab_area_t.SIDEBAR1].redraws = 2;
+		ui_nodes_group_stack = [];
+		ui_base_hwnds[tab_area_t.SIDEBAR1].redraws = 2;
 		data_delete_blob(path);
 	}
 
@@ -502,12 +502,12 @@ class ImportArm {
 		let _init = () => {
 			for (let b of imported) {
 				context_set_brush(b);
-				UtilRender.make_brush_preview();
+				util_render_make_brush_preview();
 			}
 		}
 		app_notify_on_init(_init);
 
-		UIBase.hwnds[tab_area_t.SIDEBAR1].redraws = 2;
+		ui_base_hwnds[tab_area_t.SIDEBAR1].redraws = 2;
 		data_delete_blob(path);
 	}
 	///end
@@ -533,7 +533,7 @@ class ImportArm {
 				project_raw.swatches.push(s);
 			}
 		}
-		UIBase.hwnds[tab_area_t.STATUS].redraws = 2;
+		ui_base_hwnds[tab_area_t.STATUS].redraws = 2;
 		data_delete_blob(path);
 	}
 

+ 8 - 8
base/Sources/ImportAsset.ts

@@ -25,14 +25,14 @@ class ImportAsset {
 
 		if (path_is_mesh(path)) {
 			showBox ? project_import_mesh_box(path) : ImportMesh.run(path);
-			if (dropX > 0) UIBox.click_to_hide = false; // Prevent closing when going back to window after drag and drop
+			if (dropX > 0) ui_box_click_to_hide = false; // Prevent closing when going back to window after drag and drop
 		}
 		else if (path_is_texture(path)) {
 			ImportTexture.run(path, hdrAsEnvmap);
 			// Place image node
-			let x0: i32 = UINodes.wx;
-			let x1: i32 = UINodes.wx + UINodes.ww;
-			if (UINodes.show && dropX > x0 && dropX < x1) {
+			let x0: i32 = ui_nodes_wx;
+			let x1: i32 = ui_nodes_wx + ui_nodes_ww;
+			if (ui_nodes_show && dropX > x0 && dropX < x1) {
 				let asset_index: i32 = 0;
 				for (let i: i32 = 0; i < project_assets.length; ++i) {
 					if (project_assets[i].file == path) {
@@ -40,14 +40,14 @@ class ImportAsset {
 						break;
 					}
 				}
-				UINodes.accept_asset_drag(asset_index);
-				UINodes.get_nodes().nodesDrag = false;
-				UINodes.hwnd.redraws = 2;
+				ui_nodes_accept_asset_drag(asset_index);
+				ui_nodes_get_nodes().nodesDrag = false;
+				ui_nodes_hwnd.redraws = 2;
 			}
 
 			///if is_paint
 			if (context_raw.tool == workspace_tool_t.COLORID && project_asset_names.length == 1) {
-				UIHeader.header_handle.redraws = 2;
+				ui_header_handle.redraws = 2;
 				context_raw.ddirty = 2;
 			}
 			///end

+ 16 - 16
base/Sources/ImportBlendMaterial.ts

@@ -84,7 +84,7 @@ class ImportBlendMaterial {
 				}
 
 				if (base != null) {
-					let n: zui_node_t = UINodes.make_node(base, nodes, canvas);
+					let n: zui_node_t = ui_nodes_make_node(base, nodes, canvas);
 					n.x = BlHandle.get(node, "locx") + 400;
 					n.y = -BlHandle.get(node, "locy") + 400;
 					n.name = BlHandle.get(node, "name");
@@ -120,11 +120,11 @@ class ImportBlendMaterial {
 						for (let i: i32 = 0; i < BlHandle.get(ramp, "tot"); ++i) {
 							if (i >= elems.length) elems.push([1.0, 1.0, 1.0, 1.0, 0.0]);
 							let cbdata: any = BlHandle.get(ramp, "data", i, "CBData");
-							elems[i][0] = Math.floor(BlHandle.get(cbdata, "r") * 100) / 100;
-							elems[i][1] = Math.floor(BlHandle.get(cbdata, "g") * 100) / 100;
-							elems[i][2] = Math.floor(BlHandle.get(cbdata, "b") * 100) / 100;
-							elems[i][3] = Math.floor(BlHandle.get(cbdata, "a") * 100) / 100;
-							elems[i][4] = Math.floor(BlHandle.get(cbdata, "pos") * 100) / 100;
+							elems[i][0] = math_floor(BlHandle.get(cbdata, "r") * 100) / 100;
+							elems[i][1] = math_floor(BlHandle.get(cbdata, "g") * 100) / 100;
+							elems[i][2] = math_floor(BlHandle.get(cbdata, "b") * 100) / 100;
+							elems[i][3] = math_floor(BlHandle.get(cbdata, "a") * 100) / 100;
+							elems[i][4] = math_floor(BlHandle.get(cbdata, "pos") * 100) / 100;
 						}
 					}
 					else if (search == "mixrgb" || search == "math") {
@@ -247,12 +247,12 @@ class ImportBlendMaterial {
 			for (let m of imported) {
 				context_set_material(m);
 				MakeMaterial.parse_paint_material();
-				UtilRender.make_material_preview();
+				util_render_make_material_preview();
 			}
 		}
 		app_notify_on_init(_init);
 
-		UIBase.hwnds[tab_area_t.SIDEBAR1].redraws = 2;
+		ui_base_hwnds[tab_area_t.SIDEBAR1].redraws = 2;
 		data_delete_blob(path);
 	}
 
@@ -260,22 +260,22 @@ class ImportBlendMaterial {
 		let idname: any = BlHandle.get(sock, "idname");
 		if (idname.startsWith("NodeSocketVector")) {
 			let v: any = BlHandle.get(BlHandle.get(sock, "default_value", 0, "bNodeSocketValueVector"), "value");
-			v[0] = Math.floor(v[0] * 100) / 100;
-			v[1] = Math.floor(v[1] * 100) / 100;
-			v[2] = Math.floor(v[2] * 100) / 100;
+			v[0] = math_floor(v[0] * 100) / 100;
+			v[1] = math_floor(v[1] * 100) / 100;
+			v[2] = math_floor(v[2] * 100) / 100;
 			return v;
 		}
 		else if (idname.startsWith("NodeSocketColor")) {
 			let v: any = BlHandle.get(BlHandle.get(sock, "default_value", 0, "bNodeSocketValueRGBA"), "value");
-			v[0] = Math.floor(v[0] * 100) / 100;
-			v[1] = Math.floor(v[1] * 100) / 100;
-			v[2] = Math.floor(v[2] * 100) / 100;
-			v[3] = Math.floor(v[3] * 100) / 100;
+			v[0] = math_floor(v[0] * 100) / 100;
+			v[1] = math_floor(v[1] * 100) / 100;
+			v[2] = math_floor(v[2] * 100) / 100;
+			v[3] = math_floor(v[3] * 100) / 100;
 			return v;
 		}
 		else if (idname.startsWith("NodeSocketFloat")) {
 			let v: any = BlHandle.get(BlHandle.get(sock, "default_value", 0, "bNodeSocketValueFloat"), "value");
-			v = Math.floor(v * 100) / 100;
+			v = math_floor(v * 100) / 100;
 			return v;
 		}
 		else if (idname.startsWith("NodeSocketInt")) {

+ 56 - 56
base/Sources/ImportBlendMesh.ts

@@ -106,12 +106,12 @@ class ImportBlendMesh {
 					if (hasuv) {
 						bl.pos = uvdata_pos + (loopstart + totloop - 1) * 4 * 3; // * 3 = x, y, flag
 						uv0 = ParserBlend.read_f32array(bl, 2);
-						if (uv0[0] > 1.0 + ImportBlendMesh.eps) uv0[0] = uv0[0] - Math.floor(uv0[0]);
-						if (uv0[1] > 1.0 + ImportBlendMesh.eps) uv0[1] = uv0[1] - Math.floor(uv0[1]);
+						if (uv0[0] > 1.0 + ImportBlendMesh.eps) uv0[0] = uv0[0] - math_floor(uv0[0]);
+						if (uv0[1] > 1.0 + ImportBlendMesh.eps) uv0[1] = uv0[1] - math_floor(uv0[1]);
 						bl.pos = uvdata_pos + (loopstart) * 4 * 3;
 						uv1 = ParserBlend.read_f32array(bl, 2);
-						if (uv1[0] > 1.0 + ImportBlendMesh.eps) uv1[0] = uv1[0] - Math.floor(uv1[0]);
-						if (uv1[1] > 1.0 + ImportBlendMesh.eps) uv1[1] = uv1[1] - Math.floor(uv1[1]);
+						if (uv1[0] > 1.0 + ImportBlendMesh.eps) uv1[0] = uv1[0] - math_floor(uv1[0]);
+						if (uv1[1] > 1.0 + ImportBlendMesh.eps) uv1[1] = uv1[1] - math_floor(uv1[1]);
 					}
 					let col0r: i32 = 0;
 					let col0g: i32 = 0;
@@ -157,29 +157,29 @@ class ImportBlendMesh {
 						posa32[tri * 9 + 6] = co2[0];
 						posa32[tri * 9 + 7] = co2[1];
 						posa32[tri * 9 + 8] = co2[2];
-						posa[tri * 12 + 3] = Math.floor(vec0.z * 32767);
-						posa[tri * 12 + 7] = Math.floor((smooth ? vec1.z : vec0.z) * 32767);
-						posa[tri * 12 + 11] = Math.floor((smooth ? vec2.z : vec0.z) * 32767);
-						nora[tri * 6    ] = Math.floor(vec0.x * 32767);
-						nora[tri * 6 + 1] = Math.floor(vec0.y * 32767);
-						nora[tri * 6 + 2] = Math.floor((smooth ? vec1.x : vec0.x) * 32767);
-						nora[tri * 6 + 3] = Math.floor((smooth ? vec1.y : vec0.y) * 32767);
-						nora[tri * 6 + 4] = Math.floor((smooth ? vec2.x : vec0.x) * 32767);
-						nora[tri * 6 + 5] = Math.floor((smooth ? vec2.y : vec0.y) * 32767);
+						posa[tri * 12 + 3] = math_floor(vec0.z * 32767);
+						posa[tri * 12 + 7] = math_floor((smooth ? vec1.z : vec0.z) * 32767);
+						posa[tri * 12 + 11] = math_floor((smooth ? vec2.z : vec0.z) * 32767);
+						nora[tri * 6    ] = math_floor(vec0.x * 32767);
+						nora[tri * 6 + 1] = math_floor(vec0.y * 32767);
+						nora[tri * 6 + 2] = math_floor((smooth ? vec1.x : vec0.x) * 32767);
+						nora[tri * 6 + 3] = math_floor((smooth ? vec1.y : vec0.y) * 32767);
+						nora[tri * 6 + 4] = math_floor((smooth ? vec2.x : vec0.x) * 32767);
+						nora[tri * 6 + 5] = math_floor((smooth ? vec2.y : vec0.y) * 32767);
 						co1 = co2;
 						no1 = no2;
 						vec4_set_from(vec1, vec2);
 						if (hasuv) {
 							bl.pos = uvdata_pos + (loopstart + j + 1) * 4 * 3;
 							uv2 = ParserBlend.read_f32array(bl, 2);
-							if (uv2[0] > 1.0 + ImportBlendMesh.eps) uv2[0] = uv2[0] - Math.floor(uv2[0]);
-							if (uv2[1] > 1.0 + ImportBlendMesh.eps) uv2[1] = uv2[1] - Math.floor(uv2[1]);
-							texa[tri * 6    ] = Math.floor(uv0[0] * 32767);
-							texa[tri * 6 + 1] = Math.floor((1.0 - uv0[1]) * 32767);
-							texa[tri * 6 + 2] = Math.floor(uv1[0] * 32767);
-							texa[tri * 6 + 3] = Math.floor((1.0 - uv1[1]) * 32767);
-							texa[tri * 6 + 4] = Math.floor(uv2[0] * 32767);
-							texa[tri * 6 + 5] = Math.floor((1.0 - uv2[1]) * 32767);
+							if (uv2[0] > 1.0 + ImportBlendMesh.eps) uv2[0] = uv2[0] - math_floor(uv2[0]);
+							if (uv2[1] > 1.0 + ImportBlendMesh.eps) uv2[1] = uv2[1] - math_floor(uv2[1]);
+							texa[tri * 6    ] = math_floor(uv0[0] * 32767);
+							texa[tri * 6 + 1] = math_floor((1.0 - uv0[1]) * 32767);
+							texa[tri * 6 + 2] = math_floor(uv1[0] * 32767);
+							texa[tri * 6 + 3] = math_floor((1.0 - uv1[1]) * 32767);
+							texa[tri * 6 + 4] = math_floor(uv2[0] * 32767);
+							texa[tri * 6 + 5] = math_floor((1.0 - uv2[1]) * 32767);
 							uv1 = uv2;
 						}
 						if (hascol) {
@@ -223,9 +223,9 @@ class ImportBlendMesh {
 					let nx: f32 = vec0.x;
 					let ny: f32 = vec0.y;
 					let nz: f32 = vec0.z;
-					let nxabs: f32 = Math.abs(nx);
-					let nyabs: f32 = Math.abs(ny);
-					let nzabs: f32 = Math.abs(nz);
+					let nxabs: f32 = math_abs(nx);
+					let nyabs: f32 = math_abs(ny);
+					let nzabs: f32 = math_abs(nz);
 					let flip: bool = nx + ny + nz > 0;
 					let axis: i32 = nxabs > nyabs && nxabs > nzabs ? 0 : nyabs > nxabs && nyabs > nzabs ? 1 : 2;
 					let axis0: i32 = axis == 0 ? (flip ? 2 : 1) : axis == 1 ? (flip ? 0 : 2) : (flip ? 1 : 0);
@@ -278,7 +278,7 @@ class ImportBlendMesh {
 							let px: f32 = co[axis0];
 							let py: f32 = co[axis1];
 
-							if (UtilMesh.pnpoly(v0x, v0y, v1x, v1y, v2x, v2y, px, py)) {
+							if (util_mesh_pnpoly(v0x, v0y, v1x, v1y, v2x, v2y, px, py)) {
 								overlap = true;
 								break;
 							}
@@ -310,16 +310,16 @@ class ImportBlendMesh {
 							if (hasuv) {
 								bl.pos = uvdata_pos + (va[i ]) * 4 * 3;
 								uv0 = ParserBlend.read_f32array(bl, 2);
-								if (uv0[0] > 1.0 + ImportBlendMesh.eps) uv0[0] = uv0[0] - Math.floor(uv0[0]);
-								if (uv0[1] > 1.0 + ImportBlendMesh.eps) uv0[1] = uv0[1] - Math.floor(uv0[1]);
+								if (uv0[0] > 1.0 + ImportBlendMesh.eps) uv0[0] = uv0[0] - math_floor(uv0[0]);
+								if (uv0[1] > 1.0 + ImportBlendMesh.eps) uv0[1] = uv0[1] - math_floor(uv0[1]);
 								bl.pos = uvdata_pos + (va[i1]) * 4 * 3;
 								uv1 = ParserBlend.read_f32array(bl, 2);
-								if (uv1[0] > 1.0 + ImportBlendMesh.eps) uv1[0] = uv1[0] - Math.floor(uv1[0]);
-								if (uv1[1] > 1.0 + ImportBlendMesh.eps) uv1[1] = uv1[1] - Math.floor(uv1[1]);
+								if (uv1[0] > 1.0 + ImportBlendMesh.eps) uv1[0] = uv1[0] - math_floor(uv1[0]);
+								if (uv1[1] > 1.0 + ImportBlendMesh.eps) uv1[1] = uv1[1] - math_floor(uv1[1]);
 								bl.pos = uvdata_pos + (va[i2]) * 4 * 3;
 								uv2 = ParserBlend.read_f32array(bl, 2);
-								if (uv2[0] > 1.0 + ImportBlendMesh.eps) uv2[0] = uv2[0] - Math.floor(uv2[0]);
-								if (uv2[1] > 1.0 + ImportBlendMesh.eps) uv2[1] = uv2[1] - Math.floor(uv2[1]);
+								if (uv2[0] > 1.0 + ImportBlendMesh.eps) uv2[0] = uv2[0] - math_floor(uv2[0]);
+								if (uv2[1] > 1.0 + ImportBlendMesh.eps) uv2[1] = uv2[1] - math_floor(uv2[1]);
 							}
 							let col0r: i32 = 0;
 							let col0g: i32 = 0;
@@ -353,22 +353,22 @@ class ImportBlendMesh {
 							posa32[tri * 9 + 6] = co2[0];
 							posa32[tri * 9 + 7] = co2[1];
 							posa32[tri * 9 + 8] = co2[2];
-							posa[tri * 12 + 3] = Math.floor(vec0.z * 32767);
-							posa[tri * 12 + 7] = Math.floor((smooth ? vec1.z : vec0.z) * 32767);
-							posa[tri * 12 + 11] = Math.floor((smooth ? vec2.z : vec0.z) * 32767);
-							nora[tri * 6    ] = Math.floor(vec0.x * 32767);
-							nora[tri * 6 + 1] = Math.floor(vec0.y * 32767);
-							nora[tri * 6 + 2] = Math.floor((smooth ? vec1.x : vec0.x) * 32767);
-							nora[tri * 6 + 3] = Math.floor((smooth ? vec1.y : vec0.y) * 32767);
-							nora[tri * 6 + 4] = Math.floor((smooth ? vec2.x : vec0.x) * 32767);
-							nora[tri * 6 + 5] = Math.floor((smooth ? vec2.y : vec0.y) * 32767);
+							posa[tri * 12 + 3] = math_floor(vec0.z * 32767);
+							posa[tri * 12 + 7] = math_floor((smooth ? vec1.z : vec0.z) * 32767);
+							posa[tri * 12 + 11] = math_floor((smooth ? vec2.z : vec0.z) * 32767);
+							nora[tri * 6    ] = math_floor(vec0.x * 32767);
+							nora[tri * 6 + 1] = math_floor(vec0.y * 32767);
+							nora[tri * 6 + 2] = math_floor((smooth ? vec1.x : vec0.x) * 32767);
+							nora[tri * 6 + 3] = math_floor((smooth ? vec1.y : vec0.y) * 32767);
+							nora[tri * 6 + 4] = math_floor((smooth ? vec2.x : vec0.x) * 32767);
+							nora[tri * 6 + 5] = math_floor((smooth ? vec2.y : vec0.y) * 32767);
 							if (hasuv) {
-								texa[tri * 6    ] = Math.floor(uv0[0] * 32767);
-								texa[tri * 6 + 1] = Math.floor((1.0 - uv0[1]) * 32767);
-								texa[tri * 6 + 2] = Math.floor(uv1[0] * 32767);
-								texa[tri * 6 + 3] = Math.floor((1.0 - uv1[1]) * 32767);
-								texa[tri * 6 + 4] = Math.floor(uv2[0] * 32767);
-								texa[tri * 6 + 5] = Math.floor((1.0 - uv2[1]) * 32767);
+								texa[tri * 6    ] = math_floor(uv0[0] * 32767);
+								texa[tri * 6 + 1] = math_floor((1.0 - uv0[1]) * 32767);
+								texa[tri * 6 + 2] = math_floor(uv1[0] * 32767);
+								texa[tri * 6 + 3] = math_floor((1.0 - uv1[1]) * 32767);
+								texa[tri * 6 + 4] = math_floor(uv2[0] * 32767);
+								texa[tri * 6 + 5] = math_floor((1.0 - uv2[1]) * 32767);
 							}
 							if (hascol) {
 								cola[tri * 12    ] = col0r * 128;
@@ -398,7 +398,7 @@ class ImportBlendMesh {
 			let obmat: any = BlHandle.get(ob, "obmat", 0, "float", 16);
 			let mat: mat4_t = mat4_transpose(mat4_from_f32_array(obmat));
 			let v: vec4_t = vec4_create();
-			for (let i: i32 = 0; i < Math.floor(posa32.length / 3); ++i) {
+			for (let i: i32 = 0; i < math_floor(posa32.length / 3); ++i) {
 				vec4_set(v, posa32[i * 3], posa32[i * 3 + 1], posa32[i * 3 + 2]);
 				vec4_apply_mat4(v, mat);
 				posa32[i * 3    ] = v.x;
@@ -408,26 +408,26 @@ class ImportBlendMesh {
 			mat4_get_inv(mat, mat);
 			mat4_transpose3x3(mat);
 			mat.m[12] = mat.m[13] = mat.m[14] = mat.m[15] = 0;
-			for (let i: i32 = 0; i < Math.floor(nora.length / 2); ++i) {
+			for (let i: i32 = 0; i < math_floor(nora.length / 2); ++i) {
 				vec4_set(v, nora[i * 2] / 32767, nora[i * 2 + 1] / 32767, posa[i * 4 + 3] / 32767);
 				vec4_apply_mat(v, mat);
 				vec4_normalize(v);
-				nora[i * 2    ] = Math.floor(v.x * 32767);
-				nora[i * 2 + 1] = Math.floor(v.y * 32767);
-				posa[i * 4 + 3] = Math.floor(v.z * 32767);
+				nora[i * 2    ] = math_floor(v.x * 32767);
+				nora[i * 2 + 1] = math_floor(v.y * 32767);
+				posa[i * 4 + 3] = math_floor(v.z * 32767);
 			}
 
 			// Pack positions to (-1, 1) range
 			let scale_pos: f32 = 0.0;
 			for (let i: i32 = 0; i < posa32.length; ++i) {
-				let f: f32 = Math.abs(posa32[i]);
+				let f: f32 = math_abs(posa32[i]);
 				if (scale_pos < f) scale_pos = f;
 			}
 			let inv: f32 = 1 / scale_pos;
-			for (let i: i32 = 0; i < Math.floor(posa32.length / 3); ++i) {
-				posa[i * 4    ] = Math.floor(posa32[i * 3    ] * 32767 * inv);
-				posa[i * 4 + 1] = Math.floor(posa32[i * 3 + 1] * 32767 * inv);
-				posa[i * 4 + 2] = Math.floor(posa32[i * 3 + 2] * 32767 * inv);
+			for (let i: i32 = 0; i < math_floor(posa32.length / 3); ++i) {
+				posa[i * 4    ] = math_floor(posa32[i * 3    ] * 32767 * inv);
+				posa[i * 4 + 1] = math_floor(posa32[i * 3 + 1] * 32767 * inv);
+				posa[i * 4 + 2] = math_floor(posa32[i * 3 + 2] * 32767 * inv);
 			}
 
 			let obj: any = {

+ 7 - 7
base/Sources/ImportEnvmap.ts

@@ -32,8 +32,8 @@ class ImportEnvmap {
 			ImportEnvmap.mips = [];
 			let w: i32 = 512;
 			for (let i: i32 = 0; i < 10; ++i) {
-				ImportEnvmap.mips.push(image_create_render_target(w, w > 1 ? Math.floor(w / 2) : 1, tex_format_t.RGBA128));
-				w = Math.floor(w / 2);
+				ImportEnvmap.mips.push(image_create_render_target(w, w > 1 ? math_floor(w / 2) : 1, tex_format_t.RGBA128));
+				w = math_floor(w / 2);
 			}
 
 			if (const_data_screen_aligned_vb == null) const_data_create_screen_aligned_data();
@@ -104,10 +104,10 @@ class ImportEnvmap {
 	}
 
 	static reverse_equirect = (x: f32, y: f32): vec4_t => {
-		let theta: f32 = x * Math.PI * 2 - Math.PI;
-		let phi: f32 = y * Math.PI;
-		// return n.set(Math.sin(phi) * Math.cos(theta), -(Math.sin(phi) * Math.sin(theta)), Math.cos(phi));
-		return vec4_set(ImportEnvmap.n, -Math.cos(phi), Math.sin(phi) * Math.cos(theta), -(Math.sin(phi) * Math.sin(theta)));
+		let theta: f32 = x * math_pi() * 2 - math_pi();
+		let phi: f32 = y * math_pi();
+		// return n.set(math_sin(phi) * math_cos(theta), -(math_sin(phi) * math_sin(theta)), math_cos(phi));
+		return vec4_set(ImportEnvmap.n, -math_cos(phi), math_sin(phi) * math_cos(theta), -(math_sin(phi) * math_sin(theta)));
 	}
 
 	// https://ndotl.wordpress.com/2015/03/07/pbr-cubemap-filtering
@@ -129,7 +129,7 @@ class ImportEnvmap {
 
 				for (let i: i32 = 0; i < 3; ++i) {
 					let value: f32 = view.getFloat32(((x + y * sourceWidth) * 16 + i * 4), true);
-					value = Math.pow(value, 1.0 / 2.2);
+					value = math_pow(value, 1.0 / 2.2);
 
 					sh[0 + i] += value * weight1;
 					sh[3 + i] += value * weight2 * ImportEnvmap.n.x;

+ 2 - 2
base/Sources/ImportFont.ts

@@ -27,12 +27,12 @@ class ImportFont {
 			for (let f of font_slots) {
 				context_raw.font = f;
 				project_fonts.push(f);
-				UtilRender.make_font_preview();
+				util_render_make_font_preview();
 			}
 		}
 		app_notify_on_init(_init);
 
-		UIBase.hwnds[tab_area_t.STATUS].redraws = 2;
+		ui_base_hwnds[tab_area_t.STATUS].redraws = 2;
 	}
 }
 

+ 11 - 11
base/Sources/ImportMesh.ts

@@ -78,7 +78,7 @@ class ImportMesh {
 
 			// No mask by default
 			for (let p of project_paint_objects) p.base.visible = true;
-			if (context_raw.merged_object == null) UtilMesh.merge_mesh();
+			if (context_raw.merged_object == null) util_mesh_merge();
 			context_raw.paint_object.skip_context = "paint";
 			context_raw.merged_object.base.visible = true;
 		}
@@ -90,7 +90,7 @@ class ImportMesh {
 		MakeMaterial.parse_mesh_material();
 
 		///if (is_paint || is_sculpt)
-		UIView2D.hwnd.redraws = 2;
+		ui_view2d_hwnd.redraws = 2;
 		///end
 
 		///if (krom_direct3d12 || krom_vulkan || krom_metal)
@@ -131,11 +131,11 @@ class ImportMesh {
 		context_raw.ddirty = 4;
 
 		///if (is_paint || is_sculpt)
-		UIBase.hwnds[tab_area_t.SIDEBAR0].redraws = 2;
-		UIBase.hwnds[tab_area_t.SIDEBAR1].redraws = 2;
-		UtilUV.uvmap_cached = false;
-		UtilUV.trianglemap_cached = false;
-		UtilUV.dilatemap_cached = false;
+		ui_base_hwnds[tab_area_t.SIDEBAR0].redraws = 2;
+		ui_base_hwnds[tab_area_t.SIDEBAR1].redraws = 2;
+		util_uv_uvmap_cached = false;
+		util_uv_trianglemap_cached = false;
+		util_uv_dilatemap_cached = false;
 		///end
 
 		///if (is_paint || is_sculpt)
@@ -207,10 +207,10 @@ class ImportMesh {
 		context_raw.ddirty = 4;
 
 		///if (is_paint || is_sculpt)
-		UIBase.hwnds[tab_area_t.SIDEBAR0].redraws = 2;
-		UtilUV.uvmap_cached = false;
-		UtilUV.trianglemap_cached = false;
-		UtilUV.dilatemap_cached = false;
+		ui_base_hwnds[tab_area_t.SIDEBAR0].redraws = 2;
+		util_uv_uvmap_cached = false;
+		util_uv_trianglemap_cached = false;
+		util_uv_dilatemap_cached = false;
 		///end
 	}
 

+ 12 - 12
base/Sources/ImportObj.ts

@@ -17,7 +17,7 @@ class ImportObj {
 			for (let i: i32 = 0; i < part.udims.length; ++i) {
 				if (part.udims[i].length == 0) continue;
 				let u: i32 = i % part.udims_u;
-				let v: i32 = Math.floor(i / part.udims_u);
+				let v: i32 = math_floor(i / part.udims_u);
 				part.name = name + "." + (1000 + v * 10 + u + 1);
 				part.inda = part.udims[i];
 				i == 0 ? (replace_existing ? ImportMesh.make_mesh(part, path) : ImportMesh.add_mesh(part)) : ImportMesh.add_mesh(part);
@@ -57,33 +57,33 @@ class ImportObj {
 							texa1 = parts[j].texa != null ? parts[j].texa : null;
 							inda0 = parts[i].inda;
 							inda1 = parts[j].inda;
-							let voff: i32 = Math.floor(posa0.length / 4);
+							let voff: i32 = math_floor(posa0.length / 4);
 							// Repack merged positions
-							let posa32: Float32Array = new Float32Array(Math.floor(posa0.length / 4) * 3 + Math.floor(posa1.length / 4) * 3);
-							for (let k: i32 = 0; k < Math.floor(posa0.length / 4); ++k) {
+							let posa32: Float32Array = new Float32Array(math_floor(posa0.length / 4) * 3 + math_floor(posa1.length / 4) * 3);
+							for (let k: i32 = 0; k < math_floor(posa0.length / 4); ++k) {
 								posa32[k * 3    ] = posa0[k * 4    ] / 32767 * parts[i].scale_pos;
 								posa32[k * 3 + 1] = posa0[k * 4 + 1] / 32767 * parts[i].scale_pos;
 								posa32[k * 3 + 2] = posa0[k * 4 + 2] / 32767 * parts[i].scale_pos;
 							}
-							for (let k: i32 = 0; k < Math.floor(posa1.length / 4); ++k) {
+							for (let k: i32 = 0; k < math_floor(posa1.length / 4); ++k) {
 								posa32[voff * 3 + k * 3    ] = posa1[k * 4    ] / 32767 * parts[j].scale_pos;
 								posa32[voff * 3 + k * 3 + 1] = posa1[k * 4 + 1] / 32767 * parts[j].scale_pos;
 								posa32[voff * 3 + k * 3 + 2] = posa1[k * 4 + 2] / 32767 * parts[j].scale_pos;
 							}
 							let scale_pos: f32 = 0.0;
 							for (let k: i32 = 0; k < posa32.length; ++k) {
-								let f: f32 = Math.abs(posa32[k]);
+								let f: f32 = math_abs(posa32[k]);
 								if (scale_pos < f) scale_pos = f;
 							}
 							let inv: f32 = 32767 * (1 / scale_pos);
 							let posa: Int16Array = new Int16Array(posa0.length + posa1.length);
-							for (let k: i32 = 0; k < Math.floor(posa.length / 4); ++k) {
-								posa[k * 4    ] = Math.floor(posa32[k * 3    ] * inv);
-								posa[k * 4 + 1] = Math.floor(posa32[k * 3 + 1] * inv);
-								posa[k * 4 + 2] = Math.floor(posa32[k * 3 + 2] * inv);
+							for (let k: i32 = 0; k < math_floor(posa.length / 4); ++k) {
+								posa[k * 4    ] = math_floor(posa32[k * 3    ] * inv);
+								posa[k * 4 + 1] = math_floor(posa32[k * 3 + 1] * inv);
+								posa[k * 4 + 2] = math_floor(posa32[k * 3 + 2] * inv);
 							}
-							for (let k: i32 = 0; k < Math.floor(posa0.length / 4); ++k) posa[k * 4 + 3] = posa0[k * 4 + 3];
-							for (let k: i32 = 0; k < Math.floor(posa1.length / 4); ++k) posa[posa0.length + k * 4 + 3] = posa1[k * 4 + 3];
+							for (let k: i32 = 0; k < math_floor(posa0.length / 4); ++k) posa[k * 4 + 3] = posa0[k * 4 + 3];
+							for (let k: i32 = 0; k < math_floor(posa1.length / 4); ++k) posa[posa0.length + k * 4 + 3] = posa1[k * 4 + 3];
 							// Merge normals and uvs
 							let nora: Int16Array = new Int16Array(nora0.length + nora1.length);
 							let texa: Int16Array = (texa0 != null && texa1 != null) ? new Int16Array(texa0.length + texa1.length) : null;

+ 1 - 1
base/Sources/ImportTexture.ts

@@ -38,7 +38,7 @@ class ImportTexture {
 			if (context_raw.texture == null) context_raw.texture = asset;
 			project_asset_names.push(name);
 			project_asset_map.set(asset.id, image);
-			UIBase.hwnds[tab_area_t.STATUS].redraws = 2;
+			ui_base_hwnds[tab_area_t.STATUS].redraws = 2;
 			console_info(tr("Texture imported:") + " " + name);
 
 			// Set as envmap

+ 1 - 1
base/Sources/NodeShader.ts

@@ -7,7 +7,7 @@ class NodeShaderRaw {
 	outs: string[] = [];
 	shared_samplers: string[] = [];
 	uniforms: string[] = [];
-	functions: Map<string, string> = new Map();
+	functions: map_t<string, string> = map_create();
 	main: string = '';
 	main_init: string = '';
 	main_end: string = '';

+ 11 - 11
base/Sources/NodesMaterial.ts

@@ -2802,7 +2802,7 @@ class NodesMaterial {
 			if (val.length > 2) val.pop();
 		}
 		let ihandle: zui_handle_t = zui_nest(zui_nest(zui_nest(nhandle, 0), 2), axis, {position: 0});
-		let i: i32 = Math.floor(zui_slider(ihandle, "Index", 0, num - 1, false, 1, true, zui_align_t.LEFT));
+		let i: i32 = math_floor(zui_slider(ihandle, "Index", 0, num - 1, false, 1, true, zui_align_t.LEFT));
 		if (i >= val.length || i < 0) ihandle.value = i = val.length - 1; // Stay in bounds
 		zui_row([1 / 2, 1 / 2]);
 		zui_nest(zui_nest(nhandle, 0), 3).value = val[i][0];
@@ -2847,7 +2847,7 @@ class NodesMaterial {
 		but.data = zui_combo(zui_nest(zui_nest(nhandle, 0), 1, {position: but.data}), [tr("Linear"), tr("Constant")], tr("Interpolate"));
 
 		zui_row([1 / 2, 1 / 2]);
-		let i: i32 = Math.floor(zui_slider(ihandle, "Index", 0, vals.length - 1, false, 1, true, zui_align_t.LEFT));
+		let i: i32 = math_floor(zui_slider(ihandle, "Index", 0, vals.length - 1, false, 1, true, zui_align_t.LEFT));
 		if (i >= vals.length || i < 0) ihandle.value = i = vals.length - 1; // Stay in bounds
 
 		let val: Float32Array = vals[i];
@@ -2862,7 +2862,7 @@ class NodesMaterial {
 			let rx: f32 = nx + ui._w - zui_nodes_p(37);
 			let ry: f32 = ny - zui_nodes_p(5);
 			nodes._inputStarted = ui.input_started = false;
-			zui_nodes_rgba_popup(ui, chandle, val, Math.floor(rx), Math.floor(ry + zui_ELEMENT_H(ui)));
+			zui_nodes_rgba_popup(ui, chandle, val, math_floor(rx), math_floor(ry + zui_ELEMENT_H(ui)));
 		}
 		val[0] = color_get_rb(chandle.color) / 255;
 		val[1] = color_get_gb(chandle.color) / 255;
@@ -2938,7 +2938,7 @@ class NodesMaterial {
 		}
 
 		if (zui_button(tr("Nodes"))) {
-			UINodes.group_stack.push(group);
+			ui_nodes_group_stack.push(group);
 		}
 	}
 
@@ -2952,18 +2952,18 @@ class NodesMaterial {
 
 	static add_socket_button = (ui: zui_t, nodes: zui_nodes_t, node: zui_node_t, sockets: zui_node_socket_t[]) => {
 		if (zui_button(tr("Add"))) {
-			UIMenu.draw((ui: zui_t) => {
-				let groupStack: node_group_t[] = UINodes.group_stack;
+			ui_menu_draw((ui: zui_t) => {
+				let groupStack: node_group_t[] = ui_nodes_group_stack;
 				let c: zui_node_canvas_t = groupStack[groupStack.length - 1].canvas;
-				if (UIMenu.menu_button(ui, tr("RGBA"))) {
+				if (ui_menu_button(ui, tr("RGBA"))) {
 					sockets.push(NodesMaterial.create_socket(nodes, node, null, "RGBA", c));
 					NodesMaterial.sync_sockets(node);
 				}
-				if (UIMenu.menu_button(ui, tr("Vector"))) {
+				if (ui_menu_button(ui, tr("Vector"))) {
 					sockets.push(NodesMaterial.create_socket(nodes, node, null, "VECTOR", c));
 					NodesMaterial.sync_sockets(node);
 				}
-				if (UIMenu.menu_button(ui, tr("Value"))) {
+				if (ui_menu_button(ui, tr("Value"))) {
 					sockets.push(NodesMaterial.create_socket(nodes, node, null, "VALUE", c));
 					NodesMaterial.sync_sockets(node);
 				}
@@ -2972,7 +2972,7 @@ class NodesMaterial {
 	}
 
 	static sync_sockets = (node: zui_node_t) => {
-		let groupStack: node_group_t[] = UINodes.group_stack;
+		let groupStack: node_group_t[] = ui_nodes_group_stack;
 		let c: zui_node_canvas_t = groupStack[groupStack.length - 1].canvas;
 		for (let m of project_materials) NodesMaterial.sync_group_sockets(m.canvas, c.name, node);
 		for (let g of project_material_groups) NodesMaterial.sync_group_sockets(g.canvas, c.name, node);
@@ -3032,7 +3032,7 @@ class NodesMaterial {
 		if (n == null) return null;
 		let canvas: zui_node_canvas_t = group != null ? group.canvas : context_raw.material.canvas;
 		let nodes: zui_nodes_t = group != null ? group.nodes : context_raw.material.nodes;
-		let node: zui_node_t = UINodes.make_node(n, nodes, canvas);
+		let node: zui_node_t = ui_nodes_make_node(n, nodes, canvas);
 		canvas.nodes.push(node);
 		return node;
 	}

+ 1 - 1
base/Sources/ParserBlend.ts

@@ -19,7 +19,7 @@ class BlendRaw {
 	// Data
 	blocks: Block[] = [];
 	dna: Dna = null;
-	map: Map<any, Block> = new Map(); // Map blocks by memory address
+	map: map_t<any, Block> = map_create(); // Map blocks by memory address
 }
 
 class ParserBlend {

+ 7 - 7
base/Sources/ParserLogic.ts

@@ -1,14 +1,14 @@
 
 class ParserLogic {
 
-	static custom_nodes: Map<any, any> = new Map();
+	static custom_nodes: map_t<any, any> = map_create();
 	static nodes: zui_node_t[];
 	static links: zui_node_link_t[];
 
 	static parsed_nodes: string[] = null;
-	static parsed_labels: Map<string, string> = null;
-	static node_map: Map<string, LogicNode>;
-	static raw_map: Map<LogicNode, zui_node_t>;
+	static parsed_labels: map_t<string, string> = null;
+	static node_map: map_t<string, LogicNode>;
+	static raw_map: map_t<LogicNode, zui_node_t>;
 
 	static get_logic_node = (node: zui_node_t): LogicNode => {
 		return ParserLogic.node_map.get(ParserLogic.node_name(node));
@@ -65,9 +65,9 @@ class ParserLogic {
 		ParserLogic.links = canvas.links;
 
 		ParserLogic.parsed_nodes = [];
-		ParserLogic.parsed_labels = new Map();
-		ParserLogic.node_map = new Map();
-		ParserLogic.raw_map = new Map();
+		ParserLogic.parsed_labels = map_create();
+		ParserLogic.node_map = map_create();
+		ParserLogic.raw_map = map_create();
 		let root_nodes: zui_node_t[] = ParserLogic.get_root_nodes(canvas);
 
 		for (let node of root_nodes) ParserLogic.build_node(node);

+ 32 - 32
base/Sources/ParserMaterial.ts

@@ -33,7 +33,7 @@ class ParserMaterial {
 	static tex_coord: string = "texCoord";
 	static eps: f32 = 0.000001;
 
-	static custom_nodes: Map<any, any> = new Map();
+	static custom_nodes: map_t<any, any> = map_create();
 	static parse_surface: bool = true;
 	static parse_opacity: bool = true;
 	static parse_height: bool = false;
@@ -59,10 +59,10 @@ class ParserMaterial {
 	static arm_export_tangents: bool = true;
 	static out_normaltan: string; // Raw tangent space normal parsed from normal map
 
-	static script_links: Map<string, string> = null;
+	static script_links: map_t<string, string> = null;
 
-	static parsedMap: Map<string, string> = new Map();
-	static textureMap: Map<string, string> = new Map();
+	static parsedMap: map_t<string, string> = map_create();
+	static textureMap: map_t<string, string> = map_create();
 
 	static get_node = (id: i32): zui_node_t => {
 		for (let n of ParserMaterial.nodes) if (n.id == id) return n;
@@ -462,7 +462,7 @@ class ParserMaterial {
 			return ParserMaterial.vec3(socket.default_value);
 		}
 		else if (node.type == "TEX_BRICK") {
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_tex_brick);
+			NodeShader.add_function(ParserMaterial.curshader, str_tex_brick);
 			let co: string = ParserMaterial.get_coord(node);
 			let col1: string = ParserMaterial.parse_vector_input(node.inputs[1]);
 			let col2: string = ParserMaterial.parse_vector_input(node.inputs[2]);
@@ -472,7 +472,7 @@ class ParserMaterial {
 			return res;
 		}
 		else if (node.type == "TEX_CHECKER") {
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_tex_checker);
+			NodeShader.add_function(ParserMaterial.curshader, str_tex_checker);
 			let co: string = ParserMaterial.get_coord(node);
 			let col1: string = ParserMaterial.parse_vector_input(node.inputs[1]);
 			let col2: string = ParserMaterial.parse_vector_input(node.inputs[2]);
@@ -509,21 +509,21 @@ class ParserMaterial {
 			}
 		}
 		else if (node.type == "TEX_MAGIC") {
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_tex_magic);
+			NodeShader.add_function(ParserMaterial.curshader, str_tex_magic);
 			let co: string = ParserMaterial.get_coord(node);
 			let scale: string = ParserMaterial.parse_value_input(node.inputs[1]);
 			let res: string = `tex_magic(${co} * ${scale} * 4.0)`;
 			return res;
 		}
 		else if (node.type == "TEX_NOISE") {
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_tex_noise);
+			NodeShader.add_function(ParserMaterial.curshader, str_tex_noise);
 			let co: string = ParserMaterial.get_coord(node);
 			let scale: string = ParserMaterial.parse_value_input(node.inputs[1]);
 			let res: string = `vec3(tex_noise(${co} * ${scale}), tex_noise(${co} * ${scale} + 0.33), tex_noise(${co} * ${scale} + 0.66))`;
 			return res;
 		}
 		else if (node.type == "TEX_VORONOI") {
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_tex_voronoi);
+			NodeShader.add_function(ParserMaterial.curshader, str_tex_voronoi);
 			NodeShader.add_uniform(ParserMaterial.curshader, "sampler2D snoise256", "$noise256.k");
 			let co: string = ParserMaterial.get_coord(node);
 			let scale: string = ParserMaterial.parse_value_input(node.inputs[1]);
@@ -540,7 +540,7 @@ class ParserMaterial {
 			return res;
 		}
 		else if (node.type == "TEX_WAVE") {
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_tex_wave);
+			NodeShader.add_function(ParserMaterial.curshader, str_tex_wave);
 			let co: string = ParserMaterial.get_coord(node);
 			let scale: string = ParserMaterial.parse_value_input(node.inputs[1]);
 			let res: string = ParserMaterial.to_vec3(`tex_wave_f(${co} * ${scale})`);
@@ -550,7 +550,7 @@ class ParserMaterial {
 			let out_col: string = ParserMaterial.parse_vector_input(node.inputs[0]);
 			let bright: string = ParserMaterial.parse_value_input(node.inputs[1]);
 			let contr: string = ParserMaterial.parse_value_input(node.inputs[2]);
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_brightcontrast);
+			NodeShader.add_function(ParserMaterial.curshader, str_brightcontrast);
 			return `brightcontrast(${out_col}, ${bright}, ${contr})`;
 		}
 		else if (node.type == "GAMMA") {
@@ -565,7 +565,7 @@ class ParserMaterial {
 			let tex_name: string = "texwarp_" + ParserMaterial.node_name(node);
 			NodeShader.add_uniform(ParserMaterial.curshader, "sampler2D " + tex_name, "_" + tex_name);
 			let store: string = ParserMaterial.store_var_name(node);
-			NodeShader.write(ParserMaterial.curshader, `float ${store}_rad = ${angle} * (${Math.PI} / 180);`);
+			NodeShader.write(ParserMaterial.curshader, `float ${store}_rad = ${angle} * (${math_pi()} / 180);`);
 			NodeShader.write(ParserMaterial.curshader, `float ${store}_x = cos(${store}_rad);`);
 			NodeShader.write(ParserMaterial.curshader, `float ${store}_y = sin(${store}_rad);`);
 			return `texture(${tex_name}, texCoord + vec2(${store}_x, ${store}_y) * ${mask}).rgb;`;
@@ -588,7 +588,7 @@ class ParserMaterial {
 			return `${store}_res`;
 		}
 		else if (node.type == "HUE_SAT") {
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_hue_sat);
+			NodeShader.add_function(ParserMaterial.curshader, str_hue_sat);
 			let hue: string = ParserMaterial.parse_value_input(node.inputs[0]);
 			let sat: string = ParserMaterial.parse_value_input(node.inputs[1]);
 			let val: string = ParserMaterial.parse_value_input(node.inputs[2]);
@@ -661,19 +661,19 @@ class ParserMaterial {
 				out_col = "(" + ParserMaterial.to_vec3(`(1.0 - ${fac_var}) * ${col1} + ${fac_var} * ${col1} / ${col2}`) + ")";
 			}
 			else if (blend == "HUE") {
-				NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_hue_sat);
+				NodeShader.add_function(ParserMaterial.curshader, str_hue_sat);
 				out_col = `mix(${col1}, hsv_to_rgb(vec3(rgb_to_hsv(${col2}).r, rgb_to_hsv(${col1}).g, rgb_to_hsv(${col1}).b)), ${fac_var})`;
 			}
 			else if (blend == "SATURATION") {
-				NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_hue_sat);
+				NodeShader.add_function(ParserMaterial.curshader, str_hue_sat);
 				out_col = `mix(${col1}, hsv_to_rgb(vec3(rgb_to_hsv(${col1}).r, rgb_to_hsv(${col2}).g, rgb_to_hsv(${col1}).b)), ${fac_var})`;
 			}
 			else if (blend == "COLOR") {
-				NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_hue_sat);
+				NodeShader.add_function(ParserMaterial.curshader, str_hue_sat);
 				out_col = `mix(${col1}, hsv_to_rgb(vec3(rgb_to_hsv(${col2}).r, rgb_to_hsv(${col2}).g, rgb_to_hsv(${col1}).b)), ${fac_var})`;
 			}
 			else if (blend == "VALUE") {
-				NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_hue_sat);
+				NodeShader.add_function(ParserMaterial.curshader, str_hue_sat);
 				out_col = `mix(${col1}, hsv_to_rgb(vec3(rgb_to_hsv(${col1}).r, rgb_to_hsv(${col1}).g, rgb_to_hsv(${col2}).b)), ${fac_var})`;
 			}
 			if (use_clamp) return `clamp(${out_col}, vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0))`;
@@ -748,7 +748,7 @@ class ParserMaterial {
 			return `(sqrt(vec3(${vc0}, ${vc1}, ${vc2}) * vec3(${vc3a}, ${vc3b}, ${vc3c})) * ${fac})`;
 		}
 		else if (node.type == "COMBHSV") {
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_hue_sat);
+			NodeShader.add_function(ParserMaterial.curshader, str_hue_sat);
 			let h: string = ParserMaterial.parse_value_input(node.inputs[0]);
 			let s: string = ParserMaterial.parse_value_input(node.inputs[1]);
 			let v: string = ParserMaterial.parse_value_input(node.inputs[2]);
@@ -761,9 +761,9 @@ class ParserMaterial {
 			return `vec3(${r}, ${g}, ${b})`;
 		}
 		else if (node.type == "WAVELENGTH") {
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_wavelength_to_rgb);
+			NodeShader.add_function(ParserMaterial.curshader, str_wavelength_to_rgb);
 			let wl: string = ParserMaterial.parse_value_input(node.inputs[0]);
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_wavelength_to_rgb);
+			NodeShader.add_function(ParserMaterial.curshader, str_wavelength_to_rgb);
 			return `wavelength_to_rgb((${wl} - 450.0) / 150.0)`;
 		}
 		else if (node.type == "CAMERA") {
@@ -923,10 +923,10 @@ class ParserMaterial {
 			}
 			// if node.rotation[1] != 0.0:
 			//     a = node.rotation[1]
-			//     out = `vec3({0}.x * {1} - {0}.z * {2}, {0}.x * {2} + {0}.z * {1}, 0.0)`.format(out, math.cos(a), math.sin(a))
+			//     out = `vec3({0}.x * {1} - {0}.z * {2}, {0}.x * {2} + {0}.z * {1}, 0.0)`.format(out, math_cos(a), math_sin(a))
 			// if node.rotation[0] != 0.0:
 			//     a = node.rotation[0]
-			//     out = `vec3({0}.y * {1} - {0}.z * {2}, {0}.y * {2} + {0}.z * {1}, 0.0)`.format(out, math.cos(a), math.sin(a))
+			//     out = `vec3({0}.y * {1} - {0}.z * {2}, {0}.y * {2} + {0}.z * {1}, 0.0)`.format(out, math_cos(a), math_sin(a))
 			if (node_translation != `vec3(0, 0, 0)`) {
 				out = `(${out} + ${node_translation})`;
 			}
@@ -1093,7 +1093,7 @@ class ParserMaterial {
 			NodeShader.write(ParserMaterial.frag, `texn.y = -texn.y;`);
 			if (!ParserMaterial.cotangent_frame_written) {
 				ParserMaterial.cotangent_frame_written = true;
-				NodeShader.add_function(ParserMaterial.frag, ShaderFunctions.str_cotangent_frame);
+				NodeShader.add_function(ParserMaterial.frag, str_cotangent_frame);
 			}
 			ParserMaterial.frag.n = true;
 			///if (krom_direct3d11 || krom_direct3d12 || krom_metal || krom_vulkan)
@@ -1314,14 +1314,14 @@ class ParserMaterial {
 			return ParserMaterial.vec1(node.outputs[0].default_value);
 		}
 		else if (node.type == "TEX_BRICK") {
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_tex_brick);
+			NodeShader.add_function(ParserMaterial.curshader, str_tex_brick);
 			let co: string = ParserMaterial.get_coord(node);
 			let scale: string = ParserMaterial.parse_value_input(node.inputs[4]);
 			let res: string = `tex_brick_f(${co} * ${scale})`;
 			return res;
 		}
 		else if (node.type == "TEX_CHECKER") {
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_tex_checker);
+			NodeShader.add_function(ParserMaterial.curshader, str_tex_checker);
 			let co: string = ParserMaterial.get_coord(node);
 			let scale: string = ParserMaterial.parse_value_input(node.inputs[3]);
 			let res: string = `tex_checker_f(${co}, ${scale})`;
@@ -1351,28 +1351,28 @@ class ParserMaterial {
 			}
 		}
 		else if (node.type == "TEX_MAGIC") {
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_tex_magic);
+			NodeShader.add_function(ParserMaterial.curshader, str_tex_magic);
 			let co: string = ParserMaterial.get_coord(node);
 			let scale: string = ParserMaterial.parse_value_input(node.inputs[1]);
 			let res: string = `tex_magic_f(${co} * ${scale} * 4.0)`;
 			return res;
 		}
 		else if (node.type == "TEX_MUSGRAVE") {
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_tex_musgrave);
+			NodeShader.add_function(ParserMaterial.curshader, str_tex_musgrave);
 			let co: string = ParserMaterial.get_coord(node);
 			let scale: string = ParserMaterial.parse_value_input(node.inputs[1]);
 			let res: string = `tex_musgrave_f(${co} * ${scale} * 0.5)`;
 			return res;
 		}
 		else if (node.type == "TEX_NOISE") {
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_tex_noise);
+			NodeShader.add_function(ParserMaterial.curshader, str_tex_noise);
 			let co: string = ParserMaterial.get_coord(node);
 			let scale: string = ParserMaterial.parse_value_input(node.inputs[1]);
 			let res: string = `tex_noise(${co} * ${scale})`;
 			return res;
 		}
 		else if (node.type == "TEX_VORONOI") {
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_tex_voronoi);
+			NodeShader.add_function(ParserMaterial.curshader, str_tex_voronoi);
 			NodeShader.add_uniform(ParserMaterial.curshader, "sampler2D snoise256", "$noise256.k");
 			let co: string = ParserMaterial.get_coord(node);
 			let scale: string = ParserMaterial.parse_value_input(node.inputs[1]);
@@ -1389,7 +1389,7 @@ class ParserMaterial {
 			return res;
 		}
 		else if (node.type == "TEX_WAVE") {
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_tex_wave);
+			NodeShader.add_function(ParserMaterial.curshader, str_tex_wave);
 			let co: string = ParserMaterial.get_coord(node);
 			let scale: string = ParserMaterial.parse_value_input(node.inputs[1]);
 			let res: string = `tex_wave_f(${co} * ${scale})`;
@@ -1542,7 +1542,7 @@ class ParserMaterial {
 			}
 		}
 		else if (node.type == "SCRIPT_CPU") {
-			if (ParserMaterial.script_links == null) ParserMaterial.script_links = new Map();
+			if (ParserMaterial.script_links == null) ParserMaterial.script_links = map_create();
 			let script: any = node.buttons[0].default_value;
 			let link: string = ParserMaterial.node_name(node);
 			ParserMaterial.script_links.set(link, script);
@@ -1558,7 +1558,7 @@ class ParserMaterial {
 			return `(((${col}.r * 0.3 + ${col}.g * 0.59 + ${col}.b * 0.11) / 3.0) * 2.5)`;
 		}
 		else if (node.type == "SEPHSV") {
-			NodeShader.add_function(ParserMaterial.curshader, ShaderFunctions.str_hue_sat);
+			NodeShader.add_function(ParserMaterial.curshader, str_hue_sat);
 			let col: string = ParserMaterial.parse_vector_input(node.inputs[0]);
 			if (socket == node.outputs[0]) {
 				return `rgb_to_hsv(${col}).r`;

+ 6 - 6
base/Sources/PhysicsBody.ts

@@ -64,9 +64,9 @@ class PhysicsBody {
 	static trans2: Ammo.btTransform;
 	static quat: quat_t = quat_create();
 
-	static convex_hull_cache: Map<mesh_data_t, Ammo.btConvexHullShape> = new Map();
-	static triangle_mesh_cache: Map<mesh_data_t, Ammo.btTriangleMesh> = new Map();
-	static users_cache: Map<mesh_data_t, i32> = new Map();
+	static convex_hull_cache: map_t<mesh_data_t, Ammo.btConvexHullShape> = map_create();
+	static triangle_mesh_cache: map_t<mesh_data_t, Ammo.btTriangleMesh> = map_create();
+	static users_cache: map_t<mesh_data_t, i32> = map_create();
 
 	static create(): PhysicsBodyRaw {
 		if (PhysicsBody.first) {
@@ -163,7 +163,7 @@ class PhysicsBody {
 			for (let i: i32 = 0; i < length; ++i) {
 				Ammo.HEAPU8[PhysicsBody.ammo_array + i] = pb.height_data[i];
 			}
-			let slice: i32 = Math.floor(Math.sqrt(length)); // Assuming square terrain data
+			let slice: i32 = math_floor(math_sqrt(length)); // Assuming square terrain data
 			let axis: i32 = 2; // z
 			let data_type: i32 = 5; // u8
 			pb.btshape = new Ammo.btHeightfieldTerrainShape(slice, slice, PhysicsBody.ammo_array, 1 / 255, 0, 1, axis, data_type, false);
@@ -391,7 +391,7 @@ class PhysicsBody {
 		sy *= data.scale_pos;
 		sz *= data.scale_pos;
 
-		for (let i: i32 = 0; i < Math.floor(positions.length / 4); ++i) {
+		for (let i: i32 = 0; i < math_floor(positions.length / 4); ++i) {
 			PhysicsBody.vec1.setX(positions[i * 4    ] * sx);
 			PhysicsBody.vec1.setY(positions[i * 4 + 1] * sy);
 			PhysicsBody.vec1.setZ(positions[i * 4 + 2] * sz);
@@ -425,7 +425,7 @@ class PhysicsBody {
 		sz *= data.scale_pos;
 
 		for (let ar of indices) {
-			for (let i: i32 = 0; i < Math.floor(ar.length / 3); ++i) {
+			for (let i: i32 = 0; i < math_floor(ar.length / 3); ++i) {
 				PhysicsBody.vec1.setX(positions[ar[i * 3    ] * 4    ] * sx);
 				PhysicsBody.vec1.setY(positions[ar[i * 3    ] * 4 + 1] * sy);
 				PhysicsBody.vec1.setZ(positions[ar[i * 3    ] * 4 + 2] * sz);

+ 1 - 1
base/Sources/PhysicsWorld.ts

@@ -5,7 +5,7 @@ class PhysicsWorldRaw {
 	world: Ammo.btDiscreteDynamicsWorld;
 	dispatcher: Ammo.btCollisionDispatcher;
 	contacts: pair_t[] = [];
-	body_map: Map<i32, PhysicsBodyRaw> = new Map();
+	body_map: map_t<i32, PhysicsBodyRaw> = map_create();
 	time_scale: f32 = 1.0;
 	time_step: f32 = 1 / 60;
 	max_steps: i32 = 1;

+ 5 - 5
base/Sources/RenderPathBase.ts

@@ -18,13 +18,13 @@ class RenderPathBase {
 	}
 
 	///if arm_voxels
-	static init_voxels = (targetName: string = "voxels") => {
+	static init_voxels = (target_name: string = "voxels") => {
 		if (config_raw.rp_gi != true || RenderPathBase.voxels_created) return;
 		RenderPathBase.voxels_created = true;
 
 		{
 			let t: render_target_t = render_target_create();
-			t.name = targetName;
+			t.name = target_name;
 			t.format = "R8";
 			t.width = RenderPathBase.voxels_res;
 			t.height = RenderPathBase.voxels_res;
@@ -216,9 +216,9 @@ class RenderPathBase {
 			}
 
 			let bloom_radius: f32 = 6.5;
-			let min_dim: f32 = Math.min(render_path_current_w,render_path_current_h);
-			let log_min_dim: f32 = Math.max(1.0, Math.log2(min_dim) + (bloom_radius - 8.0));
-			let num_mips: i32 = Math.floor(log_min_dim);
+			let min_dim: f32 = math_min(render_path_current_w, render_path_current_h);
+			let log_min_dim: f32 = math_max(1.0, math_log2(min_dim) + (bloom_radius - 8.0));
+			let num_mips: i32 = math_floor(log_min_dim);
 			RenderPathBase.bloom_sample_scale = 0.5 + log_min_dim - num_mips;
 
 			for (let i: i32 = 0; i < num_mips; ++i) {

+ 1 - 1
base/Sources/RenderPathRaytrace.ts

@@ -148,7 +148,7 @@ class RenderPathRaytrace {
 	}
 
 	static build_data = () => {
-		if (context_raw.merged_object == null) UtilMesh.merge_mesh();
+		if (context_raw.merged_object == null) util_mesh_merge();
 		///if is_paint
 		let mo: mesh_object_t = !context_layer_filter_used() ? context_raw.merged_object : context_raw.paint_object;
 		///else

+ 0 - 524
base/Sources/ShaderFunctions.ts

@@ -1,524 +0,0 @@
-
-class ShaderFunctions {
-
-	static str_tex_checker: string = `
-vec3 tex_checker(const vec3 co, const vec3 col1, const vec3 col2, const float scale) {
-	// Prevent precision issues on unit coordinates
-	vec3 p = (co + 0.000001 * 0.999999) * scale;
-	float xi = abs(floor(p.x));
-	float yi = abs(floor(p.y));
-	float zi = abs(floor(p.z));
-	bool check = ((mod(xi, 2.0) == mod(yi, 2.0)) == bool(mod(zi, 2.0)));
-	return check ? col1 : col2;
-}
-float tex_checker_f(const vec3 co, const float scale) {
-	vec3 p = (co + 0.000001 * 0.999999) * scale;
-	float xi = abs(floor(p.x));
-	float yi = abs(floor(p.y));
-	float zi = abs(floor(p.z));
-	return float((mod(xi, 2.0) == mod(yi, 2.0)) == bool(mod(zi, 2.0)));
-}
-`;
-
-	// Created by inigo quilez - iq/2013
-	// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
-	static str_tex_voronoi: string = `
-vec4 tex_voronoi(const vec3 x, textureArg(snoise256)) {
-	vec3 p = floor(x);
-	vec3 f = fract(x);
-	float id = 0.0;
-	float res = 100.0;
-	for (int k = -1; k <= 1; k++)
-	for (int j = -1; j <= 1; j++)
-	for (int i = -1; i <= 1; i++) {
-		vec3 b = vec3(float(i), float(j), float(k));
-		vec3 pb = p + b;
-		vec3 r = vec3(b) - f + texture(snoise256, (pb.xy + vec2(3.0, 1.0) * pb.z + 0.5) / 256.0).xyz;
-		float d = dot(r, r);
-		if (d < res) {
-			id = dot(p + b, vec3(1.0, 57.0, 113.0));
-			res = d;
-		}
-	}
-	vec3 col = 0.5 + 0.5 * cos(id * 0.35 + vec3(0.0, 1.0, 2.0));
-	return vec4(col, sqrt(res));
-}
-`;
-
-	// By Morgan McGuire @morgan3d, http://graphicscodex.com Reuse permitted under the BSD license.
-	// https://www.shadertoy.com/view/4dS3Wd
-	static str_tex_noise: string = `
-float hash(float n) { return fract(sin(n) * 1e4); }
-float tex_noise_f(vec3 x) {
-    const vec3 step = vec3(110, 241, 171);
-    vec3 i = floor(x);
-    vec3 f = fract(x);
-    float n = dot(i, step);
-    vec3 u = f * f * (3.0 - 2.0 * f);
-    return mix(mix(mix(hash(n + dot(step, vec3(0, 0, 0))), hash(n + dot(step, vec3(1, 0, 0))), u.x),
-                   mix(hash(n + dot(step, vec3(0, 1, 0))), hash(n + dot(step, vec3(1, 1, 0))), u.x), u.y),
-               mix(mix(hash(n + dot(step, vec3(0, 0, 1))), hash(n + dot(step, vec3(1, 0, 1))), u.x),
-                   mix(hash(n + dot(step, vec3(0, 1, 1))), hash(n + dot(step, vec3(1, 1, 1))), u.x), u.y), u.z);
-}
-float tex_noise(vec3 p) {
-	p *= 1.25;
-	float f = 0.5 * tex_noise_f(p); p *= 2.01;
-	f += 0.25 * tex_noise_f(p); p *= 2.02;
-	f += 0.125 * tex_noise_f(p); p *= 2.03;
-	f += 0.0625 * tex_noise_f(p);
-	return 1.0 - f;
-}
-`;
-
-	// Based on noise created by Nikita Miropolskiy, nikat/2013
-	// Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
-	static str_tex_musgrave: string = `
-vec3 random3(const vec3 c) {
-	float j = 4096.0 * sin(dot(c, vec3(17.0, 59.4, 15.0)));
-	vec3 r;
-	r.z = fract(512.0 * j);
-	j *= 0.125;
-	r.x = fract(512.0 * j);
-	j *= 0.125;
-	r.y = fract(512.0 * j);
-	return r - 0.5;
-}
-float tex_musgrave_f(const vec3 p) {
-	const float F3 = 0.3333333;
-	const float G3 = 0.1666667;
-	vec3 s = floor(p + dot(p, vec3(F3, F3, F3)));
-	vec3 x = p - s + dot(s, vec3(G3, G3, G3));
-	vec3 e = step(vec3(0.0, 0.0, 0.0), x - x.yzx);
-	vec3 i1 = e*(1.0 - e.zxy);
-	vec3 i2 = 1.0 - e.zxy*(1.0 - e);
-	vec3 x1 = x - i1 + G3;
-	vec3 x2 = x - i2 + 2.0*G3;
-	vec3 x3 = x - 1.0 + 3.0*G3;
-	vec4 w, d;
-	w.x = dot(x, x);
-	w.y = dot(x1, x1);
-	w.z = dot(x2, x2);
-	w.w = dot(x3, x3);
-	w = max(0.6 - w, 0.0);
-	d.x = dot(random3(s), x);
-	d.y = dot(random3(s + i1), x1);
-	d.z = dot(random3(s + i2), x2);
-	d.w = dot(random3(s + 1.0), x3);
-	w *= w;
-	w *= w;
-	d *= w;
-	return clamp(dot(d, vec4(52.0, 52.0, 52.0, 52.0)), 0.0, 1.0);
-}
-`;
-
-	static str_hue_sat: string = `
-vec3 hsv_to_rgb(const vec3 c) {
-	const vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
-	vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
-	return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
-}
-vec3 rgb_to_hsv(const vec3 c) {
-	const vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
-	vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
-	vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
-	float d = q.x - min(q.w, q.y);
-	float e = 1.0e-10;
-	return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
-}
-vec3 hue_sat(const vec3 col, const vec4 shift) {
-	vec3 hsv = rgb_to_hsv(col);
-	hsv.x += shift.x;
-	hsv.y *= shift.y;
-	hsv.z *= shift.z;
-	return mix(hsv_to_rgb(hsv), col, shift.w);
-}
-`;
-
-	// https://twitter.com/Donzanoid/status/903424376707657730
-	static str_wavelength_to_rgb: string = `
-vec3 wavelength_to_rgb(const float t) {
-	vec3 r = t * 2.1 - vec3(1.8, 1.14, 0.3);
-	return 1.0 - r * r;
-}
-`;
-
-	static str_tex_magic: string = `
-vec3 tex_magic(const vec3 p) {
-	float a = 1.0 - (sin(p.x) + sin(p.y));
-	float b = 1.0 - sin(p.x - p.y);
-	float c = 1.0 - sin(p.x + p.y);
-	return vec3(a, b, c);
-}
-float tex_magic_f(const vec3 p) {
-	vec3 c = tex_magic(p);
-	return (c.x + c.y + c.z) / 3.0;
-}
-`;
-
-	static str_tex_brick: string = `
-float tex_brick_noise(int n) { /* fast integer noise */
-	int nn;
-	n = (n >> 13) ^ n;
-	nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
-	return 0.5f * float(nn) / 1073741824.0;
-}
-vec3 tex_brick(vec3 p, const vec3 c1, const vec3 c2, const vec3 c3) {
-	vec3 brickSize = vec3(0.9, 0.49, 0.49);
-	vec3 mortarSize = vec3(0.05, 0.1, 0.1);
-	p /= brickSize / 2;
-	if (fract(p.y * 0.5) > 0.5) p.x += 0.5;
-	float col = floor(p.x / (brickSize.x + (mortarSize.x * 2.0)));
-	float row = p.y;
-	p = fract(p);
-	vec3 b = step(p, 1.0 - mortarSize);
-	float tint = min(max(tex_brick_noise((int(col) << 16) + (int(row) & 0xFFFF)), 0.0), 1.0);
-	return mix(c3, mix(c1, c2, tint), b.x * b.y * b.z);
-}
-float tex_brick_f(vec3 p) {
-	p /= vec3(0.9, 0.49, 0.49) / 2;
-	if (fract(p.y * 0.5) > 0.5) p.x += 0.5;
-	p = fract(p);
-	vec3 b = step(p, vec3(0.95, 0.9, 0.9));
-	return mix(1.0, 0.0, b.x * b.y * b.z);
-}
-`;
-
-	static str_tex_wave: string = `
-float tex_wave_f(const vec3 p) {
-	return 1.0 - sin((p.x + p.y) * 10.0);
-}
-`;
-
-	static str_brightcontrast: string = `
-vec3 brightcontrast(const vec3 col, const float bright, const float contr) {
-	float a = 1.0 + contr;
-	float b = bright - contr * 0.5;
-	return max(a * col + b, 0.0);
-}
-`;
-
-//
-
-	///if arm_voxels
-	static str_trace_ao: string = `
-float traceConeAO(sampler3D voxels, const vec3 origin, vec3 dir, const float aperture, const float maxDist, const float offset) {
-	const ivec3 voxelgiResolution = ivec3(256, 256, 256);
-	const float voxelgiStep = 1.0;
-	const float VOXEL_SIZE = (2.0 / voxelgiResolution.x) * voxelgiStep;
-	dir = normalize(dir);
-	float sampleCol = 0.0;
-	float dist = offset;
-	float diam = dist * aperture;
-	vec3 samplePos;
-	while (sampleCol < 1.0 && dist < maxDist) {
-		samplePos = dir * dist + origin;
-		float mip = max(log2(diam * voxelgiResolution.x), 0);
-		float mipSample = textureLod(voxels, samplePos * 0.5 + vec3(0.5, 0.5, 0.5), mip).r;
-		sampleCol += (1 - sampleCol) * mipSample;
-		dist += max(diam / 2, VOXEL_SIZE);
-		diam = dist * aperture;
-	}
-	return sampleCol;
-}
-vec3 tangent(const vec3 n) {
-	vec3 t1 = cross(n, vec3(0, 0, 1));
-	vec3 t2 = cross(n, vec3(0, 1, 0));
-	if (length(t1) > length(t2)) return normalize(t1);
-	else return normalize(t2);
-}
-float traceAO(const vec3 origin, const vec3 normal, const float vrange, const float voffset) {
-	const float angleMix = 0.5f;
-	const float aperture = 0.55785173935;
-	vec3 o1 = normalize(tangent(normal));
-	vec3 o2 = normalize(cross(o1, normal));
-	vec3 c1 = 0.5f * (o1 + o2);
-	vec3 c2 = 0.5f * (o1 - o2);
-	float MAX_DISTANCE = 1.73205080757 * 2.0 * vrange;
-	const ivec3 voxelgiResolution = ivec3(256, 256, 256);
-	const float voxelgiStep = 1.0;
-	const float VOXEL_SIZE = (2.0 / voxelgiResolution.x) * voxelgiStep;
-	float offset = 1.5 * VOXEL_SIZE * 2.5 * voffset;
-	float col = traceConeAO(voxels, origin, normal, aperture, MAX_DISTANCE, offset);
-	col += traceConeAO(voxels, origin, mix(normal, o1, angleMix), aperture, MAX_DISTANCE, offset);
-	col += traceConeAO(voxels, origin, mix(normal, o2, angleMix), aperture, MAX_DISTANCE, offset);
-	col += traceConeAO(voxels, origin, mix(normal, -c1, angleMix), aperture, MAX_DISTANCE, offset);
-	col += traceConeAO(voxels, origin, mix(normal, -c2, angleMix), aperture, MAX_DISTANCE, offset);
-	col += traceConeAO(voxels, origin, mix(normal, -o1, angleMix), aperture, MAX_DISTANCE, offset);
-	col += traceConeAO(voxels, origin, mix(normal, -o2, angleMix), aperture, MAX_DISTANCE, offset);
-	col += traceConeAO(voxels, origin, mix(normal, c1, angleMix), aperture, MAX_DISTANCE, offset);
-	col += traceConeAO(voxels, origin, mix(normal, c2, angleMix), aperture, MAX_DISTANCE, offset);
-	return col / 9.0;
-}
-`;
-	///end
-
-	static str_cotangent_frame: string = `
-mat3 cotangentFrame(const vec3 n, const vec3 p, const vec2 duv1, const vec2 duv2) {
-	vec3 dp1 = dFdx(p);
-	vec3 dp2 = dFdy(p);
-	vec3 dp2perp = cross(dp2, n);
-	vec3 dp1perp = cross(n, dp1);
-	vec3 t = dp2perp * duv1.x + dp1perp * duv2.x;
-	vec3 b = dp2perp * duv1.y + dp1perp * duv2.y;
-	float invmax = inversesqrt(max(dot(t, t), dot(b, b)));
-	return mat3(t * invmax, b * invmax, n);
-}
-mat3 cotangentFrame(const vec3 n, const vec3 p, const vec2 texCoord) {
-	return cotangentFrame(n, p, dFdx(texCoord), dFdy(texCoord));
-}
-`;
-
-	static str_octahedron_wrap: string = `
-vec2 octahedronWrap(const vec2 v) {
-	return (1.0 - abs(v.yx)) * (vec2(v.x >= 0.0 ? 1.0 : -1.0, v.y >= 0.0 ? 1.0 : -1.0));
-}
-`;
-
-	static str_pack_float_int16: string = `
-float packFloatInt16(const float f, const uint i) {
-	const float prec = float(1 << 16);
-	const float maxi = float(1 << 4);
-	const float precMinusOne = prec - 1.0;
-	const float t1 = ((prec / maxi) - 1.0) / precMinusOne;
-	const float t2 = (prec / maxi) / precMinusOne;
-	return t1 * f + t2 * float(i);
-}
-`;
-
-	///if arm_skin
-	static str_get_skinning_dual_quat: string = `
-void getSkinningDualQuat(const ivec4 bone, vec4 weight, out vec4 A, inout vec4 B) {
-	ivec4 bonei = bone * 2;
-	mat4 matA = mat4(
-		skinBones[bonei.x],
-		skinBones[bonei.y],
-		skinBones[bonei.z],
-		skinBones[bonei.w]);
-	mat4 matB = mat4(
-		skinBones[bonei.x + 1],
-		skinBones[bonei.y + 1],
-		skinBones[bonei.z + 1],
-		skinBones[bonei.w + 1]);
-	weight.xyz *= sign(mul(matA, matA[3])).xyz;
-	A = mul(weight, matA);
-	B = mul(weight, matB);
-	float invNormA = 1.0 / length(A);
-	A *= invNormA;
-	B *= invNormA;
-}
-`;
-	///end
-
-	static str_create_basis: string = `
-void createBasis(vec3 normal, out vec3 tangent, out vec3 binormal) {
-	tangent = normalize(cameraRight - normal * dot(cameraRight, normal));
-	binormal = cross(tangent, normal);
-}
-`;
-
-	static get str_sh_irradiance(): string {
-		///if krom_metal
-		return `vec3 shIrradiance(const vec3 nor, constant vec4 shirr[7]) {
-	const float c1 = 0.429043;
-	const float c2 = 0.511664;
-	const float c3 = 0.743125;
-	const float c4 = 0.886227;
-	const float c5 = 0.247708;
-	vec3 cl00 = vec3(shirr[0].x, shirr[0].y, shirr[0].z);
-	vec3 cl1m1 = vec3(shirr[0].w, shirr[1].x, shirr[1].y);
-	vec3 cl10 = vec3(shirr[1].z, shirr[1].w, shirr[2].x);
-	vec3 cl11 = vec3(shirr[2].y, shirr[2].z, shirr[2].w);
-	vec3 cl2m2 = vec3(shirr[3].x, shirr[3].y, shirr[3].z);
-	vec3 cl2m1 = vec3(shirr[3].w, shirr[4].x, shirr[4].y);
-	vec3 cl20 = vec3(shirr[4].z, shirr[4].w, shirr[5].x);
-	vec3 cl21 = vec3(shirr[5].y, shirr[5].z, shirr[5].w);
-	vec3 cl22 = vec3(shirr[6].x, shirr[6].y, shirr[6].z);
-	return (
-		c1 * cl22 * (nor.y * nor.y - (-nor.z) * (-nor.z)) +
-		c3 * cl20 * nor.x * nor.x +
-		c4 * cl00 -
-		c5 * cl20 +
-		2.0 * c1 * cl2m2 * nor.y * (-nor.z) +
-		2.0 * c1 * cl21  * nor.y * nor.x +
-		2.0 * c1 * cl2m1 * (-nor.z) * nor.x +
-		2.0 * c2 * cl11  * nor.y +
-		2.0 * c2 * cl1m1 * (-nor.z) +
-		2.0 * c2 * cl10  * nor.x
-	);
-}
-`;
-		///else
-		return `vec3 shIrradiance(const vec3 nor, const vec4 shirr[7]) {
-	const float c1 = 0.429043;
-	const float c2 = 0.511664;
-	const float c3 = 0.743125;
-	const float c4 = 0.886227;
-	const float c5 = 0.247708;
-	vec3 cl00 = vec3(shirr[0].x, shirr[0].y, shirr[0].z);
-	vec3 cl1m1 = vec3(shirr[0].w, shirr[1].x, shirr[1].y);
-	vec3 cl10 = vec3(shirr[1].z, shirr[1].w, shirr[2].x);
-	vec3 cl11 = vec3(shirr[2].y, shirr[2].z, shirr[2].w);
-	vec3 cl2m2 = vec3(shirr[3].x, shirr[3].y, shirr[3].z);
-	vec3 cl2m1 = vec3(shirr[3].w, shirr[4].x, shirr[4].y);
-	vec3 cl20 = vec3(shirr[4].z, shirr[4].w, shirr[5].x);
-	vec3 cl21 = vec3(shirr[5].y, shirr[5].z, shirr[5].w);
-	vec3 cl22 = vec3(shirr[6].x, shirr[6].y, shirr[6].z);
-	return (
-		c1 * cl22 * (nor.y * nor.y - (-nor.z) * (-nor.z)) +
-		c3 * cl20 * nor.x * nor.x +
-		c4 * cl00 -
-		c5 * cl20 +
-		2.0 * c1 * cl2m2 * nor.y * (-nor.z) +
-		2.0 * c1 * cl21  * nor.y * nor.x +
-		2.0 * c1 * cl2m1 * (-nor.z) * nor.x +
-		2.0 * c2 * cl11  * nor.y +
-		2.0 * c2 * cl1m1 * (-nor.z) +
-		2.0 * c2 * cl10  * nor.x
-	);
-}
-`;
-///end
-	}
-
-	static str_envmap_equirect: string = `
-vec2 envMapEquirect(const vec3 normal, const float angle) {
-	const float PI = 3.1415926535;
-	const float PI2 = PI * 2.0;
-	float phi = acos(normal.z);
-	float theta = atan2(-normal.y, normal.x) + PI + angle;
-	return vec2(theta / PI2, phi / PI);
-}
-`;
-
-	// Linearly Transformed Cosines
-	// https://eheitzresearch.wordpress.com/415-2/
-	static str_ltc_evaluate: string = `
-float integrateEdge(vec3 v1, vec3 v2) {
-	float cosTheta = dot(v1, v2);
-	float theta = acos(cosTheta);
-	float res = cross(v1, v2).z * ((theta > 0.001) ? theta / sin(theta) : 1.0);
-	return res;
-}
-float ltcEvaluate(vec3 N, vec3 V, float dotNV, vec3 P, mat3 Minv, vec3 points0, vec3 points1, vec3 points2, vec3 points3) {
-	vec3 T1 = normalize(V - N * dotNV);
-	vec3 T2 = cross(N, T1);
-	Minv = mul(transpose(mat3(T1, T2, N)), Minv);
-	vec3 L0 = mul((points0 - P), Minv);
-	vec3 L1 = mul((points1 - P), Minv);
-	vec3 L2 = mul((points2 - P), Minv);
-	vec3 L3 = mul((points3 - P), Minv);
-	vec3 L4 = vec3(0.0, 0.0, 0.0);
-	int n = 0;
-	int config = 0;
-	if (L0.z > 0.0) config += 1;
-	if (L1.z > 0.0) config += 2;
-	if (L2.z > 0.0) config += 4;
-	if (L3.z > 0.0) config += 8;
-	if (config == 0) {}
-	else if (config == 1) {
-		n = 3;
-		L1 = -L1.z * L0 + L0.z * L1;
-		L2 = -L3.z * L0 + L0.z * L3;
-	}
-	else if (config == 2) {
-		n = 3;
-		L0 = -L0.z * L1 + L1.z * L0;
-		L2 = -L2.z * L1 + L1.z * L2;
-	}
-	else if (config == 3) {
-		n = 4;
-		L2 = -L2.z * L1 + L1.z * L2;
-		L3 = -L3.z * L0 + L0.z * L3;
-	}
-	else if (config == 4) {
-		n = 3;
-		L0 = -L3.z * L2 + L2.z * L3;
-		L1 = -L1.z * L2 + L2.z * L1;
-	}
-	else if (config == 5) { n = 0; }
-	else if (config == 6) {
-		n = 4;
-		L0 = -L0.z * L1 + L1.z * L0;
-		L3 = -L3.z * L2 + L2.z * L3;
-	}
-	else if (config == 7) {
-		n = 5;
-		L4 = -L3.z * L0 + L0.z * L3;
-		L3 = -L3.z * L2 + L2.z * L3;
-	}
-	else if (config == 8) {
-		n = 3;
-		L0 = -L0.z * L3 + L3.z * L0;
-		L1 = -L2.z * L3 + L3.z * L2;
-		L2 =  L3;
-	}
-	else if (config == 9) {
-		n = 4;
-		L1 = -L1.z * L0 + L0.z * L1;
-		L2 = -L2.z * L3 + L3.z * L2;
-	}
-	else if (config == 10) { n = 0; }
-	else if (config == 11) {
-		n = 5;
-		L4 = L3;
-		L3 = -L2.z * L3 + L3.z * L2;
-		L2 = -L2.z * L1 + L1.z * L2;
-	}
-	else if (config == 12) {
-		n = 4;
-		L1 = -L1.z * L2 + L2.z * L1;
-		L0 = -L0.z * L3 + L3.z * L0;
-	}
-	else if (config == 13) {
-		n = 5;
-		L4 = L3;
-		L3 = L2;
-		L2 = -L1.z * L2 + L2.z * L1;
-		L1 = -L1.z * L0 + L0.z * L1;
-	}
-	else if (config == 14) {
-		n = 5;
-		L4 = -L0.z * L3 + L3.z * L0;
-		L0 = -L0.z * L1 + L1.z * L0;
-	}
-	else if (config == 15) { n = 4; }
-	if (n == 0) return 0.0;
-	if (n == 3) L3 = L0;
-	if (n == 4) L4 = L0;
-	L0 = normalize(L0);
-	L1 = normalize(L1);
-	L2 = normalize(L2);
-	L3 = normalize(L3);
-	L4 = normalize(L4);
-	float sum = 0.0;
-	sum += integrateEdge(L0, L1);
-	sum += integrateEdge(L1, L2);
-	sum += integrateEdge(L2, L3);
-	if (n >= 4) sum += integrateEdge(L3, L4);
-	if (n == 5) sum += integrateEdge(L4, L0);
-	return max(0.0, -sum);
-}
-`;
-
-	static str_get_pos_from_depth: string = `
-vec3 get_pos_from_depth(vec2 uv, mat4 invVP, textureArg(gbufferD)) {
-	#if defined(HLSL) || defined(METAL) || defined(SPIRV)
-	float depth = textureLod(gbufferD, vec2(uv.x, 1.0 - uv.y), 0.0).r;
-	#else
-	float depth = textureLod(gbufferD, uv, 0.0).r;
-	#endif
-	vec4 wpos = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
-	wpos = mul(wpos, invVP);
-	return wpos.xyz / wpos.w;
-}
-`;
-
-	static str_get_nor_from_depth: string = `
-vec3 get_nor_from_depth(vec3 p0, vec2 uv, mat4 invVP, vec2 texStep, textureArg(gbufferD)) {
-	vec3 p1 = get_pos_from_depth(uv + vec2(texStep.x * 4.0, 0.0), invVP, texturePass(gbufferD));
-	vec3 p2 = get_pos_from_depth(uv + vec2(0.0, texStep.y * 4.0), invVP, texturePass(gbufferD));
-	return normalize(cross(p2 - p0, p1 - p0));
-}
-`;
-
-}

+ 22 - 22
base/Sources/TabBrowser.ts

@@ -9,19 +9,19 @@ class TabBrowser {
 	static show_directory = (directory: string) => {
 		TabBrowser.hpath.text = directory;
 		TabBrowser.hsearch.text = "";
-		UIBase.htabs[tab_area_t.STATUS].position = 0;
+		ui_base_htabs[tab_area_t.STATUS].position = 0;
 	}
 
 	static draw = (htab: zui_handle_t) => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 		let statush: i32 = config_raw.layout[layout_size_t.STATUS_H];
-		if (zui_tab(htab, tr("Browser")) && statush > UIStatus.default_status_h * zui_SCALE(ui)) {
+		if (zui_tab(htab, tr("Browser")) && statush > ui_status_default_status_h * zui_SCALE(ui)) {
 
 			if (config_raw.bookmarks == null) {
 				config_raw.bookmarks = [];
 			}
 
-			let bookmarks_w: i32 = Math.floor(100 * zui_SCALE(ui));
+			let bookmarks_w: i32 = math_floor(100 * zui_SCALE(ui));
 
 			if (TabBrowser.hpath.text == "" && config_raw.bookmarks.length > 0) { // Init to first bookmark
 				TabBrowser.hpath.text = config_raw.bookmarks[0];
@@ -83,15 +83,15 @@ class TabBrowser {
 			let _y: f32 = ui._y;
 			ui._x = bookmarks_w;
 			ui._w -= bookmarks_w;
-			UIFiles.file_browser(ui, TabBrowser.hpath, false, true, TabBrowser.hsearch.text, refresh, (file: string) => {
+			ui_files_file_browser(ui, TabBrowser.hpath, false, true, TabBrowser.hsearch.text, refresh, (file: string) => {
 				let file_name: string = file.substr(file.lastIndexOf(path_sep) + 1);
 				if (file_name != "..") {
-					UIMenu.draw((ui: zui_t) => {
-						if (UIMenu.menu_button(ui, tr("Import"))) {
+					ui_menu_draw((ui: zui_t) => {
+						if (ui_menu_button(ui, tr("Import"))) {
 							ImportAsset.run(file);
 						}
 						if (path_is_texture(file)) {
-							if (UIMenu.menu_button(ui, tr("Set as Envmap"))) {
+							if (ui_menu_button(ui, tr("Set as Envmap"))) {
 								ImportAsset.run(file, -1.0, -1.0, true, true, () => {
 									base_notify_on_next_frame(() => {
 										let asset_index: i32 = -1;
@@ -109,7 +109,7 @@ class TabBrowser {
 							}
 
 							///if (is_paint || is_sculpt)
-							if (UIMenu.menu_button(ui, tr("Set as Mask"))) {
+							if (ui_menu_button(ui, tr("Set as Mask"))) {
 								ImportAsset.run(file, -1.0, -1.0, true, true, () => {
 									base_notify_on_next_frame(() => {
 										let asset_index: i32 = -1;
@@ -128,7 +128,7 @@ class TabBrowser {
 							///end
 
 							///if is_paint
-							if (UIMenu.menu_button(ui, tr("Set as Color ID Map"))) {
+							if (ui_menu_button(ui, tr("Set as Color ID Map"))) {
 								ImportAsset.run(file, -1.0, -1.0, true, true, () => {
 									base_notify_on_next_frame(() => {
 										let asset_index: i32 = -1;
@@ -141,9 +141,9 @@ class TabBrowser {
 										if (asset_index != -1) {
 											context_raw.colorid_handle.position = asset_index;
 											context_raw.colorid_picked = false;
-											UIToolbar.toolbar_handle.redraws = 1;
+											ui_toolbar_handle.redraws = 1;
 											if (context_raw.tool == workspace_tool_t.COLORID) {
-												UIHeader.header_handle.redraws = 2;
+												ui_header_handle.redraws = 2;
 												context_raw.ddirty = 2;
 											}
 										}
@@ -152,7 +152,7 @@ class TabBrowser {
 							}
 							///end
 						}
-						if (UIMenu.menu_button(ui, tr("Open Externally"))) {
+						if (ui_menu_button(ui, tr("Open Externally"))) {
 							file_start(file);
 						}
 					}, path_is_texture(file) ? 5 : 2);
@@ -182,22 +182,22 @@ class TabBrowser {
 
 			if (zui_button(tr("Disk"), zui_align_t.LEFT)) {
 				///if krom_android
-				UIMenu.draw((ui: zui_t) => {
-					if (UIMenu.menu_button(ui, tr("Download"))) {
-						TabBrowser.hpath.text = UIFiles.default_path;
+				ui_menu_draw((ui: zui_t) => {
+					if (ui_menu_button(ui, tr("Download"))) {
+						TabBrowser.hpath.text = ui_files_default_path;
 					}
-					if (UIMenu.menu_button(ui, tr("Pictures"))) {
+					if (ui_menu_button(ui, tr("Pictures"))) {
 						TabBrowser.hpath.text = "/storage/emulated/0/Pictures";
 					}
-					if (UIMenu.menu_button(ui, tr("Camera"))) {
+					if (ui_menu_button(ui, tr("Camera"))) {
 						TabBrowser.hpath.text = "/storage/emulated/0/DCIM/Camera";
 					}
-					if (UIMenu.menu_button(ui, tr("Projects"))) {
+					if (ui_menu_button(ui, tr("Projects"))) {
 						TabBrowser.hpath.text = krom_save_path();
 					}
 				}, 4);
 				///else
-				TabBrowser.hpath.text = UIFiles.default_path;
+				TabBrowser.hpath.text = ui_files_default_path;
 				///end
 			}
 
@@ -209,8 +209,8 @@ class TabBrowser {
 				}
 
 				if (ui.is_hovered && ui.input_released_r) {
-					UIMenu.draw((ui: zui_t) => {
-						if (UIMenu.menu_button(ui, tr("Delete"))) {
+					ui_menu_draw((ui: zui_t) => {
+						if (ui_menu_button(ui, tr("Delete"))) {
 							array_remove(config_raw.bookmarks, b);
 							config_save();
 						}

+ 16 - 16
base/Sources/TabBrushes.ts

@@ -4,7 +4,7 @@
 class TabBrushes {
 
 	static draw = (htab: zui_handle_t) => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 		if (zui_tab(htab, tr("Brushes"))) {
 			zui_begin_sticky();
 			zui_row([1 / 4, 1 / 4, 1 / 4]);
@@ -12,21 +12,21 @@ class TabBrushes {
 				context_raw.brush = SlotBrush.create();
 				project_brushes.push(context_raw.brush);
 				MakeMaterial.parse_brush();
-				UINodes.hwnd.redraws = 2;
+				ui_nodes_hwnd.redraws = 2;
 			}
 			if (zui_button(tr("Import"))) {
 				project_import_brush();
 			}
 			if (zui_button(tr("Nodes"))) {
-				UIBase.show_brush_nodes();
+				ui_base_show_brush_nodes();
 			}
 			zui_end_sticky();
 			zui_separator(3, false);
 
-			let slotw: i32 = Math.floor(51 * zui_SCALE(ui));
-			let num: i32 = Math.floor(config_raw.layout[layout_size_t.SIDEBAR_W] / slotw);
+			let slotw: i32 = math_floor(51 * zui_SCALE(ui));
+			let num: i32 = math_floor(config_raw.layout[layout_size_t.SIDEBAR_W] / slotw);
 
-			for (let row: i32 = 0; row < Math.floor(Math.ceil(project_brushes.length / num)); ++row) {
+			for (let row: i32 = 0; row < math_floor(math_ceil(project_brushes.length / num)); ++row) {
 				let mult: i32 = config_raw.show_asset_names ? 2 : 1;
 				let ar: f32[] = [];
 				for (let i: i32 = 0; i < num * mult; ++i) ar.push(1 / num);
@@ -37,7 +37,7 @@ class TabBrushes {
 				if (row > 0) ui._y += off;
 
 				for (let j: i32 = 0; j < num; ++j) {
-					let imgw: i32 = Math.floor(50 * zui_SCALE(ui));
+					let imgw: i32 = math_floor(50 * zui_SCALE(ui));
 					let i: i32 = j + row * num;
 					if (i >= project_brushes.length) {
 						zui_end_element(imgw);
@@ -51,7 +51,7 @@ class TabBrushes {
 						// Zui.fill(1, -2, img.width + 3, img.height + 3, ui.t.HIGHLIGHT_COL); // TODO
 						let off: i32 = row % 2 == 1 ? 1 : 0;
 						let w: i32 = 50;
-						if (config_raw.window_scale > 1) w += Math.floor(config_raw.window_scale * 2);
+						if (config_raw.window_scale > 1) w += math_floor(config_raw.window_scale * 2);
 						zui_fill(-1,         -2, w + 3,       2, ui.t.HIGHLIGHT_COL);
 						zui_fill(-1,    w - off, w + 3, 2 + off, ui.t.HIGHLIGHT_COL);
 						zui_fill(-1,         -2,     2,   w + 3, ui.t.HIGHLIGHT_COL);
@@ -64,7 +64,7 @@ class TabBrushes {
 					let state: zui_state_t = project_brushes[i].preview_ready ? zui_image(img) : zui_image(resource_get("icons.k"), -1, -1.0, tile * 5, tile, tile, tile);
 					if (state == zui_state_t.STARTED) {
 						if (context_raw.brush != project_brushes[i]) context_select_brush(i);
-						if (time_time() - context_raw.select_time < 0.25) UIBase.show_brush_nodes();
+						if (time_time() - context_raw.select_time < 0.25) ui_base_show_brush_nodes();
 						context_raw.select_time = time_time();
 						// app_drag_off_x = -(mouse_x - uix - ui._windowX - 3);
 						// app_drag_off_y = -(mouse_y - uiy - ui._windowY + 1);
@@ -73,27 +73,27 @@ class TabBrushes {
 					if (ui.is_hovered && ui.input_released_r) {
 						context_select_brush(i);
 						let add: i32 = project_brushes.length > 1 ? 1 : 0;
-						UIMenu.draw((ui: zui_t) => {
+						ui_menu_draw((ui: zui_t) => {
 							//let b: SlotBrushRaw = brushes[i];
 
-							if (UIMenu.menu_button(ui, tr("Export"))) {
+							if (ui_menu_button(ui, tr("Export"))) {
 								context_select_brush(i);
 								BoxExport.show_brush();
 							}
 
-							if (UIMenu.menu_button(ui, tr("Duplicate"))) {
+							if (ui_menu_button(ui, tr("Duplicate"))) {
 								let _init = () => {
 									context_raw.brush = SlotBrush.create();
 									project_brushes.push(context_raw.brush);
 									let cloned: any = json_parse(json_stringify(project_brushes[i].canvas));
 									context_raw.brush.canvas = cloned;
 									context_set_brush(context_raw.brush);
-									UtilRender.make_brush_preview();
+									util_render_make_brush_preview();
 								}
 								app_notify_on_init(_init);
 							}
 
-							if (project_brushes.length > 1 && UIMenu.menu_button(ui, tr("Delete"), "delete")) {
+							if (project_brushes.length > 1 && ui_menu_button(ui, tr("Delete"), "delete")) {
 								TabBrushes.delete_brush(project_brushes[i]);
 							}
 						}, 2 + add);
@@ -105,7 +105,7 @@ class TabBrushes {
 								let _brush: SlotBrushRaw = context_raw.brush;
 								context_raw.brush = project_brushes[i];
 								MakeMaterial.parse_brush();
-								UtilRender.make_brush_preview();
+								util_render_make_brush_preview();
 								context_raw.brush = _brush;
 							});
 						}
@@ -143,7 +143,7 @@ class TabBrushes {
 		let i: i32 = project_brushes.indexOf(b);
 		context_select_brush(i == project_brushes.length - 1 ? i - 1 : i + 1);
 		project_brushes.splice(i, 1);
-		UIBase.hwnds[1].redraws = 2;
+		ui_base_hwnds[1].redraws = 2;
 	}
 }
 

+ 5 - 5
base/Sources/TabConsole.ts

@@ -2,13 +2,13 @@
 class TabConsole {
 
 	static draw = (htab: zui_handle_t) => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 
 		let title: string = console_message_timer > 0 ? console_message + "        " : tr("Console");
 		let color: i32 = console_message_timer > 0 ? console_message_color : -1;
 
 		let statush: i32 = config_raw.layout[layout_size_t.STATUS_H];
-		if (zui_tab(htab, title, false, color) && statush > UIStatus.default_status_h * zui_SCALE(ui)) {
+		if (zui_tab(htab, title, false, color) && statush > ui_status_default_status_h * zui_SCALE(ui)) {
 
 			zui_begin_sticky();
 			///if (krom_windows || krom_linux || krom_darwin) // Copy
@@ -32,8 +32,8 @@ class TabConsole {
 			}
 			if (zui_button(tr("Export"))) {
 				let str: string = console_last_traces.join("\n");
-				UIFiles.show("txt", true, false, (path: string) => {
-					let f: string = UIFiles.filename;
+				ui_files_show("txt", true, false, (path: string) => {
+					let f: string = ui_files_filename;
 					if (f == "") f = tr("untitled");
 					path = path + path_sep + f;
 					if (!path.endsWith(".txt")) path += ".txt";
@@ -53,7 +53,7 @@ class TabConsole {
 			let _fontSize: i32 = ui.font_size;
 			let f: g2_font_t = data_get_font("font_mono.ttf");
 			zui_set_font(ui, f);
-			ui.font_size = Math.floor(15 * zui_SCALE(ui));
+			ui.font_size = math_floor(15 * zui_SCALE(ui));
 			for (let t of console_last_traces) {
 				zui_text(t);
 			}

+ 17 - 17
base/Sources/TabFonts.ts

@@ -4,9 +4,9 @@
 class TabFonts {
 
 	static draw = (htab: zui_handle_t) => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 		let statush: i32 = config_raw.layout[layout_size_t.STATUS_H];
-		if (zui_tab(htab, tr("Fonts")) && statush > UIStatus.default_status_h * zui_SCALE(ui)) {
+		if (zui_tab(htab, tr("Fonts")) && statush > ui_status_default_status_h * zui_SCALE(ui)) {
 
 			zui_begin_sticky();
 			if (config_raw.touch_ui) {
@@ -20,16 +20,16 @@ class TabFonts {
 			if (ui.is_hovered) zui_tooltip(tr("Import font file"));
 
 			if (zui_button(tr("2D View"))) {
-				UIBase.show_2d_view(view_2d_type_t.FONT);
+				ui_base_show_2d_view(view_2d_type_t.FONT);
 			}
 			zui_end_sticky();
 			zui_separator(3, false);
 
-			let statusw: i32 = sys_width() - UIToolbar.toolbar_w - config_raw.layout[layout_size_t.SIDEBAR_W];
-			let slotw: i32 = Math.floor(51 * zui_SCALE(ui));
-			let num: i32 = Math.floor(statusw / slotw);
+			let statusw: i32 = sys_width() - ui_toolbar_w - config_raw.layout[layout_size_t.SIDEBAR_W];
+			let slotw: i32 = math_floor(51 * zui_SCALE(ui));
+			let num: i32 = math_floor(statusw / slotw);
 
-			for (let row: i32 = 0; row < Math.floor(Math.ceil(project_fonts.length / num)); ++row) {
+			for (let row: i32 = 0; row < math_floor(math_ceil(project_fonts.length / num)); ++row) {
 				let mult: i32 = config_raw.show_asset_names ? 2 : 1;
 				let ar: f32[] = [];
 				for (let i: i32 = 0; i < num * mult; ++i) ar.push(1 / num);
@@ -40,7 +40,7 @@ class TabFonts {
 				if (row > 0) ui._y += off;
 
 				for (let j: i32 = 0; j < num; ++j) {
-					let imgw: i32 = Math.floor(50 * zui_SCALE(ui));
+					let imgw: i32 = math_floor(50 * zui_SCALE(ui));
 					let i: i32 = j + row * num;
 					if (i >= project_fonts.length) {
 						zui_end_element(imgw);
@@ -53,7 +53,7 @@ class TabFonts {
 						// Zui.fill(1, -2, img.width + 3, img.height + 3, ui.t.HIGHLIGHT_COL); // TODO
 						let off: i32 = row % 2 == 1 ? 1 : 0;
 						let w: i32 = 50;
-						if (config_raw.window_scale > 1) w += Math.floor(config_raw.window_scale * 2);
+						if (config_raw.window_scale > 1) w += math_floor(config_raw.window_scale * 2);
 						zui_fill(-1,         -2, w + 3,       2, ui.t.HIGHLIGHT_COL);
 						zui_fill(-1,    w - off, w + 3, 2 + off, ui.t.HIGHLIGHT_COL);
 						zui_fill(-1,         -2,     2,   w + 3, ui.t.HIGHLIGHT_COL);
@@ -64,11 +64,11 @@ class TabFonts {
 					let tile: i32 = zui_SCALE(ui) > 1 ? 100 : 50;
 					let state: zui_state_t = zui_state_t.IDLE;
 					if (project_fonts[i].preview_ready) {
-						// g2_set_pipeline(UIView2D.pipe); // L8
+						// g2_set_pipeline(pipe); // L8
 						// ///if krom_opengl
-						// g4_set_pipeline(UIView2D.pipe);
+						// g4_set_pipeline(pipe);
 						// ///end
-						// g4_set_int(UIView2D.channelLocation, 1);
+						// g4_set_int(channelLocation, 1);
 						state = zui_image(img);
 						// g2_set_pipeline(null);
 					}
@@ -83,14 +83,14 @@ class TabFonts {
 							}
 							app_notify_on_init(_init);
 						}
-						if (time_time() - context_raw.select_time < 0.25) UIBase.show_2d_view(view_2d_type_t.FONT);
+						if (time_time() - context_raw.select_time < 0.25) ui_base_show_2d_view(view_2d_type_t.FONT);
 						context_raw.select_time = time_time();
 					}
 					if (ui.is_hovered && ui.input_released_r) {
 						context_select_font(i);
 						let add: i32 = project_fonts.length > 1 ? 1 : 0;
-						UIMenu.draw((ui: zui_t) => {
-							if (project_fonts.length > 1 && UIMenu.menu_button(ui, tr("Delete"), "delete") && project_fonts[i].file != "") {
+						ui_menu_draw((ui: zui_t) => {
+							if (project_fonts.length > 1 && ui_menu_button(ui, tr("Delete"), "delete") && project_fonts[i].file != "") {
 								TabFonts.delete_font(project_fonts[i]);
 							}
 						}, 0 + add);
@@ -100,7 +100,7 @@ class TabFonts {
 							app_notify_on_init(() => {
 								let _font: SlotFontRaw = context_raw.font;
 								context_raw.font = project_fonts[i];
-								UtilRender.make_font_preview();
+								util_render_make_font_preview();
 								context_raw.font = _font;
 							});
 						}
@@ -142,7 +142,7 @@ class TabFonts {
 			project_fonts.splice(i, 1);
 		}
 		app_notify_on_init(_init);
-		UIBase.hwnds[2].redraws = 2;
+		ui_base_hwnds[2].redraws = 2;
 	}
 }
 

+ 1 - 1
base/Sources/TabHistory.ts

@@ -4,7 +4,7 @@
 class TabHistory {
 
 	static draw = (htab: zui_handle_t) => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 		if (zui_tab(htab, tr("History"))) {
 			for (let i: i32 = 0; i < history_steps.length; ++i) {
 				let active: i32 = history_steps.length - 1 - history_redos;

+ 34 - 34
base/Sources/TabMaterials.ts

@@ -4,7 +4,7 @@
 class TabMaterials {
 
 	static draw = (htab: zui_handle_t) => {
-		let mini: bool = config_raw.layout[layout_size_t.SIDEBAR_W] <= UIBase.sidebar_mini_w;
+		let mini: bool = config_raw.layout[layout_size_t.SIDEBAR_W] <= ui_base_sidebar_mini_w;
 		mini ? TabMaterials.draw_mini(htab) : TabMaterials.draw_full(htab);
 	}
 
@@ -40,19 +40,19 @@ class TabMaterials {
 	}
 
 	static button_nodes = () => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 		if (zui_button(tr("Nodes"))) {
-			UIBase.show_material_nodes();
+			ui_base_show_material_nodes();
 		}
 		else if (ui.is_hovered) zui_tooltip(tr("Show Node Editor") + ` (${config_keymap.toggle_node_editor})`);
 	}
 
 	static draw_slots = (mini: bool) => {
-		let ui: zui_t = UIBase.ui;
-		let slotw: i32 = Math.floor(51 * zui_SCALE(ui));
-		let num: i32 = Math.floor(config_raw.layout[layout_size_t.SIDEBAR_W] / slotw);
+		let ui: zui_t = ui_base_ui;
+		let slotw: i32 = math_floor(51 * zui_SCALE(ui));
+		let num: i32 = math_floor(config_raw.layout[layout_size_t.SIDEBAR_W] / slotw);
 
-		for (let row: i32 = 0; row < Math.floor(Math.ceil(project_materials.length / num)); ++row) {
+		for (let row: i32 = 0; row < math_floor(math_ceil(project_materials.length / num)); ++row) {
 			let mult: i32 = config_raw.show_asset_names ? 2 : 1;
 			let ar: f32[] = [];
 			for (let i = 0; i < num * mult; ++i) ar.push(1 / num);
@@ -63,7 +63,7 @@ class TabMaterials {
 			if (row > 0) ui._y += off;
 
 			for (let j: i32 = 0; j < num; ++j) {
-				let imgw: i32 = Math.floor(50 * zui_SCALE(ui));
+				let imgw: i32 = math_floor(50 * zui_SCALE(ui));
 				let i: i32 = j + row * num;
 				if (i >= project_materials.length) {
 					zui_end_element(imgw);
@@ -82,7 +82,7 @@ class TabMaterials {
 					else {
 						let off: i32 = row % 2 == 1 ? 1 : 0;
 						let w: i32 = 50;
-						if (config_raw.window_scale > 1) w += Math.floor(config_raw.window_scale * 2);
+						if (config_raw.window_scale > 1) w += math_floor(config_raw.window_scale * 2);
 						zui_fill(-1,         -2, w + 3,       2, ui.t.HIGHLIGHT_COL);
 						zui_fill(-1,    w - off, w + 3, 2 + off, ui.t.HIGHLIGHT_COL);
 						zui_fill(-1,         -2,     2,   w + 3, ui.t.HIGHLIGHT_COL);
@@ -98,13 +98,13 @@ class TabMaterials {
 				let uix: f32 = ui._x;
 				let uiy: f32 = ui._y;
 				let tile: i32 = zui_SCALE(ui) > 1 ? 100 : 50;
-				let imgh: f32 = mini ? UIBase.default_sidebar_mini_w * 0.85 * zui_SCALE(ui) : -1.0;
+				let imgh: f32 = mini ? ui_base_default_sidebar_mini_w * 0.85 * zui_SCALE(ui) : -1.0;
 				let state = project_materials[i].preview_ready ?
 					zui_image(img, 0xffffffff, imgh) :
 					zui_image(resource_get("icons.k"), 0xffffffff, -1.0, tile, tile, tile, tile);
 
 				// Draw material numbers when selecting a material via keyboard shortcut
-				let is_typing: bool = ui.is_typing || UIView2D.ui.is_typing || UINodes.ui.is_typing;
+				let is_typing: bool = ui.is_typing || ui_view2d_ui.is_typing || ui_nodes_ui.is_typing;
 				if (!is_typing) {
 					if (i < 9 && operator_shortcut(config_keymap.select_material, shortcut_type_t.DOWN)) {
 						let number: string = String(i + 1);
@@ -135,7 +135,7 @@ class TabMaterials {
 					base_drag_material = context_raw.material;
 					// Double click to show nodes
 					if (time_time() - context_raw.select_time < 0.25) {
-						UIBase.show_material_nodes();
+						ui_base_show_material_nodes();
 						base_drag_material = null;
 						base_is_dragging = false;
 					}
@@ -147,27 +147,27 @@ class TabMaterials {
 					context_select_material(i);
 					let add: i32 = project_materials.length > 1 ? 1 : 0;
 
-					UIMenu.draw((ui: zui_t) => {
+					ui_menu_draw((ui: zui_t) => {
 						let m: SlotMaterialRaw = project_materials[i];
 
-						if (UIMenu.menu_button(ui, tr("To Fill Layer"))) {
+						if (ui_menu_button(ui, tr("To Fill Layer"))) {
 							context_select_material(i);
 							base_create_fill_layer();
 						}
 
-						if (UIMenu.menu_button(ui, tr("Export"))) {
+						if (ui_menu_button(ui, tr("Export"))) {
 							context_select_material(i);
 							BoxExport.show_material();
 						}
 
 						///if is_paint
-						if (UIMenu.menu_button(ui, tr("Bake"))) {
+						if (ui_menu_button(ui, tr("Bake"))) {
 							context_select_material(i);
 							BoxExport.show_bake_material();
 						}
 						///end
 
-						if (UIMenu.menu_button(ui, tr("Duplicate"))) {
+						if (ui_menu_button(ui, tr("Duplicate"))) {
 							let _init = () => {
 								context_raw.material = SlotMaterial.create(project_materials[0].data);
 								project_materials.push(context_raw.material);
@@ -179,7 +179,7 @@ class TabMaterials {
 							app_notify_on_init(_init);
 						}
 
-						if (project_materials.length > 1 && UIMenu.menu_button(ui, tr("Delete"), "delete")) {
+						if (project_materials.length > 1 && ui_menu_button(ui, tr("Delete"), "delete")) {
 							TabMaterials.delete_material(m);
 						}
 
@@ -192,23 +192,23 @@ class TabMaterials {
 						let height_handle: zui_handle_t = zui_nest(zui_handle("tabmaterials_6"), m.id, {selected: m.paint_height});
 						let emis_handle: zui_handle_t = zui_nest(zui_handle("tabmaterials_7"), m.id, {selected: m.paint_emis});
 						let subs_handle: zui_handle_t = zui_nest(zui_handle("tabmaterials_8"), m.id, {selected: m.paint_subs});
-						UIMenu.menu_fill(ui);
+						ui_menu_fill(ui);
 						m.paint_base = zui_check(base_handle, tr("Base Color"));
-						UIMenu.menu_fill(ui);
+						ui_menu_fill(ui);
 						m.paint_opac = zui_check(opac_handle, tr("Opacity"));
-						UIMenu.menu_fill(ui);
+						ui_menu_fill(ui);
 						m.paint_nor = zui_check(nor_handle, tr("Normal"));
-						UIMenu.menu_fill(ui);
+						ui_menu_fill(ui);
 						m.paint_occ = zui_check(occ_handle, tr("Occlusion"));
-						UIMenu.menu_fill(ui);
+						ui_menu_fill(ui);
 						m.paint_rough = zui_check(rough_handle, tr("Roughness"));
-						UIMenu.menu_fill(ui);
+						ui_menu_fill(ui);
 						m.paint_met = zui_check(met_handle, tr("Metallic"));
-						UIMenu.menu_fill(ui);
+						ui_menu_fill(ui);
 						m.paint_height = zui_check(height_handle, tr("Height"));
-						UIMenu.menu_fill(ui);
+						ui_menu_fill(ui);
 						m.paint_emis = zui_check(emis_handle, tr("Emission"));
-						UIMenu.menu_fill(ui);
+						ui_menu_fill(ui);
 						m.paint_subs = zui_check(subs_handle, tr("Subsurface"));
 						if (base_handle.changed ||
 							opac_handle.changed ||
@@ -220,7 +220,7 @@ class TabMaterials {
 							emis_handle.changed ||
 							subs_handle.changed) {
 							MakeMaterial.parse_paint_material();
-							UIMenu.keep_open = true;
+							ui_menu_keep_open = true;
 						}
 					}, 13 + add);
 				}
@@ -273,13 +273,13 @@ class TabMaterials {
 	}
 
 	static update_material = () => {
-		UIHeader.header_handle.redraws = 2;
-		UINodes.hwnd.redraws = 2;
-		UINodes.group_stack = [];
+		ui_header_handle.redraws = 2;
+		ui_nodes_hwnd.redraws = 2;
+		ui_nodes_group_stack = [];
 		MakeMaterial.parse_paint_material();
-		UtilRender.make_material_preview();
+		util_render_make_material_preview();
 		let decal: bool = context_raw.tool == workspace_tool_t.DECAL || context_raw.tool == workspace_tool_t.TEXT;
-		if (decal) UtilRender.make_decal_preview();
+		if (decal) util_render_make_decal_preview();
 	}
 
 	static update_material_pointers = (nodes: zui_node_t[], i: i32) => {
@@ -325,7 +325,7 @@ class TabMaterials {
 		history_delete_material();
 		context_select_material(i == project_materials.length - 1 ? i - 1 : i + 1);
 		project_materials.splice(i, 1);
-		UIBase.hwnds[1].redraws = 2;
+		ui_base_hwnds[1].redraws = 2;
 		for (let m of project_materials) TabMaterials.update_material_pointers(m.canvas.nodes, i);
 	}
 }

+ 32 - 32
base/Sources/TabMeshes.ts

@@ -2,9 +2,9 @@
 class TabMeshes {
 
 	static draw = (htab: zui_handle_t) => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 		let statush: i32 = config_raw.layout[layout_size_t.STATUS_H];
-		if (zui_tab(htab, tr("Meshes")) && statush > UIStatus.default_status_h * zui_SCALE(ui)) {
+		if (zui_tab(htab, tr("Meshes")) && statush > ui_status_default_status_h * zui_SCALE(ui)) {
 
 			zui_begin_sticky();
 
@@ -27,11 +27,11 @@ class TabMeshes {
 			///end
 
 			if (zui_button(tr("Import"))) {
-				UIMenu.draw((ui: zui_t) => {
-					if (UIMenu.menu_button(ui, tr("Replace Existing"), `${config_keymap.file_import_assets}`)) {
+				ui_menu_draw((ui: zui_t) => {
+					if (ui_menu_button(ui, tr("Replace Existing"), `${config_keymap.file_import_assets}`)) {
 						project_import_mesh(true);
 					}
-					if (UIMenu.menu_button(ui, tr("Append"))) {
+					if (ui_menu_button(ui, tr("Append"))) {
 						project_import_mesh(false);
 					}
 				}, 2);
@@ -40,60 +40,60 @@ class TabMeshes {
 
 			///if is_lab
 			if (zui_button(tr("Set Default"))) {
-				UIMenu.draw((ui: zui_t) => {
-					if (UIMenu.menu_button(ui, tr("Cube"))) TabMeshes.set_default_mesh(".Cube");
-					if (UIMenu.menu_button(ui, tr("Plane"))) TabMeshes.set_default_mesh(".Plane");
-					if (UIMenu.menu_button(ui, tr("Sphere"))) TabMeshes.set_default_mesh(".Sphere");
-					if (UIMenu.menu_button(ui, tr("Cylinder"))) TabMeshes.set_default_mesh(".Cylinder");
+				ui_menu_draw((ui: zui_t) => {
+					if (ui_menu_button(ui, tr("Cube"))) TabMeshes.set_default_mesh(".Cube");
+					if (ui_menu_button(ui, tr("Plane"))) TabMeshes.set_default_mesh(".Plane");
+					if (ui_menu_button(ui, tr("Sphere"))) TabMeshes.set_default_mesh(".Sphere");
+					if (ui_menu_button(ui, tr("Cylinder"))) TabMeshes.set_default_mesh(".Cylinder");
 				}, 4);
 			}
 			///end
 
 			if (zui_button(tr("Flip Normals"))) {
-				UtilMesh.flip_normals();
+				util_mesh_flip_normals();
 				context_raw.ddirty = 2;
 			}
 
 			if (zui_button(tr("Calculate Normals"))) {
-				UIMenu.draw((ui: zui_t) => {
-					if (UIMenu.menu_button(ui, tr("Smooth"))) { UtilMesh.calc_normals(true); context_raw.ddirty = 2; }
-					if (UIMenu.menu_button(ui, tr("Flat"))) { UtilMesh.calc_normals(false); context_raw.ddirty = 2; }
+				ui_menu_draw((ui: zui_t) => {
+					if (ui_menu_button(ui, tr("Smooth"))) { util_mesh_calc_normals(true); context_raw.ddirty = 2; }
+					if (ui_menu_button(ui, tr("Flat"))) { util_mesh_calc_normals(false); context_raw.ddirty = 2; }
 				}, 2);
 			}
 
 			if (zui_button(tr("Geometry to Origin"))) {
-				UtilMesh.to_origin();
+				util_mesh_to_origin();
 				context_raw.ddirty = 2;
 			}
 
 			if (zui_button(tr("Apply Displacement"))) {
 				///if is_paint
-				UtilMesh.apply_displacement(project_layers[0].texpaint_pack);
+				util_mesh_apply_displacement(project_layers[0].texpaint_pack);
 				///end
 				///if is_lab
 				let displace_strength: f32 = config_raw.displace_strength > 0 ? config_raw.displace_strength : 1.0;
 				let uv_scale: f32 = scene_meshes[0].data.scale_tex * context_raw.brush_scale;
-				UtilMesh.apply_displacement(BrushOutputNode.inst.texpaint_pack, 0.05 * displace_strength, uv_scale);
+				util_mesh_apply_displacement(BrushOutputNode.inst.texpaint_pack, 0.05 * displace_strength, uv_scale);
 				///end
 
-				UtilMesh.calc_normals();
+				util_mesh_calc_normals();
 				context_raw.ddirty = 2;
 			}
 
 			if (zui_button(tr("Rotate"))) {
-				UIMenu.draw((ui: zui_t) => {
-					if (UIMenu.menu_button(ui, tr("Rotate X"))) {
-						UtilMesh.swap_axis(1, 2);
+				ui_menu_draw((ui: zui_t) => {
+					if (ui_menu_button(ui, tr("Rotate X"))) {
+						util_mesh_swap_axis(1, 2);
 						context_raw.ddirty = 2;
 					}
 
-					if (UIMenu.menu_button(ui, tr("Rotate Y"))) {
-						UtilMesh.swap_axis(2, 0);
+					if (ui_menu_button(ui, tr("Rotate Y"))) {
+						util_mesh_swap_axis(2, 0);
 						context_raw.ddirty = 2;
 					}
 
-					if (UIMenu.menu_button(ui, tr("Rotate Z"))) {
-						UtilMesh.swap_axis(0, 1);
+					if (ui_menu_button(ui, tr("Rotate Z"))) {
+						util_mesh_swap_axis(0, 1);
 						context_raw.ddirty = 2;
 					}
 				}, 3);
@@ -107,12 +107,12 @@ class TabMeshes {
 				h.selected = o.base.visible;
 				o.base.visible = zui_check(h, o.base.name);
 				if (ui.is_hovered && ui.input_released_r) {
-					UIMenu.draw((ui: zui_t) => {
-						if (UIMenu.menu_button(ui, tr("Export"))) {
+					ui_menu_draw((ui: zui_t) => {
+						if (ui_menu_button(ui, tr("Export"))) {
 							context_raw.export_mesh_index = i + 1;
 							BoxExport.show_mesh();
 						}
-						if (project_paint_objects.length > 1 && UIMenu.menu_button(ui, tr("Delete"))) {
+						if (project_paint_objects.length > 1 && ui_menu_button(ui, tr("Delete"))) {
 							array_remove(project_paint_objects, o);
 							while (o.base.children.length > 0) {
 								let child: object_t = o.base.children[0];
@@ -128,7 +128,7 @@ class TabMeshes {
 							data_delete_mesh(o.data._.handle);
 							mesh_object_remove(o);
 							context_raw.paint_object = context_main_object();
-							UtilMesh.merge_mesh();
+							util_mesh_merge();
 							context_raw.ddirty = 2;
 						}
 					}, project_paint_objects.length > 1 ? 2 : 1);
@@ -136,7 +136,7 @@ class TabMeshes {
 				if (h.changed) {
 					let visibles: mesh_object_t[] = [];
 					for (let p of project_paint_objects) if (p.base.visible) visibles.push(p);
-					UtilMesh.merge_mesh(visibles);
+					util_mesh_merge(visibles);
 					context_raw.ddirty = 2;
 				}
 			}
@@ -148,7 +148,7 @@ class TabMeshes {
 		let mo: mesh_object_t = null;
 		if (name == ".Plane" || name == ".Sphere") {
 			let res: i32 = config_raw.rp_supersample > 1.0 ? 2048 : 1024;
-			let mesh: any = name == ".Plane" ? geom_make_plane(1, 1, res, res) : geom_make_uv_sphere(1.0, res, Math.floor(res / 2), false, 2.0);
+			let mesh: any = name == ".Plane" ? geom_make_plane(1, 1, res, res) : geom_make_uv_sphere(1.0, res, math_floor(res / 2), false, 2.0);
 			let raw: any = {
 				name: "Tessellated",
 				vertex_arrays: [
@@ -175,7 +175,7 @@ class TabMeshes {
 		context_raw.ddirty = 2;
 		context_raw.paint_object = mo;
 		project_paint_objects[0] = mo;
-		if (UIHeader.worktab.position == space_type_t.SPACE3D) {
+		if (ui_header_worktab.position == space_type_t.SPACE3D) {
 			scene_meshes = [mo];
 		}
 

+ 1 - 1
base/Sources/TabPlugins.ts

@@ -2,7 +2,7 @@
 class TabPlugins {
 
 	static draw = (htab: zui_handle_t) => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 		if (zui_tab(htab, tr("Plugins"))) {
 
 			zui_begin_sticky();

+ 9 - 9
base/Sources/TabScript.ts

@@ -5,9 +5,9 @@ class TabScript {
 	static text_coloring: zui_text_coloring_t = null;
 
 	static draw = (htab: zui_handle_t) => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 		let statush: i32 = config_raw.layout[layout_size_t.STATUS_H];
-		if (zui_tab(htab, tr("Script")) && statush > UIStatus.default_status_h * zui_SCALE(ui)) {
+		if (zui_tab(htab, tr("Script")) && statush > ui_status_default_status_h * zui_SCALE(ui)) {
 
 			zui_begin_sticky();
 			if (config_raw.touch_ui) {
@@ -28,7 +28,7 @@ class TabScript {
 				TabScript.hscript.text = "";
 			}
 			if (zui_button(tr("Import"))) {
-				UIFiles.show("js", false, false, (path: string) => {
+				ui_files_show("js", false, false, (path: string) => {
 					let b: ArrayBuffer = data_get_blob(path);
 					TabScript.hscript.text = sys_buffer_to_string(b);
 					data_delete_blob(path);
@@ -36,8 +36,8 @@ class TabScript {
 			}
 			if (zui_button(tr("Export"))) {
 				let str: string = TabScript.hscript.text;
-				UIFiles.show("js", true, false, (path: string) => {
-					let f: string = UIFiles.filename;
+				ui_files_show("js", true, false, (path: string) => {
+					let f: string = ui_files_filename;
 					if (f == "") f = tr("untitled");
 					path = path + path_sep + f;
 					if (!path.endsWith(".js")) path += ".js";
@@ -50,7 +50,7 @@ class TabScript {
 			let _font_size: i32 = ui.font_size;
 			let f: g2_font_t = data_get_font("font_mono.ttf");
 			zui_set_font(ui, f);
-			ui.font_size = Math.floor(15 * zui_SCALE(ui));
+			ui.font_size = math_floor(15 * zui_SCALE(ui));
 			zui_set_text_area_line_numbers(true);
 			zui_set_text_area_scroll_past_end(true);
 			zui_set_text_area_coloring(TabScript.get_text_coloring());
@@ -66,10 +66,10 @@ class TabScript {
 	static get_text_coloring = (): zui_text_coloring_t => {
 		if (TabScript.text_coloring == null) {
 			let blob: ArrayBuffer = data_get_blob("text_coloring.json");
-			TabScript.text_coloring = JSON.parse(sys_buffer_to_string(blob));
-			TabScript.text_coloring.default_color = Math.floor(TabScript.text_coloring.default_color);
+			TabScript.text_coloring = json_parse(sys_buffer_to_string(blob));
+			TabScript.text_coloring.default_color = math_floor(TabScript.text_coloring.default_color);
 			for (let coloring of TabScript.text_coloring.colorings) {
-				coloring.color = Math.floor(coloring.color);
+				coloring.color = math_floor(coloring.color);
 			}
 		}
 		return TabScript.text_coloring;

+ 19 - 19
base/Sources/TabSwatches.ts

@@ -21,9 +21,9 @@ class TabSwatches {
 	}
 
 	static draw = (htab: zui_handle_t) => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 		let statush: i32 = config_raw.layout[layout_size_t.STATUS_H];
-		if (zui_tab(htab, tr("Swatches")) && statush > UIStatus.default_status_h * zui_SCALE(ui)) {
+		if (zui_tab(htab, tr("Swatches")) && statush > ui_status_default_status_h * zui_SCALE(ui)) {
 
 			zui_begin_sticky();
 			if (config_raw.touch_ui) {
@@ -40,12 +40,12 @@ class TabSwatches {
 			if (ui.is_hovered) zui_tooltip(tr("Add new swatch"));
 
 			if (zui_button(tr("Import"))) {
-				UIMenu.draw((ui: zui_t) => {
-					if (UIMenu.menu_button(ui, tr("Replace Existing"))) {
+				ui_menu_draw((ui: zui_t) => {
+					if (ui_menu_button(ui, tr("Replace Existing"))) {
 						project_import_swatches(true);
 						context_set_swatch(project_raw.swatches[0]);
 					}
-					if (UIMenu.menu_button(ui, tr("Append"))) {
+					if (ui_menu_button(ui, tr("Append"))) {
 						project_import_swatches(false);
 					}
 				}, 2);
@@ -69,13 +69,13 @@ class TabSwatches {
 			zui_end_sticky();
 			zui_separator(3, false);
 
-			let slotw: i32 = Math.floor(26 * zui_SCALE(ui));
-			let num: i32 = Math.floor(ui._w / (slotw + 3));
+			let slotw: i32 = math_floor(26 * zui_SCALE(ui));
+			let num: i32 = math_floor(ui._w / (slotw + 3));
 			let drag_pos_set: bool = false;
 
 			let uix: f32 = 0.0;
 			let uiy: f32 = 0.0;
-			for (let row: i32 = 0; row < Math.floor(Math.ceil(project_raw.swatches.length / num)); ++row) {
+			for (let row: i32 = 0; row < math_floor(math_ceil(project_raw.swatches.length / num)); ++row) {
 				let ar: f32[] = [];
 				for (let i: i32 = 0; i < num; ++i) ar.push(1 / num);
 				zui_row(ar);
@@ -118,7 +118,7 @@ class TabSwatches {
 					}
 					else if (state == zui_state_t.RELEASED) {
 						if (time_time() - context_raw.select_time < 0.25) {
-							UIMenu.draw((ui: zui_t) => {
+							ui_menu_draw((ui: zui_t) => {
 								ui.changed = false;
 								let h: zui_handle_t = zui_handle("tabswatches_0");
 								h.color = context_raw.swatch.base;
@@ -146,9 +146,9 @@ class TabSwatches {
 								hheight.value = context_raw.swatch.height;
 								context_raw.swatch.height = zui_slider(hheight, "Height", 0, 1, true);
 
-								if (ui.changed || ui.is_typing) UIMenu.keep_open = true;
+								if (ui.changed || ui.is_typing) ui_menu_keep_open = true;
 								if (ui.input_released) context_set_swatch(context_raw.swatch); // Trigger material preview update
-							}, 16, Math.floor(mouse_x - 200 * zui_SCALE(ui)), Math.floor(mouse_y - 250 * zui_SCALE(ui)));
+							}, 16, math_floor(mouse_x - 200 * zui_SCALE(ui)), math_floor(mouse_y - 250 * zui_SCALE(ui)));
 						}
 
 						context_raw.select_time = time_time();
@@ -167,13 +167,13 @@ class TabSwatches {
 						add += 1;
 						///end
 
-						UIMenu.draw((ui: zui_t) => {
-							if (UIMenu.menu_button(ui, tr("Duplicate"))) {
+						ui_menu_draw((ui: zui_t) => {
+							if (ui_menu_button(ui, tr("Duplicate"))) {
 								context_set_swatch(project_clone_swatch(context_raw.swatch));
 								project_raw.swatches.push(context_raw.swatch);
 							}
 							///if (krom_windows || krom_linux || krom_darwin)
-							else if (UIMenu.menu_button(ui, tr("Copy Hex Code"))) {
+							else if (ui_menu_button(ui, tr("Copy Hex Code"))) {
 								let color: i32 = context_raw.swatch.base;
 								color = color_set_ab(color, context_raw.swatch.opacity * 255);
 								let val: i32 = color;
@@ -181,14 +181,14 @@ class TabSwatches {
 								krom_copy_to_clipboard(val.toString(16));
 							}
 							///end
-							else if (project_raw.swatches.length > 1 && UIMenu.menu_button(ui, tr("Delete"), "delete")) {
+							else if (project_raw.swatches.length > 1 && ui_menu_button(ui, tr("Delete"), "delete")) {
 								TabSwatches.delete_swatch(project_raw.swatches[i]);
 							}
 							///if (is_paint || is_sculpt)
-							else if (UIMenu.menu_button(ui, tr("Create Material"))) {
+							else if (ui_menu_button(ui, tr("Create Material"))) {
 								TabMaterials.accept_swatch_drag(project_raw.swatches[i]);
 							}
-							else if (UIMenu.menu_button(ui, tr("Create Color Layer"))) {
+							else if (ui_menu_button(ui, tr("Create Color Layer"))) {
 								let color: i32 = project_raw.swatches[i].base;
 								color = color_set_ab(color, project_raw.swatches[i].opacity * 255);
 								base_create_color_layer(color, project_raw.swatches[i].occlusion, project_raw.swatches[i].roughness, project_raw.swatches[i].metallic);
@@ -236,7 +236,7 @@ class TabSwatches {
 		if (swatch_pos == -1) {
 			project_raw.swatches.splice(TabSwatches.drag_pos, 0, swatch);
 		}
-		else if (Math.abs(swatch_pos - TabSwatches.drag_pos) > 0) { // Existing swatch is reordered
+		else if (math_abs(swatch_pos - TabSwatches.drag_pos) > 0) { // Existing swatch is reordered
 			array_remove(project_raw.swatches, swatch);
 			// If the new position is after the old one, decrease by one because the swatch has been deleted
 			let new_pos: i32 = TabSwatches.drag_pos - swatch_pos > 0 ? TabSwatches.drag_pos -1 : TabSwatches.drag_pos;
@@ -248,6 +248,6 @@ class TabSwatches {
 		let i: i32 = project_raw.swatches.indexOf(swatch);
 		context_set_swatch(project_raw.swatches[i == project_raw.swatches.length - 1 ? i - 1 : i + 1]);
 		project_raw.swatches.splice(i, 1);
-		UIBase.hwnds[tab_area_t.STATUS].redraws = 2;
+		ui_base_hwnds[tab_area_t.STATUS].redraws = 2;
 	}
 }

+ 30 - 30
base/Sources/TabTextures.ts

@@ -2,9 +2,9 @@
 class TabTextures {
 
 	static draw = (htab: zui_handle_t) => {
-		let ui: zui_t = UIBase.ui;
+		let ui: zui_t = ui_base_ui;
 		let statush: i32 = config_raw.layout[layout_size_t.STATUS_H];
-		if (zui_tab(htab, tr("Textures")) && statush > UIStatus.default_status_h * zui_SCALE(ui)) {
+		if (zui_tab(htab, tr("Textures")) && statush > ui_status_default_status_h * zui_SCALE(ui)) {
 
 			zui_begin_sticky();
 
@@ -16,30 +16,30 @@ class TabTextures {
 			}
 
 			if (zui_button(tr("Import"))) {
-				UIFiles.show(path_texture_formats.join(","), false, true, (path: string) => {
+				ui_files_show(path_texture_formats.join(","), false, true, (path: string) => {
 					ImportAsset.run(path, -1.0, -1.0, true, false);
-					UIBase.hwnds[tab_area_t.STATUS].redraws = 2;
+					ui_base_hwnds[tab_area_t.STATUS].redraws = 2;
 				});
 			}
 			if (ui.is_hovered) zui_tooltip(tr("Import texture file") + ` (${config_keymap.file_import_assets})`);
 
-			if (zui_button(tr("2D View"))) UIBase.show_2d_view(view_2d_type_t.ASSET);
+			if (zui_button(tr("2D View"))) ui_base_show_2d_view(view_2d_type_t.ASSET);
 
 			zui_end_sticky();
 
 			if (project_assets.length > 0) {
 
 				///if (is_paint || is_sculpt)
-				let statusw: i32 = sys_width() - UIToolbar.toolbar_w - config_raw.layout[layout_size_t.SIDEBAR_W];
+				let statusw: i32 = sys_width() - ui_toolbar_w - config_raw.layout[layout_size_t.SIDEBAR_W];
 				///end
 				///if is_lab
 				let statusw: i32 = sys_width();
 				///end
 
-				let slotw: i32 = Math.floor(52 * zui_SCALE(ui));
-				let num: i32 = Math.floor(statusw / slotw);
+				let slotw: i32 = math_floor(52 * zui_SCALE(ui));
+				let num: i32 = math_floor(statusw / slotw);
 
-				for (let row: i32 = 0; row < Math.floor(Math.ceil(project_assets.length / num)); ++row) {
+				for (let row: i32 = 0; row < math_floor(math_ceil(project_assets.length / num)); ++row) {
 					let mult: i32 = config_raw.show_asset_names ? 2 : 1;
 					let ar: f32[] = [];
 					for (let i: i32 = 0; i < num * mult; ++i) ar.push(1 / num);
@@ -50,7 +50,7 @@ class TabTextures {
 					if (row > 0) ui._y += off;
 
 					for (let j: i32 = 0; j < num; ++j) {
-						let imgw: i32 = Math.floor(50 * zui_SCALE(ui));
+						let imgw: i32 = math_floor(50 * zui_SCALE(ui));
 						let i: i32 = j + row * num;
 						if (i >= project_assets.length) {
 							zui_end_element(imgw);
@@ -69,9 +69,9 @@ class TabTextures {
 							base_drag_asset = asset;
 							context_raw.texture = asset;
 
-							if (time_time() - context_raw.select_time < 0.25) UIBase.show_2d_view(view_2d_type_t.ASSET);
+							if (time_time() - context_raw.select_time < 0.25) ui_base_show_2d_view(view_2d_type_t.ASSET);
 							context_raw.select_time = time_time();
-							UIView2D.hwnd.redraws = 2;
+							ui_view2d_hwnd.redraws = 2;
 						}
 
 						if (asset == context_raw.texture) {
@@ -108,9 +108,9 @@ class TabTextures {
 							count = is_packed ? 6 : 6;
 							///end
 
-							UIMenu.draw((ui: zui_t) => {
-								if (UIMenu.menu_button(ui, tr("Export"))) {
-									UIFiles.show("png", true, false, (path: string) => {
+							ui_menu_draw((ui: zui_t) => {
+								if (ui_menu_button(ui, tr("Export"))) {
+									ui_files_show("png", true, false, (path: string) => {
 										base_notify_on_next_frame(() => {
 											///if (is_paint || is_sculpt)
 											if (base_pipe_merge == null) base_make_pipe();
@@ -126,7 +126,7 @@ class TabTextures {
 											g2_set_pipeline(null);
 											g2_end();
 											base_notify_on_next_frame(() => {
-												let f: string = UIFiles.filename;
+												let f: string = ui_files_filename;
 												if (f == "") f = tr("untitled");
 												if (!f.endsWith(".png")) f += ".png";
 												krom_write_png(path + path_sep + f, image_get_pixels(target), target.width, target.height, 0);
@@ -135,43 +135,43 @@ class TabTextures {
 										});
 									});
 								}
-								if (UIMenu.menu_button(ui, tr("Reimport"))) {
+								if (ui_menu_button(ui, tr("Reimport"))) {
 									project_reimport_texture(asset);
 								}
 
 								///if (is_paint || is_sculpt)
-								if (UIMenu.menu_button(ui, tr("To Mask"))) {
+								if (ui_menu_button(ui, tr("To Mask"))) {
 									base_notify_on_next_frame(() => {
 										base_create_image_mask(asset);
 									});
 								}
 								///end
 
-								if (UIMenu.menu_button(ui, tr("Set as Envmap"))) {
+								if (ui_menu_button(ui, tr("Set as Envmap"))) {
 									base_notify_on_next_frame(() => {
 										ImportEnvmap.run(asset.file, img);
 									});
 								}
 
 								///if is_paint
-								if (UIMenu.menu_button(ui, tr("Set as Color ID Map"))) {
+								if (ui_menu_button(ui, tr("Set as Color ID Map"))) {
 									context_raw.colorid_handle.position = i;
 									context_raw.colorid_picked = false;
-									UIToolbar.toolbar_handle.redraws = 1;
+									ui_toolbar_handle.redraws = 1;
 									if (context_raw.tool == workspace_tool_t.COLORID) {
-										UIHeader.header_handle.redraws = 2;
+										ui_header_handle.redraws = 2;
 										context_raw.ddirty = 2;
 									}
 								}
 								///end
 
-								if (UIMenu.menu_button(ui, tr("Delete"), "delete")) {
+								if (ui_menu_button(ui, tr("Delete"), "delete")) {
 									TabTextures.delete_texture(asset);
 								}
-								if (!is_packed && UIMenu.menu_button(ui, tr("Open Containing Directory..."))) {
+								if (!is_packed && ui_menu_button(ui, tr("Open Containing Directory..."))) {
 									file_start(asset.file.substr(0, asset.file.lastIndexOf(path_sep)));
 								}
-								if (!is_packed && UIMenu.menu_button(ui, tr("Open in Browser"))) {
+								if (!is_packed && ui_menu_button(ui, tr("Open in Browser"))) {
 									TabBrowser.show_directory(asset.file.substr(0, asset.file.lastIndexOf(path_sep)));
 								}
 							}, count);
@@ -235,14 +235,14 @@ class TabTextures {
 		if (project_assets.length > 1) {
 			context_raw.texture = project_assets[i == project_assets.length - 1 ? i - 1 : i + 1];
 		}
-		UIBase.hwnds[tab_area_t.STATUS].redraws = 2;
+		ui_base_hwnds[tab_area_t.STATUS].redraws = 2;
 
 		///if is_paint
 		if (context_raw.tool == workspace_tool_t.COLORID && i == context_raw.colorid_handle.position) {
-			UIHeader.header_handle.redraws = 2;
+			ui_header_handle.redraws = 2;
 			context_raw.ddirty = 2;
 			context_raw.colorid_picked = false;
-			UIToolbar.toolbar_handle.redraws = 1;
+			ui_toolbar_handle.redraws = 1;
 		}
 		///end
 
@@ -254,8 +254,8 @@ class TabTextures {
 			MakeMaterial.parse_paint_material();
 
 			///if (is_paint || is_sculpt)
-			UtilRender.make_material_preview();
-			UIBase.hwnds[tab_area_t.SIDEBAR1].redraws = 2;
+			util_render_make_material_preview();
+			ui_base_hwnds[tab_area_t.SIDEBAR1].redraws = 2;
 			///end
 		}
 		base_notify_on_next_frame(_next);

+ 0 - 1533
base/Sources/UIBase.ts

@@ -1,1533 +0,0 @@
-
-///if is_paint
-/// <reference path='../../armorpaint/Sources/TabLayers.ts'/>
-///end
-///if is_sculpt
-/// <reference path='../../armorsculpt/Sources/TabLayers.ts'/>
-///end
-///if is_forge
-/// <reference path='../../armorforge/Sources/TabObjects.ts'/>
-///end
-/// <reference path='./TabHistory.ts'/>
-/// <reference path='./TabPlugins.ts'/>
-/// <reference path='./TabMaterials.ts'/>
-/// <reference path='./TabBrushes.ts'/>
-/// <reference path='./TabParticles.ts'/>
-/// <reference path='./TabBrowser.ts'/>
-/// <reference path='./TabTextures.ts'/>
-/// <reference path='./TabMeshes.ts'/>
-/// <reference path='./TabFonts.ts'/>
-/// <reference path='./TabSwatches.ts'/>
-/// <reference path='./TabScript.ts'/>
-/// <reference path='./TabConsole.ts'/>
-/// <reference path='./UIStatus.ts'/>
-
-class UIBase {
-
-	static show: bool = true;
-	static ui: zui_t;
-	static border_started: i32 = 0;
-	static border_handle_ptr: i32 = 0;
-	static action_paint_remap: string = "";
-	static operator_search_offset: i32 = 0;
-	static undo_tap_time: f32 = 0.0;
-	static redo_tap_time: f32 = 0.0;
-
-	static init_hwnds = (): zui_handle_t[] => {
-		///if is_paint
-		return [zui_handle_create(), zui_handle_create(), zui_handle_create()];
-		///end
-		///if is_sculpt
-		return [zui_handle_create(), zui_handle_create(), zui_handle_create()];
-		///end
-		///if is_lab
-		return [zui_handle_create()];
-		///end
-	}
-
-	static init_htabs = (): zui_handle_t[] => {
-		///if is_paint
-		return [zui_handle_create(), zui_handle_create(), zui_handle_create()];
-		///end
-		///if is_sculpt
-		return [zui_handle_create(), zui_handle_create(), zui_handle_create()];
-		///end
-		///if is_lab
-		return [zui_handle_create()];
-		///end
-	}
-
-	static init_hwnd_tabs = (): any[] => {
-		///if is_paint
-		return [
-			[TabLayers.draw, TabHistory.draw, TabPlugins.draw
-				///if is_forge
-				, TabObjects.draw
-				///end
-			],
-			[TabMaterials.draw, TabBrushes.draw, TabParticles.draw],
-			[TabBrowser.draw, TabTextures.draw, TabMeshes.draw, TabFonts.draw, TabSwatches.draw, TabScript.draw, TabConsole.draw, UIStatus.draw_version_tab]
-		];
-		///end
-		///if is_sculpt
-		return [
-			[TabLayers.draw, TabHistory.draw, TabPlugins.draw
-				///if is_forge
-				, TabObjects.draw
-				///end
-			],
-			[TabMaterials.draw, TabBrushes.draw, TabParticles.draw],
-			[TabBrowser.draw, TabTextures.draw, TabMeshes.draw, TabFonts.draw, TabScript.draw, TabConsole.draw, UIStatus.draw_version_tab]
-		];
-		///end
-		///if is_lab
-		return [
-			[TabBrowser.draw, TabTextures.draw, TabMeshes.draw, TabSwatches.draw, TabPlugins.draw, TabScript.draw, TabConsole.draw, UIStatus.draw_version_tab]
-		];
-		///end
-	}
-
-	static hwnds: zui_handle_t[] = UIBase.init_hwnds();
-	static htabs: zui_handle_t[] = UIBase.init_htabs();
-	static hwnd_tabs: any[] = UIBase.init_hwnd_tabs();
-
-	///if (is_paint || is_sculpt)
-	static default_sidebar_mini_w: i32 = 56;
-	static default_sidebar_full_w: i32 = 280;
-	///if (krom_android || krom_ios)
-	static default_sidebar_w: i32 = UIBase.default_sidebar_mini_w;
-	///else
-	static default_sidebar_w: i32 = UIBase.default_sidebar_full_w;
-	///end
-	static tabx: i32 = 0;
-	static hminimized: zui_handle_t = zui_handle_create();
-	static sidebar_mini_w: i32 = UIBase.default_sidebar_mini_w;
-	///end
-
-	constructor() {
-		///if (is_paint || is_sculpt)
-		new UIToolbar();
-		UIToolbar.toolbar_w = Math.floor(UIToolbar.default_toolbar_w * config_raw.window_scale);
-		context_raw.text_tool_text = tr("Text");
-		///end
-
-		new UIHeader();
-		new UIStatus();
-		new UIMenubar();
-
-		UIHeader.headerh = Math.floor(UIHeader.default_header_h * config_raw.window_scale);
-		UIMenubar.menubarw = Math.floor(UIMenubar.default_menubar_w * config_raw.window_scale);
-
-		///if (is_paint || is_sculpt)
-		if (project_materials == null) {
-			project_materials = [];
-			let m: material_data_t = data_get_material("Scene", "Material");
-			project_materials.push(SlotMaterial.create(m));
-			context_raw.material = project_materials[0];
-		}
-
-		if (project_brushes == null) {
-			project_brushes = [];
-			project_brushes.push(SlotBrush.create());
-			context_raw.brush = project_brushes[0];
-			MakeMaterial.parse_brush();
-		}
-
-		if (project_fonts == null) {
-			project_fonts = [];
-			project_fonts.push(SlotFont.create("default.ttf", base_font));
-			context_raw.font = project_fonts[0];
-		}
-
-		if (project_layers == null) {
-			project_layers = [];
-			project_layers.push(SlotLayer.create());
-			context_raw.layer = project_layers[0];
-		}
-		///end
-
-		///if is_lab
-		if (project_material_data == null) {
-			let m: material_data_t = data_get_material("Scene", "Material");
-			project_material_data = m;
-		}
-
-		if (project_default_canvas == null) { // Synchronous
-			let b: ArrayBuffer = data_get_blob("default_brush.arm");
-			project_default_canvas = b;
-		}
-
-		project_nodes = zui_nodes_create();
-		project_canvas = armpack_decode(project_default_canvas);
-		project_canvas.name = "Brush 1";
-
-		context_parse_brush_inputs();
-
-		ParserLogic.parse(project_canvas);
-		///end
-
-		if (project_raw.swatches == null) {
-			project_set_default_swatches();
-			context_raw.swatch = project_raw.swatches[0];
-		}
-
-		if (context_raw.empty_envmap == null) {
-			let b: Uint8Array = new Uint8Array(4);
-			b[0] = 8;
-			b[1] = 8;
-			b[2] = 8;
-			b[3] = 255;
-			context_raw.empty_envmap = image_from_bytes(b.buffer, 1, 1);
-		}
-		if (context_raw.preview_envmap == null) {
-			let b: Uint8Array = new Uint8Array(4);
-			b[0] = 0;
-			b[1] = 0;
-			b[2] = 0;
-			b[3] = 255;
-			context_raw.preview_envmap = image_from_bytes(b.buffer, 1, 1);
-		}
-
-		let world: world_data_t = scene_world;
-		if (context_raw.saved_envmap == null) {
-			// raw.savedEnvmap = world._envmap;
-			context_raw.default_irradiance = world._.irradiance;
-			context_raw.default_radiance = world._.radiance;
-			context_raw.default_radiance_mipmaps = world._.radiance_mipmaps;
-		}
-		world._.envmap = context_raw.show_envmap ? context_raw.saved_envmap : context_raw.empty_envmap;
-		context_raw.ddirty = 1;
-
-		history_reset();
-
-		let scale: f32 = config_raw.window_scale;
-		UIBase.ui = zui_create({ theme: base_theme, font: base_font, scale_factor: scale, color_wheel: base_color_wheel, black_white_gradient: base_color_wheel_gradient });
-		zui_set_on_border_hover(UIBase.on_border_hover);
-		zui_set_on_text_hover(UIBase.on_text_hover);
-		zui_set_on_deselect_text(UIBase.on_deselect_text);
-		zui_set_on_tab_drop(UIBase.on_tab_drop);
-
-		///if (is_paint || is_sculpt)
-		let resources: string[] = ["cursor.k", "icons.k"];
-		///end
-		///if is_lab
-		let resources: string[] = ["cursor.k", "icons.k", "placeholder.k"];
-		///end
-
-		///if (is_paint || is_sculpt)
-		context_raw.gizmo = scene_get_child(".Gizmo");
-		context_raw.gizmo_translate_x = object_get_child(context_raw.gizmo, ".TranslateX");
-		context_raw.gizmo_translate_y = object_get_child(context_raw.gizmo, ".TranslateY");
-		context_raw.gizmo_translate_z = object_get_child(context_raw.gizmo, ".TranslateZ");
-		context_raw.gizmo_scale_x = object_get_child(context_raw.gizmo, ".ScaleX");
-		context_raw.gizmo_scale_y = object_get_child(context_raw.gizmo, ".ScaleY");
-		context_raw.gizmo_scale_z = object_get_child(context_raw.gizmo, ".ScaleZ");
-		context_raw.gizmo_rotate_x = object_get_child(context_raw.gizmo, ".RotateX");
-		context_raw.gizmo_rotate_y = object_get_child(context_raw.gizmo, ".RotateY");
-		context_raw.gizmo_rotate_z = object_get_child(context_raw.gizmo, ".RotateZ");
-		///end
-
-		resource_load(resources, () => {});
-
-		if (zui_SCALE(UIBase.ui) > 1) UIBase.set_icon_scale();
-
-		context_raw.paint_object = scene_get_child(".Cube").ext;
-		project_paint_objects = [context_raw.paint_object];
-
-		if (project_filepath == "") {
-			app_notify_on_init(base_init_layers);
-		}
-
-		context_raw.project_objects = [];
-		for (let m of scene_meshes) context_raw.project_objects.push(m);
-
-		operator_register("view_top", UIBase.view_top);
-	}
-
-	static update = () => {
-		UIBase.update_ui();
-		operator_update();
-
-		for (let p of plugin_map.values()) if (p.update != null) p.update();
-
-		if (!base_ui_enabled) return;
-
-		if (!UINodes.ui.is_typing && !UIBase.ui.is_typing) {
-			if (operator_shortcut(config_keymap.toggle_node_editor)) {
-				///if (is_paint || is_sculpt)
-				UINodes.canvas_type == canvas_type_t.MATERIAL ? UIBase.show_material_nodes() : UIBase.show_brush_nodes();
-				///end
-				///if is_lab
-				UIBase.show_material_nodes();
-				///end
-			}
-			else if (operator_shortcut(config_keymap.toggle_browser)) {
-				UIBase.toggle_browser();
-			}
-
-			else if (operator_shortcut(config_keymap.toggle_2d_view)) {
-				///if (is_paint || is_sculpt)
-				UIBase.show_2d_view(view_2d_type_t.LAYER);
-				///else
-				UIBase.show_2d_view(view_2d_type_t.ASSET);
-				///end
-			}
-		}
-
-		if (operator_shortcut(config_keymap.file_save_as)) project_save_as();
-		else if (operator_shortcut(config_keymap.file_save)) project_save();
-		else if (operator_shortcut(config_keymap.file_open)) project_open();
-		else if (operator_shortcut(config_keymap.file_open_recent)) BoxProjects.show();
-		else if (operator_shortcut(config_keymap.file_reimport_mesh)) project_reimport_mesh();
-		else if (operator_shortcut(config_keymap.file_reimport_textures)) project_reimport_textures();
-		else if (operator_shortcut(config_keymap.file_new)) project_new_box();
-		///if (is_paint || is_lab)
-		else if (operator_shortcut(config_keymap.file_export_textures)) {
-			if (context_raw.texture_export_path == "") { // First export, ask for path
-				///if is_paint
-				context_raw.layers_export = export_mode_t.VISIBLE;
-				///end
-				BoxExport.show_textures();
-			}
-			else {
-				let _init = () => {
-					ExportTexture.run(context_raw.texture_export_path);
-				}
-				app_notify_on_init(_init);
-			}
-		}
-		else if (operator_shortcut(config_keymap.file_export_textures_as)) {
-			///if (is_paint || is_sculpt)
-			context_raw.layers_export = export_mode_t.VISIBLE;
-			///end
-			BoxExport.show_textures();
-		}
-		///end
-		else if (operator_shortcut(config_keymap.file_import_assets)) project_import_asset();
-		else if (operator_shortcut(config_keymap.edit_prefs)) BoxPreferences.show();
-
-		if (keyboard_started(config_keymap.view_distract_free) ||
-		   (keyboard_started("escape") && !UIBase.show && !UIBox.show)) {
-			UIBase.toggle_distract_free();
-		}
-
-		///if krom_linux
-		if (operator_shortcut("alt+enter", shortcut_type_t.STARTED)) {
-			base_toggle_fullscreen();
-		}
-		///end
-
-		///if (is_paint || is_sculpt)
-		let decal: bool = context_raw.tool == workspace_tool_t.DECAL || context_raw.tool == workspace_tool_t.TEXT;
-		let decal_mask: bool = decal && operator_shortcut(config_keymap.decal_mask, shortcut_type_t.DOWN);
-
-		if ((context_raw.brush_can_lock || context_raw.brush_locked) && mouse_moved) {
-			if (operator_shortcut(config_keymap.brush_radius, shortcut_type_t.DOWN) ||
-				operator_shortcut(config_keymap.brush_opacity, shortcut_type_t.DOWN) ||
-				operator_shortcut(config_keymap.brush_angle, shortcut_type_t.DOWN) ||
-				(decal_mask && operator_shortcut(config_keymap.decal_mask + "+" + config_keymap.brush_radius, shortcut_type_t.DOWN))) {
-				if (context_raw.brush_locked) {
-					if (operator_shortcut(config_keymap.brush_opacity, shortcut_type_t.DOWN)) {
-						context_raw.brush_opacity += mouse_movement_x / 500;
-						context_raw.brush_opacity = Math.max(0.0, Math.min(1.0, context_raw.brush_opacity));
-						context_raw.brush_opacity = Math.round(context_raw.brush_opacity * 100) / 100;
-						context_raw.brush_opacity_handle.value = context_raw.brush_opacity;
-					}
-					else if (operator_shortcut(config_keymap.brush_angle, shortcut_type_t.DOWN)) {
-						context_raw.brush_angle += mouse_movement_x / 5;
-						context_raw.brush_angle = Math.floor(context_raw.brush_angle) % 360;
-						if (context_raw.brush_angle < 0) context_raw.brush_angle += 360;
-						context_raw.brush_angle_handle.value = context_raw.brush_angle;
-						MakeMaterial.parse_paint_material();
-					}
-					else if (decal_mask && operator_shortcut(config_keymap.decal_mask + "+" + config_keymap.brush_radius, shortcut_type_t.DOWN)) {
-						context_raw.brush_decal_mask_radius += mouse_movement_x / 150;
-						context_raw.brush_decal_mask_radius = Math.max(0.01, Math.min(4.0, context_raw.brush_decal_mask_radius));
-						context_raw.brush_decal_mask_radius = Math.round(context_raw.brush_decal_mask_radius * 100) / 100;
-						context_raw.brush_decal_mask_radius_handle.value = context_raw.brush_decal_mask_radius;
-					}
-					else {
-						context_raw.brush_radius += mouse_movement_x / 150;
-						context_raw.brush_radius = Math.max(0.01, Math.min(4.0, context_raw.brush_radius));
-						context_raw.brush_radius = Math.round(context_raw.brush_radius * 100) / 100;
-						context_raw.brush_radius_handle.value = context_raw.brush_radius;
-					}
-					UIHeader.header_handle.redraws = 2;
-				}
-				else if (context_raw.brush_can_lock) {
-					context_raw.brush_can_lock = false;
-					context_raw.brush_locked = true;
-				}
-			}
-		}
-		///end
-
-		///if is_lab
-		if ((context_raw.brush_can_lock || context_raw.brush_locked) && mouse_moved) {
-			if (operator_shortcut(config_keymap.brush_radius, shortcut_type_t.DOWN)) {
-				if (context_raw.brush_locked) {
-					context_raw.brush_radius += mouse_movement_x / 150;
-					context_raw.brush_radius = Math.max(0.01, Math.min(4.0, context_raw.brush_radius));
-					context_raw.brush_radius = Math.round(context_raw.brush_radius * 100) / 100;
-					context_raw.brush_radius_handle.value = context_raw.brush_radius;
-					UIHeader.header_handle.redraws = 2;
-				}
-				else if (context_raw.brush_can_lock) {
-					context_raw.brush_can_lock = false;
-					context_raw.brush_locked = true;
-				}
-			}
-		}
-		///end
-
-		let is_typing: bool = UIBase.ui.is_typing || UIView2D.ui.is_typing || UINodes.ui.is_typing;
-
-		///if (is_paint || is_sculpt)
-		if (!is_typing) {
-			if (operator_shortcut(config_keymap.select_material, shortcut_type_t.DOWN)) {
-				UIBase.hwnds[tab_area_t.SIDEBAR1].redraws = 2;
-				for (let i: i32 = 1; i < 10; ++i) if (keyboard_started(i + "")) context_select_material(i - 1);
-			}
-			else if (operator_shortcut(config_keymap.select_layer, shortcut_type_t.DOWN)) {
-				UIBase.hwnds[tab_area_t.SIDEBAR0].redraws = 2;
-				for (let i: i32 = 1; i < 10; ++i) if (keyboard_started(i + "")) context_select_layer(i - 1);
-			}
-		}
-		///end
-
-		// Viewport shortcuts
-		if (context_in_paint_area() && !is_typing) {
-
-			///if is_paint
-			if (!mouse_down("right")) { // Fly mode off
-				if (operator_shortcut(config_keymap.tool_brush)) context_select_tool(workspace_tool_t.BRUSH);
-				else if (operator_shortcut(config_keymap.tool_eraser)) context_select_tool(workspace_tool_t.ERASER);
-				else if (operator_shortcut(config_keymap.tool_fill)) context_select_tool(workspace_tool_t.FILL);
-				else if (operator_shortcut(config_keymap.tool_colorid)) context_select_tool(workspace_tool_t.COLORID);
-				else if (operator_shortcut(config_keymap.tool_decal)) context_select_tool(workspace_tool_t.DECAL);
-				else if (operator_shortcut(config_keymap.tool_text)) context_select_tool(workspace_tool_t.TEXT);
-				else if (operator_shortcut(config_keymap.tool_clone)) context_select_tool(workspace_tool_t.CLONE);
-				else if (operator_shortcut(config_keymap.tool_blur)) context_select_tool(workspace_tool_t.BLUR);
-				else if (operator_shortcut(config_keymap.tool_smudge)) context_select_tool(workspace_tool_t.SMUDGE);
-				else if (operator_shortcut(config_keymap.tool_particle)) context_select_tool(workspace_tool_t.PARTICLE);
-				else if (operator_shortcut(config_keymap.tool_picker)) context_select_tool(workspace_tool_t.PICKER);
-				else if (operator_shortcut(config_keymap.tool_bake)) context_select_tool(workspace_tool_t.BAKE);
-				else if (operator_shortcut(config_keymap.tool_gizmo)) context_select_tool(workspace_tool_t.GIZMO);
-				else if (operator_shortcut(config_keymap.tool_material)) context_select_tool(workspace_tool_t.MATERIAL);
-				else if (operator_shortcut(config_keymap.swap_brush_eraser)) context_select_tool(context_raw.tool == workspace_tool_t.BRUSH ? workspace_tool_t.ERASER : workspace_tool_t.BRUSH);
-			}
-
-			// Radius
-			if (context_raw.tool == workspace_tool_t.BRUSH  ||
-				context_raw.tool == workspace_tool_t.ERASER ||
-				context_raw.tool == workspace_tool_t.DECAL  ||
-				context_raw.tool == workspace_tool_t.TEXT   ||
-				context_raw.tool == workspace_tool_t.CLONE  ||
-				context_raw.tool == workspace_tool_t.BLUR   ||
-				context_raw.tool == workspace_tool_t.SMUDGE   ||
-				context_raw.tool == workspace_tool_t.PARTICLE) {
-				if (operator_shortcut(config_keymap.brush_radius) ||
-					operator_shortcut(config_keymap.brush_opacity) ||
-					operator_shortcut(config_keymap.brush_angle) ||
-					(decal_mask && operator_shortcut(config_keymap.decal_mask + "+" + config_keymap.brush_radius))) {
-					context_raw.brush_can_lock = true;
-					if (!pen_connected) mouse_lock();
-					context_raw.lock_started_x = mouse_x;
-					context_raw.lock_started_y = mouse_y;
-				}
-				else if (operator_shortcut(config_keymap.brush_radius_decrease, shortcut_type_t.REPEAT)) {
-					context_raw.brush_radius -= UIBase.get_radius_increment();
-					context_raw.brush_radius = Math.max(Math.round(context_raw.brush_radius * 100) / 100, 0.01);
-					context_raw.brush_radius_handle.value = context_raw.brush_radius;
-					UIHeader.header_handle.redraws = 2;
-				}
-				else if (operator_shortcut(config_keymap.brush_radius_increase, shortcut_type_t.REPEAT)) {
-					context_raw.brush_radius += UIBase.get_radius_increment();
-					context_raw.brush_radius = Math.round(context_raw.brush_radius * 100) / 100;
-					context_raw.brush_radius_handle.value = context_raw.brush_radius;
-					UIHeader.header_handle.redraws = 2;
-				}
-				else if (decal_mask) {
-					if (operator_shortcut(config_keymap.decal_mask + "+" + config_keymap.brush_radius_decrease, shortcut_type_t.REPEAT)) {
-						context_raw.brush_decal_mask_radius -= UIBase.get_radius_increment();
-						context_raw.brush_decal_mask_radius = Math.max(Math.round(context_raw.brush_decal_mask_radius * 100) / 100, 0.01);
-						context_raw.brush_decal_mask_radius_handle.value = context_raw.brush_decal_mask_radius;
-						UIHeader.header_handle.redraws = 2;
-					}
-					else if (operator_shortcut(config_keymap.decal_mask + "+" + config_keymap.brush_radius_increase, shortcut_type_t.REPEAT)) {
-						context_raw.brush_decal_mask_radius += UIBase.get_radius_increment();
-						context_raw.brush_decal_mask_radius = Math.round(context_raw.brush_decal_mask_radius * 100) / 100;
-						context_raw.brush_decal_mask_radius_handle.value = context_raw.brush_decal_mask_radius;
-						UIHeader.header_handle.redraws = 2;
-					}
-				}
-			}
-
-			if (decal_mask && (operator_shortcut(config_keymap.decal_mask, shortcut_type_t.STARTED) || operator_shortcut(config_keymap.decal_mask, shortcut_type_t.RELEASED))) {
-				UIHeader.header_handle.redraws = 2;
-			}
-			///end
-
-			///if is_lab
-			if (UIHeader.worktab.position == space_type_t.SPACE3D) {
-				// Radius
-				if (context_raw.tool == workspace_tool_t.ERASER ||
-					context_raw.tool == workspace_tool_t.CLONE  ||
-					context_raw.tool == workspace_tool_t.BLUR   ||
-					context_raw.tool == workspace_tool_t.SMUDGE) {
-					if (operator_shortcut(config_keymap.brush_radius)) {
-						context_raw.brush_can_lock = true;
-						if (!pen_connected) mouse_lock();
-						context_raw.lock_started_x = mouse_x;
-						context_raw.lock_started_y = mouse_y;
-					}
-					else if (operator_shortcut(config_keymap.brush_radius_decrease, shortcut_type_t.REPEAT)) {
-						context_raw.brush_radius -= UIBase.get_radius_increment();
-						context_raw.brush_radius = Math.max(Math.round(context_raw.brush_radius * 100) / 100, 0.01);
-						context_raw.brush_radius_handle.value = context_raw.brush_radius;
-						UIHeader.header_handle.redraws = 2;
-					}
-					else if (operator_shortcut(config_keymap.brush_radius_increase, shortcut_type_t.REPEAT)) {
-						context_raw.brush_radius += UIBase.get_radius_increment();
-						context_raw.brush_radius = Math.round(context_raw.brush_radius * 100) / 100;
-						context_raw.brush_radius_handle.value = context_raw.brush_radius;
-						UIHeader.header_handle.redraws = 2;
-					}
-				}
-			}
-			///end
-
-			// Viewpoint
-			if (mouse_view_x() < app_w()) {
-				if (operator_shortcut(config_keymap.view_reset)) {
-					viewport_reset();
-					viewport_scale_to_bounds();
-				}
-				else if (operator_shortcut(config_keymap.view_back)) viewport_set_view(0, 1, 0, Math.PI / 2, 0, Math.PI);
-				else if (operator_shortcut(config_keymap.view_front)) viewport_set_view(0, -1, 0, Math.PI / 2, 0, 0);
-				else if (operator_shortcut(config_keymap.view_left)) viewport_set_view(-1, 0, 0, Math.PI / 2, 0, -Math.PI / 2);
-				else if (operator_shortcut(config_keymap.view_right)) viewport_set_view(1, 0, 0, Math.PI / 2, 0, Math.PI / 2);
-				else if (operator_shortcut(config_keymap.view_bottom)) viewport_set_view(0, 0, -1, Math.PI, 0, Math.PI);
-				else if (operator_shortcut(config_keymap.view_camera_type)) {
-					context_raw.camera_type = context_raw.camera_type == camera_type_t.PERSPECTIVE ? camera_type_t.ORTHOGRAPHIC : camera_type_t.PERSPECTIVE;
-					context_raw.cam_handle.position = context_raw.camera_type;
-					viewport_update_camera_type(context_raw.camera_type);
-				}
-				else if (operator_shortcut(config_keymap.view_orbit_left, shortcut_type_t.REPEAT)) viewport_orbit(-Math.PI / 12, 0);
-				else if (operator_shortcut(config_keymap.view_orbit_right, shortcut_type_t.REPEAT)) viewport_orbit(Math.PI / 12, 0);
-				else if (operator_shortcut(config_keymap.view_orbit_up, shortcut_type_t.REPEAT)) viewport_orbit(0, -Math.PI / 12);
-				else if (operator_shortcut(config_keymap.view_orbit_down, shortcut_type_t.REPEAT)) viewport_orbit(0, Math.PI / 12);
-				else if (operator_shortcut(config_keymap.view_orbit_opposite)) viewport_orbit_opposite();
-				else if (operator_shortcut(config_keymap.view_zoom_in, shortcut_type_t.REPEAT)) viewport_zoom(0.2);
-				else if (operator_shortcut(config_keymap.view_zoom_out, shortcut_type_t.REPEAT)) viewport_zoom(-0.2);
-				else if (operator_shortcut(config_keymap.viewport_mode)) {
-
-					let count: i32;
-
-					///if (is_paint || is_sculpt)
-					count = 16;
-					///if (krom_direct3d12 || krom_vulkan || krom_metal)
-					count += 1;
-					///end
-					///end
-
-					///if is_lab
-					count = 9;
-					///if (krom_direct3d12 || krom_vulkan || krom_metal)
-					count += 1;
-					///end
-					///end
-
-					UIMenu.draw((ui: zui_t) => {
-						let mode_handle: zui_handle_t = zui_handle("uibase_0");
-						mode_handle.position = context_raw.viewport_mode;
-						zui_text(tr("Viewport Mode"), zui_align_t.RIGHT, ui.t.HIGHLIGHT_COL);
-						let modes: string[] = [
-							tr("Lit"),
-							tr("Base Color"),
-							tr("Normal"),
-							tr("Occlusion"),
-							tr("Roughness"),
-							tr("Metallic"),
-							tr("Opacity"),
-							tr("Height"),
-							///if (is_paint || is_sculpt)
-							tr("Emission"),
-							tr("Subsurface"),
-							tr("TexCoord"),
-							tr("Object Normal"),
-							tr("Material ID"),
-							tr("Object ID"),
-							tr("Mask")
-							///end
-						];
-
-						let shortcuts: string[] = ["l", "b", "n", "o", "r", "m", "a", "h", "e", "s", "t", "1", "2", "3", "4"];
-
-						///if (krom_direct3d12 || krom_vulkan || krom_metal)
-						if (krom_raytrace_supported()) {
-							modes.push(tr("Path Traced"));
-							shortcuts.push("p");
-						}
-						///end
-
-						for (let i: i32 = 0; i < modes.length; ++i) {
-							zui_radio(mode_handle, i, modes[i], shortcuts[i]);
-						}
-
-						let index: i32 = shortcuts.indexOf(keyboard_key_code(ui.key));
-						if (ui.is_key_pressed && index != -1) {
-							mode_handle.position = index;
-							ui.changed = true;
-							context_set_viewport_mode(mode_handle.position);
-						}
-						else if (mode_handle.changed) {
-							context_set_viewport_mode(mode_handle.position);
-							ui.changed = true;
-						}
-					}, count);
-				}
-			}
-
-			if (operator_shortcut(config_keymap.operator_search)) UIBase.operator_search();
-		}
-
-		if (context_raw.brush_can_lock || context_raw.brush_locked) {
-			if (mouse_moved && context_raw.brush_can_unlock) {
-				context_raw.brush_locked = false;
-				context_raw.brush_can_unlock = false;
-			}
-
-			///if (is_paint || is_sculpt)
-			let b: bool = (context_raw.brush_can_lock || context_raw.brush_locked) &&
-				!operator_shortcut(config_keymap.brush_radius, shortcut_type_t.DOWN) &&
-				!operator_shortcut(config_keymap.brush_opacity, shortcut_type_t.DOWN) &&
-				!operator_shortcut(config_keymap.brush_angle, shortcut_type_t.DOWN) &&
-				!(decal_mask && operator_shortcut(config_keymap.decal_mask + "+" + config_keymap.brush_radius, shortcut_type_t.DOWN));
-			///end
-			///if is_lab
-			let b: bool = (context_raw.brush_can_lock || context_raw.brush_locked) &&
-				!operator_shortcut(config_keymap.brush_radius, shortcut_type_t.DOWN);
-			///end
-
-			if (b) {
-				mouse_unlock();
-				context_raw.last_paint_x = -1;
-				context_raw.last_paint_y = -1;
-				if (context_raw.brush_can_lock) {
-					context_raw.brush_can_lock = false;
-					context_raw.brush_can_unlock = false;
-					context_raw.brush_locked = false;
-				}
-				else {
-					context_raw.brush_can_unlock = true;
-				}
-			}
-		}
-
-		///if (is_paint || is_sculpt)
-		if (UIBase.border_handle_ptr != 0) {
-			if (UIBase.border_handle_ptr == UINodes.hwnd.ptr || UIBase.border_handle_ptr == UIView2D.hwnd.ptr) {
-				if (UIBase.border_started == border_side_t.LEFT) {
-					config_raw.layout[layout_size_t.NODES_W] -= Math.floor(mouse_movement_x);
-					if (config_raw.layout[layout_size_t.NODES_W] < 32) config_raw.layout[layout_size_t.NODES_W] = 32;
-					else if (config_raw.layout[layout_size_t.NODES_W] > sys_width() * 0.7) config_raw.layout[layout_size_t.NODES_W] = Math.floor(sys_width() * 0.7);
-				}
-				else { // UINodes / UIView2D ratio
-					config_raw.layout[layout_size_t.NODES_H] -= Math.floor(mouse_movement_y);
-					if (config_raw.layout[layout_size_t.NODES_H] < 32) config_raw.layout[layout_size_t.NODES_H] = 32;
-					else if (config_raw.layout[layout_size_t.NODES_H] > app_h() * 0.95) config_raw.layout[layout_size_t.NODES_H] = Math.floor(app_h() * 0.95);
-				}
-			}
-			else if (UIBase.border_handle_ptr == UIBase.hwnds[tab_area_t.STATUS].ptr) {
-				let my: i32 = Math.floor(mouse_movement_y);
-				if (config_raw.layout[layout_size_t.STATUS_H] - my >= UIStatus.default_status_h * config_raw.window_scale && config_raw.layout[layout_size_t.STATUS_H] - my < sys_height() * 0.7) {
-					config_raw.layout[layout_size_t.STATUS_H] -= my;
-				}
-			}
-			else {
-				if (UIBase.border_started == border_side_t.LEFT) {
-					config_raw.layout[layout_size_t.SIDEBAR_W] -= Math.floor(mouse_movement_x);
-					if (config_raw.layout[layout_size_t.SIDEBAR_W] < UIBase.sidebar_mini_w) config_raw.layout[layout_size_t.SIDEBAR_W] = UIBase.sidebar_mini_w;
-					else if (config_raw.layout[layout_size_t.SIDEBAR_W] > sys_width() - UIBase.sidebar_mini_w) config_raw.layout[layout_size_t.SIDEBAR_W] = sys_width() - UIBase.sidebar_mini_w;
-				}
-				else {
-					let my: i32 = Math.floor(mouse_movement_y);
-					if (UIBase.border_handle_ptr == UIBase.hwnds[tab_area_t.SIDEBAR1].ptr && UIBase.border_started == border_side_t.TOP) {
-						if (config_raw.layout[layout_size_t.SIDEBAR_H0] + my > 32 && config_raw.layout[layout_size_t.SIDEBAR_H1] - my > 32) {
-							config_raw.layout[layout_size_t.SIDEBAR_H0] += my;
-							config_raw.layout[layout_size_t.SIDEBAR_H1] -= my;
-						}
-					}
-				}
-			}
-		}
-		///end
-
-		///if is_lab
-		if (UIBase.border_handle_ptr != 0) {
-			if (UIBase.border_handle_ptr == UINodes.hwnd.ptr || UIBase.border_handle_ptr == UIView2D.hwnd.ptr) {
-				if (UIBase.border_started == border_side_t.LEFT) {
-					config_raw.layout[layout_size_t.NODES_W] -= Math.floor(mouse_movement_x);
-					if (config_raw.layout[layout_size_t.NODES_W] < 32) config_raw.layout[layout_size_t.NODES_W] = 32;
-					else if (config_raw.layout[layout_size_t.NODES_W] > sys_width() * 0.7) config_raw.layout[layout_size_t.NODES_W] = Math.floor(sys_width() * 0.7);
-				}
-				else { // UINodes / UIView2D ratio
-					config_raw.layout[layout_size_t.NODES_H] -= Math.floor(mouse_movement_y);
-					if (config_raw.layout[layout_size_t.NODES_H] < 32) config_raw.layout[layout_size_t.NODES_H] = 32;
-					else if (config_raw.layout[layout_size_t.NODES_H] > app_h() * 0.95) config_raw.layout[layout_size_t.NODES_H] = Math.floor(app_h() * 0.95);
-				}
-			}
-			else if (UIBase.border_handle_ptr == UIBase.hwnds[tab_area_t.STATUS].ptr) {
-				let my: i32 = Math.floor(mouse_movement_y);
-				if (config_raw.layout[layout_size_t.STATUS_H] - my >= UIStatus.default_status_h * config_raw.window_scale && config_raw.layout[layout_size_t.STATUS_H] - my < sys_height() * 0.7) {
-					config_raw.layout[layout_size_t.STATUS_H] -= my;
-				}
-			}
-		}
-		///end
-
-		if (!mouse_down()) {
-			UIBase.border_handle_ptr = 0;
-			base_is_resizing = false;
-		}
-
-		///if arm_physics
-		if (context_raw.tool == workspace_tool_t.PARTICLE && context_raw.particle_physics && context_in_paint_area() && !context_raw.paint2d) {
-			UtilParticle.init_particle_physics();
-			let world: PhysicsWorldRaw = PhysicsWorld.active;
-			PhysicsWorld.late_update(world);
-			context_raw.ddirty = 2;
-			context_raw.rdirty = 2;
-			if (mouse_started()) {
-				if (context_raw.particle_timer != null) {
-					tween_stop(context_raw.particle_timer);
-					context_raw.particle_timer.done();
-					context_raw.particle_timer = null;
-				}
-				history_push_undo = true;
-				context_raw.particle_hit_x = context_raw.particle_hit_y = context_raw.particle_hit_z = 0;
-				let o: object_t = scene_spawn_object(".Sphere");
-				let md: material_data_t = data_get_material("Scene", ".Gizmo");
-				let mo: mesh_object_t = o.ext;
-				mo.base.name = ".Bullet";
-				mo.materials[0] = md;
-				mo.base.visible = true;
-
-				let camera: camera_object_t = scene_camera;
-				let ct: transform_t = camera.base.transform;
-				vec4_set(mo.base.transform.loc, transform_world_x(ct), transform_world_y(ct), transform_world_z(ct));
-				vec4_set(mo.base.transform.scale, context_raw.brush_radius * 0.2, context_raw.brush_radius * 0.2, context_raw.brush_radius * 0.2);
-				transform_build_matrix(mo.base.transform);
-
-				let body: PhysicsBodyRaw = PhysicsBody.create();
-				body.shape = shape_type_t.SPHERE;
-				body.mass = 1.0;
-				body.ccd = true;
-				mo.base.transform.radius /= 10; // Lower ccd radius
-				PhysicsBody.init(body, mo.base);
-				(mo.base as any).physicsBody = body;
-				mo.base.transform.radius *= 10;
-
-				let ray: ray_t = raycast_get_ray(mouse_view_x(), mouse_view_y(), camera);
-				PhysicsBody.apply_impulse(body, vec4_mult(ray.dir, 0.15));
-
-				context_raw.particle_timer = tween_timer(5, function() { mesh_object_remove(mo); });
-			}
-
-			let pairs: pair_t[] = PhysicsWorld.get_contact_pairs(world, context_raw.paint_body);
-			if (pairs != null) {
-				for (let p of pairs) {
-					context_raw.last_particle_hit_x = context_raw.particle_hit_x != 0 ? context_raw.particle_hit_x : p.pos_a.x;
-					context_raw.last_particle_hit_y = context_raw.particle_hit_y != 0 ? context_raw.particle_hit_y : p.pos_a.y;
-					context_raw.last_particle_hit_z = context_raw.particle_hit_z != 0 ? context_raw.particle_hit_z : p.pos_a.z;
-					context_raw.particle_hit_x = p.pos_a.x;
-					context_raw.particle_hit_y = p.pos_a.y;
-					context_raw.particle_hit_z = p.pos_a.z;
-					context_raw.pdirty = 1;
-					break; // 1 pair for now
-				}
-			}
-		}
-		///end
-	}
-
-	static view_top = () => {
-		let is_typing: bool = UIBase.ui.is_typing || UIView2D.ui.is_typing || UINodes.ui.is_typing;
-
-		if (context_in_paint_area() && !is_typing) {
-			if (mouse_view_x() < app_w()) {
-				viewport_set_view(0, 0, 1, 0, 0, 0);
-			}
-		}
-	}
-
-	static operator_search = () => {
-		let search_handle: zui_handle_t = zui_handle("uibase_1");
-		let first: bool = true;
-		UIMenu.draw((ui: zui_t) => {
-			zui_fill(0, 0, ui._w / zui_SCALE(ui), ui.t.ELEMENT_H * 8, ui.t.SEPARATOR_COL);
-			let search: string = zui_text_input(search_handle, "", zui_align_t.LEFT, true, true);
-			ui.changed = false;
-			if (first) {
-				first = false;
-				search_handle.text = "";
-				zui_start_text_edit(search_handle); // Focus search bar
-			}
-
-			if (search_handle.changed) UIBase.operator_search_offset = 0;
-
-			if (ui.is_key_pressed) { // Move selection
-				if (ui.key == key_code_t.DOWN && UIBase.operator_search_offset < 6) UIBase.operator_search_offset++;
-				if (ui.key == key_code_t.UP && UIBase.operator_search_offset > 0) UIBase.operator_search_offset--;
-			}
-			let enter: bool = keyboard_down("enter");
-			let count: i32 = 0;
-			let BUTTON_COL: i32 = ui.t.BUTTON_COL;
-
-			for (let n in config_keymap) {
-				if (n.indexOf(search) >= 0) {
-					ui.t.BUTTON_COL = count == UIBase.operator_search_offset ? ui.t.HIGHLIGHT_COL : ui.t.SEPARATOR_COL;
-					if (zui_button(n, zui_align_t.LEFT, config_keymap[n]) || (enter && count == UIBase.operator_search_offset)) {
-						if (enter) {
-							ui.changed = true;
-							count = 6; // Trigger break
-						}
-						operator_run(n);
-					}
-					if (++count > 6) break;
-				}
-			}
-
-			if (enter && count == 0) { // Hide popup on enter when command is not found
-				ui.changed = true;
-				search_handle.text = "";
-			}
-			ui.t.BUTTON_COL = BUTTON_COL;
-		}, 8, -1, -1);
-	}
-
-	static toggle_distract_free = () => {
-		UIBase.show = !UIBase.show;
-		base_resize();
-	}
-
-	static get_radius_increment = (): f32 => {
-		return 0.1;
-	}
-
-	static hit_rect = (mx: f32, my: f32, x: i32, y: i32, w: i32, h: i32) => {
-		return mx > x && mx < x + w && my > y && my < y + h;
-	}
-
-	///if (is_paint || is_sculpt)
-	static get_brush_stencil_rect = (): rect_t => {
-		let w: i32 = Math.floor(context_raw.brush_stencil_image.width * (base_h() / context_raw.brush_stencil_image.height) * context_raw.brush_stencil_scale);
-		let h: i32 = Math.floor(base_h() * context_raw.brush_stencil_scale);
-		let x: i32 = Math.floor(base_x() + context_raw.brush_stencil_x * base_w());
-		let y: i32 = Math.floor(base_y() + context_raw.brush_stencil_y * base_h());
-		return { w: w, h: h, x: x, y: y };
-	}
-	///end
-
-	static update_ui = () => {
-		if (console_message_timer > 0) {
-			console_message_timer -= time_delta();
-			if (console_message_timer <= 0) UIBase.hwnds[tab_area_t.STATUS].redraws = 2;
-		}
-
-		///if (is_paint || is_sculpt)
-		UIBase.sidebar_mini_w = Math.floor(UIBase.default_sidebar_mini_w * zui_SCALE(UIBase.ui));
-		///end
-
-		if (!base_ui_enabled) return;
-
-		///if (is_paint || is_sculpt)
-		// Same mapping for paint and rotate (predefined in touch keymap)
-		if (context_in_viewport()) {
-			if (mouse_started() && config_keymap.action_paint == config_keymap.action_rotate) {
-				UIBase.action_paint_remap = config_keymap.action_paint;
-				UtilRender.pick_pos_nor_tex();
-				let is_mesh: bool = Math.abs(context_raw.posx_picked) < 50 && Math.abs(context_raw.posy_picked) < 50 && Math.abs(context_raw.posz_picked) < 50;
-				///if krom_android
-				// Allow rotating with both pen and touch, because hovering a pen prevents touch input on android
-				let pen_only: bool = false;
-				///else
-				let pen_only: bool = context_raw.pen_painting_only;
-				///end
-				let is_pen: bool = pen_only && pen_down();
-				// Mesh picked - disable rotate
-				// Pen painting only - rotate with touch, paint with pen
-				if ((is_mesh && !pen_only) || is_pen) {
-					config_keymap.action_rotate = "";
-					config_keymap.action_paint = UIBase.action_paint_remap;
-				}
-				// World sphere picked - disable paint
-				else {
-					config_keymap.action_paint = "";
-					config_keymap.action_rotate = UIBase.action_paint_remap;
-				}
-			}
-			else if (!mouse_down() && UIBase.action_paint_remap != "") {
-				config_keymap.action_rotate = UIBase.action_paint_remap;
-				config_keymap.action_paint = UIBase.action_paint_remap;
-				UIBase.action_paint_remap = "";
-			}
-		}
-
-		if (context_raw.brush_stencil_image != null && operator_shortcut(config_keymap.stencil_transform, shortcut_type_t.DOWN)) {
-			let r: rect_t = UIBase.get_brush_stencil_rect();
-			if (mouse_started("left")) {
-				context_raw.brush_stencil_scaling =
-					UIBase.hit_rect(mouse_x, mouse_y, r.x - 8,       r.y - 8,       16, 16) ||
-					UIBase.hit_rect(mouse_x, mouse_y, r.x - 8,       r.h + r.y - 8, 16, 16) ||
-					UIBase.hit_rect(mouse_x, mouse_y, r.w + r.x - 8, r.y - 8,       16, 16) ||
-					UIBase.hit_rect(mouse_x, mouse_y, r.w + r.x - 8, r.h + r.y - 8, 16, 16);
-				let cosa: f32 = Math.cos(-context_raw.brush_stencil_angle);
-				let sina: f32 = Math.sin(-context_raw.brush_stencil_angle);
-				let ox: f32 = 0;
-				let oy: f32 = -r.h / 2;
-				let x: f32 = ox * cosa - oy * sina;
-				let y: f32 = ox * sina + oy * cosa;
-				x += r.x + r.w / 2;
-				y += r.y + r.h / 2;
-				context_raw.brush_stencil_rotating =
-					UIBase.hit_rect(mouse_x, mouse_y, Math.floor(x - 16), Math.floor(y - 16), 32, 32);
-			}
-			let _scale: f32 = context_raw.brush_stencil_scale;
-			if (mouse_down("left")) {
-				if (context_raw.brush_stencil_scaling) {
-					let mult: i32 = mouse_x > r.x + r.w / 2 ? 1 : -1;
-					context_raw.brush_stencil_scale += mouse_movement_x / 400 * mult;
-				}
-				else if (context_raw.brush_stencil_rotating) {
-					let gizmo_x: f32 = r.x + r.w / 2;
-					let gizmo_y: f32 = r.y + r.h / 2;
-					context_raw.brush_stencil_angle = -Math.atan2(mouse_y - gizmo_y, mouse_x - gizmo_x) - Math.PI / 2;
-				}
-				else {
-					context_raw.brush_stencil_x += mouse_movement_x / base_w();
-					context_raw.brush_stencil_y += mouse_movement_y / base_h();
-				}
-			}
-			else context_raw.brush_stencil_scaling = false;
-			if (mouse_wheel_delta != 0) {
-				context_raw.brush_stencil_scale -= mouse_wheel_delta / 10;
-			}
-			// Center after scale
-			let ratio: f32 = base_h() / context_raw.brush_stencil_image.height;
-			let old_w: f32 = _scale * context_raw.brush_stencil_image.width * ratio;
-			let new_w: f32 = context_raw.brush_stencil_scale * context_raw.brush_stencil_image.width * ratio;
-			let old_h: f32 = _scale * base_h();
-			let new_h: f32 = context_raw.brush_stencil_scale * base_h();
-			context_raw.brush_stencil_x += (old_w - new_w) / base_w() / 2;
-			context_raw.brush_stencil_y += (old_h - new_h) / base_h() / 2;
-		}
-		///end
-
-		let set_clone_source: bool = context_raw.tool == workspace_tool_t.CLONE && operator_shortcut(config_keymap.set_clone_source + "+" + config_keymap.action_paint, shortcut_type_t.DOWN);
-
-		///if (is_paint || is_sculpt)
-		let decal: bool = context_raw.tool == workspace_tool_t.DECAL || context_raw.tool == workspace_tool_t.TEXT;
-		let decal_mask: bool = decal && operator_shortcut(config_keymap.decal_mask + "+" + config_keymap.action_paint, shortcut_type_t.DOWN);
-		let down: bool = operator_shortcut(config_keymap.action_paint, shortcut_type_t.DOWN) ||
-				   		 decal_mask ||
-				   		 set_clone_source ||
-				   		 operator_shortcut(config_keymap.brush_ruler + "+" + config_keymap.action_paint, shortcut_type_t.DOWN) ||
-				   		 (pen_down() && !keyboard_down("alt"));
-		///end
-		///if is_lab
-		let down: bool = operator_shortcut(config_keymap.action_paint, shortcut_type_t.DOWN) ||
-				   		 set_clone_source ||
-				   		 operator_shortcut(config_keymap.brush_ruler + "+" + config_keymap.action_paint, shortcut_type_t.DOWN) ||
-				   		 (pen_down() && !keyboard_down("alt"));
-		///end
-
-		if (config_raw.touch_ui) {
-			if (pen_down()) {
-				context_raw.pen_painting_only = true;
-			}
-			else if (context_raw.pen_painting_only) {
-				down = false;
-			}
-		}
-
-		///if arm_physics
-		if (context_raw.tool == workspace_tool_t.PARTICLE && context_raw.particle_physics) {
-			down = false;
-		}
-		///end
-
-		///if (is_paint || is_sculpt)
-		///if krom_ios
-		// No hover on iPad, decals are painted by pen release
-		if (decal) {
-			down = pen_released();
-			if (!context_raw.pen_painting_only) {
-				down = down || mouse_released();
-			}
-		}
-		///end
-		///end
-
-		if (down) {
-			let mx: i32 = mouse_view_x();
-			let my: i32 = mouse_view_y();
-			let ww: i32 = app_w();
-
-			///if (is_paint || is_sculpt)
-			if (context_raw.paint2d) {
-				mx -= app_w();
-				ww = UIView2D.ww;
-			}
-			///end
-
-			if (mx < ww &&
-				mx > app_x() &&
-				my < app_h() &&
-				my > app_y()) {
-
-				if (set_clone_source) {
-					context_raw.clone_start_x = mx;
-					context_raw.clone_start_y = my;
-				}
-				else {
-					if (context_raw.brush_time == 0 &&
-						!base_is_dragging &&
-						!base_is_resizing &&
-						!base_is_combo_selected()) { // Paint started
-
-						// Draw line
-						if (operator_shortcut(config_keymap.brush_ruler + "+" + config_keymap.action_paint, shortcut_type_t.DOWN)) {
-							context_raw.last_paint_vec_x = context_raw.last_paint_x;
-							context_raw.last_paint_vec_y = context_raw.last_paint_y;
-						}
-
-						///if (is_paint || is_sculpt)
-						history_push_undo = true;
-
-						if (context_raw.tool == workspace_tool_t.CLONE && context_raw.clone_start_x >= 0.0) { // Clone delta
-							context_raw.clone_delta_x = (context_raw.clone_start_x - mx) / ww;
-							context_raw.clone_delta_y = (context_raw.clone_start_y - my) / app_h();
-							context_raw.clone_start_x = -1;
-						}
-						else if (context_raw.tool == workspace_tool_t.PARTICLE) {
-							// Reset particles
-							///if arm_particles
-							let emitter: mesh_object_t = scene_get_child(".ParticleEmitter").ext;
-							let psys: particle_sys_t = emitter.particle_systems[0];
-							psys.time = 0;
-							// psys.time = psys.seed * psys.animtime;
-							// psys.seed++;
-							///end
-						}
-						else if (context_raw.tool == workspace_tool_t.FILL && context_raw.fill_type_handle.position == fill_type_t.UV_ISLAND) {
-							UtilUV.uvislandmap_cached = false;
-						}
-						///end
-					}
-
-					context_raw.brush_time += time_delta();
-
-					///if (is_paint || is_sculpt)
-					if (context_raw.run_brush != null) {
-						context_raw.run_brush(0);
-					}
-					///end
-					///if is_lab
-					if (context_run_brush != null) {
-						context_run_brush(0);
-					}
-					///end
-				}
-			}
-		}
-		else if (context_raw.brush_time > 0) { // Brush released
-			context_raw.brush_time = 0;
-			context_raw.prev_paint_vec_x = -1;
-			context_raw.prev_paint_vec_y = -1;
-			///if (!krom_direct3d12 && !krom_vulkan && !krom_metal) // Keep accumulated samples for D3D12
-			context_raw.ddirty = 3;
-			///end
-			context_raw.brush_blend_dirty = true; // Update brush mask
-
-			///if (is_paint || is_sculpt)
-			context_raw.layer_preview_dirty = true; // Update layer preview
-			///end
-
-			///if is_paint
-			// New color id picked, update fill layer
-			if (context_raw.tool == workspace_tool_t.COLORID && context_raw.layer.fill_layer != null) {
-				base_notify_on_next_frame(() => {
-					base_update_fill_layer();
-					MakeMaterial.parse_paint_material(false);
-				});
-			}
-			///end
-		}
-
-		///if is_paint
-		if (context_raw.layers_preview_dirty) {
-			context_raw.layers_preview_dirty = false;
-			context_raw.layer_preview_dirty = false;
-			context_raw.mask_preview_last = null;
-			if (base_pipe_merge == null) base_make_pipe();
-			// Update all layer previews
-			for (let l of project_layers) {
-				if (SlotLayer.is_group(l)) continue;
-				let target: image_t = l.texpaint_preview;
-				let source: image_t = l.texpaint;
-				g2_begin(target);
-				g2_clear(0x00000000);
-				// g2_set_pipeline(l.isMask() ? base_pipe_copy8 : base_pipe_copy);
-				g2_set_pipeline(base_pipe_copy); // texpaint_preview is always RGBA32 for now
-				g2_draw_scaled_image(source, 0, 0, target.width, target.height);
-				g2_set_pipeline(null);
-				g2_end();
-			}
-			UIBase.hwnds[tab_area_t.SIDEBAR0].redraws = 2;
-		}
-		if (context_raw.layer_preview_dirty && !SlotLayer.is_group(context_raw.layer)) {
-			context_raw.layer_preview_dirty = false;
-			context_raw.mask_preview_last = null;
-			if (base_pipe_merge == null) base_make_pipe();
-			// Update layer preview
-			let l: SlotLayerRaw = context_raw.layer;
-			let target: image_t = l.texpaint_preview;
-			let source: image_t = l.texpaint;
-			g2_begin(target);
-			g2_clear(0x00000000);
-			// g2_set_pipeline(raw.layer.isMask() ? base_pipe_copy8 : base_pipe_copy);
-			g2_set_pipeline(base_pipe_copy); // texpaint_preview is always RGBA32 for now
-			g2_draw_scaled_image(source, 0, 0, target.width, target.height);
-			g2_set_pipeline(null);
-			g2_end();
-			UIBase.hwnds[tab_area_t.SIDEBAR0].redraws = 2;
-		}
-		///end
-
-		let undo_pressed: bool = operator_shortcut(config_keymap.edit_undo);
-		let redo_pressed: bool = operator_shortcut(config_keymap.edit_redo) ||
-						  		(keyboard_down("control") && keyboard_started("y"));
-
-		// Two-finger tap to undo, three-finger tap to redo
-		if (context_in_viewport() && config_raw.touch_ui) {
-			if (mouse_started("middle")) { UIBase.redo_tap_time = time_time(); }
-			else if (mouse_started("right")) { UIBase.undo_tap_time = time_time(); }
-			else if (mouse_released("middle") && time_time() - UIBase.redo_tap_time < 0.1) { UIBase.redo_tap_time = UIBase.undo_tap_time = 0; redo_pressed = true; }
-			else if (mouse_released("right") && time_time() - UIBase.undo_tap_time < 0.1) { UIBase.redo_tap_time = UIBase.undo_tap_time = 0; undo_pressed = true; }
-		}
-
-		if (undo_pressed) history_undo();
-		else if (redo_pressed) history_redo();
-
-		///if (is_paint || is_sculpt)
-		gizmo_update();
-		///end
-	}
-
-	static render = () => {
-		if (!UIBase.show && config_raw.touch_ui) {
-			UIBase.ui.input_enabled = true;
-			g2_end();
-			zui_begin(UIBase.ui);
-			if (zui_window(zui_handle("uibase_2"), 0, 0, 150, Math.floor(zui_ELEMENT_H(UIBase.ui) + zui_ELEMENT_OFFSET(UIBase.ui) + 1))) {
-				if (zui_button(tr("Close"))) {
-					UIBase.toggle_distract_free();
-				}
-			}
-			zui_end();
-			g2_begin(null);
-		}
-
-		if (!UIBase.show || sys_width() == 0 || sys_height() == 0) return;
-
-		UIBase.ui.input_enabled = base_ui_enabled;
-
-		// Remember last tab positions
-		for (let i: i32 = 0; i < UIBase.htabs.length; ++i) {
-			if (UIBase.htabs[i].changed) {
-				config_raw.layout_tabs[i] = UIBase.htabs[i].position;
-				config_save();
-			}
-		}
-
-		// Set tab positions
-		for (let i: i32 = 0; i < UIBase.htabs.length; ++i) {
-			UIBase.htabs[i].position = config_raw.layout_tabs[i];
-		}
-
-		g2_end();
-		zui_begin(UIBase.ui);
-
-		///if (is_paint || is_sculpt)
-		UIToolbar.render_ui();
-		///end
-		UIMenubar.render_ui();
-		UIHeader.render_ui();
-		UIStatus.render_ui();
-
-		///if (is_paint || is_sculpt)
-		UIBase.draw_sidebar();
-		///end
-
-		zui_end();
-		g2_begin(null);
-	}
-
-	///if (is_paint || is_sculpt)
-	static draw_sidebar = () => {
-		// Tabs
-		let mini: bool = config_raw.layout[layout_size_t.SIDEBAR_W] <= UIBase.sidebar_mini_w;
-		let expand_button_offset: i32 = config_raw.touch_ui ? Math.floor(zui_ELEMENT_H(UIBase.ui) + zui_ELEMENT_OFFSET(UIBase.ui)) : 0;
-		UIBase.tabx = sys_width() - config_raw.layout[layout_size_t.SIDEBAR_W];
-
-		let _SCROLL_W: i32 = UIBase.ui.t.SCROLL_W;
-		if (mini) UIBase.ui.t.SCROLL_W = UIBase.ui.t.SCROLL_MINI_W;
-
-		if (zui_window(UIBase.hwnds[tab_area_t.SIDEBAR0], UIBase.tabx, 0, config_raw.layout[layout_size_t.SIDEBAR_W], config_raw.layout[layout_size_t.SIDEBAR_H0])) {
-			for (let i: i32 = 0; i < (mini ? 1 : UIBase.hwnd_tabs[tab_area_t.SIDEBAR0].length); ++i) UIBase.hwnd_tabs[tab_area_t.SIDEBAR0][i](UIBase.htabs[tab_area_t.SIDEBAR0]);
-		}
-		if (zui_window(UIBase.hwnds[tab_area_t.SIDEBAR1], UIBase.tabx, config_raw.layout[layout_size_t.SIDEBAR_H0], config_raw.layout[layout_size_t.SIDEBAR_W], config_raw.layout[layout_size_t.SIDEBAR_H1] - expand_button_offset)) {
-			for (let i: i32 = 0; i < (mini ? 1 : UIBase.hwnd_tabs[tab_area_t.SIDEBAR1].length); ++i) UIBase.hwnd_tabs[tab_area_t.SIDEBAR1][i](UIBase.htabs[tab_area_t.SIDEBAR1]);
-		}
-
-		zui_end_window();
-		UIBase.ui.t.SCROLL_W = _SCROLL_W;
-
-		// Collapse / expand button for mini sidebar
-		if (config_raw.touch_ui) {
-			let width: i32 = config_raw.layout[layout_size_t.SIDEBAR_W];
-			let height: i32 = Math.floor(zui_ELEMENT_H(UIBase.ui) + zui_ELEMENT_OFFSET(UIBase.ui));
-			if (zui_window(zui_handle("uibase_3"), sys_width() - width, sys_height() - height, width, height + 1)) {
-				UIBase.ui._w = width;
-				let _BUTTON_H: i32 = UIBase.ui.t.BUTTON_H;
-				let _BUTTON_COL: i32 = UIBase.ui.t.BUTTON_COL;
-				UIBase.ui.t.BUTTON_H = UIBase.ui.t.ELEMENT_H;
-				UIBase.ui.t.BUTTON_COL = UIBase.ui.t.WINDOW_BG_COL;
-				if (zui_button(mini ? "<<" : ">>")) {
-					config_raw.layout[layout_size_t.SIDEBAR_W] = mini ? UIBase.default_sidebar_full_w : UIBase.default_sidebar_mini_w;
-					config_raw.layout[layout_size_t.SIDEBAR_W] = Math.floor(config_raw.layout[layout_size_t.SIDEBAR_W] * zui_SCALE(UIBase.ui));
-				}
-				UIBase.ui.t.BUTTON_H = _BUTTON_H;
-				UIBase.ui.t.BUTTON_COL = _BUTTON_COL;
-			}
-		}
-
-		// Expand button
-		if (config_raw.layout[layout_size_t.SIDEBAR_W] == 0) {
-			let width: i32 = Math.floor(g2_font_width(UIBase.ui.font, UIBase.ui.font_size, "<<") + 25 * zui_SCALE(UIBase.ui));
-			if (zui_window(UIBase.hminimized, sys_width() - width, 0, width, Math.floor(zui_ELEMENT_H(UIBase.ui) + zui_ELEMENT_OFFSET(UIBase.ui) + 1))) {
-				UIBase.ui._w = width;
-				let _BUTTON_H: i32 = UIBase.ui.t.BUTTON_H;
-				let _BUTTON_COL: i32 = UIBase.ui.t.BUTTON_COL;
-				UIBase.ui.t.BUTTON_H = UIBase.ui.t.ELEMENT_H;
-				UIBase.ui.t.BUTTON_COL = UIBase.ui.t.SEPARATOR_COL;
-
-				if (zui_button("<<")) {
-					config_raw.layout[layout_size_t.SIDEBAR_W] = context_raw.maximized_sidebar_width != 0 ? context_raw.maximized_sidebar_width : Math.floor(UIBase.default_sidebar_w * config_raw.window_scale);
-				}
-				UIBase.ui.t.BUTTON_H = _BUTTON_H;
-				UIBase.ui.t.BUTTON_COL = _BUTTON_COL;
-			}
-		}
-		else if (UIBase.htabs[tab_area_t.SIDEBAR0].changed && UIBase.htabs[tab_area_t.SIDEBAR0].position == context_raw.last_htab0_pos) {
-			if (time_time() - context_raw.select_time < 0.25) {
-				context_raw.maximized_sidebar_width = config_raw.layout[layout_size_t.SIDEBAR_W];
-				config_raw.layout[layout_size_t.SIDEBAR_W] = 0;
-			}
-			context_raw.select_time = time_time();
-		}
-		context_raw.last_htab0_pos = UIBase.htabs[tab_area_t.SIDEBAR0].position;
-	}
-
-	static render_cursor = () => {
-		if (!base_ui_enabled) return;
-
-		///if is_paint
-		if (context_raw.tool == workspace_tool_t.MATERIAL || context_raw.tool == workspace_tool_t.BAKE) return;
-		///end
-
-		g2_set_color(0xffffffff);
-
-		context_raw.view_index = context_raw.view_index_last;
-		let mx: i32 = base_x() + context_raw.paint_vec.x * base_w();
-		let my: i32 = base_y() + context_raw.paint_vec.y * base_h();
-		context_raw.view_index = -1;
-
-		// Radius being scaled
-		if (context_raw.brush_locked) {
-			mx += context_raw.lock_started_x - sys_width() / 2;
-			my += context_raw.lock_started_y - sys_height() / 2;
-		}
-
-		let tool: workspace_tool_t = context_raw.tool as workspace_tool_t;
-
-		///if is_paint
-		if (context_raw.brush_stencil_image != null &&
-			tool != workspace_tool_t.BAKE &&
-			tool != workspace_tool_t.PICKER &&
-			tool != workspace_tool_t.MATERIAL &&
-			tool != workspace_tool_t.COLORID) {
-			let r: rect_t = UIBase.get_brush_stencil_rect();
-			if (!operator_shortcut(config_keymap.stencil_hide, shortcut_type_t.DOWN)) {
-				g2_set_color(0x88ffffff);
-				let angle: f32 = context_raw.brush_stencil_angle;
-				let cx: f32 = r.x + r.w / 2;
-				let cy: f32 = r.y + r.h / 2;
-				g2_set_transformation(mat3_multmat(mat3_multmat(mat3_translation(cx, cy), mat3_rotation(-angle)), mat3_translation(-cx, -cy)));
-				g2_draw_scaled_image(context_raw.brush_stencil_image, r.x, r.y, r.w, r.h);
-				g2_set_transformation(null);
-				g2_set_color(0xffffffff);
-			}
-			let transform: bool = operator_shortcut(config_keymap.stencil_transform, shortcut_type_t.DOWN);
-			if (transform) {
-				// Outline
-				g2_draw_rect(r.x, r.y, r.w, r.h);
-				// Scale
-				g2_draw_rect(r.x - 8,       r.y - 8,       16, 16);
-				g2_draw_rect(r.x - 8 + r.w, r.y - 8,       16, 16);
-				g2_draw_rect(r.x - 8,       r.y - 8 + r.h, 16, 16);
-				g2_draw_rect(r.x - 8 + r.w, r.y - 8 + r.h, 16, 16);
-				// Rotate
-				let angle: f32 = context_raw.brush_stencil_angle;
-				let cx: f32 = r.x + r.w / 2;
-				let cy: f32 = r.y + r.h / 2;
-				g2_set_transformation(mat3_multmat(mat3_multmat(mat3_translation(cx, cy), mat3_rotation(-angle)), mat3_translation(-cx, -cy)));
-				g2_fill_circle(r.x + r.w / 2, r.y - 4, 8);
-				g2_set_transformation(null);
-			}
-		}
-		///end
-
-		// Show picked material next to cursor
-		if (context_raw.tool == workspace_tool_t.PICKER && context_raw.picker_select_material && context_raw.color_picker_callback == null) {
-			let img: image_t = context_raw.material.image_icon;
-			///if krom_opengl
-			g2_draw_scaled_image(img, mx + 10, my + 10 + img.height, img.width, -img.height);
-			///else
-			g2_draw_image(img, mx + 10, my + 10);
-			///end
-		}
-		if (context_raw.tool == workspace_tool_t.PICKER && context_raw.color_picker_callback != null) {
-			let img: image_t = resource_get("icons.k");
-			let rect: rect_t = resource_tile50(img, workspace_tool_t.PICKER, 0);
-			g2_draw_sub_image(img, mx + 10, my + 10, rect.x, rect.y, rect.w, rect.h);
-		}
-
-		let cursor_img: image_t = resource_get("cursor.k");
-		let psize: i32 = Math.floor(cursor_img.width * (context_raw.brush_radius * context_raw.brush_nodes_radius) * zui_SCALE(UIBase.ui));
-
-		// Clone source cursor
-		if (context_raw.tool == workspace_tool_t.CLONE && !keyboard_down("alt") && (mouse_down() || pen_down())) {
-			g2_set_color(0x66ffffff);
-			g2_draw_scaled_image(cursor_img, mx + context_raw.clone_delta_x * app_w() - psize / 2, my + context_raw.clone_delta_y * app_h() - psize / 2, psize, psize);
-			g2_set_color(0xffffffff);
-		}
-
-		let decal: bool = context_raw.tool == workspace_tool_t.DECAL || context_raw.tool == workspace_tool_t.TEXT;
-
-		if (!config_raw.brush_3d || context_in_2d_view() || decal) {
-			let decal_mask: bool = decal && operator_shortcut(config_keymap.decal_mask, shortcut_type_t.DOWN);
-			if (decal && !context_in_nodes()) {
-				let decal_alpha: f32 = 0.5;
-				if (!decal_mask) {
-					context_raw.decal_x = context_raw.paint_vec.x;
-					context_raw.decal_y = context_raw.paint_vec.y;
-					decal_alpha = context_raw.brush_opacity;
-
-					// Radius being scaled
-					if (context_raw.brush_locked) {
-						context_raw.decal_x += (context_raw.lock_started_x - sys_width() / 2) / base_w();
-						context_raw.decal_y += (context_raw.lock_started_y - sys_height() / 2) / base_h();
-					}
-				}
-
-				if (!config_raw.brush_live) {
-					let psizex: i32 = Math.floor(256 * zui_SCALE(UIBase.ui) * (context_raw.brush_radius * context_raw.brush_nodes_radius * context_raw.brush_scale_x));
-					let psizey: i32 = Math.floor(256 * zui_SCALE(UIBase.ui) * (context_raw.brush_radius * context_raw.brush_nodes_radius));
-
-					context_raw.view_index = context_raw.view_index_last;
-					let decalx: f32 = base_x() + context_raw.decal_x * base_w() - psizex / 2;
-					let decaly: f32 = base_y() + context_raw.decal_y * base_h() - psizey / 2;
-					context_raw.view_index = -1;
-
-					g2_set_color(color_from_floats(1, 1, 1, decal_alpha));
-					let angle: f32 = (context_raw.brush_angle + context_raw.brush_nodes_angle) * (Math.PI / 180);
-					let cx: f32 = decalx + psizex / 2;
-					let cy: f32 = decaly + psizey / 2;
-					g2_set_transformation(mat3_multmat(mat3_multmat(mat3_translation(cx, cy), mat3_rotation(angle)), mat3_translation(-cx, -cy)));
-					///if (krom_direct3d11 || krom_direct3d12 || krom_metal || krom_vulkan)
-					g2_draw_scaled_image(context_raw.decal_image, decalx, decaly, psizex, psizey);
-					///else
-					g2_draw_scaled_image(context_raw.decal_image, decalx, decaly + psizey, psizex, -psizey);
-					///end
-					g2_set_transformation(null);
-					g2_set_color(0xffffffff);
-				}
-			}
-			if (context_raw.tool == workspace_tool_t.BRUSH  ||
-				context_raw.tool == workspace_tool_t.ERASER ||
-				context_raw.tool == workspace_tool_t.CLONE  ||
-				context_raw.tool == workspace_tool_t.BLUR   ||
-				context_raw.tool == workspace_tool_t.SMUDGE   ||
-				context_raw.tool == workspace_tool_t.PARTICLE ||
-				(decal_mask && !config_raw.brush_3d) ||
-				(decal_mask && context_in_2d_view())) {
-				if (decal_mask) {
-					psize = Math.floor(cursor_img.width * (context_raw.brush_decal_mask_radius * context_raw.brush_nodes_radius) * zui_SCALE(UIBase.ui));
-				}
-				if (config_raw.brush_3d && context_in_2d_view()) {
-					psize = Math.floor(psize * UIView2D.pan_scale);
-				}
-				g2_draw_scaled_image(cursor_img, mx - psize / 2, my - psize / 2, psize, psize);
-			}
-		}
-
-		if (context_raw.brush_lazy_radius > 0 && !context_raw.brush_locked &&
-			(context_raw.tool == workspace_tool_t.BRUSH ||
-			 context_raw.tool == workspace_tool_t.ERASER ||
-			 context_raw.tool == workspace_tool_t.DECAL ||
-			 context_raw.tool == workspace_tool_t.TEXT ||
-			 context_raw.tool == workspace_tool_t.CLONE ||
-			 context_raw.tool == workspace_tool_t.BLUR ||
-			 context_raw.tool == workspace_tool_t.SMUDGE ||
-			 context_raw.tool == workspace_tool_t.PARTICLE)) {
-			g2_fill_rect(mx - 1, my - 1, 2, 2);
-			mx = context_raw.brush_lazy_x * base_w() + base_x();
-			my = context_raw.brush_lazy_y * base_h() + base_y();
-			let radius: f32 = context_raw.brush_lazy_radius * 180;
-			g2_set_color(0xff666666);
-			g2_draw_scaled_image(cursor_img, mx - radius / 2, my - radius / 2, radius, radius);
-			g2_set_color(0xffffffff);
-		}
-	}
-	///end
-
-	static show_material_nodes = () => {
-		// Clear input state as ui receives input events even when not drawn
-		zui_end_input();
-
-		///if (is_paint || is_sculpt)
-		UINodes.show = !UINodes.show || UINodes.canvas_type != canvas_type_t.MATERIAL;
-		UINodes.canvas_type = canvas_type_t.MATERIAL;
-		///end
-		///if is_lab
-		UINodes.show = !UINodes.show;
-		///end
-
-		base_resize();
-	}
-
-	///if (is_paint || is_sculpt)
-	static show_brush_nodes = () => {
-		// Clear input state as ui receives input events even when not drawn
-		zui_end_input();
-		UINodes.show = !UINodes.show || UINodes.canvas_type != canvas_type_t.BRUSH;
-		UINodes.canvas_type = canvas_type_t.BRUSH;
-		base_resize();
-	}
-	///end
-
-	static show_2d_view = (type: view_2d_type_t) => {
-		// Clear input state as ui receives input events even when not drawn
-		zui_end_input();
-		if (UIView2D.type != type) UIView2D.show = true;
-		else UIView2D.show = !UIView2D.show;
-		UIView2D.type = type;
-		UIView2D.hwnd.redraws = 2;
-		base_resize();
-	}
-
-	static toggle_browser = () => {
-		let minimized: bool = config_raw.layout[layout_size_t.STATUS_H] <= (UIStatus.default_status_h * config_raw.window_scale);
-		config_raw.layout[layout_size_t.STATUS_H] = minimized ? 240 : UIStatus.default_status_h;
-		config_raw.layout[layout_size_t.STATUS_H] = Math.floor(config_raw.layout[layout_size_t.STATUS_H] * config_raw.window_scale);
-	}
-
-	static set_icon_scale = () => {
-		if (zui_SCALE(UIBase.ui) > 1) {
-			resource_load(["icons2x.k"], () => {
-				resource_bundled.set("icons.k", resource_get("icons2x.k"));
-			});
-		}
-		else {
-			resource_load(["icons.k"], () => {});
-		}
-	}
-
-	static on_border_hover = (handle_ptr: i32, side: i32) => {
-		if (!base_ui_enabled) return;
-
-		///if (is_paint || is_sculpt)
-		if (handle_ptr != UIBase.hwnds[tab_area_t.SIDEBAR0].ptr &&
-			handle_ptr != UIBase.hwnds[tab_area_t.SIDEBAR1].ptr &&
-			handle_ptr != UIBase.hwnds[tab_area_t.STATUS].ptr &&
-			handle_ptr != UINodes.hwnd.ptr &&
-			handle_ptr != UIView2D.hwnd.ptr) return; // Scalable handles
-		if (handle_ptr == UIView2D.hwnd.ptr && side != border_side_t.LEFT) return;
-		if (handle_ptr == UINodes.hwnd.ptr && side == border_side_t.TOP && !UIView2D.show) return;
-		if (handle_ptr == UIBase.hwnds[tab_area_t.SIDEBAR0].ptr && side == border_side_t.TOP) return;
-		///end
-
-		///if is_lab
-		if (handle_ptr != UIBase.hwnds[tab_area_t.STATUS].ptr &&
-			handle_ptr != UINodes.hwnd.ptr &&
-			handle_ptr != UIView2D.hwnd.ptr) return; // Scalable handles
-		if (handle_ptr == UIView2D.hwnd.ptr && side != border_side_t.LEFT) return;
-		if (handle_ptr == UINodes.hwnd.ptr && side == border_side_t.TOP && !UIView2D.show) return;
-		///end
-
-		if (handle_ptr == UINodes.hwnd.ptr && side != border_side_t.LEFT && side != border_side_t.TOP) return;
-		if (handle_ptr == UIBase.hwnds[tab_area_t.STATUS].ptr && side != border_side_t.TOP) return;
-		if (side == border_side_t.RIGHT) return; // UI is snapped to the right side
-
-		side == border_side_t.LEFT || side == border_side_t.RIGHT ?
-			krom_set_mouse_cursor(3) : // Horizontal
-			krom_set_mouse_cursor(4);  // Vertical
-
-		if (zui_current.input_started) {
-			UIBase.border_started = side;
-			UIBase.border_handle_ptr = handle_ptr;
-			base_is_resizing = true;
-		}
-	}
-
-	static on_text_hover = () => {
-		krom_set_mouse_cursor(2); // I-cursor
-	}
-
-	static on_deselect_text = () => {
-		///if krom_ios
-		keyboard_up_listener(key_code_t.SHIFT);
-		///end
-	}
-
-	static on_tab_drop = (to_ptr: i32, toPosition: i32, from_ptr: i32, fromPosition: i32) => {
-		let i: i32 = -1;
-		let j: i32 = -1;
-		for (let k: i32 = 0; k < UIBase.htabs.length; ++k) {
-			if (UIBase.htabs[k].ptr == to_ptr) i = k;
-			if (UIBase.htabs[k].ptr == from_ptr) j = k;
-		}
-		if (i > -1 && j > -1) {
-			let element: any = UIBase.hwnd_tabs[j][fromPosition];
-			UIBase.hwnd_tabs[j].splice(fromPosition, 1);
-			UIBase.hwnd_tabs[i].splice(toPosition, 0, element);
-			UIBase.hwnds[i].redraws = 2;
-			UIBase.hwnds[j].redraws = 2;
-		}
-	}
-
-	static tag_ui_redraw = () => {
-		UIHeader.header_handle.redraws = 2;
-		UIBase.hwnds[tab_area_t.STATUS].redraws = 2;
-		UIMenubar.workspace_handle.redraws = 2;
-		UIMenubar.menu_handle.redraws = 2;
-		///if (is_paint || is_sculpt)
-		UIBase.hwnds[tab_area_t.SIDEBAR0].redraws = 2;
-		UIBase.hwnds[tab_area_t.SIDEBAR1].redraws = 2;
-		UIToolbar.toolbar_handle.redraws = 2;
-		///end
-	}
-}

+ 0 - 187
base/Sources/UIBox.ts

@@ -1,187 +0,0 @@
-
-class UIBox {
-
-	static show: bool = false;
-	static draggable: bool = true;
-	static hwnd: zui_handle_t = zui_handle_create();
-	static box_title: string = "";
-	static box_text: string = "";
-	static box_commands: (ui: zui_t)=>void = null;
-	static click_to_hide: bool = true;
-	static modalw: i32 = 400;
-	static modalh: i32 = 170;
-	static modal_on_hide: ()=>void = null;
-	static draws: i32 = 0;
-	static copyable: bool = false;
-	///if (krom_android || krom_ios)
-	static tween_alpha: f32 = 0.0;
-	///end
-
-	static render = () => {
-		if (!UIMenu.show) {
-			let ui: zui_t = base_ui_box;
-			let in_use: bool = ui.combo_selected_handle_ptr != 0;
-			let is_escape: bool = keyboard_started("escape");
-			if (UIBox.draws > 2 && (ui.input_released || is_escape) && !in_use && !ui.is_typing) {
-				let appw: i32 = sys_width();
-				let apph: i32 = sys_height();
-				let mw: i32 = Math.floor(UIBox.modalw * zui_SCALE(ui));
-				let mh: i32 = Math.floor(UIBox.modalh * zui_SCALE(ui));
-				let left: f32 = (appw / 2 - mw / 2) + UIBox.hwnd.drag_x;
-				let right: f32 = (appw / 2 + mw / 2) + UIBox.hwnd.drag_x;
-				let top: f32 = (apph / 2 - mh / 2) + UIBox.hwnd.drag_y;
-				let bottom: f32 = (apph / 2 + mh / 2) + UIBox.hwnd.drag_y;
-				let mx: i32 = mouse_x;
-				let my: i32 = mouse_y;
-				if ((UIBox.click_to_hide && (mx < left || mx > right || my < top || my > bottom)) || is_escape) {
-					UIBox.hide();
-				}
-			}
-		}
-
-		if (config_raw.touch_ui) { // Darken bg
-			///if (krom_android || krom_ios)
-			g2_set_color(color_from_floats(0, 0, 0, UIBox.tween_alpha));
-			///else
-			g2_set_color(color_from_floats(0, 0, 0, 0.5));
-			///end
-			g2_fill_rect(0, 0, sys_width(), sys_height());
-		}
-
-		g2_end();
-
-		let ui: zui_t = base_ui_box;
-		let appw: i32 = sys_width();
-		let apph: i32 = sys_height();
-		let mw: i32 = Math.floor(UIBox.modalw * zui_SCALE(ui));
-		let mh: i32 = Math.floor(UIBox.modalh * zui_SCALE(ui));
-		if (mw > appw) mw = appw;
-		if (mh > apph) mh = apph;
-		let left: i32 = Math.floor(appw / 2 - mw / 2);
-		let top: i32 = Math.floor(apph / 2 - mh / 2);
-
-		if (UIBox.box_commands == null) {
-			zui_begin(ui);
-			if (zui_window(UIBox.hwnd, left, top, mw, mh, UIBox.draggable)) {
-				ui._y += 10;
-				let tab_vertical: bool = config_raw.touch_ui;
-				if (zui_tab(zui_handle("uibox_0"), UIBox.box_title, tab_vertical)) {
-					let htext: zui_handle_t = zui_handle("uibox_1");
-					htext.text = UIBox.box_text;
-					UIBox.copyable ?
-						zui_text_area(htext, zui_align_t.LEFT, false) :
-						zui_text(UIBox.box_text);
-					zui_end_element();
-
-					///if (krom_windows || krom_linux || krom_darwin)
-					if (UIBox.copyable) zui_row([1 / 3, 1 / 3, 1 / 3]);
-					else zui_row([2 / 3, 1 / 3]);
-					///else
-					zui_row([2 / 3, 1 / 3]);
-					///end
-
-					zui_end_element();
-
-					///if (krom_windows || krom_linux || krom_darwin)
-					if (UIBox.copyable && zui_button(tr("Copy"))) {
-						krom_copy_to_clipboard(UIBox.box_text);
-					}
-					///end
-					if (zui_button(tr("OK"))) {
-						UIBox.hide();
-					}
-				}
-				UIBox.window_border(ui);
-			}
-			zui_end();
-		}
-		else {
-			zui_begin(ui);
-			if (zui_window(UIBox.hwnd, left, top, mw, mh, UIBox.draggable)) {
-				ui._y += 10;
-				UIBox.box_commands(ui);
-				UIBox.window_border(ui);
-			}
-			zui_end();
-		}
-
-		g2_begin(null);
-
-		UIBox.draws++;
-	}
-
-	static show_message = (title: string, text: string, copyable: bool = false) => {
-		UIBox.init();
-		UIBox.modalw = 400;
-		UIBox.modalh = 210;
-		UIBox.box_title = title;
-		UIBox.box_text = text;
-		UIBox.box_commands = null;
-		UIBox.copyable = copyable;
-		UIBox.draggable = true;
-		///if (krom_android || krom_ios)
-		UIBox.tween_in();
-		///end
-	}
-
-	static show_custom = (commands: (ui: zui_t)=>void = null, mw: i32 = 400, mh: i32 = 200, onHide: ()=>void = null, draggable: bool = true) => {
-		UIBox.init();
-		UIBox.modalw = mw;
-		UIBox.modalh = mh;
-		UIBox.modal_on_hide = onHide;
-		UIBox.box_commands = commands;
-		UIBox.draggable = draggable;
-		///if (krom_android || krom_ios)
-		UIBox.tween_in();
-		///end
-	}
-
-	static hide = () => {
-		///if (krom_android || krom_ios)
-		UIBox.tween_out();
-		///else
-		UIBox.hide_internal();
-		///end
-	}
-
-	static hide_internal = () => {
-		if (UIBox.modal_on_hide != null) UIBox.modal_on_hide();
-		UIBox.show = false;
-		base_redraw_ui();
-	}
-
-	///if (krom_android || krom_ios)
-	static tween_in = () => {
-		tween_reset();
-		tween_to({target: UIBox, props: { tweenAlpha: 0.5 }, duration: 0.2, ease: ease_t.EXPO_OUT});
-		UIBox.hwnd.drag_y = Math.floor(sys_height() / 2);
-		tween_to({target: UIBox.hwnd, props: { dragY: 0 }, duration: 0.2, ease: ease_t.EXPO_OUT, tick: () => { base_redraw_ui(); }});
-	}
-
-	static tween_out = () => {
-		tween_to({target: UIBox, props: { tweenAlpha: 0.0 }, duration: 0.2, ease: ease_t.EXPO_IN, done: UIBox.hide_internal});
-		tween_to({target: UIBox.hwnd, props: { dragY: sys_height() / 2 }, duration: 0.2, ease: ease_t.EXPO_IN});
-	}
-	///end
-
-	static init = () => {
-		UIBox.hwnd.redraws = 2;
-		UIBox.hwnd.drag_x = 0;
-		UIBox.hwnd.drag_y = 0;
-		UIBox.show = true;
-		UIBox.draws = 0;
-		UIBox.click_to_hide = true;
-	}
-
-	static window_border = (ui: zui_t) => {
-		if (ui.scissor) {
-			ui.scissor = false;
-			g2_disable_scissor();
-		}
-		// Border
-		g2_set_color(ui.t.SEPARATOR_COL);
-		g2_fill_rect(0, 0, 1, ui._window_h);
-		g2_fill_rect(0 + ui._window_w - 1, 0, 1, ui._window_h);
-		g2_fill_rect(0, 0 + ui._window_h - 1, ui._window_w, 1);
-	}
-}

+ 0 - 387
base/Sources/UIFiles.ts

@@ -1,387 +0,0 @@
-
-class UIFiles {
-
-	static default_path: string =
-		///if krom_windows
-		"C:\\Users"
-		///elseif krom_android
-		"/storage/emulated/0/Download"
-		///elseif krom_darwin
-		"/Users"
-		///else
-		"/"
-		///end
-	;
-
-	static filename: string;
-	static path: string = UIFiles.default_path;
-	static last_path: string = "";
-	static last_search: string = "";
-	static files: string[] = null;
-	static icon_map: Map<string, image_t> = null;
-	static selected: i32 = -1;
-	static show_extensions: bool = false;
-	static offline: bool = false;
-
-	static show = (filters: string, isSave: bool, openMultiple: bool, filesDone: (s: string)=>void) => {
-		if (isSave) {
-			UIFiles.path = krom_save_dialog(filters, "");
-			if (UIFiles.path != null) {
-				while (UIFiles.path.indexOf(path_sep + path_sep) >= 0) UIFiles.path = string_replace_all(UIFiles.path, path_sep + path_sep, path_sep);
-				UIFiles.path = string_replace_all(UIFiles.path, "\r", "");
-				UIFiles.filename = UIFiles.path.substr(UIFiles.path.lastIndexOf(path_sep) + 1);
-				UIFiles.path = UIFiles.path.substr(0, UIFiles.path.lastIndexOf(path_sep));
-				filesDone(UIFiles.path);
-			}
-		}
-		else {
-			let paths: string[] = krom_open_dialog(filters, "", openMultiple);
-			if (paths != null) {
-				for (let path of paths) {
-					while (path.indexOf(path_sep + path_sep) >= 0) path = string_replace_all(path, path_sep + path_sep, path_sep);
-					path = string_replace_all(path, "\r", "");
-					UIFiles.filename = path.substr(path.lastIndexOf(path_sep) + 1);
-					filesDone(path);
-				}
-			}
-		}
-
-		UIFiles.release_keys();
-	}
-
-	// static show_custom = (filters: string, isSave: bool, filesDone: (s: string)=>void) => {
-	// 	let known: bool = false;
-	// 	UIBox.show_custom((ui: ZuiRaw) => {
-	// 		if (Zui.tab(Zui.handle(), tr("File Browser"))) {
-	// 			let path_handle: zui_handle_t = Zui.handle();
-	// 			let file_handle: zui_handle_t = Zui.handle();
-	// 			Zui.row([6 / 10, 2 / 10, 2 / 10]);
-	// 			filename = Zui.textInput(file_handle, tr("File"));
-	// 			Zui.text("*." + filters, Center);
-	// 			if (Zui.button(isSave ? tr("Save") : tr("Open")) || known || ui.isReturnDown) {
-	// 				UIBox.hide();
-	// 				filesDone((known || isSave) ? path : path + sep + filename);
-	// 				if (known) path_handle.text = path_handle.text.substr(0, path_handle.text.lastIndexOf(sep));
-	// 			}
-	// 			known = isTexture(path) || isMesh(path) || isProject(path);
-	// 			path = fileBrowser(ui, path_handle, false);
-	// 			if (path_handle.changed) ui.currentWindow.redraws = 3;
-	// 		}
-	// 	}, 600, 500);
-	// }
-
-	static release_keys = () => {
-		// File dialog may prevent firing key up events
-		keyboard_up_listener(key_code_t.SHIFT);
-		keyboard_up_listener(key_code_t.CONTROL);
-		///if krom_darwin
-		keyboard_up_listener(key_code_t.META);
-		///end
-	}
-
-	static file_browser = (ui: zui_t, handle: zui_handle_t, foldersOnly: bool = false, dragFiles: bool = false, search: string = "", refresh: bool = false, contextMenu: (s: string)=>void = null): string => {
-
-		let icons: image_t = resource_get("icons.k");
-		let folder: rect_t = resource_tile50(icons, 2, 1);
-		let file: rect_t = resource_tile50(icons, 3, 1);
-		let is_cloud: bool = handle.text.startsWith("cloud");
-
-		if (is_cloud && file_cloud == null) file_init_cloud(() => { UIBase.hwnds[tab_area_t.STATUS].redraws = 3; });
-		if (is_cloud && file_read_directory("cloud", false).length == 0) return handle.text;
-
-		///if krom_ios
-		let document_directory: string = krom_save_dialog("", "");
-		document_directory = document_directory.substr(0, document_directory.length - 8); // Strip /'untitled'
-		///end
-
-		if (handle.text == "") handle.text = UIFiles.default_path;
-		if (handle.text != UIFiles.last_path || search != UIFiles.last_search || refresh) {
-			UIFiles.files = [];
-
-			// Up directory
-			let i1: i32 = handle.text.indexOf(path_sep);
-			let nested: bool = i1 > -1 && handle.text.length - 1 > i1;
-			///if krom_windows
-			// Server addresses like \\server are not nested
-			nested = nested && !(handle.text.length >= 2 && handle.text.charAt(0) == path_sep && handle.text.charAt(1) == path_sep && handle.text.lastIndexOf(path_sep) == 1);
-			///end
-			if (nested) UIFiles.files.push("..");
-
-			let dir_path: string = handle.text;
-			///if krom_ios
-			if (!is_cloud) dir_path = document_directory + dir_path;
-			///end
-			let files_all: string[] = file_read_directory(dir_path, foldersOnly);
-
-			for (let f of files_all) {
-				if (f == "" || f.charAt(0) == ".") continue; // Skip hidden
-				if (f.indexOf(".") > 0 && !path_is_known(f)) continue; // Skip unknown extensions
-				if (is_cloud && f.indexOf("_icon.") >= 0) continue; // Skip thumbnails
-				if (f.toLowerCase().indexOf(search.toLowerCase()) < 0) continue; // Search filter
-				UIFiles.files.push(f);
-			}
-		}
-		UIFiles.last_path = handle.text;
-		UIFiles.last_search = search;
-		handle.changed = false;
-
-		let slotw: i32 = Math.floor(70 * zui_SCALE(ui));
-		let num: i32 = Math.floor(ui._w / slotw);
-
-		ui._y += 4; // Don't cut off the border around selected materials
-		// Directory contents
-		for (let row: i32 = 0; row < Math.floor(Math.ceil(UIFiles.files.length / num)); ++row) {
-			let ar: f32[] = [];
-			for (let i: i32 = 0; i < num * 2; ++i) ar.push(1 / num);
-			zui_row(ar);
-			if (row > 0) ui._y += zui_ELEMENT_OFFSET(ui) * 14.0;
-
-			for (let j: i32 = 0; j < num; ++j) {
-				let i: i32 = j + row * num;
-				if (i >= UIFiles.files.length) {
-					zui_end_element(slotw);
-					zui_end_element(slotw);
-					continue;
-				}
-
-				let f: string = UIFiles.files[i];
-				let _x: f32 = ui._x;
-
-				let rect: rect_t = f.indexOf(".") > 0 ? file : folder;
-				let col: i32 = rect == file ? ui.t.LABEL_COL : ui.t.LABEL_COL - 0x00202020;
-				if (UIFiles.selected == i) col = ui.t.HIGHLIGHT_COL;
-
-				let off: f32 = ui._w / 2 - 25 * zui_SCALE(ui);
-				ui._x += off;
-
-				let uix: f32 = ui._x;
-				let uiy: f32 = ui._y;
-				let state: zui_state_t = zui_state_t.IDLE;
-				let generic: bool = true;
-				let icon: image_t = null;
-
-				if (is_cloud && f != ".." && !UIFiles.offline) {
-					if (UIFiles.icon_map == null) UIFiles.icon_map = new Map();
-					icon = UIFiles.icon_map.get(handle.text + path_sep + f);
-					if (icon == null) {
-						let files_all: string[] = file_read_directory(handle.text);
-						let icon_file: string = f.substr(0, f.lastIndexOf(".")) + "_icon.jpg";
-						if (files_all.indexOf(icon_file) >= 0) {
-							let empty: image_t = render_path_render_targets.get("empty_black")._image;
-							UIFiles.icon_map.set(handle.text + path_sep + f, empty);
-							file_cache_cloud(handle.text + path_sep + icon_file, (abs: string) => {
-								if (abs != null) {
-									let image: image_t = data_get_image(abs);
-									app_notify_on_init(() => {
-										if (base_pipe_copy_rgb == null) base_make_pipe_copy_rgb();
-										icon = image_create_render_target(image.width, image.height);
-										if (f.endsWith(".arm")) { // Used for material sphere alpha cutout
-											g2_begin(icon);
-
-											///if (is_paint || is_sculpt)
-											g2_draw_image(project_materials[0].image, 0, 0);
-											///end
-										}
-										else {
-											g2_begin(icon);
-											g2_clear(0xffffffff);
-										}
-										g2_set_pipeline(base_pipe_copy_rgb);
-										g2_draw_image(image, 0, 0);
-										g2_set_pipeline(null);
-										g2_end();
-										UIFiles.icon_map.set(handle.text + path_sep + f, icon);
-										UIBase.hwnds[tab_area_t.STATUS].redraws = 3;
-									});
-								}
-								else UIFiles.offline = true;
-							});
-						}
-					}
-					if (icon != null) {
-						let w: i32 = 50;
-						if (i == UIFiles.selected) {
-							zui_fill(-2,        -2, w + 4,     2, ui.t.HIGHLIGHT_COL);
-							zui_fill(-2,     w + 2, w + 4,     2, ui.t.HIGHLIGHT_COL);
-							zui_fill(-2,         0,     2, w + 4, ui.t.HIGHLIGHT_COL);
-							zui_fill(w + 2 ,    -2,     2, w + 6, ui.t.HIGHLIGHT_COL);
-						}
-						state = zui_image(icon, 0xffffffff, w * zui_SCALE(ui));
-						if (ui.is_hovered) {
-							zui_tooltip_image(icon);
-							zui_tooltip(f);
-						}
-						generic = false;
-					}
-				}
-				if (f.endsWith(".arm") && !is_cloud) {
-					if (UIFiles.icon_map == null) UIFiles.icon_map = new Map();
-					let key: string = handle.text + path_sep + f;
-					icon = UIFiles.icon_map.get(key);
-					if (!UIFiles.icon_map.has(key)) {
-						let blob_path: string = key;
-
-						///if krom_ios
-						blob_path = document_directory + blob_path;
-						// TODO: implement native .arm parsing first
-						///else
-
-						let buffer: buffer_t = krom_load_blob(blob_path);
-						let raw: any = armpack_decode(buffer);
-						if (raw.material_icons != null) {
-							let bytes_icon: any = raw.material_icons[0];
-							icon = image_from_bytes(lz4_decode(bytes_icon, 256 * 256 * 4), 256, 256);
-						}
-
-						///if (is_paint || is_sculpt)
-						else if (raw.mesh_icons != null) {
-							let bytes_icon: any = raw.mesh_icons[0];
-							icon = image_from_bytes(lz4_decode(bytes_icon, 256 * 256 * 4), 256, 256);
-						}
-						else if (raw.brush_icons != null) {
-							let bytes_icon: any = raw.brush_icons[0];
-							icon = image_from_bytes(lz4_decode(bytes_icon, 256 * 256 * 4), 256, 256);
-						}
-						///end
-
-						///if is_lab
-						if (raw.mesh_icon != null) {
-							let bytes_icon: any = raw.mesh_icon;
-							icon = image_from_bytes(lz4_decode(bytes_icon, 256 * 256 * 4), 256, 256);
-						}
-						///end
-
-						UIFiles.icon_map.set(key, icon);
-						///end
-					}
-					if (icon != null) {
-						let w: i32 = 50;
-						if (i == UIFiles.selected) {
-							zui_fill(-2,        -2, w + 4,     2, ui.t.HIGHLIGHT_COL);
-							zui_fill(-2,     w + 2, w + 4,     2, ui.t.HIGHLIGHT_COL);
-							zui_fill(-2,         0,     2, w + 4, ui.t.HIGHLIGHT_COL);
-							zui_fill(w + 2 ,    -2,     2, w + 6, ui.t.HIGHLIGHT_COL);
-						}
-						state = zui_image(icon, 0xffffffff, w * zui_SCALE(ui));
-						if (ui.is_hovered) {
-							zui_tooltip_image(icon);
-							zui_tooltip(f);
-						}
-						generic = false;
-					}
-				}
-
-				if (path_is_texture(f) && !is_cloud) {
-					let w: i32 = 50;
-					if (UIFiles.icon_map == null) UIFiles.icon_map = new Map();
-					let shandle: string = handle.text + path_sep + f;
-					icon = UIFiles.icon_map.get(shandle);
-					if (icon == null) {
-						let empty: image_t = render_path_render_targets.get("empty_black")._image;
-						UIFiles.icon_map.set(shandle, empty);
-						let image: image_t = data_get_image(shandle);
-						app_notify_on_init(() => {
-							if (base_pipe_copy_rgb == null) base_make_pipe_copy_rgb();
-							let sw: i32 = image.width > image.height ? w : Math.floor(1.0 * image.width / image.height * w);
-							let sh: i32 = image.width > image.height ? Math.floor(1.0 * image.height / image.width * w) : w;
-							icon = image_create_render_target(sw, sh);
-							g2_begin(icon);
-							g2_clear(0xffffffff);
-							g2_set_pipeline(base_pipe_copy_rgb);
-							g2_draw_scaled_image(image, 0, 0, sw, sh);
-							g2_set_pipeline(null);
-							g2_end();
-							UIFiles.icon_map.set(shandle, icon);
-							UIBase.hwnds[tab_area_t.STATUS].redraws = 3;
-							data_delete_image(shandle); // The big image is not needed anymore
-						});
-					}
-					if (icon != null) {
-						if (i == UIFiles.selected) {
-							zui_fill(-2,        -2, w + 4,     2, ui.t.HIGHLIGHT_COL);
-							zui_fill(-2,     w + 2, w + 4,     2, ui.t.HIGHLIGHT_COL);
-							zui_fill(-2,         0,     2, w + 4, ui.t.HIGHLIGHT_COL);
-							zui_fill(w + 2 ,    -2,     2, w + 6, ui.t.HIGHLIGHT_COL);
-						}
-						state = zui_image(icon, 0xffffffff, icon.height * zui_SCALE(ui));
-						generic = false;
-					}
-				}
-
-				if (generic) {
-					state = zui_image(icons, col, 50 * zui_SCALE(ui), rect.x, rect.y, rect.w, rect.h);
-				}
-
-				if (ui.is_hovered && ui.input_released_r && contextMenu != null) {
-					contextMenu(handle.text + path_sep + f);
-				}
-
-				if (state == zui_state_t.STARTED) {
-					if (f != ".." && dragFiles) {
-						base_drag_off_x = -(mouse_x - uix - ui._window_x - 3);
-						base_drag_off_y = -(mouse_y - uiy - ui._window_y + 1);
-						base_drag_file = handle.text;
-						///if krom_ios
-						if (!is_cloud) base_drag_file = document_directory + base_drag_file;
-						///end
-						if (base_drag_file.charAt(base_drag_file.length - 1) != path_sep) {
-							base_drag_file += path_sep;
-						}
-						base_drag_file += f;
-						base_drag_file_icon = icon;
-					}
-
-					UIFiles.selected = i;
-					if (time_time() - context_raw.select_time < 0.25) {
-						base_drag_file = null;
-						base_drag_file_icon = null;
-						base_is_dragging = false;
-						handle.changed = ui.changed = true;
-						if (f == "..") { // Up
-							handle.text = handle.text.substring(0, handle.text.lastIndexOf(path_sep));
-							// Drive root
-							if (handle.text.length == 2 && handle.text.charAt(1) == ":") handle.text += path_sep;
-						}
-						else {
-							if (handle.text.charAt(handle.text.length - 1) != path_sep) {
-								handle.text += path_sep;
-							}
-							handle.text += f;
-						}
-						UIFiles.selected = -1;
-					}
-					context_raw.select_time = time_time();
-				}
-
-				// Label
-				ui._x = _x;
-				ui._y += slotw * 0.75;
-				let label0: string = (UIFiles.show_extensions || f.indexOf(".") <= 0) ? f : f.substr(0, f.lastIndexOf("."));
-				let label1: string = "";
-				while (label0.length > 0 && g2_font_width(ui.font, ui.font_size, label0) > ui._w - 6) { // 2 line split
-					label1 = label0.charAt(label0.length - 1) + label1;
-					label0 = label0.substr(0, label0.length - 1);
-				}
-				if (label1 != "") ui.cur_ratio--;
-				zui_text(label0, zui_align_t.CENTER);
-				if (ui.is_hovered) zui_tooltip(label0 + label1);
-				if (label1 != "") { // Second line
-					ui._x = _x;
-					ui._y += g2_font_height(ui.font, ui.font_size);
-					zui_text(label1, zui_align_t.CENTER);
-					if (ui.is_hovered) zui_tooltip(label0 + label1);
-					ui._y -= g2_font_height(ui.font, ui.font_size);
-				}
-
-				ui._y -= slotw * 0.75;
-
-				if (handle.changed) break;
-			}
-
-			if (handle.changed) break;
-		}
-		ui._y += slotw * 0.8;
-
-		return handle.text;
-	}
-}

+ 0 - 502
base/Sources/UIHeader.ts

@@ -1,502 +0,0 @@
-
-class UIHeader {
-
-	static default_header_h: i32 = 28;
-	static headerh: i32 = UIHeader.default_header_h;
-	static header_handle: zui_handle_t = zui_handle_create({ layout: zui_layout_t.HORIZONTAL });
-	static worktab: zui_handle_t = zui_handle_create();
-
-	constructor() {
-	}
-
-	static render_ui = () => {
-		let ui: zui_t = UIBase.ui;
-		if (config_raw.touch_ui) {
-			UIHeader.headerh = UIHeader.default_header_h + 6;
-		}
-		else {
-			UIHeader.headerh = UIHeader.default_header_h;
-		}
-		UIHeader.headerh = Math.floor(UIHeader.headerh * zui_SCALE(ui));
-
-		if (config_raw.layout[layout_size_t.HEADER] == 0) return;
-
-		let nodesw: i32 = (UINodes.show || UIView2D.show) ? config_raw.layout[layout_size_t.NODES_W] : 0;
-		///if is_lab
-		let ww: i32 = sys_width() - nodesw;
-		///else
-		let ww: i32 = sys_width() - UIToolbar.toolbar_w - config_raw.layout[layout_size_t.SIDEBAR_W] - nodesw;
-		///end
-
-		if (zui_window(UIHeader.header_handle, app_x(), UIHeader.headerh, ww, UIHeader.headerh)) {
-			ui._y += 2;
-			UIHeader.draw_tool_properties(ui);
-		}
-	}
-
-	///if is_paint
-
-	static draw_tool_properties = (ui: zui_t) => {
-		if (context_raw.tool == workspace_tool_t.COLORID) {
-			zui_text(tr("Picked Color"));
-			if (context_raw.colorid_picked) {
-				zui_image(render_path_render_targets.get("texpaint_colorid")._image, 0xffffffff, 64);
-			}
-			ui.enabled = context_raw.colorid_picked;
-			if (zui_button(tr("Clear"))) {
-				context_raw.colorid_picked = false;
-				UIToolbar.toolbar_handle.redraws = 1;
-			}
-			ui.enabled = true;
-			zui_text(tr("Color ID Map"));
-			if (project_asset_names.length > 0) {
-				let cid: i32 = zui_combo(context_raw.colorid_handle, base_enum_texts("TEX_IMAGE"), tr("Color ID"));
-				if (context_raw.colorid_handle.changed) {
-					context_raw.ddirty = 2;
-					context_raw.colorid_picked = false;
-					UIToolbar.toolbar_handle.redraws = 1;
-				}
-				zui_image(project_get_image(project_assets[cid]));
-				if (ui.is_hovered) zui_tooltip_image(project_get_image(project_assets[cid]), 256);
-			}
-			if (zui_button(tr("Import"))) {
-				UIFiles.show(path_texture_formats.join(","), false, true, (path: string) => {
-					ImportAsset.run(path, -1.0, -1.0, true, false);
-
-					context_raw.colorid_handle.position = project_asset_names.length - 1;
-					for (let a of project_assets) {
-						// Already imported
-						if (a.file == path) context_raw.colorid_handle.position = project_assets.indexOf(a);
-					}
-					context_raw.ddirty = 2;
-					context_raw.colorid_picked = false;
-					UIToolbar.toolbar_handle.redraws = 1;
-					UIBase.hwnds[2].redraws = 2;
-				});
-			}
-			ui.enabled = context_raw.colorid_picked;
-			if (zui_button(tr("To Mask"))) {
-				if (SlotLayer.is_mask(context_raw.layer)) context_set_layer(context_raw.layer.parent);
-				let m: SlotLayerRaw = base_new_mask(false, context_raw.layer);
-				let _next = () => {
-					if (base_pipe_merge == null) base_make_pipe();
-					if (const_data_screen_aligned_vb == null) const_data_create_screen_aligned_data();
-					g4_begin(m.texpaint);
-					g4_set_pipeline(base_pipe_colorid_to_mask);
-					g4_set_tex(base_texpaint_colorid,render_path_render_targets.get("texpaint_colorid")._image);
-					g4_set_tex(base_tex_colorid, project_get_image(project_assets[context_raw.colorid_handle.position]));
-					g4_set_vertex_buffer(const_data_screen_aligned_vb);
-					g4_set_index_buffer(const_data_screen_aligned_ib);
-					g4_draw();
-					g4_end();
-					context_raw.colorid_picked = false;
-					UIToolbar.toolbar_handle.redraws = 1;
-					UIHeader.header_handle.redraws = 1;
-					context_raw.layer_preview_dirty = true;
-					base_update_fill_layers();
-				}
-				base_notify_on_next_frame(_next);
-				history_new_white_mask();
-			}
-			ui.enabled = true;
-		}
-		else if (context_raw.tool == workspace_tool_t.PICKER || context_raw.tool == workspace_tool_t.MATERIAL) {
-			let base_r_picked: f32 = Math.round(color_get_rb(context_raw.picked_color.base) / 255 * 10) / 10;
-			let base_g_picked: f32 = Math.round(color_get_gb(context_raw.picked_color.base) / 255 * 10) / 10;
-			let base_b_picked: f32 = Math.round(color_get_bb(context_raw.picked_color.base) / 255 * 10) / 10;
-			let normal_r_picked: f32 = Math.round(color_get_rb(context_raw.picked_color.normal) / 255 * 10) / 10;
-			let normal_g_picked: f32 = Math.round(color_get_gb(context_raw.picked_color.normal) / 255 * 10) / 10;
-			let normal_b_picked: f32 = Math.round(color_get_bb(context_raw.picked_color.normal) / 255 * 10) / 10;
-			let occlusion_picked: f32 = Math.round(context_raw.picked_color.occlusion * 100) / 100;
-			let roughness_picked: f32 = Math.round(context_raw.picked_color.roughness * 100) / 100;
-			let metallic_picked: f32 = Math.round(context_raw.picked_color.metallic * 100) / 100;
-			let height_picked: f32 = Math.round(context_raw.picked_color.height * 100) / 100;
-			let opacity_picked: f32 = Math.round(context_raw.picked_color.opacity * 100) / 100;
-
-			let h: zui_handle_t = zui_handle("uiheader_0");
-			let color: color_t = 0xffffffff;
-			color = color_set_rb(color, base_r_picked * 255);
-			color = color_set_gb(color, base_g_picked * 255);
-			color = color_set_bb(color, base_b_picked * 255);
-			h.color = color;
-			let state: zui_state_t = zui_text("", 0, h.color);
-			if (state == zui_state_t.STARTED) {
-				let uix: i32 = ui._x;
-				let uiy: i32 = ui._y;
-				base_drag_off_x = -(mouse_x - uix - ui._window_x - 3);
-				base_drag_off_y = -(mouse_y - uiy - ui._window_y + 1);
-				base_drag_swatch = project_clone_swatch(context_raw.picked_color);
-			}
-			if (ui.is_hovered) zui_tooltip(tr("Drag and drop picked color to swatches, materials, layers or to the node editor"));
-			if (ui.is_hovered && ui.input_released) {
-				UIMenu.draw((ui: zui_t) => {
-					zui_fill(0, 0, ui._w / zui_SCALE(ui), ui.t.ELEMENT_H * 9, ui.t.SEPARATOR_COL);
-					ui.changed = false;
-					zui_color_wheel(h, false, null, 10 * ui.t.ELEMENT_H * zui_SCALE(ui), false);
-					if (ui.changed) UIMenu.keep_open = true;
-				}, 10);
-			}
-			if (zui_button(tr("Add Swatch"))) {
-				let new_swatch: swatch_color_t = project_clone_swatch(context_raw.picked_color);
-				context_set_swatch(new_swatch);
-				project_raw.swatches.push(new_swatch);
-				UIBase.hwnds[2].redraws = 1;
-			}
-			if (ui.is_hovered) zui_tooltip(tr("Add picked color to swatches"));
-
-			zui_text(tr("Base") + ` (${base_r_picked},${base_g_picked},${base_b_picked})`);
-			zui_text(tr("Normal") + ` (${normal_r_picked},${normal_g_picked},${normal_b_picked})`);
-			zui_text(tr("Occlusion") + ` (${occlusion_picked})`);
-			zui_text(tr("Roughness") + ` (${roughness_picked})`);
-			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("uiheader_1", { selected: context_raw.picker_select_material }), tr("Select Material"));
-			zui_combo(context_raw.picker_mask_handle, [tr("None"), tr("Material")], tr("Mask"), true);
-			if (context_raw.picker_mask_handle.changed) {
-				MakeMaterial.parse_paint_material();
-			}
-		}
-		else if (context_raw.tool == workspace_tool_t.BAKE) {
-			ui.changed = false;
-
-			///if (krom_direct3d12 || krom_vulkan || krom_metal)
-			let baking: bool = context_raw.pdirty > 0;
-			let rt_bake: bool = context_raw.bake_type == bake_type_t.AO || context_raw.bake_type == bake_type_t.LIGHTMAP || context_raw.bake_type == bake_type_t.BENT_NORMAL || context_raw.bake_type == bake_type_t.THICKNESS;
-			if (baking && zui_button(tr("Stop"))) {
-				context_raw.pdirty = 0;
-				context_raw.rdirty = 2;
-			}
-			///else
-			let baking: bool = false;
-			let rt_bake: bool = false;
-			///end
-
-			if (!baking && zui_button(tr("Bake"))) {
-				context_raw.pdirty = rt_bake ? context_raw.bake_samples : 1;
-				context_raw.rdirty = 3;
-				base_notify_on_next_frame(() => {
-					context_raw.layer_preview_dirty = true;
-				});
-				UIBase.hwnds[0].redraws = 2;
-				history_push_undo = true;
-				///if (krom_direct3d12 || krom_vulkan || krom_metal)
-				RenderPathRaytraceBake.current_sample = 0;
-				///end
-			}
-
-			let bake_handle: zui_handle_t = zui_handle("uiheader_2", { position: context_raw.bake_type });
-			let bakes: string[] = [
-				tr("AO"),
-				tr("Curvature"),
-				tr("Normal"),
-				tr("Object Normal"),
-				tr("Height"),
-				tr("Derivative"),
-				tr("Position"),
-				tr("TexCoord"),
-				tr("Material ID"),
-				tr("Object ID"),
-				tr("Vertex Color"),
-			];
-			///if (krom_direct3d12 || krom_vulkan || krom_metal)
-			if (krom_raytrace_supported()) {
-				bakes.push(tr("Lightmap"));
-				bakes.push(tr("Bent Normal"));
-				bakes.push(tr("Thickness"));
-			}
-			else {
-				bakes.shift(); // Remove AO
-			}
-			///end
-
-			context_raw.bake_type = zui_combo(bake_handle, bakes, tr("Bake"));
-
-			///if (krom_direct3d12 || krom_vulkan || krom_metal)
-			if (!krom_raytrace_supported()) {
-				context_raw.bake_type += 1; // Offset for removed AO
-			}
-			///end
-
-			///if (krom_direct3d12 || krom_vulkan || krom_metal)
-			if (rt_bake) {
-				let samples_handle: zui_handle_t = zui_handle("uiheader_3", { 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("uiheader_4", { 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("uiheader_5", { 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("uiheader_6", { 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("uiheader_7", { 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("uiheader_8", { 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)
-			if (rt_bake) {
-				let progress: f32 = RenderPathRaytraceBake.current_sample / context_raw.bake_samples;
-				if (progress > 1.0) progress = 1.0;
-				// Progress bar
-				g2_set_color(ui.t.SEPARATOR_COL);
-				zui_draw_rect(true, ui._x + 1, ui._y, ui._w - 2, zui_ELEMENT_H(ui));
-				g2_set_color(ui.t.HIGHLIGHT_COL);
-				zui_draw_rect(true, ui._x + 1, ui._y, (ui._w - 2) * progress, zui_ELEMENT_H(ui));
-				g2_set_color(0xffffffff);
-				zui_text(tr("Samples") + ": " + RenderPathRaytraceBake.current_sample);
-				zui_text(tr("Rays/pixel" + ": ") + RenderPathRaytraceBake.rays_pix);
-				zui_text(tr("Rays/second" + ": ") + RenderPathRaytraceBake.rays_sec);
-			}
-			///end
-			if (context_raw.bake_type == bake_type_t.CURVATURE) {
-				let strength_handle: zui_handle_t = zui_handle("uiheader_9", { 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("uiheader_10", { 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("uiheader_11", { 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("uiheader_12", { 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) {
-				let ar: string[] = [];
-				for (let p of project_paint_objects) ar.push(p.base.name);
-				let poly_handle: zui_handle_t = zui_handle("uiheader_13", { position: context_raw.bake_high_poly });
-				context_raw.bake_high_poly = zui_combo(poly_handle, ar, tr("High Poly"));
-			}
-			if (ui.changed) {
-				MakeMaterial.parse_paint_material();
-			}
-		}
-		else if (context_raw.tool == workspace_tool_t.BRUSH ||
-				 context_raw.tool == workspace_tool_t.ERASER ||
-				 context_raw.tool == workspace_tool_t.FILL ||
-				 context_raw.tool == workspace_tool_t.DECAL ||
-				 context_raw.tool == workspace_tool_t.TEXT ||
-				 context_raw.tool == workspace_tool_t.CLONE ||
-				 context_raw.tool == workspace_tool_t.BLUR ||
-				 context_raw.tool == workspace_tool_t.SMUDGE ||
-				 context_raw.tool == workspace_tool_t.PARTICLE) {
-
-			let decal: bool = context_raw.tool == workspace_tool_t.DECAL || context_raw.tool == workspace_tool_t.TEXT;
-			let decal_mask: bool = decal && operator_shortcut(config_keymap.decal_mask, shortcut_type_t.DOWN);
-			if (context_raw.tool != workspace_tool_t.FILL) {
-				if (decal_mask) {
-					context_raw.brush_decal_mask_radius = zui_slider(context_raw.brush_decal_mask_radius_handle, tr("Radius"), 0.01, 2.0, true);
-					if (ui.is_hovered) zui_tooltip(tr("Hold {brush_radius} and move mouse to the left or press {brush_radius_decrease} to decrease the radius\nHold {brush_radius} and move mouse to the right or press {brush_radius_increase} to increase the radius", new Map([["brush_radius", config_keymap.brush_radius], ["brush_radius_decrease", config_keymap.brush_radius_decrease], ["brush_radius_increase", config_keymap.brush_radius_increase]])));
-				}
-				else {
-					context_raw.brush_radius = zui_slider(context_raw.brush_radius_handle, tr("Radius"), 0.01, 2.0, true);
-					if (ui.is_hovered) zui_tooltip(tr("Hold {brush_radius} and move mouse to the left or press {brush_radius_decrease} to decrease the radius\nHold {brush_radius} and move mouse to the right or press {brush_radius_increase} to increase the radius", new Map([["brush_radius", config_keymap.brush_radius], ["brush_radius_decrease", config_keymap.brush_radius_decrease], ["brush_radius_increase", config_keymap.brush_radius_increase]])));
-				}
-			}
-
-			if (context_raw.tool == workspace_tool_t.DECAL || context_raw.tool == workspace_tool_t.TEXT) {
-				context_raw.brush_scale_x = zui_slider(context_raw.brush_scale_x_handle, tr("Scale X"), 0.01, 2.0, true);
-			}
-
-			if (context_raw.tool == workspace_tool_t.BRUSH  ||
-				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("uiheader_14", { 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) {
-						let current: image_t = _g2_current;
-						g2_end();
-						UtilRender.make_decal_preview();
-						g2_begin(current);
-					}
-				}
-
-				context_raw.brush_angle = zui_slider(context_raw.brush_angle_handle, tr("Angle"), 0.0, 360.0, true, 1);
-				if (ui.is_hovered) zui_tooltip(tr("Hold {brush_angle} and move mouse to the left to decrease the angle\nHold {brush_angle} and move mouse to the right to increase the angle", new Map([["brush_angle", config_keymap.brush_angle]])));
-
-				if (context_raw.brush_angle_handle.changed) {
-					MakeMaterial.parse_paint_material();
-				}
-			}
-
-			context_raw.brush_opacity = zui_slider(context_raw.brush_opacity_handle, tr("Opacity"), 0.0, 1.0, true);
-			if (ui.is_hovered) zui_tooltip(tr("Hold {brush_opacity} and move mouse to the left to decrease the opacity\nHold {brush_opacity} and move mouse to the right to increase the opacity", new Map([["brush_opacity", config_keymap.brush_opacity]])));
-
-			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("uiheader_15", { value: context_raw.brush_hardness }), tr("Hardness"), 0.0, 1.0, true);
-			}
-
-			if (context_raw.tool != workspace_tool_t.ERASER) {
-				let brush_blending_handle: zui_handle_t = zui_handle("uiheader_16", { value: context_raw.brush_blending });
-				context_raw.brush_blending = zui_combo(brush_blending_handle, [
-					tr("Mix"),
-					tr("Darken"),
-					tr("Multiply"),
-					tr("Burn"),
-					tr("Lighten"),
-					tr("Screen"),
-					tr("Dodge"),
-					tr("Add"),
-					tr("Overlay"),
-					tr("Soft Light"),
-					tr("Linear Light"),
-					tr("Difference"),
-					tr("Subtract"),
-					tr("Divide"),
-					tr("Hue"),
-					tr("Saturation"),
-					tr("Color"),
-					tr("Value"),
-				], tr("Blending"));
-				if (brush_blending_handle.changed) {
-					MakeMaterial.parse_paint_material();
-				}
-			}
-
-			if (context_raw.tool == workspace_tool_t.BRUSH || context_raw.tool == workspace_tool_t.FILL) {
-				let paint_handle: zui_handle_t = zui_handle("uiheader_17");
-				context_raw.brush_paint = zui_combo(paint_handle, [tr("UV Map"), tr("Triplanar"), tr("Project")], tr("TexCoord"));
-				if (paint_handle.changed) {
-					MakeMaterial.parse_paint_material();
-				}
-			}
-			if (context_raw.tool == workspace_tool_t.TEXT) {
-				let h: zui_handle_t = zui_handle("uiheader_18");
-				h.text = context_raw.text_tool_text;
-				let w: i32 = ui._w;
-				if (ui.text_selected_handle_ptr == h.ptr || ui.submit_text_handle_ptr == h.ptr) {
-					ui._w *= 3;
-				}
-
-				context_raw.text_tool_text = zui_text_input(h, "", zui_align_t.LEFT, true, true);
-				ui._w = w;
-
-				if (h.changed) {
-					let current: image_t = _g2_current;
-					g2_end();
-					UtilRender.make_text_preview();
-					UtilRender.make_decal_preview();
-					g2_begin(current);
-				}
-			}
-
-			if (context_raw.tool == workspace_tool_t.FILL) {
-				zui_combo(context_raw.fill_type_handle, [tr("Object"), tr("Face"), tr("Angle"), tr("UV Island")], tr("Fill Mode"));
-				if (context_raw.fill_type_handle.changed) {
-					if (context_raw.fill_type_handle.position == fill_type_t.FACE) {
-						let current: image_t = _g2_current;
-						g2_end();
-						// UtilUV.cacheUVMap();
-						UtilUV.cache_triangle_map();
-						g2_begin(current);
-						// wireframeHandle.selected = drawWireframe = true;
-					}
-					MakeMaterial.parse_paint_material();
-					MakeMaterial.parse_mesh_material();
-				}
-			}
-			else {
-				let _w: i32 = ui._w;
-				let sc: f32 = zui_SCALE(ui);
-				let touch_header: bool = (config_raw.touch_ui && config_raw.layout[layout_size_t.HEADER] == 1);
-				if (touch_header) ui._x -= 4 * sc;
-				ui._w = Math.floor((touch_header ? 54 : 60) * sc);
-
-				let xray_handle: zui_handle_t = zui_handle("uiheader_19", { selected: context_raw.xray });
-				context_raw.xray = zui_check(xray_handle, tr("X-Ray"));
-				if (xray_handle.changed) {
-					MakeMaterial.parse_paint_material();
-				}
-
-				let sym_x_handle: zui_handle_t = zui_handle("uiheader_20", { selected: false });
-				let sym_y_handle: zui_handle_t = zui_handle("uiheader_21", { selected: false });
-				let sym_z_handle: zui_handle_t = zui_handle("uiheader_22", { selected: false });
-
-				if (config_raw.layout[layout_size_t.HEADER] == 1) {
-					if (config_raw.touch_ui) {
-						ui._w = Math.floor(19 * sc);
-						context_raw.sym_x = zui_check(sym_x_handle, "");
-						ui._x -= 4 * sc;
-						context_raw.sym_y = zui_check(sym_y_handle, "");
-						ui._x -= 4 * sc;
-						context_raw.sym_z = zui_check(sym_z_handle, "");
-						ui._x -= 4 * sc;
-						ui._w = Math.floor(40 * sc);
-						zui_text(tr("X") + tr("Y") + tr("Z"));
-					}
-					else {
-						ui._w = Math.floor(56 * sc);
-						zui_text(tr("Symmetry"));
-						ui._w = Math.floor(25 * sc);
-						context_raw.sym_x = zui_check(sym_x_handle, tr("X"));
-						context_raw.sym_y = zui_check(sym_y_handle, tr("Y"));
-						context_raw.sym_z = zui_check(sym_z_handle, tr("Z"));
-					}
-					ui._w = _w;
-				}
-				else {
-					// Popup
-					ui._w = _w;
-					context_raw.sym_x = zui_check(sym_x_handle, tr("Symmetry") + " " + tr("X"));
-					context_raw.sym_y = zui_check(sym_y_handle, tr("Symmetry") + " " + tr("Y"));
-					context_raw.sym_z = zui_check(sym_z_handle, tr("Symmetry") + " " + tr("Z"));
-				}
-
-				if (sym_x_handle.changed || sym_y_handle.changed || sym_z_handle.changed) {
-					MakeMaterial.parse_paint_material();
-				}
-			}
-
-			///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("uiheader_23", { selected: false });
-				context_raw.particle_physics = zui_check(phys_handle, tr("Physics"));
-				if (phys_handle.changed) {
-					UtilParticle.init_particle_physics();
-					MakeMaterial.parse_paint_material();
-				}
-			}
-			///end
-		}
-	}
-
-	///end
-
-	///if is_sculpt
-	static draw_tool_properties = (ui: zui_t) => {
-		if (context_raw.tool == workspace_tool_t.BRUSH) {
-			context_raw.brush_radius = zui_slider(context_raw.brush_radius_handle, tr("Radius"), 0.01, 2.0, true);
-			if (ui.is_hovered) zui_tooltip(tr("Hold {brush_radius} and move mouse to the left or press {brush_radius_decrease} to decrease the radius\nHold {brush_radius} and move mouse to the right or press {brush_radius_increase} to increase the radius", new Map([["brush_radius", config_keymap.brush_radius], ["brush_radius_decrease", config_keymap.brush_radius_decrease], ["brush_radius_increase", config_keymap.brush_radius_increase]])));
-		}
-	}
-	///end
-
-	///if is_lab
-	static draw_tool_properties = (ui: zui_t) => {
-		if (context_raw.tool == workspace_tool_t.PICKER) {
-
-		}
-		else if (context_raw.tool == workspace_tool_t.ERASER ||
-				 context_raw.tool == workspace_tool_t.CLONE  ||
-				 context_raw.tool == workspace_tool_t.BLUR   ||
-				 context_raw.tool == workspace_tool_t.SMUDGE) {
-
-			let nodes: zui_nodes_t = UINodes.get_nodes();
-			let canvas: zui_node_canvas_t = UINodes.get_canvas(true);
-			let inpaint: bool = nodes.nodes_selected_id.length > 0 && zui_get_node(canvas.nodes, nodes.nodes_selected_id[0]).type == "InpaintNode";
-			if (inpaint) {
-				context_raw.brush_radius = zui_slider(context_raw.brush_radius_handle, tr("Radius"), 0.01, 2.0, true);
-				if (ui.is_hovered) zui_tooltip(tr("Hold {brush_radius} and move mouse to the left or press {brush_radius_decrease} to decrease the radius\nHold {brush_radius} and move mouse to the right or press {brush_radius_increase} to increase the radius", new Map([["brush_radius", config_keymap.brush_radius], ["brush_radius_decrease", config_keymap.brush_radius_decrease], ["brush_radius_increase", config_keymap.brush_radius_increase]])));
-			}
-		}
-	}
-	///end
-}

+ 0 - 625
base/Sources/UIMenu.ts

@@ -1,625 +0,0 @@
-
-class UIMenu {
-
-	static show: bool = false;
-	static menu_category: i32 = 0;
-	static menu_category_w: i32 = 0;
-	static menu_category_h: i32 = 0;
-	static menu_x: i32 = 0;
-	static menu_y: i32 = 0;
-	static menu_elements: i32 = 0;
-	static keep_open: bool = false;
-	static menu_commands: (ui: zui_t)=>void = null;
-	static show_menu_first: bool = true;
-	static hide_menu: bool = false;
-
-	static render = () => {
-		let ui: zui_t = base_ui_menu;
-		let menu_w: i32 = UIMenu.menu_commands != null ? Math.floor(base_default_element_w * zui_SCALE(base_ui_menu) * 2.3) : Math.floor(zui_ELEMENT_W(ui) * 2.3);
-		let _BUTTON_COL: i32 = ui.t.BUTTON_COL;
-		ui.t.BUTTON_COL = ui.t.SEPARATOR_COL;
-		let _ELEMENT_OFFSET: i32 = ui.t.ELEMENT_OFFSET;
-		ui.t.ELEMENT_OFFSET = 0;
-		let _ELEMENT_H: i32 = ui.t.ELEMENT_H;
-		ui.t.ELEMENT_H = config_raw.touch_ui ? (28 + 2) : 28;
-
-		zui_begin_region(ui, UIMenu.menu_x, UIMenu.menu_y, menu_w);
-
-		if (UIMenu.menu_commands != null) {
-			g2_set_color(ui.t.ACCENT_SELECT_COL);
-			zui_draw_rect(true, ui._x + -1, ui._y + -1, ui._w + 2, zui_ELEMENT_H(ui) * UIMenu.menu_elements + 2);
-			g2_set_color(ui.t.SEPARATOR_COL);
-			zui_draw_rect(true, ui._x + 0, ui._y + 0, ui._w, zui_ELEMENT_H(ui) * UIMenu.menu_elements);
-			g2_set_color(0xffffffff);
-
-			UIMenu.menu_commands(ui);
-		}
-		else {
-			UIMenu.menu_start(ui);
-			if (UIMenu.menu_category == menu_category_t.FILE) {
-				if (UIMenu.menu_button(ui, tr("New .."), config_keymap.file_new)) project_new_box();
-				if (UIMenu.menu_button(ui, tr("Open..."), config_keymap.file_open)) project_open();
-				if (UIMenu.menu_button(ui, tr("Open Recent..."), config_keymap.file_open_recent)) BoxProjects.show();
-				if (UIMenu.menu_button(ui, tr("Save"), config_keymap.file_save)) project_save();
-				if (UIMenu.menu_button(ui, tr("Save As..."), config_keymap.file_save_as)) project_save_as();
-				UIMenu.menu_separator(ui);
-				if (UIMenu.menu_button(ui, tr("Import Texture..."), config_keymap.file_import_assets)) project_import_asset(path_texture_formats.join(","), false);
-				if (UIMenu.menu_button(ui, tr("Import Envmap..."))) {
-					UIFiles.show("hdr", false, false, (path: string) => {
-						if (!path.endsWith(".hdr")) {
-							console_error(tr("Error: .hdr file expected"));
-							return;
-						}
-						ImportAsset.run(path);
-					});
-				}
-
-				///if (is_paint || is_sculpt)
-				if (UIMenu.menu_button(ui, tr("Import Font..."))) project_import_asset("ttf,ttc,otf");
-				if (UIMenu.menu_button(ui, tr("Import Material..."))) project_import_material();
-				if (UIMenu.menu_button(ui, tr("Import Brush..."))) project_import_brush();
-				///end
-
-				///if (is_paint || is_lab)
-				if (UIMenu.menu_button(ui, tr("Import Swatches..."))) project_import_swatches();
-				///end
-				if (UIMenu.menu_button(ui, tr("Import Mesh..."))) project_import_mesh();
-				if (UIMenu.menu_button(ui, tr("Reimport Mesh"), config_keymap.file_reimport_mesh)) project_reimport_mesh();
-				if (UIMenu.menu_button(ui, tr("Reimport Textures"), config_keymap.file_reimport_textures)) project_reimport_textures();
-				UIMenu.menu_separator(ui);
-				///if (is_paint || is_lab)
-				if (UIMenu.menu_button(ui, tr("Export Textures..."), config_keymap.file_export_textures_as)) {
-					///if is_paint
-					context_raw.layers_export = export_mode_t.VISIBLE;
-					///end
-					BoxExport.show_textures();
-				}
-				if (UIMenu.menu_button(ui, tr("Export Swatches..."))) project_export_swatches();
-				///end
-				if (UIMenu.menu_button(ui, tr("Export Mesh..."))) {
-					context_raw.export_mesh_index = 0; // All
-					BoxExport.show_mesh();
-				}
-
-				///if is_paint
-				if (UIMenu.menu_button(ui, tr("Bake Material..."))) BoxExport.show_bake_material();
-				///end
-
-				UIMenu.menu_separator(ui);
-				if (UIMenu.menu_button(ui, tr("Exit"))) sys_stop();
-			}
-			else if (UIMenu.menu_category == menu_category_t.EDIT) {
-				let step_undo: string = "";
-				let step_redo: string = "";
-				if (history_undos > 0) {
-					step_undo = history_steps[history_steps.length - 1 - history_redos].name;
-				}
-				if (history_redos > 0) {
-					step_redo = history_steps[history_steps.length - history_redos].name;
-				}
-				ui.enabled = history_undos > 0;
-				if (UIMenu.menu_button(ui, tr("Undo {step}", new Map([["step", step_undo]])), config_keymap.edit_undo)) history_undo();
-				ui.enabled = history_redos > 0;
-				if (UIMenu.menu_button(ui, tr("Redo {step}", new Map([["step", step_redo]])), config_keymap.edit_redo)) history_redo();
-				ui.enabled = true;
-				UIMenu.menu_separator(ui);
-				if (UIMenu.menu_button(ui, tr("Preferences..."), config_keymap.edit_prefs)) BoxPreferences.show();
-			}
-			else if (UIMenu.menu_category == menu_category_t.VIEWPORT) {
-				if (UIMenu.menu_button(ui, tr("Distract Free"), config_keymap.view_distract_free)) {
-					UIBase.toggle_distract_free();
-					UIBase.ui.is_hovered = false;
-				}
-
-				///if !(krom_android || krom_ios)
-				if (UIMenu.menu_button(ui, tr("Toggle Fullscreen"), "alt+enter")) {
-					base_toggle_fullscreen();
-				}
-				///end
-
-				ui.changed = false;
-
-				UIMenu.menu_fill(ui);
-				let p: world_data_t = scene_world;
-				let env_handle: zui_handle_t = zui_handle("uimenu_0");
-				env_handle.value = p.strength;
-				UIMenu.menu_align(ui);
-				p.strength = zui_slider(env_handle, tr("Environment"), 0.0, 8.0, true);
-				if (env_handle.changed) context_raw.ddirty = 2;
-
-				UIMenu.menu_fill(ui);
-				let enva_handle: zui_handle_t = zui_handle("uimenu_1");
-				enva_handle.value = context_raw.envmap_angle / Math.PI * 180.0;
-				if (enva_handle.value < 0) {
-					enva_handle.value += (Math.floor(-enva_handle.value / 360) + 1) * 360;
-				}
-				else if (enva_handle.value > 360) {
-					enva_handle.value -= Math.floor(enva_handle.value / 360) * 360;
-				}
-				UIMenu.menu_align(ui);
-				context_raw.envmap_angle = zui_slider(enva_handle, tr("Environment Angle"), 0.0, 360.0, true, 1) / 180.0 * Math.PI;
-				if (ui.is_hovered) zui_tooltip(tr("{shortcut} and move mouse", new Map([["shortcut", config_keymap.rotate_envmap]])));
-				if (enva_handle.changed) context_raw.ddirty = 2;
-
-				if (scene_lights.length > 0) {
-					let light: light_object_t = scene_lights[0];
-
-					UIMenu.menu_fill(ui);
-					let lhandle: zui_handle_t = zui_handle("uimenu_2");
-					let scale: f32 = 1333;
-					lhandle.value = light.data.strength / scale;
-					lhandle.value = Math.floor(lhandle.value * 100) / 100;
-					UIMenu.menu_align(ui);
-					light.data.strength = zui_slider(lhandle, tr("Light"), 0.0, 4.0, true) * scale;
-					if (lhandle.changed) context_raw.ddirty = 2;
-
-					UIMenu.menu_fill(ui);
-					light = scene_lights[0];
-					let lahandle: zui_handle_t = zui_handle("uimenu_3");
-					lahandle.value = context_raw.light_angle / Math.PI * 180;
-					UIMenu.menu_align(ui);
-					let new_angle: f32 = zui_slider(lahandle, tr("Light Angle"), 0.0, 360.0, true, 1) / 180 * Math.PI;
-					if (ui.is_hovered) zui_tooltip(tr("{shortcut} and move mouse", new Map([["shortcut", config_keymap.rotate_light]])));
-					let ldiff: f32 = new_angle - context_raw.light_angle;
-					if (Math.abs(ldiff) > 0.005) {
-						if (new_angle < 0) new_angle += (Math.floor(-new_angle / (2 * Math.PI)) + 1) * 2 * Math.PI;
-						else if (new_angle > 2 * Math.PI) new_angle -= Math.floor(new_angle / (2 * Math.PI)) * 2 * Math.PI;
-						context_raw.light_angle = new_angle;
-						let m: mat4_t = mat4_rot_z(ldiff);
-						mat4_mult_mat(light.base.transform.local, m);
-						transform_decompose(light.base.transform);
-						context_raw.ddirty = 2;
-					}
-
-					UIMenu.menu_fill(ui);
-					let sxhandle: zui_handle_t = zui_handle("uimenu_4");
-					sxhandle.value = light.data.size;
-					UIMenu.menu_align(ui);
-					light.data.size = zui_slider(sxhandle, tr("Light Size"), 0.0, 4.0, true);
-					if (sxhandle.changed) context_raw.ddirty = 2;
-				}
-
-				///if (is_paint || is_sculpt)
-				UIMenu.menu_fill(ui);
-				let split_view_handle: zui_handle_t = zui_handle("uimenu_5", { selected: context_raw.split_view });
-				context_raw.split_view = zui_check(split_view_handle, " " + tr("Split View"));
-				if (split_view_handle.changed) {
-					base_resize();
-				}
-				///end
-
-				///if is_lab
-				UIMenu.menu_fill(ui);
-				let brush_scale_handle: zui_handle_t = zui_handle("uimenu_6", { value: context_raw.brush_scale });
-				UIMenu.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) {
-					MakeMaterial.parse_mesh_material();
-					///if (krom_direct3d12 || krom_vulkan || krom_metal)
-					RenderPathRaytrace.uv_scale = context_raw.brush_scale;
-					RenderPathRaytrace.ready = false;
-					///end
-				}
-				///end
-
-				UIMenu.menu_fill(ui);
-				let cull_handle: zui_handle_t = zui_handle("uimenu_7", { selected: context_raw.cull_backfaces });
-				context_raw.cull_backfaces = zui_check(cull_handle, " " + tr("Cull Backfaces"));
-				if (cull_handle.changed) {
-					MakeMaterial.parse_mesh_material();
-				}
-
-				UIMenu.menu_fill(ui);
-				let filter_handle: zui_handle_t = zui_handle("uimenu_8", { selected: context_raw.texture_filter });
-				context_raw.texture_filter = zui_check(filter_handle, " " + tr("Filter Textures"));
-				if (filter_handle.changed) {
-					MakeMaterial.parse_paint_material();
-					MakeMaterial.parse_mesh_material();
-				}
-
-				///if (is_paint || is_sculpt)
-				UIMenu.menu_fill(ui);
-				context_raw.draw_wireframe = zui_check(context_raw.wireframe_handle, " " + tr("Wireframe"));
-				if (context_raw.wireframe_handle.changed) {
-					let current: image_t = _g2_current;
-					g2_end();
-					UtilUV.cache_uv_map();
-					g2_begin(current);
-					MakeMaterial.parse_mesh_material();
-				}
-				///end
-
-				///if is_paint
-				UIMenu.menu_fill(ui);
-				context_raw.draw_texels = zui_check(context_raw.texels_handle, " " + tr("Texels"));
-				if (context_raw.texels_handle.changed) {
-					MakeMaterial.parse_mesh_material();
-				}
-				///end
-
-				UIMenu.menu_fill(ui);
-				let compass_handle: zui_handle_t = zui_handle("uimenu_9", { selected: context_raw.show_compass });
-				context_raw.show_compass = zui_check(compass_handle, " " + tr("Compass"));
-				if (compass_handle.changed) context_raw.ddirty = 2;
-
-				UIMenu.menu_fill(ui);
-				context_raw.show_envmap = zui_check(context_raw.show_envmap_handle, " " + tr("Envmap"));
-				if (context_raw.show_envmap_handle.changed) {
-					context_load_envmap();
-					context_raw.ddirty = 2;
-				}
-
-				UIMenu.menu_fill(ui);
-				context_raw.show_envmap_blur = zui_check(context_raw.show_envmap_blur_handle, " " + tr("Blur Envmap"));
-				if (context_raw.show_envmap_blur_handle.changed) context_raw.ddirty = 2;
-
-				context_update_envmap();
-
-				if (ui.changed) UIMenu.keep_open = true;
-			}
-			else if (UIMenu.menu_category == menu_category_t.MODE) {
-				let mode_handle: zui_handle_t = zui_handle("uimenu_10");
-				mode_handle.position = context_raw.viewport_mode;
-				let modes: string[] = [
-					tr("Lit"),
-					tr("Base Color"),
-					///if (is_paint || is_lab)
-					tr("Normal"),
-					tr("Occlusion"),
-					tr("Roughness"),
-					tr("Metallic"),
-					tr("Opacity"),
-					tr("Height"),
-					///end
-					///if (is_paint)
-					tr("Emission"),
-					tr("Subsurface"),
-					///end
-					///if (is_paint || is_sculpt)
-					tr("TexCoord"),
-					tr("Object Normal"),
-					tr("Material ID"),
-					tr("Object ID"),
-					tr("Mask")
-					///end
-				];
-				let shortcuts: string[] = ["l", "b", "n", "o", "r", "m", "a", "h", "e", "s", "t", "1", "2", "3", "4"];
-
-				///if (krom_direct3d12 || krom_vulkan || krom_metal)
-				if (krom_raytrace_supported()) {
-					modes.push(tr("Path Traced"));
-					shortcuts.push("p");
-				}
-				///end
-
-				for (let i: i32 = 0; i < modes.length; ++i) {
-					UIMenu.menu_fill(ui);
-					let shortcut: string = config_raw.touch_ui ? "" : config_keymap.viewport_mode + ", " + shortcuts[i];
-					zui_radio(mode_handle, i, modes[i], shortcut);
-				}
-
-				if (mode_handle.changed) {
-					context_set_viewport_mode(mode_handle.position);
-					// TODO: rotate mode is not supported for path tracing yet
-					if (mode_handle.position == viewport_mode_t.PATH_TRACE && context_raw.camera_controls == camera_controls_t.ROTATE) {
-						context_raw.camera_controls = camera_controls_t.ORBIT;
-						viewport_reset();
-					}
-				}
-			}
-			else if (UIMenu.menu_category == menu_category_t.CAMERA) {
-				if (UIMenu.menu_button(ui, tr("Reset"), config_keymap.view_reset)) {
-					viewport_reset();
-					viewport_scale_to_bounds();
-				}
-				UIMenu.menu_separator(ui);
-				if (UIMenu.menu_button(ui, tr("Front"), config_keymap.view_front)) {
-					viewport_set_view(0, -1, 0, Math.PI / 2, 0, 0);
-				}
-				if (UIMenu.menu_button(ui, tr("Back"), config_keymap.view_back)) {
-					viewport_set_view(0, 1, 0, Math.PI / 2, 0, Math.PI);
-				}
-				if (UIMenu.menu_button(ui, tr("Right"), config_keymap.view_right)) {
-					viewport_set_view(1, 0, 0, Math.PI / 2, 0, Math.PI / 2);
-				}
-				if (UIMenu.menu_button(ui, tr("Left"), config_keymap.view_left)) {
-					viewport_set_view(-1, 0, 0, Math.PI / 2, 0, -Math.PI / 2);
-				}
-				if (UIMenu.menu_button(ui, tr("Top"), config_keymap.view_top)) {
-					viewport_set_view(0, 0, 1, 0, 0, 0);
-				}
-				if (UIMenu.menu_button(ui, tr("Bottom"), config_keymap.view_bottom)) {
-					viewport_set_view(0, 0, -1, Math.PI, 0, Math.PI);
-				}
-				UIMenu.menu_separator(ui);
-
-				ui.changed = false;
-
-				if (UIMenu.menu_button(ui, tr("Orbit Left"), config_keymap.view_orbit_left)) {
-					viewport_orbit(-Math.PI / 12, 0);
-				}
-				if (UIMenu.menu_button(ui, tr("Orbit Right"), config_keymap.view_orbit_right)) {
-					viewport_orbit(Math.PI / 12, 0);
-				}
-				if (UIMenu.menu_button(ui, tr("Orbit Up"), config_keymap.view_orbit_up)) {
-					viewport_orbit(0, -Math.PI / 12);
-				}
-				if (UIMenu.menu_button(ui, tr("Orbit Down"), config_keymap.view_orbit_down)) {
-					viewport_orbit(0, Math.PI / 12);
-				}
-				if (UIMenu.menu_button(ui, tr("Orbit Opposite"), config_keymap.view_orbit_opposite)) {
-					viewport_orbit_opposite();
-				}
-				if (UIMenu.menu_button(ui, tr("Zoom In"), config_keymap.view_zoom_in)) {
-					viewport_zoom(0.2);
-				}
-				if (UIMenu.menu_button(ui, tr("Zoom Out"), config_keymap.view_zoom_out)) {
-					viewport_zoom(-0.2);
-				}
-				// menuSeparator(ui);
-
-				UIMenu.menu_fill(ui);
-				let cam: camera_object_t = scene_camera;
-				context_raw.fov_handle = zui_handle("uimenu_11", { value: Math.floor(cam.data.fov * 100) / 100 });
-				UIMenu.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) {
-					viewport_update_camera_type(context_raw.camera_type);
-				}
-
-				UIMenu.menu_fill(ui);
-				UIMenu.menu_align(ui);
-				let camera_controls_handle: zui_handle_t = zui_handle("uimenu_12");
-				camera_controls_handle.position = context_raw.camera_controls;
-				context_raw.camera_controls = zui_inline_radio(camera_controls_handle, [tr("Orbit"), tr("Rotate"), tr("Fly")], zui_align_t.LEFT);
-
-				let orbit_and_rotate_tooltip: string = tr("Orbit and Rotate mode:\n{rotate_shortcut} or move right mouse button to rotate.\n{zoom_shortcut} or scroll to zoom.\n{pan_shortcut} or move middle mouse to pan.",
-					new Map([
-						["rotate_shortcut", config_keymap.action_rotate],
-						["zoom_shortcut", config_keymap.action_zoom],
-						["pan_shortcut", config_keymap.action_pan]
-					])
-				);
-				let fly_tooltip: string = tr("Fly mode:\nHold the right mouse button and one of the following commands:\nmove mouse to rotate.\nw, up or scroll up to move forward.\ns, down or scroll down to move backward.\na or left to move left.\nd or right to move right.\ne to move up.\nq to move down.\nHold shift to move faster or alt to move slower.");
-				if (ui.is_hovered) zui_tooltip(orbit_and_rotate_tooltip + "\n\n" + fly_tooltip);
-
-				UIMenu.menu_fill(ui);
-				UIMenu.menu_align(ui);
-				context_raw.camera_type = zui_inline_radio(context_raw.cam_handle, [tr("Perspective"), tr("Orthographic")], zui_align_t.LEFT);
-				if (ui.is_hovered) zui_tooltip(tr("Camera Type") + ` (${config_keymap.view_camera_type})`);
-				if (context_raw.cam_handle.changed) {
-					viewport_update_camera_type(context_raw.camera_type);
-				}
-
-				if (ui.changed) UIMenu.keep_open = true;
-			}
-			else if (UIMenu.menu_category == menu_category_t.HELP) {
-				if (UIMenu.menu_button(ui, tr("Manual"))) {
-					file_load_url(manifest_url + "/manual");
-				}
-				if (UIMenu.menu_button(ui, tr("How To"))) {
-					file_load_url(manifest_url + "/howto");
-				}
-				if (UIMenu.menu_button(ui, tr("What's New"))) {
-					file_load_url(manifest_url + "/notes");
-				}
-				if (UIMenu.menu_button(ui, tr("Issue Tracker"))) {
-					file_load_url("https://github.com/armory3d/armortools/issues");
-				}
-				if (UIMenu.menu_button(ui, tr("Report Bug"))) {
-					///if (krom_darwin || krom_ios) // Limited url length
-					file_load_url("https://github.com/armory3d/armortools/issues/new?labels=bug&template=bug_report.md&body=*" + manifest_title + "%20" + manifest_version + "-" + config_get_sha() + ",%20" + sys_system_id());
-					///else
-					file_load_url("https://github.com/armory3d/armortools/issues/new?labels=bug&template=bug_report.md&body=*" + manifest_title + "%20" + manifest_version + "-" + config_get_sha() + ",%20" + sys_system_id() + "*%0A%0A**Issue description:**%0A%0A**Steps to reproduce:**%0A%0A");
-					///end
-				}
-				if (UIMenu.menu_button(ui, tr("Request Feature"))) {
-					///if (krom_darwin || krom_ios) // Limited url length
-					file_load_url("https://github.com/armory3d/armortools/issues/new?labels=feature%20request&template=feature_request.md&body=*" + manifest_title + "%20" + manifest_version + "-" + config_get_sha() + ",%20" + sys_system_id());
-					///else
-					file_load_url("https://github.com/armory3d/armortools/issues/new?labels=feature%20request&template=feature_request.md&body=*" + manifest_title + "%20" + manifest_version + "-" + config_get_sha() + ",%20" + sys_system_id() + "*%0A%0A**Feature description:**%0A%0A");
-					///end
-				}
-				UIMenu.menu_separator(ui);
-
-				if (UIMenu.menu_button(ui, tr("Check for Updates..."))) {
-					///if krom_android
-					file_load_url(manifest_url_android);
-					///elseif krom_ios
-					file_load_url(manifest_url_ios);
-					///else
-					// Retrieve latest version number
-					file_download_bytes("https://server.armorpaint.org/" + manifest_title.toLowerCase() + ".html", (buffer: ArrayBuffer) => {
-						if (buffer != null)  {
-							// Compare versions
-							let update: any = json_parse(sys_buffer_to_string(buffer));
-							let update_version: i32 = Math.floor(update.version);
-							if (update_version > 0) {
-								let date: string = config_get_date().substr(2); // 2019 -> 19
-								let date_int: i32 = parseInt(string_replace_all(date, "-", ""));
-								if (update_version > date_int) {
-									UIBox.show_message(tr("Update"), tr("Update is available!\nPlease visit {url}.", new Map([["url", manifest_url]])));
-								}
-								else {
-									UIBox.show_message(tr("Update"), tr("You are up to date!"));
-								}
-							}
-						}
-						else {
-							UIBox.show_message(tr("Update"), tr("Unable to check for updates.\nPlease visit {url}.", new Map([["url", manifest_url]])));
-						}
-					});
-					///end
-				}
-
-				if (UIMenu.menu_button(ui, tr("About..."))) {
-
-					let msg: string = manifest_title + ".org - v" + manifest_version + " (" + config_get_date() + ") - " + config_get_sha() + "\n";
-					msg += sys_system_id() + " - " + strings_graphics_api();
-
-					///if krom_windows
-					let save: string = (path_is_protected() ? krom_save_path() : path_data()) + path_sep + "tmp.txt";
-					krom_sys_command('wmic path win32_VideoController get name > "' + save + '"');
-					let blob: buffer_t = krom_load_blob(save);
-					let u8: Uint8Array = new Uint8Array(blob);
-					let gpu_raw: string = "";
-					for (let i: i32 = 0; i < Math.floor(u8.length / 2); ++i) {
-						let c: string = String.fromCharCode(u8[i * 2]);
-						gpu_raw += c;
-					}
-
-					let gpus: string[] = gpu_raw.split("\n");
-					gpus = gpus.splice(1, gpus.length - 2);
-					let gpu: string = "";
-					for (let g of gpus) {
-						gpu += trim_end(g) + ", ";
-					}
-					gpu = gpu.substr(0, gpu.length - 2);
-					msg += `\n${gpu}`;
-					///else
-					// { lshw -C display }
-					///end
-
-					UIBox.show_custom((ui: zui_t) => {
-						let tab_vertical: bool = config_raw.touch_ui;
-						if (zui_tab(zui_handle("uimenu_13"), tr("About"), tab_vertical)) {
-
-							let img: image_t = data_get_image("badge.k");
-							zui_image(img);
-							zui_end_element();
-
-							zui_text_area(zui_handle("uimenu_14", { text: msg }), zui_align_t.LEFT, false);
-
-							zui_row([1 / 3, 1 / 3, 1 / 3]);
-
-							///if (krom_windows || krom_linux || krom_darwin)
-							if (zui_button(tr("Copy"))) {
-								krom_copy_to_clipboard(msg);
-							}
-							///else
-							zui_end_element();
-							///end
-
-							if (zui_button(tr("Contributors"))) {
-								file_load_url("https://github.com/armory3d/armortools/graphs/contributors");
-							}
-							if (zui_button(tr("OK"))) {
-								UIBox.hide();
-							}
-						}
-					}, 400, 320);
-				}
-			}
-		}
-
-		UIMenu.hide_menu = ui.combo_selected_handle_ptr == 0 && !UIMenu.keep_open && !UIMenu.show_menu_first && (ui.changed || ui.input_released || ui.input_released_r || ui.is_escape_down);
-		UIMenu.show_menu_first = false;
-		UIMenu.keep_open = false;
-
-		ui.t.BUTTON_COL = _BUTTON_COL;
-		ui.t.ELEMENT_OFFSET = _ELEMENT_OFFSET;
-		ui.t.ELEMENT_H = _ELEMENT_H;
-		zui_end_region();
-
-		if (UIMenu.hide_menu) {
-			UIMenu.hide();
-			UIMenu.show_menu_first = true;
-			UIMenu.menu_commands = null;
-		}
-	}
-
-	static hide = () => {
-		UIMenu.show = false;
-		base_redraw_ui();
-	}
-
-	static draw = (commands: (ui: zui_t)=>void = null, elements: i32, x: i32 = -1, y: i32 = -1) => {
-		zui_end_input();
-		UIMenu.show = true;
-		UIMenu.menu_commands = commands;
-		UIMenu.menu_elements = elements;
-		UIMenu.menu_x = x > -1 ? x : Math.floor(mouse_x + 1);
-		UIMenu.menu_y = y > -1 ? y : Math.floor(mouse_y + 1);
-		UIMenu.fit_to_screen();
-	}
-
-	static fit_to_screen = () => {
-		// Prevent the menu going out of screen
-		let menu_w: f32 = base_default_element_w * zui_SCALE(base_ui_menu) * 2.3;
-		if (UIMenu.menu_x + menu_w > sys_width()) {
-			if (UIMenu.menu_x - menu_w > 0) {
-				UIMenu.menu_x = Math.floor(UIMenu.menu_x - menu_w);
-			}
-			else {
-				UIMenu.menu_x = Math.floor(sys_width() - menu_w);
-			}
-		}
-		let menu_h: f32 = Math.floor(UIMenu.menu_elements * 30 * zui_SCALE(base_ui_menu)); // ui.t.ELEMENT_H
-		if (UIMenu.menu_y + menu_h > sys_height()) {
-			if (UIMenu.menu_y - menu_h > 0) {
-				UIMenu.menu_y = Math.floor(UIMenu.menu_y - menu_h);
-			}
-			else {
-				UIMenu.menu_y = sys_height() - menu_h;
-			}
-			UIMenu.menu_x += 1; // Move out of mouse focus
-		}
-	}
-
-	static menu_fill = (ui: zui_t) => {
-		g2_set_color(ui.t.ACCENT_SELECT_COL);
-		g2_fill_rect(ui._x - 1, ui._y, ui._w + 2, zui_ELEMENT_H(ui) + 1 + 1);
-		g2_set_color(ui.t.SEPARATOR_COL);
-		g2_fill_rect(ui._x, ui._y, ui._w, zui_ELEMENT_H(ui) + 1);
-		g2_set_color(0xffffffff);
-	}
-
-	static menu_separator = (ui: zui_t) => {
-		ui._y++;
-		if (config_raw.touch_ui) {
-			zui_fill(0, 0, ui._w / zui_SCALE(ui), 1, ui.t.ACCENT_SELECT_COL);
-		}
-		else {
-			zui_fill(26, 0, ui._w / zui_SCALE(ui) - 26, 1, ui.t.ACCENT_SELECT_COL);
-		}
-	}
-
-	static menu_button = (ui: zui_t, text: string, label: string = ""/*, icon: i32 = -1*/): bool => {
-		UIMenu.menu_fill(ui);
-		if (config_raw.touch_ui) {
-			label = "";
-		}
-
-		// let icons: image_t = icon > -1 ? get("icons.k") : null;
-		// let r: rect_t = tile25(icons, icon, 8);
-		// return Zui.button(config_button_spacing + text, config_button_align, label, icons, r.x, r.y, r.w, r.h);
-
-		return zui_button(config_button_spacing + text, config_button_align, label);
-	}
-
-	static menu_align = (ui: zui_t) => {
-		if (!config_raw.touch_ui) {
-			zui_row([12 / 100, 88 / 100]);
-			zui_end_element();
-		}
-	}
-
-	static menu_start = (ui: zui_t) => {
-		// Draw top border
-		g2_set_color(ui.t.ACCENT_SELECT_COL);
-		if (config_raw.touch_ui) {
-			g2_fill_rect(ui._x + ui._w / 2 + UIMenu.menu_category_w / 2, ui._y - 1, ui._w / 2 - UIMenu.menu_category_w / 2 + 1, 1);
-			g2_fill_rect(ui._x - 1, ui._y - 1, ui._w / 2 - UIMenu.menu_category_w / 2 + 1, 1);
-			g2_fill_rect(ui._x + ui._w / 2 - UIMenu.menu_category_w / 2, ui._y - UIMenu.menu_category_h, UIMenu.menu_category_w, 1);
-			g2_fill_rect(ui._x + ui._w / 2 - UIMenu.menu_category_w / 2, ui._y - UIMenu.menu_category_h, 1, UIMenu.menu_category_h);
-			g2_fill_rect(ui._x + ui._w / 2 + UIMenu.menu_category_w / 2, ui._y - UIMenu.menu_category_h, 1, UIMenu.menu_category_h);
-		}
-		else {
-			g2_fill_rect(ui._x - 1 + UIMenu.menu_category_w, ui._y - 1, ui._w + 2 - UIMenu.menu_category_w, 1);
-			g2_fill_rect(ui._x - 1, ui._y - UIMenu.menu_category_h, UIMenu.menu_category_w, 1);
-			g2_fill_rect(ui._x - 1, ui._y - UIMenu.menu_category_h, 1, UIMenu.menu_category_h);
-			g2_fill_rect(ui._x - 1 + UIMenu.menu_category_w, ui._y - UIMenu.menu_category_h, 1, UIMenu.menu_category_h);
-		}
-		g2_set_color(0xffffffff);
-	}
-}

+ 0 - 187
base/Sources/UIMenubar.ts

@@ -1,187 +0,0 @@
-
-class UIMenubar {
-
-	static default_menubar_w: i32 = 330;
-	static workspace_handle: zui_handle_t = zui_handle_create({ layout: zui_layout_t.HORIZONTAL });
-	static menu_handle: zui_handle_t = zui_handle_create({ layout: zui_layout_t.HORIZONTAL });
-	static menubarw: i32 = UIMenubar.default_menubar_w;
-
-	///if is_lab
-	static _saved_camera: mat4_t = null;
-	static _plane: mesh_object_t = null;
-	///end
-
-	constructor() {
-	}
-
-	static render_ui = () => {
-		let ui: zui_t = UIBase.ui;
-
-		///if (is_paint || is_sculpt)
-		let panelx: i32 = app_x() - UIToolbar.toolbar_w;
-		///end
-		///if is_lab
-		let panelx: i32 = app_x();
-		///end
-
-		if (zui_window(UIMenubar.menu_handle, panelx, 0, UIMenubar.menubarw, UIHeader.headerh)) {
-			ui._x += 1; // Prevent "File" button highlight on startup
-
-			zui_begin_menu();
-
-			if (config_raw.touch_ui) {
-
-				///if (is_paint || is_sculpt)
-				ui._w = UIToolbar.toolbar_w;
-				///end
-				///if is_lab
-				ui._w = 36;
-				///end
-
-				if (UIMenubar.icon_button(ui, 0, 2)) BoxPreferences.show();
-				if (UIMenubar.icon_button(ui, 0, 3)) {
-					///if (krom_android || krom_ios)
-					console_toast(tr("Saving project"));
-					project_save();
-					///end
-					base_notify_on_next_frame(() => {
-						BoxProjects.show();
-					});
-				}
-				if (UIMenubar.icon_button(ui, 4, 2)) project_import_asset();
-				///if (is_paint || is_lab)
-				if (UIMenubar.icon_button(ui, 5, 2)) BoxExport.show_textures();
-				///end
-				let size: i32 = Math.floor(ui._w / zui_SCALE(ui));
-				if (UIMenu.show && UIMenu.menu_category == menu_category_t.VIEWPORT) zui_fill(0, -6, size, size - 4, ui.t.HIGHLIGHT_COL);
-				if (UIMenubar.icon_button(ui, 8, 2)) UIMenubar.show_menu(ui, menu_category_t.VIEWPORT);
-				if (UIMenu.show && UIMenu.menu_category == menu_category_t.MODE) zui_fill(0, -6, size, size - 4, ui.t.HIGHLIGHT_COL);
-				if (UIMenubar.icon_button(ui, 9, 2)) UIMenubar.show_menu(ui, menu_category_t.MODE);
-				if (UIMenu.show && UIMenu.menu_category == menu_category_t.CAMERA) zui_fill(0, -6, size, size - 4, ui.t.HIGHLIGHT_COL);
-				if (UIMenubar.icon_button(ui, 10, 2)) UIMenubar.show_menu(ui, menu_category_t.CAMERA);
-				if (UIMenu.show && UIMenu.menu_category == menu_category_t.HELP) zui_fill(0, -6, size, size - 4, ui.t.HIGHLIGHT_COL);
-				if (UIMenubar.icon_button(ui, 11, 2)) UIMenubar.show_menu(ui, menu_category_t.HELP);
-				ui.enabled = history_undos > 0;
-				if (UIMenubar.icon_button(ui, 6, 2)) history_undo();
-				ui.enabled = history_redos > 0;
-				if (UIMenubar.icon_button(ui, 7, 2)) history_redo();
-				ui.enabled = true;
-			}
-			else {
-				let categories: string[] = [tr("File"), tr("Edit"), tr("Viewport"), tr("Mode"), tr("Camera"), tr("Help")];
-				for (let i: i32 = 0; i < categories.length; ++i) {
-					if (zui_menu_button(categories[i]) || (UIMenu.show && UIMenu.menu_commands == null && ui.is_hovered)) {
-						UIMenubar.show_menu(ui, i);
-					}
-				}
-			}
-
-			if (UIMenubar.menubarw < ui._x + 10) {
-				UIMenubar.menubarw = Math.floor(ui._x + 10);
-
-				///if (is_paint || is_sculpt)
-				UIToolbar.toolbar_handle.redraws = 2;
-				///end
-			}
-
-			zui_end_menu();
-		}
-
-		let nodesw: i32 = (UINodes.show || UIView2D.show) ? config_raw.layout[layout_size_t.NODES_W] : 0;
-		///if (is_paint || is_sculpt)
-		let ww: i32 = sys_width() - config_raw.layout[layout_size_t.SIDEBAR_W] - UIMenubar.menubarw - nodesw;
-		panelx = (app_x() - UIToolbar.toolbar_w) + UIMenubar.menubarw;
-		///else
-		let ww: i32 = sys_width() - UIMenubar.menubarw - nodesw;
-		panelx = (app_x()) + UIMenubar.menubarw;
-		///end
-
-		if (zui_window(UIMenubar.workspace_handle, panelx, 0, ww, UIHeader.headerh)) {
-
-			if (!config_raw.touch_ui) {
-				zui_tab(UIHeader.worktab, tr("3D View"));
-			}
-			else {
-				zui_fill(0, 0, ui._window_w, ui._window_h + 4, ui.t.SEPARATOR_COL);
-			}
-
-			///if is_lab
-			zui_tab(UIHeader.worktab, tr("2D View"));
-			if (UIHeader.worktab.changed) {
-				context_raw.ddirty = 2;
-				context_raw.brush_blend_dirty = true;
-				UIHeader.header_handle.redraws = 2;
-				context_main_object().skip_context = null;
-
-				if (UIHeader.worktab.position == space_type_t.SPACE3D) {
-					if (UIMenubar._saved_camera != null) {
-						transform_set_matrix(scene_camera.base.transform, UIMenubar._saved_camera);
-						UIMenubar._saved_camera = null;
-					}
-					scene_meshes = [context_main_object()];
-				}
-				else { // Space2D
-					if (UIMenubar._plane == null) {
-						let mesh: any = geom_make_plane(1, 1, 2, 2);
-						let raw: any = {
-							name: "2DView",
-							vertex_arrays: [
-								{ values: mesh.posa, attrib: "pos", data: "short4norm" },
-								{ values: mesh.nora, attrib: "nor", data: "short2norm" },
-								{ values: mesh.texa, attrib: "tex", data: "short2norm" }
-							],
-							index_arrays: [
-								{ values: mesh.inda, material: 0 }
-							],
-							scale_pos: mesh.scale_pos,
-							scale_tex: mesh.scale_tex
-						};
-						let md: mesh_data_t = mesh_data_create(raw);
-						let dot_plane: mesh_object_t = scene_get_child(".Plane").ext;
-						UIMenubar._plane = mesh_object_create(md, dot_plane.materials);
-						array_remove(scene_meshes, UIMenubar._plane);
-					}
-
-					if (UIMenubar._saved_camera == null) {
-						UIMenubar._saved_camera = mat4_clone(scene_camera.base.transform.local);
-					}
-					scene_meshes = [UIMenubar._plane];
-					let m: mat4_t = mat4_identity();
-					mat4_translate(m, 0, 0, 1.6);
-					transform_set_matrix(scene_camera.base.transform, m);
-				}
-				///if (krom_direct3d12 || krom_vulkan || krom_metal)
-				RenderPathRaytrace.ready = false;
-				///end
-			}
-			///end
-		}
-	}
-
-	static show_menu = (ui: zui_t, category: i32) => {
-		UIMenu.show = true;
-		UIMenu.menu_commands = null;
-		UIMenu.menu_category = category;
-		UIMenu.menu_category_w = ui._w;
-		UIMenu.menu_category_h = Math.floor(zui_MENUBAR_H(ui));
-		UIMenu.menu_x = Math.floor(ui._x - ui._w);
-		UIMenu.menu_y = Math.floor(zui_MENUBAR_H(ui));
-		if (config_raw.touch_ui) {
-			let menuW: i32 = Math.floor(base_default_element_w * zui_SCALE(base_ui_menu) * 2.0);
-			UIMenu.menu_x -= Math.floor((menuW - ui._w) / 2) + Math.floor(UIHeader.headerh / 2);
-			UIMenu.menu_x += Math.floor(2 * zui_SCALE(base_ui_menu));
-			UIMenu.menu_y -= Math.floor(2 * zui_SCALE(base_ui_menu));
-			UIMenu.keep_open = true;
-		}
-	}
-
-	static icon_button = (ui: zui_t, i: i32, j: i32): bool => {
-		let col: i32 = ui.t.WINDOW_BG_COL;
-		if (col < 0) col += 4294967296;
-		let light: bool = col > (0xff666666 + 4294967296);
-		let icon_accent: i32 = light ? 0xff666666 : 0xffaaaaaa;
-		let img: image_t = resource_get("icons.k");
-		let rect: rect_t = resource_tile50(img, i, j);
-		return zui_image(img, icon_accent, -1.0, rect.x, rect.y, rect.w, rect.h) == zui_state_t.RELEASED;
-	}
-}

+ 0 - 1291
base/Sources/UINodes.ts

@@ -1,1291 +0,0 @@
-
-class UINodes {
-
-	///if (is_paint || is_sculpt)
-	static show: bool = false;
-	///end
-	///if is_lab
-	static show: bool = true;
-	///end
-
-	static wx: i32;
-	static wy: i32;
-	static ww: i32;
-	static wh: i32;
-
-	static ui: zui_t;
-	static canvas_type = canvas_type_t.MATERIAL;
-	static show_menu: bool = false;
-	static show_menu_first: bool = true;
-	static hide_menu: bool = false;
-	static menu_category: i32 = 0;
-	static popup_x: f32 = 0.0;
-	static popup_y: f32 = 0.0;
-
-	static uichanged_last: bool = false;
-	static recompile_mat: bool = false; // Mat preview
-	static recompile_mat_final: bool = false;
-	static node_search_spawn: zui_node_t = null;
-	static node_search_offset: i32 = 0;
-	static last_canvas: zui_node_canvas_t = null;
-	static last_node_selected_id: i32 = -1;
-	static release_link: bool = false;
-	static is_node_menu_op: bool = false;
-
-	static grid: image_t = null;
-	static hwnd: zui_handle_t = zui_handle_create();
-	static group_stack: node_group_t[] = [];
-	static controls_down: bool = false;
-
-	constructor() {
-		zui_set_on_link_drag(UINodes.on_link_drag);
-		zui_set_on_socket_released(UINodes.on_socket_released);
-		zui_set_on_canvas_released(UINodes.on_canvas_released);
-		zui_set_on_canvas_control(UINodes.on_canvas_control);
-
-		let scale: f32 = config_raw.window_scale;
-		UINodes.ui = zui_create({ theme: base_theme, font: base_font, color_wheel: base_color_wheel, black_white_gradient: base_color_wheel_gradient, scale_factor: scale });
-		UINodes.ui.scroll_enabled = false;
-	}
-
-	static on_link_drag = (linkDragId: i32, isNewLink: bool) => {
-		if (isNewLink) {
-			let nodes: zui_nodes_t = UINodes.get_nodes();
-			let link_drag: zui_node_link_t = zui_get_link(UINodes.get_canvas(true).links, linkDragId);
-			let node: zui_node_t = zui_get_node(UINodes.get_canvas(true).nodes, link_drag.from_id > -1 ? link_drag.from_id : link_drag.to_id);
-			let link_x: i32 = UINodes.ui._window_x + zui_nodes_NODE_X(node);
-			let link_y: i32 = UINodes.ui._window_y + zui_nodes_NODE_Y(node);
-			if (link_drag.from_id > -1) {
-				link_x += zui_nodes_NODE_W(node);
-				link_y += zui_nodes_OUTPUT_Y(node.outputs, link_drag.from_socket);
-			}
-			else {
-				link_y += zui_nodes_INPUT_Y(UINodes.get_canvas(true), node.inputs, link_drag.to_socket) + zui_nodes_OUTPUTS_H(node.outputs) + zui_nodes_BUTTONS_H(node);
-			}
-			if (Math.abs(mouse_x - link_x) > 5 || Math.abs(mouse_y - link_y) > 5) { // Link length
-				UINodes.node_search(-1, -1, () => {
-					let n: zui_node_t = zui_get_node(UINodes.get_canvas(true).nodes, nodes.nodes_selected_id[0]);
-					if (link_drag.to_id == -1 && n.inputs.length > 0) {
-						link_drag.to_id = n.id;
-						let from_type: string = node.outputs[link_drag.from_socket].type;
-						// Connect to the first socket
-						link_drag.to_socket = 0;
-						// Try to find the first type-matching socket and use it if present
-						for (let socket of n.inputs) {
-							if (socket.type == from_type) {
-								link_drag.to_socket = n.inputs.indexOf(socket);
-								break;
-							}
-						}
-						UINodes.get_canvas(true).links.push(link_drag);
-					}
-					else if (link_drag.from_id == -1 && n.outputs.length > 0) {
-						link_drag.from_id = n.id;
-						link_drag.from_socket = 0;
-						UINodes.get_canvas(true).links.push(link_drag);
-					}
-					///if is_lab
-					ParserLogic.parse(UINodes.get_canvas(true));
-					context_raw.rdirty = 5;
-					///end
-				});
-			}
-			// Selecting which node socket to preview
-			else if (node.id == nodes.nodes_selected_id[0]) {
-				context_raw.node_preview_socket = link_drag.from_id > -1 ? link_drag.from_socket : 0;
-				///if (is_paint || is_sculpt)
-				context_raw.node_preview_dirty = true;
-				///end
-			}
-		}
-	}
-
-	static on_socket_released = (socket_id: i32) => {
-		let nodes: zui_nodes_t = UINodes.get_nodes();
-		let canvas: zui_node_canvas_t = UINodes.get_canvas(true);
-		let socket: zui_node_socket_t = zui_get_socket(canvas.nodes, socket_id);
-		let node: zui_node_t = zui_get_node(canvas.nodes, socket.node_id);
-		if (UINodes.ui.input_released_r) {
-			if (node.type == "GROUP_INPUT" || node.type == "GROUP_OUTPUT") {
-				base_notify_on_next_frame(() => {
-					UIMenu.draw((ui: zui_t) => {
-						if (UIMenu.menu_button(ui, tr("Edit"))) {
-							let htype: zui_handle_t = zui_handle("uinodes_0");
-							let hname: zui_handle_t = zui_handle("uinodes_1");
-							let hmin: zui_handle_t = zui_handle("uinodes_2");
-							let hmax: zui_handle_t = zui_handle("uinodes_3");
-							let hval0: zui_handle_t = zui_handle("uinodes_4");
-							let hval1: zui_handle_t = zui_handle("uinodes_5");
-							let hval2: zui_handle_t = zui_handle("uinodes_6");
-							let hval3: zui_handle_t = zui_handle("uinodes_7");
-							htype.position = socket.type == "RGBA" ? 0 : socket.type == "VECTOR" ? 1 : 2;
-							hname.text = socket.name;
-							hmin.value = socket.min;
-							hmax.value = socket.max;
-							if (socket.type == "RGBA" || socket.type == "VECTOR") {
-								hval0.value = socket.default_value[0];
-								hval1.value = socket.default_value[1];
-								hval2.value = socket.default_value[2];
-								if (socket.type == "RGBA") {
-									hval3.value = socket.default_value[3];
-								}
-							}
-							else hval0.value = socket.default_value;
-							base_notify_on_next_frame(() => {
-								zui_end_input();
-								UIBox.show_custom((ui: zui_t) => {
-									if (zui_tab(zui_handle("uinodes_8"), tr("Socket"))) {
-										let type: i32 = zui_combo(htype, [tr("Color"), tr("Vector"), tr("Value")], tr("Type"), true);
-										if (htype.changed) hname.text = type == 0 ? tr("Color") : type == 1 ? tr("Vector") : tr("Value");
-										let name: string = zui_text_input(hname, tr("Name"));
-										let min: f32 = zui_float_input(hmin, tr("Min"));
-										let max: f32 = zui_float_input(hmax, tr("Max"));
-										let default_value: any = null;
-										if (type == 0) {
-											zui_row([1 / 4, 1 / 4, 1 / 4, 1 / 4]);
-											zui_float_input(hval0, tr("R"));
-											zui_float_input(hval1, tr("G"));
-											zui_float_input(hval2, tr("B"));
-											zui_float_input(hval3, tr("A"));
-											default_value = new Float32Array([hval0.value, hval1.value, hval2.value, hval3.value]);
-										}
-										else if (type == 1) {
-											zui_row([1 / 3, 1 / 3, 1 / 3]);
-											hval0.value = zui_float_input(hval0, tr("X"));
-											hval1.value = zui_float_input(hval1, tr("Y"));
-											hval2.value = zui_float_input(hval2, tr("Z"));
-											default_value = new Float32Array([hval0.value, hval1.value, hval2.value]);
-										}
-										else {
-											default_value = zui_float_input(hval0, tr("default_value"));
-										}
-										if (zui_button(tr("OK"))) { // || ui.isReturnDown
-											socket.name = name;
-											socket.type = type == 0 ? "RGBA" : type == 1 ? "VECTOR" : "VALUE";
-											socket.color = NodesMaterial.get_socket_color(socket.type);
-											socket.min = min;
-											socket.max = max;
-											socket.default_value = default_value;
-											UIBox.hide();
-											NodesMaterial.sync_sockets(node);
-											UINodes.hwnd.redraws = 2;
-										}
-									}
-								}, 400, 250);
-							});
-						}
-						if (UIMenu.menu_button(ui, tr("Delete"))) {
-							let i: i32 = 0;
-							// Remove links connected to the socket
-							while (i < canvas.links.length) {
-								let l: zui_node_link_t = canvas.links[i];
-								if ((l.from_id == node.id && l.from_socket == node.outputs.indexOf(socket)) ||
-									(l.to_id == node.id && l.to_socket == node.inputs.indexOf(socket))) {
-									canvas.links.splice(i, 1);
-								}
-								else i++;
-							}
-							// Remove socket
-							array_remove(node.inputs, socket);
-							array_remove(node.outputs, socket);
-							NodesMaterial.sync_sockets(node);
-						}
-					}, 2);
-				});
-			}
-			else UINodes.on_canvas_released();
-		}
-		// Selecting which node socket to preview
-		else if (node.id == nodes.nodes_selected_id[0]) {
-			let i: i32 = node.outputs.indexOf(socket);
-			if (i > -1) {
-				context_raw.node_preview_socket = i;
-				///if (is_paint || is_sculpt)
-				context_raw.node_preview_dirty = true;
-				///end
-			}
-		}
-	}
-
-	static on_canvas_released = () => {
-		if (UINodes.ui.input_released_r && Math.abs(UINodes.ui.input_x - UINodes.ui.input_started_x) < 2 && Math.abs(UINodes.ui.input_y - UINodes.ui.input_started_y) < 2) {
-			// Node selection
-			let nodes: zui_nodes_t = UINodes.get_nodes();
-			let canvas: zui_node_canvas_t = UINodes.get_canvas(true);
-			let selected: zui_node_t = null;
-			for (let node of canvas.nodes) {
-				if (zui_get_input_in_rect(UINodes.ui._window_x + zui_nodes_NODE_X(node), UINodes.ui._window_y + zui_nodes_NODE_Y(node), zui_nodes_NODE_W(node), zui_nodes_NODE_H(canvas, node))) {
-					selected = node;
-					break;
-				}
-			}
-			if (selected == null) nodes.nodes_selected_id = [];
-			else if (nodes.nodes_selected_id.indexOf(selected.id) == -1) nodes.nodes_selected_id = [selected.id];
-
-			// Node context menu
-			if (!zui_socket_released()) {
-				let number_of_entries: i32 = 5;
-				if (UINodes.canvas_type == canvas_type_t.MATERIAL) ++number_of_entries;
-				if (selected != null && selected.type == "RGB") ++number_of_entries;
-
-				UIMenu.draw((uiMenu: zui_t) => {
-					uiMenu._y += 1;
-					let is_protected: bool = selected == null ||
-									///if (is_paint || is_sculpt)
-									selected.type == "OUTPUT_MATERIAL_PBR" ||
-									///end
-									selected.type == "GROUP_INPUT" ||
-									selected.type == "GROUP_OUTPUT" ||
-									selected.type == "BrushOutputNode";
-					uiMenu.enabled = !is_protected;
-					if (UIMenu.menu_button(uiMenu, tr("Cut"), "ctrl+x")) {
-						base_notify_on_next_frame(() => {
-							UINodes.hwnd.redraws = 2;
-							zui_set_is_copy(true);
-							zui_set_is_cut(true);
-							UINodes.is_node_menu_op = true;
-						});
-					}
-					if (UIMenu.menu_button(uiMenu, tr("Copy"), "ctrl+c")) {
-						base_notify_on_next_frame(() => {
-							zui_set_is_copy(true);
-							UINodes.is_node_menu_op = true;
-						});
-					}
-					uiMenu.enabled = zui_clipboard != "";
-					if (UIMenu.menu_button(uiMenu, tr("Paste"), "ctrl+v")) {
-						base_notify_on_next_frame(() => {
-							UINodes.hwnd.redraws = 2;
-							zui_set_is_paste(true);
-							UINodes.is_node_menu_op = true;
-						});
-					}
-					uiMenu.enabled = !is_protected;
-					if (UIMenu.menu_button(uiMenu, tr("Delete"), "delete")) {
-						base_notify_on_next_frame(() => {
-							UINodes.hwnd.redraws = 2;
-							UINodes.ui.is_delete_down = true;
-							UINodes.is_node_menu_op = true;
-						});
-					}
-					if (UIMenu.menu_button(uiMenu, tr("Duplicate"))) {
-						base_notify_on_next_frame(() => {
-							UINodes.hwnd.redraws = 2;
-							zui_set_is_copy(true);
-							zui_set_is_paste(true);
-							UINodes.is_node_menu_op = true;
-						});
-					}
-					if (selected != null && selected.type == "RGB") {
-						if (UIMenu.menu_button(uiMenu, tr("Add Swatch"))) {
-							let color: any = selected.outputs[0].default_value;
-							let new_swatch: swatch_color_t = make_swatch(color_from_floats(color[0], color[1], color[2], color[3]));
-							context_set_swatch(new_swatch);
-							project_raw.swatches.push(new_swatch);
-							UIBase.hwnds[tab_area_t.STATUS].redraws = 1;
-						}
-					}
-
-					if (UINodes.canvas_type == canvas_type_t.MATERIAL) {
-						UIMenu.menu_separator(uiMenu);
-						if (UIMenu.menu_button(uiMenu, tr("2D View"))) {
-							UIBase.show_2d_view(view_2d_type_t.NODE);
-						}
-					}
-
-					uiMenu.enabled = true;
-				}, number_of_entries);
-			}
-		}
-
-		if (UINodes.ui.input_released) {
-			let nodes: zui_nodes_t = UINodes.get_nodes();
-			let canvas: zui_node_canvas_t = UINodes.get_canvas(true);
-			for (let node of canvas.nodes) {
-				if (zui_get_input_in_rect(UINodes.ui._window_x + zui_nodes_NODE_X(node), UINodes.ui._window_y + zui_nodes_NODE_Y(node), zui_nodes_NODE_W(node), zui_nodes_NODE_H(canvas, node))) {
-					if (node.id == nodes.nodes_selected_id[0]) {
-						UIView2D.hwnd.redraws = 2;
-						if (time_time() - context_raw.select_time < 0.25) UIBase.show_2d_view(view_2d_type_t.NODE);
-						context_raw.select_time = time_time();
-					}
-					break;
-				}
-			}
-		}
-	}
-
-	static on_canvas_control = (): zui_canvas_control_t => {
-		return UINodes.get_canvas_control(UINodes.ui, UINodes);
-	}
-
-	static get_canvas_control = (ui: zui_t, parent: any): zui_canvas_control_t => {
-		if (config_raw.wrap_mouse && parent.controlsDown) {
-			if (ui.input_x < ui._window_x) {
-				ui.input_x = ui._window_x + ui._window_w;
-				krom_set_mouse_position(Math.floor(ui.input_x), Math.floor(ui.input_y));
-			}
-			else if (ui.input_x > ui._window_x + ui._window_w) {
-				ui.input_x = ui._window_x;
-				krom_set_mouse_position(Math.floor(ui.input_x), Math.floor(ui.input_y));
-			}
-			else if (ui.input_y < ui._window_y) {
-				ui.input_y = ui._window_y + ui._window_h;
-				krom_set_mouse_position(Math.floor(ui.input_x), Math.floor(ui.input_y));
-			}
-			else if (ui.input_y > ui._window_y + ui._window_h) {
-				ui.input_y = ui._window_y;
-				krom_set_mouse_position(Math.floor(ui.input_x), Math.floor(ui.input_y));
-			}
-		}
-
-		if (operator_shortcut(config_keymap.action_pan, shortcut_type_t.STARTED) ||
-			operator_shortcut(config_keymap.action_zoom, shortcut_type_t.STARTED) ||
-			ui.input_started_r ||
-			ui.input_wheel_delta != 0.0) {
-			parent.controlsDown = true;
-		}
-		else if (!operator_shortcut(config_keymap.action_pan, shortcut_type_t.DOWN) &&
-			!operator_shortcut(config_keymap.action_zoom, shortcut_type_t.DOWN) &&
-			!ui.input_down_r &&
-			ui.input_wheel_delta == 0.0) {
-			parent.controlsDown = false;
-		}
-		if (!parent.controlsDown) {
-			return {
-				pan_x: 0,
-				pan_y: 0,
-				zoom: 0
-			}
-		}
-
-		let pan: bool = ui.input_down_r || operator_shortcut(config_keymap.action_pan, shortcut_type_t.DOWN);
-		let zoom_delta: f32 = operator_shortcut(config_keymap.action_zoom, shortcut_type_t.DOWN) ? UINodes.get_zoom_delta(ui) / 100.0 : 0.0;
-		let control: any = {
-			pan_x: pan ? ui.input_dx : 0.0,
-			pan_y: pan ? ui.input_dy : 0.0,
-			zoom: ui.input_wheel_delta != 0.0 ? -ui.input_wheel_delta / 10 : zoom_delta
-		};
-		if (base_is_combo_selected()) control.zoom = 0.0;
-		return control;
-	}
-
-	static get_zoom_delta = (ui: zui_t): f32 => {
-		return config_raw.zoom_direction == zoom_direction_t.VERTICAL ? -ui.input_dy :
-			   config_raw.zoom_direction == zoom_direction_t.VERTICAL_INVERTED ? -ui.input_dy :
-			   config_raw.zoom_direction == zoom_direction_t.HORIZONTAL ? ui.input_dx :
-			   config_raw.zoom_direction == zoom_direction_t.HORIZONTAL_INVERTED ? ui.input_dx :
-			   -(ui.input_dy - ui.input_dx);
-	}
-
-	static get_canvas = (groups: bool = false): zui_node_canvas_t => {
-		///if (is_paint || is_sculpt)
-		if (UINodes.canvas_type == canvas_type_t.MATERIAL) {
-			if (groups && UINodes.group_stack.length > 0) return UINodes.group_stack[UINodes.group_stack.length - 1].canvas;
-			else return UINodes.get_canvas_material();
-		}
-		else return context_raw.brush.canvas;
-		///end
-
-		///if is_lab
-		return project_canvas;
-		///end
-	}
-
-	///if (is_paint || is_sculpt)
-	static get_canvas_material = (): zui_node_canvas_t => {
-		return context_raw.material.canvas;
-	}
-	///end
-
-	static get_nodes = (): zui_nodes_t => {
-		///if (is_paint || is_sculpt)
-		if (UINodes.canvas_type == canvas_type_t.MATERIAL) {
-			if (UINodes.group_stack.length > 0) return UINodes.group_stack[UINodes.group_stack.length - 1].nodes;
-			else return context_raw.material.nodes;
-		}
-		else return context_raw.brush.nodes;
-		///end
-
-		///if is_lab
-		if (UINodes.group_stack.length > 0) return UINodes.group_stack[UINodes.group_stack.length - 1].nodes;
-		else return project_nodes;
-		///end
-	}
-
-	static update = () => {
-		if (!UINodes.show || !base_ui_enabled) return;
-
-		///if (is_paint || is_sculpt)
-		UINodes.wx = Math.floor(app_w()) + UIToolbar.toolbar_w;
-		///end
-		///if is_lab
-		UINodes.wx = Math.floor(app_w());
-		///end
-		UINodes.wy = UIHeader.headerh * 2;
-
-		if (UIView2D.show) {
-			UINodes.wy += app_h() - config_raw.layout[layout_size_t.NODES_H];
-		}
-
-		let ww: i32 = config_raw.layout[layout_size_t.NODES_W];
-		if (!UIBase.show) {
-			///if (is_paint || is_sculpt)
-			ww += config_raw.layout[layout_size_t.SIDEBAR_W] + UIToolbar.toolbar_w;
-			UINodes.wx -= UIToolbar.toolbar_w;
-			///end
-			UINodes.wy = 0;
-		}
-
-		let mx: i32 = mouse_x;
-		let my: i32 = mouse_y;
-		if (mx < UINodes.wx || mx > UINodes.wx + ww || my < UINodes.wy) return;
-		if (UINodes.ui.is_typing || !UINodes.ui.input_enabled) return;
-
-		let nodes: zui_nodes_t = UINodes.get_nodes();
-		if (nodes.nodes_selected_id.length > 0 && UINodes.ui.is_key_pressed) {
-			if (UINodes.ui.key == key_code_t.LEFT) for (let n of nodes.nodes_selected_id) zui_get_node(UINodes.get_canvas(true).nodes, n).x -= 1;
-			else if (UINodes.ui.key == key_code_t.RIGHT) for (let n of nodes.nodes_selected_id) zui_get_node(UINodes.get_canvas(true).nodes, n).x += 1;
-			if (UINodes.ui.key == key_code_t.UP) for (let n of nodes.nodes_selected_id) zui_get_node(UINodes.get_canvas(true).nodes, n).y -= 1;
-			else if (UINodes.ui.key == key_code_t.DOWN) for (let n of nodes.nodes_selected_id) zui_get_node(UINodes.get_canvas(true).nodes, n).y += 1;
-		}
-
-		// Node search popup
-		if (operator_shortcut(config_keymap.node_search)) UINodes.node_search();
-		if (UINodes.node_search_spawn != null) {
-			UINodes.ui.input_x = mouse_x; // Fix inputDX after popup removal
-			UINodes.ui.input_y = mouse_y;
-			UINodes.node_search_spawn = null;
-		}
-
-		if (operator_shortcut(config_keymap.view_reset)) {
-			nodes.panX = 0.0;
-			nodes.panY = 0.0;
-			nodes.zoom = 1.0;
-		}
-	}
-
-	static canvas_changed = () => {
-		UINodes.recompile_mat = true;
-		UINodes.recompile_mat_final = true;
-	}
-
-	static node_search = (x: i32 = -1, y: i32 = -1, done: ()=>void = null) => {
-		let search_handle: zui_handle_t = zui_handle("uinodes_9");
-		let first: bool = true;
-		UIMenu.draw((ui: zui_t) => {
-			g2_set_color(ui.t.SEPARATOR_COL);
-			zui_draw_rect(true, ui._x, ui._y, ui._w, zui_ELEMENT_H(ui) * 8);
-			g2_set_color(0xffffffff);
-
-			let search: string = zui_text_input(search_handle, "", zui_align_t.LEFT, true, true).toLowerCase();
-			ui.changed = false;
-			if (first) {
-				first = false;
-				search_handle.text = "";
-				zui_start_text_edit(search_handle); // Focus search bar
-			}
-
-			if (search_handle.changed) UINodes.node_search_offset = 0;
-
-			if (ui.is_key_pressed) { // Move selection
-				if (ui.key == key_code_t.DOWN && UINodes.node_search_offset < 6) UINodes.node_search_offset++;
-				if (ui.key == key_code_t.UP && UINodes.node_search_offset > 0) UINodes.node_search_offset--;
-			}
-			let enter: bool = keyboard_down("enter");
-			let count: i32 = 0;
-			let BUTTON_COL: i32 = ui.t.BUTTON_COL;
-
-			///if (is_paint || is_sculpt)
-			let node_list: zui_node_t[][] = UINodes.canvas_type == canvas_type_t.MATERIAL ? NodesMaterial.list : NodesBrush.list;
-			///end
-			///if is_lab
-			let node_list: zui_node_t[][] = NodesBrush.list;
-			///end
-
-			for (let list of node_list) {
-				for (let n of list) {
-					if (tr(n.name).toLowerCase().indexOf(search) >= 0) {
-						ui.t.BUTTON_COL = count == UINodes.node_search_offset ? ui.t.HIGHLIGHT_COL : ui.t.SEPARATOR_COL;
-						if (zui_button(tr(n.name), zui_align_t.LEFT) || (enter && count == UINodes.node_search_offset)) {
-							UINodes.push_undo();
-							let nodes: zui_nodes_t = UINodes.get_nodes();
-							let canvas: zui_node_canvas_t = UINodes.get_canvas(true);
-							UINodes.node_search_spawn = UINodes.make_node(n, nodes, canvas); // Spawn selected node
-							canvas.nodes.push(UINodes.node_search_spawn);
-							nodes.nodes_selected_id = [UINodes.node_search_spawn.id];
-							nodes.nodesDrag = true;
-
-							///if is_lab
-							ParserLogic.parse(canvas);
-							///end
-
-							UINodes.hwnd.redraws = 2;
-							if (enter) {
-								ui.changed = true;
-								count = 6; // Trigger break
-							}
-							if (done != null) done();
-						}
-						if (++count > 6) break;
-					}
-				}
-				if (count > 6) break;
-			}
-			if (enter && count == 0) { // Hide popup on enter when node is not found
-				ui.changed = true;
-				search_handle.text = "";
-			}
-			ui.t.BUTTON_COL = BUTTON_COL;
-		}, 8, x, y);
-	}
-
-	static get_node_x = (): i32 => {
-		return Math.floor((mouse_x - UINodes.wx - zui_nodes_PAN_X()) / zui_nodes_SCALE());
-	}
-
-	static get_node_y = (): i32 => {
-		return Math.floor((mouse_y - UINodes.wy - zui_nodes_PAN_Y()) / zui_nodes_SCALE());
-	}
-
-	static draw_grid = () => {
-		let ww: i32 = config_raw.layout[layout_size_t.NODES_W];
-
-		///if (is_paint || is_sculpt)
-		if (!UIBase.show) {
-			ww += config_raw.layout[layout_size_t.SIDEBAR_W] + UIToolbar.toolbar_w;
-		}
-		///end
-
-		let wh: i32 = app_h();
-		let step: f32 = 100 * zui_SCALE(UINodes.ui);
-		let w: i32 = Math.floor(ww + step * 3);
-		let h: i32 = Math.floor(wh + step * 3);
-		if (w < 1) w = 1;
-		if (h < 1) h = 1;
-		UINodes.grid = image_create_render_target(w, h);
-		g2_begin(UINodes.grid);
-		g2_clear(UINodes.ui.t.SEPARATOR_COL);
-
-		g2_set_color(UINodes.ui.t.SEPARATOR_COL - 0x00050505);
-		step = 20 * zui_SCALE(UINodes.ui);
-		for (let i: i32 = 0; i < Math.floor(h / step) + 1; ++i) {
-			g2_draw_line(0, i * step, w, i * step);
-		}
-		for (let i: i32 = 0; i < Math.floor(w / step) + 1; ++i) {
-			g2_draw_line(i * step, 0, i * step, h);
-		}
-
-		g2_set_color(UINodes.ui.t.SEPARATOR_COL - 0x00090909);
-		step = 100 * zui_SCALE(UINodes.ui);
-		for (let i: i32 = 0; i < Math.floor(h / step) + 1; ++i) {
-			g2_draw_line(0, i * step, w, i * step);
-		}
-		for (let i: i32 = 0; i < Math.floor(w / step) + 1; ++i) {
-			g2_draw_line(i * step, 0, i * step, h);
-		}
-
-		g2_end();
-	}
-
-	static render = () => {
-		if (UINodes.recompile_mat) {
-			///if (is_paint || is_sculpt)
-			if (UINodes.canvas_type == canvas_type_t.BRUSH) {
-				MakeMaterial.parse_brush();
-				UtilRender.make_brush_preview();
-				UIBase.hwnds[tab_area_t.SIDEBAR1].redraws = 2;
-			}
-			else {
-				base_is_fill_material() ? base_update_fill_layers() : UtilRender.make_material_preview();
-				if (UIView2D.show && UIView2D.type == view_2d_type_t.NODE) {
-					UIView2D.hwnd.redraws = 2;
-				}
-			}
-
-			UIBase.hwnds[tab_area_t.SIDEBAR1].redraws = 2;
-			if (context_raw.split_view) context_raw.ddirty = 2;
-			///end
-
-			///if is_lab
-			ParserLogic.parse(project_canvas);
-			///end
-
-			UINodes.recompile_mat = false;
-		}
-		else if (UINodes.recompile_mat_final) {
-			///if (is_paint || is_sculpt)
-			MakeMaterial.parse_paint_material();
-
-			if (UINodes.canvas_type == canvas_type_t.MATERIAL && base_is_fill_material()) {
-				base_update_fill_layers();
-				UtilRender.make_material_preview();
-			}
-
-			let decal: bool = context_raw.tool == workspace_tool_t.DECAL || context_raw.tool == workspace_tool_t.TEXT;
-			if (decal) UtilRender.make_decal_preview();
-
-			UIBase.hwnds[tab_area_t.SIDEBAR0].redraws = 2;
-			context_raw.node_preview_dirty = true;
-			///end
-
-			UINodes.recompile_mat_final = false;
-		}
-
-		let nodes: zui_nodes_t = UINodes.get_nodes();
-		if (nodes.nodes_selected_id.length > 0 && nodes.nodes_selected_id[0] != UINodes.last_node_selected_id) {
-			UINodes.last_node_selected_id = nodes.nodes_selected_id[0];
-			///if (is_paint || is_sculpt)
-			context_raw.node_preview_dirty = true;
-			///end
-
-			///if is_lab
-			context_raw.ddirty = 2; // Show selected node texture in viewport
-			UIHeader.header_handle.redraws = 2;
-			///end
-
-			context_raw.node_preview_socket = 0;
-		}
-
-		// Remove dragged link when mouse is released out of the node viewport
-		let c: zui_node_canvas_t = UINodes.get_canvas(true);
-		if (UINodes.release_link && nodes.linkDragId != -1) {
-			array_remove(c.links, zui_get_link(c.links, nodes.linkDragId));
-			nodes.linkDragId = -1;
-		}
-		UINodes.release_link = UINodes.ui.input_released;
-
-		if (!UINodes.show || sys_width() == 0 || sys_height() == 0) return;
-
-		UINodes.ui.input_enabled = base_ui_enabled;
-
-		g2_end();
-
-		if (UINodes.grid == null) UINodes.draw_grid();
-
-		///if (is_paint || is_sculpt)
-		if (config_raw.node_preview && context_raw.node_preview_dirty) {
-			UINodes.make_node_preview();
-		}
-		///end
-
-		// Start with UI
-		zui_begin(UINodes.ui);
-
-		// Make window
-		UINodes.ww = config_raw.layout[layout_size_t.NODES_W];
-
-		///if (is_paint || is_sculpt)
-		UINodes.wx = Math.floor(app_w()) + UIToolbar.toolbar_w;
-		///end
-		///if is_lab
-		UINodes.wx = Math.floor(app_w());
-		///end
-
-		UINodes.wy = 0;
-
-		///if (is_paint || is_sculpt)
-		if (!UIBase.show) {
-			UINodes.ww += config_raw.layout[layout_size_t.SIDEBAR_W] + UIToolbar.toolbar_w;
-			UINodes.wx -= UIToolbar.toolbar_w;
-		}
-		///end
-
-		let ew: i32 = Math.floor(zui_ELEMENT_W(UINodes.ui) * 0.7);
-		UINodes.wh = app_h() + UIHeader.headerh;
-		if (config_raw.layout[layout_size_t.HEADER] == 1) UINodes.wh += UIHeader.headerh;
-
-		if (UIView2D.show) {
-			UINodes.wh = config_raw.layout[layout_size_t.NODES_H];
-			UINodes.wy = app_h() - config_raw.layout[layout_size_t.NODES_H] + UIHeader.headerh;
-			if (config_raw.layout[layout_size_t.HEADER] == 1) UINodes.wy += UIHeader.headerh;
-			if (!UIBase.show) {
-				UINodes.wy -= UIHeader.headerh * 2;
-			}
-		}
-
-		if (zui_window(UINodes.hwnd, UINodes.wx, UINodes.wy, UINodes.ww, UINodes.wh)) {
-
-			zui_tab(zui_handle("uinodes_10"), tr("Nodes"));
-
-			// Grid
-			g2_set_color(0xffffffff);
-			let step: f32 = 100 * zui_SCALE(UINodes.ui);
-			g2_draw_image(UINodes.grid, (nodes.panX * zui_nodes_SCALE()) % step - step, (nodes.panY * zui_nodes_SCALE()) % step - step);
-
-			// Undo
-			if (UINodes.ui.input_started || UINodes.ui.is_key_pressed) {
-				UINodes.last_canvas = JSON.parse(JSON.stringify(UINodes.get_canvas(true)));
-			}
-
-			// Nodes
-			let _input_enabled: bool = UINodes.ui.input_enabled;
-			UINodes.ui.input_enabled = _input_enabled && !UINodes.show_menu;
-			///if (is_paint || is_sculpt)
-			UINodes.ui.window_border_right = config_raw.layout[layout_size_t.SIDEBAR_W];
-			///end
-			UINodes.ui.window_border_top = UIHeader.headerh * 2;
-			UINodes.ui.window_border_bottom = config_raw.layout[layout_size_t.STATUS_H];
-			zui_node_canvas(nodes, UINodes.ui, c);
-			UINodes.ui.input_enabled = _input_enabled;
-
-			if (nodes.colorPickerCallback != null) {
-				context_raw.color_picker_previous_tool = context_raw.tool;
-				context_select_tool(workspace_tool_t.PICKER);
-				let tmp: (col: i32)=>void = nodes.colorPickerCallback;
-				context_raw.color_picker_callback = (color: swatch_color_t) => {
-					tmp(color.base);
-					UINodes.hwnd.redraws = 2;
-
-					///if (is_paint || is_sculpt)
-					let material_live: bool = config_raw.material_live;
-					///end
-					///if is_lab
-					let material_live: bool = true;
-					///end
-
-					if (material_live) {
-						UINodes.canvas_changed();
-					}
-				};
-				nodes.colorPickerCallback = null;
-			}
-
-			// Remove nodes with unknown id for this canvas type
-			if (zui_is_paste) {
-				///if (is_paint || is_sculpt)
-				let node_list: zui_node_t[][] = UINodes.canvas_type == canvas_type_t.MATERIAL ? NodesMaterial.list : NodesBrush.list;
-				///end
-				///if is_lab
-				let node_list: zui_node_t[][] = NodesBrush.list;
-				///end
-
-				let i: i32 = 0;
-				while (i++ < c.nodes.length) {
-					let canvas_node: zui_node_t = c.nodes[i - 1];
-					if (zui_exclude_remove.indexOf(canvas_node.type) >= 0) {
-						continue;
-					}
-					let found: bool = false;
-					for (let list of node_list) {
-						for (let list_node of list) {
-							if (canvas_node.type == list_node.type) {
-								found = true;
-								break;
-							}
-						}
-						if (found) break;
-					}
-					if (canvas_node.type == "GROUP" && !UINodes.can_place_group(canvas_node.name)) {
-						found = false;
-					}
-					if (!found) {
-						zui_remove_node(canvas_node, c);
-						array_remove(nodes.nodes_selected_id, canvas_node.id);
-						i--;
-					}
-				}
-			}
-
-			if (UINodes.is_node_menu_op) {
-				zui_set_is_copy(false);
-				zui_set_is_cut(false);
-				zui_set_is_paste(false);
-				UINodes.ui.is_delete_down = false;
-			}
-
-			// Recompile material on change
-			if (UINodes.ui.changed) {
-				///if (is_paint || is_sculpt)
-				UINodes.recompile_mat = (UINodes.ui.input_dx != 0 || UINodes.ui.input_dy != 0 || !UINodes.uichanged_last) && config_raw.material_live; // Instant preview
-				///end
-				///if is_lab
-				UINodes.recompile_mat = (UINodes.ui.input_dx != 0 || UINodes.ui.input_dy != 0 || !UINodes.uichanged_last); // Instant preview
-				///end
-			}
-			else if (UINodes.uichanged_last) {
-				UINodes.canvas_changed();
-				UINodes.push_undo(UINodes.last_canvas);
-			}
-			UINodes.uichanged_last = UINodes.ui.changed;
-
-			// Node previews
-			if (config_raw.node_preview && nodes.nodes_selected_id.length > 0) {
-				let img: image_t = null;
-				let sel: zui_node_t = zui_get_node(c.nodes, nodes.nodes_selected_id[0]);
-
-				///if (is_paint || is_sculpt)
-
-				let single_channel: bool = sel.type == "LAYER_MASK";
-				if (sel.type == "LAYER" || sel.type == "LAYER_MASK") {
-					let id: any = sel.buttons[0].default_value;
-					if (id < project_layers.length) {
-						///if is_paint
-						img = project_layers[id].texpaint_preview;
-						///end
-					}
-				}
-				else if (sel.type == "MATERIAL") {
-					let id: any = sel.buttons[0].default_value;
-					if (id < project_materials.length) {
-						img = project_materials[id].image;
-					}
-				}
-				else if (sel.type == "OUTPUT_MATERIAL_PBR") {
-					img = context_raw.material.image;
-				}
-				else if (sel.type == "BrushOutputNode") {
-					img = context_raw.brush.image;
-				}
-				else if (UINodes.canvas_type == canvas_type_t.MATERIAL) {
-					img = context_raw.node_preview;
-				}
-
-				///else
-
-				let brush_node: LogicNode = ParserLogic.get_logic_node(sel);
-				if (brush_node != null) {
-					img = brush_node.get_cached_image();
-				}
-
-				///end
-
-				if (img != null) {
-					let tw: f32 = 128 * zui_SCALE(UINodes.ui);
-					let th: f32 = tw * (img.height / img.width);
-					let tx: f32 = UINodes.ww - tw - 8 * zui_SCALE(UINodes.ui);
-					let ty: f32 = UINodes.wh - th - 8 * zui_SCALE(UINodes.ui);
-
-					///if krom_opengl
-					let invert_y: bool = sel.type == "MATERIAL";
-					///else
-					let invert_y: bool = false;
-					///end
-
-					///if (is_paint || is_sculpt)
-					if (single_channel) {
-						g2_set_pipeline(UIView2D.pipe);
-						///if krom_opengl
-						krom_g4_set_pipeline(UIView2D.pipe.pipeline_);
-						///end
-						krom_g4_set_int(UIView2D.channel_location, 1);
-					}
-					///end
-
-					g2_set_color(0xffffffff);
-					invert_y ?
-						g2_draw_scaled_image(img, tx, ty + th, tw, -th) :
-						g2_draw_scaled_image(img, tx, ty, tw, th);
-
-					///if (is_paint || is_sculpt)
-					if (single_channel) {
-						g2_set_pipeline(null);
-					}
-					///end
-				}
-			}
-
-			// Menu
-			g2_set_color(UINodes.ui.t.SEPARATOR_COL);
-			g2_fill_rect(0, zui_ELEMENT_H(UINodes.ui), UINodes.ww, zui_ELEMENT_H(UINodes.ui) + zui_ELEMENT_OFFSET(UINodes.ui) * 2);
-			g2_set_color(0xffffffff);
-
-			let start_y: i32 = zui_ELEMENT_H(UINodes.ui) + zui_ELEMENT_OFFSET(UINodes.ui);
-			UINodes.ui._x = 0;
-			UINodes.ui._y = 2 + start_y;
-			UINodes.ui._w = ew;
-
-			///if (is_paint || is_sculpt)
-			// Editable canvas name
-			let h: zui_handle_t = zui_handle("uinodes_11");
-			h.text = c.name;
-			UINodes.ui._w = Math.floor(Math.min(g2_font_width(UINodes.ui.font, UINodes.ui.font_size, h.text) + 15 * zui_SCALE(UINodes.ui), 100 * zui_SCALE(UINodes.ui)));
-			let new_name: string = zui_text_input(h, "");
-			UINodes.ui._x += UINodes.ui._w + 3;
-			UINodes.ui._y = 2 + start_y;
-			UINodes.ui._w = ew;
-
-			if (h.changed) { // Check whether renaming is possible and update group links
-				if (UINodes.group_stack.length > 0) {
-					let can_rename: bool = true;
-					for (let m of project_material_groups) {
-						if (m.canvas.name == new_name) can_rename = false; // Name already used
-					}
-
-					if (can_rename) {
-						let old_name: string = c.name;
-						c.name = new_name;
-						let canvases: zui_node_canvas_t[] = [];
-						for (let m of project_materials) canvases.push(m.canvas);
-						for (let m of project_material_groups) canvases.push(m.canvas);
-						for (let canvas of canvases) {
-							for (let n of canvas.nodes) {
-								if (n.type == "GROUP" && n.name == old_name) {
-									n.name = c.name;
-								}
-							}
-						}
-					}
-				}
-				else {
-					c.name = new_name;
-				}
-			}
-			///end
-
-			///if is_lab
-			UINodes.ui.window_border_top = 0;
-			UINodesExt.drawButtons(ew, start_y);
-			///end
-
-			let _BUTTON_COL: i32 = UINodes.ui.t.BUTTON_COL;
-			UINodes.ui.t.BUTTON_COL = UINodes.ui.t.SEPARATOR_COL;
-
-			///if (is_paint || is_sculpt)
-			let cats: string[] = UINodes.canvas_type == canvas_type_t.MATERIAL ? NodesMaterial.categories : NodesBrush.categories;
-			///end
-			///if is_lab
-			let cats: string[] = NodesBrush.categories;
-			///end
-
-			for (let i: i32 = 0; i < cats.length; ++i) {
-				if ((zui_menu_button(tr(cats[i]))) || (UINodes.ui.is_hovered && UINodes.show_menu)) {
-					UINodes.show_menu = true;
-					UINodes.menu_category = i;
-					UINodes.popup_x = UINodes.wx + UINodes.ui._x;
-					UINodes.popup_y = UINodes.wy + UINodes.ui._y;
-					if (config_raw.touch_ui) {
-						UINodes.show_menu_first = true;
-						let menuw: i32 = Math.floor(ew * 2.3);
-						UINodes.popup_x -= menuw / 2;
-						UINodes.popup_x += UINodes.ui._w / 2;
-					}
-					UIMenu.menu_category_w = UINodes.ui._w;
-					UIMenu.menu_category_h = Math.floor(zui_MENUBAR_H(UINodes.ui));
-				}
-				UINodes.ui._x += UINodes.ui._w + 3;
-				UINodes.ui._y = 2 + start_y;
-			}
-
-			if (config_raw.touch_ui) {
-				let _w: i32 = UINodes.ui._w;
-				UINodes.ui._w = Math.floor(36 * zui_SCALE(UINodes.ui));
-				UINodes.ui._y = 4 * zui_SCALE(UINodes.ui) + start_y;
-				if (UIMenubar.icon_button(UINodes.ui, 2, 3)) {
-					UINodes.node_search(Math.floor(UINodes.ui._window_x + UINodes.ui._x), Math.floor(UINodes.ui._window_y + UINodes.ui._y));
-				}
-				UINodes.ui._w = _w;
-			}
-			else {
-				if (zui_menu_button(tr("Search"))) {
-					UINodes.node_search(Math.floor(UINodes.ui._window_x + UINodes.ui._x), Math.floor(UINodes.ui._window_y + UINodes.ui._y));
-				}
-			}
-			if (UINodes.ui.is_hovered) {
-				zui_tooltip(tr("Search for nodes") + ` (${config_keymap.node_search})`);
-			}
-			UINodes.ui._x += UINodes.ui._w + 3;
-			UINodes.ui._y = 2 + start_y;
-
-			UINodes.ui.t.BUTTON_COL = _BUTTON_COL;
-
-			// Close node group
-			if (UINodes.group_stack.length > 0 && zui_menu_button(tr("Close"))) {
-				UINodes.group_stack.pop();
-			}
-		}
-
-		zui_end(!UINodes.show_menu);
-
-		g2_begin(null);
-
-		if (UINodes.show_menu) {
-			///if (is_paint || is_sculpt)
-			let list:zui_node_t[][] = UINodes.canvas_type == canvas_type_t.MATERIAL ? NodesMaterial.list : NodesBrush.list;
-			///end
-			///if is_lab
-			let list:zui_node_t[][] = NodesBrush.list;
-			///end
-
-			let num_nodes: i32 = list[UINodes.menu_category].length;
-
-			///if (is_paint || is_sculpt)
-			let is_group_category: bool = UINodes.canvas_type == canvas_type_t.MATERIAL && NodesMaterial.categories[UINodes.menu_category] == "Group";
-			///end
-			///if is_lab
-			let is_group_category: bool = NodesMaterial.categories[UINodes.menu_category] == "Group";
-			///end
-
-			if (is_group_category) num_nodes += project_material_groups.length;
-
-			let py: i32 = UINodes.popup_y;
-			let menuw: i32 = Math.floor(ew * 2.3);
-			zui_begin_region(UINodes.ui, Math.floor(UINodes.popup_x), Math.floor(py), menuw);
-			let _BUTTON_COL: i32 = UINodes.ui.t.BUTTON_COL;
-			UINodes.ui.t.BUTTON_COL = UINodes.ui.t.SEPARATOR_COL;
-			let _ELEMENT_OFFSET: i32 = UINodes.ui.t.ELEMENT_OFFSET;
-			UINodes.ui.t.ELEMENT_OFFSET = 0;
-			let _ELEMENT_H: i32 = UINodes.ui.t.ELEMENT_H;
-			UINodes.ui.t.ELEMENT_H = config_raw.touch_ui ? (28 + 2) : 28;
-
-			UIMenu.menu_start(UINodes.ui);
-
-			for (let n of list[UINodes.menu_category]) {
-				if (UIMenu.menu_button(UINodes.ui, tr(n.name))) {
-					UINodes.push_undo();
-					let canvas: zui_node_canvas_t = UINodes.get_canvas(true);
-					let nodes: zui_nodes_t = UINodes.get_nodes();
-					let node: zui_node_t = UINodes.make_node(n, nodes, canvas);
-					canvas.nodes.push(node);
-					nodes.nodes_selected_id = [node.id];
-					nodes.nodesDrag = true;
-					///if is_lab
-					ParserLogic.parse(canvas);
-					///end
-				}
-				// Next column
-				if (UINodes.ui._y - UINodes.wy + zui_ELEMENT_H(UINodes.ui) / 2 > UINodes.wh) {
-					UINodes.ui._x += menuw;
-					UINodes.ui._y = py;
-				}
-			}
-			if (is_group_category) {
-				for (let g of project_material_groups) {
-					zui_fill(0, 1, UINodes.ui._w / zui_SCALE(UINodes.ui), UINodes.ui.t.BUTTON_H + 2, UINodes.ui.t.ACCENT_SELECT_COL);
-					zui_fill(1, 1, UINodes.ui._w / zui_SCALE(UINodes.ui) - 2, UINodes.ui.t.BUTTON_H + 1, UINodes.ui.t.SEPARATOR_COL);
-					UINodes.ui.enabled = UINodes.can_place_group(g.canvas.name);
-					UIMenu.menu_fill(UINodes.ui);
-					zui_row([5 / 6, 1 / 6]);
-					if (zui_button(config_button_spacing + g.canvas.name, zui_align_t.LEFT)) {
-						UINodes.push_undo();
-						let canvas: zui_node_canvas_t = UINodes.get_canvas(true);
-						let nodes: zui_nodes_t = UINodes.get_nodes();
-						let node: zui_node_t = UINodes.make_group_node(g.canvas, nodes, canvas);
-						canvas.nodes.push(node);
-						nodes.nodes_selected_id = [node.id];
-						nodes.nodesDrag = true;
-					}
-
-					///if (is_paint || is_sculpt)
-					UINodes.ui.enabled = !project_is_material_group_in_use(g);
-					if (zui_button("x", zui_align_t.CENTER)) {
-						history_delete_material_group(g);
-						array_remove(project_material_groups, g);
-					}
-					///end
-
-					UINodes.ui.enabled = true;
-				}
-			}
-
-			UINodes.hide_menu = UINodes.ui.combo_selected_handle_ptr == 0 && !UINodes.show_menu_first && (UINodes.ui.changed || UINodes.ui.input_released || UINodes.ui.input_released_r || UINodes.ui.is_escape_down);
-			UINodes.show_menu_first = false;
-
-			UINodes.ui.t.BUTTON_COL = _BUTTON_COL;
-			UINodes.ui.t.ELEMENT_OFFSET = _ELEMENT_OFFSET;
-			UINodes.ui.t.ELEMENT_H = _ELEMENT_H;
-			zui_end_region();
-		}
-
-		if (UINodes.hide_menu) {
-			UINodes.show_menu = false;
-			UINodes.show_menu_first = true;
-		}
-	}
-
-	static contains_node_group_recursive = (group: node_group_t, groupName: string): bool => {
-		if (group.canvas.name == groupName) {
-			return true;
-		}
-		for (let n of group.canvas.nodes) {
-			if (n.type == "GROUP") {
-				let g: node_group_t = project_get_material_group_by_name(n.name);
-				if (g != null && UINodes.contains_node_group_recursive(g, groupName)) {
-					return true;
-				}
-			}
-		}
-		return false;
-	}
-
-	static can_place_group = (groupName: string): bool => {
-		// Prevent Recursive node groups
-		// The group to place must not contain the current group or a group that contains the current group
-		if (UINodes.group_stack.length > 0) {
-			for (let g of UINodes.group_stack) {
-				if (UINodes.contains_node_group_recursive(project_get_material_group_by_name(groupName), g.canvas.name)) return false;
-			}
-		}
-		// Group was deleted / renamed
-		let group_exists: bool = false;
-		for (let group of project_material_groups) {
-			if (groupName == group.canvas.name) {
-				group_exists = true;
-			}
-		}
-		if (!group_exists) return false;
-		return true;
-	}
-
-	static push_undo = (last_canvas: zui_node_canvas_t = null) => {
-		if (last_canvas == null) last_canvas = UINodes.get_canvas(true);
-		let canvas_group: i32 = UINodes.group_stack.length > 0 ? project_material_groups.indexOf(UINodes.group_stack[UINodes.group_stack.length - 1]) : null;
-
-		///if (is_paint || is_sculpt)
-		UIBase.hwnds[tab_area_t.SIDEBAR0].redraws = 2;
-		history_edit_nodes(last_canvas, UINodes.canvas_type, canvas_group);
-		///end
-		///if is_lab
-		history_edit_nodes(last_canvas, canvas_group);
-		///end
-	}
-
-	static accept_asset_drag = (index: i32) => {
-		UINodes.push_undo();
-		let g: node_group_t = UINodes.group_stack.length > 0 ? UINodes.group_stack[UINodes.group_stack.length - 1] : null;
-		///if (is_paint || is_sculpt)
-		let n: zui_node_t = UINodes.canvas_type == canvas_type_t.MATERIAL ? NodesMaterial.create_node("TEX_IMAGE", g) : NodesBrush.create_node("TEX_IMAGE");
-		///end
-		///if is_lab
-		let n: zui_node_t = NodesBrush.create_node("ImageTextureNode");
-		///end
-
-		n.buttons[0].default_value = index;
-		UINodes.get_nodes().nodes_selected_id = [n.id];
-
-		///if is_lab
-		ParserLogic.parse(project_canvas);
-		///end
-	}
-
-	///if (is_paint || is_sculpt)
-	static accept_layer_drag = (index: i32) => {
-		UINodes.push_undo();
-		if (SlotLayer.is_group(project_layers[index])) return;
-		let g: node_group_t = UINodes.group_stack.length > 0 ? UINodes.group_stack[UINodes.group_stack.length - 1] : null;
-		let n: zui_node_t = NodesMaterial.create_node(SlotLayer.is_mask(context_raw.layer) ? "LAYER_MASK" : "LAYER", g);
-		n.buttons[0].default_value = index;
-		UINodes.get_nodes().nodes_selected_id = [n.id];
-	}
-
-	static accept_material_drag = (index: i32) => {
-		UINodes.push_undo();
-		let g: node_group_t = UINodes.group_stack.length > 0 ? UINodes.group_stack[UINodes.group_stack.length - 1] : null;
-		let n: zui_node_t = NodesMaterial.create_node("MATERIAL", g);
-		n.buttons[0].default_value = index;
-		UINodes.get_nodes().nodes_selected_id = [n.id];
-	}
-	///end
-
-	static accept_swatch_drag = (swatch: swatch_color_t) => {
-		///if (is_paint || is_sculpt)
-		UINodes.push_undo();
-		let g: node_group_t = UINodes.group_stack.length > 0 ? UINodes.group_stack[UINodes.group_stack.length - 1] : null;
-		let n: zui_node_t = NodesMaterial.create_node("RGB", g);
-		n.outputs[0].default_value = [
-			color_get_rb(swatch.base) / 255,
-			color_get_gb(swatch.base) / 255,
-			color_get_bb(swatch.base) / 255,
-			color_get_ab(swatch.base) / 255
-		];
-		UINodes.get_nodes().nodes_selected_id = [n.id];
-		///end
-	}
-
-	static 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));
-		node.id = zui_get_node_id(canvas.nodes);
-		node.x = UINodes.get_node_x();
-		node.y = UINodes.get_node_y();
-		let count: i32 = 0;
-		for (let soc of node.inputs) {
-			soc.id = zui_get_socket_id(canvas.nodes) + count;
-			soc.node_id = node.id;
-			count++;
-		}
-		for (let soc of node.outputs) {
-			soc.id = zui_get_socket_id(canvas.nodes) + count;
-			soc.node_id = node.id;
-			count++;
-		}
-		return node;
-	}
-
-	static make_group_node = (groupCanvas: zui_node_canvas_t, nodes: zui_nodes_t, canvas: zui_node_canvas_t): zui_node_t => {
-		let n: zui_node_t = NodesMaterial.list[5][0];
-		let node: zui_node_t = JSON.parse(JSON.stringify(n));
-		node.name = groupCanvas.name;
-		node.id = zui_get_node_id(canvas.nodes);
-		node.x = UINodes.get_node_x();
-		node.y = UINodes.get_node_y();
-		let group_input: zui_node_t = null;
-		let group_output: zui_node_t = null;
-		for (let g of project_material_groups) {
-			if (g.canvas.name == node.name) {
-				for (let n of g.canvas.nodes) {
-					if (n.type == "GROUP_INPUT") group_input = n;
-					else if (n.type == "GROUP_OUTPUT") group_output = n;
-				}
-				break;
-			}
-		}
-		if (group_input != null && group_output != null) {
-			for (let soc of group_input.outputs) {
-				node.inputs.push(NodesMaterial.create_socket(nodes, node, soc.name, soc.type, canvas, soc.min, soc.max, soc.default_value));
-			}
-			for (let soc of group_output.inputs) {
-				node.outputs.push(NodesMaterial.create_socket(nodes, node, soc.name, soc.type, canvas, soc.min, soc.max, soc.default_value));
-			}
-		}
-		return node;
-	}
-
-	///if (is_paint || is_sculpt)
-	static make_node_preview = () => {
-		let nodes: zui_nodes_t = context_raw.material.nodes;
-		if (nodes.nodes_selected_id.length == 0) return;
-
-		let node: zui_node_t = zui_get_node(context_raw.material.canvas.nodes, nodes.nodes_selected_id[0]);
-		// if (node == null) return;
-		context_raw.node_preview_name = node.name;
-
-		if (node.type == "LAYER" ||
-			node.type == "LAYER_MASK" ||
-			node.type == "MATERIAL" ||
-			node.type == "OUTPUT_MATERIAL_PBR") return;
-
-		if (context_raw.material.canvas.nodes.indexOf(node) == -1) return;
-
-		if (context_raw.node_preview == null) {
-			context_raw.node_preview = image_create_render_target(UtilRender.material_preview_size, UtilRender.material_preview_size);
-		}
-
-		context_raw.node_preview_dirty = false;
-		UINodes.hwnd.redraws = 2;
-		UtilRender.make_node_preview(context_raw.material.canvas, node, context_raw.node_preview);
-	}
-	///end
-
-	static has_group = (c: zui_node_canvas_t): bool => {
-		for (let n of c.nodes) if (n.type == "GROUP") return true;
-		return false;
-	}
-
-	static traverse_group = (mgroups: zui_node_canvas_t[], c: zui_node_canvas_t) => {
-		for (let n of c.nodes) {
-			if (n.type == "GROUP") {
-				if (UINodes.get_group(mgroups, n.name) == null) {
-					let canvases: zui_node_canvas_t[] = [];
-					for (let g of project_material_groups) canvases.push(g.canvas);
-					let group: zui_node_canvas_t = UINodes.get_group(canvases, n.name);
-					mgroups.push(JSON.parse(JSON.stringify(group)));
-					UINodes.traverse_group(mgroups, group);
-				}
-			}
-		}
-	}
-
-	static get_group = (canvases: zui_node_canvas_t[], name: string): zui_node_canvas_t => {
-		for (let c of canvases) if (c.name == name) return c;
-		return null;
-	}
-}

+ 0 - 51
base/Sources/UIStatus.ts

@@ -1,51 +0,0 @@
-
-class UIStatus {
-
-	static default_status_h: i32 = 33;
-
-	constructor() {
-	}
-
-	static get width(): i32 {
-		///if (is_paint || is_sculpt)
-		return sys_width() - UIToolbar.toolbar_w - config_raw.layout[layout_size_t.SIDEBAR_W];
-		///end
-		///if is_lab
-		return sys_width();
-		///end
-	}
-
-	static render_ui = () => {
-		let ui: zui_t = UIBase.ui;
-
-		let statush: i32 = config_raw.layout[layout_size_t.STATUS_H];
-
-		if (zui_window(UIBase.hwnds[tab_area_t.STATUS], app_x(), sys_height() - statush, UIStatus.width, statush)) {
-			ui._y += 2;
-
-			// Border
-			g2_set_color(ui.t.SEPARATOR_COL);
-			g2_fill_rect(0, 0, 1, ui._window_h);
-			g2_fill_rect(ui._window_w - 1, 0, 1, ui._window_h);
-
-			// Draw tabs
-			for (let draw of UIBase.hwnd_tabs[tab_area_t.STATUS]) draw(UIBase.htabs[tab_area_t.STATUS]);
-
-			let minimized: bool = statush <= UIStatus.default_status_h * config_raw.window_scale;
-			if (UIBase.htabs[tab_area_t.STATUS].changed && (UIBase.htabs[tab_area_t.STATUS].position == context_raw.last_status_position || minimized)) {
-				UIBase.toggle_browser();
-			}
-			context_raw.last_status_position = UIBase.htabs[tab_area_t.STATUS].position;
-		}
-	}
-
-	static draw_version_tab = (htab: zui_handle_t) => {
-		// Version label
-		if (!config_raw.touch_ui) {
-			let ui: zui_t = UIBase.ui;
-			ui.enabled = false;
-			zui_tab(UIBase.htabs[tab_area_t.STATUS], manifest_version);
-			ui.enabled = true;
-		}
-	}
-}

+ 0 - 207
base/Sources/UIToolbar.ts

@@ -1,207 +0,0 @@
-
-///if (is_paint || is_sculpt)
-
-class UIToolbar {
-
-	static default_toolbar_w: i32 = 36;
-
-	static toolbar_handle: zui_handle_t = zui_handle_create();
-	static toolbar_w: i32 = UIToolbar.default_toolbar_w;
-	static last_tool: i32 = 0;
-
-	static tool_names: string[] = [
-		_tr("Brush"),
-		_tr("Eraser"),
-		_tr("Fill"),
-		_tr("Decal"),
-		_tr("Text"),
-		_tr("Clone"),
-		_tr("Blur"),
-		_tr("Smudge"),
-		_tr("Particle"),
-		_tr("ColorID"),
-		_tr("Picker"),
-		_tr("Bake"),
-		_tr("Gizmo"),
-		_tr("Material"),
-	];
-
-	constructor() {
-	}
-
-	static render_ui = () => {
-		let ui: zui_t = UIBase.ui;
-
-		if (config_raw.touch_ui) {
-			UIToolbar.toolbar_w = UIToolbar.default_toolbar_w + 6;
-		}
-		else {
-			UIToolbar.toolbar_w = UIToolbar.default_toolbar_w;
-		}
-		UIToolbar.toolbar_w = Math.floor(UIToolbar.toolbar_w * zui_SCALE(ui));
-
-		if (zui_window(UIToolbar.toolbar_handle, 0, UIHeader.headerh, UIToolbar.toolbar_w, sys_height() - UIHeader.headerh)) {
-			ui._y -= 4 * zui_SCALE(ui);
-
-			ui.image_scroll_align = false;
-			let img: image_t = resource_get("icons.k");
-
-			let col: i32 = ui.t.WINDOW_BG_COL;
-			if (col < 0) col += 4294967296;
-			let light: bool = col > (0xff666666 + 4294967296);
-			let icon_accent: i32 = light ? 0xff666666 : -1;
-
-			// Properties icon
-			if (config_raw.layout[layout_size_t.HEADER] == 1) {
-				let rect: rect_t = resource_tile50(img, 7, 1);
-				if (zui_image(img, light ? 0xff666666 : ui.t.BUTTON_COL, -1.0, rect.x, rect.y, rect.w, rect.h) == zui_state_t.RELEASED) {
-					config_raw.layout[layout_size_t.HEADER] = 0;
-				}
-			}
-			// Draw ">>" button if header is hidden
-			else {
-				let _ELEMENT_H: i32 = ui.t.ELEMENT_H;
-				let _BUTTON_H: i32 = ui.t.BUTTON_H;
-				let _BUTTON_COL: i32 = ui.t.BUTTON_COL;
-				let _fontOffsetY: i32 = ui.font_offset_y;
-				ui.t.ELEMENT_H = Math.floor(ui.t.ELEMENT_H * 1.5);
-				ui.t.BUTTON_H = ui.t.ELEMENT_H;
-				ui.t.BUTTON_COL = ui.t.WINDOW_BG_COL;
-				let font_height: i32 = g2_font_height(ui.font, ui.font_size);
-				ui.font_offset_y = (zui_ELEMENT_H(ui) - font_height) / 2;
-				let _w: i32 = ui._w;
-				ui._w = UIToolbar.toolbar_w;
-
-				if (zui_button(">>")) {
-					UIToolbar.tool_properties_menu();
-				}
-
-				ui._w = _w;
-				ui.t.ELEMENT_H = _ELEMENT_H;
-				ui.t.BUTTON_H = _BUTTON_H;
-				ui.t.BUTTON_COL = _BUTTON_COL;
-				ui.font_offset_y = _fontOffsetY;
-			}
-			if (ui.is_hovered) zui_tooltip(tr("Toggle header"));
-			ui._y -= 4 * zui_SCALE(ui);
-
-			let keys: string[] = [
-				"(" + config_keymap.tool_brush + ") - " + tr("Hold {action_paint} to paint\nHold {key} and press {action_paint} to paint a straight line (ruler mode)", new Map([["key", config_keymap.brush_ruler], ["action_paint", config_keymap.action_paint]])),
-				"(" + config_keymap.tool_eraser + ") - " + tr("Hold {action_paint} to erase\nHold {key} and press {action_paint} to erase a straight line (ruler mode)", new Map([["key", config_keymap.brush_ruler], ["action_paint", config_keymap.action_paint]])),
-				"(" + config_keymap.tool_fill + ")",
-				"(" + config_keymap.tool_decal + ") - " + tr("Hold {key} to paint on a decal mask", new Map([["key", config_keymap.decal_mask]])),
-				"(" + config_keymap.tool_text + ") - " + tr("Hold {key} to use the text as a mask", new Map([["key", config_keymap.decal_mask]])),
-				"(" + config_keymap.tool_clone + ") - " + tr("Hold {key} to set source", new Map([["key", config_keymap.set_clone_source]])),
-				"(" + config_keymap.tool_blur + ")",
-				"(" + config_keymap.tool_smudge + ")",
-				"(" + config_keymap.tool_particle + ")",
-				"(" + config_keymap.tool_colorid + ")",
-				"(" + config_keymap.tool_picker + ")",
-				"(" + config_keymap.tool_bake + ")",
-				"(" + config_keymap.tool_gizmo + ")",
-				"(" + config_keymap.tool_material + ")",
-			];
-
-			let draw_tool = (i: i32) => {
-				ui._x += 2;
-				if (context_raw.tool == i) UIToolbar.draw_highlight();
-				let tile_y: i32 = Math.floor(i / 12);
-				let tile_x: i32 = tile_y % 2 == 0 ? i % 12 : (11 - (i % 12));
-				let rect: rect_t = resource_tile50(img, tile_x, tile_y);
-				let _y: i32 = ui._y;
-
-				let image_state: zui_state_t = zui_image(img, icon_accent, -1.0, rect.x, rect.y, rect.w, rect.h);
-				if (image_state == zui_state_t.STARTED) {
-					context_select_tool(i);
-				}
-				else if (image_state == zui_state_t.RELEASED && config_raw.layout[layout_size_t.HEADER] == 0) {
-					if (UIToolbar.last_tool == i) {
-						UIToolbar.tool_properties_menu();
-					}
-					UIToolbar.last_tool = i;
-				}
-
-				///if is_paint
-				if (i == workspace_tool_t.COLORID && context_raw.colorid_picked) {
-					g2_draw_scaled_sub_image(render_path_render_targets.get("texpaint_colorid")._image, 0, 0, 1, 1, 0, _y + 1.5 * zui_SCALE(ui), 5 * zui_SCALE(ui), 34 * zui_SCALE(ui));
-				}
-				///end
-
-				if (ui.is_hovered) zui_tooltip(tr(UIToolbar.tool_names[i]) + " " + keys[i]);
-				ui._x -= 2;
-				ui._y += 2;
-			}
-
-			draw_tool(workspace_tool_t.BRUSH);
-			///if is_paint
-			draw_tool(workspace_tool_t.ERASER);
-			draw_tool(workspace_tool_t.FILL);
-			draw_tool(workspace_tool_t.DECAL);
-			draw_tool(workspace_tool_t.TEXT);
-			draw_tool(workspace_tool_t.CLONE);
-			draw_tool(workspace_tool_t.BLUR);
-			draw_tool(workspace_tool_t.SMUDGE);
-			draw_tool(workspace_tool_t.PARTICLE);
-			draw_tool(workspace_tool_t.COLORID);
-			draw_tool(workspace_tool_t.PICKER);
-			draw_tool(workspace_tool_t.BAKE);
-			draw_tool(workspace_tool_t.MATERIAL);
-			///end
-
-			///if is_forge
-			draw_tool(workspace_tool_t.GIZMO);
-			///end
-
-			ui.image_scroll_align = true;
-		}
-
-		if (config_raw.touch_ui) {
-			// Hide scrollbar
-			let _SCROLL_W: i32 = ui.t.SCROLL_W;
-			ui.t.SCROLL_W = 0;
-			zui_end_window();
-			ui.t.SCROLL_W = _SCROLL_W;
-		}
-	}
-
-	static tool_properties_menu = () => {
-		let ui: zui_t = UIBase.ui;
-		let _x: i32 = ui._x;
-		let _y: i32 = ui._y;
-		let _w: i32 = ui._w;
-		UIMenu.draw((ui: zui_t) => {
-			let start_y: i32 = ui._y;
-			ui.changed = false;
-
-			UIHeader.draw_tool_properties(ui);
-
-			if (ui.changed) {
-				UIMenu.keep_open = true;
-			}
-
-			if (zui_button(tr("Pin to Header"), zui_align_t.LEFT)) {
-				config_raw.layout[layout_size_t.HEADER] = 1;
-			}
-
-			let h: i32 = ui._y - start_y;
-			UIMenu.menu_elements = Math.floor(h / zui_ELEMENT_H(ui));
-			UIMenu.menu_x = Math.floor(_x + _w + 2);
-			UIMenu.menu_y = Math.floor(_y - 6 * zui_SCALE(ui));
-			UIMenu.fit_to_screen();
-
-		}, 0);
-
-		// First draw out of screen, then align the menu based on menu height
-		UIMenu.menu_x = -sys_width();
-		UIMenu.menu_y = -sys_height();
-	}
-
-	static draw_highlight = () => {
-		let ui: zui_t = UIBase.ui;
-		let size: i32 = UIToolbar.toolbar_w - 4;
-		g2_set_color(ui.t.HIGHLIGHT_COL);
-		zui_draw_rect(true, ui._x + -1,  ui._y + 2, size + 2, size + 2);
-	}
-}
-
-///end

+ 0 - 459
base/Sources/UIView2D.ts

@@ -1,459 +0,0 @@
-
-class UIView2D {
-
-	///if (is_paint || is_sculpt)
-	static pipe: pipeline_t;
-	static channel_location: kinc_const_loc_t;
-	static text_input_hover: bool = false;
-	static uvmap_show: bool = false;
-	static tex_type: paint_tex_t = paint_tex_t.BASE;
-	static layer_mode: view_2d_layer_mode_t = view_2d_layer_mode_t.SELECTED;
-	///end
-
-	///if (is_paint || is_sculpt)
-	static type: view_2d_type_t = view_2d_type_t.LAYER;
-	///else
-	static type: view_2d_type_t = view_2d_type_t.ASSET;
-	///end
-
-	static show: bool = false;
-	static wx: i32;
-	static wy: i32;
-	static ww: i32;
-	static wh: i32;
-	static ui: zui_t;
-	static hwnd: zui_handle_t = zui_handle_create();
-	static pan_x: f32 = 0.0;
-	static pan_y: f32 = 0.0;
-	static pan_scale: f32 = 1.0;
-	static tiled_show: bool = false;
-	static controls_down: bool = false;
-
-	constructor() {
-		///if (is_paint || is_sculpt)
-		UIView2D.pipe = g4_pipeline_create();
-		UIView2D.pipe.vertex_shader = sys_get_shader("layer_view.vert");
-		UIView2D.pipe.fragment_shader = sys_get_shader("layer_view.frag");
-		let vs: vertex_struct_t = g4_vertex_struct_create();
-		g4_vertex_struct_add(vs, "pos", vertex_data_t.F32_3X);
-		g4_vertex_struct_add(vs, "tex", vertex_data_t.F32_2X);
-		g4_vertex_struct_add(vs, "col", vertex_data_t.U8_4X_NORM);
-		UIView2D.pipe.input_layout = [vs];
-		UIView2D.pipe.blend_source = blend_factor_t.BLEND_ONE;
-		UIView2D.pipe.blend_dest = blend_factor_t.BLEND_ZERO;
-		UIView2D.pipe.color_write_masks_alpha[0] = false;
-		g4_pipeline_compile(UIView2D.pipe);
-		UIView2D.channel_location = g4_pipeline_get_const_loc(UIView2D.pipe, "channel");
-		///end
-
-		let scale: f32 = config_raw.window_scale;
-		UIView2D.ui = zui_create({ theme: base_theme, font: base_font, color_wheel: base_color_wheel, black_white_gradient: base_color_wheel_gradient, scale_factor: scale });
-		UIView2D.ui.scroll_enabled = false;
-	}
-
-	static render = () => {
-
-		UIView2D.ww = config_raw.layout[layout_size_t.NODES_W];
-
-		///if (is_paint || is_sculpt)
-		UIView2D.wx = Math.floor(app_w()) + UIToolbar.toolbar_w;
-		///else
-		UIView2D.wx = Math.floor(app_w());
-		///end
-
-		UIView2D.wy = 0;
-
-		///if (is_paint || is_sculpt)
-		if (!UIBase.show) {
-			UIView2D.ww += config_raw.layout[layout_size_t.SIDEBAR_W] + UIToolbar.toolbar_w;
-			UIView2D.wx -= UIToolbar.toolbar_w;
-		}
-		///end
-
-		if (!UIView2D.show) return;
-		if (sys_width() == 0 || sys_height() == 0) return;
-
-		if (context_raw.pdirty >= 0) UIView2D.hwnd.redraws = 2; // Paint was active
-
-		g2_end();
-
-		// Cache grid
-		if (UINodes.grid == null) UINodes.draw_grid();
-
-		// Ensure UV map is drawn
-		///if (is_paint || is_sculpt)
-		if (UIView2D.uvmap_show) UtilUV.cache_uv_map();
-		///end
-
-		// Ensure font image is drawn
-		///if (is_paint || is_sculpt)
-		if (context_raw.font.image == null) UtilRender.make_font_preview();
-		///end
-
-		zui_begin(UIView2D.ui);
-
-		let headerh: i32 = config_raw.layout[layout_size_t.HEADER] == 1 ? UIHeader.headerh * 2 : UIHeader.headerh;
-		let apph: i32 = sys_height() - config_raw.layout[layout_size_t.STATUS_H] + headerh;
-		UIView2D.wh = sys_height() - config_raw.layout[layout_size_t.STATUS_H];
-
-		if (UINodes.show) {
-			UIView2D.wh -= config_raw.layout[layout_size_t.NODES_H];
-			if (config_raw.touch_ui) UIView2D.wh += UIHeader.headerh;
-		}
-
-		if (zui_window(UIView2D.hwnd, UIView2D.wx, UIView2D.wy, UIView2D.ww, UIView2D.wh)) {
-
-			zui_tab(zui_handle("uiview2d_0"), tr("2D View"));
-
-			// Grid
-			g2_set_color(0xffffffff);
-			g2_draw_image(UINodes.grid, (UIView2D.pan_x * UIView2D.pan_scale) % 100 - 100, (UIView2D.pan_y * UIView2D.pan_scale) % 100 - 100);
-
-			// Texture
-			let tex: image_t = null;
-
-			///if (is_paint || is_sculpt)
-			let l: SlotLayerRaw = context_raw.layer;
-			let channel: i32 = 0;
-			///end
-
-			let tw: f32 = UIView2D.ww * 0.95 * UIView2D.pan_scale;
-			let tx: f32 = UIView2D.ww / 2 - tw / 2 + UIView2D.pan_x;
-			let ty: f32 = apph / 2 - tw / 2 + UIView2D.pan_y;
-
-			if (UIView2D.type == view_2d_type_t.ASSET) {
-				tex = project_get_image(context_raw.texture);
-			}
-			else if (UIView2D.type == view_2d_type_t.NODE) {
-				///if (is_paint || is_sculpt)
-
-				tex = context_raw.node_preview;
-
-				///else
-
-				let nodes: zui_nodes_t = UINodes.get_nodes();
-				if (nodes.nodes_selected_id.length > 0) {
-					let sel: zui_node_t = zui_get_node(UINodes.get_canvas(true).nodes, nodes.nodes_selected_id[0]);
-					let brush_node: LogicNode = ParserLogic.get_logic_node(sel);
-					if (brush_node != null) {
-						tex = brush_node.get_cached_image();
-					}
-				}
-
-				///end
-			}
-			///if is_paint
-			else if (UIView2D.type == view_2d_type_t.LAYER) {
-				let layer: SlotLayerRaw = l;
-
-				if (config_raw.brush_live && RenderPathPaint.live_layer_drawn > 0) {
-					layer = RenderPathPaint.live_layer;
-				}
-
-				if (UIView2D.layer_mode == view_2d_layer_mode_t.VISIBLE) {
-					let current: image_t = _g2_current;
-					if (current != null) g2_end();
-					layer = base_flatten();
-					if (current != null) g2_begin(current);
-				}
-				else if (SlotLayer.is_group(layer)) {
-					let current: image_t = _g2_current;
-					if (current != null) g2_end();
-					layer = base_flatten(false, SlotLayer.get_children(layer));
-					if (current != null) g2_begin(current);
-				}
-
-				tex =
-					SlotLayer.is_mask(context_raw.layer) ? layer.texpaint :
-					UIView2D.tex_type == paint_tex_t.BASE     ? layer.texpaint :
-					UIView2D.tex_type == paint_tex_t.OPACITY  ? layer.texpaint :
-					UIView2D.tex_type == paint_tex_t.NORMAL   ? layer.texpaint_nor :
-														   layer.texpaint_pack;
-
-				channel =
-					SlotLayer.is_mask(context_raw.layer)  ? 1 :
-					UIView2D.tex_type == paint_tex_t.OCCLUSION ? 1 :
-					UIView2D.tex_type == paint_tex_t.ROUGHNESS ? 2 :
-					UIView2D.tex_type == paint_tex_t.METALLIC  ? 3 :
-					UIView2D.tex_type == paint_tex_t.OPACITY   ? 4 :
-					UIView2D.tex_type == paint_tex_t.HEIGHT    ? 4 :
-					UIView2D.tex_type == paint_tex_t.NORMAL    ? 5 :
-															0;
-			}
-			else if (UIView2D.type == view_2d_type_t.FONT) {
-				tex = context_raw.font.image;
-			}
-			///end
-
-			let th: f32 = tw;
-			if (tex != null) {
-				th = tw * (tex.height / tex.width);
-				ty = apph / 2 - th / 2 + UIView2D.pan_y;
-
-				///if (is_paint || is_sculpt)
-				if (UIView2D.type == view_2d_type_t.LAYER) {
-					///if (!krom_opengl)
-					g2_set_pipeline(UIView2D.pipe);
-					///end
-					if (!context_raw.texture_filter) {
-						g2_set_bilinear_filter(false);
-					}
-					///if krom_opengl
-					krom_g4_set_pipeline(UIView2D.pipe.pipeline_);
-					///end
-					krom_g4_set_int(UIView2D.channel_location, channel);
-				}
-				///end
-
-				g2_draw_scaled_image(tex, tx, ty, tw, th);
-
-				if (UIView2D.tiled_show) {
-					g2_draw_scaled_image(tex, tx - tw, ty, tw, th);
-					g2_draw_scaled_image(tex, tx - tw, ty - th, tw, th);
-					g2_draw_scaled_image(tex, tx - tw, ty + th, tw, th);
-					g2_draw_scaled_image(tex, tx + tw, ty, tw, th);
-					g2_draw_scaled_image(tex, tx + tw, ty - th, tw, th);
-					g2_draw_scaled_image(tex, tx + tw, ty + th, tw, th);
-					g2_draw_scaled_image(tex, tx, ty - th, tw, th);
-					g2_draw_scaled_image(tex, tx, ty + th, tw, th);
-				}
-
-				///if (is_paint || is_sculpt)
-				if (UIView2D.type == view_2d_type_t.LAYER) {
-					g2_set_pipeline(null);
-					if (!context_raw.texture_filter) {
-						g2_set_bilinear_filter(true);
-					}
-				}
-
-				// Texture and node preview color picking
-				if ((context_in_2d_view(view_2d_type_t.ASSET) || context_in_2d_view(view_2d_type_t.NODE)) && context_raw.tool == workspace_tool_t.PICKER && UIView2D.ui.input_down) {
-					let x: f32 = UIView2D.ui.input_x - tx - UIView2D.wx;
-					let y: f32 = UIView2D.ui.input_y - ty - UIView2D.wy;
-					base_notify_on_next_frame(() => {
-						let texpaint_picker: image_t = render_path_render_targets.get("texpaint_picker")._image;
-						g2_begin(texpaint_picker);
-						g2_draw_scaled_image(tex, -x, -y, tw, th);
-						g2_end();
-						let a: DataView = new DataView(image_get_pixels(texpaint_picker));
-						///if (krom_metal || krom_vulkan)
-						let i0: i32 = 2;
-						let i1: i32 = 1;
-						let i2: i32 = 0;
-						///else
-						let i0: i32 = 0;
-						let i1: i32 = 1;
-						let i2: i32 = 2;
-						///end
-
-						context_raw.picked_color.base = color_set_rb(context_raw.picked_color.base, a.getUint8(i0));
-						context_raw.picked_color.base = color_set_gb(context_raw.picked_color.base, a.getUint8(i1));
-						context_raw.picked_color.base = color_set_bb(context_raw.picked_color.base, a.getUint8(i2));
-						UIHeader.header_handle.redraws = 2;
-					});
-				}
-				///end
-			}
-
-			///if (is_paint || is_sculpt)
-			// UV map
-			if (UIView2D.type == view_2d_type_t.LAYER && UIView2D.uvmap_show) {
-				g2_draw_scaled_image(UtilUV.uvmap, tx, ty, tw, th);
-			}
-			///end
-
-			// Menu
-			let ew: i32 = Math.floor(zui_ELEMENT_W(UIView2D.ui));
-			g2_set_color(UIView2D.ui.t.SEPARATOR_COL);
-			g2_fill_rect(0, zui_ELEMENT_H(UIView2D.ui), UIView2D.ww, zui_ELEMENT_H(UIView2D.ui) + zui_ELEMENT_OFFSET(UIView2D.ui) * 2);
-			g2_set_color(0xffffffff);
-
-			let start_y: f32 = zui_ELEMENT_H(UIView2D.ui) + zui_ELEMENT_OFFSET(UIView2D.ui);
-			UIView2D.ui._x = 2;
-			UIView2D.ui._y = 2 + start_y;
-			UIView2D.ui._w = ew;
-
-			// Editable layer name
-			let h: zui_handle_t = zui_handle("uiview2d_1");
-
-			///if (is_paint || is_sculpt)
-			let text: string = UIView2D.type == view_2d_type_t.NODE ? context_raw.node_preview_name : h.text;
-			///else
-			let text: string = h.text;
-			///end
-
-			UIView2D.ui._w = Math.floor(Math.min(g2_font_width(UIView2D.ui.font, UIView2D.ui.font_size, text) + 15 * zui_SCALE(UIView2D.ui), 100 * zui_SCALE(UIView2D.ui)));
-
-			if (UIView2D.type == view_2d_type_t.ASSET) {
-				let asset: asset_t = context_raw.texture;
-				if (asset != null) {
-					let assetNames: string[] = project_asset_names;
-					let i: i32 = assetNames.indexOf(asset.name);
-					h.text = asset.name;
-					asset.name = zui_text_input(h, "");
-					assetNames[i] = asset.name;
-				}
-			}
-			else if (UIView2D.type == view_2d_type_t.NODE) {
-				///if (is_paint || is_sculpt)
-
-				zui_text(context_raw.node_preview_name);
-
-				///else
-
-				let nodes: zui_nodes_t = UINodes.get_nodes();
-				if (nodes.nodes_selected_id.length > 0) {
-					zui_text(zui_get_node(UINodes.get_canvas(true).nodes, nodes.nodes_selected_id[0]).name);
-				}
-
-				///end
-			}
-			///if (is_paint || is_sculpt)
-			else if (UIView2D.type == view_2d_type_t.LAYER) {
-				h.text = l.name;
-				l.name = zui_text_input(h, "");
-				UIView2D.text_input_hover = UIView2D.ui.is_hovered;
-			}
-			else if (UIView2D.type == view_2d_type_t.FONT) {
-				h.text = context_raw.font.name;
-				context_raw.font.name = zui_text_input(h, "");
-			}
-			///end
-
-			if (h.changed) UIBase.hwnds[0].redraws = 2;
-			UIView2D.ui._x += UIView2D.ui._w + 3;
-			UIView2D.ui._y = 2 + start_y;
-			UIView2D.ui._w = ew;
-
-			///if (is_paint || is_sculpt)
-			if (UIView2D.type == view_2d_type_t.LAYER) {
-				UIView2D.layer_mode = zui_combo(zui_handle("uiview2d_2", { position: UIView2D.layer_mode }), [
-					tr("Visible"),
-					tr("Selected"),
-				], tr("Layers"));
-				UIView2D.ui._x += ew + 3;
-				UIView2D.ui._y = 2 + start_y;
-
-				if (!SlotLayer.is_mask(context_raw.layer)) {
-					UIView2D.tex_type = zui_combo(zui_handle("uiview2d_3", { position: UIView2D.tex_type }), [
-						tr("Base Color"),
-						tr("Normal Map"),
-						tr("Occlusion"),
-						tr("Roughness"),
-						tr("Metallic"),
-						tr("Opacity"),
-						tr("Height"),
-					], tr("Texture"));
-					UIView2D.ui._x += ew + 3;
-					UIView2D.ui._y = 2 + start_y;
-				}
-
-				UIView2D.ui._w = Math.floor(ew * 0.7 + 3);
-				UIView2D.uvmap_show = zui_check(zui_handle("uiview2d_4", { selected: UIView2D.uvmap_show }), tr("UV Map"));
-				UIView2D.ui._x += ew * 0.7 + 3;
-				UIView2D.ui._y = 2 + start_y;
-			}
-			///end
-
-			UIView2D.tiled_show = zui_check(zui_handle("uiview2d_5", { selected: UIView2D.tiled_show }), tr("Tiled"));
-			UIView2D.ui._x += ew * 0.7 + 3;
-			UIView2D.ui._y = 2 + start_y;
-
-			if (UIView2D.type == view_2d_type_t.ASSET && tex != null) { // Texture resolution
-				zui_text(tex.width + "x" + tex.height);
-			}
-
-			// Picked position
-			///if (is_paint || is_sculpt)
-			if (context_raw.tool == workspace_tool_t.PICKER && (UIView2D.type == view_2d_type_t.LAYER || UIView2D.type == view_2d_type_t.ASSET)) {
-				let cursor_img: image_t = resource_get("cursor.k");
-				let hsize: f32 = 16 * zui_SCALE(UIView2D.ui);
-				let size: f32 = hsize * 2;
-				g2_draw_scaled_image(cursor_img, tx + tw * context_raw.uvx_picked - hsize, ty + th * context_raw.uvy_picked - hsize, size, size);
-			}
-			///end
-		}
-		zui_end();
-		g2_begin(null);
-	}
-
-	static update = () => {
-		let headerh: f32 = zui_ELEMENT_H(UIView2D.ui) * 1.4;
-
-		///if (is_paint || is_sculpt)
-		context_raw.paint2d = false;
-		///end
-
-		if (!base_ui_enabled ||
-			!UIView2D.show ||
-			mouse_x < UIView2D.wx ||
-			mouse_x > UIView2D.wx + UIView2D.ww ||
-			mouse_y < UIView2D.wy + headerh ||
-			mouse_y > UIView2D.wy + UIView2D.wh) {
-			if (UIView2D.controls_down) {
-				UINodes.get_canvas_control(UIView2D.ui, UIView2D);
-			}
-			return;
-		}
-
-		let control: zui_canvas_control_t = UINodes.get_canvas_control(UIView2D.ui, UIView2D);
-		UIView2D.pan_x += control.pan_x;
-		UIView2D.pan_y += control.pan_y;
-		if (control.zoom != 0) {
-			let _pan_x: f32 = UIView2D.pan_x / UIView2D.pan_scale;
-			let _pan_y: f32 = UIView2D.pan_y / UIView2D.pan_scale;
-			UIView2D.pan_scale += control.zoom;
-			if (UIView2D.pan_scale < 0.1) UIView2D.pan_scale = 0.1;
-			if (UIView2D.pan_scale > 6.0) UIView2D.pan_scale = 6.0;
-			UIView2D.pan_x = _pan_x * UIView2D.pan_scale;
-			UIView2D.pan_y = _pan_y * UIView2D.pan_scale;
-
-			if (zui_touch_scroll()) {
-				// Zoom to finger location
-				UIView2D.pan_x -= (UIView2D.ui.input_x - UIView2D.ui._window_x - UIView2D.ui._window_w / 2) * control.zoom;
-				UIView2D.pan_y -= (UIView2D.ui.input_y - UIView2D.ui._window_y - UIView2D.ui._window_h / 2) * control.zoom;
-			}
-		}
-
-		///if (is_paint || is_sculpt)
-		let decal: bool = context_raw.tool == workspace_tool_t.DECAL || context_raw.tool == workspace_tool_t.TEXT;
-		let decal_mask: bool = decal && operator_shortcut(config_keymap.decal_mask + "+" + config_keymap.action_paint, shortcut_type_t.DOWN);
-		let set_clone_source: bool = context_raw.tool == workspace_tool_t.CLONE && operator_shortcut(config_keymap.set_clone_source + "+" + config_keymap.action_paint, shortcut_type_t.DOWN);
-
-		if (UIView2D.type == view_2d_type_t.LAYER &&
-			!UIView2D.text_input_hover &&
-			(operator_shortcut(config_keymap.action_paint, shortcut_type_t.DOWN) ||
-			 operator_shortcut(config_keymap.brush_ruler + "+" + config_keymap.action_paint, shortcut_type_t.DOWN) ||
-			 decal_mask ||
-			 set_clone_source ||
-			 config_raw.brush_live)) {
-			context_raw.paint2d = true;
-		}
-		///end
-
-		if (UIView2D.ui.is_typing) return;
-
-		if (keyboard_started("left")) UIView2D.pan_x -= 5;
-		else if (keyboard_started("right")) UIView2D.pan_x += 5;
-		if (keyboard_started("up")) UIView2D.pan_y -= 5;
-		else if (keyboard_started("down")) UIView2D.pan_y += 5;
-
-		// Limit panning to keep texture in viewport
-		let border: i32 = 32;
-		let tw: f32 = UIView2D.ww * 0.95 * UIView2D.pan_scale;
-		let tx: f32 = UIView2D.ww / 2 - tw / 2 + UIView2D.pan_x;
-		let hh: f32 = app_h();
-		let ty: f32 = hh / 2 - tw / 2 + UIView2D.pan_y;
-
-		if      (tx + border >  UIView2D.ww) UIView2D.pan_x =  UIView2D.ww / 2 + tw / 2 - border;
-		else if (tx - border < -tw) UIView2D.pan_x = -tw / 2 - UIView2D.ww / 2 + border;
-		if      (ty + border >  hh) UIView2D.pan_y =  hh / 2 + tw / 2 - border;
-		else if (ty - border < -tw) UIView2D.pan_y = -tw / 2 - hh / 2 + border;
-
-		if (operator_shortcut(config_keymap.view_reset)) {
-			UIView2D.pan_x = 0.0;
-			UIView2D.pan_y = 0.0;
-			UIView2D.pan_scale = 1.0;
-		}
-	}
-}

+ 0 - 380
base/Sources/UtilMesh.ts

@@ -1,380 +0,0 @@
-
-class UtilMesh {
-
-	static unwrappers: Map<string, ((a: any)=>void)> = new Map();
-
-	static merge_mesh = (paint_objects: mesh_object_t[] = null) => {
-		if (paint_objects == null) paint_objects = project_paint_objects;
-		if (paint_objects.length == 0) return;
-		context_raw.merged_object_is_atlas = paint_objects.length < project_paint_objects.length;
-		let vlen: i32 = 0;
-		let ilen: i32 = 0;
-		let max_scale: f32 = 0.0;
-		for (let i: i32 = 0; i < paint_objects.length; ++i) {
-			vlen += paint_objects[i].data.vertex_arrays[0].values.length;
-			ilen += paint_objects[i].data.index_arrays[0].values.length;
-			if (paint_objects[i].data.scale_pos > max_scale) max_scale = paint_objects[i].data.scale_pos;
-		}
-		vlen = Math.floor(vlen / 4);
-		let va0: Int16Array = new Int16Array(vlen * 4);
-		let va1: Int16Array = new Int16Array(vlen * 2);
-		let va2: Int16Array = new Int16Array(vlen * 2);
-		let va3: Int16Array = paint_objects[0].data.vertex_arrays.length > 3 ? new Int16Array(vlen * 4) : null;
-		let ia: Uint32Array = new Uint32Array(ilen);
-
-		let voff: i32 = 0;
-		let ioff: i32 = 0;
-		for (let i: i32 = 0; i < paint_objects.length; ++i) {
-			let vas: vertex_array_t[] = paint_objects[i].data.vertex_arrays;
-			let ias: index_array_t[] = paint_objects[i].data.index_arrays;
-			let scale: f32 = paint_objects[i].data.scale_pos;
-
-			// Pos
-			for (let j: i32 = 0; j < vas[0].values.length; ++j) va0[j + voff * 4] = vas[0].values[j];
-
-			// Translate
-			///if is_forge
-			for (let j: i32 = 0; j < Math.floor(va0.length / 4); ++j) {
-				va0[j * 4     + voff * 4] += Math.floor(transform_world_x(paint_objects[i].base.transform) * 32767);
-				va0[j * 4 + 1 + voff * 4] += Math.floor(transform_world_y(paint_objects[i].base.transform) * 32767);
-				va0[j * 4 + 2 + voff * 4] += Math.floor(transform_world_z(paint_objects[i].base.transform) * 32767);
-			}
-			///end
-
-			// Re-scale
-			for (let j: i32 = 0; j < Math.floor(va0.length / 4); ++j) {
-				va0[j * 4     + voff * 4] = Math.floor((va0[j * 4     + voff * 4] * scale) / max_scale);
-				va0[j * 4 + 1 + voff * 4] = Math.floor((va0[j * 4 + 1 + voff * 4] * scale) / max_scale);
-				va0[j * 4 + 2 + voff * 4] = Math.floor((va0[j * 4 + 2 + voff * 4] * scale) / max_scale);
-			}
-			// Nor
-			for (let j: i32 = 0; j < vas[1].values.length; ++j) va1[j + voff * 2] = vas[1].values[j];
-			// Tex
-			for (let j: i32 = 0; j < vas[2].values.length; ++j) va2[j + voff * 2] = vas[2].values[j];
-			// Col
-			if (va3 != null) for (let j: i32 = 0; j < vas[3].values.length; ++j) va3[j + voff * 4] = vas[3].values[j];
-			// Indices
-			for (let j: i32 = 0; j < ias[0].values.length; ++j) ia[j + ioff] = ias[0].values[j] + voff;
-
-			voff += Math.floor(vas[0].values.length / 4);
-			ioff += Math.floor(ias[0].values.length);
-		}
-
-		let raw: mesh_data_t = {
-			name: context_raw.paint_object.base.name,
-			vertex_arrays: [
-				{ values: va0, attrib: "pos", data: "short4norm" },
-				{ values: va1, attrib: "nor", data: "short2norm" },
-				{ values: va2, attrib: "tex", data: "short2norm" }
-			],
-			index_arrays: [
-				{ values: ia, material: 0 }
-			],
-			scale_pos: max_scale,
-			scale_tex: 1.0
-		};
-		if (va3 != null) raw.vertex_arrays.push({ values: va3, attrib: "col", data: "short4norm" });
-
-		UtilMesh.remove_merged_mesh();
-		let md: mesh_data_t = mesh_data_create(raw);
-		context_raw.merged_object = mesh_object_create(md, context_raw.paint_object.materials);
-		context_raw.merged_object.base.name = context_raw.paint_object.base.name + "_merged";
-		context_raw.merged_object.force_context = "paint";
-		object_set_parent(context_raw.merged_object.base, context_main_object().base);
-
-		///if (krom_direct3d12 || krom_vulkan || krom_metal)
-		RenderPathRaytrace.ready = false;
-		///end
-	}
-
-	static remove_merged_mesh = () => {
-		if (context_raw.merged_object != null) {
-			mesh_data_delete(context_raw.merged_object.data);
-			mesh_object_remove(context_raw.merged_object);
-			context_raw.merged_object = null;
-		}
-	}
-
-	static swap_axis = (a: i32, b: i32) => {
-		let objects: mesh_object_t[] = project_paint_objects;
-		for (let o of objects) {
-			// Remapping vertices, buckle up
-			// 0 - x, 1 - y, 2 - z
-			let vas: vertex_array_t[] = o.data.vertex_arrays;
-			let pa: i16_array_t  = vas[0].values;
-			let na0: i16_array_t = a == 2 ? vas[0].values : vas[1].values;
-			let na1: i16_array_t = b == 2 ? vas[0].values : vas[1].values;
-			let c: i32 = a == 2 ? 3 : a;
-			let d: i32 = b == 2 ? 3 : b;
-			let e: i32 = a == 2 ? 4 : 2;
-			let f: i32 = b == 2 ? 4 : 2;
-
-			for (let i: i32 = 0; i < Math.floor(pa.length / 4); ++i) {
-				let t: i32 = pa[i * 4 + a];
-				pa[i * 4 + a] = pa[i * 4 + b];
-				pa[i * 4 + b] = -t;
-				t = na0[i * e + c];
-				na0[i * e + c] = na1[i * f + d];
-				na1[i * f + d] = -t;
-			}
-
-			let g: mesh_data_t = o.data;
-			let l: i32 = g4_vertex_struct_byte_size(g._.structure) / 2;
-			let vertices: buffer_view_t = g4_vertex_buffer_lock(g._.vertex_buffer); // posnortex
-			for (let i: i32 = 0; i < Math.floor(vertices.byteLength / 2 / l); ++i) {
-				vertices.setInt16((i * l    ) * 2, vas[0].values[i * 4    ], true);
-				vertices.setInt16((i * l + 1) * 2, vas[0].values[i * 4 + 1], true);
-				vertices.setInt16((i * l + 2) * 2, vas[0].values[i * 4 + 2], true);
-				vertices.setInt16((i * l + 3) * 2, vas[0].values[i * 4 + 3], true);
-				vertices.setInt16((i * l + 4) * 2, vas[1].values[i * 2    ], true);
-				vertices.setInt16((i * l + 5) * 2, vas[1].values[i * 2 + 1], true);
-			}
-			g4_vertex_buffer_unlock(g._.vertex_buffer);
-		}
-
-		UtilMesh.remove_merged_mesh();
-		UtilMesh.merge_mesh();
-	}
-
-	static flip_normals = () => {
-		let objects: mesh_object_t[] = project_paint_objects;
-		for (let o of objects) {
-			let vas: vertex_array_t[] = o.data.vertex_arrays;
-			let va0: i16_array_t = vas[0].values;
-			let va1: i16_array_t = vas[1].values;
-			let g: mesh_data_t = o.data;
-			let l: i32 = g4_vertex_struct_byte_size(g._.structure) / 2;
-			let vertices: buffer_view_t = g4_vertex_buffer_lock(g._.vertex_buffer); // posnortex
-			for (let i: i32 = 0; i < Math.floor(vertices.byteLength / 2 / l); ++i) {
-				va0[i * 4 + 3] = -va0[i * 4 + 3];
-				va1[i * 2] = -va1[i * 2];
-				va1[i * 2 + 1] = -va1[i * 2 + 1];
-				vertices.setInt16((i * l + 3) * 2, -vertices.getInt16((i * l + 3) * 2, true), true);
-				vertices.setInt16((i * l + 4) * 2, -vertices.getInt16((i * l + 4) * 2, true), true);
-				vertices.setInt16((i * l + 5) * 2, -vertices.getInt16((i * l + 5) * 2, true), true);
-			}
-			g4_vertex_buffer_unlock(g._.vertex_buffer);
-		}
-
-		///if (krom_direct3d12 || krom_vulkan || krom_metal)
-		RenderPathRaytrace.ready = false;
-		///end
-	}
-
-	static calc_normals = (smooth: bool = false) => {
-		let va: vec4_t = vec4_create();
-		let vb: vec4_t = vec4_create();
-		let vc: vec4_t = vec4_create();
-		let cb: vec4_t = vec4_create();
-		let ab: vec4_t = vec4_create();
-		let objects: mesh_object_t[] = project_paint_objects;
-		for (let o of objects) {
-			let g: mesh_data_t = o.data;
-			let l: i32 = g4_vertex_struct_byte_size(g._.structure) / 2;
-			let inda: u32_array_t = g._.indices[0];
-			let vertices: buffer_view_t = g4_vertex_buffer_lock(g._.vertex_buffer); // posnortex
-			for (let i: i32 = 0; i < Math.floor(inda.length / 3); ++i) {
-				let i1: i32 = inda[i * 3    ];
-				let i2: i32 = inda[i * 3 + 1];
-				let i3: i32 = inda[i * 3 + 2];
-				vec4_set(va, vertices.getInt16((i1 * l) * 2, true), vertices.getInt16((i1 * l + 1) * 2, true), vertices.getInt16((i1 * l + 2) * 2, true));
-				vec4_set(vb, vertices.getInt16((i2 * l) * 2, true), vertices.getInt16((i2 * l + 1) * 2, true), vertices.getInt16((i2 * l + 2) * 2, true));
-				vec4_set(vc, vertices.getInt16((i3 * l) * 2, true), vertices.getInt16((i3 * l + 1) * 2, true), vertices.getInt16((i3 * l + 2) * 2, true));
-				vec4_sub_vecs(cb, vc, vb);
-				vec4_sub_vecs(ab, va, vb);
-				vec4_cross(cb, ab);
-				vec4_normalize(cb, );
-				vertices.setInt16((i1 * l + 4) * 2, Math.floor(cb.x * 32767), true);
-				vertices.setInt16((i1 * l + 5) * 2, Math.floor(cb.y * 32767), true);
-				vertices.setInt16((i1 * l + 3) * 2, Math.floor(cb.z * 32767), true);
-				vertices.setInt16((i2 * l + 4) * 2, Math.floor(cb.x * 32767), true);
-				vertices.setInt16((i2 * l + 5) * 2, Math.floor(cb.y * 32767), true);
-				vertices.setInt16((i2 * l + 3) * 2, Math.floor(cb.z * 32767), true);
-				vertices.setInt16((i3 * l + 4) * 2, Math.floor(cb.x * 32767), true);
-				vertices.setInt16((i3 * l + 5) * 2, Math.floor(cb.y * 32767), true);
-				vertices.setInt16((i3 * l + 3) * 2, Math.floor(cb.z * 32767), true);
-			}
-
-			if (smooth) {
-				let shared: Uint32Array = new Uint32Array(1024);
-				let sharedLen: i32 = 0;
-				let found: i32[] = [];
-				for (let i: i32 = 0; i < (inda.length - 1); ++i) {
-					if (found.indexOf(i) >= 0) continue;
-					let i1: i32 = inda[i];
-					sharedLen = 0;
-					shared[sharedLen++] = i1;
-					for (let j: i32 = (i + 1); j < inda.length; ++j) {
-						let i2: i32 = inda[j];
-						let i1l: i32 = i1 * l;
-						let i2l: i32 = i2 * l;
-						if (vertices.getInt16((i1l    ) * 2, true) == vertices.getInt16((i2l    ) * 2, true) &&
-							vertices.getInt16((i1l + 1) * 2, true) == vertices.getInt16((i2l + 1) * 2, true) &&
-							vertices.getInt16((i1l + 2) * 2, true) == vertices.getInt16((i2l + 2) * 2, true)) {
-							// if (n1.dot(n2) > 0)
-							shared[sharedLen++] = i2;
-							found.push(j);
-							if (sharedLen >= 1024) break;
-						}
-					}
-					if (sharedLen > 1) {
-						vec4_set(va, 0, 0, 0);
-						for (let j: i32 = 0; j < sharedLen; ++j) {
-							let i1: i32 = shared[j];
-							let i1l: i32 = i1 * l;
-							vec4_add_f(va, vertices.getInt16((i1l + 4) * 2, true), vertices.getInt16((i1l + 5) * 2, true), vertices.getInt16((i1l + 3) * 2, true));
-						}
-						vec4_mult(va, 1 / sharedLen);
-						vec4_normalize(va, );
-						let vax: i32 = Math.floor(va.x * 32767);
-						let vay: i32 = Math.floor(va.y * 32767);
-						let vaz: i32 = Math.floor(va.z * 32767);
-						for (let j: i32 = 0; j < sharedLen; ++j) {
-							let i1: i32 = shared[j];
-							let i1l: i32 = i1 * l;
-							vertices.setInt16((i1l + 4) * 2, vax, true);
-							vertices.setInt16((i1l + 5) * 2, vay, true);
-							vertices.setInt16((i1l + 3) * 2, vaz, true);
-						}
-					}
-				}
-			}
-			g4_vertex_buffer_unlock(g._.vertex_buffer);
-
-			let va0: i16_array_t = o.data.vertex_arrays[0].values;
-			let va1: i16_array_t = o.data.vertex_arrays[1].values;
-			for (let i: i32 = 0; i < Math.floor(vertices.byteLength / 4 / l); ++i) {
-				va1[i * 2    ] = vertices.getInt16((i * l + 4) * 2, true);
-				va1[i * 2 + 1] = vertices.getInt16((i * l + 5) * 2, true);
-				va0[i * 4 + 3] = vertices.getInt16((i * l + 3) * 2, true);
-			}
-		}
-
-		///if (krom_direct3d12 || krom_vulkan || krom_metal)
-		UtilMesh.merge_mesh();
-		RenderPathRaytrace.ready = false;
-		///end
-	}
-
-	static to_origin = () => {
-		let dx: f32 = 0.0;
-		let dy: f32 = 0.0;
-		let dz: f32 = 0.0;
-		for (let o of project_paint_objects) {
-			let l: i32 = 4;
-			let sc: f32 = o.data.scale_pos / 32767;
-			let va: i16_array_t = o.data.vertex_arrays[0].values;
-			let minx: f32 = va[0];
-			let maxx: f32 = va[0];
-			let miny: f32 = va[1];
-			let maxy: f32 = va[1];
-			let minz: f32 = va[2];
-			let maxz: f32 = va[2];
-			for (let i: i32 = 1; i < Math.floor(va.length / l); ++i) {
-				if (va[i * l] < minx) minx = va[i * l];
-				else if (va[i * l] > maxx) maxx = va[i * l];
-				if (va[i * l + 1] < miny) miny = va[i * l + 1];
-				else if (va[i * l + 1] > maxy) maxy = va[i * l + 1];
-				if (va[i * l + 2] < minz) minz = va[i * l + 2];
-				else if (va[i * l + 2] > maxz) maxz = va[i * l + 2];
-			}
-			dx += (minx + maxx) / 2 * sc;
-			dy += (miny + maxy) / 2 * sc;
-			dz += (minz + maxz) / 2 * sc;
-		}
-		dx /= project_paint_objects.length;
-		dy /= project_paint_objects.length;
-		dz /= project_paint_objects.length;
-
-		for (let o of project_paint_objects) {
-			let g: mesh_data_t = o.data;
-			let sc: f32 = o.data.scale_pos / 32767;
-			let va: i16_array_t = o.data.vertex_arrays[0].values;
-			let max_scale: f32 = 0.0;
-			for (let i: i32 = 0; i < Math.floor(va.length / 4); ++i) {
-				if (Math.abs(va[i * 4    ] * sc - dx) > max_scale) max_scale = Math.abs(va[i * 4    ] * sc - dx);
-				if (Math.abs(va[i * 4 + 1] * sc - dy) > max_scale) max_scale = Math.abs(va[i * 4 + 1] * sc - dy);
-				if (Math.abs(va[i * 4 + 2] * sc - dz) > max_scale) max_scale = Math.abs(va[i * 4 + 2] * sc - dz);
-			}
-			o.base.transform.scale_world = o.data.scale_pos = o.data.scale_pos = max_scale;
-			transform_build_matrix(o.base.transform);
-
-			for (let i: i32 = 0; i < Math.floor(va.length / 4); ++i) {
-				va[i * 4    ] = Math.floor((va[i * 4    ] * sc - dx) / max_scale * 32767);
-				va[i * 4 + 1] = Math.floor((va[i * 4 + 1] * sc - dy) / max_scale * 32767);
-				va[i * 4 + 2] = Math.floor((va[i * 4 + 2] * sc - dz) / max_scale * 32767);
-			}
-
-			let l: i32 = g4_vertex_struct_byte_size(g._.structure) / 2;
-			let vertices: buffer_view_t = g4_vertex_buffer_lock(g._.vertex_buffer); // posnortex
-			for (let i: i32 = 0; i < Math.floor(vertices.byteLength / 2 / l); ++i) {
-				vertices.setInt16((i * l    ) * 2, va[i * 4    ], true);
-				vertices.setInt16((i * l + 1) * 2, va[i * 4 + 1], true);
-				vertices.setInt16((i * l + 2) * 2, va[i * 4 + 2], true);
-			}
-			g4_vertex_buffer_unlock(g._.vertex_buffer);
-		}
-
-		UtilMesh.merge_mesh();
-	}
-
-	static apply_displacement = (texpaint_pack: image_t, strength: f32 = 0.1, uvScale: f32 = 1.0) => {
-		let height: buffer_t = image_get_pixels(texpaint_pack);
-		let height_view: buffer_view_t = new DataView(height);
-		let res: i32 = texpaint_pack.width;
-		let o: mesh_object_t = project_paint_objects[0];
-		let g: mesh_data_t = o.data;
-		let l: i32 = g4_vertex_struct_byte_size(g._.structure) / 2;
-		let vertices: buffer_view_t = g4_vertex_buffer_lock(g._.vertex_buffer); // posnortex
-		for (let i: i32 = 0; i < Math.floor(vertices.byteLength / 2 / l); ++i) {
-			let x: i32 = Math.floor(vertices.getInt16((i * l + 6) * 2, true) / 32767 * res);
-			let y: i32 = Math.floor(vertices.getInt16((i * l + 7) * 2, true) / 32767 * res);
-			let xx: i32 = Math.floor(x * uvScale) % res;
-			let yy: i32 = Math.floor(y * uvScale) % res;
-			let h: f32 = (1.0 - height_view.getUint8((yy * res + xx) * 4 + 3) / 255) * strength;
-			vertices.setInt16((i * l    ) * 2, vertices.getInt16((i * l    ) * 2, true) - Math.floor(vertices.getInt16((i * l + 4) * 2, true) * h), true);
-			vertices.setInt16((i * l + 1) * 2, vertices.getInt16((i * l + 1) * 2, true) - Math.floor(vertices.getInt16((i * l + 5) * 2, true) * h), true);
-			vertices.setInt16((i * l + 2) * 2, vertices.getInt16((i * l + 2) * 2, true) - Math.floor(vertices.getInt16((i * l + 3) * 2, true) * h), true);
-		}
-		g4_vertex_buffer_unlock(g._.vertex_buffer);
-
-		let va0: i16_array_t = o.data.vertex_arrays[0].values;
-		for (let i: i32 = 0; i < Math.floor(vertices.byteLength / 4 / l); ++i) {
-			va0[i * 4    ] = vertices.getInt16((i * l    ) * 2, true);
-			va0[i * 4 + 1] = vertices.getInt16((i * l + 1) * 2, true);
-			va0[i * 4 + 2] = vertices.getInt16((i * l + 2) * 2, true);
-		}
-	}
-
-	static equirect_unwrap = (mesh: any) => {
-		let verts: i32 = Math.floor(mesh.posa.length / 4);
-		mesh.texa = new Int16Array(verts * 2);
-		let n: vec4_t = vec4_create();
-		for (let i: i32 = 0; i < verts; ++i) {
-			vec4_normalize(vec4_set(n, mesh.posa[i * 4] / 32767, mesh.posa[i * 4 + 1] / 32767, mesh.posa[i * 4 + 2] / 32767));
-			// Sphere projection
-			// mesh.texa[i * 2    ] = Math.atan2(n.x, n.y) / (Math.PI * 2) + 0.5;
-			// mesh.texa[i * 2 + 1] = n.z * 0.5 + 0.5;
-			// Equirect
-			mesh.texa[i * 2    ] = Math.floor(((Math.atan2(-n.z, n.x) + Math.PI) / (Math.PI * 2)) * 32767);
-			mesh.texa[i * 2 + 1] = Math.floor((Math.acos(n.y) / Math.PI) * 32767);
-		}
-	}
-
-	static pnpoly = (v0x: f32, v0y: f32, v1x: f32, v1y: f32, v2x: f32, v2y: f32, px: f32, py: f32): bool => {
-		// https://wrf.ecse.rpi.edu//Research/Short_Notes/pnpoly.html
-		let c: bool = false;
-		if (((v0y > py) != (v2y > py)) && (px < (v2x - v0x) * (py - v0y) / (v2y - v0y) + v0x)) c = !c;
-		if (((v1y > py) != (v0y > py)) && (px < (v0x - v1x) * (py - v1y) / (v0y - v1y) + v1x)) c = !c;
-		if (((v2y > py) != (v1y > py)) && (px < (v1x - v2x) * (py - v2y) / (v1y - v2y) + v2x)) c = !c;
-		return c;
-	}
-
-	static calc_normal = (p0: vec4_t, p1: vec4_t, p2: vec4_t): vec4_t => {
-		let cb: vec4_t = vec4_sub_vecs(vec4_create(), p2, p1);
-		let ab: vec4_t = vec4_sub_vecs(vec4_create(), p0, p1);
-		vec4_cross(cb, ab);
-		vec4_normalize(cb);
-		return cb;
-	}
-}

+ 0 - 116
base/Sources/UtilParticle.ts

@@ -1,116 +0,0 @@
-
-///if (is_paint || is_sculpt)
-
-class UtilParticle {
-
-	static init_particle = () => {
-		if (context_raw.particle_material != null) return;
-
-		let raw: particle_data_t = {
-			name: "Particles",
-			type: 0,
-			loop: false,
-			count: 1000,
-			frame_start: 0,
-			frame_end: 1000,
-			lifetime: 400,
-			lifetime_random: 0.5,
-			emit_from: 1,
-			object_align_factor: new Float32Array([0, 0, -40]),
-			factor_random: 2.0,
-			physics_type: 0,
-			particle_size: 1.0,
-			size_random: 0,
-			mass: 1,
-			instance_object: ".Particle",
-			weight_gravity: 1
-		};
-		_scene_raw.particle_datas = [raw];
-		let particle_refs: particle_ref_t[] = [
-			{
-				name: "Particles",
-				particle: "Particles",
-				seed: 0
-			}
-		];
-
-		{
-			let t: render_target_t = render_target_create();
-			t.name = "texparticle";
-			t.width = 0;
-			t.height = 0;
-			t.format = "R8";
-			t.scale = RenderPathBase.get_super_sampling();
-			render_path_create_render_target(t);
-		}
-
-		for (let mat of _scene_raw.material_datas) {
-			if (mat.name == "Material2") {
-				let m: material_data_t = JSON.parse(JSON.stringify(mat));
-				m.name = "MaterialParticle";
-				_scene_raw.material_datas.push(m);
-				break;
-			}
-		}
-
-		let md: material_data_t = data_get_material("Scene", "MaterialParticle");
-		context_raw.particle_material = md;
-
-		for (let obj of _scene_raw.objects) {
-			if (obj.name == ".Sphere") {
-				let particle: obj_t = JSON.parse(JSON.stringify(obj));
-				particle.name = ".Particle";
-				if (particle.particles == null) {
-					particle.particles = {};
-				}
-				particle.particles.is_particle = true;
-				particle.material_refs = ["MaterialParticle"];
-				_scene_raw.objects.push(particle);
-				for (let i: i32 = 0; i < 16; ++i) particle.transform[i] *= 0.01;
-				break;
-			}
-		}
-
-		let o: object_t = scene_spawn_object(".Sphere");
-		let mo: mesh_object_t = o.ext;
-		mo.base.name = ".ParticleEmitter";
-		mo.base.raw = JSON.parse(JSON.stringify(mo.base.raw));
-		mo.base.raw.particles.refs = particle_refs;
-		///if arm_particles
-		mesh_object_setup_particle_system(mo, "Scene", particle_refs[0]);
-		///end
-	}
-
-	///if arm_physics
-
-	static init_particle_physics = () => {
-		if (PhysicsWorld.active != null) {
-			UtilParticle.init_particle_mesh();
-			return;
-		}
-
-		PhysicsWorld.load(() => {
-			PhysicsWorld.create();
-			UtilParticle.init_particle_mesh();
-		});
-	}
-
-	static init_particle_mesh = () => {
-		if (context_raw.paint_body != null) return;
-
-		let po: mesh_object_t = context_raw.merged_object != null ? context_raw.merged_object : context_raw.paint_object;
-
-		po.base.transform.scale.x = po.base.parent.transform.scale.x;
-		po.base.transform.scale.y = po.base.parent.transform.scale.y;
-		po.base.transform.scale.z = po.base.parent.transform.scale.z;
-
-		context_raw.paint_body = PhysicsBody.create();
-		context_raw.paint_body.shape = shape_type_t.MESH;
-		PhysicsBody.init(context_raw.paint_body, po.base);
-		(po.base as any).physicsBody = context_raw.paint_body;
-	}
-
-	///end
-}
-
-///end

+ 0 - 451
base/Sources/UtilRender.ts

@@ -1,451 +0,0 @@
-
-///if (is_paint || is_sculpt)
-
-class UtilRender {
-
-	static material_preview_size: i32 = 256;
-	static decal_preview_size: i32 = 512;
-	static layer_preview_size: i32 = 200;
-	static screen_aligned_full_vb: vertex_buffer_t = null;
-	static screen_aligned_full_ib: index_buffer_t = null;
-
-	static make_material_preview = () => {
-		context_raw.material_preview = true;
-
-		let sphere: mesh_object_t = scene_get_child(".Sphere").ext;
-		sphere.base.visible = true;
-		let meshes: mesh_object_t[] = scene_meshes;
-		scene_meshes = [sphere];
-		let painto: mesh_object_t = context_raw.paint_object;
-		context_raw.paint_object = sphere;
-
-		sphere.materials[0] = project_materials[0].data;
-		context_raw.material.preview_ready = true;
-
-		mat4_set_from(context_raw.saved_camera, scene_camera.base.transform.local);
-		let m: mat4_t = mat4_create(0.9146286343879498, -0.0032648027153306235, 0.404281837254303, 0.4659988049397712, 0.404295023959927, 0.007367569133732468, -0.9145989516155143, -1.0687517188018691, 0.000007410128652369705, 0.9999675337275382, 0.008058532943908717, 0.015935682577325486, 0, 0, 0, 1);
-		transform_set_matrix(scene_camera.base.transform, m);
-		let saved_fov: f32 = scene_camera.data.fov;
-		scene_camera.data.fov = 0.92;
-		viewport_update_camera_type(camera_type_t.PERSPECTIVE);
-		let light: light_object_t = scene_lights[0];
-		let _light_strength: f32 = light.data.strength;
-		let probe: world_data_t = scene_world;
-		let _probe_strength: f32 = probe.strength;
-		light.data.strength = 0;
-		probe.strength = 7;
-		let _envmap_angle: f32 = context_raw.envmap_angle;
-		context_raw.envmap_angle = 6.0;
-		let _brush_scale: f32 = context_raw.brush_scale;
-		context_raw.brush_scale = 1.5;
-		let _brush_nodes_scale: f32 = context_raw.brush_nodes_scale;
-		context_raw.brush_nodes_scale = 1.0;
-
-		scene_world._.envmap = context_raw.preview_envmap;
-		// No resize
-		_render_path_last_w = UtilRender.material_preview_size;
-		_render_path_last_h = UtilRender.material_preview_size;
-		camera_object_build_proj(scene_camera);
-		camera_object_build_mat(scene_camera);
-
-		MakeMaterial.parse_mesh_preview_material();
-		let _commands: ()=>void = render_path_commands;
-		render_path_commands = RenderPathPreview.commands_preview;
-		render_path_render_frame();
-		render_path_commands = _commands;
-
-		context_raw.material_preview = false;
-		_render_path_last_w = app_w();
-		_render_path_last_h = app_h();
-
-		// Restore
-		sphere.base.visible = false;
-		scene_meshes = meshes;
-		context_raw.paint_object = painto;
-
-		transform_set_matrix(scene_camera.base.transform, context_raw.saved_camera);
-		viewport_update_camera_type(context_raw.camera_type);
-		scene_camera.data.fov = saved_fov;
-		camera_object_build_proj(scene_camera);
-		camera_object_build_mat(scene_camera);
-		light.data.strength = _light_strength;
-		probe.strength = _probe_strength;
-		context_raw.envmap_angle = _envmap_angle;
-		context_raw.brush_scale = _brush_scale;
-		context_raw.brush_nodes_scale = _brush_nodes_scale;
-		scene_world._.envmap = context_raw.show_envmap ? context_raw.saved_envmap : context_raw.empty_envmap;
-		MakeMaterial.parse_mesh_material();
-		context_raw.ddirty = 0;
-	}
-
-	static make_decal_preview = () => {
-		let current: image_t = _g2_current;
-		let g2_in_use: bool = _g2_in_use;
-		if (g2_in_use) g2_end();
-
-		if (context_raw.decal_image == null) {
-			context_raw.decal_image = image_create_render_target(UtilRender.decal_preview_size, UtilRender.decal_preview_size);
-		}
-		context_raw.decal_preview = true;
-
-		let plane: mesh_object_t = scene_get_child(".Plane").ext;
-		vec4_set(plane.base.transform.scale, 1, 1, 1);
-		quat_from_euler(plane.base.transform.rot, -Math.PI / 2, 0, 0);
-		transform_build_matrix(plane.base.transform);
-		plane.base.visible = true;
-		let meshes: mesh_object_t[] = scene_meshes;
-		scene_meshes = [plane];
-		let painto: mesh_object_t = context_raw.paint_object;
-		context_raw.paint_object = plane;
-
-		mat4_set_from(context_raw.saved_camera, scene_camera.base.transform.local);
-		let m: mat4_t = mat4_identity();
-		mat4_translate(m, 0, 0, 1);
-		transform_set_matrix(scene_camera.base.transform, m);
-		let saved_fov: f32 = scene_camera.data.fov;
-		scene_camera.data.fov = 0.92;
-		viewport_update_camera_type(camera_type_t.PERSPECTIVE);
-		let light: light_object_t = scene_lights[0];
-		light.base.visible = false;
-		scene_world._.envmap = context_raw.preview_envmap;
-
-		// No resize
-		_render_path_last_w = UtilRender.decal_preview_size;
-		_render_path_last_h = UtilRender.decal_preview_size;
-		camera_object_build_proj(scene_camera);
-		camera_object_build_mat(scene_camera);
-
-		MakeMaterial.parse_mesh_preview_material();
-		let _commands: ()=>void = render_path_commands;
-		render_path_commands = RenderPathPreview.commands_decal;
-		render_path_render_frame();
-		render_path_commands = _commands;
-
-		context_raw.decal_preview = false;
-		_render_path_last_w = app_w();
-		_render_path_last_h = app_h();
-
-		// Restore
-		plane.base.visible = false;
-		scene_meshes = meshes;
-		context_raw.paint_object = painto;
-
-		transform_set_matrix(scene_camera.base.transform, context_raw.saved_camera);
-		scene_camera.data.fov = saved_fov;
-		viewport_update_camera_type(context_raw.camera_type);
-		camera_object_build_proj(scene_camera);
-		camera_object_build_mat(scene_camera);
-		light = scene_lights[0];
-		light.base.visible = true;
-		scene_world._.envmap = context_raw.show_envmap ? context_raw.saved_envmap : context_raw.empty_envmap;
-
-		MakeMaterial.parse_mesh_material();
-		context_raw.ddirty = 1; // Refresh depth for decal paint
-
-		if (g2_in_use) g2_begin(current);
-	}
-
-	static make_text_preview = () => {
-		let current: image_t = _g2_current;
-		if (current != null) g2_end();
-
-		let text: string = context_raw.text_tool_text;
-		let font: g2_font_t = context_raw.font.font;
-		let font_size: i32 = 200;
-		let text_w: i32 = Math.floor(g2_font_width(font, font_size, text));
-		let text_h: i32 = Math.floor(g2_font_height(font, font_size));
-		let texW: i32 = text_w + 32;
-		if (texW < 512) texW = 512;
-		if (context_raw.text_tool_image != null && context_raw.text_tool_image.width < texW) {
-			image_unload(context_raw.text_tool_image);
-			context_raw.text_tool_image = null;
-		}
-		if (context_raw.text_tool_image == null) {
-			///if krom_metal
-			context_raw.text_tool_image = image_create_render_target(texW, texW, tex_format_t.RGBA32);
-			///else
-			context_raw.text_tool_image = image_create_render_target(texW, texW, tex_format_t.R8);
-			///end
-		}
-		g2_begin(context_raw.text_tool_image);
-		g2_clear(0xff000000);
-		g2_set_font(font);
-		g2_set_font_size(font_size);
-		g2_set_color(0xffffffff);
-		g2_draw_string(text, texW / 2 - text_w / 2, texW / 2 - text_h / 2);
-		g2_end();
-
-		if (current != null) g2_begin(current);
-	}
-
-	static make_font_preview = () => {
-		let current: image_t = _g2_current;
-		if (current != null) g2_end();
-
-		let text: string = "Abg";
-		let font: g2_font_t = context_raw.font.font;
-		let font_size: i32 = 318;
-		let text_w: i32 = Math.floor(g2_font_width(font, font_size, text)) + 8;
-		let text_h: i32 = Math.floor(g2_font_height(font, font_size)) + 8;
-		if (context_raw.font.image == null) {
-			context_raw.font.image = image_create_render_target(512, 512, tex_format_t.RGBA32);
-		}
-		g2_begin(context_raw.font.image);
-		g2_clear(0x00000000);
-		g2_set_font(font);
-		g2_set_font_size(font_size);
-		g2_set_color(0xffffffff);
-		g2_draw_string(text, 512 / 2 - text_w / 2, 512 / 2 - text_h / 2);
-		g2_end();
-		context_raw.font.preview_ready = true;
-
-		if (current != null) g2_begin(current);
-	}
-
-	static make_brush_preview = () => {
-		if (RenderPathPaint.live_layer_locked) return;
-		context_raw.material_preview = true;
-
-		let current: image_t = _g2_current;
-		if (current != null) g2_end();
-
-		// Prepare layers
-		if (RenderPathPaint.live_layer == null) {
-			RenderPathPaint.live_layer = SlotLayer.create("_live");
-		}
-
-		let l: SlotLayerRaw = RenderPathPaint.live_layer;
-		SlotLayer.clear(l);
-
-		if (context_raw.brush.image == null) {
-			context_raw.brush.image = image_create_render_target(UtilRender.material_preview_size, UtilRender.material_preview_size);
-			context_raw.brush.image_icon = image_create_render_target(50, 50);
-		}
-
-		let _material: SlotMaterialRaw = context_raw.material;
-		context_raw.material = SlotMaterial.create();
-		let _tool: workspace_tool_t = context_raw.tool;
-		context_raw.tool = workspace_tool_t.BRUSH;
-
-		let _layer: SlotLayerRaw = context_raw.layer;
-		if (SlotLayer.is_mask(context_raw.layer)) {
-			context_raw.layer = context_raw.layer.parent;
-		}
-
-		let _fill_layer: SlotMaterialRaw = context_raw.layer.fill_layer;
-		context_raw.layer.fill_layer = null;
-
-		RenderPathPaint.use_live_layer(true);
-		MakeMaterial.parse_paint_material(false);
-
-		let hid: i32 = history_undo_i - 1 < 0 ? config_raw.undo_steps - 1 : history_undo_i - 1;
-		render_path_render_targets.set("texpaint_undo" + hid,render_path_render_targets.get("empty_black"));
-
-		// Set plane mesh
-		let painto: mesh_object_t = context_raw.paint_object;
-		let visibles: bool[] = [];
-		for (let p of project_paint_objects) {
-			visibles.push(p.base.visible);
-			p.base.visible = false;
-		}
-		let merged_object_visible: bool = false;
-		if (context_raw.merged_object != null) {
-			merged_object_visible = context_raw.merged_object.base.visible;
-			context_raw.merged_object.base.visible = false;
-		}
-
-		let cam: camera_object_t = scene_camera;
-		mat4_set_from(context_raw.saved_camera, cam.base.transform.local);
-		let saved_fov: f32 = cam.data.fov;
-		viewport_update_camera_type(camera_type_t.PERSPECTIVE);
-		let m: mat4_t = mat4_identity();
-		mat4_translate(m, 0, 0, 0.5);
-		transform_set_matrix(cam.base.transform, m);
-		cam.data.fov = 0.92;
-		camera_object_build_proj(cam);
-		camera_object_build_mat(cam);
-		mat4_get_inv(m, scene_camera.vp);
-
-		let planeo: mesh_object_t = scene_get_child(".Plane").ext;
-		planeo.base.visible = true;
-		context_raw.paint_object = planeo;
-
-		let v: vec4_t = vec4_create();
-		let sx: f32 = vec4_len(vec4_set(v, m.m[0], m.m[1], m.m[2]));
-		quat_from_euler(planeo.base.transform.rot, -Math.PI / 2, 0, 0);
-		vec4_set(planeo.base.transform.scale, sx, 1.0, sx);
-		vec4_set(planeo.base.transform.loc, m.m[12], -m.m[13], 0.0);
-		transform_build_matrix(planeo.base.transform);
-
-		RenderPathPaint.live_layer_drawn = 0;
-		RenderPathBase.draw_gbuffer();
-
-		// Paint brush preview
-		let _brush_radius: f32 = context_raw.brush_radius;
-		let _brush_opacity: f32 = context_raw.brush_opacity;
-		let _brush_hardness: f32 = context_raw.brush_hardness;
-		context_raw.brush_radius = 0.33;
-		context_raw.brush_opacity = 1.0;
-		context_raw.brush_hardness = 0.8;
-		let _x: f32 = context_raw.paint_vec.x;
-		let _y: f32 = context_raw.paint_vec.y;
-		let _last_x: f32 = context_raw.last_paint_vec_x;
-		let _last_y: f32 = context_raw.last_paint_vec_y;
-		let _pdirty: i32 = context_raw.pdirty;
-		context_raw.pdirty = 2;
-
-		let points_x: f32[] = [0.2, 0.2,  0.35, 0.5,  0.5, 0.5,  0.65, 0.8,  0.8, 0.8];
-		let points_y: f32[] = [0.5, 0.5,  0.35 - 0.04, 0.2 - 0.08,  0.4 + 0.015, 0.6 + 0.03,  0.45 - 0.025, 0.3 - 0.05,  0.5 + 0.025, 0.7 + 0.05];
-		for (let i: i32 = 1; i < points_x.length; ++i) {
-			context_raw.last_paint_vec_x = points_x[i - 1];
-			context_raw.last_paint_vec_y = points_y[i - 1];
-			context_raw.paint_vec.x = points_x[i];
-			context_raw.paint_vec.y = points_y[i];
-			RenderPathPaint.commands_paint(false);
-		}
-
-		context_raw.brush_radius = _brush_radius;
-		context_raw.brush_opacity = _brush_opacity;
-		context_raw.brush_hardness = _brush_hardness;
-		context_raw.paint_vec.x = _x;
-		context_raw.paint_vec.y = _y;
-		context_raw.last_paint_vec_x = _last_x;
-		context_raw.last_paint_vec_y = _last_y;
-		context_raw.prev_paint_vec_x = -1;
-		context_raw.prev_paint_vec_y = -1;
-		context_raw.pdirty = _pdirty;
-		RenderPathPaint.use_live_layer(false);
-		context_raw.layer.fill_layer = _fill_layer;
-		context_raw.layer = _layer;
-		context_raw.material = _material;
-		context_raw.tool = _tool;
-		let _init = () => {
-			MakeMaterial.parse_paint_material(false);
-		}
-		app_notify_on_init(_init);
-
-		// Restore paint mesh
-		context_raw.material_preview = false;
-		planeo.base.visible = false;
-		for (let i: i32 = 0; i < project_paint_objects.length; ++i) {
-			project_paint_objects[i].base.visible = visibles[i];
-		}
-		if (context_raw.merged_object != null) {
-			context_raw.merged_object.base.visible = merged_object_visible;
-		}
-		context_raw.paint_object = painto;
-		transform_set_matrix(scene_camera.base.transform, context_raw.saved_camera);
-		scene_camera.data.fov = saved_fov;
-		viewport_update_camera_type(context_raw.camera_type);
-		camera_object_build_proj(scene_camera);
-		camera_object_build_mat(scene_camera);
-
-		// Scale layer down to to image preview
-		if (base_pipe_merge == null) base_make_pipe();
-		l = RenderPathPaint.live_layer;
-		let target: image_t = context_raw.brush.image;
-		g2_begin(target);
-		g2_clear(0x00000000);
-		g2_set_pipeline(base_pipe_copy);
-		g2_draw_scaled_image(l.texpaint, 0, 0, target.width, target.height);
-		g2_set_pipeline(null);
-		g2_end();
-
-		// Scale image preview down to to icon
-		render_path_render_targets.get("texpreview")._image = context_raw.brush.image;
-		render_path_render_targets.get("texpreview_icon")._image = context_raw.brush.image_icon;
-		render_path_set_target("texpreview_icon");
-		render_path_bind_target("texpreview", "tex");
-		render_path_draw_shader("shader_datas/supersample_resolve/supersample_resolve");
-
-		context_raw.brush.preview_ready = true;
-		context_raw.brush_blend_dirty = true;
-
-		if (current != null) g2_begin(current);
-	}
-
-	static make_node_preview = (canvas: zui_node_canvas_t, node: zui_node_t, image: image_t, group: zui_node_canvas_t = null, parents: zui_node_t[] = null) => {
-		let res: any = MakeMaterial.parse_node_preview_material(node, group, parents);
-		if (res == null || res.scon == null) return;
-
-		if (UtilRender.screen_aligned_full_vb == null) {
-			UtilRender.create_screen_aligned_full_data();
-		}
-
-		let _scale_world: f32 = context_raw.paint_object.base.transform.scale_world;
-		context_raw.paint_object.base.transform.scale_world = 3.0;
-		transform_build_matrix(context_raw.paint_object.base.transform);
-
-		g4_begin(image);
-		g4_set_pipeline(res.scon._.pipe_state);
-		uniforms_set_context_consts(res.scon, [""]);
-		uniforms_set_obj_consts(res.scon, context_raw.paint_object.base);
-		uniforms_set_material_consts(res.scon, res.mcon);
-		g4_set_vertex_buffer(UtilRender.screen_aligned_full_vb);
-		g4_set_index_buffer(UtilRender.screen_aligned_full_ib);
-		g4_draw();
-		g4_end();
-
-		context_raw.paint_object.base.transform.scale_world = _scale_world;
-		transform_build_matrix(context_raw.paint_object.base.transform);
-	}
-
-	static pick_pos_nor_tex = () => {
-		context_raw.pick_pos_nor_tex = true;
-		context_raw.pdirty = 1;
-		let _tool: workspace_tool_t = context_raw.tool;
-		context_raw.tool = workspace_tool_t.PICKER;
-		MakeMaterial.parse_paint_material();
-		if (context_raw.paint2d) {
-			RenderPathPaint.set_plane_mesh();
-		}
-		RenderPathPaint.commands_paint(false);
-		///if krom_metal
-		// Flush command list
-		RenderPathPaint.commands_paint(false);
-		///end
-		if (context_raw.paint2d) {
-			RenderPathPaint.restore_plane_mesh();
-		}
-		context_raw.tool = _tool;
-		context_raw.pick_pos_nor_tex = false;
-		MakeMaterial.parse_paint_material();
-		context_raw.pdirty = 0;
-	}
-
-	static get_decal_mat = (): mat4_t => {
-		UtilRender.pick_pos_nor_tex();
-		let decal_mat: mat4_t = mat4_identity();
-		let loc: vec4_t = vec4_create(context_raw.posx_picked, context_raw.posy_picked, context_raw.posz_picked);
-		let rot: quat_t = quat_from_to(quat_create(), vec4_create(0.0, 0.0, -1.0), vec4_create(context_raw.norx_picked, context_raw.nory_picked, context_raw.norz_picked));
-		let scale: vec4_t = vec4_create(context_raw.brush_radius * 0.5, context_raw.brush_radius * 0.5, context_raw.brush_radius * 0.5);
-		mat4_compose(decal_mat, loc, rot, scale);
-		return decal_mat;
-	}
-
-	static create_screen_aligned_full_data = () => {
-		// Over-sized triangle
-		let data: f32[] = [-Math.floor(32767 / 3), -Math.floor(32767 / 3), 0, 32767, 0, 0, 0, 0, 0, 0, 0, 0,
-					 	    32767,                 -Math.floor(32767 / 3), 0, 32767, 0, 0, 0, 0, 0, 0, 0, 0,
-						   -Math.floor(32767 / 3),  32767,                 0, 32767, 0, 0, 0, 0, 0, 0, 0, 0];
-		let indices: i32[] = [0, 1, 2];
-
-		// Mandatory vertex data names and sizes
-		let structure: vertex_struct_t = g4_vertex_struct_create();
-		g4_vertex_struct_add(structure, "pos", vertex_data_t.I16_4X_NORM);
-		g4_vertex_struct_add(structure, "nor", vertex_data_t.I16_2X_NORM);
-		g4_vertex_struct_add(structure, "tex", vertex_data_t.I16_2X_NORM);
-		g4_vertex_struct_add(structure, "col", vertex_data_t.I16_4X_NORM);
-		UtilRender.screen_aligned_full_vb = g4_vertex_buffer_create(Math.floor(data.length / Math.floor(g4_vertex_struct_byte_size(structure) / 4)), structure, usage_t.STATIC);
-		let vertices: buffer_view_t = g4_vertex_buffer_lock(UtilRender.screen_aligned_full_vb);
-		for (let i: i32 = 0; i < Math.floor(vertices.byteLength / 2); ++i) vertices.setInt16(i * 2, data[i], true);
-		g4_vertex_buffer_unlock(UtilRender.screen_aligned_full_vb);
-
-		UtilRender.screen_aligned_full_ib = g4_index_buffer_create(indices.length);
-		let id: u32_array_t = g4_index_buffer_lock(UtilRender.screen_aligned_full_ib);
-		for (let i: i32 = 0; i < id.length; ++i) id[i] = indices[i];
-		g4_index_buffer_unlock(UtilRender.screen_aligned_full_ib);
-	}
-}
-
-///end

+ 0 - 190
base/Sources/UtilUV.ts

@@ -1,190 +0,0 @@
-
-///if (is_paint || is_sculpt)
-
-class UtilUV {
-
-	static uvmap: image_t = null;
-	static uvmap_cached: bool = false;
-	static trianglemap: image_t = null;
-	static trianglemap_cached: bool = false;
-	static dilatemap: image_t = null;
-	static dilatemap_cached: bool = false;
-	static uvislandmap: image_t = null;
-	static uvislandmap_cached: bool = false;
-	static dilate_bytes: ArrayBuffer = null;
-	static pipe_dilate: pipeline_t = null;
-
-	static cache_uv_map = () => {
-		if (UtilUV.uvmap != null && (UtilUV.uvmap.width != config_get_texture_res_x() || UtilUV.uvmap.height != config_get_texture_res_y())) {
-			image_unload(UtilUV.uvmap);
-			UtilUV.uvmap = null;
-			UtilUV.uvmap_cached = false;
-		}
-
-		if (UtilUV.uvmap_cached) return;
-
-		let res_x: i32 = config_get_texture_res_x();
-		let res_y: i32 = config_get_texture_res_y();
-		if (UtilUV.uvmap == null) {
-			UtilUV.uvmap = image_create_render_target(res_x, res_y);
-		}
-
-		UtilUV.uvmap_cached = true;
-		let merged: mesh_object_t = context_raw.merged_object;
-		let mesh: mesh_data_t = (context_raw.layer_filter == 0 && merged != null) ?
-					merged.data : context_raw.paint_object.data;
-
-		let texa: i16_array_t = mesh.vertex_arrays[2].values;
-		let inda: u32_array_t = mesh.index_arrays[0].values;
-		g2_begin(UtilUV.uvmap);
-		g2_clear(0x00000000);
-		g2_set_color(0xffcccccc);
-		let strength: f32 = res_x > 2048 ? 2.0 : 1.0;
-		let f: f32 = (1 / 32767) * UtilUV.uvmap.width;
-		for (let i: i32 = 0; i < Math.floor(inda.length / 3); ++i) {
-			let x1: f32 = (texa[inda[i * 3    ] * 2    ]) * f;
-			let x2: f32 = (texa[inda[i * 3 + 1] * 2    ]) * f;
-			let x3: f32 = (texa[inda[i * 3 + 2] * 2    ]) * f;
-			let y1: f32 = (texa[inda[i * 3    ] * 2 + 1]) * f;
-			let y2: f32 = (texa[inda[i * 3 + 1] * 2 + 1]) * f;
-			let y3: f32 = (texa[inda[i * 3 + 2] * 2 + 1]) * f;
-			g2_draw_line(x1, y1, x2, y2, strength);
-			g2_draw_line(x2, y2, x3, y3, strength);
-			g2_draw_line(x3, y3, x1, y1, strength);
-		}
-		g2_end();
-	}
-
-	static cache_triangle_map = () => {
-		if (UtilUV.trianglemap != null && (UtilUV.trianglemap.width != config_get_texture_res_x() || UtilUV.trianglemap.height != config_get_texture_res_y())) {
-			image_unload(UtilUV.trianglemap);
-			UtilUV.trianglemap = null;
-			UtilUV.trianglemap_cached = false;
-		}
-
-		if (UtilUV.trianglemap_cached) return;
-
-		if (UtilUV.trianglemap == null) {
-			UtilUV.trianglemap = image_create_render_target(config_get_texture_res_x(), config_get_texture_res_y());
-		}
-
-		UtilUV.trianglemap_cached = true;
-		let merged: mesh_data_t = context_raw.merged_object != null ? context_raw.merged_object.data : context_raw.paint_object.data;
-		let mesh: mesh_data_t = merged;
-		let texa: i16_array_t = mesh.vertex_arrays[2].values;
-		let inda: u32_array_t = mesh.index_arrays[0].values;
-		g2_begin(UtilUV.trianglemap);
-		g2_clear(0xff000000);
-		let f: f32 = (1 / 32767) * UtilUV.trianglemap.width;
-		let color: i32 = 0xff000001;
-		for (let i: i32 = 0; i < Math.floor(inda.length / 3); ++i) {
-			if (color == 0xffffffff) color = 0xff000001;
-			color++;
-			g2_set_color(color);
-			let x1: f32 = (texa[inda[i * 3    ] * 2    ]) * f;
-			let x2: f32 = (texa[inda[i * 3 + 1] * 2    ]) * f;
-			let x3: f32 = (texa[inda[i * 3 + 2] * 2    ]) * f;
-			let y1: f32 = (texa[inda[i * 3    ] * 2 + 1]) * f;
-			let y2: f32 = (texa[inda[i * 3 + 1] * 2 + 1]) * f;
-			let y3: f32 = (texa[inda[i * 3 + 2] * 2 + 1]) * f;
-			g2_fill_triangle(x1, y1, x2, y2, x3, y3);
-		}
-		g2_end();
-	}
-
-	static cache_dilate_map = () => {
-		if (UtilUV.dilatemap != null && (UtilUV.dilatemap.width != config_get_texture_res_x() || UtilUV.dilatemap.height != config_get_texture_res_y())) {
-			image_unload(UtilUV.dilatemap);
-			UtilUV.dilatemap = null;
-			UtilUV.dilatemap_cached = false;
-		}
-
-		if (UtilUV.dilatemap_cached) return;
-
-		if (UtilUV.dilatemap == null) {
-			UtilUV.dilatemap = image_create_render_target(config_get_texture_res_x(), config_get_texture_res_y(), tex_format_t.R8);
-		}
-
-		if (UtilUV.pipe_dilate == null) {
-			UtilUV.pipe_dilate = g4_pipeline_create();
-			UtilUV.pipe_dilate.vertex_shader = sys_get_shader("dilate_map.vert");
-			UtilUV.pipe_dilate.fragment_shader = sys_get_shader("dilate_map.frag");
-			let vs: vertex_struct_t = g4_vertex_struct_create();
-			///if (krom_metal || krom_vulkan)
-			g4_vertex_struct_add(vs, "tex", vertex_data_t.I16_2X_NORM);
-			///else
-			g4_vertex_struct_add(vs, "pos", vertex_data_t.I16_4X_NORM);
-			g4_vertex_struct_add(vs, "nor", vertex_data_t.I16_2X_NORM);
-			g4_vertex_struct_add(vs, "tex", vertex_data_t.I16_2X_NORM);
-			///end
-			UtilUV.pipe_dilate.input_layout = [vs];
-			UtilUV.pipe_dilate.depth_write = false;
-			UtilUV.pipe_dilate.depth_mode = compare_mode_t.ALWAYS;
-			UtilUV.pipe_dilate.color_attachments[0] = tex_format_t.R8;
-			g4_pipeline_compile(UtilUV.pipe_dilate);
-			// dilateTexUnpack = getConstantLocation(UtilUV.pipeDilate, "texUnpack");
-		}
-
-		let mask: i32 = context_object_mask_used() ? SlotLayer.get_object_mask(context_raw.layer) : 0;
-		if (context_layer_filter_used()) mask = context_raw.layer_filter;
-		let geom: mesh_data_t = mask == 0 && context_raw.merged_object != null ? context_raw.merged_object.data : context_raw.paint_object.data;
-		g4_begin(UtilUV.dilatemap);
-		g4_clear(0x00000000);
-		g4_set_pipeline(UtilUV.pipe_dilate);
-		///if (krom_metal || krom_vulkan)
-		g4_set_vertex_buffer(mesh_data_get(geom, [{name: "tex", data: "short2norm"}]));
-		///else
-		g4_set_vertex_buffer(geom._.vertex_buffer);
-		///end
-		g4_set_index_buffer(geom._.index_buffers[0]);
-		g4_draw();
-		g4_end();
-		UtilUV.dilatemap_cached = true;
-		UtilUV.dilate_bytes = null;
-	}
-
-	static cache_uv_island_map = () => {
-		UtilUV.cache_dilate_map();
-		if (UtilUV.dilate_bytes == null) {
-			UtilUV.dilate_bytes = image_get_pixels(UtilUV.dilatemap);
-		}
-		UtilRender.pick_pos_nor_tex();
-		let w: i32 = 2048; // config_get_texture_res_x()
-		let h: i32 = 2048; // config_get_texture_res_y()
-		let x: i32 = Math.floor(context_raw.uvx_picked * w);
-		let y: i32 = Math.floor(context_raw.uvy_picked * h);
-		let bytes: ArrayBuffer = new ArrayBuffer(w * h);
-		let view: DataView = new DataView(bytes);
-		let coords: coord_t[] = [{ x: x, y: y }];
-		let r: i32 = Math.floor(UtilUV.dilatemap.width / w);
-
-		let check = (c: coord_t) => {
-			if (c.x < 0 || c.x >= w || c.y < 0 || c.y >= h) return;
-			if (view.getUint8(c.y * w + c.x) == 255) return;
-			let dilate_view: DataView = new DataView(UtilUV.dilate_bytes);
-			if (dilate_view.getUint8(c.y * r * UtilUV.dilatemap.width + c.x * r) == 0) return;
-			view.setUint8(c.y * w + c.x, 255);
-			coords.push({ x: c.x + 1, y: c.y });
-			coords.push({ x: c.x - 1, y: c.y });
-			coords.push({ x: c.x, y: c.y + 1 });
-			coords.push({ x: c.x, y: c.y - 1 });
-		}
-
-		while (coords.length > 0) {
-			check(coords.pop());
-		}
-
-		if (UtilUV.uvislandmap != null) {
-			image_unload(UtilUV.uvislandmap);
-		}
-		UtilUV.uvislandmap = image_from_bytes(bytes, w, h, tex_format_t.R8);
-		UtilUV.uvislandmap_cached = true;
-	}
-}
-
-type coord_t = {
-	x?: i32;
-	y?: i32;
-}
-
-///end

+ 3 - 3
base/Sources/args.ts

@@ -86,7 +86,7 @@ function args_run() {
 				ImportAsset.run(args_asset_path, -1, -1, false);
 				///if is_paint
 				if (path_is_texture(args_asset_path)) {
-					UIBase.show_2d_view(view_2d_type_t.ASSET);
+					ui_base_show_2d_view(view_2d_type_t.ASSET);
 				}
 				///end
 			}
@@ -143,7 +143,7 @@ function args_run() {
 						}
 
 						let blob: ArrayBuffer = data_get_blob(file);
-						BoxExport.preset = JSON.parse(sys_buffer_to_string(blob));
+						BoxExport.preset = json_parse(sys_buffer_to_string(blob));
 						data_delete_blob("export_presets/" + file);
 
 						// Export queue
@@ -164,7 +164,7 @@ function args_run() {
 			///if (is_paint || is_sculpt)
 			else if (args_export_mesh) {
 				if (path_is_folder(args_export_mesh_path)) {
-					let f: string = UIFiles.filename;
+					let f: string = ui_files_filename;
 					if (f == "") f = tr("untitled");
 					ExportMesh.run(args_export_mesh_path + path_sep + f, null, false);
 				}

+ 105 - 104
base/Sources/base.ts

@@ -218,7 +218,7 @@ function base_init() {
 	base_default_element_w = base_theme.ELEMENT_W;
 	base_default_font_size = base_theme.FONT_SIZE;
 	translator_load_translations(config_raw.locale);
-	UIFiles.filename = tr("untitled");
+	ui_files_filename = tr("untitled");
 	///if (krom_android || krom_ios)
 	sys_title_set(tr("untitled"));
 	///end
@@ -248,38 +248,38 @@ function base_init() {
 	args_parse();
 
 	camera_init();
-	new UIBase();
-	new UINodes();
-	new UIView2D();
+	ui_base_init();
+	ui_nodes_init();
+	ui_view2d_init();
 
 	///if is_lab
-	RandomNode.setSeed(Math.floor(time_time() * 4294967295));
+	RandomNode.setSeed(math_floor(time_time() * 4294967295));
 	///end
 
 	app_notify_on_update(base_update);
-	app_notify_on_render_2d(UIView2D.render);
-	app_notify_on_update(UIView2D.update);
+	app_notify_on_render_2d(ui_view2d_render);
+	app_notify_on_update(ui_view2d_update);
 	///if (is_paint || is_sculpt)
-	app_notify_on_render_2d(UIBase.render_cursor);
+	app_notify_on_render_2d(ui_base_render_cursor);
 	///end
-	app_notify_on_update(UINodes.update);
-	app_notify_on_render_2d(UINodes.render);
-	app_notify_on_update(UIBase.update);
-	app_notify_on_render_2d(UIBase.render);
+	app_notify_on_update(ui_nodes_update);
+	app_notify_on_render_2d(ui_nodes_render);
+	app_notify_on_update(ui_base_update);
+	app_notify_on_render_2d(ui_base_render);
 	app_notify_on_update(camera_update);
 	app_notify_on_render_2d(base_render);
 
 	///if (is_paint || is_sculpt)
-	base_appx = UIToolbar.toolbar_w;
+	base_appx = ui_toolbar_w;
 	///end
 	///if is_lab
 	base_appx = 0;
 	///end
 
-	base_appy = UIHeader.headerh;
-	if (config_raw.layout[layout_size_t.HEADER] == 1) base_appy += UIHeader.headerh;
+	base_appy = ui_header_h;
+	if (config_raw.layout[layout_size_t.HEADER] == 1) base_appy += ui_header_h;
 	let cam: camera_object_t = scene_camera;
-	cam.data.fov = Math.floor(cam.data.fov * 100) / 100;
+	cam.data.fov = math_floor(cam.data.fov * 100) / 100;
 	camera_object_build_proj(cam);
 
 	args_run();
@@ -305,33 +305,33 @@ function base_save_and_quit_callback(save: bool) {
 function base_w(): i32 {
 	// Drawing material preview
 	if (context_raw.material_preview) {
-		return UtilRender.material_preview_size;
+		return util_render_material_preview_size;
 	}
 
 	// Drawing decal preview
 	if (context_raw.decal_preview) {
-		return UtilRender.decal_preview_size;
+		return util_render_decal_preview_size;
 	}
 
 	let res: i32 = 0;
 	if (config_raw.layout == null) {
-		let sidebarw: i32 = UIBase.default_sidebar_w;
-		res = sys_width() - sidebarw - UIToolbar.default_toolbar_w;
+		let sidebarw: i32 = ui_base_default_sidebar_w;
+		res = sys_width() - sidebarw - ui_toolbar_default_w;
 	}
-	else if (UINodes.show || UIView2D.show) {
-		res = sys_width() - config_raw.layout[layout_size_t.SIDEBAR_W] - config_raw.layout[layout_size_t.NODES_W] - UIToolbar.toolbar_w;
+	else if (ui_nodes_show || ui_view2d_show) {
+		res = sys_width() - config_raw.layout[layout_size_t.SIDEBAR_W] - config_raw.layout[layout_size_t.NODES_W] - ui_toolbar_w;
 	}
-	else if (UIBase.show) {
-		res = sys_width() - config_raw.layout[layout_size_t.SIDEBAR_W] - UIToolbar.toolbar_w;
+	else if (ui_base_show) {
+		res = sys_width() - config_raw.layout[layout_size_t.SIDEBAR_W] - ui_toolbar_w;
 	}
 	else { // Distract free
 		res = sys_width();
 	}
 	if (context_raw.view_index > -1) {
-		res = Math.floor(res / 2);
+		res = math_floor(res / 2);
 	}
 	if (context_raw.paint2d_view) {
-		res = UIView2D.ww;
+		res = ui_view2d_ww;
 	}
 
 	return res > 0 ? res : 1; // App was minimized, force render path resize
@@ -340,18 +340,18 @@ function base_w(): i32 {
 function base_h(): i32 {
 	// Drawing material preview
 	if (context_raw.material_preview) {
-		return UtilRender.material_preview_size;
+		return util_render_material_preview_size;
 	}
 
 	// Drawing decal preview
 	if (context_raw.decal_preview) {
-		return UtilRender.decal_preview_size;
+		return util_render_decal_preview_size;
 	}
 
 	let res: i32 = sys_height();
 
 	if (config_raw.layout == null) {
-		res -= UIHeader.default_header_h * 2 + UIStatus.default_status_h;
+		res -= ui_header_default_h * 2 + ui_status_default_status_h;
 
 		///if (krom_android || krom_ios)
 		let layout_header: i32 = 0;
@@ -359,15 +359,15 @@ function base_h(): i32 {
 		let layout_header: i32 = 1;
 		///end
 		if (layout_header == 0) {
-			res += UIHeader.headerh;
+			res += ui_header_h;
 		}
 	}
-	else if (UIBase.show && res > 0) {
+	else if (ui_base_show && res > 0) {
 		let statush: i32 = config_raw.layout[layout_size_t.STATUS_H];
-		res -= Math.floor(UIHeader.default_header_h * 2 * config_raw.window_scale) + statush;
+		res -= math_floor(ui_header_default_h * 2 * config_raw.window_scale) + statush;
 
 		if (config_raw.layout[layout_size_t.HEADER] == 0) {
-			res += UIHeader.headerh;
+			res += ui_header_h;
 		}
 	}
 
@@ -381,7 +381,7 @@ function base_w(): i32 {
 	if (UINodes == null) {
 		res = sys_width();
 	}
-	else if (UINodes.show || UIView2D.show) {
+	else if (ui_nodes_show || ui_view2d_show) {
 		res = sys_width() - config_raw.layout[layout_size_t.NODES_W];
 	}
 	else { // Distract free
@@ -394,11 +394,11 @@ function base_w(): i32 {
 function base_h(): i32 {
 	let res: i32 = sys_height();
 	if (UIBase == null) {
-		res -= UIHeader.default_header_h * 2 + UIStatus.default_status_h;
+		res -= ui_header_default_h * 2 + ui_status_default_status_h;
 	}
 	else if (res > 0) {
 		let statush: i32 = config_raw.layout[layout_size_t.STATUS_H];
-		res -= Math.floor(UIHeader.default_header_h * 2 * config_raw.window_scale) + statush;
+		res -= math_floor(ui_header_default_h * 2 * config_raw.window_scale) + statush;
 	}
 
 	return res > 0 ? res : 1; // App was minimized, force render path resize
@@ -426,9 +426,9 @@ function base_on_resize() {
 	let ratio_h: f32 = sys_height() / base_last_window_height;
 	base_last_window_height = sys_height();
 
-	config_raw.layout[layout_size_t.NODES_W] = Math.floor(config_raw.layout[layout_size_t.NODES_W] * ratio_w);
+	config_raw.layout[layout_size_t.NODES_W] = math_floor(config_raw.layout[layout_size_t.NODES_W] * ratio_w);
 	///if (is_paint || is_sculpt)
-	config_raw.layout[layout_size_t.SIDEBAR_H0] = Math.floor(config_raw.layout[layout_size_t.SIDEBAR_H0] * ratio_h);
+	config_raw.layout[layout_size_t.SIDEBAR_H0] = math_floor(config_raw.layout[layout_size_t.SIDEBAR_H0] * ratio_h);
 	config_raw.layout[layout_size_t.SIDEBAR_H1] = sys_height() - config_raw.layout[layout_size_t.SIDEBAR_H0];
 	///end
 
@@ -465,16 +465,16 @@ function base_resize() {
 
 	context_raw.ddirty = 2;
 
-	if (UIBase.show) {
+	if (ui_base_show) {
 		///if (is_paint || is_sculpt)
-		base_appx = UIToolbar.toolbar_w;
+		base_appx = ui_toolbar_w;
 		///end
 		///if is_lab
 		base_appx = 0;
 		///end
-		base_appy = UIHeader.headerh * 2;
+		base_appy = ui_header_h * 2;
 		if (config_raw.layout[layout_size_t.HEADER] == 0) {
-			base_appy -= UIHeader.headerh;
+			base_appy -= ui_header_h;
 		}
 	}
 	else {
@@ -482,31 +482,31 @@ function base_resize() {
 		base_appy = 0;
 	}
 
-	if (UINodes.grid != null) {
-		let _grid: image_t = UINodes.grid;
+	if (ui_nodes_grid != null) {
+		let _grid: image_t = ui_nodes_grid;
 		let _next = function() {
 			image_unload(_grid);
 		}
 		base_notify_on_next_frame(_next);
-		UINodes.grid = null;
+		ui_nodes_grid = null;
 	}
 
 	base_redraw_ui();
 }
 
 function base_redraw_ui() {
-	UIHeader.header_handle.redraws = 2;
-	UIBase.hwnds[tab_area_t.STATUS].redraws = 2;
-	UIMenubar.menu_handle.redraws = 2;
-	UIMenubar.workspace_handle.redraws = 2;
-	UINodes.hwnd.redraws = 2;
-	UIBox.hwnd.redraws = 2;
-	UIView2D.hwnd.redraws = 2;
+	ui_header_handle.redraws = 2;
+	ui_base_hwnds[tab_area_t.STATUS].redraws = 2;
+	ui_menubar_menu_handle.redraws = 2;
+	ui_menubar_workspace_handle.redraws = 2;
+	ui_nodes_hwnd.redraws = 2;
+	ui_box_hwnd.redraws = 2;
+	ui_view2d_hwnd.redraws = 2;
 	if (context_raw.ddirty < 0) context_raw.ddirty = 0; // Redraw viewport
 	///if (is_paint || is_sculpt)
-	UIBase.hwnds[tab_area_t.SIDEBAR0].redraws = 2;
-	UIBase.hwnds[tab_area_t.SIDEBAR1].redraws = 2;
-	UIToolbar.toolbar_handle.redraws = 2;
+	ui_base_hwnds[tab_area_t.SIDEBAR0].redraws = 2;
+	ui_base_hwnds[tab_area_t.SIDEBAR1].redraws = 2;
+	ui_toolbar_handle.redraws = 2;
 	if (context_raw.split_view) context_raw.ddirty = 1;
 	///end
 }
@@ -533,7 +533,7 @@ function base_update() {
 		if (mouse_released()) {
 			base_drag_start = 0;
 		}
-		let moved: bool = Math.abs(mouse_movement_x) > 1 && Math.abs(mouse_movement_y) > 1;
+		let moved: bool = math_abs(mouse_movement_x) > 1 && math_abs(mouse_movement_y) > 1;
 		if ((mouse_released() || moved) && !has_drag) {
 			base_drag_asset = null;
 			base_drag_swatch = null;
@@ -555,7 +555,7 @@ function base_update() {
 	if (mouse_released() && has_drag) {
 		if (base_drag_asset != null) {
 			if (context_in_nodes()) { // Create image texture
-				UINodes.accept_asset_drag(project_assets.indexOf(base_drag_asset));
+				ui_nodes_accept_asset_drag(project_assets.indexOf(base_drag_asset));
 			}
 			else if (context_in_viewport()) {
 				if (base_drag_asset.file.toLowerCase().endsWith(".hdr")) {
@@ -572,7 +572,7 @@ function base_update() {
 		}
 		else if (base_drag_swatch != null) {
 			if (context_in_nodes()) { // Create RGB node
-				UINodes.accept_swatch_drag(base_drag_swatch);
+				ui_nodes_accept_swatch_drag(base_drag_swatch);
 			}
 			else if (context_in_swatches()) {
 				TabSwatches.accept_swatch_drag(base_drag_swatch);
@@ -624,7 +624,7 @@ function base_update() {
 		}
 		else if (base_drag_layer != null) {
 			if (context_in_nodes()) {
-				UINodes.accept_layer_drag(project_layers.indexOf(base_drag_layer));
+				ui_nodes_accept_layer_drag(project_layers.indexOf(base_drag_layer));
 			}
 			else if (context_in_layers() && base_is_dragging) {
 				SlotLayer.move(base_drag_layer, context_raw.drag_dest);
@@ -649,12 +649,12 @@ function base_update() {
 	let is_picker: bool = context_raw.tool == workspace_tool_t.PICKER || context_raw.tool == workspace_tool_t.MATERIAL;
 	let decal: bool = context_raw.tool == workspace_tool_t.DECAL || context_raw.tool == workspace_tool_t.TEXT;
 	zui_set_always_redraw_window(!context_raw.cache_draws ||
-		UIMenu.show ||
-		UIBox.show ||
+		ui_menu_show ||
+		ui_box_show ||
 		base_is_dragging ||
 		is_picker ||
 		decal ||
-		UIView2D.show ||
+		ui_view2d_show ||
 		!config_raw.brush_3d ||
 		context_raw.frame < 3);
 	///end
@@ -668,16 +668,16 @@ function base_material_dropped() {
 	// Material drag and dropped onto viewport or layers tab
 	if (context_in_viewport()) {
 		let uv_type: uv_type_t = keyboard_down("control") ? uv_type_t.PROJECT : uv_type_t.UVMAP;
-		let decal_mat: mat4_t = uv_type == uv_type_t.PROJECT ? UtilRender.get_decal_mat() : null;
+		let decal_mat: mat4_t = uv_type == uv_type_t.PROJECT ? util_render_get_decal_mat() : null;
 		base_create_fill_layer(uv_type, decal_mat);
 	}
 	if (context_in_layers() && TabLayers.can_drop_new_layer(context_raw.drag_dest)) {
 		let uv_type: uv_type_t = keyboard_down("control") ? uv_type_t.PROJECT : uv_type_t.UVMAP;
-		let decal_mat: mat4_t = uv_type == uv_type_t.PROJECT ? UtilRender.get_decal_mat() : null;
+		let decal_mat: mat4_t = uv_type == uv_type_t.PROJECT ? util_render_get_decal_mat() : null;
 		base_create_fill_layer(uv_type, decal_mat, context_raw.drag_dest);
 	}
 	else if (context_in_nodes()) {
-		UINodes.accept_material_drag(project_materials.indexOf(base_drag_material));
+		ui_nodes_accept_material_drag(project_materials.indexOf(base_drag_material));
 	}
 	base_drag_material = null;
 }
@@ -725,7 +725,7 @@ function base_get_drag_image(): image_t {
 		if (base_drag_file_icon != null) return base_drag_file_icon;
 		let icons: image_t = resource_get("icons.k");
 		base_drag_rect = base_drag_file.indexOf(".") > 0 ? resource_tile50(icons, 3, 1) : resource_tile50(icons, 2, 1);
-		base_drag_tint = UIBase.ui.t.HIGHLIGHT_COL;
+		base_drag_tint = ui_base_ui.t.HIGHLIGHT_COL;
 		return icons;
 	}
 
@@ -738,7 +738,7 @@ function base_get_drag_image(): image_t {
 		let folder_closed: rect_t = resource_tile50(icons, 2, 1);
 		let folder_open: rect_t = resource_tile50(icons, 8, 1);
 		base_drag_rect = base_drag_layer.show_panel ? folder_open : folder_closed;
-		base_drag_tint = UIBase.ui.t.LABEL_COL - 0x00202020;
+		base_drag_tint = ui_base_ui.t.LABEL_COL - 0x00202020;
 		return icons;
 	}
 	if (base_drag_layer != null && SlotLayer.is_mask(base_drag_layer) && base_drag_layer.fill_layer == null) {
@@ -758,8 +758,8 @@ function base_render() {
 
 	if (context_raw.frame == 2) {
 		///if (is_paint || is_sculpt)
-		UtilRender.make_material_preview();
-		UIBase.hwnds[tab_area_t.SIDEBAR1].redraws = 2;
+		util_render_make_material_preview();
+		ui_base_hwnds[tab_area_t.SIDEBAR1].redraws = 2;
 		///end
 
 		MakeMaterial.parse_mesh_material();
@@ -778,9 +778,9 @@ function base_render() {
 
 		// Default workspace
 		if (config_raw.workspace != 0) {
-			UIHeader.worktab.position = config_raw.workspace;
-			UIMenubar.workspace_handle.redraws = 2;
-			UIHeader.worktab.changed = true;
+			ui_header_worktab.position = config_raw.workspace;
+			ui_menubar_workspace_handle.redraws = 2;
+			ui_header_worktab.changed = true;
 		}
 
 		// Default camera controls
@@ -813,7 +813,7 @@ function base_render() {
 		let img: image_t = base_get_drag_image();
 
 		///if (is_paint || is_sculpt)
-		let scale_factor: f32 = zui_SCALE(UIBase.ui);
+		let scale_factor: f32 = zui_SCALE(ui_base_ui);
 		///end
 		///if is_lab
 		let scale_factor: f32 = zui_SCALE(base_ui_box);
@@ -844,10 +844,10 @@ function base_render() {
 		g2_set_color(0xffffffff);
 	}
 
-	let using_menu: bool = UIMenu.show && mouse_y > UIHeader.headerh;
-	base_ui_enabled = !UIBox.show && !using_menu && !base_is_combo_selected();
-	if (UIBox.show) UIBox.render();
-	if (UIMenu.show) UIMenu.render();
+	let using_menu: bool = ui_menu_show && mouse_y > ui_header_h;
+	base_ui_enabled = !ui_box_show && !using_menu && !base_is_combo_selected();
+	if (ui_box_show) ui_box_render();
+	if (ui_menu_show) ui_menu_render();
 
 	// Save last pos for continuos paint
 	context_raw.last_paint_vec_x = context_raw.paint_vec.x;
@@ -935,7 +935,7 @@ function base_is_combo_selected(): bool {
 }
 
 function base_get_uis(): zui_t[] {
-	return [base_ui_box, base_ui_menu, UIBase.ui, UINodes.ui, UIView2D.ui];
+	return [base_ui_box, base_ui_menu, ui_base_ui, ui_nodes_ui, ui_view2d_ui];
 }
 
 function base_is_decal_layer(): bool {
@@ -950,37 +950,37 @@ function base_is_decal_layer(): bool {
 }
 
 function base_redraw_status() {
-	UIBase.hwnds[tab_area_t.STATUS].redraws = 2;
+	ui_base_hwnds[tab_area_t.STATUS].redraws = 2;
 }
 
 function base_redraw_console() {
 	let statush: i32 = config_raw.layout[layout_size_t.STATUS_H];
-	if (UIBase.ui != null && statush > UIStatus.default_status_h * zui_SCALE(UIBase.ui)) {
-		UIBase.hwnds[tab_area_t.STATUS].redraws = 2;
+	if (ui_base_ui != null && statush > ui_status_default_status_h * zui_SCALE(ui_base_ui)) {
+		ui_base_hwnds[tab_area_t.STATUS].redraws = 2;
 	}
 }
 
 function base_init_layout() {
-	let show2d: bool = (UINodes != null && UINodes.show) || (UIView2D != null && UIView2D.show);
+	let show2d: bool = ui_nodes_show || ui_view2d_show;
 
 	let raw: config_t = config_raw;
 	raw.layout = [
 		///if (is_paint || is_sculpt)
-		Math.floor(UIBase.default_sidebar_w * raw.window_scale), // LayoutSidebarW
-		Math.floor(sys_height() / 2), // LayoutSidebarH0
-		Math.floor(sys_height() / 2), // LayoutSidebarH1
+		math_floor(ui_base_default_sidebar_w * raw.window_scale), // LayoutSidebarW
+		math_floor(sys_height() / 2), // LayoutSidebarH0
+		math_floor(sys_height() / 2), // LayoutSidebarH1
 		///end
 
 		///if krom_ios
-		show2d ? Math.floor((app_w() + raw.layout[layout_size_t.NODES_W]) * 0.473) : Math.floor(app_w() * 0.473), // LayoutNodesW
+		show2d ? math_floor((app_w() + raw.layout[layout_size_t.NODES_W]) * 0.473) : math_floor(app_w() * 0.473), // LayoutNodesW
 		///elseif krom_android
-		show2d ? Math.floor((app_w() + raw.layout[layout_size_t.NODES_W]) * 0.473) : Math.floor(app_w() * 0.473),
+		show2d ? math_floor((app_w() + raw.layout[layout_size_t.NODES_W]) * 0.473) : math_floor(app_w() * 0.473),
 		///else
-		show2d ? Math.floor((app_w() + raw.layout[layout_size_t.NODES_W]) * 0.515) : Math.floor(app_w() * 0.515), // Align with ui header controls
+		show2d ? math_floor((app_w() + raw.layout[layout_size_t.NODES_W]) * 0.515) : math_floor(app_w() * 0.515), // Align with ui header controls
 		///end
 
-		Math.floor(app_h() / 2), // LayoutNodesH
-		Math.floor(UIStatus.default_status_h * raw.window_scale), // LayoutStatusH
+		math_floor(app_h() / 2), // LayoutNodesH
+		math_floor(ui_status_default_status_h * raw.window_scale), // LayoutStatusH
 
 		///if (krom_android || krom_ios)
 		0, // LayoutHeader
@@ -1109,7 +1109,7 @@ function base_init_layers() {
 ///if (is_paint || is_sculpt)
 function base_resize_layers() {
 	let conf: config_t = config_raw;
-	if (base_res_handle.position >= Math.floor(texture_res_t.RES16384)) { // Save memory for >=16k
+	if (base_res_handle.position >= math_floor(texture_res_t.RES16384)) { // Save memory for >=16k
 		conf.undo_steps = 1;
 		if (context_raw.undo_handle != null) {
 			context_raw.undo_handle.value = conf.undo_steps;
@@ -1144,8 +1144,8 @@ function base_resize_layers() {
 		base_notify_on_next_frame(function() {
 			image_unload(_texpaint_blur);
 		});
-		let size_x: f32 = Math.floor(config_get_texture_res_x() * 0.95);
-		let size_y: f32 = Math.floor(config_get_texture_res_y() * 0.95);
+		let size_x: f32 = math_floor(config_get_texture_res_x() * 0.95);
+		let size_y: f32 = math_floor(config_get_texture_res_y() * 0.95);
 		rts.get("texpaint_blur").width = size_x;
 		rts.get("texpaint_blur").height = size_y;
 		rts.get("texpaint_blur")._image = image_create_render_target(size_x, size_y);
@@ -2038,7 +2038,8 @@ function base_update_fill_layers() {
 
 function base_update_fill_layer(parse_paint: bool = true) {
 	let current: image_t = _g2_current;
-	if (current != null) g2_end();
+	let g2_in_use: bool = _g2_in_use;
+	if (g2_in_use) g2_end();
 
 	let _tool: workspace_tool_t = context_raw.tool;
 	let _fill_type: i32 = context_raw.fill_type_handle.position;
@@ -2055,7 +2056,7 @@ function base_update_fill_layer(parse_paint: bool = true) {
 	context_raw.rdirty = 2;
 	context_raw.tool = _tool;
 	context_raw.fill_type_handle.position = _fill_type;
-	if (current != null) g2_begin(current);
+	if (g2_in_use) g2_begin(current);
 }
 
 function base_set_object_mask() {
@@ -2085,13 +2086,13 @@ function base_set_object_mask() {
 		let is_atlas: bool = SlotLayer.get_object_mask(context_raw.layer) > 0 && SlotLayer.get_object_mask(context_raw.layer) <= project_paint_objects.length;
 		if (context_raw.merged_object == null || is_atlas || context_raw.merged_object_is_atlas) {
 			let visibles: mesh_object_t[] = is_atlas ? project_get_atlas_objects(SlotLayer.get_object_mask(context_raw.layer)) : null;
-			UtilMesh.merge_mesh(visibles);
+			util_mesh_merge(visibles);
 		}
 		context_select_paint_object(context_main_object());
 		context_raw.paint_object.skip_context = "paint";
 		context_raw.merged_object.base.visible = true;
 	}
-	UtilUV.dilatemap_cached = false;
+	util_uv_dilatemap_cached = false;
 }
 
 function base_new_layer(clear: bool = true, position: i32 = -1): SlotLayerRaw {
@@ -2190,11 +2191,11 @@ function base_on_layers_resized() {
 		context_raw.material = _material;
 		MakeMaterial.parse_paint_material();
 	});
-	UtilUV.uvmap = null;
-	UtilUV.uvmap_cached = false;
-	UtilUV.trianglemap = null;
-	UtilUV.trianglemap_cached = false;
-	UtilUV.dilatemap_cached = false;
+	util_uv_uvmap = null;
+	util_uv_uvmap_cached = false;
+	util_uv_trianglemap = null;
+	util_uv_trianglemap_cached = false;
+	util_uv_dilatemap_cached = false;
 	///if (krom_direct3d12 || krom_vulkan || krom_metal)
 	RenderPathRaytrace.ready = false;
 	///end
@@ -2207,8 +2208,8 @@ function base_flatten(heightToNormal: bool = false): any {
 	let texpaint_nor: image_t = BrushOutputNode.inst.texpaint_nor;
 	let texpaint_pack: image_t = BrushOutputNode.inst.texpaint_pack;
 
-	let nodes: zui_nodes_t = UINodes.get_nodes();
-	let canvas: zui_node_canvas_t = UINodes.get_canvas(true);
+	let nodes: zui_nodes_t = ui_nodes_get_nodes();
+	let canvas: zui_node_canvas_t = ui_nodes_get_canvas(true);
 	if (nodes.nodes_selected_id.length > 0) {
 		let node: zui_node_t = zui_get_node(canvas.nodes, nodes.nodes_selected_id[0]);
 		let brush_node: LogicNode = ParserLogic.get_logic_node(node);

+ 6 - 6
base/Sources/camera.ts

@@ -21,19 +21,19 @@ function camera_update() {
 		if (config_raw.wrap_mouse && camera_controls_down) {
 			if (mouse_view_x() < 0) {
 				mouse_x = mouse_last_x = app_x() + app_w();
-				krom_set_mouse_position(Math.floor(mouse_x), Math.floor(mouse_y));
+				krom_set_mouse_position(math_floor(mouse_x), math_floor(mouse_y));
 			}
 			else if (mouse_view_x() > app_w()) {
 				mouse_x = mouse_last_x = app_x();
-				krom_set_mouse_position(Math.floor(mouse_x), Math.floor(mouse_y));
+				krom_set_mouse_position(math_floor(mouse_x), math_floor(mouse_y));
 			}
 			else if (mouse_view_y() < 0) {
 				mouse_y = mouse_last_y = app_y() + app_h();
-				krom_set_mouse_position(Math.floor(mouse_x), Math.floor(mouse_y));
+				krom_set_mouse_position(math_floor(mouse_x), math_floor(mouse_y));
 			}
 			else if (mouse_view_y() > app_h()) {
 				mouse_y = mouse_last_y = app_y();
-				krom_set_mouse_position(Math.floor(mouse_x), Math.floor(mouse_y));
+				krom_set_mouse_position(math_floor(mouse_x), math_floor(mouse_y));
 			}
 		}
 		else {
@@ -121,7 +121,7 @@ function camera_update() {
 		let strafe_down: bool = keyboard_down("q");
 		let fast: f32 = keyboard_down("shift") ? 2.0 : (keyboard_down("alt") ? 0.5 : 1.0);
 		if (mouse_wheel_delta != 0) {
-			fast *= Math.abs(mouse_wheel_delta) * 4.0;
+			fast *= math_abs(mouse_wheel_delta) * 4.0;
 		}
 
 		if (move_forward || move_backward || strafe_right || strafe_left || strafe_up || strafe_down) {
@@ -157,7 +157,7 @@ function camera_update() {
 	if (operator_shortcut(config_keymap.rotate_light, shortcut_type_t.DOWN)) {
 		camera_redraws = 2;
 		let light: light_object_t = scene_lights[0];
-		context_raw.light_angle = (context_raw.light_angle + ((mouse_movement_x / 100) % (2 * Math.PI) + 2 * Math.PI)) % (2 * Math.PI);
+		context_raw.light_angle = (context_raw.light_angle + ((mouse_movement_x / 100) % (2 * math_pi()) + 2 * math_pi())) % (2 * math_pi());
 		let m: mat4_t = mat4_rot_z(mouse_movement_x / 100);
 		mat4_mult_mat(light.base.transform.local, m);
 		transform_decompose(light.base.transform);

+ 16 - 15
base/Sources/config.ts

@@ -10,7 +10,7 @@ function config_load(done: ()=>void) {
 	try {
 		let blob: ArrayBuffer = data_get_blob((path_is_protected() ? krom_save_path() : "") + "config.json");
 		config_loaded = true;
-		config_raw = JSON.parse(sys_buffer_to_string(blob));
+		config_raw = json_parse(sys_buffer_to_string(blob));
 		done();
 	}
 	catch (e: any) {
@@ -18,7 +18,7 @@ function config_load(done: ()=>void) {
 		try { // Protected directory
 			let blob: ArrayBuffer = data_get_blob(krom_save_path() + "config.json");
 			config_loaded = true;
-			config_raw = JSON.parse(sys_buffer_to_string(blob));
+			config_raw = json_parse(sys_buffer_to_string(blob));
 			done();
 		}
 		catch (e: any) {
@@ -35,7 +35,7 @@ function config_save() {
 	// Use system application data folder
 	// when running from protected path like "Program Files"
 	let path: string = (path_is_protected() ? krom_save_path() : path_data() + path_sep) + "config.json";
-	let buffer: buffer_t = sys_string_to_buffer(JSON.stringify(config_raw));
+	let buffer: buffer_t = sys_string_to_buffer(json_stringify(config_raw));
 	krom_file_save_bytes(path, buffer);
 
 	///if krom_linux // Protected directory
@@ -107,14 +107,14 @@ function config_init() {
 function config_get_sha(): string {
 	let sha: string = "";
 	let blob: ArrayBuffer = data_get_blob("version.json");
-	sha = JSON.parse(sys_buffer_to_string(blob)).sha;
+	sha = json_parse(sys_buffer_to_string(blob)).sha;
 	return sha;
 }
 
 function config_get_date(): string {
 	let date: string = "";
 	let blob: ArrayBuffer = data_get_blob("version.json");
-	date = JSON.parse(sys_buffer_to_string(blob)).date;
+	date = json_parse(sys_buffer_to_string(blob)).date;
 	return date;
 }
 
@@ -139,7 +139,7 @@ function config_get_options(): kinc_sys_ops_t {
 }
 
 function config_restore() {
-	zui_children = new Map(); // Reset ui handles
+	zui_children = map_create(); // Reset ui handles
 	config_loaded = false;
 	let _layout: i32[] = config_raw.layout;
 	config_init();
@@ -156,7 +156,7 @@ function config_import_from(from: config_t) {
 	config_raw = from;
 	config_raw.sha = _sha;
 	config_raw.version = _version;
-	zui_children = new Map(); // Reset ui handles
+	zui_children = map_create(); // Reset ui handles
 	config_load_keymap();
 	base_init_layout();
 	translator_load_translations(config_raw.locale);
@@ -174,9 +174,10 @@ function config_apply() {
 	context_raw.ddirty = 2;
 
 	let current: image_t = _g2_current;
-	if (current != null) g2_end();
+	let g2_in_use: bool = _g2_in_use;
+	if (g2_in_use) g2_end();
 	RenderPathBase.apply_config();
-	if (current != null) g2_begin(current);
+	if (g2_in_use) g2_begin(current);
 }
 
 function config_load_keymap() {
@@ -185,7 +186,7 @@ function config_load_keymap() {
 	}
 	else {
 		let blob: ArrayBuffer = data_get_blob("keymap_presets/" + config_raw.keymap);
-		config_keymap = JSON.parse(sys_buffer_to_string(blob));
+		config_keymap = json_parse(sys_buffer_to_string(blob));
 		// Fill in undefined keys with defaults
 		for (let field in base_default_keymap) {
 			if (!(field in config_keymap)) {
@@ -199,7 +200,7 @@ function config_load_keymap() {
 function config_save_keymap() {
 	if (config_raw.keymap == "default.json") return;
 	let path: string = data_path() + "keymap_presets/" + config_raw.keymap;
-	let buffer: buffer_t = sys_string_to_buffer(JSON.stringify(config_keymap));
+	let buffer: buffer_t = sys_string_to_buffer(json_stringify(config_keymap));
 	krom_file_save_bytes(path, buffer);
 }
 
@@ -232,11 +233,11 @@ function config_get_texture_res(): i32 {
 }
 
 function config_get_texture_res_x(): i32 {
-	return context_raw.project_aspect_ratio == 2 ? Math.floor(config_get_texture_res() / 2) : config_get_texture_res();
+	return context_raw.project_aspect_ratio == 2 ? math_floor(config_get_texture_res() / 2) : config_get_texture_res();
 }
 
 function config_get_texture_res_y(): i32 {
-	return context_raw.project_aspect_ratio == 1 ? Math.floor(config_get_texture_res() / 2) : config_get_texture_res();
+	return context_raw.project_aspect_ratio == 1 ? math_floor(config_get_texture_res() / 2) : config_get_texture_res();
 }
 
 function config_get_texture_res_pos(i: i32): i32 {
@@ -256,7 +257,7 @@ function config_load_theme(theme: string, tagRedraw: bool = true) {
 	}
 	else {
 		let b: ArrayBuffer = data_get_blob("themes/" + theme);
-		let parsed: any = JSON.parse(sys_buffer_to_string(b));
+		let parsed: any = json_parse(sys_buffer_to_string(b));
 		base_theme = zui_theme_create();
 		for (let key in base_theme) {
 			if (key == "theme_") continue;
@@ -269,7 +270,7 @@ function config_load_theme(theme: string, tagRedraw: bool = true) {
 	base_theme.FILL_WINDOW_BG = true;
 	if (tagRedraw) {
 		for (let ui of base_get_uis()) ui.t = base_theme;
-		UIBase.tag_ui_redraw();
+		ui_base_tag_ui_redraw();
 	}
 	if (config_raw.touch_ui) {
 		// Enlarge elements

+ 1 - 1
base/Sources/console.ts

@@ -13,7 +13,7 @@ function console_draw_toast(s: string) {
 	let y: f32 = sys_height() - 200 * scale;
 	g2_fill_rect(x - 200 * scale, y, 400 * scale, 80 * scale);
 	g2_set_font(base_font);
-	g2_set_font_size(Math.floor(22 * scale));
+	g2_set_font_size(math_floor(22 * scale));
 	g2_set_color(0xffffffff);
 	g2_draw_string(s, x - g2_font_width(_g2_font, _g2_font_size, s) / 2, y + 40 * scale - g2_font_height(_g2_font, _g2_font_size) / 2);
 }

+ 40 - 39
base/Sources/context.ts

@@ -22,15 +22,15 @@ function context_set_material(m: SlotMaterialRaw) {
 	if (project_materials.indexOf(m) == -1) return;
 	context_raw.material = m;
 	MakeMaterial.parse_paint_material();
-	UIBase.hwnds[tab_area_t.SIDEBAR1].redraws = 2;
-	UIHeader.header_handle.redraws = 2;
-	UINodes.hwnd.redraws = 2;
-	UINodes.group_stack = [];
+	ui_base_hwnds[tab_area_t.SIDEBAR1].redraws = 2;
+	ui_header_handle.redraws = 2;
+	ui_nodes_hwnd.redraws = 2;
+	ui_nodes_group_stack = [];
 
 	let decal: bool = context_raw.tool == workspace_tool_t.DECAL || context_raw.tool == workspace_tool_t.TEXT;
 	if (decal) {
 		let _next = function() {
-			UtilRender.make_decal_preview();
+			util_render_make_decal_preview();
 		}
 		base_notify_on_next_frame(_next);
 	}
@@ -45,8 +45,8 @@ function context_set_brush(b: SlotBrushRaw) {
 	if (project_brushes.indexOf(b) == -1) return;
 	context_raw.brush = b;
 	MakeMaterial.parse_brush();
-	UIBase.hwnds[tab_area_t.SIDEBAR1].redraws = 2;
-	UINodes.hwnd.redraws = 2;
+	ui_base_hwnds[tab_area_t.SIDEBAR1].redraws = 2;
+	ui_nodes_hwnd.redraws = 2;
 }
 
 function context_select_font(i: i32) {
@@ -57,10 +57,10 @@ function context_select_font(i: i32) {
 function context_set_font(f: SlotFontRaw) {
 	if (project_fonts.indexOf(f) == -1) return;
 	context_raw.font = f;
-	UtilRender.make_text_preview();
-	UtilRender.make_decal_preview();
-	UIBase.hwnds[tab_area_t.STATUS].redraws = 2;
-	UIView2D.hwnd.redraws = 2;
+	util_render_make_text_preview();
+	util_render_make_decal_preview();
+	ui_base_hwnds[tab_area_t.STATUS].redraws = 2;
+	ui_view2d_hwnd.redraws = 2;
 }
 
 function context_select_layer(i: i32) {
@@ -71,19 +71,20 @@ function context_select_layer(i: i32) {
 function context_set_layer(l: SlotLayerRaw) {
 	if (l == context_raw.layer) return;
 	context_raw.layer = l;
-	UIHeader.header_handle.redraws = 2;
+	ui_header_handle.redraws = 2;
 
 	let current: image_t = _g2_current;
-	if (current != null) g2_end();
+	let g2_in_use: bool = _g2_in_use;
+	if (g2_in_use) g2_end();
 
 	base_set_object_mask();
 	MakeMaterial.parse_mesh_material();
 	MakeMaterial.parse_paint_material();
 
-	if (current != null) g2_begin(current);
+	if (g2_in_use) g2_begin(current);
 
-	UIBase.hwnds[tab_area_t.SIDEBAR0].redraws = 2;
-	UIView2D.hwnd.redraws = 2;
+	ui_base_hwnds[tab_area_t.SIDEBAR0].redraws = 2;
+	ui_view2d_hwnd.redraws = 2;
 }
 ///end
 
@@ -98,8 +99,8 @@ function context_select_tool(i: i32) {
 
 	///if (is_paint || is_sculpt)
 	context_init_tool();
-	UIHeader.header_handle.redraws = 2;
-	UIToolbar.toolbar_handle.redraws = 2;
+	ui_header_handle.redraws = 2;
+	ui_toolbar_handle.redraws = 2;
 	///end
 }
 
@@ -108,13 +109,13 @@ function context_init_tool() {
 	let decal: bool = context_raw.tool == workspace_tool_t.DECAL || context_raw.tool == workspace_tool_t.TEXT;
 	if (decal) {
 		if (context_raw.tool == workspace_tool_t.TEXT) {
-			UtilRender.make_text_preview();
+			util_render_make_text_preview();
 		}
-		UtilRender.make_decal_preview();
+		util_render_make_decal_preview();
 	}
 
 	else if (context_raw.tool == workspace_tool_t.PARTICLE) {
-		UtilParticle.init_particle();
+		util_particle_init();
 		MakeMaterial.parse_particle_material();
 	}
 
@@ -141,7 +142,7 @@ function context_init_tool() {
 
 function context_select_paint_object(o: mesh_object_t) {
 	///if (is_paint || is_sculpt)
-	UIHeader.header_handle.redraws = 2;
+	ui_header_handle.redraws = 2;
 	for (let p of project_paint_objects) p.skip_context = "paint";
 	context_raw.paint_object = o;
 
@@ -151,9 +152,9 @@ function context_select_paint_object(o: mesh_object_t) {
 	if (context_raw.merged_object == null || mask > 0) {
 		context_raw.paint_object.skip_context = "";
 	}
-	UtilUV.uvmap_cached = false;
-	UtilUV.trianglemap_cached = false;
-	UtilUV.dilatemap_cached = false;
+	util_uv_uvmap_cached = false;
+	util_uv_trianglemap_cached = false;
+	util_uv_dilatemap_cached = false;
 	///end
 
 	///if is_lab
@@ -200,7 +201,7 @@ function context_in_viewport(): bool {
 function context_in_paint_area(): bool {
 	///if (is_paint || is_sculpt)
 	let right: i32 = app_w();
-	if (UIView2D.show) right += UIView2D.ww;
+	if (ui_view2d_show) right += ui_view2d_ww;
 	return mouse_view_x() > 0 && mouse_view_x() < right &&
 			mouse_view_y() > 0 && mouse_view_y() < app_h();
 	///end
@@ -220,16 +221,16 @@ function context_in_materials(): bool {
 
 ///if (is_paint || is_sculpt)
 function context_in_2d_view(type: view_2d_type_t = view_2d_type_t.LAYER): bool {
-	return UIView2D.show && UIView2D.type == type &&
-			mouse_x > UIView2D.wx && mouse_x < UIView2D.wx + UIView2D.ww &&
-			mouse_y > UIView2D.wy && mouse_y < UIView2D.wy + UIView2D.wh;
+	return ui_view2d_show && ui_view2d_type == type &&
+			mouse_x > ui_view2d_wx && mouse_x < ui_view2d_wx + ui_view2d_ww &&
+			mouse_y > ui_view2d_wy && mouse_y < ui_view2d_wy + ui_view2d_wh;
 }
 ///end
 
 function context_in_nodes(): bool {
-	return UINodes.show &&
-			mouse_x > UINodes.wx && mouse_x < UINodes.wx + UINodes.ww &&
-			mouse_y > UINodes.wy && mouse_y < UINodes.wy + UINodes.wh;
+	return ui_nodes_show &&
+			mouse_x > ui_nodes_wx && mouse_x < ui_nodes_wx + ui_nodes_ww &&
+			mouse_y > ui_nodes_wy && mouse_y < ui_nodes_wy + ui_nodes_wh;
 }
 
 function context_in_swatches(): bool {
@@ -262,10 +263,10 @@ function context_set_viewport_mode(mode: viewport_mode_t) {
 	else {
 		render_path_commands = RenderPathForward.commands;
 	}
-	let _workspace: i32 = UIHeader.worktab.position;
-	UIHeader.worktab.position = 0;
+	let _workspace: i32 = ui_header_worktab.position;
+	ui_header_worktab.position = 0;
 	MakeMaterial.parse_mesh_material();
-	UIHeader.worktab.position = _workspace;
+	ui_header_worktab.position = _workspace;
 }
 
 function context_load_envmap() {
@@ -335,8 +336,8 @@ function context_run_brush(from: i32) {
 		context_raw.last_paint_vec_y = context_raw.paint_vec.y;
 	}
 
-	let nodes: zui_nodes_t = UINodes.get_nodes();
-	let canvas: zui_node_canvas_t = UINodes.get_canvas(true);
+	let nodes: zui_nodes_t = ui_nodes_get_nodes();
+	let canvas: zui_node_canvas_t = ui_nodes_get_canvas(true);
 	let inpaint: bool = nodes.nodes_selected_id.length > 0 && zui_get_node(canvas.nodes, nodes.nodes_selected_id[0]).type == "InpaintNode";
 
 	// Paint bounds
@@ -409,8 +410,8 @@ function context_update() {
 	context_raw.coords.y = paint_y;
 
 	if (context_raw.lock_begin) {
-		let dx: i32 = Math.abs(context_raw.lock_start_x - mouse_view_x());
-		let dy: i32 = Math.abs(context_raw.lock_start_y - mouse_view_y());
+		let dx: i32 = math_abs(context_raw.lock_start_x - mouse_view_x());
+		let dy: i32 = math_abs(context_raw.lock_start_y - mouse_view_y());
 		if (dx > 1 || dy > 1) {
 			context_raw.lock_begin = false;
 			dx > dy ? context_raw.lock_y = true : context_raw.lock_x = true;

+ 5 - 5
base/Sources/file.ts

@@ -7,11 +7,11 @@ let file_cmd_mkdir: string = "mkdir -p";
 let file_cmd_copy: string = "cp";
 ///end
 
-let file_cloud: Map<string, string[]> = null;
-let file_cloud_sizes: Map<string, i32> = null;
+let file_cloud: map_t<string, string[]> = null;
+let file_cloud_sizes: map_t<string, i32> = null;
 
 // ///if krom_android
-// let let file_internal: Map<string, string[]> = null; // .apk contents
+// let let file_internal: map_t<string, string[]> = null; // .apk contents
 // ///end
 
 function file_read_directory(path: string, folders_only: bool = false): string[] {
@@ -190,7 +190,7 @@ function file_init_cloud_bytes(done: ()=>void, append: string = "") {
 }
 
 function file_init_cloud(done: ()=>void) {
-	file_cloud = new Map();
-	file_cloud_sizes = new Map();
+	file_cloud = map_create();
+	file_cloud_sizes = map_create();
 	file_init_cloud_bytes(done);
 }

+ 22 - 22
base/Sources/geom.ts

@@ -10,7 +10,7 @@ function geom_make_plane(size_x: f32 = 1.0, size_y: f32 = 1.0, verts_x: i32 = 2,
 	// Pack positions to (-1, 1) range
 	let half_x: f32 = size_x / 2;
 	let half_y: f32 = size_y / 2;
-	mesh.scale_pos = Math.max(half_x, half_y);
+	mesh.scale_pos = math_max(half_x, half_y);
 	let inv: f32 = (1 / mesh.scale_pos) * 32767;
 
 	mesh.posa = new Int16Array(verts_x * verts_y * 4);
@@ -21,21 +21,21 @@ function geom_make_plane(size_x: f32 = 1.0, size_y: f32 = 1.0, verts_x: i32 = 2,
 	let step_y: f32 = size_y / (verts_y - 1);
 	for (let i: i32 = 0; i < verts_x * verts_y; ++i) {
 		let x: f32 = (i % verts_x) * step_x - half_x;
-		let y: f32 = Math.floor(i / verts_x) * step_y - half_y;
-		mesh.posa[i * 4    ] = Math.floor(x * inv);
-		mesh.posa[i * 4 + 1] = Math.floor(y * inv);
+		let y: f32 = math_floor(i / verts_x) * step_y - half_y;
+		mesh.posa[i * 4    ] = math_floor(x * inv);
+		mesh.posa[i * 4 + 1] = math_floor(y * inv);
 		mesh.posa[i * 4 + 2] = 0;
 		mesh.nora[i * 2    ] = 0;
 		mesh.nora[i * 2 + 1] = 0;
 		mesh.posa[i * 4 + 3] = 32767;
 		x = (i % verts_x) / (verts_x - 1);
-		y = 1.0 - Math.floor(i / verts_x) / (verts_y - 1);
-		mesh.texa[i * 2    ] = (Math.floor(x * 32767 * uv_scale) - 1) % 32767;
-		mesh.texa[i * 2 + 1] = (Math.floor(y * 32767 * uv_scale) - 1) % 32767;
+		y = 1.0 - math_floor(i / verts_x) / (verts_y - 1);
+		mesh.texa[i * 2    ] = (math_floor(x * 32767 * uv_scale) - 1) % 32767;
+		mesh.texa[i * 2 + 1] = (math_floor(y * 32767 * uv_scale) - 1) % 32767;
 	}
 	for (let i: i32 = 0; i < (verts_x - 1) * (verts_y - 1); ++i) {
 		let x: f32 = i % (verts_x - 1);
-		let y: f32 = Math.floor(i / (verts_y - 1));
+		let y: f32 = math_floor(i / (verts_y - 1));
 		mesh.inda[i * 6    ] = y * verts_x + x;
 		mesh.inda[i * 6 + 1] = y * verts_x + x + 1;
 		mesh.inda[i * 6 + 2] = (y + 1) * verts_x + x;
@@ -59,7 +59,7 @@ function geom_make_uv_sphere(radius: f32 = 1.0, widthSegments: i32 = 32, heightS
 	mesh.scale_pos = radius;
 	mesh.scale_tex = uvScale;
 	let inv: f32 = (1 / mesh.scale_pos) * 32767;
-	let pi2: f32 = Math.PI * 2;
+	let pi2: f32 = math_pi() * 2;
 
 	let width_verts: i32 = widthSegments + 1;
 	let height_verts: i32 = heightSegments + 1;
@@ -78,22 +78,22 @@ function geom_make_uv_sphere(radius: f32 = 1.0, widthSegments: i32 = 32, heightS
 		for (let x: i32 = 0; x < width_verts; ++x) {
 			let u: f32 = x / widthSegments;
 			let u_pi2: f32 = u * pi2;
-			let v_pi: f32  = v * Math.PI;
-			let v_pi_sin: f32 = Math.sin(v_pi);
-			let vx: f32 = -radius * Math.cos(u_pi2) * v_pi_sin;
-			let vy: f32 =  radius * Math.sin(u_pi2) * v_pi_sin;
-			let vz: f32 = -radius * Math.cos(v_pi);
+			let v_pi: f32  = v * math_pi();
+			let v_pi_sin: f32 = math_sin(v_pi);
+			let vx: f32 = -radius * math_cos(u_pi2) * v_pi_sin;
+			let vy: f32 =  radius * math_sin(u_pi2) * v_pi_sin;
+			let vz: f32 = -radius * math_cos(v_pi);
 			let i4: i32 = pos * 4;
 			let i2: i32 = pos * 2;
-			mesh.posa[i4    ] = Math.floor(vx * inv);
-			mesh.posa[i4 + 1] = Math.floor(vy * inv);
-			mesh.posa[i4 + 2] = Math.floor(vz * inv);
+			mesh.posa[i4    ] = math_floor(vx * inv);
+			mesh.posa[i4 + 1] = math_floor(vy * inv);
+			mesh.posa[i4 + 2] = math_floor(vz * inv);
 			vec4_normalize(vec4_set(nor, vx, vy, vz));
-			mesh.posa[i4 + 3] = Math.floor(nor.z * 32767);
-			mesh.nora[i2    ] = Math.floor(nor.x * 32767);
-			mesh.nora[i2 + 1] = Math.floor(nor.y * 32767);
-			mesh.texa[i2    ] = (Math.floor((u + u_off) * 32767) - 1) % 32767;
-			mesh.texa[i2 + 1] = (Math.floor(v_flip      * 32767) - 1) % 32767;
+			mesh.posa[i4 + 3] = math_floor(nor.z * 32767);
+			mesh.nora[i2    ] = math_floor(nor.x * 32767);
+			mesh.nora[i2 + 1] = math_floor(nor.y * 32767);
+			mesh.texa[i2    ] = (math_floor((u + u_off) * 32767) - 1) % 32767;
+			mesh.texa[i2 + 1] = (math_floor(v_flip      * 32767) - 1) % 32767;
 			pos++;
 		}
 	}

+ 7 - 7
base/Sources/gizmo.ts

@@ -225,9 +225,9 @@ function gizmo_update() {
 			if (hit != null) {
 				if (context_raw.gizmo_started) {
 					mat4_decompose(context_raw.layer.decal_mat, gizmo_v, gizmo_q, gizmo_v0);
-					context_raw.gizmo_offset = Math.atan2(hit.y - gizmo_v.y, hit.z - gizmo_v.z);
+					context_raw.gizmo_offset = math_atan2(hit.y - gizmo_v.y, hit.z - gizmo_v.z);
 				}
-				context_raw.gizmo_drag = Math.atan2(hit.y - gizmo_v.y, hit.z - gizmo_v.z) - context_raw.gizmo_offset;
+				context_raw.gizmo_drag = math_atan2(hit.y - gizmo_v.y, hit.z - gizmo_v.z) - context_raw.gizmo_offset;
 			}
 		}
 		else if (context_raw.rotate_y) {
@@ -235,9 +235,9 @@ function gizmo_update() {
 			if (hit != null) {
 				if (context_raw.gizmo_started) {
 					mat4_decompose(context_raw.layer.decal_mat, gizmo_v, gizmo_q, gizmo_v0);
-					context_raw.gizmo_offset = Math.atan2(hit.z - gizmo_v.z, hit.x - gizmo_v.x);
+					context_raw.gizmo_offset = math_atan2(hit.z - gizmo_v.z, hit.x - gizmo_v.x);
 				}
-				context_raw.gizmo_drag = Math.atan2(hit.z - gizmo_v.z, hit.x - gizmo_v.x) - context_raw.gizmo_offset;
+				context_raw.gizmo_drag = math_atan2(hit.z - gizmo_v.z, hit.x - gizmo_v.x) - context_raw.gizmo_offset;
 			}
 		}
 		else if (context_raw.rotate_z) {
@@ -245,16 +245,16 @@ function gizmo_update() {
 			if (hit != null) {
 				if (context_raw.gizmo_started) {
 					mat4_decompose(context_raw.layer.decal_mat, gizmo_v, gizmo_q, gizmo_v0);
-					context_raw.gizmo_offset = Math.atan2(hit.y - gizmo_v.y, hit.x - gizmo_v.x);
+					context_raw.gizmo_offset = math_atan2(hit.y - gizmo_v.y, hit.x - gizmo_v.x);
 				}
-				context_raw.gizmo_drag = Math.atan2(hit.y - gizmo_v.y, hit.x - gizmo_v.x) - context_raw.gizmo_offset;
+				context_raw.gizmo_drag = math_atan2(hit.y - gizmo_v.y, hit.x - gizmo_v.x) - context_raw.gizmo_offset;
 			}
 		}
 
 		if (context_raw.gizmo_started) context_raw.gizmo_drag_last = context_raw.gizmo_drag;
 
 		///if is_forge
-		UtilMesh.remove_merged_mesh();
+		util_mesh_remove_merged();
 		RenderPathRaytrace.ready = false;
 		///end
 	}

+ 25 - 25
base/Sources/history.ts

@@ -193,8 +193,8 @@ function history_undo() {
 			context_raw.material = SlotMaterial.create(project_materials[0].data);
 			project_materials.splice(step.material, 0, context_raw.material);
 			context_raw.material.canvas = step.canvas;
-			UINodes.canvas_changed();
-			UINodes.hwnd.redraws = 2;
+			ui_nodes_canvas_changed();
+			ui_nodes_hwnd.redraws = 2;
 		}
 		else if (step.name == tr("Duplicate Material")) {
 			context_raw.material = project_materials[step.material];
@@ -216,15 +216,15 @@ function history_undo() {
 		context_raw.ddirty = 2;
 
 		///if (is_paint || is_sculpt)
-		UIBase.hwnds[tab_area_t.SIDEBAR0].redraws = 2;
-		UIBase.hwnds[tab_area_t.SIDEBAR1].redraws = 2;
-		if (UIView2D.show) {
-			UIView2D.hwnd.redraws = 2;
+		ui_base_hwnds[tab_area_t.SIDEBAR0].redraws = 2;
+		ui_base_hwnds[tab_area_t.SIDEBAR1].redraws = 2;
+		if (ui_view2d_show) {
+			ui_view2d_hwnd.redraws = 2;
 		}
 
 		if (config_raw.touch_ui) {
 			// Refresh undo & redo buttons
-			UIMenubar.menu_handle.redraws = 2;
+			ui_menubar_menu_handle.redraws = 2;
 		}
 		///end
 	}
@@ -378,8 +378,8 @@ function history_redo() {
 			context_raw.material = SlotMaterial.create(project_materials[0].data);
 			project_materials.splice(step.material, 0, context_raw.material);
 			context_raw.material.canvas = step.canvas;
-			UINodes.canvas_changed();
-			UINodes.hwnd.redraws = 2;
+			ui_nodes_canvas_changed();
+			ui_nodes_hwnd.redraws = 2;
 		}
 		else if (step.name == tr("Delete Material")) {
 			context_raw.material = project_materials[step.material];
@@ -390,8 +390,8 @@ function history_redo() {
 			context_raw.material = SlotMaterial.create(project_materials[0].data);
 			project_materials.splice(step.material, 0, context_raw.material);
 			context_raw.material.canvas = step.canvas;
-			UINodes.canvas_changed();
-			UINodes.hwnd.redraws = 2;
+			ui_nodes_canvas_changed();
+			ui_nodes_hwnd.redraws = 2;
 		}
 		else { // Paint operation
 			let lay: SlotLayerRaw = history_undo_layers[history_undo_i];
@@ -408,13 +408,13 @@ function history_redo() {
 		context_raw.ddirty = 2;
 
 		///if (is_paint || is_sculpt)
-		UIBase.hwnds[tab_area_t.SIDEBAR0].redraws = 2;
-		UIBase.hwnds[tab_area_t.SIDEBAR1].redraws = 2;
-		if (UIView2D.show) UIView2D.hwnd.redraws = 2;
+		ui_base_hwnds[tab_area_t.SIDEBAR0].redraws = 2;
+		ui_base_hwnds[tab_area_t.SIDEBAR1].redraws = 2;
+		if (ui_view2d_show) ui_view2d_hwnd.redraws = 2;
 
 		if (config_raw.touch_ui) {
 			// Refresh undo & redo buttons
-			UIMenubar.menu_handle.redraws = 2;
+			ui_menubar_menu_handle.redraws = 2;
 		}
 		///end
 	}
@@ -444,7 +444,7 @@ function history_edit_nodes(canvas: zui_node_canvas_t, canvas_group: Null<i32> =
 	///if (is_paint || is_sculpt)
 	step.canvas_type = canvas_type;
 	///end
-	step.canvas = JSON.parse(JSON.stringify(canvas));
+	step.canvas = json_parse(json_stringify(canvas));
 }
 
 ///if (is_paint || is_sculpt)
@@ -453,7 +453,7 @@ function history_paint() {
 	history_copy_to_undo(context_raw.layer.id, history_undo_i, is_mask);
 
 	history_push_undo = false;
-	history_push(tr(UIToolbar.tool_names[context_raw.tool]));
+	history_push(tr(ui_toolbar_tool_names[context_raw.tool]));
 }
 
 function history_new_layer() {
@@ -564,38 +564,38 @@ function history_layer_blending() {
 function history_new_material() {
 	let step: step_t = history_push(tr("New Material"));
 	step.canvas_type = 0;
-	step.canvas = JSON.parse(JSON.stringify(context_raw.material.canvas));
+	step.canvas = json_parse(json_stringify(context_raw.material.canvas));
 }
 
 function history_delete_material() {
 	let step: step_t = history_push(tr("Delete Material"));
 	step.canvas_type = 0;
-	step.canvas = JSON.parse(JSON.stringify(context_raw.material.canvas));
+	step.canvas = json_parse(json_stringify(context_raw.material.canvas));
 }
 
 function history_duplicate_material() {
 	let step: step_t = history_push(tr("Duplicate Material"));
 	step.canvas_type = 0;
-	step.canvas = JSON.parse(JSON.stringify(context_raw.material.canvas));
+	step.canvas = json_parse(json_stringify(context_raw.material.canvas));
 }
 
 function history_delete_material_group(group: node_group_t) {
 	let step: step_t = history_push(tr("Delete Node Group"));
 	step.canvas_type = canvas_type_t.MATERIAL;
 	step.canvas_group = project_material_groups.indexOf(group);
-	step.canvas = JSON.parse(JSON.stringify(group.canvas));
+	step.canvas = json_parse(json_stringify(group.canvas));
 }
 ///end
 
 function history_push(name: string): step_t {
 	///if (krom_windows || krom_linux || krom_darwin)
-	let filename: string = project_filepath == "" ? UIFiles.filename : project_filepath.substring(project_filepath.lastIndexOf(path_sep) + 1, project_filepath.length - 4);
+	let filename: string = project_filepath == "" ? ui_files_filename : project_filepath.substring(project_filepath.lastIndexOf(path_sep) + 1, project_filepath.length - 4);
 	sys_title_set(filename + "* - " + manifest_title);
 	///end
 
 	if (config_raw.touch_ui) {
 		// Refresh undo & redo buttons
-		UIMenubar.menu_handle.redraws = 2;
+		ui_menubar_menu_handle.redraws = 2;
 	}
 
 	if (history_undos < config_raw.undo_steps) history_undos++;
@@ -716,8 +716,8 @@ function history_swap_canvas(step: step_t) {
 	step.canvas = _canvas;
 	///end
 
-	UINodes.canvas_changed();
-	UINodes.hwnd.redraws = 2;
+	ui_nodes_canvas_changed();
+	ui_nodes_hwnd.redraws = 2;
 }
 
 type step_t = {

部分文件因文件數量過多而無法顯示