Skip to content

Commit f798c5b

Browse files
authored
Merge pull request scp-fs2open#2007 from asarium/feature/scriptedHudGauges
Add new HUD gauge type for scripted gauges
2 parents 7611512 + 1662a3c commit f798c5b

11 files changed

Lines changed: 186 additions & 6 deletions

File tree

code/hud/hud.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* or otherwise commercially exploit the source or things you created based on the
66
* source.
77
*
8-
*/
8+
*/
99

1010

1111
#include "ai/aigoals.h"
@@ -23,9 +23,10 @@
2323
#include "hud/hudets.h"
2424
#include "hud/hudlock.h"
2525
#include "hud/hudmessage.h"
26-
#include "hud/hudnavigation.h" //kazan
26+
#include "hud/hudnavigation.h" //kazan
2727
#include "hud/hudobserver.h"
2828
#include "hud/hudreticle.h"
29+
#include "hud/hudscripting.h"
2930
#include "hud/hudshield.h"
3031
#include "hud/hudsquadmsg.h"
3132
#include "hud/hudtarget.h"
@@ -50,6 +51,7 @@
5051
#include "radar/radar.h"
5152
#include "radar/radarsetup.h"
5253
#include "render/3d.h"
54+
#include "scripting/scripting.h"
5355
#include "ship/ship.h"
5456
#include "starfield/supernova.h"
5557
#include "weapon/emp.h"
@@ -1231,6 +1233,25 @@ void HUD_init()
12311233
default_hud_gauges[j]->resetTimers();
12321234
default_hud_gauges[j]->updateSexpOverride(false);
12331235
}
1236+
1237+
Script_system.OnStateDestroy.add(hud_scripting_close);
1238+
}
1239+
1240+
void hud_scripting_close(lua_State*) {
1241+
// Clean up Lua references so that we don't have dangling references on to the lua state in the HUD gauges
1242+
for (auto it = Ship_info.begin(); it != Ship_info.end(); ++it) {
1243+
for (const auto& gauge : it->hud_gauges) {
1244+
if (gauge->getObjectType() == HUD_OBJECT_SCRIPTING) {
1245+
static_cast<HudGaugeScripting*>(gauge.get())->setRenderFunction(luacpp::LuaFunction());
1246+
}
1247+
}
1248+
}
1249+
1250+
for (const auto& gauge : default_hud_gauges) {
1251+
if (gauge->getObjectType() == HUD_OBJECT_SCRIPTING) {
1252+
static_cast<HudGaugeScripting*>(gauge.get())->setRenderFunction(luacpp::LuaFunction());
1253+
}
1254+
}
12341255
}
12351256

12361257
/**

code/hud/hud.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ extern int Hud_max_targeting_range;
110110

111111
void HUD_init_colors();
112112
void HUD_init();
113+
void hud_scripting_close(lua_State*);
113114
void hud_close();
114115
void hud_level_close();
115116
void hud_update_frame(float frametime); // updates hud systems not dependant on rendering

code/hud/hudparse.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "hud/hudmessage.h"
2020
#include "hud/hudparse.h" //Duh.
2121
#include "hud/hudreticle.h"
22+
#include "hud/hudscripting.h"
2223
#include "hud/hudshield.h"
2324
#include "hud/hudsquadmsg.h"
2425
#include "hud/hudtarget.h"
@@ -914,6 +915,9 @@ int parse_gauge_type()
914915

915916
if ( optional_string("+Secondary Weapons:") )
916917
return HUD_OBJECT_SECONDARY_WEAPONS;
918+
919+
if ( optional_string("+Scripted Gauge:") )
920+
return HUD_OBJECT_SCRIPTING;
917921

918922
return -1;
919923
}
@@ -1094,6 +1098,9 @@ void load_gauge(int gauge, gauge_settings* settings)
10941098
case HUD_OBJECT_SECONDARY_WEAPONS:
10951099
load_gauge_secondary_weapons(settings);
10961100
break;
1101+
case HUD_OBJECT_SCRIPTING:
1102+
load_gauge_scripting(settings);
1103+
break;
10971104
default:
10981105
// It's either -1, indicating we're ignoring a parse error, or it's a coding error.
10991106
Assertion(gauge == -1, "Invalid value '%d' passed to load_gauge(); get a coder!\n", gauge);
@@ -5219,3 +5226,15 @@ void load_gauge_secondary_weapons(gauge_settings* settings)
52195226

52205227
gauge_assign_common(settings, std::move(hud_gauge));
52215228
}
5229+
5230+
void load_gauge_scripting(gauge_settings* settings) {
5231+
auto hud_gauge = gauge_load_common<HudGaugeScripting>(settings);
5232+
5233+
required_string("Name:");
5234+
SCP_string name;
5235+
stuff_string(name, F_NAME);
5236+
5237+
hud_gauge->initName(name);
5238+
5239+
gauge_assign_common(settings, std::move(hud_gauge));
5240+
}

code/hud/hudparse.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,4 +232,7 @@ void load_gauge_primary_weapons(gauge_settings* settings);
232232
#define HUD_OBJECT_SECONDARY_WEAPONS 55
233233
void load_gauge_secondary_weapons(gauge_settings* settings);
234234

235+
#define HUD_OBJECT_SCRIPTING 56
236+
void load_gauge_scripting(gauge_settings* settings);
237+
235238
#endif // _HUDPARSE_H

code/hud/hudscripting.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//
2+
//
3+
4+
#include "hud/hudscripting.h"
5+
6+
#include "parse/parselo.h"
7+
8+
#include "scripting/api/objs/hudgauge.h"
9+
10+
HudGaugeScripting::HudGaugeScripting() :
11+
HudGauge(HUD_OBJECT_SCRIPTING,
12+
HUD_CENTER_RETICLE,
13+
true,
14+
false,
15+
(VM_EXTERNAL | VM_DEAD_VIEW | VM_WARP_CHASE | VM_PADLOCK_ANY | VM_TOPDOWN | VM_OTHER_SHIP),
16+
255,
17+
255,
18+
255) {
19+
}
20+
21+
void HudGaugeScripting::render(float /*frametime*/) {
22+
using namespace scripting::api;
23+
24+
if (!_renderFunction.isValid()) {
25+
return;
26+
}
27+
28+
_renderFunction.call({ luacpp::LuaValue::createValue(_renderFunction.getLuaState(),
29+
l_HudGaugeDrawFuncs.Set(this)) });
30+
}
31+
32+
void HudGaugeScripting::initName(SCP_string name) {
33+
if (name.size() > NAME_LENGTH - 1) {
34+
error_display(0,
35+
"Name \"%s\" is too long. May not be longer than %d! Name will be truncated",
36+
name.c_str(),
37+
NAME_LENGTH - 1);
38+
name.resize(NAME_LENGTH - 1);
39+
}
40+
strcpy(custom_name, name.c_str());
41+
}
42+
const luacpp::LuaFunction& HudGaugeScripting::getRenderFunction() const {
43+
return _renderFunction;
44+
}
45+
void HudGaugeScripting::setRenderFunction(const luacpp::LuaFunction& renderFunction) {
46+
_renderFunction = renderFunction;
47+
}

code/hud/hudscripting.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#pragma once
2+
3+
#include "globalincs/pstypes.h"
4+
#include "hud/hud.h"
5+
#include "scripting/lua/LuaFunction.h"
6+
7+
class HudGaugeScripting: public HudGauge {
8+
luacpp::LuaFunction _renderFunction;
9+
public:
10+
HudGaugeScripting();
11+
12+
void render(float frametime) override;
13+
14+
void initName(SCP_string name);
15+
16+
const luacpp::LuaFunction& getRenderFunction() const;
17+
void setRenderFunction(const luacpp::LuaFunction& renderFunction);
18+
};

code/scripting/ade_args.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,15 +108,25 @@ void set_single_arg(lua_State* L, char fmt, const char* s)
108108
// WMC - Isn't working with HookVar for some strange reason
109109
lua_pushstring(L, s);
110110
}
111-
void set_single_arg(lua_State*, char fmt, luacpp::LuaTable* table)
111+
112+
void set_single_arg(lua_State* L, char fmt, luacpp::LuaTable* table)
113+
{
114+
set_single_arg(L, fmt, *table);
115+
}
116+
void set_single_arg(lua_State*, char fmt, const luacpp::LuaTable& table)
112117
{
113118
Assertion(fmt == 't', "Invalid format character '%c' for table type!", fmt);
114-
table->pushValue();
119+
table.pushValue();
120+
}
121+
122+
void set_single_arg(lua_State* L, char fmt, luacpp::LuaFunction* func)
123+
{
124+
set_single_arg(L, fmt, *func);
115125
}
116-
void set_single_arg(lua_State*, char fmt, luacpp::LuaFunction* func)
126+
void set_single_arg(lua_State*, char fmt, const luacpp::LuaFunction& func)
117127
{
118128
Assertion(fmt == 'u', "Invalid format character '%c' for function type!", fmt);
119-
func->pushValue();
129+
func.pushValue();
120130
}
121131

122132
} // namespace internal

code/scripting/ade_args.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,10 @@ void set_single_arg(lua_State* L, char fmt, ade_odata_setter<T>&& od)
299299
luacpp::convert::pushValue(L, std::forward<ade_odata_setter<T>>(od));
300300
}
301301
void set_single_arg(lua_State* /*L*/, char fmt, luacpp::LuaTable* table);
302+
void set_single_arg(lua_State* /*L*/, char fmt, const luacpp::LuaTable& table);
303+
302304
void set_single_arg(lua_State* /*L*/, char fmt, luacpp::LuaFunction* func);
305+
void set_single_arg(lua_State* /*L*/, char fmt, const luacpp::LuaFunction& func);
303306

304307
// This is not a template function so we can put the implementation in a source file
305308
inline void set_args_actual(lua_State* /*L*/, set_args_state& /*state*/, const char* fmt)

code/scripting/api/objs/hudgauge.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//
33

44
#include "hudgauge.h"
5+
#include "hud/hudscripting.h"
56

67
namespace scripting {
78
namespace api {
@@ -40,6 +41,59 @@ ADE_VIRTVAR(Text, l_HudGauge, "string", "Custom HUD Gauge text", "string", "Cust
4041
return ade_set_args(L, "s", gauge->getCustomGaugeText());
4142
}
4243

44+
ADE_VIRTVAR(RenderFunction,
45+
l_HudGauge,
46+
"function (HudGaugeDrawFunctions gauge_handle)",
47+
"For scripted HUD gauges, the function that will be called for rendering the HUD gauge",
48+
"function (HudGaugeDrawFunctions gauge_handle)",
49+
"Render function or nil if no action is set or handle is invalid") {
50+
HudGauge* gauge;
51+
luacpp::LuaFunction func;
52+
53+
if (!ade_get_args(L, "o|u", l_HudGauge.Get(&gauge), &func)) {
54+
return ADE_RETURN_NIL;
55+
}
56+
57+
if (gauge->getObjectType() != HUD_OBJECT_SCRIPTING) {
58+
return ADE_RETURN_NIL;
59+
}
60+
61+
auto scriptedGauge = static_cast<HudGaugeScripting*>(gauge);
62+
63+
if (ADE_SETTING_VAR && func.isValid()) {
64+
scriptedGauge->setRenderFunction(func);
65+
}
66+
67+
return ade_set_args(L, "u", scriptedGauge->getRenderFunction());
68+
}
69+
70+
ADE_OBJ(l_HudGaugeDrawFuncs,
71+
HudGauge*,
72+
"HudGaugeDrawFunctions",
73+
"Handle to the rendering functions used for HUD gauges. Do not keep a reference to this since these are only useful inside the rendering callback of a HUD gauge.");
74+
75+
ADE_FUNC(drawString,
76+
l_HudGaugeDrawFuncs,
77+
"number x, number y, string text",
78+
"Draws a string in the context of the HUD gauge.",
79+
"boolean",
80+
"true on success, false otherwise") {
81+
HudGauge* gauge;
82+
float x;
83+
float y;
84+
const char* text;
85+
86+
if (!ade_get_args(L, "offs", l_HudGaugeDrawFuncs.Get(&gauge), &x, &y, &text)) {
87+
return ADE_RETURN_FALSE;
88+
}
89+
90+
int gauge_x, gauge_y;
91+
gauge->getPosition(&gauge_x, &gauge_y);
92+
93+
gauge->renderString(fl2i(gauge_x + x), fl2i(gauge_y), text);
94+
95+
return ADE_RETURN_TRUE;
96+
}
4397

4498
}
4599
}

code/scripting/api/objs/hudgauge.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ namespace api {
1010

1111
DECLARE_ADE_OBJ(l_HudGauge, HudGauge*);
1212

13+
DECLARE_ADE_OBJ(l_HudGaugeDrawFuncs, HudGauge*);
14+
1315
}
1416
}
1517

0 commit comments

Comments
 (0)