Merge branch 'dev' into kotlin/2.0.0-Beta

# Conflicts:
#	gradle.properties
#	settings.gradle.kts
#	ui/compose/build.gradle.kts
#	visionforge-core/build.gradle.kts
#	visionforge-markdown/src/jsMain/kotlin/space/kscience/visionforge/markup/MarkupPlugin.kt
This commit is contained in:
Alexander Nozik 2024-03-18 13:49:22 +03:00
commit d0220c98a4
222 changed files with 5800 additions and 5657 deletions

1
.gitignore vendored
View File

@ -3,6 +3,7 @@
*.iws
out/
.gradle
.kotlin
build/
data/
.kotlin/

View File

@ -1,4 +0,0 @@
job("Build") {
gradlew("openjdk:11", "build")
}

View File

@ -1,12 +1,54 @@
# Changelog
## [Unreleased]
## Unreleased
### Added
### Changed
### Deprecated
### Removed
### Fixed
### Security
## 0.4.1 - 2024-03-15
### Changed
- VisionProperties `flowChanges()` -> `changes`
### Fixed
- Bug with ElementVisionRenderer having the same name
- Plotly update problem
## 0.4.0 - 2024-02-16
### Added
- Added compose-mpp rendering.
### Changed
- **Breaking API** Move vision cache to upper level for renderers to avoid re-creating visions for page reload.
- **Breaking API** Forms refactor.
- **Breaking API** Migrated from React to Compose-html.
- **Breaking API** changed js package for `visionforge-core` to `space.kscience.visionforge.html` to avoid mixing html and generic parts.
## 0.3.0 - 2023-12-23
### Added
- Context receivers flag
- MeshLine for thick lines
- Custom client-side events and thier processing in VisionServer
- Control/input visions
### Changed
- Color accessor property is now `colorProperty`. Color uses non-nullable `invoke` instead of `set`.
- API update for server and pages
- Edges moved to solids module for easier construction
@ -17,17 +59,14 @@
- Naming of Canvas3D options.
- Lights are added to the scene instead of 3D options.
### Deprecated
### Removed
### Fixed
- Jupyter integration for IDEA and Jupyter lab.
### Security
## 0.2.0
## [0.2.0]
### Added
- Server module
- Change collector
- Customizable accessors for colors
@ -38,8 +77,8 @@
- Markdown module
- Tables module
### Changed
- Vision does not implement ItemProvider anymore. Property changes are done via `getProperty`/`setProperty` and `property` delegate.
- Point3D and Point2D are made separate classes instead of expect/actual (to split up different engines.
- JavaFX support moved to a separate module
@ -54,16 +93,10 @@
- Property listeners are not triggered if there are no changes.
- Feedback websocket connection in the client.
### Deprecated
### Removed
- Primary modules dependencies on UI
### Fixed
- Version conflicts
### Security

128
README.md
View File

@ -61,157 +61,96 @@ To learn more about DataForge, please consult the following URLs:
## Modules contained in this repository
<hr/>
* ### [cern-root-loader](cern-root-loader)
>
### [cern-root-loader](cern-root-loader)
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [demo](demo)
>
### [demo](demo)
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [jupyter](jupyter)
>
### [visionforge-compose-html](visionforge-compose-html)
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [ui](ui)
>
### [visionforge-compose-multiplatform](visionforge-compose-multiplatform)
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [visionforge-core](visionforge-core)
>
### [visionforge-core](visionforge-core)
>
> **Maturity**: DEVELOPMENT
<hr/>
* ### [visionforge-fx](visionforge-fx)
>
>
> **Maturity**: PROTOTYPE
<hr/>
* ### [visionforge-gdml](visionforge-gdml)
>
### [visionforge-gdml](visionforge-gdml)
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [visionforge-markdown](visionforge-markdown)
>
### [visionforge-jupyter](visionforge-jupyter)
> Common visionforge jupyter module
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [visionforge-plotly](visionforge-plotly)
>
### [visionforge-markdown](visionforge-markdown)
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [visionforge-server](visionforge-server)
>
### [visionforge-plotly](visionforge-plotly)
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [visionforge-solid](visionforge-solid)
### [visionforge-server](visionforge-server)
>
> **Maturity**: EXPERIMENTAL
### [visionforge-solid](visionforge-solid)
>
> **Maturity**: DEVELOPMENT
<hr/>
* ### [visionforge-tables](visionforge-tables)
>
### [visionforge-tables](visionforge-tables)
>
> **Maturity**: PROTOTYPE
<hr/>
* ### [visionforge-threejs](visionforge-threejs)
>
### [visionforge-threejs](visionforge-threejs)
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [gdml](demo/gdml)
>
### [demo/compose-desktop-demo](demo/compose-desktop-demo)
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [js-playground](demo/js-playground)
>
### [demo/gdml](demo/gdml)
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [muon-monitor](demo/muon-monitor)
>
### [demo/js-playground](demo/js-playground)
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [playground](demo/playground)
>
### [demo/muon-monitor](demo/muon-monitor)
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [plotly-fx](demo/plotly-fx)
>
### [demo/playground](demo/playground)
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [sat-demo](demo/sat-demo)
>
### [demo/sat-demo](demo/sat-demo)
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [solid-showcase](demo/solid-showcase)
>
### [demo/solid-showcase](demo/solid-showcase)
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [visionforge-jupyter-gdml](jupyter/visionforge-jupyter-gdml)
>
### [visionforge-jupyter/visionforge-jupyter-common](visionforge-jupyter/visionforge-jupyter-common)
> Jupyter api artifact including all common modules
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [bootstrap](ui/bootstrap)
>
### [visionforge-threejs/visionforge-threejs-server](visionforge-threejs/visionforge-threejs-server)
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [react](ui/react)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [ring](ui/ring)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [visionforge-threejs-server](visionforge-threejs/visionforge-threejs-server)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
**Class diagram:**
@ -283,6 +222,21 @@ Visualization example for geometry defined as GDML file.
![](docs/images/gdml-demo.png)
## Stability and documentation
VisionForge is a modular library. Different modules provide different features with different API stability guarantees. All core modules are released with the same version, but with different API change policy. The features are described in module definitions below. The module stability could have the following levels:
* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version.
* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked
with `@DFExperimental` or other stability warning annotations.
* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor
versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
* **STABLE**. The API stabilized. Breaking changes are allowed only in major releases.
Additionally, one should note that the VisionForge Json format impacts the reproducibility of stored vision fragments. There should not be any breaks of the format between major releases. All problems should be reported.
The documentation for the project is a work in progress. Please report any issues with missing, vague or wrong information. The contributions into documentation are quite welcome.
## Thanks and references
The original three.js bindings were made by [Lars Ivar Hatledal](https://github.com/markaren), but the project is discontinued right now.

View File

@ -1,18 +1,16 @@
import org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile
import space.kscience.gradle.useApache2Licence
import space.kscience.gradle.useSPCTeam
plugins {
id("space.kscience.gradle.project")
// id("org.jetbrains.kotlinx.kover") version "0.5.0"
id("org.jetbrains.kotlinx.kover") version "0.5.0"
}
val dataforgeVersion by extra("0.6.2")
val fxVersion by extra("11")
val dataforgeVersion by extra("0.8.0")
allprojects {
group = "space.kscience"
version = "0.3.0-dev-16"
version = "0.4.1"
}
subprojects {
@ -32,11 +30,11 @@ subprojects {
}
}
tasks.withType<KotlinJsCompile>{
kotlinOptions{
useEsClasses = true
}
}
// tasks.withType<KotlinJsCompile>{
// kotlinOptions{
// useEsClasses = true
// }
// }
}
ksciencePublish {

View File

@ -1,3 +1,77 @@
public final class ru/mipt/npm/root/BMN {
public static final field INSTANCE Lru/mipt/npm/root/BMN;
public final fun getJson ()Lkotlinx/serialization/json/Json;
public final fun readEventJson (Ljava/lang/String;)Lru/mipt/npm/root/BmnEventContainer;
}
public final class ru/mipt/npm/root/BMNKt {
public static final fun toVector (Lru/mipt/npm/root/FairTrackParam;)Lspace/kscience/visionforge/solid/Float32Vector3D;
}
public final class ru/mipt/npm/root/BmnEventContainer {
public fun <init> (Ljava/util/List;Ljava/util/List;)V
public final fun getBmnGlobalTracks ()Ljava/util/List;
public final fun getCbmTracks ()Ljava/util/List;
}
public final class ru/mipt/npm/root/BmnGlobalTrack {
public static final field Companion Lru/mipt/npm/root/BmnGlobalTrack$Companion;
public fun <init> (Lru/mipt/npm/root/FairTrackParam;Lru/mipt/npm/root/FairTrackParam;)V
public final fun component1 ()Lru/mipt/npm/root/FairTrackParam;
public final fun component2 ()Lru/mipt/npm/root/FairTrackParam;
public final fun copy (Lru/mipt/npm/root/FairTrackParam;Lru/mipt/npm/root/FairTrackParam;)Lru/mipt/npm/root/BmnGlobalTrack;
public static synthetic fun copy$default (Lru/mipt/npm/root/BmnGlobalTrack;Lru/mipt/npm/root/FairTrackParam;Lru/mipt/npm/root/FairTrackParam;ILjava/lang/Object;)Lru/mipt/npm/root/BmnGlobalTrack;
public fun equals (Ljava/lang/Object;)Z
public final fun getFParamFirst ()Lru/mipt/npm/root/FairTrackParam;
public final fun getFParamLast ()Lru/mipt/npm/root/FairTrackParam;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class ru/mipt/npm/root/BmnGlobalTrack$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/BmnGlobalTrack$$serializer;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/BmnGlobalTrack;
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lru/mipt/npm/root/BmnGlobalTrack;)V
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
}
public final class ru/mipt/npm/root/BmnGlobalTrack$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class ru/mipt/npm/root/CbmStsTrack {
public static final field Companion Lru/mipt/npm/root/CbmStsTrack$Companion;
public fun <init> (Lru/mipt/npm/root/FairTrackParam;Lru/mipt/npm/root/FairTrackParam;)V
public final fun component1 ()Lru/mipt/npm/root/FairTrackParam;
public final fun component2 ()Lru/mipt/npm/root/FairTrackParam;
public final fun copy (Lru/mipt/npm/root/FairTrackParam;Lru/mipt/npm/root/FairTrackParam;)Lru/mipt/npm/root/CbmStsTrack;
public static synthetic fun copy$default (Lru/mipt/npm/root/CbmStsTrack;Lru/mipt/npm/root/FairTrackParam;Lru/mipt/npm/root/FairTrackParam;ILjava/lang/Object;)Lru/mipt/npm/root/CbmStsTrack;
public fun equals (Ljava/lang/Object;)Z
public final fun getFParamFirst ()Lru/mipt/npm/root/FairTrackParam;
public final fun getFParamLast ()Lru/mipt/npm/root/FairTrackParam;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class ru/mipt/npm/root/CbmStsTrack$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/CbmStsTrack$$serializer;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/CbmStsTrack;
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lru/mipt/npm/root/CbmStsTrack;)V
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
}
public final class ru/mipt/npm/root/CbmStsTrack$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class ru/mipt/npm/root/DGeoBoolNode : ru/mipt/npm/root/DObject {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
public final fun getFLeft ()Lru/mipt/npm/root/DGeoShape;
@ -6,6 +80,28 @@ public final class ru/mipt/npm/root/DGeoBoolNode : ru/mipt/npm/root/DObject {
public final fun getFRightMat ()Lru/mipt/npm/root/DGeoMatrix;
}
public class ru/mipt/npm/root/DGeoCombiTrans : ru/mipt/npm/root/DGeoMatrix {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
public final fun getFRotation ()Lru/mipt/npm/root/DGeoRotation;
public final fun getFTranslation ()[D
}
public final class ru/mipt/npm/root/DGeoGenTrans : ru/mipt/npm/root/DGeoCombiTrans {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
public final fun getFScale ()[D
}
public final class ru/mipt/npm/root/DGeoHMatrix : ru/mipt/npm/root/DGeoMatrix {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
public final fun getFRotation ()Lru/mipt/npm/root/DGeoRotation;
public final fun getFScale ()[D
public final fun getFTranslation ()[D
}
public final class ru/mipt/npm/root/DGeoIdentity : ru/mipt/npm/root/DGeoMatrix {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
}
public final class ru/mipt/npm/root/DGeoManager : ru/mipt/npm/root/DNamed {
public static final field Companion Lru/mipt/npm/root/DGeoManager$Companion;
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
@ -23,8 +119,8 @@ public final class ru/mipt/npm/root/DGeoMaterial : ru/mipt/npm/root/DNamed {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
}
public class ru/mipt/npm/root/DGeoMatrix : ru/mipt/npm/root/DNamed {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
public abstract class ru/mipt/npm/root/DGeoMatrix : ru/mipt/npm/root/DNamed {
public synthetic fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public final class ru/mipt/npm/root/DGeoMedium : ru/mipt/npm/root/DNamed {
@ -38,7 +134,12 @@ public final class ru/mipt/npm/root/DGeoNode : ru/mipt/npm/root/DNamed {
public final fun getFVolume ()Lru/mipt/npm/root/DGeoVolume;
}
public class ru/mipt/npm/root/DGeoScale : ru/mipt/npm/root/DGeoMatrix {
public final class ru/mipt/npm/root/DGeoRotation : ru/mipt/npm/root/DGeoMatrix {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
public final fun getFRotationMatrix ()[D
}
public final class ru/mipt/npm/root/DGeoScale : ru/mipt/npm/root/DGeoMatrix {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
public final fun getFScale ()[D
public final fun getX ()D
@ -53,6 +154,11 @@ public final class ru/mipt/npm/root/DGeoShape : ru/mipt/npm/root/DNamed {
public final fun getFDZ ()D
}
public final class ru/mipt/npm/root/DGeoTranslation : ru/mipt/npm/root/DGeoMatrix {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
public final fun getFTranslation ()[D
}
public final class ru/mipt/npm/root/DGeoVolume : ru/mipt/npm/root/DNamed, space/kscience/dataforge/misc/Named {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
public final fun getFFillColor ()Ljava/lang/Integer;
@ -94,7 +200,45 @@ public final class ru/mipt/npm/root/DObjectKt {
}
public final class ru/mipt/npm/root/DRootToSolidKt {
public static final fun toSolid (Lru/mipt/npm/root/DGeoManager;)Lspace/kscience/visionforge/solid/SolidGroup;
public static final fun rootGeo (Lspace/kscience/visionforge/MutableVisionContainer;Lru/mipt/npm/root/DGeoManager;Ljava/lang/String;IZ)Lspace/kscience/visionforge/solid/SolidGroup;
public static synthetic fun rootGeo$default (Lspace/kscience/visionforge/MutableVisionContainer;Lru/mipt/npm/root/DGeoManager;Ljava/lang/String;IZILjava/lang/Object;)Lspace/kscience/visionforge/solid/SolidGroup;
}
public final class ru/mipt/npm/root/FairTrackParam {
public static final field Companion Lru/mipt/npm/root/FairTrackParam$Companion;
public fun <init> (DDDDDD)V
public final fun component1 ()D
public final fun component2 ()D
public final fun component3 ()D
public final fun component4 ()D
public final fun component5 ()D
public final fun component6 ()D
public final fun copy (DDDDDD)Lru/mipt/npm/root/FairTrackParam;
public static synthetic fun copy$default (Lru/mipt/npm/root/FairTrackParam;DDDDDDILjava/lang/Object;)Lru/mipt/npm/root/FairTrackParam;
public fun equals (Ljava/lang/Object;)Z
public final fun getFQp ()D
public final fun getFTx ()D
public final fun getFTy ()D
public final fun getFX ()D
public final fun getFY ()D
public final fun getFZ ()D
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class ru/mipt/npm/root/FairTrackParam$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/FairTrackParam$$serializer;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/FairTrackParam;
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lru/mipt/npm/root/FairTrackParam;)V
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
}
public final class ru/mipt/npm/root/FairTrackParam$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class ru/mipt/npm/root/RootColors {
@ -108,7 +252,7 @@ public final class ru/mipt/npm/root/serialization/JsonToRootKt {
}
public final class ru/mipt/npm/root/serialization/RootToSolidKt {
public static final fun toSolid (Lru/mipt/npm/root/serialization/TGeoManager;)Lspace/kscience/visionforge/solid/SolidGroup;
public static final fun rootGeo (Lspace/kscience/visionforge/MutableVisionContainer;Lru/mipt/npm/root/serialization/TGeoManager;)Lspace/kscience/visionforge/solid/SolidGroup;
}
public class ru/mipt/npm/root/serialization/TGeoBBox : ru/mipt/npm/root/serialization/TGeoShape {
@ -119,12 +263,11 @@ public class ru/mipt/npm/root/serialization/TGeoBBox : ru/mipt/npm/root/serializ
public final fun getFDY ()D
public final fun getFDZ ()D
public final fun getFOrigin ()[D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoBBox;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoBBox;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoBBox$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoBBox$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoBBox;
@ -145,7 +288,7 @@ public abstract class ru/mipt/npm/root/serialization/TGeoBoolNode : ru/mipt/npm/
public final fun getFLeftMat ()Lru/mipt/npm/root/serialization/TGeoMatrix;
public abstract fun getFRight ()Lru/mipt/npm/root/serialization/TGeoShape;
public final fun getFRightMat ()Lru/mipt/npm/root/serialization/TGeoMatrix;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoBoolNode;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoBoolNode;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoBoolNode$Companion {
@ -154,17 +297,14 @@ public final class ru/mipt/npm/root/serialization/TGeoBoolNode$Companion {
public final class ru/mipt/npm/root/serialization/TGeoCombiTrans : ru/mipt/npm/root/serialization/TGeoMatrix {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoCombiTrans$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;[DLru/mipt/npm/root/serialization/TGeoRotation;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> ([DLru/mipt/npm/root/serialization/TGeoRotation;)V
public synthetic fun <init> ([DLru/mipt/npm/root/serialization/TGeoRotation;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFRotation ()Lru/mipt/npm/root/serialization/TGeoRotation;
public final fun getFTranslation ()[D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoCombiTrans;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoCombiTrans$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoCombiTrans$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoCombiTrans;
@ -180,15 +320,12 @@ public final class ru/mipt/npm/root/serialization/TGeoCombiTrans$Companion {
public final class ru/mipt/npm/root/serialization/TGeoCompositeShape : ru/mipt/npm/root/serialization/TGeoBBox {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoCompositeShape$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;IDDD[DLru/mipt/npm/root/serialization/TGeoBoolNode;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lru/mipt/npm/root/serialization/TGeoBoolNode;)V
public final fun getFNode ()Lru/mipt/npm/root/serialization/TGeoBoolNode;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoCompositeShape;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoCompositeShape$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoCompositeShape$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoCompositeShape;
@ -204,17 +341,14 @@ public final class ru/mipt/npm/root/serialization/TGeoCompositeShape$Companion {
public final class ru/mipt/npm/root/serialization/TGeoHMatrix : ru/mipt/npm/root/serialization/TGeoMatrix {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoHMatrix$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;[D[D[DLkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> ([D[D[D)V
public final fun getFRotationMatrix ()[D
public final fun getFScale ()[D
public final fun getFTranslation ()[D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoHMatrix;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoHMatrix$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoHMatrix$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoHMatrix;
@ -231,13 +365,10 @@ public final class ru/mipt/npm/root/serialization/TGeoHMatrix$Companion {
public final class ru/mipt/npm/root/serialization/TGeoIdentity : ru/mipt/npm/root/serialization/TGeoMatrix {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoIdentity$Companion;
public fun <init> ()V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoIdentity;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoIdentity$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoIdentity$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoIdentity;
@ -253,16 +384,13 @@ public final class ru/mipt/npm/root/serialization/TGeoIdentity$Companion {
public final class ru/mipt/npm/root/serialization/TGeoIntersection : ru/mipt/npm/root/serialization/TGeoBoolNode {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoIntersection$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Lru/mipt/npm/root/serialization/TGeoMatrix;Lru/mipt/npm/root/serialization/TGeoMatrix;Lru/mipt/npm/root/serialization/TGeoShape;Lru/mipt/npm/root/serialization/TGeoShape;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lru/mipt/npm/root/serialization/TGeoShape;Lru/mipt/npm/root/serialization/TGeoShape;)V
public fun getFLeft ()Lru/mipt/npm/root/serialization/TGeoShape;
public fun getFRight ()Lru/mipt/npm/root/serialization/TGeoShape;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoIntersection;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoIntersection$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoIntersection$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoIntersection;
@ -279,17 +407,14 @@ public final class ru/mipt/npm/root/serialization/TGeoIntersection$Companion {
public final class ru/mipt/npm/root/serialization/TGeoManager : ru/mipt/npm/root/serialization/TNamed {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoManager$Companion;
public fun <init> ()V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lru/mipt/npm/root/serialization/TObjArray;Lru/mipt/npm/root/serialization/TObjArray;Lru/mipt/npm/root/serialization/TObjArray;Lru/mipt/npm/root/serialization/TObjArray;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFMatrices ()Lru/mipt/npm/root/serialization/TObjArray;
public final fun getFNodes ()Lru/mipt/npm/root/serialization/TObjArray;
public final fun getFShapes ()Lru/mipt/npm/root/serialization/TObjArray;
public final fun getFVolumes ()Lru/mipt/npm/root/serialization/TObjArray;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoManager;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoManager$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoManager$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoManager;
@ -307,12 +432,11 @@ public class ru/mipt/npm/root/serialization/TGeoMaterial : ru/mipt/npm/root/seri
public static final field Companion Lru/mipt/npm/root/serialization/TGeoMaterial$Companion;
public fun <init> ()V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoMaterial;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoMaterial;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoMaterial$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoMaterial$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoMaterial;
@ -329,7 +453,7 @@ public final class ru/mipt/npm/root/serialization/TGeoMaterial$Companion {
public abstract class ru/mipt/npm/root/serialization/TGeoMatrix : ru/mipt/npm/root/serialization/TNamed {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoMatrix$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoMatrix;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoMatrix;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoMatrix$Companion {
@ -338,17 +462,14 @@ public final class ru/mipt/npm/root/serialization/TGeoMatrix$Companion {
public final class ru/mipt/npm/root/serialization/TGeoMedium : ru/mipt/npm/root/serialization/TNamed {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoMedium$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;ILru/mipt/npm/root/serialization/TGeoMaterial;[DLkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (ILru/mipt/npm/root/serialization/TGeoMaterial;[D)V
public final fun getFId ()I
public final fun getFMaterial ()Lru/mipt/npm/root/serialization/TGeoMaterial;
public final fun getFParams ()[D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoMedium;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoMedium$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoMedium$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoMedium;
@ -365,13 +486,10 @@ public final class ru/mipt/npm/root/serialization/TGeoMedium$Companion {
public final class ru/mipt/npm/root/serialization/TGeoMixture : ru/mipt/npm/root/serialization/TGeoMaterial {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoMixture$Companion;
public fun <init> ()V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoMixture;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoMixture$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoMixture$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoMixture;
@ -394,12 +512,11 @@ public class ru/mipt/npm/root/serialization/TGeoNode : ru/mipt/npm/root/serializ
public final fun getFNumber ()I
public final fun getFOverlaps ()[I
public final fun getFVolume ()Lru/mipt/npm/root/serialization/TGeoVolume;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoNode;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoNode;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoNode$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoNode$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoNode;
@ -416,14 +533,11 @@ public final class ru/mipt/npm/root/serialization/TGeoNode$Companion {
public final class ru/mipt/npm/root/serialization/TGeoNodeMatrix : ru/mipt/npm/root/serialization/TGeoNode {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoNodeMatrix$Companion;
public fun <init> ()V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;Lru/mipt/npm/root/serialization/TGeoVolume;II[ILru/mipt/npm/root/serialization/TGeoMatrix;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFMatrix ()Lru/mipt/npm/root/serialization/TGeoMatrix;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoNodeMatrix;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoNodeMatrix$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoNodeMatrix$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoNodeMatrix;
@ -440,14 +554,11 @@ public final class ru/mipt/npm/root/serialization/TGeoNodeMatrix$Companion {
public final class ru/mipt/npm/root/serialization/TGeoNodeOffset : ru/mipt/npm/root/serialization/TGeoNode {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoNodeOffset$Companion;
public fun <init> ()V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;Lru/mipt/npm/root/serialization/TGeoVolume;II[IDLkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFOffset ()D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoNodeOffset;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoNodeOffset$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoNodeOffset$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoNodeOffset;
@ -471,12 +582,11 @@ public class ru/mipt/npm/root/serialization/TGeoPcon : ru/mipt/npm/root/serializ
public final fun getFRmax ()[D
public final fun getFRmin ()[D
public final fun getFZ ()[D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoPcon;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoPcon;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoPcon$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoPcon$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoPcon;
@ -495,12 +605,11 @@ public class ru/mipt/npm/root/serialization/TGeoPgon : ru/mipt/npm/root/serializ
public fun <init> ()V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;IDDD[DIDD[D[D[DILkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFNedges ()I
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoPgon;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoPgon;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoPgon$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoPgon$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoPgon;
@ -516,15 +625,12 @@ public final class ru/mipt/npm/root/serialization/TGeoPgon$Companion {
public final class ru/mipt/npm/root/serialization/TGeoRotation : ru/mipt/npm/root/serialization/TGeoMatrix {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoRotation$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;[DLkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> ([D)V
public final fun getFRotationMatrix ()[D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoRotation;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoRotation$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoRotation$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoRotation;
@ -543,7 +649,7 @@ public abstract class ru/mipt/npm/root/serialization/TGeoShape : ru/mipt/npm/roo
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;ILkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFShapeBits-pVg5ArA ()I
public final fun getFShapeId ()I
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoShape;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoShape;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoShape$Companion {
@ -552,17 +658,14 @@ public final class ru/mipt/npm/root/serialization/TGeoShape$Companion {
public final class ru/mipt/npm/root/serialization/TGeoShapeAssembly : ru/mipt/npm/root/serialization/TGeoBBox {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoShapeAssembly$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;IDDD[DLru/mipt/npm/root/serialization/TGeoVolumeAssembly;ZLkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lru/mipt/npm/root/serialization/TGeoVolumeAssembly;Z)V
public synthetic fun <init> (Lru/mipt/npm/root/serialization/TGeoVolumeAssembly;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFBBoxOK ()Z
public final fun getFVolume ()Lru/mipt/npm/root/serialization/TGeoVolumeAssembly;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoShapeAssembly;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoShapeAssembly$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoShapeAssembly$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoShapeAssembly;
@ -583,16 +686,13 @@ public final class ru/mipt/npm/root/serialization/TGeoShapeRef : ru/mipt/npm/roo
public final class ru/mipt/npm/root/serialization/TGeoSubtraction : ru/mipt/npm/root/serialization/TGeoBoolNode {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoSubtraction$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Lru/mipt/npm/root/serialization/TGeoMatrix;Lru/mipt/npm/root/serialization/TGeoMatrix;Lru/mipt/npm/root/serialization/TGeoShape;Lru/mipt/npm/root/serialization/TGeoShape;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lru/mipt/npm/root/serialization/TGeoShape;Lru/mipt/npm/root/serialization/TGeoShape;)V
public fun getFLeft ()Lru/mipt/npm/root/serialization/TGeoShape;
public fun getFRight ()Lru/mipt/npm/root/serialization/TGeoShape;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoSubtraction;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoSubtraction$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoSubtraction$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoSubtraction;
@ -608,15 +708,12 @@ public final class ru/mipt/npm/root/serialization/TGeoSubtraction$Companion {
public final class ru/mipt/npm/root/serialization/TGeoTranslation : ru/mipt/npm/root/serialization/TGeoMatrix {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoTranslation$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;[DLkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> ([D)V
public final fun getFTranslation ()[D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoTranslation;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoTranslation$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoTranslation$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoTranslation;
@ -637,12 +734,11 @@ public class ru/mipt/npm/root/serialization/TGeoTube : ru/mipt/npm/root/serializ
public final fun getFDz ()D
public final fun getFRmax ()D
public final fun getFRmin ()D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoTube;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoTube;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoTube$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoTube$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoTube;
@ -659,7 +755,6 @@ public final class ru/mipt/npm/root/serialization/TGeoTube$Companion {
public final class ru/mipt/npm/root/serialization/TGeoTubeSeg : ru/mipt/npm/root/serialization/TGeoTube {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoTubeSeg$Companion;
public fun <init> (DDDDDDDDD)V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;IDDD[DDDDDDDDDDDDDLkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFC1 ()D
public final fun getFC2 ()D
public final fun getFCdfi ()D
@ -669,12 +764,10 @@ public final class ru/mipt/npm/root/serialization/TGeoTubeSeg : ru/mipt/npm/root
public final fun getFS1 ()D
public final fun getFS2 ()D
public final fun getFSm ()D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoTubeSeg;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoTubeSeg$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoTubeSeg$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoTubeSeg;
@ -690,16 +783,13 @@ public final class ru/mipt/npm/root/serialization/TGeoTubeSeg$Companion {
public final class ru/mipt/npm/root/serialization/TGeoUnion : ru/mipt/npm/root/serialization/TGeoBoolNode {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoUnion$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Lru/mipt/npm/root/serialization/TGeoMatrix;Lru/mipt/npm/root/serialization/TGeoMatrix;Lru/mipt/npm/root/serialization/TGeoShape;Lru/mipt/npm/root/serialization/TGeoShape;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lru/mipt/npm/root/serialization/TGeoShape;Lru/mipt/npm/root/serialization/TGeoShape;)V
public fun getFLeft ()Lru/mipt/npm/root/serialization/TGeoShape;
public fun getFRight ()Lru/mipt/npm/root/serialization/TGeoShape;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoUnion;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoUnion$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoUnion$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoUnion;
@ -729,12 +819,11 @@ public class ru/mipt/npm/root/serialization/TGeoVolume : ru/mipt/npm/root/serial
public final fun getFNumber ()I
public final fun getFRefCount ()I
public final fun getFShape ()Lru/mipt/npm/root/serialization/TGeoShape;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoVolume;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoVolume;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoVolume$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoVolume$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoVolume;
@ -752,12 +841,11 @@ public class ru/mipt/npm/root/serialization/TGeoVolumeAssembly : ru/mipt/npm/roo
public static final field Companion Lru/mipt/npm/root/serialization/TGeoVolumeAssembly$Companion;
public fun <init> ()V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;ILjava/lang/Integer;Lkotlin/UInt;Ljava/lang/Integer;Ljava/lang/Integer;Lru/mipt/npm/root/serialization/TObjArray;Lru/mipt/npm/root/serialization/TGeoShape;Lru/mipt/npm/root/serialization/TGeoMedium;IIILkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoVolumeAssembly;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoVolumeAssembly;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoVolumeAssembly$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoVolumeAssembly$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoVolumeAssembly;
@ -784,7 +872,6 @@ public final class ru/mipt/npm/root/serialization/TGeoVolumeRef : ru/mipt/npm/ro
public final class ru/mipt/npm/root/serialization/TGeoXtru : ru/mipt/npm/root/serialization/TGeoBBox {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoXtru$Companion;
public fun <init> (IID[D[D[D[D[D[D)V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;IDDD[DIID[D[D[D[D[D[DLkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFNvert ()I
public final fun getFNz ()I
public final fun getFScale ()[D
@ -794,12 +881,10 @@ public final class ru/mipt/npm/root/serialization/TGeoXtru : ru/mipt/npm/root/se
public final fun getFY0 ()[D
public final fun getFZ ()[D
public final fun getFZcurrent ()D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoXtru;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoXtru$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoXtru$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoXtru;
@ -815,15 +900,12 @@ public final class ru/mipt/npm/root/serialization/TGeoXtru$Companion {
public final class ru/mipt/npm/root/serialization/THashList : ru/mipt/npm/root/serialization/TObject {
public static final field Companion Lru/mipt/npm/root/serialization/THashList$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/util/List;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/util/List;)V
public final fun getArr ()Ljava/util/List;
public static final fun write$Self (Lru/mipt/npm/root/serialization/THashList;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/THashList$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/THashList$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/THashList;
@ -839,15 +921,12 @@ public final class ru/mipt/npm/root/serialization/THashList$Companion {
public final class ru/mipt/npm/root/serialization/TList : ru/mipt/npm/root/serialization/TObject {
public static final field Companion Lru/mipt/npm/root/serialization/TList$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/util/List;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/util/List;)V
public final fun getArr ()Ljava/util/List;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TList;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TList$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TList$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TList;
@ -867,12 +946,11 @@ public class ru/mipt/npm/root/serialization/TNamed : ru/mipt/npm/root/serializat
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFName ()Ljava/lang/String;
public final fun getFTitle ()Ljava/lang/String;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TNamed;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TNamed;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TNamed$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TNamed$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TNamed;
@ -888,14 +966,11 @@ public final class ru/mipt/npm/root/serialization/TNamed$Companion {
public final class ru/mipt/npm/root/serialization/TObjArray : ru/mipt/npm/root/serialization/TObject {
public static final field Companion Lru/mipt/npm/root/serialization/TObjArray$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/util/List;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/util/List;)V
public final fun getArr ()Ljava/util/List;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TObjArray;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;Lkotlinx/serialization/KSerializer;)V
}
public final class ru/mipt/npm/root/serialization/TObjArray$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public synthetic fun <init> (Lkotlinx/serialization/KSerializer;)V
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
@ -917,7 +992,7 @@ public abstract class ru/mipt/npm/root/serialization/TObject {
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFBits-pVg5ArA ()I
public final fun getFUniqueID-pVg5ArA ()I
public static final fun write$Self (Lru/mipt/npm/root/serialization/TObject;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TObject;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TObject$Companion {

View File

@ -1,9 +1,6 @@
package ru.mipt.npm.root
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.double
import space.kscience.dataforge.meta.int
import space.kscience.dataforge.meta.set
import space.kscience.dataforge.meta.*
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.parseAsName
import space.kscience.dataforge.names.plus
@ -365,7 +362,7 @@ private fun buildVolume(volume: DGeoVolume, context: RootToSolidContext): Solid?
}
return if (group.children.isEmpty()) {
null
} else if (group.items.size == 1 && group.properties.own == null) {
} else if (group.items.size == 1 && group.properties.own.isEmpty()) {
group.items.values.first().apply { parent = null }
} else {
group

View File

@ -0,0 +1,4 @@
# Module compose-desktop-demo

View File

@ -0,0 +1,17 @@
public final class ComposableSingletons$MainKt {
public static final field INSTANCE LComposableSingletons$MainKt;
public static field lambda-1 Lkotlin/jvm/functions/Function2;
public static field lambda-2 Lkotlin/jvm/functions/Function3;
public static field lambda-3 Lkotlin/jvm/functions/Function3;
public fun <init> ()V
public final fun getLambda-1$compose_desktop_demo ()Lkotlin/jvm/functions/Function2;
public final fun getLambda-2$compose_desktop_demo ()Lkotlin/jvm/functions/Function3;
public final fun getLambda-3$compose_desktop_demo ()Lkotlin/jvm/functions/Function3;
}
public final class MainKt {
public static final fun App (Landroidx/compose/runtime/Composer;I)V
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}

View File

@ -0,0 +1,40 @@
plugins {
id("space.kscience.gradle.mpp")
alias(spclibs.plugins.compose)
}
kscience {
jvm()
useCoroutines()
commonMain{
implementation(projects.visionforgeSolid)
}
jvmMain {
implementation(projects.visionforgeComposeMultiplatform)
}
}
kotlin{
explicitApi = null
sourceSets{
commonMain{
dependencies {
implementation(compose.desktop.currentOs)
api(compose.preview)
}
}
}
}
compose{
desktop{
desktop {
application {
mainClass = "MainKt"
}
}
}
}

View File

@ -0,0 +1,33 @@
import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import space.kscience.dataforge.meta.set
import space.kscience.visionforge.compose.PropertyEditor
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
@Composable
@Preview
fun App(){
val options = remember {
Canvas3DOptions{
meta["custom.field"] = 32
}
}
PropertyEditor(
properties = options.meta,
descriptor = Canvas3DOptions.descriptor,
expanded = true
)
}
fun main() = application {
Window(onCloseRequest = ::exitApplication) {
MaterialTheme {
App()
}
}
}

View File

@ -1,21 +1,3 @@
public final class space/kscience/visionforge/gdml/demo/GDMLDemoApp : tornadofx/App {
public fun <init> ()V
}
public final class space/kscience/visionforge/gdml/demo/GDMLView : tornadofx/View {
public static final field Companion Lspace/kscience/visionforge/gdml/demo/GDMLView$Companion;
public fun <init> ()V
public fun getRoot ()Ljavafx/scene/Parent;
}
public final class space/kscience/visionforge/gdml/demo/GDMLView$Companion {
}
public final class space/kscience/visionforge/gdml/demo/GdmlFxDemoAppKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/gdml/demo/ReadFileKt {
public static final fun readFile (Lspace/kscience/visionforge/VisionManager;Ljava/io/File;)Lspace/kscience/visionforge/Vision;
public static final fun readFile (Lspace/kscience/visionforge/VisionManager;Ljava/lang/String;)Lspace/kscience/visionforge/Vision;

View File

@ -1,19 +1,23 @@
plugins {
id("space.kscience.gradle.mpp")
alias(spclibs.plugins.compose)
}
group = "demo"
kscience {
jvm()
// jvm()
js {
useCommonJs()
browser {
binaries.executable()
commonWebpackConfig {
cssSupport {
enabled.set(false)
commonWebpackConfig{
cssSupport{
enabled = true
}
scssSupport{
enabled = true
}
sourceMaps = true
}
}
}
@ -21,14 +25,12 @@ kscience {
implementation(projects.visionforgeSolid)
implementation(projects.visionforgeGdml)
}
jvmMain {
// implementation(project(":visionforge-fx"))
implementation(spclibs.logback.classic)
}
// jvmMain {
//// implementation(project(":visionforge-fx"))
// implementation(spclibs.logback.classic)
// }
jsMain {
implementation(projects.ui.ring)
implementation(projects.visionforgeThreejs)
implementation(npm("react-file-drop", "3.0.6"))
}
}
@ -36,30 +38,6 @@ kotlin {
explicitApi = null
}
//kotlin {
//
// sourceSets {
// commonMain {
// dependencies {
// implementation(project(":visionforge-solid"))
// implementation(project(":visionforge-gdml"))
// }
// }
// jvmMain {
// dependencies {
//// implementation(project(":visionforge-fx"))
// implementation("ch.qos.logback:logback-classic:1.2.11")
// }
// }
// jsMain {
// dependencies {
// implementation(project(":ui:ring"))
// implementation(project(":visionforge-threejs"))
// implementation(npm("react-file-drop", "3.0.6"))
// }
// }
// }
//}
//val convertGdmlToJson by tasks.creating(JavaExec::class) {
// group = "application"

View File

@ -34,6 +34,6 @@ class GDMLVisionTest {
val child = cubes[Name.of("composite-000","segment-0")]
assertNotNull(child)
child.properties.setValue(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue())
assertEquals("red", child.properties.getMeta(SolidMaterial.MATERIAL_COLOR_KEY).string)
assertEquals("red", child.properties[SolidMaterial.MATERIAL_COLOR_KEY].string)
}
}

View File

@ -1,50 +0,0 @@
@file:JsModule("react-file-drop")
@file:JsNonModule
package drop
import org.w3c.dom.DragEvent
import org.w3c.files.FileList
import react.Component
import react.Props
import react.State
sealed external class DropEffects {
@JsName("copy")
object Copy : DropEffects
@JsName("move")
object Move : DropEffects
@JsName("link")
object Link : DropEffects
@JsName("none")
object None : DropEffects
}
external interface FileDropProps : Props {
var className: String?
var targetClassName: String?
var draggingOverFrameClassName: String?
var draggingOverTargetClassName: String?
// var frame?: Exclude<HTMLElementTagNameMap[keyof HTMLElementTagNameMap], HTMLElement> | HTMLDocument;
var onFrameDragEnter: ((event: DragEvent) -> Unit)?
var onFrameDragLeave: ((event: DragEvent) -> Unit)?
var onFrameDrop: ((event: DragEvent) -> Unit)?
// var onDragOver: ReactDragEventHandler<HTMLDivElement>?
// var onDragLeave: ReactDragEventHandler<HTMLDivElement>?
var onDrop: ((files: FileList?, event: dynamic) -> Unit)?//event:DragEvent<HTMLDivElement>)
var dropEffect: DropEffects?
}
external interface FileDropState : State {
var draggingOverFrame: Boolean
var draggingOverTarget: Boolean
}
external class FileDrop : Component<FileDropProps, FileDropState> {
override fun render(): dynamic
}

View File

@ -0,0 +1,86 @@
@file:OptIn(ExperimentalComposeWebApi::class)
package space.kscience.visionforge.gdml.demo
import androidx.compose.runtime.*
import app.softwork.bootstrapcompose.Container
import app.softwork.bootstrapcompose.Icon
import org.jetbrains.compose.web.ExperimentalComposeWebApi
import org.jetbrains.compose.web.attributes.InputType
import org.jetbrains.compose.web.attributes.name
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.Input
import org.jetbrains.compose.web.dom.Text
import org.w3c.files.FileList
//https://codepen.io/zahedkamal87/pen/PobNNwE
@Composable
fun FileDrop(
title: String = "Drop files or Click here to select files to upload.",
onFileDrop: (FileList) -> Unit,
) {
var dragOver by remember { mutableStateOf(false) }
Container(attrs = {
id("dropzone")
style {
border(
width = 0.2.cssRem,
style = LineStyle.Dashed,
color = Color("#6583fe")
)
padding(2.cssRem)
borderRadius(0.25.cssRem)
backgroundColor(Color("#fff"))
textAlign("center")
fontSize(1.5.cssRem)
transitions {
all {
delay(0.25.s)
timingFunction(AnimationTimingFunction.EaseInOut)
properties("background-color")
}
}
cursor("pointer")
}
listOf("drag", "dragstart", "dragend", "dragenter").forEach {
addEventListener(it) { event ->
event.preventDefault()
event.stopPropagation()
}
}
onDragOver { event ->
event.preventDefault()
event.stopPropagation()
dragOver = true
}
onDragLeave { event ->
event.preventDefault()
event.stopPropagation()
dragOver = false
}
onDrop { event ->
event.preventDefault()
event.stopPropagation()
dragOver = false
event.dataTransfer?.files?.let {
onFileDrop(it)
}
}
}) {
Icon("cloud-upload"){ classes("dropzone-icon") }
Text(title)
Input(type = InputType.File, attrs = {
style {
display(DisplayStyle.None)
}
classes("dropzone-input")
name("files")
})
}
}
//
//dropzone.addEventListener("click", function(e) {
// dropzone_input.click();
//});

View File

@ -1,46 +1,35 @@
package space.kscience.visionforge.gdml.demo
import androidx.compose.runtime.*
import kotlinx.browser.window
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Deferred
import kotlinx.css.*
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.Div
import org.jetbrains.compose.web.dom.P
import org.jetbrains.compose.web.dom.Text
import org.w3c.files.File
import org.w3c.files.FileReader
import org.w3c.files.get
import react.Props
import react.dom.h2
import react.fc
import react.useState
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.names.Name
import space.kscience.gdml.Gdml
import space.kscience.gdml.decodeFromString
import space.kscience.visionforge.Colors
import space.kscience.visionforge.gdml.markLayers
import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.ring.ThreeCanvasWithControls
import space.kscience.visionforge.ring.tab
import space.kscience.visionforge.setAsRoot
import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.invoke
import styled.css
import styled.styledDiv
import space.kscience.visionforge.solid.three.compose.ThreeView
import space.kscience.visionforge.visionManager
external interface GDMLAppProps : Props {
var solids: Solids
var vision: Solid?
var selected: Name?
}
@JsExport
val GDMLApp = fc<GDMLAppProps>("GDMLApp") { props ->
var deferredVision: Deferred<Solid?> by useState {
CompletableDeferred(props.vision)
}
@Composable
fun GDMLApp(context: Context, initialVision: Solid?, selected: Name? = null) {
var vision: Solid? by remember { mutableStateOf(initialVision) }
fun readFileAsync(file: File): Deferred<Solid?> {
val deferred = CompletableDeferred<Solid?>()
fun readFileAsync(file: File) {
val visionManager = context.visionManager
FileReader().apply {
onload = {
val data = result as String
@ -49,7 +38,7 @@ val GDMLApp = fc<GDMLAppProps>("GDMLApp") { props ->
name.endsWith(".gdml") || name.endsWith(".xml") -> {
val gdml = Gdml.decodeFromString(data)
gdml.toVision().apply {
setAsRoot(props.solids.visionManager)
setAsRoot(visionManager)
console.info("Marking layers for file $name")
markLayers()
ambientLight {
@ -57,43 +46,38 @@ val GDMLApp = fc<GDMLAppProps>("GDMLApp") { props ->
}
}
}
name.endsWith(".json") -> props.solids.visionManager.decodeFromString(data)
name.endsWith(".json") -> visionManager.decodeFromString(data)
else -> {
window.alert("File extension is not recognized: $name")
error("File extension is not recognized: $name")
}
}
deferred.complete(parsedVision as? Solid ?: error("Parsed vision is not a solid"))
vision = parsedVision as? Solid ?: error("Parsed vision is not a solid")
Unit
}
readAsText(file)
}
return deferred
}
styledDiv {
css {
height = 100.vh - 12.pt
width = 100.vw
Div({
style {
height(100.vh - 12.pt)
width(100.vw)
}
child(ThreeCanvasWithControls) {
attrs {
this.solids = props.solids
this.builderOfSolid = deferredVision
this.selected = props.selected
tab("Load") {
h2 {
+"Drag and drop .gdml or .json VisionForge files here"
}
fileDrop("(drag file here)") { files ->
val file = files?.get(0)
if (file != null) {
deferredVision = readFileAsync(file)
}
}) {
ThreeView(context, vision, selected) {
Tab("Load") {
P {
Text("Drag and drop .gdml or .json VisionForge files here")
}
FileDrop("(drag file here)") { files ->
val file = files[0]
if (file != null) {
readFileAsync(file)
}
}
}
}
}
}

View File

@ -1,63 +1,57 @@
package space.kscience.visionforge.gdml.demo
import kotlinx.css.*
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.Style
import org.jetbrains.compose.web.renderComposable
import org.w3c.dom.Document
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
import space.kscience.gdml.GdmlShowCase
import space.kscience.visionforge.Application
import space.kscience.visionforge.Colors
import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.react.createRoot
import space.kscience.visionforge.react.render
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.html.Application
import space.kscience.visionforge.html.VisionForgeStyles
import space.kscience.visionforge.html.startApplication
import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.three.ThreePlugin
import space.kscience.visionforge.startApplication
import styled.injectGlobal
private class GDMLDemoApp : Application {
val context = Context("gdml-demo") {
plugin(ThreePlugin)
}
override fun start(document: Document, state: Map<String, Any>) {
val context = Context("gdml-demo"){
plugin(ThreePlugin)
}
injectGlobal {
html{
height = 100.pct
}
body{
height = 100.pct
display = Display.flex
alignItems = Align.stretch
}
"#application"{
width = 100.pct
display = Display.flex
alignItems = Align.stretch
}
}
val element = document.getElementById("application") ?: error("Element with id 'application' not found on page")
createRoot(element).render {
child(GDMLApp) {
val vision = GdmlShowCase.cubes().toVision().apply {
ambientLight {
color(Colors.white)
}
val vision = GdmlShowCase.cubes().toVision().apply {
ambientLight {
color(Colors.white)
}
}
renderComposable(element) {
Style(VisionForgeStyles)
Style {
"html" {
height(100.percent)
}
//println(context.plugins.fetch(VisionManager).encodeToString(vision))
attrs {
this.solids = context.request(Solids)
this.vision = vision
"body" {
height(100.percent)
display(DisplayStyle.Flex)
alignItems(AlignItems.Stretch)
}
"#application" {
width(100.percent)
display(DisplayStyle.Flex)
alignItems(AlignItems.Stretch)
}
}
GDMLApp(context, vision)
}
}
}

View File

@ -1,30 +0,0 @@
package space.kscience.visionforge.gdml.demo
import drop.FileDrop
import kotlinx.css.*
import org.w3c.files.FileList
import react.RBuilder
import styled.css
import styled.styledDiv
//TODO move styles to inline
fun RBuilder.fileDrop(title: String, action: (files: FileList?) -> Unit) {
styledDiv {
css {
border = Border(style = BorderStyle.dashed, width = 1.px, color = Color.orange)
flexGrow = 0.0
alignContent = Align.center
}
child(FileDrop::class) {
attrs {
onDrop = { files, _ ->
console.info("loaded $files")
action(files)
}
}
+title
}
}
}

View File

@ -1,3 +0,0 @@
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
config.module.rules.push(...ringConfig.module.rules)

View File

@ -1,5 +1,6 @@
plugins {
id("space.kscience.gradle.mpp")
alias(spclibs.plugins.compose)
}
kscience {
@ -9,27 +10,26 @@ kscience {
kotlin {
explicitApi = null
js {
useCommonJs()
browser {
binaries.executable()
commonWebpackConfig {
cssSupport {
enabled.set(false)
commonWebpackConfig{
cssSupport{
enabled = true
}
scssSupport{
enabled = true
}
sourceMaps = true
}
}
}
}
kscience {
dependencies {
implementation(projects.visionforge.visionforgeGdml)
implementation(projects.visionforge.visionforgePlotly)
implementation(projects.visionforge.visionforgeMarkdown)
implementation(projects.visionforge.visionforgeThreejs)
}
jsMain {
implementation(projects.ui.ring)
}
}

View File

@ -1,24 +1,20 @@
import kotlinx.css.*
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.Div
import org.jetbrains.compose.web.renderComposable
import org.w3c.dom.Document
import ringui.SmartTabs
import ringui.Tab
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
import space.kscience.plotly.models.Trace
import space.kscience.plotly.scatter
import space.kscience.visionforge.Application
import space.kscience.visionforge.Colors
import space.kscience.visionforge.JsVisionClient
import space.kscience.visionforge.html.Application
import space.kscience.visionforge.html.Tabs
import space.kscience.visionforge.html.VisionForgeStyles
import space.kscience.visionforge.html.startApplication
import space.kscience.visionforge.markup.MarkupPlugin
import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.react.createRoot
import space.kscience.visionforge.react.render
import space.kscience.visionforge.ring.ThreeCanvasWithControls
import space.kscience.visionforge.ring.ThreeWithControlsPlugin
import space.kscience.visionforge.ring.solid
import space.kscience.visionforge.solid.*
import space.kscience.visionforge.startApplication
import styled.css
import styled.styledDiv
import space.kscience.visionforge.solid.three.ThreePlugin
import space.kscience.visionforge.solid.three.compose.ThreeView
import kotlin.random.Random
fun Trace.appendXYLatest(x: Number, y: Number, history: Int = 400, xErr: Number? = null, yErr: Number? = null) {
@ -30,31 +26,32 @@ fun Trace.appendXYLatest(x: Number, y: Number, history: Int = 400, xErr: Number?
private class JsPlaygroundApp : Application {
val playgroundContext = Context {
plugin(ThreePlugin)
plugin(PlotlyPlugin)
plugin(MarkupPlugin)
}
override fun start(document: Document, state: Map<String, Any>) {
val playgroundContext = Context {
plugin(ThreeWithControlsPlugin)
plugin(JsVisionClient)
plugin(PlotlyPlugin)
}
// val solids = playgroundContext.request(Solids)
// val client = playgroundContext.request(JsVisionClient)
val element = document.getElementById("playground") ?: error("Element with id 'playground' not found on page")
createRoot(element).render {
styledDiv {
css {
padding = Padding(0.pt)
margin = Margin(0.pt)
height = 100.vh
width = 100.vw
renderComposable(element) {
Style(VisionForgeStyles)
Div({
style {
padding(0.pt)
margin(0.pt)
height(100.vh)
width(100.vw)
}
SmartTabs("gravity") {
}) {
Tabs("gravity") {
Tab("gravity") {
GravityDemo {
attrs {
this.solids = playgroundContext.request(Solids)
}
}
GravityDemo(playgroundContext)
}
// Tab("D0") {
@ -66,43 +63,34 @@ private class JsPlaygroundApp : Application {
// }
// }
Tab("spheres") {
styledDiv {
css {
height = 100.vh - 50.pt
Div({
style {
height(100.vh - 50.pt)
}
child(ThreeCanvasWithControls) {
val random = Random(112233)
attrs {
solids = playgroundContext.request(Solids)
solid {
ambientLight {
color(Colors.white)
}
repeat(100) {
sphere(5, name = "sphere[$it]") {
x = random.nextDouble(-300.0, 300.0)
y = random.nextDouble(-300.0, 300.0)
z = random.nextDouble(-300.0, 300.0)
material {
color(random.nextInt())
}
detail = 16
}
}) {
ThreeView(playgroundContext, SolidGroup {
ambientLight {
color(Colors.white)
}
repeat(100) {
sphere(5, name = "sphere[$it]") {
x = Random.nextDouble(-300.0, 300.0)
y = Random.nextDouble(-300.0, 300.0)
z = Random.nextDouble(-300.0, 300.0)
material {
color(Random.nextInt())
}
detail = 16
}
}
}
})
}
}
Tab("plotly") {
Plotly {
attrs {
plot = space.kscience.plotly.Plotly.plot {
scatter {
x(1, 2, 3)
y(5, 8, 7)
}
}
Plot(playgroundContext) {
scatter {
x(1, 2, 3)
y(5, 8, 7)
}
}
}
@ -110,6 +98,7 @@ private class JsPlaygroundApp : Application {
}
}
}
}
public fun main() {

View File

@ -1,110 +1,163 @@
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import app.softwork.bootstrapcompose.Column
import app.softwork.bootstrapcompose.Row
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.css.*
import react.Props
import react.fc
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.AttrBuilderContext
import org.jetbrains.compose.web.dom.Div
import org.w3c.dom.HTMLDivElement
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.meta.Meta
import space.kscience.plotly.Plot
import space.kscience.plotly.layout
import space.kscience.plotly.models.Trace
import space.kscience.visionforge.Colors
import space.kscience.visionforge.html.Vision
import space.kscience.visionforge.html.zIndex
import space.kscience.visionforge.markup.VisionOfMarkup
import space.kscience.visionforge.react.flexRow
import space.kscience.visionforge.ring.ThreeCanvasWithControls
import space.kscience.visionforge.ring.solid
import space.kscience.visionforge.plotly.asVision
import space.kscience.visionforge.solid.*
import styled.css
import styled.styledDiv
import space.kscience.visionforge.solid.three.compose.ThreeView
import kotlin.math.sqrt
external interface DemoProps : Props {
var solids: Solids
}
@Composable
fun Plot(
context: Context,
meta: Meta = Meta.EMPTY,
attrs: AttrBuilderContext<HTMLDivElement>? = null,
block: Plot.() -> Unit,
) = Vision(
context = context,
attrs = attrs,
meta = meta,
vision = Plot().apply(block).asVision()
)
val GravityDemo = fc<DemoProps> { props ->
val velocityTrace = Trace {
name = "velocity"
}
val energyTrace = Trace {
name = "energy"
}
val markup = VisionOfMarkup()
@Composable
fun Markup(
context: Context,
markup: VisionOfMarkup,
meta: Meta = Meta.EMPTY,
attrs: AttrBuilderContext<HTMLDivElement>? = null,
) = Vision(
context = context,
attrs = attrs,
meta = meta,
vision = markup
)
styledDiv {
css {
height = 100.vh - 50.pt
private val h = 100.0
@Composable
fun GravityDemo(context: Context) {
val velocityTrace = remember {
Trace {
name = "velocity"
}
styledDiv {
css {
height = 50.vh
}
val energyTrace = remember {
Trace {
name = "energy"
}
}
val markup = remember { VisionOfMarkup() }
val solid = remember {
SolidGroup {
pointLight(200, 200, 200, name = "light") {
color(Colors.white)
}
child(ThreeCanvasWithControls) {
attrs {
solids = props.solids
solid {
pointLight(200, 200, 200, name = "light"){
color(Colors.white)
}
ambientLight()
ambientLight()
sphere(5.0, "ball") {
detail = 16
color("red")
val h = 100.0
y = h
solids.context.launch {
val g = 10.0
val dt = 0.1
var time = 0.0
var velocity = 0.0
while (isActive) {
delay(20)
time += dt
velocity -= g * dt
val energy = g * y.toDouble() + velocity * velocity / 2
y = y.toDouble() + velocity * dt
sphere(5.0, "ball") {
detail = 16
color("red")
y = h
velocityTrace.appendXYLatest(time, y)
energyTrace.appendXYLatest(time, energy)
if (y.toDouble() <= 2.5) {
//conservation of energy
velocity = sqrt(2 * g * h)
}
box(200, 5, 200, name = "floor") {
y = -2.5
}
}
}
}
markup.content = """
## Bouncing sphere parameters
LaunchedEffect(solid) {
val ball = solid["ball"]!!
val g = 10.0
val dt = 0.1
var time = 0.0
var velocity = 0.0
while (isActive) {
delay(20)
time += dt
velocity -= g * dt
val energy = g * ball.y.toDouble() + velocity * velocity / 2
ball.y = ball.y.toDouble() + velocity * dt
**velocity** = $velocity
velocityTrace.appendXYLatest(time, ball.y)
energyTrace.appendXYLatest(time, energy)
**energy** = $energy
""".trimIndent()
}
}
}
if (ball.y.toDouble() <= 2.5) {
//conservation of energy
velocity = sqrt(2 * g * h)
}
box(200, 5, 200, name = "floor") {
y = -2.5
}
markup.content = """
## Bouncing sphere parameters
**velocity** = $velocity
**energy** = $energy
""".trimIndent()
}
}
Div({
style {
height(100.vh - 50.pt)
}
}) {
Div({
style {
height(50.vh)
}
}) {
ThreeView(context, solid)
}
Row(attrs = {
style {
alignContent(AlignContent.Stretch)
alignItems(AlignItems.Stretch)
height(50.vh - 50.pt)
}
}) {
Column {
Plot(context) {
traces(velocityTrace, energyTrace)
layout {
xaxis.title = "time"
}
}
}
}
flexRow {
css {
alignContent = Align.stretch
alignItems = Align.stretch
height = 50.vh - 50.pt
}
plotly {
traces(velocityTrace, energyTrace)
layout {
xaxis.title = "time"
}
}
Markup {
attrs {
this.markup = markup
}
Column {
Markup(context, markup, attrs = {
style {
width(100.percent)
height(100.percent)
border(2.pt, LineStyle.Solid, Color.blue)
paddingLeft(8.pt)
backgroundColor(Color.white)
flex(1)
zIndex(10000)
}
})
}
}
}

View File

@ -1,55 +0,0 @@
import kotlinx.css.*
import kotlinx.dom.clear
import kotlinx.html.dom.append
import org.intellij.markdown.flavours.commonmark.CommonMarkFlavourDescriptor
import org.intellij.markdown.flavours.gfm.GFMFlavourDescriptor
import org.w3c.dom.Element
import org.w3c.dom.HTMLElement
import react.Props
import react.fc
import react.useEffect
import react.useRef
import space.kscience.visionforge.markup.VisionOfMarkup
import space.kscience.visionforge.markup.markdown
import space.kscience.visionforge.useProperty
import styled.css
import styled.styledDiv
external interface MarkupProps : Props {
var markup: VisionOfMarkup?
}
val Markup = fc<MarkupProps>("Markup") { props ->
val elementRef = useRef<Element>(null)
useEffect(props.markup, elementRef) {
val element = elementRef.current as? HTMLElement ?: error("Markup element not found")
props.markup?.let { vision ->
val flavour = when (vision.format) {
VisionOfMarkup.COMMONMARK_FORMAT -> CommonMarkFlavourDescriptor()
VisionOfMarkup.GFM_FORMAT -> GFMFlavourDescriptor()
//TODO add new formats via plugins
else -> error("Format ${vision.format} not recognized")
}
vision.useProperty(VisionOfMarkup::content) { content: String? ->
element.clear()
element.append {
markdown(flavour) { content ?: "" }
}
}
}
}
styledDiv {
css {
width = 100.pct
height = 100.pct
border= Border(2.pt, BorderStyle.solid, Color.blue)
padding = Padding(left = 8.pt)
backgroundColor = Color.white
flex = Flex(1.0)
zIndex = 10000
}
ref = elementRef
}
}

View File

@ -1,43 +0,0 @@
import kotlinx.css.*
import org.w3c.dom.Element
import org.w3c.dom.HTMLElement
import react.*
import space.kscience.plotly.Plot
import space.kscience.plotly.PlotlyConfig
import space.kscience.plotly.plot
import styled.css
import styled.styledDiv
external interface PlotlyProps : Props {
var plot: Plot?
}
val Plotly = fc<PlotlyProps>("Plotly") { props ->
val elementRef = useRef<Element>(null)
useEffect(props.plot, elementRef) {
val element = elementRef.current as? HTMLElement ?: error("Plotly element not found")
props.plot?.let {
element.plot(PlotlyConfig {
responsive = true
}, it)
}
}
styledDiv {
css {
width = 100.pct
height = 100.pct
border = Border(2.pt, BorderStyle.solid, Color.blue)
flex = Flex(1.0)
}
ref = elementRef
}
}
fun RBuilder.plotly(plotbuilder: Plot.() -> Unit) = Plotly {
attrs {
this.plot = Plot().apply(plotbuilder)
}
}

View File

@ -1,3 +0,0 @@
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
config.module.rules.push(...ringConfig.module.rules)

View File

@ -1,6 +1,6 @@
public final class ru/mipt/npm/muon/monitor/Event {
public static final field $stable I
public static final field Companion Lru/mipt/npm/muon/monitor/Event$Companion;
public synthetic fun <init> (IILjava/util/List;Ljava/util/Collection;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V
public fun <init> (ILjava/util/List;Ljava/util/Collection;)V
public final fun component1 ()I
public final fun component2 ()Ljava/util/List;
@ -13,12 +13,11 @@ public final class ru/mipt/npm/muon/monitor/Event {
public final fun getTrack ()Ljava/util/List;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
public static final fun write$Self (Lru/mipt/npm/muon/monitor/Event;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/muon/monitor/Event$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field $stable I
public static final field INSTANCE Lru/mipt/npm/muon/monitor/Event$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/muon/monitor/Event;
@ -33,6 +32,7 @@ public final class ru/mipt/npm/muon/monitor/Event$Companion {
}
public final class ru/mipt/npm/muon/monitor/Model {
public static final field $stable I
public fun <init> (Lspace/kscience/visionforge/VisionManager;)V
public final fun displayEvent (Lru/mipt/npm/muon/monitor/Event;)V
public final fun encodeToString ()Ljava/lang/String;
@ -40,10 +40,10 @@ public final class ru/mipt/npm/muon/monitor/Model {
public final fun getRoot ()Lspace/kscience/visionforge/solid/SolidGroup;
public final fun getTracks ()Lspace/kscience/visionforge/solid/SolidGroup;
public final fun reset ()V
public final fun setTracks (Lspace/kscience/visionforge/solid/SolidGroup;)V
}
public final class ru/mipt/npm/muon/monitor/Monitor {
public static final field $stable I
public static final field CENTRAL_LAYER_Z F
public static final field GEOMETRY_TOLERANCE D
public static final field INSTANCE Lru/mipt/npm/muon/monitor/Monitor;
@ -61,9 +61,10 @@ public final class ru/mipt/npm/muon/monitor/ReadResourceKt {
}
public final class ru/mipt/npm/muon/monitor/SC1 {
public fun <init> (Ljava/lang/String;Lspace/kscience/visionforge/solid/Point3D;FFF)V
public synthetic fun <init> (Ljava/lang/String;Lspace/kscience/visionforge/solid/Point3D;FFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getCenter ()Lspace/kscience/visionforge/solid/Point3D;
public static final field $stable I
public fun <init> (Ljava/lang/String;Lspace/kscience/visionforge/solid/Float32Vector3D;FFF)V
public synthetic fun <init> (Ljava/lang/String;Lspace/kscience/visionforge/solid/Float32Vector3D;FFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getCenter ()Lspace/kscience/visionforge/solid/Float32Vector3D;
public final fun getName ()Ljava/lang/String;
public final fun getXSize ()F
public final fun getYSize ()F
@ -71,8 +72,9 @@ public final class ru/mipt/npm/muon/monitor/SC1 {
}
public final class ru/mipt/npm/muon/monitor/SC16 {
public fun <init> (Ljava/lang/String;Lspace/kscience/visionforge/solid/Point3D;)V
public final fun getCenter ()Lspace/kscience/visionforge/solid/Point3D;
public static final field $stable I
public fun <init> (Ljava/lang/String;Lspace/kscience/visionforge/solid/Float32Vector3D;)V
public final fun getCenter ()Lspace/kscience/visionforge/solid/Float32Vector3D;
public final fun getName ()Ljava/lang/String;
public final fun getPixels ()Ljava/util/Collection;
}
@ -80,11 +82,12 @@ public final class ru/mipt/npm/muon/monitor/SC16 {
public final class ru/mipt/npm/muon/monitor/server/MMServerKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
public static final fun module (Lio/ktor/application/Application;Lspace/kscience/dataforge/context/Context;)V
public static synthetic fun module$default (Lio/ktor/application/Application;Lspace/kscience/dataforge/context/Context;ILjava/lang/Object;)V
public static final fun module (Lio/ktor/server/application/Application;Lspace/kscience/dataforge/context/Context;)V
public static synthetic fun module$default (Lio/ktor/server/application/Application;Lspace/kscience/dataforge/context/Context;ILjava/lang/Object;)V
}
public final class ru/mipt/npm/muon/monitor/sim/Cos2TrackGenerator : ru/mipt/npm/muon/monitor/sim/TrackGenerator {
public static final field $stable I
public fun <init> (Lorg/apache/commons/math3/random/RandomGenerator;DFF)V
public synthetic fun <init> (Lorg/apache/commons/math3/random/RandomGenerator;DFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun generate ()Lorg/apache/commons/math3/geometry/euclidean/threed/Line;
@ -95,6 +98,7 @@ public final class ru/mipt/npm/muon/monitor/sim/Cos2TrackGenerator : ru/mipt/npm
}
public final class ru/mipt/npm/muon/monitor/sim/FixedAngleGenerator : ru/mipt/npm/muon/monitor/sim/TrackGenerator {
public static final field $stable I
public fun <init> (Lorg/apache/commons/math3/random/RandomGenerator;DDFF)V
public synthetic fun <init> (Lorg/apache/commons/math3/random/RandomGenerator;DDFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun generate ()Lorg/apache/commons/math3/geometry/euclidean/threed/Line;
@ -112,8 +116,8 @@ public final class ru/mipt/npm/muon/monitor/sim/LineKt {
public static final fun getY (Lorg/apache/commons/math3/geometry/euclidean/threed/Line;)D
public static final fun makeTrack (DDDD)Lorg/apache/commons/math3/geometry/euclidean/threed/Line;
public static final fun makeTrack (Lorg/apache/commons/math3/geometry/euclidean/threed/Vector3D;Lorg/apache/commons/math3/geometry/euclidean/threed/Vector3D;)Lorg/apache/commons/math3/geometry/euclidean/threed/Line;
public static final fun toPoint (Lorg/apache/commons/math3/geometry/euclidean/threed/Vector3D;)Lspace/kscience/visionforge/solid/Point3D;
public static final fun toPoints (Lorg/apache/commons/math3/geometry/euclidean/threed/Line;)Ljava/util/List;
public static final fun toKMathVector (Lorg/apache/commons/math3/geometry/euclidean/threed/Vector3D;)Lspace/kscience/visionforge/solid/Float32Vector3D;
public static final fun toKMathVectors (Lorg/apache/commons/math3/geometry/euclidean/threed/Line;)Ljava/util/List;
}
public final class ru/mipt/npm/muon/monitor/sim/MonitorKt {
@ -138,6 +142,7 @@ public abstract interface class ru/mipt/npm/muon/monitor/sim/TrackGenerator {
}
public final class ru/mipt/npm/muon/monitor/sim/UniformTrackGenerator : ru/mipt/npm/muon/monitor/sim/TrackGenerator {
public static final field $stable I
public fun <init> (Lorg/apache/commons/math3/random/RandomGenerator;FF)V
public synthetic fun <init> (Lorg/apache/commons/math3/random/RandomGenerator;FFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun generate ()Lorg/apache/commons/math3/geometry/euclidean/threed/Line;

View File

@ -1,5 +1,6 @@
plugins {
id("space.kscience.gradle.mpp")
alias(spclibs.plugins.compose)
application
}
@ -14,17 +15,22 @@ kscience {
fullStack(
"muon-monitor.js",
jvmConfig = { withJava() },
jsConfig = { useCommonJs() }
) {
commonWebpackConfig {
cssSupport {
enabled.set(false)
// jsConfig = { useCommonJs() },
browserConfig = {
webpackTask{
cssSupport{
enabled = true
}
scssSupport{
enabled = true
}
}
}
}
)
commonMain {
implementation(projects.visionforgeSolid)
implementation(projects.visionforgeComposeHtml)
}
jvmMain {
implementation("org.apache.commons:commons-math3:3.6.1")
@ -34,13 +40,14 @@ kscience {
implementation("ch.qos.logback:logback-classic:1.2.11")
}
jsMain {
implementation(projects.ui.ring)
implementation(projects.visionforgeThreejs)
//implementation(devNpm("webpack-bundle-analyzer", "4.4.0"))
}
}
kotlin{
explicitApi = null
}
kotlin.explicitApi = null
application {
mainClass.set("ru.mipt.npm.muon.monitor.server.MMServerKt")

View File

@ -71,7 +71,7 @@ class Model(val manager: VisionManager) {
fun reset() {
map.values.forEach {
it.properties.setMeta(SolidMaterial.MATERIAL_COLOR_KEY, null)
it.properties[SolidMaterial.MATERIAL_COLOR_KEY] = null
}
tracks.children.clear()
}

View File

@ -1,281 +1,113 @@
package ru.mipt.npm.muon.monitor
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import app.softwork.bootstrapcompose.Button
import app.softwork.bootstrapcompose.ButtonGroup
import app.softwork.bootstrapcompose.Color.Secondary
import app.softwork.bootstrapcompose.Container
import app.softwork.bootstrapcompose.Layout.Width
import kotlinx.browser.window
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.await
import kotlinx.coroutines.launch
import kotlinx.css.*
import kotlinx.html.js.onClickFunction
import kotlinx.serialization.json.Json
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.P
import org.jetbrains.compose.web.dom.Span
import org.jetbrains.compose.web.dom.Text
import org.w3c.fetch.RequestInit
import react.Props
import react.dom.attrs
import react.dom.button
import react.dom.p
import react.fc
import react.useMemo
import react.useState
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.meta.invoke
import space.kscience.dataforge.names.Name
import space.kscience.visionforge.Colors
import space.kscience.visionforge.react.flexColumn
import space.kscience.visionforge.react.flexRow
import space.kscience.visionforge.ring.ThreeCanvasWithControls
import space.kscience.visionforge.ring.tab
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.edges
import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import styled.css
import styled.styledDiv
import styled.styledSpan
import space.kscience.visionforge.solid.three.compose.ThreeView
import kotlin.math.PI
external interface MMAppProps : Props {
var model: Model
var solids: Solids
var selected: Name?
}
@Composable
fun MMApp(context: Context, model: Model, selected: Name? = null) {
@OptIn(DelicateCoroutinesApi::class)
@JsExport
val MMApp = fc<MMAppProps>("Muon monitor") { props ->
val mmOptions = useMemo {
val mmOptions = remember {
Canvas3DOptions {
camera {
distance = 2100.0
latitude = PI / 6
azimuth = PI + PI / 6
}
}
}
val root = useMemo(props.model) {
props.model.root.apply {
val root = remember(model) {
model.root.apply {
edges()
ambientLight{
ambientLight {
color(Colors.white)
}
}
}
var events: Set<Event> by useState(emptySet())
val events = remember { mutableStateListOf<Event>() }
styledDiv {
css {
height = 100.vh - 12.pt
Container(fluid = true,
attrs = {
style {
height(100.vh - 12.pt)
}
}
child(ThreeCanvasWithControls) {
attrs {
this.solids = props.solids
this.builderOfSolid = CompletableDeferred(root)
this.selected = props.selected
this.options = mmOptions
tab("Events") {
flexColumn {
flexRow {
button {
+"Next"
attrs {
onClickFunction = {
solids.context.launch {
val event = window.fetch(
"http://localhost:8080/event",
RequestInit("GET")
).then { response ->
if (response.ok) {
response.text()
} else {
error("Failed to get event")
}
}.then { body ->
Json.decodeFromString(Event.serializer(), body)
}.await()
events = events + event
props.model.displayEvent(event)
}
) {
ThreeView(
context,
solid = root,
initialSelected = selected,
options = mmOptions,
sidebarTabs = {
Tab("Events") {
ButtonGroup({ Layout.width = Width.Full }) {
Button("Next") {
context.launch {
val event = window.fetch(
"http://localhost:8080/event",
RequestInit("GET")
).then { response ->
if (response.ok) {
response.text()
} else {
error("Failed to get event")
}
}
}
button {
+"Clear"
attrs {
onClickFunction = {
events = emptySet()
props.model.reset()
}
}
}.then { body ->
Json.decodeFromString(Event.serializer(), body)
}.await()
events.add(event)
model.displayEvent(event)
}
}
Button("Clear", color = Secondary) {
events.clear()
model.reset()
}
}
events.forEach { event ->
p {
styledSpan {
+event.id.toString()
P {
Span {
Text(event.id.toString())
}
+" : "
styledSpan {
css {
color = Color.blue
Text(" : ")
Span({
style {
color(Color.blue)
}
+event.hits.toString()
}) {
Text(event.hits.toString())
}
}
}
}
}
}
)
}
// var selected by useState { props.selected }
//
// val onSelect: (Name?) -> Unit = {
// selected = it
// }
//
//
// gridRow {
// flexColumn {
// css {
// +"col-lg-3"
// +"order-lg-1"
// +"order-2"
// padding(0.px)
// overflowY = Overflow.auto
// height = 100.vh
// }
// //tree
// card("Object tree") {
// css {
// flex(1.0, 1.0, FlexBasis.auto)
// }
// visionTree(root, selected, onSelect)
// }
// }
// flexColumn {
// css {
// +"col-lg-6"
// +"order-lg-2"
// +"order-1"
// height = 100.vh
// }
// h1("mx-auto page-header") {
// +"Muon monitor demo"
// }
// //canvas
//
// child(ThreeCanvasComponent) {
// attrs {
// this.context = props.context
// this.solid = root
// this.selected = selected
// this.options = mmOptions
// }
// }
// }
// flexColumn {
// css {
// +"col-lg-3"
// +"order-3"
// padding(0.px)
// height = 100.vh
// }
// styledDiv {
// css {
// flex(0.0, 1.0, FlexBasis.zero)
// }
// //settings
// card("Canvas configuration") {
// canvasControls(mmOptions, root)
// }
//
// card("Events") {
// button {
// +"Next"
// attrs {
// onClickFunction = {
// GlobalScope.launch {
// val event = props.connection.get<Event>("http://localhost:8080/event")
// props.model.displayEvent(event)
// }
// }
// }
// }
// button {
// +"Clear"
// attrs {
// onClickFunction = {
// props.model.reset()
// }
// }
// }
// }
// }
// styledDiv {
// css {
// padding(0.px)
// }
// nav {
// attrs {
// attributes["aria-label"] = "breadcrumb"
// }
// ol("breadcrumb") {
// li("breadcrumb-item") {
// button(classes = "btn btn-link p-0") {
// +"World"
// attrs {
// onClickFunction = {
// selected = Name.EMPTY
// }
// }
// }
// }
// if (selected != null) {
// val tokens = ArrayList<NameToken>(selected?.length ?: 1)
// selected?.tokens?.forEach { token ->
// tokens.add(token)
// val fullName = Name(tokens.toList())
// li("breadcrumb-item") {
// button(classes = "btn btn-link p-0") {
// +token.toString()
// attrs {
// onClickFunction = {
// console.log("Selected = $fullName")
// selected = fullName
// }
// }
// }
// }
// }
// }
// }
// }
// }
// styledDiv {
// css {
// overflowY = Overflow.auto
// }
// //properties
// card("Properties") {
// selected.let { selected ->
// val selectedObject: Vision? = when {
// selected == null -> null
// selected.isEmpty() -> root
// else -> root[selected]
// }
// if (selectedObject != null) {
// visionPropertyEditor(selectedObject, key = selected)
// }
// }
// }
// }
// }
//
// }
}

View File

@ -1,15 +1,15 @@
package ru.mipt.npm.muon.monitor
import org.jetbrains.compose.web.css.Style
import org.jetbrains.compose.web.renderComposable
import org.w3c.dom.Document
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
import space.kscience.visionforge.Application
import space.kscience.visionforge.VisionManager
import space.kscience.visionforge.react.createRoot
import space.kscience.visionforge.react.render
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.html.Application
import space.kscience.visionforge.html.VisionForgeStyles
import space.kscience.visionforge.html.startApplication
import space.kscience.visionforge.solid.three.ThreePlugin
import space.kscience.visionforge.startApplication
private class MMDemoApp : Application {
@ -23,14 +23,9 @@ private class MMDemoApp : Application {
val model = Model(visionManager)
val element = document.getElementById("app") ?: error("Element with id 'app' not found on page")
createRoot(element).render {
child(MMApp) {
attrs {
this.model = model
this.solids = context.request(Solids)
}
}
renderComposable("app") {
Style(VisionForgeStyles)
MMApp(context, model)
}
}
}

View File

@ -1,3 +0,0 @@
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
config.module.rules.push(...ringConfig.module.rules)

View File

@ -3,6 +3,36 @@ public final class space/kscience/visionforge/examples/AllThingsDemoKt {
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/AntennaKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/AxesKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/BmnDemoKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/ControlVisionKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/DynamicPlotlyVisionKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/ExtrudedKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/FormServerKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
@ -28,6 +58,11 @@ public final class space/kscience/visionforge/examples/GenerateSchemaKt {
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/MarkdownVisionKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/PlotlyVisionKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
@ -38,17 +73,24 @@ public final class space/kscience/visionforge/examples/RandomSpheresKt {
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/RootParserKt {
public final class space/kscience/visionforge/examples/ServerExtensionsKt {
public static final fun makeVisionFile (Ljava/nio/file/Path;Ljava/lang/String;Lspace/kscience/visionforge/html/ResourceLocation;ZLspace/kscience/visionforge/html/HtmlVisionFragment;)V
public static synthetic fun makeVisionFile$default (Ljava/nio/file/Path;Ljava/lang/String;Lspace/kscience/visionforge/html/ResourceLocation;ZLspace/kscience/visionforge/html/HtmlVisionFragment;ILjava/lang/Object;)V
public static final fun serve (Ljava/lang/String;ZLspace/kscience/visionforge/html/HtmlVisionFragment;)V
public static synthetic fun serve$default (Ljava/lang/String;ZLspace/kscience/visionforge/html/HtmlVisionFragment;ILjava/lang/Object;)V
}
public final class space/kscience/visionforge/examples/ShapesKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/ServerExtensionsKt {
public static final fun makeVisionFile (Ljava/nio/file/Path;Ljava/lang/String;Lspace/kscience/visionforge/html/ResourceLocation;ZLkotlin/jvm/functions/Function1;)V
public static synthetic fun makeVisionFile$default (Ljava/nio/file/Path;Ljava/lang/String;Lspace/kscience/visionforge/html/ResourceLocation;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
public final class space/kscience/visionforge/examples/SimpleCubeKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/SimpleCubeKt {
public final class space/kscience/visionforge/examples/SurfaceKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}

View File

@ -14,16 +14,15 @@ repositories {
kotlin {
js(IR) {
useCommonJs()
browser {
webpackTask {
mainOutputFileName.set("js/visionforge-playground.js")
}
commonWebpackConfig {
sourceMaps = true
cssSupport{
enabled.set(false)
enabled = true
}
scssSupport{
enabled = true
}
mainOutputFileName.set("js/visionforge-playground.js")
}
}
binaries.executable()
@ -57,7 +56,6 @@ kotlin {
val jsMain by getting {
dependencies {
implementation(projects.ui.ring)
implementation(projects.visionforgeThreejs)
compileOnly(npm("webpack-bundle-analyzer","4.5.0"))
}

View File

@ -54,9 +54,6 @@
"cell_type": "code",
"execution_count": null,
"metadata": {
"jupyter": {
"outputs_hidden": false
},
"tags": []
},
"outputs": [],
@ -83,9 +80,6 @@
"language": "kotlin",
"name": "kotlin"
},
"ktnbPluginMetadata": {
"isAddProjectLibrariesToClasspath": false
},
"language_info": {
"codemirror_mode": "text/x-kotlin",
"file_extension": ".kt",
@ -94,6 +88,9 @@
"nbconvert_exporter": "",
"pygments_lexer": "kotlin",
"version": "1.8.20"
},
"ktnbPluginMetadata": {
"projectLibraries": []
}
},
"nbformat": 4,

View File

@ -0,0 +1,45 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"USE(JupyterCommonIntegration())"
]
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [],
"metadata": {
"collapsed": false
}
}
],
"metadata": {
"kernelspec": {
"display_name": "Kotlin",
"language": "kotlin",
"name": "kotlin"
},
"language_info": {
"name": "kotlin",
"version": "1.9.0",
"mimetype": "text/x-kotlin",
"file_extension": ".kt",
"pygments_lexer": "kotlin",
"codemirror_mode": "text/x-kotlin",
"nbconvert_exporter": ""
},
"ktnbPluginMetadata": {
"projectDependencies": true
}
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -25,10 +25,7 @@
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
"collapsed": false
},
"outputs": [],
"source": [
@ -84,7 +81,7 @@
"version": "1.8.0-dev-3517"
},
"ktnbPluginMetadata": {
"isAddProjectLibrariesToClasspath": false
"projectLibraries": []
}
},
"nbformat": 4,

View File

@ -1,14 +1,14 @@
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.visionforge.html.runVisionClient
import space.kscience.visionforge.jupyter.VFNotebookClient
import space.kscience.visionforge.markup.MarkupPlugin
import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.ring.ThreeWithControlsPlugin
import space.kscience.visionforge.runVisionClient
import space.kscience.visionforge.solid.three.ThreePlugin
import space.kscience.visionforge.tables.TableVisionJsPlugin
@DFExperimental
fun main() = runVisionClient {
plugin(ThreeWithControlsPlugin)
plugin(ThreePlugin)
plugin(PlotlyPlugin)
plugin(MarkupPlugin)
plugin(TableVisionJsPlugin)

View File

@ -2,7 +2,6 @@ package space.kscience.visionforge.examples
import kotlinx.html.h2
import space.kscience.dataforge.meta.ValueType
import space.kscience.dataforge.meta.invoke
import space.kscience.plotly.layout
import space.kscience.plotly.models.ScatterMode
import space.kscience.plotly.models.TextPosition
@ -11,9 +10,9 @@ import space.kscience.tables.ColumnHeader
import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.markup.markdown
import space.kscience.visionforge.plotly.plotly
import space.kscience.visionforge.solid.axes
import space.kscience.visionforge.solid.box
import space.kscience.visionforge.solid.solid
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.solid.z
import space.kscience.visionforge.tables.columnTable
import kotlin.io.path.Path
@ -34,14 +33,8 @@ fun main() = makeVisionFile(
h2 { +"3D visualization with Three-js" }
vision("3D") {
solid(
Canvas3DOptions {
axes {
size = 200.0
visible = true
}
}
) {
solid {
axes(200)
box(100, 100, 100, name = "aBox") {
z = 50.0
}

View File

@ -0,0 +1,71 @@
package space.kscience.visionforge.examples
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.html.h2
import kotlinx.html.p
import space.kscience.visionforge.VisionControlEvent
import space.kscience.visionforge.html.*
import space.kscience.visionforge.onSubmit
import kotlin.time.Duration.Companion.seconds
fun main() = serve {
val events = ArrayDeque<VisionControlEvent>(10)
val html = VisionOfPlainHtml()
fun pushEvent(event: VisionControlEvent) {
events.addFirst(event)
if (events.size >= 10) {
events.removeLast()
}
html.content {
events.forEach { event ->
p {
text(event.toString())
}
}
}
}
h2 { +"Control elements" }
vision {
htmlCheckBox {
checked = true
onValueChange(context) {
pushEvent(this)
}
}
}
vision {
htmlRangeField(1, 10) {
numberValue = 4
onValueChange(context) {
pushEvent(this)
}
context.launch {
while (isActive) {
delay(1.seconds)
numberValue = ((numberValue?.toInt() ?: 0) + 1) % 10
}
}
}
}
vision {
button("Click me") {
onSubmit(context) {
pushEvent(this)
}
}
}
vision(html)
}

View File

@ -0,0 +1,112 @@
package space.kscience.visionforge.examples
import io.ktor.server.cio.CIO
import io.ktor.server.engine.embeddedServer
import io.ktor.server.http.content.staticResources
import io.ktor.server.routing.routing
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.html.a
import kotlinx.html.h1
import space.kscience.dataforge.context.Global
import space.kscience.dataforge.context.request
import space.kscience.plotly.layout
import space.kscience.plotly.models.Trace
import space.kscience.plotly.models.invoke
import space.kscience.visionforge.html.VisionPage
import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.plotly.plotly
import space.kscience.visionforge.server.close
import space.kscience.visionforge.server.openInBrowser
import space.kscience.visionforge.server.visionPage
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin
fun main() {
val plotlyPlugin = Global.request(PlotlyPlugin)
val visionManager = plotlyPlugin.visionManager
val server = embeddedServer(CIO) {
routing {
staticResources("/", null)
}
val freq = 1.0 / 1000
val oscillationFreq = 1.0 / 10000
val x = (0..100).map { it.toDouble() / 100.0 }
val sinY = x.map { sin(2.0 * PI * it) }
val cosY = x.map { cos(2.0 * PI * it) }
val sinTrace = Trace(x, sinY) { name = "sin" }
val cosTrace = Trace(x, cosY) { name = "cos" }
visionPage(
visionManager,
VisionPage.scriptHeader("js/visionforge-playground.js"),
) {
h1 { +"This is the plot page" }
a("/other") { +"The other page" }
vision {
plotly {
traces(sinTrace, cosTrace)
layout {
title = "Other dynamic plot"
xaxis.title = "x axis name"
yaxis.title = "y axis name"
}
}
}
}
visionPage(
visionManager,
VisionPage.scriptHeader("js/visionforge-playground.js"),
route = "other"
) {
h1 { +"This is the other plot page" }
a("/") { +"Back to the main page" }
vision {
plotly {
traces(sinTrace)
layout {
title = "Dynamic plot"
xaxis.title = "x axis name"
yaxis.title = "y axis name"
}
}
}
}
//Start pushing updates
launch {
var time: Long = 0
while (isActive) {
delay(10)
time += 10
sinTrace.y.numbers = x.map { sin(2.0 * PI * (it + time.toDouble() * freq)) }
val cosAmp = cos(2.0 * PI * oscillationFreq * time)
cosTrace.y.numbers = x.map { cos(2.0 * PI * (it + time.toDouble() * freq)) * cosAmp }
}
}
}.start(false)
server.openInBrowser()
while (readlnOrNull() != "exit") {
}
server.close()
}

View File

@ -10,7 +10,7 @@ import space.kscience.dataforge.context.request
import space.kscience.visionforge.VisionManager
import space.kscience.visionforge.html.VisionOfHtmlForm
import space.kscience.visionforge.html.VisionPage
import space.kscience.visionforge.html.bindForm
import space.kscience.visionforge.html.visionOfForm
import space.kscience.visionforge.onPropertyChange
import space.kscience.visionforge.server.close
import space.kscience.visionforge.server.openInBrowser
@ -36,7 +36,7 @@ fun main() {
visionManager,
VisionPage.scriptHeader("js/visionforge-playground.js"),
) {
bindForm(form) {
visionOfForm(form) {
label {
htmlFor = "fname"
+"First name:"
@ -67,15 +67,15 @@ fun main() {
value = "Submit"
}
}
println(form.values)
vision(form)
println(form.values)
}
}.start(false)
server.openInBrowser()
while (readln() != "exit") {
while (readlnOrNull() != "exit") {
}

View File

@ -0,0 +1,19 @@
package space.kscience.visionforge.examples
import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.markup.markdown
fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
vision {
markdown{
content = """
# h1 Heading 8-)
## h2 Heading
### h3 Heading
#### h4 Heading
##### h5 Heading
###### h6 Heading
""".trimIndent()
}
}
}

View File

@ -1,23 +0,0 @@
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
const path = require('path');
config.module.rules.push(...ringConfig.module.rules)
config.module.rules.push(
{
test: /\.css$/,
exclude: [
path.resolve(__dirname, "../../node_modules/@jetbrains/ring-ui")
],
use: [
{
loader: 'style-loader',
options: {}
},
{
loader: 'css-loader',
options: {}
}
]
}
)

View File

@ -3,3 +3,8 @@ public final class ru/mipt/npm/sat/SatServerKt {
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class ru/mipt/npm/sat/StaticKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}

View File

@ -1,5 +1,9 @@
import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode
plugins {
id("space.kscience.gradle.jvm")
id("space.kscience.gradle.mpp")
alias(spclibs.plugins.ktor)
application
}
@ -8,8 +12,10 @@ kscience {
// useSerialization {
// json()
// }
useKtor()
dependencies{
jvm{
withJava()
}
jvmMain{
implementation("io.ktor:ktor-server-cio")
implementation(projects.visionforgeThreejs.visionforgeThreejsServer)
implementation(spclibs.logback.classic)
@ -18,6 +24,8 @@ kscience {
group = "center.sciprog"
kotlin.explicitApi = ExplicitApiMode.Disabled
application {
mainClass.set("ru.mipt.npm.sat.SatServerKt")
}

View File

@ -14,10 +14,12 @@ import space.kscience.dataforge.meta.Null
import space.kscience.dataforge.names.Name
import space.kscience.visionforge.Colors
import space.kscience.visionforge.html.VisionPage
import space.kscience.visionforge.html.meta
import space.kscience.visionforge.server.close
import space.kscience.visionforge.server.openInBrowser
import space.kscience.visionforge.server.visionPage
import space.kscience.visionforge.solid.*
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.three.threeJsHeader
import kotlin.random.Random
@ -47,7 +49,12 @@ fun main() {
) {
div("flex-column") {
h1 { +"Satellite detector demo" }
vision { sat }
vision {
meta(Canvas3DOptions {
controls.enabled = false
})
sat
}
}
}

View File

@ -1,20 +1,3 @@
public final class space/kscience/visionforge/demo/MetaEditorDemo : tornadofx/View {
public fun <init> ()V
public final fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;
public final fun getMeta ()Lspace/kscience/dataforge/meta/ObservableMutableMeta;
public synthetic fun getRoot ()Ljavafx/scene/Parent;
public fun getRoot ()Ljavafx/scene/control/SplitPane;
}
public final class space/kscience/visionforge/demo/MetaEditorDemoApp : tornadofx/App {
public fun <init> ()V
}
public final class space/kscience/visionforge/demo/MetaEditorDemoKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/solid/demo/DemoKt {
public static final fun demo (Lspace/kscience/visionforge/solid/demo/VisionLayout;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
public static synthetic fun demo$default (Lspace/kscience/visionforge/solid/demo/VisionLayout;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
@ -23,25 +6,8 @@ public final class space/kscience/visionforge/solid/demo/DemoKt {
public static final fun showcaseCSG (Lspace/kscience/visionforge/solid/demo/VisionLayout;)V
}
public final class space/kscience/visionforge/solid/demo/FXDemoApp : tornadofx/App {
public fun <init> ()V
public final fun getView ()Lspace/kscience/visionforge/solid/demo/FXDemoGrid;
public fun start (Ljavafx/stage/Stage;)V
}
public final class space/kscience/visionforge/solid/demo/FXDemoAppKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/solid/demo/FXDemoGrid : tornadofx/View, space/kscience/visionforge/solid/demo/VisionLayout {
public fun <init> ()V
public fun getRoot ()Ljavafx/scene/Parent;
public synthetic fun render (Lspace/kscience/dataforge/names/Name;Lspace/kscience/visionforge/Vision;Lspace/kscience/dataforge/meta/Meta;)V
public fun render (Lspace/kscience/dataforge/names/Name;Lspace/kscience/visionforge/solid/Solid;Lspace/kscience/dataforge/meta/Meta;)V
}
public abstract interface class space/kscience/visionforge/solid/demo/VisionLayout {
public abstract fun getSolids ()Lspace/kscience/visionforge/solid/Solids;
public abstract fun render (Lspace/kscience/dataforge/names/Name;Lspace/kscience/visionforge/Vision;Lspace/kscience/dataforge/meta/Meta;)V
public static synthetic fun render$default (Lspace/kscience/visionforge/solid/demo/VisionLayout;Lspace/kscience/dataforge/names/Name;Lspace/kscience/visionforge/Vision;Lspace/kscience/dataforge/meta/Meta;ILjava/lang/Object;)V
}

View File

@ -8,6 +8,16 @@ kscience {
jvm()
js{
binaries.executable()
browser{
commonWebpackConfig{
cssSupport{
enabled = true
}
scssSupport{
enabled = true
}
}
}
}
dependencies {
implementation(projects.visionforgeSolid)

View File

@ -24,6 +24,11 @@ fun VisionLayout<Solid>.demo(name: String, title: String = name, block: SolidGro
block()
ambientLight {
color(Colors.white)
intensity = 0.5
}
pointLight(0, 0, 1000) {
color(Colors.white)
intensity = 10.0
}
}
render(Name.parse(name), vision, meta)
@ -33,10 +38,6 @@ val canvasOptions = Canvas3DOptions {
size {
minSize = 400
}
axes {
size = 500.0
visible = true
}
camera {
distance = 600.0
latitude = PI / 6
@ -47,6 +48,8 @@ val canvasOptions = Canvas3DOptions {
fun VisionLayout<Solid>.showcase() {
demo("shapes", "Basic shapes") {
ambientLight()
axes(size = 500.0)
box(100.0, 100.0, 100.0) {
z = -110.0
color("teal")
@ -111,7 +114,7 @@ fun VisionLayout<Solid>.showcase() {
GlobalScope.launch(Dispatchers.Main) {
while (isActive) {
delay(100)
rotate((PI/20).radians,Euclidean3DSpace.yAxis)
rotate((PI / 20).radians, Euclidean3DSpace.yAxis)
}
}
color(Colors.red)
@ -122,13 +125,16 @@ fun VisionLayout<Solid>.showcase() {
demo("extrude", "extruded shape") {
extruded {
shape {
polygon(8, 50)
polygon(32, 50)
}
for (i in 0..100) {
layer(i * 5, 20 * sin(2 * PI / 100 * i), 20 * cos(2 * PI / 100 * i))
}
color(Colors.teal)
rotationX = -PI / 2
rotationY = -PI / 2
material {
type = "lambert"
color(Colors.teal)
}
}
}
@ -161,7 +167,15 @@ fun VisionLayout<Solid>.showcase() {
}
demo("STL", "STL loaded from URL") {
stl("https://ozeki.hu/attachments/116/Menger_sponge_sample.stl")
stl("Menger_sponge_sample.stl") {
scale(100f)
material {
type = "phong"
color("red")
specularColor("blue")
}
}
//stl("https://ozeki.hu/attachments/116/Menger_sponge_sample.stl")
}
}

View File

@ -4,10 +4,10 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import org.w3c.dom.Document
import space.kscience.visionforge.Application
import space.kscience.visionforge.html.Application
import space.kscience.visionforge.html.startApplication
import space.kscience.visionforge.solid.x
import space.kscience.visionforge.solid.y
import space.kscience.visionforge.startApplication
import kotlin.random.Random
private class ThreeDemoApp : Application {

View File

@ -72,7 +72,7 @@ class ThreeDemoGrid(element: Element) : VisionLayout<Solid> {
}
}
val element = document.getElementById("output-$name") ?: error("Element not found")
three.getOrCreateCanvas(element, canvasOptions)
ThreeCanvas(three, element, canvasOptions)
}.render(vision)
}
}

View File

@ -46,7 +46,7 @@ internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision
mesh.scale.z = properties.getValue(VALUE)?.number?.toDouble() ?: 1.0
//add listener to object properties
onPropertyChange { name ->
onPropertyChange(three.context) { name ->
when {
name == VALUE -> {
val value = properties.getValue(VALUE)?.int ?: 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -0,0 +1,416 @@
# Event Display Tutorial
In this tutorial, we will explore properties of Visions and build a simple front-end application. You may find a complete project [here](https://git.sciprog.center/teldufalsari/visionforge-event-display-demo).
__NOTE:__ You will need Kotlin Multiplatform 1.9.0 or higher to complete this tutorial!
### Starting the Project
We will use Idea's default project template for Kotlin Multiplatform. To initialize the project, go to *File -> New -> Project...*, Then choose *Full-Stack Web Application* project template and
*Kotlin Gradle* build system. Then select *Next -> Finish*. You will end up with a project with some sample code.
To check that everything is working correctly, run *application -> run* Gradle target. You should see a greeting page when you open `http://localhost:8080` in a web browser.
We will use Kotlin React as our main UI library and Ktor Netty both as a web server. Our event display frontend and server will reside in `jsMain` and `jvmMain` directories respectively.
Before we start, we have to load necessary dependencies:
* Add SciProgCentre maven repo in `build.gradle.kts` file:
```kotlin
repositories {
mavenCentral()
maven("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven")
// Add either the line below:
maven("https://repo.kotlin.link")
// Or this line:
maven("https://maven.sciprog.center/kscience")
}
```
* Add `visionforge-threejs-server` into the list of JS dependencies of your project:
```kotlin
kotlin {
sourceSets {
val jsMain by getting {
dependencies {
implementation("space.kscience:visionforge-threejs-server:0.3.0-dev-14")
}
}
}
}
```
Refresh build model in the Idea to make sure the dependencies are successfully resolved.
__NOTE:__ In previous versions of VisionForge, some imports may be broken. If these dependencies fail to resolve, replace `space.kscience:visionforge-threejs-server:0.3.0-dev-14` with `space.kscience:visionforge-threejs:0.3.0-dev-14`. The resulting bundle will lack a React component used in the tutorial (see "Managing Visions"). You may copy and paste it directly from either [VisionForge](https://git.sciprog.center/kscience/visionforge/src/branch/master/ui/react/src/main/kotlin/space/kscience/visionforge/react/ThreeCanvasComponent.kt) or the [tutorial repo](https://git.sciprog.center/teldufalsari/visionforge-event-display-demo/src/branch/main/src/jsMain/kotlin/canvas/ThreeCanvasComponent.kt), or even come up with a better implementation if your own.
### Setting up Page Markup
We need to create a page layout and set up Netty to serve our page to clients. There is nothing special related to VisionForge, so feel free to copy and paste the code below.
File: `src/jvmMain/.../Server.kt`
```kotlin
// ... imports go here
fun HTML.index() {
head {
// Compatibility headers
meta { charset = "UTF-8" }
meta {
name = "viewport"
content = "width=device-width, initial-scale=1.0"
}
meta {
httpEquiv = "X-UA-Compatible"
content = "IE=edge"
}
title("VF Demo")
}
// Link to our react script
body {
script(src = "/static/vf-demo.js") {}
}
}
fun main() {
// Seting up Netty
embeddedServer(Netty, port = 8080, host = "127.0.0.1") {
routing {
get("/") {
call.respondHtml(HttpStatusCode.OK, HTML::index)
}
static("/static") {
resources()
}
}
}.start(wait = true)
}
```
File: `src/jsMain/.../Client.kt`
```kotlin
fun main() {
val container = document.createElement("div")
document.body!!.appendChild(container)
val eventDisplay = EventDisplay.create {}
createRoot(container).render(eventDisplay)
}
```
File: `src/jsMain/.../Display.kt`
```kotlin
// All markup goes here:
val EventDisplay = FC<Props> {
// Global CSS rules
Global {
styles {
"html,\n" +
"body" {
height = 100.vh
width = 100.vw
margin = 0.px
}
"body > div" {
height = 100.vh
width = 100.vw
display = Display.flex
flexDirection = FlexDirection.column
justifyContent = JustifyContent.start
alignItems = AlignItems.center
}
"*,\n" +
"*:before,\n" +
"*:after" {
boxSizing = BoxSizing.borderBox
}
}
}
div {
css {
height = 100.pct
width = 100.pct
display = Display.flex
flexDirection = FlexDirection.column
alignItems = AlignItems.center
}
div {
css {
width = 100.pct
display = Display.flex
flexDirection = FlexDirection.row
alignItems = AlignItems.center
justifyContent = JustifyContent.center
}
input {
css {
margin = 5.px
padding = 5.px
}
type = InputType.button
value = "Update Events"
}
input {
css {
margin = 5.px
padding = 5.px
}
type = InputType.button
value = "Update Geometry"
}
}
div {
css {
width = 98.pct
height = 1.pct
margin = 5.px
display = Display.flex
flexGrow = number(1.0)
justifyContent = JustifyContent.center
alignItems = AlignItems.center
backgroundColor = Color("#b3b3b3")
}
}
}
}
```
After setting everything up, you should see a gray rectangle with two buttons above it when opening `localhost:8080`.
### Managing Visions
We are approaching the main part of the tutorial - the place where we will create a working demo. In particle accelerator experiments, event displays are employed to visualise particle collision events. Essentially, it requires drawing a detector setup and visual interpretation of events: tracks, detector hits etc. Usually, a number of events share a common detector setup (e.g. if these events occured in a single experiment run). It makes sense to update and re-render only event information, while keeping detector geometry constant between updates.
Visions (namely, the `SolidGroup` class) allow us to create an object tree for our displayed event. `SolidGroup` can hold other Visions as its child nodes, access these nodes by names and update/delete them. We will use this property to update our event display efficiently.
To display Visions as actual 3D object, we will use `ThreePlugin` that renders Visions using *three.js* library. The plugin allows us to create a Three.js representation of a vision that will observe changes of its correspondent Vision. This way we can update only Visions without diving deep into three.js stuff. Using observable Visions is also efficient: Three.js representations are not generated from scratch after each Vision update but are modified too.
First, let's simulate data load operations:
* Add state variables to our `EventDisplay` React component. These variables will be treated as data loaded from a remote server. In real life, these may be JSON string with event data:
```kotlin
val EventDisplay = FC<Props> {
// ...
var eventData: kotlin.Float? by useState(null)
var geometryData: kotlin.Float? by useState(null)
// ...
}
```
* Write two simple functions that will convert data to a Vision. In this case, we will simply parameters of solids like color of size; in real life, these functions will usually take raw data and convert it into Visions.
```kotlin
fun generateEvents(radius: Float): SolidGroup {
val count = Random.nextInt(10, 20)
return SolidGroup {
repeat(count) {
sphere(radius) {
x = 5.0 * (Random.nextFloat() - 0.5)
y = 2.0 * (Random.nextFloat() - 0.5)
z = 2.0 * (Random.nextFloat() - 0.5)
color(Colors.red)
}
}
}
}
fun generateGeometry(distance: Float): SolidGroup {
return SolidGroup {
box(10, 3, 3) {
x = 0.0
y = -distance
z = 0.0
color(Colors.gray)
}
box(10, 3, 3) {
x = 0.0
y = distance
z = 0.0
color(Colors.gray)
}
}
}
```
* Then, let's create our main Vision and add a static light source:
```kotlin
val EventDisplay = FC<Props> {
// ...
val containedVision: SolidGroup by useState(SolidGroup {
ambientLight {
color(Colors.white)
}
})
// ...
}
```
* A `Context` object is required to hold plugins like `ThreePlugin`. It is also necessary to make Visions observable: we have to root our main Vision in the context. Declare a global `Context` in the same file with `EventDisplay` component:
```kotlin
val viewContext = Context {
plugin(Solids)
plugin(ThreePlugin)
}
```
* Import `ThreeCanvasComponent` from VisionForge. This is a React component that handles all display work. It creates three.js canvas, attaches it to its own parent element and creates and draws `Object3D` on the canvas. We will attach this component to a
separate React component. Note order for Visions to update their Three.js representations, these Visions need to be rooted in a `Context`. This way Visions will be observed for changes, and any such change will trigger an update of the corresponding Three.js object.
```kotlin
external interface EventViewProps: Props {
var displayedVision: Solid?
var context: Context
}
val EventView = FC<EventViewProps> { props ->
ThreeCanvasComponent {
solid = props.displayedVision
context = props.context
}
// Make displayedVision observed:
useEffect(props.displayedVision) {
props.displayedVision?.setAsRoot(props.context.visionManager)
}
}
```
__NOTE:__ If you had problems with dependency resolution, `ThreeCanvasComponent` may missing from your import scope. You may find a compatible implementation [here](https://git.sciprog.center/teldufalsari/visionforge-event-display-demo/src/branch/main/src/jsMain/kotlin/canvas/ThreeCanvasComponent.kt).
* Finally, we need to attach EventView to our main component and connect raw data updates to Vision updates using React hooks:
```kotlin
// ...
// Names used as keys to access and update Visions
// Refer to DataForge documentation for more details
val EVENTS_NAME = "DEMO_EVENTS".parseAsName(false)
val GEOMETRY_NAME = "DEMO_GEOMETRY".parseAsName(false)
// ...
val EventDisplay = FC<Props> {
// ...
useEffect(eventData) {
eventData?.let {
containedVision.setChild(EVENTS_NAME, generateEvents(it))
}
}
useEffect(geometryData) {
geometryData?.let {
containedVision.setChild(GEOMETRY_NAME, generateGeometry(it))
}
}
// ...
div {
// ...
div {
css {
width = 98.pct
height = 1.pct
flexGrow = number(1.0)
margin = 5.px
display = Display.flex
justifyContent = JustifyContent.center
alignItems = AlignItems.center
}
// Replace the gray rectangle with an EventView:
EventView {
displayedVision = containedVision
context = viewContext
}
}
}
// ...
}
```
When we press either of the buttons, corresponding raw data changes. This update triggers `UseEffect` hook, which generates new event or geometry data and replaces the old data in the main Vision. Three.js representation is then updated to match our new Vision, so that changes are visible on the canvas.
Recompile the project and go on `http://localhost:8080`. See how the displayed scene changes with each click: for example, when you update geometry, only the distance between "magnets" varies, but spheres remain intact.
### Clearing the Scene
We can erase children Visions from the scene completely. To do so, we cat pass `null` to the function `setChild` as `child` argument. Add these lines to the hooks that update Visions to remove the corresponding Vision from our diplayed `SolidGroup` when raw data changes to `null`:
```kotlin
useEffect(eventData) {
// ...
if (eventData == null) {
containedVision.setChild(EVENT_NAME, null)
}
}
useEffect(geometryData) {
// ...
if (geometryData == null) {
containedVision.setChild(GEOMETRY_NAME, null)
}
}
```
To test how this works, let's create an erase button that will completely clear the scene:
```kotlin
val EventDisplay = FC<Props> {
// ...
div {
// ...
input {
css {
margin = 5.px
padding = 5.px
backgroundColor = NamedColor.lightcoral
color = NamedColor.white
}
type = InputType.button
value = "Clear Scene"
onClick = {
geometryData = null
eventData = null
}
}
}
// ...
}
```
![Picture of an event display with a red button with a caption "Clear Scene" added to the two previous buttons](../images/event-display-final.png "Scene clearing function")
### Making Selection Fine-Grained
You may feel annoyed by how selection works in our demo. That's right, selecting the whole detector or the entire event array is not that useful. This is due to the fact that VisionForge selects object based on names. We used names to distinguish SolidGroups, but in fact not only groups but every single Vision can have a name. But when we were randomly generating Vision, we did not use any names, did we? Right, Vision can be nameless, in which case they are treated as a monolithic object together with their parent. So it should be clear now that when we were selecting a single rectangle, we were in fact selecting the whole pair of rectangles and the other one went lit up as well.
Fortunately, every `Solid` constructor takes a `name` parameter after essential parameters, so it should be easy to fix it. Go to the generator functions and add the change construction invocations to the following:
```kotlin
fun generateGeometry(distance: Float): SolidGroup {
return SolidGroup {
box(10, 3, 3, "Magnet1") {
// ...
}
box(10, 3, 3, "Magnet2") {
// ...
}
}
}
```
For the events part, we will use the index in a loop as a name:
```kotlin
fun generateEvents(radius: Float): SolidGroup {
// ...
repeat(count) {
sphere(radius, it.toString()) {
// ...
}
```
After you update the build, it should be possible to select only one sphere or rectangle:
![Picture of an event display with only one sphere between the magnets selected](../images/event-display-selection.png "Selection demonstration")

View File

@ -1,7 +1,6 @@
kotlin.code.style=official
kotlin.mpp.stability.nowarn=true
kotlin.js.compiler=ir
#kotlin.incremental.js.ir=true
org.gradle.parallel=true
org.gradle.jvmargs=-Xmx4G

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@ -40,13 +40,9 @@ dependencyResolutionManagement {
}
include(
// ":ui",
":ui:react",
":ui:ring",
// ":ui:material",
":ui:bootstrap",
// ":ui:compose",
":visionforge-core",
":visionforge-compose-html",
":visionforge-compose-multiplatform",
":visionforge-solid",
// ":visionforge-fx",
":visionforge-threejs",
@ -64,6 +60,7 @@ include(
":demo:playground",
// ":demo:plotly-fx",
":demo:js-playground",
":demo:compose-desktop-demo",
":visionforge-jupyter",
":visionforge-jupyter:visionforge-jupyter-common"
)

View File

@ -1,4 +0,0 @@
# Module ui

View File

@ -1,4 +0,0 @@
# Module bootstrap

View File

@ -1,19 +0,0 @@
plugins {
id("space.kscience.gradle.mpp")
}
val dataforgeVersion: String by rootProject.extra
kscience{
js()
jsMain{
dependencies {
api(project(":visionforge-solid"))
api(project(":ui:react"))
implementation(npm("file-saver", "2.0.2"))
implementation(npm("bootstrap","4.6.0"))
implementation(npm("jquery","3.5.1"))
implementation(npm("popper.js","1.16.1"))
}
}
}

View File

@ -1,121 +0,0 @@
package space.kscience.visionforge.bootstrap
public fun useBootstrap(){
kotlinext.js.require<dynamic>("bootstrap/dist/css/bootstrap.min.css")
kotlinext.js.require<dynamic>("bootstrap")
}
//public inline fun TagConsumer<HTMLElement>.card(title: String, crossinline block: TagConsumer<HTMLElement>.() -> Unit) {
// div("card w-100") {
// div("card-body") {
// h3(classes = "card-title") { +title }
// block()
// }
// }
//}
//public typealias SectionsBuilder = MutableList<Pair<String, DIV.() -> Unit>>
//
//public fun SectionsBuilder.entry(title: String, builder: DIV.() -> Unit) {
// add(title to builder)
//}
//public fun TagConsumer<HTMLElement>.accordion(id: String, elements: List<Pair<String, DIV.() -> Unit>>) {
// div("container-fluid") {
// div("accordion") {
// this.id = id
// elements.forEachIndexed { index, (title, builder) ->
// val headerID = "${id}-${index}-heading"
// val collapseID = "${id}-${index}-collapse"
// div("card") {
// div("card-header") {
// this.id = headerID
// h5("mb-0") {
// button(classes = "btn btn-link collapsed", type = ButtonType.button) {
// attributes["data-toggle"] = "collapse"
// attributes["data-target"] = "#$collapseID"
// attributes["aria-expanded"] = "false"
// attributes["aria-controls"] = collapseID
// +title
// }
// }
// }
// div("collapse") {
// this.id = collapseID
// attributes["aria-labelledby"] = headerID
// attributes["data-parent"] = "#$id"
// div("card-body", block = builder)
// }
// }
// }
// }
// }
//}
//public fun TagConsumer<HTMLElement>.accordion(id: String, builder: AccordionBuilder.() -> Unit) {
// val list = ArrayList<Pair<String, DIV.() -> Unit>>().apply(builder)
// accordion(id, list)
//}
//public fun Element.displayCanvasControls(canvas: ThreeCanvas, block: TagConsumer<HTMLElement>.() -> Unit = {}) {
// clear()
// append {
// accordion("controls") {
// entry("Settings") {
// div("row") {
// div("col-2") {
// label("checkbox-inline") {
// input(type = InputType.checkBox) {
// checked = canvas.axes.visible
// onChangeFunction = {
// canvas.axes.visible = checked
// }
// }
// +"Axes"
// }
// }
// div("col-1") {
// button {
// +"Export"
// onClickFunction = {
// val json = (canvas.content as? SolidGroup)?.let { group ->
// val visionManager = canvas.context.plugins.fetch(SolidManager).visionManager
// visionManager.encodeToString(group)
// }
// if (json != null) {
// saveData(it, "object.json", "text/json") {
// json
// }
// }
// }
// }
// }
// }
// }
// entry("Layers") {
// div("row") {
// (0..11).forEach { layer ->
// div("col-1") {
// label { +layer.toString() }
// input(type = InputType.checkBox) {
// if (layer == 0) {
// checked = true
// }
// onChangeFunction = {
// if (checked) {
// canvas.camera.layers.enable(layer)
// } else {
// canvas.camera.layers.disable(layer)
// }
// }
// }
// }
// }
// }
// }
// }
// block()
// }
//}

View File

@ -1,77 +0,0 @@
package space.kscience.visionforge.bootstrap
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.css.*
import kotlinx.html.js.onClickFunction
import org.w3c.dom.events.Event
import org.w3c.files.Blob
import org.w3c.files.BlobPropertyBag
import react.FC
import react.Props
import react.RBuilder
import react.dom.attrs
import react.dom.button
import react.fc
import space.kscience.visionforge.Vision
import space.kscience.visionforge.encodeToString
import space.kscience.visionforge.react.flexColumn
import space.kscience.visionforge.react.flexRow
import space.kscience.visionforge.react.propertyEditor
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import styled.css
private fun saveData(event: Event, fileName: String, mimeType: String = "text/plain", dataBuilder: () -> String) {
event.stopPropagation();
event.preventDefault();
val fileSaver = kotlinext.js.require<dynamic>("file-saver")
val blob = Blob(arrayOf(dataBuilder()), BlobPropertyBag("$mimeType;charset=utf-8"))
fileSaver.saveAs(blob, fileName)
}
public fun RBuilder.canvasControls(canvasOptions: Canvas3DOptions, vision: Vision?) {
child(CanvasControls) {
attrs {
this.canvasOptions = canvasOptions
this.vision = vision
}
}
}
public external interface CanvasControlsProps : Props {
public var canvasOptions: Canvas3DOptions
public var vision: Vision?
}
public val CanvasControls: FC<CanvasControlsProps> = fc("CanvasControls") { props ->
flexColumn {
flexRow {
css {
border = Border(1.px, BorderStyle.solid, Color.blue)
padding = Padding(4.px)
}
props.vision?.let { vision ->
button {
+"Export"
attrs {
onClickFunction = {
val json = vision.encodeToString()
saveData(it, "object.json", "text/json") {
json
}
}
}
}
}
}
@OptIn(DelicateCoroutinesApi::class)
propertyEditor(
scope = props.vision?.manager?.context ?: GlobalScope,
properties = props.canvasOptions.meta,
descriptor = Canvas3DOptions.descriptor,
expanded = false
)
}
}

View File

@ -1,181 +0,0 @@
package space.kscience.visionforge.bootstrap
import kotlinx.html.ButtonType
import kotlinx.html.DIV
import kotlinx.html.id
import kotlinx.html.js.onClickFunction
import react.RBuilder
import react.dom.*
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.NameToken
import space.kscience.dataforge.names.length
import styled.StyledDOMBuilder
import styled.css
import styled.styledDiv
import styled.styledNav
public inline fun RBuilder.card(title: String, crossinline block: StyledDOMBuilder<DIV>.() -> Unit): Unit =
styledDiv {
css {
+"card"
+"w-100"
}
styledDiv {
css {
+"card-body"
}
h3(classes = "card-title") {
+title
}
block()
}
}
public fun RBuilder.accordion(
id: String,
elements: List<Pair<String, StyledDOMBuilder<DIV>.() -> Unit>>,
): Unit = styledDiv {
css {
+"accordion"
//+"p-1"
}
attrs {
this.id = id
}
elements.forEachIndexed { index, (title, builder) ->
val headerID = "${id}-${index}-heading"
val collapseID = "${id}-${index}-collapse"
div("card p-0 m-0") {
div("card-header") {
attrs {
this.id = headerID
}
h5("mb-0") {
button(classes = "btn btn-link collapsed", type = ButtonType.button) {
attrs {
attributes["data-toggle"] = "collapse"
attributes["data-target"] = "#$collapseID"
attributes["aria-expanded"] = "false"
attributes["aria-controls"] = collapseID
}
+title
}
}
}
div("collapse") {
attrs {
this.id = collapseID
attributes["aria-labelledby"] = headerID
attributes["data-parent"] = "#$id"
}
styledDiv {
css {
+"card-body"
}
builder()
}
}
}
}
}
public fun RBuilder.nameCrumbs(name: Name?, rootTitle: String, link: (Name) -> Unit): Unit = styledNav {
css {
+"p-0"
}
attrs {
attributes["aria-label"] = "breadcrumb"
}
ol("breadcrumb") {
li("breadcrumb-item") {
button(classes = "btn btn-link p-0") {
+rootTitle
attrs {
onClickFunction = {
link(Name.EMPTY)
}
}
}
}
if (name != null) {
val tokens = ArrayList<NameToken>(name.length)
name.tokens.forEach { token ->
tokens.add(token)
val fullName = Name(tokens.toList())
li("breadcrumb-item") {
button(classes = "btn btn-link p-0") {
+token.toString()
attrs {
onClickFunction = {
console.log("Selected = $fullName")
link(fullName)
}
}
}
}
}
}
}
}
public typealias RSectionsBuilder = MutableList<Pair<String, StyledDOMBuilder<DIV>.() -> Unit>>
public fun RSectionsBuilder.entry(title: String, builder: StyledDOMBuilder<DIV>.() -> Unit) {
add(title to builder)
}
public fun RBuilder.accordion(id: String, builder: RSectionsBuilder.() -> Unit): Unit {
val list = ArrayList<Pair<String, StyledDOMBuilder<DIV>.() -> Unit>>().apply(builder)
accordion(id, list)
}
public enum class ContainerSize(public val suffix: String) {
DEFAULT(""),
SM("-sm"),
MD("-md"),
LG("-lg"),
XL("-xl"),
FLUID("-fluid")
}
public inline fun RBuilder.container(
size: ContainerSize = ContainerSize.FLUID,
block: StyledDOMBuilder<DIV>.() -> Unit,
): Unit = styledDiv {
css {
classes.add("container${size.suffix}")
}
block()
}
public enum class GridMaxSize(public val suffix: String) {
NONE(""),
SM("-sm"),
MD("-md"),
LG("-lg"),
XL("-xl")
}
public inline fun RBuilder.gridColumn(
weight: Int? = null,
maxSize: GridMaxSize = GridMaxSize.NONE,
block: StyledDOMBuilder<DIV>.() -> Unit,
): Unit = styledDiv {
val weightSuffix = weight?.let { "-$it" } ?: ""
css {
classes.add("col${maxSize.suffix}$weightSuffix")
}
block()
}
public inline fun RBuilder.gridRow(
block: StyledDOMBuilder<DIV>.() -> Unit,
): Unit = styledDiv {
css {
classes.add("row")
}
block()
}

View File

@ -1,86 +0,0 @@
package space.kscience.visionforge.bootstrap
import kotlinx.html.DIV
import kotlinx.html.classes
import kotlinx.html.js.onClickFunction
import react.*
import react.dom.attrs
import react.dom.button
import react.dom.li
import react.dom.ul
import space.kscience.visionforge.react.flexColumn
import styled.StyledDOMBuilder
import styled.styledDiv
public external interface TabProps : PropsWithChildren {
public var id: String
public var title: String?
}
@JsExport
public val Tab: FC<TabProps> = fc { props ->
props.children()
}
public external interface TabPaneProps : PropsWithChildren {
public var activeTab: String?
}
@JsExport
public val TabPane: FC<TabPaneProps> = fc("TabPane") { props ->
var activeTab: String? by useState(props.activeTab)
val children: Array<out ReactElement<*>?> = Children.map(props.children) {
it.asElementOrNull()
} ?: emptyArray()
val childrenProps = children.mapNotNull {
it?.props?.unsafeCast<TabProps>()
}
flexColumn {
ul("nav nav-tabs") {
childrenProps.forEach { cp ->
li("nav-item") {
button(classes = "nav-link") {
+(cp.title ?: cp.id)
attrs {
if (cp.id == activeTab) {
classes = classes + "active"
}
onClickFunction = {
activeTab = cp.id
}
}
}
}
}
}
children.find { (it?.props?.unsafeCast<TabProps>())?.id == activeTab }?.let {
child(it)
}
}
}
public class TabBuilder(internal val parentBuilder: RBuilder) {
public fun tab(id: String, title: String? = null, builder: StyledDOMBuilder<DIV>.() -> Unit) {
parentBuilder.child(Tab) {
attrs {
this.id = id
this.title = title
}
styledDiv {
builder()
}
}
}
}
public inline fun RBuilder.tabPane(activeTab: String? = null, crossinline builder: TabBuilder.() -> Unit) {
child(TabPane) {
attrs {
this.activeTab = activeTab
}
TabBuilder(this).builder()
}
}

View File

@ -1,80 +0,0 @@
package space.kscience.visionforge.bootstrap
import kotlinx.css.*
import react.FC
import react.PropsWithChildren
import react.RBuilder
import react.dom.h2
import react.fc
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.isEmpty
import space.kscience.visionforge.Vision
import space.kscience.visionforge.react.visionTree
import space.kscience.visionforge.solid.SolidGroup
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import styled.css
import styled.styledDiv
public external interface ThreeControlsProps : PropsWithChildren {
public var canvasOptions: Canvas3DOptions
public var vision: Vision?
public var selected: Name?
public var onSelect: (Name) -> Unit
}
@JsExport
public val ThreeControls: FC<ThreeControlsProps> = fc { props ->
tabPane(if (props.selected != null) "Properties" else null) {
tab("Canvas") {
card("Canvas configuration") {
canvasControls(props.canvasOptions, props.vision)
}
}
tab("Tree") {
css {
border = Border(1.px, BorderStyle.solid, Color.lightGray)
padding = Padding(10.px)
}
h2 { +"Object tree" }
styledDiv {
css {
flex = Flex(1.0, 1.0, FlexBasis.inherit)
}
props.vision?.let {
visionTree(it, props.selected, props.onSelect)
}
}
}
tab("Properties") {
props.selected.let { selected ->
val selectedObject: Vision? = when {
selected == null -> null
selected.isEmpty() -> props.vision
else -> (props.vision as? SolidGroup)?.get(selected)
}
if (selectedObject != null) {
visionPropertyEditor(selectedObject, key = selected)
}
}
}
this.parentBuilder.run {
props.children()
}
}
}
public fun RBuilder.threeControls(
canvasOptions: Canvas3DOptions,
vision: Vision?,
selected: Name?,
onSelect: (Name) -> Unit = {},
builder: TabBuilder.() -> Unit = {},
): Unit = child(ThreeControls) {
attrs {
this.canvasOptions = canvasOptions
this.vision = vision
this.selected = selected
this.onSelect = onSelect
}
TabBuilder(this).builder()
}

View File

@ -1,71 +0,0 @@
package space.kscience.visionforge.bootstrap
import org.w3c.dom.Element
import react.RBuilder
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.isEmpty
import space.kscience.visionforge.Vision
import space.kscience.visionforge.getStyle
import space.kscience.visionforge.react.EditorPropertyState
import space.kscience.visionforge.react.PropertyEditor
import space.kscience.visionforge.react.metaViewer
import space.kscience.visionforge.react.render
import space.kscience.visionforge.root
import space.kscience.visionforge.solid.SolidReference
import space.kscience.visionforge.styles
public fun RBuilder.visionPropertyEditor(
vision: Vision,
descriptor: MetaDescriptor? = vision.descriptor,
key: Any? = null,
) {
card("Properties") {
child(PropertyEditor) {
attrs {
this.key = key?.toString()
this.meta = vision.properties.root()
this.updates = vision.properties.changes
this.descriptor = descriptor
this.scope = vision.manager?.context ?: error("Orphan vision could not be observed")
this.getPropertyState = { name ->
val ownMeta = vision.properties.own?.getMeta(name)
if (ownMeta != null && !ownMeta.isEmpty()) {
EditorPropertyState.Defined
} else if (vision.properties.root().getValue(name) != null) {
// TODO differentiate
EditorPropertyState.Default()
} else {
EditorPropertyState.Undefined
}
}
}
}
}
val styles = if (vision is SolidReference) {
(vision.styles + vision.prototype.styles).distinct()
} else {
vision.styles
}
if (styles.isNotEmpty()) {
card("Styles") {
accordion("styles") {
styles.forEach { styleName ->
val style = vision.getStyle(styleName)
if (style != null) {
entry(styleName) {
metaViewer(style)
}
}
}
}
}
}
}
public fun Element.visionPropertyEditor(
item: Vision,
descriptor: MetaDescriptor? = item.descriptor,
): Unit = space.kscience.visionforge.react.createRoot(this).render {
visionPropertyEditor(item, descriptor = descriptor)
}

View File

@ -1,56 +0,0 @@
/*full height*/
html, body {
height: 100%;
width: 100%;
}
.container-fluid { height: inherit; }
/* Remove default bullets */
ul, .tree {
list-style-type: none;
}
/* Style the caret/arrow */
.tree-caret {
cursor: pointer;
user-select: none; /* Prevent text selection */
}
/* Create the caret/arrow with a unicode, and style it */
.tree-caret::before {
content: "\25B6";
color: black;
display: inline-block;
margin-right: 6px;
}
.tree-leaf{
user-select: none;
display: inline-block;
}
.tree-leaf::before {
content: "\25C6";
color: black;
display: inline-block;
margin-right: 6px;
}
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.tree-caret-down::before {
transform: rotate(90deg);
}
.tree-label-inactive {
color: lightgrey;
}
.tree-label-selected{
background-color: lightblue;
}
.no-padding{
padding: 0;
}

View File

@ -1,102 +0,0 @@
package space.kscience.visionforge.compose
import androidx.compose.runtime.*
import org.jetbrains.compose.web.dom.*
import org.w3c.dom.HTMLDivElement
import org.w3c.dom.HTMLLIElement
public class ComposeTab(
public val key: String,
public val title: String,
public val content: ContentBuilder<HTMLDivElement>,
public val disabled: Boolean,
public val titleExt: ContentBuilder<HTMLLIElement>,
)
@Composable
public fun Tabs(tabs: List<ComposeTab>, activeKey: String) {
var active by remember(activeKey) { mutableStateOf(activeKey) }
Div({ classes("card", "text-center") }) {
Div({ classes("card-header") }) {
Ul({ classes("nav", "nav-tabs", "card-header-tabs") }) {
tabs.forEach { tab ->
Li({
classes("nav-item")
}) {
A(attrs = {
classes("nav-link")
if (active == tab.key) {
classes("active")
}
if (tab.disabled) {
classes("disabled")
}
onClick {
active = tab.key
}
}) {
Text(tab.title)
}
tab.titleExt.invoke(this)
}
}
}
}
tabs.find { it.key == active }?.let { tab ->
Div({ classes("card-body") }) {
tab.content.invoke(this)
}
}
}
}
public class TabBuilder internal constructor(public val key: String) {
private var title: String = key
public var disabled: Boolean = false
private var content: ContentBuilder<HTMLDivElement> = {}
private var titleExt: ContentBuilder<HTMLLIElement> = {}
@Composable
public fun Content(content: ContentBuilder<HTMLDivElement>) {
this.content = content
}
@Composable
public fun Title(title: String, titleExt: ContentBuilder<HTMLLIElement> = {}) {
this.title = title
this.titleExt = titleExt
}
internal fun build(): ComposeTab = ComposeTab(
key,
title,
content,
disabled,
titleExt
)
}
public class TabsBuilder {
public var active: String = ""
internal val tabs: MutableList<ComposeTab> = mutableListOf()
@Composable
public fun Tab(key: String, builder: @Composable TabBuilder.() -> Unit) {
tabs.add(TabBuilder(key).apply { builder() }.build())
}
public fun addTab(tab: ComposeTab) {
tabs.add(tab)
}
}
@Composable
public fun Tabs(builder: @Composable TabsBuilder.() -> Unit) {
val result = TabsBuilder().apply { builder() }
Tabs(result.tabs, result.active)
}

View File

@ -1,52 +0,0 @@
package space.kscience.visionforge.compose
import androidx.compose.runtime.*
import kotlinx.dom.clear
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.Div
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
import space.kscience.dataforge.names.Name
import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.solid.three.ThreeCanvas
import space.kscience.visionforge.solid.three.ThreePlugin
@Composable
public fun ThreeCanvas(
context: Context,
options: Canvas3DOptions?,
solid: Solid?,
selected: Name?,
) {
val three: ThreePlugin by derivedStateOf { context.request(ThreePlugin) }
Div({
style {
maxWidth(100.vw)
maxHeight(100.vh)
width(100.percent)
height(100.percent)
}
}) {
var canvas: ThreeCanvas? = null
DisposableEffect(options) {
canvas = ThreeCanvas(three, scopeElement, options ?: Canvas3DOptions())
onDispose {
scopeElement.clear()
canvas = null
}
}
LaunchedEffect(solid) {
if (solid != null) {
canvas?.render(solid)
} else {
canvas?.clear()
}
}
LaunchedEffect(selected) {
canvas?.select(selected)
}
}
}

View File

@ -1,80 +0,0 @@
package space.kscience.visionforge.compose
import androidx.compose.runtime.Composable
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.Button
import org.jetbrains.compose.web.dom.Text
import org.w3c.files.Blob
import org.w3c.files.BlobPropertyBag
import space.kscience.dataforge.context.Global
import space.kscience.dataforge.names.Name
import space.kscience.visionforge.Vision
import space.kscience.visionforge.encodeToString
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
@Composable
internal fun CanvasControls(
vision: Vision?,
options: Canvas3DOptions,
) {
FlexColumn {
FlexRow({
style {
border {
width(1.px)
style(LineStyle.Solid)
color(Color("blue"))
}
padding(4.px)
}
}) {
vision?.let { vision ->
Button({
onClick { event ->
val json = vision.encodeToString()
event.stopPropagation();
event.preventDefault();
val fileSaver = kotlinext.js.require<dynamic>("file-saver")
val blob = Blob(arrayOf(json), BlobPropertyBag("text/json;charset=utf-8"))
fileSaver.saveAs(blob, "object.json") as Unit
}
}) {
Text("Export")
}
}
}
PropertyEditor(
scope = vision?.manager?.context ?: Global,
properties = options.meta,
descriptor = Canvas3DOptions.descriptor,
expanded = false
)
}
}
@Composable
public fun ThreeControls(
vision: Vision?,
canvasOptions: Canvas3DOptions,
selected: Name?,
onSelect: (Name?) -> Unit,
tabBuilder: @Composable TabsBuilder.() -> Unit = {},
) {
Tabs {
active = "Tree"
vision?.let { vision ->
Tab("Tree") {
CardTitle("Vision tree")
VisionTree(vision, Name.EMPTY, selected, onSelect)
}
}
Tab("Settings") {
CardTitle("Canvas configuration")
CanvasControls(vision, canvasOptions)
}
tabBuilder()
}
}

View File

@ -1,169 +0,0 @@
@file:OptIn(ExperimentalComposeWebApi::class)
package space.kscience.visionforge.compose
import androidx.compose.runtime.*
import app.softwork.bootstrapcompose.Card
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.launch
import org.jetbrains.compose.web.ExperimentalComposeWebApi
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.*
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.isEmpty
import space.kscience.visionforge.*
import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.SolidGroup
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
@Composable
public fun ThreeCanvasWithControls(
solids: Solids,
builderOfSolid: Deferred<Solid?>,
initialSelected: Name?,
options: Canvas3DOptions?,
tabBuilder: @Composable TabsBuilder.() -> Unit = {},
) {
var selected: Name? by remember { mutableStateOf(initialSelected) }
var solid: Solid? by remember { mutableStateOf(null) }
LaunchedEffect(builderOfSolid) {
solids.context.launch {
solid = builderOfSolid.await()
//ensure that the solid is properly rooted
if (solid?.parent == null) {
solid?.setAsRoot(solids.context.visionManager)
}
}
}
val optionsWithSelector = remember(options) {
(options ?: Canvas3DOptions()).apply {
this.onSelect = {
selected = it
}
}
}
val selectedVision: Vision? = remember(builderOfSolid, selected) {
selected?.let {
when {
it.isEmpty() -> solid
else -> (solid as? SolidGroup)?.get(it)
}
}
}
FlexRow({
style {
height(100.percent)
width(100.percent)
flexWrap(FlexWrap.Wrap)
alignItems(AlignItems.Stretch)
alignContent(AlignContent.Stretch)
}
}) {
FlexColumn({
style {
height(100.percent)
minWidth(600.px)
flex(10, 1, 600.px)
position(Position.Relative)
}
}) {
if (solid == null) {
Div({
style {
position(Position.Fixed)
width(100.percent)
height(100.percent)
zIndex(1000)
top(40.percent)
left(0.px)
opacity(0.5)
filter {
opacity(50.percent)
}
}
}) {
Div({ classes("d-flex", " justify-content-center") }) {
Div({
classes("spinner-grow", "text-primary")
style {
width(3.cssRem)
height(3.cssRem)
zIndex(20)
}
attr("role", "status")
}) {
Span({ classes("sr-only") }) { Text("Loading 3D vision") }
}
}
}
} else {
ThreeCanvas(solids.context, optionsWithSelector, solid, selected)
}
selectedVision?.let { vision ->
Div({
style {
position(Position.Absolute)
top(5.px)
right(5.px)
width(450.px)
}
}) {
Card(
headerAttrs = {
// border = true
},
header = {
NameCrumbs(selected) { selected = it }
}
) {
PropertyEditor(
scope = solids.context,
meta = vision.properties.root(),
getPropertyState = { name ->
if (vision.properties.own?.get(name) != null) {
EditorPropertyState.Defined
} else if (vision.properties.root()[name] != null) {
// TODO differentiate
EditorPropertyState.Default()
} else {
EditorPropertyState.Undefined
}
},
updates = vision.properties.changes,
rootDescriptor = vision.descriptor
)
}
vision.styles.takeIf { it.isNotEmpty() }?.let { styles ->
P {
B { Text("Styles: ") }
Text(styles.joinToString(separator = ", "))
}
}
}
}
}
}
FlexColumn({
style {
paddingAll(4.px)
minWidth(400.px)
height(100.percent)
overflowY("auto")
flex(1, 10, 300.px)
}
}) {
ThreeControls(solid, optionsWithSelector, selected, onSelect = { selected = it }, tabBuilder = tabBuilder)
}
}

View File

@ -1,4 +0,0 @@
# Module react

View File

@ -1,16 +0,0 @@
plugins {
id("space.kscience.gradle.mpp")
}
kscience {
js()
jsMain {
dependencies {
api(projects.visionforgeSolid)
api("org.jetbrains.kotlin-wrappers:kotlin-styled")
api("org.jetbrains.kotlin-wrappers:kotlin-react-dom")
// implementation(npm("react-select","4.3.0"))
api(projects.visionforgeThreejs)
}
}
}

View File

@ -1,149 +0,0 @@
package space.kscience.visionforge.react
import kotlinx.css.Align
import kotlinx.css.alignItems
import kotlinx.html.js.onClickFunction
import org.w3c.dom.events.Event
import react.*
import react.dom.a
import react.dom.attrs
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.descriptors.get
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.isLeaf
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.NameToken
import space.kscience.dataforge.names.lastOrNull
import space.kscience.dataforge.names.plus
import styled.css
import styled.styledDiv
import styled.styledSpan
public external interface MetaViewerProps : Props {
/**
* Root meta
*/
public var root: Meta
/**
* The title of root node
*/
public var rootName: String?
/**
* Full path to the displayed node in [root]. Could be empty
*/
public var name: Name
/**
* Root descriptor
*/
public var descriptor: MetaDescriptor?
}
private val MetaViewerItem: FC<MetaViewerProps> = fc("MetaViewerItem") { props ->
metaViewerItem(props)
}
private fun RBuilder.metaViewerItem(props: MetaViewerProps) {
var expanded: Boolean by useState { true }
val item = props.root[props.name]
val descriptorItem: MetaDescriptor? = props.descriptor?.get(props.name)
val actualValue = item?.value ?: descriptorItem?.defaultValue
val actualMeta = item ?: descriptorItem?.defaultNode
val token = props.name.lastOrNull()?.toString() ?: props.rootName ?: ""
val expanderClick: (Event) -> Unit = {
expanded = !expanded
}
flexRow {
css {
alignItems = Align.center
}
if (actualMeta?.isLeaf == false) {
styledSpan {
css {
+TreeStyles.treeCaret
if (expanded) {
+TreeStyles.treeCaredDown
}
}
attrs {
onClickFunction = expanderClick
}
}
}
styledSpan {
css {
+TreeStyles.treeLabel
if (item == null) {
+TreeStyles.treeLabelInactive
}
}
+token
}
styledDiv {
a {
+actualValue.toString()
}
}
}
if (expanded) {
flexColumn {
css {
+TreeStyles.tree
}
val keys = buildSet {
descriptorItem?.children?.keys?.forEach {
add(NameToken(it))
}
actualMeta!!.items.keys.let { addAll(it) }
}
keys.filter { !it.body.startsWith("@") }.forEach { token ->
styledDiv {
css {
+TreeStyles.treeItem
}
child(MetaViewerItem) {
attrs {
this.key = props.name.toString()
this.root = props.root
this.name = props.name + token
this.descriptor = props.descriptor
}
}
//configEditor(props.root, props.name + token, props.descriptor, props.default)
}
}
}
}
}
@JsExport
public val MetaViewer: FC<MetaViewerProps> = fc("MetaViewer") { props ->
child(MetaViewerItem) {
attrs {
this.key = ""
this.root = props.root
this.name = Name.EMPTY
this.descriptor = props.descriptor
}
}
}
public fun RBuilder.metaViewer(meta: Meta, descriptor: MetaDescriptor? = null, key: Any? = null) {
child(MetaViewer) {
attrs {
this.key = key?.toString() ?: ""
this.root = meta
this.descriptor = descriptor
}
}
}

View File

@ -1,38 +0,0 @@
package space.kscience.visionforge.react
import kotlinx.html.js.onChangeFunction
import org.w3c.dom.HTMLOptionElement
import org.w3c.dom.HTMLSelectElement
import org.w3c.dom.asList
import org.w3c.dom.events.Event
import react.FC
import react.dom.attrs
import react.dom.option
import react.dom.select
import react.fc
import space.kscience.dataforge.meta.asValue
import space.kscience.dataforge.meta.descriptors.allowedValues
import space.kscience.dataforge.meta.string
@JsExport
public val MultiSelectChooser: FC<ValueChooserProps> = fc("MultiSelectChooser") { props ->
val onChange: (Event) -> Unit = { event: Event ->
val newSelected = (event.target as HTMLSelectElement).selectedOptions.asList()
.map { (it as HTMLOptionElement).value.asValue() }
props.onValueChange(newSelected.asValue())
}
select {
attrs {
multiple = true
values = (props.value?.list ?: emptyList()).mapTo(HashSet()) { it.string }
onChangeFunction = onChange
}
props.descriptor?.allowedValues?.forEach { optionValue ->
option {
+optionValue.string
}
}
}
}

View File

@ -1,278 +0,0 @@
package space.kscience.visionforge.react
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.css.*
import kotlinx.css.properties.TextDecoration
import kotlinx.html.js.onClickFunction
import org.w3c.dom.events.Event
import react.*
import react.dom.attrs
import space.kscience.dataforge.meta.MutableMeta
import space.kscience.dataforge.meta.ObservableMutableMeta
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.descriptors.ValueRequirement
import space.kscience.dataforge.meta.descriptors.get
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.remove
import space.kscience.dataforge.names.*
import space.kscience.visionforge.hidden
import styled.css
import styled.styledButton
import styled.styledDiv
import styled.styledSpan
/**
* The display state of a property
*/
public sealed class EditorPropertyState {
public object Defined : EditorPropertyState()
public class Default(public val source: String = "unknown") : EditorPropertyState()
public object Undefined : EditorPropertyState()
}
public external interface PropertyEditorProps : Props {
/**
* Root config object - always non-null
*/
public var meta: MutableMeta
public var getPropertyState: (Name) -> EditorPropertyState
public var scope: CoroutineScope
public var updates: Flow<Name>
/**
* Full path to the displayed node in [meta]. Could be empty
*/
public var name: Name
/**
* Root descriptor
*/
public var descriptor: MetaDescriptor?
/**
* Initial expanded state
*/
public var expanded: Boolean?
}
private val PropertyEditorItem: FC<PropertyEditorProps> = fc("PropertyEditorItem") { props ->
propertyEditorItem(props)
}
private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
var expanded: Boolean by useState { props.expanded ?: true }
val descriptor: MetaDescriptor? = useMemo(props.descriptor, props.name) { props.descriptor?.get(props.name) }
var property: MutableMeta by useState { props.meta.getOrCreate(props.name) }
var editorPropertyState: EditorPropertyState by useState { props.getPropertyState(props.name) }
val keys = useMemo(descriptor) {
buildSet {
descriptor?.children?.filterNot {
it.key.startsWith("@") || it.value.hidden
}?.forEach {
add(NameToken(it.key))
}
//ownProperty?.items?.keys?.filterNot { it.body.startsWith("@") }?.let { addAll(it) }
}
}
val token = props.name.lastOrNull()?.toString() ?: "Properties"
fun update() {
property = props.meta.getOrCreate(props.name)
editorPropertyState = props.getPropertyState(props.name)
}
useEffect(props.meta) {
val job = props.updates.onEach { updatedName ->
if (updatedName == props.name) {
update()
}
}.launchIn(props.scope)
cleanup {
job.cancel()
}
}
val expanderClick: (Event) -> Unit = {
expanded = !expanded
}
val removeClick: (Event) -> Unit = {
props.meta.remove(props.name)
update()
}
flexRow {
css {
alignItems = Align.center
}
if (keys.isNotEmpty()) {
styledSpan {
css {
+TreeStyles.treeCaret
if (expanded) {
+TreeStyles.treeCaredDown
}
}
attrs {
onClickFunction = expanderClick
}
}
}
styledSpan {
css {
+TreeStyles.treeLabel
if (editorPropertyState != EditorPropertyState.Defined) {
+TreeStyles.treeLabelInactive
}
}
+token
}
if (!props.name.isEmpty() && descriptor?.valueRequirement != ValueRequirement.ABSENT) {
styledDiv {
css {
//+TreeStyles.resizeableInput
width = 160.px
margin = Margin(1.px, 5.px)
}
ValueChooser {
attrs {
this.descriptor = descriptor
this.state = editorPropertyState
this.value = property.value
this.onValueChange = {
property.value = it
editorPropertyState = props.getPropertyState(props.name)
}
}
}
}
styledButton {
css {
width = 24.px
alignSelf = Align.stretch
margin = Margin(1.px, 5.px)
backgroundColor = Color.white
borderStyle = BorderStyle.solid
borderRadius = 2.px
textAlign = TextAlign.center
textDecoration = TextDecoration.none
cursor = Cursor.pointer
disabled {
cursor = Cursor.auto
borderStyle = BorderStyle.dashed
color = Color.lightGray
}
}
+"\u00D7"
attrs {
if (editorPropertyState!= EditorPropertyState.Defined) {
disabled = true
} else {
onClickFunction = removeClick
}
}
}
}
}
if (expanded) {
flexColumn {
css {
+TreeStyles.tree
}
keys.forEach { token ->
styledDiv {
css {
+TreeStyles.treeItem
}
child(PropertyEditorItem) {
attrs {
this.key = props.name.toString()
this.meta = props.meta
this.name = props.name + token
this.descriptor = props.descriptor
this.scope = props.scope
this.getPropertyState = { props.getPropertyState(props.name + token) }
this.updates = props.updates
}
}
//configEditor(props.root, props.name + token, props.descriptor, props.default)
}
}
}
}
}
@JsExport
public val PropertyEditor: FC<PropertyEditorProps> = fc("PropertyEditor") { props ->
child(PropertyEditorItem) {
attrs {
this.key = ""
this.meta = props.meta
this.name = Name.EMPTY
this.descriptor = props.descriptor
this.expanded = props.expanded
this.scope = props.scope
this.getPropertyState = props.getPropertyState
this.updates = props.updates
}
}
}
@OptIn(ExperimentalCoroutinesApi::class)
public fun RBuilder.propertyEditor(
scope: CoroutineScope,
properties: ObservableMutableMeta,
descriptor: MetaDescriptor? = null,
key: Any? = null,
expanded: Boolean? = null,
) {
child(PropertyEditor) {
attrs {
this.meta = properties
this.descriptor = descriptor
this.key = key?.toString() ?: ""
this.expanded = expanded
this.scope = scope
this.getPropertyState = { name ->
if (properties[name] != null) {
EditorPropertyState.Defined
} else if (descriptor?.get(name)?.defaultValue != null) {
EditorPropertyState.Default("descriptor")
} else {
EditorPropertyState.Undefined
}
}
this.updates = callbackFlow {
properties.onChange(scope) { name ->
scope.launch {
send(name)
}
}
invokeOnClose {
properties.removeListener(scope)
}
}
}
}
}

View File

@ -1,78 +0,0 @@
package space.kscience.visionforge.react
import kotlinx.css.pct
import kotlinx.css.width
import kotlinx.html.InputType
import kotlinx.html.js.onChangeFunction
import kotlinx.html.js.onInputFunction
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.events.Event
import react.FC
import react.dom.attrs
import react.fc
import react.useState
import space.kscience.dataforge.meta.asValue
import space.kscience.dataforge.meta.descriptors.ValueRequirement
import space.kscience.dataforge.meta.double
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.string
import styled.css
import styled.styledInput
@JsExport
public val RangeValueChooser: FC<ValueChooserProps> = fc("RangeValueChooser") { props ->
var innerValue by useState(props.value?.double)
var rangeDisabled: Boolean by useState(props.state != EditorPropertyState.Defined)
val handleDisable: (Event) -> Unit = {
val checkBoxValue = (it.target as HTMLInputElement).checked
rangeDisabled = !checkBoxValue
props.onValueChange(
if (!checkBoxValue) {
null
} else {
innerValue?.asValue()
}
)
}
val handleChange: (Event) -> Unit = {
val newValue = (it.target as HTMLInputElement).value
props.onValueChange(newValue.toDoubleOrNull()?.asValue())
innerValue = newValue.toDoubleOrNull()
}
flexRow {
if (props.descriptor?.valueRequirement != ValueRequirement.REQUIRED) {
styledInput(type = InputType.checkBox) {
attrs {
defaultChecked = rangeDisabled.not()
onChangeFunction = handleDisable
}
}
}
styledInput(type = InputType.range) {
css {
width = 100.pct
}
attrs {
disabled = rangeDisabled
value = innerValue?.toString() ?: ""
// onChangeFunction = handleChange
onInputFunction = handleChange
val minValue = props.descriptor?.attributes?.get("min").string
minValue?.let {
min = it
}
val maxValue = props.descriptor?.attributes?.get("max").string
maxValue?.let {
max = it
}
props.descriptor?.attributes?.get("step").string?.let {
step = it
}
}
}
}
}

View File

@ -1,55 +0,0 @@
package space.kscience.visionforge.react
import kotlinx.css.*
import org.w3c.dom.Element
import react.*
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
import space.kscience.dataforge.names.Name
import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.solid.three.ThreeCanvas
import space.kscience.visionforge.solid.three.ThreePlugin
import styled.css
import styled.styledDiv
public external interface ThreeCanvasProps : Props {
public var context: Context
public var options: Canvas3DOptions?
public var solid: Solid?
public var selected: Name?
}
public val ThreeCanvasComponent: FC<ThreeCanvasProps> = fc("ThreeCanvasComponent") { props ->
val elementRef = useRef<Element>(null)
var canvas by useState<ThreeCanvas?>(null)
val three: ThreePlugin = useMemo(props.context) { props.context.request(ThreePlugin) }
useEffect(props.solid, props.options, elementRef) {
if (canvas == null) {
val element = elementRef.current ?: error("Canvas element not found")
canvas = ThreeCanvas(three, element, props.options ?: Canvas3DOptions())
}
}
useEffect(canvas, props.solid) {
props.solid?.let { obj ->
canvas?.render(obj)
}
}
useEffect(canvas, props.selected) {
canvas?.select(props.selected)
}
styledDiv {
css {
maxWidth = 100.vw
maxHeight = 100.vh
width = 100.pct
height = 100.pct
}
ref = elementRef
}
}

View File

@ -1,69 +0,0 @@
package space.kscience.visionforge.react
import kotlinx.css.*
import kotlinx.css.properties.deg
import kotlinx.css.properties.rotate
import styled.StyleSheet
public object TreeStyles : StyleSheet("treeStyles", true) {
/**
* Remove default bullets
*/
public val tree: RuleSet by css {
paddingLeft = 5.px
marginLeft = 0.px
listStyleType = ListStyleType.none
}
/**
* Style the caret/arrow
*/
public val treeCaret: RuleSet by css {
cursor = Cursor.pointer
userSelect = UserSelect.none
/* Create the caret/arrow with a unicode, and style it */
before {
content = "\u25B6".quoted
color = Color.black
display = Display.inlineBlock
marginRight = 6.px
}
}
/**
* Rotate the caret/arrow icon when clicked on (using JavaScript)
*/
public val treeCaredDown:RuleSet by css {
before {
content = "\u25B6".quoted
color = Color.black
display = Display.inlineBlock
marginRight = 6.px
transform.rotate(90.deg)
}
}
public val treeItem:RuleSet by css {
alignItems = Align.center
paddingLeft = 10.px
borderLeftStyle = BorderStyle.dashed
borderLeftWidth = 1.px
borderLeftColor = Color.lightGray
}
public val treeLabel:RuleSet by css {
border = Border.none
padding = Padding(left = 4.pt, right = 4.pt, top = 0.pt, bottom = 0.pt)
textAlign = TextAlign.left
flex = Flex(1.0)
}
public val treeLabelInactive: RuleSet by css {
color = Color.lightGray
}
public val treeLabelSelected:RuleSet by css {
backgroundColor = Color.lightBlue
}
}

View File

@ -1,126 +0,0 @@
package space.kscience.visionforge.react
import kotlinx.css.*
import kotlinx.css.properties.TextDecoration
import kotlinx.css.properties.TextDecorationLine
import kotlinx.html.js.onClickFunction
import org.w3c.dom.events.Event
import react.*
import react.dom.attrs
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.lastOrNull
import space.kscience.dataforge.names.plus
import space.kscience.dataforge.names.startsWith
import space.kscience.visionforge.Vision
import space.kscience.visionforge.VisionGroup
import space.kscience.visionforge.asSequence
import space.kscience.visionforge.isEmpty
import styled.css
import styled.styledDiv
import styled.styledSpan
public external interface ObjectTreeProps : Props {
public var name: Name
public var selected: Name?
public var obj: Vision
public var clickCallback: (Name) -> Unit
}
private val TreeLabel = fc<ObjectTreeProps> { props ->
val token = useMemo(props.name) { props.name.lastOrNull()?.toString() ?: "World" }
styledSpan {
css {
+TreeStyles.treeLabel
color = Color("#069")
cursor = Cursor.pointer
hover {
textDecoration = TextDecoration(setOf(TextDecorationLine.underline))
}
if (props.name == props.selected) {
+TreeStyles.treeLabelSelected
}
}
+token
attrs {
onClickFunction = { props.clickCallback(props.name) }
}
}
}
private fun RBuilder.visionTree(props: ObjectTreeProps): Unit {
var expanded: Boolean by useState { props.selected?.startsWith(props.name) ?: false }
val onClick: (Event) -> Unit = {
expanded = !expanded
}
val obj = props.obj
//display as node if any child is visible
if (obj is VisionGroup) {
flexRow {
if (obj.children.keys.any { !it.body.startsWith("@") }) {
styledSpan {
css {
+TreeStyles.treeCaret
if (expanded) {
+TreeStyles.treeCaredDown
}
}
attrs {
onClickFunction = onClick
}
}
}
child(TreeLabel, props = props)
}
if (expanded) {
flexColumn {
css {
+TreeStyles.tree
}
obj.children.asSequence()
.filter { !it.first.toString().startsWith("@") } // ignore statics and other hidden children
.sortedBy { (it.second as? VisionGroup)?.children?.isEmpty() ?: true } // ignore empty groups
.forEach { (childToken, child) ->
styledDiv {
css {
+TreeStyles.treeItem
}
child(ObjectTree) {
attrs {
this.name = props.name + childToken
this.obj = child
this.selected = props.selected
this.clickCallback = props.clickCallback
}
}
}
}
}
}
} else {
child(TreeLabel, props = props)
}
}
@JsExport
public val ObjectTree: FC<ObjectTreeProps> = fc("ObjectTree") { props ->
visionTree(props)
}
public fun RBuilder.visionTree(
vision: Vision,
selected: Name? = null,
clickCallback: (Name) -> Unit = {},
) {
child(ObjectTree) {
attrs {
this.name = Name.EMPTY
this.obj = vision
this.selected = selected
this.clickCallback = clickCallback
}
}
}

View File

@ -1,17 +0,0 @@
@file:JsModule("react-dom/client")
@file:JsNonModule
package space.kscience.visionforge.react
import org.w3c.dom.Element
import react.dom.client.Root
import react.dom.client.RootOptions
/**
* Compatibility method to work with old browser API
*/
public external fun createRoot(
container: Element,
options: RootOptions = definedExternally,
): Root

View File

@ -1,10 +0,0 @@
package space.kscience.visionforge.react
import react.Props
import react.RBuilder
import react.createElement
import react.dom.client.Root
public fun Root.render(block: RBuilder.() -> Unit) {
render(createElement<Props>(block))
}

View File

@ -1,31 +0,0 @@
package space.kscience.visionforge.react
import kotlinx.css.Display
import kotlinx.css.FlexDirection
import kotlinx.css.display
import kotlinx.css.flexDirection
import kotlinx.html.DIV
import react.RBuilder
import styled.StyledDOMBuilder
import styled.css
import styled.styledDiv
public inline fun RBuilder.flexColumn(
block: StyledDOMBuilder<DIV>.() -> Unit
): Unit = styledDiv {
css {
display = Display.flex
flexDirection = FlexDirection.column
}
block()
}
public inline fun RBuilder.flexRow(
block: StyledDOMBuilder<DIV>.() -> Unit
): Unit = styledDiv {
css {
display = Display.flex
flexDirection = FlexDirection.row
}
block()
}

View File

@ -1,175 +0,0 @@
package space.kscience.visionforge.react
import kotlinx.css.*
import kotlinx.html.InputType
import kotlinx.html.js.onChangeFunction
import kotlinx.html.js.onKeyDownFunction
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.HTMLSelectElement
import org.w3c.dom.events.Event
import react.FC
import react.Props
import react.dom.attrs
import react.dom.option
import react.fc
import react.useState
import space.kscience.dataforge.meta.*
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.descriptors.allowedValues
import space.kscience.visionforge.Colors
import space.kscience.visionforge.widgetType
import styled.css
import styled.styledInput
import styled.styledSelect
import three.math.Color
public external interface ValueChooserProps : Props {
public var descriptor: MetaDescriptor?
public var state: EditorPropertyState
public var value: Value?
public var onValueChange: (Value?) -> Unit
}
@JsExport
public val StringValueChooser: FC<ValueChooserProps> = fc("StringValueChooser") { props ->
var value by useState(props.value?.string ?: "")
val keyDown: (Event) -> Unit = { event ->
if (event.type == "keydown" && event.asDynamic().key == "Enter") {
value = (event.target as HTMLInputElement).value
props.onValueChange(value.asValue())
}
}
val handleChange: (Event) -> Unit = {
value = (it.target as HTMLInputElement).value
}
styledInput(type = InputType.text) {
css {
width = 100.pct
}
attrs {
this.value = value
onKeyDownFunction = keyDown
onChangeFunction = handleChange
}
}
}
@JsExport
public val BooleanValueChooser: FC<ValueChooserProps> = fc("BooleanValueChooser") { props ->
val handleChange: (Event) -> Unit = {
val newValue = (it.target as HTMLInputElement).checked
props.onValueChange(newValue.asValue())
}
styledInput(type = InputType.checkBox) {
css {
width = 100.pct
}
attrs {
//this.attributes["indeterminate"] = (props.item == null).toString()
checked = props.value?.boolean ?: false
onChangeFunction = handleChange
}
}
}
@JsExport
public val NumberValueChooser: FC<ValueChooserProps> = fc("NumberValueChooser") { props ->
var innerValue by useState(props.value?.string ?: "")
val keyDown: (Event) -> Unit = { event ->
if (event.type == "keydown" && event.asDynamic().key == "Enter") {
innerValue = (event.target as HTMLInputElement).value
val number = innerValue.toDoubleOrNull()
if (number == null) {
console.error("The input value $innerValue is not a number")
} else {
props.onValueChange(number.asValue())
}
}
}
val handleChange: (Event) -> Unit = {
innerValue = (it.target as HTMLInputElement).value
}
styledInput(type = InputType.number) {
css {
width = 100.pct
}
attrs {
value = innerValue
onKeyDownFunction = keyDown
onChangeFunction = handleChange
props.descriptor?.attributes?.get("step").string?.let {
step = it
}
props.descriptor?.attributes?.get("min").string?.let {
min = it
}
props.descriptor?.attributes?.get("max").string?.let {
max = it
}
}
}
}
@JsExport
public val ComboValueChooser: FC<ValueChooserProps> = fc("ComboValueChooser") { props ->
var selected by useState(props.value?.string ?: "")
val handleChange: (Event) -> Unit = {
selected = (it.target as HTMLSelectElement).value
props.onValueChange(selected.asValue())
}
styledSelect {
css {
width = 100.pct
}
props.descriptor?.allowedValues?.forEach {
option {
+it.string
}
}
attrs {
this.value = props.value?.string ?: ""
multiple = false
onChangeFunction = handleChange
}
}
}
@JsExport
public val ColorValueChooser: FC<ValueChooserProps> = fc("ColorValueChooser") { props ->
val handleChange: (Event) -> Unit = {
props.onValueChange((it.target as HTMLInputElement).value.asValue())
}
styledInput(type = InputType.color) {
css {
width = 100.pct
margin = Margin(0.px)
}
attrs {
this.value = props.value?.let { value ->
if (value.type == ValueType.NUMBER) Colors.rgbToString(value.int)
else "#" + Color(value.string).getHexString()
} ?: "#000000"
onChangeFunction = handleChange
}
}
}
@JsExport
public val ValueChooser: FC<ValueChooserProps> = fc("ValueChooser") { props ->
val rawInput by useState(false)
val descriptor = props.descriptor
val type = descriptor?.valueTypes?.firstOrNull()
when {
rawInput -> child(StringValueChooser, props)
descriptor?.widgetType == "color" -> child(ColorValueChooser, props)
descriptor?.widgetType == "multiSelect" -> child(MultiSelectChooser, props)
descriptor?.widgetType == "range" -> child(RangeValueChooser, props)
type == ValueType.BOOLEAN -> child(BooleanValueChooser, props)
type == ValueType.NUMBER -> child(NumberValueChooser, props)
descriptor?.allowedValues?.isNotEmpty() ?: false -> child(ComboValueChooser, props)
//TODO handle lists
else -> child(StringValueChooser, props)
}
}

View File

@ -1,4 +0,0 @@
# Module ring

View File

@ -1,25 +0,0 @@
plugins {
id("space.kscience.gradle.mpp")
}
val dataforgeVersion: String by rootProject.extra
kscience{
js{
useCommonJs()
browser {
commonWebpackConfig {
cssSupport{
enabled.set(false)
}
}
}
}
jsMain{
api(projects.ui.react)
api("org.jetbrains.kotlin-wrappers:kotlin-ring-ui")
implementation(npm("core-js","3.12.1"))
implementation(npm("file-saver", "2.0.2"))
}
}

View File

@ -1,20 +0,0 @@
@file:JsModule("@jetbrains/ring-ui/components/loader/loader")
@file:JsNonModule
package ringui
import react.ComponentClass
import react.PropsWithClassName
// https://github.com/JetBrains/ring-ui/blob/master/components/loader/loader.js
public external interface LoaderProps : PropsWithClassName {
public var size: Number
public var colors: Array<String>
public var message: String
public var stop: Boolean
public var deterministic: Boolean
}
@JsName("default")
public external val Loader: ComponentClass<LoaderProps>

View File

@ -1,16 +0,0 @@
@file:JsModule("@jetbrains/ring-ui/components/loader-screen/loader-screen")
@file:JsNonModule
package ringui
import react.ComponentClass
import react.PropsWithClassName
// https://github.com/JetBrains/ring-ui/blob/master/components/loader-screen/loader-screen.js
public external interface LoaderScreenProps : PropsWithClassName {
public var containerClassName: String
public var message: String
}
@JsName("default")
public external val LoaderScreen: ComponentClass<LoaderScreenProps>

View File

@ -1,212 +0,0 @@
package space.kscience.visionforge.ring
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.css.*
import react.*
import react.dom.b
import react.dom.div
import react.dom.p
import react.dom.span
import ringui.*
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.NameToken
import space.kscience.dataforge.names.isEmpty
import space.kscience.dataforge.names.length
import space.kscience.visionforge.*
import space.kscience.visionforge.react.*
import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.SolidGroup
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.solidGroup
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import styled.css
import styled.styledDiv
public external interface ThreeCanvasWithControlsProps : Props {
public var solids: Solids
public var builderOfSolid: Deferred<Solid?>
public var selected: Name?
public var options: Canvas3DOptions?
public var additionalTabs: Map<String, RBuilder.() -> Unit>?
}
private val ThreeCanvasWithControlsProps.context get() = solids.context
public fun ThreeCanvasWithControlsProps.solid(block: SolidGroup.() -> Unit) {
builderOfSolid = context.async {
solids.solidGroup(null, block)
}
}
public fun ThreeCanvasWithControlsProps.options(block: Canvas3DOptions.() -> Unit) {
options = Canvas3DOptions(block)
}
public fun ThreeCanvasWithControlsProps.tab(title: String, block: RBuilder.() -> Unit) {
additionalTabs = (additionalTabs ?: emptyMap()) + (title to block)
}
public fun RBuilder.nameCrumbs(name: Name?, link: (Name) -> Unit): Unit = styledDiv {
div {
Link {
attrs {
onClick = {
link(Name.EMPTY)
}
}
+"\u2302"
}
if (name != null) {
val tokens = ArrayList<NameToken>(name.length)
name.tokens.forEach { token ->
tokens.add(token)
val fullName = Name(tokens.toList())
span { +"." }
Link {
+token.toString()
attrs {
onClick = {
console.log("Selected = $fullName")
link(fullName)
}
}
}
}
}
}
}
@JsExport
public val ThreeCanvasWithControls: FC<ThreeCanvasWithControlsProps> = fc("ThreeViewWithControls") { props ->
var selected: Name? by useState { props.selected }
var solid: Solid? by useState(null)
useEffect {
props.context.launch {
solid = props.builderOfSolid.await()
//ensure that the solid is properly rooted
if (solid?.parent == null) {
solid?.setAsRoot(props.context.visionManager)
}
}
}
val onSelect: (Name?) -> Unit = {
selected = it
}
val options = useMemo(props.options) {
(props.options ?: Canvas3DOptions()).apply {
this.onSelect = onSelect
}
}
val selectedVision: Vision? = useMemo(props.builderOfSolid, selected) {
selected?.let {
when {
it.isEmpty() -> solid
else -> (solid as? SolidGroup)?.get(it)
}
}
}
flexRow {
css {
height = 100.pct
width = 100.pct
flexWrap = FlexWrap.wrap
alignItems = Align.stretch
alignContent = Align.stretch
}
flexColumn {
css {
height = 100.pct
minWidth = 600.px
flex = Flex(10.0, 1.0, FlexBasis("600px"))
position = Position.relative
}
if (solid == null) {
LoaderScreen {
attrs {
message = "Loading Three vision"
}
}
} else {
child(ThreeCanvasComponent) {
attrs {
this.context = props.context
this.solid = solid
this.selected = selected
this.options = options
}
}
}
selectedVision?.let { vision ->
styledDiv {
css {
position = Position.absolute
top = 5.px
right = 5.px
width = 450.px
}
Island {
IslandHeader {
attrs {
border = true
}
nameCrumbs(selected) { selected = it }
}
IslandContent {
child(PropertyEditor) {
attrs {
this.key = selected.toString()
this.meta = vision.properties.root()
this.updates = vision.properties.changes
this.descriptor = vision.descriptor
this.scope = props.context
this.getPropertyState = { name ->
if (vision.properties.own?.get(name) != null) {
EditorPropertyState.Defined
} else if (vision.properties.root()[name] != null) {
// TODO differentiate
EditorPropertyState.Default()
} else {
EditorPropertyState.Undefined
}
}
}
}
vision.styles.takeIf { it.isNotEmpty() }?.let { styles ->
p {
b { +"Styles: " }
+styles.joinToString(separator = ", ")
}
}
}
}
}
}
}
flexColumn {
css {
padding = Padding(4.px)
minWidth = 400.px
height = 100.pct
overflowY = Overflow.auto
flex = Flex(1.0, 10.0, FlexBasis("300px"))
}
ringThreeControls(options, solid, selected, onSelect, additionalTabs = props.additionalTabs)
}
}
}

View File

@ -1,57 +0,0 @@
package space.kscience.visionforge.ring
import kotlinx.coroutines.async
import org.w3c.dom.Element
import space.kscience.dataforge.context.AbstractPlugin
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.PluginFactory
import space.kscience.dataforge.context.PluginTag
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.boolean
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName
import space.kscience.visionforge.ElementVisionRenderer
import space.kscience.visionforge.Vision
import space.kscience.visionforge.react.render
import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.solid.three.ThreePlugin
public class ThreeWithControlsPlugin : AbstractPlugin(), ElementVisionRenderer {
public val three: ThreePlugin by require(ThreePlugin)
override val tag: PluginTag get() = Companion.tag
override fun rateVision(vision: Vision): Int =
if (vision is Solid) ElementVisionRenderer.DEFAULT_RATING * 2 else ElementVisionRenderer.ZERO_RATING
override fun render(element: Element, name: Name, vision: Vision, meta: Meta) {
if(meta["controls.enabled"].boolean == false){
three.render(element, name, vision, meta)
} else {
space.kscience.visionforge.react.createRoot(element).render {
child(ThreeCanvasWithControls) {
attrs {
this.solids = three.solids
this.options = Canvas3DOptions.read(meta)
this.builderOfSolid = context.async { vision as Solid }
}
}
}
}
}
override fun content(target: String): Map<Name, Any> {
return when (target) {
ElementVisionRenderer.TYPE -> mapOf("three.withControls".asName() to this)
else -> super.content(target)
}
}
public companion object : PluginFactory<ThreeWithControlsPlugin> {
override val tag: PluginTag = PluginTag("vision.threejs.withControls", PluginTag.DATAFORGE_GROUP)
override fun build(context: Context, meta: Meta): ThreeWithControlsPlugin = ThreeWithControlsPlugin()
}
}

View File

@ -1,88 +0,0 @@
package space.kscience.visionforge.ring
import org.w3c.dom.Element
import react.RBuilder
import react.dom.p
import ringui.Island
import ringui.SmartTabs
import ringui.Tab
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.get
import space.kscience.visionforge.Vision
import space.kscience.visionforge.getStyle
import space.kscience.visionforge.react.*
import space.kscience.visionforge.root
import space.kscience.visionforge.solid.SolidReference
import space.kscience.visionforge.styles
public fun RBuilder.ringPropertyEditor(
vision: Vision,
descriptor: MetaDescriptor? = vision.descriptor,
key: Any? = null,
) {
val styles = if (vision is SolidReference) {
(vision.styles + vision.prototype.styles).distinct()
} else {
vision.styles
}
flexColumn {
Island("Properties") {
child(PropertyEditor) {
attrs {
this.key = key?.toString()
this.meta = vision.properties.root()
this.updates = vision.properties.changes
this.descriptor = descriptor
this.scope = vision.manager?.context ?: error("Orphan vision could not be observed")
this.getPropertyState = {name->
if(vision.properties.own?.get(name)!= null){
EditorPropertyState.Defined
} else if(vision.properties.root()[name] != null){
// TODO differentiate
EditorPropertyState.Default()
} else {
EditorPropertyState.Undefined
}
}
}
}
}
if (styles.isNotEmpty()) {
Island("Styles") {
if (styles.size == 1) {
val styleName = styles.first()
p {
+styleName
}
val style = vision.getStyle(styleName)
if (style != null) {
Tab(styleName, id = styleName) {
metaViewer(style)
}
}
} else {
SmartTabs {
styles.forEach { styleName ->
val style = vision.getStyle(styleName)
if (style != null) {
Tab(styleName, id = styleName) {
metaViewer(style)
}
}
}
}
}
}
}
}
}
public fun Element.ringPropertyEditor(
item: Vision,
descriptor: MetaDescriptor? = item.descriptor,
): Unit = createRoot(this).render {
ringPropertyEditor(item, descriptor = descriptor)
}

View File

@ -1,131 +0,0 @@
package space.kscience.visionforge.ring
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.css.*
import kotlinx.html.js.onClickFunction
import org.w3c.dom.events.Event
import org.w3c.files.Blob
import org.w3c.files.BlobPropertyBag
import react.FC
import react.Props
import react.RBuilder
import react.dom.attrs
import react.dom.button
import react.fc
import ringui.Island
import ringui.SmartTabs
import ringui.Tab
import space.kscience.dataforge.names.Name
import space.kscience.visionforge.Vision
import space.kscience.visionforge.encodeToString
import space.kscience.visionforge.react.flexColumn
import space.kscience.visionforge.react.flexRow
import space.kscience.visionforge.react.propertyEditor
import space.kscience.visionforge.react.visionTree
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import styled.css
internal fun saveData(event: Event, fileName: String, mimeType: String = "text/plain", dataBuilder: () -> String) {
event.stopPropagation();
event.preventDefault();
val fileSaver = kotlinext.js.require<dynamic>("file-saver")
val blob = Blob(arrayOf(dataBuilder()), BlobPropertyBag("$mimeType;charset=utf-8"))
fileSaver.saveAs(blob, fileName)
}
internal fun RBuilder.canvasControls(options: Canvas3DOptions, vision: Vision?): Unit {
child(CanvasControls) {
attrs {
this.options = options
this.vision = vision
}
}
}
internal external interface CanvasControlsProps : Props {
public var options: Canvas3DOptions
public var vision: Vision?
}
@OptIn(DelicateCoroutinesApi::class)
internal val CanvasControls: FC<CanvasControlsProps> = fc("CanvasControls") { props ->
flexColumn {
flexRow {
css {
border = Border(1.px, BorderStyle.solid, Color.blue)
padding = Padding(4.px)
}
props.vision?.let { vision ->
button {
+"Export"
attrs {
onClickFunction = {
val json = vision.encodeToString()
saveData(it, "object.json", "text/json") {
json
}
}
}
}
}
}
propertyEditor(
scope = props.vision?.manager?.context ?: GlobalScope,
properties = props.options.meta,
descriptor = Canvas3DOptions.descriptor,
expanded = false
)
}
}
public external interface ThreeControlsProps : Props {
public var canvasOptions: Canvas3DOptions
public var vision: Vision?
public var selected: Name?
public var onSelect: (Name?) -> Unit
public var additionalTabs: Map<String, RBuilder.() -> Unit>
}
@JsExport
public val ThreeControls: FC<ThreeControlsProps> = fc { props ->
SmartTabs("Tree") {
props.vision?.let {
Tab("Tree") {
Island("Vision tree") {
visionTree(it, props.selected, props.onSelect)
}
}
}
Tab("Settings") {
Island("Canvas configuration") {
canvasControls(props.canvasOptions, props.vision)
}
}
props.additionalTabs.forEach { (name, handler) ->
Tab(name) {
handler()
}
}
}
}
public fun RBuilder.ringThreeControls(
canvasOptions: Canvas3DOptions,
vision: Vision?,
selected: Name?,
onSelect: (Name?) -> Unit = {},
additionalTabs: Map<String, RBuilder.() -> Unit>? = null
): Unit = child(ThreeControls) {
attrs {
this.canvasOptions = canvasOptions
this.vision = vision
this.selected = selected
this.onSelect = onSelect
this.additionalTabs = additionalTabs ?: emptyMap()
}
}

View File

@ -1,3 +0,0 @@
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
config.module.rules.push(...ringConfig.module.rules)

View File

@ -1,40 +1,31 @@
plugins {
id("space.kscience.gradle.mpp")
alias(spclibs.plugins.compose)
// id("com.android.library")
}
kscience{
jvm()
kscience {
js()
// wasm()
jvm()
}
kotlin {
// android()
sourceSets {
val commonMain by getting {
dependencies {
}
}
val jvmMain by getting {
commonMain {
dependencies {
api(projects.visionforgeCore)
//need this to placate compose compiler in MPP applications
api(compose.runtime)
api(compose.foundation)
api(compose.material)
api(compose.preview)
}
}
val jsMain by getting{
jsMain{
dependencies {
api(compose.html.core)
api("app.softwork:bootstrap-compose:0.1.15")
api("app.softwork:bootstrap-compose-icons:0.1.15")
api(projects.visionforge.visionforgeThreejs)
implementation(compose.html.svg)
api(compose.html.core)
}
}
}

Some files were not shown because too many files have changed in this diff Show More