Restore support for animated png files

* Rework resource manager
* Add missing files
* Improve some graphics classes
This commit is contained in:
Eduardo Bart 2013-01-08 19:31:41 -02:00
parent fdcad184f9
commit 0120b7554c
47 changed files with 807 additions and 161 deletions

View File

@ -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()));

View File

@ -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()));

View File

@ -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;

View File

@ -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()));

View File

@ -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

View File

@ -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();

View File

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

View File

@ -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();

View File

@ -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();

View File

@ -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() + "]");
}

View File

@ -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)
@ -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<char> buffer(fileSize);
PHYSFS_read(file, (void*)&buffer[0], 1, fileSize);
out.write(&buffer[0], fileSize);
} else
std::string buffer = readFileContents(fileName);
if(buffer.length() == 0) {
out.clear(std::ios::eofbit);
PHYSFS_close(file);
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<char> 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>() + "/";
}
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)

View File

@ -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);

View File

@ -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; }

View File

@ -24,53 +24,60 @@
#include "graphics.h"
#include <framework/core/eventdispatcher.h>
/*
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<ImagePtr> frames, std::vector<int> 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;i<numFrames;++i) {
uchar *framePixels = framesPixels + (i*height*width* channels);
uint id = internalLoadGLTexture(framePixels, channels, width, height);
m_framesTextureId[i] = id;
m_framesDelay[i] = framesDelay[i];
for(uint i=0;i<frames.size();++i) {
m_frames.push_back(new Texture(frames[i], buildMipmaps, compress));
}
m_currentFrame = -1;
g_dispatcher.scheduleEvent(std::bind(&AnimatedTexture::processAnimation, this), 0);
m_framesDelay = framesDelay;
m_hasMipmaps = buildMipmaps;
m_id = m_frames[0]->getId();
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;i<m_numFrames;++i) {
glBindTexture(GL_TEXTURE_2D, m_framesTextureId[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
if(!g_graphics.canUseHardwareMipmaps())
return false;
for(const TexturePtr& frame : m_frames)
frame->buildHardwareMipmaps();
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();
}
*/

View File

@ -24,24 +24,28 @@
#define ANIMATEDTEXTURE_H
#include "texture.h"
/*
#include <framework/core/timer.h>
class AnimatedTexture : public Texture
{
public:
AnimatedTexture(int width, int height, int channels, int numFrames, uchar *framesPixels, int *framesDelay);
AnimatedTexture(const Size& size, std::vector<ImagePtr> frames, std::vector<int> framesDelay, bool buildMipmaps = false, bool compress = false);
virtual ~AnimatedTexture();
void enableBilinearFilter();
void processAnimation();
virtual bool buildHardwareMipmaps();
AnimatedTexturePtr asAnimatedTexture() { return static_self_cast<AnimatedTexture>(); }
virtual void setSmooth(bool smooth);
virtual void setRepeat(bool repeat);
void updateAnimation();
virtual bool isAnimatedTexture() { return true; }
private:
std::vector<uint> m_framesTextureId;
std::vector<TexturePtr> m_frames;
std::vector<int> m_framesDelay;
int m_numFrames;
int m_currentFrame;
ticks_t m_lastAnimCheckTicks;
uint m_currentFrame;
Timer m_animTimer;
};
*/
#endif

View File

@ -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();

View File

@ -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:

View File

@ -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);

View File

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

View File

@ -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);

View File

@ -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) {

View File

@ -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<true> m_useMipmaps;
stdext::boolean<true> m_useHardwareMipmaps;
stdext::boolean<true> m_useClampToEdge;
stdext::boolean<true> m_shouldUseShaders;
stdext::boolean<true> m_cacheBackbuffer;
PainterEngine m_prefferedPainterEngine;
PainterEngine m_selectedPainterEngine;

View File

@ -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) {

View File

@ -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);

View File

@ -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;

View File

@ -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())

View File

@ -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);

View File

@ -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())

View File

@ -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);

View File

@ -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());
}

View File

@ -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;

View File

@ -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") {

View File

@ -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();

View File

@ -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));

View File

@ -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();

View File

@ -26,6 +26,7 @@
#include "image.h"
#include <framework/core/resourcemanager.h>
#include <framework/core/clock.h>
#include <framework/graphics/apngloader.h>
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<ImagePtr> frames;
std::vector<int> framesDelay;
for(uint i=0;i<apng.num_frames;++i) {
uchar *frameData = apng.pdata + ((apng.first_frame+i) * imageSize.area() * apng.bpp);
int frameDelay = apng.frames_delay[i];
framesDelay.push_back(frameDelay);
frames.push_back(ImagePtr(new Image(imageSize, apng.bpp, frameData)));
}
AnimatedTexturePtr animatedTexture = new AnimatedTexture(imageSize, frames, framesDelay);
m_animatedTextures.push_back(animatedTexture);
texture = animatedTexture;
} else {
ImagePtr image = ImagePtr(new Image(Size(apng.width, apng.height), apng.bpp, apng.pdata));
ImagePtr image = ImagePtr(new Image(imageSize, apng.bpp, apng.pdata));
texture = TexturePtr(new Texture(image));
}
free_apng(&apng);

View File

@ -30,6 +30,7 @@ class TextureManager
public:
void init();
void terminate();
void poll();
void clearTexturesCache();
TexturePtr getTexture(const std::string& fileName);
@ -39,6 +40,7 @@ private:
TexturePtr loadPNG(std::stringstream& file);
std::unordered_map<std::string, TexturePtr> m_textures;
std::vector<AnimatedTexturePtr> m_animatedTextures;
TexturePtr m_emptyTexture;
};

View File

@ -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; }

View File

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

View File

@ -191,7 +191,7 @@ void Application::registerLuaFunctions()
g_lua.registerClass<ScheduledEvent, Event>();
g_lua.bindClassMemberFunction<ScheduledEvent>("nextCycle", &ScheduledEvent::nextCycle);
g_lua.bindClassMemberFunction<ScheduledEvent>("ticks", &ScheduledEvent::ticks);
g_lua.bindClassMemberFunction<ScheduledEvent>("remainingTicks", &ScheduledEvent::remainingTicks);
g_lua.bindClassMemberFunction<ScheduledEvent>("reamaningTicks", &ScheduledEvent::reamaningTicks);
g_lua.bindClassMemberFunction<ScheduledEvent>("delay", &ScheduledEvent::delay);
g_lua.bindClassMemberFunction<ScheduledEvent>("cyclesExecuted", &ScheduledEvent::cyclesExecuted);
g_lua.bindClassMemberFunction<ScheduledEvent>("maxCycles", &ScheduledEvent::maxCycles);

View File

@ -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)

View File

@ -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());
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/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 <boost/filesystem.hpp>
Platform g_platform;

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/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 <string>
#include <vector>
class Platform
{
public:
void processArgs(std::vector<std::string>& args);
bool spawnProcess(const std::string& process, const std::vector<std::string>& 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

View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/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 <fstream>
#include <unistd.h>
#include <string.h>
#include <framework/stdext/stdext.h>
void Platform::processArgs(std::vector<std::string>& args)
{
//nothing todo, linux args are already utf8 encoded
}
bool Platform::spawnProcess(const std::string& process, const std::vector<std::string>& 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<double>(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

View File

@ -0,0 +1,347 @@
/*
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/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 <windows.h>
#include <framework/stdext/stdext.h>
#include <boost/algorithm/string.hpp>
#include <tchar.h>
void Platform::processArgs(std::vector<std::string>& args)
{
int nargs;
wchar_t **wchar_argv = CommandLineToArgvW(GetCommandLineW(), &nargs);
if(!wchar_argv)
return;
args.clear();
if(wchar_argv) {
for(int i=0;i<nargs;++i)
args.push_back(stdext::utf16_to_utf8(wchar_argv[i]));
}
}
bool Platform::spawnProcess(const std::string& process, const std::vector<std::string>& 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

View File

@ -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!");