creator.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  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. #include "platform/platform.h"
  23. #include "gui/worldEditor/creator.h"
  24. #include "gfx/gfxDrawUtil.h"
  25. IMPLEMENT_CONOBJECT(CreatorTree);
  26. ConsoleDocClass( CreatorTree,
  27. "@brief Creator tree from old editor. Not used in current editor.\n\n"
  28. "@internal"
  29. );
  30. //------------------------------------------------------------------------------
  31. // Class CreatorTree::Node
  32. //------------------------------------------------------------------------------
  33. CreatorTree::Node::Node() :
  34. mFlags(0),
  35. mParent(0),
  36. mName(0),
  37. mValue(0),
  38. mId(0),
  39. mTab(0)
  40. {
  41. VECTOR_SET_ASSOCIATION(mChildren);
  42. }
  43. CreatorTree::Node::~Node()
  44. {
  45. for(U32 i = 0; i < mChildren.size(); i++)
  46. delete mChildren[i];
  47. }
  48. //------------------------------------------------------------------------------
  49. void CreatorTree::Node::expand(bool exp)
  50. {
  51. if(exp)
  52. {
  53. if(mParent)
  54. mParent->expand(exp);
  55. mFlags.set(Node::Expanded);
  56. }
  57. else if(!isRoot())
  58. {
  59. if(isGroup())
  60. for(U32 i = 0; i < mChildren.size(); i++)
  61. mChildren[i]->expand(exp);
  62. mFlags.clear(Selected);
  63. mFlags.clear(Expanded);
  64. }
  65. }
  66. //------------------------------------------------------------------------------
  67. CreatorTree::Node * CreatorTree::Node::find(S32 id)
  68. {
  69. if(mId == id)
  70. return(this);
  71. if(!isGroup())
  72. return(0);
  73. for(U32 i = 0; i < mChildren.size(); i++)
  74. {
  75. Node * node = mChildren[i]->find(id);
  76. if(node)
  77. return(node);
  78. }
  79. return(0);
  80. }
  81. //------------------------------------------------------------------------------
  82. bool CreatorTree::Node::isFirst()
  83. {
  84. AssertFatal(!isRoot(), "CreatorTree::Node::isFirst - cannot call on root node");
  85. return(this == mParent->mChildren[0]);
  86. }
  87. bool CreatorTree::Node::isLast()
  88. {
  89. AssertFatal(!isRoot(), "CreatorTree::Node::isLast - cannot call on root node");
  90. return(this == mParent->mChildren[mParent->mChildren.size()-1]);
  91. }
  92. bool CreatorTree::Node::hasChildItem()
  93. {
  94. for(U32 i = 0; i < mChildren.size(); i++)
  95. {
  96. if(mChildren[i]->isGroup() && mChildren[i]->hasChildItem())
  97. return(true);
  98. if(!mChildren[i]->isGroup())
  99. return(true);
  100. }
  101. return(false);
  102. }
  103. S32 CreatorTree::Node::getSelected()
  104. {
  105. for(U32 i = 0; i < mChildren.size(); i++)
  106. {
  107. if(mChildren[i]->isSelected())
  108. return(mChildren[i]->mId);
  109. else if(mChildren[i]->isGroup())
  110. {
  111. S32 ret = mChildren[i]->getSelected();
  112. if(ret != -1)
  113. return(ret);
  114. }
  115. }
  116. return(-1);
  117. }
  118. //------------------------------------------------------------------------------
  119. // Class CreatorTree
  120. //------------------------------------------------------------------------------
  121. CreatorTree::CreatorTree() :
  122. mCurId(0),
  123. mTxtOffset(5),
  124. mRoot(0)
  125. {
  126. VECTOR_SET_ASSOCIATION(mNodeList);
  127. clear();
  128. }
  129. CreatorTree::~CreatorTree()
  130. {
  131. delete mRoot;
  132. }
  133. //------------------------------------------------------------------------------
  134. CreatorTree::Node * CreatorTree::createNode(const char * name, const char * value, bool group, Node * parent)
  135. {
  136. Node * node = new Node();
  137. node->mId = mCurId++;
  138. node->mName = name ? StringTable->insert(name) : 0;
  139. node->mValue = value ? StringTable->insert(value) : 0;
  140. node->mFlags.set(Node::Group, group);
  141. // add to the parent group
  142. if(parent)
  143. {
  144. node->mParent = parent;
  145. if(!addNode(parent, node))
  146. {
  147. delete node;
  148. return(0);
  149. }
  150. }
  151. return(node);
  152. }
  153. //------------------------------------------------------------------------------
  154. void CreatorTree::clear()
  155. {
  156. delete mRoot;
  157. mCurId = 0;
  158. mRoot = createNode(0, 0, true);
  159. mRoot->mFlags.set(Node::Root | Node::Expanded);
  160. mSize = Point2I(1,0);
  161. }
  162. //------------------------------------------------------------------------------
  163. bool CreatorTree::addNode(Node * parent, Node * node)
  164. {
  165. if(!parent->isGroup())
  166. return(false);
  167. //
  168. parent->mChildren.push_back(node);
  169. return(true);
  170. }
  171. //------------------------------------------------------------------------------
  172. CreatorTree::Node * CreatorTree::findNode(S32 id)
  173. {
  174. return(mRoot->find(id));
  175. }
  176. //------------------------------------------------------------------------------
  177. void CreatorTree::sort()
  178. {
  179. // groups then items by alpha
  180. }
  181. //------------------------------------------------------------------------------
  182. ConsoleMethod( CreatorTree, addGroup, S32, 4, 4, "(string group, string name, string value)")
  183. {
  184. CreatorTree::Node * grp = object->findNode(dAtoi(argv[2]));
  185. if(!grp || !grp->isGroup())
  186. return(-1);
  187. // return same named group if found...
  188. for(U32 i = 0; i < grp->mChildren.size(); i++)
  189. if(!dStricmp(argv[3], grp->mChildren[i]->mName))
  190. return(grp->mChildren[i]->mId);
  191. CreatorTree::Node * node = object->createNode(argv[3], 0, true, grp);
  192. object->build();
  193. return(node ? node->getId() : -1);
  194. }
  195. ConsoleMethod( CreatorTree, addItem, S32, 5, 5, "(Node group, string name, string value)")
  196. {
  197. CreatorTree::Node * grp = object->findNode(dAtoi(argv[2]));
  198. if(!grp || !grp->isGroup())
  199. return -1;
  200. CreatorTree::Node * node = object->createNode(argv[3], argv[4], false, grp);
  201. object->build();
  202. return(node ? node->getId() : -1);
  203. }
  204. //------------------------------------------------------------------------------
  205. ConsoleMethod( CreatorTree, fileNameMatch, bool, 5, 5, "(string world, string type, string filename)"){
  206. // argv[2] - world short
  207. // argv[3] - type short
  208. // argv[4] - filename
  209. // interior filenames
  210. // 0 - world short ('b', 'x', ...)
  211. // 1-> - type short ('towr', 'bunk', ...)
  212. U32 typeLen = dStrlen(argv[3]);
  213. if(dStrlen(argv[4]) < (typeLen + 1))
  214. return(false);
  215. // world
  216. if(dToupper(argv[4][0]) != dToupper(argv[2][0]))
  217. return(false);
  218. return(!dStrnicmp(((const char*)argv[4])+1, argv[3], typeLen));
  219. }
  220. ConsoleMethod( CreatorTree, getSelected, S32, 2, 2, "Return a handle to the currently selected item.")
  221. {
  222. return(object->getSelected());
  223. }
  224. ConsoleMethod( CreatorTree, isGroup, bool, 3, 3, "(Group g)")
  225. {
  226. CreatorTree::Node * node = object->findNode(dAtoi(argv[2]));
  227. if(node && node->isGroup())
  228. return(true);
  229. return(false);
  230. }
  231. ConsoleMethod( CreatorTree, getName, const char*, 3, 3, "(Node item)")
  232. {
  233. CreatorTree::Node * node = object->findNode(dAtoi(argv[2]));
  234. return(node ? node->mName : 0);
  235. }
  236. ConsoleMethod( CreatorTree, getValue, const char*, 3, 3, "(Node n)")
  237. {
  238. CreatorTree::Node * node = object->findNode(dAtoi(argv[2]));
  239. return(node ? node->mValue : 0);
  240. }
  241. ConsoleMethod( CreatorTree, clear, void, 2, 2, "Clear the tree.")
  242. {
  243. object->clear();
  244. }
  245. ConsoleMethod( CreatorTree, getParent, S32, 3, 3, "(Node n)")
  246. {
  247. CreatorTree::Node * node = object->findNode(dAtoi(argv[2]));
  248. if(node && node->mParent)
  249. return(node->mParent->getId());
  250. return(-1);
  251. }
  252. //------------------------------------------------------------------------------
  253. void CreatorTree::buildNode(Node * node, U32 tab)
  254. {
  255. if(node->isExpanded())
  256. for(U32 i = 0; i < node->mChildren.size(); i++)
  257. {
  258. Node * child = node->mChildren[i];
  259. child->mTab = tab;
  260. child->select(false);
  261. mNodeList.push_back(child);
  262. // grab width
  263. if(bool(mProfile->mFont) && child->mName)
  264. {
  265. S32 width = (tab + 1) * mTabSize + mProfile->mFont->getStrWidth(child->mName) + mTxtOffset;
  266. if(width > mMaxWidth)
  267. mMaxWidth = width;
  268. }
  269. if(node->mChildren[i]->isGroup())
  270. buildNode(node->mChildren[i], tab+1);
  271. }
  272. }
  273. //------------------------------------------------------------------------------
  274. void CreatorTree::build()
  275. {
  276. mMaxWidth = 0;
  277. mNodeList.clear();
  278. buildNode(mRoot, 0);
  279. mCellSize.set( mMaxWidth + 1, 11 );
  280. setSize(Point2I(1, mNodeList.size()));
  281. }
  282. //------------------------------------------------------------------------------
  283. bool CreatorTree::onWake()
  284. {
  285. if(!Parent::onWake())
  286. return(false);
  287. mTabSize = 11;
  288. //
  289. build();
  290. mCellSize.set( mMaxWidth + 1, 11 );
  291. setSize(Point2I(1, mNodeList.size()));
  292. return true;
  293. }
  294. //------------------------------------------------------------------------------
  295. void CreatorTree::onMouseUp(const GuiEvent & event)
  296. {
  297. onAction();
  298. }
  299. void CreatorTree::onMouseDown(const GuiEvent & event)
  300. {
  301. Point2I pos = globalToLocalCoord(event.mousePoint);
  302. bool dblClick = event.mouseClickCount > 1;
  303. // determine cell
  304. Point2I cell(pos.x < 0 ? -1 : pos.x / mCellSize.x, pos.y < 0 ? -1 : pos.y / mCellSize.y);
  305. if(cell.x >= 0 && cell.x < mSize.x && cell.y >= 0 && cell.y < mSize.y)
  306. {
  307. Node * node = mNodeList[cell.y];
  308. S32 offset = mTabSize * node->mTab;
  309. if(node->isGroup() && node->mChildren.size() && pos.x >= offset && pos.x <= (offset + mTabSize))
  310. {
  311. node->expand(!node->isExpanded());
  312. build();
  313. dblClick = false;
  314. }
  315. if(pos.x >= offset)
  316. {
  317. if(dblClick)
  318. node->expand(!node->isExpanded());
  319. build();
  320. node->select(true);
  321. }
  322. }
  323. }
  324. //------------------------------------------------------------------------------
  325. void CreatorTree::onMouseDragged(const GuiEvent & event)
  326. {
  327. TORQUE_UNUSED(event);
  328. }
  329. //------------------------------------------------------------------------------
  330. void CreatorTree::onRenderCell(Point2I offset, Point2I cell, bool, bool)
  331. {
  332. Point2I cellOffset = offset;
  333. Node *node = mNodeList[cell.y];
  334. // Get our points
  335. Point2I boxStart( cellOffset.x + mTabSize * node->mTab, cellOffset.y );
  336. boxStart.x += 2;
  337. boxStart.y += 1;
  338. Point2I boxEnd = Point2I( boxStart );
  339. boxEnd.x += 8;
  340. boxEnd.y += 8;
  341. GFXDrawUtil *drawer = GFX->getDrawUtil();
  342. // Start drawing stuff
  343. if( node->isGroup() )
  344. {
  345. // If we need a box...
  346. drawer->drawRectFill( boxStart, boxEnd, mProfile->mFillColor ); // Box background
  347. drawer->drawRect( boxStart, boxEnd, mProfile->mFontColor ); // Border
  348. // Cross line
  349. drawer->drawLine( boxStart.x + 2, boxStart.y + 4, boxStart.x + 7, boxStart.y + 4, mProfile->mFontColor );
  350. if( !node->isExpanded() ) // If it's a [+] draw down line
  351. drawer->drawLine( boxStart.x + 4, boxStart.y + 2, boxStart.x + 4, boxStart.y + 7, mProfile->mFontColor );
  352. }
  353. else
  354. {
  355. // Draw horizontal line
  356. drawer->drawLine( boxStart.x + 4, boxStart.y + 4, boxStart.x + 9, boxStart.y + 4, mProfile->mFontColor );
  357. if( !node->isLast() ) // If it's a continuing one, draw a long down line
  358. drawer->drawLine( boxStart.x + 4, boxStart.y - 6, boxStart.x + 4, boxStart.y + 10, mProfile->mFontColor );
  359. else // Otherwise, just a small one
  360. drawer->drawLine( boxStart.x + 4, boxStart.y - 2, boxStart.x + 4, boxStart.y + 4, mProfile->mFontColor );
  361. }
  362. //draw in all the required continuation lines
  363. Node *parent = node->mParent;
  364. while( !parent->isRoot() )
  365. {
  366. if( !parent->isLast() )
  367. {
  368. drawer->drawLine( cellOffset.x + ( parent->mTab * mTabSize ) + 6,
  369. cellOffset.y - 2,
  370. cellOffset.x + ( parent->mTab * mTabSize ) + 6,
  371. cellOffset.y + 11,
  372. mProfile->mFontColor );
  373. }
  374. parent = parent->mParent;
  375. }
  376. ColorI fontColor = mProfile->mFontColor;
  377. if( node->isSelected() )
  378. fontColor = mProfile->mFontColorHL;
  379. else if( node->isGroup() && node->hasChildItem() )
  380. fontColor.set( 128, 0, 0 );
  381. else if( !node->isGroup() )
  382. fontColor.set( 0, 0, 128 );
  383. drawer->setBitmapModulation(fontColor); //node->isSelected() ? mProfile->mFontColorHL : mProfile->mFontColor);
  384. drawer->drawText( mProfile->mFont,
  385. Point2I( offset.x + mTxtOffset + mTabSize * ( node->mTab + 1 ), offset.y ),
  386. node->mName);
  387. }