Fixing new property update model
This commit is contained in:
parent
929832f3a5
commit
6a6d9659ca
@ -2,7 +2,7 @@ plugins {
|
|||||||
id("ru.mipt.npm.project")
|
id("ru.mipt.npm.project")
|
||||||
}
|
}
|
||||||
|
|
||||||
val dataforgeVersion by extra("0.2.1-dev-4")
|
val dataforgeVersion by extra("0.2.1-dev-5")
|
||||||
val ktorVersion by extra("1.4.3")
|
val ktorVersion by extra("1.4.3")
|
||||||
val htmlVersion by extra("0.7.2")
|
val htmlVersion by extra("0.7.2")
|
||||||
val kotlinWrappersVersion by extra("pre.129-kotlin-1.4.20")
|
val kotlinWrappersVersion by extra("pre.129-kotlin-1.4.20")
|
||||||
|
@ -5,6 +5,7 @@ import hep.dataforge.names.plus
|
|||||||
import hep.dataforge.names.startsWith
|
import hep.dataforge.names.startsWith
|
||||||
import hep.dataforge.values.asValue
|
import hep.dataforge.values.asValue
|
||||||
import hep.dataforge.vision.getProperty
|
import hep.dataforge.vision.getProperty
|
||||||
|
import hep.dataforge.vision.properties
|
||||||
import hep.dataforge.vision.set
|
import hep.dataforge.vision.set
|
||||||
import hep.dataforge.vision.setProperty
|
import hep.dataforge.vision.setProperty
|
||||||
import hep.dataforge.vision.solid.*
|
import hep.dataforge.vision.solid.*
|
||||||
@ -16,6 +17,8 @@ import info.laht.threekt.core.BufferGeometry
|
|||||||
import info.laht.threekt.core.Object3D
|
import info.laht.threekt.core.Object3D
|
||||||
import info.laht.threekt.geometries.BoxBufferGeometry
|
import info.laht.threekt.geometries.BoxBufferGeometry
|
||||||
import info.laht.threekt.objects.Mesh
|
import info.laht.threekt.objects.Mesh
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
internal fun SolidGroup.varBox(
|
internal fun SolidGroup.varBox(
|
||||||
@ -31,11 +34,11 @@ internal class VariableBox(xSize: Number, ySize: Number, zSize: Number) : ThreeV
|
|||||||
scaleX = xSize
|
scaleX = xSize
|
||||||
scaleY = ySize
|
scaleY = ySize
|
||||||
scaleZ = zSize
|
scaleZ = zSize
|
||||||
config[MeshThreeFactory.EDGES_ENABLED_KEY] = false
|
properties[MeshThreeFactory.EDGES_ENABLED_KEY] = false
|
||||||
config[MeshThreeFactory.WIREFRAME_ENABLED_KEY] = false
|
properties[MeshThreeFactory.WIREFRAME_ENABLED_KEY] = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun render(): Object3D {
|
override fun render(three: ThreePlugin): Object3D {
|
||||||
val xSize = getProperty(X_SIZE_KEY, false).number?.toDouble() ?: 1.0
|
val xSize = getProperty(X_SIZE_KEY, false).number?.toDouble() ?: 1.0
|
||||||
val ySize = getProperty(Y_SIZE_KEY, false).number?.toDouble() ?: 1.0
|
val ySize = getProperty(Y_SIZE_KEY, false).number?.toDouble() ?: 1.0
|
||||||
val zSize = getProperty(Z_SIZE_KEY, false).number?.toDouble() ?: 1.0
|
val zSize = getProperty(Z_SIZE_KEY, false).number?.toDouble() ?: 1.0
|
||||||
@ -60,7 +63,7 @@ internal class VariableBox(xSize: Number, ySize: Number, zSize: Number) : ThreeV
|
|||||||
mesh.scale.set(xSize, ySize, zSize)
|
mesh.scale.set(xSize, ySize, zSize)
|
||||||
|
|
||||||
//add listener to object properties
|
//add listener to object properties
|
||||||
onPropertyChange(mesh) { name ->
|
propertyInvalidated.onEach { name ->
|
||||||
when {
|
when {
|
||||||
name.startsWith(GEOMETRY_KEY) -> {
|
name.startsWith(GEOMETRY_KEY) -> {
|
||||||
val newXSize = getProperty(X_SIZE_KEY, false).number?.toDouble() ?: 1.0
|
val newXSize = getProperty(X_SIZE_KEY, false).number?.toDouble() ?: 1.0
|
||||||
@ -71,12 +74,12 @@ internal class VariableBox(xSize: Number, ySize: Number, zSize: Number) : ThreeV
|
|||||||
}
|
}
|
||||||
name.startsWith(MeshThreeFactory.WIREFRAME_KEY) -> mesh.applyWireFrame(this@VariableBox)
|
name.startsWith(MeshThreeFactory.WIREFRAME_KEY) -> mesh.applyWireFrame(this@VariableBox)
|
||||||
name.startsWith(MeshThreeFactory.EDGES_KEY) -> mesh.applyEdges(this@VariableBox)
|
name.startsWith(MeshThreeFactory.EDGES_KEY) -> mesh.applyEdges(this@VariableBox)
|
||||||
name.startsWith(MATERIAL_COLOR_KEY)->{
|
name.startsWith(MATERIAL_COLOR_KEY) -> {
|
||||||
mesh.material = getMaterial(this, true)
|
mesh.material = getMaterial(this, true)
|
||||||
}
|
}
|
||||||
else -> mesh.updateProperty(this@VariableBox, name)
|
else -> mesh.updateProperty(this@VariableBox, name)
|
||||||
}
|
}
|
||||||
}
|
}.launchIn(three.context)
|
||||||
return mesh
|
return mesh
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +103,7 @@ internal class VariableBox(xSize: Number, ySize: Number, zSize: Number) : ThreeV
|
|||||||
color(r.toUByte(), g.toUByte(), b.toUByte())
|
color(r.toUByte(), g.toUByte(), b.toUByte())
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object{
|
companion object {
|
||||||
private val X_SIZE_KEY = GEOMETRY_KEY + "xSize"
|
private val X_SIZE_KEY = GEOMETRY_KEY + "xSize"
|
||||||
private val Y_SIZE_KEY = GEOMETRY_KEY + "ySize"
|
private val Y_SIZE_KEY = GEOMETRY_KEY + "ySize"
|
||||||
private val Z_SIZE_KEY = GEOMETRY_KEY + "zSize"
|
private val Z_SIZE_KEY = GEOMETRY_KEY + "zSize"
|
||||||
|
@ -4,6 +4,7 @@ import hep.dataforge.names.Name
|
|||||||
import hep.dataforge.names.isEmpty
|
import hep.dataforge.names.isEmpty
|
||||||
import hep.dataforge.vision.Vision
|
import hep.dataforge.vision.Vision
|
||||||
import hep.dataforge.vision.VisionGroup
|
import hep.dataforge.vision.VisionGroup
|
||||||
|
import hep.dataforge.vision.describedProperties
|
||||||
import hep.dataforge.vision.react.objectTree
|
import hep.dataforge.vision.react.objectTree
|
||||||
import hep.dataforge.vision.solid.three.ThreeCanvas
|
import hep.dataforge.vision.solid.three.ThreeCanvas
|
||||||
import kotlinx.css.*
|
import kotlinx.css.*
|
||||||
@ -53,7 +54,7 @@ public val ThreeControls: FunctionalComponent<ThreeControlsProps> = functionalCo
|
|||||||
if (selectedObject != null) {
|
if (selectedObject != null) {
|
||||||
visionPropertyEditor(
|
visionPropertyEditor(
|
||||||
selectedObject,
|
selectedObject,
|
||||||
default = selectedObject.allProperties,
|
default = selectedObject.describedProperties,
|
||||||
key = selected
|
key = selected
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import hep.dataforge.meta.Meta
|
|||||||
import hep.dataforge.meta.descriptors.NodeDescriptor
|
import hep.dataforge.meta.descriptors.NodeDescriptor
|
||||||
import hep.dataforge.vision.Vision
|
import hep.dataforge.vision.Vision
|
||||||
import hep.dataforge.vision.getStyle
|
import hep.dataforge.vision.getStyle
|
||||||
|
import hep.dataforge.vision.properties
|
||||||
import hep.dataforge.vision.react.configEditor
|
import hep.dataforge.vision.react.configEditor
|
||||||
import hep.dataforge.vision.react.metaViewer
|
import hep.dataforge.vision.react.metaViewer
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
@ -17,7 +18,7 @@ public fun RBuilder.visionPropertyEditor(
|
|||||||
key: Any? = null
|
key: Any? = null
|
||||||
) {
|
) {
|
||||||
card("Properties") {
|
card("Properties") {
|
||||||
configEditor(item.config, descriptor, default, key)
|
configEditor(item.properties, descriptor, default, key)
|
||||||
}
|
}
|
||||||
val styles = item.styles
|
val styles = item.styles
|
||||||
if(styles.isNotEmpty()) {
|
if(styles.isNotEmpty()) {
|
||||||
|
@ -19,7 +19,7 @@ public external interface ConfigEditorItemProps : RProps {
|
|||||||
/**
|
/**
|
||||||
* Root config object - always non null
|
* Root config object - always non null
|
||||||
*/
|
*/
|
||||||
public var root: Config
|
public var root: MutableItemProvider
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Full path to the displayed node in [root]. Could be empty
|
* Full path to the displayed node in [root]. Could be empty
|
||||||
@ -44,7 +44,7 @@ private val ConfigEditorItem: FunctionalComponent<ConfigEditorItemProps> =
|
|||||||
|
|
||||||
private fun RBuilder.configEditorItem(props: ConfigEditorItemProps) {
|
private fun RBuilder.configEditorItem(props: ConfigEditorItemProps) {
|
||||||
var expanded: Boolean by useState { true }
|
var expanded: Boolean by useState { true }
|
||||||
var item: MetaItem<Config>? by useState { props.root[props.name] }
|
var item: MetaItem<*>? by useState { props.root.getItem(props.name) }
|
||||||
val descriptorItem: ItemDescriptor? = props.descriptor?.get(props.name)
|
val descriptorItem: ItemDescriptor? = props.descriptor?.get(props.name)
|
||||||
val defaultItem = props.default?.get(props.name)
|
val defaultItem = props.default?.get(props.name)
|
||||||
var actualItem: MetaItem<Meta>? by useState { item ?: defaultItem ?: descriptorItem?.defaultItem() }
|
var actualItem: MetaItem<Meta>? by useState { item ?: defaultItem ?: descriptorItem?.defaultItem() }
|
||||||
@ -52,7 +52,7 @@ private fun RBuilder.configEditorItem(props: ConfigEditorItemProps) {
|
|||||||
val token = props.name.lastOrNull()?.toString() ?: "Properties"
|
val token = props.name.lastOrNull()?.toString() ?: "Properties"
|
||||||
|
|
||||||
fun update() {
|
fun update() {
|
||||||
item = props.root[props.name]
|
item = props.root.getItem(props.name)
|
||||||
actualItem = item ?: defaultItem ?: descriptorItem?.defaultItem()
|
actualItem = item ?: defaultItem ?: descriptorItem?.defaultItem()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ private fun RBuilder.configEditorItem(props: ConfigEditorItemProps) {
|
|||||||
|
|
||||||
public external interface ConfigEditorProps : RProps {
|
public external interface ConfigEditorProps : RProps {
|
||||||
public var id: Name
|
public var id: Name
|
||||||
public var root: Config
|
public var root: MutableItemProvider
|
||||||
public var default: Meta?
|
public var default: Meta?
|
||||||
public var descriptor: NodeDescriptor?
|
public var descriptor: NodeDescriptor?
|
||||||
}
|
}
|
||||||
@ -229,7 +229,7 @@ public fun Element.configEditor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun RBuilder.configEditor(
|
public fun RBuilder.configEditor(
|
||||||
config: Config,
|
config: MutableItemProvider,
|
||||||
descriptor: NodeDescriptor? = null,
|
descriptor: NodeDescriptor? = null,
|
||||||
default: Meta? = null,
|
default: Meta? = null,
|
||||||
key: Any? = null,
|
key: Any? = null,
|
||||||
|
@ -8,7 +8,6 @@ import hep.dataforge.names.Name
|
|||||||
import hep.dataforge.names.asName
|
import hep.dataforge.names.asName
|
||||||
import hep.dataforge.values.ValueType
|
import hep.dataforge.values.ValueType
|
||||||
import hep.dataforge.vision.Vision.Companion.STYLE_KEY
|
import hep.dataforge.vision.Vision.Companion.STYLE_KEY
|
||||||
import kotlinx.coroutines.channels.BufferOverflow
|
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.SharedFlow
|
import kotlinx.coroutines.flow.SharedFlow
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
@ -32,32 +31,33 @@ public open class VisionBase : Vision {
|
|||||||
* Object own properties excluding styles and inheritance
|
* Object own properties excluding styles and inheritance
|
||||||
*/
|
*/
|
||||||
@SerialName("properties")
|
@SerialName("properties")
|
||||||
private var _properties: Config? = null
|
protected var innerProperties: Config? = null
|
||||||
|
private set
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All own properties as a read-only Meta
|
* All own properties as a read-only Meta
|
||||||
*/
|
*/
|
||||||
public val ownProperties: Meta get() = _properties?: Meta.EMPTY
|
public val ownProperties: Meta get() = innerProperties ?: Meta.EMPTY
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
private fun getOrCreateConfig(): Config {
|
private fun getOrCreateConfig(): Config {
|
||||||
if (_properties == null) {
|
if (innerProperties == null) {
|
||||||
val newProperties = Config()
|
val newProperties = Config()
|
||||||
_properties = newProperties
|
innerProperties = newProperties
|
||||||
newProperties.onChange(this) { name, oldItem, newItem ->
|
newProperties.onChange(this) { name, oldItem, newItem ->
|
||||||
if (oldItem != newItem) {
|
if (oldItem != newItem) {
|
||||||
notifyPropertyChanged(name)
|
notifyPropertyChanged(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _properties!!
|
return innerProperties!!
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A fast accessor method to get own property (no inheritance or styles
|
* A fast accessor method to get own property (no inheritance or styles
|
||||||
*/
|
*/
|
||||||
override fun getOwnProperty(name: Name): MetaItem<*>? {
|
override fun getOwnProperty(name: Name): MetaItem<*>? {
|
||||||
return _properties?.getItem(name)
|
return innerProperties?.getItem(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getProperty(
|
override fun getProperty(
|
||||||
@ -93,9 +93,8 @@ public open class VisionBase : Vision {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val _propertyInvalidationFlow: MutableSharedFlow<Name> = MutableSharedFlow(
|
@Transient
|
||||||
onBufferOverflow = BufferOverflow.DROP_OLDEST
|
private val _propertyInvalidationFlow: MutableSharedFlow<Name> = MutableSharedFlow()
|
||||||
)
|
|
||||||
|
|
||||||
override val propertyInvalidated: SharedFlow<Name> get() = _propertyInvalidationFlow
|
override val propertyInvalidated: SharedFlow<Name> get() = _propertyInvalidationFlow
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package hep.dataforge.vision
|
package hep.dataforge.vision
|
||||||
|
|
||||||
import hep.dataforge.names.*
|
import hep.dataforge.names.*
|
||||||
import kotlinx.coroutines.channels.BufferOverflow
|
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.SharedFlow
|
import kotlinx.coroutines.flow.SharedFlow
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
@ -36,9 +35,7 @@ public open class VisionGroupBase : VisionBase(), MutableVisionGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private val _structureChanges: MutableSharedFlow<MutableVisionGroup.StructureChange> = MutableSharedFlow(
|
private val _structureChanges: MutableSharedFlow<MutableVisionGroup.StructureChange> = MutableSharedFlow()
|
||||||
onBufferOverflow = BufferOverflow.DROP_OLDEST
|
|
||||||
)
|
|
||||||
|
|
||||||
override val structureChanges: SharedFlow<MutableVisionGroup.StructureChange> get() = _structureChanges
|
override val structureChanges: SharedFlow<MutableVisionGroup.StructureChange> get() = _structureChanges
|
||||||
|
|
||||||
|
@ -18,6 +18,10 @@ import org.w3c.dom.WebSocket
|
|||||||
import org.w3c.dom.asList
|
import org.w3c.dom.asList
|
||||||
import org.w3c.dom.get
|
import org.w3c.dom.get
|
||||||
import org.w3c.dom.url.URL
|
import org.w3c.dom.url.URL
|
||||||
|
import kotlin.collections.HashMap
|
||||||
|
import kotlin.collections.forEach
|
||||||
|
import kotlin.collections.maxByOrNull
|
||||||
|
import kotlin.collections.set
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
public class VisionClient : AbstractPlugin() {
|
public class VisionClient : AbstractPlugin() {
|
||||||
@ -124,9 +128,9 @@ public class VisionClient : AbstractPlugin() {
|
|||||||
)
|
)
|
||||||
logger.debug { "Got update $dif for output with name $name" }
|
logger.debug { "Got update $dif for output with name $name" }
|
||||||
visionMap[element]?.update(dif)
|
visionMap[element]?.update(dif)
|
||||||
?: logger.info { "Target vision for element $element with name $name not found" }
|
?: console.info("Target vision for element $element with name $name not found")
|
||||||
} else {
|
} else {
|
||||||
console.error("WebSocket message data is not a string")
|
console.error ("WebSocket message data is not a string")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onopen = {
|
onopen = {
|
||||||
|
@ -81,7 +81,7 @@ public interface Solid : Vision {
|
|||||||
if (first.position != second.position) return false
|
if (first.position != second.position) return false
|
||||||
if (first.rotation != second.rotation) return false
|
if (first.rotation != second.rotation) return false
|
||||||
if (first.scale != second.scale) return false
|
if (first.scale != second.scale) return false
|
||||||
if (first.properties != second.properties) return false
|
if (first.ownProperties != second.ownProperties) return false
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ public class SolidGroup : VisionGroupBase(), Solid, PrototypeHolder {
|
|||||||
/**
|
/**
|
||||||
* Create or edit prototype node as a group
|
* Create or edit prototype node as a group
|
||||||
*/
|
*/
|
||||||
|
@VisionBuilder
|
||||||
public fun prototypes(builder: VisionContainerBuilder<Solid>.() -> Unit): Unit {
|
public fun prototypes(builder: VisionContainerBuilder<Solid>.() -> Unit): Unit {
|
||||||
(prototypes ?: Prototypes().also {
|
(prototypes ?: Prototypes().also {
|
||||||
prototypes = it
|
prototypes = it
|
||||||
@ -107,10 +108,9 @@ internal class Prototypes(
|
|||||||
children: Map<NameToken, Vision> = emptyMap(),
|
children: Map<NameToken, Vision> = emptyMap(),
|
||||||
) : VisionGroupBase(), PrototypeHolder {
|
) : VisionGroupBase(), PrototypeHolder {
|
||||||
|
|
||||||
override var parent: VisionGroup? = null
|
init {
|
||||||
|
childrenInternal.putAll(children)
|
||||||
private val _children = HashMap(children)
|
}
|
||||||
override val children: Map<NameToken, Vision> get() = _children
|
|
||||||
|
|
||||||
override val prototypes: MutableVisionGroup get() = this
|
override val prototypes: MutableVisionGroup get() = this
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package hep.dataforge.vision.solid
|
|||||||
|
|
||||||
import hep.dataforge.meta.int
|
import hep.dataforge.meta.int
|
||||||
import hep.dataforge.names.asName
|
import hep.dataforge.names.asName
|
||||||
|
import hep.dataforge.vision.getProperty
|
||||||
import hep.dataforge.vision.setProperty
|
import hep.dataforge.vision.setProperty
|
||||||
import hep.dataforge.vision.styleSheet
|
import hep.dataforge.vision.styleSheet
|
||||||
import hep.dataforge.vision.useStyle
|
import hep.dataforge.vision.useStyle
|
||||||
@ -19,7 +20,7 @@ class PropertyTest {
|
|||||||
box = box(100, 100, 100)
|
box = box(100, 100, 100)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertEquals(22, box?.getProperty("test".asName()).int)
|
assertEquals(22, box?.getProperty("test").int)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -37,7 +38,7 @@ class PropertyTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertEquals(22, box?.getProperty("test".asName()).int)
|
assertEquals(22, box?.getProperty("test").int)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -85,7 +85,7 @@ internal fun Mesh.applyProperties(obj: Solid): Mesh = apply {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Mesh.applyEdges(obj: Solid) {
|
public fun Mesh.applyEdges(obj: Solid) {
|
||||||
val edges = children.find { it.name == "@edges" } as? LineSegments
|
val edges = children.find { it.name == "@edges" } as? LineSegments
|
||||||
//inherited edges definition, enabled by default
|
//inherited edges definition, enabled by default
|
||||||
if (obj.getProperty(MeshThreeFactory.EDGES_ENABLED_KEY).boolean != false) {
|
if (obj.getProperty(MeshThreeFactory.EDGES_ENABLED_KEY).boolean != false) {
|
||||||
@ -111,7 +111,7 @@ internal fun Mesh.applyEdges(obj: Solid) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Mesh.applyWireFrame(obj: Solid) {
|
public fun Mesh.applyWireFrame(obj: Solid) {
|
||||||
children.find { it.name == "@wireframe" }?.let {
|
children.find { it.name == "@wireframe" }?.let {
|
||||||
remove(it)
|
remove(it)
|
||||||
(it as LineSegments).dispose()
|
(it as LineSegments).dispose()
|
||||||
|
@ -22,7 +22,7 @@ import kotlin.reflect.KClass
|
|||||||
public object ThreeCanvasLabelFactory : ThreeFactory<SolidLabel> {
|
public object ThreeCanvasLabelFactory : ThreeFactory<SolidLabel> {
|
||||||
override val type: KClass<in SolidLabel> get() = SolidLabel::class
|
override val type: KClass<in SolidLabel> get() = SolidLabel::class
|
||||||
|
|
||||||
override fun invoke(obj: SolidLabel): Object3D {
|
override fun invoke(three: ThreePlugin, obj: SolidLabel): Object3D {
|
||||||
val canvas = document.createElement("canvas") as HTMLCanvasElement
|
val canvas = document.createElement("canvas") as HTMLCanvasElement
|
||||||
val context = canvas.getContext("2d") as CanvasRenderingContext2D
|
val context = canvas.getContext("2d") as CanvasRenderingContext2D
|
||||||
context.font = "Bold ${obj.fontSize}pt ${obj.fontFamily}"
|
context.font = "Bold ${obj.fontSize}pt ${obj.fontFamily}"
|
||||||
|
@ -25,7 +25,6 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
|
|
||||||
private val objectFactories = HashMap<KClass<out Solid>, ThreeFactory<*>>()
|
private val objectFactories = HashMap<KClass<out Solid>, ThreeFactory<*>>()
|
||||||
private val compositeFactory = ThreeCompositeFactory(this)
|
private val compositeFactory = ThreeCompositeFactory(this)
|
||||||
private val refFactory = ThreeReferenceFactory(this)
|
|
||||||
|
|
||||||
//TODO generate a separate supervisor update scope
|
//TODO generate a separate supervisor update scope
|
||||||
internal val updateScope: CoroutineScope get() = context
|
internal val updateScope: CoroutineScope get() = context
|
||||||
@ -49,8 +48,8 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
|
|
||||||
public fun buildObject3D(obj: Solid): Object3D {
|
public fun buildObject3D(obj: Solid): Object3D {
|
||||||
return when (obj) {
|
return when (obj) {
|
||||||
is ThreeVision -> obj.render()
|
is ThreeVision -> obj.render(this)
|
||||||
is SolidReferenceGroup -> refFactory(obj)
|
is SolidReferenceGroup -> ThreeReferenceFactory(this, obj)
|
||||||
is SolidGroup -> {
|
is SolidGroup -> {
|
||||||
val group = ThreeGroup()
|
val group = ThreeGroup()
|
||||||
obj.children.forEach { (token, child) ->
|
obj.children.forEach { (token, child) ->
|
||||||
@ -108,13 +107,13 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
}.launchIn(updateScope)
|
}.launchIn(updateScope)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Composite -> compositeFactory(obj)
|
is Composite -> compositeFactory(this, obj)
|
||||||
else -> {
|
else -> {
|
||||||
//find specialized factory for this type if it is present
|
//find specialized factory for this type if it is present
|
||||||
val factory: ThreeFactory<Solid>? = findObjectFactory(obj::class)
|
val factory: ThreeFactory<Solid>? = findObjectFactory(obj::class)
|
||||||
when {
|
when {
|
||||||
factory != null -> factory(obj)
|
factory != null -> factory(this, obj)
|
||||||
obj is GeometrySolid -> ThreeShapeFactory(obj)
|
obj is GeometrySolid -> ThreeShapeFactory(this, obj)
|
||||||
else -> error("Renderer for ${obj::class} not found")
|
else -> error("Renderer for ${obj::class} not found")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import kotlinx.coroutines.flow.launchIn
|
|||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
public class ThreeReferenceFactory(public val three: ThreePlugin) : ThreeFactory<SolidReferenceGroup> {
|
public object ThreeReferenceFactory : ThreeFactory<SolidReferenceGroup> {
|
||||||
private val cache = HashMap<Solid, Object3D>()
|
private val cache = HashMap<Solid, Object3D>()
|
||||||
|
|
||||||
override val type: KClass<SolidReferenceGroup> = SolidReferenceGroup::class
|
override val type: KClass<SolidReferenceGroup> = SolidReferenceGroup::class
|
||||||
@ -32,7 +32,7 @@ public class ThreeReferenceFactory(public val three: ThreePlugin) : ThreeFactory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun invoke(obj: SolidReferenceGroup): Object3D {
|
override fun invoke(three: ThreePlugin, obj: SolidReferenceGroup): Object3D {
|
||||||
val template = obj.prototype
|
val template = obj.prototype
|
||||||
val cachedObject = cache.getOrPut(template) {
|
val cachedObject = cache.getOrPut(template) {
|
||||||
three.buildObject3D(template)
|
three.buildObject3D(template)
|
||||||
|
@ -7,5 +7,5 @@ import info.laht.threekt.core.Object3D
|
|||||||
* A custom visual object that has its own Three.js renderer
|
* A custom visual object that has its own Three.js renderer
|
||||||
*/
|
*/
|
||||||
public abstract class ThreeVision : SolidBase() {
|
public abstract class ThreeVision : SolidBase() {
|
||||||
public abstract fun render(): Object3D
|
public abstract fun render(three: ThreePlugin): Object3D
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user