luboslenco hace 1 año
padre
commit
299ea5f99e
Se han modificado 50 ficheros con 847 adiciones y 837 borrados
  1. 8 8
      armorforge/Sources/TabObjects.ts
  2. 14 14
      armorlab/Sources/UINodesExt.ts
  3. 6 6
      armorlab/Sources/nodes/InpaintNode.ts
  4. 4 4
      armorlab/Sources/nodes/PhotoToPBRNode.ts
  5. 1 1
      armorlab/Sources/nodes/TextToPhotoNode.ts
  6. 4 4
      armorlab/Sources/nodes/TilingNode.ts
  7. 6 6
      armorlab/Sources/nodes/UpscaleNode.ts
  8. 2 2
      armorlab/Sources/nodes/VarianceNode.ts
  9. 3 3
      armorpaint/Sources/MakeMaterial.ts
  10. 5 6
      armorpaint/Sources/RenderPathPaint.ts
  11. 45 45
      armorpaint/Sources/SlotLayer.ts
  12. 9 9
      armorpaint/Sources/TabLayers.ts
  13. 4 4
      armorsculpt/Sources/ImportMesh.ts
  14. 1 1
      armorsculpt/Sources/MakeMaterial.ts
  15. 143 143
      base/Sources/Base.ts
  16. 3 2
      base/Sources/BoxPreferences.ts
  17. 1 1
      base/Sources/BoxProjects.ts
  18. 2 2
      base/Sources/Config.ts
  19. 15 17
      base/Sources/Console.ts
  20. 2 2
      base/Sources/Context.ts
  21. 6 6
      base/Sources/ExportArm.ts
  22. 25 25
      base/Sources/ExportTexture.ts
  23. 18 18
      base/Sources/ImportArm.ts
  24. 12 12
      base/Sources/ImportEnvmap.ts
  25. 1 1
      base/Sources/ImportFont.ts
  26. 12 15
      base/Sources/LineDraw.ts
  27. 2 2
      base/Sources/MakeVoxel.ts
  28. 1 1
      base/Sources/Path.ts
  29. 7 7
      base/Sources/Project.ts
  30. 3 4
      base/Sources/RenderPathBase.ts
  31. 1 1
      base/Sources/RenderPathDeferred.ts
  32. 1 1
      base/Sources/RenderPathForward.ts
  33. 3 3
      base/Sources/RenderPathRaytrace.ts
  34. 2 2
      base/Sources/RenderPathRaytraceBake.ts
  35. 4 4
      base/Sources/TabFonts.ts
  36. 5 4
      base/Sources/TabMaterials.ts
  37. 4 4
      base/Sources/TabTextures.ts
  38. 43 45
      base/Sources/UIBase.ts
  39. 11 11
      base/Sources/UIBox.ts
  40. 9 9
      base/Sources/UIFiles.ts
  41. 17 14
      base/Sources/UIHeader.ts
  42. 15 14
      base/Sources/UIMenu.ts
  43. 3 3
      base/Sources/UIMenubar.ts
  44. 20 20
      base/Sources/UINodes.ts
  45. 3 3
      base/Sources/UIStatus.ts
  46. 4 4
      base/Sources/UIToolbar.ts
  47. 22 23
      base/Sources/UIView2D.ts
  48. 24 27
      base/Sources/UtilRender.ts
  49. 13 14
      base/Sources/UtilUV.ts
  50. 278 260
      misc/pad/Sources/main.ts

+ 8 - 8
armorforge/Sources/TabObjects.ts

@@ -34,16 +34,16 @@ class TabObjects {
 
 					// Highlight every other line
 					if (lineCounter % 2 == 0) {
-						ui.g.color = ui.t.SEPARATOR_COL;
+						g2_set_color(ui.t.SEPARATOR_COL);
 						g2_fill_rect(0, ui._y, ui._window_w, zui_ELEMENT_H(ui));
-						ui.g.color = 0xffffffff;
+						g2_set_color(0xffffffff);
 					}
 
 					// Highlight selected line
 					if (currentObject == Context.raw.selectedObject) {
-						ui.g.color = 0xff205d9c;
+						g2_set_color(0xff205d9c);
 						g2_fill_rect(0, ui._y, ui._window_w, zui_ELEMENT_H(ui));
-						ui.g.color = 0xffffffff;
+						g2_set_color(0xffffffff);
 					}
 
 					if (currentObject.children.length > 0) {
@@ -55,9 +55,9 @@ class TabObjects {
 						ui._x += 18; // Sign offset
 
 						// Draw line that shows parent relations
-						ui.g.color = ui.t.ACCENT_COL;
+						g2_set_color(ui.t.ACCENT_COL);
 						g2_draw_line(ui._x - 10, ui._y + zui_ELEMENT_H(ui) / 2, ui._x, ui._y + zui_ELEMENT_H(ui) / 2);
-						ui.g.color = 0xffffffff;
+						g2_set_color(0xffffffff);
 
 						zui_text(currentObject.name);
 						ui._x -= 18;
@@ -113,9 +113,9 @@ class TabObjects {
 						}
 
 						// Draw line that shows parent relations
-						ui.g.color = ui.t.ACCENT_COL;
+						g2_set_color(ui.t.ACCENT_COL);
 						g2_draw_line(ui._x + 14, currentY, ui._x + 14, ui._y - zui_ELEMENT_H(ui) / 2);
-						ui.g.color = 0xffffffff;
+						g2_set_color(0xffffffff);
 					}
 				}
 				for (let c of _scene_root.children) {

+ 14 - 14
armorlab/Sources/UINodesExt.ts

@@ -8,7 +8,7 @@ class UINodesExt {
 		if (zui_button(tr("Run"))) {
 			Console.progress(tr("Processing"));
 
-			let delayIdleSleep = (_: any) => {
+			let delayIdleSleep = () => {
 				Krom.delayIdleSleep();
 			}
 			app_notify_on_render_2d(delayIdleSleep);
@@ -41,16 +41,16 @@ class UINodesExt {
 
 					if (texbase != null) {
 						let texpaint = render_path_render_targets.get("texpaint").image;
-						g2_begin(texpaint.g2, false);
+						g2_begin(texpaint, false);
 						g2_draw_scaled_image(texbase, 0, 0, Config.getTextureResX(), Config.getTextureResY());
-						g2_end(texpaint.g2);
+						g2_end();
 					}
 
 					if (texnor != null) {
 						let texpaint_nor = render_path_render_targets.get("texpaint_nor").image;
-						g2_begin(texpaint_nor.g2, false);
+						g2_begin(texpaint_nor, false);
 						g2_draw_scaled_image(texnor, 0, 0, Config.getTextureResX(), Config.getTextureResY());
-						g2_end(texpaint_nor.g2);
+						g2_end();
 					}
 
 					if (Base.pipeCopy == null) Base.makePipe();
@@ -60,23 +60,23 @@ class UINodesExt {
 					let texpaint_pack = render_path_render_targets.get("texpaint_pack").image;
 
 					if (texocc != null) {
-						g2_begin(texpaint_pack.g2, false);
-						texpaint_pack.g2.pipeline = Base.pipeCopyR;
+						g2_begin(texpaint_pack, false);
+						g2_set_pipeline(Base.pipeCopyR);
 						g2_draw_scaled_image(texocc, 0, 0, Config.getTextureResX(), Config.getTextureResY());
-						texpaint_pack.g2.pipeline = null;
-						g2_end(texpaint_pack.g2);
+						g2_set_pipeline(null);
+						g2_end();
 					}
 
 					if (texrough != null) {
-						g2_begin(texpaint_pack.g2, false);
-						texpaint_pack.g2.pipeline = Base.pipeCopyG;
+						g2_begin(texpaint_pack, false);
+						g2_set_pipeline(Base.pipeCopyG);
 						g2_draw_scaled_image(texrough, 0, 0, Config.getTextureResX(), Config.getTextureResY());
-						texpaint_pack.g2.pipeline = null;
-						g2_end(texpaint_pack.g2);
+						g2_set_pipeline(null);
+						g2_end();
 					}
 
 					if (texheight != null) {
-						g4_begin(texpaint_pack.g4);
+						g4_begin(texpaint_pack);
 						g4_set_pipeline(Base.pipeCopyA);
 						g4_set_tex(Base.pipeCopyATex, texheight);
 						g4_set_vertex_buffer(const_data_screen_aligned_vb);

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

@@ -25,7 +25,7 @@ class InpaintNode extends LogicNode {
 		if (InpaintNode.mask == null) {
 			InpaintNode.mask = image_create_render_target(Config.getTextureResX(), Config.getTextureResY(), TextureFormat.R8);
 			Base.notifyOnNextFrame(() => {
-				g4_begin(InpaintNode.mask.g4);
+				g4_begin(InpaintNode.mask);
 				g4_clear(color_from_floats(1.0, 1.0, 1.0, 1.0));
 				g4_end();
 			});
@@ -55,9 +55,9 @@ class InpaintNode extends LogicNode {
 
 			Console.progress(tr("Processing") + " - " + tr("Inpaint"));
 			Base.notifyOnNextFrame(() => {
-				g2_begin(InpaintNode.image.g2, false);
+				g2_begin(InpaintNode.image, false);
 				g2_draw_scaled_image(source, 0, 0, Config.getTextureResX(), Config.getTextureResY());
-				g2_end(InpaintNode.image.g2);
+				g2_end();
 
 				InpaintNode.auto ? InpaintNode.texsynthInpaint(InpaintNode.image, false, InpaintNode.mask, done) : InpaintNode.sdInpaint(InpaintNode.image, InpaintNode.mask, done);
 			});
@@ -69,7 +69,7 @@ class InpaintNode extends LogicNode {
 			this.inputs[0].getAsImage((source: image_t) => {
 				if (Base.pipeCopy == null) Base.makePipe();
 				if (const_data_screen_aligned_vb == null) const_data_create_screen_aligned_data();
-				g4_begin(InpaintNode.image.g4);
+				g4_begin(InpaintNode.image);
 				g4_set_pipeline(Base.pipeInpaintPreview);
 				g4_set_tex(Base.tex0InpaintPreview, source);
 				g4_set_tex(Base.texaInpaintPreview, InpaintNode.mask);
@@ -127,10 +127,10 @@ class InpaintNode extends LogicNode {
 						}
 					}
 
-					g2_begin(InpaintNode.temp.g2, false);
+					g2_begin(InpaintNode.temp, false);
 					// g2_drawImage(image, -x * 512, -y * 512);
 					g2_draw_scaled_image(image, 0, 0, 512, 512);
-					g2_end(InpaintNode.temp.g2);
+					g2_end();
 
 					let bytes_img = image_get_pixels(InpaintNode.temp);
 					let u8a = new Uint8Array(bytes_img);

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

@@ -48,7 +48,7 @@ class PhotoToPBRNode extends LogicNode {
 					let x = i % tilesX;
 					let y = Math.floor(i / tilesX);
 
-					g2_begin(PhotoToPBRNode.temp.g2, false);
+					g2_begin(PhotoToPBRNode.temp, false);
 					g2_draw_scaled_image(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW, -Config.getTextureResX(), Config.getTextureResY());
 					g2_draw_scaled_image(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW, Config.getTextureResX(), -Config.getTextureResY());
 					g2_draw_scaled_image(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW, -Config.getTextureResX(), -Config.getTextureResY());
@@ -56,7 +56,7 @@ class PhotoToPBRNode extends LogicNode {
 					g2_draw_scaled_image(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW + PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW + PhotoToPBRNode.tileW, -Config.getTextureResX(), Config.getTextureResY());
 					g2_draw_scaled_image(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW + PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW + PhotoToPBRNode.tileW, Config.getTextureResX(), -Config.getTextureResY());
 					g2_draw_scaled_image(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW, Config.getTextureResX(), Config.getTextureResY());
-					g2_end(PhotoToPBRNode.temp.g2);
+					g2_end();
 
 					let bytes_img = image_get_pixels(PhotoToPBRNode.temp);
 					let u8a = new Uint8Array(bytes_img);
@@ -142,9 +142,9 @@ class PhotoToPBRNode extends LogicNode {
 						///end
 
 						let temp2 = image_from_bytes(u8a.buffer, PhotoToPBRNode.tileW, PhotoToPBRNode.tileW);
-						g2_begin(PhotoToPBRNode.images[from].g2, false);
+						g2_begin(PhotoToPBRNode.images[from], false);
 						g2_draw_image(temp2, x * PhotoToPBRNode.tileW, y * PhotoToPBRNode.tileW);
-						g2_end(PhotoToPBRNode.images[from].g2);
+						g2_end();
 						Base.notifyOnNextFrame(() => {
 							image_unload(temp2);
 						});

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

@@ -95,7 +95,7 @@ class TextToPhotoNode extends LogicNode {
 		let ets: Float32Array[] = [];
 		let counter = 0;
 
-		let processing = (g: g2_t) => {
+		let processing = () => {
 			Console.progress(tr("Processing") + " - " + tr("Text to Photo") + " (" + (counter + 1) + "/" + (50 - offset) + ")");
 
 			let timestep = TextToPhotoNode.timesteps[counter + offset];

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

@@ -30,9 +30,9 @@ class TilingNode extends LogicNode {
 
 	override getAsImage = (from: i32, done: (img: image_t)=>void) => {
 		this.inputs[0].getAsImage((source: image_t) => {
-			g2_begin(TilingNode.image.g2, false);
+			g2_begin(TilingNode.image, false);
 			g2_draw_scaled_image(source, 0, 0, Config.getTextureResX(), Config.getTextureResY());
-			g2_end(TilingNode.image.g2);
+			g2_end();
 
 			Console.progress(tr("Processing") + " - " + tr("Tiling"));
 			Base.notifyOnNextFrame(() => {
@@ -52,12 +52,12 @@ class TilingNode extends LogicNode {
 	static sdTiling = (image: image_t, seed: i32/* = -1*/, done: (img: image_t)=>void) => {
 		TextToPhotoNode.tiling = false;
 		let tile = image_create_render_target(512, 512);
-		g2_begin(tile.g2, false);
+		g2_begin(tile, false);
 		g2_draw_scaled_image(image, -256, -256, 512, 512);
 		g2_draw_scaled_image(image, 256, -256, 512, 512);
 		g2_draw_scaled_image(image, -256, 256, 512, 512);
 		g2_draw_scaled_image(image, 256, 256, 512, 512);
-		g2_end(tile.g2);
+		g2_end();
 
 		let u8a = new Uint8Array(512 * 512);
 		for (let i = 0; i < 512 * 512; ++i) {

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

@@ -51,9 +51,9 @@ class UpscaleNode extends LogicNode {
 			image_unload(UpscaleNode.temp);
 		}
 		UpscaleNode.temp = image_create_render_target(size1w, size1h);
-		g2_begin(UpscaleNode.temp.g2, false);
+		g2_begin(UpscaleNode.temp, false);
 		g2_draw_scaled_image(source, 0, 0, size1w, size1h);
-		g2_end(UpscaleNode.temp.g2);
+		g2_end();
 
 		let bytes_img = image_get_pixels(UpscaleNode.temp);
 		let u8a = new Uint8Array(bytes_img);
@@ -97,7 +97,7 @@ class UpscaleNode extends LogicNode {
 			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) {
-					g2_begin(tileSource.g2, false);
+					g2_begin(tileSource, false);
 					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);
 					g2_draw_scaled_image(source, 32 - x * tileSize, 32 - y * tileSize, -source.width, -source.height);
@@ -105,11 +105,11 @@ class UpscaleNode extends LogicNode {
 					g2_draw_scaled_image(source, 32 - x * tileSize + tileSize, 32 - y * tileSize + tileSize, -source.width, source.height);
 					g2_draw_scaled_image(source, 32 - x * tileSize + tileSize, 32 - y * tileSize + tileSize, source.width, -source.height);
 					g2_draw_scaled_image(source, 32 - x * tileSize, 32 - y * tileSize, source.width, source.height);
-					g2_end(tileSource.g2);
+					g2_end();
 					let tileResult = UpscaleNode.doTile(tileSource);
-					g2_begin(result.g2, false);
+					g2_begin(result, false);
 					g2_draw_sub_image(tileResult, x * tileSize2x, y * tileSize2x, 64, 64, tileSize2x, tileSize2x);
-					g2_end(result.g2);
+					g2_end();
 					image_unload(tileResult);
 				}
 			}

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

@@ -27,9 +27,9 @@ class VarianceNode extends LogicNode {
 		let strength = (VarianceNode.inst.inputs[1].node as any).value;
 
 		VarianceNode.inst.inputs[0].getAsImage((source: image_t) => {
-			g2_begin(VarianceNode.temp.g2, false);
+			g2_begin(VarianceNode.temp, false);
 			g2_draw_scaled_image(source, 0, 0, 512, 512);
-			g2_end(VarianceNode.temp.g2);
+			g2_end();
 
 			let bytes_img = image_get_pixels(VarianceNode.temp);
 			let u8a = new Uint8Array(bytes_img);

+ 3 - 3
armorpaint/Sources/MakeMaterial.ts

@@ -183,7 +183,7 @@ class MakeMaterial {
 
 		if (bakePreviews) {
 			let current = _g2_current;
-			if (current != null) g2_end(current);
+			if (current != null) g2_end();
 			MakeMaterial.bakeNodePreviews();
 			if (current != null) g2_begin(current, false);
 		}
@@ -341,9 +341,9 @@ class MakeMaterial {
 			let rts = render_path_render_targets;
 			let texpaint_live = rts.get("texpaint_live");
 
-			g2_begin(image.g2, false);
+			g2_begin(image, false);
 			g2_draw_image(texpaint_live.image, 0, 0);
-			g2_end(image.g2);
+			g2_end();
 		}
 	}
 

+ 5 - 6
armorpaint/Sources/RenderPathPaint.ts

@@ -123,12 +123,12 @@ class RenderPathPaint {
 
 				let mo: mesh_object_t = scene_get_child(".ParticleEmitter").ext;
 				mo.base.visible = true;
-				mesh_object_render(mo,_render_path_current_g, "mesh",render_path_bind_params);
+				mesh_object_render(mo, "mesh",render_path_bind_params);
 				mo.base.visible = false;
 
 				mo = scene_get_child(".Particle").ext;
 				mo.base.visible = true;
-				mesh_object_render(mo,_render_path_current_g, "mesh",render_path_bind_params);
+				mesh_object_render(mo, "mesh",render_path_bind_params);
 				mo.base.visible = false;
 				render_path_end();
 			}
@@ -353,9 +353,9 @@ class RenderPathPaint {
 			let cc_context = shaderContexts[0];
 			if (const_data_screen_aligned_vb == null) const_data_create_screen_aligned_data();
 			g4_set_pipeline(cc_context._pipe_state);
-			uniforms_set_context_consts(_render_path_current_g, cc_context,render_path_bind_params);
-			uniforms_set_obj_consts(_render_path_current_g, cc_context, Project.paintObjects[0].base);
-			uniforms_set_material_consts(_render_path_current_g, cc_context, materialContexts[0]);
+			uniforms_set_context_consts(cc_context,render_path_bind_params);
+			uniforms_set_obj_consts(cc_context, Project.paintObjects[0].base);
+			uniforms_set_material_consts(cc_context, materialContexts[0]);
 			g4_set_vertex_buffer(const_data_screen_aligned_vb);
 			g4_set_index_buffer(const_data_screen_aligned_ib);
 			g4_draw();
@@ -498,7 +498,6 @@ class RenderPathPaint {
 		let plane: mesh_object_t = scene_get_child(".Plane").ext;
 		let geom = plane.data;
 
-		let g =_render_path_frame_g;
 		if (Base.pipeCursor == null) Base.makeCursorPipe();
 
 		render_path_set_target("");

+ 45 - 45
armorpaint/Sources/SlotLayer.ts

@@ -200,21 +200,21 @@ class SlotLayer {
 	}
 
 	static clear = (raw: SlotLayerRaw, baseColor = 0x00000000, baseImage: image_t = null, occlusion = 1.0, roughness = Base.defaultRough, metallic = 0.0) => {
-		g4_begin(raw.texpaint.g4);
+		g4_begin(raw.texpaint);
 		g4_clear(baseColor); // Base
 		g4_end();
 		if (baseImage != null) {
-			g2_begin(raw.texpaint.g2, false);
+			g2_begin(raw.texpaint, false);
 			g2_draw_scaled_image(baseImage, 0, 0, raw.texpaint.width, raw.texpaint.height);
-			g2_end(raw.texpaint.g2);
+			g2_end();
 		}
 
 		///if is_paint
 		if (SlotLayer.isLayer(raw)) {
-			g4_begin(raw.texpaint_nor.g4);
+			g4_begin(raw.texpaint_nor);
 			g4_clear(color_from_floats(0.5, 0.5, 1.0, 0.0)); // Nor
 			g4_end();
-			g4_begin(raw.texpaint_pack.g4);
+			g4_begin(raw.texpaint_pack);
 			g4_clear(color_from_floats(occlusion, roughness, metallic, 0.0)); // Occ, rough, met
 			g4_end();
 		}
@@ -227,11 +227,11 @@ class SlotLayer {
 	static invertMask = (raw: SlotLayerRaw) => {
 		if (Base.pipeInvert8 == null) Base.makePipe();
 		let inverted = image_create_render_target(raw.texpaint.width, raw.texpaint.height, TextureFormat.RGBA32);
-		g2_begin(inverted.g2, false);
-		inverted.g2.pipeline = Base.pipeInvert8;
+		g2_begin(inverted, false);
+		g2_set_pipeline(Base.pipeInvert8);
 		g2_draw_image(raw.texpaint, 0, 0);
-		inverted.g2.pipeline = null;
-		g2_end(inverted.g2);
+		g2_set_pipeline(null);
+		g2_end();
 		let _texpaint = raw.texpaint;
 		let _next = () => {
 			image_unload(_texpaint);
@@ -265,38 +265,38 @@ class SlotLayer {
 
 		if (Base.pipeMerge == null) Base.makePipe();
 		if (SlotLayer.isLayer(raw)) {
-			g2_begin(l.texpaint.g2, false);
-			l.texpaint.g2.pipeline = Base.pipeCopy;
+			g2_begin(l.texpaint, false);
+			g2_set_pipeline(Base.pipeCopy);
 			g2_draw_image(raw.texpaint, 0, 0);
-			l.texpaint.g2.pipeline = null;
-			g2_end(l.texpaint.g2);
+			g2_set_pipeline(null);
+			g2_end();
 			///if is_paint
-			g2_begin(l.texpaint_nor.g2, false);
-			l.texpaint_nor.g2.pipeline = Base.pipeCopy;
+			g2_begin(l.texpaint_nor, false);
+			g2_set_pipeline(Base.pipeCopy);
 			g2_draw_image(raw.texpaint_nor, 0, 0);
-			l.texpaint_nor.g2.pipeline = null;
-			g2_end(l.texpaint_nor.g2);
-			g2_begin(l.texpaint_pack.g2, false);
-			l.texpaint_pack.g2.pipeline = Base.pipeCopy;
+			g2_set_pipeline(null);
+			g2_end();
+			g2_begin(l.texpaint_pack, false);
+			g2_set_pipeline(Base.pipeCopy);
 			g2_draw_image(raw.texpaint_pack, 0, 0);
-			l.texpaint_pack.g2.pipeline = null;
-			g2_end(l.texpaint_pack.g2);
+			g2_set_pipeline(null);
+			g2_end();
 			///end
 		}
 		else if (SlotLayer.isMask(raw)) {
-			g2_begin(l.texpaint.g2, false);
-			l.texpaint.g2.pipeline = Base.pipeCopy8;
+			g2_begin(l.texpaint, false);
+			g2_set_pipeline(Base.pipeCopy8);
 			g2_draw_image(raw.texpaint, 0, 0);
-			l.texpaint.g2.pipeline = null;
-			g2_end(l.texpaint.g2);
+			g2_set_pipeline(null);
+			g2_end();
 		}
 
 		///if is_paint
-		g2_begin(l.texpaint_preview.g2, true, 0x00000000);
-		l.texpaint_preview.g2.pipeline = Base.pipeCopy;
+		g2_begin(l.texpaint_preview, true, 0x00000000);
+		g2_set_pipeline(Base.pipeCopy);
 		g2_draw_scaled_image(raw.texpaint_preview, 0, 0, raw.texpaint_preview.width, raw.texpaint_preview.height);
-		l.texpaint_preview.g2.pipeline = null;
-		g2_end(l.texpaint_preview.g2);
+		g2_set_pipeline(null);
+		g2_end();
 		///end
 
 		l.visible = raw.visible;
@@ -341,11 +341,11 @@ class SlotLayer {
 
 			let _texpaint = raw.texpaint;
 			raw.texpaint = image_create_render_target(resX, resY, format);
-			g2_begin(raw.texpaint.g2, false);
-			raw.texpaint.g2.pipeline = Base.pipeCopy;
+			g2_begin(raw.texpaint, false);
+			g2_set_pipeline(Base.pipeCopy);
 			g2_draw_scaled_image(_texpaint, 0, 0, resX, resY);
-			raw.texpaint.g2.pipeline = null;
-			g2_end(raw.texpaint.g2);
+			g2_set_pipeline(null);
+			g2_end();
 
 			///if is_paint
 			let _texpaint_nor = raw.texpaint_nor;
@@ -353,17 +353,17 @@ class SlotLayer {
 			raw.texpaint_nor = image_create_render_target(resX, resY, format);
 			raw.texpaint_pack = image_create_render_target(resX, resY, format);
 
-			g2_begin(raw.texpaint_nor.g2, false);
-			raw.texpaint_nor.g2.pipeline = Base.pipeCopy;
+			g2_begin(raw.texpaint_nor, false);
+			g2_set_pipeline(Base.pipeCopy);
 			g2_draw_scaled_image(_texpaint_nor, 0, 0, resX, resY);
-			raw.texpaint_nor.g2.pipeline = null;
-			g2_end(raw.texpaint_nor.g2);
+			g2_set_pipeline(null);
+			g2_end();
 
-			g2_begin(raw.texpaint_pack.g2, false);
-			raw.texpaint_pack.g2.pipeline = Base.pipeCopy;
+			g2_begin(raw.texpaint_pack, false);
+			g2_set_pipeline(Base.pipeCopy);
 			g2_draw_scaled_image(_texpaint_pack, 0, 0, resX, resY);
-			raw.texpaint_pack.g2.pipeline = null;
-			g2_end(raw.texpaint_pack.g2);
+			g2_set_pipeline(null);
+			g2_end();
 			///end
 
 			let _next = () => {
@@ -385,11 +385,11 @@ class SlotLayer {
 			let _texpaint = raw.texpaint;
 			raw.texpaint = image_create_render_target(resX, resY, TextureFormat.RGBA32);
 
-			g2_begin(raw.texpaint.g2, false);
-			raw.texpaint.g2.pipeline = Base.pipeCopy8;
+			g2_begin(raw.texpaint, false);
+			g2_set_pipeline(Base.pipeCopy8);
 			g2_draw_scaled_image(_texpaint, 0, 0, resX, resY);
-			raw.texpaint.g2.pipeline = null;
-			g2_end(raw.texpaint.g2);
+			g2_set_pipeline(null);
+			g2_end();
 
 			let _next = () => {
 				image_unload(_texpaint);

+ 9 - 9
armorpaint/Sources/TabLayers.ts

@@ -614,7 +614,7 @@ class TabLayers {
 				ui._w = _w;
 			}
 			if (l.fill_layer == null && SlotLayer.isMask(l)) {
-				ui.g.pipeline = UIView2D.pipe;
+				g2_set_pipeline(UIView2D.pipe);
 				///if krom_opengl
 				Krom.setPipeline(UIView2D.pipe.pipeline_);
 				///end
@@ -624,7 +624,7 @@ class TabLayers {
 			let state = zui_image(icon, 0xffffffff, iconH);
 
 			if (l.fill_layer == null && SlotLayer.isMask(l)) {
-				ui.g.pipeline = null;
+				g2_set_pipeline(null);
 			}
 
 			// Draw layer numbers when selecting a layer via keyboard shortcut
@@ -634,9 +634,9 @@ class TabLayers {
 					let number = String(i + 1) ;
 					let width = font_width(ui.font, ui.font_size, number) + 10;
 					let height = font_height(ui.font, ui.font_size);
-					ui.g.color = ui.t.TEXT_COL;
+					g2_set_color(ui.t.TEXT_COL);
 					g2_fill_rect(uix, uiy, width, height);
-					ui.g.color = ui.t.ACCENT_COL;
+					g2_set_color(ui.t.ACCENT_COL);
 					g2_draw_string(number, uix + 5, uiy);
 				}
 			}
@@ -845,7 +845,7 @@ class TabLayers {
 					Base.onLayersResized();
 				}
 				ui._y = _y;
-				zui_draw_string(ui.g, tr("Res"), null, 0, Align.Right);
+				zui_draw_string(tr("Res"), null, 0, Align.Right);
 				zui_end_element();
 
 				UIMenu.menuFill(ui);
@@ -982,12 +982,12 @@ class TabLayers {
 		if (Context.raw.maskPreviewLast != l) {
 			Context.raw.maskPreviewLast = l;
 			app_notify_on_init(() => {
-				g2_begin(Context.raw.maskPreviewRgba32.g2);
-				Context.raw.maskPreviewRgba32.g2.pipeline = UIView2D.pipe;
+				g2_begin(Context.raw.maskPreviewRgba32);
+				g2_set_pipeline(UIView2D.pipe);
 				g4_set_int(UIView2D.channelLocation, 1);
 				g2_draw_image(l.texpaint_preview, 0, 0);
-				g2_end(Context.raw.maskPreviewRgba32.g2);
-				Context.raw.maskPreviewRgba32.g2.pipeline = null;
+				g2_end();
+				g2_set_pipeline(null);
 			});
 		}
 		///end

+ 4 - 4
armorsculpt/Sources/ImportMesh.ts

@@ -129,11 +129,11 @@ class ImportMesh {
 					}
 					let imgmesh = image_from_bytes(f32.buffer, Config.getTextureResX(), Config.getTextureResY(), TextureFormat.RGBA128);
 					let texpaint = Project.layers[0].texpaint;
-					g2_begin(texpaint.g2, false);
-					texpaint.g2.pipeline = Base.pipeCopy128;
+					g2_begin(texpaint, false);
+					g2_set_pipeline(Base.pipeCopy128);
 					g2_draw_scaled_image(imgmesh, 0, 0, Config.getTextureResX(), Config.getTextureResY());
-					texpaint.g2.pipeline = null;
-					g2_end(texpaint.g2);
+					g2_set_pipeline(null);
+					g2_end();
 				});
 			});
 		}

+ 1 - 1
armorsculpt/Sources/MakeMaterial.ts

@@ -178,7 +178,7 @@ class MakeMaterial {
 
 		if (bakePreviews) {
 			let current = _g2_current;
-			if (current != null) g2_end(current);
+			if (current != null) g2_end();
 			MakeMaterial.bakeNodePreviews();
 			if (current != null) g2_begin(current, false);
 		}

+ 143 - 143
base/Sources/Base.ts

@@ -157,7 +157,7 @@ class Base {
 						Base.font.font_ = Krom.g2_font_13(Base.font.blob);
 						Base.font.glyphs = _g2_font_glyphs;
 					}
-					else font_init(Base.font);
+					else g2_font_init(Base.font);
 
 					Base.colorWheel = imageColorWheel;
 					Base.colorWheelGradient = imageColorWheelGradient;
@@ -685,7 +685,7 @@ class Base {
 		return null;
 	}
 
-	static render = (g: g2_t) => {
+	static render = () => {
 		if (sys_width() == 0 || sys_height() == 0) return;
 
 		if (Context.raw.frame == 2) {
@@ -761,7 +761,7 @@ class Base {
 			let inv = (Base.dragMaterial != null || (Base.dragLayer != null && Base.dragLayer.fill_layer != null)) ? h : 0;
 			///end
 
-			g.color = Base.dragTint;
+			g2_set_color(Base.dragTint);
 
 			///if (is_paint || is_sculpt)
 			let bgRect = Base.getDragBackground();
@@ -773,13 +773,13 @@ class Base {
 			Base.dragRect == null ?
 				g2_draw_scaled_image(img, mouse_x + Base.dragOffX, mouse_y + Base.dragOffY + inv, size, h - inv * 2) :
 				g2_draw_scaled_sub_image(img, Base.dragRect.x, Base.dragRect.y, Base.dragRect.w, Base.dragRect.h, mouse_x + Base.dragOffX, mouse_y + Base.dragOffY + inv, size, h - inv * 2);
-			g.color = 0xffffffff;
+			g2_set_color(0xffffffff);
 		}
 
 		let usingMenu = UIMenu.show && mouse_y > UIHeader.headerh;
 		Base.uiEnabled = !UIBox.show && !usingMenu && !Base.isComboSelected();
-		if (UIBox.show) UIBox.render(g);
-		if (UIMenu.show) UIMenu.render(g);
+		if (UIBox.show) UIBox.render();
+		if (UIMenu.show) UIMenu.render();
 
 		// Save last pos for continuos paint
 		Context.raw.lastPaintVecX = Context.raw.paintVec.x;
@@ -826,7 +826,7 @@ class Base {
 	}
 
 	static notifyOnNextFrame = (f: ()=>void) => {
-		let _render = (_: any) => {
+		let _render = () => {
 			app_notify_on_init(() => {
 				let _update = () => {
 					app_notify_on_init(f);
@@ -1018,21 +1018,21 @@ class Base {
 		let texpaint = render_path_render_targets.get("texpaint").image;
 		let texpaint_nor = render_path_render_targets.get("texpaint_nor").image;
 		let texpaint_pack = render_path_render_targets.get("texpaint_pack").image;
-		g2_begin(texpaint.g2, false);
+		g2_begin(texpaint, false);
 		g2_draw_scaled_image(Res.get("placeholder.k"), 0, 0, Config.getTextureResX(), Config.getTextureResY()); // Base
-		g2_end(texpaint.g2);
-		g4_begin(texpaint_nor.g4);
+		g2_end();
+		g4_begin(texpaint_nor);
 		g4_clear(color_from_floats(0.5, 0.5, 1.0, 0.0)); // Nor
 		g4_end();
-		g4_begin(texpaint_pack.g4);
+		g4_begin(texpaint_pack);
 		g4_clear(color_from_floats(1.0, 0.4, 0.0, 0.0)); // Occ, rough, met
 		g4_end();
 		let texpaint_nor_empty = render_path_render_targets.get("texpaint_nor_empty").image;
 		let texpaint_pack_empty = render_path_render_targets.get("texpaint_pack_empty").image;
-		g4_begin(texpaint_nor_empty.g4);
+		g4_begin(texpaint_nor_empty);
 		g4_clear(color_from_floats(0.5, 0.5, 1.0, 0.0)); // Nor
 		g4_end();
-		g4_begin(texpaint_pack_empty.g4);
+		g4_begin(texpaint_pack_empty);
 		g4_clear(color_from_floats(1.0, 0.4, 0.0, 0.0)); // Occ, rough, met
 		g4_end();
 		///end
@@ -1096,15 +1096,15 @@ class Base {
 
 	static makeMergePipe = (red: bool, green: bool, blue: bool, alpha: bool): pipeline_t => {
 		let pipe = pipeline_create();
-		pipe.vertexShader = sys_get_shader("pass.vert");
-		pipe.fragmentShader = sys_get_shader("layer_merge.frag");
+		pipe.vertex_shader = sys_get_shader("pass.vert");
+		pipe.fragment_shader = sys_get_shader("layer_merge.frag");
 		let vs = vertex_struct_create();
 		vertex_struct_add(vs, "pos", VertexData.F32_2X);
-		pipe.inputLayout = [vs];
-		pipe.colorWriteMasksRed = [red];
-		pipe.colorWriteMasksGreen = [green];
-		pipe.colorWriteMasksBlue = [blue];
-		pipe.colorWriteMasksAlpha = [alpha];
+		pipe.input_layout = [vs];
+		pipe.color_write_masks_red = [red];
+		pipe.color_write_masks_green = [green];
+		pipe.color_write_masks_blue = [blue];
+		pipe.color_write_masks_alpha = [alpha];
 		pipeline_compile(pipe);
 		return pipe;
 	}
@@ -1127,54 +1127,54 @@ class Base {
 
 		{
 			Base.pipeCopy = pipeline_create();
-			Base.pipeCopy.vertexShader = sys_get_shader("layer_view.vert");
-			Base.pipeCopy.fragmentShader = sys_get_shader("layer_copy.frag");
+			Base.pipeCopy.vertex_shader = sys_get_shader("layer_view.vert");
+			Base.pipeCopy.fragment_shader = sys_get_shader("layer_copy.frag");
 			let vs = vertex_struct_create();
 			vertex_struct_add(vs, "pos", VertexData.F32_3X);
 			vertex_struct_add(vs, "tex", VertexData.F32_2X);
 			vertex_struct_add(vs, "col", VertexData.U8_4X_Normalized);
-			Base.pipeCopy.inputLayout = [vs];
+			Base.pipeCopy.input_layout = [vs];
 			pipeline_compile(Base.pipeCopy);
 		}
 
 		{
 			Base.pipeCopyBGRA = pipeline_create();
-			Base.pipeCopyBGRA.vertexShader = sys_get_shader("layer_view.vert");
-			Base.pipeCopyBGRA.fragmentShader = sys_get_shader("layer_copy_bgra.frag");
+			Base.pipeCopyBGRA.vertex_shader = sys_get_shader("layer_view.vert");
+			Base.pipeCopyBGRA.fragment_shader = sys_get_shader("layer_copy_bgra.frag");
 			let vs = vertex_struct_create();
 			vertex_struct_add(vs, "pos", VertexData.F32_3X);
 			vertex_struct_add(vs, "tex", VertexData.F32_2X);
 			vertex_struct_add(vs, "col", VertexData.U8_4X_Normalized);
-			Base.pipeCopyBGRA.inputLayout = [vs];
+			Base.pipeCopyBGRA.input_layout = [vs];
 			pipeline_compile(Base.pipeCopyBGRA);
 		}
 
 		///if (krom_metal || krom_vulkan || krom_direct3d12)
 		{
 			Base.pipeCopy8 = pipeline_create();
-			Base.pipeCopy8.vertexShader = sys_get_shader("layer_view.vert");
-			Base.pipeCopy8.fragmentShader = sys_get_shader("layer_copy.frag");
+			Base.pipeCopy8.vertex_shader = sys_get_shader("layer_view.vert");
+			Base.pipeCopy8.fragment_shader = sys_get_shader("layer_copy.frag");
 			let vs = vertex_struct_create();
 			vertex_struct_add(vs, "pos", VertexData.F32_3X);
 			vertex_struct_add(vs, "tex", VertexData.F32_2X);
 			vertex_struct_add(vs, "col", VertexData.U8_4X_Normalized);
-			Base.pipeCopy8.inputLayout = [vs];
-			Base.pipeCopy8.colorAttachmentCount = 1;
-			Base.pipeCopy8.colorAttachments[0] = TextureFormat.R8;
+			Base.pipeCopy8.input_layout = [vs];
+			Base.pipeCopy8.color_attachment_count = 1;
+			Base.pipeCopy8.color_attachments[0] = TextureFormat.R8;
 			pipeline_compile(Base.pipeCopy8);
 		}
 
 		{
 			Base.pipeCopy128 = pipeline_create();
-			Base.pipeCopy128.vertexShader = sys_get_shader("layer_view.vert");
-			Base.pipeCopy128.fragmentShader = sys_get_shader("layer_copy.frag");
+			Base.pipeCopy128.vertex_shader = sys_get_shader("layer_view.vert");
+			Base.pipeCopy128.fragment_shader = sys_get_shader("layer_copy.frag");
 			let vs = vertex_struct_create();
 			vertex_struct_add(vs, "pos", VertexData.F32_3X);
 			vertex_struct_add(vs, "tex", VertexData.F32_2X);
 			vertex_struct_add(vs, "col", VertexData.U8_4X_Normalized);
-			Base.pipeCopy128.inputLayout = [vs];
-			Base.pipeCopy128.colorAttachmentCount = 1;
-			Base.pipeCopy128.colorAttachments[0] = TextureFormat.RGBA128;
+			Base.pipeCopy128.input_layout = [vs];
+			Base.pipeCopy128.color_attachment_count = 1;
+			Base.pipeCopy128.color_attachments[0] = TextureFormat.RGBA128;
 			pipeline_compile(Base.pipeCopy128);
 		}
 		///else
@@ -1185,25 +1185,25 @@ class Base {
 		///if (is_paint || is_sculpt)
 		{
 			Base.pipeInvert8 = pipeline_create();
-			Base.pipeInvert8.vertexShader = sys_get_shader("layer_view.vert");
-			Base.pipeInvert8.fragmentShader = sys_get_shader("layer_invert.frag");
+			Base.pipeInvert8.vertex_shader = sys_get_shader("layer_view.vert");
+			Base.pipeInvert8.fragment_shader = sys_get_shader("layer_invert.frag");
 			let vs = vertex_struct_create();
 			vertex_struct_add(vs, "pos", VertexData.F32_3X);
 			vertex_struct_add(vs, "tex", VertexData.F32_2X);
 			vertex_struct_add(vs, "col", VertexData.U8_4X_Normalized);
-			Base.pipeInvert8.inputLayout = [vs];
-			Base.pipeInvert8.colorAttachmentCount = 1;
-			Base.pipeInvert8.colorAttachments[0] = TextureFormat.R8;
+			Base.pipeInvert8.input_layout = [vs];
+			Base.pipeInvert8.color_attachment_count = 1;
+			Base.pipeInvert8.color_attachments[0] = TextureFormat.R8;
 			pipeline_compile(Base.pipeInvert8);
 		}
 
 		{
 			Base.pipeApplyMask = pipeline_create();
-			Base.pipeApplyMask.vertexShader = sys_get_shader("pass.vert");
-			Base.pipeApplyMask.fragmentShader = sys_get_shader("mask_apply.frag");
+			Base.pipeApplyMask.vertex_shader = sys_get_shader("pass.vert");
+			Base.pipeApplyMask.fragment_shader = sys_get_shader("mask_apply.frag");
 			let vs = vertex_struct_create();
 			vertex_struct_add(vs, "pos", VertexData.F32_2X);
-			Base.pipeApplyMask.inputLayout = [vs];
+			Base.pipeApplyMask.input_layout = [vs];
 			pipeline_compile(Base.pipeApplyMask);
 			Base.tex0Mask = pipeline_get_tex_unit(Base.pipeApplyMask, "tex0");
 			Base.texaMask = pipeline_get_tex_unit(Base.pipeApplyMask, "texa");
@@ -1211,11 +1211,11 @@ class Base {
 
 		{
 			Base.pipeMergeMask = pipeline_create();
-			Base.pipeMergeMask.vertexShader = sys_get_shader("pass.vert");
-			Base.pipeMergeMask.fragmentShader = sys_get_shader("mask_merge.frag");
+			Base.pipeMergeMask.vertex_shader = sys_get_shader("pass.vert");
+			Base.pipeMergeMask.fragment_shader = sys_get_shader("mask_merge.frag");
 			let vs = vertex_struct_create();
 			vertex_struct_add(vs, "pos", VertexData.F32_2X);
-			Base.pipeMergeMask.inputLayout = [vs];
+			Base.pipeMergeMask.input_layout = [vs];
 			pipeline_compile(Base.pipeMergeMask);
 			Base.tex0MergeMask = pipeline_get_tex_unit(Base.pipeMergeMask, "tex0");
 			Base.texaMergeMask = pipeline_get_tex_unit(Base.pipeMergeMask, "texa");
@@ -1225,11 +1225,11 @@ class Base {
 
 		{
 			Base.pipeColorIdToMask = pipeline_create();
-			Base.pipeColorIdToMask.vertexShader = sys_get_shader("pass.vert");
-			Base.pipeColorIdToMask.fragmentShader = sys_get_shader("mask_colorid.frag");
+			Base.pipeColorIdToMask.vertex_shader = sys_get_shader("pass.vert");
+			Base.pipeColorIdToMask.fragment_shader = sys_get_shader("mask_colorid.frag");
 			let vs = vertex_struct_create();
 			vertex_struct_add(vs, "pos", VertexData.F32_2X);
-			Base.pipeColorIdToMask.inputLayout = [vs];
+			Base.pipeColorIdToMask.input_layout = [vs];
 			pipeline_compile(Base.pipeColorIdToMask);
 			Base.texpaintColorId = pipeline_get_tex_unit(Base.pipeColorIdToMask, "texpaint_colorid");
 			Base.texColorId = pipeline_get_tex_unit(Base.pipeColorIdToMask, "texcolorid");
@@ -1239,56 +1239,56 @@ class Base {
 		///if is_lab
 		{
 			Base.pipeCopyR = pipeline_create();
-			Base.pipeCopyR.vertexShader = sys_get_shader("layer_view.vert");
-			Base.pipeCopyR.fragmentShader = sys_get_shader("layer_copy.frag");
+			Base.pipeCopyR.vertex_shader = sys_get_shader("layer_view.vert");
+			Base.pipeCopyR.fragment_shader = sys_get_shader("layer_copy.frag");
 			let vs = vertex_struct_create();
 			vertex_struct_add(vs, "pos", VertexData.F32_3X);
 			vertex_struct_add(vs, "tex", VertexData.F32_2X);
 			vertex_struct_add(vs, "col", VertexData.U8_4X_Normalized);
-			Base.pipeCopyR.inputLayout = [vs];
-			Base.pipeCopyR.colorWriteMasksGreen = [false];
-			Base.pipeCopyR.colorWriteMasksBlue = [false];
-			Base.pipeCopyR.colorWriteMasksAlpha = [false];
+			Base.pipeCopyR.input_layout = [vs];
+			Base.pipeCopyR.color_write_masks_green = [false];
+			Base.pipeCopyR.color_write_masks_blue = [false];
+			Base.pipeCopyR.color_write_masks_alpha = [false];
 			pipeline_compile(Base.pipeCopyR);
 		}
 
 		{
 			Base.pipeCopyG = pipeline_create();
-			Base.pipeCopyG.vertexShader = sys_get_shader("layer_view.vert");
-			Base.pipeCopyG.fragmentShader = sys_get_shader("layer_copy.frag");
+			Base.pipeCopyG.vertex_shader = sys_get_shader("layer_view.vert");
+			Base.pipeCopyG.fragment_shader = sys_get_shader("layer_copy.frag");
 			let vs = vertex_struct_create();
 			vertex_struct_add(vs, "pos", VertexData.F32_3X);
 			vertex_struct_add(vs, "tex", VertexData.F32_2X);
 			vertex_struct_add(vs, "col", VertexData.U8_4X_Normalized);
-			Base.pipeCopyG.inputLayout = [vs];
-			Base.pipeCopyG.colorWriteMasksRed = [false];
-			Base.pipeCopyG.colorWriteMasksBlue = [false];
-			Base.pipeCopyG.colorWriteMasksAlpha = [false];
+			Base.pipeCopyG.input_layout = [vs];
+			Base.pipeCopyG.color_write_masks_red = [false];
+			Base.pipeCopyG.color_write_masks_blue = [false];
+			Base.pipeCopyG.color_write_masks_alpha = [false];
 			pipeline_compile(Base.pipeCopyG);
 		}
 
 		{
 			Base.pipeCopyB = pipeline_create();
-			Base.pipeCopyB.vertexShader = sys_get_shader("layer_view.vert");
-			Base.pipeCopyB.fragmentShader = sys_get_shader("layer_copy.frag");
+			Base.pipeCopyB.vertex_shader = sys_get_shader("layer_view.vert");
+			Base.pipeCopyB.fragment_shader = sys_get_shader("layer_copy.frag");
 			let vs = vertex_struct_create();
 			vertex_struct_add(vs, "pos", VertexData.F32_3X);
 			vertex_struct_add(vs, "tex", VertexData.F32_2X);
 			vertex_struct_add(vs, "col", VertexData.U8_4X_Normalized);
-			Base.pipeCopyB.inputLayout = [vs];
-			Base.pipeCopyB.colorWriteMasksRed = [false];
-			Base.pipeCopyB.colorWriteMasksGreen = [false];
-			Base.pipeCopyB.colorWriteMasksAlpha = [false];
+			Base.pipeCopyB.input_layout = [vs];
+			Base.pipeCopyB.color_write_masks_red = [false];
+			Base.pipeCopyB.color_write_masks_green = [false];
+			Base.pipeCopyB.color_write_masks_alpha = [false];
 			pipeline_compile(Base.pipeCopyB);
 		}
 
 		{
 			Base.pipeInpaintPreview = pipeline_create();
-			Base.pipeInpaintPreview.vertexShader = sys_get_shader("pass.vert");
-			Base.pipeInpaintPreview.fragmentShader = sys_get_shader("inpaint_preview.frag");
+			Base.pipeInpaintPreview.vertex_shader = sys_get_shader("pass.vert");
+			Base.pipeInpaintPreview.fragment_shader = sys_get_shader("inpaint_preview.frag");
 			let vs = vertex_struct_create();
 			vertex_struct_add(vs, "pos", VertexData.F32_2X);
-			Base.pipeInpaintPreview.inputLayout = [vs];
+			Base.pipeInpaintPreview.input_layout = [vs];
 			pipeline_compile(Base.pipeInpaintPreview);
 			Base.tex0InpaintPreview = pipeline_get_tex_unit(Base.pipeInpaintPreview, "tex0");
 			Base.texaInpaintPreview = pipeline_get_tex_unit(Base.pipeInpaintPreview, "texa");
@@ -1298,28 +1298,28 @@ class Base {
 
 	static makePipeCopyRGB = () => {
 		Base.pipeCopyRGB = pipeline_create();
-		Base.pipeCopyRGB.vertexShader = sys_get_shader("layer_view.vert");
-		Base.pipeCopyRGB.fragmentShader = sys_get_shader("layer_copy.frag");
+		Base.pipeCopyRGB.vertex_shader = sys_get_shader("layer_view.vert");
+		Base.pipeCopyRGB.fragment_shader = sys_get_shader("layer_copy.frag");
 		let vs = vertex_struct_create();
 		vertex_struct_add(vs, "pos", VertexData.F32_3X);
 		vertex_struct_add(vs, "tex", VertexData.F32_2X);
 		vertex_struct_add(vs, "col", VertexData.U8_4X_Normalized);
-		Base.pipeCopyRGB.inputLayout = [vs];
-		Base.pipeCopyRGB.colorWriteMasksAlpha = [false];
+		Base.pipeCopyRGB.input_layout = [vs];
+		Base.pipeCopyRGB.color_write_masks_alpha = [false];
 		pipeline_compile(Base.pipeCopyRGB);
 	}
 
 	///if is_lab
 	static makePipeCopyA = () => {
 		Base.pipeCopyA = pipeline_create();
-		Base.pipeCopyA.vertexShader = sys_get_shader("pass.vert");
-		Base.pipeCopyA.fragmentShader = sys_get_shader("layer_copy_rrrr.frag");
+		Base.pipeCopyA.vertex_shader = sys_get_shader("pass.vert");
+		Base.pipeCopyA.fragment_shader = sys_get_shader("layer_copy_rrrr.frag");
 		let vs = vertex_struct_create();
 		vertex_struct_add(vs, "pos", VertexData.F32_2X);
-		Base.pipeCopyA.inputLayout = [vs];
-		Base.pipeCopyA.colorWriteMasksRed = [false];
-		Base.pipeCopyA.colorWriteMasksGreen = [false];
-		Base.pipeCopyA.colorWriteMasksBlue = [false];
+		Base.pipeCopyA.input_layout = [vs];
+		Base.pipeCopyA.color_write_masks_red = [false];
+		Base.pipeCopyA.color_write_masks_green = [false];
+		Base.pipeCopyA.color_write_masks_blue = [false];
 		pipeline_compile(Base.pipeCopyA);
 		Base.pipeCopyATex = pipeline_get_tex_unit(Base.pipeCopyA, "tex");
 	}
@@ -1327,8 +1327,8 @@ class Base {
 
 	static makeCursorPipe = () => {
 		Base.pipeCursor = pipeline_create();
-		Base.pipeCursor.vertexShader = sys_get_shader("cursor.vert");
-		Base.pipeCursor.fragmentShader = sys_get_shader("cursor.frag");
+		Base.pipeCursor.vertex_shader = sys_get_shader("cursor.vert");
+		Base.pipeCursor.fragment_shader = sys_get_shader("cursor.frag");
 		let vs = vertex_struct_create();
 		///if (krom_metal || krom_vulkan)
 		vertex_struct_add(vs, "tex", VertexData.I16_2X_Normalized);
@@ -1337,11 +1337,11 @@ class Base {
 		vertex_struct_add(vs, "nor", VertexData.I16_2X_Normalized);
 		vertex_struct_add(vs, "tex", VertexData.I16_2X_Normalized);
 		///end
-		Base.pipeCursor.inputLayout = [vs];
-		Base.pipeCursor.blendSource = BlendingFactor.SourceAlpha;
-		Base.pipeCursor.blendDestination = BlendingFactor.InverseSourceAlpha;
-		Base.pipeCursor.depthWrite = false;
-		Base.pipeCursor.depthMode = CompareMode.Always;
+		Base.pipeCursor.input_layout = [vs];
+		Base.pipeCursor.blend_source = BlendingFactor.SourceAlpha;
+		Base.pipeCursor.blend_dest = BlendingFactor.InverseSourceAlpha;
+		Base.pipeCursor.depth_write = false;
+		Base.pipeCursor.depth_mode = CompareMode.Always;
 		pipeline_compile(Base.pipeCursor);
 		Base.cursorVP = pipeline_get_const_loc(Base.pipeCursor, "VP");
 		Base.cursorInvVP = pipeline_get_const_loc(Base.pipeCursor, "invVP");
@@ -1599,11 +1599,11 @@ class Base {
 		Base.makeTempImg();
 		if (const_data_screen_aligned_vb == null) const_data_create_screen_aligned_data();
 
-		g2_begin(Base.tempImage.g2, false); // Copy to temp
-		Base.tempImage.g2.pipeline = Base.pipeCopy;
+		g2_begin(Base.tempImage, false); // Copy to temp
+		g2_set_pipeline(Base.pipeCopy);
 		g2_draw_image(l0.texpaint, 0, 0);
-		Base.tempImage.g2.pipeline = null;
-		g2_end(Base.tempImage.g2);
+		g2_set_pipeline(null);
+		g2_end();
 
 		let empty = render_path_render_targets.get("empty_white").image;
 		let mask = empty;
@@ -1616,7 +1616,7 @@ class Base {
 		}
 
 		if (SlotLayer.isMask(l1)) {
-			g4_begin(l0.texpaint.g4);
+			g4_begin(l0.texpaint);
 			g4_set_pipeline(Base.pipeMergeMask);
 			g4_set_tex(Base.tex0MergeMask, l1.texpaint);
 			g4_set_tex(Base.texaMergeMask, Base.tempImage);
@@ -1630,7 +1630,7 @@ class Base {
 
 		if (SlotLayer.isLayer(l1)) {
 			if (l1.paintBase) {
-				g4_begin(l0.texpaint.g4);
+				g4_begin(l0.texpaint);
 				g4_set_pipeline(Base.pipeMerge);
 				g4_set_tex(Base.tex0, l1.texpaint);
 				g4_set_tex(Base.tex1, empty);
@@ -1645,14 +1645,14 @@ class Base {
 			}
 
 			///if is_paint
-			g2_begin(Base.tempImage.g2, false);
-			Base.tempImage.g2.pipeline = Base.pipeCopy;
+			g2_begin(Base.tempImage, false);
+			g2_set_pipeline(Base.pipeCopy);
 			g2_draw_image(l0.texpaint_nor, 0, 0);
-			Base.tempImage.g2.pipeline = null;
-			g2_end(Base.tempImage.g2);
+			g2_set_pipeline(null);
+			g2_end();
 
 			if (l1.paintNor) {
-				g4_begin(l0.texpaint_nor.g4);
+				g4_begin(l0.texpaint_nor);
 				g4_set_pipeline(Base.pipeMerge);
 				g4_set_tex(Base.tex0, l1.texpaint);
 				g4_set_tex(Base.tex1, l1.texpaint_nor);
@@ -1666,11 +1666,11 @@ class Base {
 				g4_end();
 			}
 
-			g2_begin(Base.tempImage.g2, false);
-			Base.tempImage.g2.pipeline = Base.pipeCopy;
+			g2_begin(Base.tempImage, false);
+			g2_set_pipeline(Base.pipeCopy);
 			g2_draw_image(l0.texpaint_pack, 0, 0);
-			Base.tempImage.g2.pipeline = null;
-			g2_end(Base.tempImage.g2);
+			g2_set_pipeline(null);
+			g2_end();
 
 			if (l1.paintOcc || l1.paintRough || l1.paintMet || l1.paintHeight) {
 				if (l1.paintOcc && l1.paintRough && l1.paintMet && l1.paintHeight) {
@@ -1695,13 +1695,13 @@ class Base {
 		let empty = render_path_render_targets.get("empty_white").image;
 
 		// Clear export layer
-		g4_begin(Base.expa.g4);
+		g4_begin(Base.expa);
 		g4_clear(color_from_floats(0.0, 0.0, 0.0, 0.0));
 		g4_end();
-		g4_begin(Base.expb.g4);
+		g4_begin(Base.expb);
 		g4_clear(color_from_floats(0.5, 0.5, 1.0, 0.0));
 		g4_end();
-		g4_begin(Base.expc.g4);
+		g4_begin(Base.expc);
 		g4_clear(color_from_floats(1.0, 0.0, 0.0, 0.0));
 		g4_end();
 
@@ -1715,8 +1715,8 @@ class Base {
 			if (l1masks != null) {
 				if (l1masks.length > 1) {
 					Base.makeTempMaskImg();
-					g2_begin(Base.tempMaskImage.g2, true, 0x00000000);
-					g2_end(Base.tempMaskImage.g2);
+					g2_begin(Base.tempMaskImage, true, 0x00000000);
+					g2_end();
 					let l1: any = { texpaint: Base.tempMaskImage };
 					for (let i = 0; i < l1masks.length; ++i) {
 						Base.mergeLayer(l1, l1masks[i]);
@@ -1727,13 +1727,13 @@ class Base {
 			}
 
 			if (l1.paintBase) {
-				g2_begin(Base.tempImage.g2, false); // Copy to temp
-				Base.tempImage.g2.pipeline = Base.pipeCopy;
+				g2_begin(Base.tempImage, false); // Copy to temp
+				g2_set_pipeline(Base.pipeCopy);
 				g2_draw_image(Base.expa, 0, 0);
-				Base.tempImage.g2.pipeline = null;
-				g2_end(Base.tempImage.g2);
+				g2_set_pipeline(null);
+				g2_end();
 
-				g4_begin(Base.expa.g4);
+				g4_begin(Base.expa);
 				g4_set_pipeline(Base.pipeMerge);
 				g4_set_tex(Base.tex0, l1.texpaint);
 				g4_set_tex(Base.tex1, empty);
@@ -1749,13 +1749,13 @@ class Base {
 
 			///if is_paint
 			if (l1.paintNor) {
-				g2_begin(Base.tempImage.g2, false);
-				Base.tempImage.g2.pipeline = Base.pipeCopy;
+				g2_begin(Base.tempImage, false);
+				g2_set_pipeline(Base.pipeCopy);
 				g2_draw_image(Base.expb, 0, 0);
-				Base.tempImage.g2.pipeline = null;
-				g2_end(Base.tempImage.g2);
+				g2_set_pipeline(null);
+				g2_end();
 
-				g4_begin(Base.expb.g4);
+				g4_begin(Base.expb);
 				g4_set_pipeline(Base.pipeMerge);
 				g4_set_tex(Base.tex0, l1.texpaint);
 				g4_set_tex(Base.tex1, l1.texpaint_nor);
@@ -1770,11 +1770,11 @@ class Base {
 			}
 
 			if (l1.paintOcc || l1.paintRough || l1.paintMet || l1.paintHeight) {
-				g2_begin(Base.tempImage.g2, false);
-				Base.tempImage.g2.pipeline = Base.pipeCopy;
+				g2_begin(Base.tempImage, false);
+				g2_set_pipeline(Base.pipeCopy);
 				g2_draw_image(Base.expc, 0, 0);
-				Base.tempImage.g2.pipeline = null;
-				g2_end(Base.tempImage.g2);
+				g2_set_pipeline(null);
+				g2_end();
 
 				if (l1.paintOcc && l1.paintRough && l1.paintMet && l1.paintHeight) {
 					Base.commandsMergePack(Base.pipeMerge, Base.expc, l1.texpaint, l1.texpaint_pack, SlotLayer.getOpacity(l1), mask, l1.paintHeightBlend ? -3 : -1);
@@ -1790,12 +1790,12 @@ class Base {
 
 		///if krom_metal
 		// Flush command list
-		g2_begin(Base.expa.g2, false);
-		g2_end(Base.expa.g2);
-		g2_begin(Base.expb.g2, false);
-		g2_end(Base.expb.g2);
-		g2_begin(Base.expc.g2, false);
-		g2_end(Base.expc.g2);
+		g2_begin(Base.expa, false);
+		g2_end();
+		g2_begin(Base.expb, false);
+		g2_end();
+		g2_begin(Base.expc, false);
+		g2_end();
 		///end
 
 		let l0 = { texpaint: Base.expa, texpaint_nor: Base.expb, texpaint_pack: Base.expc };
@@ -1803,13 +1803,13 @@ class Base {
 		// Merge height map into normal map
 		if (heightToNormal && MakeMaterial.heightUsed) {
 
-			g2_begin(Base.tempImage.g2, false);
-			Base.tempImage.g2.pipeline = Base.pipeCopy;
+			g2_begin(Base.tempImage, false);
+			g2_set_pipeline(Base.pipeCopy);
 			g2_draw_image(l0.texpaint_nor, 0, 0);
-			Base.tempImage.g2.pipeline = null;
-			g2_end(Base.tempImage.g2);
+			g2_set_pipeline(null);
+			g2_end();
 
-			g4_begin(l0.texpaint_nor.g4);
+			g4_begin(l0.texpaint_nor);
 			g4_set_pipeline(Base.pipeMerge);
 			g4_set_tex(Base.tex0, Base.tempImage);
 			g4_set_tex(Base.tex1, l0.texpaint_pack);
@@ -1833,15 +1833,15 @@ class Base {
 		Base.makeTempImg();
 
 		// Copy layer to temp
-		g2_begin(Base.tempImage.g2, false);
-		Base.tempImage.g2.pipeline = Base.pipeCopy;
+		g2_begin(Base.tempImage, false);
+		g2_set_pipeline(Base.pipeCopy);
 		g2_draw_image(l.texpaint, 0, 0);
-		Base.tempImage.g2.pipeline = null;
-		g2_end(Base.tempImage.g2);
+		g2_set_pipeline(null);
+		g2_end();
 
 		// Apply mask
 		if (const_data_screen_aligned_vb == null) const_data_create_screen_aligned_data();
-		g4_begin(l.texpaint.g4);
+		g4_begin(l.texpaint);
 		g4_set_pipeline(Base.pipeApplyMask);
 		g4_set_tex(Base.tex0Mask, Base.tempImage);
 		g4_set_tex(Base.texaMask, m.texpaint);
@@ -1852,7 +1852,7 @@ class Base {
 	}
 
 	static commandsMergePack = (pipe: pipeline_t, i0: image_t, i1: image_t, i1pack: image_t, i1maskOpacity: f32, i1texmask: image_t, i1blending = -1) => {
-		g4_begin(i0.g4);
+		g4_begin(i0);
 		g4_set_pipeline(pipe);
 		g4_set_tex(Base.tex0, i1);
 		g4_set_tex(Base.tex1, i1pack);
@@ -1880,7 +1880,7 @@ class Base {
 		let _layer = Context.raw.layer;
 		let _tool = Context.raw.tool;
 		let _fillType = Context.raw.fillTypeHandle.position;
-		let current: g2_t = null;
+		let current: image_t = null;
 
 		///if is_paint
 		if (Context.raw.tool == WorkspaceTool.ToolMaterial) {
@@ -1889,7 +1889,7 @@ class Base {
 			}
 
 			current = _g2_current;
-			if (current != null) g2_end(current);
+			if (current != null) g2_end();
 
 			Context.raw.tool = WorkspaceTool.ToolFill;
 			Context.raw.fillTypeHandle.position = FillType.FillObject;
@@ -1916,7 +1916,7 @@ class Base {
 
 		if (hasFillLayer || hasFillMask) {
 			current = _g2_current;
-			if (current != null) g2_end(current);
+			if (current != null) g2_end();
 			Context.raw.pdirty = 1;
 			Context.raw.tool = WorkspaceTool.ToolFill;
 			Context.raw.fillTypeHandle.position = FillType.FillObject;
@@ -1969,7 +1969,7 @@ class Base {
 
 	static updateFillLayer = (parsePaint = true) => {
 		let current = _g2_current;
-		if (current != null) g2_end(current);
+		if (current != null) g2_end();
 
 		let _tool = Context.raw.tool;
 		let _fillType = Context.raw.fillTypeHandle.position;

+ 3 - 2
base/Sources/BoxPreferences.ts

@@ -271,7 +271,8 @@ class BoxPreferences {
 					Config.raw.undo_steps = Math.floor(Context.raw.undoHandle.value = 1);
 				}
 				if (Context.raw.undoHandle.changed) {
-					g2_end(ui.g);
+					let current = _g2_current;
+					g2_end();
 
 					///if (is_paint || is_sculpt)
 					while (History.undoLayers.length < Config.raw.undo_steps) {
@@ -285,7 +286,7 @@ class BoxPreferences {
 					///end
 
 					History.reset();
-					g2_begin(ui.g, false);
+					g2_begin(current, false);
 				}
 
 				///if is_paint

+ 1 - 1
base/Sources/BoxProjects.ts

@@ -194,7 +194,7 @@ class BoxProjects {
 
 				if (zui_button(file, Align.Left) && File.exists(path)) {
 					let current = _g2_current;
-					if (current != null) g2_end(current);
+					if (current != null) g2_end();
 
 					ImportArm.runProject(path);
 

+ 2 - 2
base/Sources/Config.ts

@@ -180,7 +180,7 @@ class Config {
 		Context.raw.ddirty = 2;
 
 		let current = _g2_current;
-		if (current != null) g2_end(current);
+		if (current != null) g2_end();
 		RenderPathBase.applyConfig();
 		if (current != null) g2_begin(current, false);
 	}
@@ -205,7 +205,7 @@ class Config {
 
 	static saveKeymap = () => {
 		if (Config.raw.keymap == "default.json") return;
-		let path = data_data_path() + "keymap_presets/" + Config.raw.keymap;
+		let path = data_path() + "keymap_presets/" + Config.raw.keymap;
 		let buffer = sys_string_to_buffer(JSON.stringify(Config.keymap));
 		Krom.fileSaveBytes(path, buffer);
 	}

+ 15 - 17
base/Sources/Console.ts

@@ -7,35 +7,33 @@ class Console {
 	static lastTraces: string[] = [""];
 	static progressText: string = null;
 
-	static drawToast = (s: string, g: g2_t) => {
-		g.color = 0x55000000;
+	static drawToast = (s: string) => {
+		g2_set_color(0x55000000);
 		g2_fill_rect(0, 0, sys_width(), sys_height());
 		let scale = zui_SCALE(Base.getUIs()[0]);
 		let x = sys_width() / 2;
 		let y = sys_height() - 200 * scale;
 		g2_fill_rect(x - 200 * scale, y, 400 * scale, 80 * scale);
-		g.font = Base.font;
-		g.font_size = Math.floor(22 * scale);
-		g.color = 0xffffffff;
-		g2_draw_string(s, x - font_width(g.font, g.font_size, s) / 2, y + 40 * scale - font_height(g.font, g.font_size) / 2);
+		g2_set_font(Base.font);
+		g2_set_font_size(Math.floor(22 * scale));
+		g2_set_color(0xffffffff);
+		g2_draw_string(s, x - font_width(_g2_font, _g2_font_size, s) / 2, y + 40 * scale - font_height(_g2_font, _g2_font_size) / 2);
 	}
 
-	static toast = (s: string, g2: g2_t = null) => {
+	static toast = (s: string) => {
 		// Show a popup message
-		let _render = (g: g2_t) => {
-			Console.drawToast(s, g);
-			if (g2 == null) {
-				Base.notifyOnNextFrame(() => {
-					app_remove_render_2d(_render);
-				});
-			}
+		let _render = () => {
+			Console.drawToast(s);
+			Base.notifyOnNextFrame(() => {
+				app_remove_render_2d(_render);
+			});
 		}
-		g2 != null ? _render(g2) : app_notify_on_render_2d(_render);
+		app_notify_on_render_2d(_render);
 		Console.consoleTrace(s);
 	}
 
-	static drawProgress = (g: g2_t) => {
-		Console.drawToast(Console.progressText, g);
+	static drawProgress = () => {
+		Console.drawToast(Console.progressText);
 	}
 
 	static progress = (s: string) => {

+ 2 - 2
base/Sources/Context.ts

@@ -76,7 +76,7 @@ class Context {
 		UIHeader.headerHandle.redraws = 2;
 
 		let current = _g2_current;
-		if (current != null) g2_end(current);
+		if (current != null) g2_end();
 
 		Base.setObjectMask();
 		MakeMaterial.parseMeshMaterial();
@@ -282,7 +282,7 @@ class Context {
 
 	static updateEnvmap = () => {
 		if (Context.raw.showEnvmap) {
-			scene_world._envmap = Context.raw.showEnvmapBlur ? scene_world._radianceMipmaps[0] : Context.raw.savedEnvmap;
+			scene_world._envmap = Context.raw.showEnvmapBlur ? scene_world._radiance_mipmaps[0] : Context.raw.savedEnvmap;
 		}
 		else {
 			scene_world._envmap = Context.raw.emptyEnvmap;

+ 6 - 6
base/Sources/ExportArm.ts

@@ -141,17 +141,17 @@ class ExportArm {
 		let tex = render_path_render_targets.get(Context.raw.renderMode == RenderMode.RenderForward ? "buf" : "tex").image;
 		let mesh_icon = image_create_render_target(256, 256);
 		let r = app_w() / app_h();
-		g2_begin(mesh_icon.g2, false);
+		g2_begin(mesh_icon, false);
 		///if krom_opengl
 		g2_draw_scaled_image(tex, -(256 * r - 256) / 2, 256, 256 * r, -256);
 		///else
 		g2_draw_scaled_image(tex, -(256 * r - 256) / 2, 0, 256 * r, 256);
 		///end
-		g2_end(mesh_icon.g2);
+		g2_end();
 		///if krom_metal
 		// Flush command list
-		g2_begin(mesh_icon.g2, false);
-		g2_end(mesh_icon.g2);
+		g2_begin(mesh_icon, false);
+		g2_end();
 		///end
 		let mesh_icon_pixels = image_get_pixels(mesh_icon);
 		let u8a = new Uint8Array(mesh_icon_pixels);
@@ -427,9 +427,9 @@ class ExportArm {
 			if (!Project.packedAssetExists(raw.packed_assets, assets[i].file)) {
 				let image = Project.getImage(assets[i]);
 				let temp = image_create_render_target(image.width, image.height);
-				g2_begin(temp.g2, false);
+				g2_begin(temp, false);
 				g2_draw_image(image, 0, 0);
-				g2_end(temp.g2);
+				g2_end();
 				tempImages.push(temp);
 				raw.packed_assets.push({
 					name: assets[i].file,

+ 25 - 25
base/Sources/ExportTexture.ts

@@ -153,13 +153,13 @@ class ExportTexture {
 		}
 
 		// Clear export layer
-		g4_begin(Base.expa.g4);
+		g4_begin(Base.expa);
 		g4_clear(color_from_floats(0.0, 0.0, 0.0, 0.0));
 		g4_end();
-		g4_begin(Base.expb.g4);
+		g4_begin(Base.expb);
 		g4_clear(color_from_floats(0.5, 0.5, 1.0, 0.0));
 		g4_end();
-		g4_begin(Base.expc.g4);
+		g4_begin(Base.expc);
 		g4_clear(color_from_floats(1.0, 0.0, 0.0, 0.0));
 		g4_end();
 
@@ -179,8 +179,8 @@ class ExportTexture {
 			if (l1masks != null && !bakeMaterial) {
 				if (l1masks.length > 1) {
 					Base.makeTempMaskImg();
-					g2_begin(Base.tempMaskImage.g2, true, 0x00000000);
-					g2_end(Base.tempMaskImage.g2);
+					g2_begin(Base.tempMaskImage, true, 0x00000000);
+					g2_end();
 					let l1: any = { texpaint: Base.tempMaskImage };
 					for (let i = 0; i < l1masks.length; ++i) {
 						Base.mergeLayer(l1, l1masks[i]);
@@ -191,13 +191,13 @@ class ExportTexture {
 			}
 
 			if (l1.paintBase) {
-				g2_begin(Base.tempImage.g2, false); // Copy to temp
-				Base.tempImage.g2.pipeline = Base.pipeCopy;
+				g2_begin(Base.tempImage, false); // Copy to temp
+				g2_set_pipeline(Base.pipeCopy);
 				g2_draw_image(Base.expa, 0, 0);
-				Base.tempImage.g2.pipeline = null;
-				g2_end(Base.tempImage.g2);
+				g2_set_pipeline(null);
+				g2_end();
 
-				g4_begin(Base.expa.g4);
+				g4_begin(Base.expa);
 				g4_set_pipeline(Base.pipeMerge);
 				g4_set_tex(Base.tex0, l1.texpaint);
 				g4_set_tex(Base.tex1, empty);
@@ -212,13 +212,13 @@ class ExportTexture {
 			}
 
 			if (l1.paintNor) {
-				g2_begin(Base.tempImage.g2, false);
-				Base.tempImage.g2.pipeline = Base.pipeCopy;
+				g2_begin(Base.tempImage, false);
+				g2_set_pipeline(Base.pipeCopy);
 				g2_draw_image(Base.expb, 0, 0);
-				Base.tempImage.g2.pipeline = null;
-				g2_end(Base.tempImage.g2);
+				g2_set_pipeline(null);
+				g2_end();
 
-				g4_begin(Base.expb.g4);
+				g4_begin(Base.expb);
 				g4_set_pipeline(Base.pipeMerge);
 				g4_set_tex(Base.tex0, l1.texpaint);
 				g4_set_tex(Base.tex1, l1.texpaint_nor);
@@ -233,11 +233,11 @@ class ExportTexture {
 			}
 
 			if (l1.paintOcc || l1.paintRough || l1.paintMet || l1.paintHeight) {
-				g2_begin(Base.tempImage.g2, false);
-				Base.tempImage.g2.pipeline = Base.pipeCopy;
+				g2_begin(Base.tempImage, false);
+				g2_set_pipeline(Base.pipeCopy);
 				g2_draw_image(Base.expc, 0, 0);
-				Base.tempImage.g2.pipeline = null;
-				g2_end(Base.tempImage.g2);
+				g2_set_pipeline(null);
+				g2_end();
 
 				if (l1.paintOcc && l1.paintRough && l1.paintMet && l1.paintHeight) {
 					Base.commandsMergePack(Base.pipeMerge, Base.expc, l1.texpaint, l1.texpaint_pack, SlotLayer.getOpacity(l1), mask, l1.paintHeightBlend ? -3 : -1);
@@ -252,12 +252,12 @@ class ExportTexture {
 
 		///if krom_metal
 		// Flush command list
-		g2_begin(Base.expa.g2, false);
-		g2_end(Base.expa.g2);
-		g2_begin(Base.expb.g2, false);
-		g2_end(Base.expb.g2);
-		g2_begin(Base.expc.g2, false);
-		g2_end(Base.expc.g2);
+		g2_begin(Base.expa, false);
+		g2_end();
+		g2_begin(Base.expb, false);
+		g2_end();
+		g2_begin(Base.expc, false);
+		g2_end();
 		///end
 		///end
 

+ 18 - 18
base/Sources/ImportArm.ts

@@ -223,36 +223,36 @@ class ImportArm {
 
 					if (isMask) {
 						_texpaint = image_from_bytes(lz4_decode(ld.texpaint, ld.res * ld.res * 4), ld.res, ld.res, TextureFormat.RGBA32);
-						g2_begin(l.texpaint.g2, false);
-						// l.texpaint.g2.pipeline = Base.pipeCopy8;
-						l.texpaint.g2.pipeline = project.is_bgra ? Base.pipeCopyBGRA : Base.pipeCopy; // Full bits for undo support, R8 is used
+						g2_begin(l.texpaint, false);
+						// g2_set_pipeline(Base.pipeCopy8);
+						g2_set_pipeline(project.is_bgra ? Base.pipeCopyBGRA : Base.pipeCopy); // Full bits for undo support, R8 is used
 						g2_draw_image(_texpaint, 0, 0);
-						l.texpaint.g2.pipeline = null;
-						g2_end(l.texpaint.g2);
+						g2_set_pipeline(null);
+						g2_end();
 					}
 					else { // Layer
 						// TODO: create render target from bytes
 						_texpaint = image_from_bytes(lz4_decode(ld.texpaint, ld.res * ld.res * 4 * bytesPerPixel), ld.res, ld.res, format);
-						g2_begin(l.texpaint.g2, false);
-						l.texpaint.g2.pipeline = project.is_bgra ? Base.pipeCopyBGRA : Base.pipeCopy;
+						g2_begin(l.texpaint, false);
+						g2_set_pipeline(project.is_bgra ? Base.pipeCopyBGRA : Base.pipeCopy);
 						g2_draw_image(_texpaint, 0, 0);
-						l.texpaint.g2.pipeline = null;
-						g2_end(l.texpaint.g2);
+						g2_set_pipeline(null);
+						g2_end();
 
 						///if is_paint
 						_texpaint_nor = image_from_bytes(lz4_decode(ld.texpaint_nor, ld.res * ld.res * 4 * bytesPerPixel), ld.res, ld.res, format);
-						g2_begin(l.texpaint_nor.g2, false);
-						l.texpaint_nor.g2.pipeline = project.is_bgra ? Base.pipeCopyBGRA : Base.pipeCopy;
+						g2_begin(l.texpaint_nor, false);
+						g2_set_pipeline(project.is_bgra ? Base.pipeCopyBGRA : Base.pipeCopy);
 						g2_draw_image(_texpaint_nor, 0, 0);
-						l.texpaint_nor.g2.pipeline = null;
-						g2_end(l.texpaint_nor.g2);
+						g2_set_pipeline(null);
+						g2_end();
 
 						_texpaint_pack = image_from_bytes(lz4_decode(ld.texpaint_pack, ld.res * ld.res * 4 * bytesPerPixel), ld.res, ld.res, format);
-						g2_begin(l.texpaint_pack.g2, false);
-						l.texpaint_pack.g2.pipeline = project.is_bgra ? Base.pipeCopyBGRA : Base.pipeCopy;
+						g2_begin(l.texpaint_pack, false);
+						g2_set_pipeline(project.is_bgra ? Base.pipeCopyBGRA : Base.pipeCopy);
 						g2_draw_image(_texpaint_pack, 0, 0);
-						l.texpaint_pack.g2.pipeline = null;
-						g2_end(l.texpaint_pack.g2);
+						g2_set_pipeline(null);
+						g2_end();
 						///end
 					}
 
@@ -597,7 +597,7 @@ class ImportArm {
 				}
 				image_from_encoded_bytes(pa.bytes, pa.name.endsWith(".jpg") ? ".jpg" : ".png", (image: image_t) => {
 					data_cached_images.set(abs, image);
-				}, null, false);
+				}, false);
 				break;
 			}
 		}

+ 12 - 12
base/Sources/ImportEnvmap.ts

@@ -16,13 +16,13 @@ class ImportEnvmap {
 		// Init
 		if (ImportEnvmap.pipeline == null) {
 			ImportEnvmap.pipeline = pipeline_create();
-			ImportEnvmap.pipeline.vertexShader = sys_get_shader("pass.vert");
-			ImportEnvmap.pipeline.fragmentShader = sys_get_shader("prefilter_envmap.frag");
+			ImportEnvmap.pipeline.vertex_shader = sys_get_shader("pass.vert");
+			ImportEnvmap.pipeline.fragment_shader = sys_get_shader("prefilter_envmap.frag");
 			let vs = vertex_struct_create();
 			vertex_struct_add(vs, "pos", VertexData.F32_2X);
-			ImportEnvmap.pipeline.inputLayout = [vs];
-			ImportEnvmap.pipeline.colorAttachmentCount = 1;
-			ImportEnvmap.pipeline.colorAttachments[0] = TextureFormat.RGBA128;
+			ImportEnvmap.pipeline.input_layout = [vs];
+			ImportEnvmap.pipeline.color_attachment_count = 1;
+			ImportEnvmap.pipeline.color_attachments[0] = TextureFormat.RGBA128;
 			pipeline_compile(ImportEnvmap.pipeline);
 			ImportEnvmap.paramsLocation = pipeline_get_const_loc(ImportEnvmap.pipeline, "params");
 			ImportEnvmap.radianceLocation = pipeline_get_tex_unit(ImportEnvmap.pipeline, "radiance");
@@ -40,11 +40,11 @@ class ImportEnvmap {
 		}
 
 		// Down-scale to 1024x512
-		g2_begin(ImportEnvmap.radiance.g2, false);
-		ImportEnvmap.radiance.g2.pipeline = Base.pipeCopy128;
+		g2_begin(ImportEnvmap.radiance, false);
+		g2_set_pipeline(Base.pipeCopy128);
 		g2_draw_scaled_image(image, 0, 0, 1024, 512);
-		ImportEnvmap.radiance.g2.pipeline = null;
-		g2_end(ImportEnvmap.radiance.g2);
+		g2_set_pipeline(null);
+		g2_end();
 
 		let radiancePixels = image_get_pixels(ImportEnvmap.radiance);
 		if (ImportEnvmap.radianceCpu != null) {
@@ -82,17 +82,17 @@ class ImportEnvmap {
 		scene_world._envmap = image;
 		scene_world.envmap = path;
 		scene_world._radiance = ImportEnvmap.radianceCpu;
-		scene_world._radianceMipmaps = ImportEnvmap.mipsCpu;
+		scene_world._radiance_mipmaps = ImportEnvmap.mipsCpu;
 		Context.raw.savedEnvmap = image;
 		if (Context.raw.showEnvmapBlur) {
-			scene_world._envmap = scene_world._radianceMipmaps[0];
+			scene_world._envmap = scene_world._radiance_mipmaps[0];
 		}
 		Context.raw.ddirty = 2;
 		Project.raw.envmap = path;
 	}
 
 	static getRadianceMip = (mip: image_t, level: i32, radiance: image_t) => {
-		g4_begin(mip.g4);
+		g4_begin(mip);
 		g4_set_vertex_buffer(const_data_screen_aligned_vb);
 		g4_set_index_buffer(const_data_screen_aligned_ib);
 		g4_set_pipeline(ImportEnvmap.pipeline);

+ 1 - 1
base/Sources/ImportFont.ts

@@ -11,7 +11,7 @@ class ImportFont {
 			}
 		}
 		data_get_font(path, (font: font_t) => {
-			font_init(font); // Make sure font_ is ready
+			g2_font_init(font); // Make sure font_ is ready
 			let count = Krom.g2_font_count(font.font_);
 			let fontSlots: SlotFontRaw[] = [];
 			for (let i = 0; i < count; ++i) {

+ 12 - 15
base/Sources/LineDraw.ts

@@ -21,10 +21,7 @@ class LineDraw {
 	static maxIndices = LineDraw.maxLines * 6;
 	static lines = 0;
 
-	static g: g4_t;
-
-	static render = (g4: g4_t, matrix: mat4_t) => {
-		LineDraw.g = g4;
+	static render = (matrix: mat4_t) => {
 		LineDraw.mat = matrix;
 		LineDraw.dim = mat4_get_scale(matrix);
 
@@ -33,17 +30,17 @@ class LineDraw {
 			vertex_struct_add(structure, "pos", VertexData.F32_3X);
 			vertex_struct_add(structure, "col", VertexData.F32_3X);
 			LineDraw.pipeline = pipeline_create();
-			LineDraw.pipeline.inputLayout = [structure];
-			LineDraw.pipeline.fragmentShader = sys_get_shader("line.frag");
-			LineDraw.pipeline.vertexShader = sys_get_shader("line.vert");
-			LineDraw.pipeline.depthWrite = true;
-			LineDraw.pipeline.depthMode = CompareMode.Less;
-			LineDraw.pipeline.cullMode = CullMode.None;
-			LineDraw.pipeline.colorAttachmentCount = 3;
-			LineDraw.pipeline.colorAttachments[0] = TextureFormat.RGBA64;
-			LineDraw.pipeline.colorAttachments[1] = TextureFormat.RGBA64;
-			LineDraw.pipeline.colorAttachments[2] = TextureFormat.RGBA64;
-			LineDraw.pipeline.depthStencilAttachment = DepthFormat.DepthOnly;
+			LineDraw.pipeline.input_layout = [structure];
+			LineDraw.pipeline.fragment_shader = sys_get_shader("line.frag");
+			LineDraw.pipeline.vertex_shader = sys_get_shader("line.vert");
+			LineDraw.pipeline.depth_write = true;
+			LineDraw.pipeline.depth_mode = CompareMode.Less;
+			LineDraw.pipeline.cull_mode = CullMode.None;
+			LineDraw.pipeline.color_attachment_count = 3;
+			LineDraw.pipeline.color_attachments[0] = TextureFormat.RGBA64;
+			LineDraw.pipeline.color_attachments[1] = TextureFormat.RGBA64;
+			LineDraw.pipeline.color_attachments[2] = TextureFormat.RGBA64;
+			LineDraw.pipeline.depth_attachment = DepthFormat.DepthOnly;
 			pipeline_compile(LineDraw.pipeline);
 			LineDraw.vpID = pipeline_get_const_loc(LineDraw.pipeline, "VP");
 			LineDraw.vp = mat4_identity();

+ 2 - 2
base/Sources/MakeVoxel.ts

@@ -9,7 +9,7 @@ class MakeVoxel {
 		vertex_struct_add(structure, "tex", VertexData.I16_2X_Normalized);
 
 		let pipeState = data._pipe_state;
-		pipeState.inputLayout = [structure];
+		pipeState.input_layout = [structure];
 		data.vertex_elements = [{name: "pos", data: "short4norm"}, {name: "nor", data: "short2norm"}, {name: "tex", data: "short2norm"}];
 
 		// ///if arm_skin
@@ -24,7 +24,7 @@ class MakeVoxel {
 		// ///end
 
 		let ds = MakeMaterial.getDisplaceStrength();
-		pipeState.vertexShader = shader_from_source(MakeVoxel.voxelSource(), ShaderType.Vertex);
+		pipeState.vertex_shader = shader_from_source(MakeVoxel.voxelSource(), ShaderType.Vertex);
 
 		pipeline_compile(pipeState);
 		data.constants = [{ name: "W", type: "mat4", link: "_worldMatrix" }, { name: "N", type: "mat3", link: "_normalMatrix" }];

+ 1 - 1
base/Sources/Path.ts

@@ -26,7 +26,7 @@ class Path {
 	static workingDirCache: string = null;
 
 	static data = (): string => {
-		return Krom.getFilesLocation() + Path.sep + data_data_path();
+		return Krom.getFilesLocation() + Path.sep + data_path();
 	}
 
 	static toRelative = (from: string, to: string): string => {

+ 7 - 7
base/Sources/Project.ts

@@ -35,7 +35,7 @@ class Project {
 			}
 
 			let current = _g2_current;
-			if (current != null) g2_end(current);
+			if (current != null) g2_end();
 
 			ImportArm.runProject(path);
 
@@ -180,11 +180,11 @@ class Project {
 
 					let imgmesh = image_from_bytes(f32a.buffer, Config.getTextureResX(), Config.getTextureResY(), TextureFormat.RGBA128);
 					let texpaint = Project.layers[0].texpaint;
-					g2_begin(texpaint.g2, false);
-					texpaint.g2.pipeline = Base.pipeCopy128;
+					g2_begin(texpaint, false);
+					g2_set_pipeline(Base.pipeCopy128);
 					g2_draw_scaled_image(imgmesh, 0, 0, Config.getTextureResX(), Config.getTextureResY());
-					texpaint.g2.pipeline = null;
-					g2_end(texpaint.g2);
+					g2_set_pipeline(null);
+					g2_end();
 				});
 				///end
 			}
@@ -207,7 +207,7 @@ class Project {
 		data_get_mesh("Scene", n, (md: mesh_data_t) => {
 
 			let current = _g2_current;
-			if (current != null) g2_end(current);
+			if (current != null) g2_end();
 
 			///if is_paint
 			Context.raw.pickerMaskHandle.position = PickerMask.MaskNone;
@@ -296,7 +296,7 @@ class Project {
 			scene_world.envmap = "World_radiance.k";
 			Context.raw.showEnvmapHandle.selected = Context.raw.showEnvmap = false;
 			scene_world._radiance = Context.raw.defaultRadiance;
-			scene_world._radianceMipmaps = Context.raw.defaultRadianceMipmaps;
+			scene_world._radiance_mipmaps = Context.raw.defaultRadianceMipmaps;
 			scene_world._irradiance = Context.raw.defaultIrradiance;
 			scene_world.strength = 4.0;
 

+ 3 - 4
base/Sources/RenderPathBase.ts

@@ -55,7 +55,7 @@ class RenderPathBase {
 		return RenderPathBase.superSample;
 	}
 
-	static drawCompass = (currentG: g4_t) => {
+	static drawCompass = () => {
 		if (Context.raw.showCompass) {
 			let cam = scene_camera;
 			let compass: mesh_object_t = scene_get_child(".Compass").ext;
@@ -75,7 +75,7 @@ class RenderPathBase {
 			vec4_set(compass.base.transform.scale, 0.4, 0.4, 0.4);
 			transform_build_matrix(compass.base.transform);
 			compass.frustum_culling = false;
-			mesh_object_render(compass, currentG, "overlay", []);
+			mesh_object_render(compass, "overlay", []);
 
 			cam.p = _P;
 			compass.base.visible = _visible;
@@ -516,7 +516,6 @@ class RenderPathBase {
 			render_path_clear_target(0xff000000);
 		}
 		render_path_set_target("gbuffer0", ["gbuffer1", "gbuffer2"]);
-		let currentG =_render_path_current_g;
 		RenderPathPaint.bindLayers();
 		render_path_draw_meshes("mesh");
 		RenderPathPaint.unbindLayers();
@@ -544,7 +543,7 @@ class RenderPathBase {
 
 		let hide = Operator.shortcut(Config.keymap.stencil_hide, ShortcutType.ShortcutDown) || keyboard_down("control");
 		let isDecal = Base.isDecalLayer();
-		if (isDecal && !hide) LineDraw.render(currentG, Context.raw.layer.decalMat);
+		if (isDecal && !hide) LineDraw.render(Context.raw.layer.decalMat);
 	}
 
 	static makeGbufferCopyTextures = () => {

+ 1 - 1
base/Sources/RenderPathDeferred.ts

@@ -193,7 +193,7 @@ class RenderPathDeferred {
 		render_path_draw_shader("shader_datas/compositor_pass/compositor_pass");
 
 		render_path_set_target("buf");
-		RenderPathBase.drawCompass(_render_path_current_g);
+		RenderPathBase.drawCompass();
 		render_path_draw_meshes("overlay");
 
 		RenderPathBase.drawTAA();

+ 1 - 1
base/Sources/RenderPathForward.ts

@@ -22,7 +22,7 @@ class RenderPathForward {
 		render_path_draw_shader("shader_datas/compositor_pass/compositor_pass");
 
 		render_path_set_target("buf");
-		RenderPathBase.drawCompass(_render_path_current_g);
+		RenderPathBase.drawCompass();
 		render_path_draw_meshes("overlay");
 
 		RenderPathBase.drawTAA();

+ 3 - 3
base/Sources/RenderPathRaytrace.ts

@@ -47,7 +47,7 @@ class RenderPathRaytrace {
 		}
 
 		let probe = scene_world;
-		let savedEnvmap = Context.raw.showEnvmapBlur ? probe._radianceMipmaps[0] : Context.raw.savedEnvmap;
+		let savedEnvmap = Context.raw.showEnvmapBlur ? probe._radiance_mipmaps[0] : Context.raw.savedEnvmap;
 
 		if (RenderPathRaytrace.lastEnvmap != savedEnvmap) {
 			RenderPathRaytrace.lastEnvmap = savedEnvmap;
@@ -118,7 +118,7 @@ class RenderPathRaytrace {
 		///end
 
 		let framebuffer = render_path_render_targets.get("buf").image;
-		Krom.raytraceDispatchRays(framebuffer.renderTarget_, RenderPathRaytrace.f32a.buffer);
+		Krom.raytraceDispatchRays(framebuffer.render_target_, RenderPathRaytrace.f32a.buffer);
 
 		if (Context.raw.ddirty == 1 || Context.raw.pdirty == 1) {
 			///if krom_metal
@@ -184,7 +184,7 @@ class RenderPathRaytrace {
 		render_path_set_target("buf");
 		render_path_draw_meshes("overlay");
 		render_path_set_target("buf");
-		RenderPathBase.drawCompass(_render_path_current_g);
+		RenderPathBase.drawCompass();
 		render_path_set_target("taa");
 		render_path_bind_target("buf", "tex");
 		render_path_draw_shader("shader_datas/compositor_pass/compositor_pass");

+ 2 - 2
base/Sources/RenderPathRaytraceBake.ts

@@ -75,7 +75,7 @@ class RenderPathRaytraceBake {
 			Context.updateEnvmap();
 		}
 		let probe = scene_world;
-		let savedEnvmap = Context.raw.showEnvmapBlur ? probe._radianceMipmaps[0] : Context.raw.savedEnvmap;
+		let savedEnvmap = Context.raw.showEnvmapBlur ? probe._radiance_mipmaps[0] : Context.raw.savedEnvmap;
 		if (RenderPathRaytrace.lastEnvmap != savedEnvmap || RenderPathRaytraceBake.lastLayer != Context.raw.layer.texpaint) {
 			RenderPathRaytrace.lastEnvmap = savedEnvmap;
 			RenderPathRaytraceBake.lastLayer = Context.raw.layer.texpaint;
@@ -105,7 +105,7 @@ class RenderPathRaytraceBake {
 			f32a[6] = Context.raw.envmapAngle;
 
 			let framebuffer = render_path_render_targets.get("baketex2").image;
-			Krom.raytraceDispatchRays(framebuffer.renderTarget_, f32a.buffer);
+			Krom.raytraceDispatchRays(framebuffer.render_target_, f32a.buffer);
 
 			render_path_set_target("texpaint" + Context.raw.layer.id);
 			render_path_bind_target("baketex2", "tex");

+ 4 - 4
base/Sources/TabFonts.ts

@@ -64,13 +64,13 @@ class TabFonts {
 					let tile = zui_SCALE(ui) > 1 ? 100 : 50;
 					let state = State.Idle;
 					if (Project.fonts[i].previewReady) {
-						// ui.g.pipeline = UIView2D.pipe; // L8
+						// g2_set_pipeline(UIView2D.pipe); // L8
 						// ///if krom_opengl
-						// ui.currentWindow.texture.g4.setPipeline(UIView2D.pipe);
+						// g4_set_pipeline(UIView2D.pipe);
 						// ///end
-						// ui.currentWindow.texture.g4.setInt(UIView2D.channelLocation, 1);
+						// g4_set_int(UIView2D.channelLocation, 1);
 						state = zui_image(img);
-						// ui.g.pipeline = null;
+						// g2_set_pipeline(null);
 					}
 					else {
 						state = zui_image(Res.get("icons.k"), -1, null, tile * 6, tile, tile, tile);

+ 5 - 4
base/Sources/TabMaterials.ts

@@ -112,9 +112,9 @@ class TabMaterials {
 						let number = String(i + 1);
 						let width = font_width(ui.font, ui.font_size, number) + 10;
 						let height = font_height(ui.font, ui.font_size);
-						ui.g.color = ui.t.TEXT_COL;
+						g2_set_color(ui.t.TEXT_COL);
 						g2_fill_rect(uix, uiy, width, height);
-						ui.g.color = ui.t.ACCENT_COL;
+						g2_set_color(ui.t.ACCENT_COL);
 						g2_draw_string(number, uix + 5, uiy);
 					}
 				}
@@ -265,11 +265,12 @@ class TabMaterials {
 	static buttonNew = (text: string) => {
 		let ui = UIBase.ui;
 		if (zui_button(text)) {
-			g2_end(ui.g);
+			let current = _g2_current;
+			g2_end();
 			Context.raw.material = SlotMaterial.create(Project.materials[0].data);
 			Project.materials.push(Context.raw.material);
 			TabMaterials.updateMaterial();
-			g2_begin(ui.g, false);
+			g2_begin(current, false);
 			History.newMaterial();
 		}
 	}

+ 4 - 4
base/Sources/TabTextures.ts

@@ -120,11 +120,11 @@ class TabTextures {
 											///end
 
 											let target = image_create_render_target(TabTextures.to_pow2(img.width), TabTextures.to_pow2(img.height));
-											g2_begin(target.g2, false);
-											target.g2.pipeline = Base.pipeCopy;
+											g2_begin(target, false);
+											g2_set_pipeline(Base.pipeCopy);
 											g2_draw_scaled_image(img, 0, 0, target.width, target.height);
-											target.g2.pipeline = null;
-											g2_end(target.g2);
+											g2_set_pipeline(null);
+											g2_end();
 											Base.notifyOnNextFrame(() => {
 												let f = UIFiles.filename;
 												if (f == "") f = tr("untitled");

+ 43 - 45
base/Sources/UIBase.ts

@@ -196,7 +196,7 @@ class UIBase {
 			// Context.raw.savedEnvmap = world._envmap;
 			Context.raw.defaultIrradiance = world._irradiance;
 			Context.raw.defaultRadiance = world._radiance;
-			Context.raw.defaultRadianceMipmaps = world._radianceMipmaps;
+			Context.raw.defaultRadianceMipmaps = world._radiance_mipmaps;
 		}
 		world._envmap = Context.raw.showEnvmap ? Context.raw.savedEnvmap : Context.raw.emptyEnvmap;
 		Context.raw.ddirty = 1;
@@ -1082,13 +1082,12 @@ class UIBase {
 				if (SlotLayer.isGroup(l)) continue;
 				let target = l.texpaint_preview;
 				let source = l.texpaint;
-				let g2 = target.g2;
-				g2_begin(g2, true, 0x00000000);
-				// g2.pipeline = l.isMask() ? Base.pipeCopy8 : Base.pipeCopy;
-				g2.pipeline = Base.pipeCopy; // texpaint_preview is always RGBA32 for now
+				g2_begin(target, true, 0x00000000);
+				// g2_set_pipeline(l.isMask() ? Base.pipeCopy8 : Base.pipeCopy);
+				g2_set_pipeline(Base.pipeCopy); // texpaint_preview is always RGBA32 for now
 				g2_draw_scaled_image(source, 0, 0, target.width, target.height);
-				g2.pipeline = null;
-				g2_end(g2);
+				g2_set_pipeline(null);
+				g2_end();
 			}
 			UIBase.hwnds[TabArea.TabSidebar0].redraws = 2;
 		}
@@ -1100,13 +1099,12 @@ class UIBase {
 			let l = Context.raw.layer;
 			let target = l.texpaint_preview;
 			let source = l.texpaint;
-			let g2 = target.g2;
-			g2_begin(g2, true, 0x00000000);
-			// g2.pipeline = Context.raw.layer.isMask() ? Base.pipeCopy8 : Base.pipeCopy;
-			g2.pipeline = Base.pipeCopy; // texpaint_preview is always RGBA32 for now
+			g2_begin(target, true, 0x00000000);
+			// g2_set_pipeline(Context.raw.layer.isMask() ? Base.pipeCopy8 : Base.pipeCopy);
+			g2_set_pipeline(Base.pipeCopy); // texpaint_preview is always RGBA32 for now
 			g2_draw_scaled_image(source, 0, 0, target.width, target.height);
-			g2.pipeline = null;
-			g2_end(g2);
+			g2_set_pipeline(null);
+			g2_end();
 			UIBase.hwnds[TabArea.TabSidebar0].redraws = 2;
 		}
 		///end
@@ -1131,18 +1129,18 @@ class UIBase {
 		///end
 	}
 
-	static render = (g: g2_t) => {
+	static render = () => {
 		if (!UIBase.show && Config.raw.touch_ui) {
 			UIBase.ui.input_enabled = true;
-			g2_end(g);
-			zui_begin(UIBase.ui, g);
-			if (zui_window(UIBase.ui, zui_handle("uibase_2"), 0, 0, 150, Math.floor(zui_ELEMENT_H(UIBase.ui) + zui_ELEMENT_OFFSET(UIBase.ui) + 1))) {
+			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.toggleDistractFree();
 				}
 			}
 			zui_end();
-			g2_begin(g, false);
+			g2_begin(null, false);
 		}
 
 		if (!UIBase.show || sys_width() == 0 || sys_height() == 0) return;
@@ -1162,22 +1160,22 @@ class UIBase {
 			UIBase.htabs[i].position = Config.raw.layout_tabs[i];
 		}
 
-		g2_end(g);
-		zui_begin(UIBase.ui, g);
+		g2_end();
+		zui_begin(UIBase.ui);
 
 		///if (is_paint || is_sculpt)
-		UIToolbar.renderUI(g);
+		UIToolbar.renderUI();
 		///end
-		UIMenubar.renderUI(g);
-		UIHeader.renderUI(g);
-		UIStatus.renderUI(g);
+		UIMenubar.renderUI();
+		UIHeader.renderUI();
+		UIStatus.renderUI();
 
 		///if (is_paint || is_sculpt)
 		UIBase.drawSidebar();
 		///end
 
 		zui_end();
-		g2_begin(g, false);
+		g2_begin(null, false);
 	}
 
 	///if (is_paint || is_sculpt)
@@ -1190,10 +1188,10 @@ class UIBase {
 		let _SCROLL_W = UIBase.ui.t.SCROLL_W;
 		if (mini) UIBase.ui.t.SCROLL_W = UIBase.ui.t.SCROLL_MINI_W;
 
-		if (zui_window(UIBase.ui, UIBase.hwnds[TabArea.TabSidebar0], UIBase.tabx, 0, Config.raw.layout[LayoutSize.LayoutSidebarW], Config.raw.layout[LayoutSize.LayoutSidebarH0])) {
+		if (zui_window(UIBase.hwnds[TabArea.TabSidebar0], UIBase.tabx, 0, Config.raw.layout[LayoutSize.LayoutSidebarW], Config.raw.layout[LayoutSize.LayoutSidebarH0])) {
 			for (let i = 0; i < (mini ? 1 : UIBase.hwndTabs[TabArea.TabSidebar0].length); ++i) UIBase.hwndTabs[TabArea.TabSidebar0][i](UIBase.htabs[TabArea.TabSidebar0]);
 		}
-		if (zui_window(UIBase.ui, UIBase.hwnds[TabArea.TabSidebar1], UIBase.tabx, Config.raw.layout[LayoutSize.LayoutSidebarH0], Config.raw.layout[LayoutSize.LayoutSidebarW], Config.raw.layout[LayoutSize.LayoutSidebarH1] - expandButtonOffset)) {
+		if (zui_window(UIBase.hwnds[TabArea.TabSidebar1], UIBase.tabx, Config.raw.layout[LayoutSize.LayoutSidebarH0], Config.raw.layout[LayoutSize.LayoutSidebarW], Config.raw.layout[LayoutSize.LayoutSidebarH1] - expandButtonOffset)) {
 			for (let i = 0; i < (mini ? 1 : UIBase.hwndTabs[TabArea.TabSidebar1].length); ++i) UIBase.hwndTabs[TabArea.TabSidebar1][i](UIBase.htabs[TabArea.TabSidebar1]);
 		}
 
@@ -1204,7 +1202,7 @@ class UIBase {
 		if (Config.raw.touch_ui) {
 			let width = Config.raw.layout[LayoutSize.LayoutSidebarW];
 			let height = Math.floor(zui_ELEMENT_H(UIBase.ui) + zui_ELEMENT_OFFSET(UIBase.ui));
-			if (zui_window(UIBase.ui, zui_handle("uibase_3"), sys_width() - width, sys_height() - height, width, height + 1)) {
+			if (zui_window(zui_handle("uibase_3"), sys_width() - width, sys_height() - height, width, height + 1)) {
 				UIBase.ui._w = width;
 				let _BUTTON_H = UIBase.ui.t.BUTTON_H;
 				let _BUTTON_COL = UIBase.ui.t.BUTTON_COL;
@@ -1222,7 +1220,7 @@ class UIBase {
 		// Expand button
 		if (Config.raw.layout[LayoutSize.LayoutSidebarW] == 0) {
 			let width = Math.floor(font_width(UIBase.ui.font, UIBase.ui.font_size, "<<") + 25 * zui_SCALE(UIBase.ui));
-			if (zui_window(UIBase.ui, UIBase.hminimized, sys_width() - width, 0, width, Math.floor(zui_ELEMENT_H(UIBase.ui) + zui_ELEMENT_OFFSET(UIBase.ui) + 1))) {
+			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 = UIBase.ui.t.BUTTON_H;
 				let _BUTTON_COL = UIBase.ui.t.BUTTON_COL;
@@ -1246,14 +1244,14 @@ class UIBase {
 		Context.raw.lastHtab0Position = UIBase.htabs[TabArea.TabSidebar0].position;
 	}
 
-	static renderCursor = (g: g2_t) => {
+	static renderCursor = () => {
 		if (!Base.uiEnabled) return;
 
 		///if is_paint
 		if (Context.raw.tool == WorkspaceTool.ToolMaterial || Context.raw.tool == WorkspaceTool.ToolBake) return;
 		///end
 
-		g.color = 0xffffffff;
+		g2_set_color(0xffffffff);
 
 		Context.raw.viewIndex = Context.raw.viewIndexLast;
 		let mx = Base.x() + Context.raw.paintVec.x * Base.w();
@@ -1276,14 +1274,14 @@ class UIBase {
 			tool != WorkspaceTool.ToolColorId) {
 			let r = UIBase.getBrushStencilRect();
 			if (!Operator.shortcut(Config.keymap.stencil_hide, ShortcutType.ShortcutDown)) {
-				g.color = 0x88ffffff;
+				g2_set_color(0x88ffffff);
 				let angle = Context.raw.brushStencilAngle;
 				let cx = r.x + r.w / 2;
 				let cy = r.y + r.h / 2;
-				g.transformation = mat3_multmat(mat3_multmat(mat3_translation(cx, cy), mat3_rotation(-angle)), mat3_translation(-cx, -cy));
+				g2_set_transformation(mat3_multmat(mat3_multmat(mat3_translation(cx, cy), mat3_rotation(-angle)), mat3_translation(-cx, -cy)));
 				g2_draw_scaled_image(Context.raw.brushStencilImage, r.x, r.y, r.w, r.h);
-				g.transformation = null;
-				g.color = 0xffffffff;
+				g2_set_transformation(null);
+				g2_set_color(0xffffffff);
 			}
 			let transform = Operator.shortcut(Config.keymap.stencil_transform, ShortcutType.ShortcutDown);
 			if (transform) {
@@ -1298,9 +1296,9 @@ class UIBase {
 				let angle = Context.raw.brushStencilAngle;
 				let cx = r.x + r.w / 2;
 				let cy = r.y + r.h / 2;
-				g.transformation = mat3_multmat(mat3_multmat(mat3_translation(cx, cy), mat3_rotation(-angle)), mat3_translation(-cx, -cy));
+				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);
-				g.transformation = null;
+				g2_set_transformation(null);
 			}
 		}
 		///end
@@ -1325,9 +1323,9 @@ class UIBase {
 
 		// Clone source cursor
 		if (Context.raw.tool == WorkspaceTool.ToolClone && !keyboard_down("alt") && (mouse_down() || pen_down())) {
-			g.color = 0x66ffffff;
+			g2_set_color(0x66ffffff);
 			g2_draw_scaled_image(cursorImg, mx + Context.raw.cloneDeltaX * app_w() - psize / 2, my + Context.raw.cloneDeltaY * app_h() - psize / 2, psize, psize);
-			g.color = 0xffffffff;
+			g2_set_color(0xffffffff);
 		}
 
 		let decal = Context.raw.tool == WorkspaceTool.ToolDecal || Context.raw.tool == WorkspaceTool.ToolText;
@@ -1357,18 +1355,18 @@ class UIBase {
 					let decalY = Base.y() + Context.raw.decalY * Base.h() - psizey / 2;
 					Context.raw.viewIndex = -1;
 
-					g.color = color_from_floats(1, 1, 1, decalAlpha);
+					g2_set_color(color_from_floats(1, 1, 1, decalAlpha));
 					let angle = (Context.raw.brushAngle + Context.raw.brushNodesAngle) * (Math.PI / 180);
 					let cx = decalX + psizex / 2;
 					let cy = decalY + psizey / 2;
-					g.transformation = mat3_multmat(mat3_multmat(mat3_translation(cx, cy), mat3_rotation(angle)), mat3_translation(-cx, -cy));
+					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.decalImage, decalX, decalY, psizex, psizey);
 					///else
 					g2_draw_scaled_image(Context.raw.decalImage, decalX, decalY + psizey, psizex, -psizey);
 					///end
-					g.transformation = null;
-					g.color = 0xffffffff;
+					g2_set_transformation(null);
+					g2_set_color(0xffffffff);
 				}
 			}
 			if (Context.raw.tool == WorkspaceTool.ToolBrush  ||
@@ -1402,9 +1400,9 @@ class UIBase {
 			mx = Context.raw.brushLazyX * Base.w() + Base.x();
 			my = Context.raw.brushLazyY * Base.h() + Base.y();
 			let radius = Context.raw.brushLazyRadius * 180;
-			g.color = 0xff666666;
+			g2_set_color(0xff666666);
 			g2_draw_scaled_image(cursorImg, mx - radius / 2, my - radius / 2, radius, radius);
-			g.color = 0xffffffff;
+			g2_set_color(0xffffffff);
 		}
 	}
 	///end

+ 11 - 11
base/Sources/UIBox.ts

@@ -17,7 +17,7 @@ class UIBox {
 	static tweenAlpha = 0.0;
 	///end
 
-	static render = (g: g2_t) => {
+	static render = () => {
 		if (!UIMenu.show) {
 			let ui = Base.uiBox;
 			let inUse = ui.combo_selected_handle_ptr != null;
@@ -41,14 +41,14 @@ class UIBox {
 
 		if (Config.raw.touch_ui) { // Darken bg
 			///if (krom_android || krom_ios)
-			g.color = color_from_floats(0, 0, 0, UIBox.tweenAlpha);
+			g2_set_color(color_from_floats(0, 0, 0, UIBox.tweenAlpha));
 			///else
-			g.color = color_from_floats(0, 0, 0, 0.5);
+			g2_set_color(color_from_floats(0, 0, 0, 0.5));
 			///end
 			g2_fill_rect(0, 0, sys_width(), sys_height());
 		}
 
-		g2_end(g);
+		g2_end();
 
 		let ui = Base.uiBox;
 		let appw = sys_width();
@@ -61,8 +61,8 @@ class UIBox {
 		let top = Math.floor(apph / 2 - mh / 2);
 
 		if (UIBox.boxCommands == null) {
-			zui_begin(ui, g);
-			if (zui_window(ui, UIBox.hwnd, left, top, mw, mh, UIBox.draggable)) {
+			zui_begin(ui);
+			if (zui_window(UIBox.hwnd, left, top, mw, mh, UIBox.draggable)) {
 				ui._y += 10;
 				let tabVertical = Config.raw.touch_ui;
 				if (zui_tab(zui_handle("uibox_0"), UIBox.boxTitle, tabVertical)) {
@@ -96,8 +96,8 @@ class UIBox {
 			zui_end();
 		}
 		else {
-			zui_begin(ui, g);
-			if (zui_window(ui, UIBox.hwnd, left, top, mw, mh, UIBox.draggable)) {
+			zui_begin(ui);
+			if (zui_window(UIBox.hwnd, left, top, mw, mh, UIBox.draggable)) {
 				ui._y += 10;
 				UIBox.boxCommands(ui);
 				UIBox.windowBorder(ui);
@@ -105,7 +105,7 @@ class UIBox {
 			zui_end();
 		}
 
-		g2_begin(g, false);
+		g2_begin(null, false);
 
 		UIBox.draws++;
 	}
@@ -176,10 +176,10 @@ class UIBox {
 	static windowBorder = (ui: zui_t) => {
 		if (ui.scissor) {
 			ui.scissor = false;
-			g2_disable_scissor(ui.g);
+			g2_disable_scissor();
 		}
 		// Border
-		ui.g.color = ui.t.SEPARATOR_COL;
+		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);

+ 9 - 9
base/Sources/UIFiles.ts

@@ -176,19 +176,19 @@ class UIFiles {
 											if (Base.pipeCopyRGB == null) Base.makePipeCopyRGB();
 											icon = image_create_render_target(image.width, image.height);
 											if (f.endsWith(".arm")) { // Used for material sphere alpha cutout
-												g2_begin(icon.g2, false);
+												g2_begin(icon, false);
 
 												///if (is_paint || is_sculpt)
 												g2_draw_image(Project.materials[0].image, 0, 0);
 												///end
 											}
 											else {
-												g2_begin(icon.g2, true, 0xffffffff);
+												g2_begin(icon, true, 0xffffffff);
 											}
-											icon.g2.pipeline = Base.pipeCopyRGB;
+											g2_set_pipeline(Base.pipeCopyRGB);
 											g2_draw_image(image, 0, 0);
-											icon.g2.pipeline = null;
-											g2_end(icon.g2);
+											g2_set_pipeline(null);
+											g2_end();
 											UIFiles.iconMap.set(handle.text + Path.sep + f, icon);
 											UIBase.hwnds[TabArea.TabStatus].redraws = 3;
 										});
@@ -285,11 +285,11 @@ class UIFiles {
 								let sw = image.width > image.height ? w : Math.floor(1.0 * image.width / image.height * w);
 								let sh = 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, true, 0xffffffff);
-								icon.g2.pipeline = Base.pipeCopyRGB;
+								g2_begin(icon, true, 0xffffffff);
+								g2_set_pipeline(Base.pipeCopyRGB);
 								g2_draw_scaled_image(image, 0, 0, sw, sh);
-								icon.g2.pipeline = null;
-								g2_end(icon.g2);
+								g2_set_pipeline(null);
+								g2_end();
 								UIFiles.iconMap.set(shandle, icon);
 								UIBase.hwnds[TabArea.TabStatus].redraws = 3;
 								data_delete_image(shandle); // The big image is not needed anymore

+ 17 - 14
base/Sources/UIHeader.ts

@@ -9,7 +9,7 @@ class UIHeader {
 	constructor() {
 	}
 
-	static renderUI = (g: g2_t) => {
+	static renderUI = () => {
 		let ui = UIBase.ui;
 		if (Config.raw.touch_ui) {
 			UIHeader.headerh = UIHeader.defaultHeaderH + 6;
@@ -28,7 +28,7 @@ class UIHeader {
 		let ww = sys_width() - UIToolbar.toolbarw - Config.raw.layout[LayoutSize.LayoutSidebarW] - nodesw;
 		///end
 
-		if (zui_window(ui, UIHeader.headerHandle, app_x(), UIHeader.headerh, ww, UIHeader.headerh)) {
+		if (zui_window(UIHeader.headerHandle, app_x(), UIHeader.headerh, ww, UIHeader.headerh)) {
 			ui._y += 2;
 			UIHeader.drawToolProperties(ui);
 		}
@@ -81,7 +81,7 @@ class UIHeader {
 				let _next = () => {
 					if (Base.pipeMerge == null) Base.makePipe();
 					if (const_data_screen_aligned_vb == null) const_data_create_screen_aligned_data();
-					g4_begin(m.texpaint.g4);
+					g4_begin(m.texpaint);
 					g4_set_pipeline(Base.pipeColorIdToMask);
 					g4_set_tex(Base.texpaintColorId,render_path_render_targets.get("texpaint_colorid").image);
 					g4_set_tex(Base.texColorId, Project.getImage(Project.assets[Context.raw.colorIdHandle.position]));
@@ -246,11 +246,11 @@ class UIHeader {
 				let progress = RenderPathRaytraceBake.currentSample / Context.raw.bakeSamples;
 				if (progress > 1.0) progress = 1.0;
 				// Progress bar
-				ui.g.color = ui.t.SEPARATOR_COL;
-				zui_draw_rect(ui.g, true, ui._x + 1, ui._y, ui._w - 2, zui_ELEMENT_H(ui));
-				ui.g.color = ui.t.HIGHLIGHT_COL;
-				zui_draw_rect(ui.g, true, ui._x + 1, ui._y, (ui._w - 2) * progress, zui_ELEMENT_H(ui));
-				ui.g.color = 0xffffffff;
+				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.currentSample);
 				zui_text(tr("Rays/pixel" + ": ") + RenderPathRaytraceBake.raysPix);
 				zui_text(tr("Rays/second" + ": ") + RenderPathRaytraceBake.raysSec);
@@ -311,9 +311,10 @@ class UIHeader {
 				Context.raw.brushScale = zui_slider(brushScaleHandle, tr("UV Scale"), 0.01, 5.0, true);
 				if (brushScaleHandle.changed) {
 					if (Context.raw.tool == WorkspaceTool.ToolDecal || Context.raw.tool == WorkspaceTool.ToolText) {
-						g2_end(ui.g);
+						let current = _g2_current;
+						g2_end();
 						UtilRender.makeDecalPreview();
-						g2_begin(ui.g, false);
+						g2_begin(current, false);
 					}
 				}
 
@@ -378,10 +379,11 @@ class UIHeader {
 				ui._w = w;
 
 				if (h.changed) {
-					g2_end(ui.g);
+					let current = _g2_current;
+					g2_end();
 					UtilRender.makeTextPreview();
 					UtilRender.makeDecalPreview();
-					g2_begin(ui.g, false);
+					g2_begin(current, false);
 				}
 			}
 
@@ -389,10 +391,11 @@ class UIHeader {
 				zui_combo(Context.raw.fillTypeHandle, [tr("Object"), tr("Face"), tr("Angle"), tr("UV Island")], tr("Fill Mode"));
 				if (Context.raw.fillTypeHandle.changed) {
 					if (Context.raw.fillTypeHandle.position == FillType.FillFace) {
-						g2_end(ui.g);
+						let current = _g2_current;
+						g2_end();
 						// UtilUV.cacheUVMap();
 						UtilUV.cacheTriangleMap();
-						g2_begin(ui.g, false);
+						g2_begin(current, false);
 						// wireframeHandle.selected = drawWireframe = true;
 					}
 					MakeMaterial.parsePaintMaterial();

+ 15 - 14
base/Sources/UIMenu.ts

@@ -13,7 +13,7 @@ class UIMenu {
 	static showMenuFirst = true;
 	static hideMenu = false;
 
-	static render = (g: g2_t) => {
+	static render = () => {
 		let ui = Base.uiMenu;
 		let menuW = UIMenu.menuCommands != null ? Math.floor(Base.defaultElementW * zui_SCALE(Base.uiMenu) * 2.3) : Math.floor(zui_ELEMENT_W(ui) * 2.3);
 		let _BUTTON_COL = ui.t.BUTTON_COL;
@@ -23,14 +23,14 @@ class UIMenu {
 		let _ELEMENT_H = ui.t.ELEMENT_H;
 		ui.t.ELEMENT_H = Config.raw.touch_ui ? (28 + 2) : 28;
 
-		zui_begin_region(ui, g, UIMenu.menuX, UIMenu.menuY, menuW);
+		zui_begin_region(ui, UIMenu.menuX, UIMenu.menuY, menuW);
 
 		if (UIMenu.menuCommands != null) {
-			ui.g.color = ui.t.ACCENT_SELECT_COL;
-			zui_draw_rect(ui.g, true, ui._x + -1, ui._y + -1, ui._w + 2, zui_ELEMENT_H(ui) * UIMenu.menuElements + 2);
-			ui.g.color = ui.t.SEPARATOR_COL;
-			zui_draw_rect(ui.g, true, ui._x + 0, ui._y + 0, ui._w, zui_ELEMENT_H(ui) * UIMenu.menuElements);
-			ui.g.color = 0xffffffff;
+			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.menuElements + 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.menuElements);
+			g2_set_color(0xffffffff);
 
 			UIMenu.menuCommands(ui);
 		}
@@ -221,9 +221,10 @@ class UIMenu {
 				UIMenu.menuFill(ui);
 				Context.raw.drawWireframe = zui_check(Context.raw.wireframeHandle, " " + tr("Wireframe"));
 				if (Context.raw.wireframeHandle.changed) {
-					g2_end(ui.g);
+					let current = _g2_current;
+					g2_end();
 					UtilUV.cacheUVMap();
-					g2_begin(ui.g, false);
+					g2_begin(current, false);
 					MakeMaterial.parseMeshMaterial();
 				}
 				///end
@@ -567,11 +568,11 @@ class UIMenu {
 	}
 
 	static menuFill = (ui: zui_t) => {
-		ui.g.color = ui.t.ACCENT_SELECT_COL;
+		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);
-		ui.g.color = ui.t.SEPARATOR_COL;
+		g2_set_color(ui.t.SEPARATOR_COL);
 		g2_fill_rect(ui._x, ui._y, ui._w, zui_ELEMENT_H(ui) + 1);
-		ui.g.color = 0xffffffff;
+		g2_set_color(0xffffffff);
 	}
 
 	static menuSeparator = (ui: zui_t) => {
@@ -606,7 +607,7 @@ class UIMenu {
 
 	static menuStart = (ui: zui_t) => {
 		// Draw top border
-		ui.g.color = ui.t.ACCENT_SELECT_COL;
+		g2_set_color(ui.t.ACCENT_SELECT_COL);
 		if (Config.raw.touch_ui) {
 			g2_fill_rect(ui._x + ui._w / 2 + UIMenu.menuCategoryW / 2, ui._y - 1, ui._w / 2 - UIMenu.menuCategoryW / 2 + 1, 1);
 			g2_fill_rect(ui._x - 1, ui._y - 1, ui._w / 2 - UIMenu.menuCategoryW / 2 + 1, 1);
@@ -620,6 +621,6 @@ class UIMenu {
 			g2_fill_rect(ui._x - 1, ui._y - UIMenu.menuCategoryH, 1, UIMenu.menuCategoryH);
 			g2_fill_rect(ui._x - 1 + UIMenu.menuCategoryW, ui._y - UIMenu.menuCategoryH, 1, UIMenu.menuCategoryH);
 		}
-		ui.g.color = 0xffffffff;
+		g2_set_color(0xffffffff);
 	}
 }

+ 3 - 3
base/Sources/UIMenubar.ts

@@ -14,7 +14,7 @@ class UIMenubar {
 	constructor() {
 	}
 
-	static renderUI = (g: g2_t) => {
+	static renderUI = () => {
 		let ui = UIBase.ui;
 
 		///if (is_paint || is_sculpt)
@@ -24,7 +24,7 @@ class UIMenubar {
 		let panelx = app_x();
 		///end
 
-		if (zui_window(ui, UIMenubar.menuHandle, panelx, 0, UIMenubar.menubarw, UIHeader.headerh)) {
+		if (zui_window(UIMenubar.menuHandle, panelx, 0, UIMenubar.menubarw, UIHeader.headerh)) {
 			ui._x += 1; // Prevent "File" button highlight on startup
 
 			zui_begin_menu();
@@ -96,7 +96,7 @@ class UIMenubar {
 		panelx = (app_x()) + UIMenubar.menubarw;
 		///end
 
-		if (zui_window(ui, UIMenubar.workspaceHandle, panelx, 0, ww, UIHeader.headerh)) {
+		if (zui_window(UIMenubar.workspaceHandle, panelx, 0, ww, UIHeader.headerh)) {
 
 			if (!Config.raw.touch_ui) {
 				zui_tab(UIHeader.worktab, tr("3D View"));

+ 20 - 20
base/Sources/UINodes.ts

@@ -473,9 +473,9 @@ class UINodes {
 		let searchHandle = zui_handle("uinodes_9");
 		let first = true;
 		UIMenu.draw((ui: zui_t) => {
-			ui.g.color = ui.t.SEPARATOR_COL;
-			zui_draw_rect(ui.g, true, ui._x, ui._y, ui._w, zui_ELEMENT_H(ui) * 8);
-			ui.g.color = 0xffffffff;
+			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 = zui_text_input(searchHandle, "", Align.Left, true, true).toLowerCase();
 			ui.changed = false;
@@ -563,9 +563,9 @@ class UINodes {
 		if (w < 1) w = 1;
 		if (h < 1) h = 1;
 		UINodes.grid = image_create_render_target(w, h);
-		g2_begin(UINodes.grid.g2, true, UINodes.ui.t.SEPARATOR_COL);
+		g2_begin(UINodes.grid, true, UINodes.ui.t.SEPARATOR_COL);
 
-		UINodes.grid.g2.color = UINodes.ui.t.SEPARATOR_COL - 0x00050505;
+		g2_set_color(UINodes.ui.t.SEPARATOR_COL - 0x00050505);
 		step = 20 * zui_SCALE(UINodes.ui);
 		for (let i = 0; i < Math.floor(h / step) + 1; ++i) {
 			g2_draw_line(0, i * step, w, i * step);
@@ -574,7 +574,7 @@ class UINodes {
 			g2_draw_line(i * step, 0, i * step, h);
 		}
 
-		UINodes.grid.g2.color = UINodes.ui.t.SEPARATOR_COL - 0x00090909;
+		g2_set_color(UINodes.ui.t.SEPARATOR_COL - 0x00090909);
 		step = 100 * zui_SCALE(UINodes.ui);
 		for (let i = 0; i < Math.floor(h / step) + 1; ++i) {
 			g2_draw_line(0, i * step, w, i * step);
@@ -583,10 +583,10 @@ class UINodes {
 			g2_draw_line(i * step, 0, i * step, h);
 		}
 
-		g2_end(UINodes.grid.g2);
+		g2_end();
 	}
 
-	static render = (g: g2_t) => {
+	static render = () => {
 		if (UINodes.recompileMat) {
 			///if (is_paint || is_sculpt)
 			if (UINodes.canvasType == CanvasType.CanvasBrush) {
@@ -657,7 +657,7 @@ class UINodes {
 
 		UINodes.ui.input_enabled = Base.uiEnabled;
 
-		g2_end(g);
+		g2_end();
 
 		if (UINodes.grid == null) UINodes.drawGrid();
 
@@ -668,7 +668,7 @@ class UINodes {
 		///end
 
 		// Start with UI
-		zui_begin(UINodes.ui, g);
+		zui_begin(UINodes.ui);
 
 		// Make window
 		UINodes.ww = Config.raw.layout[LayoutSize.LayoutNodesW];
@@ -702,12 +702,12 @@ class UINodes {
 			}
 		}
 
-		if (zui_window(UINodes.ui, UINodes.hwnd, UINodes.wx, UINodes.wy, UINodes.ww, UINodes.wh)) {
+		if (zui_window(UINodes.hwnd, UINodes.wx, UINodes.wy, UINodes.ww, UINodes.wh)) {
 
 			zui_tab(zui_handle("uinodes_10"), tr("Nodes"));
 
 			// Grid
-			UINodes.ui.g.color = 0xffffffff;
+			g2_set_color(0xffffffff);
 			let step = 100 * zui_SCALE(UINodes.ui);
 			g2_draw_image(UINodes.grid, (nodes.panX * zui_nodes_SCALE()) % step - step, (nodes.panY * zui_nodes_SCALE()) % step - step);
 
@@ -862,7 +862,7 @@ class UINodes {
 
 					///if (is_paint || is_sculpt)
 					if (singleChannel) {
-						UINodes.ui.g.pipeline = UIView2D.pipe;
+						g2_set_pipeline(UIView2D.pipe);
 						///if krom_opengl
 						Krom.setPipeline(UIView2D.pipe.pipeline_);
 						///end
@@ -870,23 +870,23 @@ class UINodes {
 					}
 					///end
 
-					UINodes.ui.g.color = 0xffffffff;
+					g2_set_color(0xffffffff);
 					invertY ?
 						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  (singleChannel) {
-						UINodes.ui.g.pipeline = null;
+					if (singleChannel) {
+						g2_set_pipeline(null);
 					}
 					///end
 				}
 			}
 
 			// Menu
-			UINodes.ui.g.color = UINodes.ui.t.SEPARATOR_COL;
+			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);
-			UINodes.ui.g.color = 0xffffffff;
+			g2_set_color(0xffffffff);
 
 			let startY = zui_ELEMENT_H(UINodes.ui) + zui_ELEMENT_OFFSET(UINodes.ui);
 			UINodes.ui._x = 0;
@@ -995,7 +995,7 @@ class UINodes {
 
 		zui_end(!UINodes.showMenu);
 
-		g2_begin(g, false);
+		g2_begin(null, false);
 
 		if (UINodes.showMenu) {
 			///if (is_paint || is_sculpt)
@@ -1018,7 +1018,7 @@ class UINodes {
 
 			let py = UINodes.popupY;
 			let menuw = Math.floor(ew * 2.3);
-			zui_begin_region(UINodes.ui, g, Math.floor(UINodes.popupX), Math.floor(py), menuw);
+			zui_begin_region(UINodes.ui, Math.floor(UINodes.popupX), Math.floor(py), menuw);
 			let _BUTTON_COL = UINodes.ui.t.BUTTON_COL;
 			UINodes.ui.t.BUTTON_COL = UINodes.ui.t.SEPARATOR_COL;
 			let _ELEMENT_OFFSET = UINodes.ui.t.ELEMENT_OFFSET;

+ 3 - 3
base/Sources/UIStatus.ts

@@ -15,16 +15,16 @@ class UIStatus {
 		///end
 	}
 
-	static renderUI = (g: g2_t) => {
+	static renderUI = () => {
 		let ui = UIBase.ui;
 
 		let statush = Config.raw.layout[LayoutSize.LayoutStatusH];
 
-		if (zui_window(ui, UIBase.hwnds[TabArea.TabStatus], app_x(), sys_height() - statush, UIStatus.width, statush)) {
+		if (zui_window(UIBase.hwnds[TabArea.TabStatus], app_x(), sys_height() - statush, UIStatus.width, statush)) {
 			ui._y += 2;
 
 			// Border
-			ui.g.color = ui.t.SEPARATOR_COL;
+			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);
 

+ 4 - 4
base/Sources/UIToolbar.ts

@@ -29,7 +29,7 @@ class UIToolbar {
 	constructor() {
 	}
 
-	static renderUI = (g: g2_t) => {
+	static renderUI = () => {
 		let ui = UIBase.ui;
 
 		if (Config.raw.touch_ui) {
@@ -40,7 +40,7 @@ class UIToolbar {
 		}
 		UIToolbar.toolbarw = Math.floor(UIToolbar.toolbarw * zui_SCALE(ui));
 
-		if (zui_window(ui, UIToolbar.toolbarHandle, 0, UIHeader.headerh, UIToolbar.toolbarw, sys_height() - UIHeader.headerh)) {
+		if (zui_window(UIToolbar.toolbarHandle, 0, UIHeader.headerh, UIToolbar.toolbarw, sys_height() - UIHeader.headerh)) {
 			ui._y -= 4 * zui_SCALE(ui);
 
 			ui.image_scroll_align = false;
@@ -200,8 +200,8 @@ class UIToolbar {
 	static drawHighlight = () => {
 		let ui = UIBase.ui;
 		let size = UIToolbar.toolbarw - 4;
-		ui.g.color = ui.t.HIGHLIGHT_COL;
-		zui_draw_rect(ui.g, true, ui._x + -1,  ui._y + 2, size + 2, size + 2);
+		g2_set_color(ui.t.HIGHLIGHT_COL);
+		zui_draw_rect(true, ui._x + -1,  ui._y + 2, size + 2, size + 2);
 	}
 }
 

+ 22 - 23
base/Sources/UIView2D.ts

@@ -32,16 +32,16 @@ class UIView2D {
 	constructor() {
 		///if (is_paint || is_sculpt)
 		UIView2D.pipe = pipeline_create();
-		UIView2D.pipe.vertexShader = sys_get_shader("layer_view.vert");
-		UIView2D.pipe.fragmentShader = sys_get_shader("layer_view.frag");
+		UIView2D.pipe.vertex_shader = sys_get_shader("layer_view.vert");
+		UIView2D.pipe.fragment_shader = sys_get_shader("layer_view.frag");
 		let vs = vertex_struct_create();
 		vertex_struct_add(vs, "pos", VertexData.F32_3X);
 		vertex_struct_add(vs, "tex", VertexData.F32_2X);
 		vertex_struct_add(vs, "col", VertexData.U8_4X_Normalized);
-		UIView2D.pipe.inputLayout = [vs];
-		UIView2D.pipe.blendSource = BlendingFactor.BlendOne;
-		UIView2D.pipe.blendDestination = BlendingFactor.BlendZero;
-		UIView2D.pipe.colorWriteMasksAlpha[0] = false;
+		UIView2D.pipe.input_layout = [vs];
+		UIView2D.pipe.blend_source = BlendingFactor.BlendOne;
+		UIView2D.pipe.blend_dest = BlendingFactor.BlendZero;
+		UIView2D.pipe.color_write_masks_alpha[0] = false;
 		pipeline_compile(UIView2D.pipe);
 		UIView2D.channelLocation = pipeline_get_const_loc(UIView2D.pipe, "channel");
 		///end
@@ -51,7 +51,7 @@ class UIView2D {
 		UIView2D.ui.scroll_enabled = false;
 	}
 
-	static render = (g: g2_t) => {
+	static render = () => {
 
 		UIView2D.ww = Config.raw.layout[LayoutSize.LayoutNodesW];
 
@@ -75,7 +75,7 @@ class UIView2D {
 
 		if (Context.raw.pdirty >= 0) UIView2D.hwnd.redraws = 2; // Paint was active
 
-		g2_end(g);
+		g2_end();
 
 		// Cache grid
 		if (UINodes.grid == null) UINodes.drawGrid();
@@ -90,7 +90,7 @@ class UIView2D {
 		if (Context.raw.font.image == null) UtilRender.makeFontPreview();
 		///end
 
-		zui_begin(UIView2D.ui, g);
+		zui_begin(UIView2D.ui);
 
 		let headerh = Config.raw.layout[LayoutSize.LayoutHeader] == 1 ? UIHeader.headerh * 2 : UIHeader.headerh;
 		let apph = sys_height() - Config.raw.layout[LayoutSize.LayoutStatusH] + headerh;
@@ -101,12 +101,12 @@ class UIView2D {
 			if (Config.raw.touch_ui) UIView2D.wh += UIHeader.headerh;
 		}
 
-		if (zui_window(UIView2D.ui, UIView2D.hwnd, UIView2D.wx, UIView2D.wy, UIView2D.ww, UIView2D.wh)) {
+		if (zui_window(UIView2D.hwnd, UIView2D.wx, UIView2D.wy, UIView2D.ww, UIView2D.wh)) {
 
 			zui_tab(zui_handle("uiview2d_0"), tr("2D View"));
 
 			// Grid
-			UIView2D.ui.g.color = 0xffffffff;
+			g2_set_color(0xffffffff);
 			g2_draw_image(UINodes.grid, (UIView2D.panX * UIView2D.panScale) % 100 - 100, (UIView2D.panY * UIView2D.panScale) % 100 - 100);
 
 			// Texture
@@ -152,13 +152,13 @@ class UIView2D {
 
 				if (UIView2D.layerMode == View2DLayerMode.View2DVisible) {
 					let current = _g2_current;
-					if (current != null) g2_end(current);
+					if (current != null) g2_end();
 					layer = Base.flatten();
 					if (current != null) g2_begin(current, false);
 				}
 				else if (SlotLayer.isGroup(layer)) {
 					let current = _g2_current;
-					if (current != null) g2_end(current);
+					if (current != null) g2_end();
 					layer = Base.flatten(false, SlotLayer.getChildren(layer));
 					if (current != null) g2_begin(current, false);
 				}
@@ -193,10 +193,10 @@ class UIView2D {
 				///if (is_paint || is_sculpt)
 				if (UIView2D.type == View2DType.View2DLayer) {
 					///if (!krom_opengl)
-					UIView2D.ui.g.pipeline = UIView2D.pipe;
+					g2_set_pipeline(UIView2D.pipe);
 					///end
 					if (!Context.raw.textureFilter) {
-						UIView2D.ui.g.image_scale_quality = ImageScaleQuality.Low;
+						g2_set_image_scale_quality(ImageScaleQuality.Low);
 					}
 					///if krom_opengl
 					Krom.setPipeline(UIView2D.pipe.pipeline_);
@@ -220,9 +220,9 @@ class UIView2D {
 
 				///if (is_paint || is_sculpt)
 				if (UIView2D.type == View2DType.View2DLayer) {
-					UIView2D.ui.g.pipeline = null;
+					g2_set_pipeline(null);
 					if (!Context.raw.textureFilter) {
-						UIView2D.ui.g.image_scale_quality = ImageScaleQuality.High;
+						g2_set_image_scale_quality(ImageScaleQuality.High);
 					}
 				}
 
@@ -232,10 +232,9 @@ class UIView2D {
 					let y = UIView2D.ui.input_y - ty - UIView2D.wy;
 					Base.notifyOnNextFrame(() => {
 						let texpaint_picker = render_path_render_targets.get("texpaint_picker").image;
-						let g2 = texpaint_picker.g2;
-						g2_begin(g2, false);
+						g2_begin(texpaint_picker, false);
 						g2_draw_scaled_image(tex, -x, -y, tw, th);
-						g2_end(g2);
+						g2_end();
 						let a = new DataView(image_get_pixels(texpaint_picker));
 						///if (krom_metal || krom_vulkan)
 						let i0 = 2;
@@ -265,9 +264,9 @@ class UIView2D {
 
 			// Menu
 			let ew = Math.floor(zui_ELEMENT_W(UIView2D.ui));
-			UIView2D.ui.g.color = UIView2D.ui.t.SEPARATOR_COL;
+			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);
-			UIView2D.ui.g.color = 0xffffffff;
+			g2_set_color(0xffffffff);
 
 			let startY = zui_ELEMENT_H(UIView2D.ui) + zui_ELEMENT_OFFSET(UIView2D.ui);
 			UIView2D.ui._x = 2;
@@ -375,7 +374,7 @@ class UIView2D {
 			///end
 		}
 		zui_end();
-		g2_begin(g, false);
+		g2_begin(null, false);
 	}
 
 	static update = () => {

+ 24 - 27
base/Sources/UtilRender.ts

@@ -51,7 +51,7 @@ class UtilRender {
 		MakeMaterial.parseMeshPreviewMaterial();
 		let _commands = render_path_commands;
 		render_path_commands = RenderPathPreview.commandsPreview;
-		render_path_render_frame(_render_path_frame_g);
+		render_path_render_frame();
 		render_path_commands = _commands;
 
 		Context.raw.materialPreview = false;
@@ -80,7 +80,7 @@ class UtilRender {
 
 	static makeDecalPreview = () => {
 		let current = _g2_current;
-		if (current != null) g2_end(current);
+		if (current != null) g2_end();
 
 		if (Context.raw.decalImage == null) {
 			Context.raw.decalImage = image_create_render_target(UtilRender.decalPreviewSize, UtilRender.decalPreviewSize);
@@ -117,7 +117,7 @@ class UtilRender {
 		MakeMaterial.parseMeshPreviewMaterial();
 		let _commands = render_path_commands;
 		render_path_commands = RenderPathPreview.commandsDecal;
-		render_path_render_frame(_render_path_frame_g);
+		render_path_render_frame();
 		render_path_commands = _commands;
 
 		Context.raw.decalPreview = false;
@@ -146,7 +146,7 @@ class UtilRender {
 
 	static makeTextPreview = () => {
 		let current = _g2_current;
-		if (current != null) g2_end(current);
+		if (current != null) g2_end();
 
 		let text = Context.raw.textToolText;
 		let font = Context.raw.font.font;
@@ -166,20 +166,19 @@ class UtilRender {
 			Context.raw.textToolImage = image_create_render_target(texW, texW, TextureFormat.R8);
 			///end
 		}
-		let g2 = Context.raw.textToolImage.g2;
-		g2_begin(g2, true, 0xff000000);
-		g2.font = font;
-		g2.font_size = fontSize;
-		g2.color = 0xffffffff;
+		g2_begin(Context.raw.textToolImage, true, 0xff000000);
+		g2_set_font(font);
+		g2_set_font_size(fontSize);
+		g2_set_color(0xffffffff);
 		g2_draw_string(text, texW / 2 - textW / 2, texW / 2 - textH / 2);
-		g2_end(g2);
+		g2_end();
 
 		if (current != null) g2_begin(current, false);
 	}
 
 	static makeFontPreview = () => {
 		let current = _g2_current;
-		if (current != null) g2_end(current);
+		if (current != null) g2_end();
 
 		let text = "Abg";
 		let font = Context.raw.font.font;
@@ -189,13 +188,12 @@ class UtilRender {
 		if (Context.raw.font.image == null) {
 			Context.raw.font.image = image_create_render_target(512, 512, TextureFormat.RGBA32);
 		}
-		let g2 = Context.raw.font.image.g2;
-		g2_begin(g2, true, 0x00000000);
-		g2.font = font;
-		g2.font_size = fontSize;
-		g2.color = 0xffffffff;
+		g2_begin(Context.raw.font.image, true, 0x00000000);
+		g2_set_font(font);
+		g2_set_font_size(fontSize);
+		g2_set_color(0xffffffff);
 		g2_draw_string(text, 512 / 2 - textW / 2, 512 / 2 - textH / 2);
-		g2_end(g2);
+		g2_end();
 		Context.raw.font.previewReady = true;
 
 		if (current != null) g2_begin(current, false);
@@ -206,7 +204,7 @@ class UtilRender {
 		Context.raw.materialPreview = true;
 
 		let current = _g2_current;
-		if (current != null) g2_end(current);
+		if (current != null) g2_end();
 
 		// Prepare layers
 		if (RenderPathPaint.liveLayer == null) {
@@ -343,11 +341,11 @@ class UtilRender {
 		if (Base.pipeMerge == null) Base.makePipe();
 		l = RenderPathPaint.liveLayer;
 		let target = Context.raw.brush.image;
-		g2_begin(target.g2, true, 0x00000000);
-		target.g2.pipeline = Base.pipeCopy;
+		g2_begin(target, true, 0x00000000);
+		g2_set_pipeline(Base.pipeCopy);
 		g2_draw_scaled_image(l.texpaint, 0, 0, target.width, target.height);
-		target.g2.pipeline = null;
-		g2_end(target.g2);
+		g2_set_pipeline(null);
+		g2_end();
 
 		// Scale image preview down to to icon
 		render_path_render_targets.get("texpreview").image = Context.raw.brush.image;
@@ -366,7 +364,6 @@ class UtilRender {
 		let res = MakeMaterial.parseNodePreviewMaterial(node, group, parents);
 		if (res == null || res.scon == null) return;
 
-		let g4 = image.g4;
 		if (UtilRender.screenAlignedFullVB == null) {
 			UtilRender.createScreenAlignedFullData();
 		}
@@ -375,11 +372,11 @@ class UtilRender {
 		Context.raw.paintObject.base.transform.scale_world = 3.0;
 		transform_build_matrix(Context.raw.paintObject.base.transform);
 
-		g4_begin(g4);
+		g4_begin(image);
 		g4_set_pipeline(res.scon._pipe_state);
-		uniforms_set_context_consts(g4, res.scon, [""]);
-		uniforms_set_obj_consts(g4, res.scon, Context.raw.paintObject.base);
-		uniforms_set_material_consts(g4, res.scon, res.mcon);
+		uniforms_set_context_consts(res.scon, [""]);
+		uniforms_set_obj_consts(res.scon, Context.raw.paintObject.base);
+		uniforms_set_material_consts(res.scon, res.mcon);
 		g4_set_vertex_buffer(UtilRender.screenAlignedFullVB);
 		g4_set_index_buffer(UtilRender.screenAlignedFullIB);
 		g4_draw();

+ 13 - 14
base/Sources/UtilUV.ts

@@ -36,8 +36,8 @@ class UtilUV {
 
 		let texa = mesh.vertex_arrays[2].values;
 		let inda = mesh.index_arrays[0].values;
-		g2_begin(UtilUV.uvmap.g2, true, 0x00000000);
-		UtilUV.uvmap.g2.color = 0xffcccccc;
+		g2_begin(UtilUV.uvmap, true, 0x00000000);
+		g2_set_color(0xffcccccc);
 		let strength = resX > 2048 ? 2.0 : 1.0;
 		let f = (1 / 32767) * UtilUV.uvmap.width;
 		for (let i = 0; i < Math.floor(inda.length / 3); ++i) {
@@ -51,7 +51,7 @@ class UtilUV {
 			g2_draw_line(x2, y2, x3, y3, strength);
 			g2_draw_line(x3, y3, x1, y1, strength);
 		}
-		g2_end(UtilUV.uvmap.g2);
+		g2_end();
 	}
 
 	static cacheTriangleMap = () => {
@@ -72,13 +72,13 @@ class UtilUV {
 		let mesh = merged;
 		let texa = mesh.vertex_arrays[2].values;
 		let inda = mesh.index_arrays[0].values;
-		g2_begin(UtilUV.trianglemap.g2, true, 0xff000000);
+		g2_begin(UtilUV.trianglemap, true, 0xff000000);
 		let f = (1 / 32767) * UtilUV.trianglemap.width;
 		let color = 0xff000001;
 		for (let i = 0; i < Math.floor(inda.length / 3); ++i) {
 			if (color == 0xffffffff) color = 0xff000001;
 			color++;
-			UtilUV.trianglemap.g2.color = color;
+			g2_set_color(color);
 			let x1 = (texa[inda[i * 3    ] * 2    ]) * f;
 			let x2 = (texa[inda[i * 3 + 1] * 2    ]) * f;
 			let x3 = (texa[inda[i * 3 + 2] * 2    ]) * f;
@@ -87,7 +87,7 @@ class UtilUV {
 			let y3 = (texa[inda[i * 3 + 2] * 2 + 1]) * f;
 			g2_fill_triangle(x1, y1, x2, y2, x3, y3);
 		}
-		g2_end(UtilUV.trianglemap.g2);
+		g2_end();
 	}
 
 	static cacheDilateMap = () => {
@@ -105,8 +105,8 @@ class UtilUV {
 
 		if (UtilUV.pipeDilate == null) {
 			UtilUV.pipeDilate = pipeline_create();
-			UtilUV.pipeDilate.vertexShader = sys_get_shader("dilate_map.vert");
-			UtilUV.pipeDilate.fragmentShader = sys_get_shader("dilate_map.frag");
+			UtilUV.pipeDilate.vertex_shader = sys_get_shader("dilate_map.vert");
+			UtilUV.pipeDilate.fragment_shader = sys_get_shader("dilate_map.frag");
 			let vs = vertex_struct_create();
 			///if (krom_metal || krom_vulkan)
 			vertex_struct_add(vs, "tex", VertexData.I16_2X_Normalized);
@@ -115,10 +115,10 @@ class UtilUV {
 			vertex_struct_add(vs, "nor", VertexData.I16_2X_Normalized);
 			vertex_struct_add(vs, "tex", VertexData.I16_2X_Normalized);
 			///end
-			UtilUV.pipeDilate.inputLayout = [vs];
-			UtilUV.pipeDilate.depthWrite = false;
-			UtilUV.pipeDilate.depthMode = CompareMode.Always;
-			UtilUV.pipeDilate.colorAttachments[0] = TextureFormat.R8;
+			UtilUV.pipeDilate.input_layout = [vs];
+			UtilUV.pipeDilate.depth_write = false;
+			UtilUV.pipeDilate.depth_mode = CompareMode.Always;
+			UtilUV.pipeDilate.color_attachments[0] = TextureFormat.R8;
 			pipeline_compile(UtilUV.pipeDilate);
 			// dilateTexUnpack = getConstantLocation(UtilUV.pipeDilate, "texUnpack");
 		}
@@ -126,8 +126,7 @@ class UtilUV {
 		let mask = Context.objectMaskUsed() ? SlotLayer.getObjectMask(Context.raw.layer) : 0;
 		if (Context.layerFilterUsed()) mask = Context.raw.layerFilter;
 		let geom = mask == 0 && Context.raw.mergedObject != null ? Context.raw.mergedObject.data : Context.raw.paintObject.data;
-		let g4 = UtilUV.dilatemap.g4;
-		g4_begin(g4);
+		g4_begin(UtilUV.dilatemap);
 		g4_clear(0x00000000);
 		g4_set_pipeline(UtilUV.pipeDilate);
 		///if (krom_metal || krom_vulkan)

+ 278 - 260
misc/pad/Sources/main.ts

@@ -1,5 +1,5 @@
 
-type TStorage = {
+type storage_t = {
 	project: string;
 	file: string;
 	text: string;
@@ -12,318 +12,336 @@ type TStorage = {
 	sidebar_w: i32;
 };
 
-class Main {
-
-	static ui: ZuiRaw;
-	static text_handle = zui_handle_create();
-	static sidebar_handle = zui_handle_create();
-	static editor_handle = zui_handle_create();
-	static storage: TStorage = null;
-	static resizing_sidebar = false;
-	static minimap_w = 150;
-	static minimap_h = 0;
-	static minimap_box_h = 0;
-	static minimap_scrolling = false;
-	static minimap: ImageRaw = null;
-	static window_header_h = 0;
-
-	static main = () => {
-		Zui.textAreaLineNumbers = true;
-		Zui.textAreaScrollPastEnd = true;
-
-		Krom.setApplicationName("ArmorPad");
-		let blob_storage = Krom.loadBlob(Krom.savePath() + "/config.json");
-		if (blob_storage == null) {
-			Main.storage = {
-				project: "",
-				file: "untitled",
-				text: "",
-				modified: false,
-				expanded: [],
-				window_w: 1600,
-				window_h: 900,
-				window_x: -1,
-				window_y: -1,
-				sidebar_w: 230,
-			};
-		}
-		else Main.storage = JSON.parse(sys_buffer_to_string(blob_storage));
-
-		Main.text_handle.text = Main.storage.text;
-		let ops: kinc_sys_ops_t = {
-			title: "ArmorPad",
-			x: Main.storage.window_x,
-			y: Main.storage.window_y,
-			width: Main.storage.window_w,
-			height: Main.storage.window_h,
-			features: WindowFeatures.FeatureResizable | WindowFeatures.FeatureMaximizable | WindowFeatures.FeatureMinimizable,
-			mode: WindowMode.Windowed,
-			frequency: 60,
-			vsync: true
+let ui: zui_t;
+let text_handle = zui_handle_create();
+let sidebar_handle = zui_handle_create();
+let editor_handle = zui_handle_create();
+let storage: storage_t = null;
+let resizing_sidebar = false;
+let minimap_w = 150;
+let minimap_h = 0;
+let minimap_box_h = 0;
+let minimap_scrolling = false;
+let minimap: image_t = null;
+let window_header_h = 0;
+
+function main() {
+	zui_set_text_area_line_numbers(true);
+	zui_set_text_area_scroll_past_end(true);
+
+	Krom.setApplicationName("ArmorPad");
+	let blob_storage = Krom.loadBlob(Krom.savePath() + "/config.json");
+	if (blob_storage == null) {
+		storage = {
+			project: "",
+			file: "untitled",
+			text: "",
+			modified: false,
+			expanded: [],
+			window_w: 1600,
+			window_h: 900,
+			window_x: -1,
+			window_y: -1,
+			sidebar_w: 230,
 		};
+	}
+	else {
+		storage = JSON.parse(sys_buffer_to_string(blob_storage));
+	}
 
-		sys_start(ops, () => {
-			data_get_font("font_mono.ttf", (font: FontRaw) => {
-				data_get_blob("themes/dark.json", (blob_theme: ArrayBuffer) => {
-					data_get_blob("text_coloring.json", (blob_coloring: ArrayBuffer) => {
-
-						let parsed = JSON.parse(sys_buffer_to_string(blob_theme));
-						let theme: any = Theme.create();
-						for (let key of Object.getOwnPropertyNames(Theme.prototype)) {
-							if (key == "constructor") continue;
-							theme[key] = parsed[key];
+	text_handle.text = storage.text;
+	let ops: kinc_sys_ops_t = {
+		title: "ArmorPad",
+		x: storage.window_x,
+		y: storage.window_y,
+		width: storage.window_w,
+		height: storage.window_h,
+		features: WindowFeatures.FeatureResizable | WindowFeatures.FeatureMaximizable | WindowFeatures.FeatureMinimizable,
+		mode: WindowMode.Windowed,
+		frequency: 60,
+		vsync: true
+	};
+
+	sys_start(ops, function() {
+		data_get_font("font_mono.ttf", function (font: font_t) {
+			data_get_blob("themes/dark.json", function (blob_theme: ArrayBuffer) {
+				data_get_blob("text_coloring.json", function (blob_coloring: ArrayBuffer) {
+
+					let parsed = JSON.parse(sys_buffer_to_string(blob_theme));
+					let theme: any = zui_theme_create();
+					for (let key of Object.getOwnPropertyNames(theme_t.prototype)) {
+						if (key == "constructor") {
+							continue;
 						}
+						theme[key] = parsed[key];
+					}
 
-						font_init(font);
-						Main.ui = Zui.create({ theme: theme, font: font, scaleFactor: 1.0, color_wheel: null, black_white_gradient: null });
-						Zui.onBorderHover = Main.on_border_hover;
-						Zui.onTextHover = Main.on_text_hover;
+					g2_font_init(font);
+					ui = zui_create({ theme: theme, font: font, scaleFactor: 1.0, color_wheel: null, black_white_gradient: null });
+					zui_set_on_border_hover(on_border_hover);
+					zui_set_on_text_hover(on_text_hover);
 
-						let textColoring: TTextColoring = JSON.parse(sys_buffer_to_string(blob_coloring));
-						textColoring.default_color = Math.floor(textColoring.default_color);
-						for (let coloring of textColoring.colorings) coloring.color = Math.floor(coloring.color);
-						Zui.textAreaColoring = textColoring;
+					let text_coloring: zui_text_coloring_t = JSON.parse(sys_buffer_to_string(blob_coloring));
+					text_coloring.default_color = Math.floor(text_coloring.default_color);
+					for (let coloring of text_coloring.colorings) {
+						coloring.color = Math.floor(coloring.color);
+					}
+					zui_set_text_area_coloring(text_coloring);
 
-						sys_notify_on_frames(Main.render);
-					});
+					sys_notify_on_frames(render);
 				});
 			});
 		});
+	});
+
+	Krom.setDropFilesCallback(function (path: string) {
+		storage.project = path;
+		sidebar_handle.redraws = 1;
+	});
+
+	Krom.setApplicationStateCallback(
+		function() {},
+		function() {},
+		function() {},
+		function() {},
+		function () { // Shutdown
+			Krom.fileSaveBytes(Krom.savePath() + "/config.json", sys_string_to_buffer(JSON.stringify(storage)));
+		}
+	);
+}
 
-		Krom.setDropFilesCallback((path: string) => {
-			Main.storage.project = path;
-			Main.sidebar_handle.redraws = 1;
-		});
-
-		Krom.setApplicationStateCallback(() => {}, () => {}, () => {}, () => {},
-			() => { // Shutdown
-				Krom.fileSaveBytes(Krom.savePath() + "/config.json", sys_string_to_buffer(JSON.stringify(Main.storage)));
-			}
-		);
-	}
-
-	static list_folder = (path: string) => {
-		let ui = Main.ui;
-		let files = Krom.readDirectory(path, false).split("\n");
-		for (let f of files) {
-			let abs = path + "/" + f;
-			let isFile = f.indexOf(".") >= 0;
-			let isExpanded = Main.storage.expanded.indexOf(abs) >= 0;
-
-			// Active file
-			if (abs == Main.storage.file) {
-				Zui.fill(0, 1, ui._w - 1, Zui.ELEMENT_H(ui) - 1, ui.t.BUTTON_PRESSED_COL);
-			}
+function list_folder(path: string) {
+	let files = Krom.readDirectory(path, false).split("\n");
+	for (let f of files) {
+		let abs = path + "/" + f;
+		let is_file = f.indexOf(".") >= 0;
+		let is_expanded = storage.expanded.indexOf(abs) >= 0;
 
-			let prefix = "";
-			if (!isFile) prefix = isExpanded ? "- " : "+ ";
-
-			if (Zui.button(prefix + f, Align.Left)) {
-				// Open file
-				if (isFile) {
-					Main.storage.file = abs;
-					let bytes = Krom.loadBlob(Main.storage.file);
-					Main.storage.text = f.endsWith(".arm") ? JSON.stringify(decode(bytes), null, 4) : sys_buffer_to_string(bytes);
-					Main.storage.text = Main.storage.text.replaceAll("\r", "");
-					Main.text_handle.text = Main.storage.text;
-					Main.editor_handle.redraws = 1;
-					Krom.setWindowTitle(abs);
-				}
-				// Expand folder
-				else {
-					Main.storage.expanded.indexOf(abs) == -1 ? Main.storage.expanded.push(abs) : array_remove(Main.storage.expanded, abs);
-				}
-			}
+		// Active file
+		if (abs == storage.file) {
+			zui_fill(0, 1, ui._w - 1, zui_ELEMENT_H(ui) - 1, ui.t.BUTTON_PRESSED_COL);
+		}
 
-			if (isExpanded) {
-				// ui.indent(false);
-				Main.list_folder(abs);
-				// ui.unindent(false);
-			}
+		let prefix = "";
+		if (!is_file) {
+			prefix = is_expanded ? "- " : "+ ";
 		}
-	}
 
-	static render = (g2: Graphics2Raw, g4: Graphics4Raw): void => {
-		let ui = Main.ui;
-		Main.storage.window_w = sys_width();
-		Main.storage.window_h = sys_height();
-		Main.storage.window_x = Krom.windowX();
-		Main.storage.window_y = Krom.windowY();
-		if (ui.inputDX != 0 || ui.inputDY != 0) Krom.setMouseCursor(0); // Arrow
-
-		Zui.begin(ui, g2);
-
-		if (Zui.window(ui, Main.sidebar_handle, 0, 0, Main.storage.sidebar_w, sys_height(), false)) {
-			let _BUTTON_TEXT_COL = ui.t.BUTTON_TEXT_COL;
-			ui.t.BUTTON_TEXT_COL = ui.t.ACCENT_COL;
-			if (Main.storage.project != "") {
-				Main.list_folder(Main.storage.project);
+		if (zui_button(prefix + f, Align.Left)) {
+			// Open file
+			if (is_file) {
+				storage.file = abs;
+				let bytes = Krom.loadBlob(storage.file);
+				storage.text = f.endsWith(".arm") ? JSON.stringify(armpack_decode(bytes), null, 4) : sys_buffer_to_string(bytes);
+				storage.text = storage.text.replaceAll("\r", "");
+				text_handle.text = storage.text;
+				editor_handle.redraws = 1;
+				Krom.setWindowTitle(abs);
 			}
+			// Expand folder
 			else {
-				Zui.button("Drop folder here", Align.Left);
+				storage.expanded.indexOf(abs) == -1 ? storage.expanded.push(abs) : array_remove(storage.expanded, abs);
 			}
-			ui.t.BUTTON_TEXT_COL = _BUTTON_TEXT_COL;
 		}
 
-		Zui.fill(sys_width() - Main.minimap_w, 0, Main.minimap_w, Zui.ELEMENT_H(ui) + Zui.ELEMENT_OFFSET(ui) + 1, ui.t.SEPARATOR_COL);
-		Zui.fill(Main.storage.sidebar_w, 0, 1, sys_height(), ui.t.SEPARATOR_COL);
+		if (is_expanded) {
+			// ui.indent(false);
+			list_folder(abs);
+			// ui.unindent(false);
+		}
+	}
+}
 
-		let editor_updated = false;
+function render() {
+	storage.window_w = sys_width();
+	storage.window_h = sys_height();
+	storage.window_x = Krom.windowX();
+	storage.window_y = Krom.windowY();
+	if (ui.input_dx != 0 || ui.input_dy != 0) {
+		Krom.setMouseCursor(0); // Arrow
+	}
 
-		if (Zui.window(ui, Main.editor_handle, Main.storage.sidebar_w + 1, 0, sys_width() - Main.storage.sidebar_w - Main.minimap_w, sys_height(), false)) {
-			editor_updated = true;
-			let htab = Zui.handle("main_0", { position: 0 });
-			let file_name = Main.storage.file.substring(Main.storage.file.lastIndexOf("/") + 1);
-			let file_names = [file_name];
+	zui_begin(ui);
 
-			for (let file_name of file_names) {
-				if (Zui.tab(htab, file_name + (Main.storage.modified ? "*" : ""))) {
-					// File modified
-					if (ui.isKeyPressed) {
-						Main.storage.modified = true;
-					}
+	if (zui_window(sidebar_handle, 0, 0, storage.sidebar_w, sys_height(), false)) {
+		let _BUTTON_TEXT_COL = ui.t.BUTTON_TEXT_COL;
+		ui.t.BUTTON_TEXT_COL = ui.t.ACCENT_COL;
+		if (storage.project != "") {
+			list_folder(storage.project);
+		}
+		else {
+			zui_button("Drop folder here", Align.Left);
+		}
+		ui.t.BUTTON_TEXT_COL = _BUTTON_TEXT_COL;
+	}
 
-					// Save
-					if (ui.isCtrlDown && ui.key == KeyCode.S) {
-						Main.save_file();
-					}
+	zui_fill(sys_width() - minimap_w, 0, minimap_w, zui_ELEMENT_H(ui) + zui_ELEMENT_OFFSET(ui) + 1, ui.t.SEPARATOR_COL);
+	zui_fill(storage.sidebar_w, 0, 1, sys_height(), ui.t.SEPARATOR_COL);
+
+	let editor_updated = false;
 
-					Main.storage.text = Zui.textArea(Main.text_handle);
+	if (zui_window(editor_handle, storage.sidebar_w + 1, 0, sys_width() - storage.sidebar_w - minimap_w, sys_height(), false)) {
+		editor_updated = true;
+		let htab = zui_handle("main_0", { position: 0 });
+		let file_name = storage.file.substring(storage.file.lastIndexOf("/") + 1);
+		let file_names = [file_name];
+
+		for (let file_name of file_names) {
+			if (zui_tab(htab, file_name + (storage.modified ? "*" : ""))) {
+				// File modified
+				if (ui.is_key_pressed) {
+					storage.modified = true;
 				}
-			}
 
-			Main.window_header_h = 32;//Math.floor(ui.windowHeaderH);
-		}
+				// Save
+				if (ui.is_ctrl_down && ui.key == KeyCode.S) {
+					save_file();
+				}
 
-		if (Main.resizing_sidebar) {
-			Main.storage.sidebar_w += Math.floor(ui.inputDX);
-		}
-		if (!ui.inputDown) {
-			Main.resizing_sidebar = false;
+				storage.text = zui_text_area(text_handle);
+			}
 		}
 
-		// Minimap controls
-		let minimap_x = sys_width() - Main.minimap_w;
-		let minimap_y = Main.window_header_h + 1;
-		let redraw = false;
-		if (ui.inputStarted && Main.hit_test(ui.inputX, ui.inputY, minimap_x + 5, minimap_y, Main.minimap_w, Main.minimap_h)) {
-			Main.minimap_scrolling = true;
-		}
-		if (!ui.inputDown) {
-			Main.minimap_scrolling = false;
-		}
-		if (Main.minimap_scrolling) {
-			// Main.editor_handle.scrollOffset -= ui.inputDY * Zui.ELEMENT_H(ui) / 2;
-			// // Main.editor_handle.scrollOffset = -((ui.inputY - minimap_y - Main.minimap_box_h / 2) * Zui.ELEMENT_H(ui) / 2);
-			redraw = true;
-		}
+		window_header_h = 32;//Math.floor(ui.windowHeaderH);
+	}
 
-		// Build project
-		if (ui.isCtrlDown && ui.key == KeyCode.B) {
-			Main.save_file();
-			Main.build_project();
-		}
+	if (resizing_sidebar) {
+		storage.sidebar_w += Math.floor(ui.input_dx);
+	}
+	if (!ui.input_down) {
+		resizing_sidebar = false;
+	}
 
-		Zui.end();
+	// Minimap controls
+	let minimap_x = sys_width() - minimap_w;
+	let minimap_y = window_header_h + 1;
+	let redraw = false;
+	if (ui.input_started && hit_test(ui.input_x, ui.input_y, minimap_x + 5, minimap_y, minimap_w, minimap_h)) {
+		minimap_scrolling = true;
+	}
+	if (!ui.input_down) {
+		minimap_scrolling = false;
+	}
+	if (minimap_scrolling) {
+		// editor_handle.scroll_offset -= ui.input_dy * zui_ELEMENT_H(ui) / 2;
+		// // editor_handle.scroll_offset = -((ui.input_y - minimap_y - minimap_box_h / 2) * zui_ELEMENT_H(ui) / 2);
+		redraw = true;
+	}
 
-		if (redraw) {
-			Main.editor_handle.redraws = 2;
-		}
+	// Build project
+	if (ui.is_ctrl_down && ui.key == KeyCode.B) {
+		save_file();
+		build_project();
+	}
 
-		if (Main.minimap != null) {
-			Graphics2.begin(g2, false);
-			Graphics2.drawImage(Main.minimap, minimap_x, minimap_y);
-			Graphics2.end(g2);
-		}
+	zui_end();
 
-		if (editor_updated) {
-			Main.draw_minimap();
-		}
+	if (redraw) {
+		editor_handle.redraws = 2;
 	}
 
-	static save_file = () => {
-		// Trim
-		let lines = Main.storage.text.split("\n");
-		for (let i = 0; i < lines.length; ++i) lines[i] = trim_end(lines[i]);
-		Main.storage.text = lines.join("\n");
-		// Spaces to tabs
-		Main.storage.text = Main.storage.text.replaceAll("    ", "\t");
-		Main.text_handle.text = Main.storage.text;
-		// Write bytes
-		let bytes = Main.storage.file.endsWith(".arm") ? encode(JSON.parse(Main.storage.text)) : sys_string_to_buffer(Main.storage.text);
-		Krom.fileSaveBytes(Main.storage.file, bytes, bytes.byteLength);
-		Main.storage.modified = false;
+	if (minimap != null) {
+		g2_begin();
+		g2_draw_image(minimap, minimap_x, minimap_y);
+		g2_end();
 	}
 
-	static get build_file(): string {
-		///if krom_windows
-		return "\\build.bat";
-		///else
-		return "/build.sh";
-		///end
+	if (editor_updated) {
+		draw_minimap();
 	}
+}
 
-	static build_project = () => {
-		Krom.sysCommand(Main.storage.project + Main.build_file + " " + Main.storage.project);
+function save_file() {
+	// Trim
+	let lines = storage.text.split("\n");
+	for (let i = 0; i < lines.length; ++i) {
+		lines[i] = trim_end(lines[i]);
 	}
+	storage.text = lines.join("\n");
+	// Spaces to tabs
+	storage.text = storage.text.replaceAll("    ", "\t");
+	text_handle.text = storage.text;
+	// Write bytes
+	let bytes = storage.file.endsWith(".arm") ? armpack_encode(JSON.parse(storage.text)) : sys_string_to_buffer(storage.text);
+	Krom.fileSaveBytes(storage.file, bytes, bytes.byteLength);
+	storage.modified = false;
+}
 
-	static draw_minimap = () => {
-		let ui = Main.ui;
-		if (Main.minimap_h != sys_height()) {
-			Main.minimap_h = sys_height();
-			if (Main.minimap != null) image_unload(Main.minimap);
-			Main.minimap = image_create_render_target(Main.minimap_w, Main.minimap_h);
-		}
+function build_file(): string {
+	///if krom_windows
+	return "\\build.bat";
+	///else
+	return "/build.sh";
+	///end
+}
 
-		Graphics2.begin(Main.minimap.g2, true, ui.t.SEPARATOR_COL);
-		Main.minimap.g2.color = 0xff333333;
-		let lines = Main.storage.text.split("\n");
-		let minimap_full_h = lines.length * 2;
-		let scrollProgress = -Main.editor_handle.scrollOffset / (lines.length * Zui.ELEMENT_H(ui));
-		let outOfScreen = minimap_full_h - Main.minimap_h;
-		if (outOfScreen < 0) outOfScreen = 0;
-		let offset = Math.floor((outOfScreen * scrollProgress) / 2);
-
-		for (let i = 0; i < lines.length; ++i) {
-			if (i * 2 > Main.minimap_h || i + offset >= lines.length) {
-				// Out of screen
-				break;
-			}
-			let words = lines[i + offset].split(" ");
-			let x = 0;
-			for (let j = 0; j < words.length; ++j) {
-				let word = words[j];
-				Graphics2.fillRect(x, i * 2, word.length, 2);
-				x += word.length + 1;
-			}
+function build_project() {
+	Krom.sysCommand(storage.project + build_file() + " " + storage.project);
+}
+
+function draw_minimap() {
+	if (minimap_h != sys_height()) {
+		minimap_h = sys_height();
+		if (minimap != null) {
+			image_unload(minimap);
 		}
+		minimap = image_create_render_target(minimap_w, minimap_h);
+	}
 
-		// Current position
-		let visibleArea = outOfScreen > 0 ? Main.minimap_h : minimap_full_h;
-		Main.minimap.g2.color = 0x11ffffff;
-		Main.minimap_box_h = Math.floor((sys_height() - Main.window_header_h) / Zui.ELEMENT_H(ui) * 2);
-		Graphics2.fillRect(0, scrollProgress * visibleArea, Main.minimap_w, Main.minimap_box_h);
-		Graphics2.end(Main.minimap.g2);
+	g2_begin(minimap, true, ui.t.SEPARATOR_COL);
+	g2_set_color(0xff333333);
+	let lines = storage.text.split("\n");
+	let minimap_full_h = lines.length * 2;
+	let scrollProgress = -editor_handle.scroll_offset / (lines.length * zui_ELEMENT_H(ui));
+	let out_of_screen = minimap_full_h - minimap_h;
+	if (out_of_screen < 0) {
+		out_of_screen = 0;
 	}
+	let offset = Math.floor((out_of_screen * scrollProgress) / 2);
 
-	static hit_test = (mx: f32, my: f32, x: f32, y: f32, w: f32, h: f32): bool => {
-		return mx > x && mx < x + w && my > y && my < y + h;
+	for (let i = 0; i < lines.length; ++i) {
+		if (i * 2 > minimap_h || i + offset >= lines.length) {
+			// Out of screen
+			break;
+		}
+		let words = lines[i + offset].split(" ");
+		let x = 0;
+		for (let j = 0; j < words.length; ++j) {
+			let word = words[j];
+			g2_fill_rect(x, i * 2, word.length, 2);
+			x += word.length + 1;
+		}
 	}
 
-	static on_border_hover = (handle: Handle, side: i32) => {
-		if (handle != Main.sidebar_handle) return;
-		if (side != 1) return; // Right
+	// Current position
+	let visible_area = out_of_screen > 0 ? minimap_h : minimap_full_h;
+	g2_set_color(0x11ffffff);
+	minimap_box_h = Math.floor((sys_height() - window_header_h) / zui_ELEMENT_H(ui) * 2);
+	g2_fill_rect(0, scrollProgress * visible_area, minimap_w, minimap_box_h);
+	g2_end();
+}
 
-		Krom.setMouseCursor(3); // Horizontal
+function hit_test(mx: f32, my: f32, x: f32, y: f32, w: f32, h: f32): bool {
+	return mx > x && mx < x + w && my > y && my < y + h;
+}
 
-		if (Zui.current.inputStarted) {
-			Main.resizing_sidebar = true;
-		}
+function on_border_hover(handle: zui_handle_t, side: i32) {
+	if (handle != sidebar_handle) {
+		return;
 	}
+	if (side != 1) {
+		return; // Right
+	}
+
+	Krom.setMouseCursor(3); // Horizontal
 
-	static on_text_hover = () => {
-		Krom.setMouseCursor(2); // I-cursor
+	if (zui_current.input_started) {
+		resizing_sidebar = true;
 	}
 }
 
-Main.main();
+function on_text_hover() {
+	Krom.setMouseCursor(2); // I-cursor
+}
+
+main();