00001 #ifndef OBJECTANIMATION_QT_C 00002 #define OBJECTANIMATION_QT_C 00003 00004 #include "NeovisionII/NeoAnnotate/ObjectAnimation.qt.H" 00005 #include "rutz/trace.h" 00006 00007 //###################################################################### 00008 ObjectAnimation::ObjectAnimation(int frameNum, FrameRange masterFrameRange, QPointF initialPos) : 00009 itsMasterFrameRange(masterFrameRange) 00010 { 00011 itsKeyFrames.clear(); 00012 00013 //Insert a single keyframe at the current frame number at the given initial position 00014 FrameState defaultKey; 00015 defaultKey.pos = initialPos; 00016 defaultKey.visible = true; 00017 // itsKeyFrames[masterFrameRange.getFirst()] = defaultKey; 00018 itsKeyFrames[frameNum] = defaultKey; 00019 } 00020 00021 //###################################################################### 00022 std::pair<QMap<int, ObjectAnimation::FrameState>::const_iterator, 00023 QMap<int, ObjectAnimation::FrameState>::const_iterator> 00024 ObjectAnimation::getBoundingKeyframes(int fnum) 00025 { 00026 00027 GVX_TRACE(__PRETTY_FUNCTION__); 00028 00029 //Create our bounding keyframes container, and fill it with bogus 00030 //values, in case we're asked to find unreasonable bounding frames 00031 std::pair<QMap<int, ObjectAnimation::FrameState>::const_iterator, 00032 QMap<int, ObjectAnimation::FrameState>::const_iterator> ret; 00033 ret.first = itsKeyFrames.end(); 00034 ret.second = itsKeyFrames.end(); 00035 00036 //If we're asked for unreasonable bounding frames, then just return the 00037 //bogus container 00038 if(fnum < itsKeyFrames.begin().key()) 00039 return ret; 00040 if(fnum > (itsKeyFrames.end()-1).key()) 00041 return ret; 00042 00043 //Find the first keyframe which has a larger or equal value 00044 //to the frame number 00045 ret.second = itsKeyFrames.lowerBound(fnum); 00046 00047 //Try to find the previous keyframe as long as our frameNum isn't a keyframe, or 00048 //the first frame in the animation. 00049 ret.first = ret.second; 00050 if(ret.second != itsKeyFrames.begin() && ret.second.key() != fnum) 00051 ret.first--; 00052 00053 return ret; 00054 } 00055 00056 //###################################################################### 00057 ObjectAnimation::FrameState ObjectAnimation::getFrameState(int frameNum) 00058 { 00059 GVX_TRACE(__PRETTY_FUNCTION__); 00060 00061 00062 //If the requested frame is before the first keyframe, just return an invisible 00063 //framestate 00064 if(frameNum < itsKeyFrames.begin().key()) 00065 { 00066 FrameState ret; 00067 ret.visible = false; 00068 ret.is_keyframe = false; 00069 return ret; 00070 } 00071 00072 //If we are beyond the final keyframe, then just return the position of the last known one 00073 //Note that this means that all frames after the last keyframe will inherit that last keyframe's 00074 //visibility state 00075 if(frameNum > (itsKeyFrames.end()-1).key()) 00076 { 00077 FrameState ret = (itsKeyFrames.end()-1).value(); 00078 ret.is_keyframe = false; 00079 return ret; 00080 } 00081 00082 //Find the bounding keyframes for the given frame 00083 std::pair<QMap<int, ObjectAnimation::FrameState>::const_iterator, 00084 QMap<int, ObjectAnimation::FrameState>::const_iterator> bounds = 00085 getBoundingKeyframes(frameNum); 00086 00087 //If the bounding keyframes are the same, then no need to interpolate - we 00088 //already have a keyframe 00089 if(bounds.first == bounds.second) 00090 { 00091 return bounds.first.value(); 00092 } 00093 00094 FrameState upperKey = bounds.second.value(); 00095 FrameState lowerKey = bounds.first.value(); 00096 QPointF lowerPos = lowerKey.pos; 00097 QPointF upperPos = upperKey.pos; 00098 00099 //Interpolate between the two neighboring keyframes 00100 float alpha = 1.0; 00101 if(bounds.second.key() != bounds.first.key()) 00102 { 00103 alpha = float(frameNum - bounds.first.key()) / 00104 float(bounds.second.key() - bounds.first.key()); 00105 } 00106 QPointF intPos = upperPos*alpha + lowerPos*(1.0-alpha); 00107 00108 FrameState ret; 00109 ret.pos = intPos; 00110 ret.visible = lowerKey.visible; 00111 ret.is_keyframe = false; 00112 00113 return ret; 00114 } 00115 00116 //###################################################################### 00117 AnimationDelegate::FrameType ObjectAnimation::getFrameType(int fnum) 00118 { 00119 GVX_TRACE(__PRETTY_FUNCTION__); 00120 00121 //If the requested frame is before the first keyframe, just return an invisible frametype 00122 if(fnum < itsKeyFrames.begin().key()) 00123 return AnimationDelegate::Invisible; 00124 00125 //If we are beyond the final keyframe, then look to our previous keyframe to see if we are invisible or not 00126 if(fnum > (itsKeyFrames.end()-1).key()) 00127 { 00128 FrameState ret = (itsKeyFrames.end()-1).value(); 00129 if(ret.visible) 00130 return AnimationDelegate::Tween; 00131 else 00132 return AnimationDelegate::Invisible; 00133 } 00134 00135 //Find the bounding keyframes for the given frame 00136 std::pair<QMap<int, ObjectAnimation::FrameState>::const_iterator, 00137 QMap<int, ObjectAnimation::FrameState>::const_iterator> bounds = 00138 getBoundingKeyframes(fnum); 00139 00140 //If we have an actual keyframe: 00141 if(bounds.first.key() == bounds.second.key()) 00142 { 00143 if(bounds.first.value().visible) 00144 return AnimationDelegate::VisibleKeyframe; 00145 else 00146 return AnimationDelegate::InvisibleKeyframe; 00147 } 00148 00149 if(bounds.first.value().visible) 00150 return AnimationDelegate::Tween; 00151 00152 return AnimationDelegate::Invisible; 00153 } 00154 00155 //###################################################################### 00156 bool ObjectAnimation::moveKeyframe(int from_fnum, int to_fnum) 00157 { 00158 if(itsKeyFrames.contains(from_fnum) && !itsKeyFrames.contains(to_fnum)) 00159 { 00160 if(to_fnum >= itsMasterFrameRange.getFirst() && to_fnum <= itsMasterFrameRange.getLast()) 00161 { 00162 itsKeyFrames[to_fnum] = itsKeyFrames[from_fnum]; 00163 itsKeyFrames.remove(from_fnum); 00164 emit(animationChanged()); 00165 return true; 00166 } 00167 } 00168 00169 return false; 00170 } 00171 00172 //###################################################################### 00173 void ObjectAnimation::setPosition(int frameNum, QPointF pos, bool visible) 00174 { 00175 //Construct a new keyframe at the given framenumber with the given position 00176 FrameState key; 00177 key.pos = pos; 00178 key.visible = visible; 00179 key.is_keyframe = true; 00180 //Insert the keyframe into the data store 00181 itsKeyFrames[frameNum] = key; 00182 00183 emit(animationChanged()); 00184 } 00185 00186 //###################################################################### 00187 void ObjectAnimation::constructContextMenu(QPoint pos, int column) 00188 { 00189 //Compute the absolute frame number 00190 int frameNum = column + itsMasterFrameRange.getFirst(); 00191 00192 //Create a new drop down menu 00193 QMenu menu; 00194 00195 QAction *createKeyframe = NULL; 00196 QAction *removeKeyframe = NULL; 00197 QAction *makeVisible = NULL; 00198 QAction *makeInvisible = NULL; 00199 00200 //Find the relevant frame number 00201 QMap<int, FrameState>::iterator frameIt = itsKeyFrames.find(frameNum); 00202 00203 if(frameIt != itsKeyFrames.end()) 00204 { 00205 //Create some actions if the active frame is a keyframe 00206 00207 FrameState state = frameIt.value(); 00208 00209 //Allow the user to make the current keyframe visible or invisible 00210 if(state.visible == true) 00211 { 00212 makeInvisible = new QAction(tr("Make &Invisible"), this); 00213 menu.addAction(makeInvisible); 00214 } 00215 else if(state.visible == false) 00216 { 00217 makeVisible = new QAction(tr("Make &Visible"), this); 00218 menu.addAction(makeVisible); 00219 } 00220 00221 //Allow the user to delete the current keyframe 00222 removeKeyframe = new QAction(tr("&Delete Keyframe"), this); 00223 menu.addAction(removeKeyframe); 00224 } 00225 else 00226 { 00227 //If the active frame is not a keyframe, allow the user to make it one 00228 createKeyframe = new QAction(tr("&Create Keyframe"), this); 00229 menu.addAction(createKeyframe); 00230 } 00231 00232 //Show the menu and retrieve the selected action 00233 QAction* menuAction = menu.exec(pos); 00234 00235 if(menuAction != NULL) 00236 { 00237 //Perform the requested action 00238 00239 if(menuAction == createKeyframe) 00240 { 00241 FrameState newState = getFrameState(frameNum); 00242 newState.visible = true; 00243 newState.is_keyframe = true; 00244 itsKeyFrames[frameNum] = newState; 00245 emit(animationChanged()); 00246 } 00247 else if(menuAction == removeKeyframe) 00248 { 00249 itsKeyFrames.erase(frameIt); 00250 emit(animationChanged()); 00251 } 00252 else if(menuAction == makeVisible) 00253 { 00254 frameIt->visible = true; 00255 emit(animationChanged()); 00256 } 00257 else if(menuAction == makeInvisible) 00258 { 00259 frameIt->visible = false; 00260 emit(animationChanged()); 00261 } 00262 } 00263 00264 //Clean up the menu items 00265 if(createKeyframe != NULL) delete createKeyframe; 00266 if(removeKeyframe != NULL) delete removeKeyframe; 00267 if(makeVisible != NULL) delete makeVisible; 00268 if(makeInvisible != NULL) delete makeInvisible; 00269 } 00270 00271 void ObjectAnimation::clear() 00272 { 00273 itsKeyFrames.clear(); 00274 emit(animationChanged()); 00275 } 00276 00277 #endif //OBJECTANIMATION_QT_C