guiTypes.cpp

Engine/source/gui/core/guiTypes.cpp

More...

Public Variables

Public Functions

ConsoleDocClass(GuiControlProfile , "@brief A collection of properties that determine <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> behavior and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rendering.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiCore\n</a>" "" )
ConsoleDocClass(GuiCursor , "@brief Acts as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> skin <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the cursor, where each <a href="/coding/class/classguicursor/">GuiCursor</a> object can have its own look and click-<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">zone.\n\n</a>" "GuiCursors act as skins <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/sdlcursorcontroller_8cpp/#sdlcursorcontroller_8cpp_1a06e8dd1f849973ccc456f8553601e8b9">cursor</a> in the game, where each individual <a href="/coding/class/classguicursor/">GuiCursor</a> can have its own defined imagemap, \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "click zone and <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> offset. This allows <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> game <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> easily support <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> wide range of cursors. The active <a href="/coding/file/sdlcursorcontroller_8cpp/#sdlcursorcontroller_8cpp_1a06e8dd1f849973ccc456f8553601e8b9">cursor</a> can de <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">changed\n</a>" "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> each Canvas using %canvasObj.setCursor(<a href="/coding/class/classguicursor/">GuiCursor</a>);." " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classguicursor/">GuiCursor</a>(DefaultCursor)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " hotSpot=\"1 1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	renderOffset = \"0 0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	bitmapName = \"~/art/gui/images/defaultCursor\";\n" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiCanvas\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiCore\n</a>" )
ConsoleSetType(TypeRectSpacingI )
ConsoleType(RectSpacingI , TypeRectSpacingI , RectSpacingI , "" )
DefineEngineMethod(GuiControlProfile , getStringWidth , S32 , (const char *string) , "Get the width of the string in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">pixels.\n</a>" "@param string <a href="/coding/class/classstring/">String</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get the width of." "@return width of the string in pixels." )
ImplementEnumType(GuiAlignmentType , "\n\n" "@ingroup GuiCore" )
ImplementEnumType(GuiFontCharset , "\n\n" "@ingroup GuiCore" )

Detailed Description

Public Variables

RectSpacingI ConsoleGetType (TypeRectSpacingI)
 EndImplementEnumType 

Public Functions

ConsoleDocClass(GuiControlProfile , "@brief A collection of properties that determine <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> behavior and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rendering.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiCore\n</a>" "" )

ConsoleDocClass(GuiCursor , "@brief Acts as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> skin <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the cursor, where each <a href="/coding/class/classguicursor/">GuiCursor</a> object can have its own look and click-<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">zone.\n\n</a>" "GuiCursors act as skins <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/sdlcursorcontroller_8cpp/#sdlcursorcontroller_8cpp_1a06e8dd1f849973ccc456f8553601e8b9">cursor</a> in the game, where each individual <a href="/coding/class/classguicursor/">GuiCursor</a> can have its own defined imagemap, \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "click zone and <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> offset. This allows <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> game <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> easily support <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> wide range of cursors. The active <a href="/coding/file/sdlcursorcontroller_8cpp/#sdlcursorcontroller_8cpp_1a06e8dd1f849973ccc456f8553601e8b9">cursor</a> can de <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">changed\n</a>" "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> each Canvas using %canvasObj.setCursor(<a href="/coding/class/classguicursor/">GuiCursor</a>);." " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classguicursor/">GuiCursor</a>(DefaultCursor)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " hotSpot=\"1 1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	renderOffset = \"0 0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	bitmapName = \"~/art/gui/images/defaultCursor\";\n" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiCanvas\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiCore\n</a>" )

ConsoleSetType(TypeRectSpacingI )

ConsoleType(RectSpacingI , TypeRectSpacingI , RectSpacingI , "" )

DefineEngineMethod(GuiControlProfile , getStringWidth , S32 , (const char *string) , "Get the width of the string in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">pixels.\n</a>" "@param string <a href="/coding/class/classstring/">String</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get the width of." "@return width of the string in pixels." )

GFX_ImplementTextureProfile(GFXDefaultGUIProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82da23d780ef2bcc57521a4945415ce5207f">GFXTextureProfile::Static</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daf6773a6da8ddf28520016603401b8f23">GFXTextureProfile::SRGB</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82dad441bdb77a6cc976d9927679237fa96e">GFXTextureProfile::NoPadding , GFXTextureProfile::NONE )

GFX_ImplementTextureProfile(GFXGuiCursorProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82da23d780ef2bcc57521a4945415ce5207f">GFXTextureProfile::Static</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daf6773a6da8ddf28520016603401b8f23">GFXTextureProfile::SRGB , GFXTextureProfile::NONE )

IMPLEMENT_CONOBJECT(GuiControlProfile )

IMPLEMENT_CONOBJECT(GuiCursor )

IMPLEMENT_STRUCT(RectSpacingI , RectSpacingI , GuiAPI , "" )

ImplementEnumType(GuiAlignmentType , "\n\n" "@ingroup GuiCore" )

ImplementEnumType(GuiFontCharset , "\n\n" "@ingroup GuiCore" )

  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 "platform/types.h"
 26#include "console/consoleTypes.h"
 27#include "console/console.h"
 28#include "console/engineAPI.h"
 29#include "gui/core/guiTypes.h"
 30#include "gui/core/guiControl.h"
 31#include "gfx/gFont.h"
 32#include "gfx/bitmap/gBitmap.h"
 33#include "gfx/gfxDevice.h"
 34#include "gfx/gfxDrawUtil.h"
 35#include "sfx/sfxTrack.h"
 36#include "sfx/sfxTypes.h"
 37#include "console/engineAPI.h"
 38
 39//#define DEBUG_SPEW
 40
 41
 42// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
 43IMPLEMENT_CONOBJECT(GuiCursor);
 44
 45ConsoleDocClass( GuiCursor,
 46   "@brief Acts as a skin for the cursor, where each GuiCursor object can have its own look and click-zone.\n\n"
 47
 48   "GuiCursors act as skins for the cursor in the game, where each individual GuiCursor can have its own defined imagemap,\n"
 49   "click zone and render offset. This allows a game to easily support a wide range of cursors. The active cursor can de changed\n"
 50   "for each Canvas using %canvasObj.setCursor(GuiCursor);."
 51
 52   "@tsexample\n"
 53   "new GuiCursor(DefaultCursor)\n"
 54   "{\n"
 55    " hotSpot = \"1 1\";\n"
 56    " renderOffset = \"0 0\";\n"
 57    " bitmapName = \"~/art/gui/images/defaultCursor\";\n"
 58   "};\n"
 59   "@endtsexample\n\n"
 60   "@see GuiCanvas\n\n"
 61   "@ingroup GuiCore\n"
 62);
 63
 64GFX_ImplementTextureProfile(GFXGuiCursorProfile,
 65                            GFXTextureProfile::DiffuseMap, 
 66                            GFXTextureProfile::PreserveSize |
 67                            GFXTextureProfile::Static | GFXTextureProfile::SRGB,
 68                            GFXTextureProfile::NONE);
 69GFX_ImplementTextureProfile(GFXDefaultGUIProfile,
 70                            GFXTextureProfile::DiffuseMap, 
 71                            GFXTextureProfile::PreserveSize |
 72                            GFXTextureProfile::Static | GFXTextureProfile::SRGB |
 73                            GFXTextureProfile::NoPadding, 
 74                            GFXTextureProfile::NONE);
 75
 76
 77GuiCursor::GuiCursor()
 78{
 79   mHotSpot.set(0,0);
 80   mRenderOffset.set(0.0f,0.0f);
 81   mExtent.set(1,1);
 82   mTextureObject = NULL;
 83   mBitmapName = StringTable->EmptyString();
 84}
 85
 86GuiCursor::~GuiCursor()
 87{
 88}
 89
 90void GuiCursor::initPersistFields()
 91{
 92   addField("hotSpot",     TypePoint2I,   Offset(mHotSpot, GuiCursor), "The location of the cursor's hot spot (which pixel carries the click).");
 93   addField("renderOffset",TypePoint2F,   Offset(mRenderOffset, GuiCursor), "Offset of the bitmap, where 0 signifies left edge of the bitmap, 1, the right. Similarly for the Y-component.");
 94   addField("bitmapName",  TypeFilename,  Offset(mBitmapName, GuiCursor), "File name of the bitmap for the cursor.");
 95   Parent::initPersistFields();
 96}
 97
 98bool GuiCursor::onAdd()
 99{
100   if(!Parent::onAdd())
101      return false;
102
103   Sim::getGuiDataGroup()->addObject(this);
104
105   return true;
106}
107
108void GuiCursor::onRemove()
109{
110   Parent::onRemove();
111}
112
113void GuiCursor::render(const Point2I &pos)
114{
115   if (!mTextureObject && mBitmapName && mBitmapName[0])
116   {
117      mTextureObject.set( mBitmapName, &GFXGuiCursorProfile, avar("%s() - mTextureObject (line %d)", __FUNCTION__, __LINE__));
118      if(!mTextureObject)
119         return;
120      mExtent.set(mTextureObject->getWidth(), mTextureObject->getHeight());
121   }
122
123   // Render the cursor centered according to dimensions of texture
124   S32 texWidth = mTextureObject.getWidth();
125   S32 texHeight = mTextureObject.getHeight();
126
127   Point2I renderPos = pos;
128   renderPos.x -= (S32)( texWidth  * mRenderOffset.x );
129   renderPos.y -= (S32)( texHeight * mRenderOffset.y );
130
131   GFX->getDrawUtil()->clearBitmapModulation();
132   GFX->getDrawUtil()->drawBitmap(mTextureObject, renderPos);
133}
134
135//------------------------------------------------------------------------------
136IMPLEMENT_CONOBJECT(GuiControlProfile);
137
138ConsoleDocClass( GuiControlProfile,
139   "@brief A collection of properties that determine control behavior and rendering.\n"
140   "@ingroup GuiCore\n"
141   
142   ""
143);
144
145ImplementEnumType( GuiAlignmentType,
146   "\n\n"
147   "@ingroup GuiCore" )
148   { GuiControlProfile::LeftJustify,          "Left"      },
149   { GuiControlProfile::CenterJustify,        "Center"    },
150   { GuiControlProfile::RightJustify,         "Right"     },
151   { GuiControlProfile::TopJustify,           "Top"       },
152   { GuiControlProfile::BottomJustify,        "Bottom"    }
153EndImplementEnumType;
154
155ImplementEnumType( GuiFontCharset,
156   "\n\n"
157   "@ingroup GuiCore" )
158    { TGE_ANSI_CHARSET,         "ANSI" },
159    { TGE_SYMBOL_CHARSET,       "SYMBOL" },
160    { TGE_SHIFTJIS_CHARSET,     "SHIFTJIS" },
161    { TGE_HANGEUL_CHARSET,      "HANGEUL" },
162    { TGE_HANGUL_CHARSET,       "HANGUL" },
163    { TGE_GB2312_CHARSET,       "GB2312" },
164    { TGE_CHINESEBIG5_CHARSET,  "CHINESEBIG5" },
165    { TGE_OEM_CHARSET,          "OEM" },
166    { TGE_JOHAB_CHARSET,        "JOHAB" },
167    { TGE_HEBREW_CHARSET,       "HEBREW" },
168    { TGE_ARABIC_CHARSET,       "ARABIC" },
169    { TGE_GREEK_CHARSET,        "GREEK" },
170    { TGE_TURKISH_CHARSET,      "TURKISH" },
171    { TGE_VIETNAMESE_CHARSET,   "VIETNAMESE" },
172    { TGE_THAI_CHARSET,         "THAI" },
173    { TGE_EASTEUROPE_CHARSET,   "EASTEUROPE" },
174    { TGE_RUSSIAN_CHARSET,      "RUSSIAN" },
175    { TGE_MAC_CHARSET,          "MAC" },
176    { TGE_BALTIC_CHARSET,       "BALTIC" },
177EndImplementEnumType;
178
179
180StringTableEntry GuiControlProfile::sFontCacheDirectory = "";
181
182void GuiControlProfile::setBitmapHandle(GFXTexHandle handle)
183{
184   mTextureObject = handle;
185
186   mBitmapName = StringTable->insert("texhandle");
187}
188
189bool GuiControlProfile::protectedSetBitmap( void *object, const char *index, const char *data )
190{
191   GuiControlProfile *profile = static_cast<GuiControlProfile*>( object );
192   
193   profile->mBitmapName = StringTable->insert(data);
194
195   if ( !profile->isProperlyAdded() )
196      return false;
197      
198   if( profile->mLoadCount > 0 )
199   {
200      profile->mBitmapArrayRects.clear();
201      profile->mTextureObject = NULL;
202
203      //verify the bitmap
204      if (profile->mBitmapName && profile->mBitmapName[0] && dStricmp(profile->mBitmapName, "texhandle") != 0 &&
205         !profile->mTextureObject.set( profile->mBitmapName, &GFXTexturePersistentProfile, avar("%s() - mTextureObject (line %d)", __FUNCTION__, __LINE__) ))
206         Con::errorf("Failed to load profile bitmap (%s)",profile->mBitmapName);
207
208      // If we've got a special border, make sure it's usable.
209      //if( profile->mBorder == -1 || profile->mBorder == -2 )
210      profile->constructBitmapArray();
211   }
212
213   return false;
214}
215
216const char* GuiControlProfile::protectedGetSoundButtonDown( void* object, const char* data )
217{
218   GuiControlProfile* profile = reinterpret_cast< GuiControlProfile* >( object );
219
220   SFXTrack* track = profile->mSoundButtonDown;
221   if( !track )
222      return "";
223
224   return track->getName();
225}
226
227bool GuiControlProfile::protectedSetSoundButtonDown( void* object, const char* index, const char* data )
228{
229   GuiControlProfile* profile = reinterpret_cast< GuiControlProfile* >( object );
230   
231   SFXTrack* track = NULL;
232   if( data && data[ 0] && !Sim::findObject( data, track ) )
233   {
234      Con::errorf( "GuiControlProfile::protectedSetSoundButtonDown - no SFXTrack '%s'", data );
235      return false;
236   }
237   
238   profile->mSoundButtonDown = track;
239   
240   return false;
241}
242
243const char* GuiControlProfile::protectedGetSoundButtonOver( void* object, const char* data )
244{
245   GuiControlProfile* profile = reinterpret_cast< GuiControlProfile* >( object );
246
247   SFXTrack* track = profile->mSoundButtonOver;
248   if( !track )
249      return "";
250
251   return track->getName();
252}
253
254bool GuiControlProfile::protectedSetSoundButtonOver( void* object, const char* index, const char* data )
255{
256   GuiControlProfile* profile = reinterpret_cast< GuiControlProfile* >( object );
257   
258   SFXTrack* track = NULL;
259   if( data && data[ 0] && !Sim::findObject( data, track ) )
260   {
261      Con::errorf( "GuiControlProfile::protectedSetSoundButtonOver - no SFXTrack '%s'", data );
262      return false;
263   }
264   
265   profile->mSoundButtonOver = track;
266   
267   return false;
268}
269
270GuiControlProfile::GuiControlProfile(void) :
271   mFillColor(255,0,255,255),
272   mFillColorHL(255,0,255,255),
273   mFillColorNA(255,0,255,255),
274   mFillColorERR(255,0,0,255),
275   mFillColorSEL(255,0,255,255),
276   mBorderColor(255,0,255,255),
277   mBorderColorHL(255,0,255,255),
278   mBorderColorNA(255,0,255,255),
279   mBevelColorHL(255,0,255,255),
280   mBevelColorLL(255,0,255,255),
281   // initialize these references to locations in the font colors array
282   // the array is initialized below.
283   mFontColor(mFontColors[BaseColor]),
284   mFontColorHL(mFontColors[ColorHL]),
285   mFontColorNA(mFontColors[ColorNA]),
286   mFontColorSEL(mFontColors[ColorSEL]),
287   mCursorColor(255,0,255,255),
288   mTextOffset(0,0),
289   mBitmapArrayRects(0)
290{
291   mLoadCount = 0;
292   mUseCount = 0;
293   
294   // event focus behavior
295   mTabable = false;
296   mCanKeyFocus = false;
297   mModal = false;
298
299   // fill and border   
300   mOpaque = false;
301   mBorder = 1;
302   mBorderThickness = 1;
303
304   // font members
305   mFontType = "Arial";
306   mFontSize = 10;
307
308   for(U32 i = 0; i < 10; i++)
309      mFontColors[i].set(255,0,255,255);
310
311   mFontCharset = TGE_ANSI_CHARSET;
312
313   // sizing and alignment
314   mAlignment = LeftJustify;
315   mAutoSizeWidth = false;
316   mAutoSizeHeight= false;
317   mReturnTab     = false;
318   mNumbersOnly   = false;
319   mMouseOverSelected = false;
320   
321   // bitmap members
322   mBitmapName = NULL;
323   mUseBitmapArray = false;
324   mTextureObject = NULL; // initialized in incLoadCount()
325
326   mChildrenProfileName = NULL;
327   mChildrenProfile = NULL;
328
329   // inherit/copy values from GuiDefaultProfile
330   GuiControlProfile *def = dynamic_cast<GuiControlProfile*>(Sim::findObject("GuiDefaultProfile"));
331   if (def)
332   {
333      mTabable       = def->mTabable;
334      mCanKeyFocus   = def->mCanKeyFocus;
335
336      mOpaque        = def->mOpaque;
337      mFillColor     = def->mFillColor;
338      mFillColorHL   = def->mFillColorHL;
339      mFillColorNA   = def->mFillColorNA;
340      mFillColorERR  = def->mFillColorERR;
341      mFillColorSEL  = def->mFillColorSEL;
342
343      mBorder        = def->mBorder;
344      mBorderThickness = def->mBorderThickness;
345      mBorderColor   = def->mBorderColor;
346      mBorderColorHL = def->mBorderColorHL;
347      mBorderColorNA = def->mBorderColorNA;
348
349      mBevelColorHL = def->mBevelColorHL;
350      mBevelColorLL = def->mBevelColorLL;
351
352      // default font
353      mFontType      = def->mFontType;
354      mFontSize      = def->mFontSize;
355      mFontCharset   = def->mFontCharset;
356
357      for(U32 i = 0; i < 10; i++)
358         mFontColors[i] = def->mFontColors[i];
359      
360      // default bitmap
361      mBitmapName     = def->mBitmapName;
362      mUseBitmapArray = def->mUseBitmapArray;
363      mTextOffset     = def->mTextOffset;
364
365      // default sound
366      mSoundButtonDown = def->mSoundButtonDown;
367      mSoundButtonOver = def->mSoundButtonOver;
368
369      //used by GuiTextCtrl
370      mModal         = def->mModal;
371      mAlignment     = def->mAlignment;
372      mAutoSizeWidth = def->mAutoSizeWidth;
373      mAutoSizeHeight= def->mAutoSizeHeight;
374      mReturnTab     = def->mReturnTab;
375      mNumbersOnly   = def->mNumbersOnly;
376      mCursorColor   = def->mCursorColor;
377      mChildrenProfileName = def->mChildrenProfileName;
378      setChildrenProfile(def->mChildrenProfile);
379   }
380}
381
382GuiControlProfile::~GuiControlProfile()
383{
384}
385
386
387void GuiControlProfile::initPersistFields()
388{
389   addGroup( "Behavior" );
390   
391      addField( "tab",           TypeBool,       Offset(mTabable, GuiControlProfile));
392      addField("canKeyFocus",   TypeBool,       Offset(mCanKeyFocus, GuiControlProfile),
393         "Whether the control can have the keyboard focus." );
394      addField("mouseOverSelected", TypeBool,   Offset(mMouseOverSelected, GuiControlProfile));
395      addField("modal",         TypeBool,       Offset(mModal, GuiControlProfile));
396   
397   endGroup( "Behavior" );
398   
399   addGroup( "Appearance" );
400   
401      addField("opaque",        TypeBool,       Offset(mOpaque, GuiControlProfile));
402      addField("fillColor",     TypeColorI,     Offset(mFillColor, GuiControlProfile));
403      addField("fillColorHL",   TypeColorI,     Offset(mFillColorHL, GuiControlProfile));
404      addField("fillColorNA",   TypeColorI,     Offset(mFillColorNA, GuiControlProfile));
405      addField("fillColorERR",  TypeColorI,     Offset(mFillColorERR, GuiControlProfile));
406      addField("fillColorSEL",  TypeColorI,     Offset(mFillColorSEL, GuiControlProfile));
407      addField("border",        TypeS32,        Offset(mBorder, GuiControlProfile),
408         "Border type (0=no border)." );
409      addField("borderThickness",TypeS32,       Offset(mBorderThickness, GuiControlProfile),
410         "Thickness of border in pixels." );
411      addField("borderColor",   TypeColorI,     Offset(mBorderColor, GuiControlProfile),
412         "Color to draw border with." );
413      addField("borderColorHL", TypeColorI,     Offset(mBorderColorHL, GuiControlProfile));
414      addField("borderColorNA", TypeColorI,     Offset(mBorderColorNA, GuiControlProfile));
415
416      addField("bevelColorHL", TypeColorI,     Offset(mBevelColorHL, GuiControlProfile));
417      addField("bevelColorLL", TypeColorI,     Offset(mBevelColorLL, GuiControlProfile));
418   
419   endGroup( "Appearance" );
420   
421   addGroup( "Text" );
422
423      addField("fontType",             TypeString,     Offset(mFontType, GuiControlProfile),
424         "Name of font family and typeface (e.g. \"Arial Bold\")." );
425      addField("fontSize",             TypeS32,        Offset(mFontSize, GuiControlProfile),
426         "Font size in points." );
427      addField("fontCharset",          TYPEID< FontCharset >(),       Offset(mFontCharset, GuiControlProfile) );
428      addField("fontColors",           TypeColorI,     Offset(mFontColors, GuiControlProfile), 10,
429         "Font colors to use for different text types/states." );
430      addField("fontColor",            TypeColorI,     Offset(mFontColors[BaseColor], GuiControlProfile),
431         "Font color for normal text (same as fontColors[0])." );
432      addField("fontColorHL",          TypeColorI,     Offset(mFontColors[ColorHL], GuiControlProfile),
433         "Font color for highlighted text (same as fontColors[1])." );
434      addField("fontColorNA",          TypeColorI,     Offset(mFontColors[ColorNA], GuiControlProfile),
435         "Font color when control is not active/disabled (same as fontColors[2])." );
436      addField("fontColorSEL",         TypeColorI,     Offset(mFontColors[ColorSEL], GuiControlProfile),
437         "Font color for selected text (same as fontColors[3])." );
438      addField("fontColorLink",        TypeColorI,     Offset(mFontColors[ColorUser0], GuiControlProfile),
439         "Font color for links in text (same as fontColors[4])." );
440      addField("fontColorLinkHL",      TypeColorI,     Offset(mFontColors[ColorUser1], GuiControlProfile),
441         "Font color for highlighted links in text (same as fontColors[5])." );
442            
443      addField( "justify",       TYPEID< GuiControlProfile::AlignmentType >(),       Offset(mAlignment, GuiControlProfile),
444         "Horizontal alignment for text." );
445      addField( "textOffset",    TypePoint2I,    Offset(mTextOffset, GuiControlProfile));
446      addField( "autoSizeWidth", TypeBool,       Offset(mAutoSizeWidth, GuiControlProfile),
447         "Automatically adjust width of control to fit contents." );
448      addField("autoSizeHeight",TypeBool,       Offset(mAutoSizeHeight, GuiControlProfile),
449         "Automatically adjust height of control to fit contents." );
450      addField("returnTab",     TypeBool,       Offset(mReturnTab, GuiControlProfile),
451         "Whether to add automatic tab event when return is pressed so focus moves on to next control (GuiTextEditCtrl)." );
452      addField("numbersOnly",   TypeBool,       Offset(mNumbersOnly, GuiControlProfile),
453         "Whether control should only accept numerical data (GuiTextEditCtrl)." );
454      addField("cursorColor",   TypeColorI,     Offset(mCursorColor, GuiControlProfile),
455         "Color to use for the text cursor." );
456
457   endGroup( "Text" );
458   
459   addGroup( "Misc" );
460
461      addProtectedField( "bitmap", TypeFilename,  Offset(mBitmapName, GuiControlProfile),
462         &GuiControlProfile::protectedSetBitmap, &defaultProtectedGetFn,
463         "Texture to use for rendering control." );
464      addField("hasBitmapArray", TypeBool,      Offset(mUseBitmapArray, GuiControlProfile),
465         "If true, 'bitmap' is an array of images." );
466
467      addProtectedField( "soundButtonDown", TypeSFXTrackName,  Offset(mSoundButtonDown, GuiControlProfile),
468         &GuiControlProfile::protectedSetSoundButtonDown, &GuiControlProfile::protectedGetSoundButtonDown,
469         "Sound to play when mouse has been pressed on control." );
470      addProtectedField( "soundButtonOver", TypeSFXTrackName,  Offset(mSoundButtonOver, GuiControlProfile),
471         &GuiControlProfile::protectedSetSoundButtonOver, &GuiControlProfile::protectedGetSoundButtonOver,
472         "Sound to play when mouse is hovering over control." );
473      addField("profileForChildren", TypeString,      Offset(mChildrenProfileName, GuiControlProfile));
474   
475   endGroup( "Misc" );
476   
477   addField( "category", TypeRealString, Offset( mCategory, GuiControlProfile ),
478      "Category under which the profile will appear in the editor."
479   );
480
481   Parent::initPersistFields();
482}
483
484bool GuiControlProfile::onAdd()
485{
486   if(!Parent::onAdd())
487      return false;
488
489   Sim::getGuiDataGroup()->addObject(this);
490   
491   // Make sure we have an up-to-date children profile
492   getChildrenProfile();
493
494   return true;
495}
496
497void GuiControlProfile::onStaticModified(const char* slotName, const char* newValue)
498{
499   if( mLoadCount > 0 )
500   {
501      if ( !dStricmp(slotName, "fontType") || 
502           !dStricmp(slotName, "fontCharset") ||
503           !dStricmp(slotName, "fontSize" ) )
504      {
505         // Reload the font
506         mFont = GFont::create(mFontType, mFontSize, sFontCacheDirectory, mFontCharset);
507         if ( mFont == NULL )
508            Con::errorf("Failed to load/create profile font (%s/%d)", mFontType, mFontSize);
509      }
510   }
511}
512
513void GuiControlProfile::onDeleteNotify(SimObject *object)
514{
515   if (object == mChildrenProfile)
516      mChildrenProfile = NULL;
517}
518
519GuiControlProfile* GuiControlProfile::getChildrenProfile()
520{
521   // We can early out if we still have a valid profile
522   if (mChildrenProfile)
523      return mChildrenProfile;
524
525   // Attempt to find the profile specified
526   if (mChildrenProfileName)
527   {
528      GuiControlProfile *profile = dynamic_cast<GuiControlProfile*>(Sim::findObject( mChildrenProfileName ));
529
530      if( profile )
531         setChildrenProfile(profile);
532   }
533
534   return mChildrenProfile;
535}
536
537void GuiControlProfile::setChildrenProfile(GuiControlProfile *prof)
538{
539   if(prof == mChildrenProfile)
540      return;
541
542   // Clear the delete notification we previously set up
543   if (mChildrenProfile)
544      clearNotify(mChildrenProfile);
545
546   mChildrenProfile = prof;
547
548   // Make sure that the new profile will notify us when it is deleted
549   if (mChildrenProfile)
550      deleteNotify(mChildrenProfile);
551}
552
553RectI GuiControlProfile::getBitmapArrayRect(U32 i)
554{
555   if(!mBitmapArrayRects.size())
556      constructBitmapArray();
557   
558   if( i >= mBitmapArrayRects.size())
559      return RectI(0,0,0,0);
560
561   return mBitmapArrayRects[i];
562}
563
564S32 GuiControlProfile::constructBitmapArray()
565{
566   if(mBitmapArrayRects.size())
567      return mBitmapArrayRects.size();
568
569   if( mTextureObject.isNull() )
570   {   
571      if ( !mBitmapName || !mBitmapName[0] || !mTextureObject.set( mBitmapName, &GFXTexturePersistentSRGBProfile, avar("%s() - mTextureObject (line %d)", __FUNCTION__, __LINE__) ))
572         return 0;
573   }
574
575   GBitmap *bmp = mTextureObject->getBitmap();
576
577   //get the separator color
578   ColorI sepColor;
579   if ( !bmp || !bmp->getColor( 0, 0, sepColor ) )
580   {
581      Con::errorf("Failed to create bitmap array from %s for profile %s - couldn't ascertain seperator color!", mBitmapName, getName());
582      AssertFatal( false, avar("Failed to create bitmap array from %s for profile %s - couldn't ascertain seperator color!", mBitmapName, getName()));
583      return 0;
584   }
585
586   //now loop through all the scroll pieces, and find the bounding rectangle for each piece in each state
587   S32 curY = 0;
588
589   // ascertain the height of this row...
590   ColorI color;
591   mBitmapArrayRects.clear();
592   while(curY < bmp->getHeight())
593   {
594      // skip any sep colors
595      bmp->getColor( 0, curY, color);
596      if(color == sepColor)
597      {
598         curY++;
599         continue;
600      }
601      // ok, process left to right, grabbing bitmaps as we go...
602      S32 curX = 0;
603      while(curX < bmp->getWidth())
604      {
605         bmp->getColor(curX, curY, color);
606         if(color == sepColor)
607         {
608            curX++;
609            continue;
610         }
611         S32 startX = curX;
612         while(curX < bmp->getWidth())
613         {
614            bmp->getColor(curX, curY, color);
615            if(color == sepColor)
616               break;
617            curX++;
618         }
619         S32 stepY = curY;
620         while(stepY < bmp->getHeight())
621         {
622            bmp->getColor(startX, stepY, color);
623            if(color == sepColor)
624               break;
625            stepY++;
626         }
627         mBitmapArrayRects.push_back(RectI(startX, curY, curX - startX, stepY - curY));
628      }
629      // ok, now skip to the next separation color on column 0
630      while(curY < bmp->getHeight())
631      {
632         bmp->getColor(0, curY, color);
633         if(color == sepColor)
634            break;
635         curY++;
636      }
637   }
638   return mBitmapArrayRects.size();
639}
640
641void GuiControlProfile::incLoadCount()
642{
643   if( !mLoadCount )
644   {
645      #ifdef DEBUG_SPEW
646      Platform::outputDebugString( "[GuiControlProfile] Loading profile %i:%s (%s:%s)",
647         getId(), getClassName(), getName(), getInternalName() );
648      #endif
649      
650      sFontCacheDirectory = Con::getVariable( "$GUI::fontCacheDirectory" );
651         
652      // Load font (if not already loaded).
653      
654      if( mFont == NULL )
655         loadFont();
656
657      //
658
659      if (mBitmapName && mBitmapName[0] && dStricmp(mBitmapName, "texhandle") != 0 &&
660         !mTextureObject.set( mBitmapName, &GFXTexturePersistentSRGBProfile, avar("%s() - mTextureObject (line %d)", __FUNCTION__, __LINE__) ))
661         Con::errorf("Failed to load profile bitmap (%s)",mBitmapName);
662
663      constructBitmapArray();
664   }
665   
666   mLoadCount ++;
667
668   // Quick check to make sure our children profile is up-to-date
669   getChildrenProfile();
670}
671
672void GuiControlProfile::decLoadCount()
673{
674   AssertFatal( mLoadCount, "GuiControlProfile::decLoadCount - zero load count" );
675   if(!mLoadCount)
676      return;
677
678   -- mLoadCount;
679   if( !mLoadCount )
680   {
681      #ifdef DEBUG_SPEW
682      Platform::outputDebugString( "[GuiControlProfile] Unloading profile %i:%s (%s:%s)",
683         getId(), getClassName(), getName(), getInternalName() );
684      #endif
685
686      if( !mBitmapName || !mBitmapName[0] || dStricmp(mBitmapName, "texhandle") != 0 )
687         mTextureObject = NULL;
688   }
689}
690
691bool GuiControlProfile::loadFont()
692{
693   mFont = GFont::create( mFontType, mFontSize, sFontCacheDirectory, mFontCharset );
694   if( mFont == NULL )
695   {
696      Con::errorf( "GuiControlProfile::loadFont - Failed to load/create profile font (%s/%d)", mFontType, mFontSize );
697      return false;
698   }
699      
700   return true;
701}
702
703DefineEngineMethod( GuiControlProfile, getStringWidth, S32, (const char* string),,
704   "Get the width of the string in pixels.\n"
705   "@param string String to get the width of."
706   "@return width of the string in pixels." )
707{
708   return object->mFont->getStrNWidth( string, dStrlen( string ) );
709}
710
711//-----------------------------------------------------------------------------
712// TypeRectSpacingI
713//-----------------------------------------------------------------------------
714IMPLEMENT_STRUCT( RectSpacingI,
715   RectSpacingI, GuiAPI,
716   "" )
717   
718      FIELD( left, leftPadding, 1, "" )
719      FIELD( right, rightPadding, 1, "" )
720      FIELD( top, topPadding, 1, "" )
721      FIELD( bottom, bottomPadding, 1, "" )
722      
723END_IMPLEMENT_STRUCT;
724
725ConsoleType(RectSpacingI, TypeRectSpacingI, RectSpacingI, "")
726ImplementConsoleTypeCasters( TypeRectSpacingI, RectSpacingI )
727
728ConsoleGetType( TypeRectSpacingI )
729{
730   RectSpacingI *rect = (RectSpacingI *) dptr;
731   static const U32 bufSize = 256;
732   char* returnBuffer = Con::getReturnBuffer(bufSize);
733   dSprintf(returnBuffer, bufSize, "%d %d %d %d", rect->top, rect->bottom,
734      rect->left, rect->right);
735   return returnBuffer;
736}
737
738ConsoleSetType( TypeRectSpacingI )
739{
740   if(argc == 1)
741      dSscanf(argv[0], "%d %d %d %d", &((RectSpacingI *) dptr)->top, &((RectSpacingI *) dptr)->bottom,
742      &((RectSpacingI *) dptr)->left, &((RectSpacingI *) dptr)->right);
743   else if(argc == 4)
744      *((RectSpacingI *) dptr) = RectSpacingI(dAtoi(argv[0]), dAtoi(argv[1]), dAtoi(argv[2]), dAtoi(argv[3]));
745   else
746      Con::printf("RectSpacingI must be set as { t, b, l, r } or \"t b l r\"");
747}
748