/*
	Copyright (c) 2010, Laurent "MrPingouin" CHEA
	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 LAURENTCHEA.COM 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 HOLDER 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.

*********************************************************************************************************

	MrPingouin's Playback Viewport 0.1
	contact@laurentchea.com
	http://www.laurentchea.com
	
	Dec 2010

	This scripts reproduces a killer feature already existing in XSI for animators :
	it automatically switches to a designated viewport when playing animation,
	very useful in case of viewport layout showing different rigging parts (e.g. face controls, character placement in top view, + trackview).
	

	NOTES :
	
		Many thanks to Foxious @ #techart for his help.
		http://www.horowitz3d.com/

*/

	g_app_name = "Playback Viewport"
	g_app_version = "0.1"

	g_workingViewport = 1
	
	AutoSwitchView_R = undefined
	
	app = undefined

	function saveWorkingViewport =
	(
		g_workingViewport = viewport.activeViewport
	)
	
	function watchViewportLayout = 
	(
		app.updateUIddl()
	)

	struct AutoSwitchViewApp 
	(
		_playViewport,
		_ui_ddl,
		
		function createApp ui_ddl =
		(
			local app = AutoSwitchViewApp()
			app._ui_ddl = ui_ddl
			app.updateUIddl()
			app._ui_ddl.selection = app.getViewportIndex()
			app.setWorkingViewport ui_ddl.selection
			
			callbacks.addScript #viewportChange "watchViewportLayout()" id:#watchViewportLayout
			
			return app
		),
		
		function setWorkingViewport index =
		(
			_playViewport = index
		),
		
		function getViewportList = 
		(
			local list = #()
			if viewport.numViews > 0 then
			(
				for i=1 to viewport.numViews do
				(
					local type = viewport.getType index:i
					local viewName = ""
					case type of 
					(
						#view_top : viewName = "Top"
						#view_bottom : viewName = "Bottom"
						#view_left : viewName = "Left"
						#view_right : viewName = "Right"
						#view_front : viewName = "Front"
						#view_back : viewName = "Back"
						#view_persp_user : viewName = "Perspective"
						#view_iso_user : viewName = "User"
						#view_camera : viewName = (viewport.getCamera index:i).name
						#view_spot : viewName = (viewport.getCamera index:i).name
						#view_shape : viewName = "Shape"
						#view_grid : viewName = "Grid"
						undefined : viewName = "Extended view"
					)
					
					append list ((i as string) + " : " + viewName)
				)
			)
			else
				append list "Fulls Screen Extended view"
			
			return list
		),
		
		function getViewportIndex = 
		(
			if viewport.activeViewport > 0 then
				return viewport.activeViewport
			else
				return 1
		),
		
		function switchToWorkingViewport =
		(
			viewport.activeViewport = g_workingViewport
		),
		
		function updateUIddl = 
		(
			local views_list = #()
			views_list = getViewportList()
			
			local old_viewport_count = _ui_ddl.items.count
			
			_ui_ddl.items = views_list
			
			-- The layout has changed, and has less viewports (from 4 to 3 for example, or, staying in 4 viewports, but one goes to a trackview)
			-- by default, we switch back to the top-left viewport (index 1)
			
			if  viewport.numViews < old_viewport_count then
			(
				_playViewport = 1
				_ui_ddl.selection = 1
				g_workingViewport = 1
				-- when creating a trackview for example, there's no more activeViewport
				viewport.activeViewport = 1
			)
			
			
		),
		
		------------------------------------------------------------------------------------------------------------------------------------------
		--
		-- THE TRICKY PART : the callbacks
		--
		-- 1 : first callback : #viewportChange : watchWorkingViewport(), to know the last viewport chosen by user before playing animation
		-- 2 : second callback : timeChange : switchToPlayViewport(), goes to the designated viewport, this callback occurs only one time, and deregisters.
		--						  this call back registers "resetTimer()" on a timechangeCallback, and *starts the timer*
		-- 3 : last callback : timeChange : resetTimer() : makes clock.ticks = 0, that means : each time a frame is played, the ticks are set on 0
		-- 3 : the timers clicks every frameRate milliseconds, if ticks > 1 then it means that the user has stopped playing the animation
		-- 
		------------------------------------------------------------------------------------------------------------------------------------------
		
		function resetTimer = 
		(
			AutoSwitchView_R.clock.active = true
			AutoSwitchView_R.clock.ticks = 0
		),
		
		function registerResetTimerCallback state = 
		(
			if state == true then
				registerTimeCallback resetTimer
			else
				unregisterTimeCallback resetTimer
		),
		
		function registerWatchWorkingViewportCallback state = 
		(
			if state == true then
			(
				callbacks.addScript #viewportChange "saveWorkingViewport()" id:#watchWorkingViewport
			)
			else
			(
				callbacks.removeScripts #viewportChange id:#watchWorkingViewport
			)
		),
		
		
		function switchToPlayViewport = 
		(
			-- Once the animation starts, this callback must be called only ONE TIME
			
			if isAnimPlaying() == true then
			(
				-- We MUST unregister the watchWorkingViewport call back :
				-- As the script changes the active viewport for playing, it would raise a #viewportChange, and thus set the workingViewport to the playingViewport
				registerWatchWorkingViewportCallback false
				
				-- if viewport.numViews == 1, the current viewport is maximized
				if viewport.numViews > 1 then
				(
					viewport.activeViewport = _playViewport
				)
				
				-- The callback directly unregisters itself : as it has changed the active viewport, it doesn't need to do it anymore
				unregisterTimeCallback switchToPlayViewport
				
				-- The callback starts the timer !
				registerResetTimerCallback true
			)
		),
		
		function registerSwitchToPlayViewportCallback active = 
		(
			if active == true then
			(
				registerTimeCallback switchToPlayViewport
			)
			else
			(
				unregisterTimeCallback switchToPlayViewport
			)
		),
		
		function toggleToolActivation state = 
		(
			app.registerWatchWorkingViewportCallback state
			app.registerSwitchToPlayViewportCallback state
			
			-- It doesn't matter if the tool is active or not at this time, the resetTimer callback should always be false, it is only registered by switchToPlayViewport function
			
			app.registerResetTimerCallback false
		),
		
		function quit = 
		(
			app.toggleToolActivation false
			
			-- This callback has been registered on AutoSwitchViewApp construction
			callbacks.removeScripts #viewportChange id:#watchViewportLayout
		)
	)

	rollout AutoSwitchView_R (g_app_name + " " + g_app_version)
	(
		
		timer clock "watchDog" interval:(1000.0/framerate) active:false
		dropdownlist views_ddl "Viewport :"
		checkbutton active_cb "Active" align:#right
		
		on AutoSwitchView_R open do
		(
			app = AutoSwitchViewApp.createApp views_ddl
			
			app.toggleToolActivation true
			active_cb.state = true
		)
		
		on views_ddl selected val do with undo off
		(
			app.setWorkingViewport val
		)
		
		on active_cb changed state do
		(
			app.toggleToolActivation state
		)
		
		on AutoSwitchView_R close do with undo off
		(
			app.quit()
		)
		
		on clock tick do
		(
			-- clock.ticks > 1 : the timer has been started, but the animation is not playing animore
			
			if clock.ticks > 1 then
			(
				clock.active = false
				app.updateUIddl()
				app.switchToWorkingViewport()
				app.toggleToolActivation active_cb.checked
			)
		)
	)
	
	createDialog AutoSwitchView_R 200 80

