void CEffectVis::OnMouseMove(UINT nFlags, CPoint point) { CDialog::OnMouseMove(nFlags, point); m_pModDoc = m_pViewPattern->GetDocument(); if (!m_pModDoc) return; ROWINDEX row = ScreenXToRow(point.x); if ((m_dwStatus & FXVSTATUS_RDRAGGING) && (m_nDragItem>=0) ) { m_nRowToErase = m_nDragItem; m_nParamToErase = GetParam(m_nDragItem); MakeChange(m_nDragItem, point.y); } else if ((m_dwStatus & FXVSTATUS_LDRAGGING)) { // Interpolate if we detect that rows have been skipped but the left mouse button was not released. // This ensures we produce a smooth curve even when we are not notified of mouse movements at a high frequency (e.g. if CPU usage is high) const int steps = mpt::abs((int)row - (int)m_nLastDrawnRow); if (m_nLastDrawnRow != ROWINDEX_INVALID && m_nLastDrawnRow > m_startRow && steps > 1) { int direction = ((int)(row - m_nLastDrawnRow) > 0) ? 1 : -1; float factor = (float)(point.y - m_nLastDrawnY)/(float)steps + 0.5f; int currentRow; for (int i=1; i<=steps; i++) { currentRow = m_nLastDrawnRow+(direction*i); int interpolatedY = Util::Round<int>(m_nLastDrawnY + ((float)i * factor)); MakeChange(currentRow, interpolatedY); } //Don't use single value update m_nRowToErase = -1; m_nParamToErase = -1; } else { m_nRowToErase = -1; m_nParamToErase = -1; MakeChange(row, point.y); } // Remember last modified point in case we need to interpolate m_nLastDrawnRow = row; m_nLastDrawnY = point.y; } //update status bar CHAR status[256]; CHAR effectName[128]; uint16 paramValue; if (IsPcNote(row)) { paramValue = ScreenYToPCParam(point.y); wsprintf(effectName, "%s", "Param Control"); // TODO - show smooth & plug+param } else { paramValue = ScreenYToFXParam(point.y); effectInfo.GetEffectInfo(effectInfo.GetIndexFromEffect(GetCommand(row), ModCommand::PARAM(GetParam(row))), effectName, true); } wsprintf(status, "Pat: %d\tChn: %d\tRow: %d\tVal: %02X (%03d) [%s]", m_nPattern, m_nChan+1, row, paramValue, paramValue, effectName); m_edVisStatus.SetWindowText(status); }
// Child thread가 실행하는 life game int Child_LifeGame (int * StartLine) { char * pMap, * ppCMap, *ppNMap; int iZ, iY, i, iOffset; int ChangeCnt = 0; if (*StartLine >= _CheckSize) { return -1; } #ifdef __TESTMUTEX printf ("Searching at [ %d ] Total [ %d ] \n", *StartLine, _CheckSize); #endif // Check Map에서 비어있는 Line 선택 pMap = _pMapCheck + *StartLine; while (1) { if (*pMap != _cLoopCheck) { pthread_mutex_lock (&_mMapCheck); if (*pMap != _cLoopCheck) { *pMap = _cLoopCheck; pthread_mutex_unlock (&_mMapCheck); break; } pthread_mutex_unlock (&_mMapCheck); } pMap++; *StartLine = *StartLine + 1; if (*StartLine >= _CheckSize) { return -1; } } #ifdef __TESTMUTEX printf ("Select [ %d ] th Line of Total [ %d ] Lines\n", *StartLine, _CheckSize); #endif // 선택된 x,y plane의 Z 좌표 계산 iZ = pMap - _pMapCheck; // Map 위치 계산 iOffset = __OFFSET_1D(iZ); pMap = _ppMap + iOffset; ppNMap = _ppNMap + iOffset; ppCMap = _ppCMap + iZ * _iMapSize * _iMapSize; // 해당 Line에 있는 Cell들의 생존상태 계산 for (iY=0; iY < _iMapSize; iY++) { for (i = 0; i < _iMapSize; i++) { if (*ppCMap == 1) { *ppCMap = 0; // 검사 완료 된 셀을 초기화 if (CalcDoA (i, iY, iZ) == 1) { MakeChange (i, iY, iZ); // 변했을 경우 주위 셀을 다음 Change map에 추가 *ppNMap = *pMap ^ 0x01; // 다음 상태에 반전으로 입력 ChangeCnt++; } else { *ppNMap = *pMap; } } else { *ppNMap = *pMap; } pMap++; ppNMap++; ppCMap++; } pMap += __OFFSET_Y; ppNMap += __OFFSET_Y; } return ChangeCnt; }