-- $LastChangedDate: 2010-04-16 22:43:07 -0500 (Fri, 16 Apr 2010) $
--
-- **GENERIC** library of Lua objects to interface with simulator.
--
-- This extends and supplements what C++ exports to Lua.
-- See module.txt for documentation and pitfalls.
-- Notes: Use Vec3() instead of tables (XX=0).

---------------------
-- sim definitions --
---------------------

sim.LANDING_GEAR_UP   = false
sim.LANDING_GEAR_DOWN = true

sim.COLLISION_NONE  = 0  -- Object::eCollision
sim.COLLISION       = 1
sim.COLLISION_FATAL = 2

----------------
-- ModelCache --
----------------

sim.ModelCache = {
    LOAD_SHARED = 0,
    LOAD_COPY = 1,
}

------------
-- Object --
------------

-- Block to place Objects without interference from physics/collision.
function sim.BeginPlacement()
    local placement = { enableCollision = sim.Collision:IfEnabled(),
                        enablePhysics   = sim.Physics:IfEnabled() }
    sim.Collision:Enable( false )  -- disable collision-detection
    sim.Physics:Enable( false )    -- disable physics
    return placement
end

function sim.EndPlacement( placement )
    sim.Collision:Enable( placement.enableCollision )  -- restore collision-detecton
    sim.Physics:Enable(   placement.enablePhysics )    -- restore physics
end

-- Schedule a 3D Object for deletion (ok if object was already freed/zombified).
-- Example: For self.object : sim.ZombifyObject( self, "object" )
-- Similar to lib:Destroy()
function sim.ZombifyObject( t, objectMember )
    local object = t[objectMember]
    if ( object ) then
        sim.SceneGraph:DetachObject( object )  -- remove from scene-graph
        object:Zombify()                       -- schedule for deletion
        t[objectMember] = nil                  -- release Lua table's reference to it
    end
end

------------------------------------
-- Handler for DestroyObjectEvent --
------------------------------------

-- This is a special-case of the C++ core calling a Lua function.
-- Because of reference-counts, an Object to be destroyed (zombie)
-- must be broadcast so that all of its holders will release references to it.

function sim.HandleDestroyObject( objectPtr )
    -- This will propagate the event to all Actors.
    Game:HandleDestroyObject( objectPtr )

    -- Force releasing C++ objects.
    collectgarbage()

    return 0
end

-- Return true if two references both refer to the same C++ 3D Object.
function sim.IfIdenticalObject( obj1, obj2 )
    if ( obj1 == nil or obj2 == nil ) then
        return false
    else
        -- Convert either/both args to raw pointers.
        if ( type(obj1) == "userdata" ) then  -- is userdata if binding to C++ Object
            obj1 = obj1:GetRawPtr()           -- returns raw ptr of C++ Object as a Lua number
        end
        if ( type(obj2) == "userdata" ) then
            obj2 = obj2:GetRawPtr()
        end
        -- Compare raw pointers.
        return obj1 == obj2
    end
end

-------------
-- Control --
-------------

-- Defines which way to rotate player according to control input.
sim.Control.rollLeftDir  =  1
sim.Control.rollRightDir = -1
sim.Control.pitchUpDir   =  1
sim.Control.pitchDownDir = -1
sim.Control.yawLeftDir   =  1
sim.Control.yawRightDir  = -1

-----------
-- Craft --
-----------

sim.Craft = { }
sim.Craft.eState_PARKED  = 0
sim.Craft.eState_TAKEOFF = 1
sim.Craft.eState_FLYING  = 2
sim.Craft.eState_LANDING = 3
sim.Craft.eState_CRASHED = 4

--------------
-- Aircraft --
--------------

-- Compute KPH.
function sim.AircraftComputeSpeedKPH( aircraft )
    return sim.Physics.Speed2KPH( aircraft:GetPhysics():ComputeSpeed() )
end

---------
-- Geo --
---------

-- (abbrevation) Meters to world coordinates.
Meters2Sim = sim.World.Meters2Sim  -- function
M2W        = sim.World.Meters2Sim
Sim2Meters = sim.World.Sim2Meters  -- function
W2M        = sim.World.Sim2Meters

-----------
-- Sound --
-----------

sim.Sound.PLAY_ONCE = false
sim.Sound.PLAY_LOOP = true
sim.Sound.DEFAULT_VOLUME = 1.0
