Fully working file renderer.
This commit is contained in:
parent
70ac2c99dd
commit
651a875eee
@ -1,64 +1,20 @@
|
||||
plugins {
|
||||
id("ru.mipt.npm.mpp")
|
||||
id("ru.mipt.npm.jvm")
|
||||
application
|
||||
}
|
||||
|
||||
|
||||
group = "ru.mipt.npm"
|
||||
|
||||
//val kvisionVersion: String = "3.16.2"
|
||||
|
||||
kscience{
|
||||
useSerialization{
|
||||
kscience {
|
||||
useSerialization {
|
||||
json()
|
||||
}
|
||||
application()
|
||||
}
|
||||
|
||||
val ktorVersion: String by rootProject.extra
|
||||
group = "ru.mipt.npm"
|
||||
|
||||
kotlin {
|
||||
js{
|
||||
browser {
|
||||
webpackTask {
|
||||
this.outputFileName = "visionforge-solid.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
afterEvaluate {
|
||||
val jsBrowserDistribution by tasks.getting
|
||||
|
||||
jvm {
|
||||
withJava()
|
||||
compilations[org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME]?.apply {
|
||||
tasks.getByName<ProcessResources>(processResourcesTaskName) {
|
||||
dependsOn(jsBrowserDistribution)
|
||||
afterEvaluate {
|
||||
from(jsBrowserDistribution)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
implementation(project(":visionforge-solid"))
|
||||
}
|
||||
}
|
||||
jvmMain {
|
||||
dependencies {
|
||||
implementation(project(":visionforge-server"))
|
||||
}
|
||||
}
|
||||
jsMain {
|
||||
dependencies {
|
||||
implementation(project(":visionforge-threejs"))
|
||||
}
|
||||
}
|
||||
}
|
||||
dependencies{
|
||||
implementation(project(":visionforge-threejs:visionforge-threejs-server"))
|
||||
}
|
||||
|
||||
application {
|
||||
|
@ -1,17 +0,0 @@
|
||||
package ru.mipt.npm.sat
|
||||
|
||||
import hep.dataforge.context.Global
|
||||
import hep.dataforge.vision.solid.SolidManager
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class GeometrySerializationTest {
|
||||
@Test
|
||||
fun testSerialization(){
|
||||
val geometry = visionOfSatellite()
|
||||
val manager = Global.plugins.fetch(SolidManager)
|
||||
val string = manager.visionManager.encodeToString(geometry)
|
||||
val reconstructed = manager.visionManager.decodeFromString(string)
|
||||
assertEquals(geometry.config,reconstructed.config)
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package ru.mipt.npm.sat
|
||||
|
||||
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
|
||||
|
||||
fun main() {
|
||||
//Loading three-js renderer
|
||||
Global.plugins.load(ThreePlugin)
|
||||
//Fetch from server and render visions for all outputs
|
||||
window.onload = {
|
||||
Global.plugins.fetch(VisionClient).renderAllVisions()
|
||||
}
|
||||
}
|
@ -1,14 +1,11 @@
|
||||
package ru.mipt.npm.sat
|
||||
|
||||
|
||||
import hep.dataforge.context.Global
|
||||
import hep.dataforge.names.toName
|
||||
import hep.dataforge.vision.server.*
|
||||
import hep.dataforge.vision.solid.Solid
|
||||
import hep.dataforge.vision.solid.SolidManager
|
||||
import hep.dataforge.vision.solid.color
|
||||
import hep.dataforge.vision.visionManager
|
||||
import io.ktor.util.KtorExperimentalAPI
|
||||
import hep.dataforge.vision.three.server.*
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
@ -16,22 +13,13 @@ import kotlinx.html.div
|
||||
import kotlinx.html.h1
|
||||
import kotlin.random.Random
|
||||
|
||||
@OptIn(KtorExperimentalAPI::class)
|
||||
fun main() {
|
||||
//Create a geometry
|
||||
val sat = visionOfSatellite(ySegments = 3)
|
||||
|
||||
val context = Global.context("SAT") {
|
||||
//need to install solids extension, vision manager is installed automatically
|
||||
plugin(SolidManager)
|
||||
}
|
||||
|
||||
// fetch vision manager
|
||||
val visionManager = context.visionManager
|
||||
|
||||
val server = visionManager.serve {
|
||||
//use client library
|
||||
useScript("visionforge-solid.js")
|
||||
useThreeJs()
|
||||
//use css
|
||||
useCss("css/styles.css")
|
||||
page {
|
||||
@ -44,9 +32,12 @@ fun main() {
|
||||
|
||||
server.show()
|
||||
|
||||
context.launch {
|
||||
GlobalScope.launch {
|
||||
while (isActive) {
|
||||
val target = "layer[${Random.nextInt(1, 11)}].segment[${Random.nextInt(3)},${Random.nextInt(3)}]".toName()
|
||||
val randomLayer = Random.nextInt(1, 11)
|
||||
val randomI = Random.nextInt(1, 4)
|
||||
val randomJ = Random.nextInt(1, 4)
|
||||
val target = "layer[$randomLayer].segment[$randomI,$randomJ]".toName()
|
||||
(sat[target] as? Solid)?.color("red")
|
||||
delay(300)
|
||||
(sat[target] as? Solid)?.color = "green"
|
||||
@ -54,7 +45,7 @@ fun main() {
|
||||
}
|
||||
}
|
||||
|
||||
println("Press Enter to close server")
|
||||
println("Enter 'exit' to close server")
|
||||
while (readLine() != "exit") {
|
||||
//
|
||||
}
|
@ -12,7 +12,14 @@ repositories{
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvm()
|
||||
jvm{
|
||||
compilations.all {
|
||||
kotlinOptions.jvmTarget = "11"
|
||||
}
|
||||
testRuns["test"].executionTask.configure {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
}
|
||||
js(IR) {
|
||||
browser {
|
||||
}
|
||||
@ -36,6 +43,7 @@ kotlin {
|
||||
val jvmMain by getting{
|
||||
dependencies {
|
||||
implementation("com.github.Ricky12Awesome:json-schema-serialization:0.6.6")
|
||||
implementation(project(":visionforge-threejs:visionforge-threejs-server"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
package ru.mipt.npm.sat
|
||||
|
||||
import hep.dataforge.vision.VisionManager
|
||||
import hep.dataforge.vision.html.fragment
|
||||
import hep.dataforge.vision.solid.box
|
||||
import hep.dataforge.vision.three.server.makeFile
|
||||
import hep.dataforge.vision.three.server.solid
|
||||
|
||||
fun main() {
|
||||
val fragment = VisionManager.fragment {
|
||||
vision("canvas") {
|
||||
solid {
|
||||
box(100, 100, 100)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fragment.makeFile()
|
||||
}
|
@ -40,6 +40,7 @@ include(
|
||||
":visionforge-solid",
|
||||
":visionforge-fx",
|
||||
":visionforge-threejs",
|
||||
":visionforge-threejs:visionforge-threejs-server",
|
||||
":visionforge-gdml",
|
||||
":visionforge-server",
|
||||
":demo:spatial-showcase",
|
||||
|
@ -110,23 +110,21 @@ public fun Vision.flowChanges(
|
||||
manager: VisionManager,
|
||||
collectionDuration: Duration,
|
||||
): Flow<VisionChange> = flow {
|
||||
supervisorScope {
|
||||
val mutex = Mutex()
|
||||
val mutex = Mutex()
|
||||
|
||||
var collector = VisionChangeBuilder()
|
||||
collectChange(Name.EMPTY, this@flowChanges, mutex) { collector }
|
||||
var collector = VisionChangeBuilder()
|
||||
manager.context.collectChange(Name.EMPTY, this@flowChanges, mutex) { collector }
|
||||
|
||||
while (currentCoroutineContext().isActive) {
|
||||
//Wait for changes to accumulate
|
||||
delay(collectionDuration)
|
||||
//Propagate updates only if something is changed
|
||||
if (!collector.isEmpty()) {
|
||||
//emit changes
|
||||
mutex.withLock {
|
||||
emit(collector.isolate(manager))
|
||||
//Reset the collector
|
||||
collector = VisionChangeBuilder()
|
||||
}
|
||||
while (currentCoroutineContext().isActive) {
|
||||
//Wait for changes to accumulate
|
||||
delay(collectionDuration)
|
||||
//Propagate updates only if something is changed
|
||||
if (!collector.isEmpty()) {
|
||||
//emit changes
|
||||
mutex.withLock {
|
||||
emit(collector.isolate(manager))
|
||||
//Reset the collector
|
||||
collector = VisionChangeBuilder()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package hep.dataforge.vision.html
|
||||
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.vision.VisionManager
|
||||
import kotlinx.html.FlowContent
|
||||
import kotlinx.html.TagConsumer
|
||||
|
||||
@ -13,4 +15,7 @@ public fun FlowContent.fragment(fragment: HtmlFragment) {
|
||||
fragment(consumer)
|
||||
}
|
||||
|
||||
public typealias HtmlVisionFragment = VisionTagConsumer<*>.() -> Unit
|
||||
public typealias HtmlVisionFragment = VisionTagConsumer<*>.() -> Unit
|
||||
|
||||
@DFExperimental
|
||||
public fun VisionManager.Companion.fragment(content: HtmlVisionFragment): VisionTagConsumer<*>.() -> Unit = content
|
@ -1,5 +1,7 @@
|
||||
package hep.dataforge.vision
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.vision.html.HtmlFragment
|
||||
import kotlinx.html.link
|
||||
import kotlinx.html.script
|
||||
@ -33,6 +35,8 @@ public enum class ResourceLocation {
|
||||
EMBED
|
||||
}
|
||||
|
||||
internal const val DATAFORGE_ASSETS_PATH = ".dataforge/assets"
|
||||
|
||||
|
||||
/**
|
||||
* Check if the asset exists in given local location and put it there if it does not
|
||||
@ -62,14 +66,11 @@ internal fun checkOrStoreFile(basePath: Path, filePath: Path, resource: String):
|
||||
* A header that automatically copies relevant scripts to given path
|
||||
*/
|
||||
internal fun fileScriptHeader(
|
||||
basePath: Path,
|
||||
scriptPath: Path,
|
||||
resource: String
|
||||
path: Path,
|
||||
): HtmlFragment = {
|
||||
val relativePath = checkOrStoreFile(basePath, scriptPath, resource)
|
||||
script {
|
||||
type = "text/javascript"
|
||||
src = relativePath.toString()
|
||||
src = path.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,7 +87,7 @@ internal fun embedScriptHeader(resource: String): HtmlFragment = {
|
||||
internal fun fileCssHeader(
|
||||
basePath: Path,
|
||||
cssPath: Path,
|
||||
resource: String
|
||||
resource: String,
|
||||
): HtmlFragment = {
|
||||
val relativePath = checkOrStoreFile(basePath, cssPath, resource)
|
||||
link {
|
||||
@ -95,6 +96,37 @@ internal fun fileCssHeader(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a script header, automatically copying file to appropriate location
|
||||
*/
|
||||
@DFExperimental
|
||||
public fun Context.Companion.scriptHeader(
|
||||
scriptResource: String,
|
||||
basePath: Path?,
|
||||
resourceLocation: ResourceLocation,
|
||||
): HtmlFragment {
|
||||
val targetPath = if (basePath == null) null else {
|
||||
when (resourceLocation) {
|
||||
ResourceLocation.LOCAL -> checkOrStoreFile(
|
||||
basePath,
|
||||
Path.of(DATAFORGE_ASSETS_PATH),
|
||||
scriptResource
|
||||
)
|
||||
ResourceLocation.SYSTEM -> checkOrStoreFile(
|
||||
Path.of("."),
|
||||
Path.of(System.getProperty("user.home")).resolve(DATAFORGE_ASSETS_PATH),
|
||||
scriptResource
|
||||
)
|
||||
ResourceLocation.EMBED -> null
|
||||
}
|
||||
}
|
||||
return if (targetPath == null) {
|
||||
embedScriptHeader(scriptResource)
|
||||
} else {
|
||||
fileScriptHeader(targetPath)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
///**
|
||||
// * A system-wide plotly store location
|
||||
|
@ -1,5 +1,6 @@
|
||||
package hep.dataforge.vision
|
||||
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.vision.html.*
|
||||
import kotlinx.html.*
|
||||
import kotlinx.html.stream.createHTML
|
||||
@ -8,11 +9,17 @@ import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Make a file with the embedded vision data
|
||||
*/
|
||||
public fun HtmlVisionFragment.makeFile(manager: VisionManager, vararg headers: HtmlFragment, path: Path? = null, show: Boolean = true) {
|
||||
@DFExperimental
|
||||
public fun HtmlVisionFragment.makeFile(
|
||||
manager: VisionManager,
|
||||
vararg headers: HtmlFragment,
|
||||
path: Path? = null,
|
||||
title: String = "VisionForge page",
|
||||
show: Boolean = true,
|
||||
) {
|
||||
val actualFile = path ?: Files.createTempFile("tempPlot", ".html")
|
||||
Files.createDirectories(actualFile.parent)
|
||||
val htmlString = createHTML().apply {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package hep.dataforge.vision.server
|
||||
package hep.dataforge.vision.three.server
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.meta.*
|
||||
@ -12,7 +12,7 @@ import hep.dataforge.vision.html.HtmlFragment
|
||||
import hep.dataforge.vision.html.HtmlVisionFragment
|
||||
import hep.dataforge.vision.html.VisionTagConsumer
|
||||
import hep.dataforge.vision.html.fragment
|
||||
import hep.dataforge.vision.server.VisionServer.Companion.DEFAULT_PAGE
|
||||
import hep.dataforge.vision.three.server.VisionServer.Companion.DEFAULT_PAGE
|
||||
import io.ktor.application.*
|
||||
import io.ktor.features.CORS
|
||||
import io.ktor.features.CallLogging
|
@ -134,7 +134,9 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
||||
}
|
||||
|
||||
override fun render(element: Element, vision: Vision, meta: Meta) {
|
||||
createCanvas(element, Canvas3DOptions.read(meta)).render(vision as? Solid ?: error("Only solids are rendered"))
|
||||
createCanvas(element, Canvas3DOptions.read(meta)).render(
|
||||
vision as? Solid ?: error("Solid expected but ${vision::class} is found")
|
||||
)
|
||||
}
|
||||
|
||||
public companion object : PluginFactory<ThreePlugin> {
|
||||
|
@ -0,0 +1,52 @@
|
||||
plugins {
|
||||
id("ru.mipt.npm.mpp")
|
||||
}
|
||||
|
||||
|
||||
kscience{
|
||||
useSerialization{
|
||||
json()
|
||||
}
|
||||
}
|
||||
|
||||
val ktorVersion: String by rootProject.extra
|
||||
|
||||
kotlin {
|
||||
js{
|
||||
browser {
|
||||
webpackTask {
|
||||
this.outputFileName = "js/visionforge-three.js"
|
||||
}
|
||||
}
|
||||
binaries.executable()
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
val jsBrowserDistribution by tasks.getting
|
||||
|
||||
tasks.getByName<ProcessResources>("jvmProcessResources") {
|
||||
dependsOn(jsBrowserDistribution)
|
||||
afterEvaluate {
|
||||
from(jsBrowserDistribution)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
api(project(":visionforge-solid"))
|
||||
}
|
||||
}
|
||||
jvmMain {
|
||||
dependencies {
|
||||
api(project(":visionforge-server"))
|
||||
}
|
||||
}
|
||||
jsMain {
|
||||
dependencies {
|
||||
api(project(":visionforge-threejs"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
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)
|
@ -0,0 +1,48 @@
|
||||
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() {
|
||||
//Fetch from server and render visions for all outputs
|
||||
window.onload = {
|
||||
clientManager.renderAllVisions()
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
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.scriptHeader
|
||||
import hep.dataforge.vision.solid.SolidGroup
|
||||
import hep.dataforge.vision.solid.SolidManager
|
||||
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(
|
||||
path: Path? = null,
|
||||
title: String = "VisionForge page",
|
||||
resourceLocation: ResourceLocation = ResourceLocation.SYSTEM,
|
||||
show: Boolean = true,
|
||||
) {
|
||||
val scriptHeader = Context.scriptHeader("/js/visionforge-three.js", path, resourceLocation)
|
||||
makeFile(visionManager, path = path, show = show, title = title, headers = arrayOf(scriptHeader))
|
||||
}
|
Loading…
Reference in New Issue
Block a user