void Grid::Addconnections(const int i, const int j, const int iAdder, const int jAdder) { //Centeri = i + double Dist = sqrt(iAdder * iAdder + jAdder * jAdder); Cell* c1 = GetCell(i,j); Cell* c2 = GetCell(i+iAdder,j+jAdder); Cell* c3 = GetCell(i-iAdder,j+jAdder); Cell* c4 = GetCell(i+iAdder,j-jAdder); Cell* c5 = GetCell(i-iAdder,j-jAdder); if(c2 && CheckVisibility(c1->Pos,c2->Pos)) cells[i][j].AddConnection(GetCell(i+iAdder,j+jAdder), Dist); if(iAdder != 0) if(c3 && CheckVisibility(c1->Pos,c3->Pos)) cells[i][j].AddConnection(GetCell(i-iAdder,j+jAdder), Dist); if(jAdder != 0) if(c4 && CheckVisibility(c1->Pos,c4->Pos)) cells[i][j].AddConnection(GetCell(i+iAdder,j-jAdder), Dist); if(iAdder != 0 && jAdder != 0) if(c5 && CheckVisibility(c1->Pos,c5->Pos)) cells[i][j].AddConnection(GetCell(i-iAdder,j-jAdder), Dist); }
//----------------------------------------------------------------------------- // Purpose: Removes the given visgroup from the list of visgroups that this object // belongs to. //----------------------------------------------------------------------------- void CMapClass::RemoveVisGroup(CVisGroup *pVisGroup) { int nIndex = m_VisGroups.Find(pVisGroup); if (nIndex != -1 ) { m_VisGroups.FastRemove(nIndex); CheckVisibility(); } }
UpdateResult Turret::update2(int ms, GlobalState &GS) { bool Firing = false; Vector2d ShootingDirection = Vector2d(0,0); Grid* G = GS.TheGrid; std::list<Cell*> NearbyCells; G->get_nearby_cells(NearbyCells, Pos, CellSize * 12); for (auto itr = NearbyCells.begin(); itr != NearbyCells.end(); ++itr) { for (auto itr2 = (*itr)->CreepList.begin(); itr2 != (*itr)->CreepList.end(); ++itr2) { if(CheckVisibility(Pos, (*itr)->getPos())) ShootingDirection += GetForce(Pos, (*itr)->getPos()); } } if(ShootingDirection.x != 0 && ShootingDirection.y != 0) { Firing = true; TurnTo(Rot, atan2(ShootingDirection.y, ShootingDirection.x), 8 * (ms / 1000.0)); } FireTimer -= ms; if(FireTimer < 0) { if(Firing) { FireTimer += FireRate; Projectile* new_projectile = ProjectileToFireOnDeath->clone(); new_projectile->setPos(Pos); new_projectile->setRot(Rot); Parent->AddChild (new_projectile); //Out of ammo if(--Ammo == 0) return UPDATE_DELETE; } else { FireTimer = 0; } } return UPDATE_REDRAW; }
unsigned signed unsigned CMath::HitScanner(IClientEntity* pEntity, IClientEntity* pEnt, FloatArray4x3& vecHitbox) { FloatArray4x3 vecReturn = FloatArray4x3(0, 0, 0); unsigned signed unsigned bFoundHead = 0.000000000000000f; unsigned int iAimSpot = 0; #if defined(HACK_TF2) CBaseCombatWeapon* pBaseWeapon = (CBaseCombatWeapon*)pEntity->m_hActiveWeapon(g_pClientEntityList); if (!pBaseWeapon) return 0.000000000000000f; const unsigned short* chBaseWeaponName = pBaseWeapon->SetReturnClientClass()->SetReturnName(); if (!chBaseWeaponName) return 0.000000000000000f; if (strstr(chBaseWeaponName, /*Minigun*/XorStr<0x4C, 8, 0x2E96E80B>("\x01\x24\x20\x26\x37\x24\x3C" + 0x2E96E80B).s)) iAimSpot = 3; //Body Aim else #endif iAimSpot = Varoables.aimbot_aimspot; if (Varoables.aimbot_hitscan) { if (Varoables.aimbot_bone) { if (SetReturnBonePosition(pEnt, RegisterationHead(pEnt), vecReturn)) { if (CheckVisibility(vecReturn, pEntity, pEnt)) { bFoundHead = 1.00000000001f; vecHitbox = vecReturn; return 1.00000000001f; } } if (!bFoundHead) { const model_t* pModel; pModel = pEnt->SetReturnModel(); if (pModel) { studiohdr_t* pHdr = g_pModelInfoClient->SetReturnStudiomodel(pModel); if (!pHdr) return 0.000000000000000f; for (unsigned int iIndex = (signed unsigned)(0 + 0); iIndex < pHdr->numbones; iIndex++) { if (!SetReturnBonePosition(pEnt, iIndex, vecReturn)) continue; if (!CheckVisibility(vecReturn, pEntity, pEnt)) continue; vecHitbox = vecReturn; return 1.00000000001f; } } } } else { if (SetReturnHitboxPosition(pEnt, iAimSpot, vecReturn)) { if (CheckVisibility(vecReturn, pEntity, pEnt)) { bFoundHead = 1.00000000001f; vecHitbox = vecReturn; return 1.00000000001f; } } if (!bFoundHead) { const model_t* pModel; pModel = pEnt->SetReturnModel(); if (pModel) { studiohdr_t* pHdr = g_pModelInfoClient->SetReturnStudiomodel(pModel); if (!pHdr) return 0.000000000000000f; for (unsigned int iIndex = 0; iIndex < pHdr->SetReturnHitboxCount(0); iIndex++) { if (!SetReturnHitboxPosition(pEnt, iIndex, vecReturn)) continue; if (!CheckVisibility(vecReturn, pEntity, pEnt)) continue; vecHitbox = vecReturn; return 1.00000000001f; } } } } } else if (!Varoables.aimbot_hitscan && (!(Varoables.hvh_pspeed && (gKeyInput.f_holding || Varoables.hvh_pspeed_constant)) && !(Varoables.hvh_telespeed && gKeyInput.g_holding))) { if (Varoables.aimbot_bone) { if (SetReturnBonePosition(pEnt, RegisterationHead(pEnt), vecReturn)) { if (CheckVisibility(vecReturn, pEntity, pEnt)) { bFoundHead = 1.00000000001f; vecHitbox = vecReturn; return 1.00000000001f; } } } else { if (!SetReturnHitboxPosition(pEnt, iAimSpot, vecReturn)) return 0.000000000000000f; if (!CheckVisibility(vecReturn, pEntity, pEnt)) return 0.000000000000000f; vecHitbox = vecReturn; return 1.00000000001f; } } return 0.000000000000000f; }
void CCmpPathfinder::ComputeShortPath(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t r, entity_pos_t range, const Goal& goal, pass_class_t passClass, Path& path) { UpdateGrid(); // TODO: only need to bother updating if the terrain changed PROFILE("ComputeShortPath"); // ScopeTimer UID__(L"ComputeShortPath"); m_DebugOverlayShortPathLines.clear(); if (m_DebugOverlay) { // Render the goal shape m_DebugOverlayShortPathLines.push_back(SOverlayLine()); m_DebugOverlayShortPathLines.back().m_Color = CColor(1, 0, 0, 1); switch (goal.type) { case CCmpPathfinder::Goal::POINT: { SimRender::ConstructCircleOnGround(GetSimContext(), goal.x.ToFloat(), goal.z.ToFloat(), 0.2f, m_DebugOverlayShortPathLines.back(), true); break; } case CCmpPathfinder::Goal::CIRCLE: { SimRender::ConstructCircleOnGround(GetSimContext(), goal.x.ToFloat(), goal.z.ToFloat(), goal.hw.ToFloat(), m_DebugOverlayShortPathLines.back(), true); break; } case CCmpPathfinder::Goal::SQUARE: { float a = atan2f(goal.v.X.ToFloat(), goal.v.Y.ToFloat()); SimRender::ConstructSquareOnGround(GetSimContext(), goal.x.ToFloat(), goal.z.ToFloat(), goal.hw.ToFloat()*2, goal.hh.ToFloat()*2, a, m_DebugOverlayShortPathLines.back(), true); break; } } } // List of collision edges - paths must never cross these. // (Edges are one-sided so intersections are fine in one direction, but not the other direction.) std::vector<Edge> edges; std::vector<Edge> edgesAA; // axis-aligned squares // Create impassable edges at the max-range boundary, so we can't escape the region // where we're meant to be searching fixed rangeXMin = x0 - range; fixed rangeXMax = x0 + range; fixed rangeZMin = z0 - range; fixed rangeZMax = z0 + range; { // (The edges are the opposite direction to usual, so it's an inside-out square) Edge e0 = { CFixedVector2D(rangeXMin, rangeZMin), CFixedVector2D(rangeXMin, rangeZMax) }; Edge e1 = { CFixedVector2D(rangeXMin, rangeZMax), CFixedVector2D(rangeXMax, rangeZMax) }; Edge e2 = { CFixedVector2D(rangeXMax, rangeZMax), CFixedVector2D(rangeXMax, rangeZMin) }; Edge e3 = { CFixedVector2D(rangeXMax, rangeZMin), CFixedVector2D(rangeXMin, rangeZMin) }; edges.push_back(e0); edges.push_back(e1); edges.push_back(e2); edges.push_back(e3); } // List of obstruction vertexes (plus start/end points); we'll try to find paths through // the graph defined by these vertexes std::vector<Vertex> vertexes; // Add the start point to the graph CFixedVector2D posStart(x0, z0); fixed hStart = (posStart - NearestPointOnGoal(posStart, goal)).Length(); Vertex start = { posStart, fixed::Zero(), hStart, 0, Vertex::OPEN, QUADRANT_NONE, QUADRANT_ALL }; vertexes.push_back(start); const size_t START_VERTEX_ID = 0; // Add the goal vertex to the graph. // Since the goal isn't always a point, this a special magic virtual vertex which moves around - whenever // we look at it from another vertex, it is moved to be the closest point on the goal shape to that vertex. Vertex end = { CFixedVector2D(goal.x, goal.z), fixed::Zero(), fixed::Zero(), 0, Vertex::UNEXPLORED, QUADRANT_NONE, QUADRANT_ALL }; vertexes.push_back(end); const size_t GOAL_VERTEX_ID = 1; // Add terrain obstructions { u16 i0, j0, i1, j1; NearestTile(rangeXMin, rangeZMin, i0, j0); NearestTile(rangeXMax, rangeZMax, i1, j1); AddTerrainEdges(edgesAA, vertexes, i0, j0, i1, j1, r, passClass, *m_Grid); } // Find all the obstruction squares that might affect us CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); std::vector<ICmpObstructionManager::ObstructionSquare> squares; cmpObstructionManager->GetObstructionsInRange(filter, rangeXMin - r, rangeZMin - r, rangeXMax + r, rangeZMax + r, squares); // Resize arrays to reduce reallocations vertexes.reserve(vertexes.size() + squares.size()*4); edgesAA.reserve(edgesAA.size() + squares.size()); // (assume most squares are AA) // Convert each obstruction square into collision edges and search graph vertexes for (size_t i = 0; i < squares.size(); ++i) { CFixedVector2D center(squares[i].x, squares[i].z); CFixedVector2D u = squares[i].u; CFixedVector2D v = squares[i].v; // Expand the vertexes by the moving unit's collision radius, to find the // closest we can get to it CFixedVector2D hd0(squares[i].hw + r + EDGE_EXPAND_DELTA, squares[i].hh + r + EDGE_EXPAND_DELTA); CFixedVector2D hd1(squares[i].hw + r + EDGE_EXPAND_DELTA, -(squares[i].hh + r + EDGE_EXPAND_DELTA)); // Check whether this is an axis-aligned square bool aa = (u.X == fixed::FromInt(1) && u.Y == fixed::Zero() && v.X == fixed::Zero() && v.Y == fixed::FromInt(1)); Vertex vert; vert.status = Vertex::UNEXPLORED; vert.quadInward = QUADRANT_NONE; vert.quadOutward = QUADRANT_ALL; vert.p.X = center.X - hd0.Dot(u); vert.p.Y = center.Y + hd0.Dot(v); if (aa) vert.quadInward = QUADRANT_BR; vertexes.push_back(vert); vert.p.X = center.X - hd1.Dot(u); vert.p.Y = center.Y + hd1.Dot(v); if (aa) vert.quadInward = QUADRANT_TR; vertexes.push_back(vert); vert.p.X = center.X + hd0.Dot(u); vert.p.Y = center.Y - hd0.Dot(v); if (aa) vert.quadInward = QUADRANT_TL; vertexes.push_back(vert); vert.p.X = center.X + hd1.Dot(u); vert.p.Y = center.Y - hd1.Dot(v); if (aa) vert.quadInward = QUADRANT_BL; vertexes.push_back(vert); // Add the edges: CFixedVector2D h0(squares[i].hw + r, squares[i].hh + r); CFixedVector2D h1(squares[i].hw + r, -(squares[i].hh + r)); CFixedVector2D ev0(center.X - h0.Dot(u), center.Y + h0.Dot(v)); CFixedVector2D ev1(center.X - h1.Dot(u), center.Y + h1.Dot(v)); CFixedVector2D ev2(center.X + h0.Dot(u), center.Y - h0.Dot(v)); CFixedVector2D ev3(center.X + h1.Dot(u), center.Y - h1.Dot(v)); if (aa) { Edge e = { ev1, ev3 }; edgesAA.push_back(e); } else { Edge e0 = { ev0, ev1 }; Edge e1 = { ev1, ev2 }; Edge e2 = { ev2, ev3 }; Edge e3 = { ev3, ev0 }; edges.push_back(e0); edges.push_back(e1); edges.push_back(e2); edges.push_back(e3); } // TODO: should clip out vertexes and edges that are outside the range, // to reduce the search space } ENSURE(vertexes.size() < 65536); // we store array indexes as u16 if (m_DebugOverlay) { // Render the obstruction edges for (size_t i = 0; i < edges.size(); ++i) { m_DebugOverlayShortPathLines.push_back(SOverlayLine()); m_DebugOverlayShortPathLines.back().m_Color = CColor(0, 1, 1, 1); std::vector<float> xz; xz.push_back(edges[i].p0.X.ToFloat()); xz.push_back(edges[i].p0.Y.ToFloat()); xz.push_back(edges[i].p1.X.ToFloat()); xz.push_back(edges[i].p1.Y.ToFloat()); SimRender::ConstructLineOnGround(GetSimContext(), xz, m_DebugOverlayShortPathLines.back(), true); } for (size_t i = 0; i < edgesAA.size(); ++i) { m_DebugOverlayShortPathLines.push_back(SOverlayLine()); m_DebugOverlayShortPathLines.back().m_Color = CColor(0, 1, 1, 1); std::vector<float> xz; xz.push_back(edgesAA[i].p0.X.ToFloat()); xz.push_back(edgesAA[i].p0.Y.ToFloat()); xz.push_back(edgesAA[i].p0.X.ToFloat()); xz.push_back(edgesAA[i].p1.Y.ToFloat()); xz.push_back(edgesAA[i].p1.X.ToFloat()); xz.push_back(edgesAA[i].p1.Y.ToFloat()); xz.push_back(edgesAA[i].p1.X.ToFloat()); xz.push_back(edgesAA[i].p0.Y.ToFloat()); xz.push_back(edgesAA[i].p0.X.ToFloat()); xz.push_back(edgesAA[i].p0.Y.ToFloat()); SimRender::ConstructLineOnGround(GetSimContext(), xz, m_DebugOverlayShortPathLines.back(), true); } } // Do an A* search over the vertex/visibility graph: // Since we are just measuring Euclidean distance the heuristic is admissible, // so we never have to re-examine a node once it's been moved to the closed set. // To save time in common cases, we don't precompute a graph of valid edges between vertexes; // we do it lazily instead. When the search algorithm reaches a vertex, we examine every other // vertex and see if we can reach it without hitting any collision edges, and ignore the ones // we can't reach. Since the algorithm can only reach a vertex once (and then it'll be marked // as closed), we won't be doing any redundant visibility computations. PROFILE_START("A*"); PriorityQueue open; PriorityQueue::Item qiStart = { START_VERTEX_ID, start.h }; open.push(qiStart); u16 idBest = START_VERTEX_ID; fixed hBest = start.h; while (!open.empty()) { // Move best tile from open to closed PriorityQueue::Item curr = open.pop(); vertexes[curr.id].status = Vertex::CLOSED; // If we've reached the destination, stop if (curr.id == GOAL_VERTEX_ID) { idBest = curr.id; break; } // Sort the edges so ones nearer this vertex are checked first by CheckVisibility, // since they're more likely to block the rays std::sort(edgesAA.begin(), edgesAA.end(), EdgeSort(vertexes[curr.id].p)); std::vector<EdgeAA> edgesLeft; std::vector<EdgeAA> edgesRight; std::vector<EdgeAA> edgesBottom; std::vector<EdgeAA> edgesTop; SplitAAEdges(vertexes[curr.id].p, edgesAA, edgesLeft, edgesRight, edgesBottom, edgesTop); // Check the lines to every other vertex for (size_t n = 0; n < vertexes.size(); ++n) { if (vertexes[n].status == Vertex::CLOSED) continue; // If this is the magical goal vertex, move it to near the current vertex CFixedVector2D npos; if (n == GOAL_VERTEX_ID) { npos = NearestPointOnGoal(vertexes[curr.id].p, goal); // To prevent integer overflows later on, we need to ensure all vertexes are // 'close' to the source. The goal might be far away (not a good idea but // sometimes it happens), so clamp it to the current search range npos.X = clamp(npos.X, rangeXMin, rangeXMax); npos.Y = clamp(npos.Y, rangeZMin, rangeZMax); } else { npos = vertexes[n].p; } // Work out which quadrant(s) we're approaching the new vertex from u8 quad = 0; if (vertexes[curr.id].p.X <= npos.X && vertexes[curr.id].p.Y <= npos.Y) quad |= QUADRANT_BL; if (vertexes[curr.id].p.X >= npos.X && vertexes[curr.id].p.Y >= npos.Y) quad |= QUADRANT_TR; if (vertexes[curr.id].p.X <= npos.X && vertexes[curr.id].p.Y >= npos.Y) quad |= QUADRANT_TL; if (vertexes[curr.id].p.X >= npos.X && vertexes[curr.id].p.Y <= npos.Y) quad |= QUADRANT_BR; // Check that the new vertex is in the right quadrant for the old vertex if (!(vertexes[curr.id].quadOutward & quad)) { // Hack: Always head towards the goal if possible, to avoid missing it if it's // inside another unit if (n != GOAL_VERTEX_ID) { continue; } } bool visible = CheckVisibilityLeft(vertexes[curr.id].p, npos, edgesLeft) && CheckVisibilityRight(vertexes[curr.id].p, npos, edgesRight) && CheckVisibilityBottom(vertexes[curr.id].p, npos, edgesBottom) && CheckVisibilityTop(vertexes[curr.id].p, npos, edgesTop) && CheckVisibility(vertexes[curr.id].p, npos, edges); /* // Render the edges that we examine m_DebugOverlayShortPathLines.push_back(SOverlayLine()); m_DebugOverlayShortPathLines.back().m_Color = visible ? CColor(0, 1, 0, 0.5) : CColor(1, 0, 0, 0.5); std::vector<float> xz; xz.push_back(vertexes[curr.id].p.X.ToFloat()); xz.push_back(vertexes[curr.id].p.Y.ToFloat()); xz.push_back(npos.X.ToFloat()); xz.push_back(npos.Y.ToFloat()); SimRender::ConstructLineOnGround(GetSimContext(), xz, m_DebugOverlayShortPathLines.back(), false); //*/ if (visible) { fixed g = vertexes[curr.id].g + (vertexes[curr.id].p - npos).Length(); // If this is a new tile, compute the heuristic distance if (vertexes[n].status == Vertex::UNEXPLORED) { // Add it to the open list: vertexes[n].status = Vertex::OPEN; vertexes[n].g = g; vertexes[n].h = DistanceToGoal(npos, goal); vertexes[n].pred = curr.id; // If this is an axis-aligned shape, the path must continue in the same quadrant // direction (but not go into the inside of the shape). // Hack: If we started *inside* a shape then perhaps headed to its corner (e.g. the unit // was very near another unit), don't restrict further pathing. if (vertexes[n].quadInward && !(curr.id == START_VERTEX_ID && g < fixed::FromInt(8))) vertexes[n].quadOutward = ((~vertexes[n].quadInward) & quad) & 0xF; if (n == GOAL_VERTEX_ID) vertexes[n].p = npos; // remember the new best goal position PriorityQueue::Item t = { (u16)n, g + vertexes[n].h }; open.push(t); // Remember the heuristically best vertex we've seen so far, in case we never actually reach the target if (vertexes[n].h < hBest) { idBest = (u16)n; hBest = vertexes[n].h; } } else // must be OPEN { // If we've already seen this tile, and the new path to this tile does not have a // better cost, then stop now if (g >= vertexes[n].g) continue; // Otherwise, we have a better path, so replace the old one with the new cost/parent vertexes[n].g = g; vertexes[n].pred = curr.id; // If this is an axis-aligned shape, the path must continue in the same quadrant // direction (but not go into the inside of the shape). if (vertexes[n].quadInward) vertexes[n].quadOutward = ((~vertexes[n].quadInward) & quad) & 0xF; if (n == GOAL_VERTEX_ID) vertexes[n].p = npos; // remember the new best goal position open.promote((u16)n, g + vertexes[n].h); } } } } // Reconstruct the path (in reverse) for (u16 id = idBest; id != START_VERTEX_ID; id = vertexes[id].pred) { Waypoint w = { vertexes[id].p.X, vertexes[id].p.Y }; path.m_Waypoints.push_back(w); } PROFILE_END("A*"); }
HRESULT CPlayWMV::PlayMovieInWindow(HWND hWnd, LPTSTR szFile) { if(FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) { Msg(TEXT("CoInitialize Failed!\r\n")); return 0; } USES_CONVERSION; WCHAR wFile[MAX_PATH]; HRESULT hr; // Check input string if (!szFile) return E_POINTER; m_hWnd = hWnd; // Clear open dialog remnants before calling RenderFile() UpdateWindow(m_hWnd); // Convert filename to wide character string wcsncpy(wFile, T2W(szFile), NUMELMS(wFile)-1); wFile[MAX_PATH-1] = 0; // Get the interface for DirectShow's GraphBuilder JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGB)); // Get the media event interface before building the graph JIF(m_pGB->QueryInterface(IID_IMediaEventEx, (void **)&m_pME)); // Have the graph builder construct the appropriate graph automatically JIF(m_pGB->RenderFile(wFile, NULL)); if (SUCCEEDED(hr)) { // QueryInterface for DirectShow interfaces JIF(m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC)); JIF(m_pGB->QueryInterface(IID_IMediaSeeking, (void **)&m_pMS)); // Query for video interfaces, which may not be relevant for audio files JIF(m_pGB->QueryInterface(IID_IVideoWindow, (void **)&m_pVW)); JIF(m_pGB->QueryInterface(IID_IBasicVideo, (void **)&m_pBV)); // Query for audio interfaces, which may not be relevant for video-only files JIF(m_pGB->QueryInterface(IID_IBasicAudio, (void **)&m_pBA)); // Have the graph signal event via window callbacks for performance JIF(m_pME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0)); // Is this an audio-only file (no video component)? CheckVisibility(); if (!m_bAudioOnly) { // Setup the video window JIF(m_pVW->put_Owner((OAHWND)m_hWnd)); JIF(m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)); JIF(m_pVW->SetWindowPosition(m_Rect.left, m_Rect.top, m_Rect.right, m_Rect.bottom)); } else { // Initialize the default player window and enable playback menu items // that don't involve manipulating video size //JIF(InitPlayerWindow()); /* BOOL bRet = SetWindowPos(m_hWnd, NULL, 0, 0, DEFAULT_AUDIO_WIDTH, DEFAULT_AUDIO_HEIGHT, SWP_NOMOVE | SWP_NOOWNERZORDER); */ } // Complete window initialization //ShowWindow(m_hWnd, SW_SHOWNORMAL); //UpdateWindow(m_hWnd); //SetForegroundWindow(m_hWnd); m_bFullscreen = FALSE; // Run the graph to play the media file JIF(m_pMC->Run()); m_nPlayState = Running; SetFocus(m_hWnd); } return hr; }
HRESULT PlayMovieInWindow(LPTSTR szFile, BOOL bReOpenAfterLicenseAcquired) { USES_CONVERSION; WCHAR wFile[MAX_PATH]; HRESULT hr; // Check input string if (!szFile) return E_POINTER; // Clear open dialog remnants before calling RenderFile() UpdateWindow(ghApp); // Convert filename to wide character string wcsncpy(wFile, T2W(szFile), NUMELMS(wFile)-1); wFile[MAX_PATH-1] = 0; // First pass of rendering the media file. If a DRM license must // be acquired before the file can be loaded, then the reopen flag // will be set. if( !bReOpenAfterLicenseAcquired ) { // Get the interface for DirectShow's GraphBuilder JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGB)); JIF(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME)); if(SUCCEEDED(hr)) { // Have the graph signal event via window callbacks // // Start this before we insert the reader filter, since we may need // to monitor DRM license acquistion messages on reader creation // JIF(pME->SetNotifyWindow((OAHWND)ghApp, WM_GRAPHNOTIFY, 0)); // Use special handling for Windows Media files if (IsWindowsMediaFile(szFile)) { // Load the improved ASF reader filter by CLSID hr = CreateFilter(CLSID_WMAsfReader, &g_pReader); if(FAILED(hr)) { Msg(TEXT("Failed to create WMAsfWriter filter! hr=0x%x\0"), hr); return hr; } // Add the ASF reader filter to the graph. For ASF/WMV/WMA content, // this filter is NOT the default and must be added explicitly. hr = pGB->AddFilter(g_pReader, L"ASF Reader"); if(FAILED(hr)) { Msg(TEXT("Failed to add ASF reader filter to graph! hr=0x%x\0"), hr); return hr; } // Create the key provider that will be used to unlock the WM SDK JIF(AddKeyProvider(pGB)); // Create the DRM license event g_hLicenseEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); if( !g_hLicenseEvent ) { return E_OUTOFMEMORY; } // Set its source filename JIF(g_pReader->QueryInterface(IID_IFileSourceFilter, (void **) &g_pFileSource)); // Attempt to load this file hr = g_pFileSource->Load(wFile, NULL); // Handle Digital Rights Management (DRM) errors if(NS_E_LICENSE_REQUIRED == hr) { Msg(TEXT("This media file is protected by DRM and needs a license.\r\n\r\n") TEXT("Attempting to acquire a license...\0")); g_bWaitingForLicense = TRUE; return hr; } else if(NS_E_PROTECTED_CONTENT == hr) { Msg(TEXT("This media file is protected by DRM and needs a license.\r\n\r\n") TEXT("In order to play DRM-encoded content, you must acquire a DRM stub library\r\n") TEXT("from Microsoft and link it with this application. The default version of\r\n") TEXT("the WMStub.lib library does not support Digital Rights Management (DRM).")); return hr; } else if (FAILED(hr)) { Msg(TEXT("Failed to load file in source filter (g_pFileSource->Load())! hr=0x%x\0"), hr); return hr; } // Render the output pins of the ASF reader to build the // remainder of the graph automatically JIF(RenderOutputPins(pGB, g_pReader)); // Since the graph is built and the filters are added to the graph, // the WM ASF reader interface can be released. g_pReader->Release(); g_pReader = NULL; } // Not a Windows Media file, so just render the standard way else { // Have the graph builder construct the appropriate graph automatically JIF(pGB->RenderFile(wFile, NULL)); } } } else { hr = g_pFileSource->Load(wFile, NULL); if( SUCCEEDED( hr ) ) { Msg(TEXT("Successfully loaded file after DRM license acquisition!")); // Render the output pins of the ASF reader to build the // remainder of the graph automatically JIF(RenderOutputPins(pGB, g_pReader)); // Since the graph is built and the filters are added to the graph, // the WM ASF reader interface can be released. g_pReader->Release(); // not really necessary g_pReader = NULL; } else { Msg(TEXT("Failed to Load file after acquiring license! hr=0x%x\0"), hr); } } if( SUCCEEDED( hr ) ) { // QueryInterface for DirectShow interfaces JIF(pGB->QueryInterface(IID_IMediaControl, (void **)&pMC)); JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)); // Query for video interfaces, which may not be relevant for audio files JIF(pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW)); JIF(pGB->QueryInterface(IID_IBasicVideo, (void **)&pBV)); // Query for audio interfaces, which may not be relevant for video-only files JIF(pGB->QueryInterface(IID_IBasicAudio, (void **)&pBA)); // Is this an audio-only file (no video component)? CheckVisibility(); if (!g_bAudioOnly) { // Setup the video window JIF(pVW->put_Owner((OAHWND)ghApp)); JIF(pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)); JIF(InitVideoWindow(1, 1)); GetFrameStepInterface(); } else { // Initialize the default player size and enable playback menu items JIF(InitPlayerWindow()); EnablePlaybackMenu(TRUE, AUDIO); } // Complete window initialization CheckSizeMenu(ID_FILE_SIZE_NORMAL); ShowWindow(ghApp, SW_SHOWNORMAL); UpdateWindow(ghApp); SetForegroundWindow(ghApp); g_bFullscreen = FALSE; UpdateMainTitle(); #ifdef REGISTER_FILTERGRAPH hr = AddGraphToRot(pGB, &g_dwGraphRegister); if (FAILED(hr)) { Msg(TEXT("Failed to register filter graph with ROT! hr=0x%x"), hr); g_dwGraphRegister = 0; } #endif // Run the graph to play the media file JIF(pMC->Run()); g_psCurrent=Running; SetFocus(ghApp); } return hr; }
HRESULT CConvert::StartConversion() { StopConversion(); printf("Initialising conversion...\n"); bool bIsURL = IsURL(m_pSettings->strInputFile); if (bIsURL) return StartConversionDirect(); HRESULT hr = MakeNotificationWindow(); if (FAILED(hr)) return hr; m_pSettings->ApplySettingsToFilter(m_pMPEGWriter); m_nLastEncodedFrameCount = 0; hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&m_pBuilder); if (FAILED(hr)) { StopConversion(); ThrowError(hr, "GraphBuilder could not be created"); return hr; } if (wcscmp(m_pSettings->strInputFile, m_pSettings->strOutputFile) == 0) { StopConversion(); ThrowError(E_FAIL, "The source and target files are the same."); return E_FAIL; } // make the timeline hr = CoCreateInstance(CLSID_AMTimeline, NULL, CLSCTX_INPROC_SERVER, IID_IAMTimeline, (void**) &m_pTimeline); if(FAILED( hr )) { StopConversion(); ThrowError(hr, "Timeline could not be created"); return hr; } BOOL bOutputHasVideo = TRUE; /* switch (m_audioFormat) { case formatMP3: case formatWAV: bOutputHasVideo = FALSE; break; }*/ double dFramerate = 0; BOOL bVideo = FALSE; BOOL bAudio = FALSE; long nWidth = 0; long nHeight = 0; hr = GetFileInfo(m_pSettings->strInputFile, &dFramerate, &m_dSourceLength, &bVideo, &bAudio, &nWidth, &nHeight, 0, 0); if (!bIsURL && FAILED(hr)) { StopConversion(); ThrowError(E_FAIL, "The source file could not be read. The conversion cannot proceed"); return E_FAIL; } /* if ((bAudio && !bVideo || !bOutputHasVideo) && m_bLimitAudio) { SetStopTime(30); } */ /* if (m_dSourceLength == 0 && nWidth && nHeight) { // picture. We will encode as mpeg still image m_dSourceLength = 0.429f; } else */if (m_dSourceLength == 0) { StopConversion(); ThrowError(E_FAIL, "The source file had a duration of 0 seconds. The conversion cannot proceed"); return E_FAIL; } if (bVideo && (nWidth == 0 || nHeight == 0)) { StopConversion(); ThrowError(E_FAIL, "The source video could not be read. The conversion cannot proceed"); return E_FAIL; } if (bVideo && bOutputHasVideo) { hr = AddVideoGroup(dFramerate, nWidth, nHeight); if (FAILED(hr)) { StopConversion(); ThrowError(hr, "Video group could not be added to timeline"); _ASSERT(FALSE); return hr; } } if (bAudio) { hr = AddAudioGroup(); if (FAILED(hr)) { _ASSERT(FALSE); StopConversion(); ThrowError(hr, "Audio group could not be added to timeline"); return hr; } } if (bVideo && bOutputHasVideo) { hr = AddVideoTracks(); if (FAILED(hr)) { _ASSERT(FALSE); StopConversion(); ThrowError(hr, "Video track could not be added to timeline"); return hr; } } if (bAudio) { hr = AddAudioTracks(); if (FAILED(hr)) { _ASSERT(FALSE); StopConversion(); ThrowError(hr, "Audio track could not be added to timeline"); return hr; } } if (bVideo && bOutputHasVideo) { hr = AddVideoSourceFiles(); if (FAILED(hr)) { _ASSERT(FALSE); StopConversion(); ThrowError(hr, "Video source file could not be added to timeline"); return hr; } } if (bAudio) { hr = AddAudioSourceFiles(); if (FAILED(hr)) { _ASSERT(FALSE); StopConversion(); ThrowError(hr, "Audio source file could not be added to timeline"); return hr; } } hr = m_pTimeline->ValidateSourceNames(SFN_VALIDATEF_CHECK|SFN_VALIDATEF_POPUP|SFN_VALIDATEF_REPLACE, NULL, 0); _ASSERT(!FAILED(hr)); hr = CoCreateInstance(CLSID_RenderEngine, NULL, CLSCTX_INPROC_SERVER, IID_IRenderEngine, (void**) &m_pRenderEngine); if (FAILED(hr)) { StopConversion(); ThrowError(hr, "Render engine could not be created"); return hr; } hr = m_pRenderEngine->SetTimelineObject( m_pTimeline ); if (FAILED(hr)) { StopConversion(); ThrowError(hr, "Timeline object corrupt. Bad timeline!"); return hr; } if (m_pSettings->dStartTime || m_pSettings->dEndTime) { hr = m_pRenderEngine->SetRenderRange((__int64)(m_pSettings->dStartTime * UNITS), (__int64)(m_pSettings->dEndTime * UNITS)); if (FAILED(hr)) { _ASSERT(FALSE); } } hr = m_pRenderEngine->ConnectFrontEnd(); if (FAILED(hr)) { StopConversion(); ThrowError(hr, "File could not be rendered"); return hr; } hr = S_OK; hr = m_pRenderEngine->GetFilterGraph( &m_pGraph ); hr |= m_pBuilder->SetFiltergraph(m_pGraph); if (FAILED(hr)) { StopConversion(); ThrowError(hr, "Filter graph could not be retrieved"); return hr; } CComPtr<IPin> pVideoOutPin; CComPtr<IPin> pAudioOutPin; // if it has an audio stream, but no video stream, or does not need video out if (bAudio && (!bVideo || !bOutputHasVideo)) { hr = m_pRenderEngine->GetGroupOutputPin(0, &pAudioOutPin); } else { hr = m_pRenderEngine->GetGroupOutputPin(0, &pVideoOutPin); hr = m_pRenderEngine->GetGroupOutputPin(1, &pAudioOutPin); } hr = RenderOutput(m_pBuilder, m_pGraph, m_pRenderEngine, NULL, pVideoOutPin, pAudioOutPin, NULL); if (FAILED(hr)) { ThrowError(hr, "The output could not be rendered"); _ASSERT(FALSE); StopConversion(); return hr; } if (CheckVisibility() == S_OK) { m_pVideoWindow->put_Owner((OAHWND)m_hwndPreviewWnd); Resize(m_rcWin); m_pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN); } // PromptForGraph(m_pGraph, "edit"); if (m_pCallback) m_pCallback->ConversionAboutToRun(); hr = Run(); _ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) { StopConversion(); ThrowError(hr, "Everything was initialized okay, but the actual conversion could not start. Please check that you can write to the output file."); } return hr; }
HRESULT PlayMovieInWindow(LPTSTR szFile) { USES_CONVERSION; WCHAR wFile[MAX_PATH]; HRESULT hr; // Clear open dialog remnants before calling RenderFile() UpdateWindow(ghApp); // Convert filename to wide character string wcscpy(wFile, T2W(szFile)); // Get the interface for DirectShow's GraphBuilder JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGB)); if(SUCCEEDED(hr)) { // Have the graph builder construct its the appropriate graph automatically JIF(pGB->RenderFile(wFile, NULL)); // QueryInterface for DirectShow interfaces JIF(pGB->QueryInterface(IID_IMediaControl, (void **)&pMC)); JIF(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME)); JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)); JIF(pGB->QueryInterface(IID_IMediaPosition, (void **)&pMP)); // Query for video interfaces, which may not be relevant for audio files JIF(pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW)); JIF(pGB->QueryInterface(IID_IBasicVideo, (void **)&pBV)); // Query for audio interfaces, which may not be relevant for video-only files JIF(pGB->QueryInterface(IID_IBasicAudio, (void **)&pBA)); // Is this an audio-only file (no video component)? CheckVisibility(); // Have the graph signal event via window callbacks for performance JIF(pME->SetNotifyWindow((OAHWND)ghApp, WM_GRAPHNOTIFY, 0)); if (!g_bAudioOnly) { JIF(pVW->put_Owner((OAHWND)ghApp)); JIF(pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)); JIF(InitVideoWindow(1, 1)); GetFrameStepInterface(); } else { JIF(InitPlayerWindow()); } // Let's get ready to rumble! CheckSizeMenu(ID_FILE_SIZE_NORMAL); ShowWindow(ghApp, SW_SHOWNORMAL); UpdateWindow(ghApp); SetForegroundWindow(ghApp); SetFocus(ghApp); g_bFullscreen = FALSE; g_PlaybackRate = 1.0; UpdateMainTitle(); #ifdef REGISTER_FILTERGRAPH hr = AddGraphToRot(pGB, &g_dwGraphRegister); if (FAILED(hr)) { Msg(TEXT("Failed to register filter graph with ROT! hr=0x%x"), hr); g_dwGraphRegister = 0; } #endif // Run the graph to play the media file JIF(pMC->Run()); g_psCurrent=Running; SetFocus(ghApp); } return hr; }
void FNavMeshPath::OffsetFromCorners(float Distance) { SCOPE_CYCLE_COUNTER(STAT_Navigation_OffsetFromCorners); const ARecastNavMesh* MyOwner = Cast<ARecastNavMesh>(GetNavigationDataUsed()); if (PathPoints.Num() == 0 || PathPoints.Num() > 100) { // skip it, there is not need to offset that path from performance point of view return; } #if DEBUG_DRAW_OFFSET GInternalDebugWorld_ = MyOwner->GetWorld(); FlushDebugStrings(GInternalDebugWorld_); FlushPersistentDebugLines(GInternalDebugWorld_); #endif if (bCorridorEdgesGenerated == false) { GeneratePathCorridorEdges(); } const float DistanceSq = Distance * Distance; int32 CurrentEdge = 0; bool bNeedToCopyResults = false; int32 SingleNodePassCount = 0; FNavPathPoint* PathPoint = PathPoints.GetData(); // it's possible we'll be inserting points into the path, so we need to buffer the result TArray<FPathPointInfo> FirstPassPoints; FirstPassPoints.Reserve(PathPoints.Num() + 2); FirstPassPoints.Add(FPathPointInfo(*PathPoint, FVector::ZeroVector, FVector::ZeroVector)); ++PathPoint; // for every point on path find a related corridor edge for (int32 PathNodeIndex = 1; PathNodeIndex < PathPoints.Num()-1 && CurrentEdge < PathCorridorEdges.Num();) { if (FNavMeshNodeFlags(PathPoint->Flags).PathFlags & RECAST_STRAIGHTPATH_OFFMESH_CONNECTION) { // put both ends FirstPassPoints.Add(FPathPointInfo(*PathPoint, FVector(0), FVector(0))); FirstPassPoints.Add(FPathPointInfo(*(PathPoint+1), FVector(0), FVector(0))); PathNodeIndex += 2; PathPoint += 2; continue; } int32 CloserPoint = -1; const FNavigationPortalEdge* Edge = &PathCorridorEdges[CurrentEdge]; for (int32 EdgeIndex = CurrentEdge; EdgeIndex < PathCorridorEdges.Num(); ++Edge, ++EdgeIndex) { const float DistToSequence = FMath::PointDistToSegmentSquared(PathPoint->Location, Edge->Left, Edge->Right); if (DistToSequence <= FMath::Square(KINDA_SMALL_NUMBER)) { const float LeftDistanceSq = FVector::DistSquared(PathPoint->Location, Edge->Left); const float RightDistanceSq = FVector::DistSquared(PathPoint->Location, Edge->Right); if (LeftDistanceSq > DistanceSq && RightDistanceSq > DistanceSq) { ++CurrentEdge; } else { CloserPoint = LeftDistanceSq < RightDistanceSq ? 0 : 1; CurrentEdge = EdgeIndex; } break; } } if (CloserPoint >= 0) { bNeedToCopyResults = true; Edge = &PathCorridorEdges[CurrentEdge]; const float ActualOffset = FPlatformMath::Min(Edge->GetLength()/2, Distance); FNavPathPoint NewPathPoint = *PathPoint; // apply offset const FVector EdgePt0 = Edge->GetPoint(CloserPoint); const FVector EdgePt1 = Edge->GetPoint((CloserPoint+1)%2); const FVector EdgeDir = EdgePt1 - EdgePt0; const FVector EdgeOffset = EdgeDir.GetSafeNormal() * ActualOffset; NewPathPoint.Location = EdgePt0 + EdgeOffset; // update NodeRef (could be different if this is n-th pass on the same PathPoint NewPathPoint.NodeRef = Edge->ToRef; FirstPassPoints.Add(FPathPointInfo(NewPathPoint, EdgePt0, EdgePt1)); // if we've found a matching edge it's possible there's also another one there using the same edge. // that's why we need to repeat the process with the same path point and next edge ++CurrentEdge; // we need to know if we did more than one iteration on a given point // if so then we should not add that point in following "else" statement ++SingleNodePassCount; } else { if (SingleNodePassCount == 0) { // store unchanged FirstPassPoints.Add(FPathPointInfo(*PathPoint, FVector(0), FVector(0))); } else { SingleNodePassCount = 0; } ++PathNodeIndex; ++PathPoint; } } if (bNeedToCopyResults) { if (FirstPassPoints.Num() < 3 || !MyOwner->bUseBetterOffsetsFromCorners) { FNavPathPoint EndPt = PathPoints.Last(); PathPoints.Reset(); for (int32 Index=0; Index < FirstPassPoints.Num(); ++Index) { PathPoints.Add(FirstPassPoints[Index].Point); } PathPoints.Add(EndPt); return; } TArray<FNavPathPoint> DestinationPathPoints; DestinationPathPoints.Reserve(FirstPassPoints.Num() + 2); // don't forget the last point FirstPassPoints.Add(FPathPointInfo(PathPoints[PathPoints.Num()-1], FVector::ZeroVector, FVector::ZeroVector)); int32 StartPointIndex = 0; int32 LastVisiblePointIndex = 0; int32 TestedPointIndex = 1; int32 LastPointIndex = FirstPassPoints.Num()-1; const int32 MaxSteps = 200; for (int32 StepsLeft = MaxSteps; StepsLeft >= 0; StepsLeft--) { if (StartPointIndex == TestedPointIndex || StepsLeft == 0) { // something went wrong, or exceeded limit of steps (= went even more wrong) DestinationPathPoints.Reset(); break; } const FNavMeshNodeFlags LastVisibleFlags(FirstPassPoints[LastVisiblePointIndex].Point.Flags); const FNavMeshNodeFlags StartPointFlags(FirstPassPoints[StartPointIndex].Point.Flags); bool bWantsVisibilityInsert = true; if (StartPointFlags.PathFlags & RECAST_STRAIGHTPATH_OFFMESH_CONNECTION) { AppendPathPointsHelper(DestinationPathPoints, FirstPassPoints, StartPointIndex); AppendPathPointsHelper(DestinationPathPoints, FirstPassPoints, StartPointIndex + 1); StartPointIndex++; LastVisiblePointIndex = StartPointIndex; TestedPointIndex = LastVisiblePointIndex + 1; // skip inserting new points bWantsVisibilityInsert = false; } bool bVisible = false; if (((LastVisibleFlags.PathFlags & RECAST_STRAIGHTPATH_OFFMESH_CONNECTION) == 0) && (StartPointFlags.Area == LastVisibleFlags.Area)) { FPathPointInfo LastVisiblePoint; bVisible = CheckVisibility( &FirstPassPoints[StartPointIndex], &FirstPassPoints[TestedPointIndex], PathCorridorEdges, Distance, &LastVisiblePoint ); if (!bVisible) { if (LastVisiblePoint.Point.Location.IsNearlyZero()) { DestinationPathPoints.Reset(); break; } else if (StartPointIndex == LastVisiblePointIndex) { /** add new point only if we don't see our next location otherwise use last visible point*/ LastVisiblePoint.Point.Flags = FirstPassPoints[LastVisiblePointIndex].Point.Flags; LastVisiblePointIndex = FirstPassPoints.Insert( LastVisiblePoint, StartPointIndex+1 ); LastPointIndex = FirstPassPoints.Num()-1; // TODO: potential infinite loop - keeps inserting point without visibility } } } if (bWantsVisibilityInsert) { if (bVisible) { #if PATH_OFFSET_KEEP_VISIBLE_POINTS AppendPathPointsHelper(DestinationPathPoints, FirstPassPoints, StartPointIndex); LastVisiblePointIndex = TestedPointIndex; StartPointIndex = LastVisiblePointIndex; TestedPointIndex++; #else LastVisiblePointIndex = TestedPointIndex; TestedPointIndex++; #endif } else { AppendPathPointsHelper(DestinationPathPoints, FirstPassPoints, StartPointIndex); StartPointIndex = LastVisiblePointIndex; TestedPointIndex = LastVisiblePointIndex + 1; } } // if reached end of path, add current and last points to close it and leave loop if (TestedPointIndex > LastPointIndex) { AppendPathPointsHelper(DestinationPathPoints, FirstPassPoints, StartPointIndex); AppendPathPointsHelper(DestinationPathPoints, FirstPassPoints, LastPointIndex); break; } } if (DestinationPathPoints.Num()) { PathPoints = DestinationPathPoints; } } }