Add swatches tab

This commit is contained in:
luboslenco
2021-01-29 20:51:46 +01:00
parent b6b75b26b8
commit d8dcea5619
12 changed files with 214 additions and 46 deletions
+11 -11
View File
@@ -61,17 +61,8 @@ class Context {
public static var viewIndexLast = -1;
public static var materialPreview = false; // Drawing material previews
public static var savedCamera = Mat4.identity();
public static var baseRPicked = 0.0;
public static var baseGPicked = 0.0;
public static var baseBPicked = 0.0;
public static var normalRPicked = 0.0;
public static var normalGPicked = 0.0;
public static var normalBPicked = 0.0;
public static var opacityPicked = 0.0;
public static var roughnessPicked = 0.0;
public static var metallicPicked = 0.0;
public static var occlusionPicked = 0.0;
public static var heightPicked = 0.0;
public static var swatch: TSwatch;
public static var materialIdPicked = 0;
public static var uvxPicked = 0.0;
public static var uvyPicked = 0.0;
@@ -318,6 +309,15 @@ class Context {
UIView2D.inst.hwnd.redraws = 2;
}
public static function setSwatch(s: TSwatch) {
swatch = s;
App.notifyOnNextFrame(function() {
MakeMaterial.parsePaintMaterial();
RenderUtil.makeMaterialPreview();
UISidebar.inst.hwnd1.redraws = 2;
});
}
public static function setLayer(l: LayerSlot, isMask = false) {
if (l == layer && layerIsMask == isMask) return;
layer = l;
+12
View File
@@ -253,6 +253,8 @@ class Project {
var fontNames = App.font.getFontNames();
fonts = [new FontSlot(fontNames.length > 0 ? fontNames[0] : "default.ttf", App.font)];
Context.font = fonts[0];
Project.raw.swatches = [makeSwatch()];
Context.swatch = Project.raw.swatches[0];
History.reset();
@@ -463,6 +465,16 @@ class Project {
for (pa in packed_assets) if (pa.name == name) return true;
return false;
}
public static function exportSwatches() {
UIFiles.show("arm", true, function(path: String) {
ExportArm.runSwatches(path);
});
}
public static function makeSwatch(): TSwatch {
return { base: 0xffffffff, opacity: 1.0, occlusion: 1.0, roughness: 0.0, metallic: 0.0, normal: 0xff8080ff, emission: 0.0, height: 0.0, subsurface: 0.0 };
}
}
typedef TNodeGroup = {
+13
View File
@@ -17,6 +17,7 @@ typedef TProjectFormat = {
@:optional public var mesh_assets: Array<String>;
@:optional public var atlas_objects: Array<Int>;
@:optional public var atlas_names: Array<String>;
@:optional public var swatches: Array<TSwatch>;
@:optional public var is_bgra: Null<Bool>; // Swapped red and blue channels for layer textures
@:optional public var packed_assets: Array<TPackedAsset>;
}
@@ -62,3 +63,15 @@ typedef TPackedAsset = {
public var name: String;
public var bytes: haxe.io.Bytes;
}
typedef TSwatch = {
public var base: kha.Color;
public var opacity: Float;
public var occlusion: Float;
public var roughness: Float;
public var metallic: Float;
public var normal: kha.Color;
public var emission: Float;
public var height: Float;
public var subsurface: Float;
}
+11
View File
@@ -102,6 +102,7 @@ class ExportArm {
mesh_assets: mesh_files,
atlas_objects: Project.atlasObjects,
atlas_names: Project.atlasNames,
swatches: Project.raw.swatches,
packed_assets: packed_assets,
#if (kha_metal || kha_vulkan)
is_bgra: true
@@ -347,4 +348,14 @@ class ExportArm {
for (image in tempImages) image.unload();
});
}
public static function runSwatches(path: String) {
if (!path.endsWith(".arm")) path += ".arm";
var raw = {
version: Main.version,
swatches: Project.raw.swatches
};
var bytes = ArmPack.encode(raw);
Krom.fileSaveBytes(path, bytes.getData(), bytes.length + 1);
}
}
+12
View File
@@ -75,6 +75,10 @@ class ImportArm {
else if (project.brush_nodes != null) {
runBrushFromProject(project, path);
}
// Import as swatches
else if (project.swatches != null) {
runSwatchesFromProject(project, path);
}
return;
}
@@ -465,6 +469,14 @@ class ImportArm {
Data.deleteBlob(path);
}
public static function runSwatchesFromProject(project: TProjectFormat, path: String) {
for (s in project.swatches) {
Project.raw.swatches.push(s);
}
UISidebar.inst.hwnd2.redraws = 2;
Data.deleteBlob(path);
}
static function makePink(abs: String) {
Log.error(Strings.error2() + " " + abs);
var b = Bytes.alloc(4);
+11 -9
View File
@@ -9,6 +9,7 @@ import iron.Scene;
import arm.util.ViewportUtil;
import arm.ui.UIView2D;
import arm.ui.UIHeader;
import arm.ui.UISidebar;
import arm.node.MakeMaterial;
import arm.Enums;
@@ -177,6 +178,7 @@ class RenderPathPaint {
path.bindTarget("texpaint_pack" + tid, "texpaint_pack");
path.drawMeshes("paint");
UIHeader.inst.headerHandle.redraws = 2;
UISidebar.inst.hwnd2.redraws = 2;
var texpaint_picker = path.renderTargets.get("texpaint_picker").image;
var texpaint_nor_picker = path.renderTargets.get("texpaint_nor_picker").image;
@@ -186,17 +188,17 @@ class RenderPathPaint {
var c = texpaint_pack_picker.getPixels();
// Picked surface values
Context.baseRPicked = a.get(0) / 255;
Context.baseGPicked = a.get(1) / 255;
Context.baseBPicked = a.get(2) / 255;
Context.swatch.base.Rb = a.get(0);
Context.swatch.base.Gb = a.get(1);
Context.swatch.base.Bb = a.get(2);
Context.uvxPicked = a.get(3) / 255;
Context.normalRPicked = b.get(0) / 255;
Context.normalGPicked = b.get(1) / 255;
Context.normalBPicked = b.get(2) / 255;
Context.swatch.normal.Rb = b.get(0);
Context.swatch.normal.Gb = b.get(1);
Context.swatch.normal.Bb = b.get(2);
Context.uvyPicked = c.get(3) / 255;
Context.occlusionPicked = c.get(0) / 255;
Context.roughnessPicked = c.get(1) / 255;
Context.metallicPicked = c.get(2) / 255;
Context.swatch.occlusion = c.get(0) / 255;
Context.swatch.roughness = c.get(1) / 255;
Context.swatch.metallic = c.get(2) / 255;
// Pick material
if (Context.pickerSelectMaterial) {
var matid = b.get(3);
+7 -7
View File
@@ -101,19 +101,19 @@ class Uniforms {
return Context.layer.decalMat.getScale().z * 0.5;
}
case "_pickerOpacity": {
return Context.opacityPicked;
return Context.swatch.opacity;
}
case "_pickerOcclusion": {
return Context.occlusionPicked;
return Context.swatch.occlusion;
}
case "_pickerRoughness": {
return Context.roughnessPicked;
return Context.swatch.roughness;
}
case "_pickerMetallic": {
return Context.metallicPicked;
return Context.swatch.metallic;
}
case "_pickerHeight": {
return Context.heightPicked;
return Context.swatch.height;
}
}
if (MaterialParser.script_links != null) {
@@ -198,12 +198,12 @@ class Uniforms {
}
case "_pickerBase": {
v = iron.object.Uniforms.helpVec;
v.set(Context.baseRPicked, Context.baseGPicked, Context.baseBPicked);
v.set(Context.swatch.base.R, Context.swatch.base.G, Context.swatch.base.B);
return v;
}
case "_pickerNormal": {
v = iron.object.Uniforms.helpVec;
v.set(Context.normalRPicked, Context.normalGPicked, Context.normalBPicked);
v.set(Context.swatch.normal.R, Context.swatch.normal.G, Context.swatch.normal.B);
return v;
}
}
+8
View File
@@ -60,6 +60,14 @@ class TabMeshes {
var h = Id.handle();
h.selected = o.visible;
o.visible = ui.check(h, o.name);
if (ui.isHovered && ui.inputReleasedR) {
UIMenu.draw(function(ui: Zui) {
ui.text(o.name, Right, ui.t.HIGHLIGHT_COL);
if (ui.button(tr("Export"), Left)) {
BoxExport.showMesh();
}
}, 2);
}
if (h.changed) {
var visibles: Array<MeshObject> = [];
for (p in Project.paintObjects) if (p.visible) visibles.push(p);
+110
View File
@@ -0,0 +1,110 @@
package arm.ui;
import zui.Zui;
import zui.Id;
import iron.system.Time;
import iron.system.Input;
import arm.io.ImportFont;
import arm.util.RenderUtil;
import arm.Enums;
class TabSwatches {
static var empty: kha.Image = null;
@:access(zui.Zui)
public static function draw() {
var ui = UISidebar.inst.ui;
if (ui.tab(UISidebar.inst.htab2, tr("Swatches"))) {
ui.beginSticky();
ui.row([1 / 4, 1 / 4, 1 / 4]);
if (ui.button(tr("New"))) {
Context.setSwatch(Project.makeSwatch());
Project.raw.swatches.push(Context.swatch);
}
if (ui.button(tr("Import"))) Project.importAsset("arm");
if (ui.isHovered) ui.tooltip(tr("Import swatches") + ' (${Config.keymap.file_import_assets})');
if (ui.button(tr("Tools..."))) {
UIMenu.draw(function(ui: Zui) {
ui.text(tr("Tools"), Right, ui.t.HIGHLIGHT_COL);
if (ui.button(tr("Clear"), Left)) {
Project.raw.swatches = [Project.makeSwatch()];
}
}, 3);
}
ui.endSticky();
ui.separator(3, false);
var slotw = Std.int(26 * ui.SCALE());
var num = Std.int(Config.raw.layout[LayoutSidebarW] / (slotw + 3));
for (row in 0...Std.int(Math.ceil(Project.raw.swatches.length / num))) {
ui.row([for (i in 0...num) 1 / num]);
ui._x += 2;
if (row > 0) ui._y += 6;
for (j in 0...num) {
var imgw = Std.int(20 * ui.SCALE());
var i = j + row * num;
if (i >= Project.raw.swatches.length) {
@:privateAccess ui.endElement(imgw);
continue;
}
if (Context.swatch == Project.raw.swatches[i]) {
var off = row % 2 == 1 ? 1 : 0;
var w = 32;
if (Config.raw.window_scale > 1) w += Std.int(Config.raw.window_scale * 2);
ui.fill(-2, -2, w, w, ui.t.HIGHLIGHT_COL);
}
if (empty == null) {
var b = haxe.io.Bytes.alloc(4);
b.set(0, 255);
b.set(1, 255);
b.set(2, 255);
b.set(3, 255);
empty = kha.Image.fromBytes(b, 1, 1);
}
var state = ui.image(empty, Project.raw.swatches[i].base, slotw);
if (state == State.Started) {
Context.setSwatch(Project.raw.swatches[i]);
}
else if (state == State.Released) {
if (Time.time() - Context.selectTime < 0.25) {
UIMenu.draw(function(ui) {
ui.fill(0, 0, ui._w / ui.ops.scaleFactor, ui.t.ELEMENT_H * 9, ui.t.SEPARATOR_COL);
ui.changed = false;
var h = Id.handle();
h.color = Context.swatch.base;
Context.swatch.base = zui.Ext.colorWheel(ui, h, false, null, false);
if (ui.changed) UIMenu.keepOpen = true;
if (ui.inputReleased) Context.setSwatch(Context.swatch); // Trigger material preview update
}, 3, Std.int(Input.getMouse().x) - 200, Std.int(Input.getMouse().y) - 250);
}
Context.selectTime = Time.time();
}
if (ui.isHovered && ui.inputReleasedR) {
var add = Project.raw.swatches.length > 1 ? 1 : 0;
UIMenu.draw(function(ui: Zui) {
ui.text(tr("Swatch"), Right, ui.t.HIGHLIGHT_COL);
if (Project.raw.swatches.length > 1 && ui.button(tr("Delete"), Left)) {
Context.setSwatch(Project.raw.swatches[i == 0 ? 1 : 0]);
Project.raw.swatches.splice(i, 1);
UISidebar.inst.hwnd2.redraws = 2;
}
}, 1 + add);
}
if (ui.isHovered) ui.tooltip(tr("Swatch"));
}
}
}
}
}
+9 -18
View File
@@ -44,24 +44,15 @@ class UIHeader {
if (Project.assets.length > 0) ui.image(Project.getImage(Project.assets[cid]));
}
else if (Context.tool == ToolPicker) {
Context.baseRPicked = Math.round(Context.baseRPicked * 10) / 10;
Context.baseGPicked = Math.round(Context.baseGPicked * 10) / 10;
Context.baseBPicked = Math.round(Context.baseBPicked * 10) / 10;
Context.normalRPicked = Math.round(Context.normalRPicked * 10) / 10;
Context.normalGPicked = Math.round(Context.normalGPicked * 10) / 10;
Context.normalBPicked = Math.round(Context.normalBPicked * 10) / 10;
Context.occlusionPicked = Math.round(Context.occlusionPicked * 100) / 100;
Context.roughnessPicked = Math.round(Context.roughnessPicked * 100) / 100;
Context.metallicPicked = Math.round(Context.metallicPicked * 100) / 100;
var baseRPicked = Context.baseRPicked;
var baseGPicked = Context.baseGPicked;
var baseBPicked = Context.baseBPicked;
var normalRPicked = Context.normalRPicked;
var normalGPicked = Context.normalGPicked;
var normalBPicked = Context.normalBPicked;
var occlusionPicked = Context.occlusionPicked;
var roughnessPicked = Context.roughnessPicked;
var metallicPicked = Context.metallicPicked;
var baseRPicked = Math.round(Context.swatch.base.R * 10) / 10;
var baseGPicked = Math.round(Context.swatch.base.G * 10) / 10;
var baseBPicked = Math.round(Context.swatch.base.B * 10) / 10;
var normalRPicked = Math.round(Context.swatch.normal.R * 10) / 10;
var normalGPicked = Math.round(Context.swatch.normal.G * 10) / 10;
var normalBPicked = Math.round(Context.swatch.normal.B * 10) / 10;
var occlusionPicked = Math.round(Context.swatch.occlusion * 100) / 100;
var roughnessPicked = Math.round(Context.swatch.roughness * 100) / 100;
var metallicPicked = Math.round(Context.swatch.metallic * 100) / 100;
#if kha_metal
ui.text('TODO'); // Skips first draw
#end
+3 -1
View File
@@ -54,7 +54,7 @@ class UIMenu {
}
else {
var menuItems = [
16, // MenuFile
18, // MenuFile
4, // MenuEdit
#if (krom_windows || krom_linux) 14 #else 13 #end, // MenuViewport
#if (kha_direct3d12 || kha_vulkan) 13 #else 12 #end, // MenuMode
@@ -76,6 +76,7 @@ class UIMenu {
if (ui.button(" " + tr("Import Font..."), Left)) Project.importAsset("ttf,ttc,otf");
if (ui.button(" " + tr("Import Material..."), Left)) Project.importMaterial();
if (ui.button(" " + tr("Import Brush..."), Left)) Project.importBrush();
if (ui.button(" " + tr("Import Swatches..."), Left)) Project.importAsset("arm");
if (ui.button(" " + tr("Import Mesh..."), Left)) Project.importMesh();
if (ui.button(" " + tr("Reimport Mesh"), Left, Config.keymap.file_reimport_mesh)) Project.reimportMesh();
if (ui.button(" " + tr("Reimport Textures"), Left, Config.keymap.file_reimport_textures)) Project.reimportTextures();
@@ -84,6 +85,7 @@ class UIMenu {
Context.layersExport = ExportVisible;
BoxExport.showTextures();
}
if (ui.button(" " + tr("Export Swatches..."), Left)) Project.exportSwatches();
if (ui.button(" " + tr("Export Mesh..."), Left)) BoxExport.showMesh();
if (ui.button(" " + tr("Bake Material..."), Left)) BoxExport.showBakeMaterial();
ui.fill(0, 0, sepw, 1, ui.t.ACCENT_SELECT_COL);
+7
View File
@@ -89,6 +89,12 @@ class UISidebar {
Context.layer = Project.layers[0];
}
if (Project.raw.swatches == null) {
Project.raw.swatches = [];
Project.raw.swatches.push(Project.makeSwatch());
Context.swatch = Project.raw.swatches[0];
}
if (Context.emptyEnvmap == null) {
var b = Bytes.alloc(4);
b.set(0, 3);
@@ -682,6 +688,7 @@ class UISidebar {
TabTextures.draw();
TabMeshes.draw();
TabFonts.draw();
TabSwatches.draw();
}
ui.end();