Files
armorpaint/base/Sources/TabMaterials.ts
T
luboslenco 156f3eb274 Refactor
2024-02-10 19:26:53 +01:00

337 lines
11 KiB
TypeScript

///if (is_paint || is_sculpt)
class TabMaterials {
static draw = (htab: zui_handle_t) => {
let mini = Config.raw.layout[LayoutSize.LayoutSidebarW] <= UIBase.sidebarMiniW;
mini ? TabMaterials.drawMini(htab) : TabMaterials.drawFull(htab);
}
static drawMini = (htab: zui_handle_t) => {
let ui = UIBase.ui;
zui_set_hovered_tab_name(tr("Materials"));
zui_begin_sticky();
zui_separator(5);
TabMaterials.buttonNodes();
TabMaterials.buttonNew("+");
zui_end_sticky();
zui_separator(3, false);
TabMaterials.drawSlots(true);
}
static drawFull = (htab: zui_handle_t) => {
let ui = UIBase.ui;
if (zui_tab(htab, tr("Materials"))) {
zui_begin_sticky();
zui_row([1 / 4, 1 / 4, 1 / 4]);
TabMaterials.buttonNew(tr("New"));
if (zui_button(tr("Import"))) {
Project.importMaterial();
}
TabMaterials.buttonNodes();
zui_end_sticky();
zui_separator(3, false);
TabMaterials.drawSlots(false);
}
}
static buttonNodes = () => {
let ui = UIBase.ui;
if (zui_button(tr("Nodes"))) {
UIBase.showMaterialNodes();
}
else if (ui.is_hovered) zui_tooltip(tr("Show Node Editor") + ` (${Config.keymap.toggle_node_editor})`);
}
static drawSlots = (mini: bool) => {
let ui = UIBase.ui;
let slotw = Math.floor(51 * zui_SCALE(ui));
let num = Math.floor(Config.raw.layout[LayoutSize.LayoutSidebarW] / slotw);
for (let row = 0; row < Math.floor(Math.ceil(Project.materials.length / num)); ++row) {
let mult = Config.raw.show_asset_names ? 2 : 1;
let ar = [];
for (let i = 0; i < num * mult; ++i) ar.push(1 / num);
zui_row(ar);
ui._x += 2;
let off = Config.raw.show_asset_names ? zui_ELEMENT_OFFSET(ui) * 10.0 : 6;
if (row > 0) ui._y += off;
for (let j = 0; j < num; ++j) {
let imgw = Math.floor(50 * zui_SCALE(ui));
let i = j + row * num;
if (i >= Project.materials.length) {
zui_end_element(imgw);
if (Config.raw.show_asset_names) zui_end_element(0);
continue;
}
let img = zui_SCALE(ui) > 1 ? Project.materials[i].image : Project.materials[i].imageIcon;
let imgFull = Project.materials[i].image;
// Highligh selected
if (Context.raw.material == Project.materials[i]) {
if (mini) {
let w = ui._w / zui_SCALE(ui);
zui_rect(0, -2, w - 2, w - 4, ui.t.HIGHLIGHT_COL, 3);
}
else {
let off = row % 2 == 1 ? 1 : 0;
let w = 50;
if (Config.raw.window_scale > 1) w += Math.floor(Config.raw.window_scale * 2);
zui_fill(-1, -2, w + 3, 2, ui.t.HIGHLIGHT_COL);
zui_fill(-1, w - off, w + 3, 2 + off, ui.t.HIGHLIGHT_COL);
zui_fill(-1, -2, 2, w + 3, ui.t.HIGHLIGHT_COL);
zui_fill(w + 1, -2, 2, w + 4, ui.t.HIGHLIGHT_COL);
}
}
///if krom_opengl
ui.image_invert_y = Project.materials[i].previewReady;
///end
// Draw material icon
let uix = ui._x;
let uiy = ui._y;
let tile = zui_SCALE(ui) > 1 ? 100 : 50;
let imgh: Null<f32> = mini ? UIBase.defaultSidebarMiniW * 0.85 * zui_SCALE(ui) : null;
let state = Project.materials[i].previewReady ?
zui_image(img, 0xffffffff, imgh) :
zui_image(Res.get("icons.k"), 0xffffffff, null, tile, tile, tile, tile);
// Draw material numbers when selecting a material via keyboard shortcut
let isTyping = ui.is_typing || UIView2D.ui.is_typing || UINodes.ui.is_typing;
if (!isTyping) {
if (i < 9 && Operator.shortcut(Config.keymap.select_material, ShortcutType.ShortcutDown)) {
let number = String(i + 1);
let width = g2_font_width(ui.font, ui.font_size, number) + 10;
let height = g2_font_height(ui.font, ui.font_size);
g2_set_color(ui.t.TEXT_COL);
g2_fill_rect(uix, uiy, width, height);
g2_set_color(ui.t.ACCENT_COL);
g2_draw_string(number, uix + 5, uiy);
}
}
// Select material
if (state == State.Started && ui.input_y > ui._window_y) {
if (Context.raw.material != Project.materials[i]) {
Context.selectMaterial(i);
///if is_paint
if (Context.raw.tool == WorkspaceTool.ToolMaterial) {
let _init = () => {
Base.updateFillLayers();
}
app_notify_on_init(_init);
}
///end
}
Base.dragOffX = -(mouse_x - uix - ui._window_x - 3);
Base.dragOffY = -(mouse_y - uiy - ui._window_y + 1);
Base.dragMaterial = Context.raw.material;
// Double click to show nodes
if (time_time() - Context.raw.selectTime < 0.25) {
UIBase.showMaterialNodes();
Base.dragMaterial = null;
Base.isDragging = false;
}
Context.raw.selectTime = time_time();
}
// Context menu
if (ui.is_hovered && ui.input_released_r) {
Context.selectMaterial(i);
let add = Project.materials.length > 1 ? 1 : 0;
UIMenu.draw((ui: zui_t) => {
let m = Project.materials[i];
if (UIMenu.menuButton(ui, tr("To Fill Layer"))) {
Context.selectMaterial(i);
Base.createFillLayer();
}
if (UIMenu.menuButton(ui, tr("Export"))) {
Context.selectMaterial(i);
BoxExport.showMaterial();
}
///if is_paint
if (UIMenu.menuButton(ui, tr("Bake"))) {
Context.selectMaterial(i);
BoxExport.showBakeMaterial();
}
///end
if (UIMenu.menuButton(ui, tr("Duplicate"))) {
let _init = () => {
Context.raw.material = SlotMaterial.create(Project.materials[0].data);
Project.materials.push(Context.raw.material);
let cloned = JSON.parse(JSON.stringify(Project.materials[i].canvas));
Context.raw.material.canvas = cloned;
TabMaterials.updateMaterial();
History.duplicateMaterial();
}
app_notify_on_init(_init);
}
if (Project.materials.length > 1 && UIMenu.menuButton(ui, tr("Delete"), "delete")) {
TabMaterials.deleteMaterial(m);
}
let baseHandle = zui_nest(zui_handle("tabmaterials_0"), m.id, {selected: m.paintBase});
let opacHandle = zui_nest(zui_handle("tabmaterials_1"), m.id, {selected: m.paintOpac});
let norHandle = zui_nest(zui_handle("tabmaterials_2"), m.id, {selected: m.paintNor});
let occHandle = zui_nest(zui_handle("tabmaterials_3"), m.id, {selected: m.paintOcc});
let roughHandle = zui_nest(zui_handle("tabmaterials_4"), m.id, {selected: m.paintRough});
let metHandle = zui_nest(zui_handle("tabmaterials_5"), m.id, {selected: m.paintMet});
let heightHandle = zui_nest(zui_handle("tabmaterials_6"), m.id, {selected: m.paintHeight});
let emisHandle = zui_nest(zui_handle("tabmaterials_7"), m.id, {selected: m.paintEmis});
let subsHandle = zui_nest(zui_handle("tabmaterials_8"), m.id, {selected: m.paintSubs});
UIMenu.menuFill(ui);
m.paintBase = zui_check(baseHandle, tr("Base Color"));
UIMenu.menuFill(ui);
m.paintOpac = zui_check(opacHandle, tr("Opacity"));
UIMenu.menuFill(ui);
m.paintNor = zui_check(norHandle, tr("Normal"));
UIMenu.menuFill(ui);
m.paintOcc = zui_check(occHandle, tr("Occlusion"));
UIMenu.menuFill(ui);
m.paintRough = zui_check(roughHandle, tr("Roughness"));
UIMenu.menuFill(ui);
m.paintMet = zui_check(metHandle, tr("Metallic"));
UIMenu.menuFill(ui);
m.paintHeight = zui_check(heightHandle, tr("Height"));
UIMenu.menuFill(ui);
m.paintEmis = zui_check(emisHandle, tr("Emission"));
UIMenu.menuFill(ui);
m.paintSubs = zui_check(subsHandle, tr("Subsurface"));
if (baseHandle.changed ||
opacHandle.changed ||
norHandle.changed ||
occHandle.changed ||
roughHandle.changed ||
metHandle.changed ||
heightHandle.changed ||
emisHandle.changed ||
subsHandle.changed) {
MakeMaterial.parsePaintMaterial();
UIMenu.keepOpen = true;
}
}, 13 + add);
}
if (ui.is_hovered) {
zui_tooltip_image(imgFull);
if (i < 9) zui_tooltip(Project.materials[i].canvas.name + " - (" + Config.keymap.select_material + " " + (i + 1) + ")");
else zui_tooltip(Project.materials[i].canvas.name);
}
if (Config.raw.show_asset_names) {
ui._x = uix;
ui._y += slotw * 0.9;
zui_text(Project.materials[i].canvas.name, Align.Center);
if (ui.is_hovered) {
if (i < 9) zui_tooltip(Project.materials[i].canvas.name + " - (" + Config.keymap.select_material + " " + (i + 1) + ")");
else zui_tooltip(Project.materials[i].canvas.name);
}
ui._y -= slotw * 0.9;
if (i == Project.materials.length - 1) {
ui._y += j == num - 1 ? imgw : imgw + zui_ELEMENT_H(ui) + zui_ELEMENT_OFFSET(ui);
}
}
}
ui._y += mini ? 0 : 6;
///if krom_opengl
ui.image_invert_y = false; // Material preview
///end
}
let inFocus = ui.input_x > ui._window_x && ui.input_x < ui._window_x + ui._window_w &&
ui.input_y > ui._window_y && ui.input_y < ui._window_y + ui._window_h;
if (inFocus && ui.is_delete_down && Project.materials.length > 1) {
ui.is_delete_down = false;
TabMaterials.deleteMaterial(Context.raw.material);
}
}
static buttonNew = (text: string) => {
let ui = UIBase.ui;
if (zui_button(text)) {
let current = _g2_current;
g2_end();
Context.raw.material = SlotMaterial.create(Project.materials[0].data);
Project.materials.push(Context.raw.material);
TabMaterials.updateMaterial();
g2_begin(current, false);
History.newMaterial();
}
}
static updateMaterial = () => {
UIHeader.headerHandle.redraws = 2;
UINodes.hwnd.redraws = 2;
UINodes.groupStack = [];
MakeMaterial.parsePaintMaterial();
UtilRender.makeMaterialPreview();
let decal = Context.raw.tool == WorkspaceTool.ToolDecal || Context.raw.tool == WorkspaceTool.ToolText;
if (decal) UtilRender.makeDecalPreview();
}
static updateMaterialPointers = (nodes: zui_node_t[], i: i32) => {
for (let n of nodes) {
if (n.type == "MATERIAL") {
if (n.buttons[0].default_value == i) {
n.buttons[0].default_value = 9999; // Material deleted
}
else if (n.buttons[0].default_value > i) {
n.buttons[0].default_value--; // Offset by deleted material
}
}
}
}
static acceptSwatchDrag = (swatch: TSwatchColor) => {
Context.raw.material = SlotMaterial.create(Project.materials[0].data);
for (let node of Context.raw.material.canvas.nodes) {
if (node.type == "RGB" ) {
node.outputs[0].default_value = [
color_get_rb(swatch.base) / 255,
color_get_gb(swatch.base) / 255,
color_get_bb(swatch.base) / 255,
color_get_ab(swatch.base) / 255
];
}
else if (node.type == "OUTPUT_MATERIAL_PBR") {
node.inputs[1].default_value = swatch.opacity;
node.inputs[2].default_value = swatch.occlusion;
node.inputs[3].default_value = swatch.roughness;
node.inputs[4].default_value = swatch.metallic;
node.inputs[7].default_value = swatch.height;
}
}
Project.materials.push(Context.raw.material);
TabMaterials.updateMaterial();
History.newMaterial();
}
static deleteMaterial = (m: SlotMaterialRaw) => {
let i = Project.materials.indexOf(m);
for (let l of Project.layers) if (l.fill_layer == m) l.fill_layer = null;
History.deleteMaterial();
Context.selectMaterial(i == Project.materials.length - 1 ? i - 1 : i + 1);
Project.materials.splice(i, 1);
UIBase.hwnds[1].redraws = 2;
for (let m of Project.materials) TabMaterials.updateMaterialPointers(m.canvas.nodes, i);
}
}
///end