diff --git a/res/ex-layout/main.xml b/res/ex-layout/main.xml index c24cd46..39b85a5 100644 --- a/res/ex-layout/main.xml +++ b/res/ex-layout/main.xml @@ -18,7 +18,6 @@ width="wrap_content" height="wrap_content" textSize="14sp" - textStyle="bold" text="Hello world"/> + + + + + \ No newline at end of file diff --git a/res/font/roboto.xml b/res/font/roboto.xml index 1b9492d..45f8a3e 100644 --- a/res/font/roboto.xml +++ b/res/font/roboto.xml @@ -1,5 +1,7 @@ + @fonts/Roboto/Roboto-BoldItalic + @fonts/Roboto/Roboto-Italic @fonts/Roboto/Roboto-Bold @fonts/Roboto/Roboto-Regular \ No newline at end of file diff --git a/res/fonts/Roboto/Roboto-BoldItalic.ttf b/res/fonts/Roboto/Roboto-BoldItalic.ttf new file mode 100644 index 0000000..bcfdab4 Binary files /dev/null and b/res/fonts/Roboto/Roboto-BoldItalic.ttf differ diff --git a/res/fonts/Roboto/Roboto-Italic.ttf b/res/fonts/Roboto/Roboto-Italic.ttf new file mode 100644 index 0000000..1b5eaa3 Binary files /dev/null and b/res/fonts/Roboto/Roboto-Italic.ttf differ diff --git a/res/raw/view_renderer.frag b/res/raw/view_renderer.frag index 4e50d94..a950bfd 100644 --- a/res/raw/view_renderer.frag +++ b/res/raw/view_renderer.frag @@ -1,10 +1,9 @@ precision mediump float; -#define ALPHA float(params[1])/255.0 -#define MODE params[0] - -uniform int[8] params; +#define ALPHA float(params.y)/255.0 +#define MODE params.x +uniform vec4 params; uniform sampler2D texture; varying vec2 uv; @@ -12,7 +11,7 @@ varying vec2 uv; void main() { vec4 diffuse = vec4(1.0); - if(MODE == 0) { + if(MODE == 0.0) { diffuse = texture2D(texture, uv); } diff --git a/res/raw/view_renderer.vert b/res/raw/view_renderer.vert index fdfcf68..03449b2 100644 --- a/res/raw/view_renderer.vert +++ b/res/raw/view_renderer.vert @@ -1,3 +1,5 @@ +precision mediump float; + attribute vec4 vPos; attribute vec2 vTexCoords; diff --git a/src/br/nullexcept/mux/app/Application.java b/src/br/nullexcept/mux/app/Application.java index 70c9682..40801c8 100644 --- a/src/br/nullexcept/mux/app/Application.java +++ b/src/br/nullexcept/mux/app/Application.java @@ -3,9 +3,16 @@ import br.nullexcept.mux.C; import br.nullexcept.mux.core.texel.TexelAPI; import br.nullexcept.mux.lang.Valuable; +import br.nullexcept.mux.utils.Log; import br.nullexcept.mux.view.Window; +import org.lwjgl.egl.EGL; +import org.lwjgl.egl.EGL10; +import org.lwjgl.egl.EGL11; +import org.lwjgl.glfw.GLFWNativeEGL; import org.lwjgl.opengles.GLES; +import org.lwjgl.system.MemoryUtil; +import java.nio.IntBuffer; import java.util.ArrayList; import java.util.HashMap; @@ -18,13 +25,8 @@ public class Application { public static void initialize(Valuable creator){ glfwInit(); - glfwDefaultWindowHints(); - if (C.Config.SET_WINDOW_GL_HINT) { - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, C.Config.WINDOW_GL_VERSION[0]); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, C.Config.WINDOW_GL_VERSION[1]); - glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); - } - glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); + + setupEGL(); long window = glfwCreateWindow(1,1,"[MasterUI - Core]",0, 0); glfwMakeContextCurrent(window); @@ -43,10 +45,28 @@ public static void initialize(Valuable creator){ TexelAPI.destroy(); glfwTerminate(); System.gc(); - Looper.sleep(2000,0); // Wait for all services stop + Looper.sleep(2000); // Wait for all services stop System.exit(0); } + private static void setupEGL() { + glfwDefaultWindowHints(); + if (C.Config.SET_WINDOW_GL_HINT) { + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, C.Config.WINDOW_GL_VERSION[0]); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, C.Config.WINDOW_GL_VERSION[1]); + glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API); + glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); + + long display = GLFWNativeEGL.glfwGetEGLDisplay(); + try {// Setup EGL + int[][] version = new int[2][1]; + EGL10.eglInitialize(display, version[0], version[1]); + EGL.createDisplayCapabilities(display, version[0][0], version[1][0]); + } catch (Exception e) {} + } + glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); + } + private static void loop(){ glfwPollEvents(); if (System.currentTimeMillis() - lastGc > 5000){ @@ -124,7 +144,7 @@ public static void stop(){ Looper.getMainLooper().stop(); } - static T beginService(Launch launch) { + static synchronized T beginService(Launch launch) { String name = launch.getLaunchClass().getName(); if (services.containsKey(name)) { diff --git a/src/br/nullexcept/mux/app/Looper.java b/src/br/nullexcept/mux/app/Looper.java index f8552e4..94d5b2e 100644 --- a/src/br/nullexcept/mux/app/Looper.java +++ b/src/br/nullexcept/mux/app/Looper.java @@ -1,13 +1,9 @@ package br.nullexcept.mux.app; -import br.nullexcept.mux.utils.Log; - -import java.util.HashMap; +import java.util.ArrayList; public class Looper { - private static final String LOG_TAG = "Looper"; - - private final HashMap executions = new HashMap<>(); + private final ArrayList executions = new ArrayList<>(); static Looper mainLooper; private boolean stop = false; @@ -21,8 +17,9 @@ public void initialize(){ } public void postDelayed(Runnable runnable, long msTime){ + msTime = Math.max(0, msTime); synchronized (executions) { - executions.put(System.nanoTime() + (msTime * 1000000L), runnable); + executions.add(new Callback(runnable,System.currentTimeMillis()+msTime)); } } @@ -32,28 +29,24 @@ public void post(Runnable runnable){ public void loop(){ while (!stop) { - long time = System.nanoTime(); - Long[] keys; + Callback[] list; + int i = 0; synchronized (executions) { - keys = executions.keySet().toArray(new Long[0]); - } - for (long key : keys) { - if (key <= time) { - Runnable runnable; - synchronized (executions) { - runnable = executions.get(key); - executions.remove(key); - } - try { - runnable.run(); - } catch (Throwable e) { - Log.error(LOG_TAG, "[ERROR ON LOOPER]",e); - stop = true; + list = executions.toArray(new Callback[0]); + for (Callback call: list) { + if (call.time <= System.currentTimeMillis()) { + executions.remove(call); + } else { + list[i] = null; } + i++; } } - - sleep(0, (int) (Math.random()*400)); + for (Callback call: list) { + if (call == null) continue; + call.handle.run(); + } + sleep(0, (int) (Math.random()*100)); } } @@ -70,4 +63,29 @@ public static void sleep(int ms, int nano) { public void stop(){ this.stop = true; } + + private static class Callback { + private static long current; + private final Runnable handle; + private final long time; + private final long id = hash(); + + private Callback(Runnable handle, long time) { + this.handle = handle; + this.time = time; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Callback) { + return ((Callback) obj).id == id; + } + return false; + } + + public static synchronized long hash() { + current++; + return current; + } + } } diff --git a/src/br/nullexcept/mux/core/texel/GLProgramTexture.java b/src/br/nullexcept/mux/core/texel/GLProgramTexture.java index f8b4bd5..6de7f3c 100644 --- a/src/br/nullexcept/mux/core/texel/GLProgramTexture.java +++ b/src/br/nullexcept/mux/core/texel/GLProgramTexture.java @@ -5,22 +5,25 @@ class GLProgramTexture extends GLProgram { protected String fragment() { return ("precision mediump float;\n" + "uniform sampler2D __texture__;\n" + - "varying vec2 xuv;" + + "varying vec2 xuv\n\n;" + "void main(){\n" + " gl_FragColor = texture2D(__texture__, xuv);\n" + - "};\n").replaceAll("__texture__", UNIFORM_TEXTURE); + "}\n").replaceAll("__texture__", UNIFORM_TEXTURE) + .replaceAll("\n","\n\r"); } @Override protected String vertex() { - return ("attribute vec4 __position__;\n" + + return ("precision mediump float;\n" + + "attribute vec4 __position__;\n" + "attribute vec2 __uv__;\n" + - "varying vec2 xuv;" + + "varying vec2 xuv;\n\n" + "void main(){\n" + " gl_Position = __position__;\n" + " xuv = __uv__;\n" + - "};\n").replaceAll("__position__", ATTRIBUTE_POSITION) - .replaceAll("__uv__", ATTRIBUTE_UV); + "}\n").replaceAll("__position__", ATTRIBUTE_POSITION) + .replaceAll("__uv__", ATTRIBUTE_UV) + .replaceAll("\n","\n\r"); } @Override diff --git a/src/br/nullexcept/mux/core/texel/GLTexel.java b/src/br/nullexcept/mux/core/texel/GLTexel.java index 84179fb..fe82267 100644 --- a/src/br/nullexcept/mux/core/texel/GLTexel.java +++ b/src/br/nullexcept/mux/core/texel/GLTexel.java @@ -84,9 +84,11 @@ public static void drawViewLayers(float[][] vertices, int[] textures, float[] al glVertexAttribPointer(program.uv, 2, GL_FLOAT, false, 0, bufferUV); glUniform1i(program.texture, GL_TEXTURE_2D); - glUniform1iv(program.params, new int[]{ - 0, - Math.round(alphas[i] * 255) + glUniform1fv(program.params, new float[]{ + 0.0f, + Math.round(alphas[i] * 255) / 255.0f, + 0.0f, + 0.0f }); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } diff --git a/src/br/nullexcept/mux/core/texel/GlesUtils.java b/src/br/nullexcept/mux/core/texel/GlesUtils.java index 607dc9c..cfeb9a4 100644 --- a/src/br/nullexcept/mux/core/texel/GlesUtils.java +++ b/src/br/nullexcept/mux/core/texel/GlesUtils.java @@ -10,7 +10,7 @@ public static int compileShader(String source, int type){ int[] res = new int[1]; glGetShaderiv(shader, GL_COMPILE_STATUS,res); if (res[0] != GL_TRUE){ - throw new RuntimeException("Error on compile gl shader: "+ glGetShaderInfoLog(shader)); + throw new RuntimeException("Error on compile gl shader: "+ glGetShaderInfoLog(shader)+"\nSource: \n"+source); } return shader; } diff --git a/src/br/nullexcept/mux/core/texel/GlfwWindow.java b/src/br/nullexcept/mux/core/texel/GlfwWindow.java index 9e15950..59ee52b 100644 --- a/src/br/nullexcept/mux/core/texel/GlfwWindow.java +++ b/src/br/nullexcept/mux/core/texel/GlfwWindow.java @@ -43,6 +43,13 @@ public GlfwWindow() { window = GLFW.glfwCreateWindow(512, 512, title = "[MasterUI:Window]", 0, C.GLFW_CONTEXT); eventManager = new GlfwEventManager(this); GLFW.glfwIconifyWindow(window); + GLFW.glfwSetWindowSizeCallback(window, (l, w,h) -> { + windowSize.set(w,h); + Looper.getMainLooper().post(this::drawSurface); + }); + GLFW.glfwSetWindowPosCallback(window, (l, x, y) -> { + p.set(x,y); + }); setMinimumSize(256,256); center(); } @@ -85,6 +92,21 @@ private void refresh() { private long[] times = new long[8]; private long last = System.currentTimeMillis(); + private Point p = new Point(); + private Point pd = new Point(); + + private void drawSurface() { + if (destroyed)return; + GLFW.glfwSwapBuffers(C.GLFW_CONTEXT); + GLFW.glfwMakeContextCurrent(window); + glfwSwapInterval(0); //NEED THAT FOR NOT SLOW MAIN LOOP + GLES.glViewport(0, 0, windowSize.width, windowSize.height); + GLES.glClearColor(0,0,0,1); + GLES.glClear(GLES20.GL_COLOR_BUFFER_BIT| GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_STENCIL_BUFFER_BIT); + GLTexel.drawTexture(0, 0, windowSize.width, windowSize.height, container.getCanvas().getFramebuffer().getTexture()); + GLFW.glfwSwapBuffers(window); + GLFW.glfwMakeContextCurrent(C.GLFW_CONTEXT); + } private void update() { if(destroyed) @@ -109,22 +131,14 @@ private void update() { container.resize(windowSize.width, windowSize.height); container.drawFrame(); - GLFW.glfwSwapBuffers(C.GLFW_CONTEXT); - GLFW.glfwMakeContextCurrent(window); - glfwSwapInterval(0); //NEED THAT FOR NOT SLOW MAIN LOOP - GLES.glViewport(0, 0, windowSize.width, windowSize.height); - GLES.glClearColor(0,0,0,1); - GLES.glClear(GLES20.GL_COLOR_BUFFER_BIT| GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_STENCIL_BUFFER_BIT); - GLTexel.drawTexture(0, 0, windowSize.width, windowSize.height, container.getCanvas().getFramebuffer().getTexture()); - + drawSurface(); times[1] += System.currentTimeMillis() - begin; if (C.Flags.DEBUG_OVERLAY) { drawDebug(); } - - GLFW.glfwSwapBuffers(window); - GLFW.glfwMakeContextCurrent(C.GLFW_CONTEXT); } + + if (GLFW.glfwWindowShouldClose(window)) { destroy(); } @@ -220,7 +234,7 @@ public void setSize(int width, int height) { @Override public void setMinimumSize(int width, int height) { - GLFW.glfwSetWindowSizeLimits(window, width,height,Integer.MAX_VALUE, Integer.MAX_VALUE); + //GLFW.glfwSetWindowSizeLimits(window, width,height,Integer.MAX_VALUE, Integer.MAX_VALUE); } public void onMouseEvent(MouseEvent event) { @@ -252,6 +266,7 @@ public void setVisible(boolean visible) { if (visible) { align(); GLFW.glfwShowWindow(window); + GLFW.glfwFocusWindow(window); } else { refresh(); align(); diff --git a/src/br/nullexcept/mux/view/View.java b/src/br/nullexcept/mux/view/View.java index 546e989..de6e111 100644 --- a/src/br/nullexcept/mux/view/View.java +++ b/src/br/nullexcept/mux/view/View.java @@ -248,6 +248,12 @@ public final void requestFocus() { } } + protected void requestNextFocus() { + if (parent != null) { + parent.findNextFocus(this); + } + } + public void setFocusable(boolean focusable) { if (parent != null && this.focusable && !focusable) { parent.requestFocus(null); @@ -322,6 +328,9 @@ protected void onCharEvent(CharEvent charEvent) { } protected void onKeyEvent(KeyEvent keyEvent) { + if (keyEvent.getAction() == KeyEvent.ACTION_UP && keyEvent.getKeyCode() == KeyEvent.KEY_TAB && isFocused()) { + requestNextFocus(); + } } protected void onMouseMoved(MotionEvent event) { diff --git a/src/br/nullexcept/mux/view/ViewGroup.java b/src/br/nullexcept/mux/view/ViewGroup.java index c089d0f..56fbc90 100644 --- a/src/br/nullexcept/mux/view/ViewGroup.java +++ b/src/br/nullexcept/mux/view/ViewGroup.java @@ -94,6 +94,55 @@ public void measure() { measureBounds(); } + private View searchFocus(View vw) { + if (!vw.isVisible()) { + return null; + } + if (vw.isFocusable()) { + return vw; + } + if (vw instanceof ViewGroup) { + for (View child : ((ViewGroup) vw).children) { + View v = searchFocus(child); + if (v != null) { + return v; + } + } + } + return null; + } + + boolean findNextFocus(View child) { + int index = children.indexOf(child); + if (index + 1 < children.size()) { + for (int i = index+1; i < children.size(); i++) { + View ch = searchFocus(children.get(i)); + if (ch != null) { + ch.requestFocus(); + return true; + } + } + if (getParent() != null) { + return getParent().findNextFocus(this); + } else { + View fcs = searchFocus(this); + if (fcs != null) { + fcs.requestFocus();; + return true; + } + } + } else if (getParent() != null) { + return getParent().findNextFocus(this); + } else { + View focus = searchFocus(this); + if (focus != null) { + focus.requestFocus(); + return true; + } + } + return false; + } + @Override protected boolean dispatchMouseEvent(MouseEvent mouseEvent) { boolean handle = false; diff --git a/src/br/nullexcept/mux/widget/EditText.java b/src/br/nullexcept/mux/widget/EditText.java index ba5fabc..92f9b36 100644 --- a/src/br/nullexcept/mux/widget/EditText.java +++ b/src/br/nullexcept/mux/widget/EditText.java @@ -300,6 +300,10 @@ protected void onKeyEvent(KeyEvent keyEvent) { } break; } + } else { + if (keyEvent.getKeyCode() == KeyEvent.KEY_TAB) { + requestNextFocus(); + } } } diff --git a/src/br/nullexcept/mux/widget/TextView.java b/src/br/nullexcept/mux/widget/TextView.java index 2eec0f5..dcbb28d 100644 --- a/src/br/nullexcept/mux/widget/TextView.java +++ b/src/br/nullexcept/mux/widget/TextView.java @@ -48,8 +48,6 @@ public TextView(Context context, AttributeList attrs) { Typeface font = context.getResources().getFont(fontFamily[0], fontStyle[0]); if (font != null) { setTypeface(font); - } else { - System.err.println("Font is null"); } }