2007-01-08 22:11:06 +01:00
// Copyright (c) 2005-2007, Rodrigo Braz Monteiro
2006-01-16 22:02:54 +01:00
// 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.
//
2009-07-29 07:43:02 +02:00
// Aegisub Project http://www.aegisub.org/
2006-01-16 22:02:54 +01:00
//
2009-07-29 07:43:02 +02:00
// $Id$
/// @file video_display.cpp
/// @brief Control displaying a video frame obtained from the video context
/// @ingroup video main_ui
///
2006-01-16 22:02:54 +01:00
// Includes
2009-01-04 07:31:48 +01:00
# include "config.h"
2009-09-10 15:06:40 +02:00
# ifndef AGI_PRE
# include <wx/clipbrd.h>
# include <wx/dataobj.h>
# include <wx/dcclient.h>
2007-01-23 21:50:41 +01:00
# include <wx/glcanvas.h>
2009-09-10 15:06:40 +02:00
# include <wx/menu.h>
# endif
2007-09-12 01:22:26 +02:00
# ifdef __APPLE__
2007-04-22 04:24:27 +02:00
# include <OpenGL/GL.h>
# include <OpenGL/glu.h>
# else
2007-01-22 23:57:45 +01:00
# include <GL/gl.h>
# include <GL/glu.h>
2007-04-22 04:24:27 +02:00
# endif
2009-09-10 15:06:40 +02:00
2006-01-16 22:02:54 +01:00
# include "ass_dialogue.h"
2009-09-10 15:06:40 +02:00
# include "hotkeys.h"
2006-01-16 22:02:54 +01:00
# include "options.h"
2009-09-10 15:06:40 +02:00
# include "utils.h"
2009-10-05 06:22:28 +02:00
# include "video_out_gl.h"
2009-09-10 15:06:40 +02:00
# include "vfr.h"
2007-01-11 04:53:20 +01:00
# include "video_box.h"
2009-09-10 03:41:34 +02:00
# include "video_context.h"
2009-09-10 15:06:40 +02:00
# include "video_display.h"
# include "video_provider_manager.h"
2009-10-05 06:22:28 +02:00
# include "video_slider.h"
2007-07-01 02:19:55 +02:00
# include "visual_tool.h"
2009-09-10 15:06:40 +02:00
# include "visual_tool_clip.h"
2007-07-01 02:19:55 +02:00
# include "visual_tool_cross.h"
2009-09-10 15:06:40 +02:00
# include "visual_tool_drag.h"
2007-07-01 04:46:12 +02:00
# include "visual_tool_rotatexy.h"
2009-09-10 15:06:40 +02:00
# include "visual_tool_rotatez.h"
2007-07-01 05:17:56 +02:00
# include "visual_tool_scale.h"
2007-07-05 06:32:46 +02:00
# include "visual_tool_vector_clip.h"
2009-09-10 15:06:40 +02:00
2006-01-16 22:02:54 +01:00
2009-09-10 03:41:34 +02:00
// Menu item IDs
2006-01-16 22:02:54 +01:00
enum {
2009-09-10 03:41:34 +02:00
/// Copy mouse coordinates to clipboard
2007-04-08 00:03:06 +02:00
VIDEO_MENU_COPY_COORDS = 1230 ,
2009-09-10 03:41:34 +02:00
/// Copy frame to clipboard with subtitles
2007-04-08 00:03:06 +02:00
VIDEO_MENU_COPY_TO_CLIPBOARD ,
2009-09-10 03:41:34 +02:00
/// Copy frame to clipboard without subtitles
2007-04-08 00:03:06 +02:00
VIDEO_MENU_COPY_TO_CLIPBOARD_RAW ,
2009-09-10 03:41:34 +02:00
/// Save frame with subtitles
2006-01-16 22:02:54 +01:00
VIDEO_MENU_SAVE_SNAPSHOT ,
2009-09-10 03:41:34 +02:00
/// Save frame without subtitles
2007-04-08 00:03:06 +02:00
VIDEO_MENU_SAVE_SNAPSHOT_RAW
2006-01-16 22:02:54 +01:00
} ;
// Event table
2007-01-21 07:30:19 +01:00
BEGIN_EVENT_TABLE ( VideoDisplay , wxGLCanvas )
EVT_MOUSE_EVENTS ( VideoDisplay : : OnMouseEvent )
2007-01-23 21:50:41 +01:00
EVT_KEY_DOWN ( VideoDisplay : : OnKey )
2007-01-21 07:30:19 +01:00
EVT_PAINT ( VideoDisplay : : OnPaint )
2007-01-23 05:42:08 +01:00
EVT_SIZE ( VideoDisplay : : OnSizeEvent )
2007-01-21 07:30:19 +01:00
EVT_ERASE_BACKGROUND ( VideoDisplay : : OnEraseBackground )
2006-01-16 22:02:54 +01:00
2007-04-08 00:03:06 +02:00
EVT_MENU ( VIDEO_MENU_COPY_COORDS , VideoDisplay : : OnCopyCoords )
2006-01-16 22:02:54 +01:00
EVT_MENU ( VIDEO_MENU_COPY_TO_CLIPBOARD , VideoDisplay : : OnCopyToClipboard )
EVT_MENU ( VIDEO_MENU_SAVE_SNAPSHOT , VideoDisplay : : OnSaveSnapshot )
2007-04-08 00:03:06 +02:00
EVT_MENU ( VIDEO_MENU_COPY_TO_CLIPBOARD_RAW , VideoDisplay : : OnCopyToClipboardRaw )
EVT_MENU ( VIDEO_MENU_SAVE_SNAPSHOT_RAW , VideoDisplay : : OnSaveSnapshotRaw )
2006-01-16 22:02:54 +01:00
END_EVENT_TABLE ( )
2009-09-10 03:41:34 +02:00
/// Attribute list for gl canvases; set the canvases to doublebuffered rgba with an 8 bit stencil buffer
2007-07-05 06:32:46 +02:00
int attribList [ ] = { WX_GL_RGBA , WX_GL_DOUBLEBUFFER , WX_GL_STENCIL_SIZE , 8 , 0 } ;
2007-01-22 23:57:45 +01:00
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
2009-09-10 03:41:34 +02:00
/// @brief Constructor
/// @param parent Pointer to a parent window.
/// @param id Window identifier. If -1, will automatically create an identifier.
/// @param pos Window position. wxDefaultPosition is (-1, -1) which indicates that wxWidgets should generate a default position for the window.
/// @param size Window size. wxDefaultSize is (-1, -1) which indicates that wxWidgets should generate a default size for the window. If no suitable size can be found, the window will be sized to 20x20 pixels so that the window is visible but obviously not correctly sized.
/// @param style Window style.
/// @param name Window name.
2009-10-05 06:22:28 +02:00
VideoDisplay : : VideoDisplay ( VideoBox * box , VideoSlider * ControlSlider , wxTextCtrl * PositionDisplay , wxTextCtrl * SubsPosition , wxWindow * parent , wxWindowID id , const wxPoint & pos , const wxSize & size , long style , const wxString & name )
: wxGLCanvas ( parent , id , attribList , pos , size , style , name )
, visualMode ( - 1 )
, origSize ( size )
, currentFrame ( - 1 )
, w ( 8 ) , h ( 8 ) , dx1 ( 0 ) , dx2 ( 8 ) , dy1 ( 0 ) , dy2 ( 8 )
, mouse_x ( - 1 ) , mouse_y ( - 1 )
, locked ( false )
, zoomValue ( 1.0 )
, ControlSlider ( ControlSlider )
, SubsPosition ( SubsPosition )
, PositionDisplay ( PositionDisplay )
, visual ( NULL )
2009-10-13 19:28:39 +02:00
, videoOut ( new VideoOutGL ( ) )
2009-10-05 06:22:28 +02:00
, box ( box )
, freeSize ( false )
2006-01-16 22:02:54 +01:00
{
2007-01-21 07:30:19 +01:00
SetCursor ( wxNullCursor ) ;
2006-01-16 22:02:54 +01:00
}
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
/// @brief Destructor
2006-01-16 22:02:54 +01:00
VideoDisplay : : ~ VideoDisplay ( ) {
2009-10-05 06:22:28 +02:00
if ( visual ) delete visual ;
2007-07-01 02:19:55 +02:00
visual = NULL ;
2007-01-21 07:30:19 +01:00
VideoContext : : Get ( ) - > RemoveDisplay ( this ) ;
2006-01-16 22:02:54 +01:00
}
2009-09-10 03:41:34 +02:00
/// @brief Set the cursor to either default or blank
2009-10-05 06:22:28 +02:00
/// @param show Whether or not the cursor should be visible
2007-04-18 06:51:17 +02:00
void VideoDisplay : : ShowCursor ( bool show ) {
if ( show ) SetCursor ( wxNullCursor ) ;
else {
wxCursor cursor ( wxCURSOR_BLANK ) ;
SetCursor ( cursor ) ;
}
}
2009-10-05 06:22:28 +02:00
void VideoDisplay : : SetFrame ( int frameNumber ) {
2009-10-27 15:27:39 +01:00
VideoContext * context = VideoContext : : Get ( ) ;
2009-10-05 06:22:28 +02:00
ControlSlider - > SetValue ( frameNumber ) ;
// Get time for frame
int time = VFR_Output . GetTimeAtFrame ( frameNumber , true , true ) ;
int h = time / 3600000 ;
int m = time % 3600000 / 60000 ;
int s = time % 60000 / 1000 ;
int ms = time % 1000 ;
// Set the text box for frame number and time
PositionDisplay - > SetValue ( wxString : : Format ( _T ( " %01i:%02i:%02i.%03i - %i " ) , h , m , s , ms , frameNumber ) ) ;
2009-10-27 15:27:39 +01:00
if ( context - > GetKeyFrames ( ) . Index ( frameNumber ) ! = wxNOT_FOUND ) {
2009-10-05 06:22:28 +02:00
// Set the background color to indicate this is a keyframe
PositionDisplay - > SetBackgroundColour ( Options . AsColour ( _T ( " Grid selection background " ) ) ) ;
PositionDisplay - > SetForegroundColour ( Options . AsColour ( _T ( " Grid selection foreground " ) ) ) ;
}
else {
PositionDisplay - > SetBackgroundColour ( wxNullColour ) ;
PositionDisplay - > SetForegroundColour ( wxNullColour ) ;
}
wxString startSign ;
wxString endSign ;
int startOff = 0 ;
int endOff = 0 ;
2009-10-27 15:27:39 +01:00
if ( AssDialogue * curLine = context - > curLine ) {
2009-10-05 06:22:28 +02:00
startOff = time - curLine - > Start . GetMS ( ) ;
endOff = time - curLine - > End . GetMS ( ) ;
}
// Positive signs
if ( startOff > 0 ) startSign = _T ( " + " ) ;
if ( endOff > 0 ) endSign = _T ( " + " ) ;
2009-06-01 17:26:26 +02:00
2009-10-05 06:22:28 +02:00
// Set the text box for time relative to active subtitle line
SubsPosition - > SetValue ( wxString : : Format ( _T ( " %s%ims; %s%ims " ) , startSign . c_str ( ) , startOff , endSign . c_str ( ) , endOff ) ) ;
2009-10-13 19:28:39 +02:00
if ( IsShownOnScreen ( ) & & visual ) visual - > Refresh ( ) ;
2009-10-05 06:22:28 +02:00
2009-10-13 19:28:39 +02:00
// Render the new frame
2009-10-27 15:27:39 +01:00
if ( context - > IsLoaded ( ) ) {
2009-12-01 01:32:43 +01:00
AegiVideoFrame frame ;
try {
frame = context - > GetFrame ( frameNumber ) ;
}
catch ( const wxChar * err ) {
wxLogError (
_T ( " Failed seeking video. The video file may be corrupt or incomplete. \n " )
_T ( " Error message reported: %s " ) ,
err ) ;
}
catch ( . . . ) {
wxLogError (
_T ( " Failed seeking video. The video file may be corrupt or incomplete. \n " )
_T ( " No further error message given. " ) ) ;
}
try {
videoOut - > UploadFrameData ( frame ) ;
}
catch ( const VideoOutInitException & err ) {
wxLogError (
L " Failed to initialize video display. Closing other running programs and updating your video card drivers may fix this. \n "
L " Error message reported: %s " ,
2009-12-13 20:27:45 +01:00
err . GetMessage ( ) . c_str ( ) ) ;
2009-12-01 01:32:43 +01:00
context - > Reset ( ) ;
}
catch ( const VideoOutRenderException & err ) {
wxLogError (
L " Could not upload video frame to graphics card. \n "
L " Error message reported: %s " ,
2009-12-13 20:27:45 +01:00
err . GetMessage ( ) . c_str ( ) ) ;
2009-12-01 01:32:43 +01:00
}
2009-10-27 15:27:39 +01:00
}
Render ( ) ;
2009-10-05 06:22:28 +02:00
currentFrame = frameNumber ;
}
void VideoDisplay : : SetFrameRange ( int from , int to ) {
ControlSlider - > SetRange ( from , to ) ;
}
/// @brief Render the currently visible frame
2009-10-27 15:27:39 +01:00
void VideoDisplay : : Render ( ) try {
2007-01-23 05:42:08 +01:00
if ( ! IsShownOnScreen ( ) ) return ;
2010-01-24 20:05:20 +01:00
wxASSERT ( wxIsMainThread ( ) ) ;
2007-01-21 07:30:19 +01:00
VideoContext * context = VideoContext : : Get ( ) ;
2007-03-30 01:04:26 +02:00
wxASSERT ( context ) ;
2007-04-02 01:07:29 +02:00
if ( ! context - > IsLoaded ( ) ) return ;
// Set GL context
2007-01-21 07:30:19 +01:00
SetCurrent ( * context - > GetGLContext ( this ) ) ;
// Get sizes
2009-10-05 06:22:28 +02:00
int w , h , sw , sh , pw , ph ;
GetClientSize ( & w , & h ) ;
2007-03-30 01:04:26 +02:00
wxASSERT ( w > 0 ) ;
wxASSERT ( h > 0 ) ;
2009-10-05 06:22:28 +02:00
context - > GetScriptSize ( sw , sh ) ;
2007-01-21 07:30:19 +01:00
pw = context - > GetWidth ( ) ;
ph = context - > GetHeight ( ) ;
2007-03-30 01:04:26 +02:00
wxASSERT ( pw > 0 ) ;
wxASSERT ( ph > 0 ) ;
2007-01-21 07:30:19 +01:00
2007-01-23 07:32:16 +01:00
// Freesized transform
dx1 = 0 ;
dy1 = 0 ;
dx2 = w ;
dy2 = h ;
if ( freeSize ) {
2007-03-30 01:04:26 +02:00
// Set aspect ratio
2007-01-23 07:32:16 +01:00
float thisAr = float ( w ) / float ( h ) ;
2009-10-05 06:22:28 +02:00
float vidAr = context - > GetAspectRatioType ( ) = = 0 ? float ( pw ) / float ( ph ) : context - > GetAspectRatioValue ( ) ;
2007-01-23 07:32:16 +01:00
// Window is wider than video, blackbox left/right
if ( thisAr - vidAr > 0.01f ) {
2007-04-04 22:42:44 +02:00
int delta = int ( w - vidAr * h ) ;
2007-01-23 07:32:16 +01:00
dx1 + = delta / 2 ;
dx2 - = delta ;
}
// Video is wider than window, blackbox top/bottom
else if ( vidAr - thisAr > 0.01f ) {
2007-04-04 22:42:44 +02:00
int delta = int ( h - w / vidAr ) ;
2007-01-23 07:32:16 +01:00
dy1 + = delta / 2 ;
dy2 - = delta ;
}
}
2010-01-24 20:05:20 +01:00
videoOut - > SetViewport ( dx1 , dy1 , dx2 , dy2 ) ;
2009-10-27 15:27:39 +01:00
videoOut - > Render ( sw , sh ) ;
2009-10-05 06:22:28 +02:00
2007-06-28 22:29:56 +02:00
DrawTVEffects ( ) ;
2007-01-02 21:07:52 +01:00
2009-10-05 06:22:28 +02:00
if ( visualMode = = - 1 ) SetVisualMode ( 0 , false ) ;
2007-07-01 02:19:55 +02:00
if ( visual ) visual - > Draw ( ) ;
2007-01-02 21:07:52 +01:00
2007-04-13 02:44:46 +02:00
glFinish ( ) ;
2007-01-21 07:30:19 +01:00
SwapBuffers ( ) ;
2007-01-02 21:07:52 +01:00
}
2009-10-05 06:22:28 +02:00
catch ( const VideoOutException & err ) {
2009-12-01 01:32:43 +01:00
wxLogError (
_T ( " An error occurred trying to render the video frame on the screen. \n " )
2009-10-05 06:22:28 +02:00
_T ( " Error message reported: %s " ) ,
2009-12-13 20:27:45 +01:00
err . GetMessage ( ) . c_str ( ) ) ;
2009-10-05 06:22:28 +02:00
VideoContext : : Get ( ) - > Reset ( ) ;
}
2009-06-01 17:26:26 +02:00
catch ( . . . ) {
wxLogError (
_T ( " An error occurred trying to render the video frame to screen. \n " )
_T ( " No further error message given. " ) ) ;
VideoContext : : Get ( ) - > Reset ( ) ;
}
2007-01-02 21:07:52 +01:00
2009-09-10 03:41:34 +02:00
/// @brief Draw the appropriate overscan masks for the current aspect ratio
2007-06-28 22:29:56 +02:00
void VideoDisplay : : DrawTVEffects ( ) {
// Get coordinates
int sw , sh ;
VideoContext * context = VideoContext : : Get ( ) ;
context - > GetScriptSize ( sw , sh ) ;
2007-06-28 23:35:37 +02:00
bool drawOverscan = Options . AsBool ( _T ( " Show Overscan Mask " ) ) ;
2007-06-28 22:29:56 +02:00
if ( drawOverscan ) {
2009-09-10 03:41:34 +02:00
// Get aspect ratio
2007-06-29 01:27:37 +02:00
double ar = context - > GetAspectRatioValue ( ) ;
// Based on BBC's guidelines: http://www.bbc.co.uk/guidelines/dq/pdf/tv/tv_standards_london.pdf
// 16:9 or wider
if ( ar > 1.75 ) {
DrawOverscanMask ( int ( sw * 0.1 ) , int ( sh * 0.05 ) , wxColour ( 30 , 70 , 200 ) , 0.5 ) ;
DrawOverscanMask ( int ( sw * 0.035 ) , int ( sh * 0.035 ) , wxColour ( 30 , 70 , 200 ) , 0.5 ) ;
}
// Less wide than 16:9 (use 4:3 standard)
else {
DrawOverscanMask ( int ( sw * 0.067 ) , int ( sh * 0.05 ) , wxColour ( 30 , 70 , 200 ) , 0.5 ) ;
DrawOverscanMask ( int ( sw * 0.033 ) , int ( sh * 0.035 ) , wxColour ( 30 , 70 , 200 ) , 0.5 ) ;
}
2007-06-28 22:29:56 +02:00
}
}
2009-09-10 03:41:34 +02:00
/// @brief Draw an overscan mask
/// @param sizeH The amount of horizontal overscan on one side
/// @param sizeV The amount of vertical overscan on one side
/// @param colour The color of the mask
/// @param alpha The alpha of the mask
2007-06-28 22:29:56 +02:00
void VideoDisplay : : DrawOverscanMask ( int sizeH , int sizeV , wxColour colour , double alpha ) {
// Parameters
int sw , sh ;
VideoContext * context = VideoContext : : Get ( ) ;
context - > GetScriptSize ( sw , sh ) ;
2007-06-28 23:35:37 +02:00
int rad1 = int ( sh * 0.05 ) ;
2007-06-28 22:29:56 +02:00
int gapH = sizeH + rad1 ;
int gapV = sizeV + rad1 ;
int rad2 = ( int ) sqrt ( double ( gapH * gapH + gapV * gapV ) ) + 1 ;
// Set up GL wrapper
OpenGLWrapper gl ;
gl . SetFillColour ( colour , alpha ) ;
gl . SetLineColour ( wxColour ( 0 , 0 , 0 ) , 0.0 , 1 ) ;
// Draw rectangles
gl . DrawRectangle ( gapH , 0 , sw - gapH , sizeV ) ; // Top
gl . DrawRectangle ( sw - sizeH , gapV , sw , sh - gapV ) ; // Right
gl . DrawRectangle ( gapH , sh - sizeV , sw - gapH , sh ) ; // Bottom
gl . DrawRectangle ( 0 , gapV , sizeH , sh - gapV ) ; // Left
// Draw corners
gl . DrawRing ( gapH , gapV , rad1 , rad2 , 1.0 , 180.0 , 270.0 ) ; // Top-left
gl . DrawRing ( sw - gapH , gapV , rad1 , rad2 , 1.0 , 90.0 , 180.0 ) ; // Top-right
gl . DrawRing ( sw - gapH , sh - gapV , rad1 , rad2 , 1.0 , 0.0 , 90.0 ) ; // Bottom-right
gl . DrawRing ( gapH , sh - gapV , rad1 , rad2 , 1.0 , 270.0 , 360.0 ) ; // Bottom-left
// Done
glDisable ( GL_BLEND ) ;
}
2009-09-10 03:41:34 +02:00
/// @brief Update the size of the display
2007-01-21 07:30:19 +01:00
void VideoDisplay : : UpdateSize ( ) {
2007-01-23 07:32:16 +01:00
VideoContext * con = VideoContext : : Get ( ) ;
2007-03-30 01:04:26 +02:00
wxASSERT ( con ) ;
2007-01-23 07:32:16 +01:00
if ( ! con - > IsLoaded ( ) ) return ;
2007-01-23 21:50:41 +01:00
if ( ! IsShownOnScreen ( ) ) return ;
2007-01-22 00:16:03 +01:00
2008-01-11 06:44:00 +01:00
if ( freeSize ) {
GetClientSize ( & w , & h ) ;
}
else {
if ( con - > GetAspectRatioType ( ) = = 0 ) w = int ( con - > GetWidth ( ) * zoomValue ) ;
else w = int ( con - > GetHeight ( ) * zoomValue * con - > GetAspectRatioValue ( ) ) ;
h = int ( con - > GetHeight ( ) * zoomValue ) ;
2010-01-31 19:49:37 +01:00
// Sizers ignore SetClientSize/SetSize, so only use them to calculate
// what size is required after including the borders
SetClientSize ( w , h ) ;
GetSize ( & w , & h ) ;
wxSize size ( w , h ) ;
SetMinSize ( size ) ;
SetMaxSize ( size ) ;
2009-10-09 04:21:30 +02:00
locked = true ;
box - > VideoSizer - > Fit ( box ) ;
box - > GetParent ( ) - > Layout ( ) ;
2010-01-31 19:49:37 +01:00
// The sizer makes us use the full width, which at very low zoom levels
// results in stretched video, so after using the sizer to update the
// parent window sizes, reset our size to the correct value
SetSize ( w , h ) ;
2009-10-09 04:21:30 +02:00
locked = false ;
2008-01-11 06:44:00 +01:00
}
2007-01-21 07:30:19 +01:00
Refresh ( false ) ;
2006-01-22 13:44:53 +01:00
}
2006-01-16 22:02:54 +01:00
2009-09-10 03:41:34 +02:00
/// @brief Reset the size of the display to the video size
2007-01-21 07:30:19 +01:00
void VideoDisplay : : Reset ( ) {
2007-03-30 01:04:26 +02:00
// Only calculate sizes if it's visible
if ( ! IsShownOnScreen ( ) ) return ;
2007-01-21 07:30:19 +01:00
int w = origSize . GetX ( ) ;
int h = origSize . GetY ( ) ;
2007-03-30 01:04:26 +02:00
wxASSERT ( w > 0 ) ;
wxASSERT ( h > 0 ) ;
2007-01-21 07:30:19 +01:00
SetClientSize ( w , h ) ;
int _w , _h ;
GetSize ( & _w , & _h ) ;
2007-03-30 01:04:26 +02:00
wxASSERT ( _w > 0 ) ;
wxASSERT ( _h > 0 ) ;
2007-01-21 07:30:19 +01:00
SetSizeHints ( _w , _h , _w , _h ) ;
2006-01-16 22:02:54 +01:00
}
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
/// @brief Paint event
/// @param event
2006-01-16 22:02:54 +01:00
void VideoDisplay : : OnPaint ( wxPaintEvent & event ) {
wxPaintDC dc ( this ) ;
2007-01-21 07:30:19 +01:00
Render ( ) ;
2006-01-16 22:02:54 +01:00
}
2009-09-10 03:41:34 +02:00
/// @brief Handle resize events
/// @param event
2007-01-23 05:42:08 +01:00
void VideoDisplay : : OnSizeEvent ( wxSizeEvent & event ) {
2009-09-10 03:41:34 +02:00
if ( freeSize ) UpdateSize ( ) ;
2007-01-23 21:50:41 +01:00
event . Skip ( ) ;
2007-01-23 05:42:08 +01:00
}
2009-09-10 03:41:34 +02:00
/// @brief Handle mouse events
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
/// @param event
2006-01-16 22:02:54 +01:00
void VideoDisplay : : OnMouseEvent ( wxMouseEvent & event ) {
2007-01-23 21:50:41 +01:00
// Locked?
if ( locked ) return ;
2008-03-07 00:27:54 +01:00
// Mouse coordinates
mouse_x = event . GetX ( ) ;
mouse_y = event . GetY ( ) ;
2006-01-16 22:02:54 +01:00
// Disable when playing
2007-01-21 07:30:19 +01:00
if ( VideoContext : : Get ( ) - > IsPlaying ( ) ) return ;
2006-01-16 22:02:54 +01:00
// Right click
if ( event . ButtonUp ( wxMOUSE_BTN_RIGHT ) ) {
2007-04-18 06:51:17 +02:00
// Create menu
2006-01-16 22:02:54 +01:00
wxMenu menu ;
menu . Append ( VIDEO_MENU_SAVE_SNAPSHOT , _ ( " Save PNG snapshot " ) ) ;
menu . Append ( VIDEO_MENU_COPY_TO_CLIPBOARD , _ ( " Copy image to Clipboard " ) ) ;
2007-04-08 00:03:06 +02:00
menu . AppendSeparator ( ) ;
2009-05-15 14:44:36 +02:00
menu . Append ( VIDEO_MENU_SAVE_SNAPSHOT_RAW , _ ( " Save PNG snapshot (no subtitles) " ) ) ;
menu . Append ( VIDEO_MENU_COPY_TO_CLIPBOARD_RAW , _ ( " Copy image to Clipboard (no subtitles) " ) ) ;
2007-04-08 00:03:06 +02:00
menu . AppendSeparator ( ) ;
2006-01-16 22:02:54 +01:00
menu . Append ( VIDEO_MENU_COPY_COORDS , _ ( " Copy coordinates to Clipboard " ) ) ;
2007-04-18 06:51:17 +02:00
// Show cursor and popup
ShowCursor ( true ) ;
2006-01-16 22:02:54 +01:00
PopupMenu ( & menu ) ;
return ;
}
2007-04-18 06:51:17 +02:00
// Enforce correct cursor display
2007-07-01 02:19:55 +02:00
ShowCursor ( visualMode ! = 0 ) ;
2007-04-18 06:51:17 +02:00
2007-01-09 02:52:30 +01:00
// Click?
if ( event . ButtonDown ( wxMOUSE_BTN_ANY ) ) {
SetFocus ( ) ;
}
2007-01-08 22:11:06 +01:00
// Send to visual
2007-07-01 02:19:55 +02:00
if ( visual ) visual - > OnMouseEvent ( event ) ;
2006-01-16 22:02:54 +01:00
}
2009-09-10 03:41:34 +02:00
/// @brief Handle keypress events for switching visual typesetting modes
/// @param event
2007-01-09 02:52:30 +01:00
void VideoDisplay : : OnKey ( wxKeyEvent & event ) {
2009-08-14 00:07:43 +02:00
int key = event . GetKeyCode ( ) ;
# ifdef __APPLE__
Hotkeys . SetPressed ( key , event . m_metaDown , event . m_altDown , event . m_shiftDown ) ;
# else
Hotkeys . SetPressed ( key , event . m_controlDown , event . m_altDown , event . m_shiftDown ) ;
# endif
if ( Hotkeys . IsPressed ( _T ( " Visual Tool Default " ) ) ) SetVisualMode ( 0 ) ;
else if ( Hotkeys . IsPressed ( _T ( " Visual Tool Drag " ) ) ) SetVisualMode ( 1 ) ;
else if ( Hotkeys . IsPressed ( _T ( " Visual Tool Rotate Z " ) ) ) SetVisualMode ( 2 ) ;
else if ( Hotkeys . IsPressed ( _T ( " Visual Tool Rotate X/Y " ) ) ) SetVisualMode ( 3 ) ;
else if ( Hotkeys . IsPressed ( _T ( " Visual Tool Scale " ) ) ) SetVisualMode ( 4 ) ;
else if ( Hotkeys . IsPressed ( _T ( " Visual Tool Rectangular Clip " ) ) ) SetVisualMode ( 5 ) ;
else if ( Hotkeys . IsPressed ( _T ( " Visual Tool Vector Clip " ) ) ) SetVisualMode ( 6 ) ;
2007-07-27 06:05:18 +02:00
event . Skip ( ) ;
2007-01-09 02:52:30 +01:00
}
2009-09-10 03:41:34 +02:00
/// @brief Set the zoom level
/// @param value The new zoom level
2006-01-16 22:02:54 +01:00
void VideoDisplay : : SetZoom ( double value ) {
2006-02-19 03:31:25 +01:00
zoomValue = value ;
2007-01-21 07:30:19 +01:00
UpdateSize ( ) ;
2006-01-16 22:02:54 +01:00
}
2009-09-10 03:41:34 +02:00
/// @brief Set the position of the zoom dropdown and switch to that zoom
/// @param value The new zoom position
2006-01-16 22:02:54 +01:00
void VideoDisplay : : SetZoomPos ( int value ) {
if ( value < 0 ) value = 0 ;
2009-10-06 19:43:15 +02:00
if ( value > 23 ) value = 23 ;
2006-01-16 22:02:54 +01:00
SetZoom ( double ( value + 1 ) / 8.0 ) ;
if ( zoomBox - > GetSelection ( ) ! = value ) zoomBox - > SetSelection ( value ) ;
}
2009-09-10 03:41:34 +02:00
/// @brief Copy the currently display frame to the clipboard, with subtitles
/// @param event Unused
2006-01-16 22:02:54 +01:00
void VideoDisplay : : OnCopyToClipboard ( wxCommandEvent & event ) {
if ( wxTheClipboard - > Open ( ) ) {
2007-01-21 07:30:19 +01:00
wxTheClipboard - > SetData ( new wxBitmapDataObject ( wxBitmap ( VideoContext : : Get ( ) - > GetFrame ( - 1 ) . GetImage ( ) , 24 ) ) ) ;
2006-01-16 22:02:54 +01:00
wxTheClipboard - > Close ( ) ;
}
}
2009-09-10 03:41:34 +02:00
/// @brief Copy the currently display frame to the clipboard, without subtitles
/// @param event Unused
2007-04-08 00:03:06 +02:00
void VideoDisplay : : OnCopyToClipboardRaw ( wxCommandEvent & event ) {
if ( wxTheClipboard - > Open ( ) ) {
wxTheClipboard - > SetData ( new wxBitmapDataObject ( wxBitmap ( VideoContext : : Get ( ) - > GetFrame ( - 1 , true ) . GetImage ( ) , 24 ) ) ) ;
wxTheClipboard - > Close ( ) ;
}
}
2009-09-10 03:41:34 +02:00
/// @brief Save the currently display frame to a file, with subtitles
/// @param event Unused
2006-01-16 22:02:54 +01:00
void VideoDisplay : : OnSaveSnapshot ( wxCommandEvent & event ) {
2007-04-08 00:03:06 +02:00
VideoContext : : Get ( ) - > SaveSnapshot ( false ) ;
}
2009-09-10 03:41:34 +02:00
/// @brief Save the currently display frame to a file, without subtitles
/// @param event Unused
2007-04-08 00:03:06 +02:00
void VideoDisplay : : OnSaveSnapshotRaw ( wxCommandEvent & event ) {
VideoContext : : Get ( ) - > SaveSnapshot ( true ) ;
2006-01-16 22:02:54 +01:00
}
2009-09-10 03:41:34 +02:00
/// @brief Copy coordinates of the mouse to the clipboard
/// @param event Unused
2006-01-16 22:02:54 +01:00
void VideoDisplay : : OnCopyCoords ( wxCommandEvent & event ) {
if ( wxTheClipboard - > Open ( ) ) {
int sw , sh ;
2007-01-21 07:30:19 +01:00
VideoContext : : Get ( ) - > GetScriptSize ( sw , sh ) ;
2008-03-07 00:27:54 +01:00
int vx = ( sw * mouse_x + w / 2 ) / w ;
int vy = ( sh * mouse_y + h / 2 ) / h ;
2006-01-16 22:02:54 +01:00
wxTheClipboard - > SetData ( new wxTextDataObject ( wxString : : Format ( _T ( " %i,%i " ) , vx , vy ) ) ) ;
wxTheClipboard - > Close ( ) ;
}
}
2009-09-10 03:41:34 +02:00
/// @brief Convert mouse coordinates relative to the display to coordinates relative to the video
/// @param x X coordinate
/// @param y Y coordinate
2007-01-23 07:32:16 +01:00
void VideoDisplay : : ConvertMouseCoords ( int & x , int & y ) {
int w , h ;
GetClientSize ( & w , & h ) ;
2007-03-30 01:04:26 +02:00
wxASSERT ( dx2 > 0 ) ;
wxASSERT ( dy2 > 0 ) ;
wxASSERT ( w > 0 ) ;
wxASSERT ( h > 0 ) ;
2007-01-23 07:32:16 +01:00
x = ( x - dx1 ) * w / dx2 ;
y = ( y - dy1 ) * h / dy2 ;
}
2007-07-01 02:19:55 +02:00
2009-09-10 03:41:34 +02:00
/// @brief Set the current visual typesetting mode
/// @param mode The new mode
2009-10-05 06:22:28 +02:00
/// @param render Whether the display should be rerendered
void VideoDisplay : : SetVisualMode ( int mode , bool render ) {
2007-07-01 02:19:55 +02:00
// Set visual
2007-07-04 06:24:47 +02:00
if ( visualMode ! = mode ) {
2007-07-07 05:21:52 +02:00
wxToolBar * toolBar = NULL ;
2007-07-04 06:24:47 +02:00
if ( box ) {
toolBar = box - > visualSubToolBar ;
2007-07-07 05:21:52 +02:00
toolBar - > ClearTools ( ) ;
toolBar - > Realize ( ) ;
toolBar - > Show ( false ) ;
2009-09-10 03:41:34 +02:00
if ( ! box - > visualToolBar - > GetToolState ( mode + Video_Mode_Standard ) ) {
box - > visualToolBar - > ToggleTool ( mode + Video_Mode_Standard , true ) ;
}
2007-07-04 06:24:47 +02:00
}
// Replace mode
visualMode = mode ;
delete visual ;
switch ( mode ) {
case 0 : visual = new VisualToolCross ( this ) ; break ;
2007-07-07 05:21:52 +02:00
case 1 : visual = new VisualToolDrag ( this , toolBar ) ; break ;
2007-07-04 06:24:47 +02:00
case 2 : visual = new VisualToolRotateZ ( this ) ; break ;
case 3 : visual = new VisualToolRotateXY ( this ) ; break ;
case 4 : visual = new VisualToolScale ( this ) ; break ;
case 5 : visual = new VisualToolClip ( this ) ; break ;
2007-07-07 05:21:52 +02:00
case 6 : visual = new VisualToolVectorClip ( this , toolBar ) ; break ;
2007-07-04 06:24:47 +02:00
default : visual = NULL ;
}
2009-09-10 03:41:34 +02:00
// Update size as the new typesetting tool may have changed the subtoolbar size
2007-07-04 06:24:47 +02:00
UpdateSize ( ) ;
2009-10-13 19:28:39 +02:00
ControlSlider - > Refresh ( false ) ;
2007-07-01 02:19:55 +02:00
}
2009-10-05 06:22:28 +02:00
if ( render ) Render ( ) ;
}
void VideoDisplay : : OnSubTool ( wxCommandEvent & event ) {
if ( visual ) visual - > OnSubTool ( event ) ;
2007-07-01 02:19:55 +02:00
}