Add materials to import output

This commit is contained in:
Lucas Dower 2022-10-01 15:31:02 +01:00
parent d78316fff3
commit ecffefe920
8 changed files with 194 additions and 5 deletions

View File

@ -3,18 +3,21 @@ import path from 'path';
import { FallableBehaviour } from './block_mesh';
import { ArcballCamera } from './camera';
import { RGBAUtil } from './colour';
import { AppConfig } from './config';
import { EAppEvent, EventManager } from './event';
import { IExporter } from './exporters/base_exporter';
import { ExporterFactory, TExporters } from './exporters/exporters';
import { MaterialType } from './mesh';
import { Renderer } from './renderer';
import { StatusHandler, StatusMessage } from './status';
import { TextureFiltering } from './texture';
import { OutputStyle } from './ui/elements/output';
import { UI } from './ui/layout';
import { UIMessageBuilder } from './ui/misc';
import { ColourSpace, EAction } from './util';
import { UIMessageBuilder, UITreeBuilder } from './ui/misc';
import { ColourSpace, EAction, getRandomID } from './util';
import { ASSERT } from './util/error_util';
import { FileUtil } from './util/file_util';
import { LOG, LOG_ERROR, Logger } from './util/log_util';
import { TWorkerJob, WorkerController } from './worker_controller';
import { TFromWorkerMessage, TToWorkerMessage } from './worker_types';
@ -142,7 +145,7 @@ export class AppContext {
const builder = new UIMessageBuilder();
builder.addBold('action', [StatusHandler.Get.getDefaultSuccessMessage(action) + (hasInfos ? ':' : '')], 'success');
builder.addItem('action', infoStatuses, 'success');
builder.addItem('action', infoStatuses, 'none');
builder.addItem('action', warningStatuses, 'warning');
return { builder: builder, style: hasWarnings ? 'warning' : 'success' };
@ -181,6 +184,36 @@ export class AppContext {
ASSERT(payload.action === 'Import');
const outputElement = this._ui.getActionOutput(EAction.Import);
// Add material information to the output log
{
const messageBuilder = outputElement.getMessage();
const tree = UITreeBuilder.create('Materials');
for (const [materialName, material] of Object.entries(payload.result.materials)) {
if (materialName === 'DEFAULT_UNASSIGNED') {
continue;
}
const subTree = UITreeBuilder.create(materialName);
if (material.type === MaterialType.solid) {
subTree.addChild(`Colour: ${RGBAUtil.toUint8String(material.colour)}`);
} else {
const parsedPath = path.parse(material.path);
const id = getRandomID();
subTree.addChild(`Texture: <a id="${id}">${parsedPath.base}</a>`, () => {
const tmp = document.getElementById(id) as HTMLLinkElement;
tmp.onclick = () => {
FileUtil.openDir(material.path);
};
});
}
tree.addChild(subTree);
}
messageBuilder.addTree('materials', tree);
}
if (payload.result.triangleCount < AppConfig.RENDER_TRIANGLE_THRESHOLD) {
outputElement.setTaskInProgress('render', '[Renderer]: Processing...');
this._workerController.addJob(this._renderMesh());

View File

@ -8,6 +8,14 @@ export type RGBA = {
}
export namespace RGBAUtil {
export function toString(a: RGBA) {
return `(${a.r}, ${a.g}, ${a.b}, ${a.a})`;
}
export function toUint8String(a: RGBA) {
return `(${Math.floor(255 * a.r)}, ${Math.floor(255 * a.g)}, ${Math.floor(255 * a.b)}, ${Math.floor(255 * a.a)})`;
}
export function lerp(a: RGBA, b: RGBA, alpha: number) {
return {
r: a.r * (1 - alpha) + b.r * alpha,

View File

@ -18,6 +18,20 @@ export class OutputElement {
`;
}
public registerEvents() {
const toggler = document.getElementsByClassName('caret');
for (let i = 0; i < toggler.length; i++) {
const temp = toggler[i];
temp.addEventListener('click', function () {
temp.parentElement?.querySelector('.nested')?.classList.toggle('active');
temp.classList.toggle('caret-down');
});
}
this._message.postBuild();
}
private _message: UIMessageBuilder;
public setMessage(message: UIMessageBuilder, style?: OutputStyle) {
@ -60,6 +74,7 @@ export class OutputElement {
ASSERT(element !== null);
element.innerHTML = this._message.toString();
this.registerEvents();
}
public setStyle(style: OutputStyle) {

View File

@ -5,11 +5,67 @@ type TMessage = {
body: string,
}
interface IUIOutputElement {
buildHTML(): string;
}
export class UITreeBuilder implements IUIOutputElement {
private _rootLabel: string;
private _children: Array<string | UITreeBuilder>;
private _postBuildDelegates: Array<() => void>;
private constructor(rootLabel: string) {
this._rootLabel = rootLabel;
this._children = [];
this._postBuildDelegates = [];
}
public static create(rootLabel: string): UITreeBuilder {
return new UITreeBuilder(rootLabel);
}
public addChild(child: string | UITreeBuilder, postBuildDelegate?: () => void) {
this._children.push(child);
if (postBuildDelegate !== undefined) {
this._postBuildDelegates.push(postBuildDelegate);
}
if (child instanceof UITreeBuilder) {
this._postBuildDelegates.push(() => { child.postBuild(); });
}
}
public postBuild() {
this._postBuildDelegates.forEach((delegate) => {
delegate();
});
}
public buildHTML(): string {
let childrenHTML: string = '';
this._children.forEach((child) => {
childrenHTML += '<li>';
if (child instanceof UITreeBuilder) {
childrenHTML += child.buildHTML();
} else {
childrenHTML += child;
}
childrenHTML += '<li>';
});
return `
<span class="caret">${this._rootLabel}</span>
<ul class="nested">${childrenHTML}</ul>
`;
}
}
export class UIMessageBuilder {
private _messages: TMessage[];
private _postBuildDelegates: Array<() => void>;
public constructor() {
this._messages = [];
this._postBuildDelegates = [];
}
public static create() {
@ -35,7 +91,21 @@ export class UIMessageBuilder {
return this;
}
public addItem(groupId: string, messages: string[], style: OutputStyle) {
public addTree(groupId: string, tree: UITreeBuilder) {
this._messages.push({
groupId: groupId,
body: `<div style="padding-left: 16px;">${tree.buildHTML()}</div>`,
});
this._postBuildDelegates.push(() => { tree.postBuild(); });
}
public postBuild() {
this._postBuildDelegates.forEach((delegate) => {
delegate();
});
}
public addItem(groupId: string, messages: string[], style: OutputStyle, indent: number = 1) {
for (const message of messages) {
const cssColourClass = this._getStatusCSSClass(style);
this._messages.push({

View File

@ -1,3 +1,4 @@
import child from 'child_process';
import fs from 'fs';
export namespace FileUtil {
@ -10,4 +11,11 @@ export namespace FileUtil {
fs.mkdirSync(path);
}
}
export function openDir(absolutePath: string) {
switch (process.platform) {
case 'darwin':
child.exec(`open -R ${absolutePath}`);
}
}
}

View File

@ -77,6 +77,7 @@ export class WorkerClient {
return {
triangleCount: this._loadedMesh.getTriangleCount(),
materials: this._loadedMesh.getMaterials(),
};
}

View File

@ -2,6 +2,7 @@ import { TBlockAssigners } from './assigners/assigners';
import { FallableBehaviour } from './block_mesh';
import { TBlockMeshBufferDescription, TMeshBufferDescription, TVoxelMeshBufferDescription } from './buffer';
import { TExporters } from './exporters/exporters';
import { MaterialMap } from './mesh';
import { StatusMessage } from './status';
import { TextureFiltering } from './texture';
import { ColourSpace } from './util';
@ -25,6 +26,7 @@ export namespace ImportParams {
export type Output = {
triangleCount: number,
materials: MaterialMap
}
}

View File

@ -135,7 +135,7 @@ code {
select {
width: 100%;
height: 30px;
padding-left: 10px;
padding-left: 8px;
border-radius: 5px;
border: none;
font-family: 'Lexend', sans-serif;
@ -605,4 +605,56 @@ svg {
background-color: var(--prop-accent-standard);
height: 100%;
transition: width 0.1s;
}
/* Remove default bullets */
ul {
list-style-type: none;
margin: 0;
padding-left: 20px;
}
/* Style the caret/arrow */
.caret {
cursor: pointer;
user-select: none; /* Prevent text selection */
}
.caret:hover {
color: var(--text-standard) !important;
}
/* Create the caret/arrow with a unicode, and style it */
.caret::before {
content: "\25B6";
display: inline-block;
margin-right: 6px;
}
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.caret-down::before {
transform: rotate(90deg);
}
/* Hide the nested list */
.nested {
display: none;
}
/* Show the nested list when the user clicks on the caret/arrow (with JavaScript) */
.active {
display: block;
}
a {
border-bottom: 1px solid currentColor;
cursor: pointer;
color: #8C8C8C80;
}
a:hover {
color: var(--text-standard) !important;
}