JS 3d Visualization
This commit is contained in:
parent
8c77d3800b
commit
ec01b0d7a8
@ -58,6 +58,28 @@ subprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
js{
|
||||||
|
configure(listOf(compilations["main"], compilations["test"])) {
|
||||||
|
tasks.getByName(compileKotlinTaskName) {
|
||||||
|
kotlinOptions {
|
||||||
|
metaInfo = true
|
||||||
|
sourceMap = true
|
||||||
|
sourceMapEmbedSources = "always"
|
||||||
|
moduleKind = "umd"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configure(listOf(compilations["main"])) {
|
||||||
|
tasks.getByName(compileKotlinTaskName) {
|
||||||
|
kotlinOptions {
|
||||||
|
main = "call"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
targets.all {
|
targets.all {
|
||||||
sourceSets.all {
|
sourceSets.all {
|
||||||
languageSettings.progressiveMode = true
|
languageSettings.progressiveMode = true
|
||||||
@ -119,6 +141,4 @@ subprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id "org.jetbrains.kotlin.multiplatform"
|
|
||||||
}
|
|
||||||
|
|
||||||
description = "IO for meta"
|
|
||||||
|
|
||||||
kotlin {
|
|
||||||
targets {
|
|
||||||
fromPreset(presets.jvm, 'jvm')
|
|
||||||
fromPreset(presets.js, 'js')
|
|
||||||
// For ARM, preset should be changed to presets.iosArm32 or presets.iosArm64
|
|
||||||
// For Linux, preset should be changed to e.g. presets.linuxX64
|
|
||||||
// For MacOS, preset should be changed to e.g. presets.macosX64
|
|
||||||
//fromPreset(presets.iosX64, 'ios')
|
|
||||||
}
|
|
||||||
sourceSets {
|
|
||||||
commonMain {
|
|
||||||
dependencies {
|
|
||||||
api project(":dataforge-meta")
|
|
||||||
//implementation 'org.jetbrains.kotlin:kotlin-reflect'
|
|
||||||
api "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serializationVersion"
|
|
||||||
api "org.jetbrains.kotlinx:kotlinx-io:$ioVersion"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
commonTest {
|
|
||||||
dependencies {
|
|
||||||
implementation 'org.jetbrains.kotlin:kotlin-test-common'
|
|
||||||
implementation 'org.jetbrains.kotlin:kotlin-test-annotations-common'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
jvmMain {
|
|
||||||
dependencies {
|
|
||||||
api "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serializationVersion"
|
|
||||||
api "org.jetbrains.kotlinx:kotlinx-io-jvm:$ioVersion"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
jvmTest {
|
|
||||||
dependencies {
|
|
||||||
implementation 'org.jetbrains.kotlin:kotlin-test'
|
|
||||||
implementation 'org.jetbrains.kotlin:kotlin-test-junit'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
jsMain {
|
|
||||||
dependencies {
|
|
||||||
api "org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:$serializationVersion"
|
|
||||||
api "org.jetbrains.kotlinx:kotlinx-io-js:$ioVersion"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
jsTest {
|
|
||||||
dependencies {
|
|
||||||
implementation 'org.jetbrains.kotlin:kotlin-test-js'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// iosMain {
|
|
||||||
// }
|
|
||||||
// iosTest {
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
57
dataforge-meta-io/build.gradle.kts
Normal file
57
dataforge-meta-io/build.gradle.kts
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("multiplatform")
|
||||||
|
}
|
||||||
|
|
||||||
|
description = "IO for meta"
|
||||||
|
|
||||||
|
|
||||||
|
val ioVersion: String by rootProject.extra
|
||||||
|
val serializationVersion: String by rootProject.extra
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
jvm()
|
||||||
|
js()
|
||||||
|
sourceSets {
|
||||||
|
val commonMain by getting{
|
||||||
|
dependencies {
|
||||||
|
api(project(":dataforge-meta"))
|
||||||
|
//implementation 'org.jetbrains.kotlin:kotlin-reflect'
|
||||||
|
api("org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serializationVersion")
|
||||||
|
api("org.jetbrains.kotlinx:kotlinx-io:$ioVersion")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val commonTest by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation("org.jetbrains.kotlin:kotlin-test-common")
|
||||||
|
implementation("org.jetbrains.kotlin:kotlin-test-annotations-common")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val jvmMain by getting {
|
||||||
|
dependencies {
|
||||||
|
api("org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serializationVersion")
|
||||||
|
api("org.jetbrains.kotlinx:kotlinx-io-jvm:$ioVersion")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val jvmTest by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation("org.jetbrains.kotlin:kotlin-test")
|
||||||
|
implementation("org.jetbrains.kotlin:kotlin-test-junit")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val jsMain by getting {
|
||||||
|
dependencies {
|
||||||
|
api("org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:$serializationVersion")
|
||||||
|
api("org.jetbrains.kotlinx:kotlinx-io-js:$ioVersion")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val jsTest by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation("org.jetbrains.kotlin:kotlin-test-js")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// iosMain {
|
||||||
|
// }
|
||||||
|
// iosTest {
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,8 @@
|
|||||||
|
import org.openjfx.gradle.JavaFXOptions
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("multiplatform")
|
kotlin("multiplatform")
|
||||||
|
id("org.openjfx.javafxplugin")
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
@ -14,6 +17,7 @@ kotlin {
|
|||||||
}
|
}
|
||||||
val jvmMain by getting {
|
val jvmMain by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
|
//api("no.tornado:tornadofx:1.7.18")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val jsMain by getting {
|
val jsMain by getting {
|
||||||
@ -21,4 +25,8 @@ kotlin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configure<JavaFXOptions>{
|
||||||
|
modules("javafx.controls")
|
||||||
}
|
}
|
@ -1,23 +0,0 @@
|
|||||||
package hep.dataforge.vis
|
|
||||||
|
|
||||||
import javafx.scene.paint.Color
|
|
||||||
import javafx.scene.paint.PhongMaterial
|
|
||||||
|
|
||||||
object Materials{
|
|
||||||
val RED = PhongMaterial().apply {
|
|
||||||
diffuseColor = Color.DARKRED
|
|
||||||
specularColor = Color.RED
|
|
||||||
}
|
|
||||||
|
|
||||||
val WHITE = PhongMaterial().apply {
|
|
||||||
diffuseColor = Color.WHITE
|
|
||||||
specularColor = Color.LIGHTBLUE
|
|
||||||
}
|
|
||||||
|
|
||||||
val GREY = PhongMaterial().apply {
|
|
||||||
diffuseColor = Color.DARKGREY
|
|
||||||
specularColor = Color.GREY
|
|
||||||
}
|
|
||||||
|
|
||||||
val BLUE = PhongMaterial(Color.BLUE)
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
package hep.dataforge.vis.spatial
|
|
||||||
|
|
||||||
import hep.dataforge.context.Context
|
|
||||||
import hep.dataforge.io.Output
|
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.meta.int
|
|
||||||
import hep.dataforge.vis.DisplayGroup
|
|
||||||
import hep.dataforge.vis.DisplayObject
|
|
||||||
import hep.dataforge.vis.DisplayObjectPropertyListener
|
|
||||||
import hep.dataforge.vis.transform
|
|
||||||
import javafx.scene.Group
|
|
||||||
import javafx.scene.Node
|
|
||||||
import javafx.scene.paint.Color
|
|
||||||
import org.fxyz3d.geometry.Point3D
|
|
||||||
import org.fxyz3d.shapes.primitives.CuboidMesh
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* https://github.com/miho/JCSG for operations
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class FXSpatialRenderer(override val context: Context) : Output<DisplayObject> {
|
|
||||||
|
|
||||||
val canvas by lazy { Canvas3D() }
|
|
||||||
|
|
||||||
private fun buildObject(obj: DisplayObject): Node {
|
|
||||||
return when (obj) {
|
|
||||||
is DisplayGroup -> Group(obj.children.map { buildObject(it) })
|
|
||||||
is Box -> CuboidMesh(obj.xSize, obj.ySize, obj.zSize).apply {
|
|
||||||
val listener = DisplayObjectPropertyListener(obj)
|
|
||||||
this.center = Point3D(obj.x.toFloat(), obj.y.toFloat(), obj.z.toFloat())
|
|
||||||
this.diffuseColorProperty().bind(listener["color"].transform {
|
|
||||||
//TODO Move to extension
|
|
||||||
val int = it.int ?: 0
|
|
||||||
val red = int and 0x00ff0000 shr 16
|
|
||||||
val green = int and 0x0000ff00 shr 8
|
|
||||||
val blue = int and 0x000000ff
|
|
||||||
return@transform Color.rgb(red, green, blue)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
else -> TODO()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun render(obj: DisplayObject, meta: Meta) {
|
|
||||||
canvas.world.children.add(buildObject(obj))
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
plugins{
|
|
||||||
kotlin("js")
|
|
||||||
id("kotlin")
|
|
||||||
}
|
|
||||||
|
|
||||||
// configure(listOf(compilations.main, compilations.test)) {
|
|
||||||
// tasks.getByName(compileKotlinTaskName).kotlinOptions {
|
|
||||||
// sourceMap = true
|
|
||||||
// moduleKind = "umd"
|
|
||||||
// metaInfo = true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// configure(compilations.main) {
|
|
||||||
// tasks.getByName(compileKotlinTaskName).kotlinOptions {
|
|
||||||
// main = "call"
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation("info.laht.threekt:threejs-wrapper:0.88-npm-1")
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions.findByType<KotlinFrontendExtension>()?.apply {
|
|
||||||
extensions.findByType<NpmExtension>()?.apply {
|
|
||||||
dependency("three")
|
|
||||||
dependency("three-orbitcontrols")
|
|
||||||
devDependency("karma")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceMaps = true
|
|
||||||
|
|
||||||
bundle("webpack") {
|
|
||||||
this as WebPackExtension
|
|
||||||
bundleName = "main"
|
|
||||||
proxyUrl = "http://localhost:8080"
|
|
||||||
contentPath = file("src/main/web")
|
|
||||||
sourceMapEnabled = true
|
|
||||||
mode = "development"
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,7 +12,7 @@ dependencies{
|
|||||||
implementation("org.fxyz3d:fxyz3d:0.4.0")
|
implementation("org.fxyz3d:fxyz3d:0.4.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
extensions.findByType<JavaFXOptions>()?.apply {
|
configure<JavaFXOptions> {
|
||||||
modules("javafx.controls")
|
modules("javafx.controls")
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,5 @@
|
|||||||
package hep.dataforge.vis
|
package hep.dataforge.vis
|
||||||
|
|
||||||
import hep.dataforge.meta.*
|
|
||||||
import hep.dataforge.names.Name
|
|
||||||
import hep.dataforge.names.toName
|
|
||||||
import javafx.beans.binding.ObjectBinding
|
import javafx.beans.binding.ObjectBinding
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
@ -19,21 +19,34 @@ class Canvas3D : Fragment() {
|
|||||||
translateZ = CAMERA_INITIAL_DISTANCE
|
translateZ = CAMERA_INITIAL_DISTANCE
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO move up
|
private val cameraShift = CameraTransformer().apply {
|
||||||
val cameraShift = CameraTransformer().apply {
|
|
||||||
val cameraFlip = CameraTransformer()
|
val cameraFlip = CameraTransformer()
|
||||||
cameraFlip.children.add(camera)
|
cameraFlip.children.add(camera)
|
||||||
cameraFlip.setRotateZ(180.0)
|
cameraFlip.setRotateZ(180.0)
|
||||||
children.add(cameraFlip)
|
children.add(cameraFlip)
|
||||||
}
|
}
|
||||||
|
|
||||||
val cameraRotation = CameraTransformer().apply {
|
val translationXProperty get() = cameraShift.t.xProperty()
|
||||||
|
var translateX by translationXProperty
|
||||||
|
val translationYProperty get() = cameraShift.t.yProperty()
|
||||||
|
var translateY by translationYProperty
|
||||||
|
val translationZProperty get() = cameraShift.t.zProperty()
|
||||||
|
var translateZ by translationZProperty
|
||||||
|
|
||||||
|
private val cameraRotation = CameraTransformer().apply {
|
||||||
children.add(cameraShift)
|
children.add(cameraShift)
|
||||||
ry.angle = CAMERA_INITIAL_Y_ANGLE
|
ry.angle = CAMERA_INITIAL_Y_ANGLE
|
||||||
rx.angle = CAMERA_INITIAL_X_ANGLE
|
rx.angle = CAMERA_INITIAL_X_ANGLE
|
||||||
rz.angle = CAMERA_INITIAL_Z_ANGLE
|
rz.angle = CAMERA_INITIAL_Z_ANGLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val rotationXProperty get() = cameraRotation.rx.angleProperty()
|
||||||
|
var angleX by rotationXProperty
|
||||||
|
val rotationYProperty get() = cameraRotation.ry.angleProperty()
|
||||||
|
var angleY by rotationYProperty
|
||||||
|
val rotationZProperty get() = cameraRotation.rz.angleProperty()
|
||||||
|
var angleZ by rotationZProperty
|
||||||
|
|
||||||
|
|
||||||
override val root =borderpane {
|
override val root =borderpane {
|
||||||
center = SubScene(
|
center = SubScene(
|
||||||
@ -122,10 +135,6 @@ class Canvas3D : Fragment() {
|
|||||||
cameraRotation.rz.angle + mouseDeltaX * MOUSE_SPEED * modifier * ROTATION_SPEED
|
cameraRotation.rz.angle + mouseDeltaX * MOUSE_SPEED * modifier * ROTATION_SPEED
|
||||||
cameraRotation.rx.angle =
|
cameraRotation.rx.angle =
|
||||||
cameraRotation.rx.angle + mouseDeltaY * MOUSE_SPEED * modifier * ROTATION_SPEED
|
cameraRotation.rx.angle + mouseDeltaY * MOUSE_SPEED * modifier * ROTATION_SPEED
|
||||||
// } else if (me.isSecondaryButtonDown()) {
|
|
||||||
// double z = camera.getTranslateZ();
|
|
||||||
// double newZ = z + mouseDeltaX * MOUSE_SPEED * modifier*100;
|
|
||||||
// camera.setTranslateZ(newZ);
|
|
||||||
} else if (me.isSecondaryButtonDown) {
|
} else if (me.isSecondaryButtonDown) {
|
||||||
cameraShift.t.x = cameraShift.t.x + mouseDeltaX * MOUSE_SPEED * modifier * TRACK_SPEED
|
cameraShift.t.x = cameraShift.t.x + mouseDeltaX * MOUSE_SPEED * modifier * TRACK_SPEED
|
||||||
cameraShift.t.y = cameraShift.t.y + mouseDeltaY * MOUSE_SPEED * modifier * TRACK_SPEED
|
cameraShift.t.y = cameraShift.t.y + mouseDeltaY * MOUSE_SPEED * modifier * TRACK_SPEED
|
@ -0,0 +1,54 @@
|
|||||||
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import hep.dataforge.vis.DisplayObjectPropertyListener
|
||||||
|
import javafx.scene.Group
|
||||||
|
import javafx.scene.Node
|
||||||
|
import org.fxyz3d.shapes.primitives.CuboidMesh
|
||||||
|
import tornadofx.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://github.com/miho/JCSG for operations
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class FX3DOutput(override val context: Context) : Output<Any> {
|
||||||
|
val canvas by lazy { Canvas3D() }
|
||||||
|
|
||||||
|
|
||||||
|
private fun buildNode(obj: Any): Node? {
|
||||||
|
return when (obj) {
|
||||||
|
is DisplayShape3D -> {
|
||||||
|
val listener = DisplayObjectPropertyListener(obj)
|
||||||
|
val x = listener["x"].float()
|
||||||
|
val y = listener["y"].float()
|
||||||
|
val z = listener["z"].float()
|
||||||
|
val center = objectBinding(x, y, z) {
|
||||||
|
Point3D(x.value ?: 0f, y.value ?: 0f, z.value ?: 0f)
|
||||||
|
}
|
||||||
|
when (obj) {
|
||||||
|
is DisplayGroup3D -> Group(obj.children.map { buildNode(it) }).apply {
|
||||||
|
this.translateXProperty().bind(x)
|
||||||
|
this.translateYProperty().bind(y)
|
||||||
|
this.translateZProperty().bind(z)
|
||||||
|
}
|
||||||
|
is Box -> CuboidMesh(obj.xSize, obj.ySize, obj.zSize).apply {
|
||||||
|
this.centerProperty().bind(center)
|
||||||
|
this.materialProperty().bind(listener["color"].transform { it.material() })
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
logger.error { "No renderer defined for ${obj::class}" }
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is DisplayGroup -> Group(obj.children.map { buildNode(it) }) // a logical group
|
||||||
|
else -> {
|
||||||
|
logger.error { "No renderer defined for ${obj::class}" }
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun render(obj: Any, meta: Meta) {
|
||||||
|
buildNode(obj)?.let { canvas.world.children.add(it) }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import javafx.scene.paint.Color
|
||||||
|
import javafx.scene.paint.Material
|
||||||
|
import javafx.scene.paint.PhongMaterial
|
||||||
|
|
||||||
|
object Materials {
|
||||||
|
val RED = PhongMaterial().apply {
|
||||||
|
diffuseColor = Color.DARKRED
|
||||||
|
specularColor = Color.RED
|
||||||
|
}
|
||||||
|
|
||||||
|
val WHITE = PhongMaterial().apply {
|
||||||
|
diffuseColor = Color.WHITE
|
||||||
|
specularColor = Color.LIGHTBLUE
|
||||||
|
}
|
||||||
|
|
||||||
|
val GREY = PhongMaterial().apply {
|
||||||
|
diffuseColor = Color.DARKGREY
|
||||||
|
specularColor = Color.GREY
|
||||||
|
}
|
||||||
|
|
||||||
|
val BLUE = PhongMaterial(Color.BLUE)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Infer color based on meta item
|
||||||
|
*/
|
||||||
|
fun MetaItem<*>.color(): Color {
|
||||||
|
return when (this) {
|
||||||
|
is MetaItem.ValueItem -> if (this.value.type == ValueType.STRING) {
|
||||||
|
Color.web(this.value.string)
|
||||||
|
} else {
|
||||||
|
val int = value.number.toInt()
|
||||||
|
val red = int and 0x00ff0000 shr 16
|
||||||
|
val green = int and 0x0000ff00 shr 8
|
||||||
|
val blue = int and 0x000000ff
|
||||||
|
Color.rgb(red, green, blue)
|
||||||
|
}
|
||||||
|
is MetaItem.NodeItem -> {
|
||||||
|
Color.rgb(
|
||||||
|
node["red"]?.int ?: 0,
|
||||||
|
node["green"]?.int ?: 0,
|
||||||
|
node["blue"]?.int ?: 0,
|
||||||
|
node["opacity"]?.double ?: 1.0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Infer FX material based on meta item
|
||||||
|
*/
|
||||||
|
fun MetaItem<*>.material(): Material {
|
||||||
|
return when (this) {
|
||||||
|
is MetaItem.ValueItem -> PhongMaterial(color())
|
||||||
|
is MetaItem.NodeItem -> PhongMaterial().apply {
|
||||||
|
node["color"]?.let { diffuseColor = it.color() }
|
||||||
|
node["specularColor"]?.let { specularColor = it.color() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,5 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.context.Global
|
|
||||||
import hep.dataforge.meta.number
|
|
||||||
import hep.dataforge.vis.DisplayGroup
|
|
||||||
import javafx.scene.Parent
|
import javafx.scene.Parent
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@ -16,7 +13,7 @@ class RendererDemoApp : App(RendererDemoView::class)
|
|||||||
|
|
||||||
|
|
||||||
class RendererDemoView : View() {
|
class RendererDemoView : View() {
|
||||||
val renderer = FXSpatialRenderer(Global)
|
val renderer = FX3DOutput(Global)
|
||||||
override val root: Parent = borderpane {
|
override val root: Parent = borderpane {
|
||||||
center = renderer.canvas.root
|
center = renderer.canvas.root
|
||||||
}
|
}
|
||||||
@ -51,9 +48,9 @@ class RendererDemoView : View() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.canvas.cameraRotation.apply {
|
renderer.canvas.apply {
|
||||||
ry.angle = -30.0
|
angleY = -30.0
|
||||||
rx.angle = -15.0
|
angleX = -15.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
59
dataforge-vis/dataforge-vis-spatial-js/build.gradle.kts
Normal file
59
dataforge-vis/dataforge-vis-spatial-js/build.gradle.kts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import org.jetbrains.kotlin.gradle.frontend.KotlinFrontendExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.frontend.npm.NpmExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.frontend.webpack.WebPackExtension
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("kotlin2js")
|
||||||
|
id("kotlin-dce-js")
|
||||||
|
id("org.jetbrains.kotlin.frontend")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api(project(":dataforge-vis:dataforge-vis-spatial"))
|
||||||
|
implementation("info.laht.threekt:threejs-wrapper:0.88-npm-1")
|
||||||
|
}
|
||||||
|
|
||||||
|
configure<KotlinFrontendExtension> {
|
||||||
|
downloadNodeJsVersion = "latest"
|
||||||
|
|
||||||
|
configure<NpmExtension> {
|
||||||
|
dependency("three")
|
||||||
|
dependency("three-orbitcontrols")
|
||||||
|
dependency("style-loader")
|
||||||
|
devDependency("karma")
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceMaps = true
|
||||||
|
|
||||||
|
bundle("webpack") {
|
||||||
|
this as WebPackExtension
|
||||||
|
bundleName = "main"
|
||||||
|
proxyUrl = "http://localhost:8080"
|
||||||
|
contentPath = file("src/main/web")
|
||||||
|
sourceMapEnabled = true
|
||||||
|
//mode = "production"
|
||||||
|
mode = "development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks{
|
||||||
|
compileKotlin2Js{
|
||||||
|
kotlinOptions{
|
||||||
|
metaInfo = true
|
||||||
|
outputFile = "${project.buildDir.path}/js/${project.name}.js"
|
||||||
|
sourceMap = true
|
||||||
|
moduleKind = "umd"
|
||||||
|
main = "call"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileTestKotlin2Js{
|
||||||
|
kotlinOptions{
|
||||||
|
metaInfo = true
|
||||||
|
outputFile = "${project.buildDir.path}/js/${project.name}-test.js"
|
||||||
|
sourceMap = true
|
||||||
|
moduleKind = "umd"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"description": "A demo project for particle visualization in JS"
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package hep.dataforge.vis.hmr
|
||||||
|
|
||||||
|
external val module: Module
|
||||||
|
|
||||||
|
external interface Module {
|
||||||
|
val hot: Hot?
|
||||||
|
}
|
||||||
|
|
||||||
|
external interface Hot {
|
||||||
|
val data: dynamic
|
||||||
|
|
||||||
|
fun accept()
|
||||||
|
fun accept(dependency: String, callback: () -> Unit)
|
||||||
|
fun accept(dependencies: Array<String>, callback: (updated: Array<String>) -> Unit)
|
||||||
|
|
||||||
|
fun dispose(callback: (data: dynamic) -> Unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
external fun require(name: String): dynamic
|
@ -0,0 +1,50 @@
|
|||||||
|
package hep.dataforge.vis
|
||||||
|
|
||||||
|
import hep.dataforge.vis.hmr.module
|
||||||
|
import hep.dataforge.vis.spatial.ThreeDemoApp
|
||||||
|
import kotlin.browser.document
|
||||||
|
import kotlin.dom.hasClass
|
||||||
|
|
||||||
|
|
||||||
|
abstract class ApplicationBase {
|
||||||
|
abstract val stateKeys: List<String>
|
||||||
|
|
||||||
|
abstract fun start(state: Map<String, Any>)
|
||||||
|
abstract fun dispose(): Map<String, Any>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
var application: ApplicationBase? = null
|
||||||
|
|
||||||
|
val state: dynamic = module.hot?.let { hot ->
|
||||||
|
hot.accept()
|
||||||
|
|
||||||
|
hot.dispose { data ->
|
||||||
|
data.appState = application?.dispose()
|
||||||
|
application = null
|
||||||
|
}
|
||||||
|
|
||||||
|
hot.data
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.body != null) {
|
||||||
|
application = start(state)
|
||||||
|
} else {
|
||||||
|
application = null
|
||||||
|
document.addEventListener("DOMContentLoaded", { application = start(state) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun start(state: dynamic): ApplicationBase? {
|
||||||
|
return if (document.body?.hasClass("testApp") == true) {
|
||||||
|
val application = ThreeDemoApp()
|
||||||
|
|
||||||
|
@Suppress("UnsafeCastFromDynamic")
|
||||||
|
application.start(state?.appState ?: emptyMap())
|
||||||
|
|
||||||
|
application
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import hep.dataforge.context.Global
|
||||||
|
import hep.dataforge.meta.number
|
||||||
|
import hep.dataforge.vis.ApplicationBase
|
||||||
|
import hep.dataforge.vis.DisplayGroup
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlin.browser.document
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
|
||||||
|
class ThreeDemoApp : ApplicationBase() {
|
||||||
|
|
||||||
|
override val stateKeys: List<String> = emptyList()
|
||||||
|
|
||||||
|
override fun start(state: Map<String, Any>) {
|
||||||
|
println("started")
|
||||||
|
val renderer = ThreeOutput(Global)
|
||||||
|
document.getElementById("canvas")?.appendChild(renderer.root)
|
||||||
|
|
||||||
|
lateinit var group: DisplayGroup
|
||||||
|
|
||||||
|
renderer.render {
|
||||||
|
group = group {
|
||||||
|
box {
|
||||||
|
xSize = 100.0
|
||||||
|
ySize = 100.0
|
||||||
|
zSize = 100.0
|
||||||
|
}
|
||||||
|
box {
|
||||||
|
x = 110.0
|
||||||
|
xSize = 100.0
|
||||||
|
ySize = 100.0
|
||||||
|
zSize = 100.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var color by group.properties.number(1530).int
|
||||||
|
|
||||||
|
GlobalScope.launch {
|
||||||
|
val random = Random(111)
|
||||||
|
while (isActive) {
|
||||||
|
delay(1000)
|
||||||
|
color = random.nextInt(0, Int.MAX_VALUE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// view.animate()
|
||||||
|
|
||||||
|
// view = WebLinesView(document.getElementById("lines")!!, document.getElementById("addForm")!!)
|
||||||
|
// presenter = LinesPresenter(view)
|
||||||
|
//
|
||||||
|
// state["lines"]?.let { linesState ->
|
||||||
|
// @Suppress("UNCHECKED_CAST")
|
||||||
|
// presenter.restore(linesState as Array<String>)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() = emptyMap<String,Any>()//mapOf("lines" to presenter.dispose())
|
||||||
|
}
|
@ -0,0 +1,140 @@
|
|||||||
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import hep.dataforge.context.Context
|
||||||
|
import hep.dataforge.io.Output
|
||||||
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.vis.DisplayGroup
|
||||||
|
import info.laht.threekt.WebGLRenderer
|
||||||
|
import info.laht.threekt.cameras.PerspectiveCamera
|
||||||
|
import info.laht.threekt.core.Object3D
|
||||||
|
import info.laht.threekt.external.controls.OrbitControls
|
||||||
|
import info.laht.threekt.geometries.BoxBufferGeometry
|
||||||
|
import info.laht.threekt.lights.AmbientLight
|
||||||
|
import info.laht.threekt.materials.MeshPhongMaterial
|
||||||
|
import info.laht.threekt.math.ColorConstants
|
||||||
|
import info.laht.threekt.objects.Mesh
|
||||||
|
import info.laht.threekt.scenes.Scene
|
||||||
|
import kotlin.browser.window
|
||||||
|
|
||||||
|
class ThreeOutput(override val context: Context) : Output<Any> {
|
||||||
|
|
||||||
|
private val renderer = WebGLRenderer { antialias = true }.apply {
|
||||||
|
setClearColor(ColorConstants.skyblue, 1)
|
||||||
|
setSize(window.innerWidth, window.innerHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val scene: Scene = Scene().apply {
|
||||||
|
add(AmbientLight())
|
||||||
|
}
|
||||||
|
private val camera = PerspectiveCamera(
|
||||||
|
75,
|
||||||
|
window.innerWidth.toDouble() / window.innerHeight,
|
||||||
|
0.1,
|
||||||
|
10000
|
||||||
|
).apply {
|
||||||
|
position.z = 4500.0
|
||||||
|
}
|
||||||
|
|
||||||
|
private val controls: OrbitControls = OrbitControls(camera, renderer.domElement)
|
||||||
|
|
||||||
|
val root by lazy {
|
||||||
|
window.addEventListener("resize", {
|
||||||
|
camera.aspect = window.innerWidth.toDouble() / window.innerHeight;
|
||||||
|
camera.updateProjectionMatrix();
|
||||||
|
|
||||||
|
renderer.setSize(window.innerWidth, window.innerHeight)
|
||||||
|
}, false)
|
||||||
|
renderer.domElement
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun buildNode(obj: Any): Object3D? {
|
||||||
|
return when (obj) {
|
||||||
|
is DisplayShape3D -> {
|
||||||
|
// val listener = DisplayObjectPropertyListener(obj)
|
||||||
|
// val x = listener["x"].float()
|
||||||
|
// val y = listener["y"].float()
|
||||||
|
// val z = listener["z"].float()
|
||||||
|
// val center = objectBinding(x, y, z) {
|
||||||
|
// Vector3(x.value ?: 0f, y.value ?: 0f, z.value ?: 0f)
|
||||||
|
// }
|
||||||
|
when (obj) {
|
||||||
|
is DisplayGroup3D -> Group(obj.children.mapNotNull { buildNode(it) }).apply {
|
||||||
|
this.translateX(obj.x)
|
||||||
|
this.translateY(obj.y)
|
||||||
|
this.translateZ(obj.z)
|
||||||
|
}
|
||||||
|
is Box -> {
|
||||||
|
val geometry = BoxBufferGeometry(obj.xSize, obj.ySize, obj.zSize)
|
||||||
|
.translate(obj.x, obj.y, obj.z)
|
||||||
|
val material = MeshPhongMaterial().apply {
|
||||||
|
this.color.set(ColorConstants.darkgreen)
|
||||||
|
}
|
||||||
|
Mesh(geometry, material)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
logger.error { "No renderer defined for ${obj::class}" }
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is DisplayGroup -> Group(obj.children.mapNotNull { buildNode(it) }) // a logical group
|
||||||
|
else -> {
|
||||||
|
logger.error { "No renderer defined for ${obj::class}" }
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun render(obj: Any, meta: Meta) {
|
||||||
|
buildNode(obj)?.let { scene.add(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// init {
|
||||||
|
// val cube: Mesh
|
||||||
|
|
||||||
|
// cube = Mesh(
|
||||||
|
// BoxBufferGeometry(1, 1, 1),
|
||||||
|
// MeshPhongMaterial().apply {
|
||||||
|
// this.color.set(ColorConstants.darkgreen)
|
||||||
|
// }
|
||||||
|
// ).also(scene::add)
|
||||||
|
//
|
||||||
|
// Mesh(cube.geometry as BufferGeometry,
|
||||||
|
// MeshBasicMaterial().apply {
|
||||||
|
// this.wireframe = true
|
||||||
|
// this.color.set(ColorConstants.black)
|
||||||
|
// }
|
||||||
|
// ).also(cube::add)
|
||||||
|
//
|
||||||
|
// val points = CatmullRomCurve3(
|
||||||
|
// arrayOf(
|
||||||
|
// Vector3(-10, 0, 10),
|
||||||
|
// Vector3(-5, 5, 5),
|
||||||
|
// Vector3(0, 0, 0),
|
||||||
|
// Vector3(5, -5, 5),
|
||||||
|
// Vector3(10, 0, 10)
|
||||||
|
// )
|
||||||
|
// ).getPoints(50)
|
||||||
|
//
|
||||||
|
// val geometry = BufferGeometry().setFromPoints(points)
|
||||||
|
//
|
||||||
|
// val material = LineBasicMaterial().apply {
|
||||||
|
// color.set(0xff0000)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Create the final object to add to the scene
|
||||||
|
// Line(geometry, material).apply(scene::add)
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fun animate() {
|
||||||
|
// window.requestAnimationFrame {
|
||||||
|
// cube.rotation.x += 0.01
|
||||||
|
// cube.rotation.y += 0.01
|
||||||
|
// animate()
|
||||||
|
// }
|
||||||
|
// renderer.render(scene, camera)
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import info.laht.threekt.core.Object3D
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods for three.kt.
|
||||||
|
* TODO move to three project
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
fun Group(children: Collection<Object3D>) = info.laht.threekt.objects.Group().apply {
|
||||||
|
children.forEach { this.add(it) }
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Three js demo for particle physics</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<!--<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.min.js"></script>-->
|
||||||
|
<!--<script type="text/javascript" src="js/OrbitControls.js"></script>-->
|
||||||
|
<script type="text/javascript" language="JavaScript" src="main.bundle.js"></script>
|
||||||
|
</head>
|
||||||
|
<body class="testApp">
|
||||||
|
<h1>Demo canvas</h1>
|
||||||
|
<div id="canvas"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1 @@
|
|||||||
|
config.module.rules.push({ test: /\.css$/, loader: "style!css" });
|
@ -4,7 +4,26 @@ plugins {
|
|||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
jvm()
|
jvm()
|
||||||
js()
|
js {
|
||||||
|
configure(listOf(compilations["main"], compilations["test"])) {
|
||||||
|
tasks.getByName(compileKotlinTaskName) {
|
||||||
|
kotlinOptions {
|
||||||
|
metaInfo = true
|
||||||
|
sourceMap = true
|
||||||
|
sourceMapEmbedSources = "always"
|
||||||
|
moduleKind = "umd"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configure(listOf(compilations["main"])) {
|
||||||
|
tasks.getByName(compileKotlinTaskName) {
|
||||||
|
kotlinOptions {
|
||||||
|
main = "call"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
val commonMain by getting {
|
val commonMain by getting {
|
||||||
@ -23,4 +42,5 @@ kotlin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import hep.dataforge.vis.DisplayGroup
|
|||||||
import hep.dataforge.vis.DisplayObject
|
import hep.dataforge.vis.DisplayObject
|
||||||
import hep.dataforge.vis.double
|
import hep.dataforge.vis.double
|
||||||
|
|
||||||
class Box(parent: DisplayObject?, meta: Meta) : DisplayObject3D(parent, TYPE, meta) {
|
class Box(parent: DisplayObject?, meta: Meta) : DisplayShape3D(parent, TYPE, meta) {
|
||||||
var xSize by double(1.0)
|
var xSize by double(1.0)
|
||||||
var ySize by double(1.0)
|
var ySize by double(1.0)
|
||||||
var zSize by double(1.0)
|
var zSize by double(1.0)
|
||||||
|
@ -7,18 +7,32 @@ import hep.dataforge.vis.*
|
|||||||
import hep.dataforge.vis.DisplayObject.Companion.DEFAULT_TYPE
|
import hep.dataforge.vis.DisplayObject.Companion.DEFAULT_TYPE
|
||||||
|
|
||||||
|
|
||||||
open class DisplayObject3D(parent: DisplayObject?, type: String, meta: Meta) : DisplayLeaf(parent, type, meta) {
|
interface DisplayObject3D : DisplayObject {
|
||||||
var x by double(0.0)
|
val x: Double
|
||||||
var y by double(0.0)
|
val y: Double
|
||||||
var z by double(0.0)
|
val z: Double
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TYPE = "geometry.spatial"
|
const val TYPE = "geometry.spatial"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open class DisplayShape3D(parent: DisplayObject?, type: String, meta: Meta) :
|
||||||
|
DisplayLeaf(parent, type, meta), DisplayObject3D {
|
||||||
|
override var x by double(0.0, inherited = false)
|
||||||
|
override var y by double(0.0, inherited = false)
|
||||||
|
override var z by double(0.0, inherited = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
class DisplayGroup3D(parent: DisplayObject?, type: String, meta: Meta) : DisplayNode(parent, type, meta),
|
||||||
|
DisplayObject3D {
|
||||||
|
override var x by double(0.0, inherited = false)
|
||||||
|
override var y by double(0.0, inherited = false)
|
||||||
|
override var z by double(0.0, inherited = false)
|
||||||
|
}
|
||||||
|
|
||||||
fun DisplayGroup.group(meta: Meta = EmptyMeta, action: DisplayGroup.() -> Unit = {}) =
|
fun DisplayGroup.group(meta: Meta = EmptyMeta, action: DisplayGroup.() -> Unit = {}) =
|
||||||
DisplayNode(this, DEFAULT_TYPE, meta).apply(action).also{addChild(it)}
|
DisplayNode(this, DEFAULT_TYPE, meta).apply(action).also { addChild(it) }
|
||||||
|
|
||||||
|
|
||||||
fun Output<DisplayObject>.render(meta: Meta = EmptyMeta, action: DisplayGroup.() -> Unit) =
|
fun Output<DisplayObject>.render(meta: Meta = EmptyMeta, action: DisplayGroup.() -> Unit) =
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import hep.dataforge.meta.EmptyMeta
|
||||||
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.vis.DisplayGroup
|
||||||
|
import hep.dataforge.vis.DisplayObject
|
||||||
|
|
||||||
|
class Extruded(parent: DisplayObject?, meta: Meta) : DisplayShape3D(parent, TYPE, meta) {
|
||||||
|
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TYPE = "geometry.spatial.extruded"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun DisplayGroup.extrude(meta: Meta = EmptyMeta, action: Extruded.() -> Unit = {}) =
|
||||||
|
Extruded(this, meta).apply(action).also { addChild(it) }
|
@ -5,6 +5,7 @@ import hep.dataforge.names.Name
|
|||||||
import hep.dataforge.names.toName
|
import hep.dataforge.names.toName
|
||||||
import hep.dataforge.values.Value
|
import hep.dataforge.values.Value
|
||||||
import kotlin.jvm.JvmName
|
import kotlin.jvm.JvmName
|
||||||
|
import kotlin.properties.ReadOnlyProperty
|
||||||
import kotlin.properties.ReadWriteProperty
|
import kotlin.properties.ReadWriteProperty
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
@ -95,4 +96,25 @@ fun DisplayObject.double(default: Double, key: String? = null, inherited: Boolea
|
|||||||
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.double }
|
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.double }
|
||||||
|
|
||||||
inline fun <reified E : Enum<E>> DisplayObject.enum(default: E, key: String? = null, inherited: Boolean = true) =
|
inline fun <reified E : Enum<E>> DisplayObject.enum(default: E, key: String? = null, inherited: Boolean = true) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { item -> item.string?.let { enumValueOf<E>(it) } }
|
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { item -> item.string?.let { enumValueOf<E>(it) } }
|
||||||
|
|
||||||
|
//merge properties
|
||||||
|
|
||||||
|
fun <T> DisplayObject.merge(
|
||||||
|
key: String? = null,
|
||||||
|
transformer: (Sequence<MetaItem<*>>) -> T
|
||||||
|
): ReadOnlyProperty<DisplayObject, T> {
|
||||||
|
return object : ReadOnlyProperty<DisplayObject, T> {
|
||||||
|
override fun getValue(thisRef: DisplayObject, property: KProperty<*>): T {
|
||||||
|
val name = key?.toName() ?: property.name.toName()
|
||||||
|
val sequence = sequence<MetaItem<*>> {
|
||||||
|
var thisObj: DisplayObject? = thisRef
|
||||||
|
while (thisObj != null) {
|
||||||
|
thisObj.properties[name]?.let { yield(it) }
|
||||||
|
thisObj = thisObj.parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return transformer(sequence)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,16 @@
|
|||||||
pluginManagement {
|
pluginManagement {
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
|
||||||
jcenter()
|
jcenter()
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
maven("https://dl.bintray.com/kotlin/kotlin-eap/")
|
maven("https://dl.bintray.com/kotlin/kotlin-eap")
|
||||||
}
|
}
|
||||||
resolutionStrategy {
|
resolutionStrategy {
|
||||||
eachPlugin {
|
eachPlugin {
|
||||||
when (requested.id.id) {
|
when (requested.id.id) {
|
||||||
"kotlinx-atomicfu" -> useModule("org.jetbrains.kotlinx:atomicfu-gradle-plugin:${requested.version}")
|
"kotlinx-atomicfu" -> useModule("org.jetbrains.kotlinx:atomicfu-gradle-plugin:${requested.version}")
|
||||||
"kotlin-multiplatform" -> useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
|
"kotlin-multiplatform" -> useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
|
||||||
"org.jetbrains.kotlin.frontend" -> useModule("org.jetbrains.kotlin:kotlin-frontend-plugin:0.0.45")
|
"kotlin2js" -> useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
|
||||||
|
"org.jetbrains.kotlin.frontend" -> useModule("org.jetbrains.kotlin:kotlin-frontend-plugin:0.0.45")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,5 +29,6 @@ include(
|
|||||||
":dataforge-scripting",
|
":dataforge-scripting",
|
||||||
":dataforge-vis",
|
":dataforge-vis",
|
||||||
":dataforge-vis:dataforge-vis-spatial",
|
":dataforge-vis:dataforge-vis-spatial",
|
||||||
":dataforge-vis:dataforge-vis-fx"
|
":dataforge-vis:dataforge-vis-spatial-fx",
|
||||||
)
|
":dataforge-vis:dataforge-vis-spatial-js"
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user