00001 #include "global.h"
00002 #include "MercuryMath.h"
00003 #include "ScreenMapEditor.h"
00004 #include "MercuryTheme.h"
00005 #include "MercuryInput.h"
00006 #include "MercuryLoadableModel.h"
00007 #include "MercuryDisplay.h"
00008
00009 #include "MercuryObjectFactory.h"
00010 REGISTER_SCREEN_CLASS( ScreenMapEditor )
00011
00012 #define MC_INPUTMAPPED 1 //convention: MESSAGE CODE
00013 #define MC_INPUTUNMAPPED 2
00014 #define MC_RESPFilename 3
00015 #define MC_RESPWorldname 4
00016 #define MC_RESPObjectname 5
00017 #define MC_RESPJumpToSel 6
00018 #define MC_RESPSetGravity 7
00019 #define MC_RESPFilename2 8
00020 #define MC_RESPDensity 9
00021 #define MC_RESPType 10
00022 #define MC_RESPLength 11
00023 #define MC_RESPRadius 12
00024 #define MC_RESPScale 13
00025
00026 #define MC_NewObjectName 14
00027 #define MC_DeleteConfirm 15
00028
00029
00030 KeyMappingWithCode( button_shift, "0-16" );
00031 KeyMappingWithCode( button_ctrl, "0-17" );
00032 KeyMappingWithCode( button_alt, "0-18" );
00033 KeyMappingWithCode( button_mouse1, "0-1" );
00034 KeyMappingWithCode( button_mouse2, "0-2" );
00035
00036 KeyMappingWithCode( button_up, "0-273" );
00037 KeyMappingWithCode( button_down, "0-274" );
00038 KeyMappingWithCode( button_right, "0-275" );
00039 KeyMappingWithCode( button_left, "0-276" );
00040
00041 KeyMappingWithCode( button_c, "0-99" );
00042 KeyMappingWithCode( button_d, "0-100" );
00043
00044 KeyMappingWithCode( button_F1, "0-282" );
00045 KeyMappingWithCode( button_F2, "0-283" );
00046 KeyMappingWithCode( button_F3, "0-284" );
00047
00048 const MString sPromptedInput = "PromptedInput";
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 ScreenMapEditor::~ScreenMapEditor()
00095 {
00096 DISPLAY->RemoveLight(&m_light);
00097 }
00098
00099 void ScreenMapEditor::Init()
00100 {
00101 MercuryScreen::Init();
00102 MercurySprite* background = new MercurySprite;
00103 m_pBackground = background;
00104 background->SetName(m_name + " background");
00105 background->Init();
00106 background->LoadImage( THEME.GetMetricS( m_name, "background" ));
00107 background->MoveX(320);
00108 background->MoveY(240);
00109
00110
00111 INPUTMAN->GetCursorPosition( m_iOldMouseX, m_iOldMouseY );
00112
00113 m_fODEables.SetName( "MapEditor_ODEables" );
00114 m_fODEables.Init();
00115
00116 AddPerspObject( &m_fODEables );
00117
00118 m_fVisibles.SetName( "MapEditor_Visibles" );
00119 m_fVisibles.Init();
00120
00121 AddPerspObject( &m_fVisibles );
00122
00123 m_pCameraPos.SetX(-100);
00124 m_qCamera.w = 1;
00125
00126 m_bShowingElems = false;
00127
00128 m_fOverlays.SetName( "ScreenMapEditorOverlays" );
00129 m_fOverlays.Init();
00130 AddOrthoObject( &m_fOverlays );
00131
00132 m_pOverlay.SetName( "ObjectControlPane" );
00133 m_pOverlay.Init();
00134 m_fOverlays.AddObject( &m_pOverlay );
00135
00136 m_pPrompt.SetName( "EditorTextPrompt" );
00137 m_pPrompt.Init();
00138 m_fOverlays.AddObject( &m_pPrompt );
00139
00140 m_tMessage.SetName( "TextMessage" );
00141 m_tMessage.Init();
00142 m_tMessage.SetFont( THEME.GetMetricS( GetName(), "Font" ) );
00143 m_tMessage.Tweening.AddCommand( THEME.GetMetricS( GetName(), "TextMessageActiveCommand" ), MercuryTweenState::LOCAL, "ActiveCommand" );
00144 m_fOverlays.AddObject( &m_tMessage );
00145
00146 m_tElems.SetName( "ListOfKeys" );
00147 m_tElems.Init();
00148 m_fOverlays.AddObject( &m_tElems );
00149
00150 m_oSelectedPart = NULL;
00151 m_iSelectedPart = -1;
00152 m_bObjectLoaded = false;
00153 m_bWorldLoaded = false;
00154
00155 m_pCamera = new MercuryCamera;
00156 m_pCamera->SetName( "Camera" );
00157 m_pCamera->Init();
00158 m_pCamera->SetPosition( MercuryPoint( 500,100,900) );
00159 m_pCamera->SetUp(MercuryPoint(0,0,1));
00160 AddObject( m_pCamera );
00161
00162
00163 m_light.Init();
00164 m_light.SetY(100);
00165 m_light.SetX(-100);
00166 m_light.SetZ(110);
00167 m_light.SetAttenuation(0.001f, Attenuation::LINEAR);
00168 m_light.SetStatic(true);
00169 DISPLAY->AddLight(&m_light);
00170
00171 RegisterMessage( MC_INPUTUNMAPPED, "unmappedinput" );
00172 RegisterMessage( MC_INPUTMAPPED, "mappedinput" );
00173 }
00174
00175 MercuryObject * ScreenMapEditor::GetSelectedHandleODE()
00176 {
00177 if ( SelectedObject() < 0 )
00178 return NULL;
00179 if (m_bWorldLoaded)
00180 {
00181 if (m_vODEObjs[SelectedObject()])
00182 return m_vODEObjs[SelectedObject()];
00183 }
00184 else if(m_bObjectLoaded)
00185 {
00186 if(m_vLastODE[SelectedObject()])
00187 return m_vLastODE[SelectedObject()];
00188 }
00189 return NULL;
00190 }
00191
00192 MercuryObject * ScreenMapEditor::GetSelectedHandleVis()
00193 {
00194 if ( SelectedObject() < 0 )
00195 return NULL;
00196 if (m_bWorldLoaded)
00197 {
00198 if (m_vVisObjs[SelectedObject()])
00199 return m_vVisObjs[SelectedObject()];
00200 }
00201 else if(m_bObjectLoaded)
00202 {
00203 if(m_vLastVis[SelectedObject()])
00204 return m_vLastVis[SelectedObject()];
00205 }
00206 return NULL;
00207 }
00208
00209 void ScreenMapEditor::Update( const float dTime )
00210 {
00211
00212 int cX, cY;
00213 INPUTMAN->GetCursorPosition( cX, cY );
00214 int dX = cX - m_iOldMouseX;
00215 int dY = cY - m_iOldMouseY;
00216 m_iOldMouseX = cX;
00217 m_iOldMouseY = cY;
00218
00219 if ( m_pPrompt.m_bPromptingForText )
00220 {
00221 m_pPrompt.Update( dTime );
00222 return;
00223 }
00224
00225 if ( m_oSelectedPart )
00226 m_oSelectedPart->SetDiffuse( MercuryColor( 0.0f,1.0f,0.0f,0.5f ) );
00227
00228
00229
00230
00231 float qX = 0;
00232 float qY = 0;
00233
00234
00235 if ( INPUTMAN->IsButtonDown( button_up ) )
00236 qY++;
00237 if ( INPUTMAN->IsButtonDown( button_down ) )
00238 qY--;
00239 if ( INPUTMAN->IsButtonDown( button_left ) )
00240 qX++;
00241 if ( INPUTMAN->IsButtonDown( button_right ) )
00242 qX--;
00243
00244 float AngleToGo=m_pCameraRot.x;
00245
00246
00247
00248 m_pCameraPos.x += (COS(AngleToGo+(3.141592653589f/2))*qX + COS(AngleToGo)*qY);
00249 m_pCameraPos.y += (SIN(AngleToGo+(3.141592653589f/2))*qX + SIN(AngleToGo)*qY);
00250
00251 if ( INPUTMAN->IsButtonDown( button_c ) )
00252 m_pCameraPos.z--;
00253 if ( INPUTMAN->IsButtonDown( button_d ) )
00254 m_pCameraPos.z++;
00255
00256 if ( INPUTMAN->IsButtonDown( button_mouse1 ) )
00257 {
00258 if ( SelectedObject() >= 0 && ( m_bObjectLoaded || m_bWorldLoaded ) )
00259 {
00260 float dx = 0, dy = 0, dz = 0;
00261 if ( INPUTMAN->IsButtonDown( button_F3 ) )
00262 dz += dY;
00263 else if ( INPUTMAN->IsButtonDown( button_F1 ) )
00264 dx += dY;
00265 else if ( INPUTMAN->IsButtonDown( button_F2 ) )
00266 dy += dY;
00267 else
00268 {
00269
00270
00271
00272 dx = -(COS(m_pCameraRot.x+(3.141592653589f/2))*dX + COS(m_pCameraRot.x)*dY);
00273 dy = -(SIN(m_pCameraRot.x+(3.141592653589f/2))*dX + SIN(m_pCameraRot.x)*dY);
00274 }
00275 float x,y,z;
00276 if ( INPUTMAN->IsButtonDown( button_ctrl ) )
00277 {
00278 float magnitude = 0.25;
00279 x = m_iTightFile.GetValueF( m_sEditingName, ssprintf( "Piece%dRotX", SelectedObject() + 1 ) ) + (dx * magnitude);
00280 y = m_iTightFile.GetValueF( m_sEditingName, ssprintf( "Piece%dRotY", SelectedObject() + 1 ) ) + (dy * magnitude);
00281 z = m_iTightFile.GetValueF( m_sEditingName, ssprintf( "Piece%dRotZ", SelectedObject() + 1 ) ) + (dz * magnitude);
00282 if ( x < 0 ) x = 360;
00283 if ( x > 360 ) x = 0;
00284 if ( y < 0 ) y = 360;
00285 if ( y > 360 ) y = 0;
00286 if ( z < 0 ) z = 360;
00287 if ( z > 360 ) z = 0;
00288 SetIni( m_sEditingName, ssprintf( "Piece%dRotX", SelectedObject() + 1 ), ssprintf( "%f", x ) );
00289 SetIni( m_sEditingName, ssprintf( "Piece%dRotY", SelectedObject() + 1 ), ssprintf( "%f", y ) );
00290 SetIni( m_sEditingName, ssprintf( "Piece%dRotZ", SelectedObject() + 1 ), ssprintf( "%f", z ) );
00291 if ( GetSelectedHandleVis() ) GetSelectedHandleVis()->SetRot(MercuryPoint(x, y, z));
00292 if ( GetSelectedHandleODE() ) GetSelectedHandleODE()->SetRot(MercuryPoint(x, y, z));
00293 }
00294 else
00295 {
00296 float magnitude = CameraDistance()/100;
00297 x = m_iTightFile.GetValueF( m_sEditingName, ssprintf( "Piece%dX", SelectedObject() + 1 ) ) + (dx * magnitude);
00298 y = m_iTightFile.GetValueF( m_sEditingName, ssprintf( "Piece%dY", SelectedObject() + 1 ) ) + (dy * magnitude);
00299 z = m_iTightFile.GetValueF( m_sEditingName, ssprintf( "Piece%dZ", SelectedObject() + 1 ) ) + (dz * magnitude);
00300 SetIni( m_sEditingName, ssprintf( "Piece%dX", SelectedObject() + 1 ), ssprintf( "%f", x ) );
00301 SetIni( m_sEditingName, ssprintf( "Piece%dY", SelectedObject() + 1 ), ssprintf( "%f", y ) );
00302 SetIni( m_sEditingName, ssprintf( "Piece%dZ", SelectedObject() + 1 ), ssprintf( "%f", z ) );
00303 if ( GetSelectedHandleVis() ) GetSelectedHandleVis()->SetPosition(MercuryPoint(x, y, z));
00304 if ( GetSelectedHandleODE() ) GetSelectedHandleODE()->SetPosition(MercuryPoint(x, y, z));
00305 }
00306 }
00307 }
00308 else
00309 {
00310 m_pCameraRot.x -= float(dX)/100.0f;
00311 m_pCameraRot.y -= float(dY)/100.0f;
00312 m_pCameraRot.y = Clamp( m_pCameraRot.y, -1.57f,1.57f );
00313 }
00314
00315 MercuryScreen::Update( dTime );
00316 }
00317
00318 void ScreenMapEditor::Render()
00319 {
00320 MercuryPoint pAt;
00321
00322 pAt.z = SIN(m_pCameraRot.y);
00323 float fProdA = (pAt.z*pAt.z);
00324 pAt.x = COS(m_pCameraRot.x) * SQRT(1-fProdA);
00325 pAt.y = SIN(m_pCameraRot.x) * SQRT(1-fProdA);
00326
00327 MercuryPoint pUp = MercuryPoint( -COS(m_pCameraRot.x)*pAt.z,-SIN(m_pCameraRot.x)*pAt.z, SQRT(1-fProdA) );
00328
00329 m_pCamera->SetPosition( m_pCameraPos );
00330 m_pCamera->SetTarget( m_pCameraPos + pAt );
00331 m_pCamera->SetUp( pUp );
00332 MercuryScreen::Render();
00333 }
00334
00335 void ScreenMapEditor::LoadFile( const MString & sFilename )
00336 {
00337 if ( !m_iWorldFile.Open( THEME.GetPathToFile( sFilename ), true, true ) || !m_iTightFile.Open( THEME.GetPathToFile( sFilename ), false, true ) )
00338 {
00339 NotifyMessage( "Failed to load file." );
00340 return;
00341 }
00342
00343 m_bFileLoaded = true;
00344 m_bWorldLoaded = false;
00345 m_bObjectLoaded = false;
00346 m_sFilename = sFilename;
00347
00348 MVector< MString > vsKeys;
00349 m_iTightFile.EnumerateKeys( vsKeys );
00350 m_tElems.SetupList( vsKeys );
00351
00352 ClearOutArea();
00353
00354 NotifyMessage( "Loaded file." );
00355 }
00356
00357 void ScreenMapEditor::LoadWorld( const MString & sWorldname )
00358 {
00359 MString sTmp;
00360 if ( !m_iTightFile.GetValue( sWorldname, "Gravity", sTmp ) )
00361 {
00362 NotifyMessage( "\"" + sWorldname + "\" does not describe a world." );
00363 return;
00364 }
00365
00366 ClearOutArea();
00367 for ( unsigned i = 0; i < (unsigned int)m_iTightFile.GetValueI( sWorldname, "NumElements", 0 ); i++ )
00368 {
00369 MakeWorldPiece( i, sWorldname );
00370 }
00371
00372 m_sEditingName = sWorldname;
00373 m_bWorldLoaded = true;
00374 m_bObjectLoaded = false;
00375 NotifyMessage( "Loaded World." );
00376 }
00377
00378 void ScreenMapEditor::MakeWorldPiece( int i, const MString & sWorldname, int iTempSelect )
00379 {
00380 MString sPieceName = ssprintf( "Piece%d", i+1 );
00381 int iObjNum = GenerateObject( m_iTightFile.GetValueS( sWorldname, sPieceName ), iTempSelect );
00382 if ( iTempSelect >= 0 )
00383 iObjNum = iTempSelect;
00384 MercuryObject * oODE = m_vODEObjs[iObjNum];
00385 MercuryObject * oVis = m_vVisObjs[iObjNum];
00386
00387 float fX = m_iTightFile.GetValueF( sWorldname, sPieceName+"X" );
00388 float fY = m_iTightFile.GetValueF( sWorldname, sPieceName+"Y" );
00389 float fZ = m_iTightFile.GetValueF( sWorldname, sPieceName+"Z" );
00390 float fRX = m_iTightFile.GetValueF( sWorldname, sPieceName+"RotX" );
00391 float fRY = m_iTightFile.GetValueF( sWorldname, sPieceName+"RotY" );
00392 float fRZ = m_iTightFile.GetValueF( sWorldname, sPieceName+"RotZ" );
00393 if ( oODE )
00394 {
00395 oODE->SetPosition( MercuryPoint( fX, fY, fZ ) );
00396 oODE->SetRot( MercuryPoint( fRX, fRY, fRZ ) );
00397 }
00398 if ( oVis )
00399 {
00400 oVis->SetPosition( MercuryPoint( fX, fY, fZ ) );
00401 oVis->SetRot( MercuryPoint( fRX, fRY, fRZ ) );
00402 }
00403 }
00404
00405 void ScreenMapEditor::LoadObject( const MString & sObjectname )
00406 {
00407 MString sTmp;
00408 if ( m_iTightFile.GetValue( sObjectname, "Gravity", sTmp ) )
00409 {
00410 NotifyMessage( "\"" + sObjectname + "\" is already a world!" );
00411 return;
00412 }
00413
00414 ClearOutArea();
00415 int iObjNum = GenerateObject( sObjectname );
00416
00417 if ( iObjNum == -1 )
00418 {
00419 SetIni( sObjectname, "NumPieces", "0" );
00420 ClearOutArea();
00421 int iRetry = GenerateObject( sObjectname );
00422 if ( iRetry == -1 )
00423 {
00424 NotifyMessage( "Object Creation Failed." );
00425 return;
00426 }
00427 m_sEditingName = sObjectname;
00428 m_bWorldLoaded = false;
00429 m_bObjectLoaded = true;
00430 NotifyMessage( "Object Created" );
00431 }
00432 else
00433 {
00434 m_sEditingName = sObjectname;
00435 m_bWorldLoaded = false;
00436 m_bObjectLoaded = true;
00437 NotifyMessage( "Object Loaded." );
00438 }
00439 }
00440
00441 void ScreenMapEditor::NotifyMessage( const MString & sMessage )
00442 {
00443 m_tMessage.SetText( sMessage );
00444 m_tMessage.Tweening.StopTweening();
00445 m_tMessage.Tweening.ExecuteCommand( "ActiveCommand", PStack() );
00446 }
00447
00448 int ScreenMapEditor::GenerateObject( MString sObjectIn, int iPieceToReplace )
00449 {
00450 unsigned int iPieces = m_iWorldFile.GetValueI( sObjectIn, "NumPieces", 0, true );
00451
00452 if ( iPieceToReplace != -1 )
00453 {
00454 m_fODEables.RemoveObject( m_vODEObjs[iPieceToReplace] );
00455 m_fVisibles.RemoveObject( m_vVisObjs[iPieceToReplace] );
00456 }
00457
00458 m_vLastODE.resize( iPieces );
00459 m_vLastVis.resize( iPieces );
00460
00461 MercuryObject * pODEObj = NULL;
00462 MercuryObject * pVisObj = NULL;
00463
00464 for ( unsigned i = 0; i < iPieces; i++ )
00465 {
00466 m_vLastODE[i] = NULL;
00467 m_vLastVis[i] = NULL;
00468
00469 MString sPName = ssprintf( "Piece%d", i+1 );
00470 int iType = m_iWorldFile.GetValueI( sObjectIn, sPName + "Type", -1 );
00471 if ( iType < 0 )
00472 {
00473 NotifyMessage( ssprintf( "Could not load piece #%d of object '%s'.", i, sObjectIn.c_str() ) );
00474 continue;
00475 }
00476
00477
00478 MString sFilename = m_iWorldFile.GetValueS( sObjectIn, sPName + "Filename" );
00479 bool bUsesODE = m_iWorldFile.GetValueB( sObjectIn, sPName + "UsesODE" );
00480 bool bVisible = m_iWorldFile.GetValueB( sObjectIn, sPName + "Visible" );
00481
00482
00483
00484 float fX = m_iWorldFile.GetValueF( sObjectIn, sPName + "X" );
00485 float fY = m_iWorldFile.GetValueF( sObjectIn, sPName + "Y" );
00486 float fZ = m_iWorldFile.GetValueF( sObjectIn, sPName + "Z" );
00487
00488 float fRotX = m_iWorldFile.GetValueF( sObjectIn, sPName + "RotX" );
00489 float fRotY = m_iWorldFile.GetValueF( sObjectIn, sPName + "RotY" );
00490 float fRotZ = m_iWorldFile.GetValueF( sObjectIn, sPName + "RotZ" );
00491
00492 if ( !bUsesODE && !bVisible )
00493 continue;
00494
00495
00496 for ( unsigned j = 0; j < ((bVisible&&bUsesODE)?2:1); j++ )
00497 {
00498 MercuryObject * co = NULL;
00499
00500
00501
00502 switch ( iType )
00503 {
00504 case 0:
00505 {
00506 MercuryShape * s = new MercuryShape;
00507 s->SetName( sObjectIn + sPName );
00508 s->Init();
00509
00510 s->MakeSphere( m_iWorldFile.GetValueI( sObjectIn, sPName + "Stacks", 6 ),
00511 m_iWorldFile.GetValueI( sObjectIn, sPName + "Slices", 12 ) );
00512
00513
00514 s->LoadImage( THEME.GetPathToGraphic( sFilename ) );
00515
00516
00517 float fRadius = m_iWorldFile.GetValueF( sObjectIn, sPName + "Radius", 1 );
00518 s->SetScale( MercuryPoint( fRadius, fRadius, fRadius ) );
00519
00520
00521 co = s;
00522 break;
00523 }
00524 case 1:
00525 {
00526
00527 MercuryShape * s = new MercuryShape;
00528 s->SetName( sPName + sObjectIn );
00529 s->Init();
00530 s->MakeCylinder(m_iWorldFile.GetValueI( sObjectIn, sPName + "Stacks", 6 ),
00531 m_iWorldFile.GetValueI( sObjectIn, sPName + "Slices", 12 ) );
00532 s->LoadImage( THEME.GetPathToGraphic( sFilename ) );
00533 float fRadius = m_iWorldFile.GetValueF( sObjectIn, sPName + "Radius", 1 );
00534 float fLength = m_iWorldFile.GetValueF( sObjectIn, sPName + "Length", 1 );
00535 s->SetScale( MercuryPoint( fRadius, fRadius, fLength ) );
00536 co = s;
00537 break;
00538 }
00539 case 2:
00540 {
00541
00542 MercuryShape * s = new MercuryShape;
00543 s->SetName( sPName + sObjectIn );
00544 s->Init();
00545 s->MakeBox( );
00546 s->LoadImage( THEME.GetPathToGraphic( sFilename ) );
00547 s->SetScaleX( m_iWorldFile.GetValueF( sObjectIn, sPName + "LengthX", 1 ) );
00548 s->SetScaleY( m_iWorldFile.GetValueF( sObjectIn, sPName + "LengthY", 1 ) );
00549 s->SetScaleZ( m_iWorldFile.GetValueF( sObjectIn, sPName + "LengthZ", 1 ) );
00550 co = s;
00551 break;
00552 }
00553 case 3:
00554 {
00555
00556 MercuryLoadableModel * s = new MercuryLoadableModel();
00557 s->SetName( sPName + sObjectIn );
00558 s->Init();
00559 s->Load( THEME.GetPathToModel( sFilename ) );
00560 s->SetScaleX( m_iWorldFile.GetValueF( sObjectIn, sPName + "LengthX", 1 ) );
00561 s->SetScaleY( m_iWorldFile.GetValueF( sObjectIn, sPName + "LengthY", 1 ) );
00562 s->SetScaleZ( m_iWorldFile.GetValueF( sObjectIn, sPName + "LengthZ", 1 ) );
00563 co = s;
00564 break;
00565 }
00566 };
00567
00568 if ( !co )
00569 {
00570 NotifyMessage( "Warning: Could not load ["+sObjectIn+"]:"+sPName );
00571 continue;
00572 }
00573 co->SetX(fX);
00574 co->SetY(fY);
00575 co->SetZ(fZ);
00576 co->SetRotX(fRotX);
00577 co->SetRotY(fRotY);
00578 co->SetRotZ(fRotZ);
00579
00580 if ( bUsesODE && ( j == 0 ) )
00581 {
00582
00583 if ( !pODEObj )
00584 pODEObj = new MercuryObject;
00585 pODEObj->SetName( "AddedODE" );
00586 pODEObj->Init();
00587 pODEObj->AddObject( co, true );
00588 m_vLastODE[i] = co;
00589 }
00590 else
00591 {
00592
00593 if ( !pVisObj )
00594 pVisObj = new MercuryObject;
00595 pVisObj->SetName( "AddedVisible" );
00596 pVisObj->Init();
00597 pVisObj->AddObject( co, true );
00598 m_vLastVis[i] = co;
00599 }
00600 }
00601 }
00602
00603 if ( iPieceToReplace == -1 )
00604 {
00605 m_vODEObjs.push_back( pODEObj );
00606 m_vVisObjs.push_back( pVisObj );
00607 } else {
00608 m_vODEObjs[iPieceToReplace] = pODEObj;
00609 m_vVisObjs[iPieceToReplace] = pVisObj;
00610 }
00611
00612 if ( pODEObj )
00613 m_fODEables.AddObject( pODEObj, true );
00614
00615 if ( pVisObj )
00616 m_fVisibles.AddObject( pVisObj, true );
00617
00618 return m_vODEObjs.size()-1;
00619 }
00620
00621 float ScreenMapEditor::CameraDistance()
00622 {
00623 MercuryPoint pObject;
00624 if ( GetSelectedHandleVis() ) pObject = GetSelectedHandleVis()->GetPosition();
00625 if ( GetSelectedHandleODE() ) pObject = GetSelectedHandleODE()->GetPosition();
00626
00627 pObject = m_pCameraPos - pObject;
00628 return pObject.Magnitude();
00629 }
00630
00631 void ScreenMapEditor::ClearOutArea()
00632 {
00633 unsigned i;
00634 for ( i = 0; i < m_vODEObjs.size(); i++ )
00635 m_fODEables.RemoveObject( m_vODEObjs[i] );
00636
00637 m_vODEObjs.resize(0);
00638
00639 for ( i = 0; i < m_vVisObjs.size(); i++ )
00640 m_fVisibles.RemoveObject( m_vVisObjs[i] );
00641
00642 m_vVisObjs.resize(0);
00643
00644 m_pOverlay.SetObject( NULL, 0, 0 );
00645 m_oSelectedPart = NULL;
00646 }
00647
00648 void ScreenMapEditor::Message( int Message, PStack & data, const MString &name )
00649 {
00650 MercuryScreen::Message( Message, data, name );
00651
00652 if ( m_pPrompt.m_bPromptingForText )
00653 {
00654 m_pPrompt.Message( Message, data, name );
00655 return;
00656 }
00657
00658 switch ( Message )
00659 {
00660 case MC_INPUTMAPPED:
00661 case MC_INPUTUNMAPPED:
00662 if ( data.PeekItem( 0 ).GetValueI() != 0 )
00663 break;
00664 if ( data.PeekItem( 2 ).GetValueI() == IET_RELEASE )
00665 break;
00666 switch ( data.PeekItem( 1 ).GetValueI() )
00667 {
00668 case 'b':
00669 if ( m_bWorldLoaded )
00670 if ( SelectedObject() >= 0 && SelectedObject() < (int)m_vODEObjs.size() )
00671 {
00672 MString sPName = ssprintf( "Piece%dBodied", SelectedObject()+1 );
00673 bool bDidHaveBody = m_iTightFile.GetValueB( m_sEditingName, sPName );
00674
00675 SetIni( m_sEditingName, sPName, ssprintf( "%d", !bDidHaveBody ) );
00676 SelectObject( SelectedObject() );
00677 }
00678 else
00679 NotifyMessage( "No piece selected." );
00680 else
00681 NotifyMessage( "No World loaded." );
00682 break;
00683 case 'e':
00684 if ( m_bObjectLoaded )
00685 m_pPrompt.PromptForText( MC_RESPDensity, this, "Enter Object Density", m_iTightFile.GetValueS( m_sEditingName, ssprintf( "Piece%dDensity", SelectedObject()+1 ) ), true );
00686 else
00687 NotifyMessage( "No object loaded." );
00688 break;
00689 case 'f':
00690 if ( m_bObjectLoaded )
00691 m_pPrompt.PromptForText( MC_RESPFilename2, this, "Enter Object Filename", m_iTightFile.GetValueS( m_sEditingName, ssprintf( "Piece%dFilename", SelectedObject()+1 ) ), true );
00692 else
00693 NotifyMessage( "No object loaded." );
00694 break;
00695 case 'g':
00696 m_pPrompt.PromptForText( MC_RESPJumpToSel, this, "Enter Object # to jump to.", ssprintf("%d",SelectedObject()), true );
00697 break;
00698 case 'i':
00699
00700 if ( !m_bFileLoaded )
00701 NotifyMessage( "You must first load a file." );
00702 else
00703 {
00704 m_bShowingElems = !m_bShowingElems;
00705 if ( m_bShowingElems )
00706 {
00707 m_tElems.Tweening.FinishTweening();
00708 m_tElems.Show();
00709 }
00710 else
00711 {
00712 m_tElems.Tweening.FinishTweening();
00713 m_tElems.Hide();
00714 }
00715 }
00716 break;
00717 case 'j':
00718 if ( m_bObjectLoaded )
00719 m_pPrompt.PromptForText( MC_RESPLength, this, "Enter Object Length", m_iTightFile.GetValueS( m_sEditingName, ssprintf( "Piece%dLength", SelectedObject()+1 ) ) );
00720 else
00721 NotifyMessage( "No object loaded." );
00722 break;
00723 case 'k':
00724 if ( m_bObjectLoaded )
00725 if ( m_iTightFile.GetValueI( m_sEditingName, ssprintf( "Piece%iType", SelectedObject() + 1 ) ) < 2 )
00726 m_pPrompt.PromptForText( MC_RESPRadius, this, "Enter Object Radius", m_iTightFile.GetValueS( m_sEditingName, ssprintf( "Piece%dRadius", SelectedObject()+1 ) ), true );
00727 else
00728 {
00729 MString sPName = ssprintf( "Piece%iLength", SelectedObject() + 1 );
00730 MString sInitial = m_iTightFile.GetValueS( m_sEditingName, sPName + "X" ) + "," +
00731 m_iTightFile.GetValueS( m_sEditingName, sPName + "Y" ) + "," +
00732 m_iTightFile.GetValueS( m_sEditingName, sPName + "Z" );
00733 m_pPrompt.PromptForText( MC_RESPScale, this, "Enter Object Scale x,y,z", sInitial, true );
00734 }
00735 else
00736 NotifyMessage( "No object loaded." );
00737 break;
00738 case 'l':
00739 m_pPrompt.PromptForText( MC_RESPFilename, this, "Enter Filename to Load", "myworld.ini", true );
00740 break;
00741 case 'n':
00742 if ( m_bWorldLoaded )
00743 m_pPrompt.PromptForText( MC_NewObjectName, this, "Enter new type for object.", "", true );
00744 else if ( m_bObjectLoaded )
00745 {
00746 MercuryShape * c = new MercuryShape;
00747 c->SetName( m_sEditingName+ssprintf("AddedObj%d",m_vLastODE.size()+2) );
00748 c->MakeSphere();
00749 m_vLastODE.push_back( NULL );
00750 m_vLastVis.push_back( c );
00751
00752 if ( m_vVisObjs.size() < 1 )
00753 m_vVisObjs.resize( 1 );
00754 if ( !m_vVisObjs[0] )
00755 m_vVisObjs[0] = new MercuryObject;
00756
00757 m_vVisObjs[0]->AddObject( c, true );
00758
00759 SelectObject( m_vLastVis.size() - 1 );
00760
00761 SetIni( m_sEditingName, ssprintf( "Piece%dType", m_vLastODE.size() ), "0" );
00762 SetIni( m_sEditingName, ssprintf( "Piece%dVisible", m_vLastODE.size() ), "1" );
00763 SetIni( m_sEditingName, ssprintf( "Piece%dUsesODE", m_vLastODE.size() ), "0" );
00764 SetIni( m_sEditingName, "NumPieces", ssprintf( "%ld", m_iTightFile.GetValueI( m_sEditingName, "NumPieces" ) + 1 ) );
00765 NotifyMessage( "Piece Created." );
00766 }
00767 else
00768 NotifyMessage( "You must already have an object or world loaded to do this." );
00769 break;
00770 case 'o':
00771 if ( !m_bFileLoaded )
00772 NotifyMessage( "You must first load a file." );
00773 else
00774 m_pPrompt.PromptForText( MC_RESPObjectname, this, "Enter Object to Load/Create.", "", true );
00775 break;
00776 case 'r':
00777 m_pCameraRot = MercuryPoint( 0, 0, 0 );
00778 m_pCameraPos = MercuryPoint( -100, 0, 0);
00779 NotifyMessage( "Camera Reset." );
00780 break;
00781 case 's':
00782 if ( m_iTightFile.Save() )
00783 NotifyMessage( "Save Successful." );
00784 else
00785 NotifyMessage( "Save Failed." );
00786 break;
00787 case 't':
00788 if ( m_bObjectLoaded )
00789 m_pPrompt.PromptForText( MC_RESPType, this, "Enter Type Number (0:Sphere, 1:Cylinder, 2:Box, 3:Model)", m_iTightFile.GetValueS( m_sEditingName, ssprintf( "Piece%dType", SelectedObject()+1 ) ) );
00790 else
00791 NotifyMessage( "No object loaded." );
00792 break;
00793 case 'u':
00794 if ( m_bObjectLoaded )
00795 if ( SelectedObject() >= 0 && SelectedObject() < (int)m_vLastODE.size() )
00796 {
00797 MString sPName = ssprintf( "Piece%dUsesODE", SelectedObject()+1 );
00798 bool bDidUseODE = m_iTightFile.GetValueB( m_sEditingName, sPName );
00799 if ( !m_vLastVis[SelectedObject()] && bDidUseODE )
00800 {
00801 NotifyMessage( "An object must be visible and/or be ODEized" );
00802 break;
00803 }
00804
00805 SetIni( m_sEditingName, sPName, ssprintf( "%d", !bDidUseODE ) );
00806 if ( bDidUseODE )
00807 m_vLastODE[SelectedObject()] = NULL;
00808 else
00809 m_vLastODE[SelectedObject()] = m_vLastVis[SelectedObject()];
00810 SelectObject( SelectedObject() );
00811 }
00812 else
00813 NotifyMessage( "No piece selected." );
00814 else
00815 NotifyMessage( "No object loaded." );
00816 break;
00817 case 'v':
00818 if ( m_bObjectLoaded )
00819 {
00820 if ( SelectedObject() >= 0 && SelectedObject() < (int)m_vLastODE.size() )
00821 {
00822 MString sPName = ssprintf( "Piece%dVisible", SelectedObject()+1 );
00823 bool bWasVisible = m_iTightFile.GetValueB( m_sEditingName, sPName );
00824 if ( !m_vLastODE[SelectedObject()] && bWasVisible )
00825 {
00826 NotifyMessage( "An object must be visible and/or be ODEized" );
00827 break;
00828 }
00829
00830 SetIni( m_sEditingName, sPName, ssprintf( "%d", !bWasVisible ) );
00831 if ( bWasVisible )
00832 m_vLastVis[SelectedObject()] = NULL;
00833 else
00834 m_vLastVis[SelectedObject()] = m_vLastODE[SelectedObject()];
00835 SelectObject( SelectedObject() );
00836 }
00837 else
00838 NotifyMessage( "No piece selected." );
00839 }
00840 else if ( m_bWorldLoaded )
00841 {
00842 m_pPrompt.PromptForText( MC_RESPSetGravity, this, "Enter Gravity.", m_iTightFile.GetValueS( m_sEditingName, "Gravity" ), true );
00843 } else
00844 NotifyMessage( "You must either have a world or object loaded." );
00845 break;
00846 case 'w':
00847 if ( !m_bFileLoaded )
00848 NotifyMessage( "You must first load a world." );
00849 else
00850 m_pPrompt.PromptForText( MC_RESPWorldname, this, "Enter World to Load", "", true );
00851 break;
00852 case 127:
00853 {
00854 if ( SelectedObject() < 0 )
00855 {
00856 NotifyMessage( "No object selected.");
00857 return;
00858 }
00859 if ( (!m_bObjectLoaded) && (!m_bWorldLoaded) )
00860 {
00861 NotifyMessage( "No Object or World loaded." );
00862 return;
00863 }
00864
00865 map< MString, MString > values;
00866 m_iTightFile.EnumerateValues( m_sEditingName, values );
00867 int iNumInFile = 0;
00868
00869 if ( m_bWorldLoaded )
00870 iNumInFile = m_vODEObjs.size();
00871 else if ( m_bObjectLoaded )
00872 iNumInFile = m_vLastODE.size();
00873
00874 for ( int i = SelectedObject(); i < iNumInFile; i++ )
00875 {
00876 MString sPrefix = ssprintf( "Piece%d", i+1 );
00877 map< MString, MString >::iterator t = values.begin();
00878
00879 while ( t != values.end() )
00880 {
00881 MString cur = t->first;
00882 if ( cur.substr( 0, sPrefix.length() ).compare( sPrefix ) == 0 )
00883 {
00884 m_iTightFile.RemoveValue( m_sEditingName, (t->first) );
00885 m_iWorldFile.RemoveValue( m_sEditingName, (t->first) );
00886 }
00887 t++;
00888 }
00889
00890 t = values.begin();
00891 MString sPrefix2 = ssprintf( "Piece%d", i+2 );
00892
00893 while ( t != values.end() )
00894 {
00895 if ( ((t->first).substr( 0, sPrefix2.length() )).compare( sPrefix2 ) == 0 )
00896 {
00897 MString sOnS = (t->first).substr( sPrefix2.length() );
00898 SetIni( m_sEditingName, sPrefix + sOnS, t->second );
00899 }
00900 t++;
00901 }
00902 }
00903
00904 if ( m_bWorldLoaded )
00905 {
00906 SetIni( m_sEditingName, "NumElements", ssprintf( "%d", m_vODEObjs.size() - 1 ) );
00907 if ( m_vODEObjs[SelectedObject()] )
00908 m_fODEables.RemoveObject( m_vODEObjs[SelectedObject()] );
00909 if ( m_vVisObjs[SelectedObject()] )
00910 m_fVisibles.RemoveObject( m_vVisObjs[SelectedObject()] );
00911 m_vODEObjs.erase( m_vODEObjs.begin() + SelectedObject() );
00912 m_vVisObjs.erase( m_vVisObjs.begin() + SelectedObject() );
00913 }
00914 else if ( m_bObjectLoaded )
00915 {
00916 SetIni( m_sEditingName, "NumPieces", ssprintf( "%d", m_vLastODE.size() - 1 ) );
00917 RewriteCurrent();
00918 }
00919 }
00920 case 278:
00921 SelectObject( 0 );
00922 break;
00923 case 279:
00924 SelectObject( GetNumObjects() - 1 );
00925 break;
00926 case 280:
00927 if ( SelectedObject() > 0 )
00928 SelectObject( SelectedObject() - 1 );
00929 break;
00930 case 281:
00931 if ( SelectedObject() < ( GetNumObjects() - 1 ) )
00932 SelectObject( SelectedObject() + 1 );
00933 break;
00934 case 8:
00935 SelectObject();
00936 break;
00937 };
00938 break;
00939 case MC_RESPFilename:
00940 if ( data.PeekItem( 1 ).GetValueI() )
00941 LoadFile( data.PeekItem( 0 ).GetValueS() );
00942 break;
00943 case MC_RESPWorldname:
00944 if ( data.PeekItem( 1 ).GetValueI() )
00945 LoadWorld( data.PeekItem( 0 ).GetValueS() );
00946 break;
00947 case MC_RESPObjectname:
00948 if ( data.PeekItem( 1 ).GetValueI() )
00949 LoadObject( data.PeekItem( 0 ).GetValueS() );
00950 break;
00951 case MC_RESPJumpToSel:
00952 if ( data.PeekItem( 1 ).GetValueI() )
00953 SelectObject(( data.PeekItem( 0 ).GetValueI() ));
00954 break;
00955 case MC_RESPSetGravity:
00956 if ( data.PeekItem( 1 ).GetValueI() )
00957 SetIni( m_sEditingName, "Gravity", data.PeekItem( 0 ).GetValueS() );
00958 break;
00959 case MC_RESPFilename2:
00960 if ( data.PeekItem( 1 ).GetValueI() )
00961 {
00962 SetIni( m_sEditingName, ssprintf( "Piece%dFilename", SelectedObject()+1 ), data.PeekItem( 0 ).GetValueS() );
00963 RewriteCurrent();
00964 }
00965 break;
00966 case MC_RESPDensity:
00967 if ( data.PeekItem( 1 ).GetValueI() )
00968 SetIni( m_sEditingName, ssprintf( "Piece%dDensity", SelectedObject()+1 ), data.PeekItem( 0 ).GetValueS() );
00969 break;
00970 case MC_RESPType:
00971 if ( data.PeekItem( 1 ).GetValueI() )
00972 {
00973 SetIni( m_sEditingName, ssprintf( "Piece%dType", SelectedObject()+1 ), data.PeekItem( 0 ).GetValueS() );
00974 RewriteCurrent();
00975 }
00976 break;
00977 case MC_RESPLength:
00978 if ( data.PeekItem( 1 ).GetValueI() )
00979 {
00980 SetIni( m_sEditingName, ssprintf( "Piece%dLength", SelectedObject()+1 ), data.PeekItem( 0 ).GetValueS() );
00981 RewriteCurrent();
00982 }
00983 break;
00984 case MC_RESPRadius:
00985 if ( data.PeekItem( 1 ).GetValueI() )
00986 {
00987 SetIni( m_sEditingName, ssprintf( "Piece%dRadius", SelectedObject()+1 ), data.PeekItem( 0 ).GetValueS() );
00988 RewriteCurrent();
00989 }
00990 break;
00991 case MC_RESPScale:
00992 if ( data.PeekItem( 1 ).GetValueI() )
00993 {
00994 float x,y,z;
00995 int ret = sscanf( data.PeekItem( 0 ).GetValueS().c_str(), "%f,%f,%f", &x, &y, &z );
00996 if ( ret != 3 )
00997 {
00998 NotifyMessage( "Invalid format." );
00999 break;
01000 }
01001 SetIni( m_sEditingName, ssprintf( "Piece%dLengthX", SelectedObject()+1 ), ssprintf( "%f", x ) );
01002 SetIni( m_sEditingName, ssprintf( "Piece%dLengthY", SelectedObject()+1 ), ssprintf( "%f", y ) );
01003 SetIni( m_sEditingName, ssprintf( "Piece%dLengthZ", SelectedObject()+1 ), ssprintf( "%f", z ) );
01004 RewriteCurrent();
01005 }
01006 break;
01007 case MC_NewObjectName:
01008 if ( data.PeekItem( 1 ).GetValueI() )
01009 {
01010 int ret = GenerateObject( data.PeekItem( 0 ).GetValueS() );
01011 if ( ret < 0 )
01012 break;
01013 SetIni( m_sEditingName, "NumElements", ssprintf( "%ld", m_iTightFile.GetValueI( m_sEditingName, "NumElements" ) + 1 ) );
01014 SetIni( m_sEditingName, ssprintf( "Piece%d", ret+1), data.PeekItem( 0 ).GetValueS() );
01015 SelectObject( ret );
01016 RewriteCurrent();
01017 }
01018 break;
01019 }
01020 }
01021
01022 int ScreenMapEditor::SelectObject( int ObjectNumber )
01023 {
01024 MercuryObject * oOldObject = NULL;
01025 MercuryObject * oNewObject = NULL;
01026 if ( m_bObjectLoaded )
01027 {
01028 if ( m_iSelectedPart >= 0 && m_iSelectedPart < (int)m_vLastODE.size() )
01029 {
01030 if ( m_vLastODE[m_iSelectedPart] != NULL )
01031 oOldObject = m_vLastODE[m_iSelectedPart];
01032 else if ( m_vLastVis[m_iSelectedPart] != NULL )
01033 oOldObject = m_vLastVis[m_iSelectedPart];
01034 }
01035
01036 if ( ObjectNumber >= 0 && ObjectNumber < (int)m_vLastODE.size() )
01037 {
01038 if ( m_vLastODE[ObjectNumber] != NULL )
01039 oNewObject = m_vLastODE[ObjectNumber];
01040 else if ( m_vLastVis[ObjectNumber] != NULL )
01041 oNewObject = m_vLastVis[ObjectNumber];
01042 } else
01043 return -1;
01044 }
01045 else if ( m_bWorldLoaded )
01046 {
01047 if ( m_iSelectedPart >= 0 && m_iSelectedPart < (int)m_vODEObjs.size() )
01048 {
01049 if ( m_vODEObjs[m_iSelectedPart] != NULL )
01050 oOldObject = m_vODEObjs[m_iSelectedPart];
01051 else if ( m_vVisObjs[m_iSelectedPart] != NULL )
01052 oOldObject = m_vVisObjs[m_iSelectedPart];
01053 }
01054
01055 if ( ObjectNumber >= 0 && ObjectNumber < (int)m_vODEObjs.size() )
01056 {
01057 if ( m_vODEObjs[ObjectNumber] != NULL )
01058 oNewObject = m_vODEObjs[ObjectNumber];
01059 else if ( m_vVisObjs[ObjectNumber] != NULL )
01060 oNewObject = m_vVisObjs[ObjectNumber];
01061 } else
01062 return -1;
01063 }
01064 else
01065 {
01066 NotifyMessage( "No World or Object loaded." );
01067 return -1;
01068 }
01069
01070 m_pOverlay.SetObject( oNewObject, 0, 0 );
01071 m_iSelectedPart = ObjectNumber;
01072 m_oSelectedPart = oNewObject;
01073
01074 MString sAttributes = ssprintf( "%d", ObjectNumber );
01075
01076 if ( m_bObjectLoaded )
01077 {
01078 if ( m_iTightFile.GetValueB( m_sEditingName, ssprintf( "Piece%dVisible", ObjectNumber+1 ) ) )
01079 sAttributes += " Visible";
01080 if ( m_iTightFile.GetValueB( m_sEditingName, ssprintf( "Piece%dUsesODE", ObjectNumber+1 ) ) )
01081 sAttributes += " UsesODE";
01082 }
01083
01084 if ( m_bWorldLoaded )
01085 {
01086 if ( m_iTightFile.GetValueB( m_sEditingName, ssprintf( "Piece%dBodied", ObjectNumber+1 ) ) )
01087 sAttributes += " Bodied";
01088 }
01089
01090 m_pOverlay.SetAttributes( sAttributes );
01091
01092 MercuryColor c = MercuryColor( 1.0f,1.0f,1.0f,1.0f );
01093 if ( oOldObject != NULL )
01094 oOldObject->SetDiffuse( c );
01095
01096 if( oNewObject != NULL )
01097 oNewObject->SetDiffuse( MercuryColor( 1,0,0,1 ) );
01098
01099 return m_iSelectedPart;
01100 }
01101
01102 void ScreenMapEditor::SetIni( const MString & key, const MString & value, const MString & data )
01103 {
01104 m_iTightFile.SetValue( key, value, data );
01105 m_iWorldFile.SetValue( key, value, data );
01106 }
01107
01108 void ScreenMapEditor::RewriteCurrent()
01109 {
01110 int iTempSelect = SelectedObject();
01111 if ( m_bWorldLoaded )
01112 {
01113 MakeWorldPiece( iTempSelect, m_sEditingName, iTempSelect );
01114
01115
01116 }
01117 if ( m_bObjectLoaded )
01118 {
01119 ClearOutArea();
01120 GenerateObject( m_sEditingName );
01121 }
01122 SelectObject( iTempSelect );
01123 }
01124
01125 int ScreenMapEditor::GetNumObjects()
01126 {
01127 if (m_bObjectLoaded)
01128 return m_vLastVis.size();
01129 else if(m_bWorldLoaded)
01130 return m_vVisObjs.size();
01131 return -1;
01132 }
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143 void MercuryTextPrompt::Init()
01144 {
01145 MercuryObject::Init();
01146
01147 m_bPromptingForText = false;
01148 m_sTextInOverlay.SetName( "TextInOverlay" );
01149 m_sTextInOverlay.Init();
01150 m_sTextInOverlay.LoadImage( THEME.GetMetricS( GetName(), "TextInOverlay" ) );
01151 m_sTextInOverlay.Tweening.AddCommand( THEME.GetMetricS( GetName(), "OverlaySpriteOnCommand" ), MercuryTweenState::LOCAL, "OnCommand" );
01152 m_sTextInOverlay.Tweening.AddCommand( THEME.GetMetricS( GetName(), "OverlaySpriteOffCommand" ), MercuryTweenState::LOCAL, "OffCommand" );
01153 m_sTextInOverlay.SetHide( true );
01154 AddObject( &m_sTextInOverlay );
01155
01156 m_tTextInOverlayPrompt.SetName( "TextInOverlayPrompt" );
01157 m_tTextInOverlayPrompt.Init();
01158 m_tTextInOverlayPrompt.SetFont( THEME.GetMetricS( GetName(), "Font" ) );
01159 m_tTextInOverlayPrompt.SetHide( true );
01160 m_tTextInOverlayPrompt.Tweening.AddCommand( THEME.GetMetricS( GetName(), "OverlayPromptOnCommand" ), MercuryTweenState::LOCAL, "OnCommand" );
01161 m_tTextInOverlayPrompt.Tweening.AddCommand( THEME.GetMetricS( GetName(), "OverlayPromptOffCommand" ), MercuryTweenState::LOCAL, "OffCommand" );
01162 AddObject( &m_tTextInOverlayPrompt );
01163
01164 m_tTextInOverlayText.SetName( "TextInOverlayText" );
01165 m_tTextInOverlayText.Init();
01166 m_tTextInOverlayText.Tweening.AddCommand( THEME.GetMetricS( GetName(), "OverlayTextOnCommand" ), MercuryTweenState::LOCAL, "OnCommand" );
01167 m_tTextInOverlayText.Tweening.AddCommand( THEME.GetMetricS( GetName(), "OverlayTextOffCommand" ), MercuryTweenState::LOCAL, "OffCommand" );
01168 m_tTextInOverlayText.SetFont( THEME.GetMetricS( GetName(), "Font" ) );
01169 m_tTextInOverlayText.SetHide( true );
01170 AddObject( &m_tTextInOverlayText );
01171 }
01172
01173 void MercuryTextPrompt::Update( const float dTime )
01174 {
01175 m_tTextInOverlayText.SetText( m_sPromptedText );
01176 MercuryObject::Update( dTime );
01177 }
01178
01179 void MercuryTextPrompt::Message( int Message, PStack & data, const MString & name )
01180 {
01181 if ( m_bPromptingForText )
01182 {
01183 switch ( Message )
01184 {
01185 case MC_INPUTMAPPED:
01186 case MC_INPUTUNMAPPED:
01187 if ( data.PeekItem(2).GetValueI() == IET_DOWN && data.PeekItem(0).GetValueI() == 0 )
01188 {
01189 char cPress = data.PeekItem(1).GetValueI();
01190 if ( cPress == 8 && !m_sPromptedText.empty() )
01191 m_sPromptedText = m_sPromptedText.substr( 0, m_sPromptedText.length() - 1 );
01192 else if ( cPress == 27 && m_bAllowCancel )
01193 {
01194 m_bPromptingForText = false;
01195 m_tTextInOverlayPrompt.Tweening.ExecuteCommand( "OffCommand", PStack() );
01196 m_tTextInOverlayText.Tweening.ExecuteCommand( "OffCommand", PStack() );
01197 m_sTextInOverlay.Tweening.ExecuteCommand( "OffCommand", PStack() );
01198 PStack ToSend;
01199 ToSend.PushItem( PSElement( false ) );
01200 ToSend.PushItem( PSElement(m_sPromptedText ) );
01201 m_objNotify->Message( m_iMessageWhenDone, ToSend, sPromptedInput );
01202 }
01203 else
01204 {
01205 cPress = KeyToChar( data.PeekItem(1).GetValueI(), INPUTMAN->IsButtonDown( button_shift ) );
01206 if ( cPress == 10 )
01207 {
01208 m_tTextInOverlayPrompt.Tweening.ExecuteCommand( "OffCommand", PStack() );
01209 m_tTextInOverlayText.Tweening.ExecuteCommand( "OffCommand", PStack() );
01210 m_sTextInOverlay.Tweening.ExecuteCommand( "OffCommand", PStack() );
01211 m_bPromptingForText = false;
01212 PStack ToSend;
01213 ToSend.PushItem( PSElement( true ) );
01214 ToSend.PushItem( PSElement(m_sPromptedText ) );
01215 m_objNotify->Message( m_iMessageWhenDone, ToSend, sPromptedInput );
01216 } else if ( cPress != 0 )
01217 if ( m_bSingleChar )
01218 {
01219 m_tTextInOverlayPrompt.Tweening.ExecuteCommand( "OffCommand", PStack() );
01220 m_tTextInOverlayText.Tweening.ExecuteCommand( "OffCommand", PStack() );
01221 m_sTextInOverlay.Tweening.ExecuteCommand( "OffCommand", PStack() );
01222 m_bPromptingForText = false;
01223 PStack ToSend;
01224 ToSend.PushItem( PSElement( true ) );
01225 ToSend.PushItem( PSElement( MString( cPress ) ) );
01226 m_objNotify->Message( m_iMessageWhenDone, ToSend, sPromptedInput );
01227 } else
01228 m_sPromptedText+= cPress;
01229 }
01230 }
01231 break;
01232 }
01233 }
01234 MercuryObject::Message( Message, data, name );
01235 }
01236
01237 void MercuryTextPrompt::PromptForText( int iMessageWhenDone, MercuryScreen * Notifier, const MString &sPrompt,
01238 const MString &sDefaultText, bool bAllowCancel, bool bSingleChar )
01239 {
01240 m_bAllowCancel = bAllowCancel;
01241 m_objNotify = Notifier;
01242 m_iMessageWhenDone = iMessageWhenDone;
01243 m_bSingleChar = bSingleChar;
01244 m_bPromptingForText = true;
01245 m_sPromptedText = sDefaultText;
01246 m_tTextInOverlayPrompt.SetText( sPrompt );
01247 m_tTextInOverlayPrompt.SetHide( false );
01248 m_tTextInOverlayPrompt.Tweening.ExecuteCommand( "OnCommand", PStack() );
01249 m_tTextInOverlayText.SetText( sDefaultText );
01250 m_tTextInOverlayText.SetHide( false );
01251 m_tTextInOverlayText.Tweening.ExecuteCommand( "OnCommand", PStack() );
01252 m_sTextInOverlay.SetHide( false );
01253 m_sTextInOverlay.Tweening.ExecuteCommand( "OnCommand", PStack() );
01254 }
01255
01256
01257
01258 void AddControlPaneObject( MercuryObject * parent, MercuryText * child, const char * name )
01259 {
01260 child->SetName( parent->GetName() + name );
01261 child->Init();
01262 child->SetFont( THEME.GetMetricS( parent->GetName(), "Font" ) );
01263 child->Tweening.AddCommand( THEME.GetMetricS( parent->GetName(), MString( name ) + "OnCommand" ) );
01264 parent->AddObject( child );
01265 }
01266
01267 void ObjectControlPane::Init()
01268 {
01269 MercuryObject::Init();
01270
01271
01272 m_objWatch = NULL;
01273 m_objMimic.SetName( GetName() + "MimicHolder" );
01274 m_objMimic.Init();
01275 m_objMimic.SetPosition( MercuryPoint(-1,-1,-1) );
01276 m_objMimic.SetScale( MercuryPoint(-1,-1,-1) );
01277 m_objMimic.SetRot( MercuryPoint(-1,-1,-1) );
01278
01279
01280 m_sBackground.SetName( GetName() + "Background" );
01281 m_sBackground.Init();
01282 m_sBackground.LoadImage( THEME.GetMetricS( GetName(), "Background" ) );
01283 m_sBackground.Tweening.AddCommand( THEME.GetMetricS( GetName(), "BackgroundOnCommand" ) );
01284 AddObject( &m_sBackground );
01285
01286 AddControlPaneObject( this, &m_tName, "Name" );
01287 AddControlPaneObject( this, &m_tPosition, "Position" );
01288 AddControlPaneObject( this, &m_tScale, "Scale" );
01289 AddControlPaneObject( this, &m_tRotation, "Rotation" );
01290 AddControlPaneObject( this, &m_tAttributes, "Attributes" );
01291
01292
01293
01294 Tweening.AddCommand( THEME.GetMetricS( GetName(), "PaneOn", "x,%1;y,%2" ), MercuryTweenState::LOCAL, "PaneOn" );
01295 Tweening.AddCommand( THEME.GetMetricS( GetName(), "PaneOff", "x,%1;y,%2" ), MercuryTweenState::LOCAL, "PaneOff" );
01296 }
01297
01298 void ObjectControlPane::Update( const float dTime )
01299 {
01300 if ( m_objWatch )
01301 {
01302 if ( m_objMimic.GetPosition() != m_objWatch->GetPosition() )
01303 {
01304 MercuryPoint p = m_objWatch->GetPosition();
01305 m_tPosition.SetText( ssprintf( "(%.4f, %.4f, %.4f)", p.GetX(), p.GetY(), p.GetZ() ) );
01306
01307 m_objMimic.SetPosition( m_objWatch->GetPosition() );
01308 }
01309 if ( m_objMimic.GetScale() != m_objWatch->GetScale() )
01310 {
01311 MercuryPoint p = m_objWatch->GetScale();
01312 m_tScale.SetText( ssprintf( "(%.4f, %.4f, %.4f)", p.GetX(), p.GetY(), p.GetZ() ) );
01313
01314 m_objMimic.SetScale( m_objWatch->GetScale() );
01315 }
01316 if ( m_objMimic.GetRot() != m_objWatch->GetRot() )
01317 {
01318 MercuryPoint p = m_objWatch->GetRot();
01319 m_tRotation.SetText( ssprintf( "(%.4f, %.4f, %.4f)", p.GetX(), p.GetY(), p.GetZ() ) );
01320
01321 m_objMimic.SetRot( m_objWatch->GetRot() );
01322 }
01323 }
01324 MercuryObject::Update( dTime );
01325 }
01326
01327 void ObjectControlPane::SetObject( MercuryObject * obj, int LX, int LY )
01328 {
01329 if ( !obj && m_objWatch )
01330 {
01331 Tweening.StopTweening();
01332 Tweening.ExecuteCommand( "PaneOff", PStack() );
01333 }
01334 else if ( obj != m_objWatch )
01335 {
01336 Tweening.StopTweening();
01337 Tweening.ExecuteCommand( "PaneOn", PStack( PSElement( LX ), PSElement( LY ) ) );
01338 m_tName.SetText( obj->GetName() );
01339 }
01340
01341 m_objWatch = obj;
01342 m_tAttributes.SetText( "" );
01343 }
01344
01345 void ObjectControlPane::SetAttributes( const MString & sAttributes )
01346 {
01347 m_tAttributes.SetText( sAttributes );
01348 }
01349
01350 void TextList::Init()
01351 {
01352 MercuryObject::Init();
01353 Tweening.AddCommand( THEME.GetMetricS( GetName(), "TextSetupCommand" ), MercuryTweenState::GLOBAL, "SidebarTextOn" );
01354 }
01355
01356 void TextList::SetupList( MVector< MString > &vsList )
01357 {
01358 Tweening.AddCommand( THEME.GetMetricS( GetName(), "OffCommand" ) );
01359 Tweening.FinishTweening();
01360
01361 m_sBG.SetName( GetName() + "Overlay" );
01362 m_sBG.Init();
01363 m_sBG.LoadImage( THEME.GetMetricS( GetName(), "Overlay" ) );
01364 m_sBG.Tweening.AddCommand( THEME.GetMetricS( GetName(), "GraphicOnCommand" ) );
01365 AddObject( &m_sBG );
01366
01367 float dY = THEME.GetMetricF( GetName(), "DeltaY" );
01368 float cY = THEME.GetMetricF( GetName(), "StartY" );
01369
01370 UnsetupList();
01371
01372 m_vTexts.resize( vsList.size() );
01373 for ( unsigned i = 0; i < vsList.size(); i++ )
01374 {
01375 if ( vsList[i] == "AdditionalFiles" )
01376 continue;
01377 MercuryText* t = new MercuryText;
01378 m_vTexts[i] = t;
01379 t->SetName( ssprintf( "%sText%d", GetName().c_str(), i+1 ) );
01380 t->Init();
01381 t->SetFont( THEME.GetMetricS( GetName(), "Font" ) );
01382 t->Tweening.ExecuteCommand( "SidebarTextOn", PStack( PSElement( cY ) ) );
01383 t->SetText(vsList[i]);
01384 AddObject( t, true );
01385 cY += dY;
01386 }
01387 }
01388
01389 TextList::~TextList()
01390 {
01391 UnsetupList();
01392 }
01393
01394 void TextList::UnsetupList()
01395 {
01396 for ( unsigned i = 0; i < m_vTexts.size(); i++ )
01397 RemoveObject( m_vTexts[i] );
01398
01399 m_vTexts.resize(0);
01400 }
01401
01402 void TextList::Show()
01403 {
01404 Tweening.AddCommand( THEME.GetMetricS( GetName(), "OnCommand" ) );
01405 }
01406
01407 void TextList::Hide()
01408 {
01409 Tweening.AddCommand( THEME.GetMetricS( GetName(), "OffCommand" ) );
01410 }
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438