From: <geo...@us...> - 2008-05-31 11:16:17
|
Revision: 2576 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=2576&view=rev Author: geoffthemedio Date: 2008-05-31 04:16:25 -0700 (Sat, 31 May 2008) Log Message: ----------- Fixed a few fleet move path rendering and ETA calculation issues. A bug remains in that ordering a fleet to move to its current system (ie. cancel move order) doesn't stop rendering the previous fleet move line. Modified Paths: -------------- trunk/FreeOrion/UI/MapWnd.cpp trunk/FreeOrion/UI/MapWnd.h trunk/FreeOrion/universe/Fleet.cpp Modified: trunk/FreeOrion/UI/MapWnd.cpp =================================================================== --- trunk/FreeOrion/UI/MapWnd.cpp 2008-05-30 17:29:01 UTC (rev 2575) +++ trunk/FreeOrion/UI/MapWnd.cpp 2008-05-31 11:16:25 UTC (rev 2576) @@ -1386,29 +1386,19 @@ void MapWnd::SetFleetMovement(FleetButton* fleet_button) { assert(fleet_button); - std::set<int> destinations; // keeps track of systems to which lines are being drawn for given fleet button for (std::vector<Fleet*>::const_iterator it = fleet_button->Fleets().begin(); it != fleet_button->Fleets().end(); ++it) { Fleet* fleet = *it; - // ensure the fleet has a valid destination, and that there isn't already a movement line to that location - if (fleet->FinalDestinationID() != UniverseObject::INVALID_OBJECT_ID && - fleet->FinalDestinationID() != fleet->SystemID() && - destinations.find(fleet->FinalDestinationID()) == destinations.end()) - { - destinations.insert(fleet->FinalDestinationID()); + // ensure the fleet has a valid destination + if (fleet->FinalDestinationID() != UniverseObject::INVALID_OBJECT_ID && fleet->FinalDestinationID() != fleet->SystemID()) m_fleet_lines[fleet] = MovementLineData(fleet_button, fleet->MovePath()); - } else { - // fleet's destination already has a line from this button, or the destination is invalid. If there is - // another preexisting fleet line for this fleet, it is no longer needed. - m_fleet_lines.erase(fleet); - } } } void MapWnd::SetFleetMovement(Fleet* fleet) { assert(fleet); - + std::map<Fleet*, MovementLineData>::iterator it = m_fleet_lines.find(fleet); if (it != m_fleet_lines.end()) { const System* system = fleet->GetSystem(); @@ -1737,12 +1727,13 @@ void MapWnd::RenderStarlanes() { + const float STARLANE_GRAY = 127.0f / 255.0f; + const float STARLANE_ALPHA = 0.7f; + const double STARLANE_WIDTH = 2.5; + glDisableClientState(GL_TEXTURE_COORD_ARRAY); if (m_starlane_vertices.m_name) { - const float STARLANE_GRAY = 127.0f / 255.0f; - const float STARLANE_ALPHA = 0.7f; - const double STARLANE_WIDTH = 2.5; glColor4f(STARLANE_GRAY, STARLANE_GRAY, STARLANE_GRAY, STARLANE_ALPHA); #ifdef FREEORION_WIN32 glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_starlane_vertices.m_name); @@ -1763,8 +1754,8 @@ const int SHIFT = static_cast<int>(GG::GUI::GetGUI()->Ticks() * RATE / GLUSHORT_BIT_LENGTH) % GLUSHORT_BIT_LENGTH; const unsigned int STIPPLE = (PATTERN << SHIFT) | (PATTERN >> (GLUSHORT_BIT_LENGTH - SHIFT)); const double LINE_SCALE = std::max(0.75, m_zoom_factor); - glLineStipple(static_cast<int>(LINE_SCALE), STIPPLE); - glLineWidth(LINE_SCALE); + glLineStipple(static_cast<int>(STARLANE_WIDTH), STIPPLE); + glLineWidth(STARLANE_WIDTH); glEnableClientState(GL_COLOR_ARRAY); #ifdef FREEORION_WIN32 glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_starlane_supply_vertices.m_name); @@ -1787,76 +1778,71 @@ void MapWnd::RenderFleetMovementLines() { + const double STARLANE_WIDTH = 2.5; + glLineWidth(STARLANE_WIDTH); + + // standard movement line stipple const GLushort PATTERN = 0xF0F0; const int GLUSHORT_BIT_LENGTH = sizeof(GLushort) * 8; const double RATE = 0.25; - const double PROJECTED_PATH_RATE = 0.35; const int SHIFT = static_cast<int>(GG::GUI::GetGUI()->Ticks() * RATE / GLUSHORT_BIT_LENGTH) % GLUSHORT_BIT_LENGTH; + const unsigned int STIPPLE = (PATTERN << SHIFT) | (PATTERN >> (GLUSHORT_BIT_LENGTH - SHIFT)); + + // render standard movement lines + glLineStipple(static_cast<int>(STARLANE_WIDTH), STIPPLE); + for (std::map<Fleet*, MovementLineData>::iterator it = m_fleet_lines.begin(); it != m_fleet_lines.end(); ++it) + RenderMovementLine(it->second); + + + // projected movement line stipple + const double PROJECTED_PATH_RATE = 0.35; const int PROJECTED_PATH_SHIFT = static_cast<int>(GG::GUI::GetGUI()->Ticks() * PROJECTED_PATH_RATE / GLUSHORT_BIT_LENGTH) % GLUSHORT_BIT_LENGTH; - const unsigned int STIPPLE = (PATTERN << SHIFT) | (PATTERN >> (GLUSHORT_BIT_LENGTH - SHIFT)); const unsigned int PROJECTED_PATH_STIPPLE = (PATTERN << PROJECTED_PATH_SHIFT) | (PATTERN >> (GLUSHORT_BIT_LENGTH - PROJECTED_PATH_SHIFT)); - double LINE_SCALE = std::max(1.0, m_zoom_factor); - glLineWidth(LINE_SCALE); - glLineStipple(static_cast<int>(LINE_SCALE), STIPPLE); + //// render projected move path + glLineStipple(static_cast<int>(STARLANE_WIDTH), PROJECTED_PATH_STIPPLE); + RenderMovementLine(m_projected_fleet_line); +} - GG::Pt ul = ClientUpperLeft(); - for (std::map<Fleet*, MovementLineData>::iterator it = m_fleet_lines.begin(); it != m_fleet_lines.end(); ++it) { - const MovementLineData& move_line = it->second; +void MapWnd::RenderMovementLine(const MapWnd::MovementLineData& move_line) { + if (move_line.Path().empty() || move_line.Path().size() == 1) + return; - if (move_line.Path().empty()) - continue; + // get starting vertex + std::pair<double, double> start = move_line.Start(); + double prev_vertex_x = start.first, prev_vertex_y = start.second; - // this is obviously less efficient than using GL_LINE_STRIP, but GL_LINE_STRIP sometimes produces nasty artifacts - // when the begining of a line segment starts offscreen - glBegin(GL_LINES); - glColor(move_line.Colour()); + bool started = false; - // add starting vertex - std::pair<double, double> start = move_line.Start(); - glVertex2d(start.first, start.second); + // draw lines connecting starting to second vertex, second to third, etc, + std::list<MovePathNode>::const_iterator path_it = move_line.Path().begin(); + ++path_it; + for (; path_it != move_line.Path().end(); ++path_it) { - for (std::list<MovePathNode>::const_iterator path_it = move_line.Path().begin(); path_it != move_line.Path().end(); ++path_it) { - // add ending vertex for previous leg of path - glVertex2d(path_it->x, path_it->y); + // if this vertex can be reached, add vertices for line from previous to this vertex + if (path_it->eta == Fleet::ETA_NEVER || path_it->eta == Fleet::ETA_NEVER || path_it->eta == Fleet::ETA_OUT_OF_RANGE) + break; // don't render additional legs of path that aren't reachable - // if not done, add starting vertex for next leg of path - std::list<MovePathNode>::const_iterator temp_it = path_it; - if (++temp_it != move_line.Path().end()) { - if (path_it->eta >= Fleet::ETA_NEVER) // includes ETA_NEVER, ETA_UNKNOWN and ETA_OUT_OF_RANGE - break; // don't render additional legs of path that aren't reachable - glVertex2d(path_it->x, path_it->y); - } + if (!started) { + // this is obviously less efficient than using GL_LINE_STRIP, but GL_LINE_STRIP sometimes produces nasty artifacts + // when the begining of a line segment starts offscreen + glBegin(GL_LINES); + glColor(move_line.Colour()); + started = true; } - glEnd(); - } - // render projected move path - glLineStipple(static_cast<int>(LINE_SCALE), PROJECTED_PATH_STIPPLE); - if (!m_projected_fleet_line.Path().empty()) { - glBegin(GL_LINES); - glColor(m_projected_fleet_line.Colour()); + glVertex2d(prev_vertex_x, prev_vertex_y); + glVertex2d(path_it->x, path_it->y); - // add starting vertex - std::pair<double, double> start = m_projected_fleet_line.Start(); - glVertex2d(start.first, start.second); + // and update previous vertex for next iteration + prev_vertex_x = path_it->x; + prev_vertex_y = path_it->y; + } - for (std::list<MovePathNode>::const_iterator path_it = m_projected_fleet_line.Path().begin(); path_it != m_projected_fleet_line.Path().end(); ++path_it) { - // add ending vertex for previous leg of path - glVertex2d(path_it->x, path_it->y); - - // if not done, add starting vertex for next leg of path - std::list<MovePathNode>::const_iterator temp_it = path_it; - if (++temp_it != m_projected_fleet_line.Path().end()) { - if (path_it->eta >= Fleet::ETA_NEVER) - break; // don't render additional legs of path that aren't reachable - glVertex2d(path_it->x, path_it->y); - } - } + if (started) glEnd(); - } } void MapWnd::CorrectMapPosition(GG::Pt &move_to_pt) Modified: trunk/FreeOrion/UI/MapWnd.h =================================================================== --- trunk/FreeOrion/UI/MapWnd.h 2008-05-30 17:29:01 UTC (rev 2575) +++ trunk/FreeOrion/UI/MapWnd.h 2008-05-31 11:16:25 UTC (rev 2576) @@ -153,12 +153,15 @@ void Zoom(int delta); //!< changes the zoomlevel of the main map void DoMovingFleetButtonsLayout(); //!< does layout of fleet buttons for moving fleets void DoSystemIconsLayout(); //!< does layout of system icons + void RenderStarfields(); //!< renders the background starfiends void RenderNebulae(); //!< renders nebulae void RenderGalaxyGas(); //!< renders gassy substance to make shape of galaxy void RenderSystems(); //!< renders stars and halos void RenderStarlanes(); //!< renders the starlanes between the systems void RenderFleetMovementLines(); //!< renders the dashed lines indicating where each fleet is going + void RenderMovementLine(const MapWnd::MovementLineData& move_line); //!< renders a single fleet movement line + void CorrectMapPosition(GG::Pt &move_to_pt); //!< ensures that the map data are positioned sensibly void SystemDoubleClicked(int system_id); void SystemLeftClicked(int system_id); Modified: trunk/FreeOrion/universe/Fleet.cpp =================================================================== --- trunk/FreeOrion/universe/Fleet.cpp 2008-05-30 17:29:01 UTC (rev 2575) +++ trunk/FreeOrion/universe/Fleet.cpp 2008-05-31 11:16:25 UTC (rev 2576) @@ -103,12 +103,13 @@ { std::list<MovePathNode> retval = std::list<MovePathNode>(); - if (route.empty()) return retval; // nowhere to go => empty path - if (route.size() == 2 && route.front() == route.back()) return retval; // nowhere to go => empty path - - if (this->Speed() < FLEET_MOVEMENT_EPSILON) { // can't move => ETA is never + if (route.empty()) + return retval; // nowhere to go => empty path + if (route.size() == 2 && route.front() == route.back()) + return retval; // nowhere to go => empty path + if (this->Speed() < FLEET_MOVEMENT_EPSILON) { retval.push_back(MovePathNode(this->X(), this->Y(), true, ETA_NEVER, this->SystemID())); - return retval; + return retval; // can't move => path is just this system with explanitory ETA } @@ -139,9 +140,15 @@ } + // determine if, given fuel available and supplyable systems, fleet will ever be able to move + if (fuel < 1.0 && this->GetSystem() && fleet_supplied_systems.find(this->SystemID()) == fleet_supplied_systems.end()) { + retval.push_back(MovePathNode(this->X(), this->Y(), true, ETA_OUT_OF_RANGE, this->SystemID())); + return retval; // can't move => path is just this system with explanitory ETA + } + + // node for initial position of fleet MovePathNode cur_pos(this->X(), this->Y(), true, 0, this->SystemID()); - retval.push_back(cur_pos); // get current system of fleet, if it is in a system, and next system reached in path @@ -169,6 +176,11 @@ int turns_taken = 0; while (turns_taken <= TOO_LONG) { + cur_pos.eta = turns_taken; + cur_pos.turn_end = new_turn; + if (!cur_system) + cur_pos.object_id = INVALID_OBJECT_ID; + // check for arrival at next system on path if (dist_to_next_system < FLEET_MOVEMENT_EPSILON) { // update current system and position, and next system and position @@ -176,31 +188,35 @@ cur_pos.x = next_system->X(); cur_pos.y = next_system->Y(); - cur_pos.eta = turns_taken; - cur_pos.turn_end = false; + // cur_pos.turn_end // set previously; don't want to modify here + // cur_pos.turns_taken // set previously; don't want to modify here cur_pos.object_id = next_system->ID(); - retval.push_back(cur_pos); - ++route_it; - if (route_it == route.end()) + if (route_it == route.end()) { + cur_pos.turn_end = true; + retval.push_back(cur_pos); break; + } else { + retval.push_back(cur_pos); + } next_system = *route_it; next_sys_pos.x = next_system->X(); next_sys_pos.y = next_system->Y(); - next_sys_pos.eta = ETA_UNKNOWN; - next_sys_pos.turn_end = false; + next_sys_pos.eta = ETA_UNKNOWN; // will be set later + next_sys_pos.turn_end = false; // may be set later next_sys_pos.object_id = next_system->ID(); dist_to_next_system = std::sqrt((next_sys_pos.x - cur_pos.x)*(next_sys_pos.x - cur_pos.x) + (next_sys_pos.y - cur_pos.y)*(next_sys_pos.y - cur_pos.y)); + } else { + retval.push_back(cur_pos); } // if this iteration is the start of a new simulated turn, distance to be travelled this turn is reset and turns taken incremented if (new_turn) { ++turns_taken; - cur_pos.eta = turns_taken; turn_dist_remaining = m_speed; } @@ -264,11 +280,15 @@ } if (turns_taken >= TOO_LONG) { - next_sys_pos.eta = turns_taken; - next_sys_pos.turn_end = true; - retval.push_back(next_sys_pos); + cur_pos.eta = turns_taken; + cur_pos.turn_end = true; + retval.push_back(cur_pos); } + Logger().debugStream() << "MovePath size: " << retval.size(); + for (std::list<MovePathNode>::const_iterator it = retval.begin(); it != retval.end(); ++it) + Logger().debugStream() << " .. (" << it->x << ", " << it->y << ") eta: " << it->eta << " end turn?: " << boost::lexical_cast<std::string>(it->turn_end) << + " object id: " << it->object_id; return retval; } @@ -290,12 +310,18 @@ return std::make_pair(node.eta, node.eta); } - // general case: there is a multi-node path. return the second (first after initial position of fleet) and last nodes' ETAs - std::list<MovePathNode>::const_iterator it = move_path.begin(); - ++it; - const MovePathNode& first = *it; - const MovePathNode& last = *move_path.rbegin(); - return std::make_pair(last.eta, first.eta); + // general case: there is a multi-node path. return the ETA of the first object node, and the ETA of the last node + int last_stop_eta = move_path.rbegin()->eta; + int first_stop_eta = last_stop_eta; + for (std::list<MovePathNode>::const_iterator it = ++(move_path.begin()); it != move_path.end(); ++it) { + const MovePathNode& node = *it; + if (node.object_id != INVALID_OBJECT_ID) { + first_stop_eta = node.eta; + break; + } + } + + return std::make_pair(last_stop_eta, first_stop_eta); } int Fleet::FinalDestinationID() const |