BsEditorTestSuite.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Testing/BsEditorTestSuite.h"
  4. #include "Scene/BsSceneObject.h"
  5. #include "UndoRedo/BsCmdRecordSO.h"
  6. #include "UndoRedo/BsCmdDeleteSO.h"
  7. #include "UndoRedo/BsUndoRedo.h"
  8. #include "Reflection/BsRTTIType.h"
  9. #include "RTTI/BsGameObjectRTTI.h"
  10. #include "Serialization/BsBinarySerializer.h"
  11. #include "Serialization/BsMemorySerializer.h"
  12. #include "Serialization/BsBinaryDiff.h"
  13. #include "Scene/BsPrefab.h"
  14. #include "Resources/BsResources.h"
  15. #include "Scene/BsPrefabDiff.h"
  16. #include "Allocators/BsFrameAlloc.h"
  17. #include "FileSystem/BsFileSystem.h"
  18. #include "Scene/BsSceneManager.h"
  19. namespace bs
  20. {
  21. class TestComponentARTTI : public RTTIType<TestComponentA, Component, TestComponentARTTI>
  22. {
  23. private:
  24. HSceneObject& getRef1(TestComponentA* obj) { return obj->ref1; }
  25. void setRef1(TestComponentA* obj, HSceneObject& val) { obj->ref1 = val; }
  26. HComponent& getRef2(TestComponentA* obj) { return obj->ref2; }
  27. void setRef2(TestComponentA* obj, HComponent& val) { obj->ref2 = val; }
  28. public:
  29. TestComponentARTTI()
  30. {
  31. addReflectableField("ref1", 0, &TestComponentARTTI::getRef1, &TestComponentARTTI::setRef1);
  32. addReflectableField("ref2", 1, &TestComponentARTTI::getRef2, &TestComponentARTTI::setRef2);
  33. }
  34. const String& getRTTIName() override
  35. {
  36. static String name = "TestComponentA";
  37. return name;
  38. }
  39. UINT32 getRTTIId() override
  40. {
  41. return TID_TestComponentA;
  42. }
  43. SPtr<IReflectable> newRTTIObject() override
  44. {
  45. return GameObjectRTTI::createGameObject<TestComponentA>();
  46. }
  47. };
  48. class TestComponentBRTTI : public RTTIType<TestComponentB, Component, TestComponentBRTTI>
  49. {
  50. private:
  51. HSceneObject& getRef1(TestComponentB* obj) { return obj->ref1; }
  52. void setRef1(TestComponentB* obj, HSceneObject& val) { obj->ref1 = val; }
  53. String& getVal1(TestComponentB* obj) { return obj->val1; }
  54. void setVal1(TestComponentB* obj, String& val) { obj->val1 = val; }
  55. public:
  56. TestComponentBRTTI()
  57. {
  58. addReflectableField("ref1", 0, &TestComponentBRTTI::getRef1, &TestComponentBRTTI::setRef1);
  59. addPlainField("val1", 1, &TestComponentBRTTI::getVal1, &TestComponentBRTTI::setVal1);
  60. }
  61. const String& getRTTIName() override
  62. {
  63. static String name = "TestComponentB";
  64. return name;
  65. }
  66. UINT32 getRTTIId() override
  67. {
  68. return TID_TestComponentB;
  69. }
  70. SPtr<IReflectable> newRTTIObject() override
  71. {
  72. return GameObjectRTTI::createGameObject<TestComponentB>();
  73. }
  74. };
  75. TestComponentA::TestComponentA(const HSceneObject& parent)
  76. :Component(parent)
  77. {}
  78. RTTITypeBase* TestComponentA::getRTTIStatic()
  79. {
  80. return TestComponentARTTI::instance();
  81. }
  82. RTTITypeBase* TestComponentA::getRTTI() const
  83. {
  84. return TestComponentA::getRTTIStatic();
  85. }
  86. TestComponentB::TestComponentB(const HSceneObject& parent)
  87. :Component(parent)
  88. {}
  89. RTTITypeBase* TestComponentB::getRTTIStatic()
  90. {
  91. return TestComponentBRTTI::instance();
  92. }
  93. RTTITypeBase* TestComponentB::getRTTI() const
  94. {
  95. return TestComponentB::getRTTIStatic();
  96. }
  97. struct TestObjectB : IReflectable
  98. {
  99. UINT32 intA = 100;
  100. String strA = "100";
  101. /************************************************************************/
  102. /* RTTI */
  103. /************************************************************************/
  104. public:
  105. friend class TestObjectBRTTI;
  106. static RTTITypeBase* getRTTIStatic();
  107. RTTITypeBase* getRTTI() const override;
  108. };
  109. struct TestObjectA : IReflectable
  110. {
  111. TestObjectA()
  112. {
  113. arrStrA = { "10", "11", "12" };
  114. arrStrB = { "13", "14", "15" };
  115. arrStrC = { "16", "17", "18" };
  116. arrObjA = { TestObjectB(), TestObjectB(), TestObjectB() };
  117. arrObjB = { TestObjectB(), TestObjectB(), TestObjectB() };
  118. arrObjPtrA = { bs_shared_ptr_new<TestObjectB>(), bs_shared_ptr_new<TestObjectB>(), bs_shared_ptr_new<TestObjectB>() };
  119. arrObjPtrB = { bs_shared_ptr_new<TestObjectB>(), bs_shared_ptr_new<TestObjectB>(), bs_shared_ptr_new<TestObjectB>() };
  120. }
  121. UINT32 intA = 5;
  122. String strA = "5";
  123. String strB = "7";
  124. TestObjectB objA;
  125. TestObjectB objB;
  126. SPtr<TestObjectB> objPtrA = bs_shared_ptr_new<TestObjectB>();
  127. SPtr<TestObjectB> objPtrB = bs_shared_ptr_new<TestObjectB>();
  128. SPtr<TestObjectB> objPtrC = bs_shared_ptr_new<TestObjectB>();
  129. SPtr<TestObjectB> objPtrD = nullptr;
  130. Vector<String> arrStrA;
  131. Vector<String> arrStrB;
  132. Vector<String> arrStrC;
  133. Vector<TestObjectB> arrObjA;
  134. Vector<TestObjectB> arrObjB;
  135. Vector<SPtr<TestObjectB>> arrObjPtrA;
  136. Vector<SPtr<TestObjectB>> arrObjPtrB;
  137. /************************************************************************/
  138. /* RTTI */
  139. /************************************************************************/
  140. public:
  141. friend class TestObjectARTTI;
  142. static RTTITypeBase* getRTTIStatic();
  143. RTTITypeBase* getRTTI() const override;
  144. };
  145. class TestObjectARTTI : public RTTIType < TestObjectA, IReflectable, TestObjectARTTI >
  146. {
  147. private:
  148. BS_BEGIN_RTTI_MEMBERS
  149. BS_RTTI_MEMBER_PLAIN(intA, 0)
  150. BS_RTTI_MEMBER_PLAIN(strA, 1)
  151. BS_RTTI_MEMBER_PLAIN(strB, 2)
  152. BS_RTTI_MEMBER_REFL(objA, 3)
  153. BS_RTTI_MEMBER_REFL(objB, 4)
  154. BS_RTTI_MEMBER_REFLPTR(objPtrA, 5)
  155. BS_RTTI_MEMBER_REFLPTR(objPtrB, 6)
  156. BS_RTTI_MEMBER_REFLPTR(objPtrC, 7)
  157. BS_RTTI_MEMBER_REFLPTR(objPtrD, 8)
  158. BS_RTTI_MEMBER_PLAIN_ARRAY(arrStrA, 9)
  159. BS_RTTI_MEMBER_PLAIN_ARRAY(arrStrB, 10)
  160. BS_RTTI_MEMBER_PLAIN_ARRAY(arrStrC, 11)
  161. BS_RTTI_MEMBER_REFL_ARRAY(arrObjA, 12)
  162. BS_RTTI_MEMBER_REFL_ARRAY(arrObjB, 13)
  163. BS_RTTI_MEMBER_REFLPTR_ARRAY(arrObjPtrA, 14)
  164. BS_RTTI_MEMBER_REFLPTR_ARRAY(arrObjPtrB, 15)
  165. BS_END_RTTI_MEMBERS
  166. public:
  167. TestObjectARTTI()
  168. :mInitMembers(this)
  169. { }
  170. const String& getRTTIName() override
  171. {
  172. static String name = "TestObjectA";
  173. return name;
  174. }
  175. UINT32 getRTTIId() override
  176. {
  177. return TID_TestObjectA;
  178. }
  179. SPtr<IReflectable> newRTTIObject() override
  180. {
  181. return bs_shared_ptr_new<TestObjectA>();
  182. }
  183. };
  184. class TestObjectBRTTI : public RTTIType < TestObjectB, IReflectable, TestObjectBRTTI >
  185. {
  186. private:
  187. BS_BEGIN_RTTI_MEMBERS
  188. BS_RTTI_MEMBER_PLAIN(intA, 0)
  189. BS_RTTI_MEMBER_PLAIN(strA, 1)
  190. BS_END_RTTI_MEMBERS
  191. public:
  192. TestObjectBRTTI()
  193. :mInitMembers(this)
  194. { }
  195. const String& getRTTIName() override
  196. {
  197. static String name = "TestObjectB";
  198. return name;
  199. }
  200. UINT32 getRTTIId() override
  201. {
  202. return TID_TestObjectB;
  203. }
  204. SPtr<IReflectable> newRTTIObject() override
  205. {
  206. return bs_shared_ptr_new<TestObjectB>();
  207. }
  208. };
  209. RTTITypeBase* TestObjectB::getRTTIStatic()
  210. {
  211. return TestObjectBRTTI::instance();
  212. }
  213. RTTITypeBase* TestObjectB::getRTTI() const
  214. {
  215. return TestObjectB::getRTTIStatic();
  216. }
  217. RTTITypeBase* TestObjectA::getRTTIStatic()
  218. {
  219. return TestObjectARTTI::instance();
  220. }
  221. RTTITypeBase* TestObjectA::getRTTI() const
  222. {
  223. return TestObjectA::getRTTIStatic();
  224. }
  225. class TestComponentC : public Component
  226. {
  227. public:
  228. TestObjectA obj;
  229. /************************************************************************/
  230. /* COMPONENT OVERRIDES */
  231. /************************************************************************/
  232. protected:
  233. friend class SceneObject;
  234. TestComponentC(const HSceneObject& parent)
  235. :Component(parent)
  236. {}
  237. /************************************************************************/
  238. /* RTTI */
  239. /************************************************************************/
  240. public:
  241. friend class TestComponentCRTTI;
  242. static RTTITypeBase* getRTTIStatic();
  243. RTTITypeBase* getRTTI() const override;
  244. protected:
  245. TestComponentC() {} // Serialization only
  246. };
  247. class TestComponentD : public Component
  248. {
  249. public:
  250. TestObjectB obj;
  251. /************************************************************************/
  252. /* COMPONENT OVERRIDES */
  253. /************************************************************************/
  254. protected:
  255. friend class SceneObject;
  256. TestComponentD(const HSceneObject& parent)
  257. :Component(parent)
  258. {}
  259. /************************************************************************/
  260. /* RTTI */
  261. /************************************************************************/
  262. public:
  263. friend class TestComponentDRTTI;
  264. static RTTITypeBase* getRTTIStatic();
  265. virtual RTTITypeBase* getRTTI() const override;
  266. protected:
  267. TestComponentD() {} // Serialization only
  268. };
  269. class TestComponentCRTTI : public RTTIType < TestComponentC, Component, TestComponentCRTTI >
  270. {
  271. private:
  272. BS_BEGIN_RTTI_MEMBERS
  273. BS_RTTI_MEMBER_REFL(obj, 0)
  274. BS_END_RTTI_MEMBERS
  275. public:
  276. TestComponentCRTTI()
  277. :mInitMembers(this)
  278. { }
  279. const String& getRTTIName() override
  280. {
  281. static String name = "TestComponentC";
  282. return name;
  283. }
  284. UINT32 getRTTIId() override
  285. {
  286. return TID_TestComponentC;
  287. }
  288. SPtr<IReflectable> newRTTIObject() override
  289. {
  290. return GameObjectRTTI::createGameObject<TestComponentC>();
  291. }
  292. };
  293. class TestComponentDRTTI : public RTTIType < TestComponentD, Component, TestComponentDRTTI >
  294. {
  295. private:
  296. BS_BEGIN_RTTI_MEMBERS
  297. BS_RTTI_MEMBER_REFL(obj, 0)
  298. BS_END_RTTI_MEMBERS
  299. public:
  300. TestComponentDRTTI()
  301. :mInitMembers(this)
  302. { }
  303. const String& getRTTIName() override
  304. {
  305. static String name = "TestComponentD";
  306. return name;
  307. }
  308. UINT32 getRTTIId() override
  309. {
  310. return TID_TestComponentD;
  311. }
  312. SPtr<IReflectable> newRTTIObject() override
  313. {
  314. return GameObjectRTTI::createGameObject<TestComponentD>();
  315. }
  316. };
  317. RTTITypeBase* TestComponentC::getRTTIStatic()
  318. {
  319. return TestComponentCRTTI::instance();
  320. }
  321. RTTITypeBase* TestComponentC::getRTTI() const
  322. {
  323. return TestComponentC::getRTTIStatic();
  324. }
  325. RTTITypeBase* TestComponentD::getRTTIStatic()
  326. {
  327. return TestComponentDRTTI::instance();
  328. }
  329. RTTITypeBase* TestComponentD::getRTTI() const
  330. {
  331. return TestComponentD::getRTTIStatic();
  332. }
  333. EditorTestSuite::EditorTestSuite()
  334. {
  335. BS_ADD_TEST(EditorTestSuite::SceneObjectRecord_UndoRedo);
  336. BS_ADD_TEST(EditorTestSuite::SceneObjectDelete_UndoRedo);
  337. BS_ADD_TEST(EditorTestSuite::BinaryDiff);
  338. BS_ADD_TEST(EditorTestSuite::TestPrefabComplex);
  339. BS_ADD_TEST(EditorTestSuite::TestPrefabDiff);
  340. BS_ADD_TEST(EditorTestSuite::TestFrameAlloc);
  341. }
  342. void EditorTestSuite::SceneObjectRecord_UndoRedo()
  343. {
  344. HSceneObject so0_0 = SceneObject::create("so0_0");
  345. HSceneObject so1_0 = SceneObject::create("so1_0");
  346. HSceneObject so1_1 = SceneObject::create("so1_1");
  347. HSceneObject so2_0 = SceneObject::create("so2_0");
  348. so1_0->setParent(so0_0);
  349. so1_1->setParent(so0_0);
  350. so2_0->setParent(so1_0);
  351. GameObjectHandle<TestComponentA> cmpA1_1 = so1_1->addComponent<TestComponentA>();
  352. GameObjectHandle<TestComponentB> cmpB1_1 = so0_0->addComponent<TestComponentB>();
  353. HSceneObject soExternal = SceneObject::create("soExternal");
  354. GameObjectHandle<TestComponentA> cmpExternal = soExternal->addComponent<TestComponentA>();
  355. cmpA1_1->ref1 = so2_0;
  356. cmpA1_1->ref2 = cmpB1_1;
  357. cmpB1_1->ref1 = soExternal;
  358. cmpB1_1->val1 = "InitialValue";
  359. cmpExternal->ref1 = so1_1;
  360. cmpExternal->ref2 = cmpA1_1;
  361. CmdRecordSO::execute(so0_0);
  362. cmpB1_1->val1 = "ModifiedValue";
  363. so0_0->setName("modified");
  364. UndoRedo::instance().undo();
  365. BS_TEST_ASSERT(!so0_0.isDestroyed());
  366. BS_TEST_ASSERT(!so1_0.isDestroyed());
  367. BS_TEST_ASSERT(!so1_1.isDestroyed());
  368. BS_TEST_ASSERT(!so2_0.isDestroyed());
  369. BS_TEST_ASSERT(!cmpA1_1.isDestroyed());
  370. BS_TEST_ASSERT(!cmpB1_1.isDestroyed());
  371. BS_TEST_ASSERT(!cmpA1_1->ref1.isDestroyed());
  372. BS_TEST_ASSERT(!cmpA1_1->ref2.isDestroyed());
  373. BS_TEST_ASSERT(!cmpB1_1->ref1.isDestroyed());
  374. BS_TEST_ASSERT(!cmpExternal->ref1.isDestroyed());
  375. BS_TEST_ASSERT(!cmpExternal->ref2.isDestroyed());
  376. BS_TEST_ASSERT(cmpB1_1->val1 == "InitialValue");
  377. BS_TEST_ASSERT(so0_0->getName() == "so0_0");
  378. so0_0->destroy();
  379. soExternal->destroy();
  380. }
  381. void EditorTestSuite::SceneObjectDelete_UndoRedo()
  382. {
  383. HSceneObject so0_0 = SceneObject::create("so0_0");
  384. HSceneObject so1_0 = SceneObject::create("so1_0");
  385. HSceneObject so1_1 = SceneObject::create("so1_1");
  386. HSceneObject so2_0 = SceneObject::create("so2_0");
  387. so1_0->setParent(so0_0);
  388. so1_1->setParent(so0_0);
  389. so2_0->setParent(so1_0);
  390. GameObjectHandle<TestComponentA> cmpA1_1 = so1_1->addComponent<TestComponentA>();
  391. GameObjectHandle<TestComponentB> cmpB1_1 = so1_1->addComponent<TestComponentB>();
  392. HSceneObject soExternal = SceneObject::create("soExternal");
  393. GameObjectHandle<TestComponentA> cmpExternal = soExternal->addComponent<TestComponentA>();
  394. cmpA1_1->ref1 = so2_0;
  395. cmpA1_1->ref2 = cmpB1_1;
  396. cmpB1_1->ref1 = soExternal;
  397. cmpB1_1->val1 = "InitialValue";
  398. cmpExternal->ref1 = so1_1;
  399. cmpExternal->ref2 = cmpA1_1;
  400. CmdDeleteSO::execute(so0_0);
  401. UndoRedo::instance().undo();
  402. BS_TEST_ASSERT(!so0_0.isDestroyed());
  403. BS_TEST_ASSERT(!so1_0.isDestroyed());
  404. BS_TEST_ASSERT(!so1_1.isDestroyed());
  405. BS_TEST_ASSERT(!so2_0.isDestroyed());
  406. BS_TEST_ASSERT(!cmpA1_1.isDestroyed());
  407. BS_TEST_ASSERT(!cmpB1_1.isDestroyed());
  408. BS_TEST_ASSERT(!cmpA1_1->ref1.isDestroyed());
  409. BS_TEST_ASSERT(!cmpA1_1->ref2.isDestroyed());
  410. BS_TEST_ASSERT(!cmpB1_1->ref1.isDestroyed());
  411. BS_TEST_ASSERT(!cmpExternal->ref1.isDestroyed());
  412. BS_TEST_ASSERT(!cmpExternal->ref2.isDestroyed());
  413. BS_TEST_ASSERT(cmpB1_1->val1 == "InitialValue");
  414. so0_0->destroy();
  415. soExternal->destroy();
  416. }
  417. void EditorTestSuite::BinaryDiff()
  418. {
  419. SPtr<TestObjectA> orgObj = bs_shared_ptr_new<TestObjectA>();
  420. SPtr<TestObjectA> newObj = bs_shared_ptr_new<TestObjectA>();
  421. newObj->intA = 995;
  422. newObj->strA = "potato";
  423. newObj->arrStrB = { "orange", "carrot" };
  424. newObj->arrStrC[2] = "banana";
  425. newObj->objB.intA = 9940;
  426. newObj->objPtrB->strA = "kiwi";
  427. newObj->objPtrC = nullptr;
  428. newObj->objPtrD = bs_shared_ptr_new<TestObjectB>();
  429. newObj->arrObjB[1].strA = "strawberry";
  430. newObj->arrObjPtrB[0]->intA = 99100;
  431. BinarySerializer bs;
  432. SPtr<SerializedObject> orgSerialized = bs._encodeToIntermediate(orgObj.get());
  433. SPtr<SerializedObject> newSerialized = bs._encodeToIntermediate(newObj.get());
  434. IDiff& diffHandler = orgObj->getRTTI()->getDiffHandler();
  435. SPtr<SerializedObject> objDiff = diffHandler.generateDiff(orgSerialized, newSerialized);
  436. diffHandler.applyDiff(orgObj, objDiff);
  437. BS_TEST_ASSERT(orgObj->intA == newObj->intA);
  438. BS_TEST_ASSERT(orgObj->strA == newObj->strA);
  439. BS_TEST_ASSERT(orgObj->strB == newObj->strB);
  440. BS_TEST_ASSERT(orgObj->objA.intA == newObj->objA.intA);
  441. BS_TEST_ASSERT(orgObj->objB.intA == newObj->objB.intA);
  442. BS_TEST_ASSERT(orgObj->objPtrA->strA == newObj->objPtrA->strA);
  443. BS_TEST_ASSERT(orgObj->objPtrB->strA == newObj->objPtrB->strA);
  444. BS_TEST_ASSERT(orgObj->objPtrD->strA == newObj->objPtrD->strA);
  445. BS_TEST_ASSERT(orgObj->objPtrC == newObj->objPtrC);
  446. BS_TEST_ASSERT(orgObj->arrStrA.size() == newObj->arrStrA.size());
  447. for (UINT32 i = 0; i < (UINT32)orgObj->arrStrA.size(); i++)
  448. BS_TEST_ASSERT(orgObj->arrStrA[i] == newObj->arrStrA[i]);
  449. BS_TEST_ASSERT(orgObj->arrStrB.size() == newObj->arrStrB.size());
  450. for (UINT32 i = 0; i < (UINT32)orgObj->arrStrB.size(); i++)
  451. BS_TEST_ASSERT(orgObj->arrStrB[i] == newObj->arrStrB[i]);
  452. BS_TEST_ASSERT(orgObj->arrStrC.size() == newObj->arrStrC.size());
  453. for (UINT32 i = 0; i < (UINT32)orgObj->arrStrC.size(); i++)
  454. BS_TEST_ASSERT(orgObj->arrStrC[i] == newObj->arrStrC[i]);
  455. BS_TEST_ASSERT(orgObj->arrObjA.size() == newObj->arrObjA.size());
  456. for (UINT32 i = 0; i < (UINT32)orgObj->arrObjA.size(); i++)
  457. BS_TEST_ASSERT(orgObj->arrObjA[i].strA == newObj->arrObjA[i].strA);
  458. BS_TEST_ASSERT(orgObj->arrObjB.size() == newObj->arrObjB.size());
  459. for (UINT32 i = 0; i < (UINT32)orgObj->arrObjB.size(); i++)
  460. BS_TEST_ASSERT(orgObj->arrObjB[i].strA == newObj->arrObjB[i].strA);
  461. BS_TEST_ASSERT(orgObj->arrObjPtrA.size() == newObj->arrObjPtrA.size());
  462. for (UINT32 i = 0; i < (UINT32)orgObj->arrObjPtrA.size(); i++)
  463. BS_TEST_ASSERT(orgObj->arrObjPtrA[i]->intA == newObj->arrObjPtrA[i]->intA);
  464. BS_TEST_ASSERT(orgObj->arrObjPtrB.size() == newObj->arrObjPtrB.size());
  465. for (UINT32 i = 0; i < (UINT32)orgObj->arrObjPtrB.size(); i++)
  466. BS_TEST_ASSERT(orgObj->arrObjPtrB[i]->intA == newObj->arrObjPtrB[i]->intA);
  467. }
  468. void EditorTestSuite::TestPrefabComplex()
  469. {
  470. HSceneObject aDeleteMe = SceneObject::create("A");
  471. HSceneObject box = SceneObject::create("Box");
  472. box->addComponent<TestComponentA>();
  473. HSceneObject light = SceneObject::create("Directional light");
  474. light->addComponent<TestComponentA>();
  475. HSceneObject sceneRoot = gSceneManager().getRootNode();
  476. HPrefab scenePrefab = Prefab::create(sceneRoot, true);
  477. HSceneObject bDeleteMe = SceneObject::create("B");
  478. HSceneObject _1 = SceneObject::create("1");
  479. scenePrefab->update(sceneRoot);
  480. aDeleteMe->destroy();
  481. bDeleteMe->destroy();
  482. HPrefab targetBoxPrefab = Prefab::create(_1, false);
  483. HSceneObject camera = SceneObject::create("Camera");
  484. camera->addComponent<TestComponentA>();
  485. scenePrefab->update(sceneRoot);
  486. HSceneObject target = SceneObject::create("Target");
  487. _1->setParent(target);
  488. HSceneObject _3 = targetBoxPrefab->instantiate();
  489. _3->setName("3");
  490. _3->setParent(target);
  491. HSceneObject _10 = targetBoxPrefab->instantiate();
  492. _10->setParent(target);
  493. _10->setName("10");
  494. // Ensure multiple instances of the same prefab don't have the same ID
  495. BS_TEST_ASSERT(_1->getLinkId() != _3->getLinkId() && _1->getLinkId() != _10->getLinkId());
  496. // Ensure new instances of a prefab have -1 root link ID
  497. BS_TEST_ASSERT(_3->getLinkId() == (UINT32)-1 && _10->getLinkId() == (UINT32)-1);
  498. scenePrefab->update(sceneRoot);
  499. _1->addComponent<TestComponentA>();
  500. _3->addComponent<TestComponentA>();
  501. _10->addComponent<TestComponentA>();
  502. _1->addComponent<TestComponentB>();
  503. _3->addComponent<TestComponentB>();
  504. _10->addComponent<TestComponentB>();
  505. _1->breakPrefabLink();
  506. _3->breakPrefabLink();
  507. _10->breakPrefabLink();
  508. HPrefab targetPrefab = Prefab::create(target, false);
  509. target->addComponent<TestComponentA>();
  510. scenePrefab->update(sceneRoot);
  511. targetPrefab->update(target);
  512. box->destroy();
  513. light->destroy();
  514. camera->destroy();
  515. target->destroy();
  516. }
  517. void EditorTestSuite::TestPrefabDiff()
  518. {
  519. HSceneObject root = SceneObject::create("root");
  520. HSceneObject so0 = SceneObject::create("so0");
  521. HSceneObject so1 = SceneObject::create("so1");
  522. HSceneObject so2 = SceneObject::create("so2");
  523. HSceneObject so0_0 = SceneObject::create("so0_0");
  524. HSceneObject so0_1 = SceneObject::create("so0_1");
  525. HSceneObject so1_0 = SceneObject::create("so1_0");
  526. HSceneObject so1_1 = SceneObject::create("so1_1");
  527. HSceneObject so1_2 = SceneObject::create("so1_2");
  528. HSceneObject so2_0 = SceneObject::create("so2_0");
  529. so0->setParent(root);
  530. so1->setParent(root);
  531. so2->setParent(root);
  532. so0_0->setParent(so0);
  533. so0_1->setParent(so0);
  534. so1_0->setParent(so1);
  535. so1_1->setParent(so1);
  536. so1_2->setParent(so1);
  537. so2_0->setParent(so2);
  538. GameObjectHandle<TestComponentC> cmp0 = so0->addComponent<TestComponentC>();
  539. GameObjectHandle<TestComponentC> cmp0_1_A = so0_1->addComponent<TestComponentC>();
  540. GameObjectHandle<TestComponentD> cmp0_1_B = so0_1->addComponent<TestComponentD>();
  541. GameObjectHandle<TestComponentD> cmp1 = so1->addComponent<TestComponentD>();
  542. GameObjectHandle<TestComponentD> cmp1_2 = so1_2->addComponent<TestComponentD>();
  543. GameObjectHandle<TestComponentD> cmp2 = so2->addComponent<TestComponentD>();
  544. Path prefabPath = Path::combine(FileSystem::getTempDirectoryPath(), "testprefab.asset");
  545. HPrefab prefab = Prefab::create(root);
  546. gResources().save(prefab, prefabPath, true);
  547. // Perform modifications
  548. GameObjectHandle<TestComponentC> cmp1_3;
  549. GameObjectHandle<TestComponentD> cmp3;
  550. HSceneObject so1_3, so2_1, so3;
  551. {
  552. cmp0->obj.strA = "banana";
  553. so0_0->destroy();
  554. cmp0_1_A->destroy();
  555. so1_3 = SceneObject::create("so1_2");
  556. so1_3->setParent(so1);
  557. cmp1_3 = so1_3->addComponent<TestComponentC>();
  558. cmp1_3->obj.intA = 999;
  559. so1_0->setName("apple");
  560. so1_1->destroy();
  561. cmp1_2->destroy();
  562. cmp1_2 = so1_2->addComponent<TestComponentD>();
  563. cmp1_2->obj.strA = "orange";
  564. so2_1 = SceneObject::create("so2_1");
  565. so2_1->setParent(so2);
  566. so2_0->addComponent<TestComponentD>();
  567. so3 = SceneObject::create("so3");
  568. so3->setParent(root);
  569. cmp3 = so3->addComponent<TestComponentD>();
  570. }
  571. SPtr<PrefabDiff> prefabDiff = PrefabDiff::create(prefab->_getRoot(), root);
  572. prefab = gResources().load<Prefab>(prefabPath);
  573. HSceneObject newRoot = prefab->instantiate();
  574. prefabDiff->apply(newRoot);
  575. // Compare and assert
  576. BS_TEST_ASSERT(root->getNumChildren() == newRoot->getNumChildren());
  577. HSceneObject nso0 = newRoot->getChild(0);
  578. GameObjectHandle<TestComponentC> ncmp0 = nso0->getComponent<TestComponentC>();
  579. BS_TEST_ASSERT(cmp0->obj.strA == ncmp0->obj.strA);
  580. BS_TEST_ASSERT(so0->getNumChildren() == nso0->getNumChildren());
  581. HSceneObject nso0_1 = nso0->getChild(0);
  582. GameObjectHandle<TestComponentC> ncmp0_1 = nso0_1->getComponent<TestComponentD>();
  583. BS_TEST_ASSERT(ncmp0_1 != nullptr);
  584. HSceneObject nso1 = newRoot->getChild(1);
  585. BS_TEST_ASSERT(so1->getNumChildren() == nso1->getNumChildren());
  586. HSceneObject nso1_0 = nso1->getChild(0);
  587. BS_TEST_ASSERT(so1_0->getName() == nso1_0->getName());
  588. HSceneObject nso1_2 = nso1->getChild(1);
  589. GameObjectHandle<TestComponentD> ncmp1_2 = nso1_2->getComponent<TestComponentD>();
  590. BS_TEST_ASSERT(cmp1_2->obj.strA == ncmp1_2->obj.strA);
  591. HSceneObject nso1_3 = nso1->getChild(2);
  592. GameObjectHandle<TestComponentC> ncmp1_3 = nso1_3->getComponent<TestComponentC>();
  593. BS_TEST_ASSERT(cmp1_3->obj.intA == ncmp1_3->obj.intA);
  594. HSceneObject nso2 = newRoot->getChild(2);
  595. BS_TEST_ASSERT(so2->getNumChildren() == nso2->getNumChildren());
  596. HSceneObject nso2_0 = nso2->getChild(0);
  597. GameObjectHandle<TestComponentD> ncmp2_0 = nso2_0->getComponent<TestComponentD>();
  598. BS_TEST_ASSERT(ncmp2_0 != nullptr);
  599. HSceneObject nso3 = newRoot->getChild(3);
  600. GameObjectHandle<TestComponentD> ncmp3 = nso3->getComponent<TestComponentD>();
  601. BS_TEST_ASSERT(ncmp3 != nullptr);
  602. root->destroy();
  603. newRoot->destroy();
  604. }
  605. void EditorTestSuite::TestFrameAlloc()
  606. {
  607. FrameAlloc alloc(128);
  608. alloc.markFrame();
  609. UINT8* a1 = alloc.alloc(5);
  610. UINT8* a2 = alloc.alloc(10);
  611. UINT8* a3 = alloc.alloc(130);
  612. UINT8* a4 = alloc.alloc(5);
  613. alloc.dealloc(a1);
  614. alloc.dealloc(a2);
  615. alloc.dealloc(a3);
  616. alloc.dealloc(a4);
  617. alloc.clear();
  618. alloc.markFrame();
  619. UINT8* a5 = alloc.alloc(5);
  620. UINT8* a6 = alloc.alloc(10);
  621. UINT8* a7 = alloc.alloc(130);
  622. UINT8* a8 = alloc.alloc(5);
  623. alloc.dealloc(a5);
  624. alloc.dealloc(a6);
  625. alloc.dealloc(a7);
  626. alloc.dealloc(a8);
  627. alloc.markFrame();
  628. UINT8* a9 = alloc.alloc(5);
  629. UINT8* a10 = alloc.alloc(10);
  630. UINT8* a11 = alloc.alloc(130);
  631. UINT8* a12 = alloc.alloc(5);
  632. alloc.dealloc(a9);
  633. alloc.dealloc(a10);
  634. alloc.dealloc(a11);
  635. alloc.dealloc(a12);
  636. alloc.clear();
  637. alloc.clear();
  638. UINT8* a13 = alloc.alloc(5);
  639. alloc.dealloc(a13);
  640. alloc.clear();
  641. }
  642. }