瀏覽代碼

Prepare iron to c port

luboslenco 1 年之前
父節點
當前提交
e80509c4f6
共有 71 個文件被更改,包括 1184 次插入1190 次删除
  1. 4 4
      armorforge/Sources/TabObjects.ts
  2. 30 34
      armorlab/Sources/RenderPathPaint.ts
  3. 26 26
      armorlab/Sources/UINodesExt.ts
  4. 11 11
      armorlab/Sources/nodes/BrushOutputNode.ts
  5. 4 4
      armorlab/Sources/nodes/ImageTextureNode.ts
  6. 34 34
      armorlab/Sources/nodes/InpaintNode.ts
  7. 21 21
      armorlab/Sources/nodes/PhotoToPBRNode.ts
  8. 5 5
      armorlab/Sources/nodes/RGBNode.ts
  9. 8 8
      armorlab/Sources/nodes/TextToPhotoNode.ts
  10. 16 16
      armorlab/Sources/nodes/TilingNode.ts
  11. 29 29
      armorlab/Sources/nodes/UpscaleNode.ts
  12. 10 10
      armorlab/Sources/nodes/VarianceNode.ts
  13. 9 9
      armorpaint/Sources/MakeMaterial.ts
  14. 41 41
      armorpaint/Sources/RenderPathPaint.ts
  15. 6 6
      armorpaint/Sources/RenderPathPreview.ts
  16. 2 2
      armorpaint/Sources/SlotBrush.ts
  17. 3 3
      armorpaint/Sources/SlotFont.ts
  18. 60 60
      armorpaint/Sources/SlotLayer.ts
  19. 4 4
      armorpaint/Sources/SlotMaterial.ts
  20. 9 9
      armorpaint/Sources/TabLayers.ts
  21. 1 1
      armorsculpt/Sources/ExportObj.ts
  22. 3 3
      armorsculpt/Sources/ImportMesh.ts
  23. 5 5
      armorsculpt/Sources/MakeMaterial.ts
  24. 319 319
      base/Sources/Base.ts
  25. 2 2
      base/Sources/BoxPreferences.ts
  26. 5 5
      base/Sources/BoxProjects.ts
  27. 2 2
      base/Sources/Config.ts
  28. 7 7
      base/Sources/Console.ts
  29. 2 2
      base/Sources/Context.ts
  30. 12 12
      base/Sources/ContextFormat.ts
  31. 19 19
      base/Sources/ExportArm.ts
  32. 55 55
      base/Sources/ExportTexture.ts
  33. 25 25
      base/Sources/ImportArm.ts
  34. 29 29
      base/Sources/ImportEnvmap.ts
  35. 4 4
      base/Sources/ImportFont.ts
  36. 3 3
      base/Sources/ImportTexture.ts
  37. 22 22
      base/Sources/LineDraw.ts
  38. 3 3
      base/Sources/LogicNode.ts
  39. 9 9
      base/Sources/MakeVoxel.ts
  40. 1 1
      base/Sources/Path.ts
  41. 9 9
      base/Sources/Project.ts
  42. 17 17
      base/Sources/RenderPathBase.ts
  43. 16 18
      base/Sources/RenderPathDeferred.ts
  44. 4 4
      base/Sources/RenderPathRaytrace.ts
  45. 7 7
      base/Sources/RenderPathRaytraceBake.ts
  46. 7 7
      base/Sources/Res.ts
  47. 1 1
      base/Sources/TabConsole.ts
  48. 6 6
      base/Sources/TabMaterials.ts
  49. 1 1
      base/Sources/TabScript.ts
  50. 3 3
      base/Sources/TabSwatches.ts
  51. 5 5
      base/Sources/TabTextures.ts
  52. 2 2
      base/Sources/Translator.ts
  53. 29 29
      base/Sources/UIBase.ts
  54. 8 8
      base/Sources/UIBox.ts
  55. 15 15
      base/Sources/UIFiles.ts
  56. 15 15
      base/Sources/UIHeader.ts
  57. 15 15
      base/Sources/UIMenu.ts
  58. 1 1
      base/Sources/UIMenubar.ts
  59. 16 16
      base/Sources/UINodes.ts
  60. 3 3
      base/Sources/UIStatus.ts
  61. 3 3
      base/Sources/UIToolbar.ts
  62. 34 34
      base/Sources/UIView2D.ts
  63. 1 1
      base/Sources/UniformsExt.ts
  64. 17 17
      base/Sources/UtilMesh.ts
  65. 1 1
      base/Sources/UtilParticle.ts
  66. 42 42
      base/Sources/UtilRender.ts
  67. 34 34
      base/Sources/UtilUV.ts
  68. 3 3
      base/Sources/nodes/ColorNode.ts
  69. 3 3
      base/Sources/nodes/FloatNode.ts
  70. 3 3
      base/Sources/nodes/VectorNode.ts
  71. 3 3
      misc/pad/Sources/main.ts

+ 4 - 4
armorforge/Sources/TabObjects.ts

@@ -35,14 +35,14 @@ class TabObjects {
 					// Highlight every other line
 					if (lineCounter % 2 == 0) {
 						ui.g.color = ui.t.SEPARATOR_COL;
-						ui.g.fillRect(0, ui._y, ui._windowW, ui.ELEMENT_H());
+						Graphics2.fillRect(0, ui._y, ui._windowW, ui.ELEMENT_H());
 						ui.g.color = 0xffffffff;
 					}
 
 					// Highlight selected line
 					if (currentObject == Context.raw.selectedObject) {
 						ui.g.color = 0xff205d9c;
-						ui.g.fillRect(0, ui._y, ui._windowW, ui.ELEMENT_H());
+						Graphics2.fillRect(0, ui._y, ui._windowW, ui.ELEMENT_H());
 						ui.g.color = 0xffffffff;
 					}
 
@@ -56,7 +56,7 @@ class TabObjects {
 
 						// Draw line that shows parent relations
 						ui.g.color = ui.t.ACCENT_COL;
-						ui.g.drawLine(ui._x - 10, ui._y + ui.ELEMENT_H() / 2, ui._x, ui._y + ui.ELEMENT_H() / 2);
+						Graphics2.drawLine(ui._x - 10, ui._y + ui.ELEMENT_H() / 2, ui._x, ui._y + ui.ELEMENT_H() / 2);
 						ui.g.color = 0xffffffff;
 
 						ui.text(currentObject.name);
@@ -114,7 +114,7 @@ class TabObjects {
 
 						// Draw line that shows parent relations
 						ui.g.color = ui.t.ACCENT_COL;
-						ui.g.drawLine(ui._x + 14, currentY, ui._x + 14, ui._y - ui.ELEMENT_H() / 2);
+						Graphics2.drawLine(ui._x + 14, currentY, ui._x + 14, ui._y - ui.ELEMENT_H() / 2);
 						ui.g.color = 0xffffffff;
 					}
 				}

+ 30 - 34
armorlab/Sources/RenderPathPaint.ts

@@ -6,7 +6,7 @@ class RenderPathPaint {
 	static init = () => {
 
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texpaint_blend0";
 			t.width = Config.getTextureResX();
 			t.height = Config.getTextureResY();
@@ -14,7 +14,7 @@ class RenderPathPaint {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texpaint_blend1";
 			t.width = Config.getTextureResX();
 			t.height = Config.getTextureResY();
@@ -22,7 +22,7 @@ class RenderPathPaint {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texpaint_picker";
 			t.width = 1;
 			t.height = 1;
@@ -30,7 +30,7 @@ class RenderPathPaint {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texpaint_nor_picker";
 			t.width = 1;
 			t.height = 1;
@@ -38,7 +38,7 @@ class RenderPathPaint {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texpaint_pack_picker";
 			t.width = 1;
 			t.height = 1;
@@ -46,7 +46,7 @@ class RenderPathPaint {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texpaint_uv_picker";
 			t.width = 1;
 			t.height = 1;
@@ -88,10 +88,10 @@ class RenderPathPaint {
 					let texpaint_nor_picker = RenderPath.renderTargets.get("texpaint_nor_picker").image;
 					let texpaint_pack_picker = RenderPath.renderTargets.get("texpaint_pack_picker").image;
 					let texpaint_uv_picker = RenderPath.renderTargets.get("texpaint_uv_picker").image;
-					let a = texpaint_picker.getPixels();
-					let b = texpaint_nor_picker.getPixels();
-					let c = texpaint_pack_picker.getPixels();
-					let d = texpaint_uv_picker.getPixels();
+					let a = Image.getPixels(texpaint_picker);
+					let b = Image.getPixels(texpaint_nor_picker);
+					let c = Image.getPixels(texpaint_pack_picker);
+					let d = Image.getPixels(texpaint_uv_picker);
 
 					if (Context.raw.colorPickerCallback != null) {
 						Context.raw.colorPickerCallback(Context.raw.pickedColor);
@@ -184,35 +184,33 @@ class RenderPathPaint {
 	static drawCursor = (mx: f32, my: f32, radius: f32, tintR = 1.0, tintG = 1.0, tintB = 1.0) => {
 		let plane = Scene.getChild(".Plane").ext;
 		let geom = plane.data;
-
-		let g = RenderPath.frameG;
 		if (Base.pipeCursor == null) Base.makeCursorPipe();
 
 		RenderPath.setTarget("");
-		g.setPipeline(Base.pipeCursor);
+		Graphics4.setPipeline(Base.pipeCursor);
 		let img = Res.get("cursor.k");
-		g.setTexture(Base.cursorTex, img);
+		Graphics4.setTexture(Base.cursorTex, img);
 		let gbuffer0 = RenderPath.renderTargets.get("gbuffer0").image;
-		g.setTextureDepth(Base.cursorGbufferD, gbuffer0);
-		g.setFloat2(Base.cursorMouse, mx, my);
-		g.setFloat2(Base.cursorTexStep, 1 / gbuffer0.width, 1 / gbuffer0.height);
-		g.setFloat(Base.cursorRadius, radius);
+		Graphics4.setTextureDepth(Base.cursorGbufferD, gbuffer0);
+		Graphics4.setFloat2(Base.cursorMouse, mx, my);
+		Graphics4.setFloat2(Base.cursorTexStep, 1 / gbuffer0.width, 1 / gbuffer0.height);
+		Graphics4.setFloat(Base.cursorRadius, radius);
 		let right = Vec4.normalize(CameraObject.rightWorld(Scene.camera));
-		g.setFloat3(Base.cursorCameraRight, right.x, right.y, right.z);
-		g.setFloat3(Base.cursorTint, tintR, tintG, tintB);
-		g.setMatrix(Base.cursorVP, Scene.camera.VP);
+		Graphics4.setFloat3(Base.cursorCameraRight, right.x, right.y, right.z);
+		Graphics4.setFloat3(Base.cursorTint, tintR, tintG, tintB);
+		Graphics4.setMatrix(Base.cursorVP, Scene.camera.VP);
 		let helpMat = Mat4.identity();
 		Mat4.getInverse(helpMat, Scene.camera.VP);
-		g.setMatrix(Base.cursorInvVP, helpMat);
+		Graphics4.setMatrix(Base.cursorInvVP, helpMat);
 		///if (krom_metal || krom_vulkan)
-		g.setVertexBuffer(MeshData.get(geom, [{name: "tex", data: "short2norm"}]));
+		Graphics4.setVertexBuffer(MeshData.get(geom, [{name: "tex", data: "short2norm"}]));
 		///else
-		g.setVertexBuffer(geom._vertexBuffer);
+		Graphics4.setVertexBuffer(geom._vertexBuffer);
 		///end
-		g.setIndexBuffer(geom._indexBuffers[0]);
-		g.drawIndexedVertices();
+		Graphics4.setIndexBuffer(geom._indexBuffers[0]);
+		Graphics4.drawIndexedVertices();
 
-		g.disableScissor();
+		Graphics4.disableScissor();
 		RenderPath.end();
 	}
 
@@ -253,7 +251,7 @@ class RenderPathPaint {
 	}
 
 	static bindLayers = () => {
-		let image: Image = null;
+		let image: ImageRaw = null;
 		let nodes = UINodes.getNodes();
 		let canvas = UINodes.getCanvas(true);
 		if (nodes.nodesSelectedId.length > 0) {
@@ -265,22 +263,20 @@ class RenderPathPaint {
 		}
 		if (image != null) {
 			if (RenderPath.renderTargets.get("texpaint_node") == null) {
-				let t = new RenderTargetRaw();
+				let t = RenderTarget.create();
 				t.name = "texpaint_node";
 				t.width = Config.getTextureResX();
 				t.height = Config.getTextureResY();
 				t.format = "RGBA32";
-				let rt = new RenderTarget(t);
-				RenderPath.renderTargets.set(t.name, rt);
+				RenderPath.renderTargets.set(t.name, t);
 			}
 			if (RenderPath.renderTargets.get("texpaint_node_target") == null) {
-				let t = new RenderTargetRaw();
+				let t = RenderTarget.create();
 				t.name = "texpaint_node_target";
 				t.width = Config.getTextureResX();
 				t.height = Config.getTextureResY();
 				t.format = "RGBA32";
-				let rt = new RenderTarget(t);
-				RenderPath.renderTargets.set(t.name, rt);
+				RenderPath.renderTargets.set(t.name, t);
 			}
 			RenderPath.renderTargets.get("texpaint_node").image = image;
 			RenderPath.bindTarget("texpaint_node", "texpaint");

+ 26 - 26
armorlab/Sources/UINodesExt.ts

@@ -33,24 +33,24 @@ class UINodesExt {
 				ParserLogic.parse(Project.canvas);
 
 				PhotoToPBRNode.cachedSource = null;
-				BrushOutputNode.inst.getAsImage(ChannelType.ChannelBaseColor, (texbase: Image) => {
-				BrushOutputNode.inst.getAsImage(ChannelType.ChannelOcclusion, (texocc: Image) => {
-				BrushOutputNode.inst.getAsImage(ChannelType.ChannelRoughness, (texrough: Image) => {
-				BrushOutputNode.inst.getAsImage(ChannelType.ChannelNormalMap, (texnor: Image) => {
-				BrushOutputNode.inst.getAsImage(ChannelType.ChannelHeight, (texheight: Image) => {
+				BrushOutputNode.inst.getAsImage(ChannelType.ChannelBaseColor, (texbase: ImageRaw) => {
+				BrushOutputNode.inst.getAsImage(ChannelType.ChannelOcclusion, (texocc: ImageRaw) => {
+				BrushOutputNode.inst.getAsImage(ChannelType.ChannelRoughness, (texrough: ImageRaw) => {
+				BrushOutputNode.inst.getAsImage(ChannelType.ChannelNormalMap, (texnor: ImageRaw) => {
+				BrushOutputNode.inst.getAsImage(ChannelType.ChannelHeight, (texheight: ImageRaw) => {
 
 					if (texbase != null) {
 						let texpaint = RenderPath.renderTargets.get("texpaint").image;
-						texpaint.g2.begin(false);
-						texpaint.g2.drawScaledImage(texbase, 0, 0, Config.getTextureResX(), Config.getTextureResY());
-						texpaint.g2.end();
+						Graphics2.begin(texpaint.g2, false);
+						Graphics2.drawScaledImage(texbase, 0, 0, Config.getTextureResX(), Config.getTextureResY());
+						Graphics2.end(texpaint.g2);
 					}
 
 					if (texnor != null) {
 						let texpaint_nor = RenderPath.renderTargets.get("texpaint_nor").image;
-						texpaint_nor.g2.begin(false);
-						texpaint_nor.g2.drawScaledImage(texnor, 0, 0, Config.getTextureResX(), Config.getTextureResY());
-						texpaint_nor.g2.end();
+						Graphics2.begin(texpaint_nor.g2, false);
+						Graphics2.drawScaledImage(texnor, 0, 0, Config.getTextureResX(), Config.getTextureResY());
+						Graphics2.end(texpaint_nor.g2);
 					}
 
 					if (Base.pipeCopy == null) Base.makePipe();
@@ -60,29 +60,29 @@ class UINodesExt {
 					let texpaint_pack = RenderPath.renderTargets.get("texpaint_pack").image;
 
 					if (texocc != null) {
-						texpaint_pack.g2.begin(false);
+						Graphics2.begin(texpaint_pack.g2, false);
 						texpaint_pack.g2.pipeline = Base.pipeCopyR;
-						texpaint_pack.g2.drawScaledImage(texocc, 0, 0, Config.getTextureResX(), Config.getTextureResY());
+						Graphics2.drawScaledImage(texocc, 0, 0, Config.getTextureResX(), Config.getTextureResY());
 						texpaint_pack.g2.pipeline = null;
-						texpaint_pack.g2.end();
+						Graphics2.end(texpaint_pack.g2);
 					}
 
 					if (texrough != null) {
-						texpaint_pack.g2.begin(false);
+						Graphics2.begin(texpaint_pack.g2, false);
 						texpaint_pack.g2.pipeline = Base.pipeCopyG;
-						texpaint_pack.g2.drawScaledImage(texrough, 0, 0, Config.getTextureResX(), Config.getTextureResY());
+						Graphics2.drawScaledImage(texrough, 0, 0, Config.getTextureResX(), Config.getTextureResY());
 						texpaint_pack.g2.pipeline = null;
-						texpaint_pack.g2.end();
+						Graphics2.end(texpaint_pack.g2);
 					}
 
 					if (texheight != null) {
-						texpaint_pack.g4.begin();
-						texpaint_pack.g4.setPipeline(Base.pipeCopyA);
-						texpaint_pack.g4.setTexture(Base.pipeCopyATex, texheight);
-						texpaint_pack.g4.setVertexBuffer(ConstData.screenAlignedVB);
-						texpaint_pack.g4.setIndexBuffer(ConstData.screenAlignedIB);
-						texpaint_pack.g4.drawIndexedVertices();
-						texpaint_pack.g4.end();
+						Graphics4.begin(texpaint_pack.g4);
+						Graphics4.setPipeline(Base.pipeCopyA);
+						Graphics4.setTexture(Base.pipeCopyATex, texheight);
+						Graphics4.setVertexBuffer(ConstData.screenAlignedVB);
+						Graphics4.setIndexBuffer(ConstData.screenAlignedIB);
+						Graphics4.drawIndexedVertices();
+						Graphics4.end();
 
 						if (UIHeader.worktab.position == SpaceType.Space3D &&
 							BrushOutputNode.inst.inputs[ChannelType.ChannelHeight].node.constructor != FloatNode) {
@@ -90,7 +90,7 @@ class UINodesExt {
 							// Make copy of vertices before displacement
 							let o = Project.paintObjects[0];
 							let g = o.data;
-							let vertices = g._vertexBuffer.lock();
+							let vertices = VertexBuffer.lock(g._vertexBuffer);
 							if (UINodesExt.lastVertices == null || UINodesExt.lastVertices.byteLength != vertices.byteLength) {
 								UINodesExt.lastVertices = new DataView(new ArrayBuffer(vertices.byteLength));
 								for (let i = 0; i < Math.floor(vertices.byteLength / 2); ++i) {
@@ -102,7 +102,7 @@ class UINodesExt {
 									vertices.setInt16(i * 2, UINodesExt.lastVertices.getInt16(i * 2, true), true);
 								}
 							}
-							g._vertexBuffer.unlock();
+							VertexBuffer.unlock(g._vertexBuffer);
 
 							// Apply displacement
 							if (Config.raw.displace_strength > 0) {

+ 11 - 11
armorlab/Sources/nodes/BrushOutputNode.ts

@@ -2,11 +2,11 @@
 class BrushOutputNode extends LogicNode {
 
 	id = 0;
-	texpaint: Image = null;
-	texpaint_nor: Image = null;
-	texpaint_pack: Image = null;
-	texpaint_nor_empty: Image = null;
-	texpaint_pack_empty: Image = null;
+	texpaint: ImageRaw = null;
+	texpaint_nor: ImageRaw = null;
+	texpaint_pack: ImageRaw = null;
+	texpaint_nor_empty: ImageRaw = null;
+	texpaint_pack_empty: ImageRaw = null;
 
 	static inst: BrushOutputNode = null;
 
@@ -15,7 +15,7 @@ class BrushOutputNode extends LogicNode {
 
 		if (BrushOutputNode.inst == null) {
 			{
-				let t = new RenderTargetRaw();
+				let t = RenderTarget.create();
 				t.name = "texpaint";
 				t.width = Config.getTextureResX();
 				t.height = Config.getTextureResY();
@@ -23,7 +23,7 @@ class BrushOutputNode extends LogicNode {
 				this.texpaint = RenderPath.createRenderTarget(t).image;
 			}
 			{
-				let t = new RenderTargetRaw();
+				let t = RenderTarget.create();
 				t.name = "texpaint_nor";
 				t.width = Config.getTextureResX();
 				t.height = Config.getTextureResY();
@@ -31,7 +31,7 @@ class BrushOutputNode extends LogicNode {
 				this.texpaint_nor = RenderPath.createRenderTarget(t).image;
 			}
 			{
-				let t = new RenderTargetRaw();
+				let t = RenderTarget.create();
 				t.name = "texpaint_pack";
 				t.width = Config.getTextureResX();
 				t.height = Config.getTextureResY();
@@ -39,7 +39,7 @@ class BrushOutputNode extends LogicNode {
 				this.texpaint_pack = RenderPath.createRenderTarget(t).image;
 			}
 			{
-				let t = new RenderTargetRaw();
+				let t = RenderTarget.create();
 				t.name = "texpaint_nor_empty";
 				t.width = 1;
 				t.height = 1;
@@ -47,7 +47,7 @@ class BrushOutputNode extends LogicNode {
 				this.texpaint_nor_empty = RenderPath.createRenderTarget(t).image;
 			}
 			{
-				let t = new RenderTargetRaw();
+				let t = RenderTarget.create();
 				t.name = "texpaint_pack_empty";
 				t.width = 1;
 				t.height = 1;
@@ -64,7 +64,7 @@ class BrushOutputNode extends LogicNode {
 		BrushOutputNode.inst = this;
 	}
 
-	override getAsImage = (from: i32, done: (img: Image)=>void) => {
+	override getAsImage = (from: i32, done: (img: ImageRaw)=>void) => {
 		this.inputs[from].getAsImage(done);
 	}
 }

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

@@ -8,15 +8,15 @@ class ImageTextureNode extends LogicNode {
 		super();
 	}
 
-	override getAsImage = (from: i32, done: (img: Image)=>void) => {
+	override getAsImage = (from: i32, done: (img: ImageRaw)=>void) => {
 		let index = Project.assetNames.indexOf(this.file);
 		let asset = Project.assets[index];
 		done(Project.getImage(asset));
 	}
 
-	override getCachedImage = (): Image => {
-		let image: Image;
-		this.getAsImage(0, (img: Image) => { image = img; });
+	override getCachedImage = (): ImageRaw => {
+		let image: ImageRaw;
+		this.getAsImage(0, (img: ImageRaw) => { image = img; });
 		return image;
 	}
 

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

@@ -3,11 +3,11 @@ declare let Krom_texsynth: any;
 
 class InpaintNode extends LogicNode {
 
-	static image: Image = null;
-	static mask: Image = null;
-	static result: Image = null;
+	static image: ImageRaw = null;
+	static mask: ImageRaw = null;
+	static result: ImageRaw = null;
 
-	static temp: Image = null;
+	static temp: ImageRaw = null;
 	static prompt = "";
 	static strength = 0.5;
 	static auto = true;
@@ -25,9 +25,9 @@ class InpaintNode extends LogicNode {
 		if (InpaintNode.mask == null) {
 			InpaintNode.mask = Image.createRenderTarget(Config.getTextureResX(), Config.getTextureResY(), TextureFormat.R8);
 			Base.notifyOnNextFrame(() => {
-				InpaintNode.mask.g4.begin();
-				InpaintNode.mask.g4.clear(color_from_floats(1.0, 1.0, 1.0, 1.0));
-				InpaintNode.mask.g4.end();
+				Graphics4.begin(InpaintNode.mask.g4);
+				Graphics4.clear(color_from_floats(1.0, 1.0, 1.0, 1.0));
+				Graphics4.end();
 			});
 		}
 
@@ -50,48 +50,48 @@ class InpaintNode extends LogicNode {
 		else node.buttons[1].height = 0;
 	}
 
-	override getAsImage = (from: i32, done: (img: Image)=>void) => {
-		this.inputs[0].getAsImage((source: Image) => {
+	override getAsImage = (from: i32, done: (img: ImageRaw)=>void) => {
+		this.inputs[0].getAsImage((source: ImageRaw) => {
 
 			Console.progress(tr("Processing") + " - " + tr("Inpaint"));
 			Base.notifyOnNextFrame(() => {
-				InpaintNode.image.g2.begin(false);
-				InpaintNode.image.g2.drawScaledImage(source, 0, 0, Config.getTextureResX(), Config.getTextureResY());
-				InpaintNode.image.g2.end();
+				Graphics2.begin(InpaintNode.image.g2, false);
+				Graphics2.drawScaledImage(source, 0, 0, Config.getTextureResX(), Config.getTextureResY());
+				Graphics2.end(InpaintNode.image.g2);
 
 				InpaintNode.auto ? InpaintNode.texsynthInpaint(InpaintNode.image, false, InpaintNode.mask, done) : InpaintNode.sdInpaint(InpaintNode.image, InpaintNode.mask, done);
 			});
 		});
 	}
 
-	override getCachedImage = (): Image => {
+	override getCachedImage = (): ImageRaw => {
 		Base.notifyOnNextFrame(() => {
-			this.inputs[0].getAsImage((source: Image) => {
+			this.inputs[0].getAsImage((source: ImageRaw) => {
 				if (Base.pipeCopy == null) Base.makePipe();
 				if (ConstData.screenAlignedVB == null) ConstData.createScreenAlignedData();
-				InpaintNode.image.g4.begin();
-				InpaintNode.image.g4.setPipeline(Base.pipeInpaintPreview);
-				InpaintNode.image.g4.setTexture(Base.tex0InpaintPreview, source);
-				InpaintNode.image.g4.setTexture(Base.texaInpaintPreview, InpaintNode.mask);
-				InpaintNode.image.g4.setVertexBuffer(ConstData.screenAlignedVB);
-				InpaintNode.image.g4.setIndexBuffer(ConstData.screenAlignedIB);
-				InpaintNode.image.g4.drawIndexedVertices();
-				InpaintNode.image.g4.end();
+				Graphics4.begin(InpaintNode.image.g4);
+				Graphics4.setPipeline(Base.pipeInpaintPreview);
+				Graphics4.setTexture(Base.tex0InpaintPreview, source);
+				Graphics4.setTexture(Base.texaInpaintPreview, InpaintNode.mask);
+				Graphics4.setVertexBuffer(ConstData.screenAlignedVB);
+				Graphics4.setIndexBuffer(ConstData.screenAlignedIB);
+				Graphics4.drawIndexedVertices();
+				Graphics4.end();
 			});
 		});
 		return InpaintNode.image;
 	}
 
-	getTarget = (): Image => {
+	getTarget = (): ImageRaw => {
 		return InpaintNode.mask;
 	}
 
-	static texsynthInpaint = (image: Image, tiling: bool, mask: Image/* = null*/, done: (img: Image)=>void) => {
+	static texsynthInpaint = (image: ImageRaw, tiling: bool, mask: ImageRaw/* = null*/, done: (img: ImageRaw)=>void) => {
 		let w = Config.getTextureResX();
 		let h = Config.getTextureResY();
 
-		let bytes_img = image.getPixels();
-		let bytes_mask = mask != null ? mask.getPixels() : new ArrayBuffer(w * h);
+		let bytes_img = Image.getPixels(image);
+		let bytes_mask = mask != null ? Image.getPixels(mask) : new ArrayBuffer(w * h);
 		let bytes_out = new ArrayBuffer(w * h * 4);
 		Krom_texsynth.inpaint(w, h, bytes_out, bytes_img, bytes_mask, tiling);
 
@@ -99,10 +99,10 @@ class InpaintNode extends LogicNode {
 		done(InpaintNode.result);
 	}
 
-	static sdInpaint = (image: Image, mask: Image, done: (img: Image)=>void) => {
+	static sdInpaint = (image: ImageRaw, mask: ImageRaw, done: (img: ImageRaw)=>void) => {
 		InpaintNode.init();
 
-		let bytes_img = mask.getPixels();
+		let bytes_img = Image.getPixels(mask);
 		let u8 = new Uint8Array(bytes_img);
 		let f32mask = new Float32Array(4 * 64 * 64);
 
@@ -127,12 +127,12 @@ class InpaintNode extends LogicNode {
 						}
 					}
 
-					InpaintNode.temp.g2.begin(false);
-					// InpaintNode.temp.g2.drawImage(image, -x * 512, -y * 512);
-					InpaintNode.temp.g2.drawScaledImage(image, 0, 0, 512, 512);
-					InpaintNode.temp.g2.end();
+					Graphics2.begin(InpaintNode.temp.g2, false);
+					// Graphics2.drawImage(image, -x * 512, -y * 512);
+					Graphics2.drawScaledImage(image, 0, 0, 512, 512);
+					Graphics2.end(InpaintNode.temp.g2);
 
-					let bytes_img = InpaintNode.temp.getPixels();
+					let bytes_img = Image.getPixels(InpaintNode.temp);
 					let u8a = new Uint8Array(bytes_img);
 					let f32a = new Float32Array(3 * 512 * 512);
 					for (let i = 0; i < (512 * 512); ++i) {
@@ -163,7 +163,7 @@ class InpaintNode extends LogicNode {
 
 					let start = num_inference_steps - init_timestep;
 
-					TextToPhotoNode.stableDiffusion(InpaintNode.prompt, (img: Image) => {
+					TextToPhotoNode.stableDiffusion(InpaintNode.prompt, (img: ImageRaw) => {
 						// result.g2.begin(false);
 						// result.g2.drawImage(img, x * 512, y * 512);
 						// result.g2.end();

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

@@ -1,11 +1,11 @@
 
 class PhotoToPBRNode extends LogicNode {
 
-	static temp: Image = null;
-	static images: Image[] = null;
+	static temp: ImageRaw = null;
+	static images: ImageRaw[] = null;
 	static modelNames = ["base", "occlusion", "roughness", "metallic", "normal", "height"];
 
-	static cachedSource: Image = null;
+	static cachedSource: ImageRaw = null;
 	static borderW = 64;
 	static tileW = 2048;
 	static tileWithBorderW = PhotoToPBRNode.tileW + PhotoToPBRNode.borderW * 2;
@@ -29,13 +29,13 @@ class PhotoToPBRNode extends LogicNode {
 		}
 	}
 
-	override getAsImage = (from: i32, done: (img: Image)=>void) => {
-		let getSource = (done: (img: Image)=>void) => {
+	override getAsImage = (from: i32, done: (img: ImageRaw)=>void) => {
+		let getSource = (done: (img: ImageRaw)=>void) => {
 			if (PhotoToPBRNode.cachedSource != null) done(PhotoToPBRNode.cachedSource);
 			else this.inputs[0].getAsImage(done);
 		}
 
-		getSource((source: Image) => {
+		getSource((source: ImageRaw) => {
 			PhotoToPBRNode.cachedSource = source;
 
 			Console.progress(tr("Processing") + " - " + tr("Photo to PBR"));
@@ -48,17 +48,17 @@ class PhotoToPBRNode extends LogicNode {
 					let x = i % tilesX;
 					let y = Math.floor(i / tilesX);
 
-					PhotoToPBRNode.temp.g2.begin(false);
-					PhotoToPBRNode.temp.g2.drawScaledImage(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW, -Config.getTextureResX(), Config.getTextureResY());
-					PhotoToPBRNode.temp.g2.drawScaledImage(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW, Config.getTextureResX(), -Config.getTextureResY());
-					PhotoToPBRNode.temp.g2.drawScaledImage(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW, -Config.getTextureResX(), -Config.getTextureResY());
-					PhotoToPBRNode.temp.g2.drawScaledImage(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW + PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW + PhotoToPBRNode.tileW, Config.getTextureResX(), Config.getTextureResY());
-					PhotoToPBRNode.temp.g2.drawScaledImage(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW + PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW + PhotoToPBRNode.tileW, -Config.getTextureResX(), Config.getTextureResY());
-					PhotoToPBRNode.temp.g2.drawScaledImage(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW + PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW + PhotoToPBRNode.tileW, Config.getTextureResX(), -Config.getTextureResY());
-					PhotoToPBRNode.temp.g2.drawScaledImage(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW, Config.getTextureResX(), Config.getTextureResY());
-					PhotoToPBRNode.temp.g2.end();
-
-					let bytes_img = PhotoToPBRNode.temp.getPixels();
+					Graphics2.begin(PhotoToPBRNode.temp.g2, false);
+					Graphics2.drawScaledImage(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW, -Config.getTextureResX(), Config.getTextureResY());
+					Graphics2.drawScaledImage(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW, Config.getTextureResX(), -Config.getTextureResY());
+					Graphics2.drawScaledImage(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW, -Config.getTextureResX(), -Config.getTextureResY());
+					Graphics2.drawScaledImage(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW + PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW + PhotoToPBRNode.tileW, Config.getTextureResX(), Config.getTextureResY());
+					Graphics2.drawScaledImage(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW + PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW + PhotoToPBRNode.tileW, -Config.getTextureResX(), Config.getTextureResY());
+					Graphics2.drawScaledImage(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW + PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW + PhotoToPBRNode.tileW, Config.getTextureResX(), -Config.getTextureResY());
+					Graphics2.drawScaledImage(source, PhotoToPBRNode.borderW - x * PhotoToPBRNode.tileW, PhotoToPBRNode.borderW - y * PhotoToPBRNode.tileW, Config.getTextureResX(), Config.getTextureResY());
+					Graphics2.end(PhotoToPBRNode.temp.g2);
+
+					let bytes_img = Image.getPixels(PhotoToPBRNode.temp);
 					let u8a = new Uint8Array(bytes_img);
 					let f32a = new Float32Array(3 * PhotoToPBRNode.tileWithBorderW * PhotoToPBRNode.tileWithBorderW);
 					for (let i = 0; i < (PhotoToPBRNode.tileWithBorderW * PhotoToPBRNode.tileWithBorderW); ++i) {
@@ -142,11 +142,11 @@ class PhotoToPBRNode extends LogicNode {
 						///end
 
 						let temp2 = Image.fromBytes(u8a.buffer, PhotoToPBRNode.tileW, PhotoToPBRNode.tileW);
-						PhotoToPBRNode.images[from].g2.begin(false);
-						PhotoToPBRNode.images[from].g2.drawImage(temp2, x * PhotoToPBRNode.tileW, y * PhotoToPBRNode.tileW);
-						PhotoToPBRNode.images[from].g2.end();
+						Graphics2.begin(PhotoToPBRNode.images[from].g2, false);
+						Graphics2.drawImage(temp2, x * PhotoToPBRNode.tileW, y * PhotoToPBRNode.tileW);
+						Graphics2.end(PhotoToPBRNode.images[from].g2);
 						Base.notifyOnNextFrame(() => {
-							temp2.unload();
+							Image.unload(temp2);
 						});
 					});
 				}

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

@@ -1,16 +1,16 @@
 
 class RGBNode extends LogicNode {
 
-	image: Image = null;
+	image: ImageRaw = null;
 
 	constructor() {
 		super();
 	}
 
-	override getAsImage = (from: i32, done: (img: Image)=>void) => {
+	override getAsImage = (from: i32, done: (img: ImageRaw)=>void) => {
 		if (this.image != null) {
 			Base.notifyOnNextFrame(() => {
-				this.image.unload();
+				Image.unload(this.image);
 			});
 		}
 
@@ -25,8 +25,8 @@ class RGBNode extends LogicNode {
 		done(this.image);
 	}
 
-	override getCachedImage = (): Image => {
-		this.getAsImage(0, (img: Image) => {});
+	override getCachedImage = (): ImageRaw => {
+		this.getAsImage(0, (img: ImageRaw) => {});
 		return this.image;
 	}
 

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

@@ -2,7 +2,7 @@
 class TextToPhotoNode extends LogicNode {
 
 	static prompt = "";
-	static image: Image = null;
+	static image: ImageRaw = null;
 	static tiling = false;
 	static text_encoder_blob : ArrayBuffer;
 	static unet_blob : ArrayBuffer;
@@ -12,14 +12,14 @@ class TextToPhotoNode extends LogicNode {
 		super();
 	}
 
-	override getAsImage = (from: i32, done: (img: Image)=>void) => {
-		TextToPhotoNode.stableDiffusion(TextToPhotoNode.prompt, (_image: Image) => {
+	override getAsImage = (from: i32, done: (img: ImageRaw)=>void) => {
+		TextToPhotoNode.stableDiffusion(TextToPhotoNode.prompt, (_image: ImageRaw) => {
 			TextToPhotoNode.image = _image;
 			done(TextToPhotoNode.image);
 		});
 	}
 
-	override getCachedImage = (): Image => {
+	override getCachedImage = (): ImageRaw => {
 		return TextToPhotoNode.image;
 	}
 
@@ -29,7 +29,7 @@ class TextToPhotoNode extends LogicNode {
 		node.buttons[1].height = TextToPhotoNode.prompt.split("\n").length;
 	}
 
-	static stableDiffusion = (prompt: string, done: (img: Image)=>void, inpaintLatents: Float32Array = null, offset = 0, upscale = true, mask: Float32Array = null, latents_orig: Float32Array = null) => {
+	static stableDiffusion = (prompt: string, done: (img: ImageRaw)=>void, inpaintLatents: Float32Array = null, offset = 0, upscale = true, mask: Float32Array = null, latents_orig: Float32Array = null) => {
 		Data.getBlob("models/sd_text_encoder.quant.onnx", (_text_encoder_blob: ArrayBuffer) => {
 		Data.getBlob("models/sd_unet.quant.onnx", (_unet_blob: ArrayBuffer) => {
 		Data.getBlob("models/sd_vae_decoder.quant.onnx", (_vae_decoder_blob: ArrayBuffer) => {
@@ -95,7 +95,7 @@ class TextToPhotoNode extends LogicNode {
 		let ets: Float32Array[] = [];
 		let counter = 0;
 
-		let processing = (g: Graphics2) => {
+		let processing = (g: Graphics2Raw) => {
 			Console.progress(tr("Processing") + " - " + tr("Text to Photo") + " (" + (counter + 1) + "/" + (50 - offset) + ")");
 
 			let timestep = TextToPhotoNode.timesteps[counter + offset];
@@ -195,7 +195,7 @@ class TextToPhotoNode extends LogicNode {
 		App.notifyOnRender2D(processing);
 	}
 
-	static vaeDecoder = (latents: Float32Array, upscale: bool, done: (img: Image)=>void) => {
+	static vaeDecoder = (latents: Float32Array, upscale: bool, done: (img: ImageRaw)=>void) => {
 		Console.progress(tr("Processing") + " - " + tr("Text to Photo"));
 		Base.notifyOnNextFrame(() => {
 			for (let i = 0; i < latents.length; ++i) {
@@ -231,7 +231,7 @@ class TextToPhotoNode extends LogicNode {
 						while (image.width < Config.getTextureResX()) {
 							let lastImage = image;
 							image = UpscaleNode.esrgan(image);
-							lastImage.unload();
+							Image.unload(lastImage);
 						}
 						done(image);
 					});

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

@@ -1,8 +1,8 @@
 
 class TilingNode extends LogicNode {
 
-	result: Image = null;
-	static image: Image = null;
+	result: ImageRaw = null;
+	static image: ImageRaw = null;
 	static prompt = "";
 	static strength = 0.5;
 	static auto = true;
@@ -28,15 +28,15 @@ class TilingNode extends LogicNode {
 		else node.buttons[1].height = 0;
 	}
 
-	override getAsImage = (from: i32, done: (img: Image)=>void) => {
-		this.inputs[0].getAsImage((source: Image) => {
-			TilingNode.image.g2.begin(false);
-			TilingNode.image.g2.drawScaledImage(source, 0, 0, Config.getTextureResX(), Config.getTextureResY());
-			TilingNode.image.g2.end();
+	override getAsImage = (from: i32, done: (img: ImageRaw)=>void) => {
+		this.inputs[0].getAsImage((source: ImageRaw) => {
+			Graphics2.begin(TilingNode.image.g2, false);
+			Graphics2.drawScaledImage(source, 0, 0, Config.getTextureResX(), Config.getTextureResY());
+			Graphics2.end(TilingNode.image.g2);
 
 			Console.progress(tr("Processing") + " - " + tr("Tiling"));
 			Base.notifyOnNextFrame(() => {
-				let _done = (image: Image) => {
+				let _done = (image: ImageRaw) => {
 					this.result = image;
 					done(image);
 				}
@@ -45,19 +45,19 @@ class TilingNode extends LogicNode {
 		});
 	}
 
-	override getCachedImage = (): Image => {
+	override getCachedImage = (): ImageRaw => {
 		return this.result;
 	}
 
-	static sdTiling = (image: Image, seed: i32/* = -1*/, done: (img: Image)=>void) => {
+	static sdTiling = (image: ImageRaw, seed: i32/* = -1*/, done: (img: ImageRaw)=>void) => {
 		TextToPhotoNode.tiling = false;
 		let tile = Image.createRenderTarget(512, 512);
-		tile.g2.begin(false);
-		tile.g2.drawScaledImage(image, -256, -256, 512, 512);
-		tile.g2.drawScaledImage(image, 256, -256, 512, 512);
-		tile.g2.drawScaledImage(image, -256, 256, 512, 512);
-		tile.g2.drawScaledImage(image, 256, 256, 512, 512);
-		tile.g2.end();
+		Graphics2.begin(tile.g2, false);
+		Graphics2.drawScaledImage(image, -256, -256, 512, 512);
+		Graphics2.drawScaledImage(image, 256, -256, 512, 512);
+		Graphics2.drawScaledImage(image, -256, 256, 512, 512);
+		Graphics2.drawScaledImage(image, 256, 256, 512, 512);
+		Graphics2.end(tile.g2);
 
 		let u8a = new Uint8Array(512 * 512);
 		for (let i = 0; i < 512 * 512; ++i) {

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

@@ -1,16 +1,16 @@
 
 class UpscaleNode extends LogicNode {
 
-	static temp: Image = null;
-	static image: Image = null;
+	static temp: ImageRaw = null;
+	static image: ImageRaw = null;
 	static esrgan_blob: ArrayBuffer;
 
 	constructor() {
 		super();
 	}
 
-	override getAsImage = (from: i32, done: (img: Image)=>void) => {
-		this.inputs[0].getAsImage((_image: Image) => {
+	override getAsImage = (from: i32, done: (img: ImageRaw)=>void) => {
+		this.inputs[0].getAsImage((_image: ImageRaw) => {
 			UpscaleNode.image = _image;
 
 			Console.progress(tr("Processing") + " - " + tr("Upscale"));
@@ -21,7 +21,7 @@ class UpscaleNode extends LogicNode {
 						while (UpscaleNode.image.width < Config.getTextureResX()) {
 							let lastImage = UpscaleNode.image;
 							UpscaleNode.image = UpscaleNode.esrgan(UpscaleNode.image);
-							lastImage.unload();
+							Image.unload(lastImage);
 						}
 					}
 					done(UpscaleNode.image);
@@ -37,25 +37,25 @@ class UpscaleNode extends LogicNode {
 		});
 	}
 
-	override getCachedImage = (): Image => {
+	override getCachedImage = (): ImageRaw => {
 		return UpscaleNode.image;
 	}
 
-	static doTile = (source: Image) => {
-		let result: Image = null;
+	static doTile = (source: ImageRaw) => {
+		let result: ImageRaw = null;
 		let size1w = source.width;
 		let size1h = source.height;
 		let size2w = Math.floor(size1w * 2);
 		let size2h = Math.floor(size1h * 2);
 		if (UpscaleNode.temp != null) {
-			UpscaleNode.temp.unload();
+			Image.unload(UpscaleNode.temp);
 		}
 		UpscaleNode.temp = Image.createRenderTarget(size1w, size1h);
-		UpscaleNode.temp.g2.begin(false);
-		UpscaleNode.temp.g2.drawScaledImage(source, 0, 0, size1w, size1h);
-		UpscaleNode.temp.g2.end();
+		Graphics2.begin(UpscaleNode.temp.g2, false);
+		Graphics2.drawScaledImage(source, 0, 0, size1w, size1h);
+		Graphics2.end(UpscaleNode.temp.g2);
 
-		let bytes_img = UpscaleNode.temp.getPixels();
+		let bytes_img = Image.getPixels(UpscaleNode.temp);
 		let u8a = new Uint8Array(bytes_img);
 		let f32a = new Float32Array(3 * size1w * size1h);
 		for (let i = 0; i < (size1w * size1h); ++i) {
@@ -83,8 +83,8 @@ class UpscaleNode extends LogicNode {
 		return result;
 	}
 
-	static esrgan = (source: Image): Image => {
-		let result: Image = null;
+	static esrgan = (source: ImageRaw): ImageRaw => {
+		let result: ImageRaw = null;
 		let size1w = source.width;
 		let size1h = source.height;
 		let tileSize = 512;
@@ -97,23 +97,23 @@ class UpscaleNode extends LogicNode {
 			let tileSource = Image.createRenderTarget(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) {
-					tileSource.g2.begin(false);
-					tileSource.g2.drawScaledImage(source, 32 - x * tileSize, 32 - y * tileSize, -source.width, source.height);
-					tileSource.g2.drawScaledImage(source, 32 - x * tileSize, 32 - y * tileSize, source.width, -source.height);
-					tileSource.g2.drawScaledImage(source, 32 - x * tileSize, 32 - y * tileSize, -source.width, -source.height);
-					tileSource.g2.drawScaledImage(source, 32 - x * tileSize + tileSize, 32 - y * tileSize + tileSize, source.width, source.height);
-					tileSource.g2.drawScaledImage(source, 32 - x * tileSize + tileSize, 32 - y * tileSize + tileSize, -source.width, source.height);
-					tileSource.g2.drawScaledImage(source, 32 - x * tileSize + tileSize, 32 - y * tileSize + tileSize, source.width, -source.height);
-					tileSource.g2.drawScaledImage(source, 32 - x * tileSize, 32 - y * tileSize, source.width, source.height);
-					tileSource.g2.end();
+					Graphics2.begin(tileSource.g2, false);
+					Graphics2.drawScaledImage(source, 32 - x * tileSize, 32 - y * tileSize, -source.width, source.height);
+					Graphics2.drawScaledImage(source, 32 - x * tileSize, 32 - y * tileSize, source.width, -source.height);
+					Graphics2.drawScaledImage(source, 32 - x * tileSize, 32 - y * tileSize, -source.width, -source.height);
+					Graphics2.drawScaledImage(source, 32 - x * tileSize + tileSize, 32 - y * tileSize + tileSize, source.width, source.height);
+					Graphics2.drawScaledImage(source, 32 - x * tileSize + tileSize, 32 - y * tileSize + tileSize, -source.width, source.height);
+					Graphics2.drawScaledImage(source, 32 - x * tileSize + tileSize, 32 - y * tileSize + tileSize, source.width, -source.height);
+					Graphics2.drawScaledImage(source, 32 - x * tileSize, 32 - y * tileSize, source.width, source.height);
+					Graphics2.end(tileSource.g2);
 					let tileResult = UpscaleNode.doTile(tileSource);
-					result.g2.begin(false);
-					result.g2.drawSubImage(tileResult, x * tileSize2x, y * tileSize2x, 64, 64, tileSize2x, tileSize2x);
-					result.g2.end();
-					tileResult.unload();
+					Graphics2.begin(result.g2, false);
+					Graphics2.drawSubImage(tileResult, x * tileSize2x, y * tileSize2x, 64, 64, tileSize2x, tileSize2x);
+					Graphics2.end(result.g2);
+					Image.unload(tileResult);
 				}
 			}
-			tileSource.unload();
+			Image.unload(tileSource);
 		}
 		else result = UpscaleNode.doTile(source); // Single tile
 		return result;

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

@@ -1,8 +1,8 @@
 
 class VarianceNode extends LogicNode {
 
-	static temp: Image = null;
-	static image: Image = null;
+	static temp: ImageRaw = null;
+	static image: ImageRaw = null;
 	static inst: VarianceNode = null;
 	static prompt = "";
 
@@ -23,15 +23,15 @@ class VarianceNode extends LogicNode {
 		node.buttons[0].height = VarianceNode.prompt.split("\n").length;
 	}
 
-	override getAsImage = (from: i32, done: (img: Image)=>void) => {
+	override getAsImage = (from: i32, done: (img: ImageRaw)=>void) => {
 		let strength = (VarianceNode.inst.inputs[1].node as any).value;
 
-		VarianceNode.inst.inputs[0].getAsImage((source: Image) => {
-			VarianceNode.temp.g2.begin(false);
-			VarianceNode.temp.g2.drawScaledImage(source, 0, 0, 512, 512);
-			VarianceNode.temp.g2.end();
+		VarianceNode.inst.inputs[0].getAsImage((source: ImageRaw) => {
+			Graphics2.begin(VarianceNode.temp.g2, false);
+			Graphics2.drawScaledImage(source, 0, 0, 512, 512);
+			Graphics2.end(VarianceNode.temp.g2);
 
-			let bytes_img = VarianceNode.temp.getPixels();
+			let bytes_img = Image.getPixels(VarianceNode.temp);
 			let u8a = new Uint8Array(bytes_img);
 			let f32a = new Float32Array(3 * 512 * 512);
 			for (let i = 0; i < (512 * 512); ++i) {
@@ -62,7 +62,7 @@ class VarianceNode extends LogicNode {
 					}
 					let t_start = num_inference_steps - init_timestep;
 
-					TextToPhotoNode.stableDiffusion(VarianceNode.prompt, (_image: Image) => {
+					TextToPhotoNode.stableDiffusion(VarianceNode.prompt, (_image: ImageRaw) => {
 						VarianceNode.image = _image;
 						done(VarianceNode.image);
 					}, latents, t_start);
@@ -71,7 +71,7 @@ class VarianceNode extends LogicNode {
 		});
 	}
 
-	override getCachedImage = (): Image => {
+	override getCachedImage = (): ImageRaw => {
 		return VarianceNode.image;
 	}
 

+ 9 - 9
armorpaint/Sources/MakeMaterial.ts

@@ -183,9 +183,9 @@ class MakeMaterial {
 
 		if (bakePreviews) {
 			let current = Graphics2.current;
-			if (current != null) current.end();
+			if (current != null) Graphics2.end(current);
 			MakeMaterial.bakeNodePreviews();
-			if (current != null) current.begin(false);
+			if (current != null) Graphics2.begin(current, false);
 		}
 
 		let m = Project.materials[0].data;
@@ -239,7 +239,7 @@ class MakeMaterial {
 		for (let key of Context.raw.nodePreviews.keys()) {
 			if (Context.raw.nodePreviewsUsed.indexOf(key) == -1) {
 				let image = Context.raw.nodePreviews.get(key);
-				Base.notifyOnNextFrame(image.unload);
+				Base.notifyOnNextFrame(function() { Image.unload(image); });
 				Context.raw.nodePreviews.delete(key);
 			}
 		}
@@ -269,7 +269,7 @@ class MakeMaterial {
 			let resX = Math.floor(Config.getTextureResX() / 4);
 			let resY = Math.floor(Config.getTextureResY() / 4);
 			if (image == null || image.width != resX || image.height != resY) {
-				if (image != null) image.unload();
+				if (image != null) Image.unload(image);
 				image = Image.createRenderTarget(resX, resY);
 				Context.raw.nodePreviews.set(id, image);
 			}
@@ -285,7 +285,7 @@ class MakeMaterial {
 			let resX = Math.floor(Config.getTextureResX());
 			let resY = Math.floor(Config.getTextureResY());
 			if (image == null || image.width != resX || image.height != resY) {
-				if (image != null) image.unload();
+				if (image != null) Image.unload(image);
 				image = Image.createRenderTarget(resX, resY);
 				Context.raw.nodePreviews.set(id, image);
 			}
@@ -301,7 +301,7 @@ class MakeMaterial {
 			let resX = Math.floor(Config.getTextureResX());
 			let resY = Math.floor(Config.getTextureResY());
 			if (image == null || image.width != resX || image.height != resY) {
-				if (image != null) image.unload();
+				if (image != null) Image.unload(image);
 				image = Image.createRenderTarget(resX, resY, TextureFormat.R8);
 				Context.raw.nodePreviews.set(id, image);
 			}
@@ -341,9 +341,9 @@ class MakeMaterial {
 			let rts = RenderPath.renderTargets;
 			let texpaint_live = rts.get("texpaint_live");
 
-			image.g2.begin(false);
-			image.g2.drawImage(texpaint_live.image, 0, 0);
-			image.g2.end();
+			Graphics2.begin(image.g2, false);
+			Graphics2.drawImage(texpaint_live.image, 0, 0);
+			Graphics2.end(image.g2);
 		}
 	}
 

+ 41 - 41
armorpaint/Sources/RenderPathPaint.ts

@@ -13,19 +13,19 @@ class RenderPathPaint {
 	static mergedObjectVisible = false;
 	static savedFov = 0.0;
 	static baking = false;
-	static _texpaint: RenderTarget;
-	static _texpaint_nor: RenderTarget;
-	static _texpaint_pack: RenderTarget;
-	static _texpaint_undo: RenderTarget;
-	static _texpaint_nor_undo: RenderTarget;
-	static _texpaint_pack_undo: RenderTarget;
+	static _texpaint: RenderTargetRaw;
+	static _texpaint_nor: RenderTargetRaw;
+	static _texpaint_pack: RenderTargetRaw;
+	static _texpaint_undo: RenderTargetRaw;
+	static _texpaint_nor_undo: RenderTargetRaw;
+	static _texpaint_pack_undo: RenderTargetRaw;
 	static lastX = -1.0;
 	static lastY = -1.0;
 
 	static init = () => {
 
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texpaint_blend0";
 			t.width = Config.getTextureResX();
 			t.height = Config.getTextureResY();
@@ -33,7 +33,7 @@ class RenderPathPaint {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texpaint_blend1";
 			t.width = Config.getTextureResX();
 			t.height = Config.getTextureResY();
@@ -41,7 +41,7 @@ class RenderPathPaint {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texpaint_colorid";
 			t.width = 1;
 			t.height = 1;
@@ -49,7 +49,7 @@ class RenderPathPaint {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texpaint_picker";
 			t.width = 1;
 			t.height = 1;
@@ -57,7 +57,7 @@ class RenderPathPaint {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texpaint_nor_picker";
 			t.width = 1;
 			t.height = 1;
@@ -65,7 +65,7 @@ class RenderPathPaint {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texpaint_pack_picker";
 			t.width = 1;
 			t.height = 1;
@@ -73,7 +73,7 @@ class RenderPathPaint {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texpaint_uv_picker";
 			t.width = 1;
 			t.height = 1;
@@ -81,7 +81,7 @@ class RenderPathPaint {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texpaint_posnortex_picker0";
 			t.width = 1;
 			t.height = 1;
@@ -89,7 +89,7 @@ class RenderPathPaint {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texpaint_posnortex_picker1";
 			t.width = 1;
 			t.height = 1;
@@ -153,8 +153,8 @@ class RenderPathPaint {
 					RenderPath.drawMeshes("paint");
 					let texpaint_posnortex_picker0 = RenderPath.renderTargets.get("texpaint_posnortex_picker0").image;
 					let texpaint_posnortex_picker1 = RenderPath.renderTargets.get("texpaint_posnortex_picker1").image;
-					let a = new DataView(texpaint_posnortex_picker0.getPixels());
-					let b = new DataView(texpaint_posnortex_picker1.getPixels());
+					let a = new DataView(Image.getPixels(texpaint_posnortex_picker0));
+					let b = new DataView(Image.getPixels(texpaint_posnortex_picker1));
 					Context.raw.posXPicked = a.getFloat32(0, true);
 					Context.raw.posYPicked = a.getFloat32(4, true);
 					Context.raw.posZPicked = a.getFloat32(8, true);
@@ -182,10 +182,10 @@ class RenderPathPaint {
 					let texpaint_nor_picker = RenderPath.renderTargets.get("texpaint_nor_picker").image;
 					let texpaint_pack_picker = RenderPath.renderTargets.get("texpaint_pack_picker").image;
 					let texpaint_uv_picker = RenderPath.renderTargets.get("texpaint_uv_picker").image;
-					let a = new DataView(texpaint_picker.getPixels());
-					let b = new DataView(texpaint_nor_picker.getPixels());
-					let c = new DataView(texpaint_pack_picker.getPixels());
-					let d = new DataView(texpaint_uv_picker.getPixels());
+					let a = new DataView(Image.getPixels(texpaint_picker));
+					let b = new DataView(Image.getPixels(texpaint_nor_picker));
+					let c = new DataView(Image.getPixels(texpaint_pack_picker));
+					let d = new DataView(Image.getPixels(texpaint_uv_picker));
 
 					if (Context.raw.colorPickerCallback != null) {
 						Context.raw.colorPickerCallback(Context.raw.pickedColor);
@@ -299,7 +299,7 @@ class RenderPathPaint {
 
 				if (Context.raw.tool == WorkspaceTool.ToolBake && Context.raw.bakeType == BakeType.BakeCurvature && Context.raw.bakeCurvSmooth > 0) {
 					if (RenderPath.renderTargets.get("texpaint_blur") == null) {
-						let t = new RenderTargetRaw();
+						let t = RenderTarget.create();
 						t.name = "texpaint_blur";
 						t.width = Math.floor(Config.getTextureResX() * 0.95);
 						t.height = Math.floor(Config.getTextureResY() * 0.95);
@@ -352,13 +352,13 @@ class RenderPathPaint {
 
 			let cc_context = shaderContexts[0];
 			if (ConstData.screenAlignedVB == null) ConstData.createScreenAlignedData();
-			RenderPath.currentG.setPipeline(cc_context._pipeState);
+			Graphics4.setPipeline(cc_context._pipeState);
 			Uniforms.setContextConstants(RenderPath.currentG, cc_context, RenderPath.bindParams);
 			Uniforms.setObjectConstants(RenderPath.currentG, cc_context, Project.paintObjects[0].base);
 			Uniforms.setMaterialConstants(RenderPath.currentG, cc_context, materialContexts[0]);
-			RenderPath.currentG.setVertexBuffer(ConstData.screenAlignedVB);
-			RenderPath.currentG.setIndexBuffer(ConstData.screenAlignedIB);
-			RenderPath.currentG.drawIndexedVertices();
+			Graphics4.setVertexBuffer(ConstData.screenAlignedVB);
+			Graphics4.setIndexBuffer(ConstData.screenAlignedIB);
+			Graphics4.drawIndexedVertices();
 			RenderPath.end();
 			///end
 		}
@@ -502,32 +502,32 @@ class RenderPathPaint {
 		if (Base.pipeCursor == null) Base.makeCursorPipe();
 
 		RenderPath.setTarget("");
-		g.setPipeline(Base.pipeCursor);
+		Graphics4.setPipeline(Base.pipeCursor);
 		let decal = Context.raw.tool == WorkspaceTool.ToolDecal || Context.raw.tool == WorkspaceTool.ToolText;
 		let decalMask = decal && Operator.shortcut(Config.keymap.decal_mask, ShortcutType.ShortcutDown);
 		let img = (decal && !decalMask) ? Context.raw.decalImage : Res.get("cursor.k");
-		g.setTexture(Base.cursorTex, img);
+		Graphics4.setTexture(Base.cursorTex, img);
 		let gbuffer0 = RenderPath.renderTargets.get("gbuffer0").image;
-		g.setTextureDepth(Base.cursorGbufferD, gbuffer0);
-		g.setFloat2(Base.cursorMouse, mx, my);
-		g.setFloat2(Base.cursorTexStep, 1 / gbuffer0.width, 1 / gbuffer0.height);
-		g.setFloat(Base.cursorRadius, radius);
+		Graphics4.setTextureDepth(Base.cursorGbufferD, gbuffer0);
+		Graphics4.setFloat2(Base.cursorMouse, mx, my);
+		Graphics4.setFloat2(Base.cursorTexStep, 1 / gbuffer0.width, 1 / gbuffer0.height);
+		Graphics4.setFloat(Base.cursorRadius, radius);
 		let right = Vec4.normalize(CameraObject.rightWorld(Scene.camera));
-		g.setFloat3(Base.cursorCameraRight, right.x, right.y, right.z);
-		g.setFloat3(Base.cursorTint, tintR, tintG, tintB);
-		g.setMatrix(Base.cursorVP, Scene.camera.VP);
+		Graphics4.setFloat3(Base.cursorCameraRight, right.x, right.y, right.z);
+		Graphics4.setFloat3(Base.cursorTint, tintR, tintG, tintB);
+		Graphics4.setMatrix(Base.cursorVP, Scene.camera.VP);
 		let helpMat = Mat4.identity();
 		Mat4.getInverse(helpMat, Scene.camera.VP);
-		g.setMatrix(Base.cursorInvVP, helpMat);
+		Graphics4.setMatrix(Base.cursorInvVP, helpMat);
 		///if (krom_metal || krom_vulkan)
-		g.setVertexBuffer(MeshData.get(geom, [{name: "tex", data: "short2norm"}]));
+		Graphics4.setVertexBuffer(MeshData.get(geom, [{name: "tex", data: "short2norm"}]));
 		///else
-		g.setVertexBuffer(geom._vertexBuffer);
+		Graphics4.setVertexBuffer(geom._vertexBuffer);
 		///end
-		g.setIndexBuffer(geom._indexBuffers[0]);
-		g.drawIndexedVertices();
+		Graphics4.setIndexBuffer(geom._indexBuffers[0]);
+		Graphics4.drawIndexedVertices();
 
-		g.disableScissor();
+		Graphics4.disableScissor();
 		RenderPath.end();
 	}
 

+ 6 - 6
armorpaint/Sources/RenderPathPreview.ts

@@ -4,7 +4,7 @@ class RenderPathPreview {
 	static init = () => {
 
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texpreview";
 			t.width = 1;
 			t.height = 1;
@@ -12,7 +12,7 @@ class RenderPathPreview {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texpreview_icon";
 			t.width = 1;
 			t.height = 1;
@@ -23,7 +23,7 @@ class RenderPathPreview {
 		RenderPath.createDepthBuffer("mmain", "DEPTH24");
 
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "mtex";
 			t.width = Math.floor(UtilRender.materialPreviewSize * 2.0);
 			t.height = Math.floor(UtilRender.materialPreviewSize * 2.0);
@@ -36,7 +36,7 @@ class RenderPathPreview {
 		}
 
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "mgbuffer0";
 			t.width = Math.floor(UtilRender.materialPreviewSize * 2.0);
 			t.height = Math.floor(UtilRender.materialPreviewSize * 2.0);
@@ -47,7 +47,7 @@ class RenderPathPreview {
 		}
 
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "mgbuffer1";
 			t.width = Math.floor(UtilRender.materialPreviewSize * 2.0);
 			t.height = Math.floor(UtilRender.materialPreviewSize * 2.0);
@@ -57,7 +57,7 @@ class RenderPathPreview {
 		}
 
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "mgbuffer2";
 			t.width = Math.floor(UtilRender.materialPreviewSize * 2.0);
 			t.height = Math.floor(UtilRender.materialPreviewSize * 2.0);

+ 2 - 2
armorpaint/Sources/SlotBrush.ts

@@ -2,8 +2,8 @@
 class SlotBrushRaw {
 	nodes = new Nodes();
 	canvas: TNodeCanvas;
-	image: Image = null; // 200px
-	imageIcon: Image = null; // 50px
+	image: ImageRaw = null; // 200px
+	imageIcon: ImageRaw = null; // 50px
 	previewReady = false;
 	id = 0;
 }

+ 3 - 3
armorpaint/Sources/SlotFont.ts

@@ -1,16 +1,16 @@
 
 class SlotFontRaw {
-	image: Image = null; // 200px
+	image: ImageRaw = null; // 200px
 	previewReady = false;
 	id = 0;
-	font: Font;
+	font: FontRaw;
 	name: string;
 	file: string;
 }
 
 class SlotFont {
 
-	static create(name: string, font: Font, file = ""): SlotFontRaw {
+	static create(name: string, font: FontRaw, file = ""): SlotFontRaw {
 		let raw = new SlotFontRaw();
 		for (let slot of Project.fonts) if (slot.id >= raw.id) raw.id = slot.id + 1;
 		raw.name = name;

+ 60 - 60
armorpaint/Sources/SlotLayer.ts

@@ -6,11 +6,11 @@ class SlotLayerRaw {
 	visible = true;
 	parent: SlotLayerRaw = null; // Group (for layers) or layer (for masks)
 
-	texpaint: Image = null; // Base or mask
+	texpaint: ImageRaw = null; // Base or mask
 	///if is_paint
-	texpaint_nor: Image = null;
-	texpaint_pack: Image = null;
-	texpaint_preview: Image = null; // Layer preview
+	texpaint_nor: ImageRaw = null;
+	texpaint_pack: ImageRaw = null;
+	texpaint_preview: ImageRaw = null; // Layer preview
 	///end
 
 	maskOpacity = 1.0; // Opacity mask
@@ -63,7 +63,7 @@ class SlotLayer {
 			///end
 
 			{
-				let t = new RenderTargetRaw();
+				let t = RenderTarget.create();
 				t.name = "texpaint" + ext;
 				t.width = Config.getTextureResX();
 				t.height = Config.getTextureResY();
@@ -73,7 +73,7 @@ class SlotLayer {
 
 			///if is_paint
 			{
-				let t = new RenderTargetRaw();
+				let t = RenderTarget.create();
 				t.name = "texpaint_nor" + ext;
 				t.width = Config.getTextureResX();
 				t.height = Config.getTextureResY();
@@ -81,7 +81,7 @@ class SlotLayer {
 				raw.texpaint_nor = RenderPath.createRenderTarget(t).image;
 			}
 			{
-				let t = new RenderTargetRaw();
+				let t = RenderTarget.create();
 				t.name = "texpaint_pack" + ext;
 				t.width = Config.getTextureResX();
 				t.height = Config.getTextureResY();
@@ -100,7 +100,7 @@ class SlotLayer {
 			raw.blending = BlendType.BlendAdd;
 
 			{
-				let t = new RenderTargetRaw();
+				let t = RenderTarget.create();
 				t.name = "texpaint" + ext;
 				t.width = Config.getTextureResX();
 				t.height = Config.getTextureResY();
@@ -150,11 +150,11 @@ class SlotLayer {
 		///end
 
 		let _next = () => {
-			_texpaint.unload();
+			Image.unload(_texpaint);
 			///if is_paint
-			if (_texpaint_nor != null) _texpaint_nor.unload();
-			if (_texpaint_pack != null) _texpaint_pack.unload();
-			_texpaint_preview.unload();
+			if (_texpaint_nor != null) Image.unload(_texpaint_nor);
+			if (_texpaint_pack != null) Image.unload(_texpaint_pack);
+			Image.unload(_texpaint_preview);
 			///end
 		}
 		Base.notifyOnNextFrame(_next);
@@ -199,24 +199,24 @@ class SlotLayer {
 		///end
 	}
 
-	static clear = (raw: SlotLayerRaw, baseColor = 0x00000000, baseImage: Image = null, occlusion = 1.0, roughness = Base.defaultRough, metallic = 0.0) => {
-		raw.texpaint.g4.begin();
-		raw.texpaint.g4.clear(baseColor); // Base
-		raw.texpaint.g4.end();
+	static clear = (raw: SlotLayerRaw, baseColor = 0x00000000, baseImage: ImageRaw = null, occlusion = 1.0, roughness = Base.defaultRough, metallic = 0.0) => {
+		Graphics4.begin(raw.texpaint.g4);
+		Graphics4.clear(baseColor); // Base
+		Graphics4.end();
 		if (baseImage != null) {
-			raw.texpaint.g2.begin(false);
-			raw.texpaint.g2.drawScaledImage(baseImage, 0, 0, raw.texpaint.width, raw.texpaint.height);
-			raw.texpaint.g2.end();
+			Graphics2.begin(raw.texpaint.g2, false);
+			Graphics2.drawScaledImage(baseImage, 0, 0, raw.texpaint.width, raw.texpaint.height);
+			Graphics2.end(raw.texpaint.g2);
 		}
 
 		///if is_paint
 		if (SlotLayer.isLayer(raw)) {
-			raw.texpaint_nor.g4.begin();
-			raw.texpaint_nor.g4.clear(color_from_floats(0.5, 0.5, 1.0, 0.0)); // Nor
-			raw.texpaint_nor.g4.end();
-			raw.texpaint_pack.g4.begin();
-			raw.texpaint_pack.g4.clear(color_from_floats(occlusion, roughness, metallic, 0.0)); // Occ, rough, met
-			raw.texpaint_pack.g4.end();
+			Graphics4.begin(raw.texpaint_nor.g4);
+			Graphics4.clear(color_from_floats(0.5, 0.5, 1.0, 0.0)); // Nor
+			Graphics4.end();
+			Graphics4.begin(raw.texpaint_pack.g4);
+			Graphics4.clear(color_from_floats(occlusion, roughness, metallic, 0.0)); // Occ, rough, met
+			Graphics4.end();
 		}
 		///end
 
@@ -227,14 +227,14 @@ class SlotLayer {
 	static invertMask = (raw: SlotLayerRaw) => {
 		if (Base.pipeInvert8 == null) Base.makePipe();
 		let inverted = Image.createRenderTarget(raw.texpaint.width, raw.texpaint.height, TextureFormat.RGBA32);
-		inverted.g2.begin(false);
+		Graphics2.begin(inverted.g2, false);
 		inverted.g2.pipeline = Base.pipeInvert8;
-		inverted.g2.drawImage(raw.texpaint, 0, 0);
+		Graphics2.drawImage(raw.texpaint, 0, 0);
 		inverted.g2.pipeline = null;
-		inverted.g2.end();
+		Graphics2.end(inverted.g2);
 		let _texpaint = raw.texpaint;
 		let _next = () => {
-			_texpaint.unload();
+			Image.unload(_texpaint);
 		}
 		Base.notifyOnNextFrame(_next);
 		raw.texpaint = RenderPath.renderTargets.get("texpaint" + raw.id).image = inverted;
@@ -265,38 +265,38 @@ class SlotLayer {
 
 		if (Base.pipeMerge == null) Base.makePipe();
 		if (SlotLayer.isLayer(raw)) {
-			l.texpaint.g2.begin(false);
+			Graphics2.begin(l.texpaint.g2, false);
 			l.texpaint.g2.pipeline = Base.pipeCopy;
-			l.texpaint.g2.drawImage(raw.texpaint, 0, 0);
+			Graphics2.drawImage(raw.texpaint, 0, 0);
 			l.texpaint.g2.pipeline = null;
-			l.texpaint.g2.end();
+			Graphics2.end(l.texpaint.g2);
 			///if is_paint
-			l.texpaint_nor.g2.begin(false);
+			Graphics2.begin(l.texpaint_nor.g2, false);
 			l.texpaint_nor.g2.pipeline = Base.pipeCopy;
-			l.texpaint_nor.g2.drawImage(raw.texpaint_nor, 0, 0);
+			Graphics2.drawImage(raw.texpaint_nor, 0, 0);
 			l.texpaint_nor.g2.pipeline = null;
-			l.texpaint_nor.g2.end();
-			l.texpaint_pack.g2.begin(false);
+			Graphics2.end(l.texpaint_nor.g2);
+			Graphics2.begin(l.texpaint_pack.g2, false);
 			l.texpaint_pack.g2.pipeline = Base.pipeCopy;
-			l.texpaint_pack.g2.drawImage(raw.texpaint_pack, 0, 0);
+			Graphics2.drawImage(raw.texpaint_pack, 0, 0);
 			l.texpaint_pack.g2.pipeline = null;
-			l.texpaint_pack.g2.end();
+			Graphics2.end(l.texpaint_pack.g2);
 			///end
 		}
 		else if (SlotLayer.isMask(raw)) {
-			l.texpaint.g2.begin(false);
+			Graphics2.begin(l.texpaint.g2, false);
 			l.texpaint.g2.pipeline = Base.pipeCopy8;
-			l.texpaint.g2.drawImage(raw.texpaint, 0, 0);
+			Graphics2.drawImage(raw.texpaint, 0, 0);
 			l.texpaint.g2.pipeline = null;
-			l.texpaint.g2.end();
+			Graphics2.end(l.texpaint.g2);
 		}
 
 		///if is_paint
-		l.texpaint_preview.g2.begin(true, 0x00000000);
+		Graphics2.begin(l.texpaint_preview.g2, true, 0x00000000);
 		l.texpaint_preview.g2.pipeline = Base.pipeCopy;
-		l.texpaint_preview.g2.drawScaledImage(raw.texpaint_preview, 0, 0, raw.texpaint_preview.width, raw.texpaint_preview.height);
+		Graphics2.drawScaledImage(raw.texpaint_preview, 0, 0, raw.texpaint_preview.width, raw.texpaint_preview.height);
 		l.texpaint_preview.g2.pipeline = null;
-		l.texpaint_preview.g2.end();
+		Graphics2.end(l.texpaint_preview.g2);
 		///end
 
 		l.visible = raw.visible;
@@ -341,11 +341,11 @@ class SlotLayer {
 
 			let _texpaint = raw.texpaint;
 			raw.texpaint = Image.createRenderTarget(resX, resY, format);
-			raw.texpaint.g2.begin(false);
+			Graphics2.begin(raw.texpaint.g2, false);
 			raw.texpaint.g2.pipeline = Base.pipeCopy;
-			raw.texpaint.g2.drawScaledImage(_texpaint, 0, 0, resX, resY);
+			Graphics2.drawScaledImage(_texpaint, 0, 0, resX, resY);
 			raw.texpaint.g2.pipeline = null;
-			raw.texpaint.g2.end();
+			Graphics2.end(raw.texpaint.g2);
 
 			///if is_paint
 			let _texpaint_nor = raw.texpaint_nor;
@@ -353,24 +353,24 @@ class SlotLayer {
 			raw.texpaint_nor = Image.createRenderTarget(resX, resY, format);
 			raw.texpaint_pack = Image.createRenderTarget(resX, resY, format);
 
-			raw.texpaint_nor.g2.begin(false);
+			Graphics2.begin(raw.texpaint_nor.g2, false);
 			raw.texpaint_nor.g2.pipeline = Base.pipeCopy;
-			raw.texpaint_nor.g2.drawScaledImage(_texpaint_nor, 0, 0, resX, resY);
+			Graphics2.drawScaledImage(_texpaint_nor, 0, 0, resX, resY);
 			raw.texpaint_nor.g2.pipeline = null;
-			raw.texpaint_nor.g2.end();
+			Graphics2.end(raw.texpaint_nor.g2);
 
-			raw.texpaint_pack.g2.begin(false);
+			Graphics2.begin(raw.texpaint_pack.g2, false);
 			raw.texpaint_pack.g2.pipeline = Base.pipeCopy;
-			raw.texpaint_pack.g2.drawScaledImage(_texpaint_pack, 0, 0, resX, resY);
+			Graphics2.drawScaledImage(_texpaint_pack, 0, 0, resX, resY);
 			raw.texpaint_pack.g2.pipeline = null;
-			raw.texpaint_pack.g2.end();
+			Graphics2.end(raw.texpaint_pack.g2);
 			///end
 
 			let _next = () => {
-				_texpaint.unload();
+				Image.unload(_texpaint);
 				///if is_paint
-				_texpaint_nor.unload();
-				_texpaint_pack.unload();
+				Image.unload(_texpaint_nor);
+				Image.unload(_texpaint_pack);
 				///end
 			}
 			Base.notifyOnNextFrame(_next);
@@ -385,14 +385,14 @@ class SlotLayer {
 			let _texpaint = raw.texpaint;
 			raw.texpaint = Image.createRenderTarget(resX, resY, TextureFormat.RGBA32);
 
-			raw.texpaint.g2.begin(false);
+			Graphics2.begin(raw.texpaint.g2, false);
 			raw.texpaint.g2.pipeline = Base.pipeCopy8;
-			raw.texpaint.g2.drawScaledImage(_texpaint, 0, 0, resX, resY);
+			Graphics2.drawScaledImage(_texpaint, 0, 0, resX, resY);
 			raw.texpaint.g2.pipeline = null;
-			raw.texpaint.g2.end();
+			Graphics2.end(raw.texpaint.g2);
 
 			let _next = () => {
-				_texpaint.unload();
+				Image.unload(_texpaint);
 			}
 			Base.notifyOnNextFrame(_next);
 

+ 4 - 4
armorpaint/Sources/SlotMaterial.ts

@@ -2,8 +2,8 @@
 class SlotMaterialRaw {
 	nodes = new Nodes();
 	canvas: TNodeCanvas;
-	image: Image = null;
-	imageIcon: Image = null;
+	image: ImageRaw = null;
+	imageIcon: ImageRaw = null;
 	previewReady = false;
 	data: TMaterialData;
 	id = 0;
@@ -54,8 +54,8 @@ class SlotMaterial {
 
 	static unload = (raw: SlotMaterialRaw) => {
 		let _next = () => {
-			raw.image.unload();
-			raw.imageIcon.unload();
+			Image.unload(raw.image);
+			Image.unload(raw.imageIcon);
 		}
 		Base.notifyOnNextFrame(_next);
 	}

+ 9 - 9
armorpaint/Sources/TabLayers.ts

@@ -632,12 +632,12 @@ class TabLayers {
 			if (!isTyping) {
 				if (i < 9 && Operator.shortcut(Config.keymap.select_layer, ShortcutType.ShortcutDown)) {
 					let number = String(i + 1) ;
-					let width = ui.font.width(ui.fontSize, number) + 10;
-					let height = ui.font.height(ui.fontSize);
+					let width = Font.width(ui.font, ui.fontSize, number) + 10;
+					let height = Font.height(ui.font, ui.fontSize);
 					ui.g.color = ui.t.TEXT_COL;
-					ui.g.fillRect(uix, uiy, width, height);
+					Graphics2.fillRect(uix, uiy, width, height);
 					ui.g.color = ui.t.ACCENT_COL;
-					ui.g.drawString(number, uix + 5, uiy);
+					Graphics2.drawString(number, uix + 5, uiy);
 				}
 			}
 
@@ -710,7 +710,7 @@ class TabLayers {
 						let f = UIFiles.filename;
 						if (f == "") f = tr("untitled");
 						if (!f.endsWith(".png")) f += ".png";
-						Krom.writePng(path + Path.sep + f, l.texpaint.getPixels(), l.texpaint.width, l.texpaint.height, 3); // RRR1
+						Krom.writePng(path + Path.sep + f, Image.getPixels(l.texpaint), l.texpaint.width, l.texpaint.height, 3); // RRR1
 					});
 				}
 				else {
@@ -982,11 +982,11 @@ class TabLayers {
 		if (Context.raw.maskPreviewLast != l) {
 			Context.raw.maskPreviewLast = l;
 			App.notifyOnInit(() => {
-				Context.raw.maskPreviewRgba32.g2.begin();
+				Graphics2.begin(Context.raw.maskPreviewRgba32.g2);
 				Context.raw.maskPreviewRgba32.g2.pipeline = UIView2D.pipe;
-				Context.raw.maskPreviewRgba32.g4.setInt(UIView2D.channelLocation, 1);
-				Context.raw.maskPreviewRgba32.g2.drawImage(l.texpaint_preview, 0, 0);
-				Context.raw.maskPreviewRgba32.g2.end();
+				Graphics4.setInt(UIView2D.channelLocation, 1);
+				Graphics2.drawImage(l.texpaint_preview, 0, 0);
+				Graphics2.end(Context.raw.maskPreviewRgba32.g2);
 				Context.raw.maskPreviewRgba32.g2.pipeline = null;
 			});
 		}

+ 1 - 1
armorsculpt/Sources/ExportObj.ts

@@ -12,7 +12,7 @@ class ExportObj {
 		ExportObj.writeString(o, "# armorsculpt.org\n");
 
 		let texpaint = Project.layers[0].texpaint;
-		let pixels = texpaint.getPixels();
+		let pixels = Image.getPixels(texpaint);
 		let pixelsView = new DataView(pixels);
 		let mesh = paintObjects[0].data;
 		let inda = mesh.index_arrays[0].values;

+ 3 - 3
armorsculpt/Sources/ImportMesh.ts

@@ -129,11 +129,11 @@ class ImportMesh {
 					}
 					let imgmesh = Image.fromBytes(f32.buffer, Config.getTextureResX(), Config.getTextureResY(), TextureFormat.RGBA128);
 					let texpaint = Project.layers[0].texpaint;
-					texpaint.g2.begin(false);
+					Graphics2.begin(texpaint.g2, false);
 					texpaint.g2.pipeline = Base.pipeCopy128;
-					texpaint.g2.drawScaledImage(imgmesh, 0, 0, Config.getTextureResX(), Config.getTextureResY());
+					Graphics2.drawScaledImage(imgmesh, 0, 0, Config.getTextureResX(), Config.getTextureResY());
 					texpaint.g2.pipeline = null;
-					texpaint.g2.end();
+					Graphics2.end(texpaint.g2);
 				});
 			});
 		}

+ 5 - 5
armorsculpt/Sources/MakeMaterial.ts

@@ -178,9 +178,9 @@ class MakeMaterial {
 
 		if (bakePreviews) {
 			let current = Graphics2.current;
-			if (current != null) current.end();
+			if (current != null) Graphics2.end(current);
 			MakeMaterial.bakeNodePreviews();
-			if (current != null) current.begin(false);
+			if (current != null) Graphics2.begin(current, false);
 		}
 
 		let m = Project.materials[0].data;
@@ -234,7 +234,7 @@ class MakeMaterial {
 		for (let key of Context.raw.nodePreviews.keys()) {
 			if (Context.raw.nodePreviewsUsed.indexOf(key) == -1) {
 				let image = Context.raw.nodePreviews.get(key);
-				Base.notifyOnNextFrame(image.unload);
+				Base.notifyOnNextFrame(function() { Image.unload(image); });
 				Context.raw.nodePreviews.delete(key);
 			}
 		}
@@ -264,7 +264,7 @@ class MakeMaterial {
 			let resX = Math.floor(Config.getTextureResX() / 4);
 			let resY = Math.floor(Config.getTextureResY() / 4);
 			if (image == null || image.width != resX || image.height != resY) {
-				if (image != null) image.unload();
+				if (image != null) Image.unload(image);
 				image = Image.createRenderTarget(resX, resY);
 				Context.raw.nodePreviews.set(id, image);
 			}
@@ -280,7 +280,7 @@ class MakeMaterial {
 			let resX = Math.floor(Config.getTextureResX());
 			let resY = Math.floor(Config.getTextureResY());
 			if (image == null || image.width != resX || image.height != resY) {
-				if (image != null) image.unload();
+				if (image != null) Image.unload(image);
 				image = Image.createRenderTarget(resX, resY);
 				Context.raw.nodePreviews.set(id, image);
 			}

File diff suppressed because it is too large
+ 319 - 319
base/Sources/Base.ts


+ 2 - 2
base/Sources/BoxPreferences.ts

@@ -269,7 +269,7 @@ class BoxPreferences {
 					Config.raw.undo_steps = Math.floor(Context.raw.undoHandle.value = 1);
 				}
 				if (Context.raw.undoHandle.changed) {
-					ui.g.end();
+					Graphics2.end(ui.g);
 
 					///if (is_paint || is_sculpt)
 					while (History.undoLayers.length < Config.raw.undo_steps) {
@@ -283,7 +283,7 @@ class BoxPreferences {
 					///end
 
 					History.reset();
-					ui.g.begin(false);
+					Graphics2.begin(ui.g, false);
 				}
 
 				///if is_paint

+ 5 - 5
base/Sources/BoxProjects.ts

@@ -3,7 +3,7 @@ class BoxProjects {
 
 	static htab = new Handle();
 	static hsearch = new Handle();
-	static iconMap: Map<string, Image> = null;
+	static iconMap: Map<string, ImageRaw> = null;
 
 	static show = () => {
 		if (BoxProjects.iconMap != null) {
@@ -100,7 +100,7 @@ class BoxProjects {
 					if (BoxProjects.iconMap == null) BoxProjects.iconMap = new Map();
 					let icon = BoxProjects.iconMap.get(iconPath);
 					if (icon == null) {
-						Data.getImage(iconPath, (image: Image) => {
+						Data.getImage(iconPath, (image: ImageRaw) => {
 							icon = image;
 							BoxProjects.iconMap.set(iconPath, icon);
 						});
@@ -194,11 +194,11 @@ class BoxProjects {
 
 				if (ui.button(file, Align.Left) && File.exists(path)) {
 					let current = Graphics2.current;
-					if (current != null) current.end();
+					if (current != null) Graphics2.end(current);
 
 					ImportArm.runProject(path);
 
-					if (current != null) current.begin(false);
+					if (current != null) Graphics2.begin(current, false);
 					UIBox.hide();
 				}
 				if (ui.isHovered) ui.tooltip(path);
@@ -218,7 +218,7 @@ class BoxProjects {
 	}
 
 	static drawBadge = (ui: Zui) => {
-		Data.getImage("badge.k", (img: Image) => {
+		Data.getImage("badge.k", (img: ImageRaw) => {
 			ui.image(img);
 			ui.endElement();
 		});

+ 2 - 2
base/Sources/Config.ts

@@ -178,9 +178,9 @@ class Config {
 		Context.raw.ddirty = 2;
 
 		let current = Graphics2.current;
-		if (current != null) current.end();
+		if (current != null) Graphics2.end(current);
 		RenderPathBase.applyConfig();
-		if (current != null) current.begin(false);
+		if (current != null) Graphics2.begin(current, false);
 	}
 
 	static loadKeymap = () => {

+ 7 - 7
base/Sources/Console.ts

@@ -7,22 +7,22 @@ class Console {
 	static lastTraces: string[] = [""];
 	static progressText: string = null;
 
-	static drawToast = (s: string, g: Graphics2) => {
+	static drawToast = (s: string, g: Graphics2Raw) => {
 		g.color = 0x55000000;
-		g.fillRect(0, 0, System.width, System.height);
+		Graphics2.fillRect(0, 0, System.width, System.height);
 		let scale = Base.getUIs()[0].SCALE();
 		let x = System.width / 2;
 		let y = System.height - 200 * scale;
-		g.fillRect(x - 200 * scale, y, 400 * scale, 80 * scale);
+		Graphics2.fillRect(x - 200 * scale, y, 400 * scale, 80 * scale);
 		g.font = Base.font;
 		g.fontSize = Math.floor(22 * scale);
 		g.color = 0xffffffff;
-		g.drawString(s, x - g.font.width(g.fontSize, s) / 2, y + 40 * scale - g.font.height(g.fontSize) / 2);
+		Graphics2.drawString(s, x - Font.width(g.font, g.fontSize, s) / 2, y + 40 * scale - Font.height(g.font, g.fontSize) / 2);
 	}
 
-	static toast = (s: string, g2: Graphics2 = null) => {
+	static toast = (s: string, g2: Graphics2Raw = null) => {
 		// Show a popup message
-		let _render = (g: Graphics2) => {
+		let _render = (g: Graphics2Raw) => {
 			Console.drawToast(s, g);
 			if (g2 == null) {
 				Base.notifyOnNextFrame(() => {
@@ -34,7 +34,7 @@ class Console {
 		Console.consoleTrace(s);
 	}
 
-	static drawProgress = (g: Graphics2) => {
+	static drawProgress = (g: Graphics2Raw) => {
 		Console.drawToast(Console.progressText, g);
 	}
 

+ 2 - 2
base/Sources/Context.ts

@@ -76,13 +76,13 @@ class Context {
 		UIHeader.headerHandle.redraws = 2;
 
 		let current = Graphics2.current;
-		if (current != null) current.end();
+		if (current != null) Graphics2.end(current);
 
 		Base.setObjectMask();
 		MakeMaterial.parseMeshMaterial();
 		MakeMaterial.parsePaintMaterial();
 
-		if (current != null) current.begin(false);
+		if (current != null) Graphics2.begin(current, false);
 
 		UIBase.hwnds[TabArea.TabSidebar0].redraws = 2;
 		UIView2D.hwnd.redraws = 2;

+ 12 - 12
base/Sources/ContextFormat.ts

@@ -23,11 +23,11 @@ class TContext {
 	colorPickerCallback?: (sc: TSwatchColor)=>void = null;
 
 	defaultIrradiance?: Float32Array = null;
-	defaultRadiance?: Image = null;
-	defaultRadianceMipmaps?: Image[] = null;
-	savedEnvmap?: Image = null;
-	emptyEnvmap?: Image = null;
-	previewEnvmap?: Image = null;
+	defaultRadiance?: ImageRaw = null;
+	defaultRadianceMipmaps?: ImageRaw[] = null;
+	savedEnvmap?: ImageRaw = null;
+	emptyEnvmap?: ImageRaw = null;
+	previewEnvmap?: ImageRaw = null;
 	envmapLoaded? = false;
 	showEnvmap? = false;
 	showEnvmapHandle? = new Handle({ selected: false });
@@ -125,11 +125,11 @@ class TContext {
 	layerPreviewDirty? = true;
 	layersPreviewDirty? = false;
 	nodePreviewDirty? = false;
-	nodePreview?: Image = null;
-	nodePreviews?: Map<string, Image> = null;
+	nodePreview?: ImageRaw = null;
+	nodePreviews?: Map<string, ImageRaw> = null;
 	nodePreviewsUsed?: string[] = null;
 	nodePreviewName? = "";
-	maskPreviewRgba32?: Image = null;
+	maskPreviewRgba32?: ImageRaw = null;
 	maskPreviewLast?: SlotLayerRaw = null;
 
 	colorIdPicked? = false;
@@ -158,7 +158,7 @@ class TContext {
 	colorIdHandle? = new Handle();
 	layersExport? = ExportMode.ExportVisible;
 
-	decalImage?: Image = null;
+	decalImage?: ImageRaw = null;
 	decalPreview? = false;
 	decalX? = 0.0;
 	decalY? = 0.0;
@@ -166,7 +166,7 @@ class TContext {
 	cacheDraws? = false;
 	writeIconOnExport? = false;
 
-	textToolImage?: Image = null;
+	textToolImage?: ImageRaw = null;
 	textToolText?: string;
 	particleMaterial?: TMaterialData = null;
 	///if arm_physics
@@ -211,9 +211,9 @@ class TContext {
 
 	brushNodesRadius? = 1.0;
 	brushNodesOpacity? = 1.0;
-	brushMaskImage?: Image = null;
+	brushMaskImage?: ImageRaw = null;
 	brushMaskImageIsAlpha? = false;
-	brushStencilImage?: Image = null;
+	brushStencilImage?: ImageRaw = null;
 	brushStencilImageIsAlpha? = false;
 	brushStencilX? = 0.02;
 	brushStencilY? = 0.02;

+ 19 - 19
base/Sources/ExportArm.ts

@@ -62,7 +62,7 @@ class ExportArm {
 				name: l.name,
 				res: l.texpaint != null ? l.texpaint.width : Project.layers[0].texpaint.width,
 				bpp: bpp,
-				texpaint: l.texpaint != null ? Lz4.encode(l.texpaint.getPixels()) : null,
+				texpaint: l.texpaint != null ? Lz4.encode(Image.getPixels(l.texpaint)) : null,
 				uv_scale: l.scale,
 				uv_rot: l.angle,
 				uv_type: l.uvType,
@@ -74,8 +74,8 @@ class ExportArm {
 				parent: l.parent != null ? Project.layers.indexOf(l.parent) : -1,
 				visible: l.visible,
 				///if is_paint
-				texpaint_nor: l.texpaint_nor != null ? Lz4.encode(l.texpaint_nor.getPixels()) : null,
-				texpaint_pack: l.texpaint_pack != null ? Lz4.encode(l.texpaint_pack.getPixels()) : null,
+				texpaint_nor: l.texpaint_nor != null ? Lz4.encode(Image.getPixels(l.texpaint_nor)) : null,
+				texpaint_pack: l.texpaint_pack != null ? Lz4.encode(Image.getPixels(l.texpaint_pack)) : null,
 				paint_base: l.paintBase,
 				paint_opac: l.paintOpac,
 				paint_occ: l.paintOcc,
@@ -153,7 +153,7 @@ class ExportArm {
 		mesh_icon.g2.begin(false);
 		mesh_icon.g2.end();
 		///end
-		let mesh_icon_pixels = mesh_icon.getPixels();
+		let mesh_icon_pixels = Image.getPixels(mesh_icon);
 		let u8a = new Uint8Array(mesh_icon_pixels);
 		for (let i = 0; i < 256 * 256 * 4; ++i) {
 			u8a[i] = Math.floor(Math.pow(u8a[i] / 255, 1.0 / 2.2) * 255);
@@ -162,7 +162,7 @@ class ExportArm {
 		ExportArm.bgraSwap(mesh_icon_pixels);
 		///end
 		Base.notifyOnNextFrame(() => {
-			mesh_icon.unload();
+			Image.unload(mesh_icon);
 		});
 		// Project.raw.mesh_icons =
 		// 	///if (krom_metal || krom_vulkan)
@@ -253,18 +253,18 @@ class ExportArm {
 			material_groups: mgroups,
 			material_icons: isCloud ? null :
 				///if (krom_metal || krom_vulkan)
-				[Lz4.encode(ExportArm.bgraSwap(m.image.getPixels()))],
+				[Lz4.encode(ExportArm.bgraSwap(Image.getPixels(m.image)))],
 				///else
-				[Lz4.encode(m.image.getPixels())],
+				[Lz4.encode(Image.getPixels(m.image))],
 				///end
 			assets: texture_files,
 			packed_assets: packed_assets
 		};
 
 		if (Context.raw.writeIconOnExport) { // Separate icon files
-			Krom.writePng(path.substr(0, path.length - 4) + "_icon.png", m.image.getPixels(), m.image.width, m.image.height, 0);
+			Krom.writePng(path.substr(0, path.length - 4) + "_icon.png", Image.getPixels(m.image), m.image.width, m.image.height, 0);
 			if (isCloud) {
-				Krom.writeJpg(path.substr(0, path.length - 4) + "_icon.jpg", m.image.getPixels(), m.image.width, m.image.height, 0, 50);
+				Krom.writeJpg(path.substr(0, path.length - 4) + "_icon.jpg", Image.getPixels(m.image), m.image.width, m.image.height, 0, 50);
 			}
 		}
 
@@ -312,16 +312,16 @@ class ExportArm {
 			brush_nodes: bnodes,
 			brush_icons: isCloud ? null :
 			///if (krom_metal || krom_vulkan)
-			[Lz4.encode(ExportArm.bgraSwap(b.image.getPixels()))],
+			[Lz4.encode(ExportArm.bgraSwap(Image.getPixels(b.image)))],
 			///else
-			[Lz4.encode(b.image.getPixels())],
+			[Lz4.encode(Image.getPixels(b.image))],
 			///end
 			assets: texture_files,
 			packed_assets: packed_assets
 		};
 
 		if (Context.raw.writeIconOnExport) { // Separate icon file
-			Krom.writePng(path.substr(0, path.length - 4) + "_icon.png", b.image.getPixels(), b.image.width, b.image.height, 0);
+			Krom.writePng(path.substr(0, path.length - 4) + "_icon.png", Image.getPixels(b.image), b.image.width, b.image.height, 0);
 		}
 
 		if (Context.raw.packAssetsOnExport) { // Pack textures
@@ -422,25 +422,25 @@ class ExportArm {
 		if (raw.packed_assets == null) {
 			raw.packed_assets = [];
 		}
-		let tempImages: Image[] = [];
+		let tempImages: ImageRaw[] = [];
 		for (let i = 0; i < assets.length; ++i) {
 			if (!Project.packedAssetExists(raw.packed_assets, assets[i].file)) {
 				let image = Project.getImage(assets[i]);
 				let temp = Image.createRenderTarget(image.width, image.height);
-				temp.g2.begin(false);
-				temp.g2.drawImage(image, 0, 0);
-				temp.g2.end();
+				Graphics2.begin(temp.g2, false);
+				Graphics2.drawImage(image, 0, 0);
+				Graphics2.end(temp.g2);
 				tempImages.push(temp);
 				raw.packed_assets.push({
 					name: assets[i].file,
 					bytes: assets[i].file.endsWith(".jpg") ?
-						Krom.encodeJpg(temp.getPixels(), temp.width, temp.height, 0, 80) :
-						Krom.encodePng(temp.getPixels(), temp.width, temp.height, 0)
+						Krom.encodeJpg(Image.getPixels(temp), temp.width, temp.height, 0, 80) :
+						Krom.encodePng(Image.getPixels(temp), temp.width, temp.height, 0)
 				});
 			}
 		}
 		Base.notifyOnNextFrame(() => {
-			for (let image of tempImages) image.unload();
+			for (let image of tempImages) Image.unload(image);
 		});
 	}
 

+ 55 - 55
base/Sources/ExportTexture.ts

@@ -153,15 +153,15 @@ class ExportTexture {
 		}
 
 		// Clear export layer
-		Base.expa.g4.begin();
-		Base.expa.g4.clear(color_from_floats(0.0, 0.0, 0.0, 0.0));
-		Base.expa.g4.end();
-		Base.expb.g4.begin();
-		Base.expb.g4.clear(color_from_floats(0.5, 0.5, 1.0, 0.0));
-		Base.expb.g4.end();
-		Base.expc.g4.begin();
-		Base.expc.g4.clear(color_from_floats(1.0, 0.0, 0.0, 0.0));
-		Base.expc.g4.end();
+		Graphics4.begin(Base.expa.g4);
+		Graphics4.clear(color_from_floats(0.0, 0.0, 0.0, 0.0));
+		Graphics4.end();
+		Graphics4.begin(Base.expb.g4);
+		Graphics4.clear(color_from_floats(0.5, 0.5, 1.0, 0.0));
+		Graphics4.end();
+		Graphics4.begin(Base.expc.g4);
+		Graphics4.clear(color_from_floats(1.0, 0.0, 0.0, 0.0));
+		Graphics4.end();
 
 		// Flatten layers
 		for (let l1 of layers) {
@@ -179,8 +179,8 @@ class ExportTexture {
 			if (l1masks != null && !bakeMaterial) {
 				if (l1masks.length > 1) {
 					Base.makeTempMaskImg();
-					Base.tempMaskImage.g2.begin(true, 0x00000000);
-					Base.tempMaskImage.g2.end();
+					Graphics2.begin(Base.tempMaskImage.g2, true, 0x00000000);
+					Graphics2.end(Base.tempMaskImage.g2);
 					let l1: any = { texpaint: Base.tempMaskImage };
 					for (let i = 0; i < l1masks.length; ++i) {
 						Base.mergeLayer(l1, l1masks[i]);
@@ -191,53 +191,53 @@ class ExportTexture {
 			}
 
 			if (l1.paintBase) {
-				Base.tempImage.g2.begin(false); // Copy to temp
+				Graphics2.begin(Base.tempImage.g2, false); // Copy to temp
 				Base.tempImage.g2.pipeline = Base.pipeCopy;
-				Base.tempImage.g2.drawImage(Base.expa, 0, 0);
+				Graphics2.drawImage(Base.expa, 0, 0);
 				Base.tempImage.g2.pipeline = null;
-				Base.tempImage.g2.end();
-
-				Base.expa.g4.begin();
-				Base.expa.g4.setPipeline(Base.pipeMerge);
-				Base.expa.g4.setTexture(Base.tex0, l1.texpaint);
-				Base.expa.g4.setTexture(Base.tex1, empty);
-				Base.expa.g4.setTexture(Base.texmask, mask);
-				Base.expa.g4.setTexture(Base.texa, Base.tempImage);
-				Base.expa.g4.setFloat(Base.opac, SlotLayer.getOpacity(l1));
-				Base.expa.g4.setInt(Base.blending, layers.length > 1 ? l1.blending : 0);
-				Base.expa.g4.setVertexBuffer(ConstData.screenAlignedVB);
-				Base.expa.g4.setIndexBuffer(ConstData.screenAlignedIB);
-				Base.expa.g4.drawIndexedVertices();
-				Base.expa.g4.end();
+				Graphics2.end(Base.tempImage.g2);
+
+				Graphics4.begin(Base.expa.g4);
+				Graphics4.setPipeline(Base.pipeMerge);
+				Graphics4.setTexture(Base.tex0, l1.texpaint);
+				Graphics4.setTexture(Base.tex1, empty);
+				Graphics4.setTexture(Base.texmask, mask);
+				Graphics4.setTexture(Base.texa, Base.tempImage);
+				Graphics4.setFloat(Base.opac, SlotLayer.getOpacity(l1));
+				Graphics4.setInt(Base.blending, layers.length > 1 ? l1.blending : 0);
+				Graphics4.setVertexBuffer(ConstData.screenAlignedVB);
+				Graphics4.setIndexBuffer(ConstData.screenAlignedIB);
+				Graphics4.drawIndexedVertices();
+				Graphics4.end();
 			}
 
 			if (l1.paintNor) {
-				Base.tempImage.g2.begin(false);
+				Graphics2.begin(Base.tempImage.g2, false);
 				Base.tempImage.g2.pipeline = Base.pipeCopy;
-				Base.tempImage.g2.drawImage(Base.expb, 0, 0);
+				Graphics2.drawImage(Base.expb, 0, 0);
 				Base.tempImage.g2.pipeline = null;
-				Base.tempImage.g2.end();
-
-				Base.expb.g4.begin();
-				Base.expb.g4.setPipeline(Base.pipeMerge);
-				Base.expb.g4.setTexture(Base.tex0, l1.texpaint);
-				Base.expb.g4.setTexture(Base.tex1, l1.texpaint_nor);
-				Base.expb.g4.setTexture(Base.texmask, mask);
-				Base.expb.g4.setTexture(Base.texa, Base.tempImage);
-				Base.expb.g4.setFloat(Base.opac, SlotLayer.getOpacity(l1));
-				Base.expb.g4.setInt(Base.blending, l1.paintNorBlend ? -2 : -1);
-				Base.expb.g4.setVertexBuffer(ConstData.screenAlignedVB);
-				Base.expb.g4.setIndexBuffer(ConstData.screenAlignedIB);
-				Base.expb.g4.drawIndexedVertices();
-				Base.expb.g4.end();
+				Graphics2.end(Base.tempImage.g2);
+
+				Graphics4.begin(Base.expb.g4);
+				Graphics4.setPipeline(Base.pipeMerge);
+				Graphics4.setTexture(Base.tex0, l1.texpaint);
+				Graphics4.setTexture(Base.tex1, l1.texpaint_nor);
+				Graphics4.setTexture(Base.texmask, mask);
+				Graphics4.setTexture(Base.texa, Base.tempImage);
+				Graphics4.setFloat(Base.opac, SlotLayer.getOpacity(l1));
+				Graphics4.setInt(Base.blending, l1.paintNorBlend ? -2 : -1);
+				Graphics4.setVertexBuffer(ConstData.screenAlignedVB);
+				Graphics4.setIndexBuffer(ConstData.screenAlignedIB);
+				Graphics4.drawIndexedVertices();
+				Graphics4.end();
 			}
 
 			if (l1.paintOcc || l1.paintRough || l1.paintMet || l1.paintHeight) {
-				Base.tempImage.g2.begin(false);
+				Graphics2.begin(Base.tempImage.g2, false);
 				Base.tempImage.g2.pipeline = Base.pipeCopy;
-				Base.tempImage.g2.drawImage(Base.expc, 0, 0);
+				Graphics2.drawImage(Base.expc, 0, 0);
 				Base.tempImage.g2.pipeline = null;
-				Base.tempImage.g2.end();
+				Graphics2.end(Base.tempImage.g2);
 
 				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
-		Base.expa.g2.begin(false);
-		Base.expa.g2.end();
-		Base.expb.g2.begin(false);
-		Base.expb.g2.end();
-		Base.expc.g2.begin(false);
-		Base.expc.g2.end();
+		Graphics2.begin(Base.expa.g2, false);
+		Graphics2.end(Base.expa.g2);
+		Graphics2.begin(Base.expb.g2, false);
+		Graphics2.end(Base.expb.g2);
+		Graphics2.begin(Base.expc.g2, false);
+		Graphics2.end(Base.expc.g2);
 		///end
 		///end
 
@@ -281,9 +281,9 @@ class ExportTexture {
 
 		for (let t of preset.textures) {
 			for (let c of t.channels) {
-				if      ((c == "base_r" || c == "base_g" || c == "base_b" || c == "opac") && pixpaint == null) pixpaint = texpaint.getPixels();
-				else if ((c == "nor_r" || c == "nor_g" || c == "nor_g_directx" || c == "nor_b" || c == "emis" || c == "subs") && pixpaint_nor == null) pixpaint_nor = texpaint_nor.getPixels();
-				else if ((c == "occ" || c == "rough" || c == "metal" || c == "height" || c == "smooth") && pixpaint_pack == null) pixpaint_pack = texpaint_pack.getPixels();
+				if      ((c == "base_r" || c == "base_g" || c == "base_b" || c == "opac") && pixpaint == null) pixpaint = Image.getPixels(texpaint);
+				else if ((c == "nor_r" || c == "nor_g" || c == "nor_g_directx" || c == "nor_b" || c == "emis" || c == "subs") && pixpaint_nor == null) pixpaint_nor = Image.getPixels(texpaint_nor);
+				else if ((c == "occ" || c == "rough" || c == "metal" || c == "height" || c == "smooth") && pixpaint_pack == null) pixpaint_pack = Image.getPixels(texpaint_pack);
 			}
 		}
 

+ 25 - 25
base/Sources/ImportArm.ts

@@ -178,17 +178,17 @@ class ImportArm {
 				let rts = RenderPath.renderTargets;
 				let _texpaint_blend0 = rts.get("texpaint_blend0").image;
 				Base.notifyOnNextFrame(() => {
-					_texpaint_blend0.unload();
+					Image.unload(_texpaint_blend0);
 				});
-				rts.get("texpaint_blend0").raw.width = Config.getTextureResX();
-				rts.get("texpaint_blend0").raw.height = Config.getTextureResY();
+				rts.get("texpaint_blend0").width = Config.getTextureResX();
+				rts.get("texpaint_blend0").height = Config.getTextureResY();
 				rts.get("texpaint_blend0").image = Image.createRenderTarget(Config.getTextureResX(), Config.getTextureResY(), TextureFormat.R8, DepthStencilFormat.NoDepthAndStencil);
 				let _texpaint_blend1 = rts.get("texpaint_blend1").image;
 				Base.notifyOnNextFrame(() => {
-					_texpaint_blend1.unload();
+					Image.unload(_texpaint_blend1);
 				});
-				rts.get("texpaint_blend1").raw.width = Config.getTextureResX();
-				rts.get("texpaint_blend1").raw.height = Config.getTextureResY();
+				rts.get("texpaint_blend1").width = Config.getTextureResX();
+				rts.get("texpaint_blend1").height = Config.getTextureResY();
 				rts.get("texpaint_blend1").image = Image.createRenderTarget(Config.getTextureResX(), Config.getTextureResY(), TextureFormat.R8, DepthStencilFormat.NoDepthAndStencil);
 				Context.raw.brushBlendDirty = true;
 			}
@@ -214,45 +214,45 @@ class ImportArm {
 				if (!isGroup) {
 					if (Base.pipeMerge == null) Base.makePipe();
 
-					let _texpaint: Image = null;
+					let _texpaint: ImageRaw = null;
 
 					///if is_paint
-					let _texpaint_nor: Image = null;
-					let _texpaint_pack: Image = null;
+					let _texpaint_nor: ImageRaw = null;
+					let _texpaint_pack: ImageRaw = null;
 					///end
 
 					if (isMask) {
 						_texpaint = Image.fromBytes(Lz4.decode(ld.texpaint, ld.res * ld.res * 4), ld.res, ld.res, TextureFormat.RGBA32);
-						l.texpaint.g2.begin(false);
+						Graphics2.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
-						l.texpaint.g2.drawImage(_texpaint, 0, 0);
+						Graphics2.drawImage(_texpaint, 0, 0);
 						l.texpaint.g2.pipeline = null;
-						l.texpaint.g2.end();
+						Graphics2.end(l.texpaint.g2);
 					}
 					else { // Layer
 						// TODO: create render target from bytes
 						_texpaint = Image.fromBytes(Lz4.decode(ld.texpaint, ld.res * ld.res * 4 * bytesPerPixel), ld.res, ld.res, format);
-						l.texpaint.g2.begin(false);
+						Graphics2.begin(l.texpaint.g2, false);
 						l.texpaint.g2.pipeline = project.is_bgra ? Base.pipeCopyBGRA : Base.pipeCopy;
-						l.texpaint.g2.drawImage(_texpaint, 0, 0);
+						Graphics2.drawImage(_texpaint, 0, 0);
 						l.texpaint.g2.pipeline = null;
-						l.texpaint.g2.end();
+						Graphics2.end(l.texpaint.g2);
 
 						///if is_paint
 						_texpaint_nor = Image.fromBytes(Lz4.decode(ld.texpaint_nor, ld.res * ld.res * 4 * bytesPerPixel), ld.res, ld.res, format);
-						l.texpaint_nor.g2.begin(false);
+						Graphics2.begin(l.texpaint_nor.g2, false);
 						l.texpaint_nor.g2.pipeline = project.is_bgra ? Base.pipeCopyBGRA : Base.pipeCopy;
-						l.texpaint_nor.g2.drawImage(_texpaint_nor, 0, 0);
+						Graphics2.drawImage(_texpaint_nor, 0, 0);
 						l.texpaint_nor.g2.pipeline = null;
-						l.texpaint_nor.g2.end();
+						Graphics2.end(l.texpaint_nor.g2);
 
 						_texpaint_pack = Image.fromBytes(Lz4.decode(ld.texpaint_pack, ld.res * ld.res * 4 * bytesPerPixel), ld.res, ld.res, format);
-						l.texpaint_pack.g2.begin(false);
+						Graphics2.begin(l.texpaint_pack.g2, false);
 						l.texpaint_pack.g2.pipeline = project.is_bgra ? Base.pipeCopyBGRA : Base.pipeCopy;
-						l.texpaint_pack.g2.drawImage(_texpaint_pack, 0, 0);
+						Graphics2.drawImage(_texpaint_pack, 0, 0);
 						l.texpaint_pack.g2.pipeline = null;
-						l.texpaint_pack.g2.end();
+						Graphics2.end(l.texpaint_pack.g2);
 						///end
 					}
 
@@ -279,10 +279,10 @@ class ImportArm {
 					///end
 
 					Base.notifyOnNextFrame(() => {
-						_texpaint.unload();
+						Image.unload(_texpaint);
 						///if is_paint
-						if (_texpaint_nor != null) _texpaint_nor.unload();
-						if (_texpaint_pack != null) _texpaint_pack.unload();
+						if (_texpaint_nor != null) Image.unload(_texpaint_nor);
+						if (_texpaint_pack != null) Image.unload(_texpaint_pack);
 						///end
 					});
 				}
@@ -595,7 +595,7 @@ class ImportArm {
 				if (!Project.packedAssetExists(Project.raw.packed_assets, pa.name)) {
 					Project.raw.packed_assets.push(pa);
 				}
-				Image.fromEncodedBytes(pa.bytes, pa.name.endsWith(".jpg") ? ".jpg" : ".png", (image: Image) => {
+				Image.fromEncodedBytes(pa.bytes, pa.name.endsWith(".jpg") ? ".jpg" : ".png", (image: ImageRaw) => {
 					Data.cachedImages.set(abs, image);
 				}, null, false);
 				break;

+ 29 - 29
base/Sources/ImportEnvmap.ts

@@ -1,31 +1,31 @@
 
 class ImportEnvmap {
 
-	static pipeline: PipelineState = null;
+	static pipeline: PipelineStateRaw = null;
 	static paramsLocation: ConstantLocation;
 	static params = Vec4.create();
 	static n = Vec4.create();
 	static radianceLocation: TextureUnit;
-	static radiance: Image = null;
-	static radianceCpu: Image = null;
-	static mips: Image[] = null;
-	static mipsCpu: Image[] = null;
+	static radiance: ImageRaw = null;
+	static radianceCpu: ImageRaw = null;
+	static mips: ImageRaw[] = null;
+	static mipsCpu: ImageRaw[] = null;
 
-	static run = (path: string, image: Image) => {
+	static run = (path: string, image: ImageRaw) => {
 
 		// Init
 		if (ImportEnvmap.pipeline == null) {
-			ImportEnvmap.pipeline = new PipelineState();
+			ImportEnvmap.pipeline = PipelineState.create();
 			ImportEnvmap.pipeline.vertexShader = System.getShader("pass.vert");
 			ImportEnvmap.pipeline.fragmentShader = System.getShader("prefilter_envmap.frag");
-			let vs = new VertexStructure();
-			vs.add("pos", VertexData.F32_2X);
+			let vs = VertexStructure.create();
+			VertexStructure.add(vs, "pos", VertexData.F32_2X);
 			ImportEnvmap.pipeline.inputLayout = [vs];
 			ImportEnvmap.pipeline.colorAttachmentCount = 1;
 			ImportEnvmap.pipeline.colorAttachments[0] = TextureFormat.RGBA128;
-			ImportEnvmap.pipeline.compile();
-			ImportEnvmap.paramsLocation = ImportEnvmap.pipeline.getConstantLocation("params");
-			ImportEnvmap.radianceLocation = ImportEnvmap.pipeline.getTextureUnit("radiance");
+			PipelineState.compile(ImportEnvmap.pipeline);
+			ImportEnvmap.paramsLocation = PipelineState.getConstantLocation(ImportEnvmap.pipeline, "params");
+			ImportEnvmap.radianceLocation = PipelineState.getTextureUnit(ImportEnvmap.pipeline, "radiance");
 
 			ImportEnvmap.radiance = Image.createRenderTarget(1024, 512, TextureFormat.RGBA128);
 
@@ -40,17 +40,17 @@ class ImportEnvmap {
 		}
 
 		// Down-scale to 1024x512
-		ImportEnvmap.radiance.g2.begin(false);
+		Graphics2.begin(ImportEnvmap.radiance.g2, false);
 		ImportEnvmap.radiance.g2.pipeline = Base.pipeCopy128;
-		ImportEnvmap.radiance.g2.drawScaledImage(image, 0, 0, 1024, 512);
+		Graphics2.drawScaledImage(image, 0, 0, 1024, 512);
 		ImportEnvmap.radiance.g2.pipeline = null;
-		ImportEnvmap.radiance.g2.end();
+		Graphics2.end(ImportEnvmap.radiance.g2);
 
-		let radiancePixels = ImportEnvmap.radiance.getPixels();
+		let radiancePixels = Image.getPixels(ImportEnvmap.radiance);
 		if (ImportEnvmap.radianceCpu != null) {
 			let _radianceCpu = ImportEnvmap.radianceCpu;
 			Base.notifyOnNextFrame(() => {
-				_radianceCpu.unload();
+				Image.unload(_radianceCpu);
 			});
 		}
 		ImportEnvmap.radianceCpu = Image.fromBytes(radiancePixels, ImportEnvmap.radiance.width, ImportEnvmap.radiance.height, TextureFormat.RGBA128, Usage.DynamicUsage);
@@ -61,7 +61,7 @@ class ImportEnvmap {
 				let _mip = mip;
 				Base.notifyOnNextFrame(() => {
 					///if (!krom_direct3d12) // TODO: crashes after 50+ imports
-					_mip.unload();
+					Image.unload(_mip);
 					///end
 				});
 			}
@@ -69,9 +69,9 @@ class ImportEnvmap {
 		ImportEnvmap.mipsCpu = [];
 		for (let i = 0; i < ImportEnvmap.mips.length; ++i) {
 			ImportEnvmap.getRadianceMip(ImportEnvmap.mips[i], i, ImportEnvmap.radiance);
-			ImportEnvmap.mipsCpu.push(Image.fromBytes(ImportEnvmap.mips[i].getPixels(), ImportEnvmap.mips[i].width, ImportEnvmap.mips[i].height, TextureFormat.RGBA128, Usage.DynamicUsage));
+			ImportEnvmap.mipsCpu.push(Image.fromBytes(Image.getPixels(ImportEnvmap.mips[i]), ImportEnvmap.mips[i].width, ImportEnvmap.mips[i].height, TextureFormat.RGBA128, Usage.DynamicUsage));
 		}
-		ImportEnvmap.radianceCpu.setMipmaps(ImportEnvmap.mipsCpu);
+		Image.setMipmaps(ImportEnvmap.radianceCpu, ImportEnvmap.mipsCpu);
 
 		// Irradiance
 		Scene.world._irradiance = ImportEnvmap.getSphericalHarmonics(radiancePixels, ImportEnvmap.radiance.width, ImportEnvmap.radiance.height);
@@ -91,16 +91,16 @@ class ImportEnvmap {
 		Project.raw.envmap = path;
 	}
 
-	static getRadianceMip = (mip: Image, level: i32, radiance: Image) => {
-		mip.g4.begin();
-		mip.g4.setVertexBuffer(ConstData.screenAlignedVB);
-		mip.g4.setIndexBuffer(ConstData.screenAlignedIB);
-		mip.g4.setPipeline(ImportEnvmap.pipeline);
+	static getRadianceMip = (mip: ImageRaw, level: i32, radiance: ImageRaw) => {
+		Graphics4.begin(mip.g4);
+		Graphics4.setVertexBuffer(ConstData.screenAlignedVB);
+		Graphics4.setIndexBuffer(ConstData.screenAlignedIB);
+		Graphics4.setPipeline(ImportEnvmap.pipeline);
 		ImportEnvmap.params.x = 0.1 + level / 8;
-		mip.g4.setFloat4(ImportEnvmap.paramsLocation, ImportEnvmap.params.x, ImportEnvmap.params.y, ImportEnvmap.params.z, ImportEnvmap.params.w);
-		mip.g4.setTexture(ImportEnvmap.radianceLocation, radiance);
-		mip.g4.drawIndexedVertices();
-		mip.g4.end();
+		Graphics4.setFloat4(ImportEnvmap.paramsLocation, ImportEnvmap.params.x, ImportEnvmap.params.y, ImportEnvmap.params.z, ImportEnvmap.params.w);
+		Graphics4.setTexture(ImportEnvmap.radianceLocation, radiance);
+		Graphics4.drawIndexedVertices();
+		Graphics4.end();
 	}
 
 	static reverseEquirect = (x: f32, y: f32): TVec4 => {

+ 4 - 4
base/Sources/ImportFont.ts

@@ -10,15 +10,15 @@ class ImportFont {
 				return;
 			}
 		}
-		Data.getFont(path, (font: Font) => {
-			font.init(); // Make sure font_ is ready
+		Data.getFont(path, (font: FontRaw) => {
+			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) {
 				let ar = path.split(Path.sep);
 				let name = ar[ar.length - 1];
-				let f = font.clone();
-				f.setFontIndex(i);
+				let f = Font.clone(font);
+				Font.setFontIndex(f, i);
 				let fontSlot = SlotFont.create(name, f, path);
 				fontSlots.push(fontSlot);
 			}

+ 3 - 3
base/Sources/ImportTexture.ts

@@ -14,7 +14,7 @@ class ImportTexture {
 			if (a.file == path) {
 				// Set as envmap
 				if (hdrAsEnvmap && path.toLowerCase().endsWith(".hdr")) {
-					Data.getImage(path, (image: Image) => {
+					Data.getImage(path, (image: ImageRaw) => {
 						Base.notifyOnNextFrame(() => { // Make sure file browser process did finish
 							ImportEnvmap.run(path, image);
 						});
@@ -30,7 +30,7 @@ class ImportTexture {
 		let cached = Data.cachedImages.get(path) != null; // Already loaded or pink texture for missing file
 		if (importer == null || cached) importer = ImportTexture.defaultImporter;
 
-		importer(path, (image: Image) => {
+		importer(path, (image: ImageRaw) => {
 			Data.cachedImages.set(path, image);
 			let ar = path.split(Path.sep);
 			let name = ar[ar.length - 1];
@@ -51,7 +51,7 @@ class ImportTexture {
 		});
 	}
 
-	static defaultImporter = (path: string, done: (img: Image)=>void) => {
+	static defaultImporter = (path: string, done: (img: ImageRaw)=>void) => {
 		Data.getImage(path, done);
 	}
 }

+ 22 - 22
base/Sources/LineDraw.ts

@@ -6,9 +6,9 @@ class LineDraw {
 	static mat: TMat4 = null;
 	static dim: TVec4 = null;
 
-	static vertexBuffer: VertexBuffer;
-	static indexBuffer: IndexBuffer;
-	static pipeline: PipelineState = null;
+	static vertexBuffer: VertexBufferRaw;
+	static indexBuffer: IndexBufferRaw;
+	static pipeline: PipelineStateRaw = null;
 
 	static vp: TMat4;
 	static vpID: ConstantLocation;
@@ -21,18 +21,18 @@ class LineDraw {
 	static maxIndices = LineDraw.maxLines * 6;
 	static lines = 0;
 
-	static g: Graphics4;
+	static g: Graphics4Raw;
 
-	static render = (g4: Graphics4, matrix: TMat4) => {
+	static render = (g4: Graphics4Raw, matrix: TMat4) => {
 		LineDraw.g = g4;
 		LineDraw.mat = matrix;
 		LineDraw.dim = Mat4.getScale(matrix);
 
 		if (LineDraw.pipeline == null) {
-			let structure = new VertexStructure();
-			structure.add("pos", VertexData.F32_3X);
-			structure.add("col", VertexData.F32_3X);
-			LineDraw.pipeline = new PipelineState();
+			let structure = VertexStructure.create();
+			VertexStructure.add(structure, "pos", VertexData.F32_3X);
+			VertexStructure.add(structure, "col", VertexData.F32_3X);
+			LineDraw.pipeline = PipelineState.create();
 			LineDraw.pipeline.inputLayout = [structure];
 			LineDraw.pipeline.fragmentShader = System.getShader("line.frag");
 			LineDraw.pipeline.vertexShader = System.getShader("line.vert");
@@ -44,11 +44,11 @@ class LineDraw {
 			LineDraw.pipeline.colorAttachments[1] = TextureFormat.RGBA64;
 			LineDraw.pipeline.colorAttachments[2] = TextureFormat.RGBA64;
 			LineDraw.pipeline.depthStencilAttachment = DepthStencilFormat.DepthOnly;
-			LineDraw.pipeline.compile();
-			LineDraw.vpID = LineDraw.pipeline.getConstantLocation("VP");
+			PipelineState.compile(LineDraw.pipeline);
+			LineDraw.vpID = PipelineState.getConstantLocation(LineDraw.pipeline, "VP");
 			LineDraw.vp = Mat4.identity();
-			LineDraw.vertexBuffer = new VertexBuffer(LineDraw.maxVertices, structure, Usage.DynamicUsage);
-			LineDraw.indexBuffer = new IndexBuffer(LineDraw.maxIndices, Usage.DynamicUsage);
+			LineDraw.vertexBuffer = VertexBuffer.create(LineDraw.maxVertices, structure, Usage.DynamicUsage);
+			LineDraw.indexBuffer = IndexBuffer.create(LineDraw.maxIndices, Usage.DynamicUsage);
 		}
 
 		LineDraw.begin();
@@ -170,22 +170,22 @@ class LineDraw {
 
 	static begin = () => {
 		LineDraw.lines = 0;
-		LineDraw.vbData = LineDraw.vertexBuffer.lock();
-		LineDraw.ibData = LineDraw.indexBuffer.lock();
+		LineDraw.vbData = VertexBuffer.lock(LineDraw.vertexBuffer);
+		LineDraw.ibData = IndexBuffer.lock(LineDraw.indexBuffer);
 	}
 
 	static end = () => {
-		LineDraw.vertexBuffer.unlock();
-		LineDraw.indexBuffer.unlock();
+		VertexBuffer.unlock(LineDraw.vertexBuffer);
+		IndexBuffer.unlock(LineDraw.indexBuffer);
 
-		LineDraw.g.setVertexBuffer(LineDraw.vertexBuffer);
-		LineDraw.g.setIndexBuffer(LineDraw.indexBuffer);
-		LineDraw.g.setPipeline(LineDraw.pipeline);
+		Graphics4.setVertexBuffer(LineDraw.vertexBuffer);
+		Graphics4.setIndexBuffer(LineDraw.indexBuffer);
+		Graphics4.setPipeline(LineDraw.pipeline);
 		let camera = Scene.camera;
 		Mat4.setFrom(LineDraw.vp, camera.V);
 		Mat4.multmat(LineDraw.vp, camera.P);
-		LineDraw.g.setMatrix(LineDraw.vpID, LineDraw.vp);
-		LineDraw.g.drawIndexedVertices(0, LineDraw.lines * 6);
+		Graphics4.setMatrix(LineDraw.vpID, LineDraw.vp);
+		Graphics4.drawIndexedVertices(0, LineDraw.lines * 6);
 	}
 
 	static addVbData = (i: i32, data: f32[]) => {

+ 3 - 3
base/Sources/LogicNode.ts

@@ -17,11 +17,11 @@ class LogicNode {
 		done(null);
 	}
 
-	getAsImage = (from: i32, done: (img: Image)=>void) => {
+	getAsImage = (from: i32, done: (img: ImageRaw)=>void) => {
 		done(null);
 	}
 
-	getCachedImage = (): Image => {
+	getCachedImage = (): ImageRaw => {
 		return null;
 	}
 
@@ -41,7 +41,7 @@ class LogicNodeInput {
 		this.node.get(this.from, done);
 	}
 
-	getAsImage = (done: (img: Image)=>void) => {
+	getAsImage = (done: (img: ImageRaw)=>void) => {
 		this.node.getAsImage(this.from, done);
 	}
 

+ 9 - 9
base/Sources/MakeVoxel.ts

@@ -3,10 +3,10 @@ class MakeVoxel {
 
 	///if arm_voxels
 	static run = (data: TShaderContext) => {
-		let structure = new VertexStructure();
-		structure.add("pos", VertexData.I16_4X_Normalized);
-		structure.add("nor", VertexData.I16_2X_Normalized);
-		structure.add("tex", VertexData.I16_2X_Normalized);
+		let structure = VertexStructure.create();
+		VertexStructure.add(structure, "pos", VertexData.I16_4X_Normalized);
+		VertexStructure.add(structure, "nor", VertexData.I16_2X_Normalized);
+		VertexStructure.add(structure, "tex", VertexData.I16_2X_Normalized);
 
 		let pipeState = data._pipeState;
 		pipeState.inputLayout = [structure];
@@ -16,8 +16,8 @@ class MakeVoxel {
 		// let isMesh = Context.raw.object.constructor == TMeshObject;
 		// let skin = isMesh && cast(Context.raw.object, TMeshObject).data.geom.bones != null;
 		// if (skin) {
-		// 	structure.add("bone", VertexData.I16_4X_Normalized);
-		// 	structure.add("weight", VertexData.I16_4X_Normalized);
+		// 	VertexStructure.add(structure, "bone", VertexData.I16_4X_Normalized);
+		// 	VertexStructure.add(structure, "weight", VertexData.I16_4X_Normalized);
 		// 	data.raw.vertex_elements.push({ name: "bone", data: 'short4norm' });
 		// 	data.raw.vertex_elements.push({ name: "weight", data: 'short4norm' });
 		// }
@@ -26,11 +26,11 @@ class MakeVoxel {
 		let ds = MakeMaterial.getDisplaceStrength();
 		pipeState.vertexShader = Shader.fromSource(MakeVoxel.voxelSource(), ShaderType.Vertex);
 
-		pipeState.compile();
+		PipelineState.compile(pipeState);
 		data.constants = [{ name: "W", type: "mat4", link: "_worldMatrix" }, { name: "N", type: "mat3", link: "_normalMatrix" }];
-		data._constants = [pipeState.getConstantLocation("W"), pipeState.getConstantLocation("N")];
+		data._constants = [PipelineState.getConstantLocation(pipeState, "W"), PipelineState.getConstantLocation(pipeState, "N")];
 		data.texture_units = [{ name: "texpaint_pack" }, { name: "voxels", is_image: true }];
-		data._textureUnits = [pipeState.getTextureUnit("texpaint_pack"), pipeState.getTextureUnit("voxels")];
+		data._textureUnits = [PipelineState.getTextureUnit(pipeState, "texpaint_pack"), PipelineState.getTextureUnit(pipeState, "voxels")];
 	}
 
 	static voxelSource = (): string => {

+ 1 - 1
base/Sources/Path.ts

@@ -13,7 +13,7 @@ class Path {
 	static textureFormats = ["jpg", "jpeg", "png", "tga", "bmp", "psd", "gif", "hdr", "k"];
 
 	static meshImporters = new Map<string, (s: string, f: (a: any)=>void)=>void>();
-	static textureImporters = new Map<string, (s: string, f: (img: Image)=>void)=>void>();
+	static textureImporters = new Map<string, (s: string, f: (img: ImageRaw)=>void)=>void>();
 
 	static baseColorExt = ["albedo", "alb", "basecol", "basecolor", "diffuse", "diff", "base", "bc", "d", "color", "col"];
 	static opacityExt = ["opac", "opacity", "alpha"];

+ 9 - 9
base/Sources/Project.ts

@@ -9,7 +9,7 @@ class Project {
 	static meshAssets: string[] = [];
 	static materialGroups: TNodeGroup[] = [];
 	static paintObjects: TMeshObject[] = null;
-	static assetMap = new Map<i32, any>(); // Image | Font
+	static assetMap = new Map<i32, any>(); // ImageRaw | FontRaw
 	static meshList: string[] = null;
 	///if (is_paint || is_sculpt)
 	static materials: SlotMaterialRaw[] = null;
@@ -35,11 +35,11 @@ class Project {
 			}
 
 			let current = Graphics2.current;
-			if (current != null) current.end();
+			if (current != null) Graphics2.end(current);
 
 			ImportArm.runProject(path);
 
-			if (current != null) current.begin(false);
+			if (current != null) Graphics2.begin(current, false);
 		});
 	}
 
@@ -180,11 +180,11 @@ class Project {
 
 					let imgmesh = Image.fromBytes(f32a.buffer, Config.getTextureResX(), Config.getTextureResY(), TextureFormat.RGBA128);
 					let texpaint = Project.layers[0].texpaint;
-					texpaint.g2.begin(false);
+					Graphics2.begin(texpaint.g2, false);
 					texpaint.g2.pipeline = Base.pipeCopy128;
-					texpaint.g2.drawScaledImage(imgmesh, 0, 0, Config.getTextureResX(), Config.getTextureResY());
+					Graphics2.drawScaledImage(imgmesh, 0, 0, Config.getTextureResX(), Config.getTextureResY());
 					texpaint.g2.pipeline = null;
-					texpaint.g2.end();
+					Graphics2.end(texpaint.g2);
 				});
 				///end
 			}
@@ -207,7 +207,7 @@ class Project {
 		Data.getMesh("Scene", n, (md: TMeshData) => {
 
 			let current = Graphics2.current;
-			if (current != null) current.end();
+			if (current != null) Graphics2.end(current);
 
 			///if is_paint
 			Context.raw.pickerMaskHandle.position = PickerMask.MaskNone;
@@ -288,7 +288,7 @@ class Project {
 				App.notifyOnInit(Base.initLayers);
 			}
 
-			if (current != null) current.begin(false);
+			if (current != null) Graphics2.begin(current, false);
 
 			Context.raw.savedEnvmap = null;
 			Context.raw.envmapLoaded = false;
@@ -553,7 +553,7 @@ class Project {
 		else load(asset.file);
 	}
 
-	static getImage = (asset: TAsset): Image => {
+	static getImage = (asset: TAsset): ImageRaw => {
 		return asset != null ? Project.assetMap.get(asset.id) : null;
 	}
 

+ 17 - 17
base/Sources/RenderPathBase.ts

@@ -5,7 +5,7 @@ class RenderPathBase {
 	static superSample = 1.0;
 	static lastX = -1.0;
 	static lastY = -1.0;
-	static bloomMipmaps: RenderTarget[];
+	static bloomMipmaps: RenderTargetRaw[];
 	static bloomCurrentMip = 0;
 	static bloomSampleScale: f32;
 	///if arm_voxels
@@ -23,7 +23,7 @@ class RenderPathBase {
 		RenderPathBase.voxelsCreated = true;
 
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = targetName;
 			t.format = "R8";
 			t.width = RenderPathBase.voxelsRes;
@@ -40,8 +40,8 @@ class RenderPathBase {
 		if (RenderPathBase.superSample != Config.raw.rp_supersample) {
 			RenderPathBase.superSample = Config.raw.rp_supersample;
 			for (let rt of RenderPath.renderTargets.values()) {
-				if (rt.raw.width == 0 && rt.raw.scale != null) {
-					rt.raw.scale = RenderPathBase.superSample;
+				if (rt.width == 0 && rt.scale != null) {
+					rt.scale = RenderPathBase.superSample;
 				}
 			}
 			RenderPath.resize();
@@ -55,7 +55,7 @@ class RenderPathBase {
 		return RenderPathBase.superSample;
 	}
 
-	static drawCompass = (currentG: Graphics4) => {
+	static drawCompass = (currentG: Graphics4Raw) => {
 		if (Context.raw.showCompass) {
 			let cam = Scene.camera;
 			let compass: TMeshObject = Scene.getChild(".Compass").ext;
@@ -202,7 +202,7 @@ class RenderPathBase {
 
 				let prevScale = 1.0;
 				for (let i = 0; i < 10; ++i) {
-					let t = new RenderTargetRaw();
+					let t = RenderTarget.create();
 					t.name = "bloom_mip_" + i;
 					t.width = 0;
 					t.height = 0;
@@ -232,16 +232,16 @@ class RenderPathBase {
 
 			for (let i = 0; i < numMips; ++i) {
 				RenderPathBase.bloomCurrentMip = i;
-				RenderPath.setTarget(RenderPathBase.bloomMipmaps[i].raw.name);
+				RenderPath.setTarget(RenderPathBase.bloomMipmaps[i].name);
 				RenderPath.clearTarget();
-				RenderPath.bindTarget(i == 0 ? tex : RenderPathBase.bloomMipmaps[i - 1].raw.name, "tex");
+				RenderPath.bindTarget(i == 0 ? tex : RenderPathBase.bloomMipmaps[i - 1].name, "tex");
 				RenderPath.drawShader("shader_datas/bloom_pass/bloom_downsample_pass");
 			}
 			for (let i = 0; i < numMips; ++i) {
 				let mipLevel = numMips - 1 - i;
 				RenderPathBase.bloomCurrentMip = mipLevel;
-				RenderPath.setTarget(mipLevel == 0 ? tex : RenderPathBase.bloomMipmaps[mipLevel - 1].raw.name);
-				RenderPath.bindTarget(RenderPathBase.bloomMipmaps[mipLevel].raw.name, "tex");
+				RenderPath.setTarget(mipLevel == 0 ? tex : RenderPathBase.bloomMipmaps[mipLevel - 1].name);
+				RenderPath.bindTarget(RenderPathBase.bloomMipmaps[mipLevel].name, "tex");
 				RenderPath.drawShader("shader_datas/bloom_pass/bloom_upsample_pass");
 			}
 		}
@@ -299,7 +299,7 @@ class RenderPathBase {
 
 	static initSSAO = () => {
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "singlea";
 			t.width = 0;
 			t.height = 0;
@@ -308,7 +308,7 @@ class RenderPathBase {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "singleb";
 			t.width = 0;
 			t.height = 0;
@@ -386,7 +386,7 @@ class RenderPathBase {
 		if (Config.raw.rp_ssr != false) {
 			if (RenderPath.cachedShaderContexts.get("shader_datas/ssr_pass/ssr_pass") == null) {
 				{
-					let t = new RenderTargetRaw();
+					let t = RenderTarget.create();
 					t.name = "bufb";
 					t.width = 0;
 					t.height = 0;
@@ -443,7 +443,7 @@ class RenderPathBase {
 
 	// static drawHistogram = () => {
 	// 	{
-	// 		let t = new RenderTargetRaw();
+	// 		let t = RenderTarget.create();
 	// 		t.name = "histogram";
 	// 		t.width = 1;
 	// 		t.height = 1;
@@ -551,7 +551,7 @@ class RenderPathBase {
 		let copy = RenderPath.renderTargets.get("gbuffer0_copy");
 		if (copy == null || copy.image.width != RenderPath.renderTargets.get("gbuffer0").image.width || copy.image.height != RenderPath.renderTargets.get("gbuffer0").image.height) {
 			{
-				let t = new RenderTargetRaw();
+				let t = RenderTarget.create();
 				t.name = "gbuffer0_copy";
 				t.width = 0;
 				t.height = 0;
@@ -561,7 +561,7 @@ class RenderPathBase {
 				RenderPath.createRenderTarget(t);
 			}
 			{
-				let t = new RenderTargetRaw();
+				let t = RenderTarget.create();
 				t.name = "gbuffer1_copy";
 				t.width = 0;
 				t.height = 0;
@@ -570,7 +570,7 @@ class RenderPathBase {
 				RenderPath.createRenderTarget(t);
 			}
 			{
-				let t = new RenderTargetRaw();
+				let t = RenderTarget.create();
 				t.name = "gbuffer2_copy";
 				t.width = 0;
 				t.height = 0;

+ 16 - 18
base/Sources/RenderPathDeferred.ts

@@ -5,7 +5,7 @@ class RenderPathDeferred {
 		RenderPath.createDepthBuffer("main", "DEPTH24");
 
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "gbuffer0";
 			t.width = 0;
 			t.height = 0;
@@ -15,7 +15,7 @@ class RenderPathDeferred {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "gbuffer1";
 			t.width = 0;
 			t.height = 0;
@@ -24,7 +24,7 @@ class RenderPathDeferred {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "gbuffer2";
 			t.width = 0;
 			t.height = 0;
@@ -33,7 +33,7 @@ class RenderPathDeferred {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "tex";
 			t.width = 0;
 			t.height = 0;
@@ -45,7 +45,7 @@ class RenderPathDeferred {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "buf";
 			t.width = 0;
 			t.height = 0;
@@ -60,7 +60,7 @@ class RenderPathDeferred {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "buf2";
 			t.width = 0;
 			t.height = 0;
@@ -69,7 +69,7 @@ class RenderPathDeferred {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "taa";
 			t.width = 0;
 			t.height = 0;
@@ -78,7 +78,7 @@ class RenderPathDeferred {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "taa2";
 			t.width = 0;
 			t.height = 0;
@@ -87,38 +87,36 @@ class RenderPathDeferred {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "empty_white";
 			t.width = 1;
 			t.height = 1;
 			t.format = "R8";
-			let rt = new RenderTarget(t);
 			let b = new ArrayBuffer(1);
 			let v = new DataView(b);
 			v.setUint8(0, 255);
-			rt.image = Image.fromBytes(b, t.width, t.height, TextureFormat.R8);
-			RenderPath.renderTargets.set(t.name, rt);
+			t.image = Image.fromBytes(b, t.width, t.height, TextureFormat.R8);
+			RenderPath.renderTargets.set(t.name, t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "empty_black";
 			t.width = 1;
 			t.height = 1;
 			t.format = "RGBA32";
-			let rt = new RenderTarget(t);
 			let b = new ArrayBuffer(4);
 			let v = new DataView(b);
 			v.setUint8(0, 0);
 			v.setUint8(1, 0);
 			v.setUint8(2, 0);
 			v.setUint8(3, 0);
-			rt.image = Image.fromBytes(b, t.width, t.height, TextureFormat.RGBA32);
-			RenderPath.renderTargets.set(t.name, rt);
+			t.image = Image.fromBytes(b, t.width, t.height, TextureFormat.RGBA32);
+			RenderPath.renderTargets.set(t.name, t);
 		}
 
 		///if is_sculpt
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "gbuffer0_undo";
 			t.width = 0;
 			t.height = 0;
@@ -127,7 +125,7 @@ class RenderPathDeferred {
 			RenderPath.createRenderTarget(t);
 		}
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "gbufferD_undo";
 			t.width = 0;
 			t.height = 0;

+ 4 - 4
base/Sources/RenderPathRaytrace.ts

@@ -11,10 +11,10 @@ class RenderPathRaytrace {
 	static f32a = new Float32Array(24);
 	static helpMat = Mat4.identity();
 	static vb_scale = 1.0;
-	static vb: VertexBuffer;
-	static ib: IndexBuffer;
+	static vb: VertexBufferRaw;
+	static ib: IndexBufferRaw;
 
-	static lastEnvmap: Image = null;
+	static lastEnvmap: ImageRaw = null;
 	static isBake = false;
 
 	///if krom_direct3d12
@@ -26,7 +26,7 @@ class RenderPathRaytrace {
 	///end
 
 	///if is_lab
-	static lastTexpaint: Image = null;
+	static lastTexpaint: ImageRaw = null;
 	///end
 
 	static init = () => {

+ 7 - 7
base/Sources/RenderPathRaytraceBake.ts

@@ -8,7 +8,7 @@ class RenderPathRaytraceBake {
 	static currentSample = 0;
 	static raysTimer = 0.0;
 	static raysCounter = 0;
-	static lastLayer: Image = null;
+	static lastLayer: ImageRaw = null;
 	static lastBake = 0;
 
 	static commands = (parsePaintMaterial: (b?: bool)=>void): bool => {
@@ -22,13 +22,13 @@ class RenderPathRaytraceBake {
 			RenderPathRaytraceBake.lastLayer = null;
 
 			if (RenderPath.renderTargets.get("baketex0") != null) {
-				RenderPath.renderTargets.get("baketex0").image.unload();
-				RenderPath.renderTargets.get("baketex1").image.unload();
-				RenderPath.renderTargets.get("baketex2").image.unload();
+				Image.unload(RenderPath.renderTargets.get("baketex0").image);
+				Image.unload(RenderPath.renderTargets.get("baketex1").image);
+				Image.unload(RenderPath.renderTargets.get("baketex2").image);
 			}
 
 			{
-				let t = new RenderTargetRaw();
+				let t = RenderTarget.create();
 				t.name = "baketex0";
 				t.width = Config.getTextureResX();
 				t.height = Config.getTextureResY();
@@ -36,7 +36,7 @@ class RenderPathRaytraceBake {
 				RenderPath.createRenderTarget(t);
 			}
 			{
-				let t = new RenderTargetRaw();
+				let t = RenderTarget.create();
 				t.name = "baketex1";
 				t.width = Config.getTextureResX();
 				t.height = Config.getTextureResY();
@@ -44,7 +44,7 @@ class RenderPathRaytraceBake {
 				RenderPath.createRenderTarget(t);
 			}
 			{
-				let t = new RenderTargetRaw();
+				let t = RenderTarget.create();
 				t.name = "baketex2";
 				t.width = Config.getTextureResX();
 				t.height = Config.getTextureResY();

+ 7 - 7
base/Sources/Res.ts

@@ -1,12 +1,12 @@
 
 class Res {
 
-	static bundled: Map<string, Image> = new Map();
+	static bundled: Map<string, ImageRaw> = new Map();
 
 	static load = (names: string[], done: ()=>void) => {
 		let loaded = 0;
 		for (let s of names) {
-			Data.getImage(s, (image: Image) => {
+			Data.getImage(s, (image: ImageRaw) => {
 				Res.bundled.set(s, image);
 				loaded++;
 				if (loaded == names.length) done();
@@ -14,21 +14,21 @@ class Res {
 		}
 	}
 
-	static get = (name: string): Image => {
+	static get = (name: string): ImageRaw => {
 		return Res.bundled.get(name);
 	}
 
-	static tile50 = (img: Image, x: i32, y: i32): TRect => {
+	static tile50 = (img: ImageRaw, x: i32, y: i32): TRect => {
 		let size = Config.raw.window_scale > 1 ? 100 : 50;
 		return { x: x * size, y: y * size, w: size, h: size };
 	}
 
-	static tile25 = (img: Image, x: i32, y: i32): TRect => {
+	static tile25 = (img: ImageRaw, x: i32, y: i32): TRect => {
 		let size = Config.raw.window_scale > 1 ? 50 : 25;
 		return { x: x * size, y: y * size, w: size, h: size };
 	}
 
-	static tile18 = (img: Image, x: i32, y: i32): TRect => {
+	static tile18 = (img: ImageRaw, x: i32, y: i32): TRect => {
 		let size = Config.raw.window_scale > 1 ? 36 : 18;
 		return { x: x * size, y: img.height - (y + 1) * size, w: size, h: size };
 	}
@@ -45,7 +45,7 @@ class Res {
 	}
 
 	static embedFont = (name: string, file: ArrayBuffer) => {
-		Data.cachedFonts.set(name, new Font(file));
+		Data.cachedFonts.set(name, Font.create(file));
 	}
 	///end
 }

+ 1 - 1
base/Sources/TabConsole.ts

@@ -51,7 +51,7 @@ class TabConsole {
 
 			let _font = ui.font;
 			let _fontSize = ui.fontSize;
-			Data.getFont("font_mono.ttf", (f: Font) => { ui.setFont(f); }); // Sync
+			Data.getFont("font_mono.ttf", (f: FontRaw) => { ui.setFont(f); }); // Sync
 			ui.fontSize = Math.floor(15 * ui.SCALE());
 			for (let t of Console.lastTraces) {
 				ui.text(t);

+ 6 - 6
base/Sources/TabMaterials.ts

@@ -110,12 +110,12 @@ class TabMaterials {
 				if (!isTyping) {
 					if (i < 9 && Operator.shortcut(Config.keymap.select_material, ShortcutType.ShortcutDown)) {
 						let number = String(i + 1);
-						let width = ui.font.width(ui.fontSize, number) + 10;
-						let height = ui.font.height(ui.fontSize);
+						let width = Font.width(ui.font, ui.fontSize, number) + 10;
+						let height = Font.height(ui.font, ui.fontSize);
 						ui.g.color = ui.t.TEXT_COL;
-						ui.g.fillRect(uix, uiy, width, height);
+						Graphics2.fillRect(uix, uiy, width, height);
 						ui.g.color = ui.t.ACCENT_COL;
-						ui.g.drawString(number, uix + 5, uiy);
+						Graphics2.drawString(number, uix + 5, uiy);
 					}
 				}
 
@@ -265,11 +265,11 @@ class TabMaterials {
 	static buttonNew = (text: string) => {
 		let ui = UIBase.ui;
 		if (ui.button(text)) {
-			ui.g.end();
+			Graphics2.end(ui.g);
 			Context.raw.material = SlotMaterial.create(Project.materials[0].data);
 			Project.materials.push(Context.raw.material);
 			TabMaterials.updateMaterial();
-			ui.g.begin(false);
+			Graphics2.begin(ui.g, false);
 			History.newMaterial();
 		}
 	}

+ 1 - 1
base/Sources/TabScript.ts

@@ -49,7 +49,7 @@ class TabScript {
 
 			let _font = ui.font;
 			let _fontSize = ui.fontSize;
-			Data.getFont("font_mono.ttf", (f: Font) => { ui.setFont(f); }); // Sync
+			Data.getFont("font_mono.ttf", (f: FontRaw) => { ui.setFont(f); }); // Sync
 			ui.fontSize = Math.floor(15 * ui.SCALE());
 			Zui.textAreaLineNumbers = true;
 			Zui.textAreaScrollPastEnd = true;

+ 3 - 3
base/Sources/TabSwatches.ts

@@ -1,13 +1,13 @@
 
 class TabSwatches {
 
-	static _empty: Image;
+	static _empty: ImageRaw;
 
-	static set empty(image: Image) {
+	static set empty(image: ImageRaw) {
 		TabSwatches._empty = image;
 	}
 
-	static get empty(): Image {
+	static get empty(): ImageRaw {
 		if (TabSwatches._empty == null) {
 			let b = new Uint8Array(4);
 			b[0] = 255;

+ 5 - 5
base/Sources/TabTextures.ts

@@ -120,17 +120,17 @@ class TabTextures {
 											///end
 
 											let target = Image.createRenderTarget(TabTextures.to_pow2(img.width), TabTextures.to_pow2(img.height));
-											target.g2.begin(false);
+											Graphics2.begin(target.g2, false);
 											target.g2.pipeline = Base.pipeCopy;
-											target.g2.drawScaledImage(img, 0, 0, target.width, target.height);
+											Graphics2.drawScaledImage(img, 0, 0, target.width, target.height);
 											target.g2.pipeline = null;
-											target.g2.end();
+											Graphics2.end(target.g2);
 											Base.notifyOnNextFrame(() => {
 												let f = UIFiles.filename;
 												if (f == "") f = tr("untitled");
 												if (!f.endsWith(".png")) f += ".png";
-												Krom.writePng(path + Path.sep + f, target.getPixels(), target.width, target.height, 0);
-												target.unload();
+												Krom.writePng(path + Path.sep + f, Image.getPixels(target), target.width, target.height, 0);
+												Image.unload(target);
 											});
 										});
 									});

+ 2 - 2
base/Sources/Translator.ts

@@ -114,11 +114,11 @@ class Translator {
 		Graphics2.fontGlyphs.sort((a: i32, b: i32) => { return a - b; });
 		// Load and assign font with cjk characters
 		App.notifyOnInit(() => {
-			Data.getFont(fontPath, (f: Font) => {
+			Data.getFont(fontPath, (f: FontRaw) => {
 				if (cjk) {
 					let acjkFontIndices = Translator.cjkFontIndices as any;
 					let fontIndex = Translator.cjkFontIndices.has(Config.raw.locale) ? acjkFontIndices[Config.raw.locale] : 0;
-					f.setFontIndex(fontIndex);
+					Font.setFontIndex(f, fontIndex);
 				}
 				Base.font = f;
 				// Scale up the font size and elements width a bit

+ 29 - 29
base/Sources/UIBase.ts

@@ -1083,12 +1083,12 @@ class UIBase {
 				let target = l.texpaint_preview;
 				let source = l.texpaint;
 				let g2 = target.g2;
-				g2.begin(true, 0x00000000);
+				Graphics2.begin(g2, true, 0x00000000);
 				// g2.pipeline = l.isMask() ? Base.pipeCopy8 : Base.pipeCopy;
 				g2.pipeline = Base.pipeCopy; // texpaint_preview is always RGBA32 for now
-				g2.drawScaledImage(source, 0, 0, target.width, target.height);
+				Graphics2.drawScaledImage(source, 0, 0, target.width, target.height);
 				g2.pipeline = null;
-				g2.end();
+				Graphics2.end(g2);
 			}
 			UIBase.hwnds[TabArea.TabSidebar0].redraws = 2;
 		}
@@ -1101,12 +1101,12 @@ class UIBase {
 			let target = l.texpaint_preview;
 			let source = l.texpaint;
 			let g2 = target.g2;
-			g2.begin(true, 0x00000000);
+			Graphics2.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.drawScaledImage(source, 0, 0, target.width, target.height);
+			Graphics2.drawScaledImage(source, 0, 0, target.width, target.height);
 			g2.pipeline = null;
-			g2.end();
+			Graphics2.end(g2);
 			UIBase.hwnds[TabArea.TabSidebar0].redraws = 2;
 		}
 		///end
@@ -1131,10 +1131,10 @@ class UIBase {
 		///end
 	}
 
-	static render = (g: Graphics2) => {
+	static render = (g: Graphics2Raw) => {
 		if (!UIBase.show && Config.raw.touch_ui) {
 			UIBase.ui.inputEnabled = true;
-			g.end();
+			Graphics2.end(g);
 			UIBase.ui.begin(g);
 			if (UIBase.ui.window(Zui.handle("uibase_2"), 0, 0, 150, Math.floor(UIBase.ui.ELEMENT_H() + UIBase.ui.ELEMENT_OFFSET() + 1))) {
 				if (UIBase.ui.button(tr("Close"))) {
@@ -1142,7 +1142,7 @@ class UIBase {
 				}
 			}
 			UIBase.ui.end();
-			g.begin(false);
+			Graphics2.begin(g, false);
 		}
 
 		if (!UIBase.show || System.width == 0 || System.height == 0) return;
@@ -1162,7 +1162,7 @@ class UIBase {
 			UIBase.htabs[i].position = Config.raw.layout_tabs[i];
 		}
 
-		g.end();
+		Graphics2.end(g);
 		UIBase.ui.begin(g);
 
 		///if (is_paint || is_sculpt)
@@ -1177,7 +1177,7 @@ class UIBase {
 		///end
 
 		UIBase.ui.end();
-		g.begin(false);
+		Graphics2.begin(g, false);
 	}
 
 	///if (is_paint || is_sculpt)
@@ -1221,7 +1221,7 @@ class UIBase {
 
 		// Expand button
 		if (Config.raw.layout[LayoutSize.LayoutSidebarW] == 0) {
-			let width = Math.floor(UIBase.ui.font.width(UIBase.ui.fontSize, "<<") + 25 * UIBase.ui.SCALE());
+			let width = Math.floor(Font.width(UIBase.ui.font, UIBase.ui.fontSize, "<<") + 25 * UIBase.ui.SCALE());
 			if (UIBase.ui.window(UIBase.hminimized, System.width - width, 0, width, Math.floor(UIBase.ui.ELEMENT_H() + UIBase.ui.ELEMENT_OFFSET() + 1))) {
 				UIBase.ui._w = width;
 				let _BUTTON_H = UIBase.ui.t.BUTTON_H;
@@ -1246,7 +1246,7 @@ class UIBase {
 		Context.raw.lastHtab0Position = UIBase.htabs[TabArea.TabSidebar0].position;
 	}
 
-	static renderCursor = (g: Graphics2) => {
+	static renderCursor = (g: Graphics2Raw) => {
 		if (!Base.uiEnabled) return;
 
 		///if is_paint
@@ -1281,25 +1281,25 @@ class UIBase {
 				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));
-				g.drawScaledImage(Context.raw.brushStencilImage, r.x, r.y, r.w, r.h);
+				Graphics2.drawScaledImage(Context.raw.brushStencilImage, r.x, r.y, r.w, r.h);
 				g.transformation = null;
 				g.color = 0xffffffff;
 			}
 			let transform = Operator.shortcut(Config.keymap.stencil_transform, ShortcutType.ShortcutDown);
 			if (transform) {
 				// Outline
-				g.drawRect(r.x, r.y, r.w, r.h);
+				Graphics2.drawRect(r.x, r.y, r.w, r.h);
 				// Scale
-				g.drawRect(r.x - 8,       r.y - 8,       16, 16);
-				g.drawRect(r.x - 8 + r.w, r.y - 8,       16, 16);
-				g.drawRect(r.x - 8,       r.y - 8 + r.h, 16, 16);
-				g.drawRect(r.x - 8 + r.w, r.y - 8 + r.h, 16, 16);
+				Graphics2.drawRect(r.x - 8,       r.y - 8,       16, 16);
+				Graphics2.drawRect(r.x - 8 + r.w, r.y - 8,       16, 16);
+				Graphics2.drawRect(r.x - 8,       r.y - 8 + r.h, 16, 16);
+				Graphics2.drawRect(r.x - 8 + r.w, r.y - 8 + r.h, 16, 16);
 				// Rotate
 				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));
-				g.fillCircle(r.x + r.w / 2, r.y - 4, 8);
+				Graphics2.fillCircle(r.x + r.w / 2, r.y - 4, 8);
 				g.transformation = null;
 			}
 		}
@@ -1309,15 +1309,15 @@ class UIBase {
 		if (Context.raw.tool == WorkspaceTool.ToolPicker && Context.raw.pickerSelectMaterial && Context.raw.colorPickerCallback == null) {
 			let img = Context.raw.material.imageIcon;
 			///if krom_opengl
-			g.drawScaledImage(img, mx + 10, my + 10 + img.height, img.width, -img.height);
+			Graphics2.drawScaledImage(img, mx + 10, my + 10 + img.height, img.width, -img.height);
 			///else
-			g.drawImage(img, mx + 10, my + 10);
+			Graphics2.drawImage(img, mx + 10, my + 10);
 			///end
 		}
 		if (Context.raw.tool == WorkspaceTool.ToolPicker && Context.raw.colorPickerCallback != null) {
 			let img = Res.get("icons.k");
 			let rect = Res.tile50(img, WorkspaceTool.ToolPicker, 0);
-			g.drawSubImage(img, mx + 10, my + 10, rect.x, rect.y, rect.w, rect.h);
+			Graphics2.drawSubImage(img, mx + 10, my + 10, rect.x, rect.y, rect.w, rect.h);
 		}
 
 		let cursorImg = Res.get("cursor.k");
@@ -1326,7 +1326,7 @@ class UIBase {
 		// Clone source cursor
 		if (Context.raw.tool == WorkspaceTool.ToolClone && !Keyboard.down("alt") && (Mouse.down() || Pen.down())) {
 			g.color = 0x66ffffff;
-			g.drawScaledImage(cursorImg, mx + Context.raw.cloneDeltaX * App.w() - psize / 2, my + Context.raw.cloneDeltaY * App.h() - psize / 2, psize, psize);
+			Graphics2.drawScaledImage(cursorImg, mx + Context.raw.cloneDeltaX * App.w() - psize / 2, my + Context.raw.cloneDeltaY * App.h() - psize / 2, psize, psize);
 			g.color = 0xffffffff;
 		}
 
@@ -1363,9 +1363,9 @@ class UIBase {
 					let cy = decalY + psizey / 2;
 					g.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)
-					g.drawScaledImage(Context.raw.decalImage, decalX, decalY, psizex, psizey);
+					Graphics2.drawScaledImage(Context.raw.decalImage, decalX, decalY, psizex, psizey);
 					///else
-					g.drawScaledImage(Context.raw.decalImage, decalX, decalY + psizey, psizex, -psizey);
+					Graphics2.drawScaledImage(Context.raw.decalImage, decalX, decalY + psizey, psizex, -psizey);
 					///end
 					g.transformation = null;
 					g.color = 0xffffffff;
@@ -1385,7 +1385,7 @@ class UIBase {
 				if (Config.raw.brush_3d && Context.in2dView()) {
 					psize = Math.floor(psize * UIView2D.panScale);
 				}
-				g.drawScaledImage(cursorImg, mx - psize / 2, my - psize / 2, psize, psize);
+				Graphics2.drawScaledImage(cursorImg, mx - psize / 2, my - psize / 2, psize, psize);
 			}
 		}
 
@@ -1398,12 +1398,12 @@ class UIBase {
 			 Context.raw.tool == WorkspaceTool.ToolBlur ||
 			 Context.raw.tool == WorkspaceTool.ToolSmudge ||
 			 Context.raw.tool == WorkspaceTool.ToolParticle)) {
-			g.fillRect(mx - 1, my - 1, 2, 2);
+			Graphics2.fillRect(mx - 1, my - 1, 2, 2);
 			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;
-			g.drawScaledImage(cursorImg, mx - radius / 2, my - radius / 2, radius, radius);
+			Graphics2.drawScaledImage(cursorImg, mx - radius / 2, my - radius / 2, radius, radius);
 			g.color = 0xffffffff;
 		}
 	}

+ 8 - 8
base/Sources/UIBox.ts

@@ -17,7 +17,7 @@ class UIBox {
 	static tweenAlpha = 0.0;
 	///end
 
-	static render = (g: Graphics2) => {
+	static render = (g: Graphics2Raw) => {
 		if (!UIMenu.show) {
 			let ui = Base.uiBox;
 			let inUse = ui.comboSelectedHandle_ptr != null;
@@ -45,10 +45,10 @@ class UIBox {
 			///else
 			g.color = color_from_floats(0, 0, 0, 0.5);
 			///end
-			g.fillRect(0, 0, System.width, System.height);
+			Graphics2.fillRect(0, 0, System.width, System.height);
 		}
 
-		g.end();
+		Graphics2.end(g);
 
 		let ui = Base.uiBox;
 		let appw = System.width;
@@ -105,7 +105,7 @@ class UIBox {
 			ui.end();
 		}
 
-		g.begin(false);
+		Graphics2.begin(g, false);
 
 		UIBox.draws++;
 	}
@@ -176,12 +176,12 @@ class UIBox {
 	static windowBorder = (ui: Zui) => {
 		if (ui.scissor) {
 			ui.scissor = false;
-			ui.g.disableScissor();
+			Graphics2.disableScissor(ui.g);
 		}
 		// Border
 		ui.g.color = ui.t.SEPARATOR_COL;
-		ui.g.fillRect(0, 0, 1, ui._windowH);
-		ui.g.fillRect(0 + ui._windowW - 1, 0, 1, ui._windowH);
-		ui.g.fillRect(0, 0 + ui._windowH - 1, ui._windowW, 1);
+		Graphics2.fillRect(0, 0, 1, ui._windowH);
+		Graphics2.fillRect(0 + ui._windowW - 1, 0, 1, ui._windowH);
+		Graphics2.fillRect(0, 0 + ui._windowH - 1, ui._windowW, 1);
 	}
 }

+ 15 - 15
base/Sources/UIFiles.ts

@@ -18,7 +18,7 @@ class UIFiles {
 	static lastPath = "";
 	static lastSearch = "";
 	static files: string[] = null;
-	static iconMap: Map<string, Image> = null;
+	static iconMap: Map<string, ImageRaw> = null;
 	static selected = -1;
 	static showExtensions = false;
 	static offline = false;
@@ -158,7 +158,7 @@ class UIFiles {
 				let uiy = ui._y;
 				let state = State.Idle;
 				let generic = true;
-				let icon: Image = null;
+				let icon: ImageRaw = null;
 
 				if (isCloud && f != ".." && !UIFiles.offline) {
 					if (UIFiles.iconMap == null) UIFiles.iconMap = new Map();
@@ -171,24 +171,24 @@ class UIFiles {
 							UIFiles.iconMap.set(handle.text + Path.sep + f, empty);
 							File.cacheCloud(handle.text + Path.sep + iconFile, (abs: string) => {
 								if (abs != null) {
-									Data.getImage(abs, (image: Image) => {
+									Data.getImage(abs, (image: ImageRaw) => {
 										App.notifyOnInit(() => {
 											if (Base.pipeCopyRGB == null) Base.makePipeCopyRGB();
 											icon = Image.createRenderTarget(image.width, image.height);
 											if (f.endsWith(".arm")) { // Used for material sphere alpha cutout
-												icon.g2.begin(false);
+												Graphics2.begin(icon.g2, false);
 
 												///if (is_paint || is_sculpt)
-												icon.g2.drawImage(Project.materials[0].image, 0, 0);
+												Graphics2.drawImage(Project.materials[0].image, 0, 0);
 												///end
 											}
 											else {
-												icon.g2.begin(true, 0xffffffff);
+												Graphics2.begin(icon.g2, true, 0xffffffff);
 											}
 											icon.g2.pipeline = Base.pipeCopyRGB;
-											icon.g2.drawImage(image, 0, 0);
+											Graphics2.drawImage(image, 0, 0);
 											icon.g2.pipeline = null;
-											icon.g2.end();
+											Graphics2.end(icon.g2);
 											UIFiles.iconMap.set(handle.text + Path.sep + f, icon);
 											UIBase.hwnds[TabArea.TabStatus].redraws = 3;
 										});
@@ -279,17 +279,17 @@ class UIFiles {
 					if (icon == null) {
 						let empty = RenderPath.renderTargets.get("empty_black").image;
 						UIFiles.iconMap.set(shandle, empty);
-						Data.getImage(shandle, (image: Image) => {
+						Data.getImage(shandle, (image: ImageRaw) => {
 							App.notifyOnInit(() => {
 								if (Base.pipeCopyRGB == null) Base.makePipeCopyRGB();
 								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.createRenderTarget(sw, sh);
-								icon.g2.begin(true, 0xffffffff);
+								Graphics2.begin(icon.g2, true, 0xffffffff);
 								icon.g2.pipeline = Base.pipeCopyRGB;
-								icon.g2.drawScaledImage(image, 0, 0, sw, sh);
+								Graphics2.drawScaledImage(image, 0, 0, sw, sh);
 								icon.g2.pipeline = null;
-								icon.g2.end();
+								Graphics2.end(icon.g2);
 								UIFiles.iconMap.set(shandle, icon);
 								UIBase.hwnds[TabArea.TabStatus].redraws = 3;
 								Data.deleteImage(shandle); // The big image is not needed anymore
@@ -358,7 +358,7 @@ class UIFiles {
 				ui._y += slotw * 0.75;
 				let label0 = (UIFiles.showExtensions || f.indexOf(".") <= 0) ? f : f.substr(0, f.lastIndexOf("."));
 				let label1 = "";
-				while (label0.length > 0 && ui.font.width(ui.fontSize, label0) > ui._w - 6) { // 2 line split
+				while (label0.length > 0 && Font.width(ui.font, ui.fontSize, label0) > ui._w - 6) { // 2 line split
 					label1 = label0.charAt(label0.length - 1) + label1;
 					label0 = label0.substr(0, label0.length - 1);
 				}
@@ -367,10 +367,10 @@ class UIFiles {
 				if (ui.isHovered) ui.tooltip(label0 + label1);
 				if (label1 != "") { // Second line
 					ui._x = _x;
-					ui._y += ui.font.height(ui.fontSize);
+					ui._y += Font.height(ui.font, ui.fontSize);
 					ui.text(label1, Align.Center);
 					if (ui.isHovered) ui.tooltip(label0 + label1);
-					ui._y -= ui.font.height(ui.fontSize);
+					ui._y -= Font.height(ui.font, ui.fontSize);
 				}
 
 				ui._y -= slotw * 0.75;

+ 15 - 15
base/Sources/UIHeader.ts

@@ -9,7 +9,7 @@ class UIHeader {
 	constructor() {
 	}
 
-	static renderUI = (g: Graphics2) => {
+	static renderUI = (g: Graphics2Raw) => {
 		let ui = UIBase.ui;
 		if (Config.raw.touch_ui) {
 			UIHeader.headerh = UIHeader.defaultHeaderH + 6;
@@ -81,14 +81,14 @@ class UIHeader {
 				let _next = () => {
 					if (Base.pipeMerge == null) Base.makePipe();
 					if (ConstData.screenAlignedVB == null) ConstData.createScreenAlignedData();
-					m.texpaint.g4.begin();
-					m.texpaint.g4.setPipeline(Base.pipeColorIdToMask);
-					m.texpaint.g4.setTexture(Base.texpaintColorId, RenderPath.renderTargets.get("texpaint_colorid").image);
-					m.texpaint.g4.setTexture(Base.texColorId, Project.getImage(Project.assets[Context.raw.colorIdHandle.position]));
-					m.texpaint.g4.setVertexBuffer(ConstData.screenAlignedVB);
-					m.texpaint.g4.setIndexBuffer(ConstData.screenAlignedIB);
-					m.texpaint.g4.drawIndexedVertices();
-					m.texpaint.g4.end();
+					Graphics4.begin(m.texpaint.g4);
+					Graphics4.setPipeline(Base.pipeColorIdToMask);
+					Graphics4.setTexture(Base.texpaintColorId, RenderPath.renderTargets.get("texpaint_colorid").image);
+					Graphics4.setTexture(Base.texColorId, Project.getImage(Project.assets[Context.raw.colorIdHandle.position]));
+					Graphics4.setVertexBuffer(ConstData.screenAlignedVB);
+					Graphics4.setIndexBuffer(ConstData.screenAlignedIB);
+					Graphics4.drawIndexedVertices();
+					Graphics4.end();
 					Context.raw.colorIdPicked = false;
 					UIToolbar.toolbarHandle.redraws = 1;
 					UIHeader.headerHandle.redraws = 1;
@@ -311,9 +311,9 @@ class UIHeader {
 				Context.raw.brushScale = ui.slider(brushScaleHandle, tr("UV Scale"), 0.01, 5.0, true);
 				if (brushScaleHandle.changed) {
 					if (Context.raw.tool == WorkspaceTool.ToolDecal || Context.raw.tool == WorkspaceTool.ToolText) {
-						ui.g.end();
+						Graphics2.end(ui.g);
 						UtilRender.makeDecalPreview();
-						ui.g.begin(false);
+						Graphics2.begin(ui.g, false);
 					}
 				}
 
@@ -378,10 +378,10 @@ class UIHeader {
 				ui._w = w;
 
 				if (h.changed) {
-					ui.g.end();
+					Graphics2.end(ui.g);
 					UtilRender.makeTextPreview();
 					UtilRender.makeDecalPreview();
-					ui.g.begin(false);
+					Graphics2.begin(ui.g, false);
 				}
 			}
 
@@ -389,10 +389,10 @@ class UIHeader {
 				ui.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) {
-						ui.g.end();
+						Graphics2.end(ui.g);
 						// UtilUV.cacheUVMap();
 						UtilUV.cacheTriangleMap();
-						ui.g.begin(false);
+						Graphics2.begin(ui.g, false);
 						// wireframeHandle.selected = drawWireframe = true;
 					}
 					MakeMaterial.parsePaintMaterial();

+ 15 - 15
base/Sources/UIMenu.ts

@@ -13,7 +13,7 @@ class UIMenu {
 	static showMenuFirst = true;
 	static hideMenu = false;
 
-	static render = (g: Graphics2) => {
+	static render = (g: Graphics2Raw) => {
 		let ui = Base.uiMenu;
 		let menuW = UIMenu.menuCommands != null ? Math.floor(Base.defaultElementW * Base.uiMenu.SCALE() * 2.3) : Math.floor(ui.ELEMENT_W() * 2.3);
 		let _BUTTON_COL = ui.t.BUTTON_COL;
@@ -221,9 +221,9 @@ class UIMenu {
 				UIMenu.menuFill(ui);
 				Context.raw.drawWireframe = ui.check(Context.raw.wireframeHandle, " " + tr("Wireframe"));
 				if (Context.raw.wireframeHandle.changed) {
-					ui.g.end();
+					Graphics2.end(ui.g);
 					UtilUV.cacheUVMap();
-					ui.g.begin(false);
+					Graphics2.begin(ui.g, false);
 					MakeMaterial.parseMeshMaterial();
 				}
 				///end
@@ -483,7 +483,7 @@ class UIMenu {
 						let tabVertical = Config.raw.touch_ui;
 						if (ui.tab(Zui.handle("uimenu_13"), tr("About"), tabVertical)) {
 
-							Data.getImage("badge.k", (img: Image) => {
+							Data.getImage("badge.k", (img: ImageRaw) => {
 								ui.image(img);
 								ui.endElement();
 							});
@@ -568,9 +568,9 @@ class UIMenu {
 
 	static menuFill = (ui: Zui) => {
 		ui.g.color = ui.t.ACCENT_SELECT_COL;
-		ui.g.fillRect(ui._x - 1, ui._y, ui._w + 2, ui.ELEMENT_H() + 1 + 1);
+		Graphics2.fillRect(ui._x - 1, ui._y, ui._w + 2, ui.ELEMENT_H() + 1 + 1);
 		ui.g.color = ui.t.SEPARATOR_COL;
-		ui.g.fillRect(ui._x, ui._y, ui._w, ui.ELEMENT_H() + 1);
+		Graphics2.fillRect(ui._x, ui._y, ui._w, ui.ELEMENT_H() + 1);
 		ui.g.color = 0xffffffff;
 	}
 
@@ -608,17 +608,17 @@ class UIMenu {
 		// Draw top border
 		ui.g.color = ui.t.ACCENT_SELECT_COL;
 		if (Config.raw.touch_ui) {
-			ui.g.fillRect(ui._x + ui._w / 2 + UIMenu.menuCategoryW / 2, ui._y - 1, ui._w / 2 - UIMenu.menuCategoryW / 2 + 1, 1);
-			ui.g.fillRect(ui._x - 1, ui._y - 1, ui._w / 2 - UIMenu.menuCategoryW / 2 + 1, 1);
-			ui.g.fillRect(ui._x + ui._w / 2 - UIMenu.menuCategoryW / 2, ui._y - UIMenu.menuCategoryH, UIMenu.menuCategoryW, 1);
-			ui.g.fillRect(ui._x + ui._w / 2 - UIMenu.menuCategoryW / 2, ui._y - UIMenu.menuCategoryH, 1, UIMenu.menuCategoryH);
-			ui.g.fillRect(ui._x + ui._w / 2 + UIMenu.menuCategoryW / 2, ui._y - UIMenu.menuCategoryH, 1, UIMenu.menuCategoryH);
+			Graphics2.fillRect(ui._x + ui._w / 2 + UIMenu.menuCategoryW / 2, ui._y - 1, ui._w / 2 - UIMenu.menuCategoryW / 2 + 1, 1);
+			Graphics2.fillRect(ui._x - 1, ui._y - 1, ui._w / 2 - UIMenu.menuCategoryW / 2 + 1, 1);
+			Graphics2.fillRect(ui._x + ui._w / 2 - UIMenu.menuCategoryW / 2, ui._y - UIMenu.menuCategoryH, UIMenu.menuCategoryW, 1);
+			Graphics2.fillRect(ui._x + ui._w / 2 - UIMenu.menuCategoryW / 2, ui._y - UIMenu.menuCategoryH, 1, UIMenu.menuCategoryH);
+			Graphics2.fillRect(ui._x + ui._w / 2 + UIMenu.menuCategoryW / 2, ui._y - UIMenu.menuCategoryH, 1, UIMenu.menuCategoryH);
 		}
 		else {
-			ui.g.fillRect(ui._x - 1 + UIMenu.menuCategoryW, ui._y - 1, ui._w + 2 - UIMenu.menuCategoryW, 1);
-			ui.g.fillRect(ui._x - 1, ui._y - UIMenu.menuCategoryH, UIMenu.menuCategoryW, 1);
-			ui.g.fillRect(ui._x - 1, ui._y - UIMenu.menuCategoryH, 1, UIMenu.menuCategoryH);
-			ui.g.fillRect(ui._x - 1 + UIMenu.menuCategoryW, ui._y - UIMenu.menuCategoryH, 1, UIMenu.menuCategoryH);
+			Graphics2.fillRect(ui._x - 1 + UIMenu.menuCategoryW, ui._y - 1, ui._w + 2 - UIMenu.menuCategoryW, 1);
+			Graphics2.fillRect(ui._x - 1, ui._y - UIMenu.menuCategoryH, UIMenu.menuCategoryW, 1);
+			Graphics2.fillRect(ui._x - 1, ui._y - UIMenu.menuCategoryH, 1, UIMenu.menuCategoryH);
+			Graphics2.fillRect(ui._x - 1 + UIMenu.menuCategoryW, ui._y - UIMenu.menuCategoryH, 1, UIMenu.menuCategoryH);
 		}
 		ui.g.color = 0xffffffff;
 	}

+ 1 - 1
base/Sources/UIMenubar.ts

@@ -14,7 +14,7 @@ class UIMenubar {
 	constructor() {
 	}
 
-	static renderUI = (g: Graphics2) => {
+	static renderUI = (g: Graphics2Raw) => {
 		let ui = UIBase.ui;
 
 		///if (is_paint || is_sculpt)

+ 16 - 16
base/Sources/UINodes.ts

@@ -32,7 +32,7 @@ class UINodes {
 	static releaseLink = false;
 	static isNodeMenuOperation = false;
 
-	static grid: Image = null;
+	static grid: ImageRaw = null;
 	static hwnd = new Handle();
 	static groupStack: TNodeGroup[] = [];
 	static controlsDown = false;
@@ -589,30 +589,30 @@ class UINodes {
 		if (w < 1) w = 1;
 		if (h < 1) h = 1;
 		UINodes.grid = Image.createRenderTarget(w, h);
-		UINodes.grid.g2.begin(true, UINodes.ui.t.SEPARATOR_COL);
+		Graphics2.begin(UINodes.grid.g2, true, UINodes.ui.t.SEPARATOR_COL);
 
 		UINodes.grid.g2.color = UINodes.ui.t.SEPARATOR_COL - 0x00050505;
 		step = 20 * UINodes.ui.SCALE();
 		for (let i = 0; i < Math.floor(h / step) + 1; ++i) {
-			UINodes.grid.g2.drawLine(0, i * step, w, i * step);
+			Graphics2.drawLine(0, i * step, w, i * step);
 		}
 		for (let i = 0; i < Math.floor(w / step) + 1; ++i) {
-			UINodes.grid.g2.drawLine(i * step, 0, i * step, h);
+			Graphics2.drawLine(i * step, 0, i * step, h);
 		}
 
 		UINodes.grid.g2.color = UINodes.ui.t.SEPARATOR_COL - 0x00090909;
 		step = 100 * UINodes.ui.SCALE();
 		for (let i = 0; i < Math.floor(h / step) + 1; ++i) {
-			UINodes.grid.g2.drawLine(0, i * step, w, i * step);
+			Graphics2.drawLine(0, i * step, w, i * step);
 		}
 		for (let i = 0; i < Math.floor(w / step) + 1; ++i) {
-			UINodes.grid.g2.drawLine(i * step, 0, i * step, h);
+			Graphics2.drawLine(i * step, 0, i * step, h);
 		}
 
-		UINodes.grid.g2.end();
+		Graphics2.end(UINodes.grid.g2);
 	}
 
-	static render = (g: Graphics2) => {
+	static render = (g: Graphics2Raw) => {
 		if (UINodes.recompileMat) {
 			///if (is_paint || is_sculpt)
 			if (UINodes.canvasType == CanvasType.CanvasBrush) {
@@ -683,7 +683,7 @@ class UINodes {
 
 		UINodes.ui.inputEnabled = Base.uiEnabled;
 
-		g.end();
+		Graphics2.end(g);
 
 		if (UINodes.grid == null) UINodes.drawGrid();
 
@@ -735,7 +735,7 @@ class UINodes {
 			// Grid
 			UINodes.ui.g.color = 0xffffffff;
 			let step = 100 * UINodes.ui.SCALE();
-			UINodes.ui.g.drawImage(UINodes.grid, (nodes.panX * nodes.SCALE()) % step - step, (nodes.panY * nodes.SCALE()) % step - step);
+			Graphics2.drawImage(UINodes.grid, (nodes.panX * nodes.SCALE()) % step - step, (nodes.panY * nodes.SCALE()) % step - step);
 
 			// Undo
 			if (UINodes.ui.inputStarted || UINodes.ui.isKeyPressed) {
@@ -832,7 +832,7 @@ class UINodes {
 
 			// Node previews
 			if (Config.raw.node_preview && nodes.nodesSelectedId.length > 0) {
-				let img: Image = null;
+				let img: ImageRaw = null;
 				let sel = nodes.getNode(c.nodes, nodes.nodesSelectedId[0]);
 
 				///if (is_paint || is_sculpt)
@@ -895,8 +895,8 @@ class UINodes {
 
 					UINodes.ui.g.color = 0xffffffff;
 					invertY ?
-						UINodes.ui.g.drawScaledImage(img, tx, ty + th, tw, -th) :
-						UINodes.ui.g.drawScaledImage(img, tx, ty, tw, th);
+						Graphics2.drawScaledImage(img, tx, ty + th, tw, -th) :
+						Graphics2.drawScaledImage(img, tx, ty, tw, th);
 
 					///if (is_paint || is_sculpt)
 					if  (singleChannel) {
@@ -908,7 +908,7 @@ class UINodes {
 
 			// Menu
 			UINodes.ui.g.color = UINodes.ui.t.SEPARATOR_COL;
-			UINodes.ui.g.fillRect(0, UINodes.ui.ELEMENT_H(), UINodes.ww, UINodes.ui.ELEMENT_H() + UINodes.ui.ELEMENT_OFFSET() * 2);
+			Graphics2.fillRect(0, UINodes.ui.ELEMENT_H(), UINodes.ww, UINodes.ui.ELEMENT_H() + UINodes.ui.ELEMENT_OFFSET() * 2);
 			UINodes.ui.g.color = 0xffffffff;
 
 			let startY = UINodes.ui.ELEMENT_H() + UINodes.ui.ELEMENT_OFFSET();
@@ -920,7 +920,7 @@ class UINodes {
 			// Editable canvas name
 			let h = Zui.handle("uinodes_11");
 			h.text = c.name;
-			UINodes.ui._w = Math.floor(Math.min(UINodes.ui.font.width(UINodes.ui.fontSize, h.text) + 15 * UINodes.ui.SCALE(), 100 * UINodes.ui.SCALE()));
+			UINodes.ui._w = Math.floor(Math.min(Font.width(UINodes.ui.font, UINodes.ui.fontSize, h.text) + 15 * UINodes.ui.SCALE(), 100 * UINodes.ui.SCALE()));
 			let newName = UINodes.ui.textInput(h, "");
 			UINodes.ui._x += UINodes.ui._w + 3;
 			UINodes.ui._y = 2 + startY;
@@ -1018,7 +1018,7 @@ class UINodes {
 
 		UINodes.ui.end(!UINodes.showMenu);
 
-		g.begin(false);
+		Graphics2.begin(g, false);
 
 		if (UINodes.showMenu) {
 			///if (is_paint || is_sculpt)

+ 3 - 3
base/Sources/UIStatus.ts

@@ -15,7 +15,7 @@ class UIStatus {
 		///end
 	}
 
-	static renderUI = (g: Graphics2) => {
+	static renderUI = (g: Graphics2Raw) => {
 		let ui = UIBase.ui;
 
 		let statush = Config.raw.layout[LayoutSize.LayoutStatusH];
@@ -25,8 +25,8 @@ class UIStatus {
 
 			// Border
 			ui.g.color = ui.t.SEPARATOR_COL;
-			ui.g.fillRect(0, 0, 1, ui._windowH);
-			ui.g.fillRect(ui._windowW - 1, 0, 1, ui._windowH);
+			Graphics2.fillRect(0, 0, 1, ui._windowH);
+			Graphics2.fillRect(ui._windowW - 1, 0, 1, ui._windowH);
 
 			// Draw tabs
 			for (let draw of UIBase.hwndTabs[TabArea.TabStatus]) draw(UIBase.htabs[TabArea.TabStatus]);

+ 3 - 3
base/Sources/UIToolbar.ts

@@ -29,7 +29,7 @@ class UIToolbar {
 	constructor() {
 	}
 
-	static renderUI = (g: Graphics2) => {
+	static renderUI = (g: Graphics2Raw) => {
 		let ui = UIBase.ui;
 
 		if (Config.raw.touch_ui) {
@@ -68,7 +68,7 @@ class UIToolbar {
 				ui.t.ELEMENT_H = Math.floor(ui.t.ELEMENT_H * 1.5);
 				ui.t.BUTTON_H = ui.t.ELEMENT_H;
 				ui.t.BUTTON_COL = ui.t.WINDOW_BG_COL;
-				let fontHeight = ui.font.height(ui.fontSize);
+				let fontHeight = Font.height(ui.font, ui.fontSize);
 				ui.fontOffsetY = (ui.ELEMENT_H() - fontHeight) / 2;
 				let _w = ui._w;
 				ui._w = UIToolbar.toolbarw;
@@ -124,7 +124,7 @@ class UIToolbar {
 
 				///if is_paint
 				if (i == WorkspaceTool.ToolColorId && Context.raw.colorIdPicked) {
-					ui.g.drawScaledSubImage(RenderPath.renderTargets.get("texpaint_colorid").image, 0, 0, 1, 1, 0, _y + 1.5 * ui.SCALE(), 5 * ui.SCALE(), 34 * ui.SCALE());
+					Graphics2.drawScaledSubImage(RenderPath.renderTargets.get("texpaint_colorid").image, 0, 0, 1, 1, 0, _y + 1.5 * ui.SCALE(), 5 * ui.SCALE(), 34 * ui.SCALE());
 				}
 				///end
 

+ 34 - 34
base/Sources/UIView2D.ts

@@ -2,7 +2,7 @@
 class UIView2D {
 
 	///if (is_paint || is_sculpt)
-	static pipe: PipelineState;
+	static pipe: PipelineStateRaw;
 	static channelLocation: ConstantLocation;
 	static textInputHover = false;
 	static uvmapShow = false;
@@ -31,19 +31,19 @@ class UIView2D {
 
 	constructor() {
 		///if (is_paint || is_sculpt)
-		UIView2D.pipe = new PipelineState();
+		UIView2D.pipe = PipelineState.create();
 		UIView2D.pipe.vertexShader = System.getShader("layer_view.vert");
 		UIView2D.pipe.fragmentShader = System.getShader("layer_view.frag");
-		let vs = new VertexStructure();
-		vs.add("pos", VertexData.F32_3X);
-		vs.add("tex", VertexData.F32_2X);
-		vs.add("col", VertexData.U8_4X_Normalized);
+		let vs = VertexStructure.create();
+		VertexStructure.add(vs, "pos", VertexData.F32_3X);
+		VertexStructure.add(vs, "tex", VertexData.F32_2X);
+		VertexStructure.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.compile();
-		UIView2D.channelLocation = UIView2D.pipe.getConstantLocation("channel");
+		PipelineState.compile(UIView2D.pipe);
+		UIView2D.channelLocation = PipelineState.getConstantLocation(UIView2D.pipe, "channel");
 		///end
 
 		let scale = Config.raw.window_scale;
@@ -51,7 +51,7 @@ class UIView2D {
 		UIView2D.ui.scrollEnabled = false;
 	}
 
-	static render = (g: Graphics2) => {
+	static render = (g: Graphics2Raw) => {
 
 		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
 
-		g.end();
+		Graphics2.end(g);
 
 		// Cache grid
 		if (UINodes.grid == null) UINodes.drawGrid();
@@ -107,10 +107,10 @@ class UIView2D {
 
 			// Grid
 			UIView2D.ui.g.color = 0xffffffff;
-			UIView2D.ui.g.drawImage(UINodes.grid, (UIView2D.panX * UIView2D.panScale) % 100 - 100, (UIView2D.panY * UIView2D.panScale) % 100 - 100);
+			Graphics2.drawImage(UINodes.grid, (UIView2D.panX * UIView2D.panScale) % 100 - 100, (UIView2D.panY * UIView2D.panScale) % 100 - 100);
 
 			// Texture
-			let tex: Image = null;
+			let tex: ImageRaw = null;
 
 			///if (is_paint || is_sculpt)
 			let l = Context.raw.layer;
@@ -152,15 +152,15 @@ class UIView2D {
 
 				if (UIView2D.layerMode == View2DLayerMode.View2DVisible) {
 					let current = Graphics2.current;
-					if (current != null) current.end();
+					if (current != null) Graphics2.end(current);
 					layer = Base.flatten();
-					if (current != null) current.begin(false);
+					if (current != null) Graphics2.begin(current, false);
 				}
 				else if (SlotLayer.isGroup(layer)) {
 					let current = Graphics2.current;
-					if (current != null) current.end();
+					if (current != null) Graphics2.end(current);
 					layer = Base.flatten(false, SlotLayer.getChildren(layer));
-					if (current != null) current.begin(false);
+					if (current != null) Graphics2.begin(current, false);
 				}
 
 				tex =
@@ -205,17 +205,17 @@ class UIView2D {
 				}
 				///end
 
-				UIView2D.ui.g.drawScaledImage(tex, tx, ty, tw, th);
+				Graphics2.drawScaledImage(tex, tx, ty, tw, th);
 
 				if (UIView2D.tiledShow) {
-					UIView2D.ui.g.drawScaledImage(tex, tx - tw, ty, tw, th);
-					UIView2D.ui.g.drawScaledImage(tex, tx - tw, ty - th, tw, th);
-					UIView2D.ui.g.drawScaledImage(tex, tx - tw, ty + th, tw, th);
-					UIView2D.ui.g.drawScaledImage(tex, tx + tw, ty, tw, th);
-					UIView2D.ui.g.drawScaledImage(tex, tx + tw, ty - th, tw, th);
-					UIView2D.ui.g.drawScaledImage(tex, tx + tw, ty + th, tw, th);
-					UIView2D.ui.g.drawScaledImage(tex, tx, ty - th, tw, th);
-					UIView2D.ui.g.drawScaledImage(tex, tx, ty + th, tw, th);
+					Graphics2.drawScaledImage(tex, tx - tw, ty, tw, th);
+					Graphics2.drawScaledImage(tex, tx - tw, ty - th, tw, th);
+					Graphics2.drawScaledImage(tex, tx - tw, ty + th, tw, th);
+					Graphics2.drawScaledImage(tex, tx + tw, ty, tw, th);
+					Graphics2.drawScaledImage(tex, tx + tw, ty - th, tw, th);
+					Graphics2.drawScaledImage(tex, tx + tw, ty + th, tw, th);
+					Graphics2.drawScaledImage(tex, tx, ty - th, tw, th);
+					Graphics2.drawScaledImage(tex, tx, ty + th, tw, th);
 				}
 
 				///if (is_paint || is_sculpt)
@@ -233,10 +233,10 @@ class UIView2D {
 					Base.notifyOnNextFrame(() => {
 						let texpaint_picker = RenderPath.renderTargets.get("texpaint_picker").image;
 						let g2 = texpaint_picker.g2;
-						g2.begin(false);
-						g2.drawScaledImage(tex, -x, -y, tw, th);
-						g2.end();
-						let a = new DataView(texpaint_picker.getPixels());
+						Graphics2.begin(g2, false);
+						Graphics2.drawScaledImage(tex, -x, -y, tw, th);
+						Graphics2.end(g2);
+						let a = new DataView(Image.getPixels(texpaint_picker));
 						///if (krom_metal || krom_vulkan)
 						let i0 = 2;
 						let i1 = 1;
@@ -259,14 +259,14 @@ class UIView2D {
 			///if (is_paint || is_sculpt)
 			// UV map
 			if (UIView2D.type == View2DType.View2DLayer && UIView2D.uvmapShow) {
-				UIView2D.ui.g.drawScaledImage(UtilUV.uvmap, tx, ty, tw, th);
+				Graphics2.drawScaledImage(UtilUV.uvmap, tx, ty, tw, th);
 			}
 			///end
 
 			// Menu
 			let ew = Math.floor(UIView2D.ui.ELEMENT_W());
 			UIView2D.ui.g.color = UIView2D.ui.t.SEPARATOR_COL;
-			UIView2D.ui.g.fillRect(0, UIView2D.ui.ELEMENT_H(), UIView2D.ww, UIView2D.ui.ELEMENT_H() + UIView2D.ui.ELEMENT_OFFSET() * 2);
+			Graphics2.fillRect(0, UIView2D.ui.ELEMENT_H(), UIView2D.ww, UIView2D.ui.ELEMENT_H() + UIView2D.ui.ELEMENT_OFFSET() * 2);
 			UIView2D.ui.g.color = 0xffffffff;
 
 			let startY = UIView2D.ui.ELEMENT_H() + UIView2D.ui.ELEMENT_OFFSET();
@@ -283,7 +283,7 @@ class UIView2D {
 			let text = h.text;
 			///end
 
-			UIView2D.ui._w = Math.floor(Math.min(UIView2D.ui.font.width(UIView2D.ui.fontSize, text) + 15 * UIView2D.ui.SCALE(), 100 * UIView2D.ui.SCALE()));
+			UIView2D.ui._w = Math.floor(Math.min(Font.width(UIView2D.ui.font, UIView2D.ui.fontSize, text) + 15 * UIView2D.ui.SCALE(), 100 * UIView2D.ui.SCALE()));
 
 			if (UIView2D.type == View2DType.View2DAsset) {
 				let asset = Context.raw.texture;
@@ -370,12 +370,12 @@ class UIView2D {
 				let cursorImg = Res.get("cursor.k");
 				let hsize = 16 * UIView2D.ui.SCALE();
 				let size = hsize * 2;
-				UIView2D.ui.g.drawScaledImage(cursorImg, tx + tw * Context.raw.uvxPicked - hsize, ty + th * Context.raw.uvyPicked - hsize, size, size);
+				Graphics2.drawScaledImage(cursorImg, tx + tw * Context.raw.uvxPicked - hsize, ty + th * Context.raw.uvyPicked - hsize, size, size);
 			}
 			///end
 		}
 		UIView2D.ui.end();
-		g.begin(false);
+		Graphics2.begin(g, false);
 	}
 
 	static update = () => {

+ 1 - 1
base/Sources/UniformsExt.ts

@@ -332,7 +332,7 @@ class UniformsExt {
 		return null;
 	}
 
-	static linkTex = (object: TBaseObject, mat: TMaterialData, link: string): Image => {
+	static linkTex = (object: TBaseObject, mat: TMaterialData, link: string): ImageRaw => {
 		switch (link) {
 			case "_texpaint_undo": {
 				///if (is_paint || is_sculpt)

+ 17 - 17
base/Sources/UtilMesh.ts

@@ -120,8 +120,8 @@ class UtilMesh {
 			}
 
 			let g = o.data;
-			let l = g._struct.byteSize() / 2;
-			let vertices = g._vertexBuffer.lock(); // posnortex
+			let l = VertexStructure.byteSize(g._struct) / 2;
+			let vertices = VertexBuffer.lock(g._vertexBuffer); // posnortex
 			for (let i = 0; i < Math.floor(vertices.byteLength / 2 / l); ++i) {
 				vertices.setInt16((i * l    ) * 2, vas[0].values[i * 4    ], true);
 				vertices.setInt16((i * l + 1) * 2, vas[0].values[i * 4 + 1], true);
@@ -130,7 +130,7 @@ class UtilMesh {
 				vertices.setInt16((i * l + 4) * 2, vas[1].values[i * 2    ], true);
 				vertices.setInt16((i * l + 5) * 2, vas[1].values[i * 2 + 1], true);
 			}
-			g._vertexBuffer.unlock();
+			VertexBuffer.unlock(g._vertexBuffer);
 		}
 
 		UtilMesh.removeMergedMesh();
@@ -144,8 +144,8 @@ class UtilMesh {
 			let va0 = vas[0].values;
 			let va1 = vas[1].values;
 			let g = o.data;
-			let l = g._struct.byteSize() / 2;
-			let vertices = g._vertexBuffer.lock(); // posnortex
+			let l = VertexStructure.byteSize(g._struct) / 2;
+			let vertices = VertexBuffer.lock(g._vertexBuffer); // posnortex
 			for (let i = 0; i < Math.floor(vertices.byteLength / 2 / l); ++i) {
 				va0[i * 4 + 3] = -va0[i * 4 + 3];
 				va1[i * 2] = -va1[i * 2];
@@ -154,7 +154,7 @@ class UtilMesh {
 				vertices.setInt16((i * l + 4) * 2, -vertices.getInt16((i * l + 4) * 2, true), true);
 				vertices.setInt16((i * l + 5) * 2, -vertices.getInt16((i * l + 5) * 2, true), true);
 			}
-			g._vertexBuffer.unlock();
+			VertexBuffer.unlock(g._vertexBuffer);
 		}
 
 		///if (krom_direct3d12 || krom_vulkan || krom_metal)
@@ -171,9 +171,9 @@ class UtilMesh {
 		let objects = Project.paintObjects;
 		for (let o of objects) {
 			let g = o.data;
-			let l = g._struct.byteSize() / 2;
+			let l = VertexStructure.byteSize(g._struct) / 2;
 			let inda = g._indices[0];
-			let vertices = g._vertexBuffer.lock(); // posnortex
+			let vertices = VertexBuffer.lock(g._vertexBuffer); // posnortex
 			for (let i = 0; i < Math.floor(inda.length / 3); ++i) {
 				let i1 = inda[i * 3    ];
 				let i2 = inda[i * 3 + 1];
@@ -240,7 +240,7 @@ class UtilMesh {
 					}
 				}
 			}
-			g._vertexBuffer.unlock();
+			VertexBuffer.unlock(g._vertexBuffer);
 
 			let va0 = o.data.vertex_arrays[0].values;
 			let va1 = o.data.vertex_arrays[1].values;
@@ -306,27 +306,27 @@ class UtilMesh {
 				va[i * 4 + 2] = Math.floor((va[i * 4 + 2] * sc - dz) / maxScale * 32767);
 			}
 
-			let l = g._struct.byteSize() / 2;
-			let vertices = g._vertexBuffer.lock(); // posnortex
+			let l = VertexStructure.byteSize(g._struct) / 2;
+			let vertices = VertexBuffer.lock(g._vertexBuffer); // posnortex
 			for (let i = 0; i < Math.floor(vertices.byteLength / 2 / l); ++i) {
 				vertices.setInt16((i * l    ) * 2, va[i * 4    ], true);
 				vertices.setInt16((i * l + 1) * 2, va[i * 4 + 1], true);
 				vertices.setInt16((i * l + 2) * 2, va[i * 4 + 2], true);
 			}
-			g._vertexBuffer.unlock();
+			VertexBuffer.unlock(g._vertexBuffer);
 		}
 
 		UtilMesh.mergeMesh();
 	}
 
-	static applyDisplacement = (texpaint_pack: Image, strength = 0.1, uvScale = 1.0) => {
-		let height = texpaint_pack.getPixels();
+	static applyDisplacement = (texpaint_pack: ImageRaw, strength = 0.1, uvScale = 1.0) => {
+		let height = Image.getPixels(texpaint_pack);
 		let heightView = new DataView(height);
 		let res = texpaint_pack.width;
 		let o = Project.paintObjects[0];
 		let g = o.data;
-		let l = g._struct.byteSize() / 2;
-		let vertices = g._vertexBuffer.lock(); // posnortex
+		let l = VertexStructure.byteSize(g._struct) / 2;
+		let vertices = VertexBuffer.lock(g._vertexBuffer); // posnortex
 		for (let i = 0; i < Math.floor(vertices.byteLength / 2 / l); ++i) {
 			let x = Math.floor(vertices.getInt16((i * l + 6) * 2, true) / 32767 * res);
 			let y = Math.floor(vertices.getInt16((i * l + 7) * 2, true) / 32767 * res);
@@ -337,7 +337,7 @@ class UtilMesh {
 			vertices.setInt16((i * l + 1) * 2, vertices.getInt16((i * l + 1) * 2, true) - Math.floor(vertices.getInt16((i * l + 5) * 2, true) * h), true);
 			vertices.setInt16((i * l + 2) * 2, vertices.getInt16((i * l + 2) * 2, true) - Math.floor(vertices.getInt16((i * l + 3) * 2, true) * h), true);
 		}
-		g._vertexBuffer.unlock();
+		VertexBuffer.unlock(g._vertexBuffer);
 
 		let va0 = o.data.vertex_arrays[0].values;
 		for (let i = 0; i < Math.floor(vertices.byteLength / 4 / l); ++i) {

+ 1 - 1
base/Sources/UtilParticle.ts

@@ -35,7 +35,7 @@ class UtilParticle {
 		];
 
 		{
-			let t = new RenderTargetRaw();
+			let t = RenderTarget.create();
 			t.name = "texparticle";
 			t.width = 0;
 			t.height = 0;

+ 42 - 42
base/Sources/UtilRender.ts

@@ -6,8 +6,8 @@ class UtilRender {
 	static materialPreviewSize = 256;
 	static decalPreviewSize = 512;
 	static layerPreviewSize = 200;
-	static screenAlignedFullVB: VertexBuffer = null;
-	static screenAlignedFullIB: IndexBuffer = null;
+	static screenAlignedFullVB: VertexBufferRaw = null;
+	static screenAlignedFullIB: IndexBufferRaw = null;
 
 	static makeMaterialPreview = () => {
 		Context.raw.materialPreview = true;
@@ -80,7 +80,7 @@ class UtilRender {
 
 	static makeDecalPreview = () => {
 		let current = Graphics2.current;
-		if (current != null) current.end();
+		if (current != null) Graphics2.end(current);
 
 		if (Context.raw.decalImage == null) {
 			Context.raw.decalImage = Image.createRenderTarget(UtilRender.decalPreviewSize, UtilRender.decalPreviewSize);
@@ -141,22 +141,22 @@ class UtilRender {
 		MakeMaterial.parseMeshMaterial();
 		Context.raw.ddirty = 1; // Refresh depth for decal paint
 
-		if (current != null) current.begin(false);
+		if (current != null) Graphics2.begin(current, false);
 	}
 
 	static makeTextPreview = () => {
 		let current = Graphics2.current;
-		if (current != null) current.end();
+		if (current != null) Graphics2.end(current);
 
 		let text = Context.raw.textToolText;
 		let font = Context.raw.font.font;
 		let fontSize = 200;
-		let textW = Math.floor(font.width(fontSize, text));
-		let textH = Math.floor(font.height(fontSize));
+		let textW = Math.floor(Font.width(font, fontSize, text));
+		let textH = Math.floor(Font.height(font, fontSize));
 		let texW = textW + 32;
 		if (texW < 512) texW = 512;
 		if (Context.raw.textToolImage != null && Context.raw.textToolImage.width < texW) {
-			Context.raw.textToolImage.unload();
+			Image.unload(Context.raw.textToolImage);
 			Context.raw.textToolImage = null;
 		}
 		if (Context.raw.textToolImage == null) {
@@ -167,38 +167,38 @@ class UtilRender {
 			///end
 		}
 		let g2 = Context.raw.textToolImage.g2;
-		g2.begin(true, 0xff000000);
+		Graphics2.begin(g2, true, 0xff000000);
 		g2.font = font;
 		g2.fontSize = fontSize;
 		g2.color = 0xffffffff;
-		g2.drawString(text, texW / 2 - textW / 2, texW / 2 - textH / 2);
-		g2.end();
+		Graphics2.drawString(text, texW / 2 - textW / 2, texW / 2 - textH / 2);
+		Graphics2.end(g2);
 
-		if (current != null) current.begin(false);
+		if (current != null) Graphics2.begin(current, false);
 	}
 
 	static makeFontPreview = () => {
 		let current = Graphics2.current;
-		if (current != null) current.end();
+		if (current != null) Graphics2.end(current);
 
 		let text = "Abg";
 		let font = Context.raw.font.font;
 		let fontSize = 318;
-		let textW = Math.floor(font.width(fontSize, text)) + 8;
-		let textH = Math.floor(font.height(fontSize)) + 8;
+		let textW = Math.floor(Font.width(font, fontSize, text)) + 8;
+		let textH = Math.floor(Font.height(font, fontSize)) + 8;
 		if (Context.raw.font.image == null) {
 			Context.raw.font.image = Image.createRenderTarget(512, 512, TextureFormat.RGBA32);
 		}
 		let g2 = Context.raw.font.image.g2;
-		g2.begin(true, 0x00000000);
+		Graphics2.begin(g2, true, 0x00000000);
 		g2.font = font;
 		g2.fontSize = fontSize;
 		g2.color = 0xffffffff;
-		g2.drawString(text, 512 / 2 - textW / 2, 512 / 2 - textH / 2);
-		g2.end();
+		Graphics2.drawString(text, 512 / 2 - textW / 2, 512 / 2 - textH / 2);
+		Graphics2.end(g2);
 		Context.raw.font.previewReady = true;
 
-		if (current != null) current.begin(false);
+		if (current != null) Graphics2.begin(current, false);
 	}
 
 	static makeBrushPreview = () => {
@@ -206,7 +206,7 @@ class UtilRender {
 		Context.raw.materialPreview = true;
 
 		let current = Graphics2.current;
-		if (current != null) current.end();
+		if (current != null) Graphics2.end(current);
 
 		// Prepare layers
 		if (RenderPathPaint.liveLayer == null) {
@@ -343,11 +343,11 @@ class UtilRender {
 		if (Base.pipeMerge == null) Base.makePipe();
 		l = RenderPathPaint.liveLayer;
 		let target = Context.raw.brush.image;
-		target.g2.begin(true, 0x00000000);
+		Graphics2.begin(target.g2, true, 0x00000000);
 		target.g2.pipeline = Base.pipeCopy;
-		target.g2.drawScaledImage(l.texpaint, 0, 0, target.width, target.height);
+		Graphics2.drawScaledImage(l.texpaint, 0, 0, target.width, target.height);
 		target.g2.pipeline = null;
-		target.g2.end();
+		Graphics2.end(target.g2);
 
 		// Scale image preview down to to icon
 		RenderPath.renderTargets.get("texpreview").image = Context.raw.brush.image;
@@ -359,10 +359,10 @@ class UtilRender {
 		Context.raw.brush.previewReady = true;
 		Context.raw.brushBlendDirty = true;
 
-		if (current != null) current.begin(false);
+		if (current != null) Graphics2.begin(current, false);
 	}
 
-	static makeNodePreview = (canvas: TNodeCanvas, node: TNode, image: Image, group: TNodeCanvas = null, parents: TNode[] = null) => {
+	static makeNodePreview = (canvas: TNodeCanvas, node: TNode, image: ImageRaw, group: TNodeCanvas = null, parents: TNode[] = null) => {
 		let res = MakeMaterial.parseNodePreviewMaterial(node, group, parents);
 		if (res == null || res.scon == null) return;
 
@@ -375,15 +375,15 @@ class UtilRender {
 		Context.raw.paintObject.base.transform.scaleWorld = 3.0;
 		Transform.buildMatrix(Context.raw.paintObject.base.transform);
 
-		g4.begin();
-		g4.setPipeline(res.scon._pipeState);
+		Graphics4.begin(g4);
+		Graphics4.setPipeline(res.scon._pipeState);
 		Uniforms.setContextConstants(g4, res.scon, [""]);
 		Uniforms.setObjectConstants(g4, res.scon, Context.raw.paintObject.base);
 		Uniforms.setMaterialConstants(g4, res.scon, res.mcon);
-		g4.setVertexBuffer(UtilRender.screenAlignedFullVB);
-		g4.setIndexBuffer(UtilRender.screenAlignedFullIB);
-		g4.drawIndexedVertices();
-		g4.end();
+		Graphics4.setVertexBuffer(UtilRender.screenAlignedFullVB);
+		Graphics4.setIndexBuffer(UtilRender.screenAlignedFullIB);
+		Graphics4.drawIndexedVertices();
+		Graphics4.end();
 
 		Context.raw.paintObject.base.transform.scaleWorld = _scaleWorld;
 		Transform.buildMatrix(Context.raw.paintObject.base.transform);
@@ -430,20 +430,20 @@ class UtilRender {
 		let indices = [0, 1, 2];
 
 		// Mandatory vertex data names and sizes
-		let structure = new VertexStructure();
-		structure.add("pos", VertexData.I16_4X_Normalized);
-		structure.add("nor", VertexData.I16_2X_Normalized);
-		structure.add("tex", VertexData.I16_2X_Normalized);
-		structure.add("col", VertexData.I16_4X_Normalized);
-		UtilRender.screenAlignedFullVB = new VertexBuffer(Math.floor(data.length / Math.floor(structure.byteSize() / 4)), structure, Usage.StaticUsage);
-		let vertices = UtilRender.screenAlignedFullVB.lock();
+		let structure = VertexStructure.create();
+		VertexStructure.add(structure, "pos", VertexData.I16_4X_Normalized);
+		VertexStructure.add(structure, "nor", VertexData.I16_2X_Normalized);
+		VertexStructure.add(structure, "tex", VertexData.I16_2X_Normalized);
+		VertexStructure.add(structure, "col", VertexData.I16_4X_Normalized);
+		UtilRender.screenAlignedFullVB = VertexBuffer.create(Math.floor(data.length / Math.floor(VertexStructure.byteSize(structure) / 4)), structure, Usage.StaticUsage);
+		let vertices = VertexBuffer.lock(UtilRender.screenAlignedFullVB);
 		for (let i = 0; i < Math.floor(vertices.byteLength / 2); ++i) vertices.setInt16(i * 2, data[i], true);
-		UtilRender.screenAlignedFullVB.unlock();
+		VertexBuffer.unlock(UtilRender.screenAlignedFullVB);
 
-		UtilRender.screenAlignedFullIB = new IndexBuffer(indices.length, Usage.StaticUsage);
-		let id = UtilRender.screenAlignedFullIB.lock();
+		UtilRender.screenAlignedFullIB = IndexBuffer.create(indices.length, Usage.StaticUsage);
+		let id = IndexBuffer.lock(UtilRender.screenAlignedFullIB);
 		for (let i = 0; i < id.length; ++i) id[i] = indices[i];
-		UtilRender.screenAlignedFullIB.unlock();
+		IndexBuffer.unlock(UtilRender.screenAlignedFullIB);
 	}
 }
 

+ 34 - 34
base/Sources/UtilUV.ts

@@ -3,20 +3,20 @@
 
 class UtilUV {
 
-	static uvmap: Image = null;
+	static uvmap: ImageRaw = null;
 	static uvmapCached = false;
-	static trianglemap: Image = null;
+	static trianglemap: ImageRaw = null;
 	static trianglemapCached = false;
-	static dilatemap: Image = null;
+	static dilatemap: ImageRaw = null;
 	static dilatemapCached = false;
-	static uvislandmap: Image = null;
+	static uvislandmap: ImageRaw = null;
 	static uvislandmapCached = false;
 	static dilateBytes: ArrayBuffer = null;
-	static pipeDilate: PipelineState = null;
+	static pipeDilate: PipelineStateRaw = null;
 
 	static cacheUVMap = () => {
 		if (UtilUV.uvmap != null && (UtilUV.uvmap.width != Config.getTextureResX() || UtilUV.uvmap.height != Config.getTextureResY())) {
-			UtilUV.uvmap.unload();
+			Image.unload(UtilUV.uvmap);
 			UtilUV.uvmap = null;
 			UtilUV.uvmapCached = false;
 		}
@@ -36,7 +36,7 @@ class UtilUV {
 
 		let texa = mesh.vertex_arrays[2].values;
 		let inda = mesh.index_arrays[0].values;
-		UtilUV.uvmap.g2.begin(true, 0x00000000);
+		Graphics2.begin(UtilUV.uvmap.g2, true, 0x00000000);
 		UtilUV.uvmap.g2.color = 0xffcccccc;
 		let strength = resX > 2048 ? 2.0 : 1.0;
 		let f = (1 / 32767) * UtilUV.uvmap.width;
@@ -47,16 +47,16 @@ class UtilUV {
 			let y1 = (texa[inda[i * 3    ] * 2 + 1]) * f;
 			let y2 = (texa[inda[i * 3 + 1] * 2 + 1]) * f;
 			let y3 = (texa[inda[i * 3 + 2] * 2 + 1]) * f;
-			UtilUV.uvmap.g2.drawLine(x1, y1, x2, y2, strength);
-			UtilUV.uvmap.g2.drawLine(x2, y2, x3, y3, strength);
-			UtilUV.uvmap.g2.drawLine(x3, y3, x1, y1, strength);
+			Graphics2.drawLine(x1, y1, x2, y2, strength);
+			Graphics2.drawLine(x2, y2, x3, y3, strength);
+			Graphics2.drawLine(x3, y3, x1, y1, strength);
 		}
-		UtilUV.uvmap.g2.end();
+		Graphics2.end(UtilUV.uvmap.g2);
 	}
 
 	static cacheTriangleMap = () => {
 		if (UtilUV.trianglemap != null && (UtilUV.trianglemap.width != Config.getTextureResX() || UtilUV.trianglemap.height != Config.getTextureResY())) {
-			UtilUV.trianglemap.unload();
+			Image.unload(UtilUV.trianglemap);
 			UtilUV.trianglemap = null;
 			UtilUV.trianglemapCached = false;
 		}
@@ -72,7 +72,7 @@ class UtilUV {
 		let mesh = merged;
 		let texa = mesh.vertex_arrays[2].values;
 		let inda = mesh.index_arrays[0].values;
-		UtilUV.trianglemap.g2.begin(true, 0xff000000);
+		Graphics2.begin(UtilUV.trianglemap.g2, true, 0xff000000);
 		let f = (1 / 32767) * UtilUV.trianglemap.width;
 		let color = 0xff000001;
 		for (let i = 0; i < Math.floor(inda.length / 3); ++i) {
@@ -85,14 +85,14 @@ class UtilUV {
 			let y1 = (texa[inda[i * 3    ] * 2 + 1]) * f;
 			let y2 = (texa[inda[i * 3 + 1] * 2 + 1]) * f;
 			let y3 = (texa[inda[i * 3 + 2] * 2 + 1]) * f;
-			UtilUV.trianglemap.g2.fillTriangle(x1, y1, x2, y2, x3, y3);
+			Graphics2.fillTriangle(x1, y1, x2, y2, x3, y3);
 		}
-		UtilUV.trianglemap.g2.end();
+		Graphics2.end(UtilUV.trianglemap.g2);
 	}
 
 	static cacheDilateMap = () => {
 		if (UtilUV.dilatemap != null && (UtilUV.dilatemap.width != Config.getTextureResX() || UtilUV.dilatemap.height != Config.getTextureResY())) {
-			UtilUV.dilatemap.unload();
+			Image.unload(UtilUV.dilatemap);
 			UtilUV.dilatemap = null;
 			UtilUV.dilatemapCached = false;
 		}
@@ -104,40 +104,40 @@ class UtilUV {
 		}
 
 		if (UtilUV.pipeDilate == null) {
-			UtilUV.pipeDilate = new PipelineState();
+			UtilUV.pipeDilate = PipelineState.create();
 			UtilUV.pipeDilate.vertexShader = System.getShader("dilate_map.vert");
 			UtilUV.pipeDilate.fragmentShader = System.getShader("dilate_map.frag");
-			let vs = new VertexStructure();
+			let vs = VertexStructure.create();
 			///if (krom_metal || krom_vulkan)
-			vs.add("tex", VertexData.I16_2X_Normalized);
+			VertexStructure.add(vs, "tex", VertexData.I16_2X_Normalized);
 			///else
-			vs.add("pos", VertexData.I16_4X_Normalized);
-			vs.add("nor", VertexData.I16_2X_Normalized);
-			vs.add("tex", VertexData.I16_2X_Normalized);
+			VertexStructure.add(vs, "pos", VertexData.I16_4X_Normalized);
+			VertexStructure.add(vs, "nor", VertexData.I16_2X_Normalized);
+			VertexStructure.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.compile();
-			// dilateTexUnpack = UtilUV.pipeDilate.getConstantLocation("texUnpack");
+			PipelineState.compile(UtilUV.pipeDilate);
+			// dilateTexUnpack = PipelineState.getConstantLocation(UtilUV.pipeDilate, "texUnpack");
 		}
 
 		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.clear(0x00000000);
-		g4.setPipeline(UtilUV.pipeDilate);
+		Graphics4.begin(g4);
+		Graphics4.clear(0x00000000);
+		Graphics4.setPipeline(UtilUV.pipeDilate);
 		///if (krom_metal || krom_vulkan)
-		g4.setVertexBuffer(MeshData.get(geom, [{name: "tex", data: "short2norm"}]));
+		Graphics4.setVertexBuffer(MeshData.get(geom, [{name: "tex", data: "short2norm"}]));
 		///else
-		g4.setVertexBuffer(geom._vertexBuffer);
+		Graphics4.setVertexBuffer(geom._vertexBuffer);
 		///end
-		g4.setIndexBuffer(geom._indexBuffers[0]);
-		g4.drawIndexedVertices();
-		g4.end();
+		Graphics4.setIndexBuffer(geom._indexBuffers[0]);
+		Graphics4.drawIndexedVertices();
+		Graphics4.end();
 		UtilUV.dilatemapCached = true;
 		UtilUV.dilateBytes = null;
 	}
@@ -145,7 +145,7 @@ class UtilUV {
 	static cacheUVIslandMap = () => {
 		UtilUV.cacheDilateMap();
 		if (UtilUV.dilateBytes == null) {
-			UtilUV.dilateBytes = UtilUV.dilatemap.getPixels();
+			UtilUV.dilateBytes = Image.getPixels(UtilUV.dilatemap);
 		}
 		UtilRender.pickPosNorTex();
 		let w = 2048; // Config.getTextureResX()
@@ -174,7 +174,7 @@ class UtilUV {
 		}
 
 		if (UtilUV.uvislandmap != null) {
-			UtilUV.uvislandmap.unload();
+			Image.unload(UtilUV.uvislandmap);
 		}
 		UtilUV.uvislandmap = Image.fromBytes(bytes, w, h, TextureFormat.R8);
 		UtilUV.uvislandmapCached = true;

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

@@ -2,7 +2,7 @@
 class ColorNode extends LogicNode {
 
 	value = Vec4.create();
-	image: Image = null;
+	image: ImageRaw = null;
 
 	constructor(r = 0.8, g = 0.8, b = 0.8, a = 1.0) {
 		super();
@@ -14,9 +14,9 @@ class ColorNode extends LogicNode {
 		else done(this.value);
 	}
 
-	override getAsImage = (from: i32, done: (img: Image)=>void) => {
+	override getAsImage = (from: i32, done: (img: ImageRaw)=>void) => {
 		if (this.inputs.length > 0) { this.inputs[0].getAsImage(done); return; }
-		if (this.image != null) this.image.unload();
+		if (this.image != null) Image.unload(this.image);
 		let b = new ArrayBuffer(16);
 		let v = new DataView(b);
 		v.setFloat32(0, this.value.x, true);

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

@@ -2,7 +2,7 @@
 class FloatNode extends LogicNode {
 
 	value: f32;
-	image: Image = null;
+	image: ImageRaw = null;
 
 	constructor(value = 0.0) {
 		super();
@@ -14,9 +14,9 @@ class FloatNode extends LogicNode {
 		else done(this.value);
 	}
 
-	override getAsImage = (from: i32, done: (img: Image)=>void) => {
+	override getAsImage = (from: i32, done: (img: ImageRaw)=>void) => {
 		if (this.inputs.length > 0) { this.inputs[0].getAsImage(done); return; }
-		if (this.image != null) this.image.unload();
+		if (this.image != null) Image.unload(this.image);
 		let b = new ArrayBuffer(16);
 		let v = new DataView(b);
 		v.setFloat32(0, this.value, true);

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

@@ -2,7 +2,7 @@
 class VectorNode extends LogicNode {
 
 	value = Vec4.create();
-	image: Image = null;
+	image: ImageRaw = null;
 
 	constructor(x: Null<f32> = null, y: Null<f32> = null, z: Null<f32> = null) {
 		super();
@@ -27,11 +27,11 @@ class VectorNode extends LogicNode {
 		});
 	}
 
-	override getAsImage = (from: i32, done: (img: Image)=>void) => {
+	override getAsImage = (from: i32, done: (img: ImageRaw)=>void) => {
 		this.inputs[0].get((x: f32) => {
 			this.inputs[1].get((y: f32) => {
 				this.inputs[2].get((z: f32) => {
-					if (this.image != null) this.image.unload();
+					if (this.image != null) Image.unload(this.image);
 					let b = new ArrayBuffer(16);
 					let v = new DataView(b);
 					v.setFloat32(0, (this.inputs[0].node as any).value, true);

+ 3 - 3
misc/pad/Sources/main.ts

@@ -24,7 +24,7 @@ class Main {
 	static minimap_h = 0;
 	static minimap_box_h = 0;
 	static minimap_scrolling = false;
-	static minimap: Image = null;
+	static minimap: ImageRaw = null;
 	static window_header_h = 0;
 
 	static main = () => {
@@ -63,7 +63,7 @@ class Main {
 		};
 
 		System.start(ops, () => {
-			Data.getFont("font_mono.ttf", (font: Font) => {
+			Data.getFont("font_mono.ttf", (font: FontRaw) => {
 				Data.getBlob("themes/dark.json", (blob_theme: ArrayBuffer) => {
 					Data.getBlob("text_coloring.json", (blob_coloring: ArrayBuffer) => {
 
@@ -143,7 +143,7 @@ class Main {
 		}
 	}
 
-	static render = (g2: Graphics2, g4: Graphics4): void => {
+	static render = (g2: Graphics2Raw, g4: Graphics4Raw): void => {
 		let ui = Main.ui;
 		Main.storage.window_w = System.width;
 		Main.storage.window_h = System.height;

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