From 7e8de1c3899eb599fc183326c76fd19f51f02a48 Mon Sep 17 00:00:00 2001 From: Rodrigo Braz Monteiro Date: Sun, 1 Jul 2007 00:19:55 +0000 Subject: [PATCH] Visual tools rewriting, currently only the crosshair works. Originally committed to SVN as r1324. --- aegisub/Makefile.am | 5 +- aegisub/main.cpp | 12 +- aegisub/video_box.cpp | 13 +- aegisub/video_context.h | 2 +- aegisub/video_display.cpp | 60 +- aegisub/video_display.h | 10 +- aegisub/video_display_visual.cpp | 1125 ----------------- ...aggable_feature.cpp => visual_feature.cpp} | 8 +- ...o_draggable_feature.h => visual_feature.h} | 4 +- aegisub/visual_tool.cpp | 338 +++++ .../{video_display_visual.h => visual_tool.h} | 47 +- aegisub/visual_tool_cross.cpp | 142 +++ aegisub/visual_tool_cross.h | 54 + 13 files changed, 617 insertions(+), 1203 deletions(-) delete mode 100644 aegisub/video_display_visual.cpp rename aegisub/{video_draggable_feature.cpp => visual_feature.cpp} (91%) rename aegisub/{video_draggable_feature.h => visual_feature.h} (97%) create mode 100644 aegisub/visual_tool.cpp rename aegisub/{video_display_visual.h => visual_tool.h} (80%) create mode 100644 aegisub/visual_tool_cross.cpp create mode 100644 aegisub/visual_tool_cross.h diff --git a/aegisub/Makefile.am b/aegisub/Makefile.am index 3b11b87c5..0b5fe056f 100644 --- a/aegisub/Makefile.am +++ b/aegisub/Makefile.am @@ -209,12 +209,13 @@ aegisub_SOURCES = \ video_box.cpp \ video_context.cpp \ video_display.cpp \ - video_display_visual.cpp \ - video_draggable_feature.cpp \ video_frame.cpp \ video_provider.cpp \ video_provider_dummy.cpp \ video_slider.cpp \ + visual_feature.cpp \ + visual_tool.cpp \ + visual_tool_cross.cpp \ MatroskaParser.c noinst_HEADERS = \ diff --git a/aegisub/main.cpp b/aegisub/main.cpp index b32fb0069..000345492 100644 --- a/aegisub/main.cpp +++ b/aegisub/main.cpp @@ -81,17 +81,21 @@ bool AegisubApp::OnInit() { setlocale(LC_NUMERIC, "C"); setlocale(LC_CTYPE, "C"); - // App name -#ifdef __WXMSW__ || __WXMAC__ + // App name (yeah, this is a little weird to get rid of an odd warning) +#ifdef __WXMSW__ + SetAppName(_T("Aegisub")); +#else +#ifdef __WXMAC__ SetAppName(_T("Aegisub")); #else SetAppName(_T("aegisub")); +#endif #endif // Crash handling - #ifndef _DEBUG +#ifndef _DEBUG wxHandleFatalExceptions(true); - #endif +#endif // Set config file Options.SetFile(StandardPaths::DecodePath(_T("?data/config.dat"))); diff --git a/aegisub/video_box.cpp b/aegisub/video_box.cpp index cc2bab084..d52972aee 100644 --- a/aegisub/video_box.cpp +++ b/aegisub/video_box.cpp @@ -43,7 +43,6 @@ #include #include "video_box.h" #include "video_display.h" -#include "video_display_visual.h" #include "video_slider.h" #include "frame_main.h" #include "toggle_bitmap.h" @@ -208,42 +207,42 @@ void VideoBox::OnVideoToggleScroll(wxCommandEvent &event) { ///////////////// // Standard mode void VideoBox::OnModeStandard(wxCommandEvent &event) { - videoDisplay->visual->SetMode(0); + videoDisplay->SetVisualMode(0); } ///////////// // Drag mode void VideoBox::OnModeDrag(wxCommandEvent &event) { - videoDisplay->visual->SetMode(1); + videoDisplay->SetVisualMode(1); } ///////////////// // Rotate Z mode void VideoBox::OnModeRotateZ(wxCommandEvent &event) { - videoDisplay->visual->SetMode(2); + videoDisplay->SetVisualMode(2); } ////////////////// // Rotate XY mode void VideoBox::OnModeRotateXY(wxCommandEvent &event) { - videoDisplay->visual->SetMode(3); + videoDisplay->SetVisualMode(3); } ////////////// // Scale mode void VideoBox::OnModeScale(wxCommandEvent &event) { - videoDisplay->visual->SetMode(4); + videoDisplay->SetVisualMode(4); } ///////////// // Clip mode void VideoBox::OnModeClip(wxCommandEvent &event) { - videoDisplay->visual->SetMode(5); + videoDisplay->SetVisualMode(5); } diff --git a/aegisub/video_context.h b/aegisub/video_context.h index 789efc482..1a68b8e25 100644 --- a/aegisub/video_context.h +++ b/aegisub/video_context.h @@ -72,7 +72,7 @@ class VideoContextThread; // Main class class VideoContext : public wxEvtHandler { friend class AudioProvider; - friend class VideoDisplayVisual; + friend class VisualTool; friend class VideoContextThread; private: diff --git a/aegisub/video_display.cpp b/aegisub/video_display.cpp index b85c97101..5563c1382 100644 --- a/aegisub/video_display.cpp +++ b/aegisub/video_display.cpp @@ -51,7 +51,6 @@ #include #include "utils.h" #include "video_display.h" -#include "video_display_visual.h" #include "video_provider.h" #include "vfr.h" #include "ass_file.h" @@ -68,6 +67,8 @@ #include "video_slider.h" #include "video_box.h" #include "gl_wrap.h" +#include "visual_tool.h" +#include "visual_tool_cross.h" /////// @@ -116,8 +117,10 @@ VideoDisplay::VideoDisplay(wxWindow* parent, wxWindowID id, const wxPoint& pos, origSize = size; zoomValue = 1.0; freeSize = false; - visual = new VideoDisplayVisual(this); + visual = NULL; SetCursor(wxNullCursor); + visualMode = -1; + SetVisualMode(0); } @@ -125,6 +128,7 @@ VideoDisplay::VideoDisplay(wxWindow* parent, wxWindowID id, const wxPoint& pos, // Destructor VideoDisplay::~VideoDisplay () { delete visual; + visual = NULL; VideoContext::Get()->RemoveDisplay(this); } @@ -275,8 +279,7 @@ void VideoDisplay::Render() { DrawTVEffects(); // Draw overlay - wxASSERT(visual); - visual->DrawOverlay(); + if (visual) visual->Draw(); // Swap buffers glFinish(); @@ -451,7 +454,7 @@ void VideoDisplay::OnMouseEvent(wxMouseEvent& event) { } // Enforce correct cursor display - ShowCursor(visual->mode != 0); + ShowCursor(visualMode != 0); // Click? if (event.ButtonDown(wxMOUSE_BTN_ANY)) { @@ -459,16 +462,21 @@ void VideoDisplay::OnMouseEvent(wxMouseEvent& event) { } // Send to visual - wxASSERT(visual); - visual->OnMouseEvent(event); + if (visual) visual->OnMouseEvent(event); } ///////////// // Key event void VideoDisplay::OnKey(wxKeyEvent &event) { - wxASSERT(visual); - visual->OnKeyEvent(event); + // FIXME: should these be configurable? + // Think of the frenchmen and other people not using qwerty layout + if (event.GetKeyCode() == 'A') SetVisualMode(0); + if (event.GetKeyCode() == 'S') SetVisualMode(1); + if (event.GetKeyCode() == 'D') SetVisualMode(2); + if (event.GetKeyCode() == 'F') SetVisualMode(3); + if (event.GetKeyCode() == 'G') SetVisualMode(4); + if (event.GetKeyCode() == 'H') SetVisualMode(5); } @@ -603,6 +611,7 @@ void VideoDisplay::OnSaveSnapshotRaw(wxCommandEvent &event) { ///////////////////// // Copy coordinates void VideoDisplay::OnCopyCoords(wxCommandEvent &event) { + wxLogMessage(_T("TODO: FIXME")); if (wxTheClipboard->Open()) { int sw,sh; VideoContext::Get()->GetScriptSize(sw,sh); @@ -614,23 +623,6 @@ void VideoDisplay::OnCopyCoords(wxCommandEvent &event) { } -////////////////// -// DrawVideoWithOverlay -void VideoDisplay::DrawText( wxPoint Pos, wxString text ) { - //// Draw frame - //wxClientDC dc(this); - //dc.SetBrush(wxBrush(wxColour(128,128,128),wxSOLID)); - //dc.DrawRectangle( 0,0, provider->GetWidth(), provider->GetHeight() ); - //dc.SetTextForeground(wxColour(64,64,64)); - //dc.DrawText(text,Pos.x+1,Pos.y-1); - //dc.DrawText(text,Pos.x+1,Pos.y+1); - //dc.DrawText(text,Pos.x-1,Pos.y-1); - //dc.DrawText(text,Pos.x-1,Pos.y+1); - //dc.SetTextForeground(wxColour(255,255,255)); - //dc.DrawText(text,Pos.x,Pos.y); -} - - ///////////////////////////// // Convert mouse coordinates void VideoDisplay::ConvertMouseCoords(int &x,int &y) { @@ -643,3 +635,19 @@ void VideoDisplay::ConvertMouseCoords(int &x,int &y) { x = (x-dx1)*w/dx2; y = (y-dy1)*h/dy2; } + + +//////////// +// Set mode +void VideoDisplay::SetVisualMode(int mode) { + // Set visual + visualMode = mode; + delete visual; + switch (mode) { + case 0: visual = new VisualToolCross(this); break; + default: visual = NULL; + } + + // Render + Render(); +} diff --git a/aegisub/video_display.h b/aegisub/video_display.h index 218090794..5e068d7d0 100644 --- a/aegisub/video_display.h +++ b/aegisub/video_display.h @@ -56,7 +56,7 @@ class AudioProvider; class AudioDisplay; class AssDialogue; class VideoProvider; -class VideoDisplayVisual; +class VisualTool; class VideoBox; @@ -64,9 +64,11 @@ class VideoBox; // Main class class VideoDisplay: public wxGLCanvas { friend class AudioProvider; - friend class VideoDisplayVisual; + friend class VisualTool; private: + int visualMode; + wxSize origSize; int w,h; int dx1,dx2,dy1,dy2; @@ -88,7 +90,7 @@ private: void OnSaveSnapshotRaw(wxCommandEvent &event); public: - VideoDisplayVisual *visual; + VisualTool *visual; VideoBox *box; double zoomValue; @@ -107,12 +109,12 @@ public: void ShowCursor(bool show); void ConvertMouseCoords(int &x,int &y); - void DrawText(wxPoint Pos, wxString Text); void UpdatePositionDisplay(); void UpdateSize(); void SetZoom(double value); void SetZoomPos(int pos); void UpdateSubsRelativeTime(); + void SetVisualMode(int mode); DECLARE_EVENT_TABLE() }; diff --git a/aegisub/video_display_visual.cpp b/aegisub/video_display_visual.cpp deleted file mode 100644 index a6dde4560..000000000 --- a/aegisub/video_display_visual.cpp +++ /dev/null @@ -1,1125 +0,0 @@ -// Copyright (c) 2005-2007, Rodrigo Braz Monteiro -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of the Aegisub Group nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// ----------------------------------------------------------------------------- -// -// AEGISUB -// -// Website: http://aegisub.cellosoft.com -// Contact: mailto:zeratul@cellosoft.com -// - - -////////////// -// Headers -#include -#include -#include -#include "video_display_visual.h" -#include "video_display.h" -#include "video_provider.h" -#include "vfr.h" -#include "ass_file.h" -#include "ass_time.h" -#include "ass_dialogue.h" -#include "ass_override.h" -#include "ass_style.h" -#include "subs_grid.h" -#include "options.h" -#include "subs_edit_box.h" -#include "export_visible_lines.h" -#include "utils.h" -#include "gl_text.h" - - -/////////////// -// Constructor -VideoDisplayVisual::VideoDisplayVisual(VideoDisplay *par) { - parent = par; - curSelection = NULL; - holding = false; - mode = -1; - SetMode(0); - colour[0] = wxColour(27,60,114); - //colour[1] = wxColour(175,219,254); - colour[1] = wxColour(166,247,177); - colour[2] = wxColour(255,255,255); - colour[3] = wxColour(187,0,0); -} - - -////////////// -// Destructor -VideoDisplayVisual::~VideoDisplayVisual() { -} - - -//////////// -// Set mode -void VideoDisplayVisual::SetMode(int _mode) { - // Set mode - mode = _mode; - - // Display cursor or not - parent->ShowCursor(mode != 0); - - // Refresh parent - parent->Render(); -} - - -//////////////// -// Draw overlay -void VideoDisplayVisual::DrawOverlay() { - // Variables - int frame_n = VideoContext::Get()->GetFrameN(); - int w,h; - parent->GetClientSize(&w,&h); - int sw,sh; - VideoContext::Get()->GetScriptSize(sw,sh); - int x = mouseX; - int y = mouseY; - int mx = mouseX * sw / w; - int my = mouseY * sh / h; - - // Draw lines - if (mode != 0) { - int numRows = VideoContext::Get()->grid->GetRows(); - AssDialogue *diag; - AssDialogue *diagHigh = NULL; - - // Find where the highlight is - if (mode == 1) { - int dx,dy; - for (int i=0;igrid->GetDialogue(i); - if (diag) { - if (VFR_Output.GetFrameAtTime(diag->Start.GetMS(),true) <= frame_n && VFR_Output.GetFrameAtTime(diag->End.GetMS(),false) >= frame_n) { - GetLinePosition(diag,dx,dy); - dx = dx * w / sw; - dy = dy * h / sh; - if (x >= dx-8 && x <= dx+8 && y >= dy-8 && y <= dy+8) { - diagHigh = diag; - } - } - } - } - } - - // For each line - for (int i=0;igrid->GetDialogue(i); - if (diag) { - // Draw? - //bool draw = false; - bool high = false; - bool isCur = diag == curSelection; - bool timeVisible = VFR_Output.GetFrameAtTime(diag->Start.GetMS(),true) <= frame_n && VFR_Output.GetFrameAtTime(diag->End.GetMS(),false) >= frame_n; - bool show = timeVisible; - if (mode != 1) { - show = diag == VideoContext::Get()->grid->GetDialogue(VideoContext::Get()->grid->editBox->linen) && timeVisible; - } - - // Variables - int dx = -1; - int dy = -1; - int orgx = -1; - int orgy = -1; - float rx = 0.0f; - float ry = 0.0f; - float rz = 0.0f; - float scalX = 100.0f; - float scalY = 100.0f; - int deltax = 0; - int deltay = 0; - - // Line visible? - if (show) { - // Get position - if (isCur && mode == 1) { - dx = curX; - dy = curY; - high = true; - } - else GetLinePosition(diag,dx,dy,orgx,orgy); - - // Get scale - if (isCur && mode == 4) { - scalX = curFloat1; - scalY = curFloat2; - } - else GetLineScale(diag,scalX,scalY); - - // Get angle - GetLineRotation(diag,rx,ry,rz); - if (isCur) { - if (mode == 2) rz = curFloat1; - else if (mode == 3) { - rx = curFloat1; - ry = curFloat2; - } - } - - // Mouse over? - if (diag == diagHigh) { - high = true; - } - - // Highlight - int brushCol = 1; - if (high) brushCol = 2; - SetLineColour(colour[0]); - SetFillColour(colour[brushCol],0.3f); - - // Set drawing coordinates - int radius = (int) sqrt(double((dx-orgx)*(dx-orgx)+(dy-orgy)*(dy-orgy))); - - // Drag - if (mode == 1) { - SetFillColour(colour[brushCol],0.5f); - DrawRectangle(dx-8,dy-8,dx+8,dy+8); - SetLineColour(colour[2]); - SetModeLine(); - DrawLine(dx,dy-16,dx,dy+16); - DrawLine(dx-16,dy,dx+16,dy); - } - - // Rotation - if (mode == 2 || mode == 3) { - // Pivot coordinates - int odx = dx; - int ody = dy; - dx = orgx; - dy = orgy; - - // Draw pivot - DrawCircle(dx,dy,7); - DrawLine(dx,dy-16,dx,dy+16); - DrawLine(dx-16,dy,dx+16,dy); - - // Rotate Z - if (mode == 2) { - // Transform - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glTranslatef(dx,dy,-1.0f); - float matrix[16] = { 2500, 0, 0, 0, 0, 2500, 0, 0, 0, 0, 1, 1, 0, 0, 2500, 2500 }; - glMultMatrixf(matrix); - glScalef(1.0f,1.0f,8.0f); - glRotatef(ry,0.0f,-1.0f,0.0f); - glRotatef(rx,-1.0f,0.0f,0.0f); - glScalef(scalX/100.0f,scalY/100.0f,1.0f); - - // Calculate radii - int oRadius = radius; - if (radius < 50) radius = 50; - - // Draw the circle - SetLineColour(colour[0]); - SetFillColour(colour[1],0.3f); - DrawRing(0,0,radius+4,radius-4); - - // Draw markers around circle - int markers = 6; - float markStart = -90.0f / markers; - float markEnd = markStart+(180.0f/markers); - for (int i=0;i dx2) IntSwap(dx1,dx2); - if (dy1 > dy2) IntSwap(dy1,dy2); - - // Draw rectangle - SetLineColour(colour[3]); - SetFillColour(colour[3],0.0f); - DrawRectangle(dx1,dy1,dx2,dy2); - - // Draw outside area - SetLineColour(colour[3],0.0f); - SetFillColour(colour[3],0.3f); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - DrawRectangle(0,0,sw,dy1); - DrawRectangle(0,dy2,sw,sh); - DrawRectangle(0,dy1,dx1,dy2); - DrawRectangle(dx2,dy1,sw,dy2); - glDisable(GL_BLEND); - - // Draw circles - SetLineColour(colour[0]); - SetFillColour(colour[1],0.5); - DrawCircle(dx1,dy1,4); - DrawCircle(dx2,dy1,4); - DrawCircle(dx2,dy2,4); - DrawCircle(dx1,dy2,4); - } - } - } - } - } - - // Current position info - if (mode == 0 && x >= 0 && x < w && y >= 0 && y < h) { - // Draw cross - glDisable(GL_LINE_SMOOTH); - glEnable(GL_COLOR_LOGIC_OP); - glLogicOp(GL_INVERT); - glBegin(GL_LINES); - glColor3f(1.0f,1.0f,1.0f); - glVertex2f(0,my); - glVertex2f(sw,my); - glVertex2f(mx,0); - glVertex2f(mx,sh); - glEnd(); - glDisable(GL_COLOR_LOGIC_OP); - - // Switch display - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0.0f,w,h,0.0f,-1000.0f,1000.0f); - glMatrixMode(GL_MODELVIEW); - - // Setup text - int tw,th; - OpenGLText::SetFont(_T("Verdana"),12,true); - OpenGLText::SetColour(wxColour(255,255,255)); - OpenGLText::GetExtent(mouseText,tw,th); - - // Calculate draw position - bool left = x > w/2; - bool bottom = y < h/2; - - // Text draw coords - int dx = x,dy = y; - if (left) dx -= tw + 4; - else dx += 4; - if (bottom) dy += 3; - else dy -= th + 3; - - // Draw text - OpenGLText::Print(mouseText,dx,dy); - - // Restore matrix - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - } -} - - -//////////////////////// -// Get position of line -void VideoDisplayVisual::GetLinePosition(AssDialogue *diag,int &x, int &y) { - int orgx=0,orgy=0; - GetLinePosition(diag,x,y,orgx,orgy); -} -void VideoDisplayVisual::GetLinePosition(AssDialogue *diag,int &x, int &y, int &orgx, int &orgy) { - // No dialogue - if (!diag) { - x = -1; - y = -1; - return; - } - - // Default values - int margin[4]; - for (int i=0;i<4;i++) margin[i] = diag->Margin[i]; - int align = 2; - - // Get style - AssStyle *style = VideoContext::Get()->grid->ass->GetStyle(diag->Style); - if (style) { - align = style->alignment; - for (int i=0;i<4;i++) { - if (margin[i] == 0) margin[i] = style->Margin[i]; - } - } - - // Script size - int sw,sh; - VideoContext::Get()->GetScriptSize(sw,sh); - - // Process margins - margin[3] = margin[2]; - margin[1] = sw - margin[1]; - margin[3] = sh - margin[3]; - - // Position - bool posSet = false; - bool orgSet = false; - int posx = -1; - int posy = -1; - - // Overrides processing - diag->ParseASSTags(); - AssDialogueBlockOverride *override; - AssOverrideTag *tag; - size_t blockn = diag->Blocks.size(); - for (size_t i=0;iBlocks.at(i)); - if (override) { - for (size_t j=0;jTags.size();j++) { - tag = override->Tags.at(j); - - // Position - if ((tag->Name == _T("\\pos") || tag->Name == _("\\move")) && tag->Params.size() >= 2) { - if (!posSet) { - posx = tag->Params[0]->AsInt(); - posy = tag->Params[1]->AsInt(); - posSet = true; - } - } - - // Alignment - else if ((tag->Name == _T("\\an") || tag->Name == _T("\\a")) && tag->Params.size() >= 1) { - align = tag->Params[0]->AsInt(); - if (tag->Name == _T("\\a")) { - switch(align) { - case 1: align = 1; break; - case 2: align = 2; break; - case 3: align = 3; break; - case 5: align = 7; break; - case 6: align = 8; break; - case 7: align = 9; break; - case 9: align = 4; break; - case 10: align = 5; break; - case 11: align = 6; break; - default: align = 2; break; - } - } - } - - // Origin - else if (!orgSet && tag->Name == _T("\\org") && tag->Params.size() >= 2) { - orgx = tag->Params[0]->AsInt(); - orgy = tag->Params[1]->AsInt(); - orgSet = true; - } - } - } - } - diag->ClearBlocks(); - - // Got position - if (posSet) { - x = posx; - y = posy; - if (!orgSet) { - orgx = x; - orgy = y; - } - return; - } - - // Alignment type - int hor = (align - 1) % 3; - int vert = (align - 1) / 3; - - // Calculate positions - if (hor == 0) x = margin[0]; - else if (hor == 1) x = (margin[0] + margin[1])/2; - else if (hor == 2) x = margin[1]; - if (vert == 0) y = margin[3]; - else if (vert == 1) y = (margin[2] + margin[3])/2; - else if (vert == 2) y = margin[2]; - - // No origin? - if (!orgSet) { - orgx = x; - orgy = y; - } -} - - -/////////////////////// -// Get line's rotation -void VideoDisplayVisual::GetLineRotation(AssDialogue *diag,float &rx,float &ry,float &rz) { - // Default values - rx = ry = rz = 0.0f; - - // Prepare overrides - diag->ParseASSTags(); - AssDialogueBlockOverride *override; - AssOverrideTag *tag; - size_t blockn = diag->Blocks.size(); - if (blockn == 0) { - diag->ClearBlocks(); - return; - } - - // Process override - override = AssDialogueBlock::GetAsOverride(diag->Blocks.at(0)); - if (override) { - for (size_t j=0;jTags.size();j++) { - tag = override->Tags.at(j); - if (tag->Name == _T("\\frx") && tag->Params.size() == 1) { - rx = tag->Params[0]->AsFloat(); - } - if (tag->Name == _T("\\fry") && tag->Params.size() == 1) { - ry = tag->Params[0]->AsFloat(); - } - if ((tag->Name == _T("\\frz") || tag->Name == _T("\fr")) && tag->Params.size() == 1) { - rz = tag->Params[0]->AsFloat(); - } - } - } - diag->ClearBlocks(); -} - - -//////////////////// -// Get line's scale -void VideoDisplayVisual::GetLineScale(AssDialogue *diag,float &scalX,float &scalY) { - // Default values - scalX = scalY = 100.0f; - - // Prepare overrides - diag->ParseASSTags(); - AssDialogueBlockOverride *override; - AssOverrideTag *tag; - size_t blockn = diag->Blocks.size(); - if (blockn == 0) { - diag->ClearBlocks(); - return; - } - - // Process override - override = AssDialogueBlock::GetAsOverride(diag->Blocks.at(0)); - if (override) { - for (size_t j=0;jTags.size();j++) { - tag = override->Tags.at(j); - if (tag->Name == _T("\\fscx") && tag->Params.size() == 1) { - scalX = tag->Params[0]->AsFloat(); - } - if (tag->Name == _T("\\fscy") && tag->Params.size() == 1) { - scalY = tag->Params[0]->AsFloat(); - } - } - } - diag->ClearBlocks(); -} - - -/////////////////// -// Get line's clip -void VideoDisplayVisual::GetLineClip(AssDialogue *diag,int &x1,int &y1,int &x2,int &y2) { - // Default values - x1 = y1 = 0; - int sw,sh; - VideoContext::Get()->GetScriptSize(sw,sh); - x2 = sw-1; - y2 = sh-1; - - // Prepare overrides - diag->ParseASSTags(); - AssDialogueBlockOverride *override; - AssOverrideTag *tag; - size_t blockn = diag->Blocks.size(); - if (blockn == 0) { - diag->ClearBlocks(); - return; - } - - // Process override - override = AssDialogueBlock::GetAsOverride(diag->Blocks.at(0)); - if (override) { - for (size_t j=0;jTags.size();j++) { - tag = override->Tags.at(j); - if (tag->Name == _T("\\clip") && tag->Params.size() == 4) { - x1 = tag->Params[0]->AsInt(); - y1 = tag->Params[1]->AsInt(); - x2 = tag->Params[2]->AsInt(); - y2 = tag->Params[3]->AsInt(); - } - } - } - diag->ClearBlocks(); -} - - -/////////////// -// Mouse event -void VideoDisplayVisual::OnMouseEvent (wxMouseEvent &event) { - // Coords - int x = event.GetX(); - int y = event.GetY(); - parent->ConvertMouseCoords(x,y); - int w,h; - parent->GetClientSize(&w,&h); - int orgx = -1; - int orgy = -1; - int sw,sh; - VideoContext::Get()->GetScriptSize(sw,sh); - int frame_n = VideoContext::Get()->GetFrameN(); - SubtitlesGrid *grid = VideoContext::Get()->grid; - bool hasOverlay = false; - bool realTime = Options.AsBool(_T("Video Visual Realtime")); - - // Text of current coords - int vx = (sw * x + w/2) / w; - int vy = (sh * y + h/2) / h; - if (!event.ShiftDown()) mouseText = wxString::Format(_T("%i,%i"),vx,vy); - else mouseText = wxString::Format(_T("%i,%i"),vx - sw,vy - sh); - - // Start dragging - if (mode != 0 && event.LeftIsDown() && !holding) { - float rx,ry,rz,scalX,scalY; - AssDialogue *gotDiag = NULL; - - // Drag - if (mode == 1) { - // For each line - int numRows = VideoContext::Get()->grid->GetRows(); - //int startMs = VFR_Output.GetTimeAtFrame(frame_n,true); - //int endMs = VFR_Output.GetTimeAtFrame(frame_n,false); - AssDialogue *diag; - - // Don't uninvert this loop or selection will break - for (int i=numRows;--i>=0;) { - diag = VideoContext::Get()->grid->GetDialogue(i); - if (diag) { - // Line visible? - int f1 = VFR_Output.GetFrameAtTime(diag->Start.GetMS(),true); - int f2 = VFR_Output.GetFrameAtTime(diag->End.GetMS(),false); - if (f1 <= frame_n && f2 >= frame_n) { - // Get position - int lineX,lineY; - int torgx,torgy; - GetLinePosition(diag,lineX,lineY,torgx,torgy); - lineX = lineX * w / sw; - lineY = lineY * h / sh; - orgx = orgx * w / sw; - orgy = orgy * h / sh; - - // Mouse over? - if (x >= lineX-8 && x <= lineX+8 && y >= lineY-8 && y <= lineY+8) { - VideoContext::Get()->grid->editBox->SetToLine(i,true); - gotDiag = diag; - origX = lineX; - origY = lineY; - orgx = torgx; - orgy = torgy; - break; - } - } - } - } - } - - // Pick active line - else { - // Get active - gotDiag = VideoContext::Get()->grid->GetDialogue(VideoContext::Get()->grid->editBox->linen); - - // Check if it's within range - if (gotDiag) { - int f1 = VFR_Output.GetFrameAtTime(gotDiag->Start.GetMS(),true); - int f2 = VFR_Output.GetFrameAtTime(gotDiag->End.GetMS(),false); - - // Invisible - if (f1 > frame_n || f2 < frame_n) { - gotDiag = NULL; - } - - // OK - else { - GetLinePosition(gotDiag,origX,origY,orgx,orgy); - } - } - } - - // Got a line? - if (gotDiag) { - // Set dialogue - curSelection = gotDiag; - lineOrgX = orgx; - lineOrgY = orgy; - - // Set coordinates - if (mode == 1) { - startX = x; - startY = y; - curSelection->StripTag(_T("\\pos")); - curSelection->StripTag(_T("\\move")); - } - - // Rotate Z - if (mode == 2) { - startFloat1 = atan2(double(lineOrgY-y*sh/h),double(x*sw/w-lineOrgX)) * 180.0 / 3.1415926535897932; - GetLineRotation(curSelection,rx,ry,rz); - origFloat1 = rz; - curFloat1 = rz; - curSelection->StripTag(_T("\\frz")); - curSelection->StripTag(_T("\\fr")); - } - - // Rotate XY - if (mode == 3) { - startFloat1 = (lineOrgY-y*sh/h)*2.0; - startFloat2 = (x*sw/w-lineOrgX)*2.0; - GetLineRotation(curSelection,rx,ry,rz); - origFloat1 = rx; - origFloat2 = ry; - curFloat1 = rx; - curFloat2 = ry; - curSelection->StripTag(_T("\\frx")); - curSelection->StripTag(_T("\\fry")); - } - - // Scale - if (mode == 4) { - //startScaleX = x; - //startScaleY = y; - startX = x; - startY = y; - GetLineScale(curSelection,scalX,scalY); - origFloat1 = scalX; - origFloat2 = scalY; - curFloat1 = scalX; - curFloat2 = scalY; - curSelection->StripTag(_T("\\fscx")); - curSelection->StripTag(_T("\\fscy")); - } - - // Clip - if (mode == 5) { - startX = x; - startY = y; - curSelection->StripTag(_T("\\clip")); - } - - // Commit changes to edit box - grid->editBox->TextEdit->SetTextTo(curSelection->Text); - grid->editBox->CommitText(true); - - // Hold it - holding = true; - hold = mode; - parent->CaptureMouse(); - hasOverlay = true; - } - } - - // Drag - if (hold == 1) { - curX = (x - startX + origX) * sw / w; - curY = (y - startY + origY) * sh / h; - if (realTime) { - AssLimitToVisibleFilter::SetFrame(frame_n); - grid->editBox->SetOverride(_T("\\pos"),wxString::Format(_T("(%i,%i)"),curX,curY),0,false); - grid->editBox->CommitText(true); - grid->CommitChanges(false,true); - } - } - - // Rotate Z - else if (hold == 2) { - // Find angle - float screenAngle = atan2(double(lineOrgY-y*sh/h),double(x*sw/w-lineOrgX)) * 180.0 / 3.1415926535897932; - curFloat1 = screenAngle - startFloat1 + origFloat1; - while (curFloat1 < 0.0f) curFloat1 += 360.0f; - while (curFloat1 >= 360.0f) curFloat1 -= 360.0f; - - // Snap - if (event.ShiftDown()) { - curFloat1 = (float)((int)((curFloat1+15.0f)/30.0f))*30.0f; - if (curFloat1 == 360.0f) curFloat1 = 0.0f; - } - - // Update - if (realTime) { - AssLimitToVisibleFilter::SetFrame(frame_n); - wxString param = PrettyFloat(wxString::Format(_T("(%0.3f)"),curFloat1)); - grid->editBox->SetOverride(_T("\\frz"),param,0,false); - grid->editBox->CommitText(true); - grid->CommitChanges(false,true); - } - } - - // Rotate XY - else if (hold == 3) { - // Find screen angles - float screenAngle = (lineOrgY-y*sh/h)*2.0; - float screenFloat2 = (x*sw/w-lineOrgX)*2.0; - - // Calculate - curFloat1 = screenAngle - startFloat1 + origFloat1; - curFloat2 = screenFloat2 - startFloat2 + origFloat2; - while (curFloat1 < 0.0) curFloat1 += 360.0; - while (curFloat1 >= 360.0) curFloat1 -= 360.0; - while (curFloat2 < 0.0) curFloat2 += 360.0; - while (curFloat2 >= 360.0) curFloat2 -= 360.0; - - // Oh Snap - if (event.ShiftDown()) { - curFloat1 = (float)((int)((curFloat1+15.0f)/30.0f))*30.0f; - curFloat2 = (float)((int)((curFloat2+15.0f)/30.0f))*30.0f; - if (curFloat1 == 360.0f) curFloat1 = 0.0f; - if (curFloat2 == 360.0f) curFloat1 = 0.0f; - } - - // Update - if (realTime) { - AssLimitToVisibleFilter::SetFrame(frame_n); - grid->editBox->SetOverride(_T("\\frx"),PrettyFloat(wxString::Format(_T("(%0.3f)"),curFloat1)),0,false); - grid->editBox->SetOverride(_T("\\fry"),PrettyFloat(wxString::Format(_T("(%0.3f)"),curFloat2)),0,false); - grid->editBox->CommitText(true); - grid->CommitChanges(false,true); - } - } - - // Scale - else if (hold == 4) { - // Calculate - curFloat1 = (float(x - startX)/0.8f) + origFloat1; - curFloat2 = (float(startY - y)/0.8f) + origFloat2; - if (curFloat1 < 0.0f) curFloat1 = 0.0f; - if (curFloat2 < 0.0f) curFloat2 = 0.0f; - - // Snap - if (event.ShiftDown()) { - curFloat1 = (float)((int)((curFloat1+12.5f)/25.0f))*25.0f; - curFloat2 = (float)((int)((curFloat2+12.5f)/25.0f))*25.0f; - } - - // Update - if (realTime) { - AssLimitToVisibleFilter::SetFrame(frame_n); - grid->editBox->SetOverride(_T("\\fscx"),PrettyFloat(wxString::Format(_T("(%0.3f)"),curFloat1)),0,false); - grid->editBox->SetOverride(_T("\\fscy"),PrettyFloat(wxString::Format(_T("(%0.3f)"),curFloat2)),0,false); - grid->editBox->CommitText(true); - grid->CommitChanges(false,true); - } - } - - // Clip - else if (hold == 5) { - // Coordinates - curX = startX * sw / w; - curY = startY * sh / h; - curX2 = x * sw / w; - curY2 = y * sh / h; - int temp; - if (curX > curX2) { - temp = curX; - curX = curX2; - curX2 = temp; - } - if (curY > curY2) { - temp = curY; - curY = curY2; - curY2 = temp; - } - - // Update - if (realTime) { - AssLimitToVisibleFilter::SetFrame(frame_n); - grid->editBox->SetOverride(_T("\\clip"),wxString::Format(_T("(%i,%i,%i,%i)"),curX,curY,curX2,curY2),0,false); - grid->editBox->CommitText(true); - grid->CommitChanges(false,true); - } - } - - // End dragging - if (holding && !event.LeftIsDown()) { - // Disable limiting - if (realTime) AssLimitToVisibleFilter::SetFrame(-1); - - // Finished dragging subtitles - if (hold == 1) { - grid->editBox->SetOverride(_T("\\pos"),wxString::Format(_T("(%i,%i)"),curX,curY),0,false); - } - - // Finished rotating Z - else if (hold == 2) { - grid->editBox->SetOverride(_T("\\frz"),PrettyFloat(wxString::Format(_T("(%0.3f)"),curFloat1)),0,false); - } - - // Finished rotating XY - else if (hold == 3) { - grid->editBox->SetOverride(_T("\\frx"),PrettyFloat(wxString::Format(_T("(%0.3f)"),curFloat1)),0,false); - grid->editBox->SetOverride(_T("\\fry"),PrettyFloat(wxString::Format(_T("(%0.3f)"),curFloat2)),0,false); - } - - // Finished scaling - else if (hold == 4) { - grid->editBox->SetOverride(_T("\\fscx"),PrettyFloat(wxString::Format(_T("(%0.3f)"),curFloat1)),0,false); - grid->editBox->SetOverride(_T("\\fscy"),PrettyFloat(wxString::Format(_T("(%0.3f)"),curFloat2)),0,false); - } - - // Finished clipping - else if (hold == 5) { - grid->editBox->SetOverride(_T("\\clip"),wxString::Format(_T("(%i,%i,%i,%i)"),curX,curY,curX2,curY2),0,false); - } - - // Commit - grid->editBox->CommitText(); - grid->ass->FlagAsModified(_("visual typesetting")); - grid->CommitChanges(false,true); - - // Set flags - hold = 0; - holding = false; - hasOverlay = true; - - // Clean up - curSelection = NULL; - parent->ReleaseMouse(); - parent->SetFocus(); - } - - // Double click - if (mode == 0 && event.LeftDClick()) { - grid->editBox->SetOverride(_T("\\pos"),wxString::Format(_T("(%i,%i)"),vx,vy),0,false); - grid->editBox->CommitText(); - grid->ass->FlagAsModified(_("positioning")); - grid->CommitChanges(false,true); - parent->SetFocus(); - } - - // Hover - if (x != mouseX || y != mouseY) { - // Set coords - mouseX = x; - mouseY = y; - hasOverlay = true; - } - if (event.Leaving()) { - mouseX = -1; - mouseY = -1; - } - - // Has something to draw - if (hasOverlay) { - //DrawOverlay(); - parent->Render(); - } -} - - -///////////// -// Key event -void VideoDisplayVisual::OnKeyEvent(wxKeyEvent &event) { - // FIXME: should these be configurable? - // Think of the frenchmen and other people not using qwerty layout - if (event.GetKeyCode() == 'A') SetMode(0); - if (event.GetKeyCode() == 'S') SetMode(1); - if (event.GetKeyCode() == 'D') SetMode(2); - if (event.GetKeyCode() == 'F') SetMode(3); - if (event.GetKeyCode() == 'G') SetMode(4); - if (event.GetKeyCode() == 'H') SetMode(5); -} diff --git a/aegisub/video_draggable_feature.cpp b/aegisub/visual_feature.cpp similarity index 91% rename from aegisub/video_draggable_feature.cpp rename to aegisub/visual_feature.cpp index db2a37a8c..2576c2aa2 100644 --- a/aegisub/video_draggable_feature.cpp +++ b/aegisub/visual_feature.cpp @@ -36,12 +36,12 @@ /////////// // Headers -#include "video_draggable_feature.h" +#include "visual_feature.h" /////////////// // Constructor -VideoDraggableFeature::VideoDraggableFeature() { +VisualDraggableFeature::VisualDraggableFeature() { type = DRAG_NONE; x = -1; y = -1; @@ -51,12 +51,12 @@ VideoDraggableFeature::VideoDraggableFeature() { ///////////////////// // Is mouse over it? -bool VideoDraggableFeature::IsMouseOver(int x,int y) { +bool VisualDraggableFeature::IsMouseOver(int x,int y) { return false; } //////////////// // Draw feature -void VideoDraggableFeature::Draw(bool highlighted) { +void VisualDraggableFeature::Draw(bool highlighted) { } diff --git a/aegisub/video_draggable_feature.h b/aegisub/visual_feature.h similarity index 97% rename from aegisub/video_draggable_feature.h rename to aegisub/visual_feature.h index 3733c9563..8e0f2c327 100644 --- a/aegisub/video_draggable_feature.h +++ b/aegisub/visual_feature.h @@ -55,7 +55,7 @@ enum DraggableFeatureType { ///////////////////// // Drag-able feature -class VideoDraggableFeature { +class VisualDraggableFeature { public: DraggableFeatureType type; int x,y; @@ -65,5 +65,5 @@ public: bool IsMouseOver(int x,int y); void Draw(bool highlighted); - VideoDraggableFeature(); + VisualDraggableFeature(); }; diff --git a/aegisub/visual_tool.cpp b/aegisub/visual_tool.cpp new file mode 100644 index 000000000..4248d78e4 --- /dev/null +++ b/aegisub/visual_tool.cpp @@ -0,0 +1,338 @@ +// Copyright (c) 2007, Rodrigo Braz Monteiro +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// ----------------------------------------------------------------------------- +// +// AEGISUB +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:zeratul@cellosoft.com +// + + +////////////// +// Headers +#include +#include +#include +#include "visual_tool.h" +#include "video_display.h" +#include "video_provider.h" +#include "vfr.h" +#include "ass_file.h" +#include "ass_time.h" +#include "ass_dialogue.h" +#include "ass_override.h" +#include "ass_style.h" +#include "subs_grid.h" +#include "options.h" +#include "subs_edit_box.h" +#include "export_visible_lines.h" +#include "utils.h" + + +/////////////// +// Constructor +VisualTool::VisualTool(VideoDisplay *par) { + parent = par; + colour[0] = wxColour(27,60,114); + colour[1] = wxColour(166,247,177); + colour[2] = wxColour(255,255,255); + colour[3] = wxColour(187,0,0); +} + + +////////////// +// Destructor +VisualTool::~VisualTool() { +} + + +//////////////////////// +// Get position of line +void VisualTool::GetLinePosition(AssDialogue *diag,int &x, int &y) { + int orgx=0,orgy=0; + GetLinePosition(diag,x,y,orgx,orgy); +} +void VisualTool::GetLinePosition(AssDialogue *diag,int &x, int &y, int &orgx, int &orgy) { + // No dialogue + if (!diag) { + x = -1; + y = -1; + return; + } + + // Default values + int margin[4]; + for (int i=0;i<4;i++) margin[i] = diag->Margin[i]; + int align = 2; + + // Get style + AssStyle *style = VideoContext::Get()->grid->ass->GetStyle(diag->Style); + if (style) { + align = style->alignment; + for (int i=0;i<4;i++) { + if (margin[i] == 0) margin[i] = style->Margin[i]; + } + } + + // Script size + int sw,sh; + VideoContext::Get()->GetScriptSize(sw,sh); + + // Process margins + margin[3] = margin[2]; + margin[1] = sw - margin[1]; + margin[3] = sh - margin[3]; + + // Position + bool posSet = false; + bool orgSet = false; + int posx = -1; + int posy = -1; + + // Overrides processing + diag->ParseASSTags(); + AssDialogueBlockOverride *override; + AssOverrideTag *tag; + size_t blockn = diag->Blocks.size(); + for (size_t i=0;iBlocks.at(i)); + if (override) { + for (size_t j=0;jTags.size();j++) { + tag = override->Tags.at(j); + + // Position + if ((tag->Name == _T("\\pos") || tag->Name == _("\\move")) && tag->Params.size() >= 2) { + if (!posSet) { + posx = tag->Params[0]->AsInt(); + posy = tag->Params[1]->AsInt(); + posSet = true; + } + } + + // Alignment + else if ((tag->Name == _T("\\an") || tag->Name == _T("\\a")) && tag->Params.size() >= 1) { + align = tag->Params[0]->AsInt(); + if (tag->Name == _T("\\a")) { + switch(align) { + case 1: align = 1; break; + case 2: align = 2; break; + case 3: align = 3; break; + case 5: align = 7; break; + case 6: align = 8; break; + case 7: align = 9; break; + case 9: align = 4; break; + case 10: align = 5; break; + case 11: align = 6; break; + default: align = 2; break; + } + } + } + + // Origin + else if (!orgSet && tag->Name == _T("\\org") && tag->Params.size() >= 2) { + orgx = tag->Params[0]->AsInt(); + orgy = tag->Params[1]->AsInt(); + orgSet = true; + } + } + } + } + diag->ClearBlocks(); + + // Got position + if (posSet) { + x = posx; + y = posy; + if (!orgSet) { + orgx = x; + orgy = y; + } + return; + } + + // Alignment type + int hor = (align - 1) % 3; + int vert = (align - 1) / 3; + + // Calculate positions + if (hor == 0) x = margin[0]; + else if (hor == 1) x = (margin[0] + margin[1])/2; + else if (hor == 2) x = margin[1]; + if (vert == 0) y = margin[3]; + else if (vert == 1) y = (margin[2] + margin[3])/2; + else if (vert == 2) y = margin[2]; + + // No origin? + if (!orgSet) { + orgx = x; + orgy = y; + } +} + + +/////////////////////// +// Get line's rotation +void VisualTool::GetLineRotation(AssDialogue *diag,float &rx,float &ry,float &rz) { + // Default values + rx = ry = rz = 0.0f; + + // Prepare overrides + diag->ParseASSTags(); + AssDialogueBlockOverride *override; + AssOverrideTag *tag; + size_t blockn = diag->Blocks.size(); + if (blockn == 0) { + diag->ClearBlocks(); + return; + } + + // Process override + override = AssDialogueBlock::GetAsOverride(diag->Blocks.at(0)); + if (override) { + for (size_t j=0;jTags.size();j++) { + tag = override->Tags.at(j); + if (tag->Name == _T("\\frx") && tag->Params.size() == 1) { + rx = tag->Params[0]->AsFloat(); + } + if (tag->Name == _T("\\fry") && tag->Params.size() == 1) { + ry = tag->Params[0]->AsFloat(); + } + if ((tag->Name == _T("\\frz") || tag->Name == _T("\fr")) && tag->Params.size() == 1) { + rz = tag->Params[0]->AsFloat(); + } + } + } + diag->ClearBlocks(); +} + + +//////////////////// +// Get line's scale +void VisualTool::GetLineScale(AssDialogue *diag,float &scalX,float &scalY) { + // Default values + scalX = scalY = 100.0f; + + // Prepare overrides + diag->ParseASSTags(); + AssDialogueBlockOverride *override; + AssOverrideTag *tag; + size_t blockn = diag->Blocks.size(); + if (blockn == 0) { + diag->ClearBlocks(); + return; + } + + // Process override + override = AssDialogueBlock::GetAsOverride(diag->Blocks.at(0)); + if (override) { + for (size_t j=0;jTags.size();j++) { + tag = override->Tags.at(j); + if (tag->Name == _T("\\fscx") && tag->Params.size() == 1) { + scalX = tag->Params[0]->AsFloat(); + } + if (tag->Name == _T("\\fscy") && tag->Params.size() == 1) { + scalY = tag->Params[0]->AsFloat(); + } + } + } + diag->ClearBlocks(); +} + + +/////////////////// +// Get line's clip +void VisualTool::GetLineClip(AssDialogue *diag,int &x1,int &y1,int &x2,int &y2) { + // Default values + x1 = y1 = 0; + int sw,sh; + VideoContext::Get()->GetScriptSize(sw,sh); + x2 = sw-1; + y2 = sh-1; + + // Prepare overrides + diag->ParseASSTags(); + AssDialogueBlockOverride *override; + AssOverrideTag *tag; + size_t blockn = diag->Blocks.size(); + if (blockn == 0) { + diag->ClearBlocks(); + return; + } + + // Process override + override = AssDialogueBlock::GetAsOverride(diag->Blocks.at(0)); + if (override) { + for (size_t j=0;jTags.size();j++) { + tag = override->Tags.at(j); + if (tag->Name == _T("\\clip") && tag->Params.size() == 4) { + x1 = tag->Params[0]->AsInt(); + y1 = tag->Params[1]->AsInt(); + x2 = tag->Params[2]->AsInt(); + y2 = tag->Params[3]->AsInt(); + } + } + } + diag->ClearBlocks(); +} + + +/////////////// +// Mouse event +void VisualTool::OnMouseEvent (wxMouseEvent &event) { + // Coords + int x = event.GetX(); + int y = event.GetY(); + parent->ConvertMouseCoords(x,y); + parent->GetClientSize(&w,&h); + VideoContext::Get()->GetScriptSize(sw,sh); + frame_n = VideoContext::Get()->GetFrameN(); + + // Hover + if (x != mouseX || y != mouseY) { + mouseX = x; + mouseY = y; + } + + // Mouse leaving control + if (event.Leaving()) { + mouseX = -1; + mouseY = -1; + } + + // Transformed mouse x/y + mx = mouseX * sw / w; + my = mouseY * sh / h; + + // Clicks + leftClick = event.ButtonDown(wxMOUSE_BTN_LEFT); + leftDClick = event.LeftDClick(); + + // Update + Update(); +} diff --git a/aegisub/video_display_visual.h b/aegisub/visual_tool.h similarity index 80% rename from aegisub/video_display_visual.h rename to aegisub/visual_tool.h index aedc91b66..3cdbd70f7 100644 --- a/aegisub/video_display_visual.h +++ b/aegisub/visual_tool.h @@ -39,9 +39,8 @@ /////////// // Headers +#include "video_display.h" #include "gl_wrap.h" -#include "video_draggable_feature.h" -#include ////////////// @@ -52,43 +51,35 @@ class AssDialogue; //////////////////////// // Visual handler class -class VideoDisplayVisual : public OpenGLWrapper { - friend class VideoDisplay; - +class VisualTool : public OpenGLWrapper { private: - wxColour colour[4]; - - int mouseX,mouseY; - int startX,startY; - int curX,curY,curX2,curY2; - int origX,origY; - float curFloat1,startFloat1,origFloat1; - float curFloat2,startFloat2,origFloat2; - int lineOrgX,lineOrgY; - - int mode; - int hold; - bool holding; - - wxString mouseText; - AssDialogue *curSelection; VideoDisplay *parent; - std::vector drags; +protected: + wxColour colour[4]; + + int w,h,sw,sh,mx,my; + int frame_n; + + bool leftClick; + bool leftDClick; void GetLinePosition(AssDialogue *diag,int &x,int &y); void GetLinePosition(AssDialogue *diag,int &x,int &y,int &orgx,int &orgy); void GetLineRotation(AssDialogue *diag,float &rx,float &ry,float &rz); void GetLineScale(AssDialogue *diag,float &scalX,float &scalY); void GetLineClip(AssDialogue *diag,int &x1,int &y1,int &x2,int &y2); + void FillPositionData(); - void DrawOverlay(); - void OnMouseEvent(wxMouseEvent &event); - void OnKeyEvent(wxKeyEvent &event); + VideoDisplay *GetParent() { return parent; } public: - void SetMode(int mode); + int mouseX,mouseY; - VideoDisplayVisual(VideoDisplay *parent); - ~VideoDisplayVisual(); + void OnMouseEvent(wxMouseEvent &event); + virtual void Update()=0; + virtual void Draw()=0; + + VisualTool(VideoDisplay *parent); + virtual ~VisualTool(); }; diff --git a/aegisub/visual_tool_cross.cpp b/aegisub/visual_tool_cross.cpp new file mode 100644 index 000000000..78a8ee2ae --- /dev/null +++ b/aegisub/visual_tool_cross.cpp @@ -0,0 +1,142 @@ +// Copyright (c) 2007, Rodrigo Braz Monteiro +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// ----------------------------------------------------------------------------- +// +// AEGISUB +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:zeratul@cellosoft.com +// + + +#pragma once + + +/////////// +// Headers +#include "visual_tool_cross.h" +#include "gl_text.h" +#include "subs_grid.h" +#include "subs_edit_box.h" +#include "ass_file.h" + + +/////////////// +// Constructor +VisualToolCross::VisualToolCross(VideoDisplay *_parent) +: VisualTool(_parent) +{ + _parent->ShowCursor(false); +} + + +////////////// +// Destructor +VisualToolCross::~VisualToolCross() { + GetParent()->ShowCursor(true); +} + + +////////// +// Update +void VisualToolCross::Update() { + // Position + if (leftDClick) { + int vx = (sw * mouseX + w/2) / w; + int vy = (sh * mouseY + h/2) / h; + SubtitlesGrid *grid = VideoContext::Get()->grid; + grid->editBox->SetOverride(_T("\\pos"),wxString::Format(_T("(%i,%i)"),vx,vy),0,false); + grid->editBox->CommitText(); + grid->ass->FlagAsModified(_("positioning")); + grid->CommitChanges(false,true); + } + + // Render parent + GetParent()->Render(); +} + + +//////// +// Draw +void VisualToolCross::Draw() { + // Is it outside? + if (mouseX == -1 || mouseY == -1) return; + + // Draw cross + glDisable(GL_LINE_SMOOTH); + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(GL_INVERT); + glBegin(GL_LINES); + glColor3f(1.0f,1.0f,1.0f); + glVertex2f(0,my); + glVertex2f(sw,my); + glVertex2f(mx,0); + glVertex2f(mx,sh); + glEnd(); + glDisable(GL_COLOR_LOGIC_OP); + + // Switch display + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0.0f,w,h,0.0f,-1000.0f,1000.0f); + glMatrixMode(GL_MODELVIEW); + + // Text of current coords + int dx = mouseX; + int dy = mouseY; + int vx = (sw * dx + w/2) / w; + int vy = (sh * dy + h/2) / h; + wxString mouseText; + if (!wxGetMouseState().ShiftDown()) mouseText = wxString::Format(_T("%i,%i"),vx,vy); + else mouseText = wxString::Format(_T("%i,%i"),vx - sw,vy - sh); + + // Setup gl text + int tw,th; + OpenGLText::SetFont(_T("Verdana"),12,true); + OpenGLText::SetColour(wxColour(255,255,255)); + OpenGLText::GetExtent(mouseText,tw,th); + + // Calculate draw position + bool left = dx > w/2; + bool bottom = dy < h/2; + + // Text draw coords + if (left) dx -= tw + 4; + else dx += 4; + if (bottom) dy += 3; + else dy -= th + 3; + + // Draw text + OpenGLText::Print(mouseText,dx,dy); + + // Restore matrix + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); +} diff --git a/aegisub/visual_tool_cross.h b/aegisub/visual_tool_cross.h new file mode 100644 index 000000000..786e5f00b --- /dev/null +++ b/aegisub/visual_tool_cross.h @@ -0,0 +1,54 @@ +// Copyright (c) 2007, Rodrigo Braz Monteiro +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// ----------------------------------------------------------------------------- +// +// AEGISUB +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:zeratul@cellosoft.com +// + + +#pragma once + + +/////////// +// Headers +#include "visual_tool.h" + + +//////////////////////// +// Crosshair tool class +class VisualToolCross : public VisualTool { +public: + VisualToolCross(VideoDisplay *parent); + ~VisualToolCross(); + + void Update(); + void Draw(); +};