void ofxTLTicker::updateBPMPoints(){ bpmScreenPoints.clear(); if(!timeline->getIsFrameBased()){ double currentPoint = 0; double oneMeasure = 1.0/(bpm/60.); double halfMeasure = oneMeasure/2; double quarterMeasure = halfMeasure/2; bool showMeasure = false; bool showHalfMeasure = false; bool showQuarterMeasure = false; showMeasure = screenXForTime(oneMeasure) - screenXForTime(0) > 20; if(showMeasure){ showHalfMeasure = screenXForTime(halfMeasure) - screenXForTime(0) > 20; if (showHalfMeasure) { showQuarterMeasure = screenXForTime(halfMeasure) - screenXForTime(0) > 20; } } while(currentPoint < timeline->getDurationInSeconds()){ ofxTLBPMPoint measures[4]; int numMeasures = 0; if(showMeasure){ measures[0].screenX = screenXForTime(currentPoint); measures[0].weight = 4; numMeasures = 1; } if(showHalfMeasure){ measures[1].screenX = screenXForTime(currentPoint+halfMeasure); measures[1].weight = 2; numMeasures = 2; } if(showQuarterMeasure){ measures[2].screenX = screenXForTime(currentPoint+quarterMeasure); measures[2].weight = 1; measures[3].screenX = screenXForTime(currentPoint+halfMeasure+quarterMeasure); measures[3].weight = 1; numMeasures = 4; } // cout << "measures " << measures[0].screenX << endl; for(int m = 0; m < numMeasures; m++){ if( isOnScreen(measures[m].screenX) ){ bpmScreenPoints.push_back( measures[m] ); } } currentPoint += oneMeasure; } } }
//TODO: find a way to make this not happen every frame void ofxTLTicker::updateBPMPoints(){ bpmScreenPoints.clear(); double currentPoint = 0; double oneMeasure = 1.0/(bpm/60.); double halfMeasure = oneMeasure/2; double quarterMeasure = halfMeasure/2; bool showMeasure = false; bool showHalfMeasure = false; bool showQuarterMeasure = false; showMeasure = screenXForTime(oneMeasure) - screenXForTime(0) > 20; if(showMeasure){ showHalfMeasure = screenXForTime(halfMeasure) - screenXForTime(0) > 20; if (showHalfMeasure) { showQuarterMeasure = screenXForTime(halfMeasure) - screenXForTime(0) > 20; } } int currentMeasure = 0; while(currentPoint < timeline->getDurationInSeconds()){ ofxTLBPMPoint measures[4]; int numMeasures = 0; if(showMeasure){ measures[0].millis = currentPoint * 1000; measures[0].screenX = millisToScreenX(measures[0].millis); measures[0].weight = 4; numMeasures = 1; } if(showHalfMeasure){ measures[1].millis = (currentPoint+halfMeasure) * 1000; measures[1].screenX = millisToScreenX(measures[1].millis); measures[1].weight = 2; numMeasures = 2; } if(showQuarterMeasure){ measures[2].millis = (currentPoint+quarterMeasure) * 1000; measures[2].screenX = millisToScreenX(measures[2].millis); measures[2].weight = 1; measures[3].millis = (currentPoint+halfMeasure+quarterMeasure) * 1000; measures[3].screenX = millisToScreenX(measures[3].millis); measures[3].weight = 1; numMeasures = 4; } for(int m = 0; m < numMeasures; m++){ if( isOnScreen(measures[m].screenX) ){ bpmScreenPoints.push_back( measures[m] ); } } currentMeasure++; currentPoint = currentMeasure*oneMeasure; } }
float ofxTLElement::screenXForTime(float time){ return screenXForTime(time, timeline->getDurationInSeconds()); }
void ofxTLTicker::draw(){ ofPushStyle(); int textH, textW; string text; //draw tickers with time float startTime = zoomBounds.min * timeline->getDurationInSeconds(); float endTime = zoomBounds.max * timeline->getDurationInSeconds(); float durationInview = endTime-startTime; float secondsPerPixel = durationInview / bounds.width; if(viewIsDirty){ refreshTickMarks(); } tickerMarks.setStrokeColor( ofColor(200, 180, 40) ); tickerMarks.setStrokeWidth(1); tickerMarks.draw(bounds.x, bounds.y); if(drawBPMGrid){ if(viewIsDirty){ updateBPMPoints(); } ofPushStyle(); ofSetColor(255, 255, 255, 50); for(int i = 0; i < bpmScreenPoints.size(); i++){ ofSetLineWidth(bpmScreenPoints[i].weight); ofLine(bpmScreenPoints[i].screenX, getBottomEdge(), bpmScreenPoints[i].screenX, totalDrawRect.y+totalDrawRect.height); } ofPopStyle(); } textH = timeline->getFont().getLineHeight(); textW = 3; //highlite current mouse position if(hover){ //draw background rect ofSetColor(timeline->getColors().backgroundColor); float screenX = millisToScreenX(hoverTime); text = timeline->formatTime(hoverTime); textW = timeline->getFont().stringWidth(text)+3; if(bounds.height > 2){ int previewTimecodeX = ofClamp(screenX+5, bounds.x, bounds.x+bounds.width-textW-5); ofFill(); ofRect(previewTimecodeX-5, bounds.y+textH, textW, textH); //draw playhead line ofSetColor(timeline->getColors().textColor); timeline->getFont().drawString(text, previewTimecodeX, bounds.y+textH*2); } ofSetColor(timeline->getColors().highlightColor); ofSetLineWidth(1); ofLine(screenX, totalDrawRect.y, screenX, totalDrawRect.y+totalDrawRect.height); } //draw current frame //TIMECODE int currentFrameX; if (timeline->getIsFrameBased()) { text = ofToString(timeline->getCurrentFrame()); currentFrameX = screenXForIndex(timeline->getCurrentFrame()); } else{ text = timeline->formatTime(timeline->getCurrentTime()); currentFrameX = screenXForTime(timeline->getCurrentTime()); } if(bounds.height > 2){ int timeCodeX = ofClamp(currentFrameX+5, bounds.x, bounds.x+bounds.width-textW-5); ofSetColor(timeline->getColors().backgroundColor); ofFill(); ofRect(timeCodeX-5, bounds.y, textW, textH); ofSetColor(timeline->getColors().textColor); timeline->getFont().drawString(text, timeCodeX, bounds.y+textH); } if(timeline->getIsPlaying()){ ofSetColor(timeline->getColors().keyColor); } else{ ofSetColor(timeline->getColors().outlineColor); } //draw playhead line ofSetLineWidth(1); ofLine(currentFrameX, totalDrawRect.y, currentFrameX, totalDrawRect.y+totalDrawRect.height); //draw bounds ofNoFill(); ofSetColor(200, 180, 40); ofRect(bounds); ofPopStyle(); }
void ofxTLVideoTrack::draw(){ if(player == NULL){ return; } //inFrame = outFrame = -1; inFrame = 0; outFrame = player->getTotalNumFrames(); ofPushStyle(); int selectedFrameX = screenXForTime( timeline->getTimecode().secondsForFrame(selectedFrame)); if(thumbsEnabled && getDrawRect().height > 10){ //clip hanging frames off the sides ofSetColor(255); lock(); for(int i = 0; i < videoThumbs.size(); i++){ if(videoThumbs[i].thumb != NULL){ if(videoThumbs[i].loaded &&!videoThumbs[i].thumb->isUsingTexture()){ videoThumbs[i].thumb->setUseTexture(true); videoThumbs[i].thumb->update(); } videoThumbs[i].thumb->draw(videoThumbs[i].displayRect); } else{ ofPushStyle(); ofSetColor(0); ofRect(videoThumbs[i].displayRect); ofPopStyle(); } } unlock(); for(int i = 0; i < videoThumbs.size(); i++){ if (!thumbsEnabled) { ofFill(); ofSetColor(0); ofRect(videoThumbs[i].displayRect); } ofNoFill(); ofSetColor(timeline->getColors().textColor); timeline->getFont().drawString(ofToString(videoThumbs[i].framenum), videoThumbs[i].displayRect.x+5, videoThumbs[i].displayRect.y+15); ofRect(videoThumbs[i].displayRect); } if(drawVideoPreview){ ofRectangle previewRect = ofRectangle(0, 0, player->getWidth() - 2, player->getHeight() - 4); previewRect.scaleTo(bounds, OF_ASPECT_RATIO_KEEP); previewRect.x = selectedFrameX + 1; previewRect.y = bounds.y - 1; player->draw(previewRect); ofPushStyle(); ofFill(); ofSetColor(timeline->getColors().backgroundColor, 100); ofRect(selectedFrameX + 1, bounds.y + 1, previewRect.width - 2, bounds.height - 2); ofPopStyle(); } } ofSetColor(timeline->getColors().textColor); ofLine(selectedFrameX, bounds.y, selectedFrameX, bounds.y+bounds.height); timeline->getFont().drawString("F# " + ofToString(selectedFrame), selectedFrameX, bounds.y+15); timeline->getFont().drawString(ofxTimecode::timecodeForSeconds(player->getPosition()*player->getDuration()), selectedFrameX, bounds.y+30); if(inFrame != -1){ ofSetLineWidth(2); ofSetColor(timeline->getColors().highlightColor); int inFrameX = screenXForTime( timeline->getTimecode().secondsForFrame(inFrame)); int outFrameX = screenXForTime( timeline->getTimecode().secondsForFrame(outFrame)); ofLine(inFrameX, bounds.y, inFrameX, bounds.y+bounds.height); ofLine(outFrameX, bounds.y, outFrameX, bounds.y+bounds.height); ofSetColor(timeline->getColors().textColor); timeline->getFont().drawString("in " + ofToString(inFrame), inFrameX + 5, bounds.y + 10); timeline->getFont().drawString("out " + ofToString(outFrame), outFrameX + 5, bounds.y + bounds.height - 20); } ofPopStyle(); }
void ofxTLTicker::draw(){ ofPushStyle(); int textH, textW; string text; if(timeline->getIsFrameBased()){ int curStartFrame = ofMap(zoomBounds.min, 0, 1.0, 0, timeline->getDurationInFrames()); int curEndFrame = ofMap(zoomBounds.max, 0, 1.0, 0, timeline->getDurationInFrames()); int framesInView = curEndFrame-curStartFrame; float framesPerPixel = framesInView / bounds.width; int frameStepSize = 1; //TODO make adaptive if we are way zoomed in don't draw so many //draw ticker marks for(int i = curStartFrame; i <= curEndFrame; i++){ float x = ofMap(i, curStartFrame, curEndFrame, totalDrawRect.x, totalDrawRect.x+totalDrawRect.width, true); ofSetColor(200, 180, 40); float heightMultiplier = 0.0; if(i % 10 == 0){ ofSetLineWidth(3); heightMultiplier = .5; } else { ofSetLineWidth(1); heightMultiplier = .75; } ofLine(x, bounds.y+bounds.height*heightMultiplier, x, bounds.y+bounds.height); } } //Time based else { //draw tickers with time float startTime = zoomBounds.min * timeline->getDurationInSeconds(); float endTime = zoomBounds.max * timeline->getDurationInSeconds(); float durationInview = endTime-startTime; float secondsPerPixel = durationInview / bounds.width; //draw ticker marks ofSetLineWidth(1); ofSetColor(200, 180, 40); float heightMultiplier = .75; for(float i = startTime; i <= endTime; i += secondsPerPixel*5){ //float x = ofMap(i, curStartFrame, curEndFrame, totalDrawRect.x, totalDrawRect.x+totalDrawRect.width, true); float x = screenXForTime(i); ofLine(x, bounds.y+bounds.height*heightMultiplier, x, bounds.y+bounds.height); } //draw regular increments int bigTickStep; if(durationInview < 1){ //draw big tick every 100 millis bigTickStep = .1; } else if(durationInview < 60){ // draw big tick every second bigTickStep = 1; } else { bigTickStep = 60; } ofSetLineWidth(3); heightMultiplier = .5; for(float i = startTime-fmod(startTime, bigTickStep); i <= endTime; i+=bigTickStep){ float x = screenXForTime(i); ofLine(x, bounds.y+bounds.height*heightMultiplier, x, bounds.y+bounds.height); } if(drawBPMGrid){ updateBPMPoints(); ofPushStyle(); ofSetColor(255, 255, 255, 50); for(int i = 0; i < bpmScreenPoints.size(); i++){ ofSetLineWidth(bpmScreenPoints[i].weight); ofLine(bpmScreenPoints[i].screenX, totalDrawRect.y, bpmScreenPoints[i].screenX, totalDrawRect.y+totalDrawRect.height-20); } ofPopStyle(); } } //highlite current mouse position if(hover){ //draw background rect ofSetColor(timeline->getColors().backgroundColor); if (timeline->getIsFrameBased()) { text = ofToString(indexForScreenX(ofGetMouseX())); } else{ //text = ofToString(); text = timeline->formatTime(timeForScreenX(ofGetMouseX())); } textH = 10; textW = (text.size()+1)*7; ofRect(ofGetMouseX(), bounds.y+textH, textW, textH); //draw playhead line ofSetColor(timeline->getColors().textColor); ofDrawBitmapString(text, ofGetMouseX()+5, bounds.y+textH*2); ofSetColor(timeline->getColors().highlightColor); ofSetLineWidth(1); ofLine(ofGetMouseX(), totalDrawRect.y, ofGetMouseX(), totalDrawRect.y+totalDrawRect.height); } //draw current frame int currentFrameX; if (timeline->getIsFrameBased()) { text = ofToString(timeline->getCurrentFrame()); currentFrameX = screenXForIndex(timeline->getCurrentFrame()); } else{ //text = ofToString(); text = timeline->formatTime(timeline->getCurrentTime()); currentFrameX = screenXForTime(timeline->getCurrentTime()); } textH = 10; textW = (text.size()+1)*7; ofSetColor(timeline->getColors().backgroundColor); ofRect(currentFrameX, bounds.y, textW, textH); ofSetColor(timeline->getColors().textColor); ofDrawBitmapString(text, currentFrameX+5, bounds.y+textH); if(timeline->getIsPlaying()){ ofSetColor(timeline->getColors().keyColor); } else{ ofSetColor(timeline->getColors().outlineColor); } //draw playhead line ofSetLineWidth(1); ofLine(currentFrameX, totalDrawRect.y, currentFrameX, totalDrawRect.y+totalDrawRect.height); //draw in/out point float inPointX = normalizedXtoScreenX(timeline->getInOutRange().min, zoomBounds); float outPointX = normalizedXtoScreenX(timeline->getInOutRange().max, zoomBounds); if(bounds.x < inPointX){ ofSetColor(timeline->getColors().disabledColor,120); ofRect(bounds.x, bounds.y, inPointX - bounds.x, totalDrawRect.height); ofSetColor(timeline->getColors().highlightColor); ofLine(inPointX, bounds.y, inPointX, bounds.y+totalDrawRect.height); } if(bounds.x+bounds.width > outPointX){ ofSetColor(timeline->getColors().disabledColor,120); ofRect(outPointX, bounds.y, (bounds.x+bounds.width) - outPointX, totalDrawRect.height); ofSetColor(timeline->getColors().highlightColor); ofLine(outPointX, bounds.y, outPointX, bounds.y+totalDrawRect.height); } //draw bounds ofNoFill(); ofSetColor(200, 180, 40); ofRect(bounds); ofPopStyle(); }
void ofxTLBeatTicker::draw(){ if (!isSetup || disabled) return; ofPushStyle(); int textH, textW; string text; if(viewIsDirty){ refreshTickMarks(); } drawBPMGrid = true; tickerMarks.setStrokeColor( ofColor(0, 0, 240) ); tickerMarks.setStrokeWidth(1); tickerMarks.draw(bounds.x, bounds.y); if(drawBPMGrid){ if(viewIsDirty){ updateBPMPoints(); } ofPushStyle(); ofSetColor(0, 0, 0, 200); ofSetLineWidth(1); int siz = bpmScreenPoints.size(); int howmany; if (siz > 20) howmany = siz / 15; else if (siz > 12) howmany = 4; else howmany = 4; for(int i = 0; i < bpmScreenPoints.size(); i++) { if (isOnScreen(bpmScreenPoints[i].screenX)) { int bi = floor(bpmScreenPoints[i].beat); //if ((bi) % 4 == 1) { // draw bpms indices if ((bi) % howmany == 1) { // draw bpms indices #if DRAW_FXCKING_GRID ofLine(bpmScreenPoints[i].screenX, getBottomEdge(), bpmScreenPoints[i].screenX, totalDrawRect.y+totalDrawRect.height); #endif text = tostr(bi); textW = timeline->getFont().stringWidth(text); timeline->getFont().drawString(text, bpmScreenPoints[i].screenX - textW/2, getBottomEdge()-20); } } } ofPopStyle(); } textH = timeline->getFont().getLineHeight(); textW = 3; //draw current frame int currentFrameX; if (timeline->getIsFrameBased()) { //text = ofToString(timeline->getCurrentFrame()); text = tostr(timeline->millisecToBeat(hoverTime)); currentFrameX = screenXForIndex(timeline->getCurrentFrame()); } else{ //text = timeline->formatTime(timeline->getCurrentTime()); text = tostr(timeline->millisecToBeat(hoverTime)); currentFrameX = screenXForTime(timeline->getCurrentTime()); //currenttimeline->normalizedXtoScreenX(timeline->beatToNormalizedX(currentPoint), zoomBounds); //;timeline->millisToScreenX(timeline->beatToMillisec(measures[0].beat)); } currentFrameX = ofClamp(currentFrameX, bounds.getMinX(), bounds.getMaxX()); //draw playhead line ofSetLineWidth(1); ofLine(currentFrameX, totalDrawRect.y, currentFrameX, totalDrawRect.y+totalDrawRect.height); //text = tostr(timeline->millisecToBeat(hoverTime)+1 - startBeat); unsigned long startBeat = timeline->normalizedXToBeat(zoomBounds.min);// * timeline->getDurationInMilliseconds(); text = tostr( timeline->normalizedXToBeat( screenXtoNormalizedX( millisToScreenX(hoverTime), zoomBounds) ) + 1); //cout << "ofxTLBeatTicker: hoverTime: " << hoverTime << " text:"<< text << endl; float screenX = ofClamp(millisToScreenX(hoverTime), bounds.getMinX(), bounds.getMaxX()); timeline->getFont().drawString(text, screenX, bounds.y+textH+25); ofPopStyle(); }