전체 화면 전환 효과

 | 개발
2008.02.06 00:00
QuickTime Player는 전체 화면 전환시 멋진 애니메이션 효과를 보여줍니다.
저는 이게 참 멋져보였습니다. 그래서 무비스트에도 이 효과를 넣고 싶었죠. MPlayer도 비슷하게 하고 있긴 하지만 QuickTime Player와는 조금 다릅니다. 차이점은 아래에서 설명하겠습니다.

그럼 먼저 어떤 효과인지 자세히 살펴보죠.
다음은 전체화면으로 전환할 때의 현상입니다.
  • 영상 부분이 전체 화면 시의 크기까지 점진적으로 변합니다.
  • 영상 부분이 변하는 동안 윈도우 프레임도 따라서 변합니다.
  • 그러는 동안 주변은 점점 어두워져 전체 화면 상태가 되면 완전히 검게 변합니다.
리사이즈 애니메이션을 영상과 윈도우 프레임 두 부분으로 나눈 것은 이유가 있습니다.
영상 부분이 전체 화면에서의 영상 크기까지 커지는 동안 윈도우 프레임은 정확히 영상 부분의 리사이즈를 쫓아갑니다. 이렇게 말을 해서 그렇지 실제로는 그냥 윈도우가 리사이즈되는 것 처럼 보이죠. 그러나 윈도우 프레임은 모니터 경계를 만나면 더 이상 커지지 않고 멈추는 반면, 영상 부분은 윈도우 프레임과 상관없이 모니터 경계까지 계속 커집니다. 여기에서 영상 부분과 윈도우 프레임은 따로 리사이즈 된다는 것을 알 수 있습니다. 또, 리사이즈되는 동안 영상 부분 이외의 주변부가 점점 어두워지는데 윈도우 프레임도 함께 어두워진다는 점 역시 영상 부분이 윈도우로부터 분리되어 따로 리사이즈된다는 것을 보여줍니다.

반면 MPlayer는 영상과 윈도우가 함께 리사이즈되는 것 처럼 보입니다. 윈도우 프레임이 영상 부분과 상관없이 무조건 모니터를 가득 채우도록 커지는데 이 때문에 영상 크기보다 커지는 순간부터 레터박스 영역도 보이기 시작하죠. 또한, 주변이 어두워지는 현상이 없고 윈도우 프레임이 모니터 경계로 한정되지도 않습니다. 작은 차이이지만 막상 둘을 비교해보면 QuickTime Player가 훨씬 세련되었다고 느끼게 됩니다.

이게 뭐 그리 중요하느냐고 물으신다면 할 말 없습니다. 사실 MPlayer 정도만 해도 충분하다고 생각할지 모릅니다. 하지만 이 별 것 아니고 실제 쓰는데 큰 도움이 되는 것도 없는 이런 부분이 고급스러움과 알 수 없는 만족감을 주는 것 같습니다. 애플의 장기죠. 작은 차이가 명품을 만든다고 할까요.. QuickTime Player도 쉬운 방법으로 만들 수 있었겠지만 굳이 저렇게 어려운 방법을 택한 데에는 이유가 있을 것이고 저 역시 같은 이유로 이것을 구현해보고 싶은 것입니다.

서론이 길었네요. 자 이제 본론으로 들어가보죠.
다음은 전체 화면 전환의 일반적인 구현 방법입니다.
1. 화면 전체 크기의 윈도우를 하나 만들고,
2. 영상 뷰를 메인 윈도우에서 떼어내어 전체 화면용 윈도우에 붙인다.

위 방법에는 애니메이션에 대한 부분이 없습니다. 그냥 순식간에 바뀌는 방식이죠. 여기에 애니메이션을 넣어야 하는데 기본 아이디어는 이렇습니다. 윈도우 크기에서 화면 전체 크기로 애니메이션을 해야 하므로 1의 화면 전체 크기의 윈도우 대신 영상 뷰 크기의 윈도우를 만들어야 합니다. 여기에 영상 뷰를 붙인 후(2의 과정) 화면 전체 크기로 리사이즈 애니메이션을 하는거죠. 이 때 메인 윈도우도 함께 리사이즈되어야 한다는 것을 잊으면 안되겠죠. 아이디어는 간단하지만 실제 두 윈도우의 애니메이션을 어떻게 동기화 하느냐과 관건입니다.

애니메이션 하니까 Leopard에 추가된 Core Animation이 떠오르는군요. 하지만 Tiger에서도 똑같이 실행되려면 Core Animation 없이도 할 수 있어야 합니다. QuickTime Player가 이미 하고 있으니 방법은 있겠죠?

우선 가장 간단한 방법인 -[NSWindow setFrame:display:animate:] 메시지를 생각해 보죠. 이 메시지를 영상 뷰를 붙인 윈도우와 메인 윈도우에 동시에 보내면 되지 않을까요? 그런데 이 메시지는 애니메이션이 끝날 때 까지 복귀하지 않으므로 동시에 보낸다는게 불가능합니다. 뭐 스레드를 분리하면 가능이야 하겠지만 그럴 거라면 더 좋은 방법이 있죠. NSViewAnimation을 사용하는 것입니다. NSViewAnimation은 여러 윈도우나 뷰를 동시에 애니메이션할 수 있으니 딱인 것 같습니다. 그런데 실제로 해보니 메인 윈도우와 영상 뷰 윈도우가 딱 맞게 움직이질 않더군요. 살짝씩 어긋나서 움직이는게 영 어색하고 어설퍼 보입니다. 내부적으로 스레드를 돌릴 것 같은데 스레드 스위칭이 이상적으로 되지 않는 이상 이걸 딱 맞추기는 어려울 것 같네요.

그렇다면 동시 애니메이션은 포기해야 한다는 것인데... 하나만 애니메이션을 하고 다른 하나는 그것을 쫒아가는 식은 어떨까요? NSWindowDidResizeNotification을 사용하자는 것입니다. 방법은 이렇습니다. 메인 윈도우는 모니터 가장자리를 만나면 더 이상 커질 수 없으니 영상 뷰 윈도우를 애니메이션 주체로 정합니다. 이 윈도우가 애니메이션 하는 동안 NSWindowDidResizeNotification 통지를 받아 메인 윈도우를 영상 뷰 윈도우에 맞춰 -[NSWindow setFrame:display:]로 애니메이션 없이 바로 프레임을 지정하는거죠. 이렇게 하면 메인 윈도우와 영상 뷰 윈도우의 동기가 딱 맞을 것입니다. 실제로 해보니 효과가 괜찮았습니다. 꽤 그럴 듯 하더군요.

이제 페이드 효과를 구현할 차례입니다.
페이드 효과는 보통 화면 전체를 덮는 검정색 윈도우를 만들고 NSViewAnimation으로 알파값을 조절하는 식으로 구현하는 것 같습니다. NSViewAniamtion 대신 타이머를 쓰기도 한다는데 직접 해보니 타이머 방식은 약간 부자연스럽더군요. 보통은 NSViewAnimation에서 이미 Fade In/Out 효과가 지원되므로 그걸 그냥 사용하면 될 듯 합니다.

주의할 점은 페이드 효과는 영상 부분에는 적용되지 않는다는 것입니다. 그러니 영상 뷰 윈도우에는 적용할 수 없고 페이드용 윈도우를 하나 더 만들어야 한다는 결론이 나오네요. 그리고 페이드 효과는 메인 윈도우에도 적용되어야 하므로 페이드 윈도우는 전체 화면 윈도우와 메인 윈도우 사이에 위치해야 합니다. 즉, 위에서부터 전체 화면 윈도우, 페이드 윈도우, 메인 윈도우 순으로 있게 되죠. 순서 지정을 부모-자식 관계를 설정하여 처리했습니다.

그런데 생각해보니 굳이 NSViewAnimation을 사용하지 않고 NSWindowDidResizeNotification 통지를 받을 때 알파값을 조절하는 식으로 처리해도 될 것 같더군요. 굳이 스레드 하나 더 만들지 않아도 되니까요. 두 방식을 모두 구현해 보았는데 제 느낌엔 통지를 받아 처리하는 방식이 더 자연스러운 것 같아 NSViewAnimation으로 구현한 코드는 #ifdef 로 막아두었습니다.

이제 겉보기에는 아주 흡사합니다. 하지만 QuickTime Player에 비하면 어딘가 모르게 살짝 무거운 것이 느껴지네요. 뭔가 더 나은 방식이 있는 것 같은데 잘 모르겠습니다. 하지만 이 정도도 충분히 만족스럽네요. ^^
신고

'개발' 카테고리의 다른 글

무비스트 빌드하기  (11) 2008.04.14
전체 화면 전환 효과  (1) 2008.02.06
자막 이야기 3  (6) 2007.12.30
자막 이야기 2  (2) 2007.12.30
자막 이야기 1  (2) 2007.12.30
Posted by 코코아벌레

BLOG main image
Mac OS X 용 동영상 플레이어 . . . . <무비스트> 공식 홈페이지 . . . . . . by 코코아벌레

카테고리

전체 (72)
무비스트 (9)
릴리즈 (54)
개발 (5)
FAQ (4)

달력

«   2017/12   »
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            

글 보관함