ScreenMapEditor.cpp

Go to the documentation of this file.
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 L = LoadFile
00054 W = LoadWorld
00055 O = LoadObject Class
00056 S = Save Current
00057 I = List contents of File
00058 
00059 G = Jump to Piece #
00060 Home = First Piece
00061 PgUp = Previous Piece
00062 PgDn = Next Piece
00063 End = Last Piece
00064 <- = Deselect object
00065 
00066 C = Down
00067 D = Up
00068 
00069 N = New Piece       ************* NOT YET IMPLEMENTED *************
00070 DEL = Delete Piece  ************* NOT YET IMPLEMENTED *************
00071 R = Reset Camera
00072 
00073 Button 1 = Control on Object
00074 
00075 Position Normally (When Button1 is pressed)
00076 Ctrl: Control Rotation
00077 Shift: Control Z
00078 
00079 ---Piece Only Commands---
00080 U = Set/Reset uses ODE
00081 V = Set/Reset is Visible
00082 F = Set Filename
00083 E = Set Density
00084 T = Set Type
00085 
00086 J = Length
00087 K = Radius (If applicable, or Scale if applicable)
00088 
00089 ---World Only Commands---
00090 V = Set Gravity
00091 B = Set/Reset Bodied
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     //Set the mouse to start
00111     INPUTMAN->GetCursorPosition( m_iOldMouseX, m_iOldMouseY );
00112 
00113     m_fODEables.SetName( "MapEditor_ODEables" );
00114     m_fODEables.Init();
00115     //m_fODEables.SetProjectionType( PERSPECTIVE );
00116     AddPerspObject( &m_fODEables );
00117 
00118     m_fVisibles.SetName( "MapEditor_Visibles" );
00119     m_fVisibles.Init();
00120     //m_fODEables.SetProjectionType( PERSPECTIVE );
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     //Setup a light
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;  //Update mouse location regardless as to if we have focus so we don't jump
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     // OK The next few lines should use Quaternions.
00229     // Seriously... they REALLY shouldn't be done this way.
00230     // if ANYONE WANTS... FEEL FREE TO EDIT THIS!
00231     float qX = 0;
00232     float qY = 0;
00233 
00234     //Camera Position
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     //I commented out these lines of code so that you don't move the camera up and down with the arrow keys
00247     //m_pCamera.z += SIN(m_pCameraRot.y)*qY;
00248     m_pCameraPos.x += (COS(AngleToGo+(3.141592653589f/2))*qX + COS(AngleToGo)*qY);//*SQRT(1-SIN(m_pCameraRot.y)*SIN(m_pCameraRot.y));
00249     m_pCameraPos.y += (SIN(AngleToGo+(3.141592653589f/2))*qX + SIN(AngleToGo)*qY);//*SQRT(1-SIN(m_pCameraRot.y)*SIN(m_pCameraRot.y));
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                 //dx -= dY;
00270                 //dy -= dX;
00271                 //Now we do it based on world coordinates
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 ) //FIXME (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;   //Reset these here incase something is wrong with the part.
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         //Cores
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 //      float   fDensity =  m_iWorldFile.GetValueF( sObjectIn, sPName + "Density" );
00482         
00483         //Optionals
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         //If we are both ODE and VISIBLE, do it twice, otherwise, once.
00496         for ( unsigned j = 0; j < ((bVisible&&bUsesODE)?2:1); j++ )
00497         {
00498             MercuryObject * co = NULL;
00499 
00500             //NOTE: The next few lines are exactly as they are found in MercuryODE.
00501 
00502             switch ( iType )
00503             {
00504             case 0:     //Sphere
00505                 {
00506                 MercuryShape * s = new MercuryShape;
00507                 s->SetName( sObjectIn + sPName );
00508                 s->Init();
00509                 //Make a sphere with stacks/slices based on the INI file
00510                 s->MakeSphere(  m_iWorldFile.GetValueI( sObjectIn, sPName + "Stacks", 6 ),
00511                                 m_iWorldFile.GetValueI( sObjectIn, sPName + "Slices", 12 ) );
00512                 
00513                 //Load the PNG file based on the theme
00514                 s->LoadImage( THEME.GetPathToGraphic( sFilename ) );
00515 
00516                 //Set all other information for the sphere here
00517                 float fRadius = m_iWorldFile.GetValueF( sObjectIn, sPName + "Radius", 1 );
00518                 s->SetScale( MercuryPoint( fRadius, fRadius, fRadius ) );
00519 
00520                 //Put our sphere in the vector of objects so it gets deleted in the end.
00521                 co = s;
00522                 break;
00523                 }
00524             case 1:     //Cylinder
00525                 {
00526                     //For info, refer to sphere
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                     //For info, refer to sphere
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: //Model
00554                 {
00555                     //Refer to sphere
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                 //ODE
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                 //Visible
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() );   //Refresh any necessiary data.
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             //this is counting both down and up, it should only count one of the two
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() );   //Refresh any necessiary data.
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() );   //Refresh any necessiary data.
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:           //Home
00921             SelectObject( 0 );
00922             break;
00923         case 279:           //End
00924             SelectObject( GetNumObjects() - 1 );
00925             break;
00926         case 280:           //PgUp
00927             if ( SelectedObject() > 0 )
00928                 SelectObject( SelectedObject() - 1 );
00929             break;
00930         case 281:           //PgDn
00931             if ( SelectedObject() < ( GetNumObjects() - 1 ) )
00932                 SelectObject( SelectedObject() + 1 );
00933             break;
00934         case 8:             //Back Space
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     //  ClearOutArea();
01115     //  GenerateObject( m_iTightFile.GetValueS( m_sEditingName, ssprintf( "Piece%d", iTempSelect+1 ) ), iTempSelect );
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 /****************************** TEXT PROMPT **********************************/
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 )    //Make sure we're pressing DOWN on the KEYBOARD
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 /****************************** CONTROL PANE *********************************/
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 //  SetProjectionType( ORTHOGRAPHIC );
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 //  m_sBackground.SetProjectionType( ORTHOGRAPHIC );
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 //  SetHide(1);
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         //  m_tPosition.Tweening.AddCommand( THEME.GetMetricS( m_tPosition.GetName(), "Change" ) ); 
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         //  m_tScale.Tweening.AddCommand( THEME.GetMetricS( m_tScale.GetName(), "Change" ) ); 
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         //  m_tRotation.Tweening.AddCommand( THEME.GetMetricS( m_tRotation.GetName(), "Change" ) ); 
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  * Copyright (c) 2006 Charles Lohr
01414  * All rights reserved.
01415  *
01416  * Redistribution and use in source and binary forms, with or
01417  * without modification, are permitted provided that the following
01418  * conditions are met:
01419  *  -   Redistributions of source code must retain the above
01420  *      copyright notice, this list of conditions and the following disclaimer.
01421  *  -   Redistributions in binary form must reproduce the above copyright
01422  *      notice, this list of conditions and the following disclaimer in
01423  *      the documentation and/or other materials provided with the distribution.
01424  *  -   Neither the name of the Mercury Engine nor the names of its
01425  *      contributors may be used to endorse or promote products derived from
01426  *      this software without specific prior written permission.
01427  *
01428  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
01429  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
01430  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
01431  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
01432  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
01433  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
01434  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
01435  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
01436  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
01437  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
01438  */

Hosted by SourceForge.net Logo