Example #1
0
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;	
}