Sfoglia il codice sorgente

Merge remote-tracking branch 'upstream/development' into development

marauder2k7 2 anni fa
parent
commit
cc5a8108c7
100 ha cambiato i file con 909 aggiunte e 428 eliminazioni
  1. 1 0
      .gitignore
  2. 6 5
      CMakeLists.txt
  3. 11 1
      Engine/lib/CMakeLists.txt
  4. 5 5
      Engine/lib/Torque_postBuild.cmake
  5. 2 0
      Engine/lib/nativeFileDialogs/CMakeLists.txt
  6. 9 9
      Engine/lib/nativeFileDialogs/nfd_cocoa.m
  7. 68 12
      Engine/source/CMakeLists.txt
  8. 1 1
      Engine/source/T3D/accumulationVolume.h
  9. 1 0
      Engine/source/T3D/aiPlayer.h
  10. 8 18
      Engine/source/T3D/assets/ImageAsset.cpp
  11. 2 3
      Engine/source/T3D/assets/ImageAsset.h
  12. 7 6
      Engine/source/T3D/assets/MaterialAsset.cpp
  13. 1 1
      Engine/source/T3D/assets/MaterialAsset.h
  14. 8 8
      Engine/source/T3D/assets/ShapeAsset.cpp
  15. 2 2
      Engine/source/T3D/assets/ShapeAsset.h
  16. 248 55
      Engine/source/T3D/assets/SoundAsset.cpp
  17. 58 25
      Engine/source/T3D/assets/SoundAsset.h
  18. 6 6
      Engine/source/T3D/assets/TerrainAsset.cpp
  19. 1 1
      Engine/source/T3D/assets/TerrainAsset.h
  20. 7 6
      Engine/source/T3D/assets/TerrainMaterialAsset.cpp
  21. 1 1
      Engine/source/T3D/assets/TerrainMaterialAsset.h
  22. 1 1
      Engine/source/T3D/camera.h
  23. 2 4
      Engine/source/T3D/convexShape.cpp
  24. 1 0
      Engine/source/T3D/convexShape.h
  25. 1 0
      Engine/source/T3D/debris.h
  26. 1 0
      Engine/source/T3D/decal/decalManager.cpp
  27. 1 0
      Engine/source/T3D/decal/decalManager.h
  28. 1 1
      Engine/source/T3D/fps/guiHealthBarHud.cpp
  29. 1 1
      Engine/source/T3D/fps/guiHealthTextHud.cpp
  30. 1 1
      Engine/source/T3D/fps/guiShapeNameHud.cpp
  31. 1 1
      Engine/source/T3D/fx/explosion.cpp
  32. 1 0
      Engine/source/T3D/fx/explosion.h
  33. 1 0
      Engine/source/T3D/fx/fxFoliageReplicator.h
  34. 2 0
      Engine/source/T3D/fx/fxShapeReplicator.h
  35. 1 0
      Engine/source/T3D/fx/groundCover.h
  36. 1 0
      Engine/source/T3D/fx/lightning.h
  37. 2 1
      Engine/source/T3D/fx/particleEmitter.h
  38. 1 0
      Engine/source/T3D/fx/particleEmitterNode.h
  39. 1 0
      Engine/source/T3D/fx/precipitation.h
  40. 1 0
      Engine/source/T3D/fx/ribbon.h
  41. 1 0
      Engine/source/T3D/fx/ribbonNode.h
  42. 1 1
      Engine/source/T3D/fx/splash.cpp
  43. 1 0
      Engine/source/T3D/fx/splash.h
  44. 2 0
      Engine/source/T3D/gameBase/gameBase.h
  45. 1 1
      Engine/source/T3D/gameBase/gameConnection.cpp
  46. 2 2
      Engine/source/T3D/gameBase/gameConnectionEvents.cpp
  47. 1 0
      Engine/source/T3D/groundPlane.h
  48. 101 98
      Engine/source/T3D/guiObjectView.cpp
  49. 26 27
      Engine/source/T3D/guiObjectView.h
  50. 1 0
      Engine/source/T3D/item.h
  51. 1 0
      Engine/source/T3D/lightBase.h
  52. 1 0
      Engine/source/T3D/lighting/boxEnvironmentProbe.h
  53. 7 1
      Engine/source/T3D/lighting/reflectionProbe.cpp
  54. 1 0
      Engine/source/T3D/lighting/reflectionProbe.h
  55. 1 0
      Engine/source/T3D/lighting/skylight.h
  56. 1 0
      Engine/source/T3D/lighting/sphereEnvironmentProbe.h
  57. 3 1
      Engine/source/T3D/missionMarker.h
  58. 1 0
      Engine/source/T3D/notesObject.h
  59. 1 1
      Engine/source/T3D/occlusionVolume.h
  60. 1 0
      Engine/source/T3D/pathCamera.h
  61. 1 0
      Engine/source/T3D/pathShape.h
  62. 1 0
      Engine/source/T3D/physicalZone.h
  63. 1 0
      Engine/source/T3D/physics/physicsDebris.h
  64. 2 2
      Engine/source/T3D/physics/physicsForce.h
  65. 1 0
      Engine/source/T3D/physics/physicsShape.h
  66. 1 0
      Engine/source/T3D/player.h
  67. 1 0
      Engine/source/T3D/pointLight.h
  68. 2 1
      Engine/source/T3D/portal.h
  69. 1 0
      Engine/source/T3D/prefab.h
  70. 1 0
      Engine/source/T3D/projectile.h
  71. 1 1
      Engine/source/T3D/rigid.cpp
  72. 37 64
      Engine/source/T3D/rigidShape.cpp
  73. 2 2
      Engine/source/T3D/rigidShape.h
  74. 1 0
      Engine/source/T3D/scopeAlwaysShape.cpp
  75. 163 16
      Engine/source/T3D/sfx/sfxEmitter.cpp
  76. 23 3
      Engine/source/T3D/sfx/sfxEmitter.h
  77. 1 1
      Engine/source/T3D/sfx/sfxSpace.h
  78. 6 3
      Engine/source/T3D/shapeBase.cpp
  79. 1 1
      Engine/source/T3D/shapeBase.h
  80. 2 2
      Engine/source/T3D/shapeImage.cpp
  81. 1 0
      Engine/source/T3D/spotLight.h
  82. 1 0
      Engine/source/T3D/staticShape.h
  83. 1 0
      Engine/source/T3D/trigger.h
  84. 1 0
      Engine/source/T3D/tsStatic.h
  85. 14 7
      Engine/source/T3D/vehicles/flyingVehicle.cpp
  86. 1 0
      Engine/source/T3D/vehicles/flyingVehicle.h
  87. 1 0
      Engine/source/T3D/vehicles/hoverVehicle.h
  88. 2 2
      Engine/source/T3D/vehicles/vehicle.cpp
  89. 1 0
      Engine/source/T3D/vehicles/vehicle.h
  90. 1 0
      Engine/source/T3D/vehicles/vehicleBlocker.h
  91. 1 0
      Engine/source/T3D/vehicles/wheeledVehicle.h
  92. 1 1
      Engine/source/T3D/zone.h
  93. 1 2
      Engine/source/afx/afxCamera.h
  94. 1 2
      Engine/source/afx/afxChoreographer.h
  95. 0 1
      Engine/source/afx/afxEffectGroup.h
  96. 0 3
      Engine/source/afx/afxEffectWrapper.h
  97. 0 2
      Engine/source/afx/afxEffectron.h
  98. 1 2
      Engine/source/afx/afxMagicMissile.h
  99. 0 2
      Engine/source/afx/afxMagicSpell.h
  100. 1 1
      Engine/source/afx/afxResidueMgr.h

+ 1 - 0
.gitignore

@@ -68,6 +68,7 @@ local.properties
 .builds
 *.dotCover
 *.dll
+!d3dcompiler_47.dll
 *.lib
 *.exp
 *.exe

+ 6 - 5
CMakeLists.txt

@@ -4,10 +4,6 @@ set(CMAKE_CONFIGURATION_TYPES "Debug;RelWithDebInfo;Release" CACHE STRING "" FOR
 
 include("${CMAKE_SOURCE_DIR}/Tools/CMake/torque_macros.cmake")
 include("${CMAKE_SOURCE_DIR}/Tools/CMake/torque_configs.cmake")
-file(GLOB OS_SCRIPTS "${CMAKE_SOURCE_DIR}/Tools/CMake/torque*configs.cmake")
-foreach (TORQUE_OS_SCRIPT ${OS_SCRIPTS})
-    include(${TORQUE_OS_SCRIPT})
-endforeach() 
 
 # Ensure multi-core compilation is enabled for everything
 add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/MP>)
@@ -27,9 +23,10 @@ set(TORQUE_APP_GAME_DIRECTORY "${TORQUE_APP_ROOT_DIRECTORY}/game")
 #library handling
 set(TORQUE_LIB_ROOT_DIRECTORY "${CMAKE_SOURCE_DIR}/Engine/lib")
 set(TORQUE_LIB_TARG_DIRECTORY "${CMAKE_BINARY_DIR}/Engine/lib")
+set(TORQUE_SOURCE_DIRECTROY "${CMAKE_SOURCE_DIR}/Engine/source")
 
 # Ensure all possible configurations end up in the project directory
-set(CMAKE_INSTALL_PREFIX "${TORQUE_APP_ROOT_DIRECTORY}")
+set(CMAKE_INSTALL_PREFIX "${TORQUE_APP_ROOT_DIRECTORY}" CACHE STRING "" FORCE)
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${TORQUE_APP_GAME_DIRECTORY}")
 foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} )
     string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG )
@@ -73,4 +70,8 @@ endif(NOT TORQUE_INSTALLED_TEMPLATE)
 # Generate torqueConfig.h in our temp directory
 configure_file("${CMAKE_SOURCE_DIR}/Tools/CMake/torqueConfig.h.in" "${TORQUE_APP_ROOT_DIRECTORY}/source/torqueConfig.h")
 
+if(APPLE)
+include("${CMAKE_SOURCE_DIR}/Tools/CMake/torqueMacOSconfigs.cmake")
+endif(APPLE)
+
 add_subdirectory(Engine)

+ 11 - 1
Engine/lib/CMakeLists.txt

@@ -110,6 +110,7 @@ mark_as_advanced(SDL_X11)
 mark_as_advanced(SDL_XINPUT)
 
 add_subdirectory(sdl ${TORQUE_LIB_TARG_DIRECTORY}/sdl2 EXCLUDE_FROM_ALL)
+
 add_subdirectory(nativeFileDialogs ${TORQUE_LIB_TARG_DIRECTORY}/nfd EXCLUDE_FROM_ALL)
 
 # Assimp
@@ -153,10 +154,17 @@ mark_as_advanced(ASSIMP_PACKAGE_VERSION)
 mark_as_advanced(ASSIMP_RUNTIME_OUTPUT_DIRECTORY)
 add_subdirectory(assimp ${TORQUE_LIB_TARG_DIRECTORY}/assimp EXCLUDE_FROM_ALL)
 target_compile_definitions(assimp PUBLIC ASSIMP_BUILD_NO_OWN_ZLIB)
+
 if (TORQUE_CPU_ARM32 OR TORQUE_CPU_ARM64)
-	set(PNG_ARM_NEON on CACHE BOOL "" FORCE)
+    if(NOT APPLE)
+	    set(PNG_ARM_NEON on CACHE BOOL "" FORCE)
+    endif(NOT APPLE)
 endif (TORQUE_CPU_ARM32 OR TORQUE_CPU_ARM64)
 
+if(APPLE)
+    set(PNG_ARM_NEON off CACHE BOOL "" FORCE)
+endif()
+
 #PNG
 set(PNG_STATIC on CACHE BOOL "" FORCE)
 mark_as_advanced(PNG_STATIC)
@@ -168,10 +176,12 @@ set(PNG_TESTS off CACHE BOOL "" FORCE)
 mark_as_advanced(PNG_TESTS)
 set(PNG_HARDWARE_OPTIMIZATIONS on CACHE BOOL "" FORCE)
 mark_as_advanced(PNG_HARDWARE_OPTIMIZATIONS)
+
 if(APPLE)
     set(PNG_FRAMEWORK on CACHE BOOL "" FORCE)
     addDef(PNG_DEBUG Debug)
 endif()
+
 mark_as_advanced(PNG_DEBUG)
 mark_as_advanced(PNG_FRAMEWORK)
 mark_as_advanced(PNG_PREFIX)

+ 5 - 5
Engine/lib/Torque_postBuild.cmake

@@ -2,9 +2,9 @@
 
 # When on Windows, we need to link against winsock and windows codecs
 if (WIN32)
-	set(TORQUE_LINK_LIBRARIES ${TORQUE_LINK_LIBRARIES} WS2_32.LIB windowscodecs.lib)	
+	set(TORQUE_LINK_WINDOWS ${TORQUE_LINK_WINDOWS} WS2_32.LIB windowscodecs.lib)	
 	if (TORQUE_D3D11)
-		set(TORQUE_LINK_LIBRARIES ${TORQUE_LINK_LIBRARIES} dxguid.lib)
+		set(TORQUE_LINK_WINDOWS ${TORQUE_LINK_WINDOWS} dxguid.lib)
 	endif (TORQUE_D3D11)
 endif (WIN32)
 
@@ -19,7 +19,7 @@ if (APPLE)
     addFramework("IOKit")
     #grrr damn you sdl!
     addFramework("Carbon")
-    set(TORQUE_LINK_LIBRARIES ${TORQUE_LINK_LIBRARIES} iconv)
+    set(TORQUE_LINK_FRAMEWORKS ${TORQUE_LINK_FRAMEWORKS} iconv)
     if(NOT TORQUE_DEDICATED)
         addFramework("OpenGL")
         addFramework("CoreVideo")
@@ -36,8 +36,8 @@ set(TORQUE_LINK_LIBRARIES ${TORQUE_LINK_LIBRARIES} nativeFileDialogs)
 
 # Linux requires X11 & freetype
 if (UNIX AND NOT APPLE)
-	set(TORQUE_LINK_LIBRARIES ${TORQUE_LINK_LIBRARIES} "X11" "Xft" "dl" "pthread")  
+	set(TORQUE_LINK_LINUX ${TORQUE_LINK_LINUX} "X11" "Xft" "dl" "pthread")  
 	find_package(Freetype REQUIRED)
 	set(TORQUE_INCLUDE_DIRECTORIES ${TORQUE_INCLUDE_DIRECTORIES} ${FREETYPE_INCLUDE_DIRS})
-	set(TORQUE_LINK_LIBRARIES ${TORQUE_LINK_LIBRARIES} ${FREETYPE_LIBRARIES})
+	set(TORQUE_LINK_LINUX ${TORQUE_LINK_LINUX} ${FREETYPE_LIBRARIES})
 endif (UNIX AND NOT APPLE)

+ 2 - 0
Engine/lib/nativeFileDialogs/CMakeLists.txt

@@ -5,7 +5,9 @@ set(TORQUE_NFD_COMMON_SOURCES "${TORQUE_NFD_ROOT}/nfd_common.c")
 set(TORQUE_NFD_INCLUDE_DIRECTORIES "${TORQUE_NFD_ROOT}" "${TORQUE_NFD_ROOT}/include")
 
 if (APPLE)
+  enable_language(OBJC)
   set(TORQUE_NFD_SOURCES ${TORQUE_NFD_COMMON_SOURCES} "${TORQUE_NFD_ROOT}/nfd_cocoa.m")
+  set_source_files_properties(${TORQUE_NFD_SOURCES} PROPERTIES LANGUAGE OBJC)
 elseif (UNIX)
   if (TORQUE_USE_ZENITY)
     set(TORQUE_NFD_SOURCES ${TORQUE_NFD_COMMON_SOURCES} "${TORQUE_NFD_ROOT}/nfd_zenity.c")

+ 9 - 9
Engine/lib/nativeFileDialogs/nfd_cocoa.m

@@ -64,7 +64,7 @@ static void SetDefaultPath( NSSavePanel *dialog, const nfdchar_t *defaultPath )
 
     NSString *defaultPathString = [NSString stringWithUTF8String: defaultPath];
     NSURL *url = [NSURL fileURLWithPath:defaultPathString isDirectory:YES];
-    [dialog setDirectoryURL:url];    
+    [dialog setDirectoryURL:url];
 }
 
 
@@ -76,7 +76,7 @@ static nfdresult_t AllocPathSet( NSArray *urls, nfdpathset_t *pathset )
 
     pathset->count = (size_t)[urls count];
     pathset->indices = NFDi_Malloc( sizeof(size_t)*pathset->count );
-    if ( !pathset->indices ) 
+    if ( !pathset->indices )
     {
         return NFD_ERROR;
     }
@@ -125,7 +125,7 @@ nfdresult_t NFD_OpenDialog( const nfdchar_t *filterList,
 {
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
-    NSWindow *keyWindow = [[NSApplication sharedApplication] keyWindow];    
+    NSWindow *keyWindow = [[NSApplication sharedApplication] keyWindow];
     NSOpenPanel *dialog = [NSOpenPanel openPanel];
     [dialog setAllowsMultipleSelection:NO];
 
@@ -148,7 +148,7 @@ nfdresult_t NFD_OpenDialog( const nfdchar_t *filterList,
         if ( !*outPath )
         {
             [pool release];
-            [keyWindow makeKeyAndOrderFront:nil];            
+            [keyWindow makeKeyAndOrderFront:nil];
             return NFD_ERROR;
         }
         memcpy( *outPath, utf8Path, len+1 ); /* copy null term */
@@ -185,14 +185,14 @@ nfdresult_t NFD_OpenDialogMultiple( const nfdchar_t *filterList,
         if ( [urls count] == 0 )
         {
             [pool release];
-            [keyWindow makeKeyAndOrderFront:nil];            
+            [keyWindow makeKeyAndOrderFront:nil];
             return NFD_CANCEL;
         }
 
         if ( AllocPathSet( urls, outPaths ) == NFD_ERROR )
         {
             [pool release];
-            [keyWindow makeKeyAndOrderFront:nil];            
+            [keyWindow makeKeyAndOrderFront:nil];
             return NFD_ERROR;
         }
 
@@ -200,7 +200,7 @@ nfdresult_t NFD_OpenDialogMultiple( const nfdchar_t *filterList,
     }
     [pool release];
 
-    [keyWindow makeKeyAndOrderFront:nil];    
+    [keyWindow makeKeyAndOrderFront:nil];
     return nfdResult;
 }
 
@@ -233,7 +233,7 @@ nfdresult_t NFD_SaveDialog( const nfdchar_t *filterList,
         if ( !*outPath )
         {
             [pool release];
-            [keyWindow makeKeyAndOrderFront:nil];            
+            [keyWindow makeKeyAndOrderFront:nil];
             return NFD_ERROR;
         }
         memcpy( *outPath, utf8Path, byteLen );
@@ -273,7 +273,7 @@ nfdresult_t NFD_PickFolder(const nfdchar_t *defaultPath,
         if ( !*outPath )
         {
             [pool release];
-            [keyWindow makeKeyAndOrderFront:nil];            
+            [keyWindow makeKeyAndOrderFront:nil];
             return NFD_ERROR;
         }
         memcpy( *outPath, utf8Path, len+1 ); /* copy null term */

+ 68 - 12
Engine/source/CMakeLists.txt

@@ -57,7 +57,6 @@ torqueAddSourceDirectories("platform" "platform/threads" "platform/async"
                                   "platform/input" "platform/output")
 
 torqueAddSourceDirectories("platform/nativeDialogs")
-
 # Handle T3D
 torqueAddSourceDirectories("T3D/fps" "T3D/fx" "T3D/vehicles" "T3D/physics"
                               "T3D/decal" "T3D/sfx" "T3D/gameBase" "T3D/turret"
@@ -151,6 +150,12 @@ endif (TORQUE_OPENGL)
 # Handle terrain
 torqueAddSourceDirectories("terrain")
 
+# Handle theora
+if (TORQUE_THEORA)
+  torqueAddSourceDirectories("core/ogg")
+  torqueAddSourceDirectories("gui/theora")
+endif(TORQUE_THEORA)
+
 if (WIN32 AND TORQUE_D3D11)
   torqueAddSourceDirectories("terrain/hlsl")
 endif (WIN32 AND TORQUE_D3D11)
@@ -199,9 +204,11 @@ torqueAddSourceDirectories("i18n")
 if (UNIX)
 	torqueAddSourceDirectories("platformPOSIX")
 
-	if (TORQUE_CPU_X32 OR TORQUE_CPU_X64)
-    torqueAddSourceDirectories("platformX86UNIX")
-	endif (TORQUE_CPU_X32 OR TORQUE_CPU_X64)
+  if(NOT APPLE)
+    if (TORQUE_CPU_X32 OR TORQUE_CPU_X64)
+      torqueAddSourceDirectories("platformX86UNIX")
+    endif (TORQUE_CPU_X32 OR TORQUE_CPU_X64)
+  endif(NOT APPLE)
 endif (UNIX)
 
 # Handle platformMac
@@ -308,8 +315,23 @@ endif (WIN32)
 
 # Prepare OSX Plist
 if (APPLE)
-	set(TORQUE_SOURCE_FILES ${TORQUE_SOURCE_FILES} ${TORQUE_PLATFORM_MAC_SOURCES} "${CMAKE_SOURCE_DIR}/Tools/CMake/torque.icns")
-	set_source_files_properties("${CMAKE_SOURCE_DIR}/Tools/CMake/torque.icns" PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
+  set(MACOSX_RESOURCES "${CMAKE_SOURCE_DIR}/Tools/CMake/torque.icns" 
+  "${TORQUE_APP_GAME_DIRECTORY}/data"
+  "${TORQUE_APP_GAME_DIRECTORY}/core"
+  "${TORQUE_APP_GAME_DIRECTORY}/tools"
+  "${TORQUE_APP_GAME_DIRECTORY}/main.${TORQUE_SCRIPT_EXTENSION}"
+  "${TORQUE_APP_GAME_DIRECTORY}/${TORQUE_APP_NAME}.torsion"
+  "${TORQUE_APP_GAME_DIRECTORY}/Template.torsion.exports")
+
+  if(TORQUE_TESTING)
+    set(MACOSX_RESOURCES ${MACOSX_RESOURCES} "${TORQUE_APP_GAME_DIRECTORY}/runTests.${TORQUE_SCRIPT_EXTENSION}")
+  endif()
+
+	set(TORQUE_SOURCE_FILES ${TORQUE_SOURCE_FILES} ${TORQUE_PLATFORM_MAC_SOURCES} ${MACOSX_RESOURCES})
+
+  source_group("Resources" FILES ${MACOSX_RESOURCES})
+
+	set_source_files_properties(${MACOSX_RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
 
 	set(EXECUTABLE_NAME "${TORQUE_APP_NAME}")
 	configure_file("${CMAKE_SOURCE_DIR}/Tools/CMake/Info.plist.in" "${TORQUE_APP_ROOT_DIRECTORY}/source/Info.plist" COPYONLY)
@@ -321,6 +343,10 @@ addDef(TORQUE_ENABLE_ASSERTS "Debug;RelWithDebInfo")
 addDef(TORQUE_DEBUG_GFX_MODE "RelWithDebInfo")
 addDef(TORQUE_OGGVORBIS)
 
+if (TORQUE_THEORA)
+   addDef(TORQUE_OGGTHEORA)
+endif(TORQUE_THEORA)
+
 if(NOT TORQUE_SDL)
    filterOut("platform/nativeDialogs/fileDialog.cpp" )
 endif()
@@ -351,10 +377,19 @@ endif (TORQUE_DYNAMIC_LIBRARY AND NOT TORQUE_TESTING)
 
 if (APPLE)
 	add_executable(${TORQUE_APP_NAME} MACOSX_BUNDLE ${TORQUE_SOURCE_FILES})
-	set_target_properties(${TORQUE_APP_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${TORQUE_APP_ROOT_DIRECTORY}/source/Info.plist")
+	set_target_properties(${TORQUE_APP_NAME} PROPERTIES 
+  BUNDLE true
+  MACOSX_BUNDLE_INFO_PLIST "${TORQUE_APP_ROOT_DIRECTORY}/source/Info.plist"
+  XCODE_ATTRIBUTE_INSTALL_PATH "/Applications"
+  XCODE_ATTRIBUTE_SKIP_INSTALL "No"
+  XCODE_ATTRIBUTE_LINKER_DISPLAYS_MANGLED_NAMES[variant=Debug] YES
+  XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH[variant=Debug] YES
+  XCODE_ATTRIBUTE_ENABLE_TESTABILITY[variant=Debug] YES
+  XCODE_ATTRIBUTE_SDL_FILE_DIR[variant=Debug] parent
+  XCODE_ATTRIBUTE_SDL_FILE_DIR[variant=RelWithDebInfo] parent
+  XCODE_ATTRIBUTE_SDL_FILE_DIR[variant=Release] resource
+  MACOSX_RPATH TRUE)
 
-	# Ensure the shared libraries are actually referenced at the correct path
-	set(CMAKE_XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../Frameworks")
 elseif (WIN32)
 	add_executable(${TORQUE_APP_NAME} WIN32 ${TORQUE_SOURCE_FILES})
 
@@ -401,8 +436,29 @@ if(MSVC)
     set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${TORQUE_APP_NAME})
 endif()
 
+set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+foreach (TORQUE_LIBRARY ${TORQUE_LINK_LIBRARIES})
+  set_target_properties(${TORQUE_LIBRARY} PROPERTIES
+  FOLDER "Libraries")
+  # remove warnings from 3rd parties.
+  target_compile_options(${TORQUE_LIBRARY} PRIVATE "-w")
+endforeach()
+
 target_compile_definitions(${TORQUE_APP_NAME} PUBLIC ${TORQUE_COMPILE_DEFINITIONS})
 target_link_libraries(${TORQUE_APP_NAME} ${TORQUE_LINK_LIBRARIES})
+
+if(APPLE)
+  target_link_libraries(${TORQUE_APP_NAME} ${TORQUE_LINK_FRAMEWORKS})
+endif(APPLE)
+
+if(WIN32)
+  target_link_libraries(${TORQUE_APP_NAME} ${TORQUE_LINK_WINDOWS})
+endif(WIN32)
+
+if(UNIX AND NOT APPLE)
+  target_link_libraries(${TORQUE_APP_NAME} ${TORQUE_LINK_LINUX})
+endif(UNIX AND NOT APPLE)
+
 target_link_options(${TORQUE_APP_NAME} PUBLIC ${TORQUE_LINK_OPTIONS})
 if (TORQUE_TARGET_PROPERTIES)
    set_target_properties(${TORQUE_APP_NAME} PROPERTIES ${TORQUE_TARGET_PROPERTIES})
@@ -425,7 +481,7 @@ append_defs()
 foreach (LIBRARY_BINARY ${TORQUE_ADDITIONAL_LIBRARY_BINARIES})
   if (APPLE)
     # For OSX, we want these binaries to be copied to the Frameworks directory
-    add_custom_command(TARGET ${TORQUE_APP_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${LIBRARY_BINARY} "${TORQUE_APP_GAME_DIRECTORY}/${TORQUE_APP_NAME}.app/Contents/Frameworks")
+    add_custom_command(TARGET ${TORQUE_APP_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${LIBRARY_BINARY} "${TORQUE_APP_GAME_DIRECTORY}/${TORQUE_APP_NAME}.app/Contents/Frameworks/$(CONFIGURATION)")
   else()
     # All other platforms expect the file next to the executable
     add_custom_command(TARGET ${TORQUE_APP_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${LIBRARY_BINARY} "${TORQUE_APP_GAME_DIRECTORY}")
@@ -442,11 +498,11 @@ if (UNIX)
 	  # For eg. OSX some links are not valid targets - for example frameworks provided by OS
 	  if (TARGET ${GAME_LINK_LIBRARY})
 		  get_target_property(LINK_LIBRARY_TYPE ${GAME_LINK_LIBRARY} TYPE)
-
 		  # Only pay attention to shared libraries and make them output to the app resources
 		  if ("${LINK_LIBRARY_TYPE}" STREQUAL "SHARED_LIBRARY")
         if (APPLE)
-          set_target_properties(${GAME_LINK_LIBRARY} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${TORQUE_APP_GAME_DIRECTORY}/${TORQUE_APP_NAME}.app/Contents/Frameworks")
+          set_target_properties(${GAME_LINK_LIBRARY} PROPERTIES 
+          XCODE_ATTRIBUTE_INSTALL_PATH "@rpath")
         else()
           set_target_properties(${GAME_LINK_LIBRARY} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${TORQUE_APP_GAME_DIRECTORY}")
         endif(APPLE)

+ 1 - 1
Engine/source/T3D/accumulationVolume.h

@@ -74,7 +74,7 @@ class AccumulationVolume : public ScenePolyhedralSpace
       // SimObject.
       DECLARE_CONOBJECT( AccumulationVolume );
       DECLARE_DESCRIPTION( "Allows objects in an area to have accumulation effect applied." );
-      DECLARE_CATEGORY( "3D Scene" );
+      DECLARE_CATEGORY("Volume");
 
       virtual bool onAdd();
       virtual void onRemove();

+ 1 - 0
Engine/source/T3D/aiPlayer.h

@@ -150,6 +150,7 @@ protected:
 
 public:
    DECLARE_CONOBJECT( AIPlayer );
+   DECLARE_CATEGORY("Actor \t AI");
 
    AIPlayer();
    ~AIPlayer();

+ 8 - 18
Engine/source/T3D/assets/ImageAsset.cpp

@@ -207,8 +207,7 @@ U32 ImageAsset::getAssetByFilename(StringTableEntry fileName, AssetPtr<ImageAsse
    {
       //acquire and bind the asset, and return it out
       imageAsset->setAssetId(query.mAssetList[0]);
-      (*imageAsset)->loadImage();
-      return (*imageAsset)->mLoadedState;
+      return (*imageAsset)->load();
    }
 }
 
@@ -240,23 +239,18 @@ U32 ImageAsset::getAssetById(StringTableEntry assetId, AssetPtr<ImageAsset>* ima
 
    if (imageAsset->notNull())
    {
-      (*imageAsset)->loadImage();
-      return (*imageAsset)->mLoadedState;
+      return (*imageAsset)->load();
    }
    else
    {
       if (imageAsset->isNull())
       {
-         (*imageAsset)->loadImage();
-         //Well that's bad, loading the fallback failed.
-         Con::warnf("ImageAsset::getAssetById - Finding of asset with id %s failed with no fallback asset", assetId);
          return AssetErrCode::Failed;
       }
 
-      //handle noshape not being loaded itself
+      //handle fallback not being loaded itself
       if ((*imageAsset)->mLoadedState == BadFileReference)
       {
-         (*imageAsset)->loadImage();
          Con::warnf("ImageAsset::getAssetById - Finding of asset with id %s failed, and fallback asset reported error of Bad File Reference.", assetId);
          return AssetErrCode::BadFileReference;
       }
@@ -275,25 +269,26 @@ void ImageAsset::copyTo(SimObject* object)
    Parent::copyTo(object);
 }
 
-void ImageAsset::loadImage()
+U32 ImageAsset::load()
 {
-   if (mLoadedState == AssetErrCode::Ok) return;
+   if (mLoadedState == AssetErrCode::Ok) return mLoadedState;
    if (mImagePath)
    {
       if (!Torque::FS::IsFile(mImagePath))
       {
          Con::errorf("ImageAsset::initializeAsset: Attempted to load file %s but it was not valid!", mImageFileName);
          mLoadedState = BadFileReference;
-         return;
+         return mLoadedState;
       }
 
       mLoadedState = Ok;
       mIsValidImage = true;
-      return;
+      return mLoadedState;
    }
    mLoadedState = BadFileReference;
 
    mIsValidImage = false;
+   return mLoadedState;
 }
 
 void ImageAsset::initializeAsset()
@@ -330,11 +325,6 @@ void ImageAsset::setImageFileName(const char* pScriptFile)
    refreshAsset();
 }
 
-const GBitmap& ImageAsset::getImage()
-{
-   return GBitmap(); //TODO fix this
-}
-
 GFXTexHandle ImageAsset::getTexture(GFXTextureProfile* requestedProfile)
 {
    if (mResourceMap.contains(requestedProfile))

+ 2 - 3
Engine/source/T3D/assets/ImageAsset.h

@@ -136,7 +136,6 @@ public:
 
    bool isValid() { return mIsValidImage; }
 
-   const GBitmap& getImage();
    GFXTexHandle getTexture(GFXTextureProfile* requestedProfile);
 
    StringTableEntry getImageInfo();
@@ -152,14 +151,14 @@ public:
    static U32 getAssetById(StringTableEntry assetId, AssetPtr<ImageAsset>* imageAsset);
    static U32 getAssetById(String assetId, AssetPtr<ImageAsset>* imageAsset) { return getAssetById(assetId.c_str(), imageAsset); };
 
+   U32 load();
+
 protected:
    virtual void            initializeAsset(void);
    virtual void            onAssetRefresh(void);
 
    static bool setImageFileName(void* obj, StringTableEntry index, StringTableEntry data) { static_cast<ImageAsset*>(obj)->setImageFileName(data); return false; }
    static StringTableEntry getImageFileName(void* obj, StringTableEntry data) { return static_cast<ImageAsset*>(obj)->getImageFileName(); }
-
-   void loadImage();
 };
 
 DefineConsoleType(TypeImageAssetPtr, ImageAsset)

+ 7 - 6
Engine/source/T3D/assets/MaterialAsset.cpp

@@ -206,7 +206,7 @@ void MaterialAsset::initializeAsset()
       }
    }
 
-   loadMaterial();
+   load();
 }
 
 void MaterialAsset::onAssetRefresh()
@@ -236,7 +236,7 @@ void MaterialAsset::onAssetRefresh()
       Con::setVariable("$Con::redefineBehavior", redefineBehaviorPrev.c_str());
    }
 
-   loadMaterial();
+   load();
 }
 
 void MaterialAsset::setScriptFile(const char* pScriptFile)
@@ -255,7 +255,7 @@ void MaterialAsset::setScriptFile(const char* pScriptFile)
 
 //------------------------------------------------------------------------------
 
-void MaterialAsset::loadMaterial()
+U32 MaterialAsset::load()
 {
    if (mMaterialDefinition)
    {
@@ -274,7 +274,7 @@ void MaterialAsset::loadMaterial()
                mLoadedState = Ok;
                mMaterialDefinition->setInternalName(getAssetId());
                mMaterialDefinition->reload();
-               return;
+               return mLoadedState;
             }
          }
       }
@@ -286,7 +286,7 @@ void MaterialAsset::loadMaterial()
       {
          Con::errorf("MaterialAsset: Unable to find the Material %s", mMatDefinitionName);
          mLoadedState = BadFileReference;
-         return;
+         return mLoadedState;
       }
 
       mMaterialDefinition = matDef;
@@ -294,10 +294,11 @@ void MaterialAsset::loadMaterial()
       mLoadedState = Ok;
       mMaterialDefinition->setInternalName(getAssetId());
       mMaterialDefinition->reload();
-      return;
+      return mLoadedState;
    }
 
    mLoadedState = Failed;
+   return mLoadedState;
 }
 
 //------------------------------------------------------------------------------

+ 1 - 1
Engine/source/T3D/assets/MaterialAsset.h

@@ -104,7 +104,7 @@ public:
    static void initPersistFields();
    virtual void copyTo(SimObject* object);
 
-   void loadMaterial();
+   U32 load();
 
    StringTableEntry getMaterialDefinitionName() { return mMatDefinitionName; }
    SimObjectPtr<Material> getMaterialDefinition() { return mMaterialDefinition; }

+ 8 - 8
Engine/source/T3D/assets/ShapeAsset.cpp

@@ -308,9 +308,9 @@ void ShapeAsset::_onResourceChanged(const Torque::Path &path)
    onAssetRefresh();
 }
 
-bool ShapeAsset::loadShape()
+U32 ShapeAsset::load()
 {
-   if (mLoadedState == AssetErrCode::Ok) return true;
+   if (mLoadedState == AssetErrCode::Ok) return mLoadedState;
 
    mMaterialAssets.clear();
    mMaterialAssetIds.clear();
@@ -357,7 +357,7 @@ bool ShapeAsset::loadShape()
    {
       Con::errorf("ShapeAsset::loadShape : failed to load shape file %s (%s)!", getAssetName(), mFilePath);
       mLoadedState = BadFileReference;
-      return false; //if it failed to load, bail out
+      return mLoadedState; //if it failed to load, bail out
    }
    // Construct billboards if not done already
    if (GFXDevice::devicePresent())
@@ -379,7 +379,7 @@ bool ShapeAsset::loadShape()
          mAnimationAssets[i]->getStartFrame(), mAnimationAssets[i]->getEndFrame(), mAnimationAssets[i]->getPadRotation(), mAnimationAssets[i]->getPadTransforms()))
       {
          mLoadedState = MissingAnimatons;
-         return false;
+         return mLoadedState;
       }
       if (mAnimationAssets[i]->isBlend())
          hasBlends = true;
@@ -402,7 +402,7 @@ bool ShapeAsset::loadShape()
                Con::errorf("ShapeAsset::initializeAsset - Unable to acquire reference animation asset %s for asset %s to blend!", mAnimationAssets[i]->getBlendAnimationName(), mAnimationAssets[i]->getAssetName());
                {
                   mLoadedState = MissingAnimatons;
-                  return false;
+                  return mLoadedState;
                }
             }
 
@@ -412,7 +412,7 @@ bool ShapeAsset::loadShape()
                Con::errorf("ShapeAnimationAsset::initializeAsset - Unable to set animation clip %s for asset %s to blend!", mAnimationAssets[i]->getAnimationName(), mAnimationAssets[i]->getAssetName());
                {
                   mLoadedState = MissingAnimatons;
-                  return false;
+                  return mLoadedState;
                }
             }
          }
@@ -422,7 +422,7 @@ bool ShapeAsset::loadShape()
    mChangeSignal.trigger();
 
    mLoadedState = Ok;
-   return true;
+   return mLoadedState;
 }
 
 //------------------------------------------------------------------------------
@@ -706,7 +706,7 @@ DefineEngineMethod(ShapeAsset, generateCachedPreviewImage, const char*, (S32 res
    "@param resolution Optional field for what resolution to bake the preview image at. Must be pow2\n"
    "@param overrideMaterialName Optional field for overriding the material used when rendering the shape for the bake.")
 {
-   object->loadShape();
+   object->load();
    return object->generateCachedPreviewImage(resolution, overrideMaterialName);
 }
 

+ 2 - 2
Engine/source/T3D/assets/ShapeAsset.h

@@ -132,11 +132,11 @@ public:
    /// Declare Console Object.
    DECLARE_CONOBJECT(ShapeAsset);
 
-   bool loadShape();
+   U32 load();
 
    TSShape* getShape() { return mShape; }
 
-   Resource<TSShape> getShapeResource() { loadShape(); return mShape; }
+   Resource<TSShape> getShapeResource() { load(); return mShape; }
 
    void SplitSequencePathAndName(String& srcPath, String& srcName);
    StringTableEntry getShapeFileName() { return mFileName; }

+ 248 - 55
Engine/source/T3D/assets/SoundAsset.cpp

@@ -44,6 +44,10 @@
 #include "sfx/sfxSource.h"
 #endif
 
+#ifndef _SFXPROFILE_H_
+#include "sfx/sfxProfile.h"
+#endif // !_SFXPROFILE_H_
+
 // Debug Profiling.
 #include "platform/profiler.h"
 #include "sfx/sfxTypes.h"
@@ -119,8 +123,28 @@ const String SoundAsset::mErrCodeStrings[] =
 SoundAsset::SoundAsset()
    : AssetBase()
 {
-   mSoundFile = StringTable->EmptyString();
-   mSoundPath = StringTable->EmptyString();
+   dMemset(mPlaylist.mSlots.mReplayMode, 0, sizeof(mPlaylist.mSlots.mReplayMode));
+   dMemset(mPlaylist.mSlots.mTransitionIn, 0, sizeof(mPlaylist.mSlots.mTransitionIn));
+   dMemset(mPlaylist.mSlots.mRepeatCount, 0, sizeof(mPlaylist.mSlots.mRepeatCount));
+   dMemset(mPlaylist.mSlots.mState, 0, sizeof(mPlaylist.mSlots.mState));
+   dMemset(mPlaylist.mSlots.mTrack, 0, sizeof(mPlaylist.mSlots.mTrack));
+   dMemset(mPlaylist.mSlots.mStateMode, 0, sizeof(mPlaylist.mSlots.mStateMode));
+
+   for (U32 i = 0; i < SFXPlayList::NUM_SLOTS; i++)
+   {
+      mSoundFile[i] = StringTable->EmptyString();
+      mSoundPath[i] = StringTable->EmptyString();
+
+      mPlaylist.mSlots.mTransitionOut[i] = SFXPlayList::TRANSITION_Wait;
+      mPlaylist.mSlots.mVolumeScale.mValue[i] = 1.f;
+      mPlaylist.mSlots.mPitchScale.mValue[i] = 1.f;
+      mPlaylist.mSlots.mFadeTimeIn.mValue[i] = -1.f;  // Don't touch by default.
+      mPlaylist.mSlots.mFadeTimeOut.mValue[i] = -1.f;  // Don't touch by default.
+      mPlaylist.mSlots.mMinDistance.mValue[i] = -1.f;  // Don't touch by default.
+      mPlaylist.mSlots.mMaxDistance.mValue[i] = -1.f;  // Don't touch by default.
+
+   }
+
    mSubtitleString = StringTable->EmptyString();
 
    mLoadedState = AssetErrCode::NotLoaded;
@@ -143,6 +167,14 @@ SoundAsset::SoundAsset()
    mProfileDesc.mPriority = 1.0f;
    mProfileDesc.mSourceGroup = NULL;
 
+   mIsPlaylist = false;
+
+   mPlaylist.mNumSlotsToPlay = SFXPlayList::SFXPlaylistSettings::NUM_SLOTS;
+   mPlaylist.mRandomMode = SFXPlayList::RANDOM_NotRandom;
+   mPlaylist.mTrace = false;
+   mPlaylist.mLoopMode = SFXPlayList::LOOP_All;
+   mPlaylist.mActiveSlots = 12;
+
 }
 
 //-----------------------------------------------------------------------------
@@ -158,9 +190,79 @@ void SoundAsset::initPersistFields()
    docsURL;
    // Call parent.
    Parent::initPersistFields();
-
-   addProtectedField("soundFile", TypeAssetLooseFilePath, Offset(mSoundFile, SoundAsset),
-      &setSoundFile, &getSoundFile, "Path to the sound file.");
+   addArray("slots", SFXPlayList::SFXPlaylistSettings::NUM_SLOTS);
+      addProtectedField("soundFile", TypeAssetLooseFilePath, Offset(mSoundFile, SoundAsset),
+         &_setSoundFile, &_getSoundFile, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, "Path to the sound file.");
+
+      addField("replay", TYPEID< SFXPlayList::EReplayMode >(), Offset(mPlaylist.mSlots.mReplayMode, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Behavior when an already playing sound is encountered on this slot from a previous cycle.\n"
+         "Each slot can have an arbitrary number of sounds playing on it from previous cycles.  This field determines "
+         "how SFXController will handle these sources.");
+      addField("transitionIn", TYPEID< SFXPlayList::ETransitionMode >(), Offset(mPlaylist.mSlots.mTransitionIn, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Behavior when moving into this slot.\n"
+         "After the delayIn time has expired (if any), this slot determines what the controller "
+         "will do before actually playing the slot.");
+      addField("transitionOut", TYPEID< SFXPlayList::ETransitionMode >(), Offset(mPlaylist.mSlots.mTransitionOut, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Behavior when moving out of this slot.\n"
+         "After the #detailTimeOut has expired (if any), this slot determines what the controller "
+         "will do before moving on to the next slot.");
+      addField("delayTimeIn", TypeF32, Offset(mPlaylist.mSlots.mDelayTimeIn.mValue, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Seconds to wait after moving into slot before #transitionIn.");
+      addField("delayTimeInVariance", TypePoint2F, Offset(mPlaylist.mSlots.mDelayTimeIn.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Bounds on randomization of #delayTimeIn.\n\n"
+         "@ref SFXPlayList_randomization\n");
+      addField("delayTimeOut", TypeF32, Offset(mPlaylist.mSlots.mDelayTimeOut.mValue, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Seconds to wait before moving out of slot after #transitionOut.");
+      addField("delayTimeOutVariance", TypePoint2F, Offset(mPlaylist.mSlots.mDelayTimeOut.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Bounds on randomization of #delayTimeOut.\n\n"
+         "@ref SFXPlayList_randomization\n");
+      addField("fadeTimeIn", TypeF32, Offset(mPlaylist.mSlots.mFadeTimeIn.mValue, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Seconds to fade sound in (-1 to use the track's own fadeInTime.)\n"
+         "@see SFXDescription::fadeTimeIn");
+      addField("fadeTimeInVariance", TypePoint2F, Offset(mPlaylist.mSlots.mFadeTimeIn.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Bounds on randomization of #fadeInTime.\n\n"
+         "@ref SFXPlayList_randomization\n");
+      addField("fadeTimeOut", TypeF32, Offset(mPlaylist.mSlots.mFadeTimeOut.mValue, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Seconds to fade sound out (-1 to use the track's own fadeOutTime.)\n"
+         "@see SFXDescription::fadeTimeOut");
+      addField("fadeTimeOutVariance", TypePoint2F, Offset(mPlaylist.mSlots.mFadeTimeOut.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Bounds on randomization of #fadeOutTime\n\n"
+         "@ref SFXPlayList_randomization\n");
+      addField("referenceDistance", TypeF32, Offset(mPlaylist.mSlots.mMinDistance.mValue, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "@c referenceDistance to set for 3D sounds in this slot (<1 to use @c referenceDistance of track's own description).\n"
+         "@see SFXDescription::referenceDistance");
+      addField("referenceDistanceVariance", TypePoint2F, Offset(mPlaylist.mSlots.mMinDistance.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Bounds on randomization of #referenceDistance.\n\n"
+         "@ref SFXPlayList_randomization\n");
+      addField("maxDistance", TypeF32, Offset(mPlaylist.mSlots.mMaxDistance.mValue, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "@c maxDistance to apply to 3D sounds in this slot (<1 to use @c maxDistance of track's own description).\n"
+         "@see SFXDescription::maxDistance");
+      addField("maxDistanceVariance", TypePoint2F, Offset(mPlaylist.mSlots.mMaxDistance.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Bounds on randomization of #maxDistance.\n\n"
+         "@ref SFXPlayList_randomization\n");
+      addField("volumeScale", TypeF32, Offset(mPlaylist.mSlots.mVolumeScale.mValue, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Scale factor to apply to volume of sounds played on this list slot.\n"
+         "This value will scale the actual volume level set on the track assigned to the slot, i.e. a value of 0.5 will "
+         "cause the track to play at half-volume.");
+      addField("volumeScaleVariance", TypePoint2F, Offset(mPlaylist.mSlots.mVolumeScale.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Bounds on randomization of #volumeScale.\n\n"
+         "@ref SFXPlayList_randomization\n");
+      addField("pitchScale", TypeF32, Offset(mPlaylist.mSlots.mPitchScale.mValue, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Scale factor to apply to pitch of sounds played on this list slot.\n"
+         "This value will scale the actual pitch set on the track assigned to the slot, i.e. a value of 0.5 will "
+         "cause the track to play at half its assigned speed.");
+      addField("pitchScaleVariance", TypePoint2F, Offset(mPlaylist.mSlots.mPitchScale.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Bounds on randomization of #pitchScale.\n\n"
+         "@ref SFXPlayList_randomization\n");
+      addField("repeatCount", TypeS32, Offset(mPlaylist.mSlots.mRepeatCount, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Number of times to loop this slot.");
+      addField("state", TypeSFXStateName, Offset(mPlaylist.mSlots.mState, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "State that must be active for this slot to play.\n\n"
+         "@ref SFXPlayList_states");
+      addField("stateMode", TYPEID< SFXPlayList::EStateMode >(), Offset(mPlaylist.mSlots.mStateMode, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+         "Behavior when assigned state is deactivated while slot is playing.\n\n"
+         "@ref SFXPlayList_states");
+   endArray("slots");
 
    addField("pitchAdjust", TypeF32, Offset(mProfileDesc.mPitch, SoundAsset), "Adjustment of the pitch value 1 is default.");
    addField("volumeAdjust", TypeF32, Offset(mProfileDesc.mVolume, SoundAsset), "Adjustment to the volume.");
@@ -170,16 +272,33 @@ void SoundAsset::initPersistFields()
    addField("isStreaming", TypeBool, Offset(mProfileDesc.mIsStreaming, SoundAsset), "Use streaming.");
    //....why?
    addField("useHardware", TypeBool, Offset(mProfileDesc.mUseHardware, SoundAsset), "Use hardware mixing for this sound.");
-   addField("minDistance", TypeF32, Offset(mProfileDesc.mMinDistance, SoundAsset), "Minimum distance for sound.");
-   // more like it.
-   addField("maxDistance", TypeF32, Offset(mProfileDesc.mMaxDistance, SoundAsset), "Max distance for sound.");
-   addField("coneInsideAngle", TypeS32, Offset(mProfileDesc.mConeInsideAngle, SoundAsset), "Cone inside angle.");
-   addField("coneOutsideAngle", TypeS32, Offset(mProfileDesc.mConeOutsideAngle, SoundAsset), "Cone outside angle.");
-   addField("coneOutsideVolume", TypeF32, Offset(mProfileDesc.mConeOutsideVolume, SoundAsset), "Cone outside volume.");
-   addField("rolloffFactor", TypeF32, Offset(mProfileDesc.mRolloffFactor, SoundAsset), "Rolloff factor.");
-   addField("scatterDistance", TypePoint3F, Offset(mProfileDesc.mScatterDistance, SoundAsset), "Randomization to the spacial position of the sound.");
    addField("sourceGroup", TypeSFXSourceName, Offset(mProfileDesc.mSourceGroup, SoundAsset), "Group that sources playing with this description should be put into.");
-
+   addField("preload", TypeBool, Offset(mPreload, SoundAsset), "Whether to preload sound data when the profile is added to system.");
+
+   addGroup("Fading");
+      addField("fadeInTime", TypeF32, Offset(mProfileDesc.mFadeInTime, SoundAsset), "Number of seconds to gradually fade in volume from zero when playback starts.");
+      addField("fadeOutTime", TypeF32, Offset(mProfileDesc.mFadeOutTime, SoundAsset), "Number of seconds to gradually fade out volume down to zero when playback is stopped or paused.");
+      addField("fadeInEase", TypeEaseF, Offset(mProfileDesc.mFadeInEase, SoundAsset), "Easing curve for fade-in transition.");
+      addField("fadeOutEase", TypeEaseF, Offset(mProfileDesc.mFadeOutEase, SoundAsset), "Easing curve for fade-out transition.");
+      addField("fadeLoops", TypeBool, Offset(mProfileDesc.mFadeLoops, SoundAsset), "Fade each cycle of a loop in and/or out; otherwise only fade-in first cycle.");
+   endGroup("Fading");
+
+   addGroup("3D");
+      addField("minDistance", TypeF32, Offset(mProfileDesc.mMinDistance, SoundAsset), "Minimum distance for sound.");
+      addField("maxDistance", TypeF32, Offset(mProfileDesc.mMaxDistance, SoundAsset), "Max distance for sound.");
+      addField("coneInsideAngle", TypeS32, Offset(mProfileDesc.mConeInsideAngle, SoundAsset), "Cone inside angle.");
+      addField("coneOutsideAngle", TypeS32, Offset(mProfileDesc.mConeOutsideAngle, SoundAsset), "Cone outside angle.");
+      addField("coneOutsideVolume", TypeF32, Offset(mProfileDesc.mConeOutsideVolume, SoundAsset), "Cone outside volume.");
+      addField("rolloffFactor", TypeF32, Offset(mProfileDesc.mRolloffFactor, SoundAsset), "Rolloff factor.");
+      addField("scatterDistance", TypePoint3F, Offset(mProfileDesc.mScatterDistance, SoundAsset), "Randomization to the spacial position of the sound.");
+   endGroup("3D");
+
+   addGroup("Playlist settings");
+      addField("random", TYPEID< SFXPlayList::ERandomMode >(), Offset(mPlaylist.mRandomMode, SoundAsset), "Slot playback order randomization pattern.");
+      addField("loopMode", TYPEID< SFXPlayList::ELoopMode >(), Offset(mPlaylist.mLoopMode, SoundAsset), "Behavior when description has looping enabled.");
+      addField("numSlotsToPlay", TypeS32, Offset(mPlaylist.mNumSlotsToPlay, SoundAsset), "Number of slots to play.");
+      addField("trace", TypeBool, Offset(mPlaylist.mTrace, SoundAsset), "Enable/disable execution tracing for this playlist (local only).");
+   endGroup("Playlist settings");
 }
 
 //------------------------------------------------------------------------------
@@ -193,67 +312,141 @@ void SoundAsset::copyTo(SimObject* object)
 void SoundAsset::initializeAsset(void)
 {
    Parent::initializeAsset();
+   for (U32 i = 0; i < SFXPlayList::SFXPlaylistSettings::NUM_SLOTS; i++)
+   {
+      if (i == 0 && mSoundFile[i] == StringTable->EmptyString())
+         return;
 
-   if (mSoundFile == StringTable->EmptyString())
-      return;
+      if (mSoundFile[i] == StringTable->EmptyString())
+         break;
 
-   mSoundPath = getOwned() ? expandAssetFilePath(mSoundFile) : mSoundPath;
-   //loadSound();
+      mSoundPath[i] = getOwned() ? expandAssetFilePath(mSoundFile[i]) : mSoundPath[i];
+   }
 }
 
 void SoundAsset::_onResourceChanged(const Torque::Path &path)
 {
-   if (path != Torque::Path(mSoundPath))
-      return;
+   for (U32 i = 0; i < SFXPlayList::NUM_SLOTS; i++)
+   {
 
+      if (path != Torque::Path(mSoundPath[i]))
+         return;
+   }
    refreshAsset();
-
-   //loadSound();
 }
 
 void SoundAsset::onAssetRefresh(void)
 {
-   if (mSoundFile == StringTable->EmptyString())
-      return;
+   for (U32 i = 0; i < SFXPlayList::SFXPlaylistSettings::NUM_SLOTS; i++)
+   {
+      if (i == 0 && mSoundFile[i] == StringTable->EmptyString())
+         return;
 
-   //Update
-   mSoundPath = getOwned() ? expandAssetFilePath(mSoundFile) : mSoundPath;
-   //loadSound();
+      if (mSoundFile[i] == StringTable->EmptyString())
+         break;
+
+      mSoundPath[i] = getOwned() ? expandAssetFilePath(mSoundFile[i]) : mSoundPath[i];
+   }
 }
 
-bool SoundAsset::loadSound()
+U32 SoundAsset::load()
 {
-   if (mLoadedState == AssetErrCode::Ok) return true;
-   if (mSoundPath)
+   if (mLoadedState == AssetErrCode::Ok) return mLoadedState;
+
+   // find out how many active slots we have.
+   U32 numSlots = 0;
+   for (U32 i = 0; i < SFXPlayList::SFXPlaylistSettings::NUM_SLOTS; i++)
    {
-      if (!Torque::FS::IsFile(mSoundPath))
-      {
-         Con::errorf("SoundAsset::initializeAsset: Attempted to load file %s but it was not valid!", mSoundFile);
-         mLoadedState = BadFileReference;
-         mSFXProfile.setDescription(NULL);
-         mSFXProfile.setSoundFileName(StringTable->insert(StringTable->EmptyString()));
-         mSFXProfile.setPreload(false);
+      if (i == 0 && mSoundPath[i] == StringTable->EmptyString())
          return false;
-      }
-      else
-      {// = new SFXProfile(mProfileDesc, mSoundFile, mPreload);
-         if (mProfileDesc.mSourceGroup == NULL)
-            mProfileDesc.mSourceGroup = dynamic_cast<SFXSource*>(Sim::findObject("AudioChannelMaster"));
-         mSFXProfile.setDescription(&mProfileDesc);
-         mSFXProfile.setSoundFileName(mSoundPath);
-         mSFXProfile.setPreload(mPreload);
-
-         //give it a nudge to preload if required
-         mSFXProfile.getBuffer();
+
+      if (mSoundPath[i] == StringTable->EmptyString())
+         break;
+
+      numSlots++;
+   }
+
+
+   if (numSlots > 1)
+   {
+      mIsPlaylist = true;
+
+      for (U32 i = 0; i < numSlots; i++)
+      {
+         if (mSoundPath[i])
+         {
+            if (!Torque::FS::IsFile(mSoundPath[i]))
+            {
+               Con::errorf("SoundAsset::initializeAsset: Attempted to load file %s but it was not valid!", mSoundFile[i]);
+               mLoadedState = BadFileReference;
+               mSFXProfile[i].setDescription(NULL);
+               mSFXProfile[i].setSoundFileName(StringTable->insert(StringTable->EmptyString()));
+               mSFXProfile[i].setPreload(false);
+               return mLoadedState;
+            }
+            else
+            {// = new SFXProfile(mProfileDesc, mSoundFile, mPreload);
+               if (mProfileDesc.mSourceGroup == NULL)
+                  mProfileDesc.mSourceGroup = dynamic_cast<SFXSource*>(Sim::findObject("AudioChannelMaster"));
+               SFXProfile* trackProfile = new SFXProfile();
+               trackProfile->setDescription(&mProfileDesc);
+               trackProfile->setSoundFileName(mSoundPath[i]);
+               trackProfile->setPreload(mPreload);
+               trackProfile->getBuffer();
+
+               mSFXProfile[i] = *trackProfile;
+
+               mPlaylist.mSlots.mTrack[i] = trackProfile;
+               
+            }
+         }
       }
 
+      mPlaylist.setDescription(&mProfileDesc);
    }
+   else
+   {
+      if (mSoundPath[0])
+      {
+         if (!Torque::FS::IsFile(mSoundPath[0]))
+         {
+            Con::errorf("SoundAsset::initializeAsset: Attempted to load file %s but it was not valid!", mSoundFile[0]);
+            mLoadedState = BadFileReference;
+            mSFXProfile[0].setDescription(NULL);
+            mSFXProfile[0].setSoundFileName(StringTable->insert(StringTable->EmptyString()));
+            mSFXProfile[0].setPreload(false);
+            return mLoadedState;
+         }
+         else
+         {// = new SFXProfile(mProfileDesc, mSoundFile, mPreload);
+            if (mProfileDesc.mSourceGroup == NULL)
+               mProfileDesc.mSourceGroup = dynamic_cast<SFXSource*>(Sim::findObject("AudioChannelMaster"));
+            mSFXProfile[0].setDescription(&mProfileDesc);
+            mSFXProfile[0].setSoundFileName(mSoundPath[0]);
+            mSFXProfile[0].setPreload(mPreload);
+
+            //give it a nudge to preload if required
+            mSFXProfile[0].getBuffer();
+         }
+
+      }
+   }
+
    mChangeSignal.trigger();
    mLoadedState = Ok;
-   return true;
+   return mLoadedState;
+}
+
+StringTableEntry SoundAsset::getSoundFile(const char* pSoundFile, const U32 slotId)
+{
+   for (U32 i = 0; i < 12; i++)
+   {
+      if(mSoundFile[i] == pSoundFile)
+         return mSoundFile[i];
+   }
 }
 
-void SoundAsset::setSoundFile(const char* pSoundFile)
+void SoundAsset::setSoundFile(const char* pSoundFile, const U32 slotId)
 {
    // Sanity!
    AssertFatal(pSoundFile != NULL, "Cannot use a NULL sound file.");
@@ -261,12 +454,12 @@ void SoundAsset::setSoundFile(const char* pSoundFile)
    // Fetch sound file.
    pSoundFile = StringTable->insert(pSoundFile, true);
 
-   // Ignore no change,
-   if (pSoundFile == mSoundFile)
+   //Ignore no change,
+   if (pSoundFile == mSoundFile[slotId])
       return;
 
    // Update.
-   mSoundFile = getOwned() ? expandAssetFilePath(pSoundFile) : pSoundFile;
+   mSoundFile[slotId] = getOwned() ? expandAssetFilePath(pSoundFile) : pSoundFile;
 
    // Refresh the asset.
    refreshAsset();
@@ -353,11 +546,11 @@ DefineEngineMethod(SoundAsset, playSound, S32, (Point3F position), (Point3F::Zer
    "Plays the sound for this asset.\n"
    "@return (sound plays).\n")
 {
-   if (object->getSfxProfile())
+   if (object->getSFXTrack())
    {
       MatrixF transform;
       transform.setPosition(position);
-      SFXSource* source = SFX->playOnce(object->getSfxProfile(), &transform, NULL, -1);
+      SFXSource* source = SFX->playOnce(object->getSFXTrack(), &transform, NULL, -1);
       if(source)
          return source->getId();
       else

+ 58 - 25
Engine/source/T3D/assets/SoundAsset.h

@@ -55,6 +55,11 @@
 #include "sfx/sfxDescription.h"
 #endif // !_SFXDESCRIPTION_H_
 
+
+#ifndef _SFXTRACK_H_
+#include "sfx/sfxTrack.h"
+#endif
+
 #ifndef _SFXPROFILE_H_
 #include "sfx/sfxProfile.h"
 #endif // !_SFXPROFILE_H_
@@ -63,8 +68,17 @@
 #include "core/resourceManager.h"
 #endif
 
+#ifndef _SFXPLAYLIST_H_
+#include "sfx/sfxPlayList.h"
+#endif
+
+#ifndef _SFXTYPES_H_
+#include "sfx/sfxTypes.h"
+#endif
+
 #include "assetMacroHelpers.h"
 class SFXResource;
+class SFXPlayList;
 
 //-----------------------------------------------------------------------------
 class SoundAsset : public AssetBase
@@ -73,13 +87,17 @@ class SoundAsset : public AssetBase
    typedef AssetPtr<SoundAsset> ConcreteAssetPtr;
 
 protected:
-   StringTableEntry        mSoundFile;
-   StringTableEntry        mSoundPath;
-   SFXProfile              mSFXProfile;
+   StringTableEntry        mSoundFile[12];
+   StringTableEntry        mSoundPath[12];
+   SFXProfile              mSFXProfile[12];
+
    SFXDescription          mProfileDesc;
+   SFXPlayList             mPlaylist;
    // subtitles
    StringTableEntry        mSubtitleString;
    bool                    mPreload;
+   bool                    mIsPlaylist;
+   //SFXPlayList::SlotData   mSlots;
 
    /*These will be needed in the refactor!
    Resource<SFXResource>   mSoundResource;
@@ -132,17 +150,20 @@ public:
    virtual void copyTo(SimObject* object);
 
    //SFXResource* getSound() { return mSoundResource; }
-   Resource<SFXResource> getSoundResource() { loadSound(); return mSFXProfile.getResource(); }
+   Resource<SFXResource> getSoundResource(const U32 slotId = 0) { load(); return mSFXProfile[slotId].getResource(); }
 
    /// Declare Console Object.
    DECLARE_CONOBJECT(SoundAsset);
 
-   void                    setSoundFile(const char* pSoundFile);
-   bool loadSound();
-   inline StringTableEntry getSoundFile(void) const { return mSoundFile; };
-   inline StringTableEntry getSoundPath(void) const { return mSoundPath; };
-   SFXProfile* getSfxProfile() { return &mSFXProfile; }
+   void setSoundFile(const char* pSoundFile, const U32 slotId = 0);
+   U32 load();
+   StringTableEntry getSoundFile(const char* pSoundFile, const U32 slotId = 0);
+   inline StringTableEntry getSoundPath(const U32 slotId = 0) const { return mSoundPath[slotId]; };
+   SFXProfile* getSfxProfile(const U32 slotId = 0) { return &mSFXProfile[slotId]; }
+   SFXPlayList* getSfxPlaylist() { return &mPlaylist; }
+   SFXTrack* getSFXTrack() { return mIsPlaylist ? dynamic_cast<SFXTrack*>(&mPlaylist) : dynamic_cast<SFXTrack*>(&mSFXProfile[0]); }
    SFXDescription* getSfxDescription() { return &mProfileDesc; }
+   bool isPlaylist(){ return mIsPlaylist; }
 
    bool isLoop() { return mProfileDesc.mIsLooping; }
    bool is3D() { return mProfileDesc.mIs3D; }
@@ -156,8 +177,8 @@ protected:
    void _onResourceChanged(const Torque::Path & path);
    virtual void            onAssetRefresh(void);
 
-   static bool setSoundFile(void *obj, const char *index, const char *data) { static_cast<SoundAsset*>(obj)->setSoundFile(data); return false; }
-   static const char* getSoundFile(void* obj, const char* data) { return static_cast<SoundAsset*>(obj)->getSoundFile(); }
+  static bool _setSoundFile(void *obj, const char *index, const char *data) { static_cast<SoundAsset*>(obj)->setSoundFile(data, index ? dAtoi(index) : 0); return false; }
+  static const char* _getSoundFile(void* obj, const char* data) { return static_cast<SoundAsset*>(obj)->getSoundFile(data); }
 };
 
 DefineConsoleType(TypeSoundAssetPtr, SoundAsset)
@@ -175,7 +196,7 @@ DefineConsoleType(TypeSoundAssetId, String)
    StringTableEntry m##name##Name; \
    StringTableEntry m##name##AssetId;\
    AssetPtr<SoundAsset> m##name##Asset = NULL;\
-   SFXProfile* m##name##Profile = NULL;\
+   SFXTrack* m##name##Profile = NULL;\
    SFXDescription* m##name##Desc = NULL;\
    SimObjectId m##name##SFXId = 0;\
 public: \
@@ -268,11 +289,12 @@ public: \
    {\
       return m##name;\
    }\
-   SFXProfile* get##name##Profile()\
+   SFXTrack* get##name##Profile()\
    {\
       if (get##name() != StringTable->EmptyString() && m##name##Asset.notNull()){\
-         m##name##Profile = m##name##Asset->getSfxProfile();\
-         return m##name##Profile;}\
+            m##name##Profile = m##name##Asset->getSFXTrack(); \
+            return m##name##Profile;\
+      }\
       return NULL;\
    }\
    SFXDescription* get##name##Description()\
@@ -308,9 +330,9 @@ public: \
    {\
       if(stream->writeFlag(Sim::findObject(m##name##Name)))\
       {\
-         SFXTrack* sndTrack;\
-         Sim::findObject(m##name##Name, sndTrack);\
+         SFXTrack* sndTrack = get##name##Profile();\
          stream->writeRangedU32(SimObjectId(sndTrack->getId()), DataBlockObjectIdFirst, DataBlockObjectIdLast);\
+         sfxWrite(stream, sndTrack);\
       }\
       else\
       {\
@@ -330,7 +352,10 @@ public: \
    {\
       if(stream->readFlag())\
       {\
+         String errorStr;\
          m##name##SFXId = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );\
+         sfxReadAndResolve(stream, &m##name##Profile, errorStr);\
+         Con::errorf("%s", errorStr.c_str());\
       }\
       else\
       {\
@@ -359,7 +384,7 @@ public: \
    StringTableEntry m##name##Name[max]; \
    StringTableEntry m##name##AssetId[max];\
    AssetPtr<SoundAsset> m##name##Asset[max];\
-   SFXProfile* m##name##Profile[max];\
+   SFXTrack* m##name##Profile[max];\
    SimObjectId m##name##SFXId[max];\
 public: \
    const StringTableEntry get##name##File(const U32& index) const { return m##name##Name[index]; }\
@@ -461,10 +486,10 @@ public: \
          return ResourceManager::get().load( "" );\
       return m##name[id];\
    }\
-   SFXProfile* get##name##Profile(const U32& id)\
+   SFXTrack* get##name##Profile(const U32& id)\
    {\
-      if (get##name(id) != StringTable->EmptyString() && m##name##Asset[id].notNull())\
-         return m##name##Asset[id]->getSfxProfile();\
+         if (m##name##Asset[id].notNull())\
+            return  m##name##Asset[id]->getSFXTrack(); \
       return NULL;\
    }\
    bool is##name##Valid(const U32& id) {return (get##name(id) != StringTable->EmptyString() && m##name##Asset[id] && m##name##Asset[id]->getStatus() == AssetBase::Ok); }
@@ -518,9 +543,12 @@ if (m##name##AssetId[index] != StringTable->EmptyString())\
    {\
       if(stream->writeFlag(Sim::findObject(m##name##Name[index])))\
       {\
-         SFXTrack* sndTrack;\
-         Sim::findObject(m##name##Name[index], sndTrack);\
-         stream->writeRangedU32(SimObjectId(sndTrack->getId()), DataBlockObjectIdFirst, DataBlockObjectIdLast);\
+         SFXTrack* sndTrack = get##name##Profile(index);\
+         if(stream->writeFlag(sndTrack != nullptr))\
+         {\
+            stream->writeRangedU32(SimObjectId(sndTrack->getId()), DataBlockObjectIdFirst, DataBlockObjectIdLast);\
+            sfxWrite(stream, sndTrack);\
+         }\
       }\
       else\
       {\
@@ -540,7 +568,12 @@ if (m##name##AssetId[index] != StringTable->EmptyString())\
    {\
       if(stream->readFlag())\
       {\
-         m##name##SFXId[index] = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );\
+         String errorStr;\
+         if(stream->readFlag())\
+         {\
+            m##name##SFXId[index] = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );\
+            sfxReadAndResolve(stream, &m##name##Profile[index], errorStr);\
+         }\
       }\
       else\
       {\

+ 6 - 6
Engine/source/T3D/assets/TerrainAsset.cpp

@@ -161,14 +161,14 @@ void TerrainAsset::initializeAsset()
 
    mTerrainFilePath = getOwned() ? expandAssetFilePath(mTerrainFileName) : mTerrainFilePath;
 
-   loadTerrain();
+   load();
 }
 
 void TerrainAsset::onAssetRefresh()
 {
    mTerrainFilePath = getOwned() ? expandAssetFilePath(mTerrainFileName) : mTerrainFilePath;
 
-   loadTerrain();
+   load();
 }
 
 void TerrainAsset::setTerrainFileName(const char* pScriptFile)
@@ -189,10 +189,10 @@ void TerrainAsset::setTerrainFileName(const char* pScriptFile)
    refreshAsset();
 }
 
-bool TerrainAsset::loadTerrain()
+U32 TerrainAsset::load()
 {
    if (!Torque::FS::IsFile(mTerrainFilePath))
-      return false;
+      return BadFileReference;
 
    mTerrMaterialAssets.clear();
    mTerrMaterialAssetIds.clear();
@@ -229,9 +229,9 @@ bool TerrainAsset::loadTerrain()
    mTerrainFile = ResourceManager::get().load(mTerrainFilePath);
 
    if (mTerrainFile)
-      return true;
+      return Ok;
 
-   return false;
+   return BadFileReference;
 }
 
 //------------------------------------------------------------------------------

+ 1 - 1
Engine/source/T3D/assets/TerrainAsset.h

@@ -82,7 +82,7 @@ public:
 
    inline Resource<TerrainFile> getTerrainResource(void) const { return mTerrainFile; };
 
-   bool loadTerrain();
+   U32 load();
 
    static bool getAssetByFilename(StringTableEntry fileName, AssetPtr<TerrainAsset>* shapeAsset);
    static StringTableEntry getAssetIdByFilename(StringTableEntry fileName);

+ 7 - 6
Engine/source/T3D/assets/TerrainMaterialAsset.cpp

@@ -202,7 +202,7 @@ void TerrainMaterialAsset::initializeAsset()
       }
    }
 
-   loadMaterial();
+   load();
 }
 
 void TerrainMaterialAsset::onAssetRefresh()
@@ -232,7 +232,7 @@ void TerrainMaterialAsset::onAssetRefresh()
       Con::setVariable("$Con::redefineBehavior", redefineBehaviorPrev.c_str());
    }
 
-   loadMaterial();
+   load();
 }
 
 void TerrainMaterialAsset::setScriptFile(const char* pScriptFile)
@@ -251,7 +251,7 @@ void TerrainMaterialAsset::setScriptFile(const char* pScriptFile)
 
 //------------------------------------------------------------------------------
 
-void TerrainMaterialAsset::loadMaterial()
+U32 TerrainMaterialAsset::load()
 {
    if (mMaterialDefinition)
       mMaterialDefinition->safeDeleteObject();
@@ -287,7 +287,7 @@ void TerrainMaterialAsset::loadMaterial()
       }
 
       if(mLoadedState == Ok)
-         return;
+         return mLoadedState;
    }
    else if ((mLoadedState == ScriptLoaded || mLoadedState == DefinitionAlreadyExists) && mMatDefinitionName != StringTable->EmptyString())
    {
@@ -296,17 +296,18 @@ void TerrainMaterialAsset::loadMaterial()
       {
          Con::errorf("TerrainMaterialAsset: Unable to find the Material %s", mMatDefinitionName);
          mLoadedState = BadFileReference;
-         return;
+         return mLoadedState;
       }
 
       mMaterialDefinition = matDef;
 
       mLoadedState = Ok;
       mMaterialDefinition->setInternalName(getAssetId());
-      return;
+      return mLoadedState;
    }
 
    mLoadedState = Failed;
+   return mLoadedState;
 }
 
 //------------------------------------------------------------------------------

+ 1 - 1
Engine/source/T3D/assets/TerrainMaterialAsset.h

@@ -89,7 +89,7 @@ public:
    static void initPersistFields();
    virtual void copyTo(SimObject* object);
 
-   void loadMaterial();
+   U32 load();
 
    StringTableEntry getMaterialDefinitionName() { return mMatDefinitionName; }
    SimObjectPtr<TerrainMaterial> getMaterialDefinition() { return mMaterialDefinition; }

+ 1 - 1
Engine/source/T3D/camera.h

@@ -249,7 +249,7 @@ class Camera: public ShapeBase
       virtual void unpackUpdate( NetConnection* conn, BitStream* stream );
 
       DECLARE_CONOBJECT( Camera );
-      DECLARE_CATEGORY( "Game" );
+      DECLARE_CATEGORY("Actor \t Controllable");
       DECLARE_DESCRIPTION( "Represents a position, direction and field of view to render a scene from." );
       static F32 getMovementSpeed() { return smMovementSpeed; }
       bool isCamera() const { return true; }

+ 2 - 4
Engine/source/T3D/convexShape.cpp

@@ -221,10 +221,8 @@ bool ConvexShape::protectedSetSurface( void *object, const char *index, const ch
       &mat[12], &mat[13], &mat[14], &mat[15] );
 	*/
 
-   String t = data;
-
-	dSscanf( data, "%g %g %g %g %g %g %g %i %g %g %g %g %f", &quat.x, &quat.y, &quat.z, &quat.w, &pos.x, &pos.y, &pos.z,
-      &matID, &offset.x, &offset.y, &scale.x, &scale.y, &rot);
+	dSscanf( data, "%g %g %g %g %g %g %g %i %g %g %g %g %g %i %i", &quat.x, &quat.y, &quat.z, &quat.w, &pos.x, &pos.y, &pos.z,
+      &matID, &offset.x, &offset.y, &scale.x, &scale.y, &rot, &horz, &vert);
 
 	MatrixF surface;
 	quat.setMatrix( &surface );

+ 1 - 0
Engine/source/T3D/convexShape.h

@@ -194,6 +194,7 @@ public:
    virtual ~ConvexShape();
 
    DECLARE_CONOBJECT( ConvexShape );
+   DECLARE_CATEGORY("Object \t Simple");
 
    // ConsoleObject
    static void initPersistFields();

+ 1 - 0
Engine/source/T3D/debris.h

@@ -179,6 +179,7 @@ public:
    void  setRotAngles( const Point3F &angles ){ mRotAngles = angles; }
 
    DECLARE_CONOBJECT(Debris);
+   DECLARE_CATEGORY("UNLISTED");
 
 private:
    SimObject*   ss_object;

+ 1 - 0
Engine/source/T3D/decal/decalManager.cpp

@@ -87,6 +87,7 @@ const U32 DecalManager::smMaxIndices = 10000;
 DecalManager *gDecalManager = NULL;
 
 IMPLEMENT_CONOBJECT(DecalManager);
+DECLARE_CATEGORY("UNLISTED");
 
 ConsoleDoc(
    "@defgroup Decals\n"

+ 1 - 0
Engine/source/T3D/decal/decalManager.h

@@ -270,6 +270,7 @@ class DecalManager : public SceneObject
 
       // SimObject.
       DECLARE_CONOBJECT( DecalManager );
+      DECLARE_CATEGORY("UNLISTED");
       static void consoleInit();
 };
 

+ 1 - 1
Engine/source/T3D/fps/guiHealthBarHud.cpp

@@ -147,7 +147,7 @@ void GuiHealthBarHud::onRender(Point2I offset, const RectI &updateRect)
    if (!conn)
       return;
    ShapeBase* control = dynamic_cast<ShapeBase*>(conn->getControlObject());
-   if (!control || !(control->getTypeMask() & PlayerObjectType))
+   if (!control || !(control->getTypeMask() & (PlayerObjectType | VehicleObjectType)))
       return;
 
    if(mDisplayEnergy)

+ 1 - 1
Engine/source/T3D/fps/guiHealthTextHud.cpp

@@ -149,7 +149,7 @@ void GuiHealthTextHud::onRender(Point2I offset, const RectI &updateRect)
    if (!conn)  
       return;  
    ShapeBase* control = dynamic_cast<ShapeBase*>(conn->getControlObject());  
-   if (!control || !(control->getTypeMask() & PlayerObjectType))  
+   if (!control || !(control->getTypeMask() & (PlayerObjectType | VehicleObjectType)))
       return;  
   
    // Just grab the damage/energy right off the control object.    

+ 1 - 1
Engine/source/T3D/fps/guiShapeNameHud.cpp

@@ -209,7 +209,7 @@ void GuiShapeNameHud::onRender( Point2I, const RectI &updateRect)
             // Target pos to test, if it's a player run the LOS to his eye
             // point, otherwise we'll grab the generic box center.
             Point3F shapePos;
-            if (shape->getTypeMask() & PlayerObjectType) 
+            if (shape->getTypeMask() & (PlayerObjectType | VehicleObjectType))
             {
                MatrixF eye;
 

+ 1 - 1
Engine/source/T3D/fx/explosion.cpp

@@ -1403,7 +1403,7 @@ bool Explosion::explode()
       resetWorldBox();
    }
 
-   SFXProfile* sound_prof = mDataBlock->getSoundProfile();
+   SFXProfile* sound_prof = static_cast<SFXProfile*>(mDataBlock->getSoundProfile());
    if (sound_prof)
    {
       soundProfile_clone = sound_prof->cloneAndPerformSubstitutions(ss_object, ss_index);

+ 1 - 0
Engine/source/T3D/fx/explosion.h

@@ -205,6 +205,7 @@ class Explosion : public GameBase, public ISceneLight
    void setCollideType( U32 cType ){ mCollideType = cType; }
 
    DECLARE_CONOBJECT(Explosion);
+   DECLARE_CATEGORY("UNLISTED");
    static void initPersistFields();
 private:
    SimObject*     ss_object;

+ 1 - 0
Engine/source/T3D/fx/fxFoliageReplicator.h

@@ -390,6 +390,7 @@ public:
 
    // Declare Console Object.
    DECLARE_CONOBJECT(fxFoliageReplicator);
+   DECLARE_CATEGORY("UNLISTED");
 };
 #pragma warning( pop ) 
 #endif // _FOLIAGEREPLICATOR_H_

+ 2 - 0
Engine/source/T3D/fx/fxShapeReplicator.h

@@ -59,6 +59,7 @@ public:
    void setTransform(const MatrixF & mat) { Parent::setTransform(mat); setRenderTransform(mat); };
 
    DECLARE_CONOBJECT(fxShapeReplicatedStatic);
+   DECLARE_CATEGORY("UNLISTED");
 };
 
 
@@ -187,6 +188,7 @@ public:
 
    // Declare Console Object.
    DECLARE_CONOBJECT(fxShapeReplicator);
+   DECLARE_CATEGORY("UNLISTED");
 };
 
 #endif // _SHAPEREPLICATOR_H_

+ 1 - 0
Engine/source/T3D/fx/groundCover.h

@@ -123,6 +123,7 @@ public:
    ~GroundCover();
 
    DECLARE_CONOBJECT(GroundCover);
+   DECLARE_CATEGORY("Environment \t BackGround");
 
    static void consoleInit();
    static void initPersistFields();

+ 1 - 0
Engine/source/T3D/fx/lightning.h

@@ -239,6 +239,7 @@ class Lightning : public GameBase
    void processEvent(LightningStrikeEvent*);
 
    DECLARE_CONOBJECT(Lightning);
+   DECLARE_CATEGORY("Environment \t Weather");
    static void initPersistFields();
 
    U32  packUpdate  (NetConnection *conn, U32 mask, BitStream *stream);

+ 2 - 1
Engine/source/T3D/fx/particleEmitter.h

@@ -168,6 +168,7 @@ class ParticleEmitter : public GameBase
    ~ParticleEmitter();
 
    DECLARE_CONOBJECT(ParticleEmitter);
+   DECLARE_CATEGORY("UNLISTED");
 
    static Point3F mWindVelocity;
    static void setWindVelocity( const Point3F &vel ){ mWindVelocity = vel; }
@@ -237,7 +238,7 @@ class ParticleEmitter : public GameBase
                                const LinearColorF &ambientColor,
                                ParticleVertexType *lVerts );
 
-   inline void setupOriented( Particle *part,
+   void setupOriented( Particle *part,
                               const Point3F &camPos,
                               const LinearColorF &ambientColor,
                               ParticleVertexType *lVerts );

+ 1 - 0
Engine/source/T3D/fx/particleEmitterNode.h

@@ -103,6 +103,7 @@ class ParticleEmitterNode : public GameBase
    void advanceTime(F32 dt);
 
    DECLARE_CONOBJECT(ParticleEmitterNode);
+   DECLARE_CATEGORY("Environment \t FX");
    static void initPersistFields();
 
    U32  packUpdate  (NetConnection *conn, U32 mask, BitStream* stream);

+ 1 - 0
Engine/source/T3D/fx/precipitation.h

@@ -280,6 +280,7 @@ class Precipitation : public GameBase
 
    bool onNewDataBlock( GameBaseData *dptr, bool reload );
    DECLARE_CONOBJECT(Precipitation);
+   DECLARE_CATEGORY("Environment \t Weather");
    static void initPersistFields();
    
    U32  packUpdate(NetConnection*, U32 mask, BitStream* stream);

+ 1 - 0
Engine/source/T3D/fx/ribbon.h

@@ -124,6 +124,7 @@ public:
    ~Ribbon();
 
    DECLARE_CONOBJECT(Ribbon);
+   DECLARE_CATEGORY("UNLISTED");
    static void initPersistFields();
    bool onNewDataBlock(GameBaseData*,bool);
    void onRemove();

+ 1 - 0
Engine/source/T3D/fx/ribbonNode.h

@@ -87,6 +87,7 @@ public:
    void advanceTime(F32 dt);
 
    DECLARE_CONOBJECT(RibbonNode);
+   DECLARE_CATEGORY("Environment \t FX");
    static void initPersistFields();
 
    U32  packUpdate  (NetConnection *conn, U32 mask, BitStream* stream);

+ 1 - 1
Engine/source/T3D/fx/splash.cpp

@@ -686,7 +686,7 @@ void Splash::spawnExplosion()
 
    /// could just play the explosion one, but explosion could be weapon specific,
    /// splash sound could be liquid specific. food for thought.
-   SFXProfile* sound_prof = mDataBlock->getSoundProfile();
+   SFXTrack* sound_prof = mDataBlock->getSoundProfile();
    if (sound_prof)
    {
       SFX->playOnce(sound_prof, &getTransform());

+ 1 - 0
Engine/source/T3D/fx/splash.h

@@ -195,6 +195,7 @@ public:
 
    bool onNewDataBlock( GameBaseData *dptr, bool reload );
    DECLARE_CONOBJECT(Splash);
+   DECLARE_CATEGORY("UNLISTED");
 };
 
 

+ 2 - 0
Engine/source/T3D/gameBase/gameBase.h

@@ -105,6 +105,7 @@ public:
 
    // The derived class should provide the following:
    DECLARE_CONOBJECT(GameBaseData);
+   DECLARE_CATEGORY("Datablock");
    GameBaseData();
    static void initPersistFields();
    bool preload(bool server, String &errorStr);
@@ -442,6 +443,7 @@ public:
    #endif
 
    DECLARE_CONOBJECT (GameBase );
+   DECLARE_CATEGORY("UNLISTED");
 
    /// @name Callbacks
    /// @{

+ 1 - 1
Engine/source/T3D/gameBase/gameConnection.cpp

@@ -478,7 +478,7 @@ bool GameConnection::readConnectRequest(BitStream *stream, const char **errorStr
    setProtocolVersion(currentProtocol < CurrentProtocolVersion ? currentProtocol : CurrentProtocolVersion);
 
    const char *serverPassword = Con::getVariable("pref::Server::Password");
-   if(serverPassword[0])
+   if(serverPassword[0] && !isLocalConnection())
    {
       if(String::compare(joinPassword, serverPassword))
       {

+ 2 - 2
Engine/source/T3D/gameBase/gameConnectionEvents.cpp

@@ -387,9 +387,9 @@ void SimSoundAssetEvent::process(NetConnection* con)
 {
 
    if (mAsset->is3D())
-      SFX->playOnce(mAsset->getSfxProfile(), &mTransform);
+      SFX->playOnce(mAsset->getSFXTrack(), &mTransform);
    else
-      SFX->playOnce(mAsset->getSfxProfile());
+      SFX->playOnce(mAsset->getSFXTrack());
 
 }
 

+ 1 - 0
Engine/source/T3D/groundPlane.h

@@ -60,6 +60,7 @@ public:
    typedef SceneObject Parent;
 
    DECLARE_CONOBJECT( GroundPlane );
+   DECLARE_CATEGORY("Environment \t BackGround");
 
    GroundPlane();
    virtual ~GroundPlane();

+ 101 - 98
Engine/source/T3D/guiObjectView.cpp

@@ -91,7 +91,7 @@ IMPLEMENT_CALLBACK( GuiObjectView, onMouseLeave, void, (),(),
 GuiObjectView::GuiObjectView()
    :  mMouseState( None ),
       mLastMousePoint( 0, 0 ),
-      mModel( NULL ),
+      mModelInstance(NULL),
       mMaxOrbitDist( 5.0f ),
       mMinOrbitDist( 0.0f ),
       mCameraRotation( 0.0f, 0.0f, 0.0f ),
@@ -99,13 +99,13 @@ GuiObjectView::GuiObjectView()
       mCameraSpeed( 0.01f ),
       mMountNode( -1 ),
       mMountNodeName( "mount0" ),
-      mMountedModel( NULL ),
+      mMountedModelInstance( NULL ),
       mAnimationSeq( -1 ),
       mRunThread( NULL ),
       mLastRenderTime( 0 ),
       mLight( NULL ),
       mLightColor( 1.0f, 1.0f, 1.0f ),
-      mLightAmbient( 0.5f, 0.5f, 0.5f ),
+      mLightAmbient( 1.0f, 1.0f, 1.0f ),
       mLightDirection( 0.f, 0.707f, -0.707f )
 {
    mCameraMatrix.identity();
@@ -117,16 +117,14 @@ GuiObjectView::GuiObjectView()
    // By default don't do dynamic reflection
    // updates for this viewport.
    mReflectPriority = 0.0f;
+   INIT_ASSET(Model);
+   INIT_ASSET(MountedModel);
 }
 
 //------------------------------------------------------------------------------
 
 GuiObjectView::~GuiObjectView()
 {
-   if( mModel )
-      SAFE_DELETE( mModel );
-   if( mMountedModel )
-      SAFE_DELETE( mMountedModel );
    if( mLight )
       SAFE_DELETE( mLight );
 }
@@ -136,13 +134,10 @@ GuiObjectView::~GuiObjectView()
 void GuiObjectView::initPersistFields()
 {
    docsURL;
-   addGroup( "Model" );
-   
-      addField( "shapeFile", TypeStringFilename, Offset( mModelName, GuiObjectView ),
-         "The object model shape file to show in the view." );
+   addGroup( "Model" );   
+      INITPERSISTFIELD_SHAPEASSET(Model, GuiObjectView, "The source shape asset.");
       addField( "skin", TypeRealString, Offset( mSkinName, GuiObjectView ),
-         "The skin to use on the object model." );
-   
+         "The skin to use on the object model." );   
    endGroup( "Model" );
    
    addGroup( "Animation" );
@@ -152,10 +147,8 @@ void GuiObjectView::initPersistFields()
 
    endGroup( "Animation" );
    
-   addGroup( "Mounting" );
-   
-      addField( "mountedShapeFile", TypeStringFilename, Offset( mMountedModelName, GuiObjectView ),
-         "Optional shape file to mount on the primary model (e.g. weapon)." );
+   addGroup( "Mounting" );   
+      INITPERSISTFIELD_SHAPEASSET(MountedModel, GuiObjectView, "The mounted shape asset.");
       addField( "mountedSkin", TypeRealString, Offset( mMountSkinName, GuiObjectView ),
          "Skin name used on mounted shape file." );
       addField( "mountedNode", TypeRealString, Offset( mMountNodeName, GuiObjectView ),
@@ -197,9 +190,7 @@ void GuiObjectView::onStaticModified( StringTableEntry slotName, const char* new
 {
    Parent::onStaticModified( slotName, newValue );
    
-   static StringTableEntry sShapeFile = StringTable->insert( "shapeFile" );
    static StringTableEntry sSkin = StringTable->insert( "skin" );
-   static StringTableEntry sMountedShapeFile = StringTable->insert( "mountedShapeFile" );
    static StringTableEntry sMountedSkin = StringTable->insert( "mountedSkin" );
    static StringTableEntry sMountedNode = StringTable->insert( "mountedNode" );
    static StringTableEntry sLightColor = StringTable->insert( "lightColor" );
@@ -211,12 +202,8 @@ void GuiObjectView::onStaticModified( StringTableEntry slotName, const char* new
    static StringTableEntry sCameraRotation = StringTable->insert( "cameraRotation" );
    static StringTableEntry sAnimSequence = StringTable->insert( "animSequence" );
    
-   if( slotName == sShapeFile )
-      setObjectModel( String( mModelName ) );
-   else if( slotName == sSkin )
+   if( slotName == sSkin )
       setSkin( String( mSkinName ) );
-   else if( slotName == sMountedShapeFile )
-      setMountedObject( String( mMountedModelName ) );
    else if( slotName == sMountedSkin )
       setMountSkin( String( mMountSkinName ) );
    else if( slotName == sMountedNode )
@@ -325,7 +312,7 @@ void GuiObjectView::setObjectAnimation( S32 index )
    mAnimationSeq = index;
    mAnimationSeqName = String();
    
-   if( mModel )
+   if(mModelInstance)
       _initAnimation();
 }
 
@@ -336,107 +323,123 @@ void GuiObjectView::setObjectAnimation( const String& sequenceName )
    mAnimationSeq = -1;
    mAnimationSeqName = sequenceName;
    
-   if( mModel )
+   if(mModelInstance)
       _initAnimation();
 }
 
 //------------------------------------------------------------------------------
 
-void GuiObjectView::setObjectModel( const String& modelName )
+bool GuiObjectView::setObjectModel( const String& modelName )
 {
-   SAFE_DELETE( mModel );
    mRunThread = 0;
-   mModelName = String::EmptyString;
-   
-   // Load the shape.
 
-   Resource< TSShape > model = ResourceManager::get().load( modelName );
-   if( !model )
+   // Load the shape.
+   _setModel(modelName);
+   if( !getModelResource())
    {
       Con::warnf( "GuiObjectView::setObjectModel - Failed to load model '%s'", modelName.c_str() );
-      return;
+      return false;
    }
-   
+
+   if (!getModelResource()->preloadMaterialList(getModelResource().getPath())) return false;
+
    // Instantiate it.
 
-   mModel = new TSShapeInstance( model, true );
-   mModelName = modelName;
+   mModelInstance = new TSShapeInstance(getModelResource(), true );
+   mModelInstance->resetMaterialList();
+   mModelInstance->cloneMaterialList();
    
    if( !mSkinName.isEmpty() )
-      mModel->reSkin( mSkinName );
+      mModelInstance->reSkin( mSkinName );
 
+   TSMaterialList* pMatList = mModelInstance->getMaterialList();
+   pMatList->setTextureLookupPath(mModelAsset->getShapeFileName());
+   mModelInstance->initMaterialList();
    // Initialize camera values.
    
-   mOrbitPos = mModel->getShape()->center;
-   mMinOrbitDist = mModel->getShape()->mRadius;
+   mOrbitPos = getModelResource()->center;
+   mMinOrbitDist = getModelResource()->mRadius;
 
    // Initialize animation.
    
    _initAnimation();
    _initMount();
+   return true;
+}
+
+void GuiObjectView::onModelChanged()
+{
+
 }
 
 //------------------------------------------------------------------------------
 
 void GuiObjectView::setSkin( const String& name )
 {
-   if( mModel )
-      mModel->reSkin( name, mSkinName );
+   if(mModelInstance)
+      mModelInstance->reSkin( name, mSkinName );
       
    mSkinName = name;
 }
 
+
 //------------------------------------------------------------------------------
 
-void GuiObjectView::setMountSkin( const String& name )
+bool GuiObjectView::setMountedObject( const String& modelName )
 {
-   if( mMountedModel )
-      mMountedModel->reSkin( name, mMountSkinName );
-      
-   mMountSkinName = name;
+   // Load the model.   
+   _setMountedModel(modelName);
+   if (!getMountedModelResource())
+   {
+      Con::warnf("GuiObjectView::setMountedObject - Failed to load model '%s'", modelName.c_str());
+      return false;
+   }
+
+   if (!getMountedModelResource()->preloadMaterialList(getMountedModelResource().getPath())) return false;
+
+   mMountedModelInstance = new TSShapeInstance(getMountedModelResource(), true);
+   mMountedModelInstance->resetMaterialList();
+   mMountedModelInstance->cloneMaterialList();
+
+   if( !mMountSkinName.isEmpty() )
+      mMountedModelInstance->reSkin( mMountSkinName );
+
+   mMountedModelInstance->initMaterialList();
+   
+   if(mMountedModelInstance)
+      _initMount();
+   return true;
+}
+
+void GuiObjectView::onMountedModelChanged()
+{
+
 }
 
 //------------------------------------------------------------------------------
 
-void GuiObjectView::setMountNode( S32 index )
+void GuiObjectView::setMountSkin(const String& name)
 {
-   setMountNode( String::ToString( "mount%i", index ) );
+   if (mMountedModelInstance)
+      mMountedModelInstance->reSkin(name, mMountSkinName);
+
+   mMountSkinName = name;
 }
 
 //------------------------------------------------------------------------------
 
-void GuiObjectView::setMountNode( const String& name )
+void GuiObjectView::setMountNode(S32 index)
 {
-   mMountNodeName = name;
-   
-   if( mModel )
-      _initMount();
+   setMountNode(String::ToString("mount%i", index));
 }
 
 //------------------------------------------------------------------------------
 
-void GuiObjectView::setMountedObject( const String& modelName )
+void GuiObjectView::setMountNode(const String& name)
 {
-   SAFE_DELETE( mMountedModel );
-   mMountedModelName = String::EmptyString;
-
-   // Load the model.
-   
-   Resource< TSShape > model = ResourceManager::get().load( modelName );
-   if( !model )
-   {
-      Con::warnf( "GuiObjectView::setMountedObject -  Failed to load object model '%s'",
-         modelName.c_str() );
-      return;
-   }
+   mMountNodeName = name;
 
-   mMountedModel = new TSShapeInstance( model, true );
-   mMountedModelName = modelName;
-   
-   if( !mMountSkinName.isEmpty() )
-      mMountedModel->reSkin( mMountSkinName );
-   
-   if( mModel )
+   if (mModelInstance)
       _initMount();
 }
 
@@ -483,7 +486,7 @@ void GuiObjectView::onMouseLeave( const GuiEvent & event )
 
 void GuiObjectView::renderWorld( const RectI& updateRect )
 {
-   if( !mModel )
+   if( !mModelInstance)
       return;
       
    GFXTransformSaver _saveTransforms;
@@ -538,26 +541,26 @@ void GuiObjectView::renderWorld( const RectI& updateRect )
 
    // Render primary model.
 
-   if( mModel )
+   if(mModelInstance)
    {
       if( mRunThread )
       {
-         mModel->advanceTime( dt / 1000.f, mRunThread );
-         mModel->animate();
+         mModelInstance->advanceTime( dt / 1000.f, mRunThread );
+         mModelInstance->animate();
       }
       
-      mModel->render( rdata );
+      mModelInstance->render( rdata );
    }
    
    // Render mounted model.
 
-   if( mMountedModel && mMountNode != -1 )
+   if( mMountedModelInstance && mMountNode != -1 )
    {
       GFX->pushWorldMatrix();
-      GFX->multWorld( mModel->mNodeTransforms[ mMountNode ] );
+      GFX->multWorld(mModelInstance->mNodeTransforms[ mMountNode ] );
       GFX->multWorld( mMountTransform );
       
-      mMountedModel->render( rdata );
+      mMountedModelInstance->render( rdata );
 
       GFX->popWorldMatrix();
    }
@@ -620,7 +623,7 @@ void GuiObjectView::setLightDirection( const Point3F& direction )
 
 void GuiObjectView::_initAnimation()
 {
-   AssertFatal( mModel, "GuiObjectView::_initAnimation - No model loaded!" );
+   AssertFatal(getModelResource(), "GuiObjectView::_initAnimation - No model loaded!" );
    
    if( mAnimationSeqName.isEmpty() && mAnimationSeq == -1 )
       return;
@@ -629,7 +632,7 @@ void GuiObjectView::_initAnimation()
             
    if( !mAnimationSeqName.isEmpty() )
    {
-      mAnimationSeq = mModel->getShape()->findSequence( mAnimationSeqName );
+      mAnimationSeq = getModelResource()->findSequence( mAnimationSeqName );
       
       if( mAnimationSeq == -1 )
       {
@@ -646,7 +649,7 @@ void GuiObjectView::_initAnimation()
       
    if( mAnimationSeq != -1 )
    {
-      if( mAnimationSeq >= mModel->getShape()->sequences.size() )
+      if( mAnimationSeq >= getModelResource()->sequences.size() )
       {
          Con::errorf( "GuiObjectView::_initAnimation - Sequence '%i' out of range for model '%s'",
             mAnimationSeq,
@@ -658,9 +661,9 @@ void GuiObjectView::_initAnimation()
       }
       
       if( !mRunThread )
-         mRunThread = mModel->addThread();
+         mRunThread = mModelInstance->addThread();
          
-      mModel->setSequence( mRunThread, mAnimationSeq, 0.f );
+      mModelInstance->setSequence( mRunThread, mAnimationSeq, 0.f );
    }
    
    mLastRenderTime = Platform::getVirtualMilliseconds();
@@ -670,9 +673,9 @@ void GuiObjectView::_initAnimation()
 
 void GuiObjectView::_initMount()
 {
-   AssertFatal( mModel, "GuiObjectView::_initMount - No model loaded!" );
+   AssertFatal(mModelInstance, "GuiObjectView::_initMount - No model loaded!" );
       
-   if( !mMountedModel )
+   if( !mModelInstance)
       return;
       
    mMountTransform.identity();
@@ -681,7 +684,7 @@ void GuiObjectView::_initMount()
    
    if( !mMountNodeName.isEmpty() )
    {
-      mMountNode = mModel->getShape()->findNode( mMountNodeName );
+      mMountNode = getModelResource()->findNode( mMountNodeName );
       if( mMountNode == -1 )
       {
          Con::errorf( "GuiObjectView::_initMount - No node '%s' on '%s'",
@@ -695,7 +698,7 @@ void GuiObjectView::_initMount()
    
    // Make sure mount node is valid.
    
-   if( mMountNode != -1 && mMountNode >= mModel->getShape()->nodes.size() )
+   if( mMountNode != -1 && mMountNode >= getModelResource()->nodes.size() )
    {
       Con::errorf( "GuiObjectView::_initMount - Mount node index '%i' out of range for '%s'",
          mMountNode,
@@ -708,11 +711,11 @@ void GuiObjectView::_initMount()
    
    // Look up node on the mounted model from
    // which to mount to the primary model's node.
-
-   S32 mountPoint = mMountedModel->getShape()->findNode( "mountPoint" );
+   if (!getMountedModelResource()) return;
+   S32 mountPoint = getMountedModelResource()->findNode( "mountPoint" );
    if( mountPoint != -1 )
    {
-      mMountedModel->getShape()->getNodeWorldTransform( mountPoint, &mMountTransform ),
+      getMountedModelResource()->getNodeWorldTransform(mountPoint, &mMountTransform),
       mMountTransform.inverse();
    }
 }
@@ -733,12 +736,12 @@ DefineEngineMethod( GuiObjectView, getModel, const char*, (),,
    "@return Name of the displayed model.\n\n"
    "@see GuiControl")
 {
-   return Con::getReturnBuffer( object->getModelName() );
+   return Con::getReturnBuffer( object->getModel() );
 }
 
 //-----------------------------------------------------------------------------
 
-DefineEngineMethod( GuiObjectView, setModel, void, (const char* shapeName),,
+DefineEngineMethod( GuiObjectView, setModel, bool, (const char* shapeName),,
    "@brief Sets the model to be displayed in this control.\n\n"
    "@param shapeName Name of the model to display.\n"
    "@tsexample\n"
@@ -749,7 +752,7 @@ DefineEngineMethod( GuiObjectView, setModel, void, (const char* shapeName),,
    "@endtsexample\n\n"
    "@see GuiControl")
 {
-   object->setObjectModel( shapeName );
+   return object->setObjectModel( shapeName );
 }
 
 //-----------------------------------------------------------------------------
@@ -763,7 +766,7 @@ DefineEngineMethod( GuiObjectView, getMountedModel, const char*, (),,
    "@return Name of the mounted model.\n\n"
    "@see GuiControl")
 {
-   return Con::getReturnBuffer( object->getMountedModelName() );
+   return Con::getReturnBuffer( object->getMountedModel() );
 }
 
 //-----------------------------------------------------------------------------

+ 26 - 27
Engine/source/T3D/guiObjectView.h

@@ -69,12 +69,17 @@ class GuiObjectView : public GuiTSCtrl
       /// @name Model
       /// @{
       
-      /// Name of the model loaded for display.
-      StringTableEntry mModelName;
-
-      /// Model being displayed in the view.
-      TSShapeInstance* mModel;
-
+      ///Model loaded for display.
+      DECLARE_SHAPEASSET(GuiObjectView, Model, onModelChanged);
+      static bool _setModelData(void* obj, const char* index, const char* data)\
+      {
+         bool ret = false;
+         GuiObjectView* object = static_cast<GuiObjectView*>(obj);
+         ret = object->setObjectModel(StringTable->insert(data));
+         return ret;
+      }
+      void onModelChanged();
+      TSShapeInstance* mModelInstance;
       /// Name of skin to use on model.
       String mSkinName;
       
@@ -103,8 +108,17 @@ class GuiObjectView : public GuiTSCtrl
       /// @name Mounting
       /// @{
       
-      /// Name of model to mount to the primary model.
-      String mMountedModelName;
+      ///Model to mount to the primary model.
+      DECLARE_SHAPEASSET(GuiObjectView, MountedModel, onMountedModelChanged);
+      static bool _setMountedModelData(void* obj, const char* index, const char* data)\
+      {
+         bool ret = false;
+         GuiObjectView* object = static_cast<GuiObjectView*>(obj);
+         ret = object->setMountedObject(StringTable->insert(data));
+         return ret;
+      }
+      void onMountedModelChanged();
+      TSShapeInstance* mMountedModelInstance;
       
       ///
       String mMountSkinName;
@@ -114,9 +128,6 @@ class GuiObjectView : public GuiTSCtrl
       
       /// Name of node to mount the secondary model to.  Unset by default.
       String mMountNodeName;
-
-      /// Model mounted as an image to the primary model.
-      TSShapeInstance* mMountedModel;
             
       ///
       MatrixF mMountTransform;
@@ -173,13 +184,7 @@ class GuiObjectView : public GuiTSCtrl
       
       /// @name Model
       /// @{
-      
-      ///
-      const String& getModelName() const { return mModelName; }
-
-      /// Return the instance of the model being rendered in the view.
-      TSShapeInstance* getModel() const { return mModel; }
-      
+ 
       /// Return the name of the skin used on the primary model.
       const String& getSkin() const { return mSkinName; }
             
@@ -187,7 +192,7 @@ class GuiObjectView : public GuiTSCtrl
       void setSkin( const String& name );
 
       /// Set the model to show in this view.
-      void setObjectModel( const String& modelName );
+      bool setObjectModel( const String& modelName );
       
       /// @}
       
@@ -206,13 +211,7 @@ class GuiObjectView : public GuiTSCtrl
       
       /// @name Mounting
       /// @{
-      
-      /// Return the model mounted to the current primary model; NULL if none.
-      TSShapeInstance* getMountedModel() const { return mMountedModel; }
-      
-      ///
-      const String& getMountedModelName() const { return mMountedModelName; }
-      
+
       /// Return the name of the skin used on the mounted model.
       const String& getMountSkin() const { return mMountSkinName; }
       
@@ -226,7 +225,7 @@ class GuiObjectView : public GuiTSCtrl
       void setMountNode( const String& nodeName );
       
       ///
-      void setMountedObject( const String& modelName );
+      bool setMountedObject( const String& modelName );
             
       /// @}
       

+ 1 - 0
Engine/source/T3D/item.h

@@ -159,6 +159,7 @@ class Item: public ShapeBase
 
   public:
    DECLARE_CONOBJECT(Item);
+   DECLARE_CATEGORY("Item");
 
 
    Item();

+ 1 - 0
Engine/source/T3D/lightBase.h

@@ -111,6 +111,7 @@ public:
    void inspectPostApply();
    static void initPersistFields();
    DECLARE_CONOBJECT(LightBase);
+   DECLARE_CATEGORY("UNLISTED");
 
    // NetObject
    U32 packUpdate( NetConnection *conn, U32 mask, BitStream *stream );

+ 1 - 0
Engine/source/T3D/lighting/boxEnvironmentProbe.h

@@ -69,6 +69,7 @@ public:
    // Declare this object as a ConsoleObject so that we can
    // instantiate it into the world and network it
    DECLARE_CONOBJECT(BoxEnvironmentProbe);
+   DECLARE_CATEGORY("Lighting \t Probes");
 
    //--------------------------------------------------------------------------
    // Object Editing

+ 7 - 1
Engine/source/T3D/lighting/reflectionProbe.cpp

@@ -184,6 +184,10 @@ void ReflectionProbe::initPersistFields()
       "@note Only works for shadow mapped lights.\n\n"
       "@ingroup Lighting");
 
+   Con::addVariable("$Probes::Capturing", TypeBool, &RenderProbeMgr::smBakeReflectionProbes,
+      "Toggles probe rendering capture state.\n\n"
+      "@ingroup Lighting");
+
    Con::addVariable("$Light::renderPreviewProbes", TypeBool, &ReflectionProbe::smRenderPreviewProbes,
       "Toggles rendering of light frustums when the light is selected in the editor.\n\n"
       "@note Only works for shadow mapped lights.\n\n"
@@ -793,7 +797,9 @@ void ReflectionProbe::bake()
    if (mReflectionModeType != BakedCubemap)
       return;
 
+   PROBEMGR->preBake();
    PROBEMGR->bakeProbe(this);
+   PROBEMGR->postBake();
 
    setMaskBits(-1);
 }
@@ -823,7 +829,7 @@ void ReflectionProbe::createEditorResources()
 
 void ReflectionProbe::prepRenderImage(SceneRenderState *state)
 {
-   if (!mEnabled || (!RenderProbeMgr::smRenderReflectionProbes && !dStrcmp(Con::getVariable("$Probes::Capturing", "0"),"1")))
+   if (!mEnabled || (!RenderProbeMgr::smRenderReflectionProbes || RenderProbeMgr::smBakeReflectionProbes))
       return;
 
    Point3F distVec = getRenderPosition() - state->getCameraPosition();

+ 1 - 0
Engine/source/T3D/lighting/reflectionProbe.h

@@ -274,6 +274,7 @@ public:
    // Declare this object as a ConsoleObject so that we can
    // instantiate it into the world and network it
    DECLARE_CONOBJECT(ReflectionProbe);
+   DECLARE_CATEGORY("UNLISTED");
 
    //--------------------------------------------------------------------------
    // Object Editing

+ 1 - 0
Engine/source/T3D/lighting/skylight.h

@@ -68,6 +68,7 @@ public:
    // Declare this object as a ConsoleObject so that we can
    // instantiate it into the world and network it
    DECLARE_CONOBJECT(Skylight);
+   DECLARE_CATEGORY("Lighting \t Probes");
 
    //--------------------------------------------------------------------------
    // Object Editing

+ 1 - 0
Engine/source/T3D/lighting/sphereEnvironmentProbe.h

@@ -64,6 +64,7 @@ public:
    // Declare this object as a ConsoleObject so that we can
    // instantiate it into the world and network it
    DECLARE_CONOBJECT(SphereEnvironmentProbe);
+   DECLARE_CATEGORY("Lighting \t Probes");
 
    //--------------------------------------------------------------------------
    // Object Editing

+ 3 - 1
Engine/source/T3D/missionMarker.h

@@ -85,6 +85,7 @@ class MissionMarker : public ShapeBase
       void unpackUpdate(NetConnection *conn,           BitStream *stream);
 
       DECLARE_CONOBJECT(MissionMarker);
+      DECLARE_CATEGORY("Markers");
       static void initPersistFields();
 };
 
@@ -217,6 +218,7 @@ class CameraBookmark : public MissionMarker
       static void initPersistFields();
 
       DECLARE_CONOBJECT(CameraBookmark);
+      DECLARE_CATEGORY("Markers");
 	  /*DECLARE_CALLBACK( void, onAdd, () );
 	  DECLARE_CALLBACK( void, onRemove, () );
 	  DECLARE_CALLBACK( void, onGroupAdd, () );
@@ -224,4 +226,4 @@ class CameraBookmark : public MissionMarker
 	  DECLARE_CALLBACK( void, onInspectPostApply, () );*/
 };
 
-#endif // _MISSIONMARKER_H_
+#endif // _MISSIONMARKER_H_

+ 1 - 0
Engine/source/T3D/notesObject.h

@@ -67,6 +67,7 @@ public:
    // Declare this object as a ConsoleObject so that we can
    // instantiate it into the world and network it
    DECLARE_CONOBJECT(NotesObject);
+   DECLARE_CATEGORY("Markers");
 
    //--------------------------------------------------------------------------
    // Object Editing

+ 1 - 1
Engine/source/T3D/occlusionVolume.h

@@ -64,7 +64,7 @@ class OcclusionVolume : public ScenePolyhedralSpace
       // SimObject.
       DECLARE_CONOBJECT( OcclusionVolume );
       DECLARE_DESCRIPTION( "A visibility blocking volume." );
-      DECLARE_CATEGORY( "3D Scene" );
+      DECLARE_CATEGORY("Volume");
 
       virtual bool onAdd();
 

+ 1 - 0
Engine/source/T3D/pathCamera.h

@@ -92,6 +92,7 @@ private:
 
 public:
    DECLARE_CONOBJECT(PathCamera);
+   DECLARE_CATEGORY("Cinematic");
    
    DECLARE_CALLBACK( void, onNode, (S32 node));
 

+ 1 - 0
Engine/source/T3D/pathShape.h

@@ -79,6 +79,7 @@ private:
 
 public:
    DECLARE_CONOBJECT(PathShape);
+   DECLARE_CATEGORY("Cinematic");
 
    PathShape();
    ~PathShape();

+ 1 - 0
Engine/source/T3D/physicalZone.h

@@ -77,6 +77,7 @@ class PhysicalZone : public SceneObject
 
    // SimObject
    DECLARE_CONOBJECT(PhysicalZone);
+   DECLARE_CATEGORY("Volume");
    static void consoleInit();
    static void initPersistFields();
    bool onAdd();

+ 1 - 0
Engine/source/T3D/physics/physicsDebris.h

@@ -129,6 +129,7 @@ public:
    virtual ~PhysicsDebris();
 
    DECLARE_CONOBJECT(PhysicsDebris);
+   DECLARE_CATEGORY("UNLISTED");
    static void initPersistFields();
 
    bool onAdd();

+ 2 - 2
Engine/source/T3D/physics/physicsForce.h

@@ -48,7 +48,7 @@ public:
    virtual ~PhysicsForce();
 
    DECLARE_CONOBJECT( PhysicsForce );
-
+   DECLARE_CATEGORY("UNLISTED");
    // SimObject
    static void initPersistFields();
    bool onAdd();
@@ -88,4 +88,4 @@ protected:
 };
 
 
-#endif // _T3D_PHYSICS_PHYSICSFORCE_H_
+#endif // _T3D_PHYSICS_PHYSICSFORCE_H_

+ 1 - 0
Engine/source/T3D/physics/physicsShape.h

@@ -229,6 +229,7 @@ public:
    virtual ~PhysicsShape();
 
    DECLARE_CONOBJECT( PhysicsShape );
+   DECLARE_CATEGORY("Object \t Destructable");
 
    /// Returns the PhysicsShapeData datablock.
    PhysicsShapeData* getDataBlock() { return static_cast<PhysicsShapeData*>( Parent::getDataBlock() ); }

+ 1 - 0
Engine/source/T3D/player.h

@@ -697,6 +697,7 @@ protected:
 
 public:
    DECLARE_CONOBJECT(Player);
+   DECLARE_CATEGORY("Actor \t Controllable");
 
    Player();
    ~Player();

+ 1 - 0
Engine/source/T3D/pointLight.h

@@ -47,6 +47,7 @@ public:
 
    // ConsoleObject
    DECLARE_CONOBJECT( PointLight );
+   DECLARE_CATEGORY("Lighting \t Lights");
    static void initPersistFields();
 
    // SceneObject

+ 2 - 1
Engine/source/T3D/portal.h

@@ -185,7 +185,8 @@ class Portal : public Zone
 
       // SimObject.
       DECLARE_CONOBJECT( Portal );
-      
+      DECLARE_CATEGORY("Volume");
+
       static void initPersistFields();
       static void consoleInit();
 

+ 1 - 0
Engine/source/T3D/prefab.h

@@ -57,6 +57,7 @@ public:
    virtual ~Prefab();
 
    DECLARE_CONOBJECT(Prefab);
+   DECLARE_CATEGORY("Object \t Collection");
   
    static void initPersistFields();
 

+ 1 - 0
Engine/source/T3D/projectile.h

@@ -187,6 +187,7 @@ public:
    ~Projectile();
 
    DECLARE_CONOBJECT(Projectile);
+   DECLARE_CATEGORY("UNLISTED");
 
    // SimObject
    bool onAdd();

+ 1 - 1
Engine/source/T3D/rigid.cpp

@@ -156,7 +156,7 @@ bool Rigid::resolveCollision(const Point3F& p, const Point3F &normal, Rigid* rig
       return false;
 
    // Compute impulse
-   F32 d, n = -nv * (2.0f + restitution * rigid->restitution);
+   F32 d, n = -nv * (1.0+(restitution + rigid->restitution)*0.5);
    Point3F a1,b1,c1;
    mCross(r1,normal,&a1);
    invWorldInertia.mulV(a1,&b1);

+ 37 - 64
Engine/source/T3D/rigidShape.cpp

@@ -900,9 +900,11 @@ bool RigidShape::onNewDataBlock(GameBaseData* dptr, bool reload)
    mRigid.restitution = mDataBlock->body.restitution;
    mRigid.setCenterOfMass(mDataBlock->massCenter);
 
-   // Ignores massBox, just set sphere for now. Derived objects
-   // can set what they want.
-   mRigid.setObjectInertia();
+   // Set inertial tensor, default for the RigidShape is sphere
+   if (mDataBlock->massBox.x > 0 && mDataBlock->massBox.y > 0 && mDataBlock->massBox.z > 0)
+      mRigid.setObjectInertia(mDataBlock->massBox);
+   else
+      mRigid.setObjectInertia(mObjBox.maxExtents - mObjBox.minExtents);
 
    scriptOnNewDataBlock();
 
@@ -1115,9 +1117,9 @@ void RigidShape::updatePos(F32 dt)
       if (mCollisionList.getCount())
       {
          F32 k = mRigid.getKineticEnergy();
-         F32 G = mNetGravity * dt;
+         F32 G = mNetGravity;
          F32 Kg = 0.5 * mRigid.mass * G * G;
-         if (k < sRestTol * Kg && ++restCount > sRestCount)
+         if (k < sRestTol * Kg* dt && ++restCount > sRestCount)
             mRigid.setAtRest();
       }
       else
@@ -1205,8 +1207,12 @@ void RigidShape::updatePos(F32 dt)
 
 void RigidShape::updateForces(F32 dt)
 {
-   if (mDisableMove) return;
-
+   if (mDisableMove)
+   {
+      mRigid.linVelocity = Point3F::Zero;
+      mRigid.angMomentum = Point3F::Zero;
+      return;
+   }
    Point3F torque(0, 0, 0);
    Point3F force(0, 0, mRigid.mass * mNetGravity);
 
@@ -1222,10 +1228,6 @@ void RigidShape::updateForces(F32 dt)
 
    mRigid.force  = force;
    mRigid.torque = torque;
-
-   // If we're still atRest, make sure we're not accumulating anything
-   if ((force.lenSquared() < mDataBlock->contactTol)&& (force.lenSquared() < mDataBlock->contactTol))
-      mRigid.setAtRest();
 }
 
 
@@ -1260,8 +1262,7 @@ bool RigidShape::updateCollision(F32 dt)
    }
 
    // Resolve collisions
-   bool collided = resolveCollision(mRigid,mCollisionList);
-   resolveContacts(mRigid,mCollisionList,dt);
+   bool collided = resolveCollision(mRigid,mCollisionList, dt);
    return collided;
 }
 
@@ -1271,7 +1272,7 @@ bool RigidShape::updateCollision(F32 dt)
 Handle collision impacts, as opposed to contacts. Impulses are calculated based
 on standard collision resolution formulas.
 */
-bool RigidShape::resolveCollision(Rigid&  ns,CollisionList& cList)
+bool RigidShape::resolveCollision(Rigid&  ns,CollisionList& cList, F32 dt)
 {
    PROFILE_SCOPE(RigidShape_resolveCollision);
    // Apply impulses to resolve collision
@@ -1279,6 +1280,11 @@ bool RigidShape::resolveCollision(Rigid&  ns,CollisionList& cList)
    for (S32 i = 0; i < cList.getCount(); i++)
    {
       Collision& c = cList[i];
+      if (c.object == this)
+      {
+         //Con::printf("IMPOSSIBLE!!!!--------------------------------> Self-collision event?");
+         continue;
+      }
       if (c.distance < mDataBlock->collisionTol)
       {
          // Velocity into surface
@@ -1288,9 +1294,7 @@ bool RigidShape::resolveCollision(Rigid&  ns,CollisionList& cList)
          F32 vn = mDot(v, c.normal);
 
          // Only interested in velocities greater than sContactTol,
-         // velocities less than that will be dealt with as contacts
-         // "constraints".
-         if (vn < -mDataBlock->contactTol)
+         if (mFabs(vn) > mDataBlock->contactTol)
          {
 
             // Apply impulses to the rigid body to keep it from
@@ -1313,45 +1317,15 @@ bool RigidShape::resolveCollision(Rigid&  ns,CollisionList& cList)
                queueCollision(col, v - col->getVelocity());
             }
          }
-      }
-   }
-
-   return collided;
-}
-
-//----------------------------------------------------------------------------
-/** Resolve contact forces
-Resolve contact forces using the "penalty" method. Forces are generated based
-on the depth of penetration and the moment of inertia at the point of contact.
-*/
-bool RigidShape::resolveContacts(Rigid& ns,CollisionList& cList,F32 dt)
-{
-   PROFILE_SCOPE(RigidShape_resolveContacts);
-   // Use spring forces to manage contact constraints.
-   bool collided = false;
-   Point3F t,p(0,0,0),l(0,0,0);
-   for (S32 i = 0; i < cList.getCount(); i++) 
-   {
-      const Collision& c = cList[i];
-      if (c.distance < mDataBlock->collisionTol) 
-      {
-
-         // Velocity into the surface
-         Point3F v,r;
-         ns.getOriginVector(c.point,&r);
-         ns.getVelocity(r,&v);
-         F32 vn = mDot(v,c.normal);
-
-         // Only interested in velocities less than mDataBlock->contactTol,
-         // velocities greater than that are dealt with as collisions.
-         if (mFabs(vn) < mDataBlock->contactTol) 
+         // velocities less than that will be dealt with as contacts
+         // "constraints".
+         else
          {
-            collided = true;
-
+            Point3F t;
             // Penetration force. This is actually a spring which
             // will seperate the body from the collision surface.
-            F32 zi = 2 * mFabs(mRigid.getZeroImpulse(r,c.normal));
-            F32 s = (mDataBlock->collisionTol - c.distance) * zi - ((vn / mDataBlock->contactTol) * zi);
+            F32 zi = 2 * mFabs(mRigid.getZeroImpulse(r, c.normal) / dt);
+            F32 s = mMax((mDataBlock->collisionTol - c.distance) * zi - ((vn / 2.0) * zi),0.0f);
             Point3F f = c.normal * s;
 
             // Friction impulse, calculated as a function of the
@@ -1359,10 +1333,10 @@ bool RigidShape::resolveContacts(Rigid& ns,CollisionList& cList,F32 dt)
             // perpendicular to the normal.
             Point3F uv = v - (c.normal * vn);
             F32 ul = uv.len();
-            if (s > 0 && ul) 
+            if (s > 0 && ul)
             {
                uv /= -ul;
-               F32 u = ul * ns.getZeroImpulse(r,uv);
+               F32 u = ul * ns.getZeroImpulse(r, uv) / dt;
                s *= mRigid.friction;
                if (u > s)
                   u = s;
@@ -1370,20 +1344,17 @@ bool RigidShape::resolveContacts(Rigid& ns,CollisionList& cList,F32 dt)
             }
 
             // Accumulate forces
-            p += f;
-            mCross(r,f,&t);
-            l += t;
+            mCross(r, f, &t);
+            ns.linMomentum += f * dt;
+            ns.angMomentum += t * dt;
+            ns.updateVelocity();
          }
       }
    }
 
-   // Contact constraint forces act over time...
-   ns.linMomentum += p * dt;
-   ns.angMomentum += l * dt;
-   ns.updateVelocity();
-   return true;
-}
 
+   return collided;
+}
 
 //----------------------------------------------------------------------------
 
@@ -1693,6 +1664,8 @@ void RigidShape::initPersistFields()
    docsURL;
    addField("disableMove", TypeBool, Offset(mDisableMove, RigidShape),
       "When this flag is set, the vehicle will ignore throttle changes.");
+   addField("isAtRest", TypeBool, Offset(mRigid.atRest, RigidShape),
+      "Debug read of the rest state. do not set");   
    Parent::initPersistFields();
 }
 

+ 2 - 2
Engine/source/T3D/rigidShape.h

@@ -216,8 +216,7 @@ class RigidShape: public ShapeBase
    bool onNewDataBlock( GameBaseData *dptr, bool reload );
    void updatePos(F32 dt);
    bool updateCollision(F32 dt);
-   bool resolveCollision(Rigid& ns,CollisionList& cList);
-   bool resolveContacts(Rigid& ns,CollisionList& cList,F32 dt);
+   bool resolveCollision(Rigid& ns,CollisionList& cList, F32 dt);
    bool resolveDisplacement(Rigid& ns,CollisionState *state,F32 dt);
    void checkTriggers();
    static void findCallback(SceneObject* obj,void * key);
@@ -308,6 +307,7 @@ public:
    void unpackUpdate(NetConnection *conn,           BitStream *stream);
 
    DECLARE_CONOBJECT(RigidShape);
+   DECLARE_CATEGORY("Object \t Destructable");
 };
 
 

+ 1 - 0
Engine/source/T3D/scopeAlwaysShape.cpp

@@ -30,6 +30,7 @@ class ScopeAlwaysShape : public StaticShape
       ScopeAlwaysShape();
       static void initPersistFields();
       DECLARE_CONOBJECT(ScopeAlwaysShape);
+      DECLARE_CATEGORY("UNLISTED");
 };
 
 ScopeAlwaysShape::ScopeAlwaysShape()

+ 163 - 16
Engine/source/T3D/sfx/sfxEmitter.cpp

@@ -89,6 +89,120 @@ ColorI SFXEmitter::smRenderColorOutsideVolume( 255, 0, 0, 255 );
 ColorI SFXEmitter::smRenderColorRangeSphere( 200, 0, 0, 90 );
 
 
+
+//-----------------------------------------------------------------------------
+
+ConsoleType(SoundControls, TypeSoundControls, bool, "")
+
+ConsoleGetType(TypeSoundControls)
+{
+   return "";
+}
+ConsoleSetType(TypeSoundControls)
+{
+}
+
+IMPLEMENT_CONOBJECT(GuiInspectorTypeSoundControls);
+ConsoleDocClass(GuiInspectorTypeSoundControls,
+   "@brief Inspector field type for Controlling playback of sounds\n\n"
+   "Editor use only.\n\n"
+   "@internal"
+);
+
+void GuiInspectorTypeSoundControls::consoleInit()
+{
+   Parent::consoleInit();
+
+   ConsoleBaseType::getType(TypeSoundControls)->setInspectorFieldType("GuiInspectorTypeSoundControls");
+}
+
+GuiControl* GuiInspectorTypeSoundControls::constructEditControl()
+{
+   // Create base filename edit controls
+   GuiControl* retCtrl = Parent::constructEditControl();
+   if (retCtrl == NULL)
+      return retCtrl;
+
+   char szBuffer[512];
+
+   setDataField(StringTable->insert("targetObject"), NULL, mInspector->getInspectObject()->getIdString());
+
+   mPlayButton = new GuiBitmapButtonCtrl();
+   dSprintf(szBuffer, sizeof(szBuffer), "%d.play();", mInspector->getInspectObject()->getId());
+   mPlayButton->setField("Command", szBuffer);
+
+   mPlayButton->setBitmap(StringTable->insert("ToolsModule:playbutton_n_image"));
+
+   mPlayButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
+   mPlayButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
+   mPlayButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
+   mPlayButton->setDataField(StringTable->insert("tooltip"), NULL, "Play this sound emitter");
+
+   mPlayButton->registerObject();
+   addObject(mPlayButton);
+
+   mPauseButton = new GuiBitmapButtonCtrl();
+   dSprintf(szBuffer, sizeof(szBuffer), "%d.pause();", mInspector->getInspectObject()->getId());
+   mPauseButton->setField("Command", szBuffer);
+
+   mPauseButton->setBitmap(StringTable->insert("ToolsModule:pausebutton_n_image"));
+
+   mPauseButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
+   mPauseButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
+   mPauseButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
+   mPauseButton->setDataField(StringTable->insert("tooltip"), NULL, "Pause this sound emitter");
+
+   mPauseButton->registerObject();
+   addObject(mPauseButton);
+
+   mStopButton = new GuiBitmapButtonCtrl();
+   dSprintf(szBuffer, sizeof(szBuffer), "%d.stop();", mInspector->getInspectObject()->getId());
+   mStopButton->setField("Command", szBuffer);
+
+   mStopButton->setBitmap(StringTable->insert("ToolsModule:stopbutton_n_image"));
+
+   mStopButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
+   mStopButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
+   mStopButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
+   mStopButton->setDataField(StringTable->insert("tooltip"), NULL, "Stop this sound emitter");
+
+   mStopButton->registerObject();
+   addObject(mStopButton);
+
+   return retCtrl;
+}
+
+bool GuiInspectorTypeSoundControls::updateRects()
+{
+   S32 dividerPos, dividerMargin;
+   mInspector->getDivider(dividerPos, dividerMargin);
+   Point2I fieldExtent = getExtent();
+   Point2I fieldPos = getPosition();
+
+   bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
+
+   if (mPlayButton != NULL)
+   {
+      RectI shapeEdRect(2, 2, 16, 16);
+      resized |= mPlayButton->resize(shapeEdRect.point, shapeEdRect.extent);
+   }
+
+   if (mPauseButton != NULL)
+   {
+      RectI shapeEdRect(20, 2, 16, 16);
+      resized |= mPauseButton->resize(shapeEdRect.point, shapeEdRect.extent);
+   }
+
+   if (mStopButton != NULL)
+   {
+      RectI shapeEdRect(38, 2, 16, 16);
+      resized |= mStopButton->resize(shapeEdRect.point, shapeEdRect.extent);
+   }
+
+   return resized;
+}
+
+
 //-----------------------------------------------------------------------------
 
 SFXEmitter::SFXEmitter()
@@ -106,8 +220,7 @@ SFXEmitter::SFXEmitter()
    mDescription.mFadeInTime = -1.f;
    mDescription.mFadeOutTime = -1.f;
    mInstanceDescription = &mDescription;
-   mLocalProfile.mFilename = StringTable->EmptyString();
-   mLocalProfile._registerSignals();
+   mLocalProfile = NULL;
 
    INIT_ASSET(Sound);
 
@@ -119,7 +232,9 @@ SFXEmitter::SFXEmitter()
 
 SFXEmitter::~SFXEmitter()
 {
-   mLocalProfile.onRemove();
+   if(mLocalProfile != NULL)
+      mLocalProfile->onRemove();
+
    SFX_DELETE( mSource );
 }
 
@@ -191,6 +306,8 @@ void SFXEmitter::initPersistFields()
 
    addGroup( "Sound" );
 
+      addField("Controls", TypeSoundControls, 0, "");
+
       addField( "playOnAdd",           TypeBool,      Offset( mPlayOnAdd, SFXEmitter ),
          "Whether playback of the emitter's sound should start as soon as the emitter object is added to the level.\n"
          "If this is true, the emitter will immediately start to play when the level is loaded." );
@@ -365,6 +482,7 @@ U32 SFXEmitter::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
 
    // Write the source playback state.
    stream->writeFlag( mask & SourcePlayMask );
+   stream->writeFlag( mask & SourcePauseMask );
    stream->writeFlag( mask & SourceStopMask );
 
    return retMask;
@@ -490,6 +608,8 @@ void SFXEmitter::unpackUpdate( NetConnection *conn, BitStream *stream )
    // Check the source playback masks.
    if ( stream->readFlag() ) // SourcePlayMask
       play();
+   if (stream->readFlag()) //SourcePauseMask
+      pause();
    if ( stream->readFlag() ) // SourceStopMask
       stop();
 }
@@ -653,7 +773,7 @@ void SFXEmitter::_update()
    SFXStatus prevState = mSource ? mSource->getStatus() : SFXStatusNull;
 
    // are we overriding the asset properties?
-   bool useTrackDescriptionOnly = (mUseTrackDescriptionOnly && mSoundAsset.notNull() && mSoundAsset->getSfxProfile());
+   bool useTrackDescriptionOnly = (mUseTrackDescriptionOnly && mSoundAsset.notNull() && getSoundProfile());
 
    if (mSoundAsset.notNull())
    {
@@ -662,12 +782,12 @@ void SFXEmitter::_update()
       else
          mInstanceDescription = &mDescription;
 
-      mLocalProfile = *mSoundAsset->getSfxProfile();
-   }
-   // Make sure all the settings are valid.
-   mInstanceDescription->validate();
-   mLocalProfile.setDescription(mInstanceDescription);
+      mLocalProfile = getSoundProfile();
 
+      // Make sure all the settings are valid.
+      mInstanceDescription->validate();
+      mLocalProfile->setDescription(mInstanceDescription);
+   }
 
    const MatrixF& transform = getTransform();
    const VectorF& velocity = getVelocity();
@@ -676,12 +796,12 @@ void SFXEmitter::_update()
    if( mDirty.test( Track | Is3D | IsLooping | IsStreaming | TrackOnly ) )
    {
       SFX_DELETE( mSource );
-      if (mLocalProfile.getSoundFileName().isNotEmpty())
+      if (getSoundProfile())
       {
-         mSource = SFX->createSource(&mLocalProfile, &transform, &velocity);
+         mSource = SFX->createSource(mLocalProfile, &transform, &velocity);
          if (!mSource)
             Con::errorf("SFXEmitter::_update() - failed to create sound for track %i (%s)",
-               mSoundAsset->getSfxProfile()->getId(), mSoundAsset->getSfxProfile()->getName());
+               getSoundProfile()->getId(), getSoundProfile()->getName());
 
          // If we're supposed to play when the emitter is 
          // added to the scene then also restart playback 
@@ -999,6 +1119,23 @@ void SFXEmitter::play()
 
 //-----------------------------------------------------------------------------
 
+void SFXEmitter::pause()
+{
+   if (mSource)
+      mSource->pause();
+   else
+   {
+      // By clearing the playback masks first we
+      // ensure the last playback command called 
+      // within a single tick is the one obeyed.
+      clearMaskBits(AllSourceMasks);
+
+      setMaskBits(SourcePauseMask);
+   }
+}
+
+//-----------------------------------------------------------------------------
+
 void SFXEmitter::stop()
 {
    if ( mSource )
@@ -1043,8 +1180,8 @@ SFXStatus SFXEmitter::_getPlaybackStatus() const
 
 bool SFXEmitter::is3D() const
 {
-   if( mSoundAsset.notNull() && mSoundAsset->getSfxProfile() != NULL )
-      return mSoundAsset->getSfxProfile()->getDescription()->mIs3D;
+   if( mSoundAsset.notNull() )
+      return mSoundAsset->getSfxDescription()->mIs3D;
    else
       return mInstanceDescription->mIs3D;
 }
@@ -1080,8 +1217,8 @@ void SFXEmitter::setScale( const VectorF &scale )
 {
    F32 maxDistance;
    
-   if( mUseTrackDescriptionOnly && mSoundAsset.notNull() && mSoundAsset->getSfxProfile())
-      maxDistance = mSoundAsset->getSfxProfile()->getDescription()->mMaxDistance;
+   if( mUseTrackDescriptionOnly && mSoundAsset.notNull() && getSoundProfile())
+      maxDistance = mSoundAsset->getSfxDescription()->mMaxDistance;
    else
    {
       // Use the average of the three coords.
@@ -1113,6 +1250,15 @@ DefineEngineMethod( SFXEmitter, play, void, (),,
 
 //-----------------------------------------------------------------------------
 
+DefineEngineMethod(SFXEmitter, pause, void, (), ,
+   "Manually pause playback of the emitter's sound.\n"
+   "If this is called on the server-side object, the pause command will be related to all client-side ghosts.\n")
+{
+   object->pause();
+}
+
+//-----------------------------------------------------------------------------
+
 DefineEngineMethod( SFXEmitter, stop, void, (),,
    "Manually stop playback of the emitter's sound.\n"
    "If this is called on the server-side object, the stop command will be related to all client-side ghosts.\n" )
@@ -1130,3 +1276,4 @@ DefineEngineMethod( SFXEmitter, getSource, SFXSource*, (),,
 {
    return object->getSource();
 }
+

+ 23 - 3
Engine/source/T3D/sfx/sfxEmitter.h

@@ -41,6 +41,21 @@
 class SFXSource;
 class SFXTrack;
 
+DefineConsoleType(TypeSoundControls, bool)
+class GuiInspectorTypeSoundControls : public GuiInspectorField
+{
+   typedef GuiInspectorField Parent;
+public:
+   GuiBitmapButtonCtrl* mPlayButton;
+   GuiBitmapButtonCtrl* mPauseButton;
+   GuiBitmapButtonCtrl* mStopButton;
+
+   DECLARE_CONOBJECT(GuiInspectorTypeSoundControls);
+   static void consoleInit();
+
+   virtual GuiControl* constructEditControl();
+   virtual bool updateRects();
+};
 //RDTODO: make 3D sound emitters yield their source when being culled
 
 /// The SFXEmitter is used to place 2D or 3D sounds into a 
@@ -69,7 +84,8 @@ class SFXEmitter : public SceneObject
          DirtyUpdateMask      = BIT(2),
 
          SourcePlayMask       = BIT(3),
-         SourceStopMask       = BIT(4),
+         SourcePauseMask       = BIT(4),
+         SourceStopMask       = BIT(5),
 
          AllSourceMasks = SourcePlayMask | SourceStopMask,
       };
@@ -116,7 +132,7 @@ class SFXEmitter : public SceneObject
 
       /// A local profile object used to coax the
       /// sound system to play a custom sound.
-      SFXProfile mLocalProfile;
+      SFXTrack* mLocalProfile;
 
       /// The description used by the local profile.
       SFXDescription mDescription;
@@ -219,6 +235,10 @@ class SFXEmitter : public SceneObject
       /// the emitter source is not already playing.
       void play();
 
+      /// Sends network event to pause playback if 
+      /// the emitter source is already playing.
+      void pause();
+
       /// Sends network event to stop emitter 
       /// playback on all ghosted clients.
       void stop();
@@ -240,7 +260,7 @@ class SFXEmitter : public SceneObject
 
       DECLARE_CONOBJECT( SFXEmitter );
       DECLARE_DESCRIPTION( "A 3D object emitting sound." );
-      DECLARE_CATEGORY( "3D Sound" );
+      DECLARE_CATEGORY("Environment \t FX");
 };
 
 #endif // _SFXEMITTER_H_

+ 1 - 1
Engine/source/T3D/sfx/sfxSpace.h

@@ -55,7 +55,7 @@ class SFXSpace : public SceneAmbientSoundObject< ScenePolyhedralObject< SceneSpa
       // SimObject.
       DECLARE_CONOBJECT( SFXSpace );
       DECLARE_DESCRIPTION( "A box volume that defines an ambient sound space." );
-      DECLARE_CATEGORY( "3D Sound" );
+      DECLARE_CATEGORY("Volume");
 
       static void consoleInit();
 };

+ 6 - 3
Engine/source/T3D/shapeBase.cpp

@@ -2303,9 +2303,12 @@ void ShapeBase::updateAudioState(SoundThread& st)
          // if asset is valid, play
          if (st.asset->isAssetValid() )
          {
-            st.sound = SFX->createSource( st.asset->getSfxProfile() , &getTransform() );
-            if ( st.sound )
-               st.sound->play();
+            if (st.asset->load() == AssetBase::Ok)
+            {
+               st.sound = SFX->createSource(st.asset->getSFXTrack(), &getTransform());
+               if (st.sound)
+                  st.sound->play();
+            }
          }
          else
             st.play = false;

+ 1 - 1
Engine/source/T3D/shapeBase.h

@@ -91,7 +91,7 @@ class SFXProfile;
 
 typedef void* Light;
 
-const F32 gGravity = -20;
+const F32 gGravity = -9.8f;
 
 //--------------------------------------------------------------------------
 

+ 2 - 2
Engine/source/T3D/shapeImage.cpp

@@ -2785,7 +2785,7 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState, bool force)
    // Delete any loooping sounds that were in the previous state.
    // this is the crazy bit =/ needs to know prev state in order to stop sounds.
    // lastState does not return an id for the prev state so we keep track of it.
-   if (lastState->sound && lastState->sound->getSfxProfile()->getDescription()->mIsLooping)
+   if (lastState->sound && lastState->sound->getSFXTrack()->getDescription()->mIsLooping)
    {  
       for (Vector<SFXSource*>::iterator i = image.mSoundSources.begin(); i != image.mSoundSources.end(); i++)
          SFX_DELETE((*i));    
@@ -2799,7 +2799,7 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState, bool force)
       if (stateData.sound)
    {
       const Point3F& velocity         = getVelocity();
-         image.addSoundSource(SFX->createSource(stateData.sound->getSfxProfile(), &getRenderTransform(), &velocity));
+         image.addSoundSource(SFX->createSource(stateData.sound->getSFXTrack(), &getRenderTransform(), &velocity));
       }
       if (stateData.soundTrack)
       {

+ 1 - 0
Engine/source/T3D/spotLight.h

@@ -51,6 +51,7 @@ public:
 
    // ConsoleObject
    DECLARE_CONOBJECT( SpotLight );
+   DECLARE_CATEGORY("Lighting \t Lights");
    static void initPersistFields();
 
    // SceneObject

+ 1 - 0
Engine/source/T3D/staticShape.h

@@ -75,6 +75,7 @@ protected:
 
 public:
    DECLARE_CONOBJECT(StaticShape);
+   DECLARE_CATEGORY("Object \t Destructable");
 
    StaticShape();
    ~StaticShape();

+ 1 - 0
Engine/source/T3D/trigger.h

@@ -127,6 +127,7 @@ class Trigger : public GameBase
 
    // SimObject
    DECLARE_CONOBJECT(Trigger);
+   DECLARE_CATEGORY("Volume");
 
    DECLARE_CALLBACK( void, onAdd, ( U32 objectId ) );
    DECLARE_CALLBACK( void, onRemove, ( U32 objectId ) );

+ 1 - 0
Engine/source/T3D/tsStatic.h

@@ -236,6 +236,7 @@ public:
    ~TSStatic();
 
    DECLARE_CONOBJECT(TSStatic);
+   DECLARE_CATEGORY("Object \t Simple");
    static void initPersistFields();
    /// returns the shape asset used for this object
    StringTableEntry getTypeHint() const override { return (getShapeAsset()) ? getShapeAsset()->getAssetName(): StringTable->EmptyString(); }

+ 14 - 7
Engine/source/T3D/vehicles/flyingVehicle.cpp

@@ -541,13 +541,20 @@ void FlyingVehicle::updateForces(F32 /*dt*/)
    F32 vf = mRigid.mass * -mNetGravity;
    F32 h  = getHeight();
    if (h <= 1) {
-      if (h > 0) {
-         vf -= vf * h * 0.1;
+      F32 seperationForce = vf * (1.0 - h);
+      if (h > 0.5) {
+         vf -= seperationForce * mDataBlock->drag;
       } else {
-         vf += mDataBlock->jetForce * -h;
+         if (h < 0.0)
+         {
+            Point3F displacePos = getPosition();
+            displacePos.z += mDataBlock->hoverHeight * (-h * 2);
+            mRigid.linPosition = displacePos;
+         }
+         vf += seperationForce;
       }
    }
-   force += zv * vf;
+   force.z += vf;
 
    // Damping "surfaces"
    force -= xv * mDot(xv,mRigid.linVelocity) * mDataBlock->horizontalSurfaceForce;
@@ -599,8 +606,8 @@ F32 FlyingVehicle::getHeight()
 {
    Point3F sp,ep;
    RayInfo collision;
-   F32 height = (createHeightOn) ? mDataBlock->createHoverHeight : mDataBlock->hoverHeight;
-   F32 r = 10 + height;
+   F32 height = ((createHeightOn) ? mDataBlock->createHoverHeight : mDataBlock->hoverHeight) + mDataBlock->collisionTol*2;
+   F32 r = 3 * height;
    getTransform().getColumn(3, &sp);
    ep.x = sp.x;
    ep.y = sp.y;
@@ -609,7 +616,7 @@ F32 FlyingVehicle::getHeight()
    if( !mContainer->castRay(sp, ep, sClientCollisionMask, &collision) == true )
       collision.t = 1;
    enableCollision();
-   return (r * collision.t - height) / 10;
+   return (r * collision.t - height) / r;
 }
 
 

+ 1 - 0
Engine/source/T3D/vehicles/flyingVehicle.h

@@ -180,6 +180,7 @@ class FlyingVehicle: public Vehicle
    U32 getCollisionMask();
   public:
    DECLARE_CONOBJECT(FlyingVehicle);
+   DECLARE_CATEGORY("Actor \t Controllable");
    static void initPersistFields();
 
    FlyingVehicle();

+ 1 - 0
Engine/source/T3D/vehicles/hoverVehicle.h

@@ -200,6 +200,7 @@ class HoverVehicle : public Vehicle
    void advanceTime(F32 dt);
 
    DECLARE_CONOBJECT(HoverVehicle);
+   DECLARE_CATEGORY("Actor \t Controllable");
 //   static void initPersistFields();
 
    U32  packUpdate  (NetConnection *conn, U32 mask, BitStream *stream);

+ 2 - 2
Engine/source/T3D/vehicles/vehicle.cpp

@@ -807,9 +807,9 @@ void Vehicle::updatePos(F32 dt)
       if (mCollisionList.getCount()) 
       {
          F32 k = mRigid.getKineticEnergy();
-         F32 G = mNetGravity * dt;
+         F32 G = mNetGravity;
          F32 Kg = 0.5 * mRigid.mass * G * G;
-         if (k < sRestTol * Kg && ++restCount > sRestCount)
+         if (k < sRestTol * Kg * dt && ++restCount > sRestCount)
             mRigid.setAtRest();
       }
       else

+ 1 - 0
Engine/source/T3D/vehicles/vehicle.h

@@ -165,6 +165,7 @@ public:
    /// @}
 
    DECLARE_CONOBJECT(Vehicle);
+   DECLARE_CATEGORY("UNLISTED");
 };
 
 

+ 1 - 0
Engine/source/T3D/vehicles/vehicleBlocker.h

@@ -52,6 +52,7 @@ class VehicleBlocker : public SceneObject
    ~VehicleBlocker();
 
    DECLARE_CONOBJECT(VehicleBlocker);
+   DECLARE_CATEGORY("Volume");
    static void initPersistFields();
 
    U32  packUpdate  (NetConnection *conn, U32 mask, BitStream *stream);

+ 1 - 0
Engine/source/T3D/vehicles/wheeledVehicle.h

@@ -225,6 +225,7 @@ class WheeledVehicle: public Vehicle
 
 public:
    DECLARE_CONOBJECT(WheeledVehicle);
+   DECLARE_CATEGORY("Actor \t Controllable");
    static void initPersistFields();
 
    WheeledVehicle();

+ 1 - 1
Engine/source/T3D/zone.h

@@ -68,7 +68,7 @@ class Zone : public SceneAmbientSoundObject< ScenePolyhedralZone >
       // SimObject
       DECLARE_CONOBJECT( Zone );
       DECLARE_DESCRIPTION( "A volume that encloses objects for visibility culling." );
-      DECLARE_CATEGORY( "3D" );
+      DECLARE_CATEGORY("Volume");
 
       static void consoleInit();
 };

+ 1 - 2
Engine/source/afx/afxCamera.h

@@ -51,7 +51,6 @@ struct afxCameraData: public ShapeBaseData {
 
   //
   DECLARE_CONOBJECT(afxCameraData);
-  DECLARE_CATEGORY("AFX");
   static void initPersistFields();
   virtual void packData(BitStream* stream);
   virtual void unpackData(BitStream* stream);
@@ -144,7 +143,7 @@ public:
   bool            isCamera() const { return true; }
 
   DECLARE_CONOBJECT(afxCamera);
-  DECLARE_CATEGORY("AFX");
+  DECLARE_CATEGORY("UNLISTED");
 
 private:          // 3POV SECTION
   void            cam_update_3pov(F32 dt, bool on_server);

+ 1 - 2
Engine/source/afx/afxChoreographer.h

@@ -57,7 +57,6 @@ public:
   static void   initPersistFields();
 
   DECLARE_CONOBJECT(afxChoreographerData);
-  DECLARE_CATEGORY("AFX");
 };
 
 //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
@@ -200,7 +199,7 @@ public:
   virtual void  impactNotify(const Point3F& p, const Point3F& n, SceneObject*) { }
 
   DECLARE_CONOBJECT(afxChoreographer);
-  DECLARE_CATEGORY("AFX");
+  DECLARE_CATEGORY("UNLISTED");
   
   // CONSTRAINT REMAPPING <<
 protected:

+ 0 - 1
Engine/source/afx/afxEffectGroup.h

@@ -96,7 +96,6 @@ public:
   static void   initPersistFields();
 
   DECLARE_CONOBJECT(afxEffectGroupData);
-  DECLARE_CATEGORY("AFX");
 };
 
 //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

+ 0 - 3
Engine/source/afx/afxEffectWrapper.h

@@ -100,7 +100,6 @@ public:
   virtual void    gather_cons_defs(Vector<afxConstraintDef>& defs) { };
 
   DECLARE_CONOBJECT(afxEffectBaseData);
-  DECLARE_CATEGORY("AFX");
 };
 
 //class afxEffectWrapperData : public GameBaseData, public afxEffectDefs
@@ -207,7 +206,6 @@ public:
   static void       initPersistFields();
 
   DECLARE_CONOBJECT(afxEffectWrapperData);
-  DECLARE_CATEGORY("AFX");
 };
 
 inline bool afxEffectWrapperData::testExecConditions(U32 conditions)
@@ -382,7 +380,6 @@ public:
   static afxEffectWrapper* ew_create(afxChoreographer*, afxEffectWrapperData*, afxConstraintMgr*, F32 time_factor, S32 group_index=0);
 
   DECLARE_CONOBJECT(afxEffectWrapper);
-  DECLARE_CATEGORY("AFX");
 };
 
 //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

+ 0 - 2
Engine/source/afx/afxEffectron.h

@@ -82,7 +82,6 @@ public:
   static void   initPersistFields();
 
   DECLARE_CONOBJECT(afxEffectronData);
-  DECLARE_CATEGORY("AFX");
 };
 
 //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
@@ -178,7 +177,6 @@ public:
   void          finish_startup();
 
   DECLARE_CONOBJECT(afxEffectron);
-  DECLARE_CATEGORY("AFX");
 
 private:
   void          process_server();

+ 1 - 2
Engine/source/afx/afxMagicMissile.h

@@ -218,7 +218,6 @@ public:
   static void           initPersistFields();
   
   DECLARE_CONOBJECT(afxMagicMissileData);
-  DECLARE_CATEGORY("AFX");
 
 public:
   /*C*/                 afxMagicMissileData(const afxMagicMissileData&, bool = false);
@@ -400,7 +399,7 @@ public:
   virtual void      onDeleteNotify(SimObject*);
 
   DECLARE_CONOBJECT(afxMagicMissile);
-  DECLARE_CATEGORY("AFX");
+  DECLARE_CATEGORY("UNLISTED");
 
   static void       initPersistFields();  
 

+ 0 - 2
Engine/source/afx/afxMagicSpell.h

@@ -122,7 +122,6 @@ public:
   static void           initPersistFields();
 
   DECLARE_CONOBJECT(afxMagicSpellData);
-  DECLARE_CATEGORY("AFX");
 
   /// @name Callbacks
   /// @{
@@ -320,7 +319,6 @@ public:
   static void   initPersistFields();
 
   DECLARE_CONOBJECT(afxMagicSpell);
-  DECLARE_CATEGORY("AFX");
 
 private:
   void          process_server();

+ 1 - 1
Engine/source/afx/afxResidueMgr.h

@@ -171,7 +171,7 @@ public:
   static void           setMaster(afxResidueMgr* m) { the_mgr = m; }
 
   DECLARE_CONOBJECT(afxResidueMgr);
-  DECLARE_CATEGORY("AFX");
+  DECLARE_CATEGORY("UNLISTED");
 };
 
 //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

Some files were not shown because too many files changed in this diff