Files
armorpaint/Sources/arm/App.hx
T
2021-08-28 16:34:08 +02:00

738 lines
23 KiB
Haxe

package arm;
import haxe.io.Bytes;
import kha.graphics2.truetype.StbTruetype;
import kha.Image;
import kha.Font;
import kha.System;
import zui.Zui;
import zui.Themes;
import zui.Nodes;
import iron.Scene;
import iron.data.Data;
import iron.system.Input;
import arm.ui.UISidebar;
import arm.ui.UIToolbar;
import arm.ui.UINodes;
import arm.ui.UIView2D;
import arm.ui.UIMenu;
import arm.ui.UIBox;
import arm.ui.UIFiles;
import arm.ui.UIHeader;
import arm.ui.UIStatus;
import arm.ui.UIMenubar;
import arm.ui.TabSwatches;
import arm.ui.TabLayers;
import arm.ui.BoxExport;
import arm.io.ImportAsset;
import arm.io.ExportMesh;
import arm.io.ExportTexture;
import arm.sys.File;
import arm.sys.Path;
import arm.util.RenderUtil;
import arm.Viewport;
import arm.data.MaterialSlot;
import arm.data.LayerSlot;
import arm.data.ConstData;
import arm.node.MakeMaterial;
import arm.Camera;
import arm.Enums;
import arm.ProjectFormat;
import arm.Res;
class App {
public static var uiEnabled = true;
public static var isDragging = false;
public static var isResizing = false;
public static var dragMaterial: MaterialSlot = null;
public static var dragLayer: LayerSlot = null;
public static var dragAsset: TAsset = null;
public static var dragSwatch: TSwatchColor = null;
public static var dragFile: String = null;
public static var dragFileIcon: Image = null;
public static var dragTint = 0xffffffff;
public static var dragSize = -1;
public static var dragRect: TRect = null;
public static var dragOffX = 0.0;
public static var dragOffY = 0.0;
public static var dropX = 0.0;
public static var dropY = 0.0;
public static var font: Font = null;
public static var theme: TTheme;
public static var colorWheel: Image;
public static var uiBox: Zui;
public static var uiMenu: Zui;
public static var defaultElementW = 100;
public static var defaultElementH = 28;
public static var defaultFontSize = 13;
public static var resHandle = new Handle();
public static var bitsHandle = new Handle();
static var dropPaths: Array<String> = [];
static var appx = 0;
static var appy = 0;
static var lastWindowWidth = 0;
static var lastWindowHeight = 0;
public function new() {
Console.init();
lastWindowWidth = System.windowWidth();
lastWindowHeight = System.windowHeight();
#if arm_resizable
iron.App.onResize = onResize;
#end
System.notifyOnDropFiles(function(dropPath: String) {
#if krom_linux
dropPath = untyped decodeURIComponent(dropPath);
dropPaths = dropPath.split("file://");
for (i in 0...dropPaths.length) dropPaths[i] = dropPaths[i].rtrim();
#else
dropPath = dropPath.rtrim();
dropPaths.push(dropPath);
#end
#if krom_ios
// Import immediately while access to resource is unlocked
handleDropPaths();
#end
});
System.notifyOnApplicationState(
function() { // Foreground
Context.foregroundEvent = true;
Context.lastPaintX = -1;
Context.lastPaintY = -1;
},
function() {}, // Resume
function() {}, // Pause
function() { // Background
// Release keys after alt-tab / win-tab
@:privateAccess Input.getKeyboard().upListener(kha.input.KeyCode.Alt);
@:privateAccess Input.getKeyboard().upListener(kha.input.KeyCode.Win);
},
function() { // Shutdown
#if (krom_android || krom_ios)
Project.projectSave();
#end
}
);
Krom.setSaveAndQuitCallback(saveAndQuitCallback);
Data.getFont("font.ttf", function(f: Font) {
Data.getImage("color_wheel.k", function(image: Image) {
font = f;
Config.loadTheme(Config.raw.theme, false);
defaultElementW = theme.ELEMENT_W;
defaultFontSize = theme.FONT_SIZE;
Translator.loadTranslations(Config.raw.locale);
UIFiles.filename = tr("untitled");
// Precompiled font for fast startup
if (Config.raw.locale == "en") {
var kimg: kha.Font.KravurImage = js.lib.Object.create(untyped kha.Font.KravurImage.prototype);
@:privateAccess kimg.mySize = 13;
@:privateAccess kimg.width = 128;
@:privateAccess kimg.height = 128;
@:privateAccess kimg.baseline = 10;
var chars = new haxe.ds.Vector(ConstData.font_x0.length);
kha.graphics2.Graphics.fontGlyphs = [for (i in 32...127) i];
for (i in 0...95) chars[i] = new Stbtt_bakedchar();
for (i in 0...ConstData.font_x0.length) chars[i].x0 = ConstData.font_x0[i];
for (i in 0...ConstData.font_y0.length) chars[i].y0 = ConstData.font_y0[i];
for (i in 0...ConstData.font_x1.length) chars[i].x1 = ConstData.font_x1[i];
for (i in 0...ConstData.font_y1.length) chars[i].y1 = ConstData.font_y1[i];
for (i in 0...ConstData.font_xoff.length) chars[i].xoff = ConstData.font_xoff[i];
for (i in 0...ConstData.font_yoff.length) chars[i].yoff = ConstData.font_yoff[i];
for (i in 0...ConstData.font_xadvance.length) chars[i].xadvance = ConstData.font_xadvance[i];
@:privateAccess kimg.chars = chars;
Data.getBlob("font13.bin", function(fontbin: kha.Blob) {
@:privateAccess kimg.texture = Image.fromBytes(fontbin.toBytes(), 128, 128, kha.graphics4.TextureFormat.L8);
@:privateAccess cast(font, kha.Font).images.set(130095, kimg);
});
}
colorWheel = image;
Nodes.enumTexts = enumTexts;
Nodes.tr = tr;
uiBox = new Zui({ theme: App.theme, font: f, scaleFactor: Config.raw.window_scale, color_wheel: colorWheel });
uiMenu = new Zui({ theme: App.theme, font: f, scaleFactor: Config.raw.window_scale, color_wheel: colorWheel });
defaultElementH = uiMenu.t.ELEMENT_H;
// Init plugins
if (Config.raw.plugins != null) {
for (plugin in Config.raw.plugins) {
Plugin.start(plugin);
}
}
Args.parse();
iron.App.notifyOnUpdate(update);
new UISidebar();
new UINodes();
new UIView2D();
new Camera();
iron.App.notifyOnRender2D(UIView2D.inst.render);
iron.App.notifyOnUpdate(UIView2D.inst.update);
iron.App.notifyOnRender2D(UISidebar.inst.renderCursor);
iron.App.notifyOnUpdate(UINodes.inst.update);
iron.App.notifyOnRender2D(UINodes.inst.render);
iron.App.notifyOnUpdate(UISidebar.inst.update);
iron.App.notifyOnRender2D(UISidebar.inst.render);
iron.App.notifyOnRender2D(render);
appx = UIToolbar.inst.toolbarw;
appy = UIHeader.inst.headerh * 2;
var cam = Scene.active.camera;
cam.data.raw.fov = Std.int(cam.data.raw.fov * 100) / 100;
cam.buildProjection();
Args.run();
});
});
}
static function saveAndQuitCallback(save: Bool) {
saveWindowRect();
if (save) Project.projectSave(true);
else System.stop();
}
public static function w(): Int {
// Draw material preview
if (UISidebar.inst != null && Context.materialPreview) {
return RenderUtil.matPreviewSize;
}
// Drawing decal preview
if (UISidebar.inst != null && Context.decalPreview) {
return RenderUtil.decalPreviewSize;
}
var res = 0;
if (UINodes.inst == null || UISidebar.inst == null) {
var sidebarw = Config.raw.layout == null ? UISidebar.defaultWindowW : Config.raw.layout[LayoutSidebarW];
res = System.windowWidth() - sidebarw - UIToolbar.defaultToolbarW;
}
else if (UINodes.inst.show || UIView2D.inst.show) {
res = System.windowWidth() - Config.raw.layout[LayoutSidebarW] - Config.raw.layout[LayoutNodesW] - UIToolbar.inst.toolbarw;
}
else if (UISidebar.inst.show) {
res = System.windowWidth() - Config.raw.layout[LayoutSidebarW] - UIToolbar.inst.toolbarw;
}
else { // Distract free
res = System.windowWidth();
}
if (UISidebar.inst != null && Context.viewIndex > -1) {
res = Std.int(res / 2);
}
if (Context.paint2dView) {
res = UIView2D.inst.ww;
}
return res > 0 ? res : 1; // App was minimized, force render path resize
}
public static function h(): Int {
// Draw material preview
if (UISidebar.inst != null && Context.materialPreview) {
return RenderUtil.matPreviewSize;
}
// Drawing decal preview
if (UISidebar.inst != null && Context.decalPreview) {
return RenderUtil.decalPreviewSize;
}
var res = System.windowHeight();
if (UISidebar.inst == null) {
res -= UIHeader.defaultHeaderH * 2 + UIStatus.defaultStatusH;
}
else if (UISidebar.inst != null && UISidebar.inst.show && res > 0) {
var statush = Config.raw.layout[LayoutStatusH];
res -= Std.int(UIHeader.defaultHeaderH * 2 * Config.raw.window_scale) + statush;
}
return res > 0 ? res : 1; // App was minimized, force render path resize
}
public static function x(): Int {
return Context.viewIndex == 1 ? appx + w() : appx;
}
public static function y(): Int {
return appy;
}
#if arm_resizable
static function onResize() {
if (System.windowWidth() == 0 || System.windowHeight() == 0) return;
var ratioW = System.windowWidth() / lastWindowWidth;
lastWindowWidth = System.windowWidth();
var ratioH = System.windowHeight() / lastWindowHeight;
lastWindowHeight = System.windowHeight();
Config.raw.layout[LayoutNodesW] = Std.int(Config.raw.layout[LayoutNodesW] * ratioW);
Config.raw.layout[LayoutSidebarH0] = Std.int(Config.raw.layout[LayoutSidebarH0] * ratioH);
Config.raw.layout[LayoutSidebarH1] = System.windowHeight() - Config.raw.layout[LayoutSidebarH0];
resize();
#if (krom_linux || krom_darwin)
saveWindowRect();
#end
}
#end
static function saveWindowRect() {
#if (krom_windows || krom_linux || krom_darwin)
Config.raw.window_w = System.windowWidth();
Config.raw.window_h = System.windowHeight();
Config.raw.window_x = kha.Window.get(0).x;
Config.raw.window_y = kha.Window.get(0).y;
Config.save();
#end
}
public static function resize() {
if (System.windowWidth() == 0 || System.windowHeight() == 0) return;
var cam = Scene.active.camera;
if (cam.data.raw.ortho != null) {
cam.data.raw.ortho[2] = -2 * (iron.App.h() / iron.App.w());
cam.data.raw.ortho[3] = 2 * (iron.App.h() / iron.App.w());
}
cam.buildProjection();
if (Context.cameraType == CameraOrthographic) {
Viewport.updateCameraType(Context.cameraType);
}
Context.ddirty = 2;
if (UISidebar.inst.show) {
appx = UIToolbar.inst.toolbarw;
appy = UIHeader.inst.headerh * 2;
}
else {
appx = 0;
appy = 0;
}
if (UINodes.inst.grid != null) {
var _grid = UINodes.inst.grid;
function _next() {
_grid.unload();
}
App.notifyOnNextFrame(_next);
UINodes.inst.grid = null;
}
redrawUI();
}
public static function redrawUI() {
UISidebar.inst.hwnd0.redraws = 2;
UISidebar.inst.hwnd1.redraws = 2;
UIHeader.inst.headerHandle.redraws = 2;
UIToolbar.inst.toolbarHandle.redraws = 2;
UIStatus.inst.statusHandle.redraws = 2;
UIMenubar.inst.menuHandle.redraws = 2;
UIMenubar.inst.workspaceHandle.redraws = 2;
UINodes.inst.hwnd.redraws = 2;
UIView2D.inst.hwnd.redraws = 2;
if (Context.ddirty < 0) Context.ddirty = 0; // Redraw viewport
if (Context.splitView) Context.ddirty = 1;
}
static function update() {
var mouse = Input.getMouse();
if (mouse.movementX != 0 || mouse.movementY != 0) {
Krom.setMouseCursor(0); // Arrow
}
var hasDrag = dragAsset != null || dragMaterial != null || dragLayer != null || dragFile != null || dragSwatch != null;
if (hasDrag && (mouse.movementX != 0 || mouse.movementY != 0)) {
isDragging = true;
}
if (mouse.released() && hasDrag) {
var mx = mouse.x;
var my = mouse.y;
var inViewport = Context.paintVec.x < 1 && Context.paintVec.x > 0 &&
Context.paintVec.y < 1 && Context.paintVec.y > 0;
var inLayers = UISidebar.inst.htab0.position == 0 &&
mx > UISidebar.inst.tabx && my < Config.raw.layout[LayoutSidebarH0];
var in2dView = UIView2D.inst.show && UIView2D.inst.type == View2DLayer &&
mx > UIView2D.inst.wx && mx < UIView2D.inst.wx + UIView2D.inst.ww &&
my > UIView2D.inst.wy && my < UIView2D.inst.wy + UIView2D.inst.wh;
var inNodes = UINodes.inst.show &&
mx > UINodes.inst.wx && mx < UINodes.inst.wx + UINodes.inst.ww &&
my > UINodes.inst.wy && my < UINodes.inst.wy + UINodes.inst.wh;
if (dragAsset != null) {
if (inNodes) { // Create image texture
UINodes.inst.acceptAssetDrag(Project.assets.indexOf(dragAsset));
}
else if (inLayers || in2dView) { // Create mask
Layers.createImageMask(dragAsset);
}
else if (inViewport) {
if (dragAsset.file.toLowerCase().endsWith(".hdr")) {
var image = Project.getImage(dragAsset);
arm.io.ImportEnvmap.run(dragAsset.file, image);
}
}
dragAsset = null;
}
else if (dragSwatch != null) {
if (inNodes) { // Create RGB node
UINodes.inst.acceptSwatchDrag(Project.raw.swatches.indexOf(dragSwatch));
}
dragSwatch = null;
}
else if (dragMaterial != null) {
materialDropped(inViewport, inLayers, inNodes);
}
else if (dragLayer != null) {
if (inNodes) {
UINodes.inst.acceptLayerDrag(Project.layers.indexOf(dragLayer));
}
else if (inLayers && isDragging) {
dragLayer.move(Context.dragDestination);
MakeMaterial.parseMeshMaterial();
}
dragLayer = null;
}
else if (dragFile != null) {
var statush = Config.raw.layout[LayoutStatusH];
var inBrowser =
mx > iron.App.x() && mx < iron.App.x() + (System.windowWidth() - UIToolbar.inst.toolbarw - Config.raw.layout[LayoutSidebarW]) &&
my > System.windowHeight() - statush;
if (!inBrowser) {
dropX = mouse.x;
dropY = mouse.y;
var materialCount = Project.materials.length;
ImportAsset.run(dragFile, dropX, dropY, true, true, function() {
// Asset was material
if (Project.materials.length > materialCount) {
dragMaterial = Context.material;
materialDropped(inViewport, inLayers, inNodes);
}
});
}
dragFile = null;
dragFileIcon = null;
}
Krom.setMouseCursor(0); // Arrow
isDragging = false;
}
handleDropPaths();
var decal = Context.tool == ToolDecal || Context.tool == ToolText;
var isPicker = Context.tool == ToolPicker;
#if krom_windows
Zui.alwaysRedrawWindow = !Context.cacheDraws ||
UIMenu.show ||
UIBox.show ||
isDragging ||
isPicker ||
decal ||
UIView2D.inst.show ||
!Config.raw.brush_3d ||
Context.frame < 3;
#end
if (Zui.alwaysRedrawWindow && Context.ddirty < 0) Context.ddirty = 0;
}
static function materialDropped(inViewport: Bool, inLayers: Bool, inNodes: Bool) {
// Material drag and dropped onto viewport or layers tab
if (inViewport || inLayers) {
var uvType = Input.getKeyboard().down("control") ? UVProject : UVMap;
var decalMat = uvType == UVProject ? RenderUtil.getDecalMat() : null;
Layers.createFillLayer(uvType, decalMat);
}
else if (inNodes) {
UINodes.inst.acceptMaterialDrag(Project.materials.indexOf(dragMaterial));
}
dragMaterial = null;
}
static function handleDropPaths() {
if (dropPaths.length > 0) {
var mouse = Input.getMouse();
#if (krom_linux || krom_darwin)
var wait = !mouse.moved; // Mouse coords not updated during drag
#else
var wait = false;
#end
if (!wait) {
dropX = mouse.x;
dropY = mouse.y;
var dropPath = dropPaths.shift();
ImportAsset.run(dropPath, dropX, dropY);
}
}
}
static function getDragBackground(): TRect {
var icons = Res.get("icons.k");
if (dragLayer != null && !dragLayer.isGroup() && dragLayer.fill_layer == null) {
return Res.tile50(icons, 4, 1);
}
return null;
}
static function getDragImage(): kha.Image {
dragTint = 0xffffffff;
dragSize = -1;
dragRect = null;
if (dragAsset != null) {
return Project.getImage(dragAsset);
}
if (dragSwatch != null) {
dragTint = dragSwatch.base;
dragSize = 26;
return TabSwatches.empty;
}
if (dragMaterial != null) {
return dragMaterial.imageIcon;
}
if (dragLayer != null && dragLayer.isGroup()) {
var icons = Res.get("icons.k");
var folderClosed = Res.tile50(icons, 2, 1);
var folderOpen = Res.tile50(icons, 8, 1);
dragRect = dragLayer.show_panel ? folderOpen : folderClosed;
dragTint = UISidebar.inst.ui.t.LABEL_COL - 0x00202020;
return icons;
}
if (dragLayer != null && dragLayer.isMask() && dragLayer.fill_layer == null) {
TabLayers.makeMaskPreviewRgba32(dragLayer);
return TabLayers.maskPreviewRgba32;
}
if (dragLayer != null) {
return dragLayer.fill_layer != null ? dragLayer.fill_layer.imageIcon : dragLayer.texpaint_preview;
}
if (dragFile != null) {
if (dragFileIcon != null) return dragFileIcon;
var icons = Res.get("icons.k");
dragRect = dragFile.indexOf(".") > 0 ? Res.tile50(icons, 3, 1) : Res.tile50(icons, 2, 1);
dragTint = UISidebar.inst.ui.t.HIGHLIGHT_COL;
return icons;
}
return null;
}
static function render(g: kha.graphics2.Graphics) {
if (System.windowWidth() == 0 || System.windowHeight() == 0) return;
if (Context.frame == 2) {
RenderUtil.makeMaterialPreview();
UISidebar.inst.hwnd1.redraws = 2;
MakeMaterial.parseMeshMaterial();
MakeMaterial.parsePaintMaterial();
Context.ddirty = 0;
if (History.undoLayers == null) {
History.undoLayers = [];
for (i in 0...Config.raw.undo_steps) {
var l = new LayerSlot("_undo" + History.undoLayers.length);
History.undoLayers.push(l);
}
}
// Default workspace
if (Config.raw.workspace != 0) {
UIHeader.inst.worktab.position = Config.raw.workspace;
UIMenubar.inst.workspaceHandle.redraws = 2;
if (UIHeader.inst.worktab.position == SpaceBake) {
Context.selectTool(ToolBake);
}
else {
Context.selectTool(ToolGizmo);
}
if (UIHeader.inst.worktab.position == SpaceMaterial) {
Layers.updateFillLayers();
UINodes.inst.show = true;
}
}
}
else if (Context.frame == 3) {
Context.ddirty = Context.renderMode == RenderForward ? 3 : 1;
}
Context.frame++;
var mouse = Input.getMouse();
if (isDragging) {
Krom.setMouseCursor(1); // Hand
var img = getDragImage();
var size = (dragSize == -1 ? 50 : dragSize) * UISidebar.inst.ui.ops.scaleFactor;
var ratio = size / img.width;
var h = img.height * ratio;
#if (kha_direct3d11 || kha_direct3d12 || kha_metal || kha_vulkan)
var inv = 0;
#else
var inv = (dragMaterial != null || (dragLayer != null && dragLayer.fill_layer != null)) ? h : 0;
#end
g.color = dragTint;
var bgRect = getDragBackground();
if (bgRect != null) g.drawScaledSubImage(Res.get("icons.k"), bgRect.x, bgRect.y, bgRect.w, bgRect.h, mouse.x + dragOffX, mouse.y + dragOffY + inv, size, h - inv * 2);
dragRect == null ?
g.drawScaledImage(img, mouse.x + dragOffX, mouse.y + dragOffY + inv, size, h - inv * 2) :
g.drawScaledSubImage(img, dragRect.x, dragRect.y, dragRect.w, dragRect.h, mouse.x + dragOffX, mouse.y + dragOffY + inv, size, h - inv * 2);
g.color = 0xffffffff;
}
var usingMenu = UIMenu.show && mouse.y > UIHeader.inst.headerh;
uiEnabled = !UIBox.show && !usingMenu;
if (UIBox.show) UIBox.render(g);
if (UIMenu.show) UIMenu.render(g);
// Save last pos for continuos paint
Context.lastPaintVecX = Context.paintVec.x;
Context.lastPaintVecY = Context.paintVec.y;
#if (krom_android || krom_ios)
// No mouse move events for touch, re-init last paint position on touch start
if (!mouse.down()) {
Context.lastPaintX = -1;
Context.lastPaintY = -1;
}
#end
}
public static function enumTexts(nodeType: String): Array<String> {
if (nodeType == "TEX_IMAGE") {
return Project.assetNames.length > 0 ? Project.assetNames : [""];
}
else if (nodeType == "LAYER" || nodeType == "LAYER_MASK") {
var layerNames: Array<String> = [];
for (l in Project.layers) layerNames.push(l.name);
return layerNames;
}
else if (nodeType == "MATERIAL") {
var materialNames: Array<String> = [];
for (m in Project.materials) materialNames.push(m.canvas.name);
return materialNames;
}
return null;
}
public static function getAssetIndex(fileName: String): Int {
var i = Project.assetNames.indexOf(fileName);
return i >= 0 ? i : 0;
}
public static function notifyOnNextFrame(f: Void->Void) {
function _render(_) {
iron.App.notifyOnInit(function() {
function _update() {
iron.App.notifyOnInit(f);
iron.App.removeUpdate(_update);
}
iron.App.notifyOnUpdate(_update);
});
iron.App.removeRender(_render);
}
iron.App.notifyOnRender(_render);
}
public static function toggleFullscreen() {
if (kha.Window.get(0).mode == kha.WindowMode.Windowed) {
#if (krom_windows || krom_linux || krom_darwin)
Config.raw.window_w = System.windowWidth();
Config.raw.window_h = System.windowHeight();
Config.raw.window_x = kha.Window.get(0).x;
Config.raw.window_y = kha.Window.get(0).y;
#end
kha.Window.get(0).mode = kha.WindowMode.Fullscreen;
}
else {
kha.Window.get(0).mode = kha.WindowMode.Windowed;
kha.Window.get(0).resize(Config.raw.window_w, Config.raw.window_h);
kha.Window.get(0).move(Config.raw.window_x, Config.raw.window_y);
}
}
public static function isScrolling(): Bool {
for (ui in getUIs()) if (ui.isScrolling) return true;
return false;
}
public static function isComboSelected(): Bool {
for (ui in getUIs()) if (@:privateAccess ui.comboSelectedHandle != null) return true;
return false;
}
public static function getUIs(): Array<Zui> {
return [App.uiBox, App.uiMenu, arm.ui.UISidebar.inst.ui, arm.ui.UINodes.inst.ui, arm.ui.UIView2D.inst.ui];
}
public static function isDecalLayer(): Bool {
var isPaint = UIHeader.inst.worktab.position == SpacePaint;
return isPaint && Context.layer.fill_layer != null && Context.layer.uvType == UVProject;
}
public static function redrawStatus() {
if (arm.ui.UIStatus.inst != null) {
arm.ui.UIStatus.inst.statusHandle.redraws = 2;
}
}
public static function redrawConsole() {
var statush = Config.raw.layout[LayoutStatusH];
if (arm.ui.UIStatus.inst != null && arm.ui.UISidebar.inst != null && arm.ui.UISidebar.inst.ui != null && statush > arm.ui.UIStatus.defaultStatusH * arm.ui.UISidebar.inst.ui.SCALE()) {
arm.ui.UIStatus.inst.statusHandle.redraws = 2;
}
}
public static function initLayout() {
var show2d = (UINodes.inst != null && UINodes.inst.show) || (UIView2D.inst != null && UIView2D.inst.show);
var raw = Config.raw;
raw.layout = [
Std.int(UISidebar.defaultWindowW * raw.window_scale),
Std.int(kha.System.windowHeight() / 2),
Std.int(kha.System.windowHeight() / 2),
show2d ? Std.int((iron.App.w() + raw.layout[LayoutNodesW]) / 2) : Std.int(iron.App.w() / 2),
Std.int(iron.App.h() / 2),
Std.int(UIStatus.defaultStatusH * raw.window_scale)
];
}
public static function initConfig() {
var raw = Config.raw;
raw.recent_projects = [];
raw.bookmarks = [];
raw.plugins = [];
raw.keymap = "default.json";
raw.theme = "default.json";
raw.server = "https://armorpaint.fra1.digitaloceanspaces.com";
raw.undo_steps = 4;
raw.pressure_radius = true;
raw.pressure_hardness = true;
raw.pressure_angle = false;
raw.pressure_opacity = false;
raw.pressure_sensitivity = 1.0;
#if kha_vulkan
raw.material_live = false;
#else
raw.material_live = true;
#end
raw.brush_3d = true;
raw.brush_depth_reject = true;
raw.brush_angle_reject = true;
raw.brush_live = false;
raw.camera_speed = 1.0;
raw.zoom_direction = ZoomVertical;
raw.displace_strength = 0.0;
raw.show_asset_names = false;
raw.wrap_mouse = false;
raw.node_preview = true;
raw.workspace = 0;
raw.layer_res = Res2048;
raw.dilate = DilateInstant;
raw.dilate_radius = 2;
}
}