SceneGroup.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  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. Parent::onInspect(inspector);
  91. //Put the SubScene group before everything that'd be SubScene-effecting, for orginazational purposes
  92. GuiInspectorGroup* sceneGroupGrp = inspector->findExistentGroup(StringTable->insert("Editing"));
  93. if (!sceneGroupGrp)
  94. return;
  95. GuiControl* stack = dynamic_cast<GuiControl*>(sceneGroupGrp->findObjectByInternalName(StringTable->insert("Stack")));
  96. //Regen bounds button
  97. GuiInspectorField* regenFieldGui = sceneGroupGrp->createInspectorField();
  98. regenFieldGui->init(inspector, sceneGroupGrp);
  99. regenFieldGui->setSpecialEditField(true);
  100. regenFieldGui->setTargetObject(this);
  101. StringTableEntry fldnm = StringTable->insert("RegenerateBounds");
  102. regenFieldGui->setSpecialEditVariableName(fldnm);
  103. regenFieldGui->setInspectorField(NULL, fldnm);
  104. regenFieldGui->setDocs("");
  105. stack->addObject(regenFieldGui);
  106. GuiButtonCtrl* regenButton = new GuiButtonCtrl();
  107. regenButton->registerObject();
  108. regenButton->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiButtonProfile");
  109. regenButton->setText("Regenerate Bounds");
  110. regenButton->resize(Point2I::Zero, regenFieldGui->getExtent());
  111. regenButton->setHorizSizing(GuiControl::horizResizeWidth);
  112. regenButton->setVertSizing(GuiControl::vertResizeHeight);
  113. char rgBuffer[512];
  114. dSprintf(rgBuffer, 512, "%d.recalculateBounds();", this->getId());
  115. regenButton->setConsoleCommand(rgBuffer);
  116. regenFieldGui->addObject(regenButton);
  117. }
  118. void SceneGroup::setTransform(const MatrixF& mat)
  119. {
  120. //transform difference
  121. MatrixF oldTransform = getTransform();
  122. Parent::setTransform(mat);
  123. // Calculate the delta transformation
  124. MatrixF deltaTransform;
  125. oldTransform.inverse();
  126. deltaTransform.mul(oldTransform, getTransform());
  127. if (isServerObject())
  128. {
  129. setMaskBits(TransformMask);
  130. // Update all child transforms
  131. for (SimSetIterator itr(this); *itr; ++itr)
  132. {
  133. SceneObject* child = dynamic_cast<SceneObject*>(*itr);
  134. if (child)
  135. {
  136. MatrixF childTransform = child->getTransform();
  137. MatrixF relativeTransform;
  138. relativeTransform.mul(deltaTransform, childTransform);
  139. child->setTransform(relativeTransform);
  140. child->setScale(childTransform.getScale()); //we don't modify scale
  141. }
  142. }
  143. }
  144. }
  145. void SceneGroup::setRenderTransform(const MatrixF& mat)
  146. {
  147. //transform difference
  148. MatrixF oldTransform = getRenderTransform();
  149. Parent::setRenderTransform(mat);
  150. // Calculate the delta transformation
  151. MatrixF deltaTransform;
  152. oldTransform.inverse();
  153. deltaTransform.mul(oldTransform, getRenderTransform());
  154. // Update all child transforms
  155. for (SimSetIterator itr(this); *itr; ++itr)
  156. {
  157. SceneObject* child = dynamic_cast<SceneObject*>(*itr);
  158. if (child)
  159. {
  160. MatrixF childTransform = child->getRenderTransform();
  161. MatrixF relativeTransform;
  162. relativeTransform.mul(deltaTransform, childTransform);
  163. child->setRenderTransform(relativeTransform);
  164. child->setScale(childTransform.getScale()); //we don't modify scale
  165. }
  166. }
  167. }
  168. void SceneGroup::addObject(SimObject* object)
  169. {
  170. Parent::addObject(object);
  171. // Recalculate the bounding box from scratch (simpler but potentially costly)
  172. recalculateBoundingBox();
  173. }
  174. void SceneGroup::removeObject(SimObject* object)
  175. {
  176. Parent::removeObject(object);
  177. // Recalculate the bounding box from scratch (simpler but potentially costly)
  178. recalculateBoundingBox();
  179. }
  180. void SceneGroup::recalculateBoundingBox()
  181. {
  182. if (empty())
  183. return;
  184. // Reset the bounding box
  185. Box3F bounds;
  186. bounds.minExtents.set(1e10, 1e10, 1e10);
  187. bounds.maxExtents.set(-1e10, -1e10, -1e10);
  188. // Extend the bounding box to include each child's bounding box
  189. for (SimSetIterator itr(this); *itr; ++itr)
  190. {
  191. SceneObject* child = dynamic_cast<SceneObject*>(*itr);
  192. if (child)
  193. {
  194. const Box3F& childBox = child->getWorldBox();
  195. bounds.minExtents.setMin(childBox.minExtents);
  196. bounds.maxExtents.setMax(childBox.maxExtents);
  197. }
  198. }
  199. MatrixF newTrans = mObjToWorld;
  200. newTrans.setPosition(bounds.getCenter());
  201. Parent::setTransform(newTrans);
  202. mObjScale = Point3F(bounds.len_x(), bounds.len_y(), bounds.len_z());
  203. mWorldBox = bounds;
  204. resetObjectBox();
  205. setMaskBits(TransformMask);
  206. }
  207. U32 SceneGroup::packUpdate(NetConnection* conn, U32 mask, BitStream* stream)
  208. {
  209. U32 retMask = Parent::packUpdate(conn, mask, stream);
  210. mathWrite(*stream, mObjBox);
  211. if (stream->writeFlag(mask & TransformMask))
  212. {
  213. mathWrite(*stream, getTransform());
  214. mathWrite(*stream, getScale());
  215. }
  216. return retMask;
  217. }
  218. void SceneGroup::unpackUpdate(NetConnection* conn, BitStream* stream)
  219. {
  220. Parent::unpackUpdate(conn, stream);
  221. mathRead(*stream, &mObjBox);
  222. resetWorldBox();
  223. // TransformMask
  224. if (stream->readFlag())
  225. {
  226. mathRead(*stream, &mObjToWorld);
  227. mathRead(*stream, &mObjScale);
  228. setTransform(mObjToWorld);
  229. }
  230. }
  231. bool SceneGroup::buildPolyList(PolyListContext context, AbstractPolyList* polyList, const Box3F& box, const SphereF& sphere)
  232. {
  233. Vector<SceneObject*> foundObjects;
  234. if (empty())
  235. {
  236. Con::warnf("SceneGroup::buildPolyList() - SceneGroup %s is empty!", getName());
  237. return false;
  238. }
  239. findObjectByType(foundObjects);
  240. for (S32 i = 0; i < foundObjects.size(); i++)
  241. {
  242. foundObjects[i]->buildPolyList(context, polyList, box, sphere);
  243. }
  244. return true;
  245. }
  246. bool SceneGroup::buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F& box, const SphereF& sphere)
  247. {
  248. Vector<SceneObject*> foundObjects;
  249. findObjectByType(foundObjects);
  250. for (S32 i = 0; i < foundObjects.size(); i++)
  251. {
  252. foundObjects[i]->buildExportPolyList(exportData, box, sphere);
  253. }
  254. return true;
  255. }
  256. void SceneGroup::getUtilizedAssets(Vector<StringTableEntry>* usedAssetsList)
  257. {
  258. //if (empty())
  259. return;
  260. Vector<SceneObject*> foundObjects;
  261. findObjectByType(foundObjects);
  262. for (S32 i = 0; i < foundObjects.size(); i++)
  263. {
  264. SceneObject* child = foundObjects[i];
  265. child->getUtilizedAssets(usedAssetsList);
  266. }
  267. }
  268. DefineEngineMethod(SceneGroup, recalculateBounds, void, (), ,
  269. "Recalculates the SceneGroups' bounds and centerpoint.\n")
  270. {
  271. object->recalculateBoundingBox();
  272. }