Files
armorpaint/base/Sources/TabSwatches.ts
T

254 lines
9.1 KiB
TypeScript
Raw Normal View History

2021-01-29 20:51:46 +01:00
class TabSwatches {
2024-02-05 20:57:20 +01:00
static _empty: image_t;
2024-03-07 20:37:30 +01:00
static drag_pos: i32 = -1;
2024-01-17 18:53:31 +01:00
2024-02-05 20:57:20 +01:00
static set empty(image: image_t) {
2024-01-17 18:53:31 +01:00
TabSwatches._empty = image;
}
2022-03-02 17:37:06 +01:00
2024-02-05 20:57:20 +01:00
static get empty(): image_t {
2024-01-17 18:53:31 +01:00
if (TabSwatches._empty == null) {
2024-03-07 20:37:30 +01:00
let b: Uint8Array = new Uint8Array(4);
2023-12-07 23:35:02 +01:00
b[0] = 255;
b[1] = 255;
b[2] = 255;
b[3] = 255;
2024-02-05 20:57:20 +01:00
TabSwatches._empty = image_from_bytes(b.buffer, 1, 1);
2022-03-02 17:37:06 +01:00
}
2024-01-17 18:53:31 +01:00
return TabSwatches._empty;
2022-03-02 17:37:06 +01:00
}
2024-02-06 19:32:21 +01:00
static draw = (htab: zui_handle_t) => {
2024-03-07 20:37:30 +01:00
let ui: zui_t = UIBase.ui;
let statush: i32 = Config.raw.layout[layout_size_t.STATUS_H];
if (zui_tab(htab, tr("Swatches")) && statush > UIStatus.default_status_h * zui_SCALE(ui)) {
2021-01-29 20:51:46 +01:00
2024-02-06 19:32:21 +01:00
zui_begin_sticky();
2022-11-29 19:25:16 +01:00
if (Config.raw.touch_ui) {
2024-02-06 19:32:21 +01:00
zui_row([1 / 5, 1 / 5, 1 / 5, 1 / 5, 1 / 5]);
2022-11-29 19:25:16 +01:00
}
else {
2024-02-06 19:32:21 +01:00
zui_row([1 / 14, 1 / 14, 1 / 14, 1 / 14, 1 / 14]);
2022-11-29 19:25:16 +01:00
}
2021-01-29 20:51:46 +01:00
2024-02-06 19:32:21 +01:00
if (zui_button(tr("New"))) {
2024-03-07 20:37:30 +01:00
Context.set_swatch(Project.make_swatch());
2023-02-27 21:13:25 +01:00
Project.raw.swatches.push(Context.raw.swatch);
2021-01-29 20:51:46 +01:00
}
2024-02-06 19:32:21 +01:00
if (ui.is_hovered) zui_tooltip(tr("Add new swatch"));
2021-08-03 15:02:15 +02:00
2024-02-06 19:32:21 +01:00
if (zui_button(tr("Import"))) {
UIMenu.draw((ui: zui_t) => {
2024-03-07 20:37:30 +01:00
if (UIMenu.menu_button(ui, tr("Replace Existing"))) {
Project.import_swatches(true);
Context.set_swatch(Project.raw.swatches[0]);
2022-01-28 16:07:07 +01:00
}
2024-03-07 20:37:30 +01:00
if (UIMenu.menu_button(ui, tr("Append"))) {
Project.import_swatches(false);
2022-01-28 16:07:07 +01:00
}
2023-05-18 22:53:58 +02:00
}, 2);
2023-12-07 23:35:02 +01:00
}
2024-02-06 19:32:21 +01:00
if (ui.is_hovered) zui_tooltip(tr("Import swatches"));
2021-08-03 15:02:15 +02:00
2024-03-07 20:37:30 +01:00
if (zui_button(tr("Export"))) Project.export_swatches();
2024-02-06 19:32:21 +01:00
if (ui.is_hovered) zui_tooltip(tr("Export swatches"));
2022-01-28 16:07:07 +01:00
2024-02-06 19:32:21 +01:00
if (zui_button(tr("Clear"))) {
2024-03-07 20:37:30 +01:00
Context.set_swatch(Project.make_swatch());
2023-02-27 21:13:25 +01:00
Project.raw.swatches = [Context.raw.swatch];
2021-08-03 15:02:15 +02:00
}
2024-02-06 19:32:21 +01:00
if (zui_button(tr("Restore"))) {
2024-03-07 20:37:30 +01:00
Project.set_default_swatches();
Context.set_swatch(Project.raw.swatches[0]);
2021-01-29 20:51:46 +01:00
}
2024-02-06 19:32:21 +01:00
if (ui.is_hovered) zui_tooltip(tr("Restore default swatches"));
2021-01-29 20:51:46 +01:00
2024-02-06 19:32:21 +01:00
zui_end_sticky();
zui_separator(3, false);
2021-01-29 20:51:46 +01:00
2024-03-07 20:37:30 +01:00
let slotw: i32 = Math.floor(26 * zui_SCALE(ui));
let num: i32 = Math.floor(ui._w / (slotw + 3));
let dragPositionSet: bool = false;
2021-01-29 20:51:46 +01:00
2024-03-07 20:37:30 +01:00
let uix: f32 = 0.0;
let uiy: f32 = 0.0;
for (let row: i32 = 0; row < Math.floor(Math.ceil(Project.raw.swatches.length / num)); ++row) {
let ar: f32[] = [];
for (let i: i32 = 0; i < num; ++i) ar.push(1 / num);
2024-02-06 19:32:21 +01:00
zui_row(ar);
2021-01-29 20:51:46 +01:00
ui._x += 2;
if (row > 0) ui._y += 6;
2024-03-07 20:37:30 +01:00
for (let j: i32 = 0; j < num; ++j) {
let i: i32 = j + row * num;
2021-01-29 20:51:46 +01:00
if (i >= Project.raw.swatches.length) {
2024-02-06 19:32:21 +01:00
zui_end_element(slotw);
2021-01-29 20:51:46 +01:00
continue;
}
2023-02-27 21:13:25 +01:00
if (Context.raw.swatch == Project.raw.swatches[i]) {
2024-03-07 20:37:30 +01:00
let w: i32 = 32;
2024-02-06 19:32:21 +01:00
zui_fill(-2, -2, w, w, ui.t.HIGHLIGHT_COL);
2021-01-29 20:51:46 +01:00
}
2022-03-02 17:37:06 +01:00
uix = ui._x;
uiy = ui._y;
// Draw the drag position indicator
2024-03-07 20:37:30 +01:00
if (Base.drag_swatch != null && TabSwatches.drag_pos == i) {
2024-02-06 19:32:21 +01:00
zui_fill(-1, -2 , 2, 32, ui.t.HIGHLIGHT_COL);
2021-01-29 20:51:46 +01:00
}
2021-01-30 12:50:30 +01:00
2024-03-07 20:37:30 +01:00
let state: zui_state_t = zui_image(TabSwatches.empty, Project.raw.swatches[i].base, slotw);
2021-01-29 20:51:46 +01:00
2024-03-06 12:53:46 +01:00
if (state == zui_state_t.STARTED) {
2024-03-07 20:37:30 +01:00
Context.set_swatch(Project.raw.swatches[i]);
2021-01-30 12:50:30 +01:00
2024-03-07 20:37:30 +01:00
Base.drag_off_x = -(mouse_x - uix - ui._window_x - 2 * slotw);
Base.drag_off_y = -(mouse_y - uiy - ui._window_y + 1);
Base.drag_swatch = Context.raw.swatch;
2021-01-29 20:51:46 +01:00
}
2024-03-06 12:53:46 +01:00
else if (state == zui_state_t.HOVERED) {
2024-03-07 20:37:30 +01:00
TabSwatches.drag_pos = (mouse_x > uix + ui._window_x + slotw / 2) ? i + 1 : i; // Switch to the next position if the mouse crosses the swatch rectangle center
2022-03-02 17:37:06 +01:00
dragPositionSet = true;
}
2024-03-06 12:53:46 +01:00
else if (state == zui_state_t.RELEASED) {
2024-03-07 20:37:30 +01:00
if (time_time() - Context.raw.select_time < 0.25) {
2024-02-06 19:32:21 +01:00
UIMenu.draw((ui: zui_t) => {
2021-01-29 20:51:46 +01:00
ui.changed = false;
2024-03-07 20:37:30 +01:00
let h: zui_handle_t = zui_handle("tabswatches_0");
2023-02-27 21:13:25 +01:00
h.color = Context.raw.swatch.base;
2022-03-15 14:50:53 +01:00
2024-02-06 19:32:21 +01:00
Context.raw.swatch.base = zui_color_wheel(h, false, null, 11 * ui.t.ELEMENT_H * zui_SCALE(ui), true, () => {
2024-03-07 20:37:30 +01:00
Context.raw.color_picker_previous_tool = Context.raw.tool;
Context.select_tool(workspace_tool_t.PICKER);
Context.raw.color_picker_callback = (color: swatch_color_t) => {
Project.raw.swatches[i] = Project.clone_swatch(color);
2022-03-12 15:15:34 +01:00
};
});
2024-03-07 20:37:30 +01:00
let hopacity: zui_handle_t = zui_handle("tabswatches_1");
2023-02-27 21:13:25 +01:00
hopacity.value = Context.raw.swatch.opacity;
2024-02-06 19:32:21 +01:00
Context.raw.swatch.opacity = zui_slider(hopacity, "Opacity", 0, 1, true);
2024-03-07 20:37:30 +01:00
let hocclusion: zui_handle_t = zui_handle("tabswatches_2");
2023-02-27 21:13:25 +01:00
hocclusion.value = Context.raw.swatch.occlusion;
2024-02-06 19:32:21 +01:00
Context.raw.swatch.occlusion = zui_slider(hocclusion, "Occlusion", 0, 1, true);
2024-03-07 20:37:30 +01:00
let hroughness: zui_handle_t = zui_handle("tabswatches_3");
2023-02-27 21:13:25 +01:00
hroughness.value = Context.raw.swatch.roughness;
2024-02-06 19:32:21 +01:00
Context.raw.swatch.roughness = zui_slider(hroughness, "Roughness", 0, 1, true);
2024-03-07 20:37:30 +01:00
let hmetallic: zui_handle_t = zui_handle("tabswatches_4");
2023-02-27 21:13:25 +01:00
hmetallic.value = Context.raw.swatch.metallic;
2024-02-06 19:32:21 +01:00
Context.raw.swatch.metallic = zui_slider(hmetallic, "Metallic", 0, 1, true);
2024-03-07 20:37:30 +01:00
let hheight: zui_handle_t = zui_handle("tabswatches_5");
2023-02-27 21:13:25 +01:00
hheight.value = Context.raw.swatch.height;
2024-02-06 19:32:21 +01:00
Context.raw.swatch.height = zui_slider(hheight, "Height", 0, 1, true);
2022-03-15 14:50:53 +01:00
2024-03-07 20:37:30 +01:00
if (ui.changed || ui.is_typing) UIMenu.keep_open = true;
if (ui.input_released) Context.set_swatch(Context.raw.swatch); // Trigger material preview update
2024-02-06 19:32:21 +01:00
}, 16, Math.floor(mouse_x - 200 * zui_SCALE(ui)), Math.floor(mouse_y - 250 * zui_SCALE(ui)));
2021-01-29 20:51:46 +01:00
}
2024-03-07 20:37:30 +01:00
Context.raw.select_time = time_time();
2021-01-29 20:51:46 +01:00
}
2024-02-06 19:32:21 +01:00
if (ui.is_hovered && ui.input_released_r) {
2024-03-07 20:37:30 +01:00
Context.set_swatch(Project.raw.swatches[i]);
let add: i32 = Project.raw.swatches.length > 1 ? 1 : 0;
2024-01-17 18:53:31 +01:00
///if (krom_windows || krom_linux || krom_darwin)
2021-10-03 12:13:06 +02:00
add += 1; // Copy
2024-01-17 18:53:31 +01:00
///end
///if (is_paint || is_sculpt)
add += 3;
///end
///if is_lav
add += 1;
///end
2021-10-03 12:13:06 +02:00
2024-02-06 19:32:21 +01:00
UIMenu.draw((ui: zui_t) => {
2024-03-07 20:37:30 +01:00
if (UIMenu.menu_button(ui, tr("Duplicate"))) {
Context.set_swatch(Project.clone_swatch(Context.raw.swatch));
2023-02-27 21:13:25 +01:00
Project.raw.swatches.push(Context.raw.swatch);
2021-09-03 13:03:41 +02:00
}
2024-01-17 18:53:31 +01:00
///if (krom_windows || krom_linux || krom_darwin)
2024-03-07 20:37:30 +01:00
else if (UIMenu.menu_button(ui, tr("Copy Hex Code"))) {
let color: i32 = Context.raw.swatch.base;
2024-01-17 18:53:31 +01:00
color = color_set_ab(color, Context.raw.swatch.opacity * 255);
2024-03-07 20:37:30 +01:00
let val: i32 = color;
2024-01-17 18:53:31 +01:00
if (val < 0) val += 4294967296;
2024-02-10 19:26:53 +01:00
krom_copy_to_clipboard(val.toString(16));
2021-10-01 08:29:03 +02:00
}
2024-01-17 18:53:31 +01:00
///end
2024-03-07 20:37:30 +01:00
else if (Project.raw.swatches.length > 1 && UIMenu.menu_button(ui, tr("Delete"), "delete")) {
TabSwatches.delete_swatch(Project.raw.swatches[i]);
2021-01-29 20:51:46 +01:00
}
2024-01-17 18:53:31 +01:00
///if (is_paint || is_sculpt)
2024-03-07 20:37:30 +01:00
else if (UIMenu.menu_button(ui, tr("Create Material"))) {
TabMaterials.accept_swatch_drag(Project.raw.swatches[i]);
}
2024-03-07 20:37:30 +01:00
else if (UIMenu.menu_button(ui, tr("Create Color Layer"))) {
let color: i32 = Project.raw.swatches[i].base;
2024-01-17 18:53:31 +01:00
color = color_set_ab(color, Project.raw.swatches[i].opacity * 255);
2024-03-07 20:37:30 +01:00
Base.create_color_layer(color, Project.raw.swatches[i].occlusion, Project.raw.swatches[i].roughness, Project.raw.swatches[i].metallic);
}
2024-01-17 18:53:31 +01:00
///end
}, add);
2021-01-29 20:51:46 +01:00
}
2024-02-06 19:32:21 +01:00
if (ui.is_hovered) {
2024-03-07 20:37:30 +01:00
let color: i32 = Project.raw.swatches[i].base;
2024-01-17 18:53:31 +01:00
color = color_set_ab(color, Project.raw.swatches[i].opacity * 255);
2024-03-07 20:37:30 +01:00
let val: i32 = color;
2024-01-17 18:53:31 +01:00
if (val < 0) val += 4294967296;
2024-02-06 19:32:21 +01:00
zui_tooltip("#" + val.toString(16));
2021-01-31 10:40:05 +01:00
}
2021-01-29 20:51:46 +01:00
}
}
2021-12-06 14:04:28 +01:00
2022-06-22 15:21:34 +02:00
// Draw the rightmost line next to the last swatch
2024-03-07 20:37:30 +01:00
if (Base.drag_swatch != null && TabSwatches.drag_pos == Project.raw.swatches.length) {
2022-03-02 17:37:06 +01:00
ui._x = uix; // Reset the position because otherwise it would start in the row below
ui._y = uiy;
2024-02-06 19:32:21 +01:00
zui_fill(28, -2, 2, 32, ui.t.HIGHLIGHT_COL);
2022-03-02 17:37:06 +01:00
}
2022-06-22 15:21:34 +02:00
// Currently there is no valid dragPosition so reset it
2023-04-20 00:38:27 +02:00
if (!dragPositionSet) {
2024-03-07 20:37:30 +01:00
TabSwatches.drag_pos = -1;
2023-04-20 00:38:27 +02:00
}
2022-03-02 17:37:06 +01:00
2024-03-07 20:37:30 +01:00
let inFocus: bool = 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;
2024-02-06 19:32:21 +01:00
if (inFocus && ui.is_delete_down && Project.raw.swatches.length > 1) {
ui.is_delete_down = false;
2024-03-07 20:37:30 +01:00
TabSwatches.delete_swatch(Context.raw.swatch);
2021-12-06 14:04:28 +01:00
}
2021-01-29 20:51:46 +01:00
}
}
2021-12-06 14:04:28 +01:00
2024-03-07 20:37:30 +01:00
static accept_swatch_drag = (swatch: swatch_color_t) => {
2022-03-02 17:37:06 +01:00
// No valid position available
2024-03-07 20:37:30 +01:00
if (TabSwatches.drag_pos == -1) return;
2022-03-02 17:37:06 +01:00
2024-03-07 20:37:30 +01:00
let swatchPosition: i32 = Project.raw.swatches.indexOf(swatch);
2023-04-12 12:18:22 +02:00
// A new swatch from color picker
if (swatchPosition == -1) {
2024-03-07 20:37:30 +01:00
Project.raw.swatches.splice(TabSwatches.drag_pos, 0, swatch);
2022-03-02 17:37:06 +01:00
}
2024-03-07 20:37:30 +01:00
else if (Math.abs(swatchPosition - TabSwatches.drag_pos) > 0) { // Existing swatch is reordered
2024-01-17 18:53:31 +01:00
array_remove(Project.raw.swatches, swatch);
2023-04-12 12:18:22 +02:00
// If the new position is after the old one, decrease by one because the swatch has been deleted
2024-03-07 20:37:30 +01:00
let newPosition: i32 = TabSwatches.drag_pos - swatchPosition > 0 ? TabSwatches.drag_pos -1 : TabSwatches.drag_pos;
2024-01-17 18:53:31 +01:00
Project.raw.swatches.splice(newPosition, 0, swatch);
2022-03-02 17:37:06 +01:00
}
}
2024-03-07 20:37:30 +01:00
static delete_swatch = (swatch: swatch_color_t) => {
let i: i32 = Project.raw.swatches.indexOf(swatch);
Context.set_swatch(Project.raw.swatches[i == Project.raw.swatches.length - 1 ? i - 1 : i + 1]);
2021-12-06 14:04:28 +01:00
Project.raw.swatches.splice(i, 1);
2024-03-07 20:37:30 +01:00
UIBase.hwnds[tab_area_t.STATUS].redraws = 2;
2021-12-06 14:04:28 +01:00
}
2021-01-29 20:51:46 +01:00
}