Skip to content

Commit

Permalink
perf: update multithreading for layer matrices
Browse files Browse the repository at this point in the history
  • Loading branch information
kylehue committed Mar 31, 2024
1 parent 84149fc commit 3ed0d7d
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 163 deletions.
29 changes: 10 additions & 19 deletions src/components/material-manager-item.vue
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ import { SelectMixedOption } from "naive-ui/es/select/src/interface";
import { useProjectStore } from "../store/project";
import { useMaterialSplitter } from "../composables/use-material-splitter";
import { Material } from "../utils/Material";
import { HistoryStateAction } from "../types";
import { Layer } from "../types";
const dialog = useDialog();
const projectStore = useProjectStore();
Expand Down Expand Up @@ -261,17 +261,17 @@ async function handleMaterialChangeMatrixId() {
if (oldMatrixId === newMatrixId) return;
// Check if any layer is using this material
const materialLayerMatrixRows: string[][] = [];
const layersThatUseThisMaterial: Layer[] = [];
for (const layer of projectStore.layers) {
const matrix = layer.matrix.getMatrix();
for (const row of matrix) {
if (!row.some((v) => v === oldMatrixId)) continue;
materialLayerMatrixRows.push(row);
layersThatUseThisMaterial.push(layer);
}
}
// If so, ask the user if they wanna change it in the matrix or not
const isIdBeingUsed = !!materialLayerMatrixRows.length;
const isIdBeingUsed = !!layersThatUseThisMaterial.length;
let isReplaced = false;
if (isIdBeingUsed) {
await new Promise((resolve) => {
Expand All @@ -282,11 +282,8 @@ async function handleMaterialChangeMatrixId() {
positiveText: "Replace",
positiveButtonProps: { quaternary: true },
onPositiveClick(e) {
for (const row of materialLayerMatrixRows) {
for (let i = 0; i < row.length; i++) {
if (row[i] !== oldMatrixId) continue;
row[i] = newMatrixId;
}
for (const layer of layersThatUseThisMaterial) {
layer.matrix.replaceMatrixId(oldMatrixId, newMatrixId);
}
isReplaced = true;
resolve(1);
Expand All @@ -311,23 +308,17 @@ async function handleMaterialChangeMatrixId() {
materialComputedModels.matrixId.value = oldMatrixId;
matrixId.value = oldMatrixId;
if (isReplaced) {
for (const row of materialLayerMatrixRows) {
for (let i = 0; i < row.length; i++) {
if (row[i] !== newMatrixId) continue;
row[i] = oldMatrixId;
}
for (const layer of layersThatUseThisMaterial) {
layer.matrix.replaceMatrixId(newMatrixId, oldMatrixId);
}
}
},
() => {
materialComputedModels.matrixId.value = newMatrixId;
matrixId.value = newMatrixId;
if (isReplaced) {
for (const row of materialLayerMatrixRows) {
for (let i = 0; i < row.length; i++) {
if (row[i] !== oldMatrixId) continue;
row[i] = newMatrixId;
}
for (const layer of layersThatUseThisMaterial) {
layer.matrix.replaceMatrixId(oldMatrixId, newMatrixId);
}
}
}
Expand Down
22 changes: 7 additions & 15 deletions src/designer/Designer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export class Designer {
this.lastRowSinceInitTooling = row;
}

public initTooling() {
public async initTooling() {
let [col, row] = this.getMouseColumnRow();
const tool = this.designerStore.activeTool;

Expand All @@ -179,25 +179,17 @@ export class Designer {
const material = this.projectStore.selectedMaterial;
if (tool == "brush") {
if (!material || !layer || layer?.isLocked) return;
layer.matrix.add(row, col, material.getMatrixId()).then(() => {
this.projectStore.makeLayersMatrixSizeUniform();
this.repaint();
});
await layer.matrix.add(row, col, material.getMatrixId());
} else if (tool == "eraser") {
if (!layer || layer?.isLocked) return;
layer.matrix
.add(row, col, this.projectStore.emptyMatrixId)
.then(() => {
this.projectStore.makeLayersMatrixSizeUniform();
this.repaint();
});
await layer.matrix.add(row, col, this.projectStore.emptyMatrixId);
} else if (tool == "paint-bucket") {
if (!material || !layer || layer?.isLocked) return;
layer.matrix.fill(row, col, material.getMatrixId()).then(() => {
this.projectStore.makeLayersMatrixSizeUniform();
this.repaint();
});
await layer.matrix.fill(row, col, material.getMatrixId());
}

this.projectStore.makeLayersMatrixSizeUniform();
this.repaint();
}

public setSize(width: number, height: number) {
Expand Down
2 changes: 1 addition & 1 deletion src/panes/matrix-area/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<script setup lang="ts">
import { useThemeVars } from "naive-ui";
import { computed, ref, watch } from "vue";
import { computed, onMounted, ref, watch } from "vue";
import Navbar from "./navbar.vue";
import { useProjectStore } from "../../store/project";
import { useDesignerStore } from "../../store/designer";
Expand Down
17 changes: 8 additions & 9 deletions src/store/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,14 @@ export const useProjectStore = defineStore("project", () => {

function makeLayersMatrixSizeUniform() {
// should only take care of visible layers
if (_layers.filter((v) => v.isVisible).length <= 1) return;

const largestNonEmptyLayer = _layers
.filter((v) => v.isVisible)
.sort((a, b) => {
return (
b.matrix.getNonEmptyTotalSize() - a.matrix.getNonEmptyTotalSize()
);
})[0];
const visibleLayers = _layers.filter((v) => v.isVisible);
if (visibleLayers.length <= 1) return;

const largestNonEmptyLayer = visibleLayers.sort((a, b) => {
return (
b.matrix.getNonEmptyTotalSize() - a.matrix.getNonEmptyTotalSize()
);
})[0];

const size = largestNonEmptyLayer.matrix.getNonEmptyTotalSize();
for (const layer of _layers) {
Expand Down
111 changes: 25 additions & 86 deletions src/utils/MapMatrix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,14 @@ export class MapMatrix {
this.matrix = [];
}

setEmptyMatrixId(emptyMatrixId: string) {
for (let i = this.matrix.length - 1; i >= 0; i--) {
this.matrix[i] = this.matrix[i].map((v) => {
if (v === this.emptyMatrixId) return emptyMatrixId;
return v;
});
}
async setEmptyMatrixId(emptyMatrixId: string) {
const result = await postAsync(worker, "setEmptyMatrixId", {
matrix: this.id,
from: this.emptyMatrixId,
to: emptyMatrixId,
});
if (!result) return;
this.matrix = result.data.matrix;
this.emptyMatrixId = emptyMatrixId;
}

Expand All @@ -60,6 +61,7 @@ export class MapMatrix {
}

private async _updateNonEmptyTotalSize() {
this.nonEmptyTotalSize = this.matrix.length;
const result = await postAsync(worker, "getNonEmptyTotalSize", {
matrix: this.id,
emptyMatrixId: this.emptyMatrixId,
Expand Down Expand Up @@ -107,92 +109,29 @@ export class MapMatrix {
this._updateNonEmptyTotalSize();
}

private async _expand(size: number) {
if (!size) return;
const result = await postAsync(worker, "expand", {
toString() {
return this.matrix.map((v) => v.join(this.separator)).join("\n");
}

async fromString(matrixString: string) {
const result = await postAsync(worker, "setMatrixFromString", {
matrix: this.id,
size,
matrixString,
separator: this.separator,
emptyMatrixId: this.emptyMatrixId,
});
if (!result) return;
this.matrix = result.data.matrix;
}

private _translate(rowStep: number, colStep: number) {
const rowStepAbs = Math.abs(rowStep);
const colStepAbs = Math.abs(colStep);

if (rowStepAbs === 0 && colStepAbs === 0) return;

const translated: string[][] = [];

for (let i = 0; i < this.matrix.length + rowStepAbs; i++) {
for (let j = 0; j < (this.matrix[0]?.length || 0) + colStepAbs; j++) {
translated[i] ??= [];
translated[i][j] = this.emptyMatrixId;
}
}

for (
let row = rowStep < 0 ? 0 : rowStepAbs;
row < translated.length - (rowStep >= 0 ? 0 : rowStepAbs);
row++
) {
for (
let col = colStep < 0 ? 0 : colStepAbs;
col < translated[row].length - (colStep >= 0 ? 0 : colStepAbs);
col++
) {
translated[row][col] =
this.matrix[row - (rowStep < 0 ? 0 : rowStepAbs)][
col - (colStep < 0 ? 0 : colStepAbs)
];
}
}

this.matrix = translated;
}

toString() {
return this.matrix.map((v) => v.join(this.separator)).join("\n");
}

fromString(matrixStr: string) {
this.matrix = matrixStr.split("\n").map((v) => v.split(this.separator));
this._clean();
}

private _clean() {
let maxRow = this.matrix.length;
let maxCol = -Infinity;
for (let i = this.matrix.length - 1; i >= 0; i--) {
const row = this.matrix[i].filter(
(str) => typeof str == "string" && str.length
);
maxCol = Math.max(maxCol, row.length);
}

maxRow = Math.max(maxRow, 2);
maxCol = Math.max(maxCol, 2);
let maxLength = Math.max(maxRow, maxCol);

// Keep it even so that its position in designer can be consistent
if (maxLength % 2 != 0) {
maxLength++;
}

// Adjust matrix dimensions to make rows and columns equal
for (let i = 0; i < maxLength; i++) {
const row = (this.matrix[i] || []).filter(
(str) => typeof str == "string" && str.length
);
while (row.length < maxLength) {
row.push(this.emptyMatrixId);
}
this.matrix[i] = row;
}

this.trim();
async replaceMatrixId(from: string, to: string) {
const result = await postAsync(worker, "replaceMatrixId", {
matrix: this.id,
from,
to,
});
if (!result) return;
this.matrix = result.data.matrix;
}
}

Expand Down
Loading

0 comments on commit 3ed0d7d

Please sign in to comment.