1-- $LastChangedDate: 2010-05-25 21:26:05 -0400 (Tue, 25 May 2010) $
2-- LEGAL: COPYRIGHT (C) 2010 JIM E. BROOKS WWW.PALOMINO3D.ORG
3-- Updates HUD every tick.
4-- See module.txt for documentation and pitfalls.
5
6---------------------
7-- Hud (singleton) --
8---------------------
9
10Hud = {
11    statusText = "",
12    enableInfoText = true,  -- enable the info text in top-left corner of window (disabled to show OSG stats)
13}
14
15-- Initialize HUD.
16function Hud:Init()
17    -- Register timer-tick handler.
18    -- Don't update HUD too fast.  Give time for the user to read it.
19    Timer:Register( self, defs.HUD_TICK_FREQ )
20
21    -- HUD is composed of lines of HudText objects defined by HudText::Args.
22    local hudTextArgs = {
23        text = "",
24        orientation = "BOTTOM_LEFT",
25        fontSize = 28.0,
26        x = 16,
27        y = 16,
28    }
29
30    local alpha = 1.0
31    local yi = 32
32
33    self.hudText1 = sim.HudText:New( hudTextArgs )
34    hudTextArgs.y = hudTextArgs.y + yi
35
36    self.hudText2 = sim.HudText:New( hudTextArgs )
37    hudTextArgs.y = hudTextArgs.y + yi
38
39    self.hudText3 = sim.HudText:New( hudTextArgs )
40    hudTextArgs.y = hudTextArgs.y + yi
41
42    self.hudText4 = sim.HudText:New( hudTextArgs )
43    hudTextArgs.y = hudTextArgs.y + yi
44
45    self.hudText5 = sim.HudText:New( hudTextArgs )
46    self.hudText5:SetColor( 1.0, 1.0, 0.0, alpha )  -- yellow
47    hudTextArgs.y = hudTextArgs.y + yi
48
49    self.hudText6 = sim.HudText:New( hudTextArgs )
50    hudTextArgs.y = hudTextArgs.y + yi
51
52    if ( sim.Base:IfDebug() ) then
53        self.hudTextDebug = sim.HudText:New( hudTextArgs )
54        hudTextArgs.y = hudTextArgs.y + yi
55    end
56
57    self.hudTextOver = sim.HudText:New( { text="", orientation="TOP_LEFT", x=0, y=yi, fontSize = 34.0, } )
58    self.hudTextOver:SetColor( 1.0, 0.6, 0.6, 1.0 )
59
60    self.hudTextInfo = sim.HudText:New( { text="", orientation="TOP_LEFT" } )
61    self.hudTextInfo:SetColor( 1.0, 1.0, 0.6, 1.0 )
62end
63
64-- Set/unset status text.
65function Hud:AddStatusText( text )
66    -- Already added?
67    if ( not string.find( self.statusText, text ) ) then
68        self.statusText = lib.CatWords( self.statusText, text )
69    end
70end
71
72function Hud:RemoveStatusText( text )
73    self.statusText = string.gsub( self.statusText, text, "" )
74end
75
76function Hud:ClearStatusText()
77    self.statusText = ""
78end
79
80-- Update HUD.
81function Hud:Tick()
82    local temp = ""
83    local current = PlayerActor:GetAircraft()  -- 3D Object
84    local playerDestroyed = PlayerActor:IfDestroyed()
85    local physics = current:GetPhysics()
86    local posSph = sim.World:WorldVertex2SphereVertex( current:GetPosition() )
87
88    -- Line 1.
89    if ( playerDestroyed ) then
90        temp = ""
91    else
92        local speedKPH = sim.Physics:Speed2KPH( physics:ComputeSpeed() )
93        local throttle = current:GetThrottle()
94        local paused = ""
95        if ( sim.Program:IfPaused() ) then paused = "[PAUSED]" end
96        temp = string.format( "KPH: %3d THROT: %3d%% FPS: %u  [%dX] %s",
97                              speedKPH,
98                              throttle * 100.0,
99                              sim.Window:GetFPS(),
100                              sim.Base:GetSimulationSpeed(),
101                              paused )
102    end
103    self.hudText1:SetText( temp )
104
105    -- Line 2.
106    if ( playerDestroyed ) then
107        temp = ""
108    else
109        local belowRadar = nil
110        if ( posSph[ALT] < defs.SAM_RADAR_MIN_ALT_METERS ) then
111            belowRadar = "BELOW RADAR"
112        else
113            belowRadar = ""
114        end
115        temp = string.format( "LAT,LON,ALT: %.2f %.2f %.2f %s",
116                              posSph[LAT],
117                              posSph[LON],
118                              posSph[ALT],
119                              belowRadar )
120    end
121    self.hudText2:SetText( temp )
122
123    -- Line 3.
124    if ( playerDestroyed ) then
125        temp = ""
126    else
127        local coturn = ""
128        if ( current:IfCoordinatedTurnExecuting() ) then coturn = "  COTURN  " end
129        temp = string.format( "DRAG  : %8.2fN WEIGHT: %8.2fN  AoA: %2d %s",
130                              Distance3(physics:ComputeDragForce()),
131                              Distance3(physics:ComputeWeightForce()),
132                              physics:ComputeAngleOfAttack(),
133                              coturn )
134    end
135    self.hudText3:SetText( temp )
136
137    -- Line 4.
138    if ( playerDestroyed ) then
139        temp = ""
140    else
141        temp = string.format( "THRUST: %8.2fN LIFT  : %8.2fN",
142                              Distance3(physics:ComputeThrustForce()),
143                              Distance3(physics:ComputeLiftForce()) )
144    end
145    self.hudText4:SetText( temp )
146
147    -- Line 5.
148    if ( playerDestroyed ) then
149        temp = ""
150    else
151        temp = ""
152
153        if ( current:IfWheelBrakes() ) then
154            temp = "WHEEL BRAKES"
155        elseif ( current:IfBrakes() ) then
156            temp = "AIR BRAKES"
157        end
158
159        if ( physics:IfStall() ) then
160            temp = lib.CatWords( temp, "STALL" )
161        end
162
163        local replay = PlayerActor:GetReplay()
164        if ( replay:IfPlaying() ) then
165            temp = lib.CatWords( temp, "REPLAY" )
166        elseif ( replay:IfRecording() ) then
167            temp = lib.CatWords( temp, "RECORDING REPLAY" )
168        end
169
170        -- And show any status text.
171        temp = lib.CatWords( temp, self.statusText )
172    end
173    self.hudText5:SetText( temp )
174
175    -- Line 6.
176    if ( sim.argvMap["-jp"] ) then
177        -- C++ can compute a string for joystick state faster than Lua.
178        temp = string.format( "JOY " .. sim.Joystick:GetStateAsString() )
179        self.hudText6:SetText( temp )
180    end
181
182    -- Line DEBUG.
183    if ( self.hudTextDebug ) then
184        local megabytes = sim.Base:GetMemoryUsed() / 1048576
185        temp = string.format( "DBG: OBJS=%d MEM=%dMB",
186                              sim.Object:GetObjectCount(),
187                              sim.Math:TruncInt( megabytes ) )
188        self.hudTextDebug:SetText( temp )
189    end
190
191    -- "GAME OVER".
192    temp = ""
193    if ( playerDestroyed ) then
194        temp = lib.CatWords( temp, "** GAME OVER ** [INSERT QUARTER] PRESS BACKSPACE" )
195    end
196    self.hudTextOver:SetText( temp )
197end
198
199-- Reset the HUD.
200function Hud:Reset()
201    self:EnableInfoText( true )
202    self:ClearStatusText()
203end
204
205-- Enable/disable the top-left info line.
206function Hud:EnableInfoText( enable )
207    self.enableInfoText = enable
208
209    -- Clear info text if disabled.
210    if ( not enable ) then
211        self.hudTextInfo:SetText( "" )
212    end
213end
214
215-- Set text in the top-left info line.
216function Hud:SetInfoText( infoText )
217    if ( self.enableInfoText ) then
218        self.hudTextInfo:SetText( infoText )
219    end
220end
221
222Events:RegisterReset( function() Hud:Reset() end )  -- need anon func
223
224-- Start HUD.
225Hud:Init()
226