forked from kscience/visionforge
Add solids configuration to vision builder
This commit is contained in:
parent
f6f74b54f6
commit
18c39fc076
@ -13,7 +13,7 @@ val fxVersion by extra("11")
|
|||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
group = "space.kscience"
|
group = "space.kscience"
|
||||||
version = "0.3.0-dev-8"
|
version = "0.3.0-dev-9"
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
|
11
demo/build.gradle.kts
Normal file
11
demo/build.gradle.kts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper
|
||||||
|
|
||||||
|
subprojects {
|
||||||
|
plugins.withType<KotlinPluginWrapper> {
|
||||||
|
configure<KotlinProjectExtension> {
|
||||||
|
explicitApi = ExplicitApiMode.Disabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -30,6 +30,10 @@ kscience {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
explicitApi = null
|
||||||
|
}
|
||||||
|
|
||||||
//kotlin {
|
//kotlin {
|
||||||
//
|
//
|
||||||
// sourceSets {
|
// sourceSets {
|
||||||
|
@ -2,7 +2,7 @@ package space.kscience.visionforge.examples
|
|||||||
|
|
||||||
import io.ktor.server.cio.CIO
|
import io.ktor.server.cio.CIO
|
||||||
import io.ktor.server.engine.embeddedServer
|
import io.ktor.server.engine.embeddedServer
|
||||||
import io.ktor.server.http.content.resources
|
import io.ktor.server.http.content.staticResources
|
||||||
import io.ktor.server.routing.routing
|
import io.ktor.server.routing.routing
|
||||||
import kotlinx.html.*
|
import kotlinx.html.*
|
||||||
import space.kscience.dataforge.context.Global
|
import space.kscience.dataforge.context.Global
|
||||||
@ -12,21 +12,18 @@ import space.kscience.visionforge.html.VisionOfHtmlForm
|
|||||||
import space.kscience.visionforge.html.VisionPage
|
import space.kscience.visionforge.html.VisionPage
|
||||||
import space.kscience.visionforge.html.bindForm
|
import space.kscience.visionforge.html.bindForm
|
||||||
import space.kscience.visionforge.onPropertyChange
|
import space.kscience.visionforge.onPropertyChange
|
||||||
import space.kscience.visionforge.server.EngineConnectorConfig
|
|
||||||
import space.kscience.visionforge.server.close
|
import space.kscience.visionforge.server.close
|
||||||
import space.kscience.visionforge.server.openInBrowser
|
import space.kscience.visionforge.server.openInBrowser
|
||||||
import space.kscience.visionforge.server.visionPage
|
import space.kscience.visionforge.server.visionPage
|
||||||
|
|
||||||
|
@Suppress("ExtractKtorModule")
|
||||||
fun main() {
|
fun main() {
|
||||||
val visionManager = Global.request(VisionManager)
|
val visionManager = Global.request(VisionManager)
|
||||||
|
|
||||||
|
val server = embeddedServer(CIO) {
|
||||||
val connector = EngineConnectorConfig("localhost", 7777)
|
|
||||||
|
|
||||||
val server = embeddedServer(CIO, connector.port, connector.host) {
|
|
||||||
|
|
||||||
routing {
|
routing {
|
||||||
resources()
|
staticResources("/", null)
|
||||||
}
|
}
|
||||||
|
|
||||||
val form = VisionOfHtmlForm("form").apply {
|
val form = VisionOfHtmlForm("form").apply {
|
||||||
@ -36,7 +33,6 @@ fun main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
visionPage(
|
visionPage(
|
||||||
connector,
|
|
||||||
visionManager,
|
visionManager,
|
||||||
VisionPage.scriptHeader("js/visionforge-playground.js"),
|
VisionPage.scriptHeader("js/visionforge-playground.js"),
|
||||||
) {
|
) {
|
||||||
|
@ -33,6 +33,7 @@ fun main() = makeVisionFile {
|
|||||||
cylinder(30,20, name = "cylinder"){
|
cylinder(30,20, name = "cylinder"){
|
||||||
detail = 31
|
detail = 31
|
||||||
y = -220
|
y = -220
|
||||||
|
z = 15
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@ import space.kscience.dataforge.meta.Null
|
|||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.visionforge.Colors
|
import space.kscience.visionforge.Colors
|
||||||
import space.kscience.visionforge.html.VisionPage
|
import space.kscience.visionforge.html.VisionPage
|
||||||
import space.kscience.visionforge.server.EngineConnectorConfig
|
|
||||||
import space.kscience.visionforge.server.close
|
import space.kscience.visionforge.server.close
|
||||||
import space.kscience.visionforge.server.openInBrowser
|
import space.kscience.visionforge.server.openInBrowser
|
||||||
import space.kscience.visionforge.server.visionPage
|
import space.kscience.visionforge.server.visionPage
|
||||||
@ -23,6 +22,7 @@ import space.kscience.visionforge.three.threeJsHeader
|
|||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
|
||||||
|
@Suppress("ExtractKtorModule")
|
||||||
fun main() {
|
fun main() {
|
||||||
val satContext = Context("sat") {
|
val satContext = Context("sat") {
|
||||||
plugin(Solids)
|
plugin(Solids)
|
||||||
@ -36,15 +36,12 @@ fun main() {
|
|||||||
color.set(Colors.white)
|
color.set(Colors.white)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val connector = EngineConnectorConfig("localhost", 7777)
|
val server = embeddedServer(CIO, port = 7777) {
|
||||||
|
|
||||||
val server = embeddedServer(CIO, connector.port, connector.host) {
|
|
||||||
routing {
|
routing {
|
||||||
staticResources("", null, null)
|
staticResources("", null, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
visionPage(
|
visionPage(
|
||||||
connector,
|
|
||||||
solids.visionManager, VisionPage.threeJsHeader,
|
solids.visionManager, VisionPage.threeJsHeader,
|
||||||
VisionPage.styleSheetHeader("css/styles.css")
|
VisionPage.styleSheetHeader("css/styles.css")
|
||||||
) {
|
) {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("space.kscience.gradle.mpp")
|
id("space.kscience.gradle.mpp")
|
||||||
`maven-publish`
|
|
||||||
application
|
application
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,7 +22,3 @@ kscience {
|
|||||||
application {
|
application {
|
||||||
mainClass.set("space.kscience.visionforge.solid.demo.FXDemoAppKt")
|
mainClass.set("space.kscience.visionforge.solid.demo.FXDemoAppKt")
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin{
|
|
||||||
explicitApi = null
|
|
||||||
}
|
|
@ -20,7 +20,6 @@ import kotlinx.coroutines.flow.onEach
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.html.*
|
import kotlinx.html.*
|
||||||
import kotlinx.html.stream.createHTML
|
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
import space.kscience.dataforge.context.ContextAware
|
import space.kscience.dataforge.context.ContextAware
|
||||||
import space.kscience.dataforge.meta.*
|
import space.kscience.dataforge.meta.*
|
||||||
@ -96,7 +95,7 @@ public fun Application.serveVisionData(
|
|||||||
val vision: Vision = resolveVision(Name.parse(name)) ?: error("Vision with id='$name' not registered")
|
val vision: Vision = resolveVision(Name.parse(name)) ?: error("Vision with id='$name' not registered")
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
for(frame in incoming) {
|
for (frame in incoming) {
|
||||||
val data = frame.data.decodeToString()
|
val data = frame.data.decodeToString()
|
||||||
application.log.debug("Received update for $name: \n$data")
|
application.log.debug("Received update for $name: \n$data")
|
||||||
val change = configuration.visionManager.jsonFormat.decodeFromString(
|
val change = configuration.visionManager.jsonFormat.decodeFromString(
|
||||||
@ -151,82 +150,82 @@ public fun Application.serveVisionData(
|
|||||||
public fun Application.visionPage(
|
public fun Application.visionPage(
|
||||||
route: String,
|
route: String,
|
||||||
configuration: VisionRoute,
|
configuration: VisionRoute,
|
||||||
connector: EngineConnectorConfig,
|
|
||||||
headers: Collection<HtmlFragment>,
|
headers: Collection<HtmlFragment>,
|
||||||
|
connector: EngineConnectorConfig? = null,
|
||||||
visionFragment: HtmlVisionFragment,
|
visionFragment: HtmlVisionFragment,
|
||||||
) {
|
) {
|
||||||
require(WebSockets)
|
require(WebSockets)
|
||||||
|
|
||||||
val collector: MutableMap<Name, Vision> = mutableMapOf()
|
val collector: MutableMap<Name, Vision> = mutableMapOf()
|
||||||
|
|
||||||
val html = createHTML().apply {
|
|
||||||
head {
|
|
||||||
meta {
|
|
||||||
charset = "utf-8"
|
|
||||||
}
|
|
||||||
headers.forEach { header ->
|
|
||||||
consumer.header()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
//Load the fragment and remember all loaded visions
|
|
||||||
visionFragment(
|
|
||||||
visionManager = configuration.visionManager,
|
|
||||||
embedData = configuration.dataMode == VisionRoute.Mode.EMBED,
|
|
||||||
fetchDataUrl = if (configuration.dataMode != VisionRoute.Mode.EMBED) {
|
|
||||||
url {
|
|
||||||
host = connector.host
|
|
||||||
port = connector.port
|
|
||||||
path(route, "data")
|
|
||||||
}
|
|
||||||
} else null,
|
|
||||||
updatesUrl = if (configuration.dataMode == VisionRoute.Mode.UPDATE) {
|
|
||||||
url {
|
|
||||||
protocol = URLProtocol.WS
|
|
||||||
host = connector.host
|
|
||||||
port = connector.port
|
|
||||||
path(route, "ws")
|
|
||||||
}
|
|
||||||
} else null,
|
|
||||||
onVisionRendered = { name, vision -> collector[name] = vision },
|
|
||||||
fragment = visionFragment
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}.finalize()
|
|
||||||
|
|
||||||
//serve data
|
//serve data
|
||||||
serveVisionData(configuration, collector)
|
serveVisionData(configuration, collector)
|
||||||
|
|
||||||
//filled pages
|
//filled pages
|
||||||
routing {
|
routing {
|
||||||
get(route) {
|
get(route) {
|
||||||
call.respondText(html, ContentType.Text.Html)
|
val host = connector?.host ?: call.request.host()
|
||||||
|
val port = connector?.port ?: call.request.port()
|
||||||
|
call.respondHtml {
|
||||||
|
head {
|
||||||
|
meta {
|
||||||
|
charset = "utf-8"
|
||||||
|
}
|
||||||
|
headers.forEach { header ->
|
||||||
|
consumer.header()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
//Load the fragment and remember all loaded visions
|
||||||
|
visionFragment(
|
||||||
|
visionManager = configuration.visionManager,
|
||||||
|
embedData = configuration.dataMode == VisionRoute.Mode.EMBED,
|
||||||
|
fetchDataUrl = if (configuration.dataMode != VisionRoute.Mode.EMBED) {
|
||||||
|
url {
|
||||||
|
this.host = host
|
||||||
|
this.port = port
|
||||||
|
path(route, "data")
|
||||||
|
}
|
||||||
|
} else null,
|
||||||
|
updatesUrl = if (configuration.dataMode == VisionRoute.Mode.UPDATE) {
|
||||||
|
url {
|
||||||
|
protocol = URLProtocol.WS
|
||||||
|
this.host = host
|
||||||
|
this.port = port
|
||||||
|
path(route, "ws")
|
||||||
|
}
|
||||||
|
} else null,
|
||||||
|
onVisionRendered = { name, vision -> collector[name] = vision },
|
||||||
|
fragment = visionFragment
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun Application.visionPage(
|
public fun Application.visionPage(
|
||||||
connector: EngineConnectorConfig,
|
|
||||||
visionManager: VisionManager,
|
visionManager: VisionManager,
|
||||||
vararg headers: HtmlFragment,
|
vararg headers: HtmlFragment,
|
||||||
route: String = "/",
|
route: String = "/",
|
||||||
|
connector: EngineConnectorConfig? = null,
|
||||||
configurationBuilder: VisionRoute.() -> Unit = {},
|
configurationBuilder: VisionRoute.() -> Unit = {},
|
||||||
visionFragment: HtmlVisionFragment,
|
visionFragment: HtmlVisionFragment,
|
||||||
) {
|
) {
|
||||||
val configuration = VisionRoute(route, visionManager).apply(configurationBuilder)
|
val configuration = VisionRoute(route, visionManager).apply(configurationBuilder)
|
||||||
visionPage(route, configuration, connector, listOf(*headers), visionFragment)
|
visionPage(route, configuration, listOf(*headers), connector, visionFragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render given [VisionPage] at server
|
* Render given [VisionPage] at server
|
||||||
*/
|
*/
|
||||||
public fun Application.visionPage(
|
public fun Application.visionPage(
|
||||||
connector: EngineConnectorConfig,
|
|
||||||
page: VisionPage,
|
page: VisionPage,
|
||||||
route: String = "/",
|
route: String = "/",
|
||||||
|
connector: EngineConnectorConfig? = null,
|
||||||
configurationBuilder: VisionRoute.() -> Unit = {},
|
configurationBuilder: VisionRoute.() -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val configuration = VisionRoute(route, page.visionManager).apply(configurationBuilder)
|
val configuration = VisionRoute(route, page.visionManager).apply(configurationBuilder)
|
||||||
visionPage(route, configuration, connector, page.pageHeaders.values, visionFragment = page.content)
|
visionPage(route, configuration, page.pageHeaders.values, connector, visionFragment = page.content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,8 @@ public fun <P : Pipeline<*, ApplicationCall>, B : Any, F : Any> P.require(
|
|||||||
*/
|
*/
|
||||||
public fun ApplicationEngine.openInBrowser() {
|
public fun ApplicationEngine.openInBrowser() {
|
||||||
val connector = environment.connectors.first()
|
val connector = environment.connectors.first()
|
||||||
val uri = URI("http", null, connector.host, connector.port, null, null, null)
|
val host = if (connector.host == "0.0.0.0") "127.0.0.1" else connector.host
|
||||||
|
val uri = URI("http", null, host, connector.port, null, null, null)
|
||||||
Desktop.getDesktop().browse(uri)
|
Desktop.getDesktop().browse(uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,10 +11,10 @@ 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.misc.DFExperimental
|
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.visionforge.*
|
import space.kscience.visionforge.*
|
||||||
import space.kscience.visionforge.html.VisionOutput
|
import space.kscience.visionforge.html.VisionOutput
|
||||||
|
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||||
|
|
||||||
|
|
||||||
public class Solids(meta: Meta) : VisionPlugin(meta), MutableVisionContainer<Solid> {
|
public class Solids(meta: Meta) : VisionPlugin(meta), MutableVisionContainer<Solid> {
|
||||||
@ -80,8 +80,10 @@ public class Solids(meta: Meta) : VisionPlugin(meta), MutableVisionContainer<Sol
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
@DFExperimental
|
public inline fun VisionOutput.solid(options: Canvas3DOptions? = null, block: SolidGroup.() -> Unit): SolidGroup {
|
||||||
public inline fun VisionOutput.solid(block: SolidGroup.() -> Unit): SolidGroup {
|
|
||||||
requirePlugin(Solids)
|
requirePlugin(Solids)
|
||||||
|
options?.let {
|
||||||
|
meta = options.meta
|
||||||
|
}
|
||||||
return SolidGroup().apply(block)
|
return SolidGroup().apply(block)
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,6 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
objectFactories[Box::class] = ThreeBoxFactory
|
objectFactories[Box::class] = ThreeBoxFactory
|
||||||
objectFactories[Convex::class] = ThreeConvexFactory
|
objectFactories[Convex::class] = ThreeConvexFactory
|
||||||
objectFactories[Sphere::class] = ThreeSphereFactory
|
objectFactories[Sphere::class] = ThreeSphereFactory
|
||||||
// objectFactories[ConeSegment::class] = ThreeConeFactory
|
|
||||||
objectFactories[PolyLine::class] = ThreeSmartLineFactory
|
objectFactories[PolyLine::class] = ThreeSmartLineFactory
|
||||||
objectFactories[SolidLabel::class] = ThreeCanvasLabelFactory
|
objectFactories[SolidLabel::class] = ThreeCanvasLabelFactory
|
||||||
objectFactories[AmbientLightSource::class] = ThreeAmbientLightFactory
|
objectFactories[AmbientLightSource::class] = ThreeAmbientLightFactory
|
||||||
@ -143,7 +142,8 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
internal fun renderSolid(
|
internal fun renderSolid(
|
||||||
element: Element,
|
element: Element,
|
||||||
vision: Solid,
|
vision: Solid,
|
||||||
): ThreeCanvas = getOrCreateCanvas(element).apply {
|
options: Canvas3DOptions = Canvas3DOptions(),
|
||||||
|
): ThreeCanvas = getOrCreateCanvas(element, options).apply {
|
||||||
render(vision)
|
render(vision)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,9 +151,8 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
renderSolid(
|
renderSolid(
|
||||||
element,
|
element,
|
||||||
vision as? Solid ?: error("Solid expected but ${vision::class} found"),
|
vision as? Solid ?: error("Solid expected but ${vision::class} found"),
|
||||||
).apply {
|
Canvas3DOptions.read(meta)
|
||||||
options.meta.update(meta)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public companion object : PluginFactory<ThreePlugin> {
|
public companion object : PluginFactory<ThreePlugin> {
|
||||||
|
Loading…
Reference in New Issue
Block a user