@cc-component/cc-guide 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cc-ex-component.md +12 -0
- package/assets/guide/common/GuideTool.ts +33 -0
- package/assets/guide/common/GuideTool.ts.meta +9 -0
- package/assets/guide/common/Log.ts +82 -0
- package/assets/guide/common/Log.ts.meta +9 -0
- package/assets/guide/common/ViewUtil.ts +163 -0
- package/assets/guide/common/ViewUtil.ts.meta +9 -0
- package/assets/guide/common.meta +9 -0
- package/assets/guide/guide/Guide.ts +42 -0
- package/assets/guide/guide/Guide.ts.meta +9 -0
- package/assets/guide/guide/GuideCenter.ts +364 -0
- package/assets/guide/guide/GuideCenter.ts.meta +9 -0
- package/assets/guide/guide/GuideSDK.ts +71 -0
- package/assets/guide/guide/GuideSDK.ts.meta +9 -0
- package/assets/guide/guide/model/GuideCommon.ts +27 -0
- package/assets/guide/guide/model/GuideCommon.ts.meta +9 -0
- package/assets/guide/guide/model/GuideModelComp.ts +161 -0
- package/assets/guide/guide/model/GuideModelComp.ts.meta +9 -0
- package/assets/guide/guide/model/ITableGuide.ts +32 -0
- package/assets/guide/guide/model/ITableGuide.ts.meta +9 -0
- package/assets/guide/guide/model/ITableNPC.ts +10 -0
- package/assets/guide/guide/model/ITableNPC.ts.meta +9 -0
- package/assets/guide/guide/model.meta +12 -0
- package/assets/guide/guide/view/GuideTest.ts +150 -0
- package/assets/guide/guide/view/GuideTest.ts.meta +9 -0
- package/assets/guide/guide/view/GuideViewComp.ts +299 -0
- package/assets/guide/guide/view/GuideViewComp.ts.meta +9 -0
- package/assets/guide/guide/view/GuideViewItem.ts +104 -0
- package/assets/guide/guide/view/GuideViewItem.ts.meta +9 -0
- package/assets/guide/guide/view/GuideViewMask.ts +342 -0
- package/assets/guide/guide/view/GuideViewMask.ts.meta +9 -0
- package/assets/guide/guide/view/GuideViewPrompt.ts +178 -0
- package/assets/guide/guide/view/GuideViewPrompt.ts.meta +9 -0
- package/assets/guide/guide/view/PolygonMask.ts +161 -0
- package/assets/guide/guide/view/PolygonMask.ts.meta +9 -0
- package/assets/guide/guide/view/touch.ts.meta +9 -0
- package/assets/guide/guide/view.meta +12 -0
- package/assets/guide/guide.meta +9 -0
- package/assets/guide/interface/GuideModule.ts +54 -0
- package/assets/guide/interface/GuideModule.ts.meta +1 -0
- package/assets/guide/interface/Interface.ts +44 -0
- package/assets/guide/interface/Interface.ts.meta +9 -0
- package/assets/guide/interface/guide/mask.prefab +716 -0
- package/assets/guide/interface/guide/mask.prefab.meta +13 -0
- package/assets/guide/interface/guide/prompt.prefab +1524 -0
- package/assets/guide/interface/guide/prompt.prefab.meta +13 -0
- package/assets/guide/interface/guide/skeleton.atlas +20 -0
- package/assets/guide/interface/guide/skeleton.atlas.meta +12 -0
- package/assets/guide/interface/guide/skeleton.json +1 -0
- package/assets/guide/interface/guide/skeleton.json.meta +13 -0
- package/assets/guide/interface/guide/skeleton.png +0 -0
- package/assets/guide/interface/guide/skeleton.png.meta +134 -0
- package/assets/guide/interface/guide.meta +9 -0
- package/assets/guide/interface.meta +1 -0
- package/assets/guide.meta +11 -0
- package/assets.meta +9 -0
- package/index.ts +5 -0
- package/index.ts.meta +9 -0
- package/package.json +19 -0
- package/package.json.meta +11 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Layers, Node, Widget } from "cc";
|
|
2
|
+
export function CreateNode(name: string) {
|
|
3
|
+
const node = new Node(name);
|
|
4
|
+
node.layer = Layers.Enum.UI_2D;
|
|
5
|
+
const w: Widget = node.addComponent(Widget);
|
|
6
|
+
w.isAlignLeft = w.isAlignRight = w.isAlignTop = w.isAlignBottom = true;
|
|
7
|
+
w.left = w.right = w.top = w.bottom = 0;
|
|
8
|
+
w.alignMode = 2;
|
|
9
|
+
w.enabled = true;
|
|
10
|
+
return node;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
export function IsJson(value: string) {
|
|
15
|
+
const str = value
|
|
16
|
+
// 检查是否为字符串类型
|
|
17
|
+
if (typeof str !== 'string') {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// 检查是否为空字符串
|
|
22
|
+
if (str.trim().length === 0) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const parsed = JSON.parse(str);
|
|
28
|
+
// 确保解析结果是对象或数组(JSON的顶级必须是对象或数组)
|
|
29
|
+
return (typeof parsed === 'object' && parsed !== null) || Array.isArray(parsed);
|
|
30
|
+
} catch (e) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
|
|
2
|
+
export const Log = {
|
|
3
|
+
_enabled: true,
|
|
4
|
+
|
|
5
|
+
enable(enabled: boolean): void {
|
|
6
|
+
this._enabled = enabled;
|
|
7
|
+
},
|
|
8
|
+
|
|
9
|
+
// 自动从调用栈中提取用户代码的文件名和行号
|
|
10
|
+
_getCallerInfo(): string {
|
|
11
|
+
// 仅在 Cocos 编辑器预览中启用自动调用位置(最可靠)
|
|
12
|
+
if (!this._enabled) return '';
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
const stack = new Error().stack;
|
|
16
|
+
if (!stack) return '';
|
|
17
|
+
// console.log(stack)
|
|
18
|
+
|
|
19
|
+
const lines = stack.split('\n');
|
|
20
|
+
for (let i = 2; i < lines.length; i++) {
|
|
21
|
+
const line = lines[i].trim();
|
|
22
|
+
if (!line || line.includes('ExTool.ts')) continue;
|
|
23
|
+
//console.log(line)
|
|
24
|
+
// console.log("-----------------------------------------")
|
|
25
|
+
// 匹配 Cocos 编辑器中的典型格式:
|
|
26
|
+
// at onLoad (assets/scripts/GameCtrl.ts:25:12)
|
|
27
|
+
const match = line.match(/assets\/[^)]+\.ts:(\d+):\d+/);
|
|
28
|
+
if (match) {
|
|
29
|
+
const full = match[0];
|
|
30
|
+
const parts = full.split('/');
|
|
31
|
+
const fileAndLine = parts[parts.length - 1]; // "GameCtrl.ts:25"
|
|
32
|
+
return fileAndLine;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
} catch (e) {
|
|
36
|
+
// ignore
|
|
37
|
+
}
|
|
38
|
+
return '';
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
debug(message?: any, ...optionalParams: any[]): void {
|
|
42
|
+
if (this._enabled) {
|
|
43
|
+
const caller = this._getCallerInfo();
|
|
44
|
+
console.debug?.(`[DEBUG][${caller}]`, message, ...optionalParams);
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
error(message?: any, ...optionalParams: any[]): void {
|
|
48
|
+
if (this._enabled) {
|
|
49
|
+
const caller = this._getCallerInfo();
|
|
50
|
+
console.error?.(`[ERROR][${caller}]`, message, ...optionalParams);
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
group(groupTitle?: string, ...optionalParams: any[]): void {
|
|
54
|
+
if (this._enabled) {
|
|
55
|
+
const caller = this._getCallerInfo();
|
|
56
|
+
console.group?.(`[GROUP][${caller}] ${groupTitle || ''}`, ...optionalParams);
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
groupEnd(): void {
|
|
60
|
+
if (this._enabled) {
|
|
61
|
+
console.groupEnd?.();
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
info(message?: any, ...optionalParams: any[]): void {
|
|
65
|
+
if (this._enabled) {
|
|
66
|
+
const caller = this._getCallerInfo();
|
|
67
|
+
console.info?.(`[INFO][${caller}]`, message, ...optionalParams);
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
log(message?: any, ...optionalParams: any[]): void {
|
|
71
|
+
if (this._enabled) {
|
|
72
|
+
const caller = this._getCallerInfo();
|
|
73
|
+
console.log?.(`[LOG][${caller}]`, message, ...optionalParams);
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
warn(message?: any, ...optionalParams: any[]): void {
|
|
77
|
+
if (this._enabled) {
|
|
78
|
+
const caller = this._getCallerInfo();
|
|
79
|
+
console.warn?.(`[WARN][${caller}]`, message, ...optionalParams);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: dgflash
|
|
3
|
+
* @Date: 2021-08-16 09:34:56
|
|
4
|
+
* @LastEditors: dgflash
|
|
5
|
+
* @LastEditTime: 2023-01-19 14:52:12
|
|
6
|
+
*/
|
|
7
|
+
import { Animation, AnimationClip, EventTouch, instantiate, Node, Prefab, Size, UITransform, v3, Vec3 } from "cc";
|
|
8
|
+
|
|
9
|
+
/** 显示对象工具 */
|
|
10
|
+
export class ViewUtil {
|
|
11
|
+
/**
|
|
12
|
+
* 把Node当前的节点树结构根据Node命名转成一个js对象,重名的组件会覆盖,
|
|
13
|
+
* Node的name不应该包含空格键,否则将跳过
|
|
14
|
+
* @param parent 被遍历的Node组件
|
|
15
|
+
* @param obj 绑定的js对象 (可选)
|
|
16
|
+
*/
|
|
17
|
+
static nodeTreeInfoLite(parent: Node, obj?: Map<string, Node>): Map<string, Node> | null {
|
|
18
|
+
let map: Map<string, Node> = obj || new Map();
|
|
19
|
+
let items = parent.children;
|
|
20
|
+
for (let i = 0; i < items.length; i++) {
|
|
21
|
+
let _node = items[i];
|
|
22
|
+
if (_node.name.indexOf(" ") < 0) {
|
|
23
|
+
map.set(_node.name, _node);
|
|
24
|
+
}
|
|
25
|
+
ViewUtil.nodeTreeInfoLite(_node, map);
|
|
26
|
+
}
|
|
27
|
+
return map;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 正则搜索节点名字,符合条件的节点将会返回
|
|
32
|
+
* @param reg 正则表达式
|
|
33
|
+
* @param parent 要搜索的父节点
|
|
34
|
+
* @param nodes 返回的数组(可选)
|
|
35
|
+
*/
|
|
36
|
+
static findNodes(reg: RegExp, parent: Node, nodes?: Array<Node>): Array<Node> {
|
|
37
|
+
let ns: Array<Node> = nodes || [];
|
|
38
|
+
let items = parent.children;
|
|
39
|
+
for (let i = 0; i < items.length; i++) {
|
|
40
|
+
let _name: string = items[i].name;
|
|
41
|
+
if (reg.test(_name)) {
|
|
42
|
+
ns.push(items[i]);
|
|
43
|
+
}
|
|
44
|
+
ViewUtil.findNodes(reg, items[i], ns);
|
|
45
|
+
}
|
|
46
|
+
return ns;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 节点之间坐标互转
|
|
51
|
+
* @param a A节点
|
|
52
|
+
* @param b B节点
|
|
53
|
+
* @param aPos A节点空间中的相对位置
|
|
54
|
+
*/
|
|
55
|
+
static calculateASpaceToBSpacePos(a: Node, b: Node, aPos: Vec3): Vec3 {
|
|
56
|
+
const world: Vec3 = a.getComponent(UITransform)!.convertToWorldSpaceAR(aPos);
|
|
57
|
+
return b.getComponent(UITransform)!.convertToNodeSpaceAR(world);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 屏幕转空间坐标
|
|
62
|
+
* @param event 触摸事件
|
|
63
|
+
* @param space 转到此节点的坐标空间
|
|
64
|
+
*/
|
|
65
|
+
static calculateScreenPosToSpacePos(event: EventTouch, space: Node): Vec3 {
|
|
66
|
+
const uil = event.getUILocation();
|
|
67
|
+
const worldPos: Vec3 = v3(uil.x, uil.y);
|
|
68
|
+
return space.getComponent(UITransform)!.convertToNodeSpaceAR(worldPos);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// /**
|
|
72
|
+
// * 显示对象等比缩放
|
|
73
|
+
// * @param targetWidth 目标宽
|
|
74
|
+
// * @param targetHeight 目标高
|
|
75
|
+
// * @param defaultWidth 默认宽
|
|
76
|
+
// * @param defaultHeight 默认高
|
|
77
|
+
// */
|
|
78
|
+
// static uniformScale(targetWidth: number, targetHeight: number, defaultWidth: number, defaultHeight: number) {
|
|
79
|
+
// const widthRatio = defaultWidth / targetWidth;
|
|
80
|
+
// const heightRatio = defaultHeight / targetHeight;
|
|
81
|
+
// let ratio;
|
|
82
|
+
// widthRatio < heightRatio ? ratio = widthRatio : ratio = heightRatio;
|
|
83
|
+
// return new Size(Math.floor(targetWidth * ratio), Math.floor(targetHeight * ratio));
|
|
84
|
+
// }
|
|
85
|
+
|
|
86
|
+
// /**
|
|
87
|
+
// * 从资源缓存中找到预制资源名并创建一个显示对象(建议使用GameComponent里的同名方法,能自动管理内存施放)
|
|
88
|
+
// * @param path 资源路径
|
|
89
|
+
// * @param bundleName 资源包名
|
|
90
|
+
// */
|
|
91
|
+
// static createPrefabNode(path: string, bundleName: string = resLoader.defaultBundleName): Node {
|
|
92
|
+
// const p = resLoader.get(path, Prefab, bundleName);
|
|
93
|
+
// if (p) {
|
|
94
|
+
// return instantiate(p);
|
|
95
|
+
// }
|
|
96
|
+
// return null!;
|
|
97
|
+
// }
|
|
98
|
+
|
|
99
|
+
// /**
|
|
100
|
+
// * 加载预制并创建预制节点(建议使用GameComponent里的同名方法,能自动管理内存施放)
|
|
101
|
+
// * @param path 资源路径
|
|
102
|
+
// * @param bundleName 资源包名
|
|
103
|
+
// */
|
|
104
|
+
// static createPrefabNodeAsync(path: string, bundleName: string = resLoader.defaultBundleName): Promise<Node> {
|
|
105
|
+
// return new Promise(async (resolve, reject) => {
|
|
106
|
+
// const p = await resLoader.loadAsync(bundleName, path, Prefab);
|
|
107
|
+
// if (p) {
|
|
108
|
+
// resolve(instantiate(p));
|
|
109
|
+
// }
|
|
110
|
+
// else {
|
|
111
|
+
// Log.error(`名为【${path}】的资源加载失败`);
|
|
112
|
+
// resolve(null!);
|
|
113
|
+
// }
|
|
114
|
+
// });
|
|
115
|
+
// }
|
|
116
|
+
|
|
117
|
+
// /**
|
|
118
|
+
// * 添加节点动画
|
|
119
|
+
// * @param path 资源路径
|
|
120
|
+
// * @param node 目标节点
|
|
121
|
+
// * @param onlyOne 是否唯一
|
|
122
|
+
// * @param isDefaultClip 是否播放默认动画剪辑
|
|
123
|
+
// */
|
|
124
|
+
// static addNodeAnimation(path: string, node: Node, onlyOne: boolean = true, isDefaultClip: boolean = false) {
|
|
125
|
+
// if (!node || !node.isValid) {
|
|
126
|
+
// return;
|
|
127
|
+
// }
|
|
128
|
+
|
|
129
|
+
// let anim = node.getComponent(Animation);
|
|
130
|
+
// if (anim == null) {
|
|
131
|
+
// anim = node.addComponent(Animation);
|
|
132
|
+
// }
|
|
133
|
+
|
|
134
|
+
// const clip = resLoader.get(path, AnimationClip) as AnimationClip;
|
|
135
|
+
// if (!clip) {
|
|
136
|
+
// return;
|
|
137
|
+
// }
|
|
138
|
+
|
|
139
|
+
// if (onlyOne && anim.getState(clip.name) && anim.getState(clip.name).isPlaying) {
|
|
140
|
+
// return;
|
|
141
|
+
// }
|
|
142
|
+
|
|
143
|
+
// if (isDefaultClip) {
|
|
144
|
+
// anim.defaultClip = clip;
|
|
145
|
+
// anim.play();
|
|
146
|
+
// return;
|
|
147
|
+
// }
|
|
148
|
+
|
|
149
|
+
// // 播放完成后恢复播放默认动画
|
|
150
|
+
// anim.once(Animation.EventType.FINISHED, () => {
|
|
151
|
+
// if (anim!.defaultClip) {
|
|
152
|
+
// anim!.play();
|
|
153
|
+
// }
|
|
154
|
+
// }, this);
|
|
155
|
+
|
|
156
|
+
// if (anim.getState(clip.name)) {
|
|
157
|
+
// anim.play(clip.name);
|
|
158
|
+
// return
|
|
159
|
+
// }
|
|
160
|
+
// anim.createState(clip, clip!.name);
|
|
161
|
+
// anim.play(clip!.name);
|
|
162
|
+
// }
|
|
163
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
|
|
2
|
+
/*
|
|
3
|
+
* @Author: dgflash
|
|
4
|
+
* @Date: 2021-11-18 17:47:56
|
|
5
|
+
* @LastEditors: dgflash
|
|
6
|
+
* @LastEditTime: 2022-09-06 10:15:10
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { IGuideData } from "./model/GuideCommon";
|
|
10
|
+
import { GuideModelComp } from "./model/GuideModelComp";
|
|
11
|
+
import { GuideViewComp } from "./view/GuideViewComp";
|
|
12
|
+
import { Node } from "cc";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 新手引导
|
|
16
|
+
* 1、组件方式绑定到引导 Node 上自动注册引导数据
|
|
17
|
+
* 2、通过设置引导步骤可回复到上次引导点
|
|
18
|
+
* 3、触发引导分为穿透模式与事件模拟模式(模拟模式不会导致不规则图形在引导区域中导致误点)
|
|
19
|
+
*/
|
|
20
|
+
export class Guide {
|
|
21
|
+
GuideModel!: GuideModelComp;
|
|
22
|
+
GuideView!: GuideViewComp;
|
|
23
|
+
init(param: IGuideData) {
|
|
24
|
+
this.GuideModel = new GuideModelComp();
|
|
25
|
+
this.GuideModel.loadData(param)
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** 加载引导资源 */
|
|
30
|
+
load(node: Node) {
|
|
31
|
+
this.GuideView = node.addComponent(GuideViewComp);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** 检查指定引导是否触发 */
|
|
35
|
+
check(step: number) {
|
|
36
|
+
if (this.GuideModel) {
|
|
37
|
+
this.GuideModel.step = step;
|
|
38
|
+
this.GuideView.check();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
}
|