@cc-component/cc-core 1.2.8
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/core/config/CommonEnum.ts +94 -0
- package/assets/core/config/CommonEnum.ts.meta +9 -0
- package/assets/core/config/IConfig.ts +89 -0
- package/assets/core/config/IConfig.ts.meta +9 -0
- package/assets/core/config/LayerType.ts +44 -0
- package/assets/core/config/LayerType.ts.meta +9 -0
- package/assets/core/config/LayerUI.ts +113 -0
- package/assets/core/config/LayerUI.ts.meta +9 -0
- package/assets/core/config.meta +9 -0
- package/assets/core/editor/LanguageManager.ts +323 -0
- package/assets/core/editor/LanguageManager.ts.meta +9 -0
- package/assets/core/editor/SpineRunner.ts +39 -0
- package/assets/core/editor/SpineRunner.ts.meta +9 -0
- package/assets/core/editor/i18nEditorComponent.ts +137 -0
- package/assets/core/editor/i18nEditorComponent.ts.meta +9 -0
- package/assets/core/editor.meta +9 -0
- package/assets/core/home/AudioUtil.ts +164 -0
- package/assets/core/home/AudioUtil.ts.meta +9 -0
- package/assets/core/home/BaseBoxView.ts +60 -0
- package/assets/core/home/BaseBoxView.ts.meta +9 -0
- package/assets/core/home/BaseLaunchComponent.ts +9 -0
- package/assets/core/home/BaseLaunchComponent.ts.meta +9 -0
- package/assets/core/home/BaseLoading.ts +136 -0
- package/assets/core/home/BaseLoading.ts.meta +9 -0
- package/assets/core/home/BaseSkeleton.ts +39 -0
- package/assets/core/home/BaseSkeleton.ts.meta +9 -0
- package/assets/core/home/CameraAngel.ts +326 -0
- package/assets/core/home/CameraAngel.ts.meta +9 -0
- package/assets/core/home/DouYinShow.ts +27 -0
- package/assets/core/home/DouYinShow.ts.meta +9 -0
- package/assets/core/home/EventManager.ts +39 -0
- package/assets/core/home/EventManager.ts.meta +9 -0
- package/assets/core/home/ExView.ts +9 -0
- package/assets/core/home/ExView.ts.meta +9 -0
- package/assets/core/home/FollowCamera.ts +205 -0
- package/assets/core/home/FollowCamera.ts.meta +9 -0
- package/assets/core/home/InViewCenter.ts +52 -0
- package/assets/core/home/InViewCenter.ts.meta +9 -0
- package/assets/core/home/JsonUtil.ts +102 -0
- package/assets/core/home/JsonUtil.ts.meta +9 -0
- package/assets/core/home/LoadingWindow.ts +44 -0
- package/assets/core/home/LoadingWindow.ts.meta +9 -0
- package/assets/core/home/ParabolaTween.ts +110 -0
- package/assets/core/home/ParabolaTween.ts.meta +9 -0
- package/assets/core/home/ProgessView.ts +96 -0
- package/assets/core/home/ProgessView.ts.meta +9 -0
- package/assets/core/home/Quaternion.ts +237 -0
- package/assets/core/home/Quaternion.ts.meta +9 -0
- package/assets/core/home/ResUtil.ts +132 -0
- package/assets/core/home/ResUtil.ts.meta +9 -0
- package/assets/core/home/ResourceManager.ts +430 -0
- package/assets/core/home/ResourceManager.ts.meta +9 -0
- package/assets/core/home/StateMachine.ts +93 -0
- package/assets/core/home/StateMachine.ts.meta +9 -0
- package/assets/core/home/StorageManager.ts +161 -0
- package/assets/core/home/StorageManager.ts.meta +9 -0
- package/assets/core/home/ThirdFreeLookCamera.ts +201 -0
- package/assets/core/home/ThirdFreeLookCamera.ts.meta +9 -0
- package/assets/core/home/TimeManager.ts +486 -0
- package/assets/core/home/TimeManager.ts.meta +9 -0
- package/assets/core/home/Tools.ts +103 -0
- package/assets/core/home/Tools.ts.meta +9 -0
- package/assets/core/home/prefabs.meta +12 -0
- package/assets/core/home/util/EncryptUtil.ts +60 -0
- package/assets/core/home/util/EncryptUtil.ts.meta +11 -0
- package/assets/core/home/util/MathUtil.ts +22 -0
- package/assets/core/home/util/MathUtil.ts.meta +9 -0
- package/assets/core/home/util/Md5.ts +202 -0
- package/assets/core/home/util/Md5.ts.meta +11 -0
- package/assets/core/home/util/RandomUtil.ts +61 -0
- package/assets/core/home/util/RandomUtil.ts.meta +9 -0
- package/assets/core/home/util/ResUtil.ts +129 -0
- package/assets/core/home/util/ResUtil.ts.meta +9 -0
- package/assets/core/home/util/crypto-js.d.ts +30 -0
- package/assets/core/home/util/crypto-js.d.ts.meta +11 -0
- package/assets/core/home/util/crypto-js.js +6030 -0
- package/assets/core/home/util/crypto-js.js.meta +9 -0
- package/assets/core/home/util.meta +12 -0
- package/assets/core/home.meta +12 -0
- package/assets/core/interface/ISceneParam.ts +11 -0
- package/assets/core/interface/ISceneParam.ts.meta +9 -0
- package/assets/core/interface/Interface.ts +160 -0
- package/assets/core/interface/Interface.ts.meta +1 -0
- package/assets/core/interface/MainModule.ts +1019 -0
- package/assets/core/interface/MainModule.ts.meta +9 -0
- package/assets/core/interface.meta +9 -0
- package/assets/core/lib/Logger.ts +286 -0
- package/assets/core/lib/Logger.ts.meta +9 -0
- package/assets/core/lib/language/.language.md +1 -0
- package/assets/core/lib/language/Language.ts +133 -0
- package/assets/core/lib/language/Language.ts.meta +13 -0
- package/assets/core/lib/language/LanguageData.ts +114 -0
- package/assets/core/lib/language/LanguageData.ts.meta +9 -0
- package/assets/core/lib/language/LanguageLabel.ts +172 -0
- package/assets/core/lib/language/LanguageLabel.ts.meta +13 -0
- package/assets/core/lib/language/LanguagePack.ts +126 -0
- package/assets/core/lib/language/LanguagePack.ts.meta +13 -0
- package/assets/core/lib/language/LanguagePointLabel.ts.meta +16 -0
- package/assets/core/lib/language/LanguageSpine.ts +60 -0
- package/assets/core/lib/language/LanguageSpine.ts.meta +9 -0
- package/assets/core/lib/language/LanguageSprite.ts +138 -0
- package/assets/core/lib/language/LanguageSprite.ts.meta +13 -0
- package/assets/core/lib/language.meta +9 -0
- package/assets/core/lib/logger/ELoggerLevel.ts +16 -0
- package/assets/core/lib/logger/ELoggerLevel.ts.meta +9 -0
- package/assets/core/lib/logger/MLogger.ts +118 -0
- package/assets/core/lib/logger/MLogger.ts.meta +9 -0
- package/assets/core/lib/logger.meta +9 -0
- package/assets/core/lib/net/libs/proto/output/protobuf.d.ts +2729 -0
- package/assets/core/lib/net/libs/proto/output/protobuf.d.ts.meta +9 -0
- package/assets/core/lib/net/libs/proto/output/protobuf.min.js +8 -0
- package/assets/core/lib/net/libs/proto/output/protobuf.min.js.meta +9 -0
- package/assets/core/lib/net/libs/proto/output/protobuf_custom.d.ts +102 -0
- package/assets/core/lib/net/libs/proto/output/protobuf_custom.d.ts.meta +9 -0
- package/assets/core/lib/net/libs/proto/output/protobuf_custom.js +222 -0
- package/assets/core/lib/net/libs/proto/output/protobuf_custom.js.meta +9 -0
- package/assets/core/lib/net/libs/proto/output.meta +9 -0
- package/assets/core/lib/net/libs/proto/source/Cmd.proto +6 -0
- package/assets/core/lib/net/libs/proto/source/Cmd.proto.meta +11 -0
- package/assets/core/lib/net/libs/proto/source/UserLogin.proto +12 -0
- package/assets/core/lib/net/libs/proto/source/UserLogin.proto.meta +11 -0
- package/assets/core/lib/net/libs/proto/source/base.proto +24 -0
- package/assets/core/lib/net/libs/proto/source/base.proto.meta +11 -0
- package/assets/core/lib/net/libs/proto/source/command.proto +31 -0
- package/assets/core/lib/net/libs/proto/source/command.proto.meta +11 -0
- package/assets/core/lib/net/libs/proto/source/domain/boos_battle_info.proto +13 -0
- package/assets/core/lib/net/libs/proto/source/domain/boos_battle_info.proto.meta +11 -0
- package/assets/core/lib/net/libs/proto/source/domain/player_auth.proto +26 -0
- package/assets/core/lib/net/libs/proto/source/domain/player_auth.proto.meta +11 -0
- package/assets/core/lib/net/libs/proto/source/domain.meta +9 -0
- package/assets/core/lib/net/libs/proto/source/message/game_push.proto +23 -0
- package/assets/core/lib/net/libs/proto/source/message/game_push.proto.meta +11 -0
- package/assets/core/lib/net/libs/proto/source/message/game_request.proto +24 -0
- package/assets/core/lib/net/libs/proto/source/message/game_request.proto.meta +11 -0
- package/assets/core/lib/net/libs/proto/source/message/game_response.proto +24 -0
- package/assets/core/lib/net/libs/proto/source/message/game_response.proto.meta +11 -0
- package/assets/core/lib/net/libs/proto/source/message.meta +9 -0
- package/assets/core/lib/net/libs/proto/source/push/boss_battle_events.proto +43 -0
- package/assets/core/lib/net/libs/proto/source/push/boss_battle_events.proto.meta +11 -0
- package/assets/core/lib/net/libs/proto/source/push.meta +9 -0
- package/assets/core/lib/net/libs/proto/source.meta +12 -0
- package/assets/core/lib/net/libs/proto.meta +9 -0
- package/assets/core/lib/net/libs.meta +9 -0
- package/assets/core/lib/net/net/HttpManager.ts +307 -0
- package/assets/core/lib/net/net/HttpManager.ts.meta +9 -0
- package/assets/core/lib/net/net/NetInterface.ts +114 -0
- package/assets/core/lib/net/net/NetInterface.ts.meta +9 -0
- package/assets/core/lib/net/net/NetManager.ts +77 -0
- package/assets/core/lib/net/net/NetManager.ts.meta +9 -0
- package/assets/core/lib/net/net/NetNode.ts +471 -0
- package/assets/core/lib/net/net/NetNode.ts.meta +9 -0
- package/assets/core/lib/net/net/WebSock.ts +81 -0
- package/assets/core/lib/net/net/WebSock.ts.meta +9 -0
- package/assets/core/lib/net/net/custom/NetChannelManager.ts +41 -0
- package/assets/core/lib/net/net/custom/NetChannelManager.ts.meta +9 -0
- package/assets/core/lib/net/net/custom/NetConfig.ts +11 -0
- package/assets/core/lib/net/net/custom/NetConfig.ts.meta +9 -0
- package/assets/core/lib/net/net/custom/NetErrorCode.ts +4 -0
- package/assets/core/lib/net/net/custom/NetErrorCode.ts.meta +9 -0
- package/assets/core/lib/net/net/custom/NetGameTips.ts +53 -0
- package/assets/core/lib/net/net/custom/NetGameTips.ts.meta +9 -0
- package/assets/core/lib/net/net/custom/NetNodeGame.ts +105 -0
- package/assets/core/lib/net/net/custom/NetNodeGame.ts.meta +9 -0
- package/assets/core/lib/net/net/custom.meta +9 -0
- package/assets/core/lib/net/net/protocol/NetProtocolJson.ts +39 -0
- package/assets/core/lib/net/net/protocol/NetProtocolJson.ts.meta +9 -0
- package/assets/core/lib/net/net/protocol/NetProtocolProtobuf.ts +85 -0
- package/assets/core/lib/net/net/protocol/NetProtocolProtobuf.ts.meta +9 -0
- package/assets/core/lib/net/net/protocol.meta +9 -0
- package/assets/core/lib/net/net.meta +9 -0
- package/assets/core/lib/net/prompt.meta +9 -0
- package/assets/core/lib/net.meta +9 -0
- package/assets/core/lib/old/VM2.ts +619 -0
- package/assets/core/lib/old/VM2.ts.meta +9 -0
- package/assets/core/lib/old/ViewModel.ts +905 -0
- package/assets/core/lib/old/ViewModel.ts.meta +9 -0
- package/assets/core/lib/old/ViewSearch.ts +125 -0
- package/assets/core/lib/old/ViewSearch.ts.meta +9 -0
- package/assets/core/lib/old.meta +9 -0
- package/assets/core/lib/tabbar/TabBarComponent.ts +113 -0
- package/assets/core/lib/tabbar/TabBarComponent.ts.meta +9 -0
- package/assets/core/lib/tabbar/TabBarController.ts +86 -0
- package/assets/core/lib/tabbar/TabBarController.ts.meta +9 -0
- package/assets/core/lib/tabbar/TabBarItem.ts +52 -0
- package/assets/core/lib/tabbar/TabBarItem.ts.meta +9 -0
- package/assets/core/lib/tabbar.meta +9 -0
- package/assets/core/lib.meta +12 -0
- package/assets/core.meta +9 -0
- package/assets.meta +9 -0
- package/index.ts +3 -0
- package/index.ts.meta +9 -0
- package/package.json +19 -0
- package/package.json.meta +11 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { _decorator, Camera, Component, find, Node, Vec3, view } from 'cc';
|
|
2
|
+
const { ccclass, property } = _decorator;
|
|
3
|
+
|
|
4
|
+
export class InViewCenter {
|
|
5
|
+
private _lastWPos: Vec3 = new Vec3();
|
|
6
|
+
private _pos: Vec3 = new Vec3();
|
|
7
|
+
screenSize: any;
|
|
8
|
+
height = 0
|
|
9
|
+
width = 0
|
|
10
|
+
camera: Camera;
|
|
11
|
+
canvasView: Node;
|
|
12
|
+
|
|
13
|
+
constructor() {
|
|
14
|
+
this.InitView()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
InitView() {
|
|
18
|
+
this.canvasView = find("Home");
|
|
19
|
+
this.camera = find('Camera').getComponent(Camera)
|
|
20
|
+
this.screenSize = view.getVisibleSize();
|
|
21
|
+
|
|
22
|
+
this.height = 667//this.screenSize.height / 2;
|
|
23
|
+
this.width = this.screenSize.width / 2 + 130;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
IsInView3D(wpos: Vec3) {
|
|
27
|
+
// @ts-ignore
|
|
28
|
+
if (!this.camera!._camera) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
this._lastWPos.set(wpos);
|
|
32
|
+
const camera = this.camera!;
|
|
33
|
+
// [HACK]
|
|
34
|
+
// @ts-ignore
|
|
35
|
+
camera._camera.update();
|
|
36
|
+
camera.convertToUINode(wpos, this.canvasView, this._pos);
|
|
37
|
+
// this.label.setPosition(this._pos);
|
|
38
|
+
const temp_pos = this._pos
|
|
39
|
+
|
|
40
|
+
const isInView = this.isPointInsideCanvas(temp_pos)//this.IsInView(this._pos)
|
|
41
|
+
|
|
42
|
+
return isInView;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
isPointInsideCanvas(point: Vec3): boolean {
|
|
46
|
+
const canvasSize = this.screenSize;
|
|
47
|
+
//console.log(this.width)
|
|
48
|
+
return (point.x >= -this.width && point.x <= this.width &&
|
|
49
|
+
point.y >= -this.height && point.y <= this.height);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { assetManager } from "cc";
|
|
2
|
+
import { JsonAsset, resources, AssetManager, director } from "cc";
|
|
3
|
+
|
|
4
|
+
export class JsonUtil {
|
|
5
|
+
|
|
6
|
+
data: Map<string, any> = new Map();
|
|
7
|
+
dataMap: Map<string, any> = new Map();
|
|
8
|
+
|
|
9
|
+
static _instance: JsonUtil;
|
|
10
|
+
static get instance(): JsonUtil {
|
|
11
|
+
if (!this._instance) {
|
|
12
|
+
this._instance = new JsonUtil();
|
|
13
|
+
}
|
|
14
|
+
return this._instance;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static get(tabName: string) {
|
|
18
|
+
return JsonUtil.instance.data.get(tabName);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// static getMap<T>() {
|
|
22
|
+
// const map = new Map<number, T>();
|
|
23
|
+
// const data = JsonUtil.get(T.TableName)
|
|
24
|
+
// for (const key in data) {
|
|
25
|
+
// if (data.hasOwnProperty(key)) {
|
|
26
|
+
// let id = parseInt(key);
|
|
27
|
+
// map.set(id, new T(id))
|
|
28
|
+
// }
|
|
29
|
+
// }
|
|
30
|
+
// return map;
|
|
31
|
+
// }
|
|
32
|
+
|
|
33
|
+
static getMap<T>(table_name: string, is_copy: boolean = false): Map<number, T> {
|
|
34
|
+
// 使用构造函数名称作为键值
|
|
35
|
+
const constructorName = table_name;
|
|
36
|
+
if (is_copy) {
|
|
37
|
+
return JSON.parse(JSON.stringify(JsonUtil.getMap(table_name, false)))
|
|
38
|
+
}
|
|
39
|
+
else if (JsonUtil.instance.dataMap.has(constructorName)) {
|
|
40
|
+
return JsonUtil.instance.dataMap.get(constructorName);
|
|
41
|
+
} else {
|
|
42
|
+
console.error('没有这个表', table_name)
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async loadJsonAll(bundleName, path: string) {
|
|
47
|
+
if (!this.data.has(bundleName)) {
|
|
48
|
+
await this.loadAllJsonAssets(bundleName, path)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async loadLanguage(bundleName, path: string) {
|
|
53
|
+
await this.loadAllJsonAssets(bundleName, path)
|
|
54
|
+
const bundle: AssetManager.Bundle | null = assetManager.getBundle(bundleName);
|
|
55
|
+
console.error('json===', this.data)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 从指定的bundle中加载文件夹中的所有JsonAsset资源 (3.x语法)
|
|
61
|
+
* @param bundleName bundle名称
|
|
62
|
+
* @param path 文件夹路径(相对于bundle目录)
|
|
63
|
+
* @returns 返回Promise<JsonAsset[]>,包含文件夹中所有JSON资源
|
|
64
|
+
*/
|
|
65
|
+
private loadAllJsonAssets(bundleName: string, path: string): Promise<Map<string, any>> {
|
|
66
|
+
return new Promise((resolve, reject) => {
|
|
67
|
+
const bundle: AssetManager.Bundle | null = assetManager.getBundle(bundleName);
|
|
68
|
+
if (bundle) {
|
|
69
|
+
bundle.loadDir(path, JsonAsset, (err: Error | null, assets: JsonAsset[]) => {
|
|
70
|
+
if (err) {
|
|
71
|
+
reject(err);
|
|
72
|
+
} else {
|
|
73
|
+
assets.forEach(asset => {
|
|
74
|
+
this.data.set(asset.name, asset.json);
|
|
75
|
+
const constructorName = `${asset.name}`
|
|
76
|
+
const map = new Map<number, any>();
|
|
77
|
+
const data = JsonUtil.get(constructorName);
|
|
78
|
+
if (data) {
|
|
79
|
+
for (const key in data) {
|
|
80
|
+
if (data.hasOwnProperty(key)) {
|
|
81
|
+
let id = parseInt(key);
|
|
82
|
+
data[key].id = id;
|
|
83
|
+
map.set(id, data[key]);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
JsonUtil.instance.dataMap.set(constructorName, map);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
resolve(this.data);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
} else {
|
|
96
|
+
reject(new Error(`报错了 '${bundleName}' not found`));
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { _decorator, Component, find, Label, Node, Tween, tween, v3 } from 'cc';
|
|
2
|
+
const { ccclass, property } = _decorator;
|
|
3
|
+
|
|
4
|
+
@ccclass('LoadingWindow')
|
|
5
|
+
export class LoadingWindow extends Component {
|
|
6
|
+
|
|
7
|
+
message: Label;
|
|
8
|
+
loadingSpin: Node
|
|
9
|
+
loadingSpin2: Node
|
|
10
|
+
|
|
11
|
+
protected onLoad(): void {
|
|
12
|
+
this.InitView()
|
|
13
|
+
}
|
|
14
|
+
InitView() {
|
|
15
|
+
this.message = find("root/Label", this.node).getComponent(Label);
|
|
16
|
+
this.loadingSpin = find("root/loadingSpin", this.node)
|
|
17
|
+
this.loadingSpin2 = find("root/Loading Wheel", this.node)
|
|
18
|
+
this.Show("")
|
|
19
|
+
this.node.active = false
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
Show(message: string) {
|
|
23
|
+
this.node.active = true;
|
|
24
|
+
this.StartAnim()
|
|
25
|
+
this.message.string = message === "" ? "加载中 请稍等..." : message;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
Hide() {
|
|
29
|
+
Tween.stopAllByTarget(this.node)
|
|
30
|
+
this.node.active = false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
StartAnim() {
|
|
35
|
+
Tween.stopAllByTarget(this.node)
|
|
36
|
+
tween(this.loadingSpin)
|
|
37
|
+
.repeatForever(
|
|
38
|
+
tween().by(1, { eulerAngles: v3(0, 0, -360) }) // 每次旋转360度
|
|
39
|
+
)
|
|
40
|
+
.start();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
}
|
|
44
|
+
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { instantiate } from 'cc';
|
|
2
|
+
import { randomRangeInt } from 'cc';
|
|
3
|
+
import { _decorator, Component, misc, Node, tween, v3, Vec3 } from 'cc';
|
|
4
|
+
const { ccclass, property } = _decorator;
|
|
5
|
+
|
|
6
|
+
@ccclass('ParabolaTween')
|
|
7
|
+
export class ParabolaTween {
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 开始抛物线缓动
|
|
11
|
+
* @param item 运动节点
|
|
12
|
+
* @param target_postion 目标位置
|
|
13
|
+
* @param update 更新 运动中回调
|
|
14
|
+
* @param offset_ratio 最高点 的偏移量
|
|
15
|
+
* @param time 动画时间
|
|
16
|
+
* @param is_random 是否随机上下方向
|
|
17
|
+
* @param start_position 起始位置--比如 父节点的位置和 抛物线的起点位置 不同,,用父节点的起始位置就传入
|
|
18
|
+
*/
|
|
19
|
+
RunParabolaTween(item: Node, target_postion: Vec3, update: (ratio: number) => void, param?: { offset_ratio?: number, is_random: boolean, time?: number, start_position?: Vec3,is_end_clone?:boolean }) {
|
|
20
|
+
const distance = Vec3.distance(target_postion, item.worldPosition)
|
|
21
|
+
|
|
22
|
+
const start = item.worldPosition.clone();
|
|
23
|
+
const end = target_postion
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
let fx = end.x >= (param?.start_position ? param?.start_position.x : start.x) ? 1 : -1;//朝向始终 是上抛物线,
|
|
27
|
+
if (param?.is_random) { fx = [-1, 1][randomRangeInt(0, 2)] }
|
|
28
|
+
|
|
29
|
+
const direction = end.clone().subtract(start).normalize();
|
|
30
|
+
let offset = direction.clone().multiplyScalar(distance * 0.5);
|
|
31
|
+
offset = start.add(offset)
|
|
32
|
+
//垂直方向的位置
|
|
33
|
+
const perpendicular = new Vec3(-direction.y, direction.x, 0);
|
|
34
|
+
offset = offset.add(perpendicular.multiplyScalar(distance * (param?.offset_ratio ?? 0.5) * fx))
|
|
35
|
+
offset = v3(offset.x, offset.y);
|
|
36
|
+
|
|
37
|
+
this.RunTween(item, offset, target_postion, param?.time ?? 1, update)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
RunTween(target: Node, peakPoint, endPoint, duration, update) {
|
|
41
|
+
let points = [target.worldPosition.clone(), peakPoint, endPoint];
|
|
42
|
+
const data = { ratio: 0 }
|
|
43
|
+
tween(data).to(duration, { ratio: 1 }, // 这里以node的位置信息坐标缓动的目标
|
|
44
|
+
{
|
|
45
|
+
// ITweenOption 的接口实现:
|
|
46
|
+
onUpdate: (target_data: { ratio: 0 }, ratio: number) => {
|
|
47
|
+
const pos = this.GetPosition(target_data.ratio, points)
|
|
48
|
+
const pos1 = this.GetPosition(Math.max(ratio * 1.1, 0.001), points)
|
|
49
|
+
target.setWorldPosition(pos.x, pos.y, pos.z);
|
|
50
|
+
this.LookAt(target, pos1)
|
|
51
|
+
update && update(ratio, pos)
|
|
52
|
+
}
|
|
53
|
+
}).start();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
GetPosition(ratio, points) {
|
|
57
|
+
const t = ratio
|
|
58
|
+
// 二次贝塞尔曲线公式
|
|
59
|
+
let x = (1 - t) * (1 - t) * points[0].x + 2 * (1 - t) * t * points[1].x + t * t * points[2].x;
|
|
60
|
+
let y = (1 - t) * (1 - t) * points[0].y + 2 * (1 - t) * t * points[1].y + t * t * points[2].y;
|
|
61
|
+
const pos = v3(x, y);
|
|
62
|
+
return pos
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
LookAt(target: Node, endPoint: Vec3) {
|
|
66
|
+
const direction = endPoint.clone().subtract(target.worldPosition).normalize(); // 计算A点指向B点的方向向量
|
|
67
|
+
const angle = Math.atan2(direction.x, direction.y); // 计算夹角(弧度)
|
|
68
|
+
let euler = v3(0, 0, -misc.radiansToDegrees(angle)); // 应用欧拉角到A点
|
|
69
|
+
target.eulerAngles = euler
|
|
70
|
+
return angle;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
getEuler(start: Vec3, end: Vec3) {
|
|
74
|
+
const direction = end.clone().subtract(start).normalize(); // 计算A点指向B点的方向向量
|
|
75
|
+
const angle = Math.atan2(direction.x, direction.y); // 计算夹角(弧度)
|
|
76
|
+
let euler = v3(0, 0, -misc.radiansToDegrees(angle)); // 应用欧拉角到A点
|
|
77
|
+
return -misc.radiansToDegrees(angle);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 生成抛物线上的指定数量坐标点
|
|
82
|
+
* @param start 起始点
|
|
83
|
+
* @param peak 控制点(峰值点)
|
|
84
|
+
* @param end 结束点
|
|
85
|
+
* @param count 点的数量
|
|
86
|
+
* @returns 坐标点数组
|
|
87
|
+
*/
|
|
88
|
+
generateParabolaPoints(param: { start: Vec3, end: Vec3, offset_ratio: number, count: number }) {
|
|
89
|
+
//中心点
|
|
90
|
+
const distance = Vec3.distance(param.start, param.end)
|
|
91
|
+
const direction = param.end.clone().subtract(param.start).normalize();
|
|
92
|
+
let center = direction.clone().multiplyScalar(distance * 0.5);
|
|
93
|
+
center = param.start.clone().add(center)
|
|
94
|
+
//中心点垂直方向的位置
|
|
95
|
+
const perpendicular = new Vec3(-direction.y, direction.x, 0);
|
|
96
|
+
center = center.add(perpendicular.multiplyScalar(distance * (param?.offset_ratio ?? 0.5)))
|
|
97
|
+
const points = [param.start, center, param.end];
|
|
98
|
+
const result: { positions: Vec3, rotion: number }[] = []
|
|
99
|
+
for (let i = 0; i < param.count; i++) {
|
|
100
|
+
const ratio = i / (param.count - 1);
|
|
101
|
+
const pos = this.GetPosition(ratio, points);
|
|
102
|
+
const pos1 = this.GetPosition(Math.max(ratio * 1.1, 0.001), points)
|
|
103
|
+
const euler = this.getEuler(pos, pos1)
|
|
104
|
+
result.push({ positions: pos, rotion: euler });
|
|
105
|
+
}
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
|
|
2
|
+
import { tween } from 'cc';
|
|
3
|
+
import { ProgressBar } from 'cc';
|
|
4
|
+
import { _decorator, Component, Node, game, find, director } from 'cc';
|
|
5
|
+
const { ccclass, property, menu } = _decorator;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Predefined variables
|
|
9
|
+
* Name = ProgessView
|
|
10
|
+
* DateTime = Wed Sep 28 2022 22:24:36 GMT+0800 (中国标准时间)
|
|
11
|
+
* Author = yf123mb
|
|
12
|
+
* FileBasename = ProgessView.ts
|
|
13
|
+
* FileBasenameNoExtension = ProgessView
|
|
14
|
+
* URL = db://assets/home/Home/ProgessView.ts
|
|
15
|
+
* ManualUrl = https://docs.cocos.com/creator/3.4/manual/zh/
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
@ccclass('ProgessView')
|
|
20
|
+
@menu('组件进度条/ProgessView')
|
|
21
|
+
export class ProgessView extends Component {
|
|
22
|
+
|
|
23
|
+
// static Ins:ProgessView;
|
|
24
|
+
@property({
|
|
25
|
+
type: ProgressBar,
|
|
26
|
+
displayName: "进度条"
|
|
27
|
+
})
|
|
28
|
+
pro_bar!: ProgressBar;
|
|
29
|
+
|
|
30
|
+
protected onLoad(): void {
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
SHowPro(isShow: boolean) {
|
|
35
|
+
this.pro_bar.node.active = isShow
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
stop = false
|
|
39
|
+
async SetProgessAuto(isOk) {
|
|
40
|
+
this.stop = isOk
|
|
41
|
+
if (isOk) {
|
|
42
|
+
for (var i = 90; i < 101; i++) {
|
|
43
|
+
await MainModule.timeManager.AwaitMS(1);
|
|
44
|
+
this.SetProgessValue((i));
|
|
45
|
+
}
|
|
46
|
+
this.Hide()
|
|
47
|
+
} else {
|
|
48
|
+
for (var i = 0; i < 90; i++) {
|
|
49
|
+
if (this.stop) { return }
|
|
50
|
+
await MainModule.timeManager.AwaitMS(1);
|
|
51
|
+
this.SetProgessValue((i));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async SetProgessValue(value: number) {
|
|
57
|
+
if (this.pro_bar) {
|
|
58
|
+
this.pro_bar.SetValue(value);
|
|
59
|
+
// console.log(value);
|
|
60
|
+
if (value >= 100) {
|
|
61
|
+
// this.Hide();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
Show() {
|
|
68
|
+
this.node.active = true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
Hide() {
|
|
72
|
+
this.node.active = false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
pro(this: ProgressBar, progress: number, max: number, anim_time?: number): void {
|
|
77
|
+
|
|
78
|
+
const com_max_pro = this.totalLength//getComponent(UITransform).width
|
|
79
|
+
const max_progress = com_max_pro;
|
|
80
|
+
const s = max_progress / max;
|
|
81
|
+
const pro = progress * s / max_progress;
|
|
82
|
+
|
|
83
|
+
if (anim_time) {
|
|
84
|
+
tween(this).to(anim_time, {
|
|
85
|
+
progress: pro
|
|
86
|
+
}).start();
|
|
87
|
+
|
|
88
|
+
} else {
|
|
89
|
+
this.progress = pro;
|
|
90
|
+
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
}
|
|
96
|
+
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { EPSILON, Mat3, math, quat, Quat } from "cc";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 该类属于一个引擎内部的Quat四元数类的一个扩展简化版
|
|
5
|
+
* 因为本人觉得有些out参数过于多余,在这里就隐藏掉了
|
|
6
|
+
* 同时也加了些其他的四元数旋转的功能
|
|
7
|
+
*/
|
|
8
|
+
export class Quaternion {
|
|
9
|
+
|
|
10
|
+
private static Deg2Rad: number = (Math.PI) / 180;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 绕Y轴旋转置顶节点
|
|
14
|
+
* @param _node 需要旋转的节点
|
|
15
|
+
* @param _angle 旋转的角度(是角度不是弧度)
|
|
16
|
+
*/
|
|
17
|
+
public static RotateY(_node: Node, _angle: number): Quat {
|
|
18
|
+
let _quat = new Quat();
|
|
19
|
+
_node.rotation = Quat.rotateY(_quat, _node.rotation, _angle * this.Deg2Rad);
|
|
20
|
+
return _quat;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 绕X轴旋转置顶节点
|
|
25
|
+
* @param _node 需要旋转的节点
|
|
26
|
+
* @param _angle 旋转的角度(是角度不是弧度)
|
|
27
|
+
*/
|
|
28
|
+
public static RotateX(_node: Node, _angle: number): Quat {
|
|
29
|
+
let _quat = new Quat();
|
|
30
|
+
_node.rotation = Quat.rotateX(_quat, _node.rotation, _angle * this.Deg2Rad);
|
|
31
|
+
return _quat;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 绕Z轴旋转置顶节点
|
|
36
|
+
* @param _node 需要旋转的节点
|
|
37
|
+
* @param _angle 旋转的角度(是角度不是弧度)
|
|
38
|
+
*/
|
|
39
|
+
public static RotateZ(_node: Node, _angle: number): Quat {
|
|
40
|
+
let _quat = new Quat();
|
|
41
|
+
_node.rotation = Quat.rotateZ(_quat, _node.rotation, _angle * this.Deg2Rad);
|
|
42
|
+
return _quat;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 绕世界空间下指定轴旋转四元数
|
|
47
|
+
* @param _targetQuat 指定要旋转四元数
|
|
48
|
+
* @param axis 旋转轴
|
|
49
|
+
* @param _angle 旋转角度
|
|
50
|
+
*/
|
|
51
|
+
public static RotateAround(_targetQuat: Quat, axis: Vec3, _angle: number): Quat {
|
|
52
|
+
let _quat = new Quat();
|
|
53
|
+
Quat.rotateAround(_quat, _targetQuat, axis, _angle * this.Deg2Rad);
|
|
54
|
+
return _quat;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 绕本地空间下指定轴旋转四元数
|
|
59
|
+
* @param _targetQuat 指定要旋转四元数
|
|
60
|
+
* @param axis 旋转轴
|
|
61
|
+
* @param _angle 旋转角度
|
|
62
|
+
*/
|
|
63
|
+
public static RotateAroundLocal(_targetQuat: Quat, axis: Vec3, _angle: number): Quat {
|
|
64
|
+
let _quat = new Quat();
|
|
65
|
+
Quat.rotateAroundLocal(_quat, _targetQuat, axis, _angle * this.Deg2Rad);
|
|
66
|
+
return _quat;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 将变换围绕穿过世界坐标中的 point 的 axis 旋转 angle 度。
|
|
71
|
+
* 这会修改变换的位置和旋转。
|
|
72
|
+
* @param self 要变换旋转的目标
|
|
73
|
+
* @param pos 指定围绕的point
|
|
74
|
+
* @param axis 旋转轴
|
|
75
|
+
* @param angle 旋转角度
|
|
76
|
+
*/
|
|
77
|
+
public static RotationAroundNode(self: Node, pos: Vec3, axis: Vec3, angle: number): Quat {
|
|
78
|
+
let _quat = new Quat();
|
|
79
|
+
let v1 = new Vec3();
|
|
80
|
+
let v2 = new Vec3();
|
|
81
|
+
let pos2: Vec3 = self.position;
|
|
82
|
+
let rad = angle * this.Deg2Rad;
|
|
83
|
+
Quat.fromAxisAngle(_quat, axis, rad);
|
|
84
|
+
Vec3.subtract(v1, pos2, pos);
|
|
85
|
+
Vec3.transformQuat(v2, v1, _quat);
|
|
86
|
+
self.position = Vec3.add(v2, pos, v2);
|
|
87
|
+
Quat.rotateAround(_quat, self.rotation, axis, rad);
|
|
88
|
+
return _quat;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* 从四元数得到欧拉角
|
|
93
|
+
* @param _quat 四元数
|
|
94
|
+
*/
|
|
95
|
+
public static GetEulerFromQuat(_quat: Quat): IVec3Like {
|
|
96
|
+
let angle: IVec3Like = Quat.toEuler(new Vec3(), _quat, true);
|
|
97
|
+
return angle;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* 从欧拉角得到四元数
|
|
102
|
+
* @param _angle 欧拉角
|
|
103
|
+
*/
|
|
104
|
+
public static GetQuatFromAngle(_angle: IVec3Like): Quat {
|
|
105
|
+
let _quat: Quat = Quat.fromEuler(new Quat(), _angle.x, _angle.y, _angle.z);
|
|
106
|
+
return _quat;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* 四元数差值,在 a 和 b 之间插入 t,然后对结果进行标准化处理。参数 t 被限制在 [0, 1] 范围内。
|
|
111
|
+
* 该方法比 Slerp 快,但如果旋转相距很远,其视觉效果也更糟糕。
|
|
112
|
+
* @param _a
|
|
113
|
+
* @param _b
|
|
114
|
+
* @param _t
|
|
115
|
+
*/
|
|
116
|
+
public static Lerp(_a: Quat, _b: Quat, _t: number): Quat {
|
|
117
|
+
let _quat = new Quat();
|
|
118
|
+
Quat.lerp(_quat, _a, _b, _t);
|
|
119
|
+
return _quat;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* 四元数球形差值
|
|
124
|
+
* 在 a 和 b 之间以球形方式插入 t。参数 t 被限制在 [0, 1] 范围内。
|
|
125
|
+
* @param _a
|
|
126
|
+
* @param _b
|
|
127
|
+
* @param _t
|
|
128
|
+
*/
|
|
129
|
+
public static Slerp(_a: Quat, _b: Quat, _t: number): Quat {
|
|
130
|
+
let _quat = new Quat();
|
|
131
|
+
Quat.slerp(_quat, _a, _b, _t);
|
|
132
|
+
return _quat;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
public static LookRotation(_forward: Vec3, _upwards: Vec3 = Vec3.UP): Quat {
|
|
137
|
+
let _quat = new Quat();
|
|
138
|
+
Vec3.normalize(_forward, _forward);
|
|
139
|
+
Quat.fromViewUp(_quat, _forward, _upwards);
|
|
140
|
+
return _quat;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
import { _decorator, Node, Vec3, IVec3Like } from 'cc';
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
export class VectorTool {
|
|
150
|
+
|
|
151
|
+
public static SmoothDampV3(current: IVec3Like, target: Vec3, currentVelocity: IVec3Like, smoothTime: number, maxSpeed: number, deltaTime: number) {
|
|
152
|
+
let outputX: number = 0;
|
|
153
|
+
let outputY: number = 0;
|
|
154
|
+
let outputZ: number = 0;
|
|
155
|
+
smoothTime = Math.max(0.0001, smoothTime);
|
|
156
|
+
let omega: number = 2 / smoothTime;
|
|
157
|
+
let x: number = omega * deltaTime;
|
|
158
|
+
let exp: number = 1 / (1 + x + 0.48 * x * x + 0.235 * x * x * x);
|
|
159
|
+
let changX: number = current.x - target.x;
|
|
160
|
+
let changY: number = current.y - target.y;
|
|
161
|
+
let changZ: number = current.z - target.z;
|
|
162
|
+
let originalTo: Vec3 = target;
|
|
163
|
+
|
|
164
|
+
let maxChange: number = maxSpeed * smoothTime;
|
|
165
|
+
|
|
166
|
+
let maxChangeSq: number = maxChange * maxChange;
|
|
167
|
+
let sqrmag: number = changX * changX + changY * changY + changZ * changZ;
|
|
168
|
+
if (sqrmag > maxChangeSq) {
|
|
169
|
+
let mag: number = Math.sqrt(sqrmag);
|
|
170
|
+
changX = changX / mag * maxChangeSq;
|
|
171
|
+
changY = changY / mag * maxChangeSq;
|
|
172
|
+
changZ = changZ / mag * maxChangeSq;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
target.x = current.x - changX;
|
|
176
|
+
target.y = current.y - changY;
|
|
177
|
+
target.z = current.z - changZ;
|
|
178
|
+
|
|
179
|
+
let tempX: number = (currentVelocity.x + omega * changX) * deltaTime;
|
|
180
|
+
let tempY: number = (currentVelocity.y + omega * changY) * deltaTime;
|
|
181
|
+
let tempZ: number = (currentVelocity.z + omega * changZ) * deltaTime;
|
|
182
|
+
|
|
183
|
+
currentVelocity.x = (currentVelocity.x - omega * tempX) * exp;
|
|
184
|
+
currentVelocity.y = (currentVelocity.y - omega * tempY) * exp;
|
|
185
|
+
currentVelocity.z = (currentVelocity.z - omega * tempZ) * exp;
|
|
186
|
+
|
|
187
|
+
outputX = target.x + (changX + tempX) * exp;
|
|
188
|
+
outputY = target.y + (changY + tempY) * exp;
|
|
189
|
+
outputZ = target.z + (changZ + tempZ) * exp;
|
|
190
|
+
|
|
191
|
+
let origMinusCurrentX: number = originalTo.x - current.x;
|
|
192
|
+
let origMinusCurrentY: number = originalTo.y - current.y;
|
|
193
|
+
let origMinusCurrentZ: number = originalTo.z - current.z;
|
|
194
|
+
let outMinusOrigX: number = outputX - originalTo.x;
|
|
195
|
+
let outMinusOrigY: number = outputY - originalTo.y;
|
|
196
|
+
let outMinusOrigZ: number = outputZ - originalTo.z;
|
|
197
|
+
|
|
198
|
+
if (origMinusCurrentX * outMinusOrigX + origMinusCurrentY * outMinusOrigY + origMinusCurrentZ * outMinusOrigZ > 0) {
|
|
199
|
+
outputX = originalTo.x;
|
|
200
|
+
outputY = originalTo.y;
|
|
201
|
+
outputZ = originalTo.z;
|
|
202
|
+
|
|
203
|
+
currentVelocity.x = (outputX - originalTo.x) / deltaTime;
|
|
204
|
+
currentVelocity.y = (outputY - originalTo.y) / deltaTime;
|
|
205
|
+
currentVelocity.z = (outputZ - originalTo.z) / deltaTime;
|
|
206
|
+
}
|
|
207
|
+
return new Vec3(outputX, outputY, outputZ);
|
|
208
|
+
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
public static SmoothDamp(current: number, target: number, currentVelocity: number, smoothTime: number, maxSpeed: number, deltaTime: number) {
|
|
212
|
+
smoothTime = Math.max(0.0001, smoothTime);
|
|
213
|
+
let num: number = 2 / smoothTime;
|
|
214
|
+
let num2: number = num * deltaTime;
|
|
215
|
+
let num3: number = 1 / (1 + num2 + 0.48 * num2 * num2 + 0.235 * num2 * num2 * num2);
|
|
216
|
+
let num4: number = current - target;
|
|
217
|
+
let num5: number = target;
|
|
218
|
+
let num6: number = maxSpeed * smoothTime;
|
|
219
|
+
num4 = VectorTool.Clamp(num4, -num6, num6);
|
|
220
|
+
target = current - num4;
|
|
221
|
+
let num7: number = (currentVelocity + num * num4) * deltaTime;
|
|
222
|
+
currentVelocity = (currentVelocity - num * num7) * num3;
|
|
223
|
+
let num8: number = target + (num4 + num7) * num3;
|
|
224
|
+
if (num5 - current > 0 == num8 > num5) {
|
|
225
|
+
num8 = num5;
|
|
226
|
+
currentVelocity = (num8 - num5) / deltaTime;
|
|
227
|
+
}
|
|
228
|
+
return num8;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
public static Clamp(val: number, min: number, max: number) {
|
|
232
|
+
if (val <= min) val = min;
|
|
233
|
+
if (val >= max) val = max;
|
|
234
|
+
|
|
235
|
+
return val;
|
|
236
|
+
}
|
|
237
|
+
}
|