00001 #include "wxIncludes.h" 00002 #include <wx/xrc/xmlres.h> 00003 #include <wx/image.h> 00004 #include <wx/menu.h> 00005 #include <wx/toolbar.h> 00006 #include <wx/metafile.h> 00007 #include <wx/gdicmn.h> 00008 #include "ThyrixApplication.h" 00009 #include "ThyrixMainFrame.h" 00010 #include "World.h" 00011 00012 00013 //Used in a C++ implementation file to complete the declaration of a class that 00014 //has run-time type information. 00015 //(?) 00016 IMPLEMENT_CLASS(ThyrixMainFrame, wxFrame) 00017 00018 // the event tables connect the wxWindows events with the functions (event 00019 // handlers) which process them. It can be also done at run-time, but for the 00020 // simple menu events like this the static method is much simpler. 00021 BEGIN_EVENT_TABLE(ThyrixMainFrame, wxFrame) 00022 //EVT_MENU(XRCID("file_menu_exit"), ThyrixMainFrame::OnQuit) 00023 //EVT_MENU(XRCID("help_menu_about"), ThyrixMainFrame::OnAbout) 00024 //EVT_PAINT(ThyrixMainFrame::onPaint) 00025 EVT_MOTION(ThyrixMainFrame::onMotion) 00026 EVT_LEFT_DOWN(ThyrixMainFrame::onLeftDown) 00027 EVT_LEFT_UP(ThyrixMainFrame::onLeftUp) 00028 EVT_RIGHT_DOWN(ThyrixMainFrame::onRightDown) 00029 EVT_RIGHT_UP(ThyrixMainFrame::onRightUp) 00030 EVT_CLOSE(ThyrixMainFrame::OnClose) 00031 //EVT_IDLE(ThyrixMainFrame::OnIdle) 00032 EVT_MENU_RANGE(ThyrixMainFrame::kMenuTimePause, 00033 ThyrixMainFrame::kMenuTimeMax, 00034 ThyrixMainFrame::onSetSpeed) 00035 EVT_MENU_RANGE(ThyrixMainFrame::kMenuFps30, 00036 ThyrixMainFrame::kMenuFps90, 00037 ThyrixMainFrame::onSetFps) 00038 EVT_MENU(kMenuStep, ThyrixMainFrame::onStep) 00039 EVT_MENU(kMenuCapture, ThyrixMainFrame::onCapture) 00040 00041 END_EVENT_TABLE() 00042 00043 //frame constructor 00044 ThyrixMainFrame::ThyrixMainFrame(const wxString& title, World* world, 00045 int bufferWidth, int bufferHeight, int zoom) 00046 : wxFrame((wxFrame *)NULL, -1, title, wxDefaultPosition, wxDefaultSize), 00047 thread(this), 00048 gui(0), 00049 world(world), 00050 bufferWidth(bufferWidth), 00051 bufferHeight(bufferHeight), 00052 zoom(zoom){ 00053 thread.world=world; 00054 00055 // set the frame icon 00056 SetIcon(wxICON(Thyrix)); 00057 00058 //set the background color of the frame 00059 SetBackgroundColour(*wxWHITE); 00060 00061 /* load the menubar & toolbar 00062 please, find a way to load these from the executable, not from 00063 separate data (.xml) files. 00064 SetMenuBar(wxXmlResource::Get()->LoadMenuBar("main_menubar")); 00065 SetToolBar(wxXmlResource::Get()->LoadToolBar(this, "main_toolbar")); 00066 */ 00067 00068 // Set the buffer bitmap and the corresponding memory DC 00069 bitmap.Create(bufferWidth,bufferHeight); 00070 buffer.SelectObject(bitmap); 00071 buffer.SetBackground(*wxWHITE_BRUSH); 00072 buffer.Clear(); 00073 00074 CreateStatusBar(3); 00075 00076 //create a toolbar with one button 00077 wxToolBar* toolbar = CreateToolBar(wxTB_TEXT | wxTB_NOICONS); 00078 wxBitmap dummy; 00079 toolbar->AddTool(kMenuStep, "Step", dummy); 00080 toolbar->AddTool(kMenuCapture, "Capture", dummy); 00081 toolbar->Realize(); 00082 00083 buildMenu(); 00084 00085 SetClientSize(bufferWidth,bufferHeight+5); 00086 thread.Create(); 00087 } 00088 00089 // frame destructor 00090 ThyrixMainFrame::~ThyrixMainFrame() { 00091 thread.Delete(); 00092 delete gui; 00093 gui=NULL; 00094 } 00095 00096 void ThyrixMainFrame::buildMenu() { 00097 wxMenu *timeMenu = new wxMenu; 00098 timeMenu->AppendRadioItem(kMenuTimePause, "Step by step"); 00099 timeMenu->AppendRadioItem(kMenuTimeDiv10,"/10 \tslow time"); 00100 timeMenu->AppendRadioItem(kMenuTimeX1, "x1 \treal time"); 00101 timeMenu->AppendRadioItem(kMenuTimeX3, "x3 \ttime factor"); 00102 timeMenu->AppendRadioItem(kMenuTimeX10, "x10 \ttime factor"); 00103 timeMenu->AppendRadioItem(kMenuTimeX30, "x30 \ttime factor"); 00104 timeMenu->AppendRadioItem(kMenuTimeX100, "x100 \ttime factor"); 00105 timeMenu->AppendRadioItem(kMenuTimeMax, "Maximum speed"); 00106 //timeMenu->Check(kMenuTimeX1, true); 00107 timeMenu->Check(kMenuTimeMax, true); 00108 00109 wxMenu *displayMenu = new wxMenu; 00110 displayMenu->AppendRadioItem(kMenuFps30, "30 Frames Per Second"); 00111 displayMenu->AppendRadioItem(kMenuFps60, "60 FPS"); 00112 displayMenu->AppendRadioItem(kMenuFps90, "90 FPS"); 00113 displayMenu->Check(kMenuFps30, true); 00114 00115 wxMenuBar *menubar = new wxMenuBar; 00116 menubar->Append(timeMenu, "Speed"); 00117 menubar->Append(displayMenu, "Display"); 00118 SetMenuBar(menubar); 00119 } 00120 00121 void ThyrixMainFrame::start() { 00122 gui = new GUIWx(0,bufferHeight,zoom,GetStatusBar()); 00123 thread.Run(); 00124 } 00125 00126 void ThyrixMainFrame::onStep(wxCommandEvent& event) { 00127 thread.step(); 00128 } 00129 00130 void ThyrixMainFrame::onCapture(wxCommandEvent& event) { 00131 wxMetafileDC* dc=new wxMetafileDC("capture.wmf",bufferWidth,bufferHeight); 00132 paintDC(dc); 00133 wxMetafile* metafile=dc->Close(); 00134 metafile->SetClipboard((int)(dc->MaxX() + 10), (int)(dc->MaxY() + 10) ); 00135 delete metafile; 00136 delete dc; 00137 00138 } 00139 00140 void ThyrixMainFrame::onSetFps(wxCommandEvent& event) { 00141 switch(event.GetId()) { 00142 case kMenuFps30: 00143 thread.setFramesPerSecond(30); 00144 break; 00145 case kMenuFps60: 00146 thread.setFramesPerSecond(60); 00147 break; 00148 case kMenuFps90: 00149 thread.setFramesPerSecond(90); 00150 break; 00151 } 00152 } 00153 00154 void ThyrixMainFrame::onSetSpeed(wxCommandEvent& event) { 00155 switch(event.GetId()) { 00156 case kMenuTimePause: 00157 thread.setPause(); 00158 break; 00159 case kMenuTimeDiv10: 00160 thread.setTimeFactor(0.1f); 00161 break; 00162 case kMenuTimeX1: 00163 thread.setTimeFactor(1); 00164 break; 00165 case kMenuTimeX3: 00166 thread.setTimeFactor(3); 00167 break; 00168 case kMenuTimeX10: 00169 thread.setTimeFactor(10); 00170 break; 00171 case kMenuTimeX30: 00172 thread.setTimeFactor(30); 00173 break; 00174 case kMenuTimeX100: 00175 thread.setTimeFactor(100); 00176 break; 00177 case kMenuTimeMax: 00178 thread.setTimeFactor(1000); 00179 break; 00180 } 00181 } 00182 00183 /* 00184 void ThyrixMainFrame::OnIdle(wxIdleEvent& event) { 00185 event.RequestMore(); 00186 00187 for (int i = 0; i < 100; ++i) { 00188 simulator->advanceTime(); 00189 } 00190 paint(); 00191 } 00192 */ 00193 00194 00195 00196 void ThyrixMainFrame::OnClose(wxCloseEvent& event){ 00197 //thread.Delete(); 00198 Destroy(); 00199 } 00200 00201 /* 00202 void ThyrixMainFrame::OnQuit(wxCommandEvent& event){ 00203 // TRUE is to force the frame to close 00204 Close(TRUE); 00205 } 00206 */ 00207 00208 /* 00209 void ThyrixMainFrame::OnAbout(wxCommandEvent& event){ 00210 // called when help - about is picked from the menu or toolbar 00211 wxString msg; 00212 msg.Printf(_("Thyrix: a simulator for virtual environments\n(c) Arxia / Coneural 2003\n")); 00213 wxMessageBox(msg, _("About Thyrix"), wxOK | wxICON_INFORMATION, this); 00214 } 00215 */ 00216 00217 /* 00218 void ThyrixMainFrame::onPaint(wxPaintEvent& event){ 00219 //If no DC is created, the program does not stop. From the WX documentation (wxPaintEvent): 00220 //In a paint event handler, the application must always create a wxPaintDC object, 00221 //even if you do not use it. Otherwise, under MS Windows, refreshing for this and 00222 //other windows will go wrong. 00223 00224 wxPaintDC dc(this); 00225 //dc.Blit(0,50,600,400,&buffer,0,0); 00226 } 00227 */ 00228 00229 void ThyrixMainFrame::paint(){ 00230 wxClientDC dc(this); 00231 //here you can chose, to paint either directly to screen, 00232 //or paint to a memoryDC & copy to screen (to avoid flicker). 00233 //paintDC(&dc); 00234 paintDC(&buffer); 00235 dc.Blit(0,30,bufferWidth,bufferHeight,&buffer,0,0); 00236 } 00237 00238 /* 00239 void ThyrixMainFrame::onEraseBackground(wxEraseEvent& event){ 00240 } 00241 */ 00242 00243 void ThyrixMainFrame::onMotion(wxMouseEvent& event){ 00244 if(event.LeftIsDown()){ 00245 world->setMouseCoordinates(gui->inverseMapX(event.GetX()), gui->inverseMapY(event.GetY())); 00246 } 00247 } 00248 00249 void ThyrixMainFrame::onLeftDown(wxMouseEvent& event){ 00250 float x=gui->inverseMapX(event.GetX()); 00251 float y=gui->inverseMapY(event.GetY()); 00252 world->onMouseLeftDown(x,y); 00253 //simulator->applyMouseForce(x,y); 00254 //simulator->setMouseCoordinates(x,y); 00255 } 00256 00257 void ThyrixMainFrame::onLeftUp(wxMouseEvent& event){ 00258 float x=gui->inverseMapX(event.GetX()); 00259 float y=gui->inverseMapY(event.GetY()); 00260 world->onMouseLeftUp(x,y); 00261 //simulator->unsetMouseForce(); 00262 } 00263 00264 void ThyrixMainFrame::onRightDown(wxMouseEvent& event){ 00265 float x=gui->inverseMapX(event.GetX()); 00266 float y=gui->inverseMapY(event.GetY()); 00267 world->onMouseRightDown(x,y); 00268 } 00269 00270 void ThyrixMainFrame::onRightUp(wxMouseEvent& event){ 00271 float x=gui->inverseMapX(event.GetX()); 00272 float y=gui->inverseMapY(event.GetY()); 00273 world->onMouseRightUp(x,y); 00274 } 00275 00276 00277 void ThyrixMainFrame::paintDC(wxDC* dc){ 00278 //dc->SetOptimization(true); 00279 dc->BeginDrawing(); 00280 dc->Clear(); 00281 gui->setDC(dc); 00282 world->draw(gui); 00283 dc->EndDrawing(); 00284 }
Thyrix homepage Users' guide
(C) Arxia 2004-2005