SceneGroup.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. #include "SceneGroup.h"
  2. #include "gameBase/gameConnection.h"
  3. #include "gfx/gfxDrawUtil.h"
  4. #include "gfx/gfxTransformSaver.h"
  5. #include "gui/editor/inspector/group.h"
  6. #include "gui/worldEditor/editor.h"
  7. #include "math/mathIO.h"
  8. #include "physics/physicsShape.h"
  9. #include "renderInstance/renderPassManager.h"
  10. #include "scene/sceneRenderState.h"
  11. IMPLEMENT_CO_NETOBJECT_V1(SceneGroup);
  12. ConsoleDocClass(SceneGroup,
  13. "@brief A collection of arbitrary objects which can be allocated and manipulated as a group.\n\n"
  14. "%SceneGroup always points to a (.SceneGroup) file which defines its objects. In "
  15. "fact more than one %SceneGroup can reference this file and both will update "
  16. "if the file is modified.\n\n"
  17. "%SceneGroup is a very simple object and only exists on the server. When it is "
  18. "created it allocates children objects by reading the (.SceneGroup) file like "
  19. "a list of instructions. It then sets their transform relative to the %SceneGroup "
  20. "and Torque networking handles the rest by ghosting the new objects to clients. "
  21. "%SceneGroup itself is not ghosted.\n\n"
  22. "@ingroup enviroMisc"
  23. );
  24. SceneGroup::SceneGroup()
  25. {
  26. // Not ghosted unless we're editing
  27. mNetFlags.clear(Ghostable | ScopeAlways);
  28. mTypeMask |= StaticObjectType;
  29. }
  30. SceneGroup::~SceneGroup()
  31. {
  32. }
  33. void SceneGroup::initPersistFields()
  34. {
  35. docsURL;
  36. addGroup("SceneGroup");
  37. endGroup("SceneGroup");
  38. Parent::initPersistFields();
  39. }
  40. bool SceneGroup::onAdd()
  41. {
  42. if (!Parent::onAdd())
  43. return false;
  44. mObjBox.set(Point3F(-0.5f, -0.5f, -0.5f),
  45. Point3F(0.5f, 0.5f, 0.5f));
  46. resetWorldBox();
  47. // Not added to the scene unless we are editing.
  48. if (gEditingMission)
  49. onEditorEnable();
  50. addToScene();
  51. return true;
  52. }
  53. void SceneGroup::onRemove()
  54. {
  55. removeFromScene();
  56. Parent::onRemove();
  57. }
  58. void SceneGroup::onEditorEnable()
  59. {
  60. if (isClientObject())
  61. return;
  62. // Just in case we are already in the scene, lets not cause an assert.
  63. if (mContainer != NULL)
  64. return;
  65. // Enable ghosting so we can see this on the client.
  66. mNetFlags.set(Ghostable);
  67. setScopeAlways();
  68. addToScene();
  69. Parent::onEditorEnable();
  70. }
  71. void SceneGroup::onEditorDisable()
  72. {
  73. if (isClientObject())
  74. return;
  75. // Just in case we are not in the scene, lets not cause an assert.
  76. if (mContainer == NULL)
  77. return;
  78. // Do not need this on the client if we are not editing.
  79. removeFromScene();
  80. mNetFlags.clear(Ghostable);
  81. clearScopeAlways();
  82. Parent::onEditorDisable();
  83. }
  84. void SceneGroup::inspectPostApply()
  85. {
  86. Parent::inspectPostApply();
  87. }
  88. void SceneGroup::onInspect(GuiInspector* inspector)
  89. {
  90. //Put the SubScene group before everything that'd be SubScene-effecting, for orginazational purposes
  91. GuiInspectorGroup* sceneGroupGrp = inspector->findExistentGroup(StringTable->insert("SceneGroup"));
  92. if (!sceneGroupGrp)
  93. return;
  94. GuiControl* stack = dynamic_cast<GuiControl*>(sceneGroupGrp->findObjectByInternalName(StringTable->insert("Stack")));
  95. //Regen bounds button
  96. GuiInspectorField* regenFieldGui = sceneGroupGrp->createInspectorField();
  97. regenFieldGui->init(inspector, sceneGroupGrp);
  98. regenFieldGui->setSpecialEditField(true);
  99. regenFieldGui->setTargetObject(this);
  100. StringTableEntry fldnm = StringTable->insert("RegenerateBounds");
  101. regenFieldGui->setSpecialEditVariableName(fldnm);
  102. regenFieldGui->setInspectorField(NULL, fldnm);
  103. regenFieldGui->setDocs("");
  104. stack->addObject(regenFieldGui);
  105. GuiButtonCtrl* regenButton = new GuiButtonCtrl();
  106. regenButton->registerObject();
  107. regenButton->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiButtonProfile");
  108. regenButton->setText("Regenerate Bounds");
  109. regenButton->resize(Point2I::Zero, regenFieldGui->getExtent());
  110. regenButton->setHorizSizing(GuiControl::horizResizeWidth);
  111. regenButton->setVertSizing(GuiControl::vertResizeHeight);
  112. char rgBuffer[512];
  113. dSprintf(rgBuffer, 512, "%d.recalculateBounds();", this->getId());
  114. regenButton->setConsoleCommand(rgBuffer);
  115. regenFieldGui->addObject(regenButton);
  116. }
  117. void SceneGroup::setTransform(const MatrixF& mat)
  118. {
  119. //transform difference
  120. MatrixF oldTransform = getTransform();
  121. Parent::setTransform(mat);
  122. // Calculate the delta transformation
  123. MatrixF deltaTransform;
  124. oldTransform.inverse();
  125. deltaTransform.mul(oldTransform, getTransform());
  126. if (isServerObject())
  127. {
  128. setMaskBits(TransformMask);
  129. // Update all child transforms
  130. for (SimSetIterator itr(this); *itr; ++itr)
  131. {
  132. SceneObject* child = dynamic_cast<SceneObject*>(*itr);
  133. if (child)
  134. {
  135. MatrixF childTransform = child->getTransform();
  136. MatrixF relativeTransform;
  137. relativeTransform.mul(deltaTransform, childTransform);
  138. child->setTransform(relativeTransform);
  139. child->setScale(childTransform.getScale()); //we don't modify scale
  140. }
  141. }
  142. }
  143. }
  144. void SceneGroup::setRenderTransform(const MatrixF& mat)
  145. {
  146. //transform difference
  147. MatrixF oldTransform = getRenderTransform();
  148. Parent::setRenderTransform(mat);
  149. // Calculate the delta transformation
  150. MatrixF deltaTransform;
  151. oldTransform.inverse();
  152. deltaTransform.mul(oldTransform, getRenderTransform());
  153. // Update all child transforms
  154. for (SimSetIterator itr(this); *itr; ++itr)
  155. {
  156. SceneObject* child = dynamic_cast<SceneObject*>(*itr);
  157. if (child)
  158. {
  159. MatrixF childTransform = child->getRenderTransform();
  160. MatrixF relativeTransform;
  161. relativeTransform.mul(deltaTransform, childTransform);
  162. child->setRenderTransform(relativeTransform);
  163. child->setScale(childTransform.getScale()); //we don't modify scale
  164. }
  165. }
  166. }
  167. void SceneGroup::addObject(SimObject* object)
  168. {
  169. Parent::addObject(object);
  170. // Recalculate the bounding box from scratch (simpler but potentially costly)
  171. recalculateBoundingBox();
  172. }
  173. void SceneGroup::removeObject(SimObject* object)
  174. {
  175. Parent::removeObject(object);
  176. // Recalculate the bounding box from scratch (simpler but potentially costly)
  177. recalculateBoundingBox();
  178. }
  179. void SceneGroup::recalculateBoundingBox()
  180. {
  181. if (empty())
  182. return;
  183. // Reset the bounding box
  184. Box3F bounds;
  185. bounds.minExtents.set(1e10, 1e10, 1e10);
  186. bounds.maxExtents.set(-1e10, -1e10, -1e10);
  187. // Extend the bounding box to include each child's bounding box
  188. for (SimSetIterator itr(this); *itr; ++itr)
  189. {
  190. SceneObject* child = dynamic_cast<SceneObject*>(*itr);
  191. if (child)
  192. {
  193. const Box3F& childBox = child->getWorldBox();
  194. bounds.minExtents.setMin(childBox.minExtents);
  195. bounds.maxExtents.setMax(childBox.maxExtents);
  196. }
  197. }
  198. MatrixF newTrans = mObjToWorld;
  199. newTrans.setPosition(bounds.getCenter());
  200. Parent::setTransform(newTrans);
  201. mObjScale = Point3F(bounds.len_x(), bounds.len_y(), bounds.len_z());
  202. mWorldBox = bounds;
  203. resetObjectBox();
  204. setMaskBits(TransformMask);
  205. }
  206. U32 SceneGroup::packUpdate(NetConnection* conn, U32 mask, BitStream* stream)
  207. {
  208. U32 retMask = Parent::packUpdate(conn, mask, stream);
  209. mathWrite(*stream, mObjBox);
  210. if (stream->writeFlag(mask & TransformMask))
  211. {
  212. mathWrite(*stream, getTransform());
  213. mathWrite(*stream, getScale());
  214. }
  215. return retMask;
  216. }
  217. void SceneGroup::unpackUpdate(NetConnection* conn, BitStream* stream)
  218. {
  219. Parent::unpackUpdate(conn, stream);
  220. mathRead(*stream, &mObjBox);
  221. resetWorldBox();
  222. // TransformMask
  223. if (stream->readFlag())
  224. {
  225. mathRead(*stream, &mObjToWorld);
  226. mathRead(*stream, &mObjScale);
  227. setTransform(mObjToWorld);
  228. }
  229. }
  230. bool SceneGroup::buildPolyList(PolyListContext context, AbstractPolyList* polyList, const Box3F& box, const SphereF& sphere)
  231. {
  232. Vector<SceneObject*> foundObjects;
  233. if (empty())
  234. {
  235. Con::warnf("SceneGroup::buildPolyList() - SceneGroup %s is empty!", getName());
  236. return false;
  237. }
  238. findObjectByType(foundObjects);
  239. for (S32 i = 0; i < foundObjects.size(); i++)
  240. {
  241. foundObjects[i]->buildPolyList(context, polyList, box, sphere);
  242. }
  243. return true;
  244. }
  245. bool SceneGroup::buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F& box, const SphereF& sphere)
  246. {
  247. Vector<SceneObject*> foundObjects;
  248. findObjectByType(foundObjects);
  249. for (S32 i = 0; i < foundObjects.size(); i++)
  250. {
  251. foundObjects[i]->buildExportPolyList(exportData, box, sphere);
  252. }
  253. return true;
  254. }
  255. void SceneGroup::getUtilizedAssets(Vector<StringTableEntry>* usedAssetsList)
  256. {
  257. //if (empty())
  258. return;
  259. Vector<SceneObject*> foundObjects;
  260. findObjectByType(foundObjects);
  261. for (S32 i = 0; i < foundObjects.size(); i++)
  262. {
  263. SceneObject* child = foundObjects[i];
  264. child->getUtilizedAssets(usedAssetsList);
  265. }
  266. }
  267. DefineEngineMethod(SceneGroup, recalculateBounds, void, (), ,
  268. "Recalculates the SceneGroups' bounds and centerpoint.\n")
  269. {
  270. object->recalculateBoundingBox();
  271. }