void Game::loadGame() { FILE *f = fopen("save.dat", "rb"); GameSave *save = new GameSave; fread(save, sizeof(*save), 1, f); gameTime = save->gameTime; points = save->points; stage = save->stage; lastMoveDeletedRow = save->lastMoveDeletedRow; lastStageUp = save->lastStageUp; nextBrickType = save->nextBrickType; saves = save->saves; if (nextBrick != nullptr) delete nextBrick; nextBrick = new Brick(nextBrickType); if (brick != nullptr) delete brick; brick = new Brick(save->brickType - 1); brick->lastPosition = V2D(save->brickPosX, save->brickPosY); brick->nextPosition = V2D(save->brickPosX, save->brickPosY + 1); for (int iy = 0; iy < map.size.y; iy++) for (int ix = 0; ix < map.size.x; ix++) map.map[iy][ix] = save->map[iy][ix]; pause = false; fclose(f); }
static void fsstat(Req *r) { int rc; FInfo fi; Aux *a = r->fid->aux; if(ptype(r->fid->qid.path) == Proot) V2D(&r->d, r->fid->qid, ""); else if(ptype(r->fid->qid.path) == Pinfo) dirgeninfo(pindex(r->fid->qid.path), &r->d); else if(ptype(r->fid->qid.path) == Pshare) V2D(&r->d, r->fid->qid, a->path +1); else{ memset(&fi, 0, sizeof fi); if(Sess->caps & CAP_NT_SMBS) rc = T2queryall(Sess, a->sp, mapfile(a->path), &fi); else rc = T2querystandard(Sess, a->sp, mapfile(a->path), &fi); if(rc == -1){ responderrstr(r); return; } I2D(&r->d, a->sp, a->path, &fi); if(Billtrog == 0) upd_names(Sess, a->sp, mapfile(a->path), &r->d); } respond(r, nil); }
void EventManager::handleEvents() { while (_eventQueueTail != _eventQueueHead) { CGE2Event e = _eventQueue[_eventQueueTail]; _vm->_mouse->_point = V2D(_vm, e._x, e._y); if (e._mask) { if (e._mask & kMouseMask) { e._spritePtr = _vm->spriteAt(_vm->_mouse->_point); e._x += (_vm->_mouse->_siz.x >> 1); e._y -= _vm->_mouse->_siz.y; if (_vm->_mouse->_hold && (e._spritePtr != _vm->_mouse->_hold)) { _vm->_mouse->_hold->touch(e._mask | kEventAttn, V2D(_vm, e._x - _vm->_mouse->_hold->_pos2D.x, e._y - _vm->_mouse->_hold->_pos2D.y), e._keyCode); } // update mouse cursor position if (e._mask & kMouseRoll) _vm->_mouse->gotoxyz(V2D(_vm, e._x, e._y)); } // activate current touched SPRITE if (e._spritePtr) { if (e._mask & kEventKeyb) e._spritePtr->touch(e._mask, _vm->_mouse->_point, e._keyCode); else e._spritePtr->touch(e._mask, _vm->_mouse->_point - e._spritePtr->_pos2D, e._keyCode); } else if (_vm->_sys) _vm->_sys->touch(e._mask, _vm->_mouse->_point, e._keyCode); // discard Text if button released if (e._mask & (kMouseLeftUp | kMouseRightUp)) _vm->killText(); } _eventQueueTail = (_eventQueueTail + 1) % kEventMax; }
Game::Game() : points(0), stage(1), lastMoveDeletedRow(false), tempSpeedUp(false), lastStageUp(0), gameTime(0), pause(false), saves(0) { map = mapArray(); map.size = V2D(10, 20); map.allocateMemory(); map.fillMap(0); brick = nextBrick = nullptr; lastPressedKey = NONE; nextBrickType = rand() % 7; pauseBox = new InfoDialogBox(); pauseBox->size = V2D(80, 50); pauseBox->answer = "PAUZA"; }
void Exit::Init(Map& World){ int x=0; int y=0; bool NotDone = true; while(NotDone){ x = rand()%(int)World.GetSize().x; y = rand()%(int)World.GetSize().y; if(World.GetTile(x,y).isTraversable()){ Loc = V2D(x,y); CurrentLoc = V2D(x,y); NotDone = false; } } }
bool Player::step(R dt) { DOPE_ASSERT(m_playerDataPtr.get()); V2D null(0,0); // normally i use a different coord system // this one has y up x right and rotates clockwise // usable fitness R fit=m_fitness; if (fit>1.0) { if (fit>R(0.90)*m_defaultDataPtr->maxfitness*m_playerDataPtr->maxfitness) fit=1.2; // fountain boost else fit=1.0; } // calculate direction if (getX()) m_direction+=R(getX())*dt*m_defaultDataPtr->rotspeed*m_playerDataPtr->rotspeed; //! calculate new speed if (getY()) { m_speed+=V2D(0,1).rot(m_direction)*R(getY())*fit*m_defaultDataPtr->acceleration*m_playerDataPtr->acceleration*dt; m_fitness-=dt*1.0/(m_defaultDataPtr->endurance*m_playerDataPtr->endurance); m_fitness=std::max(m_fitness,R(m_defaultDataPtr->minfitness*m_playerDataPtr->minfitness)); } if (m_speed==null) { // we are standing still if (m_fitness<1.0) m_fitness+=dt/(m_defaultDataPtr->recoverTime*m_playerDataPtr->recoverTime); return true; } // we are moving if (!getY()&&m_speed.length()<m_defaultDataPtr->minspeed*m_playerDataPtr->minspeed) { m_speed=null; return true; } R maxs=m_defaultDataPtr->maxspeed*m_playerDataPtr->maxspeed*fit; if (m_speed.length()>maxs) (m_speed.normalize())*=maxs; // damp the speed not in the correct direction V2D hspeed(V2D(0,1).rot(m_direction).rot90().project(m_speed)); m_speed-=hspeed*m_defaultDataPtr->hdamping*m_playerDataPtr->hdamping*dt; // damp the speed in the correct direction (only if up and down aren't pressed) if (!getY()) m_speed-=V2D(0,1).rot(m_direction).project(m_speed)*m_defaultDataPtr->vdamping*m_playerDataPtr->vdamping*dt; m_pos+=m_speed*dt; return true; }
/** * Find the overlap of the inputWS with the given polygon * @param oldAxis1 :: Axis 1 bin boundaries from the input grid * @param oldAxis2 :: Axis 2 bin boundaries from the input grid * @param newPoly :: The new polygon to test * @returns A list of intersection locations with weights of the overlap */ std::vector<SofQW2::BinWithWeight> SofQW2::findIntersections(API::MatrixWorkspace_const_sptr inputWS, const Geometry::ConvexPolygon & newPoly) const { const MantidVec & oldAxis1 = inputWS->readX(0); // Find the X boundaries const double xn_lo(newPoly[0].X()), xn_hi(newPoly[2].X()); MantidVec::const_iterator start_it = std::upper_bound(oldAxis1.begin(), oldAxis1.end(), xn_lo); MantidVec::const_iterator end_it = std::upper_bound(oldAxis1.begin(), oldAxis1.end(), xn_hi); size_t start_index(0), end_index(oldAxis1.size() - 1); if( start_it != oldAxis1.begin() ) { start_index = (start_it - oldAxis1.begin() - 1); } if( end_it != oldAxis1.end() ) { end_index = end_it - oldAxis1.begin(); } const double yn_lo(newPoly[0].Y()), yn_hi(newPoly[1].Y()); std::vector<BinWithWeight> overlaps; overlaps.reserve(5); // Have a guess at a possible limit std::list<QRangeCache>::const_iterator iend = m_qcached.end(); for(std::list<QRangeCache>::const_iterator itr = m_qcached.begin(); itr != iend; ++itr) { for(size_t j = start_index; j < end_index; ++j) { const double xo_lo(oldAxis1[j]), xo_hi(oldAxis1[j+1]); const QValues & qold = itr->qValues[j]; if( qold.upperLeft < yn_lo || qold.upperRight < yn_lo || qold.lowerLeft > yn_hi || qold.lowerRight > yn_hi ) continue; Quadrilateral oldPoly(V2D(xo_lo, qold.lowerLeft), V2D(xo_hi, qold.lowerRight), V2D(xo_hi, qold.upperRight), V2D(xo_lo, qold.upperLeft)); try { ConvexPolygon overlap = intersectionByLaszlo(newPoly, oldPoly); // std::cerr << "Areas " << newPoly << " " << oldPoly << "\n"; // std::cerr << "Areas " << overlap.area() << " " << oldPoly.area() << "\n"; overlaps.push_back(BinWithWeight(itr->wsIndex,j,itr->weight*overlap.area()/oldPoly.area())); } catch(Geometry::NoIntersectionException &) {} } } return overlaps; }
shape& shapeSetting::createShape() { int size = points.size(); float *p_c = new float[size]; V2D *p_s = new V2D[size]; scalev = scale->value(); for (int i = 0; i < size; ++i) { p_c[i] = points[i]->coe->value(); p_s[i] = V2D(points[i]->x * scalev, points[i]->y * scalev); } sp[shape::C_C] = pc->value(); sp.setShape(p_c, polygen(p_s, p_s+size)); //apply->setEnabled(false); reset->setEnabled(false); emit valueChanged(false); emit finished(true); //emit sendShape(sp); delete p_c; delete p_s; return sp; }
void Mouse::newMouse(Common::Event &event) { if (!_active) return; CGE2Event &evt = _vm->_eventManager->getNextEvent(); evt._x = event.mouse.x; evt._y = event.mouse.y; evt._keyCode = Common::KEYCODE_INVALID; evt._spritePtr = _vm->spriteAt(V2D(_vm, evt._x, evt._y)); switch (event.type) { case Common::EVENT_MOUSEMOVE: evt._mask = kMouseRoll; break; case Common::EVENT_LBUTTONDOWN: evt._mask = kMouseLeftDown; _buttons |= 1; break; case Common::EVENT_LBUTTONUP: evt._mask = kMouseLeftUp; _buttons &= ~1; break; case Common::EVENT_RBUTTONDOWN: evt._mask = kMouseRightDown; _buttons |= 2; break; case Common::EVENT_RBUTTONUP: evt._mask = kMouseRightUp; _buttons &= ~2; break; default: break; } }
void CSetSplitsDlg::GetSplitPoint(int x, SplitPoints szTempSplit, HWND hWnd) { // Fill in the S/F vectors for this lap StartFinish* pSF = (StartFinish*)m_pLap->GetLap()->GetSF(); if (szTempSplit.m_sfSectorTime >= m_sfLapOpts->m_SplitPoints[x-1].m_sfSectorTime && m_sfLapOpts->m_SplitPoints[x-1].m_sfSectorTime) { // Assign the highlighted time into the latest SF data m_sfLapOpts->m_SplitPoints[x] = szTempSplit; // Compute and load the Time Difference for this sector into the SF data m_sfLapOpts->m_SplitPoints[x].m_sfSplitTime = szTempSplit.m_sfSplitTime - m_sfLapOpts->m_SplitPoints[x-1].m_sfSplitTime; pSF[x].m_pt1 = V2D(m_sfLapOpts->m_SplitPoints[x].m_sfXPoint,m_sfLapOpts->m_SplitPoints[x].m_sfYPoint); pSF[x].m_pt2 = V2D(m_sfLapOpts->m_SplitPoints[x].m_sfXPoint,m_sfLapOpts->m_SplitPoints[x].m_sfYPoint); } else { MessageBox(hWnd, L"Sector point is earlier than previous.\nPlease Re-pick or re-assign",L"ERROR",MB_OK); } }
bool Line::collide(const Line &o, R &cp) { V2D ov = V2D(o.m_v); V2D ovn = V2D(o.m_vn); V2D oa = V2D(o.m_a); R t1 = m_v[0]*ovn[1]-m_v[1]*ovn[0]; R t2 = ov[0]*m_vn[1]-ov[1]*m_vn[0]; if (t1 == 0) return false; if (t2 == 0) return false; R n1 = ovn[0]*(oa[1]-m_a[1]) - ovn[1]*(oa[0]-m_a[0]); R n2 = m_vn[0]*(m_a[1]-oa[1]) - m_vn[1]*(m_a[0]-oa[0]); cp = -m_l*n1/t1; R cp2 = -o.m_l*n2/t2; if (((cp>=0) && (cp<=m_l)) && ((cp2>=0) && (cp2<=o.m_l))) return true; else return false; }
SoccerPitch::SoccerPitch(int cx, int cy): m_cxClient(cx), m_cyClient(cy), m_bPaused(false) { //GoalWidth指的是得分區厚度 int GoalWidth = 200; m_pPlayingArea = new Region(20, 20, cx-20, cy-20); // m_pRedGoal = new Goal(V2D(m_pPlayingArea->Left(), (cy-GoalWidth)/2), V2D(m_pPlayingArea->Left(), cy - (cy-GoalWidth)/2), V2D(1,0)); m_pBlueGoal = new Goal(V2D( m_pPlayingArea->Right(), (cy-GoalWidth)/2), V2D(m_pPlayingArea->Right(), cy - (cy-GoalWidth)/2), V2D(-1,0)); //建立外牆 V2D TopLeft(m_pPlayingArea->Left(), m_pPlayingArea->Top()); V2D TopRight(m_pPlayingArea->Right(), m_pPlayingArea->Top()); V2D BottomRight(m_pPlayingArea->Right(), m_pPlayingArea->Bottom()); V2D BottomLeft(m_pPlayingArea->Left(), m_pPlayingArea->Bottom()); m_vecWalls.push_back(Wall(BottomLeft, m_pRedGoal->RightPost())); m_vecWalls.push_back(Wall(m_pRedGoal->LeftPost(), TopLeft)); m_vecWalls.push_back(Wall(TopLeft, TopRight)); m_vecWalls.push_back(Wall(TopRight, m_pBlueGoal->LeftPost())); m_vecWalls.push_back(Wall(m_pBlueGoal->RightPost(), BottomRight)); m_vecWalls.push_back(Wall(BottomRight, BottomLeft)); }
void SoccerPitch::Render() { ngdi->TransparentText(); ngdi->HollowBrush(); //畫草地 ngdi->DarkGreenPen(); ngdi->DarkGreenBrush(); ngdi->Rect(V2D(0,0),V2D(m_cxClient, m_cyClient)); //畫球門 ngdi->HollowBrush(); ngdi->RedPen(); ngdi->Rect(V2D(m_pPlayingArea->Left(), (m_cyClient-m_pBlueGoal->GoalWidth())/2), V2D(m_pPlayingArea->Left()+40, m_cyClient - (m_cyClient-m_pBlueGoal->GoalWidth())/2)); ngdi->BluePen(); ngdi->Rect(V2D(m_pPlayingArea->Right(), (m_cyClient-m_pRedGoal->GoalWidth())/2), V2D(m_pPlayingArea->Right()-40, m_cyClient - (m_cyClient-m_pRedGoal->GoalWidth())/2)); //render the pitch markings //畫球場中間圓線 ngdi->WhitePen(); ngdi->Circle(m_pPlayingArea->Center(), m_pPlayingArea->Width() * 0.125); //畫球場中線 ngdi->Line(V2D(m_pPlayingArea->Center().x, m_pPlayingArea->Top()), V2D(m_pPlayingArea->Center().x, m_pPlayingArea->Bottom())); ngdi->WhiteBrush(); //畫球場中間小圓 ngdi->Circle(m_pPlayingArea->Center(), 2.0); //the ball //gdi->WhitePen(); //gdi->WhiteBrush(); //m_pBall->Render(); //Render the teams //m_pRedTeam->Render(); //m_pBlueTeam->Render(); //render the walls ngdi->WhitePen(); for (unsigned int w=0; w<m_vecWalls.size(); ++w) { m_vecWalls[w].Render(); } //show the score ngdi->TextColor(NEOgdi::red); //gdi->TextAtPos((m_cxClient/2)-50, m_cyClient-18, "Red: " + ttos(m_pBlueGoal->NumGoalsScored())); ngdi->TextAtPos((m_cxClient/2)-50, m_cyClient-18, L"Red: " + ttos(99)); ngdi->TextColor(NEOgdi::blue); //ngdi->TextAtPos((m_cxClient/2)+10, m_cyClient-18, "Blue: " + ttos(m_pRedGoal->NumGoalsScored())); ngdi->TextAtPos((m_cxClient/2)+10, m_cyClient-18, L"Blue: " + ttos(99)); }
int main(int argc, char* argv[]) { std::vector<V2D> vpoly; R r; int i=1; std::cout << "arg " << argc << std::endl; for(i=1; i< argc-2; i+=2) { vpoly.push_back( V2D(atof(argv[i]), atof(argv[i+1])) ); std::cout << "i " << vpoly.back() << std::endl; } V2D a(atof(argv[i]), atof(argv[i+1])); std::cout << "a: " << a << std::endl; Poly poly(vpoly); std::cout << "in polygon: " << poly.inside(a) << std::endl; return 0; }
Exit::Exit(){ Scale = 1; Loc = V2D(0,0); CurrentLoc = V2D(0,0); }
V2D Lens:: profile(const double alpha) const { const double r = Radius__(alpha); return V2D(r*Sin(alpha),Radius__(0)-r*Cos(alpha)); }
void World::setFromMesh(const Mesh &mesh) { // DOPE_WARN("called"); // this does not have to be fast since it is called only once or twice ;-) // copy all vertices m_vertices=mesh.vertices; m_startPoints=mesh.startPoints; m_startObjects=mesh.startObjects; // calculate bounding box R big=999999999999; // todo m_topLeft=V2D(big,-big); m_bottomRight=V2D(-big,big); for (unsigned i=0;i<m_vertices.size();++i){ m_topLeft=V2D(std::min(m_topLeft[0],m_vertices[i][0]), std::max(m_topLeft[1],m_vertices[i][1])); m_bottomRight=V2D(std::max(m_bottomRight[0],m_vertices[i][0]), std::min(m_bottomRight[1],m_vertices[i][1])); } // constuct our new edge-list typedef std::pair<Edge::VID,Edge::VID> Key; typedef FWEdge::EID Value; // first edge ID of the current room FWEdge::EID fe; // the first edge was clockwise bool feCW; // the ID of the last edge we visisted FWEdge::EID lastID=FWEdge::noEdge; // the last edge was clockwise bool lastCW; // half edges already stored std::map<Key,Value> stored; for (Mesh::EID ce=0;ce<mesh.edgelist.size();++ce) { if (mesh.edgelist[ce].vid==-1) continue; // first edge of room bool firstEdge=(lastID==FWEdge::noEdge); // next edge in this room Mesh::EID ne=mesh.getNCW(ce); // is this the "last" edge of this room ? bool leor=mesh.lastEdgeOfRoom(ce); // if it is the first edge remember this id // we assume that all rooms are in clockwise or counter clockwise order // each edge is visited in both directions or only once (borders) std::map<Key,Value>::const_iterator it(stored.find(Key(mesh.edgelist[ne].vid,mesh.edgelist[ce].vid))); // \todo clean it up this is nearly twice if (it!=stored.end()) { // we visited this edge already - set current full winged edge Value cfweID=it->second; if (firstEdge) { fe=cfweID; // todo here is a bug? (if the first edge is not CW there is a bug) feCW=false; } FWEdge &cfwe=m_edges[cfweID]; // cfwe.m_nccw=; if (!firstEdge) { cfwe.m_pccw=lastID; if (lastCW) m_edges[lastID].m_ncw=cfweID; else m_edges[lastID].m_nccw=cfweID; } cfwe.m_rccw=m_rooms.size(); cfwe.m_etccw=mesh.edgelist[ce].type; if (leor) { // we finished this room if (feCW) m_edges[fe].m_pcw=cfweID; else m_edges[fe].m_pccw=cfweID; cfwe.m_nccw=fe; Room newRoom; newRoom.m_e=fe; newRoom.m_cw=feCW; m_rooms.push_back(newRoom); fe=lastID=FWEdge::noEdge; }else{ lastID=cfweID; lastCW=false; } } else { // we did not visit this edge yet // the id of the new edge FWEdge::EID newID=m_edges.size(); if (firstEdge) { fe=newID; feCW=true; } // fill in the things we know already FWEdge newEdge; newEdge.m_sv=mesh.edgelist[ce].vid; newEdge.m_ev=mesh.edgelist[ne].vid; // if it is the first edge we have to fill this in later if (!firstEdge) { newEdge.m_pcw=lastID; if (lastCW) m_edges[lastID].m_ncw=newID; else m_edges[lastID].m_nccw=newID; } // we don't know yet but the constructor initialized to noEdge/noRoom // newEdge.m_ncw=FWEdge::noEdge; // newEdge.m_nccw=FWEdge::noEdge; // newEdge.m_pccw=FWEdge::noEdge; newEdge.m_rcw=m_rooms.size(); newEdge.m_etcw=mesh.edgelist[ce].type; // newEdge.m_rccw=FWEdge::noRoom; if (leor) { // we finished this room if (feCW) m_edges[fe].m_pcw=newID; else m_edges[fe].m_pccw=newID; newEdge.m_ncw=fe; Room newRoom; newRoom.m_e=fe; newRoom.m_cw=feCW; m_rooms.push_back(newRoom); fe=lastID=FWEdge::noEdge; }else{ lastID=newID; lastCW=true; } // calculate corresponding wall DOPE_ASSERT(newEdge.m_sv<m_vertices.size()&&newEdge.m_ev<m_vertices.size()); newEdge.m_wall=Wall(Line(m_vertices[newEdge.m_sv],m_vertices[newEdge.m_ev])); m_edges.push_back(newEdge); stored[Key(mesh.edgelist[ce].vid,mesh.edgelist[ne].vid)]=newID; // std::cout << "Stored "<<mesh.edgelist[ce].vid<<","<<mesh.edgelist[ne].vid<<std::endl; } } for (unsigned r=0;r<m_rooms.size();++r) { m_rooms[r].m_poly=getLineLoop(r); // loop through edges of this room EdgeIterator end(*this); for (EdgeIterator it(*this,r);it!=end;++it) { if (it.getEdge().isDoor()) continue; m_rooms[r].m_walls.push_back(it.getEdge().m_wall); m_rooms[r].m_eids.push_back(it.getID()); } } }
void Game::render(SDL_Surface *screen, SDL_Surface *brickParts[]) { for (int iy = 0; iy < map.size.y; iy++) for (int ix = 0; ix < map.size.x; ix++) if (map.map[iy][ix] >= 1 && map.map[iy][ix] <= 7) DrawSurface(screen, brickParts[map.map[iy][ix] - 1], 36 + ix * BRICK_SIZE, 36 + iy * BRICK_SIZE + PADDING_TOP); if (brick != nullptr) for (int iy = 0; iy < brick->map.size.y; iy++) for (int ix = 0; ix < brick->map.size.x; ix++) if(brick->map.map[iy][ix] != 0) DrawSurface(screen, brickParts[brick->brickType->type - 1], (brick->position.x + brick->brickType->getVectorFromCenter(V2D(ix, iy)).x + 1) * BRICK_SIZE + 12, (brick->position.y + brick->brickType->getVectorFromCenter(V2D(ix, iy)).y + 1) * BRICK_SIZE + PADDING_TOP + 12); if (nextBrick != nullptr) for (int iy = 0; iy < nextBrick->map.size.y; iy++) for (int ix = 0; ix < nextBrick->map.size.x; ix++) if (nextBrick->map.map[iy][ix] != 0) DrawSurface(screen, brickParts[nextBrick->brickType->type - 1], (16 + nextBrick->brickType->getVectorFromCenter(V2D(ix, iy)).x) * BRICK_SIZE + 12, (8 + nextBrick->brickType->getVectorFromCenter(V2D(ix, iy)).y) * BRICK_SIZE + PADDING_TOP); printGameTime(screen); if (pause) { pauseBox->render(); } }
static int dirgen(int slot, Dir *d, void *aux) { long off; FInfo *fi; int rc, got; Aux *a = aux; char *npath; int numinf = numinfo(); int slots; slots = 128; /* number of dir entries to fetch at one time */ if(strcmp(a->path, "/") == 0){ if(slot < numinf){ dirgeninfo(slot, d); return 0; } else slot -= numinf; if(slot >= Nshares) return -1; V2D(d, mkqid(Shares[slot].name, 1, 1, Pshare, slot), Shares[slot].name); return 0; } off = slot * sizeof(FInfo); if(off >= a->off && off < a->end && time(nil) < a->expire) goto from_cache; if(off == 0){ fi = (FInfo *)a->cache; npath = smprint("%s/*", mapfile(a->path)); a->sh = T2findfirst(Sess, a->sp, slots, npath, &got, &a->srch, (FInfo *)a->cache); free(npath); if(a->sh == -1) return -1; a->off = 0; a->end = got * sizeof(FInfo); if(got >= 2 && strcmp(fi[0].name, ".") == 0 && strcmp(fi[1].name, "..") == 0){ a->end = (got - 2) * sizeof(FInfo); memmove(a->cache, a->cache + sizeof(FInfo)*2, a->end - a->off); } } while(off >= a->end && a->sh != -1){ fi = (FInfo *)(a->cache + (a->end - a->off) - sizeof(FInfo)); a->off = a->end; npath = smprint("%s/%s", mapfile(a->path), fi->name); rc = T2findnext(Sess, a->sp, slots, npath, &got, &a->srch, (FInfo *)a->cache, a->sh); free(npath); if(rc == -1 || got == 0) break; a->end = a->off + got * sizeof(FInfo); } a->expire = time(nil) + CACHETIME; if(got < slots){ if(a->sh != -1) CIFSfindclose2(Sess, a->sp, a->sh); a->sh = -1; } if(off >= a->end) return -1; from_cache: fi = (FInfo *)(a->cache + (off - a->off)); npath = smprint("%s/%s", mapfile(a->path), fi->name); I2D(d, a->sp, npath, fi); if(Billtrog == 0) upd_names(Sess, a->sp, npath, d); free(npath); return 0; }
void Game::update(double delta) { if (pause) return; gameTime += delta; if (stage < 10) { lastStageUp += delta; if (lastStageUp > STAGE_UP_TIME) { stage++; lastStageUp -= STAGE_UP_TIME; } } if (brick != nullptr) { // Opadanie klocka brick->update(delta); if (brick->isInCollision(SOUTH)) { for (int iy = 0; iy < brick->map.size.y; iy++) { for (int ix = 0; ix < brick->map.size.x; ix++) { if (brick->map.map[iy][ix] > 0) { Vector2D pos = brick->lastPosition + brick->brickType->getVectorFromCenter(V2D(ix, iy)); if (pos.y >= 0) map.map[int(pos.y)][int(pos.x)] = brick->brickType->type; else { pause = true; if (Window::getInstance()->ranking->getPlace(points) != -1) { Window::getInstance()->showWindow(InputNameToRanking); } else { Window::getInstance()->showWindow(FinishGame); } return; } } } } // Usuwanie pelnych wierszy int removedRows = 0; for (int iy = 0; iy < map.size.y; iy++) { bool toRemove = true; for (int ix = 0; ix < map.size.x; ix++) { if (map.map[iy][ix] == 0) toRemove = false; } if (toRemove) { removedRows++; for (int py = iy; py > 0; py--) { for (int ix = 0; ix < map.size.x; ix++) { map.map[py][ix] = map.map[py - 1][ix]; } } } } // Punktowanie usuwania wierszy switch (removedRows) { case 1: points += 100 * (stage + 1); lastMoveDeletedRow = false; break; case 2: points += 200 * (stage + 1); lastMoveDeletedRow = false; break; case 3: points += 400 * (stage + 1); lastMoveDeletedRow = false; break; case 4: { if (lastMoveDeletedRow) { points += 1200 * (stage + 1); } else { lastMoveDeletedRow = true; points += 800 * (stage + 1); } break; } } tempSpeedUp = false; delete brick; brick = new Brick(nextBrickType); nextBrickType = rand() % 7; delete nextBrick; nextBrick = new Brick(nextBrickType); } } else { brick = new Brick(nextBrickType); nextBrickType = rand() % 7; nextBrick = new Brick(nextBrickType); } }
LRESULT CSetSplitsDlg::DlgProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { HWND hWnd_OGL = GetDlgItem(hWnd,IDC_LBLSPLITMAP); float dBestLength = -1; static float dTimeToHighlight = -1; static TimePoint2D ptBest; static MAPHIGHLIGHT mapPt; POINT m_ptMouse = {0}; bool m_fMouseValid = false; static SplitPoints szTempSplit = {0}; enum SPLITS { START, SPLIT1, SPLIT2, SPLIT3, SPLIT4, SPLIT5, SPLIT6, SPLIT7, SPLIT8, FINISH }; if(p_sfRefLapPainter.HandleMessage(hWnd_OGL,uMsg,wParam,lParam)) { return 0; } switch(uMsg) { case WM_INITDIALOG: { // Get the Start time for the lap and store it int x = START; StartFinish* pSF = (StartFinish*)m_pLap->GetLap()->GetSF(); const vector<TimePoint2D>& lstPoints = m_pLap->GetPoints(); { const TimePoint2D& p = lstPoints[x]; m_sfLapOpts->m_SplitPoints[x].m_sfSectorTime = p.iTime; m_sfLapOpts->m_SplitPoints[x].m_sfXPoint = p.flX; m_sfLapOpts->m_SplitPoints[x].m_sfYPoint = p.flY; pSF[x].m_pt1 = V2D(m_sfLapOpts->m_SplitPoints[x].m_sfXPoint,m_sfLapOpts->m_SplitPoints[x].m_sfYPoint); pSF[x].m_pt2 = V2D(m_sfLapOpts->m_SplitPoints[x].m_sfXPoint,m_sfLapOpts->m_SplitPoints[x].m_sfYPoint); } x = FINISH; { const TimePoint2D& p = lstPoints[lstPoints.size()-1]; m_sfLapOpts->m_SplitPoints[x].m_sfSectorTime = p.iTime; m_sfLapOpts->m_SplitPoints[x].m_sfXPoint = p.flX; m_sfLapOpts->m_SplitPoints[x].m_sfYPoint = p.flY; pSF[x].m_pt1 = V2D(m_sfLapOpts->m_SplitPoints[x].m_sfXPoint,m_sfLapOpts->m_SplitPoints[x].m_sfYPoint); pSF[x].m_pt2 = V2D(m_sfLapOpts->m_SplitPoints[x].m_sfXPoint,m_sfLapOpts->m_SplitPoints[x].m_sfYPoint); } // Show the split points m_sfLapOpts->fDrawSplitPoints = true; // The the OGL handle p_sfRefLapPainter.Init(hWnd_OGL); p_sfRefLapPainter.DrawLapLines(*m_sfLapOpts); // draws laps as a map return TRUE; } /* case WM_MOUSEMOVE: { POINT ptLastMouse = m_ptMouse; RECT rcParent,rcThis; GetWindowRect(GetParent(hWnd_OGL),&rcParent); GetWindowRect(hWnd_OGL,&rcThis); m_ptMouse.x = LOWORD(wParam); m_ptMouse.y = HIWORD(wParam); m_ptMouse.x -= (rcThis.left - rcParent.left); m_ptMouse.y -= (rcThis.top - rcParent.top); RECT rcClient; GetClientRect(hWnd_OGL, &rcClient); RECT rcParentClient; GetClientRect(GetParent(hWnd_OGL), &rcParentClient); // the difference between rcParent and rcParentClient's height will be the height of the title bar m_ptMouse.y += (RECT_HEIGHT(&rcParent) - RECT_HEIGHT(&rcParentClient)); m_ptMouse.y = RECT_HEIGHT(&rcClient) - m_ptMouse.y; bool fLastMouseValid = m_fMouseValid; m_fMouseValid = m_ptMouse.x >= 0 && m_ptMouse.y >= 0 && m_ptMouse.x < RECT_WIDTH(&rcClient) && m_ptMouse.y < RECT_HEIGHT(&rcClient); return FALSE; } */ case WM_LBUTTONDOWN: { int iTime = -1; POINT ptMouse; Vector2D vHighlight; const vector<TimePoint2D>& lstPoints = m_pLap->GetPoints(); if (p_sfRefLapPainter.GetMouse(&ptMouse)) { // We need to convert from Window space to Map space and find closest point iTime = GetLapHighlightTime((const CExtendedLap *)m_pLap); } if (iTime > 0) { GLdouble dX=0,dY=0,dZ=0; for(int x = 0; x< lstPoints.size(); x++) { const TimePoint2D& p = lstPoints[x]; if (p.iTime >= iTime) { dX = lstPoints[x].flX; dY = lstPoints[x].flY; ptBest = p; vHighlight = V2D((float)dX,(float)dY); szTempSplit.m_sfSectorTime = ptBest.iTime; szTempSplit.m_sfXPoint = ptBest.flX; szTempSplit.m_sfYPoint = ptBest.flY; break; } } } return TRUE; } case WM_NOTIFY: { p_sfRefLapPainter.DrawLapLines(*m_sfLapOpts); // draws laps as a map NMHDR* notifyHeader = (NMHDR*)lParam; switch(wParam) { case IDC_LAPS: { return TRUE; } default: return TRUE; } } case WM_COMMAND: { switch(LOWORD(wParam)) { case IDC_SETSPLIT1: { // Get the Finish time for the lap and store it and fill in the S/F vectors for this lap GetSplitPoint(SPLIT1, szTempSplit, hWnd); m_sfLapOpts->fDrawSplitPoints = true; return TRUE; } case IDC_SETSPLIT2: { // Get the Finish time for the lap and store it and fill in the S/F vectors for this lap GetSplitPoint(SPLIT2, szTempSplit, hWnd); m_sfLapOpts->fDrawSplitPoints = true; return TRUE; } case IDC_SETSPLIT3: { // Get the Finish time for the lap and store it and fill in the S/F vectors for this lap GetSplitPoint(SPLIT3, szTempSplit, hWnd); m_sfLapOpts->fDrawSplitPoints = true; return TRUE; } case IDC_SETSPLIT4: { // Get the Finish time for the lap and store it and fill in the S/F vectors for this lap GetSplitPoint(SPLIT4, szTempSplit, hWnd); m_sfLapOpts->fDrawSplitPoints = true; return TRUE; } case IDC_SETSPLIT5: { // Get the Finish time for the lap and store it and fill in the S/F vectors for this lap GetSplitPoint(SPLIT5, szTempSplit, hWnd); m_sfLapOpts->fDrawSplitPoints = true; return TRUE; } case IDC_SETSPLIT6: { // Get the Finish time for the lap and store it and fill in the S/F vectors for this lap GetSplitPoint(SPLIT6, szTempSplit, hWnd); m_sfLapOpts->fDrawSplitPoints = true; return TRUE; } case IDC_SETSPLIT7: { // Get the Finish time for the lap and store it and fill in the S/F vectors for this lap GetSplitPoint(SPLIT7, szTempSplit, hWnd); m_sfLapOpts->fDrawSplitPoints = true; return TRUE; } case IDC_SETSPLIT8: { // Get the Finish time for the lap and store it and fill in the S/F vectors for this lap GetSplitPoint(SPLIT8, szTempSplit, hWnd); m_sfLapOpts->fDrawSplitPoints = true; return TRUE; } case IDOK: { ComputeSectors(); // Load Sector times into sfLapOpts m_pResults->fCancelled = false; EndDialog(hWnd,0); return TRUE; } case IDRESET: { for (int x=1; x < 50; x++) { m_sfLapOpts->m_SplitPoints[x].m_sfXPoint = 0.0f; m_sfLapOpts->m_SplitPoints[x].m_sfYPoint = 0.0f; m_sfLapOpts->m_SplitPoints[x].m_sfSectorTime = 0; m_sfLapOpts->m_SplitPoints[x].m_sfSplitTime = 0.0f; } StartFinish* pSF = (StartFinish*)m_pLap->GetLap()->GetSF(); for (int x=0; x < 50; x++) { pSF[x].m_pt1 = V2D(m_sfLapOpts->m_SplitPoints[x].m_sfXPoint,m_sfLapOpts->m_SplitPoints[x].m_sfYPoint); pSF[x].m_pt2 = V2D(m_sfLapOpts->m_SplitPoints[x].m_sfXPoint,m_sfLapOpts->m_SplitPoints[x].m_sfYPoint); } m_sfLapOpts->fDrawSplitPoints = false; return TRUE; } case IDCANCEL: m_pResults->fCancelled = true; EndDialog(hWnd,0); return TRUE; } break; } // end WM_COMMAND case WM_CLOSE: { m_pResults->fCancelled = true; EndDialog(hWnd,0); break; } } p_sfRefLapPainter.Refresh(); // Allow the Set Split Point window its own highlighter return FALSE; }
/** * Distance (R) between two points defined as vectors * @param other :: A second vector * @returns The distance between the two points */ double V2D::distance(const V2D &other) const { return V2D(m_x - other.m_x, m_y - other.m_y).norm(); }
void CLapPainter::DrawLapLines(const LAPSUPPLIEROPTIONS& sfLapOpts) { FLOATRECT rcAllLaps = m_pLapSupplier->GetAllLapsBounds(); RECT rcClient; GetClientRect(OGL_GetHWnd(), &rcClient); double dClientAspect = ((double)RECT_WIDTH(&rcClient)) / ((double)RECT_HEIGHT(&rcClient)); double dMapAspect = abs(RECT_WIDTH(&rcAllLaps)) / abs(RECT_HEIGHT(&rcAllLaps)); if(dClientAspect > dMapAspect) { // the window is wider than the map is. we'll want to widen the map space we show appropriately const double dCentreX = (rcAllLaps.left + rcAllLaps.right)/2; rcAllLaps.left -= dCentreX; rcAllLaps.right -= dCentreX; rcAllLaps.left *= (dClientAspect / dMapAspect); rcAllLaps.right *= (dClientAspect / dMapAspect); rcAllLaps.left += dCentreX; rcAllLaps.right += dCentreX; } else { // the window is taller than the map points are. we'll want to tallen map bounds const double dCentreY = (rcAllLaps.top + rcAllLaps.bottom)/2; rcAllLaps.top -= dCentreY; rcAllLaps.bottom -= dCentreY; rcAllLaps.top *= (dMapAspect / dClientAspect); rcAllLaps.bottom *= (dMapAspect / dClientAspect); rcAllLaps.top += dCentreY; rcAllLaps.bottom += dCentreY; } // we have now determined the bounds of the thing we're going to draw, let's draw it glPushMatrix(); glLoadIdentity(); glScalef(1.0f, 1.0f, 1.0f); // Scale it so that it fills up the window. glOrtho(rcAllLaps.left, rcAllLaps.right,rcAllLaps.bottom,rcAllLaps.top, -1.0,1.0); // Set up the non-zoomed/panned view for the map GLdouble rgModelviewMatrix[16]; GLdouble rgProjMatrix[16]; GLint rgViewport[4]; { // Now that the matrices are correct, let's graph them. glGetDoublev(GL_MODELVIEW_MATRIX, rgModelviewMatrix); glGetDoublev(GL_PROJECTION_MATRIX, rgProjMatrix); glGetIntegerv(GL_VIEWPORT, rgViewport); const double dCenterX = (rcAllLaps.left + rcAllLaps.right)/2; const double dCenterY = (rcAllLaps.top + rcAllLaps.bottom)/2; double dScaleAmt = pow(1.06,sfLapOpts.iZoomLevels); POINT ptMouse; if(GetMouse(&ptMouse) && m_pLapSupplier->IsHighlightSource(m_iSupplierId)) { // the mouse is in our window, so let's enable panning and zooming! const double dTranslateShiftX = (rcAllLaps.left + rcAllLaps.right)/2; const double dTranslateShiftY = (rcAllLaps.top + rcAllLaps.bottom)/2; double dScaleAmt = pow(1.06,sfLapOpts.iZoomLevels); GLdouble dXShift,dYShift,dZ; // Project the window shift stuff so we know how far to translate the view gluUnProject(sfLapOpts.flWindowShiftX/dScaleAmt,sfLapOpts.flWindowShiftY/dScaleAmt,0,rgModelviewMatrix,rgProjMatrix,rgViewport,&dXShift,&dYShift,&dZ); // Set up to perform the ZOOM function for MAP. glTranslated(dTranslateShiftX,dTranslateShiftY,0); // Translate the map to origin glScaled(dScaleAmt,dScaleAmt,dScaleAmt); // Scale the sucker glTranslated(-dTranslateShiftX,-dTranslateShiftY,0); // Now put the map back in its place glTranslated(dXShift-rcAllLaps.left,dYShift-rcAllLaps.bottom,0); // Now let's allow it to pan // now having shifted, let's get our new model matrices glGetDoublev(GL_MODELVIEW_MATRIX, rgModelviewMatrix); glGetDoublev(GL_PROJECTION_MATRIX, rgProjMatrix); glGetIntegerv(GL_VIEWPORT, rgViewport); } } POINT ptMouse; Vector2D vHighlight; if(GetMouse(&ptMouse) && m_pLapSupplier->IsHighlightSource(m_iSupplierId)) { // the mouse is in our window... we make our own highlighter GLdouble dX,dY,dZ; gluUnProject(ptMouse.x,ptMouse.y,0,rgModelviewMatrix,rgProjMatrix,rgViewport,&dX,&dY,&dZ); vHighlight = V2D((float)dX,(float)dY); } vector<MAPHIGHLIGHT> lstMousePointsToDraw; vector<CExtendedLap*> lstLaps = m_pLapSupplier->GetLapsToShow(); for(int x = 0; x < lstLaps.size(); x++) { CExtendedLap* pLap = lstLaps[x]; srand((int)pLap); // <-- makes sure that we randomize the colours consistently, so that lap plots don't change colour from draw to draw... float dBestLength = -1; float dTimeToHighlight = -1; TimePoint2D ptBest; if(sfLapOpts.fDrawLines) { glLineWidth(2); // Added by KDJ. Sets the width of the line to draw. glBegin(GL_LINE_STRIP); } else { glPointSize(4.0f); glBegin(GL_POINTS); } float r; float g; float b; MakeColor ( pLap, &r, &g, &b ); // Function picks color to use and tells opengl to draw the following in the colour we just made up const vector<TimePoint2D>& lstPoints = pLap->GetPoints(); for(int x = 0; x< lstPoints.size(); x++) { const TimePoint2D& p = lstPoints[x]; glVertex2f(p.flX,p.flY); // if we're a highlight source, try to figure out the closest point for this lap if(m_pLapSupplier->IsHighlightSource(m_iSupplierId)) { Vector2D vPt = V2D(p.flX,p.flY); Vector2D vDiff = vPt - vHighlight; if(vDiff.Length() < dBestLength || dBestLength < 0) { dBestLength = vDiff.Length(); dTimeToHighlight = p.iTime; ptBest = p; } } else { int iTime = m_pLapSupplier->GetLapHighlightTime(pLap); if(abs(p.iTime - iTime) < dBestLength || dBestLength < 0) { dBestLength = abs(p.iTime - iTime); ptBest = p; dTimeToHighlight = iTime; } } } // for each lap, draw an indicator of the closest thing to the mouse if(!m_pLapSupplier->IsHighlightSource(m_iSupplierId)) { // if we're not a source, use the given time to highlight dTimeToHighlight = m_pLapSupplier->GetLapHighlightTime(pLap); } else { m_pLapSupplier->SetLapHighlightTime(pLap, (int)dTimeToHighlight); } // project from unit-space (the map) to window-space so we know where we need to draw our highlight-box { GLdouble winx,winy,winz; gluProject(ptBest.flX, ptBest.flY, 0, rgModelviewMatrix, rgProjMatrix, rgViewport, &winx, &winy, &winz); MAPHIGHLIGHT mapPt; mapPt.pt.x = (int)winx; mapPt.pt.y = (int)winy; mapPt.pLap = pLap; lstMousePointsToDraw.push_back(mapPt); } glEnd(); } // if (pLap == m_pReferenceLap) // If this lap is the reference lap, draw the segment lines // { // draw the start-finish and segment lines if(lstLaps.size() > 0) { const CExtendedLap* pReferenceLap = lstLaps[lstLaps.size()-1]; const StartFinish* pSF = pReferenceLap->GetLap()->GetSF(); for(int x = 0;x < 3; x++) { Vector2D pt1 = pSF[x].GetPt1(); Vector2D pt2 = pSF[x].GetPt2(); glLineWidth(1); // Added by KDJ. Skinny lines for Start/Finish. glBegin(GL_LINE_STRIP); glColor3d(1.0,0.0,0.0); // Red for S/F line color glVertex2f(pt1.m_v[0],pt1.m_v[1]); glVertex2f(pt2.m_v[0],pt2.m_v[1]); glEnd(); glColor3d(1.0,0.0,0.0); LPCSTR lpszText = ""; if(x == 0) lpszText = "S1"; // Segment 1 if(x == 1) lpszText = "S2"; // Segment 2 if(x == 2) lpszText = "S/F"; // Segment 3, Start/Finish Line DrawText(pt1.m_v[0],pt1.m_v[1], lpszText); // Need to add offsets to these for them to be on the screen DrawText(pt2.m_v[0],pt2.m_v[1], lpszText); // Need to add offsets to these for them to be on the screen } } // } glPopMatrix(); // popping us out of map-coords space. /* // The idea here is to get the mouse location and find the closest reference lap point to set the sector location POINT ptMouse; Vector2D vHighlight; if(GetMouse(&ptMouse) && m_pLapSupplier->IsHighlightSource(m_iSupplierId)) { // the mouse is in our window... we make our own highlighter GLdouble dX,dY,dZ; gluUnProject(ptMouse.x,ptMouse.y,0,rgModelviewMatrix,rgProjMatrix,rgViewport,&dX,&dY,&dZ); vHighlight = V2D((float)dX,(float)dY); } float dBestLength = -1; float dTimeToHighlight = -1; TimePoint2D ptBest; const vector<TimePoint2D>& lstPoints = pLap->GetPoints(); for(int x = 0; x< lstPoints.size(); x++) { const TimePoint2D& p = lstPoints[x]; glVertex2f(p.flX,p.flY); // if we're a highlight source, try to figure out the closest point for this lap if(m_pLapSupplier->IsHighlightSource(m_iSupplierId)) { Vector2D vPt = V2D(p.flX,p.flY); Vector2D vDiff = vPt - vHighlight; if(vDiff.Length() < dBestLength || dBestLength < 0) { dBestLength = vDiff.Length(); dTimeToHighlight = p.iTime; ptBest = p; } } else { int iTime = m_pLapSupplier->GetLapHighlightTime(pLap); if(abs(p.iTime - iTime) < dBestLength || dBestLength < 0) { dBestLength = abs(p.iTime - iTime); ptBest = p; dTimeToHighlight = iTime; } } } */ if(lstMousePointsToDraw.size() > 0) { RECT rcClient; GetClientRect(OGL_GetHWnd(),&rcClient); glPushMatrix(); glLoadIdentity(); glOrtho(0, RECT_WIDTH(&rcClient),0, RECT_HEIGHT(&rcClient),-1.0,1.0); for(int x = 0; x < lstMousePointsToDraw.size(); x++) { const CExtendedLap* pLap = lstMousePointsToDraw[x].pLap; const POINT& ptWindow = lstMousePointsToDraw[x].pt; float r; float g; float b; MakeColor ( pLap, &r, &g, &b ); // Function picks color to use and tells opengl to draw the following in the colour we just made up // we also want to draw a highlighted square DrawGLFilledSquare(ptWindow.x, ptWindow.y, 5); } glPopMatrix(); // pop us from window space back to the identity } }
void CLapPainter::DrawGeneralGraph(const LAPSUPPLIEROPTIONS& sfLapOpts, bool fHighlightXAxis) { vector<CExtendedLap*> lstLaps = m_pLapSupplier->GetLapsToShow(); DATA_CHANNEL eX; eX = DATA_CHANNEL_DISTANCE; set<DATA_CHANNEL> setY; map<DATA_CHANNEL,float> mapMinY; map<DATA_CHANNEL,float> mapMaxY; float dMaxX = -1e30; float dMinX = 1e30; float dCenterOvalX = 0; float dCenterOvalY = 0; { // figuring out bounds and getting matrices all set up // First lets load up all of the data into an array and determine its size for(int x = 0;x < lstLaps.size(); x++) { CExtendedLap* pLap = lstLaps[x]; DATA_CHANNEL eDataX = m_pLapSupplier->GetXChannel(); const IDataChannel* pDataX = pLap->GetChannel(eDataX); if(!pDataX || !pDataX->IsValid() || pDataX->GetData().size() <= 0) continue; vector<DATA_CHANNEL> lstDataY = m_pLapSupplier->GetYChannels(); for(int y = 0; y < lstDataY.size(); y++) // Loop through the data channels and display them { int ValueDisplay = 0; // Flag if we should display this channel as a graph or not 0 = yes, 1 = no const IDataChannel* pChannel = pLap->GetChannel(lstDataY[y]); if(!pChannel || !pChannel->IsValid()) continue; const DATA_CHANNEL eType = lstDataY[y]; // Determine if this Data Channel is one that we only want to display the values for for (int u = 0; u < sizeof lstDataY; u++) { if (eType == m_pLapSupplier->GetDisplayOptions().m_PlotPrefs[u].iDataChannel && m_pLapSupplier->GetDisplayOptions().m_PlotPrefs[u].iPlotView == false) { // We have found a display only channel. Let's prevent the graph from displaying ValueDisplay = 1; break; } } if(mapMinY.find(eType) == mapMinY.end()) { mapMinY[eType] = min(pChannel->GetMin(),m_pLapSupplier->GetDataHardcodedMin(eType)); mapMaxY[eType] = max(pChannel->GetMax(),m_pLapSupplier->GetDataHardcodedMax(eType)); } else { mapMinY[eType] = min(pChannel->GetMin(),mapMinY[eType]); mapMaxY[eType] = max(pChannel->GetMax(),mapMaxY[eType]); } if (ValueDisplay == 0) { setY.insert(eType); } } if(pDataX) { dMaxX = max(dMaxX, pDataX->GetMax()); dMinX = min(dMinX, pDataX->GetMin()); eX = pDataX->GetChannelType(); } } } if(setY.size() <= 0) { DrawSelectLapsPrompt(); return; } RECT rcSpot; int iSegmentHeight=0; { RECT rcClient; GetClientRect(OGL_GetHWnd(), &rcClient); iSegmentHeight = RECT_HEIGHT(&rcClient) / setY.size(); rcSpot.left = 0; rcSpot.top = 0; rcSpot.right = RECT_WIDTH(&rcClient); rcSpot.bottom = iSegmentHeight; } int iPos = 0; // y-channel graphing loop start for(set<DATA_CHANNEL>::iterator i = setY.begin(); i != setY.end(); i++) { vector<HIGHLIGHTDATA> lstMousePointsToDraw; glViewport(rcSpot.left,rcSpot.top,RECT_WIDTH(&rcSpot),RECT_HEIGHT(&rcSpot)); // now we have the bounds of all the laps we've looked at, so let's draw them glPushMatrix(); glLoadIdentity(); glScalef(1.0f, 0.90f, 1.0f); // Let's scale it so that graphs don't touch each other. glOrtho(dMinX, dMaxX,mapMinY[*i], mapMaxY[*i],-1.0,1.0); // draw horizontal guide lines and text on the background. Yes this should probably go into a function, Art ;) // first draw the starting guideline { float flLine = m_pLapSupplier->GetGuideStart(*i, mapMinY[*i], mapMaxY[*i]); LineColor(); // Pick guideline color, based upon chosen color scheme glLineWidth(1); // Added by KDJ. Skinny lines for guidelines. glBegin(GL_LINE_STRIP); glVertex2f(dMinX,flLine); glVertex2f(dMaxX,flLine); glEnd(); LineColor(); // Pick guideline color, based upon chosen color scheme char szText[256]; GetChannelString(*i, sfLapOpts.eUnitPreference, flLine, szText, NUMCHARS(szText)); DrawText(dMinX, flLine, szText); } // now draw the rest of them for(float flLine = m_pLapSupplier->GetGuideStart(*i, mapMinY[*i], mapMaxY[*i]) + m_pLapSupplier->GetGuideStep(*i, mapMinY[*i], mapMaxY[*i]); flLine < mapMaxY[*i]; flLine += m_pLapSupplier->GetGuideStep(*i, mapMinY[*i], mapMaxY[*i])) { LineColor(); // Pick guideline color, based upon chosen color scheme glLineWidth(1); // Added by KDJ. Skinny lines for guidelines. glBegin(GL_LINE_STRIP); glVertex2f(dMinX,flLine); glVertex2f(dMaxX,flLine); glEnd(); LineColor(); // Pick guideline color, based upon chosen color scheme char szText[256]; GetChannelString(*i, sfLapOpts.eUnitPreference, flLine, szText, NUMCHARS(szText)); DrawText(dMinX, flLine, szText); } // draw vertical guide lines and text on the background only if at 1.0X magnification if (sfLapOpts.iZoomLevels != 0) { } else { // first draw the starting guideline { float flLine = m_pLapSupplier->GetGuideStartX(eX, dMinX, dMaxX); LineColor(); // Pick guideline color, based upon chosen color scheme glLineWidth(1); dCenterOvalX = 0.0f; // Center oval at the origin dCenterOvalY = 0.0f; // dCenterOvalX = (dMaxX - dMinX) / 2.0f + dMinX; // dCenterOvalY = (mapMaxY[*i] - mapMinY[*i]) / 2.0f + mapMinY[*i]; // If this is for drawing the Traction Circle, let's draw a circle as well (Oval really) if (eX == DATA_CHANNEL_X_ACCEL || eX == DATA_CHANNEL_Y_ACCEL || eX == DATA_CHANNEL_Z_ACCEL) { float w, h; w = 3.0f; h = 3.0f; drawOval (dCenterOvalX, dCenterOvalY, w, h); // Draw 1.5G circle w = 1.0f; h = 1.0f; drawOval (dCenterOvalX, dCenterOvalY, w, h); // Draw 0.5G circle w = 2.0f; h = 2.0f; drawOval (dCenterOvalX, dCenterOvalY, w, h); // Draw 1.0G circle // Now let's draw a vertical line at the origin glBegin(GL_LINE_STRIP); glVertex3f(0.0f,mapMinY[*i],0); glVertex3f(0.0f,mapMaxY[*i],0); glEnd(); } else { glBegin(GL_LINE_STRIP); glVertex3f(flLine,mapMinY[*i],0); glVertex3f(flLine,mapMaxY[*i],0); glEnd(); } LineColor(); // Pick guideline color, based upon chosen color scheme char szText[256]; GetChannelString(eX, sfLapOpts.eUnitPreference, flLine, szText, NUMCHARS(szText)); DrawText(flLine, mapMinY[*i]-12, szText); } // now draw the rest of them for(float flLine = m_pLapSupplier->GetGuideStartX(eX, dMinX, dMaxX) + m_pLapSupplier->GetGuideStepX(eX, dMinX, dMaxX); flLine < dMaxX; flLine += m_pLapSupplier->GetGuideStepX(eX, dMinX, dMaxX)) { LineColor(); // Pick guideline color, based upon chosen color scheme glLineWidth(1); glBegin(GL_LINE_STRIP); glVertex3f(flLine,mapMinY[*i],0); glVertex3f(flLine,mapMaxY[*i],0); glEnd(); LineColor(); // Pick guideline color, based upon chosen color scheme char szText[256]; GetChannelString(eX, sfLapOpts.eUnitPreference, flLine, szText, NUMCHARS(szText)); DrawText(flLine, mapMinY[*i]-12, szText); } } // Set up the non-zoomed/panned view for the map GLdouble rgModelviewMatrix[16]; GLdouble rgProjMatrix[16]; GLint rgViewport[4]; { // Now that the matrices are correct, let's graph them. glGetDoublev(GL_MODELVIEW_MATRIX, rgModelviewMatrix); glGetDoublev(GL_PROJECTION_MATRIX, rgProjMatrix); glGetIntegerv(GL_VIEWPORT, rgViewport); POINT ptMouse; if(GetMouse(&ptMouse) && m_pLapSupplier->IsHighlightSource(m_iSupplierId)) { // The mouse is in our window, so panning and zooming are active! const double dCenterX = (dMinX + dMaxX)/2; // Center of X for scaling transformation double dScaleAmt = pow(1.08,sfLapOpts.iZoomLevels); GLdouble dXShift,dYShift,dZShift; // Project the window shift stuff so we know how far to translate the view dYShift = 0; // No Y shift or zoom for Map Plot. gluUnProject(sfLapOpts.flWindowShiftX/dScaleAmt,0,0,rgModelviewMatrix,rgProjMatrix,rgViewport,&dXShift,&dYShift,&dZShift); // Set up to perform the ZOOM function for DATA PLOT. double dTranslateShiftX; dTranslateShiftX= dCenterX; glTranslated(dTranslateShiftX,0,0); // Translate the map to origin on x-axis only glScaled(dScaleAmt,1.0,1.0); // No scaling of Y-axis on Data Plot. glTranslated(-dTranslateShiftX,0,0); // Now put the map back in its place // Panning functionality glTranslated(dXShift-dMinX,0,0); // Offset for this is still slight wrong, but the best for now. // Now having shifted, let's get our new model matrices glGetDoublev(GL_MODELVIEW_MATRIX, rgModelviewMatrix); glGetDoublev(GL_PROJECTION_MATRIX, rgProjMatrix); glGetIntegerv(GL_VIEWPORT, rgViewport); } } Vector2D ptHighlight; // the (x,y) coords in unit-space that we want to highlight. Example: for a speed-distance graph, x would be in distance units, y in velocities. POINT ptMouse; if(GetMouse(&ptMouse) && m_pLapSupplier->IsHighlightSource(m_iSupplierId)) { // The mouse is in our window... we make our own highlighter, ignoring anything that got sent to us GLdouble dX,dY,dZ; gluUnProject(ptMouse.x,ptMouse.y,0,rgModelviewMatrix,rgProjMatrix,rgViewport,&dX,&dY,&dZ); ptHighlight = V2D(dX,0); } for(int x = 0; x < lstLaps.size(); x++) { CExtendedLap* pLap = lstLaps[x]; const IDataChannel* pDataX = pLap->GetChannel(m_pLapSupplier->GetXChannel()); const IDataChannel* pDataY = pLap->GetChannel(*i); if(pDataX && pDataY) { // tracking what we want to highlight float dBestLength = -1; float dTimeToHighlight = -1; const vector<DataPoint>& lstPointsX = pDataX->GetData(); const vector<DataPoint>& lstPointsY = pDataY->GetData(); // srand((int)pLap); // <-- makes sure that we randomize the colours consistently, so that lap plots don't change colour from draw to draw... float r; float g; float b; MakeColor ( pLap, &r, &g, &b ); // Function picks color to use and tells opengl to draw the following in the colour we just made up if(sfLapOpts.fDrawLines) { glLineWidth(2); // Added by KDJ. Sets the width of the line to draw. glBegin(GL_LINE_STRIP); } else { glPointSize(4.0f); glBegin(GL_POINTS); } vector<DataPoint>::const_iterator iX = lstPointsX.begin(); vector<DataPoint>::const_iterator iY = lstPointsY.begin(); while(iX != lstPointsX.end() && iY != lstPointsY.end()) { float dX; float dY; const DataPoint& ptX = *iX; const DataPoint& ptY = *iY; int iTimeUsed = 0; if(ptX.iTimeMs < ptY.iTimeMs) { iTimeUsed = ptX.iTimeMs; dX = ptX.flValue; dY = pDataY->GetValue(ptX.iTimeMs, iY); iX++; } else if(ptX.iTimeMs > ptY.iTimeMs) { iTimeUsed = ptY.iTimeMs; dX = pDataX->GetValue(ptY.iTimeMs, iX); dY = ptY.flValue; iY++; } else { iTimeUsed = ptY.iTimeMs; DASSERT(ptX.iTimeMs == ptY.iTimeMs); dX = ptX.flValue; dY = ptY.flValue; iX++; iY++; } glVertex2f(dX,dY); // if we're a highlight source, try to figure out the closest point for this lap if(m_pLapSupplier->IsHighlightSource(m_iSupplierId)) { Vector2D vPt = V2D(dX,0); Vector2D vDiff = vPt - ptHighlight; if(vDiff.Length() < dBestLength || dBestLength < 0) { dBestLength = vDiff.Length(); dTimeToHighlight = iTimeUsed; } } } glEnd(); // for each lap, draw an indicator of the closest thing to the mouse if(!m_pLapSupplier->IsHighlightSource(m_iSupplierId)) { // if we're not a source, use the given time to highlight dTimeToHighlight = m_pLapSupplier->GetLapHighlightTime(pLap); } else { m_pLapSupplier->SetLapHighlightTime(pLap, (int)dTimeToHighlight); } UpdateHighlightPointList(lstMousePointsToDraw, pLap, rgModelviewMatrix, rgProjMatrix, rgViewport, dTimeToHighlight, pDataX, pDataY); } } // end lap loop if(lstMousePointsToDraw.size() > 0) { glPushMatrix(); // <-- pushes a matrix onto the opengl matrix stack. glLoadIdentity(); // <-- makes it so that the matrix stack just converts all our coordinates directly to window coordinates glOrtho(0, RECT_WIDTH(&rcSpot),0, RECT_HEIGHT(&rcSpot),-1.0,1.0); /* <-- tells OpenGL that it should show us the part of the openGL "world" that corresponds to (0...window width, 0 ... window height). This completes the "hey opengl, just draw where we tell you to plz" part of the function */ for(int x = 0; x < lstMousePointsToDraw.size(); x++) // <-- loops through all the stupid boxes/lines we want to draw { const CExtendedLap* pLap = lstMousePointsToDraw[x].m_pLap; // <-- gets the lap data we want to draw const POINT& ptWindow = lstMousePointsToDraw[x].m_ptWindow; // <-- gets info about where in the window we want to draw the box const IDataChannel* pDataX = lstMousePointsToDraw[x].m_pDataX; // <-- gets the x channel data const IDataChannel* pDataY = lstMousePointsToDraw[x].m_pDataY; // <-- gets the y channel data float r; float g; float b; MakeColor ( pLap, &r, &g, &b ); // Function picks color to use and tells opengl to draw the following in the colour we just made up // For TIME displayed on X-axis, remove all data channel text so that user can see the trends more clearly. if (pDataX->GetChannelType() != DATA_CHANNEL_TIME) { // if we're the main screen, we want to draw some text data for each point TCHAR szLapName[256]; pLap->GetString(szLapName, NUMCHARS(szLapName)); // <-- gets the string "10:11:12 - 1:40.59 - Keith", aka the "lap name" float dTimeToHighlight = m_pLapSupplier->GetLapHighlightTime(pLap); // <-- asks the ILapSupplier interface what we should highlight TCHAR szTypeX[256]; ::GetDataChannelName(eX,szTypeX,NUMCHARS(szTypeX)); // <-- converts the data channel type into a string, like "Oil Temperature" TCHAR szTypeY[256]; ::GetDataChannelName(lstMousePointsToDraw[x].m_eChannelY, szTypeY, NUMCHARS(szTypeY)); // <-- converts the y channel into a string char szYString[256]; GetChannelString(lstMousePointsToDraw[x].m_eChannelY, sfLapOpts.eUnitPreference, pDataY->GetValue(dTimeToHighlight), szYString, NUMCHARS(szYString)); // <-- gets the actual unit string for the data channel. For speed, this might be "100.0km/h" char szXString[256]; GetChannelString(eX, sfLapOpts.eUnitPreference, pDataX->GetValue(dTimeToHighlight), szXString, NUMCHARS(szXString)); // <-- same for x channel char szText[256]; sprintf(szText, "%S - (%S @ %S) %s @ %s", szLapName, szTypeY, szTypeX, szYString, szXString); DrawText(100.0,(x+1)*GetWindowFontSize(),szText); // <-- draws the text from the bottom of the window, working upwards // we also want to draw a highlighted square DrawGLFilledSquare(ptWindow.x, ptWindow.y, 3); // <-- draws the stupid little box at ptWindow.x. // we also want to draw a highlighted LINE for that individual lap/graph combination glLineWidth(1); // Added by KDJ. Skinny line for Distance markers. glBegin(GL_LINE_STRIP); // Added by KDJ glVertex3f(ptWindow.x, 0, 0); // Added by KDJ, modified by Chas glVertex3f(ptWindow.x,rcSpot.bottom,0); // Added by KDJ } glEnd(); // Added by KDJ } glPopMatrix(); glPopMatrix(); // Should there be two of these here? } rcSpot.top += iSegmentHeight; rcSpot.bottom += iSegmentHeight; } // end y-channel data channel loop }
/** * Sum this and the rhs * @param rhs :: The other V2D * @returns The sum of this and the given V2D */ V2D V2D::operator+(const V2D &rhs) const { return V2D(m_x + rhs.m_x, m_y + rhs.m_y); }
/// Subtract this and the rhs V2D V2D::operator-(const V2D &rhs) const { return V2D(m_x - rhs.m_x, m_y - rhs.m_y); }
/** * Scale and return * @param factor :: The scale factor * @returns A new V2D object scaled by the given factor */ V2D V2D::operator*(const double factor) const { return V2D(m_x * factor, m_y * factor); }