Bläddra i källkod

Added mesh viewer to IDE, added support for resource change events in ResourceManager, added tangents to the mesh file specification (ATTN: old mesh files will need to be re-exported), added support for tangent generation in polyimport, added global version string to PolyGlobals.h, fixed clear color setting in virtual scenes, made Label textures always be POT, added global IDE texture filtering options to the IDE preferences.

Ivan Safrin 12 år sedan
förälder
incheckning
d8d788f480
35 ändrade filer med 580 tillägg och 59 borttagningar
  1. 2 1
      Core/Contents/Include/PolyEvent.h
  2. 2 0
      Core/Contents/Include/PolyGlobals.h
  3. 6 2
      Core/Contents/Include/PolyResourceManager.h
  4. 3 1
      Core/Contents/Include/PolySceneLabel.h
  5. 1 0
      Core/Contents/Source/PolyGLRenderer.cpp
  6. 2 2
      Core/Contents/Source/PolyLabel.cpp
  7. 1 0
      Core/Contents/Source/PolyMaterial.cpp
  8. 3 0
      Core/Contents/Source/PolyMaterialManager.cpp
  9. 11 4
      Core/Contents/Source/PolyMesh.cpp
  10. 12 1
      Core/Contents/Source/PolyResourceManager.cpp
  11. 4 2
      Core/Contents/Source/PolyScene.cpp
  12. 10 3
      Core/Contents/Source/PolySceneLabel.cpp
  13. 1 2
      Core/Contents/Source/PolySceneManager.cpp
  14. 6 0
      IDE/Build/Mac OS X/Polycode.xcodeproj/project.pbxproj
  15. 1 1
      IDE/Contents/Include/PolycodeFrame.h
  16. 1 0
      IDE/Contents/Include/PolycodeIDEApp.h
  17. 75 0
      IDE/Contents/Include/PolycodeMeshEditor.h
  18. 55 0
      IDE/Contents/Include/PolycodeSoundEditor.h
  19. 1 1
      IDE/Contents/Include/PolycodeTextEditor.h
  20. 1 0
      IDE/Contents/Include/SettingsWindow.h
  21. BIN
      IDE/Contents/Resources/Images/editorGrid.png
  22. 31 12
      IDE/Contents/Source/PolycodeIDEApp.cpp
  23. 2 0
      IDE/Contents/Source/PolycodeMaterialEditor.cpp
  24. 208 0
      IDE/Contents/Source/PolycodeMeshEditor.cpp
  25. 93 0
      IDE/Contents/Source/PolycodeSoundEditor.cpp
  26. 18 1
      IDE/Contents/Source/SettingsWindow.cpp
  27. 1 4
      Modules/Contents/UI/Include/PolyUIElement.h
  28. 1 1
      Modules/Contents/UI/Include/PolyUIImageButton.h
  29. 1 1
      Modules/Contents/UI/Include/PolyUITree.h
  30. 2 2
      Modules/Contents/UI/Source/PolyUIColorBox.cpp
  31. 4 12
      Modules/Contents/UI/Source/PolyUIElement.cpp
  32. 1 1
      Modules/Contents/UI/Source/PolyUIHSlider.cpp
  33. 3 1
      Modules/Contents/UI/Source/PolyUIImageButton.cpp
  34. 1 1
      Modules/Contents/UI/Source/PolyUITree.cpp
  35. 16 3
      Tools/Contents/polyimport/Source/polyimport.cpp

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

@@ -86,7 +86,8 @@ namespace Polycode {
 			static const int RESOURCE_RELOAD_EVENT = EVENTBASE_EVENT+5;
 			static const int SELECT_EVENT = EVENTBASE_EVENT+6;
 			static const int REMOVE_EVENT = EVENTBASE_EVENT+7;
-															
+			static const int RESOURCE_CHANGE_EVENT = EVENTBASE_EVENT+8;
+																		
 			static const int EVENTBASE_NONPOLYCODE = 0x10000;
 		
 			bool deleteOnDispatch;

+ 2 - 0
Core/Contents/Include/PolyGlobals.h

@@ -27,6 +27,8 @@ THE SOFTWARE.
 // Compile support for lua bindings.
 //#define _COMPILE_LUA
 
+#define POLYCODE_VERSION_STRING "0.8.3"
+
 #define COMPILE_GL_RENDERER
 
 #ifdef _WINDOWS

+ 6 - 2
Core/Contents/Include/PolyResourceManager.h

@@ -23,6 +23,7 @@ THE SOFTWARE.
 
 #pragma once
 #include "PolyGlobals.h"
+#include "PolyEventDispatcher.h"
 #include <vector>
 
 #define RESOURCE_CHECK_INTERVAL	2000
@@ -36,7 +37,7 @@ namespace Polycode {
 	/**
 	* Manages loading and unloading of resources from directories and archives. Should only be accessed via the CoreServices singleton. 
 	*/ 
-	class _PolyExport ResourceManager : public PolyBase {
+	class _PolyExport ResourceManager : public EventDispatcher {
 		public:
 			ResourceManager();
 			~ResourceManager();
@@ -108,7 +109,10 @@ namespace Polycode {
 		
 			void Update(int elapsed);
 			
-			bool reloadResourcesOnModify;
+			bool reloadResourcesOnModify;			
+			bool dispatchChangeEvents;
+			
+			void handleEvent(Event *event);
 		
 		private:
 			int ticksSinceCheck;

+ 3 - 1
Core/Contents/Include/PolySceneLabel.h

@@ -69,7 +69,9 @@ namespace Polycode {
 			
 			static Vector3 defaultAnchor;
 			static bool defaultPositionAtBaseline;
-			
+			static bool defaultSnapToPixels;
+			static bool createMipmapsForLabels;
+						
 		protected:
 			
 			void updateFromLabel();

+ 1 - 0
Core/Contents/Source/PolyGLRenderer.cpp

@@ -733,6 +733,7 @@ void OpenGLRenderer::destroyTexture(Texture *texture) {
 }
 
 void OpenGLRenderer::clearScreen() {
+	glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 }
 

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

@@ -419,14 +419,14 @@ void Label::setText(const String& text) {
 	
 	unsigned int textWidth = (bbox.xMax -  bbox.xMin)+1;
 	unsigned int textHeight = (bbox.yMax -  bbox.yMin)+1;
-/*	
+
 	if(textWidth % 2 ){
 		textWidth++;
 	}
 	if(textHeight % 2 ){
 		textHeight++;
 	}
-*/	
+
 	baseLineOffset = bbox.yMin;
 	xAdjustOffset = bbox.xMin;
 	baseLineAdjust = bbox.yMax;

+ 1 - 0
Core/Contents/Source/PolyMaterial.cpp

@@ -47,6 +47,7 @@ Material::~Material() {
 
 void Material::setName(const String &name) {
 	this->name = name;
+	dispatchEvent(new Event(), Event::RESOURCE_CHANGE_EVENT);	
 }
 
 void Material::clearShaders() {

+ 3 - 0
Core/Contents/Source/PolyMaterialManager.cpp

@@ -381,6 +381,7 @@ std::vector<Material*> MaterialManager::loadMaterialsFromFile(String fileName) {
 
 Material *MaterialManager::createMaterial(String materialName, String shaderName) {
 	Material *newMaterial = new Material(materialName);
+	newMaterial->setResourceName(materialName);
 	
 	Shader *retShader = (Shader*)CoreServices::getInstance()->getResourceManager()->getResource(Resource::RESOURCE_SHADER, shaderName);
 	
@@ -407,6 +408,8 @@ Material *MaterialManager::materialFromXMLNode(TiXmlNode *node) {
 
 	Material *newMaterial = new Material(mname);
 	
+	newMaterial->setResourceName(mname);
+	
 	if(nodeElement->Attribute("screen")) {
 		if(String(nodeElement->Attribute("screen")) == "true") {
 			newMaterial->screenMaterial = true;

+ 11 - 4
Core/Contents/Source/PolyMesh.cpp

@@ -116,6 +116,7 @@ namespace Polycode {
 			
 			Vector3_struct pos;
 			Vector3_struct nor;
+			Vector3_struct tan;			
 			Vector4_struct col;			
 			Vector2_struct tex;
 			
@@ -129,6 +130,10 @@ namespace Polycode {
 				nor.y =  polygons[i]->getVertex(j)->normal.y;
 				nor.z =  polygons[i]->getVertex(j)->normal.z;
 
+				tan.x =  polygons[i]->getVertex(j)->tangent.x;
+				tan.y =  polygons[i]->getVertex(j)->tangent.y;
+				tan.z =  polygons[i]->getVertex(j)->tangent.z;
+
 				col.x =  polygons[i]->getVertex(j)->vertexColor.r;
 				col.y =  polygons[i]->getVertex(j)->vertexColor.g;
 				col.z =  polygons[i]->getVertex(j)->vertexColor.b;
@@ -139,6 +144,7 @@ namespace Polycode {
 				
 				OSBasics::write(&pos, sizeof(Vector3_struct), 1, outFile);
 				OSBasics::write(&nor, sizeof(Vector3_struct), 1, outFile);
+				OSBasics::write(&tan, sizeof(Vector3_struct), 1, outFile);				
 				OSBasics::write(&col, sizeof(Vector4_struct), 1, outFile);				
 				OSBasics::write(&tex, sizeof(Vector2_struct), 1, outFile);								
 				
@@ -181,6 +187,7 @@ namespace Polycode {
 		
 		Vector3_struct pos;
 		Vector3_struct nor;
+		Vector3_struct tan;
 		Vector4_struct col;			
 		Vector2_struct tex;
 		
@@ -190,11 +197,13 @@ namespace Polycode {
 			for(int j=0; j < verticesPerFace; j++) {
 				OSBasics::read(&pos, sizeof(Vector3_struct), 1, inFile);
 				OSBasics::read(&nor, sizeof(Vector3_struct), 1, inFile);
+				OSBasics::read(&tan, sizeof(Vector3_struct), 1, inFile);				
 				OSBasics::read(&col, sizeof(Vector4_struct), 1, inFile);						
 				OSBasics::read(&tex, sizeof(Vector2_struct), 1, inFile);						
 				
 				Vertex *vertex = new Vertex(pos.x, pos.y, pos.z);
 				vertex->setNormal(nor.x,nor.y, nor.z);
+				vertex->tangent = Vector3(tan.x, tan.y, tan.z);
 				vertex->restNormal.set(nor.x,nor.y, nor.z);
 				vertex->vertexColor.setColor(col.x,col.y, col.z, col.w);
 				vertex->setTexCoord(tex.x, tex.y);
@@ -226,8 +235,6 @@ namespace Polycode {
 			addPolygon(poly);
 		}
 		
-		calculateTangents();
-		
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;
@@ -758,7 +765,7 @@ namespace Polycode {
 		for(int i =0; i < polygons.size(); i++) {
 			polygons[i]->calculateTangent();
 		}		
-		/*
+
 		for(int i=0; i < polygons.size(); i++) {
 			for(int j=0; j < polygons[i]->getVertexCount(); j++) {		
 				Vertex *v =  polygons[i]->getVertex(j);
@@ -776,7 +783,7 @@ namespace Polycode {
 				v->tangent = tangent;
 			}
 		}		
-		*/
+
 		arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;		
 	}
 	

+ 12 - 1
Core/Contents/Source/PolyResourceManager.cpp

@@ -38,10 +38,11 @@
 using std::vector;
 using namespace Polycode;
 
-ResourceManager::ResourceManager() {
+ResourceManager::ResourceManager() : EventDispatcher() {
 	PHYSFS_init(NULL);
 	ticksSinceCheck = 0;
 	reloadResourcesOnModify = false;
+	dispatchChangeEvents = false;
 }
 
 ResourceManager::~ResourceManager() {
@@ -169,8 +170,18 @@ bool ResourceManager::hasResource(Resource *resource) {
 }
 
 void ResourceManager::addResource(Resource *resource) {
+	resource->addEventListener(this, Event::RESOURCE_CHANGE_EVENT);
 	resources.push_back(resource);
 	resource->resourceFileTime = OSBasics::getFileTime(resource->getResourcePath());
+	if(dispatchChangeEvents) {
+		dispatchEvent(new Event(), Event::CHANGE_EVENT);
+	}
+}
+
+void ResourceManager::handleEvent(Event *event) {
+	if(event->getEventCode() == Event::RESOURCE_CHANGE_EVENT) {
+		dispatchEvent(new Event(), Event::CHANGE_EVENT);	
+	}
 }
 
 void ResourceManager::removeResource(Resource *resource) {

+ 4 - 2
Core/Contents/Source/PolyScene.cpp

@@ -179,8 +179,10 @@ void Scene::Render(Camera *targetCamera) {
 	
 	targetCamera->rebuildTransformMatrix();
 		
-	if(useClearColor)
-		CoreServices::getInstance()->getRenderer()->setClearColor(clearColor.r,clearColor.g,clearColor.b);	
+	if(useClearColor) {
+		CoreServices::getInstance()->getRenderer()->setClearColor(clearColor.r,clearColor.g,clearColor.b, clearColor.a);	
+		CoreServices::getInstance()->getRenderer()->clearScreen();		
+	}
 	
 	CoreServices::getInstance()->getRenderer()->setAmbientColor(ambientColor.r,ambientColor.g,ambientColor.b);		
 	

+ 10 - 3
Core/Contents/Source/PolySceneLabel.cpp

@@ -33,6 +33,8 @@ using namespace Polycode;
 
 Vector3 SceneLabel::defaultAnchor = Vector3();
 bool SceneLabel::defaultPositionAtBaseline = false;
+bool SceneLabel::defaultSnapToPixels = false;
+bool SceneLabel::createMipmapsForLabels = true;
 
 SceneLabel::SceneLabel(const String& fontName, const String& text, int size, Number scale, int amode, bool premultiplyAlpha) : ScenePrimitive(ScenePrimitive::TYPE_VPLANE, 1, 1) {
 	label = new Label(CoreServices::getInstance()->getFontManager()->getFontByName(fontName), text, size, amode, premultiplyAlpha);
@@ -40,6 +42,7 @@ SceneLabel::SceneLabel(const String& fontName, const String& text, int size, Num
 	positionAtBaseline = SceneLabel::defaultPositionAtBaseline;
 	setAnchorPoint(SceneLabel::defaultAnchor);
 	updateFromLabel();
+	snapToPixels = SceneLabel::defaultSnapToPixels;
 }
 
 SceneLabel::SceneLabel(const String& text, int size, const String& fontName, int amode, bool premultiplyAlpha) : ScenePrimitive(ScenePrimitive::TYPE_VPLANE, 1, 1){
@@ -48,6 +51,7 @@ SceneLabel::SceneLabel(const String& text, int size, const String& fontName, int
 	this->labelScale = 1.0;
 	positionAtBaseline = SceneLabel::defaultPositionAtBaseline;
 	setAnchorPoint(SceneLabel::defaultAnchor);	
+	snapToPixels = SceneLabel::defaultSnapToPixels;	
 	updateFromLabel();
 }
 			
@@ -69,7 +73,11 @@ void SceneLabel::updateFromLabel() {
 	if(texture)
 		materialManager->deleteTexture(texture);
 
-	texture = materialManager->createTextureFromImage(label, materialManager->clampDefault, materialManager->mipmapsDefault);
+	if(SceneLabel::createMipmapsForLabels) {
+		texture = materialManager->createTextureFromImage(label, materialManager->clampDefault, materialManager->mipmapsDefault);	
+	} else {
+		texture = materialManager->createTextureFromImage(label, materialManager->clampDefault, false);		
+	}
 
 	if(material) {
 		localShaderOptions->clearTexture("diffuse");
@@ -86,8 +94,7 @@ void SceneLabel::updateFromLabel() {
 	if(useVertexBuffer)
 		CoreServices::getInstance()->getRenderer()->createVertexBufferForMesh(mesh);
 	
-	// TODO: resize it here
-	
+	// TODO: resize it here	
 	bBoxRadius = label->getWidth()*labelScale;
 }
 

+ 1 - 2
Core/Contents/Source/PolySceneManager.cpp

@@ -91,11 +91,10 @@ void SceneManager::renderVirtual() {
 			}
 		}
 			
-		renderer->clearScreen();
 		renderer->loadIdentity();
 	}
 	renderer->setViewportSize(renderer->getXRes(), renderer->getYRes());
-
+	renderer->clearScreen();
 }
 
 void SceneManager::Render() {

+ 6 - 0
IDE/Build/Mac OS X/Polycode.xcodeproj/project.pbxproj

@@ -11,6 +11,7 @@
 		256AC3DA0F4B6AC300CF3369 /* PolycodeAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 256AC3D90F4B6AC300CF3369 /* PolycodeAppDelegate.m */; };
 		6D06CCF314BC203800E4CB4C /* libPolycore_d.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D06CCF214BC203800E4CB4C /* libPolycore_d.a */; };
 		6D06CCF514BC204200E4CB4C /* libPolycodeUI_d.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D06CCF414BC204200E4CB4C /* libPolycodeUI_d.a */; };
+		6D0F6B6218170C1000C5327F /* PolycodeMeshEditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D0F6B6118170C1000C5327F /* PolycodeMeshEditor.cpp */; };
 		6D128ABD174A9940007B0375 /* SettingsWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D128ABC174A9940007B0375 /* SettingsWindow.cpp */; };
 		6D1CD96B164D9568006CDAB1 /* polycode_project.icns in Resources */ = {isa = PBXBuildFile; fileRef = 6D1CD96A164D9568006CDAB1 /* polycode_project.icns */; };
 		6D2AC99B14B8500400BB63DA /* PolycodeProjectEditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2AC99A14B8500400BB63DA /* PolycodeProjectEditor.cpp */; };
@@ -81,6 +82,8 @@
 		29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
 		6D06CCF214BC203800E4CB4C /* libPolycore_d.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libPolycore_d.a; path = ../../../Release/Darwin/Framework/Core/lib/libPolycore_d.a; sourceTree = "<group>"; };
 		6D06CCF414BC204200E4CB4C /* libPolycodeUI_d.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libPolycodeUI_d.a; path = ../../../Release/Darwin/Framework/Modules/lib/libPolycodeUI_d.a; sourceTree = "<group>"; };
+		6D0F6B5F18170C0400C5327F /* PolycodeMeshEditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolycodeMeshEditor.h; sourceTree = "<group>"; };
+		6D0F6B6118170C1000C5327F /* PolycodeMeshEditor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolycodeMeshEditor.cpp; sourceTree = "<group>"; };
 		6D128ABA174A9936007B0375 /* SettingsWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsWindow.h; sourceTree = "<group>"; };
 		6D128ABC174A9940007B0375 /* SettingsWindow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingsWindow.cpp; sourceTree = "<group>"; };
 		6D1CD96A164D9568006CDAB1 /* polycode_project.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = polycode_project.icns; path = ../../../Assets/Icons/polycode_project.icns; sourceTree = "<group>"; };
@@ -274,6 +277,7 @@
 		6D80E91212AB53FB0037A708 /* Include */ = {
 			isa = PBXGroup;
 			children = (
+				6D0F6B5F18170C0400C5327F /* PolycodeMeshEditor.h */,
 				6D8A845A16F593C800F3BA08 /* PolycodeClipboard.h */,
 				6DC67A561656F699004FD1EF /* TextureBrowser.h */,
 				6DC8257B16485726006AFC03 /* ExportProjectWindow.h */,
@@ -308,6 +312,7 @@
 		6D80E91812AB53FB0037A708 /* Source */ = {
 			isa = PBXGroup;
 			children = (
+				6D0F6B6118170C1000C5327F /* PolycodeMeshEditor.cpp */,
 				6D128ABC174A9940007B0375 /* SettingsWindow.cpp */,
 				6D8A845C16F593D000F3BA08 /* PolycodeClipboard.cpp */,
 				6DC67A531656F693004FD1EF /* TextureBrowser.cpp */,
@@ -450,6 +455,7 @@
 				6D797333167F0EB100646407 /* PolycodeProps.cpp in Sources */,
 				6D8A845D16F593D000F3BA08 /* PolycodeClipboard.cpp in Sources */,
 				6D128ABD174A9940007B0375 /* SettingsWindow.cpp in Sources */,
+				6D0F6B6218170C1000C5327F /* PolycodeMeshEditor.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 1 - 1
IDE/Contents/Include/PolycodeFrame.h

@@ -103,7 +103,7 @@ class EditCurve : public UIElement {
 		EditPoint *pointToRemove;
 		UIElement *pointsBase;
 		vector<EditPoint*> points;
-		
+
 		unsigned int mode;
 };
 

+ 1 - 0
IDE/Contents/Include/PolycodeIDEApp.h

@@ -40,6 +40,7 @@
 #include "PolycodeTextEditor.h"
 #include "PolycodeProjectEditor.h"
 #include "PolycodeSpriteEditor.h"
+#include "PolycodeMeshEditor.h"
 
 #include "PolycodeToolLauncher.h"
 

+ 75 - 0
IDE/Contents/Include/PolycodeMeshEditor.h

@@ -0,0 +1,75 @@
+/*
+ Copyright (C) 2012 by Ivan Safrin
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+ 
+#pragma once
+
+#include "PolycodeEditor.h"
+#include "PolyUIElement.h"
+#include "PolycodeUI.h"
+#include <Polycode.h>
+
+using namespace Polycode;
+
+class PolycodeMeshEditor : public PolycodeEditor {
+	public:
+	
+		PolycodeMeshEditor();
+		virtual ~PolycodeMeshEditor();
+	
+		void handleEvent(Event *event);
+	
+		void reloadMaterials();
+	
+		bool openFile(OSFileEntry filePath);
+		void Resize(int x, int y);
+	
+	protected:
+	
+		Scene *previewScene;
+		SceneLight *mainLight;
+		SceneLight *secondLight;		
+		SceneRenderTexture *renderTexture;
+		UIRect *previewShape;
+		UIRect *bgShape;		
+		SceneMesh *previewMesh;
+		Entity *previewBase;
+		
+		Material *currentMaterial;
+		
+		bool rotating;
+		Vector2 baseMousePosition;		
+		
+		UIComboBox *materialDropDown;
+		UIRect *headerBg;
+		
+		UIHSlider *lightsSlider;
+		
+		Vector3 baseModelPosition;
+		Number baseYaw;
+		Number basePitch;
+};
+
+class PolycodeMeshEditorFactory : public PolycodeEditorFactory {
+	public:
+		PolycodeMeshEditorFactory() : PolycodeEditorFactory() { extensions.push_back("mesh"); }
+		PolycodeEditor *createEditor() { return new PolycodeMeshEditor(); }
+};

+ 55 - 0
IDE/Contents/Include/PolycodeSoundEditor.h

@@ -0,0 +1,55 @@
+/*
+ Copyright (C) 2012 by Ivan Safrin
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+ 
+#pragma once
+
+#include "PolycodeEditor.h"
+#include "PolyUIElement.h"
+#include <Polycode.h>
+
+using namespace Polycode;
+
+class PolycodeImageEditor : public PolycodeEditor {
+	public:
+	PolycodeImageEditor();
+	virtual ~PolycodeImageEditor();
+	
+	bool openFile(OSFileEntry filePath);
+	void Resize(int x, int y);
+	
+	protected:
+	
+		UIRect *editorImage;
+		
+		UIRect *leftShape;		
+		UIRect *rightShape;		
+		UIRect *topShape;		
+		UIRect *bottomShape;								
+		
+		Number aspectRatio;
+};
+
+class PolycodeImageEditorFactory : public PolycodeEditorFactory {
+	public:
+		PolycodeImageEditorFactory() : PolycodeEditorFactory() { extensions.push_back("png"); }
+		PolycodeEditor *createEditor() { return new PolycodeImageEditor(); }
+};

+ 1 - 1
IDE/Contents/Include/PolycodeTextEditor.h

@@ -76,7 +76,7 @@ class PolycodeSyntaxHighlighter : public UITextInputSyntaxHighlighter {
 		static const int MODE_GLSL = 1;
 						
 	protected:
-	
+
 		int mode;
 	
 		std::vector<char> separators;

+ 1 - 0
IDE/Contents/Include/SettingsWindow.h

@@ -46,6 +46,7 @@ class SettingsWindow : public UIWindow {
 		UIButton *browseButton;
 		UIComboBox *syntaxThemeBox;
 		UIComboBox *uiThemeBox;
+		UIComboBox *textureFilteringBox;
 		
 		UIButton *cancelButton;
 		UIButton *okButton;

BIN
IDE/Contents/Resources/Images/editorGrid.png


+ 31 - 12
IDE/Contents/Source/PolycodeIDEApp.cpp

@@ -61,8 +61,8 @@ PolycodeIDEApp::PolycodeIDEApp(PolycodeView *view) : EventDispatcher() {
 	CoreServices::getInstance()->getFontManager()->registerFont("section", "Fonts/RobotoCondensed-Bold.ttf");
 
 
-//	CoreServices::getInstance()->getRenderer()->setTextureFilteringMode(Renderer::TEX_FILTERING_LINEAR);
-	CoreServices::getInstance()->getRenderer()->setTextureFilteringMode(Renderer::TEX_FILTERING_NEAREST);
+	CoreServices::getInstance()->getRenderer()->setTextureFilteringMode(Renderer::TEX_FILTERING_LINEAR);
+//	CoreServices::getInstance()->getRenderer()->setTextureFilteringMode(Renderer::TEX_FILTERING_NEAREST);
 	
 	loadConfigFile();	
 
@@ -71,15 +71,14 @@ PolycodeIDEApp::PolycodeIDEApp(PolycodeView *view) : EventDispatcher() {
 	CoreServices::getInstance()->getConfig()->loadConfig("Polycode", "UIThemes/"+themeName+"/theme.xml");
 	CoreServices::getInstance()->getResourceManager()->addArchive("UIThemes/"+themeName+"/");
 	CoreServices::getInstance()->getResourceManager()->addArchive("Images/");	
-
-	CoreServices::getInstance()->getRenderer()->clearColor.setColorHexFromString(CoreServices::getInstance()->getConfig()->getStringValue("Polycode", "uiBgColor"));
-
 	
 	willRunProject = false;
 
 	SceneLabel::defaultAnchor = Vector3(-1.0, -1.0, 0.0);
 	SceneLabel::defaultPositionAtBaseline = true;
-	
+	SceneLabel::defaultSnapToPixels = true;
+	SceneLabel::createMipmapsForLabels = false;
+			
 	globalMenu	= new UIGlobalMenu();
 	UITextInput::setMenuSingleton(globalMenu);
 			
@@ -87,6 +86,9 @@ PolycodeIDEApp::PolycodeIDEApp(PolycodeView *view) : EventDispatcher() {
 	Scene *screen = new Scene(Scene::SCENE_2D_TOPLEFT);	
 	screen->rootEntity.processInputEvents = true;
 //	screen->rootEntity.setDefaultScreenOptions(true);
+
+	screen->clearColor.setColorHexFromString(CoreServices::getInstance()->getConfig()->getStringValue("Polycode", "uiBgColor"));	
+	screen->useClearColor = true;
 	
 	editorManager = new PolycodeEditorManager();
 	globalEditorManager = editorManager;
@@ -138,11 +140,10 @@ PolycodeIDEApp::PolycodeIDEApp(PolycodeView *view) : EventDispatcher() {
 	editorManager->registerEditorFactory(new PolycodeTextEditorFactory());
 	editorManager->registerEditorFactory(new PolycodeProjectEditorFactory(projectManager));
 	editorManager->registerEditorFactory(new PolycodeSpriteEditorFactory());
-
+	editorManager->registerEditorFactory(new PolycodeMeshEditorFactory());
 		
 	screen->addChild(globalMenu);	
 				
-	frame->settingsWindow->updateUI();
 	frame->console->applyTheme();
 
 #ifdef USE_POLYCODEUI_MENUBAR
@@ -213,6 +214,7 @@ void PolycodeIDEApp::showAbout() {
 }
 
 void PolycodeIDEApp::showSettings() {
+	frame->settingsWindow->updateUI();
 	frame->showModal(frame->settingsWindow);
 }
 
@@ -955,12 +957,15 @@ void PolycodeIDEApp::handleEvent(Event *event) {
 				config->setStringValue("Polycode", "useExternalTextEditor", settingsWindow->useExternalTextEditorBox->isChecked() ? "true" : "false");
 				config->setStringValue("Polycode", "externalTextEditorCommand", settingsWindow->externalTextEditorCommand->getText());
 				config->setStringValue("Polycode", "uiTheme", settingsWindow->uiThemeBox->getSelectedItem()->label);
+				
+				if(settingsWindow->textureFilteringBox->getSelectedIndex() == 0) {
+					config->setStringValue("Polycode", "textureFilteringMode", "linear");
+				} else {
+					config->setStringValue("Polycode", "textureFilteringMode", "nearest");				
+				}
 			
 				frame->hideModal();
 			}
-			if(event->getEventCode() == UIEvent::CLOSE_EVENT) {
-				settingsWindow->updateUI();
-			}
 		}
 	}
 
@@ -1033,7 +1038,8 @@ void PolycodeIDEApp::saveConfigFile() {
 	configFile.root.addChild("open_projects");
 	configFile.root.addChild("syntax_theme", globalSyntaxTheme->name);
 	configFile.root.addChild("ui_theme", config->getStringValue("Polycode", "uiTheme"));
-
+	configFile.root.addChild("texture_filtering_mode", config->getStringValue("Polycode", "textureFilteringMode"));
+	
 	configFile.root.addChild("app_width", String::IntToString(core->getXRes()));
 	configFile.root.addChild("app_height", String::IntToString(core->getYRes()));
 	
@@ -1084,6 +1090,19 @@ void PolycodeIDEApp::loadConfigFile() {
 	globalSyntaxTheme = new SyntaxHighlightTheme();
 	
 	String uiThemeName = "default";	
+	
+	CoreServices::getInstance()->getRenderer()->setTextureFilteringMode(Renderer::TEX_FILTERING_LINEAR);
+	
+	ObjectEntry *texture_filtering_mode = configFile.root["texture_filtering_mode"];
+	config->setStringValue("Polycode", "textureFilteringMode", "linear");	
+	
+	if(texture_filtering_mode) {
+		if(texture_filtering_mode->stringVal == "nearest") {
+		config->setStringValue("Polycode", "textureFilteringMode", "nearest");		
+			CoreServices::getInstance()->getRenderer()->setTextureFilteringMode(Renderer::TEX_FILTERING_NEAREST);
+		}
+	}
+	
 	ObjectEntry *uiTheme = configFile.root["ui_theme"];
 	if(uiTheme) {
 		uiThemeName = uiTheme->stringVal;

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

@@ -1154,6 +1154,7 @@ bool PolycodeMaterialEditor::openFile(OSFileEntry filePath) {
 	
 	for(int i=0; i < materials.size(); i++) {
 		materialBrowser->addMaterial(materials[i]);
+		CoreServices::getInstance()->getResourceManager()->addResource(materials[i]);
 	}
 
 	for(int i=0; i < postMaterials.size(); i++) {
@@ -1427,6 +1428,7 @@ void PolycodeMaterialEditor::handleEvent(Event *event) {
 	if(event->getDispatcher() == materialBrowser->newMaterialButton && event->getEventType() == "UIEvent" && event->getEventCode() == UIEvent::CLICK_EVENT) {
 		Material *newMaterial = CoreServices::getInstance()->getMaterialManager()->createMaterial("Untitled", "DefaultShader");
 			materialBrowser->addMaterial(newMaterial)->setSelected();
+			CoreServices::getInstance()->getResourceManager()->addResource(newMaterial);
 			materials.push_back(newMaterial);
 			setHasChanges(true);			
 	}	

+ 208 - 0
IDE/Contents/Source/PolycodeMeshEditor.cpp

@@ -0,0 +1,208 @@
+/*
+ Copyright (C) 2012 by Ivan Safrin
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+ 
+#include "PolycodeMeshEditor.h"
+
+extern UIGlobalMenu *globalMenu;
+
+PolycodeMeshEditor::PolycodeMeshEditor() : PolycodeEditor(true){
+	
+	previewScene = new Scene(Scene::SCENE_3D, true);		
+	renderTexture = new SceneRenderTexture(previewScene, previewScene->getDefaultCamera(), 512, 512);
+
+	previewScene->clearColor.setColor(0.0, 0.0, 0.0, 0.0);	
+	previewScene->useClearColor = true;
+	
+//	previewScene->ambientColor.setColor(0.0, 0.0, 0.0, 1.0);
+				
+	mainLight = new SceneLight(SceneLight::AREA_LIGHT, previewScene, 1590.0);
+	mainLight->setPosition(-10,10,10);
+	previewScene->addLight(mainLight);
+
+	secondLight = new SceneLight(SceneLight::AREA_LIGHT, previewScene, 1590.0);
+	secondLight->setPosition(10,-10,10);
+	previewScene->addLight(secondLight);
+
+	headerBg = new UIRect(10,10);
+	addChild(headerBg);
+	headerBg->setAnchorPoint(-1.0, -1.0, 0.0);
+	headerBg->color.setColorHexFromString(CoreServices::getInstance()->getConfig()->getStringValue("Polycode", "uiHeaderBgColor"));		
+
+	bgShape = new UIRect("Images/editorGrid.png");
+	bgShape->setAnchorPoint(-1.0, -1.0, 0.0);	
+	addChild(bgShape);	
+	bgShape->getTexture()->clamp = false;
+    bgShape->getTexture()->recreateFromImageData();     	
+	bgShape->color.setColorHexFromString(CoreServices::getInstance()->getConfig()->getStringValue("Polycode", "uiBgColor"));	
+	bgShape->processInputEvents = true;
+	bgShape->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
+	bgShape->addEventListener(this, InputEvent::EVENT_MOUSEUP);
+	bgShape->addEventListener(this, InputEvent::EVENT_MOUSEUP_OUTSIDE);
+	bgShape->addEventListener(this, InputEvent::EVENT_MOUSEMOVE);
+	bgShape->addEventListener(this, InputEvent::EVENT_MOUSEWHEEL_UP);
+	bgShape->addEventListener(this, InputEvent::EVENT_MOUSEWHEEL_DOWN);
+				
+	previewShape = new UIRect(256, 256);
+	previewShape->setAnchorPoint(-1.0, -1.0, 0.0);	
+	previewShape->setTexture(renderTexture->getTargetTexture());
+	addChild(previewShape);
+	
+	
+	UILabel *label = new UILabel("MATERIAL", 18, "section", Label::ANTIALIAS_FULL);
+	label->color.setColorHexFromString(CoreServices::getInstance()->getConfig()->getStringValue("Polycode", "uiHeaderFontColor"));
+	addChild(label);
+	label->setPosition(10, 3);
+	
+	materialDropDown = new UIComboBox(globalMenu, 200);
+	addChild(materialDropDown);
+	materialDropDown->setPosition(100, 3);
+
+	label = new UILabel("LIGHTS", 18, "section", Label::ANTIALIAS_FULL);
+	label->color.setColorHexFromString(CoreServices::getInstance()->getConfig()->getStringValue("Polycode", "uiHeaderFontColor"));
+	addChild(label);
+	label->setPosition(320, 3);
+
+	lightsSlider = new UIHSlider(0.0, 5000, 200);
+	addChild(lightsSlider);
+	lightsSlider->setSliderValue(1000.0);
+	lightsSlider->setPosition(380, 8);	
+	lightsSlider->addEventListener(this, UIEvent::CHANGE_EVENT);
+	
+	reloadMaterials();
+
+	previewBase = new Entity();
+	previewScene->addChild(previewBase);
+
+	CoreServices::getInstance()->getResourceManager()->dispatchChangeEvents = true;	
+	CoreServices::getInstance()->getResourceManager()->addEventListener(this, Event::CHANGE_EVENT);
+	
+	rotating = false;
+	previewMesh = NULL;
+}
+
+void PolycodeMeshEditor::reloadMaterials() {
+
+	Resource *selectedMaterial = NULL;
+		
+	if(materialDropDown->getSelectedItem()) {
+		selectedMaterial = (Resource*) materialDropDown->getSelectedItem()->data;
+	}
+	
+	materialDropDown->removeAllHandlersForListener(this);
+	
+	materialDropDown->clearItems();
+	std::vector<Resource*> materials = CoreServices::getInstance()->getResourceManager()->getResources(Resource::RESOURCE_MATERIAL);
+	for(int i=0; i < materials.size(); i++) {
+		materialDropDown->addComboItem(materials[i]->getResourceName(), (void*) materials[i]);
+		if(selectedMaterial == materials[i]) {
+			materialDropDown->setSelectedIndex(i);
+		}
+	}
+	
+	materialDropDown->addEventListener(this, UIEvent::CHANGE_EVENT);	
+}
+
+void PolycodeMeshEditor::handleEvent(Event *event) {
+	
+	if(event->getDispatcher() == lightsSlider) {
+		mainLight->setIntensity(lightsSlider->getSliderValue());
+		secondLight->setIntensity(lightsSlider->getSliderValue());		
+	} else if(event->getDispatcher() == materialDropDown) {
+		if(previewMesh) {
+			previewMesh->setMaterial((Material*)materialDropDown->getSelectedItem()->data);
+		}
+	} else if(event->getDispatcher() == CoreServices::getInstance()->getResourceManager()) {
+		reloadMaterials();
+	} else if(event->getDispatcher() == bgShape) {
+		InputEvent *inputEvent = (InputEvent*) event;
+		switch(event->getEventCode()) {
+			case InputEvent::EVENT_MOUSEDOWN:
+				rotating = true;
+				baseMousePosition = inputEvent->mousePosition;
+				baseYaw = previewBase->getYaw();
+				basePitch = previewBase->getPitch();
+				baseModelPosition = previewMesh->getPosition();
+			break;
+			case InputEvent::EVENT_MOUSEUP:
+				rotating = false;
+			break;
+			case InputEvent::EVENT_MOUSEUP_OUTSIDE:
+				rotating = false;			
+			break;
+			case InputEvent::EVENT_MOUSEMOVE:
+				if(rotating && previewMesh) {
+					if(CoreServices::getInstance()->getCore()->getInput()->getKeyState(KEY_LALT)) {
+						previewMesh->setPosition(baseModelPosition.x - ((baseMousePosition.x -inputEvent->mousePosition.x) * 0.01), baseModelPosition.y + ((baseMousePosition.y -inputEvent->mousePosition.y) * 0.01));
+						
+					} else {
+						previewBase->setYaw(baseYaw - ((baseMousePosition.x-inputEvent->mousePosition.x) * 0.3));
+						previewBase->setPitch(basePitch - ((baseMousePosition.y-inputEvent->mousePosition.y) * 0.3));
+					}
+				}
+			break;
+			case InputEvent::EVENT_MOUSEWHEEL_UP:
+				previewBase->Scale(1.01, 1.01, 1.01);
+			break;
+			case InputEvent::EVENT_MOUSEWHEEL_DOWN:
+				previewBase->Scale(0.99, 0.99, 0.99);			
+			break;			
+		}
+	}
+}
+
+PolycodeMeshEditor::~PolycodeMeshEditor() {
+}
+
+bool PolycodeMeshEditor::openFile(OSFileEntry filePath) {
+	previewMesh = new SceneMesh(filePath.fullPath);
+	previewBase->addChild(previewMesh);
+	previewMesh->setMaterialByName("Default");
+	PolycodeEditor::openFile(filePath);
+	
+//	previewMesh->getMesh()->recenterMesh();
+//	previewMesh->getMesh()->calculateTangents();
+	
+	Number radius = previewMesh->getBBoxRadius();
+	
+	previewScene->getDefaultCamera()->setPosition(0,0,radius*3);
+	previewScene->getDefaultCamera()->lookAt(Vector3());
+	
+		
+	mainLight->setPosition(-(radius*3),(radius*3),(radius*3));
+	secondLight->setPosition((radius*3),-(radius*3),(radius*3));
+	
+	return true;
+}
+
+void PolycodeMeshEditor::Resize(int x, int y) {
+
+	headerBg->Resize(x, 30);
+	
+	renderTexture->resizeRenderTexture(x, y-30);
+	previewShape->setTexture(renderTexture->getTargetTexture());	
+	previewShape->Resize(x, y-30);	
+	bgShape->setImageCoordinates(0,0,x,y);
+	
+	bgShape->setPosition(0, 30);
+	previewShape->setPosition(0, 30);
+}
+

+ 93 - 0
IDE/Contents/Source/PolycodeSoundEditor.cpp

@@ -0,0 +1,93 @@
+/*
+ Copyright (C) 2012 by Ivan Safrin
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+ 
+#include "PolycodeImageEditor.h"
+
+PolycodeImageEditor::PolycodeImageEditor() : PolycodeEditor(true){
+	
+}
+
+PolycodeImageEditor::~PolycodeImageEditor() {
+	delete editorImage;
+	delete leftShape;
+	delete rightShape;
+	delete topShape;
+	delete bottomShape;
+}
+
+bool PolycodeImageEditor::openFile(OSFileEntry filePath) {
+	
+	
+	leftShape = new UIRect(10,10);
+	leftShape->setColor(0.0, 0.0, 0.0, 0.3);
+	leftShape->setAnchorPoint(-1.0, -1.0, 0.0);
+	addChild(leftShape);
+
+	rightShape = new UIRect(10,10);
+	rightShape->setColor(0.0, 0.0, 0.0, 0.3);
+	rightShape->setAnchorPoint(-1.0, -1.0, 0.0);
+	addChild(rightShape);
+
+	topShape = new UIRect(10,10);
+	topShape->setColor(0.0, 0.0, 0.0, 0.3);
+	topShape->setAnchorPoint(-1.0, -1.0, 0.0);
+	addChild(topShape);
+
+	bottomShape = new UIRect(10,10);
+	bottomShape->setColor(0.0, 0.0, 0.0, 0.3);
+	bottomShape->setAnchorPoint(-1.0, -1.0, 0.0);
+	addChild(bottomShape);
+			
+	editorImage = new UIRect(filePath.fullPath);
+	aspectRatio = ((Number)editorImage->getWidth()) / ((Number)editorImage->getHeight());
+	editorImage->setAnchorPoint(0.0, 0.0, 0.0);
+	addChild(editorImage);
+	
+	PolycodeEditor::openFile(filePath);
+	
+	return true;
+}
+
+void PolycodeImageEditor::Resize(int x, int y) {
+
+	editorImage->setPosition(x/2, y/2);
+
+	if((y * 0.8) * aspectRatio > x * 0.8) {
+		editorImage->Resize((x * 0.8), (x * 0.8) / aspectRatio);	
+	} else {
+		editorImage->Resize((y * 0.8) * aspectRatio, (y * 0.8));
+	}
+	
+	leftShape->Resize((x - editorImage->getWidth())/2.0, y);	
+	rightShape->Resize((x - editorImage->getWidth())/2.0, y);	
+	rightShape->setPosition(leftShape->getWidth() + editorImage->getWidth(), 0);
+		
+	topShape->Resize(editorImage->getWidth(), (y - editorImage->getHeight())/2.0);
+	topShape->setPosition(leftShape->getWidth(),0);
+
+	bottomShape->Resize(editorImage->getWidth(), (y - editorImage->getHeight())/2.0);
+	bottomShape->setPosition(leftShape->getWidth(),y-bottomShape->getHeight());
+
+		
+	PolycodeEditor::Resize(x,y);
+}
+

+ 18 - 1
IDE/Contents/Source/SettingsWindow.cpp

@@ -96,8 +96,19 @@ SettingsWindow::SettingsWindow() : UIWindow(L"Settings", SETTINGS_WINDOW_WIDTH,
 			}
 		}
 	}
-	
 
+	label = new UILabel("Texture filtering (requires restart)", 12);
+	addChild(label);
+	label->color.a = 1.0;
+	label->setPosition(padding, 285);
+
+	textureFilteringBox = new UIComboBox(globalMenu, 300);
+	addChild(textureFilteringBox);
+	textureFilteringBox->setPosition(padding, 305);
+	textureFilteringBox->addEventListener(this, UIEvent::CHANGE_EVENT);
+	textureFilteringBox->addComboItem("Linear");
+	textureFilteringBox->addComboItem("Nearest");
+	
 	cancelButton = new UIButton("Cancel", BUTTON_WIDTH);
 	cancelButton->addEventListener(this, UIEvent::CLICK_EVENT);
 	addChild(cancelButton);
@@ -186,6 +197,12 @@ void SettingsWindow::updateUI() {
 		} 
 	}
 	
+	if(config->getStringValue("Polycode", "textureFilteringMode") == "nearest") {
+		textureFilteringBox->setSelectedIndex(1);
+	} else {
+		textureFilteringBox->setSelectedIndex(0);	
+	}
+	
 }
 	
 SettingsWindow::~SettingsWindow() {

+ 1 - 4
Modules/Contents/UI/Include/PolyUIElement.h

@@ -119,12 +119,9 @@ namespace Polycode {
 	};
 
 	
-	class _PolyExport UIImage : public UIElement {
+	class _PolyExport UIImage : public UIRect {
 		public:
 			UIImage(String imagePath);
-			SceneImage *getImage();
-		protected:
-			SceneImage *image;
 	};
 	
 }

+ 1 - 1
Modules/Contents/UI/Include/PolyUIImageButton.h

@@ -39,7 +39,7 @@ namespace Polycode {
 				
 		private:
 			UIRect *buttonRect;
-			SceneImage *buttonImage;
+			UIImage *buttonImage;
 			bool pressedDown;
 	};
 }

+ 1 - 1
Modules/Contents/UI/Include/PolyUITree.h

@@ -95,7 +95,7 @@ namespace Polycode {
 			UIBox *selection;
 			UIRect *bgBox;
 			SceneLabel *textLabel;
-			SceneImage *iconImage;
+			UIImage *iconImage;
 			bool selected;
 			Number treeHeight;
 			vector<UITree*> treeChildren;

+ 2 - 2
Modules/Contents/UI/Source/PolyUIColorBox.cpp

@@ -85,14 +85,14 @@ UIColorPicker::UIColorPicker() : UIWindow(L"", 300, 240) {
 	addChild(hueFrame);
 	
 	hueSelector = new UIImage(hueSelectorImage);
-	hueSelector->getImage()->setAnchorPoint(0.0, 0.0, 0.0);
+	hueSelector->setAnchorPoint(0.0, 0.0, 0.0);
 	hueSelector->setPosition(hueFrame->getPosition().x + (hueFrame->getWidth()/2.0), hueFrame->getPosition().y);
 	addChild(hueSelector);	
 
 	hueSelector->setDragLimits(Polycode::Rectangle(hueSelector->getPosition().x,hueSelector->getPosition().y,0,hueFrame->getHeight()));
 				
 	mainSelector = new UIImage(mainSelectorImage);
-	mainSelector->getImage()->setAnchorPoint(0.0, 0.0, 0.0);
+	mainSelector->setAnchorPoint(0.0, 0.0, 0.0);
 	mainSelector->setPosition(mainFrame->getPosition());
 	addChild(mainSelector);	
 	

+ 4 - 12
Modules/Contents/UI/Source/PolyUIElement.cpp

@@ -34,6 +34,8 @@ UILabel::UILabel(const String& text, int size, const String& fontName, int amode
 
 	Config *conf = CoreServices::getInstance()->getConfig();	
 	label = new SceneLabel(text, size, fontName, amode);
+	label->snapToPixels = true;
+	
 	color.setColorHexFromString(conf->getStringValue("Polycode", "uiDefaultFontColor"));
 	addChild(label);
 	bBox = label->bBox;
@@ -190,21 +192,11 @@ void UIRect::Resize(Number width, Number height) {
 	rectMesh->arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;	
 }
 
-UIImage::UIImage(String imagePath) : UIElement() {
-	image = new SceneImage(imagePath);
-	image->setAnchorPoint(-1.0, -1.0, 0.0);
-	image->depthTest = false;
-	image->depthWrite = false;		
-	addChild(image);
-	setWidth(image->bBox.x);
-	setHeight(image->bBox.y);	
-}
-
-SceneImage *UIImage::getImage() {
-	return image;
+UIImage::UIImage(String imagePath) : UIRect(imagePath) {
 }
 
 UIElement::UIElement() : Entity() {
+	snapToPixels = true;
 	setAnchorPoint(-1.0, -1.0, 0.0);
 	processInputEvents = true;
 	depthTest = false;	

+ 1 - 1
Modules/Contents/UI/Source/PolyUIHSlider.cpp

@@ -53,7 +53,7 @@ UIHSlider::UIHSlider(Number start, Number end, Number width) : UIElement() {
 	endValue = end;
 		
 	gripRect = new UIImage(gripImage);
-	gripRect->getImage()->setAnchorPoint(0.0, 0.0, 0.0);
+	gripRect->setAnchorPoint(0.0, 0.0, 0.0);
 	gripRect->setPosition(0, floor(bgHeight/2.0));
 
 	bgHitBox = new UIRect(width, gripRect->getHeight());

+ 3 - 1
Modules/Contents/UI/Source/PolyUIImageButton.cpp

@@ -31,9 +31,11 @@ using namespace Polycode;
 UIImageButton::UIImageButton(String imageName) : UIElement() {
 	setAnchorPoint(-1.0, -1.0, 0.0);
 	
-	buttonImage = new SceneImage(imageName.c_str());
+	buttonImage = new UIImage(imageName);
 	addChild(buttonImage);
 	buttonImage->depthTest = false;
+	buttonImage->snapToPixels = true;
+		
 	buttonImage->setAnchorPoint(-1.0, -1.0, 0.0);
 	
 	buttonRect = new UIRect(buttonImage->getWidth(),buttonImage->getHeight());

+ 1 - 1
Modules/Contents/UI/Source/PolyUITree.cpp

@@ -81,7 +81,7 @@ UITree::UITree(String icon, String text, Number treeWidth, Number treeOffset) :
 	arrowIconImage = new SceneImage(arrowIcon.c_str());
 	arrowIconImage->setPosition(cellPadding + arrowIconImage->getWidth()/2.0,(cellHeight)/2.0f);	
 	addChild(arrowIconImage);
-	iconImage = new SceneImage(icon.c_str());
+	iconImage = new UIImage(icon.c_str());
 	iconImage->setAnchorPoint(-1.0, -1.0, 0.0);
 	addChild(iconImage);
 	iconImage->setPosition(arrowIconImage->getWidth()+(cellPadding*2),(cellHeight-iconImage->getHeight())/2.0f);

+ 16 - 3
Tools/Contents/polyimport/Source/polyimport.cpp

@@ -44,6 +44,13 @@ void addToMesh(Polycode::Mesh *tmesh, const struct aiScene *sc, const struct aiN
 					vertex->vertexColor.setColorRGBA(mesh->mColors[0][index].r, mesh->mColors[0][index].g, mesh->mColors[0][index].b, mesh->mColors[0][index].a);
 				}
 
+				if(mesh->mTangents != NULL)  {
+					if(swapZY)
+						vertex->tangent = Vector3(mesh->mTangents[index].x, mesh->mTangents[index].z, -mesh->mTangents[index].y);
+					else
+						vertex->tangent = Vector3(mesh->mTangents[index].x, mesh->mTangents[index].y, mesh->mTangents[index].z);
+				}
+
 				if(mesh->mNormals != NULL)  {
 					if(swapZY)
 						vertex->setNormal(mesh->mNormals[index].x, mesh->mNormals[index].z, -mesh->mNormals[index].y);
@@ -170,11 +177,11 @@ int exportToFile(const char *fileName, bool swapZY) {
 
 int main(int argc, char **argv) {
 
-	printf("Polycode import tool v0.8.2\n");
+	printf("Polycode import tool v"POLYCODE_VERSION_STRING"\n");
 
-	if(argc != 4) {
+	if(argc != 5) {
 		printf("\n\nInvalid arguments!\n");
-		printf("usage: polyimport <source_file> <output_file> (Swap Z/Y:<true>/<false>) \n\n");
+		printf("usage: polyimport <source_file> <output_file> (Swap Z/Y:<true>/<false>) (Generate tangents:<true>/<false>) \n\n");
 		return 0;
 	}
 	
@@ -185,6 +192,12 @@ int main(int argc, char **argv) {
 
 	printf("Loading %s...\n", argv[1]);
 	scene = aiImportFile(argv[1],aiProcessPreset_TargetRealtime_Quality);
+	
+	
+	if(strcmp(argv[4], "true") == 0) {
+		aiApplyPostProcessing(scene, aiProcess_CalcTangentSpace);
+	}
+	
 	if(scene) {
 		exportToFile(argv[2], strcmp(argv[3], "true") == 0);
 	} else {