@neocompose/cli 0.80.0 → 0.81.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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.81.0
4
+
5
+ ### Minor Changes
6
+
7
+ - a130be0: `NeoSpriteObject` extends `NeoObject` (P111). A sprite class can be placed on an object layer, can have `Children`, and gets `OnObjectSpawned`/`OnObjectDespawned`. `PlacementTiles = []` keeps any object, sprite or not, out of the grid's occupied cells: it blocks no placement and `GetObjects`, `GetTile` and `GetTiles` never return it. A placed object with no tiles still has a `Cell`.
8
+
9
+ The system schema rollout gives existing sprite instances empty `PlacementTiles` and `Children`. Run `neo pull` and `neo export` after upgrading. Requires Neo Compose .NET SDK 0.71.0.
10
+
11
+ ### Patch Changes
12
+
13
+ - 2c89443: Materialize authored defaults for omitted optional constructor fields so collection mutations persist on each instance. Match the .NET runtime while preserving omission for fields without defaults.
14
+
3
15
  ## 0.80.0
4
16
 
5
17
  ### Minor Changes
package/dist/neo.mjs CHANGED
@@ -715,11 +715,11 @@ var init_world_system_kinds_generated = __esm({
715
715
  ObjectCollider: "objectCollider",
716
716
  SortingGroup: "sortingGroup",
717
717
  LayerGroupBase: "layerGroupBase",
718
- SpriteObject: "spriteObject",
719
718
  PlacementTile: "placementTile",
720
719
  TileLayerLink: "tileLayerLink",
721
720
  ObjectLayerLink: "objectLayerLink",
722
721
  Object: "object",
722
+ SpriteObject: "spriteObject",
723
723
  SmartTile: "smartTile",
724
724
  SmartTileRule: "smartTileRule",
725
725
  SmartTileNeighbor: "smartTileNeighbor",
@@ -7675,64 +7675,6 @@ var init_world_system_classes_generated = __esm({
7675
7675
  modifier: 1 /* Abstract */,
7676
7676
  worldKind: "layerGroupBase"
7677
7677
  },
7678
- {
7679
- classId: "system_d48b66ab-4d59-47e7-a25a-591fe97062de",
7680
- name: "NeoSpriteObject",
7681
- extendsWorldKind: "objectBase",
7682
- schemaFields: [
7683
- {
7684
- memberId: "system_441cb790-a45f-4488-a5a9-6f375af6c369",
7685
- memberKind: "string",
7686
- defaultValue: "",
7687
- format: 1 /* Plain */,
7688
- distribution: 1 /* Packed */,
7689
- requirement: 1 /* Required */,
7690
- schemaKey: "Name"
7691
- },
7692
- {
7693
- memberId: "system_e9288ba9-f5a2-4485-8443-6afb155b31e0",
7694
- memberKind: "sprite",
7695
- defaultValue: { fileId: "", sliceIndex: 0 },
7696
- requirement: 1 /* Required */,
7697
- schemaKey: "Sprite"
7698
- },
7699
- {
7700
- memberId: "system_9fcab37a-9743-4e35-8eee-80cb560f1433",
7701
- memberKind: "bool",
7702
- defaultValue: false,
7703
- docsText: "Mirrors the sprite horizontally about its own centre. Maps to SpriteRenderer.flipX.",
7704
- requirement: 1 /* Required */,
7705
- schemaKey: "FlipX"
7706
- },
7707
- {
7708
- memberId: "system_ddd09f08-1656-4404-b36b-5570a4c01fcf",
7709
- memberKind: "bool",
7710
- defaultValue: false,
7711
- docsText: "Mirrors the sprite vertically about its own centre. Maps to SpriteRenderer.flipY.",
7712
- requirement: 1 /* Required */,
7713
- schemaKey: "FlipY"
7714
- },
7715
- {
7716
- memberId: "system_f2a8c86d-ace5-421b-9475-0f3f6f97b2a6",
7717
- memberKind: "enum",
7718
- defaultValue: ["system_9d607a4f-60c3-4347-94fc-f24b538bf468"],
7719
- docsText: "How this sprite reacts to sprite masks. Maps to SpriteRenderer.maskInteraction. The web canvas has no real sprite mask, so anything other than None previews as a distinguishable treatment rather than as the mask itself \u2014 only Unity renders the real thing.",
7720
- enumId: "system_4e6c4d6f-1d0b-402a-ad3a-be92242dceec",
7721
- requirement: 1 /* Required */,
7722
- schemaKey: "MaskInteraction"
7723
- },
7724
- {
7725
- memberId: "system_6f32f1f2-83ea-42fc-8647-34ed0946b7f1",
7726
- memberKind: "int",
7727
- defaultValue: null,
7728
- docsText: "Added to the object layer's sorting order; it does not replace it. The result competes with every renderer in the sorting layer, or in the enclosing sorting group, and among equal orders the renderer lower on screen draws in front. Leave unset to use the layer's order.",
7729
- minValue: -32768,
7730
- maxValue: 32767,
7731
- schemaKey: "SortingOrder"
7732
- }
7733
- ],
7734
- worldKind: "spriteObject"
7735
- },
7736
7678
  {
7737
7679
  classId: "system_ccc3330c-2db5-44dc-9c8e-5ebfe430dec9",
7738
7680
  name: "NeoPlacementTile",
@@ -7811,6 +7753,7 @@ var init_world_system_classes_generated = __esm({
7811
7753
  memberId: "system_5a9ca1f5-a21b-4d4e-8c55-00341af594b4",
7812
7754
  memberKind: "list",
7813
7755
  defaultValue: [],
7756
+ docsText: "The cells this object occupies, as offsets from its placement cell. An empty list occupies nothing: the object blocks no placement and answers no cell query, but a placed object still has a Cell.",
7814
7757
  entryMemberId: "system_96c7650a-1805-5b27-ae99-d1e49d3cb207",
7815
7758
  requirement: 1 /* Required */,
7816
7759
  schemaKey: "PlacementTiles"
@@ -7995,6 +7938,64 @@ var init_world_system_classes_generated = __esm({
7995
7938
  ],
7996
7939
  worldKind: "object"
7997
7940
  },
7941
+ {
7942
+ classId: "system_d48b66ab-4d59-47e7-a25a-591fe97062de",
7943
+ name: "NeoSpriteObject",
7944
+ extendsWorldKind: "object",
7945
+ schemaFields: [
7946
+ {
7947
+ memberId: "system_441cb790-a45f-4488-a5a9-6f375af6c369",
7948
+ memberKind: "string",
7949
+ defaultValue: "",
7950
+ format: 1 /* Plain */,
7951
+ distribution: 1 /* Packed */,
7952
+ requirement: 1 /* Required */,
7953
+ schemaKey: "Name"
7954
+ },
7955
+ {
7956
+ memberId: "system_e9288ba9-f5a2-4485-8443-6afb155b31e0",
7957
+ memberKind: "sprite",
7958
+ defaultValue: { fileId: "", sliceIndex: 0 },
7959
+ requirement: 1 /* Required */,
7960
+ schemaKey: "Sprite"
7961
+ },
7962
+ {
7963
+ memberId: "system_9fcab37a-9743-4e35-8eee-80cb560f1433",
7964
+ memberKind: "bool",
7965
+ defaultValue: false,
7966
+ docsText: "Mirrors the sprite horizontally about its own centre. Maps to SpriteRenderer.flipX.",
7967
+ requirement: 1 /* Required */,
7968
+ schemaKey: "FlipX"
7969
+ },
7970
+ {
7971
+ memberId: "system_ddd09f08-1656-4404-b36b-5570a4c01fcf",
7972
+ memberKind: "bool",
7973
+ defaultValue: false,
7974
+ docsText: "Mirrors the sprite vertically about its own centre. Maps to SpriteRenderer.flipY.",
7975
+ requirement: 1 /* Required */,
7976
+ schemaKey: "FlipY"
7977
+ },
7978
+ {
7979
+ memberId: "system_f2a8c86d-ace5-421b-9475-0f3f6f97b2a6",
7980
+ memberKind: "enum",
7981
+ defaultValue: ["system_9d607a4f-60c3-4347-94fc-f24b538bf468"],
7982
+ docsText: "How this sprite reacts to sprite masks. Maps to SpriteRenderer.maskInteraction. The web canvas has no real sprite mask, so anything other than None previews as a distinguishable treatment rather than as the mask itself \u2014 only Unity renders the real thing.",
7983
+ enumId: "system_4e6c4d6f-1d0b-402a-ad3a-be92242dceec",
7984
+ requirement: 1 /* Required */,
7985
+ schemaKey: "MaskInteraction"
7986
+ },
7987
+ {
7988
+ memberId: "system_6f32f1f2-83ea-42fc-8647-34ed0946b7f1",
7989
+ memberKind: "int",
7990
+ defaultValue: null,
7991
+ docsText: "Added to the object layer's sorting order; it does not replace it. The result competes with every renderer in the sorting layer, or in the enclosing sorting group, and among equal orders the renderer lower on screen draws in front. Leave unset to use the layer's order.",
7992
+ minValue: -32768,
7993
+ maxValue: 32767,
7994
+ schemaKey: "SortingOrder"
7995
+ }
7996
+ ],
7997
+ worldKind: "spriteObject"
7998
+ },
7998
7999
  {
7999
8000
  classId: "system_9f34deed-2616-43c9-b614-d812da89ee51",
8000
8001
  name: "NeoSmartTile",
@@ -12545,11 +12546,7 @@ function completeDefaultClassRecord(args) {
12545
12546
  if (!shouldMaterializeChildDefaultForRoot(
12546
12547
  args.constructorRoot,
12547
12548
  resolvedChildMember,
12548
- defaultSettlesConstruction2,
12549
- documentHasInitValueContent(
12550
- args.document,
12551
- resolvedChildMember.defaultValue
12552
- )
12549
+ defaultSettlesConstruction2
12553
12550
  )) {
12554
12551
  continue;
12555
12552
  }
@@ -12977,11 +12974,6 @@ function shouldMaterializeChildDefault(member) {
12977
12974
  }
12978
12975
  return member.defaultValue !== void 0;
12979
12976
  }
12980
- function shouldMaterializeConstructorChildDefault(member, isInitializer = isInitValueContent(member.defaultValue)) {
12981
- if (isInitializer) return true;
12982
- if (!isRequiredMember(member)) return false;
12983
- return shouldMaterializeChildDefault(member);
12984
- }
12985
12977
  function skipProvidedConstructorSchemaKey(constructorRoot, schemaKey, member, defaultSettlesConstruction2, isInitializer = isInitValueContent(member.defaultValue)) {
12986
12978
  if (constructorRoot === void 0) return false;
12987
12979
  if (!constructorRoot.providedSchemaKeys.has(schemaKey)) return false;
@@ -12990,16 +12982,11 @@ function skipProvidedConstructorSchemaKey(constructorRoot, schemaKey, member, de
12990
12982
  }
12991
12983
  return !isInitializer && !defaultSettlesConstruction2;
12992
12984
  }
12993
- function shouldMaterializeChildDefaultForRoot(constructorRoot, member, defaultSettlesConstruction2, isInitializer = isInitValueContent(member.defaultValue)) {
12994
- if (constructorRoot === void 0)
12995
- return shouldMaterializeChildDefault(member);
12996
- if (constructorRoot.omitMissingRequired === true && !defaultSettlesConstruction2) {
12985
+ function shouldMaterializeChildDefaultForRoot(constructorRoot, member, defaultSettlesConstruction2) {
12986
+ if (constructorRoot?.omitMissingRequired === true && !defaultSettlesConstruction2) {
12997
12987
  return false;
12998
12988
  }
12999
- if (constructorRoot.runsMemberInitializers === true) {
13000
- return shouldMaterializeChildDefault(member);
13001
- }
13002
- return shouldMaterializeConstructorChildDefault(member, isInitializer);
12989
+ return shouldMaterializeChildDefault(member);
13003
12990
  }
13004
12991
  function primitiveFallbackValue(document, member) {
13005
12992
  if (isMemberBoolBase(member)) return { value: false };
@@ -23052,10 +23039,6 @@ function validateInternalRecordRelations(args) {
23052
23039
  const classesById = new Map(
23053
23040
  args.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
23054
23041
  );
23055
- const worldKindsByClassId = indexWorldSystemClassKinds(
23056
- args.classes,
23057
- classesById
23058
- );
23059
23042
  const relationIds = /* @__PURE__ */ new Set();
23060
23043
  const edgeKeys = /* @__PURE__ */ new Set();
23061
23044
  const orderedKeys2 = /* @__PURE__ */ new Set();
@@ -23119,16 +23102,14 @@ function validateInternalRecordRelations(args) {
23119
23102
  contract,
23120
23103
  endpoint: "source",
23121
23104
  recordEndpoint: source,
23122
- classesById,
23123
- worldKindsByClassId
23105
+ classesById
23124
23106
  });
23125
23107
  validateWorldEndpoint({
23126
23108
  relation,
23127
23109
  contract,
23128
23110
  endpoint: "target",
23129
23111
  recordEndpoint: target,
23130
- classesById,
23131
- worldKindsByClassId
23112
+ classesById
23132
23113
  });
23133
23114
  const edgeKey = [
23134
23115
  relation.relationKind,
@@ -23439,8 +23420,7 @@ function validateWorldEndpoint(args) {
23439
23420
  `Internal record relation "${args.relation.id}" ${args.endpoint} ${classLabel} "${classId}" does not exist.`
23440
23421
  );
23441
23422
  }
23442
- const actualWorldKind = args.worldKindsByClassId.get(schemaClass2.id) ?? null;
23443
- if (actualWorldKind !== requiredWorldKind) {
23423
+ if (!classInheritsWorldKind(schemaClass2.id, requiredWorldKind, args.classesById)) {
23444
23424
  throw new Error(
23445
23425
  `Internal record relation "${args.relation.id}" ${args.endpoint} ${classLabel} "${schemaClass2.id}" must extend world class kind "${requiredWorldKind}".`
23446
23426
  );
@@ -54544,7 +54524,7 @@ var init_registry = __esm({
54544
54524
  "../packages/manifest/schema-contract/registry.mjs"() {
54545
54525
  "use strict";
54546
54526
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
54547
- cliVersion: "0.80.0",
54527
+ cliVersion: "0.81.0",
54548
54528
  projectFileUploadBatchSize: 32,
54549
54529
  documentRecords: {
54550
54530
  member: {
@@ -75128,7 +75108,11 @@ function buildIndex(source) {
75128
75108
  }
75129
75109
  const placement = {
75130
75110
  valueId,
75131
- isNeoObject: kinds.get(row.classId) === NeoWorldSystemClassKind.Object,
75111
+ isNeoObject: classInheritsWorldKind(
75112
+ row.classId,
75113
+ NeoWorldSystemClassKind.Object,
75114
+ relations.classesById
75115
+ ),
75132
75116
  classId: row.classId,
75133
75117
  gridId: root.id,
75134
75118
  layerId,
@@ -114839,11 +114823,14 @@ function optionalNonEmptyString(value) {
114839
114823
  return typeof value === "string" && value.length > 0 ? value : null;
114840
114824
  }
114841
114825
  function consumeWorldPlacementSidecarKeys(args) {
114842
- const worldKind = args.worldKindsByClassId === void 0 ? resolveWorldSystemClassKind(args.classId, args.classes) : args.worldKindsByClassId.get(args.classId) ?? null;
114843
- if (worldKind === null) return /* @__PURE__ */ new Set();
114844
- const assetKind = WORLD_PLACEMENT_ASSET_KIND.get(worldKind);
114845
- if (assetKind === void 0) return /* @__PURE__ */ new Set();
114846
114826
  const classesById = args.classesById ?? new Map(args.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2]));
114827
+ if (!classInheritsWorldKind(
114828
+ args.classId,
114829
+ NeoWorldSystemClassKind.Object,
114830
+ classesById
114831
+ )) {
114832
+ return /* @__PURE__ */ new Set();
114833
+ }
114847
114834
  const present = /* @__PURE__ */ new Set();
114848
114835
  for (const key of WORLD_PLACEMENT_SIDECAR_KEYS) {
114849
114836
  if (!Object.hasOwn(args.body, key)) continue;
@@ -114860,13 +114847,13 @@ function consumeWorldPlacementSidecarKeys(args) {
114860
114847
  classId: assetClassId,
114861
114848
  worldKindsByClassId: args.worldKindsByClassId ?? indexWorldSystemClassKinds(args.classes, classesById),
114862
114849
  classesById,
114863
- expectedKind: assetKind,
114850
+ expectedKind: NeoWorldSystemClassKind.Object,
114864
114851
  label: `${args.label} assetClassId`
114865
114852
  });
114866
114853
  }
114867
114854
  return present;
114868
114855
  }
114869
- var WORLD_PLACEMENT_SIDECAR_KEYS, TILE_CLASS_LEVEL_KEYS, WORLD_PLACEMENT_ASSET_KIND;
114856
+ var WORLD_PLACEMENT_SIDECAR_KEYS, TILE_CLASS_LEVEL_KEYS;
114870
114857
  var init_world_content_sidecar_validation = __esm({
114871
114858
  "../src/models/project/world-content-sidecar-validation.ts"() {
114872
114859
  "use strict";
@@ -114891,7 +114878,6 @@ var init_world_content_sidecar_validation = __esm({
114891
114878
  ).flatMap(
114892
114879
  (field) => field.mutability === 1 /* ReadOnly */ ? [field.schemaKey] : []
114893
114880
  );
114894
- WORLD_PLACEMENT_ASSET_KIND = /* @__PURE__ */ new Map([[NeoWorldSystemClassKind.Object, NeoWorldSystemClassKind.Object]]);
114895
114881
  }
114896
114882
  });
114897
114883
 
@@ -128147,7 +128133,11 @@ function assertVariantMemberTargetValid(args) {
128147
128133
  `${label} targets class "${target.classId}", which is not in this project.`
128148
128134
  );
128149
128135
  }
128150
- if (resolveWorldKindFromClassMap(target.classId, classesById) !== NeoWorldSystemClassKind.Object) {
128136
+ if (!classInheritsWorldKind(
128137
+ target.classId,
128138
+ NeoWorldSystemClassKind.Object,
128139
+ classesById
128140
+ )) {
128151
128141
  throw new Error(
128152
128142
  `${label} targets class "${targetClass.name}", which does not derive from NeoObject. Only NeoObject-derived classes declare variants (P67 \xA71).`
128153
128143
  );
@@ -171787,7 +171777,7 @@ function classExtendsClass(ctx, classId, ancestorClassId) {
171787
171777
  function generateClassBackedWorldMembers(ctx, classDef, className) {
171788
171778
  if (isAbstractClass(classDef)) return [];
171789
171779
  const worldKind = ctx.worldKinds.get(classDef.id) ?? null;
171790
- if (worldKind === NeoWorldSystemClassKind.Tile || worldKind === NeoWorldSystemClassKind.Object) {
171780
+ if (worldKind === NeoWorldSystemClassKind.Tile || descendsFromWorldObject(ctx, classDef.id)) {
171791
171781
  return [
171792
171782
  `public static NeoClassRef<${className}> Definition { get; } = new NeoClassRef<${className}>("${escapeCSharpString(classDef.id)}");`
171793
171783
  ];
@@ -173537,9 +173527,10 @@ function objectSpawnHookClassMembers(classDef) {
173537
173527
  "",
173538
173528
  "/// <summary>",
173539
173529
  "/// Renderer spawn hook \u2014 override in a partial class to attach Unity",
173540
- "/// components (e.g. Rigidbody2D) to the instance's fully-built root",
173541
- `/// GameObject. See <see cref="${OBJECT_SPAWN_HOOKS_INTERFACE}"/> for timing and`,
173542
- "/// respawn semantics.",
173530
+ "/// components (e.g. Rigidbody2D) to this object's GameObject. Runs on",
173531
+ "/// the placed root and every object in its composition, parents first;",
173532
+ "/// check behaviour.IsRoot for the placed instance. See",
173533
+ `/// <see cref="${OBJECT_SPAWN_HOOKS_INTERFACE}"/> for timing and respawn semantics.`,
173543
173534
  "/// </summary>",
173544
173535
  "protected virtual void OnObjectSpawned(NeoObjectBehaviour behaviour)",
173545
173536
  "{",
@@ -173547,8 +173538,8 @@ function objectSpawnHookClassMembers(classDef) {
173547
173538
  "",
173548
173539
  "/// <summary>",
173549
173540
  "/// Renderer despawn hook \u2014 override in a partial class to release",
173550
- "/// per-GameObject state before the instance's root GameObject is",
173551
- "/// destroyed.",
173541
+ "/// per-GameObject state before this object's GameObject is destroyed.",
173542
+ "/// Children despawn before their parents.",
173552
173543
  "/// </summary>",
173553
173544
  "protected virtual void OnObjectDespawned(NeoObjectBehaviour behaviour)",
173554
173545
  "{",
@@ -181263,7 +181254,7 @@ var UNITY_CODEGEN_REVISION;
181263
181254
  var init_unity_codegen_revision = __esm({
181264
181255
  "../src/models/exports/unity-codegen-revision.ts"() {
181265
181256
  "use strict";
181266
- UNITY_CODEGEN_REVISION = "edfd4061dffcd1a747b234cd135b99beca6f4cf1958cb69715029c5935dd7f1b";
181257
+ UNITY_CODEGEN_REVISION = "d4026a3848848c8507d45dd54b6d31c1a0588b17b64c35e3fe9b25c89eb2fc05";
181267
181258
  }
181268
181259
  });
181269
181260
 
@@ -201083,7 +201074,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
201083
201074
  async function main() {
201084
201075
  const args = parseArgs(process.argv.slice(2));
201085
201076
  if (args.command === "--version") {
201086
- console.log("0.80.0");
201077
+ console.log("0.81.0");
201087
201078
  return;
201088
201079
  }
201089
201080
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
@@ -1013,11 +1013,11 @@ var NeoWorldSystemClassKind = {
1013
1013
  ObjectCollider: "objectCollider",
1014
1014
  SortingGroup: "sortingGroup",
1015
1015
  LayerGroupBase: "layerGroupBase",
1016
- SpriteObject: "spriteObject",
1017
1016
  PlacementTile: "placementTile",
1018
1017
  TileLayerLink: "tileLayerLink",
1019
1018
  ObjectLayerLink: "objectLayerLink",
1020
1019
  Object: "object",
1020
+ SpriteObject: "spriteObject",
1021
1021
  SmartTile: "smartTile",
1022
1022
  SmartTileRule: "smartTileRule",
1023
1023
  SmartTileNeighbor: "smartTileNeighbor",
@@ -7343,64 +7343,6 @@ var WORLD_SYSTEM_CLASS_DEFINITIONS = [
7343
7343
  modifier: 1 /* Abstract */,
7344
7344
  worldKind: "layerGroupBase"
7345
7345
  },
7346
- {
7347
- classId: "system_d48b66ab-4d59-47e7-a25a-591fe97062de",
7348
- name: "NeoSpriteObject",
7349
- extendsWorldKind: "objectBase",
7350
- schemaFields: [
7351
- {
7352
- memberId: "system_441cb790-a45f-4488-a5a9-6f375af6c369",
7353
- memberKind: "string",
7354
- defaultValue: "",
7355
- format: 1 /* Plain */,
7356
- distribution: 1 /* Packed */,
7357
- requirement: 1 /* Required */,
7358
- schemaKey: "Name"
7359
- },
7360
- {
7361
- memberId: "system_e9288ba9-f5a2-4485-8443-6afb155b31e0",
7362
- memberKind: "sprite",
7363
- defaultValue: { fileId: "", sliceIndex: 0 },
7364
- requirement: 1 /* Required */,
7365
- schemaKey: "Sprite"
7366
- },
7367
- {
7368
- memberId: "system_9fcab37a-9743-4e35-8eee-80cb560f1433",
7369
- memberKind: "bool",
7370
- defaultValue: false,
7371
- docsText: "Mirrors the sprite horizontally about its own centre. Maps to SpriteRenderer.flipX.",
7372
- requirement: 1 /* Required */,
7373
- schemaKey: "FlipX"
7374
- },
7375
- {
7376
- memberId: "system_ddd09f08-1656-4404-b36b-5570a4c01fcf",
7377
- memberKind: "bool",
7378
- defaultValue: false,
7379
- docsText: "Mirrors the sprite vertically about its own centre. Maps to SpriteRenderer.flipY.",
7380
- requirement: 1 /* Required */,
7381
- schemaKey: "FlipY"
7382
- },
7383
- {
7384
- memberId: "system_f2a8c86d-ace5-421b-9475-0f3f6f97b2a6",
7385
- memberKind: "enum",
7386
- defaultValue: ["system_9d607a4f-60c3-4347-94fc-f24b538bf468"],
7387
- docsText: "How this sprite reacts to sprite masks. Maps to SpriteRenderer.maskInteraction. The web canvas has no real sprite mask, so anything other than None previews as a distinguishable treatment rather than as the mask itself \u2014 only Unity renders the real thing.",
7388
- enumId: "system_4e6c4d6f-1d0b-402a-ad3a-be92242dceec",
7389
- requirement: 1 /* Required */,
7390
- schemaKey: "MaskInteraction"
7391
- },
7392
- {
7393
- memberId: "system_6f32f1f2-83ea-42fc-8647-34ed0946b7f1",
7394
- memberKind: "int",
7395
- defaultValue: null,
7396
- docsText: "Added to the object layer's sorting order; it does not replace it. The result competes with every renderer in the sorting layer, or in the enclosing sorting group, and among equal orders the renderer lower on screen draws in front. Leave unset to use the layer's order.",
7397
- minValue: -32768,
7398
- maxValue: 32767,
7399
- schemaKey: "SortingOrder"
7400
- }
7401
- ],
7402
- worldKind: "spriteObject"
7403
- },
7404
7346
  {
7405
7347
  classId: "system_ccc3330c-2db5-44dc-9c8e-5ebfe430dec9",
7406
7348
  name: "NeoPlacementTile",
@@ -7479,6 +7421,7 @@ var WORLD_SYSTEM_CLASS_DEFINITIONS = [
7479
7421
  memberId: "system_5a9ca1f5-a21b-4d4e-8c55-00341af594b4",
7480
7422
  memberKind: "list",
7481
7423
  defaultValue: [],
7424
+ docsText: "The cells this object occupies, as offsets from its placement cell. An empty list occupies nothing: the object blocks no placement and answers no cell query, but a placed object still has a Cell.",
7482
7425
  entryMemberId: "system_96c7650a-1805-5b27-ae99-d1e49d3cb207",
7483
7426
  requirement: 1 /* Required */,
7484
7427
  schemaKey: "PlacementTiles"
@@ -7663,6 +7606,64 @@ var WORLD_SYSTEM_CLASS_DEFINITIONS = [
7663
7606
  ],
7664
7607
  worldKind: "object"
7665
7608
  },
7609
+ {
7610
+ classId: "system_d48b66ab-4d59-47e7-a25a-591fe97062de",
7611
+ name: "NeoSpriteObject",
7612
+ extendsWorldKind: "object",
7613
+ schemaFields: [
7614
+ {
7615
+ memberId: "system_441cb790-a45f-4488-a5a9-6f375af6c369",
7616
+ memberKind: "string",
7617
+ defaultValue: "",
7618
+ format: 1 /* Plain */,
7619
+ distribution: 1 /* Packed */,
7620
+ requirement: 1 /* Required */,
7621
+ schemaKey: "Name"
7622
+ },
7623
+ {
7624
+ memberId: "system_e9288ba9-f5a2-4485-8443-6afb155b31e0",
7625
+ memberKind: "sprite",
7626
+ defaultValue: { fileId: "", sliceIndex: 0 },
7627
+ requirement: 1 /* Required */,
7628
+ schemaKey: "Sprite"
7629
+ },
7630
+ {
7631
+ memberId: "system_9fcab37a-9743-4e35-8eee-80cb560f1433",
7632
+ memberKind: "bool",
7633
+ defaultValue: false,
7634
+ docsText: "Mirrors the sprite horizontally about its own centre. Maps to SpriteRenderer.flipX.",
7635
+ requirement: 1 /* Required */,
7636
+ schemaKey: "FlipX"
7637
+ },
7638
+ {
7639
+ memberId: "system_ddd09f08-1656-4404-b36b-5570a4c01fcf",
7640
+ memberKind: "bool",
7641
+ defaultValue: false,
7642
+ docsText: "Mirrors the sprite vertically about its own centre. Maps to SpriteRenderer.flipY.",
7643
+ requirement: 1 /* Required */,
7644
+ schemaKey: "FlipY"
7645
+ },
7646
+ {
7647
+ memberId: "system_f2a8c86d-ace5-421b-9475-0f3f6f97b2a6",
7648
+ memberKind: "enum",
7649
+ defaultValue: ["system_9d607a4f-60c3-4347-94fc-f24b538bf468"],
7650
+ docsText: "How this sprite reacts to sprite masks. Maps to SpriteRenderer.maskInteraction. The web canvas has no real sprite mask, so anything other than None previews as a distinguishable treatment rather than as the mask itself \u2014 only Unity renders the real thing.",
7651
+ enumId: "system_4e6c4d6f-1d0b-402a-ad3a-be92242dceec",
7652
+ requirement: 1 /* Required */,
7653
+ schemaKey: "MaskInteraction"
7654
+ },
7655
+ {
7656
+ memberId: "system_6f32f1f2-83ea-42fc-8647-34ed0946b7f1",
7657
+ memberKind: "int",
7658
+ defaultValue: null,
7659
+ docsText: "Added to the object layer's sorting order; it does not replace it. The result competes with every renderer in the sorting layer, or in the enclosing sorting group, and among equal orders the renderer lower on screen draws in front. Leave unset to use the layer's order.",
7660
+ minValue: -32768,
7661
+ maxValue: 32767,
7662
+ schemaKey: "SortingOrder"
7663
+ }
7664
+ ],
7665
+ worldKind: "spriteObject"
7666
+ },
7666
7667
  {
7667
7668
  classId: "system_9f34deed-2616-43c9-b614-d812da89ee51",
7668
7669
  name: "NeoSmartTile",
@@ -11959,11 +11960,7 @@ function completeDefaultClassRecord(args) {
11959
11960
  if (!shouldMaterializeChildDefaultForRoot(
11960
11961
  args.constructorRoot,
11961
11962
  resolvedChildMember,
11962
- defaultSettlesConstruction2,
11963
- documentHasInitValueContent(
11964
- args.document,
11965
- resolvedChildMember.defaultValue
11966
- )
11963
+ defaultSettlesConstruction2
11967
11964
  )) {
11968
11965
  continue;
11969
11966
  }
@@ -12391,11 +12388,6 @@ function shouldMaterializeChildDefault(member) {
12391
12388
  }
12392
12389
  return member.defaultValue !== void 0;
12393
12390
  }
12394
- function shouldMaterializeConstructorChildDefault(member, isInitializer = isInitValueContent(member.defaultValue)) {
12395
- if (isInitializer) return true;
12396
- if (!isRequiredMember(member)) return false;
12397
- return shouldMaterializeChildDefault(member);
12398
- }
12399
12391
  function skipProvidedConstructorSchemaKey(constructorRoot, schemaKey, member, defaultSettlesConstruction2, isInitializer = isInitValueContent(member.defaultValue)) {
12400
12392
  if (constructorRoot === void 0) return false;
12401
12393
  if (!constructorRoot.providedSchemaKeys.has(schemaKey)) return false;
@@ -12404,16 +12396,11 @@ function skipProvidedConstructorSchemaKey(constructorRoot, schemaKey, member, de
12404
12396
  }
12405
12397
  return !isInitializer && !defaultSettlesConstruction2;
12406
12398
  }
12407
- function shouldMaterializeChildDefaultForRoot(constructorRoot, member, defaultSettlesConstruction2, isInitializer = isInitValueContent(member.defaultValue)) {
12408
- if (constructorRoot === void 0)
12409
- return shouldMaterializeChildDefault(member);
12410
- if (constructorRoot.omitMissingRequired === true && !defaultSettlesConstruction2) {
12399
+ function shouldMaterializeChildDefaultForRoot(constructorRoot, member, defaultSettlesConstruction2) {
12400
+ if (constructorRoot?.omitMissingRequired === true && !defaultSettlesConstruction2) {
12411
12401
  return false;
12412
12402
  }
12413
- if (constructorRoot.runsMemberInitializers === true) {
12414
- return shouldMaterializeChildDefault(member);
12415
- }
12416
- return shouldMaterializeConstructorChildDefault(member, isInitializer);
12403
+ return shouldMaterializeChildDefault(member);
12417
12404
  }
12418
12405
  function primitiveFallbackValue(document2, member) {
12419
12406
  if (isMemberBoolBase(member)) return { value: false };
@@ -16249,7 +16236,11 @@ function buildIndex(source) {
16249
16236
  }
16250
16237
  const placement = {
16251
16238
  valueId,
16252
- isNeoObject: kinds.get(row.classId) === NeoWorldSystemClassKind.Object,
16239
+ isNeoObject: classInheritsWorldKind(
16240
+ row.classId,
16241
+ NeoWorldSystemClassKind.Object,
16242
+ relations.classesById
16243
+ ),
16253
16244
  classId: row.classId,
16254
16245
  gridId: root.id,
16255
16246
  layerId,
@@ -53768,7 +53759,6 @@ var TILE_CLASS_LEVEL_KEYS = worldSystemSchemaFieldsForKind(
53768
53759
  ).flatMap(
53769
53760
  (field) => field.mutability === 1 /* ReadOnly */ ? [field.schemaKey] : []
53770
53761
  );
53771
- var WORLD_PLACEMENT_ASSET_KIND = /* @__PURE__ */ new Map([[NeoWorldSystemClassKind.Object, NeoWorldSystemClassKind.Object]]);
53772
53762
 
53773
53763
  // ../src/database/general-function-call-ir-source-recompile.ts
53774
53764
  var VOID_ACTION_TYPE_INFO = {
@@ -58806,7 +58796,7 @@ var INITIALIZER_KEY_PLACEHOLDER = new RegExp(
58806
58796
 
58807
58797
  // ../packages/manifest/schema-contract/registry.mjs
58808
58798
  var PROJECT_SCHEMA_CONTRACT = Object.freeze({
58809
- cliVersion: "0.80.0",
58799
+ cliVersion: "0.81.0",
58810
58800
  projectFileUploadBatchSize: 32,
58811
58801
  documentRecords: {
58812
58802
  member: {
@@ -60647,7 +60637,7 @@ var SCRIPT_COLLECTION_READERS = {
60647
60637
  };
60648
60638
 
60649
60639
  // ../src/models/exports/unity-codegen-revision.ts
60650
- var UNITY_CODEGEN_REVISION = "edfd4061dffcd1a747b234cd135b99beca6f4cf1958cb69715029c5935dd7f1b";
60640
+ var UNITY_CODEGEN_REVISION = "d4026a3848848c8507d45dd54b6d31c1a0588b17b64c35e3fe9b25c89eb2fc05";
60651
60641
 
60652
60642
  // src/export-cache.ts
60653
60643
  var CACHE_BUILD = JSON.stringify([
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.80.0",
3
+ "version": "0.81.0",
4
4
  "description": "Neo Compose native project-source CLI with bidirectional sync.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -9,7 +9,7 @@ description: >-
9
9
  `@neocompose/cli` or `node cli/bin/neo.mjs` in the neo-compose repository.
10
10
  ---
11
11
 
12
- <!-- reviewed-through-cli: 0.80.0 -->
12
+ <!-- reviewed-through-cli: 0.81.0 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -95,7 +95,12 @@ Object `PlacementTiles` is a `List<NeoPlacementTile>`. Each entry marks a
95
95
  footprint cell with its own `Cell` member. It is independent of `NeoTile`. Rendered
96
96
  tile classes do not belong in this list. An object with no placement tiles
97
97
  occupies no cells. It doesn't block other placements, and cell queries don't
98
- return it.
98
+ return it. A placed object with no tiles still has a `Cell`.
99
+
100
+ `NeoSpriteObject` extends `NeoObject`. Place a sprite class like any object,
101
+ give it `Children`, and override `OnObjectSpawned`/`OnObjectDespawned` on it.
102
+ Hooks fire on every object in a placed hierarchy, parent first; despawn runs
103
+ children first. `NeoObjectBehaviour.IsRoot` is true only on the placed root.
99
104
 
100
105
  Convert a writable placement without changing its row identity or cell:
101
106
 
@@ -129,7 +129,7 @@ wrappers.
129
129
  The marker near the top of `SKILL.md` must exactly match the package version:
130
130
 
131
131
  ```html
132
- <!-- reviewed-through-cli: 0.80.0 -->
132
+ <!-- reviewed-through-cli: 0.81.0 -->
133
133
  ```
134
134
 
135
135
  The quoted version above is checked too, so this instruction cannot go stale
@@ -163,6 +163,10 @@ A static field that names another static copies a value, as in
163
163
  `public static int B = Holder.A;`. A class, List, Set, or Dictionary static
164
164
  already owns its value, so call `Clone()` or use `Reference`. A static delegate cannot copy another Class's delegate field,
165
165
  because its closure compiles in its own Class; wrap it as `() => Other.Call()`.
166
+ Omitted constructor fields use their authored defaults, including optional fields.
167
+ Writable collection defaults belong to each instance; mutations persist on later
168
+ reads without changing another instance's default. Fields without defaults remain
169
+ absent, and `null` arguments in generated member-wise constructors mean omission.
166
170
  Collection type arguments in constructions, such as `new Box<List<int>>([1, 2])`,
167
171
  work even when no field declares that collection type. Preparation includes the
168
172
  needed type descriptors; spec-only types remain in the test candidate.