rework on resources system

This commit is contained in:
Eduardo Bart 2011-05-19 14:11:05 -03:00
parent e1af35f061
commit ab6c52a3ee
24 changed files with 322 additions and 226 deletions

View File

@ -7,7 +7,7 @@ panel#background:
panel#icos4d: panel#icos4d:
skin: skin:
image: lightness/mouse.png image: /skins/lightness/mouse.png
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top
margin.left: -2 margin.left: -2
@ -15,7 +15,7 @@ panel#background:
panel#mouse: panel#mouse:
skin: skin:
image: lightness/icos4d.png image: /skins/lightness/icos4d.png
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
margin.left: 60 margin.left: 60
@ -34,7 +34,7 @@ panel#background:
anchors.top: parent.top anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
margin.top: 16 margin.top: 16
onClick: UI.load("mainmenu/entergamewindow.yml") onClick: UI.load("entergamewindow.yml")
button#accessAccountButton: button#accessAccountButton:
text: Access Account text: Access Account
@ -48,14 +48,14 @@ panel#background:
anchors.top: parent.top anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
margin.top: 76 margin.top: 76
onClick: UI.load("mainmenu/optionswindow.yml") onClick: UI.load("optionswindow.yml")
button#infoButton: button#infoButton:
text: Info text: Info
anchors.top: parent.top anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
margin.top: 106 margin.top: 106
onClick: UI.load("mainmenu/infowindow.yml") onClick: UI.load("infowindow.yml")
button#exitGameButton: button#exitGameButton:
text: Exit text: Exit

View File

@ -1,6 +1,6 @@
-- menu state -- menu state
function onEnterMenuState() function onEnterMenuState()
mainMenu = UI.load("mainmenu/mainmenu.yml") mainMenu = UI.load("mainmenu.yml")
end end
function onLeaveMenuState() function onLeaveMenuState()

View File

@ -3,9 +3,9 @@ function autoDestroyParent()
end end
function messageBox(title, text) function messageBox(title, text)
local msgBox = UI.load("modules/messagebox/messagebox.yml") local msgBox = UI.load("messagebox.yml")
msgBox.locked = true msgBox.locked = true
msgBox.title = title msgBox.title = title
msgBox:child("textLabel").text = text msgBox:child("textLabel").text = text
msgBox:child("okButton").onClick = autoDestroyParent msgBox:child("okButton").onClick = autoDestroyParentz
end end

View File

@ -35,12 +35,10 @@ bool Configs::load(const std::string& fileName)
if(!g_resources.fileExists(fileName)) if(!g_resources.fileExists(fileName))
return false; return false;
std::string fileContents = g_resources.loadTextFile(fileName); std::stringstream fin;
if(!fileContents.size()) if(!g_resources.loadFile(fileName, fin))
return false; return false;
std::istringstream fin(fileContents);
try { try {
YAML::Parser parser(fin); YAML::Parser parser(fin);

View File

@ -24,6 +24,7 @@
#include <prerequisites.h> #include <prerequisites.h>
#include <core/resources.h> #include <core/resources.h>
#include <core/platform.h>
#include <physfs.h> #include <physfs.h>
@ -32,6 +33,29 @@ Resources g_resources;
void Resources::init(const char *argv0) void Resources::init(const char *argv0)
{ {
PHYSFS_init(argv0); PHYSFS_init(argv0);
// try to find data directory
std::list<std::string> searchPaths;
std::string dir;
std::string baseDir = PHYSFS_getBaseDir();
std::list<std::string> possibleDirs;
possibleDirs.push_back("data");
possibleDirs.push_back(baseDir + "data");
possibleDirs.push_back(baseDir + "../data");
possibleDirs.push_back(baseDir + "../share/data");
possibleDirs.push_back("");
foreach(dir, possibleDirs)
if(g_resources.addToSearchPath(dir))
break;
// setup write directory
dir = Platform::getAppUserDir();
if(g_resources.setWriteDir(dir))
g_resources.addToSearchPath(dir);
else
logError("ERROR: could not setup write directory");
} }
void Resources::terminate() void Resources::terminate()
@ -41,59 +65,63 @@ void Resources::terminate()
bool Resources::setWriteDir(const std::string& path) bool Resources::setWriteDir(const std::string& path)
{ {
bool ret = (bool)PHYSFS_setWriteDir(path.c_str()); if(!PHYSFS_setWriteDir(path.c_str()))
return false;
if(!ret) return true;
flogError("ERROR: Could not set the path \"%s\" as write directory, file write will not work correctly.", path.c_str());
return ret;
} }
bool Resources::addToSearchPath(const std::string& path, bool insertInFront /*= true*/) bool Resources::addToSearchPath(const std::string& path, bool insertInFront /*= true*/)
{ {
if(!PHYSFS_addToSearchPath(path.c_str(), insertInFront ? 0 : 1)) { if(!PHYSFS_addToSearchPath(path.c_str(), insertInFront ? 0 : 1))
flogError("ERROR: Error while adding \"%s\" to resources search path: %s", path.c_str() % PHYSFS_getLastError());
return false; return false;
}
return true; return true;
} }
bool Resources::fileExists(const std::string& filePath) void Resources::addPackagesToSearchPath(const std::string &packagesDirectory, const std::string &packageExtension, bool append)
{ {
return PHYSFS_exists(filePath.c_str()); auto files = listDirectoryFiles(resolvePath(packagesDirectory));
foreach(const std::string& file, files) {
if(boost::ends_with(file, packageExtension))
addToSearchPath(packagesDirectory + "/" + file, !append);
}
} }
uchar *Resources::loadFile(const std::string& fileName, uint *fileSize) bool Resources::fileExists(const std::string& fileName)
{ {
PHYSFS_file *file = PHYSFS_openRead(fileName.c_str()); return (PHYSFS_exists(resolvePath(fileName).c_str()) && !PHYSFS_isDirectory(resolvePath(fileName).c_str()));
}
bool Resources::directoryExists(const std::string& directoryName)
{
return (PHYSFS_exists(resolvePath(directoryName).c_str()) && PHYSFS_isDirectory(resolvePath(directoryName).c_str()));
}
bool Resources::loadFile(const std::string& fileName, std::iostream& out)
{
out.clear(std::ios::goodbit);
PHYSFS_file *file = PHYSFS_openRead(resolvePath(fileName).c_str());
if(!file) { if(!file) {
flogError("ERROR: Failed to load file \"%s\": %s", fileName.c_str() % PHYSFS_getLastError()); flogError("ERROR: Failed to load file \"%s\": %s", fileName.c_str() % PHYSFS_getLastError());
*fileSize = 0; out.clear(std::ios::failbit);
return NULL; return false;
} } else {
int fileSize = PHYSFS_fileLength(file);
*fileSize = PHYSFS_fileLength(file); if(fileSize > 0) {
uchar *buffer = new uchar[*fileSize + 1]; char *buffer = new char[fileSize];
PHYSFS_read(file, (void*)buffer, 1, *fileSize); PHYSFS_read(file, (void*)buffer, 1, fileSize);
buffer[*fileSize] = 0; out.write(buffer, fileSize);
delete buffer;
} else
out.clear(std::ios::eofbit);
PHYSFS_close(file); PHYSFS_close(file);
return buffer; out.seekg(0, std::ios::beg);
return true;
} }
std::string Resources::loadTextFile(const std::string& fileName)
{
std::string text;
uint fileSize;
char *buffer = (char *)loadFile(fileName, &fileSize);
if(buffer) {
text.assign(buffer);
delete[] buffer;
}
return text;
} }
bool Resources::saveFile(const std::string &fileName, const uchar *data, uint size) bool Resources::saveFile(const std::string &fileName, const uchar *data, uint size)
{ {
PHYSFS_file *file = PHYSFS_openWrite(fileName.c_str()); PHYSFS_file *file = PHYSFS_openWrite(resolvePath(fileName).c_str());
if(!file) { if(!file) {
flogError("ERROR: Failed to save file \"%s\": %s", fileName.c_str() % PHYSFS_getLastError()); flogError("ERROR: Failed to save file \"%s\": %s", fileName.c_str() % PHYSFS_getLastError());
return false; return false;
@ -104,15 +132,29 @@ bool Resources::saveFile(const std::string &fileName, const uchar *data, uint si
return true; return true;
} }
bool Resources::saveTextFile(const std::string &fileName, std::string text) bool Resources::saveFile(const std::string &fileName, std::istream& in)
{ {
return saveFile(fileName, (const uchar*)text.c_str(), text.size()); std::streampos oldPos = in.tellg();
in.seekg(0, std::ios::end);
std::streampos size = in.tellg();
in.seekg(0, std::ios::beg);
char *buffer = new char[size];
in.read(buffer, size);
bool ret = saveFile(fileName, (const uchar*)buffer, size);
delete[] buffer;
in.seekg(oldPos, std::ios::beg);
return ret;
} }
std::list<std::string> Resources::getDirectoryFiles(const std::string& directory) bool Resources::deleteFile(const std::string& fileName)
{
return PHYSFS_delete(resolvePath(fileName).c_str()) != 0;
}
std::list<std::string> Resources::listDirectoryFiles(const std::string& directoryPath)
{ {
std::list<std::string> files; std::list<std::string> files;
char **rc = PHYSFS_enumerateFiles(directory.c_str()); char **rc = PHYSFS_enumerateFiles(resolvePath(directoryPath).c_str());
for(char **i = rc; *i != NULL; i++) for(char **i = rc; *i != NULL; i++)
files.push_back(*i); files.push_back(*i);
@ -120,3 +162,31 @@ std::list<std::string> Resources::getDirectoryFiles(const std::string& directory
PHYSFS_freeList(rc); PHYSFS_freeList(rc);
return files; return files;
} }
void Resources::pushCurrentPath(const std::string &currentPath)
{
m_currentPaths.push(currentPath);
}
void Resources::popCurrentPath()
{
m_currentPaths.pop();
}
std::string Resources::resolvePath(const std::string& path)
{
std::string fullPath;
if(boost::starts_with(path, "/"))
fullPath = path.substr(1);
else {
if(m_currentPaths.size() > 0) {
std::string currentPath = m_currentPaths.top();
if(currentPath.length() > 0)
fullPath += currentPath + "/";
}
fullPath += path;
}
return fullPath;
}

View File

@ -35,36 +35,32 @@ public:
void init(const char *argv0); void init(const char *argv0);
void terminate(); void terminate();
/// Sets the write directory /// Set output files dir
bool setWriteDir(const std::string &path); bool setWriteDir(const std::string &path);
/// Adds a directory or zip archive to the search path /// Add an package or directory to the search path
bool addToSearchPath(const std::string& path, bool insertInFront = true); bool addToSearchPath(const std::string& path, bool insertInFront = true);
/// Add all packages from a directory
void addPackagesToSearchPath(const std::string &packagesDirectory, const std::string &packageExtension, bool append);
/// Checks whether the given file exists in the search path bool fileExists(const std::string& fileName);
bool fileExists(const std::string& filePath); bool directoryExists(const std::string& directoryName);
/// Searches for zip files and adds them to the search path bool loadFile(const std::string& fileName, std::iostream& out);
void searchAndAddArchives(const std::string &path,
const std::string &ext,
const bool append);
/** Load a file by allocating a buffer and filling it with the file contents
* where fileSize will be set to the file size.
* The returned buffer must be freed with delete[]. */
uchar *loadFile(const std::string &fileName, uint *fileSize);
/// Loads a text file into a std::string
std::string loadTextFile(const std::string &fileName);
/// Save a file into write directory
bool saveFile(const std::string& fileName, const uchar *data, uint size); bool saveFile(const std::string& fileName, const uchar *data, uint size);
bool saveFile(const std::string& fileName, std::istream& in);
/// Save a text file into write directory bool deleteFile(const std::string& fileName);
bool saveTextFile(const std::string &fileName, std::string text);
/// Get a list with all files in a directory std::list<std::string> listDirectoryFiles(const std::string& directoryPath = "");
std::list<std::string> getDirectoryFiles(const std::string& directory);
void pushCurrentPath(const std::string &currentPath);
void popCurrentPath();
std::string resolvePath(const std::string& path);
private:
std::stack<std::string> m_currentPaths;
}; };
extern Resources g_resources; extern Resources g_resources;

View File

@ -68,13 +68,12 @@ void Font::calculateGlyphsWidthsAutomatically(const Size& glyphSize)
bool Font::load(const std::string& file) bool Font::load(const std::string& file)
{ {
std::string fileContents = g_resources.loadTextFile(file); std::stringstream fin;
if(!fileContents.size()) { if(!g_resources.loadFile(file, fin)) {
flogError("ERROR: Coult not load font file \"%s", file.c_str()); flogError("ERROR: Coult not load font file \"%s", file.c_str());
return false; return false;
} }
std::istringstream fin(fileContents);
std::string textureName; std::string textureName;
Size glyphSize; Size glyphSize;
@ -94,7 +93,7 @@ bool Font::load(const std::string& file)
m_glyphSpacing = yamlRead(doc, "glyph spacing", Size(0,0)); m_glyphSpacing = yamlRead(doc, "glyph spacing", Size(0,0));
// load texture // load texture
m_texture = g_textures.get("fonts/" + textureName); m_texture = g_textures.get(textureName);
if(!m_texture) { if(!m_texture) {
flogError("ERROR: Failed to load image for font file \"%s\"", file.c_str()); flogError("ERROR: Failed to load image for font file \"%s\"", file.c_str());
return false; return false;

View File

@ -30,17 +30,21 @@ Fonts g_fonts;
void Fonts::init() void Fonts::init()
{ {
g_resources.pushCurrentPath("fonts");
// load all fonts // load all fonts
std::list<std::string> files = g_resources.getDirectoryFiles("fonts"); std::list<std::string> files = g_resources.listDirectoryFiles();
foreach(const std::string& file, files) { foreach(const std::string& file, files) {
if(boost::ends_with(file, ".yml")) { if(boost::ends_with(file, ".yml")) {
std::string name = file; std::string name = file;
boost::erase_first(name, ".yml"); boost::erase_first(name, ".yml");
FontPtr font(new Font(name)); FontPtr font(new Font(name));
if(font->load("fonts/" + file)) if(font->load(file))
m_fonts.push_back(font); m_fonts.push_back(font);
} }
} }
g_resources.popCurrentPath();
} }
FontPtr Fonts::get(const std::string& fontName) FontPtr Fonts::get(const std::string& fontName)

View File

@ -28,12 +28,12 @@
#include <util/apngloader.h> #include <util/apngloader.h>
#include "animatedtexture.h" #include "animatedtexture.h"
TexturePtr TextureLoader::loadPNG(uchar *fileData, uint fileSize) TexturePtr TextureLoader::loadPNG(std::stringstream& file)
{ {
TexturePtr texture; TexturePtr texture;
apng_data apng; apng_data apng;
if(load_apng(fileData, fileSize, &apng) == 0) { if(load_apng(file, &apng) == 0) {
if(apng.num_frames > 1) { // animated texture if(apng.num_frames > 1) { // animated texture
uchar *framesdata = apng.pdata + (apng.first_frame * apng.width * apng.height * apng.bpp); 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)); texture = TexturePtr(new AnimatedTexture(apng.width, apng.height, apng.bpp, apng.num_frames, framesdata, (int*)apng.frames_delay));

View File

@ -32,7 +32,7 @@ class TextureLoader
{ {
public: public:
/// Load a png textures /// Load a png textures
static TexturePtr loadPNG(uchar *fileData, uint fileSize); static TexturePtr loadPNG(std::stringstream& file);
}; };
#endif // TEXTURELOADER_H #endif // TEXTURELOADER_H

View File

@ -52,19 +52,17 @@ TexturePtr Textures::get(const std::string& textureFile)
} }
// load texture file data // load texture file data
uint fileSize; std::stringstream fin;
uchar *textureFileData = g_resources.loadFile(textureFile, &fileSize); if(!g_resources.loadFile(textureFile, fin)) {
if(!textureFileData) {
flogError("ERROR: Unable to load texture %s, file could not be read.", textureFile.c_str()); flogError("ERROR: Unable to load texture %s, file could not be read.", textureFile.c_str());
return texture; return texture;
} }
// load the texture // load the texture
texture = TexturePtr(TextureLoader::loadPNG(textureFileData, fileSize)); texture = TexturePtr(TextureLoader::loadPNG(fin));
if(!texture) if(!texture)
flogError("ERROR: Unable to load texture %s", textureFile.c_str()); flogError("ERROR: Unable to load texture %s", textureFile.c_str());
delete[] textureFileData;
} }
return texture; return texture;
} }

View File

@ -834,7 +834,7 @@ bool Platform::isWindowMaximized()
std::string Platform::getAppUserDir() std::string Platform::getAppUserDir()
{ {
std::stringstream sdir; std::stringstream sdir;
sdir << PHYSFS_getUserDir() << "/." << x11.appName << "/"; sdir << PHYSFS_getUserDir() << "." << x11.appName;
if((mkdir(sdir.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) && (errno != EEXIST)) if((mkdir(sdir.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) && (errno != EEXIST))
flogError("ERROR: Couldn't create directory for saving configuration file. (%s)", sdir.str().c_str()); flogError("ERROR: Couldn't create directory for saving configuration file. (%s)", sdir.str().c_str());
return sdir.str(); return sdir.str();

View File

@ -55,6 +55,7 @@ typedef int8_t int8;
#include <algorithm> #include <algorithm>
#include <string> #include <string>
#include <vector> #include <vector>
#include <stack>
#include <map> #include <map>
#include <string> #include <string>
#include <list> #include <list>

View File

@ -98,7 +98,7 @@ int lua_UI_load()
UIElementPtr element; UIElementPtr element;
if(parent) if(parent)
element = UILoader::loadFile(uiFile.c_str(), parent); element = g_uiLoader.loadFromYAML(uiFile.c_str(), parent);
else else
g_lua.reportErrorWithTraceback("invalid parent container"); g_lua.reportErrorWithTraceback("invalid parent container");

View File

@ -54,9 +54,9 @@ void LuaScript::terminate()
void LuaScript::loadAllModules() void LuaScript::loadAllModules()
{ {
std::list<std::string> modules = g_resources.getDirectoryFiles("modules"); std::list<std::string> modules = g_resources.listDirectoryFiles("modules");
foreach(const std::string& module, modules) { foreach(const std::string& module, modules) {
std::list<std::string> moduleFiles = g_resources.getDirectoryFiles(std::string("modules/") + module); std::list<std::string> moduleFiles = g_resources.listDirectoryFiles("modules/" + module);
foreach(const std::string& moduleFile, moduleFiles) { foreach(const std::string& moduleFile, moduleFiles) {
if(boost::ends_with(moduleFile, ".lua")) if(boost::ends_with(moduleFile, ".lua"))
loadFile(std::string("modules/") + module + "/" + moduleFile); loadFile(std::string("modules/") + module + "/" + moduleFile);
@ -66,42 +66,24 @@ void LuaScript::loadAllModules()
bool LuaScript::loadFile(const std::string& fileName) bool LuaScript::loadFile(const std::string& fileName)
{ {
if(!g_resources.fileExists(fileName)) { std::stringstream fin;
if(g_resources.loadFile(fileName, fin))
return loadBuffer(fin.str(), fileName);
else
flogError("ERROR: script file '%s' doesn't exist", fileName.c_str()); flogError("ERROR: script file '%s' doesn't exist", fileName.c_str());
return false; return false;
} }
std::string fileContents = g_resources.loadTextFile(fileName);
return loadBuffer(fileContents, fileName);
}
bool LuaScript::loadBuffer(const std::string& text, const std::string& what) bool LuaScript::loadBuffer(const std::string& text, const std::string& what)
{ {
// load buffer if(loadBufferAsFunction(text, what) && callFunction())
int ret = luaL_loadbuffer(L, text.c_str(), text.length(), what.c_str());
if(ret != 0){
reportError(popString());
return false;
}
// check if is loaded as a function
if(lua_isfunction(L, -1) == 0) {
pop();
return false;
}
// execute it
ret = lua_pcall(L, 0, 0, 0);
if(ret != 0){
reportError(popString());
return false;
}
return true; return true;
return false;
} }
bool LuaScript::loadBufferAsFunction(const std::string& text, const std::string& what) bool LuaScript::loadBufferAsFunction(const std::string& text, const std::string& what)
{ {
int ret = luaL_loadbuffer(L, text.c_str(), text.length(), what.c_str()); int ret = luaL_loadbuffer(L, text.c_str(), text.length(), ("@" + what).c_str());
if(ret != 0){ if(ret != 0){
reportError(popString()); reportError(popString());
return false; return false;
@ -111,7 +93,6 @@ bool LuaScript::loadBufferAsFunction(const std::string& text, const std::string&
pop(); pop();
return false; return false;
} }
return true; return true;
} }
@ -145,9 +126,17 @@ int LuaScript::getStackSize()
void LuaScript::insert(int index) void LuaScript::insert(int index)
{ {
if(index != -1)
lua_insert(L, index); lua_insert(L, index);
} }
void LuaScript::swap(int index)
{
insert(index);
pushValue(index+1);
remove(index);
}
void LuaScript::remove(int index) void LuaScript::remove(int index)
{ {
lua_remove(L, index); lua_remove(L, index);
@ -390,23 +379,61 @@ void LuaScript::pushRef(int ref)
lua_rawgeti(L, LUA_REGISTRYINDEX, ref); lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
} }
void LuaScript::callFunction(int numArgs) std::string LuaScript::getFunctionSourcePath()
{ {
int size = lua_gettop(L); std::string path;
int errorIndex = -(numArgs + 2);
lua_pushcfunction(L, &LuaScript::luaErrorHandler);
lua_insert(L, errorIndex);
int ret = lua_pcall(L, numArgs, 0, errorIndex); lua_Debug ar;
if(ret != 0) { memset(&ar, 0, sizeof(ar));
reportError(popString()); lua_getinfo(L, ">Sn", &ar);
// c function, we must get information of level above
if(strcmp("C", ar.what) == 0) {
memset(&ar, 0, sizeof(ar));
if(lua_getstack(L, 1, &ar) == 1) {
lua_getinfo(L, "f", &ar);
return getFunctionSourcePath();
} }
// pop error func } else {
lua_pop(L, 1); if(ar.source) {
std::string source = ar.source;
std::size_t pos = source.find_last_of('/');
if(source[0] == '@' && pos != std::string::npos)
path = source.substr(1, pos - 1);
} else {
logError("no source");
}
}
return path;
}
if(lua_gettop(L) != size - numArgs - 1) bool LuaScript::callFunction(int numArgs, int numRets)
{
pushValue(-numArgs - 1);
g_resources.pushCurrentPath(getFunctionSourcePath());
int size = getStackSize();
int errorIndex = -numArgs - 2;
lua_pushcfunction(L, &LuaScript::luaErrorHandler);
insert(errorIndex);
int ret = lua_pcall(L, numArgs, numRets, errorIndex);
if(ret != 0) {
reportError(popString());
pop(); // pop error func
return false;
}
remove(-numRets - 1); // pop error func
if(getStackSize() != size - numArgs - 1 + numRets) {
reportError("stack size changed!"); reportError("stack size changed!");
return false;
}
g_resources.popCurrentPath();
return true;
} }
void LuaScript::callModuleField(const std::string& module, const std::string& field) void LuaScript::callModuleField(const std::string& module, const std::string& field)
@ -581,8 +608,9 @@ int LuaScript::luaPackageLoader(lua_State* L)
std::string fileName = lua_tostring(L, -1); std::string fileName = lua_tostring(L, -1);
fileName += ".lua"; fileName += ".lua";
if(g_resources.fileExists(fileName)) { if(g_resources.fileExists(fileName)) {
std::string fileContents = g_resources.loadTextFile(fileName); std::stringstream fin;
luaL_loadbuffer(L, fileContents.c_str(), fileContents.length(), fileName.c_str()); if(g_resources.loadFile(fileName, fin))
luaL_loadbuffer(L, fin.str().c_str(), fin.str().length(), fileName.c_str());
} else { } else {
lua_pushfstring(L, "\n\tcould not load lua script " LUA_QS, fileName.c_str()); lua_pushfstring(L, "\n\tcould not load lua script " LUA_QS, fileName.c_str());
} }
@ -601,16 +629,8 @@ int LuaScript::luaIndexMetaMethod(lua_State* L)
if(!lua_isnil(L, -1)) { if(!lua_isnil(L, -1)) {
lua_remove(L, -2); // get_method, obj lua_remove(L, -2); // get_method, obj
lua_insert(L, -2); // obj, get_method lua_insert(L, -2); // obj, get_method
lua_pushcfunction(L, &LuaScript::luaErrorHandler); // errorfunc, obj,get_method if(!g_lua.callFunction(1, 1))
lua_insert(L, -3); // obj, get_method, errorfunc lua_pushnil(L);
int ret = lua_pcall(L, 1, 1, -3); // ret, errorfunc
if(ret != 0) {
g_lua.reportError(g_lua.popString()); // errofunc
lua_pop(L, 1); // (empty)
lua_pushnil(L); // nil
} else {
lua_remove(L, -2); // ret
}
return 1; return 1;
} else { } else {
lua_pop(L, 1); // mt, obj lua_pop(L, 1); // mt, obj
@ -618,7 +638,7 @@ int LuaScript::luaIndexMetaMethod(lua_State* L)
lua_getfield(L, -1, key.c_str()); // method, methods, mt, obj lua_getfield(L, -1, key.c_str()); // method, methods, mt, obj
lua_remove(L, -2); // method, mt, obj lua_remove(L, -2); // method, mt, obj
if(!lua_isnil(L, -1)) { if(!lua_isnil(L, -1)) {
lua_insert(L, -3); // obj, mt, method lua_insert(L, -3); // mt, obj, method
lua_pop(L, 2); // method lua_pop(L, 2); // method
return 1; return 1;
} }
@ -654,12 +674,7 @@ int LuaScript::luaNewIndexMetaMethod(lua_State* L)
if(!lua_isnil(L, -1)) { if(!lua_isnil(L, -1)) {
lua_remove(L, -2); // set_method, value, obj lua_remove(L, -2); // set_method, value, obj
lua_insert(L, -3); // value, obj, set_method lua_insert(L, -3); // value, obj, set_method
lua_pushcfunction(L, &LuaScript::luaErrorHandler); // errorfunc, value, obj, set_method g_lua.callFunction(2);
lua_insert(L, -4); // value, obj, set_method, errorfunc
int ret = lua_pcall(L, 2, 0, -4); // errorfunc
if(ret != 0)
g_lua.reportError(g_lua.popString()); // errofunc
lua_pop(L, 1); // (empty)
return 1; return 1;
} }
lua_pop(L, 2); // mt, value, obj lua_pop(L, 2); // mt, value, obj

View File

@ -52,6 +52,7 @@ public:
int getStackSize(); int getStackSize();
void insert(int index); void insert(int index);
void swap(int index);
void remove(int index); void remove(int index);
bool next(int index = -2); bool next(int index = -2);
void releaseRef(int ref); void releaseRef(int ref);
@ -103,7 +104,9 @@ public:
void pushValue(int index = -1); void pushValue(int index = -1);
void pushRef(int ref); void pushRef(int ref);
void callFunction(int numArgs = 0); std::string getFunctionSourcePath();
bool callFunction(int numArgs = 0, int numRets = 0);
void callModuleField(const std::string& module, const std::string& field); void callModuleField(const std::string& module, const std::string& field);
typedef int (*LuaCFunction)(); typedef int (*LuaCFunction)();

View File

@ -69,7 +69,7 @@ ImagePtr UIElementSkin::loadImage(const YAML::Node& node)
std::string textureName = yamlRead(cnode, "source", std::string()); std::string textureName = yamlRead(cnode, "source", std::string());
if(!textureName.empty()) if(!textureName.empty())
texture = g_textures.get("skins/" + textureName); texture = g_textures.get(textureName);
else else
texture = g_uiSkins.getDefaultTexture(); texture = g_uiSkins.getDefaultTexture();
@ -89,7 +89,7 @@ ImagePtr UIElementSkin::loadImage(const YAML::Node& node)
if(!image) if(!image)
logError(yamlErrorDesc(cnode, "failed to load bordered image")); logError(yamlErrorDesc(cnode, "failed to load bordered image"));
} else if(yamlHasValue(node, "image")) { } else if(yamlHasValue(node, "image")) {
texture = g_textures.get("skins/" + yamlRead<std::string>(node, "image")); texture = g_textures.get(yamlRead<std::string>(node, "image"));
if(texture) if(texture)
image = ImagePtr(new Image(texture)); image = ImagePtr(new Image(texture));
if(!m_defaultSize.isValid()) if(!m_defaultSize.isValid())

View File

@ -30,6 +30,8 @@
#include <script/luafunctions.h> #include <script/luafunctions.h>
#include "uianchorlayout.h" #include "uianchorlayout.h"
UILoader g_uiLoader;
UIElementPtr UILoader::createElementFromId(const std::string& id) UIElementPtr UILoader::createElementFromId(const std::string& id)
{ {
UIElementPtr element; UIElementPtr element;
@ -65,20 +67,15 @@ UIElementPtr UILoader::createElementFromId(const std::string& id)
return element; return element;
} }
UIElementPtr UILoader::loadFile(const std::string& file, const UIContainerPtr& parent) UIElementPtr UILoader::loadFromYAML(std::string filePath, const UIContainerPtr& parent)
{ {
// try to find the file std::stringstream fin;
std::string filePath = "modules/" + file; if(!g_resources.loadFile(filePath, fin)) {
if(!g_resources.fileExists(filePath)) flogError("ERROR: Could not load ui file \"%s", filePath.c_str());
filePath = "addons/" + file;
if(!g_resources.fileExists(filePath))
filePath = file;
if(!g_resources.fileExists(filePath)) {
flogError("ERROR: Could not load ui file \"%s", file.c_str());
return UIElementPtr(); return UIElementPtr();
} }
std::istringstream fin(g_resources.loadTextFile(filePath)); m_currentFile = filePath;
try { try {
YAML::Parser parser(fin); YAML::Parser parser(fin);
@ -110,7 +107,7 @@ UIElementPtr UILoader::loadFile(const std::string& file, const UIContainerPtr& p
element->onLoad(); element->onLoad();
return element; return element;
} catch (YAML::Exception& e) { } catch (YAML::Exception& e) {
flogError("ERROR: Failed to load ui file \"%s\":\n %s", file.c_str() % e.what()); flogError("ERROR: Failed to load ui file \"%s\":\n %s", filePath.c_str() % e.what());
} }
return UIElementPtr(); return UIElementPtr();
@ -208,7 +205,7 @@ void UILoader::loadElement(const UIElementPtr& element, const YAML::Node& node)
// load events // load events
if(yamlHasValue(node, "onLoad")) { if(yamlHasValue(node, "onLoad")) {
const YAML::Node& cnode = node["onLoad"]; const YAML::Node& cnode = node["onLoad"];
if(g_lua.loadBufferAsFunction(yamlRead<std::string>(cnode), element->getId() + ":onLoad")) if(g_lua.loadBufferAsFunction(yamlRead<std::string>(cnode), getElementSourceDesc(element, "onLoad")))
g_lua.setScriptableField(element, "onLoad"); g_lua.setScriptableField(element, "onLoad");
else else
logError(yamlErrorDesc(cnode, "failed to parse inline lua script")); logError(yamlErrorDesc(cnode, "failed to parse inline lua script"));
@ -216,7 +213,7 @@ void UILoader::loadElement(const UIElementPtr& element, const YAML::Node& node)
if(yamlHasValue(node, "onDestroy")) { if(yamlHasValue(node, "onDestroy")) {
const YAML::Node& cnode = node["onDestroy"]; const YAML::Node& cnode = node["onDestroy"];
if(g_lua.loadBufferAsFunction(yamlRead<std::string>(cnode), element->getId() + ":onDestroy")) if(g_lua.loadBufferAsFunction(yamlRead<std::string>(cnode), getElementSourceDesc(element, "onDestroy")))
g_lua.setScriptableField(element, "onDestroy"); g_lua.setScriptableField(element, "onDestroy");
else else
logError(yamlErrorDesc(cnode, "failed to parse inline lua script")); logError(yamlErrorDesc(cnode, "failed to parse inline lua script"));
@ -273,9 +270,19 @@ void UILoader::loadButton(const UIButtonPtr& button, const YAML::Node& node)
// set on click event // set on click event
if(yamlHasValue(node, "onClick")) { if(yamlHasValue(node, "onClick")) {
const YAML::Node& cnode = node["onClick"]; const YAML::Node& cnode = node["onClick"];
if(g_lua.loadBufferAsFunction(yamlRead<std::string>(cnode), button->getId() + ":onClick")) if(g_lua.loadBufferAsFunction(yamlRead<std::string>(cnode), getElementSourceDesc(button, "onClick")))
g_lua.setScriptableField(button, "onClick"); g_lua.setScriptableField(button, "onClick");
else else
logError(yamlErrorDesc(cnode, "failed to parse inline lua script")); logError(yamlErrorDesc(cnode, "failed to parse inline lua script"));
} }
} }
std::string UILoader::getElementSourceDesc(const UIElementPtr& element, const std::string& key)
{
std::string desc;
desc += g_resources.resolvePath(m_currentFile) + ":" + element->getId();
if(key.length() > 0)
desc += "[" + key + "]";
return desc;
}

View File

@ -34,26 +34,32 @@ class UILoader
{ {
public: public:
/// Loads an UIElement and it's children from a YAML file /// Loads an UIElement and it's children from a YAML file
static UIElementPtr loadFile(const std::string& file, const UIContainerPtr& parent = UIContainer::getRoot()); UIElementPtr loadFromYAML(std::string filePath, const UIContainerPtr& parent = UIContainer::getRoot());
private: private:
/// Detect element type and create it /// Detect element type and create it
static UIElementPtr createElementFromId(const std::string& id); UIElementPtr createElementFromId(const std::string& id);
/// Populate container children from a YAML node /// Populate container children from a YAML node
static void populateContainer(const UIContainerPtr& parent, const YAML::Node& node); void populateContainer(const UIContainerPtr& parent, const YAML::Node& node);
/// Load element and its children from a YAML node /// Load element and its children from a YAML node
static void loadElements(const UIElementPtr& parent, const YAML::Node& node); void loadElements(const UIElementPtr& parent, const YAML::Node& node);
/// Load element proprieties from a YAML node /// Load element proprieties from a YAML node
static void loadElement(const UIElementPtr& element, const YAML::Node& node); void loadElement(const UIElementPtr& element, const YAML::Node& node);
/// Load anchor from a YAML node /// Load anchor from a YAML node
static void loadElementAnchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, const YAML::Node& node); void loadElementAnchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, const YAML::Node& node);
// specific elements loading // specific elements loading
static void loadButton(const UIButtonPtr& button, const YAML::Node& node); void loadButton(const UIButtonPtr& button, const YAML::Node& node);
std::string getElementSourceDesc(const UIElementPtr& element, const std::string& key = "");
std::string m_currentFile;
}; };
extern UILoader g_uiLoader;
#endif // UILOADER_H #endif // UILOADER_H

View File

@ -35,13 +35,13 @@
UISkins g_uiSkins; UISkins g_uiSkins;
void UISkins::load(const std::string& skinsFile) void UISkins::load(const std::string& skinName)
{ {
std::string fileContents = g_resources.loadTextFile(skinsFile); g_resources.pushCurrentPath("skins");
if(!fileContents.size())
flogFatal("FATAL ERROR: Could not load skin file \"%s", skinsFile.c_str());
std::istringstream fin(fileContents); std::stringstream fin;
if(!g_resources.loadFile(skinName + ".yml", fin))
flogFatal("FATAL ERROR: Could not load skin \"%s", skinName.c_str());
try { try {
YAML::Parser parser(fin); YAML::Parser parser(fin);
@ -57,7 +57,7 @@ void UISkins::load(const std::string& skinsFile)
std::string defaultTextureName = yamlRead(doc, "default texture", std::string()); std::string defaultTextureName = yamlRead(doc, "default texture", std::string());
if(!defaultTextureName.empty()) if(!defaultTextureName.empty())
m_defaultTexture = g_textures.get("skins/" + defaultTextureName); m_defaultTexture = g_textures.get(defaultTextureName);
{ {
const YAML::Node& node = doc["buttons"]; const YAML::Node& node = doc["buttons"];
@ -133,8 +133,10 @@ void UISkins::load(const std::string& skinsFile)
} }
} }
} catch (YAML::Exception& e) { } catch (YAML::Exception& e) {
flogFatal("FATAL ERROR: Malformed skin file \"%s\":\n %s", skinsFile.c_str() % e.what()); flogFatal("FATAL ERROR: Malformed skin file \"%s\":\n %s", skinName.c_str() % e.what());
} }
g_resources.popCurrentPath();
} }
void UISkins::terminate() void UISkins::terminate()

View File

@ -35,7 +35,7 @@ class UISkins
public: public:
UISkins() { } UISkins() { }
void load(const std::string& skinsFile); void load(const std::string& skinName);
void terminate(); void terminate();
UIElementSkinPtr getElementSkin(UI::ElementType elementType, const std::string& name = "default"); UIElementSkinPtr getElementSkin(UI::ElementType elementType, const std::string& name = "default");

View File

@ -507,7 +507,7 @@ void compose6(unsigned char * dst, unsigned int dstbytes, unsigned char * src, u
} }
} }
int load_apng(unsigned char *filedata, unsigned int filesize, struct apng_data *apng) int load_apng(std::stringstream& file, struct apng_data *apng)
{ {
unsigned int i, j; unsigned int i, j;
unsigned int rowbytes; unsigned int rowbytes;
@ -522,8 +522,6 @@ int load_apng(unsigned char *filedata, unsigned int filesize, struct apng_data *
unsigned char coltype, compr, filter, interl; unsigned char coltype, compr, filter, interl;
z_stream zstream; z_stream zstream;
memset(apng, 0, sizeof(struct apng_data)); memset(apng, 0, sizeof(struct apng_data));
std::istringstream f1;
f1.rdbuf()->pubsetbuf((char*)filedata, filesize);
for (i=0; i<256; i++) for (i=0; i<256; i++)
{ {
@ -560,21 +558,21 @@ int load_apng(unsigned char *filedata, unsigned int filesize, struct apng_data *
unsigned char * pDst2; unsigned char * pDst2;
unsigned int * frames_delay; unsigned int * frames_delay;
f1.read((char*)sig, 8); file.read((char*)sig, 8);
if(f1.good() && memcmp(sig, png_sign, 8) == 0) { if(!file.eof() && memcmp(sig, png_sign, 8) == 0) {
len = read32(f1); len = read32(file);
chunk = read32(f1); chunk = read32(file);
if ((len == 13) && (chunk == 0x49484452)) /* IHDR */ if ((len == 13) && (chunk == 0x49484452)) /* IHDR */
{ {
w = w0 = read32(f1); w = w0 = read32(file);
h = h0 = read32(f1); h = h0 = read32(file);
f1.read((char*)&depth, 1); file.read((char*)&depth, 1);
f1.read((char*)&coltype, 1); file.read((char*)&coltype, 1);
f1.read((char*)&compr, 1); file.read((char*)&compr, 1);
f1.read((char*)&filter, 1); file.read((char*)&filter, 1);
f1.read((char*)&interl, 1); file.read((char*)&interl, 1);
crc = read32(f1); crc = read32(file);
channels = 1; channels = 1;
if (coltype == 2) if (coltype == 2)
@ -616,17 +614,17 @@ int load_apng(unsigned char *filedata, unsigned int filesize, struct apng_data *
memset(pOut1, 0, outimg1); memset(pOut1, 0, outimg1);
memset(pOut2, 0, outimg2); memset(pOut2, 0, outimg2);
while (!f1.eof()) while (!file.eof())
{ {
len = read32(f1); len = read32(file);
chunk = read32(f1); chunk = read32(file);
if (chunk == 0x504C5445) /* PLTE */ if (chunk == 0x504C5445) /* PLTE */
{ {
unsigned int col; unsigned int col;
for (i=0; i<len; i++) for (i=0; i<len; i++)
{ {
f1.read((char*)&c, 1); file.read((char*)&c, 1);
col = i/3; col = i/3;
if (col<256) if (col<256)
{ {
@ -634,14 +632,14 @@ int load_apng(unsigned char *filedata, unsigned int filesize, struct apng_data *
palsize = col+1; palsize = col+1;
} }
} }
crc = read32(f1); crc = read32(file);
} }
else if (chunk == 0x74524E53) /* tRNS */ else if (chunk == 0x74524E53) /* tRNS */
{ {
hasTRNS = 1; hasTRNS = 1;
for (i=0; i<len; i++) for (i=0; i<len; i++)
{ {
f1.read((char*)&c, 1); file.read((char*)&c, 1);
if (i<256) if (i<256)
{ {
trns[i] = c; trns[i] = c;
@ -671,16 +669,16 @@ int load_apng(unsigned char *filedata, unsigned int filesize, struct apng_data *
trns[5] = trns[4]; trns[4] = 0; trns[5] = trns[4]; trns[4] = 0;
} }
} }
crc = read32(f1); crc = read32(file);
} }
else if (chunk == 0x6163544C) /* acTL */ else if (chunk == 0x6163544C) /* acTL */
{ {
frames = read32(f1); frames = read32(file);
if(frames_delay) if(frames_delay)
free(frames_delay); free(frames_delay);
frames_delay = (unsigned int*)malloc(frames*sizeof(int)); frames_delay = (unsigned int*)malloc(frames*sizeof(int));
loops = read32(f1); loops = read32(file);
crc = read32(f1); crc = read32(file);
if (pOut1) if (pOut1)
free(pOut1); free(pOut1);
if (pOut2) if (pOut2)
@ -748,16 +746,16 @@ int load_apng(unsigned char *filedata, unsigned int filesize, struct apng_data *
} }
} }
seq = read32(f1); seq = read32(file);
w0 = read32(f1); w0 = read32(file);
h0 = read32(f1); h0 = read32(file);
x0 = read32(f1); x0 = read32(file);
y0 = read32(f1); y0 = read32(file);
d1 = read16(f1); d1 = read16(file);
d2 = read16(f1); d2 = read16(file);
f1.read((char*)&dop, 1); file.read((char*)&dop, 1);
f1.read((char*)&bop, 1); file.read((char*)&bop, 1);
crc = read32(f1); crc = read32(file);
if(d2 == 0) if(d2 == 0)
d2 = 100; d2 = 100;
@ -780,17 +778,17 @@ int load_apng(unsigned char *filedata, unsigned int filesize, struct apng_data *
} }
else if (chunk == 0x49444154) /* IDAT */ else if (chunk == 0x49444154) /* IDAT */
{ {
f1.read((char*)(pData + zsize), len); file.read((char*)(pData + zsize), len);
zsize += len; zsize += len;
crc = read32(f1); crc = read32(file);
} }
else if (chunk == 0x66644154) /* fdAT */ else if (chunk == 0x66644154) /* fdAT */
{ {
seq = read32(f1); seq = read32(file);
len -= 4; len -= 4;
f1.read((char*)(pData + zsize), len); file.read((char*)(pData + zsize), len);
zsize += len; zsize += len;
crc = read32(f1); crc = read32(file);
} }
else if (chunk == 0x49454E44) /* IEND */ else if (chunk == 0x49454E44) /* IEND */
{ {
@ -818,8 +816,8 @@ int load_apng(unsigned char *filedata, unsigned int filesize, struct apng_data *
c = (unsigned char)(chunk & 0xFF); c = (unsigned char)(chunk & 0xFF);
if (notabc(c)) break; if (notabc(c)) break;
f1.seekg(len, std::ios_base::cur); file.seekg(len, std::ios_base::cur);
crc = read32(f1); crc = read32(file);
} }
} }
/* apng decoding - end */ /* apng decoding - end */

View File

@ -25,6 +25,8 @@
#ifndef APNGLOADER_H #ifndef APNGLOADER_H
#define APNGLOADER_H #define APNGLOADER_H
#include <sstream>
struct apng_data { struct apng_data {
unsigned char *pdata; unsigned char *pdata;
unsigned int width; unsigned int width;
@ -39,7 +41,7 @@ struct apng_data {
}; };
// returns -1 on error, 0 on success // returns -1 on error, 0 on success
int load_apng(unsigned char *filedata, unsigned int filesize, struct apng_data *apng); int load_apng(std::stringstream& file, struct apng_data *apng);
void free_apng(struct apng_data *apng); void free_apng(struct apng_data *apng);
#endif // APNGLOADER_H #endif // APNGLOADER_H

View File

@ -101,9 +101,6 @@ int main(int argc, const char *argv[])
// init resources // init resources
g_resources.init(args[0].c_str()); g_resources.init(args[0].c_str());
if(g_resources.setWriteDir(Platform::getAppUserDir()))
g_resources.addToSearchPath(Platform::getAppUserDir());
g_resources.addToSearchPath("data");
// before loading configurations set the default ones // before loading configurations set the default ones
setDefaultConfigs(); setDefaultConfigs();
@ -127,7 +124,7 @@ int main(int argc, const char *argv[])
g_engine.enableFpsCounter(); g_engine.enableFpsCounter();
// load ui skins // load ui skins
g_uiSkins.load("skins/lightness.yml"); g_uiSkins.load("lightness");
// load script modules // load script modules
g_lua.loadAllModules(); g_lua.loadAllModules();