@woosh/meep-engine 3.16.0 → 3.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -72
- package/editor/particles/effect/ParticleEffectDocument.d.ts +21 -6
- package/editor/particles/effect/ParticleEffectDocument.d.ts.map +1 -1
- package/editor/particles/effect/ParticleEffectDocument.js +38 -17
- package/editor/view/node-graph/NodeGraphClipboard.d.ts +186 -0
- package/editor/view/node-graph/NodeGraphClipboard.d.ts.map +1 -0
- package/editor/view/node-graph/NodeGraphClipboard.js +231 -0
- package/editor/view/node-graph/NodeGraphEditorView.d.ts +59 -1
- package/editor/view/node-graph/NodeGraphEditorView.d.ts.map +1 -1
- package/editor/view/node-graph/NodeGraphEditorView.js +248 -5
- package/editor/view/node-graph/NodeGraphView.d.ts.map +1 -1
- package/editor/view/node-graph/NodeGraphView.js +84 -8
- package/editor/view/node-graph/actions/connection_bind_actions.d.ts +23 -0
- package/editor/view/node-graph/actions/connection_bind_actions.d.ts.map +1 -0
- package/editor/view/node-graph/actions/connection_bind_actions.js +39 -0
- package/editor/view/particles/effect/ParticleCodeEditorView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleCodeEditorView.js +4 -3
- package/editor/view/particles/effect/ParticleCurveEditorView.d.ts +20 -0
- package/editor/view/particles/effect/ParticleCurveEditorView.d.ts.map +1 -0
- package/editor/view/particles/effect/ParticleCurveEditorView.js +574 -0
- package/editor/view/particles/effect/ParticleEmitterInspectorView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleEmitterInspectorView.js +27 -1
- package/editor/view/particles/effect/ParticleGradientEditorView.d.ts +24 -0
- package/editor/view/particles/effect/ParticleGradientEditorView.d.ts.map +1 -0
- package/editor/view/particles/effect/ParticleGradientEditorView.js +472 -0
- package/editor/view/particles/effect/ParticleGraphEditorView.d.ts +5 -0
- package/editor/view/particles/effect/ParticleGraphEditorView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleGraphEditorView.js +61 -31
- package/editor/view/particles/effect/ParticleNodeParametersView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleNodeParametersView.js +33 -0
- package/editor/view/particles/effect/particle-editor.css +123 -35
- package/package.json +1 -1
- package/src/core/binary/allocator/OffsetAllocator.d.ts +25 -16
- package/src/core/binary/allocator/OffsetAllocator.d.ts.map +1 -1
- package/src/core/binary/allocator/OffsetAllocator.js +10 -1
- package/src/core/collection/array/typed/float32_array_hash.d.ts +21 -0
- package/src/core/collection/array/typed/float32_array_hash.d.ts.map +1 -0
- package/src/core/collection/array/typed/float32_array_hash.js +38 -0
- package/src/core/graph/csr/CSRGraph.d.ts +8 -1
- package/src/core/graph/csr/CSRGraph.d.ts.map +1 -1
- package/src/core/graph/csr/CSRGraph.js +14 -6
- package/src/core/model/node-graph/visual/layout/LayoutProblem.d.ts +24 -0
- package/src/core/model/node-graph/visual/layout/LayoutProblem.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/LayoutProblem.js +27 -0
- package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts +26 -0
- package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.js +28 -0
- package/src/core/model/node-graph/visual/layout/RouteGrid.d.ts +92 -3
- package/src/core/model/node-graph/visual/layout/RouteGrid.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/RouteGrid.js +405 -242
- package/src/core/model/node-graph/visual/layout/RouteSearch.d.ts +50 -5
- package/src/core/model/node-graph/visual/layout/RouteSearch.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/RouteSearch.js +160 -24
- package/src/core/model/node-graph/visual/layout/RouteSet.d.ts +7 -0
- package/src/core/model/node-graph/visual/layout/RouteSet.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/RouteSet.js +8 -0
- package/src/core/model/node-graph/visual/layout/layout_assign_coordinates.js +9 -3
- package/src/core/model/node-graph/visual/layout/layout_build_problem.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/layout_build_problem.js +7 -0
- package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts +9 -3
- package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/layout_insert_lanes.js +17 -3
- package/src/core/model/node-graph/visual/layout/layout_node_graph.d.ts +9 -6
- package/src/core/model/node-graph/visual/layout/layout_node_graph.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/layout_node_graph.js +49 -7
- package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts +11 -1
- package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/layout_order_layers.js +135 -16
- package/src/core/model/node-graph/visual/layout/route_connections.d.ts +29 -0
- package/src/core/model/node-graph/visual/layout/route_connections.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/route_connections.js +716 -309
- package/src/core/model/node-graph/visual/layout/route_grid_build.d.ts +3 -2
- package/src/core/model/node-graph/visual/layout/route_grid_build.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/route_grid_build.js +7 -15
- package/src/core/model/node-graph/visual/layout/route_nudge.d.ts +6 -0
- package/src/core/model/node-graph/visual/layout/route_nudge.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/route_nudge.js +42 -13
- package/src/engine/animation/AnimationUtils.js +246 -246
- package/src/engine/animation/Animations.js +74 -74
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +2078 -2078
- package/src/engine/ecs/EventType.d.ts +0 -1
- package/src/engine/ecs/EventType.js +1 -26
- package/src/engine/ecs/ik/ik_write_local_rotation.d.ts +1 -1
- package/src/engine/ecs/ik/ik_write_local_rotation.d.ts.map +1 -1
- package/src/engine/ecs/ik/ik_write_local_rotation.js +3 -7
- package/src/engine/ecs/parent/EntityNode.d.ts.map +1 -1
- package/src/engine/ecs/parent/EntityNode.js +4 -9
- package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.d.ts.map +1 -1
- package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +360 -364
- package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.d.ts +41 -0
- package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.d.ts.map +1 -0
- package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.js +40 -0
- package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +8 -0
- package/src/engine/ecs/transform/t64_announce_change.d.ts +10 -7
- package/src/engine/ecs/transform/t64_announce_change.d.ts.map +1 -1
- package/src/engine/ecs/transform/t64_announce_change.js +12 -12
- package/src/engine/ecs/transform/t64_set_rotation_axis_angle.d.ts +25 -0
- package/src/engine/ecs/transform/t64_set_rotation_axis_angle.d.ts.map +1 -0
- package/src/engine/ecs/transform/t64_set_rotation_axis_angle.js +45 -0
- package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.d.ts +30 -0
- package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.d.ts.map +1 -0
- package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.js +29 -0
- package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.d.ts.map +1 -1
- package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +13 -21
- package/src/engine/graphics/ecs/sprite/SpriteSystemPE.d.ts.map +1 -1
- package/src/engine/graphics/ecs/sprite/SpriteSystemPE.js +4 -8
- package/src/engine/graphics3/LightSystem.d.ts.map +1 -1
- package/src/engine/graphics3/LightSystem.js +4 -8
- package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
- package/src/engine/graphics3/MeshSystem.js +9 -19
- package/src/engine/graphics3/ParticleEmitterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/ParticleEmitterSystem.js +4 -8
- package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
- package/src/engine/graphics3/ShadedGeometrySystem.js +4 -10
- package/src/engine/grid/transform2grid/Transform2GridPositionSystem.d.ts +1 -1
- package/src/engine/grid/transform2grid/Transform2GridPositionSystem.d.ts.map +1 -1
- package/src/engine/grid/transform2grid/Transform2GridPositionSystem.js +4 -8
- package/src/engine/intelligence/behavior/ecs/OrbitingBehavior.js +218 -218
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +2 -5
- package/src/engine/sound/ecs/SoundListenerSystem.d.ts.map +1 -1
- package/src/engine/sound/ecs/SoundListenerSystem.js +6 -8
- package/src/engine/sound/simulation/AcousticSimulator.d.ts +11 -8
- package/src/engine/sound/simulation/AcousticSimulator.d.ts.map +1 -1
- package/src/engine/sound/simulation/AcousticSimulator.js +45 -36
- package/src/engine/sound/simulation/README.md +2 -2
- package/src/engine/sound/simulation/core/OcclusionSolver.d.ts.map +1 -1
- package/src/engine/sound/simulation/core/VolumeField.d.ts +9 -9
- package/src/engine/sound/simulation/core/VolumeField.d.ts.map +1 -1
- package/src/engine/sound/simulation/core/VolumeField.js +29 -13
- package/src/engine/sound/simulation/core/acoustic_occlusion_solve.d.ts +31 -0
- package/src/engine/sound/simulation/core/acoustic_occlusion_solve.d.ts.map +1 -0
- package/src/engine/sound/simulation/core/acoustic_occlusion_solve.js +134 -0
- package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts +0 -4
- package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts.map +1 -1
- package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.js +5 -11
- package/src/shade/playground/particle_editor/README.md +43 -2
- package/src/shade/playground/particle_system/particle_prototype.d.ts.map +1 -1
- package/src/shade/playground/particle_system/particle_prototype.js +4 -5
- package/src/shade/playground/particle_system/particle_scene.js +4 -4
- package/src/shade/playground/volumetrics_froxel/main.d.ts.map +1 -1
- package/src/shade/playground/volumetrics_froxel/main.js +6 -1
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +13 -1
- package/src/shade/renderer/particles/DESIGN.md +104 -19
- package/src/shade/renderer/particles/GPUParticleSystem.d.ts +64 -50
- package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
- package/src/shade/renderer/particles/GPUParticleSystem.js +176 -78
- package/src/shade/renderer/particles/ParticleConstants.d.ts +59 -23
- package/src/shade/renderer/particles/ParticleConstants.d.ts.map +1 -1
- package/src/shade/renderer/particles/ParticleConstants.js +66 -23
- package/src/shade/renderer/particles/ParticleRenderMode.d.ts +19 -0
- package/src/shade/renderer/particles/ParticleRenderMode.d.ts.map +1 -0
- package/src/shade/renderer/particles/ParticleRenderMode.js +33 -0
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.js +167 -166
- package/src/shade/renderer/particles/data/particle_emitter_record.d.ts +37 -0
- package/src/shade/renderer/particles/data/particle_emitter_record.d.ts.map +1 -0
- package/src/shade/renderer/particles/data/particle_emitter_record.js +109 -0
- package/src/shade/renderer/particles/graph/ParticleGroupBuilder.d.ts +3 -3
- package/src/shade/renderer/particles/graph/ParticleGroupBuilder.js +303 -303
- package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts +18 -0
- package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/ParticleNodeDescription.js +152 -133
- package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts +0 -11
- package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/ParticleNodeRegistry.js +720 -621
- package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/compile_particle_graph.js +8 -3
- package/src/shade/renderer/particles/graph/flatten_particle_graph.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/flatten_particle_graph.js +244 -213
- package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.js +6 -0
- package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.js +294 -319
- package/src/shade/renderer/particles/graph/groups/particle_groups_noise.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/groups/particle_groups_noise.js +524 -517
- package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.d.ts +22 -0
- package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.d.ts.map +1 -0
- package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.js +517 -0
- package/src/shade/renderer/particles/graph/groups/simplex_reference.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/groups/simplex_reference.js +185 -159
- package/src/shade/renderer/particles/graph/make_particle_group.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/make_particle_group.js +2 -20
- package/src/shade/renderer/particles/graph/particle_compare_ops.d.ts +17 -0
- package/src/shade/renderer/particles/graph/particle_compare_ops.d.ts.map +1 -0
- package/src/shade/renderer/particles/graph/particle_compare_ops.js +22 -0
- package/src/shade/renderer/particles/graph/particle_graph_diagnostic.d.ts +28 -8
- package/src/shade/renderer/particles/graph/particle_graph_diagnostic.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/particle_graph_diagnostic.js +49 -25
- package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts +40 -0
- package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/particle_node_parameters.js +312 -234
- package/src/shade/renderer/particles/graph/particle_node_presentation.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/particle_node_presentation.js +59 -3
- package/src/shade/renderer/particles/graph/particle_ramp.d.ts +230 -0
- package/src/shade/renderer/particles/graph/particle_ramp.d.ts.map +1 -0
- package/src/shade/renderer/particles/graph/particle_ramp.js +403 -0
- package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts +7 -1
- package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/validate_particle_graph.js +66 -10
- package/src/shade/renderer/particles/graph_particles.d.ts +23 -69
- package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph_particles.js +105 -262
- package/src/shade/renderer/particles/graph_particles_avboit.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph_particles_avboit.js +3 -2
- package/src/shade/renderer/particles/graph_particles_billboard.d.ts +37 -0
- package/src/shade/renderer/particles/graph_particles_billboard.d.ts.map +1 -0
- package/src/shade/renderer/particles/graph_particles_billboard.js +93 -0
- package/src/shade/renderer/particles/isa/InstructionStream.d.ts +51 -22
- package/src/shade/renderer/particles/isa/InstructionStream.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/InstructionStream.js +98 -38
- package/src/shade/renderer/particles/isa/ParticleProgram.d.ts +49 -8
- package/src/shade/renderer/particles/isa/ParticleProgram.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/ParticleProgram.js +95 -150
- package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts +306 -64
- package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/ParticleVMISA.js +505 -136
- package/src/shade/renderer/particles/isa/particle_assembly.d.ts +36 -12
- package/src/shade/renderer/particles/isa/particle_assembly.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/particle_assembly.js +354 -139
- package/src/shade/renderer/particles/isa/validate_particle_program.d.ts +9 -0
- package/src/shade/renderer/particles/isa/validate_particle_program.d.ts.map +1 -0
- package/src/shade/renderer/particles/isa/validate_particle_program.js +128 -0
- package/src/shade/renderer/particles/layout/ParticleLayout.d.ts +23 -0
- package/src/shade/renderer/particles/layout/ParticleLayout.d.ts.map +1 -1
- package/src/shade/renderer/particles/layout/ParticleLayout.js +68 -0
- package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.d.ts +77 -0
- package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.js +219 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts +83 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.js +283 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts +133 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.js +334 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.d.ts +117 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.js +70 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.d.ts +97 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.js +462 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.d.ts +116 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.js +687 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts +57 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.js +860 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.d.ts +115 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.js +264 -0
- package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts +81 -42
- package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/optimize_particle_program.js +477 -478
- package/src/shade/renderer/particles/optimizer/particle_integer_bounds.d.ts +100 -0
- package/src/shade/renderer/particles/optimizer/particle_integer_bounds.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/particle_integer_bounds.js +236 -0
- package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts +139 -59
- package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/particle_program_analysis.js +764 -647
- package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts +40 -7
- package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/particle_program_equivalence.js +376 -213
- package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts +30 -3
- package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/particle_program_fuzz.js +337 -223
- package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts +24 -38
- package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/particle_vm_semantics.js +166 -206
- package/src/shade/renderer/particles/optimizer/pass_allocate_registers.d.ts +99 -0
- package/src/shade/renderer/particles/optimizer/pass_allocate_registers.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/pass_allocate_registers.js +313 -0
- package/src/shade/renderer/particles/optimizer/pass_dedup_constants.d.ts +3 -2
- package/src/shade/renderer/particles/optimizer/pass_dedup_constants.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_dedup_constants.js +198 -197
- package/src/shade/renderer/particles/optimizer/pass_eliminate_dead_code.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts +19 -0
- package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_fold_constants.js +678 -561
- package/src/shade/renderer/particles/optimizer/pass_inline_constants.d.ts +22 -0
- package/src/shade/renderer/particles/optimizer/pass_inline_constants.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/pass_inline_constants.js +221 -0
- package/src/shade/renderer/particles/optimizer/pass_narrow_widths.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_narrow_widths.js +63 -72
- package/src/shade/renderer/particles/optimizer/pass_pack_registers.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_pack_registers.js +87 -86
- package/src/shade/renderer/particles/optimizer/pass_peephole.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_peephole.js +392 -271
- package/src/shade/renderer/particles/optimizer/pass_propagate_copies.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_propagate_copies.js +361 -268
- package/src/shade/renderer/particles/optimizer/pass_schedule.d.ts +4 -0
- package/src/shade/renderer/particles/optimizer/pass_schedule.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/pass_schedule.js +244 -0
- package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.js +154 -151
- package/src/shade/renderer/particles/particle_test_fixtures.d.ts +20 -0
- package/src/shade/renderer/particles/particle_test_fixtures.d.ts.map +1 -1
- package/src/shade/renderer/particles/particle_test_fixtures.js +229 -203
- package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts +99 -25
- package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts.map +1 -1
- package/src/shade/renderer/particles/runtime/EmitterRegistry.js +438 -286
- package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts +109 -0
- package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts.map +1 -0
- package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.js +127 -0
- package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +87 -102
- package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
- package/src/shade/renderer/particles/runtime/ParticleEmitter.js +184 -163
- package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts +130 -0
- package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts.map +1 -0
- package/src/shade/renderer/particles/runtime/ProgramHeap.js +595 -0
- package/src/shade/renderer/particles/runtime/ProgramPlacement.d.ts +91 -0
- package/src/shade/renderer/particles/runtime/ProgramPlacement.d.ts.map +1 -0
- package/src/shade/renderer/particles/runtime/ProgramPlacement.js +106 -0
- package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts +5 -2
- package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts.map +1 -1
- package/src/shade/renderer/particles/runtime/create_particle_effect.js +22 -19
- package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.d.ts +28 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.d.ts.map +1 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.js +136 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.d.ts +35 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.d.ts.map +1 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.js +133 -0
- package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts +18 -9
- package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.js +20 -80
- package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts +33 -0
- package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts.map +1 -0
- package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.js +114 -0
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts +8 -0
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +33 -101
- package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts +45 -0
- package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts.map +1 -0
- package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.js +123 -0
- package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts +51 -0
- package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts.map +1 -0
- package/src/shade/renderer/particles/sort/graph_particle_sort.js +120 -0
- package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.d.ts +6 -0
- package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.js +16 -0
- package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts +4 -1
- package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts.map +1 -1
- package/src/shade/renderer/particles/vm/ParticleVMReference.js +261 -140
- package/src/shade/renderer/particles/vm/chunk_particle_vm.d.ts.map +1 -1
- package/src/shade/renderer/particles/vm/chunk_particle_vm.js +217 -255
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.d.ts +43 -0
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.d.ts.map +1 -0
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.js +55 -0
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.d.ts +62 -0
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.d.ts.map +1 -0
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.js +86 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.d.ts +22 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.js +32 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.d.ts +9 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.js +19 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/README.md +65 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.d.ts +24 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.js +83 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.d.ts +25 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.js +42 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.d.ts +31 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.js +80 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.d.ts +26 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.js +109 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.d.ts +38 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.js +129 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.d.ts +21 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.js +35 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.d.ts +19 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.js +28 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.d.ts +13 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.js +22 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.d.ts +22 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.js +59 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.d.ts +23 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.js +74 -0
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts +7 -0
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.js +7 -0
- package/src/shade/wgsl/emulator/ComputeShaderEmulator.d.ts +34 -1
- package/src/shade/wgsl/emulator/ComputeShaderEmulator.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/ComputeShaderEmulator.js +41 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts +3 -2
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +49 -10
- package/src/view/minimap/dom/MinimapCameraView.d.ts.map +1 -1
- package/src/view/minimap/dom/MinimapCameraView.js +4 -9
- package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts +0 -15
- package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts.map +0 -1
- package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.d.ts +0 -45
- package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.d.ts.map +0 -1
- package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.d.ts +0 -24
- package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.d.ts.map +0 -1
- package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.d.ts +0 -19
- package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.d.ts.map +0 -1
- package/src/engine/ecs/transform/__probe.d.ts +0 -4
- package/src/engine/ecs/transform/__probe.d.ts.map +0 -1
- package/src/engine/ecs/util/hideEntityGracefully.d.ts +0 -9
- package/src/engine/ecs/util/hideEntityGracefully.d.ts.map +0 -1
- package/src/engine/sound/simulation/core/OcclusionSolver.js +0 -112
- package/src/shade/renderer/buffer/table/gpu_database_emulator_image.d.ts +0 -27
- package/src/shade/renderer/buffer/table/gpu_database_emulator_image.d.ts.map +0 -1
- package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts +0 -14
- package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts.map +0 -1
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_LAYOUT.d.ts +0 -156
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_LAYOUT.d.ts.map +0 -1
- package/src/shade/renderer/particles/runtime/Emitter.d.ts +0 -219
- package/src/shade/renderer/particles/runtime/Emitter.d.ts.map +0 -1
- package/src/shade/renderer/particles/runtime/ParticleSpawnScheduler.d.ts +0 -77
- package/src/shade/renderer/particles/runtime/ParticleSpawnScheduler.d.ts.map +0 -1
- package/src/shade/renderer/particles/runtime/ProgramArena.d.ts +0 -89
- package/src/shade/renderer/particles/runtime/ProgramArena.d.ts.map +0 -1
- package/src/shade/renderer/particles/runtime/ProgramArena.js +0 -155
- package/src/shade/renderer/particles/runtime/emitter_database_image.d.ts +0 -15
- package/src/shade/renderer/particles/runtime/emitter_database_image.d.ts.map +0 -1
- package/src/shade/renderer/particles/runtime/spawn_request_encoding.d.ts +0 -34
- package/src/shade/renderer/particles/runtime/spawn_request_encoding.d.ts.map +0 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_context.d.ts +0 -32
- package/src/shade/renderer/particles/shaders/chunk_particle_context.d.ts.map +0 -1
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
import { hex_to_rgb } from "../../../../src/core/color/hex/hex_to_rgb.js";
|
|
2
|
+
import { rgb_to_hex } from "../../../../src/core/color/hex/rgb_to_hex.js";
|
|
3
|
+
import { clamp01 } from "../../../../src/core/math/clamp01.js";
|
|
4
|
+
import { particle_gradient_sample } from "../../../../src/shade/renderer/particles/graph/particle_ramp.js";
|
|
5
|
+
import View from "../../../../src/view/View.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A colour gradient, edited the way everybody edits one: a strip of the colour it produces, with the
|
|
9
|
+
* stops that make it sitting under it.
|
|
10
|
+
*
|
|
11
|
+
* Drag a stop to move it. Click the lane under the strip where there is no stop and one is added
|
|
12
|
+
* there, in the colour the gradient already is at that point — so adding a stop never changes the
|
|
13
|
+
* gradient, it only gives you somewhere to change it *from*. Middle-click a stop, or press the
|
|
14
|
+
* remove button, and it goes. The swatch and the fields below edit whichever stop is selected.
|
|
15
|
+
*
|
|
16
|
+
* There is nothing clever here and that is deliberate: this control exists in Photoshop, in every
|
|
17
|
+
* game engine and in every vector editor, it works the same way in all of them, and an author should
|
|
18
|
+
* not have to find out how this one is different.
|
|
19
|
+
*
|
|
20
|
+
* ## When an edit is committed
|
|
21
|
+
*
|
|
22
|
+
* On pointer *up*, not on every move. Each commit is one entry on the editor's undo timeline, and a
|
|
23
|
+
* stop dragged across the strip is one edit an author means to undo once — not the ninety pointer
|
|
24
|
+
* events it was made of. The strip redraws continuously while the drag is happening, so it looks
|
|
25
|
+
* live; it is only the timeline that waits.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/** How wide the strip is drawn, in CSS pixels. @type {number} */
|
|
29
|
+
const WIDTH = 208;
|
|
30
|
+
|
|
31
|
+
/** How tall the colour strip is. @type {number} */
|
|
32
|
+
const STRIP_HEIGHT = 24;
|
|
33
|
+
|
|
34
|
+
/** How tall the lane of stop markers under it is. @type {number} */
|
|
35
|
+
const LANE_HEIGHT = 13;
|
|
36
|
+
|
|
37
|
+
/** How near a stop marker a press has to be to take hold of it rather than make a new one. */
|
|
38
|
+
const GRAB_RADIUS = 7;
|
|
39
|
+
|
|
40
|
+
/** Squares of the checkerboard drawn behind the strip, so alpha reads as transparency. */
|
|
41
|
+
const CHECKER = 6;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {number} channel `0..1`
|
|
45
|
+
* @returns {number} `0..255`
|
|
46
|
+
*/
|
|
47
|
+
function byte_of(channel) {
|
|
48
|
+
return Math.round(clamp01(channel) * 255);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export class ParticleGradientEditorView extends View {
|
|
52
|
+
/**
|
|
53
|
+
* The stops being edited. A working copy: it is what is drawn, and it becomes the parameter when
|
|
54
|
+
* an edit is committed.
|
|
55
|
+
* @type {import("../../../../src/shade/renderer/particles/graph/particle_ramp.js").ParticleGradientStop[]}
|
|
56
|
+
*/
|
|
57
|
+
#stops = [];
|
|
58
|
+
|
|
59
|
+
/** @type {HTMLCanvasElement} */
|
|
60
|
+
#canvas;
|
|
61
|
+
|
|
62
|
+
/** @type {CanvasRenderingContext2D|null} */
|
|
63
|
+
#context = null;
|
|
64
|
+
|
|
65
|
+
/** @type {number} which stop the swatch and the fields below are about */
|
|
66
|
+
#selected = 0;
|
|
67
|
+
|
|
68
|
+
/** @type {boolean} */
|
|
69
|
+
#dragging = false;
|
|
70
|
+
|
|
71
|
+
/** @type {function(Array):void} */
|
|
72
|
+
#write;
|
|
73
|
+
|
|
74
|
+
/** @type {function():Array} */
|
|
75
|
+
#read;
|
|
76
|
+
|
|
77
|
+
/** @type {boolean} whether this gradient's alpha is read by the node it belongs to */
|
|
78
|
+
#has_alpha;
|
|
79
|
+
|
|
80
|
+
/** @type {HTMLInputElement} */
|
|
81
|
+
#swatch;
|
|
82
|
+
|
|
83
|
+
/** @type {HTMLInputElement} */
|
|
84
|
+
#alpha;
|
|
85
|
+
|
|
86
|
+
/** @type {HTMLInputElement} */
|
|
87
|
+
#position;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @param {object} options
|
|
91
|
+
* @param {function():Array} options.read the parameter's current value
|
|
92
|
+
* @param {function(Array):void} options.write commit a new value
|
|
93
|
+
* @param {boolean} [options.alpha] whether the node reads the alpha channel; an RGB gradient
|
|
94
|
+
* still *stores* one — see {@link ./particle_ramp.js} — but does not offer it for editing
|
|
95
|
+
*/
|
|
96
|
+
constructor({ read, write, alpha = true }) {
|
|
97
|
+
super();
|
|
98
|
+
|
|
99
|
+
this.#read = read;
|
|
100
|
+
this.#write = write;
|
|
101
|
+
this.#has_alpha = alpha;
|
|
102
|
+
|
|
103
|
+
this.el = document.createElement('div');
|
|
104
|
+
|
|
105
|
+
this.addClass('ui-particle-gradient');
|
|
106
|
+
|
|
107
|
+
const canvas = this.#canvas = document.createElement('canvas');
|
|
108
|
+
|
|
109
|
+
canvas.width = WIDTH;
|
|
110
|
+
canvas.height = STRIP_HEIGHT + LANE_HEIGHT;
|
|
111
|
+
canvas.classList.add('strip');
|
|
112
|
+
|
|
113
|
+
this.el.appendChild(canvas);
|
|
114
|
+
|
|
115
|
+
const fields = document.createElement('div');
|
|
116
|
+
|
|
117
|
+
fields.classList.add('stop-fields');
|
|
118
|
+
|
|
119
|
+
this.el.appendChild(fields);
|
|
120
|
+
|
|
121
|
+
this.#swatch = field(fields, 'color', 'swatch');
|
|
122
|
+
this.#alpha = field(fields, 'number', 'alpha');
|
|
123
|
+
this.#position = field(fields, 'number', 'position');
|
|
124
|
+
|
|
125
|
+
for (const input of [this.#alpha, this.#position]) {
|
|
126
|
+
input.setAttribute('min', '0');
|
|
127
|
+
input.setAttribute('max', '1');
|
|
128
|
+
input.setAttribute('step', 'any');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
this.#alpha.hidden = !alpha;
|
|
132
|
+
|
|
133
|
+
const remove = document.createElement('button');
|
|
134
|
+
|
|
135
|
+
remove.type = 'button';
|
|
136
|
+
remove.classList.add('remove');
|
|
137
|
+
remove.textContent = '−';
|
|
138
|
+
remove.title = "Remove the selected stop (or middle-click it)";
|
|
139
|
+
|
|
140
|
+
fields.appendChild(remove);
|
|
141
|
+
|
|
142
|
+
this.#swatch.title = "The selected stop's colour";
|
|
143
|
+
this.#alpha.title = "The selected stop's alpha";
|
|
144
|
+
this.#position.title = "Where the selected stop sits along t";
|
|
145
|
+
|
|
146
|
+
canvas.addEventListener('pointerdown', event => this.#press(event));
|
|
147
|
+
canvas.addEventListener('pointermove', event => this.#move(event));
|
|
148
|
+
canvas.addEventListener('pointerup', event => this.#release(event));
|
|
149
|
+
canvas.addEventListener('pointercancel', event => this.#release(event));
|
|
150
|
+
|
|
151
|
+
this.#swatch.addEventListener('change', () => this.#editSelected(stop => {
|
|
152
|
+
const rgb = hex_to_rgb(this.#swatch.value);
|
|
153
|
+
|
|
154
|
+
stop.color = [rgb.r / 255, rgb.g / 255, rgb.b / 255, stop.color[3] ?? 1];
|
|
155
|
+
}));
|
|
156
|
+
|
|
157
|
+
this.#alpha.addEventListener('change', () => this.#editSelected(stop => {
|
|
158
|
+
const [r = 0, g = 0, b = 0, a = 1] = stop.color;
|
|
159
|
+
|
|
160
|
+
stop.color = [r, g, b, clamp01(number_in(this.#alpha, a))];
|
|
161
|
+
}));
|
|
162
|
+
|
|
163
|
+
this.#position.addEventListener('change', () => this.#editSelected(stop => {
|
|
164
|
+
stop.position = number_in(this.#position, stop.position);
|
|
165
|
+
}));
|
|
166
|
+
|
|
167
|
+
remove.addEventListener('click', () => this.#removeSelected());
|
|
168
|
+
|
|
169
|
+
this.on.linked.add(() => {
|
|
170
|
+
if (this.#context === null) {
|
|
171
|
+
this.#context = canvas.getContext('2d');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
this.refresh();
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
this.refresh();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Hand the working stops to the parameter, as a copy.
|
|
182
|
+
*
|
|
183
|
+
* A copy because this view goes on mutating its own array — the next drag writes straight into
|
|
184
|
+
* it — and what the node holds has to be what was committed rather than whatever this is doing
|
|
185
|
+
* next. It is also what makes each commit a distinct value, which is how the node knows anything
|
|
186
|
+
* changed at all.
|
|
187
|
+
*/
|
|
188
|
+
#commit() {
|
|
189
|
+
this.#write(structuredClone(this.#stops));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Re-read the parameter and redraw. Called when the value changed somewhere else — an undo, the
|
|
194
|
+
* code layer, a script.
|
|
195
|
+
*/
|
|
196
|
+
refresh() {
|
|
197
|
+
const value = this.#read();
|
|
198
|
+
|
|
199
|
+
this.#stops = Array.isArray(value)
|
|
200
|
+
? value.map(stop => ({ position: stop.position, color: (stop.color ?? []).slice() }))
|
|
201
|
+
: [];
|
|
202
|
+
|
|
203
|
+
this.#selected = Math.min(this.#selected, Math.max(0, this.#stops.length - 1));
|
|
204
|
+
|
|
205
|
+
this.#writeFields();
|
|
206
|
+
this.render();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* The stops in the order they are drawn and committed in, paired with where they were.
|
|
211
|
+
*
|
|
212
|
+
* Sorted for drawing and for the rollout, but the *selection* is an index into the unsorted
|
|
213
|
+
* array — so dragging a stop past its neighbour does not hand the selection to the neighbour,
|
|
214
|
+
* which is what makes a stop draggable all the way across the strip in one gesture.
|
|
215
|
+
*
|
|
216
|
+
* @returns {Array<{stop: object, index: number}>}
|
|
217
|
+
*/
|
|
218
|
+
#ordered() {
|
|
219
|
+
return this.#stops
|
|
220
|
+
.map((stop, index) => ({ stop, index }))
|
|
221
|
+
.sort((a, b) => a.stop.position - b.stop.position);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* @param {PointerEvent} event
|
|
226
|
+
* @returns {number} where along the strip the pointer is, `0..1`
|
|
227
|
+
*/
|
|
228
|
+
#positionOf(event) {
|
|
229
|
+
const rect = this.#canvas.getBoundingClientRect();
|
|
230
|
+
|
|
231
|
+
return clamp01((event.clientX - rect.left) / rect.width);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* @param {PointerEvent} event
|
|
236
|
+
* @returns {number} the index of the stop under the pointer, or -1
|
|
237
|
+
*/
|
|
238
|
+
#stopUnder(event) {
|
|
239
|
+
const rect = this.#canvas.getBoundingClientRect();
|
|
240
|
+
|
|
241
|
+
const x = event.clientX - rect.left;
|
|
242
|
+
|
|
243
|
+
// in CSS pixels, so the grab radius is the same however far the graph is zoomed out
|
|
244
|
+
const radius = GRAB_RADIUS * (rect.width / WIDTH);
|
|
245
|
+
|
|
246
|
+
let nearest = -1;
|
|
247
|
+
let distance = Infinity;
|
|
248
|
+
|
|
249
|
+
this.#stops.forEach((stop, index) => {
|
|
250
|
+
const away = Math.abs(stop.position * rect.width - x);
|
|
251
|
+
|
|
252
|
+
if (away <= radius && away < distance) {
|
|
253
|
+
nearest = index;
|
|
254
|
+
distance = away;
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
return nearest;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* @param {PointerEvent} event
|
|
263
|
+
*/
|
|
264
|
+
#press(event) {
|
|
265
|
+
const stop = this.#stopUnder(event);
|
|
266
|
+
|
|
267
|
+
if (event.button === 1) {
|
|
268
|
+
// the power-user path to the remove button beside the fields
|
|
269
|
+
if (stop !== -1) {
|
|
270
|
+
this.#selected = stop;
|
|
271
|
+
this.#removeSelected();
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
event.preventDefault();
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (event.button !== 0) {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (stop !== -1) {
|
|
283
|
+
this.#selected = stop;
|
|
284
|
+
} else {
|
|
285
|
+
const position = this.#positionOf(event);
|
|
286
|
+
|
|
287
|
+
// in the colour the gradient already is here, so adding a stop is not itself an edit to
|
|
288
|
+
// the gradient — it is somewhere to make one from
|
|
289
|
+
this.#stops.push({
|
|
290
|
+
position,
|
|
291
|
+
color: particle_gradient_sample(this.#stops, position),
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
this.#selected = this.#stops.length - 1;
|
|
295
|
+
|
|
296
|
+
this.#commit();
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
this.#dragging = true;
|
|
300
|
+
|
|
301
|
+
if (typeof this.#canvas.setPointerCapture === "function") {
|
|
302
|
+
this.#canvas.setPointerCapture(event.pointerId);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
this.#writeFields();
|
|
306
|
+
this.render();
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* @param {PointerEvent} event
|
|
311
|
+
*/
|
|
312
|
+
#move(event) {
|
|
313
|
+
if (!this.#dragging) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
this.#stops[this.#selected].position = this.#positionOf(event);
|
|
318
|
+
|
|
319
|
+
this.#writeFields();
|
|
320
|
+
this.render();
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* @param {PointerEvent} event
|
|
325
|
+
*/
|
|
326
|
+
#release(event) {
|
|
327
|
+
if (!this.#dragging) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
this.#dragging = false;
|
|
332
|
+
|
|
333
|
+
if (typeof this.#canvas.releasePointerCapture === "function" && this.#canvas.hasPointerCapture?.(event.pointerId)) {
|
|
334
|
+
this.#canvas.releasePointerCapture(event.pointerId);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// one entry on the timeline for the whole drag; see the note at the top of this file
|
|
338
|
+
this.#commit();
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* @param {function(object):void} edit applied to the selected stop
|
|
343
|
+
*/
|
|
344
|
+
#editSelected(edit) {
|
|
345
|
+
const stop = this.#stops[this.#selected];
|
|
346
|
+
|
|
347
|
+
if (stop === undefined) {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
edit(stop);
|
|
352
|
+
|
|
353
|
+
this.#commit();
|
|
354
|
+
this.#writeFields();
|
|
355
|
+
this.render();
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
#removeSelected() {
|
|
359
|
+
// A gradient with no stops has no colour to be, and the validator says so. Rather than let
|
|
360
|
+
// an author reach that state by clicking one button too many, the last stop stays.
|
|
361
|
+
if (this.#stops.length <= 1) {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
this.#stops.splice(this.#selected, 1);
|
|
366
|
+
|
|
367
|
+
this.#selected = Math.min(this.#selected, this.#stops.length - 1);
|
|
368
|
+
|
|
369
|
+
this.#commit();
|
|
370
|
+
this.#writeFields();
|
|
371
|
+
this.render();
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Put the selected stop into the fields under the strip.
|
|
376
|
+
*/
|
|
377
|
+
#writeFields() {
|
|
378
|
+
const stop = this.#stops[this.#selected];
|
|
379
|
+
|
|
380
|
+
const colour = stop === undefined ? [0, 0, 0, 1] : stop.color;
|
|
381
|
+
|
|
382
|
+
this.#swatch.value = `#${rgb_to_hex(byte_of(colour[0]), byte_of(colour[1]), byte_of(colour[2]))}`;
|
|
383
|
+
this.#alpha.value = String(colour[3] ?? 1);
|
|
384
|
+
this.#position.value = String(stop === undefined ? 0 : stop.position);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
render() {
|
|
388
|
+
const context = this.#context;
|
|
389
|
+
|
|
390
|
+
if (context === null) {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const canvas = this.#canvas;
|
|
395
|
+
|
|
396
|
+
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
397
|
+
|
|
398
|
+
// A checkerboard behind the strip, so that a stop's alpha is visible as transparency rather
|
|
399
|
+
// than as a colour that happens to look like the panel behind it.
|
|
400
|
+
if (this.#has_alpha) {
|
|
401
|
+
for (let x = 0; x < canvas.width; x += CHECKER) {
|
|
402
|
+
for (let y = 0; y < STRIP_HEIGHT; y += CHECKER) {
|
|
403
|
+
context.fillStyle = ((x + y) / CHECKER) % 2 === 0 ? '#4c4f54' : '#6a6e74';
|
|
404
|
+
context.fillRect(x, y, CHECKER, CHECKER);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// The strip is drawn by sampling the same function the node compiles to, so what is on
|
|
410
|
+
// screen is what the effect will do — including a hard edge where two stops share a place.
|
|
411
|
+
for (let x = 0; x < canvas.width; x++) {
|
|
412
|
+
const colour = particle_gradient_sample(this.#stops, x / (canvas.width - 1));
|
|
413
|
+
|
|
414
|
+
const alpha = this.#has_alpha ? clamp01(colour[3] ?? 1) : 1;
|
|
415
|
+
|
|
416
|
+
context.fillStyle = `rgba(${byte_of(colour[0])}, ${byte_of(colour[1])}, ${byte_of(colour[2])}, ${alpha})`;
|
|
417
|
+
context.fillRect(x, 0, 1, STRIP_HEIGHT);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
for (const { stop, index } of this.#ordered()) {
|
|
421
|
+
const x = clamp01(stop.position) * canvas.width;
|
|
422
|
+
const selected = index === this.#selected;
|
|
423
|
+
|
|
424
|
+
context.beginPath();
|
|
425
|
+
context.moveTo(x, STRIP_HEIGHT + 1);
|
|
426
|
+
context.lineTo(x - 5, STRIP_HEIGHT + LANE_HEIGHT - 1);
|
|
427
|
+
context.lineTo(x + 5, STRIP_HEIGHT + LANE_HEIGHT - 1);
|
|
428
|
+
context.closePath();
|
|
429
|
+
|
|
430
|
+
// the marker carries the stop's own colour, so the lane reads as the stops rather than
|
|
431
|
+
// as a row of identical arrows
|
|
432
|
+
context.fillStyle = `rgb(${byte_of(stop.color[0])}, ${byte_of(stop.color[1])}, ${byte_of(stop.color[2])})`;
|
|
433
|
+
context.fill();
|
|
434
|
+
|
|
435
|
+
context.lineWidth = selected ? 2 : 1;
|
|
436
|
+
context.strokeStyle = selected ? '#ffd35c' : '#20242a';
|
|
437
|
+
context.stroke();
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* @param {HTMLElement} parent
|
|
444
|
+
* @param {string} type
|
|
445
|
+
* @param {string} className
|
|
446
|
+
* @returns {HTMLInputElement}
|
|
447
|
+
*/
|
|
448
|
+
function field(parent, type, className) {
|
|
449
|
+
const input = document.createElement('input');
|
|
450
|
+
|
|
451
|
+
input.setAttribute('type', type);
|
|
452
|
+
input.classList.add(className);
|
|
453
|
+
|
|
454
|
+
parent.appendChild(input);
|
|
455
|
+
|
|
456
|
+
return input;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* What a number field holds, or `fallback` where it holds nothing a number can be made of — a
|
|
461
|
+
* half-typed value should snap back rather than become zero.
|
|
462
|
+
*
|
|
463
|
+
* @param {HTMLInputElement} input
|
|
464
|
+
* @param {number} fallback
|
|
465
|
+
* @returns {number}
|
|
466
|
+
*/
|
|
467
|
+
function number_in(input, fallback) {
|
|
468
|
+
const parsed = Number.parseFloat(input.value);
|
|
469
|
+
|
|
470
|
+
return Number.isFinite(parsed) ? parsed : fallback;
|
|
471
|
+
}
|
|
472
|
+
|
|
@@ -131,6 +131,11 @@ export class ParticleGraphEditorView extends View {
|
|
|
131
131
|
* Everything is listed, whichever phase it belongs to, because a problem in the phase an author
|
|
132
132
|
* is not looking at is exactly the one they would otherwise hunt for. Nodes carrying a problem
|
|
133
133
|
* are marked in the graph as well.
|
|
134
|
+
*
|
|
135
|
+
* Loudest first, so a strip too short to show everything shows what matters. What is left over
|
|
136
|
+
* at the bottom is the notes — a node nothing reads, most of all — and a graph with nothing but
|
|
137
|
+
* those still says it has no problems, because it has none: they are things worth knowing about
|
|
138
|
+
* an effect that compiles.
|
|
134
139
|
*/
|
|
135
140
|
refreshProblems(): void;
|
|
136
141
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ParticleGraphEditorView.d.ts","sourceRoot":"","sources":["../../../../../editor/view/particles/effect/ParticleGraphEditorView.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ParticleGraphEditorView.d.ts","sourceRoot":"","sources":["../../../../../editor/view/particles/effect/ParticleGraphEditorView.js"],"names":[],"mappings":"AA0LA;IA6FI;;;;;OAKG;IACH;QAJyG,MAAM,EAApG,OAAO,qDAAqD,EAAE,sBAAsB;QAC1D,eAAe;OAsDnD;IAhDG,mBAAuC;IAIvC;;OAEG;IACH,QAFU,OAAO,qDAAqD,EAAE,sBAAsB,CAE1E;IAEpB;;OAEG;IACH,2CAAsC;IA4X1C;;;;;;;;;;;;;;;OAeG;IACH,kBAHa,QAAQ,eAAa,IAAI,CAAC,CAwEtC;IAED;;;;;;;;OAQG;IACH,oBAFa,QAAQ,cAAc,CAAC,CAgCnC;IA+ID;;;;;;;;;;;;;OAaG;IACH,iBAHW,OAAO,qEAAqE,EAAE,iBAAiB,GAC7F,IAAI,CAsDhB;IAED;;;OAGG;IACH,cAFa,IAAI,CAIhB;IAED;;;;;OAKG;IACH,sBAHW,MAAM,GACJ,IAAI,CAWhB;IAED;;;;OAIG;IACH,cAFa,OAAO,qEAAqE,EAAE,iBAAiB,EAAE,CAI7G;IAED;;;;;;;;;;OAUG;IACH,gBAuCC;IAwBD;;;;;;;OAOG;IACH,wDAHW,MAAM,GACJ,qBAAqB,CAiBjC;IAiED;;;;OAIG;IACH,gBAFa,mBAAmB,CAQ/B;IAED;;OAEG;IACH,eAFa,MAAM,CAIlB;IAED;;;OAGG;IACH,aAFW,MAAM,QAmBhB;IAoGD;;;;;;;;;OASG;IACH,mBAJW,OAAO,qEAAqE,EAAE,iBAAiB,SAC/F,MAAM,GACJ,IAAI,CAqBhB;IAED;;;;;;;;;;;OAWG;IACH,wBAoCC;IAoDD;;;;;OAKG;IACH,qBAHW,MAAM,WACN,MAAM,QA2BhB;IAED;;;;;OAKG;IACH,cAFa,OAAO,6CAA6C,EAAE,uBAAuB,GAAC,IAAI,CAI9F;IAED,eAuBC;;CAgCJ;iBAtgDgB,8BAA8B;gCAvCf,sDAAsD;oCA0ClD,yCAAyC"}
|
|
@@ -3,13 +3,21 @@ import { PortDirection } from "../../../../src/core/model/node-graph/node/PortDi
|
|
|
3
3
|
import { ActionProcessor } from "../../../../src/core/process/undo/ActionProcessor.js";
|
|
4
4
|
import { infer_particle_graph_types } from "../../../../src/shade/renderer/particles/graph/infer_particle_graph_types.js";
|
|
5
5
|
import { particle_group_from_nodes } from "../../../../src/shade/renderer/particles/graph/make_particle_group.js";
|
|
6
|
+
import {
|
|
7
|
+
PARTICLE_GRAPH_ERROR,
|
|
8
|
+
PARTICLE_GRAPH_INFO,
|
|
9
|
+
PARTICLE_GRAPH_SEVERITY_RANK,
|
|
10
|
+
PARTICLE_GRAPH_WARNING,
|
|
11
|
+
} from "../../../../src/shade/renderer/particles/graph/particle_graph_diagnostic.js";
|
|
6
12
|
import {
|
|
7
13
|
particle_group_descriptions,
|
|
8
14
|
} from "../../../../src/shade/renderer/particles/graph/particle_group_json.js";
|
|
9
15
|
import {
|
|
16
|
+
is_particle_group_boundary,
|
|
10
17
|
is_particle_group_description,
|
|
11
18
|
} from "../../../../src/shade/renderer/particles/graph/ParticleNodeGroup.js";
|
|
12
19
|
import {
|
|
20
|
+
clone_particle_parameters,
|
|
13
21
|
particle_node_default_parameters,
|
|
14
22
|
particle_node_parameters,
|
|
15
23
|
} from "../../../../src/shade/renderer/particles/graph/particle_node_parameters.js";
|
|
@@ -33,6 +41,7 @@ import LabelView from "../../../../src/view/common/LabelView.js";
|
|
|
33
41
|
import EmptyView from "../../../../src/view/elements/EmptyView.js";
|
|
34
42
|
import View from "../../../../src/view/View.js";
|
|
35
43
|
import { NodeGraphCamera } from "../../node-graph/NodeGraphCamera.js";
|
|
44
|
+
import { NodeGraphClipboard } from "../../node-graph/NodeGraphClipboard.js";
|
|
36
45
|
import { NodeGraphEditorView } from "../../node-graph/NodeGraphEditorView.js";
|
|
37
46
|
import { NodeCreateAction } from "../../node-graph/actions/NodeCreateAction.js";
|
|
38
47
|
import { NodeDeleteAction } from "../../node-graph/actions/NodeDeleteAction.js";
|
|
@@ -48,8 +57,9 @@ import { ParticleNodeParametersView } from "./ParticleNodeParametersView.js";
|
|
|
48
57
|
*
|
|
49
58
|
* Built *with* the node-graph editor rather than in it. Everything particle-specific arrives
|
|
50
59
|
* through the seams the base offers — the node library the canvas's add-node menu offers, a
|
|
51
|
-
* parameter-view factory that draws vector, enum, attribute and swizzle controls,
|
|
52
|
-
*
|
|
60
|
+
* parameter-view factory that draws vector, enum, attribute and swizzle controls, the one rule the
|
|
61
|
+
* clipboard needs (a group's boundary blocks are not something there can be a second of), and a
|
|
62
|
+
* problems list fed by the document's own compile. The base is left knowing nothing about particles.
|
|
53
63
|
*
|
|
54
64
|
* ## Adding a node
|
|
55
65
|
*
|
|
@@ -79,8 +89,8 @@ import { ParticleNodeParametersView } from "./ParticleNodeParametersView.js";
|
|
|
79
89
|
* ## What is undoable
|
|
80
90
|
*
|
|
81
91
|
* Everything that touches a graph, through the {@link ActionProcessor} the host supplies. Adding a
|
|
82
|
-
* node from the menu, wiring, moving, deleting, and every parameter edit inside a node all
|
|
83
|
-
* on one timeline, so a host editor's global undo covers particle authoring without knowing it
|
|
92
|
+
* node from the menu, wiring, moving, deleting, pasting, and every parameter edit inside a node all
|
|
93
|
+
* land on one timeline, so a host editor's global undo covers particle authoring without knowing it
|
|
84
94
|
* exists.
|
|
85
95
|
*/
|
|
86
96
|
|
|
@@ -127,13 +137,17 @@ const PARTICLE_TYPE_COLORS = new Map([
|
|
|
127
137
|
const PALETTE_CATEGORIES = [
|
|
128
138
|
{ name: "sources", types: ["const", "color", "builtin", "attribute", "random", "curve"] },
|
|
129
139
|
{ name: "output", types: ["setAttribute", "kill"] },
|
|
130
|
-
|
|
131
|
-
|
|
140
|
+
// The three that are authored data rather than wiring, and are edited as a picture: a gradient
|
|
141
|
+
// strip and a curve in the unit square. Their own heading, because "a colour ramp" is a thing an
|
|
142
|
+
// author goes looking for by name and would not think to look for under `sources`.
|
|
143
|
+
{ name: "ramps", types: ["gradientRGBA", "gradientRGB", "curveLiteral"] },
|
|
144
|
+
{ name: "arithmetic", types: ["add", "sub", "mul", "div", "mad", "scale", "min", "max", "pow", "step", "mix", "clamp", "saturate", "smoothstep", "remap", "oneMinus"] },
|
|
145
|
+
{ name: "math", types: ["neg", "abs", "floor", "fract", "round", "ceil", "sqrt", "rsqrt", "sin", "cos", "tan", "asin", "acos", "atan2", "exp", "log"] },
|
|
132
146
|
{ name: "vector", types: ["vec2", "vec3", "vec4", "decompose2", "decompose3", "decompose4", "swizzle", "dot", "cross", "length", "normalize", "distance", "angleBetween2", "angleBetween3"] },
|
|
133
147
|
{ name: "logic", types: ["compare", "select"] },
|
|
134
148
|
{ name: "rotation", types: ["quatFromAxisAngle", "quatLookRotation", "quatRotate"] },
|
|
135
149
|
{ name: "sampling", types: ["sampleSphereSurface", "sampleSphereVolume"] },
|
|
136
|
-
{ name: "noise", types: ["simplex3", "simplex4", "curl3", "curl4"] },
|
|
150
|
+
{ name: "noise", types: ["simplex3", "simplex4", "curl3", "curl4", "srdnoise3", "psrdnoise3"] },
|
|
137
151
|
];
|
|
138
152
|
|
|
139
153
|
/**
|
|
@@ -221,6 +235,19 @@ export class ParticleGraphEditorView extends View {
|
|
|
221
235
|
*/
|
|
222
236
|
#open_groups = [];
|
|
223
237
|
|
|
238
|
+
/**
|
|
239
|
+
* One clipboard for every canvas this view builds — both phases, and the body of every group
|
|
240
|
+
* opened inside them.
|
|
241
|
+
*
|
|
242
|
+
* `Ctrl+C` in INIT and `Ctrl+V` in UPDATE is the same gesture an author expects it to be, and a
|
|
243
|
+
* clipboard per canvas would make it two. It belongs to this view rather than to the module,
|
|
244
|
+
* because what it holds is node types this document knows — a group an author made here has no
|
|
245
|
+
* meaning in another document's graph.
|
|
246
|
+
*
|
|
247
|
+
* @type {NodeGraphClipboard}
|
|
248
|
+
*/
|
|
249
|
+
#clipboard = new NodeGraphClipboard();
|
|
250
|
+
|
|
224
251
|
/**
|
|
225
252
|
* Phases whose camera has not yet been pointed at their contents. A graph that has just been
|
|
226
253
|
* arranged for the first time is somewhere in particular, and it is not the origin.
|
|
@@ -438,6 +465,12 @@ export class ParticleGraphEditorView extends View {
|
|
|
438
465
|
camera: new NodeGraphCamera(),
|
|
439
466
|
actionProcessor: this.actionProcessor,
|
|
440
467
|
readOnly,
|
|
468
|
+
clipboard: this.#clipboard,
|
|
469
|
+
// A group body's input and output blocks are its edge, not its contents: there is one of
|
|
470
|
+
// each, the group holds them by reference, and a second would survive flattening and
|
|
471
|
+
// reach the compiler. So they are left out of a copy rather than the copy being refused
|
|
472
|
+
// — an author who dragged a box around a whole group body wants what is inside it.
|
|
473
|
+
copyable: node => !is_particle_group_boundary(node),
|
|
441
474
|
library: {
|
|
442
475
|
// The menu heads each *run* of one category, so the order it is handed decides the
|
|
443
476
|
// order it shows; sorting here keeps that decision on the particle side of the seam.
|
|
@@ -815,7 +848,9 @@ export class ParticleGraphEditorView extends View {
|
|
|
815
848
|
inner.description,
|
|
816
849
|
(placed?.x ?? 0) + (at === undefined ? 0 : at.x - origin.x),
|
|
817
850
|
(placed?.y ?? 0) + (at === undefined ? 0 : at.y - origin.y),
|
|
818
|
-
|
|
851
|
+
// deeply: an ungrouped node must not share so much as a gradient stop with the group
|
|
852
|
+
// definition it came out of
|
|
853
|
+
clone_particle_parameters(inner.parameters)
|
|
819
854
|
));
|
|
820
855
|
}
|
|
821
856
|
|
|
@@ -1354,6 +1389,11 @@ export class ParticleGraphEditorView extends View {
|
|
|
1354
1389
|
* Everything is listed, whichever phase it belongs to, because a problem in the phase an author
|
|
1355
1390
|
* is not looking at is exactly the one they would otherwise hunt for. Nodes carrying a problem
|
|
1356
1391
|
* are marked in the graph as well.
|
|
1392
|
+
*
|
|
1393
|
+
* Loudest first, so a strip too short to show everything shows what matters. What is left over
|
|
1394
|
+
* at the bottom is the notes — a node nothing reads, most of all — and a graph with nothing but
|
|
1395
|
+
* those still says it has no problems, because it has none: they are things worth knowing about
|
|
1396
|
+
* an effect that compiles.
|
|
1357
1397
|
*/
|
|
1358
1398
|
refreshProblems() {
|
|
1359
1399
|
// The graph's own problems, not the running program's: with the code layer authoritative the
|
|
@@ -1363,9 +1403,13 @@ export class ParticleGraphEditorView extends View {
|
|
|
1363
1403
|
|
|
1364
1404
|
this.#diagnostics = diagnostics;
|
|
1365
1405
|
|
|
1406
|
+
// stable within a level, so the order the checks found them in survives
|
|
1407
|
+
diagnostics.sort((a, b) =>
|
|
1408
|
+
PARTICLE_GRAPH_SEVERITY_RANK[b.severity] - PARTICLE_GRAPH_SEVERITY_RANK[a.severity]);
|
|
1409
|
+
|
|
1366
1410
|
this.#problems.removeAllChildren();
|
|
1367
1411
|
|
|
1368
|
-
if (diagnostics.
|
|
1412
|
+
if (!diagnostics.some(diagnostic => diagnostic.severity !== PARTICLE_GRAPH_INFO)) {
|
|
1369
1413
|
this.#problems.addChild(new LabelView("No problems.", { classList: ['none'] }));
|
|
1370
1414
|
}
|
|
1371
1415
|
|
|
@@ -1425,14 +1469,18 @@ export class ParticleGraphEditorView extends View {
|
|
|
1425
1469
|
continue;
|
|
1426
1470
|
}
|
|
1427
1471
|
|
|
1428
|
-
// an error
|
|
1429
|
-
if (
|
|
1472
|
+
// a node wears the loudest thing said about it: an error over a warning, either over a note
|
|
1473
|
+
if (
|
|
1474
|
+
severity === undefined
|
|
1475
|
+
|| PARTICLE_GRAPH_SEVERITY_RANK[diagnostic.severity] > PARTICLE_GRAPH_SEVERITY_RANK[severity]
|
|
1476
|
+
) {
|
|
1430
1477
|
severity = diagnostic.severity;
|
|
1431
1478
|
}
|
|
1432
1479
|
}
|
|
1433
1480
|
|
|
1434
|
-
nodeView.setClass('has-error', severity ===
|
|
1435
|
-
nodeView.setClass('has-warning', severity ===
|
|
1481
|
+
nodeView.setClass('has-error', severity === PARTICLE_GRAPH_ERROR);
|
|
1482
|
+
nodeView.setClass('has-warning', severity === PARTICLE_GRAPH_WARNING);
|
|
1483
|
+
nodeView.setClass('has-info', severity === PARTICLE_GRAPH_INFO);
|
|
1436
1484
|
}
|
|
1437
1485
|
|
|
1438
1486
|
/**
|
|
@@ -1596,24 +1644,6 @@ function body_origin(group) {
|
|
|
1596
1644
|
return Number.isFinite(x) ? { x, y } : { x: 0, y: 0 };
|
|
1597
1645
|
}
|
|
1598
1646
|
|
|
1599
|
-
/**
|
|
1600
|
-
* A node's parameters, deep enough that the copy and the original cannot write through to each
|
|
1601
|
-
* other — an ungrouped node must not share an array with the group's definition.
|
|
1602
|
-
*
|
|
1603
|
-
* @param {object} parameters
|
|
1604
|
-
* @returns {object}
|
|
1605
|
-
*/
|
|
1606
|
-
function clone_parameters(parameters) {
|
|
1607
|
-
const result = {};
|
|
1608
|
-
|
|
1609
|
-
for (const key of Object.keys(parameters)) {
|
|
1610
|
-
const value = parameters[key];
|
|
1611
|
-
|
|
1612
|
-
result[key] = Array.isArray(value) ? value.slice() : value;
|
|
1613
|
-
}
|
|
1614
|
-
|
|
1615
|
-
return result;
|
|
1616
|
-
}
|
|
1617
1647
|
|
|
1618
1648
|
/**
|
|
1619
1649
|
* @param {string} type node type name
|