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
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ the game as it's made.
**Status:** Mission mode's Script view works. It opens a mod's missions, a mission file or one of
the game's own missions as source, colours it with the game's commands, checks it as it's typed,
offers the game's commands and conditions as you type, explains them on hover and in the Reference
panel, builds the mission, and plays it in OpenReliant, from its start or from a part. Linked to the
game, it holds the mission's script at breakpoints, steps through it, and shows its threads and
values ([Debugging a mission](docs/debugging.md)). The rest of the [design](design/README.md) is in
panel, builds the mission, and plays it in OpenReliant, from its start or from a part. The inspector
edits the records as forms, and the outline adds new ones ([Editing records](docs/editing.md)).
Linked to the game, it holds the mission's script at breakpoints, steps through it, and shows its
threads and values ([Debugging a mission](docs/debugging.md)). The rest of the [design](design/README.md) is in
place and greyed out, each part with the issue that plans it.
The plan is OpenReliant's [#1126](https://github.com/OpenReliant/openreliant/issues/1126).

Expand Down
Binary file modified design/images/keys-macos.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified design/images/keys.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified design/images/settings-link.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 6 additions & 1 deletion design/screens/keys-macos.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
.panel{background:#10131b;display:flex;flex-direction:column;min-width:0;border:1px solid #1a1f2b;border-radius:3px;overflow:hidden}
.nav{display:flex;align-items:center;gap:9px;width:100%;height:30px;padding:0 12px;border:0;border-radius:4px;background:none;color:#c9cfdb;font:inherit;font-size:13px;text-align:left;cursor:pointer}
.nav:hover{background:#171b26}
.back{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:0;border-radius:4px;background:none;color:#c9cfdb;cursor:pointer}
.back:hover{background:#171b26;color:#ffffff}
.nav-on,.nav-on:hover{background:#262d3d;color:#ffffff}
.sect{font-size:10.5px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:#8a93a6}
.kr{display:grid;grid-template-columns:minmax(150px,1.4fr) minmax(130px,1fr) minmax(130px,1fr) 40px;align-items:center;min-height:32px;padding:0 14px;border-bottom:1px solid #161b26;font-size:12.5px;color:#d4d8e1}
Expand Down Expand Up @@ -58,7 +60,10 @@
<div style="flex: 1 1 auto; display: flex; flex-wrap: wrap; gap: 3px; padding: 3px; min-height: 0">

<section class="panel" aria-label="Settings" style="flex: 1 1 220px">
<div style="padding: 14px 12px 8px; font-family: Newtown, 'IBM Plex Sans', sans-serif; font-size: 16px; letter-spacing: 0.02em">Settings</div>
<div style="display: flex; align-items: center; gap: 4px; padding: 9px 8px 3px">
<button class="back" type="button" aria-label="Back" title="Back · Esc"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="m12 19-7-7 7-7"></path><path d="M19 12H5"></path></svg></button>
<span style="font-family: Newtown, 'IBM Plex Sans', sans-serif; font-size: 16px; letter-spacing: 0.02em">Settings</span>
</div>
<nav aria-label="Settings pages" style="display: flex; flex-direction: column; gap: 2px; padding: 4px 8px">
<button class="nav" type="button">General</button>
<button class="nav" type="button">Appearance</button>
Expand Down
7 changes: 6 additions & 1 deletion design/screens/keys.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
.panel{background:#10131b;display:flex;flex-direction:column;min-width:0;border:1px solid #1a1f2b;border-radius:3px;overflow:hidden}
.nav{display:flex;align-items:center;gap:9px;width:100%;height:30px;padding:0 12px;border:0;border-radius:4px;background:none;color:#c9cfdb;font:inherit;font-size:13px;text-align:left;cursor:pointer}
.nav:hover{background:#171b26}
.back{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:0;border-radius:4px;background:none;color:#c9cfdb;cursor:pointer}
.back:hover{background:#171b26;color:#ffffff}
.nav-on,.nav-on:hover{background:#262d3d;color:#ffffff}
.sect{font-size:10.5px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:#8a93a6}
.kr{display:grid;grid-template-columns:minmax(150px,1.4fr) minmax(130px,1fr) minmax(130px,1fr) 40px;align-items:center;min-height:32px;padding:0 14px;border-bottom:1px solid #161b26;font-size:12.5px;color:#d4d8e1}
Expand Down Expand Up @@ -58,7 +60,10 @@
<div style="flex: 1 1 auto; display: flex; flex-wrap: wrap; gap: 3px; padding: 3px; min-height: 0">

<section class="panel" aria-label="Settings" style="flex: 1 1 220px">
<div style="padding: 14px 12px 8px; font-family: Newtown, 'IBM Plex Sans', sans-serif; font-size: 16px; letter-spacing: 0.02em">Settings</div>
<div style="display: flex; align-items: center; gap: 4px; padding: 9px 8px 3px">
<button class="back" type="button" aria-label="Back" title="Back · Esc"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="m12 19-7-7 7-7"></path><path d="M19 12H5"></path></svg></button>
<span style="font-family: Newtown, 'IBM Plex Sans', sans-serif; font-size: 16px; letter-spacing: 0.02em">Settings</span>
</div>
<nav aria-label="Settings pages" style="display: flex; flex-direction: column; gap: 2px; padding: 4px 8px">
<button class="nav" type="button">General</button>
<button class="nav" type="button">Appearance</button>
Expand Down
7 changes: 6 additions & 1 deletion design/screens/settings-link.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
.panel{background:#10131b;display:flex;flex-direction:column;min-width:0;border:1px solid #1a1f2b;border-radius:3px;overflow:hidden}
.nav{display:flex;align-items:center;gap:9px;width:100%;height:30px;padding:0 12px;border:0;border-radius:4px;background:none;color:#c9cfdb;font:inherit;font-size:13px;text-align:left;cursor:pointer}
.nav:hover{background:#171b26}
.back{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:0;border-radius:4px;background:none;color:#c9cfdb;cursor:pointer}
.back:hover{background:#171b26;color:#ffffff}
.nav-on,.nav-on:hover{background:#262d3d;color:#ffffff}
.sect{font-size:10.5px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:#8a93a6}
.kr{display:grid;grid-template-columns:minmax(150px,1.4fr) minmax(130px,1fr) minmax(130px,1fr) 40px;align-items:center;min-height:32px;padding:0 14px;border-bottom:1px solid #161b26;font-size:12.5px;color:#d4d8e1}
Expand Down Expand Up @@ -70,7 +72,10 @@
<div style="flex: 1 1 auto; display: flex; flex-wrap: wrap; gap: 3px; padding: 3px; min-height: 0">

<section class="panel" aria-label="Settings" style="flex: 1 1 220px">
<div style="padding: 14px 12px 8px; font-family: Newtown, 'IBM Plex Sans', sans-serif; font-size: 16px; letter-spacing: 0.02em">Settings</div>
<div style="display: flex; align-items: center; gap: 4px; padding: 9px 8px 3px">
<button class="back" type="button" aria-label="Back" title="Back · Esc"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="m12 19-7-7 7-7"></path><path d="M19 12H5"></path></svg></button>
<span style="font-family: Newtown, 'IBM Plex Sans', sans-serif; font-size: 16px; letter-spacing: 0.02em">Settings</span>
</div>
<nav aria-label="Settings pages" style="display: flex; flex-direction: column; gap: 2px; padding: 4px 8px">
<button class="nav" type="button">General</button>
<button class="nav" type="button">Appearance</button>
Expand Down
26 changes: 22 additions & 4 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ own library, which `build.zig.zon` pins, so it reads every mission exactly as th
| [`game.zig`](../src/game.zig) | What the editor asks of a game: the profile |
| [`game/starlancer.zig`](../src/game/starlancer.zig) | StarLancer's profile, on OpenReliant's tables and compiler |
| [`project.zig`](../src/project.zig) | A mod folder and its missions, and the mods of a game folder |
| [`mission/document.zig`](../src/mission/document.zig) | An open mission: its source, its checks, its build and its breakpoints |
| [`mission/document.zig`](../src/mission/document.zig) | An open mission: its source, its checks, its build and its breakpoints, and the changes the interface asks for |
| [`mission/edit.zig`](../src/mission/edit.zig) | Changes to spans of mission source: a field of a record's table set, added or taken out, an argument replaced |
| [`link/connection.zig`](../src/link/connection.zig) | The editor link's connection to the game, on a task of its own |
| [`debug/session.zig`](../src/debug/session.zig) | The debugger: the link's state, the game's mission matched with the build, the holds, the state and the actions |
| [`debug/breakpoints.zig`](../src/debug/breakpoints.zig) | Where each breakpoint holds the script, and each source file's breakpoints kept in the settings folder |
| [`shell.zig`](../src/shell.zig) | The workspace's menu bar, toolbar, dock space and status bar |
| [`panels.zig`](../src/panels.zig) | The dockable panels: the outline, problems, the inspector and the others |
| [`forms.zig`](../src/forms.zig) | The inspector's forms: a record's fields as controls that write the source |
| [`views/script.zig`](../src/views/script.zig) | The Script view: the source, its gutter, help and completion, and the listing |
| [`palette.zig`](../src/palette.zig) | The command palette, Play from part, and the game's missions |
| [`screens/`](../src/screens) | The start screen and the settings |
Expand All @@ -37,7 +39,8 @@ profile, a `game.Profile`:
- the words of mission source, from the game's own tables: the language's keywords, mission
source's declarations, the game's commands and conditions with their descriptions and
parameters, the game's variables, and the names of its values;
- the records a mission's source declares, for the outline and the inspector;
- the records a mission's source declares, for the outline and the inspector, the fields each
record's table can give, and the changes that edit them or declare a new record;
- building source into a mission file, with the map of its script's statements to the source's
lines, decompiling a mission file into source, and comparing two missions and their scripts;
- the game's messages on the editor link, and the script's flags for a set of offsets;
Expand All @@ -60,6 +63,23 @@ and builds it in memory, and the problems show in the gutter, under the text and
panel. While the source doesn't parse, the outline is the last one that did. Build writes the
mission file beside the source and keeps its script's listing.

## Editing records

The inspector shows the selected record as a form ([Editing records](editing.md)). The profile gives
the fields each record's table can give, from OpenReliant's tables of the language
(`dte.source.language`), each with its kind, which picks its control: a list of the mission's
records or of the game's values, X, Y and Z for a vector, a box for a number, a checkbox, or the
value's source for the rest. A few hints lay out a ship's place as the design does, under a heading
with its angles on one row.

A change, from a form, the outline's + or a Problems card's fix, is a change to one span of the
source, made as one step of the editor's undo. OpenReliant's syntax tree gives where each node
starts; `mission/edit.zig` reads the text from there for where the value ends, and sets, adds or
takes out a field in the table's own layout: on its line, or on a line of its own where the items
are each on one. While drawing, the interface only queues the change (`Document.queue`). The app
makes it once the frame is drawn, since making it checks the text again, which replaces the outline
the frame drew from.

## The debugger

The debugger links to the game over OpenReliant's editor link ([Debugging a mission](debugging.md)).
Expand Down Expand Up @@ -90,8 +110,6 @@ Each shows in the interface, greyed out, with its issue:
([#22](https://github.com/OpenReliant/openreliant-editor/issues/22));
- the guided first mission ([#6](https://github.com/OpenReliant/openreliant-editor/issues/6));
- new mods from templates ([#7](https://github.com/OpenReliant/openreliant-editor/issues/7));
- adding and editing records with forms
([#8](https://github.com/OpenReliant/openreliant-editor/issues/8));
- opening `.hog` mods ([#9](https://github.com/OpenReliant/openreliant-editor/issues/9));
- the General and Appearance settings
([#10](https://github.com/OpenReliant/openreliant-editor/issues/10)).
34 changes: 34 additions & 0 deletions docs/editing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Editing records

The inspector shows the record selected in the outline, or the one the source's cursor is in, as a
form. Each change is written into the source at once, as one step of Undo, and the source keeps its
own layout. The form can't change the source while it has problems: fix them first.

## The forms

- **Name** is the display name the game shows. **Declared as** is the name the source declares it
under, which the script uses.
- A field that names a record, such as a ship's **Group**, lists the mission's records it can name.
One that names a value of the game, such as a ship's **Type** or **Pilot**, lists the game's
values, with a box to find one in a long list. `none` takes the field out of the table.
- A ship's or a marker's **Position** has a box for X, Y and Z, and its **Angles** a box for the
yaw, the pitch and the roll, in degrees. Y points down.
- A number takes effect with Enter or by leaving its box. Escape puts back the value.
- A field the form can't show as a list or a number, such as a ship's **Launch**, shows its source,
which you can type.
- A trigger's form sets what it **Watches**, its **Condition**, and the values of the condition's
events it checks, how it **Repeats** and whether it's **Deferred**.

Each field's label tells what the field is when you rest the pointer on it.

## Adding records

The outline's + button, or Mission · Add a record, lists the records it can add: a ship, a nav
point, a waypoint, a flight group, a part, a trigger and a global. The new record goes after the
last one of its kind, under a name no record has, such as `ship_1`, and the form opens on it. A new
trigger watches nothing until you choose what it watches.

A name the source uses without declaring it shows in the Problems panel with **Declare**, which adds
a record under that name: choose what kind it is.

Squads, formations and curves list other records, and are written in the source.
52 changes: 50 additions & 2 deletions src/app.zig
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,11 @@ pub const App = struct {
project: ?Project = null,
document: ?*Document = null,
selection: ?Selection = null,
/// Whether the menu of records to add opens on the next frame, as + and Add a record ask, and
/// the name a Problems card's Declare gives the new record, `declare_name[0..declare_length]`.
add_menu: bool = false,
declare_name: [128]u8 = undefined,
declare_length: ?usize = null,
/// The word whose reference the Reference panel shows.
reference_word: ?[]const u8 = null,
reference_buffer: [64]u8 = undefined,
Expand Down Expand Up @@ -278,6 +283,7 @@ pub const App = struct {
palette.draw(app);
app.toasts.draw(app.window);
app.drawCloseConfirmation();
app.makeQueued();
}

/// The shortcuts of the actions, run while the editor's windows have the keyboard.
Expand Down Expand Up @@ -311,7 +317,7 @@ pub const App = struct {
if (commands.info(command).planned) |plan| return .{ .reason = gui.print("Planned · {f}", .{plan}) };
const needs_document = "Open a mission first";
return switch (command) {
.save, .build, .show_source, .show_listing, .toggle_breakpoint, .clear_breakpoints, .go_to_line, .comment_line, .find, .find_next, .replace, .undo, .redo, .cut, .copy, .paste, .select_all => if (app.document == null) .{ .reason = needs_document } else null,
.add_record, .save, .build, .show_source, .show_listing, .toggle_breakpoint, .clear_breakpoints, .go_to_line, .comment_line, .find, .find_next, .replace, .undo, .redo, .cut, .copy, .paste, .select_all => if (app.document == null) .{ .reason = needs_document } else null,
.play, .play_from_part => if (app.document == null) .{ .reason = needs_document } else if (app.settings.game_folder == null) .{ .reason = "Set the game's folder in Game settings" } else null,
.new_mission => if (app.settings.game_folder == null and app.project == null) .{ .reason = "Set the game's folder in Game settings" } else null,
.edit_game_mission => if (app.settings.game_folder == null) .{ .reason = "Set the game's folder in Game settings" } else null,
Expand Down Expand Up @@ -380,7 +386,8 @@ pub const App = struct {
/// Runs `command`.
pub fn run(app: *App, command: Command) void {
switch (command) {
.new_mod, .open_hog, .switch_mode, .layout_guided, .add_record => {},
.new_mod, .open_hog, .switch_mode, .layout_guided => {},
.add_record => app.askToAdd(null),
.open_file => app.chooseFile(),
.edit_game_mission => app.palette.show(.game_missions),
.@"continue" => app.session.release(.run_on),
Expand Down Expand Up @@ -969,6 +976,47 @@ pub const App = struct {
if (document.outline().find(selected.section, selected.line) == null) app.selection = null;
}

/// Opens the menu of records to add, which declares the record chosen under `name` where one
/// is given, as a Problems card's Declare asks.
pub fn askToAdd(app: *App, name: ?[]const u8) void {
app.add_menu = true;
app.declare_length = null;
const given = name orelse return;
if (given.len > app.declare_name.len) return;
@memcpy(app.declare_name[0..given.len], given);
app.declare_length = given.len;
}

/// The name the menu of records to add declares the new one under, where a Declare asked.
pub fn declaring(app: *const App) ?[]const u8 {
return app.declare_name[0 .. app.declare_length orelse return null];
}

/// Makes the change to the source that the interface asked for during the frame
/// (`Document.queue`), now that nothing drawn holds on to the outline it replaces: says where
/// it can't be made, and selects a record added.
fn makeQueued(app: *App) void {
const document = app.document orelse return;
const asked = document.queued orelse return;
const made = document.flush() catch {
app.toasts.push(.failure, "Can't change the source", "Out of memory");
return;
};
const reason = if (document.outline_stale) "Fix the source's problems first" else switch (asked) {
.add => "The name is taken",
else => "The declaration has no place for it",
};
switch (made) {
.none => {},
.edited => |done| if (!done) app.toasts.push(.info, "Can't change it here", reason),
.added => |added| {
const line = added.line orelse return app.toasts.push(.info, gui.print("Can't add {s}", .{asked.add.name orelse asked.add.kind.label}), reason);
app.selection = .{ .section = added.section, .line = line };
app.goTo(line, 0);
},
}
}

pub fn select(app: *App, record: game.Record) void {
app.selection = .{ .section = record.section, .line = record.first_line };
}
Expand Down
3 changes: 1 addition & 2 deletions src/commands.zig
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,6 @@ pub const plans = struct {
pub const live_changes: Plan = .{ .issue = 22 };
pub const guided: Plan = .{ .issue = 6 };
pub const templates: Plan = .{ .issue = 7 };
pub const records: Plan = .{ .issue = 8 };
pub const hogs: Plan = .{ .issue = 9 };
pub const settings: Plan = .{ .issue = 10 };
pub const live_scene: Plan = .{ .issue = 21 };
Expand Down Expand Up @@ -249,7 +248,7 @@ pub fn info(command: Command) Info {
.full_screen => .{ .label = "Full screen", .icon = .maximize, .when = .not_held, .keys = defaults(&.{"F11"}, &.{"Ctrl+Cmd+F"}), .key_group = .general },

.build => .{ .label = "Build", .icon = .hammer, .keys = defaults(&.{"Ctrl+B"}, &.{"Cmd+B"}), .key_group = .build_and_play },
.add_record => .{ .label = "Add a record", .icon = .plus, .planned = plans.records },
.add_record => .{ .label = "Add a record", .icon = .plus },
.show_source => .{ .label = "Mission source", .icon = .file_code },
.show_listing => .{ .label = "Script listing", .icon = .list },

Expand Down
Loading
Loading