forked from mia/Aegisub
Significantly revamp how visual tools interact with the rest of the program
Rather than just have a single Refresh method that gets called whenever something happens that could possibly be of interest to the visual tools, add seperate methods for signaling frame number changes and changes to the file, and use the new SelectionController stuff for other things that used to merit a Refresh. This eliminates a large amount of redundant reparsing of lines which happened on paint, as well as a large number of redundant repaints. Frame data is now only uploaded to the video card when the frame number changes rather than when anything at all changes, slightly improving performance when using mesa's software opengl implementation. Vector clip and drag tools now do a slightly better job of not discarding the user's selection for no apparent reason, and strange selection behavior from clicking on visual features should now be entirely fixed. Everything but the constructor and toolbar event handler in the visual tool implementations are now private. Originally committed to SVN as r4631.
This commit is contained in:
parent
d30326b20d
commit
5588cda268
20 changed files with 381 additions and 553 deletions
|
@ -229,6 +229,7 @@ void VideoContext::SetVideo(const wxString &filename) {
|
||||||
|
|
||||||
// Choose a provider
|
// Choose a provider
|
||||||
provider = VideoProviderFactoryManager::GetProvider(filename);
|
provider = VideoProviderFactoryManager::GetProvider(filename);
|
||||||
|
loaded = provider != NULL;
|
||||||
|
|
||||||
// Get subtitles provider
|
// Get subtitles provider
|
||||||
try {
|
try {
|
||||||
|
@ -288,14 +289,13 @@ void VideoContext::SetVideo(const wxString &filename) {
|
||||||
hasSubtitles = MatroskaWrapper::HasSubtitles(filename);
|
hasSubtitles = MatroskaWrapper::HasSubtitles(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateDisplays(true);
|
UpdateDisplays(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (wxString &e) {
|
catch (wxString &e) {
|
||||||
wxMessageBox(e,_T("Error setting video"),wxICON_ERROR | wxOK);
|
wxMessageBox(e,_T("Error setting video"),wxICON_ERROR | wxOK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loaded = provider != NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Add new display
|
/// @brief Add new display
|
||||||
|
@ -316,10 +316,7 @@ void VideoContext::RemoveDisplay(VideoDisplay *display) {
|
||||||
displayList.remove(display);
|
displayList.remove(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Update displays
|
void VideoContext::UpdateDisplays(bool full, bool seek) {
|
||||||
/// @param full
|
|
||||||
///
|
|
||||||
void VideoContext::UpdateDisplays(bool full) {
|
|
||||||
if (!loaded) return;
|
if (!loaded) return;
|
||||||
|
|
||||||
for (std::list<VideoDisplay*>::iterator cur=displayList.begin();cur!=displayList.end();cur++) {
|
for (std::list<VideoDisplay*>::iterator cur=displayList.begin();cur!=displayList.end();cur++) {
|
||||||
|
@ -329,8 +326,13 @@ void VideoContext::UpdateDisplays(bool full) {
|
||||||
display->UpdateSize();
|
display->UpdateSize();
|
||||||
display->SetFrameRange(0,GetLength()-1);
|
display->SetFrameRange(0,GetLength()-1);
|
||||||
}
|
}
|
||||||
|
if (seek) {
|
||||||
display->SetFrame(GetFrameN());
|
display->SetFrame(GetFrameN());
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
display->Refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update audio display
|
// Update audio display
|
||||||
if (audio && audio->loaded && audio->IsShownOnScreen()) {
|
if (audio && audio->loaded && audio->IsShownOnScreen()) {
|
||||||
|
@ -361,17 +363,14 @@ void VideoContext::Refresh () {
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
void VideoContext::JumpToFrame(int n) {
|
void VideoContext::JumpToFrame(int n) {
|
||||||
// Loaded?
|
|
||||||
if (!loaded) return;
|
if (!loaded) return;
|
||||||
|
|
||||||
// Prevent intervention during playback
|
// Prevent intervention during playback
|
||||||
if (isPlaying && n != playNextFrame) return;
|
if (isPlaying && n != playNextFrame) return;
|
||||||
|
|
||||||
// Set frame number
|
|
||||||
frame_n = n;
|
frame_n = n;
|
||||||
|
|
||||||
// Display
|
UpdateDisplays(false, true);
|
||||||
UpdateDisplays(false);
|
|
||||||
|
|
||||||
// Update grid
|
// Update grid
|
||||||
static agi::OptionValue* highlight = OPT_GET("Subtitle/Grid/Highlight Subtitles in Frame");
|
static agi::OptionValue* highlight = OPT_GET("Subtitle/Grid/Highlight Subtitles in Frame");
|
||||||
|
|
|
@ -267,7 +267,10 @@ public:
|
||||||
void JumpToTime(int ms,bool exact=false);
|
void JumpToTime(int ms,bool exact=false);
|
||||||
|
|
||||||
void Refresh();
|
void Refresh();
|
||||||
void UpdateDisplays(bool full);
|
/// @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);
|
||||||
|
|
||||||
void GetScriptSize(int &w,int &h);
|
void GetScriptSize(int &w,int &h);
|
||||||
wxString GetTempWorkFile ();
|
wxString GetTempWorkFile ();
|
||||||
|
|
|
@ -203,11 +203,12 @@ void VideoDisplay::SetFrame(int frameNumber) {
|
||||||
// Render the new frame
|
// Render the new frame
|
||||||
if (context->IsLoaded()) {
|
if (context->IsLoaded()) {
|
||||||
context->GetScriptSize(scriptW, scriptH);
|
context->GetScriptSize(scriptW, scriptH);
|
||||||
tool->Refresh();
|
if (!tool.get()) tool.reset(new VisualToolCross(this, video, toolBar));
|
||||||
|
tool->SetFrame(frameNumber);
|
||||||
|
|
||||||
AegiVideoFrame frame;
|
AegiVideoFrame frame;
|
||||||
try {
|
try {
|
||||||
frame = context->GetFrame(frameNumber);
|
frame = context->GetFrame(currentFrame);
|
||||||
}
|
}
|
||||||
catch (const wxChar *err) {
|
catch (const wxChar *err) {
|
||||||
wxLogError(
|
wxLogError(
|
||||||
|
@ -242,6 +243,11 @@ void VideoDisplay::SetFrame(int frameNumber) {
|
||||||
currentFrame = frameNumber;
|
currentFrame = frameNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoDisplay::Refresh() {
|
||||||
|
tool->Refresh();
|
||||||
|
Render();
|
||||||
|
}
|
||||||
|
|
||||||
void VideoDisplay::SetFrameRange(int from, int to) {
|
void VideoDisplay::SetFrameRange(int from, int to) {
|
||||||
ControlSlider->SetRange(from, to);
|
ControlSlider->SetRange(from, to);
|
||||||
}
|
}
|
||||||
|
@ -419,7 +425,7 @@ void VideoDisplay::UpdateSize() {
|
||||||
|
|
||||||
tool->Refresh();
|
tool->Refresh();
|
||||||
|
|
||||||
Refresh(false);
|
wxGLCanvas::Refresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoDisplay::Reset() {
|
void VideoDisplay::Reset() {
|
||||||
|
|
|
@ -148,7 +148,7 @@ class VideoDisplay: public wxGLCanvas {
|
||||||
void OnMode(const wxCommandEvent &event);
|
void OnMode(const wxCommandEvent &event);
|
||||||
void SetMode(int mode);
|
void SetMode(int mode);
|
||||||
/// @brief Switch the active tool to a new object of the specified class
|
/// @brief Switch the active tool to a new object of the specified class
|
||||||
/// @param T The class of the new visual typsetting tool
|
/// @param T The class of the new visual typesetting tool
|
||||||
template <class T> void SetTool();
|
template <class T> void SetTool();
|
||||||
|
|
||||||
/// The current script width
|
/// The current script width
|
||||||
|
@ -189,6 +189,8 @@ public:
|
||||||
/// @from Minimum frame number
|
/// @from Minimum frame number
|
||||||
/// @to Maximum frame number; must be >= from or strange things may happen
|
/// @to Maximum frame number; must be >= from or strange things may happen
|
||||||
void SetFrameRange(int from, int to);
|
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();
|
||||||
|
|
|
@ -75,14 +75,13 @@ VisualTool<FeatureType>::VisualTool(VideoDisplay *parent, VideoState const& vide
|
||||||
, dragStartX(0)
|
, dragStartX(0)
|
||||||
, dragStartY(0)
|
, dragStartY(0)
|
||||||
, selChanged(false)
|
, selChanged(false)
|
||||||
|
, grid(VideoContext::Get()->grid)
|
||||||
, parent(parent)
|
, parent(parent)
|
||||||
, holding(false)
|
, holding(false)
|
||||||
, curDiag(NULL)
|
|
||||||
, dragging(false)
|
, dragging(false)
|
||||||
, externalChange(true)
|
, externalChange(true)
|
||||||
, curFeature(NULL)
|
, curFeature(NULL)
|
||||||
, dragListOK(false)
|
, dragListOK(false)
|
||||||
, frame_n(0)
|
|
||||||
, video(video)
|
, video(video)
|
||||||
, leftClick(false)
|
, leftClick(false)
|
||||||
, leftDClick(false)
|
, leftDClick(false)
|
||||||
|
@ -90,15 +89,14 @@ VisualTool<FeatureType>::VisualTool(VideoDisplay *parent, VideoState const& vide
|
||||||
, ctrlDown(false)
|
, ctrlDown(false)
|
||||||
, altDown(false)
|
, altDown(false)
|
||||||
{
|
{
|
||||||
frame_n = VideoContext::Get()->GetFrameN();
|
frameNumber = VideoContext::Get()->GetFrameN();
|
||||||
|
curDiag = GetActiveDialogueLine();
|
||||||
grid->AddSelectionListener(this);
|
grid->AddSelectionListener(this);
|
||||||
|
|
||||||
PopulateFeatureList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class FeatureType>
|
template<class FeatureType>
|
||||||
VisualTool<FeatureType>::~VisualTool() {
|
VisualTool<FeatureType>::~VisualTool() {
|
||||||
VideoContext::Get()->grid->RemoveSelectionListener(this);
|
grid->RemoveSelectionListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class FeatureType>
|
template<class FeatureType>
|
||||||
|
@ -129,6 +127,7 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
|
||||||
if (!dragListOK) {
|
if (!dragListOK) {
|
||||||
PopulateFeatureList();
|
PopulateFeatureList();
|
||||||
dragListOK = true;
|
dragListOK = true;
|
||||||
|
needRender = true;
|
||||||
}
|
}
|
||||||
if (!dragging) {
|
if (!dragging) {
|
||||||
unsigned oldHigh = curFeatureI;
|
unsigned oldHigh = curFeatureI;
|
||||||
|
@ -159,10 +158,8 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
|
||||||
if (realTime) {
|
if (realTime) {
|
||||||
Commit();
|
Commit();
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
needRender = true;
|
needRender = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// end drag
|
// end drag
|
||||||
else {
|
else {
|
||||||
if (realTime) AssLimitToVisibleFilter::SetFrame(-1);
|
if (realTime) AssLimitToVisibleFilter::SetFrame(-1);
|
||||||
|
@ -178,11 +175,8 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
|
||||||
RemoveSelection(curFeatureI);
|
RemoveSelection(curFeatureI);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// deselect everything else
|
SetSelection(curFeatureI);
|
||||||
ClearSelection();
|
|
||||||
AddSelection(curFeatureI);
|
|
||||||
}
|
}
|
||||||
SetEditbox();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -206,10 +200,8 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
|
||||||
CommitHold();
|
CommitHold();
|
||||||
Commit();
|
Commit();
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
needRender = true;
|
needRender = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// end hold
|
// end hold
|
||||||
else {
|
else {
|
||||||
if (realTime) AssLimitToVisibleFilter::SetFrame(-1);
|
if (realTime) AssLimitToVisibleFilter::SetFrame(-1);
|
||||||
|
@ -218,7 +210,6 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
|
||||||
CommitHold();
|
CommitHold();
|
||||||
Commit(true);
|
Commit(true);
|
||||||
|
|
||||||
curDiag = NULL;
|
|
||||||
parent->ReleaseMouse();
|
parent->ReleaseMouse();
|
||||||
parent->SetFocus();
|
parent->SetFocus();
|
||||||
}
|
}
|
||||||
|
@ -229,15 +220,17 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
|
||||||
if (InitializeDrag(curFeature)) {
|
if (InitializeDrag(curFeature)) {
|
||||||
if (selFeatures.find(curFeatureI) == selFeatures.end()) {
|
if (selFeatures.find(curFeatureI) == selFeatures.end()) {
|
||||||
selChanged = true;
|
selChanged = true;
|
||||||
if (!ctrlDown) {
|
if (ctrlDown) {
|
||||||
ClearSelection();
|
|
||||||
}
|
|
||||||
AddSelection(curFeatureI);
|
AddSelection(curFeatureI);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
SetSelection(curFeatureI);
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
selChanged = false;
|
selChanged = false;
|
||||||
}
|
}
|
||||||
SetEditbox(curFeature->lineN);
|
if (curFeature->line) grid->SetActiveLine(curFeature->line);
|
||||||
|
|
||||||
dragStartX = video.x;
|
dragStartX = video.x;
|
||||||
dragStartY = video.y;
|
dragStartY = video.y;
|
||||||
|
@ -248,21 +241,22 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
|
||||||
|
|
||||||
dragging = true;
|
dragging = true;
|
||||||
parent->CaptureMouse();
|
parent->CaptureMouse();
|
||||||
if (realTime) AssLimitToVisibleFilter::SetFrame(frame_n);
|
if (realTime) AssLimitToVisibleFilter::SetFrame(frameNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// start hold
|
// start hold
|
||||||
else {
|
else {
|
||||||
if (!altDown) {
|
if (!altDown) {
|
||||||
ClearSelection();
|
ClearSelection();
|
||||||
SetEditbox();
|
Selection sel;
|
||||||
|
sel.insert(grid->GetActiveLine());
|
||||||
|
grid->SetSelectedSet(sel);
|
||||||
needRender = true;
|
needRender = true;
|
||||||
}
|
}
|
||||||
curDiag = GetActiveDialogueLine();
|
|
||||||
if (curDiag && InitializeHold()) {
|
if (curDiag && InitializeHold()) {
|
||||||
holding = true;
|
holding = true;
|
||||||
parent->CaptureMouse();
|
parent->CaptureMouse();
|
||||||
if (realTime) AssLimitToVisibleFilter::SetFrame(frame_n);
|
if (realTime) AssLimitToVisibleFilter::SetFrame(frameNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,7 +267,7 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
|
||||||
|
|
||||||
template<class FeatureType>
|
template<class FeatureType>
|
||||||
void VisualTool<FeatureType>::Commit(bool full, wxString message) {
|
void VisualTool<FeatureType>::Commit(bool full, wxString message) {
|
||||||
SubtitlesGrid *grid = VideoContext::Get()->grid;
|
externalChange = false;
|
||||||
if (full) {
|
if (full) {
|
||||||
if (message.empty()) {
|
if (message.empty()) {
|
||||||
message = _("visual typesetting");
|
message = _("visual typesetting");
|
||||||
|
@ -283,11 +277,11 @@ void VisualTool<FeatureType>::Commit(bool full, wxString message) {
|
||||||
grid->CommitChanges(false,!full);
|
grid->CommitChanges(false,!full);
|
||||||
if (full)
|
if (full)
|
||||||
grid->editBox->Update(false, true);
|
grid->editBox->Update(false, true);
|
||||||
|
externalChange = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class FeatureType>
|
template<class FeatureType>
|
||||||
AssDialogue* VisualTool<FeatureType>::GetActiveDialogueLine() {
|
AssDialogue* VisualTool<FeatureType>::GetActiveDialogueLine() {
|
||||||
SubtitlesGrid *grid = VideoContext::Get()->grid;
|
|
||||||
AssDialogue *diag = grid->GetActiveLine();
|
AssDialogue *diag = grid->GetActiveLine();
|
||||||
if (grid->IsDisplayed(diag))
|
if (grid->IsDisplayed(diag))
|
||||||
return diag;
|
return diag;
|
||||||
|
@ -332,20 +326,61 @@ void VisualTool<FeatureType>::DrawAllFeatures() {
|
||||||
|
|
||||||
template<class FeatureType>
|
template<class FeatureType>
|
||||||
void VisualTool<FeatureType>::Refresh() {
|
void VisualTool<FeatureType>::Refresh() {
|
||||||
frame_n = VideoContext::Get()->GetFrameN();
|
|
||||||
if (externalChange) {
|
if (externalChange) {
|
||||||
dragListOK = false;
|
dragListOK = false;
|
||||||
DoRefresh();
|
curDiag = GetActiveDialogueLine();
|
||||||
|
OnFileChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class FeatureType>
|
||||||
|
void VisualTool<FeatureType>::SetFrame(int newFrameNumber) {
|
||||||
|
if (frameNumber == newFrameNumber) return;
|
||||||
|
OnFrameChanged();
|
||||||
|
AssDialogue *newCurDiag = GetActiveDialogueLine();
|
||||||
|
if (newCurDiag != curDiag) {
|
||||||
|
curDiag = newCurDiag;
|
||||||
|
OnLineChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FeatureType>
|
||||||
|
void VisualTool<FeatureType>::OnActiveLineChanged(AssDialogue *new_line) {
|
||||||
|
if (new_line && !grid->IsDisplayed(new_line)) {
|
||||||
|
new_line = NULL;
|
||||||
|
}
|
||||||
|
if (new_line != curDiag) {
|
||||||
|
curDiag = new_line;
|
||||||
|
OnLineChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class FeatureType>
|
||||||
|
void VisualTool<FeatureType>::SetSelection(unsigned i) {
|
||||||
|
assert(i < features.size());
|
||||||
|
|
||||||
|
selFeatures.clear();
|
||||||
|
lineSelCount.clear();
|
||||||
|
selFeatures.insert(i);
|
||||||
|
|
||||||
|
AssDialogue *line = features[i].line;
|
||||||
|
if (line) {
|
||||||
|
lineSelCount[line] = 1;
|
||||||
|
|
||||||
|
Selection sel;
|
||||||
|
sel.insert(line);
|
||||||
|
grid->SetSelectedSet(sel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class FeatureType>
|
template<class FeatureType>
|
||||||
void VisualTool<FeatureType>::AddSelection(unsigned i) {
|
void VisualTool<FeatureType>::AddSelection(unsigned i) {
|
||||||
assert(i < features.size());
|
assert(i < features.size());
|
||||||
|
|
||||||
if (selFeatures.insert(i).second && features[i].line) {
|
if (selFeatures.insert(i).second && features[i].line) {
|
||||||
lineSelCount[features[i].lineN] += 1;
|
lineSelCount[features[i].line] += 1;
|
||||||
|
|
||||||
SubtitlesGrid *grid = VideoContext::Get()->grid;
|
|
||||||
grid->SelectRow(features[i].lineN, true);
|
grid->SelectRow(features[i].lineN, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,59 +392,39 @@ void VisualTool<FeatureType>::RemoveSelection(unsigned i) {
|
||||||
if (selFeatures.erase(i) > 0 && features[i].line) {
|
if (selFeatures.erase(i) > 0 && features[i].line) {
|
||||||
// Deselect a line only if all features for that line have been
|
// Deselect a line only if all features for that line have been
|
||||||
// deselected
|
// deselected
|
||||||
int lineN = features[i].lineN;
|
AssDialogue* line = features[i].line;
|
||||||
lineSelCount[lineN] -= 1;
|
lineSelCount[line] -= 1;
|
||||||
assert(lineSelCount[lineN] >= 0);
|
assert(lineSelCount[line] >= 0);
|
||||||
if (lineSelCount[lineN] <= 0) {
|
if (lineSelCount[line] <= 0) {
|
||||||
SubtitlesGrid *grid = VideoContext::Get()->grid;
|
Selection sel = grid->GetSelectedSet();
|
||||||
grid->SelectRow(lineN, true, false);
|
|
||||||
|
|
||||||
// We may have just deselected the active line, so make sure the
|
// Don't deselect the only selected line
|
||||||
// edit box is set to something sane
|
if (sel.size() <= 1) return;
|
||||||
SetEditbox();
|
|
||||||
|
sel.erase(line);
|
||||||
|
|
||||||
|
// Set the active line to an arbitrary selected line if we just
|
||||||
|
// deselected the active line
|
||||||
|
if (line == grid->GetActiveLine()) {
|
||||||
|
grid->SetActiveLine(*sel.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
grid->SetSelectedSet(sel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class FeatureType>
|
template<class FeatureType>
|
||||||
wxArrayInt VisualTool<FeatureType>::GetSelection() {
|
wxArrayInt VisualTool<FeatureType>::GetSelection() {
|
||||||
return VideoContext::Get()->grid->GetSelection();
|
return grid->GetSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class FeatureType>
|
template<class FeatureType>
|
||||||
void VisualTool<FeatureType>::ClearSelection(bool hard) {
|
void VisualTool<FeatureType>::ClearSelection() {
|
||||||
if (hard) {
|
|
||||||
Selection sel;
|
|
||||||
VideoContext::Get()->grid->SetSelectedSet(sel);
|
|
||||||
}
|
|
||||||
selFeatures.clear();
|
selFeatures.clear();
|
||||||
lineSelCount.clear();
|
lineSelCount.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class FeatureType>
|
|
||||||
void VisualTool<FeatureType>::SetEditbox(int lineN) {
|
|
||||||
VideoContext* con = VideoContext::Get();
|
|
||||||
if (lineN > -1) {
|
|
||||||
con->grid->SetActiveLine(con->grid->GetDialogue(lineN));
|
|
||||||
con->grid->SelectRow(lineN, true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Selection sel;
|
|
||||||
con->grid->GetSelectedSet(sel);
|
|
||||||
// If there is a selection and the edit box's line is in it, do nothing
|
|
||||||
// Otherwise set the edit box if there is a selection or the selection
|
|
||||||
// to the edit box if there is no selection
|
|
||||||
if (sel.empty()) {
|
|
||||||
sel.insert(con->grid->GetActiveLine());
|
|
||||||
con->grid->SetSelectedSet(sel);
|
|
||||||
}
|
|
||||||
else if (sel.find(con->grid->GetActiveLine()) == sel.end()) {
|
|
||||||
con->grid->SetActiveLine(con->grid->GetDialogue(con->grid->GetFirstSelRow()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum TagFoundType {
|
enum TagFoundType {
|
||||||
TAG_NOT_FOUND = 0,
|
TAG_NOT_FOUND = 0,
|
||||||
PRIMARY_TAG_FOUND,
|
PRIMARY_TAG_FOUND,
|
||||||
|
@ -461,7 +476,7 @@ void VisualTool<FeatureType>::GetLinePosition(AssDialogue *diag,int &x, int &y,
|
||||||
for (int i=0;i<4;i++) margin[i] = diag->Margin[i];
|
for (int i=0;i<4;i++) margin[i] = diag->Margin[i];
|
||||||
int align = 2;
|
int align = 2;
|
||||||
|
|
||||||
AssStyle *style = VideoContext::Get()->grid->ass->GetStyle(diag->Style);
|
AssStyle *style = grid->ass->GetStyle(diag->Style);
|
||||||
if (style) {
|
if (style) {
|
||||||
align = style->alignment;
|
align = style->alignment;
|
||||||
for (int i=0;i<4;i++) {
|
for (int i=0;i<4;i++) {
|
||||||
|
@ -541,7 +556,7 @@ template<class FeatureType>
|
||||||
void VisualTool<FeatureType>::GetLineRotation(AssDialogue *diag,float &rx,float &ry,float &rz) {
|
void VisualTool<FeatureType>::GetLineRotation(AssDialogue *diag,float &rx,float &ry,float &rz) {
|
||||||
rx = ry = rz = 0.f;
|
rx = ry = rz = 0.f;
|
||||||
|
|
||||||
AssStyle *style = VideoContext::Get()->grid->ass->GetStyle(diag->Style);
|
AssStyle *style = grid->ass->GetStyle(diag->Style);
|
||||||
if (style) {
|
if (style) {
|
||||||
rz = style->angle;
|
rz = style->angle;
|
||||||
}
|
}
|
||||||
|
@ -559,7 +574,7 @@ template<class FeatureType>
|
||||||
void VisualTool<FeatureType>::GetLineScale(AssDialogue *diag,float &scalX,float &scalY) {
|
void VisualTool<FeatureType>::GetLineScale(AssDialogue *diag,float &scalX,float &scalY) {
|
||||||
scalX = scalY = 100.f;
|
scalX = scalY = 100.f;
|
||||||
|
|
||||||
AssStyle *style = VideoContext::Get()->grid->ass->GetStyle(diag->Style);
|
AssStyle *style = grid->ass->GetStyle(diag->Style);
|
||||||
if (style) {
|
if (style) {
|
||||||
scalX = style->scalex;
|
scalX = style->scalex;
|
||||||
scalY = style->scaley;
|
scalY = style->scaley;
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
|
|
||||||
class VideoDisplay;
|
class VideoDisplay;
|
||||||
class AssDialogue;
|
class AssDialogue;
|
||||||
|
class SubtitlesGrid;
|
||||||
struct VideoState;
|
struct VideoState;
|
||||||
namespace agi {
|
namespace agi {
|
||||||
class OptionValue;
|
class OptionValue;
|
||||||
|
@ -71,6 +72,7 @@ public:
|
||||||
virtual bool Update()=0;
|
virtual bool Update()=0;
|
||||||
virtual void Draw()=0;
|
virtual void Draw()=0;
|
||||||
virtual void Refresh()=0;
|
virtual void Refresh()=0;
|
||||||
|
virtual void SetFrame(int frame)=0;
|
||||||
virtual ~IVisualTool() { };
|
virtual ~IVisualTool() { };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,25 +91,60 @@ private:
|
||||||
/// or NULL and -1 if there are none
|
/// or NULL and -1 if there are none
|
||||||
void GetHighlightedFeature();
|
void GetHighlightedFeature();
|
||||||
|
|
||||||
|
/// @brief Get the dialogue line currently in the edit box
|
||||||
|
/// @return NULL if the line is not active on the current frame
|
||||||
|
AssDialogue *GetActiveDialogueLine();
|
||||||
|
|
||||||
typedef typename std::set<int>::iterator selection_iterator;
|
typedef typename std::set<int>::iterator selection_iterator;
|
||||||
|
|
||||||
std::set<int> selFeatures; /// Currently selected visual features
|
std::set<int> selFeatures; /// Currently selected visual features
|
||||||
std::map<int, int> lineSelCount; /// Number of selected features for each line
|
std::map<AssDialogue*, int> lineSelCount; /// Number of selected features for each line
|
||||||
|
|
||||||
/// @brief Set the edit box's active line, ensuring proper sync with grid
|
|
||||||
/// @param lineN Line number or -1 for automatic selection
|
|
||||||
///
|
|
||||||
/// This function ensures that the selection is not empty and that the line
|
|
||||||
/// displayed in the edit box is part of the selection, by either setting
|
|
||||||
/// the edit box to the selection or setting the selection to the edit
|
|
||||||
/// box's line, as is appropriate.
|
|
||||||
void SetEditbox(int lineN = -1);
|
|
||||||
|
|
||||||
bool selChanged; /// Has the selection already been changed in the current click?
|
bool selChanged; /// Has the selection already been changed in the current click?
|
||||||
|
|
||||||
|
/// @brief Called when a hold is begun
|
||||||
|
/// @return Should the hold actually happen?
|
||||||
|
virtual bool InitializeHold() { return false; }
|
||||||
|
/// @brief Called on every mouse event during a hold
|
||||||
|
virtual void UpdateHold() { }
|
||||||
|
/// @brief Called at the end of a hold
|
||||||
|
virtual void CommitHold() { }
|
||||||
|
|
||||||
|
/// @brief Called when the feature list needs to be (re)generated
|
||||||
|
virtual void PopulateFeatureList() { }
|
||||||
|
|
||||||
|
/// @brief Called at the beginning of a drag
|
||||||
|
/// @param feature The visual feature clicked on
|
||||||
|
/// @return Should the drag happen?
|
||||||
|
virtual bool InitializeDrag(FeatureType* feature) { return true; }
|
||||||
|
/// @brief Called on every mouse event during a drag
|
||||||
|
/// @param feature The current feature to process; not necessarily the one clicked on
|
||||||
|
virtual void UpdateDrag(FeatureType* feature) { }
|
||||||
|
/// @brief Called at the end of a drag
|
||||||
|
virtual void CommitDrag(FeatureType* feature) { }
|
||||||
|
|
||||||
|
/// Called when the file is changed by something other than a visual tool
|
||||||
|
virtual void OnFileChanged() { DoRefresh(); }
|
||||||
|
/// Called when the frame number changes
|
||||||
|
virtual void OnFrameChanged() { }
|
||||||
|
/// Called when curDiag changes
|
||||||
|
virtual void OnLineChanged() { DoRefresh(); }
|
||||||
|
/// Generic refresh to simplify tools which do the same thing for any
|
||||||
|
/// external change (i.e. almost all of them). Called only by the above
|
||||||
|
/// methods.
|
||||||
|
virtual void DoRefresh() { }
|
||||||
|
|
||||||
|
/// @brief Called when there's stuff
|
||||||
|
/// @return Should the display rerender?
|
||||||
|
virtual bool Update() { return false; };
|
||||||
|
/// @brief Draw stuff
|
||||||
|
virtual void Draw()=0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
SubtitlesGrid *grid;
|
||||||
VideoDisplay *parent; /// VideoDisplay which this belongs to, used to frame conversion
|
VideoDisplay *parent; /// VideoDisplay which this belongs to, used to frame conversion
|
||||||
bool holding; /// Is a hold currently in progress?
|
bool holding; /// Is a hold currently in progress?
|
||||||
AssDialogue *curDiag; /// Active dialogue line for a hold; only valid when holding = true
|
AssDialogue *curDiag; /// Active dialogue line; NULL if it is not visible on the current frame
|
||||||
bool dragging; /// Is a drag currently in progress?
|
bool dragging; /// Is a drag currently in progress?
|
||||||
bool externalChange; /// Only invalid drag lists when refreshing due to external changes
|
bool externalChange; /// Only invalid drag lists when refreshing due to external changes
|
||||||
|
|
||||||
|
@ -116,7 +153,7 @@ protected:
|
||||||
std::vector<FeatureType> features; /// List of features which are drawn and can be clicked on
|
std::vector<FeatureType> features; /// List of features which are drawn and can be clicked on
|
||||||
bool dragListOK; /// Do the features not need to be regenerated?
|
bool dragListOK; /// Do the features not need to be regenerated?
|
||||||
|
|
||||||
int frame_n; /// Current frame number
|
int frameNumber; /// Current frame number
|
||||||
VideoState const& video; /// Mouse and video information
|
VideoState const& video; /// Mouse and video information
|
||||||
|
|
||||||
bool leftClick; /// Is a left click event currently being processed?
|
bool leftClick; /// Is a left click event currently being processed?
|
||||||
|
@ -134,53 +171,27 @@ protected:
|
||||||
wxString GetLineVectorClip(AssDialogue *diag,int &scale,bool &inverse);
|
wxString GetLineVectorClip(AssDialogue *diag,int &scale,bool &inverse);
|
||||||
void SetOverride(AssDialogue* line, wxString tag, wxString value);
|
void SetOverride(AssDialogue* line, wxString tag, wxString value);
|
||||||
|
|
||||||
/// @brief Get the dialogue line currently in the edit box
|
|
||||||
/// @return NULL if the line is not active on the current frame
|
|
||||||
AssDialogue *GetActiveDialogueLine();
|
|
||||||
/// Draw all of the features in the list
|
/// Draw all of the features in the list
|
||||||
void DrawAllFeatures();
|
void DrawAllFeatures();
|
||||||
/// @brief Commit the current file state
|
/// @brief Commit the current file state
|
||||||
/// @param message Description of changes for undo
|
/// @param message Description of changes for undo
|
||||||
void Commit(bool full=false, wxString message = L"");
|
void Commit(bool full=false, wxString message = L"");
|
||||||
|
|
||||||
/// @brief Called when a hold is begun
|
|
||||||
/// @return Should the hold actually happen?
|
|
||||||
virtual bool InitializeHold() { return false; }
|
|
||||||
|
|
||||||
/// @brief Called on every mouse event during a hold
|
|
||||||
virtual void UpdateHold() { }
|
|
||||||
|
|
||||||
/// @brief Called at the end of a hold
|
|
||||||
virtual void CommitHold() { }
|
|
||||||
|
|
||||||
/// @brief Called when the feature list needs to be (re)generated
|
|
||||||
virtual void PopulateFeatureList() { }
|
|
||||||
|
|
||||||
/// @brief Called at the beginning of a drag
|
|
||||||
/// @param feature The visual feature clicked on
|
|
||||||
/// @return Should the drag happen?
|
|
||||||
virtual bool InitializeDrag(FeatureType* feature) { return true; }
|
|
||||||
|
|
||||||
/// @brief Called on every mouse event during a drag
|
|
||||||
/// @param feature The current feature to process; not necessarily the one clicked on
|
|
||||||
virtual void UpdateDrag(FeatureType* feature) { }
|
|
||||||
|
|
||||||
// @brief Called at the end of a drag
|
|
||||||
virtual void CommitDrag(FeatureType* feature) { }
|
|
||||||
|
|
||||||
/// @brief Called by Refresh when there's stuff
|
|
||||||
virtual void DoRefresh() { }
|
|
||||||
|
|
||||||
/// @brief Add a feature (and its line) to the selection
|
/// @brief Add a feature (and its line) to the selection
|
||||||
/// @param i Index in the feature list
|
/// @param i Index in the feature list
|
||||||
void AddSelection(unsigned i);
|
void AddSelection(unsigned i);
|
||||||
|
|
||||||
/// @brief Remove a feature from the selection
|
/// @brief Remove a feature from the selection
|
||||||
/// @param i Index in the feature list
|
/// @param i Index in the feature list
|
||||||
/// Also deselects lines if all features for that line have been deselected
|
/// Also deselects lines if all features for that line have been deselected
|
||||||
void RemoveSelection(unsigned i);
|
void RemoveSelection(unsigned i);
|
||||||
|
|
||||||
|
/// @brief Set the selection to a single feature, deselecting everything else
|
||||||
|
/// @param i Index in the feature list
|
||||||
|
void SetSelection(unsigned i);
|
||||||
|
|
||||||
/// @brief Clear the selection
|
/// @brief Clear the selection
|
||||||
/// @param hard Should the grid's selection be cleared as well?
|
void ClearSelection();
|
||||||
void ClearSelection(bool hard=true);
|
|
||||||
/// @brief Get the currently selected lines
|
/// @brief Get the currently selected lines
|
||||||
wxArrayInt GetSelection();
|
wxArrayInt GetSelection();
|
||||||
|
|
||||||
|
@ -189,8 +200,7 @@ protected:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// SubtitleSelectionListener implementation
|
// SubtitleSelectionListener implementation
|
||||||
// (overridden by deriving classes too)
|
void OnActiveLineChanged(AssDialogue *new_line);
|
||||||
virtual void OnActiveLineChanged(AssDialogue *new_line) { }
|
|
||||||
virtual void OnSelectedSetChanged(const Selection &lines_added, const Selection &lines_removed) { }
|
virtual void OnSelectedSetChanged(const Selection &lines_added, const Selection &lines_removed) { }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -200,13 +210,13 @@ public:
|
||||||
|
|
||||||
/// @brief Event handler for the subtoolbar
|
/// @brief Event handler for the subtoolbar
|
||||||
virtual void OnSubTool(wxCommandEvent &) { }
|
virtual void OnSubTool(wxCommandEvent &) { }
|
||||||
/// @brief Called when there's stuff
|
|
||||||
/// @return Should the display rerender?
|
/// @brief Signal that the file has changed
|
||||||
virtual bool Update() { return false; };
|
|
||||||
/// @brief Draw stuff
|
|
||||||
virtual void Draw()=0;
|
|
||||||
/// @brief Called by stuff when there's stuff, and sometimes when there isn't stuff
|
|
||||||
void Refresh();
|
void Refresh();
|
||||||
|
/// @brief Signal that the current frame number has changed
|
||||||
|
/// @param newFrameNumber The new frame number
|
||||||
|
void SetFrame(int newFrameNumber);
|
||||||
|
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
/// @param parent The VideoDisplay to use for coordinate conversion
|
/// @param parent The VideoDisplay to use for coordinate conversion
|
||||||
|
|
|
@ -47,8 +47,6 @@
|
||||||
#include "video_display.h"
|
#include "video_display.h"
|
||||||
#include "visual_tool_clip.h"
|
#include "visual_tool_clip.h"
|
||||||
|
|
||||||
/// @brief Constructor
|
|
||||||
/// @param _parent
|
|
||||||
VisualToolClip::VisualToolClip(VideoDisplay *parent, VideoState const& video, wxToolBar *)
|
VisualToolClip::VisualToolClip(VideoDisplay *parent, VideoState const& video, wxToolBar *)
|
||||||
: VisualTool<ClipCorner>(parent, video)
|
: VisualTool<ClipCorner>(parent, video)
|
||||||
, curX1(0)
|
, curX1(0)
|
||||||
|
@ -57,14 +55,13 @@ VisualToolClip::VisualToolClip(VideoDisplay *parent, VideoState const& video, wx
|
||||||
, curY2(video.h)
|
, curY2(video.h)
|
||||||
, inverse(false)
|
, inverse(false)
|
||||||
{
|
{
|
||||||
AssDialogue *line = GetActiveDialogueLine();
|
if (curDiag) {
|
||||||
if (line) GetLineClip(line,curX1,curY1,curX2,curY2,inverse);
|
GetLineClip(curDiag,curX1,curY1,curX2,curY2,inverse);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Draw
|
|
||||||
void VisualToolClip::Draw() {
|
void VisualToolClip::Draw() {
|
||||||
AssDialogue *line = GetActiveDialogueLine();
|
if (!curDiag) return;
|
||||||
if (!line) return;
|
|
||||||
|
|
||||||
int dx1 = curX1;
|
int dx1 = curX1;
|
||||||
int dy1 = curY1;
|
int dy1 = curY1;
|
||||||
|
@ -95,7 +92,6 @@ void VisualToolClip::Draw() {
|
||||||
DrawAllFeatures();
|
DrawAllFeatures();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Start holding
|
|
||||||
bool VisualToolClip::InitializeHold() {
|
bool VisualToolClip::InitializeHold() {
|
||||||
startX = video.x;
|
startX = video.x;
|
||||||
startY = video.y;
|
startY = video.y;
|
||||||
|
@ -104,7 +100,6 @@ bool VisualToolClip::InitializeHold() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Update hold
|
|
||||||
void VisualToolClip::UpdateHold() {
|
void VisualToolClip::UpdateHold() {
|
||||||
// Coordinates
|
// Coordinates
|
||||||
curX1 = startX;
|
curX1 = startX;
|
||||||
|
@ -122,11 +117,9 @@ void VisualToolClip::UpdateHold() {
|
||||||
curY1 = MID(0,curY1,video.h);
|
curY1 = MID(0,curY1,video.h);
|
||||||
curY2 = MID(0,curY2,video.h);
|
curY2 = MID(0,curY2,video.h);
|
||||||
|
|
||||||
// Features
|
|
||||||
PopulateFeatureList();
|
PopulateFeatureList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Commit hold
|
|
||||||
void VisualToolClip::CommitHold() {
|
void VisualToolClip::CommitHold() {
|
||||||
int x1 = curX1;
|
int x1 = curX1;
|
||||||
int x2 = curX2;
|
int x2 = curX2;
|
||||||
|
@ -134,14 +127,12 @@ void VisualToolClip::CommitHold() {
|
||||||
int y2 = curY2;
|
int y2 = curY2;
|
||||||
parent->ToScriptCoords(&x1, &y1);
|
parent->ToScriptCoords(&x1, &y1);
|
||||||
parent->ToScriptCoords(&x2, &y2);
|
parent->ToScriptCoords(&x2, &y2);
|
||||||
SetOverride(GetActiveDialogueLine(), inverse ? L"\\iclip" : L"\\clip",wxString::Format(L"(%i,%i,%i,%i)",x1,y1,x2,y2));
|
SetOverride(curDiag, inverse ? L"\\iclip" : L"\\clip",wxString::Format(L"(%i,%i,%i,%i)",x1,y1,x2,y2));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Populate feature list
|
|
||||||
void VisualToolClip::PopulateFeatureList() {
|
void VisualToolClip::PopulateFeatureList() {
|
||||||
// Clear
|
|
||||||
if (features.size() != 4) {
|
if (features.size() != 4) {
|
||||||
ClearSelection(false);
|
ClearSelection();
|
||||||
features.clear();
|
features.clear();
|
||||||
features.resize(4);
|
features.resize(4);
|
||||||
}
|
}
|
||||||
|
@ -180,17 +171,12 @@ void VisualToolClip::PopulateFeatureList() {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Initialize
|
|
||||||
/// @param feature
|
|
||||||
bool VisualToolClip::InitializeDrag(ClipCorner*) {
|
bool VisualToolClip::InitializeDrag(ClipCorner*) {
|
||||||
curDiag = GetActiveDialogueLine();
|
|
||||||
curDiag->StripTag(L"\\clip");
|
curDiag->StripTag(L"\\clip");
|
||||||
curDiag->StripTag(L"\\iclip");
|
curDiag->StripTag(L"\\iclip");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Update drag
|
|
||||||
/// @param feature
|
|
||||||
void VisualToolClip::UpdateDrag(ClipCorner* feature) {
|
void VisualToolClip::UpdateDrag(ClipCorner* feature) {
|
||||||
// Update brothers
|
// Update brothers
|
||||||
feature->horiz->y = feature->y;
|
feature->horiz->y = feature->y;
|
||||||
|
@ -207,14 +193,20 @@ void VisualToolClip::UpdateDrag(ClipCorner* feature) {
|
||||||
if (curY1 > curY2) std::swap(curY1,curY2);
|
if (curY1 > curY2) std::swap(curY1,curY2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Done dragging
|
|
||||||
/// @param feature
|
|
||||||
void VisualToolClip::CommitDrag(ClipCorner*) {
|
void VisualToolClip::CommitDrag(ClipCorner*) {
|
||||||
CommitHold();
|
CommitHold();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualToolClip::DoRefresh() {
|
void VisualToolClip::OnLineChanged() {
|
||||||
AssDialogue* line = GetActiveDialogueLine();
|
if (curDiag) {
|
||||||
if (line)
|
GetLineClip(curDiag,curX1,curY1,curX2,curY2,inverse);
|
||||||
GetLineClip(line,curX1,curY1,curX2,curY2,inverse);
|
PopulateFeatureList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualToolClip::OnFileChanged() {
|
||||||
|
if (curDiag) {
|
||||||
|
GetLineClip(curDiag,curX1,curY1,curX2,curY2,inverse);
|
||||||
|
PopulateFeatureList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,43 +57,23 @@ public:
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// DOCME
|
||||||
class VisualToolClip : public VisualTool<ClipCorner> {
|
class VisualToolClip : public VisualTool<ClipCorner> {
|
||||||
private:
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
int startX,startY,curX1,curY1,curX2,curY2;
|
int startX,startY,curX1,curY1,curX2,curY2;
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
bool inverse;
|
bool inverse;
|
||||||
|
|
||||||
/// @brief DOCME
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
bool InitializeHold();
|
bool InitializeHold();
|
||||||
void UpdateHold();
|
void UpdateHold();
|
||||||
void CommitHold();
|
void CommitHold();
|
||||||
|
|
||||||
|
void OnLineChanged();
|
||||||
|
void OnFileChanged();
|
||||||
|
|
||||||
/// @brief DOCME
|
|
||||||
///
|
|
||||||
void PopulateFeatureList();
|
void PopulateFeatureList();
|
||||||
bool InitializeDrag(ClipCorner* feature);
|
bool InitializeDrag(ClipCorner* feature);
|
||||||
void UpdateDrag(ClipCorner* feature);
|
void UpdateDrag(ClipCorner* feature);
|
||||||
void CommitDrag(ClipCorner* feature);
|
void CommitDrag(ClipCorner* feature);
|
||||||
|
|
||||||
void DoRefresh();
|
void Draw();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VisualToolClip(VideoDisplay *parent, VideoState const& video, wxToolBar *);
|
VisualToolClip(VideoDisplay *parent, VideoState const& video, wxToolBar *);
|
||||||
|
|
||||||
void Draw();
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -43,26 +43,19 @@
|
||||||
#include "video_display.h"
|
#include "video_display.h"
|
||||||
#include "visual_tool_cross.h"
|
#include "visual_tool_cross.h"
|
||||||
|
|
||||||
/// @brief Constructor
|
|
||||||
/// @param _parent
|
|
||||||
VisualToolCross::VisualToolCross(VideoDisplay *parent, VideoState const& video, wxToolBar *)
|
VisualToolCross::VisualToolCross(VideoDisplay *parent, VideoState const& video, wxToolBar *)
|
||||||
: VisualTool<VisualDraggableFeature>(parent, video)
|
: VisualTool<VisualDraggableFeature>(parent, video)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
VisualToolCross::~VisualToolCross() { }
|
|
||||||
|
|
||||||
/// @brief Update
|
|
||||||
bool VisualToolCross::Update() {
|
bool VisualToolCross::Update() {
|
||||||
if (!leftDClick) return true;
|
if (!leftDClick) return true;
|
||||||
|
if (!curDiag) return true;
|
||||||
AssDialogue* line = GetActiveDialogueLine();
|
|
||||||
if (!line) return true;
|
|
||||||
|
|
||||||
|
|
||||||
int dx, dy;
|
int dx, dy;
|
||||||
int vx = video.x;
|
int vx = video.x;
|
||||||
int vy = video.y;
|
int vy = video.y;
|
||||||
GetLinePosition(line, dx, dy);
|
GetLinePosition(curDiag, dx, dy);
|
||||||
parent->ToScriptCoords(&vx, &vy);
|
parent->ToScriptCoords(&vx, &vy);
|
||||||
parent->ToScriptCoords(&dx, &dy);
|
parent->ToScriptCoords(&dx, &dy);
|
||||||
dx -= vx;
|
dx -= vx;
|
||||||
|
@ -71,7 +64,7 @@ bool VisualToolCross::Update() {
|
||||||
SubtitlesGrid *grid = VideoContext::Get()->grid;
|
SubtitlesGrid *grid = VideoContext::Get()->grid;
|
||||||
wxArrayInt sel = grid->GetSelection();
|
wxArrayInt sel = grid->GetSelection();
|
||||||
for (wxArrayInt::const_iterator cur = sel.begin(); cur != sel.end(); ++cur) {
|
for (wxArrayInt::const_iterator cur = sel.begin(); cur != sel.end(); ++cur) {
|
||||||
line = grid->GetDialogue(*cur);
|
AssDialogue *line = grid->GetDialogue(*cur);
|
||||||
if (!line) continue;
|
if (!line) continue;
|
||||||
int x1, y1;
|
int x1, y1;
|
||||||
GetLinePosition(line, x1, y1);
|
GetLinePosition(line, x1, y1);
|
||||||
|
@ -83,7 +76,6 @@ bool VisualToolCross::Update() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Draw
|
|
||||||
void VisualToolCross::Draw() {
|
void VisualToolCross::Draw() {
|
||||||
// Draw cross
|
// Draw cross
|
||||||
glDisable(GL_LINE_SMOOTH);
|
glDisable(GL_LINE_SMOOTH);
|
||||||
|
|
|
@ -44,12 +44,8 @@
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// DOCME
|
||||||
class VisualToolCross : public VisualTool<VisualDraggableFeature> {
|
class VisualToolCross : public VisualTool<VisualDraggableFeature> {
|
||||||
public:
|
|
||||||
VisualToolCross(VideoDisplay *parent, VideoState const& video, wxToolBar *);
|
|
||||||
~VisualToolCross();
|
|
||||||
|
|
||||||
bool Update();
|
bool Update();
|
||||||
void Draw();
|
void Draw();
|
||||||
|
public:
|
||||||
|
VisualToolCross(VideoDisplay *parent, VideoState const& video, wxToolBar *);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -70,11 +70,10 @@ VisualToolDrag::VisualToolDrag(VideoDisplay *parent, VideoState const& video, wx
|
||||||
void VisualToolDrag::UpdateToggleButtons() {
|
void VisualToolDrag::UpdateToggleButtons() {
|
||||||
// Check which bitmap to use
|
// Check which bitmap to use
|
||||||
bool toMove = true;
|
bool toMove = true;
|
||||||
AssDialogue *line = GetActiveDialogueLine();
|
if (curDiag) {
|
||||||
if (line) {
|
|
||||||
int x1,y1,x2,y2,t1,t2;
|
int x1,y1,x2,y2,t1,t2;
|
||||||
bool hasMove;
|
bool hasMove;
|
||||||
GetLineMove(line,hasMove,x1,y1,x2,y2,t1,t2);
|
GetLineMove(curDiag,hasMove,x1,y1,x2,y2,t1,t2);
|
||||||
toMove = !hasMove;
|
toMove = !hasMove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,13 +116,24 @@ void VisualToolDrag::OnSubTool(wxCommandEvent &) {
|
||||||
Refresh();
|
Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualToolDrag::DoRefresh() {
|
void VisualToolDrag::OnLineChanged() {
|
||||||
UpdateToggleButtons();
|
UpdateToggleButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VisualToolDrag::OnFileChanged() {
|
||||||
|
/// @todo be less dumb and preserve selections when possible
|
||||||
|
PopulateFeatureList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualToolDrag::OnFrameChanged() {
|
||||||
|
/// @todo be less dumb and preserve selections when possible
|
||||||
|
PopulateFeatureList();
|
||||||
|
}
|
||||||
|
|
||||||
void VisualToolDrag::OnSelectedSetChanged(const Selection &added, const Selection &removed) {
|
void VisualToolDrag::OnSelectedSetChanged(const Selection &added, const Selection &removed) {
|
||||||
if (!externalChange) return;
|
if (!externalChange) return;
|
||||||
externalChange = false;
|
externalChange = false;
|
||||||
|
grid->BeginBatch();
|
||||||
|
|
||||||
// Remove all deselected lines
|
// Remove all deselected lines
|
||||||
for (size_t i = 0; i < features.size(); i++) {
|
for (size_t i = 0; i < features.size(); i++) {
|
||||||
|
@ -139,6 +149,7 @@ void VisualToolDrag::OnSelectedSetChanged(const Selection &added, const Selectio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grid->EndBatch();
|
||||||
externalChange = true;
|
externalChange = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +204,7 @@ void VisualToolDrag::Draw() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualToolDrag::PopulateFeatureList() {
|
void VisualToolDrag::PopulateFeatureList() {
|
||||||
ClearSelection(false);
|
ClearSelection();
|
||||||
primary = -1;
|
primary = -1;
|
||||||
GenerateFeatures();
|
GenerateFeatures();
|
||||||
}
|
}
|
||||||
|
@ -267,7 +278,7 @@ bool VisualToolDrag::InitializeDrag(VisualToolDragDraggableFeature *feature) {
|
||||||
/// @param feature
|
/// @param feature
|
||||||
void VisualToolDrag::UpdateDrag(VisualToolDragDraggableFeature* feature) {
|
void VisualToolDrag::UpdateDrag(VisualToolDragDraggableFeature* feature) {
|
||||||
// Update "time" to reflect the time of the frame in which the feature is being dragged
|
// Update "time" to reflect the time of the frame in which the feature is being dragged
|
||||||
int time = VFR_Output.GetTimeAtFrame(frame_n,true,true);
|
int time = VFR_Output.GetTimeAtFrame(frameNumber,true,true);
|
||||||
feature->time = MID(0,time - feature->line->Start.GetMS(),feature->line->End.GetMS()-feature->line->Start.GetMS());
|
feature->time = MID(0,time - feature->line->Start.GetMS(),feature->line->End.GetMS()-feature->line->Start.GetMS());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,9 +328,8 @@ bool VisualToolDrag::Update() {
|
||||||
dy = features[primary].y;
|
dy = features[primary].y;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
AssDialogue* line = GetActiveDialogueLine();
|
if (!curDiag) return false;
|
||||||
if (!line) return false;
|
GetLinePosition(curDiag, dx, dy);
|
||||||
GetLinePosition(line, dx, dy);
|
|
||||||
}
|
}
|
||||||
parent->ToScriptCoords(&dx, &dy);
|
parent->ToScriptCoords(&dx, &dy);
|
||||||
dx -= vx;
|
dx -= vx;
|
||||||
|
|
|
@ -80,16 +80,18 @@ private:
|
||||||
|
|
||||||
/// Set the pos/move button to the correct icon based on the active line
|
/// Set the pos/move button to the correct icon based on the active line
|
||||||
void UpdateToggleButtons();
|
void UpdateToggleButtons();
|
||||||
void DoRefresh();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Overriding SubtitleSelectionListener inherited from base VisualTool<>
|
// Overriding SubtitleSelectionListener inherited from base VisualTool<>
|
||||||
virtual void OnSelectedSetChanged(const Selection &lines_added, const Selection &lines_removed);
|
void OnSelectedSetChanged(const Selection &lines_added, const Selection &lines_removed);
|
||||||
|
|
||||||
public:
|
void OnFrameChanged();
|
||||||
VisualToolDrag(VideoDisplay *parent, VideoState const& video, wxToolBar *toolbar);
|
void OnFileChanged();
|
||||||
|
void OnLineChanged();
|
||||||
|
|
||||||
void Draw();
|
void Draw();
|
||||||
bool Update();
|
bool Update();
|
||||||
|
public:
|
||||||
|
VisualToolDrag(VideoDisplay *parent, VideoState const& video, wxToolBar *toolbar);
|
||||||
|
|
||||||
void OnSubTool(wxCommandEvent &event);
|
void OnSubTool(wxCommandEvent &event);
|
||||||
};
|
};
|
||||||
|
|
|
@ -48,35 +48,22 @@
|
||||||
#include "video_display.h"
|
#include "video_display.h"
|
||||||
#include "visual_tool_rotatexy.h"
|
#include "visual_tool_rotatexy.h"
|
||||||
|
|
||||||
/// @brief Constructor
|
|
||||||
/// @param _parent
|
|
||||||
VisualToolRotateXY::VisualToolRotateXY(VideoDisplay *parent, VideoState const& video, wxToolBar *)
|
VisualToolRotateXY::VisualToolRotateXY(VideoDisplay *parent, VideoState const& video, wxToolBar *)
|
||||||
: VisualTool<VisualDraggableFeature>(parent, video)
|
: VisualTool<VisualDraggableFeature>(parent, video)
|
||||||
{
|
{
|
||||||
DoRefresh();
|
DoRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Draw
|
|
||||||
void VisualToolRotateXY::Draw() {
|
void VisualToolRotateXY::Draw() {
|
||||||
AssDialogue *line = GetActiveDialogueLine();
|
if (!curDiag) return;
|
||||||
if (!line) return;
|
|
||||||
|
|
||||||
// Pivot coordinates
|
// Pivot coordinates
|
||||||
int dx=0,dy=0;
|
int dx=0,dy=0;
|
||||||
if (dragging) GetLinePosition(line,dx,dy);
|
if (dragging) GetLinePosition(curDiag,dx,dy);
|
||||||
else GetLinePosition(line,dx,dy,orgx,orgy);
|
else GetLinePosition(curDiag,dx,dy,orgx,orgy);
|
||||||
dx = orgx;
|
dx = orgx;
|
||||||
dy = orgy;
|
dy = orgy;
|
||||||
|
|
||||||
// Rotation
|
|
||||||
float rx,ry;
|
|
||||||
GetLineRotation(line,rx,ry,rz);
|
|
||||||
if (line == curDiag) {
|
|
||||||
rx = curAngleX;
|
|
||||||
ry = curAngleY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set colours
|
|
||||||
SetLineColour(colour[0]);
|
SetLineColour(colour[0]);
|
||||||
SetFillColour(colour[1],0.3f);
|
SetFillColour(colour[1],0.3f);
|
||||||
|
|
||||||
|
@ -87,98 +74,92 @@ void VisualToolRotateXY::Draw() {
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glTranslatef(dx,dy,0.0f);
|
glTranslatef(dx,dy,0.f);
|
||||||
float matrix[16] = { 2500, 0, 0, 0, 0, 2500, 0, 0, 0, 0, 1, 1, 0, 0, 2500, 2500 };
|
float matrix[16] = { 2500, 0, 0, 0, 0, 2500, 0, 0, 0, 0, 1, 1, 0, 0, 2500, 2500 };
|
||||||
glMultMatrixf(matrix);
|
glMultMatrixf(matrix);
|
||||||
glScalef(1.0f,1.0f,8.0f);
|
glScalef(1.f,1.f,8.f);
|
||||||
if (ry != 0.0f) glRotatef(ry,0.0f,-1.0f,0.0f);
|
if (curAngleY != 0.f) glRotatef(curAngleY,0.f,-1.f,0.f);
|
||||||
if (rx != 0.0f) glRotatef(rx,-1.0f,0.0f,0.0f);
|
if (curAngleX != 0.f) glRotatef(curAngleX,-1.f,0.f,0.f);
|
||||||
if (rz != 0.0f) glRotatef(rz,0.0f,0.0f,-1.0f);
|
if (curAngleZ != 0.f) glRotatef(curAngleZ,0.f,0.f,-1.f);
|
||||||
|
|
||||||
// Draw grid
|
// Draw grid
|
||||||
glShadeModel(GL_SMOOTH);
|
glShadeModel(GL_SMOOTH);
|
||||||
SetLineColour(colour[0],0.5f,2);
|
SetLineColour(colour[0],0.5f,2);
|
||||||
SetModeLine();
|
SetModeLine();
|
||||||
float r = colour[0].Red()/255.0f;
|
float r = colour[0].Red()/255.f;
|
||||||
float g = colour[0].Green()/255.0f;
|
float g = colour[0].Green()/255.f;
|
||||||
float b = colour[0].Blue()/255.0f;
|
float b = colour[0].Blue()/255.f;
|
||||||
glBegin(GL_LINES);
|
glBegin(GL_LINES);
|
||||||
for (int i=0;i<11;i++) {
|
for (int i=0;i<11;i++) {
|
||||||
float a = 1.0f - abs(i-5)*0.18f;
|
float a = 1.f - abs(i-5)*0.18f;
|
||||||
int pos = 20*(i-5);
|
int pos = 20*(i-5);
|
||||||
glColor4f(r,g,b,0.0f);
|
glColor4f(r,g,b,0.f);
|
||||||
glVertex2i(pos,120);
|
glVertex2i(pos,120);
|
||||||
glColor4f(r,g,b,a);
|
glColor4f(r,g,b,a);
|
||||||
glVertex2i(pos,0);
|
glVertex2i(pos,0);
|
||||||
glVertex2i(pos,0);
|
glVertex2i(pos,0);
|
||||||
glColor4f(r,g,b,0.0f);
|
glColor4f(r,g,b,0.f);
|
||||||
glVertex2i(pos,-120);
|
glVertex2i(pos,-120);
|
||||||
glVertex2i(120,pos);
|
glVertex2i(120,pos);
|
||||||
glColor4f(r,g,b,a);
|
glColor4f(r,g,b,a);
|
||||||
glVertex2i(0,pos);
|
glVertex2i(0,pos);
|
||||||
glVertex2i(0,pos);
|
glVertex2i(0,pos);
|
||||||
glColor4f(r,g,b,0.0f);
|
glColor4f(r,g,b,0.f);
|
||||||
glVertex2i(-120,pos);
|
glVertex2i(-120,pos);
|
||||||
}
|
}
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
// Draw vectors
|
// Draw vectors
|
||||||
SetLineColour(colour[3],1.0f,2);
|
SetLineColour(colour[3],1.f,2);
|
||||||
SetModeLine();
|
SetModeLine();
|
||||||
glBegin(GL_LINES);
|
glBegin(GL_LINES);
|
||||||
glVertex3f(0.0f,0.0f,0.0f);
|
glVertex3f(0.f,0.f,0.f);
|
||||||
glVertex3f(50.0f,0.0f,0.0f);
|
glVertex3f(50.f,0.f,0.f);
|
||||||
glVertex3f(0.0f,0.0f,0.0f);
|
glVertex3f(0.f,0.f,0.f);
|
||||||
glVertex3f(0.0f,50.0f,0.0f);
|
glVertex3f(0.f,50.f,0.f);
|
||||||
glVertex3f(0.0f,0.0f,0.0f);
|
glVertex3f(0.f,0.f,0.f);
|
||||||
glVertex3f(0.0f,0.0f,50.0f);
|
glVertex3f(0.f,0.f,50.f);
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
// Draw arrow tops
|
// Draw arrow tops
|
||||||
glBegin(GL_TRIANGLE_FAN);
|
glBegin(GL_TRIANGLE_FAN);
|
||||||
glVertex3f(60.0f,0.0f,0.0f);
|
glVertex3f(60.f,0.f,0.f);
|
||||||
glVertex3f(50.0f,-3.0f,-3.0f);
|
glVertex3f(50.f,-3.f,-3.f);
|
||||||
glVertex3f(50.0f,3.0f,-3.0f);
|
glVertex3f(50.f,3.f,-3.f);
|
||||||
glVertex3f(50.0f,3.0f,3.0f);
|
glVertex3f(50.f,3.f,3.f);
|
||||||
glVertex3f(50.0f,-3.0f,3.0f);
|
glVertex3f(50.f,-3.f,3.f);
|
||||||
glVertex3f(50.0f,-3.0f,-3.0f);
|
glVertex3f(50.f,-3.f,-3.f);
|
||||||
glEnd();
|
glEnd();
|
||||||
glBegin(GL_TRIANGLE_FAN);
|
glBegin(GL_TRIANGLE_FAN);
|
||||||
glVertex3f(0.0f,60.0f,0.0f);
|
glVertex3f(0.f,60.f,0.f);
|
||||||
glVertex3f(-3.0f,50.0f,-3.0f);
|
glVertex3f(-3.f,50.f,-3.f);
|
||||||
glVertex3f(3.0f,50.0f,-3.0f);
|
glVertex3f(3.f,50.f,-3.f);
|
||||||
glVertex3f(3.0f,50.0f,3.0f);
|
glVertex3f(3.f,50.f,3.f);
|
||||||
glVertex3f(-3.0f,50.0f,3.0f);
|
glVertex3f(-3.f,50.f,3.f);
|
||||||
glVertex3f(-3.0f,50.0f,-3.0f);
|
glVertex3f(-3.f,50.f,-3.f);
|
||||||
glEnd();
|
glEnd();
|
||||||
glBegin(GL_TRIANGLE_FAN);
|
glBegin(GL_TRIANGLE_FAN);
|
||||||
glVertex3f(0.0f,0.0f,60.0f);
|
glVertex3f(0.f,0.f,60.f);
|
||||||
glVertex3f(-3.0f,-3.0f,50.0f);
|
glVertex3f(-3.f,-3.f,50.f);
|
||||||
glVertex3f(3.0f,-3.0f,50.0f);
|
glVertex3f(3.f,-3.f,50.f);
|
||||||
glVertex3f(3.0f,3.0f,50.0f);
|
glVertex3f(3.f,3.f,50.f);
|
||||||
glVertex3f(-3.0f,3.0f,50.0f);
|
glVertex3f(-3.f,3.f,50.f);
|
||||||
glVertex3f(-3.0f,-3.0f,50.0f);
|
glVertex3f(-3.f,-3.f,50.f);
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
// Restore gl's state
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
glShadeModel(GL_FLAT);
|
glShadeModel(GL_FLAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Start holding
|
|
||||||
bool VisualToolRotateXY::InitializeHold() {
|
bool VisualToolRotateXY::InitializeHold() {
|
||||||
if (!curDiag) return false;
|
|
||||||
GetLinePosition(curDiag,odx,ody,orgx,orgy);
|
|
||||||
GetLineRotation(curDiag,origAngleX,origAngleY,rz);
|
|
||||||
startAngleX = (orgy-video.y)*2.f;
|
startAngleX = (orgy-video.y)*2.f;
|
||||||
startAngleY = (video.x-orgx)*2.f;
|
startAngleY = (video.x-orgx)*2.f;
|
||||||
curAngleX = origAngleX;
|
origAngleX = curAngleX;
|
||||||
curAngleY = origAngleY;
|
origAngleY = curAngleY;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Update hold
|
|
||||||
void VisualToolRotateXY::UpdateHold() {
|
void VisualToolRotateXY::UpdateHold() {
|
||||||
float screenAngleX = (orgy-video.y)*2.f;
|
float screenAngleX = (orgy-video.y)*2.f;
|
||||||
float screenAngleY = (video.x-orgx)*2.f;
|
float screenAngleY = (video.x-orgx)*2.f;
|
||||||
|
@ -204,9 +185,7 @@ void VisualToolRotateXY::UpdateHold() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Commit hold
|
|
||||||
void VisualToolRotateXY::CommitHold() {
|
void VisualToolRotateXY::CommitHold() {
|
||||||
SubtitlesGrid *grid = VideoContext::Get()->grid;
|
|
||||||
wxArrayInt sel = grid->GetSelection();
|
wxArrayInt sel = grid->GetSelection();
|
||||||
for (wxArrayInt::const_iterator cur = sel.begin(); cur != sel.end(); ++cur) {
|
for (wxArrayInt::const_iterator cur = sel.begin(); cur != sel.end(); ++cur) {
|
||||||
AssDialogue* line = grid->GetDialogue(*cur);
|
AssDialogue* line = grid->GetDialogue(*cur);
|
||||||
|
@ -216,11 +195,11 @@ void VisualToolRotateXY::CommitHold() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Get \\org pivot
|
|
||||||
void VisualToolRotateXY::PopulateFeatureList() {
|
void VisualToolRotateXY::PopulateFeatureList() {
|
||||||
curDiag = GetActiveDialogueLine();
|
|
||||||
if (!curDiag) return;
|
if (!curDiag) return;
|
||||||
GetLinePosition(curDiag,odx,ody,orgx,orgy);
|
|
||||||
|
int posx, posy;
|
||||||
|
GetLinePosition(curDiag,posx,posy,orgx,orgy);
|
||||||
|
|
||||||
// Set features
|
// Set features
|
||||||
features.resize(1);
|
features.resize(1);
|
||||||
|
@ -231,15 +210,11 @@ void VisualToolRotateXY::PopulateFeatureList() {
|
||||||
feat.type = DRAG_BIG_TRIANGLE;
|
feat.type = DRAG_BIG_TRIANGLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Update dragging of \\org
|
|
||||||
/// @param feature
|
|
||||||
void VisualToolRotateXY::UpdateDrag(VisualDraggableFeature* feature) {
|
void VisualToolRotateXY::UpdateDrag(VisualDraggableFeature* feature) {
|
||||||
orgx = feature->x;
|
orgx = feature->x;
|
||||||
orgy = feature->y;
|
orgy = feature->y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Commit dragging of \\org
|
|
||||||
/// @param feature
|
|
||||||
void VisualToolRotateXY::CommitDrag(VisualDraggableFeature* feature) {
|
void VisualToolRotateXY::CommitDrag(VisualDraggableFeature* feature) {
|
||||||
int x = feature->x;
|
int x = feature->x;
|
||||||
int y = feature->y;
|
int y = feature->y;
|
||||||
|
@ -247,11 +222,9 @@ void VisualToolRotateXY::CommitDrag(VisualDraggableFeature* feature) {
|
||||||
SetOverride(feature->line, L"\\org",wxString::Format(L"(%i,%i)",x,y));
|
SetOverride(feature->line, L"\\org",wxString::Format(L"(%i,%i)",x,y));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Refresh
|
|
||||||
void VisualToolRotateXY::DoRefresh() {
|
void VisualToolRotateXY::DoRefresh() {
|
||||||
AssDialogue *line = GetActiveDialogueLine();
|
if (!curDiag) return;
|
||||||
if (!line) return;
|
int posx, posy;
|
||||||
GetLinePosition(line,odx,ody,orgx,orgy);
|
GetLinePosition(curDiag,posx,posy,orgx,orgy);
|
||||||
GetLineRotation(line,curAngleX,curAngleY,rz);
|
GetLineRotation(curDiag,curAngleX,curAngleY,curAngleZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,53 +41,23 @@
|
||||||
/// @class VisualToolRotateXY
|
/// @class VisualToolRotateXY
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
class VisualToolRotateXY : public VisualTool<VisualDraggableFeature> {
|
class VisualToolRotateXY : public VisualTool<VisualDraggableFeature> {
|
||||||
private:
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
float curAngleX,startAngleX,origAngleX;
|
float curAngleX,startAngleX,origAngleX;
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
float curAngleY,startAngleY,origAngleY;
|
float curAngleY,startAngleY,origAngleY;
|
||||||
|
float curAngleZ;
|
||||||
|
int orgx,orgy;
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
int orgx,orgy,odx,ody;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
float rz;
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
bool InitializeHold();
|
bool InitializeHold();
|
||||||
void UpdateHold();
|
void UpdateHold();
|
||||||
void CommitHold();
|
void CommitHold();
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
|
||||||
///
|
|
||||||
void PopulateFeatureList();
|
void PopulateFeatureList();
|
||||||
void UpdateDrag(VisualDraggableFeature* feature);
|
void UpdateDrag(VisualDraggableFeature* feature);
|
||||||
void CommitDrag(VisualDraggableFeature* feature);
|
void CommitDrag(VisualDraggableFeature* feature);
|
||||||
|
|
||||||
void DoRefresh();
|
void DoRefresh();
|
||||||
|
|
||||||
|
void Draw();
|
||||||
public:
|
public:
|
||||||
VisualToolRotateXY(VideoDisplay *parent, VideoState const& video, wxToolBar *);
|
VisualToolRotateXY(VideoDisplay *parent, VideoState const& video, wxToolBar *);
|
||||||
|
|
||||||
void Draw();
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <math.h>
|
#include <cmath>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "ass_dialogue.h"
|
#include "ass_dialogue.h"
|
||||||
|
@ -48,50 +48,27 @@
|
||||||
#include "video_display.h"
|
#include "video_display.h"
|
||||||
#include "visual_tool_rotatez.h"
|
#include "visual_tool_rotatez.h"
|
||||||
|
|
||||||
/// @brief Constructor
|
static const float deg2rad = 3.1415926536f / 180.f;
|
||||||
/// @param _parent
|
static const float rad2deg = 180.f / 3.1415926536f;
|
||||||
|
|
||||||
VisualToolRotateZ::VisualToolRotateZ(VideoDisplay *parent, VideoState const& video, wxToolBar *)
|
VisualToolRotateZ::VisualToolRotateZ(VideoDisplay *parent, VideoState const& video, wxToolBar *)
|
||||||
: VisualTool<VisualDraggableFeature>(parent, video)
|
: VisualTool<VisualDraggableFeature>(parent, video)
|
||||||
{
|
{
|
||||||
DoRefresh();
|
DoRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Draw
|
|
||||||
void VisualToolRotateZ::Draw() {
|
void VisualToolRotateZ::Draw() {
|
||||||
// Get line to draw
|
if (!curDiag) return;
|
||||||
AssDialogue *line = GetActiveDialogueLine();
|
|
||||||
if (!line) return;
|
|
||||||
|
|
||||||
// Draw pivot
|
// Draw pivot
|
||||||
DrawAllFeatures();
|
DrawAllFeatures();
|
||||||
|
|
||||||
// Radius
|
int radius = (int)sqrt(double((posx-orgx)*(posx-orgx)+(posy-orgy)*(posy-orgy)));
|
||||||
int dx=0,dy=0;
|
|
||||||
if (dragging) GetLinePosition(line,dx,dy);
|
|
||||||
else GetLinePosition(line,dx,dy,orgx,orgy);
|
|
||||||
int radius = (int) sqrt(double((dx-orgx)*(dx-orgx)+(dy-orgy)*(dy-orgy)));
|
|
||||||
int oRadius = radius;
|
int oRadius = radius;
|
||||||
if (radius < 50) radius = 50;
|
if (radius < 50) radius = 50;
|
||||||
|
|
||||||
// Pivot coordinates
|
int deltax = int(cos(curAngle*deg2rad)*radius);
|
||||||
int odx = dx;
|
int deltay = int(-sin(curAngle*deg2rad)*radius);
|
||||||
int ody = dy;
|
|
||||||
dx = orgx;
|
|
||||||
dy = orgy;
|
|
||||||
|
|
||||||
// Rotation
|
|
||||||
float rz;
|
|
||||||
GetLineRotation(line,rx,ry,rz);
|
|
||||||
if (line == curDiag) rz = curAngle;
|
|
||||||
|
|
||||||
// Get scale
|
|
||||||
float scalX = 100.0f;
|
|
||||||
float scalY = 100.0f;
|
|
||||||
GetLineScale(line,scalX,scalY);
|
|
||||||
|
|
||||||
// Get deltas
|
|
||||||
int deltax = int(cos(rz*3.1415926536/180.0)*radius);
|
|
||||||
int deltay = int(-sin(rz*3.1415926536/180.0)*radius);
|
|
||||||
|
|
||||||
// Set colours
|
// Set colours
|
||||||
SetLineColour(colour[0]);
|
SetLineColour(colour[0]);
|
||||||
|
@ -101,84 +78,76 @@ void VisualToolRotateZ::Draw() {
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glTranslatef(dx,dy,-1.0f);
|
glTranslatef(orgx,orgy,-1.f);
|
||||||
float matrix[16] = { 2500, 0, 0, 0, 0, 2500, 0, 0, 0, 0, 1, 1, 0, 0, 2500, 2500 };
|
float matrix[16] = { 2500, 0, 0, 0, 0, 2500, 0, 0, 0, 0, 1, 1, 0, 0, 2500, 2500 };
|
||||||
glMultMatrixf(matrix);
|
glMultMatrixf(matrix);
|
||||||
glScalef(1.0f,1.0f,8.0f);
|
glScalef(1.f,1.f,8.f);
|
||||||
glRotatef(ry,0.0f,-1.0f,0.0f);
|
glRotatef(ry,0.f,-1.f,0.f);
|
||||||
glRotatef(rx,-1.0f,0.0f,0.0f);
|
glRotatef(rx,-1.f,0.f,0.f);
|
||||||
glScalef(scalX/100.0f,scalY/100.0f,1.0f);
|
glScalef(scaleX/100.f,scaleY/100.f,1.f);
|
||||||
|
|
||||||
// Draw the circle
|
// Draw the circle
|
||||||
DrawRing(0,0,radius+4,radius-4);
|
DrawRing(0,0,radius+4,radius-4);
|
||||||
|
|
||||||
// Draw markers around circle
|
// Draw markers around circle
|
||||||
int markers = 6;
|
int markers = 6;
|
||||||
float markStart = -90.0f / markers;
|
float markStart = -90.f / markers;
|
||||||
float markEnd = markStart+(180.0f/markers);
|
float markEnd = markStart+(180.f/markers);
|
||||||
for (int i=0;i<markers;i++) {
|
for (int i=0;i<markers;i++) {
|
||||||
float angle = i*(360.0f/markers);
|
float angle = i*(360.f/markers);
|
||||||
DrawRing(0,0,radius+30,radius+12,radius/radius,angle+markStart,angle+markEnd);
|
DrawRing(0,0,radius+30,radius+12,radius/radius,angle+markStart,angle+markEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the baseline
|
// Draw the baseline
|
||||||
SetLineColour(colour[3],1.0f,2);
|
SetLineColour(colour[3],1.f,2);
|
||||||
DrawLine(deltax,deltay,-deltax,-deltay);
|
DrawLine(deltax,deltay,-deltax,-deltay);
|
||||||
|
|
||||||
// Draw the connection line
|
// Draw the connection line
|
||||||
if (orgx != odx && orgy != ody) {
|
if (orgx != posx || orgy != posy) {
|
||||||
double angle = atan2(double(dy-ody),double(odx-dx)) + rz*3.1415926536/180.0;
|
double angle = atan2(double(orgy-posy),double(posx-orgx)) + curAngle*deg2rad;
|
||||||
int fx = int(cos(angle)*oRadius);
|
int fx = int(cos(angle)*oRadius);
|
||||||
int fy = -int(sin(angle)*oRadius);
|
int fy = -int(sin(angle)*oRadius);
|
||||||
DrawLine(0,0,fx,fy);
|
DrawLine(0,0,fx,fy);
|
||||||
int mdx = int(cos(rz*3.1415926536/180.0)*20);
|
int mdx = int(cos(curAngle*deg2rad)*20);
|
||||||
int mdy = int(-sin(rz*3.1415926536/180.0)*20);
|
int mdy = int(-sin(curAngle*deg2rad)*20);
|
||||||
DrawLine(fx-mdx,fy-mdy,fx+mdx,fy+mdy);
|
DrawLine(fx-mdx,fy-mdy,fx+mdx,fy+mdy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the rotation line
|
// Draw the rotation line
|
||||||
SetLineColour(colour[0],1.0f,1);
|
SetLineColour(colour[0],1.f,1);
|
||||||
SetFillColour(colour[1],0.3f);
|
SetFillColour(colour[1],0.3f);
|
||||||
DrawCircle(deltax,deltay,4);
|
DrawCircle(deltax,deltay,4);
|
||||||
|
|
||||||
// Restore
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
// Draw line to mouse
|
// Draw line to mouse
|
||||||
if (!dragging && !curFeature && video.x > INT_MIN && video.y > INT_MIN) {
|
if (!dragging && !curFeature && video.x > INT_MIN && video.y > INT_MIN) {
|
||||||
SetLineColour(colour[0]);
|
SetLineColour(colour[0]);
|
||||||
DrawLine(dx,dy,video.x,video.y);
|
DrawLine(orgx,orgy,video.x,video.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Start holding
|
|
||||||
bool VisualToolRotateZ::InitializeHold() {
|
bool VisualToolRotateZ::InitializeHold() {
|
||||||
GetLinePosition(curDiag,odx,ody,orgx,orgy);
|
startAngle = atan2(double(orgy-video.y),double(video.x-orgx)) * rad2deg;
|
||||||
startAngle = atan2(double(orgy-video.y),double(video.x-orgx)) * 180.0 / 3.1415926535897932;
|
origAngle = curAngle;
|
||||||
GetLineRotation(curDiag,rx,ry,origAngle);
|
|
||||||
curAngle = origAngle;
|
|
||||||
curDiag->StripTag(L"\\frz");
|
curDiag->StripTag(L"\\frz");
|
||||||
curDiag->StripTag(L"\\fr");
|
curDiag->StripTag(L"\\fr");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Update hold
|
|
||||||
void VisualToolRotateZ::UpdateHold() {
|
void VisualToolRotateZ::UpdateHold() {
|
||||||
// Find angle
|
float screenAngle = atan2(double(orgy-video.y),double(video.x-orgx)) * rad2deg;
|
||||||
float screenAngle = atan2(double(orgy-video.y),double(video.x-orgx)) * 180.0 / 3.1415926535897932;
|
|
||||||
curAngle = fmodf(screenAngle - startAngle + origAngle + 360.f, 360.f);
|
curAngle = fmodf(screenAngle - startAngle + origAngle + 360.f, 360.f);
|
||||||
|
|
||||||
// Oh Snap
|
// Oh Snap
|
||||||
if (ctrlDown) {
|
if (ctrlDown) {
|
||||||
curAngle = floorf(curAngle/30.f+.5f)*30.0f;
|
curAngle = floorf(curAngle/30.f+.5f)*30.f;
|
||||||
if (curAngle > 359.0f) curAngle = 0.0f;
|
if (curAngle > 359.f) curAngle = 0.f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Commit hold
|
|
||||||
void VisualToolRotateZ::CommitHold() {
|
void VisualToolRotateZ::CommitHold() {
|
||||||
SubtitlesGrid *grid = VideoContext::Get()->grid;
|
|
||||||
wxArrayInt sel = grid->GetSelection();
|
wxArrayInt sel = grid->GetSelection();
|
||||||
for (wxArrayInt::const_iterator cur = sel.begin(); cur != sel.end(); ++cur) {
|
for (wxArrayInt::const_iterator cur = sel.begin(); cur != sel.end(); ++cur) {
|
||||||
AssDialogue* line = grid->GetDialogue(*cur);
|
AssDialogue* line = grid->GetDialogue(*cur);
|
||||||
|
@ -187,11 +156,8 @@ void VisualToolRotateZ::CommitHold() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Get \\org pivot
|
|
||||||
void VisualToolRotateZ::PopulateFeatureList() {
|
void VisualToolRotateZ::PopulateFeatureList() {
|
||||||
curDiag = GetActiveDialogueLine();
|
|
||||||
if (!curDiag) return;
|
if (!curDiag) return;
|
||||||
GetLinePosition(curDiag,odx,ody,orgx,orgy);
|
|
||||||
|
|
||||||
// Set features
|
// Set features
|
||||||
features.resize(1);
|
features.resize(1);
|
||||||
|
@ -202,15 +168,11 @@ void VisualToolRotateZ::PopulateFeatureList() {
|
||||||
feat.type = DRAG_BIG_TRIANGLE;
|
feat.type = DRAG_BIG_TRIANGLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Update dragging of \\org
|
|
||||||
/// @param feature
|
|
||||||
void VisualToolRotateZ::UpdateDrag(VisualDraggableFeature* feature) {
|
void VisualToolRotateZ::UpdateDrag(VisualDraggableFeature* feature) {
|
||||||
orgx = feature->x;
|
orgx = feature->x;
|
||||||
orgy = feature->y;
|
orgy = feature->y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Commit dragging of \\org
|
|
||||||
/// @param feature
|
|
||||||
void VisualToolRotateZ::CommitDrag(VisualDraggableFeature* feature) {
|
void VisualToolRotateZ::CommitDrag(VisualDraggableFeature* feature) {
|
||||||
int x = feature->x;
|
int x = feature->x;
|
||||||
int y = feature->y;
|
int y = feature->y;
|
||||||
|
@ -218,10 +180,9 @@ void VisualToolRotateZ::CommitDrag(VisualDraggableFeature* feature) {
|
||||||
SetOverride(feature->line, L"\\org",wxString::Format(L"(%i,%i)",x,y));
|
SetOverride(feature->line, L"\\org",wxString::Format(L"(%i,%i)",x,y));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Refresh
|
|
||||||
void VisualToolRotateZ::DoRefresh() {
|
void VisualToolRotateZ::DoRefresh() {
|
||||||
AssDialogue *line = GetActiveDialogueLine();
|
if (!curDiag) return;
|
||||||
if (!line) return;
|
GetLinePosition(curDiag, posx, posy, orgx, orgy);
|
||||||
GetLinePosition(line,odx,ody,orgx,orgy);
|
GetLineRotation(curDiag, rx, ry, curAngle);
|
||||||
GetLineRotation(line,rx,ry,curAngle);
|
GetLineScale(curDiag, scaleX, scaleY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,49 +44,24 @@
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// DOCME
|
||||||
class VisualToolRotateZ : public VisualTool<VisualDraggableFeature> {
|
class VisualToolRotateZ : public VisualTool<VisualDraggableFeature> {
|
||||||
private:
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
float curAngle, startAngle, origAngle;
|
float curAngle, startAngle, origAngle;
|
||||||
|
int orgx, orgy;
|
||||||
/// DOCME
|
int posx, posy;
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
int orgx,orgy,odx,ody;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
float rx, ry;
|
float rx, ry;
|
||||||
|
float scaleX, scaleY;
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
bool InitializeHold();
|
bool InitializeHold();
|
||||||
void UpdateHold();
|
void UpdateHold();
|
||||||
void CommitHold();
|
void CommitHold();
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
|
||||||
///
|
|
||||||
void PopulateFeatureList();
|
void PopulateFeatureList();
|
||||||
void UpdateDrag(VisualDraggableFeature* feature);
|
void UpdateDrag(VisualDraggableFeature* feature);
|
||||||
void CommitDrag(VisualDraggableFeature* feature);
|
void CommitDrag(VisualDraggableFeature* feature);
|
||||||
|
|
||||||
void DoRefresh();
|
void DoRefresh();
|
||||||
|
|
||||||
public:
|
|
||||||
VisualToolRotateZ(VideoDisplay *parent, VideoState const& video, wxToolBar *);
|
|
||||||
|
|
||||||
void Draw();
|
void Draw();
|
||||||
bool Update() { return true; }
|
bool Update() { return true; }
|
||||||
|
public:
|
||||||
|
VisualToolRotateZ(VideoDisplay *parent, VideoState const& video, wxToolBar *);
|
||||||
};
|
};
|
||||||
|
|
|
@ -48,42 +48,25 @@
|
||||||
#include "video_display.h"
|
#include "video_display.h"
|
||||||
#include "visual_tool_scale.h"
|
#include "visual_tool_scale.h"
|
||||||
|
|
||||||
/// @brief Constructor
|
|
||||||
/// @param _parent
|
|
||||||
VisualToolScale::VisualToolScale(VideoDisplay *parent, VideoState const& video, wxToolBar *)
|
VisualToolScale::VisualToolScale(VideoDisplay *parent, VideoState const& video, wxToolBar *)
|
||||||
: VisualTool<VisualDraggableFeature>(parent, video)
|
: VisualTool<VisualDraggableFeature>(parent, video)
|
||||||
, curScaleX(0.f)
|
, curScaleX(0.f)
|
||||||
, startScaleX(0.f)
|
|
||||||
, origScaleX(0.f)
|
, origScaleX(0.f)
|
||||||
, curScaleY(0.f)
|
, curScaleY(0.f)
|
||||||
, startScaleY(0.f)
|
|
||||||
, origScaleY(0.f)
|
, origScaleY(0.f)
|
||||||
, startX(0)
|
, startX(0)
|
||||||
, startY(0)
|
, startY(0)
|
||||||
{
|
{
|
||||||
|
DoRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Draw
|
|
||||||
void VisualToolScale::Draw() {
|
void VisualToolScale::Draw() {
|
||||||
// Get line to draw
|
if (!curDiag) return;
|
||||||
AssDialogue *line = GetActiveDialogueLine();
|
|
||||||
if (!line) return;
|
|
||||||
|
|
||||||
// Get scale
|
|
||||||
if (line != curDiag) GetLineScale(line,curScaleX,curScaleY);
|
|
||||||
|
|
||||||
// Get line position and rotation
|
|
||||||
int dx,dy;
|
|
||||||
float rx,ry,rz;
|
|
||||||
GetLinePosition(line,dx,dy);
|
|
||||||
GetLineRotation(line,rx,ry,rz);
|
|
||||||
|
|
||||||
// Set dx/dy
|
|
||||||
int len = 160;
|
int len = 160;
|
||||||
dx = MID(len/2+10,dx,video.w-len/2-30);
|
int dx = MID(len/2+10,posx,video.w-len/2-30);
|
||||||
dy = MID(len/2+10,dy,video.h-len/2-30);
|
int dy = MID(len/2+10,posy,video.h-len/2-30);
|
||||||
|
|
||||||
// Set colours
|
|
||||||
SetLineColour(colour[0]);
|
SetLineColour(colour[0]);
|
||||||
SetFillColour(colour[1],0.3f);
|
SetFillColour(colour[1],0.3f);
|
||||||
|
|
||||||
|
@ -91,13 +74,13 @@ void VisualToolScale::Draw() {
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glTranslatef(dx,dy,0.0f);
|
glTranslatef(dx,dy,0.f);
|
||||||
float matrix[16] = { 2500, 0, 0, 0, 0, 2500, 0, 0, 0, 0, 1, 1, 0, 0, 2500, 2500 };
|
float matrix[16] = { 2500, 0, 0, 0, 0, 2500, 0, 0, 0, 0, 1, 1, 0, 0, 2500, 2500 };
|
||||||
glMultMatrixf(matrix);
|
glMultMatrixf(matrix);
|
||||||
glScalef(1.0f,1.0f,8.0f);
|
glScalef(1.f,1.f,8.f);
|
||||||
if (ry != 0.0f) glRotatef(ry,0.0f,-1.0f,0.0f);
|
if (ry != 0.f) glRotatef(ry,0.f,-1.f,0.f);
|
||||||
if (rx != 0.0f) glRotatef(rx,-1.0f,0.0f,0.0f);
|
if (rx != 0.f) glRotatef(rx,-1.f,0.f,0.f);
|
||||||
if (rz != 0.0f) glRotatef(rz,0.0f,0.0f,-1.0f);
|
if (rz != 0.f) glRotatef(rz,0.f,0.f,-1.f);
|
||||||
|
|
||||||
// Scale parameters
|
// Scale parameters
|
||||||
int lenx = int(1.6 * curScaleX);
|
int lenx = int(1.6 * curScaleX);
|
||||||
|
@ -106,46 +89,42 @@ void VisualToolScale::Draw() {
|
||||||
int drawY = len/2 + 10;
|
int drawY = len/2 + 10;
|
||||||
|
|
||||||
// Draw length markers
|
// Draw length markers
|
||||||
SetLineColour(colour[3],1.0f,2);
|
SetLineColour(colour[3],1.f,2);
|
||||||
DrawLine(-lenx/2,drawY+10,lenx/2,drawY+10);
|
DrawLine(-lenx/2,drawY+10,lenx/2,drawY+10);
|
||||||
DrawLine(drawX+10,-leny/2,drawX+10,leny/2);
|
DrawLine(drawX+10,-leny/2,drawX+10,leny/2);
|
||||||
SetLineColour(colour[0],1.0f,1);
|
SetLineColour(colour[0],1.f,1);
|
||||||
SetFillColour(colour[1],0.3f);
|
SetFillColour(colour[1],0.3f);
|
||||||
DrawCircle(lenx/2,drawY+10,4);
|
DrawCircle(lenx/2,drawY+10,4);
|
||||||
DrawCircle(drawX+10,-leny/2,4);
|
DrawCircle(drawX+10,-leny/2,4);
|
||||||
|
|
||||||
// Draw horizontal scale
|
// Draw horizontal scale
|
||||||
SetLineColour(colour[0],1.0f,1);
|
SetLineColour(colour[0],1.f,1);
|
||||||
DrawRectangle(-len/2,drawY,len/2+1,drawY+5);
|
DrawRectangle(-len/2,drawY,len/2+1,drawY+5);
|
||||||
SetLineColour(colour[0],1.0f,2);
|
SetLineColour(colour[0],1.f,2);
|
||||||
DrawLine(-len/2+1,drawY+5,-len/2+1,drawY+15);
|
DrawLine(-len/2+1,drawY+5,-len/2+1,drawY+15);
|
||||||
DrawLine(len/2,drawY+5,len/2,drawY+15);
|
DrawLine(len/2,drawY+5,len/2,drawY+15);
|
||||||
|
|
||||||
// Draw vertical scale
|
// Draw vertical scale
|
||||||
SetLineColour(colour[0],1.0f,1);
|
SetLineColour(colour[0],1.f,1);
|
||||||
DrawRectangle(drawX,-len/2,drawX+5,len/2+1);
|
DrawRectangle(drawX,-len/2,drawX+5,len/2+1);
|
||||||
SetLineColour(colour[0],1.0f,2);
|
SetLineColour(colour[0],1.f,2);
|
||||||
DrawLine(drawX+5,-len/2+1,drawX+15,-len/2+1);
|
DrawLine(drawX+5,-len/2+1,drawX+15,-len/2+1);
|
||||||
DrawLine(drawX+5,len/2,drawX+15,len/2);
|
DrawLine(drawX+5,len/2,drawX+15,len/2);
|
||||||
|
|
||||||
// Restore gl's state
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Start holding
|
|
||||||
bool VisualToolScale::InitializeHold() {
|
bool VisualToolScale::InitializeHold() {
|
||||||
startX = video.x;
|
startX = video.x;
|
||||||
startY = video.y;
|
startY = video.y;
|
||||||
GetLineScale(curDiag,origScaleX,origScaleY);
|
origScaleX = curScaleX;
|
||||||
curScaleX = origScaleX;
|
origScaleY = curScaleY;
|
||||||
curScaleY = origScaleY;
|
|
||||||
curDiag->StripTag(L"\\fscx");
|
curDiag->StripTag(L"\\fscx");
|
||||||
curDiag->StripTag(L"\\fscy");
|
curDiag->StripTag(L"\\fscy");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Update hold
|
|
||||||
void VisualToolScale::UpdateHold() {
|
void VisualToolScale::UpdateHold() {
|
||||||
using std::max;
|
using std::max;
|
||||||
// Deltas
|
// Deltas
|
||||||
|
@ -162,14 +141,12 @@ void VisualToolScale::UpdateHold() {
|
||||||
|
|
||||||
// Oh Snap
|
// Oh Snap
|
||||||
if (ctrlDown) {
|
if (ctrlDown) {
|
||||||
curScaleX = floorf(curScaleX/25.f+.5f)*25.0f;
|
curScaleX = floorf(curScaleX/25.f+.5f)*25.f;
|
||||||
curScaleY = floorf(curScaleY/25.f+.5f)*25.0f;
|
curScaleY = floorf(curScaleY/25.f+.5f)*25.f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Commit hold
|
|
||||||
void VisualToolScale::CommitHold() {
|
void VisualToolScale::CommitHold() {
|
||||||
SubtitlesGrid *grid = VideoContext::Get()->grid;
|
|
||||||
wxArrayInt sel = grid->GetSelection();
|
wxArrayInt sel = grid->GetSelection();
|
||||||
for (wxArrayInt::const_iterator cur = sel.begin(); cur != sel.end(); ++cur) {
|
for (wxArrayInt::const_iterator cur = sel.begin(); cur != sel.end(); ++cur) {
|
||||||
AssDialogue* line = grid->GetDialogue(*cur);
|
AssDialogue* line = grid->GetDialogue(*cur);
|
||||||
|
@ -178,3 +155,11 @@ void VisualToolScale::CommitHold() {
|
||||||
SetOverride(line, L"\\fscy",wxString::Format(L"(%0.3g)",curScaleY));
|
SetOverride(line, L"\\fscy",wxString::Format(L"(%0.3g)",curScaleY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VisualToolScale::DoRefresh() {
|
||||||
|
if (!curDiag) return;
|
||||||
|
|
||||||
|
GetLineScale(curDiag, curScaleX, curScaleY);
|
||||||
|
GetLinePosition(curDiag, posx, posy);
|
||||||
|
GetLineRotation(curDiag, rx, ry, rz);
|
||||||
|
}
|
||||||
|
|
|
@ -41,36 +41,20 @@
|
||||||
/// @class VisualToolScale
|
/// @class VisualToolScale
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
class VisualToolScale : public VisualTool<VisualDraggableFeature> {
|
class VisualToolScale : public VisualTool<VisualDraggableFeature> {
|
||||||
private:
|
float curScaleX, origScaleX;
|
||||||
|
float curScaleY, origScaleY;
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
float curScaleX,startScaleX,origScaleX;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
float curScaleY,startScaleY,origScaleY;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
int startX, startY;
|
int startX, startY;
|
||||||
|
int posx, posy;
|
||||||
|
float rx, ry, rz;
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
|
||||||
///
|
|
||||||
bool InitializeHold();
|
bool InitializeHold();
|
||||||
void UpdateHold();
|
void UpdateHold();
|
||||||
void CommitHold();
|
void CommitHold();
|
||||||
|
|
||||||
|
void DoRefresh();
|
||||||
|
void Draw();
|
||||||
public:
|
public:
|
||||||
VisualToolScale(VideoDisplay *parent, VideoState const& video, wxToolBar *);
|
VisualToolScale(VideoDisplay *parent, VideoState const& video, wxToolBar *);
|
||||||
|
|
||||||
void Draw();
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
#include "video_display.h"
|
#include "video_display.h"
|
||||||
#include "visual_tool_vector_clip.h"
|
#include "visual_tool_vector_clip.h"
|
||||||
|
|
||||||
|
/// Button IDs
|
||||||
enum {
|
enum {
|
||||||
BUTTON_DRAG = VISUAL_SUB_TOOL_START,
|
BUTTON_DRAG = VISUAL_SUB_TOOL_START,
|
||||||
BUTTON_LINE,
|
BUTTON_LINE,
|
||||||
|
@ -68,17 +69,11 @@ enum {
|
||||||
BUTTON_LAST // Leave this at the end and don't use it
|
BUTTON_LAST // Leave this at the end and don't use it
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Constructor
|
|
||||||
/// @param parent
|
|
||||||
/// @param _toolBar
|
|
||||||
VisualToolVectorClip::VisualToolVectorClip(VideoDisplay *parent, VideoState const& video, wxToolBar * toolBar)
|
VisualToolVectorClip::VisualToolVectorClip(VideoDisplay *parent, VideoState const& video, wxToolBar * toolBar)
|
||||||
: VisualTool<VisualToolVectorClipDraggableFeature>(parent, video)
|
: VisualTool<VisualToolVectorClipDraggableFeature>(parent, video)
|
||||||
, spline(*parent)
|
, spline(*parent)
|
||||||
, toolBar(toolBar)
|
, toolBar(toolBar)
|
||||||
{
|
{
|
||||||
DoRefresh();
|
|
||||||
mode = 0;
|
|
||||||
|
|
||||||
// Create toolbar
|
// Create toolbar
|
||||||
toolBar->AddTool(BUTTON_DRAG,_("Drag"),GETIMAGE(visual_vector_clip_drag_24),_("Drag control points."),wxITEM_CHECK);
|
toolBar->AddTool(BUTTON_DRAG,_("Drag"),GETIMAGE(visual_vector_clip_drag_24),_("Drag control points."),wxITEM_CHECK);
|
||||||
toolBar->AddTool(BUTTON_LINE,_("Line"),GETIMAGE(visual_vector_clip_line_24),_("Appends a line."),wxITEM_CHECK);
|
toolBar->AddTool(BUTTON_LINE,_("Line"),GETIMAGE(visual_vector_clip_line_24),_("Appends a line."),wxITEM_CHECK);
|
||||||
|
@ -94,9 +89,8 @@ VisualToolVectorClip::VisualToolVectorClip(VideoDisplay *parent, VideoState cons
|
||||||
toolBar->Realize();
|
toolBar->Realize();
|
||||||
toolBar->Show(true);
|
toolBar->Show(true);
|
||||||
|
|
||||||
// Set default mode
|
DoRefresh();
|
||||||
PopulateFeatureList();
|
SetMode(features.empty());
|
||||||
if (features.size() == 0) SetMode(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualToolVectorClip::OnSubTool(wxCommandEvent &event) {
|
void VisualToolVectorClip::OnSubTool(wxCommandEvent &event) {
|
||||||
|
@ -124,13 +118,11 @@ static bool is_move(SplineCurve const& c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualToolVectorClip::Draw() {
|
void VisualToolVectorClip::Draw() {
|
||||||
|
if (!curDiag) return;
|
||||||
if (spline.empty()) return;
|
if (spline.empty()) return;
|
||||||
|
|
||||||
GL_EXT(PFNGLMULTIDRAWARRAYSPROC, glMultiDrawArrays);
|
GL_EXT(PFNGLMULTIDRAWARRAYSPROC, glMultiDrawArrays);
|
||||||
|
|
||||||
AssDialogue *line = GetActiveDialogueLine();
|
|
||||||
if (!line) return;
|
|
||||||
|
|
||||||
// Parse vector
|
// Parse vector
|
||||||
std::vector<float> points;
|
std::vector<float> points;
|
||||||
std::vector<int> start;
|
std::vector<int> start;
|
||||||
|
@ -170,7 +162,7 @@ void VisualToolVectorClip::Draw() {
|
||||||
|
|
||||||
// Draw the actual rectangle
|
// Draw the actual rectangle
|
||||||
glColorMask(1,1,1,1);
|
glColorMask(1,1,1,1);
|
||||||
SetLineColour(colour[3],0.0f);
|
SetLineColour(colour[3],0.f);
|
||||||
SetFillColour(wxColour(0,0,0),0.5f);
|
SetFillColour(wxColour(0,0,0),0.5f);
|
||||||
|
|
||||||
// VSFilter draws when the winding number is nonzero, so we want to draw the
|
// VSFilter draws when the winding number is nonzero, so we want to draw the
|
||||||
|
@ -181,8 +173,8 @@ void VisualToolVectorClip::Draw() {
|
||||||
glDisable(GL_STENCIL_TEST);
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
|
||||||
// Draw lines
|
// Draw lines
|
||||||
SetFillColour(colour[3],0.0f);
|
SetFillColour(colour[3],0.f);
|
||||||
SetLineColour(colour[3],1.0f,2);
|
SetLineColour(colour[3],1.f,2);
|
||||||
SetModeLine();
|
SetModeLine();
|
||||||
glMultiDrawArrays(GL_LINE_LOOP, &start[0], &count[0], start.size());
|
glMultiDrawArrays(GL_LINE_LOOP, &start[0], &count[0], start.size());
|
||||||
|
|
||||||
|
@ -272,7 +264,6 @@ void VisualToolVectorClip::MakeFeature(Spline::iterator cur) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Populate feature list
|
|
||||||
void VisualToolVectorClip::PopulateFeatureList() {
|
void VisualToolVectorClip::PopulateFeatureList() {
|
||||||
features.clear();
|
features.clear();
|
||||||
// This is perhaps a bit conservative as there can be up to 3N+1 features
|
// This is perhaps a bit conservative as there can be up to 3N+1 features
|
||||||
|
@ -283,21 +274,14 @@ void VisualToolVectorClip::PopulateFeatureList() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Update
|
|
||||||
/// @param feature
|
|
||||||
void VisualToolVectorClip::UpdateDrag(VisualToolVectorClipDraggableFeature* feature) {
|
void VisualToolVectorClip::UpdateDrag(VisualToolVectorClipDraggableFeature* feature) {
|
||||||
spline.MovePoint(feature->curve,feature->point,Vector2D(feature->x,feature->y));
|
spline.MovePoint(feature->curve,feature->point,Vector2D(feature->x,feature->y));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Commit
|
void VisualToolVectorClip::CommitDrag(VisualToolVectorClipDraggableFeature*) {
|
||||||
/// @param feature
|
SetOverride(curDiag, inverse ? L"\\iclip" : L"\\clip", L"(" + spline.EncodeToASS() + L")");
|
||||||
void VisualToolVectorClip::CommitDrag(VisualToolVectorClipDraggableFeature* feature) {
|
|
||||||
SetOverride(GetActiveDialogueLine(), inverse ? L"\\iclip" : L"\\clip", L"(" + spline.EncodeToASS() + L")");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Clicked a feature
|
|
||||||
/// @param feature
|
|
||||||
/// @return
|
|
||||||
bool VisualToolVectorClip::InitializeDrag(VisualToolVectorClipDraggableFeature* feature) {
|
bool VisualToolVectorClip::InitializeDrag(VisualToolVectorClipDraggableFeature* feature) {
|
||||||
// Delete a control point
|
// Delete a control point
|
||||||
if (mode == 5) {
|
if (mode == 5) {
|
||||||
|
@ -319,15 +303,13 @@ bool VisualToolVectorClip::InitializeDrag(VisualToolVectorClipDraggableFeature*
|
||||||
CommitDrag(feature);
|
CommitDrag(feature);
|
||||||
curFeature = NULL;
|
curFeature = NULL;
|
||||||
PopulateFeatureList();
|
PopulateFeatureList();
|
||||||
ClearSelection(false);
|
ClearSelection();
|
||||||
Commit(true);
|
Commit(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Initialize hold
|
|
||||||
/// @return
|
|
||||||
bool VisualToolVectorClip::InitializeHold() {
|
bool VisualToolVectorClip::InitializeHold() {
|
||||||
// Insert line/bicubic
|
// Insert line/bicubic
|
||||||
if (mode == 1 || mode == 2) {
|
if (mode == 1 || mode == 2) {
|
||||||
|
@ -348,7 +330,7 @@ bool VisualToolVectorClip::InitializeHold() {
|
||||||
|
|
||||||
// Insert
|
// Insert
|
||||||
spline.push_back(curve);
|
spline.push_back(curve);
|
||||||
ClearSelection(false);
|
ClearSelection();
|
||||||
MakeFeature(--spline.end());
|
MakeFeature(--spline.end());
|
||||||
UpdateHold();
|
UpdateHold();
|
||||||
return true;
|
return true;
|
||||||
|
@ -401,7 +383,7 @@ bool VisualToolVectorClip::InitializeHold() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit
|
// Commit
|
||||||
SetOverride(GetActiveDialogueLine(), inverse ? L"\\iclip" : L"\\clip", L"(" + spline.EncodeToASS() + L")");
|
SetOverride(curDiag, inverse ? L"\\iclip" : L"\\clip", L"(" + spline.EncodeToASS() + L")");
|
||||||
Commit(true);
|
Commit(true);
|
||||||
DoRefresh();
|
DoRefresh();
|
||||||
return false;
|
return false;
|
||||||
|
@ -409,7 +391,7 @@ bool VisualToolVectorClip::InitializeHold() {
|
||||||
|
|
||||||
// Freehand
|
// Freehand
|
||||||
if (mode == 6 || mode == 7) {
|
if (mode == 6 || mode == 7) {
|
||||||
ClearSelection(false);
|
ClearSelection();
|
||||||
features.clear();
|
features.clear();
|
||||||
spline.clear();
|
spline.clear();
|
||||||
SplineCurve curve;
|
SplineCurve curve;
|
||||||
|
@ -422,7 +404,6 @@ bool VisualToolVectorClip::InitializeHold() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Update hold
|
|
||||||
void VisualToolVectorClip::UpdateHold() {
|
void VisualToolVectorClip::UpdateHold() {
|
||||||
// Insert line
|
// Insert line
|
||||||
if (mode == 1) {
|
if (mode == 1) {
|
||||||
|
@ -470,7 +451,6 @@ void VisualToolVectorClip::UpdateHold() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Commit hold
|
|
||||||
void VisualToolVectorClip::CommitHold() {
|
void VisualToolVectorClip::CommitHold() {
|
||||||
// Smooth spline
|
// Smooth spline
|
||||||
if (!holding && mode == 7) {
|
if (!holding && mode == 7) {
|
||||||
|
@ -490,25 +470,19 @@ void VisualToolVectorClip::CommitHold() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Refresh
|
|
||||||
void VisualToolVectorClip::DoRefresh() {
|
void VisualToolVectorClip::DoRefresh() {
|
||||||
if (!dragging && !holding) {
|
if (!curDiag) return;
|
||||||
// Get line
|
|
||||||
AssDialogue *line = GetActiveDialogueLine();
|
|
||||||
if (!line) return;
|
|
||||||
|
|
||||||
// Get clip vector
|
|
||||||
wxString vect;
|
wxString vect;
|
||||||
int scale;
|
int scale;
|
||||||
vect = GetLineVectorClip(line,scale,inverse);
|
vect = GetLineVectorClip(curDiag,scale,inverse);
|
||||||
spline.DecodeFromASS(vect);
|
spline.DecodeFromASS(vect);
|
||||||
SelectAll();
|
SelectAll();
|
||||||
PopulateFeatureList();
|
PopulateFeatureList();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void VisualToolVectorClip::SelectAll() {
|
void VisualToolVectorClip::SelectAll() {
|
||||||
ClearSelection(false);
|
ClearSelection();
|
||||||
for (size_t i = 0; i < features.size(); ++i) {
|
for (size_t i = 0; i < features.size(); ++i) {
|
||||||
AddSelection(i);
|
AddSelection(i);
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,12 +82,11 @@ class VisualToolVectorClip : public VisualTool<VisualToolVectorClipDraggableFeat
|
||||||
bool InitializeDrag(VisualToolVectorClipDraggableFeature* feature);
|
bool InitializeDrag(VisualToolVectorClipDraggableFeature* feature);
|
||||||
|
|
||||||
void DoRefresh();
|
void DoRefresh();
|
||||||
|
void Draw();
|
||||||
|
bool Update() { return mode >= 1 && mode <= 4; }
|
||||||
public:
|
public:
|
||||||
VisualToolVectorClip(VideoDisplay *parent, VideoState const& video, wxToolBar *toolbar);
|
VisualToolVectorClip(VideoDisplay *parent, VideoState const& video, wxToolBar *toolbar);
|
||||||
|
|
||||||
void Draw();
|
|
||||||
bool Update() { return mode >= 1 && mode <= 4; }
|
|
||||||
/// Subtoolbar button click handler
|
/// Subtoolbar button click handler
|
||||||
void OnSubTool(wxCommandEvent &event);
|
void OnSubTool(wxCommandEvent &event);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue