forked from LeenkxTeam/LNXSDK
Update
This commit is contained in:
@ -7,15 +7,16 @@ import * as chokidar from 'chokidar';
|
||||
import * as crypto from 'crypto';
|
||||
import * as Throttle from 'promise-parallel-throttle';
|
||||
import { Options } from './Options';
|
||||
import { AssetMatcher, AssetMatcherOptions } from './Project';
|
||||
|
||||
export class AssetConverter {
|
||||
options: Options;
|
||||
exporter: KhaExporter;
|
||||
platform: string;
|
||||
assetMatchers: Array<{ match: string, options: any }>;
|
||||
assetMatchers: Array<AssetMatcher>;
|
||||
watcher: fs.FSWatcher;
|
||||
|
||||
constructor(exporter: KhaExporter, options: Options, assetMatchers: Array<{ match: string, options: any }>) {
|
||||
constructor(exporter: KhaExporter, options: Options, assetMatchers: Array<AssetMatcher>) {
|
||||
this.exporter = exporter;
|
||||
this.options = options;
|
||||
this.platform = options.target;
|
||||
@ -26,7 +27,7 @@ export class AssetConverter {
|
||||
if (this.watcher) this.watcher.close();
|
||||
}
|
||||
|
||||
static replacePattern(pattern: string, name: string, fileinfo: path.ParsedPath, options: any, from: string) {
|
||||
static replacePattern(pattern: string, name: string, fileinfo: path.ParsedPath, options: AssetMatcherOptions, from: string) {
|
||||
let basePath: string = options.nameBaseDir ? path.join(from, options.nameBaseDir) : from;
|
||||
let dirValue: string = path.relative(basePath, fileinfo.dir);
|
||||
if (basePath.length > 0 && basePath[basePath.length - 1] === path.sep
|
||||
@ -44,7 +45,7 @@ export class AssetConverter {
|
||||
return pattern.replace(/{name}/g, name).replace(/{ext}/g, fileinfo.ext).replace(dirRegex, dirValue);
|
||||
}
|
||||
|
||||
static createExportInfo(fileinfo: path.ParsedPath, keepextension: boolean, options: any, from: string): {name: string, destination: string} {
|
||||
static createExportInfo(fileinfo: path.ParsedPath, keepextension: boolean, options: AssetMatcherOptions, from: string): {name: string, destination: string} {
|
||||
let nameValue = fileinfo.name;
|
||||
|
||||
let destination = fileinfo.name;
|
||||
@ -77,7 +78,28 @@ export class AssetConverter {
|
||||
return {name: nameValue, destination: destination};
|
||||
}
|
||||
|
||||
watch(watch: boolean, match: string, temp: string, options: any): Promise<{ name: string, from: string, type: string, files: string[], file_sizes: number[], original_width: number, original_height: number, readable: boolean }[]> {
|
||||
canDecodeFormat(ext: string): boolean {
|
||||
// without ffmpeg we need to encode mp3 and ogg files
|
||||
const hasFFmpeg = !!this.options.ffmpeg;
|
||||
const hasFFmpegOgg = this.options.ogg?.includes('ffmpeg') ?? false;
|
||||
const hasFFmpegMp3 = this.options.mp3?.includes('ffmpeg') ?? false;
|
||||
const hasFFmpegAac = this.options.aac?.includes('ffmpeg') ?? false;
|
||||
switch (ext) {
|
||||
case '.wav':
|
||||
return true;
|
||||
case '.ogg':
|
||||
return hasFFmpeg || (hasFFmpegOgg && (hasFFmpegMp3 || hasFFmpegAac));
|
||||
case '.mp3':
|
||||
// lame can decode mp3, so we only need ogg ffmpeg encoder
|
||||
return hasFFmpeg || (hasFFmpegOgg && !!this.options.mp3);
|
||||
case '.flac':
|
||||
return hasFFmpeg;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
watch(watch: boolean, match: string, temp: string, options: AssetMatcherOptions): Promise<{ name: string, from: string, type: string, files: string[], file_sizes: number[], original_width: number, original_height: number, readable: boolean }[]> {
|
||||
return new Promise<{ name: string, from: string, type: string, files: string[], file_sizes: number[], original_width: number, original_height: number, readable: boolean }[]>((resolve, reject) => {
|
||||
let ready = false;
|
||||
let files: string[] = [];
|
||||
@ -88,11 +110,15 @@ export class AssetConverter {
|
||||
let outPath = fileinfo.name;
|
||||
// with subfolders
|
||||
if (options.destination) {
|
||||
const from = path.resolve(options.baseDir, '..');
|
||||
// remove trailing slash
|
||||
const nameBaseDir = options.nameBaseDir.replace(/\/$/, '');
|
||||
const lastIndex = options.baseDir.lastIndexOf(nameBaseDir)
|
||||
const from = path.resolve(options.baseDir.substring(0, lastIndex));
|
||||
outPath = AssetConverter.replacePattern(options.destination, fileinfo.name, fileinfo, options, from);
|
||||
}
|
||||
log.info('Reexporting ' + outPath + fileinfo.ext);
|
||||
switch (fileinfo.ext) {
|
||||
const ext = fileinfo.ext.toLowerCase();
|
||||
log.info('Reexporting ' + outPath + ext);
|
||||
switch (ext) {
|
||||
case '.png':
|
||||
case '.jpg':
|
||||
case '.jpeg':
|
||||
@ -104,6 +130,9 @@ export class AssetConverter {
|
||||
case '.mp3':
|
||||
case '.flac':
|
||||
case '.wav': {
|
||||
if (!this.canDecodeFormat(ext)) {
|
||||
log.error(`Error: ${fileinfo.base} should be in wav format, or use \`--ffmpeg path/to/ffmpeg\` option to convert ogg/mp3/flac files`);
|
||||
}
|
||||
await this.exporter.copySound(this.platform, file, outPath, {});
|
||||
break;
|
||||
}
|
||||
@ -122,10 +151,10 @@ export class AssetConverter {
|
||||
break;
|
||||
|
||||
default:
|
||||
await this.exporter.copyBlob(this.platform, file, outPath + fileinfo.ext, {});
|
||||
await this.exporter.copyBlob(this.platform, file, outPath + ext, {});
|
||||
}
|
||||
for (let callback of Callbacks.postAssetReexporting) {
|
||||
callback(outPath + fileinfo.ext);
|
||||
callback(outPath + ext);
|
||||
}
|
||||
};
|
||||
|
||||
@ -153,9 +182,7 @@ export class AssetConverter {
|
||||
cache = JSON.parse(fs.readFileSync(cachePath, 'utf8'));
|
||||
}
|
||||
|
||||
const self = this;
|
||||
|
||||
async function convertAsset( file: string, index: number ) {
|
||||
const convertAsset = async (file: string, index: number) => {
|
||||
let fileinfo = path.parse(file);
|
||||
log.info('Exporting asset ' + (index + 1) + ' of ' + files.length + ' (' + fileinfo.base + ').');
|
||||
const ext = fileinfo.ext.toLowerCase();
|
||||
@ -164,13 +191,13 @@ export class AssetConverter {
|
||||
case '.jpg':
|
||||
case '.jpeg':
|
||||
case '.hdr': {
|
||||
let exportInfo = AssetConverter.createExportInfo(fileinfo, false, options, self.exporter.options.from);
|
||||
let exportInfo = AssetConverter.createExportInfo(fileinfo, false, options, this.exporter.options.from);
|
||||
let images: { files: string[], sizes: number[] };
|
||||
if (options.noprocessing) {
|
||||
images = await self.exporter.copyBlob(self.platform, file, exportInfo.destination, options);
|
||||
images = await this.exporter.copyBlob(this.platform, file, exportInfo.destination, options);
|
||||
}
|
||||
else {
|
||||
images = await self.exporter.copyImage(self.platform, file, exportInfo.destination, options, cache);
|
||||
images = await this.exporter.copyImage(this.platform, file, exportInfo.destination, options, cache);
|
||||
}
|
||||
if (!options.notinlist) {
|
||||
parsedFiles.push({ name: exportInfo.name, from: file, type: 'image', files: images.files, file_sizes: images.sizes, original_width: options.original_width, original_height: options.original_height, readable: options.readable });
|
||||
@ -181,13 +208,17 @@ export class AssetConverter {
|
||||
case '.mp3':
|
||||
case '.flac':
|
||||
case '.wav': {
|
||||
let exportInfo = AssetConverter.createExportInfo(fileinfo, false, options, self.exporter.options.from);
|
||||
let exportInfo = AssetConverter.createExportInfo(fileinfo, false, options, this.exporter.options.from);
|
||||
let sounds: { files: string[], sizes: number[] };
|
||||
if (options.noprocessing) {
|
||||
sounds = await self.exporter.copyBlob(self.platform, file, exportInfo.destination, options);
|
||||
sounds = await this.exporter.copyBlob(this.platform, file, exportInfo.destination, options);
|
||||
}
|
||||
else {
|
||||
sounds = await self.exporter.copySound(self.platform, file, exportInfo.destination, options);
|
||||
if (!this.canDecodeFormat(ext)) {
|
||||
log.error(`Error: ${fileinfo.base} should be in wav format, or use \`--ffmpeg\` option to convert ogg/mp3/flac files`);
|
||||
process.exit(1);
|
||||
}
|
||||
sounds = await this.exporter.copySound(this.platform, file, exportInfo.destination, options);
|
||||
}
|
||||
if (sounds.files.length === 0) {
|
||||
throw 'Audio file ' + file + ' could not be exported, you have to specify a path to ffmpeg.';
|
||||
@ -198,13 +229,13 @@ export class AssetConverter {
|
||||
break;
|
||||
}
|
||||
case '.ttf': {
|
||||
let exportInfo = AssetConverter.createExportInfo(fileinfo, false, options, self.exporter.options.from);
|
||||
let exportInfo = AssetConverter.createExportInfo(fileinfo, false, options, this.exporter.options.from);
|
||||
let fonts: { files: string[], sizes: number[] };
|
||||
if (options.noprocessing) {
|
||||
fonts = await self.exporter.copyBlob(self.platform, file, exportInfo.destination, options);
|
||||
fonts = await this.exporter.copyBlob(this.platform, file, exportInfo.destination, options);
|
||||
}
|
||||
else {
|
||||
fonts = await self.exporter.copyFont(self.platform, file, exportInfo.destination, options);
|
||||
fonts = await this.exporter.copyFont(this.platform, file, exportInfo.destination, options);
|
||||
}
|
||||
if (!options.notinlist) {
|
||||
parsedFiles.push({ name: exportInfo.name, from: file, type: 'font', files: fonts.files, file_sizes: fonts.sizes, original_width: undefined, original_height: undefined, readable: undefined });
|
||||
@ -216,13 +247,13 @@ export class AssetConverter {
|
||||
case '.mov':
|
||||
case '.wmv':
|
||||
case '.avi': {
|
||||
let exportInfo = AssetConverter.createExportInfo(fileinfo, false, options, self.exporter.options.from);
|
||||
let exportInfo = AssetConverter.createExportInfo(fileinfo, false, options, this.exporter.options.from);
|
||||
let videos: { files: string[], sizes: number[] };
|
||||
if (options.noprocessing) {
|
||||
videos = await self.exporter.copyBlob(self.platform, file, exportInfo.destination, options);
|
||||
videos = await this.exporter.copyBlob(this.platform, file, exportInfo.destination, options);
|
||||
}
|
||||
else {
|
||||
videos = await self.exporter.copyVideo(self.platform, file, exportInfo.destination, options);
|
||||
videos = await this.exporter.copyVideo(this.platform, file, exportInfo.destination, options);
|
||||
}
|
||||
if (videos.files.length === 0) {
|
||||
log.error('Video file ' + file + ' could not be exported, you have to specify a path to ffmpeg.');
|
||||
@ -233,8 +264,8 @@ export class AssetConverter {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
let exportInfo = AssetConverter.createExportInfo(fileinfo, true, options, self.exporter.options.from);
|
||||
let blobs = await self.exporter.copyBlob(self.platform, file, exportInfo.destination, options);
|
||||
let exportInfo = AssetConverter.createExportInfo(fileinfo, true, options, this.exporter.options.from);
|
||||
let blobs = await this.exporter.copyBlob(this.platform, file, exportInfo.destination, options);
|
||||
if (!options.notinlist) {
|
||||
parsedFiles.push({ name: exportInfo.name, from: file, type: 'blob', files: blobs.files, file_sizes: blobs.sizes, original_width: undefined, original_height: undefined, readable: undefined });
|
||||
}
|
||||
|
||||
@ -36,6 +36,9 @@ export function convert(inFilename: string, outFilename: string, encoder: string
|
||||
else if (parts[i] === '{out}') options.push(outFilename.toString());
|
||||
else options.push(parts[i]);
|
||||
}
|
||||
if (fs.existsSync(outFilename.toString())) {
|
||||
fs.unlinkSync(outFilename.toString());
|
||||
}
|
||||
// About stdio ignore: https://stackoverflow.com/a/20792428
|
||||
let process = child_process.spawn(exe, options, {stdio: 'ignore'});
|
||||
process.on('close', (code: number) => {
|
||||
|
||||
@ -5,7 +5,7 @@ import {convert} from '../Converter';
|
||||
import {executeHaxe} from '../Haxe';
|
||||
import {Options} from '../Options';
|
||||
import {exportImage} from '../ImageTool';
|
||||
import {Library} from '../Project';
|
||||
import {AssetMatcherOptions, Library} from '../Project';
|
||||
import {VrApi} from '../VrApi';
|
||||
|
||||
export class Html5Exporter extends KhaExporter {
|
||||
@ -215,7 +215,7 @@ export class Html5Exporter extends KhaExporter {
|
||||
});
|
||||
}*/
|
||||
|
||||
async copySound(platform: string, from: string, to: string, options: any) {
|
||||
async copySound(platform: string, from: string, to: string, options: AssetMatcherOptions) {
|
||||
fs.ensureDirSync(path.join(this.options.to, this.sysdir(), path.dirname(to)));
|
||||
let ogg = await convert(from, path.join(this.options.to, this.sysdir(), to + '.ogg'), this.options.ogg);
|
||||
let ogg_size = (await fs.stat(path.join(this.options.to, this.sysdir(), to + '.ogg'))).size;
|
||||
|
||||
@ -8,9 +8,10 @@ import {GraphicsApi} from '../GraphicsApi';
|
||||
import {Platform} from '../Platform';
|
||||
import {exportImage} from '../ImageTool';
|
||||
import {Options} from '../Options';
|
||||
import {Library} from '../Project';
|
||||
import {AssetMatcherOptions, Library} from '../Project';
|
||||
import * as log from '../log';
|
||||
|
||||
export class KincExporter extends KhaExporter {
|
||||
export class KoreExporter extends KhaExporter {
|
||||
slowgc: boolean;
|
||||
|
||||
constructor(options: Options) {
|
||||
@ -20,7 +21,7 @@ export class KincExporter extends KhaExporter {
|
||||
}
|
||||
|
||||
backend(): string {
|
||||
return 'Kinc-hxcpp';
|
||||
return 'Kore-hxcpp';
|
||||
}
|
||||
|
||||
haxeOptions(name: string, targetOptions: any, defines: Array<string>) {
|
||||
@ -92,7 +93,7 @@ export class KincExporter extends KhaExporter {
|
||||
|
||||
}
|
||||
|
||||
async copySound(platform: string, from: string, to: string, options: any) {
|
||||
async copySound(platform: string, from: string, to: string, options: AssetMatcherOptions) {
|
||||
if (options.quality < 1) {
|
||||
fs.ensureDirSync(path.join(this.options.to, this.sysdir(), path.dirname(to)));
|
||||
await convert(from, path.join(this.options.to, this.sysdir(), to + '.ogg'), this.options.ogg);
|
||||
@ -103,7 +104,8 @@ export class KincExporter extends KhaExporter {
|
||||
fs.copySync(from.toString(), path.join(this.options.to, this.sysdir(), to + '.wav'), { overwrite: true });
|
||||
}
|
||||
else {
|
||||
throw 'Can not convert ' + from + ' to wav format.';
|
||||
log.error('Can not convert ' + from + ' to wav format.\nSet `{quality: 0.99}` in `project.addAssets` if you want to convert your files to `ogg`.');
|
||||
process.exit(1);
|
||||
}
|
||||
return { files: [to + '.wav'], sizes: [1] };
|
||||
}
|
||||
@ -8,16 +8,17 @@ import {GraphicsApi} from '../GraphicsApi';
|
||||
import {Platform} from '../Platform';
|
||||
import {exportImage} from '../ImageTool';
|
||||
import {Options} from '../Options';
|
||||
import {Library} from '../Project';
|
||||
import {AssetMatcher, AssetMatcherOptions, Library} from '../Project';
|
||||
import * as log from '../log';
|
||||
|
||||
export class KincHLExporter extends KhaExporter {
|
||||
export class KoreHLExporter extends KhaExporter {
|
||||
constructor(options: Options) {
|
||||
super(options);
|
||||
// Files.removeDirectory(this.directory.resolve(Paths.get(this.sysdir() + "-build", "Sources")));
|
||||
}
|
||||
|
||||
backend(): string {
|
||||
return 'Kinc-HL';
|
||||
return 'Kore-HL';
|
||||
}
|
||||
|
||||
haxeOptions(name: string, targetOptions: any, defines: Array<string>) {
|
||||
@ -81,14 +82,20 @@ export class KincHLExporter extends KhaExporter {
|
||||
|
||||
}
|
||||
|
||||
async copySound(platform: string, from: string, to: string, options: any) {
|
||||
async copySound(platform: string, from: string, to: string, options: AssetMatcherOptions) {
|
||||
if (options.quality < 1) {
|
||||
fs.ensureDirSync(path.join(this.options.to, this.sysdir(), path.dirname(to)));
|
||||
let ogg = await convert(from, path.join(this.options.to, this.sysdir(), to + '.ogg'), this.options.ogg);
|
||||
return { files: [to + '.ogg'], sizes: [1] };
|
||||
}
|
||||
else {
|
||||
fs.copySync(from.toString(), path.join(this.options.to, this.sysdir(), to + '.wav'), { overwrite: true });
|
||||
if (from.endsWith('.wav')) {
|
||||
fs.copySync(from.toString(), path.join(this.options.to, this.sysdir(), to + '.wav'), { overwrite: true });
|
||||
}
|
||||
else {
|
||||
log.error('Can not convert ' + from + ' to wav format.\nSet `{quality: 0.99}` in `project.addAssets` if you want to convert your files to `ogg`.');
|
||||
process.exit(1);
|
||||
}
|
||||
return { files: [to + '.wav'], sizes: [1] };
|
||||
}
|
||||
}
|
||||
@ -7,7 +7,8 @@ import {executeHaxe} from '../Haxe';
|
||||
import {GraphicsApi} from '../GraphicsApi';
|
||||
import {Options} from '../Options';
|
||||
import {exportImage} from '../ImageTool';
|
||||
import {Library} from '../Project';
|
||||
import {AssetMatcherOptions, Library} from '../Project';
|
||||
import * as log from '../log';
|
||||
|
||||
export class KromExporter extends KhaExporter {
|
||||
width: number;
|
||||
@ -72,14 +73,20 @@ export class KromExporter extends KhaExporter {
|
||||
fs.ensureDirSync(path.join(this.options.to, this.sysdir()));
|
||||
}
|
||||
|
||||
async copySound(platform: string, from: string, to: string, options: any) {
|
||||
async copySound(platform: string, from: string, to: string, options: AssetMatcherOptions) {
|
||||
if (options.quality < 1) {
|
||||
fs.ensureDirSync(path.join(this.options.to, this.sysdir(), path.dirname(to)));
|
||||
let ogg = await convert(from, path.join(this.options.to, this.sysdir(), to + '.ogg'), this.options.ogg);
|
||||
return { files: [to + '.ogg'], sizes: [1] };
|
||||
}
|
||||
else {
|
||||
fs.copySync(from.toString(), path.join(this.options.to, this.sysdir(), to + '.wav'), { overwrite: true });
|
||||
if (from.endsWith('.wav')) {
|
||||
fs.copySync(from.toString(), path.join(this.options.to, this.sysdir(), to + '.wav'), { overwrite: true });
|
||||
}
|
||||
else {
|
||||
log.error('Can not convert ' + from + ' to wav format.\nSet `{quality: 0.99}` in `project.addAssets` if you want to convert your files to `ogg`.');
|
||||
process.exit(1);
|
||||
}
|
||||
return { files: [to + '.wav'], sizes: [1] };
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +71,9 @@ export class HaxeCompiler {
|
||||
this.scheduleCompile();
|
||||
});
|
||||
this.startCompilationServer();
|
||||
this.triggerCompilationServer();
|
||||
setTimeout(() => {
|
||||
this.triggerCompilationServer();
|
||||
}, 50);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
@ -196,9 +198,11 @@ export class HaxeCompiler {
|
||||
process.stdout.write('\x1Bc');
|
||||
log.info('Haxe compile end.');
|
||||
if (this.isLiveReload) {
|
||||
this.wsClients.forEach(client => {
|
||||
client.send(JSON.stringify({}));
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.wsClients.forEach(client => {
|
||||
client.send(JSON.stringify({}));
|
||||
});
|
||||
}, 200);
|
||||
}
|
||||
for (let callback of Callbacks.postHaxeRecompilation) {
|
||||
callback();
|
||||
@ -238,13 +242,4 @@ export class HaxeCompiler {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private static spinRename(from: string, to: string): void {
|
||||
for (; ; ) {
|
||||
if (fs.existsSync(from)) {
|
||||
fs.renameSync(from, to);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ function hxml(projectdir: string, options: any) {
|
||||
if (lines.indexOf(line) === -1) {
|
||||
lines.push(line);
|
||||
return line;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
@ -122,12 +122,13 @@ function hxml(projectdir: string, options: any) {
|
||||
data += unique('-cp ' + path.relative(projectdir, path.resolve(options.from, options.sources[i])) + '\n'); // from.resolve('build').relativize(from.resolve(this.sources[i])).toString());
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < options.libraries.length; ++i) {
|
||||
if (path.isAbsolute(options.libraries[i].libpath)) {
|
||||
data += unique('-cp ' + options.libraries[i].libpath + '\n');
|
||||
for (const lib of options.libraries) {
|
||||
if (lib.classPathIsAdded) continue
|
||||
if (path.isAbsolute(lib.libpath)) {
|
||||
data += unique('-cp ' + lib.libpath + '\n');
|
||||
}
|
||||
else {
|
||||
data += unique('-cp ' + path.relative(projectdir, path.resolve(options.from, options.libraries[i].libpath)) + '\n'); // from.resolve('build').relativize(from.resolve(this.sources[i])).toString());
|
||||
data += unique('-cp ' + path.relative(projectdir, path.resolve(options.from, lib.libpath)) + '\n'); // from.resolve('build').relativize(from.resolve(this.sources[i])).toString());
|
||||
}
|
||||
}
|
||||
for (let d in options.defines) {
|
||||
@ -170,7 +171,7 @@ function hxml(projectdir: string, options: any) {
|
||||
|
||||
if (!options.parameters.some((param: string) => param.includes('-main '))) {
|
||||
const entrypoint = options ? options.main ? options.main : 'Main' : 'Main';
|
||||
data += unique('-main ' + entrypoint + '\n');
|
||||
data += unique('-main ' + entrypoint + '\n');
|
||||
}
|
||||
|
||||
fs.outputFileSync(path.join(projectdir, 'project-' + options.system + '.hxml'), data);
|
||||
|
||||
@ -34,7 +34,7 @@ function run(exe: string, from: string, to: string, width: number, height: numbe
|
||||
function findIcon(icon: string, from: string, options: any) {
|
||||
if (icon && fs.existsSync(path.join(from, icon))) return path.join(from, icon);
|
||||
if (fs.existsSync(path.join(from, 'icon.png'))) return path.join(from, 'icon.png');
|
||||
else return path.join(options.kha, 'Kinc', 'Tools', exec.sysdir(), 'icon.png');
|
||||
else return path.join(options.kha, 'Kore', 'Tools', exec.sysdir(), 'icon.png');
|
||||
}
|
||||
|
||||
export function exportIco(icon: string, to: string, from: string, options: any) {
|
||||
|
||||
@ -7,6 +7,11 @@ import {loadProject} from './ProjectFile';
|
||||
export class Library {
|
||||
libpath: string;
|
||||
libroot: string;
|
||||
/**
|
||||
* If haxelib `classPath` is specified,
|
||||
* we don't add `libpath` as `-cp` to `hxml`.
|
||||
*/
|
||||
classPathIsAdded? = false;
|
||||
}
|
||||
|
||||
export class Target {
|
||||
@ -29,6 +34,26 @@ function contains(main: string, sub: string) {
|
||||
return sub.indexOf(main) === 0 && sub.slice(main.length)[0] === path.sep;
|
||||
}
|
||||
|
||||
export type AssetMatcherOptions = {
|
||||
name?: string;
|
||||
nameBaseDir?: string;
|
||||
baseDir?: string;
|
||||
namePathSeparator?: string;
|
||||
destination?: string;
|
||||
destinationCallback?: (destination: string) => string;
|
||||
|
||||
quality?: number;
|
||||
noprocessing?: boolean;
|
||||
notinlist?: boolean;
|
||||
md5sum?: string;
|
||||
|
||||
original_height?: number;
|
||||
original_width?: number;
|
||||
readable?: boolean;
|
||||
}
|
||||
|
||||
export type AssetMatcher = { match: string, options: AssetMatcherOptions }
|
||||
|
||||
export class Project {
|
||||
static platform: string;
|
||||
static scriptdir: string;
|
||||
@ -46,7 +71,7 @@ export class Project {
|
||||
localLibraryPath: string;
|
||||
windowOptions: any;
|
||||
targetOptions: any;
|
||||
assetMatchers: { match: string, options: any }[];
|
||||
assetMatchers: AssetMatcher[];
|
||||
shaderMatchers: { match: string, options: any }[];
|
||||
customTargets: Map<string, Target>;
|
||||
stackSize: number;
|
||||
@ -95,7 +120,7 @@ export class Project {
|
||||
if (!path.isAbsolute(projectDir)) {
|
||||
projectDir = path.join(this.scriptdir, projectDir);
|
||||
}
|
||||
if (!fs.existsSync(path.join(projectDir, 'khafile.js')) && (fs.existsSync(path.join(projectDir, 'kincfile.js')) || fs.existsSync(path.join(projectDir, 'korefile.js')) || fs.existsSync(path.join(projectDir, 'kfile.js')))) {
|
||||
if (!fs.existsSync(path.join(projectDir, 'khafile.js')) && (fs.existsSync(path.join(projectDir, 'kfile.js')) || fs.existsSync(path.join(projectDir, 'korefile.js')) || fs.existsSync(path.join(projectDir, 'kincfile.js')))) {
|
||||
this.libraries.push({
|
||||
libpath: projectDir,
|
||||
libroot: projectDir
|
||||
@ -151,7 +176,7 @@ export class Project {
|
||||
* Asset types are infered from the file suffix.
|
||||
* Glob syntax is very simple, the most important patterns are * for anything and ** for anything across directories.
|
||||
*/
|
||||
addAssets(match: string, options: any) {
|
||||
addAssets(match: string, options: AssetMatcherOptions) {
|
||||
if (!options) options = {};
|
||||
|
||||
if (!path.isAbsolute(match)) {
|
||||
@ -217,15 +242,15 @@ export class Project {
|
||||
|
||||
addLibrary(library: string): string {
|
||||
this.addDefine(library);
|
||||
let self = this;
|
||||
function findLibraryDirectory(name: string) {
|
||||
|
||||
const findLibraryDirectory = (name: string) => {
|
||||
if (path.isAbsolute(name)) {
|
||||
return { libpath: name, libroot: name };
|
||||
}
|
||||
|
||||
// Tries to load the default library from inside the kha project.
|
||||
// e.g. 'Libraries/wyngine'
|
||||
let libpath = path.join(self.scriptdir, self.localLibraryPath, name);
|
||||
let libpath = path.join(this.scriptdir, this.localLibraryPath, name);
|
||||
if (fs.existsSync(libpath) && fs.statSync(libpath).isDirectory()) {
|
||||
let dir = path.resolve(libpath);
|
||||
return { libpath: dir, libroot: dir };
|
||||
@ -275,17 +300,18 @@ export class Project {
|
||||
if (elem.libroot === libInfo.libroot)
|
||||
return '';
|
||||
}
|
||||
this.libraries.push({
|
||||
const lib:Library = {
|
||||
libpath: dir,
|
||||
libroot: libInfo.libroot
|
||||
});
|
||||
}
|
||||
this.libraries.push(lib);
|
||||
// If this is a haxelib library, there must be a haxelib.json
|
||||
if (fs.existsSync(path.join(dir, 'haxelib.json'))) {
|
||||
let options = JSON.parse(fs.readFileSync(path.join(dir, 'haxelib.json'), 'utf8'));
|
||||
// If there is a classPath value, add that directory to be loaded.
|
||||
// Otherwise, just load the current path.
|
||||
if (options.classPath) {
|
||||
// TODO find an example haxelib that has a classPath value
|
||||
lib.classPathIsAdded = true
|
||||
this.sources.push(path.join(dir, options.classPath));
|
||||
}
|
||||
else {
|
||||
|
||||
@ -223,14 +223,13 @@ export class ShaderCompiler {
|
||||
ready = true;
|
||||
let compiledShaders: CompiledShader[] = [];
|
||||
|
||||
const self = this;
|
||||
async function compile(shader: any, index: number) {
|
||||
const compile = async (shader: any, index: number) => {
|
||||
let parsed = path.parse(shader);
|
||||
if (self.isSupported(shader)) {
|
||||
if (this.isSupported(shader)) {
|
||||
log.info('Compiling shader ' + (index + 1) + ' of ' + shaders.length + ' (' + parsed.base + ').');
|
||||
let compiledShader: CompiledShader = null;
|
||||
try {
|
||||
compiledShader = await self.compileShader(shader, options, recompileAll);
|
||||
compiledShader = await this.compileShader(shader, options, recompileAll);
|
||||
}
|
||||
catch (error) {
|
||||
log.error('Compiling shader ' + (index + 1) + ' of ' + shaders.length + ' (' + parsed.base + ') failed:');
|
||||
@ -249,9 +248,9 @@ export class ShaderCompiler {
|
||||
}
|
||||
if (compiledShader.files != null && compiledShader.files.length === 0) {
|
||||
// TODO: Remove when krafix has been recompiled everywhere
|
||||
compiledShader.files.push(parsed.name + '.' + self.type);
|
||||
compiledShader.files.push(parsed.name + '.' + this.type);
|
||||
}
|
||||
compiledShader.name = AssetConverter.createExportInfo(parsed, false, options, self.exporter.options.from).name;
|
||||
compiledShader.name = AssetConverter.createExportInfo(parsed, false, options, this.exporter.options.from).name;
|
||||
compiledShaders.push(compiledShader);
|
||||
}
|
||||
else {
|
||||
|
||||
@ -23,6 +23,8 @@ export function sysdir() {
|
||||
return 'freebsd_x64';
|
||||
}
|
||||
else {
|
||||
return 'macos';
|
||||
if (os.arch() === 'arm64') return 'macos_arm64';
|
||||
else if (os.arch() === 'x64') return 'macos_x64';
|
||||
else throw 'Unsupported CPU';
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import * as path from 'path';
|
||||
import {sysdir} from './exec';
|
||||
|
||||
let korepath = path.join(__dirname, '..', '..', '..', 'Kinc', 'Tools', sysdir());
|
||||
let korepath = path.join(__dirname, '..', '..', '..', 'Kore', 'Tools', sysdir());
|
||||
|
||||
export function init(options: any) {
|
||||
korepath = path.join(options.kha, 'Kinc', 'Tools', sysdir());
|
||||
korepath = path.join(options.kha, 'Kore', 'Tools', sysdir());
|
||||
}
|
||||
|
||||
export function get() {
|
||||
|
||||
@ -21,8 +21,8 @@ import {FlashExporter} from './Exporters/FlashExporter';
|
||||
import {Html5Exporter} from './Exporters/Html5Exporter';
|
||||
import {Html5WorkerExporter} from './Exporters/Html5WorkerExporter';
|
||||
import {JavaExporter} from './Exporters/JavaExporter';
|
||||
import {KincExporter} from './Exporters/KincExporter';
|
||||
import {KincHLExporter} from './Exporters/KincHLExporter';
|
||||
import {KoreExporter} from './Exporters/KoreExporter';
|
||||
import {KoreHLExporter} from './Exporters/KoreHLExporter';
|
||||
import {KromExporter} from './Exporters/KromExporter';
|
||||
import {NodeExporter} from './Exporters/NodeExporter';
|
||||
import {PlayStationMobileExporter} from './Exporters/PlayStationMobileExporter';
|
||||
@ -91,10 +91,10 @@ function createKorefile(name: string, exporter: KhaExporter, options: Options, t
|
||||
let buildpath = path.relative(options.from, path.join(options.to, exporter.sysdir() + '-build')).replace(/\\/g, '/');
|
||||
if (buildpath.startsWith('..')) buildpath = path.resolve(path.join(options.from.toString(), buildpath));
|
||||
|
||||
out += 'await project.addProject(\'' + path.join(options.kha, 'Kinc').replace(/\\/g, '/') + '\');\n';
|
||||
out += 'await project.addProject(\'' + path.join(options.kha, 'Kore').replace(/\\/g, '/') + '\');\n';
|
||||
out += 'await project.addProject(\'' + buildpath.replace(/\\/g, '/') + '\');\n';
|
||||
if (korehl) out += 'await project.addProject(\'' + path.join(options.kha, 'Backends', 'Kinc-HL').replace(/\\/g, '/') + '\');\n';
|
||||
else out += 'await project.addProject(\'' + path.join(options.kha, 'Backends', 'Kinc-hxcpp').replace(/\\/g, '/') + '\');\n';
|
||||
if (korehl) out += 'await project.addProject(\'' + path.join(options.kha, 'Backends', 'Kore-HL').replace(/\\/g, '/') + '\');\n';
|
||||
else out += 'await project.addProject(\'' + path.join(options.kha, 'Backends', 'Kore-hxcpp').replace(/\\/g, '/') + '\');\n';
|
||||
|
||||
for (let lib of libraries) {
|
||||
let libPath: string = lib.libpath.replace(/\\/g, '/');
|
||||
@ -181,12 +181,11 @@ async function exportProjectFiles(name: string, resourceDir: string, options: Op
|
||||
|
||||
if (options.haxe !== '' && kore && !options.noproject) {
|
||||
// If target is a Kore project, generate additional project folders here.
|
||||
// generate the kincfile.js
|
||||
// generate the kfile.js
|
||||
fs.copySync(path.join(__dirname, '..', 'Data', 'hxcpp', 'kfile.js'), path.join(buildDir, 'kfile.js'), { overwrite: true });
|
||||
fs.writeFileSync(path.join(options.to, 'kfile.js'), createKorefile(name, exporter, options, targetOptions, libraries, cdefines, cflags, cppflags, stackSize, version, id, false, icon));
|
||||
|
||||
// Similar to khamake.js -> main.js -> run(...)
|
||||
// We now do kincmake.js -> main.js -> run(...)
|
||||
// This will create additional project folders for the target,
|
||||
// e.g. 'build/pi-build'
|
||||
try {
|
||||
@ -282,7 +281,7 @@ function checkKorePlatform(platform: string) {
|
||||
|| platform === 'ps4'
|
||||
|| platform === 'xboxone'
|
||||
|| platform === 'switch'
|
||||
|| platform === 'xboxscarlett'
|
||||
|| platform === 'xboxseries'
|
||||
|| platform === 'ps5'
|
||||
|| platform === 'freebsd';
|
||||
}
|
||||
@ -372,7 +371,7 @@ async function exportKhaProject(options: Options): Promise<string> {
|
||||
log.error(`Unknown platform: ${target} (baseTarget=$${baseTarget})`);
|
||||
return Promise.reject('');
|
||||
}
|
||||
exporter = new KincHLExporter(options);
|
||||
exporter = new KoreHLExporter(options);
|
||||
}
|
||||
else {
|
||||
kore = true;
|
||||
@ -381,7 +380,7 @@ async function exportKhaProject(options: Options): Promise<string> {
|
||||
log.error(`Unknown platform: ${target} (baseTarget=$${baseTarget})`);
|
||||
return Promise.reject('');
|
||||
}
|
||||
exporter = new KincExporter(options);
|
||||
exporter = new KoreExporter(options);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -696,16 +695,25 @@ export async function run(options: Options, loglog: any): Promise<string> {
|
||||
if (!options.haxe) {
|
||||
let haxepath = path.join(options.kha, 'Tools', sysdir());
|
||||
if (fs.existsSync(haxepath) && fs.statSync(haxepath).isDirectory()) options.haxe = haxepath;
|
||||
else log.error('Haxe not found at ' + haxepath);
|
||||
}
|
||||
else {
|
||||
log.info('Using Haxe from ' + options.haxe);
|
||||
}
|
||||
|
||||
if (!options.krafix) {
|
||||
let krafixpath = path.join(options.kha, 'Kinc', 'Tools', sysdir(), 'krafix' + sys());
|
||||
let krafixpath = path.join(options.kha, 'Kore', 'Tools', sysdir(), 'krafix' + sys());
|
||||
if (fs.existsSync(krafixpath)) options.krafix = krafixpath;
|
||||
else log.error('krafix not found at ' + krafixpath);
|
||||
}
|
||||
else {
|
||||
log.info('Using krafix from ' + options.krafix);
|
||||
}
|
||||
|
||||
if (!options.kraffiti) {
|
||||
const kraffitipath = path.join(options.kha, 'Kinc', 'Tools', sysdir(), 'kraffiti' + sys());
|
||||
const kraffitipath = path.join(options.kha, 'Kore', 'Tools', sysdir(), 'kraffiti' + sys());
|
||||
if (fs.existsSync(kraffitipath)) options.kraffiti = kraffitipath;
|
||||
else log.error('kraffiti not found at ' + kraffitipath);
|
||||
}
|
||||
else {
|
||||
log.info('Using kraffiti from ' + options.kraffiti);
|
||||
@ -722,11 +730,13 @@ export async function run(options: Options, loglog: any): Promise<string> {
|
||||
if (!options.ogg) {
|
||||
let oggpath = path.join(options.kha, 'Tools', sysdir(), 'oggenc' + sys());
|
||||
if (fs.existsSync(oggpath)) options.ogg = oggpath + ' {in} -o {out} --quiet';
|
||||
else log.error('oggenc not found at ' + oggpath);
|
||||
}
|
||||
|
||||
if (!options.mp3) {
|
||||
let lamepath = path.join(options.kha, 'Tools', sysdir(), 'lame' + sys());
|
||||
if (fs.existsSync(lamepath)) options.mp3 = lamepath + ' {in} {out}';
|
||||
else log.error('lame not found at ' + lamepath);
|
||||
}
|
||||
|
||||
// if (!options.kravur) {
|
||||
@ -755,8 +765,7 @@ export async function run(options: Options, loglog: any): Promise<string> {
|
||||
}
|
||||
|
||||
if (options.target === 'emscripten') {
|
||||
console.log();
|
||||
console.log('Please note that the html5 target\n'
|
||||
log.info('\nPlease note that the html5 target\n'
|
||||
+ 'is usually a better choice.\n'
|
||||
+ 'In particular the html5 target usually runs faster\n'
|
||||
+ 'than the emscripten target. That is because\n'
|
||||
@ -765,9 +774,8 @@ export async function run(options: Options, loglog: any): Promise<string> {
|
||||
+ 'all of the optimizations in modern JavaScript\n'
|
||||
+ 'runtimes. The emscripten target on the other hand\n'
|
||||
+ 'has to provide its own garbage collector and many\n'
|
||||
+ 'other performance critical pieces of infrastructure.'
|
||||
+ 'other performance critical pieces of infrastructure.\n'
|
||||
);
|
||||
console.log();
|
||||
}
|
||||
|
||||
let name = '';
|
||||
|
||||
Reference in New Issue
Block a user