screenTask.cpp

00001 /*
00002   スクリーンの描画処理
00003   Satofumi KAMIMURA
00004   $Id$
00005 */
00006 
00007 #include "screenTask.h"
00008 #include "parseArgs.h"
00009 #include "deleteObjects.h"
00010 
00011 
00012 ScreenTask::ScreenTask(WindowInterface* winObj, TTF_Draw* ttfObj)
00013   : win(winObj), ttf(ttfObj), mon(vmonitor::getObject()),
00014     main_back(NULL), under_back(NULL),
00015     ticks(0), isActivated(false), component_created(false),
00016     pause_next(mon->is_pause),
00017     pause_locked(false), msec_text(NULL), pos_text(NULL), pause_text(NULL),
00018     scroll_text(NULL), v_line(NULL), h_line_1(NULL), h_line_2(NULL),
00019     msec_label(NULL), pos_label(NULL), pause_label(NULL),
00020     main_view(NULL), user_view(NULL), mini_view(NULL),
00021     body_lines(NULL), debug_area(NULL), crd_cmb(NULL), scroll_checkbox(NULL),
00022     view_magnify((480.0 / 6000.0)), // 480[px]を何[mm]相当に変換するか
00023     view_center(VXV::Grid()),
00024     grid_center(VXV::Grid(0,0)), no_scroll(false), debug_area_clear(false),
00025     layer_index(ALL_LAYER +1),
00026     command_log(NULL) {
00027 
00028   body_original.push_back(VXV::Grid(-100, 150));
00029   body_original.push_back(VXV::Grid(-100, -150));
00030   body_original.push_back(VXV::Grid(70, -150));
00031   body_original.push_back(VXV::Grid(150, 0));
00032   body_original.push_back(VXV::Grid(70, 150));
00033   body_original.push_back(VXV::Grid(-100, 150));
00034 
00035   mini_body.push_back(VXV::Grid(-2, -2));
00036   mini_body.push_back(VXV::Grid(+2, -2));
00037   mini_body.push_back(VXV::Grid(+2, +2));
00038   mini_body.push_back(VXV::Grid(-2, +2));
00039   mini_body.push_back(VXV::Grid(-2, -2));
00040 
00041   int mini_x = win->w / MiniScrMagnify /2;
00042   int mini_y = (win->h - FrameHeight - LineWidth) / MiniScrMagnify /2;
00043   scr_rect.push_back(VXV::Grid(-mini_x, -mini_y));
00044   scr_rect.push_back(VXV::Grid(+mini_x, -mini_y));
00045   scr_rect.push_back(VXV::Grid(+mini_x, +mini_y));
00046   scr_rect.push_back(VXV::Grid(-mini_x, +mini_y));
00047   scr_rect.push_back(VXV::Grid(-mini_x, -mini_y));
00048 }
00049 
00050 
00051 ScreenTask::~ScreenTask(void) {
00052   isActivated = false;
00053   clear(ALL_LAYER);
00054 
00055   delete v_line;
00056   delete h_line_1;
00057   delete h_line_2;
00058   delete msec_text;
00059   delete pos_text;
00060   delete pause_text;
00061   delete scroll_text;
00062   delete under_back;
00063   delete main_back;
00064 }
00065 
00066 
00067 void  ScreenTask::init(void) {
00068   win->lock();
00069 
00070   // 画面背景を配置
00071   main_back = new FillSurface(Rect(win->w, win->h - FrameHeight), Gray3);
00072   win->add(new LabelComponent(main_back));
00073 
00074   // 下部の背景
00075   under_back = new FillSurface(Rect(win->w, FrameHeight), Black);
00076   win->add((new LabelComponent(under_back))
00077            ->setPosition(VXV::Grid(0, win->h - FrameHeight)));
00078 
00079   v_line = new FillSurface(Rect(win->w, LineWidth), White);
00080   win->add((new LabelComponent(v_line))
00081            ->setPosition(VXV::Grid(0, win->h - FrameHeight)));
00082   h_line_1 = new FillSurface(Rect(LineWidth, FrameHeight), White);
00083   win->add((new LabelComponent(h_line_1))
00084            ->setPosition(VXV::Grid(MiniMapWidth,
00085                                    win->h - FrameHeight + LineWidth)));
00086 
00087   h_line_2 = new FillSurface(Rect(LineWidth, FrameHeight), White);
00088   win->add((new LabelComponent(h_line_2))
00089            ->setPosition(VXV::Grid(MiniMapWidth + LineWidth + MiniInfoWidth,
00090                                    win->h - FrameHeight + LineWidth)));
00091 
00092   // 描画コンポーネントを配置
00093   main_view = new ViewComponent(VXV::Rect(win->w, win->h - FrameHeight));
00094   user_view = new ViewComponent(VXV::Rect(win->w, win->h - FrameHeight));
00095   grid_center = VXV::Grid(win->w/2, (win->h - FrameHeight)/2);
00096   updateViewMagnify(view_magnify);
00097   win->add(main_view);
00098   win->add(user_view);
00099 
00100   // 表示枠の表示用
00101   mini_view = new ViewComponent(VXV::Rect(MiniMapWidth, FrameHeight));
00102   mini_view->setPosition(VXV::Grid(0, win->h - FrameHeight + LineWidth));
00103   mini_view->setViewToRangeGrid(Grid(0,0), Grid(MiniMapWidth/2,FrameHeight/2));
00104 
00105   win->add(mini_view);
00106 
00107   // コマンド履歴用
00108   command_log =
00109     new ScrollAreaComponent(*ttf, VXV::Rect(MiniCmd_X,
00110                                             win->h - FrameHeight + LineWidth,
00111                                             win->w - MiniCmd_X, FrameHeight));
00112   win->add(command_log);
00113 
00114   // デバッグ表示用
00115   debug_area =
00116     new ScrollAreaComponent(*ttf, VXV::Rect(win->w, win->h - FrameHeight));
00117   win->add(debug_area);
00118 
00119   // 座標系選択のコンボボックス
00120   crd_cmb = new ComboBoxComponent(*ttf);
00121 
00122   // スクロール指定のチェックボックス
00123   scroll_checkbox = new CheckBoxComponent(*ttf);
00124 
00125   win->unlock();
00126   ticks = mon->getTicks();
00127 }
00128 
00129 
00130 void ScreenTask::activate(void) {
00131   if (component_created) {
00132     return;
00133   }
00134   win->lock();
00135 
00136   // 座標系選択のコンボボックス
00137   crd_cmb->add(" World ");
00138   crd_cmb->add(" GL ");
00139   crd_cmb->setFontSize(LogFontPx);
00140   crd_cmb->activate(true);
00141   crd_cmb->setNowIndex(mon->property->crd_index);
00142   crd_cmb->setPosition(Grid(win->w -16, 8), Right | Top);
00143   win->addInputComponent(crd_cmb, LogLevelFore);
00144 
00145   // スクロール指定のチェックボックス
00146   scroll_text =
00147     new DrawSurface(ttf->createText("scroll with robot",
00148                                     MiniFontPx, White, Gray4), true);
00149   scroll_checkbox->setLabel(new LabelComponent(scroll_text));
00150   scroll_checkbox->setLength(LogFontPx);
00151   scroll_checkbox->activate();
00152   scroll_checkbox->setNowChecked(true);
00153   scroll_checkbox->setPosition(VXV::Grid(8, win->h - FrameHeight +4));
00154   win->add(scroll_checkbox);
00155 
00156   // ポーズ表示用のサーフェス生成
00157   pause_text =
00158     new DrawSurface(ttf->createText("Pause!", LogFontPx, Red, Gray4), true);
00159 
00160   win->unlock();
00161   component_created = true;
00162 }
00163 
00164 
00165 void ScreenTask::rotatePoint(VXV::Grid& point, double radian) {
00166   int px = (int)(point.x * cos(radian) + point.y * sin(radian));
00167   int py = (int)(point.x * -sin(radian) + point.y * cos(radian));
00168   point.x = px;
00169   point.y = py;
00170 }
00171 
00172 
00173 void ScreenTask::drawRobotBody(const VXV::Position& bodyPos,
00174                                const VXV::Direction& diff) {
00175   // 筐体のデータ点群を回転させる
00176   std::deque<Grid> body = body_original;
00177   double direction = bodyPos.zt.to_rad() + diff.to_rad();
00178   for (std::deque<Grid>::iterator it = body.begin();
00179        it != body.end(); ++it) {
00180     rotatePoint(*it, -direction);
00181     it->x += bodyPos.x;
00182     it->y += bodyPos.y;
00183   }
00184 
00185   // 描画
00186   body_lines = new ContLineDraw(body, Green);
00187   main_view->add(body_lines);
00188 }
00189 
00190 
00191 void ScreenTask::drawRunGrid(const VXV::Position& offset) {
00192   VXV::Grid first, last;
00193   first.x = static_cast<int>(+view_center.x -(main_view->w/2/view_magnify));
00194   first.y = static_cast<int>(-view_center.y -(main_view->h/2/view_magnify));
00195   last.x = first.x + static_cast<int>(main_view->w / view_magnify);
00196   last.y = first.y + static_cast<int>(main_view->h / view_magnify);
00197 
00198   first -= offset;
00199   last -= offset;
00200   char grid_str[13];
00201   for (int x = (first.x / 1000) * 1000; x <= last.x; x += 1000) {
00202     main_view->add(new LineDraw(VXV::Grid(x, first.y) + offset,
00203                                 VXV::Grid(x, last.y) + offset, Gray7));
00204     sprintf(grid_str, "%d", x);
00205     main_view->add(new TextDraw(*ttf, grid_str,
00206                                 Grid(x +16, last.y) + offset,
00207                                 MiniFontPx, true, Gray14, Black, true));
00208   }
00209   for (int y = ((first.y / 1000) * 1000); y <= last.y; y += 1000) {
00210     main_view->add(new LineDraw(VXV::Grid(first.x, y) + offset,
00211                                 VXV::Grid(last.x, y) + offset, Gray7));
00212     sprintf(grid_str, "%d", y);
00213     main_view->add(new TextDraw(*ttf, grid_str,
00214                                 Grid(first.x, y -16) + offset,
00215                                 MiniFontPx, true, Gray14, Black, true));
00216   }
00217 }
00218 
00219 
00220 void ScreenTask::drawEnvironment(const VXV::Position& pos_diff,
00221                                  const VXV::Position& diff) {
00222 
00223   VXV::Position rotate = pos_diff;
00224   rotate.zt = diff.zt;
00225   VXV::Matrix4D convert = VXV::createConvertMatrix(rotate);
00226 
00227   for (std::vector<CoordinateCtrl::polygon_t>::iterator it
00228          = env_polygons.begin(); it != env_polygons.end(); ++it) {
00229     VXV::Grid3D pre_p = it->back();
00230     for (std::vector<VXV::Grid3D>::iterator p = it->begin();
00231          p != it->end(); ++p) {
00232       VXV::Position3D rotate_p, rotate_pre_p;
00233       rotate_p.x = p->x + diff.x;
00234       rotate_p.y = p->y + diff.y;
00235       rotate_pre_p.x = pre_p.x + diff.x;
00236       rotate_pre_p.y = pre_p.y + diff.y;
00237       VXV::convert(rotate_p, rotate_p, convert);
00238       VXV::convert(rotate_pre_p, rotate_pre_p, convert);
00239       main_view->add(new LineDraw(rotate_p, rotate_pre_p, LightSalmon));
00240 
00241       pre_p = *p;
00242     }
00243   }
00244 }
00245 
00246 
00247 void ScreenTask::userInputHandle(UserInput::userInput_t& ui) {
00248   // キー入力、ホイールによる画面の拡大、縮小
00249   if (ui.isPressed('9') || (ui.wheel_moved < 0)) {
00250     // 縮小
00251     double set_magnify = view_magnify * 0.850;
00252     if (set_magnify > 0.03) {
00253       updateViewMagnify(set_magnify);
00254     }
00255   } else if (ui.isPressed('0') || (ui.wheel_moved > 0)) {
00256     // 拡大
00257     double set_magnify = view_magnify * 1.150;
00258     if (set_magnify < 0.6) {
00259       updateViewMagnify(set_magnify);
00260     }
00261   }
00262 }
00263 
00264 
00265 void ScreenTask::drawRobotInfo(const VXV::Position& bodyPos) {
00266   if (msec_text) {
00267     win->del(msec_label, LogLevel);
00268     delete msec_text;
00269   }
00270   char msec_str[22];
00271   sprintf(msec_str, "%.01f [sec]", ticks / 1000.0);
00272 
00273   msec_text = new DrawSurface(ttf->createText(msec_str, LogFontPx,
00274                                               White, Gray7), true);
00275   msec_label = new LabelComponent(msec_text);
00276   msec_label->setPosition(Grid(win->w -8, +8 +LogFontPx*2 +16), Right | Top);
00277   win->add(msec_label, LogLevel);
00278 
00279   // 自己位置の描画
00280   if (pos_text) {
00281     win->del(pos_label, LogLevel);
00282     delete pos_text;
00283   }
00284   char pos_str[47];
00285   sprintf(pos_str, "%0.3f [m], %0.3f [m], %3d [deg]",
00286           bodyPos.x / 1000.0, bodyPos.y / 1000.0, bodyPos.zt.to_deg());
00287   pos_text = new DrawSurface(ttf->createText(pos_str, LogFontPx,
00288                                              White, Gray7), true);
00289   pos_label = new LabelComponent(pos_text);
00290   pos_label->setPosition(Grid(win->w - 8, +16 +LogFontPx), Right | Top);
00291   win->add(pos_label, LogLevel);
00292 }
00293 
00294 
00295 void ScreenTask::handlePauseInput(UserInput::userInput_t& ui) {
00296 
00297   bool monitor_pause = mon->is_pause;
00298   if ((mon->mode == Monitor::Playback) && ui.isPressed(' ')) {
00299     pause_next = !monitor_pause;
00300   }
00301   if (pause_next != monitor_pause) {
00302     if (pause_next) {
00303       if (SDL_SemTryWait(mon->pause_sem) == 0) {
00304         mon->pause();
00305         pause_locked = true;
00306 
00307         pause_label = new LabelComponent(pause_text);
00308         pause_label->setPosition(VXV::Grid(win->w-10, win->h -FrameHeight -10),
00309                                  Right | Bottom);
00310         win->add(pause_label, LogLevel);
00311       }
00312     } else {
00313       if (pause_locked) {
00314         mon->start();
00315         pause_locked = false;
00316         SDL_SemPost(mon->pause_sem);
00317         win->del(pause_label, LogLevel);
00318         pause_label = NULL;
00319       }
00320     }
00321   }
00322 }
00323 
00324 
00325 // 縮小マップの描画
00326 void ScreenTask::drawMiniMap(VXV::Position& bodyPos) {
00327   mini_view->clear();
00328   mini_view->add(new ContLineDraw(mini_body, Green));
00329   mini_view->add(new ContLineDraw(scr_rect, White));
00330   VXV::Grid env_offset =
00331     VXV::Grid(static_cast<int>(-bodyPos.x /MiniScrMagnify * view_magnify),
00332               static_cast<int>(-bodyPos.y /MiniScrMagnify * view_magnify));
00333   for (std::vector<CoordinateCtrl::polygon_t>::iterator it
00334          = env_polygons.begin(); it != env_polygons.end(); ++it) {
00335     VXV::Grid3D pre_p = it->back();
00336     for (std::vector<VXV::Grid3D>::iterator p = it->begin();
00337          p != it->end(); ++p) {
00338       if (VXV::length(*p - pre_p) > 600) {
00339         int mag = static_cast<int>(1.0 * MiniScrMagnify / view_magnify);
00340         mini_view->
00341           add(new LineDraw(VXV::Grid(p->x/mag, p->y/mag) + env_offset,
00342                            VXV::Grid(pre_p.x/mag, pre_p.y/mag) + env_offset,
00343                            LightSalmon));
00344       }
00345       pre_p = *p;
00346     }
00347   }
00348 }
00349 
00350 
00351 void ScreenTask::handleCrdSelectInput(void) {
00352   if (crd_cmb->isDecided()) {
00353     mon->property->crd_index = crd_cmb->getNowIndex();
00354   }
00355 }
00356 
00357 
00358 void ScreenTask::send(void) {
00359   if (!isActivated) {
00360     return;
00361   }
00362 
00363   // キー入力にて終了するための処理
00364   UserInput::userInput_t ui = UserInput::getInputed();
00365   if (ui.quit) {
00366     exit(1);
00367   }
00368 
00369   // 表示画面の操作
00370   userInputHandle(ui);
00371 
00372   // 画面の描画情報を更新
00373   ticks = mon->getTicks();
00374   // !!!
00375   // !!! 以前に更新済みだったらな
00376 
00377   // !!! とりあえず、気にせず更新
00378   // !!! やはり、1度描画されてたら、以下の処理(描画用オブジェクトの生成)
00379   // に遷移すべき
00380 
00381   win->lock();
00382   main_view->clear();
00383 
00384   // ロボットを中心に描画する場合は、画面の描画中心を更新する必要がある
00385   if (scroll_checkbox->getNowChecked()) {
00386     view_center = VXV::Grid(MonitorTask::bodyPosition.x,
00387                             -MonitorTask::bodyPosition.y);
00388   }
00389   VXV::Position diff;
00390   VXV::Position bodyPos;
00391   if (!no_scroll) {
00392     if (mon->property->crd_index == 0) { // World
00393       bodyPos = MonitorTask::bodyPosition;
00394     } else {                    // GL
00395       bodyPos = MonitorTask::getRunPosition();
00396       diff = bodyPos - MonitorTask::bodyPosition;
00397 #if 0
00398       diff = bodyPos - MonitorTask::bodyPosition;
00399       //fprintf(stderr, "diff: (%d, %d)\n", diff.x, diff.y);
00400       VXV::Matrix4D convert =
00401         VXV::createConvertMatrix(diff);
00402 
00403       VXV::Position3D point = bodyPos;
00404       VXV::convert(point, point, convert);
00405       bodyPos.x = point.x;
00406       bodyPos.y = point.y;
00407 #endif
00408     }
00409   }
00410   updateView();
00411 
00412   drawRunGrid(MonitorTask::bodyPosition - bodyPos); // グリッドの描画
00413   drawEnvironment(MonitorTask::bodyPosition - bodyPos, diff); // 環境の描画
00414   drawRobotBody(MonitorTask::bodyPosition, diff.zt); // ロボットの描画
00415   drawRobotInfo(bodyPos);       // ticks, position の描画
00416   handlePauseInput(ui);         // スペースキーによる一時停止
00417   drawObjects(); // ユーザコマンド描画
00418   drawMiniMap(MonitorTask::bodyPosition); // 縮小マップの描画
00419   handleCrdSelectInput();       // コンボボックス選択の反映
00420 
00421   win->unlock();
00422 }
00423 
00424 
00425 void ScreenTask::show(void) {
00426   isActivated = true;
00427   activate();
00428 }
00429 
00430 
00431 void ScreenTask::hide(void) {
00432   isActivated = false;
00433 }
00434 
00435 
00436 void ScreenTask::updateView(void) {
00437   main_view->
00438     updateMagnify(view_magnify).setViewToRangeGrid(view_center, grid_center);
00439 
00440   user_view->
00441     updateMagnify(view_magnify).setViewToRangeGrid(view_center, grid_center);
00442 }
00443 
00444 
00445 void ScreenTask::updateViewMagnify(double magnify) {
00446   view_magnify = magnify;
00447   updateView();
00448 }
00449 
00450 
00451 void ScreenTask::setViewCenter(VXV::Grid& center) {
00452   view_center = center;
00453   updateView();
00454 }
00455 
00456 
00457 void ScreenTask::setEnvironment(const std::vector<CoordinateCtrl::polygon_t>&
00458                                 objs) {
00459   env_polygons = objs;
00460 }
00461 
00462 
00463 void ScreenTask::scrollWithRobot(bool on) {
00464   win->lock();
00465   scroll_checkbox->setNowChecked(on);
00466   win->unlock();
00467 }
00468 

Generated on Mon Apr 13 22:52:03 2009 by  doxygen 1.5.7.1