Преглед изворни кода

Added an optional flag for resource autoreload. Added getFileTime function to OSBasics. Implemented resource reload for GLSL programs. Made the material editor flag custom shader programs to reload when changed. Refactored some shader code

Ivan Safrin пре 12 година
родитељ
комит
073af0bbef

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

@@ -76,6 +76,7 @@ class _PolyExport OSBasics : public PolyBase {
 		static bool isFolder(const Polycode::String& pathString);
 		static bool isFolder(const Polycode::String& pathString);
 		static void createFolder(const Polycode::String& pathString);
 		static void createFolder(const Polycode::String& pathString);
 		static void removeItem(const Polycode::String& pathString);
 		static void removeItem(const Polycode::String& pathString);
+		static time_t getFileTime(const Polycode::String& pathString);
 		
 		
 	private:
 	private:
 	
 	

+ 4 - 1
Core/Contents/Include/PolyGLSLProgram.h

@@ -31,10 +31,13 @@ namespace Polycode {
 
 
 	class _PolyExport GLSLProgram : public ShaderProgram {
 	class _PolyExport GLSLProgram : public ShaderProgram {
 		public:
 		public:
-			GLSLProgram(int type);
+			GLSLProgram(String fileName, int type);
 			virtual ~GLSLProgram();
 			virtual ~GLSLProgram();
 			
 			
+			void reloadProgram();
+			
 			unsigned int program;
 			unsigned int program;
+			String fileName;
 	
 	
 	};
 	};
 }
 }

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

@@ -47,7 +47,6 @@ namespace Polycode {
 	protected:
 	protected:
 
 
 		ProgramParam addParamToProgram(GLSLProgram *program,TiXmlNode *node);		
 		ProgramParam addParamToProgram(GLSLProgram *program,TiXmlNode *node);		
-		void recreateGLSLProgram(GLSLProgram *prog, const String& fileName, int type);
 		GLSLProgram *createGLSLProgram(const String& fileName, int type);
 		GLSLProgram *createGLSLProgram(const String& fileName, int type);
 		void updateGLSLParam(Renderer *renderer, GLSLShader *glslShader, ProgramParam &param, ShaderBinding *materialOptions, ShaderBinding *localOptions);			
 		void updateGLSLParam(Renderer *renderer, GLSLShader *glslShader, ProgramParam &param, ShaderBinding *materialOptions, ShaderBinding *localOptions);			
 		
 		

+ 5 - 0
Core/Contents/Include/PolyResource.h

@@ -42,6 +42,7 @@ namespace Polycode {
 			Resource(int type);
 			Resource(int type);
 			virtual ~Resource();
 			virtual ~Resource();
 			
 			
+			virtual void reloadResource() {}
 			
 			
 			const String& getResourceName() const;
 			const String& getResourceName() const;
 			int getResourceType() const;
 			int getResourceType() const;
@@ -56,9 +57,13 @@ namespace Polycode {
 			static const int RESOURCE_MESH = 5;
 			static const int RESOURCE_MESH = 5;
 			static const int RESOURCE_CUBEMAP = 6;				
 			static const int RESOURCE_CUBEMAP = 6;				
 			
 			
+			bool reloadOnFileModify;
+			time_t resourceFileTime;
+						
 			//@}
 			//@}
 			
 			
 		protected:
 		protected:
+
 			
 			
 			int type;
 			int type;
 			String resourcePath;
 			String resourcePath;

+ 9 - 0
Core/Contents/Include/PolyResourceManager.h

@@ -25,6 +25,8 @@ THE SOFTWARE.
 #include "PolyGlobals.h"
 #include "PolyGlobals.h"
 #include <vector>
 #include <vector>
 
 
+#define RESOURCE_CHECK_INTERVAL	2000
+
 namespace Polycode {
 namespace Polycode {
 
 
 	class Resource;
 	class Resource;
@@ -87,8 +89,15 @@ namespace Polycode {
 		
 		
 			void addShaderModule(PolycodeShaderModule *module);
 			void addShaderModule(PolycodeShaderModule *module);
 		
 		
+			void checkForChangedFiles();
+		
+			void Update(int elapsed);
+			
+			bool reloadResourcesOnModify;
 		
 		
 		private:
 		private:
+			int ticksSinceCheck;
+		
 			std::vector <Resource*> resources;
 			std::vector <Resource*> resources;
 			std::vector <PolycodeShaderModule*> shaderModules;
 			std::vector <PolycodeShaderModule*> shaderModules;
 	};
 	};

+ 4 - 0
Core/Contents/Include/PolyShader.h

@@ -64,11 +64,15 @@ namespace Polycode {
 			ShaderProgram(int type);
 			ShaderProgram(int type);
 			virtual ~ShaderProgram();
 			virtual ~ShaderProgram();
 			
 			
+			virtual void reloadProgram() {}
+			
 			static const int TYPE_VERT = 0;
 			static const int TYPE_VERT = 0;
 			static const int TYPE_FRAG = 1;		
 			static const int TYPE_FRAG = 1;		
 			
 			
 			int type;
 			int type;
 			
 			
+			void reloadResource();
+			
 			std::vector<ProgramParam> params;
 			std::vector<ProgramParam> params;
 			
 			
 			ProgramParam addParam(const String& name, const String& typeString, const String& valueString, bool isAuto, int autoID, int paramType, void *defaultData, void *minData, void *maxData);
 			ProgramParam addParam(const String& name, const String& typeString, const String& valueString, bool isAuto, int autoID, int paramType, void *defaultData, void *minData, void *maxData);

+ 14 - 0
Core/Contents/Source/OSBasics.cpp

@@ -356,6 +356,20 @@ vector<OSFileEntry> OSBasics::parseFolder(const String& pathString, bool showHid
 	return returnVector;
 	return returnVector;
 }
 }
 
 
+time_t OSBasics::getFileTime(const Polycode::String& pathString) {
+#ifdef _WINDOWS
+
+#else
+	struct stat statbuf;
+	int retVal = stat(pathString.c_str(), &statbuf);
+	if (retVal == 0) {
+		return statbuf.st_mtime;
+	} else {
+		return 0;
+	}
+#endif
+}
+
 void OSBasics::removeItem(const String& pathString) {
 void OSBasics::removeItem(const String& pathString) {
 #ifdef _WINDOWS
 #ifdef _WINDOWS
 	 String _tmp = pathString.replace("/", "\\");
 	 String _tmp = pathString.replace("/", "\\");

+ 1 - 1
Core/Contents/Source/PolyCoreServices.cpp

@@ -240,7 +240,7 @@ void CoreServices::Update(int elapsed) {
 	for(int i=0; i < updateModules.size(); i++) {
 	for(int i=0; i < updateModules.size(); i++) {
 		updateModules[i]->Update(elapsed);
 		updateModules[i]->Update(elapsed);
 	}
 	}
-
+	resourceManager->Update(elapsed);
 	timerManager->Update();	
 	timerManager->Update();	
 	tweenManager->Update();	
 	tweenManager->Update();	
 	materialManager->Update(elapsed);		
 	materialManager->Update(elapsed);		

+ 43 - 1
Core/Contents/Source/PolyGLSLProgram.cpp

@@ -26,6 +26,8 @@ THE SOFTWARE.
 #include "PolyVector2.h"
 #include "PolyVector2.h"
 #include "PolyColor.h"
 #include "PolyColor.h"
 #include "PolyLogger.h"
 #include "PolyLogger.h"
+#include "PolyCoreServices.h"
+#include "PolyLogger.h"
 
 
 #ifdef _WINDOWS
 #ifdef _WINDOWS
 #include <windows.h>
 #include <windows.h>
@@ -55,9 +57,49 @@ extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocation;
 
 
 using namespace Polycode;
 using namespace Polycode;
 
 
-GLSLProgram::GLSLProgram(int type) : ShaderProgram(type) {
+GLSLProgram::GLSLProgram(String fileName, int type) : ShaderProgram(type) {
+	program = -1;
+	this->fileName = fileName;
+	reloadProgram();
 }
 }
 
 
 GLSLProgram::~GLSLProgram() {
 GLSLProgram::~GLSLProgram() {
 	glDeleteShader(program);
 	glDeleteShader(program);
+}
+
+void GLSLProgram::reloadProgram() {
+	if(program != -1)
+		glDeleteShader(program);
+		
+	OSFILE *file = OSBasics::open(fileName, "r");
+	OSBasics::seek(file, 0, SEEK_END);	
+	long progsize = OSBasics::tell(file);
+	OSBasics::seek(file, 0, SEEK_SET);
+	char *buffer = (char*)malloc(progsize+1);
+	memset(buffer, 0, progsize+1);
+	OSBasics::read(buffer, progsize, 1, file);
+	OSBasics::close(file);
+	
+	if(type == GLSLProgram::TYPE_VERT) {
+		program =  glCreateShader(GL_VERTEX_SHADER);
+	} else {
+		program =  glCreateShader(GL_FRAGMENT_SHADER);
+	}
+	
+	glShaderSource(program, 1, (const GLchar**)&buffer, 0);
+	glCompileShader(program);	
+	
+	GLint compiled = true;
+    glGetShaderiv(program, GL_COMPILE_STATUS, &compiled);
+    if(!compiled) {
+        GLint length;
+        GLchar* log;
+        glGetShaderiv(program, GL_INFO_LOG_LENGTH, &length);
+        log = (GLchar*)malloc(length);
+        glGetShaderInfoLog(program, length, &length, log);
+		printf("GLSL ERROR: %s\n", log);
+		CoreServices::getInstance()->getLogger()->logBroadcast("GLSL ERROR:" + String(log));
+        free(log);
+    }	
+	free(buffer);
 }
 }

+ 2 - 41
Core/Contents/Source/PolyGLSLShaderModule.cpp

@@ -491,51 +491,12 @@ ProgramParam GLSLShaderModule::addParamToProgram(GLSLProgram *program,TiXmlNode
 void GLSLShaderModule::reloadPrograms() {
 void GLSLShaderModule::reloadPrograms() {
 	for(int i=0; i < programs.size(); i++) {
 	for(int i=0; i < programs.size(); i++) {
 		GLSLProgram *program = programs[i];
 		GLSLProgram *program = programs[i];
-		recreateGLSLProgram(program, program->getResourcePath(), program->type);	
+		program->reloadProgram();	
 	}	
 	}	
 }
 }
 
 
-void GLSLShaderModule::recreateGLSLProgram(GLSLProgram *prog, const String& fileName, int type) {
-	
-	OSFILE *file = OSBasics::open(fileName, "r");
-	OSBasics::seek(file, 0, SEEK_END);	
-	long progsize = OSBasics::tell(file);
-	OSBasics::seek(file, 0, SEEK_SET);
-	char *buffer = (char*)malloc(progsize+1);
-	memset(buffer, 0, progsize+1);
-	OSBasics::read(buffer, progsize, 1, file);
-	OSBasics::close(file);
-	
-	if(type == GLSLProgram::TYPE_VERT) {
-		prog->program =  glCreateShader(GL_VERTEX_SHADER);
-	} else {
-		prog->program =  glCreateShader(GL_FRAGMENT_SHADER);
-	}
-	
-	glShaderSource(prog->program, 1, (const GLchar**)&buffer, 0);
-	glCompileShader(prog->program);	
-	
-	GLint compiled = true;
-    glGetShaderiv(prog->program, GL_COMPILE_STATUS, &compiled);
-    if(!compiled) {
-        GLint length;
-        GLchar* log;
-        glGetShaderiv(prog->program, GL_INFO_LOG_LENGTH, &length);
-        log = (GLchar*)malloc(length);
-        glGetShaderInfoLog(prog->program, length, &length, log);
-		printf("GLSL ERROR: %s\n", log);
-		CoreServices::getInstance()->getLogger()->logBroadcast("GLSL ERROR:" + String(log));
-        free(log);
-    }		
-		
-	
-	free(buffer);		
-	
-}
-
 GLSLProgram *GLSLShaderModule::createGLSLProgram(const String& fileName, int type) {
 GLSLProgram *GLSLShaderModule::createGLSLProgram(const String& fileName, int type) {
-	GLSLProgram *prog = new GLSLProgram(type);	
-	recreateGLSLProgram(prog, fileName, type);	
+	GLSLProgram *prog = new GLSLProgram(fileName, type);	
 	programs.push_back(prog);
 	programs.push_back(prog);
 	return prog;
 	return prog;
 }
 }

+ 2 - 0
Core/Contents/Source/PolyResource.cpp

@@ -26,6 +26,8 @@ using namespace Polycode;
 
 
 Resource::Resource(int type) {
 Resource::Resource(int type) {
 	this->type = type;
 	this->type = type;
+	reloadOnFileModify = false;
+	resourceFileTime = 0;
 }
 }
 
 
 Resource::~Resource() {
 Resource::~Resource() {

+ 31 - 5
Core/Contents/Source/PolyResourceManager.cpp

@@ -40,6 +40,8 @@ using namespace Polycode;
 
 
 ResourceManager::ResourceManager() {
 ResourceManager::ResourceManager() {
 	PHYSFS_init(NULL);
 	PHYSFS_init(NULL);
+	ticksSinceCheck = 0;
+	reloadResourcesOnModify = false;
 }
 }
 
 
 ResourceManager::~ResourceManager() {
 ResourceManager::~ResourceManager() {
@@ -63,7 +65,7 @@ void ResourceManager::parseShaders(const String& dirPath, bool recursive) {
 				
 				
 				for(int s=0; s < shaders.size(); s++) {
 				for(int s=0; s < shaders.size(); s++) {
 					shaders[s]->setResourceName(shaders[s]->getName());
 					shaders[s]->setResourceName(shaders[s]->getName());
-					resources.push_back(shaders[s]);
+					addResource(shaders[s]);
 					materialManager->addShader(shaders[s]);
 					materialManager->addShader(shaders[s]);
 				}
 				}
 			}
 			}
@@ -89,7 +91,7 @@ void ResourceManager::parsePrograms(const String& dirPath, bool recursive) {
 			if(newProgram) {
 			if(newProgram) {
 				newProgram->setResourceName(resourceDir[i].name);
 				newProgram->setResourceName(resourceDir[i].name);
 				newProgram->setResourcePath(resourceDir[i].fullPath);
 				newProgram->setResourcePath(resourceDir[i].fullPath);
-				resources.push_back(newProgram);					
+				addResource(newProgram);					
 			}			
 			}			
 		} else {
 		} else {
 			if(recursive)
 			if(recursive)
@@ -110,7 +112,7 @@ void ResourceManager::parseMaterials(const String& dirPath, bool recursive) {
 
 
 				for(int m=0; m < materials.size(); m++) {
 				for(int m=0; m < materials.size(); m++) {
 					materials[m]->setResourceName(materials[m]->getName());
 					materials[m]->setResourceName(materials[m]->getName());
-					resources.push_back(materials[m]);
+					addResource(materials[m]);
 					materialManager->addMaterial(materials[m]);
 					materialManager->addMaterial(materials[m]);
 				}
 				}
 			}
 			}
@@ -142,7 +144,7 @@ void ResourceManager::parseCubemaps(const String& dirPath, bool recursive) {
 							Cubemap *newMat = CoreServices::getInstance()->getMaterialManager()->cubemapFromXMLNode(pChild);
 							Cubemap *newMat = CoreServices::getInstance()->getMaterialManager()->cubemapFromXMLNode(pChild);
 							//						newMat->setResourceName(newMat->getName());
 							//						newMat->setResourceName(newMat->getName());
 							if(newMat)
 							if(newMat)
-								resources.push_back(newMat);
+								addResource(newMat);
 						}
 						}
 					}
 					}
 				}
 				}
@@ -156,6 +158,7 @@ void ResourceManager::parseCubemaps(const String& dirPath, bool recursive) {
 
 
 void ResourceManager::addResource(Resource *resource) {
 void ResourceManager::addResource(Resource *resource) {
 	resources.push_back(resource);
 	resources.push_back(resource);
+	resource->resourceFileTime = OSBasics::getFileTime(resource->getResourcePath());
 }
 }
 
 
 void ResourceManager::parseTextures(const String& dirPath, bool recursive, const String& basePath) {
 void ResourceManager::parseTextures(const String& dirPath, bool recursive, const String& basePath) {
@@ -173,7 +176,7 @@ void ResourceManager::parseTextures(const String& dirPath, bool recursive, const
 					} else {
 					} else {
 						t->setResourceName(basePath+"/"+resourceDir[i].name);
 						t->setResourceName(basePath+"/"+resourceDir[i].name);
 					}
 					}
-					resources.push_back(t);
+					addResource(t);
 				}
 				}
 			}
 			}
 		} else {
 		} else {
@@ -245,6 +248,29 @@ Resource *ResourceManager::getResource(int resourceType, const String& resourceN
 	return NULL;
 	return NULL;
 }
 }
 
 
+void ResourceManager::checkForChangedFiles() {
+	for(int i=0; i < resources.size(); i++) {
+		if(resources[i]->reloadOnFileModify == true) {
+			time_t newFileTime = OSBasics::getFileTime(resources[i]->getResourcePath());
+			if(newFileTime != resources[i]->resourceFileTime) {
+				resources[i]->reloadResource();
+				resources[i]->resourceFileTime = newFileTime;
+			}
+		}
+	}
+}
+
+void ResourceManager::Update(int elapsed) {
+	if(!reloadResourcesOnModify)
+		return;
+		
+	ticksSinceCheck += elapsed;
+	if(ticksSinceCheck > RESOURCE_CHECK_INTERVAL) {
+		ticksSinceCheck = 0;
+		checkForChangedFiles();
+	}
+}
+
 std::vector<Resource*> ResourceManager::getResources(int resourceType) {
 std::vector<Resource*> ResourceManager::getResources(int resourceType) {
 	std::vector<Resource*> result;
 	std::vector<Resource*> result;
 	for(int i =0; i < resources.size(); i++) {
 	for(int i =0; i < resources.size(); i++) {

+ 4 - 0
Core/Contents/Source/PolyShader.cpp

@@ -32,6 +32,10 @@ ShaderProgram::~ShaderProgram() {
 
 
 }
 }
 
 
+void ShaderProgram::reloadResource() {
+	reloadProgram();
+}
+
 ProgramParam ShaderProgram::addParam(const String& name, const String& typeString, const String& valueString, bool isAuto, int autoID, int paramType, void *defaultData, void *minData, void *maxData) {
 ProgramParam ShaderProgram::addParam(const String& name, const String& typeString, const String& valueString, bool isAuto, int autoID, int paramType, void *defaultData, void *minData, void *maxData) {
 	ProgramParam newParam;
 	ProgramParam newParam;
 	newParam.name = name;
 	newParam.name = name;

+ 2 - 1
IDE/Contents/Include/TextureBrowser.h

@@ -80,7 +80,8 @@ class AssetBrowser : public UIWindow {
 		~AssetBrowser();
 		~AssetBrowser();
 	
 	
 		String getSelectedAssetPath();
 		String getSelectedAssetPath();
-	
+		String getFullSelectedAssetPath();
+			
 		void parseFolderIntoTree(UITree *tree, OSFileEntry folder);
 		void parseFolderIntoTree(UITree *tree, OSFileEntry folder);
 
 
 		String getTemplatePath();
 		String getTemplatePath();

+ 2 - 0
IDE/Contents/Source/PolycodeIDEApp.cpp

@@ -34,6 +34,8 @@ PolycodeIDEApp::PolycodeIDEApp(PolycodeView *view) : EventDispatcher() {
 	core = new POLYCODE_CORE(view, 900,700,false,true, 0, 0,30, -1);	
 	core = new POLYCODE_CORE(view, 900,700,false,true, 0, 0,30, -1);	
 //	core->pauseOnLoseFocus = true;
 //	core->pauseOnLoseFocus = true;
 	
 	
+	CoreServices::getInstance()->getResourceManager()->reloadResourcesOnModify = true;
+	
 	runNextFrame = false;
 	runNextFrame = false;
 	
 	
 	core->addEventListener(this, Core::EVENT_CORE_RESIZE);
 	core->addEventListener(this, Core::EVENT_CORE_RESIZE);

+ 5 - 5
IDE/Contents/Source/PolycodeMaterialEditor.cpp

@@ -140,16 +140,16 @@ void ShaderEditorPane::handleEvent(Event *event) {
 	}
 	}
 	
 	
 	if(event->getDispatcher() == globalFrame->assetBrowser && event->getEventType() == "UIEvent" && event->getEventCode() == UIEvent::OK_EVENT) {
 	if(event->getDispatcher() == globalFrame->assetBrowser && event->getEventType() == "UIEvent" && event->getEventCode() == UIEvent::OK_EVENT) {
-		String newFontPath = globalFrame->assetBrowser->getSelectedAssetPath();
-		newFontPath = newFontPath.replace(parentProject->getRootFolder()+"/", "");		
+		String newProgramPath = globalFrame->assetBrowser->getFullSelectedAssetPath();
 		globalFrame->assetBrowser->removeAllHandlersForListener(this);
 		globalFrame->assetBrowser->removeAllHandlersForListener(this);
 		
 		
 
 
-		OSFileEntry entry(newFontPath, OSFileEntry::TYPE_FILE);
-		ShaderProgram *newProgram = CoreServices::getInstance()->getMaterialManager()->createProgramFromFile(newFontPath);
+		OSFileEntry entry(newProgramPath, OSFileEntry::TYPE_FILE);
+		ShaderProgram *newProgram = CoreServices::getInstance()->getMaterialManager()->createProgramFromFile(newProgramPath);
+		newProgram->reloadOnFileModify = true;
 		if(newProgram) {
 		if(newProgram) {
 			newProgram->setResourceName(entry.name);
 			newProgram->setResourceName(entry.name);
-			newProgram->setResourcePath(newFontPath);
+			newProgram->setResourcePath(newProgramPath);
 			CoreServices::getInstance()->getResourceManager()->addResource(newProgram);
 			CoreServices::getInstance()->getResourceManager()->addResource(newProgram);
 		}
 		}
 
 

+ 4 - 0
IDE/Contents/Source/TextureBrowser.cpp

@@ -242,6 +242,10 @@ String AssetBrowser::getTemplatePath() {
 	return templatePath;
 	return templatePath;
 }
 }
 
 
+String AssetBrowser::getFullSelectedAssetPath() {
+	return assetList->selectedPath;
+}
+
 String AssetBrowser::getSelectedAssetPath() {
 String AssetBrowser::getSelectedAssetPath() {
 	return assetList->selectedPath.replace(currentProject->getRootFolder()+"/", "");
 	return assetList->selectedPath.replace(currentProject->getRootFolder()+"/", "");
 }
 }