Initial commits for webpack

This commit is contained in:
Lucas Dower 2023-02-11 00:53:27 +00:00
parent 127d836f17
commit aca30d1f11
No known key found for this signature in database
GPG Key ID: B3EE6B8499593605
61 changed files with 7698 additions and 1195 deletions

6532
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,9 @@
"headless": "tsc && node ./dist/tools/run-headless.js",
"package:win": "electron-packager . ObjToSchematic --overwrite --platform=win32 --arch=x64 --icon=res/static/icon.ico --prune=true --out=release",
"package:linux": "electron-packager . ObjToSchematic --overwrite --platform=linux --arch=x64 --icon=res/static/icon.png --prune=true --out=release",
"package:macos": "electron-packager . ObjToSchematic --overwrite --platform=darwin --arch=x64 --icon=res/static/icon.icns --prune=true --out=release"
"package:macos": "electron-packager . ObjToSchematic --overwrite --platform=darwin --arch=x64 --icon=res/static/icon.icns --prune=true --out=release",
"webdev": "webpack serve --config ./webpack.dev.js",
"webbuild": "webpack --config ./webpack.prod.js"
},
"repository": {
"type": "git",
@ -42,20 +44,32 @@
"@typescript-eslint/eslint-plugin": "^5.9.1",
"@typescript-eslint/parser": "^5.9.1",
"adm-zip": "^0.5.9",
"browserify-zlib": "^0.2.0",
"chalk": "^4.1.2",
"copy-dir": "^1.3.0",
"css-loader": "^6.7.3",
"electron": "^13.6.6",
"electron-packager": "^15.2.0",
"eslint": "^8.7.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-simple-import-sort": "^8.0.0",
"file-loader": "^6.2.0",
"images": "^3.2.3",
"jest": "^27.5.1",
"node-polyfill-webpack-plugin": "^2.0.1",
"prompt": "^1.2.1",
"raw-loader": "^4.0.2",
"sharp": "^0.31.1",
"style-loader": "^3.3.1",
"ts-jest": "^27.1.3",
"ts-loader": "^9.4.2",
"ts-node": "^10.1.0",
"typescript": "^4.3.5"
"typescript": "^4.3.5",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.11.1",
"webpack-merge": "^5.8.0",
"webpack-strip-block": "^0.3.0"
},
"dependencies": {
"bvh-tree": "^1.0.1",

View File

@ -1,28 +0,0 @@
{
"AMBIENT_OCCLUSION_OVERRIDE_CORNER": true,
"LOG_TO_FILE": true,
"USE_WORKER_THREAD": true,
"MULTISAMPLE_COUNT": 16,
"OLD_SPACE_SIZE_MB": 8192,
"ALPHA_BIAS": 1.0,
"ANGLE_SNAP_RADIUS_DEGREES": 10.0,
"RENDER_TRIANGLE_THRESHOLD": 1000000,
"MAXIMUM_IMAGE_MEM_ALLOC": 2048,
"CAMERA_FOV_DEGREES": 30.0,
"CAMERA_DEFAULT_DISTANCE_UNITS": 18.0,
"CAMERA_DEFAULT_AZIMUTH_RADIANS": -1.0,
"CAMERA_DEFAULT_ELEVATION_RADIANS": 1.3,
"CAMERA_SENSITIVITY_ROTATION": 0.005,
"CAMERA_SENSITIVITY_ZOOM": 0.005,
"CONSTRAINT_MAXIMUM_HEIGHT": 380,
"DITHER_MAGNITUDE": 32,
"SMOOTHNESS_MAX": 3.0,
"CAMERA_SMOOTHING": 0.1,
"VIEWPORT_BACKGROUND_COLOUR": {
"R": 0.125,
"G": 0.125,
"B": 0.125
},
"FRESNEL_EXPONENT": 3.0,
"FRESNEL_MIX": 0.3
}

View File

@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-axis-x" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="axes-svg">
<path d="M17 20l3 -3l-3 -3" />
<path d="M4 17h16" />
<path d="M4 7l3 -3l3 3" />
<path d="M7 20v-16" />
</svg>

Before

Width:  |  Height:  |  Size: 354 B

View File

@ -1,7 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-box" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="block-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<polyline points="12 3 20 7.5 20 16.5 12 21 4 16.5 4 7.5 12 3" />
<line x1="12" y1="12" x2="20" y2="7.5" />
<line x1="12" y1="12" x2="12" y2="21" />
<line x1="12" y1="12" x2="4" y2="7.5" />
</svg>

Before

Width:  |  Height:  |  Size: 493 B

View File

@ -1,9 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-box-model" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="bounds-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M8 8h8v8h-8z" />
<rect x="4" y="4" width="16" height="16" rx="2" />
<path d="M16 16l3.3 3.3" />
<path d="M16 8l3.3 -3.3" />
<path d="M8 8l-3.3 -3.3" />
<path d="M8 16l-3.3 3.3" />
</svg>

Before

Width:  |  Height:  |  Size: 503 B

View File

@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-sun" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="bulb-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<circle cx="12" cy="12" r="4" />
<path d="M3 12h1m8 -9v1m8 8h1m-9 8v1m-6.4 -15.4l.7 .7m12.1 -.7l-.7 .7m0 11.4l.7 .7m-12.1 -.7l-.7 .7" />
</svg>

Before

Width:  |  Height:  |  Size: 435 B

View File

@ -1,9 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-focus-2" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="centre-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<circle cx="12" cy="12" r=".5" fill="currentColor" />
<circle cx="12" cy="12" r="7" />
<line x1="12" y1="3" x2="12" y2="5" />
<line x1="3" y1="12" x2="5" y2="12" />
<line x1="12" y1="19" x2="12" y2="21" />
<line x1="19" y1="12" x2="21" y2="12" />
</svg>

Before

Width:  |  Height:  |  Size: 559 B

View File

@ -1,12 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-bug" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="debug-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M9 9v-1a3 3 0 0 1 6 0v1" />
<path d="M8 9h8a6 6 0 0 1 1 3v3a5 5 0 0 1 -10 0v-3a6 6 0 0 1 1 -3" />
<line x1="3" y1="13" x2="7" y2="13" />
<line x1="17" y1="13" x2="21" y2="13" />
<line x1="12" y1="20" x2="12" y2="14" />
<line x1="4" y1="19" x2="7.35" y2="17" />
<line x1="20" y1="19" x2="16.65" y2="17" />
<line x1="4" y1="7" x2="7.75" y2="9.4" />
<line x1="20" y1="7" x2="16.25" y2="9.4" />
</svg>

Before

Width:  |  Height:  |  Size: 713 B

View File

@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-folder" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#2c3e50" fill="none" stroke-linecap="round" stroke-linejoin="round" id="folder-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M5 4h4l3 3h7a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-11a2 2 0 0 1 2 -2" />
</svg>

Before

Width:  |  Height:  |  Size: 397 B

View File

@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-border-all" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="grid-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<rect x="4" y="4" width="16" height="16" rx="2" />
<line x1="4" y1="12" x2="20" y2="12" />
<line x1="12" y1="4" x2="12" y2="20" />
</svg>

Before

Width:  |  Height:  |  Size: 438 B

View File

@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-magnet" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="magnet-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M4 13v-8a2 2 0 0 1 2 -2h1a2 2 0 0 1 2 2v8a2 2 0 0 0 6 0v-8a2 2 0 0 1 2 -2h1a2 2 0 0 1 2 2v8a8 8 0 0 1 -16 0" />
<line x1="4" y1="8" x2="9" y2="8" />
<line x1="15" y1="8" x2="19" y2="8" />
</svg>

Before

Width:  |  Height:  |  Size: 502 B

View File

@ -1,11 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-grain" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="mesh-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<circle cx="4.5" cy="9.5" r="1" />
<circle cx="9.5" cy="4.5" r="1" />
<circle cx="9.5" cy="14.5" r="1" />
<circle cx="4.5" cy="19.5" r="1" />
<circle cx="14.5" cy="9.5" r="1" />
<circle cx="19.5" cy="4.5" r="1" />
<circle cx="14.5" cy="19.5" r="1" />
<circle cx="19.5" cy="14.5" r="1" />
</svg>

Before

Width:  |  Height:  |  Size: 600 B

View File

@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-minus" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="minus-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<line x1="5" y1="12" x2="19" y2="12" />
</svg>

Before

Width:  |  Height:  |  Size: 339 B

View File

@ -1,7 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-arrows-up" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="normal-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<line x1="17" y1="3" x2="17" y2="21" />
<path d="M4 6l3 -3l3 3" />
<path d="M20 6l-3 -3l-3 3" />
<line x1="7" y1="3" x2="7" y2="21" />
</svg>

Before

Width:  |  Height:  |  Size: 445 B

View File

@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-rectangle" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="orthographic-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<rect x="3" y="5" width="18" height="14" rx="2" />
</svg>

Before

Width:  |  Height:  |  Size: 361 B

View File

@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-perspective" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="perspective-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M6.141 4.163l12 1.714a1 1 0 0 1 .859 .99v10.266a1 1 0 0 1 -.859 .99l-12 1.714a1 1 0 0 1 -1.141 -.99v-13.694a1 1 0 0 1 1.141 -.99z" />
</svg>

Before

Width:  |  Height:  |  Size: 454 B

View File

@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-plus" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="plus-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<line x1="12" y1="5" x2="12" y2="19" />
<line x1="5" y1="12" x2="19" y2="12" />
</svg>

Before

Width:  |  Height:  |  Size: 379 B

View File

@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-rotate-360" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="rotate-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M12 16h4v4" />
<path d="M19.458 11.042c.86 -2.366 .722 -4.58 -.6 -5.9c-2.272 -2.274 -7.185 -1.045 -10.973 2.743c-3.788 3.788 -5.017 8.701 -2.744 10.974c2.227 2.226 6.987 1.093 10.74 -2.515" />
</svg>

Before

Width:  |  Height:  |  Size: 509 B

View File

@ -1,7 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-switch-3" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#2c3e50" fill="none" stroke-linecap="round" stroke-linejoin="round" id="switch-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M3 17h2.397a5 5 0 0 0 4.096 -2.133l.177 -.253m3.66 -5.227l.177 -.254a5 5 0 0 1 4.096 -2.133h3.397" />
<path d="M18 4l3 3l-3 3" />
<path d="M3 7h2.397a5 5 0 0 1 4.096 2.133l4.014 5.734a5 5 0 0 0 4.096 2.133h3.397" />
<path d="M18 20l3 -3l-3 -3" />
</svg>

Before

Width:  |  Height:  |  Size: 565 B

View File

@ -1,11 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-arrows-maximize" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="translate-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<polyline points="16 4 20 4 20 8" />
<line x1="14" y1="10" x2="20" y2="4" />
<polyline points="8 20 4 20 4 16" />
<line x1="4" y1="20" x2="10" y2="14" />
<polyline points="16 20 20 20 20 16" />
<line x1="14" y1="14" x2="20" y2="20" />
<polyline points="8 4 4 4 4 8" />
<line x1="4" y1="4" x2="10" y2="10" />
</svg>

Before

Width:  |  Height:  |  Size: 635 B

View File

@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-upload" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#2c3e50" fill="none" stroke-linecap="round" stroke-linejoin="round" id="upload-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2" />
<polyline points="7 9 12 4 17 9" />
<line x1="12" y1="4" x2="12" y2="16" />
</svg>

Before

Width:  |  Height:  |  Size: 437 B

View File

@ -1,15 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-3d-cube-sphere" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="voxel-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M6 17.6l-2 -1.1v-2.5" />
<path d="M4 10v-2.5l2 -1.1" />
<path d="M10 4.1l2 -1.1l2 1.1" />
<path d="M18 6.4l2 1.1v2.5" />
<path d="M20 14v2.5l-2 1.12" />
<path d="M14 19.9l-2 1.1l-2 -1.1" />
<line x1="12" y1="12" x2="14" y2="10.9" />
<line x1="18" y1="8.6" x2="20" y2="7.5" />
<line x1="12" y1="12" x2="12" y2="14.5" />
<line x1="12" y1="18.5" x2="12" y2="21" />
<path d="M12 12l-2 -1.12" />
<line x1="6" y1="8.6" x2="4" y2="7.5" />
</svg>

Before

Width:  |  Height:  |  Size: 771 B

View File

@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-squares-diagonal" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="wireframe-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<rect x="8" y="8" width="12" height="12" rx="2" />
<path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2" />
<path d="M8.586 19.414l10.827 -10.827" />
</svg>

Before

Width:  |  Height:  |  Size: 485 B

View File

@ -1,4 +1,5 @@
import { remote } from 'electron';
import '../styles.css';
import path from 'path';
import { FallableBehaviour } from './block_mesh';
@ -18,7 +19,6 @@ import { UI } from './ui/layout';
import { UIMessageBuilder } from './ui/misc';
import { ColourSpace, EAction } from './util';
import { ASSERT } from './util/error_util';
import { FileUtil } from './util/file_util';
import { LOG_ERROR, Logger } from './util/log_util';
import { AppPaths } from './util/path_util';
import { Vector3 } from './vector';
@ -35,15 +35,14 @@ export class AppContext {
public constructor() {
this._materialManager = new MaterialMapManager(new Map());
Logger.Get.enableLogToFile();
Logger.Get.initLogFile('client');
Logger.Get.enableLOG();
Logger.Get.enableLOGMAJOR();
Logger.Get.enableLOGWARN();
AppConfig.Get.dumpConfig();
FileUtil.rmdirIfExist(AppPaths.Get.gen);
// TODO Unimplemented
//FileUtil.rmdirIfExist(AppPaths.Get.gen);
const gl = (<HTMLCanvasElement>document.getElementById('canvas')).getContext('webgl');
if (!gl) {
@ -505,6 +504,9 @@ export class AppContext {
const exporterID: TExporters = this._ui.layout.export.elements.export.getValue();
const exporter: IExporter = ExporterFactory.GetExporter(exporterID);
// TODO Unimplemented
/*
const filepath = remote.dialog.showSaveDialogSync({
title: 'Save structure',
buttonLabel: 'Save',
@ -516,7 +518,10 @@ export class AppContext {
}
this._ui.getActionOutput(EAction.Export)
.setTaskInProgress('action', '[Exporter]: Saving...');
.setTaskInProgress('action', '[Exporter]: Saving...');
*/
const filepath = '';
const payload: TToWorkerMessage = {
action: 'Export',

View File

@ -1,7 +1,5 @@
import fs from 'fs';
import path from 'path';
import { TAtlasVersion } from '../tools/build-atlas';
import { RGBA } from './colour';
import { AppTypes, AppUtil, TOptional, UV } from './util';
import { AppError, ASSERT } from './util/error_util';
@ -51,6 +49,9 @@ export class Atlas {
}
public static load(atlasName: string): TOptional<Atlas> {
// TODO Unimplemented
return undefined;
/*
if (!Atlas._isValidAtlasName(atlasName)) {
return;
}
@ -131,6 +132,7 @@ export class Atlas {
}
return atlas;
*/
}
public getAtlasSize(): number {

View File

@ -1,5 +1,3 @@
import fs from 'fs';
import { RGBA } from './colour';
import { LOG } from './util/log_util';
import { AppPaths, PathUtil } from './util/path_util';
@ -11,69 +9,38 @@ export class AppConfig {
return this._instance || (this._instance = new this());
}
public readonly RELEASE_MODE: boolean;
public readonly RELEASE_VERSION: string;
public readonly VOXEL_BUFFER_CHUNK_SIZE: number;
public readonly RELEASE_MODE = false;
public readonly RELEASE_VERSION = '0.7.2d';
public readonly VOXEL_BUFFER_CHUNK_SIZE = 5_000;
// Loaded from .json
public readonly AMBIENT_OCCLUSION_OVERRIDE_CORNER: boolean;
public readonly LOG_TO_FILE: boolean;
public readonly USE_WORKER_THREAD: boolean;
public readonly MULTISAMPLE_COUNT: number;
public readonly OLD_SPACE_SIZE_MB: number;
public readonly ALPHA_BIAS: number;
public readonly ANGLE_SNAP_RADIUS_DEGREES: number;
public readonly RENDER_TRIANGLE_THRESHOLD: number;
public readonly MAXIMUM_IMAGE_MEM_ALLOC: number;
public readonly CAMERA_FOV_DEGREES: number;
public readonly CAMERA_DEFAULT_DISTANCE_UNITS: number;
public readonly CAMERA_DEFAULT_AZIMUTH_RADIANS: number;
public readonly CAMERA_DEFAULT_ELEVATION_RADIANS: number;
public readonly CAMERA_SENSITIVITY_ROTATION: number;
public readonly CAMERA_SENSITIVITY_ZOOM: number;
public readonly CONSTRAINT_MAXIMUM_HEIGHT: number;
public readonly DITHER_MAGNITUDE: number;
public readonly SMOOTHNESS_MAX: number;
public readonly CAMERA_SMOOTHING: number;
public readonly VIEWPORT_BACKGROUND_COLOUR: RGBA;
public readonly FRESNEL_EXPONENT: number;
public readonly FRESNEL_MIX: number;
public readonly AMBIENT_OCCLUSION_OVERRIDE_CORNER = true;
public readonly USE_WORKER_THREAD = false;
public readonly MULTISAMPLE_COUNT = 16;
public readonly ALPHA_BIAS = 1.0;
public readonly ANGLE_SNAP_RADIUS_DEGREES = 10.0;
public readonly RENDER_TRIANGLE_THRESHOLD = 1_000_000;
public readonly MAXIMUM_IMAGE_MEM_ALLOC = 2048;
public readonly CAMERA_FOV_DEGREES = 30.0;
public readonly CAMERA_DEFAULT_DISTANCE_UNITS = 18.0;
public readonly CAMERA_DEFAULT_AZIMUTH_RADIANS = -1.0;
public readonly CAMERA_DEFAULT_ELEVATION_RADIANS = 1.3;
public readonly CAMERA_SENSITIVITY_ROTATION = 0.005;
public readonly CAMERA_SENSITIVITY_ZOOM = 0.005;
public readonly CONSTRAINT_MAXIMUM_HEIGHT = 380;
public readonly DITHER_MAGNITUDE = 32;
public readonly SMOOTHNESS_MAX = 3.0;
public readonly CAMERA_SMOOTHING = 0.1;
public readonly VIEWPORT_BACKGROUND_COLOUR: RGBA = {
r: 0.125,
g: 0.125,
b: 0.125,
a: 1.0,
};
public readonly FRESNEL_EXPONENT = 3.0;
public readonly FRESNEL_MIX = 0.3;
private constructor() {
this.RELEASE_MODE = true;
this.RELEASE_VERSION = '0.7.2d';
this.VOXEL_BUFFER_CHUNK_SIZE = 5_000;
const configFile = fs.readFileSync(PathUtil.join(AppPaths.Get.resources, 'config.json'), 'utf8');
const configJSON = JSON.parse(configFile);
this.AMBIENT_OCCLUSION_OVERRIDE_CORNER = configJSON.AMBIENT_OCCLUSION_OVERRIDE_CORNER;
this.LOG_TO_FILE = configJSON.LOG_TO_FILE;
this.USE_WORKER_THREAD = configJSON.USE_WORKER_THREAD && !process.argv.includes('--OTS-ENABLE-DEBUG');
this.MULTISAMPLE_COUNT = configJSON.MULTISAMPLE_COUNT;
this.OLD_SPACE_SIZE_MB = configJSON.OLD_SPACE_SIZE_MB;
this.ALPHA_BIAS = configJSON.ALPHA_BIAS;
this.ANGLE_SNAP_RADIUS_DEGREES = configJSON.ANGLE_SNAP_RADIUS_DEGREES;
this.RENDER_TRIANGLE_THRESHOLD = configJSON.RENDER_TRIANGLE_THRESHOLD;
this.MAXIMUM_IMAGE_MEM_ALLOC = configJSON.MAXIMUM_IMAGE_MEM_ALLOC;
this.CAMERA_FOV_DEGREES = configJSON.CAMERA_FOV_DEGREES;
this.CAMERA_DEFAULT_DISTANCE_UNITS = configJSON.CAMERA_DEFAULT_DISTANCE_UNITS;
this.CAMERA_DEFAULT_AZIMUTH_RADIANS = configJSON.CAMERA_DEFAULT_AZIMUTH_RADIANS;
this.CAMERA_DEFAULT_ELEVATION_RADIANS = configJSON.CAMERA_DEFAULT_ELEVATION_RADIANS;
this.CAMERA_SENSITIVITY_ROTATION = configJSON.CAMERA_SENSITIVITY_ROTATION;
this.CAMERA_SENSITIVITY_ZOOM = configJSON.CAMERA_SENSITIVITY_ZOOM;
this.CONSTRAINT_MAXIMUM_HEIGHT = configJSON.CONSTRAINT_MAXIMUM_HEIGHT;
this.DITHER_MAGNITUDE = configJSON.DITHER_MAGNITUDE;
this.SMOOTHNESS_MAX = configJSON.SMOOTHNESS_MAX;
this.CAMERA_SMOOTHING = configJSON.CAMERA_SMOOTHING;
this.VIEWPORT_BACKGROUND_COLOUR = {
r: configJSON.VIEWPORT_BACKGROUND_COLOUR.R,
g: configJSON.VIEWPORT_BACKGROUND_COLOUR.G,
b: configJSON.VIEWPORT_BACKGROUND_COLOUR.B,
a: 1.0,
};
this.FRESNEL_EXPONENT = configJSON.FRESNEL_EXPONENT;
this.FRESNEL_MIX = configJSON.FRESNEL_MIX;
}
public dumpConfig() {

View File

@ -1,6 +1,4 @@
import fs from 'fs';
import { AppTypes } from './util';
import { AppPaths, PathUtil } from './util/path_util';
@ -40,22 +38,89 @@ export class AppRuntimeConstants {
return this._instance || (this._instance = new this());
}
public readonly FALLABLE_BLOCKS: AppTypes.TNamespacedBlockName[];
public readonly TRANSPARENT_BLOCKS: AppTypes.TNamespacedBlockName[];
public readonly GRASS_LIKE_BLOCKS: AppTypes.TNamespacedBlockName[];
public readonly EMISSIVE_BLOCKS: AppTypes.TNamespacedBlockName[];
public readonly FALLABLE_BLOCKS = [
'minecraft:anvil',
'minecraft:lime_concrete_powder',
'minecraft:orange_concrete_powder',
'minecraft:black_concrete_powder',
'minecraft:brown_concrete_powder',
'minecraft:cyan_concrete_powder',
'minecraft:light_gray_concrete_powder',
'minecraft:purple_concrete_powder',
'minecraft:magenta_concrete_powder',
'minecraft:light_blue_concrete_powder',
'minecraft:yellow_concrete_powder',
'minecraft:white_concrete_powder',
'minecraft:blue_concrete_powder',
'minecraft:red_concrete_powder',
'minecraft:gray_concrete_powder',
'minecraft:pink_concrete_powder',
'minecraft:green_concrete_powder',
'minecraft:dragon_egg',
'minecraft:gravel',
'minecraft:pointed_dripstone',
'minecraft:red_sand',
'minecraft:sand',
'minecraft:scaffolding',
];
public readonly TRANSPARENT_BLOCKS = [
'minecraft:frosted_ice',
'minecraft:glass',
'minecraft:white_stained_glass',
'minecraft:orange_stained_glass',
'minecraft:magenta_stained_glass',
'minecraft:light_blue_stained_glass',
'minecraft:yellow_stained_glass',
'minecraft:lime_stained_glass',
'minecraft:pink_stained_glass',
'minecraft:gray_stained_glass',
'minecraft:light_gray_stained_glass',
'minecraft:cyan_stained_glass',
'minecraft:purple_stained_glass',
'minecraft:blue_stained_glass',
'minecraft:brown_stained_glass',
'minecraft:green_stained_glass',
'minecraft:red_stained_glass',
'minecraft:black_stained_glass',
'minecraft:ice',
'minecraft:oak_leaves',
'minecraft:spruce_leaves',
'minecraft:birch_leaves',
'minecraft:jungle_leaves',
'minecraft:acacia_leaves',
'minecraft:dark_oak_leaves',
'minecraft:mangrove_leaves',
'minecraft:azalea_leaves',
'minecraft:flowering_azalea_leaves',
'minecraft:slime_block',
'minecraft:honey_block',
];
public readonly GRASS_LIKE_BLOCKS = [
'minecraft:grass_block',
'minecraft:grass_path',
'minecraft:podzol',
'minecraft:crimson_nylium',
'minecraft:warped_nylium',
'minecraft:mycelium',
'minecraft:farmland',
];
public readonly EMISSIVE_BLOCKS = [
'minecraft:respawn_anchor',
'minecraft:magma_block',
'minecraft:sculk_catalyst',
'minecraft:crying_obsidian',
'minecraft:shroomlight',
'minecraft:sea_lantern',
'minecraft:jack_o_lantern',
'minecraft:glowstone',
'minecraft:pearlescent_froglight',
'minecraft:verdant_froglight',
'minecraft:ochre_froglight',
];
private constructor() {
const fallableBlocksString = fs.readFileSync(PathUtil.join(AppPaths.Get.resources, 'fallable_blocks.json'), 'utf-8');
this.FALLABLE_BLOCKS = JSON.parse(fallableBlocksString).fallable_blocks;
const transparentBlocksString = fs.readFileSync(PathUtil.join(AppPaths.Get.resources, 'transparent_blocks.json'), 'utf-8');
this.TRANSPARENT_BLOCKS = JSON.parse(transparentBlocksString).transparent_blocks;
const emissiveBlocksString = fs.readFileSync(PathUtil.join(AppPaths.Get.resources, 'emissive_blocks.json'), 'utf-8');
this.EMISSIVE_BLOCKS = JSON.parse(emissiveBlocksString).emissive_blocks;
const grassLikeBlocksString = fs.readFileSync(PathUtil.join(AppPaths.Get.resources, 'grass_like_blocks.json'), 'utf-8');
this.GRASS_LIKE_BLOCKS = JSON.parse(grassLikeBlocksString).grass_like_blocks;
}
}

View File

@ -1,4 +1,4 @@
import { NBT, TagType } from 'prismarine-nbt';
//import { NBT, TagType } from 'prismarine-nbt';
import { BlockMesh } from '../block_mesh';
import { AppConstants } from '../constants';
@ -134,11 +134,14 @@ export class Litematic extends IExporter {
private _createBlockStatePalette(blockMapping: BlockMapping) {
const blockStatePalette = Array(Object.keys(blockMapping).length);
/*
for (const blockName of Object.keys(blockMapping)) {
const index = blockMapping[blockName];
blockStatePalette[index] = { Name: { type: TagType.String, value: blockName } };
}
blockStatePalette[0] = { Name: { type: TagType.String, value: 'minecraft:air' } };
*/
return blockStatePalette;
}
@ -151,6 +154,7 @@ export class Litematic extends IExporter {
const blockStatePalette = this._createBlockStatePalette(blockMapping);
const numBlocks = blockMesh.getBlocks().length;
/*
const nbt: NBT = {
type: TagType.Compound,
name: 'Litematic',
@ -208,6 +212,7 @@ export class Litematic extends IExporter {
};
return nbt;
*/
}
getFormatFilter() {
@ -230,7 +235,8 @@ export class Litematic extends IExporter {
this._sizeVector = Vector3.sub(bounds.max, bounds.min).add(1);
const nbt = this._convertToNBT(blockMesh);
saveNBT(nbt, filePath);
// TODO Unimplemented
//saveNBT(nbt, filePath);
return false;
}

View File

@ -1,4 +1,4 @@
import { NBT, TagType } from 'prismarine-nbt';
//import { NBT, TagType } from 'prismarine-nbt';
import { BlockMesh } from '../block_mesh';
import { AppConstants } from '../constants';
@ -25,84 +25,86 @@ export class NBTExporter extends IExporter {
}
public override export(blockMesh: BlockMesh, filePath: string): boolean {
const bounds = blockMesh.getVoxelMesh().getBounds();
const sizeVector = bounds.getDimensions().add(1);
const isTooBig = sizeVector.x > 48 && sizeVector.y > 48 && sizeVector.z > 48;
if (isTooBig) {
StatusHandler.Get.add('warning', 'Structure blocks only support structures of size 48x48x48, blocks outside this range will be removed');
}
const blockNameToIndex = new Map<string, number>();
const palette: any = [];
for (const blockName of blockMesh.getBlockPalette()) {
palette.push({
Name: {
type: TagType.String,
value: AppUtil.Text.namespaceBlock(blockName),
},
});
blockNameToIndex.set(blockName, palette.length - 1);
}
const blocks: any = [];
for (const block of blockMesh.getBlocks()) {
const pos = block.voxel.position;
const blockIndex = blockNameToIndex.get(block.blockInfo.name);
if (blockIndex) {
if (pos.x > -24 && pos.x <= 24 && pos.y > -24 && pos.y <= 24 && pos.z > -24 && pos.z <= 24) {
blocks.push({
pos: {
type: TagType.List,
value: {
type: TagType.Int,
value: Vector3.sub(block.voxel.position, bounds.min).toArray(),
},
},
state: {
type: TagType.Int,
value: blockIndex,
},
});
}
}
}
const nbt: NBT = {
type: TagType.Compound,
name: 'SchematicBlocks',
value: {
DataVersion: {
type: TagType.Int,
value: AppConstants.DATA_VERSION,
},
size: {
type: TagType.List,
value: {
type: TagType.Int,
value: sizeVector.toArray(),
},
},
palette: {
type: TagType.List,
value: {
type: TagType.Compound,
value: palette,
},
},
blocks: {
type: TagType.List,
value: {
type: TagType.Compound,
value: blocks,
},
},
},
};
saveNBT(nbt, filePath);
// TODO Unimplemented
return false;
// const bounds = blockMesh.getVoxelMesh().getBounds();
// const sizeVector = bounds.getDimensions().add(1);
// const isTooBig = sizeVector.x > 48 && sizeVector.y > 48 && sizeVector.z > 48;
// if (isTooBig) {
// StatusHandler.Get.add('warning', 'Structure blocks only support structures of size 48x48x48, blocks outside this range will be removed');
// }
// const blockNameToIndex = new Map<string, number>();
// const palette: any = [];
// for (const blockName of blockMesh.getBlockPalette()) {
// palette.push({
// Name: {
// type: TagType.String,
// value: AppUtil.Text.namespaceBlock(blockName),
// },
// });
// blockNameToIndex.set(blockName, palette.length - 1);
// }
// const blocks: any = [];
// for (const block of blockMesh.getBlocks()) {
// const pos = block.voxel.position;
// const blockIndex = blockNameToIndex.get(block.blockInfo.name);
// if (blockIndex) {
// if (pos.x > -24 && pos.x <= 24 && pos.y > -24 && pos.y <= 24 && pos.z > -24 && pos.z <= 24) {
// blocks.push({
// pos: {
// type: TagType.List,
// value: {
// type: TagType.Int,
// value: Vector3.sub(block.voxel.position, bounds.min).toArray(),
// },
// },
// state: {
// type: TagType.Int,
// value: blockIndex,
// },
// });
// }
// }
// }
// const nbt: NBT = {
// type: TagType.Compound,
// name: 'SchematicBlocks',
// value: {
// DataVersion: {
// type: TagType.Int,
// value: AppConstants.DATA_VERSION,
// },
// size: {
// type: TagType.List,
// value: {
// type: TagType.Int,
// value: sizeVector.toArray(),
// },
// },
// palette: {
// type: TagType.List,
// value: {
// type: TagType.Compound,
// value: palette,
// },
// },
// blocks: {
// type: TagType.List,
// value: {
// type: TagType.Compound,
// value: blocks,
// },
// },
// },
// };
// saveNBT(nbt, filePath);
// return false;
}
private static _getBufferIndex(dimensions: Vector3, vec: Vector3) {

View File

@ -1,4 +1,3 @@
import fs from 'fs';
import path from 'path';
import { BlockMesh } from '../block_mesh';
@ -7,7 +6,7 @@ import { ASSERT } from '../util/error_util';
import { IExporter } from './base_exporter';
export class ObjExporter extends IExporter {
public override getFormatFilter(): Electron.FileFilter {
public override getFormatFilter() {
return {
name: 'Wavefront Obj',
extensions: ['obj'],
@ -85,20 +84,22 @@ export class ObjExporter extends IExporter {
buffers.forEach(({ buffer }) => {
positionData.set(buffer.position.data, positionIndex);
positionIndex += buffer.position.data.length;
normalData.set(buffer.normal.data, normalIndex);
normalIndex += buffer.normal.data.length;
texcoordData.set(buffer.texcoord.data, texcoordIndex);
texcoordIndex += buffer.texcoord.data.length;
blockTexcoordData.set(buffer.blockTexcoord.data, blockTexcoordIndex);
blockTexcoordIndex += buffer.blockTexcoord.data.length;
indexData.set(buffer.indices.data, indicesIndex);
indicesIndex += buffer.indices.data.length;
});
// TODO Unimplemented
/*
const file = fs.openSync(filepath, 'w');
fs.writeSync(file, '# Created with ObjToSchematic\n');
fs.writeSync(file, '# https://github.com/LucasDower/ObjToSchematic/\n\n');
@ -136,9 +137,12 @@ export class ObjExporter extends IExporter {
}
fs.closeSync(file);
*/
}
private _exportMTL(filepathMTL: string, filepathTexture: string, blockMesh: BlockMesh) {
// TODO Unimplemented
/*
ASSERT(path.isAbsolute(filepathMTL));
ASSERT(path.isAbsolute(filepathTexture));
@ -157,5 +161,6 @@ export class ObjExporter extends IExporter {
// Export texture
const filepathAtlasTexture = blockMesh.getAtlas().getAtlasTexturePath();
fs.copyFileSync(filepathAtlasTexture, filepathTexture);
*/
}
}

View File

@ -1,4 +1,4 @@
import { NBT, TagType } from 'prismarine-nbt';
//import { NBT, TagType } from 'prismarine-nbt';
import { BlockMesh } from '../block_mesh';
import { AppConstants } from '../constants';
@ -28,66 +28,68 @@ export class SchemExporter extends IExporter {
private static SCHEMA_VERSION = 2;
public override export(blockMesh: BlockMesh, filePath: string): boolean {
const bounds = blockMesh.getVoxelMesh().getBounds();
const sizeVector = bounds.getDimensions().add(1);
// https://github.com/SpongePowered/Schematic-Specification/blob/master/versions/schematic-3.md#paletteObject
// const blockMapping: BlockMapping = {};
const blockMapping: {[name: string]: { type: TagType, value: any }} = {
'minecraft:air': { type: TagType.Int, value: 0 },
};
let blockIndex = 1;
for (const blockName of blockMesh.getBlockPalette()) {
const namespacedBlockName = AppUtil.Text.namespaceBlock(blockName);
blockMapping[namespacedBlockName] = { type: TagType.Int, value: blockIndex };
++blockIndex;
}
LOG(blockMapping);
// const paletteObject = SchemExporter._createBlockStatePalette(blockMapping);
const blockData = new Array<number>(sizeVector.x * sizeVector.y * sizeVector.z).fill(0);
for (const block of blockMesh.getBlocks()) {
const indexVector = Vector3.sub(block.voxel.position, bounds.min);
const bufferIndex = SchemExporter._getBufferIndex(sizeVector, indexVector);
const namespacedBlockName = AppUtil.Text.namespaceBlock(block.blockInfo.name);
blockData[bufferIndex] = blockMapping[namespacedBlockName].value;
}
const blockEncoding: number[] = [];
for (let i = 0; i < blockData.length; ++i) {
let id = blockData[i];
while ((id & -128) != 0) {
blockEncoding.push(id & 127 | 128);
id >>>= 7;
}
blockEncoding.push(id);
}
for (let i = 0; i < blockEncoding.length; ++i) {
blockEncoding[i] = MathUtil.int8(blockEncoding[i]);
}
const nbt: NBT = {
type: TagType.Compound,
name: 'Schematic',
value: {
Version: { type: TagType.Int, value: SchemExporter.SCHEMA_VERSION },
DataVersion: { type: TagType.Int, value: AppConstants.DATA_VERSION },
Width: { type: TagType.Short, value: sizeVector.x },
Height: { type: TagType.Short, value: sizeVector.y },
Length: { type: TagType.Short, value: sizeVector.z },
PaletteMax: { type: TagType.Int, value: blockIndex },
Palette: { type: TagType.Compound, value: blockMapping },
BlockData: { type: TagType.ByteArray, value: blockEncoding },
},
};
saveNBT(nbt, filePath);
// TODO Unimplemented
return false;
// const bounds = blockMesh.getVoxelMesh().getBounds();
// const sizeVector = bounds.getDimensions().add(1);
// // https://github.com/SpongePowered/Schematic-Specification/blob/master/versions/schematic-3.md#paletteObject
// // const blockMapping: BlockMapping = {};
// const blockMapping: {[name: string]: { type: TagType, value: any }} = {
// 'minecraft:air': { type: TagType.Int, value: 0 },
// };
// let blockIndex = 1;
// for (const blockName of blockMesh.getBlockPalette()) {
// const namespacedBlockName = AppUtil.Text.namespaceBlock(blockName);
// blockMapping[namespacedBlockName] = { type: TagType.Int, value: blockIndex };
// ++blockIndex;
// }
// LOG(blockMapping);
// // const paletteObject = SchemExporter._createBlockStatePalette(blockMapping);
// const blockData = new Array<number>(sizeVector.x * sizeVector.y * sizeVector.z).fill(0);
// for (const block of blockMesh.getBlocks()) {
// const indexVector = Vector3.sub(block.voxel.position, bounds.min);
// const bufferIndex = SchemExporter._getBufferIndex(sizeVector, indexVector);
// const namespacedBlockName = AppUtil.Text.namespaceBlock(block.blockInfo.name);
// blockData[bufferIndex] = blockMapping[namespacedBlockName].value;
// }
// const blockEncoding: number[] = [];
// for (let i = 0; i < blockData.length; ++i) {
// let id = blockData[i];
// while ((id & -128) != 0) {
// blockEncoding.push(id & 127 | 128);
// id >>>= 7;
// }
// blockEncoding.push(id);
// }
// for (let i = 0; i < blockEncoding.length; ++i) {
// blockEncoding[i] = MathUtil.int8(blockEncoding[i]);
// }
// const nbt: NBT = {
// type: TagType.Compound,
// name: 'Schematic',
// value: {
// Version: { type: TagType.Int, value: SchemExporter.SCHEMA_VERSION },
// DataVersion: { type: TagType.Int, value: AppConstants.DATA_VERSION },
// Width: { type: TagType.Short, value: sizeVector.x },
// Height: { type: TagType.Short, value: sizeVector.y },
// Length: { type: TagType.Short, value: sizeVector.z },
// PaletteMax: { type: TagType.Int, value: blockIndex },
// Palette: { type: TagType.Compound, value: blockMapping },
// BlockData: { type: TagType.ByteArray, value: blockEncoding },
// },
// };
// saveNBT(nbt, filePath);
// return false;
}
private static _getBufferIndex(dimensions: Vector3, vec: Vector3) {

View File

@ -1,5 +1,4 @@
import fs from 'fs';
import { NBT, TagType } from 'prismarine-nbt';
//import { NBT, TagType } from 'prismarine-nbt';
import { BlockMesh } from '../block_mesh';
import { StatusHandler, StatusID } from '../status';
@ -17,9 +16,13 @@ export class Schematic extends IExporter {
const metaData = Array<number>(bufferSize);
const bounds = blockMesh.getVoxelMesh().getBounds();
// TODO Unimplemented
const schematicBlocks: { [blockName: string]: { id: number, meta: number, name: string } } = {};
/*
const schematicBlocks: { [blockName: string]: { id: number, meta: number, name: string } } = JSON.parse(
fs.readFileSync(PathUtil.join(AppPaths.Get.resources, './block_ids.json'), 'utf8'),
);
*/
const blocks = blockMesh.getBlocks();
const unsupportedBlocks = new Set<string>();
@ -48,6 +51,8 @@ export class Schematic extends IExporter {
LOG_WARN(unsupportedBlocks);
}
// TODO Unimplemented
/*
const nbt: NBT = {
type: TagType.Compound,
name: 'Schematic',
@ -64,6 +69,7 @@ export class Schematic extends IExporter {
};
return nbt;
*/
}
_getBufferIndex(vec: Vector3, sizeVector: Vector3) {
@ -90,7 +96,8 @@ export class Schematic extends IExporter {
this._sizeVector = Vector3.sub(bounds.max, bounds.min).add(1);
const nbt = this._convertToNBT(blockMesh);
saveNBT(nbt, filePath);
// TODO Unimplemented
//saveNBT(nbt, filePath);
return false;
}

3
src/global.d.ts vendored Normal file
View File

@ -0,0 +1,3 @@
declare module '*.vs';
declare module '*.fs';

View File

@ -1,4 +1,3 @@
import fs from 'fs';
import path from 'path';
import { RGBA, RGBAColours } from '../colour';
@ -311,6 +310,8 @@ export class ObjImporter extends IImporter {
}
private _parseOBJ(path: string) {
// TODO Unimplemented
/*
if (path === '') {
throw new AppError(`No filepath given`);
}
@ -328,6 +329,7 @@ export class ObjImporter extends IImporter {
for (const line of fileLines) {
this.parseOBJLine(line);
}
*/
}
public parseOBJLine(line: string) {
@ -357,6 +359,8 @@ export class ObjImporter extends IImporter {
}
private _parseMTL() {
//TODO Unimplemented
/*
for (const mtlLib of this._mtlLibs) {
if (!fs.existsSync(mtlLib)) {
StatusHandler.Get.add('warning', `Could not find ${mtlLib}`);
@ -373,6 +377,7 @@ export class ObjImporter extends IImporter {
this._addCurrentMaterial();
}
*/
}
private _parseMTLLine(line: string) {

View File

@ -1,118 +1,118 @@
/**
,d
88
,adPPYba, MM88MMM ,adPPYba, 8b,dPPYba,
I8[ "" 88 a8" "8a 88P' "8a
`"Y8ba, 88 8b d8 88 d8
aa ]8I 88, "8a, ,a8" 88b, ,a8"
`"YbbdP"' "Y888 `"YbbdP"' 88`YbbdP"'
88
88
// /**
// ,d
// 88
// ,adPPYba, MM88MMM ,adPPYba, 8b,dPPYba,
// I8[ "" 88 a8" "8a 88P' "8a
// `"Y8ba, 88 8b d8 88 d8
// aa ]8I 88, "8a, ,a8" 88b, ,a8"
// `"YbbdP"' "Y888 `"YbbdP"' 88`YbbdP"'
// 88
// 88
If you're interested in the code, I recommend starting in /src/AppContext.ts
The stuff here is boring Electron boilerplate \()/
*/
// If you're interested in the code, I recommend starting in /src/AppContext.ts
// The stuff here is boring Electron boilerplate \(•◡•)/
// */
import { app, BrowserWindow } from 'electron';
import url from 'url';
// import { app, BrowserWindow } from 'electron';
// import url from 'url';
import { AppConfig } from './config';
import { AppPaths, PathUtil } from './util/path_util';
// import { AppConfig } from './config';
// import { AppPaths, PathUtil } from './util/path_util';
app.commandLine.appendSwitch('js-flags', `--max-old-space-size=${AppConfig.Get.OLD_SPACE_SIZE_MB}`);
// app.commandLine.appendSwitch('js-flags', `--max-old-space-size=${AppConfig.Get.OLD_SPACE_SIZE_MB}`);
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow: BrowserWindow;
// // Keep a global reference of the window object, if you don't, the window will
// // be closed automatically when the JavaScript object is garbage collected.
// let mainWindow: BrowserWindow;
function createWindow() {
// Create the browser window.
// const {width, height} = electron.screen.getPrimaryDisplay().workAreaSize;
const width = 1400;
const height = 800;
// function createWindow() {
// // Create the browser window.
// // const {width, height} = electron.screen.getPrimaryDisplay().workAreaSize;
// const width = 1400;
// const height = 800;
// Create list of args to pass from main process to render process
const additionalArgs = [];
if (process.argv.includes('--OTS-ENABLE-DEBUG')) {
additionalArgs.push('--OTS-ENABLE-DEBUG');
}
// // Create list of args to pass from main process to render process
// const additionalArgs = [];
// if (process.argv.includes('--OTS-ENABLE-DEBUG')) {
// additionalArgs.push('--OTS-ENABLE-DEBUG');
// }
// const appIcon = new Tray("../resources/icon.png");
mainWindow = new BrowserWindow({
width: width,
height: height,
icon: PathUtil.join(AppPaths.Get.static, process.platform === 'win32' ? './icon.ico' : './icon.png'),
minWidth: 1280,
minHeight: 720,
webPreferences: {
nodeIntegration: true,
nodeIntegrationInWorker: true,
contextIsolation: false,
enableRemoteModule: true,
additionalArguments: additionalArgs,
},
});
if (AppConfig.Get.RELEASE_MODE) {
mainWindow.removeMenu();
}
// // const appIcon = new Tray("../resources/icon.png");
// mainWindow = new BrowserWindow({
// width: width,
// height: height,
// icon: PathUtil.join(AppPaths.Get.static, process.platform === 'win32' ? './icon.ico' : './icon.png'),
// minWidth: 1280,
// minHeight: 720,
// webPreferences: {
// nodeIntegration: true,
// nodeIntegrationInWorker: true,
// contextIsolation: false,
// enableRemoteModule: true,
// additionalArguments: additionalArgs,
// },
// });
// if (AppConfig.Get.RELEASE_MODE) {
// mainWindow.removeMenu();
// }
// Load index.html
mainWindow.loadURL(url.format({
pathname: PathUtil.join(AppPaths.Get.base, './index.html'),
protocol: 'file:',
slashes: true,
}));
// // Load index.html
// mainWindow.loadURL(url.format({
// pathname: PathUtil.join(AppPaths.Get.base, './index.html'),
// protocol: 'file:',
// slashes: true,
// }));
const baseTitle = 'ObjToSchematic Convert 3D models into Minecraft builds';
if (AppConfig.Get.RELEASE_MODE) {
mainWindow.setTitle(`${baseTitle} (${AppConfig.Get.RELEASE_VERSION})`);
} else {
try {
const branchName: Buffer = require('child_process')
.execSync('git rev-parse --abbrev-ref HEAD')
.toString()
.replace('\n', '');
// const baseTitle = 'ObjToSchematic Convert 3D models into Minecraft builds';
// if (AppConfig.Get.RELEASE_MODE) {
// mainWindow.setTitle(`${baseTitle} (${AppConfig.Get.RELEASE_VERSION})`);
// } else {
// try {
// const branchName: Buffer = require('child_process')
// .execSync('git rev-parse --abbrev-ref HEAD')
// .toString()
// .replace('\n', '');
const commitHash: (string | Buffer) = require('child_process')
.execSync('git rev-parse --short HEAD')
.toString()
.replace('\n', '');
// const commitHash: (string | Buffer) = require('child_process')
// .execSync('git rev-parse --short HEAD')
// .toString()
// .replace('\n', '');
mainWindow.setTitle(`${baseTitle} (git ${branchName.toString()} ${commitHash.toString().trim()})`);
} catch (e: any) {
mainWindow.setTitle(`${baseTitle} (git)`);
}
}
// mainWindow.setTitle(`${baseTitle} (git ${branchName.toString()} ${commitHash.toString().trim()})`);
// } catch (e: any) {
// mainWindow.setTitle(`${baseTitle} (git)`);
// }
// }
// Open the DevTools.
// mainWindow.webContents.openDevTools();
// // Open the DevTools.
// // mainWindow.webContents.openDevTools();
// Emitted when the window is closed.
mainWindow.on('closed', function () {
app.quit();
});
}
// // Emitted when the window is closed.
// mainWindow.on('closed', function () {
// app.quit();
// });
// }
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);
// // This method will be called when Electron has finished
// // initialization and is ready to create browser windows.
// // Some APIs can only be used after this event occurs.
// app.on('ready', createWindow);
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit();
}
});
// // Quit when all windows are closed.
// app.on('window-all-closed', function () {
// // On OS X it is common for applications and their menu bar
// // to stay active until the user quits explicitly with Cmd + Q
// if (process.platform !== 'darwin') {
// app.quit();
// }
// });
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow();
}
});
// app.on('activate', function () {
// // On OS X it's common to re-create a window in the app when the
// // dock icon is clicked and there are no other windows open.
// if (mainWindow === null) {
// createWindow();
// }
// });

View File

@ -1,4 +1,3 @@
import fs from 'fs';
import path from 'path';
import { Bounds } from './bounds';
@ -246,6 +245,8 @@ export class Mesh {
// Check texture paths are absolute and exist
this._materials.forEach((material, materialName) => {
// TODO Unimplemented
/*
if (material.type === MaterialType.textured) {
ASSERT(path.isAbsolute(material.path), 'Material texture path not absolute');
if (!fs.existsSync(material.path)) {
@ -263,6 +264,7 @@ export class Mesh {
}
}
}
*/
});
// Deduce default texture wrap mode for each material type

View File

@ -1,4 +1,3 @@
import fs from 'fs';
import path from 'path';
import { Atlas } from './atlas';
@ -12,6 +11,8 @@ export class PaletteManager {
public static getPalettesInfo(): { paletteID: string, paletteDisplayName: string }[] {
const palettes: { paletteID: string, paletteDisplayName: string }[] = [];
// TODO Unimplemented
/*
fs.readdirSync(AppPaths.Get.palettes).forEach((file) => {
const paletteFilePath = path.parse(file);
if (paletteFilePath.ext === Palette.PALETTE_FILE_EXT) {
@ -23,6 +24,7 @@ export class PaletteManager {
palettes.push({ paletteID: paletteID, paletteDisplayName: paletteDisplayName });
}
});
*/
return palettes;
}
@ -44,6 +46,9 @@ export class Palette {
}
public static load(paletteName: string): TOptional<Palette> {
// TODO Unimplemented
return undefined;
/*
if (!Palette._isValidPaletteName(paletteName)) {
return;
}
@ -74,9 +79,13 @@ export class Palette {
}
return palette;
*/
}
public save(paletteName: string): boolean {
// TODO Unimplemented
return false;
/*
if (!Palette._isValidPaletteName(paletteName)) {
return false;
}
@ -93,6 +102,7 @@ export class Palette {
} catch {
return false;
}
*/
}
public add(blockName: AppTypes.TNamespacedBlockName): void {

View File

@ -1,8 +1,16 @@
import * as fs from 'fs';
import * as twgl from 'twgl.js';
import FRAG_BLOCK from '../res/shaders/block_fragment.fs';
import VERT_BLOCK from '../res/shaders/block_vertex.vs';
import FRAG_DEBUG from '../res/shaders/debug_fragment.fs';
import VERT_DEBUG from '../res/shaders/debug_vertex.vs';
import FRAG_TRI_SOLID from '../res/shaders/solid_tri_fragment.fs';
import VERT_TRI_SOLID from '../res/shaders/solid_tri_vertex.vs';
import FRAG_TRI_TEXTURE from '../res/shaders/texture_tri_fragment.fs';
import VERT_TRI_TEXTURE from '../res/shaders/texture_tri_vertex.vs';
import FRAG_VOXEL from '../res/shaders/voxel_fragment.fs';
import VERT_VOXEL from '../res/shaders/voxel_vertex.vs';
import { Renderer } from './renderer';
import { AppPaths, PathUtil } from './util/path_util';
export class ShaderManager {
public readonly textureTriProgram: twgl.ProgramInfo;
@ -19,29 +27,14 @@ export class ShaderManager {
private constructor() {
const gl = Renderer.Get._gl;
const textureTriVertex = this._getShader('texture_tri_vertex.vs');
const textureTriFragment = this._getShader('texture_tri_fragment.fs');
this.textureTriProgram = twgl.createProgramInfo(gl, [textureTriVertex, textureTriFragment]);
this.textureTriProgram = twgl.createProgramInfo(gl, [VERT_TRI_TEXTURE, FRAG_TRI_TEXTURE]);
const solidTriVertex = this._getShader('solid_tri_vertex.vs');
const solidTriFragment = this._getShader('solid_tri_fragment.fs');
this.solidTriProgram = twgl.createProgramInfo(gl, [solidTriVertex, solidTriFragment]);
this.solidTriProgram = twgl.createProgramInfo(gl, [VERT_TRI_SOLID, FRAG_TRI_SOLID]);
const voxelVertexShader = this._getShader('voxel_vertex.vs');
const voxelFragmentShader = this._getShader('voxel_fragment.fs');
this.voxelProgram = twgl.createProgramInfo(gl, [voxelVertexShader, voxelFragmentShader]);
this.voxelProgram = twgl.createProgramInfo(gl, [VERT_VOXEL, FRAG_VOXEL]);
const blockVertexShader = this._getShader('block_vertex.vs');
const blockFragmentShader = this._getShader('block_fragment.fs');
this.blockProgram = twgl.createProgramInfo(gl, [blockVertexShader, blockFragmentShader]);
this.blockProgram = twgl.createProgramInfo(gl, [VERT_BLOCK, FRAG_BLOCK]);
const debugVertexShader = this._getShader('debug_vertex.vs');
const debugFragmentShader = this._getShader('debug_fragment.fs');
this.debugProgram = twgl.createProgramInfo(gl, [debugVertexShader, debugFragmentShader]);
}
private _getShader(filename: string) {
const absPath = PathUtil.join(AppPaths.Get.shaders, filename);
return fs.readFileSync(absPath, 'utf8');
this.debugProgram = twgl.createProgramInfo(gl, [VERT_DEBUG, FRAG_DEBUG]);
}
}

View File

@ -1,7 +1,5 @@
import * as fs from 'fs';
import * as jpeg from 'jpeg-js';
import path from 'path';
import { PNG } from 'pngjs';
const TGA = require('tga');
import { RGBA, RGBAColours, RGBAUtil } from './colour';
@ -9,7 +7,6 @@ import { AppConfig } from './config';
import { clamp } from './math';
import { UV } from './util';
import { AppError, ASSERT } from './util/error_util';
import { FileUtil } from './util/file_util';
import { LOG, LOG_ERROR, LOGF } from './util/log_util';
import { AppPaths } from './util/path_util';
import { TTexelExtension, TTexelInterpolation } from './util/type_util';
@ -68,40 +65,47 @@ export class Texture {
}
private _loadImageFile(filename: string): ImageData {
ASSERT(path.isAbsolute(filename));
const filePath = path.parse(filename);
try {
const data = fs.readFileSync(filename);
// TODO Unimplemented
return {
width: 0,
height: 0,
data: new Buffer(0),
};
// ASSERT(path.isAbsolute(filename));
// const filePath = path.parse(filename);
// try {
// const data = fs.readFileSync(filename);
switch (filePath.ext.toLowerCase()) {
case '.png': {
return PNG.sync.read(data);
}
case '.jpg':
case '.jpeg': {
this._useAlphaChannelValue = false;
return jpeg.decode(data, {
maxMemoryUsageInMB: AppConfig.Get.MAXIMUM_IMAGE_MEM_ALLOC,
formatAsRGBA: true,
});
}
/*
case '.tga': {
const tga = new TGA(data);
return {
width: tga.width,
height: tga.height,
data: tga.pixels,
};
}
*/
default:
ASSERT(false, 'Unsupported image format');
}
} catch (err) {
LOG_ERROR(err);
throw new AppError(`Could not read ${filename}`);
}
// switch (filePath.ext.toLowerCase()) {
// case '.png': {
// ASSERT(false); // TODO Unimplemented
// //return PNG.sync.read(data);
// }
// case '.jpg':
// case '.jpeg': {
// this._useAlphaChannelValue = false;
// return jpeg.decode(data, {
// maxMemoryUsageInMB: AppConfig.Get.MAXIMUM_IMAGE_MEM_ALLOC,
// formatAsRGBA: true,
// });
// }
// /*
// case '.tga': {
// const tga = new TGA(data);
// return {
// width: tga.width,
// height: tga.height,
// data: tga.pixels,
// };
// }
// */
// default:
// ASSERT(false, 'Unsupported image format');
// }
// } catch (err) {
// LOG_ERROR(err);
// throw new AppError(`Could not read ${filename}`);
// }
}
private _correctTexcoord(a: number) {
@ -128,7 +132,7 @@ export class Texture {
ASSERT(uv.u >= 0.0 && uv.u <= 1.0, 'Texcoord UV.u OOB');
ASSERT(uv.v >= 0.0 && uv.v <= 1.0, 'Texcoord UV.v OOB');
uv.v = 1.0 - uv.v;
const diffuse = (interpolation === 'nearest') ?
this._getNearestRGBA(this._image, uv) :
this._getLinearRGBA(this._image, uv);
@ -235,6 +239,9 @@ export class Texture {
export class TextureConverter {
public static createPNGfromTGA(filepath: string): string {
// TODO Unimplemented;
return '';
/*
ASSERT(fs.existsSync(filepath), '.tga does not exist');
const parsed = path.parse(filepath);
ASSERT(parsed.ext === '.tga');
@ -251,5 +258,6 @@ export class TextureConverter {
LOGF(`Creating new generated texture of '${filepath}' at '${newTexturePath}'`);
fs.writeFileSync(newTexturePath, buffer);
return newTexturePath;
*/
}
}

View File

@ -57,7 +57,7 @@ export class ComboBoxElement<T> extends ConfigUIElement<T, HTMLSelectElement> {
*/
public override _generateInnerHTML() {
ASSERT(this._items.length > 0);
//ASSERT(this._items.length > 0);
let itemsHTML = '';
for (const item of this._items) {
@ -85,7 +85,7 @@ export class ComboBoxElement<T> extends ConfigUIElement<T, HTMLSelectElement> {
const selectedIndex = this._items.findIndex((item) => item.payload === this.getValue());
const element = this._getElement();
ASSERT(selectedIndex !== -1, 'Invalid selected index');
//ASSERT(selectedIndex !== -1, 'Invalid selected index');
element.selectedIndex = selectedIndex;
}
}

View File

@ -1,4 +1,3 @@
import { remote } from 'electron';
import * as path from 'path';
import { ConfigUIElement } from './config_element';
@ -43,6 +42,8 @@ export class FileInputElement extends ConfigUIElement<string, HTMLDivElement> {
});
this._getElement().addEventListener('click', () => {
// TODO Unimplemented
/*
if (!this.getEnabled()) {
return;
}
@ -61,6 +62,7 @@ export class FileInputElement extends ConfigUIElement<string, HTMLDivElement> {
this._loadedFilePath = filePath;
this._setValue(filePath);
}
*/
});
this._getElement().addEventListener('mousemove', () => {

View File

@ -1,9 +1,8 @@
import { remote } from 'electron';
import path from 'path';
import { getRandomID } from '../../util';
import { FileUtil } from '../../util/file_util';
import { UIUtil } from '../../util/ui_util';
import { AppIcons } from '../icons';
import { ConfigUIElement } from './config_element';
import { ToolbarItemElement } from './toolbar_item';
@ -15,10 +14,12 @@ export class ImageElement extends ConfigUIElement<string, HTMLDivElement> {
public constructor(path: string) {
super(path);
this._switchElement = new ToolbarItemElement({ icon: 'upload' })
this._switchElement = new ToolbarItemElement({ iconSVG: AppIcons.UPLOAD })
.setSmall()
.setLabel('Choose')
.onClick(() => {
// TODO Unimplemented
/*
const files = remote.dialog.showOpenDialogSync({
title: 'Load',
buttonLabel: 'Load',
@ -30,11 +31,13 @@ export class ImageElement extends ConfigUIElement<string, HTMLDivElement> {
if (files && files[0]) {
this._setValue(files[0]);
}
*/
});
this._openElement = new ToolbarItemElement({ icon: 'folder' })
this._openElement = new ToolbarItemElement({ iconSVG: AppIcons.FOLDER })
.setSmall()
.onClick(() => {
FileUtil.openDir(this.getValue());
// TODO Unimplemented
//FileUtil.openDir(this.getValue());
});
this._imageId = getRandomID();

View File

@ -1,4 +1,5 @@
import { MaterialType } from '../../mesh';
import { AppIcons } from '../icons';
import { ConfigUIElement } from './config_element';
import { ToolbarItemElement } from './toolbar_item';
@ -7,7 +8,7 @@ export class MaterialTypeElement extends ConfigUIElement<MaterialType, HTMLDivEl
public constructor(material: MaterialType) {
super(material);
this._switchElement = new ToolbarItemElement({ icon: 'switch' })
this._switchElement = new ToolbarItemElement({ iconSVG: AppIcons.SWITCH })
.setSmall()
.setLabel('Switch')
.onClick(() => {

View File

@ -1,5 +1,3 @@
import fs from 'fs';
import { getRandomID } from '../../util';
import { ASSERT } from '../../util/error_util';
import { AppPaths } from '../../util/path_util';
@ -9,13 +7,12 @@ import { UIUtil } from '../../util/ui_util';
export type TToolbarBooleanProperty = 'enabled' | 'active';
export type TToolbarItemParams = {
icon: string;
iconSVG: string;
}
export class ToolbarItemElement {
private _id: string;
private _iconName: string;
private _iconPath: string;
private _iconSVG: SVGSVGElement;
private _isEnabled: boolean;
private _isActive: boolean;
private _isHovering: boolean;
@ -26,8 +23,15 @@ export class ToolbarItemElement {
public constructor(params: TToolbarItemParams) {
this._id = getRandomID();
this._iconName = params.icon;
this._iconPath = PathUtil.join(AppPaths.Get.static, params.icon + '.svg');
{
const parser = new DOMParser();
const svgParse = parser.parseFromString(params.iconSVG, 'text/html');
const svgs = svgParse.getElementsByTagName('svg');
ASSERT(svgs.length === 1, 'Missing SVG');
this._iconSVG = svgs[0];
this._iconSVG.id = this._id + '-svg';
}
this._isEnabled = true;
this._isActive = false;
@ -82,10 +86,9 @@ export class ToolbarItemElement {
}
public generateHTML() {
const svg = fs.readFileSync(this._iconPath, 'utf8');
return `
<div class="toolbar-item ${this._small ? 'toolbar-item-small' : ''}" id="${this._id}">
${svg} ${this._label}
${this._iconSVG.outerHTML} ${this._label}
</div>
`;
}
@ -110,15 +113,11 @@ export class ToolbarItemElement {
this._updateElements();
});
// Modify the svg's Id so that multiple svgs can be used without Id clashes
const svgElement = document.getElementById(this._iconName + '-svg') as HTMLDivElement;
svgElement.id += `-${this._id}`;
this._updateElements();
}
private _getSVGElement() {
const svgId = `${this._iconName}-svg-${this._id}`;
const svgId = this._id + '-svg';
return UIUtil.getElementById(svgId);
}

146
src/ui/icons.ts Normal file
View File

@ -0,0 +1,146 @@
export namespace AppIcons {
export const MESH = `
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-grain" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="mesh-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<circle cx="4.5" cy="9.5" r="1" />
<circle cx="9.5" cy="4.5" r="1" />
<circle cx="9.5" cy="14.5" r="1" />
<circle cx="4.5" cy="19.5" r="1" />
<circle cx="14.5" cy="9.5" r="1" />
<circle cx="19.5" cy="4.5" r="1" />
<circle cx="14.5" cy="19.5" r="1" />
<circle cx="19.5" cy="14.5" r="1" />
</svg>
`;
export const VOXEL = `
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-3d-cube-sphere" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="voxel-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M6 17.6l-2 -1.1v-2.5" />
<path d="M4 10v-2.5l2 -1.1" />
<path d="M10 4.1l2 -1.1l2 1.1" />
<path d="M18 6.4l2 1.1v2.5" />
<path d="M20 14v2.5l-2 1.12" />
<path d="M14 19.9l-2 1.1l-2 -1.1" />
<line x1="12" y1="12" x2="14" y2="10.9" />
<line x1="18" y1="8.6" x2="20" y2="7.5" />
<line x1="12" y1="12" x2="12" y2="14.5" />
<line x1="12" y1="18.5" x2="12" y2="21" />
<path d="M12 12l-2 -1.12" />
<line x1="6" y1="8.6" x2="4" y2="7.5" />
</svg>
`;
export const BLOCK = `
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-box" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="block-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<polyline points="12 3 20 7.5 20 16.5 12 21 4 16.5 4 7.5 12 3" />
<line x1="12" y1="12" x2="20" y2="7.5" />
<line x1="12" y1="12" x2="12" y2="21" />
<line x1="12" y1="12" x2="4" y2="7.5" />
</svg>
`;
export const GRID = `
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-border-all" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="grid-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<rect x="4" y="4" width="16" height="16" rx="2" />
<line x1="4" y1="12" x2="20" y2="12" />
<line x1="12" y1="4" x2="12" y2="20" />
</svg>
`;
export const AXES = `
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-axis-x" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="axes-svg">
<path d="M17 20l3 -3l-3 -3" />
<path d="M4 17h16" />
<path d="M4 7l3 -3l3 3" />
<path d="M7 20v-16" />
</svg>
`;
export const BULB = `
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-sun" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="bulb-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<circle cx="12" cy="12" r="4" />
<path d="M3 12h1m8 -9v1m8 8h1m-9 8v1m-6.4 -15.4l.7 .7m12.1 -.7l-.7 .7m0 11.4l.7 .7m-12.1 -.7l-.7 .7" />
</svg>
`;
export const MINUS = `
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-minus" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="minus-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<line x1="5" y1="12" x2="19" y2="12" />
</svg>
`;
export const PLUS = `
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-plus" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="plus-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<line x1="12" y1="5" x2="12" y2="19" />
<line x1="5" y1="12" x2="19" y2="12" />
</svg>
`;
export const CENTRE = `
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-focus-2" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="centre-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<circle cx="12" cy="12" r=".5" fill="currentColor" />
<circle cx="12" cy="12" r="7" />
<line x1="12" y1="3" x2="12" y2="5" />
<line x1="3" y1="12" x2="5" y2="12" />
<line x1="12" y1="19" x2="12" y2="21" />
<line x1="19" y1="12" x2="21" y2="12" />
</svg>
`;
export const PERSPECTIVE = `
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-perspective" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="perspective-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M6.141 4.163l12 1.714a1 1 0 0 1 .859 .99v10.266a1 1 0 0 1 -.859 .99l-12 1.714a1 1 0 0 1 -1.141 -.99v-13.694a1 1 0 0 1 1.141 -.99z" />
</svg>
`;
export const ORTHOGRAPHIC = `
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-rectangle" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="orthographic-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<rect x="3" y="5" width="18" height="14" rx="2" />
</svg>
`;
export const MAGNET = `
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-magnet" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="magnet-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M4 13v-8a2 2 0 0 1 2 -2h1a2 2 0 0 1 2 2v8a2 2 0 0 0 6 0v-8a2 2 0 0 1 2 -2h1a2 2 0 0 1 2 2v8a8 8 0 0 1 -16 0" />
<line x1="4" y1="8" x2="9" y2="8" />
<line x1="15" y1="8" x2="19" y2="8" />
</svg>
`;
export const UPLOAD = `
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-upload" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#2c3e50" fill="none" stroke-linecap="round" stroke-linejoin="round" id="upload-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2" />
<polyline points="7 9 12 4 17 9" />
<line x1="12" y1="4" x2="12" y2="16" />
</svg>
`;
export const FOLDER = `
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-folder" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#2c3e50" fill="none" stroke-linecap="round" stroke-linejoin="round" id="folder-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M5 4h4l3 3h7a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-11a2 2 0 0 1 2 -2" />
</svg>
`;
export const SWITCH = `
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-switch-3" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#2c3e50" fill="none" stroke-linecap="round" stroke-linejoin="round" id="switch-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M3 17h2.397a5 5 0 0 0 4.096 -2.133l.177 -.253m3.66 -5.227l.177 -.254a5 5 0 0 1 4.096 -2.133h3.397" />
path d="M18 4l3 3l-3 3" />
<path d="M3 7h2.397a5 5 0 0 1 4.096 2.133l4.014 5.734a5 5 0 0 0 4.096 2.133h3.397" />
<path d="M18 20l3 -3l-3 -3" />
</svg>
`;
}

View File

@ -1,5 +1,3 @@
import fs from 'fs';
import { AppContext } from '../app_context';
import { FallableBehaviour } from '../block_mesh';
import { ArcballCamera } from '../camera';
@ -23,6 +21,7 @@ import { OutputElement } from './elements/output';
import { SliderElement } from './elements/slider';
import { ToolbarItemElement } from './elements/toolbar_item';
import { VectorSpinboxElement } from './elements/vector_spinbox';
import { AppIcons } from './icons';
export interface Group {
label: string;
@ -285,7 +284,7 @@ export class UI {
groups: {
'viewmode': {
elements: {
'mesh': new ToolbarItemElement({ icon: 'mesh' })
'mesh': new ToolbarItemElement({ iconSVG: AppIcons.MESH })
.onClick(() => {
Renderer.Get.setModelToUse(MeshType.TriangleMesh);
})
@ -295,7 +294,7 @@ export class UI {
.isEnabled(() => {
return Renderer.Get.getModelsAvailable() >= MeshType.TriangleMesh;
}),
'voxelMesh': new ToolbarItemElement({ icon: 'voxel' })
'voxelMesh': new ToolbarItemElement({ iconSVG: AppIcons.VOXEL })
.onClick(() => {
Renderer.Get.setModelToUse(MeshType.VoxelMesh);
})
@ -305,7 +304,7 @@ export class UI {
.isEnabled(() => {
return Renderer.Get.getModelsAvailable() >= MeshType.VoxelMesh;
}),
'blockMesh': new ToolbarItemElement({ icon: 'block' })
'blockMesh': new ToolbarItemElement({ iconSVG: AppIcons.BLOCK })
.onClick(() => {
Renderer.Get.setModelToUse(MeshType.BlockMesh);
})
@ -320,7 +319,7 @@ export class UI {
},
'debug': {
elements: {
'grid': new ToolbarItemElement({ icon: 'grid' })
'grid': new ToolbarItemElement({ iconSVG: AppIcons.GRID })
.onClick(() => {
Renderer.Get.toggleIsGridEnabled();
})
@ -330,14 +329,14 @@ export class UI {
.isEnabled(() => {
return Renderer.Get.getActiveMeshType() !== MeshType.None;
}),
'axes': new ToolbarItemElement({ icon: 'axes' })
'axes': new ToolbarItemElement({ iconSVG: AppIcons.AXES })
.onClick(() => {
Renderer.Get.toggleIsAxesEnabled();
})
.isActive(() => {
return Renderer.Get.isAxesEnabled();
}),
'night-vision': new ToolbarItemElement({ icon: 'bulb' })
'night-vision': new ToolbarItemElement({ iconSVG: AppIcons.BULB })
.onClick(() => {
Renderer.Get.toggleIsNightVisionEnabled();
})
@ -359,15 +358,15 @@ export class UI {
groups: {
'zoom': {
elements: {
'zoomOut': new ToolbarItemElement({ icon: 'minus' })
'zoomOut': new ToolbarItemElement({ iconSVG: AppIcons.MINUS })
.onClick(() => {
ArcballCamera.Get.onZoomOut();
}),
'zoomIn': new ToolbarItemElement({ icon: 'plus' })
'zoomIn': new ToolbarItemElement({ iconSVG: AppIcons.PLUS })
.onClick(() => {
ArcballCamera.Get.onZoomIn();
}),
'reset': new ToolbarItemElement({ icon: 'centre' })
'reset': new ToolbarItemElement({ iconSVG: AppIcons.CENTRE })
.onClick(() => {
ArcballCamera.Get.reset();
}),
@ -376,21 +375,21 @@ export class UI {
},
'camera': {
elements: {
'perspective': new ToolbarItemElement({ icon: 'perspective' })
'perspective': new ToolbarItemElement({ iconSVG: AppIcons.PERSPECTIVE })
.onClick(() => {
ArcballCamera.Get.setCameraMode('perspective');
})
.isActive(() => {
return ArcballCamera.Get.isPerspective();
}),
'orthographic': new ToolbarItemElement({ icon: 'orthographic' })
'orthographic': new ToolbarItemElement({ iconSVG: AppIcons.ORTHOGRAPHIC })
.onClick(() => {
ArcballCamera.Get.setCameraMode('orthographic');
})
.isActive(() => {
return ArcballCamera.Get.isOrthographic();
}),
'angleSnap': new ToolbarItemElement({ icon: 'magnet' })
'angleSnap': new ToolbarItemElement({ iconSVG: AppIcons.MAGNET })
.onClick(() => {
ArcballCamera.Get.toggleAngleSnap();
})
@ -651,6 +650,8 @@ export class UI {
private _getTextureAtlases(): ComboBoxItem<string>[] {
const textureAtlases: ComboBoxItem<string>[] = [];
// TODO Unimplemented
/*
fs.readdirSync(AppPaths.Get.atlases).forEach((file) => {
if (file.endsWith('.atlas')) {
const paletteID = file.split('.')[0];
@ -659,6 +660,7 @@ export class UI {
textureAtlases.push({ payload: paletteID, displayText: paletteName });
}
});
*/
return textureAtlases;
}

View File

@ -1,35 +0,0 @@
import child from 'child_process';
import fs from 'fs';
import path from 'path';
import { LOGF } from './log_util';
export namespace FileUtil {
export function fileExists(absolutePath: string) {
return fs.existsSync(absolutePath);
}
export function mkdirIfNotExist(path: fs.PathLike) {
if (!fs.existsSync(path)) {
fs.mkdirSync(path);
}
}
export function rmdirIfExist(path: fs.PathLike) {
if (fs.existsSync(path)) {
LOGF(`Deleting '${path.toString()}'`);
fs.rmSync(path, { recursive: true, force: true });
}
}
export function openDir(absolutePath: string) {
switch (process.platform) {
case 'darwin':
child.exec(`open -R ${absolutePath}`);
break;
case 'win32':
const parsed = path.parse(absolutePath);
child.exec(`start ${parsed.dir}`);
}
}
}

View File

@ -1,8 +1,6 @@
import fs from 'fs';
import util from 'util';
import { AppConfig } from '../config';
import { FileUtil } from './file_util';
import { AppPaths, PathUtil } from './path_util';
/**
@ -15,16 +13,9 @@ export const LOG = (...data: any[]) => {
// eslint-disable-next-line no-console
console.log(...data);
}
if (Logger.Get.logToFile) {
Logger.Get.logToFile(...data);
}
};
export const LOGF = (...data: any[]) => {
if (Logger.Get.logToFile) {
Logger.Get.logToFile(...data);
}
};
export const LOGF = LOG;
/**
* Logs to console and file if logging `LOG_MAJOR` is enabled.
@ -37,9 +28,6 @@ export const LOG_MAJOR = (...data: any[]) => {
// eslint-disable-next-line no-console
console.log(...data);
}
if (Logger.Get.logToFile) {
Logger.Get.logToFile(...data);
}
};
/**
@ -50,9 +38,6 @@ export const LOG_WARN = (...data: any[]) => {
// eslint-disable-next-line no-console
console.warn(...data);
}
if (Logger.Get.logToFile) {
Logger.Get.logToFile(...data);
}
};
/**
@ -85,9 +70,6 @@ export const TIME_END = (label: string) => {
export const LOG_ERROR = (...data: any[]) => {
// eslint-disable-next-line no-console
console.error(...data);
if (Logger.Get.logToFile) {
Logger.Get.logToFile(...data);
}
};
/**
@ -107,8 +89,6 @@ export class Logger {
private _enabledLogToFile?: boolean;
private _logStream?: fs.WriteStream;
private constructor() {
this._enabledLOG = false;
this._enabledLOGMAJOR = false;
@ -116,27 +96,6 @@ export class Logger {
this._enabledLOGTIME = false;
}
/**
* Setup the log file.
* @param suffix The suffix to append to the end of the log file name.
*/
public initLogFile(suffix: string) {
if (this._logStream === undefined && this._enabledLogToFile === true) {
FileUtil.mkdirIfNotExist(AppPaths.Get.logs);
this._logStream = fs.createWriteStream(PathUtil.join(AppPaths.Get.logs, `./${Date.now()}-${suffix}.log`));
}
}
/**
* Logs to the log file if setup.
* @param data The data to print.
*/
public logToFile(...data: any[]) {
if (this._logStream && this._enabledLogToFile) {
this._logStream.write(`[${(new Date()).toISOString()}] ${util.format(...data)}\n`);
}
}
/**
* Allow `LOG` calls to be printed to the console and to the log file if setup.
*/
@ -193,16 +152,6 @@ export class Logger {
this._enabledLOGTIME = false;
}
/**
* Allow console log calls to logged to the log file if setup.
* Should be called before `initLogFile`
*/
public enableLogToFile() {
if (AppConfig.Get.LOG_TO_FILE && this._enabledLogToFile === undefined) {
this._enabledLogToFile = true;
}
}
/**
* Prevent console log calls to logged to the log file if setup.
*/
@ -237,11 +186,4 @@ export class Logger {
public isLOGTIMEEnabled() {
return this._enabledLOGTIME;
}
/**
* Whether or not console log calls should be logged to the log file if setup.
*/
public isLogToFileEnabled() {
return this.logToFile;
}
}

View File

@ -1,14 +1,18 @@
import fs from 'fs';
import path from 'path';
import { NBT, writeUncompressed } from 'prismarine-nbt';
//import { NBT, writeUncompressed } from 'prismarine-nbt';
import zlib from 'zlib';
import { ASSERT } from './error_util';
type NBT = {};
export function saveNBT(nbt: NBT, filepath: string) {
// TODO Unimplemented
/*
ASSERT(path.isAbsolute(filepath), '[saveNBT]: filepath is not absolute');
const uncompressedBuffer = writeUncompressed(nbt, 'big');
const compressedBuffer = zlib.gzipSync(uncompressedBuffer);
fs.writeFileSync(filepath, compressedBuffer);
*/
}

View File

@ -21,8 +21,6 @@ export class WorkerClient {
}
private constructor() {
Logger.Get.enableLogToFile();
Logger.Get.initLogFile('worker');
}
private _loadedMesh?: Mesh;

View File

@ -12,15 +12,17 @@ export type TWorkerJob = {
}
export class WorkerController {
private _worker: Worker;
private _worker?: Worker;
private _jobQueue: TWorkerJob[];
private _jobPending: TWorkerJob | undefined;
private _jobStartTime: number;
private _timerOn: boolean;
public constructor(scriptURL: string, options?: WorkerOptions) {
this._worker = new Worker(scriptURL, options);
this._worker.onmessage = this._onWorkerMessage.bind(this);
if (AppConfig.Get.USE_WORKER_THREAD) {
this._worker = new Worker(scriptURL, options);
this._worker.onmessage = this._onWorkerMessage.bind(this);
}
this._jobQueue = [];
this._jobStartTime = 0;
@ -105,6 +107,7 @@ export class WorkerController {
}
if (AppConfig.Get.USE_WORKER_THREAD) {
ASSERT(this._worker !== undefined, 'No worker instance');
this._worker.postMessage(this._jobPending.payload);
} else {
const result = doWork(this._jobPending.payload);

View File

@ -1,423 +1,419 @@
import fs from 'fs';
import images from 'images';
import path from 'path';
import { PNG } from 'pngjs';
import prompt from 'prompt';
// import images from 'images';
// import path from 'path';
// import prompt from 'prompt';
import { RGBA, RGBAUtil } from '../src/colour';
import { AppUtil } from '../src/util';
import { LOG, LOG_WARN, Logger } from '../src/util/log_util';
// import { RGBA, RGBAUtil } from '../src/colour';
// import { AppUtil } from '../src/util';
// import { LOG, LOG_WARN, Logger } from '../src/util/log_util';
const AdmZip = require('adm-zip');
const copydir = require('copy-dir');
// const AdmZip = require('adm-zip');
// const copydir = require('copy-dir');
import { AppPaths, PathUtil } from '../src/util/path_util';
import { log } from './logging';
import { ASSERT_EXISTS, getAverageColour, getMinecraftDir, getStandardDeviation } from './misc';
// import { AppPaths, PathUtil } from '../src/util/path_util';
// import { log } from './logging';
// import { ASSERT_EXISTS, getAverageColour, getMinecraftDir, getStandardDeviation } from './misc';
const BLOCKS_DIR = PathUtil.join(AppPaths.Get.tools, '/blocks');
const MODELS_DIR = PathUtil.join(AppPaths.Get.tools, '/models');
// const BLOCKS_DIR = PathUtil.join(AppPaths.Get.tools, '/blocks');
// const MODELS_DIR = PathUtil.join(AppPaths.Get.tools, '/models');
type TFaceData<T> = {
up: T,
down: T,
north: T,
south: T,
east: T,
west: T,
}
// type TFaceData<T> = {
// up: T,
// down: T,
// north: T,
// south: T,
// east: T,
// west: T,
// }
export type TAtlasVersion = {
formatVersion: 3,
atlasSize: number,
blocks: Array<{ name: string, faces: TFaceData<string>, colour: RGBA }>,
textures: { [texture: string]: { atlasColumn: number, atlasRow: number, colour: RGBA, std: number } },
supportedBlockNames: string[],
};
// export type TAtlasVersion = {
// formatVersion: 3,
// atlasSize: number,
// blocks: Array<{ name: string, faces: TFaceData<string>, colour: RGBA }>,
// textures: { [texture: string]: { atlasColumn: number, atlasRow: number, colour: RGBA, std: number } },
// supportedBlockNames: string[],
// };
void async function main() {
AppPaths.Get.setBaseDir(PathUtil.join(__dirname, '../..'));
Logger.Get.enableLogToFile();
Logger.Get.initLogFile('atlas');
// void async function main() {
// AppPaths.Get.setBaseDir(PathUtil.join(__dirname, '../..'));
// Logger.Get.enableLogToFile();
// Logger.Get.initLogFile('atlas');
const minecraftDir = getMinecraftDir();
// const minecraftDir = getMinecraftDir();
// Clean up temporary data from previous use
{
fs.rmSync(BLOCKS_DIR, { recursive: true, force: true });
fs.rmSync(MODELS_DIR, { recursive: true, force: true });
}
// // Clean up temporary data from previous use
// {
// fs.rmSync(BLOCKS_DIR, { recursive: true, force: true });
// fs.rmSync(MODELS_DIR, { recursive: true, force: true });
// }
// Ask for permission to access Minecraft dir
{
log('Prompt', `This script requires files inside '${minecraftDir}'`);
// // Ask for permission to access Minecraft dir
// {
// log('Prompt', `This script requires files inside '${minecraftDir}'`);
const { permission } = await prompt.get({
properties: {
permission: {
pattern: /^[YyNn]$/,
description: 'Do you give permission to access these files? (y/n)',
message: 'Response must be Y or N',
required: true,
},
},
});
// const { permission } = await prompt.get({
// properties: {
// permission: {
// pattern: /^[YyNn]$/,
// description: 'Do you give permission to access these files? (y/n)',
// message: 'Response must be Y or N',
// required: true,
// },
// },
// });
const isResponseYes = ['Y', 'y'].includes(permission as string);
if (!isResponseYes) {
process.exit(0);
}
}
// const isResponseYes = ['Y', 'y'].includes(permission as string);
// if (!isResponseYes) {
// process.exit(0);
// }
// }
ASSERT_EXISTS(minecraftDir);
// ASSERT_EXISTS(minecraftDir);
// Prompt user to pick a version
let chosenVersionName: string;
let chosenVersionDir: string;
{
const versionsDir = PathUtil.join(minecraftDir, '/versions');
ASSERT_EXISTS(versionsDir);
// // Prompt user to pick a version
// let chosenVersionName: string;
// let chosenVersionDir: string;
// {
// const versionsDir = PathUtil.join(minecraftDir, '/versions');
// ASSERT_EXISTS(versionsDir);
const versions = fs.readdirSync(versionsDir)
.filter((file) => fs.lstatSync(PathUtil.join(versionsDir, file)).isDirectory())
.map((file) => ({ file, birthtime: fs.lstatSync(PathUtil.join(versionsDir, file)).birthtime }))
.sort((a, b) => b.birthtime.getTime() - a.birthtime.getTime());
{
versions.forEach((version, index) => {
log('Option', `${index + 1}) ${version.file}`);
});
}
// const versions = fs.readdirSync(versionsDir)
// .filter((file) => fs.lstatSync(PathUtil.join(versionsDir, file)).isDirectory())
// .map((file) => ({ file, birthtime: fs.lstatSync(PathUtil.join(versionsDir, file)).birthtime }))
// .sort((a, b) => b.birthtime.getTime() - a.birthtime.getTime());
// {
// versions.forEach((version, index) => {
// log('Option', `${index + 1}) ${version.file}`);
// });
// }
// Prompt user to pick a version
const { packChoice } = await prompt.get({
properties: {
packChoice: {
description: `Which version do you want to build an atlas for? (1-${versions.length})`,
message: `Response must be between 1 and ${versions.length}`,
required: true,
conform: (value) => {
return value >= 1 && value <= versions.length;
},
},
},
});
// // Prompt user to pick a version
// const { packChoice } = await prompt.get({
// properties: {
// packChoice: {
// description: `Which version do you want to build an atlas for? (1-${versions.length})`,
// message: `Response must be between 1 and ${versions.length}`,
// required: true,
// conform: (value) => {
// return value >= 1 && value <= versions.length;
// },
// },
// },
// });
chosenVersionName = versions[(<number>packChoice) - 1].file;
chosenVersionDir = PathUtil.join(versionsDir, chosenVersionName);
}
// chosenVersionName = versions[(<number>packChoice) - 1].file;
// chosenVersionDir = PathUtil.join(versionsDir, chosenVersionName);
// }
// Get vanilla models and textures
{
const jarName = `${chosenVersionName}.jar`;
const jarDir = PathUtil.join(chosenVersionDir, jarName);
ASSERT_EXISTS(jarDir);
// // Get vanilla models and textures
// {
// const jarName = `${chosenVersionName}.jar`;
// const jarDir = PathUtil.join(chosenVersionDir, jarName);
// ASSERT_EXISTS(jarDir);
log('Info', `Upzipping '${jarDir}'...`);
{
const zip = new AdmZip(jarDir);
const zipEntries = zip.getEntries();
zipEntries.forEach((zipEntry: any) => {
if (zipEntry.entryName.startsWith('assets/minecraft/textures/block')) {
zip.extractEntryTo(zipEntry.entryName, BLOCKS_DIR, false, true);
} else if (zipEntry.entryName.startsWith('assets/minecraft/models/block')) {
zip.extractEntryTo(zipEntry.entryName, MODELS_DIR, false, true);
}
});
}
log('Success', `Extracted Vanilla models to '${MODELS_DIR}'`);
log('Success', `Extracted Vanilla textures to '${BLOCKS_DIR}'`);
}
// log('Info', `Upzipping '${jarDir}'...`);
// {
// const zip = new AdmZip(jarDir);
// const zipEntries = zip.getEntries();
// zipEntries.forEach((zipEntry: any) => {
// if (zipEntry.entryName.startsWith('assets/minecraft/textures/block')) {
// zip.extractEntryTo(zipEntry.entryName, BLOCKS_DIR, false, true);
// } else if (zipEntry.entryName.startsWith('assets/minecraft/models/block')) {
// zip.extractEntryTo(zipEntry.entryName, MODELS_DIR, false, true);
// }
// });
// }
// log('Success', `Extracted Vanilla models to '${MODELS_DIR}'`);
// log('Success', `Extracted Vanilla textures to '${BLOCKS_DIR}'`);
// }
// Prompt user to pick a resource pack
let chosenResourcePackDir: string | undefined;
{
const resourcePacksDir = PathUtil.join(minecraftDir, '/resourcepacks');
ASSERT_EXISTS(resourcePacksDir);
// // Prompt user to pick a resource pack
// let chosenResourcePackDir: string | undefined;
// {
// const resourcePacksDir = PathUtil.join(minecraftDir, '/resourcepacks');
// ASSERT_EXISTS(resourcePacksDir);
const resourcePacks = fs.readdirSync(resourcePacksDir);
{
log('Option', `1) Vanilla`);
resourcePacks.forEach((resourcePack, index) => {
log('Option', `${index + 2}) ${resourcePack}`);
});
}
// const resourcePacks = fs.readdirSync(resourcePacksDir);
// {
// log('Option', `1) Vanilla`);
// resourcePacks.forEach((resourcePack, index) => {
// log('Option', `${index + 2}) ${resourcePack}`);
// });
// }
const { resourcePackChoiceIndex } = await prompt.get({
properties: {
packChoice: {
description: `Which resource pack do you want to build an atlas for? (1-${resourcePacks.length + 1})`,
message: `Response must be between 1 and ${resourcePacks.length + 1}`,
required: true,
conform: (value) => {
return value >= 1 && value <= resourcePacks.length + 1;
},
},
},
});
// const { resourcePackChoiceIndex } = await prompt.get({
// properties: {
// packChoice: {
// description: `Which resource pack do you want to build an atlas for? (1-${resourcePacks.length + 1})`,
// message: `Response must be between 1 and ${resourcePacks.length + 1}`,
// required: true,
// conform: (value) => {
// return value >= 1 && value <= resourcePacks.length + 1;
// },
// },
// },
// });
chosenResourcePackDir = (<number>resourcePackChoiceIndex) === 1 ? undefined : resourcePacks[(<number>resourcePackChoiceIndex) - 2];
}
// chosenResourcePackDir = (<number>resourcePackChoiceIndex) === 1 ? undefined : resourcePacks[(<number>resourcePackChoiceIndex) - 2];
// }
// Get resource pack textures
if (chosenResourcePackDir !== undefined) {
log('Warning', 'Using non-16x16 texture packs is not supported and will result in undefined behaviour');
{
if (fs.lstatSync(chosenResourcePackDir).isDirectory()) {
log('Info', `Resource pack '${chosenResourcePackDir}' is a directory`);
// // Get resource pack textures
// if (chosenResourcePackDir !== undefined) {
// log('Warning', 'Using non-16x16 texture packs is not supported and will result in undefined behaviour');
// {
// if (fs.lstatSync(chosenResourcePackDir).isDirectory()) {
// log('Info', `Resource pack '${chosenResourcePackDir}' is a directory`);
const blockTexturesSrc = PathUtil.join(chosenResourcePackDir, 'assets/minecraft/textures/block');
const blockTexturesDst = BLOCKS_DIR;
// const blockTexturesSrc = PathUtil.join(chosenResourcePackDir, 'assets/minecraft/textures/block');
// const blockTexturesDst = BLOCKS_DIR;
log('Info', `Copying ${blockTexturesSrc} to ${blockTexturesDst}...`);
copydir(blockTexturesSrc, blockTexturesDst, {
utimes: true,
mode: true,
cover: true,
});
} else {
log('Info', `Resource pack '${chosenResourcePackDir}' is not a directory, expecting to be a .zip`);
// log('Info', `Copying ${blockTexturesSrc} to ${blockTexturesDst}...`);
// copydir(blockTexturesSrc, blockTexturesDst, {
// utimes: true,
// mode: true,
// cover: true,
// });
// } else {
// log('Info', `Resource pack '${chosenResourcePackDir}' is not a directory, expecting to be a .zip`);
const zip = new AdmZip(chosenResourcePackDir);
const zipEntries = zip.getEntries();
zipEntries.forEach((zipEntry: any) => {
if (zipEntry.entryName.startsWith('assets/minecraft/textures/block')) {
zip.extractEntryTo(zipEntry.entryName, BLOCKS_DIR, false, true);
}
});
}
}
log('Success', `Copied block textures successfully`);
}
// const zip = new AdmZip(chosenResourcePackDir);
// const zipEntries = zip.getEntries();
// zipEntries.forEach((zipEntry: any) => {
// if (zipEntry.entryName.startsWith('assets/minecraft/textures/block')) {
// zip.extractEntryTo(zipEntry.entryName, BLOCKS_DIR, false, true);
// }
// });
// }
// }
// log('Success', `Copied block textures successfully`);
// }
// Load the ignore list
let ignoreList: Array<string> = [];
{
log('Info', 'Loading ignore list...');
{
const ignoreListPath = PathUtil.join(AppPaths.Get.tools, './models-ignore-list.txt');
if (fs.existsSync(ignoreListPath)) {
log('Success', `Found ignore list in '${ignoreListPath}'`);
ignoreList = fs.readFileSync(ignoreListPath, 'utf-8').replace(/\r/g, '').split('\n');
log('Info', `Found ${ignoreList.length} blocks in ignore list`);
} else {
log('Warning', `Could not find ignore list '${ignoreListPath}'`);
}
}
}
// // Load the ignore list
// let ignoreList: Array<string> = [];
// {
// log('Info', 'Loading ignore list...');
// {
// const ignoreListPath = PathUtil.join(AppPaths.Get.tools, './models-ignore-list.txt');
// if (fs.existsSync(ignoreListPath)) {
// log('Success', `Found ignore list in '${ignoreListPath}'`);
// ignoreList = fs.readFileSync(ignoreListPath, 'utf-8').replace(/\r/g, '').split('\n');
// log('Info', `Found ${ignoreList.length} blocks in ignore list`);
// } else {
// log('Warning', `Could not find ignore list '${ignoreListPath}'`);
// }
// }
// }
const usedTextures = new Set<string>();
const usedModels: Array<{ name: string, faces: TFaceData<string> }> = [];
// const usedTextures = new Set<string>();
// const usedModels: Array<{ name: string, faces: TFaceData<string> }> = [];
// Load all models to use
{
const allModels = fs.readdirSync(MODELS_DIR);
log('Info', `Found ${allModels.length} models in '${MODELS_DIR}'`);
// // Load all models to use
// {
// const allModels = fs.readdirSync(MODELS_DIR);
// log('Info', `Found ${allModels.length} models in '${MODELS_DIR}'`);
allModels.forEach((modelRelDir, index) => {
const modelAbsDir = PathUtil.join(MODELS_DIR, modelRelDir);
const parsed = path.parse(modelAbsDir);
// allModels.forEach((modelRelDir, index) => {
// const modelAbsDir = PathUtil.join(MODELS_DIR, modelRelDir);
// const parsed = path.parse(modelAbsDir);
if (parsed.ext !== '.json' || ignoreList.includes(parsed.base)) {
return;
}
// if (parsed.ext !== '.json' || ignoreList.includes(parsed.base)) {
// return;
// }
const fileData = fs.readFileSync(modelAbsDir, 'utf8');
const modelData = JSON.parse(fileData);
// const fileData = fs.readFileSync(modelAbsDir, 'utf8');
// const modelData = JSON.parse(fileData);
const faceData: TFaceData<string> | undefined = (() => {
switch (modelData.parent) {
case 'minecraft:block/cube_column_horizontal':
return {
up: modelData.textures.side,
down: modelData.textures.side,
north: modelData.textures.end,
south: modelData.textures.end,
east: modelData.textures.side,
west: modelData.textures.side,
};
case 'minecraft:block/cube_all':
return {
up: modelData.textures.all,
down: modelData.textures.all,
north: modelData.textures.all,
south: modelData.textures.all,
east: modelData.textures.all,
west: modelData.textures.all,
};
case 'minecraft:block/cube_column':
return {
up: modelData.textures.end,
down: modelData.textures.end,
north: modelData.textures.side,
south: modelData.textures.side,
east: modelData.textures.side,
west: modelData.textures.side,
};
case 'minecraft:block/cube_bottom_top':
return {
up: modelData.textures.top,
down: modelData.textures.bottom,
north: modelData.textures.side,
south: modelData.textures.side,
east: modelData.textures.side,
west: modelData.textures.side,
};
case 'minecraft:block/cube':
return {
up: modelData.textures.up,
down: modelData.textures.down,
north: modelData.textures.north,
south: modelData.textures.south,
east: modelData.textures.east,
west: modelData.textures.west,
};
case 'minecraft:block/template_single_face':
return {
up: modelData.textures.texture,
down: modelData.textures.texture,
north: modelData.textures.texture,
south: modelData.textures.texture,
east: modelData.textures.texture,
west: modelData.textures.texture,
};
case 'minecraft:block/template_glazed_terracotta':
return {
up: modelData.textures.pattern,
down: modelData.textures.pattern,
north: modelData.textures.pattern,
south: modelData.textures.pattern,
east: modelData.textures.pattern,
west: modelData.textures.pattern,
};
case 'minecraft:block/leaves':
return {
up: modelData.textures.all,
down: modelData.textures.all,
north: modelData.textures.all,
south: modelData.textures.all,
east: modelData.textures.all,
west: modelData.textures.all,
};
}
})();
// const faceData: TFaceData<string> | undefined = (() => {
// switch (modelData.parent) {
// case 'minecraft:block/cube_column_horizontal':
// return {
// up: modelData.textures.side,
// down: modelData.textures.side,
// north: modelData.textures.end,
// south: modelData.textures.end,
// east: modelData.textures.side,
// west: modelData.textures.side,
// };
// case 'minecraft:block/cube_all':
// return {
// up: modelData.textures.all,
// down: modelData.textures.all,
// north: modelData.textures.all,
// south: modelData.textures.all,
// east: modelData.textures.all,
// west: modelData.textures.all,
// };
// case 'minecraft:block/cube_column':
// return {
// up: modelData.textures.end,
// down: modelData.textures.end,
// north: modelData.textures.side,
// south: modelData.textures.side,
// east: modelData.textures.side,
// west: modelData.textures.side,
// };
// case 'minecraft:block/cube_bottom_top':
// return {
// up: modelData.textures.top,
// down: modelData.textures.bottom,
// north: modelData.textures.side,
// south: modelData.textures.side,
// east: modelData.textures.side,
// west: modelData.textures.side,
// };
// case 'minecraft:block/cube':
// return {
// up: modelData.textures.up,
// down: modelData.textures.down,
// north: modelData.textures.north,
// south: modelData.textures.south,
// east: modelData.textures.east,
// west: modelData.textures.west,
// };
// case 'minecraft:block/template_single_face':
// return {
// up: modelData.textures.texture,
// down: modelData.textures.texture,
// north: modelData.textures.texture,
// south: modelData.textures.texture,
// east: modelData.textures.texture,
// west: modelData.textures.texture,
// };
// case 'minecraft:block/template_glazed_terracotta':
// return {
// up: modelData.textures.pattern,
// down: modelData.textures.pattern,
// north: modelData.textures.pattern,
// south: modelData.textures.pattern,
// east: modelData.textures.pattern,
// west: modelData.textures.pattern,
// };
// case 'minecraft:block/leaves':
// return {
// up: modelData.textures.all,
// down: modelData.textures.all,
// north: modelData.textures.all,
// south: modelData.textures.all,
// east: modelData.textures.all,
// west: modelData.textures.all,
// };
// }
// })();
// Debug logging to file
if (faceData === undefined) {
LOG_WARN(`Could not parse '${parsed.base}'`);
return;
} else {
LOG(`Parsed '${parsed.base}'`);
}
// // Debug logging to file
// if (faceData === undefined) {
// LOG_WARN(`Could not parse '${parsed.base}'`);
// return;
// } else {
// LOG(`Parsed '${parsed.base}'`);
// }
// Check that the textures that this model uses can be found
Object.values(faceData).forEach((texture) => {
const textureBaseName = texture.split('/')[1] + '.png';
const textureAbsDir = PathUtil.join(BLOCKS_DIR, textureBaseName);
// // Check that the textures that this model uses can be found
// Object.values(faceData).forEach((texture) => {
// const textureBaseName = texture.split('/')[1] + '.png';
// const textureAbsDir = PathUtil.join(BLOCKS_DIR, textureBaseName);
if (fs.existsSync(textureAbsDir)) {
LOG(`Found '${textureAbsDir}'`);
} else {
log('Warning', `'${parsed.base}' uses texture '${texture}' but the texture file could not be found at '${textureAbsDir}'`);
return;
}
});
// if (fs.existsSync(textureAbsDir)) {
// LOG(`Found '${textureAbsDir}'`);
// } else {
// log('Warning', `'${parsed.base}' uses texture '${texture}' but the texture file could not be found at '${textureAbsDir}'`);
// return;
// }
// });
// Update usedTextures and usedModels
Object.values(faceData).forEach((texture) => {
usedTextures.add(texture);
});
usedModels.push({
name: parsed.name,
faces: faceData,
});
});
// // Update usedTextures and usedModels
// Object.values(faceData).forEach((texture) => {
// usedTextures.add(texture);
// });
// usedModels.push({
// name: parsed.name,
// faces: faceData,
// });
// });
LOG('All Textures', usedTextures);
LOG('All Models', usedModels);
log('Info', `Found ${usedModels.length} models to use`);
// LOG('All Textures', usedTextures);
// LOG('All Models', usedModels);
// log('Info', `Found ${usedModels.length} models to use`);
// Prompt user for an atlas name
const { atlasName } = await prompt.get({
properties: {
atlasName: {
pattern: /^[a-zA-Z\-]+$/,
description: 'What do you want to call this texture atlas?',
message: 'Name must only be letters or dash',
required: true,
},
},
});
// // Prompt user for an atlas name
// const { atlasName } = await prompt.get({
// properties: {
// atlasName: {
// pattern: /^[a-zA-Z\-]+$/,
// description: 'What do you want to call this texture atlas?',
// message: 'Name must only be letters or dash',
// required: true,
// },
// },
// });
// Create atlas texture file
const textureDetails: { [texture: string]: { atlasColumn: number, atlasRow: number, colour: RGBA, std: number } } = {};
const atlasSize = Math.ceil(Math.sqrt(usedTextures.size));
{
const atlasWidth = atlasSize * 16;
// // Create atlas texture file
// const textureDetails: { [texture: string]: { atlasColumn: number, atlasRow: number, colour: RGBA, std: number } } = {};
// const atlasSize = Math.ceil(Math.sqrt(usedTextures.size));
// {
// const atlasWidth = atlasSize * 16;
let offsetX = 0;
let offsetY = 0;
const outputImage = images(atlasWidth * 3, atlasWidth * 3);
// let offsetX = 0;
// let offsetY = 0;
// const outputImage = images(atlasWidth * 3, atlasWidth * 3);
usedTextures.forEach((texture) => {
const shortName = texture.split('/')[1]; // Eww
const absolutePath = path.join(BLOCKS_DIR, shortName + '.png');
const fileData = fs.readFileSync(absolutePath);
const pngData = PNG.sync.read(fileData);
const image = images(absolutePath);
// usedTextures.forEach((texture) => {
// const shortName = texture.split('/')[1]; // Eww
// const absolutePath = path.join(BLOCKS_DIR, shortName + '.png');
// const fileData = fs.readFileSync(absolutePath);
// //const pngData = PNG.sync.read(fileData);
// const image = images(absolutePath);
for (let x = 0; x < 3; ++x) {
for (let y = 0; y < 3; ++y) {
outputImage.draw(image, 16 * (3 * offsetX + x), 16 * (3 * offsetY + y));
}
}
// for (let x = 0; x < 3; ++x) {
// for (let y = 0; y < 3; ++y) {
// outputImage.draw(image, 16 * (3 * offsetX + x), 16 * (3 * offsetY + y));
// }
// }
const average = getAverageColour(pngData);
textureDetails[texture] = {
/*
texcoord: new UV(
16 * (3 * offsetX + 1) / (atlasWidth * 3),
16 * (3 * offsetY + 1) / (atlasWidth * 3),
),
*/
atlasColumn: offsetX,
atlasRow: offsetY,
colour: average,
std: getStandardDeviation(pngData, average),
};
// // TODO Unimplemented
// /*
// const average = getAverageColour(pngData);
// textureDetails[texture] = {
// atlasColumn: offsetX,
// atlasRow: offsetY,
// colour: average,
// std: getStandardDeviation(pngData, average),
// };
// */
++offsetX;
if (offsetX >= atlasSize) {
++offsetY;
offsetX = 0;
}
});
// ++offsetX;
// if (offsetX >= atlasSize) {
// ++offsetY;
// offsetX = 0;
// }
// });
const atlasDir = PathUtil.join(AppPaths.Get.atlases, `./${atlasName}.png`);
outputImage.save(atlasDir);
}
// const atlasDir = PathUtil.join(AppPaths.Get.atlases, `./${atlasName}.png`);
// outputImage.save(atlasDir);
// }
const modelDetails = new Array<{ name: string, faces: TFaceData<string>, colour: RGBA }>();
{
usedModels.forEach((model) => {
const faceColours = Object.values(model.faces)
.map((face) => textureDetails[face]!.colour);
// const modelDetails = new Array<{ name: string, faces: TFaceData<string>, colour: RGBA }>();
// {
// usedModels.forEach((model) => {
// const faceColours = Object.values(model.faces)
// .map((face) => textureDetails[face]!.colour);
modelDetails.push({
name: AppUtil.Text.namespaceBlock(model.name),
faces: model.faces,
colour: RGBAUtil.average(...faceColours),
});
});
}
// modelDetails.push({
// name: AppUtil.Text.namespaceBlock(model.name),
// faces: model.faces,
// colour: RGBAUtil.average(...faceColours),
// });
// });
// }
const toExport: TAtlasVersion = {
formatVersion: 3,
atlasSize: atlasSize,
blocks: modelDetails,
textures: textureDetails,
supportedBlockNames: modelDetails.map((model) => model.name),
};
// const toExport: TAtlasVersion = {
// formatVersion: 3,
// atlasSize: atlasSize,
// blocks: modelDetails,
// textures: textureDetails,
// supportedBlockNames: modelDetails.map((model) => model.name),
// };
fs.writeFileSync(path.join(AppPaths.Get.atlases, `./${atlasName}.atlas`), JSON.stringify(toExport, null, 4));
}
}();
// fs.writeFileSync(path.join(AppPaths.Get.atlases, `./${atlasName}.atlas`), JSON.stringify(toExport, null, 4));
// }
// }();
console.log('Unimplemented');

View File

@ -1,67 +1,68 @@
import fs from 'fs';
import path from 'path';
import prompt from 'prompt';
// import fs from 'fs';
// import path from 'path';
// import prompt from 'prompt';
import { Palette } from '../src/palette';
import { AppPaths, PathUtil } from '../src/util/path_util';
import { log } from './logging';
// import { Palette } from '../src/palette';
// import { AppPaths, PathUtil } from '../src/util/path_util';
// import { log } from './logging';
const PALETTE_NAME_REGEX = /^[a-zA-Z\-]+$/;
// const PALETTE_NAME_REGEX = /^[a-zA-Z\-]+$/;
void async function main() {
AppPaths.Get.setBaseDir(PathUtil.join(__dirname, '../..'));
// void async function main() {
// AppPaths.Get.setBaseDir(PathUtil.join(__dirname, '../..'));
log('Info', 'Creating a new palette...');
// log('Info', 'Creating a new palette...');
const paletteBlocksDir = path.join(AppPaths.Get.tools, './new-palette-blocks.txt');
if (!fs.existsSync(paletteBlocksDir)) {
log('Failure', 'Could not find /tools/new-palette-blocks.txt');
return;
}
log('Success', 'Found list of blocks to use in /tools/new-palette-blocks.txt');
// const paletteBlocksDir = path.join(AppPaths.Get.tools, './new-palette-blocks.txt');
// if (!fs.existsSync(paletteBlocksDir)) {
// log('Failure', 'Could not find /tools/new-palette-blocks.txt');
// return;
// }
// log('Success', 'Found list of blocks to use in /tools/new-palette-blocks.txt');
let blocksToUse: string[] = fs.readFileSync(paletteBlocksDir, 'utf8').replace(/\r/g, '').split('\n');
blocksToUse = blocksToUse.filter((block) => {
return block.length !== 0;
});
if (blocksToUse.length === 0) {
log('Failure', 'No blocks listed for palette');
log('Info', 'List the blocks you want from /tools/all-supported-blocks.txt ');
return;
}
log('Info', `Found ${blocksToUse.length} blocks to use`);
// let blocksToUse: string[] = fs.readFileSync(paletteBlocksDir, 'utf8').replace(/\r/g, '').split('\n');
// blocksToUse = blocksToUse.filter((block) => {
// return block.length !== 0;
// });
// if (blocksToUse.length === 0) {
// log('Failure', 'No blocks listed for palette');
// log('Info', 'List the blocks you want from /tools/all-supported-blocks.txt ');
// return;
// }
// log('Info', `Found ${blocksToUse.length} blocks to use`);
const schema: prompt.Schema = {
properties: {
paletteName: {
pattern: PALETTE_NAME_REGEX,
description: 'What do you want to call this block palette? (e.g. my-block-palette)',
message: 'Must be only letters or dash',
required: true,
},
},
};
// const schema: prompt.Schema = {
// properties: {
// paletteName: {
// pattern: PALETTE_NAME_REGEX,
// description: 'What do you want to call this block palette? (e.g. my-block-palette)',
// message: 'Must be only letters or dash',
// required: true,
// },
// },
// };
const promptUser = await prompt.get(schema);
// const promptUser = await prompt.get(schema);
log('Info', 'Creating palette...');
const palette = Palette.create();
if (palette === undefined) {
log('Failure', 'Invalid palette name');
return;
}
// log('Info', 'Creating palette...');
// const palette = Palette.create();
// if (palette === undefined) {
// log('Failure', 'Invalid palette name');
// return;
// }
log('Info', 'Adding blocks to palette...');
for (const blockNames of blocksToUse) {
palette.add(blockNames);
}
// log('Info', 'Adding blocks to palette...');
// for (const blockNames of blocksToUse) {
// palette.add(blockNames);
// }
log('Info', 'Saving palette...');
const success = palette.save(promptUser.paletteName as string);
// log('Info', 'Saving palette...');
// const success = palette.save(promptUser.paletteName as string);
if (success) {
log('Success', 'Palette saved.');
} else {
log('Failure', 'Could not save palette.');
}
}();
// if (success) {
// log('Success', 'Palette saved.');
// } else {
// log('Failure', 'Could not save palette.');
// }
// }();
console.log('Unimplemented');

View File

@ -1,6 +1,4 @@
import fs from 'fs';
import path from 'path';
import { PNG } from 'pngjs';
import prompt from 'prompt';
import { RGBA } from '../src/colour';
@ -13,26 +11,10 @@ export const ASSERT = (condition: boolean, onFailMessage: string) => {
}
};
export const ASSERT_EXISTS = (path: fs.PathLike) => {
clog(
fs.existsSync(path),
`Found '${path}'`,
`Could not find '${path}'`,
);
};
export function isDirSetup(absolutePath: string) {
if (fs.existsSync(absolutePath)) {
if (fs.readdirSync(absolutePath).length > 0) {
return true;
}
} else {
fs.mkdirSync(absolutePath);
}
return false;
}
type PNG = {};
export function getAverageColour(image: PNG): RGBA {
/*
let r = 0;
let g = 0;
let b = 0;
@ -57,9 +39,14 @@ export function getAverageColour(image: PNG): RGBA {
b: b / weight,
a: a / numPixels,
};
*/
return { r: 0, g: 0, b: 0, a: 0 };
}
export function getStandardDeviation(image: PNG, average: RGBA): number {
return 0; // TODO Unimplemented
/*
let squaredDist = 0.0;
let weight = 0.0;
for (let x = 0; x < image.width; ++x) {
@ -75,6 +62,7 @@ export function getStandardDeviation(image: PNG, average: RGBA): number {
}
}
return Math.sqrt(squaredDist / weight);
*/
}
export async function getPermission() {

View File

@ -1,12 +1,10 @@
import { LOG_MAJOR, Logger } from '../src/util/log_util';
import { LOG_MAJOR } from '../src/util/log_util';
import { AppPaths, PathUtil } from '../src/util/path_util';
import { runHeadless } from './headless';
import { headlessConfig } from './headless-config';
void async function main() {
AppPaths.Get.setBaseDir(PathUtil.join(__dirname, '../..'));
Logger.Get.enableLogToFile();
Logger.Get.initLogFile('headless');
runHeadless(headlessConfig);

View File

@ -6,7 +6,7 @@
"incremental": true, /* Enable incremental compilation */
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
//"resolveJsonModule": true,
// "resolveJsonModule": true,
// "lib": [], /* Specify library files to be included in the compilation. */
"allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */

33
webpack.common.js Normal file
View File

@ -0,0 +1,33 @@
const path = require('path');
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
module.exports = {
entry: './src/client.ts',
plugins: [
new NodePolyfillPlugin(),
],
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.vs|fs$/,
use: 'raw-loader',
},
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules|main\.ts/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, './webpack'),
},
};

14
webpack.dev.js Normal file
View File

@ -0,0 +1,14 @@
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const path = require('path');
module.exports = merge(common, {
mode: 'development',
devtool: 'eval-source-map',
devServer: {
static: {
directory: path.join(__dirname, './webpack'),
},
hot: true,
},
});

9
webpack.prod.js Normal file
View File

@ -0,0 +1,9 @@
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production',
performance: {
hints: false,
},
});

View File

@ -2,8 +2,8 @@
<html>
<head>
<meta charset="utf8">
<link rel="stylesheet" href="./styles.css">
<meta charset="utf8">
<title>ObjToSchematic Web</title>
</head>
<body>
@ -18,11 +18,7 @@
</div>
</div>
</div>
<script type="module" src="bundle.js"></script>
</body>
<script>
require("./dist/src/client.js");
</script>
</html>