void ofxTLKeyframes::mouseDragged(ofMouseEventArgs& args, long millis){ if(keysAreStretchable){ //cast the stretch anchor to long so that it can be signed float stretchRatio = 1.0*(millis-long(stretchAnchor)) / (1.0*stretchSelectPoint-stretchAnchor); for(int k = 0; k < selectedKeyframes.size(); k++){ setKeyframeTime(selectedKeyframes[k], ofClamp(stretchAnchor + (selectedKeyframes[k]->grabTimeOffset * stretchRatio), 0, timeline->getDurationInMilliseconds())); selectedKeyframes[k]->screenPosition = screenPositionForKeyframe(selectedKeyframes[k]); } timeline->flagUserChangedValue(); keysDidDrag = true; updateKeyframeSort(); } if(keysAreDraggable && selectedKeyframes.size() != 0){ ofVec2f screenpoint(args.x,args.y); for(int k = 0; k < selectedKeyframes.size(); k++){ ofVec2f newScreenPosition; setKeyframeTime(selectedKeyframes[k], ofClamp(millis - selectedKeyframes[k]->grabTimeOffset, screenXToMillis(bounds.getMinX()), screenXToMillis(bounds.getMaxX()))); selectedKeyframes[k]->value = screenYToValue(args.y - selectedKeyframes[k]->grabValueOffset); selectedKeyframes[k]->screenPosition = screenPositionForKeyframe(selectedKeyframes[k]); } if(selectedKeyframe != NULL && timeline->getMovePlayheadOnDrag()){ timeline->setCurrentTimeMillis(selectedKeyframe->time); } timeline->flagUserChangedValue(); keysDidDrag = true; updateKeyframeSort(); } createNewOnMouseup = false; }
void ofxTLKeyframes::deleteSelectedKeyframes(){ //vector<ofxTLKeyframe*>::iterator selectedIt = selectedKeyframes.end(); for(int i = keyframes.size() - 1; i >= 0; i--){ if(isKeyframeSelected(keyframes[i])){ if(keyframes[i] != selectedKeyframes[selectedKeyframes.size()-1]){ ofLogError("ofxTLKeyframes::deleteSelectedKeyframes") << "keyframe delete inconsistency"; } willDeleteKeyframe(keyframes[i]); if(keyframes[i] == hoverKeyframe){ hoverKeyframe = NULL; } delete keyframes[i]; keyframes.erase(keyframes.begin()+i); //if(selectedIt != selectedKeyframes.begin()){ // selectedIt--; selectedKeyframes.erase(--selectedKeyframes.end()); //} } } selectedKeyframes.clear(); updateKeyframeSort(); timeline->flagTrackModified(this); }
void ofxTLKeyframer::load() { ofxXmlSettings savedkeyframes; cout << "Loading keyframe file " << xmlFileName << endl; if(!savedkeyframes.loadFile(xmlFileName)) { ofLog(OF_LOG_ERROR, "ofxTLKeyframer --- couldn't load xml file " + xmlFileName); reset(); return; } clear(); savedkeyframes.pushTag("keyframes"); int numKeyTags = savedkeyframes.getNumTags("key"); for(int i = 0; i < numKeyTags; i++) { savedkeyframes.pushTag("key", i); ofxTLKeyframe* key = newKeyframe(ofVec2f(savedkeyframes.getValue("x", 0.0), savedkeyframes.getValue("y", 0.0))); key->easeFunc = easingFunctions[ofClamp(savedkeyframes.getValue("easefunc", 0), 0, easingFunctions.size()-1)]; key->easeType = easingTypes[ofClamp(savedkeyframes.getValue("easetype", 0), 0, easingTypes.size()-1)]; savedkeyframes.popTag(); //key } savedkeyframes.popTag();//keyframes updateKeyframeSort(); }
void ofxTLKeyframes::pasteSent(string pasteboard){ vector<ofxTLKeyframe*> keyContainer; ofxXmlSettings pastedKeys; if(pastedKeys.loadFromBuffer(pasteboard)){ createKeyframesFromXML(pastedKeys, keyContainer); if(keyContainer.size() != 0){ timeline->unselectAll(); int numKeyframesPasted = 0; //normalize and add at playhead //for(int i = 0; i < keyContainer.size(); i++){ for(int i = keyContainer.size()-1; i >= 0; i--){ keyContainer[i]->time -= keyContainer[0]->time; keyContainer[i]->time += timeline->getCurrentTimeMillis(); if(keyContainer[i]->time <= timeline->getDurationInMilliseconds()){ selectedKeyframes.push_back(keyContainer[i]); keyframes.push_back(keyContainer[i]); numKeyframesPasted++; } else{ delete keyContainer[i]; } } if(numKeyframesPasted > 0){ updateKeyframeSort(); timeline->flagTrackModified(this); } // if(timeline->getMovePlayheadOnPaste()){ // timeline->setCurrentTimeMillis( keyContainer[keyContainer.size()-1]->time ); // } } } }
void ofxTLKeyframes::nudgeBy(ofVec2f nudgePercent){ for(int i = 0; i < selectedKeyframes.size(); i++){ selectedKeyframes[i]->time = ofClamp(selectedKeyframes[i]->time + timeline->getDurationInMilliseconds()*nudgePercent.x, 0, timeline->getDurationInMilliseconds()); selectedKeyframes[i]->value = ofClamp(selectedKeyframes[i]->value + nudgePercent.y, 0, 1.0); } updateKeyframeSort(); timeline->flagTrackModified(this); }
void ofxTLKeyframes::loadFromXMLRepresentation(string rep){ clear(); ofxXmlSettings buffer; buffer.loadFromBuffer(rep); createKeyframesFromXML(buffer, keyframes); updateKeyframeSort(); timeline->flagUserChangedValue(); //because this is only called in Undo we don't flag track modified }
void ofxTLKeyframes::regionSelected(ofLongRange timeRange, ofRange valueRange){ for(int i = 0; i < keyframes.size(); i++){ if(timeRange.contains(keyframes[i]->time) && valueRange.contains(1.-keyframes[i]->value)){ selectKeyframe(keyframes[i]); } } updateKeyframeSort(); }
void ofxTLFlags::addFlagAtTime(string key, unsigned long long time){ ofxTLKeyframe* keyFrame = newKeyframe(); ofxTLFlag* flag = (ofxTLFlag*)keyFrame; setKeyframeTime(keyFrame, time); flag->textField.text = key; keyframes.push_back(keyFrame); updateKeyframeSort(); timeline->flagTrackModified(this); }
void ofxTLKeyframes::clear(){ for(int i = 0; i < keyframes.size(); i++){ willDeleteKeyframe(keyframes[i]); delete keyframes[i]; } keyframes.clear(); selectedKeyframes.clear(); updateKeyframeSort(); }
void ofxTLKeyframes::addKeyframeAtMillis(float value, unsigned long long millis){ ofxTLKeyframe* key = newKeyframe(); key->time = key->previousTime = millis; key->value = ofMap(value, valueRange.min, valueRange.max, 0, 1.0, true); keyframes.push_back(key); //smart sort, only sort if not added to end if(keyframes.size() > 2 && keyframes[keyframes.size()-2]->time > keyframes[keyframes.size()-1]->time){ updateKeyframeSort(); } lastKeyframeIndex = 1; timeline->flagTrackModified(this); shouldRecomputePreviews = true; }
void ofxTLFlags::addFlagAtTime(string key, unsigned long long time){ // cout << "***ADDING FLAG WITH TIME " << time << endl; if(time > 2000000){ cout << "***UNITITED VAR " << time << endl; return; } ofxTLKeyframe* keyFrame = newKeyframe(); ofxTLFlag* flag = (ofxTLFlag*)keyFrame; setKeyframeTime(keyFrame, time); flag->textField.text = key; keyframes.push_back(keyFrame); updateKeyframeSort(); timeline->flagTrackModified(this); }
void ofxTLKeyframes::load(){ clear(); if(useBinarySave){ loadFromBinaryFile(); } else{ ofxXmlSettings savedkeyframes; if(!savedkeyframes.loadFile(xmlFileName)){ ofLog(OF_LOG_NOTICE, "ofxTLKeyframes --- couldn't load xml file " + xmlFileName); return; } createKeyframesFromXML(savedkeyframes, keyframes); } updateKeyframeSort(); timeline->flagTrackModified(this); }
void ofxTLKeyframes::mouseDragged(ofMouseEventArgs& args, long millis){ if(keysAreDraggable && selectedKeyframes.size() != 0){ ofVec2f screenpoint(args.x,args.y); for(int k = 0; k < selectedKeyframes.size(); k++){ ofVec2f newScreenPosition; selectedKeyframes[k]->time = millis - selectedKeyframes[k]->grabTimeOffset; selectedKeyframes[k]->value = screenYToValue(args.y - selectedKeyframes[k]->grabValueOffset); selectedKeyframes[k]->screenPosition = screenPositionForKeyframe(selectedKeyframes[k]); } if(selectedKeyframe != NULL && timeline->getMovePlayheadOnDrag()){ timeline->setCurrentTimeMillis(selectedKeyframe->time); } timeline->flagUserChangedValue(); keysDidDrag = true; updateKeyframeSort(); } createNewOnMouseup = false; }
void ofxTLNotes::addKeyframeAtMillis(int pitch, float velocity, unsigned long millis, bool isGrowing){ ofxTLNote* key = (ofxTLNote*)newKeyframe(); key->time = key->previousTime = millis; key->timeRange.min = millis; key->timeRange.max = millis + 100; key->pitch = pitch; key->velocity = velocity; cout << "added keyframe with velocity " << key->velocity << endl; key->value = ofMap(pitch, valueRange.min, valueRange.max, 0, 1, true); key->growing = isGrowing; keyframes.push_back(key); //smart sort, only sort if not added to end if(keyframes.size() > 2 && keyframes[keyframes.size()-2]->time > keyframes[keyframes.size()-1]->time){ updateKeyframeSort(); } trimToPitches(); lastKeyframeIndex = 1; timeline->flagTrackModified(this); shouldRecomputePreviews = true; }
void ofxTLKeyframes::mouseReleased(ofMouseEventArgs& args, long millis){ keysAreDraggable = false; if(keysDidDrag){ //reset these caches because they may no longer be valid lastKeyframeIndex = 1; lastSampleTime = 0; timeline->flagTrackModified(this); } if(createNewOnMouseup){ //add a new one selectedKeyframe = newKeyframe(); setKeyframeTime(selectedKeyframe,millis); selectedKeyframe->value = screenYToValue(args.y); keyframes.push_back(selectedKeyframe); selectedKeyframes.push_back(selectedKeyframe); updateKeyframeSort(); timeline->flagTrackModified(this); } createNewOnMouseup = false; }
void ofxTLKeyframer::mousePressed(ofMouseEventArgs& args) { if(!enabled) return; ofVec2f screenpoint = ofVec2f(args.x, args.y); if(drawingEasingWindow) { //see if we clicked on an drawingEasingWindow = false; for(int i = 0; i < easingFunctions.size(); i++) { if(easingFunctions[i]->bounds.inside(screenpoint-easingWindowPosition)) { selectedKeyframe->easeFunc = easingFunctions[i]; if(autosave) save(); return; } } for(int i = 0; i < easingTypes.size(); i++) { if(easingTypes[i]->bounds.inside(screenpoint-easingWindowPosition)) { selectedKeyframe->easeType = easingTypes[i]; if(autosave) save(); return; } } } bool clickIsInRect = screenpointIsInBounds(screenpoint); if(!focused) { focused = clickIsInRect; if(!focused) { selectedKeyframe = NULL; drawingEasingWindow = false; } return; } if(!clickIsInRect) { focused = false; selectedKeyframe = NULL; drawingEasingWindow = false; return; } selectedKeyframe = keyframeAtScreenpoint(screenpoint, selectedKeyframeIndex); //cout << "selected index is " << selectedKeyframeIndex << endl; if(selectedKeyframe == NULL) { //add a new one selectedKeyframe = newKeyframe( keyframePointForCoord(screenpoint) ); grabOffset = ofVec2f(0,0); updateKeyframeSort(); //find bounds for(int i = 0; i < keyframes.size(); i++) { if(keyframes[i] == selectedKeyframe) { selectedKeyframeIndex = i; } } } //grabbed a keyframe if(selectedKeyframe != NULL) { timeline->setPercentComplete(selectedKeyframe->position.x); if(args.button == 0) { grabOffset = screenpoint - coordForKeyframePoint(selectedKeyframe->position); if(keyframes.size() == 1) { minBound = 0.0; maxBound = 1.0; } else if(selectedKeyframeIndex == 0) { minBound = 0.0; maxBound = keyframes[selectedKeyframeIndex+1]->position.x; } else if(selectedKeyframeIndex == keyframes.size()-1) { minBound = keyframes[selectedKeyframeIndex-1]->position.x; maxBound = 1.0; } else { minBound = keyframes[selectedKeyframeIndex-1]->position.x; maxBound = keyframes[selectedKeyframeIndex+1]->position.x; //cout << "keyframe point is " << selectedKeyframe->position.x << " min bound is " << minBound << " max bound is " << maxBound << endl; } } else if(args.button == 2) { easingWindowPosition = screenpoint; drawingEasingWindow = true; } } }
bool ofxTLKeyframes::mousePressed(ofMouseEventArgs& args, long millis){ ofVec2f screenpoint = ofVec2f(args.x, args.y); keysAreStretchable = ofGetModifierShiftPressed() && ofGetModifierControlPressed(); keysDidDrag = false; if(keysAreStretchable && timeline->getTotalSelectedItems() > 1){ unsigned long long minSelected = timeline->getEarliestSelectedTime(); unsigned long long maxSelected = timeline->getLatestSelectedTime(); if(minSelected == maxSelected){ keysAreStretchable = false; } else { unsigned long long midSelection = (maxSelected-minSelected)/2 + minSelected; //the anchor is the selected key opposite to where we are stretching stretchAnchor = midSelection <= millis ? minSelected : maxSelected; // cout << "Min selected " << ofxTimecode::timecodeForMillis(minSelected) << " Mid Selected " << ofxTimecode::timecodeForMillis(midSelection) << " Max selected " << ofxTimecode::timecodeForMillis(maxSelected) << " anchor " << ofxTimecode::timecodeForMillis(stretchAnchor) << " millis down " << ofxTimecode::timecodeForMillis(millis) << endl; stretchSelectPoint = millis; //don't do anything else, like create or deselect keyframes updateStretchOffsets(screenpoint, millis); } return true; } keysAreDraggable = !ofGetModifierShiftPressed(); selectedKeyframe = keyframeAtScreenpoint(screenpoint); //if we clicked OFF of a keyframe OR... //if we clicked on a keyframe outside of the current selection and we aren't holding down shift, clear all if(!ofGetModifierSelection() && (isActive() || selectedKeyframe != NULL) ){ bool didJustDeselect = false; if( selectedKeyframe == NULL || !isKeyframeSelected(selectedKeyframe)){ //settings this to true causes the first click off of the timeline to deselct rather than create a new keyframe didJustDeselect = timeline->getTotalSelectedItems() > 1; timeline->unselectAll(); } //if we didn't just deselect everything and clicked in an empty space add a new keyframe there if(selectedKeyframe == NULL && !didJustDeselect){ createNewOnMouseup = args.button == 0 && !ofGetModifierControlPressed(); } } if(selectedKeyframe != NULL){ //add the keyframe to the selection, whether it was just generated or not if(!isKeyframeSelected(selectedKeyframe)){ selectedKeyframes.push_back(selectedKeyframe); updateKeyframeSort(); // selectKeyframe(selectedKeyframe); } //unselect it if it's selected and we clicked the key with shift pressed else if(ofGetModifierSelection()){ deselectKeyframe(selectedKeyframe); selectedKeyframe = NULL; } } //if we have any keyframes selected update the grab offsets and check for showing the modal window if(selectedKeyframes.size() != 0){ updateDragOffsets(screenpoint, millis); if(selectedKeyframe != NULL){ if(args.button == 0 && !ofGetModifierSelection() && !ofGetModifierControlPressed()){ timeline->setDragTimeOffset(selectedKeyframe->grabTimeOffset); //move the playhead if(timeline->getMovePlayheadOnDrag()){ timeline->setCurrentTimeMillis(selectedKeyframe->time); } } if(args.button == 2 || ofGetModifierControlPressed()){ selectedKeySecondaryClick(args); } } } return selectedKeyframe != NULL; }