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

Merge mingw compatiblity fork with 4/14 github; back out zlib cmake patch (1.2.6 incorporates the patch already)

mcc 14 лет назад
Родитель
Сommit
e15ae329af
100 измененных файлов с 2252 добавлено и 403 удалено
  1. 3 0
      BUILD.md
  2. 3 0
      BUILD.txt
  3. 1 0
      CMake/ExternalAssimp.cmake
  4. 1 0
      CMake/ExternalBox2D.cmake
  5. 1 0
      CMake/ExternalBullet.cmake
  6. 1 0
      CMake/ExternalFreetype.cmake
  7. 1 0
      CMake/ExternalLua51.cmake
  8. 1 0
      CMake/ExternalOggVorbis.cmake
  9. 1 0
      CMake/ExternalOpenAL.cmake
  10. 6 5
      CMake/ExternalPNG.cmake
  11. 1 0
      CMake/ExternalPhysFS.cmake
  12. 0 201
      CMake/zlib.cmake
  13. 33 0
      Core/Contents/Include/PolyColor.h
  14. 27 0
      Core/Contents/Include/PolyEntity.h
  15. 1 1
      Core/Contents/Include/PolyGLRenderer.h
  16. 4 2
      Core/Contents/Include/PolyGLVertexBuffer.h
  17. 9 1
      Core/Contents/Include/PolyGlobals.h
  18. 4 4
      Core/Contents/Include/PolyMaterialManager.h
  19. 1 1
      Core/Contents/Include/PolyMesh.h
  20. 1 0
      Core/Contents/Include/PolyObject.h
  21. 1 1
      Core/Contents/Include/PolyRenderer.h
  22. 2 2
      Core/Contents/Include/PolySceneEntity.h
  23. 3 0
      Core/Contents/Include/PolySceneLine.h
  24. 2 2
      Core/Contents/Include/PolyScreenEntity.h
  25. 1 1
      Core/Contents/Include/PolyScreenMesh.h
  26. 6 0
      Core/Contents/Include/PolySound.h
  27. 13 1
      Core/Contents/Include/PolyVector2.h
  28. 13 0
      Core/Contents/Include/PolyVector3.h
  29. 67 1
      Core/Contents/Include/PolyWinCore.h
  30. 15 2
      Core/Contents/PolycodeView/MSVC/PolycodeView.cpp
  31. 1 0
      Core/Contents/PolycodeView/MSVC/PolycodeView.h
  32. 52 0
      Core/Contents/Source/PolyColor.cpp
  33. 20 0
      Core/Contents/Source/PolyEntity.cpp
  34. 16 5
      Core/Contents/Source/PolyGLRenderer.cpp
  35. 3 0
      Core/Contents/Source/PolyGLSLShaderModule.cpp
  36. 26 0
      Core/Contents/Source/PolyGLVertexBuffer.cpp
  37. 3 2
      Core/Contents/Source/PolyImage.cpp
  38. 5 6
      Core/Contents/Source/PolyMesh.cpp
  39. 8 0
      Core/Contents/Source/PolyObject.cpp
  40. 1 0
      Core/Contents/Source/PolyParticleEmitter.cpp
  41. 1 1
      Core/Contents/Source/PolySceneEntity.cpp
  42. 7 0
      Core/Contents/Source/PolySceneLine.cpp
  43. 1 1
      Core/Contents/Source/PolySceneMesh.cpp
  44. 123 85
      Core/Contents/Source/PolyScreenEntity.cpp
  45. 7 0
      Core/Contents/Source/PolySound.cpp
  46. 236 8
      Core/Contents/Source/PolyWinCore.cpp
  47. 1 1
      Examples/C++/Build/Linux/Makefile
  48. 4 3
      Examples/C++/Contents/2DParticles/HelloPolycodeApp.cpp
  49. 2 1
      Examples/C++/Contents/3DMeshParticles/HelloPolycodeApp.cpp
  50. 2 1
      Examples/C++/Contents/3DParticles/HelloPolycodeApp.cpp
  51. 233 13
      IDE/Build/Mac OS X/English.lproj/MainMenu.xib
  52. 26 8
      IDE/Build/Mac OS X/Polycode.xcodeproj/project.pbxproj
  53. 4 0
      IDE/Build/Mac OS X/PolycodeAppDelegate.h
  54. 16 0
      IDE/Build/Mac OS X/PolycodeAppDelegate.m
  55. 12 1
      IDE/Contents/Include/NewFileWindow.h
  56. 4 0
      IDE/Contents/Include/PolycodeEditor.h
  57. 7 0
      IDE/Contents/Include/PolycodeFrame.h
  58. 7 0
      IDE/Contents/Include/PolycodeIDEApp.h
  59. 7 1
      IDE/Contents/Include/PolycodeProjectBrowser.h
  60. 65 0
      IDE/Contents/Include/PolycodeProjectEditor.h
  61. 11 1
      IDE/Contents/Include/PolycodeProjectManager.h
  62. 67 0
      IDE/Contents/Include/PolycodeScreenEditor.h
  63. 1 1
      IDE/Contents/Include/PolycodeTextEditor.h
  64. 48 0
      IDE/Contents/Include/ToolWindows.h
  65. 12 0
      IDE/Contents/Resources/FileTemplates/2D/Screen Entity.screen
  66. BIN
      IDE/Contents/Resources/Images/editorGrid.png
  67. BIN
      IDE/Contents/Resources/Images/screenCenter.png
  68. BIN
      IDE/Contents/Resources/Images/screenTransform.png
  69. BIN
      IDE/Contents/Resources/UIThemes/default/checkbox_checked.png
  70. BIN
      IDE/Contents/Resources/UIThemes/default/checkbox_unchecked.png
  71. BIN
      IDE/Contents/Resources/UIThemes/default/colorPickerHue.png
  72. BIN
      IDE/Contents/Resources/UIThemes/default/colorPickerHueSelector.png
  73. BIN
      IDE/Contents/Resources/UIThemes/default/colorPickerMainBg.png
  74. BIN
      IDE/Contents/Resources/UIThemes/default/colorPickerMainFrame.png
  75. BIN
      IDE/Contents/Resources/UIThemes/default/colorPickerTarget.png
  76. BIN
      IDE/Contents/Resources/UIThemes/default/colorboxBg.png
  77. BIN
      IDE/Contents/Resources/UIThemes/default/colorboxFrame.png
  78. BIN
      IDE/Contents/Resources/UIThemes/default/combobox_bg.png
  79. BIN
      IDE/Contents/Resources/UIThemes/default/combobox_drop.png
  80. BIN
      IDE/Contents/Resources/UIThemes/default/combobox_items.png
  81. BIN
      IDE/Contents/Resources/UIThemes/default/combobox_selector.png
  82. BIN
      IDE/Contents/Resources/UIThemes/default/hsliderBg.png
  83. BIN
      IDE/Contents/Resources/UIThemes/default/hsliderHandle.png
  84. 60 15
      IDE/Contents/Resources/UIThemes/default/theme.xml
  85. BIN
      IDE/Contents/Resources/UIThemes/default/windowBg.png
  86. 64 4
      IDE/Contents/Source/NewFileWindow.cpp
  87. 1 1
      IDE/Contents/Source/NewProjectWindow.cpp
  88. 4 0
      IDE/Contents/Source/PolycodeEditor.cpp
  89. 55 0
      IDE/Contents/Source/PolycodeFrame.cpp
  90. 85 2
      IDE/Contents/Source/PolycodeIDEApp.cpp
  91. 64 13
      IDE/Contents/Source/PolycodeProjectBrowser.cpp
  92. 268 0
      IDE/Contents/Source/PolycodeProjectEditor.cpp
  93. 11 0
      IDE/Contents/Source/PolycodeProjectManager.cpp
  94. 190 0
      IDE/Contents/Source/PolycodeScreenEditor.cpp
  95. 0 1
      IDE/Contents/Source/PolycodeTextEditor.cpp
  96. 72 0
      IDE/Contents/Source/ToolWindows.cpp
  97. 30 0
      Modules/Contents/3DPhysics/Include/PolyPhysicsScene.h
  98. 3 0
      Modules/Contents/3DPhysics/Include/PolyPhysicsSceneEntity.h
  99. 10 2
      Modules/Contents/3DPhysics/Source/PolyCollisionSceneEntity.cpp
  100. 73 1
      Modules/Contents/3DPhysics/Source/PolyPhysicsScene.cpp

+ 3 - 0
BUILD.md

@@ -15,6 +15,9 @@ When Polycode and its Dependencies are built, they will be available
 in the Release/YourArchitecture folder under the main source tree in 
 a structure that should mimic the main binary release.
 
+If you wish to build a 32-bit version on a 64-bit machine in OS X, pass
+-DCMAKE_OSX_ARCHITECTURES=i386 as an argument to cmake
+
 ## Building dependencies ##
 
 Polycode depends on a number of third party packages that are not

+ 3 - 0
BUILD.txt

@@ -15,6 +15,9 @@ When Polycode and its Dependencies are built, they will be available
 in the Release/YourArchitecture folder under the main source tree in 
 a structure that should mimic the main binary release.
 
+If you wish to build a 32-bit version on a 64-bit machine in OS X, pass
+-DCMAKE_OSX_ARCHITECTURES=i386 as an argument to cmake
+
 ## Building dependencies ##
 
 Polycode depends on a number of third party packages that are not

+ 1 - 0
CMake/ExternalAssimp.cmake

@@ -7,6 +7,7 @@ SET(assimp_CMAKE_ARGS
     -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
     -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
 	-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
+    -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
     -DCMAKE_DEBUG_POSTFIX=d 
     -DENABLE_BOOST_WORKAROUND=ON 
     -DBUILD_ASSIMP_TOOLS=OFF 

+ 1 - 0
CMake/ExternalBox2D.cmake

@@ -11,6 +11,7 @@ SET(box2d_CMAKE_ARGS
     -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
     -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
 	-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
+    -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
     -DCMAKE_DEBUG_POSTFIX=_d 
     -DBOX2D_INSTALL=ON 
     -DBOX2D_BUILD_EXAMPLES=OFF 

+ 1 - 0
CMake/ExternalBullet.cmake

@@ -6,6 +6,7 @@ SET(bullet_CMAKE_ARGS
     -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
     -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
 	-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
+    -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
     -DCMAKE_DEBUG_POSTFIX=_d
     -DINSTALL_LIBS=ON
     -DBUILD_DEMOS=OFF

+ 1 - 0
CMake/ExternalFreetype.cmake

@@ -7,6 +7,7 @@ SET(freetype_CMAKE_ARGS
     -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> 
     -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
 	-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
+    -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
 )
 
 EXTERNALPROJECT_ADD(freetype

+ 1 - 0
CMake/ExternalLua51.cmake

@@ -7,6 +7,7 @@ SET(lua51_CMAKE_ARGS
     -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> 
     -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
 	-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
+    -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
     -DCMAKE_DEBUG_POSTFIX=d
 )
 

+ 1 - 0
CMake/ExternalOggVorbis.cmake

@@ -7,6 +7,7 @@ SET(oggvorbis_CMAKE_ARGS
     -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> 
     -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
 	-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
+    -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
 )
 
 EXTERNALPROJECT_ADD(libogg

+ 1 - 0
CMake/ExternalOpenAL.cmake

@@ -7,6 +7,7 @@ SET(openal_CMAKE_ARGS
     -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> 
     -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
 	-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
+    -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
     -DCMAKE_DEBUG_POSTFIX=d
 )
 

+ 6 - 5
CMake/ExternalPNG.cmake

@@ -7,6 +7,7 @@ SET(libpng_CMAKE_ARGS
     -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> 
     -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
 	-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
+    -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
     -DPNG_SHARED=OFF
     -DBUILD_SHARED_LIBS=FALSE
     -DSKIP_INSTALL_FILES=1
@@ -16,10 +17,10 @@ EXTERNALPROJECT_ADD(zlib
     PREFIX ${libpng_PREFIX}
 
     DOWNLOAD_DIR ${POLYCODE_DEPS_DOWNLOAD_DIR}
-    URL http://zlib.net/zlib-1.2.5.tar.gz
-    URL_MD5 c735eab2d659a96e5a594c9e8541ad63
+    URL http://zlib.net/zlib-1.2.6.tar.gz
+    URL_MD5 618e944d7c7cd6521551e30b32322f4a
 
-    PATCH_COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PolycodeDependencies_SOURCE_DIR}/../CMake/zlib.cmake <SOURCE_DIR>/CMakeLists.txt && ${CMAKE_COMMAND} -E remove <SOURCE_DIR>/zconf.h
+    PATCH_COMMAND ${CMAKE_COMMAND} -E remove <SOURCE_DIR>/zconf.h
 
     INSTALL_DIR ${POLYCODE_DEPS_CORE_PREFIX}
     CMAKE_ARGS ${libpng_CMAKE_ARGS}
@@ -39,8 +40,8 @@ EXTERNALPROJECT_ADD(libpng
     PREFIX ${libpng_PREFIX}
 
     DOWNLOAD_DIR ${POLYCODE_DEPS_DOWNLOAD_DIR}
-    URL ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng-1.5.7.tar.gz
-    URL_MD5 944b56a84b65d94054cc73d7ff965de8
+    URL ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng-1.5.10.tar.gz
+    URL_MD5 9e5d864bce8f06751bbd99962ecf4aad
 
     INSTALL_DIR ${POLYCODE_DEPS_CORE_PREFIX}
     CMAKE_ARGS ${libpng_CMAKE_ARGS} -DCMAKE_PREFIX_PATH=${install_dir} # to find zlib

+ 1 - 0
CMake/ExternalPhysFS.cmake

@@ -7,6 +7,7 @@ SET(physfs_CMAKE_ARGS
     -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> 
     -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
 	-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
+    -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
     -DCMAKE_DEBUG_POSTFIX=d
     -DPHYSFS_BUILD_TEST=FALSE
     -DPHYSFS_BUILD_SHARED=FALSE

+ 0 - 201
CMake/zlib.cmake

@@ -1,201 +0,0 @@
-# Custom version of cmake file for zlib 1.2.5 for Polycode build, in order that 
-# the location of windres.exe can be overriden using CMAKE_RC_COMPILER
-cmake_minimum_required(VERSION 2.4.4)
-set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
-
-project(zlib C)
-
-if(NOT DEFINED BUILD_SHARED_LIBS)
-    option(BUILD_SHARED_LIBS "Build a shared library form of zlib" ON)
-endif()
-
-include(CheckTypeSize)
-include(CheckFunctionExists)
-include(CheckIncludeFile)
-include(CheckCSourceCompiles)
-enable_testing()
-
-check_include_file(sys/types.h HAVE_SYS_TYPES_H)
-check_include_file(stdint.h    HAVE_STDINT_H)
-check_include_file(stddef.h    HAVE_STDDEF_H)
-
-#
-# Check to see if we have large file support
-#
-set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1)
-# We add these other definitions here because CheckTypeSize.cmake
-# in CMake 2.4.x does not automatically do so and we want
-# compatibility with CMake 2.4.x.
-if(HAVE_SYS_TYPES_H)
-    list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H)
-endif()
-if(HAVE_STDINT_H)
-    list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H)
-endif()
-if(HAVE_STDDEF_H)
-    list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H)
-endif()
-check_type_size(off64_t OFF64_T)
-if(HAVE_OFF64_T)
-   add_definitions(-D_LARGEFILE64_SOURCE=1)
-endif()
-set(CMAKE_REQUIRED_DEFINITIONS) # clear variable
-
-#
-# Check for fseeko
-#
-check_function_exists(fseeko HAVE_FSEEKO)
-if(NOT HAVE_FSEEKO)
-    add_definitions(-DNO_FSEEKO)
-endif()
-
-#
-# Check for unistd.h
-#
-check_include_file(unistd.h Z_HAVE_UNISTD_H)
-
-if(MSVC)
-    set(CMAKE_DEBUG_POSTFIX "d")
-    add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
-    add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
-endif()
-
-if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
-    # If we're doing an out of source build and the user has a zconf.h
-    # in their source tree...
-    if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h)
-        message(FATAL_ERROR
-            "You must remove ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h "
-            "from the source tree.  This file is included with zlib "
-            "but CMake generates this file for you automatically "
-            "in the build directory.")
-  endif()
-endif()
-
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein
-               ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY)
-include_directories(${CMAKE_CURRENT_BINARY_DIR})
-
-
-#============================================================================
-# zlib
-#============================================================================
-
-set(ZLIB_PUBLIC_HDRS
-    ${CMAKE_CURRENT_BINARY_DIR}/zconf.h
-    zlib.h
-)
-set(ZLIB_PRIVATE_HDRS
-    crc32.h
-    deflate.h
-    gzguts.h
-    inffast.h
-    inffixed.h
-    inflate.h
-    inftrees.h
-    trees.h
-    zutil.h
-)
-set(ZLIB_SRCS
-    adler32.c
-    compress.c
-    crc32.c
-    deflate.c
-    gzclose.c
-    gzlib.c
-    gzread.c
-    gzwrite.c
-    inflate.c
-    infback.c
-    inftrees.c
-    inffast.c
-    trees.c
-    uncompr.c
-    zutil.c
-)
-
-IF (NOT MINGW)
-	set(ZLIB_SRCS ${ZLIB_SRCS}
-		win32/zlib1.rc # If present will override custom build rule below.s
-	)
-ENDIF()
-
-# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION
-file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents)
-string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([0-9A-Za-z.]+)\".*"
-    "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents})
-
-if(MINGW)
-    # This gets us DLL resource information when compiling on MinGW.
-    if(NOT CMAKE_RC_COMPILER)
-        SET(CMAKE_RC_COMPILER windres.exe)
-    endif()
-    
-    add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
-                       COMMAND ${CMAKE_RC_COMPILER}
-                            -D GCC_WINDRES
-                            -I ${CMAKE_CURRENT_SOURCE_DIR}
-                            -I ${CMAKE_CURRENT_BINARY_DIR}
-                            -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
-                            -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc)
-    set(ZLIB_SRCS ${ZLIB_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
-endif(MINGW)
-
-add_library(zlib ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
-set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
-
-set_target_properties(zlib PROPERTIES SOVERSION 1)
-
-if(NOT CYGWIN)
-    # This property causes shared libraries on Linux to have the full version
-    # encoded into their final filename.  We disable this on Cygwin because
-    # it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll
-    # seems to be the default.
-    #
-    # This has no effect with MSVC, on that platform the version info for
-    # the DLL comes from the resource file win32/zlib1.rc
-    set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION})
-endif()
-
-if(UNIX)
-    # On unix-like platforms the library is almost always called libz
-   set_target_properties(zlib PROPERTIES OUTPUT_NAME z)
-elseif(BUILD_SHARED_LIBS AND WIN32)
-    # Creates zlib1.dll when building shared library version
-    set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
-endif()
-
-if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL )
-    install(TARGETS zlib
-        RUNTIME DESTINATION bin
-        ARCHIVE DESTINATION lib
-        LIBRARY DESTINATION lib )
-endif()
-if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL )
-    install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION include)
-endif()
-if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
-    install(FILES zlib.3 DESTINATION share/man/man3)
-endif()
-
-#============================================================================
-# Example binaries
-#============================================================================
-
-add_executable(example example.c)
-target_link_libraries(example zlib)
-add_test(example example)
-
-add_executable(minigzip minigzip.c)
-target_link_libraries(minigzip zlib)
-
-if(HAVE_OFF64_T)
-    add_executable(example64 example.c)
-    target_link_libraries(example64 zlib)
-    set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
-    add_test(example64 example64)
-
-    add_executable(minigzip64 minigzip.c)
-    target_link_libraries(minigzip64 zlib)
-    set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
-endif()

+ 33 - 0
Core/Contents/Include/PolyColor.h

@@ -80,6 +80,18 @@ namespace Polycode {
 				return Color(nr, ng, nb, na);
 			}	
 			
+			/** 
+			* Adds the color to another color.
+			*/
+			inline Color operator + ( const Color& v2) const {
+				Number nr = r + v2.r;
+				Number ng = g + v2.g;
+				Number nb = b + v2.b;
+				Number na = a + v2.a;				
+				return Color(nr, ng, nb, na);
+			}	
+			
+			
 			bool operator == (const Color& c2) {
 				return (((int)255.0*r) == ((int)255.0*c2.r) && ((int)255.0*g) == ((int)255.0*c2.g) && ((int)255.0*b) == ((int)255.0*c2.b) && ((int)255.0*a) == ((int)255.0*c2.a));
 			}
@@ -152,6 +164,27 @@ namespace Polycode {
 			*/
 			Number getBrightness() const;
 			
+			static void RGBtoHSV(const Number &r, const Number &g, const Number &b, Number &h, Number &s, Number &v);
+			
+			/**
+			* Returns the hue of the color's HSV component.
+			* @return HSV Hue.
+			*/
+			Number getHue() const;
+
+			/**
+			* Returns the saturation of the color's HSV component.
+			* @return HSV Saturation
+			*/
+			Number getSaturation() const;
+
+			/**
+			* Returns the value of the color's HSV component
+			* @return HSV Value
+			*/
+			Number getValue() const;
+
+			
 			/**
 			* Returns the color as a 32-bit usigned integer.
 			* @return Color as a single 32-bit unsigned integer.

+ 27 - 0
Core/Contents/Include/PolyEntity.h

@@ -157,6 +157,19 @@ namespace Polycode {
 			@return Parent entity of this entity.
 			*/
 			Entity *getParentEntity() const;
+			
+			/**
+			* Returns the number of child entities belonging to this entity.
+			* @return Number of child entities.
+			*/
+			unsigned int getNumChildren();
+			
+			/**
+			* Returns the child entity at specified index.
+			* @param index Index to return entity at.
+			* @return Child entity at specified index or NULL of index out of range.
+			*/			
+			Entity *getChildAtIndex(unsigned int index);
 				
 			//@}
 			// ----------------------------------------------------------------------------------------------------------------
@@ -552,6 +565,17 @@ namespace Polycode {
 			//@}
 			// ----------------------------------------------------------------------------------------------------------------
 			
+			/**
+			* Sets user data pointer.
+			* @param userData User data pointer
+			*/
+			void setUserData(void *userData);			
+
+			/**
+			* Returns the user data pointer.
+			* @return User data pointer
+			*/			
+			void *getUserData();
 				
 			void setBlendingMode(int newBlendingMode);
 				
@@ -572,6 +596,9 @@ namespace Polycode {
 			bool isMask;
 		
 		protected:
+		
+			void *userData;
+		
 			std::vector<Entity*> children;
 
 			Vector3 childCenter;

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

@@ -113,7 +113,7 @@ namespace Polycode {
 		void enableAlphaTest(bool val);
 		
 		void createVertexBufferForMesh(Mesh *mesh);
-		void drawVertexBuffer(VertexBuffer *buffer);						
+		void drawVertexBuffer(VertexBuffer *buffer, bool enableColorBuffer);						
 		void bindFrameBufferTexture(Texture *texture);
 		void unbindFramebuffers();
 		

+ 4 - 2
Core/Contents/Include/PolyGLVertexBuffer.h

@@ -49,13 +49,15 @@ namespace Polycode {
 		GLuint getTextCoordBufferID();	
 		GLuint getNormalBufferID();
 		GLuint getColorBufferID();
-		
+		GLuint getTangentBufferID();
+				
 	protected:
 		
 		GLuint vertexBufferID;
 		GLuint texCoordBufferID;
 		GLuint normalBufferID;
-		GLuint colorBufferID;		
+		GLuint colorBufferID;	
+		GLuint tangentBufferID;				
 	};
 	
 }

+ 9 - 1
Core/Contents/Include/PolyGlobals.h

@@ -68,7 +68,15 @@ THE SOFTWARE.
 	#define PLATFORM PLATFORM_UNIX
 #endif
 
+typedef double Number;
+
+inline Number clampf(Number x, Number a, Number b)
+{
+    return x < a ? a : (x > b ? b : x);
+}
+
+#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
+#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
 
 
-typedef double Number;
 

+ 4 - 4
Core/Contents/Include/PolyMaterialManager.h

@@ -51,10 +51,10 @@ namespace Polycode {
 			* Creates a new framebuffer texture.
 			*/ 
 			Texture *createFramebufferTexture(int width, int height, int type);
-			Texture *createTexture(int width, int height, char *imageData, bool clamp=true, bool createMipmaps = true, int type=Image::IMAGE_RGBA);
-			Texture *createNewTexture(int width, int height, bool clamp=true, bool createMipmaps = true, int type=Image::IMAGE_RGBA);
-			Texture *createTextureFromImage(Image *image, bool clamp=true, bool createMipmaps = true);
-			Texture *createTextureFromFile(const String& fileName, bool clamp=true, bool createMipmaps = true);
+			Texture *createTexture(int width, int height, char *imageData, bool clamp=false, bool createMipmaps = true, int type=Image::IMAGE_RGBA);
+			Texture *createNewTexture(int width, int height, bool clamp=false, bool createMipmaps = true, int type=Image::IMAGE_RGBA);
+			Texture *createTextureFromImage(Image *image, bool clamp=false, bool createMipmaps = true);
+			Texture *createTextureFromFile(const String& fileName, bool clamp=false, bool createMipmaps = true);
 			void deleteTexture(Texture *texture);
 		
 			void reloadTextures();

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

@@ -23,12 +23,12 @@ THE SOFTWARE.
 #pragma once
 #include "PolyGlobals.h"
 #include "PolyVertex.h"
+#include "PolyPolygon.h"
 
 class OSFILE;
 
 namespace Polycode {
 	
-	class Polygon;
 	class String;
 
 	class _PolyExport VertexSorter {

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

@@ -160,6 +160,7 @@ namespace Polycode {
 			return entry;			
 		}		
 		
+		void Clear();
 		
 		static const int FLOAT_ENTRY = 0;		
 		static const int INT_ENTRY = 1;

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

@@ -160,7 +160,7 @@ namespace Polycode {
 		virtual void setDepthFunction(int depthFunction) = 0;
 				
 		virtual void createVertexBufferForMesh(Mesh *mesh) = 0;
-		virtual void drawVertexBuffer(VertexBuffer *buffer) = 0;
+		virtual void drawVertexBuffer(VertexBuffer *buffer, bool enableColorBuffer) = 0;
 		
 		void setRenderMode(int newRenderMode);
 		int getRenderMode();

+ 2 - 2
Core/Contents/Include/PolySceneEntity.h

@@ -22,7 +22,7 @@ THE SOFTWARE.
 
 #pragma once
 #include "PolyEntity.h"
-#include "PolyEventHandler.h"
+#include "PolyEventDispatcher.h"
 
 namespace Polycode {
 
@@ -30,7 +30,7 @@ namespace Polycode {
 	* 3D base entity. SceneEntities are the base class for all 3D entities in Polycode. A thin wrapper around Entity, it inherits most of its functionality.
 	@see Entity
 	*/
-	class _PolyExport SceneEntity : public Entity, public EventHandler {
+	class _PolyExport SceneEntity : public Entity, public EventDispatcher {
 		public:
 			SceneEntity();
 			virtual ~SceneEntity();

+ 3 - 0
Core/Contents/Include/PolySceneLine.h

@@ -43,6 +43,9 @@ namespace Polycode {
 			SceneLine(Vector3 start, Vector3 end);
 			~SceneLine();
 			
+			void setStart(Vector3 start);
+			void setEnd(Vector3 end);
+						
 			void Render();
 			
 		protected:		

+ 2 - 2
Core/Contents/Include/PolyScreenEntity.h

@@ -84,7 +84,7 @@ class _PolyExport ScreenEntity : public Entity, public EventDispatcher {
 		*/						
 		Number getRotation() const;
 			
-		bool _onMouseDown(Number x, Number y, int mouseButton, int timestamp);
+		bool _onMouseDown(Number x, Number y, int mouseButton, int timestamp, Vector2 parentAdjust = Vector2(0,0));
 		bool _onMouseUp(Number x, Number y, int mouseButton, int timestamp);
 		void _onMouseMove(Number x, Number y, int timestamp);
 		void _onMouseWheelUp(Number x, Number y, int timestamp);
@@ -115,7 +115,6 @@ class _PolyExport ScreenEntity : public Entity, public EventDispatcher {
 		
 		/**
 		* Returns the height of the screen entity.
-		* @param w New height value.
 		*/											
 		Number getHeight() const;
 	
@@ -171,6 +170,7 @@ class _PolyExport ScreenEntity : public Entity, public EventDispatcher {
 		*/
 		bool snapToPixels;
 
+		bool processInputEvents;
 
 	protected:
 	

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

@@ -23,11 +23,11 @@ THE SOFTWARE.
 #pragma once
 #include "PolyGlobals.h"
 #include "PolyScreenEntity.h"
+#include "PolyMesh.h"
 
 namespace Polycode {
 
 	class Image;
-	class Mesh;
 	class Texture;
 
 	/**

+ 6 - 0
Core/Contents/Include/PolySound.h

@@ -76,6 +76,12 @@ namespace Polycode {
 		* @param newPitch A Number 0-1.
 		*/		
 		void setPitch(Number newPitch);
+		
+		/**
+		* Returns true if the sound is playing.
+		* @return True if sound is playing, false if otherwise.
+		*/
+		bool isPlaying();
 				
 		void setIsPositional(bool isPositional);
 		

+ 13 - 1
Core/Contents/Include/PolyVector2.h

@@ -140,7 +140,19 @@ namespace Polycode {
 			*/
 			inline Number crossProduct( const Vector2& vec2 ) const {
 				return x * vec2.y - y * vec2.x;
-			}			
+			}
+			
+			inline Number angle(const Vector2& vec2 ) const {
+				Number dtheta,theta1,theta2;
+				theta1 = atan2(y,x);
+				theta2 = atan2(vec2.y,vec2.x);
+				dtheta = theta2 - theta1;
+				while (dtheta > PI)
+					dtheta -= PI*2.0;
+				while (dtheta < -PI)
+					dtheta += PI*2.0;
+				return(dtheta);
+			}									
 
 			/**
 			* Normalizes the vector.

+ 13 - 0
Core/Contents/Include/PolyVector3.h

@@ -124,6 +124,19 @@ namespace Polycode {
 			//@}
 			// ----------------------------------------------------------------------------------------------------------------
 	
+			/**
+			* Returns the angle between this and the specified vectors.
+			* @return Angle between the vectors
+			*/
+			inline Number angleBetween(const Vector3& dest) {
+				Number lenProduct = length() * dest.length();
+				if(lenProduct < 1e-6f)
+					lenProduct = 1e-6f;
+				
+				Number f = dot(dest) / lenProduct;
+				f = clampf(f, -1.0, 1.0);
+				return acosf(f);
+			}
 
 			/**
 			* Returns the vector length.

+ 67 - 1
Core/Contents/Include/PolyWinCore.h

@@ -27,10 +27,15 @@
 #include "PolyInputKeys.h"
 #include "PolyRectangle.h"
 
+#include <winsock2.h>
 #include <windows.h>
 #include <windowsx.h>
 #include <WinUser.h>
 
+#include <MMSystem.h>
+#include <regstr.h>
+
+
 #include <vector>
 
 #ifndef VK_0
@@ -108,6 +113,54 @@ namespace Polycode {
 		static const int INPUT_EVENT = 0;
 	};
 	
+	
+	class HIDGamepadAxis {
+		public:
+		//IOHIDElementCookie cookie;
+		//CFIndex logicalMin;
+		//CFIndex logicalMax;
+		bool hasNullState;
+		bool isHatSwitch;
+		bool isHatSwitchSecondAxis;
+	};
+
+	class HIDGamepadButton {
+		public:
+		//IOHIDElementCookie cookie;
+		int something;
+	};	
+	
+class Gamepad_devicePrivate {
+public:
+	UINT joystickID;
+	JOYINFOEX lastState;
+	int xAxisIndex;
+	int yAxisIndex;
+	int zAxisIndex;
+	int rAxisIndex;
+	int uAxisIndex;
+	int vAxisIndex;
+	int povXAxisIndex;
+	int povYAxisIndex;
+	UINT (* axisRanges)[2];
+};
+
+
+	class GamepadDeviceEntry  {
+		public:
+			GamepadDeviceEntry() {
+				numAxes = 0;
+			}
+			std::vector<HIDGamepadAxis> axisElements;
+			std::vector<HIDGamepadButton> buttonElements;			
+			unsigned int deviceID;
+			//IOHIDDeviceRef device;
+			unsigned int numAxes;
+			unsigned int numButtons;	
+			Gamepad_devicePrivate *privateData;
+		//	CoreInput *input;		
+	};
+
 	class _PolyExport Win32Core : public Core {
 		
 	public:
@@ -119,7 +172,7 @@ namespace Polycode {
 		unsigned int getTicks();		
 		bool Update();
 
-		void handleKeyDown(LPARAM lParam, WPARAM wParam);
+		void handleKeyDown(LPARAM lParam, WPARAM wParam, wchar_t unicodeChar);
 		void handleKeyUp(LPARAM lParam, WPARAM wParam);
 		void handleMouseMove(LPARAM lParam, WPARAM wParam);
 		void handleMouseWheel(LPARAM lParam, WPARAM wParam);
@@ -146,6 +199,15 @@ namespace Polycode {
 
 		std::vector<Polycode::Rectangle> getVideoModes();
 
+		void handleAxisChange(GamepadDeviceEntry * device, int axisIndex, DWORD value);
+		void handleButtonChange(GamepadDeviceEntry * device, DWORD lastValue, DWORD value);
+		void handlePOVChange(GamepadDeviceEntry * device, DWORD lastValue, DWORD value);
+
+		void detectGamepads();
+		void initGamepad();
+		void shutdownGamepad();
+		void Gamepad_processEvents();
+
 		// NEED TO IMPLEMENT:
 
 		void setCursor(int cursorType){ }
@@ -160,9 +222,13 @@ namespace Polycode {
 		std::vector<String> openFilePicker(std::vector<CoreFileExtension> extensions, bool allowMultiple) { std::vector<String> ret; return ret;}
 		void resizeTo(int xRes, int yRes) { }
 		
+		std::vector<GamepadDeviceEntry*> gamepads;
+
 	private:
 
+		unsigned int nextDeviceID;
 		PolyKEY keyMap[1024];
+		unsigned int lastGamepadDetect;
 
 		CoreMutex *eventMutex;
 

+ 15 - 2
Core/Contents/PolycodeView/MSVC/PolycodeView.cpp

@@ -65,8 +65,21 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 			core->handleMouseUp(CoreInput::MOUSE_BUTTON3, lParam,wParam);
 	break;
 	case WM_KEYDOWN:
-		if(core)
-			core->handleKeyDown(lParam,wParam);
+		if(core) {
+				wchar_t unicodeChar = 0;
+				MSG m;
+				m.hwnd = hWnd;
+				m.message = message;
+				m.wParam = wParam;
+				m.lParam = lParam;
+				m.time = 0;
+				if ( PeekMessage(&m, hWnd, 0, WM_USER, PM_NOREMOVE) && (m.message == WM_CHAR) ) {
+					GetMessage(&m, hWnd, 0, WM_USER);
+			    		unicodeChar = (wchar_t)m.wParam;
+				}
+
+			core->handleKeyDown(lParam,wParam, unicodeChar);
+		}
 	break;
 	case WM_KEYUP:
 		if(core)

+ 1 - 0
Core/Contents/PolycodeView/MSVC/PolycodeView.h

@@ -1,5 +1,6 @@
 #pragma once
 
+#include <winsock2.h>
 #include <windows.h>
 #include "PolyCore.h"
 

+ 52 - 0
Core/Contents/Source/PolyColor.cpp

@@ -75,6 +75,58 @@ Number Color::getBrightness() const {
 	return (r+g+b) / 3.0f;
 }
 
+void Color::RGBtoHSV(const Number &r, const Number &g, const Number &b, Number &h, Number &s, Number &v) {
+
+	double min, max;
+	double delta;
+
+	min = MIN(r, g);
+	min = MIN(min, b);
+	max = MAX(r, g);
+	max = MAX(max, b);
+
+    v = max;
+
+	s = (max != 0) ? (max - min) / max : 0;
+
+	if (s == 0) {
+                h = 0;
+	} else {
+		delta = max - min;
+		if (r == max) {
+			h = (g - b) / delta;
+		} else if (g == max) {
+			h = 2 + (b - r) / delta;
+		} else if (b == max) {
+			h = 4 + (r - g) / delta;
+		}
+
+		h *= 60;
+		if(h < 0) {
+			h += 360;
+		}
+	}
+}
+
+
+Number Color::getHue() const {
+	Number h,s,v;
+	Color::RGBtoHSV(r,g,b, h,s,v);
+	return h;
+}
+
+Number Color::getSaturation() const {
+	Number h,s,v;
+	Color::RGBtoHSV(r,g,b, h,s,v);
+	return s;
+}
+
+Number Color::getValue() const {
+	Number h,s,v;
+	Color::RGBtoHSV(r,g,b, h,s,v);
+	return v;
+}
+
 void Color::setColorHSV(Number H, Number S, Number V) {
 	Number r,g,b;
     

+ 20 - 0
Core/Contents/Source/PolyEntity.cpp

@@ -25,6 +25,7 @@
 using namespace Polycode;
 
 Entity::Entity() {
+	userData = NULL;
 	scale.set(1,1,1);
 	pitch = 0;
 	yaw = 0;
@@ -55,6 +56,14 @@ Entity::Entity() {
 	hasMask = false;
 }
 
+void Entity::setUserData(void *userData) {
+	this->userData = userData;
+}
+
+void *Entity::getUserData() {
+	return userData;
+}
+
 Entity *Entity::getParentEntity() const {
 	return parentEntity;
 }
@@ -115,6 +124,17 @@ void Entity::removeChild(Entity *entityToRemove) {
 	}	
 }
 
+unsigned int Entity::getNumChildren() {
+	return children.size();
+}
+
+Entity *Entity::getChildAtIndex(unsigned int index) {
+	if(index < children.size()) {
+		return children[index];
+	}
+	return NULL;
+}
+
 void Entity::addChild(Entity *newChild) {
 	addEntity(newChild);
 }

+ 16 - 5
Core/Contents/Source/PolyGLRenderer.cpp

@@ -340,22 +340,30 @@ void OpenGLRenderer::createVertexBufferForMesh(Mesh *mesh) {
 	mesh->setVertexBuffer(buffer);
 }
 
-void OpenGLRenderer::drawVertexBuffer(VertexBuffer *buffer) {
+void OpenGLRenderer::drawVertexBuffer(VertexBuffer *buffer, bool enableColorBuffer) {
 	OpenGLVertexBuffer *glVertexBuffer = (OpenGLVertexBuffer*)buffer;
 
 	glEnableClientState(GL_VERTEX_ARRAY);		
 	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 	glEnableClientState(GL_NORMAL_ARRAY);	
-//	glEnableClientState(GL_COLOR_ARRAY);		
+	
+	if(enableColorBuffer)  {
+		glEnableClientState(GL_COLOR_ARRAY);				
 		
-//	glBindBufferARB( GL_ARRAY_BUFFER_ARB, glVertexBuffer->getColorBufferID());
-//	glTexCoordPointer( 4, GL_FLOAT, 0, (char *) NULL );	
+		glBindBufferARB( GL_ARRAY_BUFFER_ARB, glVertexBuffer->getColorBufferID());
+		glColorPointer( 4, GL_FLOAT, 0, (char *) NULL );	
+	}
 	glBindBufferARB( GL_ARRAY_BUFFER_ARB, glVertexBuffer->getVertexBufferID());
 	glVertexPointer( 3, GL_FLOAT, 0, (char *) NULL );	
 	glBindBufferARB( GL_ARRAY_BUFFER_ARB, glVertexBuffer->getNormalBufferID());
 	glNormalPointer(GL_FLOAT, 0, (char *) NULL );			
 	glBindBufferARB( GL_ARRAY_BUFFER_ARB, glVertexBuffer->getTextCoordBufferID());
 	glTexCoordPointer( 2, GL_FLOAT, 0, (char *) NULL );
+
+	glBindBufferARB( GL_ARRAY_BUFFER_ARB, glVertexBuffer->getTangentBufferID());	
+	glEnableVertexAttribArrayARB(6);	
+	glVertexAttribPointer(6, 3, GL_FLOAT, 0, 0,  (char *)NULL);
+	
 	
 	
 	GLenum mode = GL_TRIANGLES;
@@ -404,7 +412,10 @@ void OpenGLRenderer::drawVertexBuffer(VertexBuffer *buffer) {
 	glDisableClientState( GL_VERTEX_ARRAY);	
 	glDisableClientState( GL_TEXTURE_COORD_ARRAY );		
 	glDisableClientState( GL_NORMAL_ARRAY );
-//	glDisableClientState( GL_COLOR_ARRAY );	
+	
+	if(enableColorBuffer) {
+		glDisableClientState( GL_COLOR_ARRAY );	
+	}
 }
 
 void OpenGLRenderer::enableFog(bool enable) {

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

@@ -70,6 +70,9 @@ GLSLShaderModule::GLSLShaderModule() : PolycodeShaderModule() {
 #ifdef _WINDOWS
 	glUseProgram   = (PFNGLUSEPROGRAMPROC)wglGetProcAddress("glUseProgram");
 	glUniform1i = (PFNGLUNIFORM1IPROC)wglGetProcAddress("glUniform1i");
+	glUniform1f = (PFNGLUNIFORM1FPROC)wglGetProcAddress("glUniform1f");	
+	glUniform3f = (PFNGLUNIFORM3FPROC)wglGetProcAddress("glUniform3f");
+	glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONARBPROC)wglGetProcAddress("glGetUniformLocation");
 	glCreateShader = (PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader");
 	glShaderSource = (PFNGLSHADERSOURCEPROC)wglGetProcAddress("glShaderSource");
 	glCompileShader = (PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader");

+ 26 - 0
Core/Contents/Source/PolyGLVertexBuffer.cpp

@@ -126,6 +126,28 @@ OpenGLVertexBuffer::OpenGLVertexBuffer(Mesh *mesh) : VertexBuffer() {
 	glBufferDataARB(GL_ARRAY_BUFFER_ARB, bufferSize*sizeof(GLfloat), buffer, GL_STATIC_DRAW_ARB);	
 	free(buffer);	
 		
+		
+
+	glGenBuffersARB(1, &tangentBufferID);
+	glBindBufferARB(GL_ARRAY_BUFFER_ARB, tangentBufferID);
+	
+	bufferSize = 0;
+	newBufferSize = 0;		
+	buffer = (GLfloat*)malloc(1);	
+	
+	for(int i=0; i < mesh->getPolygonCount(); i++) {
+		for(int j=0; j < mesh->getPolygon(i)->getVertexCount(); j++) {
+			newBufferSize = bufferSize + 3;			
+			buffer = (GLfloat*)realloc(buffer, newBufferSize * sizeof(GLfloat));		
+			buffer[bufferSize+0] = mesh->getPolygon(i)->getVertex(j)->tangent.x;
+			buffer[bufferSize+1] = mesh->getPolygon(i)->getVertex(j)->tangent.y;
+			buffer[bufferSize+2] = mesh->getPolygon(i)->getVertex(j)->tangent.z;
+			bufferSize = newBufferSize;					
+		}		   
+	}
+	
+	glBufferDataARB(GL_ARRAY_BUFFER_ARB, bufferSize*sizeof(GLfloat), buffer, GL_STATIC_DRAW_ARB);	
+	free(buffer);	
 	
 	glGenBuffersARB(1, &colorBufferID);
 	glBindBufferARB(GL_ARRAY_BUFFER_ARB, colorBufferID);
@@ -173,3 +195,7 @@ GLuint OpenGLVertexBuffer::getTextCoordBufferID() {
 GLuint OpenGLVertexBuffer::getVertexBufferID() {
 	return vertexBufferID;
 }
+
+GLuint OpenGLVertexBuffer::getTangentBufferID() {
+	return tangentBufferID;
+}

+ 3 - 2
Core/Contents/Source/PolyImage.cpp

@@ -455,7 +455,7 @@ void Image::fill(Number r, Number g, Number b, Number a) {
 }
 
 bool Image::saveImage(const String &fileName) {
-	savePNG(fileName);
+	return savePNG(fileName);
 }
 
 
@@ -503,7 +503,7 @@ bool Image::savePNG(const String &fileName) {
 	png_write_info(png_ptr, info_ptr);
 
    png_uint_32 k;
-   png_bytep row_pointers[height];
+   png_bytep *row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
 
    if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
      png_error (png_ptr, "Image is too tall to process in memory");
@@ -515,6 +515,7 @@ bool Image::savePNG(const String &fileName) {
 
    png_write_image(png_ptr, row_pointers);
 
+   free(row_pointers);
    png_free(png_ptr, 0);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose(fp);

+ 5 - 6
Core/Contents/Source/PolyMesh.cpp

@@ -22,7 +22,6 @@
 
 #include "PolyMesh.h"
 #include "PolyLogger.h"
-#include "PolyPolygon.h"
 #include "OSBasics.h"
 
 using std::min;
@@ -256,17 +255,17 @@ namespace Polycode {
 	
 	void Mesh::createVPlane(Number w, Number h) { 
 		Polygon *imagePolygon = new Polygon();
-		imagePolygon->addVertex(0,h,0,0,0);	
-		imagePolygon->addVertex(w,h,0, 1, 0);			
-		imagePolygon->addVertex(w,0,0, 1, 1);		
-		imagePolygon->addVertex(0,0,0,0,1);
+		imagePolygon->addVertex(0,h,0,1,1);	
+		imagePolygon->addVertex(w,h,0, 0, 1);			
+		imagePolygon->addVertex(w,0,0, 0, 0);		
+		imagePolygon->addVertex(0,0,0,1,0);
 
 		addPolygon(imagePolygon);
 		
 		for(int i=0; i < polygons.size(); i++) {
 			for(int j=0; j < polygons[i]->getVertexCount(); j++) {
 				polygons[i]->getVertex(j)->x = polygons[i]->getVertex(j)->x - (w/2.0f);
-				polygons[i]->getVertex(j)->z = polygons[i]->getVertex(j)->y - (h/2.0f);
+				polygons[i]->getVertex(j)->y = polygons[i]->getVertex(j)->y - (h/2.0f);
 			}
 		}
 

+ 8 - 0
Core/Contents/Source/PolyObject.cpp

@@ -25,6 +25,14 @@
 
 using namespace Polycode;
 
+void ObjectEntry::Clear() {
+	for(int i=0; i < children.size(); i++) {
+		children[i]->Clear();
+		delete children[i];
+	}
+	children.clear();
+}
+
 Object::Object() {
 	
 }

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

@@ -278,6 +278,7 @@ void ParticleEmitter::resetParticle(Particle *particle) {
 	Matrix4 concatMatrix = getBaseMatrix();
 	Vector3	startVector;
 	
+	particle->dirVector = dirVector;
 //	if(emitterMesh) {
 //		Polygon *randPoly = emitterMesh->getMesh()->getPolygon(rand() % emitterMesh->getMesh()->getPolygonCount());		
 //		startVector = *randPoly->getVertex(rand() % 3);

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

@@ -24,7 +24,7 @@
 
 using namespace Polycode;
 
-SceneEntity::SceneEntity() : EventHandler(), Entity() {
+SceneEntity::SceneEntity() : EventDispatcher(), Entity() {
 	castShadows = true;
 }
 

+ 7 - 0
Core/Contents/Source/PolySceneLine.cpp

@@ -62,6 +62,13 @@ SceneLine::~SceneLine() {
 
 }
 
+void SceneLine::setStart(Vector3 start) {
+	this->start = start;
+}
+
+void SceneLine::setEnd(Vector3 end) {
+	this->end = end;
+}
 
 void SceneLine::Render() {	
 

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

@@ -236,7 +236,7 @@ void SceneMesh::Render() {
 	}
 	
 	if(useVertexBuffer) {
-		renderer->drawVertexBuffer(mesh->getVertexBuffer());
+		renderer->drawVertexBuffer(mesh->getVertexBuffer(), mesh->useVertexColors);
 	} else {
 		renderMeshLocally();
 	}

+ 123 - 85
Core/Contents/Source/PolyScreenEntity.cpp

@@ -23,6 +23,8 @@
 #include "PolyScreenEntity.h"
 #include "PolyInputEvent.h"
 #include "PolyRectangle.h"
+#include "PolyPolygon.h"
+#include "PolyVertex.h"
 #include "PolyRenderer.h"
 
 inline double round(double x) { return floor(x + 0.5); }
@@ -62,6 +64,8 @@ ScreenEntity::ScreenEntity() : Entity(), EventDispatcher() {
 	xmouse = 0;
 	ymouse = 0;
 	
+	processInputEvents = false;
+	
 }
 
 void ScreenEntity::focusNextChild() {
@@ -154,30 +158,59 @@ Number ScreenEntity::getHeight() const {
 	return height;
 }
 
-bool ScreenEntity::hitTest(Number x, Number y) const {
-	bool retVal = false;
-    // apply compound scale to test hit against
-    Vector3 compScale = getCompoundScale();
-    Number hx = position.x * compScale.x;
-    Number hy = position.y * compScale.y;
-    Number hw = hitwidth * compScale.x;
-    Number hh = hitheight * compScale.y;
-    //        Logger::log("hittest %f,%f in %f %f %f %f\n",x, y, hx, hy, hw, hh);
-	switch(positionMode) {
-		case ScreenEntity::POSITION_TOPLEFT:
-						
-            if(x > hx && x < (hx + hw)
-                && y > hy && y < (hy + hh))
-				retVal = true;			
-		break;
-		case ScreenEntity::POSITION_CENTER:
-            if(x > (hx - hw/2.0f) && x < (hx + hw/2.0f)
-                && y > (hy - hh/2.0f) && y < (hy + hh/2.0f))
-				retVal = true;	
-		break;
+bool isPointInsidePolygon2D(Polycode::Polygon *poly, const Vector2 &p) {
+	Number angle = 0.0;
+	Vector2 p1,p2;
+/*	
+	printf("PIP: %f,%f in [%f,%f], [%f,%f], [%f,%f], [%f,%f]\n", p.x, p.y, 
+		poly->getVertex(0)->x, poly->getVertex(0)->y,
+		poly->getVertex(1)->x, poly->getVertex(1)->y,
+		poly->getVertex(2)->x, poly->getVertex(2)->y,
+		poly->getVertex(3)->x, poly->getVertex(3)->y);
+*/
+	for (int i=0; i < poly->getVertexCount(); i++) {
+
+		p1.x = poly->getVertex(i)->x - p.x;
+		p1.y = poly->getVertex(i)->y - p.y;
+		p2.x = poly->getVertex((i+1)%poly->getVertexCount())->x - p.x;
+		p2.y = poly->getVertex((i+1)%poly->getVertexCount())->y - p.y;
+		
+		Vector2 vec(p1.x,p1.y);
+		angle += vec.angle(Vector2(p2.x,p2.y));
+
 	}
 
-	return retVal;
+	if (fabs(angle) < PI)
+		return false;
+	else
+		return true;
+}
+
+bool ScreenEntity::hitTest(const Number x, const Number y) const {
+
+	Vector3 v;	
+	Polygon testPoly;
+	
+	Matrix4 transformMatrix = getConcatenatedMatrix();
+	
+	v = Vector3(-hitwidth/2.0, -hitheight/2.0,0);
+	v = transformMatrix * v;	
+	testPoly.addVertex(v.x, v.y, 0.0);
+	
+	v = Vector3(hitwidth/2.0, -hitheight/2.0,0);
+	v = transformMatrix * v;	
+	testPoly.addVertex(v.x, v.y, 0.0);
+
+	v = Vector3(hitwidth/2.0, hitheight/2.0,0);
+	v = transformMatrix * v;	
+	testPoly.addVertex(v.x, v.y, 0.0);
+
+	v = Vector3(-hitwidth/2.0,hitheight/2.0,0);
+	v = transformMatrix * v;	
+	testPoly.addVertex(v.x, v.y, 0.0);
+		
+	return isPointInsidePolygon2D(&testPoly, Vector2(x,y));
+	
 }
 
 void ScreenEntity::setPositionMode(int newPositionMode) {
@@ -228,11 +261,11 @@ void ScreenEntity::_onMouseMove(Number x, Number y, int timestamp) {
 		}
 	}
 	
-	xmouse = x-position.x;
-	ymouse = y-position.y;
+	xmouse = x;
+	ymouse = y;
 
 	onMouseMove(x,y);
-	if(enabled) {
+	if(processInputEvents && enabled) {
 		if(hitTest(x,y)) {
 			dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEMOVE);
 			if(!mouseOver) {
@@ -249,31 +282,57 @@ void ScreenEntity::_onMouseMove(Number x, Number y, int timestamp) {
 	
 	if(enabled) {
 		for(int i=0;i<children.size();i++) {
-			((ScreenEntity*)children[i])->_onMouseMove(x-position.x,y-position.y, timestamp);
+			((ScreenEntity*)children[i])->_onMouseMove(x,y, timestamp);
 		}
 	}
 }
 
 bool ScreenEntity::_onMouseUp(Number x, Number y, int mouseButton, int timestamp) {
 	bool retVal = false;
-	if(hitTest(x,y) && enabled) {
-		onMouseUp(x,y);
+	
+	if(processInputEvents && enabled) {	
+	if(hitTest(x,y)) {
+	
+		Vector3 localCoordinate = Vector3(x,y,0);
+		
+		Matrix4 inverse = getConcatenatedMatrix().inverse();
+		localCoordinate = inverse * localCoordinate;
+		if(positionMode == POSITION_TOPLEFT)
+			localCoordinate.x += hitwidth/2.0;
+		if(positionMode == POSITION_TOPLEFT)
+			localCoordinate.y += hitheight/2.0;
+	
+		onMouseUp(localCoordinate.x,localCoordinate.y);
 		
-		InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);		
+		InputEvent *inputEvent = new InputEvent(Vector2(localCoordinate.x,localCoordinate.y), timestamp);		
 		inputEvent->mouseButton = mouseButton;		
 		dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEUP);
 		retVal = true;		
 	} else {
 		
-		InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);		
+		Vector3 localCoordinate = Vector3(x,y,0);
+		
+		Matrix4 inverse = getConcatenatedMatrix().inverse();
+		localCoordinate = inverse * localCoordinate;
+		if(positionMode == POSITION_TOPLEFT)
+			localCoordinate.x += hitwidth/2.0;
+		if(positionMode == POSITION_TOPLEFT)
+			localCoordinate.y += hitheight/2.0;
+	
+		
+		InputEvent *inputEvent = new InputEvent(Vector2(localCoordinate.x,localCoordinate.y), timestamp);		
 		inputEvent->mouseButton = mouseButton;
 		
 		dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEUP_OUTSIDE);
 	}
-	
+	}
 	if(enabled) {
+		Vector2 adjust;
+		if(positionMode == POSITION_TOPLEFT)
+			adjust = Vector2(width/2.0, height/2.0);
+	
 		for(int i=0;i<children.size();i++) {
-			((ScreenEntity*)children[i])->_onMouseUp(x-position.x,y-position.y, mouseButton, timestamp);
+			((ScreenEntity*)children[i])->_onMouseUp(x+adjust.x,y+adjust.y, mouseButton, timestamp);
 		}
 	}
 	return retVal;
@@ -283,7 +342,7 @@ void ScreenEntity::_onMouseWheelUp(Number x, Number y, int timestamp) {
 	bool doTest = true;
 	
 	if(hasMask) {
-		if(!((ScreenEntity*)maskEntity)->hitTest(x-position.x,y-position.y)) {
+		if(!((ScreenEntity*)maskEntity)->hitTest(x,y)) {
 			doTest = false;
 		}	
 	}
@@ -295,9 +354,9 @@ void ScreenEntity::_onMouseWheelUp(Number x, Number y, int timestamp) {
 		}
 		if(enabled) {
 			for(int i=children.size()-1;i>=0;i--) {				
-				((ScreenEntity*)children[i])->_onMouseWheelUp(x-position.x,y-position.y, timestamp);
+				((ScreenEntity*)children[i])->_onMouseWheelUp(x,y, timestamp);
 				if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
-					if(((ScreenEntity*)children[i])->hitTest(x-position.x,y-position.y))
+					if(((ScreenEntity*)children[i])->hitTest(x,y))
 						break;
 				}
 			}
@@ -309,7 +368,7 @@ void ScreenEntity::_onMouseWheelDown(Number x, Number y, int timestamp) {
 	bool doTest = true;
 	
 	if(hasMask) {
-		if(!((ScreenEntity*)maskEntity)->hitTest(x-position.x,y-position.y)) {
+		if(!((ScreenEntity*)maskEntity)->hitTest(x,y)) {
 			doTest = false;
 		}	
 	}
@@ -321,9 +380,9 @@ void ScreenEntity::_onMouseWheelDown(Number x, Number y, int timestamp) {
 		}
 		if(enabled) {
 			for(int i=children.size()-1;i>=0;i--) {				
-				((ScreenEntity*)children[i])->_onMouseWheelDown(x-position.x,y-position.y, timestamp);
+				((ScreenEntity*)children[i])->_onMouseWheelDown(x,y, timestamp);
 				if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
-					if(((ScreenEntity*)children[i])->hitTest(x-position.x,y-position.y))
+					if(((ScreenEntity*)children[i])->hitTest(x,y))
 						break;
 				}
 			}
@@ -332,22 +391,34 @@ void ScreenEntity::_onMouseWheelDown(Number x, Number y, int timestamp) {
 }
 
 
-bool ScreenEntity::_onMouseDown(Number x, Number y, int mouseButton, int timestamp) {
+bool ScreenEntity::_onMouseDown(Number x, Number y, int mouseButton, int timestamp, Vector2 parentAdjust) {
 	bool retVal = false;
 	
-	bool doTest = true;
+	bool doTest = true;	
 	
 	if(hasMask) {
-		if(!((ScreenEntity*)maskEntity)->hitTest(x,y)) {
+		if(!((ScreenEntity*)maskEntity)->hitTest(x+parentAdjust.x,y+parentAdjust.y)) {
 			doTest = false;
 		}	
 	}
 	
 	if(doTest) {
-	if(hitTest(x,y) && enabled) {
-		onMouseDown(x,y);
+	if(processInputEvents && enabled) {
+	if(hitTest(x+parentAdjust.x,y+parentAdjust.y)) {
+		Vector3 localCoordinate = Vector3(x+(parentAdjust.x*2.0),y+(parentAdjust.y*2.0),0);
+		
+		Matrix4 inverse = getConcatenatedMatrix().inverse();
+		localCoordinate = inverse * localCoordinate;
+		if(positionMode == POSITION_TOPLEFT)
+			localCoordinate.x += hitwidth/2.0;
+		if(positionMode == POSITION_TOPLEFT)
+			localCoordinate.y += hitheight/2.0;
+
+		
+		onMouseDown(localCoordinate.x,localCoordinate.y);
+		
+		InputEvent *inputEvent = new InputEvent(Vector2(localCoordinate.x,localCoordinate.y)-parentAdjust, timestamp);
 		
-		InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);		
 		inputEvent->mouseButton = mouseButton;
 		dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEDOWN);
 		
@@ -359,12 +430,15 @@ bool ScreenEntity::_onMouseDown(Number x, Number y, int mouseButton, int timesta
 		lastClickTicks = timestamp;		
 		retVal = true;
 	}
+	}
 	if(enabled) {
-		for(int i=children.size()-1;i>=0;i--) {
-			
-			((ScreenEntity*)children[i])->_onMouseDown(x-position.x,y-position.y, mouseButton, timestamp);
+		for(int i=children.size()-1;i>=0;i--) {			
+			Vector2 adjust = parentAdjust;
+			if(positionMode == POSITION_TOPLEFT)
+				adjust += Vector2(width/2.0, height/2.0);
+			((ScreenEntity*)children[i])->_onMouseDown(x,y, mouseButton, timestamp, adjust);
 			if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
-				if(((ScreenEntity*)children[i])->hitTest(x-position.x,y-position.y))
+				if(((ScreenEntity*)children[i])->hitTest(x,y))
 				   break;
 			}
 		}
@@ -386,7 +460,6 @@ Matrix4 ScreenEntity::buildPositionMatrix() {
 	Matrix4 posMatrix;
 	switch(positionMode) {
 		case POSITION_TOPLEFT:
-//			renderer->translate2D(position.x+ceil(width/2.0f)*scale->x, position.y+ceil(height/2.0f)*scale->y);
 			posMatrix.m[3][0] = (position.x+floor(width/2.0f)*scale.x)*matrixAdj;
 			posMatrix.m[3][1] = (position.y+floor(height/2.0f)*scale.y)*matrixAdj;
 			posMatrix.m[3][2] = position.z*matrixAdj;			
@@ -411,39 +484,4 @@ Matrix4 ScreenEntity::buildPositionMatrix() {
 void ScreenEntity::adjustMatrixForChildren() {
 	if(positionMode == POSITION_TOPLEFT)
 		renderer->translate2D(-floor(width/2.0f), -floor(height/2.0f));	
-}
-
-/*
-void ScreenEntity::transformAndRender() {
-
-	Update();
-
-	if(!renderer || !visible)
-		return;
-
-	renderer->pushMatrix();
-	switch(positionMode) {
-		case POSITION_TOPLEFT:
-			renderer->translate2D(position.x+ceil(width/2.0f)*scale->x, position.y+ceil(height/2.0f)*scale->y);
-		break;
-		case POSITION_CENTER:
-			renderer->translate2D(position.x, position.y);
-		break;
-	}
-	renderer->scale2D(scale);
-	renderer->rotate2D(rotation);
-	if(parentEntity) {
-		Color combined = getCombinedColor();
-		renderer->setVertexColor(combined.r,combined.g,combined.b,combined.a);
-	} else {
-		renderer->setVertexColor(color.r,color.g,color.b,color.a);
-	}
-	
-	renderer->setBlendingMode(blendingMode);
-	Render();
-	if(positionMode == POSITION_TOPLEFT)
-		renderer->translate2D(-ceil(width/2.0f)*scale->x, -ceil(height/2.0f)*scale->y);
-	renderChildren();
-	renderer->popMatrix();
-}
-*/
+}

+ 7 - 0
Core/Contents/Source/PolySound.cpp

@@ -112,6 +112,13 @@ void Sound::Play(bool loop) {
 	alSourcePlay(soundSource);
 }
 
+bool Sound::isPlaying() {
+	ALenum state;
+	alGetSourcei(soundSource, AL_SOURCE_STATE, &state);
+	return (state == AL_PLAYING);
+}
+
+
 void Sound::setVolume(Number newVolume) {
 	alSourcef(soundSource, AL_GAIN, newVolume);
 }

+ 236 - 8
Core/Contents/Source/PolyWinCore.cpp

@@ -60,7 +60,9 @@ Win32Core::Win32Core(PolycodeViewBase *view, int xRes, int yRes, bool fullScreen
 
 	hWnd = *((HWND*)view->windowData);
 	core = this;
+
 	initKeymap();
+	initGamepad();
 
 	hDC = NULL;
 	hRC = NULL;
@@ -78,10 +80,10 @@ Win32Core::Win32Core(PolycodeViewBase *view, int xRes, int yRes, bool fullScreen
 
 	setVideoMode(xRes, yRes, fullScreen, vSync, aaLevel, anisotropyLevel);
 		
-//	WSADATA WsaData;
-///	if(WSAStartup( MAKEWORD(2,2), &WsaData ) != NO_ERROR ){
-//		Logger::log("Error initializing sockets!\n");
-//	}
+	WSADATA WsaData;
+	if(WSAStartup( MAKEWORD(2,2), &WsaData ) != NO_ERROR ){
+		Logger::log("Error initializing sockets!\n");
+	}
 
 	((OpenGLRenderer*)renderer)->initOSSpecific();
 
@@ -89,6 +91,7 @@ Win32Core::Win32Core(PolycodeViewBase *view, int xRes, int yRes, bool fullScreen
 }
 
 Win32Core::~Win32Core() {
+	shutdownGamepad();
 	destroyContext();
 }
 
@@ -105,6 +108,7 @@ bool Win32Core::Update() {
 		return false;
 
 	checkEvents();
+	Gamepad_processEvents();
 
 	renderer->BeginRender();
 	updateCore();
@@ -234,7 +238,6 @@ void Win32Core::initMultisample(int numSamples) {
 		return;
 	}
 	int pixelFormat;
-	bool valid;
 	UINT numFormats;
 	float fAttributes[] = {0,0};
 
@@ -406,13 +409,13 @@ PolyKEY Win32Core::mapKey(LPARAM lParam, WPARAM wParam) {
 	return keyMap[(unsigned int)wParam];
 }
 
-void Win32Core::handleKeyDown(LPARAM lParam, WPARAM wParam) {
+void Win32Core::handleKeyDown(LPARAM lParam, WPARAM wParam, wchar_t unicodeChar) {
 	lockMutex(eventMutex);
 	Win32Event newEvent;
 	newEvent.eventGroup = Win32Event::INPUT_EVENT;
 	newEvent.eventCode = InputEvent::EVENT_KEYDOWN;
 	newEvent.keyCode = mapKey(lParam, wParam);
-	newEvent.unicodeChar = ' ';
+	newEvent.unicodeChar = unicodeChar;
 	win32Events.push_back(newEvent);
 	unlockMutex(eventMutex);
 }
@@ -423,7 +426,7 @@ void Win32Core::handleKeyUp(LPARAM lParam, WPARAM wParam) {
 	newEvent.eventGroup = Win32Event::INPUT_EVENT;
 	newEvent.eventCode = InputEvent::EVENT_KEYUP;
 	newEvent.keyCode = mapKey(lParam, wParam);
-	newEvent.unicodeChar = ' ';
+	newEvent.unicodeChar = 0;
 	win32Events.push_back(newEvent);
 	unlockMutex(eventMutex);
 }
@@ -511,6 +514,231 @@ void Win32Core::checkEvents() {
 	unlockMutex(eventMutex);		
 }
 
+void Win32Core::handleAxisChange(GamepadDeviceEntry * device, int axisIndex, DWORD value) {
+	if (axisIndex < 0 || axisIndex >= (int) device->numAxes) {
+		return;
+	}	
+	Gamepad_devicePrivate *devicePrivate = device->privateData;
+	float floatVal = (value - devicePrivate->axisRanges[axisIndex][0]) / (float) (devicePrivate->axisRanges[axisIndex][1] - devicePrivate->axisRanges[axisIndex][0]) * 2.0f - 1.0f;
+	input->joystickAxisMoved(axisIndex, floatVal, device->deviceID);	
+}
+
+void Win32Core::handleButtonChange(GamepadDeviceEntry * device, DWORD lastValue, DWORD value) {
+	Gamepad_devicePrivate *devicePrivate = device->privateData;
+	unsigned int buttonIndex;	
+	for (buttonIndex = 0; buttonIndex < device->numButtons; buttonIndex++) {
+		if ((lastValue ^ value) & (1 << buttonIndex)) {
+			if(!!(value & (1 << buttonIndex))) {
+				input->joystickButtonDown(buttonIndex, device->deviceID);
+			} else {
+				input->joystickButtonUp(buttonIndex, device->deviceID);
+			}
+		}
+	}
+}
+
+static void povToXY(DWORD pov, int * outX, int * outY) {
+	if (pov == JOY_POVCENTERED) {
+		*outX = *outY = 0;
+		
+	} else {
+		if (pov > JOY_POVFORWARD && pov < JOY_POVBACKWARD) {
+			*outX = 1;
+			
+		} else if (pov > JOY_POVBACKWARD) {
+			*outX = -1;
+			
+		} else {
+			*outX = 0;
+		}
+		
+		if (pov > JOY_POVLEFT || pov < JOY_POVRIGHT) {
+			*outY = -1;
+			
+		} else if (pov > JOY_POVRIGHT && pov < JOY_POVLEFT) {
+			*outY = 1;
+			
+		} else {
+			*outY = 0;
+		}
+	}
+}
+
+void Win32Core::handlePOVChange(GamepadDeviceEntry * device, DWORD lastValue, DWORD value) {
+	
+	Gamepad_devicePrivate *devicePrivate = device->privateData;
+	
+	int lastX, lastY, newX, newY;
+
+	if (devicePrivate->povXAxisIndex == -1 || devicePrivate->povYAxisIndex == -1) {
+		return;
+	}
+	
+	povToXY(lastValue, &lastX, &lastY);
+	povToXY(value, &newX, &newY);
+	
+	if (newX != lastX) {
+		input->joystickAxisMoved(devicePrivate->povXAxisIndex, newX, device->deviceID);
+	}
+
+	if (newY != lastY) {
+		input->joystickAxisMoved(devicePrivate->povYAxisIndex, newY, device->deviceID);
+	}
+}
+
+
+void Win32Core::Gamepad_processEvents() {
+
+	if(getTicks() > lastGamepadDetect + 3000) {
+			detectGamepads();
+	}
+
+	unsigned int deviceIndex;
+	JOYINFOEX info;
+	MMRESULT result;
+	GamepadDeviceEntry * device;
+	Gamepad_devicePrivate * devicePrivate;
+	
+	for (deviceIndex = 0; deviceIndex < gamepads.size(); deviceIndex++) {
+		device = gamepads[deviceIndex];
+		devicePrivate = device->privateData;
+		
+		info.dwSize = sizeof(info);
+		info.dwFlags = JOY_RETURNALL;
+		result = joyGetPosEx(devicePrivate->joystickID, &info);
+		if (result == JOYERR_UNPLUGGED) {
+
+			input->removeJoystick(device->deviceID);
+			gamepads.erase(gamepads.begin() + deviceIndex);
+			
+		} else if (result == JOYERR_NOERROR) {
+			if (info.dwXpos != devicePrivate->lastState.dwXpos) {
+				handleAxisChange(device, devicePrivate->xAxisIndex, info.dwXpos);
+			}
+			if (info.dwYpos != devicePrivate->lastState.dwYpos) {
+				handleAxisChange(device, devicePrivate->yAxisIndex, info.dwYpos);
+			}
+			if (info.dwZpos != devicePrivate->lastState.dwZpos) {
+				handleAxisChange(device, devicePrivate->zAxisIndex, info.dwZpos);
+			}
+			if (info.dwRpos != devicePrivate->lastState.dwRpos) {
+				handleAxisChange(device, devicePrivate->rAxisIndex, info.dwRpos);
+			}
+			if (info.dwUpos != devicePrivate->lastState.dwUpos) {
+				handleAxisChange(device, devicePrivate->uAxisIndex, info.dwUpos);
+			}
+			if (info.dwVpos != devicePrivate->lastState.dwVpos) {
+				handleAxisChange(device, devicePrivate->vAxisIndex, info.dwVpos);
+			}
+			if (info.dwPOV != devicePrivate->lastState.dwPOV) {
+				handlePOVChange(device, devicePrivate->lastState.dwPOV, info.dwPOV);
+			}
+			if (info.dwButtons != devicePrivate->lastState.dwButtons) {
+				handleButtonChange(device, devicePrivate->lastState.dwButtons, info.dwButtons);
+			}
+			devicePrivate->lastState = info;
+		}
+	}
+}
+
+void Win32Core::detectGamepads() {
+
+	lastGamepadDetect = getTicks();
+
+	unsigned int numPadsSupported;
+	unsigned int deviceIndex, deviceIndex2;
+	JOYINFOEX info;
+	JOYCAPS caps;
+	bool duplicate;
+	Gamepad_devicePrivate * deviceRecordPrivate;
+	UINT joystickID;
+	int axisIndex;
+	
+	numPadsSupported = joyGetNumDevs();
+	for (deviceIndex = 0; deviceIndex < numPadsSupported; deviceIndex++) {
+		info.dwSize = sizeof(info);
+		info.dwFlags = JOY_RETURNALL;
+		joystickID = JOYSTICKID1 + deviceIndex;
+		if (joyGetPosEx(joystickID, &info) == JOYERR_NOERROR &&
+		    joyGetDevCaps(joystickID, &caps, sizeof(JOYCAPS)) == JOYERR_NOERROR) {
+			
+			duplicate = false;
+			for (deviceIndex2 = 0; deviceIndex2 < gamepads.size(); deviceIndex2++) {
+				if (((Gamepad_devicePrivate *) gamepads[deviceIndex2]->privateData)->joystickID == joystickID) {
+					duplicate = true;
+					break;
+				}
+			}
+			if (duplicate) {
+				continue;
+			}
+			
+			GamepadDeviceEntry *deviceRecord = new GamepadDeviceEntry();
+			deviceRecord->deviceID = nextDeviceID++;
+//			deviceRecord->description = getDeviceDescription(joystickID, caps);
+//			deviceRecord->vendorID = caps.wMid;
+//			deviceRecord->productID = caps.wPid;
+			deviceRecord->numAxes = caps.wNumAxes + ((caps.wCaps & JOYCAPS_HASPOV) ? 2 : 0);
+			deviceRecord->numButtons = caps.wNumButtons;
+//			deviceRecord->axisStates = calloc(sizeof(float), deviceRecord->numAxes);
+//			deviceRecord->buttonStates = calloc(sizeof(bool), deviceRecord->numButtons);
+//			deviceRecord->eventDispatcher = EventDispatcher_create(deviceRecord);
+//			devices = realloc(devices, sizeof(struct Gamepad_device *) * (numDevices + 1));
+			gamepads.push_back(deviceRecord);
+			
+			deviceRecordPrivate = new Gamepad_devicePrivate();
+			deviceRecordPrivate->joystickID = joystickID;
+			deviceRecordPrivate->lastState = info;
+			
+			deviceRecordPrivate->xAxisIndex = 0;
+			deviceRecordPrivate->yAxisIndex = 1;
+			axisIndex = 2;
+			deviceRecordPrivate->zAxisIndex = (caps.wCaps & JOYCAPS_HASZ) ? axisIndex++ : -1;
+			deviceRecordPrivate->rAxisIndex = (caps.wCaps & JOYCAPS_HASR) ? axisIndex++ : -1;
+			deviceRecordPrivate->uAxisIndex = (caps.wCaps & JOYCAPS_HASU) ? axisIndex++ : -1;
+			deviceRecordPrivate->vAxisIndex = (caps.wCaps & JOYCAPS_HASV) ? axisIndex++ : -1;
+			
+			deviceRecordPrivate->axisRanges = (UINT (*)[2]) malloc(sizeof(UINT[2]) * axisIndex);
+			deviceRecordPrivate->axisRanges[0][0] = caps.wXmin;
+			deviceRecordPrivate->axisRanges[0][1] = caps.wXmax;
+			deviceRecordPrivate->axisRanges[1][0] = caps.wYmin;
+			deviceRecordPrivate->axisRanges[1][1] = caps.wYmax;
+			if (deviceRecordPrivate->zAxisIndex != -1) {
+				deviceRecordPrivate->axisRanges[deviceRecordPrivate->zAxisIndex][0] = caps.wZmin;
+				deviceRecordPrivate->axisRanges[deviceRecordPrivate->zAxisIndex][1] = caps.wZmax;
+			}
+			if (deviceRecordPrivate->rAxisIndex != -1) {
+				deviceRecordPrivate->axisRanges[deviceRecordPrivate->rAxisIndex][0] = caps.wRmin;
+				deviceRecordPrivate->axisRanges[deviceRecordPrivate->rAxisIndex][1] = caps.wRmax;
+			}
+			if (deviceRecordPrivate->uAxisIndex != -1) {
+				deviceRecordPrivate->axisRanges[deviceRecordPrivate->uAxisIndex][0] = caps.wUmin;
+				deviceRecordPrivate->axisRanges[deviceRecordPrivate->uAxisIndex][1] = caps.wUmax;
+			}
+			if (deviceRecordPrivate->vAxisIndex != -1) {
+				deviceRecordPrivate->axisRanges[deviceRecordPrivate->vAxisIndex][0] = caps.wVmin;
+				deviceRecordPrivate->axisRanges[deviceRecordPrivate->vAxisIndex][1] = caps.wVmax;
+			}
+			
+			deviceRecordPrivate->povXAxisIndex = (caps.wCaps & JOYCAPS_HASPOV) ? axisIndex++ : -1;
+			deviceRecordPrivate->povYAxisIndex = (caps.wCaps & JOYCAPS_HASPOV) ? axisIndex++ : -1;
+			
+			deviceRecord->privateData = deviceRecordPrivate;
+			
+			input->addJoystick(deviceRecord->deviceID);
+		}
+	}
+}
+
+void Win32Core::initGamepad() {
+	nextDeviceID = 0;
+	detectGamepads();
+}
+
+void Win32Core::shutdownGamepad() {
+
+}
+
 DWORD WINAPI Win32LaunchThread(LPVOID data) {
 	Threaded *threaded = (Threaded*)data;
 	threaded->runThread();

+ 1 - 1
Examples/C++/Build/Linux/Makefile

@@ -1,6 +1,6 @@
 CC=g++
 CFLAGS=-I../../Core/Dependencies/include -I../../Core/Dependencies/include/AL -I../../Core/include -I../../Modules/include -I../../Modules/Dependencies/include -I../../Modules/Dependencies/include/bullet
-LDFLAGS=-lrt -ldl -lpthread ../../Core/lib/libPolycore.a ../../Core/Dependencies/lib/libfreetype.a ../../Core/Dependencies/lib/liblibvorbisfile.a ../../Core/Dependencies/lib/liblibvorbis.a ../../Core/Dependencies/lib/liblibogg.a ../../Core/Dependencies/lib/libopenal.a ../../Core/Dependencies/lib/libphysfs.a ../../Core/Dependencies/lib/libpng15.a ../../Core/Dependencies/lib/libz.a -lGL -lGLU -lSDL ../../Modules/lib/libPolycode2DPhysics.a ../../Modules/Dependencies/lib/libBox2D.a ../../Modules/lib/libPolycode3DPhysics.a ../../Modules/Dependencies/lib/libBulletDynamics.a ../../Modules/Dependencies/lib/libBulletCollision.a ../../Modules/Dependencies/lib/libLinearMath.a ../../Modules/lib/libPolycodeNetworking.a
+LDFLAGS=-lrt -ldl -lpthread ../../Core/lib/libPolycore.a ../../Core/Dependencies/lib/libfreetype.a ../../Core/Dependencies/lib/liblibvorbisfile.a ../../Core/Dependencies/lib/liblibvorbis.a ../../Core/Dependencies/lib/liblibogg.a ../../Core/Dependencies/lib/libopenal.so ../../Core/Dependencies/lib/libphysfs.a ../../Core/Dependencies/lib/libpng15.a ../../Core/Dependencies/lib/libz.a -lGL -lGLU -lSDL ../../Modules/lib/libPolycode2DPhysics.a ../../Modules/Dependencies/lib/libBox2D.a ../../Modules/lib/libPolycode3DPhysics.a ../../Modules/Dependencies/lib/libBulletDynamics.a ../../Modules/Dependencies/lib/libBulletCollision.a ../../Modules/Dependencies/lib/libLinearMath.a ../../Modules/lib/libPolycodeNetworking.a
 
 default: 2DAudio 2DParticles 2DPhysics_Basic 2DPhysics_CollisionOnly 2DPhysics_Contacts 2DPhysics_Joints 2DPhysics_PointCollision 2DShapes 2DTransforms 3DAudio 3DBasics 3DMeshParticles 3DParticles 3DPhysics_Basic 3DPhysics_Character 3DPhysics_CollisionOnly 3DPhysics_Contacts 3DPhysics_RayTest 3DPhysics_Vehicle AdvancedLighting BasicImage BasicLighting BasicText EventHandling KeyboardInput MouseInput Networking_Client Networking_Server PlayingSounds ScreenEntities ScreenSprites SkeletalAnimation UpdateLoop  
 

+ 4 - 3
Examples/C++/Contents/2DParticles/HelloPolycodeApp.cpp

@@ -12,9 +12,10 @@ HelloPolycodeApp::HelloPolycodeApp(PolycodeView *view) {
 	CoreServices::getInstance()->getResourceManager()->addDirResource("default", false);
 	
 	Screen *screen = new Screen();	
-	ScreenParticleEmitter *emitter = new ScreenParticleEmitter("Resources/particle.png", screen,
-		 Particle::BILLBOARD_PARTICLE, ParticleEmitter::CONTINUOUS_EMITTER, 4, 200,
-		Vector3(0.0,-50.0,0.0), Vector3(0.0,0.0,0.0), Vector3(20.5, 40.0, 0.0));
+	ScreenParticleEmitter *emitter = new ScreenParticleEmitter("Resources/particle.png", 
+		screen, Particle::BILLBOARD_PARTICLE, ParticleEmitter::CONTINUOUS_EMITTER, 4, 200, 
+		Vector3(0.0,-50.0,0.0), Vector3(0.0,0.0,0.0), Vector3(20.5, 40.0, 0.0), 
+		Vector3(1.5,1.5,1.5));
 	
 	emitter->useScaleCurves = true;
 	emitter->scaleCurve.addControlPoint2d(0, 0.3);

+ 2 - 1
Examples/C++/Contents/3DMeshParticles/HelloPolycodeApp.cpp

@@ -27,7 +27,8 @@ HelloPolycodeApp::HelloPolycodeApp(PolycodeView *view) {
 	
 	SceneParticleEmitter *emitter = new SceneParticleEmitter("Default", scene,
 		Particle::MESH_PARTICLE, ParticleEmitter::CONTINUOUS_EMITTER, 4, 100,
-		Vector3(0.0,1.0,0.0), Vector3(0.0,0.0,0.0), Vector3(0.3, 0.0, 0.3), mesh);
+		Vector3(0.0,1.0,0.0), Vector3(0.0,0.0,0.0), Vector3(0.3, 0.0, 0.3),
+		Vector3(1.5,1.5,1.5), mesh);
 			
 	emitter->useScaleCurves = true;
 	emitter->scaleCurve.addControlPoint2d(0, 0.1);

+ 2 - 1
Examples/C++/Contents/3DParticles/HelloPolycodeApp.cpp

@@ -22,7 +22,8 @@ HelloPolycodeApp::HelloPolycodeApp(PolycodeView *view) {
 	
 	SceneParticleEmitter *emitter = new SceneParticleEmitter("TestParticle", scene,
 		Particle::BILLBOARD_PARTICLE, ParticleEmitter::CONTINUOUS_EMITTER, 4, 200,
-		Vector3(0.0,1.0,0.0), Vector3(0.0,0.0,0.0), Vector3(0.3, 0.0, 0.3));		
+		Vector3(0.0,1.0,0.0), Vector3(0.0,0.0,0.0), Vector3(0.3, 0.0, 0.3),
+		Vector3(1.5,1.5,1.5));		
 
 	
 	emitter->useScaleCurves = true;

+ 233 - 13
IDE/Build/Mac OS X/English.lproj/MainMenu.xib

@@ -210,6 +210,15 @@
 									<reference key="NSOnImage" ref="35465992"/>
 									<reference key="NSMixedImage" ref="502551668"/>
 								</object>
+								<object class="NSMenuItem" id="93992569">
+									<reference key="NSMenu" ref="720053764"/>
+									<string key="NSTitle">New Folder</string>
+									<string key="NSKeyEquiv">F</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
 								<object class="NSMenuItem" id="425164168">
 									<reference key="NSMenu" ref="720053764"/>
 									<bool key="NSIsDisabled">YES</bool>
@@ -268,6 +277,15 @@
 									<reference key="NSOnImage" ref="35465992"/>
 									<reference key="NSMixedImage" ref="502551668"/>
 								</object>
+								<object class="NSMenuItem" id="355684970">
+									<reference key="NSMenu" ref="720053764"/>
+									<string key="NSTitle">Remove File</string>
+									<string type="base64-UTF8" key="NSKeyEquiv">CA</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
 								<object class="NSMenuItem" id="268409637">
 									<reference key="NSMenu" ref="720053764"/>
 									<bool key="NSIsDisabled">YES</bool>
@@ -279,6 +297,25 @@
 									<reference key="NSOnImage" ref="35465992"/>
 									<reference key="NSMixedImage" ref="502551668"/>
 								</object>
+								<object class="NSMenuItem" id="317190896">
+									<reference key="NSMenu" ref="720053764"/>
+									<string key="NSTitle">Refresh Project</string>
+									<string key="NSKeyEquiv">F</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
+								<object class="NSMenuItem" id="533574374">
+									<reference key="NSMenu" ref="720053764"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<string key="NSTitle"/>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
 								<object class="NSMenuItem" id="1023925487">
 									<reference key="NSMenu" ref="720053764"/>
 									<string key="NSTitle">Save File</string>
@@ -679,6 +716,14 @@
 						<reference key="NSOnImage" ref="35465992"/>
 						<reference key="NSMixedImage" ref="502551668"/>
 					</object>
+					<object class="NSMenuItem" id="46500047">
+						<reference key="NSMenu" ref="1048220208"/>
+						<string key="NSTitle">Add New Folder</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="35465992"/>
+						<reference key="NSMixedImage" ref="502551668"/>
+					</object>
 					<object class="NSMenuItem" id="26940596">
 						<reference key="NSMenu" ref="1048220208"/>
 						<bool key="NSIsDisabled">YES</bool>
@@ -689,6 +734,32 @@
 						<reference key="NSOnImage" ref="35465992"/>
 						<reference key="NSMixedImage" ref="502551668"/>
 					</object>
+					<object class="NSMenuItem" id="556423302">
+						<reference key="NSMenu" ref="1048220208"/>
+						<string key="NSTitle">Refresh</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="35465992"/>
+						<reference key="NSMixedImage" ref="502551668"/>
+					</object>
+					<object class="NSMenuItem" id="49210983">
+						<reference key="NSMenu" ref="1048220208"/>
+						<string key="NSTitle">Rename</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="35465992"/>
+						<reference key="NSMixedImage" ref="502551668"/>
+					</object>
+					<object class="NSMenuItem" id="954168611">
+						<reference key="NSMenu" ref="1048220208"/>
+						<bool key="NSIsDisabled">YES</bool>
+						<bool key="NSIsSeparator">YES</bool>
+						<string key="NSTitle"/>
+						<string key="NSKeyEquiv"/>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="35465992"/>
+						<reference key="NSMixedImage" ref="502551668"/>
+					</object>
 					<object class="NSMenuItem" id="901265223">
 						<reference key="NSMenu" ref="1048220208"/>
 						<string key="NSTitle">Remove</string>
@@ -943,14 +1014,6 @@
 					</object>
 					<int key="connectionID">564</int>
 				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">newProject:</string>
-						<reference key="source" ref="976324537"/>
-						<reference key="destination" ref="548023385"/>
-					</object>
-					<int key="connectionID">565</int>
-				</object>
 				<object class="IBConnectionRecord">
 					<object class="IBActionConnection" key="connection">
 						<string key="label">closeProject:</string>
@@ -983,6 +1046,78 @@
 					</object>
 					<int key="connectionID">572</int>
 				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">newGroup:</string>
+						<reference key="source" ref="976324537"/>
+						<reference key="destination" ref="93992569"/>
+					</object>
+					<int key="connectionID">574</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">removeFile:</string>
+						<reference key="source" ref="976324537"/>
+						<reference key="destination" ref="355684970"/>
+					</object>
+					<int key="connectionID">576</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">removeFile:</string>
+						<reference key="source" ref="976324537"/>
+						<reference key="destination" ref="901265223"/>
+					</object>
+					<int key="connectionID">577</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">newProject:</string>
+						<reference key="source" ref="976324537"/>
+						<reference key="destination" ref="548023385"/>
+					</object>
+					<int key="connectionID">578</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">newFile:</string>
+						<reference key="source" ref="976324537"/>
+						<reference key="destination" ref="921894302"/>
+					</object>
+					<int key="connectionID">579</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">newGroup:</string>
+						<reference key="source" ref="976324537"/>
+						<reference key="destination" ref="46500047"/>
+					</object>
+					<int key="connectionID">581</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">renameFile:</string>
+						<reference key="source" ref="976324537"/>
+						<reference key="destination" ref="49210983"/>
+					</object>
+					<int key="connectionID">584</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">refreshProject:</string>
+						<reference key="source" ref="976324537"/>
+						<reference key="destination" ref="556423302"/>
+					</object>
+					<int key="connectionID">586</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">refreshProject:</string>
+						<reference key="source" ref="976324537"/>
+						<reference key="destination" ref="317190896"/>
+					</object>
+					<int key="connectionID">589</int>
+				</object>
 			</object>
 			<object class="IBMutableOrderedSet" key="objectRecords">
 				<object class="NSArray" key="orderedObjects">
@@ -1081,6 +1216,10 @@
 							<reference ref="164447311"/>
 							<reference ref="810242391"/>
 							<reference ref="1071799412"/>
+							<reference ref="93992569"/>
+							<reference ref="355684970"/>
+							<reference ref="533574374"/>
+							<reference ref="317190896"/>
 						</object>
 						<reference key="parent" ref="379814623"/>
 					</object>
@@ -1470,6 +1609,10 @@
 							<reference ref="548023385"/>
 							<reference ref="901265223"/>
 							<reference ref="26940596"/>
+							<reference ref="46500047"/>
+							<reference ref="49210983"/>
+							<reference ref="954168611"/>
+							<reference ref="556423302"/>
 						</object>
 						<reference key="parent" ref="0"/>
 					</object>
@@ -1503,6 +1646,46 @@
 						<reference key="object" ref="1071799412"/>
 						<reference key="parent" ref="720053764"/>
 					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">573</int>
+						<reference key="object" ref="93992569"/>
+						<reference key="parent" ref="720053764"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">575</int>
+						<reference key="object" ref="355684970"/>
+						<reference key="parent" ref="720053764"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">580</int>
+						<reference key="object" ref="46500047"/>
+						<reference key="parent" ref="1048220208"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">582</int>
+						<reference key="object" ref="49210983"/>
+						<reference key="parent" ref="1048220208"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">583</int>
+						<reference key="object" ref="954168611"/>
+						<reference key="parent" ref="1048220208"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">585</int>
+						<reference key="object" ref="556423302"/>
+						<reference key="parent" ref="1048220208"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">587</int>
+						<reference key="object" ref="533574374"/>
+						<reference key="parent" ref="720053764"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">588</int>
+						<reference key="object" ref="317190896"/>
+						<reference key="parent" ref="720053764"/>
+					</object>
 				</object>
 			</object>
 			<object class="NSMutableDictionary" key="flattenedProperties">
@@ -1579,7 +1762,15 @@
 					<string>57.IBPluginDependency</string>
 					<string>570.IBPluginDependency</string>
 					<string>571.IBPluginDependency</string>
+					<string>573.IBPluginDependency</string>
+					<string>575.IBPluginDependency</string>
 					<string>58.IBPluginDependency</string>
+					<string>580.IBPluginDependency</string>
+					<string>582.IBPluginDependency</string>
+					<string>583.IBPluginDependency</string>
+					<string>585.IBPluginDependency</string>
+					<string>587.IBPluginDependency</string>
+					<string>588.IBPluginDependency</string>
 					<string>72.IBPluginDependency</string>
 					<string>73.IBPluginDependency</string>
 					<string>75.IBPluginDependency</string>
@@ -1670,6 +1861,14 @@
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 				</object>
 			</object>
 			<object class="NSMutableDictionary" key="unlocalizedProperties">
@@ -1684,7 +1883,7 @@
 				<reference key="dict.values" ref="0"/>
 			</object>
 			<nil key="sourceID"/>
-			<int key="maxID">572</int>
+			<int key="maxID">589</int>
 		</object>
 		<object class="IBClassDescriber" key="IBDocument.Classes">
 			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -1766,9 +1965,12 @@
 							<string>browseExamples:</string>
 							<string>closeProject:</string>
 							<string>newFile:</string>
+							<string>newGroup:</string>
 							<string>newProject:</string>
-							<string>open:</string>
 							<string>openProject:</string>
+							<string>refreshProject:</string>
+							<string>removeFile:</string>
+							<string>renameFile:</string>
 							<string>runProject:</string>
 							<string>saveFile:</string>
 						</object>
@@ -1782,6 +1984,9 @@
 							<string>id</string>
 							<string>id</string>
 							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
 						</object>
 					</object>
 					<object class="NSMutableDictionary" key="actionInfosByName">
@@ -1791,9 +1996,12 @@
 							<string>browseExamples:</string>
 							<string>closeProject:</string>
 							<string>newFile:</string>
+							<string>newGroup:</string>
 							<string>newProject:</string>
-							<string>open:</string>
 							<string>openProject:</string>
+							<string>refreshProject:</string>
+							<string>removeFile:</string>
+							<string>renameFile:</string>
 							<string>runProject:</string>
 							<string>saveFile:</string>
 						</object>
@@ -1812,17 +2020,29 @@
 								<string key="candidateClassName">id</string>
 							</object>
 							<object class="IBActionInfo">
-								<string key="name">newProject:</string>
+								<string key="name">newGroup:</string>
 								<string key="candidateClassName">id</string>
 							</object>
 							<object class="IBActionInfo">
-								<string key="name">open:</string>
+								<string key="name">newProject:</string>
 								<string key="candidateClassName">id</string>
 							</object>
 							<object class="IBActionInfo">
 								<string key="name">openProject:</string>
 								<string key="candidateClassName">id</string>
 							</object>
+							<object class="IBActionInfo">
+								<string key="name">refreshProject:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">removeFile:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">renameFile:</string>
+								<string key="candidateClassName">id</string>
+							</object>
 							<object class="IBActionInfo">
 								<string key="name">runProject:</string>
 								<string key="candidateClassName">id</string>

+ 26 - 8
IDE/Build/Mac OS X/Polycode.xcodeproj/project.pbxproj

@@ -9,7 +9,12 @@
 /* Begin PBXBuildFile section */
 		1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1DDD58140DA1D0A300B32029 /* MainMenu.xib */; };
 		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 */; };
+		6D2AC99B14B8500400BB63DA /* PolycodeProjectEditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2AC99A14B8500400BB63DA /* PolycodeProjectEditor.cpp */; };
 		6D34143412B816BC0034FA9B /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D34143312B816BC0034FA9B /* IOKit.framework */; };
+		6D3B6C5B14B820A900727F17 /* ToolWindows.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D3B6C5A14B820A900727F17 /* ToolWindows.cpp */; };
+		6D56156814C5430300FC8BD4 /* PolycodeScreenEditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D56156714C5430300FC8BD4 /* PolycodeScreenEditor.cpp */; };
 		6D6D3FA614B446A600219173 /* PolycodeToolLauncher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D6D3FA514B446A600219173 /* PolycodeToolLauncher.cpp */; };
 		6D70AB2A12B29BF200EB6D94 /* NewFileWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D70AB2912B29BF200EB6D94 /* NewFileWindow.cpp */; };
 		6D80E91E12AB53FB0037A708 /* PolycodeFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D80E91912AB53FB0037A708 /* PolycodeFrame.cpp */; };
@@ -18,7 +23,6 @@
 		6D80E92112AB53FB0037A708 /* PolycodeProjectBrowser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D80E91C12AB53FB0037A708 /* PolycodeProjectBrowser.cpp */; };
 		6D80E92212AB53FB0037A708 /* PolycodeProjectManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D80E91D12AB53FB0037A708 /* PolycodeProjectManager.cpp */; };
 		6D80EB1612AB7C6D0037A708 /* NewProjectWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D80EB1512AB7C6D0037A708 /* NewProjectWindow.cpp */; };
-		6D8A55B214B3EA6C005F6411 /* libPolycore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D8A55B114B3EA6C005F6411 /* libPolycore.a */; };
 		6D8A55B914B3EABB005F6411 /* main_icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 6D8A55B814B3EABB005F6411 /* main_icon.icns */; };
 		6D8A55BC14B3EACB005F6411 /* PolycodeView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D8A55BB14B3EACB005F6411 /* PolycodeView.mm */; };
 		6D91B3B512AF2B1D00261ED4 /* PolycodeTextEditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D91B3B412AF2B1D00261ED4 /* PolycodeTextEditor.cpp */; };
@@ -36,7 +40,6 @@
 		6DFE89C114B3FC0900DA7ABD /* libphysfs.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6DFE89BA14B3FC0900DA7ABD /* libphysfs.a */; };
 		6DFE89C214B3FC0900DA7ABD /* libpng15.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6DFE89BB14B3FC0900DA7ABD /* libpng15.a */; };
 		6DFE89C314B3FC0900DA7ABD /* libz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6DFE89BC14B3FC0900DA7ABD /* libz.a */; };
-		6DFE89C514B3FC1700DA7ABD /* libPolycodeUI.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6DFE89C414B3FC1700DA7ABD /* libPolycodeUI.a */; };
 		6DFE89CC14B3FE3D00DA7ABD /* default.pak in Resources */ = {isa = PBXBuildFile; fileRef = 6DFE89CB14B3FE3D00DA7ABD /* default.pak */; };
 		8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
 		8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
@@ -66,7 +69,15 @@
 		29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
 		29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
 		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>"; };
+		6D2AC99A14B8500400BB63DA /* PolycodeProjectEditor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolycodeProjectEditor.cpp; sourceTree = "<group>"; };
+		6D2AC99D14B8500A00BB63DA /* PolycodeProjectEditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolycodeProjectEditor.h; sourceTree = "<group>"; };
 		6D34143312B816BC0034FA9B /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
+		6D3B6C5A14B820A900727F17 /* ToolWindows.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ToolWindows.cpp; sourceTree = "<group>"; };
+		6D3B6C5C14B820B000727F17 /* ToolWindows.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ToolWindows.h; sourceTree = "<group>"; };
+		6D56156514C542FB00FC8BD4 /* PolycodeScreenEditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolycodeScreenEditor.h; sourceTree = "<group>"; };
+		6D56156714C5430300FC8BD4 /* PolycodeScreenEditor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolycodeScreenEditor.cpp; sourceTree = "<group>"; };
 		6D6D3FA514B446A600219173 /* PolycodeToolLauncher.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolycodeToolLauncher.cpp; sourceTree = "<group>"; };
 		6D6D3FA814B446AF00219173 /* PolycodeToolLauncher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolycodeToolLauncher.h; sourceTree = "<group>"; };
 		6D70AB2812B29BEC00EB6D94 /* NewFileWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewFileWindow.h; sourceTree = "<group>"; };
@@ -84,7 +95,6 @@
 		6D80EB1512AB7C6D0037A708 /* NewProjectWindow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewProjectWindow.cpp; sourceTree = "<group>"; };
 		6D80EB1712AB7C740037A708 /* NewProjectWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewProjectWindow.h; sourceTree = "<group>"; };
 		6D80EBAC12AB852B0037A708 /* PolycodeGlobals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolycodeGlobals.h; sourceTree = "<group>"; };
-		6D8A55B114B3EA6C005F6411 /* libPolycore.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libPolycore.a; path = ../../../Release/Darwin/Framework/Core/lib/libPolycore.a; sourceTree = "<group>"; };
 		6D8A55B814B3EABB005F6411 /* main_icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = main_icon.icns; path = ../../../Assets/Icons/main_icon.icns; sourceTree = "<group>"; };
 		6D8A55BA14B3EACB005F6411 /* PolycodeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PolycodeView.h; path = ../../../Release/Darwin/Framework/Core/PolycodeView/PolycodeView.h; sourceTree = "<group>"; };
 		6D8A55BB14B3EACB005F6411 /* PolycodeView.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; name = PolycodeView.mm; path = ../../../Release/Darwin/Framework/Core/PolycodeView/PolycodeView.mm; sourceTree = "<group>"; };
@@ -109,7 +119,6 @@
 		6DFE89BA14B3FC0900DA7ABD /* libphysfs.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libphysfs.a; path = ../../../Release/Darwin/Framework/Core/Dependencies/lib/libphysfs.a; sourceTree = "<group>"; };
 		6DFE89BB14B3FC0900DA7ABD /* libpng15.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng15.a; path = ../../../Release/Darwin/Framework/Core/Dependencies/lib/libpng15.a; sourceTree = "<group>"; };
 		6DFE89BC14B3FC0900DA7ABD /* libz.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libz.a; path = ../../../Release/Darwin/Framework/Core/Dependencies/lib/libz.a; sourceTree = "<group>"; };
-		6DFE89C414B3FC1700DA7ABD /* libPolycodeUI.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libPolycodeUI.a; path = ../../../Release/Darwin/Framework/Modules/lib/libPolycodeUI.a; sourceTree = "<group>"; };
 		6DFE89CB14B3FE3D00DA7ABD /* default.pak */ = {isa = PBXFileReference; lastKnownFileType = file; name = default.pak; path = ../../../Release/Darwin/Framework/Core/Assets/default.pak; sourceTree = "<group>"; };
 		8D1107310486CEB800E47090 /* Polycode-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Polycode-Info.plist"; sourceTree = "<group>"; };
 		8D1107320486CEB800E47090 /* Polycode.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Polycode.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -124,7 +133,6 @@
 				6DFBF64A12A3758400C43A7D /* OpenAL.framework in Frameworks */,
 				6DFBF64B12A3758400C43A7D /* OpenGL.framework in Frameworks */,
 				6D34143412B816BC0034FA9B /* IOKit.framework in Frameworks */,
-				6D8A55B214B3EA6C005F6411 /* libPolycore.a in Frameworks */,
 				6DFE89BD14B3FC0900DA7ABD /* libfreetype.a in Frameworks */,
 				6DFE89BE14B3FC0900DA7ABD /* liblibogg.a in Frameworks */,
 				6DFE89BF14B3FC0900DA7ABD /* liblibvorbis.a in Frameworks */,
@@ -132,7 +140,8 @@
 				6DFE89C114B3FC0900DA7ABD /* libphysfs.a in Frameworks */,
 				6DFE89C214B3FC0900DA7ABD /* libpng15.a in Frameworks */,
 				6DFE89C314B3FC0900DA7ABD /* libz.a in Frameworks */,
-				6DFE89C514B3FC1700DA7ABD /* libPolycodeUI.a in Frameworks */,
+				6D06CCF314BC203800E4CB4C /* libPolycore_d.a in Frameworks */,
+				6D06CCF514BC204200E4CB4C /* libPolycodeUI_d.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -151,7 +160,8 @@
 		1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
 			isa = PBXGroup;
 			children = (
-				6DFE89C414B3FC1700DA7ABD /* libPolycodeUI.a */,
+				6D06CCF414BC204200E4CB4C /* libPolycodeUI_d.a */,
+				6D06CCF214BC203800E4CB4C /* libPolycore_d.a */,
 				6DFE89B614B3FC0900DA7ABD /* libfreetype.a */,
 				6DFE89B714B3FC0900DA7ABD /* liblibogg.a */,
 				6DFE89B814B3FC0900DA7ABD /* liblibvorbis.a */,
@@ -159,7 +169,6 @@
 				6DFE89BA14B3FC0900DA7ABD /* libphysfs.a */,
 				6DFE89BB14B3FC0900DA7ABD /* libpng15.a */,
 				6DFE89BC14B3FC0900DA7ABD /* libz.a */,
-				6D8A55B114B3EA6C005F6411 /* libPolycore.a */,
 				6D34143312B816BC0034FA9B /* IOKit.framework */,
 				6DFBF64812A3758400C43A7D /* OpenAL.framework */,
 				6DFBF64912A3758400C43A7D /* OpenGL.framework */,
@@ -235,6 +244,9 @@
 		6D80E91212AB53FB0037A708 /* Include */ = {
 			isa = PBXGroup;
 			children = (
+				6D56156514C542FB00FC8BD4 /* PolycodeScreenEditor.h */,
+				6D2AC99D14B8500A00BB63DA /* PolycodeProjectEditor.h */,
+				6D3B6C5C14B820B000727F17 /* ToolWindows.h */,
 				6DCAFD4614B51A2D00039F34 /* ExampleBrowserWindow.h */,
 				6D6D3FA814B446AF00219173 /* PolycodeToolLauncher.h */,
 				6D70AB2812B29BEC00EB6D94 /* NewFileWindow.h */,
@@ -258,6 +270,9 @@
 		6D80E91812AB53FB0037A708 /* Source */ = {
 			isa = PBXGroup;
 			children = (
+				6D56156714C5430300FC8BD4 /* PolycodeScreenEditor.cpp */,
+				6D2AC99A14B8500400BB63DA /* PolycodeProjectEditor.cpp */,
+				6D3B6C5A14B820A900727F17 /* ToolWindows.cpp */,
 				6DCAFD4214B519C900039F34 /* ExampleBrowserWindow.cpp */,
 				6D6D3FA514B446A600219173 /* PolycodeToolLauncher.cpp */,
 				6D70AB2912B29BF200EB6D94 /* NewFileWindow.cpp */,
@@ -376,6 +391,9 @@
 				6D8A55BC14B3EACB005F6411 /* PolycodeView.mm in Sources */,
 				6D6D3FA614B446A600219173 /* PolycodeToolLauncher.cpp in Sources */,
 				6DCAFD4314B519C900039F34 /* ExampleBrowserWindow.cpp in Sources */,
+				6D3B6C5B14B820A900727F17 /* ToolWindows.cpp in Sources */,
+				6D2AC99B14B8500400BB63DA /* PolycodeProjectEditor.cpp in Sources */,
+				6D56156814C5430300FC8BD4 /* PolycodeScreenEditor.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 4 - 0
IDE/Build/Mac OS X/PolycodeAppDelegate.h

@@ -52,6 +52,10 @@ public:
 
 // Menu accessors
 
+-(IBAction) refreshProject: (id) sender;
+-(IBAction) renameFile: (id) sender;
+-(IBAction) removeFile: (id) sender;
+-(IBAction) newGroup: (id) sender;
 -(IBAction) browseExamples: (id) sender;
 -(IBAction) runProject: (id) sender;
 -(IBAction) newProject: (id) sender;

+ 16 - 0
IDE/Build/Mac OS X/PolycodeAppDelegate.m

@@ -71,6 +71,22 @@
 	return YES;
 }
 
+-(IBAction) refreshProject: (id) sender {
+	app->refreshProject();
+}	
+
+-(IBAction) renameFile: (id) sender {
+	app->renameFile();
+}
+
+-(IBAction) removeFile: (id) sender {
+	app->removeFile();
+}
+
+-(IBAction) newGroup: (id) sender {
+	app->newGroup();
+}
+
 -(IBAction) browseExamples: (id) sender {
 	app->browseExamples();
 }

+ 12 - 1
IDE/Contents/Include/NewFileWindow.h

@@ -31,7 +31,7 @@ using namespace Polycode;
 
 class FileTemplateUserData  {
 public:
-	String templateFolder;
+	String templatePath;
 	int type;
 };
 
@@ -43,9 +43,20 @@ class NewFileWindow : public UIWindow {
 		void resetForm();
 		void parseTemplatesIntoTree(UITree *tree, OSFileEntry folder);
 
+		String getTemplatePath();
+		String getFileName();
+		
+		void handleEvent(Event *event);
 	
 	protected:
 	
+		UITextInput *fileNameInput;
+	
+		UIButton *cancelButton;
+		UIButton *okButton;
+		
+		String templatePath;
+			
 		UITreeContainer *templateContainer;	
 		UITree *defaultTemplateTree;
 };

+ 4 - 0
IDE/Contents/Include/PolycodeEditor.h

@@ -23,6 +23,7 @@
 #pragma once
 
 #include "Polycode.h"
+#include "OSBasics.h"
 
 using namespace Polycode;
 
@@ -36,6 +37,9 @@ public:
 	
 	virtual void saveFile(){};
 	
+	virtual void handleDroppedFile(OSFileEntry file, Number x, Number y) {};
+	
+	void setFilePath(String newPath);
 	String getFilePath() { return filePath; }
 	
 	bool isReadOnly() { return _isReadOnly; }

+ 7 - 0
IDE/Contents/Include/PolycodeFrame.h

@@ -27,6 +27,7 @@
 #include "NewProjectWindow.h"
 #include "ExampleBrowserWindow.h"
 #include "NewFileWindow.h"
+#include "ToolWindows.h"
 
 using namespace Polycode;
 
@@ -52,6 +53,8 @@ public:
 	ExampleBrowserWindow *exampleBrowserWindow;
 	NewFileWindow *newFileWindow;
 	
+	TextInputPopup *textInputPopup;
+	
 	ScreenEntity *welcomeEntity;	
 	PolycodeProjectBrowser *projectBrowser;
 		
@@ -66,6 +69,10 @@ private:
 	ScreenImage *logo;	
 	ScreenImage *resizer;	
 
+	OSFileEntry draggedFile;
+	ScreenEntity *dragEntity;
+	ScreenLabel *dragLabel;
+	bool isDragging;
 	
 	ScreenImage *welcomeImage;	
 	

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

@@ -31,8 +31,10 @@
 #include "PolycodeFrame.h"
 
 #include "PolycodeImageEditor.h"
+#include "PolycodeScreenEditor.h"
 #include "PolycodeFontEditor.h"
 #include "PolycodeTextEditor.h"
+#include "PolycodeProjectEditor.h"
 
 #include "PolycodeToolLauncher.h"
 
@@ -50,13 +52,18 @@ public:
 	void loadConfigFile();
 	
 	// menu commands
+	void renameFile();
+	void removeFile();
 	void browseExamples();
 	void newProject();
 	void newFile();	
+	void newGroup();
 	void openProject();
 	void closeProject();	
 	void saveFile();
 	
+	void refreshProject();
+	
 	void runProject();
 	
 	const static int EVENT_SHOW_MENU = 1;

+ 7 - 1
IDE/Contents/Include/PolycodeProjectBrowser.h

@@ -57,6 +57,11 @@ public:
 	void addProject(PolycodeProject *project);
 	void removeProject(PolycodeProject *project);
 	
+	UITree *nodeHasName(UITree *node, String name);
+	bool listHasFileEntry(vector<OSFileEntry> files, OSFileEntry fileEntry);
+	
+	void refreshProject(PolycodeProject *project);
+	
 	void handleEvent(Event *event);
 	
 	void parseFolderIntoNode(UITree *node, String spath, PolycodeProject *parentProject);
@@ -65,8 +70,9 @@ public:
 	
 	BrowserUserData *getSelectedData() { return selectedData; }
 	
+	UITreeContainer *treeContainer;
+			
 protected:
 	
 		BrowserUserData *selectedData;
-		UITreeContainer *treeContainer;
 };	

+ 65 - 0
IDE/Contents/Include/PolycodeProjectEditor.h

@@ -0,0 +1,65 @@
+/*
+ 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 "PolycodeGlobals.h"
+#include "PolycodeUI.h"
+#include "PolycodeEditor.h"
+#include <Polycode.h>
+
+using namespace Polycode;
+
+class PolycodeProjectEditor : public PolycodeEditor {
+	public:
+	PolycodeProjectEditor();
+	virtual ~PolycodeProjectEditor();
+	
+	bool openFile(String filePath);
+	void Resize(int x, int y);
+	void saveFile();
+	
+	protected:
+	
+	Object configFile;	
+	
+	std::vector<UICheckBox*> moduleCheckboxes;
+	
+	UIWindow *mainSettingsWindow;
+	UIWindow *moduleSettingsWindow;
+		
+	UICheckBox *vSyncCheckBox;
+	UITextInput *defaultWidthInput;
+	UITextInput *defaultHeightInput;	
+	UITextInput *framerateInput;	
+	UIComboBox *aaLevelComboBox;
+	UIComboBox *afLevelComboBox;	
+	UITextInput *entryPointInput;	
+	UIColorBox *bgColorBox;
+	
+};
+
+class PolycodeProjectEditorFactory : public PolycodeEditorFactory {
+	public:
+		PolycodeProjectEditorFactory() : PolycodeEditorFactory() { extensions.push_back("polyproject"); }
+		PolycodeEditor *createEditor() { return new PolycodeProjectEditor(); }
+};

+ 11 - 1
IDE/Contents/Include/PolycodeProjectManager.h

@@ -33,21 +33,31 @@ class PolycodeProjectManager {
 	public:
 		PolycodeProjectManager();
 		~PolycodeProjectManager();
+		
+	void createNewFile(String templatePath, String newFileName);
 	
 	void createNewProject(String templateFolder, String projectName, String projectLocation);
 	PolycodeProject* openProject(String path);
 	void setProjectBrowser(PolycodeProjectBrowser *projectBrowser) { this->projectBrowser = projectBrowser; }
 	
 	PolycodeProject* getActiveProject() { return activeProject; }
-	void setActiveProject(PolycodeProject* project) { if(project) printf("setting active project: %s\n", project->getProjectName().c_str()); activeProject = project; }
+	void setActiveProject(PolycodeProject* project) {
+//		if(project) printf("setting active project: %s\n", project->getProjectName().c_str());
+		activeProject = project;
+	}
 	
 	int getProjectCount() { return projects.size(); }
 	PolycodeProject *getProjectByIndex(int index) { return projects[index]; }
 	
 	int removeProject(PolycodeProject *project);
 	
+	String activeFolder;
+	String selectedFile;
+	OSFileEntry selectedFileEntry;
+	
 protected:
 	
+	
 	PolycodeProject* activeProject;
 	
 	PolycodeProjectBrowser *projectBrowser;

+ 67 - 0
IDE/Contents/Include/PolycodeScreenEditor.h

@@ -0,0 +1,67 @@
+/*
+ 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 <Polycode.h>
+#include <PolycodeUI.h>
+
+using namespace Polycode;
+
+class PolycodeScreenEditor : public PolycodeEditor {
+	public:
+	PolycodeScreenEditor();
+	virtual ~PolycodeScreenEditor();
+	
+	bool openFile(String filePath);
+	void Resize(int x, int y);
+	
+	void syncTransformToSelected();
+	
+	void handleEvent(Event *event);
+	
+	void handleDroppedFile(OSFileEntry file, Number x, Number y);
+	
+	protected:
+		
+		UIColorBox *entityColorBox;
+		UIWindow *entityInfoWindow;
+		
+		Vector2 dragOffset;
+		bool isDraggingEntity;
+		bool isScalingEntity;
+		
+		ScreenEntity *selectedEntity;
+		ScreenEntity *baseEntity;
+		
+		UIBox *screenTransform;
+	
+		ScreenImage *centerImage;
+		ScreenImage *grid;	
+};
+
+class PolycodeScreenEditorFactory : public PolycodeEditorFactory {
+	public:
+		PolycodeScreenEditorFactory() : PolycodeEditorFactory() { extensions.push_back("screen"); }
+		PolycodeEditor *createEditor() { return new PolycodeScreenEditor(); }
+};

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

@@ -35,7 +35,7 @@ public:
 	
 	bool openFile(String filePath);
 	void Resize(int x, int y);
-	void saveFile();	
+	void saveFile();
 	
 protected:
 

+ 48 - 0
IDE/Contents/Include/ToolWindows.h

@@ -0,0 +1,48 @@
+/*
+ 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 "PolycodeGlobals.h"
+#include "PolycodeUI.h"
+#include "Polycode.h"
+#include "OSBasics.h"
+
+using namespace Polycode;
+
+class TextInputPopup : public UIWindow {
+	public:
+		TextInputPopup();
+		~TextInputPopup();
+		
+		void setValue(String value);
+		String getValue();
+		void handleEvent(Event *event);
+		
+	protected:
+	
+		UITextInput *textInput;
+	
+		UIButton *cancelButton;
+		UIButton *okButton;
+	
+};

+ 12 - 0
IDE/Contents/Resources/FileTemplates/2D/Screen Entity.screen

@@ -0,0 +1,12 @@
+<?xml version="1.0" ?>
+<screen>	
+	<entities>
+		<entity type="image" x="100" y="200" rot="35" tint="#ff00ff" alpha="1" scaleX="1" scaleY="1">
+			<image_path>tomato.png</image_path>
+		</entity>
+		<entity type="shape" x="300" y="200" rot="35" tint="#ff00ff" alpha="1" scaleX="1" scaleY="1">
+			<shape type="rect" width="100" height="50" texture="Whatever"></shape>
+			<physics type="static_rect" density="1" friction="1" restitution="0" sensor="false" noRotate="false"></physics>
+		</entity>
+	</entities>
+</screen>

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


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


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


BIN
IDE/Contents/Resources/UIThemes/default/checkbox_checked.png


BIN
IDE/Contents/Resources/UIThemes/default/checkbox_unchecked.png


BIN
IDE/Contents/Resources/UIThemes/default/colorPickerHue.png


BIN
IDE/Contents/Resources/UIThemes/default/colorPickerHueSelector.png


BIN
IDE/Contents/Resources/UIThemes/default/colorPickerMainBg.png


BIN
IDE/Contents/Resources/UIThemes/default/colorPickerMainFrame.png


BIN
IDE/Contents/Resources/UIThemes/default/colorPickerTarget.png


BIN
IDE/Contents/Resources/UIThemes/default/colorboxBg.png


BIN
IDE/Contents/Resources/UIThemes/default/colorboxFrame.png


BIN
IDE/Contents/Resources/UIThemes/default/combobox_bg.png


BIN
IDE/Contents/Resources/UIThemes/default/combobox_drop.png


BIN
IDE/Contents/Resources/UIThemes/default/combobox_items.png


BIN
IDE/Contents/Resources/UIThemes/default/combobox_selector.png


BIN
IDE/Contents/Resources/UIThemes/default/hsliderBg.png


BIN
IDE/Contents/Resources/UIThemes/default/hsliderHandle.png


+ 60 - 15
IDE/Contents/Resources/UIThemes/default/theme.xml

@@ -31,11 +31,9 @@
 	<uiTreeContainerSkinB>2</uiTreeContainerSkinB>
 	<uiTreeContainerSkinL>2</uiTreeContainerSkinL>
 	
-	<uiScrollDefaultSize>19</uiScrollDefaultSize>
-	
+	<uiScrollDefaultSize>19</uiScrollDefaultSize>	
 	<uiScrollPanePadding>0</uiScrollPanePadding>
 
-
 	<uiButtonSkin>button.png</uiButtonSkin>
 	<uiButtonFocusedSkin>buttonFocused.png</uiButtonFocusedSkin>
 	<uiButtonFontSize>11</uiButtonFontSize>	
@@ -44,23 +42,20 @@
 	<uiButtonSkinB>4</uiButtonSkinB>
 	<uiButtonSkinL>4</uiButtonSkinL>
 
-
 	<uiWindowSkin>windowBg.png</uiWindowSkin>
 	<uiWindowSkinT>29</uiWindowSkinT>
-	<uiWindowSkinR>3</uiWindowSkinR>
-	<uiWindowSkinB>3</uiWindowSkinB>
-	<uiWindowSkinL>3</uiWindowSkinL>
-	<uiWindowSkinPadding>10</uiWindowSkinPadding>
-		
+	<uiWindowSkinR>8</uiWindowSkinR>
+	<uiWindowSkinB>8</uiWindowSkinB>
+	<uiWindowSkinL>8</uiWindowSkinL>
+	<uiWindowSkinPadding>15</uiWindowSkinPadding>		
 	<uiWindowTitleFont>sans</uiWindowTitleFont>
 	<uiWindowTitleFontSize>12</uiWindowTitleFontSize>
-	<uiWindowTitleX>5</uiWindowTitleX>	
+	<uiWindowTitleX>10</uiWindowTitleX>	
 	<uiWindowTitleY>7</uiWindowTitleY>		
 	<uiWindowCloseIcon>closeIcon.png</uiWindowCloseIcon>
-	<uiCloseIconX>6</uiCloseIconX>	
+	<uiCloseIconX>11</uiCloseIconX>	
 	<uiCloseIconY>7</uiCloseIconY>		
 
-	
 	<uiScrollBgSkin>scrollBg.png</uiScrollBgSkin>
 	<uiScrollBgSkinPadding>2</uiScrollBgSkinPadding>
 	<uiScrollBgSkinT>2</uiScrollBgSkinT>
@@ -81,8 +76,58 @@
 	<textBgSkinL>3</textBgSkinL>
 	<textBgSkinPadding>5</textBgSkinPadding>
 	<textEditLineSpacing>4</textEditLineSpacing>
-	
-	<uiScrollHandleMinSize>30</uiScrollHandleMinSize>
-	
+		
+	<uiScrollHandleMinSize>30</uiScrollHandleMinSize>	
 	<uiTreeContainerScrollBarOffset>27</uiTreeContainerScrollBarOffset>
+	
+	<uiCheckBoxFont>sans</uiCheckBoxFont>
+	<uiCheckBoxFontSize>11</uiCheckBoxFontSize>	
+	<uiCheckBoxCheckedImage>checkbox_checked.png</uiCheckBoxCheckedImage>
+	<uiCheckBoxUncheckedImage>checkbox_unchecked.png</uiCheckBoxUncheckedImage>
+	<uiCheckBoxLabelOffsetX>10</uiCheckBoxLabelOffsetX>
+	<uiCheckBoxLabelOffsetY>3</uiCheckBoxLabelOffsetY>
+		
+	<uiComboBoxFont>sans</uiComboBoxFont>
+	<uiComboBoxFontSize>11</uiComboBoxFontSize>
+	<uiComboBoxDropdownImage>combobox_drop.png</uiComboBoxDropdownImage>
+	<uiComboBoxBgImage>combobox_bg.png</uiComboBoxBgImage>
+	<uiComboBoxBgT>3</uiComboBoxBgT>
+	<uiComboBoxBgR>3</uiComboBoxBgR>
+	<uiComboBoxBgB>3</uiComboBoxBgB>
+	<uiComboBoxBgL>3</uiComboBoxBgL>				
+	<uiComboBoxItemsBgImage>combobox_items.png</uiComboBoxItemsBgImage>	
+	<uiComboBoxDropdownBgT>3</uiComboBoxDropdownBgT>
+	<uiComboBoxDropdownBgR>3</uiComboBoxDropdownBgR>
+	<uiComboBoxDropdownBgB>3</uiComboBoxDropdownBgB>
+	<uiComboBoxDropdownBgL>3</uiComboBoxDropdownBgL>			
+	<uiComboBoxSelectorBgImage>combobox_selector.png</uiComboBoxSelectorBgImage>	
+	<uiComboBoxSelectorBgT>3</uiComboBoxSelectorBgT>
+	<uiComboBoxSelectorBgR>3</uiComboBoxSelectorBgR>
+	<uiComboBoxSelectorBgB>3</uiComboBoxSelectorBgB>
+	<uiComboBoxSelectorBgL>3</uiComboBoxSelectorBgL>					
+	<uiComboBoxTextOffsetX>7</uiComboBoxTextOffsetX>
+	<uiComboBoxTextOffsetY>3</uiComboBoxTextOffsetY>		
+
+	<uiColorBoxFrameImage>colorboxFrame.png</uiColorBoxFrameImage>
+	<uiColorBoxFrameImageT>3</uiColorBoxFrameImageT>
+	<uiColorBoxFrameImageR>3</uiColorBoxFrameImageR>
+	<uiColorBoxFrameImageB>3</uiColorBoxFrameImageB>
+	<uiColorBoxFrameImageL>3</uiColorBoxFrameImageL>					
+	<uiColorBoxBgImage>colorboxBg.png</uiColorBoxBgImage>
+	<uiFrameInset>1</uiFrameInset>
+
+	<uiColorPickerMainBg>colorPickerMainBg.png</uiColorPickerMainBg>
+	<uiColorPickerMainFrame>colorPickerMainFrame.png</uiColorPickerMainFrame>
+	<uiColorPickerHueFrame>colorPickerHue.png</uiColorPickerHueFrame>
+	<uiColorPickerHueSelector>colorPickerHueSelector.png</uiColorPickerHueSelector>
+	<uiColorPickerMainSelector>colorPickerTarget.png</uiColorPickerMainSelector>
+
+	<uiHSliderGrip>hsliderHandle.png</uiHSliderGrip>
+	<uiHSliderBg>hsliderBg.png</uiHSliderBg>
+	<uiHSliderBgHeight>6</uiHSliderBgHeight>
+	<uiHSliderBgT>2</uiHSliderBgT>
+	<uiHSliderBgR>2</uiHSliderBgR>
+	<uiHSliderBgB>2</uiHSliderBgB>
+	<uiHSliderBgL>2</uiHSliderBgL>
+
 </PolyConfig>

BIN
IDE/Contents/Resources/UIThemes/default/windowBg.png


+ 64 - 4
IDE/Contents/Source/NewFileWindow.cpp

@@ -22,9 +22,15 @@
  
 #include "NewFileWindow.h"
 
-NewFileWindow::NewFileWindow() : UIWindow(L"Create New File", 500, 300) {
+NewFileWindow::NewFileWindow() : UIWindow(L"Create New File", 480, 280) {
 	defaultTemplateTree = NULL;
 	
+	Config *conf = CoreServices::getInstance()->getConfig();	
+	String fontName = conf->getStringValue("Polycode", "uiDefaultFontName");
+	int fontSize = conf->getNumericValue("Polycode", "uiDefaultFontSize");
+	
+	closeOnEscape = true;	
+	
 	templateContainer = new UITreeContainer("boxIcon.png", L"File Templates", 200, 300-topPadding-padding-padding);	
 	
 	FileTemplateUserData *data = new FileTemplateUserData();
@@ -50,25 +56,79 @@ NewFileWindow::NewFileWindow() : UIWindow(L"Create New File", 500, 300) {
 			parseTemplatesIntoTree(newChild, entry);
 		}
 	}	
+	
+	ScreenLabel *label2 = new ScreenLabel(L"New File Name (without extension)", fontSize, fontName, Label::ANTIALIAS_FULL);
+	addChild(label2);
+	label2->setPosition(padding+220, templateContainer->getPosition().y);			
+	
+	fileNameInput = new UITextInput(false, 500-padding-220-padding-padding, 12);	
+	addChild(fileNameInput);
+	fileNameInput->setPosition(label2->getPosition().x, label2->getPosition().y+label2->getHeight()+2);
+	
+	
+	cancelButton = new UIButton(L"Cancel", 100);
+	cancelButton->addEventListener(this, UIEvent::CLICK_EVENT);
+	addChild(cancelButton);
+	cancelButton->setPosition(500-100-padding-100-10, 265);
+			
+	okButton = new UIButton(L"Create File", 100);
+	okButton->addEventListener(this, UIEvent::CLICK_EVENT);
+	addChild(okButton);
+	okButton->setPosition(500-100-padding, 265);	
 }
 
 NewFileWindow::~NewFileWindow() {
 	
 }
 
+String NewFileWindow::getFileName() {
+	return fileNameInput->getText();
+}
+
+String NewFileWindow::getTemplatePath() {
+	return templatePath;
+}
+
 void NewFileWindow::resetForm() {
 	defaultTemplateTree->setSelected();
+	fileNameInput->setText("Untitled");
 }
 
+void NewFileWindow::handleEvent(Event *event) {
+	if(event->getEventType() == "UIEvent") {
+		if(event->getEventCode() == UIEvent::CLICK_EVENT) {
+			if(event->getDispatcher() == okButton) {
+				dispatchEvent(new UIEvent(), UIEvent::OK_EVENT);						
+			}
+			
+			if(event->getDispatcher() == cancelButton) {
+				dispatchEvent(new UIEvent(), UIEvent::CLOSE_EVENT);				
+			}									
+		}
+	}
+	
+	if(event->getEventType() == "UITreeEvent" && event->getEventCode() == UITreeEvent::SELECTED_EVENT) {
+		if(event->getDispatcher() == templateContainer->getRootNode()) {
+			UITreeEvent *treeEvent = (UITreeEvent*) event;
+			FileTemplateUserData *data = (FileTemplateUserData *)treeEvent->selection->getUserData();
+			if(data->type == 1)
+				templatePath = data->templatePath;
+		}
+	}
+	
+	UIWindow::handleEvent(event);	
+}
+
+
 void NewFileWindow::parseTemplatesIntoTree(UITree *tree, OSFileEntry folder) {
 	vector<OSFileEntry> templates = OSBasics::parseFolder(folder.fullPath, false);
 	for(int i=0; i < templates.size(); i++) {
-		OSFileEntry entry = templates[i];
+		OSFileEntry entry = templates[i];	
 		if(entry.type != OSFileEntry::TYPE_FOLDER) {
-			UITree *newChild = tree->addTreeChild("templateIcon.png", entry.nameWithoutExtension, NULL);			
+			UITree *newChild = tree->addTreeChild("templateIcon.png", entry.nameWithoutExtension, NULL);
 			FileTemplateUserData *data = new FileTemplateUserData();
 			data->type = 1;
-			data->templateFolder = entry.fullPath;
+			data->templatePath = entry.fullPath;
 			newChild->setUserData(data);
 			if(entry.name == "LUA Source File.lua") {
 				defaultTemplateTree = newChild;

+ 1 - 1
IDE/Contents/Source/NewProjectWindow.cpp

@@ -22,7 +22,7 @@
 
 #include "NewProjectWindow.h"
 
-NewProjectWindow::NewProjectWindow() : UIWindow(L"Create New Project", 500, 300){
+NewProjectWindow::NewProjectWindow() : UIWindow(L"Create New Project", 480, 280){
 	
 	templateFolder = "";
 	

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

@@ -38,6 +38,10 @@ bool PolycodeEditorFactory::canHandleExtension(String extension) {
 	return false;
 }
 
+void PolycodeEditor::setFilePath(String newPath) {
+	filePath = newPath;
+}
+
 PolycodeEditor::PolycodeEditor(bool _isReadOnly) : ScreenEntity() {
 	this->_isReadOnly = _isReadOnly;
 }

+ 55 - 0
IDE/Contents/Source/PolycodeFrame.cpp

@@ -49,6 +49,8 @@ PolycodeFrame::PolycodeFrame() : ScreenEntity() {
 	
 	projectBrowser = new PolycodeProjectBrowser();
 	addChild(projectBrowser);
+	
+	projectBrowser->treeContainer->getRootNode()->addEventListener(this, UITreeEvent::DRAG_START_EVENT);
 		
 	topBarBg = new ScreenShape(ScreenShape::SHAPE_RECT, 2,2);
 	topBarBg->setColor(0,0,0,1);
@@ -83,8 +85,22 @@ PolycodeFrame::PolycodeFrame() : ScreenEntity() {
 	newFileWindow = new NewFileWindow();
 	newFileWindow->visible = false;
 	
+	textInputPopup = new TextInputPopup();
+	textInputPopup->visible = false;
+	
 	currentEditor = NULL;
 	
+	isDragging  = false;
+	dragLabel = new ScreenLabel("NONE", 11, "sans");
+	dragLabel->setPosition(0,-15);
+	
+	dragEntity = new ScreenEntity();
+	dragEntity->addChild(dragLabel);
+	addChild(dragEntity);
+	dragEntity->visible = false;	
+	
+	CoreServices::getInstance()->getCore()->getInput()->addEventListener(this, InputEvent::EVENT_MOUSEUP);
+	CoreServices::getInstance()->getCore()->getInput()->addEventListener(this, InputEvent::EVENT_MOUSEMOVE);
 }
 
 void PolycodeFrame::showModal(UIWindow *modalChild) {
@@ -130,6 +146,45 @@ void PolycodeFrame::hideModal() {
 }
 
 void PolycodeFrame::handleEvent(Event *event) {
+	
+	if(event->getDispatcher() == CoreServices::getInstance()->getCore()->getInput()) {
+		switch(event->getEventCode()) {
+			case InputEvent::EVENT_MOUSEUP:
+				if(isDragging) {
+					if(currentEditor) {
+						InputEvent *inputEvent = (InputEvent*) event;						
+						Number posX = inputEvent->mousePosition.x - editorHolder->getPosition2D().x;
+						Number posY = inputEvent->mousePosition.y - editorHolder->getPosition2D().y;						
+						currentEditor->handleDroppedFile(draggedFile, posX, posY);
+					}
+				}
+				isDragging = false;
+				dragEntity->visible = false;
+			break;
+			case InputEvent::EVENT_MOUSEMOVE:
+				if(isDragging) {
+					dragEntity->setPosition(((InputEvent*)event)->mousePosition);
+				}
+			break;	
+		}
+	}
+
+	if(event->getDispatcher() == projectBrowser->treeContainer->getRootNode()) {
+		switch (event->getEventCode()) {
+			case UITreeEvent::DRAG_START_EVENT:
+			{
+				UITreeEvent *treeEvent = (UITreeEvent*) event;
+				BrowserUserData *data = (BrowserUserData*)treeEvent->selection->getUserData();
+				draggedFile = data->fileEntry;
+				dragLabel->setText(data->fileEntry.name);
+				dragEntity->visible = true;
+				isDragging = true;
+//				printf("START DRAG: %s\n", data->fileEntry.name.c_str());
+			}
+			break;
+		}
+	}
+
 	if(event->getDispatcher() == modalChild) {
 		if(event->getEventType() == "UIEvent" && event->getEventCode() == UIEvent::CLOSE_EVENT) {
 			hideModal();

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

@@ -48,13 +48,17 @@ PolycodeIDEApp::PolycodeIDEApp(PolycodeView *view) : EventDispatcher() {
 	editorManager = new PolycodeEditorManager();
 	
 	editorManager->registerEditorFactory(new PolycodeImageEditorFactory());
+	editorManager->registerEditorFactory(new PolycodeScreenEditorFactory());	
 	editorManager->registerEditorFactory(new PolycodeFontEditorFactory());
 	editorManager->registerEditorFactory(new PolycodeTextEditorFactory());
-	
+	editorManager->registerEditorFactory(new PolycodeProjectEditorFactory());
+		
 	frame = new PolycodeFrame();
 	frame->setPositionMode(ScreenEntity::POSITION_TOPLEFT);
-	
+
+	frame->textInputPopup->addEventListener(this, UIEvent::OK_EVENT);	
 	frame->newProjectWindow->addEventListener(this, UIEvent::OK_EVENT);
+	frame->newFileWindow->addEventListener(this, UIEvent::OK_EVENT);	
 	frame->exampleBrowserWindow->addEventListener(this, UIEvent::OK_EVENT);
 	
 	frame->playButton->addEventListener(this, UIEvent::CLICK_EVENT);
@@ -79,6 +83,22 @@ PolycodeIDEApp::PolycodeIDEApp(PolycodeView *view) : EventDispatcher() {
 	loadConfigFile();
 }
 
+void PolycodeIDEApp::renameFile() {
+	if(projectManager->selectedFile != "") {
+		frame->textInputPopup->setValue(projectManager->selectedFileEntry.name);
+		frame->showModal(frame->textInputPopup);
+	}
+}
+
+void PolycodeIDEApp::removeFile() {
+	if(projectManager->selectedFile != "") {
+		core->removeDiskItem(projectManager->selectedFile);
+		if(projectManager->getActiveProject()) {
+			frame->projectBrowser->refreshProject(projectManager->getActiveProject());
+		}
+	}
+}
+
 void PolycodeIDEApp::newProject() {
 	frame->newProjectWindow->ResetForm();
 	frame->showModal(frame->newProjectWindow);
@@ -92,6 +112,12 @@ void PolycodeIDEApp::newFile() {
 	}
 }
 
+void PolycodeIDEApp::refreshProject() {
+	if(projectManager->getActiveProject()) {
+		frame->getProjectBrowser()->refreshProject(projectManager->getActiveProject());
+	}
+}
+
 void PolycodeIDEApp::closeProject() {
 	if(projectManager->getActiveProject()) {
 		frame->getProjectBrowser()->removeProject(projectManager->getActiveProject());
@@ -99,6 +125,15 @@ void PolycodeIDEApp::closeProject() {
 	}
 }
 
+void PolycodeIDEApp::newGroup() {
+	if(projectManager->activeFolder != "") {
+		core->createFolder(projectManager->activeFolder+"/New Folder");
+		if(projectManager->getActiveProject()) {
+			frame->getProjectBrowser()->refreshProject(projectManager->getActiveProject());
+		}
+	}
+}
+
 void PolycodeIDEApp::openProject() {
 	
 	vector<CoreFileExtension> extensions;
@@ -155,8 +190,25 @@ void PolycodeIDEApp::handleEvent(Event *event) {
 		
 		if(event->getEventCode() == Event::CHANGE_EVENT) {
 			BrowserUserData *selectedData = frame->getProjectBrowser()->getSelectedData();
+						
+			if(selectedData->type == 3) {
+				projectManager->activeFolder = selectedData->parentProject->getRootFolder();
+				projectManager->selectedFile = "";				
+			} else if(selectedData->type == 0) {
+				projectManager->activeFolder = "";
+				projectManager->selectedFile = "";
+			} else {
+				projectManager->selectedFileEntry = selectedData->fileEntry;
+				projectManager->selectedFile = selectedData->fileEntry.fullPath;
+				if(selectedData->fileEntry.type == OSFileEntry::TYPE_FILE) {
+					projectManager->activeFolder = selectedData->fileEntry.basePath;
+				} else {
+					projectManager->activeFolder = selectedData->fileEntry.fullPath;
+				}			
+			}
 			
 			projectManager->setActiveProject(selectedData->parentProject);
+			
 			if(selectedData->type == 0)
 				return;			
 			
@@ -192,12 +244,43 @@ void PolycodeIDEApp::handleEvent(Event *event) {
 		}
 	}
 	
+	if(event->getDispatcher() == frame->textInputPopup) {
+		if(event->getEventType() == "UIEvent" && event->getEventCode() == UIEvent::OK_EVENT) {
+			core->moveDiskItem(projectManager->selectedFileEntry.fullPath, projectManager->selectedFileEntry.basePath + "/" + frame->textInputPopup->getValue());			
+			if(projectManager->getActiveProject()) {
+				frame->getProjectBrowser()->refreshProject(projectManager->getActiveProject());
+			}
+			
+			PolycodeEditor *editor = editorManager->getEditorForPath(projectManager->selectedFileEntry.fullPath);
+			if(editor) {
+				editor->setFilePath(projectManager->selectedFileEntry.basePath + "/" + frame->textInputPopup->getValue());
+			}
+			
+			projectManager->selectedFileEntry.fullPath = projectManager->selectedFileEntry.basePath + "/" + frame->textInputPopup->getValue();
+			projectManager->selectedFileEntry.name = frame->textInputPopup->getValue();
+			
+			
+			frame->hideModal();			
+		}
+	}	
+	
 	if(event->getDispatcher() == frame->newProjectWindow) {
 		if(event->getEventType() == "UIEvent" && event->getEventCode() == UIEvent::OK_EVENT) {
 			projectManager->createNewProject(frame->newProjectWindow->getTemplateFolder(), frame->newProjectWindow->getProjectName(), frame->newProjectWindow->getProjectLocation());
 			frame->hideModal();			
 		}
 	}
+
+	if(event->getDispatcher() == frame->newFileWindow) {
+		if(event->getEventType() == "UIEvent" && event->getEventCode() == UIEvent::OK_EVENT) {
+			projectManager->createNewFile(frame->newFileWindow->getTemplatePath(), frame->newFileWindow->getFileName());
+			frame->hideModal();			
+			
+			if(projectManager->getActiveProject()) {
+				frame->projectBrowser->refreshProject(projectManager->getActiveProject());
+			}			
+		}
+	}
 	
 	if(event->getDispatcher() == frame->exampleBrowserWindow) {
 		if(event->getEventType() == "UIEvent" && event->getEventCode() == UIEvent::OK_EVENT) {

+ 64 - 13
IDE/Contents/Source/PolycodeProjectBrowser.cpp

@@ -43,6 +43,21 @@ PolycodeProjectBrowser::~PolycodeProjectBrowser() {
 	
 }
 
+void PolycodeProjectBrowser::refreshProject(PolycodeProject *project) {
+	
+	UITree *projectTree = treeContainer->getRootNode();
+	
+	for(int i=0; i < projectTree->getNumTreeChildren(); i++) {
+		UITree *projectChild = projectTree->getTreeChild(i);
+		BrowserUserData *userData = (BrowserUserData*)projectChild->getUserData();
+		if(userData->parentProject == project) {
+			parseFolderIntoNode(projectChild, project->getRootFolder(), project);		
+			return;
+		}
+	}	
+	
+}
+
 void PolycodeProjectBrowser::removeProject(PolycodeProject *project) {
 	
 	UITree *projectTree = treeContainer->getRootNode();
@@ -62,7 +77,7 @@ void PolycodeProjectBrowser::addProject(PolycodeProject *project) {
 	projectTree->toggleCollapsed();
 	
 	BrowserUserData *data = new BrowserUserData();
-	data->type = 0;
+	data->type = 3;
 	data->parentProject = project;
 	projectTree->setUserData((void*) data)	;
 	
@@ -92,26 +107,62 @@ void PolycodeProjectBrowser::handleEvent(Event *event) {
 	ScreenEntity::handleEvent(event);
 }
 
+UITree *PolycodeProjectBrowser::nodeHasName(UITree *node, String name) {
+	for(int i=0; i < node->getNumTreeChildren(); i++) {
+		UITree *projectChild = node->getTreeChild(i);
+		if(projectChild->getLabelText() == name) {
+			return projectChild;
+		}
+	}
+	return NULL;
+}
+
+bool PolycodeProjectBrowser::listHasFileEntry(vector<OSFileEntry> files, OSFileEntry fileEntry) {
+	for(int i=0; i < files.size(); i++) {
+		if(files[i].fullPath == fileEntry.fullPath && files[i].type == fileEntry.type) {
+			return true;
+		}
+	}
+	return false;
+}
+
 void PolycodeProjectBrowser::parseFolderIntoNode(UITree *node, String spath, PolycodeProject *parentProject) {
 	printf("Parsing %s\n", spath.c_str());
 	vector<OSFileEntry> files = OSBasics::parseFolder(spath, false);
+	
+	// check if files got deleted
+	for(int i=0; i < node->getNumTreeChildren(); i++) {
+		UITree *projectChild = node->getTreeChild(i);
+		if(!listHasFileEntry(files, ((BrowserUserData*)projectChild->getUserData())->fileEntry)) {
+			node->removeTreeChild(projectChild);
+		}
+	}	
+	
 	for(int i=0; i < files.size(); i++) {
 		OSFileEntry entry = files[i];
 		if(entry.type == OSFileEntry::TYPE_FOLDER) {
-			BrowserUserData *data = new BrowserUserData();
-			data->fileEntry = entry;
-			UITree *newChild = node->addTreeChild("folder.png", entry.name, (void*) data);
-			data->type = 2;	
-			data->parentProject = parentProject;
-			parseFolderIntoNode(newChild, entry.fullPath, parentProject);
+			UITree *existing = nodeHasName(node, entry.name);
+			if(!existing) {		
+				BrowserUserData *data = new BrowserUserData();
+				data->fileEntry = entry;
+				UITree *newChild = node->addTreeChild("folder.png", entry.name, (void*) data);
+				data->type = 2;	
+				data->parentProject = parentProject;
+				parseFolderIntoNode(newChild, entry.fullPath, parentProject);				
+			} else {
+				parseFolderIntoNode(existing, entry.fullPath, parentProject);							
+			}
 		} else {
-			BrowserUserData *data = new BrowserUserData();
-			data->fileEntry = entry;
-			data->type = 1;
-			data->parentProject = parentProject;			
-			UITree *newChild = node->addTreeChild("file.png", entry.name, (void*) data);			
+			if(!nodeHasName(node, entry.name)) {
+				BrowserUserData *data = new BrowserUserData();
+				data->fileEntry = entry;
+				data->type = 1;
+				data->parentProject = parentProject;			
+				UITree *newChild = node->addTreeChild("file.png", entry.name, (void*) data);
+			}
 		}
-	}	
+	}		
+	
 }
 
 void PolycodeProjectBrowser::Resize(int newWidth, int newHeight) {

+ 268 - 0
IDE/Contents/Source/PolycodeProjectEditor.cpp

@@ -0,0 +1,268 @@
+/*
+ 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 "PolycodeProjectEditor.h"
+#include "OSBasics.h"
+
+PolycodeProjectEditor::PolycodeProjectEditor() : PolycodeEditor(true){
+
+	Config *conf = CoreServices::getInstance()->getConfig();	
+	String fontName = conf->getStringValue("Polycode", "uiDefaultFontName");
+	int fontSize = conf->getNumericValue("Polycode", "uiDefaultFontSize");	
+	Number padding = conf->getNumericValue("Polycode", "uiWindowSkinPadding");	
+		
+
+	moduleSettingsWindow = new UIWindow("Project Modules", 300, 200);
+	moduleSettingsWindow->setPosition(350,10);
+	addChild(moduleSettingsWindow);
+	
+	Number lastYPos = 50;
+	
+	String polycodeBasePath = CoreServices::getInstance()->getCore()->getDefaultWorkingDirectory();
+		
+	std::vector<OSFileEntry> moduleFolders = OSBasics::parseFolder(polycodeBasePath+"/Standalone/Modules", false);
+	for(int i=0; i < moduleFolders.size(); i++) {
+		OSFileEntry entry = moduleFolders[i];
+		if(entry.type == OSFileEntry::TYPE_FOLDER) {
+			UICheckBox *moduleCheckBox = new UICheckBox(entry.name, false);
+			moduleCheckBox->setPosition(padding, lastYPos);
+			lastYPos += moduleCheckBox->getHeight() + 5;
+			moduleSettingsWindow->addChild(moduleCheckBox);
+			moduleCheckboxes.push_back(moduleCheckBox);
+		}
+	}
+
+	mainSettingsWindow = new UIWindow("Project Settings", 300, 500);
+	mainSettingsWindow->setPosition(10,10);
+	addChild(mainSettingsWindow);
+	
+	ScreenLabel *label2 = new ScreenLabel(L"DEFAULT VIDEO OPTIONS", fontSize+2, fontName, Label::ANTIALIAS_FULL);	
+	label2->setColor(1.0, 1.0, 1.0, 0.5);
+	mainSettingsWindow->addChild(label2);
+	label2->setPosition(padding, 50);		
+
+		
+	label2 = new ScreenLabel(L"Width:", fontSize, fontName, Label::ANTIALIAS_FULL);
+	mainSettingsWindow->addChild(label2);
+	label2->setPosition(padding, 80);		
+	
+	defaultWidthInput = new UITextInput(false, 60, 12);	
+	mainSettingsWindow->addChild(defaultWidthInput);
+	defaultWidthInput->setPosition(label2->getPosition().x, label2->getPosition().y+label2->getHeight());
+	
+
+	label2 = new ScreenLabel(L"Height:", fontSize, fontName, Label::ANTIALIAS_FULL);
+	mainSettingsWindow->addChild(label2);
+	label2->setPosition(padding + 80, 80);		
+	
+	defaultHeightInput = new UITextInput(false, 60, 12);	
+	mainSettingsWindow->addChild(defaultHeightInput);
+	defaultHeightInput->setPosition(label2->getPosition().x, label2->getPosition().y+label2->getHeight());
+
+	
+	label2 = new ScreenLabel(L"Anti-aliasing:", fontSize, fontName, Label::ANTIALIAS_FULL);
+	mainSettingsWindow->addChild(label2);
+	label2->setPosition(padding + 160, 80);		
+	
+	aaLevelComboBox = new UIComboBox(120);		
+	aaLevelComboBox->addComboItem("No AA");
+	aaLevelComboBox->addComboItem("2x MSAA");
+	aaLevelComboBox->addComboItem("4x MSAA");
+	aaLevelComboBox->addComboItem("6x MSAA");			
+	aaLevelComboBox->setPosition(label2->getPosition().x, label2->getPosition().y+label2->getHeight());
+
+	label2 = new ScreenLabel(L"Anisotropic filtering:", fontSize, fontName, Label::ANTIALIAS_FULL);
+	mainSettingsWindow->addChild(label2);
+	label2->setPosition(padding, defaultHeightInput->getPosition().y+defaultHeightInput->getHeight()+10);		
+	
+	afLevelComboBox = new UIComboBox(250);		
+	afLevelComboBox->addComboItem("No Anisotropic Filtering");
+	afLevelComboBox->addComboItem("1x Anisotropic Filtering");
+	afLevelComboBox->addComboItem("2x Anisotropic Filtering");
+	afLevelComboBox->addComboItem("4x Anisotropic Filtering");
+	afLevelComboBox->addComboItem("8x Anisotropic Filtering");
+	afLevelComboBox->addComboItem("16x Anisotropic Filtering");			
+	afLevelComboBox->setPosition(label2->getPosition().x, label2->getPosition().y+label2->getHeight());
+
+	label2 = new ScreenLabel(L"Framerate:", fontSize, fontName, Label::ANTIALIAS_FULL);
+	mainSettingsWindow->addChild(label2);
+	label2->setPosition(padding, afLevelComboBox->getPosition().y+afLevelComboBox->getHeight()+10);		
+	
+	framerateInput = new UITextInput(false, 60, 12);	
+	mainSettingsWindow->addChild(framerateInput);
+	framerateInput->setPosition(label2->getPosition().x, label2->getPosition().y+label2->getHeight());
+
+	vSyncCheckBox = new UICheckBox("V-Sync", false);
+	vSyncCheckBox->setPosition(padding, framerateInput->getPosition().y+framerateInput->getHeight()+10);
+	mainSettingsWindow->addChild(vSyncCheckBox);
+	
+	label2 = new ScreenLabel(L"STARTUP OPTIONS", fontSize+2, fontName, Label::ANTIALIAS_FULL);	
+	label2->setColor(1.0, 1.0, 1.0, 0.5);
+	mainSettingsWindow->addChild(label2);
+	label2->setPosition(padding, vSyncCheckBox->getPosition().y+vSyncCheckBox->getHeight()+30);		
+	
+	
+	label2 = new ScreenLabel(L"Entry point file:", fontSize, fontName, Label::ANTIALIAS_FULL);
+	mainSettingsWindow->addChild(label2);
+	label2->setPosition(padding, vSyncCheckBox->getPosition().y+vSyncCheckBox->getHeight()+60);		
+	
+	entryPointInput = new UITextInput(false, 200, 12);	
+	mainSettingsWindow->addChild(entryPointInput);
+	entryPointInput->setPosition(label2->getPosition().x, label2->getPosition().y+label2->getHeight());
+
+
+	mainSettingsWindow->addChild(afLevelComboBox);			
+	mainSettingsWindow->addChild(aaLevelComboBox);		
+
+
+	label2 = new ScreenLabel(L"Background color:", fontSize, fontName, Label::ANTIALIAS_FULL);
+	mainSettingsWindow->addChild(label2);
+	label2->setPosition(padding, entryPointInput->getPosition().y+entryPointInput->getHeight()+10);		
+
+	bgColorBox = new UIColorBox(Color(1.0, 0.5, 0.0, 0.9), 30,30);
+	bgColorBox->setPosition(label2->getPosition().x, label2->getPosition().y+label2->getHeight());
+	mainSettingsWindow->addChild(bgColorBox);
+
+}
+
+PolycodeProjectEditor::~PolycodeProjectEditor() {
+	
+}
+
+bool PolycodeProjectEditor::openFile(String filePath) {
+
+
+	if(!configFile.loadFromXML(filePath)) {
+		return false;
+	}
+	
+	if(configFile.root["entryPoint"]) {	
+		entryPointInput->setText(configFile.root["entryPoint"]->stringVal);
+	} else {
+		configFile.root.addChild("entryPoint", "Source/Main.lua");		
+	}
+	
+	if(configFile.root["defaultWidth"]) {	
+		defaultWidthInput->setText(configFile.root["defaultWidth"]->stringVal);
+	} else {
+		configFile.root.addChild("defaultWidth", 640);	
+	}
+	
+	if(configFile.root["defaultHeight"]) {		
+		defaultHeightInput->setText(configFile.root["defaultHeight"]->stringVal);
+	} else {
+		configFile.root.addChild("defaultHeight", 480);
+	}
+
+	if(configFile.root["vSync"]) {	
+		vSyncCheckBox->setChecked(configFile.root["vSync"]->boolVal);
+	} else {
+		configFile.root.addChild("vSync", false);
+	}
+
+	
+
+	unsigned int aaMap[7] = {0,1,1,1,2,2,3};
+	if(configFile.root["antiAliasingLevel"]) {
+		aaLevelComboBox->setSelectedIndex(aaMap[configFile.root["antiAliasingLevel"]->intVal]);
+	} else {
+		aaLevelComboBox->setSelectedIndex(0);
+		configFile.root.addChild("antiAliasingLevel", 0);
+	}
+
+	unsigned int afMap[17] = {0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5};
+	if(configFile.root["anisotropyLevel"]) {
+		afLevelComboBox->setSelectedIndex(afMap[configFile.root["anisotropyLevel"]->intVal]);
+	} else {
+		afLevelComboBox->setSelectedIndex(0);
+		configFile.root.addChild("anisotropyLevel", 0);
+	}
+
+	if(configFile.root["frameRate"]) {
+		framerateInput->setText(configFile.root["frameRate"]->stringVal);	
+	} else {
+		configFile.root.addChild("frameRate", 60);	
+	}
+	
+	if(configFile.root["modules"]) {
+		for(int i=0; i < configFile.root["modules"]->length; i++) {
+			ObjectEntry *module = (*configFile.root["modules"])[i];
+			for(int j=0; j < moduleCheckboxes.size(); j++) {
+				if(moduleCheckboxes[j]->getCaptionLabel() == module->stringVal) {
+					moduleCheckboxes[j]->setChecked(true);
+				}
+			}
+		}
+	}	
+
+	Number backgroundColorR, backgroundColorG, backgroundColorB;	
+	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;
+			bgColorBox->setBoxColor(Color(backgroundColorR, backgroundColorG, backgroundColorB, 1.0));	
+		} else {
+			ObjectEntry *color = configFile.root.addChild("backgroundColor");
+			color->addChild("red", 0.0);
+			color->addChild("green", 0.0);
+			color->addChild("blue", 0.0);						
+		}
+	}
+	
+	PolycodeEditor::openFile(filePath);	
+	return true;
+}
+
+void PolycodeProjectEditor::Resize(int x, int y) {
+}
+
+void PolycodeProjectEditor::saveFile() {
+
+	configFile.root["frameRate"]->intVal = atoi(framerateInput->getText().c_str());
+	configFile.root["defaultWidth"]->intVal = atoi(defaultWidthInput->getText().c_str());
+	configFile.root["defaultHeight"]->intVal = atoi(defaultHeightInput->getText().c_str());	
+	configFile.root["entryPoint"]->stringVal = entryPointInput->getText();
+	
+	ObjectEntry *color = configFile.root["backgroundColor"];	
+	(*color)["red"]->NumberVal = bgColorBox->getSelectedColor().r;
+	(*color)["green"]->NumberVal = bgColorBox->getSelectedColor().g;
+	(*color)["blue"]->NumberVal = bgColorBox->getSelectedColor().b;
+
+
+	configFile.root["modules"]->Clear();
+	for(int j=0; j < moduleCheckboxes.size(); j++) {
+		if(moduleCheckboxes[j]->isChecked()) {
+			configFile.root["modules"]->addChild("module", moduleCheckboxes[j]->getCaptionLabel());
+		}
+	}
+	
+	unsigned int afMap[6] = {0,1,2,4,8,16};
+	unsigned int aaMap[4] = {0,2,4,6};
+		
+	configFile.root["antiAliasingLevel"]->intVal = aaMap[aaLevelComboBox->getSelectedIndex()];
+	configFile.root["anisotropyLevel"]->intVal = afMap[afLevelComboBox->getSelectedIndex()];
+	configFile.root["vSync"]->boolVal = vSyncCheckBox->isChecked();
+	
+	configFile.saveToXML(filePath);
+}

+ 11 - 0
IDE/Contents/Source/PolycodeProjectManager.cpp

@@ -24,6 +24,8 @@
 
 PolycodeProjectManager::PolycodeProjectManager() {
 	activeProject = NULL;
+	activeFolder = "";
+	selectedFile = "";
 }
 
 PolycodeProjectManager::~PolycodeProjectManager() {
@@ -74,6 +76,15 @@ int PolycodeProjectManager::removeProject(PolycodeProject *project) {
 	return 1;
 }
 
+void PolycodeProjectManager::createNewFile(String templatePath, String newFileName) {
+	if(activeFolder == "")
+		return;
+	
+	std::vector<String> bits = templatePath.split(".");
+	String extension = bits[bits.size()-1];
+	
+	CoreServices::getInstance()->getCore()->copyDiskItem(templatePath, activeFolder+"/"+newFileName+"."+extension);	
+}
 
 void PolycodeProjectManager::createNewProject(String templateFolder, String projectName, String projectLocation) {	
 

+ 190 - 0
IDE/Contents/Source/PolycodeScreenEditor.cpp

@@ -0,0 +1,190 @@
+/*
+ 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 "PolycodeScreenEditor.h"
+
+PolycodeScreenEditor::PolycodeScreenEditor() : PolycodeEditor(true){
+
+	Config *conf = CoreServices::getInstance()->getConfig();	
+	String fontName = conf->getStringValue("Polycode", "uiDefaultFontName");
+	int fontSize = conf->getNumericValue("Polycode", "uiDefaultFontSize");	
+	Number padding = conf->getNumericValue("Polycode", "uiWindowSkinPadding");	
+
+	isScalingEntity = false;
+	
+	selectedEntity = NULL;
+	isDraggingEntity = false; 
+	
+	grid = new ScreenImage("editorGrid.png");
+	
+	addChild(grid);
+	grid->snapToPixels = true;
+	
+	baseEntity = new ScreenEntity();
+	addChild(baseEntity);
+	
+	grid->getTexture()->clamp = false;
+	grid->getTexture()->recreateFromImageData();	
+		
+	baseEntity->setPositionMode(ScreenEntity::POSITION_CENTER);	
+
+	centerImage = new ScreenImage("screenCenter.png");
+	centerImage->setPositionMode(ScreenEntity::POSITION_CENTER);
+	addChild(centerImage);
+	
+	baseEntity->setPosition(256,256);
+	baseEntity->setWidth(20000);
+	baseEntity->setHeight(20000);
+		
+	centerImage->setPosition(256, 256);
+				
+	baseEntity->addEventListener(this, InputEvent::EVENT_MOUSEUP);
+	baseEntity->addEventListener(this, InputEvent::EVENT_MOUSEUP_OUTSIDE);
+	baseEntity->addEventListener(this, InputEvent::EVENT_MOUSEMOVE);
+	baseEntity->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
+					
+	screenTransform = new UIBox("screenTransform.png", 16,16,16,16, 100,100);
+	screenTransform->visible = false;
+	addChild(screenTransform);
+		
+	entityInfoWindow = new UIWindow("Selected entity", 140, 100);
+	addChild(entityInfoWindow);	
+	entityInfoWindow->setPosition(15,15);
+	
+	ScreenLabel *label2 = new ScreenLabel(L"Entity color:", fontSize, fontName, Label::ANTIALIAS_FULL);
+	entityInfoWindow->addChild(label2);
+	label2->setPosition(padding, entityInfoWindow->topPadding+20);
+
+	entityColorBox = new UIColorBox(Color(1.0, 1.0, 1.0, 0.0), 30,30);
+	entityColorBox->setPosition(label2->getPosition().x, label2->getPosition().y+label2->getHeight());
+	entityInfoWindow->addChild(entityColorBox);		
+	entityColorBox->addEventListener(this, UIEvent::CHANGE_EVENT);
+	
+}
+
+PolycodeScreenEditor::~PolycodeScreenEditor() {
+	
+}
+
+bool PolycodeScreenEditor::openFile(String filePath) {
+	
+	PolycodeEditor::openFile(filePath);	
+	return true;
+}
+
+void PolycodeScreenEditor::handleDroppedFile(OSFileEntry file, Number x, Number y) {
+	ScreenEntity *newEntity = NULL;
+	if(file.extension == "png") {
+		ScreenImage *newImage = new ScreenImage(file.fullPath);
+		newImage->setPositionMode(ScreenEntity::POSITION_CENTER);
+		baseEntity->addChild(newImage);
+		newImage->setPosition(x-baseEntity->getPosition2D().x,y-baseEntity->getPosition2D().y);
+		newEntity = newImage;
+	}
+	
+	if(newEntity) {
+		newEntity->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
+		newEntity->blockMouseInput = true;
+	}
+}
+
+void PolycodeScreenEditor::syncTransformToSelected() {
+	if(!selectedEntity)
+		return;
+		
+	screenTransform->resizeBox((selectedEntity->getWidth() * selectedEntity->getScale().x) + 5, (selectedEntity->getHeight() * selectedEntity->getScale().y) + 5);		
+	screenTransform->setPosition(selectedEntity->getPosition2D().x+baseEntity->getPosition2D().x-screenTransform->getWidth()/2.0,  selectedEntity->getPosition2D().y+baseEntity->getPosition2D().y-screenTransform->getHeight()/2.0);			
+}
+
+void PolycodeScreenEditor::handleEvent(Event *event) {
+	InputEvent *inputEvent = (InputEvent*) event;
+	
+	if(event->getDispatcher() == entityColorBox  && event->getEventType() == "UIEvent") {
+		switch (event->getEventCode()) {
+			case UIEvent::CHANGE_EVENT:
+				if(selectedEntity) {
+					selectedEntity->setColor(entityColorBox->getSelectedColor());
+				}
+			break;
+		}
+		return;
+	}
+	
+	if(event->getDispatcher() == baseEntity) {
+		switch (event->getEventCode()) {
+			case InputEvent::EVENT_MOUSEDOWN:
+				selectedEntity = NULL;
+				screenTransform->visible = false;
+			break;		
+			case InputEvent::EVENT_MOUSEUP:
+			case InputEvent::EVENT_MOUSEUP_OUTSIDE:			
+				isDraggingEntity = false;	
+				isScalingEntity = false;		
+			break;
+			case InputEvent::EVENT_MOUSEMOVE:
+			{
+				if(isDraggingEntity) {
+					selectedEntity->setPosition(inputEvent->mousePosition.x-baseEntity->getPosition2D().x - dragOffset.x, inputEvent->mousePosition.y-baseEntity->getPosition2D().y  - dragOffset.y);
+					syncTransformToSelected();
+				} else if(isScalingEntity) {
+//					Number newScale = Vector2(selectedEntity->getPosition2D().x + baseEntity->getPosition2D().x + dragOffset.x, selectedEntity->getPosition2D().y + baseEntity->getPosition2D().y + dragOffset.y).distance(inputEvent->mousePosition);
+
+					Vector2 scaleVector = Vector2(selectedEntity->getPosition2D().x + baseEntity->getPosition2D().x, selectedEntity->getPosition2D().y + baseEntity->getPosition2D().y) - inputEvent->mousePosition;
+					
+					scaleVector.x =	scaleVector.x / selectedEntity->getWidth() * 2.0;
+					scaleVector.y =	scaleVector.y / selectedEntity->getHeight() * 2.0;					
+					selectedEntity->setScale(scaleVector.x, scaleVector.y, 0);
+					syncTransformToSelected();
+				}
+			}
+			break;			
+		}
+		return;
+	}
+
+	for(int i=0; i < baseEntity->getNumChildren(); i++) {
+		ScreenEntity* childEntity = (ScreenEntity*) baseEntity->getChildAtIndex(i);
+		if(event->getDispatcher() == childEntity) {		
+			screenTransform->visible = true;
+			dragOffset.x = inputEvent->getMousePosition().x - childEntity->getPosition2D().x;
+			dragOffset.y = inputEvent->getMousePosition().y - childEntity->getPosition2D().y;						
+			
+			selectedEntity = childEntity;
+			entityColorBox->setBoxColor(selectedEntity->color);
+			syncTransformToSelected();
+			
+			Number cornerSize = 12;
+			if(dragOffset.x < -(selectedEntity->getWidth()/2.0) + cornerSize && dragOffset.y <  -(selectedEntity->getHeight()/2.0) +  cornerSize) {
+				isScalingEntity = true;
+			} else {
+				isDraggingEntity = true;						
+			}
+			
+			
+		}
+	}
+}
+
+void PolycodeScreenEditor::Resize(int x, int y) {
+	grid->setImageCoordinates(0,0,x,y);	
+}
+

+ 0 - 1
IDE/Contents/Source/PolycodeTextEditor.cpp

@@ -23,7 +23,6 @@
 #include "PolycodeTextEditor.h"
 
 PolycodeTextEditor::PolycodeTextEditor() : PolycodeEditor(true){
-
 }
 
 PolycodeTextEditor::~PolycodeTextEditor() {

+ 72 - 0
IDE/Contents/Source/ToolWindows.cpp

@@ -0,0 +1,72 @@
+/*
+ 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 "ToolWindows.h"
+
+TextInputPopup::TextInputPopup() : UIWindow(L"", 300, 95) {
+	
+	textInput = new UITextInput(false, 300-(padding*3.0), 12);	
+	addChild(textInput);
+	textInput->setPosition(padding, 35);
+		
+	cancelButton = new UIButton(L"Cancel", 100);
+	cancelButton->addEventListener(this, UIEvent::CLICK_EVENT);
+	addChild(cancelButton);
+	cancelButton->setPosition(300-100-padding-100-10, 60);		
+	
+	okButton = new UIButton(L"OK", 100);
+	okButton->addEventListener(this, UIEvent::CLICK_EVENT);
+	addChild(okButton);
+	okButton->setPosition(300-100-padding, 60);
+	
+	closeOnEscape = true;
+
+}
+
+String TextInputPopup::getValue() {
+	return textInput->getText();
+}
+
+void TextInputPopup::setValue(String value) {
+	textInput->setText(value);
+	focusChild(textInput);	
+}
+
+void TextInputPopup::handleEvent(Event *event) {
+	if(event->getEventType() == "UIEvent") {
+		if(event->getEventCode() == UIEvent::CLICK_EVENT) {
+			if(event->getDispatcher() == okButton) {
+				dispatchEvent(new UIEvent(), UIEvent::OK_EVENT);						
+			}
+			
+			if(event->getDispatcher() == cancelButton) {
+				dispatchEvent(new UIEvent(), UIEvent::CLOSE_EVENT);				
+			}									
+		}
+	}
+	UIWindow::handleEvent(event);	
+}
+
+
+TextInputPopup::~TextInputPopup() {
+	
+}

+ 30 - 0
Modules/Contents/3DPhysics/Include/PolyPhysicsScene.h

@@ -33,6 +33,26 @@ namespace Polycode {
 	class PhysicsSceneEntity;
 	class PhysicsCharacter;
 	class PhysicsVehicle;
+	
+	class _PolyExport PhysicsSceneEvent : public Event {
+		public:
+			PhysicsSceneEvent() : Event () {
+				eventType = "PhysicsSceneEvent";
+			}
+			~PhysicsSceneEvent() {
+			}
+			
+			static const int COLLISION_EVENT = 0;
+			
+			PhysicsSceneEntity *entityA;
+			PhysicsSceneEntity *entityB;
+
+			Number appliedImpulse;
+						
+			Vector3 positionOnA;
+			Vector3 positionOnB;
+			Vector3 worldNormalOnB;				
+	};
 
 	/**
 	* A scene subclass that simulates physics for its children.
@@ -49,6 +69,10 @@ namespace Polycode {
 		
 		void removeEntity(SceneEntity *entity);
 		
+		void processWorldCollisions();
+		
+		PhysicsSceneEntity *getPhysicsEntityByCollisionObject(btCollisionObject *object);
+		
 			/** @name Physics scene
 			*  Public methods
 			*/
@@ -63,7 +87,13 @@ namespace Polycode {
 		PhysicsCharacter *addCharacterChild(SceneEntity *newEntity, Number mass, Number friction, Number stepSize, int group  = 1);
 		void removeCharacterChild(PhysicsCharacter *character);
 		
+		
+		void setVelocity(SceneEntity *entity, Vector3 velocity);
+		void warpEntity(SceneEntity *entity, Vector3 position, bool resetRotation = false);
+		
 		PhysicsVehicle *addVehicleChild(SceneEntity *newEntity, Number mass, Number friction, int group  = 1);
+		
+		void setGravity(Vector3 gravity);
 			//@}
 			// ----------------------------------------------------------------------------------------------------------------
 

+ 3 - 0
Modules/Contents/3DPhysics/Include/PolyPhysicsSceneEntity.h

@@ -49,6 +49,9 @@ namespace Polycode {
 		SceneEntity *getSceneEntity();
 		void setFriction(Number friction);		
 		int getType() { return type; }	
+		
+			void setVelocity(Vector3 velocity);
+			void warpTo(Vector3 position, bool resetRotation);
 			//@}
 			// ----------------------------------------------------------------------------------------------------------------
 			

+ 10 - 2
Modules/Contents/3DPhysics/Source/PolyCollisionSceneEntity.cpp

@@ -61,6 +61,14 @@ btCollisionShape *CollisionSceneEntity::createCollisionShape(SceneEntity *entity
 	
 	btCollisionShape *collisionShape = NULL;	
 	
+	Vector3 entityScale = entity->getScale();
+	Number largestScale = entityScale.x;
+	if(entityScale.y > largestScale)
+		largestScale = entityScale.y;
+	if(entityScale.z > largestScale)
+		largestScale = entityScale.z;
+
+	
 	switch(type) {
 		case SHAPE_CAPSULE:
 		case CHARACTER_CONTROLLER:
@@ -83,10 +91,10 @@ btCollisionShape *CollisionSceneEntity::createCollisionShape(SceneEntity *entity
 			collisionShape = new btBoxShape(btVector3(entity->bBox.x/2.0f, 0.05,entity->bBox.z/2.0f));			
 			break;
 		case SHAPE_BOX:
-			collisionShape = new btBoxShape(btVector3(entity->bBox.x/2.0f, entity->bBox.y/2.0f,entity->bBox.z/2.0f));			
+			collisionShape = new btBoxShape(btVector3(entity->bBox.x/2.0f*entityScale.x, entity->bBox.y/2.0f*entityScale.y,entity->bBox.z/2.0f*entityScale.z));			
 			break;
 		case SHAPE_SPHERE:
-			collisionShape = new btSphereShape(entity->bBox.x/2.0f);
+			collisionShape = new btSphereShape(entity->bBox.x/2.0f*largestScale);
 			break;
 		case SHAPE_MESH:
 		{

+ 73 - 1
Modules/Contents/3DPhysics/Source/PolyPhysicsScene.cpp

@@ -42,6 +42,11 @@ PhysicsScene::~PhysicsScene() {
 	
 }
 
+void worldTickCallback(btDynamicsWorld *world, btScalar timeStep) {
+	PhysicsScene *physicsScene = (PhysicsScene*)world->getWorldUserInfo();
+	physicsScene->processWorldCollisions();
+}
+
 void PhysicsScene::initPhysicsScene() {
 		
 	
@@ -67,6 +72,59 @@ void PhysicsScene::initPhysicsScene() {
 	sweepBP->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
 	
 	world = physicsWorld;
+	
+	physicsWorld->setInternalTickCallback(worldTickCallback, this);
+}
+
+void PhysicsScene::setGravity(Vector3 gravity) {
+	physicsWorld->setGravity(btVector3(gravity.x, gravity.y, gravity.z));
+}
+
+PhysicsSceneEntity *PhysicsScene::getPhysicsEntityByCollisionObject(btCollisionObject *object) {
+	for(int i=0; i < physicsChildren.size(); i++) {
+		PhysicsSceneEntity *entity = physicsChildren[i];
+		if(entity->rigidBody == object) {
+			return entity;
+		}
+	}
+	return  NULL;
+}
+
+void PhysicsScene::processWorldCollisions() {
+
+	int numManifolds = physicsWorld->getDispatcher()->getNumManifolds();
+	for (int i=0;i<numManifolds;i++)
+	{
+		btPersistentManifold* contactManifold =  world->getDispatcher()->getManifoldByIndexInternal(i);
+		btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
+		btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
+	
+		
+		int numContacts = contactManifold->getNumContacts();
+		for (int j=0;j<numContacts;j++)
+		{
+			btManifoldPoint& pt = contactManifold->getContactPoint(j);
+			if (pt.getDistance()<0.f)
+			{
+				const btVector3& ptA = pt.getPositionWorldOnA();
+				const btVector3& ptB = pt.getPositionWorldOnB();
+				const btVector3& normalOnB = pt.m_normalWorldOnB;
+				const btScalar appliedImpulse = pt.m_appliedImpulse;
+				
+				PhysicsSceneEvent *event = new PhysicsSceneEvent();
+				event->positionOnA = Vector3(ptA.x(), ptA.y(), ptA.z());
+				event->positionOnB = Vector3(ptB.x(), ptB.y(), ptB.z());
+				event->worldNormalOnB = Vector3(normalOnB.x(), normalOnB.y(), normalOnB.z());
+				event->appliedImpulse = appliedImpulse;				
+								
+				event->entityA = getPhysicsEntityByCollisionObject(obA);	
+				event->entityB = getPhysicsEntityByCollisionObject(obB);
+												
+				dispatchEvent(event, PhysicsSceneEvent::COLLISION_EVENT);
+			}
+		}
+	}
+
 }
 
 void PhysicsScene::Update() {
@@ -87,6 +145,20 @@ void PhysicsScene::Update() {
 	
 }
 
+void PhysicsScene::setVelocity(SceneEntity *entity, Vector3 velocity) {
+	PhysicsSceneEntity *physicsEntity = getPhysicsEntityBySceneEntity(entity);
+	if(physicsEntity) {
+		physicsEntity->setVelocity(velocity);
+	}
+}
+
+void PhysicsScene::warpEntity(SceneEntity *entity, Vector3 position, bool resetRotation) {
+	PhysicsSceneEntity *physicsEntity = getPhysicsEntityBySceneEntity(entity);
+	if(physicsEntity) {
+		physicsEntity->warpTo(position, resetRotation);
+	}
+}
+
 PhysicsCharacter *PhysicsScene::addCharacterChild(SceneEntity *newEntity,Number mass, Number friction, Number stepSize, int group) {
 	addEntity(newEntity);	
 	PhysicsCharacter *newPhysicsEntity = new PhysicsCharacter(newEntity, mass, friction, stepSize);
@@ -205,7 +277,7 @@ PhysicsSceneEntity *PhysicsScene::trackPhysicsChild(SceneEntity *newEntity, int
 	PhysicsSceneEntity *newPhysicsEntity = new PhysicsSceneEntity(newEntity, type, mass, friction,restitution);
 	physicsWorld->addRigidBody(newPhysicsEntity->rigidBody, group,  btBroadphaseProxy::AllFilter); //btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);	
 //	world->addCollisionObject(newPhysicsEntity->collisionObject, group);	
-	//	newPhysicsEntity->rigidBody->setActivationState(ISLAND_SLEEPING);	
+	//newPhysicsEntity->rigidBody->setActivationState(ISLAND_SLEEPING);	
 	physicsChildren.push_back(newPhysicsEntity);
 	collisionChildren.push_back(newPhysicsEntity);	
 	return newPhysicsEntity;	

Некоторые файлы не были показаны из-за большого количества измененных файлов