// Returns true if other has a similar stroke width to this. bool BLOBNBOX::MatchingStrokeWidth(const BLOBNBOX& other, double fractional_tolerance, double constant_tolerance) const { // The perimeter-based width is used as a backup in case there is // no information in the blob. double p_width = area_stroke_width(); double n_p_width = other.area_stroke_width(); float h_tolerance = horz_stroke_width_ * fractional_tolerance + constant_tolerance; float v_tolerance = vert_stroke_width_ * fractional_tolerance + constant_tolerance; double p_tolerance = p_width * fractional_tolerance + constant_tolerance; bool h_zero = horz_stroke_width_ == 0.0f || other.horz_stroke_width_ == 0.0f; bool v_zero = vert_stroke_width_ == 0.0f || other.vert_stroke_width_ == 0.0f; bool h_ok = !h_zero && NearlyEqual(horz_stroke_width_, other.horz_stroke_width_, h_tolerance); bool v_ok = !v_zero && NearlyEqual(vert_stroke_width_, other.vert_stroke_width_, v_tolerance); bool p_ok = h_zero && v_zero && NearlyEqual(p_width, n_p_width, p_tolerance); // For a match, at least one of the horizontal and vertical widths // must match, and the other one must either match or be zero. // Only if both are zero will we look at the perimeter metric. return p_ok || ((v_ok || h_ok) && (h_ok || h_zero) && (v_ok || v_zero)); }
/********************************************************************** * make_rotated_tess_blob * * Make a single Tess style blob, applying the given rotation and * renormalizing. **********************************************************************/ TBLOB *make_rotated_tess_blob(const DENORM* denorm, PBLOB *blob, BOOL8 flatten) { if (denorm != NULL && denorm->block() != NULL && denorm->block()->classify_rotation().y() != 0.0) { TBOX box = blob->bounding_box(); int src_width = box.width(); int src_height = box.height(); src_width = static_cast<int>(src_width / denorm->scale() + 0.5); src_height = static_cast<int>(src_height / denorm->scale() + 0.5); int x_middle = (box.left() + box.right()) / 2; int y_middle = (box.top() + box.bottom()) / 2; PBLOB* rotated_blob = PBLOB::deep_copy(blob); rotated_blob->move(FCOORD(-x_middle, -y_middle)); rotated_blob->rotate(denorm->block()->classify_rotation()); ICOORD median_size = denorm->block()->median_size(); int tolerance = median_size.x() / 8; // TODO(dsl/rays) find a better normalization solution. In the mean time // make it work for CJK by normalizing for Cap height in the same way // as is applied in compute_block_xheight when the row is presumed to // be ALLCAPS, i.e. the x-height is the fixed fraction // blob height * textord_merge_x / (textord_merge_x + textord_merge_asc) if (NearlyEqual(src_width, static_cast<int>(median_size.x()), tolerance) && NearlyEqual(src_height, static_cast<int>(median_size.y()), tolerance)) { float target_height = bln_x_height * (textord_merge_x + textord_merge_asc) / textord_merge_x; rotated_blob->scale(target_height / box.width()); rotated_blob->move(FCOORD(0.0f, bln_baseline_offset - rotated_blob->bounding_box().bottom())); } TBLOB* result = make_tess_blob(rotated_blob, flatten); delete rotated_blob; return result; } else { return make_tess_blob(blob, flatten); } }
static bool Quadable(EERIEPOLY * ep, EERIEPOLY * ep2, float tolerance) { long count=0; long ep_notcommon=-1; long ep2_notcommon=-1; if(ep2->type & POLY_QUAD) return false; if(ep->tex != ep2->tex) return false; long typ1=ep->type&(~POLY_QUAD); long typ2=ep2->type&(~POLY_QUAD); if(typ1!=typ2) return false; if((ep->type & POLY_TRANS) && ep->transval != ep2->transval) return false; ep->norm = CalcFaceNormal(ep->v); if(glm::abs(glm::dot(ep->norm, ep2->norm)) < 1.f - tolerance) return false; for (long i=0;i<3;i++) { long common=-1; long common2=-1; for (long j=0;j<3;j++) { if ( ( NearlyEqual(ep->v[i].p.x,ep2->v[j].p.x) ) && ( NearlyEqual(ep->v[i].p.y,ep2->v[j].p.y) ) && ( NearlyEqual(ep->v[i].p.z,ep2->v[j].p.z) ) && ( NearlyEqual(ep->v[i].uv.x,ep2->v[j].uv.x) ) && ( NearlyEqual(ep->v[i].uv.y,ep2->v[j].uv.y) ) ) { count++; common=j; } if ( ( NearlyEqual(ep->v[j].p.x,ep2->v[i].p.x) ) && ( NearlyEqual(ep->v[j].p.y,ep2->v[i].p.y) ) && ( NearlyEqual(ep->v[j].p.z,ep2->v[i].p.z) ) && ( NearlyEqual(ep->v[j].uv.x,ep2->v[i].uv.x) ) && ( NearlyEqual(ep->v[j].uv.y,ep2->v[i].uv.y) ) ) { common2=j; } } if (common2==-1) ep2_notcommon=i; if (common==-1) ep_notcommon=i; } if ((count>=2) && (ep_notcommon!=-1) && (ep2_notcommon!=-1)) { ep2->type |= POLY_QUAD; switch (ep2_notcommon) { case 1: CopyVertices(ep2,3,0); CopyVertices(ep2,0,1); CopyVertices(ep2,1,2); CopyVertices(ep2,2,3); break; case 2: CopyVertices(ep2,3,0); CopyVertices(ep2,0,2); CopyVertices(ep2,2,1); CopyVertices(ep2,1,3); break; } CopyVertices(ep2,3,0); ep2->v[3].p = ep->v[ep_notcommon].p; ep2->tv[3].uv = ep2->v[3].uv = ep->v[ep_notcommon].uv; ep2->tv[3].color = ep2->v[3].color = Color::white.toRGB(); ep2->tv[3].rhw = ep2->v[3].rhw = 1.f; ep2->center = (ep2->v[0].p + ep2->v[1].p + ep2->v[2].p + ep2->v[3].p) * 0.25f; ep2->max = glm::max(ep2->max, ep2->v[3].p); ep2->min = glm::min(ep2->min, ep2->v[3].p); ep2->norm2 = ep->norm; ep2->area += fdist((ep2->v[1].p + ep2->v[2].p) * .5f, ep2->v[3].p) * fdist(ep2->v[3].p, ep2->v[1].p)*.5f; // should this be v[2] instead of v[3]? return true; } return false; }
void CTaskbarNotifier::Show(LPCTSTR szCaption, int nMsgType, LPCTSTR pszLink, BOOL bAutoClose) { if (nMsgType == TBN_NONOTIFY) return; UINT nScreenWidth; UINT nScreenHeight; UINT nEvents; UINT nBitmapSize; CRect rcTaskbar; CTaskbarNotifierHistory* messagePTR; m_strCaption = szCaption; m_nActiveMessageType = nMsgType; m_strLink = pszLink; if (m_bAutoClose) // sets it only if already true, else wait for user action m_bAutoClose = bAutoClose; if ((nMsgType != TBN_NULL) && (nMsgType != TBN_LOG) && (nMsgType != TBN_IMPORTANTEVENT)) { //Add element into string list. Max 5 elements. if (m_MessageHistory.GetCount() == 5) { messagePTR = (CTaskbarNotifierHistory*)m_MessageHistory.RemoveHead(); delete messagePTR; messagePTR = NULL; } messagePTR = new CTaskbarNotifierHistory; messagePTR->m_strMessage = m_strCaption; messagePTR->m_nMessageType = nMsgType; messagePTR->m_strLink = m_strLink; m_MessageHistory.AddTail(messagePTR); } nScreenWidth = ::GetSystemMetrics(SM_CXSCREEN); nScreenHeight = ::GetSystemMetrics(SM_CYSCREEN); HWND hWndTaskbar = ::FindWindow(_T("Shell_TrayWnd"), 0); ::GetWindowRect(hWndTaskbar, &rcTaskbar); // Daniel Lohmann: Calculate taskbar position from its window rect. However, on XP it may be that // the taskbar is slightly larger or smaller than the screen size. Therefore we allow some tolerance here. if (NearlyEqual(rcTaskbar.left, 0, TASKBAR_X_TOLERANCE) && NearlyEqual(rcTaskbar.right, nScreenWidth, TASKBAR_X_TOLERANCE)) { // Taskbar is on top or on bottom m_nTaskbarPlacement = NearlyEqual(rcTaskbar.top, 0, TASKBAR_Y_TOLERANCE) ? ABE_TOP : ABE_BOTTOM; nBitmapSize = m_nBitmapHeight; } else { // Taskbar is on left or on right m_nTaskbarPlacement = NearlyEqual(rcTaskbar.left, 0, TASKBAR_X_TOLERANCE) ? ABE_LEFT : ABE_RIGHT; nBitmapSize = m_nBitmapWidth; } // We calculate the pixel increment and the timer value for the showing animation if (m_dwTimeToShow > m_dwTimerPrecision) { nEvents = min((m_dwTimeToShow / m_dwTimerPrecision) / 2, nBitmapSize); //<<-- enkeyDEV(Ottavio84) -Reduced frames of a half- //ADDED by VC-fengwen on 2007/10/08 <begin> : nEvents 有可能是0,则会出现异常。 if (0 == nEvents) nEvents = 1; //ADDED by VC-fengwen on 2007/10/08 <end> : nEvents 有可能是0,则会出现异常。 m_dwShowEvents = m_dwTimeToShow / nEvents; m_nIncrementShow = nBitmapSize / nEvents; } else { m_dwShowEvents = m_dwTimerPrecision; m_nIncrementShow = nBitmapSize; } // We calculate the pixel increment and the timer value for the hiding animation if (m_dwTimeToHide > m_dwTimerPrecision) { nEvents = min((m_dwTimeToHide / m_dwTimerPrecision / 2), nBitmapSize); //<<-- enkeyDEV(Ottavio84) -Reduced frames of a half- //ADDED by VC-fengwen on 2007/10/08 <begin> : nEvents 有可能是0,则会出现异常。 if (0 == nEvents) nEvents = 1; //ADDED by VC-fengwen on 2007/10/08 <end> : nEvents 有可能是0,则会出现异常。 m_dwHideEvents = m_dwTimeToHide / nEvents; m_nIncrementHide = nBitmapSize / nEvents; } else { m_dwShowEvents = m_dwTimerPrecision; m_nIncrementHide = nBitmapSize; } // Compute init values for the animation switch (m_nAnimStatus) { case IDT_HIDDEN: if (m_nTaskbarPlacement == ABE_RIGHT) { m_nCurrentPosX = rcTaskbar.left; m_nCurrentPosY = rcTaskbar.bottom - m_nBitmapHeight; m_nCurrentWidth = 0; m_nCurrentHeight = m_nBitmapHeight; } else if (m_nTaskbarPlacement == ABE_LEFT) { m_nCurrentPosX = rcTaskbar.right; m_nCurrentPosY = rcTaskbar.bottom - m_nBitmapHeight; m_nCurrentWidth = 0; m_nCurrentHeight = m_nBitmapHeight; } else if (m_nTaskbarPlacement == ABE_TOP) { m_nCurrentPosX = rcTaskbar.right - m_nBitmapWidth; m_nCurrentPosY = rcTaskbar.bottom; m_nCurrentWidth = m_nBitmapWidth; m_nCurrentHeight = 0; } else { // Taskbar is on the bottom or Invisible m_nCurrentPosX = rcTaskbar.right - m_nBitmapWidth; m_nCurrentPosY = rcTaskbar.top; m_nCurrentWidth = m_nBitmapWidth; m_nCurrentHeight = 0; } ShowWindow(SW_SHOWNOACTIVATE); SetTimer(IDT_APPEARING, m_dwShowEvents, NULL); break; case IDT_APPEARING: RedrawWindow(); break; case IDT_WAITING: RedrawWindow(); KillTimer(IDT_WAITING); SetTimer(IDT_WAITING, m_dwTimeToStay, NULL); break; case IDT_DISAPPEARING: KillTimer(IDT_DISAPPEARING); SetTimer(IDT_WAITING, m_dwTimeToStay, NULL); if (m_nTaskbarPlacement == ABE_RIGHT) { m_nCurrentPosX = rcTaskbar.left - m_nBitmapWidth; m_nCurrentWidth = m_nBitmapWidth; } else if (m_nTaskbarPlacement == ABE_LEFT) { m_nCurrentPosX = rcTaskbar.right; m_nCurrentWidth = m_nBitmapWidth; } else if (m_nTaskbarPlacement == ABE_TOP) { m_nCurrentPosY = rcTaskbar.bottom; m_nCurrentHeight = m_nBitmapHeight; } else { m_nCurrentPosY = rcTaskbar.top - m_nBitmapHeight; m_nCurrentHeight = m_nBitmapHeight; } SetWindowPos(&wndTopMost, m_nCurrentPosX, m_nCurrentPosY, m_nCurrentWidth, m_nCurrentHeight, SWP_NOACTIVATE); RedrawWindow(); break; } }
CSkeleton::ESkeletonStates CSkeleton::Follow() { if (NearlyEqual(GetCurrAnimation()->GetCurrTime(), 0.05f)) { AudioSystemWwise::Get()->PostEvent(AK::EVENTS::PLAYERFOOTSTEP, *GetPosition()); } if (NearlyEqual(GetCurrAnimation()->GetCurrTime(), 0.5f)) { AudioSystemWwise::Get()->PostEvent(AK::EVENTS::PLAYERFOOTSTEP, *GetPosition()); } if (m_bIsGrounded) SetWorldVelocity({ 0, m_f3Velocity.y, 0 }); else SetWorldVelocity({ knockBackVelocity.x, m_f3Velocity.y, knockBackVelocity.z }); // Get the current path vector<XMFLOAT3>& vPath = GetPath(); // path here from group // Get the current velocity //XMVECTOR currentVelocity; XMLoadFloat3(&m_f3vel); if (DistanceToPlayer() < 500.0f) { return MOVING_IN; } // Node that I'm on along the path int nCurrentNode = GetCurNodeOnPath(); if (nCurrentNode < 0 || vPath.empty()) { BuildPathToPlayer(); vPath = GetPath(); if (vPath.size() < 2) { return FOLLOW; } } nCurrentNode = GetCurNodeOnPath(); // Get the current positions XMFLOAT3 curPos = *GetPosition(); XMFLOAT3 targetPos = vPath[nCurrentNode]; // Convert them for math XMVECTOR mathPos = XMLoadFloat3(&curPos); XMVECTOR mathTarget = XMLoadFloat3(&targetPos); // Find the vector between the two points XMVECTOR mathToVec = XMVectorSubtract(mathTarget, mathPos); //XMFLOAT3 toVec; XMStoreFloat3(&toVec, mathToVec); // Normalize the toVector to get the direction XMVECTOR mathVelocity = XMVector3Normalize(mathToVec); // Add the separation factor // mathVelocity += GetParentGroup()->CalculateSeparation(this); mathVelocity *= MOVE_SPEED; XMFLOAT3 realVelocity; XMStoreFloat3(&realVelocity, mathVelocity); realVelocity.y = m_f3Velocity.y; // Get the distance to target - ANY XYZ HOLDS THE LENGTH XMVECTOR mathDistToTarget = XMVector3Length(mathToVec); XMFLOAT3 distToTarget; XMStoreFloat3(&distToTarget, mathDistToTarget); // Offset the current node float nNextNodeDistance = 300.0f; // If i reached the node, move on the next one if (distToTarget.x < nNextNodeDistance && nCurrentNode >= 0) { nCurrentNode--; } Steering().Seek(targetPos); if (m_bIsGrounded) { Steering().Update(false, m_fScale); SetWorldVelocity(realVelocity); } SetNodeOnPath(nCurrentNode); return FOLLOW; }
CSkeleton::ESkeletonStates CSkeleton::Retreating() { if (NearlyEqual(GetCurrAnimation()->GetCurrTime(), 0.05f)) AudioSystemWwise::Get()->PostEvent(AK::EVENTS::PLAYERFOOTSTEP, *GetPosition()); if (NearlyEqual(GetCurrAnimation()->GetCurrTime(), 0.5f)) AudioSystemWwise::Get()->PostEvent(AK::EVENTS::PLAYERFOOTSTEP, *GetPosition()); if (m_bIsGrounded) SetWorldVelocity({ 0, m_f3Velocity.y, 0 }); else SetWorldVelocity({ knockBackVelocity.x, m_f3Velocity.y, knockBackVelocity.z }); // Get the current path vector<XMFLOAT3>& vPath = GetPath(); // path here from group // Node that I'm on along the path int nCurrentNode = GetCurNodeOnPath(); // Clamp CurNode to 0 and max if (nCurrentNode < 0) return DEATH; // If no path was generated, then return if (vPath.size() <= 0) { nCurrentNode = -1; return DEATH; } // Get the current positions XMFLOAT3 curPos = *GetPosition(); XMFLOAT3 targetPos = vPath[nCurrentNode]; // Convert them for math XMVECTOR mathPos = XMLoadFloat3(&curPos); XMVECTOR mathTarget = XMLoadFloat3(&targetPos); // Find the vector between the two points XMVECTOR mathToVec = XMVectorSubtract(mathTarget, mathPos); // Normalize the toVector to get the direction XMVECTOR mathVelocity = XMVector3Normalize(mathToVec); // Add the separation factor //mathVelocity += GetParentGroup()->CalculateSeparation(this); //mathVelocity += GetParentGroup()->CalculateAlignment(); mathVelocity *= MOVE_SPEED; XMFLOAT3 realVelocity; XMStoreFloat3(&realVelocity, mathVelocity); realVelocity.y = m_f3Velocity.y; // Get the distance to target - ANY XYZ HOLDS THE LENGTH XMVECTOR mathDistToTarget = XMVector3Length(mathToVec); XMFLOAT3 distToTarget; XMStoreFloat3(&distToTarget, mathDistToTarget); float nNextNodeDistance = 125.0f; Steering().Seek(targetPos); // If i reached the node, move on the next one if (distToTarget.x < nNextNodeDistance && nCurrentNode >= 0) nCurrentNode--; if (m_bIsGrounded) { Steering().Update(false, m_fScale); SetWorldVelocity(realVelocity); } else SetWorldVelocity({ knockBackVelocity.x, m_f3Velocity.y, knockBackVelocity.z }); SetNodeOnPath(nCurrentNode); return RETREAT; }