Ext.StructuralMetadataRoot.cs 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.Linq;
  5. using DATATYPE = SharpGLTF.Schema2.Tiles3D.DataType;
  6. using ELEMENTTYPE = SharpGLTF.Schema2.Tiles3D.ElementType;
  7. namespace SharpGLTF.Schema2
  8. {
  9. using Collections;
  10. using Memory;
  11. using Validation;
  12. using Tiles3D;
  13. using System.Numerics;
  14. using System.Text.Json.Nodes;
  15. using System.ComponentModel;
  16. partial class Tiles3DExtensions
  17. {
  18. public static EXTStructuralMetadataRoot UseStructuralMetadata(this ModelRoot modelRoot)
  19. {
  20. return modelRoot.UseExtension<EXTStructuralMetadataRoot>();
  21. }
  22. }
  23. namespace Tiles3D
  24. {
  25. /// <remarks>
  26. /// Use <see cref="Tiles3DExtensions.UseStructuralMetadata(ModelRoot)"/> to create an instance of this class.
  27. /// </remarks>
  28. public partial class EXTStructuralMetadataRoot
  29. {
  30. #region lifecycle
  31. internal EXTStructuralMetadataRoot(ModelRoot modelRoot)
  32. {
  33. this.LogicalParent = modelRoot;
  34. _propertyTables = new ChildrenList<PropertyTable, EXTStructuralMetadataRoot>(this);
  35. _propertyAttributes = new ChildrenList<PropertyAttribute, EXTStructuralMetadataRoot>(this);
  36. _propertyTextures = new ChildrenList<PropertyTexture, EXTStructuralMetadataRoot>(this);
  37. }
  38. protected override IEnumerable<ExtraProperties> GetLogicalChildren()
  39. {
  40. var items = base.GetLogicalChildren()
  41. .Concat(_propertyTables)
  42. .Concat(_propertyAttributes)
  43. .Concat(_propertyTextures);
  44. if (Schema != null) items = items.Append(Schema);
  45. return items;
  46. }
  47. #endregion
  48. #region data
  49. public ModelRoot LogicalParent { get; }
  50. #endregion
  51. #region properties
  52. /**
  53. internal string SchemaUri
  54. {
  55. get => _schemaUri;
  56. set { _schemaUri = value; }
  57. }
  58. */
  59. internal StructuralMetadataSchema Schema
  60. {
  61. get => _schema;
  62. set { GetChildSetter(this).SetProperty(ref _schema, value); }
  63. }
  64. internal IReadOnlyList<PropertyTable> PropertyTables => _propertyTables;
  65. internal IReadOnlyList<PropertyAttribute> PropertyAttributes => _propertyAttributes;
  66. internal IReadOnlyList<PropertyTexture> PropertyTextures => _propertyTextures;
  67. #endregion
  68. #region API
  69. public bool TryGetEmbeddedSchema(out StructuralMetadataSchema schema)
  70. {
  71. if (_schema != null) { schema = _schema; return true; }
  72. schema = null;
  73. return false;
  74. }
  75. public StructuralMetadataSchema UseEmbeddedSchema(string id)
  76. {
  77. var schema = UseEmbeddedSchema();
  78. schema.Id = id;
  79. return schema;
  80. }
  81. /**
  82. // Sets the schema to use an external schema, returns an empty schema to used for adding schema properties
  83. public StructuralMetadataSchema UseExternalSchema(Uri uri)
  84. {
  85. SchemaUri = uri.ToString();
  86. return new StructuralMetadataSchema();
  87. }
  88. */
  89. public StructuralMetadataSchema UseEmbeddedSchema()
  90. {
  91. // SchemaUri = null;
  92. if (_schema == null) GetChildSetter(this).SetProperty(ref _schema, new StructuralMetadataSchema());
  93. return _schema;
  94. }
  95. public PropertyAttribute AddPropertyAttribute(StructuralMetadataClass schemaClass)
  96. {
  97. var prop = AddPropertyAttribute();
  98. prop.ClassInstance = schemaClass;
  99. return prop;
  100. }
  101. public PropertyAttribute AddPropertyAttribute()
  102. {
  103. var prop = new PropertyAttribute();
  104. _propertyAttributes.Add(prop);
  105. return prop;
  106. }
  107. public PropertyTable AddPropertyTable(StructuralMetadataClass schemaClass, int featureCount, string name = null)
  108. {
  109. var table = AddPropertyTable();
  110. table.ClassInstance = schemaClass;
  111. table.Count = featureCount;
  112. table.Name = name;
  113. return table;
  114. }
  115. private PropertyTable AddPropertyTable()
  116. {
  117. var prop = new PropertyTable();
  118. _propertyTables.Add(prop);
  119. return prop;
  120. }
  121. public PropertyTexture AddPropertyTexture(StructuralMetadataClass schemaClass)
  122. {
  123. var prop = AddPropertyTexture();
  124. prop.ClassInstance = schemaClass;
  125. return prop;
  126. }
  127. public PropertyTexture AddPropertyTexture()
  128. {
  129. var prop = new PropertyTexture();
  130. _propertyTextures.Add(prop);
  131. return prop;
  132. }
  133. #endregion
  134. #region validation
  135. protected override void OnValidateReferences(ValidationContext validate)
  136. {
  137. var root = LogicalParent.GetExtension<EXTStructuralMetadataRoot>();
  138. Guard.MustBeNull(root._schemaUri, nameof(root._schemaUri),
  139. "SchemaUri must be null, use embedded achema to set the schema");
  140. // Guard schema is null
  141. Guard.NotNull(Schema, nameof(Schema), "Schema must be defined");
  142. foreach (var propertyTexture in PropertyTextures)
  143. {
  144. foreach (var propertyTextureProperty in propertyTexture.Properties)
  145. {
  146. var textureId = propertyTextureProperty.Value.LogicalTextureIndex;
  147. validate.IsNullOrIndex(nameof(propertyTexture), textureId, LogicalParent.LogicalTextures);
  148. }
  149. }
  150. foreach (var propertyTable in PropertyTables)
  151. {
  152. Guard.NotNull(Schema.Classes[propertyTable.ClassName], nameof(propertyTable.ClassName), $"Schema must have class {propertyTable.ClassName}");
  153. foreach (var property in propertyTable.Properties)
  154. {
  155. Guard.NotNull(Schema.Classes[propertyTable.ClassName].Properties[property.Key], nameof(property.Key), $"Schema must have property {property.Key}");
  156. var values = property.Value.Values;
  157. validate.IsNullOrIndex(nameof(propertyTable), values, LogicalParent.LogicalBufferViews);
  158. if (property.Value.ArrayOffsets.HasValue)
  159. {
  160. var arrayOffsets = property.Value.ArrayOffsets.Value;
  161. validate.IsNullOrIndex(nameof(propertyTable), arrayOffsets, LogicalParent.LogicalBufferViews);
  162. }
  163. if (property.Value.StringOffsets.HasValue)
  164. {
  165. var stringOffsets = property.Value.StringOffsets.Value;
  166. validate.IsNullOrIndex(nameof(propertyTable), stringOffsets, LogicalParent.LogicalBufferViews);
  167. }
  168. }
  169. }
  170. if (Schema != null)
  171. {
  172. foreach (var @class in Schema.Classes)
  173. {
  174. foreach (var property in @class.Value.Properties)
  175. {
  176. if (property.Value.Type == ELEMENTTYPE.ENUM)
  177. {
  178. Guard.IsTrue(Schema.Enums.ContainsKey(property.Value.EnumType), nameof(property.Value.EnumType), $"Enum {property.Value.EnumType} must be defined in schema");
  179. }
  180. }
  181. }
  182. }
  183. base.OnValidateReferences(validate);
  184. }
  185. protected override void OnValidateContent(ValidationContext result)
  186. {
  187. // check schema id is defined and valid
  188. if (Schema != null && !String.IsNullOrEmpty(Schema.Id))
  189. {
  190. var regex = "^[a-zA-Z_][a-zA-Z0-9_]*$";
  191. Guard.IsTrue(System.Text.RegularExpressions.Regex.IsMatch(Schema.Id, regex), nameof(Schema.Id));
  192. foreach (var _class in Schema.Classes)
  193. {
  194. Guard.IsTrue(System.Text.RegularExpressions.Regex.IsMatch(_class.Key, regex), nameof(_class.Key));
  195. foreach (var property in _class.Value.Properties)
  196. {
  197. if (property.Value.Count.HasValue)
  198. {
  199. Guard.MustBeGreaterThanOrEqualTo(property.Value.Count.Value, 2, nameof(property.Value.Count));
  200. }
  201. if (property.Value.Required)
  202. {
  203. Guard.IsTrue(property.Value.NoData == null, nameof(property.Value.NoData), $"The property '{property.Key}' defines a 'noData' value, but is 'required'");
  204. }
  205. if(property.Value.Type == ELEMENTTYPE.SCALAR)
  206. {
  207. // check The 'componentType' must be defined for a property with type 'SCALAR'
  208. Guard.IsTrue(property.Value.ComponentType.HasValue, nameof(property.Value.ComponentType), $"The 'componentType' must be defined for a property '{property.Key}' with type 'SCALAR'");
  209. }
  210. }
  211. }
  212. }
  213. foreach (var propertyTexture in PropertyTextures)
  214. {
  215. foreach (var propertyTextureProperty in propertyTexture.Properties)
  216. {
  217. var texCoord = propertyTextureProperty.Value.TextureCoordinate;
  218. var channels = propertyTextureProperty.Value.Channels;
  219. var index = propertyTextureProperty.Value.LogicalTextureIndex;
  220. Guard.MustBeGreaterThanOrEqualTo(texCoord, 0, nameof(texCoord));
  221. Guard.IsTrue(channels.Count > 0, nameof(channels), "Channels must be defined");
  222. Guard.IsTrue(index >= 0, nameof(index), "Index must be defined");
  223. }
  224. }
  225. foreach (var propertyTable in PropertyTables)
  226. {
  227. Guard.IsTrue(propertyTable.ClassName != null, nameof(propertyTable.ClassName), "Class must be defined");
  228. Guard.IsTrue(propertyTable.Count > 0, nameof(propertyTable.Count), "Count must be greater than 0");
  229. Guard.IsTrue(propertyTable.Properties.Count > 0, nameof(propertyTable.Properties), "Properties must be defined");
  230. }
  231. // Check one of schema or schemaUri is defined, but not both
  232. // Guard.IsFalse(Schema != null && SchemaUri != null, "Schema/SchemaUri", "Schema and SchemaUri cannot both be defined");
  233. // Guard.IsFalse(Schema == null && SchemaUri == null, "Schema/SchemaUri", "One of Schema and SchemaUri must be defined");
  234. base.OnValidateContent(result);
  235. }
  236. #endregion
  237. }
  238. #region structural properties
  239. /// <remarks>
  240. /// Use <see cref="EXTStructuralMetadataRoot.AddPropertyTexture"/> to create an instance of this class.
  241. /// </remarks>
  242. public partial class PropertyTexture : IChildOfList<EXTStructuralMetadataRoot>
  243. {
  244. #region lifecycle
  245. public PropertyTexture()
  246. {
  247. _properties = new ChildrenDictionary<PropertyTextureProperty, PropertyTexture>(this);
  248. }
  249. protected override IEnumerable<ExtraProperties> GetLogicalChildren()
  250. {
  251. return base.GetLogicalChildren()
  252. .Concat(_properties.Values);
  253. }
  254. #endregion
  255. #region child properties
  256. public int LogicalIndex { get; private set; } = -1;
  257. public EXTStructuralMetadataRoot LogicalParent { get; private set; }
  258. void IChildOfList<EXTStructuralMetadataRoot>.SetLogicalParent(EXTStructuralMetadataRoot parent, int index)
  259. {
  260. LogicalParent = parent;
  261. LogicalIndex = index;
  262. }
  263. #endregion
  264. #region properties
  265. public string ClassName
  266. {
  267. get => _class;
  268. set => _class = value;
  269. }
  270. public StructuralMetadataClass ClassInstance
  271. {
  272. get
  273. {
  274. if (string.IsNullOrEmpty(ClassName)) return null;
  275. var root = _GetModelRoot()?.GetExtension<EXTStructuralMetadataRoot>();
  276. if (root == null) return null;
  277. if (root.TryGetEmbeddedSchema(out var schema))
  278. {
  279. return schema.Classes[ClassName];
  280. }
  281. else return null;
  282. }
  283. set
  284. {
  285. // Todo: check value is part of this DOM
  286. ClassName = value?.LogicalKey;
  287. }
  288. }
  289. public IReadOnlyDictionary<string, PropertyTextureProperty> Properties => _properties;
  290. #endregion
  291. #region API
  292. private ModelRoot _GetModelRoot() => LogicalParent.LogicalParent;
  293. public PropertyTextureProperty CreateProperty(string key, Texture texture, IReadOnlyList<int> channels = null)
  294. {
  295. var property = CreateProperty(key);
  296. property.Texture = texture;
  297. if (channels != null) property.Channels = channels;
  298. return property;
  299. }
  300. private PropertyTextureProperty CreateProperty(string key)
  301. {
  302. var property = new PropertyTextureProperty();
  303. _properties[key] = property;
  304. return property;
  305. }
  306. #endregion
  307. }
  308. /// <remarks>
  309. /// Use <see cref="PropertyTexture.CreateProperty(string)"/> to create an instance of this class.
  310. /// </remarks>
  311. public partial class PropertyTextureProperty : IChildOfDictionary<PropertyTexture>
  312. {
  313. #region lifecycle
  314. public PropertyTextureProperty()
  315. {
  316. _channels = new List<int>();
  317. }
  318. #endregion
  319. #region child properties
  320. public string LogicalKey { get; private set; }
  321. public PropertyTexture LogicalParent { get; private set; }
  322. void IChildOfDictionary<PropertyTexture>.SetLogicalParent(PropertyTexture parent, string key)
  323. {
  324. LogicalParent = parent;
  325. LogicalKey = key;
  326. }
  327. #endregion
  328. #region data
  329. private ModelRoot _GetModelRoot() => LogicalParent.LogicalParent.LogicalParent;
  330. public IReadOnlyList<int> Channels
  331. {
  332. get => _channels;
  333. set
  334. {
  335. _channels.Clear();
  336. _channels.AddRange(value);
  337. }
  338. }
  339. public Schema2.Texture Texture
  340. {
  341. get => _GetModelRoot().LogicalTextures[LogicalTextureIndex];
  342. set
  343. {
  344. Guard.NotNull(value, nameof(value));
  345. Guard.MustShareLogicalParent(_GetModelRoot(), nameof(MeshExtMeshFeatureIDTexture), value, nameof(value));
  346. LogicalTextureIndex = value.LogicalIndex;
  347. }
  348. }
  349. #endregion
  350. }
  351. /// <remarks>
  352. /// Use <see cref="EXTStructuralMetadataRoot.AddPropertyAttribute"/> to create an instance of this class.
  353. /// </remarks>
  354. public partial class PropertyAttribute : IChildOfList<EXTStructuralMetadataRoot>
  355. {
  356. #region lifecycle
  357. public PropertyAttribute()
  358. {
  359. _properties = new ChildrenDictionary<PropertyAttributeProperty, PropertyAttribute>(this);
  360. }
  361. protected override IEnumerable<ExtraProperties> GetLogicalChildren()
  362. {
  363. return base.GetLogicalChildren()
  364. .Concat(_properties.Values);
  365. }
  366. #endregion
  367. #region child properties
  368. /// <summary>
  369. /// Gets the zero-based index of this <see cref="MeshExtInstanceFeatureID"/> at <see cref="MeshExtInstanceFeatures.FeatureIds"/>.
  370. /// </summary>
  371. public int LogicalIndex { get; private set; } = -1;
  372. /// <summary>
  373. /// Gets the <see cref="MeshExtInstanceFeatures"/> instance that owns this <see cref="MeshExtInstanceFeatureID"/> instance.
  374. /// </summary>
  375. public EXTStructuralMetadataRoot LogicalParent { get; private set; }
  376. void IChildOfList<EXTStructuralMetadataRoot>.SetLogicalParent(EXTStructuralMetadataRoot parent, int index)
  377. {
  378. LogicalParent = parent;
  379. LogicalIndex = index;
  380. }
  381. #endregion
  382. #region properties
  383. public string ClassName
  384. {
  385. get => _class;
  386. set => _class = value;
  387. }
  388. public StructuralMetadataClass ClassInstance
  389. {
  390. get
  391. {
  392. if (string.IsNullOrEmpty(ClassName)) return null;
  393. var root = _GetModelRoot()?.GetExtension<EXTStructuralMetadataRoot>();
  394. if (root == null) return null;
  395. if (root.TryGetEmbeddedSchema(out var schema))
  396. {
  397. return schema.Classes[ClassName];
  398. }
  399. else return null;
  400. }
  401. set
  402. {
  403. // Todo: check value is part of this DOM
  404. ClassName = value?.LogicalKey;
  405. }
  406. }
  407. public IReadOnlyDictionary<string, PropertyAttributeProperty> Properties => _properties;
  408. #endregion
  409. #region API
  410. private ModelRoot _GetModelRoot() => LogicalParent.LogicalParent;
  411. public PropertyAttributeProperty CreateProperty(string key)
  412. {
  413. var property = new PropertyAttributeProperty();
  414. _properties[key] = property;
  415. return property;
  416. }
  417. #endregion
  418. }
  419. /// <remarks>
  420. /// Use <see cref="PropertyAttribute.CreateProperty(string)"/> to create an instance of this class.
  421. /// </remarks>
  422. public partial class PropertyAttributeProperty : IChildOfDictionary<PropertyAttribute>
  423. {
  424. #region child properties
  425. public string LogicalKey { get; private set; }
  426. public PropertyAttribute LogicalParent { get; private set; }
  427. void IChildOfDictionary<PropertyAttribute>.SetLogicalParent(PropertyAttribute parent, string key)
  428. {
  429. LogicalParent = parent;
  430. LogicalKey = key;
  431. }
  432. #endregion
  433. #region properties
  434. public string Attribute
  435. {
  436. get => _attribute;
  437. set => _attribute = value;
  438. }
  439. /** Commented out for now, as it is not supported
  440. public JsonNode Min
  441. {
  442. get => _min;
  443. set => _min = value;
  444. }
  445. public JsonNode Max
  446. {
  447. get => _max;
  448. set => _max = value;
  449. }
  450. public JsonNode Scale
  451. {
  452. get => _scale;
  453. set => _scale = value;
  454. }
  455. public JsonNode Offset
  456. {
  457. get => _offset;
  458. set => _offset = value;
  459. }
  460. */
  461. #endregion
  462. }
  463. /// <remarks>
  464. /// Use <see cref="EXTStructuralMetadataRoot.AddPropertyTable"/> to create an instance of this class.
  465. /// </remarks>
  466. public partial class PropertyTable : IChildOfList<EXTStructuralMetadataRoot>
  467. {
  468. #region lifecycle
  469. internal PropertyTable()
  470. {
  471. _properties = new ChildrenDictionary<PropertyTableProperty, PropertyTable>(this);
  472. _count = _countMinimum;
  473. }
  474. protected override IEnumerable<ExtraProperties> GetLogicalChildren()
  475. {
  476. return base.GetLogicalChildren()
  477. .Concat(_properties.Values);
  478. }
  479. #endregion
  480. #region child properties
  481. public int LogicalIndex { get; private set; } = -1;
  482. public EXTStructuralMetadataRoot LogicalParent { get; private set; }
  483. void IChildOfList<EXTStructuralMetadataRoot>.SetLogicalParent(EXTStructuralMetadataRoot parent, int index)
  484. {
  485. LogicalParent = parent;
  486. LogicalIndex = index;
  487. }
  488. #endregion
  489. #region properties
  490. public IReadOnlyDictionary<string, PropertyTableProperty> Properties => _properties;
  491. public string ClassName
  492. {
  493. get => _class;
  494. set => _class = value;
  495. }
  496. public StructuralMetadataClass ClassInstance
  497. {
  498. get
  499. {
  500. if (string.IsNullOrEmpty(ClassName)) return null;
  501. var root = _GetModelRoot()?.GetExtension<EXTStructuralMetadataRoot>();
  502. if (root == null) return null;
  503. if (root.TryGetEmbeddedSchema(out var schema))
  504. {
  505. return schema.Classes[ClassName];
  506. }
  507. else return null;
  508. }
  509. set
  510. {
  511. // Todo: check value is part of this DOM
  512. ClassName = value?.LogicalKey;
  513. }
  514. }
  515. public string Name
  516. {
  517. get => _name;
  518. set => _name = value;
  519. }
  520. public int Count
  521. {
  522. get => _count;
  523. set
  524. {
  525. Guard.MustBeGreaterThanOrEqualTo(value, _countMinimum, nameof(value));
  526. _count = value;
  527. }
  528. }
  529. #endregion
  530. #region API
  531. private ModelRoot _GetModelRoot() => LogicalParent.LogicalParent;
  532. public PropertyTableProperty UseProperty(StructuralMetadataClassProperty key)
  533. {
  534. return UseProperty(key.LogicalKey);
  535. }
  536. public PropertyTableProperty UseProperty(string key)
  537. {
  538. if (_properties.TryGetValue(key, out var value)) return value;
  539. value = new PropertyTableProperty();
  540. _properties[key] = value;
  541. return value;
  542. }
  543. #endregion
  544. }
  545. /// <remarks>
  546. /// Use <see cref="PropertyTable.UseProperty(string)"/> to create an instance of this class.
  547. /// </remarks>
  548. public partial class PropertyTableProperty : IChildOfDictionary<PropertyTable>
  549. {
  550. #region child properties
  551. public string LogicalKey { get; private set; }
  552. public PropertyTable LogicalParent { get; private set; }
  553. void IChildOfDictionary<PropertyTable>.SetLogicalParent(PropertyTable parent, string key)
  554. {
  555. LogicalParent = parent;
  556. LogicalKey = key;
  557. }
  558. #endregion
  559. #region properties
  560. /// <summary>
  561. /// this is an index to a BufferView
  562. /// </summary>
  563. public int Values
  564. {
  565. get => _values;
  566. set => _values = value;
  567. }
  568. public int? ArrayOffsets
  569. {
  570. get => _arrayOffsets;
  571. set => _arrayOffsets = value;
  572. }
  573. public int? StringOffsets
  574. {
  575. get => _stringOffsets;
  576. set => _stringOffsets = value;
  577. }
  578. #endregion
  579. #region API
  580. private ModelRoot _GetModelRoot() => LogicalParent.LogicalParent.LogicalParent;
  581. public void SetArrayValues<T>(List<List<T>> values)
  582. {
  583. Guard.IsTrue(values.Count == LogicalParent.Count, nameof(values), $"Values must have length {LogicalParent.Count}");
  584. var className = LogicalParent.ClassName;
  585. var metadataProperty = GetProperty<T>(className, LogicalKey);
  586. metadataProperty.Array = true;
  587. var root = _GetModelRoot();
  588. int logicalIndex = GetBufferView(root, values);
  589. Values = logicalIndex;
  590. var hasVariableLength = HasVariableLength<T>(values);
  591. if (HasVariableLength<T>(values) || typeof(T) == typeof(string))
  592. {
  593. // if the array has items of variable length, create arraysOffsets bufferview
  594. var arrayOffsets = BinaryTable.GetArrayOffsets(values);
  595. int logicalIndexOffsets = GetBufferView(root, arrayOffsets);
  596. ArrayOffsets = logicalIndexOffsets;
  597. if (typeof(T) == typeof(string))
  598. {
  599. var stringValues = values.ConvertAll(x => x.ConvertAll(y => (string)Convert.ChangeType(y, typeof(string), CultureInfo.InvariantCulture)));
  600. var stringOffsets = BinaryTable.GetStringOffsets(stringValues);
  601. int offsets = GetBufferView(root, stringOffsets);
  602. StringOffsets = offsets;
  603. }
  604. }
  605. else
  606. {
  607. metadataProperty.Count = values[0].Count;
  608. }
  609. }
  610. public void SetValues<T>(params T[] values)
  611. {
  612. Guard.IsTrue(values.Length == LogicalParent.Count, nameof(values), $"Values must have length {LogicalParent.Count}");
  613. var className = LogicalParent.ClassName;
  614. GetProperty<T>(className, LogicalKey);
  615. var root = _GetModelRoot();
  616. int logicalIndex = GetBufferView(root, values);
  617. Values = logicalIndex;
  618. if (typeof(T) == typeof(string))
  619. {
  620. var stringvalues = values
  621. .Select(x => (string)Convert.ChangeType(x, typeof(string), CultureInfo.InvariantCulture))
  622. .ToList();
  623. var stringOffsets = BinaryTable.GetStringOffsets(stringvalues);
  624. int offsets = GetBufferView(root, stringOffsets);
  625. StringOffsets = offsets;
  626. }
  627. }
  628. private StructuralMetadataClassProperty GetProperty<T>(string className, string key)
  629. {
  630. var metadataClass = LogicalParent.LogicalParent.Schema.Classes[className];
  631. Guard.IsTrue(metadataClass != null, nameof(className), $"Schema class {className} must be defined");
  632. metadataClass.Properties.TryGetValue(key, out var metadataProperty);
  633. Guard.IsTrue(metadataProperty != null, nameof(key), $"Property {key} in {className} must be defined");
  634. CheckElementTypes<T>(metadataProperty);
  635. return metadataProperty;
  636. }
  637. private bool HasVariableLength<T>(List<List<T>> values)
  638. {
  639. int length = values[0].Count;
  640. for (int i = 1; i < values.Count; i++)
  641. {
  642. if (values[i].Count != length) return true;
  643. }
  644. return false;
  645. }
  646. private void CheckElementTypes<T>(StructuralMetadataClassProperty metadataProperty)
  647. {
  648. var elementType = metadataProperty.Type;
  649. if (elementType == ELEMENTTYPE.ENUM)
  650. {
  651. // guard the type of t is an short in case of enum
  652. Guard.IsTrue(typeof(T) == typeof(short), nameof(T), $"Enum value type of {LogicalKey} must be short");
  653. }
  654. else if (elementType == ELEMENTTYPE.SCALAR)
  655. {
  656. var componentType = metadataProperty.ComponentType;
  657. CheckScalarTypes<T>(componentType);
  658. }
  659. else if (elementType == ELEMENTTYPE.STRING)
  660. {
  661. Guard.IsTrue(typeof(T) == typeof(string), nameof(T), $"String type of property {LogicalKey} must be string");
  662. }
  663. else if (elementType == ELEMENTTYPE.BOOLEAN)
  664. {
  665. Guard.IsTrue(typeof(T) == typeof(bool), nameof(T), $"Boolean type of property {LogicalKey} must beboolean");
  666. }
  667. else if (elementType == ELEMENTTYPE.VEC2)
  668. {
  669. Guard.IsTrue(typeof(T) == typeof(Vector2), nameof(T), $"Vector2 type of property {LogicalKey} must be Vector2");
  670. }
  671. else if (elementType == ELEMENTTYPE.VEC3)
  672. {
  673. Guard.IsTrue(typeof(T) == typeof(Vector3), nameof(T), $"Vector3 type of property {LogicalKey} must be Vector3");
  674. }
  675. else if (elementType == ELEMENTTYPE.VEC3)
  676. {
  677. Guard.IsTrue(typeof(T) == typeof(Vector4), nameof(T), $"Vector4 type of property {LogicalKey} must be Vector4");
  678. }
  679. // todo: add MAT2, MAT3
  680. else if (elementType == ELEMENTTYPE.MAT4)
  681. {
  682. Guard.IsTrue(typeof(T) == typeof(Matrix4x4), nameof(T), $"Matrix4x4 type of property {LogicalKey} must be Matrix4x4");
  683. }
  684. }
  685. private void CheckScalarTypes<T>(DATATYPE? componentType)
  686. {
  687. if (componentType == DATATYPE.UINT8)
  688. {
  689. Guard.IsTrue(typeof(T) == typeof(byte), nameof(T), $"Scalar value type of property {LogicalKey} must be byte");
  690. }
  691. else if (componentType == DATATYPE.INT8)
  692. {
  693. Guard.IsTrue(typeof(T) == typeof(sbyte), nameof(T), $"Scalar value type of property {LogicalKey} must be sbyte");
  694. }
  695. else if (componentType == DATATYPE.INT16)
  696. {
  697. Guard.IsTrue(typeof(T) == typeof(short), nameof(T), $"Scalar value type of property {LogicalKey} must be short");
  698. }
  699. else if (componentType == DATATYPE.UINT16)
  700. {
  701. Guard.IsTrue(typeof(T) == typeof(ushort), nameof(T), $"Scalar value type of property {LogicalKey} must be ushort");
  702. }
  703. else if (componentType == DATATYPE.INT32)
  704. {
  705. Guard.IsTrue(typeof(T) == typeof(int), nameof(T), $"Scalar value type of property {LogicalKey} must be int");
  706. }
  707. else if (componentType == DATATYPE.UINT32)
  708. {
  709. Guard.IsTrue(typeof(T) == typeof(uint), nameof(T), $"Scalar value type of property {LogicalKey} must be uint");
  710. }
  711. else if (componentType == DATATYPE.INT64)
  712. {
  713. Guard.IsTrue(typeof(T) == typeof(long), nameof(T), $"Scalar value type of property {LogicalKey} must be long");
  714. }
  715. else if (componentType == DATATYPE.UINT64)
  716. {
  717. Guard.IsTrue(typeof(T) == typeof(ulong), nameof(T), $"Scalar value type of property {LogicalKey} must be ulong");
  718. }
  719. else if (componentType == DATATYPE.FLOAT32)
  720. {
  721. Guard.IsTrue(typeof(T) == typeof(Single), nameof(T), $"Scalar value type of property {LogicalKey} must be float");
  722. }
  723. else if (componentType == DATATYPE.FLOAT64)
  724. {
  725. Guard.IsTrue(typeof(T) == typeof(double), nameof(T), $"Scalar value type of property {LogicalKey} must be double");
  726. }
  727. }
  728. private static int GetBufferView<T>(ModelRoot model, IReadOnlyList<T> values)
  729. {
  730. var bytes = BinaryTable.GetBytes(values);
  731. var bufferView = model.UseBufferView(bytes);
  732. int logicalIndex = bufferView.LogicalIndex;
  733. return logicalIndex;
  734. }
  735. private static int GetBufferView<T>(ModelRoot model, List<List<T>> values)
  736. {
  737. List<byte> bytes = BinaryTable.GetBytesForArray(values);
  738. var bufferView = model.UseBufferView(bytes.ToArray());
  739. int logicalIndex = bufferView.LogicalIndex;
  740. return logicalIndex;
  741. }
  742. #endregion
  743. }
  744. #endregion
  745. #region structural schema
  746. /// <remarks>
  747. /// Use <see cref="EXTStructuralMetadataRoot.UseEmbeddedSchema()"/> to create an instance of this class.
  748. /// </remarks>
  749. public partial class StructuralMetadataSchema : IChildOf<EXTStructuralMetadataRoot>
  750. {
  751. #region lifecycle
  752. public StructuralMetadataSchema()
  753. {
  754. _classes = new ChildrenDictionary<StructuralMetadataClass, StructuralMetadataSchema>(this);
  755. _enums = new ChildrenDictionary<StructuralMetadataEnum, StructuralMetadataSchema>(this);
  756. }
  757. protected override IEnumerable<ExtraProperties> GetLogicalChildren()
  758. {
  759. return base.GetLogicalChildren()
  760. .Concat(_classes.Values)
  761. .Concat(_enums.Values);
  762. }
  763. #endregion
  764. #region child properties
  765. public EXTStructuralMetadataRoot LogicalParent { get; private set; }
  766. void IChildOf<EXTStructuralMetadataRoot>.SetLogicalParent(EXTStructuralMetadataRoot parent)
  767. {
  768. LogicalParent = parent;
  769. }
  770. #endregion
  771. #region properties
  772. public IReadOnlyDictionary<string, StructuralMetadataClass> Classes => _classes;
  773. public IReadOnlyDictionary<string, StructuralMetadataEnum> Enums => _enums;
  774. public string Id
  775. {
  776. get => _id;
  777. set => _id = value;
  778. }
  779. public string Version
  780. {
  781. get => _version;
  782. set => _version = value;
  783. }
  784. public string Name
  785. {
  786. get => _name;
  787. set => _name = value;
  788. }
  789. public string Description
  790. {
  791. get => _description;
  792. set => _description = value;
  793. }
  794. #endregion
  795. #region API
  796. public StructuralMetadataClass UseClassMetadata(string key)
  797. {
  798. if (_classes.TryGetValue(key, out var value)) return value;
  799. value = new StructuralMetadataClass();
  800. _classes[key] = value;
  801. return value;
  802. }
  803. public StructuralMetadataEnum UseEnumMetadata(string key, params (string name, int value)[] enumValues)
  804. {
  805. var enumType = UseEnumMetadata(key);
  806. foreach (var (name, value) in enumValues)
  807. {
  808. enumType.AddEnum(name, value);
  809. }
  810. return enumType;
  811. }
  812. public StructuralMetadataEnum UseEnumMetadata(string key)
  813. {
  814. if (_enums.TryGetValue(key, out var value)) return value;
  815. value = new StructuralMetadataEnum();
  816. _enums[key] = value;
  817. return value;
  818. }
  819. #endregion
  820. }
  821. /// <remarks>
  822. /// Use <see cref="StructuralMetadataSchema.UseEnumMetadata(string)"/> to create an instance of this class.
  823. /// </remarks>
  824. public partial class StructuralMetadataEnum : IChildOfDictionary<StructuralMetadataSchema>
  825. {
  826. #region lifecycle
  827. public StructuralMetadataEnum()
  828. {
  829. _values = new ChildrenList<StructuralMetadataEnumValue, StructuralMetadataEnum>(this);
  830. }
  831. #endregion
  832. #region child properties
  833. public string LogicalKey { get; private set; }
  834. public StructuralMetadataSchema LogicalParent { get; private set; }
  835. void IChildOfDictionary<StructuralMetadataSchema>.SetLogicalParent(StructuralMetadataSchema parent, string key)
  836. {
  837. LogicalParent = parent;
  838. LogicalKey = key;
  839. }
  840. #endregion
  841. #region properties
  842. public IReadOnlyList<StructuralMetadataEnumValue> Values => _values;
  843. public string Name
  844. {
  845. get => _name;
  846. set => _name = value;
  847. }
  848. public string Description
  849. {
  850. get => _description;
  851. set => _description = value;
  852. }
  853. public IntegerType? ValueType
  854. {
  855. get => _valueType;
  856. }
  857. #endregion
  858. #region API
  859. public StructuralMetadataEnumValue AddEnum(string name, int value, string desc = null)
  860. {
  861. var prop = AddEnum();
  862. prop.Name = name;
  863. prop.Value = value;
  864. prop.Description = desc;
  865. return prop;
  866. }
  867. public StructuralMetadataEnumValue AddEnum()
  868. {
  869. var prop = new StructuralMetadataEnumValue();
  870. _values.Add(prop);
  871. return prop;
  872. }
  873. #endregion
  874. }
  875. /// <remarks>
  876. /// Use <see cref="StructuralMetadataEnum.AddEnum()"/> to create an instance of this class.
  877. /// </remarks>
  878. public partial class StructuralMetadataEnumValue : IChildOfList<StructuralMetadataEnum>
  879. {
  880. #region child properties
  881. public int LogicalIndex { get; private set; } = -1;
  882. public StructuralMetadataEnum LogicalParent { get; private set; }
  883. void IChildOfList<StructuralMetadataEnum>.SetLogicalParent(StructuralMetadataEnum parent, int index)
  884. {
  885. LogicalParent = parent;
  886. LogicalIndex = index;
  887. }
  888. #endregion
  889. #region properties
  890. public string Description
  891. {
  892. get => _description;
  893. set => _description = value;
  894. }
  895. public string Name
  896. {
  897. get => _name;
  898. set => _name = value;
  899. }
  900. public int Value
  901. {
  902. get => _value;
  903. set => _value = value;
  904. }
  905. #endregion
  906. }
  907. /// <remarks>
  908. /// Use <see cref="StructuralMetadataSchema.UseClassMetadata(string)"/> to create an instance of this class.
  909. /// </remarks>
  910. public partial class StructuralMetadataClass : IChildOfDictionary<StructuralMetadataSchema>
  911. {
  912. #region lifecycle
  913. public StructuralMetadataClass()
  914. {
  915. _properties = new ChildrenDictionary<StructuralMetadataClassProperty, StructuralMetadataClass>(this);
  916. }
  917. protected override IEnumerable<ExtraProperties> GetLogicalChildren()
  918. {
  919. return base.GetLogicalChildren()
  920. .Concat(_properties.Values);
  921. }
  922. #endregion
  923. #region child properties
  924. public string LogicalKey { get; private set; }
  925. public StructuralMetadataSchema LogicalParent { get; private set; }
  926. void IChildOfDictionary<StructuralMetadataSchema>.SetLogicalParent(StructuralMetadataSchema parent, string key)
  927. {
  928. LogicalParent = parent;
  929. LogicalKey = key;
  930. }
  931. #endregion
  932. #region properties
  933. public IReadOnlyDictionary<string, StructuralMetadataClassProperty> Properties => _properties;
  934. public string Name
  935. {
  936. get => _name;
  937. set => _name = value;
  938. }
  939. public string Description
  940. {
  941. get => _description;
  942. set => _description = value;
  943. }
  944. #endregion
  945. #region API
  946. public StructuralMetadataClass WithName(string name)
  947. {
  948. Name = name;
  949. return this;
  950. }
  951. public StructuralMetadataClass WithDescription(string description)
  952. {
  953. Description = description;
  954. return this;
  955. }
  956. public StructuralMetadataClassProperty UseProperty(string key)
  957. {
  958. if (_properties.TryGetValue(key, out var value)) return value;
  959. value = new StructuralMetadataClassProperty();
  960. _properties[key] = value;
  961. return value;
  962. }
  963. public PropertyTexture AddPropertyTexture()
  964. {
  965. return LogicalParent.LogicalParent.AddPropertyTexture(this);
  966. }
  967. public PropertyAttribute AddPropertyAttribute()
  968. {
  969. return LogicalParent.LogicalParent.AddPropertyAttribute(this);
  970. }
  971. public PropertyTable AddPropertyTable(int featureCount, string name = null)
  972. {
  973. return LogicalParent.LogicalParent.AddPropertyTable(this, featureCount, name);
  974. }
  975. #endregion
  976. }
  977. /// <remarks>
  978. /// Use <see cref="StructuralMetadataClass.UseProperty(string)"/> to create an instance of this class.
  979. /// </remarks>
  980. public partial class StructuralMetadataClassProperty : IChildOfDictionary<StructuralMetadataClass>
  981. {
  982. #region child properties
  983. public string LogicalKey { get; private set; }
  984. public StructuralMetadataClass LogicalParent { get; private set; }
  985. void IChildOfDictionary<StructuralMetadataClass>.SetLogicalParent(StructuralMetadataClass parent, string key)
  986. {
  987. LogicalParent = parent;
  988. LogicalKey = key;
  989. }
  990. #endregion
  991. #region properties
  992. public string Name
  993. {
  994. get => _name;
  995. set => _name = value;
  996. }
  997. public string Description
  998. {
  999. get => _description;
  1000. set => _description = value;
  1001. }
  1002. internal ELEMENTTYPE Type
  1003. {
  1004. get => _type;
  1005. // set => _type = value;
  1006. }
  1007. public string EnumType
  1008. {
  1009. get => _enumType;
  1010. // set => _enumType = value;
  1011. }
  1012. public DATATYPE? ComponentType
  1013. {
  1014. get => _componentType;
  1015. // set => _componentType = value;
  1016. }
  1017. public bool Required
  1018. {
  1019. get => _required ?? _requiredDefault;
  1020. set => _required = value.AsNullable(_requiredDefault);
  1021. }
  1022. public JsonNode NoData
  1023. {
  1024. get => _noData;
  1025. }
  1026. public bool Normalized
  1027. {
  1028. get => _normalized ?? _normalizedDefault;
  1029. set => _normalized = value.AsNullable(_normalizedDefault);
  1030. }
  1031. public bool Array
  1032. {
  1033. get => _array ?? _arrayDefault;
  1034. set => _array = value.AsNullable(_arrayDefault);
  1035. }
  1036. public int? Count
  1037. {
  1038. get => _count;
  1039. set => _count = value;
  1040. }
  1041. /** Commented out for now, as it is not supported
  1042. public JsonNode Min
  1043. {
  1044. get => _min;
  1045. set => _min = value;
  1046. }
  1047. public JsonNode Max
  1048. {
  1049. get => _max;
  1050. set => _max = value;
  1051. }
  1052. public JsonNode Scale
  1053. {
  1054. get => _scale;
  1055. set => _scale = value;
  1056. }
  1057. public JsonNode Offset
  1058. {
  1059. get => _offset;
  1060. set => _offset = value;
  1061. }
  1062. */
  1063. #endregion
  1064. #region API
  1065. public StructuralMetadataClassProperty WithName(string name)
  1066. {
  1067. Name = name;
  1068. return this;
  1069. }
  1070. public StructuralMetadataClassProperty WithDescription(string description)
  1071. {
  1072. Description = description;
  1073. return this;
  1074. }
  1075. public StructuralMetadataClassProperty WithStringType(string noData = null, string defaultValue = null)
  1076. {
  1077. _type = ElementType.STRING;
  1078. if (noData != null) _noData = noData;
  1079. if(defaultValue != null) _default = defaultValue;
  1080. return this;
  1081. }
  1082. public StructuralMetadataClassProperty WithBooleanType()
  1083. {
  1084. _type = ElementType.BOOLEAN;
  1085. return this;
  1086. }
  1087. public StructuralMetadataClassProperty WithUInt8Type(byte? noData = null, byte? defaultValue = null)
  1088. {
  1089. _type = ELEMENTTYPE.SCALAR;
  1090. _componentType = DATATYPE.UINT8;
  1091. if (noData != null) _noData = noData;
  1092. if (defaultValue != null) _default = defaultValue;
  1093. return this;
  1094. }
  1095. public StructuralMetadataClassProperty WithInt8Type(sbyte? noData = null, sbyte? defaultValue = null)
  1096. {
  1097. _type = ELEMENTTYPE.SCALAR;
  1098. _componentType = DATATYPE.INT8;
  1099. if (noData != null) _noData = noData;
  1100. if (defaultValue != null) _default = defaultValue;
  1101. return this;
  1102. }
  1103. public StructuralMetadataClassProperty WithUInt16Type(ushort? noData = null, ushort? defaultValue = null)
  1104. {
  1105. _type = ELEMENTTYPE.SCALAR;
  1106. _componentType = DATATYPE.UINT16;
  1107. if (noData != null) _noData = noData;
  1108. if (defaultValue != null) _default = defaultValue;
  1109. return this;
  1110. }
  1111. public StructuralMetadataClassProperty WithInt16Type(short? noData = null, short? defaultValue = null)
  1112. {
  1113. _type = ELEMENTTYPE.SCALAR;
  1114. _componentType = DATATYPE.INT16;
  1115. if (noData != null) _noData = noData;
  1116. if (defaultValue != null) _default = defaultValue;
  1117. return this;
  1118. }
  1119. public StructuralMetadataClassProperty WithUInt32Type(uint? noData = null, uint? defaultValue = null)
  1120. {
  1121. _type = ELEMENTTYPE.SCALAR;
  1122. _componentType = DATATYPE.UINT32;
  1123. if (noData != null) _noData = noData;
  1124. if (defaultValue != null) _default = defaultValue;
  1125. return this;
  1126. }
  1127. public StructuralMetadataClassProperty WithInt32Type(int? noData = null, int? defaultValue = null)
  1128. {
  1129. _type = ELEMENTTYPE.SCALAR;
  1130. _componentType = DATATYPE.INT32;
  1131. if (noData != null) _noData = noData;
  1132. if (defaultValue != null) _default = defaultValue;
  1133. return this;
  1134. }
  1135. public StructuralMetadataClassProperty WithUInt64Type(ulong? noData = null, ulong? defaultValue = null)
  1136. {
  1137. _type = ELEMENTTYPE.SCALAR;
  1138. _componentType = DATATYPE.UINT64;
  1139. if (noData != null) _noData = noData;
  1140. if (defaultValue != null) _default = defaultValue;
  1141. return this;
  1142. }
  1143. public StructuralMetadataClassProperty WithInt64Type(long? noData = null, long? defaultValue = null)
  1144. {
  1145. _type = ELEMENTTYPE.SCALAR;
  1146. _componentType = DATATYPE.INT64;
  1147. if (noData != null) _noData = noData;
  1148. if (defaultValue != null) _default = defaultValue;
  1149. return this;
  1150. }
  1151. public StructuralMetadataClassProperty WithFloat32Type(float? noData = null, float? defaultValue = null)
  1152. {
  1153. _type = ELEMENTTYPE.SCALAR;
  1154. _componentType = DATATYPE.FLOAT32;
  1155. if (noData != null) _noData = noData;
  1156. if (defaultValue != null) _default = defaultValue;
  1157. return this;
  1158. }
  1159. public StructuralMetadataClassProperty WithFloat64Type(double? noData = null, double? defaultValue = null)
  1160. {
  1161. _type = ELEMENTTYPE.SCALAR;
  1162. _componentType = DATATYPE.FLOAT64;
  1163. if (noData != null) _noData = noData;
  1164. if (defaultValue != null) _default = defaultValue;
  1165. return this;
  1166. }
  1167. public StructuralMetadataClassProperty WithVector3Type(Vector3? noData = null, Vector3? defaultValue = null)
  1168. {
  1169. _type = ElementType.VEC3;
  1170. _componentType = DataType.FLOAT32;
  1171. if (noData != null)
  1172. {
  1173. _noData = new JsonArray(noData.Value.X, noData.Value.Y, noData.Value.Z);
  1174. }
  1175. if (defaultValue != null)
  1176. {
  1177. _default = new JsonArray(defaultValue.Value.X, defaultValue.Value.Y, defaultValue.Value.Z);
  1178. }
  1179. return this;
  1180. }
  1181. public StructuralMetadataClassProperty WithMatrix4x4Type(Matrix4x4? noData = null, Matrix4x4? defaultValue = null)
  1182. {
  1183. _type = ElementType.MAT4;
  1184. _componentType = DataType.FLOAT32;
  1185. if (noData != null)
  1186. {
  1187. var m4 = noData.Value;
  1188. _noData = new JsonArray(
  1189. m4.M11, m4.M12, m4.M13, m4.M14,
  1190. m4.M21, m4.M22, m4.M23, m4.M24,
  1191. m4.M31, m4.M32, m4.M33, m4.M34,
  1192. m4.M41, m4.M42, m4.M43, m4.M44);
  1193. }
  1194. if (defaultValue != null)
  1195. {
  1196. var m4 = defaultValue.Value;
  1197. _default = new JsonArray(
  1198. m4.M11, m4.M12, m4.M13, m4.M14,
  1199. m4.M21, m4.M22, m4.M23, m4.M24,
  1200. m4.M31, m4.M32, m4.M33, m4.M34,
  1201. m4.M41, m4.M42, m4.M43, m4.M44);
  1202. }
  1203. return this;
  1204. }
  1205. public StructuralMetadataClassProperty WithCount()
  1206. {
  1207. _type = ElementType.MAT4;
  1208. _componentType = DataType.FLOAT32;
  1209. return this;
  1210. }
  1211. public StructuralMetadataClassProperty WithBooleanArrayType(int? count = null)
  1212. {
  1213. var property = WithArrayType(ELEMENTTYPE.BOOLEAN, null, count);
  1214. return property;
  1215. }
  1216. public StructuralMetadataClassProperty WithUInt8ArrayType(int? count = null, byte? noData = null)
  1217. {
  1218. var property = WithArrayType(ELEMENTTYPE.SCALAR, DATATYPE.UINT8, count);
  1219. if (noData != null) property._noData = noData;
  1220. return property;
  1221. }
  1222. public StructuralMetadataClassProperty WithInt8ArrayType(int? count = null, sbyte? noData = null)
  1223. {
  1224. var property = WithArrayType(ELEMENTTYPE.SCALAR, DATATYPE.INT8, count);
  1225. if (noData != null) property._noData = noData;
  1226. return property;
  1227. }
  1228. public StructuralMetadataClassProperty WithInt16ArrayType(int? count = null, short? noData = null)
  1229. {
  1230. var property = WithArrayType(ELEMENTTYPE.SCALAR, DATATYPE.INT16, count);
  1231. if (noData != null) property._noData = noData;
  1232. return property;
  1233. }
  1234. public StructuralMetadataClassProperty WithUInt16ArrayType(int? count = null, ushort? noData = null)
  1235. {
  1236. var property = WithArrayType(ELEMENTTYPE.SCALAR, DATATYPE.UINT16, count);
  1237. if (noData != null) property._noData = noData;
  1238. return property;
  1239. }
  1240. public StructuralMetadataClassProperty WithInt32ArrayType(int? count = null, int? noData = null)
  1241. {
  1242. var property = WithArrayType(ELEMENTTYPE.SCALAR, DATATYPE.INT32, count);
  1243. if (noData != null) property._noData = noData;
  1244. return property;
  1245. }
  1246. public StructuralMetadataClassProperty WithUInt32ArrayType(int? count = null, uint? noData = null)
  1247. {
  1248. var property = WithArrayType(ELEMENTTYPE.SCALAR, DATATYPE.UINT32, count);
  1249. if (noData != null) property._noData = noData;
  1250. return property;
  1251. }
  1252. public StructuralMetadataClassProperty WithInt64ArrayType(int? count = null, long? noData = null)
  1253. {
  1254. var property = WithArrayType(ELEMENTTYPE.SCALAR, DATATYPE.INT64, count);
  1255. if (noData != null) property._noData = noData;
  1256. return property;
  1257. }
  1258. public StructuralMetadataClassProperty WithUInt64ArrayType(int? count = null, ulong? noData = null)
  1259. {
  1260. var property = WithArrayType(ELEMENTTYPE.SCALAR, DATATYPE.UINT64, count);
  1261. if (noData != null) property._noData = noData;
  1262. return property;
  1263. }
  1264. public StructuralMetadataClassProperty WithFloat32ArrayType(int? count = null, float? noData = null)
  1265. {
  1266. var property = WithArrayType(ELEMENTTYPE.SCALAR, DATATYPE.FLOAT32, count);
  1267. if (noData != null) property._noData = noData;
  1268. return property;
  1269. }
  1270. public StructuralMetadataClassProperty WithFloat64ArrayType(int? count = null, double? noData = null)
  1271. {
  1272. var property = WithArrayType(ELEMENTTYPE.SCALAR, DATATYPE.FLOAT64, count);
  1273. if (noData != null) property._noData = noData;
  1274. return property;
  1275. }
  1276. public StructuralMetadataClassProperty WithVector3ArrayType(int? count = null, Vector3? noData = null)
  1277. {
  1278. var property = WithArrayType(ELEMENTTYPE.VEC3, DATATYPE.FLOAT32, count);
  1279. return property;
  1280. }
  1281. public StructuralMetadataClassProperty WithMatrix4x4ArrayType(int? count = null)
  1282. {
  1283. return WithArrayType(ELEMENTTYPE.MAT4, DATATYPE.FLOAT32, count);
  1284. }
  1285. public StructuralMetadataClassProperty WithStringArrayType(int? count = null)
  1286. {
  1287. return WithArrayType(ELEMENTTYPE.STRING, null, count);
  1288. }
  1289. private StructuralMetadataClassProperty WithArrayType(ELEMENTTYPE etype, DATATYPE? ctype = null, int? count = null)
  1290. {
  1291. _type = etype;
  1292. _componentType = ctype;
  1293. Array = true;
  1294. Count = count;
  1295. return this;
  1296. }
  1297. public StructuralMetadataClassProperty WithEnumArrayType(StructuralMetadataEnum enumeration, int? count = null, string noData = null)
  1298. {
  1299. _type = ELEMENTTYPE.ENUM;
  1300. _enumType = enumeration.LogicalKey;
  1301. Array = true;
  1302. Count = count;
  1303. if (noData != null) _noData = noData;
  1304. return this;
  1305. }
  1306. public StructuralMetadataClassProperty WithEnumeration(StructuralMetadataEnum enumeration, string noData = null)
  1307. {
  1308. _type = ELEMENTTYPE.ENUM;
  1309. _enumType = enumeration.LogicalKey;
  1310. if (noData != null) _noData = noData;
  1311. return this;
  1312. }
  1313. public StructuralMetadataClassProperty WithRequired(bool required)
  1314. {
  1315. Required = required;
  1316. return this;
  1317. }
  1318. public StructuralMetadataClassProperty WithNormalized(bool normalized)
  1319. {
  1320. Normalized = normalized;
  1321. return this;
  1322. }
  1323. #endregion
  1324. }
  1325. #endregion
  1326. }
  1327. }