Code in blue is to be added to each specific file.


camera.h

class Camera {
    ...
     
    //---[ Save/Load Kerframes ]------------------------------
    bool saveKeyframes(const char* szFileName) const;
    bool loadKeyframes(const char* szFileName);
    float keyframeTime(int keyframe) const;
};

camera.cpp

#include <windows.h>
#include <Fl/gl.h>
#include <gl/glu.h>
#include <fstream>

...
  
bool Camera::saveKeyframes(const char* szFileName) const
{
    std::ofstream ofsFile;
    ofsFile.open(szFileName, std::ios::out);
    if (!ofsFile.fail()) {
        ofsFile << mNumKeyframes << std::endl;
        ofsFile << NUM_KEY_CURVES << std::endl;
if (mKeyframes[0])
for (int i = 0; i < NUM_KEY_CURVES; ++i) {
mKeyframes[i]->toStream(ofsFile);
}
return true;
} return false;
}

bool Camera::loadKeyframes(const char* szFileName)
{
std::ifstream ifsFile;
ifsFile.open(szFileName, std::ios::in);
if (!ifsFile.fail()) {
int iCurveCount;
int iNumKeyframes; ifsFile >> iNumKeyframes;
if (iNumKeyframes <= 0)
return false;
mNumKeyframes = iNumKeyframes; ifsFile >> iCurveCount; if (iCurveCount != NUM_KEY_CURVES) { return false; } deleteCurves(); createCurves(0.0f, 1.0f); for (int i = 0; i < iCurveCount; ++i) {
mKeyframes[i]->fromStream(ifsFile); } return true;
} return false;
} float Camera::keyframeTime(int keyframe) const
{
if (mKeyframes[0]) {
Point ptCtrlPt;
mKeyframes[0]->getControlPoint(keyframe, ptCtrlPt);
return ptCtrlPt.x;
}
return 0.0f;
}

modelerui.cpp

inline void ModelerUI::cb_openAniScript_i(Fl_Menu_*, void*)
{
    char *szFileName = fl_file_chooser("Open Animation Script", "*.ani", NULL);
    if (szFileName) {
        if (m_pwndGraphWidget->loadScript(szFileName)) {
            endTime(m_pwndGraphWidget->endTime());
            activeCurvesChanged();
            // load the camera keyframes
            string strCamKeyframeFileName = szFileName;
            strCamKeyframeFileName += ".cam";
            m_pwndModelerView->m_curve_camera->loadKeyframes(strCamKeyframeFileName.c_str());
            // synchronize the indicator window with the loaded keyframes
            m_pwndIndicatorWnd->clearIndicators();
for (int ikf = 0; ikf < m_pwndModelerView->m_curve_camera->numKeyframes(); ++ikf) m_pwndIndicatorWnd->addIndicator(m_pwndModelerView->m_curve_camera->keyframeTime(ikf));
} else { fl_alert("Sorry! I can't load the animation script!"); } } } ... inline void ModelerUI::cb_saveAniScript_i(Fl_Menu_*, void*) { char *szFileName = fl_file_chooser("Save Animation Script As", "*.ani", NULL); if (szFileName) { string strFileName = szFileName; // Append the default extension char szExt[_MAX_EXT]; _splitpath(strFileName.c_str(), NULL, NULL, NULL, szExt); if (strlen(szExt) == 0) strFileName += ".ani"; if (m_pwndGraphWidget->saveScript(strFileName.c_str())) { // save the camera keyframes string strCamKeyframeFileName = strFileName + ".cam"; m_pwndModelerView->m_curve_camera->saveKeyframes(strCamKeyframeFileName.c_str()); } else { fl_alert("Sorry! I can't save the animation script!"); } } }