Merge branch 'development' into issue_2115

This commit is contained in:
Bloodknight 2018-02-05 15:59:33 +00:00 committed by GitHub
commit 20eefee3cd
511 changed files with 30496 additions and 151320 deletions

View file

@ -74,7 +74,7 @@ ConsoleSetType(TypeComponentAssetPtr)
if (pAssetPtr == NULL)
{
// No, so fail.
//Con::warnf("(TypeTextureAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
//Con::warnf("(TypeComponentAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
return;
}
@ -85,24 +85,20 @@ ConsoleSetType(TypeComponentAssetPtr)
}
// Warn.
Con::warnf("(TypeTextureAssetPtr) - Cannot set multiple args to a single asset.");
Con::warnf("(TypeComponentAssetPtr) - Cannot set multiple args to a single asset.");
}
//-----------------------------------------------------------------------------
ComponentAsset::ComponentAsset() :
mpOwningAssetManager(NULL),
mAssetInitialized(false),
mAcquireReferenceCount(0)
ComponentAsset::ComponentAsset()
{
// Generate an asset definition.
mpAssetDefinition = new AssetDefinition();
mComponentName = StringTable->EmptyString();
mComponentClass = StringTable->EmptyString();
mFriendlyName = StringTable->EmptyString();
mComponentType = StringTable->EmptyString();
mDescription = StringTable->EmptyString();
mComponentName = StringTable->lookup("");
mComponentClass = StringTable->lookup("");
mFriendlyName = StringTable->lookup("");
mComponentType = StringTable->lookup("");
mDescription = StringTable->lookup("");
mScriptFile = StringTable->EmptyString();
}
//-----------------------------------------------------------------------------
@ -127,6 +123,8 @@ void ComponentAsset::initPersistFields()
addField("friendlyName", TypeString, Offset(mFriendlyName, ComponentAsset), "The human-readble name for the component.");
addField("componentType", TypeString, Offset(mComponentType, ComponentAsset), "The category of the component for organizing in the editor.");
addField("description", TypeString, Offset(mDescription, ComponentAsset), "Simple description of the component.");
addField("scriptFile", TypeString, Offset(mScriptFile, ComponentAsset), "A script file with additional scripted functionality for this component.");
}
//------------------------------------------------------------------------------
@ -135,4 +133,16 @@ void ComponentAsset::copyTo(SimObject* object)
{
// Call to parent.
Parent::copyTo(object);
}
void ComponentAsset::initializeAsset()
{
if(Platform::isFile(mScriptFile))
Con::executeFile(mScriptFile, false, false);
}
void ComponentAsset::onAssetRefresh()
{
if (Platform::isFile(mScriptFile))
Con::executeFile(mScriptFile, false, false);
}

View file

@ -44,17 +44,14 @@ class ComponentAsset : public AssetBase
{
typedef AssetBase Parent;
AssetManager* mpOwningAssetManager;
bool mAssetInitialized;
AssetDefinition* mpAssetDefinition;
U32 mAcquireReferenceCount;
StringTableEntry mComponentName;
StringTableEntry mComponentClass;
StringTableEntry mFriendlyName;
StringTableEntry mComponentType;
StringTableEntry mDescription;
StringTableEntry mScriptFile;
public:
ComponentAsset();
virtual ~ComponentAsset();
@ -69,12 +66,20 @@ public:
StringTableEntry getComponentName() { return mComponentName; }
StringTableEntry getComponentClass() { return mComponentClass; }
StringTableEntry getFriendlyName() { return mFriendlyName; }
StringTableEntry getFriendlyType() { return mComponentType; }
StringTableEntry getComponentType() { return mComponentType; }
StringTableEntry getDescription() { return mDescription; }
void setComponentName(StringTableEntry name) { mComponentName = name; }
void setComponentClass(StringTableEntry name) { mComponentClass = name; }
void setFriendlyName(StringTableEntry name) { mFriendlyName = name; }
void setComponentType(StringTableEntry typeName) { mComponentType = typeName; }
void setDescription(StringTableEntry description) { mDescription = description; }
AssetDefinition* getAssetDefinition() { return mpAssetDefinition; }
protected:
virtual void initializeAsset(void) {}
virtual void onAssetRefresh(void) {}
virtual void initializeAsset(void);
virtual void onAssetRefresh(void);
};
DefineConsoleType(TypeComponentAssetPtr, ComponentAsset)

View file

@ -74,7 +74,7 @@ ConsoleSetType(TypeExampleAssetPtr)
if (pAssetPtr == NULL)
{
// No, so fail.
//Con::warnf("(TypeTextureAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
//Con::warnf("(TypeExampleAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
return;
}
@ -85,18 +85,13 @@ ConsoleSetType(TypeExampleAssetPtr)
}
// Warn.
Con::warnf("(TypeTextureAssetPtr) - Cannot set multiple args to a single asset.");
Con::warnf("(TypeExampleAssetPtr) - Cannot set multiple args to a single asset.");
}
//-----------------------------------------------------------------------------
ExampleAsset::ExampleAsset() :
mpOwningAssetManager(NULL),
mAssetInitialized(false),
mAcquireReferenceCount(0)
ExampleAsset::ExampleAsset()
{
// Generate an asset definition.
mpAssetDefinition = new AssetDefinition();
}
//-----------------------------------------------------------------------------

View file

@ -43,11 +43,6 @@ class ExampleAsset : public AssetBase
{
typedef AssetBase Parent;
AssetManager* mpOwningAssetManager;
bool mAssetInitialized;
AssetDefinition* mpAssetDefinition;
U32 mAcquireReferenceCount;
public:
ExampleAsset();
virtual ~ExampleAsset();

View file

@ -0,0 +1,222 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef GUI_ASSET_H
#include "GUIAsset.h"
#endif
#ifndef _ASSET_MANAGER_H_
#include "assets/assetManager.h"
#endif
#ifndef _CONSOLETYPES_H_
#include "console/consoleTypes.h"
#endif
#ifndef _TAML_
#include "persistence/taml/taml.h"
#endif
#ifndef _ASSET_PTR_H_
#include "assets/assetPtr.h"
#endif
// Debug Profiling.
#include "platform/profiler.h"
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(GUIAsset);
ConsoleType(GUIAssetPtr, TypeGUIAssetPtr, GUIAsset, ASSET_ID_FIELD_PREFIX)
//-----------------------------------------------------------------------------
ConsoleGetType(TypeGUIAssetPtr)
{
// Fetch asset Id.
return (*((AssetPtr<GUIAsset>*)dptr)).getAssetId();
}
//-----------------------------------------------------------------------------
ConsoleSetType(TypeGUIAssetPtr)
{
// Was a single argument specified?
if (argc == 1)
{
// Yes, so fetch field value.
const char* pFieldValue = argv[0];
// Fetch asset pointer.
AssetPtr<GUIAsset>* pAssetPtr = dynamic_cast<AssetPtr<GUIAsset>*>((AssetPtrBase*)(dptr));
// Is the asset pointer the correct type?
if (pAssetPtr == NULL)
{
// No, so fail.
//Con::warnf("(TypeGUIAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
return;
}
// Set asset.
pAssetPtr->setAssetId(pFieldValue);
return;
}
// Warn.
Con::warnf("(TypeGUIAssetPtr) - Cannot set multiple args to a single asset.");
}
//-----------------------------------------------------------------------------
GUIAsset::GUIAsset()
{
mScriptFilePath = StringTable->EmptyString();
mGUIFilePath = StringTable->EmptyString();
}
//-----------------------------------------------------------------------------
GUIAsset::~GUIAsset()
{
// If the asset manager does not own the asset then we own the
// asset definition so delete it.
if (!getOwned())
delete mpAssetDefinition;
}
//-----------------------------------------------------------------------------
void GUIAsset::initPersistFields()
{
// Call parent.
Parent::initPersistFields();
addField("scriptFilePath", TypeString, Offset(mScriptFilePath, GUIAsset), "Path to the script file for the gui");
addField("GUIFilePath", TypeString, Offset(mGUIFilePath, GUIAsset), "Path to the gui file");
}
//------------------------------------------------------------------------------
void GUIAsset::copyTo(SimObject* object)
{
// Call to parent.
Parent::copyTo(object);
}
void GUIAsset::initializeAsset()
{
if (Platform::isFile(mGUIFilePath))
Con::executeFile(mGUIFilePath, false, false);
if (Platform::isFile(mScriptFilePath))
Con::executeFile(mScriptFilePath, false, false);
}
void GUIAsset::onAssetRefresh()
{
if (Platform::isFile(mGUIFilePath))
Con::executeFile(mGUIFilePath, false, false);
if (Platform::isFile(mScriptFilePath))
Con::executeFile(mScriptFilePath, false, false);
}
//-----------------------------------------------------------------------------
// GuiInspectorTypeAssetId
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(GuiInspectorTypeGUIAssetPtr);
ConsoleDocClass(GuiInspectorTypeGUIAssetPtr,
"@brief Inspector field type for GUI Asset Objects\n\n"
"Editor use only.\n\n"
"@internal"
);
void GuiInspectorTypeGUIAssetPtr::consoleInit()
{
Parent::consoleInit();
ConsoleBaseType::getType(TypeGUIAssetPtr)->setInspectorFieldType("GuiInspectorTypeGUIAssetPtr");
}
GuiControl* GuiInspectorTypeGUIAssetPtr::constructEditControl()
{
// Create base filename edit controls
GuiControl *retCtrl = Parent::constructEditControl();
if (retCtrl == NULL)
return retCtrl;
// Change filespec
char szBuffer[512];
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"GUIAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
mInspector->getComponentGroupTargetId(), mCaption);
mBrowseButton->setField("Command", szBuffer);
// Create "Open in ShapeEditor" button
mSMEdButton = new GuiBitmapButtonCtrl();
dSprintf(szBuffer, sizeof(szBuffer), "echo(\"Game Object Editor not implemented yet!\");", retCtrl->getId());
mSMEdButton->setField("Command", szBuffer);
char bitmapName[512] = "tools/worldEditor/images/toolbar/shape-editor";
mSMEdButton->setBitmap(bitmapName);
mSMEdButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
mSMEdButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
mSMEdButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
mSMEdButton->setDataField(StringTable->insert("tooltip"), NULL, "Open this file in the State Machine Editor");
mSMEdButton->registerObject();
addObject(mSMEdButton);
return retCtrl;
}
bool GuiInspectorTypeGUIAssetPtr::updateRects()
{
S32 dividerPos, dividerMargin;
mInspector->getDivider(dividerPos, dividerMargin);
Point2I fieldExtent = getExtent();
Point2I fieldPos = getPosition();
mCaptionRect.set(0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y);
mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y);
bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
if (mBrowseButton != NULL)
{
mBrowseRect.set(fieldExtent.x - 32, 2, 14, fieldExtent.y - 4);
resized |= mBrowseButton->resize(mBrowseRect.point, mBrowseRect.extent);
}
if (mSMEdButton != NULL)
{
RectI shapeEdRect(fieldExtent.x - 16, 2, 14, fieldExtent.y - 4);
resized |= mSMEdButton->resize(shapeEdRect.point, shapeEdRect.extent);
}
return resized;
}

View file

@ -0,0 +1,89 @@
#pragma once
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef GUI_ASSET_H
#define GUI_ASSET_H
#ifndef _ASSET_BASE_H_
#include "assets/assetBase.h"
#endif
#ifndef _ASSET_DEFINITION_H_
#include "assets/assetDefinition.h"
#endif
#ifndef _STRINGUNIT_H_
#include "string/stringUnit.h"
#endif
#ifndef _ASSET_FIELD_TYPES_H_
#include "assets/assetFieldTypes.h"
#endif
#include "gui/editor/guiInspectorTypes.h"
//-----------------------------------------------------------------------------
class GUIAsset : public AssetBase
{
typedef AssetBase Parent;
StringTableEntry mScriptFilePath;
StringTableEntry mGUIFilePath;
public:
GUIAsset();
virtual ~GUIAsset();
/// Engine.
static void initPersistFields();
virtual void copyTo(SimObject* object);
/// Declare Console Object.
DECLARE_CONOBJECT(GUIAsset);
protected:
virtual void initializeAsset(void);
virtual void onAssetRefresh(void);
};
DefineConsoleType(TypeGUIAssetPtr, GUIAsset)
//-----------------------------------------------------------------------------
// TypeAssetId GuiInspectorField Class
//-----------------------------------------------------------------------------
class GuiInspectorTypeGUIAssetPtr : public GuiInspectorTypeFileName
{
typedef GuiInspectorTypeFileName Parent;
public:
GuiBitmapButtonCtrl *mSMEdButton;
DECLARE_CONOBJECT(GuiInspectorTypeGUIAssetPtr);
static void consoleInit();
virtual GuiControl* constructEditControl();
virtual bool updateRects();
};
#endif // _ASSET_BASE_H_

View file

@ -74,7 +74,7 @@ ConsoleSetType(TypeGameObjectAssetPtr)
if (pAssetPtr == NULL)
{
// No, so fail.
//Con::warnf("(TypeTextureAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
//Con::warnf("(TypeGameObjectAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
return;
}
@ -85,19 +85,13 @@ ConsoleSetType(TypeGameObjectAssetPtr)
}
// Warn.
Con::warnf("(TypeTextureAssetPtr) - Cannot set multiple args to a single asset.");
Con::warnf("(TypeGameObjectAssetPtr) - Cannot set multiple args to a single asset.");
}
//-----------------------------------------------------------------------------
GameObjectAsset::GameObjectAsset() :
mpOwningAssetManager(NULL),
mAssetInitialized(false),
mAcquireReferenceCount(0)
GameObjectAsset::GameObjectAsset()
{
// Generate an asset definition.
mpAssetDefinition = new AssetDefinition();
mGameObjectName = StringTable->lookup("");
mScriptFilePath = StringTable->lookup("");
mTAMLFilePath = StringTable->lookup("");
@ -131,4 +125,94 @@ void GameObjectAsset::copyTo(SimObject* object)
{
// Call to parent.
Parent::copyTo(object);
}
void GameObjectAsset::initializeAsset()
{
if (Platform::isFile(mScriptFilePath))
Con::executeFile(mScriptFilePath, false, false);
}
void GameObjectAsset::onAssetRefresh()
{
if (Platform::isFile(mScriptFilePath))
Con::executeFile(mScriptFilePath, false, false);
}
//-----------------------------------------------------------------------------
// GuiInspectorTypeAssetId
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(GuiInspectorTypeGameObjectAssetPtr);
ConsoleDocClass(GuiInspectorTypeGameObjectAssetPtr,
"@brief Inspector field type for Game Objects\n\n"
"Editor use only.\n\n"
"@internal"
);
void GuiInspectorTypeGameObjectAssetPtr::consoleInit()
{
Parent::consoleInit();
ConsoleBaseType::getType(TypeGameObjectAssetPtr)->setInspectorFieldType("GuiInspectorTypeGameObjectAssetPtr");
}
GuiControl* GuiInspectorTypeGameObjectAssetPtr::constructEditControl()
{
// Create base filename edit controls
GuiControl *retCtrl = Parent::constructEditControl();
if (retCtrl == NULL)
return retCtrl;
// Change filespec
char szBuffer[512];
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"GameObjectAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
mInspector->getComponentGroupTargetId(), mCaption);
mBrowseButton->setField("Command", szBuffer);
// Create "Open in ShapeEditor" button
mSMEdButton = new GuiBitmapButtonCtrl();
dSprintf(szBuffer, sizeof(szBuffer), "echo(\"Game Object Editor not implemented yet!\");", retCtrl->getId());
mSMEdButton->setField("Command", szBuffer);
char bitmapName[512] = "tools/worldEditor/images/toolbar/shape-editor";
mSMEdButton->setBitmap(bitmapName);
mSMEdButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
mSMEdButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
mSMEdButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
mSMEdButton->setDataField(StringTable->insert("tooltip"), NULL, "Open this file in the State Machine Editor");
mSMEdButton->registerObject();
addObject(mSMEdButton);
return retCtrl;
}
bool GuiInspectorTypeGameObjectAssetPtr::updateRects()
{
S32 dividerPos, dividerMargin;
mInspector->getDivider(dividerPos, dividerMargin);
Point2I fieldExtent = getExtent();
Point2I fieldPos = getPosition();
mCaptionRect.set(0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y);
mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y);
bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
if (mBrowseButton != NULL)
{
mBrowseRect.set(fieldExtent.x - 32, 2, 14, fieldExtent.y - 4);
resized |= mBrowseButton->resize(mBrowseRect.point, mBrowseRect.extent);
}
if (mSMEdButton != NULL)
{
RectI shapeEdRect(fieldExtent.x - 16, 2, 14, fieldExtent.y - 4);
resized |= mSMEdButton->resize(shapeEdRect.point, shapeEdRect.extent);
}
return resized;
}

View file

@ -38,17 +38,15 @@
#ifndef _ASSET_FIELD_TYPES_H_
#include "assets/assetFieldTypes.h"
#endif
#ifndef _GUI_INSPECTOR_TYPES_H_
#include "gui/editor/guiInspectorTypes.h"
#endif
//-----------------------------------------------------------------------------
class GameObjectAsset : public AssetBase
{
typedef AssetBase Parent;
AssetManager* mpOwningAssetManager;
bool mAssetInitialized;
AssetDefinition* mpAssetDefinition;
U32 mAcquireReferenceCount;
StringTableEntry mGameObjectName;
StringTableEntry mScriptFilePath;
StringTableEntry mTAMLFilePath;
@ -65,11 +63,29 @@ public:
DECLARE_CONOBJECT(GameObjectAsset);
protected:
virtual void initializeAsset(void) {}
virtual void onAssetRefresh(void) {}
virtual void initializeAsset(void);
virtual void onAssetRefresh(void);
};
DefineConsoleType(TypeGameObjectAssetPtr, GameObjectAsset)
//-----------------------------------------------------------------------------
// TypeAssetId GuiInspectorField Class
//-----------------------------------------------------------------------------
class GuiInspectorTypeGameObjectAssetPtr : public GuiInspectorTypeFileName
{
typedef GuiInspectorTypeFileName Parent;
public:
GuiBitmapButtonCtrl *mSMEdButton;
DECLARE_CONOBJECT(GuiInspectorTypeGameObjectAssetPtr);
static void consoleInit();
virtual GuiControl* constructEditControl();
virtual bool updateRects();
};
#endif // _ASSET_BASE_H_

View file

@ -0,0 +1,161 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef IMAGE_ASSET_H
#include "ImageAsset.h"
#endif
#ifndef _ASSET_MANAGER_H_
#include "assets/assetManager.h"
#endif
#ifndef _CONSOLETYPES_H_
#include "console/consoleTypes.h"
#endif
#ifndef _TAML_
#include "persistence/taml/taml.h"
#endif
#ifndef _ASSET_PTR_H_
#include "assets/assetPtr.h"
#endif
// Debug Profiling.
#include "platform/profiler.h"
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(ImageAsset);
ConsoleType(ImageAssetPtr, TypeImageAssetPtr, ImageAsset, ASSET_ID_FIELD_PREFIX)
//-----------------------------------------------------------------------------
ConsoleGetType(TypeImageAssetPtr)
{
// Fetch asset Id.
return (*((AssetPtr<ImageAsset>*)dptr)).getAssetId();
}
//-----------------------------------------------------------------------------
ConsoleSetType(TypeImageAssetPtr)
{
// Was a single argument specified?
if (argc == 1)
{
// Yes, so fetch field value.
const char* pFieldValue = argv[0];
// Fetch asset pointer.
AssetPtr<ImageAsset>* pAssetPtr = dynamic_cast<AssetPtr<ImageAsset>*>((AssetPtrBase*)(dptr));
// Is the asset pointer the correct type?
if (pAssetPtr == NULL)
{
// No, so fail.
//Con::warnf("(TypeImageAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
return;
}
// Set asset.
pAssetPtr->setAssetId(pFieldValue);
return;
}
// Warn.
Con::warnf("(TypeImageAssetPtr) - Cannot set multiple args to a single asset.");
}
//-----------------------------------------------------------------------------
ImageAsset::ImageAsset()
{
mImageFileName = StringTable->EmptyString();
mImage = NULL;
mUseMips = true;
mIsHDRImage = false;
mIsValidImage = false;
}
//-----------------------------------------------------------------------------
ImageAsset::~ImageAsset()
{
}
//-----------------------------------------------------------------------------
void ImageAsset::initPersistFields()
{
// Call parent.
Parent::initPersistFields();
addField("imageFile", TypeString, Offset(mImageFileName, ImageAsset), "Path to the image file.");
addField("useMips", TypeBool, Offset(mUseMips, ImageAsset), "Should the image use mips? (Currently unused).");
addField("isHDRImage", TypeBool, Offset(mIsHDRImage, ImageAsset), "Is the image in an HDR format? (Currently unused)");
}
//------------------------------------------------------------------------------
void ImageAsset::copyTo(SimObject* object)
{
// Call to parent.
Parent::copyTo(object);
}
void ImageAsset::loadImage()
{
SAFE_DELETE(mImage);
if (mImageFileName)
{
if (!Platform::isFile(mImageFileName))
{
Con::errorf("ImageAsset::initializeAsset: Attempted to load file %s but it was not valid!", mImageFileName);
return;
}
mImage.set(mImageFileName, &GFXStaticTextureSRGBProfile, avar("%s() - mImage (line %d)", __FUNCTION__, __LINE__));
if (mImage)
{
mIsValidImage = true;
return;
}
}
mIsValidImage = false;
}
void ImageAsset::initializeAsset()
{
loadImage();
}
void ImageAsset::onAssetRefresh()
{
loadImage();
}

View file

@ -0,0 +1,90 @@
#pragma once
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef IMAGE_ASSET_H
#define IMAGE_ASSET_H
#ifndef _ASSET_BASE_H_
#include "assets/assetBase.h"
#endif
#ifndef _ASSET_DEFINITION_H_
#include "assets/assetDefinition.h"
#endif
#ifndef _STRINGUNIT_H_
#include "string/stringUnit.h"
#endif
#ifndef _ASSET_FIELD_TYPES_H_
#include "assets/assetFieldTypes.h"
#endif
#include "gfx/bitmap/gBitmap.h"
#include "gfx/gfxTextureHandle.h"
//-----------------------------------------------------------------------------
class ImageAsset : public AssetBase
{
typedef AssetBase Parent;
AssetManager* mpOwningAssetManager;
bool mAssetInitialized;
AssetDefinition* mpAssetDefinition;
U32 mAcquireReferenceCount;
StringTableEntry mImageFileName;
GFXTexHandle mImage;
bool mIsValidImage;
bool mUseMips;
bool mIsHDRImage;
public:
ImageAsset();
virtual ~ImageAsset();
/// Engine.
static void initPersistFields();
virtual void copyTo(SimObject* object);
/// Declare Console Object.
DECLARE_CONOBJECT(ImageAsset);
StringTableEntry getImageFileName() { return mImageFileName; }
bool isValid() { return mIsValidImage; }
GFXTexHandle* getImage() { return &mImage; }
protected:
virtual void initializeAsset(void);
virtual void onAssetRefresh(void);
void loadImage();
};
DefineConsoleType(TypeImageAssetPtr, ImageAsset)
#endif

View file

@ -0,0 +1,126 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef LEVEL_ASSET_H
#include "LevelAsset.h"
#endif
#ifndef _ASSET_MANAGER_H_
#include "assets/assetManager.h"
#endif
#ifndef _CONSOLETYPES_H_
#include "console/consoleTypes.h"
#endif
#ifndef _TAML_
#include "persistence/taml/taml.h"
#endif
#ifndef _ASSET_PTR_H_
#include "assets/assetPtr.h"
#endif
// Debug Profiling.
#include "platform/profiler.h"
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(LevelAsset);
ConsoleType(LevelAssetPtr, TypeLevelAssetPtr, LevelAsset, ASSET_ID_FIELD_PREFIX)
//-----------------------------------------------------------------------------
ConsoleGetType(TypeLevelAssetPtr)
{
// Fetch asset Id.
return (*((AssetPtr<LevelAsset>*)dptr)).getAssetId();
}
//-----------------------------------------------------------------------------
ConsoleSetType(TypeLevelAssetPtr)
{
// Was a single argument specified?
if (argc == 1)
{
// Yes, so fetch field value.
const char* pFieldValue = argv[0];
// Fetch asset pointer.
AssetPtr<LevelAsset>* pAssetPtr = dynamic_cast<AssetPtr<LevelAsset>*>((AssetPtrBase*)(dptr));
// Is the asset pointer the correct type?
if (pAssetPtr == NULL)
{
// No, so fail.
//Con::warnf("(TypeLevelAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
return;
}
// Set asset.
pAssetPtr->setAssetId(pFieldValue);
return;
}
// Warn.
Con::warnf("(TypeLevelAssetPtr) - Cannot set multiple args to a single asset.");
}
//-----------------------------------------------------------------------------
LevelAsset::LevelAsset()
{
mLevelFile = StringTable->EmptyString();
mPreviewImage = StringTable->EmptyString();
}
//-----------------------------------------------------------------------------
LevelAsset::~LevelAsset()
{
// If the asset manager does not own the asset then we own the
// asset definition so delete it.
if (!getOwned())
delete mpAssetDefinition;
}
//-----------------------------------------------------------------------------
void LevelAsset::initPersistFields()
{
// Call parent.
Parent::initPersistFields();
addField("LevelFile", TypeString, Offset(mLevelFile, LevelAsset), "Path to the actual level file.");
addField("PreviewImage", TypeString, Offset(mPreviewImage, LevelAsset), "Path to the image used for selection preview.");
}
//------------------------------------------------------------------------------
void LevelAsset::copyTo(SimObject* object)
{
// Call to parent.
Parent::copyTo(object);
}

View file

@ -0,0 +1,72 @@
#pragma once
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef LEVEL_ASSET_H
#define LEVEL_ASSET_H
#ifndef _ASSET_BASE_H_
#include "assets/assetBase.h"
#endif
#ifndef _ASSET_DEFINITION_H_
#include "assets/assetDefinition.h"
#endif
#ifndef _STRINGUNIT_H_
#include "string/stringUnit.h"
#endif
#ifndef _ASSET_FIELD_TYPES_H_
#include "assets/assetFieldTypes.h"
#endif
//-----------------------------------------------------------------------------
class LevelAsset : public AssetBase
{
typedef AssetBase Parent;
StringTableEntry mLevelFile;
StringTableEntry mPreviewImage;
bool mIsSubLevel;
StringTableEntry mMainLevelAsset;
public:
LevelAsset();
virtual ~LevelAsset();
/// Engine.
static void initPersistFields();
virtual void copyTo(SimObject* object);
/// Declare Console Object.
DECLARE_CONOBJECT(LevelAsset);
protected:
virtual void initializeAsset(void) {}
virtual void onAssetRefresh(void) {}
};
DefineConsoleType(TypeLevelAssetPtr, LevelAsset)
#endif // _ASSET_BASE_H_

View file

@ -0,0 +1,241 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef MATERIALASSET_H
#include "MaterialAsset.h"
#endif
#ifndef _ASSET_MANAGER_H_
#include "assets/assetManager.h"
#endif
#ifndef _CONSOLETYPES_H_
#include "console/consoleTypes.h"
#endif
#ifndef _TAML_
#include "persistence/taml/taml.h"
#endif
#ifndef _ASSET_PTR_H_
#include "assets/assetPtr.h"
#endif
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(MaterialAsset);
ConsoleType(MaterialAssetPtr, TypeMaterialAssetPtr, MaterialAsset, ASSET_ID_FIELD_PREFIX)
//-----------------------------------------------------------------------------
ConsoleGetType(TypeMaterialAssetPtr)
{
// Fetch asset Id.
return (*((AssetPtr<MaterialAsset>*)dptr)).getAssetId();
}
//-----------------------------------------------------------------------------
ConsoleSetType(TypeMaterialAssetPtr)
{
// Was a single argument specified?
if (argc == 1)
{
// Yes, so fetch field value.
const char* pFieldValue = argv[0];
// Fetch asset pointer.
AssetPtr<MaterialAsset>* pAssetPtr = dynamic_cast<AssetPtr<MaterialAsset>*>((AssetPtrBase*)(dptr));
// Is the asset pointer the correct type?
if (pAssetPtr == NULL)
{
// No, so fail.
//Con::warnf("(TypeMaterialAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
return;
}
// Set asset.
pAssetPtr->setAssetId(pFieldValue);
return;
}
// Warn.
Con::warnf("(TypeMaterialAssetPtr) - Cannot set multiple args to a single asset.");
}
//-----------------------------------------------------------------------------
MaterialAsset::MaterialAsset()
{
mShaderGraphFile = "";
mScriptFile = "";
mMatDefinitionName = "";
}
//-----------------------------------------------------------------------------
MaterialAsset::~MaterialAsset()
{
// If the asset manager does not own the asset then we own the
// asset definition so delete it.
if (!getOwned())
delete mpAssetDefinition;
}
//-----------------------------------------------------------------------------
void MaterialAsset::initPersistFields()
{
// Call parent.
Parent::initPersistFields();
//addField("shaderGraph", TypeRealString, Offset(mShaderGraphFile, MaterialAsset), "");
addField("scriptFile", TypeRealString, Offset(mScriptFile, MaterialAsset), "Path to the file containing the material definition.");
addField("materialDefinitionName", TypeRealString, Offset(mMatDefinitionName, MaterialAsset), "Name of the material definition this asset is for.");
}
void MaterialAsset::initializeAsset()
{
// Call parent.
Parent::initializeAsset();
compileShader();
if (Platform::isFile(mScriptFile))
Con::executeFile(mScriptFile, false, false);
}
void MaterialAsset::onAssetRefresh()
{
if (Platform::isFile(mScriptFile))
Con::executeFile(mScriptFile, false, false);
if (!mMatDefinitionName.isEmpty())
{
Material* matDef;
if (!Sim::findObject(mMatDefinitionName.c_str(), matDef))
{
Con::errorf("MaterialAsset: Unable to find the Material %s", mMatDefinitionName.c_str());
return;
}
matDef->reload();
}
}
//------------------------------------------------------------------------------
void MaterialAsset::compileShader()
{
}
void MaterialAsset::copyTo(SimObject* object)
{
// Call to parent.
Parent::copyTo(object);
}
ConsoleMethod(MaterialAsset, compileShader, void, 2, 2, "() - Compiles the material's generated shader, if any. Not yet implemented\n")
{
object->compileShader();
}
//-----------------------------------------------------------------------------
// GuiInspectorTypeAssetId
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(GuiInspectorTypeMaterialAssetPtr);
ConsoleDocClass(GuiInspectorTypeMaterialAssetPtr,
"@brief Inspector field type for Material Asset Objects\n\n"
"Editor use only.\n\n"
"@internal"
);
void GuiInspectorTypeMaterialAssetPtr::consoleInit()
{
Parent::consoleInit();
ConsoleBaseType::getType(TypeMaterialAssetPtr)->setInspectorFieldType("GuiInspectorTypeMaterialAssetPtr");
}
GuiControl* GuiInspectorTypeMaterialAssetPtr::constructEditControl()
{
// Create base filename edit controls
GuiControl *retCtrl = Parent::constructEditControl();
if (retCtrl == NULL)
return retCtrl;
// Change filespec
char szBuffer[512];
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"MaterialAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
mInspector->getComponentGroupTargetId(), mCaption);
mBrowseButton->setField("Command", szBuffer);
// Create "Open in ShapeEditor" button
mSMEdButton = new GuiBitmapButtonCtrl();
dSprintf(szBuffer, sizeof(szBuffer), "echo(\"Game Object Editor not implemented yet!\");", retCtrl->getId());
mSMEdButton->setField("Command", szBuffer);
char bitmapName[512] = "tools/worldEditor/images/toolbar/shape-editor";
mSMEdButton->setBitmap(bitmapName);
mSMEdButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
mSMEdButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
mSMEdButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
mSMEdButton->setDataField(StringTable->insert("tooltip"), NULL, "Open this file in the Material Editor");
mSMEdButton->registerObject();
addObject(mSMEdButton);
return retCtrl;
}
bool GuiInspectorTypeMaterialAssetPtr::updateRects()
{
S32 dividerPos, dividerMargin;
mInspector->getDivider(dividerPos, dividerMargin);
Point2I fieldExtent = getExtent();
Point2I fieldPos = getPosition();
mCaptionRect.set(0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y);
mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y);
bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
if (mBrowseButton != NULL)
{
mBrowseRect.set(fieldExtent.x - 32, 2, 14, fieldExtent.y - 4);
resized |= mBrowseButton->resize(mBrowseRect.point, mBrowseRect.extent);
}
if (mSMEdButton != NULL)
{
RectI shapeEdRect(fieldExtent.x - 16, 2, 14, fieldExtent.y - 4);
resized |= mSMEdButton->resize(shapeEdRect.point, shapeEdRect.extent);
}
return resized;
}

View file

@ -0,0 +1,101 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef MATERIALASSET_H
#define MATERIALASSET_H
#ifndef _ASSET_BASE_H_
#include "assets/assetBase.h"
#endif
#ifndef _ASSET_DEFINITION_H_
#include "assets/assetDefinition.h"
#endif
#ifndef _STRINGUNIT_H_
#include "string/stringUnit.h"
#endif
#ifndef _ASSET_FIELD_TYPES_H_
#include "assets/assetFieldTypes.h"
#endif
#ifndef _GFXDEVICE_H_
#include "gfx/gfxDevice.h"
#endif
#ifndef _GUI_INSPECTOR_TYPES_H_
#include "gui/editor/guiInspectorTypes.h"
#endif
#include "materials/matTextureTarget.h"
#include "materials/materialDefinition.h"
#include "materials/customMaterialDefinition.h"
//-----------------------------------------------------------------------------
class MaterialAsset : public AssetBase
{
typedef AssetBase Parent;
String mShaderGraphFile;
String mScriptFile;
String mMatDefinitionName;
public:
MaterialAsset();
virtual ~MaterialAsset();
/// Engine.
static void initPersistFields();
virtual void copyTo(SimObject* object);
virtual void initializeAsset();
virtual void onAssetRefresh(void);
void compileShader();
String getMaterialDefinitionName() { return mMatDefinitionName; }
/// Declare Console Object.
DECLARE_CONOBJECT(MaterialAsset);
};
DefineConsoleType(TypeMaterialAssetPtr, MaterialAsset)
//-----------------------------------------------------------------------------
// TypeAssetId GuiInspectorField Class
//-----------------------------------------------------------------------------
class GuiInspectorTypeMaterialAssetPtr : public GuiInspectorTypeFileName
{
typedef GuiInspectorTypeFileName Parent;
public:
GuiBitmapButtonCtrl *mSMEdButton;
DECLARE_CONOBJECT(GuiInspectorTypeMaterialAssetPtr);
static void consoleInit();
virtual GuiControl* constructEditControl();
virtual bool updateRects();
};
#endif // _ASSET_BASE_H_

View file

@ -0,0 +1,205 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef PARTICLE_ASSET_H
#include "ParticleAsset.h"
#endif
#ifndef _ASSET_MANAGER_H_
#include "assets/assetManager.h"
#endif
#ifndef _CONSOLETYPES_H_
#include "console/consoleTypes.h"
#endif
#ifndef _TAML_
#include "persistence/taml/taml.h"
#endif
#ifndef _ASSET_PTR_H_
#include "assets/assetPtr.h"
#endif
// Debug Profiling.
#include "platform/profiler.h"
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(ParticleAsset);
ConsoleType(ParticleAssetPtr, TypeParticleAssetPtr, ParticleAsset, ASSET_ID_FIELD_PREFIX)
//-----------------------------------------------------------------------------
ConsoleGetType(TypeParticleAssetPtr)
{
// Fetch asset Id.
return (*((AssetPtr<ParticleAsset>*)dptr)).getAssetId();
}
//-----------------------------------------------------------------------------
ConsoleSetType(TypeParticleAssetPtr)
{
// Was a single argument specified?
if (argc == 1)
{
// Yes, so fetch field value.
const char* pFieldValue = argv[0];
// Fetch asset pointer.
AssetPtr<ParticleAsset>* pAssetPtr = dynamic_cast<AssetPtr<ParticleAsset>*>((AssetPtrBase*)(dptr));
// Is the asset pointer the correct type?
if (pAssetPtr == NULL)
{
// No, so fail.
//Con::warnf("(TypeParticleAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
return;
}
// Set asset.
pAssetPtr->setAssetId(pFieldValue);
return;
}
// Warn.
Con::warnf("(TypeParticleAssetPtr) - Cannot set multiple args to a single asset.");
}
//-----------------------------------------------------------------------------
ParticleAsset::ParticleAsset()
{
mScriptFilePath = StringTable->EmptyString();
mDatablockFilePath = StringTable->EmptyString();
}
//-----------------------------------------------------------------------------
ParticleAsset::~ParticleAsset()
{
// If the asset manager does not own the asset then we own the
// asset definition so delete it.
if (!getOwned())
delete mpAssetDefinition;
}
//-----------------------------------------------------------------------------
void ParticleAsset::initPersistFields()
{
// Call parent.
Parent::initPersistFields();
addField("scriptFilePath", TypeString, Offset(mScriptFilePath, ParticleAsset), "Path to the script file for the particle effect");
addField("DatablockFilePath", TypeString, Offset(mDatablockFilePath, ParticleAsset), "Path to the datablock file");
}
//------------------------------------------------------------------------------
void ParticleAsset::copyTo(SimObject* object)
{
// Call to parent.
Parent::copyTo(object);
}
//-----------------------------------------------------------------------------
// GuiInspectorTypeAssetId
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(GuiInspectorTypeParticleAssetPtr);
ConsoleDocClass(GuiInspectorTypeParticleAssetPtr,
"@brief Inspector field type for Partial Asset Objects\n\n"
"Editor use only.\n\n"
"@internal"
);
void GuiInspectorTypeParticleAssetPtr::consoleInit()
{
Parent::consoleInit();
ConsoleBaseType::getType(TypeParticleAssetPtr)->setInspectorFieldType("GuiInspectorTypeParticleAssetPtr");
}
GuiControl* GuiInspectorTypeParticleAssetPtr::constructEditControl()
{
// Create base filename edit controls
GuiControl *retCtrl = Parent::constructEditControl();
if (retCtrl == NULL)
return retCtrl;
// Change filespec
char szBuffer[512];
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"ParticleAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
mInspector->getComponentGroupTargetId(), mCaption);
mBrowseButton->setField("Command", szBuffer);
// Create "Open in ShapeEditor" button
mSMEdButton = new GuiBitmapButtonCtrl();
dSprintf(szBuffer, sizeof(szBuffer), "echo(\"Game Object Editor not implemented yet!\");", retCtrl->getId());
mSMEdButton->setField("Command", szBuffer);
char bitmapName[512] = "tools/worldEditor/images/toolbar/shape-editor";
mSMEdButton->setBitmap(bitmapName);
mSMEdButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
mSMEdButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
mSMEdButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
mSMEdButton->setDataField(StringTable->insert("tooltip"), NULL, "Open this file in the State Machine Editor");
mSMEdButton->registerObject();
addObject(mSMEdButton);
return retCtrl;
}
bool GuiInspectorTypeParticleAssetPtr::updateRects()
{
S32 dividerPos, dividerMargin;
mInspector->getDivider(dividerPos, dividerMargin);
Point2I fieldExtent = getExtent();
Point2I fieldPos = getPosition();
mCaptionRect.set(0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y);
mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y);
bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
if (mBrowseButton != NULL)
{
mBrowseRect.set(fieldExtent.x - 32, 2, 14, fieldExtent.y - 4);
resized |= mBrowseButton->resize(mBrowseRect.point, mBrowseRect.extent);
}
if (mSMEdButton != NULL)
{
RectI shapeEdRect(fieldExtent.x - 16, 2, 14, fieldExtent.y - 4);
resized |= mSMEdButton->resize(shapeEdRect.point, shapeEdRect.extent);
}
return resized;
}

View file

@ -0,0 +1,89 @@
#pragma once
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef PARTICLE_ASSET_H
#define PARTICLE_ASSET_H
#ifndef _ASSET_BASE_H_
#include "assets/assetBase.h"
#endif
#ifndef _ASSET_DEFINITION_H_
#include "assets/assetDefinition.h"
#endif
#ifndef _STRINGUNIT_H_
#include "string/stringUnit.h"
#endif
#ifndef _ASSET_FIELD_TYPES_H_
#include "assets/assetFieldTypes.h"
#endif
#include "gui/editor/guiInspectorTypes.h"
//-----------------------------------------------------------------------------
class ParticleAsset : public AssetBase
{
typedef AssetBase Parent;
StringTableEntry mScriptFilePath;
StringTableEntry mDatablockFilePath;
public:
ParticleAsset();
virtual ~ParticleAsset();
/// Engine.
static void initPersistFields();
virtual void copyTo(SimObject* object);
/// Declare Console Object.
DECLARE_CONOBJECT(ParticleAsset);
protected:
virtual void initializeAsset(void) {}
virtual void onAssetRefresh(void) {}
};
DefineConsoleType(TypeParticleAssetPtr, ParticleAsset)
//-----------------------------------------------------------------------------
// TypeAssetId GuiInspectorField Class
//-----------------------------------------------------------------------------
class GuiInspectorTypeParticleAssetPtr : public GuiInspectorTypeFileName
{
typedef GuiInspectorTypeFileName Parent;
public:
GuiBitmapButtonCtrl *mSMEdButton;
DECLARE_CONOBJECT(GuiInspectorTypeParticleAssetPtr);
static void consoleInit();
virtual GuiControl* constructEditControl();
virtual bool updateRects();
};
#endif // _ASSET_BASE_H_

View file

@ -0,0 +1,129 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef POSTEFFECT_ASSET_H
#include "PostEffectAsset.h"
#endif
#ifndef _ASSET_MANAGER_H_
#include "assets/assetManager.h"
#endif
#ifndef _CONSOLETYPES_H_
#include "console/consoleTypes.h"
#endif
#ifndef _TAML_
#include "persistence/taml/taml.h"
#endif
#ifndef _ASSET_PTR_H_
#include "assets/assetPtr.h"
#endif
// Debug Profiling.
#include "platform/profiler.h"
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(PostEffectAsset);
ConsoleType(PostEffectAssetPtr, TypePostEffectAssetPtr, PostEffectAsset, ASSET_ID_FIELD_PREFIX)
//-----------------------------------------------------------------------------
ConsoleGetType(TypePostEffectAssetPtr)
{
// Fetch asset Id.
return (*((AssetPtr<PostEffectAsset>*)dptr)).getAssetId();
}
//-----------------------------------------------------------------------------
ConsoleSetType(TypePostEffectAssetPtr)
{
// Was a single argument specified?
if (argc == 1)
{
// Yes, so fetch field value.
const char* pFieldValue = argv[0];
// Fetch asset pointer.
AssetPtr<PostEffectAsset>* pAssetPtr = dynamic_cast<AssetPtr<PostEffectAsset>*>((AssetPtrBase*)(dptr));
// Is the asset pointer the correct type?
if (pAssetPtr == NULL)
{
// No, so fail.
//Con::warnf("(TypePostEffectAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
return;
}
// Set asset.
pAssetPtr->setAssetId(pFieldValue);
return;
}
// Warn.
Con::warnf("(TypePostEffectAssetPtr) - Cannot set multiple args to a single asset.");
}
//-----------------------------------------------------------------------------
PostEffectAsset::PostEffectAsset()
{
mScriptFile = StringTable->EmptyString();
}
//-----------------------------------------------------------------------------
PostEffectAsset::~PostEffectAsset()
{
// If the asset manager does not own the asset then we own the
// asset definition so delete it.
if (!getOwned())
delete mpAssetDefinition;
}
//-----------------------------------------------------------------------------
void PostEffectAsset::initPersistFields()
{
// Call parent.
Parent::initPersistFields();
addField("scriptFile", TypeString, Offset(mScriptFile, PostEffectAsset), "Path to the script file.");
}
//------------------------------------------------------------------------------
void PostEffectAsset::copyTo(SimObject* object)
{
// Call to parent.
Parent::copyTo(object);
}
void PostEffectAsset::initializeAsset()
{
//mPostEffect = new PostEffect();
}

View file

@ -0,0 +1,71 @@
#pragma once
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef POSTEFFECT_ASSET_H
#define POSTEFFECT_ASSET_H
#ifndef _ASSET_BASE_H_
#include "assets/assetBase.h"
#endif
#ifndef _ASSET_DEFINITION_H_
#include "assets/assetDefinition.h"
#endif
#ifndef _STRINGUNIT_H_
#include "string/stringUnit.h"
#endif
#ifndef _ASSET_FIELD_TYPES_H_
#include "assets/assetFieldTypes.h"
#endif
#include "postFx/postEffect.h"
//-----------------------------------------------------------------------------
class PostEffectAsset : public AssetBase
{
typedef AssetBase Parent;
StringTableEntry mScriptFile;
public:
PostEffectAsset();
virtual ~PostEffectAsset();
/// Engine.
static void initPersistFields();
virtual void copyTo(SimObject* object);
virtual void initializeAsset();
/// Declare Console Object.
DECLARE_CONOBJECT(PostEffectAsset);
protected:
virtual void onAssetRefresh(void) {}
};
DefineConsoleType(TypePostEffectAssetPtr, PostEffectAsset)
#endif // _ASSET_BASE_H_

View file

@ -0,0 +1,137 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef SCRIPT_ASSET_H
#include "ScriptAsset.h"
#endif
#ifndef _ASSET_MANAGER_H_
#include "assets/assetManager.h"
#endif
#ifndef _CONSOLETYPES_H_
#include "console/consoleTypes.h"
#endif
#ifndef _TAML_
#include "persistence/taml/taml.h"
#endif
#ifndef _ASSET_PTR_H_
#include "assets/assetPtr.h"
#endif
// Debug Profiling.
#include "platform/profiler.h"
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(ScriptAsset);
ConsoleType(ScriptAssetPtr, TypeScriptAssetPtr, ScriptAsset, ASSET_ID_FIELD_PREFIX)
//-----------------------------------------------------------------------------
ConsoleGetType(TypeScriptAssetPtr)
{
// Fetch asset Id.
return (*((AssetPtr<ScriptAsset>*)dptr)).getAssetId();
}
//-----------------------------------------------------------------------------
ConsoleSetType(TypeScriptAssetPtr)
{
// Was a single argument specified?
if (argc == 1)
{
// Yes, so fetch field value.
const char* pFieldValue = argv[0];
// Fetch asset pointer.
AssetPtr<ScriptAsset>* pAssetPtr = dynamic_cast<AssetPtr<ScriptAsset>*>((AssetPtrBase*)(dptr));
// Is the asset pointer the correct type?
if (pAssetPtr == NULL)
{
// No, so fail.
//Con::warnf("(TypeScriptAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
return;
}
// Set asset.
pAssetPtr->setAssetId(pFieldValue);
return;
}
// Warn.
Con::warnf("(TypeScriptAssetPtr) - Cannot set multiple args to a single asset.");
}
//-----------------------------------------------------------------------------
ScriptAsset::ScriptAsset()
{
mScriptFilePath = StringTable->EmptyString();
}
//-----------------------------------------------------------------------------
ScriptAsset::~ScriptAsset()
{
// If the asset manager does not own the asset then we own the
// asset definition so delete it.
if (!getOwned())
delete mpAssetDefinition;
}
//-----------------------------------------------------------------------------
void ScriptAsset::initPersistFields()
{
// Call parent.
Parent::initPersistFields();
addField("scriptFilePath", TypeString, Offset(mScriptFilePath, ScriptAsset), "Path to the script file.");
addField("isServerSide", TypeBool, Offset(mIsServerSide, ScriptAsset), "Is this script file to be run on the server side?");
}
//------------------------------------------------------------------------------
void ScriptAsset::copyTo(SimObject* object)
{
// Call to parent.
Parent::copyTo(object);
}
void ScriptAsset::initializeAsset()
{
if (Platform::isFile(mScriptFilePath))
Con::executeFile(mScriptFilePath, false, false);
}
void ScriptAsset::onAssetRefresh()
{
if (Platform::isFile(mScriptFilePath))
Con::executeFile(mScriptFilePath, false, false);
}

View file

@ -0,0 +1,69 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef SCRIPT_ASSET_H
#define SCRIPT_ASSET_H
#pragma once
#ifndef _ASSET_BASE_H_
#include "assets/assetBase.h"
#endif
#ifndef _ASSET_DEFINITION_H_
#include "assets/assetDefinition.h"
#endif
#ifndef _STRINGUNIT_H_
#include "string/stringUnit.h"
#endif
#ifndef _ASSET_FIELD_TYPES_H_
#include "assets/assetFieldTypes.h"
#endif
//-----------------------------------------------------------------------------
class ScriptAsset : public AssetBase
{
typedef AssetBase Parent;
StringTableEntry mScriptFilePath;
bool mIsServerSide;
public:
ScriptAsset();
virtual ~ScriptAsset();
/// Engine.
static void initPersistFields();
virtual void copyTo(SimObject* object);
/// Declare Console Object.
DECLARE_CONOBJECT(ScriptAsset);
protected:
virtual void initializeAsset(void);
virtual void onAssetRefresh(void);
};
DefineConsoleType(TypeScriptAssetPtr, ScriptAsset)
#endif // _ASSET_BASE_H_

View file

@ -0,0 +1,131 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef SHAPE_ANIMATION_ASSET_H
#include "ShapeAnimationAsset.h"
#endif
#ifndef _ASSET_MANAGER_H_
#include "assets/assetManager.h"
#endif
#ifndef _CONSOLETYPES_H_
#include "console/consoleTypes.h"
#endif
#ifndef _TAML_
#include "persistence/taml/taml.h"
#endif
#ifndef _ASSET_PTR_H_
#include "assets/assetPtr.h"
#endif
#include "core/resourceManager.h"
// Debug Profiling.
#include "platform/profiler.h"
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(ShapeAnimationAsset);
ConsoleType(ShapeAnimationAssetPtr, TypeShapeAnimationAssetPtr, ShapeAnimationAsset, ASSET_ID_FIELD_PREFIX)
//-----------------------------------------------------------------------------
ConsoleGetType(TypeShapeAnimationAssetPtr)
{
// Fetch asset Id.
return (*((AssetPtr<ShapeAnimationAsset>*)dptr)).getAssetId();
}
//-----------------------------------------------------------------------------
ConsoleSetType(TypeShapeAnimationAssetPtr)
{
// Was a single argument specified?
if (argc == 1)
{
// Yes, so fetch field value.
const char* pFieldValue = argv[0];
// Fetch asset pointer.
AssetPtr<ShapeAnimationAsset>* pAssetPtr = dynamic_cast<AssetPtr<ShapeAnimationAsset>*>((AssetPtrBase*)(dptr));
// Is the asset pointer the correct type?
if (pAssetPtr == NULL)
{
// No, so fail.
//Con::warnf("(TypeShapeAnimationAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
return;
}
// Set asset.
pAssetPtr->setAssetId(pFieldValue);
return;
}
// Warn.
Con::warnf("(TypeShapeAnimationAssetPtr) - Cannot set multiple args to a single asset.");
}
//-----------------------------------------------------------------------------
ShapeAnimationAsset::ShapeAnimationAsset()
{
}
//-----------------------------------------------------------------------------
ShapeAnimationAsset::~ShapeAnimationAsset()
{
// If the asset manager does not own the asset then we own the
// asset definition so delete it.
if (!getOwned())
delete mpAssetDefinition;
}
//-----------------------------------------------------------------------------
void ShapeAnimationAsset::initPersistFields()
{
// Call parent.
Parent::initPersistFields();
addField("animationFile", TypeFilename, Offset(mFileName, ShapeAnimationAsset), "Path to the file name containing the animation");
addField("animationName", TypeString, Offset(mAnimationName, ShapeAnimationAsset), "Name of the animation");
addField("startFrame", TypeS32, Offset(mStartFrame, ShapeAnimationAsset), "What frame does this animation clip start on");
addField("endFrame", TypeS32, Offset(mEndFrame, ShapeAnimationAsset), "What fram does this animation clip end on");
addField("padRotation", TypeBool, Offset(mPadRotation, ShapeAnimationAsset), "Are the rotation values padded");
addField("padTransforms", TypeBool, Offset(mPadTransforms, ShapeAnimationAsset), "Are the transform values padded");
}
//------------------------------------------------------------------------------
void ShapeAnimationAsset::copyTo(SimObject* object)
{
// Call to parent.
Parent::copyTo(object);
}

View file

@ -0,0 +1,102 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef SHAPE_ANIMATION_ASSET_H
#define SHAPE_ANIMATION_ASSET_H
#ifndef _ASSET_BASE_H_
#include "assets/assetBase.h"
#endif
#ifndef _ASSET_DEFINITION_H_
#include "assets/assetDefinition.h"
#endif
#ifndef _STRINGUNIT_H_
#include "string/stringUnit.h"
#endif
#ifndef _ASSET_FIELD_TYPES_H_
#include "assets/assetFieldTypes.h"
#endif
//-----------------------------------------------------------------------------
class ShapeAnimationAsset : public AssetBase
{
typedef AssetBase Parent;
protected:
StringTableEntry mFileName;
//
StringTableEntry mAnimationName;
S32 mStartFrame;
S32 mEndFrame;
bool mPadRotation;
bool mPadTransforms;
public:
ShapeAnimationAsset();
virtual ~ShapeAnimationAsset();
/// Engine.
static void initPersistFields();
virtual void copyTo(SimObject* object);
/// Declare Console Object.
DECLARE_CONOBJECT(ShapeAnimationAsset);
protected:
virtual void initializeAsset(void) {}
virtual void onAssetRefresh(void) {}
public:
StringTableEntry getAnimationFilename() { return mFileName; }
StringTableEntry getAnimationName() { return mAnimationName; }
S32 getStartFrame() { return mStartFrame; }
S32 getEndFrame() { return mEndFrame; }
bool getPadRotation() { return mPadRotation; }
bool getPadTransforms() { return mPadTransforms; }
};
DefineConsoleType(TypeShapeAnimationAssetPtr, ShapeAnimationAsset)
//-----------------------------------------------------------------------------
// TypeAssetId GuiInspectorField Class
//-----------------------------------------------------------------------------
/*class GuiInspectorTypeShapeAnimationAssetPtr : public GuiInspectorTypeFileName
{
typedef GuiInspectorTypeFileName Parent;
public:
GuiBitmapButtonCtrl *mShapeEdButton;
DECLARE_CONOBJECT(GuiInspectorTypeShapeAnimationAssetPtr);
static void consoleInit();
virtual GuiControl* constructEditControl();
virtual bool updateRects();
};*/
#endif // _ASSET_BASE_H_

View file

@ -49,14 +49,14 @@
IMPLEMENT_CONOBJECT(ShapeAsset);
ConsoleType(TestAssetPtr, TypeShapeAssetPtr, ShapeAsset, ASSET_ID_FIELD_PREFIX)
ConsoleType(assetIdString, TypeShapeAssetPtr, String, ASSET_ID_FIELD_PREFIX)
//-----------------------------------------------------------------------------
ConsoleGetType(TypeShapeAssetPtr)
{
// Fetch asset Id.
return (*((AssetPtr<ShapeAsset>*)dptr)).getAssetId();
return *((StringTableEntry*)dptr);
}
//-----------------------------------------------------------------------------
@ -69,33 +69,22 @@ ConsoleSetType(TypeShapeAssetPtr)
// Yes, so fetch field value.
const char* pFieldValue = argv[0];
// Fetch asset pointer.
AssetPtr<ShapeAsset>* pAssetPtr = dynamic_cast<AssetPtr<ShapeAsset>*>((AssetPtrBase*)(dptr));
// Fetch asset Id.
StringTableEntry* assetId = (StringTableEntry*)(dptr);
// Is the asset pointer the correct type?
if (pAssetPtr == NULL)
{
// No, so fail.
//Con::warnf("(TypeTextureAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
return;
}
// Set asset.
pAssetPtr->setAssetId(pFieldValue);
// Update asset value.
*assetId = StringTable->insert(pFieldValue);
return;
}
// Warn.
Con::warnf("(TypeTextureAssetPtr) - Cannot set multiple args to a single asset.");
Con::warnf("(TypeAssetId) - Cannot set multiple args to a single asset.");
}
//-----------------------------------------------------------------------------
ShapeAsset::ShapeAsset() :
mpOwningAssetManager(NULL),
mAssetInitialized(false),
mAcquireReferenceCount(0)
ShapeAsset::ShapeAsset()
{
}
@ -116,7 +105,21 @@ void ShapeAsset::initPersistFields()
// Call parent.
Parent::initPersistFields();
addField("fileName", TypeFilename, Offset(mFileName, ShapeAsset), "Path to the script file we want to execute");
addField("fileName", TypeFilename, Offset(mFileName, ShapeAsset), "Path to the shape file we want to render");
}
void ShapeAsset::setDataField(StringTableEntry slotName, const char *array, const char *value)
{
Parent::setDataField(slotName, array, value);
//Now, if it's a material slot of some fashion, set it up
StringTableEntry matSlotName = StringTable->insert("materialAsset");
if (String(slotName).startsWith(matSlotName))
{
StringTableEntry matId = StringTable->insert(value);
mMaterialAssetIds.push_back(matId);
}
}
void ShapeAsset::initializeAsset()
@ -132,6 +135,45 @@ void ShapeAsset::initializeAsset()
bool ShapeAsset::loadShape()
{
mMaterialAssets.clear();
mMaterialAssetIds.clear();
//First, load any material, animation, etc assets we may be referencing in our asset
// Find any asset dependencies.
AssetManager::typeAssetDependsOnHash::Iterator assetDependenciesItr = mpOwningAssetManager->getDependedOnAssets()->find(mpAssetDefinition->mAssetId);
// Does the asset have any dependencies?
if (assetDependenciesItr != mpOwningAssetManager->getDependedOnAssets()->end())
{
// Iterate all dependencies.
while (assetDependenciesItr != mpOwningAssetManager->getDependedOnAssets()->end() && assetDependenciesItr->key == mpAssetDefinition->mAssetId)
{
StringTableEntry assetType = mpOwningAssetManager->getAssetType(assetDependenciesItr->value);
if (assetType == StringTable->insert("MaterialAsset"))
{
mMaterialAssetIds.push_back(assetDependenciesItr->value);
//Force the asset to become initialized if it hasn't been already
AssetPtr<MaterialAsset> matAsset = assetDependenciesItr->value;
mMaterialAssets.push_back(matAsset);
}
else if (assetType == StringTable->insert("ShapeAnimationAsset"))
{
mAnimationAssetIds.push_back(assetDependenciesItr->value);
//Force the asset to become initialized if it hasn't been already
AssetPtr<ShapeAnimationAsset> animAsset = assetDependenciesItr->value;
mAnimationAssets.push_back(animAsset);
}
// Next dependency.
assetDependenciesItr++;
}
}
mShape = ResourceManager::get().load(mFileName);
if (!mShape)
@ -140,6 +182,19 @@ bool ShapeAsset::loadShape()
return false; //if it failed to load, bail out
}
//Now that we've successfully loaded our shape and have any materials and animations loaded
//we need to set up the animations we're using on our shape
for (U32 i = 0; i < mAnimationAssets.size(); i++)
{
String srcName;
String srcPath(mAnimationAssets[i]->getAnimationFilename());
SplitSequencePathAndName(srcPath, srcName);
if (!mShape->addSequence(srcPath, srcName, mAnimationAssets[i]->getAnimationName(),
mAnimationAssets[i]->getStartFrame(), mAnimationAssets[i]->getEndFrame(), mAnimationAssets[i]->getPadRotation(), mAnimationAssets[i]->getPadTransforms()))
return false;
}
return true;
}
@ -153,4 +208,141 @@ void ShapeAsset::copyTo(SimObject* object)
void ShapeAsset::onAssetRefresh(void)
{
if (dStrcmp(mFileName, "") == 0)
return;
loadShape();
}
void ShapeAsset::SplitSequencePathAndName(String& srcPath, String& srcName)
{
srcName = "";
// Determine if there is a sequence name at the end of the source string, and
// if so, split the filename from the sequence name
S32 split = srcPath.find(' ', 0, String::Right);
S32 split2 = srcPath.find('\t', 0, String::Right);
if ((split == String::NPos) || (split2 > split))
split = split2;
if (split != String::NPos)
{
split2 = split + 1;
while ((srcPath[split2] != '\0') && dIsspace(srcPath[split2]))
split2++;
// now 'split' is at the end of the path, and 'split2' is at the start of the sequence name
srcName = srcPath.substr(split2);
srcPath = srcPath.erase(split, srcPath.length() - split);
}
}
ShapeAnimationAsset* ShapeAsset::getAnimation(S32 index)
{
if (index < mAnimationAssets.size())
{
return mAnimationAssets[index];
}
return nullptr;
}
DefineEngineMethod(ShapeAsset, getMaterialCount, S32, (), ,
"Gets the number of materials for this shape asset.\n"
"@return Material count.\n")
{
return object->getMaterialCount();
}
DefineEngineMethod(ShapeAsset, getAnimationCount, S32, (), ,
"Gets the number of animations for this shape asset.\n"
"@return Animation count.\n")
{
return object->getAnimationCount();
}
DefineEngineMethod(ShapeAsset, getAnimation, ShapeAnimationAsset*, (S32 index), (0),
"Gets a particular shape animation asset for this shape.\n"
"@param animation asset index.\n"
"@return Shape Animation Asset.\n")
{
return object->getAnimation(index);
}
//-----------------------------------------------------------------------------
// GuiInspectorTypeAssetId
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(GuiInspectorTypeShapeAssetPtr);
ConsoleDocClass(GuiInspectorTypeShapeAssetPtr,
"@brief Inspector field type for Shapes\n\n"
"Editor use only.\n\n"
"@internal"
);
void GuiInspectorTypeShapeAssetPtr::consoleInit()
{
Parent::consoleInit();
ConsoleBaseType::getType(TypeShapeAssetPtr)->setInspectorFieldType("GuiInspectorTypeShapeAssetPtr");
}
GuiControl* GuiInspectorTypeShapeAssetPtr::constructEditControl()
{
// Create base filename edit controls
GuiControl *retCtrl = Parent::constructEditControl();
if (retCtrl == NULL)
return retCtrl;
// Change filespec
char szBuffer[512];
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"ShapeAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
mInspector->getComponentGroupTargetId(), mCaption);
mBrowseButton->setField("Command", szBuffer);
setDataField(StringTable->insert("ComponentOwner"), NULL, String::ToString(mInspector->getComponentGroupTargetId()).c_str());
// Create "Open in ShapeEditor" button
mShapeEdButton = new GuiBitmapButtonCtrl();
dSprintf(szBuffer, sizeof(szBuffer), "ShapeEditorPlugin.openShapeAsset(%d.getText());", retCtrl->getId());
mShapeEdButton->setField("Command", szBuffer);
char bitmapName[512] = "tools/worldEditor/images/toolbar/shape-editor";
mShapeEdButton->setBitmap(bitmapName);
mShapeEdButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
mShapeEdButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
mShapeEdButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
mShapeEdButton->setDataField(StringTable->insert("tooltip"), NULL, "Open this file in the Shape Editor");
mShapeEdButton->registerObject();
addObject(mShapeEdButton);
return retCtrl;
}
bool GuiInspectorTypeShapeAssetPtr::updateRects()
{
S32 dividerPos, dividerMargin;
mInspector->getDivider(dividerPos, dividerMargin);
Point2I fieldExtent = getExtent();
Point2I fieldPos = getPosition();
mCaptionRect.set(0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y);
mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y);
bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
if (mBrowseButton != NULL)
{
mBrowseRect.set(fieldExtent.x - 32, 2, 14, fieldExtent.y - 4);
resized |= mBrowseButton->resize(mBrowseRect.point, mBrowseRect.extent);
}
if (mShapeEdButton != NULL)
{
RectI shapeEdRect(fieldExtent.x - 16, 2, 14, fieldExtent.y - 4);
resized |= mShapeEdButton->resize(shapeEdRect.point, shapeEdRect.extent);
}
return resized;
}

View file

@ -44,21 +44,35 @@
#ifndef __RESOURCE_H__
#include "core/resource.h"
#endif
#ifndef _ASSET_PTR_H_
#include "assets/assetPtr.h"
#endif
#ifndef MATERIALASSET_H
#include "MaterialAsset.h"
#endif
#ifndef SHAPE_ANIMATION_ASSET_H
#include "ShapeAnimationAsset.h"
#endif
#include "gui/editor/guiInspectorTypes.h"
//-----------------------------------------------------------------------------
class ShapeAsset : public AssetBase
{
typedef AssetBase Parent;
AssetManager* mpOwningAssetManager;
bool mAssetInitialized;
AssetDefinition* mpAssetDefinition;
U32 mAcquireReferenceCount;
protected:
StringTableEntry mFileName;
Resource<TSShape> mShape;
//Material assets we're dependent on and use
Vector<StringTableEntry> mMaterialAssetIds;
Vector<AssetPtr<MaterialAsset>> mMaterialAssets;
//Animation assets we're dependent on and use
Vector<StringTableEntry> mAnimationAssetIds;
Vector<AssetPtr<ShapeAnimationAsset>> mAnimationAssets;
public:
ShapeAsset();
virtual ~ShapeAsset();
@ -67,6 +81,8 @@ public:
static void initPersistFields();
virtual void copyTo(SimObject* object);
virtual void setDataField(StringTableEntry slotName, const char *array, const char *value);
virtual void initializeAsset();
/// Declare Console Object.
@ -78,11 +94,37 @@ public:
Resource<TSShape> getShapeResource() { return mShape; }
void SplitSequencePathAndName(String& srcPath, String& srcName);
String getShapeFilename() { return mFileName; }
U32 getShapeFilenameHash() { return _StringTable::hashString(mFileName); }
S32 getMaterialCount() { return mMaterialAssets.size(); }
S32 getAnimationCount() { return mAnimationAssets.size(); }
ShapeAnimationAsset* getAnimation(S32 index);
protected:
virtual void onAssetRefresh(void);
};
DefineConsoleType(TypeShapeAssetPtr, ShapeAsset)
DefineConsoleType(TypeShapeAssetPtr, S32)
//-----------------------------------------------------------------------------
// TypeAssetId GuiInspectorField Class
//-----------------------------------------------------------------------------
class GuiInspectorTypeShapeAssetPtr : public GuiInspectorTypeFileName
{
typedef GuiInspectorTypeFileName Parent;
public:
GuiBitmapButtonCtrl *mShapeEdButton;
DECLARE_CONOBJECT(GuiInspectorTypeShapeAssetPtr);
static void consoleInit();
virtual GuiControl* constructEditControl();
virtual bool updateRects();
};
#endif

View file

@ -0,0 +1,141 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef SOUND_ASSET_H
#include "SoundAsset.h"
#endif
#ifndef _ASSET_MANAGER_H_
#include "assets/assetManager.h"
#endif
#ifndef _CONSOLETYPES_H_
#include "console/consoleTypes.h"
#endif
#ifndef _TAML_
#include "persistence/taml/taml.h"
#endif
#ifndef _ASSET_PTR_H_
#include "assets/assetPtr.h"
#endif
// Debug Profiling.
#include "platform/profiler.h"
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(SoundAsset);
ConsoleType(SoundAssetPtr, TypeSoundAssetPtr, SoundAsset, ASSET_ID_FIELD_PREFIX)
//-----------------------------------------------------------------------------
ConsoleGetType(TypeSoundAssetPtr)
{
// Fetch asset Id.
return (*((AssetPtr<SoundAsset>*)dptr)).getAssetId();
}
//-----------------------------------------------------------------------------
ConsoleSetType(TypeSoundAssetPtr)
{
// Was a single argument specified?
if (argc == 1)
{
// Yes, so fetch field value.
const char* pFieldValue = argv[0];
// Fetch asset pointer.
AssetPtr<SoundAsset>* pAssetPtr = dynamic_cast<AssetPtr<SoundAsset>*>((AssetPtrBase*)(dptr));
// Is the asset pointer the correct type?
if (pAssetPtr == NULL)
{
// No, so fail.
//Con::warnf("(TypeSoundAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
return;
}
// Set asset.
pAssetPtr->setAssetId(pFieldValue);
return;
}
// Warn.
Con::warnf("(TypeSoundAssetPtr) - Cannot set multiple args to a single asset.");
}
//-----------------------------------------------------------------------------
SoundAsset::SoundAsset()
{
mSoundFilePath = StringTable->EmptyString();
mPitchAdjust = 0;
mVolumeAdjust = 0;
//mSound = nullptr;
}
//-----------------------------------------------------------------------------
SoundAsset::~SoundAsset()
{
// If the asset manager does not own the asset then we own the
// asset definition so delete it.
if (!getOwned())
delete mpAssetDefinition;
}
//-----------------------------------------------------------------------------
void SoundAsset::initPersistFields()
{
// Call parent.
Parent::initPersistFields();
addField("soundFilePath", TypeFilename, Offset(mSoundFilePath, SoundAsset), "Path to the sound file.");
addField("pitchAdjust", TypeF32, Offset(mPitchAdjust, SoundAsset), "Adjustment of the pitch value");
addField("volumeAdjust", TypeF32, Offset(mVolumeAdjust, SoundAsset), "Adjustment to the volume.");
}
//------------------------------------------------------------------------------
void SoundAsset::copyTo(SimObject* object)
{
// Call to parent.
Parent::copyTo(object);
}
void SoundAsset::initializeAsset(void)
{
}
void SoundAsset::onAssetRefresh(void)
{
}

View file

@ -0,0 +1,75 @@
#pragma once
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef SOUND_ASSET_H
#define SOUND_ASSET_H
#ifndef _ASSET_BASE_H_
#include "assets/assetBase.h"
#endif
#ifndef _ASSET_DEFINITION_H_
#include "assets/assetDefinition.h"
#endif
#ifndef _STRINGUNIT_H_
#include "string/stringUnit.h"
#endif
#ifndef _ASSET_FIELD_TYPES_H_
#include "assets/assetFieldTypes.h"
#endif
class SFXTrack;
//-----------------------------------------------------------------------------
class SoundAsset : public AssetBase
{
typedef AssetBase Parent;
protected:
StringTableEntry mSoundFilePath;
F32 mPitchAdjust;
F32 mVolumeAdjust;
public:
SoundAsset();
virtual ~SoundAsset();
/// Engine.
static void initPersistFields();
virtual void copyTo(SimObject* object);
/// Declare Console Object.
DECLARE_CONOBJECT(SoundAsset);
StringTableEntry getSoundFilePath() { return mSoundFilePath; }
protected:
virtual void initializeAsset(void);
virtual void onAssetRefresh(void);
};
DefineConsoleType(TypeSoundAssetPtr, SoundAsset)
#endif // _ASSET_BASE_H_

View file

@ -0,0 +1,207 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef STATE_MACHINE_ASSET_H
#include "stateMachineAsset.h"
#endif
#ifndef _ASSET_MANAGER_H_
#include "assets/assetManager.h"
#endif
#ifndef _CONSOLETYPES_H_
#include "console/consoleTypes.h"
#endif
#ifndef _TAML_
#include "persistence/taml/taml.h"
#endif
#ifndef _ASSET_PTR_H_
#include "assets/assetPtr.h"
#endif
// Debug Profiling.
#include "platform/profiler.h"
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(StateMachineAsset);
ConsoleType(StateMachineAssetPtr, TypeStateMachineAssetPtr, StateMachineAsset, ASSET_ID_FIELD_PREFIX)
//-----------------------------------------------------------------------------
ConsoleGetType(TypeStateMachineAssetPtr)
{
// Fetch asset Id.
return (*((AssetPtr<StateMachineAsset>*)dptr)).getAssetId();
}
//-----------------------------------------------------------------------------
ConsoleSetType(TypeStateMachineAssetPtr)
{
// Was a single argument specified?
if (argc == 1)
{
// Yes, so fetch field value.
const char* pFieldValue = argv[0];
// Fetch asset pointer.
AssetPtr<StateMachineAsset>* pAssetPtr = dynamic_cast<AssetPtr<StateMachineAsset>*>((AssetPtrBase*)(dptr));
// Is the asset pointer the correct type?
if (pAssetPtr == NULL)
{
// No, so fail.
//Con::warnf("(TypeStateMachineAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
return;
}
// Set asset.
pAssetPtr->setAssetId(pFieldValue);
return;
}
// Warn.
Con::warnf("(TypeStateMachineAssetPtr) - Cannot set multiple args to a single asset.");
}
//-----------------------------------------------------------------------------
StateMachineAsset::StateMachineAsset()
{
mStateMachineFileName = StringTable->EmptyString();
}
//-----------------------------------------------------------------------------
StateMachineAsset::~StateMachineAsset()
{
// If the asset manager does not own the asset then we own the
// asset definition so delete it.
if (!getOwned())
delete mpAssetDefinition;
}
//-----------------------------------------------------------------------------
void StateMachineAsset::initPersistFields()
{
// Call parent.
Parent::initPersistFields();
addField("stateMachineFile", TypeString, Offset(mStateMachineFileName, StateMachineAsset), "Path to the state machine file.");
}
//------------------------------------------------------------------------------
void StateMachineAsset::copyTo(SimObject* object)
{
// Call to parent.
Parent::copyTo(object);
}
DefineEngineMethod(StateMachineAsset, notifyAssetChanged, void, (),,"")
{
ResourceManager::get().getChangedSignal().trigger(object->getStateMachineFileName());
}
//-----------------------------------------------------------------------------
// GuiInspectorTypeAssetId
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(GuiInspectorTypeStateMachineAssetPtr);
ConsoleDocClass(GuiInspectorTypeStateMachineAssetPtr,
"@brief Inspector field type for State Machines\n\n"
"Editor use only.\n\n"
"@internal"
);
void GuiInspectorTypeStateMachineAssetPtr::consoleInit()
{
Parent::consoleInit();
ConsoleBaseType::getType(TypeStateMachineAssetPtr)->setInspectorFieldType("GuiInspectorTypeStateMachineAssetPtr");
}
GuiControl* GuiInspectorTypeStateMachineAssetPtr::constructEditControl()
{
// Create base filename edit controls
GuiControl *retCtrl = Parent::constructEditControl();
if (retCtrl == NULL)
return retCtrl;
// Change filespec
char szBuffer[512];
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"StateMachineAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
mInspector->getComponentGroupTargetId(), mCaption);
mBrowseButton->setField("Command", szBuffer);
// Create "Open in ShapeEditor" button
mSMEdButton = new GuiBitmapButtonCtrl();
dSprintf(szBuffer, sizeof(szBuffer), "StateMachineEditor.loadStateMachineAsset(%d.getText()); Canvas.pushDialog(StateMachineEditor);", retCtrl->getId());
mSMEdButton->setField("Command", szBuffer);
char bitmapName[512] = "tools/worldEditor/images/toolbar/shape-editor";
mSMEdButton->setBitmap(bitmapName);
mSMEdButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
mSMEdButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
mSMEdButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
mSMEdButton->setDataField(StringTable->insert("tooltip"), NULL, "Open this file in the State Machine Editor");
mSMEdButton->registerObject();
addObject(mSMEdButton);
return retCtrl;
}
bool GuiInspectorTypeStateMachineAssetPtr::updateRects()
{
S32 dividerPos, dividerMargin;
mInspector->getDivider(dividerPos, dividerMargin);
Point2I fieldExtent = getExtent();
Point2I fieldPos = getPosition();
mCaptionRect.set(0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y);
mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y);
bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
if (mBrowseButton != NULL)
{
mBrowseRect.set(fieldExtent.x - 32, 2, 14, fieldExtent.y - 4);
resized |= mBrowseButton->resize(mBrowseRect.point, mBrowseRect.extent);
}
if (mSMEdButton != NULL)
{
RectI shapeEdRect(fieldExtent.x - 16, 2, 14, fieldExtent.y - 4);
resized |= mSMEdButton->resize(shapeEdRect.point, shapeEdRect.extent);
}
return resized;
}

View file

@ -0,0 +1,89 @@
#pragma once
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef STATE_MACHINE_ASSET_H
#define STATE_MACHINE_ASSET_H
#ifndef _ASSET_BASE_H_
#include "assets/assetBase.h"
#endif
#ifndef _ASSET_DEFINITION_H_
#include "assets/assetDefinition.h"
#endif
#ifndef _STRINGUNIT_H_
#include "string/stringUnit.h"
#endif
#ifndef _ASSET_FIELD_TYPES_H_
#include "assets/assetFieldTypes.h"
#endif
#include "gui/editor/guiInspectorTypes.h"
//-----------------------------------------------------------------------------
class StateMachineAsset : public AssetBase
{
typedef AssetBase Parent;
StringTableEntry mStateMachineFileName;
public:
StateMachineAsset();
virtual ~StateMachineAsset();
/// Engine.
static void initPersistFields();
virtual void copyTo(SimObject* object);
/// Declare Console Object.
DECLARE_CONOBJECT(StateMachineAsset);
StringTableEntry getStateMachineFileName() { return mStateMachineFileName; }
protected:
virtual void initializeAsset(void) {}
virtual void onAssetRefresh(void) {}
};
DefineConsoleType(TypeStateMachineAssetPtr, StateMachineAsset)
//-----------------------------------------------------------------------------
// TypeAssetId GuiInspectorField Class
//-----------------------------------------------------------------------------
class GuiInspectorTypeStateMachineAssetPtr : public GuiInspectorTypeFileName
{
typedef GuiInspectorTypeFileName Parent;
public:
GuiBitmapButtonCtrl *mSMEdButton;
DECLARE_CONOBJECT(GuiInspectorTypeStateMachineAssetPtr);
static void consoleInit();
virtual GuiControl* constructEditControl();
virtual bool updateRects();
};
#endif

View file

@ -72,7 +72,6 @@ IMPLEMENT_CALLBACK(AnimationComponent, onAnimationTrigger, void, (Component* obj
AnimationComponent::AnimationComponent() : Component()
{
mNetworked = true;
mNetFlags.set(Ghostable | ScopeAlways);
mFriendlyName = "Animation(Component)";
mComponentType = "Render";
@ -223,31 +222,19 @@ U32 AnimationComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stre
{
U32 retMask = Parent::packUpdate(con, mask, stream);
//early test if we lack an owner, ghost-wise
//no point in trying, just re-queue the mask and go
if (!mOwner || con->getGhostIndex(mOwner) == -1)
/*for (int i = 0; i < MaxScriptThreads; i++)
{
stream->writeFlag(false);
return retMask |= ThreadMask;
}
else
{
stream->writeFlag(true);
for (int i = 0; i < MaxScriptThreads; i++)
Thread& st = mAnimationThreads[i];
if (stream->writeFlag((st.sequence != -1 || st.state == Thread::Destroy) && (mask & (ThreadMaskN << i))))
{
Thread& st = mAnimationThreads[i];
if (stream->writeFlag( (st.sequence != -1 || st.state == Thread::Destroy) && (mask & (ThreadMaskN << i)) ) )
{
stream->writeInt(st.sequence,ThreadSequenceBits);
stream->writeInt(st.state,2);
stream->write(st.timescale);
stream->write(st.position);
stream->writeFlag(st.atEnd);
stream->writeFlag(st.transition);
}
stream->writeInt(st.sequence, ThreadSequenceBits);
stream->writeInt(st.state, 2);
stream->write(st.timescale);
stream->write(st.position);
stream->writeFlag(st.atEnd);
stream->writeFlag(st.transition);
}
}
}*/
return retMask;
}
@ -256,29 +243,26 @@ void AnimationComponent::unpackUpdate(NetConnection *con, BitStream *stream)
{
Parent::unpackUpdate(con, stream);
if (stream->readFlag())
/*for (S32 i = 0; i < MaxScriptThreads; i++)
{
for (S32 i = 0; i < MaxScriptThreads; i++)
if (stream->readFlag())
{
if (stream->readFlag())
{
Thread& st = mAnimationThreads[i];
U32 seq = stream->readInt(ThreadSequenceBits);
st.state = stream->readInt(2);
stream->read( &st.timescale );
stream->read( &st.position );
st.atEnd = stream->readFlag();
bool transition = stream->readFlag();
Thread& st = mAnimationThreads[i];
U32 seq = stream->readInt(ThreadSequenceBits);
st.state = stream->readInt(2);
stream->read( &st.timescale );
stream->read( &st.position );
st.atEnd = stream->readFlag();
bool transition = stream->readFlag();
if (!st.thread || st.sequence != seq && st.state != Thread::Destroy)
setThreadSequence(i, seq, false, transition);
else
updateThread(st);
}
if (!st.thread || st.sequence != seq && st.state != Thread::Destroy)
setThreadSequence(i, seq, false, transition);
else
updateThread(st);
}
}
}*/
}
void AnimationComponent::processTick()
{
Parent::processTick();
@ -327,9 +311,6 @@ const char *AnimationComponent::getThreadSequenceName(U32 slot)
bool AnimationComponent::setThreadSequence(U32 slot, S32 seq, bool reset, bool transition, F32 transTime)
{
if (!mOwnerShapeInstance)
return false;
Thread& st = mAnimationThreads[slot];
if (st.thread && st.sequence == seq && st.state == Thread::Play && !reset)
return true;
@ -340,7 +321,6 @@ bool AnimationComponent::setThreadSequence(U32 slot, S32 seq, bool reset, bool t
if (seq < MaxSequenceIndex)
{
setMaskBits(-1);
setMaskBits(ThreadMaskN << slot);
st.sequence = seq;
st.transition = transition;
@ -647,7 +627,7 @@ void AnimationComponent::advanceThreads(F32 dt)
st.atEnd = true;
updateThread(st);
if (!isGhost())
if (!isClientObject())
{
Con::executef(this, "onAnimationEnd", st.thread->getSequenceName());
}
@ -660,7 +640,7 @@ void AnimationComponent::advanceThreads(F32 dt)
mOwnerShapeInstance->advanceTime(dt, st.thread);
}
if (mOwnerShapeInstance && !isGhost())
if (mOwnerShapeInstance && !isClientObject())
{
for (U32 i = 1; i < 32; i++)
{
@ -672,8 +652,16 @@ void AnimationComponent::advanceThreads(F32 dt)
}
}
if (isGhost())
if (isClientObject())
{
mOwnerShapeInstance->animate();
/*mOwnerShapeInstance->animateGround();
MatrixF groundTransform = mOwnerShapeInstance->getGroundTransform();
if (groundTransform != MatrixF::Identity)
{
mOwner->setPosition(groundTransform.getPosition());
}*/
}
}
}
}

View file

@ -0,0 +1,422 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "T3D/components/audio/SoundComponent.h"
#include "core/stream/bitStream.h"
#include "sim/netConnection.h"
#include "sfx/sfxSystem.h"
#include "sfx/sfxSource.h"
#include "sfx/sfxTrack.h"
#include "sfx/sfxDescription.h"
#include "T3D/sfx/sfx3DWorld.h"
#include "sfx/sfxTrack.h"
#include "sfx/sfxTypes.h"
#include "renderInstance/renderPassManager.h"
#include "gfx/gfxDrawUtil.h"
// Timeout for non-looping sounds on a channel
static SimTime sAudioTimeout = 500;
extern bool gEditingMission;
//////////////////////////////////////////////////////////////////////////
// Constructor/Destructor
//////////////////////////////////////////////////////////////////////////
SoundComponent::SoundComponent() : Component()
{
//These flags inform that, in this particular component, we network down to the client, which enables the pack/unpackData functions to operate
mNetworked = true;
mFriendlyName = "Sound(Component)";
mComponentType = "Sound";
mDescription = getDescriptionText("Stores up to 4 sounds for playback.");
for (U32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++) {
mSoundThread[slotNum].play = false;
mSoundThread[slotNum].profile = 0;
mSoundThread[slotNum].sound = 0;
mSoundFile[slotNum] = NULL;
mPreviewSound[slotNum] = false;
mPlay[slotNum] = false;
}
}
SoundComponent::~SoundComponent()
{
}
IMPLEMENT_CO_NETOBJECT_V1(SoundComponent);
//Standard onAdd function, for when the component is created
bool SoundComponent::onAdd()
{
if (!Parent::onAdd())
return false;
for (U32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
mPreviewSound[slotNum] = false;
return true;
}
//Standard onRemove function, when the component object is deleted
void SoundComponent::onRemove()
{
Parent::onRemove();
}
//This is called when the component has been added to an entity
void SoundComponent::onComponentAdd()
{
Parent::onComponentAdd();
Con::printf("We were added to an entity! SoundComponent reporting in for owner entity %i", mOwner->getId());
}
//This is called when the component has been removed from an entity
void SoundComponent::onComponentRemove()
{
Con::printf("We were removed from our entity! SoundComponent signing off for owner entity %i", mOwner->getId());
Parent::onComponentRemove();
}
//This is called any time a component is added to an entity. Every component currently owned by the entity is informed of the event.
//This allows you to do dependency behavior, like collisions being aware of a mesh component, etc
void SoundComponent::componentAddedToOwner(Component *comp)
{
for (S32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
{
if (mPlay[slotNum])
{
playAudio(slotNum, mSoundFile[slotNum]);
}
}
Con::printf("Our owner entity has a new component being added! SoundComponent welcomes component %i of type %s", comp->getId(), comp->getClassRep()->getNameSpace());
}
//This is called any time a component is removed from an entity. Every component current owned by the entity is informed of the event.
//This allows cleanup and dependency management.
void SoundComponent::componentRemovedFromOwner(Component *comp)
{
Con::printf("Our owner entity has a removed a component! SoundComponent waves farewell to component %i of type %s", comp->getId(), comp->getClassRep()->getNameSpace());
}
//Regular init persist fields function to set up static fields.
void SoundComponent::initPersistFields()
{
//addArray("Sounds", MaxSoundThreads);
addField("mSoundFile", TypeSFXTrackName, Offset(mSoundFile, SoundComponent), MaxSoundThreads, "If the text will not fit in the control, the deniedSound is played.");
addProtectedField("mPreviewSound", TypeBool, Offset(mPreviewSound, SoundComponent),
&_previewSound, &defaultProtectedGetFn, MaxSoundThreads, "Preview Sound", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
addProtectedField("play", TypeBool, Offset(mPlay, SoundComponent),
&_autoplay, &defaultProtectedGetFn, MaxSoundThreads, "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.");
//endArray("Sounds");
Parent::initPersistFields();
}
bool SoundComponent::_previewSound(void *object, const char *index, const char *data)
{
U32 slotNum = (index != NULL) ? dAtoui(index) : 0;
SoundComponent* component = reinterpret_cast< SoundComponent* >(object);
if (!component->mPreviewSound[slotNum])
component->playAudio(slotNum, component->mSoundFile[slotNum]);
else
component->stopAudio(slotNum);
component->mPreviewSound[slotNum] = !component->mPreviewSound[slotNum];
return false;
}
bool SoundComponent::_autoplay(void *object, const char *index, const char *data)
{
U32 slotNum = (index != NULL) ? dAtoui(index) : 0;
SoundComponent* component = reinterpret_cast< SoundComponent* >(object);
component->mPlay[slotNum] = dAtoui(data);
if (component->mPlay[slotNum])
component->playAudio(slotNum, component->mSoundFile[slotNum]);
else
component->stopAudio(slotNum);
return false;
}
U32 SoundComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
{
U32 retMask = Parent::packUpdate(con, mask, stream);
if (mask & InitialUpdateMask)
{
// mask off sounds that aren't playing
S32 slotNum;
for (slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
if (!mSoundThread[slotNum].play)
mask &= ~(SoundMaskN << slotNum);
}
for (S32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
stream->writeFlag(mPreviewSound[slotNum]);
if (stream->writeFlag(mask & SoundMask))
{
for (S32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
{
Sound& st = mSoundThread[slotNum];
if (stream->writeFlag(mask & (SoundMaskN << slotNum)))
{
if (stream->writeFlag(st.play))
//stream->writeRangedU32(st.profile->getId(), DataBlockObjectIdFirst,
// DataBlockObjectIdLast);
stream->writeString(st.profile->getName());
}
}
}
return retMask;
}
void SoundComponent::unpackUpdate(NetConnection *con, BitStream *stream)
{
Parent::unpackUpdate(con, stream);
for (S32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
mPreviewSound[slotNum] = stream->readFlag();
if (stream->readFlag())
{
for (S32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
{
if (stream->readFlag())
{
Sound& st = mSoundThread[slotNum];
st.play = stream->readFlag();
if (st.play)
{
//st.profile = (SFXTrack*)stream->readRangedU32(DataBlockObjectIdFirst,
// DataBlockObjectIdLast);
char profileName[255];
stream->readString(profileName);
if (!Sim::findObject(profileName, st.profile))
Con::errorf("Could not find SFXTrack");
}
//if (isProperlyAdded())
updateAudioState(st);
}
}
}
}
//This allows custom behavior in the event the owner is being edited
void SoundComponent::onInspect()
{
}
//This allows cleanup of the custom editor behavior if our owner stopped being edited
void SoundComponent::onEndInspect()
{
}
//Process tick update function, natch
void SoundComponent::processTick()
{
Parent::processTick();
}
//Client-side advance function
void SoundComponent::advanceTime(F32 dt)
{
}
//Client-side interpolation function
void SoundComponent::interpolateTick(F32 delta)
{
}
void SoundComponent::prepRenderImage(SceneRenderState *state)
{
if (!mEnabled || !mOwner || !gEditingMission)
return;
ObjectRenderInst* ri = state->getRenderPass()->allocInst< ObjectRenderInst >();
ri->renderDelegate.bind(this, &SoundComponent::_renderObject);
ri->type = RenderPassManager::RIT_Editor;
ri->defaultKey = 0;
ri->defaultKey2 = 0;
state->getRenderPass()->addInst(ri);
}
void SoundComponent::_renderObject(ObjectRenderInst *ri,
SceneRenderState *state,
BaseMatInstance *overrideMat)
{
if (overrideMat)
return;
GFXStateBlockDesc desc;
desc.setBlend(true);
MatrixF camera = GFX->getWorldMatrix();
camera.inverse();
Point3F pos = mOwner->getPosition();
for (S32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
{
if (mPreviewSound[slotNum])
{
Sound& st = mSoundThread[slotNum];
if (st.sound && st.sound->getDescription())
{
F32 minRad = st.sound->getDescription()->mMinDistance;
F32 falloffRad = st.sound->getDescription()->mMaxDistance;
SphereF sphere(pos, falloffRad);
if (sphere.isContained(camera.getPosition()))
desc.setCullMode(GFXCullNone);
GFX->getDrawUtil()->drawSphere(desc, minRad, pos, ColorI(255, 0, 255, 64));
GFX->getDrawUtil()->drawSphere(desc, falloffRad, pos, ColorI(128, 0, 128, 64));
}
}
}
}
void SoundComponent::playAudio(U32 slotNum, SFXTrack* _profile)
{
AssertFatal(slotNum < MaxSoundThreads, "ShapeBase::playAudio() bad slot index");
SFXTrack* profile = (_profile != NULL) ? _profile : mSoundFile[slotNum];
Sound& st = mSoundThread[slotNum];
if (profile && (!st.play || st.profile != profile))
{
setMaskBits(SoundMaskN << slotNum);
st.play = true;
st.profile = profile;
updateAudioState(st);
}
}
void SoundComponent::stopAudio(U32 slotNum)
{
AssertFatal(slotNum < MaxSoundThreads, "ShapeBase::stopAudio() bad slot index");
Sound& st = mSoundThread[slotNum];
if (st.play)
{
st.play = false;
setMaskBits(SoundMaskN << slotNum);
updateAudioState(st);
}
}
void SoundComponent::updateServerAudio()
{
// Timeout non-looping sounds
for (S32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
{
Sound& st = mSoundThread[slotNum];
if (st.play && st.timeout && st.timeout < Sim::getCurrentTime())
{
//clearMaskBits(SoundMaskN << slotNum);
st.play = false;
}
}
}
void SoundComponent::updateAudioState(Sound& st)
{
SFX_DELETE(st.sound);
if (st.play && st.profile)
{
if (isClientObject())
{
//if (Sim::findObject(SimObjectId((uintptr_t)st.profile), st.profile))
// {
MatrixF transform = mOwner->getTransform();
st.sound = SFX->createSource(st.profile, &transform);
if (st.sound)
st.sound->play();
//}
else
st.play = false;
}
else
{
// Non-looping sounds timeout on the server
st.timeout = 0;
if (!st.profile->getDescription()->mIsLooping)
st.timeout = Sim::getCurrentTime() + sAudioTimeout;
}
}
else
st.play = false;
}
void SoundComponent::updateAudioPos()
{
for (S32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
{
SFXSource* source = mSoundThread[slotNum].sound;
if (source)
source->setTransform(mOwner->getTransform());
}
}
//----------------------------------------------------------------------------
DefineEngineMethod(SoundComponent, playAudio, bool, (S32 slot, SFXTrack* track), (0, nullAsType<SFXTrack*>()),
"@brief Attach a sound to this shape and start playing it.\n\n"
"@param slot Audio slot index for the sound (valid range is 0 - 3)\n" // 3 = ShapeBase::MaxSoundThreads-1
"@param track SFXTrack to play\n"
"@return true if the sound was attached successfully, false if failed\n\n"
"@see stopAudio()\n")
{
if (track && slot >= 0 && slot < SoundComponent::MaxSoundThreads) {
object->playAudio(slot, track);
return true;
}
return false;
}
DefineEngineMethod(SoundComponent, stopAudio, bool, (S32 slot), ,
"@brief Stop a sound started with playAudio.\n\n"
"@param slot audio slot index (started with playAudio)\n"
"@return true if the sound was stopped successfully, false if failed\n\n"
"@see playAudio()\n")
{
if (slot >= 0 && slot < SoundComponent::MaxSoundThreads) {
object->stopAudio(slot);
return true;
}
return false;
}

View file

@ -0,0 +1,129 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef EXAMPLE_COMPONENT_H
#define EXAMPLE_COMPONENT_H
#pragma once
#ifndef COMPONENT_H
#include "T3D/components/component.h"
#endif
#ifndef RENDER_COMPONENT_INTERFACE_H
#include "T3D/components/render/renderComponentInterface.h"
#endif
class SFXSource;
//SoundComponent
//A basic example of the various functions you can utilize to make your own component!
//This example doesn't really DO anything, persay, but you can readily copy it as a base
//and use it as a starting point for your own.
class SoundComponent : public Component, public RenderComponentInterface, public EditorInspectInterface
{
typedef Component Parent;
public:
enum PublicConstants
{
MaxSoundThreads = 4, ///< Should be a power of 2
};
/// @name Network state masks
/// @{
///
enum SoundComponentMasks
{
SoundMaskN = Parent::NextFreeMask << 6, ///< Extends + MaxSoundThreads bits
};
enum BaseMaskConstants
{
SoundMask = (SoundMaskN << MaxSoundThreads) - SoundMaskN,
};
/// @name Scripted Sound
/// @{
struct Sound {
bool play; ///< Are we playing this sound?
SimTime timeout; ///< Time until we stop playing this sound.
SFXTrack* profile; ///< Profile on server
SFXSource* sound; ///< Sound on client
Sound()
{
play = false;
timeout = 0;
profile = NULL;
sound = NULL;
}
};
Sound mSoundThread[MaxSoundThreads];
SFXTrack* mSoundFile[MaxSoundThreads];
bool mPreviewSound[MaxSoundThreads];
bool mPlay[MaxSoundThreads];
/// @}
SoundComponent();
virtual ~SoundComponent();
DECLARE_CONOBJECT(SoundComponent);
virtual bool onAdd();
virtual void onRemove();
static void initPersistFields();
static bool _previewSound(void *object, const char *index, const char *data);
static bool _autoplay(void *object, const char *index, const char *data);
virtual U32 packUpdate(NetConnection *con, U32 mask, BitStream *stream);
virtual void unpackUpdate(NetConnection *con, BitStream *stream);
virtual void onComponentRemove();
virtual void onComponentAdd();
virtual void componentAddedToOwner(Component *comp);
virtual void componentRemovedFromOwner(Component *comp);
virtual void onInspect();
virtual void onEndInspect();
virtual void processTick();
virtual void advanceTime(F32 dt);
virtual void interpolateTick(F32 delta);
void prepRenderImage(SceneRenderState* state);
void _renderObject(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat);
virtual void playAudio(U32 slotNum, SFXTrack* profile = NULL);
virtual void stopAudio(U32 slot);
virtual void updateServerAudio();
virtual void updateAudioState(Sound& st);
virtual void updateAudioPos();
//why god why
virtual TSShape* getShape() { return NULL; };
Signal< void(RenderComponentInterface*) > onShapeChanged;
virtual TSShapeInstance* getShapeInstance() { return NULL; };
Signal< void(RenderComponentInterface*) > onShapeInstanceChanged;
virtual MatrixF getNodeTransform(S32 nodeIdx) { return MatrixF::Identity; };
virtual Vector<MatrixF> getNodeTransforms() { return NULL; };
virtual void setNodeTransforms(Vector<MatrixF> transforms) {};
};
#endif

View file

@ -79,6 +79,7 @@ CameraComponent::CameraComponent() : Component()
mTargetNode = "";
mUseParentTransform = true;
mNetworked = true;
mFriendlyName = "Camera(Component)";
}
@ -202,7 +203,7 @@ void CameraComponent::setCameraFov(F32 fov)
void CameraComponent::onCameraScopeQuery(NetConnection *cr, CameraScopeQuery * query)
{
// update the camera query
query->camera = this;
query->camera = mOwner;//this;
if(GameConnection * con = dynamic_cast<GameConnection*>(cr))
{
@ -357,7 +358,8 @@ U32 CameraComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
mTargetNodeIdx = nodeIndex;
}
stream->writeInt(mTargetNodeIdx, 32);
if(stream->writeFlag(mTargetNodeIdx > -1))
stream->writeInt(mTargetNodeIdx, 32);
//send offsets here
stream->writeCompressedPoint(mPosOffset);
@ -382,7 +384,10 @@ void CameraComponent::unpackUpdate(NetConnection *con, BitStream *stream)
if(stream->readFlag())
{
mTargetNodeIdx = stream->readInt(32);
if (stream->readFlag())
mTargetNodeIdx = stream->readInt(32);
else
mTargetNodeIdx = -1;
stream->readCompressedPoint(&mPosOffset);

View file

@ -125,8 +125,6 @@ EndImplementEnumType;
//
CollisionComponent::CollisionComponent() : Component()
{
mNetFlags.set(Ghostable | ScopeAlways);
mFriendlyName = "Collision(Component)";
mOwnerRenderInterface = NULL;

View file

@ -31,6 +31,7 @@
#include "console/engineAPI.h"
#include "sim/netConnection.h"
#include "console/consoleInternal.h"
#include "T3D/assets/MaterialAsset.h"
#define DECLARE_NATIVE_COMPONENT( ComponentType ) \
Component* staticComponentTemplate = new ComponentType; \
@ -42,17 +43,16 @@
Component::Component()
{
mFriendlyName = StringTable->lookup("");
mFromResource = StringTable->lookup("");
mComponentType = StringTable->lookup("");
mComponentGroup = StringTable->lookup("");
mNetworkType = StringTable->lookup("");
mTemplateName = StringTable->lookup("");
//mDependency = StringTable->lookup("");
mFriendlyName = StringTable->EmptyString();
mFromResource = StringTable->EmptyString();
mComponentType = StringTable->EmptyString();
mComponentGroup = StringTable->EmptyString();
mNetworkType = StringTable->EmptyString();
mTemplateName = StringTable->EmptyString();
//mDependency = StringTable->EmptyString();
mNetworked = false;
// [tom, 1/12/2007] We manage the memory for the description since it
// could be loaded from a file and thus massive. This is accomplished with
// protected fields, but since they still call Con::getData() the field
@ -64,7 +64,9 @@ Component::Component()
mCanSaveFieldDictionary = false;
mNetFlags.set(Ghostable);
mOriginatingAssetId = StringTable->EmptyString();
mIsServerObject = true;
}
Component::~Component()
@ -97,6 +99,10 @@ void Component::initPersistFields()
//addField("hidden", TypeBool, Offset(mHidden, Component), "Flags if this behavior is shown in the editor or not", AbstractClassRep::FieldFlags::FIELD_HideInInspectors);
addProtectedField("enabled", TypeBool, Offset(mEnabled, Component), &_setEnabled, &defaultProtectedGetFn, "");
addField("originatingAsset", TypeComponentAssetPtr, Offset(mOriginatingAsset, Component),
"Asset that spawned this component, used for tracking/housekeeping", AbstractClassRep::FieldFlags::FIELD_HideInInspectors);
endGroup("Component");
Parent::initPersistFields();
@ -149,6 +155,7 @@ bool Component::onAdd()
return false;
setMaskBits(UpdateMask);
setMaskBits(NamespaceMask);
return true;
}
@ -191,7 +198,6 @@ void Component::onComponentRemove()
{
mOwner->onComponentAdded.remove(this, &Component::componentAddedToOwner);
mOwner->onComponentRemoved.remove(this, &Component::componentRemovedFromOwner);
mOwner->onTransformSet.remove(this, &Component::ownerTransformSet);
}
mOwner = NULL;
@ -205,7 +211,6 @@ void Component::setOwner(Entity* owner)
{
mOwner->onComponentAdded.remove(this, &Component::componentAddedToOwner);
mOwner->onComponentRemoved.remove(this, &Component::componentRemovedFromOwner);
mOwner->onTransformSet.remove(this, &Component::ownerTransformSet);
mOwner->removeComponent(this, false);
}
@ -216,11 +221,18 @@ void Component::setOwner(Entity* owner)
{
mOwner->onComponentAdded.notify(this, &Component::componentAddedToOwner);
mOwner->onComponentRemoved.notify(this, &Component::componentRemovedFromOwner);
mOwner->onTransformSet.notify(this, &Component::ownerTransformSet);
}
if (isServerObject())
{
setMaskBits(OwnerMask);
//if we have any outstanding maskbits, push them along to have the network update happen on the entity
if (mDirtyMaskBits != 0 && mOwner)
{
mOwner->setMaskBits(Entity::ComponentsUpdateMask);
}
}
}
void Component::componentAddedToOwner(Component *comp)
@ -233,16 +245,19 @@ void Component::componentRemovedFromOwner(Component *comp)
return;
}
void Component::ownerTransformSet(MatrixF *mat)
void Component::setMaskBits(U32 orMask)
{
return;
AssertFatal(orMask != 0, "Invalid net mask bits set.");
if (mOwner)
mOwner->setComponentNetMask(this, orMask);
}
U32 Component::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
{
U32 retMask = Parent::packUpdate(con, mask, stream);
U32 retMask = 0;
if (mask & OwnerMask)
/*if (mask & OwnerMask)
{
if (mOwner != NULL)
{
@ -267,21 +282,32 @@ U32 Component::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
}
}
else
stream->writeFlag(false);
stream->writeFlag(false);*/
if (stream->writeFlag(mask & EnableMask))
{
stream->writeFlag(mEnabled);
}
/*if (stream->writeFlag(mask & NamespaceMask))
{
const char* name = getName();
if (stream->writeFlag(name && name[0]))
stream->writeString(String(name));
if (stream->writeFlag(mSuperClassName && mSuperClassName[0]))
stream->writeString(String(mSuperClassName));
if (stream->writeFlag(mClassName && mClassName[0]))
stream->writeString(String(mClassName));
}*/
return retMask;
}
void Component::unpackUpdate(NetConnection *con, BitStream *stream)
{
Parent::unpackUpdate(con, stream);
if (stream->readFlag())
/*if (stream->readFlag())
{
if (stream->readFlag())
{
@ -297,12 +323,38 @@ void Component::unpackUpdate(NetConnection *con, BitStream *stream)
//it's being nulled out
setOwner(NULL);
}
}
}*/
if (stream->readFlag())
{
mEnabled = stream->readFlag();
}
/*if (stream->readFlag())
{
if (stream->readFlag())
{
char name[256];
stream->readString(name);
assignName(name);
}
if (stream->readFlag())
{
char superClassname[256];
stream->readString(superClassname);
mSuperClassName = superClassname;
}
if (stream->readFlag())
{
char classname[256];
stream->readString(classname);
mClassName = classname;
}
linkNamespaces();
}*/
}
void Component::packToStream(Stream &stream, U32 tabStop, S32 behaviorID, U32 flags /* = 0 */)
@ -346,6 +398,10 @@ void Component::setDataField(StringTableEntry slotName, const char *array, const
onDataSet.trigger(this, slotName, value);
}
StringTableEntry Component::getComponentName()
{
return getNamespace()->getName();
}
//catch any behavior field updates
void Component::onStaticModified(const char* slotName, const char* newValue)
@ -417,7 +473,7 @@ void Component::addComponentField(const char *fieldName, const char *desc, const
else if (fieldType == StringTable->insert("vector"))
fieldTypeMask = TypePoint3F;
else if (fieldType == StringTable->insert("material"))
fieldTypeMask = TypeMaterialName;
fieldTypeMask = TypeMaterialAssetPtr;
else if (fieldType == StringTable->insert("image"))
fieldTypeMask = TypeImageFilename;
else if (fieldType == StringTable->insert("shape"))
@ -426,8 +482,19 @@ void Component::addComponentField(const char *fieldName, const char *desc, const
fieldTypeMask = TypeBool;
else if (fieldType == StringTable->insert("object"))
fieldTypeMask = TypeSimObjectPtr;
else if (fieldType == StringTable->insert("string"))
fieldTypeMask = TypeString;
else if (fieldType == StringTable->insert("colorI"))
fieldTypeMask = TypeColorI;
else if (fieldType == StringTable->insert("colorF"))
fieldTypeMask = TypeColorF;
else if (fieldType == StringTable->insert("ease"))
fieldTypeMask = TypeEaseF;
else if (fieldType == StringTable->insert("gameObject"))
fieldTypeMask = TypeGameObjectAssetPtr;
else
fieldTypeMask = TypeString;
field.mFieldTypeName = fieldType;
field.mFieldType = fieldTypeMask;
@ -603,6 +670,17 @@ ConsoleMethod(Component, setComponentield, const char *, 3, 3, "(int index) - Ge
return buf;
}
DefineConsoleMethod(Component, getComponentFieldType, const char *, (String fieldName), ,
"Get the number of static fields on the object.\n"
"@return The number of static fields defined on the object.")
{
ComponentField *field = object->getComponentField(fieldName);
if (field == NULL)
return "";
return field->mFieldTypeName;;
}
ConsoleMethod(Component, getBehaviorFieldUserData, const char *, 3, 3, "(int index) - Gets the UserData associated with a field by index in the field list\n"
"@param index The index of the behavior\n"
"@return Returns a string representing the user data of this field\n")

View file

@ -32,14 +32,22 @@
#ifndef CORE_INTERFACES_H
#include "T3D/components/coreInterfaces.h"
#endif
#ifndef _ASSET_PTR_H_
#include "assets/assetPtr.h"
#endif
#ifndef COMPONENT_ASSET_H
#include "T3D/assets/ComponentAsset.h"
#endif
class Entity;
class Namespace;
struct ComponentField
{
StringTableEntry mFieldName;
StringTableEntry mFieldDescription;
StringTableEntry mFieldTypeName;
S32 mFieldType;
StringTableEntry mUserData;
@ -56,9 +64,9 @@ struct ComponentField
///
///
//////////////////////////////////////////////////////////////////////////
class Component : public NetObject, public UpdateInterface
class Component : public SimObject, public UpdateInterface
{
typedef NetObject Parent;
typedef SimObject Parent;
protected:
StringTableEntry mFriendlyName;
@ -81,6 +89,13 @@ protected:
bool mHidden;
bool mEnabled;
StringTableEntry mOriginatingAssetId;
AssetPtr<ComponentAsset> mOriginatingAsset;
U32 mDirtyMaskBits;
bool mIsServerObject;
public:
Component();
virtual ~Component();
@ -102,7 +117,8 @@ public:
//This is called when a different component is removed from our owner entity
virtual void componentRemovedFromOwner(Component *comp);
virtual void ownerTransformSet(MatrixF *mat);
//Overridden by components that actually care
virtual void ownerTransformSet(MatrixF *mat) {}
void setOwner(Entity* pOwner);
inline Entity *getOwner() { return mOwner ? mOwner : NULL; }
@ -175,9 +191,20 @@ public:
OwnerMask = BIT(1),
UpdateMask = BIT(2),
EnableMask = BIT(3),
NextFreeMask = BIT(4)
NamespaceMask = BIT(4),
NextFreeMask = BIT(5)
};
virtual void setMaskBits(U32 orMask);
virtual void clearMaskBits() {
mDirtyMaskBits = 0;
}
bool isServerObject() { return mIsServerObject; }
bool isClientObject() { return !mIsServerObject; }
void setIsServerObject(bool isServerObj) { mIsServerObject = isServerObj; }
virtual U32 packUpdate(NetConnection *con, U32 mask, BitStream *stream);
virtual void unpackUpdate(NetConnection *con, BitStream *stream);
/// @}
@ -192,6 +219,8 @@ public:
void checkComponentFieldModified(const char* slotName, const char* newValue);
virtual void checkDependencies(){}
StringTableEntry getComponentName();
};
#endif // COMPONENT_H

View file

@ -57,7 +57,6 @@ StateMachineComponent::StateMachineComponent() : Component()
//doesn't need to be networked
mNetworked = false;
mNetFlags.clear();
}
StateMachineComponent::~StateMachineComponent()

View file

@ -330,93 +330,6 @@ void PlayerControllerComponent::updateMove()
bool doStandardMove = true;
GameConnection* con = mOwner->getControllingClient();
#ifdef TORQUE_EXTENDED_MOVE
// Work with an absolute rotation from the ExtendedMove class?
if (con && con->getControlSchemeAbsoluteRotation())
{
doStandardMove = false;
const ExtendedMove* emove = dynamic_cast<const ExtendedMove*>(move);
U32 emoveIndex = smExtendedMoveHeadPosRotIndex;
if (emoveIndex >= ExtendedMove::MaxPositionsRotations)
emoveIndex = 0;
if (emove->EulerBasedRotation[emoveIndex])
{
// Head pitch
mHead.x += (emove->rotX[emoveIndex] - mLastAbsolutePitch);
// Do we also include the relative yaw value?
if (con->getControlSchemeAddPitchToAbsRot())
{
F32 x = move->pitch;
if (x > M_PI_F)
x -= M_2PI_F;
mHead.x += x;
}
// Constrain the range of mHead.x
while (mHead.x < -M_PI_F)
mHead.x += M_2PI_F;
while (mHead.x > M_PI_F)
mHead.x -= M_2PI_F;
// Rotate (heading) head or body?
if (move->freeLook && ((isMounted() && getMountNode() == 0) || (con && !con->isFirstPerson())))
{
// Rotate head
mHead.z += (emove->rotZ[emoveIndex] - mLastAbsoluteYaw);
// Do we also include the relative yaw value?
if (con->getControlSchemeAddYawToAbsRot())
{
F32 z = move->yaw;
if (z > M_PI_F)
z -= M_2PI_F;
mHead.z += z;
}
// Constrain the range of mHead.z
while (mHead.z < 0.0f)
mHead.z += M_2PI_F;
while (mHead.z > M_2PI_F)
mHead.z -= M_2PI_F;
}
else
{
// Rotate body
mRot.z += (emove->rotZ[emoveIndex] - mLastAbsoluteYaw);
// Do we also include the relative yaw value?
if (con->getControlSchemeAddYawToAbsRot())
{
F32 z = move->yaw;
if (z > M_PI_F)
z -= M_2PI_F;
mRot.z += z;
}
// Constrain the range of mRot.z
while (mRot.z < 0.0f)
mRot.z += M_2PI_F;
while (mRot.z > M_2PI_F)
mRot.z -= M_2PI_F;
}
mLastAbsoluteYaw = emove->rotZ[emoveIndex];
mLastAbsolutePitch = emove->rotX[emoveIndex];
// Head bank
mHead.y = emove->rotY[emoveIndex];
// Constrain the range of mHead.y
while (mHead.y > M_PI_F)
mHead.y -= M_2PI_F;
}
}
#endif
MatrixF zRot;
zRot.set(EulerF(0.0f, 0.0f, mOwner->getRotation().asEulerF().z));

View file

@ -288,7 +288,7 @@ void RigidBodyComponent::processTick()
return;
// SINGLE PLAYER HACK!!!!
if (PHYSICSMGR->isSinglePlayer() && isClientObject() && getServerObject())
/*if (PHYSICSMGR->isSinglePlayer() && isClientObject() && getServerObject())
{
RigidBodyComponent *servObj = (RigidBodyComponent*)getServerObject();
mOwner->setTransform(servObj->mState.getTransform());
@ -296,7 +296,7 @@ void RigidBodyComponent::processTick()
mRenderState[1] = servObj->mRenderState[1];
return;
}
}*/
// Store the last render state.
mRenderState[0] = mRenderState[1];

View file

@ -34,7 +34,6 @@
#include "lighting/lightQuery.h"
#include "scene/sceneManager.h"
#include "gfx/bitmap/ddsFile.h"
#include "gfx/bitmap/ddsUtils.h"
#include "gfx/gfxTextureManager.h"
#include "materials/materialFeatureTypes.h"
#include "renderInstance/renderImposterMgr.h"
@ -46,52 +45,49 @@
#include "core/strings/findMatch.h"
#include "T3D/components/render/meshComponent_ScriptBinding.h"
ImplementEnumType(BatchingMode,
"Type of mesh data available in a shape.\n"
"@ingroup gameObjects")
{
MeshComponent::Individual, "Individual", "This mesh is rendered indivudally, wthout batching or instancing."
},
{ MeshComponent::StaticBatch, "Static Batching", "Statically batches this mesh together with others to reduce drawcalls." },
//{ MeshComponent::DynamicBatch, "Dynamic Batching", "Dynamical batches this mesh together with others to reduce drawcalls each frame." },
// { MeshComponent::Instanced, "Instanced", "This mesh is rendered as an instance, reducing draw overhead with others that share the same mesh and material." },
EndImplementEnumType;
//////////////////////////////////////////////////////////////////////////
// Constructor/Destructor
//////////////////////////////////////////////////////////////////////////
MeshComponent::MeshComponent() : Component()
{
mShapeName = StringTable->insert("");
mShapeAsset = StringTable->insert("");
mShapeInstance = NULL;
mChangingMaterials.clear();
mMaterials.clear();
mFriendlyName = "Mesh Component";
mComponentType = "Render";
mDescription = getDescriptionText("Causes the object to render a non-animating 3d shape using the file provided.");
mNetworked = true;
mNetFlags.set(Ghostable | ScopeAlways);
mShapeName = StringTable->EmptyString();
mShapeAsset = StringTable->EmptyString();
mMeshAsset = StringTable->EmptyString();
mMeshAssetId = StringTable->EmptyString();
mInterfaceData = new MeshRenderSystemInterface();
mRenderMode = Individual;
}
MeshComponent::~MeshComponent(){}
MeshComponent::~MeshComponent()
{
if (mInterfaceData)
SAFE_DELETE(mInterfaceData);
}
IMPLEMENT_CO_NETOBJECT_V1(MeshComponent);
//==========================================================================================
void MeshComponent::boneObject::addObject(SimObject* object)
{
SceneObject* sc = dynamic_cast<SceneObject*>(object);
if(sc && mOwner)
{
if(TSShape* shape = mOwner->getShape())
{
S32 nodeID = shape->findNode(mBoneName);
//we may have a offset on the shape's center
//so make sure we accomodate for that when setting up the mount offsets
MatrixF mat = mOwner->getNodeTransform(nodeID);
mOwner->getOwner()->mountObject(sc, nodeID, mat);
}
}
}
bool MeshComponent::onAdd()
{
if(! Parent::onAdd())
@ -107,6 +103,12 @@ void MeshComponent::onComponentAdd()
{
Parent::onComponentAdd();
if (isClientObject())
mInterfaceData->mIsClient = true;
// if (mInterfaceData != nullptr)
// mInterfaceData->mIsClient = isClientObject();
//get the default shape, if any
updateShape();
}
@ -114,10 +116,6 @@ void MeshComponent::onComponentAdd()
void MeshComponent::onRemove()
{
Parent::onRemove();
mMeshAsset.clear();
SAFE_DELETE(mShapeInstance);
}
void MeshComponent::onComponentRemove()
@ -136,9 +134,14 @@ void MeshComponent::initPersistFields()
{
Parent::initPersistFields();
addGroup("Rendering");
addField("BatchingMode", TypeBatchingMode, Offset(mRenderMode, MeshComponent),
"The mode of batching this shape should be rendered with.");
endGroup("Rendering");
//create a hook to our internal variables
addGroup("Model");
addProtectedField("MeshAsset", TypeAssetId, Offset(mShapeAsset, MeshComponent), &_setMesh, &defaultProtectedGetFn,
addProtectedField("MeshAsset", TypeShapeAssetPtr, Offset(mShapeAsset, MeshComponent), &_setMesh, &defaultProtectedGetFn,
"The asset Id used for the mesh.", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
endGroup("Model");
}
@ -166,6 +169,9 @@ bool MeshComponent::_setShape( void *object, const char *index, const char *data
bool MeshComponent::setMeshAsset(const char* assetName)
{
// Fetch the asset Id.
if (mInterfaceData == nullptr)
return false;
mMeshAssetId = StringTable->insert(assetName);
mMeshAsset = mMeshAssetId;
@ -184,9 +190,129 @@ bool MeshComponent::setMeshAsset(const char* assetName)
return true;
}
void MeshComponent::updateShape()
{
if (mInterfaceData == nullptr)
return;
//if ((mShapeName && mShapeName[0] != '\0') || (mShapeAsset && mShapeAsset[0] != '\0'))
if ((mShapeName && mShapeName[0] != '\0') || (mMeshAssetId && mMeshAssetId[0] != '\0'))
{
if (mMeshAsset == NULL)
return;
mShape = mMeshAsset->getShape();
if (!mMeshAsset->getShape())
return;
setupShape();
//Do this on both the server and client
S32 materialCount = mMeshAsset->getShape()->materialList->getMaterialNameList().size();
if (isServerObject())
{
//we need to update the editor
for (U32 i = 0; i < mFields.size(); i++)
{
//find any with the materialslot title and clear them out
if (FindMatch::isMatch("MaterialSlot*", mFields[i].mFieldName, false))
{
setDataField(mFields[i].mFieldName, NULL, "");
mFields.erase(i);
continue;
}
}
//next, get a listing of our materials in the shape, and build our field list for them
char matFieldName[128];
if (materialCount > 0)
mComponentGroup = StringTable->insert("Materials");
for (U32 i = 0; i < materialCount; i++)
{
String materialname = mMeshAsset->getShape()->materialList->getMaterialName(i);
if (materialname == String("ShapeBounds"))
continue;
dSprintf(matFieldName, 128, "MaterialSlot%d", i);
addComponentField(matFieldName, "A material used in the shape file", "Material", materialname, "");
}
if (materialCount > 0)
mComponentGroup = "";
}
if (mOwner != NULL)
{
Point3F min, max, pos;
pos = mOwner->getPosition();
mOwner->getWorldToObj().mulP(pos);
min = mMeshAsset->getShape()->bounds.minExtents;
max = mMeshAsset->getShape()->bounds.maxExtents;
if (mInterfaceData)
{
mInterfaceData->mBounds.set(min, max);
mInterfaceData->mScale = mOwner->getScale();
mInterfaceData->mTransform = mOwner->getRenderTransform();
}
mOwner->setObjectBox(Box3F(min, max));
mOwner->resetWorldBox();
if (mOwner->getSceneManager() != NULL)
mOwner->getSceneManager()->notifyObjectDirty(mOwner);
}
if (isClientObject() && mInterfaceData)
{
if (mRenderMode == StaticBatch)
{
mInterfaceData->mStatic = true;
OptimizedPolyList geom;
MatrixF transform = mInterfaceData->mTransform;
mInterfaceData->mGeometry.setTransform(&transform, mInterfaceData->mScale);
mInterfaceData->mGeometry.setObject(mOwner);
mInterfaceData->mShapeInstance->buildPolyList(&mInterfaceData->mGeometry, 0);
}
else
{
mInterfaceData->mStatic = false;
}
MeshRenderSystem::rebuildBuffers();
}
//finally, notify that our shape was changed
onShapeInstanceChanged.trigger(this);
}
}
void MeshComponent::setupShape()
{
mInterfaceData->mShapeInstance = new TSShapeInstance(mMeshAsset->getShape(), true);
}
void MeshComponent::_onResourceChanged( const Torque::Path &path )
{
if ( path != Torque::Path( mShapeName ) )
if (mInterfaceData == nullptr)
return;
String filePath;
if (mMeshAsset)
filePath = Torque::Path(mMeshAsset->getShapeFilename());
if (!mMeshAsset || path != Torque::Path(mMeshAsset->getShapeFilename()) )
return;
updateShape();
@ -217,6 +343,8 @@ U32 MeshComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
if (stream->writeFlag(mask & ShapeMask))
{
stream->writeString(mShapeName);
stream->writeInt(mRenderMode, 8);
}
if (stream->writeFlag( mask & MaterialMask ))
@ -227,7 +355,7 @@ U32 MeshComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
{
stream->writeInt(mChangingMaterials[i].slot, 16);
NetStringHandle matNameStr = mChangingMaterials[i].matName.c_str();
NetStringHandle matNameStr = mChangingMaterials[i].assetId.c_str();
con->packNetStringHandleU(stream, matNameStr);
}
@ -244,6 +372,8 @@ void MeshComponent::unpackUpdate(NetConnection *con, BitStream *stream)
if(stream->readFlag())
{
mShapeName = stream->readSTString();
mRenderMode = (RenderMode)stream->readInt(8);
setMeshAsset(mShapeName);
updateShape();
}
@ -257,7 +387,10 @@ void MeshComponent::unpackUpdate(NetConnection *con, BitStream *stream)
{
matMap newMatMap;
newMatMap.slot = stream->readInt(16);
newMatMap.matName = String(con->unpackNetStringHandleU(stream).getString());
newMatMap.assetId = String(con->unpackNetStringHandleU(stream).getString());
//do the lookup, now
newMatMap.matAsset = AssetDatabase.acquireAsset<MaterialAsset>(newMatMap.assetId);
mChangingMaterials.push_back(newMatMap);
}
@ -268,7 +401,7 @@ void MeshComponent::unpackUpdate(NetConnection *con, BitStream *stream)
void MeshComponent::prepRenderImage( SceneRenderState *state )
{
if (!mEnabled || !mOwner || !mShapeInstance)
/*if (!mEnabled || !mOwner || !mShapeInstance)
return;
Point3F cameraOffset;
@ -301,114 +434,41 @@ void MeshComponent::prepRenderImage( SceneRenderState *state )
rdata.setLightQuery(&query);
MatrixF mat = mOwner->getRenderTransform();
Point3F renderPos = mat.getPosition();
EulerF renderRot = mat.toEuler();
if (mOwner->isMounted())
{
MatrixF wrldPos = mOwner->getWorldTransform();
Point3F wrldPosPos = wrldPos.getPosition();
Point3F mntPs = mat.getPosition();
EulerF mntRt = RotationF(mat).asEulerF();
bool tr = true;
}
mat.scale(objScale);
GFX->setWorldMatrix(mat);
mShapeInstance->render(rdata);
}
void MeshComponent::updateShape()
{
bool isServer = isServerObject();
if ((mShapeName && mShapeName[0] != '\0') || (mShapeAsset && mShapeAsset[0] != '\0'))
{
if (mMeshAsset == NULL)
return;
mShape = mMeshAsset->getShape();
if (!mShape)
return;
setupShape();
//Do this on both the server and client
S32 materialCount = mShape->materialList->getMaterialNameList().size();
if(isServerObject())
{
//we need to update the editor
for (U32 i = 0; i < mFields.size(); i++)
{
//find any with the materialslot title and clear them out
if (FindMatch::isMatch("MaterialSlot*", mFields[i].mFieldName, false))
{
setDataField(mFields[i].mFieldName, NULL, "");
mFields.erase(i);
continue;
}
}
//next, get a listing of our materials in the shape, and build our field list for them
char matFieldName[128];
if(materialCount > 0)
mComponentGroup = StringTable->insert("Materials");
for(U32 i=0; i < materialCount; i++)
{
String materialname = mShape->materialList->getMaterialName(i);
if(materialname == String("ShapeBounds"))
continue;
dSprintf(matFieldName, 128, "MaterialSlot%d", i);
addComponentField(matFieldName, "A material used in the shape file", "TypeAssetId", materialname, "");
}
if(materialCount > 0)
mComponentGroup = "";
}
if(mOwner != NULL)
{
Point3F min, max, pos;
pos = mOwner->getPosition();
mOwner->getWorldToObj().mulP(pos);
min = mShape->bounds.minExtents;
max = mShape->bounds.maxExtents;
mShapeBounds.set(min, max);
mOwner->setObjectBox(Box3F(min, max));
if( mOwner->getSceneManager() != NULL )
mOwner->getSceneManager()->notifyObjectDirty( mOwner );
}
//finally, notify that our shape was changed
onShapeInstanceChanged.trigger(this);
}
}
void MeshComponent::setupShape()
{
mShapeInstance = new TSShapeInstance(mShape, true);
mShapeInstance->render(rdata);*/
}
void MeshComponent::updateMaterials()
{
if (mChangingMaterials.empty() || !mShape)
if (mChangingMaterials.empty() || !mMeshAsset->getShape())
return;
TSMaterialList* pMatList = mShapeInstance->getMaterialList();
TSMaterialList* pMatList = mInterfaceData->mShapeInstance->getMaterialList();
pMatList->setTextureLookupPath(getShapeResource().getPath().getPath());
const Vector<String> &materialNames = pMatList->getMaterialNameList();
for ( S32 i = 0; i < materialNames.size(); i++ )
{
const String &pName = materialNames[i];
for(U32 m=0; m < mChangingMaterials.size(); m++)
{
if(mChangingMaterials[m].slot == i)
{
pMatList->renameMaterial( i, mChangingMaterials[m].matName );
//Fetch the actual material asset
pMatList->renameMaterial( i, mChangingMaterials[m].matAsset->getMaterialDefinitionName());
}
}
@ -416,22 +476,31 @@ void MeshComponent::updateMaterials()
}
// Initialize the material instances
mShapeInstance->initMaterialList();
mInterfaceData->mShapeInstance->initMaterialList();
}
MatrixF MeshComponent::getNodeTransform(S32 nodeIdx)
{
if (mShape)
if (mInterfaceData != nullptr && mMeshAsset->getShape())
{
S32 nodeCount = getShape()->nodes.size();
if(nodeIdx >= 0 && nodeIdx < nodeCount)
{
//animate();
MatrixF mountTransform = mShapeInstance->mNodeTransforms[nodeIdx];
mountTransform.mul(mOwner->getRenderTransform());
MatrixF nodeTransform = mInterfaceData->mShapeInstance->mNodeTransforms[nodeIdx];
const Point3F& scale = mOwner->getScale();
return mountTransform;
// The position of the node needs to be scaled.
Point3F position = nodeTransform.getPosition();
position.convolve(scale);
nodeTransform.setPosition(position);
MatrixF finalTransform = MatrixF::Identity;
finalTransform.mul(mOwner->getRenderTransform(), nodeTransform);
return finalTransform;
}
}
@ -440,7 +509,7 @@ MatrixF MeshComponent::getNodeTransform(S32 nodeIdx)
S32 MeshComponent::getNodeByName(String nodeName)
{
if (mShape)
if (mMeshAsset->getShape())
{
S32 nodeIdx = getShape()->findNode(nodeName);
@ -486,12 +555,18 @@ void MeshComponent::onDynamicModified(const char* slotName, const char* newValue
if(slot == -1)
return;
//Safe to assume the inbound value for the material will be a MaterialAsset, so lets do a lookup on the name
MaterialAsset* matAsset = AssetDatabase.acquireAsset<MaterialAsset>(newValue);
if (!matAsset)
return;
bool found = false;
for(U32 i=0; i < mChangingMaterials.size(); i++)
{
if(mChangingMaterials[i].slot == slot)
{
mChangingMaterials[i].matName = String(newValue);
mChangingMaterials[i].matAsset = matAsset;
mChangingMaterials[i].assetId = newValue;
found = true;
}
}
@ -500,7 +575,8 @@ void MeshComponent::onDynamicModified(const char* slotName, const char* newValue
{
matMap newMatMap;
newMatMap.slot = slot;
newMatMap.matName = String(newValue);
newMatMap.matAsset = matAsset;
newMatMap.assetId = newValue;
mChangingMaterials.push_back(newMatMap);
}
@ -511,14 +587,31 @@ void MeshComponent::onDynamicModified(const char* slotName, const char* newValue
Parent::onDynamicModified(slotName, newValue);
}
void MeshComponent::changeMaterial(U32 slot, const char* newMat)
void MeshComponent::changeMaterial(U32 slot, MaterialAsset* newMat)
{
char fieldName[512];
//update our respective field
dSprintf(fieldName, 512, "materialSlot%d", slot);
setDataField(fieldName, NULL, newMat);
setDataField(fieldName, NULL, newMat->getAssetId());
}
bool MeshComponent::setMatInstField(U32 slot, const char* field, const char* value)
{
TSMaterialList* pMatList = mInterfaceData->mShapeInstance->getMaterialList();
pMatList->setTextureLookupPath(getShapeResource().getPath().getPath());
MaterialParameters* params = pMatList->getMaterialInst(slot)->getMaterialParameters();
if (pMatList->getMaterialInst(slot)->getFeatures().hasFeature(MFT_DiffuseColor))
{
MaterialParameterHandle* handle = pMatList->getMaterialInst(slot)->getMaterialParameterHandle("DiffuseColor");
params->set(handle, LinearColorF(0, 0, 0));
}
return true;
}
void MeshComponent::onInspect()
@ -527,4 +620,13 @@ void MeshComponent::onInspect()
void MeshComponent::onEndInspect()
{
}
void MeshComponent::ownerTransformSet(MatrixF *mat)
{
if (mInterfaceData != nullptr)
{
MatrixF newTransform = *mat;
mInterfaceData->mTransform = newTransform;
}
}

View file

@ -60,6 +60,8 @@
#include "gfx/gfxVertexFormat.h"
#endif
#include "T3D/systems/render/meshRenderSystem.h"
class TSShapeInstance;
class SceneRenderState;
//////////////////////////////////////////////////////////////////////////
@ -84,37 +86,38 @@ protected:
StringTableEntry mShapeName;
StringTableEntry mShapeAsset;
TSShape* mShape;
Box3F mShapeBounds;
//Box3F mShapeBounds;
Point3F mCenterOffset;
MeshRenderSystemInterface* mInterfaceData;
struct matMap
{
String matName;
MaterialAsset* matAsset;
String assetId;
U32 slot;
};
Vector<matMap> mChangingMaterials;
Vector<matMap> mMaterials;
class boneObject : public SimGroup
public:
enum RenderMode
{
MeshComponent *mOwner;
public:
boneObject(MeshComponent *owner){ mOwner = owner; }
StringTableEntry mBoneName;
S32 mItemID;
virtual void addObject(SimObject *obj);
Individual = 0,
DynamicBatch,
StaticBatch,
Instanced
};
Vector<boneObject*> mNodesList;
protected:
RenderMode mRenderMode;
public:
StringTableEntry mMeshAssetId;
AssetPtr<ShapeAsset> mMeshAsset;
TSShapeInstance* mShapeInstance;
//TSShapeInstance* mShapeInstance;
public:
MeshComponent();
@ -132,7 +135,7 @@ public:
virtual U32 packUpdate(NetConnection *con, U32 mask, BitStream *stream);
virtual void unpackUpdate(NetConnection *con, BitStream *stream);
Box3F getShapeBounds() { return mShapeBounds; }
Box3F getShapeBounds() { return mInterfaceData->mBounds; }
virtual MatrixF getNodeTransform(S32 nodeIdx);
S32 getNodeByName(String nodeName);
@ -144,6 +147,8 @@ public:
virtual void onComponentRemove();
virtual void onComponentAdd();
virtual void ownerTransformSet(MatrixF *mat);
static bool _setMesh(void *object, const char *index, const char *data);
static bool _setShape(void *object, const char *index, const char *data);
const char* _getShape(void *object, const char *data);
@ -151,7 +156,7 @@ public:
bool setMeshAsset(const char* assetName);
virtual TSShape* getShape() { if (mMeshAsset) return mMeshAsset->getShape(); else return NULL; }
virtual TSShapeInstance* getShapeInstance() { return mShapeInstance; }
virtual TSShapeInstance* getShapeInstance() { return mInterfaceData->mShapeInstance; }
Resource<TSShape> getShapeResource() { return mMeshAsset->getShapeResource(); }
@ -163,7 +168,8 @@ public:
virtual void onDynamicModified(const char* slotName, const char* newValue);
void changeMaterial(U32 slot, const char* newMat);
void changeMaterial(U32 slot, MaterialAsset* newMat);
bool setMatInstField(U32 slot, const char* field, const char* value);
virtual void onInspect();
virtual void onEndInspect();
@ -180,4 +186,7 @@ public:
}
};
typedef MeshComponent::RenderMode BatchingMode;
DefineEnumType(BatchingMode);
#endif

View file

@ -126,6 +126,28 @@ DefineEngineMethod(MeshComponent, getNodePosition, Point3F,
return Point3F(0, 0, 0);
}
DefineEngineMethod(MeshComponent, getNodeRotation, EulerF,
(S32 node), (-1),
"@brief Mount objB to this object at the desired slot with optional transform.\n\n"
"@param objB Object to mount onto us\n"
"@param slot Mount slot ID\n"
"@param txfm (optional) mount offset transform\n"
"@return true if successful, false if failed (objB is not valid)")
{
if (node != -1)
{
//BUG: Unsure how it broke, but atm the default transform passed in here is rotated 180 degrees. This doesn't happen
//for the SceneObject mountobject method. Hackish, but for now, just default to a clean MatrixF::Identity
//object->mountObjectToNode( objB, node, /*MatrixF::Identity*/txfm.getMatrix() );
RotationF mat = object->getNodeTransform(node);
return mat.asEulerF(RotationF::Degrees);
}
return EulerF(0, 0, 0);
}
DefineEngineMethod(MeshComponent, getNodeByName, S32,
(String nodeName), ,
"@brief Mount objB to this object at the desired slot with optional transform.\n\n"
@ -148,8 +170,14 @@ DefineEngineMethod(MeshComponent, getNodeByName, S32,
return -1;
}
DefineEngineMethod(MeshComponent, changeMaterial, void, (U32 slot, const char* newMat), (0, ""),
DefineEngineMethod(MeshComponent, changeMaterial, void, (U32 slot, MaterialAsset* newMat), (0, nullAsType<MaterialAsset*>()),
"@brief Change one of the materials on the shape.\n\n")
{
object->changeMaterial(slot, newMat);
}
DefineEngineMethod(MeshComponent, setMatInstField, bool, (U32 slot, const char* field, const char* value), (0, "", ""),
"@brief Change one of the materials on the shape.\n\n")
{
return object->setMatInstField(slot, field, value);
}

View file

@ -47,10 +47,13 @@
#include "T3D/gameBase/std/stdMoveList.h"
#include "T3D/prefab.h"
#include "T3D/gameBase/gameConnection.h"
#include <thread>
//
#include "gfx/sim/debugDraw.h"
//
#include "T3D/sfx/sfx3DWorld.h"
extern bool gEditingMission;
@ -117,6 +120,10 @@ Entity::Entity()
mInitialized = false;
mLifetimeMS = 0;
mGameObjectAssetId = StringTable->insert("");
}
Entity::~Entity()
@ -143,6 +150,15 @@ void Entity::initPersistFields()
addField("LocalRotation", TypeMatrixRotation, Offset(mMount.xfm, Entity), "Rotation we are mounted at ( object space of our mount object ).");
endGroup("Transform");
addGroup("Misc");
addField("LifetimeMS", TypeS32, Offset(mLifetimeMS, Entity), "Object world orientation.");
endGroup("Misc");
addGroup("GameObject");
addProtectedField("gameObjectName", TypeGameObjectAssetPtr, Offset(mGameObjectAsset, Entity), &_setGameObject, &defaultProtectedGetFn,
"The asset Id used for the game object this entity is based on.");
endGroup("GameObject");
}
//
@ -215,15 +231,27 @@ bool Entity::onAdd()
if (!Parent::onAdd())
return false;
mObjBox = Box3F(Point3F(-1, -1, -1), Point3F(1, 1, 1));
mObjBox = Box3F(Point3F(-0.5, -0.5, -0.5), Point3F(0.5, 0.5, 0.5));
resetWorldBox();
setObjectBox(mObjBox);
addToScene();
//Make sure we get positioned
setMaskBits(TransformMask);
if (isServerObject())
{
setMaskBits(TransformMask);
setMaskBits(NamespaceMask);
}
else
{
//We can shortcut the initialization here because stuff generally ghosts down in order, and onPostAdd isn't called on ghosts.
onPostAdd();
}
if (mLifetimeMS != 0)
mStartTimeMS = Platform::getRealMilliseconds();
return true;
}
@ -236,6 +264,8 @@ void Entity::onRemove()
onDataSet.removeAll();
mGameObjectAsset.clear();
Parent::onRemove();
}
@ -249,10 +279,41 @@ void Entity::onPostAdd()
mComponents[i]->onComponentAdd();
}
//Set up the networked components
mNetworkedComponents.clear();
for (U32 i = 0; i < mComponents.size(); i++)
{
if (mComponents[i]->isNetworked())
{
NetworkedComponent netComp;
netComp.componentIndex = i;
netComp.updateState = NetworkedComponent::Adding;
netComp.updateMaskBits = -1;
mNetworkedComponents.push_back(netComp);
}
}
if (!mNetworkedComponents.empty())
{
setMaskBits(AddComponentsMask);
setMaskBits(ComponentsUpdateMask);
}
if (isMethod("onAdd"))
Con::executef(this, "onAdd");
}
bool Entity::_setGameObject(void *object, const char *index, const char *data)
{
Entity *e = static_cast<Entity*>(object);
// Sanity!
AssertFatal(data != NULL, "Cannot use a NULL asset Id.");
return true; //rbI->setMeshAsset(data);
}
void Entity::setDataField(StringTableEntry slotName, const char *array, const char *value)
{
Parent::setDataField(slotName, array, value);
@ -363,8 +424,28 @@ void Entity::processTick(const Move* move)
}
}
if (isMethod("processTick"))
// Save current rigid state interpolation
mDelta.posVec = getPosition();
mDelta.rot[0] = mRot.asQuatF();
//Handle any script updates, which can include physics stuff
if (isServerObject() && isMethod("processTick"))
Con::executef(this, "processTick");
// Wrap up interpolation info
mDelta.pos = getPosition();
mDelta.posVec -= getPosition();
mDelta.rot[1] = mRot.asQuatF();
setTransform(getPosition(), mRot);
//Lifetime test
if (mLifetimeMS != 0)
{
S32 currentTime = Platform::getRealMilliseconds();
if (currentTime - mStartTimeMS >= mLifetimeMS)
deleteObject();
}
}
}
@ -402,11 +483,6 @@ U32 Entity::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
if (stream->writeFlag(mask & TransformMask))
{
//mathWrite( *stream, getScale() );
//stream->writeAffineTransform(mObjToWorld);
//mathWrite(*stream, getPosition());
//mathWrite(*stream, mPos);
stream->writeCompressedPoint(mPos);
mathWrite(*stream, getRotation());
@ -415,73 +491,125 @@ U32 Entity::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
stream->writeFlag(!(mask & NoWarpMask));
}
/*if (stream->writeFlag(mask & MountedMask))
{
mathWrite(*stream, mMount.xfm.getPosition());
mathWrite(*stream, mMount.xfm.toEuler());
}*/
if (stream->writeFlag(mask & BoundsMask))
{
mathWrite(*stream, mObjBox);
}
//pass our behaviors around
if (mask & ComponentsMask || mask & InitialUpdateMask)
if (stream->writeFlag(mask & AddComponentsMask))
{
stream->writeFlag(true);
//now, we run through a list of our to-be-sent behaviors and begin sending them
//if any fail, we keep our list and re-queue the mask
S32 componentCount = mToLoadComponents.size();
U32 toAddComponentCount = 0;
//build our 'ready' list
//This requires both the instance and the instances' template to be prepped(if the template hasn't been ghosted,
//then we know we shouldn't be passing the instance's ghosts around yet)
U32 ghostedCompCnt = 0;
for (U32 i = 0; i < componentCount; i++)
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
{
if (con->getGhostIndex(mToLoadComponents[i]) != -1)
ghostedCompCnt++;
}
if (ghostedCompCnt != 0)
{
stream->writeFlag(true);
stream->writeFlag(mStartComponentUpdate);
//if not all the behaviors have been ghosted, we'll need another pass
if (ghostedCompCnt != componentCount)
retMask |= ComponentsMask;
//write the currently ghosted behavior count
stream->writeInt(ghostedCompCnt, 16);
for (U32 i = 0; i < mToLoadComponents.size(); i++)
if (mNetworkedComponents[i].updateState == NetworkedComponent::Adding)
{
//now fetch them and pass the ghost
S32 ghostIndex = con->getGhostIndex(mToLoadComponents[i]);
if (ghostIndex != -1)
{
stream->writeInt(ghostIndex, NetConnection::GhostIdBitSize);
mToLoadComponents.erase(i);
i--;
mStartComponentUpdate = false;
}
toAddComponentCount++;
}
}
else if (componentCount)
//you reaaaaally shouldn't have >255 networked components on a single entity
stream->writeInt(toAddComponentCount, 8);
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
{
//on the odd chance we have behaviors to ghost, but NONE of them have been yet, just set the flag now
stream->writeFlag(false);
retMask |= ComponentsMask;
NetworkedComponent::UpdateState state = mNetworkedComponents[i].updateState;
if (mNetworkedComponents[i].updateState == NetworkedComponent::Adding)
{
const char* className = mComponents[mNetworkedComponents[i].componentIndex]->getClassName();
stream->writeString(className, strlen(className));
mNetworkedComponents[i].updateState = NetworkedComponent::Updating;
}
}
else
stream->writeFlag(false);
}
else
stream->writeFlag(false);
if (stream->writeFlag(mask & RemoveComponentsMask))
{
/*U32 toRemoveComponentCount = 0;
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
{
if (mNetworkedComponents[i].updateState == NetworkedComponent::Adding)
{
toRemoveComponentCount++;
}
}
//you reaaaaally shouldn't have >255 networked components on a single entity
stream->writeInt(toRemoveComponentCount, 8);
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
{
if (mNetworkedComponents[i].updateState == NetworkedComponent::Removing)
{
stream->writeInt(i, 16);
}
}*/
/*for (U32 i = 0; i < mNetworkedComponents.size(); i++)
{
if (mNetworkedComponents[i].updateState == NetworkedComponent::UpdateState::Removing)
{
removeComponent(mComponents[mNetworkedComponents[i].componentIndex], true);
mNetworkedComponents.erase(i);
i--;
}
}*/
}
//Update our components
if (stream->writeFlag(mask & ComponentsUpdateMask))
{
U32 toUpdateComponentCount = 0;
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
{
if (mNetworkedComponents[i].updateState == NetworkedComponent::Updating)
{
toUpdateComponentCount++;
}
}
//you reaaaaally shouldn't have >255 networked components on a single entity
stream->writeInt(toUpdateComponentCount, 8);
bool forceUpdate = false;
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
{
if (mNetworkedComponents[i].updateState == NetworkedComponent::Updating)
{
stream->writeInt(i, 8);
mNetworkedComponents[i].updateMaskBits = mComponents[mNetworkedComponents[i].componentIndex]->packUpdate(con, mNetworkedComponents[i].updateMaskBits, stream);
if (mNetworkedComponents[i].updateMaskBits != 0)
forceUpdate = true;
else
mNetworkedComponents[i].updateState = NetworkedComponent::None;
}
}
//If we have leftover, we need to re-iterate our packing
if (forceUpdate)
setMaskBits(ComponentsUpdateMask);
}
/*if (stream->writeFlag(mask & NamespaceMask))
{
const char* name = getName();
if (stream->writeFlag(name && name[0]))
stream->writeString(String(name));
if (stream->writeFlag(mSuperClassName && mSuperClassName[0]))
stream->writeString(String(mSuperClassName));
if (stream->writeFlag(mClassName && mClassName[0]))
stream->writeString(String(mClassName));
}*/
return retMask;
}
@ -492,20 +620,10 @@ void Entity::unpackUpdate(NetConnection *con, BitStream *stream)
if (stream->readFlag())
{
/*Point3F scale;
mathRead( *stream, &scale );
setScale( scale);*/
//MatrixF objToWorld;
//stream->readAffineTransform(&objToWorld);
Point3F pos;
stream->readCompressedPoint(&pos);
//mathRead(*stream, &pos);
RotationF rot;
mathRead(*stream, &rot);
mDelta.move.unpack(stream);
@ -514,72 +632,6 @@ void Entity::unpackUpdate(NetConnection *con, BitStream *stream)
{
// Determine number of ticks to warp based on the average
// of the client and server velocities.
/*mDelta.warpOffset = pos - mDelta.pos;
F32 dt = mDelta.warpOffset.len() / (0.5f * TickSec);
mDelta.warpTicks = (S32)((dt > sMinWarpTicks) ? getMax(mFloor(dt + 0.5f), 1.0f) : 0.0f);
//F32 as = (speed + mVelocity.len()) * 0.5f * TickSec;
//F32 dt = (as > 0.00001f) ? mDelta.warpOffset.len() / as : sMaxWarpTicks;
//mDelta.warpTicks = (S32)((dt > sMinWarpTicks) ? getMax(mFloor(dt + 0.5f), 1.0f) : 0.0f);
//mDelta.warpTicks = (S32)((dt > sMinWarpTicks) ? getMax(mFloor(dt + 0.5f), 1.0f) : 0.0f);
//mDelta.warpTicks = sMaxWarpTicks;
mDelta.warpTicks = 0;
if (mDelta.warpTicks)
{
// Setup the warp to start on the next tick.
if (mDelta.warpTicks > sMaxWarpTicks)
mDelta.warpTicks = sMaxWarpTicks;
mDelta.warpOffset /= (F32)mDelta.warpTicks;
mDelta.rot[0] = rot.asQuatF();
mDelta.rot[1] = rot.asQuatF();
mDelta.rotOffset = rot.asEulerF() - mDelta.rot.asEulerF();
// Ignore small rotation differences
if (mFabs(mDelta.rotOffset.x) < 0.001f)
mDelta.rotOffset.x = 0;
if (mFabs(mDelta.rotOffset.y) < 0.001f)
mDelta.rotOffset.y = 0;
if (mFabs(mDelta.rotOffset.z) < 0.001f)
mDelta.rotOffset.z = 0;
mDelta.rotOffset /= (F32)mDelta.warpTicks;
}
else
{
// Going to skip the warp, server and client are real close.
// Adjust the frame interpolation to move smoothly to the
// new position within the current tick.
Point3F cp = mDelta.pos + mDelta.posVec * mDelta.dt;
if (mDelta.dt == 0)
{
mDelta.posVec.set(0.0f, 0.0f, 0.0f);
mDelta.rotVec.set(0.0f, 0.0f, 0.0f);
}
else
{
F32 dti = 1.0f / mDelta.dt;
mDelta.posVec = (cp - pos) * dti;
mDelta.rotVec.z = mRot.z - rot.z;
mDelta.rotVec.z *= dti;
}
mDelta.pos = pos;
mDelta.rot = rot;
setTransform(pos, rot);
}*/
Point3F cp = mDelta.pos + mDelta.posVec * mDelta.dt;
mDelta.warpOffset = pos - cp;
@ -631,42 +683,101 @@ void Entity::unpackUpdate(NetConnection *con, BitStream *stream)
}
}
/*if (stream->readFlag())
{
Point3F mountOffset;
EulerF mountRot;
mathRead(*stream, &mountOffset);
mathRead(*stream, &mountRot);
RotationF rot = RotationF(mountRot);
mountRot = rot.asEulerF(RotationF::Degrees);
setMountOffset(mountOffset);
setMountRotation(mountRot);
}*/
if (stream->readFlag())
{
mathRead(*stream, &mObjBox);
resetWorldBox();
}
//AddComponentMask
if (stream->readFlag())
{
//are we passing any behaviors currently?
U32 addedComponentCount = stream->readInt(8);
for (U32 i = 0; i < addedComponentCount; i++)
{
char className[256] = "";
stream->readString(className);
//Change to components, so iterate our list and create any new components
// Well, looks like we have to create a new object.
const char* componentType = className;
ConsoleObject *object = ConsoleObject::create(componentType);
// Finally, set currentNewObject to point to the new one.
Component* newComponent = dynamic_cast<Component *>(object);
if (newComponent)
{
addComponent(newComponent);
}
}
}
//RemoveComponentMask
if (stream->readFlag())
{
}
//ComponentUpdateMask
if (stream->readFlag())
{
U32 updatingComponents = stream->readInt(8);
for (U32 i = 0; i < updatingComponents; i++)
{
U32 updateComponentIndex = stream->readInt(8);
Component* comp = mComponents[updateComponentIndex];
comp->unpackUpdate(con, stream);
}
}
/*if (stream->readFlag())
{
if (stream->readFlag())
{
//if we've just started the update, clear our behaviors
if (stream->readFlag())
clearComponents(false);
char name[256];
stream->readString(name);
assignName(name);
}
S32 componentCount = stream->readInt(16);
if (stream->readFlag())
{
char superClassname[256];
stream->readString(superClassname);
mSuperClassName = superClassname;
}
for (U32 i = 0; i < componentCount; i++)
{
S32 gIndex = stream->readInt(NetConnection::GhostIdBitSize);
addComponent(dynamic_cast<Component*>(con->resolveGhost(gIndex)));
}
if (stream->readFlag())
{
char classname[256];
stream->readString(classname);
mClassName = classname;
}
linkNamespaces();
}*/
}
void Entity::setComponentNetMask(Component* comp, U32 mask)
{
setMaskBits(Entity::ComponentsUpdateMask);
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
{
U32 netCompId = mComponents[mNetworkedComponents[i].componentIndex]->getId();
U32 compId = comp->getId();
if (netCompId == compId &&
(mNetworkedComponents[i].updateState == NetworkedComponent::None || mNetworkedComponents[i].updateState == NetworkedComponent::Updating))
{
mNetworkedComponents[i].updateState = NetworkedComponent::Updating;
mNetworkedComponents[i].updateMaskBits |= mask;
break;
}
}
}
@ -674,8 +785,7 @@ void Entity::unpackUpdate(NetConnection *con, BitStream *stream)
//Manipulation
void Entity::setTransform(const MatrixF &mat)
{
//setMaskBits(TransformMask);
setMaskBits(TransformMask | NoWarpMask);
MatrixF oldTransform = getTransform();
if (isMounted())
{
@ -687,25 +797,20 @@ void Entity::setTransform(const MatrixF &mat)
if (!newOffset.isZero())
{
//setMountOffset(newOffset);
mPos = newOffset;
}
Point3F matEul = mat.toEuler();
//mRot = Point3F(mRadToDeg(matEul.x), mRadToDeg(matEul.y), mRadToDeg(matEul.z));
if (matEul != Point3F(0, 0, 0))
{
Point3F mountEul = mMount.object->getTransform().toEuler();
Point3F diff = matEul - mountEul;
//setMountRotation(Point3F(mRadToDeg(diff.x), mRadToDeg(diff.y), mRadToDeg(diff.z)));
mRot = diff;
}
else
{
//setMountRotation(Point3F(0, 0, 0));
mRot = Point3F(0, 0, 0);
}
@ -714,6 +819,9 @@ void Entity::setTransform(const MatrixF &mat)
transf.setPosition(mPos + mMount.object->getPosition());
Parent::setTransform(transf);
if (transf != oldTransform)
setMaskBits(TransformMask);
}
else
{
@ -744,6 +852,8 @@ void Entity::setTransform(const MatrixF &mat)
void Entity::setTransform(Point3F position, RotationF rotation)
{
MatrixF oldTransform = getTransform();
if (isMounted())
{
mPos = position;
@ -755,7 +865,8 @@ void Entity::setTransform(Point3F position, RotationF rotation)
Parent::setTransform(transf);
setMaskBits(TransformMask);
if (transf != oldTransform)
setMaskBits(TransformMask);
}
else
{
@ -774,7 +885,6 @@ void Entity::setTransform(Point3F position, RotationF rotation)
mPos = position;
mRot = rotation;
setMaskBits(TransformMask);
//if (isServerObject())
// setMaskBits(TransformMask);
@ -788,19 +898,22 @@ void Entity::setTransform(Point3F position, RotationF rotation)
//PROFILE_SCOPE(Entity_setTransform);
// Update the transforms.
Parent::setTransform(newMat);
onTransformSet.trigger(&newMat);
U32 compCount = mComponents.size();
for (U32 i = 0; i < compCount; ++i)
{
mComponents[i]->ownerTransformSet(&newMat);
}
/*mObjToWorld = mWorldToObj = newMat;
mWorldToObj.affineInverse();
// Update the world-space AABB.
resetWorldBox();
// If we're in a SceneManager, sync our scene state.
if (mSceneManager != NULL)
mSceneManager->notifyObjectDirty(this);
setRenderTransform(newMat);*/
Point3F newPos = newMat.getPosition();
RotationF newRot = newMat;
Point3F oldPos = oldTransform.getPosition();
RotationF oldRot = oldTransform;
if (newPos != oldPos || newRot != oldRot)
setMaskBits(TransformMask);
}
}
@ -833,7 +946,11 @@ void Entity::setRenderTransform(Point3F position, RotationF rotation)
Parent::setRenderTransform(newMat);
onTransformSet.trigger(&newMat);
U32 compCount = mComponents.size();
for (U32 i = 0; i < compCount; ++i)
{
mComponents[i]->ownerTransformSet(&newMat);
}
}
}
@ -887,7 +1004,7 @@ void Entity::setMountRotation(EulerF rotOffset)
temp.setColumn(3, mMount.xfm.getPosition());
mMount.xfm = temp;
//mRot = RotationF(temp);
setMaskBits(MountedMask);
}
}
@ -964,63 +1081,6 @@ void Entity::getRenderMountTransform(F32 delta, S32 index, const MatrixF &xfm, M
Parent::getMountTransform(index, xfm, outMat);
}
void Entity::setForwardVector(VectorF newForward, VectorF upVector)
{
MatrixF mat = getTransform();
VectorF up(0.0f, 0.0f, 1.0f);
VectorF axisX;
VectorF axisY = newForward;
VectorF axisZ;
if (upVector != VectorF::Zero)
up = upVector;
// Validate and normalize input:
F32 lenSq;
lenSq = axisY.lenSquared();
if (lenSq < 0.000001f)
{
axisY.set(0.0f, 1.0f, 0.0f);
Con::errorf("Entity::setForwardVector() - degenerate forward vector");
}
else
{
axisY /= mSqrt(lenSq);
}
lenSq = up.lenSquared();
if (lenSq < 0.000001f)
{
up.set(0.0f, 0.0f, 1.0f);
Con::errorf("SceneObject::setForwardVector() - degenerate up vector - too small");
}
else
{
up /= mSqrt(lenSq);
}
if (fabsf(mDot(up, axisY)) > 0.9999f)
{
Con::errorf("SceneObject::setForwardVector() - degenerate up vector - same as forward");
// i haven't really tested this, but i think it generates something which should be not parallel to the previous vector:
F32 tmp = up.x;
up.x = -up.y;
up.y = up.z;
up.z = tmp;
}
// construct the remaining axes:
mCross(axisY, up, &axisX);
mCross(axisX, axisY, &axisZ);
mat.setColumn(0, axisX);
mat.setColumn(1, axisY);
mat.setColumn(2, axisZ);
setTransform(mat);
}
//
//These basically just redirect to any collision behaviors we have
bool Entity::castRay(const Point3F &start, const Point3F &end, RayInfo* info)
@ -1117,6 +1177,28 @@ void Entity::onUnmount(SceneObject *obj, S32 node)
}
}
void Entity::setControllingClient(GameConnection* client)
{
if (isGhost() && gSFX3DWorld)
{
if (gSFX3DWorld->getListener() == this && !client && getControllingClient() && getControllingClient()->isConnectionToServer())
{
// We are the current listener and are no longer a controller object on the
// connection, so clear our listener status.
gSFX3DWorld->setListener(NULL);
}
else if (client && client->isConnectionToServer() && !getControllingObject())
{
// We're on the local client and not controlled by another object, so make
// us the current SFX listener.
gSFX3DWorld->setListener(this);
}
}
Parent::setControllingClient(client);
}
//Heirarchy stuff
void Entity::addObject(SimObject* object)
{
@ -1223,11 +1305,28 @@ bool Entity::addComponent(Component *comp)
// Register the component with this owner.
comp->setOwner(this);
comp->setIsServerObject(isServerObject());
//if we've already been added and this is being added after the fact(at runtime),
//then just go ahead and call it's onComponentAdd so it can get to work
if (mInitialized)
//if (mInitialized)
{
comp->onComponentAdd();
if (comp->isNetworked())
{
NetworkedComponent netComp;
netComp.componentIndex = mComponents.size() - 1;
netComp.updateState = NetworkedComponent::Adding;
netComp.updateMaskBits = -1;
mNetworkedComponents.push_back(netComp);
setMaskBits(AddComponentsMask);
setMaskBits(ComponentsUpdateMask);
}
}
onComponentAdded.trigger(comp);
return true;
@ -1261,9 +1360,8 @@ bool Entity::removeComponent(Component *comp, bool deleteComponent)
onComponentRemoved.trigger(comp);
comp->setOwner(NULL);
comp->onComponentRemove(); //in case the behavior needs to do cleanup on the owner
comp->setOwner(NULL);
if (deleteComponent)
comp->safeDeleteObject();
@ -1338,7 +1436,7 @@ Component *Entity::getComponent(String componentType)
Namespace *NS = comp->getNamespace();
//we shouldn't ever go past Component into net object, as we're no longer dealing with component classes
while (dStrcmp(NS->getName(), "NetObject"))
while (dStrcmp(NS->getName(), "SimObject"))
{
String namespaceName = NS->getName();
@ -1364,72 +1462,6 @@ void Entity::onInspect()
{
(*it)->onInspect();
}
GuiTreeViewCtrl *editorTree = dynamic_cast<GuiTreeViewCtrl*>(Sim::findObject("EditorTree"));
if (!editorTree)
return;
GuiTreeViewCtrl::Item *newItem, *parentItem;
parentItem = editorTree->getItem(editorTree->findItemByObjectId(getId()));
S32 componentID = editorTree->insertItem(parentItem->getID(), "Components");
newItem = editorTree->getItem(componentID);
newItem->mState.set(GuiTreeViewCtrl::Item::VirtualParent);
newItem->mState.set(GuiTreeViewCtrl::Item::DenyDrag);
//newItem->mState.set(GuiTreeViewCtrl::Item::InspectorData);
newItem->mState.set(GuiTreeViewCtrl::Item::ForceItemName);
//newItem->mInspectorInfo.mObject = this;
AssetManager *assetDB = dynamic_cast<AssetManager*>(Sim::findObject("AssetDatabase"));
if (!assetDB)
return;
//This is used in the event of script-created assets, which likely only have
//the name and other 'friendly' properties stored in a ComponentAsset.
//So we'll do a query for those assets and find the asset based on the component's
//class name
AssetQuery* qry = new AssetQuery();
qry->registerObject();
assetDB->findAssetType(qry, "ComponentAsset");
for (U32 i = 0; i < mComponents.size(); ++i)
{
String compName = mComponents[i]->getFriendlyName();
if (compName == String(""))
{
String componentClass = mComponents[i]->getClassNamespace();
//Means that it's a script-derived component and we should consult the asset to try
//to get the info for it
S32 compAssetCount = qry->mAssetList.size();
for (U32 c = 0; c < compAssetCount; ++c)
{
StringTableEntry assetID = qry->mAssetList[c];
ComponentAsset* compAsset = assetDB->acquireAsset<ComponentAsset>(assetID);
String compAssetClass = compAsset->getComponentName();
if (componentClass == compAssetClass)
{
compName = compAsset->getFriendlyName();
break;
}
}
}
S32 compID = editorTree->insertItem(componentID, compName);
newItem = editorTree->getItem(compID);
newItem->mInspectorInfo.mObject = mComponents[i];
newItem->mState.set(GuiTreeViewCtrl::Item::ForceItemName);
newItem->mState.set(GuiTreeViewCtrl::Item::DenyDrag);
newItem->mState.set(GuiTreeViewCtrl::Item::InspectorData);
}
editorTree->buildVisibleTree(true);
}
void Entity::onEndInspect()
@ -1615,9 +1647,25 @@ void Entity::updateContainer()
}
//
void Entity::notifyComponents(String signalFunction, String argA, String argB, String argC, String argD, String argE)
{
for (U32 i = 0; i < mComponents.size(); i++)
{
// We can do this because both are in the string table
Component *comp = mComponents[i];
if (comp->isActive())
{
if (comp->isMethod(signalFunction))
Con::executef(comp, signalFunction, argA, argB, argC, argD, argE);
}
}
}
void Entity::setComponentsDirty()
{
if (mToLoadComponents.empty())
bool tmp = true;
/*if (mToLoadComponents.empty())
mStartComponentUpdate = true;
//we need to build a list of behaviors that need to be pushed across the network
@ -1642,7 +1690,7 @@ void Entity::setComponentsDirty()
}
}
setMaskBits(ComponentsMask);
setMaskBits(ComponentsMask);*/
}
void Entity::setComponentDirty(Component *comp, bool forceUpdate)
@ -1833,7 +1881,6 @@ DefineConsoleMethod(Entity, getComponent, S32, (String componentName), (""),
Component *comp = object->getComponent(componentName);
return (comp != NULL) ? comp->getId() : 0;
return 0;
}
/*ConsoleMethod(Entity, getBehaviorByType, S32, 3, 3, "(string BehaviorTemplateName) - gets a behavior\n"
@ -1917,6 +1964,15 @@ DefineConsoleMethod(Entity, getMoveTrigger, bool, (S32 triggerNum), (0),
return false;
}
DefineEngineMethod(Entity, getForwardVector, VectorF, (), ,
"Get the direction this object is facing.\n"
"@return a vector indicating the direction this object is facing.\n"
"@note This is the object's y axis.")
{
VectorF forVec = object->getTransform().getForwardVector();
return forVec;
}
DefineConsoleMethod(Entity, setForwardVector, void, (VectorF newForward), (VectorF(0,0,0)),
"Get the number of static fields on the object.\n"
"@return The number of static fields defined on the object.")
@ -1936,4 +1992,53 @@ DefineConsoleMethod(Entity, rotateTo, void, (Point3F lookPosition, F32 degreePer
"@return The number of static fields defined on the object.")
{
//object->setForwardVector(newForward);
}
DefineConsoleMethod(Entity, notify, void, (String signalFunction, String argA, String argB, String argC, String argD, String argE),
("", "", "", "", "", ""),
"Triggers a signal call to all components for a certain function.")
{
if (signalFunction == String(""))
return;
object->notifyComponents(signalFunction, argA, argB, argC, argD, argE);
}
DefineConsoleFunction(findEntitiesByTag, const char*, (SimGroup* searchingGroup, String tags), (nullAsType<SimGroup*>(), ""),
"Finds all entities that have the provided tags.\n"
"@param searchingGroup The SimGroup to search inside. If null, we'll search the entire dictionary(this can be slow!).\n"
"@param tags Word delimited list of tags to search for. If multiple tags are included, the list is eclusively parsed, requiring all tags provided to be found on an entity for a match.\n"
"@return A word list of IDs of entities that match the tag search terms.")
{
//if (tags.isEmpty())
return "";
/*if (searchingGroup == nullptr)
{
searchingGroup = Sim::getRootGroup();
}
StringTableEntry entityStr = StringTable->insert("Entity");
std::thread threadBob;
std::thread::id a = threadBob.get_id();
std::thread::id b = std::this_thread::get_id().;
if (a == b)
{
//do
}
for (SimGroup::iterator itr = searchingGroup->begin(); itr != searchingGroup->end(); itr++)
{
Entity* ent = dynamic_cast<Entity*>((*itr));
if (ent != nullptr)
{
ent->mTags.
}
}
object->notifyComponents(signalFunction, argA, argB, argC, argD, argE);*/
}

View file

@ -35,6 +35,12 @@
#ifndef _CONTAINERQUERY_H_
#include "T3D/containerQuery.h"
#endif
#ifndef _ASSET_PTR_H_
#include "assets/assetPtr.h"
#endif
#ifndef GAME_OBJECT_ASSET_H
#include "T3D/assets/GameObjectAsset.h"
#endif
class Component;
@ -52,18 +58,43 @@ private:
Vector<Component*> mComponents;
Vector<Component*> mToLoadComponents;
//Bit of helper data to let us track and manage the adding, removal and updating of networked components
struct NetworkedComponent
{
U32 componentIndex;
enum UpdateState
{
None,
Adding,
Removing,
Updating
};
UpdateState updateState;
U32 updateMaskBits;
};
Vector<NetworkedComponent> mNetworkedComponents;
U32 mComponentNetMask;
bool mStartComponentUpdate;
StringTableEntry mGameObjectAssetId;
AssetPtr<GameObjectAsset> mGameObjectAsset;
ContainerQueryInfo containerInfo;
bool mInitialized;
String mTags;
Signal< void(Component*) > onComponentAdded;
Signal< void(Component*) > onComponentRemoved;
Signal< void(MatrixF*) > onTransformSet;
S32 mLifetimeMS;
protected:
@ -96,9 +127,12 @@ public:
{
TransformMask = Parent::NextFreeMask << 0,
BoundsMask = Parent::NextFreeMask << 1,
ComponentsMask = Parent::NextFreeMask << 2,
NoWarpMask = Parent::NextFreeMask << 3,
NextFreeMask = Parent::NextFreeMask << 4
ComponentsUpdateMask = Parent::NextFreeMask << 2,
AddComponentsMask = Parent::NextFreeMask << 3,
RemoveComponentsMask = Parent::NextFreeMask << 4,
NoWarpMask = Parent::NextFreeMask << 5,
NamespaceMask = Parent::NextFreeMask << 6,
NextFreeMask = Parent::NextFreeMask << 7
};
StateDelta mDelta;
@ -106,6 +140,8 @@ public:
Move lastMove;
S32 mStartTimeMS;
//
Entity();
~Entity();
@ -123,16 +159,14 @@ public:
virtual MatrixF getTransform();
virtual Point3F getPosition() const { return mPos; }
//void setTransform(Point3F position, RotationF rot);
//void setRotation(RotationF rotation);
void setRotation(RotationF rotation) {
mRot = rotation;
setMaskBits(TransformMask);
};
RotationF getRotation() { return mRot; }
static bool _setGameObject(void *object, const char *index, const char *data);
void setMountOffset(Point3F posOffset);
void setMountRotation(EulerF rotOffset);
@ -146,13 +180,18 @@ public:
virtual void getMountTransform(S32 index, const MatrixF &xfm, MatrixF *outMat);
virtual void getRenderMountTransform(F32 delta, S32 index, const MatrixF &xfm, MatrixF *outMat);
void setForwardVector(VectorF newForward, VectorF upVector = VectorF::Zero);
virtual void mountObject(SceneObject *obj, S32 node, const MatrixF &xfm = MatrixF::Identity);
void mountObject(SceneObject* objB, MatrixF txfm);
void onMount(SceneObject *obj, S32 node);
void onUnmount(SceneObject *obj, S32 node);
/// Sets the client controlling this object
/// @param client Client that is now controlling this object
virtual void setControllingClient(GameConnection *client);
//
//Networking
//
// NetObject
U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream);
void unpackUpdate(NetConnection *conn, BitStream *stream);
@ -160,9 +199,13 @@ public:
void setComponentsDirty();
void setComponentDirty(Component *comp, bool forceUpdate = false);
void setComponentNetMask(Component* comp, U32 mask);
//Components
virtual bool deferAddingComponents() const { return true; }
void notifyComponents(String signalFunction, String argA, String argB, String argC, String argD, String argE);
template <class T>
T* getComponent();
template <class T>

View file

@ -44,10 +44,8 @@
#include "console/engineAPI.h"
#include "math/mTransform.h"
#ifdef TORQUE_EXPERIMENTAL_EC
#include "T3D/entity.h"
#include "T3D/components/coreInterfaces.h"
#endif
#ifdef TORQUE_HIFI_NET
#include "T3D/gameBase/hifi/hifiMoveList.h"
@ -789,7 +787,6 @@ bool GameConnection::getControlCameraFov(F32 * fov)
}
if (cObj)
{
#ifdef TORQUE_EXPERIMENTAL_EC
if (Entity* ent = dynamic_cast<Entity*>(cObj))
{
if (CameraInterface* camInterface = ent->getComponent<CameraInterface>())
@ -799,11 +796,9 @@ bool GameConnection::getControlCameraFov(F32 * fov)
}
else
{
*fov = cObj->getCameraFov();
*fov = cObj->getCameraFov();
}
#else
*fov = cObj->getCameraFov();
#endif
return(true);
}
@ -823,7 +818,6 @@ bool GameConnection::isValidControlCameraFov(F32 fov)
if (cObj)
{
#ifdef TORQUE_EXPERIMENTAL_EC
if (Entity* ent = dynamic_cast<Entity*>(cObj))
{
if (CameraInterface* camInterface = ent->getComponent<CameraInterface>())
@ -835,9 +829,6 @@ bool GameConnection::isValidControlCameraFov(F32 fov)
{
return cObj->isValidCameraFov(fov);
}
#else
return cObj->isValidCameraFov(fov);
#endif
}
return NULL;
@ -855,8 +846,6 @@ bool GameConnection::setControlCameraFov(F32 fov)
}
if (cObj)
{
#ifdef TORQUE_EXPERIMENTAL_EC
F32 newFov = 90.f;
if (Entity* ent = dynamic_cast<Entity*>(cObj))
{
@ -876,11 +865,6 @@ bool GameConnection::setControlCameraFov(F32 fov)
cObj->setCameraFov(mClampF(fov, MinCameraFov, MaxCameraFov));
newFov = cObj->getCameraFov();
}
#else
// allow shapebase to clamp fov to its datablock values
cObj->setCameraFov(mClampF(fov, MinCameraFov, MaxCameraFov));
F32 newFov = cObj->getCameraFov();
#endif
// server fov of client has 1degree resolution
if( S32(newFov) != S32(mCameraFov) || newFov != fov )

View file

@ -32,10 +32,8 @@
#include "platform/profiler.h"
#include "console/consoleTypes.h"
#ifdef TORQUE_EXPERIMENTAL_EC
#include "T3D/components/coreInterfaces.h"
#include "T3D/components/component.h"
#endif
//----------------------------------------------------------------------------
ProcessObject::ProcessObject()
@ -277,12 +275,10 @@ void ProcessList::advanceObjects()
onTickObject(pobj);
}
#ifdef TORQUE_EXPERIMENTAL_EC
for (U32 i = 0; i < UpdateInterface::all.size(); i++)
{
UpdateInterface::all[i]->processTick();
}
#endif
mTotalTicks++;

View file

@ -37,10 +37,8 @@
#include "T3D/gameBase/std/stdMoveList.h"
#include "T3D/fx/cameraFXMgr.h"
#ifdef TORQUE_EXPERIMENTAL_EC
#include "T3D/components/coreInterfaces.h"
#include "T3D/components/component.h"
#endif
MODULE_BEGIN( ProcessList )
@ -137,7 +135,6 @@ bool StdClientProcessList::advanceTime( SimTime timeDelta )
obj = obj->mProcessLink.next;
}
#ifdef TORQUE_EXPERIMENTAL_EC
for (U32 i = 0; i < UpdateInterface::all.size(); i++)
{
Component *comp = dynamic_cast<Component*>(UpdateInterface::all[i]);
@ -147,7 +144,6 @@ bool StdClientProcessList::advanceTime( SimTime timeDelta )
UpdateInterface::all[i]->interpolateTick(mLastDelta);
}
#endif
// Inform objects of total elapsed delta so they can advance
// client side animations.
@ -163,7 +159,6 @@ bool StdClientProcessList::advanceTime( SimTime timeDelta )
obj = obj->mProcessLink.next;
}
#ifdef TORQUE_EXPERIMENTAL_EC
for (U32 i = 0; i < UpdateInterface::all.size(); i++)
{
Component *comp = dynamic_cast<Component*>(UpdateInterface::all[i]);
@ -176,7 +171,6 @@ bool StdClientProcessList::advanceTime( SimTime timeDelta )
UpdateInterface::all[i]->advanceTime(dt);
}
#endif
return ret;
}

View file

@ -1209,7 +1209,7 @@ DefineEngineMethod( Item, isRotating, bool, (),,
return object->isRotating();
}
DefineEngineMethod( Item, setCollisionTimeout, bool, (S32 ignoreColObj),(NULL),
DefineEngineMethod( Item, setCollisionTimeout, bool, (S32 ignoreColObj),,
"@brief Temporarily disable collisions against a specific ShapeBase object.\n\n"
"This is useful to prevent a player from immediately picking up an Item they have "

View file

@ -4405,7 +4405,7 @@ DefineEngineMethod( ShapeBase, getEyeTransform, TransformF, (),,
return mat;
}
DefineEngineMethod( ShapeBase, getLookAtPoint, const char*, ( F32 distance, S32 typeMask ), ( 2000, 0xFFFFFFFF ),
DefineEngineMethod( ShapeBase, getLookAtPoint, const char*, ( F32 distance, U32 typeMask ), ( 2000, 0xFFFFFFFF ),
"@brief Get the world position this object is looking at.\n\n"
"Casts a ray from the eye and returns information about what the ray hits.\n"

View file

@ -0,0 +1,30 @@
#pragma once
#include "console/engineAPI.h"
template<typename T>
class SystemInterface
{
public:
bool mIsEnabled;
bool mIsServer;
static Vector<T*> all;
SystemInterface()
{
all.push_back((T*)this);
}
virtual ~SystemInterface()
{
for (U32 i = 0; i < all.size(); i++)
{
if (all[i] == (T*)this)
{
all.erase(i);
return;
}
}
}
};
template<typename T> Vector<T*> SystemInterface<T>::all(0);

View file

@ -0,0 +1,375 @@
#include "T3D/systems/render/meshRenderSystem.h"
#include "gfx/gfxTransformSaver.h"
#include "lighting/lightQuery.h"
#include "renderInstance/renderPassManager.h"
#include "materials/materialManager.h"
#include "materials/baseMatInstance.h"
Vector<MeshRenderSystem::BufferMaterials> MeshRenderSystem::mBufferMaterials(0);
Vector<MeshRenderSystem::BufferSet> MeshRenderSystem::mStaticBuffers(0);
void MeshRenderSystem::render(SceneManager *sceneManager, SceneRenderState* state)
{
Frustum viewFrustum = state->getCullingFrustum();
MatrixF camTransform = state->getCameraTransform();
U32 count = MeshRenderSystemInterface::all.size();
for (U32 i = 0; i < count; i++)
{
//Server side items exist for data, but we don't actually render them
bool isClient = MeshRenderSystemInterface::all[i]->mIsClient;
if (!MeshRenderSystemInterface::all[i]->mIsClient)
continue;
bool isStatic = MeshRenderSystemInterface::all[i]->mStatic;
if (MeshRenderSystemInterface::all[i]->mStatic)
continue;
//First, do frustum culling
if (viewFrustum.isCulled(MeshRenderSystemInterface::all[i]->mBounds))
continue;
// Set the query box for the container query. Never
// make it larger than the frustum's AABB. In the editor,
// always query the full frustum as that gives objects
// the opportunity to render editor visualizations even if
// they are otherwise not in view.
if (!state->getCullingFrustum().getBounds().isOverlapped(state->getRenderArea()))
{
// This handles fringe cases like flying backwards into a zone where you
// end up pretty much standing on a zone border and looking directly into
// its "walls". In that case the traversal area will be behind the frustum
// (remember that the camera isn't where visibility starts, it's the near
// distance).
continue;
}
//We can then sort our objects by range since we have it already, so we can do occlusion culling be rendering front-to-back
//if we've made it this far, call down to the render function to actually display our stuff
renderInterface(i, state);
}
//Static Batch rendering
if ( /*!mMaterialInst ||*/ !state)
return;
BaseMatInstance *matInst = MATMGR->getWarningMatInstance();
// Get a handy pointer to our RenderPassmanager
RenderPassManager *renderPass = state->getRenderPass();
for (U32 i = 0; i < mStaticBuffers.size(); i++)
{
for (U32 b = 0; b < mStaticBuffers[i].buffers.size(); b++)
{
if (mStaticBuffers[i].buffers[b].vertData.empty())
continue;
MeshRenderInst *ri = renderPass->allocInst<MeshRenderInst>();
// Set our RenderInst as a standard mesh render
ri->type = RenderPassManager::RIT_Mesh;
//If our material has transparency set on this will redirect it to proper render bin
if (matInst->getMaterial()->isTranslucent())
{
ri->type = RenderPassManager::RIT_Translucent;
ri->translucentSort = true;
}
// Calculate our sorting point
if (state)
{
// Calculate our sort point manually.
const Box3F& rBox = Box3F(1000);// getRenderWorldBox();
ri->sortDistSq = rBox.getSqDistanceToPoint(state->getCameraPosition());
}
else
ri->sortDistSq = 0.0f;
// Set up our transforms
MatrixF objectToWorld = MatrixF::Identity;//getRenderTransform();
//objectToWorld.scale(getScale());
ri->objectToWorld = renderPass->allocUniqueXform(objectToWorld);
ri->worldToCamera = renderPass->allocSharedXform(RenderPassManager::View);
ri->projection = renderPass->allocSharedXform(RenderPassManager::Projection);
// If our material needs lights then fill the RIs
// light vector with the best lights.
/*if (matInst->isForwardLit())
{
LightQuery query;
query.init(getWorldSphere());
query.getLights(ri->lights, 8);
}*/
// Make sure we have an up-to-date backbuffer in case
// our Material would like to make use of it
// NOTICE: SFXBB is removed and refraction is disabled!
//ri->backBuffTex = GFX->getSfxBackBuffer();
// Set our Material
ri->matInst = matInst;
// Set up our vertex buffer and primitive buffer
ri->vertBuff = &mStaticBuffers[i].buffers[b].vertexBuffer;
ri->primBuff = &mStaticBuffers[i].buffers[b].primitiveBuffer;
ri->prim = renderPass->allocPrim();
ri->prim->type = GFXTriangleList;
ri->prim->minIndex = 0;
ri->prim->startIndex = 0;
ri->prim->numPrimitives = mStaticBuffers[i].buffers[b].primData.size();
ri->prim->startVertex = 0;
ri->prim->numVertices = mStaticBuffers[i].buffers[b].vertData.size();
// We sort by the material then vertex buffer
ri->defaultKey = matInst->getStateHint();
ri->defaultKey2 = (uintptr_t)ri->vertBuff; // Not 64bit safe!
// Submit our RenderInst to the RenderPassManager
state->getRenderPass()->addInst(ri);
}
}
}
void MeshRenderSystem::renderInterface(U32 interfaceIndex, SceneRenderState* state)
{
//Fetch
MeshRenderSystemInterface* interface = MeshRenderSystemInterface::all[interfaceIndex];
if (interface->mShapeInstance == nullptr)
return;
Point3F cameraOffset;
interface->mTransform.getColumn(3, &cameraOffset);
cameraOffset -= state->getDiffuseCameraPosition();
F32 dist = cameraOffset.len();
if (dist < 0.01f)
dist = 0.01f;
Point3F objScale = interface->mScale;
F32 invScale = (1.0f / getMax(getMax(objScale.x, objScale.y), objScale.z));
interface->mShapeInstance->setDetailFromDistance(state, dist * invScale);
if (interface->mShapeInstance->getCurrentDetail() < 0)
return;
GFXTransformSaver saver;
// Set up our TS render state.
TSRenderState rdata;
rdata.setSceneState(state);
rdata.setFadeOverride(1.0f);
rdata.setOriginSort(false);
// We might have some forward lit materials
// so pass down a query to gather lights.
LightQuery query;
query.init(interface->mSphere);
rdata.setLightQuery(&query);
MatrixF mat = interface->mTransform;
mat.scale(objScale);
GFX->setWorldMatrix(mat);
interface->mShapeInstance->render(rdata);
}
void MeshRenderSystem::rebuildBuffers()
{
U32 BUFFER_SIZE = 65000;
Vector<U32> tempIndices;
tempIndices.reserve(4);
Box3F newBounds = Box3F::Zero;
mStaticBuffers.clear();
for (U32 i = 0; i < MeshRenderSystemInterface::all.size(); i++)
{
if (!MeshRenderSystemInterface::all[i]->mIsEnabled)
continue;
if (!MeshRenderSystemInterface::all[i]->mIsClient || !MeshRenderSystemInterface::all[i]->mStatic)
continue;
//TODO: Properly re-implement StaticElements to container owner interfaces and buffer sets
for (U32 j = 0; j < MeshRenderSystemInterface::all[i]->mGeometry.mPolyList.size(); j++)
{
const OptimizedPolyList::Poly& poly = MeshRenderSystemInterface::all[i]->mGeometry.mPolyList[j];
if (poly.vertexCount < 3)
continue;
tempIndices.setSize(poly.vertexCount);
dMemset(tempIndices.address(), 0, poly.vertexCount);
if (poly.type == OptimizedPolyList::TriangleStrip ||
poly.type == OptimizedPolyList::TriangleFan)
{
tempIndices[0] = 0;
U32 idx = 1;
for (U32 k = 1; k < poly.vertexCount; k += 2)
tempIndices[idx++] = k;
for (U32 k = ((poly.vertexCount - 1) & (~0x1)); k > 0; k -= 2)
tempIndices[idx++] = k;
}
else if (poly.type == OptimizedPolyList::TriangleList)
{
for (U32 k = 0; k < poly.vertexCount; k++)
tempIndices[k] = k;
}
else
continue;
//got our data, now insert it into the correct buffer!
S32 bufferId = findBufferSetByMaterial(poly.material);
if (bufferId == -1)
{
//add a new buffer set if we didn't get a match!
BufferSet newSet;
newSet.surfaceMaterialId = poly.material;
mStaticBuffers.push_back(newSet);
bufferId = mStaticBuffers.size() - 1;
}
//see if this would push us over our buffer size limit, if it is, make a new buffer for this set
if (mStaticBuffers[bufferId].buffers.last().vertData.size() + 3 > BUFFER_SIZE
|| mStaticBuffers[bufferId].buffers.last().primData.size() + 1 > BUFFER_SIZE)
{
//yep, we'll overstep with this, so spool up a new buffer in this set
BufferSet::Buffers newBuffer = BufferSet::Buffers();
mStaticBuffers[bufferId].buffers.push_back(newBuffer);
}
const U32& firstIdx = MeshRenderSystemInterface::all[i]->mGeometry.mIndexList[poly.vertexStart];
const OptimizedPolyList::VertIndex& firstVertIdx = MeshRenderSystemInterface::all[i]->mGeometry.mVertexList[firstIdx];
//Vector<Point3F> geomPoints = MeshRenderSystemInterface::all[i]->mGeometry.mPoints;
//Vector<Point3F> geomNormals = MeshRenderSystemInterface::all[i]->mGeometry.mNormals;
//Vector<Point2F> geoUVs = MeshRenderSystemInterface::all[i]->mGeometry.mUV0s;
for (U32 k = 1; k < poly.vertexCount - 1; k++)
{
const U32& secondIdx = MeshRenderSystemInterface::all[i]->mGeometry.mIndexList[poly.vertexStart + tempIndices[k]];
const U32& thirdIdx = MeshRenderSystemInterface::all[i]->mGeometry.mIndexList[poly.vertexStart + tempIndices[k + 1]];
const OptimizedPolyList::VertIndex& secondVertIdx = MeshRenderSystemInterface::all[i]->mGeometry.mVertexList[secondIdx];
const OptimizedPolyList::VertIndex& thirdVertIdx = MeshRenderSystemInterface::all[i]->mGeometry.mVertexList[thirdIdx];
Point3F points[3];
points[0] = MeshRenderSystemInterface::all[i]->mGeometry.mPoints[firstVertIdx.vertIdx];
points[1] = MeshRenderSystemInterface::all[i]->mGeometry.mPoints[secondVertIdx.vertIdx];
points[2] = MeshRenderSystemInterface::all[i]->mGeometry.mPoints[thirdVertIdx.vertIdx];
Point3F normals[3];
normals[0] = MeshRenderSystemInterface::all[i]->mGeometry.mNormals[firstVertIdx.normalIdx];
normals[1] = MeshRenderSystemInterface::all[i]->mGeometry.mNormals[secondVertIdx.normalIdx];
normals[2] = MeshRenderSystemInterface::all[i]->mGeometry.mNormals[thirdVertIdx.normalIdx];
Point3F tangents[3];
tangents[0] = mCross(points[1] - points[0], normals[0]);
tangents[1] = mCross(points[2] - points[1], normals[1]);
tangents[2] = mCross(points[0] - points[2], normals[2]);
Point2F uvs[3];
uvs[0] = MeshRenderSystemInterface::all[i]->mGeometry.mUV0s[firstVertIdx.uv0Idx];
uvs[1] = MeshRenderSystemInterface::all[i]->mGeometry.mUV0s[secondVertIdx.uv0Idx];
uvs[2] = MeshRenderSystemInterface::all[i]->mGeometry.mUV0s[thirdVertIdx.uv0Idx];
mStaticBuffers[bufferId].vertCount += 3;
mStaticBuffers[bufferId].primCount += 1;
for (U32 v = 0; v < 3; ++v)
{
//Build the vert and store it to the buffers!
GFXVertexPNTT bufVert;
bufVert.point = points[v];
bufVert.normal = normals[v];
bufVert.tangent = tangents[v];
bufVert.texCoord = uvs[v];
newBounds.extend(points[v]);
mStaticBuffers[bufferId].buffers.last().vertData.push_back(bufVert);
U32 vertPrimId = mStaticBuffers[bufferId].buffers.last().vertData.size() - 1;
mStaticBuffers[bufferId].buffers.last().primData.push_back(vertPrimId);
mStaticBuffers[bufferId].center += points[v];
}
}
}
}
//Now, iterate through the organized data and turn them into renderable buffers
for (U32 i = 0; i < mStaticBuffers.size(); i++)
{
for (U32 b = 0; b < mStaticBuffers[i].buffers.size(); b++)
{
BufferSet::Buffers& buffers = mStaticBuffers[i].buffers[b];
//if there's no data to be had in this buffer, just skip it
if (buffers.vertData.empty())
continue;
buffers.vertexBuffer.set(GFX, buffers.vertData.size(), GFXBufferTypeStatic);
GFXVertexPNTT *pVert = buffers.vertexBuffer.lock();
for (U32 v = 0; v < buffers.vertData.size(); v++)
{
pVert->normal = buffers.vertData[v].normal;
pVert->tangent = buffers.vertData[v].tangent;
//pVert->color = buffers.vertData[v].color;
pVert->point = buffers.vertData[v].point;
pVert->texCoord = buffers.vertData[v].texCoord;
pVert++;
}
buffers.vertexBuffer.unlock();
// Allocate PB
buffers.primitiveBuffer.set(GFX, buffers.primData.size(), buffers.primData.size() / 3, GFXBufferTypeStatic);
U16 *pIndex;
buffers.primitiveBuffer.lock(&pIndex);
for (U16 i = 0; i < buffers.primData.size(); i++)
{
*pIndex = i;
pIndex++;
}
buffers.primitiveBuffer.unlock();
}
mStaticBuffers[i].center /= mStaticBuffers[i].vertCount;
}
//mObjBox = newBounds;
//resetWorldBox();
}
U32 MeshRenderSystem::findBufferSetByMaterial(U32 matId)
{
for (U32 i = 0; i < mStaticBuffers.size(); i++)
{
if (mStaticBuffers[i].surfaceMaterialId == matId)
return i;
}
return -1;
}

View file

@ -0,0 +1,207 @@
#pragma once
#include "scene/sceneRenderState.h"
#include "T3D/systems/componentSystem.h"
#include "ts/tsShape.h"
#include "ts/tsShapeInstance.h"
#include "T3D/assets/ShapeAsset.h"
#include "T3D/assets/MaterialAsset.h"
#ifndef _GFXVERTEXBUFFER_H_
#include "gfx/gfxVertexBuffer.h"
#endif
#ifndef _GFXPRIMITIVEBUFFER_H_
#include "gfx/gfxPrimitiveBuffer.h"
#endif
#ifndef _OPTIMIZEDPOLYLIST_H_
#include "collision/optimizedPolyList.h"
#endif
class MeshRenderSystemInterface : public SystemInterface<MeshRenderSystemInterface>
{
public:
TSShapeInstance * mShapeInstance;
MatrixF mTransform;
Point3F mScale;
Box3F mBounds;
SphereF mSphere;
bool mIsClient;
struct matMap
{
//MaterialAsset* matAsset;
String assetId;
U32 slot;
};
Vector<matMap> mChangingMaterials;
Vector<matMap> mMaterials;
//Static geometry stuff
bool mStatic;
OptimizedPolyList mGeometry;
MeshRenderSystemInterface() : SystemInterface(), mShapeInstance(nullptr), mTransform(MatrixF::Identity), mScale(Point3F::One), mIsClient(false), mStatic(false)
{
mBounds = Box3F(1);
mSphere = SphereF();
}
~MeshRenderSystemInterface()
{
//SAFE_DELETE(mShape);
SAFE_DELETE(mShapeInstance);
}
};
class MeshRenderSystem
{
protected:
/*struct StaticBatchElement
{
SimObject* owner;
OptimizedPolyList geometry;
String batchName;
};
static Vector<StaticBatchElement> mStaticElements;*/
//We retain the pushed geometry data for rendering here. It's static(unless forced to change through editing or whatnot)
//so rendering the batches is real fast
struct BufferMaterials
{
// The name of the Material we will use for rendering
String mMaterialName;
// The actual Material instance
BaseMatInstance* mMaterialInst;
BufferMaterials()
{
mMaterialName = "";
mMaterialInst = NULL;
}
};
static Vector<BufferMaterials> mBufferMaterials;
struct BufferSet
{
U32 surfaceMaterialId;
U32 vertCount;
U32 primCount;
Point3F center;
struct Buffers
{
U32 vertStart;
U32 primStart;
U32 vertCount;
U32 primCount;
Vector<GFXVertexPNTT> vertData;
Vector<U32> primData;
GFXVertexBufferHandle< GFXVertexPNTT > vertexBuffer;
GFXPrimitiveBufferHandle primitiveBuffer;
Buffers()
{
vertStart = 0;
primStart = 0;
vertCount = 0;
primCount = 0;
vertexBuffer = NULL;
primitiveBuffer = NULL;
}
};
Vector<Buffers> buffers;
BufferSet()
{
Buffers newBuffer;
buffers.push_back(newBuffer);
surfaceMaterialId = 0;
vertCount = 0;
primCount = 0;
center = Point3F::Zero;
}
};
static Vector<BufferSet> mStaticBuffers;
public:
/*virtual void prepRenderImage(SceneRenderState *state);
bool setMeshAsset(const char* assetName);
virtual TSShape* getShape() { if (mMeshAsset) return mMeshAsset->getShape(); else return NULL; }
virtual TSShapeInstance* getShapeInstance() { return mShapeInstance; }
Resource<TSShape> getShapeResource() { return mMeshAsset->getShapeResource(); }
void _onResourceChanged(const Torque::Path &path);
virtual bool castRayRendered(const Point3F &start, const Point3F &end, RayInfo *info);
void mountObjectToNode(SceneObject* objB, String node, MatrixF txfm);
virtual void onDynamicModified(const char* slotName, const char* newValue);
void changeMaterial(U32 slot, MaterialAsset* newMat);
bool setMatInstField(U32 slot, const char* field, const char* value);
virtual void onInspect();
virtual void onEndInspect();
virtual Vector<MatrixF> getNodeTransforms()
{
Vector<MatrixF> bob;
return bob;
}
virtual void setNodeTransforms(Vector<MatrixF> transforms)
{
return;
}*/
/*MeshRenderSystem()
{
}
virtual ~MeshRenderSystem()
{
smInterfaceList.clear();
}
static MeshComponentInterface* GetNewInterface()
{
smInterfaceList.increment();
return &smInterfaceList.last();
}
static void RemoveInterface(T* q)
{
smInterfaceList.erase(q);
}*/
//Core render function, which does all the real work
static void render(SceneManager *sceneManager, SceneRenderState* state);
//Render our particular interface's data
static void renderInterface(U32 interfaceIndex, SceneRenderState* state);
//Static Batch rendering
static void rebuildBuffers();
static U32 findBufferSetByMaterial(U32 matId);
};

View file

@ -0,0 +1,34 @@
#include "T3D/systems/updateSystem.h"
void UpdateSystem::processTick()
{
for (U32 i = 0; i < UpdateSystemInterface::all.size(); i++)
{
if (UpdateSystemInterface::all[i]->mIsEnabled)
{
//do work
}
}
}
void UpdateSystem::advanceTime(U32 _tickMS)
{
for (U32 i = 0; i < UpdateSystemInterface::all.size(); i++)
{
if (UpdateSystemInterface::all[i]->mIsEnabled)
{
//do work
}
}
}
void UpdateSystem::interpolateTick(U32 _deltaMS)
{
for (U32 i = 0; i < UpdateSystemInterface::all.size(); i++)
{
if (UpdateSystemInterface::all[i]->mIsEnabled)
{
//do work
}
}
}

View file

@ -0,0 +1,16 @@
#pragma once
#include "componentSystem.h"
class UpdateSystemInterface : public SystemInterface<UpdateSystemInterface>
{
public:
bool mIsEnabled;
};
class UpdateSystem
{
public:
static void processTick();
static void advanceTime(U32 _tickMS);
static void interpolateTick(U32 _deltaMS);
};