| |
| |
| #include "toonz/tframehandle.h" |
| #include "toonz/toonzscene.h" |
| #include "toonz/txshsimplelevel.h" |
| #include "toonz/txsheet.h" |
| #include "toonz/txshcell.h" |
| #include "toonz/sceneproperties.h" |
| #include "toutputproperties.h" |
| |
| #include "toonz/txsheethandle.h" |
| |
| |
| |
| namespace { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| bool getCurrentLevelFids(std::vector<TFrameId> &fids) { |
| |
| |
| |
| |
| |
| fids.push_back(TFrameId(1)); |
| return !fids.empty(); |
| } |
| |
| TFrameId getLastLevelFid() { return TFrameId(1); } |
| |
| } |
| |
| |
| |
| |
| |
| TFrameHandle::TFrameHandle() |
| : m_frame(-1) |
| , m_fid() |
| , m_timerId(0) |
| , m_previewFrameRate(25) |
| , m_frameType(SceneFrame) |
| , m_looping(false) |
| , m_isPlaying(false) |
| , m_scrubRange(0, -1) |
| , m_audioColumn(0) |
| , m_xsheet(0) |
| , m_fps(0) |
| , m_frame0(-1) |
| , m_frame1(-1) {} |
| |
| |
| |
| TFrameHandle::~TFrameHandle() {} |
| |
| |
| |
| int TFrameHandle::getFrame() const { return m_frame; } |
| |
| |
| |
| void TFrameHandle::setCurrentFrame(int frame) { |
| if (m_frameType == LevelFrame) { |
| |
| |
| |
| if (m_fids.size() <= 0) return; |
| if (frame - 1 >= (int)m_fids.size()) |
| setFid(m_fids.back()); |
| else |
| setFid(m_fids[frame - 1]); |
| } else |
| setFrame(frame - 1); |
| } |
| |
| |
| |
| void TFrameHandle::setFrame(int frame) { |
| if (m_frame == frame && m_frameType == SceneFrame) return; |
| m_frame = frame; |
| if (m_frameType != SceneFrame) { |
| m_frameType = SceneFrame; |
| emit frameTypeChanged(); |
| } |
| emit frameSwitched(); |
| } |
| |
| |
| |
| TFrameId TFrameHandle::getFid() const { return m_fid; } |
| |
| |
| |
| void TFrameHandle::setFid(const TFrameId &fid) { |
| if (m_fid == fid && m_frameType == LevelFrame) return; |
| m_fid = fid; |
| if (m_frameType != LevelFrame) { |
| m_frameType = LevelFrame; |
| emit frameTypeChanged(); |
| } |
| emit frameSwitched(); |
| } |
| |
| |
| |
| void TFrameHandle::nextFrame() { |
| if (m_frameType == LevelFrame) { |
| |
| |
| if (m_fids.size() <= 0) return; |
| std::vector<TFrameId>::iterator it; |
| it = std::upper_bound(m_fids.begin(), m_fids.end(), m_fid); |
| if (it == m_fids.end()) { |
| |
| |
| |
| |
| TFrameId fid = m_fids.back(); |
| setFid(fid); |
| } else |
| setFid(*it); |
| } else { |
| setFrame(m_frame + 1); |
| } |
| } |
| |
| |
| |
| void TFrameHandle::prevFrame() { |
| if (m_frameType == LevelFrame) { |
| |
| if (m_fids.size() <= 0) return; |
| std::vector<TFrameId>::iterator it; |
| it = std::lower_bound(m_fids.begin(), m_fids.end(), m_fid); |
| |
| if (it != m_fids.end() && it != m_fids.begin()) { |
| --it; |
| setFid(*it); |
| } else { |
| |
| if (!m_fids.empty() && m_fid > m_fids.back()) setFid(m_fids.back()); |
| } |
| } else { |
| if (m_frame > 0) setFrame(m_frame - 1); |
| } |
| } |
| |
| |
| |
| void TFrameHandle::firstFrame() { |
| if (m_frameType == LevelFrame) { |
| |
| if (m_fids.size() <= 0) return; |
| setFid(m_fids.front()); |
| } else { |
| |
| |
| setFrame(m_frame0); |
| } |
| } |
| |
| |
| |
| void TFrameHandle::lastFrame() { |
| if (m_frameType == LevelFrame) { |
| |
| if (m_fids.size() <= 0) return; |
| setFid(m_fids.back()); |
| } else { |
| |
| |
| if (m_frame1 > 0) setFrame(m_frame1); |
| } |
| } |
| |
| |
| |
| void TFrameHandle::setPlaying(bool isPlaying) { |
| if (m_isPlaying == isPlaying) return; |
| m_isPlaying = isPlaying; |
| emit isPlayingStatusChanged(); |
| } |
| |
| |
| #ifdef LEVO |
| |
| void TFrameHandle::startPlaying(bool looping) { |
| if (m_previewFrameRate == 0) return; |
| if (isScrubbing()) stopScrubbing(); |
| setTimer(m_previewFrameRate); |
| m_looping = looping; |
| emit playStarted(); |
| } |
| |
| |
| |
| void TFrameHandle::stopPlaying() { |
| if (m_timerId != 0) killTimer(m_timerId); |
| m_timerId = 0; |
| m_looping = false; |
| emit playStopped(); |
| } |
| |
| |
| #endif |
| |
| void TFrameHandle::setTimer(int frameRate) { |
| m_previewFrameRate = frameRate; |
| if (m_timerId != 0) killTimer(m_timerId); |
| int interval = troundp(1000.0 / double(m_previewFrameRate)); |
| m_timerId = startTimer(interval); |
| } |
| |
| |
| |
| void TFrameHandle::timerEvent(QTimerEvent *event) { |
| assert(isScrubbing()); |
| |
| int elapsedTime = m_clock.elapsed(); |
| int frame = m_scrubRange.first + elapsedTime * m_fps / 1000; |
| int lastFrame = m_scrubRange.second; |
| if (frame >= lastFrame) { |
| if (m_frame != lastFrame) setFrame(lastFrame); |
| stopScrubbing(); |
| } else |
| setFrame(frame); |
| } |
| |
| |
| |
| int TFrameHandle::getMaxFrameIndex() const { |
| if (m_frameType == LevelFrame) { |
| |
| if (m_fids.size() <= 0) |
| return -1; |
| else |
| return m_fids.size() - 1; |
| } else |
| |
| return m_sceneFrameSize - 1; |
| } |
| |
| |
| |
| int TFrameHandle::getFrameIndex() const { |
| if (m_frameType == LevelFrame) { |
| |
| if (m_fids.size() > 0) { |
| std::vector<TFrameId>::const_iterator it = |
| std::find(m_fids.begin(), m_fids.end(), m_fid); |
| if (it != m_fids.end()) |
| return std::distance(m_fids.begin(), it); |
| else { |
| if (m_fid > m_fids.back()) |
| return m_fids.size(); |
| else |
| return -1; |
| } |
| } else |
| return -1; |
| } else |
| return m_frame; |
| } |
| |
| |
| |
| QString TFrameHandle::getFrameIndexName(int index) const { |
| if (m_frameType == LevelFrame) { |
| if (m_fid.getNumber() <= 0) |
| return ""; |
| else { |
| return QString::number(m_fid.getNumber()); |
| } |
| } else |
| return QString::number(m_frame + 1); |
| } |
| |
| void TFrameHandle::setFrameIndex(int index) { |
| if (m_frameType == LevelFrame) { |
| |
| if (m_fids.size() > 0 && 0 <= index && index < (int)m_fids.size()) |
| setFid(m_fids[index]); |
| } else |
| setFrame(index); |
| } |
| |
| void TFrameHandle::setFrameIndexByName(const QString &str) { |
| int num = str.toInt(); |
| if (m_frameType == LevelFrame) { |
| setFid(TFrameId(num)); |
| } else |
| setFrame(num - 1); |
| } |
| |
| void TFrameHandle::scrubColumn(int r0, int r1, TXshSoundColumn *audioColumn, |
| double framePerSecond) { |
| m_audioColumn = audioColumn; |
| if (!scrub(r0, r1, framePerSecond)) m_audioColumn = 0; |
| } |
| |
| void TFrameHandle::scrubXsheet(int r0, int r1, TXsheet *xsheet, |
| double framePerSecond) { |
| m_xsheet = xsheet; |
| if (!scrub(r0, r1, framePerSecond)) m_xsheet = 0; |
| } |
| |
| bool TFrameHandle::scrub(int r0, int r1, double framePerSecond) { |
| if (isPlaying() || isScrubbing()) return false; |
| bool onlyOneFrame = (r0 == r1); |
| |
| if (!isScrubbing() || !onlyOneFrame) emit scrubStarted(); |
| if (!onlyOneFrame) { |
| m_fps = framePerSecond; |
| m_scrubRange = std::make_pair(r0, r1); |
| } |
| setFrame(r0); |
| |
| if (m_audioColumn) |
| m_audioColumn->scrub(r0, r1); |
| else if (m_xsheet) { |
| int i; |
| for (i = r0; i <= r1; i++) m_xsheet->scrub(i); |
| } |
| |
| if (onlyOneFrame) return false; |
| |
| m_clock.start(); |
| m_timerId = startTimer(40); |
| return true; |
| } |
| |
| void TFrameHandle::stopScrubbing() { |
| if (!isScrubbing()) return; |
| if (m_timerId > 0) killTimer(m_timerId); |
| m_timerId = 0; |
| m_scrubRange = std::make_pair(0, -1); |
| if (m_audioColumn) m_audioColumn = 0; |
| if (m_xsheet) m_xsheet = 0; |
| m_fps = 0; |
| emit scrubStopped(); |
| } |
| |