Skip to content

Commit 1662a3c

Browse files
committed
Add new HUD gauge type for scripted gauges
The new gauge can be accessed by the scripting API with which a function can be set which will be called when this gauge is rendered. This can be used for exposing the HUD gauge positioning and RTT options to the scripting API without a lot of work needed for the script writer. There is currently only one rendering function implemented since this is only a proof of concept.
1 parent 62963d2 commit 1662a3c

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"
@@ -1222,6 +1224,25 @@ void HUD_init()
12221224
default_hud_gauges[j]->resetTimers();
12231225
default_hud_gauges[j]->updateSexpOverride(false);
12241226
}
1227+
1228+
Script_system.OnStateDestroy.add(hud_scripting_close);
1229+
}
1230+
1231+
void hud_scripting_close(lua_State*) {
1232+
// Clean up Lua references so that we don't have dangling references on to the lua state in the HUD gauges
1233+
for (auto it = Ship_info.begin(); it != Ship_info.end(); ++it) {
1234+
for (const auto& gauge : it->hud_gauges) {
1235+
if (gauge->getObjectType() == HUD_OBJECT_SCRIPTING) {
1236+
static_cast<HudGaugeScripting*>(gauge.get())->setRenderFunction(luacpp::LuaFunction());
1237+
}
1238+
}
1239+
}
1240+
1241+
for (const auto& gauge : default_hud_gauges) {
1242+
if (gauge->getObjectType() == HUD_OBJECT_SCRIPTING) {
1243+
static_cast<HudGaugeScripting*>(gauge.get())->setRenderFunction(luacpp::LuaFunction());
1244+
}
1245+
}
12251246
}
12261247

12271248
/**

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"
@@ -898,6 +899,9 @@ int parse_gauge_type()
898899

899900
if ( optional_string("+Secondary Weapons:") )
900901
return HUD_OBJECT_SECONDARY_WEAPONS;
902+
903+
if ( optional_string("+Scripted Gauge:") )
904+
return HUD_OBJECT_SCRIPTING;
901905

902906
return -1;
903907
}
@@ -1078,6 +1082,9 @@ void load_gauge(int gauge, gauge_settings* settings)
10781082
case HUD_OBJECT_SECONDARY_WEAPONS:
10791083
load_gauge_secondary_weapons(settings);
10801084
break;
1085+
case HUD_OBJECT_SCRIPTING:
1086+
load_gauge_scripting(settings);
1087+
break;
10811088
default:
10821089
// It's either -1, indicating we're ignoring a parse error, or it's a coding error.
10831090
Assertion(gauge == -1, "Invalid value '%d' passed to load_gauge(); get a coder!\n", gauge);
@@ -5192,3 +5199,15 @@ void load_gauge_secondary_weapons(gauge_settings* settings)
51925199

51935200
gauge_assign_common(settings, std::move(hud_gauge));
51945201
}
5202+
5203+
void load_gauge_scripting(gauge_settings* settings) {
5204+
auto hud_gauge = gauge_load_common<HudGaugeScripting>(settings);
5205+
5206+
required_string("Name:");
5207+
SCP_string name;
5208+
stuff_string(name, F_NAME);
5209+
5210+
hud_gauge->initName(name);
5211+
5212+
gauge_assign_common(settings, std::move(hud_gauge));
5213+
}

code/hud/hudparse.h

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

233+
#define HUD_OBJECT_SCRIPTING 56
234+
void load_gauge_scripting(gauge_settings* settings);
235+
233236
#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)