-- $LastChangedDate: 2010-04-16 22:43:07 -0500 (Fri, 16 Apr 2010) $
-- Code for views/windows/display.
-- See module.txt for documentation and pitfalls.

--------------------
-- view functions --
--------------------

-- Transform world --> eye.  Defaults to main view.
function sim.TransformWorld2Eye( pos, view )
    local view = view or sim.Window:GetMainView()
    return view:TransformWorld2Eye( pos )
end

---------------
-- SuperView --
---------------

sim.SuperView = { }
sim.SuperView.eViewMode_OTW_NONE  = 0
sim.SuperView.eViewMode_OTW_FRONT = 1
sim.SuperView.eViewMode_OTW_REAR  = 2
sim.SuperView.eViewMode_OTW_LEFT  = 3
sim.SuperView.eViewMode_OTW_RIGHT = 4
sim.SuperView.eViewMode_CHASE     = 0  -- alias
sim.SuperView.viewMode = sim.SuperView.eViewMode_CHASE
sim.SuperView.otwViewpoint   = sim.OtwViewpoint:New( sim.ObserverCurrentCraft:New() )
sim.SuperView.chaseViewpoint = sim.ChaseViewpoint:New()
sim.SuperView.viewControl = 0  -- 0:main
sim.SuperView.view1 = nil  -- N/A (the main view is omnipresent)
sim.SuperView.view2 = nil  -- limited to two views (main/aux) (see view/node_masks.hh)

function sim.SuperView:Reset()
    -- Reset OTW view (unless chase view).
    if ( not sim.SuperView:IfChaseView() ) then
        sim.SuperView:SetViewMode( sim.SuperView.eViewMode_OTW_FRONT )
    end
end

function sim.SuperView:SetViewMode( viewMode )
    self.viewMode = viewMode

    -- Keeping the same View object (and underlying osg::Camera),
    -- switch the Viewpoint functor that computes its view-matrix.
    local view = sim.Window:GetMainView()
    if ( viewMode == self.eViewMode_CHASE ) then
        view:SetViewpoint( self.chaseViewpoint )
        -- This is the main view in chase-view mode, so show player's aircraft.
        view:EnableObjectInMainView( PlayerActor:GetAircraft(), true )
    else  -- an OTW view
        view:SetViewpoint( self.otwViewpoint )
        self.otwViewpoint:SetOtwMode( viewMode )
        -- Don't render the player's aircraft in an OTW view.
        view:EnableObjectInMainView( PlayerActor:GetAircraft(), false )
    end

    -- Show chase-plane in either main or second view.
    if ( self.view2 ) then
        if ( viewMode == self.eViewMode_CHASE ) then
            self.view2:Enable( false )
        else
            self.view2:Enable( true )
        end
    end
end

function sim.SuperView:GetViewMode()
    return sim.SuperView.viewMode
end

function sim.SuperView:CycleViewMode()
    -- Change var.
    if ( self.viewMode == self.eViewMode_CHASE ) then
        self.viewMode = self.eViewMode_OTW_FRONT
    else
        self.viewMode = self.eViewMode_CHASE
    end

    -- Reset focus of keypad to main view.
    self:SetViewControl( 0 )

    -- Change underlying view.
    self:SetViewMode( self.viewMode )
end

-- Cycle keypad control to the next view.
function sim.SuperView:CycleViewControl()
    self.viewControl = self.viewControl + 1
    self:SetViewControl( self.viewControl )
end

-- Set which view is controlled by keypad.
-- If the requested view is disabled, this tries the next view (circular).
-- The reason is that views are very dynamic.
-- For example, switching between OTW and chase modes in the main views
-- causes the second view to be enabled/disabled, so the third view should be tried.
-- And, the third view isn't always present.
function sim.SuperView:SetViewControl( viewControl )
    self.viewControl = viewControl

    -- Begin by disabling outline colors.
    if ( self.view2 ) then  -- absent if -fast
        self.view2:SetOutlineColor( defs.VIEW_OUTLINE_COLOR_DISABLED )
    end

    -- switch statement.
    if ( self.viewControl == 0 ) then
        -- Has no effect unless main view's mode is chase.
        ChaseView.chaseViewpoint = ChaseView.chaseViewpointPlayer
    elseif ( self.viewControl == 1 ) then
        -- Is the main view in chase mode?
        -- If so, the second view is disabled, so skip it.
        if ( self.viewMode == self.eViewMode_CHASE ) then
            self:SetViewControl( 2 )  -- try again
        else
            ChaseView.chaseViewpoint = ChaseView.chaseViewpointPlayer
            if ( self.view2 ) then  -- omitted if -fast
                self.view2:SetOutlineColor( defs.VIEW_OUTLINE_COLOR_ENABLED )
            end
        end
    elseif ( self.viewControl == 2 ) then
        self:SetViewControl( 0 )  -- try again
    else  -- self.viewControl == 3
        self:SetViewControl( 0 )  -- wrap, try again
    end

end

function sim.SuperView:IfChaseView()
    return sim.SuperView.viewMode == sim.SuperView.eViewMode_CHASE
end

function sim.SuperView:GetChaseViewpoint()
    return sim.SuperView.chaseViewpoint
end

-- Create a view to show player from chase-plane.
function sim.SuperView:MakeSecondView()
    -- Second view is too slow in OSSIM with advent of clouds.
    if ( not sim.argvMap["-fast"] and not sim.argvMap["-ossim"] ) then
        -- Create view by composing a View and Viewpoint.
        local sw,sh = sim.Window:GetWindowSize()
        self.view2 = sim.View:New( { x1=sw*0.666, y1=0, x2=sw, y2=sh*0.333 } )
        self.view2:SetViewpoint( ChaseView.chaseViewpointPlayer )
        self.view2:SetOutlineColor( defs.VIEW_OUTLINE_COLOR_DISABLED )
    end
end

--------------------
-- ChaseViewpoint --
--------------------
sim.ChaseViewpoint.AXIS_CHASE_PLANE_HORZ = ZZ
sim.ChaseViewpoint.AXIS_CHASE_PLANE_VERT = XX

---------------
-- ChaseView --
---------------

ChaseView = {
    chaseViewpoint       = sim.SuperView:GetChaseViewpoint(),  -- of main view
    chaseViewpointPlayer = sim.SuperView:GetChaseViewpoint(),  -- again
    chaseViewpointFriend = nil,
    distance  = -50.0, -- -17.0,  -- meters
    inc       = 1.0,   -- meters
    horzAngle = Deg2Rad(7.0),    -- radians
    vertAngle = Deg2Rad(-10.0),  -- radians
}

-- Initialize chase-plane.
-- This can be called more than once to support mission restart.
-- Enable chase-plane which causes the camera to look at the player's aircraft.
-- Chase-plane is initially behind (along -Z axis in local space).
function ChaseView:Init( ossim )
    -- Restore the chase-plane's orientation.
    self.chaseViewpoint:Reset()

    -- Ensure player is the target in case GUI selected another aircraft type.
    self.chaseViewpoint:SetTarget( PlayerActor.aircraft )
    self.chaseViewpointPlayer:SetTarget( PlayerActor.aircraft )

    -- Initialize the chase-plane's distance and orientation.
    if ( not self.wasInit ) then
        -- Remember that Init() was called.
        self.wasInit = true
        if ( ossim ) then
            self.inc       = 20.0
            self.distance  = -125.0 -- meters
            self.horzAngle = Deg2Rad(0.0)
            self.vertAngle = Deg2Rad(-20.0)
        end
        self.chaseViewpoint:SetDistance( 0.0, 0.0, sim.World.Meters2Sim(self.distance) )
        self.chaseViewpoint:Rotate( sim.ChaseViewpoint.AXIS_CHASE_PLANE_HORZ, self.horzAngle )
        self.chaseViewpoint:Rotate( sim.ChaseViewpoint.AXIS_CHASE_PLANE_VERT, self.vertAngle )
        self.chaseViewpoint:Save()
    end
end

-- Reset chase-plane.
function ChaseView:Reset()
    self.chaseViewpoint:Reset()
end

-- Instantiate it.
ChaseView:Init( sim.argvMap["-ossim"] )

----------------
-- Brightness --
----------------

Brightness = {
    default = sim.Light:GetBrightness(),
    inc = 0.1,
    min = 0.2,
    max = 1.8,
}

function Brightness:Set( brightness )
    sim.Light:SetBrightness( brightness )
end

function Brightness:Reset()
    self:Set( self.default )
end

function Brightness:Cycle( dir )
    dir = dir or 1.0
    -- Cycle.
    local brightness = sim.Light:GetBrightness()
    brightness = brightness + self.inc * dir
    if ( brightness > self.max ) then
        brightness = self.min
    elseif ( brightness < self.min ) then
        brightness = self.max
    end
    self:Set( brightness )
    Log( "brightness = " .. tostring(brightness) )
end

Events:RegisterReset( function() Brightness:Reset() end )  -- need anon func
