const Path Browser::SelectDirectory() { Path path; path.Reserve( MAX_PATH*2 ); Object::Pod<BROWSEINFO> bi; bi.hwndOwner = Application::Instance::GetActiveWindow(); bi.pszDisplayName = path.Ptr(); bi.ulFlags = BIF_RETURNONLYFSDIRS; if (LPITEMIDLIST const idl = ::SHBrowseForFolder( &bi )) { if (::SHGetPathFromIDList( idl, path.Ptr() ) && path.Validate()) path.MakePretty( true ); else path.Clear(); IMalloc* pMalloc; if (SUCCEEDED(::SHGetMalloc( &pMalloc ))) { pMalloc->Free( idl ); pMalloc->Release(); } } else { path.Clear(); } return path; }
const Path Browser::SaveFile(wchar_t* const filter,Path initial) { Path path; path.Reserve( MAX_PATH*2 ); const Path extension( initial.Extension() ); if (initial.File().Length() && initial.File()[0] != '.') path = initial.File(); initial.File().Clear(); Object::Pod<OPENFILENAME> ofn; ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = Application::Instance::GetActiveWindow(); ofn.lpstrFile = path.Ptr(); ofn.nMaxFile = path.Capacity(); ofn.lpstrInitialDir = initial.Length() ? initial.Ptr() : L"."; ofn.Flags = OFN_EXPLORER|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY; if (filter) { for (uint i=0; filter[i]; ++i) { if (filter[i] == '\t') filter[i] = '\0'; } ofn.lpstrFilter = filter; ofn.nFilterIndex = 1; } if (extension.Length()) ofn.lpstrDefExt = extension.Ptr(); if (::GetSaveFileName( &ofn )) path.Validate(); else path.Clear(); return path; }
const Path Browser::OpenFile(wchar_t* const filter,const Path dir,const Path ext) { for (uint i=0; filter[i]; ++i) { if (filter[i] == '\t') filter[i] = '\0'; } Path path; path.Reserve( MAX_PATH*2 ); Object::Pod<OPENFILENAME> ofn; ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = Application::Instance::GetActiveWindow(); ofn.lpstrFile = path.Ptr(); ofn.nMaxFile = path.Capacity(); ofn.lpstrInitialDir = dir.Length() ? dir.Ptr() : L"."; ofn.Flags = OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY; if (filter) { ofn.lpstrFilter = filter; ofn.nFilterIndex = 1; } if (ext.Length()) ofn.lpstrDefExt = ext.Ptr(); if (::GetOpenFileName( &ofn )) path.Validate(); else path.Clear(); return path; }
void Map::FindBestPathToTile( const Unit* unit, const Vec2s& tilePos, Path& result ) { std::vector< PrimaryDirection > reverseDirections; int searchIndex = ReserveSearchIndex(); // Clear the list of results. result.Clear(); result.SetOrigin( unit->GetTilePos() ); // Clear the open list. mOpenList.clear(); // Get the Unit's current Tile and type. Iterator originTile = unit->GetTile(); UnitType* unitType = unit->GetUnitType(); MovementType* movementType = unit->GetMovementType(); // Get the starting movement range of the Unit. int movementRange = unit->GetMovementRange(); // Add the origin tile to the open list. originTile->Open( searchIndex ); originTile->SetPreviousTileDirection( PrimaryDirection::NONE ); originTile->SetBestTotalCostToEnter( 0 ); mOpenList.insert( 0, originTile ); while( !mOpenList.isEmpty() ) { // Pop the first element off the open list. Map::Iterator tile = mOpenList.popMinElement(); if( tile.GetPosition() != tilePos ) { // If this isn't the goal tile, close it. tile->Close( searchIndex ); for( int i = 0; i < CARDINAL_DIRECTION_COUNT; ++i ) { // Determine the direction to search. PrimaryDirection direction = CARDINAL_DIRECTIONS[ i ]; // If the adjacent tile isn't in the previous direction, get the adjacent tile. Iterator adjacent = tile.GetAdjacent( direction ); if( adjacent.IsValid() && !adjacent->IsClosed( searchIndex ) ) { // If the adjacent tile is valid and isn't already closed, get the TerrainType of the adjacent tile. TerrainType* adjacentTerrainType = adjacent->GetTerrainType(); if( movementType->CanMoveAcrossTerrain( adjacentTerrainType ) ) { // If the adjacent tile is passable, find the total cost of entering the tile. int costToEnterAdjacent = movementType->GetMovementCostAcrossTerrain( adjacentTerrainType ); int adjacentTotalCost = ( tile->GetBestTotalCostToEnter() + costToEnterAdjacent ); int distanceToGoal = ( originTile.GetPosition().GetManhattanDistanceTo( tilePos ) ); int adjacentWeight = ( adjacentTotalCost + distanceToGoal ); if( adjacentTotalCost <= movementRange ) { if( !adjacent->IsOpen( searchIndex ) ) { // If the tile info isn't already on the open list, add it. adjacent->SetPreviousTileDirection( direction.GetOppositeDirection() ); adjacent->SetBestTotalCostToEnter( adjacentTotalCost ); mOpenList.insert( adjacentWeight, adjacent ); } else if( adjacentTotalCost < adjacent->GetBestTotalCostToEnter() ) { // If the node is already on the open list but has a larger total cost, // update the value. adjacent->SetPreviousTileDirection( direction.GetOppositeDirection() ); adjacent->SetBestTotalCostToEnter( adjacentTotalCost ); mOpenList.update( adjacentWeight, adjacent ); } } } } } } else { // If this is the goal tile, construct the path to the location. PrimaryDirection previousDirection = tile->GetPreviousTileDirection(); while( previousDirection != PrimaryDirection::NONE ) { // Construct the list of directions from the goal back to the origin tile. reverseDirections.push_back( previousDirection ); tile = tile.GetAdjacent( previousDirection ); previousDirection = tile->GetPreviousTileDirection(); } // End the search. break; } } for( auto it = reverseDirections.rbegin(); it != reverseDirections.rend(); ++it ) { // Construct the path by reversing the directions from the goal to the origin. PrimaryDirection direction = *it; result.AddDirection( direction.GetOppositeDirection() ); } }