1. 编辑器扩展 - 自动生成框架模板功能

2. 编辑器扩展 - Tinypng 纹理压缩功能
This commit is contained in:
dgflash
2024-10-19 15:37:21 +08:00
parent 1ed43d8b29
commit d62948939d
58 changed files with 2551 additions and 12 deletions

View File

@@ -0,0 +1,42 @@
// Type definitions for gettext-parser 4.0
// Project: https://github.com/smhg/gettext-parser
// Definitions by: Lorent Lempereur <https://github.com/looorent>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
declare module 'gettext-parser' {
export interface GetTextComment {
translator?: string;
reference?: string;
extracted?: string;
flag?: string;
previous?: string;
}
export interface GetTextTranslation {
msgctxt?: string | undefined;
msgid: string;
msgid_plural?: string;
msgstr: string[];
comments: GetTextComment;
}
export interface GetTextTranslations {
charset: string;
headers: { [headerName: string]: string };
translations: { [msgctxt: string]: { [msgId: string]: GetTextTranslation } };
}
export interface PoParser {
parse: (buffer: Buffer | string, defaultCharset?: string) => GetTextTranslations;
compile: (table: GetTextTranslations, options?: any) => Buffer;
createParseStream: (buffer: any, defaultCharset?: string) => any;
}
export interface MoParser {
parse: (buffer: Buffer | string, defaultCharset?: string) => GetTextTranslations;
compile: (table: GetTextTranslations, options?: any) => Buffer;
}
export const po: PoParser;
export const mo: MoParser;
}

View File

@@ -0,0 +1,104 @@
/*
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
declare const gfx: any;
declare const global: any;
interface Window {
[x: string]: any;
WebGL2RenderingContext: any;
sharedCanvas: any;
__canvas: any;
canvas: any;
XMLHttpRequest: any;
mozRequestAnimationFrame(callback: any, element?: any): any;
oRequestAnimationFrame(callback: any, element?: any): any;
msRequestAnimationFrame(callback: any, element?: any): any;
cancelRequestAnimationFrame(callback: any, element?: any): any;
msCancelRequestAnimationFrame(callback: any, element?: any): any;
mozCancelRequestAnimationFrame(callback: any, element?: any): any;
oCancelRequestAnimationFrame(callback: any, element?: any): any;
webkitCancelRequestAnimationFrame(callback: any, element?: any): any;
msCancelAnimationFrame(callback: any, element?: any): any;
mozCancelAnimationFrame(callback: any, element?: any): any;
ocancelAnimationFrame(callback: any, element?: any): any;
}
interface Document {
mozHidden: any;
msHidden: any;
webkitHidden: any;
}
interface HTMLElement {
content: any;
name: any;
}
declare type CompareFunction<T> = (a: T, b: T) => number;
declare type RecursivePartial<T> = {
[P in keyof T]?:
T[P] extends Array<infer U> ? Array<RecursivePartial<U>> :
T[P] extends ReadonlyArray<infer V> ? ReadonlyArray<RecursivePartial<V>> : RecursivePartial<T[P]>;
};
declare type TypedArray = Uint8Array | Uint8ClampedArray | Int8Array | Uint16Array |
Int16Array | Uint32Array | Int32Array | Float32Array | Float64Array;
declare type TypedArrayConstructor = Uint8ArrayConstructor | Uint8ClampedArrayConstructor |
Int8ArrayConstructor | Uint16ArrayConstructor | Int16ArrayConstructor | Uint32ArrayConstructor |
Int32ArrayConstructor | Float32ArrayConstructor | Float64ArrayConstructor;
declare interface IWritableArrayLike<T> {
readonly length: number;
[index: number]: T;
}
declare type Constructor<T = unknown> = new (...args: any[]) => T;
declare type AbstractedConstructor<T = unknown> = abstract new (...args: any[]) => T;
/**
* Alias of `Function` but suppress eslint warning.
* Please avoid using it and explicitly specify function signatures as possible.
*/
// eslint-disable-next-line @typescript-eslint/ban-types
declare type AnyFunction = Function;
declare type Mutable<T> = { -readonly [P in keyof T]: T[P] };
declare type Getter = () => any;
declare type Setter = (value: any) => void;
declare const Buffer: any;
declare type EnumAlias<EnumT> = EnumT[keyof EnumT];

View File

@@ -0,0 +1,37 @@
interface CCENodeEventMap {
added (node: import('cc').Node): void
change (node: import('cc').Node): void
removed (node: import('cc').Node): void
}
interface CCEComponentEventMap {
added (component: import('cc').Component): void,
removed (component: import('cc').Component): void,
}
declare class CCENodeManager extends EventEmitter {
on<T extends keyof CCENodeEventMap> (message: T, callback: CCENodeEventMap[T]): this;
off<T extends keyof CCENodeEventMap> (message: T, callback: CCENodeEventMap[T]): this;
}
declare class CCEComponentManager extends EventEmitter {
on<T extends keyof CCEComponentEventMap> (message: T, callback: CCEComponentEventMap[T]): this;
off<T extends keyof CCEComponentEventMap> (message: T, callback: CCEComponentEventMap[T]): this;
}
type CCE = {
Node: CCENodeManager,
Component: CCEComponentManager,
Prefab: {
generatePrefabDataFromNode(nodeUUID: string| cc.Node): string | null
}
};
declare const cce: CCE;
declare type UnPromise<T> = T extends Promise<infer R> ? R : T;
declare type UUID = string;
declare type Dump = { value: Record<string, { value: Dump | any, values?: any | Dump[], visible: boolean, readonly: boolean }> };
declare module 'cc/env' {
export const EDITOR: boolean;
export const BUILD: boolean;
}
declare const EditorExtends: any;

View File

@@ -0,0 +1,111 @@
declare namespace Intl {
type BCP47LanguageTag = string;
/**
* The locale matching algorithm to use.
*
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat#parameters).
*/
type ListFormatLocaleMatcher = 'lookup' | 'best fit';
/**
* The format of output message.
*
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat#parameters).
*/
type ListFormatType = 'conjunction' | 'disjunction' | 'unit';
/**
* The length of the formatted message.
*
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat#parameters).
*/
type ListFormatStyle = 'long' | 'short' | 'narrow';
/**
* An object with some or all properties of the `Intl.ListFormat` constructor `options` parameter.
*
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat#parameters).
*/
interface ListFormatOptions {
/** The locale matching algorithm to use. For information about this option, see [Intl page](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_negotiation). */
localeMatcher?: ListFormatLocaleMatcher | undefined;
/** The format of output message. */
type?: ListFormatType | undefined;
/** The length of the internationalized message. */
style?: ListFormatStyle | undefined;
}
interface ListFormat {
/**
* Returns a string with a language-specific representation of the list.
*
* @param list - An iterable object, such as an [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array).
*
* @throws `TypeError` if `list` includes something other than the possible values.
*
* @returns {string} A language-specific formatted string representing the elements of the list.
*
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/format).
*/
format(list: Iterable<string>): string;
/**
* Returns an Array of objects representing the different components that can be used to format a list of values in a locale-aware fashion.
*
* @param list - An iterable object, such as an [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array), to be formatted according to a locale.
*
* @throws `TypeError` if `list` includes something other than the possible values.
*
* @returns {{ type: "element" | "literal", value: string; }[]} An Array of components which contains the formatted parts from the list.
*
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/formatToParts).
*/
formatToParts(list: Iterable<string>): { type: 'element' | 'literal', value: string; }[];
}
const ListFormat: {
prototype: ListFormat;
/**
* Creates [Intl.ListFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat) objects that
* enable language-sensitive list formatting.
*
* @param locales - A string with a [BCP 47 language tag](http://tools.ietf.org/html/rfc5646), or an array of such strings.
* For the general form and interpretation of the `locales` argument,
* see the [`Intl` page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation).
*
* @param options - An [object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat#parameters)
* with some or all options of `ListFormatOptions`.
*
* @returns [Intl.ListFormatOptions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat) object.
*
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat).
*/
new(locales?: BCP47LanguageTag | BCP47LanguageTag[], options?: ListFormatOptions): ListFormat;
/**
* Returns an array containing those of the provided locales that are
* supported in list formatting without having to fall back to the runtime's default locale.
*
* @param locales - A string with a [BCP 47 language tag](http://tools.ietf.org/html/rfc5646), or an array of such strings.
* For the general form and interpretation of the `locales` argument,
* see the [`Intl` page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation).
*
* @param options - An [object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/supportedLocalesOf#parameters).
* with some or all possible options.
*
* @returns An array of strings representing a subset of the given locale tags that are supported in list
* formatting without having to fall back to the runtime's default locale.
*
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/supportedLocalesOf).
*/
supportedLocalesOf(locales: BCP47LanguageTag | BCP47LanguageTag[], options?: Pick<ListFormatOptions, 'localeMatcher'>): BCP47LanguageTag[];
};
type TextInfo = { direction: 'ltr' | 'rtl' }
interface Locale {
prototype: Locale
textInfo(): TextInfo
}
}

View File

@@ -0,0 +1,25 @@
export type PoHeader = {
/** This is the name and version of the package. */
'Project-Id-Version'?: string
/** (非必须) po 创建日期 */
'POT-Creation-Date'?: string
/** (非必须) po 修改日期*/
'PO-Revision-Date'?: string
/** 上一个翻译人员 */
'Last-Translator'?: string
/** 翻译团队的名称或者邮箱 */
'Language-Team'?: string
/** (非必须)要使 MIME 文档符合 RFC 2045需要此字段在顶级头中值为 1.0 */
'MIME-Version'?: '1.0'
/** 译文的语言 */
Language: string
/** Content-Type 定义了正文的类型我们实际上是通过这个标识来知道正文内是什么类型的文件。比如text/plain 表示的是无格式的文本正文text/html 表示的 Html 文档image/gif 表示的是 gif 格式的图片等等 */
'Content-Type'?: 'text/plain; charset=UTF-8'
/** 它表示了这个部分文档的编码方式。只有识别了这个说明,才能用正确的解码方式实现对其解码。 */
'Content-Transfer-Encoding'?: '8bit'
/** (非必须)复数的规则,*/
'Plural-Forms'?: string
}
export type IPluralRulesJson = Record<Intl.BCP47LanguageTag, [Intl.LDMLPluralRule]>

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,11 @@
/// <reference types="../../../@types/cc" />
import { Component, Label } from 'cc';
export default abstract class L10nComponent extends Component {
protected constructor();
get string(): string;
label?: Label | null;
protected onLoad(): void;
protected start(): void;
render(): void;
preview(value: string): void;
}

View File

@@ -0,0 +1,11 @@
import L10nComponent from './l10n-component';
export default class L10nLabel extends L10nComponent {
_key: string;
set key(value: string);
get key(): string;
_count: number;
set count(value: number);
get count(): number;
onLoad(): void;
render(): void;
}

View File

@@ -0,0 +1,13 @@
import { AssetManager } from 'cc';
import type { L10nManager } from './l10n-manager';
export default class AMPipeLineManager {
initialized: boolean;
l10n?: L10nManager;
_redirectTask: this['redirectTask'];
initAssetManager(l10n: L10nManager): void;
uninstall(): void;
redirectTask: (task: {
output: AssetManager.RequestItem[];
input: AssetManager.RequestItem[];
}) => void;
}

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,51 @@
import { FallbackLanguage, L10nValue } from './l10n-options';
export declare type FormattedValue = string;
export declare type TextInfoDirection = 'ltr' | 'rtl';
export interface StandardOption {
count?: number;
defaultValue?: L10nValue;
language?: Intl.BCP47LanguageTag;
fallbackLanguage?: FallbackLanguage;
}
export interface Template {
[key: string]: string | {
[key: string]: StandardOption;
};
}
export interface NumberFormatOptions extends Intl.NumberFormatOptions {
style?: 'decimal' | 'percent' | 'currency' | string;
/**
* 货币代码采用ISO 4217标准
* @see ISO4217Tag
*/
currency?: string;
currencySign?: 'standard' | 'accounting' | string;
currencyDisplay?: 'symbol' | 'code' | 'name' | string;
useGrouping?: boolean;
minimumIntegerDigits?: number;
minimumFractionDigits?: number;
maximumFractionDigits?: number;
minimumSignificantDigits?: number;
maximumSignificantDigits?: number;
}
export interface DateTimeFormatOptions {
localeMatcher?: 'best fit' | 'lookup' | undefined | string;
weekday?: 'long' | 'short' | 'narrow' | undefined | string;
era?: 'long' | 'short' | 'narrow' | undefined | string;
year?: 'numeric' | '2-digit' | undefined | string;
month?: 'numeric' | '2-digit' | 'long' | 'short' | 'narrow' | undefined | string;
day?: 'numeric' | '2-digit' | undefined | string;
hour?: 'numeric' | '2-digit' | undefined | string;
minute?: 'numeric' | '2-digit' | undefined | string;
second?: 'numeric' | '2-digit' | undefined | string;
timeZoneName?: 'long' | 'short' | undefined | string;
formatMatcher?: 'best fit' | 'basic' | undefined | string;
hour12?: boolean | undefined;
timeZone?: string | undefined;
}
export declare type RelativeTimeFormatUnit = 'second' | 'minute' | 'hour' | 'day' | 'month' | 'year' | string;
export interface RelativeTimeFormatOptions {
localeMatcher?: 'lookup' | 'best fit' | string;
style?: 'narrow' | 'short' | 'long' | string;
numeric?: 'auto' | 'always' | string;
}

View File

@@ -0,0 +1,10 @@
/**
* Intl formatting
*/
declare enum ICUType {
DateTime = 0,
Number = 1,
List = 2,
RelativeTime = 3,
}
export default ICUType;

View File

@@ -0,0 +1,5 @@
declare enum L10nListenEvent {
languageChanged = 'languageChanged',
onMissingKey = 'missingKey',
}
export default L10nListenEvent;

View File

@@ -0,0 +1,60 @@
import type { L10nOptions, ResourceData, L10nKey, L10nValue } from './l10n-options';
import { StandardOption, Template, TextInfoDirection } from './icu-options';
import L10nListenEvent from './l10n-listen-event';
import ResourceDataManager from './resource-data-manager';
import AMPipeLineManager from './asset-manager-initer';
export declare class L10nManager {
static LOCAL_STORAGE_LANGUAGE_KEY: string;
static DEFAULT_NAMESPACE: string;
static l10n: L10nManager;
/**
* @zh
* i18n 实例
* @en
* i18next instance
*/
private _intl?;
private _options;
private resourceList?;
private resourceBundle;
resourceDataManager: ResourceDataManager;
amPipeLineManager: AMPipeLineManager;
private constructor();
isInitialized(): boolean;
createIntl(options: L10nOptions): Promise<void>;
cloneIntl(options: L10nOptions): void;
reloadResourceData(): Promise<boolean>;
/** 初始化 i18next */
config(options: L10nOptions): void;
changeLanguage(language: Intl.BCP47LanguageTag): Promise<void>;
t(key: L10nKey, options?: StandardOption | Template): L10nValue;
/**
* 实验性功能暂不开放
* 数字类ICU
*/
private tn;
/**
* 实验性功能暂不开放
* 日期/时刻类ICU
*/
private td;
/**
* 实验性功能暂不开放
* 时长类ICU
*/
private tt;
/**
* 实验性功能暂不开放
* 数组类ICU
*/
private tl;
exists(key: L10nKey): boolean;
get currentLanguage(): Intl.BCP47LanguageTag;
get languages(): readonly Intl.BCP47LanguageTag[];
direction(language?: Intl.BCP47LanguageTag): TextInfoDirection;
on(event: L10nListenEvent, callback: (...args: any[]) => void): void;
off(event: L10nListenEvent, callback: (...args: any[]) => void): void;
getResourceBundle(language: string): ResourceData | undefined;
}
declare const l10n: L10nManager;
export default l10n;

View File

@@ -0,0 +1,78 @@
export declare type L10nKey = string;
export declare type L10nValue = string;
export interface ResourceList {
defaultLanguage?: Intl.BCP47LanguageTag;
fallbackLanguage?: Intl.BCP47LanguageTag;
languages: Intl.BCP47LanguageTag[];
}
export interface ResourceBundle {
[language: Intl.BCP47LanguageTag]: ResourceData;
}
export interface ResourceData {
[namespace: string]: ResourceItem;
}
export interface ResourceItem {
[key: string]: any;
}
export interface FallbackLanguageObjectList {
[language: string]: readonly string[];
}
export declare type FallbackLanguage = string | readonly string[] | FallbackLanguageObjectList | ((language: Intl.BCP47LanguageTag) => string | readonly string[] | FallbackLanguageObjectList);
export interface L10nOptions {
/**
* Logs info level to console output. Helps finding issues with loading not working.
* @default false
*/
/**
* Resources to initialize with (if not using loading or not appending using addResourceBundle)
* @default undefined
*/
resources?: ResourceBundle;
/**
* Language to use (overrides language detection)
*/
language?: Intl.BCP47LanguageTag;
/**
* Language to use if translations in user language are not available.
* @default same as language
*/
fallbackLanguage?: false | FallbackLanguage;
/**
* @default IntlManager.LOCAL_STORAGE_LANGUAGE_KEY
*/
localStorageLanguageKey?: string;
/**
* @zh
* 可以对key进行前置处理返回值应该是处理后的key
*
* @en
* Preprocess the key
*
* @param key
* @return string
* onBeforeProcessHandler
*/
beforeTranslate?: (key: L10nKey) => L10nValue;
/**
* @zh
* 对value进行后置处理返回值应该是处理后的value
*
* @en
* Postprocess the value, return the processed value
*
* @param key
* @param value
* @return string
*/
afterTranslate?: (key: string, value: string) => string;
/**
* Allows null values as valid translation
* @default true
*/
returnNull?: boolean;
/**
* Allows empty string as valid translation
* @default true
*/
returnEmptyString?: boolean;
}

View File

@@ -0,0 +1,5 @@
export declare const pluginName = 'Localization Editor';
export declare const mainName = 'localization-editor';
export declare const runtimeBundleName = 'l10n';
export declare const resourceListPath = 'resource-list';
export declare const resourceBundlePath = 'resource-bundle';

View File

@@ -0,0 +1,25 @@
/// <reference types="../../../@types/cc" />
import { AssetManager, JsonAsset } from 'cc';
import { ResourceBundle, ResourceList } from './l10n-options';
export default class ResourceDataManager {
readResourceList(): Promise<ResourceList>;
readResourceBundle(tags: Intl.BCP47LanguageTag[]): Promise<ResourceBundle>;
/**
* 编辑器模式下使用
* @param locales
*/
editorLoad(locales: Intl.BCP47LanguageTag[]): Promise<ResourceBundle | undefined>;
/**
* 构建后运行时使用
* @param fileName
*/
runtimeLoad<T>(fileName: string): Promise<T | undefined>;
/**
* 浏览器预览使用
* @param urlPath
*/
previewLoad<T>(urlPath: string): Promise<T | undefined>;
checkBundle(bundleName: string): Promise<boolean>;
getBundle(bundleName: string): Promise<AssetManager.Bundle | undefined>;
getResource(bundle: AssetManager.Bundle, resourceName: string): Promise<JsonAsset | undefined>;
}

View File

@@ -0,0 +1,5 @@
import l10n, { L10nManager } from './core/l10n-manager';
import L10nListenEvent from './core/l10n-listen-event';
import L10nLabel from './components/l10n-label';
export type { L10nKey, L10nValue, ResourceList, ResourceBundle, ResourceData, ResourceItem, FallbackLanguageObjectList, FallbackLanguage, L10nOptions } from './core/l10n-options';
export { l10n, L10nManager, L10nLabel, L10nListenEvent };

View File

@@ -0,0 +1 @@
import '@formatjs/intl-datetimeformat';

View File

@@ -0,0 +1 @@
import '@formatjs/intl-displaynames';

View File

@@ -0,0 +1 @@
import '@formatjs/intl-listformat';

View File

@@ -0,0 +1 @@
import '@formatjs/intl-locale';

View File

@@ -0,0 +1 @@
import '@formatjs/intl-numberformat';

View File

@@ -0,0 +1 @@
import 'intl-pluralrules';

View File

@@ -0,0 +1 @@
import '@formatjs/intl-relativetimeformat';

View File

@@ -0,0 +1 @@
import '@formatjs/intl-getcanonicallocales';

View File

@@ -24,7 +24,7 @@ import { GameManager } from "./game/GameManager";
import { LayerManager } from "./gui/layer/LayerManager"; import { LayerManager } from "./gui/layer/LayerManager";
/** 框架版本号 */ /** 框架版本号 */
export var version: string = "1.3.3"; export var version: string = "2.0.0";
/** 框架核心模块访问入口 */ /** 框架核心模块访问入口 */
export class oops { export class oops {

83
dist/assets-menu.js vendored Normal file
View File

@@ -0,0 +1,83 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.onAssetMenu = void 0;
const tinypng_1 = require("./tinypng");
/** 资源栏右键菜单 */
function onAssetMenu(assetInfo) {
return [
{
label: 'i18n:oops-framework.name',
submenu: [
{
label: `i18n:oops-framework.script`,
submenu: [
{
label: `i18n:oops-framework.createGameComponent`,
async click() {
localStorage.setItem('create_path', assetInfo.file);
localStorage.setItem('create_type', "GameComponent");
Editor.Panel.open("oops-framework.set_file_name");
},
},
{
type: `separator`,
},
{
label: `i18n:oops-framework.createModule`,
click() {
localStorage.setItem('create_path', assetInfo.file);
localStorage.setItem('create_type', "Module");
Editor.Panel.open("oops-framework.set_file_name");
},
},
{
label: `i18n:oops-framework.createModel`,
click() {
localStorage.setItem('create_path', assetInfo.file);
localStorage.setItem('create_type', "Model");
Editor.Panel.open("oops-framework.set_file_name");
},
},
{
label: `i18n:oops-framework.createBll`,
click() {
localStorage.setItem('create_path', assetInfo.file);
localStorage.setItem('create_type', "Bll");
Editor.Panel.open("oops-framework.set_file_name");
},
},
{
label: `i18n:oops-framework.createView`,
click() {
localStorage.setItem('create_path', assetInfo.file);
localStorage.setItem('create_type', "View");
Editor.Panel.open("oops-framework.set_file_name");
},
},
{
label: `i18n:oops-framework.createViewMvvm`,
click() {
localStorage.setItem('create_path', assetInfo.file);
localStorage.setItem('create_type', "ViewMvvm");
Editor.Panel.open("oops-framework.set_file_name");
},
},
]
},
{
label: `i18n:oops-framework.tools`,
submenu: [
{
label: `i18n:oops-framework.tools_compress`,
click() {
(0, tinypng_1.compress)(assetInfo.file);
},
}
]
}
],
},
];
}
exports.onAssetMenu = onAssetMenu;
;

120
dist/create-script.js vendored Normal file
View File

@@ -0,0 +1,120 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createScript = exports.createScriptBll = exports.createScriptModule = exports.createView = void 0;
const fs_1 = require("fs");
const path_1 = __importDefault(require("path"));
/** 写入文件 */
function createView(directoryPath, fileName, content, isEcsComp = true) {
return new Promise(async (resolve, reject) => {
// 创建脚本
let className = fileName + "View";
let scriptUrl = "";
if (isEcsComp) {
scriptUrl = path_1.default.join(directoryPath, fileName) + "ViewComp.ts";
}
else {
scriptUrl = path_1.default.join(directoryPath, fileName) + "View.ts";
}
if (!(0, fs_1.existsSync)(scriptUrl)) {
content = content.replace(/<%Name%>/g, className);
await Editor.Message.request('asset-db', 'create-asset', scriptUrl, content);
}
// 创建预制
let prefabUrl = path_1.default.join(directoryPath, fileName) + ".prefab";
if (!(0, fs_1.existsSync)(prefabUrl)) {
if (isEcsComp)
className = className + "Comp";
await Editor.Message.request('scene', 'execute-scene-script', {
name: "oops-framework",
method: 'createPrefab',
args: [fileName, className, prefabUrl]
});
}
// 闪烁提示新创建的脚本文件
Editor.Message.send('assets', 'twinkle', scriptUrl);
// 打开脚本
Editor.Message.request('asset-db', 'open-asset', scriptUrl);
// 打开预制
Editor.Message.request('asset-db', 'open-asset', prefabUrl);
resolve();
});
}
exports.createView = createView;
function createScriptModule(directoryPath, fileName, content) {
return new Promise(async (resolve, reject) => {
// 创建目录
let pathName = fileName.toLowerCase();
let pathModule = path_1.default.join(directoryPath, pathName);
if (!(0, fs_1.existsSync)(pathModule)) {
await Editor.Message.request('asset-db', 'create-asset', pathModule, null);
}
let subPathView = path_1.default.join(pathModule, "view");
if (!(0, fs_1.existsSync)(subPathView)) {
await Editor.Message.request('asset-db', 'create-asset', subPathView, null);
}
let subPathBll = path_1.default.join(pathModule, "bll");
if (!(0, fs_1.existsSync)(subPathBll)) {
await Editor.Message.request('asset-db', 'create-asset', subPathBll, null);
}
let subPathModel = path_1.default.join(pathModule, "model");
if (!(0, fs_1.existsSync)(subPathModel)) {
await Editor.Message.request('asset-db', 'create-asset', subPathModel, null);
}
// 创建脚本
let scriptUrl = path_1.default.join(pathModule, fileName) + ".ts";
if (!(0, fs_1.existsSync)(scriptUrl)) {
content = content.replace(/<%Name%>/g, fileName);
await Editor.Message.request('asset-db', 'create-asset', scriptUrl, content);
}
// 闪烁提示新创建的脚本文件
Editor.Message.send('assets', 'twinkle', scriptUrl);
// 打开脚本
Editor.Message.request('asset-db', 'open-asset', scriptUrl);
resolve();
});
}
exports.createScriptModule = createScriptModule;
/** 创建脚本 */
function createScriptBll(directoryPath, fileName, content, moduleName) {
return new Promise(async (resolve, reject) => {
let scriptUrl = path_1.default.join(directoryPath, fileName) + ".ts";
// 创建脚本
if (!(0, fs_1.existsSync)(scriptUrl)) {
content = content.replace(/<%Name%>/g, fileName);
content = content.replace(/<%ModuleName%>/g, moduleName);
await Editor.Message.request('asset-db', 'create-asset', scriptUrl, content);
}
// 闪烁提示新创建的脚本文件
Editor.Message.send('assets', 'twinkle', scriptUrl);
// 打开脚本
Editor.Message.request('asset-db', 'open-asset', scriptUrl);
resolve();
});
}
exports.createScriptBll = createScriptBll;
/** 创建业务层脚本 */
function createScript(directoryPath, fileName, content, isEcsComp = true) {
return new Promise(async (resolve, reject) => {
let scriptUrl = "";
if (isEcsComp) {
scriptUrl = path_1.default.join(directoryPath, fileName) + "Comp.ts";
}
else {
scriptUrl = path_1.default.join(directoryPath, fileName) + ".ts";
}
// 创建脚本
if (!(0, fs_1.existsSync)(scriptUrl)) {
content = content.replace(/<%Name%>/g, fileName);
await Editor.Message.request('asset-db', 'create-asset', scriptUrl, content);
}
// 闪烁提示新创建的脚本文件
Editor.Message.send('assets', 'twinkle', scriptUrl);
// 打开脚本
Editor.Message.request('asset-db', 'open-asset', scriptUrl);
resolve();
});
}
exports.createScript = createScript;

116
dist/default/index.js vendored Normal file
View File

@@ -0,0 +1,116 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const vue_1 = require("vue");
const create_script_1 = require("../create-script");
const GameComponent_1 = require("../template/GameComponent");
const Module_1 = require("../template/Module");
const ModuleBll_1 = require("../template/ModuleBll");
const ModuleModel_1 = require("../template/ModuleModel");
const ModuleView_1 = require("../template/ModuleView");
const ModuleViewVM_1 = require("../template/ModuleViewVM");
const panelDataMap = new WeakMap();
module.exports = Editor.Panel.define({
listeners: {
show() { console.log('show'); },
hide() { console.log('hide'); },
},
template: (0, fs_extra_1.readFileSync)((0, path_1.join)(__dirname, '../../static/template/default/index.html'), 'utf-8'),
style: (0, fs_extra_1.readFileSync)((0, path_1.join)(__dirname, '../../static/style/default/index.css'), 'utf-8'),
$: {
app: '#app',
},
ready() {
let filename = "Default";
let type = localStorage.getItem('create_type');
localStorage.removeItem('create_type');
let path = localStorage.getItem('create_path');
localStorage.removeItem('create_path');
let title = "???";
let showModule = false;
let moduleName = "ModuleName";
switch (type) {
case "GameComponent":
title = `i18n:oops-framework.createGameComponent`;
break;
case "Module":
title = `i18n:oops-framework.createModule`;
break;
case "Model":
title = `i18n:oops-framework.createModel`;
break;
case "Bll":
title = `i18n:oops-framework.createBll`;
showModule = true;
break;
case "View":
title = `i18n:oops-framework.createView`;
break;
case "ViewMvvm":
title = `i18n:oops-framework.createViewMvvm`;
break;
}
// 创建框架配置界面
if (this.$.app) {
const app = (0, vue_1.createApp)({});
app.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('ui-');
app.component('MyConfig', {
template: (0, fs_extra_1.readFileSync)((0, path_1.join)(__dirname, '../../static/template/vue/set_file_name.html'), 'utf-8'),
data() {
return {
title: title,
filename: filename,
showModule: showModule
};
},
methods: {
// 记录输入的文件名
onInputName(event) {
filename = event.target.value;
},
onModuleName(event) {
moduleName = event.target.value;
},
// 创建文件
async onConfirm() {
if (filename.trim().length == 0) {
await Editor.Dialog.info('请输入文件名');
return;
}
switch (type) {
case "GameComponent":
await (0, create_script_1.createView)(path, filename, GameComponent_1.TemplateGameComponent, false);
break;
case "Module":
await (0, create_script_1.createScriptModule)(path, filename, Module_1.TemplateModule);
break;
case "Model":
await (0, create_script_1.createScript)(path, filename, ModuleModel_1.TemplateModel);
break;
case "Bll":
await (0, create_script_1.createScriptBll)(path, filename, ModuleBll_1.TemplateBll, moduleName);
break;
case "View":
await (0, create_script_1.createView)(path, filename, ModuleView_1.TemplateView);
break;
case "ViewMvvm":
await (0, create_script_1.createView)(path, filename, ModuleViewVM_1.TemplateViewMvvm);
break;
}
close();
}
},
});
app.mount(this.$.app);
panelDataMap.set(this, app);
}
},
beforeClose() { },
close() {
const app = panelDataMap.get(this);
if (app) {
app.unmount();
}
},
});

2
dist/main.js vendored
View File

@@ -46,5 +46,5 @@ exports.methods = {
/** 点亮 Github 星星 */ /** 点亮 Github 星星 */
github() { github() {
electron_1.shell.openExternal('https://github.com/dgflash/oops-framework'); electron_1.shell.openExternal('https://github.com/dgflash/oops-framework');
}, }
}; };

35
dist/scene.js vendored Normal file
View File

@@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.methods = exports.unload = exports.load = void 0;
function load() { }
exports.load = load;
function unload() { }
exports.unload = unload;
// 在其他扩展脚本中,我们可以使用如下代码调用 rotateCamera 函数
// const options: ExecuteSceneScriptMethodOptions = {
// name: scene.ts 所在的扩展包名, 如: App,
// method: scene.ts 中定义的方法, 如: createPrefab,
// args: 参数,可选, 只传递json
// };
// const result = await Editor.Message.request('scene', 'execute-scene-script', options);
exports.methods = {
/** 创建视图层制 */
async createPrefab(fileName, className, prefabUrl) {
const { Node, js, Layers } = require('cc');
const node = new Node(fileName);
node.layer = Layers.Enum.UI_2D;
while (true) {
const result = js.getClassByName(className);
if (result)
break;
await new Promise((next) => {
setTimeout(next, 100);
});
}
const com = node.addComponent(className);
com.resetInEditor && com.resetInEditor();
const info = cce.Prefab.generatePrefabDataFromNode(node);
node.destroy();
return Editor.Message.request('asset-db', 'create-asset', prefabUrl, info.prefabData || info);
}
};

15
dist/template/GameComponent.js vendored Normal file
View File

@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TemplateGameComponent = void 0;
exports.TemplateGameComponent = `import { _decorator } from 'cc';
import { GameComponent } from "db://oops-framework/module/common/GameComponent";
const { ccclass, property } = _decorator;
/** 显示对象控制 */
@ccclass('<%Name%>')
export class <%Name%> extends GameComponent {
protected start() {
}
}`;

22
dist/template/Module.js vendored Normal file
View File

@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TemplateModule = void 0;
exports.TemplateModule = `import { ecs } from "db://oops-framework/libs/ecs/ECS";
/** <%Name%> 模块 */
@ecs.register('<%Name%>')
export class <%Name%> extends ecs.Entity {
/** ---------- 数据层 ---------- */
// <%Name%>Model!: <%Name%>ModelComp;
/** ---------- 业务层 ---------- */
// <%Name%>Bll!: <%Name%>BllComp;
/** ---------- 视图层 ---------- */
// <%Name%>View!: <%Name%>ViewComp;
/** 初始添加的数据层组件 */
protected init() {
// this.addComponents<ecs.Comp>();
}
}`;

27
dist/template/ModuleBll.js vendored Normal file
View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TemplateBll = void 0;
exports.TemplateBll = `import { ecs } from "db://oops-framework/libs/ecs/ECS";
/** 业务输入参数 */
@ecs.register('<%Name%>')
export class <%Name%>Comp extends ecs.Comp {
/** 业务层组件移除时,重置所有数据为默认值 */
reset() {
}
}
/** 业务逻辑处理对象 */
@ecs.register('<%ModuleName%>')
export class <%Name%>System extends ecs.ComblockSystem implements ecs.IEntityEnterSystem {
filter(): ecs.IMatcher {
return ecs.allOf(<%Name%>Comp);
}
entityEnter(e: ecs.Entity): void {
// 注:自定义业务逻辑
e.remove(<%Name%>Comp);
}
}`;

15
dist/template/ModuleModel.js vendored Normal file
View File

@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TemplateModel = void 0;
exports.TemplateModel = `import { ecs } from "db://oops-framework/libs/ecs/ECS";
/** 数据层对象 */
@ecs.register('<%Name%>')
export class <%Name%>Comp extends ecs.Comp {
id: number = -1;
/** 数据层组件移除时,重置所有数据为默认值 */
reset() {
this.id = -1;
}
}`;

23
dist/template/ModuleView.js vendored Normal file
View File

@@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TemplateView = void 0;
exports.TemplateView = `import { _decorator } from "cc";
import { ecs } from "db://oops-framework/libs/ecs/ECS";
import { CCComp } from "db://oops-framework/module/common/CCComp";
const { ccclass, property } = _decorator;
/** 视图层对象 */
@ccclass('<%Name%>Comp')
@ecs.register('<%Name%>', false)
export class <%Name%>Comp extends CCComp {
/** 视图层逻辑代码分离演示 */
start() {
// const entity = this.ent as ecs.Entity; // ecs.Entity 可转为当前模块的具体实体对象
}
/** 视图对象通过 ecs.Entity.remove(<%Name%>Comp) 删除组件是触发组件处理自定义释放逻辑 */
reset() {
this.node.destroy();
}
}`;

26
dist/template/ModuleViewVM.js vendored Normal file
View File

@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TemplateViewMvvm = void 0;
exports.TemplateViewMvvm = `import { _decorator } from "cc";
import { ecs } from "db://oops-framework/libs/ecs/ECS";
import { CCVMParentComp } from "db://oops-framework/module/common/CCVMParentComp";
const { ccclass, property } = _decorator;
/** 视图层对象 - 支持 MVVM 框架的数据绑定 */
@ccclass('<%Name%>Comp')
@ecs.register('<%Name%>', false)
export class <%Name%>Comp extends CCVMParentComp {
/** 脚本控制的界面 MVVM 框架绑定数据 */
data: any = {};
/** 视图层逻辑代码分离演示 */
start() {
// const entity = this.ent as ecs.Entity; // ecs.Entity 可转为当前模块的具体实体对象
}
/** 视图对象通过 ecs.Entity.remove(<%Name%>Comp) 删除组件是触发组件处理自定义释放逻辑 */
reset() {
this.node.destroy();
}
}`;

160
dist/tinypng.js vendored Normal file
View File

@@ -0,0 +1,160 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.compress = void 0;
const fs_1 = __importDefault(require("fs"));
const https_1 = __importDefault(require("https"));
const path_1 = __importDefault(require("path"));
const url_1 = __importDefault(require("url"));
const exts = ['.png', '.jpg', '.jpeg'];
const max = 5200000;
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'
}
};
function compress(filePath) {
if (!fs_1.default.existsSync(filePath)) {
console.log(`路径不存在:${filePath}`);
return;
}
const fileName = path_1.default.basename(filePath);
if (!fs_1.default.statSync(filePath).isDirectory()) {
if (exts.includes(path_1.default.extname(filePath))) {
console.log(`[${fileName}] 压缩中...`);
fileTinyUpload(filePath)
.then(data => {
console.log(`[1/1] [${fileName}] 压缩成功,原始: ${toSize(data.input.size)},压缩: ${toSize(data.output.size)},压缩比: ${toPercent(data.output.ratio)}`);
})
.catch(err => {
console.log(`[1/1] [${fileName}] 压缩失败!报错:${err}`);
});
}
else {
console.log(`[${fileName}] 压缩失败!报错:只支持 png、jpg 与 jpeg 格式`);
}
}
else {
let totalCount = 0;
let processedCount = 0;
fileEach(filePath, (filePathInDir) => {
totalCount++;
const relativePath = path_1.default.relative(filePath, filePathInDir);
fileTinyUpload(filePathInDir)
.then(data => {
console.log(`[${++processedCount}/${totalCount}] [${relativePath}] 压缩成功,原始: ${toSize(data.input.size)},压缩: ${toSize(data.output.size)},压缩比: ${toPercent(data.output.ratio)}`);
})
.catch(err => {
console.log(`[${++processedCount}/${totalCount}] [${relativePath}] 压缩失败!报错:${err}`);
});
});
}
}
exports.compress = compress;
function getRandomIP() {
return Array.from(Array(4)).map(() => Math.floor(255 * Math.random())).join('.');
}
function fileEach(dir, callback) {
fs_1.default.readdir(dir, (err, files) => {
if (err) {
console.error(err);
return;
}
files.forEach((file) => {
const filePath = path_1.default.join(dir, file);
fs_1.default.stat(filePath, (statErr, stats) => {
if (statErr) {
console.error(statErr);
return;
}
if (stats.isDirectory()) {
fileEach(filePath, callback);
}
else {
if (stats.size <= max && stats.isFile() && exts.includes(path_1.default.extname(file))) {
callback(filePath);
}
}
});
});
});
}
function fileUpload(filePath) {
return new Promise((resolve, reject) => {
options.headers['X-Forwarded-For'] = getRandomIP();
const req = https_1.default.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
try {
const result = JSON.parse(data);
if (result.error) {
reject(result.message);
}
else {
resolve(result);
}
}
catch (parseErr) {
reject(parseErr);
}
});
});
req.write(fs_1.default.readFileSync(filePath), 'binary');
req.on('error', err => {
reject(err);
});
req.end();
});
}
function fileUpdate(filePath, data) {
return new Promise((resolve, reject) => {
const urlObj = new url_1.default.URL(data.output.url);
const req = https_1.default.request(urlObj, (res) => {
let body = '';
res.setEncoding('binary');
res.on('data', (chunk) => {
body += chunk;
});
res.on('end', () => {
fs_1.default.writeFile(filePath, body, 'binary', (err) => {
if (err) {
reject(err);
}
else {
resolve(data);
}
});
});
});
req.on('error', (err) => {
reject(err);
});
req.end();
});
}
function fileTinyUpload(filePath) {
return fileUpload(filePath).then(data => fileUpdate(filePath, data));
}
function toSize(size) {
if (size < 1024)
return size + 'B';
else if (size < 1048576)
return (size / 1024).toFixed(2) + 'KB';
else
return (size / 1024 / 1024).toFixed(2) + 'MB';
}
function toPercent(ratio) {
return (100 * ratio).toFixed(2) + '%';
}

View File

@@ -5,8 +5,19 @@ module.exports = {
document: "Document", document: "Document",
document_api: "API Document", document_api: "API Document",
document_oops: "Framework Document", document_oops: "Framework Document",
tutorial: "Tutorial Project",
solution: "Solution", solution: "Solution",
gitee: "Light up gitee stars", gitee: "Light up gitee stars",
github: "Light up github stars", github: "Light up gitee stars",
log: "Update Log", log: "Update Log",
script: "Script",
createGameComponent: "Create display object template",
createModule: "Create ECS module",
createModel: "Create ECS data layer script",
createBll: "Create ECS business layer script",
createView: "Create ECS view layer script",
createViewMvvm: "Create ECS view layer script - MVVM",
tools: "Tools",
tools_compress: "Image Compression",
panel_create_file: "Create Framework Template",
}; };

View File

@@ -1,9 +1,3 @@
/*
* @Author: dgflash
* @Date: 2022-06-14 19:32:16
* @LastEditors: dgflash
* @LastEditTime: 2022-06-14 19:41:18
*/
"use strict"; "use strict";
module.exports = { module.exports = {
description: "Oops Framework 基于 Cocos Creator 3.x 开发的一款游戏框架", description: "Oops Framework 基于 Cocos Creator 3.x 开发的一款游戏框架",
@@ -11,8 +5,19 @@ module.exports = {
document: "文档", document: "文档",
document_api: "API 文档", document_api: "API 文档",
document_oops: "框架文档", document_oops: "框架文档",
tutorial: "教程项目",
solution: "解决方案", solution: "解决方案",
gitee: "点亮 Gitee 星星", gitee: "点亮 Gitee 星星",
github: "点亮 Github 星星", github: "点亮 Github 星星",
log: "更新日志", log: "更新日志",
script: "脚本",
createGameComponent: "创建显示对象模板",
createModule: "创建 ECS 模块",
createModel: "创建 ECS 数据层脚本",
createBll: "创建 ECS 业务层脚本",
createView: "创建 ECS 视图层脚本",
createViewMvvm: "创建 ECS 视图层脚本 - MVVM ",
tools: "工具",
tools_compress: "图片压缩",
panel_create_file: "创建框架模板"
}; };

545
package-lock.json generated
View File

@@ -7,12 +7,81 @@
"": { "": {
"name": "oops-framework", "name": "oops-framework",
"version": "1.0.0", "version": "1.0.0",
"dependencies": {
"fs-extra": "^10.0.0",
"vue": "^3.1.4"
},
"devDependencies": { "devDependencies": {
"@cocos/creator-types": "^3.8.2",
"@types/fs-extra": "^9.0.5",
"@types/node": "^20.16.12", "@types/node": "^20.16.12",
"typedoc": "^0.23.24", "typedoc": "^0.23.24",
"typescript": "^4.8.2" "typescript": "^4.8.2"
} }
}, },
"node_modules/@babel/helper-string-parser": {
"version": "7.25.7",
"resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz",
"integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.25.7",
"resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz",
"integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
"version": "7.25.8",
"resolved": "https://mirrors.cloud.tencent.com/npm/@babel/parser/-/parser-7.25.8.tgz",
"integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==",
"dependencies": {
"@babel/types": "^7.25.8"
},
"bin": {
"parser": "bin/babel-parser.js"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@babel/types": {
"version": "7.25.8",
"resolved": "https://mirrors.cloud.tencent.com/npm/@babel/types/-/types-7.25.8.tgz",
"integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==",
"dependencies": {
"@babel/helper-string-parser": "^7.25.7",
"@babel/helper-validator-identifier": "^7.25.7",
"to-fast-properties": "^2.0.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@cocos/creator-types": {
"version": "3.8.4",
"resolved": "https://mirrors.cloud.tencent.com/npm/@cocos/creator-types/-/creator-types-3.8.4.tgz",
"integrity": "sha512-z+8qx726Zl/8rUUpbLjVAiNPn4XweRACEaY1vHeR3EHIcSQ9wtFlIFd2SZX5rOE8lt1S95nxv8OeLYXfbN4/2Q==",
"dev": true
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
},
"node_modules/@types/fs-extra": {
"version": "9.0.13",
"resolved": "https://mirrors.cloud.tencent.com/npm/@types/fs-extra/-/fs-extra-9.0.13.tgz",
"integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "20.16.12", "version": "20.16.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@types/node/-/node-20.16.12.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/@types/node/-/node-20.16.12.tgz",
@@ -22,6 +91,97 @@
"undici-types": "~6.19.2" "undici-types": "~6.19.2"
} }
}, },
"node_modules/@vue/compiler-core": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-core/-/compiler-core-3.5.12.tgz",
"integrity": "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==",
"dependencies": {
"@babel/parser": "^7.25.3",
"@vue/shared": "3.5.12",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.0"
}
},
"node_modules/@vue/compiler-dom": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-dom/-/compiler-dom-3.5.12.tgz",
"integrity": "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==",
"dependencies": {
"@vue/compiler-core": "3.5.12",
"@vue/shared": "3.5.12"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-sfc/-/compiler-sfc-3.5.12.tgz",
"integrity": "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==",
"dependencies": {
"@babel/parser": "^7.25.3",
"@vue/compiler-core": "3.5.12",
"@vue/compiler-dom": "3.5.12",
"@vue/compiler-ssr": "3.5.12",
"@vue/shared": "3.5.12",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.11",
"postcss": "^8.4.47",
"source-map-js": "^1.2.0"
}
},
"node_modules/@vue/compiler-ssr": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-ssr/-/compiler-ssr-3.5.12.tgz",
"integrity": "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==",
"dependencies": {
"@vue/compiler-dom": "3.5.12",
"@vue/shared": "3.5.12"
}
},
"node_modules/@vue/reactivity": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/reactivity/-/reactivity-3.5.12.tgz",
"integrity": "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==",
"dependencies": {
"@vue/shared": "3.5.12"
}
},
"node_modules/@vue/runtime-core": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/runtime-core/-/runtime-core-3.5.12.tgz",
"integrity": "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw==",
"dependencies": {
"@vue/reactivity": "3.5.12",
"@vue/shared": "3.5.12"
}
},
"node_modules/@vue/runtime-dom": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/runtime-dom/-/runtime-dom-3.5.12.tgz",
"integrity": "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA==",
"dependencies": {
"@vue/reactivity": "3.5.12",
"@vue/runtime-core": "3.5.12",
"@vue/shared": "3.5.12",
"csstype": "^3.1.3"
}
},
"node_modules/@vue/server-renderer": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/server-renderer/-/server-renderer-3.5.12.tgz",
"integrity": "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg==",
"dependencies": {
"@vue/compiler-ssr": "3.5.12",
"@vue/shared": "3.5.12"
},
"peerDependencies": {
"vue": "3.5.12"
}
},
"node_modules/@vue/shared": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/shared/-/shared-3.5.12.tgz",
"integrity": "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg=="
},
"node_modules/balanced-match": { "node_modules/balanced-match": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -37,18 +197,76 @@
"balanced-match": "^1.0.0" "balanced-match": "^1.0.0"
} }
}, },
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://mirrors.cloud.tencent.com/npm/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
},
"node_modules/fs-extra": {
"version": "10.1.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/fs-extra/-/fs-extra-10.1.0.tgz",
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://mirrors.cloud.tencent.com/npm/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
},
"node_modules/jsonc-parser": { "node_modules/jsonc-parser": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
"integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
"dev": true "dev": true
}, },
"node_modules/jsonfile": {
"version": "6.1.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dependencies": {
"universalify": "^2.0.0"
},
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/lunr": { "node_modules/lunr": {
"version": "2.3.9", "version": "2.3.9",
"resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
"integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==",
"dev": true "dev": true
}, },
"node_modules/magic-string": {
"version": "0.30.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/magic-string/-/magic-string-0.30.12.tgz",
"integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0"
}
},
"node_modules/marked": { "node_modules/marked": {
"version": "4.2.12", "version": "4.2.12",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.2.12.tgz", "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.12.tgz",
@@ -73,6 +291,55 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://mirrors.cloud.tencent.com/npm/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
},
"node_modules/postcss": {
"version": "8.4.47",
"resolved": "https://mirrors.cloud.tencent.com/npm/postcss/-/postcss-8.4.47.tgz",
"integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.1.0",
"source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/shiki": { "node_modules/shiki": {
"version": "0.12.1", "version": "0.12.1",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-0.12.1.tgz", "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.12.1.tgz",
@@ -84,6 +351,22 @@
"vscode-textmate": "^8.0.0" "vscode-textmate": "^8.0.0"
} }
}, },
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/to-fast-properties": {
"version": "2.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
"integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
"engines": {
"node": ">=4"
}
},
"node_modules/typedoc": { "node_modules/typedoc": {
"version": "0.23.24", "version": "0.23.24",
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.24.tgz", "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.24.tgz",
@@ -109,7 +392,7 @@
"version": "4.8.2", "version": "4.8.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz",
"integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==", "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==",
"dev": true, "devOptional": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
@@ -124,6 +407,14 @@
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
"dev": true "dev": true
}, },
"node_modules/universalify": {
"version": "2.0.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/vscode-oniguruma": { "node_modules/vscode-oniguruma": {
"version": "1.7.0", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz",
@@ -135,9 +426,77 @@
"resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz",
"integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==",
"dev": true "dev": true
},
"node_modules/vue": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/vue/-/vue-3.5.12.tgz",
"integrity": "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==",
"dependencies": {
"@vue/compiler-dom": "3.5.12",
"@vue/compiler-sfc": "3.5.12",
"@vue/runtime-dom": "3.5.12",
"@vue/server-renderer": "3.5.12",
"@vue/shared": "3.5.12"
},
"peerDependencies": {
"typescript": "*"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
} }
}, },
"dependencies": { "dependencies": {
"@babel/helper-string-parser": {
"version": "7.25.7",
"resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz",
"integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="
},
"@babel/helper-validator-identifier": {
"version": "7.25.7",
"resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz",
"integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="
},
"@babel/parser": {
"version": "7.25.8",
"resolved": "https://mirrors.cloud.tencent.com/npm/@babel/parser/-/parser-7.25.8.tgz",
"integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==",
"requires": {
"@babel/types": "^7.25.8"
}
},
"@babel/types": {
"version": "7.25.8",
"resolved": "https://mirrors.cloud.tencent.com/npm/@babel/types/-/types-7.25.8.tgz",
"integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==",
"requires": {
"@babel/helper-string-parser": "^7.25.7",
"@babel/helper-validator-identifier": "^7.25.7",
"to-fast-properties": "^2.0.0"
}
},
"@cocos/creator-types": {
"version": "3.8.4",
"resolved": "https://mirrors.cloud.tencent.com/npm/@cocos/creator-types/-/creator-types-3.8.4.tgz",
"integrity": "sha512-z+8qx726Zl/8rUUpbLjVAiNPn4XweRACEaY1vHeR3EHIcSQ9wtFlIFd2SZX5rOE8lt1S95nxv8OeLYXfbN4/2Q==",
"dev": true
},
"@jridgewell/sourcemap-codec": {
"version": "1.5.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
},
"@types/fs-extra": {
"version": "9.0.13",
"resolved": "https://mirrors.cloud.tencent.com/npm/@types/fs-extra/-/fs-extra-9.0.13.tgz",
"integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/node": { "@types/node": {
"version": "20.16.12", "version": "20.16.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@types/node/-/node-20.16.12.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/@types/node/-/node-20.16.12.tgz",
@@ -147,6 +506,94 @@
"undici-types": "~6.19.2" "undici-types": "~6.19.2"
} }
}, },
"@vue/compiler-core": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-core/-/compiler-core-3.5.12.tgz",
"integrity": "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==",
"requires": {
"@babel/parser": "^7.25.3",
"@vue/shared": "3.5.12",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.0"
}
},
"@vue/compiler-dom": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-dom/-/compiler-dom-3.5.12.tgz",
"integrity": "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==",
"requires": {
"@vue/compiler-core": "3.5.12",
"@vue/shared": "3.5.12"
}
},
"@vue/compiler-sfc": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-sfc/-/compiler-sfc-3.5.12.tgz",
"integrity": "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==",
"requires": {
"@babel/parser": "^7.25.3",
"@vue/compiler-core": "3.5.12",
"@vue/compiler-dom": "3.5.12",
"@vue/compiler-ssr": "3.5.12",
"@vue/shared": "3.5.12",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.11",
"postcss": "^8.4.47",
"source-map-js": "^1.2.0"
}
},
"@vue/compiler-ssr": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-ssr/-/compiler-ssr-3.5.12.tgz",
"integrity": "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==",
"requires": {
"@vue/compiler-dom": "3.5.12",
"@vue/shared": "3.5.12"
}
},
"@vue/reactivity": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/reactivity/-/reactivity-3.5.12.tgz",
"integrity": "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==",
"requires": {
"@vue/shared": "3.5.12"
}
},
"@vue/runtime-core": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/runtime-core/-/runtime-core-3.5.12.tgz",
"integrity": "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw==",
"requires": {
"@vue/reactivity": "3.5.12",
"@vue/shared": "3.5.12"
}
},
"@vue/runtime-dom": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/runtime-dom/-/runtime-dom-3.5.12.tgz",
"integrity": "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA==",
"requires": {
"@vue/reactivity": "3.5.12",
"@vue/runtime-core": "3.5.12",
"@vue/shared": "3.5.12",
"csstype": "^3.1.3"
}
},
"@vue/server-renderer": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/server-renderer/-/server-renderer-3.5.12.tgz",
"integrity": "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg==",
"requires": {
"@vue/compiler-ssr": "3.5.12",
"@vue/shared": "3.5.12"
}
},
"@vue/shared": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/@vue/shared/-/shared-3.5.12.tgz",
"integrity": "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg=="
},
"balanced-match": { "balanced-match": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -162,18 +609,65 @@
"balanced-match": "^1.0.0" "balanced-match": "^1.0.0"
} }
}, },
"csstype": {
"version": "3.1.3",
"resolved": "https://mirrors.cloud.tencent.com/npm/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
"entities": {
"version": "4.5.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
},
"estree-walker": {
"version": "2.0.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
},
"fs-extra": {
"version": "10.1.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/fs-extra/-/fs-extra-10.1.0.tgz",
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
"requires": {
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
}
},
"graceful-fs": {
"version": "4.2.11",
"resolved": "https://mirrors.cloud.tencent.com/npm/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
},
"jsonc-parser": { "jsonc-parser": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
"integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
"dev": true "dev": true
}, },
"jsonfile": {
"version": "6.1.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"requires": {
"graceful-fs": "^4.1.6",
"universalify": "^2.0.0"
}
},
"lunr": { "lunr": {
"version": "2.3.9", "version": "2.3.9",
"resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
"integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==",
"dev": true "dev": true
}, },
"magic-string": {
"version": "0.30.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/magic-string/-/magic-string-0.30.12.tgz",
"integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==",
"requires": {
"@jridgewell/sourcemap-codec": "^1.5.0"
}
},
"marked": { "marked": {
"version": "4.2.12", "version": "4.2.12",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.2.12.tgz", "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.12.tgz",
@@ -189,6 +683,26 @@
"brace-expansion": "^2.0.1" "brace-expansion": "^2.0.1"
} }
}, },
"nanoid": {
"version": "3.3.7",
"resolved": "https://mirrors.cloud.tencent.com/npm/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="
},
"picocolors": {
"version": "1.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
},
"postcss": {
"version": "8.4.47",
"resolved": "https://mirrors.cloud.tencent.com/npm/postcss/-/postcss-8.4.47.tgz",
"integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
"requires": {
"nanoid": "^3.3.7",
"picocolors": "^1.1.0",
"source-map-js": "^1.2.1"
}
},
"shiki": { "shiki": {
"version": "0.12.1", "version": "0.12.1",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-0.12.1.tgz", "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.12.1.tgz",
@@ -200,6 +714,16 @@
"vscode-textmate": "^8.0.0" "vscode-textmate": "^8.0.0"
} }
}, },
"source-map-js": {
"version": "1.2.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="
},
"to-fast-properties": {
"version": "2.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
"integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog=="
},
"typedoc": { "typedoc": {
"version": "0.23.24", "version": "0.23.24",
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.24.tgz", "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.24.tgz",
@@ -216,7 +740,7 @@
"version": "4.8.2", "version": "4.8.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz",
"integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==", "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==",
"dev": true "devOptional": true
}, },
"undici-types": { "undici-types": {
"version": "6.19.8", "version": "6.19.8",
@@ -224,6 +748,11 @@
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
"dev": true "dev": true
}, },
"universalify": {
"version": "2.0.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="
},
"vscode-oniguruma": { "vscode-oniguruma": {
"version": "1.7.0", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz",
@@ -235,6 +764,18 @@
"resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz",
"integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==",
"dev": true "dev": true
},
"vue": {
"version": "3.5.12",
"resolved": "https://mirrors.cloud.tencent.com/npm/vue/-/vue-3.5.12.tgz",
"integrity": "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==",
"requires": {
"@vue/compiler-dom": "3.5.12",
"@vue/compiler-sfc": "3.5.12",
"@vue/runtime-dom": "3.5.12",
"@vue/server-renderer": "3.5.12",
"@vue/shared": "3.5.12"
}
} }
} }
} }

View File

@@ -11,13 +11,35 @@
"watch": "tsc -w", "watch": "tsc -w",
"doc": "npx typedoc" "doc": "npx typedoc"
}, },
"panels": {
"set_file_name": {
"title": "i18n:oops-framework.panel_create_file",
"type": "dockable",
"main": "dist/default",
"size": {
"min-width": 450,
"min-height": 300,
"width": 450,
"height": 300
}
}
},
"contributions": { "contributions": {
"scene": {
"script": "./dist/scene.js"
},
"asset-db": { "asset-db": {
"mount": { "mount": {
"path": "./assets", "path": "./assets",
"readonly": false "readonly": false
} }
}, },
"assets": {
"menu": {
"methods": "./dist/assets-menu.js",
"assetMenu": "onAssetMenu"
}
},
"menu": [ "menu": [
{ {
"path": "i18n:oops-framework.name", "path": "i18n:oops-framework.name",
@@ -29,6 +51,11 @@
"label": "i18n:oops-framework.document_api", "label": "i18n:oops-framework.document_api",
"message": "documentApi" "message": "documentApi"
}, },
{
"path": "i18n:oops-framework.name",
"label": "i18n:oops-framework.tutorial",
"message": "tutorial"
},
{ {
"path": "i18n:oops-framework.name", "path": "i18n:oops-framework.name",
"label": "i18n:oops-framework.solution", "label": "i18n:oops-framework.solution",
@@ -70,6 +97,11 @@
"log" "log"
] ]
}, },
"tutorial": {
"methods": [
"tutorial"
]
},
"solution": { "solution": {
"methods": [ "methods": [
"solution" "solution"
@@ -87,7 +119,13 @@
} }
} }
}, },
"dependencies": {
"fs-extra": "^10.0.0",
"vue": "^3.1.4"
},
"devDependencies": { "devDependencies": {
"@cocos/creator-types": "^3.8.2",
"@types/fs-extra": "^9.0.5",
"@types/node": "^20.16.12", "@types/node": "^20.16.12",
"typedoc": "^0.23.24", "typedoc": "^0.23.24",
"typescript": "^4.8.2" "typescript": "^4.8.2"

80
src/assets-menu.ts Normal file
View File

@@ -0,0 +1,80 @@
import { AssetInfo } from "../@types/packages/asset-db/@types/public";
import { compress } from "./tinypng";
/** 资源栏右键菜单 */
export function onAssetMenu(assetInfo: AssetInfo) {
return [
{
label: 'i18n:oops-framework.name',
submenu: [
{
label: `i18n:oops-framework.script`,
submenu: [
{
label: `i18n:oops-framework.createGameComponent`,
async click() {
localStorage.setItem('create_path', assetInfo.file);
localStorage.setItem('create_type', "GameComponent");
Editor.Panel.open("oops-framework.set_file_name");
},
},
{
type: `separator`,
},
{
label: `i18n:oops-framework.createModule`,
click() {
localStorage.setItem('create_path', assetInfo.file);
localStorage.setItem('create_type', "Module");
Editor.Panel.open("oops-framework.set_file_name");
},
},
{
label: `i18n:oops-framework.createModel`,
click() {
localStorage.setItem('create_path', assetInfo.file);
localStorage.setItem('create_type', "Model");
Editor.Panel.open("oops-framework.set_file_name");
},
},
{
label: `i18n:oops-framework.createBll`,
click() {
localStorage.setItem('create_path', assetInfo.file);
localStorage.setItem('create_type', "Bll");
Editor.Panel.open("oops-framework.set_file_name");
},
},
{
label: `i18n:oops-framework.createView`,
click() {
localStorage.setItem('create_path', assetInfo.file);
localStorage.setItem('create_type', "View");
Editor.Panel.open("oops-framework.set_file_name");
},
},
{
label: `i18n:oops-framework.createViewMvvm`,
click() {
localStorage.setItem('create_path', assetInfo.file);
localStorage.setItem('create_type', "ViewMvvm");
Editor.Panel.open("oops-framework.set_file_name");
},
},
]
},
{
label: `i18n:oops-framework.tools`,
submenu: [
{
label: `i18n:oops-framework.tools_compress`,
click() {
compress(assetInfo.file);
},
}
]
}
],
},
];
};

135
src/create-script.ts Normal file
View File

@@ -0,0 +1,135 @@
import { existsSync } from 'fs';
import path from 'path';
/** 写入文件 */
export function createView(directoryPath: string, fileName: string, content: string, isEcsComp: boolean = true): Promise<void> {
return new Promise<void>(async (resolve, reject) => {
// 创建脚本
let className = fileName + "View";
let scriptUrl = "";
if (isEcsComp) {
scriptUrl = path.join(directoryPath, fileName) + "ViewComp.ts";
}
else {
scriptUrl = path.join(directoryPath, fileName) + "View.ts";
}
if (!existsSync(scriptUrl)) {
content = content.replace(/<%Name%>/g, className);
await Editor.Message.request('asset-db', 'create-asset', scriptUrl, content);
}
// 创建预制
let prefabUrl = path.join(directoryPath, fileName) + ".prefab";
if (!existsSync(prefabUrl)) {
if (isEcsComp) className = className + "Comp";
await Editor.Message.request('scene', 'execute-scene-script', {
name: "oops-framework",
method: 'createPrefab',
args: [fileName, className, prefabUrl]
});
}
// 闪烁提示新创建的脚本文件
Editor.Message.send('assets', 'twinkle', scriptUrl);
// 打开脚本
Editor.Message.request('asset-db', 'open-asset', scriptUrl);
// 打开预制
Editor.Message.request('asset-db', 'open-asset', prefabUrl);
resolve();
});
}
export function createScriptModule(directoryPath: string, fileName: string, content: string): Promise<void> {
return new Promise<void>(async (resolve, reject) => {
// 创建目录
let pathName = fileName.toLowerCase();
let pathModule = path.join(directoryPath, pathName);
if (!existsSync(pathModule)) {
await Editor.Message.request('asset-db', 'create-asset', pathModule, null);
}
let subPathView = path.join(pathModule, "view");
if (!existsSync(subPathView)) {
await Editor.Message.request('asset-db', 'create-asset', subPathView, null);
}
let subPathBll = path.join(pathModule, "bll");
if (!existsSync(subPathBll)) {
await Editor.Message.request('asset-db', 'create-asset', subPathBll, null);
}
let subPathModel = path.join(pathModule, "model");
if (!existsSync(subPathModel)) {
await Editor.Message.request('asset-db', 'create-asset', subPathModel, null);
}
// 创建脚本
let scriptUrl = path.join(pathModule, fileName) + ".ts";
if (!existsSync(scriptUrl)) {
content = content.replace(/<%Name%>/g, fileName);
await Editor.Message.request('asset-db', 'create-asset', scriptUrl, content);
}
// 闪烁提示新创建的脚本文件
Editor.Message.send('assets', 'twinkle', scriptUrl);
// 打开脚本
Editor.Message.request('asset-db', 'open-asset', scriptUrl);
resolve();
});
}
/** 创建脚本 */
export function createScriptBll(directoryPath: string, fileName: string, content: string, moduleName: string): Promise<void> {
return new Promise<void>(async (resolve, reject) => {
let scriptUrl = path.join(directoryPath, fileName) + ".ts";
// 创建脚本
if (!existsSync(scriptUrl)) {
content = content.replace(/<%Name%>/g, fileName);
content = content.replace(/<%ModuleName%>/g, moduleName);
await Editor.Message.request('asset-db', 'create-asset', scriptUrl, content);
}
// 闪烁提示新创建的脚本文件
Editor.Message.send('assets', 'twinkle', scriptUrl);
// 打开脚本
Editor.Message.request('asset-db', 'open-asset', scriptUrl);
resolve();
});
}
/** 创建业务层脚本 */
export function createScript(directoryPath: string, fileName: string, content: string, isEcsComp: boolean = true): Promise<void> {
return new Promise<void>(async (resolve, reject) => {
let scriptUrl = "";
if (isEcsComp) {
scriptUrl = path.join(directoryPath, fileName) + "Comp.ts";
}
else {
scriptUrl = path.join(directoryPath, fileName) + ".ts";
}
// 创建脚本
if (!existsSync(scriptUrl)) {
content = content.replace(/<%Name%>/g, fileName);
await Editor.Message.request('asset-db', 'create-asset', scriptUrl, content);
}
// 闪烁提示新创建的脚本文件
Editor.Message.send('assets', 'twinkle', scriptUrl);
// 打开脚本
Editor.Message.request('asset-db', 'open-asset', scriptUrl);
resolve();
});
}

119
src/default/index.ts Normal file
View File

@@ -0,0 +1,119 @@
import { readFileSync } from 'fs-extra';
import { join } from 'path';
import { App, createApp } from 'vue';
import { createScript, createScriptBll, createScriptModule, createView } from '../create-script';
import { TemplateGameComponent } from '../template/GameComponent';
import { TemplateModule } from '../template/Module';
import { TemplateBll } from '../template/ModuleBll';
import { TemplateModel } from '../template/ModuleModel';
import { TemplateView } from '../template/ModuleView';
import { TemplateViewMvvm } from '../template/ModuleViewVM';
const panelDataMap = new WeakMap<any, App>();
module.exports = Editor.Panel.define({
listeners: {
show() { console.log('show'); },
hide() { console.log('hide'); },
},
template: readFileSync(join(__dirname, '../../static/template/default/index.html'), 'utf-8'),
style: readFileSync(join(__dirname, '../../static/style/default/index.css'), 'utf-8'),
$: {
app: '#app',
},
ready() {
let filename = "Default";
let type = localStorage.getItem('create_type')!;
localStorage.removeItem('create_type');
let path = localStorage.getItem('create_path')!;
localStorage.removeItem('create_path');
let title = "???";
let showModule = false;
let moduleName = "ModuleName";
switch (type) {
case "GameComponent":
title = `i18n:oops-framework.createGameComponent`;
break;
case "Module":
title = `i18n:oops-framework.createModule`;
break;
case "Model":
title = `i18n:oops-framework.createModel`;
break;
case "Bll":
title = `i18n:oops-framework.createBll`;
showModule = true;
break;
case "View":
title = `i18n:oops-framework.createView`;
break;
case "ViewMvvm":
title = `i18n:oops-framework.createViewMvvm`;
break;
}
// 创建框架配置界面
if (this.$.app) {
const app = createApp({});
app.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('ui-');
app.component('MyConfig', {
template: readFileSync(join(__dirname, '../../static/template/vue/set_file_name.html'), 'utf-8'),
data() {
return {
title: title,
filename: filename,
showModule: showModule
};
},
methods: {
// 记录输入的文件名
onInputName(event: any) {
filename = event.target.value;
},
onModuleName(event: any) {
moduleName = event.target.value;
},
// 创建文件
async onConfirm() {
if (filename.trim().length == 0) {
await Editor.Dialog.info('请输入文件名');
return;
}
switch (type) {
case "GameComponent":
await createView(path, filename, TemplateGameComponent, false);
break;
case "Module":
await createScriptModule(path, filename, TemplateModule);
break;
case "Model":
await createScript(path, filename, TemplateModel);
break;
case "Bll":
await createScriptBll(path, filename, TemplateBll, moduleName);
break;
case "View":
await createView(path, filename, TemplateView);
break;
case "ViewMvvm":
await createView(path, filename, TemplateViewMvvm);
break;
}
close();
}
},
});
app.mount(this.$.app);
panelDataMap.set(this, app);
}
},
beforeClose() { },
close() {
const app = panelDataMap.get(this);
if (app) {
app.unmount();
}
},
});

View File

@@ -46,5 +46,5 @@ export const methods: { [key: string]: (...any: any) => any } = {
/** 点亮 Github 星星 */ /** 点亮 Github 星星 */
github() { github() {
shell.openExternal('https://github.com/dgflash/oops-framework'); shell.openExternal('https://github.com/dgflash/oops-framework');
}, }
}; };

36
src/scene.ts Normal file
View File

@@ -0,0 +1,36 @@
export function load() { }
export function unload() { }
// 在其他扩展脚本中,我们可以使用如下代码调用 rotateCamera 函数
// const options: ExecuteSceneScriptMethodOptions = {
// name: scene.ts 所在的扩展包名, 如: App,
// method: scene.ts 中定义的方法, 如: createPrefab,
// args: 参数,可选, 只传递json
// };
// const result = await Editor.Message.request('scene', 'execute-scene-script', options);
export const methods = {
/** 创建视图层制 */
async createPrefab(fileName: string, className: string, prefabUrl: string) {
const { Node, js, Layers } = require('cc');
const node = new Node(fileName);
node.layer = Layers.Enum.UI_2D;
while (true) {
const result = js.getClassByName(className);
if (result) break;
await new Promise((next) => {
setTimeout(next, 100);
});
}
const com = node.addComponent(className);
com.resetInEditor && com.resetInEditor();
const info = cce.Prefab.generatePrefabDataFromNode(node) as any;
node.destroy();
return Editor.Message.request('asset-db', 'create-asset', prefabUrl, info.prefabData || info);
}
};

View File

@@ -0,0 +1,12 @@
export const TemplateGameComponent = `import { _decorator } from 'cc';
import { GameComponent } from "db://oops-framework/module/common/GameComponent";
const { ccclass, property } = _decorator;
/** 显示对象控制 */
@ccclass('<%Name%>')
export class <%Name%> extends GameComponent {
protected start() {
}
}`;

19
src/template/Module.ts Normal file
View File

@@ -0,0 +1,19 @@
export const TemplateModule = `import { ecs } from "db://oops-framework/libs/ecs/ECS";
/** <%Name%> 模块 */
@ecs.register('<%Name%>')
export class <%Name%> extends ecs.Entity {
/** ---------- 数据层 ---------- */
// <%Name%>Model!: <%Name%>ModelComp;
/** ---------- 业务层 ---------- */
// <%Name%>Bll!: <%Name%>BllComp;
/** ---------- 视图层 ---------- */
// <%Name%>View!: <%Name%>ViewComp;
/** 初始添加的数据层组件 */
protected init() {
// this.addComponents<ecs.Comp>();
}
}`;

24
src/template/ModuleBll.ts Normal file
View File

@@ -0,0 +1,24 @@
export const TemplateBll = `import { ecs } from "db://oops-framework/libs/ecs/ECS";
/** 业务输入参数 */
@ecs.register('<%Name%>')
export class <%Name%>Comp extends ecs.Comp {
/** 业务层组件移除时,重置所有数据为默认值 */
reset() {
}
}
/** 业务逻辑处理对象 */
@ecs.register('<%ModuleName%>')
export class <%Name%>System extends ecs.ComblockSystem implements ecs.IEntityEnterSystem {
filter(): ecs.IMatcher {
return ecs.allOf(<%Name%>Comp);
}
entityEnter(e: ecs.Entity): void {
// 注:自定义业务逻辑
e.remove(<%Name%>Comp);
}
}`;

View File

@@ -0,0 +1,12 @@
export const TemplateModel = `import { ecs } from "db://oops-framework/libs/ecs/ECS";
/** 数据层对象 */
@ecs.register('<%Name%>')
export class <%Name%>Comp extends ecs.Comp {
id: number = -1;
/** 数据层组件移除时,重置所有数据为默认值 */
reset() {
this.id = -1;
}
}`;

View File

@@ -0,0 +1,20 @@
export const TemplateView = `import { _decorator } from "cc";
import { ecs } from "db://oops-framework/libs/ecs/ECS";
import { CCComp } from "db://oops-framework/module/common/CCComp";
const { ccclass, property } = _decorator;
/** 视图层对象 */
@ccclass('<%Name%>Comp')
@ecs.register('<%Name%>', false)
export class <%Name%>Comp extends CCComp {
/** 视图层逻辑代码分离演示 */
start() {
// const entity = this.ent as ecs.Entity; // ecs.Entity 可转为当前模块的具体实体对象
}
/** 视图对象通过 ecs.Entity.remove(<%Name%>Comp) 删除组件是触发组件处理自定义释放逻辑 */
reset() {
this.node.destroy();
}
}`;

View File

@@ -0,0 +1,23 @@
export const TemplateViewMvvm = `import { _decorator } from "cc";
import { ecs } from "db://oops-framework/libs/ecs/ECS";
import { CCVMParentComp } from "db://oops-framework/module/common/CCVMParentComp";
const { ccclass, property } = _decorator;
/** 视图层对象 - 支持 MVVM 框架的数据绑定 */
@ccclass('<%Name%>Comp')
@ecs.register('<%Name%>', false)
export class <%Name%>Comp extends CCVMParentComp {
/** 脚本控制的界面 MVVM 框架绑定数据 */
data: any = {};
/** 视图层逻辑代码分离演示 */
start() {
// const entity = this.ent as ecs.Entity; // ecs.Entity 可转为当前模块的具体实体对象
}
/** 视图对象通过 ecs.Entity.remove(<%Name%>Comp) 删除组件是触发组件处理自定义释放逻辑 */
reset() {
this.node.destroy();
}
}`

159
src/tinypng.ts Normal file
View File

@@ -0,0 +1,159 @@
import fs from 'fs';
import https from 'https';
import path from 'path';
import url from 'url';
const exts = ['.png', '.jpg', '.jpeg'];
const max = 5200000;
const options: any = {
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'
}
};
export function compress(filePath: string): void {
if (!fs.existsSync(filePath)) {
console.log(`路径不存在:${filePath}`);
return;
}
const fileName = path.basename(filePath);
if (!fs.statSync(filePath).isDirectory()) {
if (exts.includes(path.extname(filePath))) {
console.log(`[${fileName}] 压缩中...`);
fileTinyUpload(filePath)
.then(data => {
console.log(`[1/1] [${fileName}] 压缩成功,原始: ${toSize(data.input.size)},压缩: ${toSize(data.output.size)},压缩比: ${toPercent(data.output.ratio)}`);
})
.catch(err => {
console.log(`[1/1] [${fileName}] 压缩失败!报错:${err}`);
});
}
else {
console.log(`[${fileName}] 压缩失败!报错:只支持 png、jpg 与 jpeg 格式`);
}
}
else {
let totalCount = 0;
let processedCount = 0;
fileEach(filePath, (filePathInDir) => {
totalCount++;
const relativePath = path.relative(filePath, filePathInDir);
fileTinyUpload(filePathInDir)
.then(data => {
console.log(`[${++processedCount}/${totalCount}] [${relativePath}] 压缩成功,原始: ${toSize(data.input.size)},压缩: ${toSize(data.output.size)},压缩比: ${toPercent(data.output.ratio)}`);
})
.catch(err => {
console.log(`[${++processedCount}/${totalCount}] [${relativePath}] 压缩失败!报错:${err}`);
});
});
}
}
function getRandomIP(): string {
return Array.from(Array(4)).map(() => Math.floor(255 * Math.random())).join('.');
}
function fileEach(dir: string, callback: (filePath: string) => void): void {
fs.readdir(dir, (err: any, files: any[]) => {
if (err) {
console.error(err);
return;
}
files.forEach((file: any) => {
const filePath = path.join(dir, file);
fs.stat(filePath, (statErr: any, stats: { isDirectory: () => any; size: number; isFile: () => any; }) => {
if (statErr) {
console.error(statErr);
return;
}
if (stats.isDirectory()) {
fileEach(filePath, callback);
}
else {
if (stats.size <= max && stats.isFile() && exts.includes(path.extname(file))) {
callback(filePath);
}
}
});
});
});
}
function fileUpload(filePath: string): Promise<any> {
return new Promise((resolve, reject) => {
options.headers['X-Forwarded-For'] = getRandomIP();
const req = https.request(options, (res: any) => {
let data = '';
res.on('data', (chunk: string) => {
data += chunk;
});
res.on('end', () => {
try {
const result = JSON.parse(data);
if (result.error) {
reject(result.message);
} else {
resolve(result);
}
} catch (parseErr) {
reject(parseErr);
}
});
});
req.write(fs.readFileSync(filePath), 'binary');
req.on('error', err => {
reject(err);
});
req.end();
});
}
function fileUpdate(filePath: string, data: any): Promise<any> {
return new Promise((resolve, reject) => {
const urlObj = new url.URL(data.output.url);
const req = https.request(urlObj, (res: any) => {
let body = '';
res.setEncoding('binary');
res.on('data', (chunk: string) => {
body += chunk;
});
res.on('end', () => {
fs.writeFile(filePath, body, 'binary', (err: any) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
});
req.on('error', (err: any) => {
reject(err);
});
req.end();
});
}
function fileTinyUpload(filePath: string): Promise<any> {
return fileUpload(filePath).then(data => fileUpdate(filePath, data));
}
function toSize(size: number): string {
if (size < 1024)
return size + 'B';
else if (size < 1048576)
return (size / 1024).toFixed(2) + 'KB';
else
return (size / 1024 / 1024).toFixed(2) + 'MB';
}
function toPercent(ratio: number): string {
return (100 * ratio).toFixed(2) + '%';
}

View File

@@ -0,0 +1,37 @@
ui-input {
width: 100%;
min-width: 100px;
min-height: 30px;
line-height: 30px;
}
ui-button {
height: 30px;
}
ui-label {
margin-top: 5px;
margin-bottom: 5px;
}
.f {
flex: 1;
overflow: auto;
padding: 10px;
}
.c {
display: inline-flex;
width: 100%;
flex-wrap: nowrap;
}
.c ui-button {
width: 40%;
}
.b {
text-align: center;
padding: 10px 0;
margin-top: 5px;
}

View File

@@ -0,0 +1,5 @@
<div>
<div id="app">
<my-config></my-config>
</div>
</div>

View File

@@ -0,0 +1,18 @@
<div id="r">
<div class="f">
<b><ui-label slot="label" :value="title"></ui-label></b><br>
<div slot="content" class="c">
<ui-label slot="label" style="width: 70px;">文件名:</ui-label>
<ui-input autofocus @input="onInputName" :value="filename"></ui-input>
</div>
</div>
<div class="f" v-if="showModule">
<div slot="content" class="c">
<ui-label slot="label" style="width: 70px;">模块名:</ui-label> <ui-input autofocus
@input="onModuleName"></ui-input>
</div>
</div>
<div class="b">
<ui-button @confirm="onConfirm">确认</ui-button>
</div>
</div>