creator.cpp

Engine/source/gui/worldEditor/creator.cpp

More...

Public Functions

ConsoleDocClass(CreatorTree , "@brief Creator tree from old editor. Not used in current <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">editor.\n\n</a>" "@internal" )
DefineEngineMethod(CreatorTree , addGroup , S32 , (S32 group, const char *name, const char *value) , "(string group, string name, string <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a>)" )
DefineEngineMethod(CreatorTree , addItem , S32 , (S32 group, const char *name, const char *value) , "(Node group, string name, string <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a>)" )
DefineEngineMethod(CreatorTree , clear , void , () , "Clear the tree." )
DefineEngineMethod(CreatorTree , fileNameMatch , bool , (const char *world, const char *type, const char *filename) , "(string world, string type, string filename)" )
DefineEngineMethod(CreatorTree , getName , const char * , (const char *item) , "(Node item)" )
DefineEngineMethod(CreatorTree , getParent , S32 , (S32 nodeValue) , "(Node <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>)" )
DefineEngineMethod(CreatorTree , getSelected , S32 , () , "Return <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> handle <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the currently selected item." )
DefineEngineMethod(CreatorTree , getValue , const char * , (S32 nodeValue) , "(Node <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>)" )
DefineEngineMethod(CreatorTree , isGroup , bool , (const char *group) , "(Group g)" )

Detailed Description

Public Functions

ConsoleDocClass(CreatorTree , "@brief Creator tree from old editor. Not used in current <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">editor.\n\n</a>" "@internal" )

DefineEngineMethod(CreatorTree , addGroup , S32 , (S32 group, const char *name, const char *value) , "(string group, string name, string <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a>)" )

DefineEngineMethod(CreatorTree , addItem , S32 , (S32 group, const char *name, const char *value) , "(Node group, string name, string <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a>)" )

DefineEngineMethod(CreatorTree , clear , void , () , "Clear the tree." )

DefineEngineMethod(CreatorTree , fileNameMatch , bool , (const char *world, const char *type, const char *filename) , "(string world, string type, string filename)" )

DefineEngineMethod(CreatorTree , getName , const char * , (const char *item) , "(Node item)" )

DefineEngineMethod(CreatorTree , getParent , S32 , (S32 nodeValue) , "(Node <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>)" )

DefineEngineMethod(CreatorTree , getSelected , S32 , () , "Return <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> handle <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the currently selected item." )

DefineEngineMethod(CreatorTree , getValue , const char * , (S32 nodeValue) , "(Node <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>)" )

DefineEngineMethod(CreatorTree , isGroup , bool , (const char *group) , "(Group g)" )

IMPLEMENT_CONOBJECT(CreatorTree )

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25#include "console/engineAPI.h"
 26#include "gui/worldEditor/creator.h"
 27
 28#include "gfx/gfxDrawUtil.h"
 29
 30
 31IMPLEMENT_CONOBJECT(CreatorTree);
 32
 33ConsoleDocClass( CreatorTree,
 34   "@brief Creator tree from old editor.  Not used in current editor.\n\n"
 35   "@internal"
 36);
 37
 38//------------------------------------------------------------------------------
 39// Class CreatorTree::Node
 40//------------------------------------------------------------------------------
 41
 42CreatorTree::Node::Node() :
 43   mFlags(0),
 44   mParent(0),
 45   mName(0),
 46   mId(0),
 47   mValue(0),
 48   mTab(0)
 49{
 50   VECTOR_SET_ASSOCIATION(mChildren);
 51}
 52
 53CreatorTree::Node::~Node()
 54{
 55   for(U32 i = 0; i < mChildren.size(); i++)
 56      delete mChildren[i];
 57}
 58
 59//------------------------------------------------------------------------------
 60
 61void CreatorTree::Node::expand(bool exp)
 62{
 63   if(exp)
 64   {
 65      if(mParent)
 66         mParent->expand(exp);
 67      mFlags.set(Node::Expanded);
 68   }
 69   else if(!isRoot())
 70   {
 71      if(isGroup())
 72         for(U32 i = 0; i < mChildren.size(); i++)
 73            mChildren[i]->expand(exp);
 74
 75      mFlags.clear(Selected);
 76      mFlags.clear(Expanded);
 77   }
 78}
 79
 80//------------------------------------------------------------------------------
 81
 82CreatorTree::Node * CreatorTree::Node::find(S32 id)
 83{
 84   if(mId == id)
 85      return(this);
 86
 87   if(!isGroup())
 88      return(0);
 89
 90   for(U32 i = 0; i < mChildren.size(); i++)
 91   {
 92      Node * node = mChildren[i]->find(id);
 93      if(node)
 94         return(node);
 95   }
 96
 97   return(0);
 98}
 99
100//------------------------------------------------------------------------------
101
102bool CreatorTree::Node::isFirst()
103{
104   AssertFatal(!isRoot(), "CreatorTree::Node::isFirst - cannot call on root node");
105   return(this == mParent->mChildren[0]);
106}
107
108bool CreatorTree::Node::isLast()
109{
110   AssertFatal(!isRoot(), "CreatorTree::Node::isLast - cannot call on root node");
111   return(this == mParent->mChildren[mParent->mChildren.size()-1]);
112}
113
114bool CreatorTree::Node::hasChildItem()
115{
116   for(U32 i = 0; i < mChildren.size(); i++)
117   {
118      if(mChildren[i]->isGroup() && mChildren[i]->hasChildItem())
119         return(true);
120
121      if(!mChildren[i]->isGroup())
122         return(true);
123   }
124
125   return(false);
126}
127
128S32 CreatorTree::Node::getSelected()
129{
130   for(U32 i = 0; i < mChildren.size(); i++)
131   {
132      if(mChildren[i]->isSelected())
133         return(mChildren[i]->mId);
134      else if(mChildren[i]->isGroup())
135      {
136         S32 ret = mChildren[i]->getSelected();
137         if(ret != -1)
138            return(ret);
139      }
140   }
141   return(-1);
142}
143
144//------------------------------------------------------------------------------
145// Class CreatorTree
146//------------------------------------------------------------------------------
147CreatorTree::CreatorTree() :
148   mCurId(0),
149   mRoot(0),
150   mTxtOffset(5),
151   mTabSize(11),
152   mMaxWidth(0)
153{
154   VECTOR_SET_ASSOCIATION(mNodeList);
155   clear();
156}
157
158CreatorTree::~CreatorTree()
159{
160   delete mRoot;
161}
162
163//------------------------------------------------------------------------------
164
165CreatorTree::Node * CreatorTree::createNode(const char * name, const char * value, bool group, Node * parent)
166{
167   Node * node = new Node();
168   node->mId = mCurId++;
169   node->mName = name ? StringTable->insert(name) : 0;
170   node->mValue = value ? StringTable->insert(value) : 0;
171   node->mFlags.set(Node::Group, group);
172
173   // add to the parent group
174   if(parent)
175   {
176      node->mParent = parent;
177      if(!addNode(parent, node))
178      {
179         delete node;
180         return(0);
181      }
182   }
183
184   return(node);
185}
186
187//------------------------------------------------------------------------------
188
189void CreatorTree::clear()
190{
191   delete mRoot;
192   mCurId = 0;
193   mRoot = createNode(0, 0, true);
194   mRoot->mFlags.set(Node::Root | Node::Expanded);
195   mSize = Point2I(1,0);
196}
197
198//------------------------------------------------------------------------------
199
200bool CreatorTree::addNode(Node * parent, Node * node)
201{
202   if(!parent->isGroup())
203      return(false);
204
205   //
206   parent->mChildren.push_back(node);
207   return(true);
208}
209
210//------------------------------------------------------------------------------
211
212CreatorTree::Node * CreatorTree::findNode(S32 id)
213{
214   return(mRoot->find(id));
215}
216
217//------------------------------------------------------------------------------
218
219void CreatorTree::sort()
220{
221   // groups then items by alpha
222}
223
224//------------------------------------------------------------------------------
225DefineEngineMethod( CreatorTree, addGroup, S32, (S32 group, const char * name, const char * value), , "(string group, string name, string value)")
226{
227   CreatorTree::Node * grp = object->findNode(group);
228
229   if(!grp || !grp->isGroup())
230      return(-1);
231
232   // return same named group if found...
233   for(U32 i = 0; i < grp->mChildren.size(); i++)
234      if(!dStricmp(name, grp->mChildren[i]->mName))
235         return(grp->mChildren[i]->mId);
236
237   CreatorTree::Node * node = object->createNode(name, 0, true, grp);
238   object->build();
239   return(node ? node->getId() : -1);
240}
241
242DefineEngineMethod( CreatorTree, addItem, S32, (S32 group, const char * name, const char * value), , "(Node group, string name, string value)")
243{
244   CreatorTree::Node * grp = object->findNode(group);
245
246   if(!grp || !grp->isGroup())
247      return -1;
248
249   CreatorTree::Node * node = object->createNode(name, value, false, grp);
250   object->build();
251   return(node ? node->getId() : -1);
252}
253
254//------------------------------------------------------------------------------
255DefineEngineMethod( CreatorTree, fileNameMatch, bool, (const char * world, const char * type, const char * filename), , "(string world, string type, string filename)")
256{
257   // argv[2] - world short
258   // argv[3] - type short
259   // argv[4] - filename
260
261   // interior filenames
262   // 0     - world short ('b', 'x', ...)
263   // 1->   - type short ('towr', 'bunk', ...)
264   U32 typeLen = dStrlen(type);
265   if(dStrlen(filename) < (typeLen + 1))
266      return(false);
267
268   // world
269   if(dToupper(filename[0]) != dToupper(world[0]))
270      return(false);
271
272   return(!dStrnicmp(filename+1, type, typeLen));
273}
274
275DefineEngineMethod( CreatorTree, getSelected, S32, (), , "Return a handle to the currently selected item.")
276{
277   return(object->getSelected());
278}
279
280DefineEngineMethod( CreatorTree, isGroup, bool, (const char * group), , "(Group g)")
281{
282   CreatorTree::Node * node = object->findNode(dAtoi(group));
283   if(node && node->isGroup())
284      return(true);
285   return(false);
286}
287
288DefineEngineMethod( CreatorTree, getName, const char*, (const char * item), , "(Node item)")
289{
290   CreatorTree::Node * node = object->findNode(dAtoi(item));
291   return(node ? node->mName : 0);
292}
293
294DefineEngineMethod( CreatorTree, getValue, const char*, (S32 nodeValue), , "(Node n)")
295{
296   CreatorTree::Node * node = object->findNode(nodeValue);
297   return(node ? node->mValue : 0);
298}
299
300DefineEngineMethod( CreatorTree, clear, void, (), , "Clear the tree.")
301{
302   object->clear();
303}
304
305DefineEngineMethod( CreatorTree, getParent, S32, (S32 nodeValue), , "(Node n)")
306{
307   CreatorTree::Node * node = object->findNode(nodeValue);
308   if(node && node->mParent)
309      return(node->mParent->getId());
310
311   return(-1);
312}
313//------------------------------------------------------------------------------
314
315void CreatorTree::buildNode(Node * node, U32 tab)
316{
317   if(node->isExpanded())
318      for(U32 i = 0; i < node->mChildren.size(); i++)
319      {
320         Node * child = node->mChildren[i];
321         child->mTab = tab;
322         child->select(false);
323         mNodeList.push_back(child);
324
325         // grab width
326         if(bool(mProfile->mFont) && child->mName)
327         {
328            S32 width = (tab + 1) * mTabSize + mProfile->mFont->getStrWidth(child->mName) + mTxtOffset;
329            if(width > mMaxWidth)
330               mMaxWidth = width;
331         }
332
333         if(node->mChildren[i]->isGroup())
334            buildNode(node->mChildren[i], tab+1);
335      }
336}
337
338//------------------------------------------------------------------------------
339
340void CreatorTree::build()
341{
342   mMaxWidth = 0;
343   mNodeList.clear();
344   buildNode(mRoot, 0);
345   mCellSize.set( mMaxWidth + 1, 11 );
346   setSize(Point2I(1, mNodeList.size()));
347}
348
349//------------------------------------------------------------------------------
350bool CreatorTree::onWake()
351{
352   if(!Parent::onWake())
353      return(false);
354
355   mTabSize = 11;
356
357
358   //
359   build();
360   mCellSize.set( mMaxWidth + 1, 11 );
361   setSize(Point2I(1, mNodeList.size()));
362   return true;
363}
364
365//------------------------------------------------------------------------------
366
367void CreatorTree::onMouseUp(const GuiEvent & event)
368{
369   onAction();
370}
371
372void CreatorTree::onMouseDown(const GuiEvent & event)
373{
374   Point2I pos = globalToLocalCoord(event.mousePoint);
375
376   bool dblClick = event.mouseClickCount > 1;
377
378   // determine cell
379   Point2I cell(pos.x < 0 ? -1 : pos.x / mCellSize.x, pos.y < 0 ? -1 : pos.y / mCellSize.y);
380   if(cell.x >= 0 && cell.x < mSize.x && cell.y >= 0 && cell.y < mSize.y)
381   {
382      Node * node = mNodeList[cell.y];
383      S32 offset = mTabSize * node->mTab;
384      if(node->isGroup() && node->mChildren.size() && pos.x >= offset && pos.x <= (offset + mTabSize))
385      {
386         node->expand(!node->isExpanded());
387         build();
388         dblClick = false;
389      }
390
391      if(pos.x >= offset)
392      {
393         if(dblClick)
394            node->expand(!node->isExpanded());
395         build();
396         node->select(true);
397      }
398   }
399}
400
401//------------------------------------------------------------------------------
402
403void CreatorTree::onMouseDragged(const GuiEvent & event)
404{
405   TORQUE_UNUSED(event);
406}
407
408//------------------------------------------------------------------------------
409void CreatorTree::onRenderCell(Point2I offset, Point2I cell, bool, bool) 
410{
411   Point2I cellOffset = offset;
412
413   Node *node =  mNodeList[cell.y];
414
415   // Get our points
416   Point2I boxStart( cellOffset.x + mTabSize * node->mTab, cellOffset.y );
417
418   boxStart.x += 2;
419   boxStart.y += 1;
420
421   Point2I boxEnd = Point2I( boxStart );
422
423   boxEnd.x += 8;
424   boxEnd.y += 8;
425
426   GFXDrawUtil *drawer = GFX->getDrawUtil();
427
428   // Start drawing stuff
429   if( node->isGroup() ) 
430   { 
431      // If we need a box...
432      drawer->drawRectFill( boxStart, boxEnd, mProfile->mFillColor ); // Box background
433      drawer->drawRect( boxStart, boxEnd, mProfile->mFontColor );     // Border
434
435      // Cross line
436      drawer->drawLine( boxStart.x + 2, boxStart.y + 4, boxStart.x + 7, boxStart.y + 4, mProfile->mFontColor );
437
438      if( !node->isExpanded() ) // If it's a [+] draw down line
439         drawer->drawLine( boxStart.x + 4, boxStart.y + 2, boxStart.x + 4, boxStart.y + 7, mProfile->mFontColor );
440   }
441   else 
442   {
443      // Draw horizontal line
444      drawer->drawLine( boxStart.x + 4, boxStart.y + 4, boxStart.x + 9, boxStart.y + 4, mProfile->mFontColor );
445
446      if( !node->isLast() ) // If it's a continuing one, draw a long down line
447         drawer->drawLine( boxStart.x + 4, boxStart.y - 6, boxStart.x + 4, boxStart.y + 10, mProfile->mFontColor );
448      else  // Otherwise, just a small one
449         drawer->drawLine( boxStart.x + 4, boxStart.y - 2, boxStart.x + 4, boxStart.y + 4, mProfile->mFontColor );
450   }
451
452   //draw in all the required continuation lines
453   Node *parent = node->mParent;
454
455   while( !parent->isRoot() ) 
456   {
457      if( !parent->isLast() ) 
458      {
459         drawer->drawLine( cellOffset.x + ( parent->mTab * mTabSize ) + 6,
460                      cellOffset.y - 2,
461                      cellOffset.x + ( parent->mTab * mTabSize ) + 6,
462                      cellOffset.y + 11,
463                      mProfile->mFontColor );
464      }
465      parent = parent->mParent;
466   }
467
468   ColorI fontColor = mProfile->mFontColor;
469   if( node->isSelected() )
470      fontColor = mProfile->mFontColorHL;
471   else if( node->isGroup() && node->hasChildItem() )
472      fontColor.set( 128, 0, 0 );
473   else if( !node->isGroup() )
474      fontColor.set( 0, 0, 128 );
475
476   drawer->setBitmapModulation(fontColor); //node->isSelected() ? mProfile->mFontColorHL : mProfile->mFontColor);
477   drawer->drawText( mProfile->mFont,
478                Point2I( offset.x + mTxtOffset + mTabSize * ( node->mTab + 1 ), offset.y ),
479                node->mName);
480}
481