stylus icon indicating copy to clipboard operation
stylus copied to clipboard

Can one use stylus without AWT / JAVAFX?

Open hamoid opened this issue 3 years ago • 7 comments

Hi,

I am trying to add support for graphic tablets to the OPENRNDR creative coding framework written in Kotlin. First I tried using https://github.com/nicarran/jpen but it's no longer under active development and I have issues making it work. I was pointed to this repo and I'm very happy that there are packages I can use from Gradle.

Question: is it possible to use it without AWT or JAVAFX? OPENRNDR uses LWJGL which in turn uses GLFW. I do have access to window size, window position, pointer position and button states. What I'm missing is pressure and tilt.

Is the readme the only documentation available so far?

I see the included demos are rich in features and source code files. An idea for the future: include a minimal demo only showing how to read the state from the stylus. I think that would make it easier to understand how to integrate it in a project.

Thank you for writing and sharing your code.

hamoid avatar May 28 '22 09:05 hamoid

This is the code I came up with for testing (it's the whole program):

import org.lecturestudio.stylus.*
import org.openrndr.application
import org.openrndr.color.rgb
import org.openrndr.math.Vector2

fun main() = application {
    program {
        var pressure = 0.0
        var tilt = Vector2.ZERO
        val manager = StylusManager.getInstance()
        val stylusListener: StylusListener = object : StylusListener {
            override fun onCursorChange(event: StylusEvent?) {
                println(event)
            }

            override fun onCursorMove(event: StylusEvent) {
                event.axesData.let {
                    pressure = it.pressure
                    tilt = Vector2(it.tiltX, it.tiltY) * 0.5 + 0.5
                }
            }

            override fun onButtonDown(event: StylusEvent?) {
                println(event)
            }

            override fun onButtonUp(event: StylusEvent?) {
                println(event)
            }
        }
        manager.attachStylusListener(stylusListener, this)
        extend {
            if(mouse.pressedButtons.isNotEmpty()) {
                drawer.stroke = null
                drawer.fill = rgb(tilt.x, tilt.y, 1.0)
                drawer.circle(mouse.position, pressure * 50.0)
            }
        }
    }
}

I added stylus to the build.gradle.kts file but the program fails to start with this error:

May 29, 2022 2:06:38 PM org.lecturestudio.stylus.StylusManager <clinit>
SEVERE: Load stylus library failed
java.lang.NullPointerException
	at java.base/java.util.Objects.requireNonNull(Objects.java:208)
	at java.base/java.nio.file.Files.copy(Files.java:3112)
	at org.lecturestudio.stylus.internal.NativeLoader.loadLibrary(NativeLoader.java:62)
	at org.lecturestudio.stylus.StylusManager.<clinit>(StylusManager.java:30)
	at apps2022.TestStylusKt$main$1$1.invokeSuspend(testStylus.kt:12)
	at apps2022.TestStylusKt$main$1$1.invoke(testStylus.kt)
	at apps2022.TestStylusKt$main$1$1.invoke(testStylus.kt)
        ...

Any suggestions to solve this? I'm on Linux, latest Idea & Gradle.

hamoid avatar May 29 '22 12:05 hamoid

I tried setting JAVA_HOME correctly, then running mvn install, then copying the produced stylus-jni/target/lib/libstylus.so file to /usr/lib and various other folders but that did not help.

hamoid avatar May 31 '22 14:05 hamoid

I was having the same problem, and got it working by copying both the stylus library as well as the stylus-jni library. I'm still struggling to get a simple example (like the one you have above) working though, so if you manage to get something like that working let me know

Polian avatar Jun 20 '22 15:06 Polian

My colleague showed me how to use the right dependencies:

dependencies {
            implementation("org.lecturestudio.stylus:stylus:0.2.0")
            runtimeOnly("org.lecturestudio.stylus:stylus:0.2.0:linux-x86_64")
}

With that I didn't need to build it myself and the library is found. Unfortunately also couldn't make it work. We get this error:

Exception in thread "main" java.lang.NoSuchFieldError: nativeHandle
	at org.lecturestudio.stylus.StylusManager.attachStylusListener(Native Method)
	at Stylus01Kt$main$1$1.invokeSuspend(Stylus01.kt:31)
	at Stylus01Kt$main$1$1.invoke(Stylus01.kt)
	at Stylus01Kt$main$1$1.invoke(Stylus01.kt)
	at org.openrndr.ApplicationBuilder$program$1.setup(ApplicationBuilder.kt:15)
	at org.openrndr.internal.gl3.ApplicationGLFWGL3$loop$15.invokeSuspend(ApplicationGLFWGL3.kt:803)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:284)
	at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
	at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
	at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
	at org.openrndr.internal.gl3.ApplicationGLFWGL3.loop(ApplicationGLFWGL3.kt:802)
	at org.openrndr.Application$Companion.run(Application.kt:70)
	at org.openrndr.ApplicationKt.application(Application.kt:120)
	at org.openrndr.ApplicationBuilderKt.application(ApplicationBuilder.kt:81)
	at Stylus01Kt.main(Stylus01.kt:6)
	at Stylus01Kt.main(Stylus01.kt)

It looks like some method is not found. A JVM method called from C++ maybe? How does it fail in your case @Polian ?

hamoid avatar Jun 20 '22 15:06 hamoid

Yeah, that's the same error I'm getting. I dug around in the C++ a little, but I'm not familiar with this kind of code, and couldn't figure out what could be going wrong

Polian avatar Jun 20 '22 15:06 Polian

It looks like some method is not found. A JVM method called from C++ maybe? How does it fail in your case @Polian ?

Yes, you need to define a nativeHandle member variable of type long inside the listener class itself (like this: AwtStylusManager.java#L140, I don't know why it's designed that way.

Cdm2883 avatar Nov 27 '24 04:11 Cdm2883

Since I couldn't make it work at the time, and since I'm on Linux, I went for this approach: https://codeberg.org/hamoid/openrndr-oddity-coffer/src/branch/master/src/main/kotlin/kinputevents

hamoid avatar Nov 27 '24 15:11 hamoid