Refactored SolidMaterial to use color wrapper

This commit is contained in:
Alexander Nozik 2020-12-14 13:47:46 +03:00
parent f4970955cb
commit 1ccd45d6c5
20 changed files with 105 additions and 63 deletions

View File

@ -58,7 +58,7 @@ class Model {
}
private fun highlight(pixel: String) {
map[pixel]?.color("blue")
map[pixel]?.color?.invoke("blue")
}
fun reset() {

View File

@ -4,6 +4,7 @@ package ru.mipt.npm.sat
import hep.dataforge.names.toName
import hep.dataforge.vision.solid.Solid
import hep.dataforge.vision.solid.color
import hep.dataforge.vision.solid.invoke
import hep.dataforge.vision.three.server.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
@ -40,7 +41,7 @@ fun main() {
val target = "layer[$randomLayer].segment[$randomI,$randomJ]".toName()
(sat[target] as? Solid)?.color("red")
delay(300)
(sat[target] as? Solid)?.color = "green"
(sat[target] as? Solid)?.color("green")
delay(10)
}
}

View File

@ -134,31 +134,39 @@ fun Page<Solid>.showcase() {
fun Page<Solid>.showcaseCSG() {
demo("CSG.simple", "CSG operations") {
composite(CompositeType.UNION) {
box(100, 100, 100) {
z = 50
}
sphere(50)
material {
color(Colors.lightgreen)
opacity = 0.3f
}
}
composite(CompositeType.INTERSECT) {
y = 300
box(100, 100, 100) {
z = 50
}
sphere(50)
color(Colors.red)
sphere(50){
detail = 32
}
material {
color(Colors.red)
wireframe = false
}
}
composite(CompositeType.UNION) {
box(100, 100, 100) {
z = 50
}
sphere(50){
detail = 32
}
color(Colors.lightgreen)
opacity = 0.3
}
composite(CompositeType.SUBTRACT) {
y = -300
box(100, 100, 100) {
z = 50
}
sphere(50)
color(Colors.blue)
sphere(50){
detail = 32
}
color(Colors.teal)
opacity = 0.7
}
}

View File

@ -1,12 +1,10 @@
import hep.dataforge.Application
import hep.dataforge.context.Global
import hep.dataforge.startApplication
import hep.dataforge.vision.bootstrap.visionPropertyEditor
import hep.dataforge.vision.react.ThreeCanvasComponent
import hep.dataforge.vision.react.objectTree
import hep.dataforge.vision.solid.*
import hep.dataforge.vision.solid.specifications.Canvas3DOptions
import hep.dataforge.vision.solid.three.ThreePlugin
import kotlinx.browser.document
import org.w3c.dom.HTMLElement
import react.RBuilder
@ -14,7 +12,7 @@ import react.child
import react.dom.div
import react.dom.render
public fun RBuilder.threeCanvas(object3D: Solid, options: Canvas3DOptions.() -> Unit = {}) {
fun RBuilder.threeCanvas(object3D: Solid, options: Canvas3DOptions.() -> Unit = {}) {
child(ThreeCanvasComponent) {
attrs {
this.obj = object3D
@ -25,8 +23,6 @@ public fun RBuilder.threeCanvas(object3D: Solid, options: Canvas3DOptions.() ->
private class PlayGroundApp : Application {
private val three = Global.plugins.fetch(ThreePlugin)
override fun start(state: Map<String, Any>) {
val element =

View File

@ -8,6 +8,10 @@ import hep.dataforge.names.Name
import hep.dataforge.values.ValueType
import hep.dataforge.values.asValue
@DslMarker
public annotation class VisionBuilder
public fun Sequence<MetaItem<*>?>.merge(): MetaItem<*>? {
return when (val first = firstOrNull { it != null }) {
null -> null

View File

@ -1,5 +1,6 @@
package hep.dataforge.vision.solid
import hep.dataforge.vision.VisionBuilder
import hep.dataforge.vision.VisionContainerBuilder
import hep.dataforge.vision.set
import hep.dataforge.vision.solid.Solid.Companion.solidEquals
@ -61,6 +62,7 @@ public class Box(
}
}
@VisionBuilder
public inline fun VisionContainerBuilder<Solid>.box(
xSize: Number,
ySize: Number,

View File

@ -3,10 +3,7 @@ package hep.dataforge.vision.solid
import hep.dataforge.meta.update
import hep.dataforge.names.NameToken
import hep.dataforge.vision.Vision
import hep.dataforge.vision.VisionContainerBuilder
import hep.dataforge.vision.VisionGroup
import hep.dataforge.vision.set
import hep.dataforge.vision.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@ -33,6 +30,7 @@ public class Composite(
get() = mapOf(NameToken("first") to first, NameToken("second") to second)
}
@VisionBuilder
public inline fun VisionContainerBuilder<Solid>.composite(
type: CompositeType,
name: String = "",
@ -58,11 +56,14 @@ public inline fun VisionContainerBuilder<Solid>.composite(
}
}
@VisionBuilder
public inline fun VisionContainerBuilder<Solid>.union(name: String = "", builder: SolidGroup.() -> Unit): Composite =
composite(CompositeType.UNION, name, builder = builder)
@VisionBuilder
public inline fun VisionContainerBuilder<Solid>.subtract(name: String = "", builder: SolidGroup.() -> Unit): Composite =
composite(CompositeType.SUBTRACT, name, builder = builder)
@VisionBuilder
public inline fun VisionContainerBuilder<Solid>.intersect(name: String = "", builder: SolidGroup.() -> Unit): Composite =
composite(CompositeType.INTERSECT, name, builder = builder)

View File

@ -1,5 +1,6 @@
package hep.dataforge.vision.solid
import hep.dataforge.vision.VisionBuilder
import hep.dataforge.vision.VisionContainerBuilder
import hep.dataforge.vision.set
import kotlinx.serialization.SerialName
@ -102,5 +103,6 @@ public class Extruded(
}
}
@VisionBuilder
public fun VisionContainerBuilder<Solid>.extrude(name: String = "", action: Extruded.() -> Unit = {}): Extruded =
Extruded().apply(action).also { set(name, it) }

View File

@ -4,6 +4,7 @@ import hep.dataforge.meta.number
import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.names.plus
import hep.dataforge.vision.VisionBuilder
import hep.dataforge.vision.VisionContainerBuilder
import hep.dataforge.vision.props
import hep.dataforge.vision.set
@ -23,6 +24,7 @@ public class PolyLine(public var points: List<Point3D>) : SolidBase(), Solid {
}
@VisionBuilder
public fun VisionContainerBuilder<Solid>.polyline(
vararg points: Point3D,
name: String = "",

View File

@ -9,6 +9,7 @@ import hep.dataforge.values.ValueType
import hep.dataforge.values.asValue
import hep.dataforge.vision.Vision
import hep.dataforge.vision.Vision.Companion.VISIBLE_KEY
import hep.dataforge.vision.VisionBuilder
import hep.dataforge.vision.enum
import hep.dataforge.vision.layout.Output
import hep.dataforge.vision.setProperty
@ -104,6 +105,7 @@ public var Solid.layer: Int
config[LAYER_KEY] = value.asValue()
}
@VisionBuilder
public fun Output<Solid>.solidGroup(builder: SolidGroup.() -> Unit): Unit = render(SolidGroup().apply(builder))
// Common properties

View File

@ -86,6 +86,7 @@ public fun SolidGroup(block: SolidGroup.() -> Unit): SolidGroup {
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, action: SolidGroup.() -> Unit = {}): SolidGroup =
SolidGroup().apply(action).also { set(name, it) }

View File

@ -1,5 +1,6 @@
package hep.dataforge.vision.solid
import hep.dataforge.vision.VisionBuilder
import hep.dataforge.vision.VisionContainerBuilder
import hep.dataforge.vision.set
import kotlinx.serialization.SerialName
@ -13,6 +14,7 @@ public class SolidLabel(
public var fontFamily: String,
) : SolidBase(), Solid
@VisionBuilder
public fun VisionContainerBuilder<Solid>.label(
text: String,
fontSize: Number = 20,

View File

@ -6,26 +6,66 @@ import hep.dataforge.meta.descriptors.attributes
import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.names.plus
import hep.dataforge.values.Value
import hep.dataforge.values.ValueType
import hep.dataforge.values.asValue
import hep.dataforge.values.string
import hep.dataforge.vision.Colors
import hep.dataforge.vision.VisionBuilder
import hep.dataforge.vision.setProperty
import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY
import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_KEY
import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_OPACITY_KEY
import hep.dataforge.vision.widgetType
@VisionBuilder
public class ColorAccessor(private val parent: MutableItemProvider, private val colorKey: Name) {
public var value: Value?
get() = parent.getItem(colorKey).value
set(value) {
parent[colorKey] = value
}
}
public var ColorAccessor?.string: String?
get() = this?.value?.string
set(value) {
this?.value = value?.asValue()
}
/**
* Set [webcolor](https://en.wikipedia.org/wiki/Web_colors) as string
*/
public operator fun ColorAccessor?.invoke(webColor: String) {
this?.value = webColor.asValue()
}
/**
* Set color as RGB integer
*/
public operator fun ColorAccessor?.invoke(rgb: Int) {
this?.value = rgb.asValue()
}
/**
* Set color as RGB
*/
public operator fun ColorAccessor?.invoke(r: UByte, g: UByte, b: UByte) {
this?.value = Colors.rgbToString(r, g, b).asValue()
}
@VisionBuilder
public class SolidMaterial : Scheme() {
/**
* Primary web-color for the material
*/
public var color: String? by string(key = COLOR_KEY)
public var color: ColorAccessor = ColorAccessor(config, COLOR_KEY)
/**
* Specular color for phong material
*/
public var specularColor: String? by string(key = SPECULAR_COLOR_KEY)
public var specularColor: ColorAccessor = ColorAccessor(config, SPECULAR_COLOR_KEY)
/**
* Opacity
@ -75,37 +115,13 @@ public class SolidMaterial : Scheme() {
}
}
/**
* Set color as web-color
*/
public fun Solid.color(webColor: String) {
setProperty(MATERIAL_COLOR_KEY, webColor.asValue())
}
public val Solid.color: ColorAccessor get() = ColorAccessor(config, MATERIAL_COLOR_KEY)
/**
* Set color as integer
*/
public fun Solid.color(rgb: Int) {
setProperty(MATERIAL_COLOR_KEY, rgb.asValue())
}
public fun Solid.color(r: UByte, g: UByte, b: UByte): Unit = setProperty(
MATERIAL_COLOR_KEY,
Colors.rgbToString(r, g, b).asValue()
)
/**
* Web colors representation of the color in `#rrggbb` format or HTML name
*/
public var Solid.color: String?
get() = getProperty(MATERIAL_COLOR_KEY)?.let { Colors.fromMeta(it) }
set(value) {
setProperty(MATERIAL_COLOR_KEY, value?.asValue())
}
public val Solid.material: SolidMaterial?
public var Solid.material: SolidMaterial?
get() = getProperty(MATERIAL_KEY).node?.let { SolidMaterial.read(it) }
set(value) = setProperty(MATERIAL_KEY, value?.config)
@VisionBuilder
public fun Solid.material(builder: SolidMaterial.() -> Unit) {
val node = config[MATERIAL_KEY].node
if (node != null) {
@ -115,8 +131,8 @@ public fun Solid.material(builder: SolidMaterial.() -> Unit) {
}
}
public var Solid.opacity: Double?
get() = getProperty(MATERIAL_OPACITY_KEY).double
public var Solid.opacity: Number?
get() = getProperty(MATERIAL_OPACITY_KEY).number
set(value) {
setProperty(MATERIAL_OPACITY_KEY, value?.asValue())
}

View File

@ -1,5 +1,6 @@
package hep.dataforge.vision.solid
import hep.dataforge.vision.VisionBuilder
import hep.dataforge.vision.VisionContainerBuilder
import hep.dataforge.vision.set
import kotlinx.serialization.SerialName
@ -50,6 +51,7 @@ public class Sphere(
}
}
@VisionBuilder
public inline fun VisionContainerBuilder<Solid>.sphere(
radius: Number,
phi: Number = 2 * PI,

View File

@ -1,5 +1,6 @@
package hep.dataforge.vision.solid
import hep.dataforge.vision.VisionBuilder
import hep.dataforge.vision.VisionContainerBuilder
import hep.dataforge.vision.set
import kotlinx.serialization.SerialName
@ -118,6 +119,7 @@ public class Tube(
}
@VisionBuilder
public inline fun VisionContainerBuilder<Solid>.tube(
r: Number,
height: Number,

View File

@ -55,7 +55,7 @@ class PropertyTest {
}
}
}
assertEquals("#555555", box?.color)
assertEquals("#555555", box?.color.string)
}
@Test
@ -76,6 +76,6 @@ class PropertyTest {
box = ref("box".asName())
}
}
assertEquals("#555555", box?.color)
assertEquals("#555555", box?.color.string)
}
}

View File

@ -28,8 +28,8 @@ class VisionUpdateTest {
}
targetVision.update(dif)
assertTrue { targetVision["top"] is SolidGroup }
assertEquals("red", (targetVision["origin"] as Solid).color) // Should work
assertEquals("#00007b", (targetVision["top"] as SolidGroup).color) // new item always takes precedence
assertEquals("red", (targetVision["origin"] as Solid).color.string) // Should work
assertEquals("#00007b", (targetVision["top"] as SolidGroup).color.string) // new item always takes precedence
}
@Test

View File

@ -9,5 +9,5 @@ kscience {
dependencies {
api(project(":visionforge-solid"))
implementation(npm("three", "0.122.0"))
implementation(npm("three-csg-ts", "1.0.6"))
implementation(npm("three-csg-ts", "2.0.0"))
}

View File

@ -3,6 +3,7 @@ package hep.dataforge.vision.solid.three
import hep.dataforge.meta.node
import hep.dataforge.vision.solid.PolyLine
import hep.dataforge.vision.solid.color
import hep.dataforge.vision.solid.string
import hep.dataforge.vision.solid.three.ThreeMaterials.DEFAULT_LINE_COLOR
import info.laht.threekt.core.Geometry
import info.laht.threekt.core.Object3D
@ -21,7 +22,7 @@ public object ThreeLineFactory : ThreeFactory<PolyLine> {
val material = ThreeMaterials.getLineMaterial(obj.getProperty(MeshThreeFactory.EDGES_MATERIAL_KEY).node, true)
material.linewidth = obj.thickness.toDouble()
material.color = obj.color?.let { Color(it) } ?: DEFAULT_LINE_COLOR
material.color = obj.color.string?.let { Color(it) } ?: DEFAULT_LINE_COLOR
return LineSegments(geometry, material).apply {
updatePosition(obj)