drgame-cc 1.0.50 → 1.0.52
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/drscript/Define.ts +21 -1
- package/drscript/PlatformAdapter.ts +32 -74
- package/drscript/PlatformUtil.ts +30 -0
- package/drscript/UIAdapter.ts +99 -105
- package/drscript/ad-sdk/reporters/reporter.js +1 -1
- package/drscript/component/BtnExtra.ts +4 -11
- package/drscript/focus/FocusManager.ts +167 -170
- package/drscript/focus/FocusVisualLayer.ts +124 -94
- package/package.json +1 -1
- package/drscript/focus/FocusItem.ts +0 -39
- package/drscript/focus/FocusItem.ts.meta +0 -10
- package/drscript/focus/FocusScope.ts +0 -10
- package/drscript/focus/FocusScope.ts.meta +0 -10
package/drscript/Define.ts
CHANGED
|
@@ -48,4 +48,24 @@ export const AnalyticsEventMap: Record<AnalyticsEvent, { ep: string; expose: str
|
|
|
48
48
|
[AnalyticsEvent.WatchVideoContinueButton]: { ep: "watch_video_continue_button", expose: "watch_video_continue_expose", click: "watch_video_continue_click" },
|
|
49
49
|
[AnalyticsEvent.ReplayButton]: { ep: "replay_button", expose: "replay_expose", click: "replay_click" },
|
|
50
50
|
[AnalyticsEvent.RewardVideoAd]: { ep: "reward_video_ad", expose: "ad_expose" },
|
|
51
|
-
};
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/** 奖励模式 */
|
|
54
|
+
export enum AwardModel {
|
|
55
|
+
/** 视频奖励 */
|
|
56
|
+
Video = "video",
|
|
57
|
+
/** 免费 */
|
|
58
|
+
Free = "free",
|
|
59
|
+
/** 付费时间限制 */
|
|
60
|
+
TimeLimit = "time_limit",
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** 渠道类型 */
|
|
64
|
+
export enum EAppItem {
|
|
65
|
+
/** 小米 */
|
|
66
|
+
Xiaomi = "25",
|
|
67
|
+
/** 乐窝 */
|
|
68
|
+
LeWo = "29",
|
|
69
|
+
/** 咪咕 */
|
|
70
|
+
Migu = "30",
|
|
71
|
+
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { AdEvent, AdPlatform, AdSdk, AdType, ActionType, Reporter } from "./ad-sdk/ad-sdk";
|
|
2
|
-
import
|
|
2
|
+
import BtnExtra from "./component/BtnExtra";
|
|
3
3
|
import HelperWin from "./component/HelperWin";
|
|
4
|
-
import { AnalyticsAction, AnalyticsEvent, AnalyticsEventMap, EVideoScene, FingerStyle } from "./Define";
|
|
5
|
-
import FocusVisualLayer from "./focus/FocusVisualLayer";
|
|
4
|
+
import { AnalyticsAction, AnalyticsEvent, AnalyticsEventMap, AwardModel, EAppItem, EVideoScene, FingerStyle } from "./Define";
|
|
6
5
|
import { Loader } from "./Loader";
|
|
6
|
+
import { PlatformUtil } from "./PlatformUtil";
|
|
7
7
|
import { UIAdapter } from "./UIAdapter";
|
|
8
|
-
import { WebBridge } from "./WebBridge";
|
|
9
8
|
|
|
10
9
|
/** 平台适配器,公共 API 入口 */
|
|
11
10
|
export class PlatformAdapter {
|
|
@@ -15,6 +14,10 @@ export class PlatformAdapter {
|
|
|
15
14
|
public static back = UIAdapter.back;
|
|
16
15
|
/** WebBridge */
|
|
17
16
|
public static get webBridge() { return UIAdapter.webBridge; }
|
|
17
|
+
/** 渠道类型 */
|
|
18
|
+
private static appItem: EAppItem = EAppItem.Xiaomi;
|
|
19
|
+
/** 是否是会员 */
|
|
20
|
+
private static isVIP: boolean = false;
|
|
18
21
|
|
|
19
22
|
private static contentId: string = "";
|
|
20
23
|
|
|
@@ -28,20 +31,16 @@ export class PlatformAdapter {
|
|
|
28
31
|
* @param focusIcon 焦点的样式
|
|
29
32
|
*/
|
|
30
33
|
public static async init(cnName: string, minigameID: number, focusIcon: FingerStyle) {
|
|
34
|
+
// ── 初始化渠道类型 ──
|
|
35
|
+
this.appItem = PlatformUtil.getUrlParam('appItem') as EAppItem || EAppItem.Xiaomi;
|
|
36
|
+
this.isVIP = PlatformUtil.getUrlParam('isVIP') === '1';
|
|
37
|
+
|
|
31
38
|
// ── UI 初始化 ──
|
|
32
|
-
|
|
39
|
+
this.focus.setFocusStyle(focusIcon);
|
|
33
40
|
UIAdapter._zhName = cnName;
|
|
34
|
-
UIAdapter.
|
|
35
|
-
UIAdapter.init({ focusEnabled: true });
|
|
41
|
+
await UIAdapter.init();
|
|
36
42
|
|
|
37
43
|
this.contentId = minigameID.toString();
|
|
38
|
-
console.log(`[sdk-version] ${UIAdapter.version}`);
|
|
39
|
-
|
|
40
|
-
// ── Cocos 环境初始化 ──
|
|
41
|
-
if (this.isCocos) {
|
|
42
|
-
UIAdapter.toastPool = new cc.NodePool();
|
|
43
|
-
UIAdapter.prefab = await UIAdapter.loadPrefab('drres/prefab/Toast');
|
|
44
|
-
}
|
|
45
44
|
|
|
46
45
|
// ── 初始化广告 SDK ──
|
|
47
46
|
await AdSdk.init({
|
|
@@ -65,10 +64,7 @@ export class PlatformAdapter {
|
|
|
65
64
|
});
|
|
66
65
|
}
|
|
67
66
|
|
|
68
|
-
// ── 生命周期收尾 ──
|
|
69
67
|
AdSdk.onGameReady(UIAdapter.version);
|
|
70
|
-
UIAdapter.hookLoadScene();
|
|
71
|
-
UIAdapter.back.setFallback(() => UIAdapter.backHandler());
|
|
72
68
|
}
|
|
73
69
|
|
|
74
70
|
// ========================================================================
|
|
@@ -76,18 +72,28 @@ export class PlatformAdapter {
|
|
|
76
72
|
// ========================================================================
|
|
77
73
|
|
|
78
74
|
/** 是否 Cocos 环境 */
|
|
79
|
-
|
|
75
|
+
private static get isCocos() { return window['cc'] != undefined; }
|
|
80
76
|
/** 是否基座环境 */
|
|
81
|
-
|
|
77
|
+
private static get isWebBridge() { return this.webBridge.isAvailable(); }
|
|
82
78
|
/** 是否可以观看视频 */
|
|
83
|
-
|
|
84
|
-
/** 是否 VIP 用户 */
|
|
85
|
-
public static get isVIP() { return UIAdapter._isVIP; }
|
|
79
|
+
private static get canWatchVideo() { return this.isXiaomi; }
|
|
86
80
|
/** 是否小米平台 */
|
|
87
|
-
|
|
81
|
+
private static get isXiaomi() {
|
|
88
82
|
if (typeof window === 'undefined') return null;
|
|
89
83
|
return window['AppBridge'] || null;
|
|
90
84
|
}
|
|
85
|
+
/** 是否需要观看视频 */
|
|
86
|
+
private static get needWatchVideo() {
|
|
87
|
+
return this.canWatchVideo && !this.isVIP;
|
|
88
|
+
}
|
|
89
|
+
private static get needTimeLimit() {
|
|
90
|
+
return !this.isVIP && this.appItem === EAppItem.Migu;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** 奖励模式 */
|
|
94
|
+
public static get awardModel(): AwardModel {
|
|
95
|
+
return this.needWatchVideo ? AwardModel.Video : this.needTimeLimit ? AwardModel.TimeLimit : AwardModel.Free;
|
|
96
|
+
}
|
|
91
97
|
|
|
92
98
|
// ========================================================================
|
|
93
99
|
// Toast
|
|
@@ -101,13 +107,6 @@ export class PlatformAdapter {
|
|
|
101
107
|
// 广告
|
|
102
108
|
// ========================================================================
|
|
103
109
|
|
|
104
|
-
/**
|
|
105
|
-
* 显示奖励视频
|
|
106
|
-
* @param scene 视频场景
|
|
107
|
-
* @param rewardType 奖励类型
|
|
108
|
-
* @param callback 回调函数
|
|
109
|
-
* @param target 回调函数的this指向
|
|
110
|
-
*/
|
|
111
110
|
public static async showRewardVideo(scene: EVideoScene, rewardType: string, callback: Function, target?: any) {
|
|
112
111
|
let finishFired = false;
|
|
113
112
|
let fireFinish = () => {
|
|
@@ -124,7 +123,6 @@ export class PlatformAdapter {
|
|
|
124
123
|
};
|
|
125
124
|
|
|
126
125
|
if (this.canWatchVideo) {
|
|
127
|
-
// 监听奖励(用户完整看完广告触发)
|
|
128
126
|
try {
|
|
129
127
|
const result = await AdSdk.requestAd({
|
|
130
128
|
adType: AdType.RewardVideo,
|
|
@@ -151,50 +149,30 @@ export class PlatformAdapter {
|
|
|
151
149
|
// 按钮注册
|
|
152
150
|
// ========================================================================
|
|
153
151
|
|
|
154
|
-
/**
|
|
155
|
-
* 注册按钮事件,有 BtnExtra 组件会自动切换按钮图片
|
|
156
|
-
* @param button 按钮节点
|
|
157
|
-
*/
|
|
158
152
|
public static registerButton(button: cc.Node) {
|
|
159
153
|
var sprite = button.getComponent(cc.Sprite);
|
|
160
154
|
var btnExtra = button.getComponent(BtnExtra);
|
|
161
155
|
var onFocus = () => { sprite.spriteFrame = btnExtra.hoverSprite; };
|
|
162
156
|
var onRomove = () => { sprite.spriteFrame = btnExtra.normalSprite; };
|
|
163
|
-
|
|
157
|
+
this.focus.register(button, { onFocus: onFocus, onBlur: onRomove });
|
|
164
158
|
}
|
|
165
159
|
|
|
166
|
-
/**
|
|
167
|
-
* 按名称注册按钮
|
|
168
|
-
* @param name 按钮名称
|
|
169
|
-
* @param parent 查找的父节点,默认场景节点
|
|
170
|
-
*/
|
|
171
160
|
public static registerButtonByName(name: string, parent: cc.Node = null) {
|
|
172
161
|
if (!parent) parent = cc.director.getScene();
|
|
173
162
|
let button = this.findChildByName(parent, name);
|
|
174
163
|
this.registerButton(button);
|
|
175
164
|
}
|
|
176
165
|
|
|
177
|
-
/**
|
|
178
|
-
* 导航到指定名称的按钮
|
|
179
|
-
* @param name 按钮名称
|
|
180
|
-
* @param parent 查找的父节点,默认场景节点
|
|
181
|
-
*/
|
|
182
166
|
public static focusButtonByName(name: string, parent: cc.Node = null) {
|
|
183
167
|
if (!parent) parent = cc.director.getScene();
|
|
184
168
|
let button = this.findChildByName(parent, name);
|
|
185
|
-
|
|
169
|
+
this.focus.focus(button);
|
|
186
170
|
}
|
|
187
171
|
|
|
188
|
-
/** 导航到指定按钮 */
|
|
189
172
|
public static focusButton(btn: cc.Node) {
|
|
190
|
-
|
|
173
|
+
this.focus.focus(btn);
|
|
191
174
|
}
|
|
192
175
|
|
|
193
|
-
/**
|
|
194
|
-
* 递归查找指定名称的子节点
|
|
195
|
-
* @param parent 父节点
|
|
196
|
-
* @param name 子节点名称
|
|
197
|
-
*/
|
|
198
176
|
public static findChildByName(parent: cc.Node, name: string): cc.Node | null {
|
|
199
177
|
if (parent.name === name) return parent;
|
|
200
178
|
for (let i = 0; i < parent.children.length; i++) {
|
|
@@ -208,31 +186,20 @@ export class PlatformAdapter {
|
|
|
208
186
|
// 场景 / 窗口 栈
|
|
209
187
|
// ========================================================================
|
|
210
188
|
|
|
211
|
-
/** 显示预制体场景(压入场景栈,返回键可回溯)
|
|
212
|
-
* @param onBack 自定义返回处理,返回 false 表示不关闭,保留当前场景
|
|
213
|
-
*/
|
|
214
189
|
public static showScene(scene: cc.Node, onBack?: () => boolean | void) { UIAdapter.showScene(scene, onBack); }
|
|
215
|
-
/** 关闭预制体场景(从栈中移除,不销毁) */
|
|
216
190
|
public static hideScene(scene: cc.Node) { UIAdapter.hideScene(scene); }
|
|
217
|
-
/** 打开界面
|
|
218
|
-
* @param onBack 自定义返回处理,返回 false 表示不关闭,保留当前窗口
|
|
219
|
-
*/
|
|
220
191
|
public static showWindow(window: cc.Node, onBack?: () => boolean | void) { UIAdapter.showWindow(window, onBack); }
|
|
221
|
-
/** 关闭界面 */
|
|
222
192
|
public static hideWindow(window: cc.Node) { UIAdapter.hideWindow(window); }
|
|
223
|
-
/** 刷新导航按钮 */
|
|
224
193
|
public static refreshFocus(window: cc.Node) { UIAdapter.refreshFocus(window); }
|
|
225
194
|
|
|
226
195
|
// ========================================================================
|
|
227
196
|
// 进度 / 加载
|
|
228
197
|
// ========================================================================
|
|
229
198
|
|
|
230
|
-
/** 设置启动页进度条 */
|
|
231
199
|
public static setProgress(progress: number, tip: string) {
|
|
232
200
|
if (window["setProgress"]) window["setProgress"](progress, tip);
|
|
233
201
|
}
|
|
234
202
|
|
|
235
|
-
/** 关闭启动页 */
|
|
236
203
|
public static closeLoading() {
|
|
237
204
|
if (window["closeLoading"]) window["closeLoading"]();
|
|
238
205
|
}
|
|
@@ -241,12 +208,6 @@ export class PlatformAdapter {
|
|
|
241
208
|
// 上报
|
|
242
209
|
// ========================================================================
|
|
243
210
|
|
|
244
|
-
/**
|
|
245
|
-
* 上报事件
|
|
246
|
-
* @param event 事件类型
|
|
247
|
-
* @param action 操作类型,默认点击
|
|
248
|
-
* @param adRequestId 广告请求ID
|
|
249
|
-
*/
|
|
250
211
|
public static report(event: AnalyticsEvent, action: AnalyticsAction = AnalyticsAction.Click, adRequestId?: string) {
|
|
251
212
|
const def = AnalyticsEventMap[event];
|
|
252
213
|
if (!def) {
|
|
@@ -266,11 +227,9 @@ export class PlatformAdapter {
|
|
|
266
227
|
if (event === AnalyticsEvent.RewardVideoAd && adRequestId) {
|
|
267
228
|
reportItem.ad_request_id = adRequestId;
|
|
268
229
|
}
|
|
269
|
-
// 由 Reporter 内部队列批量上报
|
|
270
230
|
Reporter.report(reportItem);
|
|
271
231
|
}
|
|
272
232
|
|
|
273
|
-
/** 批量上报事件 */
|
|
274
233
|
public static reportBatch(events: AnalyticsEvent[]) {
|
|
275
234
|
if (events.length === 0) return;
|
|
276
235
|
const items: any[] = [];
|
|
@@ -286,7 +245,6 @@ export class PlatformAdapter {
|
|
|
286
245
|
if (items.length > 0) Reporter.reportBatch(items);
|
|
287
246
|
}
|
|
288
247
|
|
|
289
|
-
/** 显示帮助窗口 */
|
|
290
248
|
public static async showHelperWin(url: string, cb: () => void) {
|
|
291
249
|
var key = `${UIAdapter._zhName}-isFirst`;
|
|
292
250
|
var isFirst = cc.sys.localStorage.getItem(key);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export class PlatformUtil {
|
|
2
|
+
static isBrowser: boolean = cc.sys.isBrowser;
|
|
3
|
+
private _browserParams: Map<string, string> = new Map();
|
|
4
|
+
|
|
5
|
+
/** 获取浏览器 URL 查询参数 */
|
|
6
|
+
private get browserParams(): Map<string, string> {
|
|
7
|
+
if (this._browserParams.size > 0) return this._browserParams;
|
|
8
|
+
|
|
9
|
+
const query = window.location.search.substring(1);
|
|
10
|
+
const params = new Map<string, string>();
|
|
11
|
+
if (!query) return params;
|
|
12
|
+
|
|
13
|
+
const vars = query.split("&");
|
|
14
|
+
for (let i = 0; i < vars.length; i++) {
|
|
15
|
+
const pair = vars[i].split("=");
|
|
16
|
+
const key = decodeURIComponent(pair[0]);
|
|
17
|
+
const value = decodeURIComponent(pair[1] || "");
|
|
18
|
+
params.set(key, value);
|
|
19
|
+
}
|
|
20
|
+
this._browserParams = params;
|
|
21
|
+
return params;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** 获取指定 URL 参数的值 */
|
|
25
|
+
static getUrlParam(key: string): string | null {
|
|
26
|
+
if (!PlatformUtil.isBrowser) return null;
|
|
27
|
+
const params = new PlatformUtil().browserParams;
|
|
28
|
+
return params.get(key) || null;
|
|
29
|
+
}
|
|
30
|
+
}
|
package/drscript/UIAdapter.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import FocusManager from "./focus/FocusManager";
|
|
2
|
-
import FocusVisualLayer from "./focus/FocusVisualLayer";
|
|
3
2
|
import { AdSdk } from "./ad-sdk/ad-sdk";
|
|
4
3
|
import { WebBridge } from "./WebBridge";
|
|
5
|
-
import
|
|
4
|
+
import BtnExtra from "./component/BtnExtra";
|
|
6
5
|
import AlertTip from "./component/AlertTip";
|
|
7
6
|
import { Loader } from "./Loader";
|
|
8
7
|
import { KeyAdapter } from "./KeyAdapter";
|
|
@@ -15,10 +14,7 @@ export class UIAdapter {
|
|
|
15
14
|
public static focus = FocusManager;
|
|
16
15
|
|
|
17
16
|
// ---- 内部配置 ----
|
|
18
|
-
private static
|
|
19
|
-
private static _focusEnabled: boolean = true;
|
|
20
|
-
|
|
21
|
-
private static visualLayer: FocusVisualLayer | null = null;
|
|
17
|
+
private static _initialized: boolean = false;
|
|
22
18
|
|
|
23
19
|
// ---- 桥接 / 状态 ----
|
|
24
20
|
public static webBridge: WebBridge;
|
|
@@ -48,78 +44,82 @@ export class UIAdapter {
|
|
|
48
44
|
reset: () => { UIAdapter.backHandlers = []; UIAdapter.backFallback = null; },
|
|
49
45
|
};
|
|
50
46
|
|
|
51
|
-
private static removeBackHandler(handler: () => boolean | void) {
|
|
52
|
-
for (let i = UIAdapter.backHandlers.length - 1; i >= 0; i--) {
|
|
53
|
-
if (UIAdapter.backHandlers[i] === handler) UIAdapter.backHandlers.splice(i, 1);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
private static handleBack(): boolean {
|
|
58
|
-
for (let i = UIAdapter.backHandlers.length - 1; i >= 0; i--) {
|
|
59
|
-
const h = UIAdapter.backHandlers[i];
|
|
60
|
-
if (!h) continue;
|
|
61
|
-
if (h() !== false) return true;
|
|
62
|
-
}
|
|
63
|
-
if (UIAdapter.backFallback) return UIAdapter.backFallback() !== false;
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
47
|
// ========================================================================
|
|
68
48
|
// 初始化
|
|
69
49
|
// ========================================================================
|
|
70
|
-
public static init(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
enableInput?: boolean;
|
|
74
|
-
enableLifecycle?: boolean;
|
|
75
|
-
}) {
|
|
76
|
-
if (UIAdapter.visualLayer) return;
|
|
77
|
-
|
|
78
|
-
if (options) {
|
|
79
|
-
if (options.focusZIndex !== undefined) UIAdapter._focusZIndex = options.focusZIndex;
|
|
80
|
-
if (options.focusEnabled !== undefined) UIAdapter._focusEnabled = options.focusEnabled;
|
|
81
|
-
}
|
|
50
|
+
public static init() {
|
|
51
|
+
if (this._initialized) return;
|
|
52
|
+
this._initialized = true;
|
|
82
53
|
|
|
83
|
-
|
|
84
|
-
|
|
54
|
+
this.webBridge = new WebBridge();
|
|
55
|
+
FocusManager.setFocusZIndex(800);
|
|
56
|
+
FocusManager.initVisualLayer();
|
|
85
57
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const scene = cc.director.getScene();
|
|
89
|
-
UIAdapter.visualLayer = FocusVisualLayer.create(scene);
|
|
90
|
-
}
|
|
58
|
+
KeyAdapter.onBack = () => this.handleBack();
|
|
59
|
+
KeyAdapter.init();
|
|
91
60
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
61
|
+
cc.game.on(cc.game.EVENT_HIDE, this.onGameHide, this);
|
|
62
|
+
cc.game.on(cc.game.EVENT_SHOW, this.onGameShow, this);
|
|
63
|
+
|
|
64
|
+
this.hookLoadScene();
|
|
65
|
+
this.back.setFallback(() => this.backHandler());
|
|
66
|
+
this.initToast();
|
|
67
|
+
|
|
68
|
+
// 自动注册当前场景下的所有按钮
|
|
69
|
+
this.autoRegisterScene();
|
|
70
|
+
}
|
|
97
71
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
72
|
+
/** 自动注册当前场景的按钮 */
|
|
73
|
+
private static autoRegisterScene() {
|
|
74
|
+
let scene = cc.director.getScene();
|
|
75
|
+
if (scene && scene.uuid) {
|
|
76
|
+
// 先清理场景已注册的失效 items
|
|
77
|
+
FocusManager.unregisterByRoot(scene);
|
|
78
|
+
// 注册所有 Button
|
|
79
|
+
FocusManager.registerButtons(scene);
|
|
80
|
+
// 查找 BtnExtra
|
|
81
|
+
this.findBtnExtra(scene);
|
|
102
82
|
}
|
|
103
83
|
}
|
|
104
84
|
|
|
85
|
+
private static async initToast() {
|
|
86
|
+
if (window['cc'] == undefined) return;
|
|
87
|
+
this.toastPool = new cc.NodePool();
|
|
88
|
+
this.prefab = await this.loadPrefab('drres/prefab/Toast');
|
|
89
|
+
}
|
|
90
|
+
|
|
105
91
|
public static destroy() {
|
|
106
|
-
|
|
107
|
-
|
|
92
|
+
if (!this._initialized) return;
|
|
93
|
+
this._initialized = false;
|
|
94
|
+
|
|
95
|
+
cc.game.off(cc.game.EVENT_HIDE, this.onGameHide, this);
|
|
96
|
+
cc.game.off(cc.game.EVENT_SHOW, this.onGameShow, this);
|
|
108
97
|
FocusManager.reset();
|
|
109
98
|
KeyAdapter.destroy();
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (UIAdapter.visualLayer && UIAdapter.visualLayer.node) {
|
|
113
|
-
cc.game?.removePersistRootNode?.(UIAdapter.visualLayer.node);
|
|
114
|
-
UIAdapter.visualLayer.node.destroy();
|
|
115
|
-
}
|
|
116
|
-
UIAdapter.visualLayer = null;
|
|
99
|
+
this.backHandlers = [];
|
|
100
|
+
this.backFallback = null;
|
|
117
101
|
}
|
|
118
102
|
|
|
119
103
|
// ========================================================================
|
|
120
104
|
// 内部实现(供 PlatformAdapter 委托调用)
|
|
121
105
|
// ========================================================================
|
|
122
106
|
|
|
107
|
+
private static removeBackHandler(handler: () => boolean | void) {
|
|
108
|
+
for (let i = this.backHandlers.length - 1; i >= 0; i--) {
|
|
109
|
+
if (this.backHandlers[i] === handler) this.backHandlers.splice(i, 1);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private static handleBack(): boolean {
|
|
114
|
+
for (let i = this.backHandlers.length - 1; i >= 0; i--) {
|
|
115
|
+
const h = this.backHandlers[i];
|
|
116
|
+
if (!h) continue;
|
|
117
|
+
if (h() !== false) return true;
|
|
118
|
+
}
|
|
119
|
+
if (this.backFallback) return this.backFallback() !== false;
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
123
|
static loadPrefab(path: string): Promise<cc.Prefab> {
|
|
124
124
|
return new Promise((resolve, reject) => {
|
|
125
125
|
cc.loader.loadRes(path, cc.Prefab, (err, prefab) => {
|
|
@@ -130,11 +130,11 @@ export class UIAdapter {
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
static showTip(text: string, dur = 1500) {
|
|
133
|
-
if (!
|
|
134
|
-
let node =
|
|
133
|
+
if (!this.toastPool || !this.prefab) return;
|
|
134
|
+
let node = this.toastPool.get();
|
|
135
135
|
let toastComp: AlertTip | null = null;
|
|
136
136
|
if (node == null) {
|
|
137
|
-
node = cc.instantiate(
|
|
137
|
+
node = cc.instantiate(this.prefab);
|
|
138
138
|
toastComp = node.getComponent(AlertTip);
|
|
139
139
|
} else {
|
|
140
140
|
toastComp = node.getComponent(AlertTip);
|
|
@@ -143,13 +143,13 @@ export class UIAdapter {
|
|
|
143
143
|
cc.director.getScene().addChild(node, cc.macro.MAX_ZINDEX);
|
|
144
144
|
}
|
|
145
145
|
node.setPosition(cc.v2(cc.winSize.width / 2, cc.winSize.height / 2));
|
|
146
|
-
|
|
146
|
+
node.active = true;
|
|
147
147
|
if (toastComp) toastComp.show(text);
|
|
148
148
|
setTimeout(() => {
|
|
149
149
|
if (toastComp) {
|
|
150
150
|
toastComp.hide(() => {
|
|
151
151
|
if (node && node.isValid) {
|
|
152
|
-
|
|
152
|
+
this.toastPool.put(node);
|
|
153
153
|
}
|
|
154
154
|
});
|
|
155
155
|
}
|
|
@@ -159,79 +159,73 @@ export class UIAdapter {
|
|
|
159
159
|
|
|
160
160
|
/** 显示预制体场景(压入预制体场景栈,返回键可回溯) */
|
|
161
161
|
static showScene(scene: cc.Node, onBack?: () => boolean | void) {
|
|
162
|
-
let currentTop =
|
|
162
|
+
let currentTop = this.focus.getTopNodeScope();
|
|
163
163
|
if (currentTop && currentTop.nodeType === "scene" && currentTop.node && currentTop.node !== scene && currentTop.node.isValid) {
|
|
164
164
|
currentTop.node.active = false;
|
|
165
165
|
}
|
|
166
166
|
scene.active = true;
|
|
167
|
-
|
|
168
|
-
UIAdapter.focus.pushScope(scene.uuid, {
|
|
167
|
+
this.focus.pushScope(scene.uuid, {
|
|
169
168
|
node: scene,
|
|
170
169
|
nodeType: "scene",
|
|
171
170
|
onBack: onBack,
|
|
172
171
|
skipEnsureFocus: true
|
|
173
172
|
});
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
UIAdapter.findBtnExtra(scene);
|
|
173
|
+
this.focus.registerButtons(scene);
|
|
174
|
+
this.findBtnExtra(scene);
|
|
177
175
|
}
|
|
178
176
|
|
|
179
177
|
/** 关闭预制体场景(从栈中移除,不销毁) */
|
|
180
178
|
static hideScene(scene: cc.Node) {
|
|
181
|
-
|
|
179
|
+
this.focus.removeScope(scene);
|
|
182
180
|
scene.active = false;
|
|
183
181
|
}
|
|
184
182
|
|
|
185
183
|
/** 打开界面注册导航按钮 */
|
|
186
184
|
static showWindow(window: cc.Node, onBack?: () => boolean | void) {
|
|
187
|
-
|
|
188
|
-
UIAdapter.focus.pushScope(window.uuid, {
|
|
185
|
+
this.focus.pushScope(window.uuid, {
|
|
189
186
|
node: window,
|
|
190
187
|
nodeType: "window",
|
|
191
188
|
onBack: onBack,
|
|
192
189
|
skipEnsureFocus: true
|
|
193
190
|
});
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
UIAdapter.findBtnExtra(window);
|
|
191
|
+
this.focus.registerButtons(window);
|
|
192
|
+
this.findBtnExtra(window);
|
|
197
193
|
}
|
|
198
194
|
|
|
199
195
|
/** 关闭界面取消注册按钮事件 */
|
|
200
196
|
static hideWindow(window: cc.Node) {
|
|
201
|
-
|
|
197
|
+
this.focus.removeScope(window);
|
|
202
198
|
}
|
|
203
199
|
|
|
204
200
|
/** 刷新界面按钮事件 */
|
|
205
201
|
static refreshFocus(window: cc.Node) {
|
|
206
|
-
|
|
207
|
-
|
|
202
|
+
this.focus.registerButtons(window);
|
|
203
|
+
this.findBtnExtra(window);
|
|
208
204
|
}
|
|
209
205
|
|
|
210
206
|
/** 返回键处理逻辑 */
|
|
211
207
|
static backHandler(): boolean {
|
|
212
|
-
let top =
|
|
208
|
+
let top = this.focus.getTopNodeScope();
|
|
213
209
|
if (top && top.node) {
|
|
214
210
|
let node = top.node;
|
|
215
211
|
if (!node.isValid) {
|
|
216
|
-
|
|
212
|
+
this.focus.popScope(top.scopeId);
|
|
217
213
|
return true;
|
|
218
214
|
}
|
|
219
215
|
|
|
220
|
-
// 1. 优先用自定义 onBack
|
|
221
216
|
if (top.onBack) {
|
|
222
217
|
let handled = top.onBack() !== false;
|
|
223
218
|
if (handled) {
|
|
224
|
-
|
|
219
|
+
this.focus.removeScope(node);
|
|
225
220
|
}
|
|
226
221
|
return true;
|
|
227
222
|
}
|
|
228
223
|
|
|
229
224
|
if (top.nodeType === "window") {
|
|
230
|
-
|
|
225
|
+
this.focus.removeScope(node);
|
|
231
226
|
node.destroy();
|
|
232
227
|
} else {
|
|
233
|
-
|
|
234
|
-
let scopes = UIAdapter.focus.getScopes();
|
|
228
|
+
let scopes = this.focus.getScopes();
|
|
235
229
|
let hasPrev = false;
|
|
236
230
|
for (let i = scopes.length - 1; i >= 1; i--) {
|
|
237
231
|
if (scopes[i].node && scopes[i].scopeId !== top.scopeId) {
|
|
@@ -240,14 +234,12 @@ export class UIAdapter {
|
|
|
240
234
|
}
|
|
241
235
|
}
|
|
242
236
|
if (!hasPrev) {
|
|
243
|
-
|
|
244
|
-
UIAdapter.showExitWin();
|
|
237
|
+
this.showExitWin();
|
|
245
238
|
return true;
|
|
246
239
|
}
|
|
247
|
-
|
|
248
|
-
UIAdapter.focus.removeScope(node);
|
|
240
|
+
this.focus.removeScope(node);
|
|
249
241
|
node.active = false;
|
|
250
|
-
let prev =
|
|
242
|
+
let prev = this.focus.getTopNodeScope();
|
|
251
243
|
if (prev && prev.node && prev.node.isValid) {
|
|
252
244
|
prev.node.active = true;
|
|
253
245
|
}
|
|
@@ -255,13 +247,12 @@ export class UIAdapter {
|
|
|
255
247
|
return true;
|
|
256
248
|
}
|
|
257
249
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
let prevScene = UIAdapter.sceneStack.pop();
|
|
250
|
+
if (this.sceneStack.length > 0) {
|
|
251
|
+
let prevScene = this.sceneStack.pop();
|
|
261
252
|
cc.director.loadScene(prevScene);
|
|
262
253
|
return true;
|
|
263
254
|
}
|
|
264
|
-
|
|
255
|
+
this.showExitWin();
|
|
265
256
|
return true;
|
|
266
257
|
}
|
|
267
258
|
|
|
@@ -271,8 +262,7 @@ export class UIAdapter {
|
|
|
271
262
|
exitWin.parent = cc.director.getScene();
|
|
272
263
|
exitWin.setPosition(cc.v2(cc.winSize.width / 2, cc.winSize.height / 2));
|
|
273
264
|
|
|
274
|
-
|
|
275
|
-
UIAdapter.focus.pushScope(exitWin.uuid, {
|
|
265
|
+
this.focus.pushScope(exitWin.uuid, {
|
|
276
266
|
node: exitWin,
|
|
277
267
|
nodeType: "window",
|
|
278
268
|
onBack: () => {
|
|
@@ -280,19 +270,23 @@ export class UIAdapter {
|
|
|
280
270
|
},
|
|
281
271
|
skipEnsureFocus: true
|
|
282
272
|
});
|
|
283
|
-
|
|
284
|
-
|
|
273
|
+
this.focus.registerButtons(exitWin);
|
|
274
|
+
this.findBtnExtra(exitWin);
|
|
285
275
|
}
|
|
286
276
|
|
|
287
|
-
/** 拦截 loadScene
|
|
288
|
-
static hookLoadScene() {
|
|
277
|
+
/** 拦截 loadScene 自动记录场景栈,并在新场景加载后自动注册按钮 */
|
|
278
|
+
private static hookLoadScene() {
|
|
289
279
|
const origLoadScene = cc.director.loadScene.bind(cc.director);
|
|
290
280
|
cc.director.loadScene = (sceneName: string, onLaunched?: () => void) => {
|
|
291
281
|
let currentScene = cc.director.getScene();
|
|
292
282
|
if (currentScene && currentScene.name && currentScene.name !== sceneName) {
|
|
293
|
-
|
|
283
|
+
this.sceneStack.push(currentScene.name);
|
|
294
284
|
}
|
|
295
|
-
return origLoadScene(sceneName,
|
|
285
|
+
return origLoadScene(sceneName, () => {
|
|
286
|
+
// 新场景加载后自动注册按钮
|
|
287
|
+
this.autoRegisterScene();
|
|
288
|
+
if (onLaunched) onLaunched();
|
|
289
|
+
});
|
|
296
290
|
};
|
|
297
291
|
}
|
|
298
292
|
|
|
@@ -303,7 +297,7 @@ export class UIAdapter {
|
|
|
303
297
|
let btnExtra = child.getComponent(BtnExtra);
|
|
304
298
|
if (btnExtra) {
|
|
305
299
|
let sprite = child.getComponent(cc.Sprite);
|
|
306
|
-
|
|
300
|
+
this.focus.register(child, {
|
|
307
301
|
onFocus: () => {
|
|
308
302
|
if (sprite) sprite.spriteFrame = btnExtra.hoverSprite;
|
|
309
303
|
},
|
|
@@ -312,7 +306,7 @@ export class UIAdapter {
|
|
|
312
306
|
}
|
|
313
307
|
});
|
|
314
308
|
}
|
|
315
|
-
|
|
309
|
+
this.findBtnExtra(child);
|
|
316
310
|
}
|
|
317
311
|
}
|
|
318
312
|
|
|
@@ -47,7 +47,7 @@ var ActionType = {
|
|
|
47
47
|
// ────────────────────────────────────────
|
|
48
48
|
|
|
49
49
|
/** 配置接口地址 */
|
|
50
|
-
var CONFIG_URL = '
|
|
50
|
+
var CONFIG_URL = 'https://sup.daoran.tv/bi-api/api/config/get';
|
|
51
51
|
|
|
52
52
|
/** 事件队列 */
|
|
53
53
|
var _eventQueue = [];
|