From 0120b7554cdabbf1652a6cd6fbc8b649f9b46313 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Tue, 8 Jan 2013 19:31:41 -0200 Subject: [PATCH] Restore support for animated png files * Rework resource manager * Add missing files * Improve some graphics classes --- src/client/creatures.cpp | 8 +- src/client/houses.cpp | 2 +- src/client/spritemanager.cpp | 2 +- src/client/thingtypemanager.cpp | 2 +- src/framework/core/application.cpp | 4 +- src/framework/core/eventdispatcher.cpp | 2 +- src/framework/core/filestream.cpp | 12 + src/framework/core/filestream.h | 1 + src/framework/core/graphicalapplication.cpp | 2 +- src/framework/core/module.cpp | 8 +- src/framework/core/resourcemanager.cpp | 76 ++-- src/framework/core/resourcemanager.h | 12 +- src/framework/core/scheduledevent.h | 2 +- src/framework/graphics/animatedtexture.cpp | 75 ++-- src/framework/graphics/animatedtexture.h | 24 +- src/framework/graphics/bitmapfont.cpp | 8 +- src/framework/graphics/cachedtext.h | 4 +- src/framework/graphics/coordsbuffer.h | 5 + src/framework/graphics/fontmanager.cpp | 12 +- src/framework/graphics/fontmanager.h | 2 +- src/framework/graphics/graphics.cpp | 8 +- src/framework/graphics/graphics.h | 6 +- src/framework/graphics/image.cpp | 8 +- src/framework/graphics/image.h | 2 +- src/framework/graphics/painter.h | 1 + src/framework/graphics/painterogl1.cpp | 12 + src/framework/graphics/painterogl1.h | 1 + src/framework/graphics/painterogl2.cpp | 13 + src/framework/graphics/painterogl2.h | 1 + .../graphics/paintershaderprogram.cpp | 6 +- src/framework/graphics/paintershaderprogram.h | 8 +- src/framework/graphics/particlemanager.cpp | 4 +- src/framework/graphics/particlemanager.h | 2 +- src/framework/graphics/shader.cpp | 2 +- src/framework/graphics/texture.h | 7 +- src/framework/graphics/texturemanager.cpp | 40 +- src/framework/graphics/texturemanager.h | 2 + src/framework/graphics/vertexarray.h | 12 + src/framework/luaengine/luainterface.cpp | 13 +- src/framework/luafunctions.cpp | 2 +- src/framework/net/protocol.cpp | 6 +- src/framework/otml/otmldocument.cpp | 4 +- src/framework/platform/platform.cpp | 26 ++ src/framework/platform/platform.h | 45 +++ src/framework/platform/unixplatform.cpp | 123 +++++++ src/framework/platform/win32platform.cpp | 347 ++++++++++++++++++ src/main.cpp | 4 +- 47 files changed, 807 insertions(+), 161 deletions(-) create mode 100644 src/framework/platform/platform.cpp create mode 100644 src/framework/platform/platform.h create mode 100644 src/framework/platform/unixplatform.cpp create mode 100644 src/framework/platform/win32platform.cpp diff --git a/src/client/creatures.cpp b/src/client/creatures.cpp index 26dc2cfc..314b5891 100644 --- a/src/client/creatures.cpp +++ b/src/client/creatures.cpp @@ -165,7 +165,7 @@ void CreatureManager::clearSpawns() void CreatureManager::loadMonsters(const std::string& file) { TiXmlDocument doc; - doc.Parse(g_resources.loadFile(file).c_str()); + doc.Parse(g_resources.readFileContents(file).c_str()); if(doc.Error()) stdext::throw_exception(stdext::format("cannot open monsters file '%s': '%s'", file, doc.ErrorDesc())); @@ -187,7 +187,7 @@ void CreatureManager::loadMonsters(const std::string& file) void CreatureManager::loadSingleCreature(const std::string& file) { - loadCreatureBuffer(g_resources.loadFile(file)); + loadCreatureBuffer(g_resources.readFileContents(file)); } void CreatureManager::loadNpcs(const std::string& folder) @@ -205,7 +205,7 @@ void CreatureManager::loadNpcs(const std::string& folder) if(boost::filesystem::is_directory(it->status())) continue; - loadCreatureBuffer(g_resources.loadFile(tmp + f)); + loadCreatureBuffer(g_resources.readFileContents(tmp + f)); } } @@ -222,7 +222,7 @@ void CreatureManager::loadSpawns(const std::string& fileName) } TiXmlDocument doc; - doc.Parse(g_resources.loadFile(fileName).c_str()); + doc.Parse(g_resources.readFileContents(fileName).c_str()); if(doc.Error()) stdext::throw_exception(stdext::format("cannot load spawns xml file '%s: '%s'", fileName, doc.ErrorDesc())); diff --git a/src/client/houses.cpp b/src/client/houses.cpp index f6d81d03..38c6be80 100644 --- a/src/client/houses.cpp +++ b/src/client/houses.cpp @@ -114,7 +114,7 @@ const HousePtr& HouseManager::getHouse(uint32 houseId) void HouseManager::load(const std::string& fileName) { TiXmlDocument doc; - doc.Parse(g_resources.loadFile(fileName).c_str()); + doc.Parse(g_resources.readFileContents(fileName).c_str()); if(doc.Error()) stdext::throw_exception(stdext::format("failed to load '%s': %s (House XML)", fileName, doc.ErrorDesc())); diff --git a/src/client/spritemanager.cpp b/src/client/spritemanager.cpp index 0b07dec8..55fb87f7 100644 --- a/src/client/spritemanager.cpp +++ b/src/client/spritemanager.cpp @@ -125,7 +125,7 @@ ImagePtr SpriteManager::getSpriteImage(int id) read += 4 + (3 * coloredPixels); } - // fill remaining pixels with alpha + // fill reamaning pixels with alpha while(writePos < SPRITE_DATA_SIZE) { pixels[writePos + 0] = 0x00; pixels[writePos + 1] = 0x00; diff --git a/src/client/thingtypemanager.cpp b/src/client/thingtypemanager.cpp index 6c86cacb..e5829cbc 100644 --- a/src/client/thingtypemanager.cpp +++ b/src/client/thingtypemanager.cpp @@ -139,7 +139,7 @@ void ThingTypeManager::loadXml(const std::string& file) stdext::throw_exception("OTB must be loaded before XML"); TiXmlDocument doc; - doc.Parse(g_resources.loadFile(file).c_str()); + doc.Parse(g_resources.readFileContents(file).c_str()); if(doc.Error()) stdext::throw_exception(stdext::format("failed to parse '%s': '%s'", file, doc.ErrorDesc())); diff --git a/src/framework/core/application.cpp b/src/framework/core/application.cpp index eb17ce96..2a1521ee 100644 --- a/src/framework/core/application.cpp +++ b/src/framework/core/application.cpp @@ -109,10 +109,10 @@ void Application::deinit() g_modules.unloadModules(); g_modules.clear(); - // release remaining lua object references + // release reamaning lua object references g_lua.collectGarbage(); - // poll remaining events + // poll reamaning events poll(); // disable dispatcher events diff --git a/src/framework/core/eventdispatcher.cpp b/src/framework/core/eventdispatcher.cpp index 10365003..b000b46b 100644 --- a/src/framework/core/eventdispatcher.cpp +++ b/src/framework/core/eventdispatcher.cpp @@ -45,7 +45,7 @@ void EventDispatcher::poll() int loops = 0; for(int count = 0, max = m_scheduledEventList.size(); count < max && !m_scheduledEventList.empty(); ++count) { ScheduledEventPtr scheduledEvent = m_scheduledEventList.top(); - if(scheduledEvent->remainingTicks() > 0) + if(scheduledEvent->reamaningTicks() > 0) break; m_scheduledEventList.pop(); scheduledEvent->execute(); diff --git a/src/framework/core/filestream.cpp b/src/framework/core/filestream.cpp index 71588ce0..0bc26b8e 100644 --- a/src/framework/core/filestream.cpp +++ b/src/framework/core/filestream.cpp @@ -35,6 +35,17 @@ FileStream::FileStream(const std::string& name, PHYSFS_File *fileHandle, bool wr { } +FileStream::FileStream(const std::string& name, const std::string& buffer) : + m_name(name), + m_fileHandle(nullptr), + m_pos(0), + m_writeable(false), + m_caching(true) +{ + m_data.resize(buffer.length()); + memcpy(&m_data[0], &buffer[0], buffer.length()); +} + FileStream::~FileStream() { #ifndef NDEBUG @@ -338,3 +349,4 @@ void FileStream::throwError(const std::string& message, bool physfsError) completeMessage += std::string(": ") + PHYSFS_getLastError(); stdext::throw_exception(completeMessage); } + diff --git a/src/framework/core/filestream.h b/src/framework/core/filestream.h index 3e51d905..123d4b9d 100644 --- a/src/framework/core/filestream.h +++ b/src/framework/core/filestream.h @@ -36,6 +36,7 @@ class FileStream : public LuaObject { public: FileStream(const std::string& name, PHYSFS_File *fileHandle, bool writeable); + FileStream(const std::string& name, const std::string& buffer); ~FileStream(); void cache(); diff --git a/src/framework/core/graphicalapplication.cpp b/src/framework/core/graphicalapplication.cpp index cf6c72f3..d4f217f2 100644 --- a/src/framework/core/graphicalapplication.cpp +++ b/src/framework/core/graphicalapplication.cpp @@ -76,7 +76,7 @@ void GraphicalApplication::terminate() // destroy particles g_particles.terminate(); - // destroy any remaining widget + // destroy any reamaning widget g_ui.terminate(); Application::terminate(); diff --git a/src/framework/core/module.cpp b/src/framework/core/module.cpp index 81bce815..e8391428 100644 --- a/src/framework/core/module.cpp +++ b/src/framework/core/module.cpp @@ -48,10 +48,10 @@ bool Module::load() for(const std::string& depName : m_dependencies) { ModulePtr dep = g_modules.getModule(depName); if(!dep) - stdext::throw_exception(stdext::format("dependency '%s' was not found", m_name, depName)); + stdext::throw_exception(stdext::format("dependency '%s' was not found", depName)); if(!dep->isLoaded() && !dep->load()) - stdext::throw_exception(stdext::format("dependency '%s' has failed to load", m_name, depName)); + stdext::throw_exception(stdext::format("dependency '%s' has failed to load", depName)); } if(m_sandboxed) @@ -199,8 +199,8 @@ void Module::discover(const OTMLNodePtr& moduleNode) } if(OTMLNodePtr node = moduleNode->get("@onLoad")) - m_onLoadFunc = std::make_tuple(node->value(), "@" + node->source() + "[" + node->tag() + "]"); + m_onLoadFunc = std::make_tuple(node->value(), "@" + node->source() + ":[" + node->tag() + "]"); if(OTMLNodePtr node = moduleNode->get("@onUnload")) - m_onUnloadFunc = std::make_tuple(node->value(), "@" + node->source() + "[" + node->tag() + "]"); + m_onUnloadFunc = std::make_tuple(node->value(), "@" + node->source() + ":[" + node->tag() + "]"); } diff --git a/src/framework/core/resourcemanager.cpp b/src/framework/core/resourcemanager.cpp index 9c8ab0e6..bbb15de0 100644 --- a/src/framework/core/resourcemanager.cpp +++ b/src/framework/core/resourcemanager.cpp @@ -42,14 +42,12 @@ void ResourceManager::terminate() PHYSFS_deinit(); } -void ResourceManager::discoverWorkDir(const std::string& appName, const std::string& existentFile) +bool ResourceManager::discoverWorkDir(const std::string& existentFile) { // search for modules directory std::string possiblePaths[] = { g_resources.getCurrentDir(), - g_resources.getBaseDir() + "../", - g_resources.getBaseDir() + "../share/" + appName + "/", - g_resources.getBaseDir() + appName + "/" }; - + g_resources.getBaseDir(), + g_resources.getBaseDir() + "../" }; bool found = false; for(const std::string& dir : possiblePaths) { if(!PHYSFS_addToSearchPath(dir.c_str(), 0)) @@ -64,8 +62,7 @@ void ResourceManager::discoverWorkDir(const std::string& appName, const std::str PHYSFS_removeFromSearchPath(dir.c_str()); } - if(!found) - g_logger.fatal(stdext::format("Unable to find %s, the application cannot be initialized.", existentFile)); + return found; } bool ResourceManager::setupUserWriteDir(const std::string& appWriteDirName) @@ -78,7 +75,7 @@ bool ResourceManager::setupUserWriteDir(const std::string& appWriteDirName) dirName = appWriteDirName; #endif std::string writeDir = userDir + dirName; - + if(!PHYSFS_setWriteDir(writeDir.c_str())) { if(!PHYSFS_setWriteDir(userDir.c_str()) || !PHYSFS_mkdir(dirName.c_str())) { g_logger.error(stdext::format("Unable to create write directory '%s': %s", writeDir, PHYSFS_getLastError())); @@ -165,35 +162,35 @@ bool ResourceManager::directoryExists(const std::string& directoryName) return (PHYSFS_isDirectory(resolvePath(directoryName).c_str())); } -void ResourceManager::loadFile(const std::string& fileName, std::iostream& out) +void ResourceManager::readFileStream(const std::string& fileName, std::iostream& out) { - out.clear(std::ios::goodbit); - std::string fullPath = resolvePath(fileName); - PHYSFS_file* file = PHYSFS_openRead(fullPath.c_str()); - if(!file) { - out.clear(std::ios::failbit); - stdext::throw_exception(stdext::format("unable to load file '%s': %s", fullPath.c_str(), PHYSFS_getLastError())); - } else { - int fileSize = PHYSFS_fileLength(file); - if(fileSize > 0) { - std::vector buffer(fileSize); - PHYSFS_read(file, (void*)&buffer[0], 1, fileSize); - out.write(&buffer[0], fileSize); - } else - out.clear(std::ios::eofbit); - PHYSFS_close(file); - out.seekg(0, std::ios::beg); + std::string buffer = readFileContents(fileName); + if(buffer.length() == 0) { + out.clear(std::ios::eofbit); + return; } + out.clear(std::ios::goodbit); + out.write(&buffer[0], buffer.length()); + out.seekg(0, std::ios::beg); } -std::string ResourceManager::loadFile(const std::string& fileName) +std::string ResourceManager::readFileContents(const std::string& fileName) { - std::stringstream fin; - loadFile(fileName, fin); - return fin.str(); + std::string fullPath = resolvePath(fileName); + + PHYSFS_File* file = PHYSFS_openRead(fullPath.c_str()); + if(!file) + stdext::throw_exception(stdext::format("unable to open file '%s': %s", fullPath, PHYSFS_getLastError())); + + int fileSize = PHYSFS_fileLength(file); + std::string buffer(fileSize, 0); + PHYSFS_read(file, (void*)&buffer[0], 1, fileSize); + PHYSFS_close(file); + + return buffer; } -bool ResourceManager::saveFile(const std::string& fileName, const uchar* data, uint size) +bool ResourceManager::writeFileBuffer(const std::string& fileName, const uchar* data, uint size) { PHYSFS_file* file = PHYSFS_openWrite(fileName.c_str()); if(!file) { @@ -206,7 +203,7 @@ bool ResourceManager::saveFile(const std::string& fileName, const uchar* data, u return true; } -bool ResourceManager::saveFile(const std::string& fileName, std::iostream& in) +bool ResourceManager::writeFileStream(const std::string& fileName, std::iostream& in) { std::streampos oldPos = in.tellg(); in.seekg(0, std::ios::end); @@ -214,19 +211,20 @@ bool ResourceManager::saveFile(const std::string& fileName, std::iostream& in) in.seekg(0, std::ios::beg); std::vector buffer(size); in.read(&buffer[0], size); - bool ret = saveFile(fileName, (const uchar*)&buffer[0], size); + bool ret = writeFileBuffer(fileName, (const uchar*)&buffer[0], size); in.seekg(oldPos, std::ios::beg); return ret; } -bool ResourceManager::saveFile(const std::string& fileName, const std::string& data) +bool ResourceManager::writeFileContents(const std::string& fileName, const std::string& data) { - return saveFile(fileName, (const uchar*)data.c_str(), data.size()); + return writeFileBuffer(fileName, (const uchar*)data.c_str(), data.size()); } FileStreamPtr ResourceManager::openFile(const std::string& fileName) { std::string fullPath = resolvePath(fileName); + PHYSFS_File* file = PHYSFS_openRead(fullPath.c_str()); if(!file) stdext::throw_exception(stdext::format("unable to open file '%s': %s", fullPath, PHYSFS_getLastError())); @@ -299,16 +297,12 @@ std::string ResourceManager::getRealDir(const std::string& path) std::string ResourceManager::getCurrentDir() { - char buffer[2048]; - PHYSFS_utf8FromLatin1((boost::filesystem::current_path().generic_string() + "/").c_str(), buffer, 2048); - return buffer; + return boost::filesystem::current_path().generic_string() + "/"; } std::string ResourceManager::getBaseDir() { - char buffer[2048]; - PHYSFS_utf8FromLatin1(PHYSFS_getBaseDir(), buffer, 2048); - return buffer; + return PHYSFS_getBaseDir(); } std::string ResourceManager::guessFileType(const std::string& filename, const std::string& type) @@ -316,4 +310,4 @@ std::string ResourceManager::guessFileType(const std::string& filename, const st if(g_resources.fileExists(filename)) return filename; return filename + "." + type; -} \ No newline at end of file +} diff --git a/src/framework/core/resourcemanager.h b/src/framework/core/resourcemanager.h index 54f91835..1938a1fa 100644 --- a/src/framework/core/resourcemanager.h +++ b/src/framework/core/resourcemanager.h @@ -34,7 +34,7 @@ public: // @dontbind void terminate(); - void discoverWorkDir(const std::string& appName, const std::string& existentFile); + bool discoverWorkDir(const std::string& existentFile); bool setupUserWriteDir(const std::string& appWriteDirName); bool setWriteDir(const std::string& writeDir, bool create = false); @@ -46,13 +46,13 @@ public: bool directoryExists(const std::string& directoryName); // @dontbind - void loadFile(const std::string& fileName, std::iostream& out); - std::string loadFile(const std::string& fileName); + void readFileStream(const std::string& fileName, std::iostream& out); + std::string readFileContents(const std::string& fileName); // @dontbind - bool saveFile(const std::string& fileName, const uchar* data, uint size); - bool saveFile(const std::string& fileName, const std::string& data); + bool writeFileBuffer(const std::string& fileName, const uchar* data, uint size); + bool writeFileContents(const std::string& fileName, const std::string& data); // @dontbind - bool saveFile(const std::string& fileName, std::iostream& in); + bool writeFileStream(const std::string& fileName, std::iostream& in); FileStreamPtr openFile(const std::string& fileName); FileStreamPtr appendFile(const std::string& fileName); diff --git a/src/framework/core/scheduledevent.h b/src/framework/core/scheduledevent.h index 6e7f0c61..83b9339a 100644 --- a/src/framework/core/scheduledevent.h +++ b/src/framework/core/scheduledevent.h @@ -35,7 +35,7 @@ public: bool nextCycle(); int ticks() { return m_ticks; } - int remainingTicks() { return m_ticks - g_clock.millis(); } + int reamaningTicks() { return m_ticks - g_clock.millis(); } int delay() { return m_delay; } int cyclesExecuted() { return m_cyclesExecuted; } int maxCycles() { return m_maxCycles; } diff --git a/src/framework/graphics/animatedtexture.cpp b/src/framework/graphics/animatedtexture.cpp index 74fc2535..0359dc32 100644 --- a/src/framework/graphics/animatedtexture.cpp +++ b/src/framework/graphics/animatedtexture.cpp @@ -24,53 +24,60 @@ #include "graphics.h" #include -/* -AnimatedTexture::AnimatedTexture(int width, int height, int channels, int numFrames, uchar *framesPixels, int *framesDelay) : - Texture(), - m_numFrames(numFrames) + +AnimatedTexture::AnimatedTexture(const Size& size, std::vector frames, std::vector framesDelay, bool buildMipmaps, bool compress) { - m_size.resize(width, height); + if(!setupSize(size, buildMipmaps)) + return; - m_framesTextureId.resize(numFrames); - m_framesDelay.resize(numFrames); - - for(int i=0;igetId(); + m_currentFrame = 0; + m_animTimer.restart(); } AnimatedTexture::~AnimatedTexture() { - glDeleteTextures(m_numFrames, &m_framesTextureId[0]); - m_id = 0; + } -void AnimatedTexture::enableBilinearFilter() +bool AnimatedTexture::buildHardwareMipmaps() { - for(int i=0;ibuildHardwareMipmaps(); + m_hasMipmaps = true; + return true; } -void AnimatedTexture::processAnimation() +void AnimatedTexture::setSmooth(bool smooth) { + for(const TexturePtr& frame : m_frames) + frame->setSmooth(smooth); + m_smooth = smooth; +} + +void AnimatedTexture::setRepeat(bool repeat) +{ + for(const TexturePtr& frame : m_frames) + frame->setRepeat(repeat); + m_repeat = repeat; +} + +void AnimatedTexture::updateAnimation() +{ + if(m_animTimer.ticksElapsed() < m_framesDelay[m_currentFrame]) + return; + + m_animTimer.restart(); m_currentFrame++; - if(m_currentFrame >= m_numFrames) + if(m_currentFrame >= m_frames.size()) m_currentFrame = 0; - m_id = m_framesTextureId[m_currentFrame]; - - AnimatedTexturePtr self = asAnimatedTexture(); - - // continue to animate only if something still referencing this texture - if(self->ref_count() > 1) - g_dispatcher.scheduleEvent(std::bind(&AnimatedTexture::processAnimation, self), m_framesDelay[m_currentFrame]); + m_id = m_frames[m_currentFrame]->getId(); } -*/ \ No newline at end of file diff --git a/src/framework/graphics/animatedtexture.h b/src/framework/graphics/animatedtexture.h index 8598969c..7fa72fe0 100644 --- a/src/framework/graphics/animatedtexture.h +++ b/src/framework/graphics/animatedtexture.h @@ -24,24 +24,28 @@ #define ANIMATEDTEXTURE_H #include "texture.h" -/* +#include + class AnimatedTexture : public Texture { public: - AnimatedTexture(int width, int height, int channels, int numFrames, uchar *framesPixels, int *framesDelay); + AnimatedTexture(const Size& size, std::vector frames, std::vector framesDelay, bool buildMipmaps = false, bool compress = false); virtual ~AnimatedTexture(); - void enableBilinearFilter(); - void processAnimation(); + virtual bool buildHardwareMipmaps(); - AnimatedTexturePtr asAnimatedTexture() { return static_self_cast(); } + virtual void setSmooth(bool smooth); + virtual void setRepeat(bool repeat); + + void updateAnimation(); + + virtual bool isAnimatedTexture() { return true; } private: - std::vector m_framesTextureId; + std::vector m_frames; std::vector m_framesDelay; - int m_numFrames; - int m_currentFrame; - ticks_t m_lastAnimCheckTicks; + uint m_currentFrame; + Timer m_animTimer; }; -*/ + #endif diff --git a/src/framework/graphics/bitmapfont.cpp b/src/framework/graphics/bitmapfont.cpp index 9e2d47a1..f47c60e7 100644 --- a/src/framework/graphics/bitmapfont.cpp +++ b/src/framework/graphics/bitmapfont.cpp @@ -52,9 +52,6 @@ void BitmapFont::load(const OTMLNodePtr& fontNode) m_glyphsSize[32].setWidth(spaceWidth); m_glyphsSize[160].setWidth(spaceWidth); - // use 127 as spacer [Width: 1] - m_glyphsSize[127].setWidth(1); - // new line actually has a size that will be useful in multiline algorithm m_glyphsSize[(uchar)'\n'] = Size(1, m_glyphHeight); @@ -262,6 +259,9 @@ Size BitmapFont::calculateTextRectSize(const std::string& text) void BitmapFont::calculateGlyphsWidthsAutomatically(const ImagePtr& image, const Size& glyphSize) { + if(!image) + return; + int numHorizontalGlyphs = image->getSize().width() / glyphSize.width(); auto texturePixels = image->getPixels(); @@ -338,4 +338,4 @@ std::string BitmapFont::wrapText(const std::string& text, int maxWidth) outText = outText.substr(0, outText.length()-1); return outText; -} \ No newline at end of file +} diff --git a/src/framework/graphics/cachedtext.h b/src/framework/graphics/cachedtext.h index a0228c52..39c347c9 100644 --- a/src/framework/graphics/cachedtext.h +++ b/src/framework/graphics/cachedtext.h @@ -39,8 +39,8 @@ public: void setAlign(Fw::AlignmentFlag align) { m_align = align; update(); } Size getTextSize() { return m_textSize; } - std::string getText() { return m_text; } - BitmapFontPtr getFont() { return m_font; } + std::string getText() const { return m_text; } + BitmapFontPtr getFont() const { return m_font; } Fw::AlignmentFlag getAlign() { return m_align; } private: diff --git a/src/framework/graphics/coordsbuffer.h b/src/framework/graphics/coordsbuffer.h index b7023dbe..5c16d0b9 100644 --- a/src/framework/graphics/coordsbuffer.h +++ b/src/framework/graphics/coordsbuffer.h @@ -59,6 +59,11 @@ public: m_textureCoordArray.addQuad(src); m_hardwareCached = false; } + void addUpsideDownQuad(const Rect& dest, const Rect& src) { + m_vertexArray.addUpsideDownQuad(dest); + m_textureCoordArray.addQuad(src); + m_hardwareCached = false; + } void addBoudingRect(const Rect& dest, int innerLineWidth); void addRepeatedRects(const Rect& dest, const Rect& src); diff --git a/src/framework/graphics/fontmanager.cpp b/src/framework/graphics/fontmanager.cpp index a6aeaaca..d72024f2 100644 --- a/src/framework/graphics/fontmanager.cpp +++ b/src/framework/graphics/fontmanager.cpp @@ -45,13 +45,12 @@ void FontManager::clearFonts() m_defaultFont = BitmapFontPtr(new BitmapFont("emptyfont")); } -bool FontManager::importFont(std::string fontFile) +bool FontManager::importFont(std::string file) { try { - if(!stdext::ends_with(fontFile, ".otfont")) - fontFile += ".otfont"; + file = g_resources.guessFileType(file, "otfont"); - OTMLDocumentPtr doc = OTMLDocument::parse(fontFile); + OTMLDocumentPtr doc = OTMLDocument::parse(file); OTMLNodePtr fontNode = doc->at("Font"); std::string name = fontNode->valueAt("name"); @@ -69,12 +68,12 @@ bool FontManager::importFont(std::string fontFile) m_fonts.push_back(font); // set as default if needed - if(!m_defaultFont) + if(!m_defaultFont || fontNode->valueAt("default", false)) m_defaultFont = font; return true; } catch(stdext::exception& e) { - g_logger.error(stdext::format("Unable to load font from file '%s': %s", fontFile, e.what())); + g_logger.error(stdext::format("Unable to load font from file '%s': %s", file, e.what())); return false; } } @@ -100,4 +99,3 @@ BitmapFontPtr FontManager::getFont(const std::string& fontName) g_logger.error(stdext::format("font '%s' not found", fontName)); return getDefaultFont(); } - diff --git a/src/framework/graphics/fontmanager.h b/src/framework/graphics/fontmanager.h index 37b94fd7..4cba5174 100644 --- a/src/framework/graphics/fontmanager.h +++ b/src/framework/graphics/fontmanager.h @@ -34,7 +34,7 @@ public: void terminate(); void clearFonts(); - bool importFont(std::string fontFile); + bool importFont(std::string file); bool fontExists(const std::string& fontName); BitmapFontPtr getFont(const std::string& fontName); diff --git a/src/framework/graphics/graphics.cpp b/src/framework/graphics/graphics.cpp index 3b9d4204..cc580c35 100644 --- a/src/framework/graphics/graphics.cpp +++ b/src/framework/graphics/graphics.cpp @@ -173,6 +173,8 @@ bool Graphics::selectPainterEngine(PainterEngine painterEngine) { Painter *painter = nullptr; Painter *fallbackPainter = nullptr; + PainterEngine fallbackPainterEngine = Painter_Any; + #ifdef PAINTER_OGL2 // always prefer OpenGL 2 over OpenGL 1 if(g_painterOGL2) { @@ -181,6 +183,7 @@ bool Graphics::selectPainterEngine(PainterEngine painterEngine) painter = g_painterOGL2; } fallbackPainter = g_painterOGL2; + fallbackPainterEngine = Painter_OpenGL2; } #endif @@ -192,11 +195,14 @@ bool Graphics::selectPainterEngine(PainterEngine painterEngine) painter = g_painterOGL1; } fallbackPainter = g_painterOGL1; + fallbackPainterEngine = Painter_OpenGL1; } #endif - if(!painter) + if(!painter) { painter = fallbackPainter; + m_selectedPainterEngine = fallbackPainterEngine; + } // switch painters GL state if(painter) { diff --git a/src/framework/graphics/graphics.h b/src/framework/graphics/graphics.h index fc30493c..1e4053f9 100644 --- a/src/framework/graphics/graphics.h +++ b/src/framework/graphics/graphics.h @@ -59,6 +59,8 @@ public: std::string getVersion() { return (const char*)glGetString(GL_VERSION); } std::string getExtensions() { return (const char*)glGetString(GL_EXTENSIONS); } + void setShouldUseShaders(bool enable) { m_shouldUseShaders = enable; } + bool ok() { return m_ok; } bool canUseDrawArrays(); bool canUseShaders(); @@ -71,6 +73,7 @@ public: bool canUseClampToEdge(); bool canUseBlendFuncSeparate(); bool canCacheBackbuffer(); + bool shouldUseShaders() { return m_shouldUseShaders; } bool hasScissorBug(); private: @@ -87,6 +90,7 @@ private: stdext::boolean m_useMipmaps; stdext::boolean m_useHardwareMipmaps; stdext::boolean m_useClampToEdge; + stdext::boolean m_shouldUseShaders; stdext::boolean m_cacheBackbuffer; PainterEngine m_prefferedPainterEngine; PainterEngine m_selectedPainterEngine; @@ -94,4 +98,4 @@ private: extern Graphics g_graphics; -#endif +#endif \ No newline at end of file diff --git a/src/framework/graphics/image.cpp b/src/framework/graphics/image.cpp index ebab8857..cd5fa89e 100644 --- a/src/framework/graphics/image.cpp +++ b/src/framework/graphics/image.cpp @@ -35,13 +35,11 @@ Image::Image(const Size& size, int bpp, uint8 *pixels) memcpy(&m_pixels[0], pixels, m_pixels.size()); } -ImagePtr Image::load(const std::string& file) +ImagePtr Image::load(std::string file) { ImagePtr image; try { - // currently only png images are supported - if(!stdext::ends_with(file, ".png")) - stdext::throw_exception("image file format no supported"); + file = g_resources.guessFileType(file, "png"); // load image file data image = loadPNG(file); @@ -54,7 +52,7 @@ ImagePtr Image::load(const std::string& file) ImagePtr Image::loadPNG(const std::string& file) { std::stringstream fin; - g_resources.loadFile(file, fin); + g_resources.readFileStream(file, fin); ImagePtr image; apng_data apng; if(load_apng(fin, &apng) == 0) { diff --git a/src/framework/graphics/image.h b/src/framework/graphics/image.h index a7235cd3..318957c8 100644 --- a/src/framework/graphics/image.h +++ b/src/framework/graphics/image.h @@ -31,7 +31,7 @@ class Image : public stdext::shared_object public: Image(const Size& size, int bpp = 4, uint8 *pixels = nullptr); - static ImagePtr load(const std::string& file); + static ImagePtr load(std::string file); static ImagePtr loadPNG(const std::string& file); void overwriteMask(const Color& maskedColor, const Color& insideColor = Color::white, const Color& outsideColor = Color::alpha); diff --git a/src/framework/graphics/painter.h b/src/framework/graphics/painter.h index 58b68b47..0f71fcac 100644 --- a/src/framework/graphics/painter.h +++ b/src/framework/graphics/painter.h @@ -75,6 +75,7 @@ public: virtual void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles) = 0; virtual void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture) = 0; virtual void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) = 0; + virtual void drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) = 0; void drawTexturedRect(const Rect& dest, const TexturePtr& texture) { drawTexturedRect(dest, texture, Rect(Point(0,0), texture->getSize())); } virtual void drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) = 0; virtual void drawFilledRect(const Rect& dest) = 0; diff --git a/src/framework/graphics/painterogl1.cpp b/src/framework/graphics/painterogl1.cpp index 72b62d98..dfcdb018 100644 --- a/src/framework/graphics/painterogl1.cpp +++ b/src/framework/graphics/painterogl1.cpp @@ -149,6 +149,18 @@ void PainterOGL1::drawTexturedRect(const Rect& dest, const TexturePtr& texture, drawCoords(m_coordsBuffer, TriangleStrip); } +void PainterOGL1::drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) +{ + if(dest.isEmpty() || src.isEmpty() || texture->isEmpty()) + return; + + setTexture(texture.get()); + + m_coordsBuffer.clear(); + m_coordsBuffer.addUpsideDownQuad(dest, src); + drawCoords(m_coordsBuffer, TriangleStrip); +} + void PainterOGL1::drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) { if(dest.isEmpty() || src.isEmpty() || texture->isEmpty()) diff --git a/src/framework/graphics/painterogl1.h b/src/framework/graphics/painterogl1.h index 247cd547..80c69d11 100644 --- a/src/framework/graphics/painterogl1.h +++ b/src/framework/graphics/painterogl1.h @@ -51,6 +51,7 @@ public: void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles); void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture); void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); + void drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); void drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); void drawFilledRect(const Rect& dest); void drawFilledTriangle(const Point& a, const Point& b, const Point& c); diff --git a/src/framework/graphics/painterogl2.cpp b/src/framework/graphics/painterogl2.cpp index f41d9ca4..34449720 100644 --- a/src/framework/graphics/painterogl2.cpp +++ b/src/framework/graphics/painterogl2.cpp @@ -141,6 +141,19 @@ void PainterOGL2::drawTexturedRect(const Rect& dest, const TexturePtr& texture, drawCoords(m_coordsBuffer, TriangleStrip); } +void PainterOGL2::drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) +{ + if(dest.isEmpty() || src.isEmpty() || texture->isEmpty()) + return; + + setDrawProgram(m_shaderProgram ? m_shaderProgram : m_drawTexturedProgram.get()); + setTexture(texture); + + m_coordsBuffer.clear(); + m_coordsBuffer.addUpsideDownQuad(dest, src); + drawCoords(m_coordsBuffer, TriangleStrip); +} + void PainterOGL2::drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) { if(dest.isEmpty() || src.isEmpty() || texture->isEmpty()) diff --git a/src/framework/graphics/painterogl2.h b/src/framework/graphics/painterogl2.h index 86d5ef0e..ac3d6b46 100644 --- a/src/framework/graphics/painterogl2.h +++ b/src/framework/graphics/painterogl2.h @@ -43,6 +43,7 @@ public: void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles); void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture); void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); + void drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); void drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); void drawFilledRect(const Rect& dest); void drawFilledTriangle(const Point& a, const Point& b, const Point& c); diff --git a/src/framework/graphics/paintershaderprogram.cpp b/src/framework/graphics/paintershaderprogram.cpp index 6d941776..0d1428b2 100644 --- a/src/framework/graphics/paintershaderprogram.cpp +++ b/src/framework/graphics/paintershaderprogram.cpp @@ -45,6 +45,8 @@ void PainterShaderProgram::setupUniforms() bindUniformLocation(TIME_UNIFORM, "u_Time"); bindUniformLocation(TEX0_UNIFORM, "u_Tex0"); bindUniformLocation(TEX1_UNIFORM, "u_Tex1"); + bindUniformLocation(TEX2_UNIFORM, "u_Tex2"); + bindUniformLocation(TEX3_UNIFORM, "u_Tex3"); bindUniformLocation(RESOLUTION_UNIFORM, "u_Resolution"); setUniformValue(PROJECTION_MATRIX_UNIFORM, m_projectionMatrix); @@ -54,6 +56,8 @@ void PainterShaderProgram::setupUniforms() setUniformValue(TIME_UNIFORM, m_time); setUniformValue(TEX0_UNIFORM, 0); setUniformValue(TEX1_UNIFORM, 1); + setUniformValue(TEX2_UNIFORM, 2); + setUniformValue(TEX3_UNIFORM, 3); setUniformValue(RESOLUTION_UNIFORM, (float)m_resolution.width(), (float)m_resolution.height()); } @@ -154,7 +158,7 @@ void PainterShaderProgram::bindMultiTextures() int i=1; for(const TexturePtr& tex : m_multiTextures) { - glActiveTexture(GL_TEXTURE0 + 1); + glActiveTexture(GL_TEXTURE0 + i++); glBindTexture(GL_TEXTURE_2D, tex->getId()); } diff --git a/src/framework/graphics/paintershaderprogram.h b/src/framework/graphics/paintershaderprogram.h index 0db1520d..3c5b84c6 100644 --- a/src/framework/graphics/paintershaderprogram.h +++ b/src/framework/graphics/paintershaderprogram.h @@ -20,8 +20,8 @@ * THE SOFTWARE. */ -#ifndef PAINTERSHADER_H -#define PAINTERSHADER_H +#ifndef PAINTERSHADERPROGRAM_H +#define PAINTERSHADERPROGRAM_H #include "shaderprogram.h" #include "coordsbuffer.h" @@ -40,7 +40,9 @@ protected: TIME_UNIFORM = 4, TEX0_UNIFORM = 5, TEX1_UNIFORM = 6, - RESOLUTION_UNIFORM = 7, + TEX2_UNIFORM = 7, + TEX3_UNIFORM = 8, + RESOLUTION_UNIFORM = 9, }; friend class PainterOGL2; diff --git a/src/framework/graphics/particlemanager.cpp b/src/framework/graphics/particlemanager.cpp index a099372c..9a248f8f 100644 --- a/src/framework/graphics/particlemanager.cpp +++ b/src/framework/graphics/particlemanager.cpp @@ -26,9 +26,11 @@ ParticleManager g_particles; -bool ParticleManager::importParticle(const std::string& file) +bool ParticleManager::importParticle(std::string file) { try { + file = g_resources.guessFileType(file, "otps"); + OTMLDocumentPtr doc = OTMLDocument::parse(file); for(const OTMLNodePtr& node : doc->children()) { if(node->tag() == "Effect") { diff --git a/src/framework/graphics/particlemanager.h b/src/framework/graphics/particlemanager.h index 2a88ff95..0d4ce0ce 100644 --- a/src/framework/graphics/particlemanager.h +++ b/src/framework/graphics/particlemanager.h @@ -29,7 +29,7 @@ class ParticleManager { public: - bool importParticle(const std::string& file); + bool importParticle(std::string file); ParticleEffectPtr createEffect(const std::string& name); void terminate(); diff --git a/src/framework/graphics/shader.cpp b/src/framework/graphics/shader.cpp index e663f5c5..5d2e5baf 100644 --- a/src/framework/graphics/shader.cpp +++ b/src/framework/graphics/shader.cpp @@ -80,7 +80,7 @@ bool Shader::compileSourceCode(const std::string& sourceCode) bool Shader::compileSourceFile(const std::string& sourceFile) { try { - std::string sourceCode = g_resources.loadFile(sourceFile); + std::string sourceCode = g_resources.readFileContents(sourceFile); return compileSourceCode(sourceCode); } catch(stdext::exception& e) { g_logger.error(stdext::format("unable to load shader source form file: %s", sourceFile)); diff --git a/src/framework/graphics/texture.h b/src/framework/graphics/texture.h index 1d1389bf..8225d5b8 100644 --- a/src/framework/graphics/texture.h +++ b/src/framework/graphics/texture.h @@ -35,10 +35,10 @@ public: void bind(); void copyFromScreen(const Rect& screenRect); - bool buildHardwareMipmaps(); + virtual bool buildHardwareMipmaps(); - void setSmooth(bool smooth); - void setRepeat(bool repeat); + virtual void setSmooth(bool smooth); + virtual void setRepeat(bool repeat); void setUpsideDown(bool upsideDown); uint getId() { return m_id; } @@ -50,6 +50,7 @@ public: bool isEmpty() { return m_id == 0; } bool hasRepeat() { return m_repeat; } bool hasMipmaps() { return m_hasMipmaps; } + virtual bool isAnimatedTexture() { return false; } protected: void createTexture(); diff --git a/src/framework/graphics/texturemanager.cpp b/src/framework/graphics/texturemanager.cpp index 4251d2a6..42f69841 100644 --- a/src/framework/graphics/texturemanager.cpp +++ b/src/framework/graphics/texturemanager.cpp @@ -26,6 +26,7 @@ #include "image.h" #include +#include #include TextureManager g_textures; @@ -38,11 +39,26 @@ void TextureManager::init() void TextureManager::terminate() { m_textures.clear(); + m_animatedTextures.clear(); m_emptyTexture = nullptr; } +void TextureManager::poll() +{ + // update only every 16msec, this allows upto 60 fps for animated textures + static ticks_t lastUpdate = 0; + ticks_t now = g_clock.millis(); + if(now - lastUpdate < 16) + return; + lastUpdate = now; + + for(const AnimatedTexturePtr& animatedTexture : m_animatedTextures) + animatedTexture->updateAnimation(); +} + void TextureManager::clearTexturesCache() { + m_animatedTextures.clear(); m_textures.clear(); } @@ -62,13 +78,11 @@ TexturePtr TextureManager::getTexture(const std::string& fileName) // texture not found, load it if(!texture) { try { - // currently only png textures are supported - if(!stdext::ends_with(filePath, ".png")) - stdext::throw_exception("texture file format not supported"); + std::string filePathEx = g_resources.guessFileType(filePath, "png"); // load texture file data std::stringstream fin; - g_resources.loadFile(filePath, fin); + g_resources.readFileStream(filePathEx, fin); texture = loadPNG(fin); } catch(stdext::exception& e) { g_logger.error(stdext::format("Unable to load texture '%s': %s", fileName, e.what())); @@ -88,12 +102,22 @@ TexturePtr TextureManager::loadPNG(std::stringstream& file) apng_data apng; if(load_apng(file, &apng) == 0) { + Size imageSize(apng.width, apng.height); if(apng.num_frames > 1) { // animated texture - //uchar *framesdata = apng.pdata + (apng.first_frame * apng.width * apng.height * apng.bpp); - //texture = TexturePtr(new AnimatedTexture(apng.width, apng.height, apng.bpp, apng.num_frames, framesdata, (int*)apng.frames_delay)); - g_logger.error("animated textures is disabled for a while"); + std::vector frames; + std::vector framesDelay; + for(uint i=0;i m_textures; + std::vector m_animatedTextures; TexturePtr m_emptyTexture; }; diff --git a/src/framework/graphics/vertexarray.h b/src/framework/graphics/vertexarray.h index 8e3b1e32..6411e6eb 100644 --- a/src/framework/graphics/vertexarray.h +++ b/src/framework/graphics/vertexarray.h @@ -61,6 +61,18 @@ public: addVertex(right, bottom); } + inline void addUpsideDownQuad(const Rect& rect) { + float top = rect.top(); + float right = rect.right()+1; + float bottom = rect.bottom()+1; + float left = rect.left(); + + addVertex(left, bottom); + addVertex(right, bottom); + addVertex(left, top); + addVertex(right, top); + } + void clear() { m_buffer.reset(); } float *vertices() const { return m_buffer.data(); } int vertexCount() const { return m_buffer.size() / 2; } diff --git a/src/framework/luaengine/luainterface.cpp b/src/framework/luaengine/luainterface.cpp index 6bb7a34b..598439bc 100644 --- a/src/framework/luaengine/luainterface.cpp +++ b/src/framework/luaengine/luainterface.cpp @@ -328,7 +328,9 @@ void LuaInterface::loadScript(const std::string& fileName) if(!stdext::starts_with(fileName, "/")) filePath = getCurrentSourcePath() + "/" + filePath; - std::string buffer = g_resources.loadFile(fileName); + filePath = g_resources.guessFileType(filePath, "lua"); + + std::string buffer = g_resources.readFileContents(filePath); std::string source = "@" + filePath; loadBuffer(buffer, source); } @@ -560,12 +562,10 @@ int LuaInterface::luaScriptLoader(lua_State* L) int LuaInterface::lua_dofile(lua_State* L) { - std::string fileName = g_lua.popString(); - if(!stdext::ends_with(fileName, ".lua")) - fileName += ".lua"; + std::string file = g_lua.popString(); try { - g_lua.loadScript(fileName); + g_lua.loadScript(file); g_lua.call(0, LUA_MULTRET); return g_lua.stackSize(); } catch(stdext::exception& e) { @@ -580,7 +580,7 @@ int LuaInterface::lua_dofiles(lua_State* L) std::string directory = g_lua.popString(); for(const std::string& fileName : g_resources.listDirectoryFiles(directory)) { - if(!stdext::ends_with(fileName, ".lua")) + if(!stdext::ends_with(fileName, ".lua") && !stdext::ends_with(fileName, ".bc")) continue; try { @@ -1251,4 +1251,3 @@ int LuaInterface::getTop() { return lua_gettop(L); } - diff --git a/src/framework/luafunctions.cpp b/src/framework/luafunctions.cpp index 220d44ed..53a70ce0 100644 --- a/src/framework/luafunctions.cpp +++ b/src/framework/luafunctions.cpp @@ -191,7 +191,7 @@ void Application::registerLuaFunctions() g_lua.registerClass(); g_lua.bindClassMemberFunction("nextCycle", &ScheduledEvent::nextCycle); g_lua.bindClassMemberFunction("ticks", &ScheduledEvent::ticks); - g_lua.bindClassMemberFunction("remainingTicks", &ScheduledEvent::remainingTicks); + g_lua.bindClassMemberFunction("reamaningTicks", &ScheduledEvent::reamaningTicks); g_lua.bindClassMemberFunction("delay", &ScheduledEvent::delay); g_lua.bindClassMemberFunction("cyclesExecuted", &ScheduledEvent::cyclesExecuted); g_lua.bindClassMemberFunction("maxCycles", &ScheduledEvent::maxCycles); diff --git a/src/framework/net/protocol.cpp b/src/framework/net/protocol.cpp index e90b3f0d..586347de 100644 --- a/src/framework/net/protocol.cpp +++ b/src/framework/net/protocol.cpp @@ -110,11 +110,11 @@ void Protocol::internalRecvHeader(uint8* buffer, uint16 size) { // read message size m_inputMessage->fillBuffer(buffer, size); - uint16 remainingSize = m_inputMessage->readSize(); + uint16 reamaningSize = m_inputMessage->readSize(); - // read remaining message data + // read reamaning message data if(m_connection) - m_connection->read(remainingSize, std::bind(&Protocol::internalRecvData, asProtocol(), std::placeholders::_1, std::placeholders::_2)); + m_connection->read(reamaningSize, std::bind(&Protocol::internalRecvData, asProtocol(), std::placeholders::_1, std::placeholders::_2)); } void Protocol::internalRecvData(uint8* buffer, uint16 size) diff --git a/src/framework/otml/otmldocument.cpp b/src/framework/otml/otmldocument.cpp index 29aa9eec..14c70345 100644 --- a/src/framework/otml/otmldocument.cpp +++ b/src/framework/otml/otmldocument.cpp @@ -37,7 +37,7 @@ OTMLDocumentPtr OTMLDocument::parse(const std::string& fileName) { std::stringstream fin; std::string source = g_resources.resolvePath(fileName); - g_resources.loadFile(source, fin); + g_resources.readFileStream(source, fin); return parse(fin, source); } @@ -58,6 +58,6 @@ std::string OTMLDocument::emit() bool OTMLDocument::save(const std::string& fileName) { m_source = fileName; - return g_resources.saveFile(fileName, emit()); + return g_resources.writeFileContents(fileName, emit()); } diff --git a/src/framework/platform/platform.cpp b/src/framework/platform/platform.cpp new file mode 100644 index 00000000..aa0a4923 --- /dev/null +++ b/src/framework/platform/platform.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2010-2013 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "platform.h" +#include + +Platform g_platform; diff --git a/src/framework/platform/platform.h b/src/framework/platform/platform.h new file mode 100644 index 00000000..b733f2e1 --- /dev/null +++ b/src/framework/platform/platform.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2010-2013 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PLATFORM_H +#define PLATFORM_H + +#include +#include + +class Platform +{ +public: + void processArgs(std::vector& args); + bool spawnProcess(const std::string& process, const std::vector& args); + int getProcessId(); + std::string getTempPath(); + void copyFile(std::string from, std::string to); + void openUrl(std::string url); + std::string getCPUName(); + double getTotalSystemMemory(); + std::string getOSName(); +}; + +extern Platform g_platform; + +#endif diff --git a/src/framework/platform/unixplatform.cpp b/src/framework/platform/unixplatform.cpp new file mode 100644 index 00000000..2486052f --- /dev/null +++ b/src/framework/platform/unixplatform.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2010-2013 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifdef __linux + +#include "platform.h" +#include +#include +#include +#include + +void Platform::processArgs(std::vector& args) +{ + //nothing todo, linux args are already utf8 encoded +} + +bool Platform::spawnProcess(const std::string& process, const std::vector& args) +{ + pid_t pid = fork(); + if(pid == -1) + return false; + + if(pid == 0) { + char* cargs[args.size()+2]; + cargs[0] = (char*)process.c_str(); + for(uint i=1;i<=args.size();++i) + cargs[i] = (char*)args[i-1].c_str(); + cargs[args.size()+1] = 0; + + execv(process.c_str(), cargs); + } + + return true; +} + +int Platform::getProcessId() +{ + return getpid(); +} + +std::string Platform::getTempPath() +{ + return "/tmp/"; +} + +void Platform::copyFile(std::string from, std::string to) +{ + system(stdext::format("/bin/cp '%s' '%s'", from, to).c_str()); +} + +void Platform::openUrl(std::string url) +{ + if(url.find("http://") == std::string::npos) + url.insert(0, "http://"); + system(stdext::format("xdg-open %s", url).c_str()); +} + +std::string Platform::getCPUName() +{ + std::string line; + std::ifstream in("/proc/cpuinfo"); + while(getline(in, line)) { + auto strs = stdext::split(line, ":"); + std::string first = strs[0]; + std::string second = strs[1]; + stdext::trim(first); + stdext::trim(second); + if(strs.size() == 2 && first == "model name") + return second; + } + return std::string(); +} + +double Platform::getTotalSystemMemory() +{ + std::string line; + std::ifstream in("/proc/meminfo"); + while(getline(in, line)) { + auto strs = stdext::split(line, ":"); + std::string first = strs[0]; + std::string second = strs[1]; + stdext::trim(first); + stdext::trim(second); + if(strs.size() == 2 && first == "MemTotal") + return stdext::unsafe_cast(second.substr(0, second.length() - 3)) * 1000.0; + } + return 0; +} + +std::string Platform::getOSName() +{ + std::string line; + std::ifstream in("/etc/issue"); + if(getline(in, line)) { + std::size_t end = line.find('\\'); + std::string res = line.substr(0, end); + stdext::trim(res); + return res; + } + return std::string(); +} + + +#endif diff --git a/src/framework/platform/win32platform.cpp b/src/framework/platform/win32platform.cpp new file mode 100644 index 00000000..14b9dc7a --- /dev/null +++ b/src/framework/platform/win32platform.cpp @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2010-2013 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifdef WIN32 + +#include "platform.h" +#include +#include +#include +#include + + +void Platform::processArgs(std::vector& args) +{ + int nargs; + wchar_t **wchar_argv = CommandLineToArgvW(GetCommandLineW(), &nargs); + if(!wchar_argv) + return; + + args.clear(); + if(wchar_argv) { + for(int i=0;i& args) +{ + std::string commandLine; + for(uint i = 0; i < args.size(); ++i) + commandLine += stdext::format(" \"%s\"", args[i]); + std::wstring wfile = stdext::utf8_to_utf16(process); + std::wstring wcommandLine = stdext::utf8_to_utf16(commandLine); + + if((int)ShellExecuteW(NULL, L"open", wfile.c_str(), wcommandLine.c_str(), NULL, SW_SHOWNORMAL) > 32) + return true; + return false; +} + +int Platform::getProcessId() +{ + return GetCurrentProcessId(); +} + +std::string Platform::getTempPath() +{ + wchar_t path[MAX_PATH]; + GetTempPathW(MAX_PATH, path); + return stdext::utf16_to_utf8(path); +} + +void Platform::copyFile(std::string from, std::string to) +{ + boost::replace_all(from, "/", "\\"); + boost::replace_all(to, "/", "\\"); + CopyFileW(stdext::utf8_to_utf16(from).c_str(), stdext::utf8_to_utf16(to).c_str(), false); +} + +void Platform::openUrl(std::string url) +{ + if(url.find("http://") == std::string::npos) + url.insert(0, "http://"); + ShellExecuteW(NULL, L"open", stdext::utf8_to_utf16(url).c_str(), NULL, NULL, SW_SHOWNORMAL); +} + +std::string Platform::getCPUName() +{ + char buf[1024]; + memset(buf, 0, sizeof(buf)); + DWORD bufSize = sizeof(buf); + HKEY hKey; + if(RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKey) != ERROR_SUCCESS) + return ""; + RegQueryValueExA(hKey, "ProcessorNameString", NULL, NULL, (LPBYTE)buf, (LPDWORD)&bufSize); + return buf; +} + +double Platform::getTotalSystemMemory() +{ + MEMORYSTATUSEX status; + status.dwLength = sizeof(status); + GlobalMemoryStatusEx(&status); + return status.ullTotalPhys; +} + +#define PRODUCT_PROFESSIONAL 0x00000030 +#define VER_SUITE_WH_SERVER 0x00008000 +#define VER_PLATFORM_WIN32s 0 +#define VER_PLATFORM_WIN32_WINDOWS 1 +#define VER_PLATFORM_WIN32_NT 2 +#define PRODUCT_UNDEFINED 0x00000000 +#define PRODUCT_ULTIMATE 0x00000001 +#define PRODUCT_HOME_BASIC 0x00000002 +#define PRODUCT_HOME_PREMIUM 0x00000003 +#define PRODUCT_ENTERPRISE 0x00000004 +#define PRODUCT_HOME_BASIC_N 0x00000005 +#define PRODUCT_BUSINESS 0x00000006 +#define PRODUCT_STANDARD_SERVER 0x00000007 +#define PRODUCT_DATACENTER_SERVER 0x00000008 +#define PRODUCT_SMALLBUSINESS_SERVER 0x00000009 +#define PRODUCT_ENTERPRISE_SERVER 0x0000000A +#define PRODUCT_STARTER 0x0000000B +#define PRODUCT_DATACENTER_SERVER_CORE 0x0000000C +#define PRODUCT_STANDARD_SERVER_CORE 0x0000000D +#define PRODUCT_ENTERPRISE_SERVER_CORE 0x0000000E +#define PRODUCT_ENTERPRISE_SERVER_IA64 0x0000000F +#define PRODUCT_BUSINESS_N 0x00000010 +#define PRODUCT_WEB_SERVER 0x00000011 +#define PRODUCT_CLUSTER_SERVER 0x00000012 +#define PRODUCT_HOME_SERVER 0x00000013 +#define PRODUCT_STORAGE_EXPRESS_SERVER 0x00000014 +#define PRODUCT_STORAGE_STANDARD_SERVER 0x00000015 +#define PRODUCT_STORAGE_WORKGROUP_SERVER 0x00000016 +#define PRODUCT_STORAGE_ENTERPRISE_SERVER 0x00000017 +#define PRODUCT_SERVER_FOR_SMALLBUSINESS 0x00000018 +#define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM 0x00000019 +#define PRODUCT_HOME_PREMIUM_N 0x0000001A +#define PRODUCT_ENTERPRISE_N 0x0000001B +#define PRODUCT_ULTIMATE_N 0x0000001C +#define PRODUCT_WEB_SERVER_CORE 0x0000001D +#define PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT 0x0000001E +#define PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY 0x0000001F +#define PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING 0x00000020 +#define PRODUCT_SERVER_FOUNDATION 0x00000021 +#define PRODUCT_HOME_PREMIUM_SERVER 0x00000022 +#define PRODUCT_SERVER_FOR_SMALLBUSINESS_V 0x00000023 +#define PRODUCT_STANDARD_SERVER_V 0x00000024 +#define PRODUCT_DATACENTER_SERVER_V 0x00000025 +#define PRODUCT_ENTERPRISE_SERVER_V 0x00000026 +#define PRODUCT_DATACENTER_SERVER_CORE_V 0x00000027 +#define PRODUCT_STANDARD_SERVER_CORE_V 0x00000028 +#define PRODUCT_ENTERPRISE_SERVER_CORE_V 0x00000029 +#define PRODUCT_HYPERV 0x0000002A +#define PRODUCT_STORAGE_EXPRESS_SERVER_CORE 0x0000002B +#define PRODUCT_STORAGE_STANDARD_SERVER_CORE 0x0000002C +#define PRODUCT_STORAGE_WORKGROUP_SERVER_CORE 0x0000002D +#define PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE 0x0000002E +#define PRODUCT_STARTER_N 0x0000002F +#define PRODUCT_PROFESSIONAL 0x00000030 +#define PRODUCT_PROFESSIONAL_N 0x00000031 +#define PRODUCT_SB_SOLUTION_SERVER 0x00000032 + +std::string Platform::getOSName() +{ + typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); + typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD); + + std::string ret; + OSVERSIONINFOEX osvi; + SYSTEM_INFO si; + PGNSI pGNSI; + PGPI pGPI; + BOOL bOsVersionInfoEx; + DWORD dwType; + + ZeroMemory(&si, sizeof(SYSTEM_INFO)); + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*) &osvi); + + if(!bOsVersionInfoEx) + return std::string(); + + pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); + if(NULL != pGNSI) + pGNSI(&si); + else + GetSystemInfo(&si); + + if(VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && osvi.dwMajorVersion > 4) { + if(osvi.dwMajorVersion == 6) { + if(osvi.dwMinorVersion == 0) { + if(osvi.wProductType == VER_NT_WORKSTATION) + ret += "Windows Vista "; + else ret += "Windows Server 2008 "; + } + + if(osvi.dwMinorVersion == 1 || osvi.dwMinorVersion == 2) + { + if(osvi.wProductType == VER_NT_WORKSTATION && osvi.dwMinorVersion == 1) + ret += "Windows 7 "; + else + if(osvi.wProductType == VER_NT_WORKSTATION && osvi.dwMinorVersion == 2) + ret += "Windows 8 "; + else + ret += "Windows Server 2008 R2 "; + } + + pGPI = (PGPI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo"); + + pGPI( osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType); + + switch(dwType) + { + case PRODUCT_ULTIMATE: + ret += "Ultimate Edition"; + break; + case PRODUCT_PROFESSIONAL: + ret += "Professional"; + break; + case PRODUCT_HOME_PREMIUM: + ret += "Home Premium Edition"; + break; + case PRODUCT_HOME_BASIC: + ret += "Home Basic Edition"; + break; + case PRODUCT_ENTERPRISE: + ret += "Enterprise Edition"; + break; + case PRODUCT_BUSINESS: + ret += "Business Edition"; + break; + case PRODUCT_STARTER: + ret += "Starter Edition"; + break; + case PRODUCT_CLUSTER_SERVER: + ret += "Cluster Server Edition"; + break; + case PRODUCT_DATACENTER_SERVER: + ret += "Datacenter Edition"; + break; + case PRODUCT_DATACENTER_SERVER_CORE: + ret += "Datacenter Edition (core installation)"; + break; + case PRODUCT_ENTERPRISE_SERVER: + ret += "Enterprise Edition"; + break; + case PRODUCT_ENTERPRISE_SERVER_CORE: + ret += "Enterprise Edition (core installation)"; + break; + case PRODUCT_ENTERPRISE_SERVER_IA64: + ret += "Enterprise Edition for Itanium-based Systems"; + break; + case PRODUCT_SMALLBUSINESS_SERVER: + ret += "Small Business Server"; + break; + case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM: + ret += "Small Business Server Premium Edition"; + break; + case PRODUCT_STANDARD_SERVER: + ret += "Standard Edition"; + break; + case PRODUCT_STANDARD_SERVER_CORE: + ret += "Standard Edition (core installation)"; + break; + case PRODUCT_WEB_SERVER: + ret += "Web Server Edition"; + break; + } + } + + if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) { + if(GetSystemMetrics(SM_SERVERR2)) + ret += "Windows Server 2003 R2, "; + else if(osvi.wSuiteMask & VER_SUITE_STORAGE_SERVER) + ret += "Windows Storage Server 2003"; + else if(osvi.wSuiteMask & VER_SUITE_WH_SERVER) + ret += "Windows Home Server"; + else if(osvi.wProductType == VER_NT_WORKSTATION && si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) + ret += "Windows XP Professional x64 Edition"; + else + ret += "Windows Server 2003, "; + + if(osvi.wProductType != VER_NT_WORKSTATION) { + if(si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64) { + if(osvi.wSuiteMask & VER_SUITE_DATACENTER) + ret += "Datacenter Edition for Itanium-based Systems"; + else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + ret += "Enterprise Edition for Itanium-based Systems"; + } + + else if(si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) { + if(osvi.wSuiteMask & VER_SUITE_DATACENTER) + ret += "Datacenter x64 Edition"; + else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + ret += "Enterprise x64 Edition"; + else + ret += "Standard x64 Edition"; + } else { + if(osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER) + ret += "Compute Cluster Edition"; + else if(osvi.wSuiteMask & VER_SUITE_DATACENTER) + ret += "Datacenter Edition"; + else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + ret += "Enterprise Edition"; + else if(osvi.wSuiteMask & VER_SUITE_BLADE) + ret += "Web Edition"; + else ret += "Standard Edition"; + } + } + } + + if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) { + ret += "Windows XP "; + if(osvi.wSuiteMask & VER_SUITE_PERSONAL) + ret += "Home Edition"; + else ret += "Professional"; + } + + if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 ) { + ret += "Windows 2000 "; + if(osvi.wProductType == VER_NT_WORKSTATION) { + ret += "Professional"; + } else { + if(osvi.wSuiteMask & VER_SUITE_DATACENTER) + ret += "Datacenter Server"; + else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + ret += "Advanced Server"; + else ret += "Server"; + } + } + + ret += stdext::format(" (build %d)", osvi.dwBuildNumber); + + if(osvi.dwMajorVersion >= 6 ) { + if(si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 ) + ret += ", 64-bit"; + else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL ) + ret += ", 32-bit"; + } + } else { + ret = "Windows"; + } + return ret; +} + +#endif diff --git a/src/main.cpp b/src/main.cpp index f9b56dde..091aa6a7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,7 +39,9 @@ int main(int argc, const char* argv[]) g_client.init(args); // find script init.lua and run it - g_resources.discoverWorkDir(g_app.getCompactName(), "init.lua"); + if(!g_resources.discoverWorkDir("init.lua")) + g_logger.fatal("Unable to find work directory, the application cannot be initialized."); + if(!g_lua.safeRunScript("init.lua")) g_logger.fatal("Unable to run script init.lua!");