Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/guide/scripting.md
Original file line number Diff line number Diff line change
Expand Up @@ -2170,7 +2170,8 @@ return {
}
```

The rooms draw their pointer over what scripts draw, as the front end does over a mod's screen.
The pointer goes over what scripts draw, in the rooms and their places, on the front end's screens
and a mod's, and on the menus over the rooms and over a mission.
[`examples/mods/cd-player-pages`](../../examples/mods/cd-player-pages) gives the CD player its
pages, with the front end's arrows under its screen.

Expand Down
88 changes: 61 additions & 27 deletions src/engine/game/hudoptions.zig
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,14 @@ pub const PauseMenu = struct {
view_setting: camera.CockpitSetting = .cockpit,
/// The archive the fonts came from, which the settings screen's shapes are read from.
archive: ?bigfile.Hog = null,
/// The settings screen, while it is shown.
/// The settings screen, while it is shown, and on the frame that leaves it.
settings: ?SettingsScreen = null,
/// The pointer that this frame's drawing ends with, which `drawPointer` draws: the main
/// screen's or the settings screen's; none once the pause has an outcome, or where the
/// settings screen's shapes are left out.
pointer_shown: ?PointerShown = null,

const PointerShown = enum { main, settings };

/// `optfnt.fnt` and `smlfnt2.fnt`, as `hog_load` read them and `font_open` opened them
/// (`menu_font_large`, `menu_font_small`), and what holds them and their glyphs' images.
Expand Down Expand Up @@ -195,24 +201,23 @@ pub const PauseMenu = struct {
/// `pause_menu_draw` (`0x004906F0`), the overlay while paused, with the pointer brought up to
/// date first as `mission_paused_frame` does (`menu_mouse_update`). A screen shown for the
/// first time runs its enter routine; if its choice goes elsewhere, it runs its leave routine.
/// The pointer is drawn last.
/// The game draws the pointer last, which OpenReliant draws after what scripts draw over the
/// menu (`drawPointer`).
pub fn draw(pause_menu: *PauseMenu, frame: Frame) menu.Error!void {
pause_menu.pointer_shown = null;
const fonts = if (pause_menu.fonts) |*open_fonts| open_fonts else return;
pause_menu.pointer.update(frame.devices.mouse, frame.screen);
const ui: menu.Ui = .{
.gpa = fonts.gpa,
.target = frame.target,
.screen = frame.screen,
.scale = frame.ui_scale.of(frame.screen),
.art = frame.art,
.fonts = .{ .display = frame.font, .small = &fonts.small.font, .large = &fonts.large.font },
.strings = frame.strings,
};
const ui = uiOf(frame, fonts);
const screen = switch (pause_menu.at) {
.screen => |shown| shown,
.outcome => return,
};
const tab = SettingsScreen.tabOf(screen);
// The settings screen the frame before left goes, now that its pointer has been drawn.
if (tab == null) if (pause_menu.settings) |*shown| {
shown.close(fonts.gpa);
pause_menu.settings = null;
};
if (pause_menu.entered != screen) {
if (tab) |shown| pause_menu.enterSettings(frame, shown);
pause_menu.entered = screen;
Expand All @@ -222,14 +227,51 @@ pub const PauseMenu = struct {
.pointer = pause_menu.pointer,
.escaped = frame.devices.keyboard.pressed(input.scan.escape, .none, true),
});
if (next) |going| if (!std.meta.eql(going, pause_menu.at)) {
if (pause_menu.settings) |*shown| shown.close(fonts.gpa);
pause_menu.settings = null;
pause_menu.at = going;
};
if (next) |going| pause_menu.at = going;
if (tab != null) return;
if (frame.version) |version| try hud.drawVersion(ui.fonts.small, ui.gpa, ui.target, ui.screen, version, ui.scale);
try ui.drawPointer(pause_menu.pointer);
pause_menu.pointer_shown = .main;
}

/// The end of `pause_menu_draw`: the pointer of the screen drawn, which OpenReliant draws after
/// what the scripts draw over the menu, so that it stays on top
/// ([#1171](https://github.com/OpenReliant/openreliant/issues/1171)).
pub fn drawPointer(pause_menu: *PauseMenu, frame: Frame) menu.Error!void {
const fonts = if (pause_menu.fonts) |*open_fonts| open_fonts else return;
switch (pause_menu.pointer_shown orelse return) {
.main => try uiOf(frame, fonts).drawPointer(pause_menu.pointer),
.settings => {
const shown = if (pause_menu.settings) |*kept| kept else return;
const shapes = if (shown.shapes) |*read| &read.art else return;
try settingsCanvas(frame, fonts).drawPointer(shapes, shown.pointer);
},
}
}

/// What the main screen draws with.
fn uiOf(frame: Frame, fonts: *Fonts) menu.Ui {
return .{
.gpa = fonts.gpa,
.target = frame.target,
.screen = frame.screen,
.scale = frame.ui_scale.of(frame.screen),
.art = frame.art,
.fonts = .{ .display = frame.font, .small = &fonts.small.font, .large = &fonts.large.font },
.strings = frame.strings,
};
}

/// What the settings screen draws on.
fn settingsCanvas(frame: Frame, fonts: *Fonts) canvas.Canvas {
return .{
.gpa = fonts.gpa,
.target = frame.target,
.window = frame.screen,
.share = frame.ui_scale.share(),
.fonts = .{ .large = &fonts.large.font, .small = &fonts.small.font },
.strings = frame.strings,
.version = frame.version,
};
}

/// Opens the settings screen on `tab`: the front end's shapes and its dialog's read, and the
Expand Down Expand Up @@ -261,16 +303,8 @@ pub const PauseMenu = struct {
hud.drawFilled(frame.target, .{ .left = 0, .top = 0, .right = @floatFromInt(frame.screen[0]), .bottom = @floatFromInt(frame.screen[1]) }, shade);
const shapes = if (shown.shapes) |*read| &read.art else return .{ .screen = .main };
const dialog_art = if (shown.dialog) |*read| &read.art else return .{ .screen = .main };
const drawn: canvas.Canvas = .{
.gpa = fonts.gpa,
.target = frame.target,
.window = frame.screen,
.share = frame.ui_scale.share(),
.fonts = .{ .large = &fonts.large.font, .small = &fonts.small.font },
.strings = frame.strings,
.version = frame.version,
};
try shown.screen.draw(drawn, shapes, dialog_art, .{ .devices = frame.devices, .sound = frame.settings.sound, .video = frame.settings.video }, shown.pointer);
try shown.screen.draw(settingsCanvas(frame, fonts), shapes, dialog_art, .{ .devices = frame.devices, .sound = frame.settings.sound, .video = frame.settings.video });
pause_menu.pointer_shown = .settings;
return switch (end orelse return null) {
.back, .main_menu => .{ .screen = .main },
.continue_mission => .{ .outcome = .continue_mission },
Expand Down
7 changes: 7 additions & 0 deletions src/engine/game/interface/canvas.zig
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,13 @@ pub const Canvas = struct {
}
};

/// Draws `pointer` with its shape in `art`. The screens of the front end and the menus draw
/// their pointer last, so OpenReliant draws it after what the scripts draw over a screen, which
/// keeps it on top ([#1171](https://github.com/OpenReliant/openreliant/issues/1171)).
pub fn drawPointer(canvas: Canvas, art: *hud.Art, pointer: Pointer) Error!void {
try canvas.onScreen().shape(art, pointer.shape(), pointer.at);
}

/// **Improvement:** OpenReliant's version, where the canvas has one, in the window's bottom
/// right corner as the pause menu writes it (`hud.drawVersion`), as large as the screen's text.
/// A screen writes it before its pointer.
Expand Down
5 changes: 2 additions & 3 deletions src/engine/game/interface/game_modes.zig
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ pub const GameModes = struct {
}

/// The screen's drawing, over the background: the title, the list and the panel, the buttons,
/// the one under the pointer lit, OpenReliant's version, then the pointer.
pub fn draw(screen: GameModes, canvas: Canvas, art: *hud.Art, pointer: Pointer) canvas_module.Error!void {
/// the one under the pointer lit, and OpenReliant's version. The pointer goes over it all, after what scripts draw (`canvas.Canvas.drawPointer`).
pub fn draw(screen: GameModes, canvas: Canvas, art: *hud.Art) canvas_module.Error!void {
const modes = screen.modes;
try title.write(canvas, canvas.fonts.large, canvas_module.white);
mod_manager.list_frame.draw(canvas);
Expand All @@ -195,7 +195,6 @@ pub const GameModes = struct {
try shown.draw(canvas.dimmedUnless(playable), art, settings.button_shapes, std.meta.eql(screen.lit, Item{ .button = button }));
}
try canvas.drawVersion();
try canvas.onScreen().shape(art, pointer.shape(), pointer.at);
}

/// The rows shown, each a mode's label, the chosen one white, and the arrows, the one under the
Expand Down
5 changes: 2 additions & 3 deletions src/engine/game/interface/game_options.zig
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,9 @@ pub const GameOptions = struct {

/// `game_options_draw` (`0x0042AFB0`), over the menu's background: the buttons, the item under
/// the pointer lit, the title and the labels, ABOUT OPENRELIANT's box or QUIT's question where
/// either is up, OpenReliant's version, then the pointer. The game writes the label under the
/// either is up, and OpenReliant's version. The pointer goes over it all, after what scripts draw (`canvas.Canvas.drawPointer`). The game writes the label under the
/// pointer white before the labels, which write over it in blue, so it stays blue.
pub fn draw(menu: GameOptions, canvas: Canvas, art: *hud.Art, dialog_art: *hud.Art, about_art: *hud.Art, pointer: Pointer) canvas_module.Error!void {
pub fn draw(menu: GameOptions, canvas: Canvas, art: *hud.Art, dialog_art: *hud.Art, about_art: *hud.Art) canvas_module.Error!void {
for ([_]Item{ .about, .mods, .main_menu, .quit }) |item| {
const rect = rects.get(item);
try canvas.shape(art, button_shape, .{ rect.x, rect.y });
Expand All @@ -155,7 +155,6 @@ pub const GameOptions = struct {
if (menu.about) |about| try about.draw(canvas, about_art);
if (menu.confirm) |confirm| try confirm.draw(canvas, dialog_art);
try canvas.drawVersion();
try canvas.onScreen().shape(art, pointer.shape(), pointer.at);
}
};

Expand Down
5 changes: 2 additions & 3 deletions src/engine/game/interface/in_game_options.zig
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,8 @@ pub const InGameOptions = struct {

/// `in_game_options_draw` (`0x004398B0`), over the menu's background: the buttons and their
/// labels, the item under the pointer lit, the panels' labels, ABOUT OPENRELIANT's box or
/// QUIT's question where either is up, OpenReliant's version, then the pointer.
pub fn draw(menu: InGameOptions, canvas: Canvas, art: *hud.Art, dialog_art: *hud.Art, about_art: ?*hud.Art, pointer: Pointer) canvas_module.Error!void {
/// QUIT's question where either is up, and OpenReliant's version. The pointer goes over it all, after what scripts draw (`canvas.Canvas.drawPointer`).
pub fn draw(menu: InGameOptions, canvas: Canvas, art: *hud.Art, dialog_art: *hud.Art, about_art: ?*hud.Art) canvas_module.Error!void {
for (std.enums.values(Item)) |item| {
const shown = button(item) orelse continue;
try shown.draw(canvas, art, button_shapes, menu.under == item);
Expand All @@ -257,7 +257,6 @@ pub const InGameOptions = struct {
if (menu.about) |about| if (about_art) |shapes| try about.draw(canvas, shapes);
if (menu.confirm) |confirm| try confirm.draw(canvas, dialog_art);
try canvas.drawVersion();
try canvas.onScreen().shape(art, pointer.shape(), pointer.at);
}
};

Expand Down
12 changes: 8 additions & 4 deletions src/engine/game/interface/main_menu.zig
Original file line number Diff line number Diff line change
Expand Up @@ -341,9 +341,14 @@ pub const MainMenu = struct {

/// `main_menu_draw`: the panels' labels in blue, QUIT's and INSTANT ACTION's buttons and labels,
/// the item under the pointer lit and a panel's labels in gold, QUIT's question or the notice
/// of a newer release where it is up, then the pointer, and with the developers' keys on the
/// mission's number. The menu's background is drawn behind it all (`background_set`).
pub fn draw(menu: MainMenu, canvas: Canvas, art: *hud.Art, dialog_art: *hud.Art, pointer: Pointer, developer_font: ?*hud.Opened) canvas_module.Error!void {
/// of a newer release where it is up, and with the developers' keys on the mission's number.
/// The menu's background is drawn behind it all (`background_set`), and the pointer over it
/// all, after what scripts draw (`canvas.Canvas.drawPointer`).
///
/// **Improvement:** the game draws the mission's number over the pointer. OpenReliant draws
/// the pointer last, over what scripts draw too
/// ([#1171](https://github.com/OpenReliant/openreliant/issues/1171)).
pub fn draw(menu: MainMenu, canvas: Canvas, art: *hud.Art, dialog_art: *hud.Art, developer_font: ?*hud.Opened) canvas_module.Error!void {
const large = canvas.fonts.large;
const small = canvas.fonts.small;
for (std.enums.values(Item)) |item| {
Expand Down Expand Up @@ -376,7 +381,6 @@ pub const MainMenu = struct {
try asked.draw(canvas, dialog_art);
}
try canvas.drawVersion();
try canvas.onScreen().shape(art, pointer.shape(), pointer.at);
if (menu.developer) if (developer_font) |font| {
var buffer: [16]u8 = undefined;
const number = std.mem.print(&buffer, "M{d}", .{menu.mission}) catch return;
Expand Down
7 changes: 3 additions & 4 deletions src/engine/game/interface/mod_catalogue.zig
Original file line number Diff line number Diff line change
Expand Up @@ -789,9 +789,9 @@ pub const ModCatalogue = struct {
}

/// Draws the screen over the background: the title, the list, the panel, the buttons with the one
/// under the pointer highlighted and the ones that do nothing dimmed, OpenReliant's version, and
/// the pointer.
pub fn draw(screen: ModCatalogue, canvas: Canvas, art: *hud.Art, pointer: Pointer) canvas_module.Error!void {
/// under the pointer highlighted and the ones that do nothing dimmed, and OpenReliant's version.
/// The pointer goes over it all, after what scripts draw (`canvas.Canvas.drawPointer`).
pub fn draw(screen: ModCatalogue, canvas: Canvas, art: *hud.Art) canvas_module.Error!void {
try title.write(canvas, canvas.fonts.large, canvas_module.white);
list_frame.draw(canvas);
details_frame.draw(canvas);
Expand All @@ -802,7 +802,6 @@ pub const ModCatalogue = struct {
try button.shown(doing).draw(canvas.dimmedUnless(screen.usable(button)), art, settings.button_shapes, std.meta.eql(screen.lit, Item{ .button = button }));
}
try canvas.drawVersion();
try canvas.onScreen().shape(art, pointer.shape(), pointer.at);
}

/// Draws the visible rows: a group's heading in the large font, in blue, like the controls tab's
Expand Down
7 changes: 3 additions & 4 deletions src/engine/game/interface/mod_manager.zig
Original file line number Diff line number Diff line change
Expand Up @@ -630,9 +630,9 @@ pub const ModManager = struct {
}

/// The screen's drawing, over the background: the title, the note while the mods wait for the
/// next start, the list and the panel, the buttons, the one under the pointer lit, OpenReliant's
/// version, then the pointer.
pub fn draw(screen: ModManager, canvas: Canvas, art: *hud.Art, pointer: Pointer) canvas_module.Error!void {
/// next start, the list and the panel, the buttons, the one under the pointer lit, and
/// OpenReliant's version. The pointer goes over it all, after what scripts draw (`canvas.Canvas.drawPointer`).
pub fn draw(screen: ModManager, canvas: Canvas, art: *hud.Art) canvas_module.Error!void {
try title.write(canvas, canvas.fonts.large, canvas_module.white);
if (screen.waits()) try restart_note.write(canvas, canvas.fonts.small, canvas_module.gold);
list_frame.draw(canvas);
Expand All @@ -646,7 +646,6 @@ pub const ModManager = struct {
}
try movers.draw(canvas, art, screen.litArrow(.move));
try canvas.drawVersion();
try canvas.onScreen().shape(art, pointer.shape(), pointer.at);
}

/// The rows whose mods load, as the rows stand: the mods that are on, aren't damaged, and have
Expand Down
5 changes: 2 additions & 3 deletions src/engine/game/interface/mod_options.zig
Original file line number Diff line number Diff line change
Expand Up @@ -486,8 +486,8 @@ pub const ModOptions = struct {
}

/// The screen's drawing, over the background: the title, the list, the buttons, the one under the
/// pointer lit, the text of the option under it, OpenReliant's version, then the pointer.
pub fn draw(screen: *const ModOptions, canvas: Canvas, art: *hud.Art, pointer: Pointer) canvas_module.Error!void {
/// pointer lit, the text of the option under it, and OpenReliant's version. The pointer goes over it all, after what scripts draw (`canvas.Canvas.drawPointer`).
pub fn draw(screen: *const ModOptions, canvas: Canvas, art: *hud.Art) canvas_module.Error!void {
try (Label{ .text = .{ .words = screen.page.title }, .at = title_at, .alignment = .centre }).write(canvas, canvas.fonts.large, canvas_module.white);
var buffer: [max_options]Line.Shown = undefined;
var numbers: [max_options][number_words]u8 = undefined;
Expand All @@ -505,7 +505,6 @@ pub const ModOptions = struct {
try canvas.wrapped(canvas.fonts.small, descriptionAt(screen.pane), description, canvas_module.blue, .centre, description_lines);
};
try canvas.drawVersion();
try canvas.onScreen().shape(art, pointer.shape(), pointer.at);
}
};

Expand Down
8 changes: 4 additions & 4 deletions src/engine/game/interface/pilot_roster.zig
Original file line number Diff line number Diff line change
Expand Up @@ -468,9 +468,10 @@ pub const Roster = struct {
/// `pilot_roster_draw`: the pilot chosen, lit; the labels in blue; the call sign's frame and
/// the call sign, white while it is typed, with its cursor; the buttons and the list's arrow,
/// and the button under the pointer lit with its label in white; the list, where it is open;
/// SET GAME DIFFICULTY or QUIT's question, where either is up; then the pointer. The roster's
/// background is drawn behind it all (`background_set`).
pub fn draw(roster: Roster, canvas: Canvas, art: *hud.Art, dialog_art: *hud.Art, pointer: Pointer, pilot: Pilot) canvas_module.Error!void {
/// SET GAME DIFFICULTY or QUIT's question, where either is up. The roster's background is drawn
/// behind it all (`background_set`), and the pointer over it all, after what scripts draw
/// (`canvas.Canvas.drawPointer`).
pub fn draw(roster: Roster, canvas: Canvas, art: *hud.Art, dialog_art: *hud.Art, pilot: Pilot) canvas_module.Error!void {
const small = canvas.fonts.small;
if (pilot.female) try canvas.shape(art, female_shape, female_at) else try canvas.shape(art, male_shape, male_at);
for (labels.values) |held| if (held) |label| try writeLabel(canvas, label, canvas_module.blue);
Expand All @@ -497,7 +498,6 @@ pub const Roster = struct {
if (roster.difficulty) |box| try box.draw(canvas, art, pilot.difficulty);
if (roster.confirm) |confirm| try confirm.draw(canvas, dialog_art);
try canvas.drawVersion();
try canvas.onScreen().shape(art, pointer.shape(), pointer.at);
}
};

Expand Down
Loading
Loading