Переглянути джерело

engine source changes for emscripten

t 11 роки тому
батько
коміт
5d92f18b46

+ 5 - 5
Source/Urho3D/Core/ProcessUtils.cpp

@@ -46,7 +46,7 @@
 
 #if defined(_MSC_VER)
 #include <float.h>
-#elif !defined(ANDROID) && !defined(IOS) && !defined(RPI)
+#elif !defined(ANDROID) && !defined(IOS) && !defined(RPI) && !defined(EMSCRIPTEN)
 // From http://stereopsis.com/FPU.html
 
 #define FPU_CW_PREC_MASK        0x0300
@@ -90,7 +90,7 @@ static void GetCPUData(host_basic_info_data_t* data)
     infoCount = HOST_BASIC_INFO_COUNT;
     host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)data, &infoCount);
 }
-#elif !defined(ANDROID) && !defined(RPI)
+#elif !defined(ANDROID) && !defined(RPI) && !defined(EMSCRIPTEN)
 static void GetCPUData(struct cpu_id_t* data)
 {
     if (cpu_identify(0, data) < 0)
@@ -103,7 +103,7 @@ static void GetCPUData(struct cpu_id_t* data)
 
 void InitFPU()
 {
-    #if !defined(URHO3D_LUAJIT) && !defined(ANDROID) && !defined(IOS) && !defined(RPI) && !defined(__x86_64__) && !defined(_M_AMD64)
+    #if !defined(URHO3D_LUAJIT) && !defined(ANDROID) && !defined(IOS) && !defined(RPI) && !defined(__x86_64__) && !defined(_M_AMD64) && !defined(EMSCRIPTEN)
     // Make sure FPU is in round-to-nearest, single precision mode
     // This ensures Direct3D and OpenGL behave similarly, and all threads behave similarly
     #ifdef _MSC_VER
@@ -392,7 +392,7 @@ unsigned GetNumPhysicalCPUs()
     #endif
     #elif defined(ANDROID)
     return GetAndroidCPUCount();
-    #elif !defined(ANDROID) && !defined(RPI)
+    #elif !defined(ANDROID) && !defined(RPI) && !defined(EMSCRIPTEN)
     struct cpu_id_t data;
     GetCPUData(&data);
     return data.num_cores;
@@ -414,7 +414,7 @@ unsigned GetNumLogicalCPUs()
     #endif
     #elif defined(ANDROID)
     return GetAndroidCPUCount();
-    #elif !defined(ANDROID) && !defined(RPI)
+    #elif !defined(ANDROID) && !defined(RPI) && !defined(EMSCRIPTEN)
     struct cpu_id_t data;
     GetCPUData(&data);
     return data.num_logical_cpus;

+ 13 - 3
Source/Urho3D/Core/Thread.cpp

@@ -45,7 +45,11 @@ void* ThreadFunctionStatic(void* data)
 {
     Thread* thread = static_cast<Thread*>(data);
     thread->ThreadFunction();
+#ifdef EMSCRIPTEN
+// note: emscripten doesn't have this function but doesn't use threading anyway
+// so #ifdef it out to prevent linker warnings
     pthread_exit((void*)0);
+#endif
     return 0;
 }
 #endif
@@ -72,7 +76,10 @@ bool Thread::Run()
     shouldRun_ = true;
     #ifdef WIN32
     handle_ = CreateThread(0, 0, ThreadFunctionStatic, this, 0, 0);
-    #else
+//    #else
+    #elif !defined(EMSCRIPTEN)
+// note: emscripten doesn't have this function but doesn't use
+// threading anyway so #ifdef it out to prevent linker warnings
     handle_ = new pthread_t;
     pthread_attr_t type;
     pthread_attr_init(&type);
@@ -92,7 +99,10 @@ void Thread::Stop()
     #ifdef WIN32
     WaitForSingleObject((HANDLE)handle_, INFINITE);
     CloseHandle((HANDLE)handle_);
-    #else
+//    #else
+    #elif !defined(EMSCRIPTEN)
+ // note: emscripten doesn't have this function but doesn't use
+ // threading anyway so #ifdef it out to prevent linker warnings
     pthread_t* thread = (pthread_t*)handle_;
     if (thread)
         pthread_join(*thread, 0);
@@ -107,7 +117,7 @@ void Thread::SetPriority(int priority)
     if (handle_)
         SetThreadPriority((HANDLE)handle_, priority);
     #endif
-    #if defined(__linux__) && !defined(ANDROID)
+    #if defined(__linux__) && !defined(ANDROID) && !defined(EMSCRIPTEN)
     pthread_t* thread = (pthread_t*)handle_;
     if (thread)
         pthread_setschedprio(*thread, priority);

+ 27 - 3
Source/Urho3D/Engine/Application.cpp

@@ -45,6 +45,19 @@ void RunFrame(void* data)
     instance->GetSubsystem<Engine>()->RunFrame();
 }
 #endif
+
+#if defined(EMSCRIPTEN)
+#include <emscripten.h>
+// REVISIT: it seems there should only be one instance of Application
+// and it's needed here as there's no way to pass it along with a callback
+// for emscripten_set_main_loop() so just store a static pointer here for now
+static Application *emInstance = 0;
+void RunFrame()
+{
+    if (emInstance)
+        emInstance->GetSubsystem<Engine>()->RunFrame();
+}
+#endif
     
 Application::Application(Context* context) :
     Object(context),
@@ -61,12 +74,14 @@ Application::Application(Context* context) :
 
 int Application::Run()
 {
+#if !defined(EMSCRIPTEN) // TODO: do we really need to do this?
     try
     {
+#endif
         Setup();
         if (exitCode_)
             return exitCode_;
-
+		
         if (!engine_->Initialize(engineParameters_))
         {
             ErrorExit();
@@ -77,8 +92,8 @@ int Application::Run()
         if (exitCode_)
             return exitCode_;
 
-        // Platforms other than iOS run a blocking main loop
-        #ifndef IOS
+        // Platforms other than iOS and EMSCRIPTEN run a blocking main loop
+        #if !defined(IOS) && !defined(EMSCRIPTEN)
         while (!engine_->IsExiting())
             engine_->RunFrame();
 
@@ -86,16 +101,25 @@ int Application::Run()
         // iOS will setup a timer for running animation frames so eg. Game Center can run. In this case we do not
         // support calling the Stop() function, as the application will never stop manually
         #else
+        #if defined(IOS)
         SDL_iPhoneSetAnimationCallback(GetSubsystem<Graphics>()->GetImpl()->GetWindow(), 1, &RunFrame, this);
+        #else
+        // EMSCRIPTEN
+        emInstance = this; 
+        emscripten_set_main_loop(RunFrame, 0, 1);
+	
+        #endif
         #endif
         
         return exitCode_;
+#if !defined(EMSCRIPTEN)
     }
     catch (std::bad_alloc&)
     {
         ErrorDialog(GetTypeName(), "An out-of-memory error occurred. The application will now exit.");
         return EXIT_FAILURE;
     }
+#endif
 }
 
 void Application::ErrorExit(const String& message)

+ 9 - 1
Source/Urho3D/Graphics/OpenGL/OGLGraphics.cpp

@@ -310,6 +310,7 @@ void Graphics::SetWindowPosition(int x, int y)
 bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless, bool resizable, bool vsync, bool tripleBuffer, int multiSample)
 {
     PROFILE(SetScreenMode);
+LOGINFO("Graphics::SetMode()");
 
     bool maximize = false;
     
@@ -322,8 +323,12 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
         fullscreen = false;
 
     multiSample = Clamp(multiSample, 1, 16);
+bool isInitialized = IsInitialized();
+LOGINFO(isInitialized ? "isInitialized == true" : "isInitialized == false");
+
     
-    if (IsInitialized() && width == width_ && height == height_ && fullscreen == fullscreen_ && borderless == borderless_ && resizable == resizable_ &&
+    //if (IsInitialized() && width == width_ && height == height_ && fullscreen == fullscreen_ && borderless == borderless_ && resizable == resizable_ &&
+    if (isInitialized && width == width_ && height == height_ && fullscreen == fullscreen_ && borderless == borderless_ && resizable == resizable_ &&
         vsync == vsync_ && tripleBuffer == tripleBuffer_ && multiSample == multiSample_)
         return true;
     
@@ -353,6 +358,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
             height = 768;
         }
     }
+
     
     // Check fullscreen mode validity (desktop only). Use a closest match if not found
     #if !defined(ANDROID) && !defined(IOS) && !defined(RPI)
@@ -442,9 +448,11 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
                 impl_->window_ = SDL_CreateWindow(windowTitle_.CString(), x, y, width, height, flags);
             else
             {
+#if !defined(EMSCRIPTEN)
                 if (!impl_->window_)
                     impl_->window_ = SDL_CreateWindowFrom(externalWindow_, SDL_WINDOW_OPENGL);
                 fullscreen = false;
+#endif
             }
             
             if (impl_->window_)

+ 19 - 0
Source/Urho3D/Input/Input.cpp

@@ -106,7 +106,11 @@ Input::Input(Context* context) :
     mouseMoveWheel_(0),
     windowID_(0),
     toggleFullscreen_(true),
+#if defined(EMSCRIPTEN) // TODO: properly implement relative mouse motion with emscripten
+    mouseVisible_(true),
+#else
     mouseVisible_(false),
+#endif
     lastMouseVisible_(false),
     mouseGrabbed_(false),
     mouseMode_(MM_ABSOLUTE),
@@ -721,14 +725,21 @@ unsigned Input::LoadGestures(Deserializer& source)
     return SDL_LoadDollarTemplates(-1, wrapper.GetRWOps());
 }
 
+
 bool Input::RemoveGesture(unsigned gestureID)
 {
+#if defined(EMSCRIPTEN)
+    return false;
+#else
     return SDL_RemoveDollarTemplate(gestureID) != 0;
+#endif
 }
 
 void Input::RemoveAllGestures()
 {
+#if !defined(EMSCRIPTEN)
     SDL_RemoveAllDollarTemplates();
+#endif
 }
 
 SDL_JoystickID Input::OpenJoystick(unsigned index)
@@ -1248,11 +1259,19 @@ void Input::HandleSDLEvent(void* sdlEvent)
     {
     case SDL_KEYDOWN:
         // Convert to uppercase to match Win32 virtual key codes
+#if defined (EMSCRIPTEN)
+        SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, 0, true);
+#else
         SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, evt.key.keysym.raw, true);
+#endif
         break;
 
     case SDL_KEYUP:
+#if defined(EMSCRIPTEN)
+        SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, 0, false);
+#else
         SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, evt.key.keysym.raw, false);
+#endif
         break;
 
     case SDL_TEXTINPUT: