mirror of
https://gitee.com/dgflash/oops-plugin-framework.git
synced 2026-05-30 18:39:18 +08:00
强类型事件支持传空参数
This commit is contained in:
@@ -45,7 +45,7 @@ export class EventDispatcher {
|
||||
* @param event 事件名(枚举)
|
||||
* @param data 事件数据(必须完全匹配类型定义)
|
||||
*/
|
||||
emit<K extends keyof OopsFramework.TypedEventMap>(event: K, data: OopsFramework.TypedEventMap[K]): void {
|
||||
emit<K extends keyof OopsFramework.TypedEventMap>(event: K, data?: OopsFramework.TypedEventMap[K]): void {
|
||||
message.emit(event, data);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ export class MessageManager {
|
||||
* @param data 事件数据(必须完全匹配类型定义)
|
||||
* @note 使用此方法可获得编译时的强类型约束,参数不匹配会编译报错
|
||||
*/
|
||||
emit<K extends keyof OopsFramework.TypedEventMap>(event: K, data: OopsFramework.TypedEventMap[K]): void {
|
||||
emit<K extends keyof OopsFramework.TypedEventMap>(event: K, data?: OopsFramework.TypedEventMap[K]): void {
|
||||
const list = this.events.get(event as string);
|
||||
if (list != null) {
|
||||
const eds: Array<EventData> = list.concat();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { Node, Vec3 } from 'cc';
|
||||
import { LayerCustomType, LayerType } from './LayerEnum';
|
||||
|
||||
/**
|
||||
* 界面配置结构体
|
||||
@@ -28,7 +29,7 @@ export interface UIConfig {
|
||||
/** 远程包名 */
|
||||
bundle?: string;
|
||||
/** 窗口层级 */
|
||||
layer: string;
|
||||
layer: LayerType | LayerCustomType;
|
||||
/** 预制资源相对路径 */
|
||||
prefab: string;
|
||||
/** 是否自动施放(默认自动释放) */
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-09-02 14:49:42
|
||||
*/
|
||||
import { Color, Texture2D } from 'cc';
|
||||
import { assetManager, Color, ImageAsset, sys, Texture2D } from 'cc';
|
||||
|
||||
/**
|
||||
* 图像工具
|
||||
@@ -21,6 +21,15 @@ const color = ImageUtil.getPixelColor(texture, 1, 1);
|
||||
cc.color(50, 100, 123, 255);
|
||||
*/
|
||||
static getPixelColor(texture: Texture2D, x: number, y: number): Color {
|
||||
if (sys.isBrowser) {
|
||||
return ImageUtil.getPixelColorForWeb(texture, x, y);
|
||||
}
|
||||
else {
|
||||
return ImageUtil.getPixelColorForNative(texture, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
private static getPixelColorForWeb(texture: Texture2D, x: number, y: number): Color {
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d')!;
|
||||
canvas.width = texture.width;
|
||||
@@ -36,19 +45,43 @@ cc.color(50, 100, 123, 255);
|
||||
return color;
|
||||
}
|
||||
|
||||
private static getPixelColorForNative(texture: Texture2D, x: number, y: number): Color {
|
||||
const height = texture.height;
|
||||
const pixels = texture.getPixel(x - 1, height - y);
|
||||
if (pixels) {
|
||||
return new Color(pixels.r, pixels.g, pixels.b, pixels.a);
|
||||
}
|
||||
return new Color(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将图像转为 Base64 字符(仅 png、jpg 或 jpeg 格式资源)(有问题)
|
||||
* 将图像转为 Base64 字符(仅 png、jpg 或 jpeg 格式资源)
|
||||
* @param url 图像地址
|
||||
* @param callback 完成回调
|
||||
*/
|
||||
static imageToBase64(url: string, callback?: (dataURL: string) => void): Promise<string> {
|
||||
return new Promise((res) => {
|
||||
if (sys.isBrowser) {
|
||||
ImageUtil.imageToBase64ForWeb(url, callback).then((dataURL) => {
|
||||
res(dataURL);
|
||||
});
|
||||
}
|
||||
else {
|
||||
ImageUtil.imageToBase64ForNative(url, callback).then((dataURL) => {
|
||||
res(dataURL);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static imageToBase64ForWeb(url: string, callback?: (dataURL: string) => void): Promise<string> {
|
||||
return new Promise((res) => {
|
||||
let extname = /\.png|\.jpg|\.jpeg/.exec(url)?.[0];
|
||||
//@ts-ignore
|
||||
if (['.png', '.jpg', '.jpeg'].includes(extname)) {
|
||||
if (extname && ['.png', '.jpg', '.jpeg'].includes(extname)) {
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d')!;
|
||||
const image = new Image();
|
||||
image.crossOrigin = 'anonymous';
|
||||
image.src = url;
|
||||
image.onload = () => {
|
||||
canvas.height = image.height;
|
||||
@@ -61,6 +94,11 @@ cc.color(50, 100, 123, 255);
|
||||
image.remove();
|
||||
canvas.remove();
|
||||
};
|
||||
image.onerror = () => {
|
||||
console.warn('Failed to load image:', url);
|
||||
callback && callback('');
|
||||
res('');
|
||||
};
|
||||
}
|
||||
else {
|
||||
console.warn('Not a jpg/jpeg or png resource!');
|
||||
@@ -70,34 +108,215 @@ cc.color(50, 100, 123, 255);
|
||||
});
|
||||
}
|
||||
|
||||
private static imageToBase64ForNative(url: string, callback?: (dataURL: string) => void): Promise<string> {
|
||||
return new Promise((res) => {
|
||||
const extname = /\.png|\.jpg|\.jpeg/.exec(url)?.[0];
|
||||
if (!extname || !['.png', '.jpg', '.jpeg'].includes(extname)) {
|
||||
console.warn('Not a jpg/jpeg or png resource!');
|
||||
callback && callback('');
|
||||
res('');
|
||||
return;
|
||||
}
|
||||
assetManager.loadRemote<ImageAsset>(url, (err, imageAsset) => {
|
||||
if (err || !imageAsset) {
|
||||
console.warn('Failed to load image for base64:', url, err);
|
||||
callback && callback('');
|
||||
res('');
|
||||
return;
|
||||
}
|
||||
const data = imageAsset.data as Uint8Array;
|
||||
const base64 = ImageUtil.uint8ArrayToBase64(data);
|
||||
const mimeType = extname === '.jpg' ? 'image/jpeg' : `image/${extname.replace('.', '')}`;
|
||||
const dataURL = `data:${mimeType};base64,${base64}`;
|
||||
callback && callback(dataURL);
|
||||
res(dataURL);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 Base64 字符转为 cc.Texture2D 资源(有问题)
|
||||
* 将 Base64 字符转为 cc.Texture2D 资源(异步)
|
||||
* @param base64 Base64 字符
|
||||
*/
|
||||
static base64ToTexture(base64: string): Texture2D {
|
||||
static base64ToTextureAsync(base64: string): Promise<Texture2D | null> {
|
||||
return new Promise((resolve) => {
|
||||
if (sys.isBrowser) {
|
||||
ImageUtil.base64ToTextureForWebAsync(base64).then((texture) => {
|
||||
resolve(texture);
|
||||
});
|
||||
}
|
||||
else {
|
||||
const texture = ImageUtil.base64ToTextureForNative(base64);
|
||||
resolve(texture);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 Base64 字符转为 cc.Texture2D 资源(同步,仅 Web 平台推荐使用)
|
||||
* @param base64 Base64 字符
|
||||
* @deprecated 建议使用 base64ToTextureAsync 异步方法
|
||||
*/
|
||||
static base64ToTexture(base64: string): Texture2D | null {
|
||||
if (sys.isBrowser) {
|
||||
return ImageUtil.base64ToTextureForWeb(base64);
|
||||
}
|
||||
else {
|
||||
return ImageUtil.base64ToTextureForNative(base64);
|
||||
}
|
||||
}
|
||||
|
||||
private static base64ToTextureForWeb(base64: string): Texture2D | null {
|
||||
const image = document.createElement('img');
|
||||
image.src = base64;
|
||||
if (image.width === 0 || image.height === 0) {
|
||||
console.warn('Image not loaded yet, please use base64ToTextureAsync instead');
|
||||
return null;
|
||||
}
|
||||
const imageAsset = new ImageAsset(image);
|
||||
const texture = new Texture2D();
|
||||
//@ts-ignore
|
||||
texture.initWithElement(image);
|
||||
texture.image = imageAsset;
|
||||
image.remove();
|
||||
return texture;
|
||||
}
|
||||
|
||||
private static base64ToTextureForWebAsync(base64: string): Promise<Texture2D | null> {
|
||||
return new Promise((resolve) => {
|
||||
const image = new Image();
|
||||
image.onload = () => {
|
||||
const imageAsset = new ImageAsset(image);
|
||||
const texture = new Texture2D();
|
||||
texture.image = imageAsset;
|
||||
resolve(texture);
|
||||
};
|
||||
image.onerror = () => {
|
||||
console.warn('Failed to load base64 image');
|
||||
resolve(null);
|
||||
};
|
||||
image.src = base64;
|
||||
});
|
||||
}
|
||||
|
||||
private static base64ToTextureForNative(base64: string): Texture2D | null {
|
||||
try {
|
||||
const base64Data = base64.includes(',') ? base64.split(',')[1] : base64;
|
||||
if (!base64Data) {
|
||||
console.warn('Invalid base64 string');
|
||||
return null;
|
||||
}
|
||||
const bytes = ImageUtil.base64ToUint8Array(base64Data);
|
||||
const imageAsset = new ImageAsset();
|
||||
imageAsset.reset({
|
||||
_data: bytes,
|
||||
width: 0,
|
||||
height: 0,
|
||||
format: Texture2D.PixelFormat.RGBA8888,
|
||||
_compressed: false
|
||||
});
|
||||
const texture = new Texture2D();
|
||||
texture.image = imageAsset;
|
||||
return texture;
|
||||
}
|
||||
catch (e) {
|
||||
console.warn('Failed to convert base64 to texture:', e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 Base64 字符转为二进制数据(有问题)
|
||||
* 将 Base64 字符转为二进制数据
|
||||
* @param base64 Base64 字符
|
||||
*/
|
||||
static base64ToBlob(base64: string): Blob {
|
||||
const strings = base64.split(',');
|
||||
//@ts-ignore
|
||||
const type = /image\/\w+|;/.exec(strings[0])[0];
|
||||
const data = window.atob(strings[1]);
|
||||
const arrayBuffer = new ArrayBuffer(data.length);
|
||||
const uint8Array = new Uint8Array(arrayBuffer);
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
uint8Array[i] = data.charCodeAt(i) & 0xff;
|
||||
static base64ToBlob(base64: string): Blob | null {
|
||||
try {
|
||||
const strings = base64.split(',');
|
||||
const type = /image\/\w+/.exec(strings[0])?.[0] || 'image/png';
|
||||
const base64Data = strings[1] || base64;
|
||||
const bytes = ImageUtil.base64ToUint8Array(base64Data);
|
||||
return new Blob([bytes], { type: type });
|
||||
}
|
||||
return new Blob([uint8Array], { type: type });
|
||||
catch (e) {
|
||||
console.warn('Failed to convert base64 to blob:', e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static base64ToUint8Array(base64: string): Uint8Array {
|
||||
const binaryString = ImageUtil.atob(base64);
|
||||
const bytes = new Uint8Array(binaryString.length);
|
||||
for (let i = 0; i < binaryString.length; i++) {
|
||||
bytes[i] = binaryString.charCodeAt(i);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private static atob(base64: string): string {
|
||||
if (typeof window !== 'undefined' && window.atob) {
|
||||
return window.atob(base64);
|
||||
}
|
||||
return ImageUtil.atobPolyfill(base64);
|
||||
}
|
||||
|
||||
private static atobPolyfill(base64: string): string {
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
let output = '';
|
||||
let i = 0;
|
||||
base64 = base64.replace(/[^A-Za-z0-9\+\/\=]/g, '');
|
||||
while (i < base64.length) {
|
||||
const enc1 = chars.indexOf(base64.charAt(i++));
|
||||
const enc2 = chars.indexOf(base64.charAt(i++));
|
||||
const enc3 = chars.indexOf(base64.charAt(i++));
|
||||
const enc4 = chars.indexOf(base64.charAt(i++));
|
||||
const chr1 = (enc1 << 2) | (enc2 >> 4);
|
||||
const chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
||||
const chr3 = ((enc3 & 3) << 6) | enc4;
|
||||
output += String.fromCharCode(chr1);
|
||||
if (enc3 !== 64) {
|
||||
output += String.fromCharCode(chr2);
|
||||
}
|
||||
if (enc4 !== 64) {
|
||||
output += String.fromCharCode(chr3);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
private static uint8ArrayToBase64(uint8Array: Uint8Array): string {
|
||||
let binary = '';
|
||||
const len = uint8Array.byteLength;
|
||||
for (let i = 0; i < len; i++) {
|
||||
binary += String.fromCharCode(uint8Array[i]);
|
||||
}
|
||||
return ImageUtil.btoa(binary);
|
||||
}
|
||||
|
||||
private static btoa(binary: string): string {
|
||||
if (typeof window !== 'undefined' && window.btoa) {
|
||||
return window.btoa(binary);
|
||||
}
|
||||
return ImageUtil.btoaPolyfill(binary);
|
||||
}
|
||||
|
||||
private static btoaPolyfill(binary: string): string {
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
let output = '';
|
||||
let i = 0;
|
||||
while (i < binary.length) {
|
||||
const byte1 = binary.charCodeAt(i++);
|
||||
const byte2 = binary.charCodeAt(i++);
|
||||
const byte3 = binary.charCodeAt(i++);
|
||||
const enc1 = byte1 >> 2;
|
||||
const enc2 = ((byte1 & 3) << 4) | (byte2 >> 4);
|
||||
let enc3 = ((byte2 & 15) << 2) | (byte3 >> 6);
|
||||
let enc4 = byte3 & 63;
|
||||
if (isNaN(byte2)) {
|
||||
enc3 = enc4 = 64;
|
||||
}
|
||||
else if (isNaN(byte3)) {
|
||||
enc4 = 64;
|
||||
}
|
||||
output += chars.charAt(enc1) + chars.charAt(enc2) + chars.charAt(enc3) + chars.charAt(enc4);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ export class CCBusiness<T extends CCEntity> {
|
||||
* @param event 事件名(枚举)
|
||||
* @param data 事件数据
|
||||
*/
|
||||
emit<K extends keyof OopsFramework.TypedEventMap>(event: K, data: OopsFramework.TypedEventMap[K]): void {
|
||||
emit<K extends keyof OopsFramework.TypedEventMap>(event: K, data?: OopsFramework.TypedEventMap[K]): void {
|
||||
if (this._destroyed) {
|
||||
console.warn('[OopsFramework]', '尝试在已销毁的业务逻辑上触发事件');
|
||||
return;
|
||||
|
||||
@@ -93,7 +93,7 @@ export class GameComponent extends Component {
|
||||
* @param event 事件名(枚举)
|
||||
* @param data 事件数据
|
||||
*/
|
||||
emit<K extends keyof OopsFramework.TypedEventMap>(event: K, data: OopsFramework.TypedEventMap[K]): void {
|
||||
emit<K extends keyof OopsFramework.TypedEventMap>(event: K, data?: OopsFramework.TypedEventMap[K]): void {
|
||||
this.event.emit(event, data);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user