forked from kscience/visionforge
More universal treatment of highlighting in three
This commit is contained in:
parent
67afa4e45b
commit
40b784f551
@ -67,7 +67,7 @@ internal fun Vision.styleChanged(key: String, oldStyle: Meta?, newStyle: Meta?)
|
||||
* List of names of styles applied to this object. Order matters. Not inherited.
|
||||
*/
|
||||
public var Vision.styles: List<String>
|
||||
get() = properties.getValue(Vision.STYLE_KEY, inherit = false, includeStyles = false)?.stringList ?: emptyList()
|
||||
get() = properties.own?.getValue(Vision.STYLE_KEY)?.stringList ?: emptyList()
|
||||
set(value) {
|
||||
properties.setValue(Vision.STYLE_KEY, value.map { it.asValue() }.asValue())
|
||||
}
|
||||
|
@ -143,8 +143,11 @@ private class VisionPropertiesItem(
|
||||
override fun hashCode(): Int = Meta.hashCode(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* A base implementation of [MutableVisionProperties]
|
||||
*/
|
||||
public abstract class AbstractVisionProperties(
|
||||
private val vision: Vision,
|
||||
public val vision: Vision,
|
||||
) : MutableVisionProperties {
|
||||
override val descriptor: MetaDescriptor? get() = vision.descriptor
|
||||
|
||||
|
@ -58,6 +58,8 @@ public interface Solid : Vision {
|
||||
|
||||
public val ROTATION_KEY: Name = "rotation".asName()
|
||||
|
||||
public val QUATERNION_KEY: Name = "quaternion".asName()
|
||||
|
||||
public val X_ROTATION_KEY: Name = ROTATION_KEY + X_KEY
|
||||
public val Y_ROTATION_KEY: Name = ROTATION_KEY + Y_KEY
|
||||
public val Z_ROTATION_KEY: Name = ROTATION_KEY + Z_KEY
|
||||
|
@ -20,9 +20,12 @@ import three.external.controls.OrbitControls
|
||||
import three.external.controls.TrackballControls
|
||||
import three.geometries.EdgesGeometry
|
||||
import three.helpers.AxesHelper
|
||||
import three.materials.Material
|
||||
import three.math.*
|
||||
import three.meshline.MeshLine
|
||||
import three.meshline.MeshLineMaterial
|
||||
import three.meshline.isMeshLineMaterial
|
||||
import three.objects.LineSegments
|
||||
import three.objects.Mesh
|
||||
import three.scenes.Scene
|
||||
import kotlin.math.cos
|
||||
@ -276,7 +279,7 @@ public class ThreeCanvas(
|
||||
private fun Object3D.toggleHighlight(
|
||||
highlight: Boolean,
|
||||
edgesName: String,
|
||||
material: MeshLineMaterial,
|
||||
material: Material,
|
||||
) {
|
||||
|
||||
if (userData[DO_NOT_HIGHLIGHT_TAG] == true) {
|
||||
@ -284,16 +287,21 @@ public class ThreeCanvas(
|
||||
}
|
||||
|
||||
if (isMesh(this)) {
|
||||
val highlightMesh = getObjectByName(edgesName) ?: Mesh(
|
||||
MeshLine(EdgesGeometry(geometry)),
|
||||
material
|
||||
).also {
|
||||
val highlightMesh = getObjectByName(edgesName) ?: if (isMeshLineMaterial(material)) {
|
||||
Mesh(
|
||||
MeshLine(EdgesGeometry(geometry)),
|
||||
material
|
||||
)
|
||||
} else {
|
||||
LineSegments(EdgesGeometry(geometry), material)
|
||||
}.also {
|
||||
it.name = edgesName
|
||||
add(it)
|
||||
}
|
||||
highlightMesh.visible = highlight
|
||||
} else {
|
||||
children.filter { !it.name.startsWith("@") && it.name != edgesName }.forEach {
|
||||
//ignore service objects if they are not statics
|
||||
children.filter { it.name.startsWith("@static") || !it.name.startsWith("@") }.forEach {
|
||||
it.toggleHighlight(highlight, edgesName, material)
|
||||
}
|
||||
}
|
||||
@ -319,15 +327,25 @@ public class ThreeCanvas(
|
||||
public companion object {
|
||||
public val SELECTED_MATERIAL: MeshLineMaterial = MeshLineMaterial().apply {
|
||||
color.set(Colors.ivory)
|
||||
linewidth = 2.0
|
||||
thickness = 2f
|
||||
cached = true
|
||||
}
|
||||
|
||||
public val HIGHLIGHT_MATERIAL: MeshLineMaterial = MeshLineMaterial().apply {
|
||||
color.set(Colors.blue)
|
||||
linewidth = 2.0
|
||||
thickness = 2f
|
||||
cached = true
|
||||
}
|
||||
//
|
||||
// public val SELECTED_MATERIAL: LineBasicMaterial = LineBasicMaterial().apply {
|
||||
// color.set(Colors.ivory)
|
||||
// cached = true
|
||||
// }
|
||||
//
|
||||
// public val HIGHLIGHT_MATERIAL: LineBasicMaterial = LineBasicMaterial().apply {
|
||||
// color.set(Colors.blue)
|
||||
// cached = true
|
||||
// }
|
||||
|
||||
|
||||
public const val DO_NOT_HIGHLIGHT_TAG: String = "doNotHighlight"
|
||||
|
@ -1,14 +1,14 @@
|
||||
package space.kscience.visionforge.solid.three
|
||||
|
||||
|
||||
import three.core.Object3D
|
||||
import three.geometries.TextBufferGeometry
|
||||
import three.objects.Mesh
|
||||
import kotlinx.js.jso
|
||||
import space.kscience.dataforge.context.logger
|
||||
import space.kscience.dataforge.context.warn
|
||||
import space.kscience.visionforge.onPropertyChange
|
||||
import space.kscience.visionforge.solid.SolidLabel
|
||||
import three.core.Object3D
|
||||
import three.geometries.TextBufferGeometry
|
||||
import three.objects.Mesh
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
@ -25,7 +25,7 @@ public object ThreeLabelFactory : ThreeFactory<SolidLabel> {
|
||||
curveSegments = 1
|
||||
})
|
||||
return Mesh(textGeo, ThreeMaterials.DEFAULT).apply {
|
||||
createMaterial(vision)
|
||||
setMaterial(vision)
|
||||
updatePosition(vision)
|
||||
if(observe) {
|
||||
vision.onPropertyChange(three.context) {
|
||||
|
@ -60,6 +60,7 @@ public object ThreeMaterials {
|
||||
color = meta[SolidMaterial.COLOR_KEY]?.threeColor() ?: DEFAULT_COLOR
|
||||
wireframe = meta[SolidMaterial.WIREFRAME_KEY].boolean ?: false
|
||||
}
|
||||
|
||||
else -> MeshStandardMaterial().apply {
|
||||
color = meta[SolidMaterial.COLOR_KEY]?.threeColor() ?: DEFAULT_COLOR
|
||||
emissive = meta[SolidMaterial.EMISSIVE_COLOR_KEY]?.threeColor() ?: DEFAULT_EMISSIVE_COLOR
|
||||
@ -71,10 +72,18 @@ public object ThreeMaterials {
|
||||
needsUpdate = true
|
||||
}
|
||||
|
||||
private val materialCache = HashMap<Int, Material>()
|
||||
// private val materialCache = HashMap<Int, Material>()
|
||||
//
|
||||
// internal fun cacheMaterial(meta: Meta): Material = materialCache.getOrPut(meta.hashCode()) {
|
||||
// buildMaterial(meta).apply {
|
||||
// cached = true
|
||||
// }
|
||||
// }
|
||||
|
||||
internal fun cacheMaterial(meta: Meta): Material = materialCache.getOrPut(meta.hashCode()) {
|
||||
buildMaterial(meta).apply {
|
||||
private val visionMaterialCache = HashMap<Vision, Material>()
|
||||
|
||||
internal fun cacheMaterial(vision: Vision): Material = visionMaterialCache.getOrPut(vision) {
|
||||
buildMaterial(vision.properties.getProperty(SolidMaterial.MATERIAL_KEY)).apply {
|
||||
cached = true
|
||||
}
|
||||
}
|
||||
@ -84,7 +93,7 @@ public object ThreeMaterials {
|
||||
* Compute color
|
||||
*/
|
||||
public fun Meta.threeColor(): Color? {
|
||||
if(isEmpty()) return null
|
||||
if (isEmpty()) return null
|
||||
val value = value
|
||||
return if (isLeaf) {
|
||||
when {
|
||||
@ -118,13 +127,19 @@ internal var Material.cached: Boolean
|
||||
userData["cached"] = value
|
||||
}
|
||||
|
||||
public fun Mesh.createMaterial(vision: Vision) {
|
||||
val ownMaterialMeta = vision.properties.own?.get(SolidMaterial.MATERIAL_KEY)
|
||||
if (ownMaterialMeta == null) {
|
||||
if (vision is SolidReference && vision.getStyleNodes(SolidMaterial.MATERIAL_KEY).isEmpty()) {
|
||||
createMaterial(vision.prototype)
|
||||
public fun Mesh.setMaterial(vision: Vision) {
|
||||
if (
|
||||
vision.properties.own?.get(SolidMaterial.MATERIAL_KEY) == null
|
||||
&& vision.getStyleNodes(SolidMaterial.MATERIAL_KEY).isEmpty()
|
||||
) {
|
||||
//if this is a reference, use material of the prototype
|
||||
if (vision is SolidReference) {
|
||||
ThreeMaterials.cacheMaterial(vision.prototype)
|
||||
} else {
|
||||
material = ThreeMaterials.cacheMaterial(vision.properties.getProperty(SolidMaterial.MATERIAL_KEY))
|
||||
material = vision.parent?.let { parent ->
|
||||
//TODO cache parent material
|
||||
ThreeMaterials.buildMaterial(parent.properties.getProperty(SolidMaterial.MATERIAL_KEY))
|
||||
} ?: ThreeMaterials.cacheMaterial(vision)
|
||||
}
|
||||
} else {
|
||||
material = ThreeMaterials.buildMaterial(vision.properties.getProperty(SolidMaterial.MATERIAL_KEY))
|
||||
@ -138,22 +153,27 @@ public fun Mesh.updateMaterialProperty(vision: Vision, propertyName: Name) {
|
||||
|| propertyName == SolidMaterial.MATERIAL_KEY + SolidMaterial.TYPE_KEY
|
||||
) {
|
||||
//generate a new material since cached material should not be changed
|
||||
createMaterial(vision)
|
||||
setMaterial(vision)
|
||||
} else {
|
||||
when (propertyName) {
|
||||
SolidMaterial.MATERIAL_COLOR_KEY -> {
|
||||
material.asDynamic().color = vision.properties.getProperty(SolidMaterial.MATERIAL_COLOR_KEY).threeColor()
|
||||
?: ThreeMaterials.DEFAULT_COLOR
|
||||
material.asDynamic().color =
|
||||
vision.properties.getProperty(SolidMaterial.MATERIAL_COLOR_KEY).threeColor()
|
||||
?: ThreeMaterials.DEFAULT_COLOR
|
||||
}
|
||||
|
||||
SolidMaterial.SPECULAR_COLOR_KEY -> {
|
||||
material.asDynamic().specular = vision.properties.getProperty(SolidMaterial.SPECULAR_COLOR_KEY).threeColor()
|
||||
?: ThreeMaterials.DEFAULT_COLOR
|
||||
material.asDynamic().specular =
|
||||
vision.properties.getProperty(SolidMaterial.SPECULAR_COLOR_KEY).threeColor()
|
||||
?: ThreeMaterials.DEFAULT_COLOR
|
||||
}
|
||||
|
||||
SolidMaterial.MATERIAL_EMISSIVE_COLOR_KEY -> {
|
||||
material.asDynamic().emissive = vision.properties.getProperty(SolidMaterial.MATERIAL_EMISSIVE_COLOR_KEY)
|
||||
.threeColor()
|
||||
?: ThreeMaterials.BLACK_COLOR
|
||||
}
|
||||
|
||||
SolidMaterial.MATERIAL_OPACITY_KEY -> {
|
||||
val opacity = vision.properties.getValue(
|
||||
SolidMaterial.MATERIAL_OPACITY_KEY,
|
||||
@ -162,12 +182,14 @@ public fun Mesh.updateMaterialProperty(vision: Vision, propertyName: Name) {
|
||||
material.opacity = opacity
|
||||
material.transparent = opacity < 1.0
|
||||
}
|
||||
|
||||
SolidMaterial.MATERIAL_WIREFRAME_KEY -> {
|
||||
material.asDynamic().wireframe = vision.properties.getValue(
|
||||
SolidMaterial.MATERIAL_WIREFRAME_KEY,
|
||||
inherit = true,
|
||||
)?.boolean ?: false
|
||||
}
|
||||
|
||||
else -> console.warn("Unrecognized material property: $propertyName")
|
||||
}
|
||||
material.needsUpdate = true
|
||||
|
@ -85,7 +85,7 @@ public fun Solid.edges(enabled: Boolean = true, block: SolidMaterial.() -> Unit
|
||||
}
|
||||
|
||||
internal fun Mesh.applyProperties(vision: Solid): Mesh = apply {
|
||||
createMaterial(vision)
|
||||
setMaterial(vision)
|
||||
applyEdges(vision)
|
||||
//applyWireFrame(obj)
|
||||
layers.set(vision.layer)
|
||||
|
@ -1,8 +1,11 @@
|
||||
package three.meshline
|
||||
|
||||
import three.core.BufferGeometry
|
||||
import three.materials.Material
|
||||
import three.math.Vector3
|
||||
|
||||
public fun MeshLine(geometry: BufferGeometry): MeshLine = MeshLine().apply { setGeometry(geometry) }
|
||||
|
||||
public fun MeshLine(points: Array<Vector3>): MeshLine = MeshLine().apply { setPoints(points) }
|
||||
|
||||
internal fun isMeshLineMaterial(material: Material): Boolean = material.asDynamic().isMeshLineMaterial == true
|
Loading…
Reference in New Issue
Block a user