00001 #include "lugre_prefix.h"
00002 #include "lugre_gfx2D.h"
00003 #include "lugre_gfx3D.h"
00004 #include "lugre_game.h"
00005 #include "lugre_scripting.h"
00006 #include "lugre_robstring.h"
00007
00008 #include "lugre_robrenderable.h"
00009 #include <math.h>
00010 #include <vector>
00011 #include <list>
00012 #include <algorithm>
00013 #include <functional>
00014 #include "lugre_listener.h"
00015 #include "lugre_ogrewrapper.h"
00016
00017 #include <Ogre.h>
00018 #include <OgreOverlay.h>
00019 #include <OgreOverlayManager.h>
00020 #include <OgrePanelOverlayElement.h>
00021 #include <OgreTextAreaOverlayElement.h>
00022 #include <OgreFontManager.h>
00023
00024 #include "lugre_CompassOverlay.h"
00025 #include "lugre_RobRenderableOverlay.h"
00026 #include "lugre_ColourClipPaneOverlay.h"
00027 #include "lugre_ColourClipTextOverlay.h"
00028 #include "lugre_BorderColourClipPaneOverlay.h"
00029 #include "lugre_SortedOverlayContainer.h"
00030 #include "lugre_input.h"
00031
00032 using namespace Ogre;
00033
00034 namespace Lugre {
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 int giGfx2DFrameCounter = 0;
00062
00063 unsigned int cGfx2D::miCount;
00064
00065
00066
00067 std::list<cGfx2D*> cGfx2D::gPrepareFrameStepper;
00068
00069 void cGfx2D::SetPrepareFrameStep (const bool bOn) {
00070 if (mbPrepareFrameStep == bOn) return;
00071 mbPrepareFrameStep = bOn;
00072
00073 if (mbPrepareFrameStep) {
00074 gPrepareFrameStepper.push_front(this);
00075 mPrepareFrameItor = gPrepareFrameStepper.begin();
00076 assert(*mPrepareFrameItor == this && "cGfx2D::SetPrepareFrameStep insert broken\n");
00077 } else {
00078 assert(*mPrepareFrameItor == this && "cGfx2D::SetPrepareFrameStep erase broken\n");
00079 gPrepareFrameStepper.erase(mPrepareFrameItor);
00080 }
00081
00082 }
00083
00084 void cGfx2D::PrepareFrame () {
00085 ++giGfx2DFrameCounter;
00086 std::for_each(gPrepareFrameStepper.begin(),gPrepareFrameStepper.end(),std::mem_fun(&cGfx2D::PrepareFrameStep));
00087 }
00088
00090 void cGfx2D::PrepareFrameStep () {
00091 cGfx3D* pGfx3D = *mpTrackPosTarget;
00092 if (pGfx3D && pGfx3D->mpSceneNode) {
00093 cOgreWrapper& ogrewrapper = cOgreWrapper::GetSingleton();
00094 Ogre::Real sw = Ogre::Real(ogrewrapper.GetViewportWidth());
00095 Ogre::Real sh = Ogre::Real(ogrewrapper.GetViewportHeight());
00096 pGfx3D->UpdateProjected(giGfx2DFrameCounter);
00097 Ogre::Vector3 s = pGfx3D->mvProjectedSize;
00098 Ogre::Vector3 p = pGfx3D->mvProjectedPos;
00099 bool bIsBehindCam = s.z >= 0;
00100 p.x = ( p.x + 1.0)*0.5*sw;
00101 p.y = (-p.y + 1.0)*0.5*sh;
00102 s.x *= sw*0.5; s.y *= sh*0.5;
00103 bool bDidClamp = false;
00104
00105
00106 if (mbTrackClamp || mbTrackHideIfClamped || mbTrackClampMaxXIfBehindCam || mbTrackClampMaxYIfBehindCam) {
00107 float nx = mymax(mvTrackClampMin.x,mymin(mvTrackClampMax.x,p.x));
00108 float ny = mymax(mvTrackClampMin.y,mymin(mvTrackClampMax.y,p.y));
00109 if (mbTrackClampMaxXIfBehindCam && bIsBehindCam) nx = (p.x > 0.5*sw) ? mvTrackClampMin.x : mvTrackClampMax.x;
00110 if (mbTrackClampMaxYIfBehindCam && bIsBehindCam) ny = (p.y > 0.5*sh) ? mvTrackClampMin.y : mvTrackClampMax.y;
00111 bDidClamp = (nx != p.x) || (ny != p.y);
00112 p.x = nx;
00113 p.y = ny;
00114 }
00115
00116
00117 if (mbTrackSetSize) SetDimensions(myround(s.x*mvTrackSetSizeFactor.x),myround(s.y*mvTrackSetSizeFactor.y));
00118 float x = mvTrackPosOffset.x + p.x + s.x*mvTrackPosTargetSizeFactor.x + mvTrackPosOwnSizeFactor.x*GetWidth();
00119 float y = mvTrackPosOffset.y + p.y + s.y*mvTrackPosTargetSizeFactor.y + mvTrackPosOwnSizeFactor.y*GetHeight();
00120 SetPos(myround(x),myround(y));
00121
00122
00123 if (mbTrackHideIfClamped || mbTrackHideIfBehindCam) SetVisible(!bDidClamp && !bIsBehindCam);
00124 }
00125 if (mbTrackMouse) {
00126 SetPos(float(cInput::iMouse[0] + mvTrackPosOffset.x),float(cInput::iMouse[1] + mvTrackPosOffset.y));
00127 }
00128 }
00129
00130
00131
00132
00134 cGfx2D::cGfx2D (Ogre::Overlay* pRootOverlay,cGfx2D* pDefaultParent) { PROFILE
00135 mpRootOverlay = pRootOverlay;
00136 mpDefaultParent = pDefaultParent;
00137 Init();
00138 ++miCount;
00139 }
00140
00141 cGfx2D::~cGfx2D () { PROFILE
00142 Clear();
00143 --miCount;
00144 }
00145
00146 void cGfx2D::Init () {
00147 mpOverlayElement = 0;
00148 mpOverlayContainer = 0;
00149 mpPanel = 0;
00150 mpText = 0;
00151 mpCCPO = 0;
00152 mpCCTO = 0;
00153 mpBCCPO = 0;
00154 mpSOC = 0;
00155 mpRROC = 0;
00156
00157 mpParent_Overlay = 0;
00158 mpParent_Gfx2D = 0;
00159
00160 mbPrepareFrameStep = false;
00161
00162 mvTrackPosOffset = Ogre::Vector2(0,0);
00163 mvTrackPosTargetSizeFactor = Ogre::Vector2(0,0);
00164 mvTrackPosOwnSizeFactor = Ogre::Vector2(0,0);
00165 mvTrackClampMin = Ogre::Vector2(0,0);
00166 mvTrackClampMax = Ogre::Vector2(0,0);
00167 mvTrackSetSizeFactor = Ogre::Vector2(1,1);
00168 mbTrackClamp = false;
00169 mbTrackHideIfClamped = false;
00170 mbTrackHideIfBehindCam = true;
00171 mbTrackClampMaxXIfBehindCam = true;
00172 mbTrackClampMaxYIfBehindCam = true;
00173 mbTrackSetSize = false;
00174 mbTrackMouse = false;
00175 }
00176
00178 void cGfx2D::Clear () { PROFILE
00179
00180 SetPrepareFrameStep(false);
00181 if (mpOverlayElement) mpOverlayElement->hide();
00182
00183
00184 if ((*mpParent_Gfx2D) && (*mpParent_Gfx2D)->mpOverlayContainer && mpOverlayElement) {
00185 (*mpParent_Gfx2D)->mpOverlayContainer->removeChild(mpOverlayElement->getName());
00186 mpParent_Gfx2D = 0;
00187 }
00188 if (mpParent_Overlay && mpOverlayContainer) {
00189 mpParent_Overlay->remove2D(mpOverlayContainer);
00190 mpParent_Overlay = 0;
00191 }
00192
00193
00194 if (mpOverlayElement) { OverlayManager::getSingleton().destroyOverlayElement(mpOverlayElement); mpOverlayElement = 0; }
00195
00196
00197
00198
00199 Init();
00200 }
00201
00202 std::string cGfx2D::GetUniqueName () { PROFILE
00203 static int iLastName = 0;
00204 return strprintf("gfx2d_%d",++iLastName);
00205 }
00206
00207
00208 Ogre::Overlay* cGfx2D::CreateOverlay (const char* szName,const size_t iZOrder) {
00209 Ogre::Overlay* res = OverlayManager::getSingleton().create(szName);
00210 res->setZOrder(iZOrder);
00211 res->show();
00212 return res;
00213 }
00214
00215 void cGfx2D::DestroyOverlay (Ogre::Overlay* pOverlay) {
00216 if (pOverlay) OverlayManager::getSingleton().destroy(pOverlay);
00217 }
00218
00219
00220
00221
00222
00223
00225 void cGfx2D::InitPanel (cGfx2D* pParent) { PROFILE
00226 mpPanel = static_cast<PanelOverlayElement*>(OverlayManager::getSingleton().createOverlayElement("Panel",GetUniqueName()));
00227 mpOverlayContainer = mpPanel;
00228 InitBase(mpPanel,pParent);
00229 }
00230
00232 void cGfx2D::InitCCPO (cGfx2D* pParent) { PROFILE
00233 mpCCPO = static_cast<cColourClipPaneOverlay*>(OverlayManager::getSingleton().createOverlayElement("ColourClipPane",GetUniqueName()));
00234 mpOverlayContainer = mpCCPO;
00235 InitBase(mpCCPO,pParent);
00236 }
00237
00239 void cGfx2D::InitCCTO (cGfx2D* pParent) { PROFILE
00240 mpCCTO = static_cast<cColourClipTextOverlay*>(OverlayManager::getSingleton().createOverlayElement("ColourClipText",GetUniqueName()));
00241 InitBase(mpCCTO,pParent);
00242 }
00243
00244
00246 void cGfx2D::InitBCCPO (cGfx2D* pParent) { PROFILE
00247 mpBCCPO = static_cast<cBorderColourClipPaneOverlay*>(OverlayManager::getSingleton().createOverlayElement("BorderColourClipPane",GetUniqueName()));
00248 mpOverlayContainer = mpBCCPO;
00249 InitBase(mpBCCPO,pParent);
00250 }
00251
00253 void cGfx2D::InitSOC (cGfx2D* pParent) { PROFILE
00254 mpSOC = static_cast<cSortedOverlayContainer*>(OverlayManager::getSingleton().createOverlayElement("SortedOverlayContainer",GetUniqueName()));
00255 mpOverlayContainer = mpSOC;
00256 InitBase(mpSOC,pParent);
00257 }
00258
00260 void cGfx2D::InitRROC (cGfx2D* pParent) { PROFILE
00261 mpRROC = static_cast<cRobRenderableOverlay*>(OverlayManager::getSingleton().createOverlayElement("RobRenderableOverlay",GetUniqueName()));
00262 mpOverlayContainer = mpRROC;
00263 InitBase(mpRROC,pParent);
00264 }
00265
00267 void cGfx2D::InitText (cGfx2D* pParent) { PROFILE
00268 mpText = static_cast<TextAreaOverlayElement*>(OverlayManager::getSingleton().createOverlayElement("TextArea",GetUniqueName()));
00269 InitBase(mpText,pParent);
00270 }
00271
00272
00273 void cGfx2D::InitCompass (cGfx2D* pParent) { PROFILE
00274 mpCompass = static_cast<cCompassOverlay*>(OverlayManager::getSingleton().createOverlayElement("Compass",GetUniqueName()));
00275 mpOverlayContainer = mpCompass;
00276 InitBase(mpCompass,pParent);
00277 }
00278
00279
00281 void cGfx2D::InitBase (Ogre::OverlayElement* pOverlayElement,cGfx2D* pParent) { PROFILE
00282 assert(pOverlayElement);
00283 assert(!mpOverlayElement && "cannot init twice");
00284 mpOverlayElement = pOverlayElement;
00285 mpOverlayElement->setMetricsMode(Ogre::GMM_PIXELS);
00286
00287 if (!pParent) pParent = mpDefaultParent;
00288
00289 mpParent_Overlay = 0;
00290 mpParent_Gfx2D = pParent;
00291
00292 if (pParent && pParent->mpOverlayContainer) {
00293
00294 pParent->mpOverlayContainer->addChild(mpOverlayElement);
00295 } else {
00296 if (pParent) printf("cGfx2D::InitBase : could not add self to parent, as parent is no container (panel)\n");
00297 if (mpOverlayContainer) {
00298 if (mpRootOverlay) {
00299
00300 mpParent_Overlay = mpRootOverlay;
00301 mpParent_Overlay->add2D(mpOverlayContainer);
00302 } else {
00303 printf("cGfx2D::InitBase : neither overlay nor parent-container to add self to specified !\n");
00304 }
00305 } else {
00306 printf("cGfx2D::InitBase : could not add self to overlay-list, only containers (panel) allowed\n");
00307 }
00308 }
00309 }
00310
00311
00312
00313 void cGfx2D::SetVisible (const bool bVisible) {
00314 if (!mpOverlayElement) return;
00315 if (bVisible && !mpOverlayElement->isVisible()) mpOverlayElement->show();
00316 if (!bVisible && mpOverlayElement->isVisible()) mpOverlayElement->hide();
00317 }
00318
00319 bool cGfx2D::GetVisible () {
00320 if (!mpOverlayElement) return false;
00321 return mpOverlayElement->isVisible();
00322 }
00323
00324 void cGfx2D::SetMaterial (const char* szMat) { PROFILE
00325 try {
00326 if (mpOverlayElement) mpOverlayElement->setMaterialName(szMat);
00327 } catch( Ogre::Exception& e ) {
00328 printf("warning, ogre::exception in cGfx2D::SetMaterial : %s\n",e.getFullDescription().c_str());
00329 }
00330 }
00331 void cGfx2D::SetBorderMaterial (const char* szMat) { PROFILE
00332 if (mpBCCPO) mpBCCPO->setBorderMaterialName(szMat);
00333 }
00334
00337 void cGfx2D::SetPos (const Ogre::Real x,const Ogre::Real y) { PROFILE
00338 if (!mpOverlayElement) return;
00339 mpOverlayElement->setPosition(x,y);
00340
00341 }
00342
00344 void cGfx2D::SetDimensions (const Real cx,const Real cy) { PROFILE
00345 if (mpOverlayElement) mpOverlayElement->setDimensions(cx,cy);
00346 }
00347
00348 void cGfx2D::SetTextAlignment (const size_t iTextAlign) {
00349 Ogre::GuiHorizontalAlignment ogrealign = Ogre::GHA_LEFT;
00350 switch (iTextAlign) {
00351 case kGfx2DAlign_Left: ogrealign = Ogre::GHA_LEFT; break;
00352 case kGfx2DAlign_Center: ogrealign = Ogre::GHA_CENTER; break;
00353 case kGfx2DAlign_Right: ogrealign = Ogre::GHA_RIGHT; break;
00354 default : printf("cGfx2D::SetTextAlignment : unknown iTextAlign %d\n",iTextAlign);
00355 }
00356 if (mpCCTO) mpCCTO->setAlignment(ogrealign);
00357
00358 if (mpText) switch (iTextAlign) {
00359 case kGfx2DAlign_Left: mpText->setAlignment(Ogre::TextAreaOverlayElement::Left); break;
00360 case kGfx2DAlign_Center: mpText->setAlignment(Ogre::TextAreaOverlayElement::Center); break;
00361 case kGfx2DAlign_Right: mpText->setAlignment(Ogre::TextAreaOverlayElement::Right); break;
00362 }
00363 }
00364
00369 void cGfx2D::SetAlignment (const size_t iHAlign,const size_t iVAlign) { PROFILE
00370 if (!mpOverlayElement) return;
00371 switch (iHAlign) {
00372 case kGfx2DAlign_Left: mpOverlayElement->setHorizontalAlignment(Ogre::GHA_LEFT); break;
00373 case kGfx2DAlign_Center: mpOverlayElement->setHorizontalAlignment(Ogre::GHA_CENTER); break;
00374 case kGfx2DAlign_Right: mpOverlayElement->setHorizontalAlignment(Ogre::GHA_RIGHT); break;
00375 default : printf("cGfx2D::SetAlignment : unknown halign %d\n",iHAlign);
00376 }
00377 switch (iVAlign) {
00378 case kGfx2DAlign_Top: mpOverlayElement->setVerticalAlignment(Ogre::GVA_TOP); break;
00379 case kGfx2DAlign_Center: mpOverlayElement->setVerticalAlignment(Ogre::GVA_CENTER); break;
00380 case kGfx2DAlign_Bottom: mpOverlayElement->setVerticalAlignment(Ogre::GVA_BOTTOM); break;
00381 default : printf("cGfx2D::SetAlignment : unknown valign %d\n",iVAlign);
00382 }
00383 }
00384
00385
00387 void cGfx2D::SetUV (const Ogre::Real u1, const Ogre::Real v1, const Ogre::Real u2, const Ogre::Real v2) { PROFILE
00388 if (mpPanel) mpPanel->setUV(u1,v1,u2,v2);
00389 if (mpCCPO) mpCCPO->SetTexCoords(u1,v1,u2,v2);
00390 if (mpBCCPO) mpBCCPO->SetTexCoords(u1,v1,u2,v2);
00391 }
00392
00394 void cGfx2D::SetPartUV (const int iPart,const Ogre::Real u1, const Ogre::Real v1, const Ogre::Real u2, const Ogre::Real v2) { PROFILE
00395 if (mpBCCPO) mpBCCPO->SetTexCoords(iPart,u1,v1,u2,v2);
00396 }
00397
00399 void cGfx2D::SetClip (const Ogre::Real fCL,const Ogre::Real fCT,const Ogre::Real fCW,const Ogre::Real fCH) { PROFILE
00400 if (mpCCPO) mpCCPO->SetClip(fCL,fCT,fCW,fCH);
00401 if (mpCCTO) mpCCTO->SetClip(fCL,fCT,fCW,fCH);
00402 if (mpBCCPO) mpBCCPO->SetClip(fCL,fCT,fCW,fCH);
00403 }
00405 void cGfx2D::SetBorder (const Ogre::Real l,const Ogre::Real t,const Ogre::Real r,const Ogre::Real b) { PROFILE
00406 if (mpBCCPO) mpBCCPO->SetBorder(l,t,r,b);
00407 }
00408
00410 void cGfx2D::SetCharHeight (const Ogre::Real fHeight) { PROFILE
00411 if (mpText) mpText->setCharHeight(fHeight);
00412 if (mpCCTO) mpCCTO->setCharHeight(fHeight);
00413 }
00414
00416 void cGfx2D::SetFont (const char* szFont) { PROFILE
00417 if (mpText) mpText->setFontName(szFont);
00418 if (mpCCTO) mpCCTO->setFontName(szFont);
00419 }
00420
00421 void cGfx2D::SetText (const char* szText) { PROFILE
00422 int len = szText ? strlen(szText) : 0;
00423 Ogre::UTFString sCaption;
00424
00425 for (int i=0;i<len;++i) sCaption.push_back(szText[i]);
00426
00427 try {
00428 if (mpOverlayElement) mpOverlayElement->setCaption(sCaption);
00429 } catch (...) {
00430 printdebug("unicode","WARNING, cGfx2D::SetText exception, unicode error?\n");
00431 }
00432 }
00433
00434 void cGfx2D::SetAutoWrap (const int iMaxW) {
00435 if (mpCCTO) mpCCTO->SetAutoWrap(iMaxW);
00436 }
00437
00438 void cGfx2D::SetColour (const Ogre::ColourValue& col) { PROFILE
00439 SetColours(col,col,col,col);
00440 }
00441
00443 void cGfx2D::SetColours (const Ogre::ColourValue& colLT,const Ogre::ColourValue& colRT,const Ogre::ColourValue& colLB,const Ogre::ColourValue& colRB) {
00444 if (mpCCPO) mpCCPO->SetColours(colLT,colRT,colLB,colRB);
00445 else if (mpBCCPO) mpBCCPO->SetColours(colLT,colRT,colLB,colRB);
00446 else if (mpOverlayElement) mpOverlayElement->setColour(colLT);
00447 }
00448
00450 void cGfx2D::SetPartColours (const int iPart,const Ogre::ColourValue& colLT,const Ogre::ColourValue& colRT,const Ogre::ColourValue& colLB,const Ogre::ColourValue& colRB) {
00451 if (mpBCCPO) mpBCCPO->SetColours(iPart,colLT,colRT,colLB,colRB);
00452 }
00453
00454 void cGfx2D::SetRotate (const Ogre::Real radians) { PROFILE
00455
00456 }
00457
00459 Ogre::Real cGfx2D::GetLeft () {
00460 if (!mpOverlayElement) return 0;
00461 return mpOverlayElement->getLeft();
00462 }
00463
00465 Ogre::Real cGfx2D::GetTop () {
00466 if (!mpOverlayElement) return 0;
00467 return mpOverlayElement->getTop();
00468 }
00469
00471 Ogre::Real cGfx2D::GetDerivedLeft () {
00472 if (!mpOverlayElement) return 0;
00473 cGfx2D* parent = *mpParent_Gfx2D;
00474 return mpOverlayElement->getLeft() + (parent?parent->GetDerivedLeft():0);
00475
00476
00477 }
00478
00480 Ogre::Real cGfx2D::GetDerivedTop () {
00481 if (!mpOverlayElement) return 0;
00482 cGfx2D* parent = *mpParent_Gfx2D;
00483 return mpOverlayElement->getTop() + (parent?parent->GetDerivedTop():0);
00484
00485
00486 }
00487
00488 Ogre::Real cGfx2D::GetWidth () {
00489 return mpOverlayElement ? mpOverlayElement->getWidth() : 0.0;
00490
00491 }
00492
00493 Ogre::Real cGfx2D::GetHeight () {
00494 return mpOverlayElement ? mpOverlayElement->getHeight() : 0.0;
00495
00496 }
00497
00498 bool cGfx2D::IsPointWithin (const size_t x,const size_t y) {
00499 if (!mpOverlayElement) return false;
00500 Real relmousex = x - GetDerivedLeft();
00501 Real relmousey = y - GetDerivedTop();
00502 return (relmousex >= 0.0) && (relmousey >= 0) && (relmousex < GetWidth()) && (relmousey < GetHeight());
00503 }
00504
00505 void cGfx2D::GetTextBounds (Ogre::Real& w,Ogre::Real& h) {
00506 if (!mpCCTO) { w=h=0; return; }
00507 mpCCTO->GetTextBounds(w,h);
00508 }
00509 int cGfx2D::GetGlyphAtPos (const size_t x,const size_t y) {
00510 if (!mpCCTO) return -1;
00511 return mpCCTO->GetGlyphAtPos(x,y);
00512 }
00513 void cGfx2D::GetGlyphBounds (const size_t iIndex,Ogre::Real& l,Ogre::Real& t,Ogre::Real& r,Ogre::Real& b) {
00514 if (!mpCCTO) { l=t=r=b=0; return; }
00515 mpCCTO->GetGlyphBounds(iIndex,l,t,r,b);
00516 }
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533 };