Просмотр исходного кода

Fixed up Lua bindings, added default API to the player, added some design assets, improved polybuild tool

Ivan Safrin 15 лет назад
Родитель
Сommit
f797a8af9d

+ 3 - 0
.gitignore

@@ -19,6 +19,9 @@ Core/Dependencies
 Modules/Dependencies
 IDE/Dependencies
 Tools/Dependencies
+Bindings/Dependencies
+IDE/Mac\ OS\ X
+Examples
 
 # OS generated files #
 ######################

BIN
Assets/Icon_base.psd


BIN
Assets/app_file_icon.icns


BIN
Assets/app_file_icon.png


BIN
Assets/file_icon_base.psd


+ 4 - 0
Bindings/Contents/LUA/API/Polycode/OSBasics.lua

@@ -40,3 +40,7 @@ function OSBasics:createFolder(pathString)
 	return Polycore.OSBasics_createFolder(self.__ptr, pathString)
 end
 
+function OSBasics:removeItem(pathString)
+	return Polycore.OSBasics_removeItem(self.__ptr, pathString)
+end
+

+ 4 - 0
Bindings/Contents/LUA/API/Polycode/String.lua

@@ -34,6 +34,10 @@ function String:find(str, pos)
 	return Polycore.String_find(self.__ptr, str.__ptr, pos.__ptr)
 end
 
+function String:find_last_of(str, pos)
+	return Polycore.String_find_last_of(self.__ptr, str.__ptr, pos.__ptr)
+end
+
 function String:toLowerCase()
 	return Polycore.String_toLowerCase(self.__ptr)
 end

+ 8 - 0
Bindings/Contents/LUA/API/defaults.lua

@@ -0,0 +1,8 @@
+
+for k,v in pairs(math) do _G[k]=v end for k,v in pairs(table) do _G[k]=v end
+_G["count"]=_G["getn"]
+
+function Update(e)
+end
+
+print("OKGO!")

+ 20 - 0
Bindings/Contents/LUA/Include/PolycodeLUAWrappers.h

@@ -146,6 +146,15 @@ static int Polycore_OSBasics_createFolder(lua_State *L) {
 	return 0;
 }
 
+static int Polycore_OSBasics_removeItem(lua_State *L) {
+	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
+	OSBasics *inst = (OSBasics*)lua_topointer(L, 1);
+	luaL_checktype(L, 2, LUA_TSTRING);
+	String pathString = lua_tostring(L, 2);
+	inst->removeItem(pathString);
+	return 0;
+}
+
 static int Polycore_BezierCurve(lua_State *L) {
 	BezierCurve *inst = new BezierCurve();
 	lua_pushlightuserdata(L, (void*)inst);
@@ -5729,6 +5738,17 @@ static int Polycore_String_find(lua_State *L) {
 	return 1;
 }
 
+static int Polycore_String_find_last_of(lua_State *L) {
+	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
+	String *inst = (String*)lua_topointer(L, 1);
+	luaL_checktype(L, 2, LUA_TLIGHTUSERDATA);
+	const String & str = *( String *)lua_topointer(L, 2);
+	luaL_checktype(L, 3, LUA_TLIGHTUSERDATA);
+	size_t pos = *(size_t*)lua_topointer(L, 3);
+	lua_pushinteger(L, inst->find_last_of(str, pos));
+	return 1;
+}
+
 static int Polycore_String_toLowerCase(lua_State *L) {
 	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
 	String *inst = (String*)lua_topointer(L, 1);

+ 2 - 0
Bindings/Contents/LUA/Source/PolycodeLUA.cpp

@@ -15,6 +15,7 @@ int luaopen_Polycode(lua_State *L) {
 		{"OSBasics_parseFolder", Polycore_OSBasics_parseFolder},
 		{"OSBasics_isFolder", Polycore_OSBasics_isFolder},
 		{"OSBasics_createFolder", Polycore_OSBasics_createFolder},
+		{"OSBasics_removeItem", Polycore_OSBasics_removeItem},
 		{"BezierCurve", Polycore_BezierCurve},
 		{"BezierCurve_getControlPoint", Polycore_BezierCurve_getControlPoint},
 		{"BezierCurve_getNumControlPoints", Polycore_BezierCurve_getNumControlPoints},
@@ -610,6 +611,7 @@ int luaopen_Polycode(lua_State *L) {
 		{"String_substr", Polycore_String_substr},
 		{"String_rfind", Polycore_String_rfind},
 		{"String_find", Polycore_String_find},
+		{"String_find_last_of", Polycore_String_find_last_of},
 		{"String_toLowerCase", Polycore_String_toLowerCase},
 		{"String_split", Polycore_String_split},
 		{"String_replace", Polycore_String_replace},

+ 1 - 0
Core/Contents/Include/OSBasics.h

@@ -73,6 +73,7 @@ class _PolyExport OSBasics {
 		static vector<OSFileEntry> parseFolder(String pathString, bool showHidden);
 		static bool isFolder(String pathString);
 		static void createFolder(String pathString);
+		static void removeItem(String pathString);
 		
 	private:
 	

+ 1 - 1
Core/Contents/Include/PolyObject.h

@@ -89,7 +89,7 @@ namespace Polycode {
 		Object();
 		~Object();
 		
-		void loadFromXML(String fileName);
+		bool loadFromXML(String fileName);
 		void saveToXML(String fileName);
 		void createFromXMLElement(TiXmlElement *element, ObjectEntry *entry);
 		TiXmlElement *createElementFromObjectEntry(ObjectEntry *entry);

+ 2 - 1
Core/Contents/Include/PolyString.h

@@ -38,7 +38,8 @@ namespace Polycode {
 		
 			size_t rfind ( const String &str, size_t pos = wstring::npos ) const { return contents.rfind(str.contents, pos); }
 			size_t find ( const String &str, size_t pos = 0 ) const { return contents.find(str.contents, pos); }
-
+			size_t find_last_of(const String& str, size_t pos = wstring::npos ) { return contents.find_last_of(str.contents, pos); }
+		
 			inline String operator + (const char *str) const { return String(contents + String(str).contents); }
 		
 			inline String operator + (const String &str) const { return String(contents + str.contents); }

+ 8 - 1
Core/Contents/Source/OSBasics.cpp

@@ -88,7 +88,7 @@ OSFILE *OSBasics::open(String filename, String opts) {
 			return retFile;
 		}
 	} else {
-		Logger::log("File doesn't exist in archive (%s)\n", filename.c_str());
+//		Logger::log("File doesn't exist in archive (%s)\n", filename.c_str());
 	}
 	
 	FILE *file = fopen(filename.c_str(), opts.c_str());
@@ -269,6 +269,13 @@ vector<OSFileEntry> OSBasics::parseFolder(String pathString, bool showHidden) {
 	return returnVector;
 }
 
+void OSBasics::removeItem(String pathString) {
+#ifdef _WINDOWS
+#else
+	remove(pathString.c_str());
+#endif	
+}
+
 void OSBasics::createFolder(String pathString) {
 #ifdef _WINDOWS
 #else

+ 2 - 2
Core/Contents/Source/PolyCore.cpp

@@ -79,8 +79,8 @@ namespace Polycode {
 		frameTicks = getTicks();
 		elapsed = frameTicks - lastFrameTicks;
 		
-		if(elapsed > 100)
-			elapsed = 100;
+		if(elapsed > refreshInterval)
+			elapsed = refreshInterval;
 		services->Update(elapsed);
 
 		if(frameTicks-lastFPSTicks >= 1000) {

+ 22 - 6
Core/Contents/Source/PolyObject.cpp

@@ -30,7 +30,7 @@ TiXmlElement *Object::createElementFromObjectEntry(ObjectEntry *entry) {
 	for(int i=0; i < entry->children.size(); i++) {
 		ObjectEntry *childEntry = entry->children[i];
 		
-		printf("Parsing %s (type: %d)\n", childEntry->name.c_str(), childEntry->type);
+//		printf("Parsing %s (type: %d)\n", childEntry->name.c_str(), childEntry->type);
 		
 		switch(childEntry->type) {
 			case ObjectEntry::BOOL_ENTRY:
@@ -64,30 +64,32 @@ TiXmlElement *Object::createElementFromObjectEntry(ObjectEntry *entry) {
 	return newElement;
 }
 
-void Object::loadFromXML(String fileName) {
+bool Object::loadFromXML(String fileName) {
 
 	TiXmlDocument doc(fileName.c_str());
 	doc.LoadFile();
 
 	if(doc.Error()) {
 		Logger::log("Error loading xml file: %s\n", doc.ErrorDesc());
-		return;
+		return false;
 	}
 	
 	TiXmlElement *rootElement = doc.RootElement();
 	createFromXMLElement(rootElement, &root);
+	return true;	
 }
 
 
 void Object::createFromXMLElement(TiXmlElement *element, ObjectEntry *entry) {
 	entry->name = element->Value();
 	entry->type = ObjectEntry::CONTAINER_ENTRY;
+
+	int ival;
+	double dval;	
 	
 	// run through the attributes
 	TiXmlAttribute* pAttrib=element->FirstAttribute();
 	int i=0;
-	int ival;
-	double dval;
 	while (pAttrib)
 	{
 		ObjectEntry *newEntry = new ObjectEntry();
@@ -96,12 +98,13 @@ void Object::createFromXMLElement(TiXmlElement *element, ObjectEntry *entry) {
 		newEntry->name = pAttrib->Name();
 		
 		if (pAttrib->QueryIntValue(&ival)==TIXML_SUCCESS) {
-			
 			if(newEntry->stringVal.find(".") != -1 && pAttrib->QueryDoubleValue(&dval)==TIXML_SUCCESS) {
 				newEntry->NumberVal = dval;
+				newEntry->intVal = dval;				
 				newEntry->type = ObjectEntry::FLOAT_ENTRY;				
 			} else {
 				newEntry->intVal = ival;
+				newEntry->NumberVal = (Number)ival;				
 				newEntry->type = ObjectEntry::INT_ENTRY;
 			}
 		}
@@ -126,6 +129,19 @@ void Object::createFromXMLElement(TiXmlElement *element, ObjectEntry *entry) {
 	if(element->GetText()) {
 		entry->stringVal = element->GetText();
 		entry->type = ObjectEntry::STRING_ENTRY;
+		
+		entry->intVal = atoi(entry->stringVal.c_str());
+		entry->NumberVal = atof(entry->stringVal.c_str());
+		
+		if(entry->stringVal == "true") {
+			entry->boolVal = true;
+			entry->type = ObjectEntry::BOOL_ENTRY;
+		}
+		if(entry->stringVal == "false") {
+			entry->boolVal = false;
+			entry->type = ObjectEntry::BOOL_ENTRY;
+		}
+		
 		return;
 	}
 		

BIN
IDE/Assets/play_button.png


BIN
IDE/Assets/toolbar_bg.png


BIN
IDE/Assets/toolbar_logo.png


BIN
IDE/Assets/welcome.png


BIN
IDE/Assets/welcome.psd


+ 4 - 4
Player/Build/Mac OS X/English.lproj/MyDocument.xib

@@ -2,10 +2,10 @@
 <archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
 	<data>
 		<int key="IBDocument.SystemTarget">1060</int>
-		<string key="IBDocument.SystemVersion">10D2101a</string>
+		<string key="IBDocument.SystemVersion">10J567</string>
 		<string key="IBDocument.InterfaceBuilderVersion">804</string>
-		<string key="IBDocument.AppKitVersion">1038.29</string>
-		<string key="IBDocument.HIToolboxVersion">460.00</string>
+		<string key="IBDocument.AppKitVersion">1038.35</string>
+		<string key="IBDocument.HIToolboxVersion">462.00</string>
 		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
 			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
 			<string key="NS.object.0">804</string>
@@ -31,7 +31,7 @@
 				<string key="NSClassName">FirstResponder</string>
 			</object>
 			<object class="NSWindowTemplate" id="275939982">
-				<int key="NSWindowStyleMask">15</int>
+				<int key="NSWindowStyleMask">7</int>
 				<int key="NSWindowBacking">2</int>
 				<string key="NSWindowRect">{{133, 235}, {507, 413}}</string>
 				<int key="NSWTFlags">1350041600</int>

+ 5 - 1
Player/Build/Mac OS X/Polycode Player.xcodeproj/project.pbxproj

@@ -29,6 +29,7 @@
 		6DBAB0BF12B6ECCB00986D01 /* PolycodeCocoaPlayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6DBAB0BE12B6ECCB00986D01 /* PolycodeCocoaPlayer.cpp */; };
 		6DBAB0C412B6EE4400986D01 /* PolycodePlayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6DBAB0C312B6EE4400986D01 /* PolycodePlayer.cpp */; };
 		6DFF70421342F4AD00B0C47E /* player_icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 6DFF70411342F4AD00B0C47E /* player_icon.icns */; };
+		6DFF707D1343059400B0C47E /* app_file_icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 6DFF707C1343059400B0C47E /* app_file_icon.icns */; };
 		8D15AC2C0486D014006FF6A4 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 2A37F4B9FDCFA73011CA2CEA /* Credits.rtf */; };
 		8D15AC2F0486D014006FF6A4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165FFE840EACC02AAC07 /* InfoPlist.strings */; };
 		8D15AC310486D014006FF6A4 /* MyDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A37F4ACFDCFA73011CA2CEA /* MyDocument.m */; settings = {ATTRIBUTES = (); }; };
@@ -73,6 +74,7 @@
 		6DBAB0C212B6EE2200986D01 /* PolycodePlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PolycodePlayer.h; path = ../../Contents/Include/PolycodePlayer.h; sourceTree = SOURCE_ROOT; };
 		6DBAB0C312B6EE4400986D01 /* PolycodePlayer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PolycodePlayer.cpp; path = ../../Contents/Source/PolycodePlayer.cpp; sourceTree = SOURCE_ROOT; };
 		6DFF70411342F4AD00B0C47E /* player_icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = player_icon.icns; path = ../../../Assets/player_icon.icns; sourceTree = SOURCE_ROOT; };
+		6DFF707C1343059400B0C47E /* app_file_icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = app_file_icon.icns; path = ../../../Assets/app_file_icon.icns; sourceTree = SOURCE_ROOT; };
 		8D15AC360486D014006FF6A4 /* Polycode_Player-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Polycode_Player-Info.plist"; sourceTree = "<group>"; };
 		8D15AC370486D014006FF6A4 /* Polycode Player.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Polycode Player.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
@@ -186,6 +188,7 @@
 		2A37F4B8FDCFA73011CA2CEA /* Resources */ = {
 			isa = PBXGroup;
 			children = (
+				6DFF707C1343059400B0C47E /* app_file_icon.icns */,
 				6DFF70411342F4AD00B0C47E /* player_icon.icns */,
 				2A37F4B9FDCFA73011CA2CEA /* Credits.rtf */,
 				8D15AC360486D014006FF6A4 /* Polycode_Player-Info.plist */,
@@ -261,6 +264,7 @@
 				1DDD582C0DA1D0D100B32029 /* MyDocument.xib in Resources */,
 				1DDD582D0DA1D0D100B32029 /* MainMenu.xib in Resources */,
 				6DFF70421342F4AD00B0C47E /* player_icon.icns in Resources */,
+				6DFF707D1343059400B0C47E /* app_file_icon.icns in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -278,7 +282,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "";
+			shellScript = "cp -R ../../../Bindings/Contents/LUA/API build/Debug/Polycode\\ Player.app/Contents/Resources/";
 		};
 /* End PBXShellScriptBuildPhase section */
 

+ 1 - 1
Player/Build/Mac OS X/Polycode_Player-Info.plist

@@ -24,7 +24,7 @@
 				<string>polyapp</string>
 			</array>
 			<key>CFBundleTypeIconFile</key>
-			<string></string>
+			<string>app_file_icon</string>
 			<key>CFBundleTypeName</key>
 			<string>Polycode Application Bundle</string>
 			<key>CFBundleTypeOSTypes</key>

+ 51 - 50
Player/Contents/Source/PolycodePlayer.cpp

@@ -11,15 +11,24 @@
 
 extern "C" {	
 //	extern int luaopen_Tau(lua_State* L); // declare the wrapped module
+		//	loadFileIntoState(L, "Polycode Player.app/Contents/Resources/API/class.lua");
 	
 	int MyLoader(lua_State* pState)
-	{
+	{		
 		std::string module = lua_tostring(pState, 1);
 		module += ".lua";
 		
+		string defaultPath = "Contents/Resources/API/";
+		defaultPath.append(module);
+		
 		const char* fullPath = module.c_str();		
 		printf("Loading custom class: %s\n", module.c_str());
 		OSFILE *inFile = OSBasics::open(module, "r");	
+		
+		if(!inFile) {
+			inFile =  OSBasics::open(defaultPath, "r");	
+		}
+		
 		if(inFile) {
 			OSBasics::seek(inFile, 0, SEEK_END);	
 			long progsize = OSBasics::tell(inFile);
@@ -118,7 +127,7 @@ extern "C" {
 		lua_rawset(L, -3);
 		
 		// Table is still on the stack.  Get rid of it now.
-		lua_pop(L, 1);
+		lua_pop(L, 1);		
 		
 		lua_getfield(L, LUA_GLOBALSINDEX, "require");
 		lua_pushstring(L, "class");		
@@ -235,19 +244,19 @@ PolycodePlayer::PolycodePlayer(String fileName, bool knownArchive) : EventDispat
 
 void PolycodePlayer::loadFile(const char *fileName) {
 	
-	TiXmlDocument doc;
-	
 	String nameString = fileName;
 	String ext = nameString.substr(nameString.length() - 8, nameString.length());
 	
 	printf("Loading %s\n", fileName);
 	
 	bool loadingArchive = false;
+	
+	String configPath;
+	
 	if(ext == ".polyapp" || _knownArchive) {
 		ResourceManager *rman = CoreServices::getInstance()->getResourceManager();
 		rman->addArchive(nameString);
-		TiXmlDocument doc1("runinfo.polyrun");
-		doc = doc1;
+		configPath = "runinfo.polyrun";
 		loadingArchive = true;
 		Logger::log("Reading configuration from POLYAPP file... (%s)\n", nameString.c_str());
 	} else {
@@ -260,14 +269,12 @@ void PolycodePlayer::loadFile(const char *fileName) {
 		}
 		
 		rman->addArchive(fileDir);
-		
+		configPath = fileName;
 		Logger::log("Reading configuration from .polycode file directly... (%s)\n", fileName);		
-		TiXmlDocument doc1(fileName);	
-		doc = doc1;
 	}
 	
-	string mainFile = "";
-	string basePath = fileName;
+	String mainFile = "";
+	String basePath = fileName;
 	
 	Number red = 0.2f;
 	Number green = 0.2f;
@@ -275,44 +282,38 @@ void PolycodePlayer::loadFile(const char *fileName) {
 	
 	frameRate = 60;
 	
-	doc.LoadFile();
-	if(doc.Error()) {
-		Logger::log("Error loading file: %s\n", doc.ErrorDesc());
-	} else {
-		TiXmlElement *rootElement = doc.RootElement();		
+	Object configFile;
+	if(!configFile.loadFromXML(configPath)) {
+		Logger::log("Error loading config file\n");
+	} else {		
 		
-		TiXmlNode* pChild;
-		for (pChild = rootElement->FirstChild(); pChild != 0; pChild = pChild->NextSibling()) {
-			if(strcmp(pChild->Value(), "entryPoint") == 0) {
-				mainFile = pChild->ToElement()->GetText();
-			}
-			if(strcmp(pChild->Value(), "defaultWidth") == 0) {
-				xRes = atoi(pChild->ToElement()->GetText());
+		if(configFile.root["entryPoint"]) {
+			mainFile = configFile.root["entryPoint"]->stringVal;
+		}		
+		if(configFile.root["defaultWidth"]) {
+			xRes = configFile.root["defaultWidth"]->intVal;
+		}		
+		if(configFile.root["defaultHeight"]) {
+			yRes = configFile.root["defaultHeight"]->intVal;
+		}		
+		if(configFile.root["frameRate"]) {
+			frameRate = configFile.root["frameRate"]->intVal;
+		}		
+		if(configFile.root["antiAliasingLevel"]) {
+			aaLevel = configFile.root["antiAliasingLevel"]->intVal;
+		}		
+		if(configFile.root["fullScreen"]) {
+			fullScreen = configFile.root["fullScreen"]->boolVal;
+		}		
+		if(configFile.root["backgroundColor"]) {
+			ObjectEntry *color = configFile.root["backgroundColor"];
+			if((*color)["red"] && (*color)["green"] && (*color)["blue"]) {
+				red = (*color)["red"]->NumberVal;
+				green = (*color)["green"]->NumberVal;
+				blue = (*color)["blue"]->NumberVal;
+				
 			}			
-			if(strcmp(pChild->Value(), "defaultHeight") == 0) {
-				yRes = atoi(pChild->ToElement()->GetText());
-			}						
-
-			if(strcmp(pChild->Value(), "frameRate") == 0) {
-				frameRate = atoi(pChild->ToElement()->GetText());
-			}									
-			
-			if(strcmp(pChild->Value(), "antiAliasingLevel") == 0) {
-				aaLevel = atoi(pChild->ToElement()->GetText());
-			}									
-			
-			if(strcmp(pChild->Value(), "fullScreen") == 0) {
-				if(strcmp(pChild->ToElement()->GetText(),"true") == 0)
-					fullScreen = true;
-			}												
-			
-			if(strcmp(pChild->Value(), "backgroundColor") == 0) {
-				pChild->ToElement()->QueryFloatAttribute("red", &red);
-				pChild->ToElement()->QueryFloatAttribute("green", &green);
-				pChild->ToElement()->QueryFloatAttribute("blue", &blue);				
-			}			
-			
-		}
+		}		
 	}
 	
 	Logger::log("Mainfile: %s\n", mainFile.c_str());
@@ -335,14 +336,14 @@ void PolycodePlayer::loadFile(const char *fileName) {
 //	CoreServices::getInstance()->getRenderer()->setClearColor(1,0,0);
 	srand(core->getTicks());
 	
-	string fullPath;
+	String fullPath;
 	
 	if(loadingArchive) {
 		fullPath = mainFile;
 	} else {
-		int lindex = basePath.find_last_of('/');
+		int lindex = basePath.find_last_of("/");
 		fullPath = basePath.substr(0, lindex);	
-		fullPath.append(mainFile);	
+		fullPath += mainFile;	
 		Logger::log(fullPath.c_str());
 	}
 	

+ 1 - 0
Tools/Contents/polybuild/Include/polybuild.h

@@ -3,6 +3,7 @@
 
 #include "stdio.h"
 #include "PolyString.h"
+#include "PolyObject.h"
 #include "OSBasics.h"
 
 using namespace Polycode;

+ 140 - 21
Tools/Contents/polybuild/Source/polybuild.cpp

@@ -56,13 +56,9 @@ uLong filetime(
   return ret;
 }
 
-
-void addFolderToZip(zipFile z, String folderPath, String parentFolder) {
-
-	std::vector<OSFileEntry> files = OSBasics::parseFolder(folderPath, false);
-	for(int i=0; i < files.size(); i++) {
-		if(files[i].type == OSFileEntry::TYPE_FILE) {
-			printf("Adding %s\n", files[i].name.c_str());
+void addFileToZip(zipFile z, String filePath, String pathInZip, bool silent) {
+			if(!silent)
+				printf("Packaging %s as %s\n", filePath.c_str(), pathInZip.c_str());
 
                 	zip_fileinfo zi;
                 	zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
@@ -70,17 +66,11 @@ void addFolderToZip(zipFile z, String folderPath, String parentFolder) {
 			 zi.dosDate = 0;
               	 	 zi.internal_fa = 0;
              		   zi.external_fa = 0;
-             		   filetime(files[i].fullPath.c_str(),&zi.tmz_date,&zi.dosDate);
+             		   filetime(filePath.c_str(),&zi.tmz_date,&zi.dosDate);
 	
-			String pathInZip;
-			if(parentFolder == "") {
-				pathInZip = files[i].name;
-			} else {
-				pathInZip = parentFolder + "/" + files[i].name;
-			}
 			zipOpenNewFileInZip(z, pathInZip.c_str(), &zi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, 2);
 
-			FILE *f = fopen(files[i].fullPath.c_str(), "rb");
+			FILE *f = fopen(filePath.c_str(), "rb");
 			fseek(f, 0, SEEK_END);
 			long fileSize = ftell(f);
 			fseek(f, 0, SEEK_SET);
@@ -91,15 +81,33 @@ void addFolderToZip(zipFile z, String folderPath, String parentFolder) {
 			fclose(f);
 
 			zipCloseFileInZip(z);
+
+}
+
+void addFolderToZip(zipFile z, String folderPath, String parentFolder, bool silent) {
+
+	std::vector<OSFileEntry> files = OSBasics::parseFolder(folderPath, false);
+	for(int i=0; i < files.size(); i++) {
+		if(files[i].type == OSFileEntry::TYPE_FILE) {
+
+			String pathInZip;
+			if(parentFolder == "") {
+				pathInZip = files[i].name;
+			} else {
+				pathInZip = parentFolder + "/" + files[i].name;
+			}
+
+			addFileToZip(z, files[i].fullPath, pathInZip, silent);
+
 		} else {
-			addFolderToZip(z, files[i].fullPath.c_str(), files[i].name);
+			addFolderToZip(z, files[i].fullPath.c_str(), files[i].name, silent);
 		}
 	}
 }
 
 int main(int argc, char **argv) {
 
-	printf("Polycode build tool v0.1.0\n");
+	printf("Polycode build tool v0.1.1\n");
 
 	for(int i=0; i < argc; i++) {
 		String argString = String(argv[i]);
@@ -113,21 +121,132 @@ int main(int argc, char **argv) {
 		
 	}
 	
-	if(getArg("--project") == "") {
-		printf("\n\nInput project missing. Use --project=projectPath to specify.\n\n");
+	if(getArg("--config") == "") {
+		printf("\n\nInput config XML missing. Use --config=path to specify.\n\n");
 		return 0;
 	}
 
+	
 	if(getArg("--out") == "") {
 		printf("\n\nOutput file not specified. Use --out=outfile.polyapp to specify.\n\n");
 		return 0;		
 	}
-	
+
+	char dirPath[4098];
+	getcwd(dirPath, sizeof(dirPath));
+	String currentPath = String(dirPath);
+
+	String configPath = getArg("--config");
+
+	String finalPath = configPath;
+	if(configPath[0] != '/') {
+		finalPath = currentPath+"/"+configPath;
+	}
+
+	printf("Reading config file from %s\n", finalPath.c_str());
+
+	Object configFile;
+	if(!configFile.loadFromXML(finalPath)) {
+		printf("Specified config file doesn't exist!\n");
+		return 0;
+	}
+
+	// start required params
+
+	String entryPoint;
+	int defaultWidth;
+	int defaultHeight;
+	int frameRate = 60;
+	int antiAliasingLevel = 0;
+	bool fullScreen = false;
+	float backgroundColorR = 0.2;
+	float backgroundColorG = 0.2;
+	float backgroundColorB = 0.2;
+
+	if(configFile.root["entryPoint"]) {
+		printf("Entry point: %s\n", configFile.root["entryPoint"]->stringVal.c_str());
+		entryPoint = configFile.root["entryPoint"]->stringVal;
+	} else {
+		printf("Required parameter: \"entryPoint\" is missing from config file!\n");
+		return 0;		
+	}
+
+	if(configFile.root["defaultWidth"]) {
+		printf("Width: %d\n", configFile.root["defaultWidth"]->intVal);
+		defaultWidth = configFile.root["defaultWidth"]->intVal;
+	} else {
+		printf("Required parameter: \"defaultWidth\" is missing from config file!\n");
+		return 0;		
+	}
+
+	if(configFile.root["defaultHeight"]) {
+		printf("Height: %d\n", configFile.root["defaultHeight"]->intVal);
+		defaultHeight = configFile.root["defaultHeight"]->intVal;
+	} else {
+		printf("Required parameter: \"defaultHeight\" is missing from config file!\n");
+		return 0;		
+	}
+
+	// start optional params
+
+	if(configFile.root["frameRate"]) {
+		printf("Frame rate: %d\n", configFile.root["frameRate"]->intVal);
+		frameRate = configFile.root["frameRate"]->intVal;
+	}
+
+	if(configFile.root["antiAliasingLevel"]) {
+		printf("Anti-aliasing level: %d\n", configFile.root["antiAliasingLevel"]->intVal);
+		antiAliasingLevel = configFile.root["antiAliasingLevel"]->intVal;
+	}
+
+	if(configFile.root["fullScreen"]) {
+		fullScreen = configFile.root["fullScreen"]->boolVal;
+		if(fullScreen) {
+			printf("Full-screen: true\n");
+		} else {
+			printf("Full-screen: false\n");
+		}
+	}
+
+	if(configFile.root["backgroundColor"]) {
+		ObjectEntry *color = configFile.root["backgroundColor"];
+		if((*color)["red"] && (*color)["green"] && (*color)["blue"]) {
+			backgroundColorR = (*color)["red"]->NumberVal;
+			backgroundColorG = (*color)["green"]->NumberVal;
+			backgroundColorB = (*color)["blue"]->NumberVal;
+			printf("Background color: %f %f %f\n", backgroundColorR, backgroundColorG, backgroundColorB);
+
+		} else {
+			printf("backgroundColor node specified, but missing all three color attributes (red,green,blue). Ignoring.\n");
+		}
+	}
+
 	zipFile z = zipOpen(getArg("--out").c_str(), 0);
 	
-	addFolderToZip(z, getArg("--project"), "");
+
+	Object runInfo;
+	runInfo.root.name = "PolycodeApp";
+	runInfo.root.addChild("entryPoint", entryPoint);
+	runInfo.root.addChild("defaultHeight", defaultHeight);
+	runInfo.root.addChild("defaultWidth", defaultWidth);
+	runInfo.root.addChild("frameRate", frameRate);
+	runInfo.root.addChild("antiAliasingLevel", antiAliasingLevel);
+	runInfo.root.addChild("fullScreen", fullScreen);
+	
+	ObjectEntry *color = runInfo.root.addChild("backgroundColor");
+	color->addChild("red", backgroundColorR);
+	color->addChild("green", backgroundColorG);
+	color->addChild("blue", backgroundColorB);
+	runInfo.saveToXML("runinfo_tmp_zzzz.polyrun");
+
+	addFileToZip(z, entryPoint, entryPoint, false);
+	addFileToZip(z, "runinfo_tmp_zzzz.polyrun", "runinfo.polyrun", true);
+
+	//addFolderToZip(z, getArg("--project"), "");
 	
 	zipClose(z, "");	
 
+	OSBasics::removeItem("runinfo_tmp_zzzz.polyrun");
+
 	return 1;
 }