ecere: Initial Emscripten support
authorJerome St-Louis <jerome@ecere.com>
Sat, 10 Oct 2015 02:25:20 +0000 (22:25 -0400)
committerJerome St-Louis <jerome@ecere.com>
Thu, 15 Oct 2015 00:26:43 +0000 (20:26 -0400)
- Mekano, Chess and UWClone working reasonably well

47 files changed:
ecere/ecere.epj
ecere/src/com/String.ec
ecere/src/com/instance.c
ecere/src/com/instance.ec
ecere/src/gfx/3D/Object.ec
ecere/src/gfx/3D/models/Object3DSFormat.ec
ecere/src/gfx/Display.ec
ecere/src/gfx/bitmaps/JPEGFormat.ec
ecere/src/gfx/bitmaps/PNGFormat.ec
ecere/src/gfx/drivers/LFBDisplayDriver.ec
ecere/src/gfx/drivers/OpenGLDisplayDriver.ec
ecere/src/gfx/drivers/XDisplayDriver.ec
ecere/src/gfx/drivers/gl3/fixed.frag
ecere/src/gfx/drivers/gl3/fixed.vertex
ecere/src/gfx/drivers/gl3/glab.ec
ecere/src/gfx/drivers/gl3/immediate.ec
ecere/src/gfx/drivers/gl3/matrixStack.ec
ecere/src/gfx/drivers/gl3/shading.ec
ecere/src/gui/GuiApplication.ec
ecere/src/gui/Window.ec
ecere/src/gui/drivers/AndroidInterface.ec
ecere/src/gui/drivers/EmscriptenInterface.ec
ecere/src/gui/drivers/NCursesInterface.ec
ecere/src/gui/drivers/XInterface.ec
ecere/src/net/Service.ec
ecere/src/net/Socket.ec
ecere/src/net/dcom.ec
ecere/src/net/network.ec
ecere/src/sys/DualPipe.c
ecere/src/sys/EARArchive.ec
ecere/src/sys/File.c
ecere/src/sys/File.ec
ecere/src/sys/Mutex.ec
ecere/src/sys/Semaphore.ec
ecere/src/sys/System.c
ecere/src/sys/System.ec
ecere/src/sys/Thread.ec
ecere/src/sys/Time.ec
samples/games/chess/chess.epj
samples/games/chess/src/about.ec
samples/games/chess/src/ai.ec
samples/games/chess/src/chess.ec
samples/games/chess/src/chess3D.ec
samples/games/chess/src/connect.ec
samples/guiAndGfx/mekano/mekano.epj
samples/guiAndGfx/mekano/mekanosimulation.ec
samples/guiAndGfx/mekano/mekanownd.ec

index 472a834..e14aefc 100644 (file)
@@ -760,12 +760,6 @@ from wherever you obtained them.
                                        }
                                     }
                                  ]
-                              },
-                              {
-                                 "Name" : "Emscripten",
-                                 "Options" : {
-                                    "ExcludeFromBuild" : true
-                                 }
                               }
                            ]
                         },
@@ -780,17 +774,7 @@ from wherever you obtained them.
                               }
                            ]
                         },
-                        {
-                           "FileName" : "PNGFormat.ec",
-                           "Configurations" : [
-                              {
-                                 "Name" : "Emscripten",
-                                 "Options" : {
-                                    "ExcludeFromBuild" : true
-                                 }
-                              }
-                           ]
-                        },
+                        "PNGFormat.ec",
                         {
                            "FileName" : "RGBFormat.ec",
                            "Configurations" : [
@@ -996,6 +980,18 @@ from wherever you obtained them.
                                        "Options" : {
                                           "ExcludeFromBuild" : false
                                        }
+                                    },
+                                    {
+                                       "Name" : "Static",
+                                       "Options" : {
+                                          "ExcludeFromBuild" : false
+                                       }
+                                    },
+                                    {
+                                       "Name" : "Emscripten",
+                                       "Options" : {
+                                          "ExcludeFromBuild" : false
+                                       }
                                     }
                                  ]
                               },
@@ -1037,6 +1033,18 @@ from wherever you obtained them.
                                        "Options" : {
                                           "ExcludeFromBuild" : false
                                        }
+                                    },
+                                    {
+                                       "Name" : "Static",
+                                       "Options" : {
+                                          "ExcludeFromBuild" : false
+                                       }
+                                    },
+                                    {
+                                       "Name" : "Emscripten",
+                                       "Options" : {
+                                          "ExcludeFromBuild" : false
+                                       }
                                     }
                                  ]
                               },
@@ -1090,6 +1098,18 @@ from wherever you obtained them.
                                        "Options" : {
                                           "ExcludeFromBuild" : false
                                        }
+                                    },
+                                    {
+                                       "Name" : "Static",
+                                       "Options" : {
+                                          "ExcludeFromBuild" : false
+                                       }
+                                    },
+                                    {
+                                       "Name" : "Emscripten",
+                                       "Options" : {
+                                          "ExcludeFromBuild" : false
+                                       }
                                     }
                                  ]
                               },
@@ -1131,6 +1151,18 @@ from wherever you obtained them.
                                        "Options" : {
                                           "ExcludeFromBuild" : false
                                        }
+                                    },
+                                    {
+                                       "Name" : "Static",
+                                       "Options" : {
+                                          "ExcludeFromBuild" : false
+                                       }
+                                    },
+                                    {
+                                       "Name" : "Emscripten",
+                                       "Options" : {
+                                          "ExcludeFromBuild" : false
+                                       }
                                     }
                                  ]
                               },
@@ -1166,6 +1198,12 @@ from wherever you obtained them.
                                        "Options" : {
                                           "ExcludeFromBuild" : false
                                        }
+                                    },
+                                    {
+                                       "Name" : "Static",
+                                       "Options" : {
+                                          "ExcludeFromBuild" : false
+                                       }
                                     }
                                  ]
                               },
@@ -1820,6 +1858,17 @@ from wherever you obtained them.
                                        }
                                     }
                                  ]
+                              },
+                              {
+                                 "Name" : "Emscripten",
+                                 "Platforms" : [
+                                    {
+                                       "Name" : "linux",
+                                       "Options" : {
+                                          "ExcludeFromBuild" : true
+                                       }
+                                    }
+                                 ]
                               }
                            ]
                         },
@@ -2028,6 +2077,17 @@ from wherever you obtained them.
                                        }
                                     }
                                  ]
+                              },
+                              {
+                                 "Name" : "Emscripten",
+                                 "Platforms" : [
+                                    {
+                                       "Name" : "linux",
+                                       "Options" : {
+                                          "ExcludeFromBuild" : true
+                                       }
+                                    }
+                                 ]
                               }
                            ]
                         },
@@ -2162,6 +2222,17 @@ from wherever you obtained them.
                                        }
                                     }
                                  ]
+                              },
+                              {
+                                 "Name" : "Emscripten",
+                                 "Platforms" : [
+                                    {
+                                       "Name" : "linux",
+                                       "Options" : {
+                                          "ExcludeFromBuild" : true
+                                       }
+                                    }
+                                 ]
                               }
                            ]
                         },
@@ -2186,7 +2257,8 @@ from wherever you obtained them.
                                  }
                               }
                            ]
-                        }
+                        },
+                        "test_html5.c"
                      ],
                      "Options" : {
                         "ExcludeFromBuild" : true
index 4acac15..5019133 100644 (file)
@@ -1,3 +1,5 @@
+#define _Noreturn
+
 namespace sys;
 
 #define set _set
@@ -9,7 +11,7 @@ default:
 #undef __BLOCKS__
 #include <stdlib.h>
 #if !defined(ECERE_BOOTSTRAP) // quick fix for now
-#if defined(__WIN32__) && !defined(__EMSCRIPTEN__)
+#if defined(__WIN32__)
 #define WIN32_LEAN_AND_MEAN
 #define String _String
 #include <windows.h>
index 56a41be..992af78 100644 (file)
@@ -1,3 +1,5 @@
+#define _Noreturn
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
@@ -24,7 +26,7 @@
 #undef bool
 #endif
 
-#if defined(__WIN32__) && !defined(__EMSCRIPTEN__)
+#if defined(__WIN32__)
 #define WIN32_LEAN_AND_MEAN
 #define UNICODE
 #include <windows.h>
@@ -54,14 +56,14 @@ typedef unsigned long long uint64;
 __declspec(dllexport) int isblank(int c) { return c == '\t' || c == ' '; }
 #endif
 
-#if defined(__WIN32__) && !defined(__EMSCRIPTEN__)
+#if defined(__WIN32__)
 intptr_t stdinHandle, stdoutHandle;
 int osfStdin, osfStdout;
 FILE * fStdIn, * fStdOut;
 #endif
 
 FILE *eC_stdin(void)  {
-#if defined(__WIN32__) && !defined(__EMSCRIPTEN__)
+#if defined(__WIN32__)
    if(!fStdIn)
    {
       stdinHandle = (intptr_t)GetStdHandle(STD_INPUT_HANDLE);
@@ -137,7 +139,7 @@ extern struct __ecereNameSpace__ecere__com__Instance * __thisModule;
 
 typedef enum { unknown, win32, tux, apple } Platform;
 
-#if defined(__WIN32__) && !defined(__EMSCRIPTEN__)
+#if defined(__WIN32__)
 Platform runtimePlatform = win32;
 #elif defined(__APPLE__)
 Platform runtimePlatform = apple;
@@ -190,7 +192,7 @@ static bool DualPipe_GetLine(FILE * p, char *s, int max)
 
 bool Instance_LocateModule(const char * name, char * fileName)
 {
-#if defined(__WIN32__) && !defined(__EMSCRIPTEN__)
+#if defined(__WIN32__)
    HMODULE hModule = null;
    if(name && name[0])
    {
@@ -404,11 +406,11 @@ bool Instance_LocateModule(const char * name, char * fileName)
 
 void Instance_COM_Initialize(int argc, char ** argv, char ** parsedCommand, int * argcPtr, const char *** argvPtr)
 {
-#if !defined(__WIN32__) && !defined(__EMSCRIPTEN__) && !defined(ECERE_BOOTSTRAP)
+#if !defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
    // Disable stdout buffering on Unix
    setvbuf(stdout, null, _IONBF, 0);
 #endif
-#if defined(__WIN32__) && !defined(__EMSCRIPTEN__)
+#if defined(__WIN32__)
    *parsedCommand = UTF16toUTF8(GetCommandLineW());
    *argvPtr = eSystem_New0(sizeof(char *) * 512);
    *argcPtr = Tokenize(*parsedCommand, 512,(void*)(char **)(*argvPtr), forArgsPassing);
@@ -439,7 +441,7 @@ void * Instance_Module_Load(const char * libLocation, const char * name, void **
    *Load = null;
    *Unload = null;
 
-#if defined(__WIN32__) && !defined(__EMSCRIPTEN__)
+#if defined(__WIN32__)
    strcpy(fileName, name);
    GetExtension(fileName, extension);
    if(!extension[0])
@@ -559,7 +561,7 @@ void * Instance_Module_Load(const char * libLocation, const char * name, void **
 
 void Instance_Module_Free(void * library)
 {
-#if defined(__WIN32__) && !defined(__EMSCRIPTEN__)
+#if defined(__WIN32__)
    if(library)
       FreeLibrary(library);
 #elif (defined(__unix__) || defined(__APPLE__)) && !defined(__EMSCRIPTEN__)
index 5822739..fc0a8cf 100644 (file)
@@ -1,3 +1,5 @@
+#define _Noreturn
+
 namespace com;
 
 // #define DISABLE_MEMMGR
@@ -22,6 +24,10 @@ import "Mutex"
 #endif
 #endif
 
+#if defined(__EMSCRIPTEN__)
+#define GetCurrentThreadID()  0
+#endif
+
 // #define MEMINFO
 /*
 #ifdef MEMINFO
@@ -1162,6 +1168,7 @@ static uint log1_5i(uint number)
          break;
       current = current * 3 / 2;
       if(current == 1) current = 2;
+      if(current & 7) current += 8 - (current & 7);
    }
    return pos;
 }
@@ -1174,6 +1181,7 @@ static uint pow1_5(uint number)
    {
       current = current * 3 / 2;
       if(current == 1) current = 2;
+      if(current & 7) current += 8 - (current & 7);
    }
    return (uint)current;
 }
@@ -1189,6 +1197,7 @@ static uint pow1_5i(uint number)
          return (uint)current;
       current = current * 3 / 2;
       if(current == 1) current = 2;
+      if(current & 7) current += 8 - (current & 7);
    }
    return (uint)current;
 }
@@ -1435,7 +1444,7 @@ static void * _malloc(unsigned int size)
    void * pointer;
 
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
    memMutex.Wait();
 #endif
 
@@ -1462,7 +1471,9 @@ static void * _malloc(unsigned int size)
                printf("      %s\n", stack.frames[c]);
 
          memoryErrorsCount++;
+#if !defined(__EMSCRIPTEN__)
          memMutex.Release();
+#endif
          return null;
       }
 
@@ -1477,7 +1488,7 @@ static void * _malloc(unsigned int size)
    }
 #endif
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
    memMutex.Release();
 #endif
 
@@ -1500,7 +1511,7 @@ static void * _calloc(int n, unsigned int size)
 #else
    void * pointer;
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
    memMutex.Wait();
 #endif
 
@@ -1525,7 +1536,9 @@ static void * _calloc(int n, unsigned int size)
             if(stack.frames[c])
                printf("      %s\n", stack.frames[c]);
          memoryErrorsCount++;
+#if !defined(__EMSCRIPTEN__)
          memMutex.Release();
+#endif
          return null;
       }
 
@@ -1542,7 +1555,7 @@ static void * _calloc(int n, unsigned int size)
    }
 #endif
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
    memMutex.Release();
 #endif
 
@@ -1566,7 +1579,7 @@ static void * _realloc(void * pointer, unsigned int size)
 #else
    if(!size) { _free(pointer); return null; }
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
    memMutex.Wait();
 #endif
 
@@ -1608,7 +1621,9 @@ static void * _realloc(void * pointer, unsigned int size)
          if(stack.frames[c])
             printf("      %s\n", stack.frames[c]);
       memoryErrorsCount++;
+#if !defined(__EMSCRIPTEN__)
       memMutex.Release();
+#endif
       return null;
    }
    memset(pointer, 0xAB, REDZONE);
@@ -1649,7 +1664,7 @@ static void * _realloc(void * pointer, unsigned int size)
    pointer = realloc(pointer, size);
 #endif
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
    memMutex.Release();
 #endif
    return pointer ? ((byte *)pointer + REDZONE) : null;
@@ -1670,7 +1685,7 @@ static void * _crealloc(void * pointer, unsigned int size)
 #else
    if(!size) { _free(pointer); return null; }
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
    memMutex.Wait();
 #endif
 
@@ -1712,7 +1727,9 @@ static void * _crealloc(void * pointer, unsigned int size)
          if(stack.frames[c])
             printf("      %s\n", stack.frames[c]);
       memoryErrorsCount++;
+#if !defined(__EMSCRIPTEN__)
       memMutex.Release();
+#endif
       return null;
    }
    memset(pointer, 0xAB, REDZONE);
@@ -1753,7 +1770,7 @@ static void * _crealloc(void * pointer, unsigned int size)
    pointer = crealloc(pointer, size);
 #endif
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
    memMutex.Release();
 #endif
    return pointer ? ((byte *)pointer + REDZONE) : null;
@@ -1767,7 +1784,7 @@ static void _free(void * pointer)
 #if defined(DISABLE_MEMMGR) && !defined(MEMINFO)
       free(pointer);
 #else
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
       if(memMutex != pointer) memMutex.Wait();
 #endif
 
@@ -1871,7 +1888,7 @@ static void _free(void * pointer)
       free(pointer);
 #endif
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
       if(memMutex != pointer) memMutex.Release();
 #endif
 
@@ -3433,7 +3450,12 @@ static void CopyTemplateArg(ClassTemplateParameter param, ClassTemplateArgument
    switch(param.type)
    {
       case type:
-         arg.dataTypeString = CopyString(arg.dataTypeString);
+         // TOFIX: Memory leak here on e.g. registering 'ecere::com::AVLNode<AT>' from ComputeClassParameters(
+         /*
+         if(arg.dataTypeString && !strcmp(arg.dataTypeString, "ecere::com::AVLNode<AT>"))
+            ;
+         else*/
+            arg.dataTypeString = CopyString(arg.dataTypeString);
          break;
       case expression:
 
@@ -4584,7 +4606,9 @@ public dllexport void * eInstance_New(Class _class)
 #ifdef MEMINFO
 
 #undef malloc
+#if !defined(__EMSCRIPTEN__)
    memMutex.Wait();
+#endif
       //allocateClass = _class;
       allocateClass = malloc(strlen(_class.name)+1);
       allocateInternal = _class.module == __thisModule;
@@ -4613,8 +4637,10 @@ public dllexport void * eInstance_New(Class _class)
       }
 #ifdef MEMINFO
       allocateClass = null;
+#if !defined(__EMSCRIPTEN__)
    memMutex.Release();
 #endif
+#endif
 
 #if defined(_DEBUG) && !defined(MEMINFO) && defined(MEMTRACKING)
       {
@@ -7305,7 +7331,9 @@ public void queryMemInfo(char * string)
 
    blocksByClass.Free();
    sizeByClass.Free();
+#if !defined(__EMSCRIPTEN__)
    memMutex.Wait();
+#endif
    for(p = 0; pools && p < NUM_POOLS; p++)
    {
       BlockPool * pool = &pools[p];
@@ -7317,7 +7345,9 @@ public void queryMemInfo(char * string)
          sizeByClass[c] += block.size;
       }
    }
+#if !defined(__EMSCRIPTEN__)
    memMutex.Release();
+#endif
 
    //for(c : blocksByClass)
    {
index 23306a7..aa429cf 100644 (file)
@@ -487,7 +487,7 @@ static bool FindMaterialAndType(Mesh mesh, Material material, PrimitiveGroupType
    return false;
 }
 
-public class Object
+public class Object : struct
 {
 public:
    void SetMinMaxRadius(bool processMesh)
index 0733bcc..2abdefa 100644 (file)
@@ -2,7 +2,15 @@ namespace gfx3D::models;
 
 import "Object"
 
-#if !defined(_GLES)
+#if defined(__EMSCRIPTEN__)
+#define ES2
+#endif
+
+#if defined(__ANDROID__) || defined(__ODROID__)
+#define ES1_1
+#endif
+
+#if !defined(ES1_1) && !defined(ES2)
 #define USE_32_BIT_INDICES true
 #define indicesMember indices32
 #define uintindex uint32
index 2f0b541..b2af519 100644 (file)
@@ -1127,7 +1127,7 @@ private:
 };
 
 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
-private class Display3D
+private class Display3D : struct
 {
    // 3D Display
    int nTriangles;
index 963398f..8e17ff9 100644 (file)
@@ -1,5 +1,6 @@
 namespace gfx::bitmaps;
 
+#define _Noreturn
 import "Display"
 
 #include <setjmp.h>
index 95e596e..ce39a50 100644 (file)
@@ -1,8 +1,8 @@
 namespace gfx::bitmaps;
 
-import "Display"
+#define _Noreturn
 
-#if !defined(__EMSCRIPTEN__)
+import "Display"
 
 #define uint _uint
 #include "png.h"
@@ -309,5 +309,3 @@ class PNGFormat : BitmapFormat
       return result;
    }
 }
-
-#endif // !defined(__EMSCRIPTEN__)
index 9d7baaa..cb3ef14 100644 (file)
@@ -1,3 +1,5 @@
+#define _Noreturn
+
 namespace gfx::drivers;
 
 #if (defined(ECERE_VANILLA) || defined(ECERE_ONEDRIVER)) && defined(__WIN32__)
index 8313c0b..0217e8f 100644 (file)
@@ -1,9 +1,9 @@
 namespace gfx::drivers;
 
 #if defined(_GLES)
-#define ES1_1
+   #define ES1_1
 #else
- #define SHADERS
  #define SHADERS
 #endif
 
 #define GL_BGRA_EXT  0x80E1
@@ -47,12 +47,11 @@ import "shading"
 // #define USEPBUFFER
 #if defined(__unix__) || defined(__APPLE__)
 
-#if !defined(__MINGW32__)
-   #define GL_GLEXT_PROTOTYPES
-#endif
-
-#define pointer _pointer
+   #if !defined(__MINGW32__)
+      #define GL_GLEXT_PROTOTYPES
+   #endif
 
+   #define pointer _pointer
 
    #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
 
@@ -95,97 +94,91 @@ import "shading"
 #endif
 
 #if defined(__APPLE__)
-#include <OpenGl/gl.h>
+   #include <OpenGl/gl.h>
 #endif
 
 #if defined(__WIN32__) || defined(__unix__) || defined(__APPLE__)
 
-#if defined(__WIN32__)
-   //#define WIN32_LEAN_AND_MEAN
-   #undef _WIN32_WINNT
-   #define _WIN32_WINNT 0x0502
-   #define String Sting_
-   #include <windows.h>
-   #undef String
-#endif
+   #if defined(__WIN32__)
+      //#define WIN32_LEAN_AND_MEAN
+      #undef _WIN32_WINNT
+      #define _WIN32_WINNT 0x0502
+      #define String Sting_
+      #include <windows.h>
+      #undef String
+   #endif
 
-#if defined(__ANDROID__) || defined(__ODROID__)
+   #if defined(__ANDROID__) || defined(__ODROID__)
+      #if defined(__ODROID__) && !defined(ES1_1)
+         #define ES1_1
+      #endif
 
-#define uint _uint
-#define property _property
-#define new _new
-#define class _class
-#define Window    X11Window
-#define Cursor    X11Cursor
-#define Font      X11Font
-#define Display   X11Display
-#define Time      X11Time
-#define KeyCode   X11KeyCode
-#define Picture   X11Picture
-#define Bool      X11Bool
-
-   #include <GLES/gl.h>
-
-#undef Bool
-#undef Picture
-#undef Window
-#undef Cursor
-#undef Font
-#undef Display
-#undef Time
-#undef KeyCode
-#undef uint
-#undef new
-#undef property
-#undef class
+      #define uint _uint
+      #define property _property
+      #define new _new
+      #define class _class
+      #define Window    X11Window
+      #define Cursor    X11Cursor
+      #define Font      X11Font
+      #define Display   X11Display
+      #define Time      X11Time
+      #define KeyCode   X11KeyCode
+      #define Picture   X11Picture
+      #define Bool      X11Bool
 
-#elif defined(__EMSCRIPTEN__)
+      #include <GLES/gl.h>
 
-   #define property _property
-   #define uint _uint
+      #undef Bool
+      #undef Picture
+      #undef Window
+      #undef Cursor
+      #undef Font
+      #undef Display
+      #undef Time
+      #undef KeyCode
+      #undef uint
+      #undef new
+      #undef property
+      #undef class
 
-   #include <GL/gl.h>
+   #elif defined(__EMSCRIPTEN__)
+      #define ES2
+      // #define ES1_1
 
-   //#include <GLES/gl.h>
-   //#include <GLES2/gl.h>
-   #include <GL/glfw.h>
-   #include <emscripten/emscripten.h>
+      #define property _property
+      #define uint _uint
 
-   #undef property
-   #undef uint
+      //#include <GL/gl.h>
+      //#include <GLES/gl.h>
+      #include <GLES2/gl2.h>
 
-#else
-   #include <GL/gl.h>
-#endif
+      #include <emscripten/emscripten.h>
+      #include <emscripten/html5.h>
 
-#if defined(__ODROID__) && !defined(ES1_1)
-#define ES1_1
-#endif
+      #undef property
+      #undef uint
 
-#if defined(__EMSCRIPTEN__)
-#define EM_MODE
-// #define ES1_1
-#endif
+   #else
+      #include <GL/gl.h>
+   #endif
 
-//#define EM_MODE
+   #undef pointer
 
-#undef pointer
+   import "Display"
 
-import "Display"
+   #if defined(__unix__) || defined(__APPLE__)
 
-#if defined(__unix__) || defined(__APPLE__)
+      #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
+      import "XInterface"
+      #endif
 
-   #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
-   import "XInterface"
    #endif
 
-#endif
-
-#define glLoadMatrix glLoadMatrixd
-#define glMultMatrix glMultMatrixd
-#define glGetMatrix  glGetDoublev
-#define glTranslate glTranslated
-#define glScale glScaled
+   #define glLoadMatrix glLoadMatrixd
+   #define glMultMatrix glMultMatrixd
+   #define glGetMatrix  glGetDoublev
+   #define glTranslate glTranslated
+   #define glScale glScaled
 
 /*
 #define glVertex3v glVertex3dv
@@ -247,11 +240,16 @@ import "Display"
    static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = null;
    static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = null;
 
-#elif defined(__ANDROID__) || defined(__ODROID__)
+#else
 
+#if defined(__ANDROID__) || defined(__ODROID__)
    #define GL_FRAMEBUFFER           GL_FRAMEBUFFER_OES
    #define GL_RENDERBUFFER          GL_RENDERBUFFER_OES
    #define GL_COLOR_ATTACHMENT0     GL_COLOR_ATTACHMENT0_OES
+   #define GL_BGRA_EXT           0
+#endif
+
+#if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
 
    #define GL_POLYGON_STIPPLE 0xFFFF
    #define GL_LINE_STIPPLE 0xFFFF
@@ -270,7 +268,6 @@ import "Display"
    //#define GL_FILL               0
    //#define GL_LINE               0
    //#define GL_LINE_STIPPLE       0
-   #define GL_BGRA_EXT           0
    #define GL_UNPACK_ROW_LENGTH  0
    #define GL_UNPACK_SKIP_PIXELS 0
    #define GL_UNPACK_SKIP_ROWS   0
@@ -278,6 +275,7 @@ import "Display"
    #define GL_PACK_ROW_LENGTH    0
    #define GL_PACK_SKIP_ROWS     0
    #define GL_PACK_SKIP_PIXELS   0
+#endif
 
 #endif
 
@@ -290,14 +288,16 @@ import "Display"
    #define glGenRenderbuffers       glGenRenderbuffersOES
    #define glDeleteFramebuffers     glDeleteFramebuffersOES
    #define glDeleteRenderbuffers    glDeleteRenderbuffersOES
+#endif
 
+#if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
    #define GL_INT                                  0x1404
    #define GL_UNSIGNED_INT                         0x1405
    #define GL_DOUBLE                               0x140A
    #define APIENTRY
 #endif
 
-#if defined(ES1_1) || defined(SHADERS)
+#if defined(ES1_1) || defined(ES2) || defined(SHADERS)
 
    #undef glRecti
    #undef glBegin
@@ -381,7 +381,7 @@ public void glesColorMaterial(int a, int b)
 }
 
 static GLuint stippleTexture;
-#if defined(ES1_1) || defined(SHADERS) || defined(EM_MODE)
+#if defined(ES1_1) || defined(ES2) || defined(SHADERS)
 static bool stippleEnabled;
 #endif
 
@@ -415,14 +415,17 @@ public void glesLineStipple( int i, unsigned short j )
 
 public void glesLightModeli( unsigned int pname, int param )
 {
-#if !defined(EM_MODE) && !defined(SHADERS)
+#if !defined(SHADERS)
    if(pname == GL_LIGHT_MODEL_TWO_SIDE)
       glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, param);
 #endif
 }
 
-#if defined(__ANDROID__) || defined(__ODROID__)
+#if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
 void glClearDepth( double depth ) { glClearDepthf((float)depth); }
+#endif
+
+#if defined(__ANDROID__) || defined(__ODROID__)
 void glFogi( unsigned int pname, int param ) { }
 void glPolygonMode( unsigned int i, unsigned int j ) { }
 
@@ -448,7 +451,14 @@ void glDrawPixels(int a, int b, int c, int d, void * e) { }
 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
 static int primitiveTypes[RenderPrimitiveType] =
 {
-   GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GLIMTKMode::quads, GLIMTKMode::quadStrip, GL_LINE_STRIP
+   GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN,
+#if defined(SHADERS) || defined(ES1_1) || defined(ES2)
+   GL_TRIANGLE_FAN,     // NOTE: This will only work for single quads
+#else
+   GLIMTKMode::quads,
+#endif
+   GLIMTKMode::quadStrip,
+   GL_LINE_STRIP
 };
 #endif
 
@@ -465,7 +475,7 @@ public void GLSetupFog(bool enable)
 {
 #ifdef SHADERS
    shader_fog(enable);
-#elif !defined(EM_MODE)
+#else
    (enable ? glEnable : glDisable)(GL_FOG);
 #endif
 }
@@ -474,14 +484,14 @@ public void GLSetupLighting(bool enable)
 {
 #if defined(SHADERS)
    shader_lighting(enable);
-#elif !defined(EM_MODE)
+#else
    (enable ? glEnable : glDisable)(GL_LIGHTING);
 #endif
 }
 
 // Non OpenGL ES friendly stuff
 
-#if defined(ES1_1)
+#if defined(ES1_1) || defined(ES2)
 
 //#undef GL_UNSIGNED_INT
 //#undef GL_DOUBLE
@@ -588,7 +598,9 @@ class OGLSystem : struct
    HDC hdc;
    HGLRC glrc;
    HWND hwnd;
-#elif !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
+#elif defined(__EMSCRIPTEN__)
+   EMSCRIPTEN_WEBGL_CONTEXT_HANDLE glc;
+#elif !defined(__ANDROID__) && !defined(__ODROID__)
    XVisualInfo * visualInfo;
    GLXContext glContext;
    GLXDrawable glxDrawable;
@@ -625,14 +637,16 @@ class OGLIndices : struct
 int current;
 void * previous;
 
+#if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
+#ifdef _DEBUG
 static void setupDebugging()
 {
-#ifdef _DEBUG
    if(glDebugMessageCallback)
    {
       GLuint unusedIds = 0;
 
       glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+      /*
       glDebugMessageCallback(openglCallbackFunction, null);
       glDebugMessageControl(GL_DONT_CARE,
           GL_DONT_CARE,
@@ -640,9 +654,11 @@ static void setupDebugging()
           0,
           &unusedIds,
           GL_TRUE);
+      */
    }
-#endif
 }
+#endif
+#endif
 
 #if defined(__WIN32__)
 static HGLRC winCreateContext(HDC hdc)
@@ -670,7 +686,10 @@ class OpenGLDisplayDriver : DisplayDriver
 
    bool LockSystem(DisplaySystem displaySystem)
    {
-#if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
+#if defined(__EMSCRIPTEN__)
+      OGLSystem oglSystem = displaySystem.driverData;
+      emscripten_webgl_make_context_current(oglSystem.glc);
+#elif !defined(__ANDROID__) && !defined(__ODROID__)
       OGLSystem oglSystem = displaySystem.driverData;
       if(useSingleGLContext) return true;
    #if defined(__WIN32__)
@@ -798,8 +817,7 @@ class OpenGLDisplayDriver : DisplayDriver
    void ::CheckExtensions(OGLSystem oglSystem)
    {
       const char * extensions = (const char *)glGetString(GL_EXTENSIONS);
-      if(extensions)
-         oglSystem.pow2textures = strstr(extensions, "GL_ARB_texture_non_power_of_two") ? false : true;
+      oglSystem.pow2textures = (extensions && strstr(extensions, "GL_ARB_texture_non_power_of_two")) ? false : true;
       glGetIntegerv(GL_MAX_TEXTURE_SIZE, &oglSystem.maxTextureSize);
    }
 
@@ -966,19 +984,35 @@ class OpenGLDisplayDriver : DisplayDriver
 
          result = true;
       #elif defined(__EMSCRIPTEN__)
-         if(glfwInit() == GL_TRUE)
          {
-            const int width = 640, height = 480;
-            if(glfwOpenWindow(width, height, 8, 8, 8, 8, 16, 0, GLFW_WINDOW) == GL_TRUE)
-            {
-               //glfwSwapBuffers();
+            EmscriptenWebGLContextAttributes attribs = { 0 };
+            attribs.depth = 1;
+            attribs.antialias = 1;
+
+            /*
+              EM_BOOL alpha;
+              EM_BOOL depth;
+              EM_BOOL stencil;
+              EM_BOOL antialias;
+              EM_BOOL premultipliedAlpha;
+              EM_BOOL preserveDrawingBuffer;
+              EM_BOOL preferLowPowerToHighPerformance;
+              EM_BOOL failIfMajorPerformanceCaveat;
+              int majorVersion;
+              int minorVersion;
+              EM_BOOL enableExtensionsByDefault;
+              */
+
+            emscripten_webgl_init_context_attributes(&attribs);
+            oglSystem.pow2textures = true;
+            oglSystem.maxTextureSize = 16384;
+            oglSystem.glc = emscripten_webgl_create_context("canvas", &attribs);
+            if(emscripten_webgl_make_context_current(oglSystem.glc) == EMSCRIPTEN_RESULT_SUCCESS)
                result = true;
-            }
-            else
-               printf("glfwOpenWindow() failed\n"); //glfwTerminate();
+
+            /*glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+            glEnable(GL_BLEND);*/
          }
-         else
-            printf("glfwInit() failed\n"); //glfwTerminate();
       #else
       {
          X11Window root = RootWindow( xGlobalDisplay, DefaultScreen( xGlobalDisplay ) );
@@ -1035,6 +1069,8 @@ class OpenGLDisplayDriver : DisplayDriver
          stippleTexture = 0;
       }
 
+      glimtkTerminate();
+
    #if defined(__WIN32__)
       wglMakeCurrent( null, null );
 
@@ -1049,7 +1085,7 @@ class OpenGLDisplayDriver : DisplayDriver
       #if defined(__ANDROID__) || defined(__ODROID__)
          egl_term_display();
       #elif defined(__EMSCRIPTEN__)
-         glfwTerminate();
+         emscripten_webgl_destroy_context(oglSystem.glc);
       #else
       if(oglSystem.visualInfo)
       {
@@ -1074,7 +1110,7 @@ class OpenGLDisplayDriver : DisplayDriver
    {
       bool result = false;
       OGLDisplay oglDisplay = display.driverData;
-#if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
+#if !defined(__ANDROID__) && !defined(__ODROID__)
       OGLSystem oglSystem = display.displaySystem.driverData;
 #endif
 
@@ -1086,7 +1122,7 @@ class OpenGLDisplayDriver : DisplayDriver
       if(!display.alphaBlend)
 #endif
       {
-   #if defined(__WIN32__)
+#if defined(__WIN32__)
          oglDisplay.hdc = GetDC(display.window);
          SetPixelFormat(oglDisplay.hdc, oglSystem.format, &oglSystem.pfd);
          if((oglDisplay.glrc = winCreateContext(oglDisplay.hdc)))
@@ -1097,9 +1133,10 @@ class OpenGLDisplayDriver : DisplayDriver
          }
          else
             ReleaseDC(display.window, oglDisplay.hdc);
-   #elif defined(__unix__) || defined(__APPLE__)
-      #if defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__ODROID__)
-      #else
+#elif defined(__unix__) || defined(__APPLE__)
+#  if defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__ODROID__)
+         result = true;
+#  else
          XVisualInfo * visualInfo = ((XWindowData)display.windowDriverData).visual;
          /*
 #if defined(__APPLE__)
@@ -1133,8 +1170,8 @@ class OpenGLDisplayDriver : DisplayDriver
             glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext);
             result = true;
          }
-      #endif
-   #endif
+#  endif
+#endif
       }
 #if defined(__WIN32__) || defined(USEPBUFFER)
       else
@@ -1146,11 +1183,18 @@ class OpenGLDisplayDriver : DisplayDriver
          ogl_LoadFunctions();
          CheckExtensions(oglSystem);
          vboAvailable = glBindBuffer != null;
+#  ifdef _DEBUG
          setupDebugging();
+#  endif
 #endif
-         #ifdef SHADERS
+
+#if defined(__EMSCRIPTEN__)
+         emscripten_webgl_make_context_current(oglSystem.glc);
+#endif
+
+#ifdef SHADERS
          loadShaders("<:ecere>shaders/fixed.vertex", "<:ecere>shaders/fixed.frag");
-         #endif
+#endif
          glEnableClientState(GL_VERTEX_ARRAY);
          GLABBindBuffer(GL_ARRAY_BUFFER, 0);
          GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
@@ -1171,7 +1215,7 @@ class OpenGLDisplayDriver : DisplayDriver
          // glTranslatef(0.375f, 0.375f, 0.0f);
          // glTranslatef(-0.625f, -0.625f, 0.0f);
          glMatrixMode(MatrixMode::projection);
-#if !defined(EM_MODE) && !defined(SHADERS)
+#if !defined(SHADERS)
          glShadeModel(GL_FLAT);
 
          // #define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
@@ -1184,7 +1228,9 @@ class OpenGLDisplayDriver : DisplayDriver
 #endif
          glDepthFunc(GL_LESS);
          glClearDepth(1.0);
+#if !defined(__EMSCRIPTEN__)
          glDisable(GL_MULTISAMPLE_ARB);
+#endif
       }
 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
       display.ambient = Color { 50,50,50 };
@@ -1542,9 +1588,11 @@ class OpenGLDisplayDriver : DisplayDriver
 #if defined(__WIN32__)
          wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
 #elif defined(__unix__) || defined(__APPLE__)
-      #if defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__ODROID__)
+      #if defined(__ANDROID__) || defined(__ODROID__)
          width = eglWidth;
          height = eglHeight;
+      #elif defined(__EMSCRIPTEN__)
+         emscripten_webgl_make_context_current(oglSystem.glc);
       #else
          glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext);
       #endif
@@ -1573,7 +1621,7 @@ class OpenGLDisplayDriver : DisplayDriver
       {
          oglDisplay.flipBufW = width;
          oglDisplay.flipBufH = height;
-#ifdef ES1_1
+#if defined(ES1_1) || defined(ES2)
          result = true;
 #else
          oglDisplay.flippingBuffer = renew oglDisplay.flippingBuffer ColorAlpha [width * height];
@@ -1713,11 +1761,11 @@ class OpenGLDisplayDriver : DisplayDriver
 #if defined(__WIN32__)
          //wglSwapLayerBuffers(oglDisplay.hdc,WGL_SWAP_MAIN_PLANE);
          SwapBuffers(oglDisplay.hdc);
+         //ecere::sys::Sleep(0.1);
 #elif defined(__unix__) || defined(__APPLE__)
       #if defined(__ANDROID__) || defined(__ODROID__)
          egl_swap_buffers();
       #elif defined(__EMSCRIPTEN__)
-         glfwSwapBuffers();
       #else
          glXSwapBuffers(xGlobalDisplay, (GLXDrawable)display.window);
       #endif
@@ -2112,7 +2160,7 @@ class OpenGLDisplayDriver : DisplayDriver
 
       glColor4fv(oglSurface.foreground);
       glBegin(GL_LINES);
-#if defined(ES1_1) || defined(EM_MODE) || defined(SHADERS)
+#if defined(ES1_1) || defined(ES2) || defined(SHADERS)
       if(stippleEnabled)
       {
          glTexCoord2f(0.5f, 0);
@@ -2145,7 +2193,7 @@ class OpenGLDisplayDriver : DisplayDriver
       //Logf("Rectangle\n");
 
       glColor4fv(oglSurface.foreground);
-#if defined(ES1_1) || defined(EM_MODE) || defined(SHADERS)
+#if defined(ES1_1) || defined(ES2) || defined(SHADERS)
       if(stippleEnabled)
       {
          glBegin(GL_LINES);
@@ -2195,17 +2243,8 @@ class OpenGLDisplayDriver : DisplayDriver
 
       glColor4fv(oglSurface.background);
 
-#ifdef EM_MODE
-      glBegin(GL_QUADS);
-      glVertex2f(x1+surface.offset.x, y1+surface.offset.y);
-      glVertex2f(x1+surface.offset.x, y2+surface.offset.y+1);
-      glVertex2f(x2+surface.offset.x+1, y2+surface.offset.y+1);
-      glVertex2f(x2+surface.offset.x+1, y1+surface.offset.y);
-      glEnd();
-#else
       glRecti(x1+surface.offset.x, y1+surface.offset.y,
               x2+surface.offset.x + 1, y2+surface.offset.y + 1);
-#endif
       /*
       glRectf(x1+surface.offset.x, y1+surface.offset.y,
               x2+surface.offset.x + 1, y2+surface.offset.y + 1);
@@ -2354,7 +2393,6 @@ class OpenGLDisplayDriver : DisplayDriver
 
    void StretchDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
    {
-#if !defined(EM_MODE)
       float s2dw,s2dh,d2sw,d2sh;
       //bool flipX = false, flipY = false;
 
@@ -2453,12 +2491,10 @@ class OpenGLDisplayDriver : DisplayDriver
          glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
          glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
       }
-#endif
    }
 
    void BlitDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h)
    {
-#if !defined(EM_MODE)
       //Logf("BlitDI\n");
 
       //Clip against the edges of the source
@@ -2521,7 +2557,6 @@ class OpenGLDisplayDriver : DisplayDriver
          glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
          glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
       }
-#endif
    }
 
    void FilterDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
@@ -2622,7 +2657,7 @@ class OpenGLDisplayDriver : DisplayDriver
 
       if(stipple)
       {
-#if defined(ES1_1) || defined(EM_MODE) || defined(SHADERS)
+#if defined(ES1_1) || defined(ES2) || defined(SHADERS)
          stippleEnabled = true;
          glesLineStipple(1, (uint16)stipple);
 #else
@@ -2632,7 +2667,7 @@ class OpenGLDisplayDriver : DisplayDriver
       }
       else
       {
-#if defined(ES1_1) || defined(EM_MODE) || defined(SHADERS)
+#if defined(ES1_1) || defined(ES2) || defined(SHADERS)
          stippleEnabled = false;
          glMatrixMode(GL_TEXTURE);
          glLoadIdentity();
@@ -2643,6 +2678,7 @@ class OpenGLDisplayDriver : DisplayDriver
 #endif
       }
    }
+
 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
    void SetRenderState(Display display, RenderState state, uint value)
    {
@@ -2652,13 +2688,15 @@ class OpenGLDisplayDriver : DisplayDriver
       switch(state)
       {
          case antiAlias:
+#ifndef __EMSCRIPTEN__
             if(value)
                glEnable(GL_MULTISAMPLE_ARB);
             else
                glDisable(GL_MULTISAMPLE_ARB);
+#endif
             break;
          case fillMode:
-#if !defined(ES1_1)
+#if !defined(ES1_1) && !defined(ES2)
             glPolygonMode(GL_FRONT_AND_BACK, ((FillModeValue)value == solid) ? GL_FILL : GL_LINE);
 #endif
             break;
@@ -2687,13 +2725,15 @@ class OpenGLDisplayDriver : DisplayDriver
 #endif
             break;
          case blend:
+//#if !defined(__EMSCRIPTEN__)
             if(value) glEnable(GL_BLEND); else glDisable(GL_BLEND);
+//#endif
             break;
          case ambient:
          {
 #if defined(SHADERS)
             shader_setGlobalAmbient(((Color)value).r / 255.0f, ((Color)value).g / 255.0f, ((Color)value).b / 255.0f, 1.0f);
-#elif !defined(EM_MODE)
+#else
             float ambient[4] = { ((Color)value).r/255.0f, ((Color)value).g/255.0f, ((Color)value).b/255.0f, 1.0f };
             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
 #endif
@@ -2718,7 +2758,7 @@ class OpenGLDisplayDriver : DisplayDriver
    {
 #if defined(SHADERS)
       shader_setLight(display, id, light);
-#elif !defined(EM_MODE)
+#else
       //Logf("SetLight\n");
 
       if(light != null)
@@ -2943,13 +2983,15 @@ class OpenGLDisplayDriver : DisplayDriver
          glEnable(GL_DEPTH_TEST);
 
          GLSetupLighting(true);
-#if !defined(EM_MODE) && !defined(SHADERS)
+#if !defined(SHADERS)
          glShadeModel(GL_SMOOTH);
 #endif
          glDepthMask((byte)bool::true);
          oglDisplay.depthWrite = true;
 
+#ifndef __EMSCRIPTEN__
          glEnable(GL_MULTISAMPLE_ARB);
+#endif
       }
       else if(display.display3D.camera)
       {
@@ -2960,17 +3002,22 @@ class OpenGLDisplayDriver : DisplayDriver
          glDisable(GL_CULL_FACE);
          glDisable(GL_DEPTH_TEST);
 
+
          GLSetupTexturing(false);
          GLSetupLighting(false);
          GLSetupFog(false);
 
          glDisableClientState(GL_COLOR_ARRAY);
 
-#if !defined(SHADERS) && !defined(EM_MODE)
+#if defined(SHADERS)
+         shader_setPerVertexColor(false);
+#else
          glShadeModel(GL_FLAT);
 #endif
          glEnable(GL_BLEND);
+#if !defined(__EMSCRIPTEN__)
          glDisable(GL_MULTISAMPLE_ARB);
+#endif
 
          // *** Restore 2D MODELVIEW Matrix ***
          glPopMatrix();
@@ -2989,14 +3036,14 @@ class OpenGLDisplayDriver : DisplayDriver
       // Basic Properties
       if(material.flags.doubleSided)
       {
-#if !defined(EM_MODE) && !defined(SHADERS)
+#if !defined(SHADERS)
          glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, !material.flags.singleSideLight);
 #endif
          glDisable(GL_CULL_FACE);
       }
       else
       {
-#if !defined(EM_MODE) && !defined(SHADERS)
+#if !defined(SHADERS)
          glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, bool::false);
 #endif
          glEnable(GL_CULL_FACE);
@@ -3034,8 +3081,6 @@ class OpenGLDisplayDriver : DisplayDriver
 
 #if defined(SHADERS)
       shader_setMaterial(material, mesh.flags.colors);
-#elif defined(EM_MODE)
-      glimtkColor4f(material.diffuse.r, material.diffuse.g, material.diffuse.b, material.opacity);
 #else
       if(mesh.flags.colors)
       {
@@ -3239,7 +3284,7 @@ class OpenGLDisplayDriver : DisplayDriver
    {
       if(vboAvailable)
       {
-#ifdef ES1_1
+#if defined(ES1_1) || defined(ES2)
          if(indices32bit)
          {
             if(!oglIndices.buffer.buffer)
@@ -3457,6 +3502,8 @@ IS_GLGetContext(DisplaySystem displaySystem)
 #elif defined(__ANDROID__) || defined(__ODROID__)
       return eglContext;
 #elif defined(__EMSCRIPTEN__)
+      OGLSystem system = displaySystem.driverData;
+      return (void *)system.glc;
 #else
       OGLSystem system = displaySystem.driverData;
       return system.glContext;
index 81a6d8f..01497c9 100644 (file)
@@ -2,7 +2,7 @@ namespace gfx::drivers;
 
 import "instance"
 
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX) && !defined(__EMSCRIPTEN__)
+#if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX)
 
 default:
 
@@ -21,10 +21,8 @@ default:
 
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
-#if !defined(__EMSCRIPTEN__)
 #include <X11/extensions/shape.h>
 #include <X11/extensions/Xrender.h>
-#endif
 #include <X11/extensions/XShm.h>
 #include <sys/ipc.h>
 #include <sys/shm.h>
index 0a8b92c..eeb66a2 100644 (file)
@@ -1,4 +1,6 @@
-#version 150
+#version 100
+
+precision highp float;
 
 uniform sampler2D diffuseTex;
 uniform bool texturingOn;
@@ -6,14 +8,20 @@ uniform bool lightingOn;
 uniform mat4 texture_matrix;
 uniform bool matTwoSided;
 
+/*
 in vec2 fTexCoord;
 in vec4 fColor;
 in vec4 fColorBack;
+*/
+
+varying vec2 fTexCoord;
+varying  vec4 fColor;
+varying  vec4 fColorBack;
 
-out vec4 fragColor;
+// out vec4 fragColor;
 
 void main(void)
 {
    vec4 c = (matTwoSided && lightingOn && !gl_FrontFacing) ? fColorBack : fColor;
-   fragColor = texturingOn ? c * texture(diffuseTex, (vec4(fTexCoord, 0, 1) * texture_matrix).xy) : c;
+   gl_FragColor = texturingOn ? c * texture2D(diffuseTex, (vec4(fTexCoord, 0, 1) * texture_matrix).xy) : c;
 }
index 62cf8f1..ae45459 100644 (file)
@@ -1,4 +1,4 @@
-#version 150
+#version 100
 
 uniform mat4 projection_matrix;
 uniform mat4 modelview_matrix;
@@ -30,6 +30,7 @@ uniform bool fogOn;
 uniform float fogDensity;
 uniform vec3 fogColor;
 
+/*
 in vec2 texCoord;
 in vec3 vertex;
 in vec3 normal;
@@ -38,22 +39,31 @@ in vec4 color;
 out vec2 fTexCoord;
 out vec4 fColor;
 out vec4 fColorBack;
+*/
+
+attribute vec2 texCoord;
+attribute vec3 vertex;
+attribute vec3 normal;
+attribute vec4 color;
+
+varying vec2 fTexCoord;
+varying vec4 fColor;
+varying vec4 fColorBack;
 
 void main(void)
 {
-   float f = 1;
-   vec3 n = normalize(mat3x3(modelview_matrix) * normal);
+   float f = 1.0;
+   vec3 n = normalize(mat3(modelview_matrix) * normal);
    vec4 pos = modelview_matrix * vec4(vertex, 1.0);
 
    gl_Position = projection_matrix * pos;
    fTexCoord = texCoord;
 
    if(fogOn)
-      f = clamp(exp(fogDensity * pos.z), 0, 1);
+      f = clamp(exp(fogDensity * pos.z), 0.0, 1.0);
 
    if(lightingOn)
    {
-      int i;
       vec3 diffuseColor = perVertexColor ? color.xyz : matDiffuse;
       vec3 ambientColor = perVertexColor ? color.xyz : matAmbient;
       float opacity = perVertexColor ? color.w : matOpacity;
@@ -65,12 +75,12 @@ void main(void)
       fColor = vec4(0);
       if(matTwoSided)
          fColorBack = vec4(0);
-      for(i = 0; i < 8; i++)
+      for(int i = 0; i < 8; i++)
          if(lightsOn[i])
          {
             vec4 l = lightsPos[i];
             float d = dot(n, l.xyz);
-            float pf = 0;
+            float pf = 0.0;
             vec3 VP = l.xyz;
             vec3 halfVector;
             if(matPower != 0.0)
@@ -78,7 +88,7 @@ void main(void)
                float nDotVP;
                VP = l.xyz;
                halfVector = normalize(VP + eye);
-               nDotVP = max(0, dot(n, VP));
+               nDotVP = max(0.0, dot(n, VP));
                if(nDotVP != 0.0)
                {
                   float nDotHV = max(0.0, dot(n, halfVector));
@@ -86,7 +96,7 @@ void main(void)
                }
             }
 
-            c += diffuseColor * min(1, max(0, d)) * lightsDiffuse[i];
+            c += diffuseColor * min(1.0, max(0.0, d)) * lightsDiffuse[i];
             c += matSpecular * pf * lightsSpecular[i];
             c += matAmbient * lightsAmbient[i];
 
@@ -96,7 +106,7 @@ void main(void)
                float d2 = dot(iN, l.xyz);
                if(matPower != 0.0)
                {
-                  float nDotVP = max(0, dot(iN, VP));
+                  float nDotVP = max(0.0, dot(iN, VP));
                   if(nDotVP != 0.0)
                   {
                      float nDotHV = max(0.0, dot(iN, halfVector));
@@ -104,7 +114,7 @@ void main(void)
                   }
                }
 
-               c2 += diffuseColor * min(1, max(0, d2)) * lightsDiffuse[i];
+               c2 += diffuseColor * min(1.0, max(0.0, d2)) * lightsDiffuse[i];
                c2 += matSpecular * pf * lightsSpecular[i];
                c2 += matAmbient * lightsAmbient[i];
             }
@@ -115,7 +125,7 @@ void main(void)
       fColor = vec4(c, opacity);
 
       if(fogOn)
-         fColor = f * fColor + (1-f) * vec4(fogColor, 1);
+         fColor = f * fColor + (1.0-f) * vec4(fogColor, 1);
 
       if(matTwoSided)
       {
@@ -124,14 +134,14 @@ void main(void)
          fColorBack = vec4(c2, opacity);
 
          if(fogOn)
-            fColorBack = f * fColorBack + (1-f) * vec4(fogColor, 1);
+            fColorBack = f * fColorBack + (1.0-f) * vec4(fogColor, 1);
       }
    }
    else
    {
-      fColor = current_color * color;
+      fColor = current_color * (perVertexColor ? color : vec4(1,1,1,1));
 
       if(fogOn)
-         fColor = f * fColor + (1-f) * vec4(fogColor, 1);
+         fColor = f * fColor + (1.0-f) * vec4(fogColor, 1);
    }
 }
index 63d449e..ef6fda3 100644 (file)
@@ -6,11 +6,18 @@
  #define SHADERS
 #endif
 
-#if defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__ODROID__)
+#if defined(__ANDROID__) || defined(__ODROID__)
    #include <GLES/gl.h>
 
    #define GL_INT    0x1404
    #define GL_DOUBLE 0x140A
+#elif defined(__EMSCRIPTEN__)
+   #include <GLES2/gl2.h>
+
+   #define ES2
+
+   #define GL_INT    0x1404
+   #define GL_DOUBLE 0x140A
 #else
 #  if defined(SHADERS)
 #     include "gl_core_3_3.h"
@@ -96,7 +103,7 @@ public struct GLAB
 
    void useVertTrans(uint count, int n, int type, uint stride, void * pointer)
    {
-#if defined(_GLES) || defined(ES1_1)
+#if defined(_GLES) || defined(ES1_1) || defined(ES2)
       if(glabCurArrayBuffer != ((this != null) ? buffer : 0))
          GLABBindBuffer(GL_ARRAY_BUFFER, ((this != null) ? buffer : 0));
       if(type == GL_INT)
@@ -132,7 +139,10 @@ public struct GLEAB
 
          if(glabCurElementBuffer != buffer)
             GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
-         glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);  //GL_DYNAMIC_DRAW);
+         if(size)
+            glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);  //GL_DYNAMIC_DRAW);
+         else
+            ;
       }
    }
 
@@ -149,7 +159,7 @@ public struct GLEAB
    {
       if(glabCurElementBuffer != ((this != null) ? buffer : 0))
          GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ((this != null) ? buffer : 0));
-#if defined(_GLES) || defined(ES1_1)
+#if defined(_GLES) || defined(ES1_1) || defined(ES2)
       type = GL_UNSIGNED_SHORT;
 #endif
       glDrawElements(primType, count, type, indices);
index c7ab495..cfbd0cc 100644 (file)
@@ -4,8 +4,10 @@
  #define SHADERS
 #endif
 
-#if defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__ODROID__)
+#if defined(__ANDROID__) || defined(__ODROID__)
    #include <GLES/gl.h>
+#elif defined(__EMSCRIPTEN__)
+   #include <GLES2/gl2.h>
 #else
 #  if defined(SHADERS)
 #     include "gl_core_3_3.h"
@@ -15,6 +17,7 @@
 #endif
 
 import "glab"
+import "shading"
 
 #ifdef SHADERS
 
@@ -151,6 +154,8 @@ public void glimtkVertex2f(float x, float y)
 public void glimtkVertex2i(int x, int y)         { glimtkVertex2f((float)x, (float)y); }
 public void glimtkVertex2d(double x, double y)   { glimtkVertex2f((float)x, (float)y); }
 
+GLAB streamVecAB, streamNorAB;
+
 public void glimtkEnd(void)
 {
    GLIMTKMode mode = beginMode;
@@ -159,20 +164,33 @@ public void glimtkEnd(void)
 
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 
-   noAB.use(texCoord, 2, GL_FLOAT, vertexStride * sizeof(float), vertexPointer);
+   streamVecAB.upload(vertexStride * sizeof(float) * vertexCount, vertexPointer);
+
+   streamVecAB.use(texCoord, 2, GL_FLOAT, vertexStride * sizeof(float), 0);
+   // noAB.use(texCoord, 2, GL_FLOAT, vertexStride * sizeof(float), vertexPointer);
 
    if(vertexColorValues)
    {
       glEnableClientState(GL_COLOR_ARRAY);
-      noAB.use(color, 4, GL_FLOAT, vertexStride * sizeof(float), vertexPointer + 2);
+      streamVecAB.use(color, 4, GL_FLOAT, vertexStride * sizeof(float), (void *)(2 * sizeof(float)));
+
+#ifdef SHADERS
+      shader_setPerVertexColor(true);
+#endif
+
+
+      //noAB.use(color, 4, GL_FLOAT, vertexStride * sizeof(float), vertexPointer + 2);
    }
 
-   noAB.use(vertex, numVertexCoords, GL_FLOAT, vertexStride * sizeof(float), vertexPointer + vertexOffset);
+   streamVecAB.use(vertex, numVertexCoords, GL_FLOAT, vertexStride * sizeof(float), (void *)(vertexOffset * sizeof(float)));
+   // noAB.use(vertex, numVertexCoords, GL_FLOAT, vertexStride * sizeof(float), vertexPointer + vertexOffset);
 
    if(normalCount && normalCount == vertexCount)
    {
       glEnableClientState(GL_NORMAL_ARRAY);
-      noAB.use(normal, 3, GL_FLOAT, 3*sizeof(float),normalPointer);
+      streamNorAB.upload(3*sizeof(float) * vertexCount, normalPointer);
+      streamNorAB.use(normal, 3, GL_FLOAT, 3*sizeof(float), 0);
+      // noAB.use(normal, 3, GL_FLOAT, 3*sizeof(float),normalPointer);
    }
 
    glDrawArrays(mode, 0, vertexCount);
@@ -180,7 +198,14 @@ public void glimtkEnd(void)
    if(normalCount)
       glDisableClientState(GL_NORMAL_ARRAY);
    if(vertexColorValues)
+   {
       glDisableClientState(GL_COLOR_ARRAY);
+
+#ifdef SHADERS
+      shader_setPerVertexColor(false);
+#endif
+
+   }
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 
    normalCount = 0;
index e408bd9..27a45c8 100644 (file)
@@ -4,8 +4,10 @@
  #define SHADERS
 #endif
 
-#if defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__ODROID__)
+#if defined(__ANDROID__) || defined(__ODROID__)
    #include <GLES/gl.h>
+#elif defined(__EMSCRIPTEN__)
+   #include <GLES2/gl2.h>
 #else
 #  if defined(SHADERS)
 #     include "gl_core_3_3.h"
@@ -15,6 +17,7 @@
 #endif
 
 import "Display"
+import "shading"
 
 #if defined(ECERE_NO3D) || defined(ECERE_VANILLA)
 public union Matrix
index 28ad774..f3eeefd 100644 (file)
@@ -1,5 +1,6 @@
 import "Display"
 import "matrixStack"
+import "glab"
 
 #ifndef _GLES
 #define SHADERS
@@ -7,11 +8,13 @@ import "matrixStack"
 
 #if defined(SHADERS)
 
-#if defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__ODROID__)
+#if defined(__ANDROID__) || defined(__ODROID__)
    #include <GLES/gl.h>
 
    #define GL_INT    0x1404
    #define GL_DOUBLE 0x140A
+#elif defined(__EMSCRIPTEN__)
+   #include <GLES2/gl2.h>
 #else
 #  if defined(SHADERS)
 #     include "gl_core_3_3.h"
@@ -69,12 +72,12 @@ void shader_color(float r, float g, float b, float a)
 
 void shader_lighting(bool on)
 {
-   glUniform1ui(uLightingOn, on);
+   glUniform1i(uLightingOn, on);
 }
 
 void shader_fog(bool on)
 {
-   glUniform1ui(uFogOn, on);
+   glUniform1i(uFogOn, on);
 }
 
 void shader_fogDensity(float density)
@@ -89,13 +92,13 @@ void shader_fogColor(float r, float g, float b)
 
 void shader_texturing(bool on)
 {
-   glUniform1ui(uTexturingOn, on);
+   glUniform1i(uTexturingOn, on);
 }
 
 void shader_setMaterial(Material material, bool perVertexColor)
 {
-   glUniform1ui(uPerVertexColor, perVertexColor);
-   glUniform1ui(uMatTwoSided, !material.flags.singleSideLight);
+   glUniform1i(uPerVertexColor, perVertexColor);
+   glUniform1i(uMatTwoSided, !material.flags.singleSideLight);
    glUniform3f(uMatDiffuse, material.diffuse.r, material.diffuse.g, material.diffuse.b);
    glUniform3f(uMatAmbient, material.ambient.r, material.ambient.g, material.ambient.b);
    glUniform3f(uMatSpecular, material.specular.r, material.specular.g, material.specular.b);
@@ -104,6 +107,11 @@ void shader_setMaterial(Material material, bool perVertexColor)
    glUniform1f(uMatOpacity, material.opacity);
 }
 
+public void shader_setPerVertexColor(bool perVertexColor)
+{
+   glUniform1i(uPerVertexColor, perVertexColor);
+}
+
 void shader_setLight(Display display, uint id, Light light)
 {
    if(light != null)
@@ -214,155 +222,165 @@ void shader_setLight(Display display, uint id, Light light)
       glUniform1i(uLightsOn[id], 0);
 }
 
-void loadShaders(const String vertexShaderFile, const String fragmentShaderFile)
+bool loadShaders(const String vertexShaderFile, const String fragmentShaderFile)
 {
-   static char compileLog[65536];
-   #define BUFFER_SIZE  4096
-   int bufferLen = BUFFER_SIZE;
-   char * buffer = new byte[BUFFER_SIZE];
-   int vsLen = 0, fsLen = 0;
-   char * vsSource = null;
-   char * psSource = null;
+   bool result = false;
    File vf = FileOpen(vertexShaderFile, read);
    File ff = FileOpen(fragmentShaderFile, read);
-
-   if(vf)
+   // printf("loading shaders %s and %s (%p and %p)\n", vertexShaderFile, fragmentShaderFile, vf, ff);
+   if(vf && ff)
    {
-      while(!vf.eof)
+      static char compileLog[65536];
+      #define BUFFER_SIZE  4096
+      int bufferLen = BUFFER_SIZE;
+      char * buffer = new byte[BUFFER_SIZE];
+      int vsLen = 0, fsLen = 0;
+      char * vsSource = null;
+      char * psSource = null;
+      if(vf)
       {
-         int count = vf.Read(buffer + vsLen, 1, BUFFER_SIZE);
-         vsLen += count;
-         if(count == BUFFER_SIZE && bufferLen < vsLen + BUFFER_SIZE)
+         while(!vf.eof)
          {
-            bufferLen = vsLen + BUFFER_SIZE;
-            buffer = renew buffer byte[bufferLen];
+            int count = vf.Read(buffer + vsLen, 1, BUFFER_SIZE);
+            vsLen += count;
+            if(count == BUFFER_SIZE && bufferLen < vsLen + BUFFER_SIZE)
+            {
+               bufferLen = vsLen + BUFFER_SIZE;
+               buffer = renew buffer byte[bufferLen];
+            }
          }
+         vsSource = new byte[vsLen+1];
+         memcpy(vsSource, buffer, vsLen);
+         vsSource[vsLen] = 0;
+         delete vf;
       }
-      vsSource = new byte[vsLen+1];
-      memcpy(vsSource, buffer, vsLen);
-      vsSource[vsLen] = 0;
-      delete vf;
-   }
-   if(ff)
-   {
-      while(!ff.eof)
+      if(ff)
       {
-         int count = ff.Read(buffer + fsLen, 1, BUFFER_SIZE);
-         fsLen += count;
-         if(count == BUFFER_SIZE && bufferLen < fsLen + BUFFER_SIZE)
+         while(!ff.eof)
          {
-            bufferLen = fsLen + BUFFER_SIZE;
-            buffer = renew buffer byte[bufferLen];
+            int count = ff.Read(buffer + fsLen, 1, BUFFER_SIZE);
+            fsLen += count;
+            if(count == BUFFER_SIZE && bufferLen < fsLen + BUFFER_SIZE)
+            {
+               bufferLen = fsLen + BUFFER_SIZE;
+               buffer = renew buffer byte[bufferLen];
+            }
          }
+         psSource = new byte[fsLen+1];
+         memcpy(psSource, buffer, fsLen);
+         psSource[fsLen] = 0;
+         delete ff;
       }
-      psSource = new byte[fsLen+1];
-      memcpy(psSource, buffer, fsLen);
-      psSource[fsLen] = 0;
-      delete ff;
-   }
-   delete buffer;
+      delete buffer;
 
-   printf("We've got OpenGL Version %s\n\n", (char *)glGetString(GL_VERSION));
-   printf("We've got Shading Language Version %s\n\n", (char *)glGetString(GL_SHADING_LANGUAGE_VERSION));
+      printf("We've got OpenGL Version %s\n\n", (char *)glGetString(GL_VERSION));
+      printf("We've got Shading Language Version %s\n\n", (char *)glGetString(GL_SHADING_LANGUAGE_VERSION));
 
-   {
-      int program = glCreateProgram();
-      int vShader = glCreateShader(GL_VERTEX_SHADER);
-      int fShader = glCreateShader(GL_FRAGMENT_SHADER);
-      const char * vptr[1] = { vsSource };
-      const char * fptr[1] = { psSource };
-      int i;
-
-      glShaderSource(vShader, 1, vptr, &vsLen);
-      glShaderSource(fShader, 1, fptr, &fsLen);
-      delete vsSource;
-      delete psSource;
-
-      glCompileShader(vShader);
-      glGetShaderInfoLog(vShader, sizeof(compileLog), null, compileLog);
-      puts("Vertex Shader Compile Log:");
-      puts("--------------------------");
-      puts(compileLog[0] ? compileLog : "Success.");
-
-      glCompileShader(fShader);
-      glGetShaderInfoLog(fShader, sizeof(compileLog), null, compileLog);
-      puts("");
-      puts("");
-      puts("Fragment Shader Compile Log:");
-      puts("--------------------------");
-      puts(compileLog[0] ? compileLog : "Success.");
-
-      glAttachShader(program, vShader);
-      glAttachShader(program, fShader);
-
-      glBindAttribLocation(program, GLBufferContents::vertex, "vertex");
-      glBindAttribLocation(program, GLBufferContents::texCoord, "texCoord");
-      glBindAttribLocation(program, GLBufferContents::color, "color");
-      glBindAttribLocation(program, GLBufferContents::normal, "normal");
-      glBindFragDataLocation(program, 0, "fragColor");
-
-      glLinkProgram(program);
-      glValidateProgram(program);
-
-      glGetProgramInfoLog(program, sizeof(compileLog), null, compileLog);
-      puts("");
-      puts("");
-      puts("Shader Program Log:");
-      puts("--------------------------");
-      puts(compileLog[0] ? compileLog : "Success.");
-
-      uPrjMatrix     = glGetUniformLocation(program, "projection_matrix");
-      uMVMatrix      = glGetUniformLocation(program, "modelview_matrix");
-      uTextureMatrix = glGetUniformLocation(program, "texture_matrix");
-      uColor         = glGetUniformLocation(program, "current_color");
-      uTexturingOn   = glGetUniformLocation(program, "texturingOn");
-      uLightingOn    = glGetUniformLocation(program, "lightingOn");
-      uFogOn         = glGetUniformLocation(program, "fogOn");
-      uFogDensity    = glGetUniformLocation(program, "fogDensity");
-      uFogColor      = glGetUniformLocation(program, "fogColor");
-      uGlobalAmbient = glGetUniformLocation(program, "globalAmbient");
-      uPerVertexColor  = glGetUniformLocation(program, "perVertexColor");
-      uMatDiffuse       = glGetUniformLocation(program, "matDiffuse");
-      uMatAmbient       = glGetUniformLocation(program, "matAmbient");
-      uMatSpecular      = glGetUniformLocation(program, "matSpecular");
-      uMatEmissive      = glGetUniformLocation(program, "matEmissive");
-      uMatPower         = glGetUniformLocation(program, "matPower");
-      uMatOpacity       = glGetUniformLocation(program, "matOpacity");
-      uMatTwoSided      = glGetUniformLocation(program, "matTwoSided");
-
-      for(i = 0; i < 8; i++)
       {
-         char name[100];
+         int program = glCreateProgram();
+         int vShader = glCreateShader(GL_VERTEX_SHADER);
+         int fShader = glCreateShader(GL_FRAGMENT_SHADER);
+         const char * vptr[1] = { vsSource };
+         const char * fptr[1] = { psSource };
+         int i;
+
+         glShaderSource(vShader, 1, vptr, &vsLen);
+         glShaderSource(fShader, 1, fptr, &fsLen);
+         delete vsSource;
+         delete psSource;
+
+         glCompileShader(vShader);
+         glGetShaderInfoLog(vShader, sizeof(compileLog), null, compileLog);
+         puts("Vertex Shader Compile Log:");
+         puts("--------------------------");
+         puts(compileLog[0] ? compileLog : "Success.");
+
+         glCompileShader(fShader);
+         glGetShaderInfoLog(fShader, sizeof(compileLog), null, compileLog);
+         puts("");
+         puts("");
+         puts("Fragment Shader Compile Log:");
+         puts("--------------------------");
+         puts(compileLog[0] ? compileLog : "Success.");
+
+         glAttachShader(program, vShader);
+         glAttachShader(program, fShader);
+
+         glBindAttribLocation(program, GLBufferContents::vertex, "vertex");
+         glBindAttribLocation(program, GLBufferContents::texCoord, "texCoord");
+         glBindAttribLocation(program, GLBufferContents::color, "color");
+         glBindAttribLocation(program, GLBufferContents::normal, "normal");
+         // glBindFragDataLocation(program, 0, "fragColor");
+
+         glLinkProgram(program);
+         glValidateProgram(program);
+
+         glGetProgramInfoLog(program, sizeof(compileLog), null, compileLog);
+         puts("");
+         puts("");
+         puts("Shader Program Log:");
+         puts("--------------------------");
+         puts(compileLog[0] ? compileLog : "Success.");
+
+         uPrjMatrix     = glGetUniformLocation(program, "projection_matrix");
+         uMVMatrix      = glGetUniformLocation(program, "modelview_matrix");
+         uTextureMatrix = glGetUniformLocation(program, "texture_matrix");
+         uColor         = glGetUniformLocation(program, "current_color");
+         uTexturingOn   = glGetUniformLocation(program, "texturingOn");
+         uLightingOn    = glGetUniformLocation(program, "lightingOn");
+         uFogOn         = glGetUniformLocation(program, "fogOn");
+         uFogDensity    = glGetUniformLocation(program, "fogDensity");
+         uFogColor      = glGetUniformLocation(program, "fogColor");
+         uGlobalAmbient = glGetUniformLocation(program, "globalAmbient");
+         uPerVertexColor  = glGetUniformLocation(program, "perVertexColor");
+         uMatDiffuse       = glGetUniformLocation(program, "matDiffuse");
+         uMatAmbient       = glGetUniformLocation(program, "matAmbient");
+         uMatSpecular      = glGetUniformLocation(program, "matSpecular");
+         uMatEmissive      = glGetUniformLocation(program, "matEmissive");
+         uMatPower         = glGetUniformLocation(program, "matPower");
+         uMatOpacity       = glGetUniformLocation(program, "matOpacity");
+         uMatTwoSided      = glGetUniformLocation(program, "matTwoSided");
+
+         for(i = 0; i < 8; i++)
+         {
+            char name[100];
 
-         sprintf(name, "lightsOn[%d]", i);
-         uLightsOn [i] = glGetUniformLocation(program, name);
+            sprintf(name, "lightsOn[%d]", i);
+            uLightsOn [i] = glGetUniformLocation(program, name);
 
-         sprintf(name, "lightsPos[%d]", i);
-         uLightsPos[i] = glGetUniformLocation(program, name);
+            sprintf(name, "lightsPos[%d]", i);
+            uLightsPos[i] = glGetUniformLocation(program, name);
 
-         sprintf(name, "lightsDiffuse[%d]", i);
-         uLightsDiffuse[i] = glGetUniformLocation(program, name);
+            sprintf(name, "lightsDiffuse[%d]", i);
+            uLightsDiffuse[i] = glGetUniformLocation(program, name);
 
-         sprintf(name, "lightsAmbient[%d]", i);
-         uLightsAmbient[i] = glGetUniformLocation(program, name);
+            sprintf(name, "lightsAmbient[%d]", i);
+            uLightsAmbient[i] = glGetUniformLocation(program, name);
 
-         sprintf(name, "lightsSpecular[%d]", i);
-         uLightsSpecular[i] = glGetUniformLocation(program, name);
-      }
+            sprintf(name, "lightsSpecular[%d]", i);
+            uLightsSpecular[i] = glGetUniformLocation(program, name);
+         }
+
+         shadingProgram = program;
 
-      shadingProgram = program;
+         glUseProgram(shadingProgram);
 
-      glUseProgram(shadingProgram);
+         // Initialize uniforms to defaults
+         glmsMatrixMode(texture);
+         glmsLoadIdentity();
+         glmsMatrixMode(projection);
+         glmsLoadIdentity();
+         glmsMatrixMode(modelView);
+         glmsLoadIdentity();
+         shader_color(1.0, 1.0, 1.0, 1.0);
 
-      // Initialize uniforms to defaults
-      glmsMatrixMode(texture);
-      glmsLoadIdentity();
-      glmsMatrixMode(projection);
-      glmsLoadIdentity();
-      glmsMatrixMode(modelView);
-      glmsLoadIdentity();
-      shader_color(1.0, 1.0, 1.0, 1.0);
+         result = true;
+      }
    }
+   delete vf;
+   delete ff;
+
+   return result;
 }
 
 #endif
index bb7fd95..9cb5e5c 100644 (file)
@@ -1,7 +1,10 @@
+#define _Noreturn
+
 namespace gui;
 
 #ifdef __EMSCRIPTEN__
 #include <emscripten.h>
+#include <html5.h>
 #endif
 
 #ifdef __EMSCRIPTEN__
@@ -472,7 +475,11 @@ public class GuiApplication : Application
                   desktop.Update(null);
             }
             // When does the desktop have a display in not fullscreen mode?
+#if defined(__EMSCRIPTEN__)
+            if(true)
+#else
             if(!fullScreenMode && !modeSwitching)
+#endif
                desktop.UpdateDisplay();
             desktop.display.Unlock();
          }
@@ -687,6 +694,23 @@ public:
    {
       Window window;
 
+#ifdef __EMSCRIPTEN__
+      {
+         int w = 0, h = 0;
+         double dw = 0, dh = 0;
+
+         emscripten_get_element_css_size(0, &dw, &dh);
+         w = (int)dw, h = (int)dh;
+         if(w && h)
+         {
+            emscripten_set_canvas_size(w, h);
+            guiApp.desktop.ExternalPosition(0,0, w, h);
+            if(guiApp.desktop.display && guiApp.desktop.display.displaySystem)
+               guiApp.desktop.display.Resize(w, h);
+         }
+      }
+#endif
+
       if(Init())
       {
          if(desktop)
@@ -707,13 +731,14 @@ public:
          }
 
 #ifdef __EMSCRIPTEN__
-      emscripten_set_main_loop(emscripten_main_loop_callback, 1/*60*/, 1);
+      emscripten_set_main_loop(emscripten_main_loop_callback, 0 /*1/*60*/, 1);
 #endif
 
          if(desktop)
          {
             int terminated = 0;
             incref desktop;
+
             ProcessInput(true);
             while(desktop && interfaceDriver)
             {
@@ -857,7 +882,11 @@ public:
 
       if(interfaceDriver)
       {
+#if defined(__EMSCRIPTEN__)
+         if(true)
+#else
          if(fullScreenMode && desktop.display)
+#endif
          {
 #if !defined(__EMSCRIPTEN__)
             desktop.mutex.Wait();
@@ -1237,6 +1266,19 @@ public:
          (!refreshRate || refreshRate == fbRefreshRate) &&
          (currentSkin && (!skinName || !strcmp(currentSkin.name, skinName))))
          result = true;
+#if defined(__EMSCRIPTEN__)
+      else if(interfaceDriver && (!driverName || (fbDriver && !strcmp(fbDriver, driverName))) &&
+         fullScreen != fbFullScreen &&
+         (!resolution || resolution == fbResolution) &&
+         (!colorDepth || colorDepth == fbColorDepth) &&
+         (!refreshRate || refreshRate == fbRefreshRate) &&
+         (currentSkin && (!skinName || !strcmp(currentSkin.name, skinName))))
+      {
+         if(inter.ScreenMode(fullScreen, resolution, colorDepth, refreshRate, &textMode))
+            this.fullScreen = fullScreen;
+         result = true;
+      }
+#endif
       else if(inter)
       {
          bool wasFullScreen = fullScreenMode;
@@ -1529,6 +1571,7 @@ public:
    {
       set { timerResolution = value; if(interfaceDriver) interfaceDriver.SetTimerResolution(value); }
    };
+   property Window acquiredWindow { get { return acquiredWindow; } };
 };
 
 #ifdef __EMSCRIPTEN__
index 68e4f79..85dcdaa 100644 (file)
@@ -824,7 +824,9 @@ private:
             x -= rootWindow.clientStart.x;
             y -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
          }
+#if !defined(__EMSCRIPTEN__)
          if(!guiApp.fullScreenMode || is3D)
+#endif
          {
             x -= rootWindow.absPosition.x;
             y -= rootWindow.absPosition.y;
@@ -1801,7 +1803,11 @@ private:
                   if(display && !display.flags.memBackBuffer && changeRootWindow)
                      guiApp.interfaceDriver.PositionRootWindow(this, x, y, w, h, windowMoved, windowResized); //realResized);
 
-               if(!guiApp.fullScreenMode && this != guiApp.desktop && (windowResized || windowMoved))
+               if(
+#if !defined(__EMSCRIPTEN__)
+                  !guiApp.fullScreenMode &&
+#endif
+                  this != guiApp.desktop && (windowResized || windowMoved))
                   for(child = parent.children.first; child && child != this; child = child.next)
                      if(child.rootWindow)
                         guiApp.interfaceDriver.UpdateRootWindow(child.rootWindow);
@@ -3787,7 +3793,10 @@ private:
                         if(activateParent && parent && !parent.active /*parent != parent.parent.activeChild*/)
                            parent.ActivateEx(true, true, moveInactive, activateRoot, external, externalSwap);
                      }
-                     else if(!guiApp.fullScreenMode)
+                     else
+#if !defined(__EMSCRIPTEN__)
+                     if(!guiApp.fullScreenMode)
+#endif
                      {
                         Window modalRoot = FindModal();
                         if(!modalRoot) modalRoot = this;
@@ -4881,8 +4890,12 @@ private:
       Window child;
 
       // Setup relationship with outside world (bb root || !bb)
+#if defined(__EMSCRIPTEN__)
+      if(this == guiApp.desktop)
+#else
       if((!guiApp.fullScreenMode && parent == guiApp.desktop) || this == guiApp.desktop ||
          (_displayDriver && parent.dispDriver && dispDriver != parent.dispDriver))
+#endif
       {
          rootWindow = this;
          if(!tempExtents)
@@ -4914,7 +4927,11 @@ private:
       bool result = false;
       Window child;
 
+#if defined(__EMSCRIPTEN__)
+      if(this == guiApp.desktop)
+#else
       if((!guiApp.fullScreenMode && parent == guiApp.desktop) || (guiApp.fullScreenMode && (this == guiApp.desktop || (_displayDriver && parent.dispDriver && dispDriver != parent.dispDriver))))
+#endif
       {
          subclass(DisplayDriver) dDriver = (dispDriver && !formDesigner) ? dispDriver : GetDisplayDriver(guiApp.defaultDisplayDriver);
          DisplaySystem displaySystem = dDriver ? dDriver.displaySystem : null;
@@ -5020,7 +5037,11 @@ private:
          }
       }
 
-      if(guiApp.fullScreenMode || this != guiApp.desktop)
+      if(
+#if !defined(__EMSCRIPTEN__)
+      guiApp.fullScreenMode ||
+#endif
+         this != guiApp.desktop)
       {
          SetWindowMinimum(&skinMinSize.w, &skinMinSize.h);
          if(display)
@@ -5948,7 +5969,7 @@ private:
    public bool AcquireInput(bool acquired)
    {
       bool result = true;
-      if(acquiredInput != acquired)
+      if((guiApp.acquiredWindow && acquiredInput) != acquired)
       {
          if(active || (!visible && creationActivation == activate))
             result = AcquireInputEx(acquired);
@@ -5981,7 +6002,11 @@ private:
    {
       if(guiApp.driver != null)
       {
+#if !defined(__EMSCRIPTEN__)
          if(guiApp.fullScreenMode && guiApp.desktop.display)
+#else
+         if(true)
+#endif
          {
 #if !defined(__EMSCRIPTEN__)
             guiApp.desktop.mutex.Wait();
@@ -7905,16 +7930,23 @@ public:
 
    bool MenuWindowWindows(MenuItem selection, Modifiers mods)
    {
-      WindowList dialog { master = this };
-      Window document = (Window)(intptr)dialog.Modal();
-      if(document)
+      WindowList
       {
-         if(activeChild.state == maximized)
-            document.SetState(maximized, false, mods);
-         else if(document.state == minimized)
-            document.SetState(normal, false, mods);
-         document.Activate();
-      }
+         master = this; isModal = true;
+
+         void NotifyDestroyed(Window window, DialogResult result)
+         {
+            Window document = (Window)(intptr)result;
+            if(document)
+            {
+               if(activeChild.state == maximized)
+                  document.SetState(maximized, false, 0);
+               else if(document.state == minimized)
+                  document.SetState(normal, false, 0);
+               document.Activate();
+            }
+         }
+      }.Create();
       return true;
    }
 
index 4e02492..bfa009d 100644 (file)
@@ -1,3 +1,5 @@
+#define _Noreturn
+
 namespace gui::drivers;
 
 import "Window"
index 9df8751..6cf6af1 100644 (file)
@@ -21,62 +21,468 @@ public import "ecere"
 #define property _property
 #define uint _uint
 
-//#include <GLES2/gl2.h>
-#include <GL/glfw.h>
-#include <emscripten/emscripten.h>
+#include <emscripten.h>
+#include <html5.h>
 
 #undef property
 #undef uint
 
+default:
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp;
+
+private:
+
+static Point lastMouse;
+
+static inline const char *emscripten_event_type_to_string(int eventType) {
+  const char *events[] = { "(invalid)", "(none)", "keypress", "keydown", "keyup", "click", "mousedown", "mouseup", "dblclick", "mousemove", "wheel", "resize",
+    "scroll", "blur", "focus", "focusin", "focusout", "deviceorientation", "devicemotion", "orientationchange", "fullscreenchange", "pointerlockchange",
+    "visibilitychange", "touchstart", "touchend", "touchmove", "touchcancel", "gamepadconnected", "gamepaddisconnected", "beforeunload",
+    "batterychargingchange", "batterylevelchange", "webglcontextlost", "webglcontextrestored", "mouseenter", "mouseleave", "mouseover", "mouseout", "(invalid)" };
+  ++eventType;
+  if (eventType < 0) eventType = 0;
+  if (eventType >= sizeof(events)/sizeof(events[0])) eventType = sizeof(events)/sizeof(events[0])-1;
+  return events[eventType];
+}
+
+static int mouseButtons;
+static int movementX, movementY;
+
+static bool isFullScreen;
+
+static EM_BOOL mouse_callback(int eventType, const EmscriptenMouseEvent *e, void *userData)
+{
+   Window window = guiApp.desktop;
+   Modifiers mods { };
+   int methodID;
+
+   switch(eventType)
+   {
+      case EMSCRIPTEN_EVENT_MOUSEMOVE:
+         lastMouse = { e->canvasX, e->canvasY };
+         window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove,
+            e->canvasX, e->canvasY, &mods, false, true);
+         movementX += e->movementX;
+         movementY += e->movementY;
+         break;
+      case EMSCRIPTEN_EVENT_MOUSEDOWN:
+         // PrintLn("EMSCRIPTEN_EVENT_MOUSEDOWN!");
+         methodID =
+            e->button == 0 ? __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown :
+            e->button == 2 ? __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown :
+                             __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown;
+         window.MouseMessage(methodID, e->canvasX, e->canvasY, &mods, false, true);
+         if(e->button == 0)
+            mouseButtons |= 1;
+         else if(e->button == 2)
+            mouseButtons |= 2;
+         else
+            mouseButtons |= 4;
+         break;
+      case EMSCRIPTEN_EVENT_MOUSEUP:
+         methodID =
+            e->button == 0 ? __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp :
+            e->button == 2 ? __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp :
+                             __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp;
+         window.MouseMessage(methodID, e->canvasX, e->canvasY, &mods, false, true);
+         if(e->button == 0)
+            mouseButtons &= ~1;
+         else if(e->button == 2)
+            mouseButtons &= ~2;
+         else
+            mouseButtons &= ~4;
+         break;
+      case EMSCRIPTEN_EVENT_DBLCLICK:
+         methodID =
+            e->button == 0 ? __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick :
+            e->button == 2 ? __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick :
+                             __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick;
+         window.MouseMessage(methodID, e->canvasX, e->canvasY, &mods, false, true);
+         break;
+   }
+
+/*
+   printf("%s, screen: (%ld,%ld), client: (%ld,%ld),%s%s%s%s button: %hu, buttons: %hu, movement: (%ld,%ld), canvas: (%ld,%ld)\n",
+      emscripten_event_type_to_string(eventType), e->screenX, e->screenY, e->clientX, e->clientY,
+      e->ctrlKey ? " CTRL" : "", e->shiftKey ? " SHIFT" : "", e->altKey ? " ALT" : "", e->metaKey ? " META" : "",
+      e->button, e->buttons, e->movementX, e->movementY, e->canvasX, e->canvasY);
+*/
+   return 0;
+}
+
+static EM_BOOL wheel_callback(int eventType, const EmscriptenWheelEvent *e, void *userData)
+{
+   Window window = guiApp.desktop;
+   window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit,
+      e->deltaY < 0 ? wheelUp : wheelDown, 0);
+   /*
+   printf("%s, screen: (%ld,%ld), client: (%ld,%ld),%s%s%s%s button: %hu, buttons: %hu, canvas: (%ld,%ld), delta:(%g,%g,%g), deltaMode:%lu\n",
+    emscripten_event_type_to_string(eventType), e->mouse.screenX, e->mouse.screenY, e->mouse.clientX, e->mouse.clientY,
+    e->mouse.ctrlKey ? " CTRL" : "", e->mouse.shiftKey ? " SHIFT" : "", e->mouse.altKey ? " ALT" : "", e->mouse.metaKey ? " META" : "",
+    e->mouse.button, e->mouse.buttons, e->mouse.canvasX, e->mouse.canvasY,
+    (float)e->deltaX, (float)e->deltaY, (float)e->deltaZ, e->deltaMode);
+  */
+  return 0;
+}
+static bool keyStatus[KeyCode];
+
+EM_BOOL pointerlockchange_callback(int eventType, const EmscriptenPointerlockChangeEvent *e, void *userData)
+{
+   if(!e->isActive)
+   {
+      if(guiApp.acquiredWindow)
+      {
+         guiApp.acquiredWindow.acquiredInput = false;
+         guiApp.acquiredWindow = null;
+      }
+   }
+   else
+   {
+      Window w = guiApp.desktop;
+      if(w && w.children.first) w = w.children.first;
+      guiApp.acquiredWindow = w;
+      guiApp.acquiredWindow.acquiredInput = true;
+   }
+/*
+  printf("%s, isActive: %d, pointerlock element nodeName: \"%s\", id: \"%s\"\n",
+    emscripten_event_type_to_string(eventType), e->isActive, e->nodeName, e->id);
+*/
+   movementX = 0;
+   movementY = 0;
+   return 0;
+}
+
+EM_BOOL fullscreenchange_callback(int eventType, const EmscriptenFullscreenChangeEvent *e, void *userData)
+{
+   int w = 0, h = 0;
+   double dw = 0, dh = 0;
+   isFullScreen = (bool)e->isFullscreen;
+   *&guiApp.fullScreen = isFullScreen;
+
+   emscripten_get_element_css_size(0, &dw, &dh);
+   w = (int)dw, h = (int)dh;
+   if(w && h)
+   {
+      emscripten_set_canvas_size(w, h);
+      guiApp.desktop.ExternalPosition(0,0, w, h);
+      if(guiApp.desktop.display && guiApp.desktop.display.displaySystem)
+         guiApp.desktop.display.Resize(w, h);
+   }
+   movementX = 0;
+   movementY = 0;
+   return 0;
+}
+
+// The event handler functions can return 1 to suppress the event and disable the default action. That calls event.preventDefault();
+// Returning 0 signals that the event was not consumed by the code, and will allow the event to pass on and bubble up normally.
+EM_BOOL key_callback(int eventType, const EmscriptenKeyboardEvent *e, void *userData)
+{
+   Window window = guiApp.desktop;
+   Key key = 0;
+   switch(e->keyCode)
+   {
+      case 8: key = backSpace; break;
+      case 9: key = tab; break;
+      case 13: key = enter; break;
+      case 16: key = shift; break;
+      case 17: key = control; break;
+      case 18: key = alt; break;
+      case 19: key = pause; break;
+      case 20: key = capsLock; break;
+      case 27: key = escape; break;
+      case 32: key = space; break;
+      case 33: key = pageUp; break;
+      case 34: key = pageDown; break;
+      case 35: key = end; break;
+      case 36: key = home; break;
+      case 37: key = left; break;
+      case 38: key = up; break;
+      case 39: key = right; break;
+      case 40: key = down; break;
+      case 44: key = printScreen; break;
+      case 45: key = insert; break;
+      case 46: key = del; break;
+      case 48: key = k0; break;
+      case 49: key = k1; break;
+      case 50: key = k2; break;
+      case 51: key = k3; break;
+      case 52: key = k4; break;
+      case 53: key = k5; break;
+      case 54: key = k6; break;
+      case 55: key = k7; break;
+      case 56: key = k8; break;
+      case 57: key = k9; break;
+      case 65: key = a; break;
+      case 66: key = b; break;
+      case 67: key = c; break;
+      case 68: key = d; break;
+      case 69: key = KeyCode::e; break;
+      case 70: key = f; break;
+      case 71: key = g; break;
+      case 72: key = h; break;
+      case 73: key = i; break;
+      case 74: key = j; break;
+      case 75: key = k; break;
+      case 76: key = l; break;
+      case 77: key = m; break;
+      case 78: key = n; break;
+      case 79: key = o; break;
+      case 80: key = p; break;
+      case 81: key = q; break;
+      case 82: key = r; break;
+      case 83: key = s; break;
+      case 84: key = t; break;
+      case 85: key = u; break;
+      case 86: key = v; break;
+      case 87: key = w; break;
+      case 88: key = x; break;
+      case 89: key = y; break;
+      case 90: key = z; break;
+      // case 91: key = start; break;
+      // case 93: key = context; break;
+      case 112: key = f1; break;
+      case 113: key = f2; break;
+      case 114: key = f3; break;
+      case 115: key = f4; break;
+      case 116: key = f5; break;
+      case 117: key = f6; break;
+      case 118: key = f7; break;
+      case 119: key = f8; break;
+      case 120: key = f9; break;
+      case 121: key = f10; break;
+      case 122: key = f11; break;
+      case 123: key = f12; break;
+      case 144: key = numLock; break;
+      case 125: key = scrollLock; break;
+      case 188: key = comma; break;
+      case 190: key = period; break;
+      case 191: key = slash; break;
+      case 192: key = tilde; break;
+      case 219: key = leftBracket; break;    // also corresponds to the Win Key (Start) in older versions of Opera.
+      case 220: key = backSlash; break;
+      case 221: key = rightBracket; break;
+      case 222: key = quote; break;
+
+      /*case 173: */case 181: key = mute; break;       // FF: 181
+      case 174: case 182: key = volumeDown; break;     // FF: 182
+      case 175: case 183: key = volumeDown; break;     // FF: 183
+      case 186: case 59:  key = semicolon; break;      // FF: 59
+      case 187: case 61:  key = equal; break;          // FF: 61
+      case 189: case 173: key = minus; break;          // FF: 61
+
+      case 96: key = keyPad0; break;
+      //case 45: key = keyPadInsert; break;
+
+      case 97: key = keyPad1; break;
+      //case 35: key = keyPadEnd; break;
+
+      case 98: key = keyPad2; break;
+      //case 40: key = keyPadDown; break;
+
+      case 99: key = keyPad3; break;
+      //case 34: key = keyPadPageDown; break;
+
+      case 100: key = keyPad4; break;
+      //case 37: key = keyPadLeft; break;
+
+      case 101: key = keyPad5; break;
+      case 12: key = keyPad5; break;
+
+      case 102: key = keyPad6; break;
+      //case 39: key = keyPadRight; break;
+
+      case 103: key = keyPad7; break;
+      //case 36: key = keyPadHome; break;
+
+      case 104: key = keyPad8; break;
+      //case 38: key = keyPadUp; break;
+
+      case 105: key = keyPad9; break;
+      //case 33: key = keyPadPageUp; break;
+
+      case 106: key = keyPadStar; break;
+      case 107: key = keyPadPlus; break;
+      case 109: key = keyPadMinus; break;
+
+      case 110: key = keyPadDelete; break;
+      //case 46: key = keyPadDelete; break;
+
+      case 11: key = keyPadSlash; break;
+   }
+
+   key.alt = (bool)e->altKey;
+   key.shift = (bool)e->shiftKey;
+   key.ctrl = (bool)e->ctrlKey;
+/*
+     printf("%s, key: \"%s\", code: \"%s\", location: %lu,%s%s%s%s repeat: %d, locale: \"%s\", char: \"%s\", charCode: %lu, keyCode: %lu, which: %lu\n",
+       emscripten_event_type_to_string(eventType), e->key, e->code, e->location,
+       e->ctrlKey ? " CTRL" : "", e->shiftKey ? " SHIFT" : "", e->altKey ? " ALT" : "", e->metaKey ? " META" : "",
+       e->repeat, e->locale, e->charValue, e->charCode, e->keyCode, e->which);
+*/
+   if(key)
+   {
+      switch(eventType)
+      {
+         case EMSCRIPTEN_EVENT_KEYDOWN:
+            //PrintLn("Setting ", key, " to down");
+            keyStatus[key] = true;
+            window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown, key, (unichar)e->charCode);
+            break;
+         case EMSCRIPTEN_EVENT_KEYUP:
+            //PrintLn("Setting ", key, " to false");
+            keyStatus[key] = false;
+            window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp, key, (unichar)e->charCode);
+            break;
+      }
+   }
+
+  /*
+  if (eventType == EMSCRIPTEN_EVENT_KEYPRESS && (!strcmp(e->key, "f") || e->which == 102)) {
+    EmscriptenFullscreenChangeEvent fsce;
+    EMSCRIPTEN_RESULT ret = emscripten_get_fullscreen_status(&fsce);
+    TEST_RESULT(emscripten_get_fullscreen_status);
+    if (!fsce.isFullscreen) {
+      printf("Requesting fullscreen..\n");
+      ret = emscripten_request_fullscreen(0, 1);
+      TEST_RESULT(emscripten_request_fullscreen);
+    } else {
+      printf("Exiting fullscreen..\n");
+      ret = emscripten_exit_fullscreen();
+      TEST_RESULT(emscripten_exit_fullscreen);
+      ret = emscripten_get_fullscreen_status(&fsce);
+      TEST_RESULT(emscripten_get_fullscreen_status);
+      if (fsce.isFullscreen) {
+        fprintf(stderr, "Fullscreen exit did not work!\n");
+      }
+    }
+  }
+
+  if (eventType == EMSCRIPTEN_EVENT_KEYPRESS && (!strcmp(e->key, "p") || e->which == 112)) {
+    EmscriptenPointerlockChangeEvent plce;
+    EMSCRIPTEN_RESULT ret = emscripten_get_pointerlock_status(&plce);
+    TEST_RESULT(emscripten_get_pointerlock_status);
+    if (!plce.isActive) {
+      printf("Requesting pointer lock..\n");
+      ret = emscripten_request_pointerlock(0, 1);
+      TEST_RESULT(emscripten_request_pointerlock);
+    } else {
+      printf("Exiting pointer lock..\n");
+      ret = emscripten_exit_pointerlock();
+      TEST_RESULT(emscripten_exit_pointerlock);
+      ret = emscripten_get_pointerlock_status(&plce);
+      TEST_RESULT(emscripten_get_pointerlock_status);
+      if (plce.isActive) {
+        fprintf(stderr, "Pointer lock exit did not work!\n");
+      }
+    }
+  }
+  */
+
+  return 0;
+}
+
+static EM_BOOL uievent_callback(int eventType, const EmscriptenUiEvent *e, void *userData)
+{
+   switch(eventType)
+   {
+      case EMSCRIPTEN_EVENT_RESIZE:
+      //case EMSCRIPTEN_EVENT_SCROLL:
+      {
+         int w = 0, h = 0;
+         double dw = 0, dh = 0;
+         emscripten_get_element_css_size(0, &dw, &dh);
+         w = (int)dw, h = (int)dh;
+         if(w && h)
+         {
+            emscripten_set_canvas_size(w, h);
+            guiApp.desktop.ExternalPosition(0,0, w, h);
+            if(guiApp.desktop.display && guiApp.desktop.display.displaySystem)
+               guiApp.desktop.display.Resize(w, h);
+         }
+         //PrintLn("EMSCRIPTEN_EVENT_RESIZE: ", w, " x ", h);
+         break;
+      }
+   }
+   /*
+   printf("%s, detail: %ld, document.body.client size: (%d,%d), window.inner size: (%d,%d), scrollPos: (%d, %d)\n",
+      emscripten_event_type_to_string(eventType), e->detail, e->documentBodyClientWidth, e->documentBodyClientHeight,
+      e->windowInnerWidth, e->windowInnerHeight, e->scrollTop, e->scrollLeft);
+   */
+   return 0;
+}
 
 class EmscriptenInterface : Interface
 {
    class_property(name) = "Emscripten";
 
-
    // --- User Interface System ---
 
    bool ::Initialize()
    {
-      sflnprintf("class(EmscriptenInterface) ::Initialize [STUB!]\n");
-      guiApp.desktop.ExternalPosition(0,0, 640, 480);
+      emscripten_set_resize_callback(0, 0, 1, uievent_callback);
+      //emscripten_set_scroll_callback(0, 0, 1, uievent_callback);
+      emscripten_set_click_callback(0, 0, 1, mouse_callback);
+      emscripten_set_mousedown_callback(0, 0, 1, mouse_callback);
+      emscripten_set_mouseup_callback(0, 0, 1, mouse_callback);
+      emscripten_set_dblclick_callback(0, 0, 1, mouse_callback);
+      emscripten_set_mousemove_callback(0, 0, 1, mouse_callback);
+      emscripten_set_wheel_callback(0, 0, 1, wheel_callback);
+      emscripten_set_keypress_callback(0, 0, 1, key_callback);
+      emscripten_set_keydown_callback(0, 0, 1, key_callback);
+      emscripten_set_keyup_callback(0, 0, 1, key_callback);
+      emscripten_set_pointerlockchange_callback(0, 0, 1, pointerlockchange_callback);
+      emscripten_set_fullscreenchange_callback(0, 0, 1, fullscreenchange_callback);
+      /*emscripten_set_mouseenter_callback(0, 0, 1, mouse_callback);
+      emscripten_set_mouseleave_callback(0, 0, 1, mouse_callback);*/
       return true;
    }
 
    void ::Terminate()
    {
-      sflnprintf("class(EmscriptenInterface) ::Terminate [STUB!]\n");
+
    }
 
    bool ::ProcessInput(bool processAll)
    {
-      sflnprintf("class(EmscriptenInterface) ::ProcessInput [STUB!]\n");
+
       return false;
    }
 
    void ::Wait()
    {
-      sflnprintf("class(EmscriptenInterface) ::Wait [STUB!]\n");
+
    }
 
    void ::Lock(Window window)
    {
-      sflnprintf("class(EmscriptenInterface) ::Lock [STUB!]\n");
+
    }
 
    void ::Unlock(Window window)
    {
-      sflnprintf("class(EmscriptenInterface) ::Unlock [STUB!]\n");
+
    }
 
    void ::SetTimerResolution(uint hertz)
    {
-      sflnprintf("class(EmscriptenInterface) ::SetTimerResolution [STUB!] Implement high resolution timer here\n");
+
    }
 
    const char ** ::GraphicsDrivers(int * numDrivers)
    {
-      //sflnprintf("class(EmscriptenInterface) ::GraphicsDrivers [STUB!]\n");
       static const char *graphicsDrivers[] = { "OpenGL" };
       *numDrivers = sizeof(graphicsDrivers) / sizeof(char *);
       return (const char **)graphicsDrivers;
@@ -85,18 +491,20 @@ class EmscriptenInterface : Interface
 
    void ::EnsureFullScreen(bool * fullScreen)
    {
-      sflnprintf("class(EmscriptenInterface) ::EnsureFullScreen [STUB!]\n");
-      *fullScreen = true;
+
    }
 
    void ::GetCurrentMode(bool * fullScreen, Resolution * resolution, PixelFormat * colorDepth, int * refreshRate)
    {
-      sflnprintf("class(EmscriptenInterface) ::GetCurrentMode [STUB!]\n");
+      *fullScreen = isFullScreen;
    }
 
    bool ::ScreenMode(bool fullScreen, Resolution resolution, PixelFormat colorDepth, int refreshRate, bool * textMode)
    {
-      sflnprintf("class(EmscriptenInterface) ::ScreenMode [STUB!]\n");
+      if(fullScreen)
+         emscripten_request_fullscreen(0, 1);
+      else
+         emscripten_exit_fullscreen();
       return true;
    }
 
@@ -105,13 +513,13 @@ class EmscriptenInterface : Interface
 
    void * ::CreateRootWindow(Window window)
    {
-      sflnprintf("class(EmscriptenInterface) ::CreateRootWindow [STUB!]\n");
+
       return null;
    }
 
    void ::DestroyRootWindow(Window window)
    {
-      sflnprintf("class(EmscriptenInterface) ::DestroyRootWindow [STUB!]\n");
+
    }
 
 
@@ -119,47 +527,47 @@ class EmscriptenInterface : Interface
 
    void ::SetRootWindowCaption(Window window, const char * name)
    {
-      sflnprintf("class(EmscriptenInterface) ::SetRootWindowCaption [STUB!]\n");
+
    }
 
    void ::PositionRootWindow(Window window, int x, int y, int w, int h, bool move, bool resize)
    {
-      sflnprintf("class(EmscriptenInterface) ::Stub [STUB!]\n");
+
    }
 
    void ::OffsetWindow(Window window, int * x, int * y)
    {
-      sflnprintf("class(EmscriptenInterface) ::OffsetWindow [STUB!]\n");
+
    }
 
    void ::UpdateRootWindow(Window window)
    {
-      sflnprintf("class(EmscriptenInterface) ::UpdateRootWindow [STUB!]\n");
+
    }
 
    void ::SetRootWindowState(Window window, WindowState state, bool visible)
    {
-      sflnprintf("class(EmscriptenInterface) ::SetRootWindowState [STUB!]\n");
+
    }
 
    void ::ActivateRootWindow(Window window)
    {
-      sflnprintf("class(EmscriptenInterface) ::ActivateRootWindow [STUB!]\n");
+
    }
 
    void ::OrderRootWindow(Window window, bool topMost)
    {
-      sflnprintf("class(EmscriptenInterface) ::OrderRootWindow [STUB!]\n");
+
    }
 
    void ::SetRootWindowColor(Window window)
    {
-      sflnprintf("class(EmscriptenInterface) ::SetRootWindowColor [STUB!]\n");
+
    }
 
    void ::FlashRootWindow(Window window)
    {
-      sflnprintf("class(EmscriptenInterface) ::FlashRootWindow [STUB!]\n");
+
    }
 
 
@@ -167,12 +575,12 @@ class EmscriptenInterface : Interface
 
    void ::StartMoving(Window window, int x, int y, bool fromKeyBoard)
    {
-      sflnprintf("class(EmscriptenInterface) ::StartMoving [STUB!]\n");
+
    }
 
    void ::StopMoving(Window window)
    {
-      sflnprintf("class(EmscriptenInterface) ::StopMoving [STUB!]\n");
+
    }
 
 
@@ -180,22 +588,23 @@ class EmscriptenInterface : Interface
 
    void ::GetMousePosition(int *x, int *y)
    {
-      sflnprintf("class(EmscriptenInterface) ::GetMousePosition [STUB!]\n");
+      *x = lastMouse.x;
+      *y = lastMouse.y;
    }
 
    void ::SetMousePosition(int x, int y)
    {
-      sflnprintf("class(EmscriptenInterface) ::SetMousePosition [STUB!]\n");
+
    }
 
    void ::SetMouseRange(Window window, Box box)
    {
-      sflnprintf("class(EmscriptenInterface) ::SetMouseRange [STUB!]\n");
+
    }
 
    void ::SetMouseCapture(Window window)
    {
-      sflnprintf("class(EmscriptenInterface) ::SetMouseCapture [STUB!]\n");
+
    }
 
 
@@ -203,7 +612,7 @@ class EmscriptenInterface : Interface
 
    void ::SetMouseCursor(Window window, SystemCursor cursor)
    {
-      sflnprintf("class(EmscriptenInterface) ::SetMouseCursor [STUB!]\n");
+
    }
 
 
@@ -211,7 +620,7 @@ class EmscriptenInterface : Interface
 
    void ::SetCaret(int caretX, int caretY, int size)
    {
-      sflnprintf("class(EmscriptenInterface) ::SetCaret [STUB!]\n");
+
    }
 
 
@@ -219,30 +628,30 @@ class EmscriptenInterface : Interface
 
    void ::ClearClipboard()
    {
-      sflnprintf("class(EmscriptenInterface) ::ClearClipboard [STUB!]\n");
+
    }
 
    bool ::AllocateClipboard(ClipBoard clipBoard, uint size)
    {
-      sflnprintf("class(EmscriptenInterface) ::AllocateClipboard [STUB!]\n");
+
       return false;
    }
 
    bool ::SaveClipboard(ClipBoard clipBoard)
    {
-      sflnprintf("class(EmscriptenInterface) ::SaveClipboard [STUB!]\n");
+
       return false;
    }
 
    bool ::LoadClipboard(ClipBoard clipBoard)
    {
-      sflnprintf("class(EmscriptenInterface) ::LoadClipboard [STUB!]\n");
+
       return false;
    }
 
    void ::UnloadClipboard(ClipBoard clipBoard)
    {
-      sflnprintf("class(EmscriptenInterface) ::UnloadClipboard [STUB!]\n");
+
    }
 
 
@@ -250,37 +659,44 @@ class EmscriptenInterface : Interface
 
    bool ::AcquireInput(Window window, bool state)
    {
-      sflnprintf("class(EmscriptenInterface) ::AcquireInput [STUB!]\n");
-      return false;
+      if(state)
+         emscripten_request_pointerlock(0, 1);
+      else
+         emscripten_exit_pointerlock();
+
+      movementX = 0;
+      movementY = 0;
+      return true;
    }
 
    bool ::GetMouseState(MouseButtons * buttons, int * x, int * y)
    {
-      sflnprintf("class(EmscriptenInterface) ::GetMouseState [STUB!]\n");
-      return false;
+      if(buttons) *buttons = { left = mouseButtons & 1, right = (mouseButtons & 2) ? true : false, middle = (mouseButtons & 4) ? true : false };
+      if(x) { *x = movementX; movementX = 0; }
+      if(y) { *y = movementY; movementY = 0; }
+
+      return true;
    }
 
    bool ::GetJoystickState(int device, Joystick joystick)
    {
-      sflnprintf("class(EmscriptenInterface) ::GetJoystickState [STUB!]\n");
+
       return false;
    }
 
    bool ::GetKeyState(Key key)
    {
-      sflnprintf("class(EmscriptenInterface) ::GetKeyState [STUB!]\n");
-      return false;
+      return keyStatus[key];
    }
 
    bool ::SetIcon(Window window, BitmapResource icon)
    {
-      sflnprintf("class(EmscriptenInterface) ::SetIcon [STUB!]\n");
+
       return false;
    }
 
    void ::GetScreenArea(Window window, Box box)
    {
-      sflnprintf("class(EmscriptenInterface) ::GetScreenArea [STUB!]\n");
    }
 }
 
index a20a7cf..ad34f44 100644 (file)
@@ -1,8 +1,10 @@
+#define _Noreturn
+
 namespace gui::drivers;
 
 import "instance"
 
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(__DOS__) && !defined(__EMSCRIPTEN__)
+#if (defined(__unix__) || defined(__APPLE__)) && !defined(__DOS__)
 
 #undef __BLOCKS__
 #define DBLCLICK_DELAY  0.3  // seconds
index e40f6a6..a920b26 100644 (file)
@@ -1,3 +1,4 @@
+#define _Noreturn
 namespace gui::drivers;
 
 import "instance"
@@ -5,7 +6,7 @@ import "instance"
 import "OpenGLDisplayDriver"
 #endif
 
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX) && !defined(__EMSCRIPTEN__)
+#if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX)
 
 #undef __BLOCKS__
 default:
index 3b5af5a..aaa2343 100644 (file)
@@ -1,3 +1,5 @@
+#define _Noreturn
+
 #ifdef __statement
 #undef __statement
 #endif
index 56dd0fa..141ce11 100644 (file)
@@ -1,3 +1,5 @@
+#define _Noreturn
+
 namespace net;
 
 #include <stdarg.h>
index 3603854..a2b4366 100644 (file)
@@ -1,3 +1,5 @@
+#define _Noreturn
+
 namespace net;
 
 #if defined(__WIN32__)
index 568c223..e355df9 100644 (file)
@@ -1,3 +1,5 @@
+#define _Noreturn
+
 namespace net;
 
 #ifndef ECERE_NONET
index 466ccb7..c9eba7c 100644 (file)
@@ -1,3 +1,5 @@
+#define _Noreturn
+
 #if defined(__WIN32__)
 #define WIN32_LEAN_AND_MEAN
 #define UNICODE
index 9e867db..a45267d 100644 (file)
@@ -51,7 +51,12 @@ static File EAROpenArchive(const char * archive, EARHeader header)
          name = ((SubModule)__thisModule.application.modules.first).next.module.name;
 #endif
 
-      if(LocateModule(name, moduleName))
+#if defined(__EMSCRIPTEN__)
+      if(!name[0])
+         f = FileOpen("resources.ear", read);
+#endif
+
+      if(!f && LocateModule(name, moduleName))
          f = FileOpen(moduleName, read);
    }
    else
@@ -1429,6 +1434,21 @@ class EARFileSystem : FileSystem
          result = EARGetEntry(f, entry, fileName, null);
          delete f;
       }
+   #ifdef ECERE_STATIC
+      if(!f && archive[0] == ':')
+      {
+         f = EAROpenArchive(":", &header);
+         if(f)
+         {
+            EAREntry entry { };
+            char fn[MAX_LOCATION];
+            strcpy(fn, archive + 1);
+            PathCat(fn, fileName);
+            result = EARGetEntry(f, entry, fn, null);
+         }
+         delete f;
+      }
+   #endif
       return result;
    }
 
index 3bbbb2c..6aeea30 100644 (file)
@@ -1,4 +1,7 @@
+#define _Noreturn
+
 #undef __BLOCKS__
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
index 2a73e02..34da1f7 100644 (file)
@@ -1,5 +1,7 @@
 namespace sys;
 
+#define _Noreturn
+
 default:
 #define set _set
 #define uint _uint
index 9632796..84f167e 100644 (file)
@@ -1,3 +1,4 @@
+#define _Noreturn
 
 #if defined(__ANDROID__)
 #include <android/log.h>
@@ -15,7 +16,7 @@ namespace sys;
 #define uint _uint
 #define set _set
 #define String _String
-#if defined(__WIN32__) && !defined(__EMSCRIPTEN__)
+#if defined(__WIN32__)
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #else
index b7e5c7c..6d582cc 100644 (file)
@@ -1,3 +1,5 @@
+#define _Noreturn
+
 default:
 #include <errno.h>
 private:
index 1ef03a8..66cd65c 100644 (file)
@@ -1,3 +1,5 @@
+#define _Noreturn
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
index 1b7bcd8..67b2e82 100644 (file)
@@ -1,5 +1,7 @@
 namespace sys;
 
+#define _Noreturn
+
 #if defined(ECERE_BOOTSTRAP)
 #undef __WIN32__
 #undef __unix__
index ae2478b..b04144c 100644 (file)
@@ -1,3 +1,5 @@
+#define _Noreturn
+
 namespace sys;
 
 #define set _set
@@ -12,7 +14,7 @@ namespace sys;
 #undef Thread
 #else
 #include <pthread.h>
-#ifndef __ANDROID__
+#if !defined(__ANDROID__)
 #include <signal.h>
 #endif
 #endif
index a69e7de..1af3f14 100644 (file)
@@ -1,5 +1,7 @@
 namespace sys;
 
+#define _Noreturn
+
 #define set _set
 #define Date _Date
 #define uint _uint
index ca9d5b6..628d05a 100644 (file)
                "adb shell am start -a android.intent.action.MAIN -n com.ecere.$(MODULE)/android.app.NativeActivity"
             ]
          }
+      },
+      {
+         "Name" : "Emscripten",
+         "Options" : {
+            "Optimization" : "Speed",
+            "PreprocessorDefinitions" : [
+               "ECERE_STATIC",
+               "CHESS_NONET"
+            ],
+            "TargetFileName" : "chess.html",
+            "Libraries" : [
+               "ecereStatic",
+               "z",
+               "freetype",
+               "jpeg",
+               "png"
+            ],
+            "LibraryDirs" : [
+               "../../../ecere/obj/emscripten.linux.emscripten"
+            ],
+            "FastMath" : true
+         }
       }
    ],
    "Files" : [
    ],
    "ResourcesPath" : "res",
    "Resources" : [
+      {
+         "Folder" : "ecere",
+         "Files" : [
+            {
+               "Folder" : "actions",
+               "Files" : [
+                  "../../../ecere/res/actions/clean.png",
+                  "../../../ecere/res/actions/docNew.png",
+                  "../../../ecere/res/actions/docSave.png",
+                  "../../../ecere/res/actions/editFind.png",
+                  "../../../ecere/res/actions/folderNew.png",
+                  "../../../ecere/res/actions/goDown.png",
+                  "../../../ecere/res/actions/goHome.png",
+                  "../../../ecere/res/actions/goNext.png",
+                  "../../../ecere/res/actions/goPrevious.png",
+                  "../../../ecere/res/actions/goUp.png",
+                  "../../../ecere/res/actions/listAdd.png",
+                  "../../../ecere/res/actions/listRemove.png",
+                  "../../../ecere/res/actions/viewRefresh.png",
+                  "../../../ecere/res/actions/windowNew.png"
+               ]
+            },
+            {
+               "Folder" : "aqua",
+               "Files" : [
+                  "../../../ecere/res/aqua/back.png",
+                  "../../../ecere/res/aqua/down.png",
+                  "../../../ecere/res/aqua/downLeft.png",
+                  "../../../ecere/res/aqua/downMiddle.png",
+                  "../../../ecere/res/aqua/downRight.png",
+                  "../../../ecere/res/aqua/sDown.png",
+                  "../../../ecere/res/aqua/sUp.png",
+                  "../../../ecere/res/aqua/up.png",
+                  "../../../ecere/res/aqua/upLeft.png",
+                  "../../../ecere/res/aqua/upMiddle.png",
+                  "../../../ecere/res/aqua/upRight.png"
+               ]
+            },
+            {
+               "Folder" : "constructs",
+               "Files" : [
+                  "../../../ecere/res/constructs/class.png",
+                  "../../../ecere/res/constructs/data.png",
+                  "../../../ecere/res/constructs/dataPrivate.png",
+                  "../../../ecere/res/constructs/dataType.png",
+                  "../../../ecere/res/constructs/enum.png",
+                  "../../../ecere/res/constructs/enumValue.png",
+                  "../../../ecere/res/constructs/event.png",
+                  "../../../ecere/res/constructs/library.png",
+                  "../../../ecere/res/constructs/method.png",
+                  "../../../ecere/res/constructs/methodPrivate.png",
+                  "../../../ecere/res/constructs/namespace.png",
+                  "../../../ecere/res/constructs/property.png",
+                  "../../../ecere/res/constructs/propertyPrivate.png"
+               ]
+            },
+            {
+               "Folder" : "controls",
+               "Files" : [
+                  "../../../ecere/res/controls/button.png",
+                  "../../../ecere/res/controls/calendar.png",
+                  "../../../ecere/res/controls/checkBox.png",
+                  "../../../ecere/res/controls/dataBox.png",
+                  "../../../ecere/res/controls/dropBox.png",
+                  "../../../ecere/res/controls/editBox.png",
+                  "../../../ecere/res/controls/groupBox.png",
+                  "../../../ecere/res/controls/label.png",
+                  "../../../ecere/res/controls/listBox.png",
+                  "../../../ecere/res/controls/menu.png",
+                  "../../../ecere/res/controls/optionBox.png",
+                  "../../../ecere/res/controls/progressBar.png",
+                  "../../../ecere/res/controls/scrollBarHorizontal.png",
+                  "../../../ecere/res/controls/scrollBarVertical.png",
+                  "../../../ecere/res/controls/statusBar.png"
+               ]
+            },
+            {
+               "Folder" : "cursors",
+               "Files" : [
+                  "../../../ecere/res/cursors/arrow.png",
+                  "../../../ecere/res/cursors/cross.png",
+                  "../../../ecere/res/cursors/iBeam.png",
+                  "../../../ecere/res/cursors/move.png",
+                  "../../../ecere/res/cursors/sizeEastWest.png",
+                  "../../../ecere/res/cursors/sizeNortEastSouthWest.png",
+                  "../../../ecere/res/cursors/sizeNorthSouth.png",
+                  "../../../ecere/res/cursors/sizeNortWestSouthEast.png"
+               ]
+            },
+            {
+               "Folder" : "devices",
+               "Files" : [
+                  "../../../ecere/res/devices/computer.png",
+                  "../../../ecere/res/devices/driveHardDisk.png",
+                  "../../../ecere/res/devices/driveRemovableMedia.png",
+                  "../../../ecere/res/devices/mediaFloppy.png",
+                  "../../../ecere/res/devices/mediaOptical.png"
+               ]
+            },
+            {
+               "Folder" : "elements",
+               "Files" : [
+                  "../../../ecere/res/elements/areaClose.png",
+                  "../../../ecere/res/elements/areaMaximize.png",
+                  "../../../ecere/res/elements/areaMinimize.png",
+                  "../../../ecere/res/elements/areaRestore.png",
+                  "../../../ecere/res/elements/arrowDown.png",
+                  "../../../ecere/res/elements/arrowLeft.png",
+                  "../../../ecere/res/elements/arrowRight.png",
+                  "../../../ecere/res/elements/arrowUp.png",
+                  "../../../ecere/res/elements/checkBox.png",
+                  "../../../ecere/res/elements/checkBoxChecked.png",
+                  "../../../ecere/res/elements/checkBoxDisabled.png",
+                  "../../../ecere/res/elements/checkBoxDisabledChecked.png",
+                  "../../../ecere/res/elements/optionBoxDisabled.png",
+                  "../../../ecere/res/elements/optionBoxDisabledSelected.png",
+                  "../../../ecere/res/elements/optionBoxDown.png",
+                  "../../../ecere/res/elements/optionBoxSelectedDown.png",
+                  "../../../ecere/res/elements/optionBoxSelectedUp.png",
+                  "../../../ecere/res/elements/optionBoxUp.png",
+                  "../../../ecere/res/elements/orderAscending.png",
+                  "../../../ecere/res/elements/orderCategorized.png",
+                  "../../../ecere/res/elements/orderDescending.png"
+               ]
+            },
+            {
+               "Folder" : "emblems",
+               "Files" : [
+                  "../../../ecere/res/emblems/unreadable.png"
+               ]
+            },
+            {
+               "Folder" : "mimeTypes",
+               "Files" : [
+                  "../../../ecere/res/mimeTypes/brokenFile.png",
+                  "../../../ecere/res/mimeTypes/file.png",
+                  "../../../ecere/res/mimeTypes/image.png",
+                  "../../../ecere/res/mimeTypes/package.png",
+                  "../../../ecere/res/mimeTypes/packageOpticalDisc.png",
+                  "../../../ecere/res/mimeTypes/packageSoftware.png",
+                  "../../../ecere/res/mimeTypes/text.png",
+                  "../../../ecere/res/mimeTypes/textC++Header.png",
+                  "../../../ecere/res/mimeTypes/textC++Source.png",
+                  "../../../ecere/res/mimeTypes/textCHeader.png",
+                  "../../../ecere/res/mimeTypes/textCSource.png",
+                  "../../../ecere/res/mimeTypes/textEcereHeader.png",
+                  "../../../ecere/res/mimeTypes/textEcereProject.png",
+                  "../../../ecere/res/mimeTypes/textEcereSource.png",
+                  "../../../ecere/res/mimeTypes/textEcereWorkspace.png",
+                  "../../../ecere/res/mimeTypes/textHyperTextMarkup.png"
+               ]
+            },
+            {
+               "Folder" : "places",
+               "Files" : [
+                  "../../../ecere/res/places/brokenFolder.png",
+                  "../../../ecere/res/places/driveRemote.png",
+                  "../../../ecere/res/places/folder.png",
+                  "../../../ecere/res/places/folderRemote.png",
+                  "../../../ecere/res/places/networkServer.png",
+                  "../../../ecere/res/places/networkWorkgroup.png"
+               ]
+            },
+            {
+               "Folder" : "status",
+               "Files" : [
+                  "../../../ecere/res/status/audioVolumeHigh.png",
+                  "../../../ecere/res/status/folderOpen.png"
+               ]
+            },
+            {
+               "Folder" : "unicode",
+               "Files" : [
+                  "../../../ecere/res/unicode/derivedGeneralCategoryStripped.txt"
+               ]
+            },
+            {
+               "Folder" : "shaders",
+               "Files" : [
+                  "../../../ecere/src/gfx/drivers/gl3/fixed.frag",
+                  "../../../ecere/src/gfx/drivers/gl3/fixed.vertex"
+               ]
+            },
+            "C:/Windows/Fonts/tahoma.ttf",
+            "C:/Windows/Fonts/tahomabd.ttf"
+         ],
+         "Options" : {
+            "ExcludeFromBuild" : true
+         },
+         "Configurations" : [
+            {
+               "Name" : "Emscripten",
+               "Options" : {
+                  "ExcludeFromBuild" : false
+               }
+            }
+         ]
+      },
       "aboutPic.jpg",
       "blackBishop.png",
       "blackKing.png",
index 8301ee6..e2ec35c 100644 (file)
@@ -22,9 +22,9 @@ class AboutChess : Window
 
    void OnRedraw(Surface surface)
    {
-      surface.WriteTextf(200, 30, "Copyright (c) 1996-2005");
-      surface.WriteTextf(200, 50, "   Jerome Jacovella-St-Louis");
+      surface.WriteTextf(200, 30, "Copyright (c) 1996-2015");
+      surface.WriteTextf(200, 50, "   Jérôme Jacovella-St-Louis");
       surface.WriteTextf(200, 70, "Models Copyright (c) 2004");
-      surface.WriteTextf(200, 90, "   Gaetan Loyer");
+      surface.WriteTextf(200, 90, "   Gaétan Loyer");
    }
 }
index 4fc87d9..1fa159b 100644 (file)
@@ -358,9 +358,15 @@ class AIThread : Thread
    void Play()
    {
       abortAI = false;
+#if defined(__EMSCRIPTEN__)
+      Main();
+      chess.MakeMove(aiMove.x1, aiMove.y1, aiMove.x2, aiMove.y2, aiMove.promotion);
+      aiMoveResult = false;
+#else
       app.UpdateDisplay();
       Create();
       aiTimer.Start();
+#endif
    }
 
    void Abort()
index 19bc3f1..07c8215 100644 (file)
@@ -55,6 +55,9 @@ class ChessApp : GuiApplication
    }
 }
 
+enum GameAction { newAIGame, newLocalGame, endGame, close, connect, host, stop };
+
+
 #ifdef HIGH_DPI
 define stateWidth = 300;
 define turnWidth = 150;
@@ -66,17 +69,20 @@ define turnWidth = 100;
 class Chess : Window
 {
    background = gray, hasMenuBar = true, hasStatusBar = true,
+   fullRender = true;
    text = APPNAME,
-#ifndef __ANDROID__
+#if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__)
    hasClose = true, hasMaximize = true, hasMinimize = true,
    borderStyle = sizable,
 #endif
    anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 };
 
    bool hosting, local, ai;
+#ifndef CHESS_NONET
    Socket sockets[Player];
 
    ChessService service { port = CHESS_PORT, chess = this };
+#endif
 
    MenuItem * driverItems;
 
@@ -139,7 +145,7 @@ class Chess : Window
 
       bool NotifySelect(MenuItem selection, Modifiers mods)
       {
-         if(EndGame())
+         if(EndGame(newAIGame))
          {
             ai = true;
             chessState.gameRunning = true;
@@ -162,7 +168,7 @@ class Chess : Window
       gameMenu, "New Local Game\tCtrl+L", l, ctrlL;
       bool NotifySelect(MenuItem selection, Modifiers mods)
       {
-         if(EndGame())
+         if(EndGame(newLocalGame))
          {
             local = true;
             chessState.gameRunning = true;
@@ -180,24 +186,25 @@ class Chess : Window
       gameMenu, "End Game", e;
       bool NotifySelect(MenuItem selection, Modifiers mods)
       {
-         EndGame();
+         EndGame(endGame);
          return true;
       }
    };
 
    MenuItem { gameMenu, "Exit\tAlt+F4", x, NotifySelect = MenuFileExit };
 
+#ifndef CHESS_NONET
    // Network Menu
    MenuItem connectItem
    {
       networkMenu, "Connect...", c;
       bool NotifySelect(MenuItem selection, Modifiers mods)
       {
-         if(EndGame())
+         if(EndGame(connect))
          {
             hosting = false;
             service.Stop();
-            ConnectDialog { master = this }.Modal();
+            ConnectDialog { master = this, isModal = true }.Create();
          }
          return true;
       }
@@ -213,7 +220,7 @@ class Chess : Window
       networkMenu, "Host", h;
       bool NotifySelect(MenuItem selection, Modifiers mods)
       {
-         if(EndGame())
+         if(EndGame(host))
          {
             if(service.Start())
             {
@@ -230,7 +237,7 @@ class Chess : Window
       networkMenu, "Stop Hosting", s;
       bool NotifySelect(MenuItem selection, Modifiers mods)
       {
-         if(EndGame())
+         if(EndGame(stop))
          {
             hosting = false;
             service.Stop();
@@ -239,6 +246,7 @@ class Chess : Window
          return true;
       }
    };
+#endif
 
    // View Menu
    MenuItem fullScreenItem
@@ -272,31 +280,19 @@ class Chess : Window
       helpMenu, "About...\tF1", a, f1;
       bool NotifySelect(MenuItem selection, Modifiers mods)
       {
-         AboutChess { master = this }.Modal();
+         AboutChess { master = this, isModal = true }.Create();
          return true;
       }
    };
 
-   // --- Chess Utilities ---
-   bool MakeMove(int x1, int y1, int x2, int y2, PieceType promotion)
+   int cx1, cy1, cx2, cy2;
+
+   bool DoMove(int x1, int y1, int x2, int y2, PieceType promotion)
    {
       bool valid = false;
-
       PieceType type = chessState.board[y1][x1].type;
       Player player = chessState.board[y1][x1].player;
 
-      // Pawn Promotion
-      if(type == Pawn && y2 == ((player == White) ? 7 : 0))
-      {
-         if(chessState.isLocalPlayer[chessState.turn] &&
-            IsMoveValid(x1,y1,x2,y2, chessState, null, true))
-         {
-            chess2D.Update(null);
-            chess3D.Update(null);
-            promotion = (PieceType)Promotion { master = this }.Modal();
-         }
-      }
-
       if(StateMakeMove(chessState, x1,y1,x2,y2, promotion, true, null))
       {
          valid = true;
@@ -313,7 +309,9 @@ class Chess : Window
                y2 = (byte)y2,
                promotion = promotion
             };
+#ifndef CHESS_NONET
             sockets[player^(Player)1].Send((byte *)&packet, sizeof(ChessPacket));
+#endif
          }
 
          if(player == Black)
@@ -373,6 +371,44 @@ class Chess : Window
       return valid;
    }
 
+   // --- Chess Utilities ---
+   bool MakeMove(int x1, int y1, int x2, int y2, PieceType promotion)
+   {
+      bool valid = false;
+
+      PieceType type = chessState.board[y1][x1].type;
+      Player player = chessState.board[y1][x1].player;
+
+      // Pawn Promotion
+      if(type == Pawn && y2 == ((player == White) ? 7 : 0))
+      {
+         valid = true;
+         if(chessState.isLocalPlayer[chessState.turn] &&
+            (valid = IsMoveValid(x1,y1,x2,y2, chessState, null, true)))
+         {
+            valid = false;
+            cx1 = x1, cy1 = y1, cx2 = x2, cy2 = y2;
+            chess2D.Update(null);
+            chess3D.Update(null);
+            promotion = (PieceType)Promotion
+            {
+               master = this;
+               isModal = true;
+
+               void Chess::NotifyDestroyed(Window promotionDlg, DialogResult r)
+               {
+                  DoMove(cx1, cy1, cx2, cy2, (PieceType)r);
+                  if(ai)
+                     aiThread.Play();
+               }
+            }.Create();
+         }
+      }
+      else
+         valid = DoMove(x1, y1, x2, y2, promotion);
+      return valid;
+   }
+
    void ProcessUserMove(int x1, int y1, int x2, int y2)
    {
       if(MakeMove(x1, y1, x2, y2, 0))
@@ -566,10 +602,12 @@ class Chess : Window
 
    void EnableMenus()
    {
+#ifndef CHESS_NONET
       stopItem.disabled = !hosting;
       disconnectItem.disabled = !sockets[SERVER_COLOR] && !sockets[CLIENT_COLOR];
-      endGameItem.disabled = !chessState.gameRunning;
       hostItem.disabled = hosting;
+#endif
+      endGameItem.disabled = !chessState.gameRunning;
    }
 
    void SetDriver()
@@ -604,20 +642,16 @@ class Chess : Window
       return true;
    }
 
-   bool EndGame()
+   void DoEndGame(GameAction action)
    {
-      if(chessState.gameRunning &&
-         (chessState.state == Normal || chessState.state == Check))
-      {
-         if(MessageBox { type = okCancel, contents = "Quit current game?",
-            master = this, text = "ECERE Chess" }.Modal() == cancel)
-            return false;
-      }
+#ifndef CHESS_NONET
       if(sockets[SERVER_COLOR])
          sockets[SERVER_COLOR].Disconnect(0);
       else if(sockets[CLIENT_COLOR])
          sockets[CLIENT_COLOR].Disconnect(0);
-      else if(local || ai)
+      else
+#endif
+      if(local || ai)
       {
          if(ai) aiThread.Abort();
          local = ai = false;
@@ -628,21 +662,53 @@ class Chess : Window
       turnField.text = "";
       stateField.text = "";
 
+      switch(action)
+      {
+         case newAIGame:    aiItem.NotifySelect(this, aiItem, 0); break;
+         case newLocalGame: localItem.NotifySelect(this, localItem, 0); break;
+      }
+   }
+
+   GameAction nextAction;
+
+   bool EndGame(GameAction action)
+   {
+      if(chessState.gameRunning &&
+         (chessState.state == Normal || chessState.state == Check))
+      {
+         nextAction = action;
+         MessageBox
+         {
+            type = okCancel, contents = "Quit current game?",
+            master = this, text = "ECERE Chess";
+            isModal = true;
+
+            void Chess::NotifyDestroyed(Window msgBox, DialogResult result)
+            {
+               if(result != cancel)
+                  DoEndGame(nextAction);
+            }
+         }.Create();
+         return false;
+      }
       return true;
    }
 
    bool OnClose(bool parentClosing)
    {
-      return EndGame();
+      return EndGame(close);
    }
 
    void OnDestroy()
    {
+#ifndef CHESS_NONET
       delete sockets[Black];
       delete sockets[White];
+#endif
       delete driverItems;
    }
 
+#ifndef CHESS_NONET
    void Connect(const char * address)
    {
       ChessSocket socket { chess = this };
@@ -655,9 +721,11 @@ class Chess : Window
          chessState.isLocalPlayer[SERVER_COLOR] = false;
       }
    }
+#endif
 }
 
 // --- Chess Communications ---
+#ifndef CHESS_NONET
 class ChessSocket : Socket
 {
    Chess chess;
@@ -740,3 +808,4 @@ class ChessService : Service
       }
    }
 }
+#endif
index 838531b..cbf89db 100644 (file)
@@ -385,8 +385,7 @@ class Chess3D : Window
 
    void OnRedraw(Surface surface)
    {
-      //surface.SetBackground(white);
-      surface.Clear(colorAndDepth);
+      surface.Clear(depthBuffer);
 
       camera.Update();
       display.antiAlias = antiAlias;
index 9c97efb..a560b9d 100644 (file)
@@ -1,5 +1,6 @@
 import "chess.ec"
 
+#ifndef CHESS_NONET
 class ConnectDialog : Window
 {
    minClientSize = Size { 300, 100 };
@@ -36,3 +37,4 @@ class ConnectDialog : Window
       line.text = "localhost"
    };
 }
+#endif
index ab8c3f3..47662a1 100644 (file)
                }
             }
          ]
+      },
+      {
+         "Name" : "Emscripten",
+         "Options" : {
+            "Optimization" : "Speed",
+            "PreprocessorDefinitions" : [
+               "IMPORT_STATIC=static"
+            ],
+            "TargetFileName" : "mekano.html",
+            "Libraries" : [
+               "ecereStatic",
+               "z",
+               "freetype",
+               "png",
+               "jpeg"
+            ],
+            "LibraryDirs" : [
+               "../../../ecere/obj/emscripten.linux.emscripten"
+            ],
+            "FastMath" : true
+         }
       }
    ],
    "Files" : [
index 8bc4adc..106972e 100644 (file)
@@ -1,6 +1,6 @@
 import "mekanodisplay"
 
-class MekanoSimulation
+class MekanoSimulation : struct
 {
 private:
    List<MekanoObject> m_Objects { };
index e2c553b..1d65386 100644 (file)
@@ -25,9 +25,13 @@ private:
 public:
 
    caption = "Mekano";
+#if defined(__EMSCRIPTEN__) || defined(__ANDROID__)
+   anchor = { 0, 0, 0, 0 };
+#else
+   clientSize = { 640, 480 };
    hasMaximize = true, hasMinimize = true, hasClose = true;
    borderStyle = sizable;
-   clientSize = { 640, 480 };
+#endif
    background = slateGray;
 
    BitmapResource bg { ":ecere.bmp", window = this };