Files
armorpaint/Sources/arm/UITrait.hx
T
Lubos Lenco b31390864e Add envmap
2018-01-30 21:50:55 +01:00

932 lines
27 KiB
Haxe

package arm;
import zui.*;
import zui.Zui.State;
import zui.Canvas;
import iron.data.SceneFormat;
import iron.data.MeshData;
import iron.object.MeshObject;
typedef TPreferences = {
public var w:Int;
public var h:Int;
public var save_location:String;
public var load_location:String;
}
// typedef TProject = {
// public var brushes:Array<>;
// public var materials:Array<>;
// }
class UITrait extends armory.Trait {
public static var uienabled = true;
public static var isScrolling = false;
public static var isDragging = false;
public static var dragAsset:TAsset = null;
public static var showFiles = false;
public static var foldersOnly = false;
public static var filesDone:String->Void;
public static var showSplash = false;
public static var show = true;
public static var dirty = true;
var message = "";
var messageTimer = 0.0;
var dropPath = "";
var dropX = 0.0;
var dropY = 0.0;
var bundled:Map<String, kha.Image> = new Map();
var ui:Zui;
var uimodal:Zui;
public static var windowW = 240; // Panel width
function loadBundled(names:Array<String>, done:Void->Void) {
var loaded = 0;
for (s in names) {
kha.Assets.loadImage(s, function(image:kha.Image) {
bundled.set(s, image);
loaded++;
if (loaded == names.length) done();
});
}
}
public static function depthDirty():Bool {
if (!dirty && !firstPaint) return false;
dirty = false;
return true;
}
static var _onBrush:Array<Void->Void> = [];
public static function notifyOnBrush(f:Void->Void) {
_onBrush.push(f);
}
public static var firstPaint = true;
public static var paint = false;
public static var paintX = 0.0;
public static var paintY = 0.0;
public static var lastPaintX = 0.0;
public static var lastPaintY = 0.0;
static var painted = 0;
public static function paintDirty():Bool {
// Paint bounds
if (paintX > iron.App.w()) return false;
// if (UINodes.show && paintY > UINodes.wy) return false;
// if (UINodesBrush.show && paintY > UINodesBrush.wy) return false;
// Prevent painting the same spot - save perf & reduce projection paint jittering caused by _sub offset
if (paintX == lastPaintX && paintY == lastPaintY) painted++;
else painted = 0;
if (painted > 8) return false;
lastPaintX = paintX;
lastPaintY = paintY;
if (paint) firstPaint = false;
return paint;
}
// TODO: Recompile mat instead of uniforms?
public static var brushRadius = 0.5;
public static var brushOpacity = 1.0;
public static var brushScale = 0.5;
public static var brushStrength = 1.0;
public static var brushBias = 1.0;
public static var brushPaint = 0;
public static var brushType = 0;
public static var paintBase = true;
public static var paintOpac = true;
public static var paintOcc = true;
public static var paintRough = true;
public static var paintMet = true;
public static var paintNor = true;
function linkFloat(link:String):Null<Float> {
if (link == '_brushRadius') {
return brushRadius / 15.0;
}
else if (link == '_brushOpacity') {
return brushOpacity;
}
else if (link == '_brushScale') {
return brushScale * 2.0;
}
else if (link == '_brushStrength') {
return brushStrength * brushStrength * 100;
}
// else if (link == '_brushPaint') {
// return brushPaint;
// }
return null;
}
var sub = 0;
var vsub = new iron.math.Vec4();
function linkVec2(link:String):iron.math.Vec4 {
if (link == '_sub') {
var seps = brushBias * 0.0001;
sub = (sub + 1) % 9;
if (sub == 0) vsub.set(0.0 + seps, 0.0, 0.0);
else if (sub == 1) vsub.set(0.0 - seps, 0.0, 0.0);
else if (sub == 2) vsub.set(0.0, 0.0 + seps, 0.0);
else if (sub == 3) vsub.set(0.0, 0.0 - seps, 0.0);
else if (sub == 4) vsub.set(0.0 + seps, 0.0 + seps, 0.0);
else if (sub == 5) vsub.set(0.0 - seps, 0.0 - seps, 0.0);
else if (sub == 6) vsub.set(0.0 + seps, 0.0 - seps, 0.0);
else if (sub == 7) vsub.set(0.0 - seps, 0.0 + seps, 0.0);
else if (sub == 8) vsub.set(0.0, 0.0, 0.0);
return vsub;
}
return null;
}
var font:kha.Font;
public function new() {
super();
iron.object.Uniforms.externalFloatLinks = [linkFloat];
iron.object.Uniforms.externalVec2Links = [linkVec2];
iron.data.Data.getFont('droid_sans.ttf', function(f:kha.Font) {
font = f;
zui.Themes.dark.FILL_WINDOW_BG = true;
zui.Nodes.getEnumTexts = getEnumTexts;
zui.Nodes.mapEnum = mapEnum;
ui = new Zui( { font: f } );
uimodal = new Zui( { font: f } );
// ui = new Zui( { font: f, scaleFactor: 8, theme: zui.Themes.light } ); ////
loadBundled(['brush', 'mat', 'matbrush', 'cay_thumb'], done);
});
kha.System.notifyOnDropFiles(function(filePath:String) {
dropPath = StringTools.rtrim(filePath);
var mouse = iron.system.Input.getMouse();
dropX = mouse.x;
dropY = mouse.y;
});
}
function showMessage(s:String) {
messageTimer = 3.0;
message = s;
hwnd.redraws = 2;
}
function checkImageFormat(path:String):Bool {
if (!StringTools.endsWith(path, ".jpg") &&
!StringTools.endsWith(path, ".png") &&
!StringTools.endsWith(path, ".hdr")) {
return false;
}
return true;
}
function importAsset(path:String) {
if (!checkImageFormat(path)) {
showMessage("Error: Unknown asset format");
return;
}
iron.data.Data.getImage(path, function(image:kha.Image) {
var ar = path.split("/");
var name = ar[ar.length - 1];
var asset:TAsset = {name: name, file: path, id: assetId++};
assets.push(asset);
assetNames.push(name);
Canvas.assetMap.set(asset.id, image);
hwnd.redraws = 2;
});
}
function getEnumTexts():Array<String> {
return assetNames.length > 0 ? assetNames : [""];
}
function mapEnum(s:String):String {
for (a in assets) if (a.name == s) return a.file;
return "";
}
// var rt:kha.Image; ////
// var uiWidth = 2048;
// var uiHeight = 2048;
var currentObject:MeshObject;
function done() {
notifyOnInit(function() {
// iron.Scene.active.notifyOnInit(function() { ////
// var pui = iron.Scene.active.getChild("PlaneUI"); ////
// rt = kha.Image.createRenderTarget(uiWidth, uiHeight);
// var mat:armory.data.MaterialData = cast(pui, armory.object.MeshObject).materials[0];
// mat.contexts[0].textures[0] = rt; // Override diffuse texture
currentObject = cast(iron.Scene.active.getChild("Cube"), MeshObject);
iron.App.notifyOnUpdate(update);
iron.App.notifyOnRender2D(render);
iron.App.notifyOnRender(clearTargetsHandler);
});
}
function resize() {
iron.Scene.active.camera.buildProjection();
if (UINodes.grid != null) {
UINodes.grid.unload();
UINodes.grid = null;
}
}
function update() {
isScrolling = ui.isScrolling;
updateUI();
// updateSplash();
updateFiles();
}
function updateUI() {
messageTimer -= iron.system.Time.delta;
paint = false;
var mouse = iron.system.Input.getMouse();
var kb = iron.system.Input.getKeyboard();
// if (mouse.started() && mouse.x < 50 && mouse.y < 50) show = !show;
isDragging = dragAsset != null;
if (mouse.released() && isDragging) {
if (UINodes.show && mouse.x > UINodes.wx && mouse.y > UINodes.wy) {
var index = 0;
for (i in 0...assets.length) if (assets[i] == dragAsset) { index = i; break; }
UINodes.acceptDrag(index);
}
dragAsset = null;
}
if (!show) return;
if (!UITrait.uienabled) return;
if (mouse.down() && !kb.down("ctrl")) {
for (f in _onBrush) f();
}
}
var modalW = 625;
var modalH = 545;
var modalHeaderH = 66;
var modalRectW = 625; // No shadow
var modalRectH = 545;
// function updateSplash() {
// if (!showSplash) return;
// var mouse = iron.system.Input.getMouse();
// if (mouse.released()) {
// var left = iron.App.w() / 2 - modalRectW / 2;
// var right = iron.App.w() / 2 + modalRectW / 2;
// var top = iron.App.h() / 2 - modalRectH / 2;
// var bottom = iron.App.h() / 2 + modalRectH / 2;
// if (mouse.x < left || mouse.x > right || mouse.y < top + modalHeaderH || mouse.y > bottom) {
// showSplash = false;
// }
// }
// }
function updateFiles() {
if (!showFiles) return;
var mouse = iron.system.Input.getMouse();
if (mouse.released()) {
var appw = kha.System.windowWidth();
var apph = kha.System.windowHeight();
var left = appw / 2 - modalRectW / 2;
var right = appw / 2 + modalRectW / 2;
var top = apph / 2 - modalRectH / 2;
var bottom = apph / 2 + modalRectH / 2;
if (mouse.x < left || mouse.x > right || mouse.y < top + modalHeaderH || mouse.y > bottom) {
showFiles = false;
}
}
}
public static var texpaint:kha.Image;
public static var texpaint_nor:kha.Image;
public static var texpaint_pack:kha.Image;
function clearTargetsHandler(g:kha.graphics4.Graphics) {
var pd = iron.RenderPath.active;
texpaint = pd.renderTargets.get("texpaint").image;
texpaint_nor = pd.renderTargets.get("texpaint_nor").image;
texpaint_pack = pd.renderTargets.get("texpaint_pack").image;
g.end();
texpaint.g4.begin();
texpaint.g4.clear(kha.Color.fromFloats(0.2, 0.2, 0.2, 0.0)); // Base
texpaint.g4.end();
texpaint_nor.g4.begin();
texpaint_nor.g4.clear(kha.Color.fromFloats(0.5, 0.5, 1.0, 0.0)); // Nor
texpaint_nor.g4.end();
texpaint_pack.g4.begin();
texpaint_pack.g4.clear(kha.Color.fromFloats(1.0, 1.0, 0.0, 0.0)); // Occ, rough, met
texpaint_pack.g4.end();
g.begin();
iron.App.removeRender(clearTargetsHandler);
}
function resizeTargetsHandler(g:kha.graphics4.Graphics) {
var res = getTextureRes();
var pd = iron.RenderPath.active;
var texpaint = pd.renderTargets.get("texpaint");
var texpaint_nor = pd.renderTargets.get("texpaint_nor");
var texpaint_pack = pd.renderTargets.get("texpaint_pack");
var texpaint_oldimg = texpaint.image;
var texpaint_nor_oldimg = texpaint_nor.image;
var texpaint_pack_oldimg = texpaint_pack.image;
texpaint.image = kha.Image.createRenderTarget(res, res, kha.graphics4.TextureFormat.RGBA32, kha.graphics4.DepthStencilFormat.Depth16);
texpaint_nor.image = kha.Image.createRenderTarget(res, res, kha.graphics4.TextureFormat.RGBA32, kha.graphics4.DepthStencilFormat.NoDepthAndStencil);
texpaint_pack.image = kha.Image.createRenderTarget(res, res, kha.graphics4.TextureFormat.RGBA32, kha.graphics4.DepthStencilFormat.NoDepthAndStencil);
g.end();
texpaint.image.g2.begin();
texpaint.image.g2.drawScaledImage(texpaint_oldimg, 0, 0, res, res);
texpaint.image.g2.end();
texpaint_nor.image.g2.begin();
texpaint_nor.image.g2.drawScaledImage(texpaint_nor_oldimg, 0, 0, res, res);
texpaint_nor.image.g2.end();
texpaint_pack.image.g2.begin();
texpaint_pack.image.g2.drawScaledImage(texpaint_pack_oldimg, 0, 0, res, res);
texpaint_pack.image.g2.end();
g.begin();
texpaint_oldimg.unload();
texpaint_nor_oldimg.unload();
texpaint_pack_oldimg.unload();
UITrait.dirty = true;
iron.App.removeRender(resizeTargetsHandler);
}
var lastW = 0;
var lastH = 0;
function render(g:kha.graphics2.Graphics) {
if (arm.App.realw() == 0 || arm.App.realh() == 0) return;
if (dropPath != "") {
if (StringTools.endsWith(dropPath, ".obj")) importMesh(dropPath);
else {
importAsset(dropPath);
// Place image node
if (UINodes.show && dropX > UINodes.wx && dropX < UINodes.wx + UINodes.ww) {
UINodes.acceptDrag(assets.length - 1);
UINodes.nodes.nodeDrag = null;
UINodes.inst.hwnd.redraws = 2;
}
}
dropPath = "";
}
uienabled = !showSplash && !showFiles;
renderUI(g);
// if (showSplash) renderSplash(g);
if (showFiles) renderFiles(g);
if (lastW > 0 && (lastW != arm.App.realw() || lastH != arm.App.realh())) {
resize();
}
lastW = arm.App.realw();
lastH = arm.App.realh();
// var ready = showFiles || dirty;
// TODO: Texture params get overwritten
// if (ready) for (t in UINodes.inst._matcon.bind_textures) t.params_set = null;
if (UINodes.inst._matcon != null) for (t in UINodes.inst._matcon.bind_textures) t.params_set = null;
// iron.Scene.active.camera.renderPath.ready = ready;
// dirty = false;
}
var assets:Array<TAsset> = [];
var assetNames:Array<String> = [];
var assetId = 0;
public static var cameraType = 0;
var textureRes = 2;
function getTextureRes():Int {
if (textureRes == 0) return 1024;
if (textureRes == 1) return 2048;
if (textureRes == 2) return 4096;
if (textureRes == 3) return 8192;
if (textureRes == 4) return 16384;
if (textureRes == 5) return 20480;
return 0;
}
var isBase = true;
var isOpac = true;
var isOcc = true;
var isRough = true;
var isMet = true;
var isNor = true;
var hwnd = Id.handle();
function renderUI(g:kha.graphics2.Graphics) {
if (!show) return;
if (!UITrait.uienabled && ui.inputRegistered) ui.unregisterInput();
if (UITrait.uienabled && !ui.inputRegistered) ui.registerInput();
var matImg = bundled.get('mat');
var matBrushImg = bundled.get('matbrush');
var envThumbCay = bundled.get('cay_thumb');
var brushImg = bundled.get('brush');
var mouse = iron.system.Input.getMouse();
g.color = 0xffffffff;
// Brush
if (UITrait.uienabled) {
var psize = Std.int(brushImg.width * brushRadius);
// g.imageScaleQuality = kha.graphics2.ImageScaleQuality.High;
g.drawScaledImage(brushImg, mouse.x - psize / 2, mouse.y - psize / 2, psize, psize);
}
g.end();
ui.begin(g);
// ui.begin(rt.g2); ////
if (ui.window(hwnd, arm.App.realw() - windowW, 0, windowW, iron.App.h())) {
var htab = Id.handle({position: 0});
if (ui.tab(htab, "Project")) {
// ui.row([1/2, 1/2]);
// ui.button("Open");
// ui.button("Save");
// if (ui.button("Help")) {
// showSplash = true;
// }
if (messageTimer > 0) {
ui.text(message);
}
if (ui.button("Import Mesh")) {
showFiles = true;
foldersOnly = false;
filesDone = function(path:String) {
importMesh(path);
}
}
else if (ui.isHovered) ui.tooltip("Drop .obj mesh here");
if (ui.button("Export Textures")) {
var textureSize = getTextureRes();
showFiles = true;
foldersOnly = true;
// var path = 'C:\\Users\\lubos\\Documents\\';
filesDone = function(path:String) {
var bo = new haxe.io.BytesOutput();
var pixels = texpaint.getPixels();
var rgb = haxe.io.Bytes.alloc(textureSize * textureSize * 3);
// BGRA to RGB
for (i in 0...textureSize * textureSize) {
rgb.set(i * 3 + 0, pixels.get(i * 4 + 2));
rgb.set(i * 3 + 1, pixels.get(i * 4 + 1));
rgb.set(i * 3 + 2, pixels.get(i * 4 + 0));
}
var pngwriter = new iron.format.png.Writer(bo);
pngwriter.write(iron.format.png.Tools.buildRGB(textureSize, textureSize, rgb));
// var jpgdata:iron.format.jpg.Data.Data = {
// width: textureSize,
// height: textureSize,
// quality: 80,
// pixels: rgb
// };
// var jpgwriter = new iron.format.jpg.Writer(bo);
// jpgwriter.write(jpgdata);
#if kha_krom
if (isBase) Krom.fileSaveBytes(path + "/tex_basecol.png", bo.getBytes().getData());
#end
pixels = texpaint_nor.getPixels();
for (i in 0...textureSize * textureSize) {
rgb.set(i * 3 + 0, pixels.get(i * 4 + 2));
rgb.set(i * 3 + 1, pixels.get(i * 4 + 1));
rgb.set(i * 3 + 2, pixels.get(i * 4 + 0));
}
bo = new haxe.io.BytesOutput();
var pngwriter = new iron.format.png.Writer(bo);
pngwriter.write(iron.format.png.Tools.buildRGB(textureSize, textureSize, rgb));
#if kha_krom
if (isNor) Krom.fileSaveBytes(path + "/tex_nor.png", bo.getBytes().getData());
#end
// for (i in 0...textureSize * textureSize) {
// rgb.set(i * 3 + 0, pixels.get(i * 4 + 3));
// rgb.set(i * 3 + 1, pixels.get(i * 4 + 3));
// rgb.set(i * 3 + 2, pixels.get(i * 4 + 3));
// }
// bo = new haxe.io.BytesOutput();
// var pngwriter = new iron.format.png.Writer(bo);
// pngwriter.write(iron.format.png.Tools.buildRGB(textureSize, textureSize, rgb));
// #if kha_krom
// Krom.fileSaveBytes(path + "/tex_height.png", bo.getBytes().getData());
// #end
pixels = texpaint_pack.getPixels(); // occ, rough, met
for (i in 0...textureSize * textureSize) {
rgb.set(i * 3 + 0, pixels.get(i * 4));
rgb.set(i * 3 + 1, pixels.get(i * 4));
rgb.set(i * 3 + 2, pixels.get(i * 4));
}
bo = new haxe.io.BytesOutput();
var pngwriter = new iron.format.png.Writer(bo);
pngwriter.write(iron.format.png.Tools.buildRGB(textureSize, textureSize, rgb));
#if kha_krom
if (isOcc) Krom.fileSaveBytes(path + "/tex_occ.png", bo.getBytes().getData());
#end
for (i in 0...textureSize * textureSize) {
rgb.set(i * 3 + 0, pixels.get(i * 4 + 1));
rgb.set(i * 3 + 1, pixels.get(i * 4 + 1));
rgb.set(i * 3 + 2, pixels.get(i * 4 + 1));
}
bo = new haxe.io.BytesOutput();
var pngwriter = new iron.format.png.Writer(bo);
pngwriter.write(iron.format.png.Tools.buildRGB(textureSize, textureSize, rgb));
#if kha_krom
if (isRough) Krom.fileSaveBytes(path + "/tex_rough.png", bo.getBytes().getData());
#end
for (i in 0...textureSize * textureSize) {
rgb.set(i * 3 + 0, pixels.get(i * 4 + 2));
rgb.set(i * 3 + 1, pixels.get(i * 4 + 2));
rgb.set(i * 3 + 2, pixels.get(i * 4 + 2));
}
bo = new haxe.io.BytesOutput();
var pngwriter = new iron.format.png.Writer(bo);
pngwriter.write(iron.format.png.Tools.buildRGB(textureSize, textureSize, rgb));
#if kha_krom
if (isMet) Krom.fileSaveBytes(path + "/tex_met.png", bo.getBytes().getData());
#end
}
}
if (ui.panel(Id.handle({selected: false}), "Export")) {
var hres = Id.handle({position: textureRes});
textureRes = ui.combo(hres, ["1K", "2K", "4K", "8K", "16K", "20K"], "Res", true);
if (hres.changed) {
iron.App.notifyOnRender(resizeTargetsHandler);
}
ui.combo(Id.handle(), ["8bit"], "Color", true);
ui.combo(Id.handle(), ["png"], "Format", true);
ui.text("Channels");
ui.row([1/2, 1/2]);
isBase = ui.check(Id.handle({selected: isBase}), "Base Color");
isOpac = ui.check(Id.handle({selected: isOpac}), "Opacity");
ui.row([1/2, 1/2]);
isOcc = ui.check(Id.handle({selected: isOcc}), "Occlusion");
isRough = ui.check(Id.handle({selected: isRough}), "Roughness");
ui.row([1/2, 1/2]);
isMet = ui.check(Id.handle({selected: isMet}), "Metallic");
isNor = ui.check(Id.handle({selected: isNor}), "Normal Map");
}
if (ui.panel(Id.handle({selected: false}), "Camera")) {
ui.row([1/2,1/2]);
cameraType = ui.combo(Id.handle({position: cameraType}), ["Orbit", "Fly"], "Camera");
if (ui.button("Reset")) {
var scene = iron.Scene.active;
var cam = scene.cameras[0];
for (o in scene.raw.objects) {
if (o.type == 'camera_object') {
cam.transform.local.setF32(o.transform.values);
cam.transform.decompose();
currentObject.transform.reset();
break;
}
}
}
}
// if (ui.panel(Id.handle({selected: true}), "TREE")) {
// ui.row([1/3, 1/3, 1/3]);
// if (ui.button("Mesh")) {
// }
// if (ui.button("Lamp")) {
// }
// if (ui.button("Camera")) {
// }
// var h = Id.handle();
// ui.radio(h, 0, "Mesh");
// ui.radio(h, 1, "Lamp");
// ui.radio(h, 2, "Camera");
// ui.radio(h, 3, "World");
// }
// ui.separator();
// if (ui.panel(Id.handle({selected: true}), "PROPERTIES")) {
// ui.textInput(Id.handle({text: "Mesh"}), "Name", Right);
// ui.row([1/3, 1/3, 1/3]);
// var strx = ui.textInput(Id.handle().nest(0, {text: "0"}), "X", Right);
// var stry = ui.textInput(Id.handle().nest(1, {text: "0"}), "Y", Right);
// var strz = ui.textInput(Id.handle().nest(2, {text: "0"}), "X", Right);
// }
// ui.separator();
if (ui.panel(Id.handle({selected: false}), "Environment")) {
ui.image(envThumbCay);
var p = iron.Scene.active.world.getGlobalProbe();
ui.row([1/2, 1/2]);
var envType = ui.combo(Id.handle({position: 0}), ["Indoor"], "Map");
p.raw.strength = ui.slider(Id.handle({value: p.raw.strength}), "Strength", 0.0, 5.0, true);
if (iron.Scene.active.lamps.length > 0) {
var lamp = iron.Scene.active.lamps[0];
lamp.data.raw.strength = ui.slider(Id.handle({value: lamp.data.raw.strength / 10}), "Light", 0.0, 5.0, true) * 10;
}
}
if (ui.panel(Id.handle({selected: true}), "Brush")) {
ui.image(matBrushImg);
// if (ui.button("Nodes")) {
// UINodesBrush.show = !UINodesBrush.show;
// UINodes.show = false;
// }
ui.row([1/2, 1/2]);
var paintHandle = Id.handle();
brushPaint = ui.combo(paintHandle, ["UV", "Project"], "Paint");
if (paintHandle.changed) {
UINodes.inst.parseMaterial();
}
brushBias = ui.slider(Id.handle({value: brushBias}), "Bias", 0.0, 4.0, true);
ui.row([1/2, 1/2]);
var typeHandle = Id.handle();
brushType = ui.combo(typeHandle, ["Draw", "Fill"], "Type");
if (typeHandle.changed) {
UINodes.inst.parseMaterial();
}
ui.combo(Id.handle(), ["Add"], "Blending");
ui.row([1/2, 1/2]);
brushRadius = ui.slider(Id.handle({value: brushRadius}), "Radius", 0.0, 2.0, true);
brushOpacity = ui.slider(Id.handle({value: brushOpacity}), "Opacity", 0.0, 1.0, true);
ui.row([1/2, 1/2]);
brushStrength = ui.slider(Id.handle({value: brushStrength}), "Strength", 0.0, 1.0, true);
brushScale = ui.slider(Id.handle({value: brushScale}), "Scale", 0.0, 1.0, true);
}
ui.separator();
if (ui.panel(Id.handle({selected: true}), "Material")) {
ui.image(matImg);
if (ui.button("Nodes")) {
UINodes.show = !UINodes.show;
UINodesBrush.show = false;
resize();
}
// ui.text("Paint");
// ui.row([1/2, 1/2]);
// paintBase = ui.check(Id.handle({selected: paintBase}), "Base Color");
// paintOpac = ui.check(Id.handle({selected: paintOpac}), "Opacity");
// ui.row([1/2, 1/2]);
// paintOcc = ui.check(Id.handle({selected: paintOcc}), "Occlusion");
// paintRough = ui.check(Id.handle({selected: paintRough}), "Roughness");
// ui.row([1/2, 1/2]);
// paintMet = ui.check(Id.handle({selected: paintMet}), "Metallic");
// paintNor = ui.check(Id.handle({selected: paintNor}), "Normal Map");
var baseHandle = Id.handle({selected: paintBase});
paintBase = ui.check(baseHandle, "Base Color");
if (baseHandle.changed) {
UINodes.inst.parseMaterial();
}
var norHandle = Id.handle({selected: paintNor});
paintNor = ui.check(norHandle, "Normal Map");
if (norHandle.changed) {
UINodes.inst.parseMaterial();
}
var roughHandle = Id.handle({selected: paintRough});
paintRough = ui.check(roughHandle, "Rough Met Occ");
if (roughHandle.changed) {
UINodes.inst.parseMaterial();
}
}
ui.text("v0.1", zui.Zui.Align.Right);
}
if (ui.tab(htab, "Assets")) {
if (messageTimer > 0) {
ui.text(message);
}
if (ui.button("Import")) {
showFiles = true;
foldersOnly = false;
filesDone = function(path:String) {
importAsset(path);
}
}
if (assets.length > 0) {
var i = assets.length - 1;
while (i >= 0) {
var asset = assets[i];
if (ui.image(getImage(asset)) == State.Started) {
dragAsset = asset;
}
ui.row([1/8, 7/8]);
var b = ui.button("X");
asset.name = ui.textInput(Id.handle().nest(asset.id, {text: asset.name}), "", Right);
assetNames[i] = asset.name;
if (b) {
getImage(asset).unload();
assets.splice(i, 1);
assetNames.splice(i, 1);
}
i--;
}
}
else {
ui.text("(Drag & drop assets)");
}
// if (ui.panel(Id.handle({selected: false}), "LAYERS")) {}
// ui.separator();
// if (ui.panel(Id.handle({selected: false}), "HISTORY")) {}
// ui.separator();
}
}
ui.end();
g.begin(false);
if (dragAsset != null) {
UITrait.dirty = true;
var mouse = iron.system.Input.getMouse();
var ratio = 128 / getImage(dragAsset).width;
var h = getImage(dragAsset).height * ratio;
g.drawScaledImage(getImage(dragAsset), mouse.x, mouse.y, 128, h);
}
}
function renderSplash(g:kha.graphics2.Graphics) {
var left = iron.App.w() / 2 - modalW / 2;
var top = iron.App.h() / 2 - modalH / 2;
var splashImg = bundled.get('splash');
g.color = 0xffffffff;
g.drawScaledImage(splashImg, left, top, modalW, modalH);
uimodal.beginLayout(g, Std.int(left) + 200, Std.int(top) + 500, 120);
uimodal.button("Manual");
uimodal.endLayout();
}
function getImage(asset:TAsset):kha.Image {
return Canvas.assetMap.get(asset.id);
}
var path = '/';
function renderFiles(g:kha.graphics2.Graphics) {
var appw = kha.System.windowWidth();
var apph = kha.System.windowHeight();
var left = appw / 2 - modalW / 2;
var top = apph / 2 - modalH / 2;
var filesImg = bundled.get('files');
g.color = 0xff202020;
// g.drawScaledImage(filesImg, left, top, modalW, modalH);
g.fillRect(left, top, modalW, modalH);
var leftRect = Std.int(appw / 2 - modalRectW / 2);
var rightRect = Std.int(appw / 2 + modalRectW / 2);
var topRect = Std.int(apph / 2 - modalRectH / 2);
var bottomRect = Std.int(apph / 2 + modalRectH / 2);
topRect += modalHeaderH;
g.end();
uimodal.begin(g);
if (uimodal.window(Id.handle(), leftRect, topRect, modalRectW, modalRectH - 100)) {
var pathHandle = Id.handle();
pathHandle.text = uimodal.textInput(pathHandle);
path = zui.Ext.fileBrowser(uimodal, pathHandle, foldersOnly);
}
uimodal.end(false);
g.begin(false);
uimodal.beginLayout(g, rightRect - 100, bottomRect - 30, 100);
if (uimodal.button("OK")) {
showFiles = false;
filesDone(path);
UITrait.dirty = true;
}
uimodal.endLayout(false);
uimodal.beginLayout(g, rightRect - 200, bottomRect - 30, 100);
if (uimodal.button("Cancel")) {
showFiles = false;
UITrait.dirty = true;
}
uimodal.endLayout();
}
function importMesh(path:String) {
if (!StringTools.endsWith(path, ".obj")) {
showMessage("Error: Unknown mesh format");
return;
}
iron.data.Data.getBlob(path, function(b:kha.Blob) {
var obj = new iron.format.obj.Loader(b.toString());
if (obj.indexedVertices == null) {
showMessage("Error: Invalid mesh - no UVs found");
return;
}
var pa = new TFloat32Array(obj.indexedVertices.length);
for (i in 0...pa.length) pa[i] = obj.indexedVertices[i];
var uva = new TFloat32Array(obj.indexedUVs.length);
for (i in 0...uva.length) uva[i] = obj.indexedUVs[i];
var na = new TFloat32Array(obj.indexedNormals.length);
for (i in 0...na.length) na[i] = obj.indexedNormals[i];
var ia = new TUint32Array(obj.indices.length);
for (i in 0...ia.length) ia[i] = obj.indices[i];
var raw:TMeshData = {
name: "Mesh",
vertex_arrays: [
{
values: pa,
attrib: "pos"
},
{
values: na,
attrib: "nor"
},
{
values: uva,
attrib: "tex"
}
],
index_arrays: [
{
values: ia,
material: 0
}
]
};
new MeshData(raw, function(md:MeshData) {
currentObject.data.delete();
iron.App.notifyOnRender(clearTargetsHandler);
currentObject.setData(md);
// Scale to bounds
md.geom.calculateAABB();
var r = Math.sqrt(md.geom.aabb.x * md.geom.aabb.x + md.geom.aabb.y * md.geom.aabb.y + md.geom.aabb.z * md.geom.aabb.z);
if (r > 3) {
currentObject.transform.scale.set(3 / r, 3 / r, 3 / r);
currentObject.transform.buildMatrix();
}
// Face camera
currentObject.transform.setRotation(Math.PI / 2, 0, 0);
UITrait.dirty = true;
});
});
}
}