Encapsulate prototypes.
This commit is contained in:
parent
6939fba292
commit
ccb916cff7
@ -39,9 +39,10 @@ fun main() {
|
||||
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")
|
||||
val targetVision = sat[target] as Solid
|
||||
targetVision.color("red")
|
||||
delay(300)
|
||||
(sat[target] as? Solid)?.color("green")
|
||||
targetVision.color("green")
|
||||
delay(10)
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,10 @@ import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.values.ValueType
|
||||
import hep.dataforge.vision.Vision.Companion.STYLE_KEY
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
@ -68,7 +70,7 @@ public open class VisionBase : Vision {
|
||||
yieldAll(getStyleItems(name))
|
||||
}
|
||||
if (inherit ?: descriptor?.get(name)?.inherited == true) {
|
||||
yield(parent?.getProperty(name, inherit))
|
||||
yield(parent?.getProperty(name, inherit, includeStyles, includeDefaults))
|
||||
}
|
||||
yield(descriptor?.get(name)?.defaultItem())
|
||||
}.merge()
|
||||
@ -101,8 +103,9 @@ public open class VisionBase : Vision {
|
||||
if (propertyName == STYLE_KEY) {
|
||||
updateStyles(styles)
|
||||
}
|
||||
|
||||
_propertyInvalidationFlow.tryEmit(propertyName)
|
||||
GlobalScope.launch {
|
||||
_propertyInvalidationFlow.emit(propertyName)
|
||||
}
|
||||
}
|
||||
|
||||
public fun configure(block: MutableMeta<*>.() -> Unit) {
|
||||
|
@ -1,8 +1,10 @@
|
||||
package hep.dataforge.vision
|
||||
|
||||
import hep.dataforge.names.*
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
@ -43,7 +45,9 @@ public open class VisionGroupBase : VisionBase(), MutableVisionGroup {
|
||||
* Propagate children change event upwards
|
||||
*/
|
||||
private fun childrenChanged(name: NameToken, before: Vision?, after: Vision?) {
|
||||
_structureChanges.tryEmit(MutableVisionGroup.StructureChange(name, before, after))
|
||||
GlobalScope.launch {
|
||||
_structureChanges.emit(MutableVisionGroup.StructureChange(name, before, after))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,11 @@ import kotlinx.serialization.encoding.Encoder
|
||||
|
||||
public interface PrototypeHolder {
|
||||
public val parent: VisionGroup?
|
||||
public val prototypes: MutableVisionGroup?
|
||||
|
||||
@VisionBuilder
|
||||
public fun prototypes(builder: VisionContainerBuilder<Solid>.() -> Unit)
|
||||
|
||||
public fun getPrototype(name: Name): Solid?
|
||||
}
|
||||
|
||||
/**
|
||||
@ -28,18 +32,24 @@ public class SolidGroup : VisionGroupBase(), Solid, PrototypeHolder {
|
||||
|
||||
override val descriptor: NodeDescriptor get() = Solid.descriptor
|
||||
|
||||
|
||||
/**
|
||||
* A container for templates visible inside this group
|
||||
*/
|
||||
@Serializable(Prototypes.Companion::class)
|
||||
override var prototypes: MutableVisionGroup? = null
|
||||
private set
|
||||
@SerialName("prototypes")
|
||||
internal var prototypes: MutableVisionGroup? = null
|
||||
|
||||
/**
|
||||
* Ger a prototype redirecting the request to the parent if prototype is not found
|
||||
*/
|
||||
override fun getPrototype(name: Name): Solid? =
|
||||
prototypes?.get(name) as? Solid ?: (parent as? PrototypeHolder)?.getPrototype(name)
|
||||
|
||||
/**
|
||||
* Create or edit prototype node as a group
|
||||
*/
|
||||
@VisionBuilder
|
||||
public fun prototypes(builder: VisionContainerBuilder<Solid>.() -> Unit): Unit {
|
||||
override fun prototypes(builder: VisionContainerBuilder<Solid>.() -> Unit): Unit {
|
||||
(prototypes ?: Prototypes().also {
|
||||
prototypes = it
|
||||
it.parent = this
|
||||
@ -81,12 +91,6 @@ public fun SolidGroup(block: SolidGroup.() -> Unit): SolidGroup {
|
||||
return SolidGroup().apply(block)
|
||||
}
|
||||
|
||||
/**
|
||||
* Ger a prototype redirecting the request to the parent if prototype is not found
|
||||
*/
|
||||
public tailrec fun PrototypeHolder.getPrototype(name: Name): Solid? =
|
||||
prototypes?.get(name) as? Solid ?: (parent as? PrototypeHolder)?.getPrototype(name)
|
||||
|
||||
@VisionBuilder
|
||||
public fun VisionContainerBuilder<Vision>.group(
|
||||
name: Name = Name.EMPTY,
|
||||
@ -106,14 +110,12 @@ public fun VisionContainerBuilder<Vision>.group(name: String, action: SolidGroup
|
||||
@Serializable(Prototypes.Companion::class)
|
||||
internal class Prototypes(
|
||||
children: Map<NameToken, Vision> = emptyMap(),
|
||||
) : VisionGroupBase(), PrototypeHolder {
|
||||
) : VisionGroupBase() {
|
||||
|
||||
init {
|
||||
childrenInternal.putAll(children)
|
||||
}
|
||||
|
||||
override val prototypes: MutableVisionGroup get() = this
|
||||
|
||||
override fun attachChildren() {
|
||||
children.values.forEach {
|
||||
it.parent = parent
|
||||
@ -131,7 +133,7 @@ internal class Prototypes(
|
||||
): MetaItem<*>? = null
|
||||
|
||||
override fun setProperty(name: Name, item: MetaItem<*>?, notify: Boolean) {
|
||||
TODO("Not yet implemented")
|
||||
error("Can't ser property of prototypes container")
|
||||
}
|
||||
|
||||
override val descriptor: NodeDescriptor? = null
|
||||
|
@ -90,10 +90,20 @@ public class SolidMaterial : Scheme() {
|
||||
//must be lazy to avoid initialization bug
|
||||
NodeDescriptor {
|
||||
value(COLOR_KEY) {
|
||||
inherited = true
|
||||
usesStyles = true
|
||||
type(ValueType.STRING, ValueType.NUMBER)
|
||||
widgetType = "color"
|
||||
}
|
||||
// value(SPECULAR_COLOR_KEY) {
|
||||
// inherited = true
|
||||
// usesStyles = true
|
||||
// type(ValueType.STRING, ValueType.NUMBER)
|
||||
// widgetType = "color"
|
||||
// }
|
||||
value(OPACITY_KEY) {
|
||||
inherited = true
|
||||
usesStyles = true
|
||||
type(ValueType.NUMBER)
|
||||
default(1.0)
|
||||
attributes {
|
||||
@ -104,6 +114,8 @@ public class SolidMaterial : Scheme() {
|
||||
widgetType = "slider"
|
||||
}
|
||||
value(WIREFRAME_KEY) {
|
||||
inherited = true
|
||||
usesStyles = true
|
||||
type(ValueType.BOOLEAN)
|
||||
default(false)
|
||||
}
|
||||
@ -124,11 +136,7 @@ public var Solid.material: SolidMaterial?
|
||||
|
||||
@VisionBuilder
|
||||
public fun Solid.material(builder: SolidMaterial.() -> Unit) {
|
||||
val node = allProperties(
|
||||
inherit = true,
|
||||
includeStyles = true,
|
||||
includeDefaults = true
|
||||
).getItem(MATERIAL_KEY).node
|
||||
val node = allProperties(inherit = true).getItem(MATERIAL_KEY).node
|
||||
if (node != null) {
|
||||
SolidMaterial.update(node, builder)
|
||||
} else {
|
||||
|
@ -46,42 +46,41 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
||||
as ThreeFactory<Solid>?
|
||||
}
|
||||
|
||||
public fun buildObject3D(obj: Solid): Object3D {
|
||||
return when (obj) {
|
||||
is ThreeVision -> obj.render(this)
|
||||
is SolidReferenceGroup -> ThreeReferenceFactory(this, obj)
|
||||
is SolidGroup -> {
|
||||
val group = ThreeGroup()
|
||||
obj.children.forEach { (token, child) ->
|
||||
if (child is Solid && child.ignore != true) {
|
||||
try {
|
||||
val object3D = buildObject3D(child)
|
||||
group[token] = object3D
|
||||
} catch (ex: Throwable) {
|
||||
logger.error(ex) { "Failed to render $child" }
|
||||
ex.printStackTrace()
|
||||
}
|
||||
public fun buildObject3D(obj: Solid): Object3D = when (obj) {
|
||||
is ThreeVision -> obj.render(this)
|
||||
is SolidReferenceGroup -> ThreeReferenceFactory(this, obj)
|
||||
is SolidGroup -> {
|
||||
val group = ThreeGroup()
|
||||
obj.children.forEach { (token, child) ->
|
||||
if (child is Solid && child.ignore != true) {
|
||||
try {
|
||||
val object3D = buildObject3D(child)
|
||||
group[token] = object3D
|
||||
} catch (ex: Throwable) {
|
||||
logger.error(ex) { "Failed to render $child" }
|
||||
ex.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group.apply {
|
||||
updatePosition(obj)
|
||||
//obj.onChildrenChange()
|
||||
group.apply {
|
||||
updatePosition(obj)
|
||||
//obj.onChildrenChange()
|
||||
|
||||
obj.propertyNameFlow.onEach { name ->
|
||||
if (
|
||||
name.startsWith(Solid.POSITION_KEY) ||
|
||||
name.startsWith(Solid.ROTATION) ||
|
||||
name.startsWith(Solid.SCALE_KEY)
|
||||
) {
|
||||
//update position of mesh using this object
|
||||
updatePosition(obj)
|
||||
} else if (name == Vision.VISIBLE_KEY) {
|
||||
visible = obj.visible ?: true
|
||||
}
|
||||
}.launchIn(updateScope)
|
||||
obj.propertyNameFlow.onEach { name ->
|
||||
if (
|
||||
name.startsWith(Solid.POSITION_KEY) ||
|
||||
name.startsWith(Solid.ROTATION) ||
|
||||
name.startsWith(Solid.SCALE_KEY)
|
||||
) {
|
||||
//update position of mesh using this object
|
||||
updatePosition(obj)
|
||||
} else if (name == Vision.VISIBLE_KEY) {
|
||||
visible = obj.visible ?: true
|
||||
}
|
||||
}.launchIn(updateScope)
|
||||
|
||||
obj.structureChanges.onEach { (nameToken, _, child) ->
|
||||
obj.structureChanges.onEach { (nameToken, _, child) ->
|
||||
// if (name.isEmpty()) {
|
||||
// logger.error { "Children change with empty name on $group" }
|
||||
// return@onChildrenChange
|
||||
@ -90,32 +89,31 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
||||
// val parentName = name.cutLast()
|
||||
// val childName = name.last()!!
|
||||
|
||||
//removing old object
|
||||
findChild(nameToken.asName())?.let { oldChild ->
|
||||
oldChild.parent?.remove(oldChild)
|
||||
}
|
||||
//removing old object
|
||||
findChild(nameToken.asName())?.let { oldChild ->
|
||||
oldChild.parent?.remove(oldChild)
|
||||
}
|
||||
|
||||
//adding new object
|
||||
if (child != null && child is Solid) {
|
||||
try {
|
||||
val object3D = buildObject3D(child)
|
||||
set(nameToken, object3D)
|
||||
} catch (ex: Throwable) {
|
||||
logger.error(ex) { "Failed to render $child" }
|
||||
}
|
||||
//adding new object
|
||||
if (child != null && child is Solid) {
|
||||
try {
|
||||
val object3D = buildObject3D(child)
|
||||
set(nameToken, object3D)
|
||||
} catch (ex: Throwable) {
|
||||
logger.error(ex) { "Failed to render $child" }
|
||||
}
|
||||
}.launchIn(updateScope)
|
||||
}
|
||||
}
|
||||
}.launchIn(updateScope)
|
||||
}
|
||||
is Composite -> compositeFactory(this, obj)
|
||||
else -> {
|
||||
//find specialized factory for this type if it is present
|
||||
val factory: ThreeFactory<Solid>? = findObjectFactory(obj::class)
|
||||
when {
|
||||
factory != null -> factory(this, obj)
|
||||
obj is GeometrySolid -> ThreeShapeFactory(this, obj)
|
||||
else -> error("Renderer for ${obj::class} not found")
|
||||
}
|
||||
}
|
||||
is Composite -> compositeFactory(this, obj)
|
||||
else -> {
|
||||
//find specialized factory for this type if it is present
|
||||
val factory: ThreeFactory<Solid>? = findObjectFactory(obj::class)
|
||||
when {
|
||||
factory != null -> factory(this, obj)
|
||||
obj is GeometrySolid -> ThreeShapeFactory(this, obj)
|
||||
else -> error("Renderer for ${obj::class} not found")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user