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");
}
}