@ives_xxz/framework 1.4.15 → 1.5.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/FW.d.ts +61 -44
- package/Framework.ts +95 -3
- package/FrameworkBase.ts +62 -0
- package/FrameworkBase.ts.meta +10 -0
- package/config/FWSystemConfig.ts +18 -0
- package/controller/FWLayerController.ts +3 -2
- package/data/FWData.ts +2 -5
- package/define/FWEventDefine.ts +4 -0
- package/define/FWSystemDefine.ts +5 -0
- package/entry/FWEntry.ts +9 -18
- package/logic/FWLogic.ts +4 -7
- package/manager/FWAssetManager.ts +62 -67
- package/manager/FWAudioManager.ts +230 -185
- package/manager/FWBundleManager.ts +6 -7
- package/manager/FWEngineManager.ts +8 -0
- package/manager/FWEventManager.ts +91 -2
- package/manager/FWLayerManager.ts +2 -2
- package/manager/FWManager.ts +4 -51
- package/manager/FWObjectManager.ts +100 -33
- package/manager/FWPerformanceManager.ts +32 -34
- package/manager/FWPromiseManager.ts +21 -24
- package/manager/FWResManager.ts +5 -5
- package/manager/FWTaskManager.ts +3 -1
- package/manager/FWTimeManager.ts +12 -40
- package/package.json +1 -1
- package/service/FWService.ts +6 -50
- package/service/http/FWHttp.ts +39 -34
- package/service/socket/FWSocket.ts +7 -11
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FWSystemConfig } from '../config/FWSystemConfig';
|
|
1
2
|
import FWLog from '../log/FWLog';
|
|
2
3
|
import { FWManager } from './FWManager';
|
|
3
4
|
|
|
@@ -41,19 +42,20 @@ export class FWAssetManager extends FWManager implements FW.AssetManager {
|
|
|
41
42
|
bin?: boolean;
|
|
42
43
|
}): Promise<sp.SkeletonData> {
|
|
43
44
|
try {
|
|
44
|
-
return
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
45
|
+
return await this.invoke(
|
|
46
|
+
FW.Entry.promiseMgr.execute((resolve, reject, signal) => {
|
|
47
|
+
const bin = data.bin === undefined ? false : data.bin;
|
|
48
|
+
const img = data.img;
|
|
49
|
+
const ske = data.ske;
|
|
50
|
+
const atlas = data.atlas;
|
|
51
|
+
const type = bin ? '.bin' : '.txt';
|
|
52
|
+
cc.assetManager.loadAny(
|
|
53
|
+
[
|
|
54
|
+
{ url: atlas, ext: type },
|
|
55
|
+
{ url: ske, ext: type },
|
|
56
|
+
],
|
|
57
|
+
async (error, assets) => {
|
|
58
|
+
const texture: cc.Texture2D = await this.loadRemote();
|
|
57
59
|
var asset = new sp.SkeletonData();
|
|
58
60
|
asset.skeletonJson = assets[1];
|
|
59
61
|
asset.atlasText = assets[0];
|
|
@@ -61,29 +63,32 @@ export class FWAssetManager extends FWManager implements FW.AssetManager {
|
|
|
61
63
|
asset['textureNames'] = [`${img}.png`];
|
|
62
64
|
asset['_uuid'] = ske;
|
|
63
65
|
resolve(asset);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
)
|
|
67
|
-
|
|
66
|
+
},
|
|
67
|
+
);
|
|
68
|
+
}, FWSystemConfig.PromiseConfig.loadAsset).promise,
|
|
69
|
+
);
|
|
68
70
|
} catch (e) {
|
|
69
71
|
FWLog.error('从远程加载spine动画资源失败!');
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
/** 加载远程资源 */
|
|
74
|
-
loadRemote<T extends cc.Asset = cc.Asset>(
|
|
76
|
+
async loadRemote<T extends cc.Asset = cc.Asset>(
|
|
75
77
|
url?: string,
|
|
76
78
|
cb?: (asset: cc.Asset) => void,
|
|
77
79
|
): Promise<T> {
|
|
78
|
-
return
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
return await this.invoke(
|
|
81
|
+
FW.Entry.promiseMgr.execute((resolve, reject, signal) => {
|
|
82
|
+
cc.assetManager.loadRemote(url, { cacheEnabled: true, maxRetryCount: 3 }, (err, asset) => {
|
|
83
|
+
if (err || !asset) {
|
|
84
|
+
reject(err);
|
|
85
|
+
}
|
|
86
|
+
cb?.(asset as T);
|
|
87
|
+
resolve(asset as T);
|
|
88
|
+
});
|
|
89
|
+
}, FWSystemConfig.PromiseConfig.loadAsset).promise,
|
|
90
|
+
`loadAssets -> ${url}`,
|
|
91
|
+
);
|
|
87
92
|
}
|
|
88
93
|
|
|
89
94
|
/**
|
|
@@ -132,43 +137,36 @@ export class FWAssetManager extends FWManager implements FW.AssetManager {
|
|
|
132
137
|
assetData.loaded = false;
|
|
133
138
|
|
|
134
139
|
return await this.invoke(
|
|
135
|
-
FW.Entry.promiseMgr.execute(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
(finish
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
(err
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
retryCount: 3,
|
|
168
|
-
retryInterval: 1,
|
|
169
|
-
timeout: 10,
|
|
170
|
-
},
|
|
171
|
-
).promise,
|
|
140
|
+
FW.Entry.promiseMgr.execute((resolve, reject, signal) => {
|
|
141
|
+
const self = this;
|
|
142
|
+
|
|
143
|
+
bundle.load(
|
|
144
|
+
path,
|
|
145
|
+
type,
|
|
146
|
+
(finish: number, total: number, item: cc.AssetManager.RequestItem) => {
|
|
147
|
+
progress?.(finish, total, item);
|
|
148
|
+
},
|
|
149
|
+
(err: Error, asset: cc.Asset) => {
|
|
150
|
+
if (err || !asset) {
|
|
151
|
+
reject(err);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
assetData.loaded = true;
|
|
155
|
+
assetData.dependentBundle = bundleName;
|
|
156
|
+
assetData.uuid = asset['_uuid'];
|
|
157
|
+
assetData.autoRelease = autoRelease;
|
|
158
|
+
assetData.asset = asset;
|
|
159
|
+
assetData.user = assetProperty.user;
|
|
160
|
+
assetData.refCount = 1;
|
|
161
|
+
assetData.assetProperty = assetProperty;
|
|
162
|
+
|
|
163
|
+
self.assetsMap.set(key, assetData);
|
|
164
|
+
|
|
165
|
+
cb?.(assetData);
|
|
166
|
+
resolve(assetData);
|
|
167
|
+
},
|
|
168
|
+
);
|
|
169
|
+
}, FWSystemConfig.PromiseConfig.loadAsset).promise,
|
|
172
170
|
`loadAssets -> ${assetProperty.path}`,
|
|
173
171
|
);
|
|
174
172
|
}
|
|
@@ -322,9 +320,6 @@ export class FWAssetManager extends FWManager implements FW.AssetManager {
|
|
|
322
320
|
* @returns
|
|
323
321
|
*/
|
|
324
322
|
public getReferenceCount(assetProperty: FW.AssetProperty): number {
|
|
325
|
-
const bundleName = assetProperty.bundle || FW.Entry.bundleName;
|
|
326
|
-
const path = assetProperty.path;
|
|
327
|
-
const type = assetProperty.type;
|
|
328
323
|
const key = this.createAssetMapKey(assetProperty);
|
|
329
324
|
return this.assetsMap.get(key)?.refCount || 0;
|
|
330
325
|
}
|
|
@@ -1,29 +1,54 @@
|
|
|
1
1
|
import { FWManager } from './FWManager';
|
|
2
|
-
import Framework from '../Framework';
|
|
3
2
|
import FWLog from '../log/FWLog';
|
|
3
|
+
import { FWSystemDefine } from '../define/FWSystemDefine';
|
|
4
|
+
|
|
5
|
+
class FWAudioData {
|
|
6
|
+
clip: cc.AudioClip;
|
|
7
|
+
volume: number = 1;
|
|
8
|
+
loop: boolean = false;
|
|
9
|
+
cb?: (id: number) => void;
|
|
10
|
+
tag?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
class FWAudioPoolItem {
|
|
14
|
+
constructor(public audioId: number, public startTime: number, public tag?: string) {}
|
|
15
|
+
}
|
|
4
16
|
|
|
5
17
|
export default class FWAudioManager extends FWManager implements FW.AudioManager {
|
|
6
|
-
/**背景音量 */
|
|
7
18
|
musicVolume: number = 1;
|
|
8
|
-
/**音效音量 */
|
|
9
19
|
effectsVolume: number = 1;
|
|
10
|
-
/**播放音效的音量 */
|
|
11
20
|
soundVolume: number = 1;
|
|
12
21
|
|
|
13
|
-
|
|
22
|
+
private audioPool: Map<number, FWAudioPoolItem> = new Map();
|
|
23
|
+
private maxConcurrentAudio: number = 10;
|
|
24
|
+
private cleanupInterval: number = 5;
|
|
14
25
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
26
|
+
public initialize(): void {
|
|
27
|
+
this.autoClear();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 播放背景音乐
|
|
32
|
+
*/
|
|
33
|
+
async playMusic(path: string, volume?: number, loop?: boolean): Promise<void>;
|
|
34
|
+
async playMusic(music: cc.AudioClip, volume?: number, loop?: boolean): Promise<void>;
|
|
35
|
+
async playMusic(assetProperty: FW.AssetProperty, volume?: number, loop?: boolean): Promise<void>;
|
|
36
|
+
async playMusic(): Promise<void> {
|
|
19
37
|
try {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
38
|
+
const audioData = await this.processAudioArguments(
|
|
39
|
+
arguments,
|
|
40
|
+
FWSystemDefine.FWAudioType.MUSIC,
|
|
41
|
+
);
|
|
42
|
+
if (!audioData.clip) return;
|
|
43
|
+
|
|
44
|
+
const volume = audioData.volume ?? this.musicVolume;
|
|
45
|
+
const loop = audioData.loop ?? true;
|
|
46
|
+
|
|
47
|
+
cc.audioEngine.stopMusic();
|
|
48
|
+
const id = cc.audioEngine.playMusic(audioData.clip, loop);
|
|
26
49
|
cc.audioEngine.setVolume(id, volume);
|
|
50
|
+
|
|
51
|
+
FWLog.debug(`播放背景音乐: ${this.getAudioName(audioData.clip)}`);
|
|
27
52
|
} catch (e) {
|
|
28
53
|
FWLog.error('播放音乐失败:', e);
|
|
29
54
|
}
|
|
@@ -32,255 +57,275 @@ export default class FWAudioManager extends FWManager implements FW.AudioManager
|
|
|
32
57
|
stopMusic(): void {
|
|
33
58
|
cc.audioEngine.stopMusic();
|
|
34
59
|
}
|
|
60
|
+
|
|
35
61
|
pauseMusic(): void {
|
|
36
62
|
cc.audioEngine.pauseMusic();
|
|
37
63
|
}
|
|
64
|
+
|
|
38
65
|
resumeMusic(): void {
|
|
39
66
|
cc.audioEngine.resumeMusic();
|
|
40
67
|
}
|
|
41
|
-
|
|
68
|
+
|
|
69
|
+
/** 设置背景音效是否静音 */
|
|
42
70
|
setMusicMute(mute: boolean): void {
|
|
43
|
-
|
|
44
|
-
this.musicVolume = 1;
|
|
45
|
-
} else {
|
|
46
|
-
this.musicVolume = 0;
|
|
47
|
-
}
|
|
71
|
+
this.musicVolume = mute ? 0 : 1;
|
|
48
72
|
cc.audioEngine.setMusicVolume(this.musicVolume);
|
|
49
73
|
}
|
|
50
74
|
|
|
75
|
+
/**
|
|
76
|
+
* 播放音效
|
|
77
|
+
*/
|
|
51
78
|
async play(
|
|
52
79
|
path: string,
|
|
53
80
|
cb?: (id: number) => void,
|
|
54
81
|
volume?: number,
|
|
55
82
|
loop?: boolean,
|
|
83
|
+
tag?: string,
|
|
56
84
|
): Promise<number>;
|
|
57
85
|
async play(
|
|
58
86
|
audio: cc.AudioClip,
|
|
59
87
|
cb?: (id: number) => void,
|
|
60
88
|
volume?: number,
|
|
61
89
|
loop?: boolean,
|
|
90
|
+
tag?: string,
|
|
62
91
|
): Promise<number>;
|
|
63
92
|
async play(
|
|
64
93
|
assetProperty: FW.AssetProperty,
|
|
65
94
|
cb?: (id: number) => void,
|
|
66
95
|
volume?: number,
|
|
67
96
|
loop?: boolean,
|
|
97
|
+
tag?: string,
|
|
68
98
|
): Promise<number>;
|
|
69
99
|
async play(): Promise<number> {
|
|
70
100
|
try {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
101
|
+
if (this.audioPool.size >= this.maxConcurrentAudio) {
|
|
102
|
+
this.clearFinishedAudio();
|
|
103
|
+
if (this.audioPool.size >= this.maxConcurrentAudio) {
|
|
104
|
+
FWLog.warn('音频池已满,无法播放新音频');
|
|
105
|
+
return -1;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const audioData = await this.processAudioArguments(
|
|
110
|
+
arguments,
|
|
111
|
+
FWSystemDefine.FWAudioType.SOUND,
|
|
76
112
|
);
|
|
77
|
-
if (!
|
|
78
|
-
|
|
79
|
-
const volume =
|
|
80
|
-
const loop =
|
|
81
|
-
const
|
|
113
|
+
if (!audioData.clip) return -1;
|
|
114
|
+
|
|
115
|
+
const volume = (audioData.volume ?? this.soundVolume) * this.effectsVolume;
|
|
116
|
+
const loop = audioData.loop ?? false;
|
|
117
|
+
const tag = audioData.tag;
|
|
118
|
+
|
|
119
|
+
const id = cc.audioEngine.play(audioData.clip, loop, volume);
|
|
120
|
+
|
|
121
|
+
this.audioPool.set(id, new FWAudioPoolItem(id, Date.now(), tag));
|
|
122
|
+
|
|
82
123
|
cc.audioEngine.setFinishCallback(id, () => {
|
|
83
|
-
|
|
124
|
+
audioData.cb?.(id);
|
|
125
|
+
this.audioPool.delete(id);
|
|
84
126
|
});
|
|
127
|
+
|
|
85
128
|
return id;
|
|
86
129
|
} catch (e) {
|
|
87
130
|
FWLog.error('播放音效失败:', e);
|
|
131
|
+
return -1;
|
|
88
132
|
}
|
|
89
133
|
}
|
|
134
|
+
|
|
90
135
|
/**
|
|
91
|
-
*
|
|
92
|
-
* @param id 停止
|
|
136
|
+
* 停止指定音效
|
|
93
137
|
*/
|
|
94
|
-
|
|
95
|
-
|
|
138
|
+
stop(id: number): void {
|
|
139
|
+
if (this.audioPool.has(id)) {
|
|
140
|
+
cc.audioEngine.stop(id);
|
|
141
|
+
this.audioPool.delete(id);
|
|
142
|
+
FWLog.debug(`停止音效: ID ${id}`);
|
|
143
|
+
}
|
|
96
144
|
}
|
|
145
|
+
|
|
97
146
|
pauseAll(): void {
|
|
98
147
|
cc.audioEngine.pauseAll();
|
|
148
|
+
FWLog.debug('暂停所有音效');
|
|
99
149
|
}
|
|
150
|
+
|
|
100
151
|
resumeAll(): void {
|
|
101
152
|
cc.audioEngine.resumeAll();
|
|
153
|
+
FWLog.debug('恢复所有音效');
|
|
102
154
|
}
|
|
155
|
+
|
|
103
156
|
stopAll(): void {
|
|
104
157
|
cc.audioEngine.stopAll();
|
|
158
|
+
this.audioPool.clear();
|
|
159
|
+
FWLog.debug('停止所有音效');
|
|
105
160
|
}
|
|
106
|
-
|
|
161
|
+
|
|
162
|
+
/** 设置播放音效是否静音 */
|
|
107
163
|
setSoundMute(mute: boolean): void {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
} else {
|
|
111
|
-
this.soundVolume = 0;
|
|
112
|
-
}
|
|
164
|
+
this.soundVolume = mute ? 0 : 1;
|
|
165
|
+
FWLog.debug(`音效${mute ? '静音' : '取消静音'}`);
|
|
113
166
|
}
|
|
114
167
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
async
|
|
119
|
-
async playEffect(): Promise<number> {
|
|
168
|
+
/**
|
|
169
|
+
* 预加载音频资源
|
|
170
|
+
*/
|
|
171
|
+
async preloadAudio(assetProperty: FW.AssetProperty): Promise<cc.AudioClip> {
|
|
120
172
|
try {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
173
|
+
let clip: cc.AudioClip;
|
|
174
|
+
|
|
175
|
+
if (typeof assetProperty === 'string') {
|
|
176
|
+
clip = await FW.Entry.resMgr.loadAsset<cc.AudioClip>({
|
|
177
|
+
path: assetProperty,
|
|
178
|
+
bundle: FW.Entry.bundleName,
|
|
179
|
+
});
|
|
180
|
+
} else {
|
|
181
|
+
clip = await FW.Entry.resMgr.loadAsset<cc.AudioClip>(assetProperty);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return clip;
|
|
127
185
|
} catch (e) {
|
|
128
|
-
|
|
186
|
+
return null;
|
|
129
187
|
}
|
|
130
188
|
}
|
|
131
189
|
|
|
132
190
|
/**
|
|
133
|
-
*
|
|
134
|
-
* @param effectName 声音文件名
|
|
135
|
-
* @returns
|
|
191
|
+
* 释放音频资源
|
|
136
192
|
*/
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
return cc.audioEngine.stopEffect(audioID);
|
|
193
|
+
releaseAudio(assetProperty: FW.AssetProperty): void {
|
|
194
|
+
FW.Entry.resMgr.releaseAsset(assetProperty);
|
|
140
195
|
}
|
|
196
|
+
|
|
141
197
|
/**
|
|
142
|
-
*
|
|
143
|
-
* @param volume 音量
|
|
198
|
+
* 获取音频池信息
|
|
144
199
|
*/
|
|
145
|
-
|
|
146
|
-
|
|
200
|
+
getAudioPoolInfo(): { playing: number; maxConcurrent: number } {
|
|
201
|
+
return {
|
|
202
|
+
playing: this.audioPool.size,
|
|
203
|
+
maxConcurrent: this.maxConcurrentAudio,
|
|
204
|
+
};
|
|
147
205
|
}
|
|
206
|
+
|
|
148
207
|
/**
|
|
149
|
-
*
|
|
208
|
+
* 设置最大并发音频数
|
|
150
209
|
*/
|
|
151
|
-
|
|
152
|
-
|
|
210
|
+
setMaxConcurrentAudio(max: number): void {
|
|
211
|
+
this.maxConcurrentAudio = Math.max(1, max);
|
|
153
212
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* 根据标签停止音效
|
|
216
|
+
*/
|
|
217
|
+
stopByTag(tag: string): void {
|
|
218
|
+
const arr: number[] = [];
|
|
219
|
+
|
|
220
|
+
this.audioPool.forEach((item, id) => {
|
|
221
|
+
if (item.tag === tag) {
|
|
222
|
+
arr.push(id);
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
arr.forEach((id) => {
|
|
227
|
+
this.stop(id);
|
|
228
|
+
});
|
|
162
229
|
}
|
|
163
230
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
volume?: number,
|
|
180
|
-
loop?: boolean,
|
|
181
|
-
): Promise<{
|
|
182
|
-
clip: cc.AudioClip;
|
|
183
|
-
volume: number;
|
|
184
|
-
loop: boolean;
|
|
185
|
-
cb: (id: number) => void;
|
|
186
|
-
}>;
|
|
187
|
-
|
|
188
|
-
private async dataProcessing(
|
|
189
|
-
assetProperty: FW.AssetProperty,
|
|
190
|
-
cb?: (id: number) => void,
|
|
191
|
-
volume?: number,
|
|
192
|
-
loop?: boolean,
|
|
193
|
-
): Promise<{
|
|
194
|
-
clip: cc.AudioClip;
|
|
195
|
-
volume: number;
|
|
196
|
-
loop: boolean;
|
|
197
|
-
cb: (id: number) => void;
|
|
198
|
-
}>;
|
|
199
|
-
|
|
200
|
-
private async dataProcessing(
|
|
201
|
-
path: string,
|
|
202
|
-
volume?: number,
|
|
203
|
-
loop?: boolean,
|
|
204
|
-
): Promise<{
|
|
205
|
-
clip: cc.AudioClip;
|
|
206
|
-
volume: number;
|
|
207
|
-
loop: boolean;
|
|
208
|
-
cb: (id: number) => void;
|
|
209
|
-
}>;
|
|
210
|
-
private async dataProcessing(
|
|
211
|
-
music: cc.AudioClip,
|
|
212
|
-
volume?: number,
|
|
213
|
-
loop?: boolean,
|
|
214
|
-
): Promise<{
|
|
215
|
-
clip: cc.AudioClip;
|
|
216
|
-
volume: number;
|
|
217
|
-
loop: boolean;
|
|
218
|
-
cb: (id: number) => void;
|
|
219
|
-
}>;
|
|
220
|
-
private async dataProcessing(
|
|
221
|
-
assetProperty: FW.AssetProperty,
|
|
222
|
-
volume?: number,
|
|
223
|
-
loop?: boolean,
|
|
224
|
-
): Promise<{
|
|
225
|
-
clip: cc.AudioClip;
|
|
226
|
-
volume: number;
|
|
227
|
-
loop: boolean;
|
|
228
|
-
cb: (id: number) => void;
|
|
229
|
-
}>;
|
|
230
|
-
private async dataProcessing(): Promise<{
|
|
231
|
-
clip: cc.AudioClip;
|
|
232
|
-
volume: number;
|
|
233
|
-
loop: boolean;
|
|
234
|
-
cb: (id: number) => void;
|
|
235
|
-
}> {
|
|
236
|
-
let clip: cc.AudioClip;
|
|
237
|
-
if (typeof arguments[0] === 'string') {
|
|
238
|
-
const bundle = FW.Entry.bundleName;
|
|
239
|
-
const path = arguments[0];
|
|
240
|
-
clip = await FW.Entry.resMgr.loadAsset<cc.AudioClip>(<FW.AssetProperty>{
|
|
241
|
-
path: path,
|
|
242
|
-
bundle: bundle,
|
|
243
|
-
});
|
|
244
|
-
} else if (typeof arguments[0] === 'object') {
|
|
245
|
-
const bundle = (arguments[0] as FW.AssetProperty).bundle || FW.Entry.bundleName;
|
|
246
|
-
const path = (arguments[0] as FW.AssetProperty).path;
|
|
247
|
-
clip = await FW.Entry.resMgr.loadAsset<cc.AudioClip>(<FW.AssetProperty>{
|
|
248
|
-
path: path,
|
|
249
|
-
bundle: bundle,
|
|
250
|
-
});
|
|
251
|
-
} else if (arguments[0] instanceof cc.AudioClip) {
|
|
252
|
-
clip = arguments[0];
|
|
231
|
+
/**
|
|
232
|
+
* 处理音频参数
|
|
233
|
+
*/
|
|
234
|
+
private async processAudioArguments(
|
|
235
|
+
args: IArguments,
|
|
236
|
+
type: FWSystemDefine.FWAudioType,
|
|
237
|
+
): Promise<FWAudioData> {
|
|
238
|
+
const audioData = new FWAudioData();
|
|
239
|
+
const argsArray = Array.from(args);
|
|
240
|
+
|
|
241
|
+
if (argsArray[0] instanceof cc.AudioClip) {
|
|
242
|
+
audioData.clip = argsArray[0];
|
|
243
|
+
} else {
|
|
244
|
+
const assetProperty = this.normalizeAssetProperty(argsArray[0]);
|
|
245
|
+
audioData.clip = await this.loadAudioClip(assetProperty);
|
|
253
246
|
}
|
|
254
247
|
|
|
255
|
-
|
|
248
|
+
if (type === FWSystemDefine.FWAudioType.MUSIC) {
|
|
249
|
+
audioData.volume = argsArray[1];
|
|
250
|
+
audioData.loop = argsArray[2];
|
|
251
|
+
} else {
|
|
252
|
+
audioData.cb = argsArray[1];
|
|
253
|
+
audioData.volume = argsArray[2];
|
|
254
|
+
audioData.loop = argsArray[3];
|
|
255
|
+
audioData.tag = argsArray[4];
|
|
256
|
+
}
|
|
256
257
|
|
|
257
|
-
|
|
258
|
+
return audioData;
|
|
259
|
+
}
|
|
258
260
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
261
|
+
/**
|
|
262
|
+
* 标准化资源属性
|
|
263
|
+
*/
|
|
264
|
+
private normalizeAssetProperty(input: any): FW.AssetProperty {
|
|
265
|
+
if (typeof input === 'string') {
|
|
266
|
+
return {
|
|
267
|
+
path: input,
|
|
268
|
+
bundle: FW.Entry.bundleName,
|
|
269
|
+
};
|
|
266
270
|
}
|
|
271
|
+
return input;
|
|
272
|
+
}
|
|
267
273
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
274
|
+
/**
|
|
275
|
+
* 加载音频片段
|
|
276
|
+
*/
|
|
277
|
+
private async loadAudioClip(assetProperty: FW.AssetProperty): Promise<cc.AudioClip> {
|
|
278
|
+
try {
|
|
279
|
+
return await FW.Entry.resMgr.loadAsset<cc.AudioClip>(assetProperty);
|
|
280
|
+
} catch (e) {
|
|
281
|
+
return null;
|
|
272
282
|
}
|
|
283
|
+
}
|
|
273
284
|
|
|
274
|
-
|
|
275
|
-
|
|
285
|
+
/**
|
|
286
|
+
* 生成缓存键
|
|
287
|
+
*/
|
|
288
|
+
private getCacheKey(assetProperty: FW.AssetProperty): string {
|
|
289
|
+
if (typeof assetProperty === 'string') {
|
|
290
|
+
return `${FW.Entry.bundleName}_${assetProperty}`;
|
|
276
291
|
}
|
|
292
|
+
return `${assetProperty.bundle || FW.Entry.bundleName}_${assetProperty.path}`;
|
|
293
|
+
}
|
|
277
294
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
295
|
+
/**
|
|
296
|
+
* 获取音频名称
|
|
297
|
+
*/
|
|
298
|
+
private getAudioName(clip: cc.AudioClip): string {
|
|
299
|
+
return clip.name || '未知音频';
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* 清理已完成的音频
|
|
304
|
+
*/
|
|
305
|
+
private clearFinishedAudio(): void {
|
|
306
|
+
const currentTime = Date.now();
|
|
307
|
+
const maxAge = 30000;
|
|
308
|
+
|
|
309
|
+
this.audioPool.forEach((item, id) => {
|
|
310
|
+
if (!cc.audioEngine.getState(id)) {
|
|
311
|
+
this.audioPool.delete(id);
|
|
312
|
+
} else if (currentTime - item.startTime > maxAge) {
|
|
313
|
+
FWLog.warn(`强制停止超时音频: ID ${id}`);
|
|
314
|
+
this.stop(id);
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* 启动自动清理
|
|
321
|
+
*/
|
|
322
|
+
private autoClear(): void {
|
|
323
|
+
FW.Entry.timeMgr.schedule(
|
|
324
|
+
this.clearFinishedAudio,
|
|
325
|
+
this.cleanupInterval,
|
|
326
|
+
cc.macro.REPEAT_FOREVER,
|
|
327
|
+
this,
|
|
328
|
+
);
|
|
284
329
|
}
|
|
285
330
|
|
|
286
331
|
public onDestroy(): void {
|