sint32 c3_PopupWindow::AddTitle( MBCHAR *titleBlock ) { if (m_title) { // No action: already created } else { AUI_ERRCODE errcode = AUI_ERRCODE_OK; m_title = new c3_Static(&errcode, aui_UniqueId(), "c3_PopupTitle"); TestControl(m_title); char *ldlBlock = "c3_PopupTitle.c3_PopupTitleText"; m_titleText = new c3_Static (&errcode, aui_UniqueId(), (titleBlock) ? titleBlock : ldlBlock ); TestControl(m_titleText); m_title->AddSubControl(m_titleText); m_title->Move((m_width - m_title->Width()) / 2, 0); InsertChild(m_title, 0); m_title->SetParentWindow(this); m_title->SetBlindness(true); } return 1; }
static void MacScaleEventProc( ClientData clientData, /* Information about window. */ XEvent *eventPtr) /* Information about event. */ { MacScale *macScalePtr = (MacScale *) clientData; Point where; Rect bounds; int part; CGrafPtr destPort, savePort; Boolean portChanged; #ifdef TK_MAC_DEBUG_SCALE fprintf(stderr,"MacScaleEventProc\n" ); #endif /* * To call Macintosh control routines we must have the port * set to the window containing the control. We will then test * which part of the control was hit and act accordingly. */ destPort = TkMacOSXGetDrawablePort(Tk_WindowId(macScalePtr->info.tkwin)); portChanged = QDSwapPort(destPort, &savePort); TkMacOSXSetUpClippingRgn(Tk_WindowId(macScalePtr->info.tkwin)); TkMacOSXWinBounds((TkWindow *) macScalePtr->info.tkwin, &bounds); where.h = eventPtr->xbutton.x + bounds.left; where.v = eventPtr->xbutton.y + bounds.top; #ifdef TK_MAC_DEBUG_SCALE TkMacOSXDbgMsg("calling TestControl"); #endif part = TestControl(macScalePtr->scaleHandle, where); if (part == 0) { return; } TkMacOSXTrackingLoop(1); part = HandleControlClick(macScalePtr->scaleHandle, where, TkMacOSXModifierState(), scaleActionProc); TkMacOSXTrackingLoop(0); /* * Update the value for the widget. */ macScalePtr->info.value = GetControlValue(macScalePtr->scaleHandle); /* TkScaleSetValue(&macScalePtr->info, macScalePtr->info.value, 1, 0); */ /* * The HandleControlClick call will "eat" the ButtonUp event. We now * generate a ButtonUp event so Tk will unset implicit grabs etc. */ TkGenerateButtonEventForXPointer(Tk_WindowId(macScalePtr->info.tkwin)); if (portChanged) { QDSwapPort(savePort, NULL); } }
int TkpScaleElement( TkScale *scalePtr, /* Widget record for scale. */ int x, int y) /* Coordinates within scalePtr's window. */ { MacScale *macScalePtr = (MacScale *) scalePtr; ControlPartCode part; Point where; Rect bounds; CGrafPtr destPort, savePort; Boolean portChanged; #ifdef TK_MAC_DEBUG_SCALE TkMacOSXDbgMsg("TkpScaleElement"); #endif destPort = TkMacOSXGetDrawablePort(Tk_WindowId(scalePtr->tkwin)); portChanged = QDSwapPort(destPort, &savePort); /* * All of the calculations in this procedure mirror those in * DisplayScrollbar. Be sure to keep the two consistent. */ TkMacOSXWinBounds((TkWindow *) scalePtr->tkwin, &bounds); where.h = x + bounds.left; where.v = y + bounds.top; part = TestControl(macScalePtr->scaleHandle, where); if (portChanged) { QDSwapPort(savePort, NULL); } #ifdef TK_MAC_DEBUG_SCALE fprintf (stderr,"ScalePart %d, pos ( %d %d )\n", part, where.h, where.v ); #endif switch (part) { case inSlider: return SLIDER; case inInc: if (scalePtr->orient == ORIENT_VERTICAL) { return TROUGH1; } else { return TROUGH2; } case inDecr: if (scalePtr->orient == ORIENT_VERTICAL) { return TROUGH2; } else { return TROUGH1; } default: return OTHER; } }
Boolean TActiveScroller::HandleMouseClick(Point inPoint) { #if TARGET_API_MAC_CARBON==1 UPortSaver safe(GetControlOwner(scrollBar)); #else UPortSaver safe((**scrollBar).contrlOwner); #endif short partCode; if (partCode=TestControl(scrollBar,inPoint)) { switch (partCode) { case kControlUpButtonPart: case kControlDownButtonPart: case kControlPageDownPart: case kControlPageUpPart: case kControlIndicatorPart: SetupScroll(); if (partCode==kControlIndicatorPart) { // Dim the thumb HiliteControl(scrollBar,kControlIndicatorPart); IndicatorProc(inPoint); // Undim the thumb HiliteControl(scrollBar,kControlNoPart); } else { // Must call this to pass the current object to the tracking proc SetTrackingObject(this); TrackControl(scrollBar,inPoint,scrollBarProcUPP); } ShutdownScroll(); return true; break; } } return false; // missed the scroll bar }
sint32 c3_PopupWindow::AddOk ( void (*actionFunc)( aui_Control *, uint32, uint32, void *), void *cookie, MBCHAR *buttonBlock ) { if (m_ok) { // No action: already created } else { AUI_ERRCODE errcode = AUI_ERRCODE_OK; m_ok = new ctp2_Button( &errcode, aui_UniqueId(), buttonBlock, actionFunc, cookie ); TestControl( m_ok ); m_ok->Move( m_width - m_ok->Width() - 17, m_height - m_ok->Height() - 17); InsertChild(m_ok, 0); m_ok->SetParentWindow(this); } return 1; }
void ZActor::OnUpdate(float fDelta) { if(m_pVMesh) { m_pVMesh->SetVisibility(1.f); } if (CheckFlag(AF_MY_CONTROL)) { m_TaskManager.Run(fDelta); CheckDead(fDelta); ProcessNetwork(fDelta); // for test - bird if (m_bTestControl) { TestControl(fDelta); } else { __BP(60,"ZActor::OnUpdate::ProcessAI"); if(isThinkAble()) ProcessAI(fDelta); __EP(60); } ProcessMovement(fDelta); } ProcessMotion(fDelta); if (CheckFlag(AF_MY_CONTROL)) { UpdateHeight(fDelta); } }
void UpdateEditor() { static GHEvent *pHold[8] = { (GHEvent*)(size_t)-1, (GHEvent*)(size_t)-1, (GHEvent*)(size_t)-1, (GHEvent*)(size_t)-1, (GHEvent*)(size_t)-1, (GHEvent*)(size_t)-1, (GHEvent*)(size_t)-1, (GHEvent*)(size_t)-1 }; bool ctrlState = MFInput_Read(Key_LControl, IDD_Keyboard) || MFInput_Read(Key_RControl, IDD_Keyboard); bool shiftState = MFInput_Read(Key_LShift, IDD_Keyboard) || MFInput_Read(Key_LShift, IDD_Keyboard); bool altState = MFInput_Read(Key_LAlt, IDD_Keyboard) || MFInput_Read(Key_RAlt, IDD_Keyboard); int res = gEditor.pSong->GetRes(); if(TestControl(dBCtrl_Edit_Save, GHCT_Once)) { gEditor.pSong->SaveChart(); MFVoice *pVoice = MFSound_Play(gEditor.pSaveSound, MFPF_BeginPaused); MFSound_SetVolume(pVoice, gConfig.sound.fxLevel); MFSound_Pause(pVoice, false); if(gConfig.editor.saveAction[0]) system(gConfig.editor.saveAction); } if(TestControl(dBCtrl_Edit_Event, GHCT_Once)) PlaceEvent(); else if(TestControl(dBCtrl_Edit_TrackEvent, GHCT_Once)) PlaceTrackEvent(); else if(TestControl(dBCtrl_Edit_Section, GHCT_Once)) PlaceSection(); else if(TestControl(dBCtrl_Edit_Quantise, GHCT_Once)) gpStringBox->Show(MFTranslation_GetString(pStrings, MENU_SETQUANTISE), "", SetCustomQuantisation); else if(TestControl(dBCtrl_Edit_Mixer, GHCT_Once)) ((EditorScreen*)dBScreen::GetCurrent())->gMixer.Push(); // check selection if(bSelecting && !TestControl(dBCtrl_Edit_RangeSelect, GHCT_Hold)) { gEditor.selectEnd = gEditor.offset; bSelecting = false; } else if(!bSelecting && TestControl(dBCtrl_Edit_RangeSelect, GHCT_Hold)) { gEditor.selectStart = gEditor.selectEnd = gEditor.offset; bSelecting = true; } if(TestControl(dBCtrl_Edit_Cut, GHCT_Once) || TestControl(dBCtrl_Edit_Copy, GHCT_Once)) { if(gEditor.selectStart != gEditor.selectEnd) { gEditor.copyLen = gEditor.selectEnd - gEditor.selectStart; gEditor.selectEvents.Clear(); GHEventManager ¬eStream = gEditor.pSong->notes[gEditor.currentStream[gEditor.selectedStream]]; GHEvent *pEv = noteStream.GetNextEvent(gEditor.selectStart); while(pEv && pEv->tick < gEditor.selectEnd) { // copy the next pointer incase we cut the note. GHEvent *pNext = pEv->Next(); // just cut/copy notes if(pEv->event == GHE_Note) { // copy to clipboard gEditor.selectEvents.AddEvent(pEv->event, pEv->tick - gEditor.selectStart, pEv->key, pEv->parameter); // if we cut if(TestControl(dBCtrl_Edit_Cut, GHCT_Once)) pNext = noteStream.RemoveEvent(pEv); } pEv = pNext; } } } else if(TestControl(dBCtrl_Edit_Paste, GHCT_Once)) { GHEvent *pEv = gEditor.selectEvents.First(); if(pEv) { int curStream = gEditor.currentStream[gEditor.selectedStream]; GHEventManager ¬eStream = gEditor.pSong->notes[curStream]; // delete notes in paste range GHEvent *pDel = noteStream.GetNextEvent(gEditor.offset); while(pDel && pDel->tick < gEditor.offset + gEditor.copyLen) { if(pDel->event == GHE_Note) pDel = noteStream.RemoveEvent(pDel); else pDel = pDel->Next(); } // paste notes while(pEv) { noteStream.AddEvent(pEv->event, pEv->tick + gEditor.offset, pEv->key, pEv->parameter); pEv = pEv->Next(); } gEditor.pSong->CalculateNoteTimes(curStream, gEditor.offset); } } if(TestControl(dBCtrl_Edit_Delete, GHCT_Once)) { GHEventManager ¬es = gEditor.pSong->notes[gEditor.currentStream[gEditor.selectedStream]]; if(gEditor.selectStart != gEditor.selectEnd) { // delete notes in selected range GHEvent *pDel = notes.GetNextEvent(gEditor.selectStart); while(pDel && pDel->tick < gEditor.selectEnd) { if(pDel->event == GHE_Note) pDel = notes.RemoveEvent(pDel); else pDel = pDel->Next(); } } else { int numEvents = 0; uint32 eventTypes = 0; // find note events GHEvent *pEvent = notes.GetNextEvent(gEditor.offset); while(pEvent && pEvent->tick == gEditor.offset) { uint32 bit = 1 << pEvent->event; if(!(eventTypes & bit)) { ++numEvents; eventTypes |= bit; } pEvent = pEvent->Next(); } // find sync events if(gEditor.offset > 0) { pEvent = gEditor.pSong->sync.GetNextEvent(gEditor.offset); while(pEvent && pEvent->tick == gEditor.offset) { uint32 bit = 1 << pEvent->event; if(!(eventTypes & bit)) { ++numEvents; eventTypes |= bit; } pEvent = pEvent->Next(); } } // find global events pEvent = gEditor.pSong->events.GetNextEvent(gEditor.offset); while(pEvent && pEvent->tick == gEditor.offset) { uint32 bit = 1 << pEvent->event; if(!(eventTypes & bit)) { ++numEvents; eventTypes |= bit; } pEvent = pEvent->Next(); } // if there are multiple event types to remove, show a list box if(numEvents > 1) gpListBox->Show(MFTranslation_GetString(pStrings, SELECT_EVENT_REMOVE), RemoveEventCallback, 200.0f, 100.0f); for(int a=0; a<GHE_Max; ++a) { if(eventTypes & (1 << a)) { if(numEvents > 1) gpListBox->AddItem(MFTranslation_GetString(pStrings, EVENT_TYPE_UNKNOWN+a), (void*)(size_t)a); else RemoveEventCallback(false, 0, NULL, (void*)(size_t)a); } } } } // shift notes left or right int selStart, selEnd; if(gEditor.selectStart != gEditor.selectEnd) { selStart = gEditor.selectStart; selEnd = gEditor.selectEnd; } else { selStart = gEditor.offset; selEnd = gEditor.pSong->GetLastNoteTick(); } if(TestControl(dBCtrl_Edit_ShiftForwards, GHCT_Delay)) { int offset = 4*res / gEditor.quantisation; // TODO: gotta remove notes after the selection that will be overwritten as the selection shifts.. if(altState) { // shift events, sync and other tracks too GHEvent *pEv = gEditor.pSong->sync.GetNextEvent(selStart); while(pEv && pEv->tick < selEnd) { if(pEv->tick != 0) pEv->tick += offset; pEv = pEv->Next(); } pEv = gEditor.pSong->events.GetNextEvent(selStart); while(pEv && pEv->tick < selEnd) { pEv->tick += offset; pEv = pEv->Next(); } for(int i=0; i<GHS_Max; ++i) { pEv = gEditor.pSong->notes[i].GetNextEvent(selStart); while(pEv && pEv->tick < selEnd) { pEv->tick += offset; pEv = pEv->Next(); } } } else { GHEvent *pEv = gEditor.pSong->notes[gEditor.currentStream[gEditor.selectedStream]].GetNextEvent(selStart); while(pEv && pEv->tick < selEnd) { pEv->tick += offset; pEv = pEv->Next(); } } gEditor.selectStart += offset; gEditor.selectEnd += offset; gEditor.offset += offset; gEditor.pSong->CalculateNoteTimes(gEditor.currentStream[gEditor.selectedStream], gEditor.offset); } if(TestControl(dBCtrl_Edit_ShiftBackwards, GHCT_Delay)) { int offset = MFMin(4*res / gEditor.quantisation, gEditor.selectStart); // TODO: gotta remove notes before the selection that will be overwritten as the selection shifts.. if(altState) { // shift events, sync and other tracks too GHEvent *pEv = gEditor.pSong->sync.GetNextEvent(selStart); while(pEv && pEv->tick < selEnd) { if(pEv->tick != 0) pEv->tick -= offset; pEv = pEv->Next(); } pEv = gEditor.pSong->events.GetNextEvent(selStart); while(pEv && pEv->tick < selEnd) { pEv->tick -= offset; pEv = pEv->Next(); } for(int i=0; i<GHS_Max; ++i) { pEv = gEditor.pSong->notes[i].GetNextEvent(selStart); while(pEv && pEv->tick < selEnd) { pEv->tick -= offset; pEv = pEv->Next(); } } } else { GHEvent *pEv = gEditor.pSong->notes[gEditor.currentStream[gEditor.selectedStream]].GetNextEvent(selStart); while(pEv && pEv->tick < selEnd) { pEv->tick -= offset; pEv = pEv->Next(); } } gEditor.selectStart -= offset; gEditor.selectEnd -= offset; gEditor.offset -= offset; gEditor.pSong->CalculateNoteTimes(gEditor.currentStream[gEditor.selectedStream], gEditor.offset); } if(TestControl(dBCtrl_Edit_ShiftLeft, GHCT_Once)) { GHEvent *pEv = gEditor.pSong->notes[gEditor.currentStream[gEditor.selectedStream]].GetNextEvent(selStart); while(pEv && pEv->tick < selEnd) { if(pEv->event == GHE_Note) pEv->key = MFMax(0, pEv->key - 1); pEv = pEv->Next(); } } if(TestControl(dBCtrl_Edit_ShiftRight, GHCT_Once)) { GHEvent *pEv = gEditor.pSong->notes[gEditor.currentStream[gEditor.selectedStream]].GetNextEvent(selStart); while(pEv && pEv->tick < selEnd) { if(pEv->event == GHE_Note) pEv->key = MFMin(4, pEv->key + 1); pEv = pEv->Next(); } } // change quantisation if(TestControl(dBCtrl_Edit_QuantiseDown, GHCT_Delay)) { gEditor.quantiseStep = MFMax(0, gEditor.quantiseStep-1); gEditor.quantisation = gQuantiseSteps[gEditor.quantiseStep]; OffsetToMeasureAndBeat(gEditor.offset, &gEditor.measure, &gEditor.beat); MFVoice *pVoice = MFSound_Play(gEditor.pChangeSound, MFPF_BeginPaused); MFSound_SetVolume(pVoice, gConfig.sound.fxLevel); MFSound_Pause(pVoice, false); } if(TestControl(dBCtrl_Edit_QuantiseUp, GHCT_Delay)) { gEditor.quantiseStep = MFMin((int)(sizeof(gQuantiseSteps)/sizeof(gQuantiseSteps[0]))-1, gEditor.quantiseStep+1); gEditor.quantisation = gQuantiseSteps[gEditor.quantiseStep]; OffsetToMeasureAndBeat(gEditor.offset, &gEditor.measure, &gEditor.beat); MFVoice *pVoice = MFSound_Play(gEditor.pChangeSound, MFPF_BeginPaused); MFSound_SetVolume(pVoice, gConfig.sound.fxLevel); MFSound_Pause(pVoice, false); } // move the track if(TestControl(dBCtrl_Edit_Forward, GHCT_Delay)) { // forward one step ++gEditor.beat; if(gEditor.beat == gEditor.quantisation) { ++gEditor.measure; gEditor.beat = 0; } } if(TestControl(dBCtrl_Edit_Back, GHCT_Delay)) { // back one step if(gEditor.measure || gEditor.beat) { --gEditor.beat; if(gEditor.beat < 0) { --gEditor.measure; gEditor.beat += gEditor.quantisation; } } } if(TestControl(dBCtrl_Edit_Start, GHCT_Once)) { // go to start gEditor.measure = gEditor.beat = 0; } if(TestControl(dBCtrl_Edit_End, GHCT_Once)) { // go to the last note... OffsetToMeasureAndBeat(gEditor.pSong->GetLastNoteTick(), &gEditor.measure, &gEditor.beat); } if(TestControl(dBCtrl_Edit_UpMeasure, GHCT_Delay)) { // forward one measure // TODO: consider bar lengths while moving ++gEditor.measure; } if(TestControl(dBCtrl_Edit_DownMeasure, GHCT_Delay)) { // back one measure // TODO: consider bar lengths while moving if(gEditor.measure < 1) gEditor.measure = gEditor.beat = 0; else --gEditor.measure; } if(TestControl(dBCtrl_Edit_NextSection, GHCT_Delay)) { GHEvent *pEv = gEditor.pSong->events.GetNextEvent(gEditor.offset); while(pEv) { if(pEv->tick >= gEditor.offset + gEditor.pSong->resolution*4 / gEditor.quantisation && !MFString_CompareN(pEv->GetString(), "section ", 8)) { OffsetToMeasureAndBeat(pEv->tick, &gEditor.measure, &gEditor.beat); break; } pEv = pEv->Next(); } if(!pEv) OffsetToMeasureAndBeat(gEditor.pSong->GetLastNoteTick(), &gEditor.measure, &gEditor.beat); } if(TestControl(dBCtrl_Edit_PrevSection, GHCT_Delay)) { GHEvent *pMostRecent = NULL; GHEvent *pEv = gEditor.pSong->events.First(); while(pEv && pEv->tick < gEditor.offset) { if(!MFString_CompareN(pEv->GetString(), "section ", 8)) pMostRecent = pEv; pEv = pEv->Next(); } if(pMostRecent) OffsetToMeasureAndBeat(pMostRecent->tick, &gEditor.measure, &gEditor.beat); else gEditor.measure = gEditor.beat = 0; } int newOffset = MeasureAndBeatToOffset(gEditor.measure, gEditor.beat); int shift = newOffset - gEditor.offset; shift = MFMax(gEditor.offset + shift, 0) - gEditor.offset; if(shift) { // update BPM if applicable int shiftStart, shiftEnd; if(shift > 0) { shiftStart = gEditor.offset; shiftEnd = gEditor.offset+shift + 1; } else { shiftStart = 0; shiftEnd = gEditor.offset+shift + 1; } gEditor.offset += shift; if(bSelecting) gEditor.selectEnd = gEditor.offset; GHEvent *pEv = gEditor.pSong->sync.GetNextEvent(shiftStart); while(pEv && pEv->tick < shiftEnd) { if(pEv->event == GHE_BPM || pEv->event == GHE_Anchor) gEditor.currentBPM = pEv->parameter; else if(pEv->event == GHE_TimeSignature) { gEditor.currentTimeSignature = pEv->parameter; gEditor.lastTimeSignature = pEv->tick; } pEv = pEv->Next(); } gEditor.playingTime = gEditor.pSong->CalculateTimeOfTick(gEditor.offset); MFVoice *pVoice = MFSound_Play(gEditor.pStepSound, MFPF_BeginPaused); if(pVoice) { MFSound_SetVolume(pVoice, gConfig.sound.fxLevel); MFSound_Pause(pVoice, false); } } // increase/decrease BPM if(gEditor.currentBPM > 1000 && TestControl(dBCtrl_Edit_DecreaseBPM, GHCT_Delay)) { // reduce BPM int inc = 1000; if(shiftState) inc /= 10; if(ctrlState) inc /= 100; if(altState) inc *= 10; GHEvent *pEv = gEditor.pSong->sync.FindEvent(GHE_BPM, gEditor.offset, 0); if(!pEv) pEv = gEditor.pSong->sync.FindEvent(GHE_Anchor, gEditor.offset, 0); if(!pEv) pEv = gEditor.pSong->sync.AddEvent(GHE_BPM, gEditor.offset, 0, MFMax(gEditor.currentBPM - inc, 1000)); else pEv->parameter = MFMax(pEv->parameter - inc, 1000); gEditor.currentBPM = pEv->parameter; // remove this BPM marker if its the same as the previous one.. if(pEv->event != GHE_Anchor) { GHEvent *pPrev = gEditor.pSong->sync.GetMostRecentEvent(GHE_BPM, gEditor.offset); if(pPrev && pPrev->parameter == pEv->parameter) gEditor.pSong->sync.RemoveEvent(pEv); } // recalculate the note times from this point on gEditor.pSong->CalculateNoteTimes(gEditor.currentStream[0], gEditor.offset); if(gEditor.currentStream[1] != -1) gEditor.pSong->CalculateNoteTimes(gEditor.currentStream[1], gEditor.offset); } if(gEditor.currentBPM < 9999000 && TestControl(dBCtrl_Edit_IncreaseBPM, GHCT_Delay)) { // increase BPM int inc = 1000; if(shiftState) inc /= 10; if(ctrlState) inc /= 100; if(altState) inc *= 10; GHEvent *pEv = gEditor.pSong->sync.FindEvent(GHE_BPM, gEditor.offset, 0); if(!pEv) pEv = gEditor.pSong->sync.FindEvent(GHE_Anchor, gEditor.offset, 0); if(!pEv) pEv = gEditor.pSong->sync.AddEvent(GHE_BPM, gEditor.offset, 0, MFMin(gEditor.currentBPM + inc, 9999000)); else pEv->parameter = MFMin(pEv->parameter + inc, 9999000); gEditor.currentBPM = pEv->parameter; // remove this BPM marker if its the same as the previous one.. if(pEv->event != GHE_Anchor) { GHEvent *pPrev = gEditor.pSong->sync.GetMostRecentEvent(GHE_BPM, gEditor.offset); if(pEv->event != GHE_Anchor && pPrev && pPrev->parameter == pEv->parameter) gEditor.pSong->sync.RemoveEvent(pEv); } // recalculate the note times from this point on gEditor.pSong->CalculateNoteTimes(gEditor.currentStream[0], gEditor.offset); if(gEditor.currentStream[1] != -1) gEditor.pSong->CalculateNoteTimes(gEditor.currentStream[1], gEditor.offset); } // place anchor if(TestControl(dBCtrl_Edit_Anchor, GHCT_Once) && gEditor.offset > 0) { GHEvent *pEv = gEditor.pSong->sync.FindEvent(GHE_BPM, gEditor.offset, 0); if(pEv) { pEv->event = GHE_Anchor; pEv->time = gEditor.pSong->CalculateTimeOfTick(pEv->tick); } else { pEv = gEditor.pSong->sync.FindEvent(GHE_Anchor, gEditor.offset, 0); if(!pEv) { pEv = gEditor.pSong->sync.AddEvent(GHE_Anchor, gEditor.offset, 0, gEditor.currentBPM); pEv->time = gEditor.pSong->CalculateTimeOfTick(pEv->tick); } else { GHEvent *pLast = gEditor.pSong->sync.GetMostRecentSyncEvent(pEv->tick); if(pLast && pLast->parameter == pEv->parameter) gEditor.pSong->sync.RemoveEvent(pEv); else pEv->event = GHE_BPM; } } // recalculate the note times gEditor.pSong->CalculateNoteTimes(gEditor.currentStream[0], 0); if(gEditor.currentStream[1] != -1) gEditor.pSong->CalculateNoteTimes(gEditor.currentStream[1], 0); } // change time signature if(TestControl(dBCtrl_Edit_DecreaseTS, GHCT_Delay) && gEditor.currentTimeSignature > 1) { int tsTime = gEditor.offset - ((gEditor.offset - gEditor.lastTimeSignature) % (res*gEditor.currentTimeSignature)); GHEvent *pEv = gEditor.pSong->sync.FindEvent(GHE_TimeSignature, tsTime, 0); if(!pEv) pEv = gEditor.pSong->sync.AddEvent(GHE_TimeSignature, tsTime, 0, gEditor.currentTimeSignature - 1); else --pEv->parameter; gEditor.currentTimeSignature = pEv->parameter; gEditor.lastTimeSignature = tsTime; // remove this BPM marker if its the same as the previous one.. GHEvent *pPrev = gEditor.pSong->sync.GetMostRecentEvent(GHE_TimeSignature, tsTime); if(pPrev && pPrev->parameter == pEv->parameter) { gEditor.lastTimeSignature = pPrev->tick; gEditor.pSong->sync.RemoveEvent(pEv); } // recalculate the note times from this point on gEditor.pSong->CalculateNoteTimes(gEditor.currentStream[0], tsTime); if(gEditor.currentStream[1] != -1) gEditor.pSong->CalculateNoteTimes(gEditor.currentStream[1], tsTime); } else if(TestControl(dBCtrl_Edit_IncreaseTS, GHCT_Delay) && gEditor.currentTimeSignature < 99) { int tsTime = gEditor.offset - ((gEditor.offset - gEditor.lastTimeSignature) % (res*gEditor.currentTimeSignature)); GHEvent *pEv = gEditor.pSong->sync.FindEvent(GHE_TimeSignature, tsTime, 0); if(!pEv) pEv = gEditor.pSong->sync.AddEvent(GHE_TimeSignature, tsTime, 0, gEditor.currentTimeSignature + 1); else ++pEv->parameter; gEditor.currentTimeSignature = pEv->parameter; gEditor.lastTimeSignature = tsTime; // remove this BPM marker if its the same as the previous one.. GHEvent *pPrev = gEditor.pSong->sync.GetMostRecentEvent(GHE_TimeSignature, tsTime); if(pPrev && pPrev->parameter == pEv->parameter) { gEditor.lastTimeSignature = pPrev->tick; gEditor.pSong->sync.RemoveEvent(pEv); } // recalculate the note times from this point on gEditor.pSong->CalculateNoteTimes(gEditor.currentStream[0], tsTime); if(gEditor.currentStream[1] != -1) gEditor.pSong->CalculateNoteTimes(gEditor.currentStream[1], tsTime); } // add/remove notes GHEventManager ¬eStream = gEditor.pSong->notes[gEditor.currentStream[gEditor.selectedStream]]; dBControlType keys_righty[] = { dBCtrl_Edit_Note0, dBCtrl_Edit_Note1, dBCtrl_Edit_Note2, dBCtrl_Edit_Note3, dBCtrl_Edit_Note4, dBCtrl_Edit_PS1, dBCtrl_Edit_PS2, dBCtrl_Edit_Note5 }; dBControlType keys_lefty[] = { dBCtrl_Edit_Note4, dBCtrl_Edit_Note3, dBCtrl_Edit_Note2, dBCtrl_Edit_Note1, dBCtrl_Edit_Note0, dBCtrl_Edit_PS1, dBCtrl_Edit_PS2, dBCtrl_Edit_Note5 }; dBControlType *keys = gConfig.controls.leftyFlip[0] ? keys_lefty : keys_righty; for(int a=0; a<8; a++) { GHEventType ev = a < 5 ? GHE_Note : GHE_Special; int key = a < 5 ? GHEK_Green + a : GHS_Player1 + (a - 5); if(TestControl(keys[a], GHCT_Hold)) { if(pHold[a]) { if(pHold[a] != (GHEvent*)(size_t)0xFFFFFFFF) { pHold[a]->parameter = MFMax(gEditor.offset - pHold[a]->tick, 0); } } else { GHEvent *pEv = noteStream.FindEvent(ev, gEditor.offset, key); if(pEv) { noteStream.RemoveEvent(pEv); pHold[a] = (GHEvent*)(size_t)0xFFFFFFFF; for(int i=0; i<8; ++i) { if(pHold[i] && pHold[i] != (GHEvent*)(size_t)0xFFFFFFFF) { if(pHold[i] > pEv) --pHold[i]; } } } else { // check if we are intersecting a hold note pEv = noteStream.GetMostRecentEvent(GHE_Note, gEditor.offset); if(pEv && pEv->parameter > gEditor.offset - pEv->tick) { // the last note was a hold note, we'll cut it short... do { pEv->parameter = gEditor.offset - pEv->tick; pEv = pEv->Prev(); } while(pEv && pEv->tick == pEv->Next()->tick); } pEv = noteStream.AddEvent(ev, gEditor.offset, key); pEv->time = gEditor.pSong->CalculateTimeOfTick(gEditor.offset); pHold[a] = pEv; } } } else { if(a<5) { // check if we have just released a hold note if(pHold[a] && pHold[a] != (GHEvent*)(size_t)0xFFFFFFFF && pHold[a]->parameter != 0) { // remove any other notes within the hold range GHEvent *pEv = gEditor.pSong->notes[gEditor.currentStream[gEditor.selectedStream]].GetNextEvent(pHold[a]->tick); while(pEv && pEv->tick < pHold[a]->tick+pHold[a]->parameter) { GHEvent *pNext = pEv->Next(); if(pEv->event == GHE_Note) { // and make sure we dont remove chords if(pHold[a]->tick != pEv->tick || pHold[a]->parameter != pEv->parameter) { pNext = noteStream.RemoveEvent(pEv); for(int i=0; i<8; ++i) { if(pHold[i] && pHold[i] != (GHEvent*)(size_t)0xFFFFFFFF) { if(pHold[i] > pEv) --pHold[i]; } } } } pEv = pNext; } } } else { // remove zero length special events... if(pHold[a] && pHold[a] != (GHEvent*)(size_t)0xFFFFFFFF && pHold[a]->parameter == 0) { noteStream.RemoveEvent(pHold[a]); } } pHold[a] = NULL; } } }
void Editor::UpdateInput() { GHScreen::UpdateInput(); // check for main menu if(TestControl(dBCtrl_Edit_Menu, GHCT_Once)) gMenu.Push(); if(TestControl(dBCtrl_Edit_PopupMenu, GHCT_Once)) ShowPopupMenu(); // check for section jump if(TestControl(dBCtrl_Edit_Goto, GHCT_Once)) gpStringBox->Show(MFTranslation_GetString(pStrings, MENU_GOTO), "", GotoSection); // update the editor. UpdateEditor(); // enable/disable half time if(TestControl(dBCtrl_Edit_PlaybackRate, GHCT_Once)) { bHalfSpeed.data = (bHalfSpeed.data + 1) % (int)(sizeof(gSpeeds) / sizeof(gSpeeds[0])); if(gEditor.pSong->pStream) MFSound_SetPlaybackRate(MFSound_GetStreamVoice(gEditor.pSong->pStream), gSpeeds[bHalfSpeed]); if(gEditor.pSong->pGuitar) MFSound_SetPlaybackRate(MFSound_GetStreamVoice(gEditor.pSong->pGuitar), gSpeeds[bHalfSpeed]); if(gEditor.pSong->pBass) MFSound_SetPlaybackRate(MFSound_GetStreamVoice(gEditor.pSong->pBass), gSpeeds[bHalfSpeed]); } // swap modes if(TestControl(dBCtrl_Edit_StartPlayback, GHCT_Once) || TestControl(dBCtrl_Edit_RestartPlayback, GHCT_Once)) { gEditor.state = GHPS_Playing; gEditor.pSong->CalculateNoteTimes(gEditor.currentStream[0], 0); if(gEditor.currentStream[1] != -1) gEditor.pSong->CalculateNoteTimes(gEditor.currentStream[1], 0); if(TestControl(dBCtrl_Edit_RestartPlayback, GHCT_Once)) { gEditor.playbackStartOffset = 0; gEditor.playingTime = 0; } else { gEditor.playbackStartOffset = gEditor.offset; gEditor.playingTime = gEditor.pSong->CalculateTimeOfTick(gEditor.offset); } gEditor.pSong->Play(gEditor.playingTime); gPlay.scoreKeeper[0].Begin(gEditor.pSong, (GHStreams)gEditor.currentStream[0], 0, gEditor.playingTime); if(gEditor.currentStream[1] != -1) gPlay.scoreKeeper[1].Begin(gEditor.pSong, (GHStreams)gEditor.currentStream[1], 1, gEditor.playingTime); if(gEditor.pSong->pStream || gEditor.pSong->pGuitar || gEditor.pSong->pBass) { gEditor.playStart = 0; gEditor.lastTimestamp = 0; } else { gEditor.playStart = MFSystem_ReadRTC(); } gEditor.startTime = gEditor.playingTime; bSelecting = false; Pop(); gPlay.Push(); } }
void Fretboard::Draw(float time, dBChart *pSong, int track) { MFCALLSTACKc; MFView_Push(); MFRect rect; MFView_GetViewport(&rect); float aspect = rect.width / rect.height; aspect = MFClamp(0.82f, aspect, 2.0f); MFView_SetAspectRatio(aspect); if(viewPoint == 0) { // incoming MFView_ConfigureProjection(MFDEGREES(65.0f)/aspect, 1.0f, 100.0f); // Setup the Camera in 3D space. MFMatrix cameraMatrix; MFVector start = MakeVector( 0, 8, 3 ); MFVector dir = MakeVector( 0, 5, -8 ); dir = (dir-start) * (1.0f/1.777777777f); cameraMatrix.LookAt(start + dir*aspect, MakeVector(0.0f, 0.0f, 5.0f)); MFView_SetCameraMatrix(cameraMatrix); } else if(viewPoint == 1) { // overhead MFView_ConfigureProjection(MFDEGREES(45.0f), 1.0f, 100.0f); /* float aspect = MFDisplay_GetNativeAspectRatio(); MFView_SetAspectRatio(aspect); MFRect projRect; projRect.y = 15; projRect.height = -30; projRect.x = -projRect.y * aspect; projRect.width = -projRect.height * aspect; MFView_SetOrtho(&projRect); */ // Setup the Camera in 3D space. MFMatrix cameraMatrix; cameraMatrix.LookAt(MakeVector(0, 30, 10), MakeVector(0, 0, 10), MakeVector(0, 0, 1)); MFView_SetCameraMatrix(cameraMatrix); } else if(viewPoint == 2) { // overhead MFView_ConfigureProjection(MFDEGREES(45.0f), 1.0f, 100.0f); /* float aspect = MFDisplay_GetNativeAspectRatio(); MFView_SetAspectRatio(aspect); MFRect projRect; projRect.y = 15; projRect.height = -30; projRect.x = -projRect.y * aspect; projRect.width = -projRect.height * aspect; MFView_SetOrtho(&projRect); */ // Setup the Camera in 3D space. MFMatrix cameraMatrix; cameraMatrix.LookAt(MakeVector(0, 20, 13), MakeVector(0, 0, 13), MakeVector(-1, 0, 0)); MFView_SetCameraMatrix(cameraMatrix); } MFView_SetProjection(); MFMaterial *pFB = pSong->pFretboard ? pSong->pFretboard : pFretboard; MFMaterial_SetMaterial(pFB); MFPrimitive(PT_TriStrip, 0); int start = -4; int end = 60; int fadeStart = end - 10; float fretboardRepeat = 15.0f; float fretboardWidth = 7.0f; float columnWidth = fretboardWidth / 5.0f; float ringBorder = 0.1f; // draw the fretboard... MFBegin(((end-start) / 4) * 2 + 2); MFSetColourV(MFVector::white); float halfFB = fretboardWidth*0.5f; float offset = time*scrollSpeed; float topTime = time + end/scrollSpeed; float bottomTime = time + start/scrollSpeed; int a; float textureOffset = fmodf(offset, fretboardRepeat); for(a=start; a<end; a+=4) { float z = (float)a; MFSetTexCoord1(1.0f, 1.0f - (z+textureOffset) / fretboardRepeat); MFSetPosition(halfFB, 0.0f, z); MFSetTexCoord1(0.0f, 1.0f - (z+textureOffset) / fretboardRepeat); MFSetPosition(-halfFB, 0.0f, z); } float z = (float)a; MFSetTexCoord1(1.0f, 1.0f - (z+textureOffset) / fretboardRepeat); MFSetPosition(halfFB, 0.0f, z); MFSetTexCoord1(0.0f, 1.0f - (z+textureOffset) / fretboardRepeat); MFSetPosition(-halfFB, 0.0f, z); MFEnd(); // draw the selection region MFMaterial_SetMaterial(pFrets); MFPrimitive(PT_TriStrip, 0); if(gEditor.selectStart != gEditor.selectEnd) { float selectStartTime = GETSECONDS(pSong->CalculateTimeOfTick(gEditor.selectStart)); float selectEndTime = GETSECONDS(pSong->CalculateTimeOfTick(gEditor.selectEnd)); if(selectStartTime < topTime && selectEndTime > bottomTime) { selectStartTime = (MFMax(bottomTime, selectStartTime) - time) * scrollSpeed; selectEndTime = (MFMin(topTime, selectEndTime) - time) * scrollSpeed; MFBegin(4); MFSetColour(1.0f, 0.0f, 0.0f, 0.5f); MFSetPosition(-halfFB, 0.0f, selectEndTime); MFSetPosition(halfFB, 0.0f, selectEndTime); MFSetPosition(-halfFB, 0.0f, selectStartTime); MFSetPosition(halfFB, 0.0f, selectStartTime); MFEnd(); } } // draw the fretboard edges and bar lines const float barWidth = 0.2f; MFMaterial_SetMaterial(pBar); MFPrimitive(PT_TriStrip, 0); MFBegin(4); MFSetColour(0.0f, 0.0f, 0.0f, 0.8f); MFSetTexCoord1(0,0); MFSetPosition(-halfFB, 0.0f, barWidth); MFSetTexCoord1(1,0); MFSetPosition(halfFB, 0.0f, barWidth); MFSetTexCoord1(0,1); MFSetPosition(-halfFB, 0.0f, -barWidth); MFSetTexCoord1(1,1); MFSetPosition(halfFB, 0.0f, -barWidth); MFEnd(); MFMaterial_SetMaterial(pEdge); MFPrimitive(PT_TriStrip, 0); MFBegin(34); MFSetColour(0.0f, 0.0f, 0.0f, 0.3f); for(int col=1; col<5; col++) { if(col > 1) MFSetPosition(-halfFB + columnWidth*(float)col - 0.02f, 0.0f, (float)end); MFSetTexCoord1(0,0); MFSetPosition(-halfFB + columnWidth*(float)col - 0.02f, 0.0f, (float)end); MFSetTexCoord1(1,0); MFSetPosition(-halfFB + columnWidth*(float)col + 0.02f, 0.0f, (float)end); MFSetTexCoord1(0,1); MFSetPosition(-halfFB + columnWidth*(float)col - 0.02f, 0.0f, (float)start); MFSetTexCoord1(1,1); MFSetPosition(-halfFB + columnWidth*(float)col + 0.02f, 0.0f, (float)start); MFSetPosition(-halfFB + columnWidth*(float)col + 0.02f, 0.0f, (float)start); } MFSetColourV(MFVector::white); MFSetPosition(-halfFB - 0.1f, 0.0f, (float)end); MFSetTexCoord1(0,0); MFSetPosition(-halfFB - 0.1f, 0.0f, (float)end); MFSetTexCoord1(1,0); MFSetPosition(-halfFB + 0.1f, 0.0f, (float)end); MFSetTexCoord1(0,1); MFSetPosition(-halfFB - 0.1f, 0.0f, (float)start); MFSetTexCoord1(1,1); MFSetPosition(-halfFB + 0.1f, 0.0f, (float)start); MFSetPosition(-halfFB + 0.1f, 0.0f, (float)start); MFSetPosition(halfFB - 0.1f, 0.0f, (float)end); MFSetTexCoord1(0,0); MFSetPosition(halfFB - 0.1f, 0.0f, (float)end); MFSetTexCoord1(1,0); MFSetPosition(halfFB + 0.1f, 0.0f, (float)end); MFSetTexCoord1(0,1); MFSetPosition(halfFB - 0.1f, 0.0f, (float)start); MFSetTexCoord1(1,1); MFSetPosition(halfFB + 0.1f, 0.0f, (float)start); MFEnd(); // draw the frets.... MFMaterial_SetMaterial(pBar); MFPrimitive(PT_TriStrip, 0); int bottomTick = pSong->CalculateTickAtTime((int64)(bottomTime*1000000.0f)); int res = pSong->GetRes(); int ticks = bHalfFrets ? res/2 : res; int fretBeat = bottomTick + ticks - 1; fretBeat -= fretBeat % ticks; float fretTime = GETSECONDS(pSong->CalculateTimeOfTick(fretBeat)); while(fretTime < topTime) { bool halfBeat = (fretBeat % res) != 0; bool bar = false; if(!halfBeat) { GHEvent *pLastTS = pSong->sync.GetMostRecentEvent(GHE_TimeSignature, fretBeat); if(pLastTS) bar = ((fretBeat - pLastTS->tick) % (pLastTS->parameter*res)) == 0; else if(fretBeat == 0) bar = true; } float bw = bar ? barWidth : barWidth*0.5f; MFBegin(4); float position = (fretTime - time) * scrollSpeed; if(!halfBeat) MFSetColourV(MFVector::white); else MFSetColourV(MakeVector(1,1,1,0.3f)); MFSetTexCoord1(0,0); MFSetPosition(-halfFB, 0.0f, position + bw); MFSetTexCoord1(1,0); MFSetPosition(halfFB, 0.0f, position + bw); MFSetTexCoord1(0,1); MFSetPosition(-halfFB, 0.0f, position + -bw); MFSetTexCoord1(1,1); MFSetPosition(halfFB, 0.0f, position + -bw); MFEnd(); fretBeat += ticks; fretTime = GETSECONDS(pSong->CalculateTimeOfTick(fretBeat)); } // draw the notes... GHEventManager ¬eStream = pSong->notes[track]; GHEvent *pEv = noteStream.First(); int64 topTimeus = (int64)(topTime*1000000.0f); while(pEv && pEv->time < topTimeus) { if((pEv->event == GHE_Note || pEv->event == GHE_Special) && pEv->tick + pEv->parameter >= bottomTick) { float evTime = GETSECONDS(pEv->time); // TODO: we need to calculate the end of the hold... float noteEnd = evTime; if(pEv->parameter) noteEnd = GETSECONDS(pSong->CalculateTimeOfTick(pEv->tick + pEv->parameter)); if(pEv->event == GHE_Note && pEv->played != 1) { // draw a note int key = pEv->key; bool tap = false; // check if there is a previous note, and it is in range if(pEv->Prev() && pEv->Prev()->tick < pEv->tick && pEv->Prev()->tick > pEv->tick - (res/2) && pEv->Prev()->key != pEv->key && (!pEv->Next() || !(pEv->Next()->tick == pEv->tick)) && !pEv->Prev()->parameter && !(pEv->Prev()->Prev() && pEv->Prev()->Prev()->tick == pEv->Prev()->tick)) { tap = true; } int noteX = gConfig.controls.leftyFlip[0] ? 4-key : key; float position = (GETSECONDS(pEv->time) - time)*scrollSpeed; float xoffset = -halfFB + columnWidth*0.5f + (float)noteX*columnWidth; if(pEv->parameter) { MFMaterial_SetMaterial(pFrets); float whammyTop = (noteEnd - time)*scrollSpeed; MFPrimitive(PT_TriStrip, 0); // TODO: we could consider not drawing this part of the hold line.. seems reasonable that it terminates at the line... if(gEditor.state == GHPS_Stopped) { if(position < 0.0f) { MFBegin(4); MFSetColourV(gColours[key]); MFSetPosition(xoffset - 0.2f, 0.0f, MFMin(whammyTop, 0.0f)); MFSetPosition(xoffset + 0.2f, 0.0f, MFMin(whammyTop, 0.0f)); MFSetPosition(xoffset - 0.2f, 0.0f, position); MFSetPosition(xoffset + 0.2f, 0.0f, position); MFEnd(); } } if(whammyTop > 0.0f) { // this half could have waves cruising down it if we wanted to support the whammy... MFBegin(4); MFSetColourV(gColours[key]); MFSetPosition(xoffset - 0.2f, 0.0f, MFMin(whammyTop, (float)end)); MFSetPosition(xoffset + 0.2f, 0.0f, MFMin(whammyTop, (float)end)); MFSetPosition(xoffset - 0.2f, 0.0f, MFMax(position, 0.0f)); MFSetPosition(xoffset + 0.2f, 0.0f, MFMax(position, 0.0f)); MFEnd(); } } if(evTime >= bottomTime) { MFMatrix mat; mat.SetScale(MakeVector(0.5f/20, 0.5f/20, 0.5f/20)); mat.Translate(MakeVector(xoffset, 0.03f, position)); MFModel_SetWorldMatrix(pButton, mat); MFStateBlock *pSB = MFStateBlock_CreateTemporary(64); MFStateBlock_SetVector(pSB, MFSCV_DiffuseColour, pEv->played == -1 ? MakeVector(0.3f, 0.3f, 0.3f, 1.0f) : MFVector::white); // MFStateBlock_SetVector(pSB, MFSCV_DiffuseColour, position < 0.0f ? MakeVector(0.3f, 0.3f, 0.3f, 1.0f) : MFVector::white); // MFRenderer_SetRenderStateOverride(MFRS_MaterialOverride, (uint32&)(tap ? pButtonMat[key] : pButtonRing[key])); MFRenderer_AddModel(pButton, pSB, MFView_GetViewState()); // render the note time if(bRenderNoteTimes) { MFView_Push(); MFView_SetOrtho(&rect); MFVector pos; MFView_TransformPoint3DTo2D(MakeVector(xoffset, 0.0f, position), &pos); pos.x += 16.0f; pos.y -= 26.0f; int minutes = (int)(pEv->time / 60000000); int seconds = (int)((pEv->time % 60000000) / 1000000); int milliseconds = (int)((pEv->time % 1000000) / 1000); MFFont_DrawTextf(pText, pos, 20.0f, MFVector::yellow, "%s: %d:%02d.%d\nTick: %g", MFTranslation_GetString(pStrings, TRACK_TIME), minutes, seconds, milliseconds, (float)pEv->tick/res); MFView_Pop(); } } } if(pEv->event == GHE_Special) { // static MFVector specialColours[3] = { MakeVector(1,0,0,1), MakeVector(1,1,0,1), MakeVector(0,0,1,1) }; // static float specialX[3] = { halfFB + 0.2f, halfFB + 1, -halfFB - 1 }; // static float specialWidth[3] = { 0.8f, 0.8f, 0.8f }; static MFVector specialColours[3] = { MakeVector(1,0,0,0.5f), MakeVector(1,1,0,0.5f), MakeVector(0,0,1,0.5f) }; static float specialX[3] = { -halfFB, halfFB - 0.8f, -halfFB }; static float specialWidth[3] = { 0.8f, 0.8f, fretboardWidth }; float bottom = (evTime - time)*scrollSpeed; float top = (noteEnd - time)*scrollSpeed; int key = pEv->key; MFMaterial_SetMaterial(pFrets); MFPrimitive(PT_TriStrip, 0); MFBegin(4); MFSetColourV(specialColours[key]); MFSetPosition(specialX[key], 0.0f, MFMin(top, (float)end)); MFSetPosition(specialX[key]+specialWidth[key], 0.0f, MFMin(top, (float)end)); MFSetPosition(specialX[key], 0.0f, MFMax(bottom, (float)start)); MFSetPosition(specialX[key]+specialWidth[key], 0.0f, MFMax(bottom, (float)start)); MFEnd(); } } pEv = pEv->Next(); } // MFRenderer_SetRenderStateOverride(MFRS_MaterialOverride, NULL); // draw circles at the bottom.. MFMaterial_SetMaterial(pRing); for(int a=0; a<5; a++) { DrawRing(-halfFB + (float)a*columnWidth + columnWidth*ringBorder, 0.0f, columnWidth*(1.0f-ringBorder*2)); } for(int a=0; a<5; a++) { dBControlType keys_righty[] = { dBCtrl_Edit_Note0, dBCtrl_Edit_Note1, dBCtrl_Edit_Note2, dBCtrl_Edit_Note3, dBCtrl_Edit_Note4 }; dBControlType keys_lefty[] = { dBCtrl_Edit_Note4, dBCtrl_Edit_Note3, dBCtrl_Edit_Note2, dBCtrl_Edit_Note1, dBCtrl_Edit_Note0 }; dBControlType *keys = gConfig.controls.leftyFlip[0] ? keys_lefty : keys_righty; int ringPos = gConfig.controls.leftyFlip[0] ? 4-a : a; MFMaterial_SetMaterial(pColourRing[a]); DrawRing(-halfFB + (float)ringPos*columnWidth, 0.0f, columnWidth, !TestControl(keys[a], GHCT_Hold)); } // render trigger particles MFParticleSystem_Draw(pParticles); // render text and stuff MFView_SetOrtho(&rect); pEv = pSong->sync.GetNextEvent(bottomTick); while(pEv && pEv->time < topTimeus) { float evTime = GETSECONDS(pEv->time); if(evTime > bottomTime) { if(pEv->event == GHE_BPM) { float position = (evTime - time) * scrollSpeed; MFVector pos; MFView_TransformPoint3DTo2D(MakeVector(halfFB + 0.2f, 0.0f, position), &pos); pos.y -= 12.0f; MFFont_DrawTextf(pText, pos, 24.0f, MakeVector(0,0.5f,0,1), "%s: %g", MFTranslation_GetString(pStrings, TRACK_BPM), (float)pEv->parameter * 0.001f); } if(pEv->event == GHE_Anchor) { int minutes = (int)(pEv->time / 60000000); int seconds = (int)((pEv->time%60000000)/1000000); int milliseconds = (int)((pEv->time%1000000)/1000); float position = (evTime - time) * scrollSpeed; MFVector pos; MFView_TransformPoint3DTo2D(MakeVector(halfFB + 0.2f, 0.0f, position), &pos); pos.y -= 12.0f; MFFont_DrawTextf(pText, pos, 24.0f, MakeVector(0,0.5f,0,1), "A: %02d:%02d.%03d\n %s: %g", minutes, seconds, milliseconds, MFTranslation_GetString(pStrings, TRACK_BPM), (float)pEv->parameter * 0.001f); } else if(pEv->event == GHE_TimeSignature) { float position = (evTime - time) * scrollSpeed; MFVector pos; MFView_TransformPoint3DTo2D(MakeVector(-halfFB - 0.2f, 0.0f, position), &pos); const char *pString = MFStr("TS: %d/4", pEv->parameter); pos.x -= MFFont_GetStringWidth(pText, pString, 24.0f); pos.y -= 12.0f; MFFont_DrawTextf(pText, pos, 24.0f, MFVector::yellow, pString); } } pEv = pEv->Next(); } // render events pEv = pSong->events.GetNextEvent(bottomTick); int lastChecked = -1; float yEventOffset = -12.0f; while(pEv && pEv->time < topTimeus) { float evTime = GETSECONDS(pEv->time); if(evTime > bottomTime) { if(pEv->event == GHE_Event) { if(lastChecked != pEv->tick) { yEventOffset = -12.0f; lastChecked = pEv->tick; if(pSong->sync.FindEvent(GHE_TimeSignature, pEv->tick, 0)) { yEventOffset -= 24.0f; } } float position = (evTime - time) * scrollSpeed; MFVector pos; MFView_TransformPoint3DTo2D(MakeVector(-halfFB - 0.2f, 0.0f, position), &pos); if(!MFString_CompareN(pEv->GetString(), "section ", 8)) { // draw a line across? pos.x -= MFFont_GetStringWidth(pText, &pEv->GetString()[8], 24.0f); pos.y += yEventOffset; MFFont_DrawTextf(pText, pos, 24.0f, MFVector::blue, &pEv->GetString()[8]); } else { pos.x -= MFFont_GetStringWidth(pText, pEv->GetString(), 24.0f); pos.y += yEventOffset; MFFont_DrawTextf(pText, pos, 24.0f, MFVector::white, pEv->GetString()); } yEventOffset -= 24.0f; } } pEv = pEv->Next(); } // render track events pEv = pSong->notes[track].GetNextEvent(bottomTick); lastChecked = -1; yEventOffset = -12.0f; while(pEv && pEv->time < topTimeus) { float evTime = GETSECONDS(pEv->time); if(evTime > bottomTime) { if(pEv->event == GHE_Event) { if(lastChecked != pEv->tick) { yEventOffset = -12.0f; lastChecked = pEv->tick; if(pSong->sync.FindEvent(GHE_TimeSignature, pEv->tick, 0)) { yEventOffset -= 24.0f; } GHEvent *pOther = pSong->events.FindEvent(GHE_Event, pEv->tick, 0); while(pOther && pOther->tick == pEv->tick) { yEventOffset -= 24.0f; pOther = pOther->Next(); } } float position = (evTime - time) * scrollSpeed; MFVector pos; MFView_TransformPoint3DTo2D(MakeVector(-halfFB - 0.2f, 0.0f, position), &pos); pos.x -= MFFont_GetStringWidth(pText, pEv->GetString(), 24.0f); pos.y += yEventOffset; MFFont_DrawTextf(pText, pos, 24.0f, MakeVector(0.6f, 0.8f, 1.0f, 1.0f), pEv->GetString()); yEventOffset -= 24.0f; } } pEv = pEv->Next(); } MFView_Pop(); }