diff --git a/build.gradle.kts b/build.gradle.kts index 3ee913b2..30eea98f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -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 { diff --git a/demo/build.gradle.kts b/demo/build.gradle.kts new file mode 100644 index 00000000..49476bc7 --- /dev/null +++ b/demo/build.gradle.kts @@ -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 { + configure { + explicitApi = ExplicitApiMode.Disabled + } + } +} \ No newline at end of file diff --git a/demo/gdml/build.gradle.kts b/demo/gdml/build.gradle.kts index c1e3be28..72b1b283 100644 --- a/demo/gdml/build.gradle.kts +++ b/demo/gdml/build.gradle.kts @@ -30,6 +30,10 @@ kscience { } } +kotlin { + explicitApi = null +} + //kotlin { // // sourceSets { diff --git a/demo/playground/src/jvmMain/kotlin/formServer.kt b/demo/playground/src/jvmMain/kotlin/formServer.kt index 2f5b4ea1..d832d85a 100644 --- a/demo/playground/src/jvmMain/kotlin/formServer.kt +++ b/demo/playground/src/jvmMain/kotlin/formServer.kt @@ -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"), ) { diff --git a/demo/playground/src/jvmMain/kotlin/shapes.kt b/demo/playground/src/jvmMain/kotlin/shapes.kt index 1c702c5e..a338d123 100644 --- a/demo/playground/src/jvmMain/kotlin/shapes.kt +++ b/demo/playground/src/jvmMain/kotlin/shapes.kt @@ -33,6 +33,7 @@ fun main() = makeVisionFile { cylinder(30,20, name = "cylinder"){ detail = 31 y = -220 + z = 15 } } } diff --git a/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/satServer.kt b/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/satServer.kt index 4f0ff70c..9e0c8282 100644 --- a/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/satServer.kt +++ b/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/satServer.kt @@ -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") ) { diff --git a/demo/solid-showcase/build.gradle.kts b/demo/solid-showcase/build.gradle.kts index d588e035..78e7d163 100644 --- a/demo/solid-showcase/build.gradle.kts +++ b/demo/solid-showcase/build.gradle.kts @@ -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 } \ No newline at end of file diff --git a/visionforge-server/src/main/kotlin/space/kscience/visionforge/server/VisionServer.kt b/visionforge-server/src/main/kotlin/space/kscience/visionforge/server/VisionServer.kt index c05a1834..84a87a65 100644 --- a/visionforge-server/src/main/kotlin/space/kscience/visionforge/server/VisionServer.kt +++ b/visionforge-server/src/main/kotlin/space/kscience/visionforge/server/VisionServer.kt @@ -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, + connector: EngineConnectorConfig? = null, visionFragment: HtmlVisionFragment, ) { require(WebSockets) val collector: MutableMap = 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) } diff --git a/visionforge-server/src/main/kotlin/space/kscience/visionforge/server/applicationExtensions.kt b/visionforge-server/src/main/kotlin/space/kscience/visionforge/server/applicationExtensions.kt index f33b59b2..81f6e3e7 100644 --- a/visionforge-server/src/main/kotlin/space/kscience/visionforge/server/applicationExtensions.kt +++ b/visionforge-server/src/main/kotlin/space/kscience/visionforge/server/applicationExtensions.kt @@ -22,7 +22,8 @@ public fun

, 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) } diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solids.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solids.kt index 1fecd450..f828101b 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solids.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solids.kt @@ -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 { @@ -80,8 +80,10 @@ public class Solids(meta: Meta) : VisionPlugin(meta), MutableVisionContainer 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) } diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt index 234ded6f..d1309849 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt @@ -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 {