tsShapeConstruct.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _TSSHAPECONSTRUCT_H_
  23. #define _TSSHAPECONSTRUCT_H_
  24. #ifndef __RESOURCE_H__
  25. #include "core/resource.h"
  26. #endif
  27. #ifndef _MTRANSFORM_H_
  28. #include "math/mTransform.h"
  29. #endif
  30. #ifndef _TSSHAPE_H_
  31. #include "ts/tsShape.h"
  32. #endif
  33. #ifndef _SIMBASE_H_
  34. #include "console/simBase.h"
  35. #endif
  36. #ifndef _COLLADA_UTILS_H_
  37. #include "ts/collada/colladaUtils.h"
  38. #endif
  39. #ifndef _ENGINEAPI_H_
  40. #include "console/engineAPI.h"
  41. #endif
  42. #include "T3D/assets/ShapeAsset.h"
  43. #include "T3D/assets/ShapeAnimationAsset.h"
  44. /// This class allows an artist to export their animations for the model
  45. /// into the .dsq format. This class in particular matches up the model
  46. /// with the .dsqs to create a nice animated model.
  47. class TSShapeConstructor : public SimObject
  48. {
  49. typedef SimObject Parent;
  50. public:
  51. struct ChangeSet
  52. {
  53. enum eCommandType
  54. {
  55. CmdAddNode,
  56. CmdRemoveNode,
  57. CmdRenameNode,
  58. CmdSetNodeTransform,
  59. CmdSetNodeParent,
  60. CmdAddMesh,
  61. CmdAddPrimitive,
  62. CmdRemoveMesh,
  63. CmdSetMeshSize,
  64. CmdSetMeshType,
  65. CmdSetMeshMaterial,
  66. CmdRemoveObject,
  67. CmdRenameObject,
  68. CmdSetObjectNode,
  69. CmdSetBounds,
  70. CmdRenameDetailLevel,
  71. CmdRemoveDetailLevel,
  72. CmdSetDetailLevelSize,
  73. CmdAddImposter,
  74. CmdRemoveImposter,
  75. CmdAddCollisionDetail,
  76. CmdAddSequence,
  77. CmdRemoveSequence,
  78. CmdRenameSequence,
  79. CmdSetSequenceCyclic,
  80. CmdSetSequenceBlend,
  81. CmdSetSequencePriority,
  82. CmdSetSequenceGroundSpeed,
  83. CmdAddTrigger,
  84. CmdRemoveTrigger,
  85. CmdInvalid
  86. };
  87. struct Command
  88. {
  89. eCommandType type; // Command type
  90. StringTableEntry name; // Command name
  91. static const U32 MAX_ARGS = 10;
  92. String argv[MAX_ARGS]; // Command arguments
  93. S32 argc; // Number of arguments
  94. Command() : type(CmdInvalid), name(0), argc(0) { }
  95. Command(const char* _name)
  96. : type(CmdInvalid), argc(0)
  97. {
  98. name = StringTable->insert(_name);
  99. }
  100. // Helper functions to fill in the command arguments
  101. template<typename ...ArgTs> inline void addArgs(ArgTs ...args) {
  102. using Helper = engineAPI::detail::MarshallHelpers<String>;
  103. Helper::marshallEach(argc, argv, args...);
  104. }
  105. };
  106. Vector<Command> mCommands;
  107. eCommandType getCmdType(const char* name);
  108. void clear() { mCommands.clear(); }
  109. bool empty() { return mCommands.empty(); }
  110. void add(Command& cmd);
  111. // These methods handle change set optimisation based on the newly added command
  112. bool addCmd_setNodeParent(const Command& newCmd);
  113. bool addCmd_setNodeTransform(const Command& newCmd);
  114. bool addCmd_renameNode(const Command& newCmd);
  115. bool addCmd_removeNode(const Command& newCmd);
  116. bool addCmd_setMeshSize(const Command& newCmd);
  117. bool addCmd_setMeshType(const Command& newCmd);
  118. bool addCmd_setMeshMaterial(const Command& newCmd);
  119. bool addCmd_removeMesh(const Command& newCmd);
  120. bool addCmd_setObjectNode(const Command& newCmd);
  121. bool addCmd_renameObject(const Command& newCmd);
  122. bool addCmd_removeObject(const Command& newCmd);
  123. bool addCmd_setBounds(const Command& newCmd);
  124. bool addCmd_renameDetailLevel(const Command& newCmd);
  125. bool addCmd_removeDetailLevel(const Command& newCmd);
  126. bool addCmd_setDetailSize(const Command& newCmd);
  127. bool addCmd_addImposter(const Command& newCmd);
  128. bool addCmd_removeImposter(const Command& newCmd);
  129. bool addCmd_addSequence(Command& newCmd);
  130. bool addCmd_setSequencePriority(const Command& newCmd);
  131. bool addCmd_setSequenceGroundSpeed(const Command& newCmd);
  132. bool addCmd_setSequenceCyclic(const Command& newCmd);
  133. bool addCmd_setSequenceBlend(const Command& newCmd);
  134. bool addCmd_renameSequence(const Command& newCmd);
  135. bool addCmd_removeSequence(const Command& newCmd);
  136. bool addCmd_addTrigger(const Command& newCmd);
  137. bool addCmd_removeTrigger(const Command& newCmd);
  138. void write(TSShape* shape, Stream& stream, const String& savePath);
  139. };
  140. static const S32 MaxLegacySequences = 127;
  141. protected:
  142. StringTableEntry mShapeAssetId;
  143. AssetPtr<ShapeAsset> mShapeAsset;
  144. Vector<StringTableEntry> mSequenceAssetIds;
  145. Vector<AssetPtr<ShapeAnimationAsset>> mSequencesAssets;
  146. ChangeSet mChangeSet;
  147. // Paths to shapes used by MeshFit
  148. static String smCapsuleShapePath;
  149. static String smCubeShapePath;
  150. static String smSphereShapePath;
  151. static bool addSequenceFromField(void* obj, const char* index, const char* data);
  152. static void _onTSShapeLoaded(Resource< TSShape >& shape);
  153. static void _onTSShapeUnloaded(const Torque::Path& path, TSShape* shape);
  154. static ResourceRegisterPostLoadSignal< TSShape > _smAutoLoad;
  155. static ResourceRegisterUnloadSignal< TSShape > _smAutoUnload;
  156. /// @name Callbacks
  157. ///@{
  158. DECLARE_CALLBACK(void, onLoad, ());
  159. DECLARE_CALLBACK(void, onUnload, ());
  160. ///@}
  161. virtual void _onLoad(TSShape* shape);
  162. virtual void _onUnload();
  163. public:
  164. TSShape* mShape; // Edited shape; NULL while not loaded; not a Resource<TSShape> as we don't want it to prevent from unloading.
  165. ColladaUtils::ImportOptions mOptions;
  166. bool mLoadingShape;
  167. public:
  168. TSShapeConstructor();
  169. TSShapeConstructor(StringTableEntry path) : mShapeAssetId(path), mShape(NULL), mLoadingShape(false) { }
  170. ~TSShapeConstructor();
  171. DECLARE_CONOBJECT(TSShapeConstructor);
  172. static void initPersistFields();
  173. static void consoleInit();
  174. static TSShapeConstructor* findShapeConstructorByAssetId(StringTableEntry path);
  175. static TSShapeConstructor* findShapeConstructorByFilename(const FileName& path);
  176. bool onAdd();
  177. void onScriptChanged(const Torque::Path& path);
  178. void onActionPerformed();
  179. bool writeField(StringTableEntry fieldname, const char* value);
  180. void writeChangeSet();
  181. void notifyShapeChanged();
  182. void setShapeAssetId(StringTableEntry assetId);
  183. /// @name Shape paths for MeshFit
  184. ///@{
  185. static const String& getCapsuleShapePath() { return smCapsuleShapePath; }
  186. static const String& getCubeShapePath() { return smCubeShapePath; }
  187. static const String& getSphereShapePath() { return smSphereShapePath; }
  188. ///@}
  189. TSShape* getShape() const { return mShape; }
  190. StringTableEntry getShapePath() const
  191. {
  192. if (mShapeAsset.notNull())
  193. return mShapeAsset->getShapeFilePath();
  194. else
  195. return StringTable->EmptyString();
  196. }
  197. StringTableEntry getShapeAssetId() const
  198. {
  199. return mShapeAssetId;
  200. }
  201. /// @name Dumping
  202. ///@{
  203. void dumpShape(const char* filename);
  204. void saveShape(const char* filename);
  205. ///@}
  206. /// @name Nodes
  207. ///@{
  208. S32 getNodeCount();
  209. S32 getNodeIndex(const char* name);
  210. const char* getNodeName(S32 index);
  211. const char* getNodeParentName(const char* name);
  212. bool setNodeParent(const char* name, const char* parentName);
  213. S32 getNodeChildCount(const char* name);
  214. const char* getNodeChildName(const char* name, S32 index);
  215. S32 getNodeObjectCount(const char* name);
  216. const char* getNodeObjectName(const char* name, S32 index);
  217. TransformF getNodeTransform(const char* name, bool isWorld = false);
  218. bool setNodeTransform(const char* name, TransformF txfm, bool isWorld = false);
  219. bool renameNode(const char* oldName, const char* newName);
  220. bool addNode(const char* name, const char* parentName, TransformF txfm = TransformF::Identity, bool isWorld = false);
  221. bool removeNode(const char* name);
  222. ///@}
  223. /// @name Materials
  224. ///@{
  225. S32 getTargetCount();
  226. const char* getTargetName(S32 index);
  227. ///@}
  228. ///@{
  229. S32 getObjectCount();
  230. const char* getObjectName(S32 index);
  231. S32 getObjectIndex(const char* name);
  232. const char* getObjectNode(const char* name);
  233. bool setObjectNode(const char* objName, const char* nodeName);
  234. bool renameObject(const char* oldName, const char* newName);
  235. bool removeObject(const char* name);
  236. ///@}
  237. /// @name Meshes
  238. ///@{
  239. S32 getMeshCount(const char* name);
  240. const char* getMeshName(const char* name, S32 index);
  241. S32 getMeshSize(const char* name, S32 index);
  242. bool setMeshSize(const char* name, S32 size);
  243. const char* getMeshType(const char* name);
  244. bool setMeshType(const char* name, const char* type);
  245. const char* getMeshMaterial(const char* name);
  246. bool setMeshMaterial(const char* meshName, const char* matName);
  247. bool addMesh(const char* meshName, const char* srcShape, const char* srcMesh);
  248. bool addPrimitive(const char* meshName, const char* type, const char* params, TransformF txfm, const char* nodeName);
  249. bool removeMesh(const char* name);
  250. ///@}
  251. /// @name Detail Levels
  252. ///@{
  253. Box3F getBounds();
  254. bool setBounds(Box3F bbox);
  255. S32 getDetailLevelCount();
  256. const char* getDetailLevelName(S32 index);
  257. S32 getDetailLevelSize(S32 index);
  258. S32 getDetailLevelIndex(S32 size);
  259. bool renameDetailLevel(const char* oldName, const char* newName);
  260. bool removeDetailLevel(S32 index);
  261. S32 setDetailLevelSize(S32 index, S32 newSize);
  262. S32 getImposterDetailLevel();
  263. const char* getImposterSettings(S32 index);
  264. S32 addImposter(S32 size, S32 equatorSteps, S32 polarSteps, S32 dl, S32 dim, bool includePoles, F32 polarAngle);
  265. bool removeImposter();
  266. bool addCollisionDetail(S32 size, const char* type, const char* target, S32 depth = 4, F32 merge = 30.0f, F32 concavity = 30.0f, S32 maxVerts = 32, F32 boxMaxError = 0, F32 sphereMaxError = 0, F32 capsuleMaxError = 0);
  267. ///@}
  268. /// @name Sequences
  269. ///@{
  270. S32 getSequenceCount();
  271. S32 getSequenceIndex(const char* name);
  272. const char* getSequenceName(S32 index);
  273. const char* getSequenceSource(const char* name);
  274. S32 getSequenceFrameCount(const char* name);
  275. F32 getSequencePriority(const char* name);
  276. bool setSequencePriority(const char* name, F32 priority);
  277. const char* getSequenceGroundSpeed(const char* name);
  278. bool setSequenceGroundSpeed(const char* name, Point3F transSpeed, Point3F rotSpeed = Point3F::Zero);
  279. bool getSequenceCyclic(const char* name);
  280. bool setSequenceCyclic(const char* name, bool cyclic);
  281. const char* getSequenceBlend(const char* name);
  282. bool setSequenceBlend(const char* name, bool blend, const char* blendSeq, S32 blendFrame);
  283. bool renameSequence(const char* oldName, const char* newName);
  284. bool addSequence(const char* source, const char* name, S32 start = 0, S32 end = -1, bool padRot = true, bool padTrans = false);
  285. bool removeSequence(const char* name);
  286. ///@}
  287. /// @name Triggers
  288. ///@{
  289. S32 getTriggerCount(const char* name);
  290. const char* getTrigger(const char* name, S32 index);
  291. bool addTrigger(const char* name, S32 keyframe, S32 state);
  292. bool removeTrigger(const char* name, S32 keyframe, S32 state);
  293. ///@}
  294. };
  295. typedef domUpAxisType TSShapeConstructorUpAxis;
  296. typedef ColladaUtils::ImportOptions::eLodType TSShapeConstructorLodType;
  297. typedef ColladaUtils::ImportOptions::eAnimTimingType TSShapeConstructorAnimType;
  298. DefineEnumType(TSShapeConstructorUpAxis);
  299. DefineEnumType(TSShapeConstructorLodType);
  300. DefineEnumType(TSShapeConstructorAnimType);
  301. class TSShapeConstructorMethodActionCallback
  302. {
  303. TSShapeConstructor* mObject;
  304. public:
  305. TSShapeConstructorMethodActionCallback(TSShapeConstructor* object) : mObject(object) { ; }
  306. ~TSShapeConstructorMethodActionCallback() { mObject->onActionPerformed(); }
  307. };
  308. /* This macro simplifies the definition of a TSShapeConstructor API method. It
  309. wraps the actual EngineMethod definition and automatically calls the real
  310. class method. It also creates a ChangeSet::Comand (with all arguments stored
  311. as strings). The one drawback is that it includes the open brace for the real
  312. class method, so to keep the code looking mostly normal, such methods start
  313. with another open brace, and end with a double closing brace. Not perfect,
  314. but a lot better than having to type out the argument list multiple times for
  315. the 50 odd API functions. */
  316. #define DefineTSShapeConstructorMethod( name, retType, args, defArgs, rawArgs, defRet, usage ) \
  317. DefineEngineMethod( TSShapeConstructor, name, retType, args, defArgs, usage ) \
  318. { \
  319. /* Check that shape is loaded */ \
  320. if( !object->getShape() ) \
  321. { \
  322. Con::errorf( "TSShapeConstructor::" #name " - shape not loaded" ); \
  323. return defRet; \
  324. } \
  325. TSShapeConstructorMethodActionCallback actionCallback(object); \
  326. return object->name rawArgs ; \
  327. } \
  328. /* Define the real TSShapeConstructor method */ \
  329. retType TSShapeConstructor::name args \
  330. { \
  331. /* Initialise change set command (may or may not be added) */ \
  332. TSShapeConstructor::ChangeSet::Command newCmd( #name ); \
  333. newCmd.addArgs rawArgs ; \
  334. TORQUE_UNUSED(newCmd);
  335. /* This macro just hides the name of the auto-created ChangeSet::Command from
  336. above, so we are free to change the implementation later if needed */
  337. #define ADD_TO_CHANGE_SET() mChangeSet.add( newCmd );
  338. #endif