@cyclonium/2d 0.0.103 → 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.
@@ -0,0 +1 @@
1
+ {}
@@ -0,0 +1,65 @@
1
+ // Effect Syntax Guide: https://docs.cocos.com/creator/manual/zh/shader/index.html
2
+
3
+ CCEffect %{
4
+ techniques:
5
+ - name: default
6
+ passes:
7
+ - vert: sprite-renderer-vs:vert
8
+ frag: sprite-renderer-fs:frag
9
+ properties: &props
10
+ mainTexture: { value: white }
11
+ mainColor: { value: [1, 1, 1, 1], editor: { type: color } }
12
+ rasterizerState:
13
+ cullMode: none
14
+ cullFace: front
15
+ depthStencilState:
16
+ depthTest: true
17
+ depthWrite: false
18
+ blendState:
19
+ targets:
20
+ - blend: true
21
+ blendSrc: src_alpha
22
+ blendDst: one_minus_src_alpha
23
+ blendSrcAlpha: src_alpha
24
+ blendDstAlpha: one_minus_src_alpha
25
+ }%
26
+
27
+ CCProgram sprite-renderer-vs %{
28
+ precision highp float;
29
+
30
+ #include <builtin/uniforms/cc-local>
31
+ #include <builtin/uniforms/cc-global>
32
+ #include <builtin/functionalities/world-transform>
33
+
34
+ in vec2 a_position;
35
+ in vec2 a_texCoord;
36
+
37
+ out vec2 v_texCoord;
38
+
39
+ vec4 vert() {
40
+ v_texCoord = a_texCoord;
41
+
42
+ vec3 position = vec3(a_position, 0.0);
43
+ return cc_matProj * (cc_matView * cc_matWorld) * vec4(position, 1.0);
44
+ }
45
+ }%
46
+
47
+ CCProgram sprite-renderer-fs %{
48
+ precision highp float;
49
+ #include <legacy/output>
50
+ #include <legacy/fog-fs>
51
+
52
+ in vec2 v_texCoord;
53
+ in vec3 v_position;
54
+
55
+ uniform sampler2D mainTexture;
56
+
57
+ uniform Constant {
58
+ vec4 mainColor;
59
+ };
60
+
61
+ vec4 frag () {
62
+ vec4 color = mainColor * texture(mainTexture, vec2(v_texCoord.x, 1.0 - v_texCoord.y));
63
+ return color;
64
+ }
65
+ }%
@@ -0,0 +1,11 @@
1
+ {
2
+ "ver": "1.7.1",
3
+ "importer": "effect",
4
+ "imported": true,
5
+ "uuid": "230b4535-10a9-475d-843a-05cbf87b2227",
6
+ "files": [
7
+ ".json"
8
+ ],
9
+ "subMetas": {},
10
+ "userData": {}
11
+ }
@@ -1,6 +1,7 @@
1
1
  import { CycloComponent } from '@cyclonium/core/framework';
2
- import { Texture2D, Material, Color, componentEditorTraits, geometry } from 'cc';
2
+ import { Material, Color, componentEditorTraits, geometry } from 'cc';
3
3
  import { Bounds2D } from '@cyclonium/core/math/bounds-2d';
4
+ import { Sprite } from './sprite.js';
4
5
  import { SortableRenderer } from './sortable.js';
5
6
  import { SortSettings } from './sort-settings.js';
6
7
  export declare enum SpriteRenderType {
@@ -12,8 +13,8 @@ export declare class SpriteRenderer extends CycloComponent implements SortableRe
12
13
  set renderType(value: SpriteRenderType);
13
14
  get color(): Color;
14
15
  set color(value: Color);
15
- get sprite(): Texture2D | undefined;
16
- set sprite(value: Texture2D | undefined);
16
+ get sprite(): Sprite | undefined;
17
+ set sprite(value: Sprite | undefined);
17
18
  debugShowNormals: boolean;
18
19
  get sortSettings(): SortSettings;
19
20
  get [SortableRenderer.Tags.sortSettings](): SortSettings;
@@ -47,16 +48,17 @@ export declare class SpriteRenderer extends CycloComponent implements SortableRe
47
48
  private _createDefaultEffectMaterialAndSetAsEffective;
48
49
  private _setEffectiveMaterial;
49
50
  private _destroyRenderRecord;
50
- private _constructRenderRecord;
51
+ private _reconstructRenderRecord;
52
+ private _markRenderRecordDirty;
53
+ private _updateRenderRecordBounds;
51
54
  private _createRenderingSubMeshes;
52
55
  private _createRenderingSubMeshesInSimpleRenderType;
56
+ private _updateSimpleRenderVertexBuffer;
53
57
  private _updateAllMaterialProperties;
54
58
  private _updateMaterialColor;
55
59
  private _updateMaterialSprite;
56
- private _updateMaterialPixelsPerUnit;
57
60
  private _updateModelBoundingShape;
58
61
  private _updateLocalBounds;
59
- private _getBoundingHalfSize;
60
62
  private _syncRenderRecordEnabled;
61
63
  private _shouldRenderRecordBeEnabled;
62
64
  }
@@ -7,7 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  };
8
8
  import { CycloComponent } from '@cyclonium/core/framework';
9
9
  import { designType, editable, executeInEditMode, cycloClass, idem, serializable } from '@cyclonium/core/legacy-decorator';
10
- import { Texture2D, Material, Color, renderer, RenderingSubMesh, gfx, EffectAsset, Vec2, Vec3, componentEditorTraits, geometry, assetManager } from 'cc';
10
+ import { Material, Color, renderer, RenderingSubMesh, gfx, EffectAsset, Vec3, componentEditorTraits, geometry, assetManager } from 'cc';
11
11
  import { assert, markEnum } from '@cyclonium/core/utils';
12
12
  import { logger } from '@cyclonium/core/log';
13
13
  import { Bounds2D } from '@cyclonium/core/math/bounds-2d';
@@ -20,6 +20,13 @@ export var SpriteRenderType;
20
20
  SpriteRenderType["simple"] = "simple";
21
21
  })(SpriteRenderType || (SpriteRenderType = {}));
22
22
  markEnum(SpriteRenderType);
23
+ var RenderRecordDirtyFlag;
24
+ (function (RenderRecordDirtyFlag) {
25
+ // Render type changes can alter submesh/model structure, so they require a full record rebuild.
26
+ RenderRecordDirtyFlag[RenderRecordDirtyFlag["renderType"] = 1] = "renderType";
27
+ // Bounds changes keep the same simple quad topology and only rewrite vertex data.
28
+ RenderRecordDirtyFlag[RenderRecordDirtyFlag["bounds"] = 2] = "bounds";
29
+ })(RenderRecordDirtyFlag || (RenderRecordDirtyFlag = {}));
23
30
  const loadDefaultEffect = (() => {
24
31
  let defaultEffect;
25
32
  return () => {
@@ -51,7 +58,7 @@ let SpriteRenderer = class SpriteRenderer extends CycloComponent {
51
58
  }
52
59
  set renderType(value) {
53
60
  this._renderType = value;
54
- this._constructRenderRecord();
61
+ this._markRenderRecordDirty(RenderRecordDirtyFlag.renderType);
55
62
  }
56
63
  get color() {
57
64
  return this._color;
@@ -70,10 +77,7 @@ let SpriteRenderer = class SpriteRenderer extends CycloComponent {
70
77
  if (this._effectiveMaterial) {
71
78
  this._updateMaterialSprite(this._effectiveMaterial);
72
79
  }
73
- if (this._renderRecord) {
74
- this._updateModelBoundingShape(this._renderRecord.model);
75
- this._syncRenderRecordEnabled();
76
- }
80
+ this._markRenderRecordDirty(RenderRecordDirtyFlag.bounds);
77
81
  }
78
82
  debugShowNormals = false;
79
83
  get sortSettings() {
@@ -87,12 +91,7 @@ let SpriteRenderer = class SpriteRenderer extends CycloComponent {
87
91
  }
88
92
  set pixelsPerUnit(value) {
89
93
  this._pixelsPerUnit = value;
90
- if (this._effectiveMaterial) {
91
- this._updateMaterialPixelsPerUnit(this._effectiveMaterial);
92
- }
93
- if (this._renderRecord) {
94
- this._updateModelBoundingShape(this._renderRecord.model);
95
- }
94
+ this._markRenderRecordDirty(RenderRecordDirtyFlag.bounds);
96
95
  }
97
96
  get material() {
98
97
  return this._material;
@@ -149,12 +148,11 @@ let SpriteRenderer = class SpriteRenderer extends CycloComponent {
149
148
  }
150
149
  switch (this.renderType) {
151
150
  case SpriteRenderType.simple:
152
- if (this._renderRecord) {
153
- // nothing
151
+ if (!this._renderRecord || (this._renderRecord.dirty & RenderRecordDirtyFlag.renderType) !== 0) {
152
+ this._reconstructRenderRecord();
154
153
  }
155
- else {
156
- this._destroyRenderRecord();
157
- this._constructRenderRecord();
154
+ else if ((this._renderRecord.dirty & RenderRecordDirtyFlag.bounds) !== 0) {
155
+ this._updateRenderRecordBounds(this._renderRecord);
158
156
  }
159
157
  break;
160
158
  default:
@@ -232,10 +230,17 @@ let SpriteRenderer = class SpriteRenderer extends CycloComponent {
232
230
  });
233
231
  model.destroy();
234
232
  }
235
- _constructRenderRecord() {
233
+ _reconstructRenderRecord() {
234
+ this._destroyRenderRecord();
235
+ switch (this._renderType) {
236
+ case SpriteRenderType.simple:
237
+ break;
238
+ default:
239
+ return;
240
+ }
236
241
  const renderScene = this._getRenderScene();
237
242
  const device = renderScene.root.device;
238
- const renderingSubMeshes = this._createRenderingSubMeshes(device);
243
+ const { renderingSubMeshes, vertexBuffer, localVertexBuffer, } = this._createRenderingSubMeshes(device);
239
244
  const model = new renderer.scene.Model();
240
245
  model.node = this.node;
241
246
  model.transform = this.node;
@@ -248,7 +253,10 @@ let SpriteRenderer = class SpriteRenderer extends CycloComponent {
248
253
  model.enabled = this._shouldRenderRecordBeEnabled();
249
254
  renderScene.addModel(model);
250
255
  this._renderRecord = {
256
+ dirty: 0,
251
257
  renderingSubMeshes: renderingSubMeshes,
258
+ vertexBuffer,
259
+ localVertexBuffer,
252
260
  model: model,
253
261
  renderScene,
254
262
  };
@@ -256,6 +264,17 @@ let SpriteRenderer = class SpriteRenderer extends CycloComponent {
256
264
  model.priority = this._sortSettings.sortingKey;
257
265
  }
258
266
  }
267
+ _markRenderRecordDirty(flag) {
268
+ if (this._renderRecord) {
269
+ this._renderRecord.dirty |= flag;
270
+ }
271
+ }
272
+ _updateRenderRecordBounds(renderRecord) {
273
+ this._updateSimpleRenderVertexBuffer(renderRecord.vertexBuffer, renderRecord.localVertexBuffer);
274
+ this._updateModelBoundingShape(renderRecord.model);
275
+ this._syncRenderRecordEnabled();
276
+ renderRecord.dirty &= ~RenderRecordDirtyFlag.bounds;
277
+ }
259
278
  _createRenderingSubMeshes(device) {
260
279
  switch (this._renderType) {
261
280
  case SpriteRenderType.simple:
@@ -265,57 +284,55 @@ let SpriteRenderer = class SpriteRenderer extends CycloComponent {
265
284
  }
266
285
  }
267
286
  _createRenderingSubMeshesInSimpleRenderType(device) {
268
- const { vertexCount, positions, normals, indices, } = simpleSpriteQuad;
269
- const offsetPositionF = 0;
270
- const stridePositionF = 2;
271
- const offsetNormalF = offsetPositionF + stridePositionF;
272
- const strideNormalF = 2;
273
- const strideF = offsetNormalF + strideNormalF;
274
- const localVertexBuffer = new Float32Array(vertexCount * strideF);
275
- let pVerticesF = 0;
276
- for (let i = 0; i < vertexCount; i++) {
277
- localVertexBuffer[pVerticesF + offsetPositionF] = positions[i * 2];
278
- localVertexBuffer[pVerticesF + offsetPositionF + 1] = positions[i * 2 + 1];
279
- localVertexBuffer[pVerticesF + offsetNormalF] = normals[i * 2];
280
- localVertexBuffer[pVerticesF + offsetNormalF + 1] = normals[i * 2 + 1];
281
- pVerticesF += strideF;
282
- }
283
- const vertexBuffer = device.createBuffer(new gfx.BufferInfo(gfx.BufferUsageBit.VERTEX, gfx.MemoryUsageBit.DEVICE, localVertexBuffer.byteLength, Float32Array.BYTES_PER_ELEMENT * strideF, gfx.BufferFlagBit.NONE));
284
- updateGfxBuffer(vertexBuffer, localVertexBuffer);
287
+ const { indices, } = simpleSpriteQuad;
288
+ const localVertexBuffer = new Float32Array(simpleSpriteQuad.vertexCount * simpleSpriteQuad.strideF);
289
+ const vertexBuffer = device.createBuffer(new gfx.BufferInfo(gfx.BufferUsageBit.VERTEX, gfx.MemoryUsageBit.DEVICE, localVertexBuffer.byteLength, Float32Array.BYTES_PER_ELEMENT * simpleSpriteQuad.strideF, gfx.BufferFlagBit.NONE));
290
+ this._updateSimpleRenderVertexBuffer(vertexBuffer, localVertexBuffer);
285
291
  const indexBuffer = device.createBuffer(new gfx.BufferInfo(gfx.BufferUsageBit.INDEX, gfx.MemoryUsageBit.DEVICE, indices.byteLength, indices.BYTES_PER_ELEMENT, gfx.BufferFlagBit.NONE));
286
292
  updateGfxBuffer(indexBuffer, indices);
287
293
  const renderingSubMesh = new RenderingSubMesh([vertexBuffer], [
288
- new gfx.Attribute(gfx.AttributeName.ATTR_POSITION, gfx.Format.RGB32F, false, undefined, false, undefined),
294
+ new gfx.Attribute(gfx.AttributeName.ATTR_POSITION, gfx.Format.RG32F, false, undefined, false, undefined),
289
295
  new gfx.Attribute(gfx.AttributeName.ATTR_NORMAL, gfx.Format.RG32F, false, undefined, false, undefined),
290
296
  new gfx.Attribute(gfx.AttributeName.ATTR_TEX_COORD, gfx.Format.RG32F, false, undefined, false, undefined),
291
297
  ], gfx.PrimitiveMode.TRIANGLE_LIST, indexBuffer, null, true);
292
- return [renderingSubMesh];
298
+ return {
299
+ renderingSubMeshes: [renderingSubMesh],
300
+ vertexBuffer,
301
+ localVertexBuffer,
302
+ };
303
+ }
304
+ _updateSimpleRenderVertexBuffer(vertexBuffer, localVertexBuffer) {
305
+ const { offsetNormalF, offsetPositionF, offsetTexCoordF, normals, strideF, texCoords, uvVertexIndices, vertexCount, } = simpleSpriteQuad;
306
+ const localBounds = this.localBounds;
307
+ const spriteUV = this.sprite?.uv ?? texCoords;
308
+ localVertexBuffer[offsetPositionF] = localBounds.xMin;
309
+ localVertexBuffer[offsetPositionF + 1] = localBounds.yMin;
310
+ localVertexBuffer[strideF + offsetPositionF] = localBounds.xMin;
311
+ localVertexBuffer[strideF + offsetPositionF + 1] = localBounds.yMax;
312
+ localVertexBuffer[2 * strideF + offsetPositionF] = localBounds.xMax;
313
+ localVertexBuffer[2 * strideF + offsetPositionF + 1] = localBounds.yMax;
314
+ localVertexBuffer[3 * strideF + offsetPositionF] = localBounds.xMax;
315
+ localVertexBuffer[3 * strideF + offsetPositionF + 1] = localBounds.yMin;
316
+ for (let iVertex = 0; iVertex < vertexCount; iVertex++) {
317
+ const pVerticesF = iVertex * strideF;
318
+ const pVectorF = iVertex * 2;
319
+ const pUVF = uvVertexIndices[iVertex] * 2;
320
+ localVertexBuffer[pVerticesF + offsetNormalF] = normals[pVectorF];
321
+ localVertexBuffer[pVerticesF + offsetNormalF + 1] = normals[pVectorF + 1];
322
+ localVertexBuffer[pVerticesF + offsetTexCoordF] = spriteUV[pUVF];
323
+ localVertexBuffer[pVerticesF + offsetTexCoordF + 1] = spriteUV[pUVF + 1];
324
+ }
325
+ updateGfxBuffer(vertexBuffer, localVertexBuffer);
293
326
  }
294
327
  _updateAllMaterialProperties(material) {
295
328
  this._updateMaterialColor(material);
296
329
  this._updateMaterialSprite(material);
297
- this._updateMaterialPixelsPerUnit(material);
298
330
  }
299
331
  _updateMaterialColor(material) {
300
332
  material.setProperty('mainColor', this.color);
301
333
  }
302
334
  _updateMaterialSprite(material) {
303
- const pixelsPerUnit = this._pixelsPerUnit;
304
- let mainTexture = null;
305
- const spriteSize = new Vec2();
306
- if (this.sprite) {
307
- mainTexture = this.sprite;
308
- spriteSize.set(this.sprite.width / 2, this.sprite.height / 2);
309
- }
310
- else {
311
- mainTexture = null;
312
- spriteSize.set(pixelsPerUnit, pixelsPerUnit);
313
- }
314
- material.setProperty('mainTexture', mainTexture);
315
- material.setProperty('spriteSize', spriteSize);
316
- }
317
- _updateMaterialPixelsPerUnit(material) {
318
- material.setProperty('pixelsPerUnit', this._pixelsPerUnit);
335
+ material.setProperty('mainTexture', this.sprite?.texture ?? null);
319
336
  }
320
337
  _updateModelBoundingShape(model) {
321
338
  const localBounds = this.localBounds;
@@ -323,16 +340,17 @@ let SpriteRenderer = class SpriteRenderer extends CycloComponent {
323
340
  model.updateWorldBound();
324
341
  }
325
342
  _updateLocalBounds(bounds) {
326
- const halfSize = this._getBoundingHalfSize();
327
- bounds.min.set(-halfSize.x, -halfSize.y);
328
- bounds.max.set(halfSize.x, halfSize.y);
329
- return bounds;
330
- }
331
- _getBoundingHalfSize() {
332
343
  if (!this.sprite) {
333
- return new Vec2(1, 1);
344
+ bounds.min.set(-1, -1);
345
+ bounds.max.set(1, 1);
346
+ return bounds;
334
347
  }
335
- return new Vec2(this.sprite.width / 2 / this.pixelsPerUnit, this.sprite.height / 2 / this.pixelsPerUnit);
348
+ const width = this.sprite.rect.width / this.pixelsPerUnit;
349
+ const height = this.sprite.rect.height / this.pixelsPerUnit;
350
+ const pivot = this.sprite.pivot;
351
+ bounds.min.set(-pivot.x * width, -pivot.y * height);
352
+ bounds.max.set((1 - pivot.x) * width, (1 - pivot.y) * height);
353
+ return bounds;
336
354
  }
337
355
  _syncRenderRecordEnabled() {
338
356
  if (this._renderRecord) {
@@ -346,7 +364,8 @@ let SpriteRenderer = class SpriteRenderer extends CycloComponent {
346
364
  __decorate([
347
365
  editable,
348
366
  serializable,
349
- designType(SpriteRenderType)
367
+ designType(SpriteRenderType),
368
+ idem
350
369
  ], SpriteRenderer.prototype, "renderType", null);
351
370
  __decorate([
352
371
  editable
@@ -392,6 +411,13 @@ SpriteRenderer = __decorate([
392
411
  ], SpriteRenderer);
393
412
  export { SpriteRenderer };
394
413
  const simpleSpriteQuad = (() => {
414
+ const offsetPositionF = 0;
415
+ const stridePositionF = 2;
416
+ const offsetNormalF = offsetPositionF + stridePositionF;
417
+ const strideNormalF = 2;
418
+ const offsetTexCoordF = offsetNormalF + strideNormalF;
419
+ const strideTexCoordF = 2;
420
+ const strideF = offsetTexCoordF + strideTexCoordF;
395
421
  const positions = new Float32Array([
396
422
  -1, -1, // left bottom
397
423
  -1, 1, // left top
@@ -400,14 +426,27 @@ const simpleSpriteQuad = (() => {
400
426
  ]);
401
427
  const n = Math.sqrt(2);
402
428
  const normals = positions.map((position) => n * position);
429
+ const texCoords = new Float32Array([
430
+ 0, 0, // left bottom
431
+ 0, 1, // left top
432
+ 1, 1, // right top
433
+ 1, 0, // right bottom
434
+ ]);
435
+ // Cocos SpriteFrame.uv is ordered as left-bottom, right-bottom, left-top, right-top.
436
+ const uvVertexIndices = new Uint8Array([0, 2, 3, 1]);
403
437
  const indices = new Uint16Array([
404
438
  0, 1, 2,
405
439
  0, 2, 3,
406
440
  ]);
407
441
  return {
442
+ offsetNormalF,
443
+ offsetPositionF,
444
+ offsetTexCoordF,
445
+ strideF,
408
446
  vertexCount: 4,
409
- positions,
410
447
  normals,
448
+ texCoords,
449
+ uvVertexIndices,
411
450
  indices,
412
451
  };
413
452
  })();
package/lib/sprite.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { Texture2D as Sprite } from 'cc';
1
+ export { SpriteFrame as Sprite } from 'cc';
2
2
  //# sourceMappingURL=sprite.d.ts.map
package/lib/sprite.js CHANGED
@@ -1 +1 @@
1
- export { Texture2D as Sprite } from 'cc';
1
+ export { SpriteFrame as Sprite } from 'cc';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyclonium/2d",
3
- "version": "0.0.103",
3
+ "version": "1.0.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/shrinktofit/cyclonium",
@@ -8,21 +8,18 @@
8
8
  },
9
9
  "type": "module",
10
10
  "files": [
11
- "lib/**/*{.js,.d.ts}"
11
+ "lib",
12
+ "!lib/**/*.map",
13
+ "assets"
12
14
  ],
13
15
  "exports": {
14
- ".": {
15
- "types": "./lib/index.d.ts",
16
- "default": "./lib/index.js"
17
- },
18
- "./editor": {
19
- "types": "./lib/editor.d.ts",
20
- "default": "./lib/editor.js"
21
- }
16
+ ".": "./lib/index.js",
17
+ "./editor": "./lib/editor.js",
18
+ "./assets-meta": "./assets/meta.json"
22
19
  },
23
20
  "peerDependencies": {
24
- "@cyclonium/core": "0.0.103",
25
- "@cyclonium/editor": "0.0.103"
21
+ "@cyclonium/core": "0.0.104",
22
+ "@cyclonium/editor": "0.0.104"
26
23
  },
27
24
  "peerDependenciesMeta": {
28
25
  "@cyclonium/editor": {
@@ -35,8 +32,9 @@
35
32
  "playwright": "^1.59.1",
36
33
  "typescript": "^6.0.2",
37
34
  "vitest": "^4.1.5",
35
+ "@cyclonium/canvas-3d": "0.0.104",
38
36
  "@cyclonium/cc-test": "0.0.102",
39
- "@cyclonium/editor": "0.0.103",
37
+ "@cyclonium/editor": "0.0.104",
40
38
  "@cyclonium/workflow": "0.0.100",
41
39
  "@cyclonium/types-cc": "0.0.100"
42
40
  },