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
///
VideoContext::VideoContext()
: glContext(NULL)
, ownGlContext(false)
, audio(NULL)
: ownGlContext(false)
, glContext(NULL)
, provider(NULL)
, subsProvider(NULL)
, curLine(NULL)
, loaded(false)
, keyFramesLoaded(false)
, overKeyFramesLoaded(false)
, startFrame(-1)
, endFrame(-1)
, playNextFrame(-1)
, nextFrame(-1)
, loaded(false)
, isPlaying(false)
, keepAudioSync(true)
, w(-1)
, h(-1)
, frame_n(0)
, length(0)
, fps(0)
, arType(0)
, arValue(1.)
, isPlaying(false)
, nextFrame(-1)
, keepAudioSync(true)
, arType(0)
, hasSubtitles(false)
, grid(NULL)
, curLine(NULL)
, audio(NULL)
{
}

View File

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

View File

@ -29,8 +29,8 @@
//
// $Id$
/// @file visual_feature.h
/// @see visual_feature.cpp
/// @file visual_feature->h
/// @see visual_feature->cpp
/// @ingroup visual_ts
///
@ -75,6 +75,11 @@ public:
int x; /// x 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
AssDialogue* line; /// The dialogue line this feature is for
@ -83,8 +88,8 @@ public:
/// @brief Is the given point over this feature?
/// @param mx x 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
/// @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)};
/// @brief Constructor
/// @param parent
template<class FeatureType>
VisualTool<FeatureType>::VisualTool(VideoDisplay *parent, VideoState const& video)
: parent(parent)
: dragStartX(0)
, dragStartY(0)
, externalChange(true)
, selChanged(false)
, parent(parent)
, holding(false)
, curDiag(NULL)
, dragging(false)
, curFeature(-1)
, curFeature(NULL)
, dragListOK(false)
, video(video)
, frame_n(0)
, video(video)
, leftClick(false)
, leftDClick(false)
, shiftDown(false)
, ctrlDown(false)
, altDown(false)
{
if (VideoContext::Get()->IsLoaded()) {
frame_n = VideoContext::Get()->GetFrameN();
@ -87,13 +94,10 @@ VisualTool<FeatureType>::VisualTool(VideoDisplay *parent, VideoState const& vide
PopulateFeatureList();
}
/// @brief Destructor
template<class FeatureType>
VisualTool<FeatureType>::~VisualTool() {
}
/// @brief Mouse event
/// @param event
template<class FeatureType>
void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
bool realTime = Options.AsBool(L"Video Visual Realtime");
@ -102,6 +106,9 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
Update();
return;
}
externalChange = false;
VideoContext* con = VideoContext::Get();
leftClick = event.ButtonDown(wxMOUSE_BTN_LEFT);
leftDClick = event.LeftDClick();
@ -121,32 +128,62 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
if (dragging) {
// continue drag
if (event.LeftIsDown()) {
features[curFeature].x = (video.x - dragStartX + dragOrigX);
features[curFeature].y = (video.y - dragStartY + dragOrigY);
if (shiftDown) {
if (abs(video.x - dragStartX) > abs(video.y - dragStartY)) {
features[curFeature].y = dragOrigY;
for (SelFeatureIter cur = selFeatures.begin(); cur != selFeatures.end(); ++cur) {
(*cur)->x = (video.x - dragStartX + (*cur)->origX);
(*cur)->y = (video.y - dragStartY + (*cur)->origY);
if (shiftDown) {
if (abs(video.x - dragStartX) > abs(video.y - dragStartY)) {
(*cur)->y = (*cur)->origY;
}
else {
(*cur)->x = (*cur)->origX;
}
}
else {
features[curFeature].x = dragOrigX;
}
}
UpdateDrag(features[curFeature]);
UpdateDrag(*cur);
if (realTime) {
CommitDrag(features[curFeature]);
Commit();
if (realTime) {
CommitDrag(*cur);
}
}
if (realTime) Commit();
}
// end drag
else {
if (realTime) AssLimitToVisibleFilter::SetFrame(-1);
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->SetFocus();
}
@ -177,17 +214,33 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
else if (leftClick) {
curFeature = GetHighlightedFeature();
// start drag
if (curFeature > -1) {
if (InitializeDrag(features[curFeature])) {
if (features[curFeature].lineN != -1) {
VideoContext::Get()->grid->editBox->SetToLine(features[curFeature].lineN,true);
VideoContext::Get()->grid->SelectRow(features[curFeature].lineN);
if (curFeature) {
if (InitializeDrag(curFeature)) {
if (!curFeature->selected) {
selChanged = true;
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;
dragStartY = video.y;
dragOrigX = features[curFeature].x;
dragOrigY = features[curFeature].y;
for (SelFeatureIter cur = selFeatures.begin(); cur != selFeatures.end(); ++cur) {
(*cur)->origX = (*cur)->x;
(*cur)->origY = (*cur)->y;
}
dragging = true;
parent->CaptureMouse();
@ -196,6 +249,7 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
}
// start hold
else {
ClearSelection();
curDiag = GetActiveDialogueLine();
if (curDiag && InitializeHold()) {
holding = true;
@ -206,10 +260,9 @@ void VisualTool<FeatureType>::OnMouseEvent (wxMouseEvent &event) {
}
Update();
externalChange = true;
}
/// @brief Commit
/// @param full
template<class FeatureType>
void VisualTool<FeatureType>::Commit(bool full) {
SubtitlesGrid *grid = VideoContext::Get()->grid;
@ -218,8 +271,6 @@ void VisualTool<FeatureType>::Commit(bool full) {
grid->editBox->Update(false, true, false);
}
/// @brief Get active dialogue line
/// @return
template<class FeatureType>
AssDialogue* VisualTool<FeatureType>::GetActiveDialogueLine() {
SubtitlesGrid *grid = VideoContext::Get()->grid;
@ -236,22 +287,19 @@ AssDialogue* VisualTool<FeatureType>::GetActiveDialogueLine() {
return diag;
}
/// @brief Get feature under mouse
/// @return
template<class FeatureType>
int VisualTool<FeatureType>::GetHighlightedFeature() {
FeatureType* VisualTool<FeatureType>::GetHighlightedFeature() {
int highestLayerFound = INT_MIN;
int bestMatch = -1;
for (size_t i=0;i<features.size();i++) {
if (features[i].IsMouseOver(video.x, video.y) && features[i].layer > highestLayerFound) {
bestMatch = i;
highestLayerFound = features[i].layer;
FeatureType* bestMatch = NULL;
for (FeatureIter cur = features.begin(); cur != features.end(); ++cur) {
if (cur->IsMouseOver(video.x, video.y) && cur->layer > highestLayerFound) {
bestMatch = &*cur;
highestLayerFound = cur->layer;
}
}
return bestMatch;
}
/// @brief Draw all features
template<class FeatureType>
void VisualTool<FeatureType>::DrawAllFeatures() {
if (!dragListOK) {
@ -259,31 +307,40 @@ void VisualTool<FeatureType>::DrawAllFeatures() {
dragListOK = true;
}
int mouseOver = curFeature;
if (curFeature == -1) mouseOver = GetHighlightedFeature();
FeatureType* mouseOver = curFeature ? curFeature : GetHighlightedFeature();
for (size_t i=0;i<features.size();i++) {
SetFillColour(colour[(signed)i == mouseOver ? 2 : 1],0.6f);
for (FeatureCIter cur = features.begin(); cur != features.end(); ++cur) {
int fill = &*cur == mouseOver ? 2 :
cur->selected ? 3 :
1;
SetFillColour(colour[fill],0.6f);
SetLineColour(colour[0],1.0f,2);
features[i].Draw(*this);
cur->Draw(*this);
}
}
/// @brief Refresh
template<class FeatureType>
void VisualTool<FeatureType>::Refresh() {
frame_n = VideoContext::Get()->GetFrameN();
if (!dragging) dragListOK = false;
if (externalChange) dragListOK = false;
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
/// @param diag
/// @param x
/// @param y
template<class FeatureType>
void VisualTool<FeatureType>::GetLinePosition(AssDialogue *diag,int &x, int &y) {
int orgx=0,orgy=0;
int orgx,orgy;
GetLinePosition(diag,x,y,orgx,orgy);
}

View File

@ -37,7 +37,6 @@
#ifndef AGI_PRE
#include <vector>
#include "boost/shared_ptr.hpp"
#include <wx/log.h>
#include <wx/event.h>
@ -76,56 +75,38 @@ public:
template<class FeatureType>
class VisualTool : public IVisualTool {
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
int dragStartX,dragStartY,dragOrigX,dragOrigY;
int GetHighlightedFeature();
std::list<FeatureType*> selFeatures; /// Currently selected visual features
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:
/// DOCME
VideoDisplay *parent;
VideoDisplay *parent; /// VideoDisplay which this belongs to, used to frame conversion
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
bool holding;
FeatureType* curFeature; /// Topmost feature under the mouse; only valid during a drag?
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
AssDialogue *curDiag;
int frame_n; /// Current frame number
VideoState const& video; /// Mouse and video information
/// DOCME
bool dragging;
/// DOCME
int curFeature;
/// 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;
bool leftClick; /// Is a left click event currently being processed?
bool leftDClick; /// Is a left double click event currently being processed?
bool shiftDown; /// Is shift down?
bool ctrlDown; /// Is ctrl down?
bool altDown; /// Is alt down?
void GetLinePosition(AssDialogue *diag,int &x,int &y);
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);
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();
void DrawAllFeatures();
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; }
/// @brief DOCME
///
virtual void UpdateHold() {}
/// @brief Called on every mouse event during a hold
virtual void UpdateHold() { }
/// @brief DOCME
/// @return
///
virtual void CommitHold() {}
/// @brief Called at the end of a hold
virtual void CommitHold() { }
/// @brief DOCME
///
/// @brief Called when the feature list needs to be (re)generated
virtual void PopulateFeatureList() { }
/// @brief DOCME
/// @param feature
///
virtual bool InitializeDrag(FeatureType &feature) { return true; }
/// @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 DOCME
/// @param feature
///
virtual void UpdateDrag(FeatureType &feature) {}
/// @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 DOCME
/// @param feature
///
virtual void CommitDrag(FeatureType &feature) {}
// @brief Called at the end of a drag
virtual void CommitDrag(FeatureType* feature) { }
/// @brief DOCME
///
virtual void DoRefresh() {}
/// @brief Called when there's stuff
virtual void DoRefresh() { }
/// @brief Must be called before removing entries from features
void ClearSelection();
public:
/// @brief Handler for all mouse events
/// @param event Shockingly enough, the mouse event
void OnMouseEvent(wxMouseEvent &event);
/// @brief DOCME
/// @param event
///
virtual void OnSubTool(wxCommandEvent &) {}
/// @brief Event handler for the subtoolbar
virtual void OnSubTool(wxCommandEvent &) { }
/// @brief Called when there's stuff
virtual void Update() { };
/// @brief Draw stuff
virtual void Draw()=0;
/// @brief Called when there's stuff
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);
/// @brief Destructor
virtual ~VisualTool();
};

View File

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

View File

@ -75,6 +75,8 @@ private:
/// DOCME
bool inverse;
ClipCorner* feat[4];
/// @brief DOCME
/// @return
@ -87,9 +89,9 @@ private:
/// @brief DOCME
///
void PopulateFeatureList();
bool InitializeDrag(ClipCorner &feature);
void UpdateDrag(ClipCorner &feature);
void CommitDrag(ClipCorner &feature);
bool InitializeDrag(ClipCorner* feature);
void UpdateDrag(ClipCorner* feature);
void CommitDrag(ClipCorner* feature);
public:
VisualToolClip(VideoDisplay *parent, VideoState const& video, wxToolBar *);

View File

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

View File

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

View File

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

View File

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

View File

@ -81,8 +81,8 @@ private:
/// @brief DOCME
///
void PopulateFeatureList();
void UpdateDrag(VisualDraggableFeature &feature);
void CommitDrag(VisualDraggableFeature &feature);
void UpdateDrag(VisualDraggableFeature* feature);
void CommitDrag(VisualDraggableFeature* feature);
void DoRefresh();

View File

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

View File

@ -79,8 +79,8 @@ private:
/// @brief DOCME
///
void PopulateFeatureList();
void UpdateDrag(VisualDraggableFeature &feature);
void CommitDrag(VisualDraggableFeature &feature);
void UpdateDrag(VisualDraggableFeature* feature);
void CommitDrag(VisualDraggableFeature* feature);
void DoRefresh();

View File

@ -50,7 +50,7 @@
/// @brief Constructor
/// @param _parent
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 _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();
mode = 0;
@ -168,7 +170,7 @@ void VisualToolVectorClip::Draw() {
SetLineColour(colour[3],1.0f,2);
int col = 3;
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) {
col = useCol;
SetLineColour(colour[col],1.0f,2);
@ -205,6 +207,7 @@ void VisualToolVectorClip::Draw() {
/// @brief Populate feature list
void VisualToolVectorClip::PopulateFeatureList() {
// Clear
ClearSelection();
features.clear();
VisualToolVectorClipDraggableFeature feat;
@ -262,27 +265,27 @@ void VisualToolVectorClip::PopulateFeatureList() {
/// @brief Update
/// @param feature
void VisualToolVectorClip::UpdateDrag(VisualToolVectorClipDraggableFeature &feature) {
spline.MovePoint(feature.index,feature.point,wxPoint(feature.x,feature.y));
void VisualToolVectorClip::UpdateDrag(VisualToolVectorClipDraggableFeature* feature) {
spline.MovePoint(feature->index,feature->point,wxPoint(feature->x,feature->y));
}
/// @brief Commit
/// @param feature
void VisualToolVectorClip::CommitDrag(VisualToolVectorClipDraggableFeature &feature) {
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
if (mode == 5) {
int i = 0;
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
if (i != 0 || feature.point != 0) {
if (i != 0 || feature->point != 0) {
std::list<SplineCurve>::iterator next = cur;
next++;
if (next != spline.curves.end()) next->p1 = cur->p1;
@ -291,7 +294,7 @@ bool VisualToolVectorClip::InitializeDrag(VisualToolVectorClipDraggableFeature &
// Erase and save changes
spline.curves.erase(cur);
CommitDrag(feature);
curFeature = -1;
curFeature = NULL;
Commit(true);
return false;
}
@ -387,6 +390,7 @@ bool VisualToolVectorClip::InitializeHold() {
// Freehand
if (mode == 6 || mode == 7) {
ClearSelection();
features.clear();
spline.curves.clear();
lastX = INT_MIN;

View File

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