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