v0.2.0-dev-22 #47

Merged
altavir merged 158 commits from dev into master 2021-07-17 11:04:22 +03:00
83 changed files with 874 additions and 917 deletions
Showing only changes of commit 6116523091 - Show all commits

2
.gitignore vendored
View File

@ -5,6 +5,4 @@ out/
.gradle
build/
!gradle-wrapper.jar
gradle.properties

View File

@ -0,0 +1,14 @@
# Changelog
## [Unreleased]
### Added
### Changed
### Deprecated
### Removed
### Fixed
### Security

View File

@ -1,16 +1,12 @@
import scientifik.useFx
import scientifik.useSerialization
val dataforgeVersion by extra("0.1.8")
import ru.mipt.npm.gradle.useFx
plugins {
id("scientifik.mpp") apply false
id("scientifik.jvm") apply false
id("scientifik.js") apply false
id("scientifik.publish") apply false
id("org.jetbrains.changelog") version "0.4.0"
id("ru.mipt.npm.project")
}
val dataforgeVersion by extra("0.2.0-dev-3")
val ktorVersion by extra("1.4.1")
allprojects {
repositories {
mavenLocal()
@ -19,7 +15,7 @@ allprojects {
}
group = "hep.dataforge"
version = "0.1.5-dev-2"
version = "0.2.0-dev-1"
}
val githubProject by extra("visionforge")
@ -28,8 +24,17 @@ val fxVersion by extra("14")
subprojects {
if(name.startsWith("visionforge")) {
apply(plugin = "scientifik.publish")
apply<ru.mipt.npm.gradle.KSciencePublishPlugin>()
}
useSerialization()
useFx(scientifik.FXModule.CONTROLS, version = fxVersion)
afterEvaluate {
extensions.findByType<ru.mipt.npm.gradle.KScienceExtension>()?.run {
useSerialization()
useFx(ru.mipt.npm.gradle.FXModule.CONTROLS, version = fxVersion)
}
}
}
apiValidation {
validationDisabled = true
ignoredPackages.add("info.laht.threekt")
}

View File

View File

@ -1,19 +1,24 @@
import scientifik.DependencyConfiguration
import scientifik.FXModule
import scientifik.useFx
import ru.mipt.npm.gradle.DependencyConfiguration
import ru.mipt.npm.gradle.FXModule
import ru.mipt.npm.gradle.useFx
plugins {
id("scientifik.mpp")
id("application")
id("ru.mipt.npm.mpp")
application
}
val fxVersion: String by rootProject.extra
useFx(FXModule.CONTROLS, version = fxVersion, configuration = DependencyConfiguration.IMPLEMENTATION)
kscience {
val fxVersion: String by rootProject.extra
useFx(FXModule.CONTROLS, version = fxVersion, configuration = DependencyConfiguration.IMPLEMENTATION)
application()
}
kotlin {
jvm {
withJava()
afterEvaluate {
withJava()
}
}
js {
@ -27,7 +32,7 @@ kotlin {
implementation(project(":visionforge-gdml"))
}
}
jsMain{
jsMain {
dependencies {
implementation(project(":ui:bootstrap"))
implementation(npm("react-file-drop", "3.0.6"))

View File

@ -1,6 +1,6 @@
package hep.dataforge.vision.gdml.demo
import scientifik.gdml.*
import kscience.gdml.*
fun cubes(): GDML = GDML {

View File

@ -1,7 +1,6 @@
package hep.dataforge.vision.gdml.demo
import hep.dataforge.context.Context
import hep.dataforge.meta.set
import hep.dataforge.names.Name
import hep.dataforge.names.isEmpty
import hep.dataforge.vision.Vision
@ -18,18 +17,18 @@ import hep.dataforge.vision.solid.specifications.Canvas3DOptions
import hep.dataforge.vision.solid.three.ThreeCanvas
import hep.dataforge.vision.solid.three.ThreeCanvasComponent
import hep.dataforge.vision.solid.three.canvasControls
import kotlinx.browser.window
import kotlinx.css.FlexBasis
import kotlinx.css.Overflow
import kotlinx.css.flex
import kotlinx.css.overflow
import kscience.gdml.GDML
import kscience.gdml.decodeFromString
import org.w3c.files.FileReader
import org.w3c.files.get
import react.RProps
import react.dom.h1
import scientifik.gdml.GDML
import scientifik.gdml.parse
import styled.css
import kotlin.browser.window
import kotlin.math.PI
interface GDMLAppProps : RProps {
@ -58,10 +57,10 @@ val GDMLApp = component<GDMLAppProps> { props ->
fun loadData(name: String, data: String) {
val parsedVision = when {
name.endsWith(".gdml") || name.endsWith(".xml") -> {
val gdml = GDML.parse(data)
val gdml = GDML.decodeFromString(data)
gdml.toVision()
}
name.endsWith(".json") -> SolidGroup.parseJson(data)
name.endsWith(".json") -> SolidGroup.decodeFromString(data)
else -> {
window.alert("File extension is not recognized: $name")
error("File extension is not recognized: $name")

View File

@ -3,15 +3,12 @@ package hep.dataforge.vision.gdml.demo
import hep.dataforge.context.Global
import hep.dataforge.js.Application
import hep.dataforge.js.startApplication
import hep.dataforge.vision.gdml.GDMLTransformer
import hep.dataforge.vision.gdml.LUnit
import hep.dataforge.vision.gdml.toVision
import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_OPACITY_KEY
import kotlinx.browser.document
import kotlinx.css.*
import react.child
import react.dom.render
import styled.injectGlobal
import kotlin.browser.document
private class GDMLDemoApp : Application {

View File

@ -7,7 +7,7 @@
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/fileDrop.css">
<script type="text/javascript" src="main.bundle.js"></script>
<script type="text/javascript" src="gdml.js"></script>
<script type="text/javascript" src ="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript" src ="js/bootstrap.bundle.min.js"></script>
</head>

View File

@ -3,13 +3,12 @@ package hep.dataforge.vision.gdml.demo
import hep.dataforge.meta.DFExperimental
import hep.dataforge.meta.setItem
import hep.dataforge.values.asValue
import hep.dataforge.vision.gdml.LUnit
import hep.dataforge.vision.gdml.readFile
import hep.dataforge.vision.gdml.toVision
import hep.dataforge.vision.solid.SolidGroup
import hep.dataforge.vision.solid.SolidManager
import hep.dataforge.vision.solid.SolidMaterial
import scientifik.gdml.GDML
import kscience.gdml.GDML
import java.io.File
import java.util.zip.GZIPInputStream
import java.util.zip.ZipInputStream
@ -32,19 +31,19 @@ fun SolidManager.Companion.readFile(file: File): SolidGroup = when {
// }
}
}
file.extension == "json" -> SolidGroup.parseJson(file.readText())
file.extension == "json" -> SolidGroup.decodeFromString(file.readText())
file.name.endsWith("json.zip") -> {
file.inputStream().use {
val unzip = ZipInputStream(it, Charsets.UTF_8)
val text = unzip.readBytes().decodeToString()
SolidGroup.parseJson(text)
SolidGroup.decodeFromString(text)
}
}
file.name.endsWith("json.gz") -> {
file.inputStream().use {
val unzip = GZIPInputStream(it)
val text = unzip.readBytes().decodeToString()
SolidGroup.parseJson(text)
SolidGroup.decodeFromString(text)
}
}
else -> error("Unknown extension ${file.extension}")

View File

@ -1,10 +1,10 @@
package hep.dataforge.vision.gdml.demo
import hep.dataforge.vision.gdml.LUnit
import hep.dataforge.vision.gdml.readFile
import hep.dataforge.vision.gdml.toVision
import hep.dataforge.vision.solid.stringify
import scientifik.gdml.GDML
import hep.dataforge.vision.solid.encodeToString
import kscience.gdml.GDML
import kscience.gdml.LUnit
import java.io.File
import java.nio.file.Paths
@ -21,7 +21,7 @@ fun main(args: Array<String>) {
lUnit = LUnit.CM
}
val json = visual.stringify()
val json = visual.encodeToString()
println(json)
File(outputFileName).writeText(json)
//File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\cubes.json").writeText(json)

View File

@ -9,7 +9,7 @@ class FileSerializationTest {
@Ignore
fun testFileRead(){
val text = this::class.java.getResourceAsStream("/cubes.json").readBytes().decodeToString()
val visual = SolidGroup.parseJson(text)
val visual = SolidGroup.decodeFromString(text)
visual["composite_001".asName()]
}
}

View File

@ -1,43 +1,38 @@
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME
import scientifik.jsDistDirectory
plugins {
id("scientifik.mpp")
id("application")
id("ru.mipt.npm.mpp")
application
}
group = "ru.mipt.npm"
val ktorVersion = "1.3.2"
val ktorVersion: String by rootProject.extra
kscience {
application()
}
kotlin {
afterEvaluate {
val jsBrowserDistribution by tasks.getting
val installJS = tasks.getByName("jsBrowserDistribution")
js {
browser {
dceTask {
dceOptions {
keep("ktor-ktor-io.\$\$importsForInline\$\$.ktor-ktor-io.io.ktor.utils.io")
jvm {
withJava()
compilations[MAIN_COMPILATION_NAME]?.apply {
tasks.getByName<ProcessResources>(processResourcesTaskName) {
dependsOn(jsBrowserDistribution)
afterEvaluate {
from(jsBrowserDistribution)
}
}
}
webpackTask {
mode = org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig.Mode.PRODUCTION
}
}
}
jvm {
withJava()
compilations[MAIN_COMPILATION_NAME]?.apply {
tasks.getByName<ProcessResources>(processResourcesTaskName) {
dependsOn(installJS)
afterEvaluate {
from(project.jsDistDirectory)
}
}
}
js {
useCommonJs()
}
sourceSets {
@ -58,14 +53,6 @@ kotlin {
implementation(project(":ui:bootstrap"))
implementation("io.ktor:ktor-client-js:$ktorVersion")
implementation("io.ktor:ktor-client-serialization-js:$ktorVersion")
implementation(npm("text-encoding"))
implementation(npm("abort-controller"))
implementation(npm("bufferutil"))
implementation(npm("utf-8-validate"))
implementation(npm("fs"))
// implementation(npm("jquery"))
// implementation(npm("popper.js"))
// implementation(npm("react-is"))
}
}
}

View File

@ -4,6 +4,7 @@ import hep.dataforge.context.Context
import hep.dataforge.names.Name
import hep.dataforge.names.NameToken
import hep.dataforge.names.isEmpty
import hep.dataforge.names.length
import hep.dataforge.vision.Vision
import hep.dataforge.vision.bootstrap.card
import hep.dataforge.vision.react.component

View File

@ -7,11 +7,11 @@ import hep.dataforge.vision.solid.SolidManager
import io.ktor.client.HttpClient
import io.ktor.client.features.json.JsonFeature
import io.ktor.client.features.json.serializer.KotlinxSerializer
import kotlinx.browser.document
import kotlinx.serialization.json.Json
import react.child
import react.dom.div
import react.dom.render
import kotlin.browser.document
private class MMDemoApp : Application {
@ -19,7 +19,7 @@ private class MMDemoApp : Application {
private val connection = HttpClient {
install(JsonFeature) {
serializer = KotlinxSerializer(Json(context = SolidManager.serialModule))
serializer = KotlinxSerializer(Json { serializersModule = SolidManager.serialModule })
}
}
@ -34,8 +34,8 @@ private class MMDemoApp : Application {
div("container-fluid h-100") {
child(MMApp) {
attrs {
model = this@MMDemoApp.model
connection = this@MMDemoApp.connection
this.model = this@MMDemoApp.model
this.connection = this@MMDemoApp.connection
this.context = context
}
}

View File

@ -6,7 +6,7 @@
<title>Three js demo for particle physics</title>
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/main.css">
<script type="text/javascript" src="main.bundle.js"></script>
<script type="text/javascript" src="muon-monitor.js"></script>
<script type="text/javascript" src ="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript" src ="js/bootstrap.bundle.min.js"></script>
</head>

View File

@ -10,6 +10,7 @@ import io.ktor.application.log
import io.ktor.features.CallLogging
import io.ktor.features.ContentNegotiation
import io.ktor.features.DefaultHeaders
import io.ktor.http.ContentType
import io.ktor.http.content.resources
import io.ktor.http.content.static
import io.ktor.response.respond
@ -19,6 +20,7 @@ import io.ktor.serialization.json
import io.ktor.server.cio.CIO
import io.ktor.server.engine.embeddedServer
import io.ktor.util.KtorExperimentalAPI
import kotlinx.serialization.json.Json
import org.apache.commons.math3.random.JDKRandomGenerator
import ru.mipt.npm.muon.monitor.Model
import ru.mipt.npm.muon.monitor.sim.Cos2TrackGenerator
@ -38,7 +40,7 @@ fun Application.module() {
install(DefaultHeaders)
install(CallLogging)
install(ContentNegotiation) {
json(module = SolidManager.serialModule)
json(Json { serializersModule = SolidManager.serialModule }, ContentType.Application.Json)
}
install(Routing) {
get("/event") {

View File

@ -1,19 +1,22 @@
import scientifik.DependencyConfiguration
import scientifik.FXModule
import scientifik.useFx
import ru.mipt.npm.gradle.*
plugins {
id("scientifik.mpp")
id("application")
id("ru.mipt.npm.mpp")
application
}
val fxVersion: String by rootProject.extra
useFx(FXModule.CONTROLS, version = fxVersion, configuration = DependencyConfiguration.IMPLEMENTATION)
kscience {
val fxVersion: String by rootProject.extra
useFx(FXModule.CONTROLS, version = fxVersion, configuration = DependencyConfiguration.IMPLEMENTATION)
application()
}
kotlin {
jvm {
withJava()
afterEvaluate {
withJava()
}
}
sourceSets {

View File

@ -8,6 +8,7 @@ import hep.dataforge.vision.Colors
import hep.dataforge.vision.Vision
import hep.dataforge.vision.solid.*
import hep.dataforge.vision.solid.specifications.Canvas3DOptions
import hep.dataforge.vision.visible
import kotlinx.coroutines.*
import kotlin.math.PI
import kotlin.math.cos

View File

@ -6,7 +6,7 @@
<title>Three js demo for particle physics</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script type="text/javascript" src="main.bundle.js"></script>
<script type="text/javascript" src="spatial-showcase.js"></script>
</head>
<body class="application">
<div class="container">

9
gradle.properties Normal file
View File

@ -0,0 +1,9 @@
kotlin.code.style=official
kotlin.parallel.tasks.in.project=true
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false
kotlin.mpp.stability.nowarn=true
org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m
org.gradle.parallel=true
systemProp.org.gradle.internal.publish.checksums.insecure=true

View File

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

View File

@ -7,12 +7,12 @@ repositories{
maven("https://kotlin.bintray.com/kotlinx")
maven("https://dl.bintray.com/kotlin/kotlin-eap")
maven("https://dl.bintray.com/mipt-npm/dataforge")
maven("https://dl.bintray.com/mipt-npm/scientifik")
maven("https://dl.bintray.com/mipt-npm/kscience")
maven("https://dl.bintray.com/mipt-npm/dev")
}
kotlin {
js {
js(IR) {
browser {}
}

View File

@ -1,32 +1,27 @@
pluginManagement {
val kotlinVersion = "1.3.72"
val toolsVersion = "0.5.2"
val kotlinVersion = "1.4.20-M1"
val toolsVersion = "0.6.3-dev-1.4.20-M1"
repositories {
mavenLocal()
jcenter()
gradlePluginPortal()
maven("https://kotlin.bintray.com/kotlinx")
maven("https://dl.bintray.com/kotlin/kotlin-eap")
maven("https://dl.bintray.com/kotlin/kotlinx")
maven("https://dl.bintray.com/mipt-npm/dataforge")
maven("https://dl.bintray.com/mipt-npm/scientifik")
maven("https://dl.bintray.com/mipt-npm/kscience")
maven("https://dl.bintray.com/mipt-npm/dev")
}
plugins {
id("ru.mipt.npm.project") version toolsVersion
id("ru.mipt.npm.mpp") version toolsVersion
id("ru.mipt.npm.jvm") version toolsVersion
id("ru.mipt.npm.js") version toolsVersion
id("ru.mipt.npm.publish") version toolsVersion
kotlin("jvm") version kotlinVersion
id("scientifik.mpp") version toolsVersion
id("scientifik.jvm") version toolsVersion
id("scientifik.js") version toolsVersion
id("scientifik.publish") version toolsVersion
}
resolutionStrategy {
eachPlugin {
when (requested.id.id) {
"scientifik.mpp", "scientifik.publish", "scientifik.jvm", "scientifik.js" -> useModule("scientifik:gradle-tools:${toolsVersion}")
}
}
kotlin("js") version kotlinVersion
kotlin("multiplatform") version kotlinVersion
}
}
@ -34,11 +29,12 @@ pluginManagement {
rootProject.name = "visionforge"
include(
":ui",
// ":ui",
":ui:react",
":ui:ring",
":ui:material",
// ":ui:material",
":ui:bootstrap",
":visionforge-core",
":visionforge-solid",

View File

@ -1,15 +1,9 @@
plugins {
id("scientifik.js")
id("ru.mipt.npm.js")
}
val dataforgeVersion: String by rootProject.extra
kotlin {
target {
useCommonJs()
}
}
dependencies{
api(project(":ui:react"))
}

View File

@ -2,6 +2,7 @@ package hep.dataforge.vision.bootstrap
import hep.dataforge.names.Name
import hep.dataforge.names.NameToken
import hep.dataforge.names.length
import hep.dataforge.vision.Vision
import hep.dataforge.vision.react.ObjectTree
import kotlinx.html.*
@ -17,7 +18,7 @@ import styled.StyledDOMBuilder
import styled.css
import styled.styledDiv
inline fun TagConsumer<HTMLElement>.card(title: String, crossinline block: TagConsumer<HTMLElement>.() -> Unit) {
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 }
@ -26,7 +27,7 @@ inline fun TagConsumer<HTMLElement>.card(title: String, crossinline block: TagCo
}
}
inline fun RBuilder.card(title: String, classes: String? = null, crossinline block: RBuilder.() -> Unit) {
public inline fun RBuilder.card(title: String, classes: String? = null, crossinline block: RBuilder.() -> Unit) {
div("card w-100 $classes") {
div("card-body") {
h3(classes = "card-title") {
@ -37,7 +38,7 @@ inline fun RBuilder.card(title: String, classes: String? = null, crossinline blo
}
}
fun TagConsumer<HTMLElement>.accordion(id: String, elements: List<Pair<String, DIV.() -> Unit>>) {
public fun TagConsumer<HTMLElement>.accordion(id: String, elements: List<Pair<String, DIV.() -> Unit>>) {
div("container-fluid") {
div("accordion") {
this.id = id
@ -69,18 +70,18 @@ fun TagConsumer<HTMLElement>.accordion(id: String, elements: List<Pair<String, D
}
}
typealias AccordionBuilder = MutableList<Pair<String, DIV.() -> Unit>>
public typealias AccordionBuilder = MutableList<Pair<String, DIV.() -> Unit>>
fun AccordionBuilder.entry(title: String, builder: DIV.() -> Unit) {
public fun AccordionBuilder.entry(title: String, builder: DIV.() -> Unit) {
add(title to builder)
}
fun TagConsumer<HTMLElement>.accordion(id: String, builder: AccordionBuilder.() -> Unit) {
public fun TagConsumer<HTMLElement>.accordion(id: String, builder: AccordionBuilder.() -> Unit) {
val list = ArrayList<Pair<String, DIV.() -> Unit>>().apply(builder)
accordion(id, list)
}
fun RBuilder.accordion(id: String, elements: List<Pair<String, RDOMBuilder<DIV>.() -> Unit>>): ReactElement {
public fun RBuilder.accordion(id: String, elements: List<Pair<String, RDOMBuilder<DIV>.() -> Unit>>): ReactElement {
return div("container-fluid") {
div("accordion") {
attrs {
@ -120,7 +121,7 @@ fun RBuilder.accordion(id: String, elements: List<Pair<String, RDOMBuilder<DIV>.
}
}
fun RBuilder.namecrumbs(name: Name?, rootTitle: String, link: (Name) -> Unit) {
public fun RBuilder.namecrumbs(name: Name?, rootTitle: String, link: (Name) -> Unit) {
div("container-fluid p-0") {
nav {
attrs {
@ -160,20 +161,18 @@ fun RBuilder.namecrumbs(name: Name?, rootTitle: String, link: (Name) -> Unit) {
}
}
typealias RAccordionBuilder = MutableList<Pair<String, RDOMBuilder<DIV>.() -> Unit>>
public typealias RAccordionBuilder = MutableList<Pair<String, RDOMBuilder<DIV>.() -> Unit>>
fun RAccordionBuilder.entry(title: String, builder: RDOMBuilder<DIV>.() -> Unit) {
public fun RAccordionBuilder.entry(title: String, builder: RDOMBuilder<DIV>.() -> Unit) {
add(title to builder)
}
fun RBuilder.accordion(id: String, builder: RAccordionBuilder.() -> Unit): ReactElement {
public fun RBuilder.accordion(id: String, builder: RAccordionBuilder.() -> Unit): ReactElement {
val list = ArrayList<Pair<String, RDOMBuilder<DIV>.() -> Unit>>().apply(builder)
return accordion(id, list)
}
fun joinStyles(vararg styles: String?) = styles.joinToString(separator = " ") { it ?: "" }
enum class ContainerSize(val suffix: String) {
public enum class ContainerSize(public val suffix: String) {
DEFAULT(""),
SM("-sm"),
MD("-md"),
@ -182,7 +181,7 @@ enum class ContainerSize(val suffix: String) {
FLUID("-fluid")
}
inline fun RBuilder.container(
public inline fun RBuilder.container(
size: ContainerSize = ContainerSize.FLUID,
block: StyledDOMBuilder<DIV>.() -> Unit
): ReactElement = styledDiv{
@ -193,7 +192,7 @@ inline fun RBuilder.container(
}
enum class GridMaxSize(val suffix: String) {
public enum class GridMaxSize(public val suffix: String) {
NONE(""),
SM("-sm"),
MD("-md"),
@ -201,7 +200,7 @@ enum class GridMaxSize(val suffix: String) {
XL("-xl")
}
inline fun RBuilder.gridColumn(
public inline fun RBuilder.gridColumn(
weight: Int? = null,
maxSize: GridMaxSize = GridMaxSize.NONE,
block: StyledDOMBuilder<DIV>.() -> Unit
@ -213,7 +212,7 @@ inline fun RBuilder.gridColumn(
block()
}
inline fun RBuilder.gridRow(
public inline fun RBuilder.gridRow(
block: StyledDOMBuilder<DIV>.() -> Unit
): ReactElement = styledDiv{
css{
@ -222,10 +221,10 @@ inline fun RBuilder.gridRow(
block()
}
fun Element.renderObjectTree(
public fun Element.renderObjectTree(
vision: Vision,
clickCallback: (Name) -> Unit = {}
) = render(this) {
): Unit = render(this) {
card("Object tree") {
child(ObjectTree) {
attrs {

View File

@ -1,20 +1,14 @@
plugins {
id("scientifik.js")
id("ru.mipt.npm.js")
}
val dataforgeVersion: String by rootProject.extra
kotlin {
target {
useCommonJs()
}
}
dependencies{
api(project(":ui:react"))
api("subroh0508.net.kotlinmaterialui:core:0.4.0")
api("subroh0508.net.kotlinmaterialui:lab:0.4.0")
api("subroh0508.net.kotlinmaterialui:core:0.4.5")
api("subroh0508.net.kotlinmaterialui:lab:0.4.5")
api(npm("@material-ui/core","4.9.14"))
api(npm("@material-ui/lab","4.0.0-alpha.51"))
//api(npm("@material-ui/icons","4.9.1"))

View File

@ -1,11 +1,5 @@
plugins {
id("scientifik.js")
}
kotlin {
target {
useCommonJs()
}
id("ru.mipt.npm.js")
}
val reactVersion by extra("16.13.1")
@ -14,7 +8,7 @@ dependencies{
api(project(":visionforge-core"))
//api("org.jetbrains:kotlin-react:16.13.1-pre.104-kotlin-1.3.72")
api("org.jetbrains:kotlin-react-dom:$reactVersion-pre.104-kotlin-1.3.72")
api("org.jetbrains:kotlin-react-dom:$reactVersion-pre.123-kotlin-1.4.10")
api(npm("react", reactVersion))
api(npm("react-dom", reactVersion))

View File

@ -4,6 +4,7 @@ import hep.dataforge.meta.*
import hep.dataforge.meta.descriptors.*
import hep.dataforge.names.Name
import hep.dataforge.names.NameToken
import hep.dataforge.names.lastOrNull
import hep.dataforge.names.plus
import hep.dataforge.values.Value
import kotlinx.html.js.onClickFunction
@ -47,7 +48,7 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) {
val defaultItem = props.default?.get(props.name)
var actualItem: MetaItem<Meta>? by state { item ?: defaultItem ?: descriptorItem?.defaultItem() }
val token = props.name.last()?.toString() ?: "Properties"
val token = props.name.lastOrNull()?.toString() ?: "Properties"
fun update() {
item = props.root[props.name]

View File

@ -9,6 +9,7 @@ import hep.dataforge.meta.descriptors.get
import hep.dataforge.meta.get
import hep.dataforge.names.Name
import hep.dataforge.names.NameToken
import hep.dataforge.names.lastOrNull
import hep.dataforge.names.plus
import kotlinx.html.js.onClickFunction
import org.w3c.dom.events.Event
@ -43,7 +44,7 @@ private fun RFBuilder.metaViewerItem(props: MetaViewerProps) {
val descriptorItem: ItemDescriptor? = props.descriptor?.get(props.name)
val actualItem = item ?: descriptorItem?.defaultItem()
val token = props.name.last()?.toString() ?: "Meta"
val token = props.name.lastOrNull()?.toString() ?: "Meta"
val expanderClick: (Event) -> Unit = {
expanded = !expanded

View File

@ -1,6 +1,7 @@
package hep.dataforge.vision.react
import hep.dataforge.names.Name
import hep.dataforge.names.lastOrNull
import hep.dataforge.names.plus
import hep.dataforge.names.startsWith
import hep.dataforge.vision.Vision
@ -42,7 +43,7 @@ private fun RFBuilder.objectTree(props: ObjectTreeProps): Unit {
}
}
val token = props.name.last()?.toString() ?: "World"
val token = props.name.lastOrNull()?.toString() ?: "World"
val obj = props.obj
//display as node if any child is visible

View File

@ -1,22 +1,13 @@
plugins {
id("scientifik.js")
id("ru.mipt.npm.js")
}
val dataforgeVersion: String by rootProject.extra
kotlin {
target {
useCommonJs()
}
}
dependencies{
api(project(":ui:react"))
implementation(npm("@jetbrains/logos", "1.1.6"))
implementation(npm("@jetbrains/ring-ui", "3.0.13"))
implementation(npm("svg-inline-loader", "0.8.0"))
}

View File

@ -1,13 +1,10 @@
plugins {
id("scientifik.mpp")
id("ru.mipt.npm.mpp")
}
val dataforgeVersion: String by rootProject.extra
kotlin {
js {
useCommonJs()
}
sourceSets {
commonMain {
@ -30,15 +27,15 @@ kotlin {
jsMain {
dependencies {
api("hep.dataforge:dataforge-output-html:$dataforgeVersion")
api("org.jetbrains.kotlinx:kotlinx-html:0.6.12")
api("org.jetbrains.kotlinx:kotlinx-html:0.7.2")
//api("org.jetbrains:kotlin-extensions:1.0.1-pre.105-kotlin-1.3.72")
//api("org.jetbrains:kotlin-css-js:1.0.0-pre.105-kotlin-1.3.72")
api("org.jetbrains:kotlin-styled:1.0.0-pre.104-kotlin-1.3.72")
api("org.jetbrains:kotlin-styled:5.2.0-pre.123-kotlin-1.4.10")
api(npm("core-js", "2.6.5"))
api(npm("inline-style-prefixer", "5.1.0"))
api(npm("styled-components", "4.3.2"))
api(npm("styled-components", "5.2.0"))
//api(project(":ringui-wrapper"))
}
}

View File

@ -4,7 +4,7 @@ import hep.dataforge.meta.*
import hep.dataforge.names.Name
@DFExperimental
class ConfigProperty(val config: Config, val name: Name) : Property<MetaItem<*>?> {
internal class ConfigProperty(val config: Config, val name: Name) : Property<MetaItem<*>?> {
override var value: MetaItem<*>?
get() = config[name]
set(value) {

View File

@ -87,13 +87,13 @@ abstract class AbstractVision : Vision {
/**
* Reset all properties to their default values
*/
fun resetProperties() {
public fun resetProperties() {
properties?.removeListener(this)
properties = null
}
companion object {
val descriptor = NodeDescriptor {
public companion object {
public val descriptor: NodeDescriptor = NodeDescriptor {
value(STYLE_KEY) {
type(ValueType.STRING)
multiple = true

View File

@ -1,9 +1,6 @@
package hep.dataforge.vision
import hep.dataforge.names.Name
import hep.dataforge.names.NameToken
import hep.dataforge.names.asName
import hep.dataforge.names.isEmpty
import hep.dataforge.names.*
import kotlinx.serialization.Transient
@ -105,7 +102,7 @@ abstract class AbstractVisionGroup : AbstractVision(), MutableVisionGroup {
return when {
name.isEmpty() -> error("Should be unreachable")
name.length == 1 -> {
val token = name.first()!!
val token = name.tokens.first()
when (val current = children[token]) {
null -> createGroup().also { child ->
attach(child)
@ -115,7 +112,7 @@ abstract class AbstractVisionGroup : AbstractVision(), MutableVisionGroup {
else -> error("Can't create group with name $name because it exists and not a group")
}
}
else -> createGroups(name.first()!!.asName()).createGroups(name.cutFirst())
else -> createGroups(name.tokens.first().asName()).createGroups(name.cutFirst())
}
}
@ -131,7 +128,7 @@ abstract class AbstractVisionGroup : AbstractVision(), MutableVisionGroup {
}
}
name.length == 1 -> {
val token = name.first()!!
val token = name.tokens.first()
if (child == null) {
removeChild(token)
} else {
@ -142,7 +139,7 @@ abstract class AbstractVisionGroup : AbstractVision(), MutableVisionGroup {
else -> {
//TODO add safety check
val parent = (get(name.cutLast()) as? MutableVisionGroup) ?: createGroups(name.cutLast())
parent[name.last()!!.asName()] = child
parent[name.tokens.last().asName()] = child
}
}
childrenChanged(name, child)

View File

@ -8,20 +8,23 @@ import hep.dataforge.names.asName
import kotlinx.serialization.*
import kotlinx.serialization.builtins.MapSerializer
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
/**
* A container for styles
*/
@Serializable
class StyleSheet private constructor(private val styleMap: MutableMap<String, Meta> = LinkedHashMap()) {
public class StyleSheet private constructor(private val styleMap: MutableMap<String, Meta> = LinkedHashMap()) {
@Transient
internal var owner: Vision? = null
constructor(owner: Vision) : this() {
public constructor(owner: Vision) : this() {
this.owner = owner
}
val items: Map<String, Meta> get() = styleMap
public val items: Map<String, Meta> get() = styleMap
private fun Vision.styleChanged(key: String, oldStyle: Meta?, newStyle: Meta?) {
@ -38,14 +41,14 @@ class StyleSheet private constructor(private val styleMap: MutableMap<String, Me
}
}
operator fun get(key: String): Meta? {
public operator fun get(key: String): Meta? {
return styleMap[key] ?: owner?.parent?.styleSheet?.get(key)
}
/**
* Define a style without notifying owner
*/
fun define(key: String, style: Meta?) {
public fun define(key: String, style: Meta?) {
if (style == null) {
styleMap.remove(key)
} else {
@ -56,7 +59,7 @@ class StyleSheet private constructor(private val styleMap: MutableMap<String, Me
/**
* Set or clear the style
*/
operator fun set(key: String, style: Meta?) {
public operator fun set(key: String, style: Meta?) {
val oldStyle = styleMap[key]
define(key, style)
owner?.styleChanged(key, oldStyle, style)
@ -65,13 +68,14 @@ class StyleSheet private constructor(private val styleMap: MutableMap<String, Me
/**
* Create and set a style
*/
operator fun set(key: String, builder: MetaBuilder.() -> Unit) {
public operator fun set(key: String, builder: MetaBuilder.() -> Unit) {
val newStyle = get(key)?.edit(builder) ?: Meta(builder)
set(key, newStyle.seal())
}
@ExperimentalSerializationApi
@Serializer(StyleSheet::class)
companion object : KSerializer<StyleSheet> {
public companion object : KSerializer<StyleSheet> {
private val mapSerializer = MapSerializer(String.serializer(), MetaSerializer)
override val descriptor: SerialDescriptor get() = mapSerializer.descriptor
@ -91,14 +95,14 @@ class StyleSheet private constructor(private val styleMap: MutableMap<String, Me
/**
* Add style name to the list of styles to be resolved later. The style with given name does not necessary exist at the moment.
*/
fun Vision.useStyle(name: String) {
styles = properties[Vision.STYLE_KEY].stringList + name
public fun Vision.useStyle(name: String) {
styles = (properties[Vision.STYLE_KEY]?.stringList ?: emptyList()) + name
}
/**
* Resolve an item in all style layers
*/
fun Vision.getStyleItems(name: Name): Sequence<MetaItem<*>> {
public fun Vision.getStyleItems(name: Name): Sequence<MetaItem<*>> {
return styles.asSequence().map {
resolveStyle(it)
}.map {
@ -109,4 +113,4 @@ fun Vision.getStyleItems(name: Name): Sequence<MetaItem<*>> {
/**
* Collect all styles for this object in a single laminate
*/
val Vision.allStyles: Laminate get() = Laminate(styles.mapNotNull(::resolveStyle))
public val Vision.allStyles: Laminate get() = Laminate(styles.mapNotNull(::resolveStyle))

View File

@ -5,7 +5,9 @@ import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.names.toName
import hep.dataforge.provider.Type
import hep.dataforge.values.asValue
import hep.dataforge.vision.Vision.Companion.TYPE
import hep.dataforge.vision.Vision.Companion.VISIBLE_KEY
import kotlinx.serialization.PolymorphicSerializer
import kotlinx.serialization.Transient
@ -13,28 +15,28 @@ import kotlinx.serialization.Transient
* A root type for display hierarchy
*/
@Type(TYPE)
interface Vision : Configurable {
public interface Vision : Configurable {
/**
* The parent object of this one. If null, this one is a root.
*/
@Transient
var parent: VisionGroup?
public var parent: VisionGroup?
/**
* Nullable version of [config] used to check if this [Vision] has custom properties
*/
val properties: Config?
public val properties: Config?
/**
* All properties including styles and prototypes if present, including inherited ones
*/
fun getAllProperties(): Laminate
public fun getAllProperties(): Laminate
/**
* Get property (including styles). [inherit] toggles parent node property lookup
*/
fun getProperty(name: Name, inherit: Boolean): MetaItem<*>?
public fun getProperty(name: Name, inherit: Boolean): MetaItem<*>?
/**
* Ger a property including inherited values
@ -44,46 +46,55 @@ interface Vision : Configurable {
/**
* Trigger property invalidation event. If [name] is empty, notify that the whole object is changed
*/
fun propertyChanged(name: Name): Unit
public fun propertyChanged(name: Name): Unit
/**
* Add listener triggering on property change
*/
fun onPropertyChange(owner: Any?, action: (Name) -> Unit): Unit
public fun onPropertyChange(owner: Any?, action: (Name) -> Unit): Unit
/**
* Remove change listeners with given owner.
*/
fun removeChangeListener(owner: Any?)
public fun removeChangeListener(owner: Any?)
/**
* List of names of styles applied to this object. Order matters. Not inherited.
*/
var styles: List<String>
get() = properties[STYLE_KEY].stringList
public var styles: List<String>
get() = properties[STYLE_KEY]?.stringList?: emptyList()
set(value) {
config[STYLE_KEY] = value
}
companion object {
const val TYPE = "vision"
val STYLE_KEY = "@style".asName()
public companion object {
public const val TYPE: String = "vision"
public val STYLE_KEY: Name = "@style".asName()
private val VISION_SERIALIZER = PolymorphicSerializer(Vision::class)
fun serializer() = VISION_SERIALIZER
public fun serializer(): PolymorphicSerializer<Vision> = VISION_SERIALIZER
public val VISIBLE_KEY: Name = "visible".asName()
}
}
/**
* Get [Vision] property using key as a String
*/
fun Vision.getProperty(key: String, inherit: Boolean = true): MetaItem<*>? =
public fun Vision.getProperty(key: String, inherit: Boolean = true): MetaItem<*>? =
getProperty(key.toName(), inherit)
/**
* Find a style with given name for given [Vision]. The style is not necessary applied to this [Vision].
*/
tailrec fun Vision.resolveStyle(name: String): Meta? =
public tailrec fun Vision.resolveStyle(name: String): Meta? =
(this as? VisionGroup)?.styleSheet?.get(name) ?: parent?.resolveStyle(name)
/**
* Control visibility of the element
*/
public var Vision.visible: Boolean?
get() = getItem(VISIBLE_KEY).boolean
set(value) = setItem(VISIBLE_KEY, value?.asValue())

View File

@ -3,14 +3,18 @@ package hep.dataforge.vision
import hep.dataforge.names.*
import hep.dataforge.provider.Provider
public interface VisionContainer<out V: Vision>{
public operator fun get(name: Name): V?
}
/**
* Represents a group of [Vision] instances
*/
interface VisionGroup : Provider, Vision {
public interface VisionGroup : Provider, Vision, VisionContainer<Vision> {
/**
* A map of top level named children
*/
val children: Map<NameToken, Vision>
public val children: Map<NameToken, Vision>
override val defaultTarget: String get() = Vision.TYPE
@ -18,17 +22,17 @@ interface VisionGroup : Provider, Vision {
* A stylesheet for this group and its descendants. Stylesheet is not applied directly,
* but instead is just a repository for named configurations.
*/
val styleSheet: StyleSheet?
public val styleSheet: StyleSheet?
/**
* A map of direct children for specific target
* (currently "visual" or "style")
*/
override fun provideTop(target: String): Map<Name, Any> =
override fun content(target: String): Map<Name, Any> =
when (target) {
Vision.TYPE -> children.flatMap { (key, value) ->
val res: Map<Name, Any> = if (value is VisionGroup) {
value.provideTop(target).mapKeys { key + it.key }
value.content(target).mapKeys { key + it.key }
} else {
mapOf(key.asName() to value)
}
@ -38,18 +42,18 @@ interface VisionGroup : Provider, Vision {
else -> emptyMap()
}
operator fun get(name: Name): Vision? {
public override operator fun get(name: Name): Vision? {
return when {
name.isEmpty() -> this
name.length == 1 -> children[name.first()!!]
else -> (children[name.first()!!] as? VisionGroup)?.get(name.cutFirst())
name.length == 1 -> children[name.tokens.first()]
else -> (children[name.tokens.first()] as? VisionGroup)?.get(name.cutFirst())
}
}
/**
* A fix for serialization bug that writes all proper parents inside the tree after deserialization
*/
fun attachChildren() {
public fun attachChildren() {
styleSheet?.owner = this
children.values.forEach {
it.parent = this
@ -57,41 +61,45 @@ interface VisionGroup : Provider, Vision {
}
}
companion object {
const val STYLE_TARGET = "style"
public companion object {
public const val STYLE_TARGET: String = "style"
}
}
/**
* Iterate over children of this group
*/
operator fun VisionGroup.iterator(): Iterator<Vision> = children.values.iterator()
public operator fun VisionGroup.iterator(): Iterator<Vision> = children.values.iterator()
val VisionGroup.isEmpty: Boolean get() = this.children.isEmpty()
public val VisionGroup.isEmpty: Boolean get() = this.children.isEmpty()
public interface VisionContainerBuilder<in V: Vision>{
public operator fun set(name: Name, child: V?)
}
/**
* Mutable version of [VisionGroup]
*/
interface MutableVisionGroup : VisionGroup {
public interface MutableVisionGroup : VisionGroup, VisionContainerBuilder<Vision> {
/**
* Add listener for children structure change.
* @param owner the handler to properly remove listeners
* @param action First argument of the action is the name of changed child. Second argument is the new value of the object.
*/
fun onChildrenChange(owner: Any?, action: (Name, Vision?) -> Unit)
public fun onChildrenChange(owner: Any?, action: (Name, Vision?) -> Unit)
/**
* Remove children change listener
*/
fun removeChildrenChangeListener(owner: Any?)
public fun removeChildrenChangeListener(owner: Any?)
operator fun set(name: Name, child: Vision?)
// public operator fun set(name: Name, child: Vision?)
}
operator fun VisionGroup.get(str: String?): Vision? = get(str?.toName() ?: Name.EMPTY)
public operator fun <V: Vision> VisionContainer<V>.get(str: String?): V? = get(str?.toName() ?: Name.EMPTY)
operator fun MutableVisionGroup.set(token: NameToken, child: Vision?): Unit = set(token.asName(), child)
operator fun MutableVisionGroup.set(key: String, child: Vision?): Unit = set(key.toName(), child)
public operator fun <V: Vision> VisionContainerBuilder<V>.set(token: NameToken, child: V?): Unit = set(token.asName(), child)
public operator fun <V: Vision> VisionContainerBuilder<V>.set(key: String, child: V?): Unit = set(key.toName(), child)
fun MutableVisionGroup.removeAll() = children.keys.map { it.asName() }.forEach { this[it] = null }
public fun MutableVisionGroup.removeAll(): Unit = children.keys.map { it.asName() }.forEach { this[it] = null }

View File

@ -3,35 +3,37 @@ package hep.dataforge.vision
import hep.dataforge.context.*
import hep.dataforge.meta.*
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.names.Name
import hep.dataforge.names.toName
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.UnstableDefault
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.modules.SerialModule
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.polymorphic
import kotlinx.serialization.modules.subclass
import kotlin.reflect.KClass
@DFExperimental
interface VisionForm<T : Vision> {
val type: KClass<out T>
val serializer: KSerializer<T>
public interface VisionForm<T : Vision> {
public val type: KClass<out T>
public val serializer: KSerializer<T>
val name get() = serializer.descriptor.serialName.toName()
public val name: Name
get() = serializer.descriptor.serialName.toName()
/**
* Apply a patch to given [Vision]
*/
fun patch(obj: T, meta: Meta)
public fun patch(obj: T, meta: Meta)
companion object {
const val TYPE = "visionForm"
public companion object {
public const val TYPE: String = "visionForm"
}
}
@DFExperimental
object SimpleGroupForm: VisionForm<SimpleVisionGroup>{
public object SimpleGroupForm : VisionForm<SimpleVisionGroup> {
override val type: KClass<out SimpleVisionGroup> = SimpleVisionGroup::class
override val serializer: KSerializer<SimpleVisionGroup> = SimpleVisionGroup.serializer()
@ -42,86 +44,93 @@ object SimpleGroupForm: VisionForm<SimpleVisionGroup>{
}
@DFExperimental
fun <T : Vision> VisionForm<T>.visionToMeta(vision: T, module: SerialModule, descriptor: NodeDescriptor? = null): Meta {
val engine = Json(VisionManager.jsonConfiguration, module)
val json = engine.toJson<T>(serializer, vision)
public fun <T : Vision> VisionForm<T>.visionToMeta(
vision: T,
module: SerializersModule,
descriptor: NodeDescriptor? = null,
): Meta {
val engine = Json(VisionManager.jsonConfiguration) { serializersModule = module }
val json = engine.encodeToJsonElement(serializer, vision)
return json.toMetaItem(descriptor).node!!
}
@DFExperimental
fun <T : Vision> VisionForm<T>.buildVision(meta: Meta, module: SerialModule, descriptor: NodeDescriptor? = null): T {
val engine = Json(VisionManager.jsonConfiguration, module)
public fun <T : Vision> VisionForm<T>.buildVision(
meta: Meta,
module: SerializersModule,
descriptor: NodeDescriptor? = null,
): T {
val engine = Json(VisionManager.jsonConfiguration) { serializersModule = module }
val json = meta.toJson(descriptor)
return engine.fromJson(serializer, json)
return engine.decodeFromJsonElement(serializer, json)
}
@DFExperimental
class VisionManager(meta: Meta) : AbstractPlugin(meta) {
public class VisionManager(meta: Meta) : AbstractPlugin(meta) {
override val tag: PluginTag get() = Companion.tag
/**
* Create a list of factories on first call and cache it
*/
private val forms by lazy {
context.content<VisionForm<*>>(VisionForm.TYPE).mapKeys { it.value.type }
context.gather<VisionForm<*>>(VisionForm.TYPE).mapKeys { it.value.type }
}
val visionSerialModule
public val visionSerialModule: SerializersModule
get() = SerializersModule {
include(defaultSerialModule)
context.content<SerialModule>(VISION_SERIAL_MODULE_TARGET).values.forEach {
context.gather<SerializersModule>(VISION_SERIAL_MODULE_TARGET).values.forEach {
include(it)
}
}
@Suppress("UNCHECKED_CAST")
fun <T : Vision> resolveVisionForm(type: KClass<out T>): VisionForm<T>? =
public fun <T : Vision> resolveVisionForm(type: KClass<out T>): VisionForm<T> =
forms[type] as VisionForm<T>
inline fun <reified T : Vision> buildSpecificVision(meta: Meta): T {
public inline fun <reified T : Vision> buildSpecificVision(meta: Meta): T {
val factory = resolveVisionForm(T::class) ?: error("Could not resolve a form for ${meta["type"].string}")
return factory.buildVision(meta, visionSerialModule)
}
fun buildVision(meta: Meta): Vision {
@OptIn(ExperimentalSerializationApi::class)
public fun buildVision(meta: Meta): Vision {
val type = meta["type"].string ?: Vision.serializer().descriptor.serialName
val form = forms.values.find { it.name.toString() == type } ?: error("Could not resolve a form for type $type")
return form.buildVision(meta, visionSerialModule)
}
fun <T : Vision> writeVisionToMeta(vision: T): Meta {
public fun <T : Vision> writeVisionToMeta(vision: T): Meta {
val form = resolveVisionForm(vision::class) ?: error("Could not resolve a form for $vision")
val engine = Json(VisionManager.jsonConfiguration, visionSerialModule)
val json = engine.toJson(form.serializer,vision)
val engine = Json(jsonConfiguration) { serializersModule = visionSerialModule }
val json = engine.encodeToJsonElement(form.serializer, vision)
return json.toMetaItem().node!!
}
fun patchVision(vision: Vision, meta: Meta) {
public fun patchVision(vision: Vision, meta: Meta) {
val form = resolveVisionForm(vision::class) ?: error("Could not resolve a form for $vision")
form.patch(vision, meta)
}
companion object : PluginFactory<VisionManager> {
public companion object : PluginFactory<VisionManager> {
override val tag: PluginTag = PluginTag(name = "vision", group = PluginTag.DATAFORGE_GROUP)
override val type: KClass<out VisionManager> = VisionManager::class
const val VISION_SERIAL_MODULE_TARGET = "visionSerialModule"
public const val VISION_SERIAL_MODULE_TARGET: String = "visionSerialModule"
override fun invoke(meta: Meta, context: Context): VisionManager = VisionManager(meta)
@OptIn(UnstableDefault::class)
val jsonConfiguration = JsonConfiguration(
prettyPrint = true,
useArrayPolymorphism = false,
encodeDefaults = false,
public val jsonConfiguration: Json = Json {
prettyPrint = true
useArrayPolymorphism = false
encodeDefaults = false
ignoreUnknownKeys = true
)
}
val defaultSerialModule = SerializersModule {
polymorphic(Vision::class, VisionGroup::class) {
public val defaultSerialModule: SerializersModule = SerializersModule {
polymorphic(Vision::class) {
subclass(SimpleVisionGroup.serializer())
}
}
}
}

View File

@ -1,27 +1,27 @@
package hep.dataforge.vision
import hep.dataforge.meta.Meta
import hep.dataforge.meta.*
import hep.dataforge.meta.descriptors.ValueDescriptor
import hep.dataforge.meta.descriptors.setAttribute
import hep.dataforge.meta.get
import hep.dataforge.meta.node
import hep.dataforge.meta.string
import hep.dataforge.names.toName
import hep.dataforge.meta.descriptors.attributes
/**
* Extension property to access the "widget" key of [ValueDescriptor]
*/
var ValueDescriptor.widget: Meta
public var ValueDescriptor.widget: Meta
get() = attributes["widget"].node ?: Meta.EMPTY
set(value) {
setAttribute("widget".toName(), value)
attributes {
set("widget", value)
}
}
/**
* Extension property to access the "widget.type" key of [ValueDescriptor]
*/
var ValueDescriptor.widgetType: String?
public var ValueDescriptor.widgetType: String?
get() = attributes["widget.type"].string
set(value) {
setAttribute("widget.type".toName(), value)
attributes{
set("widget.type", value)
}
}

View File

@ -1,6 +1,7 @@
package hep.dataforge.vision.visitor
import hep.dataforge.names.Name
import hep.dataforge.names.length
import hep.dataforge.vision.Vision
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job

View File

@ -4,10 +4,7 @@ import hep.dataforge.meta.*
import hep.dataforge.meta.descriptors.ItemDescriptor
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.meta.descriptors.ValueDescriptor
import hep.dataforge.names.Name
import hep.dataforge.names.NameToken
import hep.dataforge.names.asName
import hep.dataforge.names.withIndex
import hep.dataforge.names.*
import hep.dataforge.values.Null
import hep.dataforge.values.Value
import javafx.beans.binding.ListBinding
@ -137,12 +134,12 @@ class FXMetaNode<M : MetaNode<M>>(
}
}
class FXMetaValue<M : MetaNode<M>>(
public class FXMetaValue<M : MetaNode<M>>(
override val name: NameToken,
override val parent: FXMetaNode<M>
) : FXMeta<M>() {
val descriptorProperty = parent.descriptorProperty.objectBinding {
public val descriptorProperty = parent.descriptorProperty.objectBinding {
it?.values?.get(name.body)
}
@ -153,24 +150,24 @@ class FXMetaValue<M : MetaNode<M>>(
//private val innerValueProperty = SimpleObjectProperty(value)
val valueProperty = descriptorProperty.objectBinding { descriptor ->
public val valueProperty = descriptorProperty.objectBinding { descriptor ->
parent.node[name].value ?: descriptor?.default
}
override val hasValue: ObservableBooleanValue = parent.nodeProperty.booleanBinding { it[name] != null }
val value by valueProperty
public val value by valueProperty
override val descriptionProperty = descriptorProperty.stringBinding { it?.info ?: "" }
}
fun <M : MutableMeta<M>> FXMetaNode<M>.remove(name: NameToken) {
public fun <M : MutableMeta<M>> FXMetaNode<M>.remove(name: NameToken) {
node?.remove(name.asName())
children.invalidate()
}
private fun <M : MutableMeta<M>> M.createEmptyNode(token: NameToken, append: Boolean): M {
return if (append && token.index.isNotEmpty()) {
return if (append && token.hasIndex()) {
val name = token.asName()
val index = (getIndexed(name).keys.mapNotNull { it.toIntOrNull() }.max() ?: -1) + 1
val newName = name.withIndex(index.toString())

View File

@ -1,5 +1,5 @@
plugins {
id("scientifik.mpp")
id("ru.mipt.npm.mpp")
}
kotlin {
@ -7,7 +7,7 @@ kotlin {
val commonMain by getting {
dependencies {
api(project(":visionforge-solid"))
api("scientifik:gdml:0.1.8")
api("kscience.gdml:gdml:0.2.0-dev-2")
}
}
}

View File

@ -12,7 +12,7 @@ import hep.dataforge.vision.set
import hep.dataforge.vision.solid.*
import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY
import hep.dataforge.vision.useStyle
import scientifik.gdml.*
import kscience.gdml.*
import kotlin.math.cos
import kotlin.math.sin
import kotlin.random.Random
@ -20,7 +20,7 @@ import kotlin.random.Random
private val solidsName = "solids".asName()
private val volumesName = "volumes".asName()
class GDMLTransformer internal constructor(val root: GDML) {
public class GDMLTransformer internal constructor(val root: GDML) {
//private val materialCache = HashMap<GDMLMaterial, Meta>()
private val random = Random(222)

View File

@ -1,70 +0,0 @@
package hep.dataforge.vision.gdml
import scientifik.gdml.AUnit
import scientifik.gdml.GDMLPosition
import scientifik.gdml.GDMLRotation
import scientifik.gdml.GDMLSolid
enum class LUnit(val value: Float) {
MM(1f),
CM(10f),
M(1000f)
}
fun GDMLPosition.unit(): LUnit = LUnit.valueOf(unit.toUpperCase())
fun GDMLPosition.x(unit: LUnit): Float = if (unit.name == this.unit) {
x.toFloat()
} else {
x.toFloat() / unit.value * unit().value
}
fun GDMLPosition.y(unit: LUnit): Float = if (unit.name == this.unit) {
y.toFloat()
} else {
y.toFloat() / unit.value * unit().value
}
fun GDMLPosition.z(unit: LUnit): Float = if (unit.name == this.unit) {
z.toFloat()
} else {
z.toFloat() / unit.value * unit().value
}
fun GDMLRotation.unit(): AUnit = AUnit.valueOf(unit.toUpperCase())
fun GDMLRotation.x(unit: AUnit = AUnit.RAD): Float = if (unit.name == this.unit) {
x.toFloat()
} else {
x.toFloat() / unit.value * unit().value
}
fun GDMLRotation.y(unit: AUnit = AUnit.RAD): Float = if (unit.name == this.unit) {
y.toFloat()
} else {
y.toFloat() / unit.value * unit().value
}
fun GDMLRotation.z(unit: AUnit = AUnit.RAD): Float = if (unit.name == this.unit) {
z.toFloat()
} else {
z.toFloat() / unit.value * unit().value
}
fun GDMLSolid.lscale(unit: LUnit): Float {
val solidUnit = lunit?.let { LUnit.valueOf(it.toUpperCase()) } ?: return 1f
return if (solidUnit == unit) {
1f
} else {
solidUnit.value / unit.value
}
}
fun GDMLSolid.ascale(unit: AUnit = AUnit.RAD): Float {
val solidUnit = aunit?.let { AUnit.valueOf(it.toUpperCase()) } ?: return 1f
return if (solidUnit == unit) {
1f
} else {
solidUnit.value / unit.value
}
}

View File

@ -2,7 +2,7 @@ package hep.dataforge.vision.gdml
import hep.dataforge.vision.solid.SolidGroup
import nl.adaptivity.xmlutil.StAXReader
import scientifik.gdml.GDML
import kscience.gdml.GDML
import java.nio.file.Files
import java.nio.file.Path
import java.util.concurrent.atomic.AtomicInteger

View File

@ -1,9 +1,9 @@
package hep.dataforge.vision.gdml
import hep.dataforge.vision.solid.stringify
import hep.dataforge.vision.solid.encodeToString
import nl.adaptivity.xmlutil.StAXReader
import org.junit.jupiter.api.Test
import scientifik.gdml.GDML
import kscience.gdml.GDML
class TestConvertor {
@ -13,7 +13,7 @@ class TestConvertor {
val xmlReader = StAXReader(stream, "UTF-8")
val xml = GDML.format.parse(GDML.serializer(), xmlReader)
val vision = xml.toVision()
println(vision.stringify())
println(vision.encodeToString())
}
@Test
@ -33,6 +33,6 @@ class TestConvertor {
val xmlReader = StAXReader(stream, "UTF-8")
val xml = GDML.format.parse(GDML.serializer(), xmlReader)
val visual = xml.toVision()
println(visual.stringify())
println(visual.encodeToString())
}
}

View File

@ -8,7 +8,7 @@ import hep.dataforge.vision.visitor.flowStatistics
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import nl.adaptivity.xmlutil.StAXReader
import scientifik.gdml.GDML
import kscience.gdml.GDML
import java.io.File
import kotlin.reflect.KClass

View File

@ -1,15 +1,14 @@
import scientifik.useSerialization
import ru.mipt.npm.gradle.KScienceVersions.coroutinesVersion
plugins {
id("scientifik.mpp")
id("ru.mipt.npm.mpp")
}
useSerialization()
kscience {
useSerialization()
}
kotlin {
js {
useCommonJs()
}
sourceSets {
commonMain {
@ -22,7 +21,7 @@ kotlin {
api("org.fxyz3d:fxyz3d:0.5.2") {
exclude(module = "slf4j-simple")
}
api("org.jetbrains.kotlinx:kotlinx-coroutines-javafx:${Scientifik.coroutinesVersion}")
api("org.jetbrains.kotlinx:kotlinx-coroutines-javafx:${coroutinesVersion}")
implementation("eu.mihosoft.vrl.jcsg:jcsg:0.5.7") {
exclude(module = "slf4j-simple")
}
@ -37,4 +36,4 @@ kotlin {
}
}
}
}
}

View File

@ -5,6 +5,7 @@ package hep.dataforge.vision.solid
import hep.dataforge.meta.Config
import hep.dataforge.vision.AbstractVision
import hep.dataforge.vision.MutableVisionGroup
import hep.dataforge.vision.VisionContainerBuilder
import hep.dataforge.vision.set
import hep.dataforge.vision.solid.Solid.Companion.solidEquals
import kotlinx.serialization.SerialName
@ -13,10 +14,10 @@ import kotlinx.serialization.UseSerializers
@Serializable
@SerialName("solid.box")
class Box(
val xSize: Float,
val ySize: Float,
val zSize: Float
public class Box(
public val xSize: Float,
public val ySize: Float,
public val zSize: Float
) : AbstractVision(), GeometrySolid {
override var position: Point3D? = null
@ -67,15 +68,15 @@ class Box(
}
companion object {
public companion object {
}
}
inline fun MutableVisionGroup.box(
public inline fun VisionContainerBuilder<Solid>.box(
xSize: Number,
ySize: Number,
zSize: Number,
name: String = "",
action: Box.() -> Unit = {}
) = Box(xSize.toFloat(), ySize.toFloat(), zSize.toFloat()).apply(action).also { set(name, it) }
): Box = Box(xSize.toFloat(), ySize.toFloat(), zSize.toFloat()).apply(action).also { set(name, it) }

View File

@ -10,7 +10,7 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers
enum class CompositeType {
public enum class CompositeType {
UNION,
INTERSECT,
SUBTRACT
@ -18,10 +18,10 @@ enum class CompositeType {
@Serializable
@SerialName("solid.composite")
class Composite(
val compositeType: CompositeType,
val first: Solid,
val second: Solid
public class Composite(
public val compositeType: CompositeType,
public val first: Solid,
public val second: Solid
) : AbstractVision(), Solid, VisionGroup {
init {
@ -42,7 +42,7 @@ class Composite(
get() = null
}
inline fun MutableVisionGroup.composite(
public inline fun MutableVisionGroup.composite(
type: CompositeType,
name: String = "",
builder: SolidGroup.() -> Unit
@ -67,11 +67,11 @@ inline fun MutableVisionGroup.composite(
}
}
inline fun MutableVisionGroup.union(name: String = "", builder: SolidGroup.() -> Unit) =
public inline fun MutableVisionGroup.union(name: String = "", builder: SolidGroup.() -> Unit): Composite =
composite(CompositeType.UNION, name, builder = builder)
inline fun MutableVisionGroup.subtract(name: String = "", builder: SolidGroup.() -> Unit) =
public inline fun MutableVisionGroup.subtract(name: String = "", builder: SolidGroup.() -> Unit): Composite =
composite(CompositeType.SUBTRACT, name, builder = builder)
inline fun MutableVisionGroup.intersect(name: String = "", builder: SolidGroup.() -> Unit) =
public inline fun MutableVisionGroup.intersect(name: String = "", builder: SolidGroup.() -> Unit): Composite =
composite(CompositeType.INTERSECT, name, builder = builder)

View File

@ -5,6 +5,7 @@ package hep.dataforge.vision.solid
import hep.dataforge.meta.Config
import hep.dataforge.vision.AbstractVision
import hep.dataforge.vision.MutableVisionGroup
import hep.dataforge.vision.VisionContainerBuilder
import hep.dataforge.vision.set
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@ -17,12 +18,12 @@ import kotlin.math.sin
*/
@Serializable
@SerialName("solid.cone")
class ConeSegment(
var radius: Float,
var height: Float,
var upperRadius: Float,
var startAngle: Float = 0f,
var angle: Float = PI2
public class ConeSegment(
public var radius: Float,
public var height: Float,
public var upperRadius: Float,
public var startAngle: Float = 0f,
public var angle: Float = PI2
) : AbstractVision(), GeometrySolid {
override var properties: Config? = null
@ -75,7 +76,7 @@ class ConeSegment(
}
inline fun MutableVisionGroup.cylinder(
public inline fun VisionContainerBuilder<Solid>.cylinder(
r: Number,
height: Number,
name: String = "",
@ -87,7 +88,7 @@ inline fun MutableVisionGroup.cylinder(
).apply(block).also { set(name, it) }
inline fun MutableVisionGroup.cone(
public inline fun VisionContainerBuilder<Solid>.cone(
bottomRadius: Number,
height: Number,
upperRadius: Number = 0.0,

View File

@ -5,6 +5,7 @@ package hep.dataforge.vision.solid
import hep.dataforge.meta.Config
import hep.dataforge.vision.AbstractVision
import hep.dataforge.vision.MutableVisionGroup
import hep.dataforge.vision.VisionContainerBuilder
import hep.dataforge.vision.set
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@ -12,7 +13,7 @@ import kotlinx.serialization.UseSerializers
@Serializable
@SerialName("solid.convex")
class Convex(val points: List<Point3D>) : AbstractVision(), Solid {
public class Convex(public val points: List<Point3D>) : AbstractVision(), Solid {
override var properties: Config? = null
@ -23,17 +24,17 @@ class Convex(val points: List<Point3D>) : AbstractVision(), Solid {
}
inline fun MutableVisionGroup.convex(name: String = "", action: ConvexBuilder.() -> Unit = {}) =
public inline fun VisionContainerBuilder<Solid>.convex(name: String = "", action: ConvexBuilder.() -> Unit = {}): Convex =
ConvexBuilder().apply(action).build().also { set(name, it) }
class ConvexBuilder {
public class ConvexBuilder {
private val points = ArrayList<Point3D>()
fun point(x: Number, y: Number, z: Number) {
public fun point(x: Number, y: Number, z: Number) {
points.add(Point3D(x, y, z))
}
fun build(): Convex {
public fun build(): Convex {
return Convex(points)
}
}

View File

@ -4,6 +4,7 @@ package hep.dataforge.vision.solid
import hep.dataforge.meta.Config
import hep.dataforge.vision.AbstractVision
import hep.dataforge.vision.MutableVisionGroup
import hep.dataforge.vision.VisionContainerBuilder
import hep.dataforge.vision.set
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@ -13,21 +14,21 @@ import kotlin.math.cos
import kotlin.math.sin
typealias Shape2D = List<Point2D>
public typealias Shape2D = List<Point2D>
@Serializable
class Shape2DBuilder(private val points: MutableList<Point2D> = ArrayList()) {
public class Shape2DBuilder(private val points: MutableList<Point2D> = ArrayList()) {
fun point(x: Number, y: Number) {
public fun point(x: Number, y: Number) {
points.add(Point2D(x, y))
}
infix fun Number.to(y: Number) = point(this, y)
public infix fun Number.to(y: Number): Unit = point(this, y)
fun build(): Shape2D = points
public fun build(): Shape2D = points
}
fun Shape2DBuilder.polygon(vertices: Int, radius: Number) {
public fun Shape2DBuilder.polygon(vertices: Int, radius: Number) {
require(vertices > 2) { "Polygon must have more than 2 vertices" }
val angle = 2 * PI / vertices
for (i in 0 until vertices) {
@ -36,13 +37,13 @@ fun Shape2DBuilder.polygon(vertices: Int, radius: Number) {
}
@Serializable
data class Layer(var x: Float, var y: Float, var z: Float, var scale: Float)
public data class Layer(var x: Float, var y: Float, var z: Float, var scale: Float)
@Serializable
@SerialName("solid.extrude")
class Extruded(
var shape: List<Point2D> = ArrayList(),
var layers: MutableList<Layer> = ArrayList()
public class Extruded(
public var shape: List<Point2D> = ArrayList(),
public var layers: MutableList<Layer> = ArrayList()
) : AbstractVision(), GeometrySolid {
override var properties: Config? = null
@ -51,12 +52,12 @@ class Extruded(
override var rotation: Point3D? = null
override var scale: Point3D? = null
fun shape(block: Shape2DBuilder.() -> Unit) {
public fun shape(block: Shape2DBuilder.() -> Unit) {
this.shape = Shape2DBuilder().apply(block).build()
//TODO send invalidation signal
}
fun layer(z: Number, x: Number = 0.0, y: Number = 0.0, scale: Number = 1.0) {
public fun layer(z: Number, x: Number = 0.0, y: Number = 0.0, scale: Number = 1.0) {
layers.add(Layer(x.toFloat(), y.toFloat(), z.toFloat(), scale.toFloat()))
//TODO send invalidation signal
}
@ -107,10 +108,10 @@ class Extruded(
geometryBuilder.cap(layers.last())
}
companion object {
const val TYPE = "geometry.3d.extruded"
public companion object {
public const val TYPE: String = "solid.extruded"
}
}
fun MutableVisionGroup.extrude(name: String = "", action: Extruded.() -> Unit = {}) =
public fun VisionContainerBuilder<Solid>.extrude(name: String = "", action: Extruded.() -> Unit = {}): Extruded =
Extruded().apply(action).also { set(name, it) }

View File

@ -5,7 +5,7 @@ import hep.dataforge.meta.Meta
/**
* @param T the type of resulting geometry
*/
interface GeometryBuilder<T : Any> {
public interface GeometryBuilder<T : Any> {
/**
* Add a face to 3D model. If one of the vertices is not present in the current geometry model list of vertices,
* it is added automatically.
@ -13,12 +13,12 @@ interface GeometryBuilder<T : Any> {
* @param normal optional external normal to the face
* @param meta optional additional platform-specific parameters like color or texture index
*/
fun face(vertex1: Point3D, vertex2: Point3D, vertex3: Point3D, normal: Point3D? = null, meta: Meta = Meta.EMPTY)
public fun face(vertex1: Point3D, vertex2: Point3D, vertex3: Point3D, normal: Point3D? = null, meta: Meta = Meta.EMPTY)
fun build(): T
public fun build(): T
}
fun GeometryBuilder<*>.face4(
public fun GeometryBuilder<*>.face4(
vertex1: Point3D,
vertex2: Point3D,
vertex3: Point3D,
@ -33,11 +33,11 @@ fun GeometryBuilder<*>.face4(
/**
* [GeometrySolid] is a [Solid] that can represent its own geometry as a set of polygons.
*/
interface GeometrySolid : Solid {
fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>)
public interface GeometrySolid : Solid {
public fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>)
}
fun <T : Any> GeometryBuilder<T>.cap(shape: List<Point3D>, normal: Point3D? = null) {
public fun <T : Any> GeometryBuilder<T>.cap(shape: List<Point3D>, normal: Point3D? = null) {
//FIXME won't work for non-convex shapes
val center = Point3D(
shape.map { it.x }.average(),

View File

@ -4,10 +4,12 @@ package hep.dataforge.vision.solid
import hep.dataforge.meta.Config
import hep.dataforge.meta.number
import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.names.plus
import hep.dataforge.vision.AbstractVision
import hep.dataforge.vision.MutableVisionGroup
import hep.dataforge.vision.VisionContainerBuilder
import hep.dataforge.vision.set
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@ -15,7 +17,7 @@ import kotlinx.serialization.UseSerializers
@Serializable
@SerialName("solid.line")
class PolyLine(var points: List<Point3D>) : AbstractVision(), Solid {
public class PolyLine(public var points: List<Point3D>) : AbstractVision(), Solid {
override var properties: Config? = null
override var position: Point3D? = null
@ -23,13 +25,13 @@ class PolyLine(var points: List<Point3D>) : AbstractVision(), Solid {
override var scale: Point3D? = null
//var lineType by string()
var thickness by number(1.0, key = SolidMaterial.MATERIAL_KEY + THICKNESS_KEY)
public var thickness: Number by number(1.0, key = SolidMaterial.MATERIAL_KEY + THICKNESS_KEY)
companion object {
val THICKNESS_KEY = "thickness".asName()
public companion object {
public val THICKNESS_KEY: Name = "thickness".asName()
}
}
fun MutableVisionGroup.polyline(vararg points: Point3D, name: String = "", action: PolyLine.() -> Unit = {}) =
public fun VisionContainerBuilder<Solid>.polyline(vararg points: Point3D, name: String = "", action: PolyLine.() -> Unit = {}): PolyLine =
PolyLine(points.toList()).apply(action).also { set(name, it) }

View File

@ -12,8 +12,8 @@ import kotlinx.serialization.Transient
import kotlinx.serialization.UseSerializers
import kotlin.collections.set
abstract class AbstractProxy : AbstractVision(), VisionGroup {
abstract val prototype: Vision
public abstract class AbstractProxy : AbstractVision(), VisionGroup {
public abstract val prototype: Vision
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
return if (inherit) {
@ -33,7 +33,7 @@ abstract class AbstractProxy : AbstractVision(), VisionGroup {
}
override var styles: List<String>
get() = properties[Vision.STYLE_KEY].stringList + prototype.styles
get() = (properties[Vision.STYLE_KEY]?.stringList ?: emptyList()) + prototype.styles
set(value) {
config[Vision.STYLE_KEY] = value
}
@ -53,11 +53,11 @@ abstract class AbstractProxy : AbstractVision(), VisionGroup {
*/
@Serializable
@SerialName("solid.proxy")
class Proxy private constructor(
val templateName: Name
public class Proxy private constructor(
public val templateName: Name
) : AbstractProxy(), Solid {
constructor(parent: SolidGroup, templateName: Name) : this(templateName) {
public constructor(parent: SolidGroup, templateName: Name) : this(templateName) {
this.parent = parent
}
@ -104,7 +104,7 @@ class Proxy private constructor(
* A ProxyChild is created temporarily only to interact with properties, it does not store any values
* (properties are stored in external cache) and created and destroyed on-demand).
*/
inner class ProxyChild(val name: Name) : AbstractProxy() {
public inner class ProxyChild(public val name: Name) : AbstractProxy() {
override val prototype: Vision get() = prototypeFor(name)
@ -136,12 +136,15 @@ class Proxy private constructor(
}
companion object {
const val PROXY_CHILD_PROPERTY_PREFIX = "@child"
public companion object {
public const val PROXY_CHILD_PROPERTY_PREFIX: String = "@child"
}
}
val Vision.prototype: Vision
/**
* Get a vision prototype if it is a [Proxy] or vision itself if it is not
*/
public val Vision.prototype: Vision
get() = when (this) {
is AbstractProxy -> prototype
else -> this
@ -150,7 +153,7 @@ val Vision.prototype: Vision
/**
* Create ref for existing prototype
*/
fun SolidGroup.ref(
public fun SolidGroup.ref(
templateName: Name,
name: String = ""
): Proxy = Proxy(this, templateName).also { set(name, it) }
@ -158,7 +161,7 @@ fun SolidGroup.ref(
/**
* Add new proxy wrapping given object and automatically adding it to the prototypes
*/
fun SolidGroup.proxy(
public fun SolidGroup.proxy(
name: String,
obj: Solid,
templateName: Name = name.toName()
@ -173,12 +176,3 @@ fun SolidGroup.proxy(
}
return ref(templateName, name)
}
fun SolidGroup.proxyGroup(
name: String,
templateName: Name = name.toName(),
block: MutableVisionGroup.() -> Unit
): Proxy {
val group = SolidGroup().apply(block)
return proxy(name, group, templateName)
}

View File

@ -4,65 +4,63 @@ package hep.dataforge.vision.solid
import hep.dataforge.meta.*
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.names.plus
import hep.dataforge.output.Renderer
import hep.dataforge.values.ValueType
import hep.dataforge.values.asValue
import hep.dataforge.vision.Vision
import hep.dataforge.vision.Vision.Companion.VISIBLE_KEY
import hep.dataforge.vision.enum
import hep.dataforge.vision.solid.Solid.Companion.DETAIL_KEY
import hep.dataforge.vision.solid.Solid.Companion.IGNORE_KEY
import hep.dataforge.vision.solid.Solid.Companion.LAYER_KEY
import hep.dataforge.vision.solid.Solid.Companion.VISIBLE_KEY
import kotlinx.serialization.UseSerializers
/**
* Interface for 3-dimensional [Vision]
*/
interface Solid : Vision {
var position: Point3D?
var rotation: Point3D?
var scale: Point3D?
public interface Solid : Vision {
public var position: Point3D?
public var rotation: Point3D?
public var scale: Point3D?
override val descriptor: NodeDescriptor? get() = Companion.descriptor
companion object {
val VISIBLE_KEY = "visible".asName()
public companion object {
// val SELECTED_KEY = "selected".asName()
val DETAIL_KEY = "detail".asName()
val LAYER_KEY = "layer".asName()
val IGNORE_KEY = "ignore".asName()
public val DETAIL_KEY: Name = "detail".asName()
public val LAYER_KEY: Name = "layer".asName()
public val IGNORE_KEY: Name = "ignore".asName()
val GEOMETRY_KEY = "geometry".asName()
public val GEOMETRY_KEY: Name = "geometry".asName()
val X_KEY = "x".asName()
val Y_KEY = "y".asName()
val Z_KEY = "z".asName()
public val X_KEY: Name = "x".asName()
public val Y_KEY: Name = "y".asName()
public val Z_KEY: Name = "z".asName()
val POSITION_KEY = "pos".asName()
public val POSITION_KEY: Name = "pos".asName()
val X_POSITION_KEY = POSITION_KEY + X_KEY
val Y_POSITION_KEY = POSITION_KEY + Y_KEY
val Z_POSITION_KEY = POSITION_KEY + Z_KEY
public val X_POSITION_KEY: Name = POSITION_KEY + X_KEY
public val Y_POSITION_KEY: Name = POSITION_KEY + Y_KEY
public val Z_POSITION_KEY: Name = POSITION_KEY + Z_KEY
val ROTATION = "rotation".asName()
public val ROTATION: Name = "rotation".asName()
val X_ROTATION_KEY = ROTATION + X_KEY
val Y_ROTATION_KEY = ROTATION + Y_KEY
val Z_ROTATION_KEY = ROTATION + Z_KEY
public val X_ROTATION_KEY: Name = ROTATION + X_KEY
public val Y_ROTATION_KEY: Name = ROTATION + Y_KEY
public val Z_ROTATION_KEY: Name = ROTATION + Z_KEY
val ROTATION_ORDER_KEY = ROTATION + "order"
public val ROTATION_ORDER_KEY: Name = ROTATION + "order"
val SCALE_KEY = "scale".asName()
public val SCALE_KEY: Name = "scale".asName()
val X_SCALE_KEY = SCALE_KEY + X_KEY
val Y_SCALE_KEY = SCALE_KEY + Y_KEY
val Z_SCALE_KEY = SCALE_KEY + Z_KEY
public val X_SCALE_KEY: Name = SCALE_KEY + X_KEY
public val Y_SCALE_KEY: Name = SCALE_KEY + Y_KEY
public val Z_SCALE_KEY: Name = SCALE_KEY + Z_KEY
val descriptor by lazy {
public val descriptor: NodeDescriptor by lazy {
NodeDescriptor {
value(VISIBLE_KEY) {
type(ValueType.BOOLEAN)
@ -100,20 +98,20 @@ interface Solid : Vision {
}
/**
* Count number of layers to the top object. Return 1 if this is top layer
* Get the layer number this solid belongs to. Return 0 if layer is not defined.
*/
var Solid.layer: Int
public var Solid.layer: Int
get() = properties?.getItem(LAYER_KEY).int ?: 0
set(value) {
config[LAYER_KEY] = value.asValue()
}
fun Renderer<Solid>.render(meta: Meta = Meta.EMPTY, action: SolidGroup.() -> Unit) =
public fun Renderer<Solid>.render(meta: Meta = Meta.EMPTY, action: SolidGroup.() -> Unit): Unit =
render(SolidGroup().apply(action), meta)
// Common properties
enum class RotationOrder {
public enum class RotationOrder {
XYZ,
YZX,
ZXY,
@ -125,7 +123,7 @@ enum class RotationOrder {
/**
* Rotation order
*/
var Solid.rotationOrder: RotationOrder
public var Solid.rotationOrder: RotationOrder
get() = getItem(Solid.ROTATION_ORDER_KEY).enum<RotationOrder>() ?: RotationOrder.XYZ
set(value) = setItem(Solid.ROTATION_ORDER_KEY, value.name.asValue())
@ -133,19 +131,15 @@ var Solid.rotationOrder: RotationOrder
/**
* Preferred number of polygons for displaying the object. If not defined, uses shape or renderer default. Not inherited
*/
var Solid.detail: Int?
public var Solid.detail: Int?
get() = getProperty(DETAIL_KEY, false).int
set(value) = setItem(DETAIL_KEY, value?.asValue())
var Vision.visible: Boolean?
get() = getItem(VISIBLE_KEY).boolean
set(value) = setItem(VISIBLE_KEY, value?.asValue())
/**
* If this property is true, the object will be ignored on render.
* Property is not inherited.
*/
var Vision.ignore: Boolean?
public var Vision.ignore: Boolean?
get() = getProperty(IGNORE_KEY, false).boolean
set(value) = setItem(IGNORE_KEY, value?.asValue())
@ -156,21 +150,21 @@ var Vision.ignore: Boolean?
private fun Solid.position(): Point3D =
position ?: Point3D(0.0, 0.0, 0.0).also { position = it }
var Solid.x: Number
public var Solid.x: Number
get() = position?.x ?: 0f
set(value) {
position().x = value.toDouble()
propertyChanged(Solid.X_POSITION_KEY)
}
var Solid.y: Number
public var Solid.y: Number
get() = position?.y ?: 0f
set(value) {
position().y = value.toDouble()
propertyChanged(Solid.Y_POSITION_KEY)
}
var Solid.z: Number
public var Solid.z: Number
get() = position?.z ?: 0f
set(value) {
position().z = value.toDouble()
@ -180,21 +174,21 @@ var Solid.z: Number
private fun Solid.rotation(): Point3D =
rotation ?: Point3D(0.0, 0.0, 0.0).also { rotation = it }
var Solid.rotationX: Number
public var Solid.rotationX: Number
get() = rotation?.x ?: 0f
set(value) {
rotation().x = value.toDouble()
propertyChanged(Solid.X_ROTATION_KEY)
}
var Solid.rotationY: Number
public var Solid.rotationY: Number
get() = rotation?.y ?: 0f
set(value) {
rotation().y = value.toDouble()
propertyChanged(Solid.Y_ROTATION_KEY)
}
var Solid.rotationZ: Number
public var Solid.rotationZ: Number
get() = rotation?.z ?: 0f
set(value) {
rotation().z = value.toDouble()
@ -204,21 +198,21 @@ var Solid.rotationZ: Number
private fun Solid.scale(): Point3D =
scale ?: Point3D(1.0, 1.0, 1.0).also { scale = it }
var Solid.scaleX: Number
public var Solid.scaleX: Number
get() = scale?.x ?: 1f
set(value) {
scale().x = value.toDouble()
propertyChanged(Solid.X_SCALE_KEY)
}
var Solid.scaleY: Number
public var Solid.scaleY: Number
get() = scale?.y ?: 1f
set(value) {
scale().y = value.toDouble()
propertyChanged(Solid.Y_SCALE_KEY)
}
var Solid.scaleZ: Number
public var Solid.scaleZ: Number
get() = scale?.z ?: 1f
set(value) {
scale().z = value.toDouble()

View File

@ -15,9 +15,9 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers
import kotlin.collections.set
interface PrototypeHolder {
val parent: VisionGroup?
val prototypes: MutableVisionGroup?
public interface PrototypeHolder {
public val parent: VisionGroup?
public val prototypes: MutableVisionGroup?
}
/**
@ -25,7 +25,7 @@ interface PrototypeHolder {
*/
@Serializable
@SerialName("group.solid")
class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder {
public class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder {
override var styleSheet: StyleSheet? = null
@ -39,7 +39,7 @@ class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder {
/**
* Create or edit prototype node as a group
*/
fun prototypes(builder: MutableVisionGroup.() -> Unit): Unit {
public fun prototypes(builder: MutableVisionGroup.() -> Unit): Unit {
(prototypes ?: Prototypes().also {
prototypes = it
attach(it)
@ -79,33 +79,33 @@ class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder {
override fun createGroup(): SolidGroup = SolidGroup()
companion object {
public companion object {
// val PROTOTYPES_KEY = NameToken("@prototypes")
@OptIn(DFExperimental::class)
fun parseJson(json: String): SolidGroup =
SolidManager.jsonForSolids.parse(serializer(), json).also { it.attachChildren() }
public fun decodeFromString(json: String): SolidGroup =
SolidManager.jsonForSolids.decodeFromString(serializer(), json).also { it.attachChildren() }
}
}
@Suppress("FunctionName")
fun SolidGroup(block: SolidGroup.() -> Unit): SolidGroup {
public fun SolidGroup(block: SolidGroup.() -> Unit): SolidGroup {
return SolidGroup().apply(block)
}
/**
* Ger a prototype redirecting the request to the parent if prototype is not found
*/
tailrec fun PrototypeHolder.getPrototype(name: Name): Solid? =
public tailrec fun PrototypeHolder.getPrototype(name: Name): Solid? =
prototypes?.get(name) as? Solid ?: (parent as? PrototypeHolder)?.getPrototype(name)
fun MutableVisionGroup.group(name: Name = Name.EMPTY, action: SolidGroup.() -> Unit = {}): SolidGroup =
public fun MutableVisionGroup.group(name: Name = Name.EMPTY, action: SolidGroup.() -> Unit = {}): SolidGroup =
SolidGroup().apply(action).also { set(name, it) }
/**
* Define a group with given [name], attach it to this parent and return it.
*/
fun MutableVisionGroup.group(name: String, action: SolidGroup.() -> Unit = {}): SolidGroup =
public fun MutableVisionGroup.group(name: String, action: SolidGroup.() -> Unit = {}): SolidGroup =
SolidGroup().apply(action).also { set(name, it) }
/**

View File

@ -5,6 +5,7 @@ package hep.dataforge.vision.solid
import hep.dataforge.meta.Config
import hep.dataforge.vision.AbstractVision
import hep.dataforge.vision.MutableVisionGroup
import hep.dataforge.vision.VisionContainerBuilder
import hep.dataforge.vision.set
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@ -12,7 +13,7 @@ import kotlinx.serialization.UseSerializers
@Serializable
@SerialName("solid.label")
class SolidLabel(var text: String, var fontSize: Double, var fontFamily: String) : AbstractVision(), Solid {
public class SolidLabel(public var text: String, public var fontSize: Double, public var fontFamily: String) : AbstractVision(), Solid {
override var properties: Config? = null
override var position: Point3D? = null
@ -21,11 +22,10 @@ class SolidLabel(var text: String, var fontSize: Double, var fontFamily: String)
}
fun MutableVisionGroup.label(
public fun VisionContainerBuilder<Solid>.label(
text: String,
fontSize: Number = 20,
fontFamily: String = "Arial",
name: String = "",
action: SolidLabel.() -> Unit = {}
) =
SolidLabel(text, fontSize.toDouble(), fontFamily).apply(action).also { set(name, it) }
action: SolidLabel.() -> Unit = {},
): SolidLabel = SolidLabel(text, fontSize.toDouble(), fontFamily).apply(action).also { set(name, it) }

View File

@ -12,20 +12,17 @@ import hep.dataforge.vision.Vision
import hep.dataforge.vision.VisionForm
import hep.dataforge.vision.VisionManager
import hep.dataforge.vision.VisionManager.Companion.VISION_SERIAL_MODULE_TARGET
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.UnstableDefault
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.modules.SerialModule
import kotlinx.serialization.modules.SerialModuleCollector
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.contextual
import kotlinx.serialization.modules.*
import kotlin.reflect.KClass
@DFExperimental
private class SolidForm<T :Solid>(
private class SolidForm<T : Solid>(
override val type: KClass<T>,
override val serializer: KSerializer<T>
override val serializer: KSerializer<T>,
) : VisionForm<T> {
private fun Solid.update(meta: Meta) {
@ -46,12 +43,12 @@ private class SolidForm<T :Solid>(
}
}
@OptIn(ExperimentalSerializationApi::class)
@DFExperimental
@OptIn(UnstableDefault::class)
private fun SerialModule.extractFactories(): List<SolidForm<*>> {
private fun SerializersModule.extractFactories(): List<SolidForm<*>> {
val list = ArrayList<SolidForm<*>>()
val collector = object : SerialModuleCollector {
val collector = object : SerializersModuleCollector {
override fun <T : Any> contextual(kClass: KClass<T>, serializer: KSerializer<T>) {
//Do nothing
}
@ -59,7 +56,7 @@ private fun SerialModule.extractFactories(): List<SolidForm<*>> {
override fun <Base : Any, Sub : Base> polymorphic(
baseClass: KClass<Base>,
actualClass: KClass<Sub>,
actualSerializer: KSerializer<Sub>
actualSerializer: KSerializer<Sub>,
) {
if (baseClass == Vision::class) {
@Suppress("UNCHECKED_CAST") val factory = SolidForm<Solid>(
@ -70,34 +67,41 @@ private fun SerialModule.extractFactories(): List<SolidForm<*>> {
}
}
override fun <Base : Any> polymorphicDefault(
baseClass: KClass<Base>,
defaultSerializerProvider: (className: String?) -> DeserializationStrategy<out Base>?,
) {
TODO("Not yet implemented")
}
}
dumpTo(collector)
return list
}
@DFExperimental
class SolidManager(meta: Meta) : AbstractPlugin(meta) {
public class SolidManager(meta: Meta) : AbstractPlugin(meta) {
val visionManager by require(VisionManager)
public val visionManager: VisionManager by require(VisionManager)
override val tag: PluginTag get() = Companion.tag
override fun provideTop(target: String): Map<Name, Any> = when (target) {
override fun content(target: String): Map<Name, Any> = when (target) {
VisionForm.TYPE -> serialModule.extractFactories().associateBy { it.name }
VISION_SERIAL_MODULE_TARGET -> mapOf(tag.name.toName() to serialModule)
else -> super.provideTop(target)
else -> super.content(target)
}
companion object : PluginFactory<SolidManager> {
public companion object : PluginFactory<SolidManager> {
override val tag: PluginTag = PluginTag(name = "visual.spatial", group = PluginTag.DATAFORGE_GROUP)
override val type: KClass<out SolidManager> = SolidManager::class
override fun invoke(meta: Meta, context: Context): SolidManager = SolidManager(meta)
val serialModule = SerializersModule {
public val serialModule: SerializersModule = SerializersModule {
contextual(Point3DSerializer)
contextual(Point2DSerializer)
polymorphic(Vision::class, Solid::class) {
polymorphic(Vision::class) {
subclass(SimpleVisionGroup.serializer())
subclass(SolidGroup.serializer())
subclass(Proxy.serializer())
@ -112,15 +116,12 @@ class SolidManager(meta: Meta) : AbstractPlugin(meta) {
}
}
@OptIn(UnstableDefault::class)
val jsonForSolids = Json(
JsonConfiguration(
prettyPrint = true,
useArrayPolymorphism = false,
encodeDefaults = false,
ignoreUnknownKeys = true
),
context = serialModule
)
val jsonForSolids = Json {
prettyPrint = true
useArrayPolymorphism = false
encodeDefaults = false
ignoreUnknownKeys = true
serializersModule = this@Companion.serialModule
}
}
}

View File

@ -3,6 +3,7 @@ package hep.dataforge.vision.solid
import hep.dataforge.meta.*
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.meta.descriptors.attributes
import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.names.plus
import hep.dataforge.values.ValueType
@ -13,41 +14,41 @@ import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_KEY
import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_OPACITY_KEY
import hep.dataforge.vision.widgetType
class SolidMaterial : Scheme() {
public class SolidMaterial : Scheme() {
/**
* Primary web-color for the material
*/
var color by string(key = COLOR_KEY)
public var color: String? by string(key = COLOR_KEY)
/**
* Specular color for phong material
*/
var specularColor by string(key = SPECULAR_COLOR_KEY)
public var specularColor: String? by string(key = SPECULAR_COLOR_KEY)
/**
* Opacity
*/
var opacity by float(1f, key = OPACITY_KEY)
public var opacity: Float by float(1f, key = OPACITY_KEY)
/**
* Replace material by wire frame
*/
var wireframe by boolean(false, WIREFRAME_KEY)
public var wireframe: Boolean by boolean(false, WIREFRAME_KEY)
companion object : SchemeSpec<SolidMaterial>(::SolidMaterial) {
public companion object : SchemeSpec<SolidMaterial>(::SolidMaterial) {
val MATERIAL_KEY = "material".asName()
public val MATERIAL_KEY: Name = "material".asName()
internal val COLOR_KEY = "color".asName()
val MATERIAL_COLOR_KEY = MATERIAL_KEY + COLOR_KEY
public val MATERIAL_COLOR_KEY: Name = MATERIAL_KEY + COLOR_KEY
internal val SPECULAR_COLOR_KEY = "specularColor".asName()
val MATERIAL_SPECULAR_COLOR_KEY = MATERIAL_KEY + SPECULAR_COLOR_KEY
public val MATERIAL_SPECULAR_COLOR_KEY: Name = MATERIAL_KEY + SPECULAR_COLOR_KEY
internal val OPACITY_KEY = "opacity".asName()
val MATERIAL_OPACITY_KEY = MATERIAL_KEY + OPACITY_KEY
public val MATERIAL_OPACITY_KEY: Name = MATERIAL_KEY + OPACITY_KEY
internal val WIREFRAME_KEY = "wireframe".asName()
val MATERIAL_WIREFRAME_KEY = MATERIAL_KEY + WIREFRAME_KEY
public val MATERIAL_WIREFRAME_KEY: Name = MATERIAL_KEY + WIREFRAME_KEY
val descriptor by lazy {
public val descriptor: NodeDescriptor by lazy {
//must be lazy to avoid initialization bug
NodeDescriptor {
value(COLOR_KEY) {
@ -77,18 +78,18 @@ class SolidMaterial : Scheme() {
/**
* Set color as web-color
*/
fun Solid.color(webColor: String) {
public fun Solid.color(webColor: String) {
setItem(MATERIAL_COLOR_KEY, webColor.asValue())
}
/**
* Set color as integer
*/
fun Solid.color(rgb: Int) {
public fun Solid.color(rgb: Int) {
setItem(MATERIAL_COLOR_KEY, rgb.asValue())
}
fun Solid.color(r: UByte, g: UByte, b: UByte) = setItem(
public fun Solid.color(r: UByte, g: UByte, b: UByte): Unit = setItem(
MATERIAL_COLOR_KEY,
Colors.rgbToMeta(r, g, b)
)
@ -96,16 +97,16 @@ fun Solid.color(r: UByte, g: UByte, b: UByte) = setItem(
/**
* Web colors representation of the color in `#rrggbb` format or HTML name
*/
var Solid.color: String?
public var Solid.color: String?
get() = getItem(MATERIAL_COLOR_KEY)?.let { Colors.fromMeta(it) }
set(value) {
setItem(MATERIAL_COLOR_KEY, value?.asValue())
}
val Solid.material: SolidMaterial?
public val Solid.material: SolidMaterial?
get() = getItem(MATERIAL_KEY).node?.let { SolidMaterial.wrap(it) }
fun Solid.material(builder: SolidMaterial.() -> Unit) {
public fun Solid.material(builder: SolidMaterial.() -> Unit) {
val node = config[MATERIAL_KEY].node
if (node != null) {
SolidMaterial.update(node, builder)
@ -114,7 +115,7 @@ fun Solid.material(builder: SolidMaterial.() -> Unit) {
}
}
var Solid.opacity: Double?
public var Solid.opacity: Double?
get() = getItem(MATERIAL_OPACITY_KEY).double
set(value) {
setItem(MATERIAL_OPACITY_KEY, value?.asValue())

View File

@ -5,6 +5,7 @@ package hep.dataforge.vision.solid
import hep.dataforge.meta.Config
import hep.dataforge.vision.AbstractVision
import hep.dataforge.vision.MutableVisionGroup
import hep.dataforge.vision.VisionContainerBuilder
import hep.dataforge.vision.set
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@ -15,12 +16,12 @@ import kotlin.math.sin
@Serializable
@SerialName("solid.sphere")
class Sphere(
var radius: Float,
var phiStart: Float = 0f,
var phi: Float = PI2,
var thetaStart: Float = 0f,
var theta: Float = PI.toFloat()
public class Sphere(
public var radius: Float,
public var phiStart: Float = 0f,
public var phi: Float = PI2,
public var thetaStart: Float = 0f,
public var theta: Float = PI.toFloat()
) : AbstractVision(), GeometrySolid {
override var properties: Config? = null
@ -60,13 +61,13 @@ class Sphere(
}
}
inline fun MutableVisionGroup.sphere(
public inline fun VisionContainerBuilder<Solid>.sphere(
radius: Number,
phi: Number = 2 * PI,
theta: Number = PI,
name: String = "",
action: Sphere.() -> Unit = {}
) = Sphere(
): Sphere = Sphere(
radius.toFloat(),
phi = phi.toFloat(),
theta = theta.toFloat()

View File

@ -5,6 +5,7 @@ package hep.dataforge.vision.solid
import hep.dataforge.meta.Config
import hep.dataforge.vision.AbstractVision
import hep.dataforge.vision.MutableVisionGroup
import hep.dataforge.vision.VisionContainerBuilder
import hep.dataforge.vision.set
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@ -18,12 +19,12 @@ import kotlin.math.sin
*/
@Serializable
@SerialName("solid.tube")
class Tube(
var radius: Float,
var height: Float,
var innerRadius: Float = 0f,
var startAngle: Float = 0f,
var angle: Float = PI2
public class Tube(
public var radius: Float,
public var height: Float,
public var innerRadius: Float = 0f,
public var startAngle: Float = 0f,
public var angle: Float = PI2
) : AbstractVision(), GeometrySolid {
override var position: Point3D? = null
@ -129,7 +130,7 @@ class Tube(
}
inline fun MutableVisionGroup.tube(
public inline fun VisionContainerBuilder<Solid>.tube(
r: Number,
height: Number,
innerRadius: Number = 0f,

View File

@ -1,47 +1,48 @@
package hep.dataforge.vision.solid
import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaBuilder
import hep.dataforge.meta.get
import hep.dataforge.meta.number
import kotlin.math.PI
object World {
val ZERO = Point3D(0.0, 0.0, 0.0)
val ONE = Point3D(1.0, 1.0, 1.0)
public object World {
public val ZERO: Point3D = Point3D(0.0, 0.0, 0.0)
public val ONE: Point3D = Point3D(1.0, 1.0, 1.0)
}
const val PI2: Float = 2 * PI.toFloat()
public const val PI2: Float = 2 * PI.toFloat()
expect class Point2D(x: Number, y: Number) {
var x: Double
var y: Double
public expect class Point2D(x: Number, y: Number) {
public var x: Double
public var y: Double
}
operator fun Point2D.component1() = x
operator fun Point2D.component2() = y
public operator fun Point2D.component1(): Double = x
public operator fun Point2D.component2(): Double = y
fun Point2D.toMeta() = Meta {
public fun Point2D.toMeta(): Meta = Meta {
Solid.X_KEY put x
Solid.Y_KEY put y
}
fun Meta.point2D() = Point2D(this["x"].number ?: 0, this["y"].number ?: 0)
internal fun Meta.point2D(): Point2D = Point2D(this["x"].number ?: 0, this["y"].number ?: 0)
expect class Point3D(x: Number, y: Number, z: Number) {
var x: Double
var y: Double
var z: Double
public expect class Point3D(x: Number, y: Number, z: Number) {
public var x: Double
public var y: Double
public var z: Double
}
expect operator fun Point3D.plus(other: Point3D): Point3D
public expect operator fun Point3D.plus(other: Point3D): Point3D
operator fun Point3D.component1() = x
operator fun Point3D.component2() = y
operator fun Point3D.component3() = z
public operator fun Point3D.component1(): Double = x
public operator fun Point3D.component2(): Double = y
public operator fun Point3D.component3(): Double = z
fun Meta.point3D() = Point3D(this["x"].number ?: 0, this["y"].number ?: 0, this["y"].number ?: 0)
internal fun Meta.point3D() = Point3D(this["x"].number ?: 0, this["y"].number ?: 0, this["y"].number ?: 0)
fun Point3D.toMeta() = Meta {
public fun Point3D.toMeta(): MetaBuilder = Meta {
Solid.X_KEY put x
Solid.Y_KEY put y
Solid.Z_KEY put z

View File

@ -2,6 +2,7 @@ package hep.dataforge.vision.solid
import hep.dataforge.meta.DFExperimental
import hep.dataforge.meta.double
import hep.dataforge.meta.transformations.MetaConverter.Companion.double
import hep.dataforge.names.NameToken
import hep.dataforge.vision.MutableVisionGroup
import hep.dataforge.vision.Vision
@ -10,34 +11,19 @@ import kotlinx.serialization.*
import kotlinx.serialization.builtins.MapSerializer
import kotlinx.serialization.builtins.nullable
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
import kotlinx.serialization.descriptors.element
import kotlinx.serialization.encoding.*
inline fun <R> Decoder.decodeStructure(
desc: SerialDescriptor,
vararg typeParams: KSerializer<*> = emptyArray(),
crossinline block: CompositeDecoder.() -> R
): R {
val decoder = beginStructure(desc, *typeParams)
val res = decoder.block()
decoder.endStructure(desc)
return res
}
inline fun Encoder.encodeStructure(
desc: SerialDescriptor,
vararg typeParams: KSerializer<*> = emptyArray(),
block: CompositeEncoder.() -> Unit
) {
val encoder = beginStructure(desc, *typeParams)
encoder.block()
encoder.endStructure(desc)
}
@OptIn(ExperimentalSerializationApi::class)
@Serializer(Point3D::class)
object Point3DSerializer : KSerializer<Point3D> {
override val descriptor: SerialDescriptor = SerialDescriptor("hep.dataforge.vis.spatial.Point3D") {
double("x", true)
double("y", true)
double("z", true)
public object Point3DSerializer : KSerializer<Point3D> {
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("hep.dataforge.vis.spatial.Point3D") {
element<Double>("x")
element<Double>("y")
element<Double>("z")
}
override fun deserialize(decoder: Decoder): Point3D {
@ -47,7 +33,7 @@ object Point3DSerializer : KSerializer<Point3D> {
decoder.decodeStructure(descriptor) {
loop@ while (true) {
when (val i = decodeElementIndex(descriptor)) {
CompositeDecoder.READ_DONE -> break@loop
CompositeDecoder.DECODE_DONE -> break@loop
0 -> x = decodeNullableSerializableElement(descriptor, 0, Double.serializer().nullable) ?: 0.0
1 -> y = decodeNullableSerializableElement(descriptor, 1, Double.serializer().nullable) ?: 0.0
2 -> z = decodeNullableSerializableElement(descriptor, 2, Double.serializer().nullable) ?: 0.0
@ -67,11 +53,12 @@ object Point3DSerializer : KSerializer<Point3D> {
}
}
@OptIn(ExperimentalSerializationApi::class)
@Serializer(Point2D::class)
object Point2DSerializer : KSerializer<Point2D> {
override val descriptor: SerialDescriptor = SerialDescriptor("hep.dataforge.vis.spatial.Point2D") {
double("x", true)
double("y", true)
public object Point2DSerializer : KSerializer<Point2D> {
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("hep.dataforge.vis.spatial.Point2D") {
element<Double>("x")
element<Double>("y")
}
override fun deserialize(decoder: Decoder): Point2D {
@ -80,7 +67,7 @@ object Point2DSerializer : KSerializer<Point2D> {
decoder.decodeStructure(descriptor) {
loop@ while (true) {
when (val i = decodeElementIndex(descriptor)) {
CompositeDecoder.READ_DONE -> break@loop
CompositeDecoder.DECODE_DONE -> break@loop
0 -> x = decodeNullableSerializableElement(descriptor, 0, Double.serializer().nullable) ?: 0.0
1 -> y = decodeNullableSerializableElement(descriptor, 1, Double.serializer().nullable) ?: 0.0
else -> throw SerializationException("Unknown index $i")
@ -98,6 +85,7 @@ object Point2DSerializer : KSerializer<Point2D> {
}
}
@OptIn(ExperimentalSerializationApi::class)
@Serializer(MutableVisionGroup::class)
internal object PrototypesSerializer : KSerializer<MutableVisionGroup> {
@ -120,10 +108,10 @@ internal object PrototypesSerializer : KSerializer<MutableVisionGroup> {
}
@OptIn(DFExperimental::class)
fun Vision.stringify(): String = SolidManager.jsonForSolids.stringify(Vision.serializer(), this)
public fun Vision.encodeToString(): String = SolidManager.jsonForSolids.encodeToString(Vision.serializer(), this)
@OptIn(DFExperimental::class)
fun Vision.Companion.parseJson(str: String) = SolidManager.jsonForSolids.parse(serializer(), str).also {
public fun Vision.Companion.decodeFromString(str: String): Vision = SolidManager.jsonForSolids.decodeFromString(serializer(), str).also {
if(it is VisionGroup){
it.attachChildren()
}

View File

@ -2,13 +2,13 @@ package hep.dataforge.vision.solid.specifications
import hep.dataforge.meta.*
class Axes : Scheme() {
var visible by boolean(!config.isEmpty())
var size by double(AXIS_SIZE)
var width by double(AXIS_WIDTH)
public class Axes : Scheme() {
public var visible: Boolean by boolean(!config.isEmpty())
public var size: Double by double(AXIS_SIZE)
public var width: Double by double(AXIS_WIDTH)
companion object : SchemeSpec<Axes>(::Axes) {
const val AXIS_SIZE = 1000.0
const val AXIS_WIDTH = 3.0
public companion object : SchemeSpec<Axes>(::Axes) {
public const val AXIS_SIZE: Double = 1000.0
public const val AXIS_WIDTH: Double = 3.0
}
}

View File

@ -6,24 +6,24 @@ import hep.dataforge.meta.double
import hep.dataforge.meta.int
import kotlin.math.PI
class Camera : Scheme() {
var fov by int(FIELD_OF_VIEW)
public class Camera : Scheme() {
public var fov: Int by int(FIELD_OF_VIEW)
//var aspect by double(1.0)
var nearClip by double(NEAR_CLIP)
var farClip by double(FAR_CLIP)
public var nearClip: Double by double(NEAR_CLIP)
public var farClip: Double by double(FAR_CLIP)
var distance by double(INITIAL_DISTANCE)
var azimuth by double(INITIAL_AZIMUTH)
var latitude by double(INITIAL_LATITUDE)
val zenith: Double get() = PI / 2 - latitude
public var distance: Double by double(INITIAL_DISTANCE)
public var azimuth: Double by double(INITIAL_AZIMUTH)
public var latitude: Double by double(INITIAL_LATITUDE)
public val zenith: Double get() = PI / 2 - latitude
companion object : SchemeSpec<Camera>(::Camera) {
const val INITIAL_DISTANCE = 300.0
const val INITIAL_AZIMUTH = 0.0
const val INITIAL_LATITUDE = PI / 6
const val NEAR_CLIP = 0.1
const val FAR_CLIP = 10000.0
const val FIELD_OF_VIEW = 75
public companion object : SchemeSpec<Camera>(::Camera) {
public const val INITIAL_DISTANCE: Double = 300.0
public const val INITIAL_AZIMUTH: Double = 0.0
public const val INITIAL_LATITUDE: Double = PI / 6
public const val NEAR_CLIP: Double = 0.1
public const val FAR_CLIP: Double = 10000.0
public const val FIELD_OF_VIEW: Int = 75
}
}

View File

@ -5,11 +5,11 @@ import hep.dataforge.meta.SchemeSpec
import hep.dataforge.meta.int
import hep.dataforge.meta.spec
class Canvas3DOptions : Scheme() {
var axes by spec(Axes, Axes.empty())
var camera by spec(Camera, Camera.empty())
var controls by spec(Controls, Controls.empty())
var minSize by int(300)
public class Canvas3DOptions : Scheme() {
public var axes: Axes by spec(Axes, Axes.empty())
public var camera: Camera by spec(Camera, Camera.empty())
public var controls: Controls by spec(Controls, Controls.empty())
public var minSize: Int by int(300)
companion object : SchemeSpec<Canvas3DOptions>(::Canvas3DOptions)
public companion object : SchemeSpec<Canvas3DOptions>(::Canvas3DOptions)
}

View File

@ -1,5 +1,6 @@
package hep.dataforge.vision.solid.transform
import hep.dataforge.meta.DFExperimental
import hep.dataforge.meta.update
import hep.dataforge.names.asName
import hep.dataforge.vision.MutableVisionGroup
@ -7,6 +8,7 @@ import hep.dataforge.vision.Vision
import hep.dataforge.vision.VisionGroup
import hep.dataforge.vision.solid.*
@DFExperimental
internal fun mergeChild(parent: VisionGroup, child: Vision): Vision {
return child.apply {
@ -32,6 +34,7 @@ internal fun mergeChild(parent: VisionGroup, child: Vision): Vision {
}
}
@DFExperimental
object RemoveSingleChild : VisualTreeTransform<SolidGroup>() {
override fun SolidGroup.transformInPlace() {

View File

@ -1,5 +1,6 @@
package hep.dataforge.vision.solid.transform
import hep.dataforge.meta.DFExperimental
import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.vision.MutableVisionGroup
@ -7,6 +8,7 @@ import hep.dataforge.vision.VisionGroup
import hep.dataforge.vision.solid.Proxy
import hep.dataforge.vision.solid.SolidGroup
@DFExperimental
object UnRef : VisualTreeTransform<SolidGroup>() {
private fun VisionGroup.countRefs(): Map<Name, Int> {
return children.values.fold(HashMap()) { reducer, obj ->

View File

@ -1,6 +1,7 @@
package hep.dataforge.vision.solid
import hep.dataforge.meta.*
import kotlinx.serialization.json.toJson
import kotlin.test.Test
import kotlin.test.assertEquals
@ -24,7 +25,7 @@ class ConvexTest {
val convex = group.children.values.first() as Convex
val json = SolidManager.jsonForSolids.toJson(Convex.serializer(), convex)
val json = SolidManager.jsonForSolids.encodeToJsonElement(Convex.serializer(), convex)
val meta = json.toMetaItem().node!!
val points = meta.getIndexed("points").values.map { (it as MetaItem.NodeItem<*>).node.point3D() }

View File

@ -1,11 +1,26 @@
package hep.dataforge.vision.solid
import hep.dataforge.names.Name
import hep.dataforge.names.toName
import hep.dataforge.vision.MutableVisionGroup
import hep.dataforge.vision.Vision
import hep.dataforge.vision.get
import kotlin.test.Test
import kotlin.test.assertEquals
/**
* Create and attach new proxied group
*/
fun SolidGroup.proxyGroup(
name: String,
templateName: Name = name.toName(),
block: MutableVisionGroup.() -> Unit
): Proxy {
val group = SolidGroup().apply(block)
return proxy(name, group, templateName)
}
class SerializationTest {
@Test
fun testCubeSerialization() {
@ -14,9 +29,9 @@ class SerializationTest {
x = 100
z = -100
}
val string = cube.stringify()
val string = cube.encodeToString()
println(string)
val newCube = Vision.parseJson(string)
val newCube = Vision.decodeFromString(string)
assertEquals(cube.config, newCube.config)
}
@ -35,9 +50,9 @@ class SerializationTest {
}
}
}
val string = group.stringify()
val string = group.encodeToString()
println(string)
val reconstructed = SolidGroup.parseJson(string)
val reconstructed = SolidGroup.decodeFromString(string)
assertEquals(group["cube"]?.config, reconstructed["cube"]?.config)
}

View File

@ -5,10 +5,10 @@ import info.laht.threekt.math.Vector2
import info.laht.threekt.math.Vector3
import info.laht.threekt.math.plus
actual typealias Point2D = Vector2
public actual typealias Point2D = Vector2
actual typealias Point3D = Vector3
public actual typealias Point3D = Vector3
actual operator fun Point3D.plus(other: Point3D): Point3D {
public actual operator fun Point3D.plus(other: Point3D): Point3D {
return this.plus(other)
}

View File

@ -8,6 +8,7 @@ import hep.dataforge.vision.solid.*
import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_KEY
import hep.dataforge.vision.solid.three.ThreeFactory.Companion.TYPE
import hep.dataforge.vision.solid.three.ThreeMaterials.getMaterial
import hep.dataforge.vision.visible
import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Object3D
import info.laht.threekt.objects.Mesh
@ -54,7 +55,7 @@ fun Object3D.updateProperty(source: Vision, propertyName: Name) {
) {
//update position of mesh using this object
updatePosition(source)
} else if (propertyName == Solid.VISIBLE_KEY) {
} else if (propertyName == Vision.VISIBLE_KEY) {
visible = source.visible ?: true
}
}

View File

@ -5,6 +5,7 @@ import hep.dataforge.meta.Meta
import hep.dataforge.names.*
import hep.dataforge.vision.Vision
import hep.dataforge.vision.solid.*
import hep.dataforge.vision.visible
import info.laht.threekt.core.Object3D
import kotlin.collections.set
import kotlin.reflect.KClass
@ -30,7 +31,7 @@ class ThreePlugin : AbstractPlugin() {
@Suppress("UNCHECKED_CAST")
private fun findObjectFactory(type: KClass<out Vision>): ThreeFactory<Solid>? {
return (objectFactories[type]
?: context.content<ThreeFactory<*>>(ThreeFactory.TYPE).values.find { it.type == type })
?: context.gather<ThreeFactory<*>>(ThreeFactory.TYPE).values.find { it.type == type })
as ThreeFactory<Solid>?
}
@ -63,7 +64,7 @@ class ThreePlugin : AbstractPlugin() {
) {
//update position of mesh using this object
updatePosition(obj)
} else if (name == Solid.VISIBLE_KEY) {
} else if (name == Vision.VISIBLE_KEY) {
visible = obj.visible ?: true
}
}
@ -123,28 +124,28 @@ internal fun Object3D.getOrCreateGroup(name: Name): Object3D {
return when {
name.isEmpty() -> this
name.length == 1 -> {
val token = name.first()!!
val token = name.tokens.first()
children.find { it.name == token.toString() } ?: info.laht.threekt.objects.Group().also { group ->
group.name = token.toString()
this.add(group)
}
}
else -> getOrCreateGroup(name.first()!!.asName()).getOrCreateGroup(name.cutFirst())
else -> getOrCreateGroup(name.tokens.first().asName()).getOrCreateGroup(name.cutFirst())
}
}
internal operator fun Object3D.set(name: Name, obj: Object3D) {
when (name.length) {
0 -> error("Can't set object with an empty name")
1 -> set(name.first()!!, obj)
else -> getOrCreateGroup(name.cutLast())[name.last()!!] = obj
1 -> set(name.tokens.first(), obj)
else -> getOrCreateGroup(name.cutLast())[name.tokens.last()] = obj
}
}
internal fun Object3D.findChild(name: Name): Object3D? {
return when {
name.isEmpty() -> this
name.length == 1 -> this.children.find { it.name == name.first()!!.toString() }
else -> findChild(name.first()!!.asName())?.findChild(name.cutFirst())
name.length == 1 -> this.children.find { it.name == name.tokens.first().toString() }
else -> findChild(name.tokens.first().asName())?.findChild(name.cutFirst())
}
}

View File

@ -1,5 +1,7 @@
package hep.dataforge.vision.solid.three
import hep.dataforge.names.cutFirst
import hep.dataforge.names.firstOrNull
import hep.dataforge.names.toName
import hep.dataforge.vision.solid.Proxy
import hep.dataforge.vision.solid.Proxy.Companion.PROXY_CHILD_PROPERTY_PREFIX
@ -42,8 +44,8 @@ class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory<Proxy> {
}
obj.onPropertyChange(this) { name ->
if (name.first()?.body == PROXY_CHILD_PROPERTY_PREFIX) {
val childName = name.first()?.index?.toName() ?: error("Wrong syntax for proxy child property: '$name'")
if (name.firstOrNull()?.body == PROXY_CHILD_PROPERTY_PREFIX) {
val childName = name.firstOrNull()?.index?.toName() ?: error("Wrong syntax for proxy child property: '$name'")
val propertyName = name.cutFirst()
val proxyChild = obj[childName] ?: error("Proxy child with name '$childName' not found")
val child = object3D.findChild(childName) ?: error("Object child with name '$childName' not found")

View File

@ -38,7 +38,7 @@ fun RBuilder.canvasControls(canvas: ThreeCanvas) = accordion("controls") {
div("row") {
div("col-2") {
label("checkbox-inline") {
input(type = InputType.checkBox){
input(type = InputType.checkBox) {
attrs {
defaultChecked = canvas.axes.visible
onChangeFunction = {
@ -55,7 +55,7 @@ fun RBuilder.canvasControls(canvas: ThreeCanvas) = accordion("controls") {
attrs {
onClickFunction = {
val json = (canvas.content as? SolidGroup)?.let { group ->
SolidManager.jsonForSolids.stringify(
SolidManager.jsonForSolids.encodeToString(
SolidGroup.serializer(),
group
)
@ -76,7 +76,7 @@ fun RBuilder.canvasControls(canvas: ThreeCanvas) = accordion("controls") {
(0..11).forEach { layer ->
div("col-1") {
label { +layer.toString() }
input(type = InputType.checkBox){
input(type = InputType.checkBox) {
attrs {
if (layer == 0) {
defaultChecked = true
@ -119,7 +119,7 @@ fun Element.displayCanvasControls(canvas: ThreeCanvas, block: TagConsumer<HTMLEl
+"Export"
onClickFunction = {
val json = (canvas.content as? SolidGroup)?.let { group ->
SolidManager.jsonForSolids.stringify(
SolidManager.jsonForSolids.encodeToString(
SolidGroup.serializer(),
group
)

View File

@ -38,7 +38,7 @@ class FX3DPlugin : AbstractPlugin() {
@Suppress("UNCHECKED_CAST")
private fun findObjectFactory(type: KClass<out Solid>): FX3DFactory<Solid>? {
return (objectFactories[type] ?: context.content<FX3DFactory<*>>(TYPE).values.find { it.type == type })
return (objectFactories[type] ?: context.gather<FX3DFactory<*>>(TYPE).values.find { it.type == type })
as FX3DFactory<Solid>?
}

View File

@ -1,8 +1,6 @@
package hep.dataforge.vision.solid.fx
import hep.dataforge.names.Name
import hep.dataforge.names.isEmpty
import hep.dataforge.names.toName
import hep.dataforge.names.*
import hep.dataforge.vision.Vision
import hep.dataforge.vision.solid.Proxy
import javafx.scene.Group
@ -17,8 +15,8 @@ class FXProxyFactory(val plugin: FX3DPlugin) : FX3DFactory<Proxy> {
val node = plugin.buildNode(prototype)
obj.onPropertyChange(this) { name->
if (name.first()?.body == Proxy.PROXY_CHILD_PROPERTY_PREFIX) {
val childName = name.first()?.index?.toName() ?: error("Wrong syntax for proxy child property: '$name'")
if (name.firstOrNull()?.body == Proxy.PROXY_CHILD_PROPERTY_PREFIX) {
val childName = name.firstOrNull()?.index?.toName() ?: error("Wrong syntax for proxy child property: '$name'")
val propertyName = name.cutFirst()
val proxyChild = obj[childName] ?: error("Proxy child with name '$childName' not found")
val child = node.findChild(childName) ?: error("Object child with name '$childName' not found")
@ -35,7 +33,7 @@ private fun Node.findChild(name: Name): Node? {
} else {
(this as? Group)
?.children
?.find { it.properties["name"] as String == name.first()?.toString() }
?.find { it.properties["name"] as String == name.firstOrNull()?.toString() }
?.findChild(name.cutFirst())
}
}

View File

@ -1,205 +1,208 @@
package hep.dataforge.vision.solid
import hep.dataforge.meta.JSON_PRETTY
import kotlinx.serialization.*
import kotlinx.serialization.json.*
import kotlinx.serialization.modules.SerialModule
import kotlinx.serialization.modules.SerialModuleCollector
import kotlin.reflect.KClass
private fun SerialDescriptor.getJsonType() = when (this.kind) {
StructureKind.LIST -> "array"
PrimitiveKind.BYTE, PrimitiveKind.SHORT, PrimitiveKind.INT, PrimitiveKind.LONG,
PrimitiveKind.FLOAT, PrimitiveKind.DOUBLE -> "number"
PrimitiveKind.STRING, PrimitiveKind.CHAR, UnionKind.ENUM_KIND -> "string"
PrimitiveKind.BOOLEAN -> "boolean"
else -> "object"
}
private fun SerialDescriptor.isVisualObject() = serialName.startsWith("solid")||serialName.startsWith("group.solid")
private const val definitionNode = "\$defs"
private fun SerialModule.enumerate(type: KClass<*>): Sequence<SerialDescriptor> {
val list = ArrayList<SerialDescriptor>()
fun send(descriptor: SerialDescriptor) = list.add(descriptor)
val enumerator = object : SerialModuleCollector {
override fun <T : Any> contextual(kClass: KClass<T>, serializer: KSerializer<T>) {
if (kClass == type) {
send(serializer.descriptor)
}
}
override fun <Base : Any, Sub : Base> polymorphic(
baseClass: KClass<Base>,
actualClass: KClass<Sub>,
actualSerializer: KSerializer<Sub>
) {
if (baseClass == type) {
send(actualSerializer.descriptor)
}
}
}
dumpTo(enumerator)
return list.asSequence()
}
/**
* Creates an [JsonObject] which contains Json Schema of given [descriptor].
*
* Schema can contain following fields:
* `description`, `type` for all descriptors;
* `properties` and `required` for objects;
* `enum` for enums;
* `items` for arrays.
*
* User can modify this schema to add additional validation keywords
* (as per [https://json-schema.org/latest/json-schema-validation.html])
* if they want.
*/
private fun jsonSchema(descriptor: SerialDescriptor, context: SerialModule): JsonObject {
if (descriptor.serialName in arrayOf(
"hep.dataforge.vision.solid.Point3D",
"hep.dataforge.vision.solid.Point3D?",
"hep.dataforge.vision.solid.Point2D",
"hep.dataforge.vision.solid.Point2D?",
"hep.dataforge.meta.Meta",
"hep.dataforge.meta.Meta?"
)
) return json {
"\$ref" to "#/$definitionNode/${descriptor.serialName.replace("?", "")}"
}
val properties: MutableMap<String, JsonObject> = mutableMapOf()
val requiredProperties: MutableSet<String> = mutableSetOf()
val isEnum = descriptor.kind == UnionKind.ENUM_KIND
val isPolymorphic = descriptor.kind is PolymorphicKind
if (!isEnum && !isPolymorphic) descriptor.elementDescriptors().forEachIndexed { index, child ->
val elementName = descriptor.getElementName(index)
val elementSchema = when (elementName) {
"properties" -> json {
"\$ref" to "#/$definitionNode/hep.dataforge.meta.Meta"
}
"first", "second" -> json {
"\$ref" to "#/$definitionNode/children"
}
"styleSheet" -> json {
"type" to "object"
"additionalProperties" to json {
"\$ref" to "#/$definitionNode/hep.dataforge.meta.Meta"
}
}
in arrayOf("children", "prototypes") -> json {
"type" to "object"
"additionalProperties" to json {
"\$ref" to "#/$definitionNode/children"
}
}
else -> jsonSchema(child, context)
}
properties[elementName] = elementSchema
if (!descriptor.isElementOptional(index)) requiredProperties.add(elementName)
}
val jsonType = descriptor.getJsonType()
val objectData: MutableMap<String, JsonElement> = mutableMapOf(
"description" to JsonLiteral(descriptor.serialName),
"type" to JsonLiteral(jsonType)
)
if (isEnum) {
val allElementNames = (0 until descriptor.elementsCount).map(descriptor::getElementName)
objectData += "enum" to JsonArray(allElementNames.map(::JsonLiteral))
}
when (jsonType) {
"object" -> {
if(descriptor.isVisualObject()) {
properties["type"] = json {
"const" to descriptor.serialName
}
}
objectData["properties"] = JsonObject(properties)
val required = requiredProperties.map { JsonLiteral(it) }
if (required.isNotEmpty()) {
objectData["required"] = JsonArray(required)
}
}
"array" -> objectData["items"] = properties.values.let {
check(it.size == 1) { "Array descriptor has returned inconsistent number of elements: expected 1, found ${it.size}" }
it.first()
}
else -> { /* no-op */
}
}
return JsonObject(objectData)
}
fun main() {
val context = SolidManager.serialModule
val definitions = json {
"children" to json {
"anyOf" to jsonArray {
context.enumerate(Solid::class).forEach {
if (it.serialName == "hep.dataforge.vis.spatial.SolidGroup") {
+json {
"\$ref" to "#/$definitionNode/${it.serialName}"
}
} else {
+jsonSchema(it, context)
}
}
}
}
"hep.dataforge.meta.Meta" to json {
"type" to "object"
}
"hep.dataforge.vision.solid.Point3D" to json {
"type" to "object"
"properties" to json {
"x" to json {
"type" to "number"
}
"y" to json {
"type" to "number"
}
"z" to json {
"type" to "number"
}
}
}
"hep.dataforge.vision.solid.Point2D" to json {
"type" to "object"
"properties" to json {
"x" to json {
"type" to "number"
}
"y" to json {
"type" to "number"
}
}
}
"hep.dataforge.vision.solid.SolidGroup" to jsonSchema(
SolidGroup.serializer().descriptor,
context
)
}
println(
JSON_PRETTY.stringify(
JsonObjectSerializer,
json {
"\$defs" to definitions
"\$ref" to "#/$definitionNode/hep.dataforge.vision.solid.SolidGroup"
}
)
)
}
//package hep.dataforge.vision.solid
//
//import hep.dataforge.meta.JSON_PRETTY
//import kotlinx.serialization.*
//import kotlinx.serialization.descriptors.PrimitiveKind
//import kotlinx.serialization.descriptors.SerialDescriptor
//import kotlinx.serialization.descriptors.StructureKind
//import kotlinx.serialization.descriptors.UnionKind
//import kotlinx.serialization.json.*
//import kotlinx.serialization.modules.SerialModule
//import kotlin.reflect.KClass
//
//private fun SerialDescriptor.getJsonType() = when (this.kind) {
// StructureKind.LIST -> "array"
// PrimitiveKind.BYTE, PrimitiveKind.SHORT, PrimitiveKind.INT, PrimitiveKind.LONG,
// PrimitiveKind.FLOAT, PrimitiveKind.DOUBLE -> "number"
// PrimitiveKind.STRING, PrimitiveKind.CHAR, UnionKind.ENUM_KIND -> "string"
// PrimitiveKind.BOOLEAN -> "boolean"
// else -> "object"
//}
//
//private fun SerialDescriptor.isVisualObject() = serialName.startsWith("solid")||serialName.startsWith("group.solid")
//
//private const val definitionNode = "\$defs"
//
//private fun SerialModule.enumerate(type: KClass<*>): Sequence<SerialDescriptor> {
// val list = ArrayList<SerialDescriptor>()
// fun send(descriptor: SerialDescriptor) = list.add(descriptor)
//
// val enumerator = object : SerialModuleCollector {
// override fun <T : Any> contextual(kClass: KClass<T>, serializer: KSerializer<T>) {
// if (kClass == type) {
// send(serializer.descriptor)
// }
// }
//
// override fun <Base : Any, Sub : Base> polymorphic(
// baseClass: KClass<Base>,
// actualClass: KClass<Sub>,
// actualSerializer: KSerializer<Sub>
// ) {
// if (baseClass == type) {
// send(actualSerializer.descriptor)
// }
// }
//
// }
// dumpTo(enumerator)
// return list.asSequence()
//}
//
///**
// * Creates an [JsonObject] which contains Json Schema of given [descriptor].
// *
// * Schema can contain following fields:
// * `description`, `type` for all descriptors;
// * `properties` and `required` for objects;
// * `enum` for enums;
// * `items` for arrays.
// *
// * User can modify this schema to add additional validation keywords
// * (as per [https://json-schema.org/latest/json-schema-validation.html])
// * if they want.
// */
//private fun jsonSchema(descriptor: SerialDescriptor, context: SerialModule): JsonObject {
//
// if (descriptor.serialName in arrayOf(
// "hep.dataforge.vision.solid.Point3D",
// "hep.dataforge.vision.solid.Point3D?",
// "hep.dataforge.vision.solid.Point2D",
// "hep.dataforge.vision.solid.Point2D?",
// "hep.dataforge.meta.Meta",
// "hep.dataforge.meta.Meta?"
// )
// ) return json {
// "\$ref" to "#/$definitionNode/${descriptor.serialName.replace("?", "")}"
// }
//
//
// val properties: MutableMap<String, JsonObject> = mutableMapOf()
// val requiredProperties: MutableSet<String> = mutableSetOf()
// val isEnum = descriptor.kind == UnionKind.ENUM_KIND
// val isPolymorphic = descriptor.kind is PolymorphicKind
//
//
// if (!isEnum && !isPolymorphic) descriptor.elementDescriptors().forEachIndexed { index, child ->
// val elementName = descriptor.getElementName(index)
//
// val elementSchema = when (elementName) {
// "properties" -> buildJsonObject {
// put("\$ref", "#/$definitionNode/hep.dataforge.meta.Meta")
// }
// "first", "second" -> buildJsonObject {
// put("\$ref", "#/$definitionNode/children")
// }
// "styleSheet" -> buildJsonObject {
// put("type", "object")
// put("additionalProperties", buildJsonObject {
// put("\$ref", "#/$definitionNode/hep.dataforge.meta.Meta")
// })
// }
// in arrayOf("children", "prototypes") -> buildJsonObject {
// put("type", "object")
// put("additionalProperties", buildJsonObject {
// put("\$ref", "#/$definitionNode/children")
// })
// }
// else -> jsonSchema(child, context)
// }
// properties[elementName] = elementSchema
//
// if (!descriptor.isElementOptional(index)) requiredProperties.add(elementName)
// }
//
// val jsonType = descriptor.getJsonType()
// val objectData: MutableMap<String, JsonElement> = mutableMapOf(
// "description" to JsonLiteral(descriptor.serialName),
// "type" to JsonLiteral(jsonType)
// )
// if (isEnum) {
// val allElementNames = (0 until descriptor.elementsCount).map(descriptor::getElementName)
// objectData += "enum" to JsonArray(allElementNames.map(::JsonLiteral))
// }
// when (jsonType) {
// "object" -> {
// if(descriptor.isVisualObject()) {
// properties["type"] = json {
// "const" to descriptor.serialName
// }
// }
// objectData["properties"] = JsonObject(properties)
// val required = requiredProperties.map { JsonLiteral(it) }
// if (required.isNotEmpty()) {
// objectData["required"] = JsonArray(required)
// }
// }
// "array" -> objectData["items"] = properties.values.let {
// check(it.size == 1) { "Array descriptor has returned inconsistent number of elements: expected 1, found ${it.size}" }
// it.first()
// }
// else -> { /* no-op */
// }
// }
// return JsonObject(objectData)
//}
//
//fun main() {
// val context = SolidManager.serialModule
// val definitions = json {
// "children" to json {
// "anyOf" to jsonArray {
// context.enumerate(Solid::class).forEach {
// if (it.serialName == "hep.dataforge.vis.spatial.SolidGroup") {
// +json {
// "\$ref" to "#/$definitionNode/${it.serialName}"
// }
// } else {
// +jsonSchema(it, context)
// }
// }
// }
// }
// "hep.dataforge.meta.Meta" to json {
// "type" to "object"
// }
// "hep.dataforge.vision.solid.Point3D" to json {
// "type" to "object"
// "properties" to json {
// "x" to json {
// "type" to "number"
// }
// "y" to json {
// "type" to "number"
// }
// "z" to json {
// "type" to "number"
// }
// }
// }
// "hep.dataforge.vision.solid.Point2D" to json {
// "type" to "object"
// "properties" to json {
// "x" to json {
// "type" to "number"
// }
// "y" to json {
// "type" to "number"
// }
// }
// }
// "hep.dataforge.vision.solid.SolidGroup" to jsonSchema(
// SolidGroup.serializer().descriptor,
// context
// )
//
// }
//
// println(
// JSON_PRETTY.stringify(
// JsonObjectSerializer,
// json {
// "\$defs" to definitions
// "\$ref" to "#/$definitionNode/hep.dataforge.vision.solid.SolidGroup"
// }
// )
// )
//}
//

View File

@ -1,11 +1,11 @@
package hep.dataforge.vision.solid
import org.fxyz3d.geometry.Point3D as FXPoint3D
actual data class Point2D(actual var x: Double, actual var y: Double) {
public actual data class Point2D(public actual var x: Double, public actual var y: Double) {
actual constructor(x: Number, y: Number) : this(x.toDouble(), y.toDouble())
}
actual class Point3D(val point: FXPoint3D) {
public actual class Point3D(val point: FXPoint3D) {
actual constructor(x: Number, y: Number, z: Number) : this(
FXPoint3D(
x.toFloat(),
@ -14,19 +14,19 @@ actual class Point3D(val point: FXPoint3D) {
)
)
actual var x: Double
public actual var x: Double
inline get() = point.x.toDouble()
inline set(value) {
point.x = value.toFloat()
}
actual var y: Double
public actual var y: Double
inline get() = point.y.toDouble()
inline set(value) {
point.y = value.toFloat()
}
actual var z: Double
public actual var z: Double
inline get() = point.z.toDouble()
inline set(value) {
point.z = value.toFloat()
@ -45,6 +45,6 @@ actual class Point3D(val point: FXPoint3D) {
}
}
actual operator fun Point3D.plus(other: Point3D): Point3D {
public actual operator fun Point3D.plus(other: Point3D): Point3D {
return Point3D(point.add(other.point))
}