90 | // for (i in l.indices) putDouble(i * Double.BYTES, l[i])
91 | // }
92 | // else -> throw Error("unsupported type")
93 | // }.run {
94 | // block()
95 | // free()
96 | // }
97 | //}
--------------------------------------------------------------------------------
/core/src/main/kotlin/uno/buffer/advanced of.kt:
--------------------------------------------------------------------------------
1 | package uno.buffer
2 |
3 | import glm_.b
4 | import glm_.vec2.Vec2
5 | import glm_.vec2.Vec2i
6 | import glm_.vec3.Vec3
7 | import glm_.vec3.Vec3i
8 | import glm_.vec4.Vec4
9 | import glm_.vec4.Vec4b
10 | import glm_.vec4.Vec4i
11 | import glm_.vec4.Vec4ub
12 | //import gln.glf.Vertex
13 | //import gln.glf.glf
14 | import kool.*
15 | import java.nio.ByteBuffer
16 | import java.nio.FloatBuffer
17 | import java.nio.IntBuffer
18 |
19 |
20 | fun bufferOf(vertices: Collection<*>): ByteBuffer {
21 | val res: ByteBuffer
22 | when (vertices.elementAt(0)) {
23 | is Vec2 -> {
24 | res = Buffer(Vec2.size * vertices.size)
25 | for (i in vertices.indices)
26 | (vertices.elementAt(i) as Vec2).to(res, i * Vec2.size)
27 | }
28 | is Vec3 -> {
29 | res = Buffer(Vec3.size * vertices.size)
30 | for (i in vertices.indices)
31 | (vertices.elementAt(i) as Vec3).to(res, i * Vec3.size)
32 | }
33 | is Vec4 -> {
34 | res = Buffer(Vec4.size * vertices.size)
35 | for (i in vertices.indices)
36 | (vertices.elementAt(i) as Vec4).to(res, i * Vec4.size)
37 | }
38 | // is Vertex.pos2_tc2 -> {
39 | // res = Buffer(glf.pos2_tc2.stride * vertices.size)
40 | // for (i in vertices.indices) {
41 | // val v = vertices.elementAt(i) as Vertex.pos2_tc2
42 | // v.p.to(res, i * glf.pos2_tc2.stride)
43 | // v.t.to(res, i * glf.pos2_tc2.stride + Vec2.size)
44 | // }
45 | // }
46 | // is Vertex.pos3_col4ub -> {
47 | // res = Buffer(glf.pos3_col4ub.stride * vertices.size)
48 | // for (i in vertices.indices) {
49 | // val v = vertices.elementAt(i) as Vertex.pos3_col4ub
50 | // v.p.to(res, i * glf.pos2_tc2.stride)
51 | // v.c.to(res, i * glf.pos2_tc2.stride + Vec3.size)
52 | // }
53 | // }
54 | else -> throw Error()
55 | }
56 | return res
57 | }
58 |
59 | fun bufferOf(vararg elements: Any): ByteBuffer {
60 | val size = elements.sumOf {
61 | when (it) {
62 | is Float, Int, Vec4b -> Float.BYTES
63 | is Vec2 -> Vec2.size
64 | is Vec3 -> Vec3.size
65 | is Vec4 -> Vec4.size
66 | // is Vertex.pos2_tc2 -> Vec2.size * 2
67 | // is Vertex.pos3_col4ub -> Vec3.size + Vec4ub.size
68 | // is Vertex.pos3_nor3_col4 -> Vec3.size * 2 + Vec4.size
69 | else -> throw Exception("Invalid")
70 | }
71 | }
72 | val res = Buffer(size)
73 | var offset = 0
74 | for (e in elements)
75 | when (e) {
76 | is Float -> {
77 | res.putFloat(offset, e)
78 | offset += Float.BYTES
79 | }
80 | is Int -> {
81 | res.putInt(offset, e)
82 | offset += Int.BYTES
83 | }
84 | is Vec4b -> {
85 | e.to(res, offset)
86 | offset += Vec4b.size
87 | }
88 | is Vec2 -> {
89 | e.to(res, offset)
90 | offset += Vec2.size
91 | }
92 | is Vec3 -> {
93 | e.to(res, offset)
94 | offset += Vec3.size
95 | }
96 | is Vec4 -> {
97 | e.to(res, offset)
98 | offset += Vec4.size
99 | }
100 | // is Vertex.pos2_tc2 -> {
101 | // e.to(res, offset)
102 | // offset += Vec4b.size
103 | // }
104 | // is Vertex.pos3_col4ub -> Vec3.size + Vec4ub.size
105 | // is Vertex.pos3_nor3_col4 -> Vec3.size * 2 + Vec4.size
106 | else -> throw Exception("Invalid")
107 | }
108 | return res
109 | }
110 |
111 | fun floatBufferOf(vertices: Collection<*>): FloatBuffer {
112 | val res: FloatBuffer
113 | when (vertices.elementAt(0)) {
114 | is Float -> res = FloatBuffer(vertices.size) { vertices.elementAt(it) as Float }
115 | is Vec2 -> {
116 | res = FloatBuffer(Vec2.length * vertices.size)
117 | for (i in vertices.indices)
118 | (vertices.elementAt(i) as Vec2).to(res, i * Vec2.length)
119 | }
120 | is Vec3 -> {
121 | res = FloatBuffer(Vec3.length * vertices.size)
122 | for (i in vertices.indices)
123 | (vertices.elementAt(i) as Vec3).to(res, i * Vec3.length)
124 | }
125 | is Vec4 -> {
126 | res = FloatBuffer(Vec4.length * vertices.size)
127 | for (i in vertices.indices)
128 | (vertices.elementAt(i) as Vec4).to(res, i * Vec4.length)
129 | }
130 | else -> throw Error()
131 | }
132 | return res
133 | }
134 |
135 | fun intBufferOf(vertices: Collection<*>): IntBuffer {
136 | val res: IntBuffer
137 | when (vertices.elementAt(0)) {
138 | is Int -> res = IntBuffer(vertices.size) { vertices.elementAt(it) as Int }
139 | is Vec2i -> {
140 | res = IntBuffer(Vec2i.length * vertices.size)
141 | for (i in vertices.indices)
142 | (vertices.elementAt(i) as Vec2i).to(res, i * Vec2i.length)
143 | }
144 | is Vec3i -> {
145 | res = IntBuffer(Vec3i.length * vertices.size)
146 | for (i in vertices.indices)
147 | (vertices.elementAt(i) as Vec3i).to(res, i * Vec3i.length)
148 | }
149 | is Vec4i -> {
150 | res = IntBuffer(Vec4i.length * vertices.size)
151 | for (i in vertices.indices)
152 | (vertices.elementAt(i) as Vec4i).to(res, i * Vec4i.length)
153 | }
154 | else -> throw Error()
155 | }
156 | return res
157 | }
158 |
159 | fun bufferOf(s: String) = ByteBuffer(s.length) { s[it].b }
--------------------------------------------------------------------------------
/core/src/main/kotlin/uno/convert/ascii85.kt:
--------------------------------------------------------------------------------
1 | package uno.convert
2 |
3 | import glm_.b
4 | import glm_.i
5 | import uno.glm.toBidDec
6 | import unsigned.toULong
7 | import java.nio.ByteBuffer
8 |
9 | object Ascii85 {
10 |
11 | private val ASCII_SHIFT = 33
12 |
13 | private val BASE85_POW = intArrayOf(
14 | 1,
15 | 85,
16 | 85 * 85,
17 | 85 * 85 * 85,
18 | 85 * 85 * 85 * 85)
19 |
20 | fun encode(payload: ByteArray): String {
21 |
22 | if (payload.isEmpty()) throw IllegalArgumentException("You must provide a non-zero length input")
23 |
24 | /* By using five ASCII characters to represent four bytes of binary data the encoded size ¹⁄₄ is larger than
25 | the original */
26 | val stringBuff = StringBuilder(payload.size * 5 / 4)
27 | // We break the payload into int (4 bytes)
28 | val chunk = ByteArray(4)
29 | var chunkIndex = 0
30 | for (currByte in payload) {
31 |
32 | chunk[chunkIndex++] = currByte
33 |
34 | if (chunkIndex == 4) {
35 |
36 | val value = chunk.int
37 | /* Because all-zero data is quite common, an exception is made for the sake of data compression, and an
38 | all-zero group is encoded as a single character "z" instead of "!!!!!". */
39 | if (value == 0)
40 | stringBuff.append('z')
41 | else
42 | stringBuff.append(encodeChunk(value))
43 |
44 | chunk.fill(0)
45 | chunkIndex = 0
46 | }
47 | }
48 |
49 | // If we didn't end on 0, then we need some padding
50 | if (chunkIndex > 0) {
51 |
52 | val numPadded = chunk.size - chunkIndex
53 | chunk.fill(0, chunkIndex, chunk.size)
54 | val value = chunk.int
55 | val encodedChunk = encodeChunk(value)
56 | for (i in 0 until encodedChunk.size - numPadded)
57 | stringBuff.append(encodedChunk[i])
58 | }
59 |
60 | return stringBuff.toString()
61 | }
62 |
63 | private fun encodeChunk(value: Int): CharArray {
64 | // transform value to unsigned long
65 | var longValue = value.toULong()
66 | val encodedChunk = CharArray(5)
67 | for (i in encodedChunk.indices) {
68 | encodedChunk[i] = (longValue / BASE85_POW[4 - i] + ASCII_SHIFT).toInt().toChar()
69 | longValue %= BASE85_POW[4 - i]
70 | }
71 | return encodedChunk
72 | }
73 |
74 | /**
75 | * This is a very simple base85 decoder. It respects the 'z' optimization for empty chunks, and strips whitespace
76 | * between characters to respect line limits.
77 | *
78 | * @param chars The input characters that are base85 encoded.
79 | * @return The binary data decoded from the input
80 | * @see [Ascii85](https://en.wikipedia.org/wiki/Ascii85)
81 | */
82 | fun decode(chars: String): ByteArray {
83 |
84 | if (chars.isEmpty()) throw IllegalArgumentException("You must provide a non-zero length input")
85 |
86 | /* By using five ASCII characters to represent four bytes of binary data the encoded size ¹⁄₄ is larger than
87 | the original */
88 | val decodedLength = chars.length.toBidDec() * 4.toBidDec() / 5.toBidDec()
89 | val buffer = ByteBuffer.allocate(decodedLength.i)
90 | val payload = chars
91 | /* Whitespace and new lines characters may occur anywhere to accommodate line length limitations.
92 | So lets strip it. */
93 | .filter { it != ' ' && it != '\n' }
94 | .toByteArray() // Since Base85 is an ascii encoder, we don't need to get the bytes as UTF-8.
95 |
96 | val chunk = ByteArray(5)
97 | var chunkIndex = 0
98 | for (byte in payload) {
99 | /* Because all-zero data is quite common, an exception is made for the sake of data compression, and an
100 | all-zero group is encoded as a single character "z" instead of "!!!!!". */
101 | if (byte == 'z'.b) {
102 |
103 | if (chunkIndex > 0) throw IllegalArgumentException("The payload is not base 85 encoded.")
104 |
105 | chunk[chunkIndex++] = '!'.b
106 | chunk[chunkIndex++] = '!'.b
107 | chunk[chunkIndex++] = '!'.b
108 | chunk[chunkIndex++] = '!'.b
109 | chunk[chunkIndex++] = '!'.b
110 |
111 | } else
112 | chunk[chunkIndex++] = byte
113 |
114 | if (chunkIndex == 5) {
115 | buffer.put(decodeChunk(chunk))
116 | chunk.fill(0)
117 | chunkIndex = 0
118 | }
119 | }
120 |
121 | //If we didn't end on 0, then we need some padding
122 | if (chunkIndex > 0) {
123 |
124 | val numPadded = chunk.size - chunkIndex
125 | chunk.fill('u'.b, chunkIndex, chunk.size)
126 | val paddedDecode = decodeChunk(chunk)
127 | for (i in 0 until paddedDecode.size - numPadded)
128 | buffer.put(paddedDecode[i])
129 | }
130 |
131 | buffer.flip()
132 | return buffer.array().copyOf(buffer.limit())
133 | }
134 |
135 | private fun decodeChunk(chunk: ByteArray): ByteArray {
136 |
137 | if (chunk.size != 5) throw IllegalArgumentException("You can only decode chunks of size 5.")
138 |
139 | return (0..4)
140 | .sumOf { (chunk[it] - ASCII_SHIFT) * BASE85_POW[4 - it] }
141 | .byteArray
142 | }
143 |
144 | private val ByteArray.int: Int
145 | get() {
146 | if (size != 4) throw IllegalArgumentException("You cannot create an int without exactly 4 bytes.")
147 | return ByteBuffer.wrap(this).int
148 | }
149 |
150 | private val Int.byteArray get() = byteArrayOf(ushr(24).b, ushr(16).b, ushr(8).b, b)
151 | }
--------------------------------------------------------------------------------
/awt/src/test/kotlin/uno/jawt/HelloTinyFD.java:
--------------------------------------------------------------------------------
1 | //package main;
2 | //
3 | //import org.lwjgl.PointerBuffer;
4 | //import org.lwjgl.glfw.GLFWErrorCallback;
5 | //import org.lwjgl.glfw.GLFWVidMode;
6 | //import org.lwjgl.opengl.GL;
7 | //import org.lwjgl.system.MemoryStack;
8 | //
9 | //import java.nio.*;
10 | //import java.util.*;
11 | //
12 | //import static org.lwjgl.glfw.Callbacks.*;
13 | //import static org.lwjgl.glfw.GLFW.*;
14 | //import static org.lwjgl.opengl.GL11C.*;
15 | //import static org.lwjgl.system.MemoryStack.*;
16 | //import static org.lwjgl.system.MemoryUtil.*;
17 | //import static org.lwjgl.util.tinyfd.TinyFileDialogs.*;
18 | //
19 | //public final class HelloTinyFD {
20 | //
21 | // private HelloTinyFD() {
22 | // }
23 | //
24 | // public static void main(String[] args) {
25 | // GLFWErrorCallback.createPrint().set();
26 | // if (!glfwInit()) {
27 | // throw new IllegalStateException("Unable to initialize GLFW");
28 | // }
29 | //
30 | // long window = glfwCreateWindow(300, 300, "Hello tiny file dialogs!", NULL, NULL);
31 | // if (window == NULL) {
32 | // throw new RuntimeException("Failed to create the GLFW window");
33 | // }
34 | //
35 | // glfwSetKeyCallback(window, (windowHnd, key, scancode, action, mods) -> {
36 | // if (action == GLFW_RELEASE) {
37 | // return;
38 | // }
39 | //
40 | // switch (key) {
41 | // case GLFW_KEY_ESCAPE:
42 | // glfwSetWindowShouldClose(windowHnd, true);
43 | // break;
44 | // case GLFW_KEY_B:
45 | // tinyfd_beep();
46 | // break;
47 | // case GLFW_KEY_N:
48 | // System.out.println("\nOpening notification popup...");
49 | // System.out.println(tinyfd_notifyPopup("Please read...", "...this message.", "info"));
50 | // break;
51 | // case GLFW_KEY_1:
52 | // System.out.println("\nOpening message dialog...");
53 | // System.out.println(tinyfd_messageBox("Please read...", "...this message.", "okcancel", "info", true) ? "OK" : "Cancel");
54 | // break;
55 | // case GLFW_KEY_2:
56 | // System.out.println("\nOpening input box dialog...");
57 | // System.out.println(tinyfd_inputBox("Input Value", "How old are you?", "30"));
58 | // break;
59 | // case GLFW_KEY_3:
60 | // System.out.println("\nOpening file open dialog...");
61 | // System.out.println(tinyfd_openFileDialog("Open File(s)", "", null, null, true));
62 | // break;
63 | // case GLFW_KEY_4:
64 | // try (MemoryStack stack = stackPush()) {
65 | // PointerBuffer aFilterPatterns = stack.mallocPointer(2);
66 | //
67 | // aFilterPatterns.put(stack.UTF8("*.jpg"));
68 | // aFilterPatterns.put(stack.UTF8("*.png"));
69 | //
70 | // aFilterPatterns.flip();
71 | //
72 | // System.out.println("\nOpening file save dialog...");
73 | // System.out.println(tinyfd_saveFileDialog("Save Image", "", aFilterPatterns, "Image files (*.jpg, *.png)"));
74 | // }
75 | // break;
76 | // case GLFW_KEY_5:
77 | // System.out.println("\nOpening folder select dialog...");
78 | // System.out.println(tinyfd_selectFolderDialog("Select Folder", ""));
79 | // break;
80 | // case GLFW_KEY_6:
81 | // System.out.println("\nOpening color chooser dialog...");
82 | // try (MemoryStack stack = stackPush()) {
83 | // ByteBuffer color = stack.malloc(3);
84 | // String hex = tinyfd_colorChooser("Choose Color", "#FF00FF", null, color);
85 | // System.out.println(hex);
86 | // if (hex != null) {
87 | // System.out.println("\tR: " + (color.get(0) & 0xFF));
88 | // System.out.println("\tG: " + (color.get(1) & 0xFF));
89 | // System.out.println("\tB: " + (color.get(2) & 0xFF));
90 | // }
91 | // }
92 | // break;
93 | // }
94 | // });
95 | //
96 | // // Center window
97 | // GLFWVidMode vidmode = Objects.requireNonNull(glfwGetVideoMode(glfwGetPrimaryMonitor()));
98 | // glfwSetWindowPos(
99 | // window,
100 | // (vidmode.width() - 300) / 2,
101 | // (vidmode.height() - 300) / 2
102 | // );
103 | //
104 | // glfwMakeContextCurrent(window);
105 | // GL.createCapabilities();
106 | //
107 | // glfwSwapInterval(1);
108 | //
109 | // tinyfd_messageBox("tinyfd_query", "", "ok", "info", true);
110 | // System.out.println("tiny file dialogs " + tinyfd_version + " (" + tinyfd_response() + ")");
111 | // System.out.println();
112 | // System.out.println(tinyfd_needs);
113 | // System.out.println();
114 | // System.out.println("Press 1 to launch a message dialog.");
115 | // System.out.println("Press 2 to launch an input box fialog.");
116 | // System.out.println("Press 3 to launch a file open dialog.");
117 | // System.out.println("Press 4 to launch a file save dialog.");
118 | // System.out.println("Press 5 to launch a folder select dialog.");
119 | // System.out.println("Press 6 to launch a color chooser dialog.");
120 | // while (!glfwWindowShouldClose(window)) {
121 | // glfwPollEvents();
122 | //
123 | // glClear(GL_COLOR_BUFFER_BIT);
124 | // glfwSwapBuffers(window);
125 | // }
126 | //
127 | // GL.setCapabilities(null);
128 | //
129 | // glfwFreeCallbacks(window);
130 | // glfwDestroyWindow(window);
131 | // glfwTerminate();
132 | //
133 | // Objects.requireNonNull(glfwSetErrorCallback(null)).free();
134 | // }
135 | //
136 | //}
137 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/awt/src/test/kotlin/uno/jawt/AbstractGears.kt:
--------------------------------------------------------------------------------
1 | package uno.jawt
2 |
3 |
4 | import glm_.d
5 | import glm_.f
6 | import glm_.func.cos
7 | import glm_.func.sin
8 | import glm_.vec2.Vec2i
9 | import org.lwjgl.opengl.GL11.*
10 | import uno.glfw.stak
11 | import kotlin.math.sqrt
12 |
13 |
14 | class AbstractGears {
15 |
16 | private val viewRotZ = 0f
17 |
18 | private var gear1 = 0
19 | private var gear2 = 0
20 | private var gear3 = 0
21 |
22 | private var angle = 0f
23 |
24 | fun init() = stak {
25 | println("GL_VENDOR: ${glGetString(GL_VENDOR)}")
26 | println("GL_RENDERER: ${glGetString(GL_RENDERER)}")
27 | println("GL_VERSION: ${glGetString(GL_VERSION)}")
28 |
29 | // setup ogl
30 | glEnable(GL_CULL_FACE)
31 | glEnable(GL_LIGHTING)
32 | glEnable(GL_LIGHT0)
33 | glEnable(GL_DEPTH_TEST)
34 |
35 | // make the gears
36 | gear1 = glGenLists(1)
37 | glNewList(gear1, GL_COMPILE)
38 | glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, it.floats(0.8f, 0.1f, 0f, 1f))
39 | gear(1f, 4f, 1f, 20, 0.7f)
40 | glEndList()
41 |
42 | gear2 = glGenLists(1)
43 | glNewList(gear2, GL_COMPILE)
44 | glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, it.floats(0f, 0.8f, 0.2f, 1f))
45 | gear(0.5f, 2f, 2f, 10, 0.7f)
46 | glEndList()
47 |
48 | gear3 = glGenLists(1)
49 | glNewList(gear3, GL_COMPILE)
50 | glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, it.floats(0.2f, 0.2f, 1f, 1f))
51 | gear(1.3f, 2f, 0.5f, 10, 0.7f)
52 | glEndList()
53 |
54 | glEnable(GL_NORMALIZE)
55 |
56 | glMatrixMode(GL_MODELVIEW)
57 | glLoadIdentity()
58 | glTranslatef(0f, 0f, -40f)
59 | }
60 |
61 | fun render() {
62 | angle += 2f
63 |
64 | glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
65 |
66 | glPushMatrix()
67 | glRotatef(view_rotx, 1f, 0f, 0f)
68 | glRotatef(view_roty, 0f, 1f, 0f)
69 | glRotatef(viewRotZ, 0f, 0f, 1f)
70 |
71 | stak { glLightfv(GL_LIGHT0, GL_POSITION, it.floats(5f, 5f, 10f, 0f)) }
72 |
73 | glPushMatrix()
74 | glTranslatef(-3f, -2f, 0f)
75 | glRotatef(angle, 0f, 0f, 1f)
76 | glCallList(gear1)
77 | glPopMatrix()
78 |
79 | glPushMatrix()
80 | glTranslatef(3.1f, -2f, 0f)
81 | glRotatef(-2f * angle - 9f, 0f, 0f, 1f)
82 | glCallList(gear2)
83 | glPopMatrix()
84 |
85 | glPushMatrix()
86 | glTranslatef(-3.1f, 4.2f, 0f)
87 | glRotatef(-2f * angle - 25f, 0f, 0f, 1f)
88 | glCallList(gear3)
89 | glPopMatrix()
90 |
91 | glPopMatrix()
92 | }
93 |
94 | fun reshape(size: Vec2i) {
95 |
96 | glViewport(0, 0, size.x, size.y)
97 |
98 | val f = size.aspect
99 |
100 | glMatrixMode(GL_PROJECTION)
101 | glLoadIdentity()
102 | glFrustum(-1.0, 1.0, -f.d, f.d, 5.0, 100.0)
103 | glMatrixMode(GL_MODELVIEW)
104 | }
105 |
106 | fun destroy() = glDeleteLists(gear1, 3)
107 |
108 | companion object {
109 |
110 | private val view_rotx = 20f
111 | private val view_roty = 30f
112 |
113 | /**
114 | * Draw a gear wheel. You'll probably want to call this function when
115 | * building a display list since we do a lot of trig here.
116 | *
117 | * @param innerRadius radius of hole at center
118 | * @param outerRadius radius at center of teeth
119 | * @param width width of gear
120 | * @param teeth number of teeth
121 | * @param toothDepth depth of tooth
122 | */
123 | private fun gear(innerRadius: Float, outerRadius: Float, width: Float, teeth: Int, toothDepth: Float) {
124 | var angle: Float
125 | val da = 2f * Math.PI.f / teeth.f / 4f
126 |
127 | val r1 = outerRadius - toothDepth / 2.0f
128 | val r2 = outerRadius + toothDepth / 2.0f
129 |
130 | glShadeModel(GL_FLAT)
131 |
132 | glNormal3f(0.0f, 0.0f, 1.0f)
133 |
134 | var i = 0
135 |
136 | /* draw front face */
137 | glBegin(GL_QUAD_STRIP)
138 | while (i <= teeth) {
139 | angle = i.f * 2f * Math.PI.f / teeth
140 |
141 | glVertex3f(innerRadius * angle.cos, innerRadius * angle.sin, width * 0.5f)
142 | glVertex3f(r1 * angle.cos, r1 * angle.sin, width * 0.5f)
143 | if (i < teeth) {
144 | glVertex3f(innerRadius * angle.cos, innerRadius * angle.sin, width * 0.5f)
145 | glVertex3f(r1 * (angle + 3f * da).cos, r1 * (angle + 3f * da).sin, width * 0.5f)
146 | }
147 | i++
148 | }
149 | glEnd()
150 |
151 | /* draw front sides of teeth */
152 | glBegin(GL_QUADS)
153 | i = 0
154 | while (i < teeth) {
155 | angle = i.toFloat() * 2.0f * Math.PI.toFloat() / teeth
156 |
157 | glVertex3f(r1 * angle.cos, r1 * angle.sin, width * 0.5f)
158 | glVertex3f(r2 * (angle + da).cos, r2 * (angle + da).sin, width * 0.5f)
159 | glVertex3f(r2 * (angle + 2f * da).cos, r2 * (angle + 2f * da).sin, width * 0.5f)
160 | glVertex3f(r1 * (angle + 3f * da).cos, r1 * (angle + 3f * da).sin, width * 0.5f)
161 | i++
162 | }
163 | glEnd()
164 |
165 | /* draw back face */
166 | glBegin(GL_QUAD_STRIP)
167 | i = 0
168 | while (i <= teeth) {
169 | angle = i.f * 2f * Math.PI.f / teeth
170 |
171 | glVertex3f(r1 * angle.cos, r1 * angle.sin, -width * 0.5f)
172 | glVertex3f(innerRadius * angle.cos, innerRadius * angle.sin, -width * 0.5f)
173 | glVertex3f(r1 * (angle + 3 * da).cos, r1 * (angle + 3 * da).sin, -width * 0.5f)
174 | glVertex3f(innerRadius * angle.cos, innerRadius * angle.sin, -width * 0.5f)
175 | i++
176 | }
177 | glEnd()
178 |
179 | /* draw back sides of teeth */
180 | glBegin(GL_QUADS)
181 | i = 0
182 | while (i < teeth) {
183 | angle = i.f * 2f * Math.PI.f / teeth
184 |
185 | glVertex3f(r1 * (angle + 3 * da).cos, r1 * (angle + 3 * da).sin, -width * 0.5f)
186 | glVertex3f(r2 * (angle + 2 * da).cos, r2 * (angle + 2 * da).sin, -width * 0.5f)
187 | glVertex3f(r2 * (angle + da).cos, r2 * (angle + da).sin, -width * 0.5f)
188 | glVertex3f(r1 * angle.cos, r1 * angle.sin, -width * 0.5f)
189 | i++
190 | }
191 | glEnd()
192 |
193 | /* draw outward faces of teeth */
194 | glBegin(GL_QUAD_STRIP)
195 | i = 0
196 | while (i < teeth) {
197 | angle = i.toFloat() * 2.0f * Math.PI.toFloat() / teeth
198 |
199 | glVertex3f(r1 * angle.cos, r1 * angle.sin, width * 0.5f)
200 | glVertex3f(r1 * angle.cos, r1 * angle.sin, -width * 0.5f)
201 |
202 | var u = r2 * (angle + da).cos - r1 * angle.cos
203 | var v = r2 * (angle + da).sin - r1 * angle.sin
204 |
205 | val len = sqrt(u * u + v * v)
206 |
207 | u /= len
208 | v /= len
209 |
210 | glNormal3f(v, -u, 0f)
211 | glVertex3f(r2 * (angle + da).cos, r2 * (angle + da).sin, width * 0.5f)
212 | glVertex3f(r2 * (angle + da).cos, r2 * (angle + da).sin, -width * 0.5f)
213 | glNormal3f(angle.cos, angle.sin, 0f)
214 | glVertex3f(r2 * (angle + 2 * da).cos, r2 * (angle + 2 * da).sin, width * 0.5f)
215 | glVertex3f(r2 * (angle + 2 * da).cos, r2 * (angle + 2 * da).sin, -width * 0.5f)
216 |
217 | u = r1 * (angle + 3 * da).cos - r2 * (angle + 2 * da).cos
218 | v = r1 * (angle + 3 * da).sin - r2 * (angle + 2 * da).sin
219 |
220 | glNormal3f(v, -u, 0f)
221 | glVertex3f(r1 * (angle + 3 * da).cos, r1 * (angle + 3 * da).sin, width * 0.5f)
222 | glVertex3f(r1 * (angle + 3 * da).cos, r1 * (angle + 3 * da).sin, -width * 0.5f)
223 | glNormal3f(angle.cos, angle.sin, 0f)
224 | i++
225 | }
226 | glVertex3f(r1 * 0f.cos, r1 * 0f.sin, width * 0.5f)
227 | glVertex3f(r1 * 0f.cos, r1 * 0f.sin, -width * 0.5f)
228 | glEnd()
229 |
230 | glShadeModel(GL_SMOOTH)
231 |
232 | /* draw inside radius cylinder */
233 | glBegin(GL_QUAD_STRIP)
234 | i = 0
235 | while (i <= teeth) {
236 | angle = i.f * 2f * Math.PI.f / teeth
237 |
238 | glNormal3f(-angle.cos, -angle.sin, 0f)
239 | glVertex3f(innerRadius * angle.cos, innerRadius * angle.sin, -width * 0.5f)
240 | glVertex3f(innerRadius * angle.cos, innerRadius * angle.sin, width * 0.5f)
241 | i++
242 | }
243 | glEnd()
244 | }
245 | }
246 |
247 | }
--------------------------------------------------------------------------------
/gl/src/test/kotlin/examples/gears.kt:
--------------------------------------------------------------------------------
1 | package examples
2 |
3 | import glm_.f
4 | import glm_.func.cos
5 | import glm_.func.sin
6 | import glm_.glm
7 | import glm_.has
8 | import glm_.vec2.Vec2i
9 | import glm_.vec3.Vec3
10 | import gln.gl
11 | import gln.glClearColor
12 | import kool.floatBufferOf
13 | import org.lwjgl.glfw.GLFW
14 | import org.lwjgl.opengl.GL11
15 | import uno.gl.GlWindow
16 | import uno.glfw.*
17 | import kotlin.math.sqrt
18 |
19 | /* program entry */
20 | fun main() {
21 |
22 | glfw {
23 | init(installDefaultErrorCB = true)
24 |
25 | hints {
26 | framebuffer.depthBits = 16
27 | window.transparentFramebuffer = true
28 | println(context.version)
29 | }
30 | }
31 |
32 | val glfwWindow = GlfwWindow(300, "Gears")
33 | val window = GlWindow(glfwWindow, forwardCompatible = false)
34 |
35 | // Set callback functions
36 | window.framebufferSizeCB = ::reshape
37 | window.keyCB = ::key
38 |
39 | window.makeCurrent()
40 | // gladLoadGL(glfwGetProcAddress) -> in GlWindow::caps
41 | glfw.swapInterval = VSync.ON
42 |
43 | val size = window.framebufferSize
44 | reshape(window, size)
45 |
46 | // Parse command-line options
47 | init()
48 |
49 | // Main loop
50 | window.loop {
51 | // Draw gears
52 | draw()
53 |
54 | // Update animation
55 | animate()
56 | }
57 |
58 | // Terminate GLFW
59 | glfw.terminate()
60 | }
61 |
62 | var viewRot = Vec3(20f, 30f, 0f)
63 | var gear1 = 0
64 | var gear2 = 0
65 | var gear3 = 0
66 | var angle = 0f
67 |
68 | val pos = floatBufferOf(5f, 5f, 10f, 0f)
69 | val red = floatBufferOf(0.8f, 0.1f, 0f, 1f)
70 | val green = floatBufferOf(0f, 0.8f, 0.2f, 1f)
71 | val blue = floatBufferOf(0.2f, 0.2f, 1f, 1f)
72 |
73 | /* new window size */
74 | fun reshape(window: GlfwWindow, size: Vec2i) {
75 | val h = size.y.f / size.x
76 |
77 | val znear = 5.0
78 | val zfar = 30.0
79 | val xmax = znear * 0.5
80 |
81 | gl.viewport(size)
82 | GL11.glMatrixMode(GL11.GL_PROJECTION)
83 | GL11.glLoadIdentity()
84 | GL11.glFrustum(-xmax, xmax, -xmax * h, xmax * h, znear, zfar)
85 | GL11.glMatrixMode(GL11.GL_MODELVIEW)
86 | GL11.glLoadIdentity()
87 | GL11.glTranslatef(0f, 0f, -20f)
88 | }
89 |
90 | /* change view angle, exit upon ESC */
91 | fun key(window: GlfwWindow, k: Key, s: Int, action: InputAction, mods: Int) {
92 |
93 | if (action != InputAction.Press) return
94 |
95 | when (k) {
96 | Key.Z ->
97 | if (mods has GLFW.GLFW_MOD_SHIFT)
98 | viewRot.z -= 5f
99 | else
100 | viewRot.z += 5f
101 |
102 | Key.ESCAPE -> window.shouldClose = true
103 | Key.UP -> viewRot.x += 5f
104 | Key.DOWN -> viewRot.x -= 5f
105 | Key.LEFT -> viewRot.y += 5f
106 | Key.RIGHT -> viewRot.y -= 5f
107 | else -> {}
108 | }
109 | }
110 |
111 | /* program & OpenGL initialization */
112 | fun init() {
113 |
114 | GL11.glLightfv(GL11.GL_LIGHT0, GL11.GL_POSITION, pos)
115 | GL11.glEnable(GL11.GL_CULL_FACE)
116 | GL11.glEnable(GL11.GL_LIGHTING)
117 | GL11.glEnable(GL11.GL_LIGHT0)
118 | GL11.glEnable(GL11.GL_DEPTH_TEST)
119 |
120 | /* make the gears */
121 | gear1 = GL11.glGenLists(1)
122 | GL11.glNewList(gear1, GL11.GL_COMPILE)
123 | GL11.glMaterialfv(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, red)
124 | gear(1f, 4f, 1f, 20, 0.7f)
125 | GL11.glEndList()
126 |
127 | gear2 = GL11.glGenLists(1)
128 | GL11.glNewList(gear2, GL11.GL_COMPILE)
129 | GL11.glMaterialfv(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, green)
130 | gear(0.5f, 2f, 2f, 10, 0.7f)
131 | GL11.glEndList()
132 |
133 | gear3 = GL11.glGenLists(1)
134 | GL11.glNewList(gear3, GL11.GL_COMPILE)
135 | GL11.glMaterialfv(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, blue)
136 | gear(1.3f, 2f, 0.5f, 10, 0.7f)
137 | GL11.glEndList()
138 |
139 | GL11.glEnable(GL11.GL_NORMALIZE)
140 | }
141 |
142 | /**
143 |
144 | Draw a gear wheel. You'll probably want to call this function when
145 | building a display list since we do a lot of trig here.
146 |
147 | Input: inner_radius - radius of hole at center
148 | outer_radius - radius at center of teeth
149 | width - width of gear teeth - number of teeth
150 | tooth_depth - depth of tooth
151 |
152 | **/
153 | fun gear(innerRadius: Float, outerRadius: Float, width: Float, teeth: Int, toothDepth: Float) {
154 |
155 | val r0 = innerRadius
156 | val r1 = outerRadius - toothDepth / 2f
157 | val r2 = outerRadius + toothDepth / 2f
158 |
159 | var da = 2f * glm.πf / teeth / 4f
160 |
161 | GL11.glShadeModel(GL11.GL_FLAT)
162 |
163 | GL11.glNormal3f(0f, 0f, 1f)
164 |
165 | /* draw front face */
166 | GL11.glBegin(GL11.GL_QUAD_STRIP)
167 | for (i in 0..teeth) {
168 | val angle = i * 2f * glm.πf / teeth
169 | GL11.glVertex3f(r0 * angle.cos, r0 * angle.sin, width * 0.5f)
170 | GL11.glVertex3f(r1 * angle.cos, r1 * angle.sin, width * 0.5f)
171 | if (i < teeth) {
172 | GL11.glVertex3f(r0 * angle.cos, r0 * angle.sin, width * 0.5f)
173 | GL11.glVertex3f(r1 * (angle + 3 * da).cos, r1 * (angle + 3 * da).sin, width * 0.5f)
174 | }
175 | }
176 | GL11.glEnd()
177 |
178 | /* draw front sides of teeth */
179 | GL11.glBegin(GL11.GL_QUADS)
180 | da = 2f * glm.πf / teeth / 4f
181 | for (i in 0 until teeth) {
182 | val angle = i * 2f * glm.πf / teeth
183 |
184 | GL11.glVertex3f(r1 * angle.cos, r1 * angle.sin, width * 0.5f)
185 | GL11.glVertex3f(r2 * (angle + da).cos, r2 * (angle + da).sin, width * 0.5f)
186 | GL11.glVertex3f(r2 * (angle + 2 * da).cos, r2 * (angle + 2 * da).sin, width * 0.5f)
187 | GL11.glVertex3f(r1 * (angle + 3 * da).cos, r1 * (angle + 3 * da).sin, width * 0.5f)
188 | }
189 | GL11.glEnd()
190 |
191 | GL11.glNormal3f(0f, 0f, -1f)
192 |
193 | /* draw back face */
194 | GL11.glBegin(GL11.GL_QUAD_STRIP)
195 | for (i in 0..teeth) {
196 | val angle = i * 2f * glm.πf / teeth
197 | GL11.glVertex3f(r1 * angle.cos, r1 * angle.sin, -width * 0.5f)
198 | GL11.glVertex3f(r0 * angle.cos, r0 * angle.sin, -width * 0.5f)
199 | if (i < teeth) {
200 | GL11.glVertex3f(r1 * (angle + 3 * da).cos, r1 * (angle + 3 * da).sin, -width * 0.5f)
201 | GL11.glVertex3f(r0 * (angle).cos, r0 * angle.sin, -width * 0.5f)
202 | }
203 | }
204 | GL11.glEnd()
205 |
206 | /* draw back sides of teeth */
207 | GL11.glBegin(GL11.GL_QUADS)
208 | da = 2f * glm.πf / teeth / 4f
209 | for (i in 0 until teeth) {
210 | val angle = i * 2f * glm.πf / teeth
211 |
212 | GL11.glVertex3f(r1 * (angle + 3 * da).cos, r1 * (angle + 3 * da).sin, -width * 0.5f)
213 | GL11.glVertex3f(r2 * (angle + 2 * da).cos, r2 * (angle + 2 * da).sin, -width * 0.5f)
214 | GL11.glVertex3f(r2 * (angle + da).cos, r2 * (angle + da).sin, -width * 0.5f)
215 | GL11.glVertex3f(r1 * angle.cos, r1 * angle.sin, -width * 0.5f)
216 | }
217 | GL11.glEnd()
218 |
219 | /* draw outward faces of teeth */
220 | GL11.glBegin(GL11.GL_QUAD_STRIP)
221 | for (i in 0 until teeth) {
222 | val angle = i * 2f * glm.πf / teeth
223 |
224 | GL11.glVertex3f(r1 * angle.cos, r1 * angle.sin, width * 0.5f)
225 | GL11.glVertex3f(r1 * angle.cos, r1 * angle.sin, -width * 0.5f)
226 | var u = r2 * (angle + da).cos - r1 * angle.cos
227 | var v = r2 * (angle + da).sin - r1 * angle.sin
228 | val len = sqrt(u * u + v * v)
229 | u /= len
230 | v /= len
231 | GL11.glNormal3f(v, -u, 0f)
232 | GL11.glVertex3f(r2 * (angle + da).cos, r2 * (angle + da).sin, width * 0.5f)
233 | GL11.glVertex3f(r2 * (angle + da).cos, r2 * (angle + da).sin, -width * 0.5f)
234 | GL11.glNormal3f(angle.cos, angle.sin, 0f)
235 | GL11.glVertex3f(r2 * (angle + 2 * da).cos, r2 * (angle + 2 * da).sin, width * 0.5f)
236 | GL11.glVertex3f(r2 * (angle + 2 * da).cos, r2 * (angle + 2 * da).sin, -width * 0.5f)
237 | u = r1 * (angle + 3 * da).cos - r2 * (angle + 2 * da).cos
238 | v = r1 * (angle + 3 * da).sin - r2 * (angle + 2 * da).sin
239 | GL11.glNormal3f(v, -u, 0f)
240 | GL11.glVertex3f(r1 * (angle + 3 * da).cos, r1 * (angle + 3 * da).sin, width * 0.5f)
241 | GL11.glVertex3f(r1 * (angle + 3 * da).cos, r1 * (angle + 3 * da).sin, -width * 0.5f)
242 | GL11.glNormal3f(angle.cos, angle.sin, 0f)
243 | }
244 |
245 | GL11.glVertex3f(r1 * 0f.cos, r1 * 0f.sin, width * 0.5f)
246 | GL11.glVertex3f(r1 * 0f.cos, r1 * 0f.sin, -width * 0.5f)
247 |
248 | GL11.glEnd()
249 |
250 | GL11.glShadeModel(GL11.GL_SMOOTH)
251 |
252 | /* draw inside radius cylinder */
253 | GL11.glBegin(GL11.GL_QUAD_STRIP)
254 | for (i in 0..teeth) {
255 | val angle = i * 2f * glm.πf / teeth
256 | GL11.glNormal3f(-angle.cos, -angle.sin, 0f)
257 | GL11.glVertex3f(r0 * angle.cos, r0 * angle.sin, -width * 0.5f)
258 | GL11.glVertex3f(r0 * angle.cos, r0 * angle.sin, width * 0.5f)
259 | }
260 | GL11.glEnd()
261 | }
262 |
263 | /* OpenGL draw function & timing */
264 | fun draw() {
265 |
266 | glClearColor(0f)
267 | GL11.glClear(GL11.GL_COLOR_BUFFER_BIT or GL11.GL_DEPTH_BUFFER_BIT)
268 |
269 | GL11.glPushMatrix()
270 | GL11.glRotatef(viewRot.x, 1f, 0f, 0f)
271 | GL11.glRotatef(viewRot.y, 0f, 1f, 0f)
272 | GL11.glRotatef(viewRot.z, 0f, 0f, 1f)
273 |
274 | GL11.glPushMatrix()
275 | GL11.glTranslatef(-3f, -2f, 0f)
276 | GL11.glRotatef(angle, 0f, 0f, 1f)
277 | GL11.glCallList(gear1)
278 | GL11.glPopMatrix()
279 |
280 | GL11.glPushMatrix()
281 | GL11.glTranslatef(3.1f, -2f, 0f)
282 | GL11.glRotatef(-2f * angle - 9f, 0f, 0f, 1f)
283 | GL11.glCallList(gear2)
284 | GL11.glPopMatrix()
285 |
286 | GL11.glPushMatrix()
287 | GL11.glTranslatef(-3.1f, 4.2f, 0f)
288 | GL11.glRotatef(-2f * angle - 25f, 0f, 0f, 1f)
289 | GL11.glCallList(gear3)
290 | GL11.glPopMatrix()
291 |
292 | GL11.glPopMatrix()
293 | }
294 |
295 | /* update animation parameters */
296 | fun animate() {
297 | angle = 100f * glfw.time.f
298 | }
--------------------------------------------------------------------------------
/awt/src/main/kotlin/uno/awt/LwjglCanvas.kt:
--------------------------------------------------------------------------------
1 | package uno.awt
2 |
3 | import glm_.vec2.Vec2i
4 | import org.lwjgl.glfw.GLFWErrorCallback
5 | import org.lwjgl.opengl.GLUtil
6 | import org.lwjgl.system.Callback
7 | import org.lwjgl.system.jawt.JAWTDrawingSurface
8 | import org.lwjgl.system.jawt.JAWTFunctions
9 | import uno.gl.GlWindow
10 | import uno.glfw.GlfwWindow
11 | import uno.glfw.VSync
12 | import uno.glfw.glfw
13 | import uno.kotlin.HWND
14 | import java.awt.Canvas
15 | import java.awt.EventQueue
16 | import java.awt.Graphics
17 | import java.awt.event.ComponentAdapter
18 | import java.awt.event.ComponentEvent
19 |
20 |
21 | /**
22 | * A Canvas component that uses OpenGL for rendering.
23 | *
24 | * Spasi: GLFW saves the AWT window proc somewhere and replaces it with its own on `glfwAttachWin32Window`.
25 | * It restores it back when the GLFW window is destroyed.
26 | * The difference between key and mouse events is that for key events the GLFW window proc returns `DefWindowProcW(...)`,
27 | * but for mouse events it returns 0, so the events do not propagate to AWT
28 | *
29 | * This implementation supports Windows only.
30 | */
31 | abstract class LwjglCanvas(val glDebug: Boolean = false) : Canvas() {
32 |
33 | val awt = JAWT()
34 |
35 | lateinit var glWindow: GlWindow
36 |
37 | var swapBuffers = true
38 | var fps = true
39 |
40 | var debugProc: Callback? = null
41 |
42 | var awtDebug = false
43 |
44 | val glfwErrorCallback = GLFWErrorCallback.createPrint().set()
45 |
46 | init {
47 | glfw {
48 | init()
49 | hints.context.debug = glDebug
50 | }
51 | }
52 |
53 | private fun initInternal(hwnd: HWND) {
54 | // println("LwjglCanvas.initInternal ${Date().toInstant()}")
55 |
56 | initialized = true
57 |
58 | // glfwWindowHint can be used here to configure the GL context
59 | val glfwWindow = GlfwWindow fromWin32Window hwnd
60 | glWindow = GlWindow(glfwWindow, forwardCompatible = false).apply {
61 | makeCurrent()
62 | }
63 |
64 | if (glDebug)
65 | debugProc = GLUtil.setupDebugMessageCallback()
66 |
67 | glfw.swapInterval = VSync.OFF
68 |
69 | init()
70 |
71 | glWindow.makeCurrent(false)
72 |
73 | // println("/LwjglCanvas.initInternal ${Date().toInstant()}")
74 | }
75 |
76 | var initialized = false
77 | var resized = false
78 | var animated = true
79 |
80 | // lateinit var caps: Caps
81 |
82 | // According to jawt.h > This value may be cached
83 | lateinit var surface: JAWTDrawingSurface
84 |
85 | init {
86 |
87 | if (!awt.get())
88 | throw IllegalStateException("GetAWT failed")
89 |
90 | // this avoids to calling the super method
91 | this.addComponentListener(object : ComponentAdapter() {
92 | override fun componentResized(e: ComponentEvent?) {
93 | // println("resized")
94 | resized = true
95 | }
96 | // Not working
97 | // override fun componentHidden(e: ComponentEvent?) {
98 | // println("hidden")
99 | // }
100 | //
101 | // override fun componentMoved(e: ComponentEvent?) {
102 | // println("moved")
103 | // }
104 | //
105 | // override fun componentShown(e: ComponentEvent?) {
106 | // println("shown")
107 | // }
108 | })
109 |
110 | if (EventQueue.isDispatchThread())
111 | surface = awt.getDrawingSurface(this)!!
112 | else EventQueue.invokeAndWait {
113 | surface = awt.getDrawingSurface(this)!!
114 | }
115 | }
116 |
117 | /** critical, call paint without default g.clearRect, because it causes flickering */
118 | override fun update(g: Graphics) = paint(g)//.also { println("update") }
119 |
120 | var last = 0L
121 | var time = 0L
122 | var frames = 0
123 |
124 | override fun paint(g: Graphics) {
125 |
126 | if (awtDebug)
127 | println("paint start " + Thread.currentThread().name)
128 |
129 | // Lock the drawing surface
130 | if (surface.lock() == JawtLock.ERROR)
131 | throw IllegalStateException("ds->Lock() failed")
132 |
133 | wrapped { hwnd ->
134 |
135 | if (!initialized)
136 | initInternal(hwnd)
137 |
138 | glWindow.withinContext {
139 |
140 | if (resized) {
141 | // println("LwjglCanvas.reshape ${Date().toInstant()}")
142 | val newSize = Vec2i(width, height)
143 | glWindow.size = newSize
144 | reshape(newSize)
145 | resized = false
146 | // println("/LwjglCanvas.reshape ${Date().toInstant()}")
147 | }
148 |
149 | // println("LwjglCanvas.render ${Date().toInstant()}")
150 | if (awtDebug)
151 | println("paint before render ")
152 |
153 | render()
154 |
155 | // println("/LwjglCanvas.render ${Date().toInstant()}")
156 | if (awtDebug)
157 | println("paint end")
158 |
159 | if (swapBuffers)
160 | glWindow.swapBuffers()
161 |
162 | if (fps) {
163 | val now = System.currentTimeMillis()
164 | time += now - last
165 | last = now
166 | frames++
167 | if (time > 1000) {
168 | time %= 1000
169 | if (awtDebug) println("fps = $frames")
170 | frames = 0
171 | }
172 | }
173 | }
174 | }
175 |
176 | if (animated)
177 | repaint()
178 | }
179 |
180 | /*override fun paint(g: Graphics) {
181 | if (awtDebug) {
182 | println("paint start " + Thread.currentThread().name)
183 | }
184 |
185 | // Lock the drawing surface
186 | val lock = JAWT_DrawingSurface_Lock(surface, surface.Lock())
187 | if (lock has JAWT_LOCK_ERROR)
188 | throw IllegalStateException("ds->Lock() failed")
189 |
190 | try {
191 | // Get the drawing surface info
192 | val dsi = JAWT_DrawingSurface_GetDrawingSurfaceInfo(surface, surface.GetDrawingSurfaceInfo())
193 | ?: throw IllegalStateException("ds->GetDrawingSurfaceInfo() failed")
194 |
195 | try {
196 | // Get the window platform drawing info
197 | val surfaceInfo = JAWTWin32DrawingSurfaceInfo.create(dsi.platformInfo())
198 |
199 | val hdc = surfaceInfo.hdc()
200 | assert(hdc != NULL)
201 |
202 | if (!initialized)
203 | initInternal(HWND(surfaceInfo.hwnd()))
204 |
205 | glfwWindow.makeContextCurrent()
206 |
207 | if (resized) {
208 | // println("LwjglCanvas.reshape ${Date().toInstant()}")
209 | val newSize = Vec2i(width, height)
210 | glfwWindow.size = newSize
211 | reshape(newSize)
212 | resized = false
213 | // println("/LwjglCanvas.reshape ${Date().toInstant()}")
214 | }
215 |
216 | // println("LwjglCanvas.render ${Date().toInstant()}")
217 | if (awtDebug) {
218 | println("paint before render ")
219 | }
220 | render()
221 | // println("/LwjglCanvas.render ${Date().toInstant()}")
222 |
223 | if (swapBuffers)
224 | glfwWindow.swapBuffers()
225 |
226 | if (fps) {
227 | val now = System.currentTimeMillis()
228 | time += now - last
229 | last = now
230 | frames++
231 | if (time > 1000) {
232 | time %= 1000
233 | println("fps = $frames")
234 | frames = 0
235 | }
236 | }
237 |
238 | glfwWindow.unmakeContextCurrent()
239 |
240 | } finally {
241 | // Free the drawing surface info
242 | JAWT_DrawingSurface_FreeDrawingSurfaceInfo(dsi, surface.FreeDrawingSurfaceInfo())
243 | }
244 | } finally {
245 | // Unlock the drawing surface
246 | JAWT_DrawingSurface_Unlock(surface, surface.Unlock())
247 | }
248 |
249 | if (awtDebug) {
250 | println("paint end")
251 | }
252 |
253 | if (animated)
254 | repaint()
255 | }*/
256 |
257 | inline fun wrapped(block: (HWND) -> Unit) {
258 |
259 | try {
260 | // Get the drawing surface info
261 | val dsi = surface.info ?: throw IllegalStateException("ds->GetDrawingSurfaceInfo() failed")
262 |
263 | try {
264 | // Get the window platform drawing info
265 | val surfaceInfo = JAWTWin32DrawingSurfaceInfo(dsi)
266 |
267 | val hdc = surfaceInfo.hdc
268 | assert(hdc.isValid)
269 |
270 | block(surfaceInfo.hwnd)
271 |
272 | } finally {
273 | // Free the drawing surface info
274 | surface free dsi
275 | }
276 | } finally {
277 | // Unlock the drawing surface
278 | surface.unlock()
279 | }
280 | }
281 |
282 | fun destroyInternal() {
283 | if (awtDebug) println("destroyInternal")
284 |
285 | // glWindow.inContext {
286 | // destroy()
287 | // debugProc?.free()
288 | // }
289 |
290 | JAWTFunctions.JAWT_FreeDrawingSurface(surface, awt.FreeDrawingSurface())
291 | awt.free()
292 |
293 | glWindow.destroy()
294 | glfw.terminate()
295 | glfwErrorCallback.free()
296 | }
297 |
298 | fun toggleAnimation() {
299 | if (animated)
300 | animated = false
301 | else {
302 | animated = true
303 | repaint()
304 | }
305 | }
306 |
307 | @JvmOverloads
308 | fun animate(animate: Boolean = true) {
309 |
310 | if (animated != animate) {
311 |
312 | animated = animate
313 |
314 | if (animate)
315 | graphics?.let { g ->
316 | if (EventQueue.isDispatchThread()) {
317 | paint(g)
318 | g.dispose()
319 | } else EventQueue.invokeAndWait {
320 | paint(g)
321 | g.dispose()
322 | }
323 | }
324 | }
325 | }
326 |
327 | // public methods to overwrite in application
328 |
329 | abstract fun init()
330 | abstract fun reshape(size: Vec2i)
331 | abstract fun render()
332 | abstract fun destroy()
333 | }
--------------------------------------------------------------------------------
/core/src/main/kotlin/uno/glfw/Hints.kt:
--------------------------------------------------------------------------------
1 | package uno.glfw
2 |
3 | import glm_.i
4 | import org.lwjgl.glfw.GLFW.*
5 |
6 | class Hints {
7 |
8 | // Window related hints
9 |
10 | val window = Window()
11 |
12 | fun window(block: Window.() -> Unit) = window.block()
13 |
14 | class Window {
15 |
16 | var resizable = true
17 | set(value) {
18 | glfwWindowHint(GLFW_RESIZABLE, value.i)
19 | field = value
20 | }
21 |
22 | var visible = true
23 | set(value) {
24 | glfwWindowHint(GLFW_VISIBLE, value.i)
25 | field = value
26 | }
27 |
28 | var decorated = true
29 | set(value) {
30 | glfwWindowHint(GLFW_DECORATED, value.i)
31 | field = value
32 | }
33 |
34 | var focused = true
35 | set(value) {
36 | glfwWindowHint(GLFW_FOCUSED, value.i)
37 | field = value
38 | }
39 |
40 | var autoIconify = true
41 | set(value) {
42 | glfwWindowHint(GLFW_AUTO_ICONIFY, value.i)
43 | field = value
44 | }
45 |
46 | var floating = false
47 | set(value) {
48 | glfwWindowHint(GLFW_FLOATING, value.i)
49 | field = value
50 | }
51 |
52 | var maximized = false
53 | set(value) {
54 | glfwWindowHint(GLFW_MAXIMIZED, value.i)
55 | field = value
56 | }
57 |
58 | var centerCursor = true
59 | set(value) {
60 | glfwWindowHint(GLFW_CENTER_CURSOR, value.i)
61 | field = value
62 | }
63 |
64 | var transparentFramebuffer = false
65 | set(value) {
66 | glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, value.i)
67 | field = value
68 | }
69 |
70 | var focusOnShow = true
71 | set(value) {
72 | glfwWindowHint(GLFW_FOCUS_ON_SHOW, value.i)
73 | field = value
74 | }
75 |
76 | var scaleToMonitor = false
77 | set(value) {
78 | glfwWindowHint(GLFW_SCALE_TO_MONITOR, value.i)
79 | field = value
80 | }
81 |
82 | var mousePassthrough = false
83 | set(value) {
84 | glfwWindowHint(GLFW_MOUSE_PASSTHROUGH, value.i)
85 | field = value
86 | }
87 | }
88 |
89 | // Framebuffer related hints
90 |
91 | val framebuffer = Framebuffer()
92 |
93 | fun framebuffer(block: Framebuffer.() -> Unit) = framebuffer.block()
94 | class Framebuffer {
95 |
96 | var redBits = 8
97 | set(value) {
98 | glfwWindowHint(GLFW_RED_BITS, value)
99 | field = value
100 | }
101 |
102 | var greenBits = 8
103 | set(value) {
104 | glfwWindowHint(GLFW_GREEN_BITS, value)
105 | field = value
106 | }
107 |
108 | var blueBits = 8
109 | set(value) {
110 | glfwWindowHint(GLFW_BLUE_BITS, value)
111 | field = value
112 | }
113 |
114 | var alphaBits = 8
115 | set(value) {
116 | glfwWindowHint(GLFW_ALPHA_BITS, value)
117 | field = value
118 | }
119 |
120 | var depthBits = 24
121 | set(value) {
122 | glfwWindowHint(GLFW_DEPTH_BITS, value)
123 | field = value
124 | }
125 |
126 | var stencilBits = 8
127 | set(value) {
128 | glfwWindowHint(GLFW_STENCIL_BITS, value)
129 | field = value
130 | }
131 |
132 | var accumRedBits = 0
133 | set(value) {
134 | glfwWindowHint(GLFW_ACCUM_RED_BITS, value)
135 | field = value
136 | }
137 |
138 | var accumGreenBits = 0
139 | set(value) {
140 | glfwWindowHint(GLFW_ACCUM_GREEN_BITS, value)
141 | field = value
142 | }
143 |
144 | var accumBlueBits = 0
145 | set(value) {
146 | glfwWindowHint(GLFW_ACCUM_BLUE_BITS, value)
147 | field = value
148 | }
149 |
150 | var accumAlphaBits = 0
151 | set(value) {
152 | glfwWindowHint(GLFW_ACCUM_ALPHA_BITS, value)
153 | field = value
154 | }
155 |
156 | var auxBuffers = 0
157 | set(value) {
158 | glfwWindowHint(GLFW_AUX_BUFFERS, value)
159 | field = value
160 | }
161 |
162 | var stereo = false
163 | set(value) {
164 | glfwWindowHint(GLFW_STEREO, value.i)
165 | field = value
166 | }
167 |
168 | var samples = 0
169 | set(value) {
170 | glfwWindowHint(GLFW_SAMPLES, value)
171 | field = value
172 | }
173 |
174 | var srgb = false
175 | set(value) {
176 | glfwWindowHint(GLFW_SRGB_CAPABLE, value.i)
177 | field = value
178 | }
179 |
180 | var doubleBuffer = true
181 | set(value) {
182 | glfwWindowHint(GLFW_DOUBLEBUFFER, value.i)
183 | field = value
184 | }
185 | }
186 |
187 | // Monitor related hints
188 |
189 | val monitor = Monitor()
190 |
191 | fun monitor(block: Monitor.() -> Unit) = monitor.block()
192 | class Monitor {
193 | var refreshRate = GLFW_DONT_CARE
194 | set(value) {
195 | glfwWindowHint(GLFW_REFRESH_RATE, value)
196 | field = value
197 | }
198 | }
199 |
200 | // Context related hints
201 | val context = Context()
202 |
203 | fun context(block: Context.() -> Unit) = context.block()
204 |
205 | class Context {
206 |
207 | enum class ClientApi { Gl, GlEs, None }
208 |
209 | var clientApi = ClientApi.Gl
210 | set(value) {
211 | glfwWindowHint(GLFW_CLIENT_API, when (value) {
212 | ClientApi.Gl -> GLFW_OPENGL_API
213 | ClientApi.GlEs -> GLFW_OPENGL_ES_API
214 | ClientApi.None -> GLFW_NO_API
215 | })
216 | field = value
217 | }
218 |
219 | enum class CreationApi { Native, Egl, OsMesa }
220 |
221 | var creationApi = CreationApi.Native
222 | set(value) {
223 | glfwWindowHint(GLFW_CONTEXT_CREATION_API, when (value) {
224 | CreationApi.Native -> GLFW_NATIVE_CONTEXT_API
225 | CreationApi.Egl -> GLFW_EGL_CONTEXT_API
226 | CreationApi.OsMesa -> GLFW_OSMESA_CONTEXT_API
227 | })
228 | field = value
229 | }
230 |
231 | var version = "1.0"
232 | set(value) {
233 | check(value.length == 3 && value[0].isDigit() && value[1] == '.' && value[2].isDigit())
234 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, Integer.parseInt(value[0].toString()))
235 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, Integer.parseInt(value[2].toString()))
236 | field = value
237 | }
238 |
239 | var major = 1
240 | set(value) {
241 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, value)
242 | field = value
243 | }
244 |
245 | var minor = 0
246 | set(value) {
247 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, value)
248 | field = value
249 | }
250 |
251 | var forwardComp = false
252 | set(value) {
253 | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, value.i)
254 | field = value
255 | }
256 |
257 | var debug = false
258 | set(value) {
259 | glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, value.i)
260 | field = value
261 | }
262 |
263 | enum class Profile { Any, Compat, Core }
264 |
265 | var profile = Profile.Any
266 | set(value) {
267 | glfwWindowHint(GLFW_OPENGL_PROFILE, when (value) {
268 | Profile.Core -> GLFW_OPENGL_CORE_PROFILE
269 | Profile.Compat -> GLFW_OPENGL_COMPAT_PROFILE
270 | Profile.Any -> GLFW_OPENGL_ANY_PROFILE
271 | })
272 | field = value
273 | }
274 |
275 | enum class Robustness { NoResetNotification, LoseContextOnReset, None }
276 |
277 | var robustness = Robustness.None
278 | set(value) {
279 | glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS, when (value) {
280 | Robustness.None -> GLFW_NO_ROBUSTNESS
281 | Robustness.NoResetNotification -> GLFW_NO_RESET_NOTIFICATION
282 | Robustness.LoseContextOnReset -> GLFW_LOSE_CONTEXT_ON_RESET
283 | })
284 | field = value
285 | }
286 |
287 | enum class ReleaseBehaviour { Any, Flush, None }
288 |
289 | var releaseBehaviour = ReleaseBehaviour.Any
290 | set(value) {
291 | glfwWindowHint(GLFW_CONTEXT_RELEASE_BEHAVIOR, when (value) {
292 | ReleaseBehaviour.Any -> GLFW_ANY_RELEASE_BEHAVIOR
293 | ReleaseBehaviour.Flush -> GLFW_RELEASE_BEHAVIOR_FLUSH
294 | ReleaseBehaviour.None -> GLFW_RELEASE_BEHAVIOR_NONE
295 | })
296 | field = value
297 | }
298 |
299 | var noError = false
300 | set(value) {
301 | glfwWindowHint(GLFW_CONTEXT_NO_ERROR, value.i)
302 | field = value
303 | }
304 | }
305 |
306 | // macOS specific window hints
307 | val cocoa = Cocoa()
308 |
309 | fun cocoa(block: Cocoa.() -> Unit) = cocoa.block()
310 |
311 | class Cocoa {
312 |
313 | var retinaFramebuffer = true
314 | set(value) {
315 | glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, value.i)
316 | field = value
317 | }
318 |
319 | var frameName = ""
320 | set(value) {
321 | glfwWindowHintString(GLFW_COCOA_FRAME_NAME, value)
322 | field = value
323 | }
324 |
325 | var graphicsSwitching = false
326 | set(value) {
327 | glfwWindowHint(GLFW_COCOA_GRAPHICS_SWITCHING, value.i)
328 | field = value
329 | }
330 | }
331 |
332 | // X11 specific window hints
333 | val x11 = X11()
334 |
335 | fun x11(block: X11.() -> Unit) = x11.block()
336 |
337 | class X11 {
338 |
339 | var className = ""
340 | set(value) {
341 | glfwWindowHintString(GLFW_X11_CLASS_NAME, value)
342 | field = value
343 | }
344 |
345 | var instanceName = ""
346 | set(value) {
347 | glfwWindowHintString(GLFW_X11_INSTANCE_NAME, value)
348 | field = value
349 | }
350 | }
351 | }
352 |
--------------------------------------------------------------------------------
/awt/src/test/kotlin/uno/jawt/LWJGLCanvas.java:
--------------------------------------------------------------------------------
1 | package uno.jawt;
2 |
3 | import org.lwjgl.*;
4 | import org.lwjgl.opengl.*;
5 | import org.lwjgl.system.*;
6 | import org.lwjgl.system.jawt.JAWT;
7 | import org.lwjgl.system.jawt.*;
8 | import org.lwjgl.system.linux.*;
9 | import uno.jawt.AbstractGears;
10 |
11 | import java.awt.*;
12 | import java.awt.event.*;
13 | import java.nio.*;
14 | import java.util.*;
15 |
16 | import static org.lwjgl.glfw.GLFW.*;
17 | import static org.lwjgl.glfw.GLFWNativeWin32.*;
18 | import static org.lwjgl.opengl.GL11.*;
19 | import static org.lwjgl.opengl.GLX13.*;
20 | import static org.lwjgl.system.MemoryStack.*;
21 | import static org.lwjgl.system.MemoryUtil.*;
22 | import static org.lwjgl.system.jawt.JAWTFunctions.*;
23 |
24 | /**
25 | * A Canvas component that uses OpenGL for rendering.
26 | *
27 | * This implementation supports Windows only.
28 | */
29 | @SuppressWarnings("serial")
30 | public class LWJGLCanvas extends Canvas {
31 |
32 | private final JAWT awt;
33 |
34 | private JAWTDrawingSurface ds;
35 |
36 | private final AbstractGears gears;
37 |
38 | private long context;
39 |
40 | private GLCapabilities caps;
41 |
42 | public LWJGLCanvas() {
43 | awt = JAWT.calloc();
44 | awt.version(JAWT_VERSION_1_4);
45 | if (!JAWT_GetAWT(awt)) {
46 | throw new IllegalStateException("GetAWT failed");
47 | }
48 |
49 | gears = new AbstractGears();
50 |
51 | // AWT event listeners are invoked in the EDT
52 |
53 | addComponentListener(new ComponentAdapter() {
54 | @Override public void componentResized(ComponentEvent e) {
55 | System.out.println(e);
56 | if (context != NULL) {
57 | paint();
58 | }
59 | }
60 | @Override public void componentMoved(ComponentEvent e) {
61 | System.out.println(e);
62 | }
63 | @Override public void componentShown(ComponentEvent e) {
64 | System.out.println(e);
65 | }
66 | @Override public void componentHidden(ComponentEvent e) {
67 | System.out.println(e);
68 | }
69 | });
70 | addFocusListener(new FocusListener() {
71 | @Override public void focusGained(FocusEvent e) {
72 | System.out.println(e);
73 | }
74 | @Override public void focusLost(FocusEvent e) {
75 | System.out.println(e);
76 | }
77 | });
78 | addKeyListener(new KeyAdapter() {
79 | @Override public void keyPressed(KeyEvent e) {
80 | System.out.println(e);
81 | }
82 | @Override public void keyTyped(KeyEvent e) {
83 | System.out.println(e);
84 | }
85 | @Override public void keyReleased(KeyEvent e) {
86 | System.out.println(e);
87 | }
88 | });
89 | addMouseListener(new MouseAdapter() {
90 | @Override public void mouseClicked(MouseEvent e) {
91 | System.out.println(e);
92 | }
93 | @Override public void mousePressed(MouseEvent e) {
94 | System.out.println(e);
95 | }
96 | @Override public void mouseReleased(MouseEvent e) {
97 | System.out.println(e);
98 | }
99 | @Override public void mouseEntered(MouseEvent e) {
100 | System.out.println(e);
101 | }
102 | @Override public void mouseExited(MouseEvent e) {
103 | System.out.println(e);
104 | }
105 | @Override public void mouseWheelMoved(MouseWheelEvent e) {
106 | System.out.println(e);
107 | }
108 | @Override public void mouseDragged(MouseEvent e) {
109 | System.out.println(e);
110 | }
111 | @Override public void mouseMoved(MouseEvent e) {
112 | System.out.println(e);
113 | }
114 | });
115 | addMouseMotionListener(new MouseMotionListener() {
116 | @Override public void mouseDragged(MouseEvent e) {
117 | System.out.println(e);
118 | }
119 | @Override public void mouseMoved(MouseEvent e) {
120 | System.out.println(e);
121 | }
122 | });
123 | addMouseWheelListener(System.out::println);
124 | }
125 |
126 | @Override
127 | public void update(Graphics g) {
128 | paint(g);
129 | }
130 |
131 | @Override
132 | public void paint(Graphics g) {
133 | paint();
134 | // repaint();
135 | }
136 |
137 | private void paint() {
138 | if (ds == null) {
139 | // Get the drawing surface
140 | ds = JAWT_GetDrawingSurface(this, awt.GetDrawingSurface());
141 | if (ds == null) {
142 | throw new IllegalStateException("awt->GetDrawingSurface() failed");
143 | }
144 | }
145 |
146 | // Lock the drawing surface
147 | int lock = JAWT_DrawingSurface_Lock(ds, ds.Lock());
148 | if ((lock & JAWT_LOCK_ERROR) != 0) {
149 | throw new IllegalStateException("ds->Lock() failed");
150 | }
151 |
152 | try {
153 | // Get the drawing surface info
154 | JAWTDrawingSurfaceInfo dsi = JAWT_DrawingSurface_GetDrawingSurfaceInfo(ds, ds.GetDrawingSurfaceInfo());
155 | if (dsi == null) {
156 | throw new IllegalStateException("ds->GetDrawingSurfaceInfo() failed");
157 | }
158 |
159 | try {
160 | switch (Platform.get()) {
161 | case LINUX:
162 | // Get the platform-specific drawing info
163 | JAWTX11DrawingSurfaceInfo dsi_x11 = JAWTX11DrawingSurfaceInfo.create(dsi.platformInfo());
164 |
165 | long drawable = dsi_x11.drawable();
166 | if (drawable == NULL) {
167 | break;
168 | }
169 |
170 | if (context == NULL) {
171 | createContextGLX(dsi_x11);
172 | gears.init();
173 | } else {
174 | if (!glXMakeCurrent(dsi_x11.display(), drawable, context)) {
175 | throw new IllegalStateException("glXMakeCurrent() failed");
176 | }
177 | GL.setCapabilities(caps);
178 | }
179 |
180 | render(getWidth(), getHeight());
181 | glXSwapBuffers(dsi_x11.display(), drawable);
182 |
183 | glXMakeCurrent(dsi_x11.display(), NULL, NULL);
184 | GL.setCapabilities(null);
185 | break;
186 | case WINDOWS:
187 | // Get the platform-specific drawing info
188 | JAWTWin32DrawingSurfaceInfo dsi_win = JAWTWin32DrawingSurfaceInfo.create(dsi.platformInfo());
189 |
190 | long hdc = dsi_win.hdc();
191 | if (hdc == NULL) {
192 | break;
193 | }
194 |
195 | // The render method is invoked in the EDT
196 | if (context == NULL) {
197 | createContextGLFW(dsi_win);
198 | gears.init();
199 | } else {
200 | glfwMakeContextCurrent(context);
201 | GL.setCapabilities(caps);
202 | }
203 |
204 | try (MemoryStack stack = stackPush()) {
205 | IntBuffer pw = stack.mallocInt(1);
206 | IntBuffer ph = stack.mallocInt(1);
207 |
208 | glfwGetFramebufferSize(context, pw, ph);
209 |
210 | render(pw.get(0), ph.get(0));
211 | }
212 | glfwSwapBuffers(context);
213 |
214 | glfwMakeContextCurrent(NULL);
215 | GL.setCapabilities(null);
216 | break;
217 | }
218 | } finally {
219 | // Free the drawing surface info
220 | JAWT_DrawingSurface_FreeDrawingSurfaceInfo(dsi, ds.FreeDrawingSurfaceInfo());
221 | }
222 | } finally {
223 | // Unlock the drawing surface
224 | JAWT_DrawingSurface_Unlock(ds, ds.Unlock());
225 | }
226 | }
227 |
228 | private void render(int width, int height) {
229 | glViewport(0, 0, width, height);
230 |
231 | float f = height / (float)width;
232 |
233 | glMatrixMode(GL_PROJECTION);
234 | glLoadIdentity();
235 | glFrustum(-1.0f, 1.0f, -f, f, 5.0f, 100.0f);
236 | glMatrixMode(GL_MODELVIEW);
237 |
238 | gears.render();
239 | }
240 |
241 | private void createContextGLFW(JAWTWin32DrawingSurfaceInfo dsi_win) {
242 | // glfwWindowHint can be used here to configure the GL context
243 | context = glfwAttachWin32Window(dsi_win.hwnd(), NULL);
244 | if (context == NULL) {
245 | throw new IllegalStateException("Failed to attach win32 window.");
246 | }
247 |
248 | // Any callbacks registered here will work. But care must be taken because
249 | // the callbacks are NOT invoked in the EDT, but in an AWT thread that
250 | // does the event polling. Many GLFW functions that require main thread
251 | // invocation, should only be called in that thread.
252 |
253 | // Because of how input focus is implemented in AWT, it is recommended that AWT
254 | // KeyListeners are always used for keyboard input.
255 |
256 | glfwMakeContextCurrent(context);
257 | caps = GL.createCapabilities();
258 | }
259 |
260 | // Simplest possible context creation.
261 | private void createContextGLX(JAWTX11DrawingSurfaceInfo dsi_x11) {
262 | long display = dsi_x11.display();
263 | long drawable = dsi_x11.drawable();
264 |
265 | PointerBuffer configs = Objects.requireNonNull(glXChooseFBConfig(display, 0, (IntBuffer)null));
266 |
267 | long config = NULL;
268 | for (int i = 0; i < configs.remaining(); i++) {
269 | XVisualInfo vi = Objects.requireNonNull(glXGetVisualFromFBConfig(display, configs.get(i)));
270 | if (vi.visualid() == dsi_x11.visualID()) {
271 | config = configs.get(i);
272 | break;
273 | }
274 | }
275 |
276 | context = glXCreateNewContext(display, config, GLX_RGBA_TYPE, NULL, true);
277 | if (context == NULL) {
278 | throw new IllegalStateException("glXCreateContext() failed");
279 | }
280 |
281 | if (!glXMakeCurrent(display, drawable, context)) {
282 | throw new IllegalStateException("glXMakeCurrent() failed");
283 | }
284 |
285 | caps = GL.createCapabilities();
286 | }
287 |
288 | public void destroy() {
289 | // Free the drawing surface
290 | JAWT_FreeDrawingSurface(ds, awt.FreeDrawingSurface());
291 |
292 | awt.free();
293 |
294 | if (context != NULL) {
295 | glfwDestroyWindow(context);
296 | }
297 | }
298 |
299 | }
--------------------------------------------------------------------------------
/core/src/test/resources/main/proggyClean_compressedBase85:
--------------------------------------------------------------------------------
1 | 7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/2*>]b(MC;$jPfY.;h^`IWM9Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1=Ke$$'5F%)]0^#0X@U.a$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_w+F%HtG9M#XL`
3 | N&.,GM4Pg;--VsM.M0rJfLH2eTM`*oJMHRC`NkfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`j@'DbG^$PG.Ll+DNa&VZ>1i%h1S9u5o@YaaW$e+bROPOpxTO7Stwi1::iB1q)C_=dV26
5 | J;2,]7op$]uQr@_V7$q^%lQwtuHY]=DX,n3L#0PHDO4f9>dC@O>HBuKPpP*E,N+b3L#lpR/MrTEH.IAQk.a>D[.e;mc.x]Ip.PH^'/aqUO/$1WxLoW0[iLAw=4h(9.`GCRUxHPeR`5Mjol(dUWxZa(>ST
6 | rPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?Ggv:[7MI2k).'2($5FNP&EQ(,)U]W]+fh18.vsai00);D3@4ku5P?DP8aJt+;qUM]=+b'8@;mViBKx0DE[-auGl8:PJ&Dj+M6OC]O^((##]`0i)drT;-7X`=-H3[igUnPG-NZlo.#k@h#=Ork$m>a>$-?Tm$UV(?#P6YY#'/
7 | ###xe7q.73rI3*pP/$1>s9)W,JrM7SN]'/4C#v$U`0#V.[0>xQsH$fEmPMgY2u7Kh(G%siIfLSoS+MK2eTM$=5,M8p`A.;_R%#u[K#$x4AG8.kK/HSB==-'Ie/QTtG?-.*^N-4B/ZM_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0+WomX2u7lqM2iEumMTcsF?-aT=Z
8 | -97UEnXglEn1K-bnEO`guFt(c%=;Am_Qs@jLooI&NX;]0#j4#F14;gl8-GQpgwhrq8'=l_f-b49'UOqkLu7-##oDY2L(te+Mch&gLYtJ,MEtJfLh'x'M=$CS-ZZ%P]8bZ>#S?YY#%Q&q'3^Fw&?D)UDNrocM3A76//oL?#h7gl85[qW/NDOk%16ij;+:1a'iNIdb-ou8.P*w,v5#EI$TWS>Pot-R*H'-SEpA:g)f+O$%%`kA#G=8RMmG1&O`>to8b
9 | C]T&$,n.LoO>29sp3dt-52U%VM#q7'DHpg+#Z9%H[Ket`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnOj%2n8)),?ILR5^.Ibn<-X-Mq7[a82Lq:Fce+S9wsCK*x`569E8ew'He]h:sI[2LM$[guka3ZRd6:t%IG:;$%YiJ:Nq=?eAw;/:nnDq0(CYcMpG)qLN4$##&J-XTt,%OVU4)S1+R-#dg0/Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$MhLbxfc$mj`,O;&%W2m`Zh:/)Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.
14 | *'&0D[Ca]J9gp8,kAW]%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(etHg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$'?;++O'>()jLR-^u68PH
15 | m8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>QWIo)0@F%q7c#4XAXN-U&VBpqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<-+k?'(^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3MD?@f&1'BW-)Ju#bmmWCMkkTR`C,5d>g)F;t,4:@_l8G/5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX(P?^@Po3$##`MSs?DWBZ/S>+4%>fX,VWv/w'KD`LP5IbH;rTV>n3cEK8U#bX]l-/V+^lj3;vlMb&[5YQ8#pekX9JP3XUC72L,,?+Ni&co7ApnO*5NK,((W-i:$,kp'UDAO(G0Sq7MVjJsbIu)'
19 | Z,*[>br5fX^:FPAWr-m2KgLQ_nN6'8uTGT5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Qh4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//,]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aege0jT6'
20 | N#(q%.O=?2S]u*(m<-V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCFB^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5isZ88+dKQ)W6>J%CL`.d*(B`-n8D9oK-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7
21 | ])$*$#@QYi9,5P r+$%CE=68>K8r0=dSC%%(@p7.m7jilQ02'0-VWAgTlGW'b)Tq7VT9q^*^$$.:&N@@$&)WHtPm*5_rO0&e%K-30j(E4#'Zb.o/(Tpm$>K'f@[PvFl,hfINTNU6u'0pao7%XUp9]5.>%h
22 | `8_=VYbxuel.NTSsJfLacFu3B'lQSu/m6-Oqem8T+oE--$0a/k]uj9EwsG>%veR*hv^BFpQj:K'#SJ,sB-'#](j.Lg92rTw-*n%@/;39rrJF,l#qV%OrtBeC6/,;qB3ebNW[?,Hqj2L.1NP&GjUR=1D8QaS3Up&@*9wP?+lo7b?@%'k4`p0Z$22%K3+iCZj?XJN4Nm&+YF]u@-W$U%VEQ/,,>>#)D#%8cY#YZ?=,`Wdxu/aew6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$s-aFRNQv>o8lKN%5/$(vdfq7+ebA#u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7
24 | mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(%:_i2B5CsR8&9Z=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoFDoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB86e%B/:=
25 | >)N4xeW.*wft-;$'58-ESqr#U`'6AQ]m&6/`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*cb0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/TQ:(Z^xBdLjL<
26 | Lni;''X.`$#8+1GD:k$YUWsbn8ogh6rxZ2Z9]%nd+>V#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hLSfD07&6D@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5_>@kXQtMacfD.m-VAb8;IReM3$wf0''hra*so568'Ip&vRs849'MRYSp%:t:h5qSgwpEr$B>Q,;s(C#$)`svQuF$##-D,##,g68@2[T;.XSdN9Qe)rpt._K-#5wF)sP'##p#C0c%-Gb%hd+<-j'Ai
31 | *x&&HMkT]C'OSl##5RG[JXaHN;d'uA#x._U;.`PU@(Z3dt4r152@:v,'R.Sj'w#0<-;kPI)FfJAYJ//)>-k=m=*XnK$>=)72L]0I%>.G690a:$##<,);?;72#?x9+d;^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmLq9wI>P(9mI[>kC-ekLC/R&CH+s'B
32 | ;K-M6$EB%is00:+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3$U4O]GKx'm9)b@p7YsvK3w^YR-CdQ*:Ir<($u&)#(&?L9Rg3H)4fiEp^iI9O8KnTj,]H?D*r7'M;PwZ9K0E^k&-cpI;.p/6_vwoFMV<->#%Xi.LxVnrU(4&8/P+:hLSKj$#U%]49t'I:rgMi'FL@a:0Y-uA[39',(vbma*hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdFTi1O*H(AL8[
34 | _P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IXSsDiWP,##P`%/L-S(qw%sf/@%#B6;/U7K]uZbi^Oc^2n%t<)'mEVE''n`WnJra
35 | $^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdFl*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/Coh58KKhLjM=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO$(>.Z-I&J(Q0Hd5Q%7Co-b`-cP)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8WlA2);Sa>gXm8YB`1d@K#n]76-a$U,mF%Ul:#/'xoFM9QX-$.QN'>[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`Peb#.3i)rtB61(o'$?X3B2Qft^ae_5tKL9MUe9b*sLEQ9
39 | 5C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@IwOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs
40 | ,eD9>XW8?N]o+(*pgC%/72LV-uW%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_KEBFkO'oU]^=[-792#ok,)i]lR8qQ2oA8wcRCZ^7w/Njh;?.stX?Q1>S1q4Bn$)K1<-rGdO'$Wr.Lc.CG
41 | )$/*JL4tNR/,SVO3,aUw'DJN:)Ss;wGn9A32ijw%FL+Z0Fn.U9;reSq)bmI32U==5ALuGVf1398/pVo1*c-(aY168o<`JsSbk-,1N;$>0:OUas(3:8Z972LSfF8eb=c-;>SPw7.6hn3m`9^Xkn(r.qS[0;T%&Qc=+STRxX'q1BNk3&*eu2;&8q$&x>Q#Q7^Tf+6<(d%ZVmj2bDi%.3L2n+4W'$PiDDG)g,r%+?,$@?uou5tSe2aN_AQU*'IAOURQ##V^Fv-XFbGM7Fl(N<3DhLGF%q.1rC$#:T__&Pi68%0xi_&[qFJ(77j_&JWoF.V735&T,[R*:xFR*K5>>#`bW-?4Ne_&6Ne_&6Ne_&n`kr-#GJcM6X;uM6X;uM(.a..^2TkL%oR(#;u.T%fAr%4tJ8
43 | &><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4Tw$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4A1OY5EI0;6Ibgr6M$HS7Q<)58C5w,;WoA*#[%T*#`1g*#d=#+#hI5+#lUG+#pbY+#tnl+#x$),#&1;,#*=M,#.I`,#2Ur,#6b.-#;w[H#iQ
45 | tA#m^0B#qjBB#uvTB##-hB#'9$C#+E6C#/QHC#3^ZC#7jmC#;v)D#?,)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5K
47 | TB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#
--------------------------------------------------------------------------------
/gl/src/test/kotlin/tests/Cursor.kt:
--------------------------------------------------------------------------------
1 | @file:OptIn(ExperimentalUnsignedTypes::class, ExperimentalUnsignedTypes::class)
2 |
3 | package tests
4 |
5 | import glm_.*
6 | import glm_.func.sin
7 | import glm_.vec2.Vec2
8 | import glm_.vec2.Vec2d
9 | import glm_.vec2.Vec2i
10 | import gln.*
11 | import gln.draw.DrawMode
12 | import gln.draw.glDrawArrays
13 | import kool.floatBufferOf
14 | import kool.free
15 | import org.lwjgl.glfw.GLFW
16 | import org.lwjgl.opengl.GL11
17 | import uno.gl.GlWindow
18 | import uno.glfw.*
19 | import java.awt.Color
20 | import kotlin.math.abs
21 | import kotlin.math.floor
22 | import kotlin.math.sqrt
23 |
24 | const val CURSOR_FRAME_COUNT = 60
25 |
26 | val vertexShaderText = """
27 | #version 110
28 | uniform mat4 MVP;
29 | attribute vec2 vPos;
30 | void main()
31 | {
32 | gl_Position = MVP * vec4(vPos, 0.0, 1.0);
33 | }""".trimIndent()
34 |
35 | val fragmentShaderText = """
36 | #version 110
37 | void main()
38 | {
39 | gl_FragColor = vec4(1.0);
40 | }""".trimIndent()
41 |
42 | var cursor = Vec2d()
43 | var swapInterval = VSync.ON
44 | var waitEvents = true
45 | var animateCursor = false
46 | var trackCursor = false
47 | val standardCursors = Array(10) { GlfwCursor.NULL }
48 | var trackingCursor: GlfwCursor = GlfwCursor.NULL
49 |
50 | fun star(x: Int, y: Int, t: Float): Float {
51 |
52 | val c = 64 / 2f
53 |
54 | val i = 0.25f * (2f * glm.πf * t).sin + 0.75f
55 | val k = 64 * 0.046875f * i
56 |
57 | val dist = sqrt((x - c) * (x - c) + (y - c) * (y - c))
58 |
59 | val sAlpha = 1f - dist / c
60 | val xAlpha = if (x.f == c) c else k / abs(x - c)
61 | val yAlpha = if (y.f == c) c else k / abs(y - c)
62 |
63 | return 0f max (1f min (i * sAlpha * 0.2f + sAlpha * xAlpha * yAlpha))
64 | }
65 |
66 | fun createCursorFrame(t: Float): GlfwCursor {
67 | var i = 0
68 | val buffer = UByteArray(64 * 64 * 4)
69 | val image = GlfwImage(64, buffer)
70 |
71 | for (y in 0 until image.width)
72 | for (x in 0 until image.height) {
73 | buffer[i++] = 255.toUByte()
74 | buffer[i++] = 255.toUByte()
75 | buffer[i++] = 255.toUByte()
76 | buffer[i++] = (255 * star(x, y, t)).toUInt().toUByte()
77 | }
78 |
79 | return GlfwCursor(image, image.width / 2, image.height / 2)
80 | }
81 |
82 | fun createTrackingCursor(): GlfwCursor {
83 | var i = 0
84 | val buffer = UByteArray(32 * 32 * 4)
85 | val image = GlfwImage(32, buffer)
86 |
87 | for (y in 0 until image.width)
88 | for (x in 0 until image.height)
89 | if (x == 7 || y == 7) {
90 | buffer[i++] = 255.toUByte()
91 | buffer[i++] = 0.toUByte()
92 | buffer[i++] = 0.toUByte()
93 | buffer[i++] = 255.toUByte()
94 | } else {
95 | buffer[i++] = 0.toUByte()
96 | buffer[i++] = 0.toUByte()
97 | buffer[i++] = 0.toUByte()
98 | buffer[i++] = 0.toUByte()
99 | }
100 | return GlfwCursor(image, 7)
101 | }
102 |
103 | fun cursorPositionCB(window: GlfwWindow, pos: Vec2d) {
104 | println("%.3f: Cursor position: ${pos.x.f} ${pos.y.f} (%+f %+f)".format(glfw.time, pos.x - cursor.x, pos.y - cursor.y))
105 |
106 | cursor.x = pos.x
107 | cursor.y = pos.y
108 | }
109 |
110 | var pos = Vec2i()
111 | var size = Vec2i()
112 | fun keyCB(window: GlfwWindow, key: Key, scancode: Int, action: InputAction, mods: Int) {
113 |
114 | if (action != InputAction.Press)
115 | return
116 |
117 | when (key) {
118 | Key.A -> {
119 | animateCursor = !animateCursor
120 | if (!animateCursor)
121 | window.cursor = GlfwCursor.NULL
122 | }
123 |
124 | Key.ESCAPE -> {
125 | val mode = window.cursorMode
126 | if (mode != GlfwWindow.CursorMode.Disabled && mode != GlfwWindow.CursorMode.Captured)
127 | window.shouldClose = true
128 |
129 | /* FALLTHROUGH */
130 | }
131 |
132 | Key.N -> {
133 | window.cursorMode = GlfwWindow.CursorMode.Normal
134 | cursor = window.cursorPos
135 | println("(( cursor is normal ))")
136 | }
137 |
138 | Key.D -> {
139 | window.cursorMode = GlfwWindow.CursorMode.Disabled
140 | println("(( cursor is disabled ))")
141 | }
142 |
143 | Key.H -> {
144 | window.cursorMode = GlfwWindow.CursorMode.Hidden
145 | println("(( cursor is hidden ))")
146 | }
147 |
148 | Key.C -> {
149 | window.cursorMode = GlfwWindow.CursorMode.Captured
150 | println("(( cursor is captured ))")
151 | }
152 |
153 | Key.R -> {
154 | if (glfw.rawMouseMotionSupported) {
155 | if (window.rawMouseMotion) {
156 | window.rawMouseMotion = false
157 | println("(( raw input is disabled ))")
158 | } else {
159 | window.rawMouseMotion = true
160 | println("(( raw input is enabled ))")
161 | }
162 | }
163 | }
164 |
165 | Key.SPACE -> {
166 | swapInterval = if (swapInterval == VSync.ON) VSync.OFF else VSync.ON
167 | println("(( swap interval: $swapInterval ))")
168 | glfw.swapInterval = swapInterval
169 | }
170 |
171 | Key.W -> {
172 | waitEvents = !waitEvents
173 | println("(( ${if (waitEvents) "wait" else "poll"}ing for events ))")
174 | }
175 |
176 | Key.T -> {
177 | trackCursor = !trackCursor
178 | window.cursor = if (trackCursor) trackingCursor else GlfwCursor.NULL
179 | }
180 |
181 | Key.P -> {
182 | var pos = window.cursorPos
183 |
184 | println("Query before set: %f %f (%+f %+f)".format(pos.x, pos.y, pos.x - cursor.x, pos.y - cursor.y))
185 | cursor put pos
186 | window.cursorPos = cursor
187 | pos = window.cursorPos
188 |
189 | println("Query after set: %f %f (%+f %+f)".format(pos.x, pos.y, pos.x - cursor.x, pos.y - cursor.y))
190 | cursor put pos
191 | }
192 |
193 | Key.UP -> {
194 | window.cursorPos = Vec2d()
195 | cursor = window.cursorPos
196 | }
197 |
198 | Key.DOWN -> {
199 | val size = window.size
200 | window.cursorPos = Vec2d(size.x - 1, size.y - 1)
201 | cursor = window.cursorPos
202 | }
203 |
204 | Key.`0` -> window.cursor = GlfwCursor.NULL
205 |
206 | Key.`1`, Key.`2`, Key.`3`, Key.`4`, Key.`5`, Key.`6`, Key.`7`, Key.`8`, Key.`9` -> {
207 | var index = key.i - Key.`1`.i
208 | if (mods has GLFW.GLFW_MOD_SHIFT)
209 | index += 9
210 |
211 | if (index < standardCursors.size)
212 | window.cursor = standardCursors[index]
213 | }
214 |
215 | Key.F11, Key.ENTER -> {
216 |
217 | if (mods != GLFW.GLFW_MOD_ALT)
218 | return
219 |
220 | if (window.monitor.isValid)
221 | window.setMonitor(GlfwMonitor.NULL, pos, size, 0)
222 | else {
223 | val monitor = glfw.primaryMonitor
224 | val mode = monitor.videoMode
225 | pos = window.pos
226 | size = window.size
227 | window.setMonitor(monitor, Vec2i(), mode.size, mode.refreshRate)
228 | }
229 |
230 | cursor = window.cursorPos
231 | }
232 | else -> {}
233 | }
234 | }
235 |
236 | fun main() {
237 | // int i
238 | // GLFWwindow * window
239 | val starCursors = Array(CURSOR_FRAME_COUNT) { GlfwCursor.NULL }
240 | var currentFrame = GlfwCursor.NULL
241 | // GLuint vertex_buffer, vertex_shader, fragment_shader, program
242 | // GLint mvp_location, vpos_location
243 |
244 | glfw.init(installDefaultErrorCB = true)
245 |
246 | trackingCursor = createTrackingCursor()
247 | if (trackingCursor.isNotValid)
248 | glfw.terminate()
249 |
250 | for (i in 0 until CURSOR_FRAME_COUNT) {
251 | starCursors[i] = createCursorFrame(i / CURSOR_FRAME_COUNT.f)
252 | if (starCursors[i].isNotValid)
253 | glfw.terminate()
254 | }
255 |
256 | for (i in standardCursors.indices)
257 | standardCursors[i] = glfw.createStandardCursor(glfw.CursorShape.values()[i])
258 |
259 | glfw.hints.context {
260 | major = 2
261 | minor = 0
262 | }
263 |
264 | val glfwWindow = GlfwWindow(640, 480, "Cursor Test")
265 | val window = GlWindow(glfwWindow)
266 |
267 | window.makeCurrent()
268 | // gladLoadGL(glfwGetProcAddress)
269 |
270 | val vertexBuffer = gl.genBuffers()
271 | vertexBuffer.bind(BufferTarget.ARRAY)
272 |
273 | val vertexShader = gl.createShader(ShaderType.VERTEX_SHADER).apply {
274 | source(vertexShaderText)
275 | compile()
276 | }
277 | val fragmentShader = gl.createShader(ShaderType.FRAGMENT_SHADER).apply {
278 | source(fragmentShaderText)
279 | compile()
280 | }
281 | val program = gl.createProgram().apply {
282 | attach(vertexShader)
283 | attach(fragmentShader)
284 | link()
285 | }
286 | val mvpLocation = program getUniformLocation "MVP"
287 | val vposLocation = program getAttribLocation "vPos"
288 |
289 | gl.enableVertexAttribArray(vposLocation)
290 | gl.vertexAttribPointer(vposLocation, Vec2.length, VertexAttrType.FLOAT, false, Vec2.size, 0)
291 | program.use()
292 |
293 | cursor = window.cursorPos
294 | println("Cursor position: ${cursor.x} ${cursor.y}")
295 |
296 | window.cursorPosCB = ::cursorPositionCB
297 | window.keyCB = ::keyCB
298 |
299 | while (!window.shouldClose) {
300 |
301 | glClearColor(Color.BLACK)
302 | GL11.glClear(GL11.GL_COLOR_BUFFER_BIT)
303 |
304 | if (trackCursor) {
305 |
306 | val wndSize = window.size
307 | val fbSize = window.framebufferSize
308 |
309 | glViewport(fbSize)
310 |
311 | val scale = fbSize.x.f / wndSize.x
312 | val vertices = floatBufferOf(0.5f,
313 | (fbSize.y - floor(cursor.y * scale) - 1f + 0.5f).f,
314 | fbSize.x +0.5f,
315 | (fbSize.y - floor(cursor.y * scale) - 1f + 0.5f).f,
316 | floor (cursor.x * scale).f + 0.5f,
317 | 0.5f,
318 | floor (cursor.x * scale).f + 0.5f,
319 | fbSize.y +0.5f)
320 |
321 | gl.bufferData(BufferTarget.ARRAY, vertices, Usage.STREAM_DRAW)
322 | vertices.free()
323 |
324 | val mvp = glm.ortho(0f, fbSize.x.f, 0f, fbSize.y.f, 0f, 1f)
325 | gl.uniform(mvpLocation, mvp)
326 |
327 | glDrawArrays(DrawMode.LINES, 4)
328 | }
329 |
330 | window.swapBuffers()
331 |
332 | if (animateCursor) {
333 | val i = (glfw.time * 30).i % CURSOR_FRAME_COUNT
334 | if (currentFrame != starCursors[i]) {
335 | window.cursor = starCursors[i]
336 | currentFrame = starCursors[i]
337 | }
338 | } else
339 | currentFrame = GlfwCursor.NULL
340 |
341 | if (waitEvents) {
342 | if (animateCursor)
343 | glfw.waitEventsTimeout(1.0 / 30.0)
344 | else
345 | glfw.waitEvents()
346 | } else
347 | glfw.pollEvents()
348 |
349 | // Workaround for an issue with msvcrt and mintty
350 | // fflush(stdout)
351 | }
352 |
353 | window.destroy()
354 |
355 | for (cursor in starCursors)
356 | cursor.destroy()
357 |
358 | for (cursor in standardCursors)
359 | cursor.destroy()
360 |
361 | glfw.terminate()
362 | }
363 |
--------------------------------------------------------------------------------