|
1 | 1 | /**************************************************************************/ |
2 | | -/* GodotGLRenderView.java */ |
| 2 | +/* GodotGLRenderView.kt */ |
3 | 3 | /**************************************************************************/ |
4 | 4 | /* This file is part of: */ |
5 | 5 | /* GODOT ENGINE */ |
|
28 | 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | 29 | /**************************************************************************/ |
30 | 30 |
|
31 | | -package org.godotengine.godot.render; |
| 31 | +package org.godotengine.godot.render |
32 | 32 |
|
33 | | -import org.godotengine.godot.Godot; |
34 | | -import org.godotengine.godot.GodotRenderView; |
35 | | -import org.godotengine.godot.input.GodotInputHandler; |
36 | | -import org.godotengine.godot.xr.XRMode; |
37 | | - |
38 | | -import android.annotation.SuppressLint; |
39 | | -import android.content.res.AssetManager; |
40 | | -import android.graphics.Bitmap; |
41 | | -import android.graphics.BitmapFactory; |
42 | | -import android.graphics.PixelFormat; |
43 | | -import android.text.TextUtils; |
44 | | -import android.util.SparseArray; |
45 | | -import android.view.KeyEvent; |
46 | | -import android.view.MotionEvent; |
47 | | -import android.view.PointerIcon; |
48 | | -import android.view.SurfaceView; |
49 | | - |
50 | | -import androidx.annotation.Keep; |
51 | | - |
52 | | -import java.io.InputStream; |
| 33 | +import android.annotation.SuppressLint |
| 34 | +import android.graphics.PixelFormat |
| 35 | +import android.view.KeyEvent |
| 36 | +import android.view.MotionEvent |
| 37 | +import android.view.PointerIcon |
| 38 | +import org.godotengine.godot.Godot |
| 39 | +import org.godotengine.godot.GodotRenderView |
| 40 | +import org.godotengine.godot.input.GodotInputHandler |
| 41 | +import org.godotengine.godot.xr.XRMode |
53 | 42 |
|
54 | 43 | /** |
55 | 44 | * A simple GLSurfaceView sub-class that demonstrate how to perform |
56 | 45 | * OpenGL ES 2.0 rendering into a GL Surface. Note the following important |
57 | 46 | * details: |
58 | 47 | * |
59 | 48 | * - The class must use a custom context factory to enable 2.0 rendering. |
60 | | - * See ContextFactory class definition below. |
| 49 | + * See ContextFactory class definition below. |
61 | 50 | * |
62 | 51 | * - The class must use a custom EGLConfigChooser to be able to select |
63 | | - * an EGLConfig that supports 3.0. This is done by providing a config |
64 | | - * specification to eglChooseConfig() that has the attribute |
65 | | - * EGL10.ELG_RENDERABLE_TYPE containing the EGL_OPENGL_ES2_BIT flag |
66 | | - * set. See ConfigChooser class definition below. |
| 52 | + * an EGLConfig that supports 3.0. This is done by providing a config |
| 53 | + * specification to eglChooseConfig() that has the attribute |
| 54 | + * EGL10.ELG_RENDERABLE_TYPE containing the EGL_OPENGL_ES2_BIT flag |
| 55 | + * set. See ConfigChooser class definition below. |
67 | 56 | * |
68 | 57 | * - The class must select the surface's format, then choose an EGLConfig |
69 | | - * that matches it exactly (with regards to red/green/blue/alpha channels |
70 | | - * bit depths). Failure to do so would result in an EGL_BAD_MATCH error. |
| 58 | + * that matches it exactly (with regards to red/green/blue/alpha channels |
| 59 | + * bit depths). Failure to do so would result in an EGL_BAD_MATCH error. |
71 | 60 | */ |
72 | | -public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView { |
73 | | - private final Godot godot; |
74 | | - private final GodotInputHandler inputHandler; |
75 | | - private final GodotRenderer godotRenderer; |
76 | | - private final SparseArray<PointerIcon> customPointerIcons = new SparseArray<>(); |
77 | | - |
78 | | - public GodotGLRenderView(Godot godot, GodotRenderer renderer, GodotInputHandler inputHandler, XRMode xrMode, boolean useDebugOpengl, boolean shouldBeTranslucent) { |
79 | | - super(godot.getContext()); |
80 | | - |
81 | | - this.godot = godot; |
82 | | - this.inputHandler = inputHandler; |
83 | | - this.godotRenderer = renderer; |
84 | | - setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT)); |
85 | | - init(xrMode, shouldBeTranslucent, useDebugOpengl); |
| 61 | +internal class GodotGLRenderView( |
| 62 | + private val godot: Godot, |
| 63 | + godotRenderer: GodotRenderer, |
| 64 | + private val inputHandler: GodotInputHandler, |
| 65 | + xrMode: XRMode, |
| 66 | + useDebugOpengl: Boolean, |
| 67 | + shouldBeTranslucent: Boolean |
| 68 | +) : GLSurfaceView( |
| 69 | + godot.context |
| 70 | +), GodotRenderView { |
| 71 | + init { |
| 72 | + pointerIcon = PointerIcon.getSystemIcon(context, PointerIcon.TYPE_DEFAULT) |
| 73 | + init(xrMode, godotRenderer, shouldBeTranslucent, useDebugOpengl) |
86 | 74 | } |
87 | 75 |
|
88 | | - @Override |
89 | | - public SurfaceView getView() { |
90 | | - return this; |
91 | | - } |
| 76 | + override fun getView() = this |
92 | 77 |
|
93 | | - @Override |
94 | | - public GodotInputHandler getInputHandler() { |
95 | | - return inputHandler; |
96 | | - } |
| 78 | + override fun getInputHandler() = inputHandler |
97 | 79 |
|
98 | 80 | @SuppressLint("ClickableViewAccessibility") |
99 | | - @Override |
100 | | - public boolean onTouchEvent(MotionEvent event) { |
101 | | - super.onTouchEvent(event); |
102 | | - return inputHandler.onTouchEvent(event); |
103 | | - } |
104 | | - |
105 | | - @Override |
106 | | - public boolean onKeyUp(final int keyCode, KeyEvent event) { |
107 | | - return inputHandler.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event); |
108 | | - } |
109 | | - |
110 | | - @Override |
111 | | - public boolean onKeyDown(final int keyCode, KeyEvent event) { |
112 | | - return inputHandler.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event); |
| 81 | + override fun onTouchEvent(event: MotionEvent): Boolean { |
| 82 | + super.onTouchEvent(event) |
| 83 | + return inputHandler.onTouchEvent(event) |
113 | 84 | } |
114 | 85 |
|
115 | | - @Override |
116 | | - public boolean onGenericMotionEvent(MotionEvent event) { |
117 | | - return inputHandler.onGenericMotionEvent(event) || super.onGenericMotionEvent(event); |
| 86 | + override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { |
| 87 | + return inputHandler.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event) |
118 | 88 | } |
119 | 89 |
|
120 | | - @Override |
121 | | - public boolean onCapturedPointerEvent(MotionEvent event) { |
122 | | - return inputHandler.onGenericMotionEvent(event); |
| 90 | + override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { |
| 91 | + return inputHandler.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event) |
123 | 92 | } |
124 | 93 |
|
125 | | - @Override |
126 | | - public void onPointerCaptureChange(boolean hasCapture) { |
127 | | - super.onPointerCaptureChange(hasCapture); |
128 | | - inputHandler.onPointerCaptureChange(hasCapture); |
| 94 | + override fun onGenericMotionEvent(event: MotionEvent): Boolean { |
| 95 | + return inputHandler.onGenericMotionEvent(event) || super.onGenericMotionEvent(event) |
129 | 96 | } |
130 | 97 |
|
131 | | - @Override |
132 | | - public void requestPointerCapture() { |
133 | | - if (canCapturePointer()) { |
134 | | - super.requestPointerCapture(); |
135 | | - inputHandler.onPointerCaptureChange(true); |
136 | | - } |
| 98 | + override fun onCapturedPointerEvent(event: MotionEvent): Boolean { |
| 99 | + return inputHandler.onGenericMotionEvent(event) |
137 | 100 | } |
138 | 101 |
|
139 | | - @Override |
140 | | - public void releasePointerCapture() { |
141 | | - super.releasePointerCapture(); |
142 | | - inputHandler.onPointerCaptureChange(false); |
| 102 | + override fun onPointerCaptureChange(hasCapture: Boolean) { |
| 103 | + super.onPointerCaptureChange(hasCapture) |
| 104 | + inputHandler.onPointerCaptureChange(hasCapture) |
143 | 105 | } |
144 | 106 |
|
145 | | - /** |
146 | | - * Used to configure the PointerIcon for the given type. |
147 | | - * |
148 | | - * Called from JNI |
149 | | - */ |
150 | | - @Keep |
151 | | - @Override |
152 | | - public void configurePointerIcon(int pointerType, String imagePath, float hotSpotX, float hotSpotY) { |
153 | | - try { |
154 | | - Bitmap bitmap = null; |
155 | | - if (!TextUtils.isEmpty(imagePath)) { |
156 | | - if (godot.getDirectoryAccessHandler().filesystemFileExists(imagePath)) { |
157 | | - // Try to load the bitmap from the file system |
158 | | - bitmap = BitmapFactory.decodeFile(imagePath); |
159 | | - } else if (godot.getDirectoryAccessHandler().assetsFileExists(imagePath)) { |
160 | | - // Try to load the bitmap from the assets directory |
161 | | - AssetManager am = getContext().getAssets(); |
162 | | - InputStream imageInputStream = am.open(imagePath); |
163 | | - bitmap = BitmapFactory.decodeStream(imageInputStream); |
164 | | - } |
165 | | - } |
166 | | - |
167 | | - PointerIcon customPointerIcon = PointerIcon.create(bitmap, hotSpotX, hotSpotY); |
168 | | - customPointerIcons.put(pointerType, customPointerIcon); |
169 | | - } catch (Exception e) { |
170 | | - // Reset the custom pointer icon |
171 | | - customPointerIcons.delete(pointerType); |
| 107 | + override fun requestPointerCapture() { |
| 108 | + if (godot.canCapturePointer()) { |
| 109 | + super.requestPointerCapture() |
| 110 | + inputHandler.onPointerCaptureChange(true) |
172 | 111 | } |
173 | 112 | } |
174 | 113 |
|
175 | | - /** |
176 | | - * called from JNI to change pointer icon |
177 | | - */ |
178 | | - @Keep |
179 | | - @Override |
180 | | - public void setPointerIcon(int pointerType) { |
181 | | - PointerIcon pointerIcon = customPointerIcons.get(pointerType); |
182 | | - if (pointerIcon == null) { |
183 | | - pointerIcon = PointerIcon.getSystemIcon(getContext(), pointerType); |
184 | | - } |
185 | | - setPointerIcon(pointerIcon); |
| 114 | + override fun releasePointerCapture() { |
| 115 | + super.releasePointerCapture() |
| 116 | + inputHandler.onPointerCaptureChange(false) |
186 | 117 | } |
187 | 118 |
|
188 | | - @Override |
189 | | - public PointerIcon onResolvePointerIcon(MotionEvent me, int pointerIndex) { |
190 | | - return getPointerIcon(); |
| 119 | + override fun onResolvePointerIcon(me: MotionEvent, pointerIndex: Int): PointerIcon { |
| 120 | + return pointerIcon |
191 | 121 | } |
192 | 122 |
|
193 | | - private void init(XRMode xrMode, boolean translucent, boolean useDebugOpengl) { |
194 | | - setPreserveEGLContextOnPause(true); |
195 | | - setFocusableInTouchMode(true); |
196 | | - switch (xrMode) { |
197 | | - case OPENXR: |
| 123 | + private fun init(xrMode: XRMode, renderer: GodotRenderer, translucent: Boolean, useDebugOpengl: Boolean) { |
| 124 | + preserveEGLContextOnPause = true |
| 125 | + isFocusableInTouchMode = true |
| 126 | + when (xrMode) { |
| 127 | + XRMode.OPENXR -> { |
198 | 128 | // Replace the default egl config chooser. |
199 | | - setEGLConfigChooser(new OvrConfigChooser()); |
| 129 | + setEGLConfigChooser(OvrConfigChooser()) |
200 | 130 |
|
201 | 131 | // Replace the default context factory. |
202 | | - setEGLContextFactory(new OvrContextFactory()); |
| 132 | + setEGLContextFactory(OvrContextFactory()) |
203 | 133 |
|
204 | 134 | // Replace the default window surface factory. |
205 | | - setEGLWindowSurfaceFactory(new OvrWindowSurfaceFactory()); |
206 | | - break; |
| 135 | + setEGLWindowSurfaceFactory(OvrWindowSurfaceFactory()) |
| 136 | + } |
207 | 137 |
|
208 | | - case REGULAR: |
209 | | - default: |
| 138 | + XRMode.REGULAR -> { |
210 | 139 | /* By default, GLSurfaceView() creates a RGB_565 opaque surface. |
211 | 140 | * If we want a translucent one, we should change the surface's |
212 | 141 | * format here, using PixelFormat.TRANSLUCENT for GL Surfaces |
213 | 142 | * is interpreted as any 32-bit surface with alpha by SurfaceFlinger. |
214 | 143 | */ |
215 | 144 | if (translucent) { |
216 | | - this.getHolder().setFormat(PixelFormat.TRANSLUCENT); |
| 145 | + this.holder.setFormat(PixelFormat.TRANSLUCENT) |
217 | 146 | } |
218 | 147 |
|
219 | 148 | /* Setup the context factory for 2.0 rendering. |
220 | 149 | * See ContextFactory class definition below |
221 | 150 | */ |
222 | | - setEGLContextFactory(new RegularContextFactory(useDebugOpengl)); |
| 151 | + setEGLContextFactory( |
| 152 | + RegularContextFactory( |
| 153 | + useDebugOpengl |
| 154 | + ) |
| 155 | + ) |
223 | 156 |
|
224 | 157 | /* We need to choose an EGLConfig that matches the format of |
225 | 158 | * our surface exactly. This is going to be done in our |
226 | 159 | * custom config chooser. See ConfigChooser class definition |
227 | 160 | * below. |
228 | 161 | */ |
229 | | - |
230 | 162 | setEGLConfigChooser( |
231 | | - new RegularFallbackConfigChooser(8, 8, 8, 8, 24, 0, |
232 | | - new RegularConfigChooser(8, 8, 8, 8, 16, 0))); |
233 | | - break; |
| 163 | + RegularFallbackConfigChooser( |
| 164 | + 8, 8, 8, 8, 24, 0, |
| 165 | + RegularConfigChooser(8, 8, 8, 8, 16, 0) |
| 166 | + ) |
| 167 | + ) |
| 168 | + } |
234 | 169 | } |
235 | | - } |
236 | 170 |
|
237 | | - @Override |
238 | | - public void startRenderer() { |
239 | | - /* Set the renderer responsible for frame rendering */ |
240 | | - setRenderer(godotRenderer); |
| 171 | + // Set the renderer responsible for frame rendering |
| 172 | + setRenderer(renderer) |
241 | 173 | } |
242 | 174 | } |
0 commit comments