mirror of
https://github.com/LucasDower/ObjToSchematic.git
synced 2024-11-27 02:19:58 +08:00
Swap material types, change solid material colour
This commit is contained in:
parent
8f0b2ed131
commit
9a38dd8207
@ -3,12 +3,12 @@ import path from 'path';
|
||||
|
||||
import { FallableBehaviour } from './block_mesh';
|
||||
import { ArcballCamera } from './camera';
|
||||
import { RGBAUtil } from './colour';
|
||||
import { RGBAColours, RGBAUtil, RGBA } from './colour';
|
||||
import { AppConfig } from './config';
|
||||
import { EAppEvent, EventManager } from './event';
|
||||
import { IExporter } from './exporters/base_exporter';
|
||||
import { ExporterFactory, TExporters } from './exporters/exporters';
|
||||
import { MaterialMap, MaterialType, TexturedMaterial } from './mesh';
|
||||
import { MaterialMap, MaterialType, TexturedMaterial, SolidMaterial } from './mesh';
|
||||
import { Renderer } from './renderer';
|
||||
import { StatusHandler, StatusMessage } from './status';
|
||||
import { TextureFiltering } from './texture';
|
||||
@ -20,7 +20,7 @@ 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';
|
||||
import { SetMaterialsParams, TFromWorkerMessage, TToWorkerMessage } from './worker_types';
|
||||
|
||||
export class AppContext {
|
||||
private _ui: UI;
|
||||
@ -202,17 +202,7 @@ export class AppContext {
|
||||
return { id: 'Import', payload: payload, callback: callback };
|
||||
}
|
||||
|
||||
private _onMaterialTextureReplace(materialName: string, newTexturePath: string) {
|
||||
const oldMaterial = this._materialMap[materialName];
|
||||
ASSERT(oldMaterial.type === MaterialType.textured);
|
||||
|
||||
this._materialMap[materialName] = {
|
||||
type: MaterialType.textured,
|
||||
alphaFactor: oldMaterial.alphaFactor,
|
||||
alphaPath: oldMaterial.alphaPath,
|
||||
path: newTexturePath,
|
||||
};
|
||||
|
||||
private _sendMaterialsToWorker(callback: (result: SetMaterialsParams.Output) => void) {
|
||||
const payload: TToWorkerMessage = {
|
||||
action: 'SetMaterials',
|
||||
params: {
|
||||
@ -227,8 +217,8 @@ export class AppContext {
|
||||
// TODO: Check the action didn't fail
|
||||
this._materialMap = result.result.materials;
|
||||
this._onMaterialMapChanged();
|
||||
Renderer.Get.updateMeshMaterialTexture(materialName, result.result.materials[materialName] as TexturedMaterial);
|
||||
this._ui.enableTo(EAction.Voxelise);
|
||||
callback(result.result);
|
||||
},
|
||||
};
|
||||
|
||||
@ -236,6 +226,50 @@ export class AppContext {
|
||||
this._ui.disableAll();
|
||||
}
|
||||
|
||||
private _onMaterialTypeSwitched(materialName: string) {
|
||||
const oldMaterial = this._materialMap[materialName];
|
||||
|
||||
if (oldMaterial.type == MaterialType.textured) {
|
||||
this._materialMap[materialName] = {
|
||||
type: MaterialType.solid,
|
||||
colour: RGBAUtil.copy(RGBAColours.WHITE),
|
||||
};
|
||||
}
|
||||
|
||||
this._sendMaterialsToWorker((result: SetMaterialsParams.Output) => {
|
||||
// TODO: Check the action didn't fail
|
||||
Renderer.Get.recreateMaterialBuffer(materialName, result.materials[materialName]);
|
||||
});
|
||||
}
|
||||
|
||||
private _onMaterialTextureReplace(materialName: string, newTexturePath: string) {
|
||||
const oldMaterial = this._materialMap[materialName];
|
||||
ASSERT(oldMaterial.type === MaterialType.textured);
|
||||
|
||||
this._materialMap[materialName] = {
|
||||
type: MaterialType.textured,
|
||||
alphaFactor: oldMaterial.alphaFactor,
|
||||
alphaPath: oldMaterial.alphaPath,
|
||||
path: newTexturePath,
|
||||
};
|
||||
|
||||
this._sendMaterialsToWorker((result: SetMaterialsParams.Output) => {
|
||||
Renderer.Get.updateMeshMaterialTexture(materialName, result.materials[materialName] as TexturedMaterial);
|
||||
});
|
||||
}
|
||||
|
||||
private _onMaterialColourChanged(materialName: string, newColour: RGBA) {
|
||||
ASSERT(this._materialMap[materialName].type === MaterialType.solid);
|
||||
this._materialMap[materialName] = {
|
||||
type: MaterialType.solid,
|
||||
colour: newColour,
|
||||
};
|
||||
|
||||
this._sendMaterialsToWorker((result: SetMaterialsParams.Output) => {
|
||||
Renderer.Get.recreateMaterialBuffer(materialName, result.materials[materialName] as SolidMaterial);
|
||||
});
|
||||
}
|
||||
|
||||
private _onMaterialMapChanged() {
|
||||
// Add material information to the output log
|
||||
const outputElement = this._ui.getActionOutput(EAction.Import);
|
||||
@ -250,21 +284,41 @@ export class AppContext {
|
||||
|
||||
const subTree = UITreeBuilder.create(materialName);
|
||||
if (material.type === MaterialType.solid) {
|
||||
subTree.addChild({ text: `Colour: ${RGBAUtil.toUint8String(material.colour)}`, warning: false });
|
||||
const colourId = getRandomID();
|
||||
subTree.addChild({ text: `Colour: <input type="color" id="${colourId}" value="${RGBAUtil.toHexString(material.colour)}">`, warning: false }, () => {
|
||||
const tmp = document.getElementById(colourId) as HTMLInputElement;
|
||||
if (tmp) {
|
||||
tmp.addEventListener('change', () => {
|
||||
const newColour = RGBAUtil.fromHexString(tmp.value);
|
||||
this._onMaterialColourChanged(materialName, newColour);
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const parsedPath = path.parse(material.path);
|
||||
const dirId = getRandomID();
|
||||
const replaceId = getRandomID();
|
||||
const switchId = getRandomID();
|
||||
|
||||
if (parsedPath.base !== 'debug.png') {
|
||||
subTree.addChild({ text: `Texture: <a id="${dirId}">${parsedPath.base}</a> <a id="${replaceId}">[Replace]</a>`, warning: false }, () => {
|
||||
const isMissingTexture = parsedPath.base === 'debug.png';
|
||||
if (!isMissingTexture) {
|
||||
subTree.addChild({ text: `Texture: <a id="${dirId}">${parsedPath.base}</a>`, warning: false }, () => {
|
||||
const tmp = document.getElementById(dirId) as HTMLLinkElement;
|
||||
tmp.onclick = () => {
|
||||
FileUtil.openDir(material.path);
|
||||
};
|
||||
if (tmp) {
|
||||
tmp.onclick = () => {
|
||||
FileUtil.openDir(material.path);
|
||||
};
|
||||
}
|
||||
});
|
||||
} else {
|
||||
subTree.addChild({ text: `Texture: Missing`, warning: true });
|
||||
}
|
||||
|
||||
const tmp2 = document.getElementById(replaceId) as HTMLLinkElement;
|
||||
tmp2.onclick = () => {
|
||||
// Add option to replace texture
|
||||
subTree.addChild({ text: `<a id="${replaceId}">[${isMissingTexture ? 'Find' : 'Replace' } Texture]</a>`, warning: false }, () => {
|
||||
const tmp = document.getElementById(replaceId) as HTMLLinkElement;
|
||||
if (tmp) {
|
||||
tmp.onclick = () => {
|
||||
const files = remote.dialog.showOpenDialogSync({
|
||||
title: 'Load',
|
||||
buttonLabel: 'Load',
|
||||
@ -277,25 +331,16 @@ export class AppContext {
|
||||
this._onMaterialTextureReplace(materialName, files[0]);
|
||||
}
|
||||
};
|
||||
});
|
||||
} else {
|
||||
subTree.addChild({ text: `Texture: MISSING <a id="${replaceId}">[Find]</a>`, warning: true }, () => {
|
||||
const tmp = document.getElementById(replaceId) as HTMLLinkElement;
|
||||
tmp.onclick = () => {
|
||||
const files = remote.dialog.showOpenDialogSync({
|
||||
title: 'Load ',
|
||||
buttonLabel: 'Load',
|
||||
filters: [{
|
||||
name: 'Images',
|
||||
extensions: ['png', 'jpeg', 'jpg'],
|
||||
}],
|
||||
});
|
||||
if (files && files[0]) {
|
||||
this._onMaterialTextureReplace(materialName, files[0]);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Add option to switch to colour material
|
||||
subTree.addChild({ text: `<a id="${switchId}">[Switch to Colour]</a>`, warning: false }, () => {
|
||||
const tmp = document.getElementById(switchId) as HTMLLinkElement;
|
||||
tmp.onclick = () => {
|
||||
this._onMaterialTypeSwitched(materialName);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
tree.addChild(subTree);
|
||||
|
@ -12,6 +12,19 @@ export namespace RGBAUtil {
|
||||
return `(${a.r}, ${a.g}, ${a.b}, ${a.a})`;
|
||||
}
|
||||
|
||||
export function toHexString(a: RGBA) {
|
||||
return `#${Math.floor(255 * a.r).toString(16)}${Math.floor(255 * a.g).toString(16)}${Math.floor(255 * a.b).toString(16)}`;
|
||||
}
|
||||
|
||||
export function fromHexString(str: string) {
|
||||
return {
|
||||
r: parseInt(str.substring(1, 3), 16) / 255,
|
||||
g: parseInt(str.substring(3, 5), 16) / 255,
|
||||
b: parseInt(str.substring(5, 7), 16) / 255,
|
||||
a: 1.0,
|
||||
};
|
||||
}
|
||||
|
||||
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)})`;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import { MaterialType, SolidMaterial, TexturedMaterial } from './mesh';
|
||||
import { RenderBuffer } from './render_buffer';
|
||||
import { ShaderManager } from './shaders';
|
||||
import { Texture } from './texture';
|
||||
import { ASSERT } from './util/error_util';
|
||||
import { Vector3 } from './vector';
|
||||
import { RenderBlockMeshParams, RenderMeshParams, RenderVoxelMeshParams } from './worker_types';
|
||||
|
||||
@ -45,7 +46,7 @@ export class Renderer {
|
||||
|
||||
private _modelsAvailable: number;
|
||||
|
||||
private _materialBuffers: Array<{
|
||||
private _materialBuffers: Map<string, {
|
||||
material: SolidMaterial | (TexturedMaterial & TextureMaterialRenderAddons)
|
||||
buffer: twgl.BufferInfo,
|
||||
numElements: number,
|
||||
@ -79,7 +80,7 @@ export class Renderer {
|
||||
twgl.addExtensionsToContext(this._gl);
|
||||
|
||||
this._modelsAvailable = 0;
|
||||
this._materialBuffers = [];
|
||||
this._materialBuffers = new Map();
|
||||
|
||||
this._gridBuffers = { x: {}, y: {}, z: {} };
|
||||
this._gridEnabled = true;
|
||||
@ -158,12 +159,45 @@ export class Renderer {
|
||||
}
|
||||
|
||||
public clearMesh() {
|
||||
this._materialBuffers = [];
|
||||
this._materialBuffers = new Map();
|
||||
|
||||
this._modelsAvailable = 0;
|
||||
this.setModelToUse(MeshType.None);
|
||||
}
|
||||
|
||||
public recreateMaterialBuffer(materialName: string, material: SolidMaterial | TexturedMaterial) {
|
||||
const oldBuffer = this._materialBuffers.get(materialName);
|
||||
ASSERT(oldBuffer !== undefined);
|
||||
if (material.type === MaterialType.solid) {
|
||||
this._materialBuffers.set(materialName, {
|
||||
buffer: oldBuffer.buffer,
|
||||
material: material,
|
||||
numElements: oldBuffer.numElements,
|
||||
materialName: materialName,
|
||||
});
|
||||
} else {
|
||||
this._materialBuffers.set(materialName, {
|
||||
buffer: oldBuffer.buffer,
|
||||
material: {
|
||||
type: MaterialType.textured,
|
||||
path: material.path,
|
||||
texture: twgl.createTexture(this._gl, {
|
||||
src: material.path,
|
||||
mag: this._gl.LINEAR,
|
||||
}),
|
||||
alphaFactor: material.alphaFactor,
|
||||
alpha: material.alphaPath ? twgl.createTexture(this._gl, {
|
||||
src: material.alphaPath,
|
||||
mag: this._gl.LINEAR,
|
||||
}) : undefined,
|
||||
useAlphaChannel: material.alphaPath ? new Texture(material.path, material.alphaPath)._useAlphaChannel() : undefined,
|
||||
},
|
||||
numElements: oldBuffer.numElements,
|
||||
materialName: materialName,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public updateMeshMaterialTexture(materialName: string, material: TexturedMaterial) {
|
||||
this._materialBuffers.forEach((buffer) => {
|
||||
if (buffer.materialName === materialName) {
|
||||
@ -186,19 +220,20 @@ export class Renderer {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public useMesh(params: RenderMeshParams.Output) {
|
||||
this._materialBuffers = [];
|
||||
this._materialBuffers = new Map();
|
||||
|
||||
for (const { material, buffer, numElements, materialName } of params.buffers) {
|
||||
if (material.type === MaterialType.solid) {
|
||||
this._materialBuffers.push({
|
||||
this._materialBuffers.set(materialName, {
|
||||
buffer: twgl.createBufferInfoFromArrays(this._gl, buffer),
|
||||
material: material,
|
||||
numElements: numElements,
|
||||
materialName: materialName,
|
||||
});
|
||||
} else {
|
||||
this._materialBuffers.push({
|
||||
this._materialBuffers.set(materialName, {
|
||||
buffer: twgl.createBufferInfoFromArrays(this._gl, buffer),
|
||||
material: {
|
||||
type: MaterialType.textured,
|
||||
@ -332,7 +367,7 @@ export class Renderer {
|
||||
}
|
||||
|
||||
private _drawMesh() {
|
||||
for (const materialBuffer of this._materialBuffers) {
|
||||
this._materialBuffers.forEach((materialBuffer, materialName) => {
|
||||
if (materialBuffer.material.type === MaterialType.textured) {
|
||||
this._drawMeshBuffer(materialBuffer.buffer, materialBuffer.numElements, ShaderManager.Get.textureTriProgram, {
|
||||
u_lightWorldPos: ArcballCamera.Get.getCameraPosition(0.0, 0.0),
|
||||
@ -352,7 +387,7 @@ export class Renderer {
|
||||
u_fillColour: RGBAUtil.toArray(materialBuffer.material.colour),
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _drawVoxelMesh() {
|
||||
|
@ -16,6 +16,9 @@ export namespace FileUtil {
|
||||
switch (process.platform) {
|
||||
case 'darwin':
|
||||
child.exec(`open -R ${absolutePath}`);
|
||||
break;
|
||||
case 'win32':
|
||||
child.exec(`explorer /select,"${absolutePath}"`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user