Some refactoring and new server demo

This commit is contained in:
Alexander Nozik 2023-07-25 13:35:55 +03:00
parent ed491bdae0
commit f5fba4747e
33 changed files with 215 additions and 93 deletions

View File

@ -6,6 +6,7 @@
- MeshLine for thick lines - MeshLine for thick lines
### Changed ### Changed
- Color accessor property is now `colorProperty`. Color uses `invoke` instead of `set`
- API update for server and pages - API update for server and pages
- Edges moved to solids module for easier construction - Edges moved to solids module for easier construction
- Visions **must** be rooted in order to subscribe to updates. - Visions **must** be rooted in order to subscribe to updates.
@ -20,6 +21,7 @@
### Removed ### Removed
### Fixed ### Fixed
- Jupyter integration for IDEA and Jupyter lab.
### Security ### Security

View File

@ -13,7 +13,7 @@ val fxVersion by extra("11")
allprojects { allprojects {
group = "space.kscience" group = "space.kscience"
version = "0.3.0-dev-12" version = "0.3.0-dev-13"
} }
subprojects { subprojects {

View File

@ -328,7 +328,7 @@ private fun buildVolume(volume: DGeoVolume, context: RootToSolidContext): Solid?
group group
}.apply { }.apply {
volume.fMedium?.let { medium -> volume.fMedium?.let { medium ->
color.set(context.colorCache.getOrPut(medium.meta) { RootColors[11 + context.colorCache.size] }) color(context.colorCache.getOrPut(medium.meta) { RootColors[11 + context.colorCache.size] })
} }
if (!context.ignoreRootColors) { if (!context.ignoreRootColors) {

View File

@ -23,7 +23,7 @@ import space.kscience.visionforge.setAsRoot
import space.kscience.visionforge.solid.Solid import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.set import space.kscience.visionforge.solid.invoke
import styled.css import styled.css
import styled.styledDiv import styled.styledDiv
@ -53,7 +53,7 @@ val GDMLApp = fc<GDMLAppProps>("GDMLApp") { props ->
console.info("Marking layers for file $name") console.info("Marking layers for file $name")
markLayers() markLayers()
ambientLight { ambientLight {
color.set(Colors.white) color(Colors.white)
} }
} }
} }

View File

@ -12,7 +12,7 @@ import space.kscience.visionforge.react.createRoot
import space.kscience.visionforge.react.render import space.kscience.visionforge.react.render
import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.set import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.three.ThreePlugin import space.kscience.visionforge.solid.three.ThreePlugin
import space.kscience.visionforge.startApplication import space.kscience.visionforge.startApplication
import styled.injectGlobal import styled.injectGlobal
@ -49,7 +49,7 @@ private class GDMLDemoApp : Application {
child(GDMLApp) { child(GDMLApp) {
val vision = GdmlShowCase.cubes().toVision().apply { val vision = GdmlShowCase.cubes().toVision().apply {
ambientLight { ambientLight {
color.set(Colors.white) color(Colors.white)
} }
} }
//println(context.plugins.fetch(VisionManager).encodeToString(vision)) //println(context.plugins.fetch(VisionManager).encodeToString(vision))

View File

@ -76,7 +76,7 @@ private class JsPlaygroundApp : Application {
solids = playgroundContext.request(Solids) solids = playgroundContext.request(Solids)
solid { solid {
ambientLight { ambientLight {
color.set(Colors.white) color(Colors.white)
} }
repeat(100) { repeat(100) {
sphere(5, name = "sphere[$it]") { sphere(5, name = "sphere[$it]") {
@ -84,7 +84,7 @@ private class JsPlaygroundApp : Application {
y = random.nextDouble(-300.0, 300.0) y = random.nextDouble(-300.0, 300.0)
z = random.nextDouble(-300.0, 300.0) z = random.nextDouble(-300.0, 300.0)
material { material {
color.set(random.nextInt()) color(random.nextInt())
} }
detail = 16 detail = 16
} }

View File

@ -42,13 +42,13 @@ val GravityDemo = fc<DemoProps> { props ->
solids = props.solids solids = props.solids
solid { solid {
pointLight(200, 200, 200, name = "light"){ pointLight(200, 200, 200, name = "light"){
color.set(Colors.white) color(Colors.white)
} }
ambientLight() ambientLight()
sphere(5.0, "ball") { sphere(5.0, "ball") {
detail = 16 detail = 16
color.set("red") color("red")
val h = 100.0 val h = 100.0
y = h y = h
solids.context.launch { solids.context.launch {

View File

@ -39,7 +39,7 @@ class Model(val manager: VisionManager) {
val root: SolidGroup = SolidGroup().apply { val root: SolidGroup = SolidGroup().apply {
setAsRoot(this@Model.manager) setAsRoot(this@Model.manager)
material { material {
color.set("darkgreen") color("darkgreen")
} }
rotationX = PI / 2 rotationX = PI / 2
solidGroup("bottom") { solidGroup("bottom") {
@ -64,7 +64,7 @@ class Model(val manager: VisionManager) {
private fun highlight(pixel: String) { private fun highlight(pixel: String) {
println("highlight $pixel") println("highlight $pixel")
map[pixel]?.color.set("blue") map[pixel]?.color("blue")
} }
fun reset() { fun reset() {
@ -82,7 +82,7 @@ class Model(val manager: VisionManager) {
} }
event.track?.let { event.track?.let {
tracks.polyline(*it.toTypedArray(), name = "track[${event.id}]") { tracks.polyline(*it.toTypedArray(), name = "track[${event.id}]") {
color.set("red") color("red")
} }
} }
} }

View File

@ -26,7 +26,7 @@ import space.kscience.visionforge.ring.tab
import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.edges import space.kscience.visionforge.solid.edges
import space.kscience.visionforge.solid.set import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.specifications.Canvas3DOptions import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import styled.css import styled.css
import styled.styledDiv import styled.styledDiv
@ -58,7 +58,7 @@ val MMApp = fc<MMAppProps>("Muon monitor") { props ->
props.model.root.apply { props.model.root.apply {
edges() edges()
ambientLight{ ambientLight{
color.set(Colors.white) color(Colors.white)
} }
} }
} }

View File

@ -1,16 +1,19 @@
package space.kscience.visionforge.examples package space.kscience.visionforge.examples
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import space.kscience.dataforge.meta.configure
import space.kscience.kmath.complex.Quaternion import space.kscience.kmath.complex.Quaternion
import space.kscience.kmath.complex.QuaternionField import space.kscience.kmath.complex.QuaternionField
import space.kscience.kmath.geometry.Angle import space.kscience.kmath.complex.conjugate
import space.kscience.kmath.geometry.Euclidean3DSpace import space.kscience.kmath.geometry.*
import space.kscience.kmath.geometry.degrees
import space.kscience.kmath.geometry.fromRotation
import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.solid.* import space.kscience.visionforge.solid.*
import kotlin.math.PI import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin
fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) { fun main() = serve {
val azimuth = 60.degrees val azimuth = 60.degrees
val inclination = 15.degrees val inclination = 15.degrees
@ -22,19 +25,26 @@ fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
//val direction2 = Quaternion.fromEuler(Angle.zero, Angle.piDiv2 - inclination, -azimuth, RotationOrder.ZYX) //val direction2 = Quaternion.fromEuler(Angle.zero, Angle.piDiv2 - inclination, -azimuth, RotationOrder.ZYX)
val target = Quaternion.fromEuler((-45).degrees, 45.degrees, Angle.zero, RotationOrder.XYZ)
vision("canvas") { vision("canvas") {
requirePlugin(Solids) requirePlugin(Solids)
solid {
solid(options = {
configure { "controls.enabled" put false }
}) {
rotationX = -PI / 2 rotationX = -PI / 2
rotationZ = PI rotationZ = PI
axes(200) //axes(200)
ambientLight() ambientLight()
val platform = solidGroup("platform") {
cylinder(50, 5, name = "base") cylinder(50, 5, name = "base")
solidGroup("frame") { solidGroup("frame") {
z = 60 z = 60
val antenna = solidGroup("antenna") {
axes(200) axes(200)
solidGroup("antenna") {
tube(40, 10, 30) tube(40, 10, 30)
sphereLayer(100, 95, theta = PI / 6) { sphereLayer(100, 95, theta = PI / 6) {
z = 100 z = 100
@ -43,7 +53,48 @@ fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
cylinder(5, 30) { cylinder(5, 30) {
z = 15 z = 15
} }
quaternion = direction
sphereLayer(101, 94, phi = PI / 32, theta = PI / 6) {
z = 100
rotationX = -PI / 2
color("red")
}
quaternion = target
}
}
}
val frame = platform["frame"] as SolidGroup
val antenna = frame["antenna"] as SolidGroup
val xPeriod = 5000 //ms
val yPeriod = 7000 //ms
val incRot = Quaternion.fromRotation(30.degrees, Euclidean3DSpace.zAxis)
val rotationJob = context.launch {
var time: Long = 0L
while (isActive) {
with(QuaternionField) {
delay(200)
platform.quaternion = Quaternion.fromRotation(
15.degrees * sin(time.toDouble() * 2 * PI / xPeriod),
Euclidean3DSpace.xAxis
) * Quaternion.fromRotation(
15.degrees * cos(time * 2 * PI / yPeriod),
Euclidean3DSpace.yAxis
)
val qi = platform.quaternion * incRot
antenna.quaternion = qi.conjugate * incRot.conjugate * target
time += 200
//antenna.quaternion = Quaternion.fromRotation(5.degrees, Euclidean3DSpace.zAxis) * antenna.quaternion
}
} }
} }
} }

View File

@ -7,7 +7,7 @@ import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.html.ResourceLocation import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.color import space.kscience.visionforge.solid.color
import space.kscience.visionforge.solid.set import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.visible import space.kscience.visionforge.visible
import java.nio.file.Path import java.nio.file.Path
@ -229,7 +229,7 @@ fun main() = makeVisionFile(Path.of("curves.html"), resourceLocation = ResourceL
visible = false visible = false
} }
if(solid.name.startsWith("gas")){ if(solid.name.startsWith("gas")){
color.set("green") color("green")
} else { } else {
//make all solids semi-transparent //make all solids semi-transparent
transparent() transparent()

View File

@ -19,7 +19,7 @@ fun main() = makeVisionFile(
vision { vision {
solid { solid {
ambientLight { ambientLight {
color.set(Colors.white) color(Colors.white)
} }
repeat(100) { repeat(100) {
sphere(5, name = "sphere[$it]") { sphere(5, name = "sphere[$it]") {
@ -27,7 +27,7 @@ fun main() = makeVisionFile(
y = random.nextDouble(-300.0, 300.0) y = random.nextDouble(-300.0, 300.0)
z = random.nextDouble(-300.0, 300.0) z = random.nextDouble(-300.0, 300.0)
material { material {
color.set(random.nextInt()) color(random.nextInt())
} }
detail = 16 detail = 16
} }

View File

@ -11,7 +11,7 @@ import space.kscience.visionforge.Colors
import space.kscience.visionforge.html.ResourceLocation import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.set import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.solid import space.kscience.visionforge.solid.solid
import java.util.zip.ZipInputStream import java.util.zip.ZipInputStream
import kotlin.io.path.Path import kotlin.io.path.Path
@ -44,7 +44,7 @@ fun main() {
requirePlugin(Solids) requirePlugin(Solids)
solid { solid {
ambientLight { ambientLight {
color.set(Colors.white) color(Colors.white)
} }
rootGeo(geo,"BM@N", maxLayer = 3, ignoreRootColors = true).also { rootGeo(geo,"BM@N", maxLayer = 3, ignoreRootColors = true).also {
Path("data/BM@N.vf.json").writeText(Solids.encodeToString(it)) Path("data/BM@N.vf.json").writeText(Solids.encodeToString(it))

View File

@ -1,11 +1,24 @@
package space.kscience.visionforge.examples package space.kscience.visionforge.examples
import io.ktor.server.cio.CIO
import io.ktor.server.engine.embeddedServer
import io.ktor.server.http.content.staticResources
import io.ktor.server.routing.routing
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.Global import space.kscience.dataforge.context.Global
import space.kscience.visionforge.html.* import space.kscience.visionforge.html.*
import space.kscience.visionforge.markup.MarkupPlugin
import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.server.close
import space.kscience.visionforge.server.openInBrowser
import space.kscience.visionforge.server.visionPage
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.tables.TableVisionPlugin
import space.kscience.visionforge.visionManager import space.kscience.visionforge.visionManager
import java.awt.Desktop import java.awt.Desktop
import java.nio.file.Path import java.nio.file.Path
public fun makeVisionFile( public fun makeVisionFile(
path: Path? = null, path: Path? = null,
title: String = "VisionForge page", title: String = "VisionForge page",
@ -26,6 +39,45 @@ public fun makeVisionFile(
if (show) Desktop.getDesktop().browse(actualPath.toFile().toURI()) if (show) Desktop.getDesktop().browse(actualPath.toFile().toURI())
} }
public fun serve(
title: String = "VisionForge page",
show: Boolean = true,
content: HtmlVisionFragment,
) {
val context = Context("playground") {
plugin(Solids)
plugin(PlotlyPlugin)
plugin(MarkupPlugin)
plugin(TableVisionPlugin)
}
val server = embeddedServer(CIO, port = 7779) {
routing {
staticResources("", null, null)
}
visionPage(
context.visionManager,
VisionPage.scriptHeader("js/visionforge-playground.js") {
defer = true
},
VisionPage.title(title),
visionFragment = content
)
}.start(false)
if (show) {
server.openInBrowser()
}
println("Enter 'exit' to close server")
while (readlnOrNull() != "exit") {
//
}
server.close()
}
//@DFExperimental //@DFExperimental
//public fun Context.makeVisionFile( //public fun Context.makeVisionFile(
// vision: Vision, // vision: Vision,

View File

@ -10,23 +10,23 @@ fun main() = makeVisionFile {
ambientLight() ambientLight()
box(100.0, 100.0, 100.0) { box(100.0, 100.0, 100.0) {
z = -110.0 z = -110.0
color.set("teal") color("teal")
} }
sphere(50.0) { sphere(50.0) {
x = 110 x = 110
detail = 16 detail = 16
color.set("red") color("red")
} }
tube(50, height = 10, innerRadius = 25, angle = PI) { tube(50, height = 10, innerRadius = 25, angle = PI) {
y = 110 y = 110
detail = 16 detail = 16
rotationX = PI / 4 rotationX = PI / 4
color.set("blue") color("blue")
} }
sphereLayer(50, 40, theta = PI / 2) { sphereLayer(50, 40, theta = PI / 2) {
rotationX = -PI * 3 / 4 rotationX = -PI * 3 / 4
z = 110 z = 110
color.set(Colors.pink) color(Colors.pink)
} }

View File

@ -2,8 +2,8 @@ package space.kscience.visionforge.examples
import space.kscience.visionforge.html.ResourceLocation import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.solid.box import space.kscience.visionforge.solid.box
import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.material import space.kscience.visionforge.solid.material
import space.kscience.visionforge.solid.set
import space.kscience.visionforge.solid.solid import space.kscience.visionforge.solid.solid
fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) { fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
@ -11,7 +11,7 @@ fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
solid { solid {
box(100, 100, 100) box(100, 100, 100)
material { material {
emissiveColor.set("red") emissiveColor("red")
} }
} }
} }

View File

@ -15,7 +15,7 @@ internal fun Solids.visionOfSatellite(
ySegmentSize: Number = xSegmentSize, ySegmentSize: Number = xSegmentSize,
fiberDiameter: Number = 1.0, fiberDiameter: Number = 1.0,
): SolidGroup = solidGroup { ): SolidGroup = solidGroup {
color.set("darkgreen") color("darkgreen")
val transparent by style { val transparent by style {
this[SolidMaterial.MATERIAL_OPACITY_KEY] = 0.3 this[SolidMaterial.MATERIAL_OPACITY_KEY] = 0.3
} }

View File

@ -33,7 +33,7 @@ fun main() {
//Create a geometry //Create a geometry
val sat = solids.visionOfSatellite(ySegments = 3).apply { val sat = solids.visionOfSatellite(ySegments = 3).apply {
ambientLight { ambientLight {
color.set(Colors.white) color(Colors.white)
} }
} }
val server = embeddedServer(CIO, port = 7777) { val server = embeddedServer(CIO, port = 7777) {
@ -63,7 +63,7 @@ fun main() {
val randomJ = Random.nextInt(1, 4) val randomJ = Random.nextInt(1, 4)
val target = Name.parse("layer[$randomLayer].segment[$randomI,$randomJ]") val target = Name.parse("layer[$randomLayer].segment[$randomI,$randomJ]")
val targetVision = sat[target] as Solid val targetVision = sat[target] as Solid
targetVision.color.set("red") targetVision.color("red")
delay(1000) delay(1000)
//use to ensure that color is cleared //use to ensure that color is cleared
targetVision.color.value = Null targetVision.color.value = Null

View File

@ -3,8 +3,8 @@ package ru.mipt.npm.sat
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
import space.kscience.visionforge.html.ResourceLocation import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.solid.box import space.kscience.visionforge.solid.box
import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.material import space.kscience.visionforge.solid.material
import space.kscience.visionforge.solid.set
import space.kscience.visionforge.solid.solid import space.kscience.visionforge.solid.solid
import space.kscience.visionforge.three.makeThreeJsFile import space.kscience.visionforge.three.makeThreeJsFile
@ -14,7 +14,7 @@ fun main() = makeThreeJsFile(resourceLocation = ResourceLocation.SYSTEM) {
solid { solid {
box(100, 100, 100) box(100, 100, 100)
material { material {
emissiveColor.set("red") emissiveColor("red")
} }
} }
} }

View File

@ -23,7 +23,7 @@ fun VisionLayout<Solid>.demo(name: String, title: String = name, block: SolidGro
val vision = solids.solidGroup { val vision = solids.solidGroup {
block() block()
ambientLight { ambientLight {
color.set(Colors.white) color(Colors.white)
} }
} }
render(Name.parse(name), vision, meta) render(Name.parse(name), vision, meta)
@ -49,23 +49,23 @@ fun VisionLayout<Solid>.showcase() {
ambientLight() ambientLight()
box(100.0, 100.0, 100.0) { box(100.0, 100.0, 100.0) {
z = -110.0 z = -110.0
color.set("teal") color("teal")
} }
sphere(50.0) { sphere(50.0) {
x = 110 x = 110
detail = 16 detail = 16
color.set("red") color("red")
} }
tube(50, height = 10, innerRadius = 25, angle = PI) { tube(50, height = 10, innerRadius = 25, angle = PI) {
y = 110 y = 110
detail = 16 detail = 16
rotationX = PI / 4 rotationX = PI / 4
color.set("blue") color("blue")
} }
sphereLayer(50, 40, theta = PI / 2) { sphereLayer(50, 40, theta = PI / 2) {
rotationX = -PI * 3 / 4 rotationX = -PI * 3 / 4
z = 110 z = 110
color.set(Colors.pink) color(Colors.pink)
} }
} }
@ -80,7 +80,7 @@ fun VisionLayout<Solid>.showcase() {
visible = false visible = false
x = 110.0 x = 110.0
//override color for this cube //override color for this cube
color.set(1530) color(1530)
GlobalScope.launch(Dispatchers.Main) { GlobalScope.launch(Dispatchers.Main) {
while (isActive) { while (isActive) {
@ -95,7 +95,7 @@ fun VisionLayout<Solid>.showcase() {
val random = Random(111) val random = Random(111)
while (isActive) { while (isActive) {
delay(1000) delay(1000)
group.color.set(random.nextInt(0, Int.MAX_VALUE)) group.color(random.nextInt(0, Int.MAX_VALUE))
} }
} }
} }
@ -114,7 +114,7 @@ fun VisionLayout<Solid>.showcase() {
rotate((PI/20).radians,Euclidean3DSpace.yAxis) rotate((PI/20).radians,Euclidean3DSpace.yAxis)
} }
} }
color.set(Colors.red) color(Colors.red)
} }
} }
} }
@ -127,7 +127,7 @@ fun VisionLayout<Solid>.showcase() {
for (i in 0..100) { for (i in 0..100) {
layer(i * 5, 20 * sin(2 * PI / 100 * i), 20 * cos(2 * PI / 100 * i)) layer(i * 5, 20 * sin(2 * PI / 100 * i), 20 * cos(2 * PI / 100 * i))
} }
color.set(Colors.teal) color(Colors.teal)
rotationX = -PI / 2 rotationX = -PI / 2
} }
} }
@ -136,7 +136,7 @@ fun VisionLayout<Solid>.showcase() {
sphere(100) { sphere(100) {
detail = 32 detail = 32
opacity = 0.4 opacity = 0.4
color.set(Colors.blue) color(Colors.blue)
} }
repeat(20) { repeat(20) {
polyline( polyline(
@ -145,7 +145,7 @@ fun VisionLayout<Solid>.showcase() {
) { ) {
thickness = 3.0 thickness = 3.0
rotationX = it * PI2 / 20 rotationX = it * PI2 / 20
color.set(Colors.green) color(Colors.green)
//rotationY = it * PI2 / 20 //rotationY = it * PI2 / 20
} }
} }
@ -176,7 +176,7 @@ fun VisionLayout<Solid>.showcaseCSG() {
detail = 32 detail = 32
} }
material { material {
color.set(Colors.pink) color(Colors.pink)
} }
} }
composite(CompositeType.UNION) { composite(CompositeType.UNION) {
@ -186,7 +186,7 @@ fun VisionLayout<Solid>.showcaseCSG() {
sphere(50) { sphere(50) {
detail = 32 detail = 32
} }
color.set("lightgreen") color("lightgreen")
opacity = 0.7 opacity = 0.7
} }
composite(CompositeType.SUBTRACT) { composite(CompositeType.SUBTRACT) {
@ -197,7 +197,7 @@ fun VisionLayout<Solid>.showcaseCSG() {
sphere(50) { sphere(50) {
detail = 32 detail = 32
} }
color.set("teal") color("teal")
opacity = 0.7 opacity = 0.7
} }
} }
@ -208,7 +208,7 @@ fun VisionLayout<Solid>.showcaseCSG() {
detail = 32 detail = 32
} }
box(100, 100, 100) box(100, 100, 100)
color.set("red") color("red")
opacity = 0.5 opacity = 0.5
} }
} }

View File

@ -7,12 +7,15 @@ import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.PluginFactory import space.kscience.dataforge.context.PluginFactory
import space.kscience.dataforge.context.PluginTag import space.kscience.dataforge.context.PluginTag
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.boolean
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.asName
import space.kscience.visionforge.ElementVisionRenderer import space.kscience.visionforge.ElementVisionRenderer
import space.kscience.visionforge.Vision import space.kscience.visionforge.Vision
import space.kscience.visionforge.react.render import space.kscience.visionforge.react.render
import space.kscience.visionforge.solid.Solid import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.solid.three.ThreePlugin import space.kscience.visionforge.solid.three.ThreePlugin
public class ThreeWithControlsPlugin : AbstractPlugin(), ElementVisionRenderer { public class ThreeWithControlsPlugin : AbstractPlugin(), ElementVisionRenderer {
@ -24,11 +27,16 @@ public class ThreeWithControlsPlugin : AbstractPlugin(), ElementVisionRenderer {
if (vision is Solid) ElementVisionRenderer.DEFAULT_RATING * 2 else ElementVisionRenderer.ZERO_RATING if (vision is Solid) ElementVisionRenderer.DEFAULT_RATING * 2 else ElementVisionRenderer.ZERO_RATING
override fun render(element: Element, name: Name, vision: Vision, meta: Meta) { override fun render(element: Element, name: Name, vision: Vision, meta: Meta) {
if(meta["controls.enabled"].boolean == false){
three.render(element, name, vision, meta)
} else {
space.kscience.visionforge.react.createRoot(element).render { space.kscience.visionforge.react.createRoot(element).render {
child(ThreeCanvasWithControls) { child(ThreeCanvasWithControls) {
attrs { attrs {
this.solids = three.solids this.solids = three.solids
this.builderOfSolid = context.async { vision as Solid} this.options = Canvas3DOptions.read(meta)
this.builderOfSolid = context.async { vision as Solid }
}
} }
} }
} }

View File

@ -42,7 +42,7 @@ public class GdmlLoaderOptions {
* Configure paint for given solid with given [GdmlMaterial] * Configure paint for given solid with given [GdmlMaterial]
*/ */
public var configurePaint: SolidMaterial.(material: GdmlMaterial, solid: GdmlSolid) -> Unit = public var configurePaint: SolidMaterial.(material: GdmlMaterial, solid: GdmlSolid) -> Unit =
{ material, _ -> color.set(randomColor(material)) } { material, _ -> color(randomColor(material)) }
private set private set
public fun paint(block: SolidMaterial.(material: GdmlMaterial, solid: GdmlSolid) -> Unit) { public fun paint(block: SolidMaterial.(material: GdmlMaterial, solid: GdmlSolid) -> Unit) {

View File

@ -57,7 +57,7 @@ public class VisionRoute(
override val context: Context get() = visionManager.context override val context: Context get() = visionManager.context
/** /**
* Update minimal interval between updates in milliseconds (if there are no updates, push will not happen * Update the minimal interval between updates in milliseconds (if there are no updates, push will not happen
*/ */
public var updateInterval: Long by meta.long(300, key = UPDATE_INTERVAL_KEY) public var updateInterval: Long by meta.long(300, key = UPDATE_INTERVAL_KEY)
@ -170,8 +170,8 @@ public fun Application.visionPage(
meta { meta {
charset = "utf-8" charset = "utf-8"
} }
headers.forEach { header -> headers.forEach { headerContent ->
consumer.header() headerContent.appendTo(consumer)
} }
} }
body { body {

View File

@ -28,7 +28,7 @@ public class ColorAccessor(
} }
} }
public fun Vision.color( public fun Vision.colorProperty(
propertyName: Name? = null, propertyName: Name? = null,
): ReadOnlyProperty<Vision, ColorAccessor> = ReadOnlyProperty { _, property -> ): ReadOnlyProperty<Vision, ColorAccessor> = ReadOnlyProperty { _, property ->
ColorAccessor(properties.root(true), propertyName ?: property.name.asName()) ColorAccessor(properties.root(true), propertyName ?: property.name.asName())
@ -43,21 +43,21 @@ public var ColorAccessor?.string: String?
/** /**
* Set [webcolor](https://en.wikipedia.org/wiki/Web_colors) as string * Set [webcolor](https://en.wikipedia.org/wiki/Web_colors) as string
*/ */
public fun ColorAccessor?.set(webColor: String) { public operator fun ColorAccessor?.invoke(webColor: String) {
this?.value = webColor.asValue() this?.value = webColor.asValue()
} }
/** /**
* Set color as RGB integer * Set color as RGB integer
*/ */
public fun ColorAccessor?.set(rgb: Int) { public operator fun ColorAccessor?.invoke(rgb: Int) {
this?.value = Colors.rgbToString(rgb).asValue() this?.value = Colors.rgbToString(rgb).asValue()
} }
/** /**
* Set color as RGB * Set color as RGB
*/ */
public fun ColorAccessor?.set(r: UByte, g: UByte, b: UByte) { public operator fun ColorAccessor?.invoke(r: UByte, g: UByte, b: UByte) {
this?.value = Colors.rgbToString(r, g, b).asValue() this?.value = Colors.rgbToString(r, g, b).asValue()
} }

View File

@ -15,7 +15,7 @@ import space.kscience.visionforge.*
public abstract class LightSource : SolidBase<LightSource>() { public abstract class LightSource : SolidBase<LightSource>() {
override val descriptor: MetaDescriptor get() = LightSource.descriptor override val descriptor: MetaDescriptor get() = LightSource.descriptor
public val color: ColorAccessor by color(SolidMaterial.COLOR_KEY) public val color: ColorAccessor by colorProperty(SolidMaterial.COLOR_KEY)
public var intensity: Number by properties.root(includeStyles = false).number(INTENSITY_KEY) { 1.0 } public var intensity: Number by properties.root(includeStyles = false).number(INTENSITY_KEY) { 1.0 }
public companion object { public companion object {

View File

@ -43,6 +43,9 @@ public class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder, Mutable
it to value it to value
}.toMap() }.toMap()
/**
* Get a child solid with given relative [name] if it exists
*/
public operator fun get(name: Name): Solid? = children.getChild(name) as? Solid public operator fun get(name: Name): Solid? = children.getChild(name) as? Solid
private var prototypes: SolidGroup? private var prototypes: SolidGroup?
@ -84,6 +87,8 @@ public class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder, Mutable
} }
} }
public operator fun SolidGroup.get(name:String): Solid? = get(name.parseAsName())
@VisionBuilder @VisionBuilder
public inline fun MutableVisionContainer<Solid>.solidGroup( public inline fun MutableVisionContainer<Solid>.solidGroup(
name: Name? = null, name: Name? = null,

View File

@ -94,3 +94,7 @@ public inline fun VisionOutput.solid(options: Canvas3DOptions? = null, block: So
} }
} }
} }
@VisionBuilder
public inline fun VisionOutput.solid(options: Canvas3DOptions.() -> Unit, block: SolidGroup.() -> Unit): SolidGroup =
solid(Canvas3DOptions(options), block)

View File

@ -18,7 +18,7 @@ class CompositeTest {
detail = 32 detail = 32
} }
material { material {
color.set("pink") color("pink")
} }
} }
} }

View File

@ -18,7 +18,7 @@ class GroupTest {
} }
box(100, 100, 100) box(100, 100, 100)
material { material {
color.set(Colors.lightgreen) color(Colors.lightgreen)
opacity = 0.3f opacity = 0.3f
} }
} }
@ -30,7 +30,7 @@ class GroupTest {
} }
box(100, 100, 100) box(100, 100, 100)
y = 300 y = 300
color.set(Colors.red) color(Colors.red)
} }
subtract("subtract") { subtract("subtract") {
box(100, 100, 100) { box(100, 100, 100) {
@ -40,7 +40,7 @@ class GroupTest {
} }
box(100, 100, 100) box(100, 100, 100)
y = -300 y = -300
color.set(Colors.blue) color(Colors.blue)
} }
} }

View File

@ -24,7 +24,7 @@ class SerializationTest {
@Test @Test
fun testCubeSerialization() { fun testCubeSerialization() {
val cube = Box(100f, 100f, 100f).apply { val cube = Box(100f, 100f, 100f).apply {
color.set(222) color(222)
x = 100 x = 100
z = -100 z = -100
} }
@ -37,7 +37,7 @@ class SerializationTest {
@Test @Test
fun testProxySerialization() { fun testProxySerialization() {
val cube = Box(100f, 100f, 100f).apply { val cube = Box(100f, 100f, 100f).apply {
color.set(222) color(222)
x = 100 x = 100
z = -100 z = -100
} }
@ -59,7 +59,7 @@ class SerializationTest {
fun lightSerialization(){ fun lightSerialization(){
val group = testSolids.solidGroup { val group = testSolids.solidGroup {
ambientLight { ambientLight {
color.set(Colors.white) color(Colors.white)
intensity = 100.0 intensity = 100.0
} }
} }

View File

@ -20,7 +20,7 @@ class SolidPropertyTest {
val box = Box(10.0f, 10.0f, 10.0f) val box = Box(10.0f, 10.0f, 10.0f)
box.material { box.material {
//meta["color"] = "pink" //meta["color"] = "pink"
color.set("pink") color("pink")
} }
assertEquals("pink", box.properties.getValue("material.color")?.string) assertEquals("pink", box.properties.getValue("material.color")?.string)
assertEquals("pink", box.color.string) assertEquals("pink", box.color.string)
@ -41,7 +41,7 @@ class SolidPropertyTest {
delay(5) delay(5)
box.material { box.material {
color.set("pink") color("pink")
} }
assertEquals("pink", c.await()) assertEquals("pink", c.await())

View File

@ -16,7 +16,7 @@ class SolidReferenceTest {
SolidMaterial.MATERIAL_COLOR_KEY put "red" SolidMaterial.MATERIAL_COLOR_KEY put "red"
} }
newRef("test", Box(100f,100f,100f).apply { newRef("test", Box(100f,100f,100f).apply {
color.set("blue") color("blue")
useStyle(theStyle) useStyle(theStyle)
}) })
} }

View File

@ -22,7 +22,7 @@ internal class VisionUpdateTest {
} }
val dif = visionManager.VisionChange { val dif = visionManager.VisionChange {
solidGroup("top") { solidGroup("top") {
color.set(123) color(123)
box(100, 100, 100) box(100, 100, 100)
} }
propertyChanged("top".asName(), SolidMaterial.MATERIAL_COLOR_KEY, Meta("red".asValue())) propertyChanged("top".asName(), SolidMaterial.MATERIAL_COLOR_KEY, Meta("red".asValue()))
@ -41,7 +41,7 @@ internal class VisionUpdateTest {
fun testVisionChangeSerialization() { fun testVisionChangeSerialization() {
val change = visionManager.VisionChange { val change = visionManager.VisionChange {
solidGroup("top") { solidGroup("top") {
color.set(123) color(123)
box(100, 100, 100) box(100, 100, 100)
} }
propertyChanged("top".asName(), SolidMaterial.MATERIAL_COLOR_KEY, Meta("red".asValue())) propertyChanged("top".asName(), SolidMaterial.MATERIAL_COLOR_KEY, Meta("red".asValue()))