first
This commit is contained in:
18
extensions/app/engine/dist/builder/hooks.js
vendored
Normal file
18
extensions/app/engine/dist/builder/hooks.js
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.onAfterBuild = void 0;
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const file_1 = require("./utils/file");
|
||||
const onAfterBuild = async function (options, result) {
|
||||
if (options.platform !== 'web-mobile' && options.platform !== 'web-desktop') {
|
||||
return;
|
||||
}
|
||||
if (!options.md5Cache) {
|
||||
return;
|
||||
}
|
||||
file_1.adaptFileMD5(path_1.default.join(result.dest, 'index.html'));
|
||||
};
|
||||
exports.onAfterBuild = onAfterBuild;
|
||||
8
extensions/app/engine/dist/builder/index.js
vendored
Normal file
8
extensions/app/engine/dist/builder/index.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.configs = void 0;
|
||||
exports.configs = {
|
||||
'*': {
|
||||
hooks: './hooks',
|
||||
}
|
||||
};
|
||||
248
extensions/app/engine/dist/builder/utils/file.js
vendored
Normal file
248
extensions/app/engine/dist/builder/utils/file.js
vendored
Normal file
@@ -0,0 +1,248 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.queryFile = exports.getFilePathRemoveMD5 = exports.getFileNameRemoveMD5 = exports.getFilesBySameNameDiffMD5 = exports.renameFileByMD5 = exports.isFileNameHasMD5 = exports.adaptFilename = exports.adaptFileMD5 = void 0;
|
||||
const fs_1 = __importDefault(require("fs"));
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const md5_1 = __importDefault(require("./md5"));
|
||||
const includeExts = ['.html', '.css', '.js', '.json'];
|
||||
const regExp = new RegExp('(?<=(\'|"|url\\(|URL\\())(?!//)[a-zA-Z0-9_\./-]+\\.(js|css|json|png|apng|jpg|jpeg|gif|svg)(?=(\'|"|\\)))', 'g');
|
||||
/**
|
||||
* 获取文件夹内的文件
|
||||
*/
|
||||
function getFiles(dir) {
|
||||
const result = [];
|
||||
// 判断文件是否存在
|
||||
if (!fs_1.default.existsSync(dir))
|
||||
return result;
|
||||
// 如果不是文件夹则返回
|
||||
if (!fs_1.default.statSync(dir).isDirectory())
|
||||
return result;
|
||||
// 遍历文件夹
|
||||
fs_1.default.readdirSync(dir).forEach(item => {
|
||||
const item_path = path_1.default.join(dir, item);
|
||||
const isDir = fs_1.default.statSync(item_path).isDirectory();
|
||||
if (!isDir)
|
||||
result.push(item_path);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* 以某个文件为起点,对其引用的文件树进行md5
|
||||
* @param filepath 文件路径
|
||||
* @param exclude 排除的文件路径(不带md5,不支持相对路径),排除的文件不会遍历子文件树,默认其本身会进行md5
|
||||
*/
|
||||
function adaptFileMD5(filepath, exclude = []) {
|
||||
// 参数不合法
|
||||
if (!filepath)
|
||||
return false;
|
||||
// 修正文件路径
|
||||
filepath = fs_1.default.existsSync(filepath) ? filepath : queryFile(filepath);
|
||||
if (!filepath)
|
||||
return false;
|
||||
// 排除的文件
|
||||
const fileExt = path_1.default.extname(filepath);
|
||||
const filepathNoMD5 = getFilePathRemoveMD5(filepath);
|
||||
const excludeItem = exclude.find(item => {
|
||||
if (item.path instanceof RegExp)
|
||||
return item.path.test(filepath);
|
||||
else
|
||||
return item.path === filepathNoMD5;
|
||||
});
|
||||
const isExcluded = !!excludeItem || includeExts.indexOf(fileExt) === -1;
|
||||
// 文件扩展名
|
||||
if (!isExcluded) {
|
||||
// 文件目录
|
||||
const fileDir = path_1.default.dirname(filepath);
|
||||
// 文件内容
|
||||
let fileText = fs_1.default.readFileSync(filepath, 'utf-8');
|
||||
// 文件内所有引用的相对路径(排重)
|
||||
const subRelativePaths = Array.from(new Set(fileText.match(regExp)));
|
||||
for (let index = 0; index < subRelativePaths.length; index++) {
|
||||
// 子文件相对路径(读取到的)
|
||||
const subRelativePath = subRelativePaths[index];
|
||||
// 子文件路径(读取到的)
|
||||
const subFilePath = path_1.default.join(fileDir, subRelativePath);
|
||||
// 如果当前引用的文件的路径带有md5戳,并且文件存在,则跳过
|
||||
if (isFileNameHasMD5(subFilePath) && fs_1.default.existsSync(subFilePath))
|
||||
continue;
|
||||
{
|
||||
// 实际的子文件路径(不确定有没有md5)
|
||||
const subFilePathReal = queryFile(subFilePath);
|
||||
// 实际的子文件不存在
|
||||
if (!subFilePathReal) {
|
||||
// console.warn('[跳过] [文件不存在]', filepath, subRelativePath);
|
||||
continue;
|
||||
}
|
||||
// 如果引用的文件路径不带md5,但是实际文件有md5,则
|
||||
if (!isFileNameHasMD5(subFilePath) && isFileNameHasMD5(subFilePathReal)) {
|
||||
// 原始的子文件名
|
||||
const subFileBasename = path_1.default.basename(subRelativePath);
|
||||
// 实际的子文件名(带md5)
|
||||
const subFileBasenameReal = path_1.default.basename(subFilePathReal);
|
||||
// 替换
|
||||
fileText = fileText.replace(new RegExp(subRelativePath, 'g'), subRelativePath.replace(subFileBasename, subFileBasenameReal));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
{
|
||||
// 对它进行md5处理
|
||||
const result = adaptFileMD5(subFilePath, exclude);
|
||||
// 文件不存在
|
||||
if (!result) {
|
||||
// console.warn('[跳过] [文件不存在]', filepath, subRelativePath);
|
||||
continue;
|
||||
}
|
||||
// 实际的子文件路径(已经带上md5了)
|
||||
const subFilepathReal = queryFile(subFilePath);
|
||||
// 原始的子文件名
|
||||
const subFileBasename = path_1.default.basename(subRelativePath);
|
||||
// 实际的子文件名(带md5)
|
||||
const subFileBasenameReal = path_1.default.basename(subFilepathReal);
|
||||
// 替换
|
||||
fileText = fileText.replace(new RegExp(subRelativePath, 'g'), subRelativePath.replace(subFileBasename, subFileBasenameReal));
|
||||
}
|
||||
}
|
||||
// 重新写入文件内容
|
||||
fs_1.default.writeFileSync(filepath, fileText, 'utf-8');
|
||||
}
|
||||
// 将文件md5重命名
|
||||
if (fileExt !== '.html' && (excludeItem === null || excludeItem === void 0 ? void 0 : excludeItem.md5) !== false) {
|
||||
renameFileByMD5(filepath);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
exports.adaptFileMD5 = adaptFileMD5;
|
||||
/**
|
||||
* 替换某个文件里引用的的文件名
|
||||
* @param {string} filepath 被替换的文件路径
|
||||
* @param {string} adaptDir adaptFile所在的文件夹
|
||||
* @param {string} adaptFile 文件名.后缀,不能包含其他东西
|
||||
*/
|
||||
function adaptFilename(filepath, adaptDir, adaptFile) {
|
||||
if (!fs_1.default.existsSync(filepath))
|
||||
return false;
|
||||
const adaptName = adaptFile.split('.')[0];
|
||||
const adaptExtname = path_1.default.extname(adaptFile) || '';
|
||||
let text = fs_1.default.readFileSync(filepath, 'utf-8');
|
||||
const filePaths = getFiles(adaptDir);
|
||||
for (let index = 0; index < filePaths.length; index++) {
|
||||
const filePath = filePaths[index];
|
||||
const basename = path_1.default.basename(filePath);
|
||||
const name = basename.split('.')[0];
|
||||
const extname = path_1.default.extname(basename) || '';
|
||||
if (basename !== adaptFile && name === adaptName && extname === adaptExtname) {
|
||||
const regExp = new RegExp(`(?<=('|"|\/))${name}[\.a-zA-Z0-9]*\\${extname}(?=('|"))`, 'g');
|
||||
text = text.replace(regExp, basename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fs_1.default.writeFileSync(filepath, text, 'utf-8');
|
||||
return true;
|
||||
}
|
||||
exports.adaptFilename = adaptFilename;
|
||||
/**
|
||||
* 判断一个文件是否有md5戳
|
||||
* @param {string} filename
|
||||
*/
|
||||
function isFileNameHasMD5(filename) {
|
||||
filename = path_1.default.basename(filename);
|
||||
return filename !== getFileNameRemoveMD5(filename);
|
||||
}
|
||||
exports.isFileNameHasMD5 = isFileNameHasMD5;
|
||||
/**
|
||||
* md5重命名文件名字
|
||||
* @param {string} filePath
|
||||
* @returns
|
||||
*/
|
||||
function renameFileByMD5(filePath) {
|
||||
const basename = getFileNameRemoveMD5(filePath);
|
||||
const extname = path_1.default.extname(basename);
|
||||
if (!extname)
|
||||
return filePath;
|
||||
const filename = basename.slice(0, -extname.length);
|
||||
if (!filename)
|
||||
return filePath;
|
||||
const dirname = path_1.default.dirname(filePath);
|
||||
const txt = fs_1.default.readFileSync(filePath, 'utf-8');
|
||||
const renamePath = path_1.default.join(dirname, `${filename}.${md5_1.default(txt)}${extname}`);
|
||||
fs_1.default.renameSync(filePath, renamePath);
|
||||
return renamePath;
|
||||
}
|
||||
exports.renameFileByMD5 = renameFileByMD5;
|
||||
/**
|
||||
* 获取相同名字相同后缀, 但md5戳不一样的文件数组
|
||||
* @param {string} dir
|
||||
*/
|
||||
function getFilesBySameNameDiffMD5(dir) {
|
||||
// [ [ {name:'index',ext:'.js',files:['/test/index.js','/test/index.c67d.js']} ]
|
||||
const result = [];
|
||||
const files = getFiles(dir);
|
||||
files.forEach(filepath => {
|
||||
const basename = getFileNameRemoveMD5(filepath);
|
||||
if (!basename)
|
||||
return;
|
||||
const extname = path_1.default.extname(basename);
|
||||
if (!extname)
|
||||
return;
|
||||
const filename = basename.slice(0, -extname.length);
|
||||
if (!filename)
|
||||
return;
|
||||
const res = result.find(data => data.name === filename && data.ext === extname);
|
||||
if (res)
|
||||
return res.files.push(filepath);
|
||||
result.push({
|
||||
name: filename,
|
||||
ext: extname,
|
||||
files: [filepath]
|
||||
});
|
||||
});
|
||||
return result.filter((data) => data.files.length >= 2);
|
||||
}
|
||||
exports.getFilesBySameNameDiffMD5 = getFilesBySameNameDiffMD5;
|
||||
/**
|
||||
* 将文件名中的md5字段去除
|
||||
* @param {string} filename
|
||||
* @returns
|
||||
*/
|
||||
function getFileNameRemoveMD5(filename) {
|
||||
const basename = path_1.default.basename(filename)
|
||||
// a-jqw89a.js => a.js
|
||||
// a-jqw89a.min.js => a.min.js
|
||||
.replace(/-[a-z0-9]+\./, '.');
|
||||
return basename.split('.').filter((str, index, array) => {
|
||||
if (index === 0 || index === array.length - 1)
|
||||
return true;
|
||||
return index == 1 && str === 'min';
|
||||
}).join('.');
|
||||
}
|
||||
exports.getFileNameRemoveMD5 = getFileNameRemoveMD5;
|
||||
/**
|
||||
* 删除文件路径中的md5字段
|
||||
* @param {string} filepath
|
||||
* @returns
|
||||
*/
|
||||
function getFilePathRemoveMD5(filepath) {
|
||||
const dirname = path_1.default.dirname(filepath);
|
||||
return path_1.default.join(dirname, getFileNameRemoveMD5(filepath));
|
||||
}
|
||||
exports.getFilePathRemoveMD5 = getFilePathRemoveMD5;
|
||||
/**
|
||||
* 输入文件路径,可以索引到对应的带有md5的文件路径
|
||||
* @param {string} filepath 文件路径(带后缀)
|
||||
* @returns
|
||||
*/
|
||||
function queryFile(filepath) {
|
||||
// 将文件名中的md5字段去除
|
||||
const filename = getFileNameRemoveMD5(filepath);
|
||||
const fileDir = path_1.default.dirname(filepath);
|
||||
const filesList = getFiles(fileDir);
|
||||
return filesList.find(filepath => {
|
||||
return path_1.default.basename(filepath) === filename;
|
||||
}) || filesList.find(filepath => {
|
||||
return getFileNameRemoveMD5(filepath) === filename;
|
||||
});
|
||||
}
|
||||
exports.queryFile = queryFile;
|
||||
370
extensions/app/engine/dist/builder/utils/md5.js
vendored
Normal file
370
extensions/app/engine/dist/builder/utils/md5.js
vendored
Normal file
@@ -0,0 +1,370 @@
|
||||
"use strict";
|
||||
/*
|
||||
* JavaScript MD5
|
||||
* https://github.com/blueimp/JavaScript-MD5
|
||||
*
|
||||
* Copyright 2011, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
* Based on
|
||||
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
|
||||
* Digest Algorithm, as defined in RFC 1321.
|
||||
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
|
||||
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
||||
* Distributed under the BSD License
|
||||
* See http://pajhome.org.uk/crypt/md5 for more info.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/* global define */
|
||||
/* eslint-disable strict */
|
||||
/**
|
||||
* Add integers, wrapping at 2^32.
|
||||
* This uses 16-bit operations internally to work around bugs in interpreters.
|
||||
*
|
||||
* @param {number} x First integer
|
||||
* @param {number} y Second integer
|
||||
* @returns {number} Sum
|
||||
*/
|
||||
function safeAdd(x, y) {
|
||||
let lsw = (x & 0xffff) + (y & 0xffff);
|
||||
let msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
||||
return (msw << 16) | (lsw & 0xffff);
|
||||
}
|
||||
/**
|
||||
* Bitwise rotate a 32-bit number to the left.
|
||||
*
|
||||
* @param {number} num 32-bit number
|
||||
* @param {number} cnt Rotation count
|
||||
* @returns {number} Rotated number
|
||||
*/
|
||||
function bitRotateLeft(num, cnt) {
|
||||
return (num << cnt) | (num >>> (32 - cnt));
|
||||
}
|
||||
/**
|
||||
* Basic operation the algorithm uses.
|
||||
*
|
||||
* @param {number} q q
|
||||
* @param {number} a a
|
||||
* @param {number} b b
|
||||
* @param {number} x x
|
||||
* @param {number} s s
|
||||
* @param {number} t t
|
||||
* @returns {number} Result
|
||||
*/
|
||||
function md5cmn(q, a, b, x, s, t) {
|
||||
return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);
|
||||
}
|
||||
/**
|
||||
* Basic operation the algorithm uses.
|
||||
*
|
||||
* @param {number} a a
|
||||
* @param {number} b b
|
||||
* @param {number} c c
|
||||
* @param {number} d d
|
||||
* @param {number} x x
|
||||
* @param {number} s s
|
||||
* @param {number} t t
|
||||
* @returns {number} Result
|
||||
*/
|
||||
function md5ff(a, b, c, d, x, s, t) {
|
||||
return md5cmn((b & c) | (~b & d), a, b, x, s, t);
|
||||
}
|
||||
/**
|
||||
* Basic operation the algorithm uses.
|
||||
*
|
||||
* @param {number} a a
|
||||
* @param {number} b b
|
||||
* @param {number} c c
|
||||
* @param {number} d d
|
||||
* @param {number} x x
|
||||
* @param {number} s s
|
||||
* @param {number} t t
|
||||
* @returns {number} Result
|
||||
*/
|
||||
function md5gg(a, b, c, d, x, s, t) {
|
||||
return md5cmn((b & d) | (c & ~d), a, b, x, s, t);
|
||||
}
|
||||
/**
|
||||
* Basic operation the algorithm uses.
|
||||
*
|
||||
* @param {number} a a
|
||||
* @param {number} b b
|
||||
* @param {number} c c
|
||||
* @param {number} d d
|
||||
* @param {number} x x
|
||||
* @param {number} s s
|
||||
* @param {number} t t
|
||||
* @returns {number} Result
|
||||
*/
|
||||
function md5hh(a, b, c, d, x, s, t) {
|
||||
return md5cmn(b ^ c ^ d, a, b, x, s, t);
|
||||
}
|
||||
/**
|
||||
* Basic operation the algorithm uses.
|
||||
*
|
||||
* @param {number} a a
|
||||
* @param {number} b b
|
||||
* @param {number} c c
|
||||
* @param {number} d d
|
||||
* @param {number} x x
|
||||
* @param {number} s s
|
||||
* @param {number} t t
|
||||
* @returns {number} Result
|
||||
*/
|
||||
function md5ii(a, b, c, d, x, s, t) {
|
||||
return md5cmn(c ^ (b | ~d), a, b, x, s, t);
|
||||
}
|
||||
/**
|
||||
* Calculate the MD5 of an array of little-endian words, and a bit length.
|
||||
*
|
||||
* @param {Array} x Array of little-endian words
|
||||
* @param {number} len Bit length
|
||||
* @returns {Array<number>} MD5 Array
|
||||
*/
|
||||
function binlMD5(x, len) {
|
||||
/* append padding */
|
||||
x[len >> 5] |= 0x80 << len % 32;
|
||||
x[(((len + 64) >>> 9) << 4) + 14] = len;
|
||||
let i;
|
||||
let olda;
|
||||
let oldb;
|
||||
let oldc;
|
||||
let oldd;
|
||||
let a = 1732584193;
|
||||
let b = -271733879;
|
||||
let c = -1732584194;
|
||||
let d = 271733878;
|
||||
for (i = 0; i < x.length; i += 16) {
|
||||
olda = a;
|
||||
oldb = b;
|
||||
oldc = c;
|
||||
oldd = d;
|
||||
a = md5ff(a, b, c, d, x[i], 7, -680876936);
|
||||
d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);
|
||||
c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);
|
||||
b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);
|
||||
a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);
|
||||
d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);
|
||||
c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);
|
||||
b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);
|
||||
a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);
|
||||
d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);
|
||||
c = md5ff(c, d, a, b, x[i + 10], 17, -42063);
|
||||
b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);
|
||||
a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);
|
||||
d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);
|
||||
c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);
|
||||
b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);
|
||||
a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);
|
||||
d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);
|
||||
c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);
|
||||
b = md5gg(b, c, d, a, x[i], 20, -373897302);
|
||||
a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);
|
||||
d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);
|
||||
c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);
|
||||
b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);
|
||||
a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);
|
||||
d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);
|
||||
c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);
|
||||
b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);
|
||||
a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);
|
||||
d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);
|
||||
c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);
|
||||
b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);
|
||||
a = md5hh(a, b, c, d, x[i + 5], 4, -378558);
|
||||
d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);
|
||||
c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);
|
||||
b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);
|
||||
a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);
|
||||
d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);
|
||||
c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);
|
||||
b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);
|
||||
a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);
|
||||
d = md5hh(d, a, b, c, x[i], 11, -358537222);
|
||||
c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);
|
||||
b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);
|
||||
a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);
|
||||
d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);
|
||||
c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);
|
||||
b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);
|
||||
a = md5ii(a, b, c, d, x[i], 6, -198630844);
|
||||
d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);
|
||||
c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);
|
||||
b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);
|
||||
a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);
|
||||
d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);
|
||||
c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);
|
||||
b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);
|
||||
a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);
|
||||
d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);
|
||||
c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);
|
||||
b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);
|
||||
a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);
|
||||
d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);
|
||||
c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);
|
||||
b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);
|
||||
a = safeAdd(a, olda);
|
||||
b = safeAdd(b, oldb);
|
||||
c = safeAdd(c, oldc);
|
||||
d = safeAdd(d, oldd);
|
||||
}
|
||||
return [a, b, c, d];
|
||||
}
|
||||
/**
|
||||
* Convert an array of little-endian words to a string
|
||||
*
|
||||
* @param {Array<number>} input MD5 Array
|
||||
* @returns {string} MD5 string
|
||||
*/
|
||||
function binl2rstr(input) {
|
||||
let i;
|
||||
let output = '';
|
||||
let length32 = input.length * 32;
|
||||
for (i = 0; i < length32; i += 8) {
|
||||
output += String.fromCharCode((input[i >> 5] >>> i % 32) & 0xff);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
/**
|
||||
* Convert a raw string to an array of little-endian words
|
||||
* Characters >255 have their high-byte silently ignored.
|
||||
*
|
||||
* @param {string} input Raw input string
|
||||
* @returns {Array<number>} Array of little-endian words
|
||||
*/
|
||||
function rstr2binl(input) {
|
||||
let i;
|
||||
let output = [];
|
||||
output[(input.length >> 2) - 1] = undefined;
|
||||
for (i = 0; i < output.length; i += 1) {
|
||||
output[i] = 0;
|
||||
}
|
||||
let length8 = input.length * 8;
|
||||
for (i = 0; i < length8; i += 8) {
|
||||
output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << i % 32;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
/**
|
||||
* Calculate the MD5 of a raw string
|
||||
*
|
||||
* @param {string} s Input string
|
||||
* @returns {string} Raw MD5 string
|
||||
*/
|
||||
function rstrMD5(s) {
|
||||
return binl2rstr(binlMD5(rstr2binl(s), s.length * 8));
|
||||
}
|
||||
/**
|
||||
* Calculates the HMAC-MD5 of a key and some data (raw strings)
|
||||
*
|
||||
* @param {string} key HMAC key
|
||||
* @param {string} data Raw input string
|
||||
* @returns {string} Raw MD5 string
|
||||
*/
|
||||
function rstrHMACMD5(key, data) {
|
||||
let i;
|
||||
let bkey = rstr2binl(key);
|
||||
let ipad = [];
|
||||
let opad = [];
|
||||
let hash;
|
||||
ipad[15] = opad[15] = undefined;
|
||||
if (bkey.length > 16) {
|
||||
bkey = binlMD5(bkey, key.length * 8);
|
||||
}
|
||||
for (i = 0; i < 16; i += 1) {
|
||||
ipad[i] = bkey[i] ^ 0x36363636;
|
||||
opad[i] = bkey[i] ^ 0x5c5c5c5c;
|
||||
}
|
||||
hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
|
||||
return binl2rstr(binlMD5(opad.concat(hash), 512 + 128));
|
||||
}
|
||||
/**
|
||||
* Convert a raw string to a hex string
|
||||
*
|
||||
* @param {string} input Raw input string
|
||||
* @returns {string} Hex encoded string
|
||||
*/
|
||||
function rstr2hex(input) {
|
||||
let hexTab = '0123456789abcdef';
|
||||
let output = '';
|
||||
let x;
|
||||
let i;
|
||||
for (i = 0; i < input.length; i += 1) {
|
||||
x = input.charCodeAt(i);
|
||||
output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
/**
|
||||
* Encode a string as UTF-8
|
||||
*
|
||||
* @param {string} input Input string
|
||||
* @returns {string} UTF8 string
|
||||
*/
|
||||
function str2rstrUTF8(input) {
|
||||
return unescape(encodeURIComponent(input));
|
||||
}
|
||||
/**
|
||||
* Encodes input string as raw MD5 string
|
||||
*
|
||||
* @param {string} s Input string
|
||||
* @returns {string} Raw MD5 string
|
||||
*/
|
||||
function rawMD5(s) {
|
||||
return rstrMD5(str2rstrUTF8(s));
|
||||
}
|
||||
/**
|
||||
* Encodes input string as Hex encoded string
|
||||
*
|
||||
* @param {string} s Input string
|
||||
* @returns {string} Hex encoded string
|
||||
*/
|
||||
function hexMD5(s) {
|
||||
return rstr2hex(rawMD5(s));
|
||||
}
|
||||
/**
|
||||
* Calculates the raw HMAC-MD5 for the given key and data
|
||||
*
|
||||
* @param {string} k HMAC key
|
||||
* @param {string} d Input string
|
||||
* @returns {string} Raw MD5 string
|
||||
*/
|
||||
function rawHMACMD5(k, d) {
|
||||
return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d));
|
||||
}
|
||||
/**
|
||||
* Calculates the Hex encoded HMAC-MD5 for the given key and data
|
||||
*
|
||||
* @param {string} k HMAC key
|
||||
* @param {string} d Input string
|
||||
* @returns {string} Raw MD5 string
|
||||
*/
|
||||
function hexHMACMD5(k, d) {
|
||||
return rstr2hex(rawHMACMD5(k, d));
|
||||
}
|
||||
/**
|
||||
* Calculates MD5 value for a given string.
|
||||
* If a key is provided, calculates the HMAC-MD5 value.
|
||||
* Returns a Hex encoded string unless the raw argument is given.
|
||||
*
|
||||
* @param {string} string Input string
|
||||
* @param {string} [key] HMAC key
|
||||
* @param {boolean} [raw] Raw output switch
|
||||
* @returns {string} MD5 output
|
||||
*/
|
||||
function md5(string, key, raw) {
|
||||
if (!key) {
|
||||
if (!raw) {
|
||||
return hexMD5(string);
|
||||
}
|
||||
return rawMD5(string);
|
||||
}
|
||||
if (!raw) {
|
||||
return hexHMACMD5(key, string);
|
||||
}
|
||||
return rawHMACMD5(key, string);
|
||||
}
|
||||
exports.default = md5;
|
||||
49
extensions/app/engine/dist/inspector/asset-directory.js
vendored
Normal file
49
extensions/app/engine/dist/inspector/asset-directory.js
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.close = exports.ready = exports.update = exports.template = exports.$ = void 0;
|
||||
const fs_1 = require("fs");
|
||||
const path_1 = require("path");
|
||||
exports.$ = {
|
||||
'code': '#code',
|
||||
'section': '#section',
|
||||
};
|
||||
exports.template = `
|
||||
<ui-section id="section" header="文件夹说明" expand>
|
||||
<ui-code id="code"></ui-code>
|
||||
</ui-section>
|
||||
`;
|
||||
function update(assetList, metaList) {
|
||||
this.assetList = assetList;
|
||||
this.metaList = metaList;
|
||||
if (assetList.length === 0) {
|
||||
this.$.code.innerHTML = '';
|
||||
}
|
||||
else {
|
||||
this.$.code.innerHTML = assetList
|
||||
.filter((asset) => {
|
||||
const mdFile = path_1.join(asset.file, `.${asset.name}.md`);
|
||||
return fs_1.existsSync(mdFile);
|
||||
})
|
||||
.map((asset) => {
|
||||
const mdFile = path_1.join(asset.file, `.${asset.name}.md`);
|
||||
const mdStr = fs_1.readFileSync(mdFile, 'utf-8');
|
||||
return assetList.length > 1 ? `${asset.url}:\n ${mdStr}` : mdStr;
|
||||
})
|
||||
.join('\n') || '';
|
||||
}
|
||||
if (this.$.code.innerHTML === '') {
|
||||
this.$.section.hidden = true;
|
||||
}
|
||||
else {
|
||||
this.$.section.hidden = false;
|
||||
}
|
||||
}
|
||||
exports.update = update;
|
||||
function ready() {
|
||||
// TODO something
|
||||
}
|
||||
exports.ready = ready;
|
||||
function close() {
|
||||
// TODO something
|
||||
}
|
||||
exports.close = close;
|
||||
549
extensions/app/engine/dist/main.js
vendored
Normal file
549
extensions/app/engine/dist/main.js
vendored
Normal file
@@ -0,0 +1,549 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @en Registration method for the main process of Extension
|
||||
* @zh 为扩展的主进程的注册方法
|
||||
*/
|
||||
/**
|
||||
* // 打开panel
|
||||
* Editor.Panel.open(`${插件名}.${panel名}`);
|
||||
* // 调用普通事件
|
||||
* Editor.Message.request(插件名, 消息名, ...args);
|
||||
* // 调用场景方法
|
||||
* Editor.Message.request('scene', 'execute-scene-script', {
|
||||
* //插件名
|
||||
* name: string,
|
||||
* //方法名
|
||||
* method: string,
|
||||
* //参数列表
|
||||
* args: any[]
|
||||
* });
|
||||
*
|
||||
*/
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.unload = exports.load = exports.methods = void 0;
|
||||
// path.join不能正确处理'db://'结构,会把'//'变成'/'
|
||||
const fs_1 = require("fs");
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const utils_1 = require("./utils");
|
||||
const electron = require('electron');
|
||||
const adminFolderName = 'app-admin';
|
||||
const controllerFolderName = 'app-controller';
|
||||
const managerFolderName = 'app-manager';
|
||||
const modelFolderName = 'app-model';
|
||||
const soundFolderName = 'app-sound';
|
||||
const viewFolderName = 'app-view';
|
||||
const builtinFolderName = 'app-builtin';
|
||||
const bundleFolderName = 'app-bundle';
|
||||
const pkgFolderUrl = 'db://pkg/';
|
||||
const pkgFolderPath = utils_1.convertUrlToPath(pkgFolderUrl);
|
||||
const builtinFolderUrl = 'db://assets/' + builtinFolderName;
|
||||
const builtinFolderPath = utils_1.convertUrlToPath(builtinFolderUrl);
|
||||
const bundleFolderUrl = 'db://assets/' + bundleFolderName;
|
||||
const bundleFolderPath = utils_1.convertUrlToPath(bundleFolderUrl);
|
||||
const adminFolderUrl = builtinFolderUrl + '/' + adminFolderName;
|
||||
const adminFolderPath = builtinFolderPath + '/' + adminFolderName;
|
||||
const controllerFolderUrl = builtinFolderUrl + '/' + controllerFolderName;
|
||||
const controllerFolderPath = builtinFolderPath + '/' + controllerFolderName;
|
||||
const managerFolderUrl = builtinFolderUrl + '/' + managerFolderName;
|
||||
const managerFolderPath = builtinFolderPath + '/' + managerFolderName;
|
||||
const modelFolderUrl = builtinFolderUrl + '/' + modelFolderName;
|
||||
const modelFolderPath = builtinFolderPath + '/' + modelFolderName;
|
||||
const soundFolderUrl = bundleFolderUrl + '/' + soundFolderName;
|
||||
const soundFolderPath = bundleFolderPath + '/' + soundFolderName;
|
||||
const viewFolderUrl = bundleFolderUrl + '/' + viewFolderName;
|
||||
const viewFolderPath = bundleFolderPath + '/' + viewFolderName;
|
||||
const executorFileUrl = adminFolderUrl + '/executor.ts';
|
||||
const executorFilePath = adminFolderPath + '/executor.ts';
|
||||
function isExecutor(info, strict = true) {
|
||||
if (!strict) {
|
||||
if (info.path.endsWith('Controller') && info.type === 'cc.Script')
|
||||
return true;
|
||||
if (info.path.endsWith('Manager') && (info.type === 'cc.Script' || info.type === 'cc.Prefab'))
|
||||
return true;
|
||||
if ((info.name.startsWith('data.') || info.name.startsWith('config.') || info.name.startsWith('store.')) && info.type === 'cc.Script')
|
||||
return true;
|
||||
if ((info.name.startsWith('Page') || info.name.startsWith('Paper') || info.name.startsWith('Pop') || info.name.startsWith('Top'))
|
||||
&& (info.type === 'cc.Script' || info.type === 'cc.Prefab' || info.type === 'cc.Scene' || info.type === 'cc.SceneAsset'))
|
||||
return true;
|
||||
if (info.type === 'cc.AudioClip')
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
if (info.path === builtinFolderUrl)
|
||||
return true;
|
||||
if (info.path === bundleFolderUrl)
|
||||
return true;
|
||||
if (info.path === managerFolderUrl)
|
||||
return true;
|
||||
if (info.path === controllerFolderUrl)
|
||||
return true;
|
||||
if (info.path === modelFolderUrl)
|
||||
return true;
|
||||
if (info.path === soundFolderUrl)
|
||||
return true;
|
||||
if (info.path === viewFolderUrl)
|
||||
return true;
|
||||
if (info.path.startsWith(controllerFolderUrl)) {
|
||||
return info.path.endsWith('Controller') && info.type === 'cc.Script';
|
||||
}
|
||||
if (info.path.startsWith(managerFolderUrl)) {
|
||||
return info.path.endsWith('Manager') && (info.type === 'cc.Script' || info.type === 'cc.Prefab');
|
||||
}
|
||||
if (info.path.startsWith(modelFolderUrl)) {
|
||||
return (info.name.startsWith('data.') || info.name.startsWith('config.') || info.name.startsWith('store.')) && info.type === 'cc.Script';
|
||||
}
|
||||
if (info.path.startsWith(viewFolderUrl)) {
|
||||
return (info.name.startsWith('Page') || info.name.startsWith('Paper') || info.name.startsWith('Pop') || info.name.startsWith('Top'))
|
||||
&& (info.type === 'cc.Script' || info.type === 'cc.Prefab' || info.type === 'cc.Scene' || info.type === 'cc.SceneAsset');
|
||||
}
|
||||
if (info.path.startsWith(soundFolderUrl)) {
|
||||
return info.type === 'cc.AudioClip';
|
||||
}
|
||||
}
|
||||
function compareStr(str1, str2) {
|
||||
if (str1 === str2) {
|
||||
return 0;
|
||||
}
|
||||
const len = Math.max(str1.length, str2.length);
|
||||
for (let i = 0, code1 = 0, code2 = 0; i < len; i++) {
|
||||
if (str1.length <= i) {
|
||||
return -1;
|
||||
}
|
||||
else if (str2.length <= i) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
code1 = str1.charCodeAt(i);
|
||||
code2 = str2.charCodeAt(i);
|
||||
if (code1 > code2) {
|
||||
return 1;
|
||||
}
|
||||
else if (code1 < code2) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
const viewSelect = ['Page', 'Paper', 'Pop', 'Top'];
|
||||
const viewRegExp = RegExp(`^(${viewSelect.join('|')})`);
|
||||
function readFileSyncByPath(url) {
|
||||
const filepath = utils_1.convertUrlToPath(url);
|
||||
return fs_1.existsSync(filepath) ? fs_1.readFileSync(filepath, 'utf8') : '';
|
||||
}
|
||||
function isTSDefault(value) {
|
||||
// const varname = value[0];
|
||||
const filename = value[1];
|
||||
const dirname = value[2];
|
||||
const extname = value[3];
|
||||
if (extname.endsWith('js')) {
|
||||
return false;
|
||||
}
|
||||
const filepath = path_1.default.join(utils_1.convertUrlToPath(dirname), filename + '.ts');
|
||||
const js = fs_1.readFileSync(filepath, 'utf8');
|
||||
return js.search(/export\s+default/) >= 0;
|
||||
}
|
||||
const keyWords = [
|
||||
'lib', 'manager', 'Manager', 'controller', 'Controller', 'data', 'config', 'store',
|
||||
'IViewName', 'IViewNames', 'IMiniViewName', 'IMiniViewNames', 'IMusicName', 'IMusicNames', 'IEffectName', 'IEffectNames',
|
||||
'ViewName', 'MiniViewName', 'MusicName', 'EffectName'
|
||||
];
|
||||
async function clearExecutor() {
|
||||
if (!fs_1.existsSync(executorFilePath))
|
||||
return;
|
||||
let result = '/* eslint-disable */\n' +
|
||||
'import { Component } from \'cc\';\n' +
|
||||
'import { app } from \'../../app/app\';\n' +
|
||||
'import { EDITOR,EDITOR_NOT_IN_PREVIEW } from \'cc/env\';\n\n';
|
||||
result += 'export type IReadOnly<T> = { readonly [P in keyof T]: T[P] extends Function ? T[P] : (T[P] extends Object ? IReadOnly<T[P]> : T[P]); };\n\n';
|
||||
result += 'export type IViewName = "never"\n';
|
||||
result += 'export type IViewNames = IViewName[]\n';
|
||||
result += 'export type IMiniViewName = "never"\n';
|
||||
result += 'export type IMiniViewNames = IMiniViewName[]\n';
|
||||
result += 'export type IMusicName = "never"\n';
|
||||
result += 'export type IMusicNames = IMusicName[]\n';
|
||||
result += 'export type IEffectName = "never"\n';
|
||||
result += 'export type IEffectNames = IEffectName[]\n\n';
|
||||
result += 'export type IApp = {\n';
|
||||
result += ' Controller: {},\n';
|
||||
result += ' controller: {},\n';
|
||||
result += ' Manager: {},\n';
|
||||
result += ' manager: {},\n';
|
||||
result += ' data: {},\n';
|
||||
result += ' config: {}\n';
|
||||
result += ' store: {}\n';
|
||||
result += '}\n';
|
||||
// config
|
||||
result += 'if(!EDITOR||!EDITOR_NOT_IN_PREVIEW) Object.assign(app.config, {})\n';
|
||||
// data
|
||||
result += 'if(!EDITOR||!EDITOR_NOT_IN_PREVIEW) Object.assign(app.data, {})\n';
|
||||
// store
|
||||
result += 'if(!EDITOR||!EDITOR_NOT_IN_PREVIEW) Object.assign(app.store, {})\n\n';
|
||||
// controller
|
||||
result += 'if(!EDITOR||!EDITOR_NOT_IN_PREVIEW) Object.assign(app.Controller, {})\n';
|
||||
result += 'if(!EDITOR||!EDITOR_NOT_IN_PREVIEW) Object.assign(app.controller, {})\n\n';
|
||||
// 修正windows系统中的\为/
|
||||
result = result.replace(/\\/g, '/');
|
||||
// save
|
||||
if (readFileSyncByPath(executorFileUrl) !== result) {
|
||||
await Editor.Message.request('asset-db', 'create-asset', executorFileUrl, result, {
|
||||
overwrite: true
|
||||
});
|
||||
}
|
||||
}
|
||||
async function updateExecutor() {
|
||||
// app-builtin文件夹不存在, 创建
|
||||
if (!fs_1.existsSync(builtinFolderPath))
|
||||
await utils_1.createFolderByUrl(builtinFolderUrl, { readme: utils_1.getResReadme(builtinFolderName) });
|
||||
// app-admin文件夹不存在, 创建
|
||||
if (!fs_1.existsSync(adminFolderPath))
|
||||
await utils_1.createFolderByUrl(adminFolderUrl, { meta: utils_1.getResMeta(adminFolderName), readme: utils_1.getResReadme(adminFolderName) });
|
||||
const mgrList = [];
|
||||
const ctrList = [];
|
||||
const dataList = [];
|
||||
const confList = [];
|
||||
const storeList = [];
|
||||
const viewScene = {};
|
||||
const miniViewKeys = {};
|
||||
const musicKeys = {};
|
||||
const effectKeys = {};
|
||||
// app-controller app-manager app-model
|
||||
const result1 = await Editor.Message.request('asset-db', 'query-assets', { pattern: builtinFolderUrl + '/{app-controller,app-manager/*,app-model}/*.ts' })
|
||||
.then(res => {
|
||||
return res.sort((a, b) => compareStr(a.name, b.name));
|
||||
})
|
||||
.catch(() => []);
|
||||
// app-sound
|
||||
const result2 = await Editor.Message.request('asset-db', 'query-assets', { pattern: soundFolderUrl + '/{music,effect}/**/*.*' })
|
||||
.then(res => {
|
||||
return res.sort((a, b) => compareStr(a.name, b.name));
|
||||
})
|
||||
.catch(() => []);
|
||||
// app-view
|
||||
const result3 = await Editor.Message.request('asset-db', 'query-assets', { pattern: viewFolderUrl + '/{page,pop,top,paper/*}/*/native/*.{prefab,scene}' })
|
||||
.then(res => {
|
||||
return res.sort((a, b) => compareStr(a.name, b.name));
|
||||
})
|
||||
.catch(() => []);
|
||||
// manager
|
||||
const result4 = await Editor.Message.request('asset-db', 'query-assets', { pattern: 'db://app/manager/**/*.ts' })
|
||||
.then(res => {
|
||||
return res.sort((a, b) => compareStr(a.name, b.name));
|
||||
})
|
||||
.catch(() => []);
|
||||
// 集合
|
||||
const results = result1.slice().concat(result2).concat(result3).concat(result4);
|
||||
for (let index = 0; index < results.length; index++) {
|
||||
const result = results[index];
|
||||
const fileUrl = result.url;
|
||||
// 文件名.扩展名
|
||||
const basename = path_1.default.basename(result.url || '') || '';
|
||||
// 扩展名
|
||||
const extname = path_1.default.extname(result.url || '') || '';
|
||||
// 文件名
|
||||
const filename = basename.slice(0, -extname.length);
|
||||
// 文件目录名
|
||||
const dirname = path_1.default.dirname(result.url || '') || '';
|
||||
if (!basename)
|
||||
continue;
|
||||
if (!extname)
|
||||
continue;
|
||||
if (!filename)
|
||||
continue;
|
||||
if (!dirname)
|
||||
continue;
|
||||
if (extname === '.ts') {
|
||||
// 变量名
|
||||
const varname = filename.replace(/[.-]/g, '_');
|
||||
if (keyWords.indexOf(varname) >= 0) {
|
||||
console.log(`[跳过此文件] [${filename}] 原因: ${varname}与关键字中(${JSON.stringify(keyWords)})的一个重复`);
|
||||
}
|
||||
else if (fileUrl.startsWith(controllerFolderUrl)) {
|
||||
// 用户controller
|
||||
if (filename.endsWith('Controller')) {
|
||||
ctrList.push([varname, filename, dirname, extname]);
|
||||
}
|
||||
}
|
||||
else if (fileUrl.startsWith(managerFolderUrl)) {
|
||||
// 用户manager
|
||||
if (filename.endsWith('Manager') && dirname.endsWith(utils_1.stringCaseNegate(filename.slice(0, -7)))) {
|
||||
mgrList.push([varname, filename, dirname, extname]);
|
||||
}
|
||||
}
|
||||
else if (fileUrl.startsWith('db://app/manager/')) {
|
||||
// 系统manager(系统Mgr的文件夹命名为了美观没有那么规范,所以和用户Mgr的逻辑有区别)
|
||||
if (filename.endsWith('Manager') && dirname.endsWith(filename.slice(0, -7).toLowerCase())) {
|
||||
mgrList.push([varname, filename, dirname, extname]);
|
||||
}
|
||||
}
|
||||
else if (fileUrl.startsWith(modelFolderUrl)) {
|
||||
// model
|
||||
if (filename.startsWith('data.')) {
|
||||
dataList.push([varname, filename, dirname, extname]);
|
||||
}
|
||||
else if (filename.startsWith('config.')) {
|
||||
confList.push([varname, filename, dirname, extname]);
|
||||
}
|
||||
else if (filename.startsWith('store.')) {
|
||||
storeList.push([varname, filename, dirname, extname]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (extname === '.prefab' || extname === '.scene') {
|
||||
if (fileUrl.startsWith(viewFolderUrl) && viewRegExp.test(filename)) {
|
||||
const dirArray = dirname.split('/');
|
||||
const index = dirArray.indexOf(viewFolderName);
|
||||
const viewDirArray = dirArray.slice(index + 1);
|
||||
if (['page', 'paper', 'pop', 'top'].indexOf(viewDirArray[0].toLowerCase()) >= 0) {
|
||||
// 主界面
|
||||
if (filename === `${utils_1.stringCase(viewDirArray[0], false)}${utils_1.stringCase(viewDirArray[1], false)}`) {
|
||||
viewScene[filename] = extname === '.scene';
|
||||
}
|
||||
// 子界面
|
||||
else if (filename === `${utils_1.stringCase(viewDirArray[0], false)}${utils_1.stringCase(viewDirArray[1], false)}${utils_1.stringCase(viewDirArray[2], false)}`) {
|
||||
miniViewKeys[filename] = `${utils_1.stringCase(viewDirArray[0], false)}${utils_1.stringCase(viewDirArray[1], false)}`;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 主界面
|
||||
if (filename === `${utils_1.stringCase(viewDirArray[1], false)}${utils_1.stringCase(viewDirArray[2], false)}`) {
|
||||
viewScene[filename] = extname === '.scene';
|
||||
}
|
||||
// 子界面
|
||||
else if (filename === `${utils_1.stringCase(viewDirArray[1], false)}${utils_1.stringCase(viewDirArray[2], false)}${utils_1.stringCase(viewDirArray[3], false)}`) {
|
||||
miniViewKeys[filename] = `${utils_1.stringCase(viewDirArray[0], false)}${utils_1.stringCase(viewDirArray[1], false)}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (fileUrl.startsWith(soundFolderUrl)) {
|
||||
const dir = path_1.default.join(dirname.split(soundFolderName + '/').pop(), filename);
|
||||
if (dir.startsWith('music')) {
|
||||
// musicKeys
|
||||
musicKeys[dir] = dir;
|
||||
}
|
||||
else {
|
||||
// effectKeys
|
||||
effectKeys[dir] = dir;
|
||||
}
|
||||
}
|
||||
}
|
||||
// const pkgNames: string[] = [];
|
||||
// if (existsSync(pkgFolderPath)) {
|
||||
// readdirSync(pkgFolderPath).forEach(function (item) {
|
||||
// const item_path = path.join(pkgFolderPath, item);
|
||||
// const item_stat = statSync(item_path);
|
||||
// if (!item_stat.isDirectory()) return;
|
||||
// const item_name = path.basename(item_path);
|
||||
// if (item_name.startsWith('@')) {
|
||||
// readdirSync(item_path).forEach(function (sub) {
|
||||
// const sub_path = path.join(item_path, sub);
|
||||
// const sub_stat = statSync(sub_path);
|
||||
// if (!sub_stat.isDirectory()) return;
|
||||
// const sub_name = path.basename(sub_path);
|
||||
// pkgNames.push(item_name + '/' + sub_name);
|
||||
// });
|
||||
// } else {
|
||||
// pkgNames.push(item_name);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
let result = '/* eslint-disable */\n' +
|
||||
'import { Component,director,Director } from \'cc\';\n' +
|
||||
'import { app } from \'../../app/app\';\n' +
|
||||
'import { EDITOR,EDITOR_NOT_IN_PREVIEW } from \'cc/env\';\n\n';
|
||||
result += 'export type IReadOnly<T> = { readonly [P in keyof T]: T[P] extends Function ? T[P] : (T[P] extends Object ? IReadOnly<T[P]> : T[P]); };\n\n';
|
||||
result += `export type IViewName = ${Object.keys(viewScene).map(str => `"${str}"`).join('|') || '"never"'}\n`;
|
||||
result += 'export type IViewNames = IViewName[]\n';
|
||||
result += `export type IMiniViewName = ${Object.keys(miniViewKeys).map(str => `"${str}"`).join('|') || '"never"'}\n`;
|
||||
result += 'export type IMiniViewNames = IMiniViewName[]\n';
|
||||
result += `export type IMusicName = ${Object.keys(musicKeys).map(str => `"${str}"`).join('|') || '"never"'}\n`;
|
||||
result += 'export type IMusicNames = IMusicName[]\n';
|
||||
result += `export type IEffectName = ${Object.keys(effectKeys).map(str => `"${str}"`).join('|') || '"never"'}\n`;
|
||||
result += 'export type IEffectNames = IEffectName[]\n\n';
|
||||
// pkgNames.forEach(name => result += `import 'db://pkg/${name}'\n`);
|
||||
const writeImport = function writeImport(arr, module) {
|
||||
return arr.forEach(function (value) {
|
||||
const varname = value[0];
|
||||
const filename = value[1];
|
||||
const dirname = value[2];
|
||||
if (isTSDefault(value)) {
|
||||
result += `import ${varname} from '${path_1.default.join(path_1.default.relative(adminFolderPath, utils_1.convertUrlToPath(dirname)), filename)}'\n`;
|
||||
}
|
||||
else if (module) {
|
||||
result += `import {${varname}} from '${path_1.default.join(path_1.default.relative(adminFolderPath, utils_1.convertUrlToPath(dirname)), filename)}'\n`;
|
||||
}
|
||||
else {
|
||||
result += `import * as ${varname} from '${path_1.default.join(path_1.default.relative(adminFolderPath, utils_1.convertUrlToPath(dirname)), filename)}'\n`;
|
||||
}
|
||||
});
|
||||
};
|
||||
writeImport(confList, false);
|
||||
writeImport(dataList, false);
|
||||
writeImport(storeList, false);
|
||||
writeImport(ctrList, true);
|
||||
writeImport(mgrList, true);
|
||||
// controller
|
||||
let ctrStr = '';
|
||||
let CtrStr = '';
|
||||
ctrList.forEach(function ([varname], index, array) {
|
||||
CtrStr += `${varname.slice(0, -10)}:typeof ${varname}`;
|
||||
ctrStr += `${varname.slice(0, -10).toLowerCase()}:IReadOnly<${varname}>`;
|
||||
if (index < array.length - 1) {
|
||||
CtrStr += ',';
|
||||
ctrStr += ',';
|
||||
}
|
||||
});
|
||||
// manager
|
||||
let mgrStr = '';
|
||||
let MgrStr = '';
|
||||
mgrList.forEach(function ([varname], index, array) {
|
||||
MgrStr += `${varname.slice(0, -7)}:Omit<typeof ${varname},keyof Component>`;
|
||||
if (varname === 'UIManager') {
|
||||
mgrStr += `${varname.slice(0, -7).toLowerCase()}:Omit<${varname}<IViewName,IMiniViewName>,keyof Component>`;
|
||||
}
|
||||
else if (varname === 'SoundManager') {
|
||||
mgrStr += `${varname.slice(0, -7).toLowerCase()}:Omit<${varname}<IEffectName,IMusicName>,keyof Component>`;
|
||||
}
|
||||
else {
|
||||
mgrStr += `${varname.slice(0, -7).toLowerCase()}:Omit<${varname},keyof Component>`;
|
||||
}
|
||||
if (index < array.length - 1) {
|
||||
MgrStr += ',';
|
||||
mgrStr += ',';
|
||||
}
|
||||
});
|
||||
result += 'export type IApp = {\n';
|
||||
result += ` Controller: {${CtrStr}},\n`;
|
||||
result += ` controller: {${ctrStr}},\n`;
|
||||
result += ` Manager: {${MgrStr}},\n`;
|
||||
result += ` manager: {${mgrStr}},\n`;
|
||||
result += ` data: {${dataList.map(([varname]) => `${varname.slice(5)}:${varname}`).join(',')}},\n`;
|
||||
result += ` config: {${confList.map(([varname]) => `${varname.slice(7)}:IReadOnly<${varname}>`).join(',')}}\n`;
|
||||
result += ` store: {${storeList.map(([varname]) => `${varname.slice(6)}:IReadOnly<${varname}>`).join(',')}}\n`;
|
||||
result += '}\n\n';
|
||||
result += 'function init(){\n';
|
||||
// config
|
||||
result += `if(!EDITOR||!EDITOR_NOT_IN_PREVIEW) Object.assign(app.config, {${confList.map(([varname]) => `${varname.slice(7)}:new ${varname}()`).join(',')}})\n`;
|
||||
// data
|
||||
result += `if(!EDITOR||!EDITOR_NOT_IN_PREVIEW) Object.assign(app.data, {${dataList.map(([varname]) => `${varname.slice(5)}:new ${varname}()`).join(',')}})\n`;
|
||||
// store
|
||||
result += `if(!EDITOR||!EDITOR_NOT_IN_PREVIEW) Object.assign(app.store, {${storeList.map(([varname]) => `${varname.slice(6)}:new ${varname}()`).join(',')}})\n\n`;
|
||||
// controller
|
||||
result += `if(!EDITOR||!EDITOR_NOT_IN_PREVIEW) Object.assign(app.Controller, {${ctrList.map(([varname]) => `${varname.slice(0, -10)}:${varname}`).join(',')}})\n`;
|
||||
result += `if(!EDITOR||!EDITOR_NOT_IN_PREVIEW) Object.assign(app.controller, {${ctrList.map(([varname]) => `${varname.slice(0, -10).toLowerCase()}:new ${varname}()`).join(',')}})\n`;
|
||||
result += '}\n';
|
||||
result += 'if(!EDITOR||!EDITOR_NOT_IN_PREVIEW) director.on(Director.EVENT_RESET,init)\n';
|
||||
result += 'if(!EDITOR||!EDITOR_NOT_IN_PREVIEW) init()\n';
|
||||
// 修正windows系统中的\为/
|
||||
result = result.replace(/\\/g, '/');
|
||||
// save
|
||||
if (readFileSyncByPath(executorFileUrl) !== result) {
|
||||
await Editor.Message.request('asset-db', 'create-asset', executorFileUrl, result, {
|
||||
overwrite: true
|
||||
});
|
||||
}
|
||||
}
|
||||
let timer = null;
|
||||
function callUpdateExecutor(clear = false) {
|
||||
if (timer)
|
||||
return;
|
||||
if (clear) {
|
||||
clearExecutor();
|
||||
callUpdateExecutor(false);
|
||||
}
|
||||
else {
|
||||
timer = setTimeout(() => {
|
||||
updateExecutor().finally(() => {
|
||||
timer = null;
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
// 获得Creator主窗口
|
||||
function getMainWebContents() {
|
||||
const windows = electron.BrowserWindow.getAllWindows();
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
const win = windows[i];
|
||||
if (win.webContents.getURL().includes('windows/main.html') || (win.title && win.title.includes('Cocos Creator'))) {
|
||||
return win.webContents;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
function updateMark() {
|
||||
const webContents = getMainWebContents();
|
||||
if (webContents) {
|
||||
const hackCode = fs_1.readFileSync(path_1.default.join(__dirname, '../res/mark.js'), 'utf-8');
|
||||
webContents.executeJavaScript(hackCode);
|
||||
}
|
||||
}
|
||||
exports.methods = {
|
||||
['open-panel']() {
|
||||
Editor.Panel.open('app.open-panel');
|
||||
},
|
||||
['open-wiki']() {
|
||||
const url = 'https://gitee.com/cocos2d-zp/xforge/wikis/pages';
|
||||
Editor.Message.send('program', 'open-url', url);
|
||||
},
|
||||
['open-issues']() {
|
||||
const url = 'https://gitee.com/cocos2d-zp/xforge/issues';
|
||||
Editor.Message.send('program', 'open-url', url);
|
||||
},
|
||||
['open-github']() {
|
||||
const url = 'https://github.com/a1076559139/XForge';
|
||||
Editor.Message.send('program', 'open-url', url);
|
||||
},
|
||||
['open-store']() {
|
||||
const url = 'https://store.cocos.com/app/search?name=xforge';
|
||||
Editor.Message.send('program', 'open-url', url);
|
||||
},
|
||||
['refresh-executor']() {
|
||||
// 点击更新
|
||||
callUpdateExecutor();
|
||||
console.log('[executor.ts] 刷新成功');
|
||||
},
|
||||
['scene:ready']() {
|
||||
//
|
||||
},
|
||||
['asset-db:ready']() {
|
||||
updateExecutor();
|
||||
updateMark();
|
||||
},
|
||||
['asset-db:asset-add'](uuid, info) {
|
||||
if (!isExecutor(info))
|
||||
return;
|
||||
callUpdateExecutor();
|
||||
},
|
||||
['asset-db:asset-change'](uuid, info) {
|
||||
if (!isExecutor(info, false))
|
||||
return;
|
||||
callUpdateExecutor();
|
||||
},
|
||||
['asset-db:asset-delete'](uuid, info) {
|
||||
if (!isExecutor(info))
|
||||
return;
|
||||
callUpdateExecutor(true);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @en Hooks triggered after extension loading is complete
|
||||
* @zh 扩展加载完成后触发的钩子
|
||||
*/
|
||||
function load() {
|
||||
Editor.Message.request('asset-db', 'query-ready').then(ready => {
|
||||
if (!ready)
|
||||
return;
|
||||
updateExecutor();
|
||||
});
|
||||
}
|
||||
exports.load = load;
|
||||
/**
|
||||
* @en Hooks triggered after extension uninstallation is complete
|
||||
* @zh 扩展卸载完成后触发的钩子
|
||||
*/
|
||||
function unload() { }
|
||||
exports.unload = unload;
|
||||
38
extensions/app/engine/dist/menu/index.js
vendored
Normal file
38
extensions/app/engine/dist/menu/index.js
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.onAssetMenu = exports.onPanelMenu = exports.onDBMenu = exports.onCreateMenu = void 0;
|
||||
const tinyPNG_1 = __importDefault(require("./tinyPNG"));
|
||||
function getMenu(assetInfo) {
|
||||
return [
|
||||
{
|
||||
label: 'i18n:app.app',
|
||||
submenu: [
|
||||
{
|
||||
label: 'i18n:app.tiny',
|
||||
click() {
|
||||
tinyPNG_1.default(assetInfo.file);
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
function onCreateMenu(assetInfo) {
|
||||
// return getMenu();
|
||||
}
|
||||
exports.onCreateMenu = onCreateMenu;
|
||||
function onDBMenu(assetInfo) {
|
||||
// return getMenu();
|
||||
}
|
||||
exports.onDBMenu = onDBMenu;
|
||||
function onPanelMenu(assetInfo) {
|
||||
// return getMenu();
|
||||
}
|
||||
exports.onPanelMenu = onPanelMenu;
|
||||
function onAssetMenu(assetInfo) {
|
||||
return getMenu(assetInfo);
|
||||
}
|
||||
exports.onAssetMenu = onAssetMenu;
|
||||
164
extensions/app/engine/dist/menu/tinyPNG.js
vendored
Normal file
164
extensions/app/engine/dist/menu/tinyPNG.js
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
"use strict";
|
||||
/**
|
||||
*
|
||||
* 参考: https://segmentfault.com/a/1190000015467084
|
||||
* 优化:通过 X-Forwarded-For 添加了动态随机伪IP,绕过 tinypng 的上传数量限制
|
||||
*
|
||||
*/
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs_1 = __importDefault(require("fs"));
|
||||
const https_1 = __importDefault(require("https"));
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const url_1 = require("url");
|
||||
const exts = ['.png', '.jpg', '.jpeg'];
|
||||
const max = 5200000; // 5MB == 5242848.754299136
|
||||
const options = {
|
||||
method: 'POST',
|
||||
hostname: 'tinypng.com',
|
||||
path: '/backend/opt/shrink',
|
||||
headers: {
|
||||
'rejectUnauthorized': 'false',
|
||||
'Postman-Token': Date.now(),
|
||||
'Cache-Control': 'no-cache',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'
|
||||
}
|
||||
};
|
||||
// 生成随机IP, 赋值给 X-Forwarded-For
|
||||
function getRandomIP() {
|
||||
return Array.from(Array(4)).map(() => Math.floor(Math.random() * 255)).join('.');
|
||||
}
|
||||
// 遍历文件列表
|
||||
function fileEach(folder, callback) {
|
||||
fs_1.default.readdir(folder, (err, files) => {
|
||||
if (err)
|
||||
console.error(err);
|
||||
files.forEach(file => {
|
||||
const filePath = path_1.default.join(folder, file);
|
||||
fs_1.default.stat(filePath, (err, stats) => {
|
||||
if (err)
|
||||
return console.error(err);
|
||||
if (stats.isDirectory()) {
|
||||
fileEach(filePath, callback);
|
||||
}
|
||||
else if (
|
||||
// 必须是文件,小于5MB,后缀 jpg||png
|
||||
stats.size <= max &&
|
||||
stats.isFile() &&
|
||||
exts.includes(path_1.default.extname(file))) {
|
||||
callback(filePath);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
// 压缩图片
|
||||
async function fileUpload(img_path) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 通过 X-Forwarded-For 头部伪造客户端IP
|
||||
options.headers['X-Forwarded-For'] = getRandomIP();
|
||||
const req = https_1.default.request(options, function (res) {
|
||||
res.on('data', buf => {
|
||||
const data = JSON.parse(buf.toString());
|
||||
if (data.error) {
|
||||
reject(data.message);
|
||||
}
|
||||
else {
|
||||
resolve(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
req.write(fs_1.default.readFileSync(img_path), 'binary');
|
||||
req.on('error', err => {
|
||||
reject(err);
|
||||
});
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
// 该方法被循环调用,请求图片数据
|
||||
function fileUpdate(img_path, obj) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const options = new url_1.URL(obj.output.url);
|
||||
const req = https_1.default.request(options, res => {
|
||||
let body = '';
|
||||
res.setEncoding('binary');
|
||||
res.on('data', function (data) {
|
||||
body += data;
|
||||
});
|
||||
res.on('end', function () {
|
||||
fs_1.default.writeFile(img_path, body, 'binary', err => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
resolve(obj);
|
||||
});
|
||||
});
|
||||
});
|
||||
req.on('error', err => {
|
||||
reject(err);
|
||||
});
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
// 根据字节大小转成B、KB、MB
|
||||
function toSize(b) {
|
||||
if (b < 1024) {
|
||||
return b + 'B';
|
||||
}
|
||||
else if (b < 1024 * 1024) {
|
||||
return (b / 1024).toFixed(2) + 'KB';
|
||||
}
|
||||
else {
|
||||
return (b / 1024 / 1024).toFixed(2) + 'MB';
|
||||
}
|
||||
}
|
||||
// 根据小数转成百分比字符串
|
||||
function toPercent(num) {
|
||||
return (num * 100).toFixed(2) + '%';
|
||||
}
|
||||
async function fileTiny(filePath) {
|
||||
return fileUpload(filePath)
|
||||
.then(obj => fileUpdate(filePath, obj));
|
||||
}
|
||||
function default_1(folder) {
|
||||
// 路径是否存在
|
||||
if (!fs_1.default.existsSync(folder)) {
|
||||
console.log(`路径不存在:${folder}`);
|
||||
return;
|
||||
}
|
||||
const basename = path_1.default.basename(folder);
|
||||
console.log(`[${basename}] 压缩中...`);
|
||||
// 是文件
|
||||
if (!fs_1.default.statSync(folder).isDirectory()) {
|
||||
if (!exts.includes(path_1.default.extname(folder))) {
|
||||
console.log(`[${basename}] 压缩失败!报错:只支持png、jpg与jpeg格式`);
|
||||
return;
|
||||
}
|
||||
fileTiny(folder)
|
||||
.then(obj => {
|
||||
console.log('[1/1]', `[${basename}]`, `压缩成功,原始: ${toSize(obj.input.size)},压缩: ${toSize(obj.output.size)},压缩比: ${toPercent(obj.output.ratio)}`);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('[1/1]', `[${basename}]`, `压缩失败!报错:${err}`);
|
||||
});
|
||||
return;
|
||||
}
|
||||
let total = 0;
|
||||
let finished = 0;
|
||||
// 是文件夹
|
||||
fileEach(folder, (filePath => {
|
||||
total++;
|
||||
const relativePath = path_1.default.relative(folder, filePath);
|
||||
fileTiny(filePath)
|
||||
.then(obj => {
|
||||
console.log(`[${++finished}/${total}]`, `[${relativePath}]`, `压缩成功,原始: ${toSize(obj.input.size)},压缩: ${toSize(obj.output.size)},压缩比: ${toPercent(obj.output.ratio)}`);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(`[${++finished}/${total}]`, `[${relativePath}]`, `压缩失败!报错:${err}`);
|
||||
});
|
||||
}));
|
||||
}
|
||||
exports.default = default_1;
|
||||
31
extensions/app/engine/dist/panel/components/app-create.js
vendored
Normal file
31
extensions/app/engine/dist/panel/components/app-create.js
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs_1 = require("fs");
|
||||
const path_1 = require("path");
|
||||
const vue_1 = __importDefault(require("../../../../vue"));
|
||||
const create_controller_1 = __importDefault(require("./create-controller"));
|
||||
const create_manager_1 = __importDefault(require("./create-manager"));
|
||||
const create_model_1 = __importDefault(require("./create-model"));
|
||||
const create_res_1 = __importDefault(require("./create-res"));
|
||||
const create_sound_1 = __importDefault(require("./create-sound"));
|
||||
const create_view_1 = __importDefault(require("./create-view"));
|
||||
const Assets = path_1.join(__dirname, '../../../res/panel');
|
||||
const Menus = ['ViewComponent', 'ManagerComponent', 'ControllerComponent', 'ModelComponent', 'SoundComponent', 'ResComponent'];
|
||||
exports.default = vue_1.default.extend({
|
||||
components: { ViewComponent: create_view_1.default, ManagerComponent: create_manager_1.default, ControllerComponent: create_controller_1.default, ModelComponent: create_model_1.default, SoundComponent: create_sound_1.default, ResComponent: create_res_1.default },
|
||||
template: fs_1.readFileSync(path_1.join(Assets, 'components/app.html'), 'utf-8'),
|
||||
data() {
|
||||
return {
|
||||
menus: ['View', 'Manager', 'Controller', 'Model', 'Sound', '资源目录'],
|
||||
content: 'ViewComponent'
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onClick(index) {
|
||||
this.content = Menus[index];
|
||||
}
|
||||
},
|
||||
});
|
||||
31
extensions/app/engine/dist/panel/components/app.js
vendored
Normal file
31
extensions/app/engine/dist/panel/components/app.js
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs_1 = require("fs");
|
||||
const path_1 = require("path");
|
||||
const vue_1 = __importDefault(require("../../../../vue"));
|
||||
const create_controller_1 = __importDefault(require("./create-controller"));
|
||||
const create_manager_1 = __importDefault(require("./create-manager"));
|
||||
const create_model_1 = __importDefault(require("./create-model"));
|
||||
const create_res_1 = __importDefault(require("./create-res"));
|
||||
const create_sound_1 = __importDefault(require("./create-sound"));
|
||||
const create_view_1 = __importDefault(require("./create-view"));
|
||||
const Assets = path_1.join(__dirname, '../../../res/panel');
|
||||
const Menus = ['ViewComponent', 'ManagerComponent', 'ControllerComponent', 'ModelComponent', 'SoundComponent', 'ResComponent'];
|
||||
exports.default = vue_1.default.extend({
|
||||
components: { ViewComponent: create_view_1.default, ManagerComponent: create_manager_1.default, ControllerComponent: create_controller_1.default, ModelComponent: create_model_1.default, SoundComponent: create_sound_1.default, ResComponent: create_res_1.default },
|
||||
template: fs_1.readFileSync(path_1.join(Assets, 'components/app.html'), 'utf-8'),
|
||||
data() {
|
||||
return {
|
||||
menus: ['View', 'Manager', 'Controller', 'Model', 'Sound', '资源目录'],
|
||||
content: 'ViewComponent'
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onClick(index) {
|
||||
this.content = Menus[index];
|
||||
}
|
||||
},
|
||||
});
|
||||
83
extensions/app/engine/dist/panel/components/create-controller.js
vendored
Normal file
83
extensions/app/engine/dist/panel/components/create-controller.js
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs_1 = require("fs");
|
||||
const vue_1 = __importDefault(require("../../../../vue"));
|
||||
const utils_1 = require("../../utils");
|
||||
/**
|
||||
* 根据语言获取脚本内容
|
||||
*/
|
||||
function getScript(name) {
|
||||
const basePath = '../../../extensions/app/assets/base/BaseController';
|
||||
return 'import BaseController from \'' + basePath + '\';\r\n' +
|
||||
'export class ' + name + ' extends BaseController<' + name + ', {\r\n' +
|
||||
' // 定义了事件,并同时定义参数列表和返回值\r\n' +
|
||||
' Refresh: (a: number) => boolean\r\n' +
|
||||
'}>() {\r\n' +
|
||||
' // Controller中发射事件, UI中监听事件:\r\n' +
|
||||
' // 1、UI中需要将 「extends BaseView」 改为=> 「extends BaseView.bindController(' + name + ')」\r\n' +
|
||||
' // 2、UI中使用「this.controller.on/once」监听事件, 使用「this.controller.emit」发射事件, 使用「this.controller.off/targetOff」取消监听事件\r\n' +
|
||||
' // 3、在外部(无法使用this.controller的地方)可以通过「app.controller.xxx」来调用对外导出的方法, 比如下面的refresh方法\r\n' +
|
||||
' refresh() {\r\n' +
|
||||
' this.emit(' + name + '.Event.Refresh, 1000); // 参数类型正确\r\n' +
|
||||
' this.emit(' + name + '.Event.Refresh, true); // 参数类型错误\r\n' +
|
||||
' const result = this.call(' + name + '.Event.Refresh, 1000); // 自动推导返回值类型\r\n' +
|
||||
' }\r\n' +
|
||||
'}';
|
||||
}
|
||||
exports.default = vue_1.default.extend({
|
||||
template: utils_1.getResPanel('create-controller'),
|
||||
data() {
|
||||
return {
|
||||
inputName: '',
|
||||
display: '',
|
||||
showLoading: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
async onClickCreate() {
|
||||
const name = this.inputName;
|
||||
if (/^[a-z][a-z0-9-]*[a-z0-9]+$/.test(name) === false) {
|
||||
this.display = '[错误] 名字不合法\n1、不能以数字开头\n2、不能有大写字母\n3、分隔符只能使用-\n4、不能以分隔符开头或结尾';
|
||||
return;
|
||||
}
|
||||
const rootPath = 'db://assets/app-builtin/app-controller';
|
||||
const controlName = `${utils_1.stringCase(name)}Controller`;
|
||||
const scriptUrl = `${rootPath}/${controlName}.ts`;
|
||||
// 创建前确认
|
||||
const createResponse = await Editor.Dialog.info('请确认', { detail: controlName, buttons: ['创建并打开', '仅创建', '取消'], default: 0, cancel: 2 });
|
||||
if (createResponse.response == 2) {
|
||||
return;
|
||||
}
|
||||
this.display = '创建中';
|
||||
this.showLoading = true;
|
||||
if (fs_1.existsSync(utils_1.convertUrlToPath(scriptUrl))) {
|
||||
this.showLoading = false;
|
||||
this.display = `[错误] 文件已存在, 请删除\n${scriptUrl}`;
|
||||
return;
|
||||
}
|
||||
// 目录如果不存在则创建
|
||||
if (!await utils_1.createFolderByUrl(rootPath, { meta: utils_1.getResMeta('app-controller'), readme: utils_1.getResReadme('app-controller') })) {
|
||||
this.showLoading = false;
|
||||
this.display = `[错误] 创建目录失败\n${rootPath}`;
|
||||
return;
|
||||
}
|
||||
// 创建script
|
||||
const createScriptResult = await Editor.Message.request('asset-db', 'create-asset', scriptUrl, getScript(controlName)).catch(_ => null);
|
||||
if (!createScriptResult) {
|
||||
this.showLoading = false;
|
||||
this.display = `[错误] 创建脚本失败\n${scriptUrl}`;
|
||||
return;
|
||||
}
|
||||
this.showLoading = false;
|
||||
this.display = `[成功] 创建成功\n${rootPath}`;
|
||||
Editor.Message.send('assets', 'twinkle', scriptUrl);
|
||||
// 是否打开
|
||||
if (createResponse.response == 0) {
|
||||
Editor.Message.request('asset-db', 'open-asset', scriptUrl);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
107
extensions/app/engine/dist/panel/components/create-manager.js
vendored
Normal file
107
extensions/app/engine/dist/panel/components/create-manager.js
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs_1 = require("fs");
|
||||
const vue_1 = __importDefault(require("../../../../vue"));
|
||||
const utils_1 = require("../../utils");
|
||||
/**
|
||||
* 根据语言获取脚本内容
|
||||
*/
|
||||
function getScript(name) {
|
||||
const basePath = '../../../../extensions/app/assets/base/BaseManager';
|
||||
return 'import { _decorator } from \'cc\';\r\n' +
|
||||
'import BaseManager from \'' + basePath + '\';\r\n' +
|
||||
'const { ccclass, property } = _decorator;\r\n' +
|
||||
'@ccclass(\'' + name + '\')\r\n' +
|
||||
'export class ' + name + ' extends BaseManager {\r\n' +
|
||||
' // [无序] 加载完成时触发\r\n' +
|
||||
' protected onLoad() { }\r\n\r\n' +
|
||||
' // [无序] 自身初始化完成, init执行完毕后被调用\r\n' +
|
||||
' protected onInited() { }\r\n\r\n' +
|
||||
' // [无序] 所有manager初始化完成\r\n' +
|
||||
' protected onFinished() { }\r\n\r\n' +
|
||||
' // [无序] 初始化manager,在初始化完成后,调用finish方法\r\n' +
|
||||
' protected init(finish: Function) {\r\n' +
|
||||
' super.init(finish);\r\n' +
|
||||
' }\r\n' +
|
||||
'}';
|
||||
}
|
||||
exports.default = vue_1.default.extend({
|
||||
template: utils_1.getResPanel('create-manager'),
|
||||
data() {
|
||||
return {
|
||||
inputName: '',
|
||||
display: '',
|
||||
showLoading: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
async onClickCreate() {
|
||||
const name = this.inputName;
|
||||
if (/^[a-z][a-z0-9-]*[a-z0-9]+$/.test(name) === false) {
|
||||
this.display = '[错误] 名字不合法\n1、不能以数字开头\n2、不能有大写字母\n3、分隔符只能使用-\n4、不能以分隔符开头或结尾';
|
||||
return;
|
||||
}
|
||||
const rootPath = 'db://assets/app-builtin/app-manager';
|
||||
const managerName = `${utils_1.stringCase(name)}Manager`;
|
||||
const folderName = name;
|
||||
const folderPath = `${rootPath}/${folderName}`;
|
||||
const scriptUrl = `${folderPath}/${managerName}.ts`;
|
||||
const prefabUrl = `${folderPath}/${managerName}.prefab`;
|
||||
// 创建前确认
|
||||
const createResponse = await Editor.Dialog.info('请确认', { detail: managerName, buttons: ['创建并打开', '仅创建', '取消'], default: 0, cancel: 2 });
|
||||
if (createResponse.response == 2) {
|
||||
return;
|
||||
}
|
||||
this.display = '创建中';
|
||||
this.showLoading = true;
|
||||
if (fs_1.existsSync(utils_1.convertUrlToPath(folderPath))) {
|
||||
this.showLoading = false;
|
||||
this.display = `[错误] 目录已存在, 请删除\n${folderPath}`;
|
||||
return;
|
||||
}
|
||||
// 目录如果不存在则创建
|
||||
if (!await utils_1.createFolderByUrl(rootPath, {
|
||||
meta: utils_1.getResMeta('app-manager'),
|
||||
readme: utils_1.getResReadme('app-manager'),
|
||||
subFolders: [
|
||||
{
|
||||
folder: folderName,
|
||||
readme: `1、${managerName}所在文件夹, 通过app.manager.${utils_1.stringCase(name, true)}的方式调用\n2、如不再需要,可以直接删除此文件夹`
|
||||
}
|
||||
]
|
||||
})) {
|
||||
this.showLoading = false;
|
||||
this.display = `[错误] 创建目录失败\n${folderPath}`;
|
||||
return;
|
||||
}
|
||||
// 创建script
|
||||
const createScriptResult = await Editor.Message.request('asset-db', 'create-asset', scriptUrl, getScript(managerName)).catch(_ => null);
|
||||
if (!createScriptResult) {
|
||||
this.showLoading = false;
|
||||
this.display = `[错误] 创建脚本失败\n${scriptUrl}`;
|
||||
return;
|
||||
}
|
||||
// 创建prefab
|
||||
const createPrefabResult = await Editor.Message.request('scene', 'execute-scene-script', {
|
||||
name: 'app',
|
||||
method: 'createPrefab',
|
||||
args: [managerName, prefabUrl]
|
||||
});
|
||||
if (!createPrefabResult) {
|
||||
this.showLoading = false;
|
||||
this.display = `[错误] 创建预制体失败\n${prefabUrl}`;
|
||||
return;
|
||||
}
|
||||
this.showLoading = false;
|
||||
this.display = `[成功] 创建成功\n${rootPath}`;
|
||||
Editor.Message.send('assets', 'twinkle', scriptUrl);
|
||||
// 是否打开
|
||||
if (createResponse.response == 0) {
|
||||
Editor.Message.request('asset-db', 'open-asset', scriptUrl);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
105
extensions/app/engine/dist/panel/components/create-model.js
vendored
Normal file
105
extensions/app/engine/dist/panel/components/create-model.js
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs_1 = require("fs");
|
||||
const vue_1 = __importDefault(require("../../../../vue"));
|
||||
const utils_1 = require("../../utils");
|
||||
/**
|
||||
* 根据语言获取脚本内容
|
||||
*/
|
||||
function getScript(type, className) {
|
||||
if (type === 'data') {
|
||||
const BaseModel = '../../../extensions/app/assets/base/BaseModel';
|
||||
return 'import { IModel } from \'' + BaseModel + '\';\r\n' +
|
||||
'// data中不能定义任何方法(更建议使用store)\r\n' +
|
||||
'export default class ' + className + ' implements IModel<' + className + '> {\r\n' +
|
||||
'}';
|
||||
}
|
||||
else if (type === 'config') {
|
||||
const BaseModel = '../../../extensions/app/assets/base/BaseModel';
|
||||
return 'import { IModel } from \'' + BaseModel + '\';\r\n' +
|
||||
'// config中不能定义任何方法, 任何变量在外部访问都是readonly\r\n' +
|
||||
'// 如果config中的内容是服务器下发的,可以使用Object.assign覆盖config中的内容\r\n' +
|
||||
'export default class ' + className + ' implements IModel<' + className + '> {\r\n' +
|
||||
'}';
|
||||
}
|
||||
else if (type === 'store') {
|
||||
const BaseModel = '../../../extensions/app/assets/base/BaseModel';
|
||||
return 'import { IStore } from \'' + BaseModel + '\';\r\n' +
|
||||
'// store中只允许在根路径下定义方法,任何变量在外部访问都是readonly\r\n' +
|
||||
'// store类型的引入是借鉴了Web前端框架中全局状态管理的思路,意图是让数据更安全,更可控。同时框架中还提供了数据绑定的扩展包,可以通过pkg的方式安装,实现「数据->视图」的单向绑定。\r\n' +
|
||||
'export default class ' + className + ' implements IStore<' + className + '> {\r\n' +
|
||||
' count = 0;\r\n' +
|
||||
' setCount(v: number) {\r\n' +
|
||||
' this.count = v;\r\n' +
|
||||
' }\r\n' +
|
||||
'}';
|
||||
}
|
||||
else {
|
||||
return '// 🔥切记: 当前文件处于分包中, 由于加载顺序的原因,不可以在「主包」中使用此文件内导出的变量\r\n' +
|
||||
'// 存放直接导出的interface、type或enum等\r\n\r\n' +
|
||||
'// export type IString = string;\r\n' +
|
||||
'// export enum Type { None };';
|
||||
}
|
||||
}
|
||||
exports.default = vue_1.default.extend({
|
||||
template: utils_1.getResPanel('create-model'),
|
||||
data() {
|
||||
return {
|
||||
inputName: '',
|
||||
display: '',
|
||||
typeSelects: ['store', 'data', 'config', 'export'],
|
||||
typeSelectIndex: 0,
|
||||
showLoading: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onChangeTypeSelect(index) {
|
||||
this.typeSelectIndex = Number(index);
|
||||
},
|
||||
async onClickCreate() {
|
||||
const type = this.typeSelects[this.typeSelectIndex];
|
||||
const name = this.inputName;
|
||||
if (/^[a-z][a-z0-9-]*[a-z0-9]+$/.test(name) === false) {
|
||||
this.display = '[错误] 名字不合法\n1、不能以数字开头\n2、不能有大写字母\n3、分隔符只能使用-\n4、不能以分隔符开头或结尾';
|
||||
return;
|
||||
}
|
||||
const rootPath = 'db://assets/app-builtin/app-model';
|
||||
const modelName = `${type}.${name}`;
|
||||
const scriptUrl = `${rootPath}/${modelName}.ts`;
|
||||
// 创建前确认
|
||||
const createResponse = await Editor.Dialog.info('请确认', { detail: modelName, buttons: ['创建并打开', '仅创建', '取消'], default: 0, cancel: 2 });
|
||||
if (createResponse.response == 2) {
|
||||
return;
|
||||
}
|
||||
this.display = '创建中';
|
||||
this.showLoading = true;
|
||||
// 目录如果不存在则创建
|
||||
if (!await utils_1.createFolderByUrl(rootPath, { meta: utils_1.getResMeta('app-model'), readme: utils_1.getResReadme('app-model') })) {
|
||||
this.showLoading = false;
|
||||
this.display = `[错误] 创建目录失败\n${rootPath}`;
|
||||
return;
|
||||
}
|
||||
if (fs_1.existsSync(utils_1.convertUrlToPath(scriptUrl))) {
|
||||
this.showLoading = false;
|
||||
this.display = `[错误] 文件已存在, 请删除\n${scriptUrl}`;
|
||||
return;
|
||||
}
|
||||
const createScriptResult = await Editor.Message.request('asset-db', 'create-asset', scriptUrl, getScript(type, utils_1.stringCase(name))).catch(_ => null);
|
||||
if (!createScriptResult) {
|
||||
this.showLoading = false;
|
||||
this.display = `[错误] 创建脚本失败\n${scriptUrl}`;
|
||||
return;
|
||||
}
|
||||
this.showLoading = false;
|
||||
this.display = `[成功] 创建成功\n${rootPath}`;
|
||||
Editor.Message.send('assets', 'twinkle', scriptUrl);
|
||||
// 是否打开
|
||||
if (createResponse.response == 0) {
|
||||
Editor.Message.request('asset-db', 'open-asset', scriptUrl);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
62
extensions/app/engine/dist/panel/components/create-res.js
vendored
Normal file
62
extensions/app/engine/dist/panel/components/create-res.js
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const vue_1 = __importDefault(require("../../../../vue"));
|
||||
const utils_1 = require("../../utils");
|
||||
const typeNames = ['res-native', 'res-bundle', 'resources'];
|
||||
exports.default = vue_1.default.extend({
|
||||
template: utils_1.getResPanel('create-res'),
|
||||
data() {
|
||||
return {
|
||||
inputName: '',
|
||||
display: '',
|
||||
typeSelects: ['公共静态目录', '公共动态目录', 'resources'],
|
||||
typeSelectIndex: 0,
|
||||
showLoading: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onChangeTypeSelect(index) {
|
||||
this.typeSelectIndex = Number(index);
|
||||
},
|
||||
async onClickCreate() {
|
||||
const folderName = typeNames[this.typeSelectIndex];
|
||||
const folderPath = `db://assets/${folderName}`;
|
||||
const name = utils_1.stringCase(this.inputName, true);
|
||||
if (/^[a-z][a-z0-9-]*[a-z0-9]+$/.test(this.inputName) === false) {
|
||||
this.display = '[错误] 名字不合法\n1、不能以数字开头\n2、不能有大写字母\n3、分隔符只能使用-\n4、不能以分隔符开头或结尾';
|
||||
return;
|
||||
}
|
||||
if (name === 'resources') {
|
||||
this.display = '[错误] 名字不合法\n1、不能使用resources作为名字';
|
||||
return;
|
||||
}
|
||||
// 创建前确认
|
||||
const createResponse = await Editor.Dialog.info('请确认', { detail: name, buttons: ['创建', '取消'], default: 0, cancel: 1 });
|
||||
if (createResponse.response == 1) {
|
||||
return;
|
||||
}
|
||||
this.display = '创建中';
|
||||
this.showLoading = true;
|
||||
if (!await utils_1.createFolderByUrl(folderPath, {
|
||||
readme: utils_1.getResReadme(folderName),
|
||||
meta: folderName === 'resources' ? utils_1.getResMeta('resources') : undefined,
|
||||
subFolders: [
|
||||
{
|
||||
folder: name,
|
||||
meta: folderName === 'res-bundle' ? utils_1.getResMeta('custom-bundle') : undefined
|
||||
}
|
||||
]
|
||||
})) {
|
||||
this.showLoading = false;
|
||||
this.display = '[错误] 创建失败';
|
||||
return;
|
||||
}
|
||||
this.showLoading = false;
|
||||
this.display = `[成功] 创建成功\n${folderPath}`;
|
||||
Editor.Message.send('assets', 'twinkle', folderPath);
|
||||
}
|
||||
},
|
||||
});
|
||||
45
extensions/app/engine/dist/panel/components/create-sound.js
vendored
Normal file
45
extensions/app/engine/dist/panel/components/create-sound.js
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const vue_1 = __importDefault(require("../../../../vue"));
|
||||
const utils_1 = require("../../utils");
|
||||
exports.default = vue_1.default.extend({
|
||||
template: utils_1.getResPanel('create-sound'),
|
||||
data() {
|
||||
return {
|
||||
display: '',
|
||||
typeSelects: ['音乐', '音效'],
|
||||
typeSelectIndex: 0,
|
||||
showLoading: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onChangeTypeSelect(index) {
|
||||
this.typeSelectIndex = Number(index);
|
||||
},
|
||||
async onClickCreate() {
|
||||
this.display = '创建中';
|
||||
this.showLoading = true;
|
||||
const rootPath = 'db://assets/app-bundle/app-sound';
|
||||
if (!await utils_1.createFolderByUrl(rootPath, {
|
||||
meta: utils_1.getResMeta('app-sound'),
|
||||
readme: utils_1.getResReadme('app-sound'),
|
||||
subFolders: [
|
||||
{
|
||||
folder: this.typeSelectIndex === 0 ? 'music' : 'effect',
|
||||
readme: utils_1.getResReadme(this.typeSelectIndex === 0 ? 'sound-music' : 'sound-effect')
|
||||
}
|
||||
]
|
||||
})) {
|
||||
this.showLoading = false;
|
||||
this.display = '[错误] 创建失败';
|
||||
return;
|
||||
}
|
||||
this.showLoading = false;
|
||||
this.display = `[成功] 创建成功\n${rootPath}`;
|
||||
Editor.Message.send('assets', 'twinkle', rootPath);
|
||||
}
|
||||
},
|
||||
});
|
||||
249
extensions/app/engine/dist/panel/components/create-view.js
vendored
Normal file
249
extensions/app/engine/dist/panel/components/create-view.js
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs_1 = require("fs");
|
||||
const path_1 = require("path");
|
||||
const vue_1 = __importDefault(require("../../../../vue"));
|
||||
const utils_1 = require("../../utils");
|
||||
/**
|
||||
* 获取脚本内容
|
||||
*/
|
||||
function getComScript(name = 'NewClass') {
|
||||
const isPage = name.toLowerCase().startsWith('page');
|
||||
const isPaper = name.toLowerCase().startsWith('paper');
|
||||
const basePath = isPaper ? '../../../../../../../extensions/app/assets/base/BaseView' : '../../../../../../extensions/app/assets/base/BaseView';
|
||||
return 'import { _decorator, Node } from \'cc\';\r\n' +
|
||||
'import BaseView from \'' + basePath + '\';\r\n' +
|
||||
`${isPage ? 'import { IMiniViewNames } from \'../../../../../app-builtin/app-admin/executor\';\r\n' : ''}` +
|
||||
'const { ccclass, property } = _decorator;\r\n' +
|
||||
'@ccclass(\'' + name + '\')\r\n' +
|
||||
'export class ' + name + ' extends BaseView {\r\n' +
|
||||
` ${isPage ? '// 子界面列表,数组顺序为子界面排列顺序\r\n' : ''}` +
|
||||
` ${isPage ? 'protected miniViews: IMiniViewNames = [];\r\n\r\n' : '\r\n'}` +
|
||||
' // 初始化的相关逻辑写在这\r\n' +
|
||||
' onLoad() {}\r\n\r\n' +
|
||||
' // 界面打开时的相关逻辑写在这(onShow可被多次调用-它与onHide不成对)\r\n' +
|
||||
' onShow(params: any) {\r\n' +
|
||||
` ${isPage ? 'this.showMiniViews({ views: this.miniViews });' : ''}\r\n` +
|
||||
' }\r\n\r\n' +
|
||||
' // 界面关闭时的相关逻辑写在这(已经关闭的界面不会触发onHide)\r\n' +
|
||||
' onHide(result: undefined) {\r\n' +
|
||||
` ${isPaper ? '' : '// app.manager.ui.show<' + name + '>({name: \'' + name + '\', onHide:(result) => { 接收到return的数据,并且有类型提示 }})\r\n'}` +
|
||||
` ${isPaper ? '' : 'return result;'}\r\n` +
|
||||
' }\r\n' +
|
||||
'}';
|
||||
}
|
||||
function getNaMetaUserData(name = 'new-class') {
|
||||
return Object.assign(Object.assign({}, utils_1.getResMeta('view-native')), { 'bundleName': `${name}` });
|
||||
}
|
||||
function getResMetaUserData(name = 'new-class') {
|
||||
return Object.assign(Object.assign({}, utils_1.getResMeta('view-resources')), { 'bundleName': `${name}-res` });
|
||||
}
|
||||
/**
|
||||
* UI类型(小写)
|
||||
*/
|
||||
const TypeSelects = ['page', 'paper', 'pop', 'top'];
|
||||
/**
|
||||
* 大驼峰UI名(带page前缀) => 串式UI目录名(不带page前缀)
|
||||
*/
|
||||
const PageNames = new Map();
|
||||
function updatePages() {
|
||||
PageNames.clear();
|
||||
// page目录
|
||||
const pageRootPath = path_1.join(Editor.Project.path, 'assets/app-bundle/app-view/page');
|
||||
// 读取page目录下所有文件
|
||||
const folderNames = fs_1.existsSync(pageRootPath) ? fs_1.readdirSync(pageRootPath) : [];
|
||||
// 大驼峰命名的UI名
|
||||
folderNames.forEach((folderName) => {
|
||||
// folderName为串式命名法
|
||||
const pagePath = path_1.join(pageRootPath, folderName);
|
||||
const isDirectory = fs_1.statSync(pagePath).isDirectory();
|
||||
if (isDirectory) {
|
||||
PageNames.set(`Page${utils_1.stringCase(folderName)}`, folderName);
|
||||
}
|
||||
});
|
||||
PageNames.set('通用', 'all');
|
||||
return Array.from(PageNames.keys());
|
||||
}
|
||||
exports.default = vue_1.default.extend({
|
||||
template: utils_1.getResPanel('create-view'),
|
||||
data() {
|
||||
return {
|
||||
showLoading: false,
|
||||
showSelectPage: false,
|
||||
showSelectGroup: true,
|
||||
inputName: '',
|
||||
display: '',
|
||||
typeSelects: TypeSelects,
|
||||
typeSelectIndex: 0,
|
||||
groupSelects: ['2D', '3D'],
|
||||
groupSelectIndex: 0,
|
||||
pageSelects: [],
|
||||
pageSelectIndex: 0,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onChangeGroupSelect(index) {
|
||||
this.groupSelectIndex = Number(index);
|
||||
},
|
||||
onChangeTypeSelect(index) {
|
||||
this.typeSelectIndex = Number(index);
|
||||
if (index == '0') {
|
||||
this.showSelectGroup = true;
|
||||
}
|
||||
else {
|
||||
this.showSelectGroup = false;
|
||||
}
|
||||
if (index == '1') {
|
||||
this.pageSelectIndex = 0;
|
||||
this.pageSelects = updatePages();
|
||||
this.showSelectPage = true;
|
||||
}
|
||||
else {
|
||||
this.showSelectPage = false;
|
||||
}
|
||||
},
|
||||
onChangePageSelect(index) {
|
||||
this.pageSelectIndex = Number(index);
|
||||
},
|
||||
async onClickCreate() {
|
||||
const isPage = this.typeSelectIndex == 0;
|
||||
const isPaper = this.typeSelectIndex == 1;
|
||||
// ui归属(大驼峰)
|
||||
const owner = this.pageSelects[this.pageSelectIndex];
|
||||
// ui类型(小写)
|
||||
const type = this.typeSelects[this.typeSelectIndex];
|
||||
// ui名字(串式)
|
||||
const name = this.inputName;
|
||||
if (/^[a-z][a-z0-9-]*[a-z0-9]+$/.test(name) === false) {
|
||||
this.display = '[错误] 名字不合法\n1、不能以数字开头\n2、不能有大写字母\n3、分隔符只能使用-\n4、不能以分隔符开头或结尾';
|
||||
return;
|
||||
}
|
||||
if (name === 'all' || name === 'page' || name === 'paper' || name === 'pop' || name === 'top') {
|
||||
this.display = '[错误] 名字不合法\n1、不能使用all、page、paper、pop、top作为名字';
|
||||
return;
|
||||
}
|
||||
const is3D = isPage && this.groupSelectIndex == 1;
|
||||
const ownerName = PageNames.get(owner);
|
||||
const uiName = isPaper ?
|
||||
`${utils_1.stringCase(type)}${utils_1.stringCase(ownerName)}${utils_1.stringCase(name)}` :
|
||||
`${utils_1.stringCase(type)}${utils_1.stringCase(name)}`;
|
||||
const bundleName = isPaper ?
|
||||
`${type}-${ownerName}-${name}` :
|
||||
`${type}-${name}`;
|
||||
const bundleFolderUrl = 'db://assets/app-bundle';
|
||||
const viewFolderUrl = `${bundleFolderUrl}/app-view`;
|
||||
const typeFolderUrl = `${viewFolderUrl}/${type}`;
|
||||
const uiFolderUrl = isPaper ?
|
||||
`${typeFolderUrl}/${ownerName}/${name}` :
|
||||
`${typeFolderUrl}/${name}`;
|
||||
const nativeUrl = `${uiFolderUrl}/native`;
|
||||
const resourcesUrl = `${uiFolderUrl}/resources`;
|
||||
const expansionUrl = `${nativeUrl}/expansion`;
|
||||
const scriptUrl = `${nativeUrl}/${uiName}.ts`;
|
||||
const prefabUrl = `${nativeUrl}/${uiName}.prefab`;
|
||||
const sceneUrl = `${nativeUrl}/${uiName}.scene`;
|
||||
const singleColorUrl = `${resourcesUrl}/singleColor.png`;
|
||||
// 创建前确认
|
||||
const createResponse = await Editor.Dialog.info('请确认', { detail: uiName, buttons: ['创建并打开', '仅创建', '取消'], default: 0, cancel: 2 });
|
||||
if (createResponse.response == 2) {
|
||||
return;
|
||||
}
|
||||
this.display = '创建中';
|
||||
this.showLoading = true;
|
||||
// 创建目录
|
||||
if (!await utils_1.createFolderByUrl(uiFolderUrl, { subPaths: ['native', 'resources', 'native/expansion'] })) {
|
||||
this.showLoading = false;
|
||||
this.display = `[错误] 创建目录失败\n${uiFolderUrl}`;
|
||||
return;
|
||||
}
|
||||
// 设置native分包
|
||||
await utils_1.delayFileExistsByUrl(`${nativeUrl}.meta`);
|
||||
const queryNativeMeta = await Editor.Message.request('asset-db', 'query-asset-meta', nativeUrl).catch(_ => null);
|
||||
if (!queryNativeMeta) {
|
||||
this.showLoading = false;
|
||||
this.display = '[错误] 设置native分包配置失败';
|
||||
return;
|
||||
}
|
||||
queryNativeMeta.userData = getNaMetaUserData(bundleName);
|
||||
await Editor.Message.request('asset-db', 'save-asset-meta', nativeUrl, JSON.stringify(queryNativeMeta)).catch(_ => null);
|
||||
// 设置resources分包
|
||||
await utils_1.delayFileExistsByUrl(`${resourcesUrl}.meta`);
|
||||
const queryResMeta = await Editor.Message.request('asset-db', 'query-asset-meta', resourcesUrl).catch(_ => null);
|
||||
if (!queryResMeta) {
|
||||
this.showLoading = false;
|
||||
this.display = '[错误] 设置resources分包配置失败';
|
||||
return;
|
||||
}
|
||||
queryResMeta.userData = getResMetaUserData(bundleName);
|
||||
await Editor.Message.request('asset-db', 'save-asset-meta', resourcesUrl, JSON.stringify(queryResMeta)).catch(_ => null);
|
||||
fs_1.writeFileSync(path_1.join(utils_1.convertUrlToPath(bundleFolderUrl), '.app-bundle.md'), utils_1.getResReadme('app-bundle'));
|
||||
fs_1.writeFileSync(path_1.join(utils_1.convertUrlToPath(viewFolderUrl), '.app-view.md'), utils_1.getResReadme('app-view'));
|
||||
fs_1.writeFileSync(path_1.join(utils_1.convertUrlToPath(typeFolderUrl), `.${type}.md`), `1、所有${type}类型UI的根目录\n2、如不再需要,可以直接删除此文件夹`);
|
||||
fs_1.writeFileSync(path_1.join(utils_1.convertUrlToPath(nativeUrl), '.native.md'), utils_1.getResReadme('view-native'));
|
||||
fs_1.writeFileSync(path_1.join(utils_1.convertUrlToPath(resourcesUrl), '.resources.md'), utils_1.getResReadme('view-resources'));
|
||||
fs_1.writeFileSync(path_1.join(utils_1.convertUrlToPath(expansionUrl), '.expansion.md'), utils_1.getResReadme('view-expansion'));
|
||||
if (isPaper) {
|
||||
fs_1.writeFileSync(path_1.join(utils_1.convertUrlToPath(`${typeFolderUrl}/${ownerName}`), `.${ownerName}.md`), (ownerName === 'all' ? '1、归属于全体Page' : `1、归属于Page${utils_1.stringCase(ownerName)}`) + '\n2、如不再需要,可以直接删除此文件夹');
|
||||
fs_1.writeFileSync(path_1.join(utils_1.convertUrlToPath(uiFolderUrl), `.${name}.md`), `${uiName}所在文件夹\n1、通过${ownerName === 'all' ? '在任意Page中配置miniViews属性并调用showMiniViews方法' : `在${owner}中配置miniViews属性并调用showMiniViews方法`}的方式加载\n2、如不再需要,可以直接删除此文件夹`);
|
||||
}
|
||||
else {
|
||||
fs_1.writeFileSync(path_1.join(utils_1.convertUrlToPath(uiFolderUrl), `.${name}.md`), `${uiName}所在文件夹\n1、通过app.manager.ui.show({ name:'${uiName}' })的方式加载\n2、如不再需要,可以直接删除此文件夹`);
|
||||
}
|
||||
// 创建script
|
||||
if (!fs_1.existsSync(utils_1.convertUrlToPath(scriptUrl))) {
|
||||
const createScriptResult = await Editor.Message.request('asset-db', 'create-asset', scriptUrl, getComScript(uiName)).catch(_ => null);
|
||||
if (!createScriptResult) {
|
||||
this.showLoading = false;
|
||||
this.display = `[错误] 创建脚本失败\n${scriptUrl}`;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 创建view
|
||||
if (!fs_1.existsSync(utils_1.convertUrlToPath(prefabUrl)) && !fs_1.existsSync(utils_1.convertUrlToPath(sceneUrl))) {
|
||||
if (is3D && isPage) {
|
||||
const createSceneResult = await Editor.Message.request('scene', 'execute-scene-script', {
|
||||
name: 'app',
|
||||
method: 'createScene',
|
||||
args: [uiName, sceneUrl]
|
||||
}).catch(_ => null);
|
||||
if (!createSceneResult) {
|
||||
this.showLoading = false;
|
||||
this.display = `[错误] 创建场景失败\n${sceneUrl}`;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const createPrefabResult = await Editor.Message.request('scene', 'execute-scene-script', {
|
||||
name: 'app',
|
||||
method: 'createPrefab',
|
||||
args: [uiName, prefabUrl, is3D]
|
||||
}).catch(_ => null);
|
||||
if (!createPrefabResult) {
|
||||
this.showLoading = false;
|
||||
this.display = `[错误] 创建预制体失败\n${prefabUrl}`;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.showLoading = false;
|
||||
this.display = `[成功] 创建成功\n${uiFolderUrl}`;
|
||||
Editor.Message.send('assets', 'twinkle', scriptUrl);
|
||||
// 是否打开
|
||||
if (createResponse.response == 0) {
|
||||
if (is3D) {
|
||||
Editor.Message.request('asset-db', 'open-asset', sceneUrl);
|
||||
}
|
||||
else {
|
||||
Editor.Message.request('asset-db', 'open-asset', prefabUrl);
|
||||
}
|
||||
Editor.Message.request('asset-db', 'open-asset', scriptUrl);
|
||||
}
|
||||
const base64 = 'iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAQMAAABIeJ9nAAAAA1BMVEX///+nxBvIAAAACklEQVQI12MAAgAABAABINItbwAAAABJRU5ErkJggg==';
|
||||
fs_1.writeFileSync(utils_1.convertUrlToPath(singleColorUrl), new Buffer(base64, 'base64'));
|
||||
Editor.Message.request('asset-db', 'refresh-asset', singleColorUrl).catch(_ => null);
|
||||
}
|
||||
}
|
||||
});
|
||||
29
extensions/app/engine/dist/panel/index.js
vendored
Normal file
29
extensions/app/engine/dist/panel/index.js
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs_1 = require("fs");
|
||||
const path_1 = require("path");
|
||||
const Assets = path_1.join(__dirname, '../../res/panel');
|
||||
const app_1 = __importDefault(require("./components/app"));
|
||||
module.exports = Editor.Panel.define({
|
||||
template: fs_1.readFileSync(path_1.join(Assets, 'index.html'), 'utf-8'),
|
||||
style: fs_1.readFileSync(path_1.join(Assets, 'styles/index.css'), 'utf-8'),
|
||||
$: {
|
||||
app: '#app'
|
||||
},
|
||||
listeners: {
|
||||
show() { console.log('show'); },
|
||||
hide() { console.log('hide'); },
|
||||
},
|
||||
methods: {},
|
||||
ready() {
|
||||
if (!this.$.app)
|
||||
return;
|
||||
const com = new app_1.default();
|
||||
com.$mount(this.$.app);
|
||||
},
|
||||
beforeClose() { },
|
||||
close() { },
|
||||
});
|
||||
73
extensions/app/engine/dist/scene.js
vendored
Normal file
73
extensions/app/engine/dist/scene.js
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.methods = exports.unload = exports.load = void 0;
|
||||
const path_1 = require("path");
|
||||
module.paths.push(path_1.join(Editor.App.path, 'node_modules'));
|
||||
function load() { }
|
||||
exports.load = load;
|
||||
function unload() { }
|
||||
exports.unload = unload;
|
||||
// 在其他扩展脚本中,我们可以使用如下代码调用 rotateCamera 函数
|
||||
// const options: ExecuteSceneScriptMethodOptions = {
|
||||
// name: scene.ts 所在的扩展包名, 如: App,
|
||||
// method: scene.ts 中定义的方法, 如: rotateCamera,
|
||||
// args: 参数,可选, 只传递json
|
||||
// };
|
||||
// const result = await Editor.Message.request('scene', 'execute-scene-script', options);
|
||||
exports.methods = {
|
||||
async createPrefab(fileName, fileUrl, is3D = false) {
|
||||
const { Node, js, Layers } = require('cc');
|
||||
const node = new Node(fileName);
|
||||
node.layer = is3D ? Layers.Enum.UI_3D : Layers.Enum.UI_2D;
|
||||
while (true) {
|
||||
const result = js.getClassByName(fileName);
|
||||
if (result)
|
||||
break;
|
||||
await new Promise((next) => {
|
||||
setTimeout(next, 100);
|
||||
});
|
||||
}
|
||||
const com = node.addComponent(fileName);
|
||||
com.resetInEditor && com.resetInEditor();
|
||||
const info = cce.Prefab.generatePrefabDataFromNode(node);
|
||||
node.destroy();
|
||||
return Editor.Message.request('asset-db', 'create-asset', fileUrl, info.prefabData || info);
|
||||
},
|
||||
async createScene(fileName, fileUrl) {
|
||||
const { SceneAsset, Scene, Node, js, Layers, Camera, DirectionalLight } = require('cc');
|
||||
while (true) {
|
||||
const result = js.getClassByName(fileName);
|
||||
if (result)
|
||||
break;
|
||||
await new Promise((next) => {
|
||||
setTimeout(next, 100);
|
||||
});
|
||||
}
|
||||
const scene = new Scene(fileName);
|
||||
// 根节点
|
||||
const node = new Node(fileName);
|
||||
node.layer = Layers.Enum.DEFAULT;
|
||||
node.parent = scene;
|
||||
// 相机
|
||||
const camera = new Node('Camera');
|
||||
camera.addComponent(Camera);
|
||||
camera.layer = Layers.Enum.DEFAULT;
|
||||
camera.parent = node;
|
||||
// 灯光
|
||||
const light = new Node('Light');
|
||||
light.addComponent(DirectionalLight);
|
||||
light.layer = Layers.Enum.DEFAULT;
|
||||
light.parent = node;
|
||||
const com = node.addComponent(fileName);
|
||||
com.resetInEditor && com.resetInEditor();
|
||||
const sceneAsset = new SceneAsset();
|
||||
sceneAsset.scene = scene;
|
||||
const info = EditorExtends.serialize(sceneAsset);
|
||||
camera.destroy();
|
||||
light.destroy();
|
||||
node.destroy();
|
||||
scene.destroy();
|
||||
sceneAsset.destroy();
|
||||
return Editor.Message.request('asset-db', 'create-asset', fileUrl, info);
|
||||
},
|
||||
};
|
||||
190
extensions/app/engine/dist/utils.js
vendored
Normal file
190
extensions/app/engine/dist/utils.js
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.delayFileExistsByUrl = exports.delay = exports.createFolderByUrl = exports.getProjectPath = exports.convertUrlToPath = exports.stringCaseNegate = exports.stringCase = exports.getResPanel = exports.getResMeta = exports.getResReadme = exports.getResJson = void 0;
|
||||
const fs_1 = require("fs");
|
||||
const path_1 = require("path");
|
||||
function getResJson(name) {
|
||||
const Assets = path_1.join(__dirname, '../res/json');
|
||||
const str = fs_1.readFileSync(path_1.join(Assets, `${name}.json`), 'utf-8');
|
||||
return str ? JSON.parse(str) : null;
|
||||
}
|
||||
exports.getResJson = getResJson;
|
||||
function getResReadme(name) {
|
||||
const Assets = path_1.join(__dirname, '../res/readme');
|
||||
return fs_1.readFileSync(path_1.join(Assets, `${name}.md`), 'utf-8');
|
||||
}
|
||||
exports.getResReadme = getResReadme;
|
||||
function getResMeta(name) {
|
||||
const Assets = path_1.join(__dirname, '../res/meta');
|
||||
const str = fs_1.readFileSync(path_1.join(Assets, `${name}.meta`), 'utf-8');
|
||||
return str ? JSON.parse(str) : null;
|
||||
}
|
||||
exports.getResMeta = getResMeta;
|
||||
function getResPanel(name) {
|
||||
const Assets = path_1.join(__dirname, '../res/panel');
|
||||
return fs_1.readFileSync(path_1.join(Assets, `components/${name}.html`), 'utf-8');
|
||||
}
|
||||
exports.getResPanel = getResPanel;
|
||||
/**
|
||||
* 将串式命名转成驼峰命名
|
||||
* @param str 串式字符串
|
||||
* @param lower 首字母是否小写(默认大写)
|
||||
* @returns
|
||||
*/
|
||||
function stringCase(str, lower = false) {
|
||||
str = str.replace(/-/g, '_');
|
||||
const arr = str.split('_');
|
||||
return arr.map(function (str, index) {
|
||||
if (index === 0 && lower) {
|
||||
return str.charAt(0).toLowerCase() + str.slice(1);
|
||||
}
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
}).join('');
|
||||
}
|
||||
exports.stringCase = stringCase;
|
||||
/**
|
||||
* 将驼峰命名转成串式命名
|
||||
* @param str 驼峰字符串
|
||||
* @returns
|
||||
*/
|
||||
function stringCaseNegate(str) {
|
||||
return str.replace(/[A-Z]/g, (searchStr, startIndex) => {
|
||||
if (startIndex === 0) {
|
||||
return searchStr.toLowerCase();
|
||||
}
|
||||
else {
|
||||
return '-' + searchStr.toLowerCase();
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.stringCaseNegate = stringCaseNegate;
|
||||
/**
|
||||
* db下的路径转换为真实路径
|
||||
*/
|
||||
function convertUrlToPath(url) {
|
||||
if (url.startsWith('db://assets')) {
|
||||
url = Editor.Utils.Path.join(Editor.Project.path, url.slice(5));
|
||||
}
|
||||
else if (url.startsWith('db://app')) {
|
||||
url = Editor.Utils.Path.join(Editor.Project.path, 'extensions/app/assets', url.slice(8));
|
||||
}
|
||||
else if (url.startsWith('db://pkg')) {
|
||||
url = Editor.Utils.Path.join(Editor.Project.path, 'extensions/pkg/node_modules', url.slice(8));
|
||||
}
|
||||
return url;
|
||||
}
|
||||
exports.convertUrlToPath = convertUrlToPath;
|
||||
/**
|
||||
* 获取程序路径
|
||||
*/
|
||||
function getProjectPath() {
|
||||
return Editor.Project.path;
|
||||
}
|
||||
exports.getProjectPath = getProjectPath;
|
||||
/**
|
||||
* 根据db下的路径创建目录(不是文件)
|
||||
* 如果已存在不会重复创建
|
||||
*/
|
||||
async function createFolderByUrl(url, opts) {
|
||||
let pathHead = 'db://assets';
|
||||
if (!url && !url.startsWith(pathHead)) {
|
||||
return false;
|
||||
}
|
||||
// 修剪path
|
||||
const pathTail = url.endsWith('/') ? url.slice(pathHead.length + 1, -1).trim() : url.slice(pathHead.length + 1).trim();
|
||||
// 每一层的路径
|
||||
const pathArr = pathTail.split('/');
|
||||
// 创建主目录
|
||||
for (let index = 0; index < pathArr.length; index++) {
|
||||
pathHead += '/' + pathArr[index];
|
||||
if (!fs_1.existsSync(convertUrlToPath(pathHead))) {
|
||||
const result = await Editor.Message.request('asset-db', 'create-asset', pathHead, null).catch(_ => null);
|
||||
if (!result)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// 主目录meta
|
||||
if (opts === null || opts === void 0 ? void 0 : opts.meta) {
|
||||
await delayFileExistsByUrl(`${url}.meta`);
|
||||
await delay(100);
|
||||
const queryMeta = await Editor.Message.request('asset-db', 'query-asset-meta', url).catch(_ => null);
|
||||
if (!queryMeta)
|
||||
return false;
|
||||
Object.assign(queryMeta.userData, opts.meta.userData);
|
||||
const result = await Editor.Message.request('asset-db', 'save-asset-meta', url, JSON.stringify(queryMeta)).catch(_ => null);
|
||||
if (!result)
|
||||
return false;
|
||||
}
|
||||
// 主目录readme
|
||||
if (opts === null || opts === void 0 ? void 0 : opts.readme) {
|
||||
fs_1.writeFileSync(path_1.join(convertUrlToPath(url), `.${path_1.basename(url)}.md`), opts.readme);
|
||||
}
|
||||
// 创建子目录
|
||||
if (opts === null || opts === void 0 ? void 0 : opts.subPaths) {
|
||||
await delay(100);
|
||||
for (let index = 0; index < opts.subPaths.length; index++) {
|
||||
const subPath = `${pathHead}/${opts.subPaths[index]}`;
|
||||
if (!fs_1.existsSync(convertUrlToPath(subPath))) {
|
||||
const result = await Editor.Message.request('asset-db', 'create-asset', subPath, null).catch(_ => null);
|
||||
if (!result)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (opts === null || opts === void 0 ? void 0 : opts.subFolders) {
|
||||
await delay(100);
|
||||
for (let index = 0; index < opts.subFolders.length; index++) {
|
||||
const subOpts = opts.subFolders[index];
|
||||
const subUrl = `${pathHead}/${subOpts.folder}`;
|
||||
// 判断是否存在
|
||||
if (!fs_1.existsSync(convertUrlToPath(subUrl))) {
|
||||
const result = await Editor.Message.request('asset-db', 'create-asset', subUrl, null).catch(_ => null);
|
||||
if (!result)
|
||||
return false;
|
||||
}
|
||||
// meta
|
||||
if (subOpts.meta) {
|
||||
await delayFileExistsByUrl(`${subUrl}.meta`);
|
||||
const queryMeta = await Editor.Message.request('asset-db', 'query-asset-meta', subUrl).catch(_ => null);
|
||||
if (!queryMeta)
|
||||
return false;
|
||||
Object.assign(queryMeta.userData, subOpts.meta.userData);
|
||||
const result = await Editor.Message.request('asset-db', 'save-asset-meta', subUrl, JSON.stringify(queryMeta)).catch(_ => null);
|
||||
if (!result)
|
||||
return false;
|
||||
}
|
||||
// readme
|
||||
if (subOpts.readme) {
|
||||
fs_1.writeFileSync(path_1.join(convertUrlToPath(subUrl), `.${path_1.basename(subUrl)}.md`), subOpts.readme);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
exports.createFolderByUrl = createFolderByUrl;
|
||||
function delay(time) {
|
||||
return new Promise((next) => {
|
||||
setTimeout(() => {
|
||||
next(null);
|
||||
}, time);
|
||||
});
|
||||
}
|
||||
exports.delay = delay;
|
||||
/**
|
||||
* 等待文件存在
|
||||
*/
|
||||
function delayFileExistsByUrl(url) {
|
||||
const path = convertUrlToPath(url);
|
||||
let timer = null;
|
||||
return new Promise((next) => {
|
||||
timer = setInterval(() => {
|
||||
if (fs_1.existsSync(path)) {
|
||||
if (timer)
|
||||
clearInterval(timer);
|
||||
timer = null;
|
||||
next(null);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
exports.delayFileExistsByUrl = delayFileExistsByUrl;
|
||||
Reference in New Issue
Block a user