bool PathInfo::Update(const float destX, const float destY, const float destZ, bool useStraightPath) { PathNode newDest(destX, destY, m_sourceUnit->GetMap()->GetHeight(destX,destY,destZ,100.0f)); PathNode oldDest = getEndPosition(); setEndPosition(newDest); float x, y, z; m_sourceUnit->GetPosition(x, y, z); PathNode newStart(x, y, m_sourceUnit->GetMap()->GetHeight(x,y,z,100.0f)); PathNode oldStart = getStartPosition(); setStartPosition(newStart); m_useStraightPath = useStraightPath; PATH_DEBUG("++ PathInfo::Update() for %u \n", m_sourceUnit->GetGUID()); // make sure navMesh works - we can run on map w/o mmap if (!m_navMesh || !m_navMeshQuery) { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return true; } float dist = m_sourceUnit->GetObjectBoundingRadius(); bool oldDestInRange = inRange(oldDest, newDest, dist, dist); // this can happen only if caller did a bad job calculating the need for path update if (oldDestInRange && inRange(newStart, oldStart, dist, dist)) { setEndPosition(oldDest); setStartPosition(oldStart); return false; } // check if destination moved - if not we can optimize something here // we are following old, precalculated path? if (oldDestInRange && m_pathPoints.size() > 2) { // our target is not moving - we just coming closer // we are moving on precalculated path - enjoy the ride PATH_DEBUG("++ PathInfo::Update:: precalculated path\n"); m_pathPoints.crop(1, 0); setNextPosition(m_pathPoints[1]); return false; } else { // target moved, so we need to update the poly path BuildPolyPath(newStart, newDest); return true; } }
////////////////// PathInfo ////////////////// PathInfo::PathInfo(const Unit* owner, const float destX, const float destY, const float destZ, bool useStraightPath) : m_polyLength(0), m_type(PATHFIND_BLANK), m_useStraightPath(useStraightPath), m_sourceUnit(owner), m_navMesh(NULL), m_navMeshQuery(NULL) { PathNode endPoint(destX, destY, destZ); setEndPosition(endPoint); float x,y,z; m_sourceUnit->GetPosition(x, y, z); PathNode startPoint(x, y, z); setStartPosition(startPoint); DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::PathInfo for %u \n", m_sourceUnit->GetGUID()); uint32 mapId = m_sourceUnit->GetMapId(); if (MMAP::MMapFactory::IsPathfindingEnabled(mapId)) { MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager(); m_navMesh = mmap->GetNavMesh(mapId); m_navMeshQuery = mmap->GetNavMeshQuery(mapId, m_sourceUnit->GetInstanceId()); } createFilter(); if (m_navMesh && m_navMeshQuery && !m_sourceUnit->hasUnitState(UNIT_STAT_IGNORE_PATHFINDING)) { BuildPolyPath(startPoint, endPoint); } else { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); } }
void testSetEndPosition_Restore_Reverse(bool unique) { auto harnessHelper = newHarnessHelper(); auto opCtx = harnessHelper->newOperationContext(); auto sorted = harnessHelper->newSortedDataInterface( unique, { {key1, loc1}, {key2, loc1}, {key3, loc1}, {key4, loc1}, }); auto cursor = sorted->newCursor(opCtx.get(), false); cursor->setEndPosition(key2, false); // Should never see key1 or key2. ASSERT_EQ(cursor->seek(key4, true), IndexKeyEntry(key4, loc1)); cursor->save(); cursor->restore(); ASSERT_EQ(cursor->next(), IndexKeyEntry(key3, loc1)); cursor->save(); removeFromIndex(opCtx, sorted, { {key2, loc1}, {key3, loc1}, }); cursor->restore(); ASSERT_EQ(cursor->next(), boost::none); }
void testSetEndPosition_Seek_Reverse(bool unique, bool inclusive) { auto harnessHelper = newHarnessHelper(); auto opCtx = harnessHelper->newOperationContext(); auto sorted = harnessHelper->newSortedDataInterface(unique, { {key1, loc1}, {key2, loc1}, // No key3 {key4, loc1}, }); auto cursor = sorted->newCursor(opCtx.get(), false); cursor->setEndPosition(key2, inclusive); // Directly seeking past end is considered out of range. ASSERT_EQ(cursor->seek(key1, true), boost::none); ASSERT_EQ(cursor->seekExact(key1), boost::none); // Seeking to key2 directly or indirectly is only returned if endPosition is inclusive. auto maybeKey2 = inclusive ? boost::make_optional(IndexKeyEntry(key2, loc1)) : boost::none; // direct ASSERT_EQ(cursor->seek(key2, true), maybeKey2); ASSERT_EQ(cursor->seekExact(key2), maybeKey2); // indirect ASSERT_EQ(cursor->seek(key3, true), maybeKey2); cursor->saveUnpositioned(); removeFromIndex(opCtx, sorted, {{key2, loc1}}); cursor->restore(); ASSERT_EQ(cursor->seek(key3, true), boost::none); ASSERT_EQ(cursor->seek(key2, true), boost::none); }
void testSetEndPosition_Next_Reverse(bool unique, bool inclusive) { auto harnessHelper = newHarnessHelper(); auto opCtx = harnessHelper->newOperationContext(); auto sorted = harnessHelper->newSortedDataInterface( unique, { {key1, loc1}, {key2, loc1}, {key3, loc1}, {key4, loc1}, {key5, loc1}, }); // Dup key on end point. Illegal for unique indexes. if (!unique) insertToIndex(opCtx, sorted, {{key3, loc2}}); auto cursor = sorted->newCursor(opCtx.get(), false); cursor->setEndPosition(key3, inclusive); ASSERT_EQ(cursor->seek(key5, true), IndexKeyEntry(key5, loc1)); ASSERT_EQ(cursor->next(), IndexKeyEntry(key4, loc1)); if (inclusive) { if (!unique) ASSERT_EQ(cursor->next(), IndexKeyEntry(key3, loc2)); ASSERT_EQ(cursor->next(), IndexKeyEntry(key3, loc1)); } ASSERT_EQ(cursor->next(), boost::none); ASSERT_EQ(cursor->next(), boost::none); // don't resurrect. }
void testSetEndPosition_RestoreEndCursor_Reverse(bool unique) { auto harnessHelper = newHarnessHelper(); auto opCtx = harnessHelper->newOperationContext(); auto sorted = harnessHelper->newSortedDataInterface(unique, { {key1, loc1}, {key4, loc1}, }); auto cursor = sorted->newCursor(opCtx.get(), false); cursor->setEndPosition(key3, true); ASSERT_EQ(cursor->seek(key4, true), IndexKeyEntry(key4, loc1)); cursor->saveUnpositioned(); insertToIndex(opCtx, sorted, { {key2, loc1}, // in range {key3, loc1}, // out of range }); cursor->restore(); // must restore end cursor even with saveUnpositioned(). ASSERT_EQ(cursor->seek(key4, true), IndexKeyEntry(key4, loc1)); ASSERT_EQ(cursor->next(), IndexKeyEntry(key3, loc1)); ASSERT_EQ(cursor->next(), boost::none); }
bool PathFinder::calculate(float destX, float destY, float destZ, bool forceDest) { Vector3 oldDest = getEndPosition(); Vector3 dest(destX, destY, destZ); setEndPosition(dest); float x, y, z; m_sourceUnit->GetPosition(x, y, z); Vector3 start(x, y, z); setStartPosition(start); m_forceDestination = forceDest; DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::calculate() for %u \n", m_sourceUnit->GetGUIDLow()); // make sure navMesh works - we can run on map w/o mmap // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->hasUnitState(UNIT_STAT_IGNORE_PATHFINDING) || !HaveTile(start) || !HaveTile(dest) || m_sourceUnit->m_movementInfo.HasMovementFlag(MOVEFLAG_TAXI)) //for transport { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return true; } updateFilter(); BuildPolyPath(start, dest); return true; }
////////////////// PathInfo ////////////////// PathInfo::PathInfo(const Unit* owner, const float destX, const float destY, const float destZ, bool useStraightPath) : m_pathPolyRefs(NULL), m_polyLength(0), m_type(PATHFIND_BLANK), m_useStraightPath(useStraightPath), m_sourceUnit(owner), m_navMesh(NULL), m_navMeshQuery(NULL) { PathNode endPoint(destX, destY, destZ); setEndPosition(endPoint); float x,y,z; m_sourceUnit->GetPosition(x, y, z); PathNode startPoint(x, y, m_sourceUnit->GetMap()->GetHeight(x,y,z,100.0f)); setStartPosition(startPoint); PATH_DEBUG("++ PathInfo::PathInfo for %u \n", m_sourceUnit->GetGUID()); uint32 mapId = m_sourceUnit->GetMapId(); MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager(); m_navMesh = mmap->GetNavMesh(mapId); m_navMeshQuery = mmap->GetNavMeshQuery(mapId); if (m_navMesh && m_navMeshQuery) { BuildPolyPath(startPoint, endPoint); } else { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); } }
bool PathFinder::calculate(float destX, float destY, float destZ, bool forceDest) { Vector3 oldDest = getEndPosition(); Vector3 dest(destX, destY, destZ); setEndPosition(dest); float x, y, z; m_sourceUnit->GetPosition(x, y, z); Vector3 start(x, y, z); setStartPosition(start); m_forceDestination = forceDest; DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::calculate() for %u \n", m_sourceUnit->GetGUIDLow()); // make sure navMesh works - we can run on map w/o mmap // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->hasUnitState(UNIT_STAT_IGNORE_PATHFINDING) || !HaveTile(start) || !HaveTile(dest) || (m_sourceUnit->GetTypeId() == TYPEID_UNIT && ((Creature*)m_sourceUnit)->IsLevitating())) { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return true; } updateFilter(); { ReadGuard Guard(MMAP::MMapFactory::createOrGetMMapManager()->GetLock(m_sourceUnit->GetMapId())); BuildPolyPath(start, dest); } return true; }
////////////////// PathInfo ////////////////// PathInfo::PathInfo(WorldObject* from, const float x, const float y, const float z) : m_length(0), m_pathPolyRefs(0), m_pathPoints(0), m_sourceObject(from), m_type(PATHFIND_BLANK) { clear(); setEndPosition(x, y, z); Build(); }
bool PathFinderMovementGenerator::calculate(float destX, float destY, float destZ, bool forceDest) { if (!SkyFire::IsValidMapCoord(destX, destY, destZ) || !SkyFire::IsValidMapCoord(m_sourceUnit->GetPositionX(), m_sourceUnit->GetPositionY(), m_sourceUnit->GetPositionZ())) return false; Vector3 oldDest = getEndPosition(); Vector3 dest(destX, destY, destZ); setEndPosition(dest); float x, y, z; m_sourceUnit->GetPosition(x, y, z); Vector3 start(x, y, z); setStartPosition(start); m_forceDestination = forceDest; sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::calculate() for %u \n", m_sourceUnit->GetGUIDLow()); // make sure navMesh works - we can run on map w/o mmap // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING) || !HaveTile(start) || !HaveTile(dest)) { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return true; } updateFilter(); // check if destination moved - if not we can optimize something here // we are following old, precalculated path? float dist = m_sourceUnit->GetObjectSize(); if (inRange(oldDest, dest, dist, dist) && m_pathPoints.size() > 2) { // our target is not moving - we just coming closer // we are moving on precalculated path - enjoy the ride sLog->outStaticDebug("++ PathFinderMovementGenerator::calculate:: precalculated path\n"); m_pathPoints.erase(m_pathPoints.begin()); return false; } else { // target moved, so we need to update the poly path m_navMeshLock->acquire_read(); BuildPolyPath(start, dest); m_navMeshLock->release(); return true; } }
bool PathInfo::Update(const float destX, const float destY, const float destZ, bool useStraightPath, bool forceDest) { PathNode newDest(destX, destY, destZ); PathNode oldDest = getEndPosition(); setEndPosition(newDest); float x, y, z; m_sourceUnit->GetPosition(x, y, z); PathNode newStart(x, y, z); PathNode oldStart = getStartPosition(); setStartPosition(newStart); m_useStraightPath = useStraightPath; m_forceDestination = forceDest; DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::Update() for %u \n", m_sourceUnit->GetGUID()); // make sure navMesh works - we can run on map w/o mmap if (!m_navMesh || !m_navMeshQuery || !HaveTiles(newDest) || m_sourceUnit->hasUnitState(UNIT_STAT_IGNORE_PATHFINDING)) { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return true; } updateFilter(); // check if destination moved - if not we can optimize something here // we are following old, precalculated path? float dist = m_sourceUnit->GetObjectBoundingRadius(); if (inRange(oldDest, newDest, dist, dist) && m_pathPoints.size() > 2) { // our target is not moving - we just coming closer // we are moving on precalculated path - enjoy the ride DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::Update:: precalculated path\n"); m_pathPoints.crop(1, 0); setNextPosition(m_pathPoints[1]); return false; } else { // target moved, so we need to update the poly path BuildPolyPath(newStart, newDest); return true; } }
void testSetEndPosition_Empty_Reverse(bool unique, bool inclusive) { auto harnessHelper = newHarnessHelper(); auto opCtx = harnessHelper->newOperationContext(); auto sorted = harnessHelper->newSortedDataInterface(unique, { {key1, loc1}, {key2, loc1}, {key3, loc1}, }); auto cursor = sorted->newCursor(opCtx.get(), false); cursor->setEndPosition(BSONObj(), inclusive); ASSERT_EQ(cursor->seek(key3, true), IndexKeyEntry(key3, loc1)); ASSERT_EQ(cursor->next(), IndexKeyEntry(key2, loc1)); ASSERT_EQ(cursor->next(), IndexKeyEntry(key1, loc1)); ASSERT_EQ(cursor->next(), boost::none); }
bool PathFinder::calculate(float destX, float destY, float destZ, bool forceDest) { Vector3 oldDest = getEndPosition(); Vector3 dest(destX, destY, destZ); setEndPosition(dest); float x, y, z; m_sourceUnit->GetPosition(x, y, z); Vector3 start(x, y, z); setStartPosition(start); m_forceDestination = forceDest; DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::calculate() for %u \n", m_sourceUnit->GetGUIDLow()); // make sure navMesh works - we can run on map w/o mmap // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->hasUnitState(UNIT_STAT_IGNORE_PATHFINDING) || !HaveTile(start) || !HaveTile(dest)) { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return true; } updateFilter(); // check if destination moved - if not we can optimize something here // we are following old, precalculated path? float dist = m_sourceUnit->GetObjectBoundingRadius(); if (inRange(oldDest, dest, dist, dist) && m_pathPoints.size() > 2) { // our target is not moving - we just coming closer // we are moving on precalculated path - enjoy the ride DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::calculate:: precalculated path\n"); m_pathPoints.erase(m_pathPoints.begin()); return false; } else { // target moved, so we need to update the poly path ReadGuard Guard(MMAP::MMapFactory::createOrGetMMapManager()->GetLock(m_sourceUnit->GetMapId())); BuildPolyPath(start, dest); return true; } }
bool PathInfo::Update(float destX, float destY, float destZ, bool forceDest) { float x, y, z; m_sourceUnit->GetPosition(x, y, z); if (!Oregon::IsValidMapCoord(destX, destY, destZ) || !Oregon::IsValidMapCoord(x, y, z)) { sLog.outMMap("PathInfo::Update() called with invalid map coords, destX: %f destY: %f destZ: %f x: %f y: %f z: %f for creature %u", destX, destY, destZ, x, y, z, m_sourceUnit->GetGUIDLow()); m_type = PATHFIND_NOPATH; return false; } Vector3 oldDest = getEndPosition(); Vector3 newDest(destX, destY, destZ); setEndPosition(newDest); Vector3 newStart(x, y, z); setStartPosition(newStart); m_forceDestination = forceDest; sLog.outMMap("PathInfo::Update() for %u \n", m_sourceUnit->GetGUIDLow()); // make sure navMesh works - we can run on map w/o mmap // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING) || !HaveTile(newStart) || !HaveTile(newDest)) { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return true; } updateFilter(); BuildPolyPath(newStart, newDest); return true; }
void GifBrush::onMouseUp(Timeline *timeline, ofFbo *fbo, int x, int y) { int numGifFrames = getNumFramesInGif(); setEndPosition(x,y); timeline->setInPointToCurrent(); // Loop through the next frames of the timeline adding the gif's frames to the timeline for(int frameNum = 0; frameNum < numGifFrames; frameNum++) { writeToFbo(fbo, frameNum); // add as many frames as we need to the timeline so the gif can be fully loaded // TODO: Check to make sure with the clips concept this is still implemented correctly if(timeline->getCurFrameNum() == timeline->getFrameCount() - 1) { timeline->addFrameNextTo(); } timeline->setCurFrame(1, RELATIVE); fbo = timeline->getCurFbo(); } timeline->setOutPointToCurrent(); // restore cur frame to the first frame and set it as the start frame timeline->setCurFrame(-numGifFrames, RELATIVE); setInitialized(false); }
////////////////// PathInfo ////////////////// PathInfo::PathInfo(const Unit* owner, const float destX, const float destY, const float destZ, bool useStraightPath) : m_pathPolyRefs(NULL), m_polyLength(0), m_type(PATHFIND_BLANK), m_useStraightPath(useStraightPath), m_sourceUnit(owner), m_navMesh(NULL), m_navMeshQuery(NULL) { PathNode endPoint(destX, destY, destZ); setEndPosition(endPoint); float x,y,z; m_sourceUnit->GetPosition(x, y, z); PathNode startPoint(x, y, z); setStartPosition(startPoint); PATH_DEBUG("++ PathInfo::PathInfo for %u \n", m_sourceUnit->GetGUID()); const Map* map = m_sourceUnit->GetMap(); if (map->IsPathfindingEnabled()) m_navMesh = map->GetNavMesh(); if (m_navMesh) { m_navMeshQuery = dtAllocNavMeshQuery(); ASSERT(m_navMeshQuery); if(DT_SUCCESS != m_navMeshQuery->init(m_navMesh, MESH_MAX_NODES)) { sLog->outError("%u's PathInfo navMeshQuery failed to init", m_sourceUnit->GetGUID()); return; } BuildPolyPath(startPoint, endPoint); } else { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); } }
void PathInfo::Update(const float destX, const float destY, const float destZ) { float x, y, z; // update start and end m_sourceObject->GetPosition(x, y, z); setStartPosition(x, y, z); setEndPosition(destX, destY, destZ); // make sure navMesh works if(!m_navMesh) { m_sourceObject->GetPosition(x, y, z); m_navMesh = m_sourceObject->GetMap()->GetNavMesh(); if(!m_navMesh) { // can't pathfind if navmesh doesn't exist shortcut(); return; } } if(!m_pathPolyRefs) { // path was not built before, most likely because navmesh wasn't working // start from scratch, then return Build(); return; } // should be safe to update path now bool startOffPath = false; bool endOffPath = false; // find start and end poly // navMesh.findNearestPoly is expensive, so first we check just the current path getStartPosition(x, y, z); dtPolyRef startPoly = getPathPolyByPosition(x, y, z); getEndPosition(x, y, z); dtPolyRef endPoly = getPathPolyByPosition(x, y, z); if(startPoly != 0 && endPoly != 0) trim(startPoly, endPoly); else { // start or end is off the path, need to find the polygon float extents[3] = {2.f, 4.f, 2.f}; // bounds of poly search area dtQueryFilter filter = dtQueryFilter(); // filter for poly search if(!startPoly) { getStartPosition(x, y, z); float startPos[3] = {y, z, x}; startOffPath = true; startPoly = m_navMesh->findNearestPoly(startPos, extents, &filter, 0); } if(!endPoly) { getEndPosition(x, y, z); float endPos[3] = {y, z, x}; endOffPath = true; endPoly = m_navMesh->findNearestPoly(endPos, extents, &filter, 0); } if(startPoly == 0 || endPoly == 0) { // source or dest not near navmesh polygons: // flying, falling, swimming, or navmesh has a hole // ignore obstacles/terrain is better than giving up // PATHFIND TODO: prevent walking/swimming mobs from flying into the air shortcut(); return; } } if(startPoly == endPoly) { // start and end are on same polygon // just need to move in straight line // PATHFIND TODO: prevent walking/swimming mobs from flying into the air clear(); m_pathPolyRefs = new dtPolyRef[1]; m_pathPolyRefs[0] = startPoly; m_length = 1; getEndPosition(x, y, z); setNextPosition(x, y, z); m_type = PathType(m_type | PATHFIND_NORMAL); return; } if(startOffPath) { bool adjacent = false; int i; for(i = 0; i < DT_VERTS_PER_POLYGON; ++i) if(startPoly == m_navMesh->getPolyByRef(m_pathPolyRefs[0])->neis[i]) { adjacent = true; break; } if(adjacent) { // startPoly is adjacent to the path, we can add it to the start of the path // 50th poly will fall off of path, shouldn't be an issue because most paths aren't that long m_length = m_length < MAX_PATH_LENGTH ? m_length + 1 : m_length; dtPolyRef* temp = new dtPolyRef[m_length]; temp[0] = startPoly; for(i = 1; i < m_length; ++i) temp[i] = m_pathPolyRefs[i - 1]; delete [] m_pathPolyRefs; m_pathPolyRefs = temp; } else { // waste of time to optimize, just find brand new path Build(startPoly, endPoly); return; } } if(endOffPath) { bool adjacent = false; int i; for(i = 0; i < DT_VERTS_PER_POLYGON; ++i) if(startPoly == m_navMesh->getPolyByRef(m_pathPolyRefs[0])->neis[i]) { adjacent = true; break; } if(adjacent) { if(m_length < MAX_PATH_LENGTH) { // endPoly is adjacent to the path, and we have enough room to add it to the end dtPolyRef* temp = new dtPolyRef[m_length + 1]; for(i = 0; i < m_length; ++i) temp[i] = m_pathPolyRefs[i]; temp[i] = endPoly; delete [] m_pathPolyRefs; m_pathPolyRefs = temp; } //else // ; // endPoly is adjacent to the path, we just don't have room to store it } else { // waste of time to optimize, just find brand new path Build(startPoly, endPoly); return; } } updateNextPosition(); }
void GifBrush::updateCanvas(Timeline *timeline, ofFbo *fbo, float x, float y, float pressure, ofColor col) { setEndPosition(x, y); draw(); }
/* Start and end points for shapes should match unless * the mouse is moved (moving mouse with pressed left key gives form to the figure) */ void Shape::startDerivation(const QPoint &start) { setStartPosition(start); setEndPosition(start); }
void Shape::endDerivation(const QPoint &start) { setEndPosition(start); }
void QNanoLinearGradient::setEndPosition(const QPointF &end) { setEndPosition(end.x(), end.y()); m_changed = true; }