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 a1f0dca1..92b1b7d0 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 @@ -1,12 +1,11 @@ package ru.mipt.npm.sat +import hep.dataforge.context.Global import hep.dataforge.names.toName -import hep.dataforge.vision.solid.Solid -import hep.dataforge.vision.solid.clear -import hep.dataforge.vision.solid.color -import hep.dataforge.vision.solid.invoke +import hep.dataforge.vision.solid.* import hep.dataforge.vision.three.server.* +import hep.dataforge.vision.visionManager import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.delay import kotlinx.coroutines.isActive @@ -16,10 +15,14 @@ import kotlinx.html.h1 import kotlin.random.Random fun main() { + val satContext = Global.context("sat") { + plugin(SolidManager) + } + //Create a geometry val sat = visionOfSatellite(ySegments = 3) - val server = visionManager.serve { + val server = satContext.visionManager.serve { //use client library useThreeJs() //use css diff --git a/playground/build.gradle.kts b/playground/build.gradle.kts index 45d20f6d..4df93ed9 100644 --- a/playground/build.gradle.kts +++ b/playground/build.gradle.kts @@ -12,6 +12,16 @@ repositories{ } kotlin { + + js(IR) { + browser { + webpackTask { + this.outputFileName = "js/visionforge-playground.js" + } + } + binaries.executable() + } + jvm{ compilations.all { kotlinOptions.jvmTarget = "11" @@ -20,30 +30,39 @@ kotlin { useJUnitPlatform() } } - js(IR) { - browser { + + afterEvaluate { + val jsBrowserDistribution by tasks.getting + + tasks.getByName("jvmProcessResources") { + dependsOn(jsBrowserDistribution) + afterEvaluate { + from(jsBrowserDistribution) + } } - binaries.executable() } + sourceSets { - commonMain { + val commonMain by getting { dependencies { implementation(project(":visionforge-solid")) implementation(project(":visionforge-gdml")) - + implementation(project(":visionforge-plotly")) } } + val jsMain by getting{ dependencies { implementation(project(":ui:bootstrap")) + implementation(project(":visionforge-threejs")) } } val jvmMain by getting{ dependencies { + implementation(project(":visionforge-server")) implementation("com.github.Ricky12Awesome:json-schema-serialization:0.6.6") - implementation(project(":visionforge-threejs:visionforge-threejs-server")) } } } diff --git a/playground/src/commonMain/kotlin/visionContext.kt b/playground/src/commonMain/kotlin/visionContext.kt new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/playground/src/commonMain/kotlin/visionContext.kt @@ -0,0 +1,2 @@ + + diff --git a/playground/src/jsMain/kotlin/PlayGroundApp.kt b/playground/src/jsMain/kotlin/PlayGroundApp.kt index a4635a04..4a3018a0 100644 --- a/playground/src/jsMain/kotlin/PlayGroundApp.kt +++ b/playground/src/jsMain/kotlin/PlayGroundApp.kt @@ -1,58 +1,67 @@ -import hep.dataforge.Application -import hep.dataforge.startApplication -import hep.dataforge.vision.bootstrap.visionPropertyEditor -import hep.dataforge.vision.react.ThreeCanvasComponent -import hep.dataforge.vision.react.objectTree -import hep.dataforge.vision.solid.* -import hep.dataforge.vision.solid.specifications.Canvas3DOptions -import kotlinx.browser.document -import org.w3c.dom.HTMLElement -import react.RBuilder -import react.child -import react.dom.div -import react.dom.render - -fun RBuilder.threeCanvas(object3D: Solid, options: Canvas3DOptions.() -> Unit = {}) { - child(ThreeCanvasComponent) { - attrs { - this.obj = object3D - this.options = Canvas3DOptions(options) - } - } -} - -private class PlayGroundApp : Application { - - override fun start(state: Map) { - - val element = - document.getElementById("app") as? HTMLElement ?: error("Element with id 'canvas' not found on page") - - val obj = SolidGroup().apply { - box(100, 100, 100, name = "A") - group("B") { - position = Point3D(120, 0, 0) - box(100, 100, 100, name = "C") - } - } - - render(element) { - div("row") { - div("col-3") { - objectTree(obj) - } - div("col-6") { - threeCanvas(obj) - } - div("col-3") { - visionPropertyEditor(obj) - } - } - } - } +import hep.dataforge.context.Context +import hep.dataforge.context.Global +import hep.dataforge.meta.DFExperimental +import hep.dataforge.vision.client.VisionClient +import hep.dataforge.vision.client.renderAllVisions +import hep.dataforge.vision.plotly.PlotlyPlugin +import hep.dataforge.vision.solid.three.ThreePlugin +import kotlinx.browser.window +//fun RBuilder.threeCanvas(object3D: Solid, options: Canvas3DOptions.() -> Unit = {}) { +// child(ThreeCanvasComponent) { +// attrs { +// this.obj = object3D +// this.options = Canvas3DOptions(options) +// } +// } +//} +// +//private class PlayGroundApp : Application { +// +// override fun start(state: Map) { +// +// val element = +// document.getElementById("app") as? HTMLElement ?: error("Element with id 'canvas' not found on page") +// +// val obj = SolidGroup().apply { +// box(100, 100, 100, name = "A") +// group("B") { +// position = Point3D(120, 0, 0) +// box(100, 100, 100, name = "C") +// } +// } +// +// render(element) { +// div("row") { +// div("col-3") { +// objectTree(obj) +// } +// div("col-6") { +// threeCanvas(obj) +// } +// div("col-3") { +// visionPropertyEditor(obj) +// } +// } +// } +// } +// +//} + +public val visionContext: Context = Global.context("VISION") { + plugin(ThreePlugin) + plugin(PlotlyPlugin) + plugin(VisionClient) } +@DFExperimental fun main() { - startApplication(::PlayGroundApp) + //Loading three-js renderer + val clientManager = visionContext.plugins.fetch(VisionClient) + + //Fetch from server and render visions for all outputs + window.onload = { + clientManager.renderAllVisions() + } + //startApplication(::PlayGroundApp) } \ No newline at end of file diff --git a/playground/src/jvmMain/kotlin/hep/dataforge/vision/solid/stars.kt b/playground/src/jvmMain/kotlin/hep/dataforge/vision/solid/randomSpheres.kt similarity index 81% rename from playground/src/jvmMain/kotlin/hep/dataforge/vision/solid/stars.kt rename to playground/src/jvmMain/kotlin/hep/dataforge/vision/solid/randomSpheres.kt index dcfd8bcc..728714af 100644 --- a/playground/src/jvmMain/kotlin/hep/dataforge/vision/solid/stars.kt +++ b/playground/src/jvmMain/kotlin/hep/dataforge/vision/solid/randomSpheres.kt @@ -4,21 +4,20 @@ import hep.dataforge.meta.DFExperimental import hep.dataforge.vision.ResourceLocation import hep.dataforge.vision.VisionManager import hep.dataforge.vision.html.fragment -import hep.dataforge.vision.three.server.makeFile -import hep.dataforge.vision.three.server.solid import kotlinx.html.h1 import java.nio.file.Paths import kotlin.random.Random @OptIn(DFExperimental::class) fun main() { + val random = Random(112233) val fragment = VisionManager.fragment { h1 { +"Happy new year!" } vision { solid { repeat(100) { - sphere(5) { + sphere(5, name = "sphere[$it]") { x = random.nextDouble(-300.0, 300.0) y = random.nextDouble(-300.0, 300.0) z = random.nextDouble(-300.0, 300.0) @@ -33,5 +32,9 @@ fun main() { } } - fragment.makeFile(Paths.get("stars.html"), resourceLocation = ResourceLocation.EMBED) + visionContext.makeVisionFile( + fragment, + Paths.get("randomSpheres.html"), + resourceLocation = ResourceLocation.EMBED + ) } \ No newline at end of file diff --git a/playground/src/jvmMain/kotlin/hep/dataforge/vision/solid/serverExtensions.kt b/playground/src/jvmMain/kotlin/hep/dataforge/vision/solid/serverExtensions.kt new file mode 100644 index 00000000..c1f3b273 --- /dev/null +++ b/playground/src/jvmMain/kotlin/hep/dataforge/vision/solid/serverExtensions.kt @@ -0,0 +1,38 @@ +package hep.dataforge.vision.solid + +import hep.dataforge.context.Context +import hep.dataforge.context.Global +import hep.dataforge.meta.DFExperimental +import hep.dataforge.vision.ResourceLocation +import hep.dataforge.vision.VisionManager +import hep.dataforge.vision.html.HtmlVisionFragment +import hep.dataforge.vision.makeVisionFile +import hep.dataforge.vision.scriptHeader +import hep.dataforge.vision.three.server.VisionServer +import hep.dataforge.vision.three.server.useScript +import java.nio.file.Path + + +/** + * A global vision context used to resolve different vision renderers + */ +@DFExperimental +public val visionContext: Context = Global.context("VISION") { + plugin(VisionManager) + plugin(SolidManager) +} + +public fun VisionServer.usePlayground(): Unit { + useScript("js/visionforge-playground.js") +} + +@DFExperimental +public fun Context.makeVisionFile( + fragment: HtmlVisionFragment, + path: Path? = null, + title: String = "VisionForge page", + resourceLocation: ResourceLocation = ResourceLocation.SYSTEM, + show: Boolean = true, +): Unit = makeVisionFile(fragment, path = path, title = title, show = show) { actualPath -> + scriptHeader("js/visionforge-playground.js", actualPath, resourceLocation) +} diff --git a/playground/src/jvmMain/kotlin/hep/dataforge/vision/solid/simpleCube.kt b/playground/src/jvmMain/kotlin/hep/dataforge/vision/solid/simpleCube.kt index 215e742c..ca8e70b5 100644 --- a/playground/src/jvmMain/kotlin/hep/dataforge/vision/solid/simpleCube.kt +++ b/playground/src/jvmMain/kotlin/hep/dataforge/vision/solid/simpleCube.kt @@ -4,8 +4,6 @@ import hep.dataforge.meta.DFExperimental import hep.dataforge.vision.ResourceLocation import hep.dataforge.vision.VisionManager import hep.dataforge.vision.html.fragment -import hep.dataforge.vision.three.server.makeFile -import hep.dataforge.vision.three.server.solid @OptIn(DFExperimental::class) fun main() { @@ -17,5 +15,5 @@ fun main() { } } - fragment.makeFile(resourceLocation = ResourceLocation.SYSTEM) + visionContext.makeVisionFile(fragment = fragment, resourceLocation = ResourceLocation.SYSTEM) } \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 3877a947..36931914 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -33,7 +33,7 @@ rootProject.name = "visionforge" include( // ":ui", ":ui:react", - ":ui:ring", +// ":ui:ring", // ":ui:material", ":ui:bootstrap", ":visionforge-core", @@ -43,6 +43,7 @@ include( ":visionforge-threejs:visionforge-threejs-server", ":visionforge-gdml", ":visionforge-server", + ":visionforge-plotly", ":demo:spatial-showcase", ":demo:gdml", ":demo:muon-monitor", diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionBase.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionBase.kt index b5d03eb7..dddcb377 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionBase.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionBase.kt @@ -16,7 +16,6 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch -import kotlinx.css.th import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.Transient @@ -27,7 +26,6 @@ internal data class PropertyListener( val action: (name: Name) -> Unit, ) - /** * A full base implementation for a [Vision] * @param properties Object own properties excluding styles and inheritance @@ -53,7 +51,7 @@ public open class VisionBase(internal var properties: Config? = null) : Vision { override val meta: Meta get() = properties ?: Meta.EMPTY @Synchronized - private fun getOrCreateConfig(): Config { + protected fun getOrCreateConfig(): Config { if (properties == null) { val newProperties = Config() newProperties.onChange(this) { name, oldItem, newItem -> @@ -91,7 +89,6 @@ public open class VisionBase(internal var properties: Config? = null) : Vision { yield(descriptor?.get(name)?.defaultItem()) }.merge() - @Synchronized override fun setProperty(name: Name, item: MetaItem?, notify: Boolean) { getOrCreateConfig().setItem(name, item) if (notify) { @@ -117,6 +114,7 @@ public open class VisionBase(internal var properties: Config? = null) : Vision { @Transient private val propertyInvalidationFlow: MutableSharedFlow = MutableSharedFlow() + @DFExperimental override val propertyChanges: Flow get() = propertyInvalidationFlow override fun onPropertyChange(scope: CoroutineScope, callback: suspend (Name) -> Unit) { diff --git a/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/headers.kt b/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/headers.kt index 7fe87dbb..5dfb5352 100644 --- a/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/headers.kt +++ b/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/headers.kt @@ -42,8 +42,8 @@ internal const val VISIONFORGE_ASSETS_PATH = ".dataforge/vision/assets" * Check if the asset exists in given local location and put it there if it does not * @param */ -internal fun checkOrStoreFile(basePath: Path, filePath: Path, resource: String): Path { - val fullPath = basePath.resolveSibling(filePath).toAbsolutePath().resolve(resource) +internal fun checkOrStoreFile(htmlPath: Path, filePath: Path, resource: String): Path { + val fullPath = htmlPath.resolveSibling(filePath).toAbsolutePath().resolve(resource) if (Files.exists(fullPath)) { //TODO checksum @@ -55,8 +55,8 @@ internal fun checkOrStoreFile(basePath: Path, filePath: Path, resource: String): Files.write(fullPath, bytes, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE) } - return if (basePath.isAbsolute && fullPath.startsWith(basePath)) { - basePath.relativize(fullPath) + return if (htmlPath.isAbsolute && fullPath.startsWith(htmlPath.parent)) { + htmlPath.parent.relativize(fullPath) } else { fullPath } @@ -100,14 +100,14 @@ internal fun fileCssHeader( * Make a script header, automatically copying file to appropriate location */ @DFExperimental -public fun Context.Companion.scriptHeader( +public fun Context.scriptHeader( scriptResource: String, - basePath: Path, + htmlPath: Path, resourceLocation: ResourceLocation, ): HtmlFragment { val targetPath = when (resourceLocation) { ResourceLocation.LOCAL -> checkOrStoreFile( - basePath, + htmlPath, Path.of(VISIONFORGE_ASSETS_PATH), scriptResource ) diff --git a/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/htmlExport.kt b/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/htmlExport.kt index 6ff99bcb..d560f46a 100644 --- a/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/htmlExport.kt +++ b/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/htmlExport.kt @@ -1,9 +1,16 @@ package hep.dataforge.vision +import hep.dataforge.context.Context import hep.dataforge.meta.DFExperimental -import hep.dataforge.vision.html.* -import kotlinx.html.* +import hep.dataforge.vision.html.HtmlFragment +import hep.dataforge.vision.html.HtmlVisionFragment +import hep.dataforge.vision.html.embedVisionFragment +import hep.dataforge.vision.html.fragment +import kotlinx.html.body +import kotlinx.html.head +import kotlinx.html.meta import kotlinx.html.stream.createHTML +import kotlinx.html.title import java.awt.Desktop import java.nio.file.Files import java.nio.file.Path @@ -13,12 +20,12 @@ import java.nio.file.Path * Make a file with the embedded vision data */ @DFExperimental -public fun HtmlVisionFragment.makeFile( - manager: VisionManager, - vararg headers: HtmlFragment, +public fun Context.makeVisionFile( + fragment: HtmlVisionFragment, path: Path? = null, title: String = "VisionForge page", show: Boolean = true, + headerBuilder: (Path) -> HtmlFragment, ) { val actualFile = path?.let { Path.of(System.getProperty("user.home")).resolve(path) @@ -28,14 +35,12 @@ public fun HtmlVisionFragment.makeFile( head { meta { charset = "utf-8" - headers.forEach { - fragment(it) - } + fragment(headerBuilder(actualFile)) } title(title) } body { - embedVisionFragment(manager, fragment = this@makeFile) + embedVisionFragment(visionManager, fragment = fragment) } }.finalize() diff --git a/visionforge-plotly/build.gradle.kts b/visionforge-plotly/build.gradle.kts new file mode 100644 index 00000000..51419b1e --- /dev/null +++ b/visionforge-plotly/build.gradle.kts @@ -0,0 +1,20 @@ +plugins { + id("ru.mipt.npm.mpp") +} + +kscience { + useSerialization() +} + +val plotlyVersion = "0.3.1-dev" + +kotlin { + sourceSets { + commonMain { + dependencies { + api(project(":visionforge-core")) + api("kscience.plotlykt:plotlykt-core:${plotlyVersion}") + } + } + } +} \ No newline at end of file diff --git a/visionforge-plotly/src/commonMain/kotlin/hep/dataforge/vision/plotly/VisionOfPlotly.kt b/visionforge-plotly/src/commonMain/kotlin/hep/dataforge/vision/plotly/VisionOfPlotly.kt new file mode 100644 index 00000000..997a560a --- /dev/null +++ b/visionforge-plotly/src/commonMain/kotlin/hep/dataforge/vision/plotly/VisionOfPlotly.kt @@ -0,0 +1,12 @@ +package hep.dataforge.vision.plotly + +import hep.dataforge.meta.DFExperimental +import hep.dataforge.vision.VisionBase +import hep.dataforge.vision.html.VisionOutput +import kscience.plotly.Plot +import kscience.plotly.Plotly + +public class VisionOfPlotly(public val plot: Plot): VisionBase(plot.config) + +@DFExperimental +public inline fun VisionOutput.plotly(block: Plot.() -> Unit): VisionOfPlotly = VisionOfPlotly(Plotly.plot(block)) \ No newline at end of file diff --git a/visionforge-plotly/src/jsMain/kotlin/hep/dataforge/vision/plotly/PlotlyPlugin.kt b/visionforge-plotly/src/jsMain/kotlin/hep/dataforge/vision/plotly/PlotlyPlugin.kt new file mode 100644 index 00000000..9e2793dc --- /dev/null +++ b/visionforge-plotly/src/jsMain/kotlin/hep/dataforge/vision/plotly/PlotlyPlugin.kt @@ -0,0 +1,33 @@ +package hep.dataforge.vision.plotly + +import hep.dataforge.context.AbstractPlugin +import hep.dataforge.context.Context +import hep.dataforge.context.PluginFactory +import hep.dataforge.context.PluginTag +import hep.dataforge.meta.Meta +import hep.dataforge.vision.Vision +import hep.dataforge.vision.client.ElementVisionRenderer +import kscience.plotly.PlotlyConfig +import kscience.plotly.plot +import org.w3c.dom.Element +import kotlin.reflect.KClass + +public class PlotlyPlugin : AbstractPlugin(), ElementVisionRenderer { + + override val tag: PluginTag get() = Companion.tag + + override fun rateVision(vision: Vision): Int = + if (vision is VisionOfPlotly) ElementVisionRenderer.DEFAULT_RATING else ElementVisionRenderer.ZERO_RATING + + override fun render(element: Element, vision: Vision, meta: Meta) { + val plot = (vision as? VisionOfPlotly)?.plot ?: error("Only VisionOfPlotly visions are supported") + val config = PlotlyConfig.read(meta) + element.plot(plot, config) + } + + public companion object : PluginFactory { + override val tag: PluginTag = PluginTag("vision.plotly", PluginTag.DATAFORGE_GROUP) + override val type: KClass = PlotlyPlugin::class + override fun invoke(meta: Meta, context: Context): PlotlyPlugin = PlotlyPlugin() + } +} \ No newline at end of file diff --git a/visionforge-plotly/src/jsMain/kotlin/hep/dataforge/vision/plotly/jsMain.kt b/visionforge-plotly/src/jsMain/kotlin/hep/dataforge/vision/plotly/jsMain.kt new file mode 100644 index 00000000..ae0ffb37 --- /dev/null +++ b/visionforge-plotly/src/jsMain/kotlin/hep/dataforge/vision/plotly/jsMain.kt @@ -0,0 +1,15 @@ +package hep.dataforge.vision.plotly + +//public fun main() { +// val visionContext: Context = Global.context("vision-client") +// +// //Loading three-js renderer +// val threePlugin = visionContext.plugins.fetch(PlotlyPlugin) +// +// val clientManager = visionContext.plugins.fetch(VisionClient) +// +// //Fetch from server and render visions for all outputs +// window.onload = { +// clientManager.renderAllVisions() +// } +//} \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidManager.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidManager.kt index e91757a4..f55dc1f4 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidManager.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidManager.kt @@ -4,6 +4,7 @@ import hep.dataforge.context.AbstractPlugin import hep.dataforge.context.Context import hep.dataforge.context.PluginFactory import hep.dataforge.context.PluginTag +import hep.dataforge.meta.DFExperimental import hep.dataforge.meta.Meta import hep.dataforge.names.Name import hep.dataforge.names.toName @@ -12,6 +13,7 @@ import hep.dataforge.vision.VisionBase import hep.dataforge.vision.VisionGroupBase import hep.dataforge.vision.VisionManager import hep.dataforge.vision.VisionManager.Companion.VISION_SERIALIZER_MODULE_TARGET +import hep.dataforge.vision.html.VisionOutput import kotlinx.serialization.PolymorphicSerializer import kotlinx.serialization.json.Json import kotlinx.serialization.modules.PolymorphicModuleBuilder @@ -73,3 +75,6 @@ public class SolidManager(meta: Meta) : AbstractPlugin(meta) { public fun decodeFromString(str: String): Solid = jsonForSolids.decodeFromString(PolymorphicSerializer(Solid::class), str) } } + +@DFExperimental +public inline fun VisionOutput.solid(block: SolidGroup.() -> Unit): SolidGroup = SolidGroup().apply(block) \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Canvas3DOptions.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Canvas3DOptions.kt index cfe59171..2a147100 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Canvas3DOptions.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Canvas3DOptions.kt @@ -5,6 +5,7 @@ import hep.dataforge.names.Name public class Canvas3DOptions : Scheme() { public var axes: Axes by spec(Axes) + public var light: Light by spec(Light) public var camera: Camera by spec(Camera) public var controls: Controls by spec(Controls) diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Light.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Light.kt new file mode 100644 index 00000000..46ba8939 --- /dev/null +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Light.kt @@ -0,0 +1,8 @@ +package hep.dataforge.vision.solid.specifications + +import hep.dataforge.meta.Scheme +import hep.dataforge.meta.SchemeSpec + +public class Light : Scheme() { + public companion object : SchemeSpec(::Light) +} \ No newline at end of file diff --git a/visionforge-threejs/src/main/kotlin/hep/dataforge/vision/solid/three/ThreeCanvas.kt b/visionforge-threejs/src/main/kotlin/hep/dataforge/vision/solid/three/ThreeCanvas.kt index d58fba37..6df44691 100644 --- a/visionforge-threejs/src/main/kotlin/hep/dataforge/vision/solid/three/ThreeCanvas.kt +++ b/visionforge-threejs/src/main/kotlin/hep/dataforge/vision/solid/three/ThreeCanvas.kt @@ -51,7 +51,7 @@ public class ThreeCanvas( public var axes: AxesHelper = AxesHelper(options.axes.size.toInt()).apply { visible = options.axes.visible } private set - private val light = AmbientLight(0x404040) + private var light = buildLight(options.light) private val scene: Scene = Scene().apply { add(axes) @@ -169,6 +169,7 @@ public class ThreeCanvas( } } + private fun buildLight(spec: Light): info.laht.threekt.lights.Light = AmbientLight(0x404040) private fun buildCamera(spec: Camera) = PerspectiveCamera( spec.fov, diff --git a/visionforge-threejs/src/main/kotlin/info/laht/threekt/helpers/HemisphereLightHelper.kt b/visionforge-threejs/src/main/kotlin/info/laht/threekt/helpers/HemisphereLightHelper.kt index af7333d5..4351faa7 100644 --- a/visionforge-threejs/src/main/kotlin/info/laht/threekt/helpers/HemisphereLightHelper.kt +++ b/visionforge-threejs/src/main/kotlin/info/laht/threekt/helpers/HemisphereLightHelper.kt @@ -28,7 +28,7 @@ package info.laht.threekt.helpers import info.laht.threekt.core.Object3D -import info.laht.threekt.lights.HemiSphereLight +import info.laht.threekt.lights.HemisphereLight import info.laht.threekt.lights.Light /** @@ -39,7 +39,7 @@ import info.laht.threekt.lights.Light * @param color (optional) if this is not the set the helper will take the color of the light. */ external class HemisphereLightHelper( - light: HemiSphereLight, + light: HemisphereLight, size: Number, color: Int = definedExternally ) : Object3D { diff --git a/visionforge-threejs/src/main/kotlin/info/laht/threekt/lights/HemiSphereLight.kt b/visionforge-threejs/src/main/kotlin/info/laht/threekt/lights/HemisphereLight.kt similarity index 94% rename from visionforge-threejs/src/main/kotlin/info/laht/threekt/lights/HemiSphereLight.kt rename to visionforge-threejs/src/main/kotlin/info/laht/threekt/lights/HemisphereLight.kt index 727a36a1..c98fbd5d 100644 --- a/visionforge-threejs/src/main/kotlin/info/laht/threekt/lights/HemiSphereLight.kt +++ b/visionforge-threejs/src/main/kotlin/info/laht/threekt/lights/HemisphereLight.kt @@ -34,7 +34,7 @@ import info.laht.threekt.math.Color * * This light cannot be used to cast shadows. */ -external class HemiSphereLight( +external class HemisphereLight( skyColor: Int = definedExternally, groundColor: Int = definedExternally, intensity: Number = definedExternally @@ -42,6 +42,6 @@ external class HemiSphereLight( var groundColor: Color - fun copy(light: HemiSphereLight): HemiSphereLight + fun copy(light: HemisphereLight): HemisphereLight } \ No newline at end of file diff --git a/visionforge-threejs/visionforge-threejs-server/src/commonMain/kotlin/hep/dataforge/vision/three/server/visionContext.kt b/visionforge-threejs/visionforge-threejs-server/src/commonMain/kotlin/hep/dataforge/vision/three/server/visionContext.kt deleted file mode 100644 index c568d74a..00000000 --- a/visionforge-threejs/visionforge-threejs-server/src/commonMain/kotlin/hep/dataforge/vision/three/server/visionContext.kt +++ /dev/null @@ -1,8 +0,0 @@ -package hep.dataforge.vision.three.server - -import hep.dataforge.context.Context -import hep.dataforge.vision.VisionManager - -public expect val visionContext: Context - -public val visionManager: VisionManager get() = visionContext.plugins.fetch(VisionManager) \ No newline at end of file diff --git a/visionforge-threejs/visionforge-threejs-server/src/jsMain/kotlin/hep/dataforge/vision/three/server/jsMain.kt b/visionforge-threejs/visionforge-threejs-server/src/jsMain/kotlin/hep/dataforge/vision/three/server/jsMain.kt index f9505680..86ad4ecc 100644 --- a/visionforge-threejs/visionforge-threejs-server/src/jsMain/kotlin/hep/dataforge/vision/three/server/jsMain.kt +++ b/visionforge-threejs/visionforge-threejs-server/src/jsMain/kotlin/hep/dataforge/vision/three/server/jsMain.kt @@ -1,46 +1,18 @@ package hep.dataforge.vision.three.server -import hep.dataforge.context.Context import hep.dataforge.context.Global import hep.dataforge.vision.client.VisionClient import hep.dataforge.vision.client.renderAllVisions import hep.dataforge.vision.solid.three.ThreePlugin import kotlinx.browser.window -//FIXME check plugin loading in JS -//public actual val visionContext: Context = Global.context("vision-client") { -// //Loading three-js renderer -// plugin(ThreePlugin) -//} - -public actual val visionContext: Context = Global.context("vision-client").apply { - //Loading three-js renderer - plugins.fetch(ThreePlugin) -} - -public val clientManager: VisionClient get() = visionContext.plugins.fetch(VisionClient) - - -///** -// * Render all visions in the document using registered renderers -// */ -//@JsExport -//public fun renderVisions() { -// //Fetch from server and render visions for all outputs -// window.onload = { -// clientManager.renderAllVisions() -// } -//} -// -///** -// * Render all visions in a given element, using registered renderers -// */ -//@JsExport -//public fun renderAllVisionsAt(element: Element) { -// clientManager.renderAllVisionsAt(element) -//} - public fun main() { + //Loading three-js renderer + val visionContext = Global.context("threejs") { + plugin(ThreePlugin) + } + val clientManager = visionContext.plugins.fetch(VisionClient) + //Fetch from server and render visions for all outputs window.onload = { clientManager.renderAllVisions() diff --git a/visionforge-threejs/visionforge-threejs-server/src/jvmMain/kotlin/hep/dataforge/vision/three/server/serverExtensions.kt b/visionforge-threejs/visionforge-threejs-server/src/jvmMain/kotlin/hep/dataforge/vision/three/server/serverExtensions.kt index d37fabc3..ca20c709 100644 --- a/visionforge-threejs/visionforge-threejs-server/src/jvmMain/kotlin/hep/dataforge/vision/three/server/serverExtensions.kt +++ b/visionforge-threejs/visionforge-threejs-server/src/jvmMain/kotlin/hep/dataforge/vision/three/server/serverExtensions.kt @@ -1,47 +1,25 @@ package hep.dataforge.vision.three.server import hep.dataforge.context.Context -import hep.dataforge.context.Global import hep.dataforge.meta.DFExperimental import hep.dataforge.vision.ResourceLocation import hep.dataforge.vision.html.HtmlVisionFragment -import hep.dataforge.vision.html.VisionOutput -import hep.dataforge.vision.makeFile +import hep.dataforge.vision.makeVisionFile import hep.dataforge.vision.scriptHeader -import hep.dataforge.vision.solid.SolidGroup -import hep.dataforge.vision.solid.SolidManager -import java.nio.file.Files import java.nio.file.Path -public actual val visionContext: Context = Global.context("vision-server") { - //Loading solid manager for the backend (it does not know about three - plugin(SolidManager) -} public fun VisionServer.useThreeJs(): Unit { useScript("js/visionforge-three.js") -// header { -// script { -// unsafe { -// +"renderThreeVisions()" -// } -// } -// } } @DFExperimental -public inline fun VisionOutput.solid(block: SolidGroup.() -> Unit): SolidGroup = SolidGroup().apply(block) - -@OptIn(DFExperimental::class) -public fun HtmlVisionFragment.makeFile( +public fun Context.makeVisionFile( + fragment: HtmlVisionFragment, path: Path? = null, title: String = "VisionForge page", resourceLocation: ResourceLocation = ResourceLocation.SYSTEM, show: Boolean = true, -) { - val actualPath = path?.let { - Path.of(System.getProperty("user.home")).resolve(path) - } ?: Files.createTempFile("tempPlot", ".html") - val scriptHeader = Context.scriptHeader("js/visionforge-three.js", actualPath, resourceLocation) - makeFile(visionManager, path = path, show = show, title = title, headers = arrayOf(scriptHeader)) +): Unit = makeVisionFile(fragment, path = path, title = title, show = show) { actualPath -> + scriptHeader("js/visionforge-three.js", actualPath, resourceLocation) } \ No newline at end of file