mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-08-11 17:17:42 +03:00
UILoader rendering glitch fix. Git create branch fix checkout in subrepos. UIMessageBox don't focus on any disabled input by default.
625 lines
16 KiB
C++
625 lines
16 KiB
C++
#include <SOIL2/src/SOIL2/SOIL2.h>
|
|
#include <eepp/graphics/globalbatchrenderer.hpp>
|
|
#include <eepp/graphics/renderer/openglext.hpp>
|
|
#include <eepp/graphics/renderer/renderer.hpp>
|
|
#include <eepp/graphics/texturefactory.hpp>
|
|
#include <eepp/system/filesystem.hpp>
|
|
#include <eepp/version.hpp>
|
|
#include <eepp/window/clipboard.hpp>
|
|
#include <eepp/window/cursormanager.hpp>
|
|
#include <eepp/window/engine.hpp>
|
|
#include <eepp/window/input.hpp>
|
|
#include <eepp/window/window.hpp>
|
|
|
|
#ifdef EE_GLES1_LATE_INCLUDE
|
|
#if EE_PLATFORM == EE_PLATFORM_IOS
|
|
#include <OpenGLES/ES1/gl.h>
|
|
#include <OpenGLES/ES1/glext.h>
|
|
#else
|
|
#include <GLES/gl.h>
|
|
|
|
#ifndef GL_GLEXT_PROTOTYPES
|
|
#define GL_GLEXT_PROTOTYPES
|
|
#endif
|
|
|
|
#include <GLES/glext.h>
|
|
#endif
|
|
#endif
|
|
|
|
#if EE_PLATFORM == EE_PLATFORM_EMSCRIPTEN
|
|
#include <emscripten.h>
|
|
#endif
|
|
|
|
namespace EE { namespace Window {
|
|
|
|
Window::FrameData::FrameData() : FrameElapsed( NULL ), ElapsedTime() {}
|
|
|
|
Window::FrameData::~FrameData() {
|
|
eeSAFE_DELETE( FrameElapsed );
|
|
}
|
|
|
|
Window::Window( WindowSettings Settings, ContextSettings Context, Clipboard* Clipboard,
|
|
Input* Input, CursorManager* CursorManager ) :
|
|
mClipboard( Clipboard ),
|
|
mInput( Input ),
|
|
mCursorManager( CursorManager ),
|
|
mCurrentView( NULL ),
|
|
mNumCallBacks( 0 ),
|
|
mIME( this ) {
|
|
mWindow.WindowConfig = Settings;
|
|
mWindow.ContextConfig = Context;
|
|
setFrameRateLimit( Context.FrameRateLimit );
|
|
}
|
|
|
|
Window::~Window() {
|
|
eeSAFE_DELETE( mClipboard );
|
|
eeSAFE_DELETE( mInput );
|
|
eeSAFE_DELETE( mCursorManager );
|
|
}
|
|
|
|
Sizei Window::getSize() {
|
|
return Sizei( mWindow.WindowConfig.Width, mWindow.WindowConfig.Height );
|
|
}
|
|
|
|
Vector2f Window::getCenter() {
|
|
return Sizef( mWindow.WindowConfig.Width, mWindow.WindowConfig.Height ) * 0.5f;
|
|
}
|
|
|
|
const Uint32& Window::getWidth() const {
|
|
return mWindow.WindowConfig.Width;
|
|
}
|
|
|
|
const Uint32& Window::getHeight() const {
|
|
return mWindow.WindowConfig.Height;
|
|
}
|
|
|
|
const Sizei& Window::getDesktopResolution() {
|
|
return mWindow.DesktopResolution;
|
|
}
|
|
|
|
void Window::setSize( Uint32 Width, Uint32 Height ) {
|
|
setSize( Width, Height, isWindowed() );
|
|
}
|
|
|
|
bool Window::isWindowed() const {
|
|
return 0 != !( mWindow.WindowConfig.Style & WindowStyle::Fullscreen );
|
|
}
|
|
|
|
bool Window::isResizeable() const {
|
|
return 0 != ( mWindow.WindowConfig.Style & WindowStyle::Resize );
|
|
}
|
|
|
|
void Window::set2DProjection( const Uint32& Width, const Uint32& Height ) {
|
|
GLi->matrixMode( GL_PROJECTION );
|
|
GLi->loadIdentity();
|
|
|
|
GLi->ortho( 0.0f, Width, Height, 0.0f, -1000.0f, 1000.0f );
|
|
|
|
GLi->matrixMode( GL_MODELVIEW );
|
|
GLi->loadIdentity();
|
|
}
|
|
|
|
void Window::setProjection( const Transform& transform ) {
|
|
GLi->matrixMode( GL_PROJECTION );
|
|
GLi->loadMatrixf( transform.getMatrix() );
|
|
|
|
GLi->matrixMode( GL_MODELVIEW );
|
|
GLi->loadIdentity();
|
|
}
|
|
|
|
Vector2f Window::mapPixelToCoords( const Vector2i& point ) {
|
|
return mapPixelToCoords( point, getView() );
|
|
}
|
|
|
|
Vector2f Window::mapPixelToCoords( const Vector2i& point, const View& view ) {
|
|
// First, convert from viewport coordinates to homogeneous coordinates
|
|
Vector2f normalized;
|
|
Rect viewport = getViewport( view );
|
|
normalized.x = -1.f + 2.f * ( point.x - viewport.Left ) / viewport.Right;
|
|
normalized.y = 1.f - 2.f * ( point.y - viewport.Top ) / viewport.Bottom;
|
|
|
|
// Then transform by the inverse of the view matrix
|
|
return view.getInverseTransform().transformPoint( normalized );
|
|
}
|
|
|
|
Vector2i Window::mapCoordsToPixel( const Vector2f& point ) {
|
|
return mapCoordsToPixel( point, getView() );
|
|
}
|
|
|
|
Vector2i Window::mapCoordsToPixel( const Vector2f& point, const View& view ) {
|
|
// First, transform the point by the view matrix
|
|
Vector2f normalized = view.getTransform().transformPoint( point );
|
|
|
|
// Then convert to viewport coordinates
|
|
Vector2i pixel;
|
|
Rect viewport = getViewport( view );
|
|
pixel.x = static_cast<int>( ( normalized.x + 1.f ) / 2.f * viewport.Right + viewport.Left );
|
|
pixel.y = static_cast<int>( ( -normalized.y + 1.f ) / 2.f * viewport.Bottom + viewport.Top );
|
|
|
|
return pixel;
|
|
}
|
|
|
|
void Window::setCloseRequestCallback( const WindowRequestCloseCallback& closeRequestCallback ) {
|
|
mCloseRequestCallback = closeRequestCallback;
|
|
}
|
|
|
|
void Window::setQuitCallback( const WindowQuitCallback& quitCallback ) {
|
|
mQuitCallback = quitCallback;
|
|
}
|
|
|
|
void Window::setViewport( const Int32& x, const Int32& y, const Uint32& Width,
|
|
const Uint32& Height ) {
|
|
GLi->viewport( x, getHeight() - ( y + Height ), Width, Height );
|
|
}
|
|
|
|
Rect Window::getViewport( const View& view ) {
|
|
float width = static_cast<float>( getSize().getWidth() );
|
|
float height = static_cast<float>( getSize().getHeight() );
|
|
const Rectf& viewport = view.getViewport();
|
|
|
|
return Rect( static_cast<int>( 0.5f + width * viewport.Left ),
|
|
static_cast<int>( 0.5f + height * viewport.Top ),
|
|
static_cast<int>( 0.5f + width * viewport.Right ),
|
|
static_cast<int>( 0.5f + height * viewport.Bottom ) );
|
|
}
|
|
|
|
void Window::setView( const View& view, bool forceRefresh ) {
|
|
const View* viewPtr = &view;
|
|
|
|
if ( viewPtr != mCurrentView || viewPtr->isDirty() || forceRefresh ) {
|
|
mCurrentView = viewPtr;
|
|
|
|
Rect viewport = getViewport( *mCurrentView );
|
|
|
|
setViewport( viewport.Left, viewport.Top, viewport.Right, viewport.Bottom );
|
|
|
|
setProjection( viewPtr->getTransform() );
|
|
}
|
|
}
|
|
|
|
const View& Window::getDefaultView() const {
|
|
return mDefaultView;
|
|
}
|
|
|
|
const View& Window::getView() const {
|
|
return *mCurrentView;
|
|
}
|
|
|
|
void Window::createView() {
|
|
mDefaultView.reset( Rectf( 0, 0, mWindow.WindowConfig.Width, mWindow.WindowConfig.Height ) );
|
|
setView( mDefaultView );
|
|
}
|
|
|
|
void Window::setup2D( const bool& KeepView ) {
|
|
EE::Window::Window* curWin = Engine::instance()->getCurrentWindow();
|
|
if ( curWin != this )
|
|
Engine::instance()->setCurrentWindow( this );
|
|
|
|
GLi->pixelStorei( GL_UNPACK_ALIGNMENT, 1 );
|
|
GLi->pixelStorei( GL_PACK_ALIGNMENT, 1 );
|
|
|
|
setClearColor( mWindow.ClearColor );
|
|
|
|
GLi->lineSmooth();
|
|
|
|
GLi->enable( GL_TEXTURE_2D ); // Enable Textures
|
|
GLi->disable( GL_DEPTH_TEST );
|
|
|
|
if ( GLv_2 == GLi->version() || GLv_ES1 == GLi->version() ) {
|
|
GLi->disable( GL_LIGHTING );
|
|
}
|
|
|
|
if ( !KeepView ) {
|
|
setView( mDefaultView, true );
|
|
}
|
|
|
|
BlendMode::setMode( BlendMode::Alpha(), true );
|
|
|
|
if ( GLv_3CP != GLi->version() && GLv_3 != GLi->version() && GLv_ES2 != GLi->version() ) {
|
|
#if !defined( EE_GLES2 ) || defined( EE_GLES_BOTH )
|
|
glTexEnvi( GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE );
|
|
#endif
|
|
}
|
|
|
|
if ( GLv_2 == GLi->version() || GLv_ES1 == GLi->version() ) {
|
|
GLi->enableClientState( GL_VERTEX_ARRAY );
|
|
GLi->enableClientState( GL_TEXTURE_COORD_ARRAY );
|
|
GLi->enableClientState( GL_COLOR_ARRAY );
|
|
}
|
|
|
|
if ( curWin != this )
|
|
Engine::instance()->setCurrentWindow( curWin );
|
|
}
|
|
|
|
const WindowInfo* Window::getWindowInfo() const {
|
|
return &mWindow;
|
|
}
|
|
|
|
void Window::setClearColor( const RGB& Color ) {
|
|
mWindow.ClearColor = Color;
|
|
GLi->clearColor( static_cast<Float>( mWindow.ClearColor.r ) / 255.0f,
|
|
static_cast<Float>( mWindow.ClearColor.g ) / 255.0f,
|
|
static_cast<Float>( mWindow.ClearColor.b ) / 255.0f, 255.0f );
|
|
}
|
|
|
|
RGB Window::getClearColor() const {
|
|
return mWindow.ClearColor;
|
|
}
|
|
|
|
bool Window::takeScreenshot( std::string filepath, const Image::SaveType& Format ) {
|
|
GlobalBatchRenderer::instance()->draw();
|
|
|
|
bool CreateNewFile = false;
|
|
std::string File, Ext;
|
|
|
|
if ( filepath.size() ) {
|
|
File = filepath.substr( filepath.find_last_of( "/\\" ) + 1 );
|
|
Ext = File.substr( File.find_last_of( "." ) + 1 );
|
|
|
|
if ( FileSystem::isDirectory( filepath ) || !Ext.size() )
|
|
CreateNewFile = true;
|
|
} else {
|
|
filepath = Sys::getProcessPath();
|
|
CreateNewFile = true;
|
|
}
|
|
|
|
if ( CreateNewFile ) { // Search if file path is given, and if have and extension
|
|
bool find = false;
|
|
Int32 FileNum = 1;
|
|
std::string TmpPath = filepath;
|
|
|
|
if ( !FileSystem::isDirectory( filepath ) )
|
|
FileSystem::makeDir( filepath );
|
|
|
|
Ext = "." + Image::saveTypeToExtension( Format );
|
|
|
|
while ( !find && FileNum < 10000 ) {
|
|
TmpPath = String::format( "%s%05d%s", filepath.c_str(), FileNum, Ext.c_str() );
|
|
|
|
FileNum++;
|
|
|
|
if ( !FileSystem::fileExists( TmpPath ) )
|
|
find = true;
|
|
|
|
if ( FileNum == 10000 && find == false )
|
|
return false;
|
|
}
|
|
|
|
return 0 != SOIL_save_screenshot( TmpPath.c_str(), Format, 0, 0, mWindow.WindowConfig.Width,
|
|
mWindow.WindowConfig.Height );
|
|
} else {
|
|
std::string Direc = FileSystem::fileRemoveFileName( filepath );
|
|
|
|
if ( !FileSystem::isDirectory( Direc ) )
|
|
FileSystem::makeDir( Direc );
|
|
|
|
return 0 != SOIL_save_screenshot( filepath.c_str(), Format, 0, 0,
|
|
mWindow.WindowConfig.Width, mWindow.WindowConfig.Height );
|
|
}
|
|
}
|
|
|
|
bool Window::isRunning() const {
|
|
return mWindow.Created;
|
|
}
|
|
|
|
bool Window::isOpen() const {
|
|
return mWindow.Created;
|
|
}
|
|
|
|
void Window::close() {
|
|
mWindow.Created = false;
|
|
}
|
|
|
|
void Window::setFrameRateLimit( const Uint32& FrameRateLimit ) {
|
|
mFrameData.FPS.Limit = (Float)FrameRateLimit;
|
|
}
|
|
|
|
Uint32 Window::getFrameRateLimit() {
|
|
return static_cast<Uint32>( mFrameData.FPS.Limit );
|
|
}
|
|
|
|
Uint32 Window::getFPS() const {
|
|
return mFrameData.FPS.Current;
|
|
}
|
|
|
|
const Time& Window::getElapsed() const {
|
|
return mFrameData.ElapsedTime;
|
|
}
|
|
|
|
void Window::updateElapsedTime() {
|
|
if ( NULL == mFrameData.FrameElapsed ) {
|
|
mFrameData.FrameElapsed = eeNew( Clock, () );
|
|
}
|
|
|
|
mFrameData.ElapsedTime = mFrameData.FrameElapsed->getElapsedTimeAndReset();
|
|
}
|
|
|
|
const Time& Window::getSleepTimePerSecond() const {
|
|
return mFrameData.FPS.CurSleepTime;
|
|
}
|
|
|
|
const Time& Window::getRenderTimePerSecond() const {
|
|
return mFrameData.FPS.CurRenderTime;
|
|
}
|
|
|
|
const Sizei& Window::getLastWindowedSize() const {
|
|
return mLastWindowedSize;
|
|
}
|
|
|
|
bool Window::showMessageBox( const MessageBoxType&, const std::string&, const std::string& ) {
|
|
return false;
|
|
}
|
|
|
|
InputMethod& Window::getIME() {
|
|
return mIME;
|
|
}
|
|
|
|
void Window::calculateFps() {
|
|
if ( mFrameData.FPS.LastCheck.getElapsedTime().asSeconds() >= 1.f ) {
|
|
mFrameData.FPS.Current = mFrameData.FPS.Count;
|
|
mFrameData.FPS.Count = 0;
|
|
mFrameData.FPS.CurSleepTime = mFrameData.FPS.SleepTime;
|
|
mFrameData.FPS.SleepTime = Time::Zero;
|
|
mFrameData.FPS.CurRenderTime = mFrameData.FPS.RenderTime;
|
|
mFrameData.FPS.RenderTime = Time::Zero;
|
|
mFrameData.FPS.LastCheck.restart();
|
|
}
|
|
|
|
mFrameData.FPS.Count++;
|
|
}
|
|
|
|
void Window::limitFps() {
|
|
if ( mFrameData.FPS.Limit > 0 ) {
|
|
Time frameTime( Milliseconds( 1000.0 / mFrameData.FPS.Limit ) );
|
|
Time remainingTime = frameTime - mFrameData.FPS.FrameTime;
|
|
|
|
if ( frameTime - mFrameData.ElapsedTime > Time::Zero ) {
|
|
remainingTime += mFrameData.FPS.Error;
|
|
}
|
|
|
|
mFrameData.FPS.Error = Time::Zero;
|
|
|
|
if ( remainingTime > Time::Zero ) {
|
|
Clock checkElapsed;
|
|
|
|
Sys::sleep( remainingTime );
|
|
|
|
Time elapsed = checkElapsed.getElapsedTimeAndReset();
|
|
Time timeDiff = elapsed - remainingTime;
|
|
|
|
mFrameData.FPS.SleepTime += elapsed;
|
|
|
|
if ( timeDiff > Time::Zero ) {
|
|
mFrameData.FPS.Error += timeDiff;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Window::clear() {
|
|
GLi->clear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
|
|
}
|
|
|
|
void Window::display( bool clear ) {
|
|
GlobalBatchRenderer::instance()->draw();
|
|
|
|
swapBuffers();
|
|
|
|
if ( mCurrentView->isDirty() )
|
|
setView( *mCurrentView );
|
|
|
|
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN
|
|
if ( clear )
|
|
this->clear();
|
|
#endif
|
|
|
|
mFrameData.FPS.FrameTime = mFrameData.FPS.RenderClock.getElapsedTime();
|
|
mFrameData.FPS.RenderTime += mFrameData.FPS.FrameTime;
|
|
|
|
updateElapsedTime();
|
|
|
|
limitFps();
|
|
|
|
calculateFps();
|
|
|
|
mFrameData.FPS.RenderClock.restart();
|
|
}
|
|
|
|
Clipboard* Window::getClipboard() const {
|
|
return mClipboard;
|
|
}
|
|
|
|
Input* Window::getInput() const {
|
|
return mInput;
|
|
}
|
|
|
|
CursorManager* Window::getCursorManager() const {
|
|
return mCursorManager;
|
|
}
|
|
|
|
Uint32 Window::pushResizeCallback( const WindowResizeCallback& cb ) {
|
|
mNumCallBacks++;
|
|
mCallbacks[mNumCallBacks] = cb;
|
|
return mNumCallBacks;
|
|
}
|
|
|
|
void Window::popResizeCallback( const Uint32& CallbackId ) {
|
|
mCallbacks[CallbackId] = 0;
|
|
mCallbacks.erase( mCallbacks.find( CallbackId ) );
|
|
}
|
|
|
|
void Window::startOnScreenKeyboard() {}
|
|
|
|
void Window::stopOnScreenKeyboard() {}
|
|
|
|
bool Window::isOnScreenKeyboardActive() const {
|
|
return false;
|
|
}
|
|
|
|
void Window::sendVideoResizeCb() {
|
|
for ( std::map<Uint32, WindowResizeCallback>::iterator i = mCallbacks.begin();
|
|
i != mCallbacks.end(); ++i ) {
|
|
i->second( this );
|
|
}
|
|
}
|
|
|
|
void Window::logSuccessfulInit( const std::string& BackendName ) {
|
|
std::string msg(
|
|
"Engine Initialized Succesfully.\n\tVersion: " + Version::getVersionName() +
|
|
" (codename: \"" + Version::getCodename() + "\")" +
|
|
"\n\tBuild time: " + Version::getBuildTime() + "\n\tPlatform: " + Sys::getPlatform() +
|
|
"\n\tOS: " + Sys::getOSName( true ) + "\n\tArch: " + Sys::getOSArchitecture() +
|
|
"\n\tCPU Cores: " + String::toString( Sys::getCPUCount() ) +
|
|
"\n\tProcess Path: " + Sys::getProcessPath() + "\n\tCurrent Working Directory: " +
|
|
FileSystem::getCurrentWorkingDirectory() + "\n\tDisk Free Space: " +
|
|
String::toString(
|
|
FileSystem::sizeToString( FileSystem::getDiskFreeSpace( Sys::getProcessPath() ) ) ) +
|
|
"\n\tWindow/Input Backend: " + BackendName + "\n\tGL Backend: " + GLi->versionStr() +
|
|
"\n\tGL Vendor: " + GLi->getVendor() + "\n\tGL Renderer: " + GLi->getRenderer() +
|
|
"\n\tGL Version: " + GLi->getVersion() + "\n\tGL Shading Language Version: " +
|
|
GLi->getShadingLanguageVersion() + "\n\tResolution: " + String::toString( getWidth() ) +
|
|
"x" + String::toString( getHeight() ) );
|
|
|
|
#ifndef EE_SILENT
|
|
Log::info( msg );
|
|
#else
|
|
Log::instance()->writel( msg );
|
|
#endif
|
|
}
|
|
|
|
void Window::logFailureInit( const std::string& ClassName, const std::string& BackendName ) {
|
|
Log::error( "Error on %s::Init. Backend %s failed to start.", ClassName.c_str(),
|
|
BackendName.c_str() );
|
|
}
|
|
|
|
void Window::onCloseRequest() {
|
|
if ( mCloseRequestCallback && !mCloseRequestCallback( this ) )
|
|
return;
|
|
|
|
close();
|
|
}
|
|
|
|
void Window::onQuit() {
|
|
if ( mQuitCallback )
|
|
mQuitCallback( this );
|
|
}
|
|
|
|
std::string Window::getTitle() {
|
|
return mWindow.WindowConfig.Title;
|
|
}
|
|
|
|
eeWindowContex Window::getContext() const {
|
|
#if defined( EE_GLEW_AVAILABLE ) && \
|
|
( EE_PLATFORM == EE_PLATFORM_WIN || defined( EE_X11_PLATFORM ) || \
|
|
EE_PLATFORM == EE_PLATFORM_MACOS )
|
|
return mWindow.Context;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
void Window::getMainContext() {}
|
|
|
|
void Window::setDefaultContext() {
|
|
#if defined( EE_GLEW_AVAILABLE ) && ( EE_PLATFORM == EE_PLATFORM_WIN || defined( EE_X11_PLATFORM ) )
|
|
setCurrentContext( mWindow.Context );
|
|
#endif
|
|
}
|
|
|
|
void Window::minimize() {}
|
|
|
|
void Window::maximize() {}
|
|
|
|
bool Window::isMaximized() {
|
|
return false;
|
|
}
|
|
|
|
void Window::hide() {}
|
|
|
|
void Window::raise() {}
|
|
|
|
void Window::flash( WindowFlashOperation ) {}
|
|
|
|
void Window::show() {}
|
|
|
|
void Window::setPosition( int, int ) {}
|
|
|
|
Vector2i Window::getPosition() {
|
|
return Vector2i::Zero;
|
|
}
|
|
|
|
void Window::setCurrentContext( eeWindowContex ) {}
|
|
|
|
void Window::setCurrent() {}
|
|
|
|
void Window::centerToDisplay() {
|
|
if ( isWindowed() ) {
|
|
setPosition( mWindow.DesktopResolution.getWidth() / 2 - mWindow.WindowConfig.Width / 2,
|
|
mWindow.DesktopResolution.getHeight() / 2 - mWindow.WindowConfig.Height / 2 );
|
|
}
|
|
}
|
|
|
|
Rect Window::getBorderSize() {
|
|
return Rect();
|
|
}
|
|
|
|
Float Window::getScale() {
|
|
return 1.f;
|
|
}
|
|
|
|
void Window::startTextInput() {}
|
|
|
|
bool Window::isTextInputActive() const {
|
|
return false;
|
|
}
|
|
|
|
void Window::stopTextInput() {}
|
|
|
|
void Window::setTextInputRect( const Rect& ) {}
|
|
|
|
void Window::clearComposition() {}
|
|
|
|
bool Window::hasScreenKeyboardSupport() {
|
|
return false;
|
|
}
|
|
|
|
bool Window::isScreenKeyboardShown() {
|
|
return false;
|
|
}
|
|
|
|
bool Window::isThreadedGLContext() {
|
|
return false;
|
|
}
|
|
|
|
void Window::setGLContextThread() {}
|
|
|
|
void Window::unsetGLContextThread() {}
|
|
|
|
#if EE_PLATFORM == EE_PLATFORM_EMSCRIPTEN
|
|
static void eepp_mainloop() {
|
|
Engine::instance()->getCurrentWindow()->getMainLoop()();
|
|
}
|
|
#endif
|
|
|
|
void Window::runMainLoop( std::function<void()> func, int fps ) {
|
|
mMainLoop = std::move( func );
|
|
|
|
#if EE_PLATFORM == EE_PLATFORM_EMSCRIPTEN
|
|
emscripten_set_main_loop( eepp_mainloop, std::max( mFrameData.FPS.Limit, std::max( 0, fps ) ),
|
|
1 );
|
|
#else
|
|
if ( fps >= 0 )
|
|
setFrameRateLimit( fps );
|
|
|
|
while ( isRunning() ) {
|
|
mMainLoop();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
int Window::getCurrentDisplayIndex() {
|
|
return 0;
|
|
}
|
|
|
|
}} // namespace EE::Window
|