decorators.ts 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. import { Tags } from "../Misc/tags";
  2. import { Nullable } from "../types";
  3. import { Quaternion, Vector2, Vector3, Matrix } from "../Maths/math.vector";
  4. import { _DevTools } from './devTools';
  5. import { IAnimatable } from '../Animations/animatable.interface';
  6. import { Color4, Color3 } from '../Maths/math.color';
  7. declare type Scene = import("../scene").Scene;
  8. declare type Camera = import("../Cameras/camera").Camera;
  9. declare type ImageProcessingConfiguration = import("../Materials/imageProcessingConfiguration").ImageProcessingConfiguration;
  10. declare type FresnelParameters = import("../Materials/fresnelParameters").FresnelParameters;
  11. declare type ColorCurves = import("../Materials/colorCurves").ColorCurves;
  12. declare type BaseTexture = import("../Materials/Textures/baseTexture").BaseTexture;
  13. var __decoratorInitialStore = {};
  14. var __mergedStore = {};
  15. var _copySource = function <T>(creationFunction: () => T, source: T, instanciate: boolean): T {
  16. var destination = creationFunction();
  17. // Tags
  18. if (Tags) {
  19. Tags.AddTagsTo(destination, (<any>source).tags);
  20. }
  21. var classStore = getMergedStore(destination);
  22. // Properties
  23. for (var property in classStore) {
  24. var propertyDescriptor = classStore[property];
  25. var sourceProperty = (<any>source)[property];
  26. var propertyType = propertyDescriptor.type;
  27. if (sourceProperty !== undefined && sourceProperty !== null && property !== "uniqueId") {
  28. switch (propertyType) {
  29. case 0: // Value
  30. case 6: // Mesh reference
  31. case 11: // Camera reference
  32. (<any>destination)[property] = sourceProperty;
  33. break;
  34. case 1: // Texture
  35. (<any>destination)[property] = (instanciate || sourceProperty.isRenderTarget) ? sourceProperty : sourceProperty.clone();
  36. break;
  37. case 2: // Color3
  38. case 3: // FresnelParameters
  39. case 4: // Vector2
  40. case 5: // Vector3
  41. case 7: // Color Curves
  42. case 10: // Quaternion
  43. case 12: // Matrix
  44. (<any>destination)[property] = instanciate ? sourceProperty : sourceProperty.clone();
  45. break;
  46. }
  47. }
  48. }
  49. return destination;
  50. };
  51. function getDirectStore(target: any): any {
  52. var classKey = target.getClassName();
  53. if (!(<any>__decoratorInitialStore)[classKey]) {
  54. (<any>__decoratorInitialStore)[classKey] = {};
  55. }
  56. return (<any>__decoratorInitialStore)[classKey];
  57. }
  58. /**
  59. * Return the list of properties flagged as serializable
  60. * @param target: host object
  61. */
  62. function getMergedStore(target: any): any {
  63. let classKey = target.getClassName();
  64. if ((<any>__mergedStore)[classKey]) {
  65. return (<any>__mergedStore)[classKey];
  66. }
  67. (<any>__mergedStore)[classKey] = {};
  68. let store = (<any>__mergedStore)[classKey];
  69. let currentTarget = target;
  70. let currentKey = classKey;
  71. while (currentKey) {
  72. let initialStore = (<any>__decoratorInitialStore)[currentKey];
  73. for (var property in initialStore) {
  74. store[property] = initialStore[property];
  75. }
  76. let parent: any;
  77. let done = false;
  78. do {
  79. parent = Object.getPrototypeOf(currentTarget);
  80. if (!parent.getClassName) {
  81. done = true;
  82. break;
  83. }
  84. if (parent.getClassName() !== currentKey) {
  85. break;
  86. }
  87. currentTarget = parent;
  88. }
  89. while (parent);
  90. if (done) {
  91. break;
  92. }
  93. currentKey = parent.getClassName();
  94. currentTarget = parent;
  95. }
  96. return store;
  97. }
  98. function generateSerializableMember(type: number, sourceName?: string) {
  99. return (target: any, propertyKey: string | symbol) => {
  100. var classStore = getDirectStore(target);
  101. if (!classStore[propertyKey]) {
  102. classStore[propertyKey] = { type: type, sourceName: sourceName };
  103. }
  104. };
  105. }
  106. function generateExpandMember(setCallback: string, targetKey: Nullable<string> = null) {
  107. return (target: any, propertyKey: string) => {
  108. var key = targetKey || ("_" + propertyKey);
  109. Object.defineProperty(target, propertyKey, {
  110. get: function(this: any) {
  111. return this[key];
  112. },
  113. set: function(this: any, value) {
  114. if (this[key] === value) {
  115. return;
  116. }
  117. this[key] = value;
  118. target[setCallback].apply(this);
  119. },
  120. enumerable: true,
  121. configurable: true
  122. });
  123. };
  124. }
  125. export function expandToProperty(callback: string, targetKey: Nullable<string> = null) {
  126. return generateExpandMember(callback, targetKey);
  127. }
  128. export function serialize(sourceName?: string) {
  129. return generateSerializableMember(0, sourceName); // value member
  130. }
  131. export function serializeAsTexture(sourceName?: string) {
  132. return generateSerializableMember(1, sourceName); // texture member
  133. }
  134. export function serializeAsColor3(sourceName?: string) {
  135. return generateSerializableMember(2, sourceName); // color3 member
  136. }
  137. export function serializeAsFresnelParameters(sourceName?: string) {
  138. return generateSerializableMember(3, sourceName); // fresnel parameters member
  139. }
  140. export function serializeAsVector2(sourceName?: string) {
  141. return generateSerializableMember(4, sourceName); // vector2 member
  142. }
  143. export function serializeAsVector3(sourceName?: string) {
  144. return generateSerializableMember(5, sourceName); // vector3 member
  145. }
  146. export function serializeAsMeshReference(sourceName?: string) {
  147. return generateSerializableMember(6, sourceName); // mesh reference member
  148. }
  149. export function serializeAsColorCurves(sourceName?: string) {
  150. return generateSerializableMember(7, sourceName); // color curves
  151. }
  152. export function serializeAsColor4(sourceName?: string) {
  153. return generateSerializableMember(8, sourceName); // color 4
  154. }
  155. export function serializeAsImageProcessingConfiguration(sourceName?: string) {
  156. return generateSerializableMember(9, sourceName); // image processing
  157. }
  158. export function serializeAsQuaternion(sourceName?: string) {
  159. return generateSerializableMember(10, sourceName); // quaternion member
  160. }
  161. export function serializeAsMatrix(sourceName?: string) {
  162. return generateSerializableMember(12, sourceName); // matrix member
  163. }
  164. /**
  165. * Decorator used to define property that can be serialized as reference to a camera
  166. * @param sourceName defines the name of the property to decorate
  167. */
  168. export function serializeAsCameraReference(sourceName?: string) {
  169. return generateSerializableMember(11, sourceName); // camera reference member
  170. }
  171. /**
  172. * Class used to help serialization objects
  173. */
  174. export class SerializationHelper {
  175. /** @hidden */
  176. public static _ImageProcessingConfigurationParser = (sourceProperty: any): ImageProcessingConfiguration => {
  177. throw _DevTools.WarnImport("ImageProcessingConfiguration");
  178. }
  179. /** @hidden */
  180. public static _FresnelParametersParser = (sourceProperty: any): FresnelParameters => {
  181. throw _DevTools.WarnImport("FresnelParameters");
  182. }
  183. /** @hidden */
  184. public static _ColorCurvesParser = (sourceProperty: any): ColorCurves => {
  185. throw _DevTools.WarnImport("ColorCurves");
  186. }
  187. /** @hidden */
  188. public static _TextureParser = (sourceProperty: any, scene: Scene, rootUrl: string): Nullable<BaseTexture> => {
  189. throw _DevTools.WarnImport("Texture");
  190. }
  191. /**
  192. * Appends the serialized animations from the source animations
  193. * @param source Source containing the animations
  194. * @param destination Target to store the animations
  195. */
  196. public static AppendSerializedAnimations(source: IAnimatable, destination: any): void {
  197. if (source.animations) {
  198. destination.animations = [];
  199. for (var animationIndex = 0; animationIndex < source.animations.length; animationIndex++) {
  200. var animation = source.animations[animationIndex];
  201. destination.animations.push(animation.serialize());
  202. }
  203. }
  204. }
  205. /**
  206. * Static function used to serialized a specific entity
  207. * @param entity defines the entity to serialize
  208. * @param serializationObject defines the optional target obecjt where serialization data will be stored
  209. * @returns a JSON compatible object representing the serialization of the entity
  210. */
  211. public static Serialize<T>(entity: T, serializationObject?: any): any {
  212. if (!serializationObject) {
  213. serializationObject = {};
  214. }
  215. // Tags
  216. if (Tags) {
  217. serializationObject.tags = Tags.GetTags(entity);
  218. }
  219. var serializedProperties = getMergedStore(entity);
  220. // Properties
  221. for (var property in serializedProperties) {
  222. var propertyDescriptor = serializedProperties[property];
  223. var targetPropertyName = propertyDescriptor.sourceName || property;
  224. var propertyType = propertyDescriptor.type;
  225. var sourceProperty = (<any>entity)[property];
  226. if (sourceProperty !== undefined && sourceProperty !== null) {
  227. switch (propertyType) {
  228. case 0: // Value
  229. serializationObject[targetPropertyName] = sourceProperty;
  230. break;
  231. case 1: // Texture
  232. serializationObject[targetPropertyName] = sourceProperty.serialize();
  233. break;
  234. case 2: // Color3
  235. serializationObject[targetPropertyName] = sourceProperty.asArray();
  236. break;
  237. case 3: // FresnelParameters
  238. serializationObject[targetPropertyName] = sourceProperty.serialize();
  239. break;
  240. case 4: // Vector2
  241. serializationObject[targetPropertyName] = sourceProperty.asArray();
  242. break;
  243. case 5: // Vector3
  244. serializationObject[targetPropertyName] = sourceProperty.asArray();
  245. break;
  246. case 6: // Mesh reference
  247. serializationObject[targetPropertyName] = sourceProperty.id;
  248. break;
  249. case 7: // Color Curves
  250. serializationObject[targetPropertyName] = sourceProperty.serialize();
  251. break;
  252. case 8: // Color 4
  253. serializationObject[targetPropertyName] = (<Color4>sourceProperty).asArray();
  254. break;
  255. case 9: // Image Processing
  256. serializationObject[targetPropertyName] = (<ImageProcessingConfiguration>sourceProperty).serialize();
  257. break;
  258. case 10: // Quaternion
  259. serializationObject[targetPropertyName] = (<Quaternion>sourceProperty).asArray();
  260. break;
  261. case 11: // Camera reference
  262. serializationObject[targetPropertyName] = (<Camera>sourceProperty).id;
  263. case 12: // Matrix
  264. serializationObject[targetPropertyName] = (<Matrix>sourceProperty).asArray();
  265. break;
  266. }
  267. }
  268. }
  269. return serializationObject;
  270. }
  271. /**
  272. * Creates a new entity from a serialization data object
  273. * @param creationFunction defines a function used to instanciated the new entity
  274. * @param source defines the source serialization data
  275. * @param scene defines the hosting scene
  276. * @param rootUrl defines the root url for resources
  277. * @returns a new entity
  278. */
  279. public static Parse<T>(creationFunction: () => T, source: any, scene: Nullable<Scene>, rootUrl: Nullable<string> = null): T {
  280. var destination = creationFunction();
  281. if (!rootUrl) {
  282. rootUrl = "";
  283. }
  284. // Tags
  285. if (Tags) {
  286. Tags.AddTagsTo(destination, source.tags);
  287. }
  288. var classStore = getMergedStore(destination);
  289. // Properties
  290. for (var property in classStore) {
  291. var propertyDescriptor = classStore[property];
  292. var sourceProperty = source[propertyDescriptor.sourceName || property];
  293. var propertyType = propertyDescriptor.type;
  294. if (sourceProperty !== undefined && sourceProperty !== null) {
  295. var dest = <any>destination;
  296. switch (propertyType) {
  297. case 0: // Value
  298. dest[property] = sourceProperty;
  299. break;
  300. case 1: // Texture
  301. if (scene) {
  302. dest[property] = SerializationHelper._TextureParser(sourceProperty, scene, rootUrl);
  303. }
  304. break;
  305. case 2: // Color3
  306. dest[property] = Color3.FromArray(sourceProperty);
  307. break;
  308. case 3: // FresnelParameters
  309. dest[property] = SerializationHelper._FresnelParametersParser(sourceProperty);
  310. break;
  311. case 4: // Vector2
  312. dest[property] = Vector2.FromArray(sourceProperty);
  313. break;
  314. case 5: // Vector3
  315. dest[property] = Vector3.FromArray(sourceProperty);
  316. break;
  317. case 6: // Mesh reference
  318. if (scene) {
  319. dest[property] = scene.getLastMeshByID(sourceProperty);
  320. }
  321. break;
  322. case 7: // Color Curves
  323. dest[property] = SerializationHelper._ColorCurvesParser(sourceProperty);
  324. break;
  325. case 8: // Color 4
  326. dest[property] = Color4.FromArray(sourceProperty);
  327. break;
  328. case 9: // Image Processing
  329. dest[property] = SerializationHelper._ImageProcessingConfigurationParser(sourceProperty);
  330. break;
  331. case 10: // Quaternion
  332. dest[property] = Quaternion.FromArray(sourceProperty);
  333. break;
  334. case 11: // Camera reference
  335. if (scene) {
  336. dest[property] = scene.getCameraByID(sourceProperty);
  337. }
  338. case 12: // Matrix
  339. dest[property] = Matrix.FromArray(sourceProperty);
  340. break;
  341. }
  342. }
  343. }
  344. return destination;
  345. }
  346. /**
  347. * Clones an object
  348. * @param creationFunction defines the function used to instanciate the new object
  349. * @param source defines the source object
  350. * @returns the cloned object
  351. */
  352. public static Clone<T>(creationFunction: () => T, source: T): T {
  353. return _copySource(creationFunction, source, false);
  354. }
  355. /**
  356. * Instanciates a new object based on a source one (some data will be shared between both object)
  357. * @param creationFunction defines the function used to instanciate the new object
  358. * @param source defines the source object
  359. * @returns the new object
  360. */
  361. public static Instanciate<T>(creationFunction: () => T, source: T): T {
  362. return _copySource(creationFunction, source, true);
  363. }
  364. }