Add selection and control of multiple visual features

Make all visual tools support selecting and manipulating multiple visual
features at once, allowing multiple lines to be moved at once, entire
vector clips to be translated, etc. Controls:

  - Left click: Select control clicked control only
  - Ctrl-left click: Add/remove control to selection
  - Drag control (with or without ctrl): Move all selected controls,
    after setting/adding to selection if target is not in the selection
  - Click on no control: Clear selection

Lots of little stuff to fix still.

Updates #513.

Originally committed to SVN as r4322.
This commit is contained in:
Thomas Goyne 2010-05-20 08:55:58 +00:00
parent 8ff2728322
commit 23972b10bc
17 changed files with 299 additions and 234 deletions

View file

@ -97,24 +97,30 @@ VideoContext *VideoContext::instance = NULL;
/// @brief Constructor /// @brief Constructor
/// ///
VideoContext::VideoContext() VideoContext::VideoContext()
: glContext(NULL) : ownGlContext(false)
, ownGlContext(false) , glContext(NULL)
, audio(NULL)
, provider(NULL) , provider(NULL)
, subsProvider(NULL) , subsProvider(NULL)
, curLine(NULL)
, loaded(false)
, keyFramesLoaded(false) , keyFramesLoaded(false)
, overKeyFramesLoaded(false) , overKeyFramesLoaded(false)
, startFrame(-1)
, endFrame(-1)
, playNextFrame(-1)
, nextFrame(-1)
, loaded(false)
, isPlaying(false)
, keepAudioSync(true)
, w(-1)
, h(-1)
, frame_n(0) , frame_n(0)
, length(0) , length(0)
, fps(0) , fps(0)
, arType(0)
, arValue(1.) , arValue(1.)
, isPlaying(false) , arType(0)
, nextFrame(-1)
, keepAudioSync(true)
, hasSubtitles(false) , hasSubtitles(false)
, grid(NULL)
, curLine(NULL)
, audio(NULL)
{ {
} }

View file

@ -29,7 +29,7 @@
// //
// $Id$ // $Id$
/// @file visual_feature.cpp /// @file visual_feature->cpp
/// @brief Feature on video the user can interact with using mouse /// @brief Feature on video the user can interact with using mouse
/// @ingroup visual_ts /// @ingroup visual_ts
/// ///
@ -43,13 +43,16 @@ VisualDraggableFeature::VisualDraggableFeature()
: type(DRAG_NONE) : type(DRAG_NONE)
, x(INT_MIN) , x(INT_MIN)
, y(INT_MIN) , y(INT_MIN)
, origX(INT_MIN)
, origY(INT_MIN)
, selected(false)
, layer(0) , layer(0)
, line(NULL) , line(NULL)
, lineN(-1) , lineN(-1)
{ {
} }
bool VisualDraggableFeature::IsMouseOver(int mx,int my) { bool VisualDraggableFeature::IsMouseOver(int mx,int my) const {
switch (type) { switch (type) {
case DRAG_BIG_SQUARE: case DRAG_BIG_SQUARE:
return !(mx < x-8 || mx > x+8 || my < y-8 || my > y+8); return !(mx < x-8 || mx > x+8 || my < y-8 || my > y+8);
@ -77,7 +80,7 @@ bool VisualDraggableFeature::IsMouseOver(int mx,int my) {
} }
} }
void VisualDraggableFeature::Draw(OpenGLWrapper const& gl) { void VisualDraggableFeature::Draw(OpenGLWrapper const& gl) const {
switch (type) { switch (type) {
case DRAG_BIG_SQUARE: case DRAG_BIG_SQUARE:
gl.DrawRectangle(x-8,y-8,x+8,y+8); gl.DrawRectangle(x-8,y-8,x+8,y+8);

View file

@ -29,8 +29,8 @@
// //
// $Id$ // $Id$
/// @file visual_feature.h /// @file visual_feature->h
/// @see visual_feature.cpp /// @see visual_feature->cpp
/// @ingroup visual_ts /// @ingroup visual_ts
/// ///
@ -75,6 +75,11 @@ public:
int x; /// x coordinate int x; /// x coordinate
int y; /// y coordinate int y; /// y coordinate
int origX; /// x coordindate before the last operation began
int origY; /// y coordindate before the last operation began
bool selected; ///Iis this feature selected?
int layer; /// Layer; Higher = above int layer; /// Layer; Higher = above
AssDialogue* line; /// The dialogue line this feature is for AssDialogue* line; /// The dialogue line this feature is for
@ -83,8 +88,8 @@ public:
/// @brief Is the given point over this feature? /// @brief Is the given point over this feature?
/// @param mx x coordinate to test /// @param mx x coordinate to test
/// @param my y coordinate to test /// @param my y coordinate to test
bool IsMouseOver(int x,int y); bool IsMouseOver(int x,int y) const;
/// @brief Draw this feature /// @brief Draw this feature
/// @param gl OpenGLWrapper to use /// @param gl OpenGLWrapper to use
void Draw(OpenGLWrapper const& gl); void Draw(OpenGLWrapper const& gl) const;
}; };

View file

@ -67,18 +67,25 @@
const wxColour IVisualTool::colour[4] = {wxColour(106,32,19), wxColour(255,169,40), wxColour(255,253,185), wxColour(187,0,0)}; const wxColour IVisualTool::colour[4] = {wxColour(106,32,19), wxColour(255,169,40), wxColour(255,253,185), wxColour(187,0,0)};
/// @brief Constructor
/// @param parent
template<class FeatureType> template<class FeatureType>
VisualTool<FeatureType>::VisualTool(VideoDisplay *parent, VideoState const& video) VisualTool<FeatureType>::VisualTool(VideoDisplay *parent, VideoState const& video)
: parent(parent) : dragStartX(0)
, dragStartY(0)
, externalChange(true)
, selChanged(false)
, parent(parent)
, holding(false) , holding(false)
, curDiag(NULL) , curDiag(NULL)
, dragging(false) , dragging(false)
, curFeature(-1) , curFeature(NULL)
, dragListOK(false) , dragListOK(false)
, video(video)
, frame_n(0) , frame_n(0)
, video(video)
, leftClick(false)
, leftDClick(false)
, shiftDown(false)
, ctrlDown(false)
, altDown(false)
{ {
if (VideoContext::Get()->IsLoaded()) { if (VideoContext::Get()->IsLoaded()) {
frame_n = VideoContext::Get()->GetFrameN(); frame_n = VideoContext::Get()->GetFrameN();
@ -87,13 +94,10 @@ VisualTool<FeatureType>::VisualTool(VideoDisplay *parent, VideoState const& vide
PopulateFeatureList(); PopulateFeatureList();
} }
/// @brief Destructor
template<class FeatureType> template<class FeatureType>
VisualTool<FeatureType>::~VisualTool() { VisualTool<FeatureType>::~VisualTool() {
} }
/// @brief Mouse event
/// @param event
template<class FeatureType> template<class FeatureType>
void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) { void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
bool realTime = Options.AsBool(L"Video Visual Realtime"); bool realTime = Options.AsBool(L"Video Visual Realtime");
@ -102,6 +106,9 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
Update(); Update();
return; return;
} }
externalChange = false;
VideoContext* con = VideoContext::Get();
leftClick = event.ButtonDown(wxMOUSE_BTN_LEFT); leftClick = event.ButtonDown(wxMOUSE_BTN_LEFT);
leftDClick = event.LeftDClick(); leftDClick = event.LeftDClick();
@ -121,32 +128,62 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
if (dragging) { if (dragging) {
// continue drag // continue drag
if (event.LeftIsDown()) { if (event.LeftIsDown()) {
features[curFeature].x = (video.x - dragStartX + dragOrigX); for (SelFeatureIter cur = selFeatures.begin(); cur != selFeatures.end(); ++cur) {
features[curFeature].y = (video.y - dragStartY + dragOrigY); (*cur)->x = (video.x - dragStartX + (*cur)->origX);
if (shiftDown) { (*cur)->y = (video.y - dragStartY + (*cur)->origY);
if (abs(video.x - dragStartX) > abs(video.y - dragStartY)) { if (shiftDown) {
features[curFeature].y = dragOrigY; if (abs(video.x - dragStartX) > abs(video.y - dragStartY)) {
(*cur)->y = (*cur)->origY;
}
else {
(*cur)->x = (*cur)->origX;
}
} }
else { UpdateDrag(*cur);
features[curFeature].x = dragOrigX;
}
}
UpdateDrag(features[curFeature]);
if (realTime) { if (realTime) {
CommitDrag(features[curFeature]); CommitDrag(*cur);
Commit(); }
} }
if (realTime) Commit();
} }
// end drag // end drag
else { else {
if (realTime) AssLimitToVisibleFilter::SetFrame(-1); if (realTime) AssLimitToVisibleFilter::SetFrame(-1);
dragging = false; dragging = false;
CommitDrag(features[curFeature]);
Commit(true);
curFeature = -1; // mouse didn't move, fiddle with selection
if (curFeature->x == curFeature->origX && curFeature->y == curFeature->origY) {
// Don't deselect stuff that was selected in this click's mousedown event
if (!selChanged) {
if (ctrlDown) {
// deselect this feature
selFeatures.remove(curFeature);
curFeature->selected = false;
if (curFeature->lineN > -1) {
con->grid->SelectRow(curFeature->lineN, true, false);
}
}
else {
// deselect everything else
ClearSelection();
selFeatures.push_back(curFeature);
curFeature->selected = true;
if (curFeature->lineN > -1) {
con->grid->SelectRow(curFeature->lineN, false);
}
}
}
}
else {
for (SelFeatureIter cur = selFeatures.begin(); cur != selFeatures.end(); ++cur) {
CommitDrag(*cur);
}
Commit(true);
}
curFeature = NULL;
parent->ReleaseMouse(); parent->ReleaseMouse();
parent->SetFocus(); parent->SetFocus();
} }
@ -177,17 +214,33 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
else if (leftClick) { else if (leftClick) {
curFeature = GetHighlightedFeature(); curFeature = GetHighlightedFeature();
// start drag // start drag
if (curFeature > -1) { if (curFeature) {
if (InitializeDrag(features[curFeature])) { if (InitializeDrag(curFeature)) {
if (features[curFeature].lineN != -1) { if (!curFeature->selected) {
VideoContext::Get()->grid->editBox->SetToLine(features[curFeature].lineN,true); selChanged = true;
VideoContext::Get()->grid->SelectRow(features[curFeature].lineN); if (!ctrlDown) {
ClearSelection();
}
selFeatures.push_back(curFeature);
curFeature->selected = true;
if (curFeature->lineN != -1) {
con->grid->editBox->SetToLine(curFeature->lineN,true);
con->grid->SelectRow(curFeature->lineN, ctrlDown);
}
}
else {
selChanged = false;
if (curFeature->lineN != -1) {
con->grid->editBox->SetToLine(curFeature->lineN,true);
}
} }
dragStartX = video.x; dragStartX = video.x;
dragStartY = video.y; dragStartY = video.y;
dragOrigX = features[curFeature].x; for (SelFeatureIter cur = selFeatures.begin(); cur != selFeatures.end(); ++cur) {
dragOrigY = features[curFeature].y; (*cur)->origX = (*cur)->x;
(*cur)->origY = (*cur)->y;
}
dragging = true; dragging = true;
parent->CaptureMouse(); parent->CaptureMouse();
@ -196,6 +249,7 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
} }
// start hold // start hold
else { else {
ClearSelection();
curDiag = GetActiveDialogueLine(); curDiag = GetActiveDialogueLine();
if (curDiag && InitializeHold()) { if (curDiag && InitializeHold()) {
holding = true; holding = true;
@ -206,10 +260,9 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
} }
Update(); Update();
externalChange = true;
} }
/// @brief Commit
/// @param full
template<class FeatureType> template<class FeatureType>
void VisualTool<FeatureType>::Commit(bool full) { void VisualTool<FeatureType>::Commit(bool full) {
SubtitlesGrid *grid = VideoContext::Get()->grid; SubtitlesGrid *grid = VideoContext::Get()->grid;
@ -218,8 +271,6 @@ void VisualTool<FeatureType>::Commit(bool full) {
grid->editBox->Update(false, true, false); grid->editBox->Update(false, true, false);
} }
/// @brief Get active dialogue line
/// @return
template<class FeatureType> template<class FeatureType>
AssDialogue* VisualTool<FeatureType>::GetActiveDialogueLine() { AssDialogue* VisualTool<FeatureType>::GetActiveDialogueLine() {
SubtitlesGrid *grid = VideoContext::Get()->grid; SubtitlesGrid *grid = VideoContext::Get()->grid;
@ -236,22 +287,19 @@ AssDialogue* VisualTool<FeatureType>::GetActiveDialogueLine() {
return diag; return diag;
} }
/// @brief Get feature under mouse
/// @return
template<class FeatureType> template<class FeatureType>
int VisualTool<FeatureType>::GetHighlightedFeature() { FeatureType* VisualTool<FeatureType>::GetHighlightedFeature() {
int highestLayerFound = INT_MIN; int highestLayerFound = INT_MIN;
int bestMatch = -1; FeatureType* bestMatch = NULL;
for (size_t i=0;i<features.size();i++) { for (FeatureIter cur = features.begin(); cur != features.end(); ++cur) {
if (features[i].IsMouseOver(video.x, video.y) && features[i].layer > highestLayerFound) { if (cur->IsMouseOver(video.x, video.y) && cur->layer > highestLayerFound) {
bestMatch = i; bestMatch = &*cur;
highestLayerFound = features[i].layer; highestLayerFound = cur->layer;
} }
} }
return bestMatch; return bestMatch;
} }
/// @brief Draw all features
template<class FeatureType> template<class FeatureType>
void VisualTool<FeatureType>::DrawAllFeatures() { void VisualTool<FeatureType>::DrawAllFeatures() {
if (!dragListOK) { if (!dragListOK) {
@ -259,31 +307,40 @@ void VisualTool<FeatureType>::DrawAllFeatures() {
dragListOK = true; dragListOK = true;
} }
int mouseOver = curFeature; FeatureType* mouseOver = curFeature ? curFeature : GetHighlightedFeature();
if (curFeature == -1) mouseOver = GetHighlightedFeature();
for (size_t i=0;i<features.size();i++) { for (FeatureCIter cur = features.begin(); cur != features.end(); ++cur) {
SetFillColour(colour[(signed)i == mouseOver ? 2 : 1],0.6f); int fill = &*cur == mouseOver ? 2 :
cur->selected ? 3 :
1;
SetFillColour(colour[fill],0.6f);
SetLineColour(colour[0],1.0f,2); SetLineColour(colour[0],1.0f,2);
features[i].Draw(*this); cur->Draw(*this);
} }
} }
/// @brief Refresh
template<class FeatureType> template<class FeatureType>
void VisualTool<FeatureType>::Refresh() { void VisualTool<FeatureType>::Refresh() {
frame_n = VideoContext::Get()->GetFrameN(); frame_n = VideoContext::Get()->GetFrameN();
if (!dragging) dragListOK = false; if (externalChange) dragListOK = false;
DoRefresh(); DoRefresh();
} }
template<class FeatureType>
void VisualTool<FeatureType>::ClearSelection() {
for (SelFeatureIter cur = selFeatures.begin(); cur != selFeatures.end(); ++cur) {
(*cur)->selected = false;
}
selFeatures.clear();
}
/// @brief Get position of line /// @brief Get position of line
/// @param diag /// @param diag
/// @param x /// @param x
/// @param y /// @param y
template<class FeatureType> template<class FeatureType>
void VisualTool<FeatureType>::GetLinePosition(AssDialogue *diag,int &x, int &y) { void VisualTool<FeatureType>::GetLinePosition(AssDialogue *diag,int &x, int &y) {
int orgx=0,orgy=0; int orgx,orgy;
GetLinePosition(diag,x,y,orgx,orgy); GetLinePosition(diag,x,y,orgx,orgy);
} }

View file

@ -37,7 +37,6 @@
#ifndef AGI_PRE #ifndef AGI_PRE
#include <vector> #include <vector>
#include "boost/shared_ptr.hpp"
#include <wx/log.h> #include <wx/log.h>
#include <wx/event.h> #include <wx/event.h>
@ -76,56 +75,38 @@ public:
template<class FeatureType> template<class FeatureType>
class VisualTool : public IVisualTool { class VisualTool : public IVisualTool {
private: private:
/// DOCME int dragStartX; /// Starting x coordinate of the current drag, if any
int dragStartY; /// Starting y coordinate of the current drag, if any
/// DOCME /// @brief Get the topmost visual feature under the mouse, or NULL if none are under the mouse
FeatureType* GetHighlightedFeature();
/// DOCME typedef typename std::list<FeatureType*>::iterator SelFeatureIter;
typedef typename std::list<FeatureType>::iterator FeatureIter;
typedef typename std::list<FeatureType>::const_iterator FeatureCIter;
/// DOCME std::list<FeatureType*> selFeatures; /// Currently selected visual features
int dragStartX,dragStartY,dragOrigX,dragOrigY;
int GetHighlightedFeature(); bool externalChange; /// Only invalid drag lists when refreshing due to external changes
bool selChanged; /// Has the selection already been changed in the current click?
protected: protected:
/// DOCME VideoDisplay *parent; /// VideoDisplay which this belongs to, used to frame conversion
VideoDisplay *parent; bool holding; /// Is a hold currently in progress?
AssDialogue *curDiag; /// Active dialogue line for a hold; only valid when holding = true
bool dragging; /// Is a drag currently in progress?
/// DOCME FeatureType* curFeature; /// Topmost feature under the mouse; only valid during a drag?
bool holding; std::list<FeatureType> features; /// List of features which are drawn and can be clicked on
bool dragListOK; /// Do the features not need to be regenerated?
/// DOCME int frame_n; /// Current frame number
AssDialogue *curDiag; VideoState const& video; /// Mouse and video information
/// DOCME bool leftClick; /// Is a left click event currently being processed?
bool dragging; bool leftDClick; /// Is a left double click event currently being processed?
bool shiftDown; /// Is shift down?
/// DOCME bool ctrlDown; /// Is ctrl down?
int curFeature; bool altDown; /// Is alt down?
/// DOCME
std::vector<FeatureType> features;
/// DOCME
bool dragListOK;
/// DOCME
int frame_n;
VideoState const& video;
/// DOCME
bool leftClick;
/// DOCME
bool leftDClick;
/// DOCME
bool shiftDown;
/// DOCME
bool ctrlDown;
/// DOCME
bool altDown;
void GetLinePosition(AssDialogue *diag,int &x,int &y); void GetLinePosition(AssDialogue *diag,int &x,int &y);
void GetLinePosition(AssDialogue *diag,int &x,int &y,int &orgx,int &orgy); void GetLinePosition(AssDialogue *diag,int &x,int &y,int &orgx,int &orgy);
@ -136,58 +117,63 @@ 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(); AssDialogue *GetActiveDialogueLine();
void DrawAllFeatures(); void DrawAllFeatures();
void Commit(bool full=false); void Commit(bool full=false);
/// @brief DOCME /// @brief Called when a hold is begun
/// /// @return Should the hold actually happen?
virtual bool InitializeHold() { return false; } virtual bool InitializeHold() { return false; }
/// @brief DOCME /// @brief Called on every mouse event during a hold
/// virtual void UpdateHold() { }
virtual void UpdateHold() {}
/// @brief DOCME /// @brief Called at the end of a hold
/// @return virtual void CommitHold() { }
///
virtual void CommitHold() {}
/// @brief DOCME /// @brief Called when the feature list needs to be (re)generated
///
virtual void PopulateFeatureList() { } virtual void PopulateFeatureList() { }
/// @brief DOCME /// @brief Called at the beginning of a drag
/// @param feature /// @param feature The visual feature clicked on
/// /// @return Should the drag happen?
virtual bool InitializeDrag(FeatureType &feature) { return true; } virtual bool InitializeDrag(FeatureType* feature) { return true; }
/// @brief DOCME /// @brief Called on every mouse event during a drag
/// @param feature /// @param feature The current feature to process; not necessarily the one clicked on
/// virtual void UpdateDrag(FeatureType* feature) { }
virtual void UpdateDrag(FeatureType &feature) {}
/// @brief DOCME // @brief Called at the end of a drag
/// @param feature virtual void CommitDrag(FeatureType* feature) { }
///
virtual void CommitDrag(FeatureType &feature) {}
/// @brief DOCME /// @brief Called when there's stuff
/// virtual void DoRefresh() { }
virtual void DoRefresh() {}
/// @brief Must be called before removing entries from features
void ClearSelection();
public: public:
/// @brief Handler for all mouse events
/// @param event Shockingly enough, the mouse event
void OnMouseEvent(wxMouseEvent &event); void OnMouseEvent(wxMouseEvent &event);
/// @brief DOCME /// @brief Event handler for the subtoolbar
/// @param event virtual void OnSubTool(wxCommandEvent &) { }
/// /// @brief Called when there's stuff
virtual void OnSubTool(wxCommandEvent &) {}
virtual void Update() { }; virtual void Update() { };
/// @brief Draw stuff
virtual void Draw()=0; virtual void Draw()=0;
/// @brief Called when there's stuff
void Refresh(); void Refresh();
/// @brief Constructor
/// @param parent The VideoDisplay to use for coordinate conversion
/// @param video Video and mouse information passing blob
VisualTool(VideoDisplay *parent, VideoState const& video); VisualTool(VideoDisplay *parent, VideoState const& video);
/// @brief Destructor
virtual ~VisualTool(); virtual ~VisualTool();
}; };

View file

@ -33,8 +33,6 @@
/// @brief Rectangular clipping visual typesetting tool /// @brief Rectangular clipping visual typesetting tool
/// @ingroup visual_ts /// @ingroup visual_ts
///////////
// Headers
#include "config.h" #include "config.h"
#include "ass_dialogue.h" #include "ass_dialogue.h"
@ -48,7 +46,7 @@
/// @brief Constructor /// @brief Constructor
/// @param _parent /// @param _parent
VisualToolClip::VisualToolClip(VideoDisplay *parent, VideoState const& video, wxToolBar *) VisualToolClip::VisualToolClip(VideoDisplay *parent, VideoState const& video, wxToolBar *)
: VisualTool(parent, video) : VisualTool<ClipCorner>(parent, video)
, curX1(0) , curX1(0)
, curY1(0) , curY1(0)
, curX2(video.w) , curX2(video.w)
@ -142,47 +140,52 @@ void VisualToolClip::CommitHold() {
void VisualToolClip::PopulateFeatureList() { void VisualToolClip::PopulateFeatureList() {
// Clear // Clear
if (features.size() != 4) { if (features.size() != 4) {
ClearSelection();
features.clear(); features.clear();
features.resize(4); features.resize(4);
int i = 0;
for (std::list<ClipCorner>::iterator cur = features.begin(); cur != features.end(); ++cur, ++i) {
feat[i] = &*cur;
}
} }
// Top-left // Top-left
int i = 0; int i = 0;
features[i].x = curX1; feat[i]->x = curX1;
features[i].y = curY1; feat[i]->y = curY1;
features[i].horiz = &features[1]; feat[i]->horiz = feat[1];
features[i].vert = &features[2]; feat[i]->vert = feat[2];
features[i].type = DRAG_SMALL_CIRCLE; feat[i]->type = DRAG_SMALL_CIRCLE;
i++; i++;
// Top-right // Top-right
features[i].x = curX2; feat[i]->x = curX2;
features[i].y = curY1; feat[i]->y = curY1;
features[i].horiz = &features[0]; feat[i]->horiz = feat[0];
features[i].vert = &features[3]; feat[i]->vert = feat[3];
features[i].type = DRAG_SMALL_CIRCLE; feat[i]->type = DRAG_SMALL_CIRCLE;
i++; i++;
// Bottom-left // Bottom-left
features[i].x = curX1; feat[i]->x = curX1;
features[i].y = curY2; feat[i]->y = curY2;
features[i].horiz = &features[3]; feat[i]->horiz = feat[3];
features[i].vert = &features[0]; feat[i]->vert = feat[0];
features[i].type = DRAG_SMALL_CIRCLE; feat[i]->type = DRAG_SMALL_CIRCLE;
i++; i++;
// Bottom-right // Bottom-right
features[i].x = curX2; feat[i]->x = curX2;
features[i].y = curY2; feat[i]->y = curY2;
features[i].horiz = &features[2]; feat[i]->horiz = feat[2];
features[i].vert = &features[1]; feat[i]->vert = feat[1];
features[i].type = DRAG_SMALL_CIRCLE; feat[i]->type = DRAG_SMALL_CIRCLE;
i++; i++;
} }
/// @brief Initialize /// @brief Initialize
/// @param feature /// @param feature
bool VisualToolClip::InitializeDrag(ClipCorner &feature) { bool VisualToolClip::InitializeDrag(ClipCorner*) {
curDiag = GetActiveDialogueLine(); curDiag = GetActiveDialogueLine();
curDiag->StripTag(L"\\clip"); curDiag->StripTag(L"\\clip");
curDiag->StripTag(L"\\iclip"); curDiag->StripTag(L"\\iclip");
@ -191,16 +194,16 @@ bool VisualToolClip::InitializeDrag(ClipCorner &feature) {
/// @brief Update drag /// @brief Update drag
/// @param feature /// @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;
feature.vert->x = feature.x; feature->vert->x = feature->x;
// Get "cur" from features // Get "cur" from features
curX1 = features[0].x; curX1 = feat[0]->x;
curX2 = features[3].x; curX2 = feat[3]->x;
curY1 = features[0].y; curY1 = feat[0]->y;
curY2 = features[3].y; curY2 = feat[3]->y;
// Make sure p1 < p2 // Make sure p1 < p2
if (curX1 > curX2) IntSwap(curX1,curX2); if (curX1 > curX2) IntSwap(curX1,curX2);
@ -209,6 +212,6 @@ void VisualToolClip::UpdateDrag(ClipCorner &feature) {
/// @brief Done dragging /// @brief Done dragging
/// @param feature /// @param feature
void VisualToolClip::CommitDrag(ClipCorner &feature) { void VisualToolClip::CommitDrag(ClipCorner*) {
CommitHold(); CommitHold();
} }

View file

@ -75,6 +75,8 @@ private:
/// DOCME /// DOCME
bool inverse; bool inverse;
ClipCorner* feat[4];
/// @brief DOCME /// @brief DOCME
/// @return /// @return
@ -87,9 +89,9 @@ private:
/// @brief DOCME /// @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);
public: public:
VisualToolClip(VideoDisplay *parent, VideoState const& video, wxToolBar *); VisualToolClip(VideoDisplay *parent, VideoState const& video, wxToolBar *);

View file

@ -33,8 +33,6 @@
/// @brief Crosshair double-click-to-position visual typesetting tool /// @brief Crosshair double-click-to-position visual typesetting tool
/// @ingroup visual_ts /// @ingroup visual_ts
///////////
// Headers
#include "config.h" #include "config.h"
#include "ass_file.h" #include "ass_file.h"
@ -48,7 +46,7 @@
/// @brief Constructor /// @brief Constructor
/// @param _parent /// @param _parent
VisualToolCross::VisualToolCross(VideoDisplay *parent, VideoState const& video, wxToolBar *) VisualToolCross::VisualToolCross(VideoDisplay *parent, VideoState const& video, wxToolBar *)
: VisualTool(parent, video) : VisualTool<VisualDraggableFeature>(parent, video)
{ {
} }
VisualToolCross::~VisualToolCross() { } VisualToolCross::~VisualToolCross() { }

View file

@ -54,7 +54,7 @@ enum {
/// @param _parent /// @param _parent
/// @param toolBar /// @param toolBar
VisualToolDrag::VisualToolDrag(VideoDisplay *parent, VideoState const& video, wxToolBar * toolBar) VisualToolDrag::VisualToolDrag(VideoDisplay *parent, VideoState const& video, wxToolBar * toolBar)
: VisualTool(parent, video) : VisualTool<VisualToolDragDraggableFeature>(parent, video)
, toolBar(toolBar) , toolBar(toolBar)
, toggleMoveOnMove(true) , toggleMoveOnMove(true)
{ {
@ -127,10 +127,10 @@ void VisualToolDrag::Draw() {
DrawAllFeatures(); DrawAllFeatures();
// Draw arrows // Draw arrows
for (size_t i=0;i<features.size();i++) { for (std::list<VisualToolDragDraggableFeature>::iterator cur = features.begin(); cur != features.end(); ++cur) {
if (features[i].type == DRAG_BIG_SQUARE) continue; if (cur->type == DRAG_BIG_SQUARE) continue;
VisualDraggableFeature *p2 = &features[i]; VisualDraggableFeature *p2 = &*cur;
VisualDraggableFeature *p1 = &features[features[i].parent]; VisualDraggableFeature *p1 = cur->parent;
// Has arrow? // Has arrow?
bool hasArrow = p2->type == DRAG_BIG_CIRCLE; bool hasArrow = p2->type == DRAG_BIG_CIRCLE;
@ -175,6 +175,7 @@ void VisualToolDrag::Draw() {
/// @brief Populate list /// @brief Populate list
void VisualToolDrag::PopulateFeatureList() { void VisualToolDrag::PopulateFeatureList() {
ClearSelection();
features.clear(); features.clear();
// Get video data // Get video data
@ -209,7 +210,7 @@ void VisualToolDrag::PopulateFeatureList() {
feat.line = diag; feat.line = diag;
feat.lineN = i; feat.lineN = i;
features.push_back(feat); features.push_back(feat);
feat.parent = features.size() - 1; feat.parent = &features.back();
// Create move destination feature // Create move destination feature
if (hasMove) { if (hasMove) {
@ -221,7 +222,7 @@ void VisualToolDrag::PopulateFeatureList() {
feat.line = diag; feat.line = diag;
feat.lineN = i; feat.lineN = i;
features.push_back(feat); features.push_back(feat);
features[feat.parent].parent = features.size() - 1; feat.parent->parent = &features.back();
} }
// Create org feature // Create org feature
if (torgx != x1 || torgy != y1) { if (torgx != x1 || torgy != y1) {
@ -241,25 +242,25 @@ void VisualToolDrag::PopulateFeatureList() {
/// @brief Update drag /// @brief Update drag
/// @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(frame_n,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());
} }
/// @brief Commit drag /// @brief Commit drag
/// @param feature /// @param feature
void VisualToolDrag::CommitDrag(VisualToolDragDraggableFeature &feature) { void VisualToolDrag::CommitDrag(VisualToolDragDraggableFeature* feature) {
// Origin // Origin
if (feature.type == DRAG_BIG_TRIANGLE) { if (feature->type == DRAG_BIG_TRIANGLE) {
int x = feature.x; int x = feature->x;
int y = feature.y; int y = feature->y;
parent->ToScriptCoords(&x, &y); parent->ToScriptCoords(&x, &y);
SetOverride(feature.line, L"\\org",wxString::Format(L"(%i,%i)",x,y)); SetOverride(feature->line, L"\\org",wxString::Format(L"(%i,%i)",x,y));
return; return;
} }
VisualToolDragDraggableFeature *p = feature->parent > -1 ? &features[feature->parent] : NULL; VisualToolDragDraggableFeature *p = feature->parent;
if (feature->type == DRAG_BIG_CIRCLE) { if (feature->type == DRAG_BIG_CIRCLE) {
std::swap(feature, p); std::swap(feature, p);
} }
@ -270,7 +271,7 @@ void VisualToolDrag::CommitDrag(VisualToolDragDraggableFeature &feature) {
// Position // Position
if (!p) { if (!p) {
SetOverride(feature.line, L"\\pos", wxString::Format(L"(%i,%i)", x1, y1)); SetOverride(feature->line, L"\\pos", wxString::Format(L"(%i,%i)", x1, y1));
} }
// Move // Move
else { else {

View file

@ -47,11 +47,11 @@
class VisualToolDragDraggableFeature : public VisualDraggableFeature { class VisualToolDragDraggableFeature : public VisualDraggableFeature {
public: public:
int time; int time;
int parent; VisualToolDragDraggableFeature* parent;
VisualToolDragDraggableFeature() VisualToolDragDraggableFeature()
: VisualDraggableFeature() : VisualDraggableFeature()
, time(0) , time(0)
, parent(-1) , parent(NULL)
{ } { }
}; };
@ -73,8 +73,8 @@ private:
/// ///
bool CanDrag() { return true; } bool CanDrag() { return true; }
void PopulateFeatureList(); void PopulateFeatureList();
void UpdateDrag(VisualToolDragDraggableFeature &feature); void UpdateDrag(VisualToolDragDraggableFeature* feature);
void CommitDrag(VisualToolDragDraggableFeature &feature); void CommitDrag(VisualToolDragDraggableFeature* feature);
void UpdateToggleButtons(); void UpdateToggleButtons();
void DoRefresh(); void DoRefresh();

View file

@ -50,7 +50,7 @@
/// @brief Constructor /// @brief Constructor
/// @param _parent /// @param _parent
VisualToolRotateXY::VisualToolRotateXY(VideoDisplay *parent, VideoState const& video, wxToolBar *) VisualToolRotateXY::VisualToolRotateXY(VideoDisplay *parent, VideoState const& video, wxToolBar *)
: VisualTool(parent, video) : VisualTool<VisualDraggableFeature>(parent, video)
{ {
DoRefresh(); DoRefresh();
} }
@ -230,18 +230,18 @@ void VisualToolRotateXY::PopulateFeatureList() {
/// @brief Update dragging of \\org /// @brief Update dragging of \\org
/// @param feature /// @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 /// @brief Commit dragging of \\org
/// @param feature /// @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;
parent->ToScriptCoords(&x, &y); parent->ToScriptCoords(&x, &y);
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 /// @brief Refresh

View file

@ -81,8 +81,8 @@ private:
/// @brief DOCME /// @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();

View file

@ -50,7 +50,7 @@
/// @brief Constructor /// @brief Constructor
/// @param _parent /// @param _parent
VisualToolRotateZ::VisualToolRotateZ(VideoDisplay *parent, VideoState const& video, wxToolBar *) VisualToolRotateZ::VisualToolRotateZ(VideoDisplay *parent, VideoState const& video, wxToolBar *)
: VisualTool(parent, video) : VisualTool<VisualDraggableFeature>(parent, video)
{ {
DoRefresh(); DoRefresh();
} }
@ -144,7 +144,7 @@ void VisualToolRotateZ::Draw() {
glPopMatrix(); glPopMatrix();
// Draw line to mouse // Draw line to mouse
if (!dragging && curFeature == -1) { if (!dragging && !curFeature) {
SetLineColour(colour[0]); SetLineColour(colour[0]);
DrawLine(dx,dy,video.x,video.y); DrawLine(dx,dy,video.x,video.y);
} }
@ -197,18 +197,18 @@ void VisualToolRotateZ::PopulateFeatureList() {
/// @brief Update dragging of \\org /// @brief Update dragging of \\org
/// @param feature /// @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 /// @brief Commit dragging of \\org
/// @param feature /// @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;
parent->ToScriptCoords(&x, &y); parent->ToScriptCoords(&x, &y);
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 /// @brief Refresh

View file

@ -79,8 +79,8 @@ private:
/// @brief DOCME /// @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();

View file

@ -50,7 +50,7 @@
/// @brief Constructor /// @brief Constructor
/// @param _parent /// @param _parent
VisualToolScale::VisualToolScale(VideoDisplay *parent, VideoState const& video, wxToolBar *) VisualToolScale::VisualToolScale(VideoDisplay *parent, VideoState const& video, wxToolBar *)
: VisualTool(parent, video) : VisualTool<VisualDraggableFeature>(parent, video)
{ {
} }

View file

@ -80,7 +80,9 @@ enum {
/// @param parent /// @param parent
/// @param _toolBar /// @param _toolBar
VisualToolVectorClip::VisualToolVectorClip(VideoDisplay *parent, VideoState const& video, wxToolBar * toolBar) VisualToolVectorClip::VisualToolVectorClip(VideoDisplay *parent, VideoState const& video, wxToolBar * toolBar)
: VisualTool(parent, video), toolBar(toolBar), spline(*parent) : VisualTool<VisualToolVectorClipDraggableFeature>(parent, video)
, toolBar(toolBar)
, spline(*parent)
{ {
DoRefresh(); DoRefresh();
mode = 0; mode = 0;
@ -168,7 +170,7 @@ void VisualToolVectorClip::Draw() {
SetLineColour(colour[3],1.0f,2); SetLineColour(colour[3],1.0f,2);
int col = 3; int col = 3;
for (size_t i=1;i<points.size();i++) { for (size_t i=1;i<points.size();i++) {
int useCol = pointCurve[i] == highCurve && curFeature == -1 ? 2 : 3; int useCol = pointCurve[i] == highCurve && !curFeature ? 2 : 3;
if (col != useCol) { if (col != useCol) {
col = useCol; col = useCol;
SetLineColour(colour[col],1.0f,2); SetLineColour(colour[col],1.0f,2);
@ -205,6 +207,7 @@ void VisualToolVectorClip::Draw() {
/// @brief Populate feature list /// @brief Populate feature list
void VisualToolVectorClip::PopulateFeatureList() { void VisualToolVectorClip::PopulateFeatureList() {
// Clear // Clear
ClearSelection();
features.clear(); features.clear();
VisualToolVectorClipDraggableFeature feat; VisualToolVectorClipDraggableFeature feat;
@ -262,27 +265,27 @@ void VisualToolVectorClip::PopulateFeatureList() {
/// @brief Update /// @brief Update
/// @param feature /// @param feature
void VisualToolVectorClip::UpdateDrag(VisualToolVectorClipDraggableFeature &feature) { void VisualToolVectorClip::UpdateDrag(VisualToolVectorClipDraggableFeature* feature) {
spline.MovePoint(feature.index,feature.point,wxPoint(feature.x,feature.y)); spline.MovePoint(feature->index,feature->point,wxPoint(feature->x,feature->y));
} }
/// @brief Commit /// @brief Commit
/// @param feature /// @param feature
void VisualToolVectorClip::CommitDrag(VisualToolVectorClipDraggableFeature &feature) { void VisualToolVectorClip::CommitDrag(VisualToolVectorClipDraggableFeature* feature) {
SetOverride(GetActiveDialogueLine(), inverse ? L"\\iclip" : L"\\clip", L"(" + spline.EncodeToASS() + L")"); SetOverride(GetActiveDialogueLine(), inverse ? L"\\iclip" : L"\\clip", L"(" + spline.EncodeToASS() + L")");
} }
/// @brief Clicked a feature /// @brief Clicked a feature
/// @param feature /// @param feature
/// @return /// @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) {
int i = 0; int i = 0;
for (std::list<SplineCurve>::iterator cur=spline.curves.begin();cur!=spline.curves.end();i++,cur++) { for (std::list<SplineCurve>::iterator cur=spline.curves.begin();cur!=spline.curves.end();i++,cur++) {
if (i == feature.index) { if (i == feature->index) {
// Update next // Update next
if (i != 0 || feature.point != 0) { if (i != 0 || feature->point != 0) {
std::list<SplineCurve>::iterator next = cur; std::list<SplineCurve>::iterator next = cur;
next++; next++;
if (next != spline.curves.end()) next->p1 = cur->p1; if (next != spline.curves.end()) next->p1 = cur->p1;
@ -291,7 +294,7 @@ bool VisualToolVectorClip::InitializeDrag(VisualToolVectorClipDraggableFeature &
// Erase and save changes // Erase and save changes
spline.curves.erase(cur); spline.curves.erase(cur);
CommitDrag(feature); CommitDrag(feature);
curFeature = -1; curFeature = NULL;
Commit(true); Commit(true);
return false; return false;
} }
@ -387,6 +390,7 @@ bool VisualToolVectorClip::InitializeHold() {
// Freehand // Freehand
if (mode == 6 || mode == 7) { if (mode == 6 || mode == 7) {
ClearSelection();
features.clear(); features.clear();
spline.curves.clear(); spline.curves.clear();
lastX = INT_MIN; lastX = INT_MIN;

View file

@ -92,9 +92,9 @@ private:
void PopulateFeatureList(); void PopulateFeatureList();
void UpdateDrag(VisualToolVectorClipDraggableFeature &feature); void UpdateDrag(VisualToolVectorClipDraggableFeature* feature);
void CommitDrag(VisualToolVectorClipDraggableFeature &feature); void CommitDrag(VisualToolVectorClipDraggableFeature* feature);
bool InitializeDrag(VisualToolVectorClipDraggableFeature &feature); bool InitializeDrag(VisualToolVectorClipDraggableFeature* feature);
void DoRefresh(); void DoRefresh();