Skip to content
Browse files

Merge pull request #1268 from Montellese/picture_zoom_rotate

Improved picture zooming and rotating on touch devices
  • Loading branch information...
2 parents d094268 + cd4ff8f commit e13dcf3cc2e4fca49448986ffb997b6c511c4db2 @Montellese Montellese committed
View
21 xbmc/android/activity/AndroidTouch.cpp
@@ -99,6 +99,20 @@ bool CAndroidTouch::OnSingleTouchStart(float x, float y)
return true;
}
+bool CAndroidTouch::OnMultiTouchStart(float x, float y, int32_t pointers /* = 2 */)
+{
+ XBMC_TouchGesture(ACTION_GESTURE_BEGIN, x, y, 0.0f, 0.0f);
+
+ return true;
+}
+
+bool CAndroidTouch::OnMultiTouchEnd(float x, float y, int32_t pointers /* = 2 */)
+{
+ XBMC_TouchGesture(ACTION_GESTURE_END, 0.0f, 0.0f, 0.0f, 0.0f);
+
+ return true;
+}
+
bool CAndroidTouch::OnTouchGesturePanStart(float x, float y)
{
XBMC_TouchGesture(ACTION_GESTURE_BEGIN, x, y, 0.0f, 0.0f);
@@ -141,6 +155,11 @@ void CAndroidTouch::OnZoomPinch(float centerX, float centerY, float zoomFactor)
XBMC_TouchGesture(ACTION_GESTURE_ZOOM, centerX, centerY, zoomFactor, 0);
}
+void CAndroidTouch::OnRotate(float centerX, float centerY, float angle)
+{
+ XBMC_TouchGesture(ACTION_GESTURE_ROTATE, centerX, centerY, angle, 0);
+}
+
void CAndroidTouch::XBMC_Touch(uint8_t type, uint8_t button, uint16_t x, uint16_t y)
{
XBMC_Event newEvent;
@@ -165,6 +184,6 @@ void CAndroidTouch::XBMC_TouchGesture(int32_t action, float posX, float posY, fl
CApplicationMessenger::Get().SendAction(CAction(action, 0, posX, posY, offsetX, offsetY), WINDOW_INVALID, false);
else if (action == ACTION_GESTURE_END)
CApplicationMessenger::Get().SendAction(CAction(action, 0, posX, posY, offsetX, offsetY), WINDOW_INVALID, false);
- else if (action == ACTION_GESTURE_ZOOM)
+ else if (action == ACTION_GESTURE_ZOOM || action == ACTION_GESTURE_ROTATE)
CApplicationMessenger::Get().SendAction(CAction(action, 0, posX, posY, offsetX, 0), WINDOW_INVALID, false);
}
View
4 xbmc/android/activity/AndroidTouch.h
@@ -34,6 +34,9 @@ class CAndroidTouch : protected ITouchHandler
protected:
virtual bool OnSingleTouchStart(float x, float y);
+ virtual bool OnMultiTouchStart(float x, float y, int32_t pointers = 2);
+ virtual bool OnMultiTouchEnd(float x, float y, int32_t pointers = 2);
+
virtual bool OnTouchGesturePanStart(float x, float y);
virtual bool OnTouchGesturePan(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY);
virtual bool OnTouchGesturePanEnd(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY);
@@ -41,6 +44,7 @@ class CAndroidTouch : protected ITouchHandler
virtual void OnSingleTap(float x, float y);
virtual void OnSingleLongPress(float x, float y);
virtual void OnZoomPinch(float centerX, float centerY, float zoomFactor);
+ virtual void OnRotate(float centerX, float centerY, float angle);
private:
void XBMC_Touch(uint8_t type, uint8_t button, uint16_t x, uint16_t y);
View
3 xbmc/guilib/Key.h
@@ -138,7 +138,8 @@
#define ACTION_CALIBRATE_SWAP_ARROWS 47 // select next arrow. Can b used in: settingsScreenCalibration.xml windowid=11
#define ACTION_CALIBRATE_RESET 48 // reset calibration to defaults. Can b used in: settingsScreenCalibration.xml windowid=11/settingsUICalibration.xml windowid=10
#define ACTION_ANALOG_MOVE 49 // analog thumbstick move. Can b used in: slideshow.xml window id=2007/settingsScreenCalibration.xml windowid=11/settingsUICalibration.xml windowid=10
-#define ACTION_ROTATE_PICTURE 50 // rotate current picture during slideshow. Can b used in slideshow.xml window id=2007
+#define ACTION_ROTATE_PICTURE_CW 50 // rotate current picture clockwise during slideshow. Can be used in slideshow.xml window id=2007
+#define ACTION_ROTATE_PICTURE_CCW 51 // rotate current picture counterclockwise during slideshow. Can be used in slideshow.xml window id=2007
#define ACTION_SUBTITLE_DELAY_MIN 52 // Decrease subtitle/movie Delay. Can b used in videoFullScreen.xml window id=2005
#define ACTION_SUBTITLE_DELAY_PLUS 53 // Increase subtitle/movie Delay. Can b used in videoFullScreen.xml window id=2005
View
3 xbmc/input/ButtonTranslator.cpp
@@ -98,7 +98,8 @@ static const ActionMapping actions[] =
{"nextcalibration" , ACTION_CALIBRATE_SWAP_ARROWS},
{"resetcalibration" , ACTION_CALIBRATE_RESET},
{"analogmove" , ACTION_ANALOG_MOVE},
- {"rotate" , ACTION_ROTATE_PICTURE},
+ {"rotate" , ACTION_ROTATE_PICTURE_CW},
+ {"rotateccw" , ACTION_ROTATE_PICTURE_CCW},
{"close" , ACTION_NAV_BACK}, // backwards compatibility
{"subtitledelayminus", ACTION_SUBTITLE_DELAY_MIN},
{"subtitledelay" , ACTION_SUBTITLE_DELAY},
View
50 xbmc/input/TouchInput.cpp
@@ -18,13 +18,20 @@
*
*/
+#include <math.h>
+
#include "TouchInput.h"
#include "threads/SingleLock.h"
#include "utils/log.h"
+#ifndef M_PI
+#define M_PI 3.1415926535897932384626433832795028842
+#endif
+
CTouchInput::CTouchInput()
: m_holdTimeout(1000),
m_handler(NULL),
+ m_fRotateAngle(0.0f),
m_gestureState(TouchGestureUnknown),
m_gestureStateOld(TouchGestureUnknown)
{
@@ -127,6 +134,7 @@ bool CTouchInput::Handle(TouchEvent event, float x, float y, int64_t time, int32
}
setGestureState(TouchGestureMultiTouchStart);
+ m_fRotateAngle = 0.0f;
}
// Otherwise we should ignore this pointer
else
@@ -314,6 +322,7 @@ void CTouchInput::saveLastTouch()
void CTouchInput::handleMultiTouchGesture()
{
handleZoomPinch();
+ handleRotation();
}
void CTouchInput::handleZoomPinch()
@@ -343,6 +352,39 @@ void CTouchInput::handleZoomPinch()
}
}
+void CTouchInput::handleRotation()
+{
+ Pointer& primaryPointer = m_pointers[0];
+ Pointer& secondaryPointer = m_pointers[1];
+
+ CVector last = primaryPointer.last - secondaryPointer.last;
+ CVector current = primaryPointer.current - secondaryPointer.current;
+
+ float length = last.length() * current.length();
+ if (length != 0.0f)
+ {
+ float centerX = (primaryPointer.current.x + secondaryPointer.current.x) / 2;
+ float centerY = (primaryPointer.current.y + secondaryPointer.current.y) / 2;
+
+ float scalar = last.scalar(current);
+ float angle = acos(scalar / length) * 180.0f / M_PI;
+
+ // make sure the result of acos is a valid number
+ if (angle == angle)
+ {
+ // calculate the direction of the rotation using the
+ // z-component of the cross-product of last and current
+ float direction = last.x * current.y - current.x * last.y;
+ if (direction < 0.0f)
+ m_fRotateAngle -= angle;
+ else
+ m_fRotateAngle += angle;
+
+ OnRotate(centerX, centerY, m_fRotateAngle);
+ }
+ }
+}
+
void CTouchInput::OnTimeout()
{
CSingleLock lock(m_critical);
@@ -548,3 +590,11 @@ void CTouchInput::OnZoomPinch(float centerX, float centerY, float zoomFactor)
if (m_handler)
m_handler->OnZoomPinch(centerX, centerY, zoomFactor);
}
+
+void CTouchInput::OnRotate(float centerX, float centerY, float angle)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ m_handler->OnRotate(centerX, centerY, angle);
+}
View
14 xbmc/input/TouchInput.h
@@ -219,6 +219,16 @@ class ITouchHandler
\sa
*/
virtual void OnZoomPinch(float centerX, float centerY, float zoomFactor) { }
+ /*!
+ \brief Two simultaneous touches have been held down and moved to perform a rotating gesture
+
+ \param centerX The x coordinate (with sub-pixel) of the center of the two touches
+ \param centerY The y coordinate (with sub-pixel) of the center of the two touches
+ \param angle The clockwise angle in degrees of the rotation
+ \return True if the event was handled otherwise false
+ \sa
+ */
+ virtual void OnRotate(float centerX, float centerY, float angle) { }
};
class CTouchInput : private ITouchHandler, private ITimerCallback
@@ -306,6 +316,7 @@ class CTouchInput : private ITouchHandler, private ITimerCallback
void handleMultiTouchGesture();
void handleZoomPinch();
+ void handleRotation();
// implementation of ITimerCallback
virtual void OnTimeout();
@@ -335,6 +346,7 @@ class CTouchInput : private ITouchHandler, private ITimerCallback
virtual void OnDoubleTap(float x1, float y1, float x2, float y2);
virtual void OnDoubleLongPress(float x1, float y1, float x2, float y2);
virtual void OnZoomPinch(float centerX, float centerY, float zoomFactor);
+ virtual void OnRotate(float centerX, float centerY, float angle);
CCriticalSection m_critical;
@@ -342,6 +354,8 @@ class CTouchInput : private ITouchHandler, private ITimerCallback
ITouchHandler *m_handler;
CTimer *m_holdTimer;
+ float m_fRotateAngle;
+
class Touch : public CVector {
public:
Touch() { reset(); }
View
2 xbmc/interfaces/http-api/XBMChttp.cpp
@@ -2151,7 +2151,7 @@ int CXbmcHttp::xbmcAction(int numParas, CStdString paras[], int theAction)
{
CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
if (pSlideShow) {
- pSlideShow->OnAction(CAction(ACTION_ROTATE_PICTURE));
+ pSlideShow->OnAction(CAction(ACTION_ROTATE_PICTURE_CW));
return SetResponse(openTag+"OK");
}
else
View
5 xbmc/interfaces/json-rpc/PlayerOperations.cpp
@@ -441,7 +441,10 @@ JSONRPC_STATUS CPlayerOperations::Rotate(const CStdString &method, ITransportLay
switch (GetPlayer(parameterObject["playerid"]))
{
case Picture:
- SendSlideshowAction(ACTION_ROTATE_PICTURE);
+ if (parameterObject["value"].asString().compare("clockwise") == 0)
+ SendSlideshowAction(ACTION_ROTATE_PICTURE_CW);
+ else
+ SendSlideshowAction(ACTION_ROTATE_PICTURE_CCW);
return ACK;
case Video:
View
3 xbmc/interfaces/json-rpc/ServiceDescription.h
@@ -1181,7 +1181,8 @@ namespace JSONRPC
"\"transport\": \"Response\","
"\"permission\": \"ControlPlayback\","
"\"params\": ["
- "{ \"name\": \"playerid\", \"$ref\": \"Player.Id\", \"required\": true }"
+ "{ \"name\": \"playerid\", \"$ref\": \"Player.Id\", \"required\": true },"
+ "{ \"name\": \"value\", \"type\": \"string\", \"enum\": [ \"clockwise\", \"counterclockwise\" ], \"default\": \"clockwise\" }"
"],"
"\"returns\": \"string\""
"}",
View
1 xbmc/interfaces/json-rpc/methods.json
@@ -318,6 +318,7 @@
"permission": "ControlPlayback",
"params": [
{ "name": "playerid", "$ref": "Player.Id", "required": true }
+ { "name": "value", "type": "string", "enum": [ "clockwise", "counterclockwise" ], "default": "clockwise" }
],
"returns": "string"
},
View
6 xbmc/osx/ios/XBMCController.h
@@ -29,7 +29,7 @@
@class IOSEAGLView;
-@interface XBMCController : UIViewController
+@interface XBMCController : UIViewController <UIGestureRecognizerDelegate>
{
UIWindow *m_window;
IOSEAGLView *m_glView;
@@ -38,8 +38,6 @@
/* Touch handling */
CGSize screensize;
CGPoint lastGesturePoint;
- CGFloat lastPinchScale;
- CGFloat currentPinchScale;
CGFloat screenScale;
bool touchBeginSignaled;
int m_screenIdx;
@@ -50,8 +48,6 @@
}
@property (readonly, nonatomic, getter=isAnimating) BOOL animating;
@property CGPoint lastGesturePoint;
-@property CGFloat lastPinchScale;
-@property CGFloat currentPinchScale;
@property CGFloat screenScale;
@property bool touchBeginSignaled;
@property int m_screenIdx;
View
72 xbmc/osx/ios/XBMCController.mm
@@ -37,6 +37,13 @@
#include "utils/TimeUtils.h"
#include "Util.h"
#include "threads/Event.h"
+#include <math.h>
+
+#ifndef M_PI
+#define M_PI 3.1415926535897932384626433832795028842
+#endif
+#define RADIANS_TO_DEGREES(radians) ((radians) * (180.0 / M_PI))
+
#undef BOOL
#import "IOSEAGLView.h"
@@ -68,8 +75,6 @@ -(void) terminateWithSuccess;
@implementation XBMCController
@synthesize animating;
@synthesize lastGesturePoint;
-@synthesize lastPinchScale;
-@synthesize currentPinchScale;
@synthesize screenScale;
@synthesize lastEvent;
@synthesize touchBeginSignaled;
@@ -144,6 +149,15 @@ -(void)sendKey:(XBMCKey) key
CWinEventsIOS::MessagePush(&newEvent);
}
//--------------------------------------------------------------
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
+{
+ if ([gestureRecognizer isKindOfClass:[UIRotationGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]]) {
+ return YES;
+ }
+
+ return NO;
+}
+//--------------------------------------------------------------
- (void)createGestureRecognizers
{
//2 finger single tab - right mouse
@@ -191,10 +205,18 @@ - (void)createGestureRecognizers
initWithTarget:self action:@selector(handlePinch:)];
pinch.delaysTouchesBegan = YES;
+ pinch.delegate = self;
[self.view addGestureRecognizer:pinch];
[pinch release];
- lastPinchScale = 1.0;
- currentPinchScale = lastPinchScale;
+
+ //for rotate gesture
+ UIRotationGestureRecognizer *rotate = [[UIRotationGestureRecognizer alloc]
+ initWithTarget:self action:@selector(handleRotate:)];
+
+ rotate.delaysTouchesBegan = YES;
+ rotate.delegate = self;
+ [self.view addGestureRecognizer:rotate];
+ [rotate release];
}
//--------------------------------------------------------------
- (void) activateKeyboard:(UIView *)view
@@ -214,21 +236,49 @@ -(void)handlePinch:(UIPinchGestureRecognizer*)sender
CGPoint point = [sender locationOfTouch:0 inView:m_glView];
point.x *= screenScale;
point.y *= screenScale;
- currentPinchScale += [sender scale] - lastPinchScale;
- lastPinchScale = [sender scale];
switch(sender.state)
{
case UIGestureRecognizerStateBegan:
- break;
+ CApplicationMessenger::Get().SendAction(CAction(ACTION_GESTURE_BEGIN, 0, (float)point.x, (float)point.y,
+ 0, 0), WINDOW_INVALID,false);
+ break;
case UIGestureRecognizerStateChanged:
CApplicationMessenger::Get().SendAction(CAction(ACTION_GESTURE_ZOOM, 0, (float)point.x, (float)point.y,
- currentPinchScale, 0), WINDOW_INVALID,false);
- break;
+ [sender scale], 0), WINDOW_INVALID,false);
+ break;
case UIGestureRecognizerStateEnded:
- break;
+ CApplicationMessenger::Get().SendAction(CAction(ACTION_GESTURE_END, 0, 0, 0,
+ 0, 0), WINDOW_INVALID,false);
+ break;
default:
- break;
+ break;
+ }
+ }
+}
+//--------------------------------------------------------------
+-(void)handleRotate:(UIRotationGestureRecognizer*)sender
+{
+ if( [m_glView isXBMCAlive] )//NO GESTURES BEFORE WE ARE UP AND RUNNING
+ {
+ CGPoint point = [sender locationOfTouch:0 inView:m_glView];
+ point.x *= screenScale;
+ point.y *= screenScale;
+
+ switch(sender.state)
+ {
+ case UIGestureRecognizerStateBegan:
+ CApplicationMessenger::Get().SendAction(CAction(ACTION_GESTURE_BEGIN, 0, (float)point.x, (float)point.y,
+ 0, 0), WINDOW_INVALID,false);
+ break;
+ case UIGestureRecognizerStateChanged:
+ CApplicationMessenger::Get().SendAction(CAction(ACTION_GESTURE_ROTATE, 0, (float)point.x, (float)point.y,
+ RADIANS_TO_DEGREES([sender rotation]), 0), WINDOW_INVALID,false);
+ break;
+ case UIGestureRecognizerStateEnded:
+ break;
+ default:
+ break;
}
}
}
View
235 xbmc/pictures/GUIWindowSlideShow.cpp
@@ -57,6 +57,8 @@ using namespace XFILE;
#define PICTURE_VIEW_BOX_COLOR 0xffffff00 // YELLOW
#define PICTURE_VIEW_BOX_BACKGROUND 0xff000000 // BLACK
+#define ROTATION_SNAP_RANGE 10.0f
+
#define FPS 25
#define BAR_IMAGE 1
@@ -150,7 +152,6 @@ CGUIWindowSlideShow::~CGUIWindowSlideShow(void)
delete m_slides;
}
-
bool CGUIWindowSlideShow::IsPlaying() const
{
return m_Image[m_iCurrentPic].IsLoaded();
@@ -168,9 +169,14 @@ void CGUIWindowSlideShow::Reset()
m_bScreensaver = false;
m_Image[0].UnLoad();
m_Image[0].Close();
+ m_Image[1].UnLoad();
+ m_Image[1].Close();
- m_iRotate = 0;
+ m_fRotate = 0.0f;
+ m_fInitialRotate = 0.0f;
m_iZoomFactor = 1;
+ m_fZoom = 1.0f;
+ m_fInitialZoom = 0.0f;
m_iCurrentSlide = 0;
m_iNextSlide = 1;
m_iCurrentPic = 0;
@@ -364,8 +370,8 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
m_bLoadNextPic = false;
// load using the background loader
int maxWidth, maxHeight;
- GetCheckedSize((float)g_settings.m_ResInfo[m_Resolution].iWidth * zoomamount[m_iZoomFactor - 1],
- (float)g_settings.m_ResInfo[m_Resolution].iHeight * zoomamount[m_iZoomFactor - 1],
+ GetCheckedSize((float)g_settings.m_ResInfo[m_Resolution].iWidth * m_fZoom,
+ (float)g_settings.m_ResInfo[m_Resolution].iHeight * m_fZoom,
maxWidth, maxHeight);
if (!m_slides->Get(m_iCurrentSlide)->IsVideo())
m_pBackgroundLoader->LoadPic(m_iCurrentPic, m_iCurrentSlide, m_slides->Get(m_iCurrentSlide)->GetPath(), maxWidth, maxHeight);
@@ -373,14 +379,11 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
// check if we should discard an already loaded next slide
if (m_bLoadNextPic && m_Image[1 - m_iCurrentPic].IsLoaded() && m_Image[1 - m_iCurrentPic].SlideNumber() != m_iNextSlide)
- {
m_Image[1 - m_iCurrentPic].Close();
- }
+
// if we're reloading an image (for better res on zooming we need to close any open ones as well)
if (m_bReloadImage && m_Image[1 - m_iCurrentPic].IsLoaded() && m_Image[1 - m_iCurrentPic].SlideNumber() != m_iCurrentSlide)
- {
m_Image[1 - m_iCurrentPic].Close();
- }
if (m_bReloadImage)
{
@@ -388,16 +391,18 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
{ // reload the image if we need to
CLog::Log(LOGDEBUG, "Reloading the current image %s at zoom level %i", m_slides->Get(m_iCurrentSlide)->GetPath().c_str(), m_iZoomFactor);
// first, our maximal size for this zoom level
- int maxWidth = (int)((float)g_settings.m_ResInfo[m_Resolution].iWidth * zoomamount[m_iZoomFactor - 1]);
- int maxHeight = (int)((float)g_settings.m_ResInfo[m_Resolution].iWidth * zoomamount[m_iZoomFactor - 1]);
+ int maxWidth = (int)((float)g_settings.m_ResInfo[m_Resolution].iWidth * m_fZoom);
+ int maxHeight = (int)((float)g_settings.m_ResInfo[m_Resolution].iWidth * m_fZoom);
// the actual maximal size of the image to optimize the sizing based on the known sizing (aspect ratio)
int width, height;
GetCheckedSize((float)m_Image[m_iCurrentPic].GetOriginalWidth(), (float)m_Image[m_iCurrentPic].GetOriginalHeight(), width, height);
// use the smaller of the two (no point zooming in more than we have to)
- if (maxWidth < width) width = maxWidth;
- if (maxHeight < height) height = maxHeight;
+ if (maxWidth < width)
+ width = maxWidth;
+ if (maxHeight < height)
+ height = maxHeight;
m_pBackgroundLoader->LoadPic(m_iCurrentPic, m_iCurrentSlide, m_slides->Get(m_iCurrentSlide)->GetPath(), width, height);
}
@@ -408,8 +413,8 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
{ // load the next image
CLog::Log(LOGDEBUG, "Loading the next image %s", m_slides->Get(m_iNextSlide)->GetPath().c_str());
int maxWidth, maxHeight;
- GetCheckedSize((float)g_settings.m_ResInfo[m_Resolution].iWidth * zoomamount[m_iZoomFactor - 1],
- (float)g_settings.m_ResInfo[m_Resolution].iHeight * zoomamount[m_iZoomFactor - 1],
+ GetCheckedSize((float)g_settings.m_ResInfo[m_Resolution].iWidth * m_fZoom,
+ (float)g_settings.m_ResInfo[m_Resolution].iHeight * m_fZoom,
maxWidth, maxHeight);
if (!m_slides->Get(m_iNextSlide)->IsVideo())
m_pBackgroundLoader->LoadPic(1 - m_iCurrentPic, m_iNextSlide, m_slides->Get(m_iNextSlide)->GetPath(), maxWidth, maxHeight);
@@ -431,7 +436,8 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
CApplicationMessenger::Get().PlayFile(*m_slides->Get(m_iCurrentSlide));
m_iCurrentSlide = m_iNextSlide;
m_iNextSlide = GetNextSlide();
- }
+ }
+
// Check if we should be transistioning immediately
if (m_bLoadNextPic)
{
@@ -475,7 +481,7 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
m_iNextSlide = GetNextSlide();
// m_iZoomFactor = 1;
- m_iRotate = 0;
+ m_fRotate = 0.0f;
}
if (m_Image[m_iCurrentPic].IsLoaded())
@@ -499,71 +505,77 @@ void CGUIWindowSlideShow::Render()
int CGUIWindowSlideShow::GetNextSlide()
{
- if(m_slides->Size() <= 1)
+ if (m_slides->Size() <= 1)
return m_iCurrentSlide;
- if(m_bSlideShow || m_iDirection >= 0)
- return (m_iCurrentSlide + 1 ) % m_slides->Size();
- else
- return (m_iCurrentSlide - 1 + m_slides->Size()) % m_slides->Size();
+ if (m_bSlideShow || m_iDirection >= 0)
+ return (m_iCurrentSlide + 1) % m_slides->Size();
+
+ return (m_iCurrentSlide - 1 + m_slides->Size()) % m_slides->Size();
}
EVENT_RESULT CGUIWindowSlideShow::OnMouseEvent(const CPoint &point, const CMouseEvent &event)
{
if (event.m_id == ACTION_GESTURE_NOTIFY)
{
- if( m_iZoomFactor == 1)//zoomed out - no inertial scrolling
- {
+ if (m_iZoomFactor == 1) //zoomed out - no inertial scrolling
return EVENT_RESULT_PAN_HORIZONTAL_WITHOUT_INERTIA;
- }
- else//zoomed in - with inertia
- {
- return EVENT_RESULT_PAN_HORIZONTAL;
- }
+
+ return EVENT_RESULT_PAN_HORIZONTAL;
}
else if (event.m_id == ACTION_GESTURE_BEGIN)
{
m_firstGesturePoint = point;
+ m_fInitialZoom = m_fZoom;
+ m_fInitialRotate = m_fRotate;
return EVENT_RESULT_HANDLED;
}
else if (event.m_id == ACTION_GESTURE_PAN)
{ // on zoomlevel 1 just detect swipe left and right
- if( m_iZoomFactor == 1 )
- {
- if( m_firstGesturePoint.x > 0 && fabs(point.x - m_firstGesturePoint.x) > 100 )
+ if (m_iZoomFactor == 1)
+ {
+ if (m_firstGesturePoint.x > 0 && fabs(point.x - m_firstGesturePoint.x) > 100)
{
- if( point.x < m_firstGesturePoint.x )
- {
+ if (point.x < m_firstGesturePoint.x)
OnAction(CAction(ACTION_NEXT_PICTURE));
- }
else
- {
OnAction(CAction(ACTION_PREV_PICTURE));
- }
+
m_firstGesturePoint.x = 0;
}
}
- else//zoomed in - free move mode
+ else //zoomed in - free move mode
{
- Move(PICTURE_MOVE_AMOUNT_TOUCH/m_iZoomFactor*(m_firstGesturePoint.x-point.x),PICTURE_MOVE_AMOUNT_TOUCH/m_iZoomFactor*(m_firstGesturePoint.y-point.y));
+ Move(PICTURE_MOVE_AMOUNT_TOUCH / m_iZoomFactor * (m_firstGesturePoint.x - point.x), PICTURE_MOVE_AMOUNT_TOUCH / m_iZoomFactor * (m_firstGesturePoint.y - point.y));
m_firstGesturePoint = point;
}
return EVENT_RESULT_HANDLED;
}
else if (event.m_id == ACTION_GESTURE_END)
{
+ if (m_fRotate != 0.0f)
+ {
+ // "snap" to nearest of 0, 90, 180 and 270 if the
+ // difference in angle is +/-10 degrees
+ float reminder = fmodf(m_fRotate, 90.0f);
+ if (reminder < ROTATION_SNAP_RANGE)
+ Rotate(-reminder);
+ else if (reminder > 90.0f - ROTATION_SNAP_RANGE)
+ Rotate(90.0f - reminder);
+ }
+
+ m_fInitialZoom = 0.0f;
+ m_fInitialRotate = 0.0f;
return EVENT_RESULT_HANDLED;
}
else if (event.m_id == ACTION_GESTURE_ZOOM)
{
- if( event.m_offsetX > 1)
- {
- Zoom((int)event.m_offsetX);
- }
- else
- {
- Zoom((int)(m_iZoomFactor - event.m_offsetX));
- }
- return EVENT_RESULT_HANDLED;
+ ZoomRelative(m_fInitialZoom * event.m_offsetX, true);
+ return EVENT_RESULT_HANDLED;
+ }
+ else if (event.m_id == ACTION_GESTURE_ROTATE)
+ {
+ Rotate(m_fInitialRotate + event.m_offsetX - m_fRotate, true);
+ return EVENT_RESULT_HANDLED;
}
return EVENT_RESULT_UNHANDLED;
}
@@ -588,17 +600,21 @@ bool CGUIWindowSlideShow::OnAction(const CAction &action)
}
}
break;
+
case ACTION_PREVIOUS_MENU:
case ACTION_NAV_BACK:
case ACTION_STOP:
g_windowManager.PreviousWindow();
break;
+
case ACTION_NEXT_PICTURE:
ShowNext();
break;
+
case ACTION_PREV_PICTURE:
ShowPrevious();
break;
+
case ACTION_MOVE_RIGHT:
if (m_iZoomFactor == 1)
ShowNext();
@@ -644,8 +660,12 @@ bool CGUIWindowSlideShow::OnAction(const CAction &action)
Zoom(m_iZoomFactor + 1);
break;
- case ACTION_ROTATE_PICTURE:
- Rotate();
+ case ACTION_ROTATE_PICTURE_CW:
+ Rotate(90.0f);
+ break;
+
+ case ACTION_ROTATE_PICTURE_CCW:
+ Rotate(-90.0f);
break;
case ACTION_ZOOM_LEVEL_NORMAL:
@@ -660,9 +680,11 @@ bool CGUIWindowSlideShow::OnAction(const CAction &action)
case ACTION_ZOOM_LEVEL_9:
Zoom((action.GetID() - ACTION_ZOOM_LEVEL_NORMAL) + 1);
break;
+
case ACTION_ANALOG_MOVE:
Move(action.GetAmount()*PICTURE_MOVE_AMOUNT_ANALOG, -action.GetAmount(1)*PICTURE_MOVE_AMOUNT_ANALOG);
break;
+
default:
return CGUIWindow::OnAction(action);
}
@@ -699,9 +721,8 @@ bool CGUIWindowSlideShow::OnMessage(CGUIMessage& message)
// Reset();
if (message.GetParam1() != WINDOW_PICTURES)
- {
m_ImageLib.Unload();
- }
+
g_windowManager.ShowOverlay(OVERLAY_STATE_SHOWN);
FreeResources();
}
@@ -713,19 +734,14 @@ bool CGUIWindowSlideShow::OnMessage(CGUIMessage& message)
//FIXME: Use GUI resolution for now
if (0 /*m_Resolution != g_guiSettings.m_LookAndFeelResolution && m_Resolution != INVALID && m_Resolution!=AUTORES*/)
- {
g_graphicsContext.SetVideoResolution(m_Resolution);
- }
else
- {
m_Resolution = g_graphicsContext.GetVideoResolution();
- }
CGUIWindow::OnMessage(message);
if (message.GetParam1() != WINDOW_PICTURES)
- {
m_ImageLib.Load();
- }
+
g_windowManager.ShowOverlay(OVERLAY_STATE_HIDDEN);
// turn off slideshow if we only have 1 image
@@ -735,6 +751,7 @@ bool CGUIWindowSlideShow::OnMessage(CGUIMessage& message)
return true;
}
break;
+
case GUI_MSG_START_SLIDESHOW:
{
CStdString strFolder = message.GetStringParam();
@@ -755,28 +772,31 @@ bool CGUIWindowSlideShow::OnMessage(CGUIMessage& message)
RunSlideShow(strFolder, bRecursive, bRandom, bNotRandom);
}
break;
+
case GUI_MSG_PLAYLISTPLAYER_STOPPED:
- {
- m_bPlayingVideo = false;
- if (m_bSlideShow)
- g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
- }
- break;
+ {
+ m_bPlayingVideo = false;
+ if (m_bSlideShow)
+ g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
+ }
+ break;
+
case GUI_MSG_PLAYBACK_STARTED:
- {
- if(m_bSlideShow && m_bPlayingVideo)
- g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
- }
- break;
+ {
+ if (m_bSlideShow && m_bPlayingVideo)
+ g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
+ }
+ break;
+
case GUI_MSG_PLAYBACK_STOPPED:
- {
- if (m_bSlideShow && m_bPlayingVideo)
{
- m_bSlideShow = false;
- g_windowManager.PreviousWindow();
+ if (m_bSlideShow && m_bPlayingVideo)
+ {
+ m_bSlideShow = false;
+ g_windowManager.PreviousWindow();
+ }
}
- }
- break;
+ break;
}
return CGUIWindow::OnMessage(message);
}
@@ -803,32 +823,61 @@ void CGUIWindowSlideShow::RenderPause()
}
-void CGUIWindowSlideShow::Rotate()
+void CGUIWindowSlideShow::Rotate(float fAngle, bool immediate /* = false */)
{
- if (!m_Image[m_iCurrentPic].DrawNextImage() && m_iZoomFactor == 1)
- {
- m_Image[m_iCurrentPic].Rotate(++m_iRotate);
- }
+ if (m_Image[m_iCurrentPic].DrawNextImage())
+ return;
+
+ m_fRotate += fAngle;
+
+ m_Image[m_iCurrentPic].Rotate(fAngle, immediate);
}
void CGUIWindowSlideShow::Zoom(int iZoom)
{
if (iZoom > MAX_ZOOM_FACTOR || iZoom < 1)
- return ;
+ return;
+
+ ZoomRelative(zoomamount[iZoom - 1]);
+}
+
+void CGUIWindowSlideShow::ZoomRelative(float fZoom, bool immediate /* = false */)
+{
+ if (fZoom < zoomamount[0])
+ fZoom = zoomamount[0];
+ else if (fZoom > zoomamount[MAX_ZOOM_FACTOR - 1])
+ fZoom = zoomamount[MAX_ZOOM_FACTOR - 1];
+
+ if (m_Image[m_iCurrentPic].DrawNextImage())
+ return;
+
+ m_fZoom = fZoom;
+
+ // find the nearest zoom factor
+#ifdef RELOAD_ON_ZOOM
+ int iOldZoomFactor = m_iZoomFactor;
+#endif
+ for (unsigned int i = 1; i < MAX_ZOOM_FACTOR; i++)
+ {
+ if (m_fZoom > zoomamount[i])
+ continue;
+
+ if (fabs(m_fZoom - zoomamount[i - 1]) < fabs(m_fZoom - zoomamount[i]))
+ m_iZoomFactor = i;
+ else
+ m_iZoomFactor = i + 1;
+
+ break;
+ }
+
// set the zoom amount and then set so that the image is reloaded at the higher (or lower)
// resolution as necessary
- if (!m_Image[m_iCurrentPic].DrawNextImage())
- {
- m_Image[m_iCurrentPic].Zoom(iZoom);
- // check if we need to reload the image for better resolution
+ m_Image[m_iCurrentPic].Zoom(m_fZoom, immediate);
+
#ifdef RELOAD_ON_ZOOM
- if (iZoom > m_iZoomFactor && !m_Image[m_iCurrentPic].FullSize())
- m_bReloadImage = true;
- if (iZoom == 1)
- m_bReloadImage = true;
+ if (m_iZoomFactor == 1 || (iZoomFactor > iOldZoomFactor && !m_Image[m_iCurrentPic].FullSize()))
+ m_bReloadImage = true;
#endif
- m_iZoomFactor = iZoom;
- }
}
void CGUIWindowSlideShow::Move(float fX, float fY)
@@ -1000,8 +1049,10 @@ void CGUIWindowSlideShow::GetCheckedSize(float width, float height, int &maxWidt
}
maxWidth = (int)width;
maxHeight = (int)height;
- if (maxWidth > (int)g_Windowing.GetMaxTextureSize()) maxWidth = g_Windowing.GetMaxTextureSize();
- if (maxHeight > (int)g_Windowing.GetMaxTextureSize()) maxHeight = g_Windowing.GetMaxTextureSize();
+ if (maxWidth > (int)g_Windowing.GetMaxTextureSize())
+ maxWidth = g_Windowing.GetMaxTextureSize();
+ if (maxHeight > (int)g_Windowing.GetMaxTextureSize())
+ maxHeight = g_Windowing.GetMaxTextureSize();
#else
maxWidth = g_Windowing.GetMaxTextureSize();
maxHeight = g_Windowing.GetMaxTextureSize();
View
8 xbmc/pictures/GUIWindowSlideShow.h
@@ -102,8 +102,9 @@ class CGUIWindowSlideShow : public CGUIWindow
SortOrder order = SortOrderAscending);
void RenderPause();
void RenderErrorMessage();
- void Rotate();
+ void Rotate(float fAngle, bool immediate = false);
void Zoom(int iZoom);
+ void ZoomRelative(float fZoom, bool immediate = false);
void Move(float fX, float fY);
void GetCheckedSize(float width, float height, int &maxWidth, int &maxHeight);
int GetNextSlide();
@@ -111,8 +112,11 @@ class CGUIWindowSlideShow : public CGUIWindow
int m_iCurrentSlide;
int m_iNextSlide;
int m_iDirection;
- int m_iRotate;
+ float m_fRotate;
+ float m_fInitialRotate;
int m_iZoomFactor;
+ float m_fZoom;
+ float m_fInitialZoom;
bool m_bShuffled;
bool m_bSlideShow;
View
62 xbmc/pictures/SlideShowPicture.cpp
@@ -103,18 +103,18 @@ void CSlideShowPic::SetTexture(int iSlideNumber, CBaseTexture* pTexture, DISPLAY
m_transistionTemp.type = TRANSISTION_NONE;
m_fTransistionAngle = 0;
m_fTransistionZoom = 0;
- m_fAngle = 0;
+ m_fAngle = 0.0f;
if (pTexture->GetOrientation() == 7)
{ // rotate to 270 degrees
- m_fAngle = 3.0f;
+ m_fAngle = 270.0f;
}
if (pTexture->GetOrientation() == 2)
{ // rotate to 180 degrees
- m_fAngle = 2.0f;
+ m_fAngle = 180.0f;
}
if (pTexture->GetOrientation() == 5)
{ // rotate to 90 degrees
- m_fAngle = 1.0f;
+ m_fAngle = 90.0f;
}
m_fZoomAmount = 1;
m_fZoomLeft = 0;
@@ -159,7 +159,7 @@ void CSlideShowPic::SetOriginalSize(int iOriginalWidth, int iOriginalHeight, boo
int CSlideShowPic::GetOriginalWidth()
{
- int iAngle = (int)(m_fAngle + 0.4f);
+ int iAngle = (int)(m_fAngle / 90.0f + 0.4f);
if (iAngle % 2)
return m_iOriginalHeight;
else
@@ -168,7 +168,7 @@ int CSlideShowPic::GetOriginalWidth()
int CSlideShowPic::GetOriginalHeight()
{
- int iAngle = (int)(m_fAngle + 0.4f);
+ int iAngle = (int)(m_fAngle / 90.0f + 0.4f);
if (iAngle % 2)
return m_iOriginalWidth;
else
@@ -246,27 +246,30 @@ void CSlideShowPic::Process(unsigned int currentTime, CDirtyRegionList &dirtyreg
{ // correct for any introduced inaccuracies.
int i;
for (i = 0; i < 10; i++)
- if (fabs(m_fZoomAmount - zoomamount[i]) < 0.01*zoomamount[i])
+ {
+ if (fabs(m_fZoomAmount - zoomamount[i]) < 0.01 * zoomamount[i])
break;
+ }
m_fZoomAmount = zoomamount[i];
m_bNoEffect = (m_fZoomAmount != 1.0f); // turn effect rendering back on.
}
- if (m_transistionTemp.type == TRANSISTION_ROTATE)
- { // round to nearest integer for accuracy purposes
- m_fAngle = floor(m_fAngle + 0.4f);
- }
+ /* not really needed anymore as we support arbitrary rotations
+ else if (m_transistionTemp.type == TRANSISTION_ROTATE)
+ { // round to nearest of 0, 90, 180 and 270
+ float reminder = fmodf(m_fAngle, 90.0f);
+ if (reminder < 45.0f)
+ m_fAngle -= reminder;
+ else
+ m_fAngle += 90.0f - reminder;
+ }*/
m_transistionTemp.type = TRANSISTION_NONE;
}
else
{
if (m_transistionTemp.type == TRANSISTION_ROTATE)
- {
m_fAngle += m_fTransistionAngle;
- }
if (m_transistionTemp.type == TRANSISTION_ZOOM)
- {
m_fZoomAmount += m_fTransistionZoom;
- }
}
}
}
@@ -365,8 +368,8 @@ void CSlideShowPic::Process(unsigned int currentTime, CDirtyRegionList &dirtyreg
// Rotate the image as needed
float x[4];
float y[4];
- float si = (float)sin(m_fAngle * M_PI * 0.5);
- float co = (float)cos(m_fAngle * M_PI * 0.5);
+ float si = (float)sin(m_fAngle / 180.0f * M_PI);
+ float co = (float)cos(m_fAngle / 180.0f * M_PI);
x[0] = -m_fWidth * co + m_fHeight * si;
y[0] = -m_fWidth * si - m_fHeight * co;
x[1] = m_fWidth * co + m_fHeight * si;
@@ -600,31 +603,36 @@ void CSlideShowPic::SetTransistionTime(int iType, int iTime)
m_transistionEnd.length = iTime;
}
-void CSlideShowPic::Rotate(int iRotate)
+void CSlideShowPic::Rotate(float fRotateAngle, bool immediate /* = false */)
{
- if (m_bDrawNextImage) return ;
- if (m_transistionTemp.type == TRANSISTION_ZOOM) return ;
+ if (m_bDrawNextImage) return;
+ if (m_transistionTemp.type == TRANSISTION_ZOOM) return;
+ if (immediate)
+ {
+ m_fAngle += fRotateAngle;
+ return;
+ }
m_transistionTemp.type = TRANSISTION_ROTATE;
m_transistionTemp.start = m_iCounter;
m_transistionTemp.length = IMMEDIATE_TRANSISTION_TIME;
- m_fTransistionAngle = (float)(iRotate - m_fAngle) / (float)m_transistionTemp.length;
+ m_fTransistionAngle = (float)fRotateAngle / (float)m_transistionTemp.length;
// reset the timer
m_transistionEnd.start = m_iCounter + m_transistionStart.length + (int)(g_graphicsContext.GetFPS() * g_guiSettings.GetInt("slideshow.staytime"));
}
-void CSlideShowPic::Zoom(int iZoom, bool immediate /*= false*/)
+void CSlideShowPic::Zoom(float fZoom, bool immediate /* = false */)
{
- if (m_bDrawNextImage) return ;
- if (m_transistionTemp.type == TRANSISTION_ROTATE) return ;
+ if (m_bDrawNextImage) return;
+ if (m_transistionTemp.type == TRANSISTION_ROTATE) return;
if (immediate)
{
- m_fZoomAmount = zoomamount[iZoom - 1];
+ m_fZoomAmount = fZoom;
return;
}
m_transistionTemp.type = TRANSISTION_ZOOM;
m_transistionTemp.start = m_iCounter;
m_transistionTemp.length = IMMEDIATE_TRANSISTION_TIME;
- m_fTransistionZoom = (float)(zoomamount[iZoom - 1] - m_fZoomAmount) / (float)m_transistionTemp.length;
+ m_fTransistionZoom = (fZoom - m_fZoomAmount) / (float)m_transistionTemp.length;
// reset the timer
m_transistionEnd.start = m_iCounter + m_transistionStart.length + (int)(g_graphicsContext.GetFPS() * g_guiSettings.GetInt("slideshow.staytime"));
// turn off the render effects until we're back down to normal zoom
@@ -646,7 +654,7 @@ void CSlideShowPic::Render()
Render(m_ax, m_ay, m_pImage, (m_alpha << 24) | 0xFFFFFF);
// now render the image in the top right corner if we're zooming
- if (m_fZoomAmount == 1 || m_bIsComic) return ;
+ if (m_fZoomAmount == 1.0f || m_bIsComic) return ;
Render(m_bx, m_by, NULL, PICTURE_VIEW_BOX_BACKGROUND);
Render(m_sx, m_sy, m_pImage, 0xFFFFFFFF);
View
4 xbmc/pictures/SlideShowPicture.h
@@ -66,8 +66,8 @@ class CSlideShowPic
int SlideNumber() const { return m_iSlideNumber;};
- void Zoom(int iZoomAmount, bool immediate = false);
- void Rotate(int iRotateAmount);
+ void Zoom(float fZoomAmount, bool immediate = false);
+ void Rotate(float fRotateAngle, bool immediate = false);
void Pause(bool bPause);
void SetInSlideshow(bool slideshow);
void SetOriginalSize(int iOriginalWidth, int iOriginalHeight, bool bFullSize);

0 comments on commit e13dcf3

Please sign in to comment.
Something went wrong with that request. Please try again.