Ver código fonte

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 anos atrás
pai
commit
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 void createFolder(const Polycode::String& pathString);
 		static void removeItem(const Polycode::String& pathString);
+		static time_t getFileTime(const Polycode::String& pathString);
 		
 	private:
 	

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

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

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

@@ -47,7 +47,6 @@ namespace Polycode {
 	protected:
 
 		ProgramParam addParamToProgram(GLSLProgram *program,TiXmlNode *node);		
-		void recreateGLSLProgram(GLSLProgram *prog, const String& fileName, int type);
 		GLSLProgram *createGLSLProgram(const String& fileName, int type);
 		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);
 			virtual ~Resource();
 			
+			virtual void reloadResource() {}
 			
 			const String& getResourceName() const;
 			int getResourceType() const;
@@ -56,9 +57,13 @@ namespace Polycode {
 			static const int RESOURCE_MESH = 5;
 			static const int RESOURCE_CUBEMAP = 6;				
 			
+			bool reloadOnFileModify;
+			time_t resourceFileTime;
+						
 			//@}
 			
 		protected:
+
 			
 			int type;
 			String resourcePath;

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

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

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

@@ -64,11 +64,15 @@ namespace Polycode {
 			ShaderProgram(int type);
 			virtual ~ShaderProgram();
 			
+			virtual void reloadProgram() {}
+			
 			static const int TYPE_VERT = 0;
 			static const int TYPE_FRAG = 1;		
 			
 			int type;
 			
+			void reloadResource();
+			
 			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);

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

@@ -356,6 +356,20 @@ vector<OSFileEntry> OSBasics::parseFolder(const String& pathString, bool showHid
 	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) {
 #ifdef _WINDOWS
 	 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++) {
 		updateModules[i]->Update(elapsed);
 	}
-
+	resourceManager->Update(elapsed);
 	timerManager->Update();	
 	tweenManager->Update();	
 	materialManager->Update(elapsed);		

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

@@ -26,6 +26,8 @@ THE SOFTWARE.
 #include "PolyVector2.h"
 #include "PolyColor.h"
 #include "PolyLogger.h"
+#include "PolyCoreServices.h"
+#include "PolyLogger.h"
 
 #ifdef _WINDOWS
 #include <windows.h>
@@ -55,9 +57,49 @@ extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocation;
 
 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() {
 	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() {
 	for(int i=0; i < programs.size(); 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 *prog = new GLSLProgram(type);	
-	recreateGLSLProgram(prog, fileName, type);	
+	GLSLProgram *prog = new GLSLProgram(fileName, type);	
 	programs.push_back(prog);
 	return prog;
 }

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

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

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

@@ -40,6 +40,8 @@ using namespace Polycode;
 
 ResourceManager::ResourceManager() {
 	PHYSFS_init(NULL);
+	ticksSinceCheck = 0;
+	reloadResourcesOnModify = false;
 }
 
 ResourceManager::~ResourceManager() {
@@ -63,7 +65,7 @@ void ResourceManager::parseShaders(const String& dirPath, bool recursive) {
 				
 				for(int s=0; s < shaders.size(); s++) {
 					shaders[s]->setResourceName(shaders[s]->getName());
-					resources.push_back(shaders[s]);
+					addResource(shaders[s]);
 					materialManager->addShader(shaders[s]);
 				}
 			}
@@ -89,7 +91,7 @@ void ResourceManager::parsePrograms(const String& dirPath, bool recursive) {
 			if(newProgram) {
 				newProgram->setResourceName(resourceDir[i].name);
 				newProgram->setResourcePath(resourceDir[i].fullPath);
-				resources.push_back(newProgram);					
+				addResource(newProgram);					
 			}			
 		} else {
 			if(recursive)
@@ -110,7 +112,7 @@ void ResourceManager::parseMaterials(const String& dirPath, bool recursive) {
 
 				for(int m=0; m < materials.size(); m++) {
 					materials[m]->setResourceName(materials[m]->getName());
-					resources.push_back(materials[m]);
+					addResource(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);
 							//						newMat->setResourceName(newMat->getName());
 							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) {
 	resources.push_back(resource);
+	resource->resourceFileTime = OSBasics::getFileTime(resource->getResourcePath());
 }
 
 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 {
 						t->setResourceName(basePath+"/"+resourceDir[i].name);
 					}
-					resources.push_back(t);
+					addResource(t);
 				}
 			}
 		} else {
@@ -245,6 +248,29 @@ Resource *ResourceManager::getResource(int resourceType, const String& resourceN
 	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*> result;
 	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 newParam;
 	newParam.name = name;

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

@@ -80,7 +80,8 @@ class AssetBrowser : public UIWindow {
 		~AssetBrowser();
 	
 		String getSelectedAssetPath();
-	
+		String getFullSelectedAssetPath();
+			
 		void parseFolderIntoTree(UITree *tree, OSFileEntry folder);
 
 		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->pauseOnLoseFocus = true;
 	
+	CoreServices::getInstance()->getResourceManager()->reloadResourcesOnModify = true;
+	
 	runNextFrame = false;
 	
 	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) {
-		String newFontPath = globalFrame->assetBrowser->getSelectedAssetPath();
-		newFontPath = newFontPath.replace(parentProject->getRootFolder()+"/", "");		
+		String newProgramPath = globalFrame->assetBrowser->getFullSelectedAssetPath();
 		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) {
 			newProgram->setResourceName(entry.name);
-			newProgram->setResourcePath(newFontPath);
+			newProgram->setResourcePath(newProgramPath);
 			CoreServices::getInstance()->getResourceManager()->addResource(newProgram);
 		}
 

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

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