forked from mia/Aegisub
Make VideoContext use events for some of its communication with other objects
Originally committed to SVN as r4900.
This commit is contained in:
parent
13f052317e
commit
d9006b0eb4
12 changed files with 132 additions and 184 deletions
|
@ -58,7 +58,6 @@
|
||||||
#include "fft.h"
|
#include "fft.h"
|
||||||
#include "hotkeys.h"
|
#include "hotkeys.h"
|
||||||
#include "include/aegisub/audio_player.h"
|
#include "include/aegisub/audio_player.h"
|
||||||
#include "include/aegisub/audio_provider.h"
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "standard_paths.h"
|
#include "standard_paths.h"
|
||||||
#include "subs_edit_box.h"
|
#include "subs_edit_box.h"
|
||||||
|
@ -123,6 +122,11 @@ AudioDisplay::AudioDisplay(wxWindow *parent)
|
||||||
h -= OPT_GET("Audio/Display/Draw/Timeline")->GetBool() ? 20 : 0;
|
h -= OPT_GET("Audio/Display/Draw/Timeline")->GetBool() ? 20 : 0;
|
||||||
SetSamplesPercent(50,false);
|
SetSamplesPercent(50,false);
|
||||||
|
|
||||||
|
VideoContext *vc = VideoContext::Get();
|
||||||
|
vc->AddKeyframesOpenListener(&AudioDisplay::Update, this);
|
||||||
|
if (OPT_GET("Audio/Display/Draw/Video Position")->GetBool())
|
||||||
|
vc->AddSeekListener(&AudioDisplay::UpdateImage, this, false);
|
||||||
|
|
||||||
// Set cursor
|
// Set cursor
|
||||||
//wxCursor cursor(wxCURSOR_BLANK);
|
//wxCursor cursor(wxCURSOR_BLANK);
|
||||||
//SetCursor(cursor);
|
//SetCursor(cursor);
|
||||||
|
@ -2221,4 +2225,3 @@ void AudioDisplay::UpdateTimeEditCtrls() {
|
||||||
grid->editBox->EndTime->SetTime(curEndMS);
|
grid->editBox->EndTime->SetTime(curEndMS);
|
||||||
grid->editBox->Duration->SetTime(curEndMS-curStartMS);
|
grid->editBox->Duration->SetTime(curEndMS-curStartMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -852,7 +852,6 @@ void FrameMain::SetDisplayMode(int video, int audio) {
|
||||||
MainSizer->RecalcSizes();
|
MainSizer->RecalcSizes();
|
||||||
MainSizer->Layout();
|
MainSizer->Layout();
|
||||||
Layout();
|
Layout();
|
||||||
if (showVideo) VideoContext::Get()->UpdateDisplays(true);
|
|
||||||
|
|
||||||
if (didFreeze) Thaw();
|
if (didFreeze) Thaw();
|
||||||
}
|
}
|
||||||
|
@ -1012,7 +1011,7 @@ void FrameMain::SynchronizeProject(bool fromSubs) {
|
||||||
wxString ar = _T("0");
|
wxString ar = _T("0");
|
||||||
wxString zoom = _T("6");
|
wxString zoom = _T("6");
|
||||||
if (VideoContext::Get()->IsLoaded()) {
|
if (VideoContext::Get()->IsLoaded()) {
|
||||||
seekpos = wxString::Format(_T("%i"),videoBox->videoDisplay->GetFrame());
|
seekpos = wxString::Format(_T("%i"),VideoContext::Get()->GetFrameN());
|
||||||
zoom = wxString::Format(_T("%f"),videoBox->videoDisplay->GetZoom());
|
zoom = wxString::Format(_T("%f"),videoBox->videoDisplay->GetZoom());
|
||||||
|
|
||||||
int arType = VideoContext::Get()->GetAspectRatioType();
|
int arType = VideoContext::Get()->GetAspectRatioType();
|
||||||
|
@ -1176,7 +1175,6 @@ void FrameMain::DetachVideo(bool detach) {
|
||||||
if (!detachedVideo) {
|
if (!detachedVideo) {
|
||||||
detachedVideo = new DialogDetachedVideo(this, videoBox->videoDisplay->GetClientSize());
|
detachedVideo = new DialogDetachedVideo(this, videoBox->videoDisplay->GetClientSize());
|
||||||
detachedVideo->Show();
|
detachedVideo->Show();
|
||||||
VideoContext::Get()->UpdateDisplays(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (detachedVideo) {
|
else if (detachedVideo) {
|
||||||
|
|
|
@ -535,18 +535,13 @@ void FrameMain::OnOpenRecentTimecodes(wxCommandEvent &event) {
|
||||||
/// @brief Open recent Keyframes entry
|
/// @brief Open recent Keyframes entry
|
||||||
/// @param event
|
/// @param event
|
||||||
void FrameMain::OnOpenRecentKeyframes(wxCommandEvent &event) {
|
void FrameMain::OnOpenRecentKeyframes(wxCommandEvent &event) {
|
||||||
int number = event.GetId()-Menu_Keyframes_Recent;
|
VideoContext::Get()->LoadKeyframes(lagi_wxString(config::mru->GetEntry("Keyframes", event.GetId()-Menu_Keyframes_Recent)));
|
||||||
VideoContext::Get()->LoadKeyframes(lagi_wxString(config::mru->GetEntry("Keyframes", number)));
|
|
||||||
videoBox->videoSlider->Refresh();
|
|
||||||
audioBox->audioDisplay->Update();
|
|
||||||
Refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Open recent audio menu entry
|
/// @brief Open recent audio menu entry
|
||||||
/// @param event
|
/// @param event
|
||||||
void FrameMain::OnOpenRecentAudio(wxCommandEvent &event) {
|
void FrameMain::OnOpenRecentAudio(wxCommandEvent &event) {
|
||||||
int number = event.GetId()-Menu_Audio_Recent;
|
LoadAudio(lagi_wxString(config::mru->GetEntry("Audio", event.GetId()-Menu_Audio_Recent)));
|
||||||
LoadAudio(lagi_wxString(config::mru->GetEntry("Audio", number)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Open new Window
|
/// @brief Open new Window
|
||||||
|
@ -813,17 +808,11 @@ void FrameMain::OnOpenKeyframes (wxCommandEvent &) {
|
||||||
|
|
||||||
// Load
|
// Load
|
||||||
VideoContext::Get()->LoadKeyframes(filename);
|
VideoContext::Get()->LoadKeyframes(filename);
|
||||||
videoBox->videoSlider->Refresh();
|
|
||||||
audioBox->audioDisplay->Update();
|
|
||||||
Refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Close keyframes
|
/// @brief Close keyframes
|
||||||
void FrameMain::OnCloseKeyframes (wxCommandEvent &) {
|
void FrameMain::OnCloseKeyframes (wxCommandEvent &) {
|
||||||
VideoContext::Get()->CloseKeyframes();
|
VideoContext::Get()->CloseKeyframes();
|
||||||
videoBox->videoSlider->Refresh();
|
|
||||||
audioBox->audioDisplay->Update();
|
|
||||||
Refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Save keyframes
|
/// @brief Save keyframes
|
||||||
|
|
|
@ -62,7 +62,6 @@
|
||||||
#include "subs_grid.h"
|
#include "subs_grid.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "video_context.h"
|
#include "video_context.h"
|
||||||
#include "video_display.h"
|
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(SubtitlesGrid, BaseGrid)
|
BEGIN_EVENT_TABLE(SubtitlesGrid, BaseGrid)
|
||||||
EVT_KEY_DOWN(SubtitlesGrid::OnKeyDown)
|
EVT_KEY_DOWN(SubtitlesGrid::OnKeyDown)
|
||||||
|
@ -107,6 +106,11 @@ SubtitlesGrid::SubtitlesGrid(FrameMain* parentFr, wxWindow *parent, wxWindowID i
|
||||||
byFrame = false;
|
byFrame = false;
|
||||||
editBox = NULL;
|
editBox = NULL;
|
||||||
parentFrame = parentFr;
|
parentFrame = parentFr;
|
||||||
|
|
||||||
|
seekListener = VideoContext::Get()->AddSeekListener(&SubtitlesGrid::Refresh, this, false, (const wxRect *)NULL);
|
||||||
|
|
||||||
|
OnHighlightVisibleChange(*OPT_GET("Subtitle/Grid/Highlight Subtitles in Frame"));
|
||||||
|
OPT_SUB("Subtitle/Grid/Highlight Subtitles in Frame", &SubtitlesGrid::OnHighlightVisibleChange, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
|
@ -1273,3 +1277,12 @@ void SubtitlesGrid::SetSelectionFromAbsolute(std::vector<int> &selection) {
|
||||||
|
|
||||||
SetSelectedSet(newsel);
|
SetSelectedSet(newsel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SubtitlesGrid::OnHighlightVisibleChange(agi::OptionValue const& opt) {
|
||||||
|
if (opt.GetBool()) {
|
||||||
|
seekListener.Unblock();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
seekListener.Block();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -46,6 +46,10 @@
|
||||||
|
|
||||||
#include "base_grid.h"
|
#include "base_grid.h"
|
||||||
|
|
||||||
|
#include <libaegisub/signals.h>
|
||||||
|
|
||||||
|
namespace agi { class OptionValue; }
|
||||||
|
|
||||||
class AssFile;
|
class AssFile;
|
||||||
class AssEntry;
|
class AssEntry;
|
||||||
class AssDialogue;
|
class AssDialogue;
|
||||||
|
@ -61,6 +65,8 @@ typedef std::list<AssEntry*>::iterator entryIter;
|
||||||
/// DOCME
|
/// DOCME
|
||||||
class SubtitlesGrid: public BaseGrid {
|
class SubtitlesGrid: public BaseGrid {
|
||||||
private:
|
private:
|
||||||
|
agi::signal::Connection seekListener;
|
||||||
|
|
||||||
void OnPopupMenu(bool alternate=false);
|
void OnPopupMenu(bool alternate=false);
|
||||||
void OnKeyDown(wxKeyEvent &event);
|
void OnKeyDown(wxKeyEvent &event);
|
||||||
|
|
||||||
|
@ -89,6 +95,8 @@ private:
|
||||||
void OnAudioClip(wxCommandEvent &event);
|
void OnAudioClip(wxCommandEvent &event);
|
||||||
void OnShowColMenu(wxCommandEvent &event);
|
void OnShowColMenu(wxCommandEvent &event);
|
||||||
|
|
||||||
|
void OnHighlightVisibleChange(agi::OptionValue const& opt);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Currently open file
|
/// Currently open file
|
||||||
AssFile *ass;
|
AssFile *ass;
|
||||||
|
|
|
@ -113,7 +113,6 @@ VideoBox::VideoBox(wxWindow *parent, bool isDetached, wxComboBox *zoomBox)
|
||||||
|
|
||||||
// Display
|
// Display
|
||||||
videoDisplay = new VideoDisplay(this,videoSlider,VideoPosition,VideoSubsPos,zoomBox,videoPage,-1,wxDefaultPosition,wxDefaultSize,wxSUNKEN_BORDER);
|
videoDisplay = new VideoDisplay(this,videoSlider,VideoPosition,VideoSubsPos,zoomBox,videoPage,-1,wxDefaultPosition,wxDefaultSize,wxSUNKEN_BORDER);
|
||||||
VideoContext::Get()->AddDisplay(videoDisplay);
|
|
||||||
|
|
||||||
// Set display
|
// Set display
|
||||||
videoSlider->Display = videoDisplay;
|
videoSlider->Display = videoDisplay;
|
||||||
|
|
|
@ -207,7 +207,8 @@ void VideoContext::SetVideo(const wxString &filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
provider->LoadSubtitles(grid->ass);
|
provider->LoadSubtitles(grid->ass);
|
||||||
UpdateDisplays(true);
|
VideoOpen();
|
||||||
|
KeyframesOpen(keyFrames);
|
||||||
}
|
}
|
||||||
catch (agi::UserCancelException const&) { }
|
catch (agi::UserCancelException const&) { }
|
||||||
catch (agi::FileNotAccessibleError const& err) {
|
catch (agi::FileNotAccessibleError const& err) {
|
||||||
|
@ -227,47 +228,11 @@ void VideoContext::Reload() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoContext::AddDisplay(VideoDisplay *display) {
|
|
||||||
if (std::find(displayList.begin(), displayList.end(), display) == displayList.end())
|
|
||||||
displayList.push_back(display);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoContext::RemoveDisplay(VideoDisplay *display) {
|
|
||||||
displayList.remove(display);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoContext::UpdateDisplays(bool full, bool seek) {
|
|
||||||
if (!IsLoaded()) return;
|
|
||||||
|
|
||||||
for (std::list<VideoDisplay*>::iterator cur=displayList.begin();cur!=displayList.end();cur++) {
|
|
||||||
VideoDisplay *display = *cur;
|
|
||||||
|
|
||||||
if (!seek) {
|
|
||||||
display->Refresh();
|
|
||||||
}
|
|
||||||
if (full) {
|
|
||||||
display->UpdateSize();
|
|
||||||
display->SetFrameRange(0,GetLength()-1);
|
|
||||||
}
|
|
||||||
if (seek || full) {
|
|
||||||
display->SetFrame(GetFrameN());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update audio display
|
|
||||||
if (audio && audio->loaded && audio->IsShownOnScreen()) {
|
|
||||||
static const agi::OptionValue* opt = OPT_GET("Audio/Display/Draw/Video Position");
|
|
||||||
if (opt->GetBool()) {
|
|
||||||
audio->UpdateImage(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoContext::Refresh() {
|
void VideoContext::Refresh() {
|
||||||
if (!IsLoaded()) return;
|
if (!IsLoaded()) return;
|
||||||
|
|
||||||
provider->LoadSubtitles(grid->ass);
|
provider->LoadSubtitles(grid->ass);
|
||||||
UpdateDisplays(false);
|
SubtitlesChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoContext::JumpToFrame(int n) {
|
void VideoContext::JumpToFrame(int n) {
|
||||||
|
@ -278,10 +243,7 @@ void VideoContext::JumpToFrame(int n) {
|
||||||
|
|
||||||
frame_n = n;
|
frame_n = n;
|
||||||
|
|
||||||
UpdateDisplays(false, true);
|
Seek(n);
|
||||||
|
|
||||||
static const agi::OptionValue* highlight = OPT_GET("Subtitle/Grid/Highlight Subtitles in Frame");
|
|
||||||
if (!isPlaying && highlight->GetBool()) grid->Refresh(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoContext::JumpToTime(int ms, agi::vfr::Time end) {
|
void VideoContext::JumpToTime(int ms, agi::vfr::Time end) {
|
||||||
|
@ -481,12 +443,9 @@ double VideoContext::GetARFromType(int type) const {
|
||||||
|
|
||||||
void VideoContext::SetAspectRatio(int type, double value) {
|
void VideoContext::SetAspectRatio(int type, double value) {
|
||||||
if (type != 4) value = GetARFromType(type);
|
if (type != 4) value = GetARFromType(type);
|
||||||
if (value < 0.5) value = 0.5;
|
|
||||||
if (value > 5.0) value = 5.0;
|
|
||||||
|
|
||||||
arType = type;
|
arType = type;
|
||||||
arValue = value;
|
arValue = MID(.5, value, 5.);
|
||||||
UpdateDisplays(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoContext::LoadKeyframes(wxString filename) {
|
void VideoContext::LoadKeyframes(wxString filename) {
|
||||||
|
@ -494,7 +453,7 @@ void VideoContext::LoadKeyframes(wxString filename) {
|
||||||
try {
|
try {
|
||||||
keyFrames = KeyFrameFile::Load(filename);
|
keyFrames = KeyFrameFile::Load(filename);
|
||||||
keyFramesFilename = filename;
|
keyFramesFilename = filename;
|
||||||
Refresh();
|
KeyframesOpen(keyFrames);
|
||||||
}
|
}
|
||||||
catch (const wchar_t *error) {
|
catch (const wchar_t *error) {
|
||||||
wxMessageBox(error, _T("Error opening keyframes file"), wxOK | wxICON_ERROR, NULL);
|
wxMessageBox(error, _T("Error opening keyframes file"), wxOK | wxICON_ERROR, NULL);
|
||||||
|
@ -520,7 +479,7 @@ void VideoContext::CloseKeyframes() {
|
||||||
else {
|
else {
|
||||||
keyFrames.clear();
|
keyFrames.clear();
|
||||||
}
|
}
|
||||||
Refresh();
|
KeyframesOpen(keyFrames);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoContext::LoadTimecodes(wxString filename) {
|
void VideoContext::LoadTimecodes(wxString filename) {
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
#error "Aegisub requires wxWidgets to be compiled with OpenGL support."
|
#error "Aegisub requires wxWidgets to be compiled with OpenGL support."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <libaegisub/signals.h>
|
||||||
#include <libaegisub/vfr.h>
|
#include <libaegisub/vfr.h>
|
||||||
|
|
||||||
class AegiVideoFrame;
|
class AegiVideoFrame;
|
||||||
|
@ -76,6 +77,17 @@ class VideoContext : public wxEvtHandler {
|
||||||
friend class AudioProvider;
|
friend class AudioProvider;
|
||||||
friend class KeyFrameFile;
|
friend class KeyFrameFile;
|
||||||
|
|
||||||
|
/// Current frame number changed
|
||||||
|
agi::signal::Signal<int> Seek;
|
||||||
|
/// A new video was opened
|
||||||
|
agi::signal::Signal<> VideoOpen;
|
||||||
|
/// Subtitles file changed
|
||||||
|
/// @todo Move this to AssFile
|
||||||
|
agi::signal::Signal<> SubtitlesChange;
|
||||||
|
/// New keyframes opened
|
||||||
|
agi::signal::Signal<std::vector<int> const&> KeyframesOpen;
|
||||||
|
|
||||||
|
private:
|
||||||
/// DOCME
|
/// DOCME
|
||||||
std::list<VideoDisplay*> displayList;
|
std::list<VideoDisplay*> displayList;
|
||||||
|
|
||||||
|
@ -165,10 +177,6 @@ public:
|
||||||
VideoContext();
|
VideoContext();
|
||||||
~VideoContext();
|
~VideoContext();
|
||||||
|
|
||||||
void AddDisplay(VideoDisplay *display);
|
|
||||||
void RemoveDisplay(VideoDisplay *display);
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get the video provider used for the currently open video
|
/// @brief Get the video provider used for the currently open video
|
||||||
VideoProvider *GetProvider() const { return videoProvider.get(); }
|
VideoProvider *GetProvider() const { return videoProvider.get(); }
|
||||||
std::tr1::shared_ptr<AegiVideoFrame> GetFrame(int n, bool raw = false);
|
std::tr1::shared_ptr<AegiVideoFrame> GetFrame(int n, bool raw = false);
|
||||||
|
@ -234,11 +242,6 @@ public:
|
||||||
/// @brief Refresh the subtitle provider
|
/// @brief Refresh the subtitle provider
|
||||||
void Refresh();
|
void Refresh();
|
||||||
|
|
||||||
/// @brief Update the video display
|
|
||||||
/// @param full Recalculate size and slider lengths
|
|
||||||
/// @param seek Update is just a seek and file has not changed
|
|
||||||
void UpdateDisplays(bool full, bool seek = false);
|
|
||||||
|
|
||||||
/// @brief Get the height and width of the current script
|
/// @brief Get the height and width of the current script
|
||||||
/// @param[out] w Width
|
/// @param[out] w Width
|
||||||
/// @param[out] h Height
|
/// @param[out] h Height
|
||||||
|
@ -257,6 +260,11 @@ public:
|
||||||
/// Stop playing
|
/// Stop playing
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
|
DEFINE_SIGNAL_ADDERS(Seek, AddSeekListener)
|
||||||
|
DEFINE_SIGNAL_ADDERS(VideoOpen, AddVideoOpenListener)
|
||||||
|
DEFINE_SIGNAL_ADDERS(KeyframesOpen, AddKeyframesOpenListener)
|
||||||
|
DEFINE_SIGNAL_ADDERS(SubtitlesChange, AddSubtitlesChangeListener)
|
||||||
|
|
||||||
const std::vector<int>& GetKeyFrames() const { return keyFrames; };
|
const std::vector<int>& GetKeyFrames() const { return keyFrames; };
|
||||||
wxString GetKeyFramesName() const { return keyFramesFilename; }
|
wxString GetKeyFramesName() const { return keyFramesFilename; }
|
||||||
void LoadKeyframes(wxString filename);
|
void LoadKeyframes(wxString filename);
|
||||||
|
|
|
@ -97,6 +97,7 @@ BEGIN_EVENT_TABLE(VideoDisplay, wxGLCanvas)
|
||||||
EVT_PAINT(VideoDisplay::OnPaint)
|
EVT_PAINT(VideoDisplay::OnPaint)
|
||||||
EVT_SIZE(VideoDisplay::OnSizeEvent)
|
EVT_SIZE(VideoDisplay::OnSizeEvent)
|
||||||
EVT_ERASE_BACKGROUND(VideoDisplay::OnEraseBackground)
|
EVT_ERASE_BACKGROUND(VideoDisplay::OnEraseBackground)
|
||||||
|
EVT_SHOW(VideoDisplay::OnShow)
|
||||||
|
|
||||||
EVT_MENU(VIDEO_MENU_COPY_COORDS,VideoDisplay::OnCopyCoords)
|
EVT_MENU(VIDEO_MENU_COPY_COORDS,VideoDisplay::OnCopyCoords)
|
||||||
EVT_MENU(VIDEO_MENU_COPY_TO_CLIPBOARD,VideoDisplay::OnCopyToClipboard)
|
EVT_MENU(VIDEO_MENU_COPY_TO_CLIPBOARD,VideoDisplay::OnCopyToClipboard)
|
||||||
|
@ -110,7 +111,7 @@ int attribList[] = { WX_GL_RGBA , WX_GL_DOUBLEBUFFER, WX_GL_STENCIL_SIZE, 8, 0 }
|
||||||
|
|
||||||
/// @class VideoOutRenderException
|
/// @class VideoOutRenderException
|
||||||
/// @extends VideoOutException
|
/// @extends VideoOutException
|
||||||
/// @brief An OpenGL error occured while uploading or displaying a frame
|
/// @brief An OpenGL error occurred while uploading or displaying a frame
|
||||||
class OpenGlException : public agi::Exception {
|
class OpenGlException : public agi::Exception {
|
||||||
public:
|
public:
|
||||||
OpenGlException(const wxChar *func, int err)
|
OpenGlException(const wxChar *func, int err)
|
||||||
|
@ -155,13 +156,18 @@ VideoDisplay::VideoDisplay(
|
||||||
{
|
{
|
||||||
if (zoomBox) zoomBox->SetValue(wxString::Format("%g%%", zoomValue * 100.));
|
if (zoomBox) zoomBox->SetValue(wxString::Format("%g%%", zoomValue * 100.));
|
||||||
box->Bind(wxEVT_COMMAND_TOOL_CLICKED, &VideoDisplay::OnMode, this, Video_Mode_Standard, Video_Mode_Vector_Clip);
|
box->Bind(wxEVT_COMMAND_TOOL_CLICKED, &VideoDisplay::OnMode, this, Video_Mode_Standard, Video_Mode_Vector_Clip);
|
||||||
VideoContext::Get()->Bind(EVT_FRAME_READY, &VideoDisplay::UploadFrameData, this);
|
|
||||||
|
VideoContext *vc = VideoContext::Get();
|
||||||
|
vc->Bind(EVT_FRAME_READY, &VideoDisplay::UploadFrameData, this);
|
||||||
|
slots.push_back(vc->AddSeekListener(&VideoDisplay::SetFrame, this));
|
||||||
|
slots.push_back(vc->AddVideoOpenListener(&VideoDisplay::OnVideoOpen, this));
|
||||||
|
slots.push_back(vc->AddSubtitlesChangeListener(&VideoDisplay::Refresh, this));
|
||||||
|
|
||||||
SetCursor(wxNullCursor);
|
SetCursor(wxNullCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoDisplay::~VideoDisplay () {
|
VideoDisplay::~VideoDisplay () {
|
||||||
VideoContext::Get()->Unbind(EVT_FRAME_READY, &VideoDisplay::UploadFrameData, this);
|
VideoContext::Get()->Unbind(EVT_FRAME_READY, &VideoDisplay::UploadFrameData, this);
|
||||||
VideoContext::Get()->RemoveDisplay(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VideoDisplay::InitContext() {
|
bool VideoDisplay::InitContext() {
|
||||||
|
@ -205,7 +211,6 @@ void VideoDisplay::UpdateRelativeTimes(int time) {
|
||||||
|
|
||||||
void VideoDisplay::SetFrame(int frameNumber) {
|
void VideoDisplay::SetFrame(int frameNumber) {
|
||||||
VideoContext *context = VideoContext::Get();
|
VideoContext *context = VideoContext::Get();
|
||||||
ControlSlider->SetValue(frameNumber);
|
|
||||||
|
|
||||||
currentFrame = frameNumber;
|
currentFrame = frameNumber;
|
||||||
|
|
||||||
|
@ -270,8 +275,9 @@ void VideoDisplay::Refresh() {
|
||||||
UpdateRelativeTimes(VideoContext::Get()->TimeAtFrame(currentFrame, agi::vfr::EXACT));
|
UpdateRelativeTimes(VideoContext::Get()->TimeAtFrame(currentFrame, agi::vfr::EXACT));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoDisplay::SetFrameRange(int from, int to) {
|
void VideoDisplay::OnVideoOpen() {
|
||||||
ControlSlider->SetRange(from, to);
|
UpdateSize();
|
||||||
|
Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoDisplay::Render() try {
|
void VideoDisplay::Render() try {
|
||||||
|
@ -548,6 +554,10 @@ double VideoDisplay::GetZoom() const {
|
||||||
return zoomValue;
|
return zoomValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoDisplay::OnShow(wxShowEvent&) {
|
||||||
|
OnVideoOpen();
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void VideoDisplay::SetTool() {
|
void VideoDisplay::SetTool() {
|
||||||
tool.reset();
|
tool.reset();
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <libaegisub/signals.h>
|
||||||
|
|
||||||
// Prototypes
|
// Prototypes
|
||||||
class FrameReadyEvent;
|
class FrameReadyEvent;
|
||||||
class VideoSlider;
|
class VideoSlider;
|
||||||
|
@ -64,6 +66,9 @@ struct VideoState {
|
||||||
/// @class VideoDisplay
|
/// @class VideoDisplay
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
class VideoDisplay : public wxGLCanvas {
|
class VideoDisplay : public wxGLCanvas {
|
||||||
|
/// Signals the display is connected to
|
||||||
|
std::list<agi::signal::Connection> slots;
|
||||||
|
|
||||||
const agi::OptionValue* alwaysShowTools;
|
const agi::OptionValue* alwaysShowTools;
|
||||||
/// The unscaled size of the displayed video
|
/// The unscaled size of the displayed video
|
||||||
wxSize origSize;
|
wxSize origSize;
|
||||||
|
@ -159,6 +164,15 @@ class VideoDisplay : public wxGLCanvas {
|
||||||
/// @param time Currently displayed frame's time
|
/// @param time Currently displayed frame's time
|
||||||
void UpdateRelativeTimes(int time);
|
void UpdateRelativeTimes(int time);
|
||||||
|
|
||||||
|
/// @brief Set this video display to the given frame
|
||||||
|
/// @frameNumber The desired frame number
|
||||||
|
void SetFrame(int frameNumber);
|
||||||
|
/// @brief Signal that the file has changed
|
||||||
|
void Refresh();
|
||||||
|
void OnVideoOpen();
|
||||||
|
|
||||||
|
void OnShow(wxShowEvent &event);
|
||||||
|
|
||||||
|
|
||||||
void OnMode(const wxCommandEvent &event);
|
void OnMode(const wxCommandEvent &event);
|
||||||
void SetMode(int mode);
|
void SetMode(int mode);
|
||||||
|
@ -206,18 +220,6 @@ public:
|
||||||
/// @brief Reset the size of the display to the video size
|
/// @brief Reset the size of the display to the video size
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
/// @brief Set this video display to the given frame
|
|
||||||
/// @frameNumber The desired frame number
|
|
||||||
void SetFrame(int frameNumber);
|
|
||||||
/// @brief Get the number of the currently displayed framed
|
|
||||||
int GetFrame() const { return currentFrame; }
|
|
||||||
/// @brief Set the range of valid frame numbers for the slider
|
|
||||||
/// @from Minimum frame number
|
|
||||||
/// @to Maximum frame number; must be >= from or strange things may happen
|
|
||||||
void SetFrameRange(int from, int to);
|
|
||||||
/// @brief Signal that the file has changed
|
|
||||||
void Refresh();
|
|
||||||
|
|
||||||
/// @brief Render the currently visible frame
|
/// @brief Render the currently visible frame
|
||||||
void Render();
|
void Render();
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,6 @@
|
||||||
/// @ingroup custom_control
|
/// @ingroup custom_control
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
////////////
|
|
||||||
// Includes
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
|
@ -66,17 +63,22 @@ VideoSlider::VideoSlider (wxWindow* parent, wxWindowID id)
|
||||||
: wxWindow (parent,id,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS | wxFULL_REPAINT_ON_RESIZE)
|
: wxWindow (parent,id,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS | wxFULL_REPAINT_ON_RESIZE)
|
||||||
{
|
{
|
||||||
val = 0;
|
val = 0;
|
||||||
min = 0;
|
|
||||||
max = 1;
|
max = 1;
|
||||||
Display = NULL;
|
Display = NULL;
|
||||||
SetClientSize(20,25);
|
SetClientSize(20,25);
|
||||||
SetMinSize(wxSize(20, 25));
|
SetMinSize(wxSize(20, 25));
|
||||||
locked = false;
|
locked = false;
|
||||||
SetRange(0,1);
|
|
||||||
OPT_SUB("Video/Slider/Show Keyframes", &wxWindow::Refresh, this, false, (wxRect*)NULL);
|
OPT_SUB("Video/Slider/Show Keyframes", &wxWindow::Refresh, this, false, (wxRect*)NULL);
|
||||||
|
VideoContext *vc = VideoContext::Get();
|
||||||
|
assert(vc);
|
||||||
|
vc->AddSeekListener(&VideoSlider::SetValue, this);
|
||||||
|
vc->AddVideoOpenListener(&VideoSlider::VideoOpened, this);
|
||||||
|
vc->AddKeyframesOpenListener(&VideoSlider::KeyframesChanged, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoSlider::~VideoSlider() {
|
VideoSlider::~VideoSlider() {
|
||||||
|
VideoContext *vc = VideoContext::Get();
|
||||||
|
assert(vc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Set value
|
/// @brief Set value
|
||||||
|
@ -84,29 +86,22 @@ VideoSlider::~VideoSlider() {
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
void VideoSlider::SetValue(int value) {
|
void VideoSlider::SetValue(int value) {
|
||||||
if (locked) return;
|
if (val == value) return;
|
||||||
val = value;
|
val = MID(0, value, max);
|
||||||
if (val < min) val = min;
|
|
||||||
if (val > max) val = max;
|
|
||||||
Refresh(false);
|
Refresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoSlider::VideoOpened() {
|
||||||
|
VideoContext *vc = VideoContext::Get();
|
||||||
/// @brief Set range
|
max = vc->GetLength() - 1;
|
||||||
/// @param from
|
keyframes = vc->GetKeyFrames();
|
||||||
/// @param to
|
Refresh(false);
|
||||||
///
|
|
||||||
void VideoSlider::SetRange(int from,int to) {
|
|
||||||
if (from > to) from = to;
|
|
||||||
locked = false;
|
|
||||||
min = from;
|
|
||||||
max = to;
|
|
||||||
if (val < from) val = from;
|
|
||||||
if (val > to) val = to;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoSlider::KeyframesChanged(std::vector<int> const& newKeyframes) {
|
||||||
|
keyframes = newKeyframes;
|
||||||
|
Refresh(false);
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Get value at X
|
/// @brief Get value at X
|
||||||
/// @param x
|
/// @param x
|
||||||
|
@ -121,7 +116,7 @@ int VideoSlider::GetValueAtX(int x) {
|
||||||
if (w <= 10) return 0;
|
if (w <= 10) return 0;
|
||||||
|
|
||||||
// Calculate
|
// Calculate
|
||||||
return (int64_t)(x-5)*(int64_t)(max-min)/(int64_t)(w-10)+min;
|
return (int64_t)(x-5)*(int64_t)max/(int64_t)(w-10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -136,10 +131,10 @@ int VideoSlider::GetXAtValue(int value) {
|
||||||
GetClientSize(&w,&h);
|
GetClientSize(&w,&h);
|
||||||
|
|
||||||
// Special case
|
// Special case
|
||||||
if (max-min <= 0) return 0;
|
if (max <= 0) return 0;
|
||||||
|
|
||||||
// Calculate
|
// Calculate
|
||||||
return (int64_t)(value-min)*(int64_t)(w-10)/(int64_t)(max-min)+5;
|
return (int64_t)value*(int64_t)(w-10)/(int64_t)max+5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -151,7 +146,7 @@ void VideoSlider::NextFrame() {
|
||||||
if (VideoContext::Get()->IsPlaying()) return;
|
if (VideoContext::Get()->IsPlaying()) return;
|
||||||
|
|
||||||
//don't request out of range frames
|
//don't request out of range frames
|
||||||
if (GetValue() < max) VideoContext::Get()->PlayNextFrame();
|
if (val < max) VideoContext::Get()->PlayNextFrame();
|
||||||
Refresh(false);
|
Refresh(false);
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
@ -165,14 +160,11 @@ void VideoSlider::PrevFrame() {
|
||||||
if (VideoContext::Get()->IsPlaying()) return;
|
if (VideoContext::Get()->IsPlaying()) return;
|
||||||
|
|
||||||
//don't request out of range frames
|
//don't request out of range frames
|
||||||
if (GetValue() > min) VideoContext::Get()->PlayPrevFrame();
|
if (val > 0) VideoContext::Get()->PlayPrevFrame();
|
||||||
Refresh(false);
|
Refresh(false);
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////
|
|
||||||
// Event table
|
|
||||||
BEGIN_EVENT_TABLE(VideoSlider, wxWindow)
|
BEGIN_EVENT_TABLE(VideoSlider, wxWindow)
|
||||||
EVT_MOUSE_EVENTS(VideoSlider::OnMouse)
|
EVT_MOUSE_EVENTS(VideoSlider::OnMouse)
|
||||||
EVT_KEY_DOWN(VideoSlider::OnKeyDown)
|
EVT_KEY_DOWN(VideoSlider::OnKeyDown)
|
||||||
|
@ -182,22 +174,6 @@ BEGIN_EVENT_TABLE(VideoSlider, wxWindow)
|
||||||
EVT_ERASE_BACKGROUND(VideoSlider::OnEraseBackground)
|
EVT_ERASE_BACKGROUND(VideoSlider::OnEraseBackground)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Change position
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
void VideoSlider::UpdateVideo() {
|
|
||||||
if (Display) {
|
|
||||||
if (VideoContext::Get()->IsPlaying()) return;
|
|
||||||
locked = true;
|
|
||||||
VideoContext::Get()->JumpToFrame(GetValue());
|
|
||||||
locked = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Mouse events
|
/// @brief Mouse events
|
||||||
/// @param event
|
/// @param event
|
||||||
/// @return
|
/// @return
|
||||||
|
@ -214,7 +190,7 @@ void VideoSlider::OnMouse(wxMouseEvent &event) {
|
||||||
bool canDrag = wxWindow::FindFocus() == this;
|
bool canDrag = wxWindow::FindFocus() == this;
|
||||||
if (!canDrag) {
|
if (!canDrag) {
|
||||||
int tolerance = 4;
|
int tolerance = 4;
|
||||||
int curX = GetXAtValue(GetValue());
|
int curX = GetXAtValue(val);
|
||||||
if (x-curX < -tolerance || x-curX > tolerance) canDrag = true;
|
if (x-curX < -tolerance || x-curX > tolerance) canDrag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,14 +213,14 @@ void VideoSlider::OnMouse(wxMouseEvent &event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jump to frame
|
// Jump to frame
|
||||||
if (closest == GetValue()) return;
|
if (closest == val) return;
|
||||||
SetValue(closest);
|
SetValue(closest);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normal click
|
// Normal click
|
||||||
else {
|
else {
|
||||||
int go = GetValueAtX(x);
|
int go = GetValueAtX(x);
|
||||||
if (go == GetValue()) return;
|
if (go == val) return;
|
||||||
SetValue(go);
|
SetValue(go);
|
||||||
}
|
}
|
||||||
Refresh(false);
|
Refresh(false);
|
||||||
|
@ -252,10 +228,10 @@ void VideoSlider::OnMouse(wxMouseEvent &event) {
|
||||||
// Playing?
|
// Playing?
|
||||||
if (VideoContext::Get()->IsPlaying()) {
|
if (VideoContext::Get()->IsPlaying()) {
|
||||||
VideoContext::Get()->Stop();
|
VideoContext::Get()->Stop();
|
||||||
UpdateVideo();
|
VideoContext::Get()->JumpToFrame(val);
|
||||||
VideoContext::Get()->Play();
|
VideoContext::Get()->Play();
|
||||||
}
|
}
|
||||||
else UpdateVideo();
|
else VideoContext::Get()->JumpToFrame(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get focus
|
// Get focus
|
||||||
|
@ -307,8 +283,8 @@ void VideoSlider::OnKeyDown(wxKeyEvent &event) {
|
||||||
// Fast move
|
// Fast move
|
||||||
if (!ctrl && !shift && alt) {
|
if (!ctrl && !shift && alt) {
|
||||||
if (VideoContext::Get()->IsPlaying()) return;
|
if (VideoContext::Get()->IsPlaying()) return;
|
||||||
int target = MID(min,GetValue() + direction * OPT_GET("Video/Slider/Fast Jump Step")->GetInt(),max);
|
int target = MID(0,val + direction * OPT_GET("Video/Slider/Fast Jump Step")->GetInt(),max);
|
||||||
if (target != GetValue()) VideoContext::Get()->JumpToFrame(target);
|
if (target != val) VideoContext::Get()->JumpToFrame(target);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,24 +347,20 @@ void VideoSlider::OnKeyDown(wxKeyEvent &event) {
|
||||||
if (direction != 0) {
|
if (direction != 0) {
|
||||||
// Prepare
|
// Prepare
|
||||||
int prevKey = 0;
|
int prevKey = 0;
|
||||||
int nextKey = VideoContext::Get()->GetLength()-1;
|
int nextKey = max;
|
||||||
std::vector<int> KeyFrames = VideoContext::Get()->GetKeyFrames();
|
int keys = keyframes.size();
|
||||||
int keys = KeyFrames.size();
|
|
||||||
int cur = VideoContext::Get()->GetFrameN();
|
|
||||||
int i;
|
|
||||||
int temp;
|
|
||||||
|
|
||||||
// Find previous keyframe
|
// Find previous keyframe
|
||||||
// This algorithm does unnecessary loops, but it ensures it works even if keyframes are out of order.
|
// This algorithm does unnecessary loops, but it ensures it works even if keyframes are out of order.
|
||||||
for (i=0;i<keys;i++) {
|
for (int i=0;i<keys;i++) {
|
||||||
temp = KeyFrames[i];
|
int temp = keyframes[i];
|
||||||
if (temp < cur && temp > prevKey) prevKey = temp;
|
if (temp < val && temp > prevKey) prevKey = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find next keyframe
|
// Find next keyframe
|
||||||
for (i=0;i<keys;i++) {
|
for (int i=0;i<keys;i++) {
|
||||||
temp = KeyFrames[i];
|
int temp = keyframes[i];
|
||||||
if (temp > cur && temp < nextKey) nextKey = KeyFrames[i];
|
if (temp > val && temp < nextKey) nextKey = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (direction == -1) VideoContext::Get()->JumpToFrame(prevKey);
|
if (direction == -1) VideoContext::Get()->JumpToFrame(prevKey);
|
||||||
|
@ -477,16 +449,14 @@ void VideoSlider::DrawImage(wxDC &destdc) {
|
||||||
int curX;
|
int curX;
|
||||||
if (Display && OPT_GET("Video/Slider/Show Keyframes")->GetBool()) {
|
if (Display && OPT_GET("Video/Slider/Show Keyframes")->GetBool()) {
|
||||||
dc.SetPen(wxPen(shad));
|
dc.SetPen(wxPen(shad));
|
||||||
std::vector<int> KeyFrames = VideoContext::Get()->GetKeyFrames();
|
for (size_t i=0;i<keyframes.size();i++) {
|
||||||
int keys = KeyFrames.size();
|
curX = GetXAtValue(keyframes[i]);
|
||||||
for (int i=0;i<keys;i++) {
|
|
||||||
curX = GetXAtValue(KeyFrames[i]);
|
|
||||||
dc.DrawLine(curX,2,curX,8);
|
dc.DrawLine(curX,2,curX,8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw cursor
|
// Draw cursor
|
||||||
curX = GetXAtValue(GetValue());
|
curX = GetXAtValue(val);
|
||||||
|
|
||||||
// Fill bg
|
// Fill bg
|
||||||
dc.SetBrush(wxBrush(face));
|
dc.SetBrush(wxBrush(face));
|
||||||
|
@ -529,8 +499,6 @@ void VideoSlider::DrawImage(wxDC &destdc) {
|
||||||
/// @brief Update image
|
/// @brief Update image
|
||||||
///
|
///
|
||||||
void VideoSlider::UpdateImage () {
|
void VideoSlider::UpdateImage () {
|
||||||
//wxClientDC dc(this);
|
|
||||||
//DrawImage(dc);
|
|
||||||
Refresh(false);
|
Refresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,5 +510,3 @@ void VideoSlider::UpdateImage () {
|
||||||
void VideoSlider::OnFocus(wxFocusEvent &event) {
|
void VideoSlider::OnFocus(wxFocusEvent &event) {
|
||||||
Refresh(false);
|
Refresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -47,11 +47,10 @@ class SubtitlesGrid;
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// DOCME
|
||||||
class VideoSlider: public wxWindow {
|
class VideoSlider: public wxWindow {
|
||||||
/// DOCME
|
std::vector<int> keyframes;
|
||||||
int val;
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
int min;
|
int val;
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
int max;
|
int max;
|
||||||
|
@ -61,22 +60,20 @@ class VideoSlider: public wxWindow {
|
||||||
|
|
||||||
int GetValueAtX(int x);
|
int GetValueAtX(int x);
|
||||||
int GetXAtValue(int value);
|
int GetXAtValue(int value);
|
||||||
void UpdateVideo();
|
|
||||||
void DrawImage(wxDC &dc);
|
void DrawImage(wxDC &dc);
|
||||||
void UpdateImage();
|
void UpdateImage();
|
||||||
|
void SetValue(int value);
|
||||||
|
|
||||||
|
void VideoOpened();
|
||||||
|
void KeyframesChanged(std::vector<int> const& newKeyframes);
|
||||||
|
|
||||||
void OnMouse(wxMouseEvent &event);
|
void OnMouse(wxMouseEvent &event);
|
||||||
void OnKeyDown(wxKeyEvent &event);
|
void OnKeyDown(wxKeyEvent &event);
|
||||||
void OnPaint(wxPaintEvent &event);
|
void OnPaint(wxPaintEvent &event);
|
||||||
void OnFocus(wxFocusEvent &event);
|
void OnFocus(wxFocusEvent &event);
|
||||||
|
|
||||||
/// @brief DOCME
|
|
||||||
/// @param event
|
|
||||||
///
|
|
||||||
void OnEraseBackground(wxEraseEvent &event) {}
|
void OnEraseBackground(wxEraseEvent &event) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
VideoDisplay *Display;
|
VideoDisplay *Display;
|
||||||
|
|
||||||
|
@ -89,9 +86,5 @@ public:
|
||||||
void NextFrame();
|
void NextFrame();
|
||||||
void PrevFrame();
|
void PrevFrame();
|
||||||
|
|
||||||
void SetRange(int start,int end);
|
|
||||||
int GetValue() const { return val; };
|
|
||||||
void SetValue(int value);
|
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue