diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.cs b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.cs index ae1a08fc1..1269eab28 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.cs +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.cs @@ -333,17 +333,7 @@ function AssetBrowser::buildAssetPreview( %this, %asset, %moduleName ) //special-case entry if(getFieldCount(%asset) > 1) { - %specialType = getField(%asset,0); - - /*if(%specialType $= "Folder") - { - - } - else if(%specialType $= "Datablock") - { - %sdfasdgah = true; - }*/ - %assetType = %specialType; + %assetType = getField(%asset,0); %assetName = getField(%asset, 1); %sdfasdgah = true; @@ -389,6 +379,38 @@ function AssetBrowser::buildAssetPreview( %this, %asset, %moduleName ) %fullPath = strreplace(%fullPath, "/", "_"); %fullPath = strreplace(%fullPath, ".", "-"); + if(isObject(%fullPath)) + %assetDesc = %fullPath; + else + %assetDesc = new ScriptObject(%fullPath); + + %assetDesc.dirPath = %moduleName; + %assetDesc.assetName = %assetName; + %assetDesc.description = %moduleName @ "/" @ %assetName; + %assetDesc.assetType = %assetType; + } + else if(%assetType $= "Cpp") + { + %fullPath = %moduleName !$= "" ? %moduleName @ "/" @ %assetName : %assetName; + %fullPath = strreplace(%fullPath, "/", "_"); + %fullPath = strreplace(%fullPath, ".", "-"); + + if(isObject(%fullPath)) + %assetDesc = %fullPath; + else + %assetDesc = new ScriptObject(%fullPath); + + %assetDesc.dirPath = %moduleName; + %assetDesc.assetName = %assetName; + %assetDesc.description = %moduleName @ "/" @ %assetName; + %assetDesc.assetType = %assetType; + } + else if(%assetType $= "tscript") + { + %fullPath = %moduleName !$= "" ? %moduleName @ "/" @ %assetName : %assetName; + %fullPath = strreplace(%fullPath, "/", "_"); + %fullPath = strreplace(%fullPath, ".", "-"); + if(isObject(%fullPath)) %assetDesc = %fullPath; else @@ -1568,6 +1590,7 @@ function AssetBrowser::doRebuildAssetArray(%this) %looseFileFullPath = ABLooseFileArray.getKey(%i); %looseFilePath = filePath(%looseFileFullPath); %looseFileName = fileName(%looseFileFullPath); + %looseFileExt = fileExt(%looseFileFullPath); %assetArray.add( %looseFilePath, "LooseFile" TAB %looseFileName ); } @@ -1599,6 +1622,78 @@ function AssetBrowser::doRebuildAssetArray(%this) %fullPrefabPath = findNextFile( %breadcrumbPath @ "/" @ %expr ); } + + //C++ files + %cppPattern = %breadcrumbPath @ "/" @ "*.cpp"; + for (%fullCppPath = findFirstFile(%cppPattern); %fullCppPath !$= ""; %fullCppPath = findNextFile(%cppPattern)) + { + %cppPath = filePath(%fullCppPath); + %cppName = fileName(%fullCppPath); + + %searchActive = AssetSearchTerms.count() != 0; + if(%searchActive) + { + if(startsWith(%cppPath, %breadcrumbPath)) + { + if(matchesSearch(%cppName, "Cpp")) + { + %assetArray.add( %cppPath, "Cpp" TAB %cppName ); + } + } + } + else if(%cppPath $= %breadcrumbPath) + { + %assetArray.add( %cppPath, "Cpp" TAB %cppName ); + } + } + + //C++ Header files + %cppPattern = %breadcrumbPath @ "/" @ "*.h"; + for (%fullCppPath = findFirstFile(%cppPattern); %fullCppPath !$= ""; %fullCppPath = findNextFile(%cppPattern)) + { + %cppPath = filePath(%fullCppPath); + %cppName = fileName(%fullCppPath); + + %searchActive = AssetSearchTerms.count() != 0; + if(%searchActive) + { + if(startsWith(%cppPath, %breadcrumbPath)) + { + if(matchesSearch(%cppName, "Cpp")) + { + %assetArray.add( %cppPath, "Cpp" TAB %cppName ); + } + } + } + else if(%cppPath $= %breadcrumbPath) + { + %assetArray.add( %cppPath, "Cpp" TAB %cppName ); + } + } + + //script files + %tscriptPattern = %breadcrumbPath @ "/" @ "*.tscript"; + for (%fullScriptPath = findFirstFile(%tscriptPattern); %fullScriptPath !$= ""; %fullScriptPath = findNextFile(%tscriptPattern)) + { + %tscriptPath = filePath(%fullScriptPath); + %tscriptName = fileName(%fullScriptPath); + + %searchActive = AssetSearchTerms.count() != 0; + if(%searchActive) + { + if(startsWith(%tscriptPath, %breadcrumbPath)) + { + if(matchesSearch(%tscriptName, "tscript")) + { + %assetArray.add( %tscriptPath, "tscript" TAB %tscriptName ); + } + } + } + else if(%tscriptPath $= %breadcrumbPath) + { + %assetArray.add( %tscriptPath, "tscript" TAB %tscriptName ); + } + } } for(%i=0; %i < %assetArray.count(); %i++) diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/cpp.cs b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/cpp.cs index aea6b6442..4ae71361b 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/cpp.cs +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/cpp.cs @@ -1,4 +1,4 @@ -function AssetBrowser::buildCppAssetPreview(%this, %assetDef, %previewData) +function AssetBrowser::buildCppPreview(%this, %assetDef, %previewData) { %previewData.assetName = %assetDef.assetName; %previewData.assetPath = %assetDef.codeFilePath; @@ -11,7 +11,7 @@ function AssetBrowser::buildCppAssetPreview(%this, %assetDef, %previewData) %previewData.tooltip = %assetDef.assetName; } -function AssetBrowser::createCppAsset(%this) +function AssetBrowser::createCpp(%this) { %moduleName = AssetBrowser.newAssetSettings.moduleName; %modulePath = "data/" @ %moduleName; @@ -20,21 +20,12 @@ function AssetBrowser::createCppAsset(%this) %assetPath = AssetBrowser.dirHandler.currentAddress @ "/"; - %tamlpath = %assetPath @ %assetName @ ".asset.taml"; + //%tamlpath = %assetPath @ %assetName @ ".asset.taml"; %codePath = %assetPath @ %assetName @ ".cpp"; %headerPath = %assetPath @ %assetName @ ".h"; //Do the work here - %assetType = AssetBrowser.newAssetSettings.assetType; - - /*if(%assetType $= "CppStaticClassAsset" - || %assetType $= "CppRegularClassAsset" - || %assetType $= "CppGameObjectAsset" - || %assetType $= "CppComponentAsset" - || %assetType $= "CppScriptClass") - { - - }*/ + /*%assetType = AssetBrowser.newAssetSettings.assetType; %asset = new CppAsset() { @@ -44,26 +35,48 @@ function AssetBrowser::createCppAsset(%this) headerFile = %headerPath; }; - TamlWrite(%asset, %tamlpath); + TamlWrite(%asset, %tamlpath);*/ %moduleDef = ModuleDatabase.findModule(%moduleName, 1); AssetDatabase.addDeclaredAsset(%moduleDef, %tamlpath); - AssetBrowser.loadFilters(); + //AssetBrowser.loadFilters(); - %treeItemId = AssetBrowserFilterTree.findItemByName(%moduleName); + /*%treeItemId = AssetBrowserFilterTree.findItemByName(%moduleName); %smItem = AssetBrowserFilterTree.findChildItemByName(%treeItemId, "CppAsset"); - AssetBrowserFilterTree.onSelect(%smItem); + AssetBrowserFilterTree.onSelect(%smItem);*/ %file = new FileObject(); %templateFile = new FileObject(); - if(%assetType $= "CppStaticClassAsset") + if($AssetBrowser::newAssetTypeOverride $= "StaticClass") { - %cppTemplateCodeFilePath = %this.templateFilesPath @ "CppStaticClassFile.cpp"; - %cppTemplateHeaderFilePath = %this.templateFilesPath @ "CppStaticClassFile.h"; + %cppTemplateCodeFilePath = %this.templateFilesPath @ "CppStaticClassFile.cpp.template"; + %cppTemplateHeaderFilePath = %this.templateFilesPath @ "CppStaticClassFile.h.template"; } + else if($AssetBrowser::newAssetTypeOverride $= "ScriptClass") + { + %cppTemplateCodeFilePath = %this.templateFilesPath @ "CppScriptClassFile.cpp.template"; + %cppTemplateHeaderFilePath = %this.templateFilesPath @ "CppScriptClassFile.h.template"; + } + else if($AssetBrowser::newAssetTypeOverride $= "AssetTypeCppClass") + { + %cppTemplateCodeFilePath = %this.templateFilesPath @ "CppAssetTypeClassFile.cpp.template"; + %cppTemplateHeaderFilePath = %this.templateFilesPath @ "CppAssetTypeClassFile.h.template"; + } + else if($AssetBrowser::newAssetTypeOverride $= "RenderCppClass") + { + %cppTemplateCodeFilePath = %this.templateFilesPath @ "CppRenderClassFile.cpp.template"; + %cppTemplateHeaderFilePath = %this.templateFilesPath @ "CppRenderClassFile.h.template"; + } + else if($AssetBrowser::newAssetTypeOverride $= "SceneObjectCppClass") + { + %cppTemplateCodeFilePath = %this.templateFilesPath @ "CppSceneObjectClassFile.cpp.template"; + %cppTemplateHeaderFilePath = %this.templateFilesPath @ "CppSceneObjectClassFile.h.template"; + } + + $AssetBrowser::newAssetTypeOverride = ""; if(%file.openForWrite(%codePath) && %templateFile.openForRead(%cppTemplateCodeFilePath)) { @@ -73,7 +86,7 @@ function AssetBrowser::createCppAsset(%this) %line = strreplace( %line, "@", %assetName ); %file.writeline(%line); - echo(%line); + //echo(%line); } %file.close(); @@ -84,7 +97,7 @@ function AssetBrowser::createCppAsset(%this) %file.close(); %templateFile.close(); - warnf("CreateNewCppAsset - Something went wrong and we couldn't write the C++ code file!"); + warn("CreateNewCppAsset - Something went wrong and we couldn't write the C++ code file!"); } if(%file.openForWrite(%headerPath) && %templateFile.openForRead(%cppTemplateHeaderFilePath)) @@ -95,7 +108,7 @@ function AssetBrowser::createCppAsset(%this) %line = strreplace( %line, "@", %assetName ); %file.writeline(%line); - echo(%line); + //echo(%line); } %file.close(); @@ -124,7 +137,7 @@ function AssetBrowser::createCppAsset(%this) %line = strreplace( %line, "@", %moduleName ); %file.writeline(%line); - echo(%line); + //echo(%line); } %file.close(); @@ -139,15 +152,15 @@ function AssetBrowser::createCppAsset(%this) } } - return %tamlpath; + return ""; } -function AssetBrowser::editCppAsset(%this, %assetDef) +function AssetBrowser::editCpp(%this, %assetDef) { } //Renames the asset -function AssetBrowser::renameCppAsset(%this, %assetDef, %newAssetName) +function AssetBrowser::renameCpp(%this, %assetDef, %newAssetName) { %newCodeLooseFilename = renameAssetLooseFile(%assetDef.codefile, %newAssetName); @@ -167,13 +180,13 @@ function AssetBrowser::renameCppAsset(%this, %assetDef, %newAssetName) } //Deletes the asset -function AssetBrowser::deleteCppAsset(%this, %assetDef) +function AssetBrowser::deleteCpp(%this, %assetDef) { AssetDatabase.deleteAsset(%assetDef.getAssetId(), true); } //Moves the asset to a new path/module -function AssetBrowser::moveCppAsset(%this, %assetDef, %destination) +function AssetBrowser::moveCpp(%this, %assetDef, %destination) { %currentModule = AssetDatabase.getAssetModule(%assetDef.getAssetId()); %targetModule = AssetBrowser.getModuleFromAddress(%destination); diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/popupMenus.cs b/Templates/BaseGame/game/tools/assetBrowser/scripts/popupMenus.cs index c5572a0a2..31909cf07 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/popupMenus.cs +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/popupMenus.cs @@ -154,13 +154,11 @@ function AssetBrowser::buildPopupMenus(%this) class = "EditorWorldMenu"; //isPopup = true; - /*item[ 0 ] = "Create Static Class" TAB "" TAB "AssetBrowser.setupCreateNewAsset(\"CppStaticClassAsset\", AssetBrowser.selectedModule);"; - item[ 1 ] = "Create Regular Class" TAB "" TAB "AssetBrowser.setupCreateNewAsset(\"CppRegularClassAsset\", AssetBrowser.selectedModule);"; - item[ 2 ] = "Create GameObject Class" TAB "" TAB "AssetBrowser.setupCreateNewAsset(\"CppGameObjectAsset\", AssetBrowser.selectedModule);"; - item[ 3 ] = "Create Component Class" TAB "" TAB "AssetBrowser.setupCreateNewAsset(\"CppComponentAsset\", AssetBrowser.selectedModule);"; - item[ 4 ] = "Create Script Class" TAB "" TAB "AssetBrowser.setupCreateNewAsset(\"CppScriptClass\", AssetBrowser.selectedModule);";*/ - - item[ 0 ] = "Create C++ Class" TAB "" TAB "AssetBrowser.setupCreateNewAsset(\"CppAsset\", AssetBrowser.selectedModule);"; + item[ 0 ] = "Create Static C++ Class" TAB "" TAB "$AssetBrowser::newAssetTypeOverride = \"StaticClass\"; AssetBrowser.setupCreateNewAsset(\"CppAsset\", AssetBrowser.selectedModule);"; + item[ 1 ] = "Create ScriptObject C++ Class" TAB "" TAB "$AssetBrowser::newAssetTypeOverride = \"ScriptClass\"; AssetBrowser.setupCreateNewAsset(\"CppAsset\", AssetBrowser.selectedModule);"; + item[ 2 ] = "Create AssetType C++ Class" TAB "" TAB "$AssetBrowser::newAssetTypeOverride = \"AssetTypeCppClass\"; AssetBrowser.setupCreateNewAsset(\"CppAsset\", AssetBrowser.selectedModule);"; + item[ 3 ] = "Create Render C++ Class" TAB "" TAB "$AssetBrowser::newAssetTypeOverride = \"RenderCppClass\"; AssetBrowser.setupCreateNewAsset(\"CppAsset\", AssetBrowser.selectedModule);"; + item[ 3 ] = "Create SceneObject Class" TAB "" TAB "$AssetBrowser::newAssetTypeOverride = \"SceneObjectCppClass\"; AssetBrowser.setupCreateNewAsset(\"CppAsset\", AssetBrowser.selectedModule);"; }; //%this.AddNewScriptAssetPopup.insertSubMenu(0, "Create Component", AddNewComponentAssetPopup); } diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppAssetTypeClassFile.cpp.template b/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppAssetTypeClassFile.cpp.template new file mode 100644 index 000000000..f7694e6d5 --- /dev/null +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppAssetTypeClassFile.cpp.template @@ -0,0 +1,409 @@ +#ifndef @_H_ +#include "@.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" +#include "T3D/assets/assetImporter.h" + +//----------------------------------------------------------------------------- + +IMPLEMENT_CONOBJECT(@); + +ConsoleType(assetIdString, Type@Ptr, String, ASSET_ID_FIELD_PREFIX) + +ConsoleGetType(Type@Ptr) +{ + // Fetch asset Id. + //return *((StringTableEntry*)dptr); + return (*((AssetPtr<@>*)dptr)).getAssetId(); +} + +ConsoleSetType(Type@Ptr) +{ + // Was a single argument specified? + if (argc == 1) + { + // Yes, so fetch field value. + const char* pFieldValue = argv[0]; + + // Fetch asset Id. + StringTableEntry* assetId = (StringTableEntry*)(dptr); + + // Update asset value. + *assetId = StringTable->insert(pFieldValue); + + return; + } + + // Warn. + Con::warnf("(TypeAssetId) - Cannot set multiple args to a single asset."); +} + +//----------------------------------------------------------------------------- + +ConsoleType(assetIdString, Type@Id, String, ASSET_ID_FIELD_PREFIX) + +ConsoleGetType(Type@Id) +{ + // Fetch asset Id. + return *((const char**)(dptr)); +} + +ConsoleSetType(Type@Id) +{ + // Was a single argument specified? + if (argc == 1) + { + // Yes, so fetch field value. + const char* pFieldValue = argv[0]; + + // Fetch asset Id. + StringTableEntry* assetId = (StringTableEntry*)(dptr); + + // Update asset value. + *assetId = StringTable->insert(pFieldValue); + + return; + } + + // Warn. + Con::warnf("(TypeAssetId) - Cannot set multiple args to a single asset."); +} + +//----------------------------------------------------------------------------- + +const String @::mErrCodeStrings[] = +{ + "UnKnown" +}; +//----------------------------------------------------------------------------- + +@::@() +{ + mFileName = StringTable->EmptyString(); + mFilePath = StringTable->EmptyString(); + mLoadedState = AssetErrCode::NotLoaded; +} + +//----------------------------------------------------------------------------- + +@::~@() +{ +} + +//----------------------------------------------------------------------------- + +void @::initPersistFields() +{ + // Call parent. + Parent::initPersistFields(); + + addProtectedField("fileName", TypeAssetLooseFilePath, Offset(mFileName, @), + &set@File, &get@File, "Path to the asset file"); +} + +// In the event we have any special case logic where the asset's values are changed(such as a dependency value is updated), this +// will let us react to that variable changing to implement behavior in response +void @::setDataField(StringTableEntry slotName, const char *array, const char *value) +{ + Parent::setDataField(slotName, array, value); +} + +void @::initializeAsset() +{ + // Call parent. + Parent::initializeAsset(); + + if (mFileName == StringTable->EmptyString()) + return; + + ResourceManager::get().getChangedSignal().notify(this, &@::_onResourceChanged); + + //Ensure our path is expando'd if it isn't already + if (!Platform::isFullPath(mFilePath)) + mFilePath = getOwned() ? expandAssetFilePath(mFileName) : mFilePath; + + //Do a loading function here to do the actual load logic +} + +void @::set@File(const char* pFile) +{ + // Sanity! + AssertFatal(pFile != NULL, "Cannot use a NULL file."); + + // Fetch file. + pFile = StringTable->insert(pFile); + + // Ignore no change, + if (pFile == mFileName) + return; + + mFileName = pFile; + + // Refresh the asset. + refreshAsset(); +} + +void @::_onResourceChanged(const Torque::Path &path) +{ + if (path != Torque::Path(mFilePath) ) + return; + + refreshAsset(); + + //Do a loading function here to do the actual load logic +} + +//------------------------------------------------------------------------------ +//Utility function to 'fill out' bindings and resources with a matching asset if one exists +bool @::getAssetByFilename(StringTableEntry fileName, AssetPtr<@>* @) +{ + AssetQuery query; + S32 foundAssetcount = AssetDatabase.findAssetLooseFile(&query, fileName); + if (foundAssetcount == 0) + { + //Didn't find any assets + //If possible, see if we can run an in-place import and the get the asset from that +#if TORQUE_DEBUG + Con::warnf("@::getAssetByFilename - Attempted to in-place import a file(%s) that had no associated asset", fileName); +#endif + + AssetImporter* autoAssetImporter; + if (!Sim::findObject("autoAssetImporter", autoAssetImporter)) + { + autoAssetImporter = new AssetImporter(); + autoAssetImporter->registerObject("autoAssetImporter"); + } + + StringTableEntry resultingAssetId = autoAssetImporter->autoImportFile(fileName); + + if (resultingAssetId != StringTable->EmptyString()) + { + @->setAssetId(resultingAssetId); + + if (!@->isNull()) + return true; + } + + //Didn't work, so have us fall back to a placeholder asset + @->setAssetId(StringTable->insert("Core_Rendering:noshape")); + + if (!@->isNull()) + return true; + + //That didn't work, so fail out + return false; + } + else + { + //acquire and bind the asset, and return it out + @->setAssetId(query.mAssetList[0]); + return true; + } +} + +StringTableEntry @::getAssetIdByFilename(StringTableEntry fileName) +{ + if (fileName == StringTable->EmptyString()) + return StringTable->EmptyString(); + + StringTableEntry @Id = StringTable->EmptyString(); + + AssetQuery query; + S32 foundAssetcount = AssetDatabase.findAssetLooseFile(&query, fileName); + if (foundAssetcount == 0) + { + //Didn't find any assets + //If possible, see if we can run an in-place import and the get the asset from that +#if TORQUE_DEBUG + Con::warnf("@::getAssetByFilename - Attempted to in-place import a file(%s) that had no associated asset", fileName); +#endif + + AssetImporter* autoAssetImporter; + if (!Sim::findObject("autoAssetImporter", autoAssetImporter)) + { + autoAssetImporter = new AssetImporter(); + autoAssetImporter->registerObject("autoAssetImporter"); + } + + StringTableEntry resultingAssetId = autoAssetImporter->autoImportFile(fileName); + + if (resultingAssetId != StringTable->EmptyString()) + { + @Id = resultingAssetId; + return @Id; + } + + //Didn't work, so have us fall back to a placeholder asset + @Id = StringTable->insert("Core_Rendering:noshape"); + } + else + { + //acquire and bind the asset, and return it out + @Id = query.mAssetList[0]; + } + + return @Id; +} + +U32 @::getAssetById(StringTableEntry assetId, AssetPtr<@>* @) +{ + (*@) = assetId; + + if ((*@)) + return (*@)->mLoadedState; + + //Didn't work, so have us fall back to a placeholder asset + StringTableEntry noShapeId = StringTable->insert("Core_Rendering:noshape"); + @->setAssetId(noShapeId); + (*@)->mLoadedState = AssetErrCode::UsingFallback; + if (@->notNull()) + return AssetErrCode::UsingFallback; + + return AssetErrCode::Failed; +} +//------------------------------------------------------------------------------ + +void @::copyTo(SimObject* object) +{ + // Call to parent. + Parent::copyTo(object); +} + +void @::onAssetRefresh(void) +{ + if (mFileName == StringTable->EmptyString()) + return; + + // Update. + if(!Platform::isFullPath(mFileName)) + mFilePath = getOwned() ? expandAssetFilePath(mFileName) : mFilePath; + + //Do a loading function here to do the actual load logic +} + +//----------------------------------------------------------------------------- +// GuiInspectorTypeAssetId +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TOOLS +IMPLEMENT_CONOBJECT(GuiInspectorType@Ptr); + +ConsoleDocClass(GuiInspectorType@Ptr, + "@brief Inspector field type for @\n\n" + "Editor use only.\n\n" + "@internal" + ); + +void GuiInspectorType@Ptr::consoleInit() +{ + Parent::consoleInit(); + + ConsoleBaseType::getType(Type@Ptr)->setInspectorFieldType("GuiInspectorType@Ptr"); +} + +GuiControl* GuiInspectorType@Ptr::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(\"@\", \"AssetBrowser.changeAsset\", %s, %s);", + mInspector->getInspectObject()->getIdString(), mCaption); + mBrowseButton->setField("Command", szBuffer); + + const char* id = mInspector->getInspectObject()->getIdString(); + + setDataField(StringTable->insert("targetObject"), NULL, mInspector->getInspectObject()->getIdString()); + + // Create "Open in ShapeEditor" button + mShapeEdButton = new GuiBitmapButtonCtrl(); + + dSprintf(szBuffer, sizeof(szBuffer), "ShapeEditorPlugin.open@Id(%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 GuiInspectorType@Ptr::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; +} + +IMPLEMENT_CONOBJECT(GuiInspectorType@Id); + +ConsoleDocClass(GuiInspectorType@Id, + "@brief Inspector field type for @\n\n" + "Editor use only.\n\n" + "@internal" +); + +void GuiInspectorType@Id::consoleInit() +{ + Parent::consoleInit(); + + ConsoleBaseType::getType(Type@Id)->setInspectorFieldType("GuiInspectorType@Id"); +} + +#endif + +DefineEngineMethod(@, getFilePath, const char*, (), , + "Creates a new script asset using the targetFilePath.\n" + "@return The bool result of calling exec") +{ + return object->get@FilePath(); +} diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppAssetTypeClassFile.h.template b/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppAssetTypeClassFile.h.template new file mode 100644 index 000000000..6e910db71 --- /dev/null +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppAssetTypeClassFile.h.template @@ -0,0 +1,157 @@ +#ifndef @_H +#define @_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 __RESOURCE_H__ +#include "core/resource.h" +#endif +#ifndef _ASSET_PTR_H_ +#include "assets/assetPtr.h" +#endif + +#ifdef TORQUE_TOOLS +#include "gui/editor/guiInspectorTypes.h" +#endif + +//----------------------------------------------------------------------------- +class @ : public AssetBase +{ + typedef AssetBase Parent; + +protected: + StringTableEntry mFileName; + StringTableEntry mFilePath; + + typedef Signal @Changed; + + @Changed mChangeSignal; + +public: + enum @ErrCode + { + Extended = AssetErrCode::Extended + }; + + static const String mErrCodeStrings[@ErrCode::Extended - Parent::Extended + 1]; + static String getAssetErrstrn(U32 errCode) + { + if (errCode < Parent::Extended) return Parent::getAssetErrstrn(errCode); + if (errCode > @ErrCode::Extended) return "undefined error"; + return mErrCodeStrings[errCode]; + }; + + @(); + virtual ~@(); + + /// Engine. + 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. + DECLARE_CONOBJECT(@); + + U32 mLoadedState; + + void _onResourceChanged(const Torque::Path &path); + + @Changed& getChangedSignal() { return mChangeSignal; } + + void set@File(const char* pFile); + inline StringTableEntry get@File(void) const { return mFileName; }; + + inline StringTableEntry get@FilePath(void) const { return mFilePath; }; + + static bool getAssetByFilename(StringTableEntry fileName, AssetPtr<@>* @); + + static StringTableEntry getAssetIdByFilename(StringTableEntry fileName); + static U32 getAssetById(StringTableEntry assetId, AssetPtr<@>* @); + + static StringTableEntry getNo@Id() { return StringTable->insert("Core_Rendering:noshape"); } + +protected: + virtual void onAssetRefresh(void); + + static bool set@File(void* obj, const char* index, const char* data) { static_cast<@*>(obj)->set@File(data); return false; } + static const char* get@File(void* obj, const char* data) { return static_cast<@*>(obj)->get@File(); } +}; + +#ifdef TORQUE_TOOLS +DefineConsoleType(Type@Ptr, S32) +DefineConsoleType(Type@Id, String) + +//----------------------------------------------------------------------------- +// TypeAssetId GuiInspectorField Class +//----------------------------------------------------------------------------- +class GuiInspectorType@Ptr : public GuiInspectorTypeFileName +{ + typedef GuiInspectorTypeFileName Parent; +public: + + GuiBitmapButtonCtrl *mShapeEdButton; + + DECLARE_CONOBJECT(GuiInspectorType@Ptr); + static void consoleInit(); + + virtual GuiControl* constructEditControl(); + virtual bool updateRects(); +}; + +class GuiInspectorType@Id : public GuiInspectorType@Ptr +{ + typedef GuiInspectorType@Ptr Parent; +public: + + DECLARE_CONOBJECT(GuiInspectorType@Id); + static void consoleInit(); +}; +#endif + +#define assetText(x,suff) std::string(std::string(#x) + std::string(#suff)).c_str() + +#define init@(name) m##name##AssetId = StringTable->EmptyString(); m##name##Asset = NULL; +#define bind@(name) if (m##name##AssetId != StringTable->EmptyString()) m##name##Asset = m##name##AssetId; + +#define scriptBind@(name, consoleClass, docs) addProtectedField(assetText(name, Asset), Type@Id, Offset(m##name##AssetId, consoleClass), consoleClass::_set##name##Asset, & defaultProtectedGetFn, assetText(name, asset reference.)); + +#define DECLARE_@(className,name) protected: \ + StringTableEntry m##name##AssetId;\ + AssetPtr<@> m##name##Asset;\ + public: \ + const AssetPtr<@> & get##name##Asset() const { return m##name##Asset; }\ + void set##name##Asset(AssetPtr<@>_in) { m##name##Asset = _in; }\ +static bool _set##name##Asset(void* obj, const char* index, const char* data)\ +{\ + className* shape = static_cast(obj);\ + shape->m##name##AssetId = StringTable->insert(data);\ + if (@::getAssetById(shape->m##name##AssetId, &shape->m##name##Asset))\ + {\ + if (shape->m##name##Asset.getAssetId() != StringTable->insert("Core_Rendering:noShape"))\ + shape->m##name##Filename = StringTable->EmptyString();\ + \ + shape->setMaskBits(-1);\ + return true;\ + }\ + return false;\ +} + +#endif + diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppRenderClassFile.cpp.template b/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppRenderClassFile.cpp.template new file mode 100644 index 000000000..a5a00bd26 --- /dev/null +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppRenderClassFile.cpp.template @@ -0,0 +1,325 @@ +#include "@.h" +#include "platform/platform.h" +#include "math/mathIO.h" +#include "scene/sceneRenderState.h" +#include "console/consoleTypes.h" +#include "core/stream/bitStream.h" +#include "materials/materialManager.h" +#include "materials/baseMatInstance.h" +#include "renderInstance/renderPassManager.h" +#include "lighting/lightQuery.h" +#include "console/engineAPI.h" + + +IMPLEMENT_CO_NETOBJECT_V1(@); + +ConsoleDocClass( @, + "@brief An example scene object which renders a mesh.\n\n" ); + + +//----------------------------------------------------------------------------- +// Object setup and teardown +//----------------------------------------------------------------------------- +@::@() +{ + // Flag this object so that it will always + // be sent across the network to clients + mNetFlags.set( Ghostable | ScopeAlways ); + + // Set it as a "static" object that casts shadows + mTypeMask |= StaticObjectType | StaticShapeObjectType; + + // Make sure we the Material instance to NULL + // so we don't try to access it incorrectly + mMaterialInst = NULL; +} + +@::~@() +{ + if ( mMaterialInst ) + SAFE_DELETE( mMaterialInst ); +} + +//----------------------------------------------------------------------------- +// Object Editing +//----------------------------------------------------------------------------- +void @::initPersistFields() +{ + addGroup( "Rendering" ); + addField( "material", TypeMaterialName, Offset( mMaterialName, @ ), + "The name of the material used to render the mesh." ); + endGroup( "Rendering" ); + + // SceneObject already handles exposing the transform + Parent::initPersistFields(); +} + +void @::inspectPostApply() +{ + Parent::inspectPostApply(); + + // Flag the network mask to send the updates + // to the client object + setMaskBits( UpdateMask ); +} + +bool @::onAdd() +{ + if ( !Parent::onAdd() ) + return false; + + // Set up a 1x1x1 bounding box + mObjBox.set( Point3F( -0.5f, -0.5f, -0.5f ), + Point3F( 0.5f, 0.5f, 0.5f ) ); + + resetWorldBox(); + + // Add this object to the scene + addToScene(); + + // Refresh this object's material (if any) + updateMaterial(); + + return true; +} + +void @::onRemove() +{ + // Remove this object from the scene + removeFromScene(); + + Parent::onRemove(); +} + +void @::setTransform(const MatrixF & mat) +{ + // Let SceneObject handle all of the matrix manipulation + Parent::setTransform( mat ); + + // Dirty our network mask so that the new transform gets + // transmitted to the client object + setMaskBits( TransformMask ); +} + +U32 @::packUpdate( NetConnection *conn, U32 mask, BitStream *stream ) +{ + // Allow the Parent to get a crack at writing its info + U32 retMask = Parent::packUpdate( conn, mask, stream ); + + // Write our transform information + if ( stream->writeFlag( mask & TransformMask ) ) + { + mathWrite(*stream, getTransform()); + mathWrite(*stream, getScale()); + } + + // Write out any of the updated editable properties + if ( stream->writeFlag( mask & UpdateMask ) ) + stream->write( mMaterialName ); + + return retMask; +} + +void @::unpackUpdate(NetConnection *conn, BitStream *stream) +{ + // Let the Parent read any info it sent + Parent::unpackUpdate(conn, stream); + + if ( stream->readFlag() ) // TransformMask + { + mathRead(*stream, &mObjToWorld); + mathRead(*stream, &mObjScale); + + setTransform( mObjToWorld ); + } + + if ( stream->readFlag() ) // UpdateMask + { + stream->read( &mMaterialName ); + + if ( isProperlyAdded() ) + updateMaterial(); + } +} + +//----------------------------------------------------------------------------- +// Object Rendering +//----------------------------------------------------------------------------- +void @::createGeometry() +{ + static const Point3F cubePoints[8] = + { + Point3F( 1, -1, -1), Point3F( 1, -1, 1), Point3F( 1, 1, -1), Point3F( 1, 1, 1), + Point3F(-1, -1, -1), Point3F(-1, 1, -1), Point3F(-1, -1, 1), Point3F(-1, 1, 1) + }; + + static const Point3F cubeNormals[6] = + { + Point3F( 1, 0, 0), Point3F(-1, 0, 0), Point3F( 0, 1, 0), + Point3F( 0, -1, 0), Point3F( 0, 0, 1), Point3F( 0, 0, -1) + }; + + static const Point2F cubeTexCoords[4] = + { + Point2F( 0, 0), Point2F( 0, -1), + Point2F( 1, 0), Point2F( 1, -1) + }; + + static const U32 cubeFaces[36][3] = + { + { 3, 0, 3 }, { 0, 0, 0 }, { 1, 0, 1 }, + { 2, 0, 2 }, { 0, 0, 0 }, { 3, 0, 3 }, + { 7, 1, 1 }, { 4, 1, 2 }, { 5, 1, 0 }, + { 6, 1, 3 }, { 4, 1, 2 }, { 7, 1, 1 }, + { 3, 2, 1 }, { 5, 2, 2 }, { 2, 2, 0 }, + { 7, 2, 3 }, { 5, 2, 2 }, { 3, 2, 1 }, + { 1, 3, 3 }, { 4, 3, 0 }, { 6, 3, 1 }, + { 0, 3, 2 }, { 4, 3, 0 }, { 1, 3, 3 }, + { 3, 4, 3 }, { 6, 4, 0 }, { 7, 4, 1 }, + { 1, 4, 2 }, { 6, 4, 0 }, { 3, 4, 3 }, + { 2, 5, 1 }, { 4, 5, 2 }, { 0, 5, 0 }, + { 5, 5, 3 }, { 4, 5, 2 }, { 2, 5, 1 } + }; + + // Fill the vertex buffer + VertexType *pVert = NULL; + + mVertexBuffer.set( GFX, 36, GFXBufferTypeStatic ); + pVert = mVertexBuffer.lock(); + + Point3F halfSize = getObjBox().getExtents() * 0.5f; + + for (U32 i = 0; i < 36; i++) + { + const U32& vdx = cubeFaces[i][0]; + const U32& ndx = cubeFaces[i][1]; + const U32& tdx = cubeFaces[i][2]; + + pVert[i].point = cubePoints[vdx] * halfSize; + pVert[i].normal = cubeNormals[ndx]; + pVert[i].texCoord = cubeTexCoords[tdx]; + } + + mVertexBuffer.unlock(); + + // Fill the primitive buffer + U16 *pIdx = NULL; + + mPrimitiveBuffer.set( GFX, 36, 12, GFXBufferTypeStatic ); + + mPrimitiveBuffer.lock(&pIdx); + + for (U16 i = 0; i < 36; i++) + pIdx[i] = i; + + mPrimitiveBuffer.unlock(); +} + +void @::updateMaterial() +{ + if ( mMaterialName.isEmpty() ) + return; + + // If the material name matches then don't bother updating it. + if ( mMaterialInst && mMaterialName.equal( mMaterialInst->getMaterial()->getName(), String::NoCase ) ) + return; + + SAFE_DELETE( mMaterialInst ); + + mMaterialInst = MATMGR->createMatInstance( mMaterialName, getGFXVertexFormat< VertexType >() ); + if ( !mMaterialInst ) + Con::errorf( "@::updateMaterial - no Material called '%s'", mMaterialName.c_str() ); +} + +void @::prepRenderImage( SceneRenderState *state ) +{ + // Do a little prep work if needed + if ( mVertexBuffer.isNull() ) + createGeometry(); + + // If we have no material then skip out. + if ( !mMaterialInst || !state) + return; + + // If we don't have a material instance after the override then + // we can skip rendering all together. + BaseMatInstance *matInst = state->getOverrideMaterial( mMaterialInst ); + if ( !matInst ) + return; + + // Get a handy pointer to our RenderPassmanager + RenderPassManager *renderPass = state->getRenderPass(); + + // Allocate an MeshRenderInst so that we can submit it to the RenderPassManager + MeshRenderInst *ri = renderPass->allocInst(); + + // 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 = getRenderWorldBox(); + ri->sortDistSq = rBox.getSqDistanceToPoint( state->getCameraPosition() ); + } + else + ri->sortDistSq = 0.0f; + + // Set up our transforms + MatrixF objectToWorld = 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 = &mVertexBuffer; + ri->primBuff = &mPrimitiveBuffer; + + ri->prim = renderPass->allocPrim(); + ri->prim->type = GFXTriangleList; + ri->prim->minIndex = 0; + ri->prim->startIndex = 0; + ri->prim->numPrimitives = 12; + ri->prim->startVertex = 0; + ri->prim->numVertices = 36; + + // 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 ); +} + +DefineEngineMethod( @, postApply, void, (),, + "A utility method for forcing a network update.\n") +{ + object->inspectPostApply(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppRenderClassFile.h.template b/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppRenderClassFile.h.template new file mode 100644 index 000000000..1acd8c89c --- /dev/null +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppRenderClassFile.h.template @@ -0,0 +1,102 @@ +#ifndef _@_H_ +#define _@_H_ + +#ifndef _SCENEOBJECT_H_ +#include "scene/sceneObject.h" +#endif +#ifndef _GFXVERTEXBUFFER_H_ +#include "gfx/gfxVertexBuffer.h" +#endif +#ifndef _GFXPRIMITIVEBUFFER_H_ +#include "gfx/gfxPrimitiveBuffer.h" +#endif + +class BaseMatInstance; + +class @ : public SceneObject +{ + typedef SceneObject Parent; + + // Networking masks + // We need to implement a mask specifically to handle + // updating our transform from the server object to its + // client-side "ghost". We also need to implement a + // maks for handling editor updates to our properties + // (like material). + enum MaskBits + { + TransformMask = Parent::NextFreeMask << 0, + UpdateMask = Parent::NextFreeMask << 1, + NextFreeMask = Parent::NextFreeMask << 2 + }; + + //-------------------------------------------------------------------------- + // Rendering variables + //-------------------------------------------------------------------------- + // The name of the Material we will use for rendering + String mMaterialName; + // The actual Material instance + BaseMatInstance* mMaterialInst; + + // Define our vertex format here so we don't have to + // change it in multiple spots later + typedef GFXVertexPNT VertexType; + + // The GFX vertex and primitive buffers + GFXVertexBufferHandle< VertexType > mVertexBuffer; + GFXPrimitiveBufferHandle mPrimitiveBuffer; + +public: + @(); + virtual ~@(); + + // Handle when we are added to the scene and removed from the scene + bool onAdd(); + void onRemove(); + + // Declare this object as a ConsoleObject so that we can + // instantiate it into the world and network it + DECLARE_CONOBJECT(@); + + //-------------------------------------------------------------------------- + // Object Editing + // Since there is always a server and a client object in Torque and we + // actually edit the server object we need to implement some basic + // networking functions + //-------------------------------------------------------------------------- + // Set up any fields that we want to be editable (like position) + static void initPersistFields(); + + // Allows the object to update its editable settings + // from the server object to the client + virtual void inspectPostApply(); + + // Override this so that we can dirty the network flag when it is called + void setTransform( const MatrixF &mat ); + + // This function handles sending the relevant data from the server + // object to the client object + U32 packUpdate( NetConnection *conn, U32 mask, BitStream *stream ); + // This function handles receiving relevant data from the server + // object and applying it to the client object + void unpackUpdate( NetConnection *conn, BitStream *stream ); + + //-------------------------------------------------------------------------- + // Object Rendering + // Torque utilizes a "batch" rendering system. This means that it builds a + // list of objects that need to render (via RenderInst's) and then renders + // them all in one batch. This allows it to optimized on things like + // minimizing texture, state, and shader switching by grouping objects that + // use the same Materials. + //-------------------------------------------------------------------------- + // Create the geometry for rendering + void createGeometry(); + + // Get the Material instance + void updateMaterial(); + + // This is the function that allows this object to submit itself for rendering + void prepRenderImage( SceneRenderState *state ); +}; + +#endif // _@_H_ \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppSceneObjectClassFile.cpp.template b/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppSceneObjectClassFile.cpp.template new file mode 100644 index 000000000..78c735b2b --- /dev/null +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppSceneObjectClassFile.cpp.template @@ -0,0 +1,105 @@ +#include "@.h" +#include "math/mathIO.h" +#include "console/consoleTypes.h" +#include "core/stream/bitStream.h" + + +IMPLEMENT_CO_NETOBJECT_V1(@); + +@::@() +{ + // Flag this object so that it will always + // be sent across the network to clients + mNetFlags.set( Ghostable | ScopeAlways ); + + // Set it as a "static" object that casts shadows + mTypeMask |= StaticObjectType | StaticShapeObjectType; +} + +@::~@() +{ +} + +bool @::onAdd() +{ + if (!Parent::onAdd()) + return false; + + // Set up a 1x1x1 bounding box + mObjBox.set( Point3F( -0.5f, -0.5f, -0.5f ), + Point3F( 0.5f, 0.5f, 0.5f ) ); + + resetWorldBox(); + + // Add this object to the scene + addToScene(); + + return true; +} + +void @::onRemove() +{ + // Remove this object from the scene + removeFromScene(); + + Parent::onRemove(); +} + +void @::initPersistFields() +{ + Parent::initPersistFields(); +} + +void @::inspectPostApply() +{ + Parent::inspectPostApply(); + + // Flag the network mask to send the updates + // to the client object + setMaskBits( TransformMask ); +} + +void @::setTransform(const MatrixF & mat) +{ + // Let SceneObject handle all of the matrix manipulation + Parent::setTransform( mat ); + + // Dirty our network mask so that the new transform gets + // transmitted to the client object + setMaskBits( TransformMask ); +} + +U32 @::packUpdate( NetConnection *conn, U32 mask, BitStream *stream ) +{ + // Allow the Parent to get a crack at writing its info + U32 retMask = Parent::packUpdate( conn, mask, stream ); + + // Write our transform information + if ( stream->writeFlag( mask & TransformMask ) ) + { + mathWrite(*stream, getTransform()); + mathWrite(*stream, getScale()); + } + + return retMask; +} + +void @::unpackUpdate(NetConnection *conn, BitStream *stream) +{ + // Let the Parent read any info it sent + Parent::unpackUpdate(conn, stream); + + if ( stream->readFlag() ) // TransformMask + { + mathRead(*stream, &mObjToWorld); + mathRead(*stream, &mObjScale); + + setTransform( mObjToWorld ); + } +} + +DefineEngineMethod( @, postApply, void, (),, + "A utility method for forcing a network update.\n") +{ + object->inspectPostApply(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppSceneObjectClassFile.h.template b/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppSceneObjectClassFile.h.template new file mode 100644 index 000000000..21f94d831 --- /dev/null +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppSceneObjectClassFile.h.template @@ -0,0 +1,53 @@ +#pragma once + +#ifndef _SCENEOBJECT_H_ +#include "scene/sceneObject.h" +#endif + +class @ : public SceneObject +{ + typedef SceneObject Parent; + +private: + enum MaskBits + { + TransformMask = Parent::NextFreeMask << 0, + NextFreeMask = Parent::NextFreeMask << 1 + }; + +protected: + +public: + @(); + virtual ~@(); + + // Declare this object as a ConsoleObject so that we can + // instantiate it into the world and network it + DECLARE_CONOBJECT(@); + + // Handle when we are added to the scene and removed from the scene + bool onAdd(); + void onRemove(); + + // Set up any fields that we want to be editable (like position) + static void initPersistFields(); + + // Allows the object to update its editable settings + // from the server object to the client + virtual void inspectPostApply(); + + // Override this so that we can dirty the network flag when it is called + void setTransform( const MatrixF &mat ); + + // This function handles sending the relevant data from the server + // object to the client object + U32 packUpdate( NetConnection *conn, U32 mask, BitStream *stream ); + + // This function handles receiving relevant data from the server + // object and applying it to the client object + void unpackUpdate( NetConnection *conn, BitStream *stream ); + + virtual void interpolateTick( F32 delta ); + virtual void processTick(); + virtual void advanceTime( F32 timeDelta ); +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppScriptClassFile.cpp.template b/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppScriptClassFile.cpp.template new file mode 100644 index 000000000..5fe7a7f5e --- /dev/null +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppScriptClassFile.cpp.template @@ -0,0 +1,45 @@ +#include "@.h" + + +IMPLEMENT_CONOBJECT(@); + +@::@() +{ +} + +@::~@() +{ +} + +void @::initPersistFields() +{ + Parent::initPersistFields(); +} + +bool @::onAdd() +{ + if (!Parent::onAdd()) + return false; + + return true; +} + +void @::onRemove() +{ + Parent::onRemove(); +} + +void @::interpolateTick( F32 delta ) +{ + Parent::interpolateTick(delta); +} + +void @::processTick() +{ + Parent::processTick(); +} + +void @::advanceTime( F32 timeDelta ) +{ + Parent::advanceTime(timeDelta); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppScriptClassFile.h.template b/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppScriptClassFile.h.template new file mode 100644 index 000000000..1d286eaf2 --- /dev/null +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/templateFiles/CppScriptClassFile.h.template @@ -0,0 +1,29 @@ +#pragma once + +#include "console/engineAPI.h" +#include "console/scriptObjects.h" + +class @ : public ScriptTickObject +{ + typedef ScriptTickObject Parent; + +private: + +protected: + +public: + @(); + ~@(); + + // Declare this object as a ConsoleObject so that we can + // instantiate it + DECLARE_CONOBJECT(@); + + static void initPersistFields(); + bool onAdd(); + void onRemove(); + + virtual void interpolateTick( F32 delta ); + virtual void processTick(); + virtual void advanceTime( F32 timeDelta ); +}; \ No newline at end of file