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 {
|
||||
group = "space.kscience"
|
||||
version = "0.3.0-dev-8"
|
||||
version = "0.3.0-dev-9"
|
||||
}
|
||||
|
||||
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 {
|
||||
//
|
||||
// sourceSets {
|
||||
|
@ -2,7 +2,7 @@ package space.kscience.visionforge.examples
|
||||
|
||||
import io.ktor.server.cio.CIO
|
||||
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 kotlinx.html.*
|
||||
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.bindForm
|
||||
import space.kscience.visionforge.onPropertyChange
|
||||
import space.kscience.visionforge.server.EngineConnectorConfig
|
||||
import space.kscience.visionforge.server.close
|
||||
import space.kscience.visionforge.server.openInBrowser
|
||||
import space.kscience.visionforge.server.visionPage
|
||||
|
||||
@Suppress("ExtractKtorModule")
|
||||
fun main() {
|
||||
val visionManager = Global.request(VisionManager)
|
||||
|
||||
|
||||
val connector = EngineConnectorConfig("localhost", 7777)
|
||||
|
||||
val server = embeddedServer(CIO, connector.port, connector.host) {
|
||||
val server = embeddedServer(CIO) {
|
||||
|
||||
routing {
|
||||
resources()
|
||||
staticResources("/", null)
|
||||
}
|
||||
|
||||
val form = VisionOfHtmlForm("form").apply {
|
||||
@ -36,7 +33,6 @@ fun main() {
|
||||
}
|
||||
|
||||
visionPage(
|
||||
connector,
|
||||
visionManager,
|
||||
VisionPage.scriptHeader("js/visionforge-playground.js"),
|
||||
) {
|
||||
|
@ -33,6 +33,7 @@ fun main() = makeVisionFile {
|
||||
cylinder(30,20, name = "cylinder"){
|
||||
detail = 31
|
||||
y = -220
|
||||
z = 15
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ import space.kscience.dataforge.meta.Null
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.visionforge.Colors
|
||||
import space.kscience.visionforge.html.VisionPage
|
||||
import space.kscience.visionforge.server.EngineConnectorConfig
|
||||
import space.kscience.visionforge.server.close
|
||||
import space.kscience.visionforge.server.openInBrowser
|
||||
import space.kscience.visionforge.server.visionPage
|
||||
@ -23,6 +22,7 @@ import space.kscience.visionforge.three.threeJsHeader
|
||||
import kotlin.random.Random
|
||||
|
||||
|
||||
@Suppress("ExtractKtorModule")
|
||||
fun main() {
|
||||
val satContext = Context("sat") {
|
||||
plugin(Solids)
|
||||
@ -36,15 +36,12 @@ fun main() {
|
||||
color.set(Colors.white)
|
||||
}
|
||||
}
|
||||
val connector = EngineConnectorConfig("localhost", 7777)
|
||||
|
||||
val server = embeddedServer(CIO, connector.port, connector.host) {
|
||||
val server = embeddedServer(CIO, port = 7777) {
|
||||
routing {
|
||||
staticResources("", null, null)
|
||||
}
|
||||
|
||||
visionPage(
|
||||
connector,
|
||||
solids.visionManager, VisionPage.threeJsHeader,
|
||||
VisionPage.styleSheetHeader("css/styles.css")
|
||||
) {
|
||||
|
@ -1,6 +1,5 @@
|
||||
plugins {
|
||||
id("space.kscience.gradle.mpp")
|
||||
`maven-publish`
|
||||
application
|
||||
}
|
||||
|
||||
@ -22,8 +21,4 @@ kscience {
|
||||
|
||||
application {
|
||||
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.withContext
|
||||
import kotlinx.html.*
|
||||
import kotlinx.html.stream.createHTML
|
||||
import space.kscience.dataforge.context.Context
|
||||
import space.kscience.dataforge.context.ContextAware
|
||||
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")
|
||||
|
||||
launch {
|
||||
for(frame in incoming) {
|
||||
for (frame in incoming) {
|
||||
val data = frame.data.decodeToString()
|
||||
application.log.debug("Received update for $name: \n$data")
|
||||
val change = configuration.visionManager.jsonFormat.decodeFromString(
|
||||
@ -151,82 +150,82 @@ public fun Application.serveVisionData(
|
||||
public fun Application.visionPage(
|
||||
route: String,
|
||||
configuration: VisionRoute,
|
||||
connector: EngineConnectorConfig,
|
||||
headers: Collection<HtmlFragment>,
|
||||
connector: EngineConnectorConfig? = null,
|
||||
visionFragment: HtmlVisionFragment,
|
||||
) {
|
||||
require(WebSockets)
|
||||
|
||||
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
|
||||
serveVisionData(configuration, collector)
|
||||
|
||||
//filled pages
|
||||
routing {
|
||||
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(
|
||||
connector: EngineConnectorConfig,
|
||||
visionManager: VisionManager,
|
||||
vararg headers: HtmlFragment,
|
||||
route: String = "/",
|
||||
connector: EngineConnectorConfig? = null,
|
||||
configurationBuilder: VisionRoute.() -> Unit = {},
|
||||
visionFragment: HtmlVisionFragment,
|
||||
) {
|
||||
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
|
||||
*/
|
||||
public fun Application.visionPage(
|
||||
connector: EngineConnectorConfig,
|
||||
page: VisionPage,
|
||||
route: String = "/",
|
||||
connector: EngineConnectorConfig? = null,
|
||||
configurationBuilder: VisionRoute.() -> Unit = {},
|
||||
) {
|
||||
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() {
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -11,10 +11,10 @@ import space.kscience.dataforge.context.Context
|
||||
import space.kscience.dataforge.context.PluginFactory
|
||||
import space.kscience.dataforge.context.PluginTag
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.visionforge.*
|
||||
import space.kscience.visionforge.html.VisionOutput
|
||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||
|
||||
|
||||
public class Solids(meta: Meta) : VisionPlugin(meta), MutableVisionContainer<Solid> {
|
||||
@ -80,8 +80,10 @@ public class Solids(meta: Meta) : VisionPlugin(meta), MutableVisionContainer<Sol
|
||||
}
|
||||
|
||||
@VisionBuilder
|
||||
@DFExperimental
|
||||
public inline fun VisionOutput.solid(block: SolidGroup.() -> Unit): SolidGroup {
|
||||
public inline fun VisionOutput.solid(options: Canvas3DOptions? = null, block: SolidGroup.() -> Unit): SolidGroup {
|
||||
requirePlugin(Solids)
|
||||
options?.let {
|
||||
meta = options.meta
|
||||
}
|
||||
return SolidGroup().apply(block)
|
||||
}
|
||||
|
@ -34,7 +34,6 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
||||
objectFactories[Box::class] = ThreeBoxFactory
|
||||
objectFactories[Convex::class] = ThreeConvexFactory
|
||||
objectFactories[Sphere::class] = ThreeSphereFactory
|
||||
// objectFactories[ConeSegment::class] = ThreeConeFactory
|
||||
objectFactories[PolyLine::class] = ThreeSmartLineFactory
|
||||
objectFactories[SolidLabel::class] = ThreeCanvasLabelFactory
|
||||
objectFactories[AmbientLightSource::class] = ThreeAmbientLightFactory
|
||||
@ -143,7 +142,8 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
||||
internal fun renderSolid(
|
||||
element: Element,
|
||||
vision: Solid,
|
||||
): ThreeCanvas = getOrCreateCanvas(element).apply {
|
||||
options: Canvas3DOptions = Canvas3DOptions(),
|
||||
): ThreeCanvas = getOrCreateCanvas(element, options).apply {
|
||||
render(vision)
|
||||
}
|
||||
|
||||
@ -151,9 +151,8 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
||||
renderSolid(
|
||||
element,
|
||||
vision as? Solid ?: error("Solid expected but ${vision::class} found"),
|
||||
).apply {
|
||||
options.meta.update(meta)
|
||||
}
|
||||
Canvas3DOptions.read(meta)
|
||||
)
|
||||
}
|
||||
|
||||
public companion object : PluginFactory<ThreePlugin> {
|
||||
|
Loading…
Reference in New Issue
Block a user