v0.2.0-dev-22 #47
@ -20,7 +20,7 @@ allprojects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "space.kscience"
|
group = "space.kscience"
|
||||||
version = "0.2.0-dev-18"
|
version = "0.2.0-dev-19"
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
|
@ -1,29 +1,20 @@
|
|||||||
package space.kscience.visionforge.gdml.demo
|
package space.kscience.visionforge.gdml.demo
|
||||||
|
|
||||||
import kotlinx.browser.window
|
import kotlinx.browser.window
|
||||||
import kotlinx.css.height
|
|
||||||
import kotlinx.css.vh
|
|
||||||
import org.w3c.files.FileReader
|
import org.w3c.files.FileReader
|
||||||
import org.w3c.files.get
|
import org.w3c.files.get
|
||||||
import react.*
|
import react.*
|
||||||
import react.dom.h1
|
|
||||||
import ringui.grid.ringCol
|
|
||||||
import ringui.grid.ringGrid
|
|
||||||
import ringui.grid.ringRow
|
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
import space.kscience.dataforge.context.fetch
|
import space.kscience.dataforge.context.fetch
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.gdml.Gdml
|
import space.kscience.gdml.Gdml
|
||||||
import space.kscience.gdml.decodeFromString
|
import space.kscience.gdml.decodeFromString
|
||||||
import space.kscience.visionforge.bootstrap.nameCrumbs
|
|
||||||
import space.kscience.visionforge.gdml.toVision
|
import space.kscience.visionforge.gdml.toVision
|
||||||
import space.kscience.visionforge.react.ThreeCanvasComponent
|
import space.kscience.visionforge.ring.ThreeCanvasWithControls
|
||||||
import space.kscience.visionforge.react.flexColumn
|
import space.kscience.visionforge.ring.tab
|
||||||
import space.kscience.visionforge.ring.ringThreeControls
|
|
||||||
import space.kscience.visionforge.solid.Solid
|
import space.kscience.visionforge.solid.Solid
|
||||||
import space.kscience.visionforge.solid.Solids
|
import space.kscience.visionforge.solid.Solids
|
||||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
import styled.styledDiv
|
||||||
import styled.css
|
|
||||||
|
|
||||||
external interface GDMLAppProps : RProps {
|
external interface GDMLAppProps : RProps {
|
||||||
var context: Context
|
var context: Context
|
||||||
@ -33,19 +24,7 @@ external interface GDMLAppProps : RProps {
|
|||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
|
val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
|
||||||
var selected by useState { props.selected }
|
|
||||||
var vision: Solid? by useState { props.vision }
|
var vision: Solid? by useState { props.vision }
|
||||||
|
|
||||||
val onSelect: (Name?) -> Unit = {
|
|
||||||
selected = it
|
|
||||||
}
|
|
||||||
|
|
||||||
val options = useMemo {
|
|
||||||
Canvas3DOptions.invoke {
|
|
||||||
this.onSelect = onSelect
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val visionManager = useMemo(props.context) { props.context.fetch(Solids).visionManager }
|
val visionManager = useMemo(props.context) { props.context.fetch(Solids).visionManager }
|
||||||
|
|
||||||
fun loadData(name: String, data: String) {
|
fun loadData(name: String, data: String) {
|
||||||
@ -64,43 +43,16 @@ val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
|
|||||||
vision = parsedVision as? Solid ?: error("Parsed vision is not a solid")
|
vision = parsedVision as? Solid ?: error("Parsed vision is not a solid")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
styledDiv {
|
||||||
ringGrid {
|
child(ThreeCanvasWithControls) {
|
||||||
ringRow {
|
attrs {
|
||||||
ringCol {
|
this.context = props.context
|
||||||
attrs {
|
this.solid = vision
|
||||||
lg = 9
|
this.selected = props.selected
|
||||||
}
|
tab("Load") {
|
||||||
flexColumn {
|
|
||||||
css {
|
|
||||||
height = 100.vh
|
|
||||||
}
|
|
||||||
h1 { +"GDML/JSON loader demo" }
|
|
||||||
//canvas
|
|
||||||
|
|
||||||
child(ThreeCanvasComponent) {
|
|
||||||
attrs {
|
|
||||||
this.context = props.context
|
|
||||||
this.solid = vision
|
|
||||||
this.selected = selected
|
|
||||||
this.options = options
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
ringCol {
|
|
||||||
attrs {
|
|
||||||
lg = 3
|
|
||||||
}
|
|
||||||
flexColumn {
|
|
||||||
css {
|
|
||||||
height = 100.vh
|
|
||||||
}
|
|
||||||
fileDrop("(drag file here)") { files ->
|
fileDrop("(drag file here)") { files ->
|
||||||
val file = files?.get(0)
|
val file = files?.get(0)
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
|
|
||||||
FileReader().apply {
|
FileReader().apply {
|
||||||
onload = {
|
onload = {
|
||||||
val string = result as String
|
val string = result as String
|
||||||
@ -110,8 +62,6 @@ val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nameCrumbs(selected, "World", onSelect)
|
|
||||||
ringThreeControls(options, vision, selected, onSelect)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import space.kscience.visionforge.Application
|
|||||||
import space.kscience.visionforge.VisionClient
|
import space.kscience.visionforge.VisionClient
|
||||||
import space.kscience.visionforge.gdml.toVision
|
import space.kscience.visionforge.gdml.toVision
|
||||||
import space.kscience.visionforge.ring.ThreeCanvasWithControls
|
import space.kscience.visionforge.ring.ThreeCanvasWithControls
|
||||||
import space.kscience.visionforge.ring.ThreeWithControls
|
import space.kscience.visionforge.ring.ThreeWithControlsPlugin
|
||||||
import space.kscience.visionforge.startApplication
|
import space.kscience.visionforge.startApplication
|
||||||
import styled.css
|
import styled.css
|
||||||
import styled.styledDiv
|
import styled.styledDiv
|
||||||
@ -21,7 +21,7 @@ private class JsPlaygroundApp : Application {
|
|||||||
override fun start(state: Map<String, Any>) {
|
override fun start(state: Map<String, Any>) {
|
||||||
|
|
||||||
val playgroundContext = Context {
|
val playgroundContext = Context {
|
||||||
plugin(ThreeWithControls)
|
plugin(ThreeWithControlsPlugin)
|
||||||
plugin(VisionClient)
|
plugin(VisionClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import space.kscience.dataforge.misc.DFExperimental
|
import space.kscience.dataforge.misc.DFExperimental
|
||||||
import space.kscience.visionforge.plotly.PlotlyPlugin
|
import space.kscience.visionforge.plotly.PlotlyPlugin
|
||||||
import space.kscience.visionforge.ring.ThreeWithControls
|
import space.kscience.visionforge.ring.ThreeWithControlsPlugin
|
||||||
import space.kscience.visionforge.runVisionClient
|
import space.kscience.visionforge.runVisionClient
|
||||||
|
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
fun main() = runVisionClient {
|
fun main() = runVisionClient {
|
||||||
plugin(PlotlyPlugin)
|
plugin(PlotlyPlugin)
|
||||||
plugin(ThreeWithControls)
|
plugin(ThreeWithControlsPlugin)
|
||||||
}
|
}
|
@ -1,12 +1,12 @@
|
|||||||
package space.kscience.visionforge.gdml.jupyter
|
package space.kscience.visionforge.gdml.jupyter
|
||||||
|
|
||||||
import space.kscience.dataforge.misc.DFExperimental
|
import space.kscience.dataforge.misc.DFExperimental
|
||||||
import space.kscience.visionforge.ring.ThreeWithControls
|
import space.kscience.visionforge.ring.ThreeWithControlsPlugin
|
||||||
import space.kscience.visionforge.runVisionClient
|
import space.kscience.visionforge.runVisionClient
|
||||||
|
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
@JsExport
|
@JsExport
|
||||||
fun main(): Unit = runVisionClient {
|
fun main(): Unit = runVisionClient {
|
||||||
plugin(ThreeWithControls)
|
plugin(ThreeWithControlsPlugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
package space.kscience.visionforge.react
|
package space.kscience.visionforge.react
|
||||||
|
|
||||||
import kotlinx.css.margin
|
|
||||||
import kotlinx.css.padding
|
|
||||||
import kotlinx.css.px
|
|
||||||
import kotlinx.html.InputType
|
import kotlinx.html.InputType
|
||||||
import kotlinx.html.js.onChangeFunction
|
import kotlinx.html.js.onChangeFunction
|
||||||
import org.w3c.dom.HTMLInputElement
|
import org.w3c.dom.HTMLInputElement
|
||||||
@ -15,7 +12,6 @@ import space.kscience.dataforge.meta.double
|
|||||||
import space.kscience.dataforge.meta.get
|
import space.kscience.dataforge.meta.get
|
||||||
import space.kscience.dataforge.meta.string
|
import space.kscience.dataforge.meta.string
|
||||||
import space.kscience.dataforge.values.asValue
|
import space.kscience.dataforge.values.asValue
|
||||||
import styled.css
|
|
||||||
import styled.styledInput
|
import styled.styledInput
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
@ -42,10 +38,6 @@ public val RangeValueChooser: FunctionalComponent<ValueChooserProps> =
|
|||||||
|
|
||||||
flexRow {
|
flexRow {
|
||||||
styledInput(type = InputType.checkBox) {
|
styledInput(type = InputType.checkBox) {
|
||||||
css{
|
|
||||||
padding(0.px)
|
|
||||||
margin(0.px)
|
|
||||||
}
|
|
||||||
attrs {
|
attrs {
|
||||||
defaultChecked = rangeDisabled.not()
|
defaultChecked = rangeDisabled.not()
|
||||||
onChangeFunction = handleDisable
|
onChangeFunction = handleDisable
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package space.kscience.visionforge.react
|
package space.kscience.visionforge.react
|
||||||
|
|
||||||
import kotlinx.css.FlexBasis
|
import kotlinx.css.*
|
||||||
import kotlinx.css.flexBasis
|
|
||||||
import kotlinx.css.flexGrow
|
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import org.w3c.dom.HTMLElement
|
import org.w3c.dom.HTMLElement
|
||||||
import react.*
|
import react.*
|
||||||
@ -39,7 +37,7 @@ public val ThreeCanvasComponent: FunctionalComponent<ThreeCanvasProps> = functio
|
|||||||
useEffect(listOf(props.solid, props.options, elementRef)) {
|
useEffect(listOf(props.solid, props.options, elementRef)) {
|
||||||
if (canvas == null) {
|
if (canvas == null) {
|
||||||
val element = elementRef.current as? HTMLElement ?: error("Canvas element not found")
|
val element = elementRef.current as? HTMLElement ?: error("Canvas element not found")
|
||||||
canvas = three.getOrCreateCanvas(element, props.options ?: Canvas3DOptions())
|
canvas = ThreeCanvas(three, element, props.options ?: Canvas3DOptions())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,8 +53,10 @@ public val ThreeCanvasComponent: FunctionalComponent<ThreeCanvasProps> = functio
|
|||||||
|
|
||||||
styledDiv {
|
styledDiv {
|
||||||
css {
|
css {
|
||||||
flexGrow = 1.0
|
maxWidth = 100.vw
|
||||||
flexBasis = FlexBasis.fill
|
maxHeight = 100.vh
|
||||||
|
display = Display.block
|
||||||
|
bottom = 0.px
|
||||||
}
|
}
|
||||||
ref = elementRef
|
ref = elementRef
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,11 @@ package space.kscience.visionforge.ring
|
|||||||
|
|
||||||
import kotlinx.css.*
|
import kotlinx.css.*
|
||||||
import react.*
|
import react.*
|
||||||
|
import ringui.grid.RowPosition
|
||||||
import ringui.grid.ringCol
|
import ringui.grid.ringCol
|
||||||
import ringui.grid.ringGrid
|
import ringui.grid.ringGrid
|
||||||
import ringui.grid.ringRow
|
import ringui.grid.ringRow
|
||||||
|
import ringui.tabs.ringTab
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.visionforge.react.ThreeCanvasComponent
|
import space.kscience.visionforge.react.ThreeCanvasComponent
|
||||||
@ -17,6 +19,11 @@ public external interface ThreeCanvasWithControlsProps : RProps {
|
|||||||
public var context: Context
|
public var context: Context
|
||||||
public var solid: Solid?
|
public var solid: Solid?
|
||||||
public var selected: Name?
|
public var selected: Name?
|
||||||
|
public var additionalTabs: Map<String, RBuilder.() -> Unit>?
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun ThreeCanvasWithControlsProps.tab(title: String, block: RBuilder.()->Unit){
|
||||||
|
additionalTabs = (additionalTabs?: emptyMap()) + (title to block)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
@ -35,11 +42,15 @@ public val ThreeCanvasWithControls: (props: ThreeCanvasWithControlsProps) -> dyn
|
|||||||
styledDiv {
|
styledDiv {
|
||||||
css {
|
css {
|
||||||
height = 100.pct
|
height = 100.pct
|
||||||
|
width = 100.pct
|
||||||
maxHeight = 100.vh
|
maxHeight = 100.vh
|
||||||
maxWidth = 100.vw
|
maxWidth = 100.vw
|
||||||
}
|
}
|
||||||
ringGrid {
|
ringGrid {
|
||||||
ringRow {
|
ringRow {
|
||||||
|
attrs {
|
||||||
|
start = RowPosition.sm
|
||||||
|
}
|
||||||
ringCol {
|
ringCol {
|
||||||
attrs {
|
attrs {
|
||||||
xs = 12
|
xs = 12
|
||||||
@ -50,12 +61,11 @@ public val ThreeCanvasWithControls: (props: ThreeCanvasWithControlsProps) -> dyn
|
|||||||
child(ThreeCanvasComponent) {
|
child(ThreeCanvasComponent) {
|
||||||
attrs {
|
attrs {
|
||||||
this.context = props.context
|
this.context = props.context
|
||||||
this.solid = props.solid as? Solid
|
this.solid = props.solid
|
||||||
this.selected = selected
|
this.selected = selected
|
||||||
this.options = options
|
this.options = options
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
ringCol {
|
ringCol {
|
||||||
attrs {
|
attrs {
|
||||||
@ -67,11 +77,14 @@ public val ThreeCanvasWithControls: (props: ThreeCanvasWithControlsProps) -> dyn
|
|||||||
styledDiv {
|
styledDiv {
|
||||||
css {
|
css {
|
||||||
padding(top = 4.px)
|
padding(top = 4.px)
|
||||||
|
width = 100.pct
|
||||||
//border(1.px, BorderStyle.solid, Color.lightGray)
|
//border(1.px, BorderStyle.solid, Color.lightGray)
|
||||||
height = 100.pct
|
|
||||||
overflowY = Overflow.auto
|
|
||||||
}
|
}
|
||||||
ringThreeControls(options, props.solid, selected, onSelect)
|
ringThreeControls(options, props.solid, selected, onSelect) {
|
||||||
|
props.additionalTabs?.forEach { (title, builder) ->
|
||||||
|
ringTab(title, title, builder)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import space.kscience.visionforge.solid.Solid
|
|||||||
import space.kscience.visionforge.solid.three.ThreePlugin
|
import space.kscience.visionforge.solid.three.ThreePlugin
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
public class ThreeWithControls : AbstractPlugin(), ElementVisionRenderer {
|
public class ThreeWithControlsPlugin : AbstractPlugin(), ElementVisionRenderer {
|
||||||
public val three: ThreePlugin by require(ThreePlugin)
|
public val three: ThreePlugin by require(ThreePlugin)
|
||||||
|
|
||||||
override val tag: PluginTag get() = Companion.tag
|
override val tag: PluginTag get() = Companion.tag
|
||||||
@ -27,7 +27,7 @@ public class ThreeWithControls : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
react.dom.render(element) {
|
react.dom.render(element) {
|
||||||
child(ThreeCanvasWithControls) {
|
child(ThreeCanvasWithControls) {
|
||||||
attrs {
|
attrs {
|
||||||
this.context = this@ThreeWithControls.context
|
this.context = this@ThreeWithControlsPlugin.context
|
||||||
this.solid = vision as? Solid
|
this.solid = vision as? Solid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,9 +41,9 @@ public class ThreeWithControls : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public companion object : PluginFactory<ThreeWithControls> {
|
public companion object : PluginFactory<ThreeWithControlsPlugin> {
|
||||||
override val tag: PluginTag = PluginTag("vision.threejs.withControls", PluginTag.DATAFORGE_GROUP)
|
override val tag: PluginTag = PluginTag("vision.threejs.withControls", PluginTag.DATAFORGE_GROUP)
|
||||||
override val type: KClass<ThreeWithControls> = ThreeWithControls::class
|
override val type: KClass<ThreeWithControlsPlugin> = ThreeWithControlsPlugin::class
|
||||||
override fun invoke(meta: Meta, context: Context): ThreeWithControls = ThreeWithControls()
|
override fun invoke(meta: Meta, context: Context): ThreeWithControlsPlugin = ThreeWithControlsPlugin()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -45,12 +45,7 @@ public class Clipping : Scheme() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Canvas3DOptions : Scheme() {
|
public class CanvasSize : 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)
|
|
||||||
|
|
||||||
public var minSize: Int by int(400)
|
public var minSize: Int by int(400)
|
||||||
public var minWith: Number by number { minSize }
|
public var minWith: Number by number { minSize }
|
||||||
public var minHeight: Number by number { minSize }
|
public var minHeight: Number by number { minSize }
|
||||||
@ -59,6 +54,26 @@ public class Canvas3DOptions : Scheme() {
|
|||||||
public var maxWith: Number by number { maxSize }
|
public var maxWith: Number by number { maxSize }
|
||||||
public var maxHeight: Number by number { maxSize }
|
public var maxHeight: Number by number { maxSize }
|
||||||
|
|
||||||
|
public companion object : SchemeSpec<CanvasSize>(::CanvasSize) {
|
||||||
|
override val descriptor: NodeDescriptor = NodeDescriptor {
|
||||||
|
value(CanvasSize::minSize)
|
||||||
|
value(CanvasSize::minWith)
|
||||||
|
value(CanvasSize::minHeight)
|
||||||
|
value(CanvasSize::maxSize)
|
||||||
|
value(CanvasSize::maxWith)
|
||||||
|
value(CanvasSize::maxHeight)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
public var size: CanvasSize by spec(CanvasSize)
|
||||||
|
|
||||||
public var layers: List<Number> by numberList(0)
|
public var layers: List<Number> by numberList(0)
|
||||||
|
|
||||||
public var clipping: Clipping by spec(Clipping)
|
public var clipping: Clipping by spec(Clipping)
|
||||||
@ -71,30 +86,19 @@ public class Canvas3DOptions : Scheme() {
|
|||||||
NodeDescriptor {
|
NodeDescriptor {
|
||||||
scheme(Canvas3DOptions::axes, Axes)
|
scheme(Canvas3DOptions::axes, Axes)
|
||||||
scheme(Canvas3DOptions::light, Light)
|
scheme(Canvas3DOptions::light, Light)
|
||||||
|
|
||||||
scheme(Canvas3DOptions::camera, Camera) {
|
scheme(Canvas3DOptions::camera, Camera) {
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
scheme(Canvas3DOptions::controls, Controls) {
|
scheme(Canvas3DOptions::controls, Controls) {
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
value(Canvas3DOptions::minSize) {
|
|
||||||
hide()
|
scheme(Canvas3DOptions::size, CanvasSize) {
|
||||||
}
|
|
||||||
value(Canvas3DOptions::minWith) {
|
|
||||||
hide()
|
|
||||||
}
|
|
||||||
value(Canvas3DOptions::minHeight) {
|
|
||||||
hide()
|
|
||||||
}
|
|
||||||
value(Canvas3DOptions::maxSize) {
|
|
||||||
hide()
|
|
||||||
}
|
|
||||||
value(Canvas3DOptions::maxWith) {
|
|
||||||
hide()
|
|
||||||
}
|
|
||||||
value(Canvas3DOptions::maxHeight) {
|
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
value(Canvas3DOptions::layers) {
|
value(Canvas3DOptions::layers) {
|
||||||
type(ValueType.NUMBER)
|
type(ValueType.NUMBER)
|
||||||
multiple = true
|
multiple = true
|
||||||
@ -108,8 +112,8 @@ public class Canvas3DOptions : Scheme() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun Canvas3DOptions.computeWidth(external: Number): Int =
|
public fun CanvasSize.computeWidth(external: Number): Int =
|
||||||
(external.toInt()).coerceIn(minWith.toInt()..maxWith.toInt())
|
(external.toInt()).coerceIn(minWith.toInt()..maxWith.toInt())
|
||||||
|
|
||||||
public fun Canvas3DOptions.computeHeight(external: Number): Int =
|
public fun CanvasSize.computeHeight(external: Number): Int =
|
||||||
(external.toInt()).coerceIn(minHeight.toInt()..maxHeight.toInt())
|
(external.toInt()).coerceIn(minHeight.toInt()..maxHeight.toInt())
|
||||||
|
@ -20,6 +20,7 @@ import info.laht.threekt.objects.Mesh
|
|||||||
import info.laht.threekt.scenes.Scene
|
import info.laht.threekt.scenes.Scene
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import org.w3c.dom.HTMLCanvasElement
|
import org.w3c.dom.HTMLCanvasElement
|
||||||
|
import org.w3c.dom.HTMLElement
|
||||||
import org.w3c.dom.Node
|
import org.w3c.dom.Node
|
||||||
import org.w3c.dom.events.MouseEvent
|
import org.w3c.dom.events.MouseEvent
|
||||||
import space.kscience.dataforge.context.info
|
import space.kscience.dataforge.context.info
|
||||||
@ -40,10 +41,8 @@ import kotlin.math.sin
|
|||||||
public class ThreeCanvas(
|
public class ThreeCanvas(
|
||||||
public val three: ThreePlugin,
|
public val three: ThreePlugin,
|
||||||
public val element: Element,
|
public val element: Element,
|
||||||
public val options: Canvas3DOptions = Canvas3DOptions()
|
public val options: Canvas3DOptions = Canvas3DOptions(),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|
||||||
private var boundingBox: Box3? = null
|
private var boundingBox: Box3? = null
|
||||||
private var root: Object3D? = null
|
private var root: Object3D? = null
|
||||||
set(value) {
|
set(value) {
|
||||||
@ -102,40 +101,10 @@ public class ThreeCanvas(
|
|||||||
antialias = true
|
antialias = true
|
||||||
}.apply {
|
}.apply {
|
||||||
setClearColor(Colors.skyblue, 1)
|
setClearColor(Colors.skyblue, 1)
|
||||||
//Clipping planes
|
|
||||||
options.onChange(this@ThreeCanvas) { name, _, _ ->
|
|
||||||
if (name.startsWith(Canvas3DOptions::clipping.name.asName())) {
|
|
||||||
localClippingEnabled = true
|
|
||||||
val clipping = options.clipping
|
|
||||||
if(!clipping.isEmpty()) {
|
|
||||||
boundingBox?.let { boundingBox ->
|
|
||||||
val xClippingPlane = clipping.x?.let {
|
|
||||||
val absoluteValue = boundingBox.min.x + (boundingBox.max.x - boundingBox.min.x) * it
|
|
||||||
Plane(Vector3(-1.0, 0.0, 0.0), absoluteValue)
|
|
||||||
|
|
||||||
}
|
|
||||||
val yClippingPlane = clipping.y?.let {
|
|
||||||
val absoluteValue = boundingBox.min.y + (boundingBox.max.y - boundingBox.min.y) * it
|
|
||||||
Plane(Vector3(0.0, -1.0, 0.0), absoluteValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
val zClippingPlane = clipping.z?.let {
|
|
||||||
val absoluteValue = boundingBox.min.z + (boundingBox.max.z - boundingBox.min.z) * it
|
|
||||||
Plane(Vector3(0.0, 0.0, -1.0), absoluteValue)
|
|
||||||
}
|
|
||||||
clippingPlanes = listOfNotNull(xClippingPlane, yClippingPlane, zClippingPlane).toTypedArray()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
localClippingEnabled = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val canvas = (renderer.domElement as HTMLCanvasElement).apply {
|
private val canvas = (renderer.domElement as HTMLCanvasElement).apply {
|
||||||
className += "three-canvas"
|
className += "three-canvas"
|
||||||
width = 600
|
|
||||||
height = 600
|
|
||||||
style.apply {
|
style.apply {
|
||||||
width = "100%"
|
width = "100%"
|
||||||
height = "100%"
|
height = "100%"
|
||||||
@ -143,35 +112,29 @@ public class ThreeCanvas(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force camera aspect ration and renderer size recalculation
|
||||||
|
*/
|
||||||
|
private fun updateSize() {
|
||||||
|
val width = element.clientWidth
|
||||||
|
val height = element.clientHeight
|
||||||
|
canvas.width = width
|
||||||
|
canvas.height = height
|
||||||
|
renderer.setSize(width, height, false)
|
||||||
|
camera.aspect = width.toDouble() / height.toDouble()
|
||||||
|
camera.updateProjectionMatrix()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach canvas to given [HTMLElement]
|
||||||
|
*/
|
||||||
init {
|
init {
|
||||||
check(element.getElementsByClassName("three-canvas").length == 0) {
|
check(element.getElementsByClassName("three-canvas").length == 0) {
|
||||||
"Three canvas already created in this element"
|
"Three canvas already created in this element"
|
||||||
}
|
}
|
||||||
element.appendChild(canvas)
|
element.appendChild(canvas)
|
||||||
updateSize()
|
updateSize()
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Force camera aspect ration and renderer size recalculation
|
|
||||||
*/
|
|
||||||
public fun updateSize() {
|
|
||||||
val width = canvas.clientWidth
|
|
||||||
val height = canvas.clientHeight
|
|
||||||
canvas.style.apply {
|
|
||||||
minWidth = "${options.minWith.toInt()}px"
|
|
||||||
maxWidth = "${options.maxWith.toInt()}px"
|
|
||||||
minHeight = "${options.minHeight.toInt()}px"
|
|
||||||
maxHeight = "${options.maxHeight.toInt()}px"
|
|
||||||
}
|
|
||||||
renderer.setSize(width, height, false)
|
|
||||||
camera.aspect = width.toDouble() / height.toDouble()
|
|
||||||
camera.updateProjectionMatrix()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attach canvas to given [HTMLElement]
|
|
||||||
*/
|
|
||||||
init {
|
|
||||||
canvas.addEventListener("pointerdown", {
|
canvas.addEventListener("pointerdown", {
|
||||||
val picked = pick()
|
val picked = pick()
|
||||||
options.onSelect?.invoke(picked?.fullName())
|
options.onSelect?.invoke(picked?.fullName())
|
||||||
@ -186,7 +149,7 @@ public class ThreeCanvas(
|
|||||||
}
|
}
|
||||||
}, false)
|
}, false)
|
||||||
|
|
||||||
canvas.onresize = {
|
(element as? HTMLElement)?.onresize = {
|
||||||
updateSize()
|
updateSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,6 +166,43 @@ public class ThreeCanvas(
|
|||||||
|
|
||||||
renderer.render(scene, camera)
|
renderer.render(scene, camera)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Clipping planes
|
||||||
|
options.onChange(this@ThreeCanvas) { name, _, _ ->
|
||||||
|
if (name.startsWith(Canvas3DOptions::clipping.name.asName())) {
|
||||||
|
val clipping = options.clipping
|
||||||
|
if (!clipping.isEmpty()) {
|
||||||
|
renderer.localClippingEnabled = true
|
||||||
|
boundingBox?.let { boundingBox ->
|
||||||
|
val xClippingPlane = clipping.x?.let {
|
||||||
|
val absoluteValue = boundingBox.min.x + (boundingBox.max.x - boundingBox.min.x) * it
|
||||||
|
Plane(Vector3(-1.0, 0.0, 0.0), absoluteValue)
|
||||||
|
|
||||||
|
}
|
||||||
|
val yClippingPlane = clipping.y?.let {
|
||||||
|
val absoluteValue = boundingBox.min.y + (boundingBox.max.y - boundingBox.min.y) * it
|
||||||
|
Plane(Vector3(0.0, -1.0, 0.0), absoluteValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
val zClippingPlane = clipping.z?.let {
|
||||||
|
val absoluteValue = boundingBox.min.z + (boundingBox.max.z - boundingBox.min.z) * it
|
||||||
|
Plane(Vector3(0.0, 0.0, -1.0), absoluteValue)
|
||||||
|
}
|
||||||
|
renderer.clippingPlanes = listOfNotNull(xClippingPlane, yClippingPlane, zClippingPlane).toTypedArray()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
renderer.localClippingEnabled = false
|
||||||
|
}
|
||||||
|
} else if (name.startsWith(Canvas3DOptions::size.name.asName())) {
|
||||||
|
canvas.style.apply {
|
||||||
|
minWidth = "${options.size.minWith.toInt()}px"
|
||||||
|
maxWidth = "${options.size.maxWith.toInt()}px"
|
||||||
|
minHeight = "${options.size.minHeight.toInt()}px"
|
||||||
|
maxHeight = "${options.size.maxHeight.toInt()}px"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user