@cjhd/cj-ecs 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/.cj-ecs.md +12 -0
- package/assets/common/component/MoveComponent.ts +292 -0
- package/assets/common/component/MoveComponent.ts.meta +9 -0
- package/assets/common/component/NodeComponent.ts +315 -0
- package/assets/common/component/NodeComponent.ts.meta +9 -0
- package/assets/common/component.meta +12 -0
- package/assets/common/system/MoveSystem.ts +108 -0
- package/assets/common/system/MoveSystem.ts.meta +9 -0
- package/assets/common/system.meta +12 -0
- package/assets/common.meta +12 -0
- package/assets/ecs/EcsComponent.ts +244 -0
- package/assets/ecs/EcsComponent.ts.meta +9 -0
- package/assets/ecs/EcsDirty.ts +459 -0
- package/assets/ecs/EcsDirty.ts.meta +9 -0
- package/assets/ecs/EcsEntity.ts +430 -0
- package/assets/ecs/EcsEntity.ts.meta +9 -0
- package/assets/ecs/EcsSingleton.ts +6 -0
- package/assets/ecs/EcsSingleton.ts.meta +9 -0
- package/assets/ecs/EcsSystem.ts +191 -0
- package/assets/ecs/EcsSystem.ts.meta +9 -0
- package/assets/ecs.meta +12 -0
- package/assets/ecs.ts +339 -0
- package/assets/ecs.ts.meta +9 -0
- package/assets/lib/EcsCache.ts +43 -0
- package/assets/lib/EcsCache.ts.meta +9 -0
- package/assets/lib/EcsFilter.ts +210 -0
- package/assets/lib/EcsFilter.ts.meta +9 -0
- package/assets/lib/EcsManager.ts +502 -0
- package/assets/lib/EcsManager.ts.meta +9 -0
- package/assets/lib/EcsObject.ts +422 -0
- package/assets/lib/EcsObject.ts.meta +9 -0
- package/assets/lib/EcsTimer.ts +239 -0
- package/assets/lib/EcsTimer.ts.meta +9 -0
- package/assets/lib/EcsTween.ts +486 -0
- package/assets/lib/EcsTween.ts.meta +9 -0
- package/assets/lib/EcsUtils.ts +352 -0
- package/assets/lib/EcsUtils.ts.meta +9 -0
- package/assets/lib.meta +12 -0
- package/assets.meta +9 -0
- package/index.ts +33 -0
- package/index.ts.meta +9 -0
- package/package.json +20 -0
- package/package.json.meta +11 -0
package/.cj-ecs.md
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { math, Vec2 } from 'cc';
|
|
2
|
+
import { EcsComponent } from '../../ecs/EcsComponent';
|
|
3
|
+
import { ecsclass } from '../../lib/EcsManager';
|
|
4
|
+
import { IEntity } from '../../lib/EcsObject';
|
|
5
|
+
import { NodeComponent } from './NodeComponent';
|
|
6
|
+
|
|
7
|
+
interface IOptions {
|
|
8
|
+
/**
|
|
9
|
+
* 允许旋转
|
|
10
|
+
* - 当rotate为true时,angle属性才会同步到NodeComponent
|
|
11
|
+
* @description 默认值: false
|
|
12
|
+
*/
|
|
13
|
+
rotate: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* 最小速度
|
|
16
|
+
* @description 单位: 像素/秒
|
|
17
|
+
* @description 默认值: -Infinity
|
|
18
|
+
* @description 取值范围: (-oo, +oo)
|
|
19
|
+
*/
|
|
20
|
+
minSpeed: number;
|
|
21
|
+
/**
|
|
22
|
+
* 最大速度
|
|
23
|
+
* @description 单位: 像素/秒
|
|
24
|
+
* @description 默认值: Infinity
|
|
25
|
+
* @description 取值范围: (-oo, +oo)
|
|
26
|
+
*/
|
|
27
|
+
maxSpeed: number;
|
|
28
|
+
/**
|
|
29
|
+
* 加速度
|
|
30
|
+
* @description 单位: 像素/秒
|
|
31
|
+
* @description 默认值: 0
|
|
32
|
+
* @description 取值范围: (-oo, +oo)
|
|
33
|
+
*/
|
|
34
|
+
acceleratedVelocity: number;
|
|
35
|
+
/**
|
|
36
|
+
* 角速度(0表示无穷大)
|
|
37
|
+
* @description 单位: 度/秒
|
|
38
|
+
* @description 默认值: 0
|
|
39
|
+
* @description 取值范围: [0, +oo)
|
|
40
|
+
*/
|
|
41
|
+
angleVelocity: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface IMoveComponent {
|
|
45
|
+
/**
|
|
46
|
+
* 选项参数
|
|
47
|
+
*/
|
|
48
|
+
options: IOptions;
|
|
49
|
+
/**
|
|
50
|
+
* 最终的目标
|
|
51
|
+
* - taget与toward二选一, 且必须设置一个
|
|
52
|
+
* @description 默认值: null
|
|
53
|
+
*/
|
|
54
|
+
target: NodeComponent;
|
|
55
|
+
/**
|
|
56
|
+
* 最终的角度
|
|
57
|
+
* - taget与toward二选一, 且必须设置一个
|
|
58
|
+
* @description 单位: 度
|
|
59
|
+
* @description 默认值: 0
|
|
60
|
+
* @description 取值范围: (-180, 180]
|
|
61
|
+
*/
|
|
62
|
+
toward: number;
|
|
63
|
+
/**
|
|
64
|
+
* 当前速度
|
|
65
|
+
* @description 单位: 像素/秒
|
|
66
|
+
* @description 默认值: 0
|
|
67
|
+
* @description 取值范围: (-oo, +oo)
|
|
68
|
+
*/
|
|
69
|
+
speed: number;
|
|
70
|
+
/**
|
|
71
|
+
* 当前角度
|
|
72
|
+
* @description 单位: 度
|
|
73
|
+
* @description 默认值: 0
|
|
74
|
+
* @description 取值范围: (-180, 180]
|
|
75
|
+
*/
|
|
76
|
+
angle: number;
|
|
77
|
+
/**
|
|
78
|
+
* 总移动距离
|
|
79
|
+
* @description 单位: 像素
|
|
80
|
+
* @description 默认值: 0
|
|
81
|
+
* @description 取值范围: [0, +oo)
|
|
82
|
+
*/
|
|
83
|
+
distance: number;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 移动方向(只给出了常用的方向)
|
|
88
|
+
* @description 单位: 度
|
|
89
|
+
* @description 取值范围: (-180, 180]
|
|
90
|
+
*/
|
|
91
|
+
export enum MoveTowardType {
|
|
92
|
+
Right = 0,
|
|
93
|
+
RightUp = 45,
|
|
94
|
+
Up = 90,
|
|
95
|
+
LeftUp = 135,
|
|
96
|
+
Left = 180,
|
|
97
|
+
LeftDown = -135,
|
|
98
|
+
Down = -90,
|
|
99
|
+
RightDown = -45
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
@ecsclass('EcsMoveComponent')
|
|
103
|
+
export class MoveComponent<T extends IEntity = IEntity> extends EcsComponent<T> implements IMoveComponent {
|
|
104
|
+
static allowRecycling: boolean = true;
|
|
105
|
+
|
|
106
|
+
protected onRemove() {
|
|
107
|
+
this.reset();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
public reset() {
|
|
111
|
+
this._target = null;
|
|
112
|
+
this._toward = null;
|
|
113
|
+
this._targetUUID = null;
|
|
114
|
+
this._angle = null;
|
|
115
|
+
this._speed = 0;
|
|
116
|
+
this._distance = 0;
|
|
117
|
+
this._options.rotate = false;
|
|
118
|
+
this._options.minSpeed = -Infinity;
|
|
119
|
+
this._options.maxSpeed = Infinity;
|
|
120
|
+
this._options.acceleratedVelocity = 0;
|
|
121
|
+
this._options.angleVelocity = 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private _options: IOptions = {
|
|
125
|
+
rotate: false,
|
|
126
|
+
minSpeed: -Infinity,
|
|
127
|
+
maxSpeed: Infinity,
|
|
128
|
+
acceleratedVelocity: 0,
|
|
129
|
+
angleVelocity: 0,
|
|
130
|
+
};
|
|
131
|
+
public get options(): IOptions {
|
|
132
|
+
return this._options;
|
|
133
|
+
}
|
|
134
|
+
public set options(value: IOptions) {
|
|
135
|
+
this._options = value;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// 总移动距离
|
|
139
|
+
private _distance = 0;
|
|
140
|
+
public get distance() {
|
|
141
|
+
return this._distance;
|
|
142
|
+
}
|
|
143
|
+
private set distance(value) {
|
|
144
|
+
this._distance = value;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// 最终目标
|
|
148
|
+
private _targetUUID: number = null;
|
|
149
|
+
private _target: NodeComponent = null;
|
|
150
|
+
public get target(): NodeComponent {
|
|
151
|
+
if (this._target && this._target.uuid !== this._targetUUID) {
|
|
152
|
+
this._target = null;
|
|
153
|
+
}
|
|
154
|
+
return this._target;
|
|
155
|
+
}
|
|
156
|
+
public set target(value: NodeComponent) {
|
|
157
|
+
this._target = (value && value.isValid) ? value : null;
|
|
158
|
+
if (this._target) {
|
|
159
|
+
this._targetUUID = this._target.uuid;
|
|
160
|
+
} else {
|
|
161
|
+
this._targetUUID = null;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// 最终朝向
|
|
166
|
+
private _toward: number = null;
|
|
167
|
+
public get toward(): number {
|
|
168
|
+
return this._toward;
|
|
169
|
+
}
|
|
170
|
+
public set toward(value: number) {
|
|
171
|
+
this._toward = MoveComponent.getAngleFromNeg180to180(value);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// 当前角度
|
|
175
|
+
private _angle: number = 0;
|
|
176
|
+
public get angle() {
|
|
177
|
+
return this._angle;
|
|
178
|
+
}
|
|
179
|
+
public set angle(value) {
|
|
180
|
+
this._angle = MoveComponent.getAngleFromNeg180to180(value);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// 当前速度
|
|
184
|
+
private _speed: number = 0;
|
|
185
|
+
public get speed(): number {
|
|
186
|
+
if (this._speed < this.options.minSpeed) {
|
|
187
|
+
this._speed = this.options.minSpeed;
|
|
188
|
+
} else if (this._speed > this.options.maxSpeed) {
|
|
189
|
+
this._speed = this.options.maxSpeed;
|
|
190
|
+
}
|
|
191
|
+
return this._speed;
|
|
192
|
+
}
|
|
193
|
+
public set speed(value: number) {
|
|
194
|
+
if (value < this.options.minSpeed) {
|
|
195
|
+
value = this.options.minSpeed;
|
|
196
|
+
} else if (value > this.options.maxSpeed) {
|
|
197
|
+
value = this.options.maxSpeed;
|
|
198
|
+
}
|
|
199
|
+
this._speed = value;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* 获取self朝向other的角度
|
|
204
|
+
*/
|
|
205
|
+
static getTowardAngle(self: NodeComponent, other: NodeComponent) {
|
|
206
|
+
if (!self) return 0;
|
|
207
|
+
if (!other) return 0;
|
|
208
|
+
return math.toDegree(Math.atan2(other.y - self.y,
|
|
209
|
+
other.x - self.x));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* 修正到(-180, 180]
|
|
214
|
+
*/
|
|
215
|
+
static getAngleFromNeg180to180(angle: number) {
|
|
216
|
+
if (angle >= 360 || angle <= -360) {
|
|
217
|
+
angle = angle % 360;
|
|
218
|
+
}
|
|
219
|
+
if (angle > 180) {
|
|
220
|
+
angle -= 360;
|
|
221
|
+
} else if (angle <= -180) {
|
|
222
|
+
angle += 360;
|
|
223
|
+
}
|
|
224
|
+
return angle;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* 修正到[0, 360)
|
|
229
|
+
*/
|
|
230
|
+
static getAngleFrom0To360(angle: number) {
|
|
231
|
+
if (angle >= 360 || angle <= -360) {
|
|
232
|
+
angle = angle % 360;
|
|
233
|
+
}
|
|
234
|
+
if (angle < 0) {
|
|
235
|
+
angle += 360;
|
|
236
|
+
}
|
|
237
|
+
return angle;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* 修正到(-360, 0]
|
|
242
|
+
*/
|
|
243
|
+
static getAngleFromNeg360To0(angle: number) {
|
|
244
|
+
if (angle >= 360 || angle <= -360) {
|
|
245
|
+
angle = angle % 360;
|
|
246
|
+
}
|
|
247
|
+
if (angle > 0) {
|
|
248
|
+
angle -= 360;
|
|
249
|
+
}
|
|
250
|
+
return angle;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* 根据速度二维分量获取toward值
|
|
255
|
+
*/
|
|
256
|
+
static getTowardByVelocity(velocity: Vec2) {
|
|
257
|
+
// y速度为0
|
|
258
|
+
if (velocity.y === 0) {
|
|
259
|
+
if (velocity.x >= 0) {
|
|
260
|
+
return MoveTowardType.Right;
|
|
261
|
+
} else {
|
|
262
|
+
return MoveTowardType.Left;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
// x速度为0
|
|
266
|
+
if (velocity.x === 0) {
|
|
267
|
+
if (velocity.y >= 0) {
|
|
268
|
+
return MoveTowardType.Up;
|
|
269
|
+
} else {
|
|
270
|
+
return MoveTowardType.Down;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// x、y速度相等
|
|
274
|
+
if (velocity.x === velocity.y) {
|
|
275
|
+
if (velocity.x >= 0) {
|
|
276
|
+
return MoveTowardType.RightDown;
|
|
277
|
+
} else {
|
|
278
|
+
return MoveTowardType.LeftDown;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
// x、y速度相反
|
|
282
|
+
if (velocity.x === -velocity.y) {
|
|
283
|
+
if (velocity.x >= 0) {
|
|
284
|
+
return MoveTowardType.RightUp;
|
|
285
|
+
} else {
|
|
286
|
+
return MoveTowardType.LeftUp;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return Vec2.UNIT_X.signAngle(velocity);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import { Mat4, Quat, Rect, size, Size, UITransform, v2, v3, Vec2, Vec3 } from 'cc';
|
|
2
|
+
import { EcsComponent } from '../../ecs/EcsComponent';
|
|
3
|
+
import { ecsclass } from '../../lib/EcsManager';
|
|
4
|
+
import { IEntity } from '../../lib/EcsObject';
|
|
5
|
+
|
|
6
|
+
// export interface INodeReadonly {
|
|
7
|
+
// readonly uuid: number
|
|
8
|
+
// readonly isValid: boolean
|
|
9
|
+
// readonly isStrictValid: boolean
|
|
10
|
+
// readonly ecsName: string
|
|
11
|
+
// readonly allowMultiple: boolean
|
|
12
|
+
// readonly allowRecycling: boolean
|
|
13
|
+
|
|
14
|
+
// readonly boundingBox: Readonly<Rect>
|
|
15
|
+
// readonly minX: number
|
|
16
|
+
// readonly minY: number
|
|
17
|
+
// readonly maxX: number
|
|
18
|
+
// readonly maxY: number
|
|
19
|
+
// }
|
|
20
|
+
|
|
21
|
+
interface ILikeSize {
|
|
22
|
+
readonly width: number,
|
|
23
|
+
readonly height: number
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface ILikeV2 {
|
|
27
|
+
readonly x: number,
|
|
28
|
+
readonly y: number
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface ILikeV3 {
|
|
32
|
+
readonly x: number,
|
|
33
|
+
readonly y: number,
|
|
34
|
+
readonly z: number
|
|
35
|
+
}
|
|
36
|
+
const _matrix = new Mat4();
|
|
37
|
+
|
|
38
|
+
@ecsclass('EcsNodeComponent')
|
|
39
|
+
/**
|
|
40
|
+
* 负责位置、尺寸、缩放、锚点、旋转
|
|
41
|
+
*/
|
|
42
|
+
export class NodeComponent<T extends IEntity = IEntity> extends EcsComponent<T> {
|
|
43
|
+
static allowRecycling: boolean = true;
|
|
44
|
+
|
|
45
|
+
protected onRemove() {
|
|
46
|
+
this.reset();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public reset() {
|
|
50
|
+
this.$position.set(0, 0, 0);
|
|
51
|
+
this.$scale.set(1, 1, 1);
|
|
52
|
+
this.$anchorPoint.set(0.5, 0.5);
|
|
53
|
+
this.$contentSize.set(0, 0);
|
|
54
|
+
this.$lrot = new Quat();
|
|
55
|
+
this.$euler.set(0, 0, 0);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**是否需要更新BoundingBox */
|
|
59
|
+
protected isBoundingBoxDirty = true;
|
|
60
|
+
|
|
61
|
+
// 坐标
|
|
62
|
+
protected $position: Vec3 = v3();
|
|
63
|
+
/**坐标 */
|
|
64
|
+
public get position(): Readonly<ILikeV3> {
|
|
65
|
+
return this.$position;
|
|
66
|
+
}
|
|
67
|
+
/**x坐标 */
|
|
68
|
+
public get x(): number {
|
|
69
|
+
return this.$position.x;
|
|
70
|
+
}
|
|
71
|
+
public set x(value: number) {
|
|
72
|
+
this.$position.x = value;
|
|
73
|
+
this.isBoundingBoxDirty = true;
|
|
74
|
+
this.entity?.node?.setPosition(this.$position);
|
|
75
|
+
}
|
|
76
|
+
/**y坐标 */
|
|
77
|
+
public get y(): number {
|
|
78
|
+
return this.$position.y;
|
|
79
|
+
}
|
|
80
|
+
public set y(value: number) {
|
|
81
|
+
this.$position.y = value;
|
|
82
|
+
this.isBoundingBoxDirty = true;
|
|
83
|
+
this.entity?.node?.setPosition(this.$position);
|
|
84
|
+
}
|
|
85
|
+
/**z坐标 */
|
|
86
|
+
public get z(): number {
|
|
87
|
+
return this.$position.z;
|
|
88
|
+
}
|
|
89
|
+
public set z(value: number) {
|
|
90
|
+
this.$position.z = value;
|
|
91
|
+
this.isBoundingBoxDirty = true;
|
|
92
|
+
this.entity?.node?.setPosition(this.$position);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// 缩放
|
|
96
|
+
protected $scale: Vec3 = v3(1, 1, 1);
|
|
97
|
+
/**缩放 */
|
|
98
|
+
public get scale(): Readonly<ILikeV3> {
|
|
99
|
+
return this.$scale;
|
|
100
|
+
}
|
|
101
|
+
/**缩放x */
|
|
102
|
+
public get scaleX(): number {
|
|
103
|
+
return this.$scale.x;
|
|
104
|
+
}
|
|
105
|
+
public set scaleX(value: number) {
|
|
106
|
+
this.$scale.x = value;
|
|
107
|
+
this.isBoundingBoxDirty = true;
|
|
108
|
+
this.entity?.node?.setScale(this.$scale);
|
|
109
|
+
}
|
|
110
|
+
/**缩放y */
|
|
111
|
+
public get scaleY(): number {
|
|
112
|
+
return this.$scale.y;
|
|
113
|
+
}
|
|
114
|
+
public set scaleY(value: number) {
|
|
115
|
+
this.$scale.y = value;
|
|
116
|
+
this.isBoundingBoxDirty = true;
|
|
117
|
+
this.entity?.node?.setScale(this.$scale);
|
|
118
|
+
}
|
|
119
|
+
/**缩放z */
|
|
120
|
+
public get scaleZ(): number {
|
|
121
|
+
return this.$scale.z;
|
|
122
|
+
}
|
|
123
|
+
public set scaleZ(value: number) {
|
|
124
|
+
this.$scale.z = value;
|
|
125
|
+
this.isBoundingBoxDirty = true;
|
|
126
|
+
this.entity?.node?.setScale(this.$scale);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// 锚点
|
|
130
|
+
protected $anchorPoint: Vec2 = v2(0.5, 0.5);
|
|
131
|
+
/**锚点 */
|
|
132
|
+
public get anchorPoint(): Readonly<ILikeV2> {
|
|
133
|
+
return this.$anchorPoint;
|
|
134
|
+
}
|
|
135
|
+
/**锚点x */
|
|
136
|
+
public get anchorX(): number {
|
|
137
|
+
return this.$anchorPoint.x;
|
|
138
|
+
}
|
|
139
|
+
public set anchorX(value: number) {
|
|
140
|
+
this.$anchorPoint.x = value;
|
|
141
|
+
this.isBoundingBoxDirty = true;
|
|
142
|
+
this.entity?.node?.getComponent(UITransform)?.setAnchorPoint(this.$anchorPoint);
|
|
143
|
+
}
|
|
144
|
+
/**锚点y */
|
|
145
|
+
public get anchorY(): number {
|
|
146
|
+
return this.$anchorPoint.y;
|
|
147
|
+
}
|
|
148
|
+
public set anchorY(value: number) {
|
|
149
|
+
this.$anchorPoint.y = value;
|
|
150
|
+
this.isBoundingBoxDirty = true;
|
|
151
|
+
this.entity?.node?.getComponent(UITransform)?.setAnchorPoint(this.$anchorPoint);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 尺寸
|
|
155
|
+
protected $contentSize: Size = size();
|
|
156
|
+
/**尺寸 */
|
|
157
|
+
public get contentSize(): Readonly<ILikeSize> {
|
|
158
|
+
return this.$contentSize;
|
|
159
|
+
}
|
|
160
|
+
/**宽 */
|
|
161
|
+
public get width(): number {
|
|
162
|
+
return this.$contentSize.width;
|
|
163
|
+
}
|
|
164
|
+
public set width(value: number) {
|
|
165
|
+
this.$contentSize.width = value;
|
|
166
|
+
this.isBoundingBoxDirty = true;
|
|
167
|
+
this.entity?.node?.getComponent(UITransform)?.setContentSize(this.$contentSize);
|
|
168
|
+
}
|
|
169
|
+
/**高 */
|
|
170
|
+
public get height(): number {
|
|
171
|
+
return this.$contentSize.height;
|
|
172
|
+
}
|
|
173
|
+
public set height(value: number) {
|
|
174
|
+
this.$contentSize.height = value;
|
|
175
|
+
this.isBoundingBoxDirty = true;
|
|
176
|
+
this.entity?.node?.getComponent(UITransform)?.setContentSize(this.$contentSize);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// 旋转四元数
|
|
180
|
+
protected $lrot = new Quat();
|
|
181
|
+
/**本地坐标系下的旋转,用四元数表示 */
|
|
182
|
+
public get rotation(): Readonly<Quat> {
|
|
183
|
+
return this.$lrot;
|
|
184
|
+
}
|
|
185
|
+
public set rotation(val) {
|
|
186
|
+
Quat.copy(this.$lrot, val);
|
|
187
|
+
Quat.toEuler(this.$euler, this.$lrot);
|
|
188
|
+
this.isBoundingBoxDirty = true;
|
|
189
|
+
this.entity?.node?.setRotation(this.$lrot);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// 旋转欧拉角
|
|
193
|
+
protected $euler: Vec3 = v3();
|
|
194
|
+
/**本地坐标系下的旋转,用欧拉角表示 */
|
|
195
|
+
public get eulerAngles(): Readonly<Vec3> {
|
|
196
|
+
return this.$euler;
|
|
197
|
+
}
|
|
198
|
+
public set eulerAngles(val) {
|
|
199
|
+
Vec3.copy(this.$euler, val);
|
|
200
|
+
Quat.fromEuler(this.$lrot, val.x, val.y, val.z);
|
|
201
|
+
this.isBoundingBoxDirty = true;
|
|
202
|
+
this.entity?.node?.setRotation(this.$lrot);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**本地坐标系下的旋转,用欧拉角表示,但是限定在 z 轴上 */
|
|
206
|
+
public get angle(): number {
|
|
207
|
+
return this.$euler.z;
|
|
208
|
+
}
|
|
209
|
+
public set angle(value: number) {
|
|
210
|
+
this.$euler.z = value;
|
|
211
|
+
Quat.fromAngleZ(this.$lrot, value);
|
|
212
|
+
this.isBoundingBoxDirty = true;
|
|
213
|
+
this.entity?.node?.setRotation(this.$lrot);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private _boundingBox = new Rect();
|
|
217
|
+
private _boundingBoxOut = new Rect();
|
|
218
|
+
/**轴对称包围盒 */
|
|
219
|
+
get boundingBox(): Rect {
|
|
220
|
+
this._updateBoundingBox();
|
|
221
|
+
return this._boundingBoxOut.set(this._boundingBox);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
protected _updateBoundingBox() {
|
|
225
|
+
if (!this.isBoundingBoxDirty) return;
|
|
226
|
+
this.isBoundingBoxDirty = false;
|
|
227
|
+
|
|
228
|
+
// selfBoundingBox
|
|
229
|
+
this._boundingBox.set(
|
|
230
|
+
-this.anchorPoint.x * this.width,
|
|
231
|
+
-this.anchorPoint.y * this.height,
|
|
232
|
+
this.width,
|
|
233
|
+
this.height,
|
|
234
|
+
);
|
|
235
|
+
// 矩阵变换
|
|
236
|
+
if (Mat4['fromSRT']) { // since 3.8.0
|
|
237
|
+
Mat4['fromSRT'](_matrix, this.rotation, this.position, this.scale);
|
|
238
|
+
} else {
|
|
239
|
+
Mat4.fromRTS(_matrix, this.rotation, this.position, this.scale);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
this._boundingBox.transformMat4(_matrix);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**最小x坐标 */
|
|
246
|
+
get minX() {
|
|
247
|
+
this._updateBoundingBox();
|
|
248
|
+
return this._boundingBox.xMin;
|
|
249
|
+
}
|
|
250
|
+
/**最小y坐标 */
|
|
251
|
+
get minY() {
|
|
252
|
+
this._updateBoundingBox();
|
|
253
|
+
return this._boundingBox.yMin;
|
|
254
|
+
}
|
|
255
|
+
/**最大x坐标 */
|
|
256
|
+
get maxX() {
|
|
257
|
+
this._updateBoundingBox();
|
|
258
|
+
return this._boundingBox.xMax;
|
|
259
|
+
}
|
|
260
|
+
/**最大y坐标 */
|
|
261
|
+
get maxY() {
|
|
262
|
+
this._updateBoundingBox();
|
|
263
|
+
return this._boundingBox.yMax;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
public setPosition(x: number, y: number, z: number = this.z) {
|
|
267
|
+
this.x = x;
|
|
268
|
+
this.y = y;
|
|
269
|
+
this.z = z;
|
|
270
|
+
return this;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
public addPosition(x: number, y: number, z: number = 0) {
|
|
274
|
+
this.x += x;
|
|
275
|
+
this.y += y;
|
|
276
|
+
this.z += z;
|
|
277
|
+
return this;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
public setScale(x: number, y: number, z: number = this.scaleZ) {
|
|
281
|
+
this.scaleX = x;
|
|
282
|
+
this.scaleY = y;
|
|
283
|
+
this.scaleZ = z;
|
|
284
|
+
return this;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
public addScale(x: number, y: number, z: number = 0) {
|
|
288
|
+
this.scaleX += x;
|
|
289
|
+
this.scaleY += y;
|
|
290
|
+
this.scaleZ += z;
|
|
291
|
+
return this;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
public setAngle(angle: number) {
|
|
295
|
+
this.angle = angle;
|
|
296
|
+
return this;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
public addAngle(angle: number) {
|
|
300
|
+
this.angle += angle;
|
|
301
|
+
return this;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
public setContentSize(width: number, height: number) {
|
|
305
|
+
this.width = width;
|
|
306
|
+
this.height = height;
|
|
307
|
+
return this;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
public setAnchorPoints(x: number, y: number) {
|
|
311
|
+
this.anchorX = x;
|
|
312
|
+
this.anchorY = y;
|
|
313
|
+
return this;
|
|
314
|
+
}
|
|
315
|
+
}
|