diff --git a/demo/playground/src/jvmMain/kotlin/allThingsDemo.kt b/demo/playground/src/jvmMain/kotlin/allThingsDemo.kt index 328387c1..5b272b72 100644 --- a/demo/playground/src/jvmMain/kotlin/allThingsDemo.kt +++ b/demo/playground/src/jvmMain/kotlin/allThingsDemo.kt @@ -2,6 +2,7 @@ package space.kscience.visionforge.examples import kotlinx.html.h2 import space.kscience.dataforge.meta.ValueType +import space.kscience.dataforge.meta.invoke import space.kscience.plotly.layout import space.kscience.plotly.models.ScatterMode import space.kscience.plotly.models.TextPosition @@ -12,13 +13,14 @@ import space.kscience.visionforge.markup.markdown import space.kscience.visionforge.plotly.plotly import space.kscience.visionforge.solid.box import space.kscience.visionforge.solid.solid +import space.kscience.visionforge.solid.specifications.Canvas3DOptions import space.kscience.visionforge.solid.z import space.kscience.visionforge.tables.columnTable -import java.nio.file.Paths +import kotlin.io.path.Path fun main() = makeVisionFile( - Paths.get("VisionForgeDemo.html"), + Path("VisionForgeDemo.html"), resourceLocation = ResourceLocation.EMBED ) { markdown { @@ -32,8 +34,15 @@ fun main() = makeVisionFile( h2 { +"3D visualization with Three-js" } vision("3D") { - solid { - box(100, 100, 100, name = "aBox"){ + solid( + Canvas3DOptions { + axes { + size = 200.0 + visible = true + } + } + ) { + box(100, 100, 100, name = "aBox") { z = 50.0 } } diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/VisionTagConsumer.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/VisionTagConsumer.kt index 80a7be7e..05bebfc2 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/VisionTagConsumer.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/VisionTagConsumer.kt @@ -26,7 +26,7 @@ public annotation class VisionDSL * A placeholder object to attach inline vision builders. */ @VisionDSL -public class VisionOutput @PublishedApi internal constructor(public val context: Context, public val name: Name) { +public class VisionOutput @PublishedApi internal constructor(override val context: Context, public val name: Name): ContextAware { public var meta: Meta = Meta.EMPTY private val requirements: MutableSet> = HashSet() @@ -95,9 +95,10 @@ public abstract class VisionTagConsumer( if (!outputMeta.isEmpty()) { //Hard-code output configuration script { + type = "text/json" attributes["class"] = OUTPUT_META_CLASS unsafe { - +manager.jsonFormat.encodeToString(MetaSerializer, outputMeta) + +("\n" + manager.jsonFormat.encodeToString(MetaSerializer, outputMeta) + "\n") } } } diff --git a/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/VisionClient.kt b/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/VisionClient.kt index af3cd574..7d61ce24 100644 --- a/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/VisionClient.kt +++ b/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/VisionClient.kt @@ -176,11 +176,13 @@ public class VisionClient : AbstractPlugin() { } val outputMeta = element.getEmbeddedData(VisionTagConsumer.OUTPUT_META_CLASS)?.let { - VisionManager.defaultJson.decodeFromString(MetaSerializer, it) + VisionManager.defaultJson.decodeFromString(MetaSerializer, it).also { + logger.info { "Output meta for $name: $it" } + } } ?: Meta.EMPTY when { - // fetch data if path is provided + // fetch data if the path is provided element.attributes[OUTPUT_FETCH_ATTRIBUTE] != null -> { val attr = element.attributes[OUTPUT_FETCH_ATTRIBUTE]!! 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 f828101b..4900fc1f 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 @@ -85,5 +85,9 @@ public inline fun VisionOutput.solid(options: Canvas3DOptions? = null, block: So options?.let { meta = options.meta } - return SolidGroup().apply(block) + return SolidGroup().apply(block).apply { + if (children.values.none { it is LightSource }) { + ambientLight() + } + } } 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 d1309849..064597e6 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 @@ -124,7 +124,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer { public fun getOrCreateCanvas( element: Element, - options: Canvas3DOptions = Canvas3DOptions(), + options: Canvas3DOptions, ): ThreeCanvas = canvasCache.getOrPut(element) { ThreeCanvas(this, element, options) } @@ -142,7 +142,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer { internal fun renderSolid( element: Element, vision: Solid, - options: Canvas3DOptions = Canvas3DOptions(), + options: Canvas3DOptions, ): ThreeCanvas = getOrCreateCanvas(element, options).apply { render(vision) } @@ -166,7 +166,7 @@ public fun ThreePlugin.render( element: HTMLElement, obj: Solid, optionsBuilder: Canvas3DOptions.() -> Unit = {}, -): ThreeCanvas = renderSolid(element, obj).apply { +): ThreeCanvas = renderSolid(element, obj, Canvas3DOptions(optionsBuilder)).apply { options.apply(optionsBuilder) }