diff --git a/build.gradle b/build.gradle index 9a1c135a..6aa4ff60 100644 --- a/build.gradle +++ b/build.gradle @@ -1,24 +1,26 @@ -def openrndrUseSnapshot = false - buildscript { repositories { jcenter() } dependencies { classpath "org.jetbrains.dokka:dokka-gradle-plugin:0.9.17" - classpath "com.netflix.nebula:nebula-kotlin-plugin:1.3.72" - classpath "com.netflix.nebula:nebula-publishing-plugin:17.0.5" - classpath "com.netflix.nebula:nebula-release-plugin:14.1.0" + classpath "com.netflix.nebula:nebula-publishing-plugin:17.3.0" + classpath "com.netflix.nebula:nebula-release-plugin:15.1.0" classpath "com.github.ben-manes:gradle-versions-plugin:0.28.0" } } +plugins { + id 'org.jetbrains.kotlin.jvm' version '1.4.0' +} + +def openrndrUseSnapshot = false apply plugin: 'org.jetbrains.dokka' project.ext { - openrndrVersion = openrndrUseSnapshot? "0.4.0-SNAPSHOT" : "0.3.44-rc.8" - kotlinVersion = "1.3.72" - spekVersion = "2.0.11" + openrndrVersion = openrndrUseSnapshot? "0.4.0-SNAPSHOT" : "0.3.44-rc.10" + kotlinVersion = "1.4.0" + spekVersion = "2.0.12" libfreenectVersion = "0.5.7-1.5.3" gsonVersion = "2.8.6" antlrVersion = "4.8-1" @@ -47,7 +49,7 @@ dokka { allprojects { apply plugin: 'idea' apply plugin: 'java' - apply plugin: 'nebula.kotlin' + apply plugin: 'kotlin' apply plugin: 'nebula.contacts' apply plugin: 'nebula.info' apply plugin: 'nebula.release' @@ -75,11 +77,12 @@ allprojects { } dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion" implementation 'io.github.microutils:kotlin-logging:1.7.9' implementation "org.openrndr:openrndr-core:$openrndrVersion" implementation "org.openrndr:openrndr-filter:$openrndrVersion" implementation "org.openrndr:openrndr-shape:$openrndrVersion" - implementation group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: '1.3.6' + implementation group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: '1.3.9' testImplementation "org.spekframework.spek2:spek-dsl-jvm:$spekVersion" testImplementation "org.amshove.kluent:kluent:1.61" testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fb15f8de..a8cf03eb 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-all.zip diff --git a/openrndr-demos/build.gradle b/openrndr-demos/build.gradle index 827bff2d..c6c17587 100644 --- a/openrndr-demos/build.gradle +++ b/openrndr-demos/build.gradle @@ -13,6 +13,7 @@ dependencies { demoImplementation(project(":orx-camera")) demoImplementation(project(":orx-parameters")) demoImplementation(project(":orx-noise")) + demoImplementation(project(":orx-gui")) demoImplementation(project(":orx-shader-phrases")) demoImplementation("org.slf4j:slf4j-simple:1.7.30") diff --git a/orx-boofcv/src/main/kotlin/Binding.kt b/orx-boofcv/src/main/kotlin/Binding.kt index c2f5159b..2df3defb 100644 --- a/orx-boofcv/src/main/kotlin/Binding.kt +++ b/orx-boofcv/src/main/kotlin/Binding.kt @@ -70,9 +70,9 @@ fun ColorBuffer.toPlanarU8() : Planar { for (y in 0 until height) { for (x in 0 until width) { val c = shadow.read(x, y) - bands[0].data[offset] = (c.r * 255).toByte() - bands[1].data[offset] = (c.g * 255).toByte() - bands[2].data[offset] = (c.b * 255).toByte() + bands[0].data[offset] = (c.r * 255).toInt().toByte() + bands[1].data[offset] = (c.g * 255).toInt().toByte() + bands[2].data[offset] = (c.b * 255).toInt().toByte() offset++ } } diff --git a/orx-boofcv/src/main/kotlin/MatrixConversion.kt b/orx-boofcv/src/main/kotlin/MatrixConversion.kt new file mode 100644 index 00000000..dc569b79 --- /dev/null +++ b/orx-boofcv/src/main/kotlin/MatrixConversion.kt @@ -0,0 +1,19 @@ +package org.openrndr.boofcv.binding + +import georegression.struct.affine.Affine2D_F32 +import georegression.struct.affine.Affine2D_F64 +import org.openrndr.math.Matrix44 + +fun Affine2D_F32.toMatrix44() = Matrix44( + c0r0 = a11.toDouble(), c1r0 = a12.toDouble(), c3r0 = tx.toDouble(), + c0r1 = a21.toDouble(), c1r1 = a22.toDouble(), c3r1 = ty.toDouble(), + c2r2 = 1.0, + c3r3 = 1.0 +) + +fun Affine2D_F64.toMatrix44() = Matrix44( + c0r0 = a11, c1r0 = a12, c3r0 = tx, + c0r1 = a21, c1r1 = a22, c3r1 = ty, + c2r2 = 1.0, + c3r3 = 1.0 +) \ No newline at end of file diff --git a/orx-compositor/src/main/kotlin/Compositor.kt b/orx-compositor/src/main/kotlin/Compositor.kt index 8c25e6c6..95067e16 100644 --- a/orx-compositor/src/main/kotlin/Compositor.kt +++ b/orx-compositor/src/main/kotlin/Compositor.kt @@ -172,7 +172,7 @@ open class Layer internal constructor() { localBlendFilter.first.apply(arrayOf(activeRenderTarget.colorBuffer(0), layerPost), activeRenderTarget.colorBuffer(0)) } - accumulation?.resolveTo(target.colorBuffer(0)) + accumulation?.copyTo(target.colorBuffer(0)) } } diff --git a/orx-dnk3/build.gradle b/orx-dnk3/build.gradle index 0b69e02e..88db1f1f 100644 --- a/orx-dnk3/build.gradle +++ b/orx-dnk3/build.gradle @@ -17,9 +17,12 @@ dependencies { demoImplementation(project(":orx-camera")) demoImplementation(project(":orx-mesh-generators")) + demoImplementation(project(":orx-noise")) + demoImplementation("org.openrndr:openrndr-core:$openrndrVersion") demoImplementation("org.openrndr:openrndr-extensions:$openrndrVersion") demoImplementation("org.openrndr:openrndr-ffmpeg:$openrndrVersion") + demoRuntimeOnly("org.openrndr:openrndr-gl3:$openrndrVersion") demoRuntimeOnly("org.openrndr:openrndr-gl3-natives-$openrndrOS:$openrndrVersion") demoImplementation(sourceSets.getByName("main").output) diff --git a/orx-dnk3/src/demo/kotlin/DemoDSL02.kt b/orx-dnk3/src/demo/kotlin/DemoDSL02.kt new file mode 100644 index 00000000..82fc9e55 --- /dev/null +++ b/orx-dnk3/src/demo/kotlin/DemoDSL02.kt @@ -0,0 +1,87 @@ +import org.openrndr.application +import org.openrndr.color.ColorRGBa +import org.openrndr.extensions.SingleScreenshot +import org.openrndr.extra.dnk3.dsl.* +import org.openrndr.extra.dnk3.renderers.dryRenderer +import org.openrndr.extra.dnk3.tools.addSkybox +import org.openrndr.extra.noise.simplex +import org.openrndr.extras.camera.Orbital +import org.openrndr.extras.meshgenerators.groundPlaneMesh +import org.openrndr.math.Vector3 +import org.openrndr.math.transforms.transform +import org.openrndr.shape.path3D + +fun main() = application { + configure { + width = 1280 + height = 720 + } + + program { + if (System.getProperty("takeScreenshot") == "true") { + extend(SingleScreenshot()) { + this.outputFile = System.getProperty("screenshotPath") + } + } + extend(Orbital()) { + eye = Vector3(4.0, 4.0, 4.0) + } + + val renderer = dryRenderer() + val scene = scene { + + addSkybox("file:demo-data/cubemaps/garage_iem.dds") + + root.hemisphereLight { + upColor = ColorRGBa.WHITE.shade(0.1) + downColor = ColorRGBa.BLACK + } + + root.node { + transform = transform { + translate(0.0, 2.0, 0.0) + } + + pointLight { + constantAttenuation = 0.0 + quadraticAttenuation = 1.0 + } + } + + root.node { + simpleMesh { + vertexBuffer = groundPlaneMesh(100.0, 100.0) + material = pbrMaterial { + color = ColorRGBa.GREEN + } + } + } + + root.node { + pathMesh { + weight = 10.0 + material = pbrMaterial { + color = ColorRGBa.PINK + } + update { + paths = mutableListOf( + path3D { + val t = seconds * 0.1 + moveTo(Vector3.ZERO) + val control = Vector3.simplex(3032, t).let { it.copy(y = it.y * 0.5 + 0.5) } * 4.0 + val target = Vector3.simplex(5077, t).let { it.copy(y = it.y * 0.5 + 0.5) } * 4.0 + val end = Vector3.simplex(9041, t).let { it.copy(y = it.y * 0.5 + 0.5) } * 4.0 + curveTo(control, target) + continueTo(end) + } + ) + } + } + } + } + extend { + drawer.clear(ColorRGBa.BLACK) + renderer.draw(drawer, scene) + } + } +} \ No newline at end of file diff --git a/orx-dnk3/src/main/kotlin/Entity.kt b/orx-dnk3/src/main/kotlin/Entity.kt index cedf8e55..e9ff407d 100644 --- a/orx-dnk3/src/main/kotlin/Entity.kt +++ b/orx-dnk3/src/main/kotlin/Entity.kt @@ -1,9 +1,12 @@ package org.openrndr.extra.dnk3 import org.openrndr.color.ColorRGBa -import org.openrndr.draw.* +import org.openrndr.draw.DrawPrimitive +import org.openrndr.draw.IndexBuffer +import org.openrndr.draw.VertexBuffer import org.openrndr.math.Matrix44 import org.openrndr.math.transforms.perspective +import org.openrndr.shape.Path3D class Geometry(val vertexBuffers: List, @@ -15,6 +18,7 @@ class Geometry(val vertexBuffers: List, override fun toString(): String { return "Geometry(vertexBuffers: $vertexBuffers, indexBuffers: $indexBuffer, primitive: $primitive, offset: $offset, vertexCount: $vertexCount)" } + override fun hashCode(): Int { var result = 0 result = 31 * result + primitive.ordinal.hashCode() @@ -41,11 +45,22 @@ class MeshPrimitive(var geometry: Geometry, var material: Material) { class MeshPrimitiveInstance(val primitive: MeshPrimitive, val instances: Int, val attributes: List) +class PathMesh(var paths: MutableList, var material: Material, var weight: Double) : Entity() { + override fun toString(): String { + return "PathMesh(paths=$paths)" + } + + override fun hashCode(): Int { + return paths.hashCode() + } +} + abstract class MeshBase(var primitives: List) : Entity() class Mesh(primitives: List) : MeshBase(primitives) { override fun toString(): String { return "Mesh(primitives: $primitives)" } + override fun hashCode(): Int { return primitives.hashCode() } @@ -62,7 +77,7 @@ class InstancedMesh(primitives: List, var attributes: List) : MeshBase(primitives) -data class Fog(var color: ColorRGBa = ColorRGBa.WHITE, var end : Double = 100.0) : Entity() +data class Fog(var color: ColorRGBa = ColorRGBa.WHITE, var end: Double = 100.0) : Entity() abstract class Light : Entity() { var color: ColorRGBa = ColorRGBa.WHITE @@ -75,14 +90,14 @@ abstract class Camera : Entity() { abstract class CubemapProbe : Entity() { open val projectionMatrix: Matrix44 - get() { - return perspective(90.0, 1.0, 0.1, 150.0) - } + get() { + return perspective(90.0, 1.0, 0.1, 150.0) + } var dirty = true } -class IrradianceProbe: CubemapProbe() { - override fun hashCode(): Int { +class IrradianceProbe : CubemapProbe() { + override fun hashCode(): Int { return true.hashCode() } } \ No newline at end of file diff --git a/orx-dnk3/src/main/kotlin/PBRMaterial.kt b/orx-dnk3/src/main/kotlin/PBRMaterial.kt index b94cb08f..8809f4e0 100644 --- a/orx-dnk3/src/main/kotlin/PBRMaterial.kt +++ b/orx-dnk3/src/main/kotlin/PBRMaterial.kt @@ -20,7 +20,7 @@ private val noise128 by lazy { for (y in 0 until cb.height) { for (x in 0 until cb.width) { for (i in 0 until 4) - buffer.put((Math.random() * 255).toByte()) + buffer.put((Math.random() * 255).toInt().toByte()) } } buffer.rewind() diff --git a/orx-dnk3/src/main/kotlin/SceneRenderer.kt b/orx-dnk3/src/main/kotlin/SceneRenderer.kt index c46318b5..b03b4e0d 100644 --- a/orx-dnk3/src/main/kotlin/SceneRenderer.kt +++ b/orx-dnk3/src/main/kotlin/SceneRenderer.kt @@ -13,11 +13,11 @@ class RenderContext( val meshes: List>, val skinnedMeshes: List>, val instancedMeshes: List>, + val pathMeshes: List>, val fogs: List> ) class SceneRenderer { - class Configuration { var multisampleLines = false } @@ -64,7 +64,8 @@ class SceneRenderer { meshes = scene.root.findContent { this as? Mesh }, skinnedMeshes = scene.root.findContent { this as? SkinnedMesh }, fogs = scene.root.findContent { this as? Fog }, - instancedMeshes = scene.root.findContent { this as? InstancedMesh } + instancedMeshes = scene.root.findContent { this as? InstancedMesh }, + pathMeshes = scene.root.findContent { this as? PathMesh} ) // shadow passes @@ -140,7 +141,7 @@ class SceneRenderer { pass.combiners.forEach { if (it is ColorBufferFacetCombiner) { val index = target.colorAttachmentIndexByName(it.targetOutput) - ?: error("attachement not found ${it.targetOutput}") + ?: error("attachment not found ${it.targetOutput}") target.blendMode(index, it.blendMode) } } @@ -305,7 +306,26 @@ class SceneRenderer { primitive.primitive.geometry.vertexCount) } } - drawer.depthWrite = true + + context.pathMeshes.filter { (it.content.material.transparent && pass.renderTransparent) || (!it.content.material.transparent && pass.renderOpaque) } + .forEach { + drawer.isolated { + val primitiveContext = PrimitiveContext(true, false) + val shadeStyle = it.content.material.generateShadeStyle(materialContext, primitiveContext) + shadeStyle.parameter("viewMatrixInverse", drawer.view.inversed) + it.content.material.applyToShadeStyle(materialContext, shadeStyle) + drawer.drawStyle.cullTestPass = CullTestPass.ALWAYS + drawer.shadeStyle = shadeStyle + drawer.model = it.node.worldTransform + drawer.strokeWeight = it.content.weight + for (path in it.content.paths) { + drawer.path(path.sampleLinear(0.0005)) + } + } + } + + + drawer.depthWrite = true } } diff --git a/orx-dnk3/src/main/kotlin/cubemap/CubemapFilter.kt b/orx-dnk3/src/main/kotlin/cubemap/CubemapFilter.kt index b62aa011..93dbe60a 100644 --- a/orx-dnk3/src/main/kotlin/cubemap/CubemapFilter.kt +++ b/orx-dnk3/src/main/kotlin/cubemap/CubemapFilter.kt @@ -73,7 +73,7 @@ open class CubemapFilter(private val shader: Shader? = null, private val watcher renderTarget.detachDepthBuffer() } - renderTarget.detachColorBuffers() + renderTarget.detachColorAttachments() renderTarget.destroy() } } diff --git a/orx-dnk3/src/main/kotlin/dsl/SceneBuilder.kt b/orx-dnk3/src/main/kotlin/dsl/SceneBuilder.kt index f678deb9..26b966c5 100644 --- a/orx-dnk3/src/main/kotlin/dsl/SceneBuilder.kt +++ b/orx-dnk3/src/main/kotlin/dsl/SceneBuilder.kt @@ -19,7 +19,7 @@ fun SceneNode.node(builder: SceneNode.() -> Unit): SceneNode { return node } -fun SceneNode.hemisphereLight(builder: HemisphereLight.() -> Unit) : HemisphereLight { +fun SceneNode.hemisphereLight(builder: HemisphereLight.() -> Unit): HemisphereLight { val hemisphereLight = HemisphereLight() hemisphereLight.builder() entities.add(hemisphereLight) @@ -64,17 +64,25 @@ class SimpleMeshBuilder { } } -fun Scene.update(function: ()->Unit) { - dispatcher.launch { - while (true) { - function() - yield() - } - } -} - fun SceneNode.simpleMesh(builder: SimpleMeshBuilder.() -> Unit): Mesh { val mesh = SimpleMeshBuilder().apply { builder() }.build() entities.add(mesh) return mesh } + + +fun SceneNode.pathMesh(builder: PathMesh.() -> Unit): PathMesh { + val pathMesh = PathMesh(mutableListOf(), DummyMaterial(), 1.0) + pathMesh.builder() + entities.add(pathMesh) + return pathMesh +} + +fun Scene.update(function: () -> Unit) { + dispatcher.launch { + while (true) { + function() + yield() + } + } +} diff --git a/orx-dnk3/src/main/kotlin/gltf/GltfScene.kt b/orx-dnk3/src/main/kotlin/gltf/GltfScene.kt index bc763a9b..cc4a89f6 100644 --- a/orx-dnk3/src/main/kotlin/gltf/GltfScene.kt +++ b/orx-dnk3/src/main/kotlin/gltf/GltfScene.kt @@ -17,7 +17,7 @@ import kotlin.reflect.KMutableProperty0 class SceneAnimation(var channels: List) { val duration: Double get() { - return channels.maxBy { it.duration }?.duration ?: 0.0 + return channels.maxByOrNull { it.duration }?.duration ?: 0.0 } fun applyToTargets(input: Double) { for (channel in channels) { diff --git a/orx-filter-extension/src/main/kotlin/FilterExtension.kt b/orx-filter-extension/src/main/kotlin/FilterExtension.kt index b541605d..de9d6df0 100644 --- a/orx-filter-extension/src/main/kotlin/FilterExtension.kt +++ b/orx-filter-extension/src/main/kotlin/FilterExtension.kt @@ -22,7 +22,7 @@ fun Program.extend(filter: F, configuration: F.() -> Unit = {}): Ex if (renderTarget == null || renderTarget?.width != program.width || renderTarget?.height != program.height) { renderTarget?.let { it.colorBuffer(0).destroy() - it.detachColorBuffers() + it.detachColorAttachments() it.destroy() } diff --git a/orx-keyframer/src/main/kotlin/Keyframer.kt b/orx-keyframer/src/main/kotlin/Keyframer.kt index fd803af4..ea4716fa 100644 --- a/orx-keyframer/src/main/kotlin/Keyframer.kt +++ b/orx-keyframer/src/main/kotlin/Keyframer.kt @@ -59,7 +59,7 @@ open class Keyframer { } val duration: Double - get() = channels.values.maxBy { it.duration() }?.duration() ?: 0.0 + get() = channels.values.maxByOrNull { it.duration() }?.duration() ?: 0.0 inner class DoubleChannel(key: String, defaultValue: Double = 0.0) : diff --git a/orx-kotlin-parser/src/main/kotlin/TreeUtils.kt b/orx-kotlin-parser/src/main/kotlin/TreeUtils.kt index a8443ac4..095bef48 100644 --- a/orx-kotlin-parser/src/main/kotlin/TreeUtils.kt +++ b/orx-kotlin-parser/src/main/kotlin/TreeUtils.kt @@ -22,7 +22,7 @@ object TreeUtils { } private fun process(t: Tree, ruleNames: List): String { - if (t.getChildCount() === 0) return Utils.escapeWhitespace(Trees.getNodeText(t, ruleNames), false) + if (t.getChildCount() == 0) return Utils.escapeWhitespace(Trees.getNodeText(t, ruleNames), false) val sb = StringBuilder() sb.append(lead(level)) level++ diff --git a/orx-mesh-generators/src/main/kotlin/Cap.kt b/orx-mesh-generators/src/main/kotlin/Cap.kt index 47e8066b..7e9a37de 100644 --- a/orx-mesh-generators/src/main/kotlin/Cap.kt +++ b/orx-mesh-generators/src/main/kotlin/Cap.kt @@ -7,7 +7,7 @@ import org.openrndr.math.YPolarity import org.openrndr.math.transforms.rotateY fun generateCap(sides: Int, radius: Double, enveloppe: List = listOf(Vector2(0.0, 0.0), Vector2(1.0, 0.0)), writer: VertexWriter) { - val maxX = enveloppe.maxBy { it.x } ?: Vector2(1.0, 0.0) + val maxX = enveloppe.maxByOrNull { it.x } ?: Vector2(1.0, 0.0) val a = maxX.x val cleanEnveloppe = enveloppe.map { Vector2((it.x / a) * radius, it.y) } @@ -51,7 +51,7 @@ fun generateCap(sides: Int, radius: Double, enveloppe: List = listOf(Ve } fun generateRevolve(sides: Int, length: Double, enveloppe: List = listOf(Vector2(1.0, 0.0), Vector2(1.0, 1.0)), writer: VertexWriter) { - val maxY = enveloppe.maxBy { it.y } ?: Vector2(0.0, 1.0) + val maxY = enveloppe.maxByOrNull { it.y } ?: Vector2(0.0, 1.0) val a = maxY.y val cleanEnveloppe = enveloppe.map { Vector2((it.x), (it.y/a - 0.5) * length ) } @@ -62,8 +62,6 @@ fun generateRevolve(sides: Int, length: Double, enveloppe: List = listO } - val extended = listOf(normals2D[0]) + normals2D + normals2D[normals2D.size-1] - val basePositions = cleanEnveloppe.map { Vector3(it.x, it.y, 0.0) } val baseNormals = normals2D.map { Vector3(it.x, it.y, 0.0) } diff --git a/orx-mesh-generators/src/main/kotlin/GeneratorBuffer.kt b/orx-mesh-generators/src/main/kotlin/GeneratorBuffer.kt index 408ff677..152eb1ab 100644 --- a/orx-mesh-generators/src/main/kotlin/GeneratorBuffer.kt +++ b/orx-mesh-generators/src/main/kotlin/GeneratorBuffer.kt @@ -32,8 +32,8 @@ class GeneratorBuffer { fun toByteBuffer(): ByteBuffer { val bb = ByteBuffer.allocateDirect(data.size * (3 * 4 + 3 * 4 + 2 * 4)) bb.order(ByteOrder.nativeOrder()) - bb.rewind() for (d in data) { + bb.rewind() bb.putFloat(d.position.x.toFloat()) bb.putFloat(d.position.y.toFloat()) bb.putFloat(d.position.z.toFloat()) @@ -212,15 +212,3 @@ fun GeneratorBuffer.group(builder: GeneratorBuffer.() -> Unit) { gb.builder() this.concat(gb) } - -fun main(args: Array) { - val gb = generator { - box(20.0, 20.0, 20.0) - group { - box(40.0, 40.0, 40.0) - transform(transform { - translate(0.0, 20.0, 0.0) - }) - } - } -} \ No newline at end of file diff --git a/orx-palette/src/main/kotlin/PaletteStudio.kt b/orx-palette/src/main/kotlin/PaletteStudio.kt index 1e1bb8aa..743fc3d0 100644 --- a/orx-palette/src/main/kotlin/PaletteStudio.kt +++ b/orx-palette/src/main/kotlin/PaletteStudio.kt @@ -138,7 +138,7 @@ class PaletteStudio( val foreground = clrs .takeLast(clrs.size - 1) .map { getContrast(background, it) to it } - .maxBy { it.first }!! + .maxByOrNull { it.first }!! .second var constraint = clrs.size diff --git a/orx-panel/src/main/kotlin/org/openrndr/panel/elements/EnvelopeEditor.kt b/orx-panel/src/main/kotlin/org/openrndr/panel/elements/EnvelopeEditor.kt index 1994a701..54e3d9ce 100644 --- a/orx-panel/src/main/kotlin/org/openrndr/panel/elements/EnvelopeEditor.kt +++ b/orx-panel/src/main/kotlin/org/openrndr/panel/elements/EnvelopeEditor.kt @@ -37,7 +37,7 @@ class Envelope(constant:Double = 0.5) { events.envelopeChanged.trigger(EnvelopeChangedEvent(this)) } - fun findNearestPoint(v: Vector2) = points.minBy { (it - v).length } + fun findNearestPoint(v: Vector2) = points.minByOrNull { (it - v).length } fun removePoint(v: Vector2) { points.remove(v) diff --git a/orx-panel/src/main/kotlin/org/openrndr/panel/hash/WatchHash.kt b/orx-panel/src/main/kotlin/org/openrndr/panel/hash/WatchHash.kt index d127c4dd..8310ae9c 100644 --- a/orx-panel/src/main/kotlin/org/openrndr/panel/hash/WatchHash.kt +++ b/orx-panel/src/main/kotlin/org/openrndr/panel/hash/WatchHash.kt @@ -1,12 +1,13 @@ package org.openrndr.panel.hash import kotlin.reflect.KProperty0 +import kotlin.reflect.KProperty1 import kotlin.reflect.full.declaredMemberProperties fun watchHash(toHash: Any): Int { var hash = 0 for (property in toHash::class.declaredMemberProperties) { - val v = (property.getter)(toHash) + val v = ((property.getter) as KProperty1).invoke(toHash) if (v is KProperty0<*>) { val pv = v.get() hash = 31 * hash + (pv?.hashCode() ?: 0)