@woosh/meep-engine 2.37.18 → 2.38.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.
Files changed (289) hide show
  1. package/core/assert.js +1 -1
  2. package/core/binary/float2uint8.js +8 -0
  3. package/core/binary/uint82float.js +8 -0
  4. package/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js +6 -4
  5. package/core/collection/array/array_get_index_in_range.js +16 -0
  6. package/core/collection/array/typed/isTypedArray.js +20 -0
  7. package/core/collection/array/typedArrayToDataType.js +1 -0
  8. package/{engine/navigation/grid → core/collection/heap}/BinaryHeap.js +6 -1
  9. package/{engine/navigation/grid → core/collection/heap}/FastBinaryHeap.js +3 -2
  10. package/{engine/navigation/grid → core/collection/heap}/FastBinaryHeap.spec.js +3 -3
  11. package/core/collection/heap/Uin32Heap.spec.js +59 -0
  12. package/core/collection/heap/Uint32Heap.js +385 -0
  13. package/core/collection/list/List.d.ts +1 -1
  14. package/core/collection/table/RowFirstTable.js +34 -0
  15. package/core/collection/table/RowFirstTable.spec.js +59 -1
  16. package/core/color/Color.js +83 -1
  17. package/core/color/YCbCr_to_rgb_uint24.js +3 -4
  18. package/core/color/hsv2rgb.js +4 -3
  19. package/core/color/linear_to_sRGB.js +4 -5
  20. package/core/color/rgb2hex.js +1 -1
  21. package/core/color/rgb2uint24.js +6 -4
  22. package/core/color/rgb_to_YCbCr_uint24.js +11 -13
  23. package/core/events/signal/Signal.d.ts +11 -9
  24. package/core/events/signal/Signal.spec.js +16 -0
  25. package/core/geom/2d/quad-tree/qt_collect_by_circle.js +67 -0
  26. package/core/geom/3d/topology/computeTopoMeshVertexDuplicates.js +9 -6
  27. package/core/geom/3d/topology/expandConnectivityByLocality.js +5 -5
  28. package/core/geom/3d/topology/query/query_edge_is_boundary.js +7 -0
  29. package/core/geom/3d/topology/query/query_edge_is_manifold.js +13 -0
  30. package/core/geom/3d/topology/query/query_edge_is_manifold_or_boundary.js +11 -0
  31. package/core/geom/3d/topology/query/query_edge_is_wire.js +13 -0
  32. package/core/geom/3d/topology/query/query_edge_other_vertex.js +20 -0
  33. package/core/geom/3d/topology/query/query_edge_share_vert.js +9 -0
  34. package/core/geom/3d/topology/query/query_face_get_other_edges.js +39 -0
  35. package/core/geom/3d/topology/query/query_face_next_vertex.js +19 -0
  36. package/core/geom/3d/topology/query/query_face_prev_vertex.js +18 -0
  37. package/core/geom/3d/topology/query/query_vertex_in_edge.js +14 -0
  38. package/core/geom/3d/topology/query/query_vertex_pair_share_face.js +24 -0
  39. package/core/geom/3d/topology/query/query_vertices_in_edge.js +19 -0
  40. package/core/geom/3d/topology/simplify/collapseEdge.spec.js +3 -5
  41. package/core/geom/3d/topology/simplify/collapse_all_degenerate_edges.js +8 -10
  42. package/core/geom/3d/topology/simplify/compute_face_normal_change_dot_product.js +12 -2
  43. package/core/geom/3d/topology/simplify/decimate_edge_collapse_snap.js +277 -0
  44. package/core/geom/3d/topology/simplify/edge_collapse_quadratic.js +126 -0
  45. package/core/geom/3d/topology/simplify/prototypeMeshSimplification.js +502 -0
  46. package/core/geom/3d/topology/simplify/quadratic/Quadratic3.js +37 -5
  47. package/core/geom/3d/topology/simplify/quadratic/build_vertex_quadratics.js +86 -1
  48. package/core/geom/3d/topology/simplify/simplifyTopoMesh.js +4 -4
  49. package/core/geom/3d/topology/simplify/simplifyTopoMesh2.js +119 -0
  50. package/core/geom/3d/topology/simplify/tm_edge_collapse_is_degenerate_flip.js +81 -0
  51. package/core/geom/3d/topology/{TopoEdge.js → struct/TopoEdge.js} +47 -20
  52. package/core/geom/3d/topology/{TopoEdge.spec.js → struct/TopoEdge.spec.js} +0 -0
  53. package/core/geom/3d/topology/{TopoMesh.js → struct/TopoMesh.js} +20 -41
  54. package/core/geom/3d/topology/{TopoTriangle.js → struct/TopoTriangle.js} +15 -25
  55. package/core/geom/3d/topology/{TopoVertex.js → struct/TopoVertex.js} +21 -4
  56. package/core/geom/3d/topology/{TopoVertex.spec.js → struct/TopoVertex.spec.js} +0 -0
  57. package/core/geom/3d/topology/tm_edge_kill.js +24 -0
  58. package/core/geom/3d/topology/tm_edge_splice.js +42 -0
  59. package/core/geom/3d/topology/tm_face_area.js +18 -0
  60. package/core/geom/3d/topology/tm_face_kill.js +12 -0
  61. package/core/geom/3d/topology/tm_face_normal.js +14 -0
  62. package/core/geom/3d/topology/tm_kill_only_edge.js +35 -0
  63. package/core/geom/3d/topology/tm_kill_only_face.js +12 -0
  64. package/core/geom/3d/topology/tm_kill_only_vert.js +14 -0
  65. package/core/geom/3d/topology/tm_vert_kill.js +19 -0
  66. package/core/geom/3d/topology/tm_vert_splice.js +64 -0
  67. package/core/geom/3d/topology/tm_vertex_compute_normal.js +42 -0
  68. package/core/geom/3d/topology/topoMeshToBufferGeometry.js +18 -4
  69. package/core/geom/3d/topology/weld_duplicate_vertices.js +63 -0
  70. package/core/geom/Quaternion.d.ts +21 -1
  71. package/core/geom/Quaternion.js +279 -200
  72. package/core/geom/Quaternion.spec.js +71 -2
  73. package/core/geom/Vector2.js +3 -3
  74. package/core/geom/Vector3.d.ts +2 -0
  75. package/core/geom/Vector3.js +31 -7
  76. package/core/geom/Vector3.schema.json +16 -0
  77. package/core/geom/Vector4.js +16 -0
  78. package/core/geom/packing/MaxRectangles.js +1 -1
  79. package/core/graph/cluster_mesh_metis.js +16 -0
  80. package/core/graph/coarsen_graph.js +1 -1
  81. package/core/graph/graph_k_means_cluster.js +1 -1
  82. package/core/json/JsonUtils.js +2 -20
  83. package/core/math/bell_membership_function.js +19 -0
  84. package/core/math/exp2.js +8 -0
  85. package/core/math/interval/NumericInterval.js +17 -0
  86. package/core/math/physics/brdf/brdf_burley.js +25 -0
  87. package/core/math/physics/bsdf/bsdf_schlick.js +22 -0
  88. package/core/math/physics/irradiance/interpolate_irradiance_linear.js +18 -0
  89. package/{engine/sound/ecs/emitter/attenuate/attenuateSoundLogarithmic.js → core/math/physics/irradiance/interpolate_irradiance_lograrithmic.js} +2 -2
  90. package/{engine/sound/ecs/emitter/attenuate/attenuateSoundSmith.js → core/math/physics/irradiance/interpolate_irradiance_smith.js} +1 -1
  91. package/core/math/random/seededRandom.js +2 -31
  92. package/core/math/random/seededRandom_Mulberry32.js +31 -0
  93. package/core/math/random/seededRandom_sine.js +33 -0
  94. package/core/model/ObservedEnum.js +8 -0
  95. package/editor/Editor.js +97 -1
  96. package/editor/actions/concrete/ModifyPatchSampler2DAction.js +118 -0
  97. package/editor/actions/concrete/ModifyPatchSampler2DAction.spec.js +30 -0
  98. package/editor/actions/concrete/PatchTerrainHeightAction.js +13 -105
  99. package/editor/ecs/component/FieldDescriptor.js +34 -0
  100. package/editor/ecs/component/FieldValueAdapter.js +20 -0
  101. package/editor/ecs/component/TypeEditor.js +33 -0
  102. package/editor/ecs/component/TypeSchema.d.ts +38 -0
  103. package/editor/ecs/component/createFieldEditor.js +90 -0
  104. package/editor/ecs/component/createObjectEditor.js +266 -60
  105. package/editor/ecs/component/editors/ColorEditor.js +39 -0
  106. package/editor/ecs/component/editors/HTMLElementEditor.js +17 -0
  107. package/editor/ecs/component/editors/ImagePathEditor.js +50 -0
  108. package/editor/ecs/component/editors/NumericIntervalEditor.js +86 -0
  109. package/editor/ecs/component/editors/ObservedBooleanEditor.js +13 -0
  110. package/editor/ecs/component/editors/ObservedEnumEditor.js +32 -0
  111. package/editor/ecs/component/editors/ObservedIntegerEditor.js +43 -0
  112. package/editor/ecs/component/editors/ObservedStringEditor.js +51 -0
  113. package/editor/ecs/component/editors/Sampler2DEditor.js +107 -0
  114. package/editor/ecs/component/editors/collection/ListEditor.js +83 -0
  115. package/editor/ecs/component/editors/common/BitFlagsEditor.js +80 -0
  116. package/editor/ecs/component/editors/common/EnumEditor.js +41 -0
  117. package/editor/ecs/component/editors/common/makeV3_editor.js +85 -0
  118. package/editor/ecs/component/editors/common/noEditor.js +9 -0
  119. package/editor/ecs/component/editors/ecs/GridObstacleEditor.js +17 -0
  120. package/editor/ecs/component/editors/ecs/MinimapMarkerEditor.js +16 -0
  121. package/editor/ecs/component/editors/ecs/ParameterLookupTableEditor.js +44 -0
  122. package/editor/ecs/component/editors/ecs/ParameterTrackEditor.js +17 -0
  123. package/editor/ecs/component/editors/ecs/ParticleEmitterEditor.js +58 -0
  124. package/editor/ecs/component/editors/ecs/ParticleEmitterLayerEditor.js +54 -0
  125. package/editor/ecs/component/editors/ecs/SimulationStepDefinitionEditor.js +21 -0
  126. package/editor/ecs/component/editors/ecs/Trail2DEditor.js +33 -0
  127. package/editor/ecs/component/editors/ecs/TransformEditor.js +23 -0
  128. package/editor/ecs/component/editors/ecs/terrain/SplatMappingEditor.js +21 -0
  129. package/editor/ecs/component/editors/ecs/terrain/TerrainEditor.js +89 -0
  130. package/editor/ecs/component/editors/ecs/terrain/TerrainLayerEditor.js +18 -0
  131. package/editor/ecs/component/editors/ecs/terrain/TerrainLayersEditor.js +22 -0
  132. package/editor/ecs/component/editors/ecs/terrain/TerrainOverlayEditor.js +20 -0
  133. package/editor/ecs/component/editors/geom/QuaternionEditor.js +56 -0
  134. package/editor/ecs/component/editors/geom/Vector1Editor.js +57 -0
  135. package/editor/ecs/component/editors/geom/Vector2Editor.js +11 -0
  136. package/editor/ecs/component/editors/geom/Vector3Editor.js +13 -0
  137. package/editor/ecs/component/editors/geom/Vector4Editor.js +12 -0
  138. package/editor/ecs/component/editors/primitive/ArrayEditor.js +46 -0
  139. package/editor/ecs/component/editors/primitive/BooleanEditor.js +27 -0
  140. package/editor/ecs/component/editors/primitive/FunctionEditor.js +29 -0
  141. package/editor/ecs/component/editors/primitive/NumberEditor.js +60 -0
  142. package/editor/ecs/component/editors/primitive/ObjectEditor.js +12 -0
  143. package/editor/ecs/component/editors/primitive/StringEditor.js +31 -0
  144. package/editor/ecs/component/editors/three/BufferGeometryEditor.js +28 -0
  145. package/editor/ecs/component/editors/three/MaterialEditor.js +27 -0
  146. package/editor/ecs/component/editors/three/MeshEditor.js +35 -0
  147. package/editor/ecs/component/editors/three/TextureEditor.js +32 -0
  148. package/editor/ecs/component/findNearestRegisteredType.js +59 -0
  149. package/editor/ecs/component/prototypeObjectEditor.js +379 -0
  150. package/editor/tools/SelectionTool.js +1 -1
  151. package/editor/tools/paint/TerrainHeightPaintTool.js +88 -68
  152. package/editor/tools/paint/TerrainPaintTool.js +2 -1
  153. package/editor/tools/paint/TerrainTexturePaintTool.js +8 -73
  154. package/editor/view/EditorView.js +1 -1
  155. package/editor/view/ecs/ComponentControlView.js +2 -30
  156. package/editor/view/ecs/EntityEditor.js +61 -139
  157. package/editor/view/ecs/components/GridObstacleController.js +4 -4
  158. package/editor/view/ecs/components/TerrainController.js +1 -1
  159. package/editor/view/ecs/components/common/NumberController.js +19 -7
  160. package/editor/view/node-graph/NodeGraphView.js +2 -2
  161. package/editor/view/node-graph/NodeView.js +7 -9
  162. package/engine/animation/keyed2/AnimationTrack.js +1 -1
  163. package/engine/asset/AssetManager.d.ts +1 -1
  164. package/engine/asset/AssetManager.js +390 -388
  165. package/engine/asset/loaders/gltf/extensions/MSFT_texture_dds.js +14 -2
  166. package/engine/ecs/components/TagEditor.js +15 -0
  167. package/engine/ecs/fow/FogOfWarEditor.js +13 -0
  168. package/engine/ecs/parent/ParentEntitySystem.js +57 -0
  169. package/engine/ecs/terrain/ecs/OffsetScaleTransform2D.d.ts +6 -0
  170. package/engine/ecs/terrain/ecs/Terrain.js +44 -43
  171. package/engine/ecs/terrain/ecs/TerrainSystem.js +2 -2
  172. package/engine/ecs/terrain/ecs/layers/TerrainLayer.js +1 -1
  173. package/engine/ecs/terrain/ecs/splat/SplatMapping.js +26 -28
  174. package/engine/ecs/terrain/overlay/TerrainOverlay.js +71 -66
  175. package/engine/ecs/terrain/tiles/TerrainTileManager.js +23 -0
  176. package/engine/ecs/terrain/util/loadVisibleTerrainTiles.js +1 -1
  177. package/engine/ecs/terrain/util/paintTerrainOverlayViaLookupTable.js +13 -7
  178. package/engine/ecs/terrain/util/tensionOptimizeUV.js +1 -1
  179. package/engine/ecs/transform/Transform.d.ts +2 -0
  180. package/engine/ecs/transform/Transform.editor.schema.json +16 -0
  181. package/engine/ecs/transform/Transform.js +3 -0
  182. package/engine/graphics/ecs/highlight/HighlightEditor.js +17 -0
  183. package/engine/graphics/ecs/light/Light.js +0 -47
  184. package/engine/graphics/ecs/light/LightSerializationAdapter.js +50 -0
  185. package/engine/graphics/ecs/mesh/MeshEditor.js +28 -0
  186. package/engine/graphics/ecs/mesh-v2/DrawMode.js +2 -1
  187. package/engine/graphics/ecs/mesh-v2/aggregate/prototypeSGMesh.js +3 -3
  188. package/engine/graphics/ecs/mesh-v2/build_three_object.js +3 -1
  189. package/engine/graphics/ecs/mesh-v2/sg_compute_hierarchy_bounding_box_by_parent_entity.js +31 -0
  190. package/engine/graphics/ecs/mesh-v2/sg_hierarchy_compute_bounding_box_via_parent_entity.d.ts +4 -0
  191. package/engine/graphics/ecs/sprite/Sprite.js +11 -0
  192. package/engine/graphics/ecs/sprite/SpriteSystemPE.js +133 -0
  193. package/engine/graphics/ecs/sprite/prototypeSpriteSystem.js +1570 -0
  194. package/engine/graphics/micron/build/PatchRepresentation.js +7 -3
  195. package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +18 -8
  196. package/engine/graphics/micron/build/clustering/build_clustering_2.js +1 -1
  197. package/engine/graphics/micron/build/clustering/build_leaf_patches.js +2 -2
  198. package/engine/graphics/micron/build/clustering/build_leaf_patches_metis.js +1 -1
  199. package/engine/graphics/micron/build/hierarchy/buildAbstractPatchHierarchy.js +21 -3
  200. package/engine/graphics/micron/build/hierarchy/merge_patches.js +96 -43
  201. package/engine/graphics/micron/build/hierarchy/qvdr_build_simplified_clusters.js +11 -5
  202. package/engine/graphics/micron/format/VirtualGeometry.js +46 -3
  203. package/engine/graphics/micron/format/micron_build_proxy_geometry.js +4 -2
  204. package/engine/graphics/micron/prototypeVirtualGeometry.js +47 -10
  205. package/engine/graphics/micron/render/instanced/shader/shader_rewrite_standard.js +17 -17
  206. package/engine/graphics/micron/render/refinement/get_geometry_patch_cut.js +15 -3
  207. package/engine/graphics/micron/simplifyGeometry.js +1 -1
  208. package/engine/graphics/particles/particular/engine/ParticularEngine.js +5 -0
  209. package/engine/graphics/particles/particular/engine/emitter/ParticleLayer.js +17 -9
  210. package/engine/graphics/particles/particular/engine/renderers/ParticleRenderer.js +12 -10
  211. package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +7 -2
  212. package/engine/graphics/particles/particular/engine/renderers/billboard/SoftBillboardParticlePool.js +27 -0
  213. package/engine/graphics/particles/particular/engine/renderers/billboard/SoftBillboardParticleRenderer.js +80 -0
  214. package/engine/graphics/particles/particular/engine/shader/ShaderManager.js +16 -4
  215. package/engine/graphics/shaders/TerrainShader.js +8 -8
  216. package/engine/graphics/texture/atlas/TextureAtlasDebugger.js +2 -1
  217. package/engine/graphics/texture/sampler/Sampler2D.js +206 -201
  218. package/engine/graphics/texture/sampler/Sampler2D.spec.js +34 -35
  219. package/engine/graphics/texture/sampler/bicubic.js +59 -0
  220. package/engine/graphics/texture/sampler/downsampleSample2D.spec.js +2 -2
  221. package/engine/graphics/texture/sampler/genericResampleSampler2D.js +0 -2
  222. package/engine/graphics/texture/sampler/prototypeSamplerFiltering.js +146 -0
  223. package/engine/graphics/texture/sampler/{downsampleSampler2D.js → sampler2D_scale_down_linear.js} +8 -4
  224. package/engine/graphics/texture/sampler/sampler2_d_scale_down_lanczos.js +140 -0
  225. package/engine/graphics/texture/sampler/scaleSampler2D.js +3 -3
  226. package/engine/graphics/texture/sampler/writeSampler2DDataToDataTexture.js +1 -1
  227. package/engine/graphics/util/ScaleObject3ToBox.js +14 -1
  228. package/engine/graphics/util/makeMeshPreviewScene.js +2 -1
  229. package/engine/grid/components/GridObstacle.js +0 -44
  230. package/engine/grid/components/GridObstacleSerializationAdapter.js +46 -0
  231. package/engine/input/devices/PointerDevice.d.ts +1 -1
  232. package/engine/input/devices/PointerDevice.js +17 -2
  233. package/engine/input/ecs/util/TerrainCameraTargetSampler.js +2 -2
  234. package/engine/navigation/ecs/components/Path.d.ts +2 -0
  235. package/engine/navigation/ecs/components/Path.js +6 -1
  236. package/engine/navigation/ecs/components/computeNonuniformCatmullRomSplineSample.js +117 -0
  237. package/engine/navigation/grid/AStar.js +1 -1
  238. package/engine/navigation/grid/GridField.js +3 -2
  239. package/engine/platform/GetURLHash.js +27 -0
  240. package/engine/platform/WebEnginePlatform.js +1 -22
  241. package/engine/sound/ecs/emitter/SoundEmitter.js +10 -6
  242. package/engine/ui/DraggableAspect.js +2 -2
  243. package/generation/GridGenerator.js +7 -6
  244. package/generation/example/SampleGenerator0.js +39 -35
  245. package/generation/example/filters/SampleGroundMoistureFilter.js +58 -17
  246. package/generation/example/generators/interactive/mir_generator_place_buff_objects.js +7 -6
  247. package/generation/example/generators/mir_generator_place_bases.js +7 -3
  248. package/generation/example/generators/mir_generator_place_road_decorators.js +3 -3
  249. package/generation/example/generators/mir_generator_place_starting_point.js +3 -2
  250. package/generation/example/themes/SampleTheme0.js +11 -7
  251. package/generation/filtering/numeric/CellFilterLiteralFloat.js +5 -0
  252. package/generation/filtering/numeric/complex/CellFilterDilate.js +36 -0
  253. package/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +15 -5
  254. package/generation/filtering/numeric/complex/CellFilterSimplexNoise.js +53 -1
  255. package/generation/filtering/numeric/math/CellFilterMax2.js +3 -0
  256. package/generation/filtering/numeric/math/CellFilterMembershipGeneralizedBell.js +55 -0
  257. package/generation/filtering/numeric/sampling/AbstractCellFilterSampleGridLayer.js +42 -0
  258. package/generation/filtering/numeric/sampling/CellFilterSampleLayerCubic.js +36 -0
  259. package/generation/filtering/numeric/sampling/CellFilterSampleLayerLinear.js +41 -0
  260. package/generation/grid/GridData.d.ts +5 -1
  261. package/generation/grid/GridData.js +35 -36
  262. package/generation/grid/MarkerMatchCounter.js +5 -3
  263. package/generation/grid/generation/discrete/GridTaskConnectRooms.js +1 -1
  264. package/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.js +1 -1
  265. package/generation/grid/generation/discrete/layer/GridTaskDistanceToMarkers.js +1 -1
  266. package/generation/grid/generation/road/GridTaskGenerateRoads.js +1 -1
  267. package/generation/markers/GridActionRuleSet.js +15 -32
  268. package/generation/markers/GridCellActionPlaceMarker.js +12 -8
  269. package/generation/markers/debug/visualizeMarkers.js +56 -36
  270. package/generation/markers/emitter/MarkerNodeEmitterFromAction.js +8 -8
  271. package/generation/markers/prototypeGridCellActionPlaceMarker.js +209 -0
  272. package/generation/markers/transform/MarkerNodeTransformerOffsetPosition.js +1 -5
  273. package/generation/markers/transform/MarkerNodeTransformerYRotateByFilterGradient.spec.js +2 -2
  274. package/generation/placement/GridCellPlacementRule.js +31 -25
  275. package/generation/theme/ThemeEngine.js +1 -1
  276. package/package.json +1 -1
  277. package/samples/terrain/from_image.js +7 -3
  278. package/samples/terrain/main.js +1 -1
  279. package/view/View.js +23 -1
  280. package/view/common/LabelView.js +1 -1
  281. package/view/compose3x3transform.js +32 -8
  282. package/view/controller/dat/DatGuiUtils.js +1 -1
  283. package/view/elements/DropDownSelectionView.js +11 -3
  284. package/view/elements/image/ImageView.js +3 -1
  285. package/core/model/ObservedReal.js +0 -55
  286. package/editor/ecs/component/ObjectEditor.js +0 -0
  287. package/engine/graphics/particles/particular/engine/renderers/SoftBillboardParticleRenderer.js +0 -7
  288. package/engine/sound/ecs/emitter/attenuate/attenuateSoundLinear.js +0 -11
  289. package/generation/filtering/numeric/CellFilterReadGridLayer.js +0 -73
@@ -1,52 +1,30 @@
1
1
  import EmptyView from "../../../view/elements/EmptyView.js";
2
+ import { FieldDescriptor } from "./FieldDescriptor.js";
3
+ import { FieldValueAdapter } from "./FieldValueAdapter.js";
4
+ import { createFieldEditor } from "./createFieldEditor.js";
5
+ import { findNearestRegisteredType } from "./findNearestRegisteredType.js";
2
6
  import LabelView from "../../../view/common/LabelView.js";
3
7
 
4
- class FieldValueAdapter {
5
- read(object, field_name) {
6
-
7
- }
8
-
9
- write(object, field_name, value) {
10
-
11
- }
12
- }
13
-
14
8
  /**
15
9
  * @template T
10
+ * @param {T|undefined} value
16
11
  */
17
- class FieldDescriptor {
18
- constructor() {
19
- /**
20
- *
21
- * @type {string}
22
- */
23
- this.name = "";
24
-
25
- /**
26
- * typeof field
27
- * @type {Class<T>}
28
- */
29
- this.type = null;
30
-
31
- /**
32
- *
33
- * @type {FieldValueAdapter|null}
34
- */
35
- this.adapter = null;
36
-
12
+ function objectToClass(value) {
13
+ if (value === null || value === undefined) {
14
+ return;
37
15
  }
38
- }
39
16
 
40
- /**
41
- * @template T
42
- * @param {T} value
43
- */
44
- function objectToClass(value) {
45
17
  const type = typeof value;
46
18
 
47
19
  switch (type) {
48
20
  case "object":
49
- return value.__ptoto__.constructor;
21
+ const proto = Object.getPrototypeOf(value);
22
+
23
+ if (proto === null) {
24
+ return;
25
+ }
26
+
27
+ return proto.constructor;
50
28
  case "boolean":
51
29
  return Boolean;
52
30
  case "function":
@@ -78,10 +56,37 @@ function isPublicField(object, field_name) {
78
56
  /**
79
57
  *
80
58
  * @param {Object} object
81
- * @returns {FieldDescriptor[]}
59
+ * @param {string} field_name
60
+ * @returns {boolean}
82
61
  */
83
- function extractObjectFields(object) {
84
- const result = [];
62
+ function isReservedField(object, field_name) {
63
+ if (field_name.startsWith('@')) {
64
+ return true;
65
+ }
66
+
67
+ return false;
68
+ }
69
+
70
+ /**
71
+ *
72
+ * @type {string[]}
73
+ */
74
+ const reserved_prototype_names = [
75
+ "constructor"
76
+ ];
77
+
78
+ const reserved_prototypes = [
79
+ Object,
80
+ Object.prototype
81
+ ];
82
+
83
+ /**
84
+ *
85
+ * @param {Object} object
86
+ * @param {FieldDescriptor[]} result
87
+ * @param {*} object_proto
88
+ */
89
+ function extract_object_fields_reflection(object, result, object_proto) {
85
90
  const keys = Object.keys(object);
86
91
 
87
92
  for (let i = 0; i < keys.length; i++) {
@@ -91,6 +96,10 @@ function extractObjectFields(object) {
91
96
  continue;
92
97
  }
93
98
 
99
+ if (isReservedField(object, key)) {
100
+ continue;
101
+ }
102
+
94
103
  const field_type = objectToClass(object[key]);
95
104
 
96
105
  if (field_type === undefined) {
@@ -100,56 +109,253 @@ function extractObjectFields(object) {
100
109
  const descriptor = new FieldDescriptor();
101
110
  descriptor.name = key;
102
111
  descriptor.type = field_type;
112
+ descriptor.adapter = new FieldValueAdapter();
103
113
 
104
114
  result.push(descriptor);
105
115
  }
106
116
 
107
- return result;
117
+ if (!reserved_prototypes.includes(object_proto)) {
118
+
119
+ const descriptors = Object.getOwnPropertyDescriptors(object_proto);
120
+
121
+ for (let d_name in descriptors) {
122
+
123
+ if (reserved_prototype_names.includes(d_name)) {
124
+ // reserved name, skip
125
+ continue;
126
+ }
127
+
128
+ const d = descriptors[d_name];
129
+
130
+ const adapter = new FieldValueAdapter();
131
+
132
+ if (d.get === undefined && d.value === undefined) {
133
+ adapter.readable = false;
134
+ }
135
+
136
+ if (d.get !== undefined && d.set === undefined) {
137
+ adapter.writable = false;
138
+ }
139
+
140
+ if (!adapter.readable) {
141
+ continue;
142
+ }
143
+
144
+
145
+ let field_value;
146
+
147
+ try {
148
+ field_value = adapter.read(object, d_name);
149
+ } catch (e) {
150
+ console.warn(e);
151
+ continue;
152
+ }
153
+
154
+ const field_type = objectToClass(field_value);
155
+
156
+ if (field_type === undefined) {
157
+ continue;
158
+ }
159
+
160
+ const descriptor = new FieldDescriptor();
161
+
162
+ descriptor.name = d_name;
163
+ descriptor.type = field_type;
164
+ descriptor.adapter = adapter;
165
+
166
+ result.push(descriptor);
167
+ }
168
+
169
+ }
108
170
  }
109
171
 
110
172
  /**
111
173
  *
112
174
  * @param {Object} object
113
- * @param {FieldDescriptor} field
114
- * @param {Map<*, (parent:*, field:FieldDescriptor)=>View>} registry
175
+ * @param {Map<*, TypeEditor>} registry
176
+ * @returns {FieldDescriptor[]}
115
177
  */
116
- export function createFieldEditor(object, field, registry) {
117
- const vResult = new EmptyView({});
178
+ function extractObjectFields(object, registry) {
118
179
 
119
- vResult.addChild(new LabelView(field.name));
180
+ const result = [];
120
181
 
121
- let vValue;
182
+ const object_proto = Object.getPrototypeOf(object);
183
+ const Klass = object_proto.constructor;
122
184
 
123
- const factory = registry.get(field.type);
185
+ const editor = registry.get(Klass);
186
+
187
+ if (!(editor?.schema?.additionalProperties === false)) {
188
+
189
+ extract_object_fields_reflection(object, result, object_proto);
124
190
 
125
- if (factory !== undefined) {
126
- vValue = factory(object, field);
127
- } else {
128
- vValue = createObjectEditor(object, registry);
129
191
  }
130
192
 
131
- vResult.addChild(vValue);
132
193
 
133
- return vResult;
194
+ if (editor !== undefined) {
195
+
196
+ const schema = editor.schema;
197
+
198
+ if (schema !== undefined) {
199
+ // has schema, apply
200
+ const prop_keys = Object.keys(schema.properties);
201
+
202
+ for (let i = 0; i < prop_keys.length; i++) {
203
+ const key = prop_keys[i];
204
+
205
+ const property = schema.properties[key];
206
+
207
+ const field_index = result.findIndex(a => a.name === key);
208
+
209
+ let field;
210
+
211
+ if (field_index === -1) {
212
+ // not in schema yet, build
213
+ field = new FieldDescriptor();
214
+ field.name = key;
215
+ field.adapter = new FieldValueAdapter();
216
+
217
+ result.push(field);
218
+ } else {
219
+ field = result[field_index];
220
+ }
221
+
222
+ let actual_type = field.type;
223
+
224
+ if (actual_type === undefined || actual_type === null) {
225
+ let actual_value;
226
+
227
+ try {
228
+ actual_value = field.adapter.read(object, key);
229
+ } catch (e) {
230
+ // silent failure
231
+ }
232
+
233
+ if (actual_value !== undefined && actual_value !== null) {
234
+ actual_type = objectToClass(actual_value);
235
+ }
236
+ }
237
+
238
+ if (property.type) {
239
+ // validate type
240
+ if (actual_type !== undefined && actual_type !== null) {
241
+ if (actual_type !== property.type) {
242
+ console.error(`Schema violation at field '${key}', schema type is different from actual type`, schema, actual_type);
243
+ }
244
+ }
245
+
246
+ field.type = property.type;
247
+ } else if (actual_type !== undefined && field.type !== actual_type) {
248
+ field.type = actual_type;
249
+ }
250
+
251
+
252
+ field.schema = property;
253
+
254
+ if (property.transient === true) {
255
+ // no point in editing transient
256
+ result.splice(field_index, 1);
257
+ }
258
+ }
259
+ }
260
+ }
261
+
262
+ return result;
134
263
  }
135
264
 
265
+ const build_path = [];
266
+ let build_path_offset = 0;
267
+
268
+
136
269
  /**
137
- *
138
270
  * @param {Object} object
139
- * @param {Map<*, (parent:*, field:FieldDescriptor)=>View>} registry
271
+ * @param {Map<*, TypeEditor>} registry
272
+ * @param {FieldDescriptor} [field_descriptor]
273
+ */
274
+ export function buildObjectEditorFromRegistry(object, registry, field_descriptor) {
275
+
276
+ const editor = findNearestRegisteredType(registry, object);
277
+
278
+ let fd;
279
+
280
+ if (field_descriptor === undefined) {
281
+
282
+ fd = new FieldDescriptor();
283
+ fd.adapter = new FieldValueAdapter();
284
+
285
+ fd.adapter.read = () => object;
286
+ fd.adapter.writable = false;
287
+
288
+ if (editor.schema) {
289
+ fd.schema = editor.schema;
290
+ }
291
+
292
+ } else {
293
+ fd = field_descriptor;
294
+ }
295
+
296
+ return editor.build(null, fd, registry);
297
+ }
298
+
299
+ const MAX_DEPTH = 7;
300
+
301
+ /**
302
+ * @param {Object} object
303
+ * @param {Map<*, TypeEditor>} registry
140
304
  */
141
305
  export function createObjectEditor(object, registry) {
142
- const fields = extractObjectFields(object);
143
306
 
144
- const vResult = new EmptyView({});
307
+ if (build_path_offset > MAX_DEPTH) {
308
+ // too deep
309
+ return undefined;
310
+ }
311
+
312
+ const seen_index = build_path.indexOf(object);
313
+ if (seen_index >= 0 && seen_index < build_path_offset) {
314
+ // recursion
315
+ return undefined;
316
+ }
317
+
318
+
319
+ build_path[build_path_offset++] = object;
320
+
321
+
322
+ const vResult = new EmptyView({
323
+ classList: ['auto-object-editor'],
324
+ css: {}
325
+ });
326
+
327
+
328
+ const fields = extractObjectFields(object, registry);
329
+
330
+ const field_views = [];
145
331
 
146
332
  for (let i = 0; i < fields.length; i++) {
147
333
  const field = fields[i];
148
334
 
149
- const vField = createFieldEditor(object, field, registry);
335
+ let vField;
336
+
337
+ try {
338
+ vField = createFieldEditor(object, field, registry);
339
+ } catch (e) {
340
+ vField = new LabelView('ERROR');
341
+ console.warn(e);
342
+ }
150
343
 
151
- vResult.addChild(vField);
344
+ if (vField === null) {
345
+ continue;
346
+ }
347
+
348
+ field_views.push(vField);
152
349
  }
153
350
 
351
+ build_path_offset--;
352
+
353
+ if (field_views.length === 0) {
354
+ // skip containers with no data
355
+ return null;
356
+ }
357
+
358
+ vResult.addChildren(field_views);
359
+
154
360
  return vResult;
155
361
  }
@@ -0,0 +1,39 @@
1
+ import { TypeEditor } from "../TypeEditor.js";
2
+ import EmptyView from "../../../../view/elements/EmptyView.js";
3
+ import { rgb2hex } from "../../../../core/color/rgb2hex.js";
4
+
5
+ export class ColorEditor extends TypeEditor {
6
+ build(parent, field) {
7
+
8
+ /**
9
+ * @type {Color}
10
+ */
11
+ const color = field.adapter.read(parent, field.name);
12
+
13
+ const view = new EmptyView({
14
+ tag: 'input'
15
+ });
16
+
17
+ view.attr({
18
+ type: "color"
19
+ });
20
+
21
+ function sync_up() {
22
+ view.attr({
23
+ value: `#${rgb2hex(color.r * 255, color.g * 255, color.b * 255)}`
24
+ })
25
+ }
26
+
27
+ function sync_down(e) {
28
+ const color_value = e.target.value;
29
+
30
+ color.parse(color_value);
31
+ }
32
+
33
+ view.on.linked.add(sync_up);
34
+ view.el.addEventListener('input', sync_down, false);
35
+ view.el.addEventListener('change', sync_down, false);
36
+
37
+ return view;
38
+ }
39
+ }
@@ -0,0 +1,17 @@
1
+ import { TypeEditor } from "../TypeEditor.js";
2
+ import View from "../../../../view/View.js";
3
+
4
+ export class HTMLElementEditor extends TypeEditor {
5
+ build(parent, field, registry) {
6
+ const el = field.adapter?.read(parent, field.name);
7
+
8
+ const view = new View();
9
+
10
+ view.el = el;
11
+
12
+ // make the size small
13
+ view.size.setScalar(32);
14
+
15
+ return view;
16
+ }
17
+ }
@@ -0,0 +1,50 @@
1
+ import { TypeEditor } from "../TypeEditor.js";
2
+ import { StringEditor } from "./primitive/StringEditor.js";
3
+ import EmptyView from "../../../../view/elements/EmptyView.js";
4
+ import ImageView from "../../../../view/elements/image/ImageView.js";
5
+ import ObservedString from "../../../../core/model/ObservedString.js";
6
+ import { ObservedStringEditor } from "./ObservedStringEditor.js";
7
+
8
+ export class ImagePathEditor extends TypeEditor {
9
+ inline = true;
10
+
11
+ build(parent, field, registry) {
12
+ let url_editor;
13
+
14
+ if (field.type === String) {
15
+
16
+ url_editor = new StringEditor();
17
+
18
+ } else if (field.type === ObservedString) {
19
+
20
+ url_editor = new ObservedStringEditor();
21
+
22
+ } else {
23
+ throw new Error(`Unsupported type`);
24
+ }
25
+
26
+ const vEditor = url_editor.build(parent, field, registry);
27
+
28
+ const r = new EmptyView({
29
+ css: {
30
+ display: "flex",
31
+ flexDirection: "row"
32
+ }
33
+ });
34
+
35
+ const vPreview = new ImageView(field.adapter.read(parent, field.name));
36
+
37
+ vPreview.size.set(32, 32);
38
+
39
+ function update() {
40
+ vPreview.__setSource(vEditor.el.value);
41
+ }
42
+
43
+ r.addChild(vPreview);
44
+ r.addChild(vEditor);
45
+
46
+ vEditor.el.addEventListener('input', update);
47
+
48
+ return r;
49
+ }
50
+ }
@@ -0,0 +1,86 @@
1
+ import { TypeEditor } from "../TypeEditor.js";
2
+ import EmptyView from "../../../../view/elements/EmptyView.js";
3
+ import { NumberController } from "../../../view/ecs/components/common/NumberController.js";
4
+ import LabelView from "../../../../view/common/LabelView.js";
5
+
6
+ export class NumericIntervalEditor extends TypeEditor {
7
+ build(parent, field, registry) {
8
+
9
+ /**
10
+ * @type {NumericInterval}
11
+ */
12
+ const interval = field.adapter?.read(parent, field.name);
13
+
14
+ const r = new EmptyView({
15
+ classList: ["inline-field-row-editor"]
16
+ });
17
+
18
+ const c_0 = new NumberController({ value: interval.min });
19
+ const c_1 = new NumberController({ value: interval.max });
20
+
21
+
22
+ r.addChild(new LabelView("min"))
23
+ r.addChild(c_0);
24
+ r.addChild(new LabelView("max"))
25
+ r.addChild(c_1);
26
+
27
+ let lock = false;
28
+
29
+ const sync_up = () => {
30
+ if (lock) {
31
+ return;
32
+ }
33
+
34
+ lock = true;
35
+
36
+ c_0.value.set(interval.min);
37
+ c_1.value.set(interval.max);
38
+
39
+ lock = false;
40
+ };
41
+
42
+ const sync_down = () => {
43
+
44
+ if (lock) {
45
+ return;
46
+ }
47
+
48
+ lock = true;
49
+
50
+ const v0 = c_0.value.getValue();
51
+ const v1 = c_1.value.getValue();
52
+
53
+ if (v0 <= v1) {
54
+
55
+ interval.set(
56
+ v0,
57
+ v1,
58
+ );
59
+ }
60
+
61
+ lock = false;
62
+ };
63
+
64
+ r.on.linked.add(sync_up);
65
+
66
+ r.bindSignal(interval.onChanged, sync_up);
67
+
68
+ r.bindSignal(c_0.value.onChanged, sync_down);
69
+ r.bindSignal(c_1.value.onChanged, sync_down);
70
+
71
+
72
+ const validate = () => {
73
+ // validation
74
+
75
+ if (c_0.value.getValue() > c_1.value.getValue()) {
76
+ // restore
77
+ sync_up();
78
+ }
79
+ };
80
+
81
+ c_0.el.addEventListener('blur', validate);
82
+ c_1.el.addEventListener('blur', validate);
83
+
84
+ return r;
85
+ }
86
+ }
@@ -0,0 +1,13 @@
1
+ import { TypeEditor } from "../TypeEditor.js";
2
+ import { CheckboxView } from "../../../../view/elements/CheckboxView.js";
3
+
4
+ export class ObservedBooleanEditor extends TypeEditor {
5
+ build(parent, field, registry) {
6
+
7
+ const ctrl = new CheckboxView({
8
+ value: field.adapter.read(parent, field.name)
9
+ });
10
+
11
+ return ctrl;
12
+ }
13
+ }
@@ -0,0 +1,32 @@
1
+ import { TypeEditor } from "../TypeEditor.js";
2
+ import DropDownSelectionView from "../../../../view/elements/DropDownSelectionView.js";
3
+ import List from "../../../../core/collection/list/List.js";
4
+ import { objectKeyByValue } from "../../../../core/model/object/objectKeyByValue.js";
5
+
6
+ export class ObservedEnumEditor extends TypeEditor {
7
+ build(parent, field, registry) {
8
+
9
+ /**
10
+ * @type {ObservedEnum}
11
+ */
12
+ const value = field.adapter.read(parent, field.name);
13
+
14
+ const valueSet = value.getValidValueSet();
15
+
16
+ const ctrl = new DropDownSelectionView(
17
+ new List(Object.keys(valueSet)), {
18
+ changeListener(key) {
19
+ const v = valueSet[key];
20
+
21
+ value.set(v);
22
+ }
23
+ }
24
+ );
25
+
26
+ ctrl.on.linked.add(() => {
27
+ ctrl.setSelectedValue(objectKeyByValue(valueSet, value.getValue()));
28
+ })
29
+
30
+ return ctrl;
31
+ }
32
+ }
@@ -0,0 +1,43 @@
1
+ import { TypeEditor } from "../TypeEditor.js";
2
+ import { NumberController } from "../../../view/ecs/components/common/NumberController.js";
3
+
4
+ export class ObservedIntegerEditor extends TypeEditor {
5
+ build(parent, field, registry) {
6
+ const instance = field.adapter.read(parent, field.name);
7
+ const ctrl = new NumberController();
8
+
9
+ let lock = false;
10
+
11
+ function sync_down() {
12
+
13
+ if (lock) {
14
+ return;
15
+ }
16
+
17
+ lock = true;
18
+
19
+ instance.set(ctrl.value.getValue());
20
+
21
+ lock = false;
22
+ }
23
+
24
+ function sync_up() {
25
+ if (lock) {
26
+ return;
27
+ }
28
+
29
+ lock = true;
30
+
31
+ ctrl.value.set(instance.getValue());
32
+
33
+ lock = false;
34
+ }
35
+
36
+ ctrl.on.linked.add(sync_up);
37
+
38
+ ctrl.value.onChanged.add(sync_down);
39
+ ctrl.bindSignal(instance.onChanged, sync_up);
40
+
41
+ return ctrl;
42
+ }
43
+ }