示例#1
0
void CPActionReverse::Redo(CMainFrame &MainFrm)
{
	CSongView *pSongView = GET_SONG_VIEW();
	auto [b, e] = GetIterators(*pSongView);
	const CSelection &Sel = m_pUndoState->Selection;

	const column_t ColStart = GetSelectColumn(Sel.m_cpStart.Xpos.Column);
	const column_t ColEnd = GetSelectColumn(Sel.m_cpEnd.Xpos.Column);

	while (b < e) {
		for (int c = Sel.m_cpStart.Xpos.Track; c <= Sel.m_cpEnd.Xpos.Track; ++c) {
			auto NoteBegin = b.Get(c);
			auto NoteEnd = e.Get(c);
			if (c == Sel.m_cpStart.Xpos.Track && ColStart > column_t::Note) {		// // //
				auto Temp = NoteEnd;
				CopyNoteSection(NoteEnd, NoteBegin, column_t::Note, static_cast<column_t>(value_cast(ColStart) - 1));
				CopyNoteSection(NoteBegin, Temp, column_t::Note, static_cast<column_t>(value_cast(ColStart) - 1));
			}
			if (c == Sel.m_cpEnd.Xpos.Track && ColEnd < column_t::Effect4) {
				auto Temp = NoteEnd;
				CopyNoteSection(NoteEnd, NoteBegin, static_cast<column_t>(value_cast(ColEnd) + 1), column_t::Effect4);
				CopyNoteSection(NoteBegin, Temp, static_cast<column_t>(value_cast(ColEnd) + 1), column_t::Effect4);
			}
			b.Set(c, NoteEnd);
			e.Set(c, NoteBegin);
		}
		++b;
		--e;
	}
}
示例#2
0
void CPActionStretch::Redo(CMainFrame &MainFrm)
{
	CSongView *pSongView = GET_SONG_VIEW();
	auto [b, e] = GetIterators(*pSongView);
	const CSelection &Sel = m_pUndoState->Selection;
	CPatternIterator s {b};

	const column_t ColStart = GetSelectColumn(Sel.m_cpStart.Xpos.Column);
	const column_t ColEnd = GetSelectColumn(Sel.m_cpEnd.Xpos.Column);

	int Pos = 0;
	int Offset = 0;
	int oldRow = -1;
	do {
		stChanNote BLANK;
		for (int i = Sel.m_cpStart.Xpos.Track; i <= Sel.m_cpEnd.Xpos.Track; ++i) {
			const auto &Source = (Offset < m_UndoClipData.ClipInfo.Rows && m_iStretchMap[Pos] > 0) ?
				*(m_UndoClipData.GetPattern(i - Sel.m_cpStart.Xpos.Track, Offset)) : BLANK;		// // //
			auto Target = b.Get(i);
			CopyNoteSection(Target, Source,
				i == Sel.m_cpStart.Xpos.Track ? ColStart : column_t::Note,
				i == Sel.m_cpEnd.Xpos.Track ? ColEnd : column_t::Effect4);
			b.Set(i, Target);
		}
		int dist = m_iStretchMap[Pos++];
		for (int i = 0; i < dist; ++i) {
			++Offset;
			oldRow = s.m_iRow;
			++s;
			if (s.m_iRow <= oldRow)
				Offset += pSongView->GetSong().GetPatternLength() + s.m_iRow - oldRow - 1;
		}
		Pos %= m_iStretchMap.size();
	} while (++b <= e);
}
bool CSelection::IsColumnSelected(column_t Column, int Channel) const
{
	column_t SelStart = GetSelectColumn(GetColStart());		// // //
	column_t SelEnd = GetSelectColumn(GetColEnd());

	return (Channel > GetChanStart() || (Channel == GetChanStart() && Column >= SelStart))		// // //
		&& (Channel < GetChanEnd() || (Channel == GetChanEnd() && Column <= SelEnd));
}
示例#4
0
void CPatternAction::DeleteSelection(CSongView &view, const CSelection &Sel) const		// // //
{
	auto [b, e] = CPatternIterator::FromSelection(Sel, view);
	const column_t ColStart = GetSelectColumn(b.m_iColumn);
	const column_t ColEnd = GetSelectColumn(e.m_iColumn);

	stChanNote BLANK;

	do for (int i = b.m_iChannel; i <= e.m_iChannel; ++i) {
		auto NoteData = b.Get(i);
		CopyNoteSection(NoteData, BLANK,
			i == b.m_iChannel ? ColStart : column_t::Note,
			i == e.m_iChannel ? ColEnd : column_t::Effect4);
		b.Set(i, NoteData);
	} while (++b <= e);
}
示例#5
0
void CPActionScrollValues::Redo(CMainFrame &MainFrm)
{
	CPatternEditor *pPatternEditor = GET_PATTERN_EDITOR();
	CSongView *pSongView = GET_SONG_VIEW();
	auto [b, e] = GetIterators(*pSongView);
	int ChanStart     = (m_pUndoState->IsSelecting ? m_pUndoState->Selection.m_cpStart : m_pUndoState->Cursor).Xpos.Track;
	int ChanEnd       = (m_pUndoState->IsSelecting ? m_pUndoState->Selection.m_cpEnd : m_pUndoState->Cursor).Xpos.Track;
	column_t ColStart = GetSelectColumn(
		(m_pUndoState->IsSelecting ? m_pUndoState->Selection.m_cpStart : m_pUndoState->Cursor).Xpos.Column);
	column_t ColEnd   = GetSelectColumn(
		(m_pUndoState->IsSelecting ? m_pUndoState->Selection.m_cpEnd : m_pUndoState->Cursor).Xpos.Column);

	const bool bSingular = b == e && !m_pUndoState->IsSelecting;
	const unsigned Length = pSongView->GetSong().GetPatternLength();

	const auto WarpFunc = [this] (unsigned char &x, int Lim) {
		int Val = x + m_iAmount;
		if (FTEnv.GetSettings()->General.bWrapPatternValue) {
			Val %= Lim;
			if (Val < 0) Val += Lim;
		}
		else {
			if (Val >= Lim) Val = Lim - 1;
			if (Val < 0) Val = 0;
		}
		x = static_cast<unsigned char>(Val);
	};

	int Row = 0;
	int oldRow = -1;
	do {
		if (b.m_iRow <= oldRow)
			Row += Length + b.m_iRow - oldRow - 1;
		for (int i = ChanStart; i <= ChanEnd; ++i) {
			auto Note = *(m_UndoClipData.GetPattern(i - ChanStart, Row));		// // //
			for (column_t k = column_t::Instrument; k <= column_t::Effect4; k = static_cast<column_t>(value_cast(k) + 1)) {
				if (i == ChanStart && k < ColStart)
					continue;
				if (i == ChanEnd && k > ColEnd)
					continue;
				switch (k) {
				case column_t::Instrument:
					if (Note.Instrument == MAX_INSTRUMENTS || Note.Instrument == HOLD_INSTRUMENT) break;		// // // 050B
					WarpFunc(Note.Instrument, MAX_INSTRUMENTS);
					break;
				case column_t::Volume:
					if (Note.Vol == MAX_VOLUME) break;
					WarpFunc(Note.Vol, MAX_VOLUME);
					break;
				case column_t::Effect1: case column_t::Effect2: case column_t::Effect3: case column_t::Effect4:
				{
					unsigned fx = value_cast(k) - value_cast(column_t::Effect1);
					if (Note.Effects[fx].fx == effect_t::none)
						break;
					if (bSingular) switch (Note.Effects[fx].fx) {
					case effect_t::SWEEPUP: case effect_t::SWEEPDOWN: case effect_t::ARPEGGIO: case effect_t::VIBRATO: case effect_t::TREMOLO:
					case effect_t::SLIDE_UP: case effect_t::SLIDE_DOWN: case effect_t::VOLUME_SLIDE: case effect_t::DELAYED_VOLUME: case effect_t::TRANSPOSE:
						unsigned char Hi = Note.Effects[fx].param >> 4;
						unsigned char Lo = Note.Effects[fx].param & 0x0F;
						WarpFunc(value_cast(pPatternEditor->GetColumn()) % 3 == 2 ? Hi : Lo, 0x10);
						Note.Effects[fx].param = (Hi << 4) | Lo;
						continue;
					}
					WarpFunc(Note.Effects[fx].param, 0x100);
					break;
				}
				}
			}
			b.Set(i, Note);
		}
		++Row;
		oldRow = b.m_iRow;
	} while (++b <= e);
}
示例#6
0
bool CPatternAction::SetTargetSelection(const CMainFrame &MainFrm, CSelection &Sel)		// // //
{
	CPatternEditor *pPatternEditor = GET_PATTERN_EDITOR();
	CCursorPos Start;

	if ((m_iPastePos == paste_pos_t::SELECTION || m_iPastePos == paste_pos_t::FILL) && !m_bSelecting)
		m_iPastePos = paste_pos_t::CURSOR;

	switch (m_iPastePos) { // Xpos.Column will be written later
	case paste_pos_t::CURSOR:
		Start = m_pUndoState->Cursor;
		break;
	case paste_pos_t::DRAG:
		Start.Ypos.Frame = m_dragTarget.GetFrameStart();
		Start.Ypos.Row = m_dragTarget.GetRowStart();
		Start.Xpos.Track = m_dragTarget.GetChanStart();
		break;
	case paste_pos_t::SELECTION:
	case paste_pos_t::FILL:
		Start.Ypos.Frame = m_selection.GetFrameStart();
		Start.Ypos.Row = m_selection.GetRowStart();
		Start.Xpos.Track = m_selection.GetChanStart();
		break;
	}

	auto pSongView = GET_SONG_VIEW();

	CPatternIterator End(*pSongView, Start);

	if (m_iPasteMode == paste_mode_t::INSERT) {
		End.m_iFrame = Start.Ypos.Frame;
		End.m_iRow = pPatternEditor->GetCurrentPatternLength(End.m_iFrame) - 1;
	}
	else
		End += m_ClipData.ClipInfo.Rows - 1;

	switch (m_iPastePos) {
	case paste_pos_t::FILL:
		End.m_iFrame = m_selection.GetFrameEnd();
		End.m_iRow = m_selection.GetRowEnd();
		End.m_iChannel = m_selection.GetChanEnd();
		Start.Xpos.Column = GetCursorStartColumn(m_ClipData.ClipInfo.StartColumn);
		End.m_iColumn = GetCursorEndColumn(
			!((End.m_iChannel - Start.Xpos.Track + 1) % m_ClipData.ClipInfo.Channels) ?
			m_ClipData.ClipInfo.EndColumn :
			static_cast<column_t>(value_cast(column_t::Effect1) + pSongView->GetEffectColumnCount(End.m_iChannel)));
		break;
	case paste_pos_t::DRAG:
		End.m_iChannel += m_ClipData.ClipInfo.Channels - 1;
		Start.Xpos.Column = m_dragTarget.GetColStart();
		End.m_iColumn = m_dragTarget.GetColEnd();
		break;
	default:
		End.m_iChannel += m_ClipData.ClipInfo.Channels - 1;
		Start.Xpos.Column = GetCursorStartColumn(m_ClipData.ClipInfo.StartColumn);
		End.m_iColumn = GetCursorEndColumn(m_ClipData.ClipInfo.EndColumn);
	}

	const bool bOverflow = FTEnv.GetSettings()->General.bOverflowPaste;
	if (!bOverflow && End.m_iFrame > Start.Ypos.Frame) {
		End.m_iFrame = Start.Ypos.Frame;
		End.m_iRow = pPatternEditor->GetCurrentPatternLength(End.m_iFrame) - 1;
	}

	const cursor_column_t EFBEGIN = GetCursorStartColumn(column_t::Effect1);
	int OFFS = 3 * (value_cast(GetSelectColumn(m_pUndoState->Cursor.Xpos.Column)) - value_cast(m_ClipData.ClipInfo.StartColumn));
	if (OFFS < static_cast<int>(value_cast(EFBEGIN) - value_cast(Start.Xpos.Column)))
		OFFS = value_cast(EFBEGIN) - value_cast(Start.Xpos.Column);
	if (Start.Xpos.Track == End.m_iChannel && Start.Xpos.Column >= EFBEGIN && End.m_iColumn >= EFBEGIN) {
		if (m_iPastePos != paste_pos_t::DRAG) {
			End.m_iColumn = static_cast<cursor_column_t>(value_cast(End.m_iColumn) + OFFS);
			Start.Xpos.Column = static_cast<cursor_column_t>(value_cast(Start.Xpos.Column) + OFFS);
			if (End.m_iColumn > cursor_column_t::EFF4_PARAM2)
				End.m_iColumn = cursor_column_t::EFF4_PARAM2;
		}
	}

	CSelection New;
	New.m_cpStart = Start;
	New.m_cpEnd = End.GetCursor();
	pPatternEditor->SetSelection(New);

	sel_condition_t Cond = pPatternEditor->GetSelectionCondition();
	if (Cond == sel_condition_t::CLEAN) {
		Sel = New;
		return true;
	}
	else {
		pPatternEditor->SetSelection(m_selection);
		if (!m_bSelecting) pPatternEditor->CancelSelection();
		int Confirm = IDYES;
		switch (Cond) {
		case sel_condition_t::REPEATED_ROW:
			Confirm = AfxMessageBox(IDS_PASTE_REPEATED_ROW, MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2);
			break;
		case sel_condition_t::NONTERMINAL_SKIP: case sel_condition_t::TERMINAL_SKIP:
			if (!bOverflow) break;
			Confirm = AfxMessageBox(IDS_PASTE_NONTERMINAL, MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2);
			break;
		}
		if (Confirm == IDYES) {
			pPatternEditor->SetSelection(Sel = New);
			return true;
		}
		else {
			return false;
		}
	}
}