Skip to content

Commit 033868c

Browse files
committed
wip
1 parent 6a03e87 commit 033868c

35 files changed

Lines changed: 1098 additions & 757 deletions

CLAUDE.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Working in this repo
2+
3+
## Use `just` for every dev command
4+
5+
Never invoke `cargo`, `pytest`, `luacheck` or `tools/e2e/ui_driver.py` directly. The
6+
recipes carry the right directories, flags and env (the crate lives in `native/`, so
7+
plain `cargo` from the repo root does not even find a `Cargo.toml`).
8+
9+
| Task | Command |
10+
| --- | --- |
11+
| All lints + type-check (before review) | `just lint` |
12+
| Rust format check | `just fmt` |
13+
| Clippy (warnings denied) | `just clippy` |
14+
| Lua lint | `just lint-lua` |
15+
| Type-check native | `just check` |
16+
| Build native plugin | `just build` (alias of `just build-native`) |
17+
| Build the engine | `just build-engine` |
18+
| Build engine-side bindings | `just build-engine-bindings` |
19+
| Rust unit tests | `just test-unit` |
20+
| Integration suite (boots engine) | `just test-integration` (or `just test-integration <tag>`) |
21+
| Everything, incl. slow tests | `just test-all` |
22+
| Native verification chain | `just verify-native` |
23+
| UI e2e (build native first!) | `just test-e2e <target> "<args>"` |
24+
| Long-lived editor session | `just run config/ui-chili.json` |
25+
26+
E2E examples — `just build` first, `test-e2e` does not rebuild:
27+
28+
just test-e2e units-panel "--tag ui:rust"
29+
just test-e2e collision "--tag ui:rust"
30+
just test-e2e dev-console "--tag ui:chili"
31+
32+
`just --list` shows every recipe.
33+
34+
## Use the file tools, not shell text tools
35+
36+
Read files with **Read**; change them with **Edit**/**Write**. Do not use `sed`, `cat`,
37+
`head`, `tail`, or python one-liners to read or edit a file, and do not use `grep` as a
38+
substitute for opening it. Searching to *locate* a file is fine — once located, Read it.
39+
Partial views are how bugs get misread and invented.
40+
41+
## Never run destructive git
42+
43+
No `git checkout`, `git stash`, `git restore`, `git reset`. The tree carries a lot of
44+
uncommitted work. Undo by hand, with edits.

LuaUI/widgets/dbg_dev_console.lua

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ function widget:Initialize()
471471
screen = Chili.Screen0
472472
Spring.SendCommands("bind f8 " .. COMMAND_NAME)
473473
Spring.SendCommands("console 0")
474+
EnsureWindow()
474475
end
475476

476477
function widget:Shutdown()
@@ -484,15 +485,14 @@ function widget:GetConfigData()
484485
return cfg
485486
end
486487

487-
function widget:SetConfigData(data)
488-
if not enabled() then
488+
-- Build the console once, whether or not the user has saved config for it.
489+
-- SetConfigData only runs when there *is* saved config, so a fresh profile (an
490+
-- isolated e2e run, a clean checkout) used to end up with no console at all.
491+
function EnsureWindow()
492+
if window then
489493
return
490494
end
491495

492-
for k, v in pairs(data) do
493-
cfg[k] = v
494-
end
495-
496496
loadWindow()
497497

498498
-- Initialization which depends on the content
@@ -502,6 +502,18 @@ function widget:SetConfigData(data)
502502
end
503503
end
504504

505+
function widget:SetConfigData(data)
506+
if not enabled() then
507+
return
508+
end
509+
510+
for k, v in pairs(data) do
511+
cfg[k] = v
512+
end
513+
514+
EnsureWindow()
515+
end
516+
505517
local function processLine(line)
506518
-- get data from player roster
507519
local roster = Spring.GetPlayerRoster()

native/src/sbc/panels/editors/brush.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,8 @@ impl BrushActions {
185185
caption: &str,
186186
enabled: bool,
187187
) {
188-
let reason = (!enabled && caption == "DNTS").then_some(
189-
"DNTS unavailable: splat textures are not available on this map.",
190-
);
188+
let reason = (!enabled && caption == "DNTS")
189+
.then_some("DNTS unavailable: splat textures are not available on this map.");
191190
self.set_enabled_with_reason(interface, document, caption, enabled, reason);
192191
}
193192

native/src/sbc/panels/editors/def_filters.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,14 @@ impl UnitTraits {
2929
/// Read the traits the filters need straight off the engine's UnitDef table.
3030
pub(crate) fn read(interface: &NativeInterfaceRef, unit_def_id: i32) -> UnitTraits {
3131
let defs = interface.unit_defs();
32-
let flag = |key: &str| defs.get_unit_def_param_bool(unit_def_id, key).unwrap_or(false);
33-
let number = |key: &str| defs.get_unit_def_param_float(unit_def_id, key).unwrap_or(0.0);
32+
let flag = |key: &str| {
33+
defs.get_unit_def_param_bool(unit_def_id, key)
34+
.unwrap_or(false)
35+
};
36+
let number = |key: &str| {
37+
defs.get_unit_def_param_float(unit_def_id, key)
38+
.unwrap_or(0.0)
39+
};
3440

3541
UnitTraits {
3642
is_building: flag("isBuilding"),
@@ -153,7 +159,10 @@ mod tests {
153159

154160
let mut floater = ground_unit();
155161
floater.float_on_water = true;
156-
assert!(!floater.matches_terrain("Ground"), "a floater is not ground");
162+
assert!(
163+
!floater.matches_terrain("Ground"),
164+
"a floater is not ground"
165+
);
157166
assert!(floater.matches_terrain("Water"));
158167

159168
let mut deep = ground_unit();

native/src/sbc/panels/editors/map_grass.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ impl Editor for GrassEditor {
145145
interactions: &InteractionQueue,
146146
) -> Result<(), Error> {
147147
self.actions.bind(interface, document)?;
148-
self.fields.bind(interface, document, changes, interactions)?;
148+
self.fields
149+
.bind(interface, document, changes, interactions)?;
149150
self.pattern_grid.refresh_navigation(interface, document)?;
150151
self.render_pattern_grid(interface, document)
151152
}

native/src/sbc/panels/editors/map_metal.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ impl Editor for MetalEditor {
120120
interactions: &InteractionQueue,
121121
) -> Result<(), Error> {
122122
self.actions.bind(interface, document)?;
123-
self.fields.bind(interface, document, changes, interactions)?;
123+
self.fields
124+
.bind(interface, document, changes, interactions)?;
124125
self.pattern_grid.refresh_navigation(interface, document)?;
125126
self.render_pattern_grid(interface, document)
126127
}

native/src/sbc/panels/editors/map_settings.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use std::collections::BTreeMap;
55
use std::rc::Rc;
66

77
use crate::sbc::command_system::model::Models;
8-
use crate::sbc::panels::editor::Editor;
98
use crate::sbc::envelope::envelope_fields;
9+
use crate::sbc::panels::editor::Editor;
1010
use crate::sbc::panels::editor_base::{envelope, resolve_base, FieldSet, Layout};
1111
use crate::sbc::panels::field::{ChangeQueue, Field, FieldValue, InteractionQueue};
1212
use crate::sbc::panels::fields::{AssetField, BooleanField, NumericField};
@@ -205,7 +205,9 @@ impl MapSettingsEditor {
205205
return;
206206
};
207207
let open = self.dialog.is_some();
208-
let _ = interface.rml_ui().element_set_class(dialog, "hidden", !open);
208+
let _ = interface
209+
.rml_ui()
210+
.element_set_class(dialog, "hidden", !open);
209211
if let Some(name) = &self.dialog {
210212
if let Some(title) = element_by_id(interface, document, "shading-dialog-title") {
211213
let caption = SHADING_TOGGLES
@@ -307,7 +309,8 @@ impl Editor for MapSettingsEditor {
307309
interactions: &InteractionQueue,
308310
) -> Result<(), Error> {
309311
self.document = Some(document);
310-
self.fields.bind(interface, document, changes, interactions)?;
312+
self.fields
313+
.bind(interface, document, changes, interactions)?;
311314
if let Some(host) = element_by_id(interface, document, "map-shading-modal") {
312315
interface
313316
.rml_ui()
@@ -402,7 +405,11 @@ impl Editor for MapSettingsEditor {
402405
}
403406
if self.dialog.is_some() {
404407
for id in self.shading_grid.drain_clicks() {
405-
if self.shading_grid.item(&id).is_some_and(|item| !item.is_directory) {
408+
if self
409+
.shading_grid
410+
.item(&id)
411+
.is_some_and(|item| !item.is_directory)
412+
{
406413
if let Some(name) = self.dialog.take() {
407414
let Some((field, _, _)) = SHADING_TOGGLES
408415
.iter()

native/src/sbc/panels/editors/map_terrain.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ impl TerrainEditor {
109109
.set_selected((!selected.is_empty()).then_some(selected.as_str()));
110110
self.pattern_grid.render(interface, document)
111111
}
112-
113112
}
114113

115114
impl Editor for TerrainEditor {

native/src/sbc/panels/editors/map_texture.rs

Lines changed: 66 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ use std::rc::Rc;
77
use crate::sbc::command_system::model::Models;
88
use crate::sbc::panels::editor::Editor;
99
use crate::sbc::panels::editor_base::{FieldSet, Layout};
10-
use crate::sbc::rml::{element_by_id, escape_rml};
1110
use crate::sbc::panels::editors::brush::{
1211
non_empty, pattern_field, BrushAction, BrushActions, ASSETS,
1312
};
1413
use crate::sbc::panels::field::{ChangeQueue, FieldValue, InteractionQueue};
1514
use crate::sbc::panels::fields::{BooleanField, ChoiceField, ColorField, NumericField};
1615
use crate::sbc::panels::grid::{list_assets, GridItem, GridView};
1716
use crate::sbc::panels::registry::{EditorSpec, Tab};
17+
use crate::sbc::rml::{element_by_id, escape_rml};
1818
use crate::sbc::states::{BrushKind, BrushSettings};
1919

2020
// Mirrors TextureEditor:Register in scen_edit/view/map/texture_editor.lua.
@@ -478,16 +478,25 @@ impl TextureEditor {
478478
for (id, visible) in [
479479
("texture-saved-brush-section", material),
480480
("texture-saved-brush-grid", material),
481-
("texture-material-dialog", material && self.material_picker_open),
481+
(
482+
"texture-material-dialog",
483+
material && self.material_picker_open,
484+
),
482485
("texture-splat-section", mode == "dnts"),
483486
] {
484487
if let Some(elem) = element_by_id(interface, doc, id) {
485-
let _ = interface.rml_ui().element_set_class(elem, "hidden", !visible);
488+
let _ = interface
489+
.rml_ui()
490+
.element_set_class(elem, "hidden", !visible);
486491
}
487492
}
488493
}
489494

490-
fn take_grid_clicks(&mut self, interface: &NativeInterfaceRef, document: u64) -> Result<bool, Error> {
495+
fn take_grid_clicks(
496+
&mut self,
497+
interface: &NativeInterfaceRef,
498+
document: u64,
499+
) -> Result<bool, Error> {
491500
let mut changed = false;
492501
for id in self.saved_brush_grid.drain_clicks() {
493502
if id == ADD_BRUSH_ID && self.paint_mode() == "paint" {
@@ -548,39 +557,53 @@ impl TextureEditor {
548557
brush
549558
}
550559

551-
fn load_saved_brush(
552-
&mut self,
553-
id: &str,
554-
interface: &NativeInterfaceRef,
555-
) {
560+
fn load_saved_brush(&mut self, id: &str, interface: &NativeInterfaceRef) {
556561
let Some(saved) = self.saved_brushes.iter().find(|brush| brush.id == id) else {
557562
return;
558563
};
559564
let brush = saved.brush.clone();
560565
self.selected_brush = Some(id.to_string());
561566
self.selected_material = Some(saved.material.clone());
562567
self.selected = brush.brush_textures.clone();
563-
self.fields.set("patternTexture", FieldValue::Text(
564-
brush.pattern_texture.clone().unwrap_or_default(),
565-
));
568+
self.fields.set(
569+
"patternTexture",
570+
FieldValue::Text(brush.pattern_texture.clone().unwrap_or_default()),
571+
);
566572
self.fields.set("size", FieldValue::Number(brush.size));
567-
self.fields.set("rotation", FieldValue::Number(brush.rotation));
568-
self.fields.set("texScale", FieldValue::Number(brush.tex_scale));
569-
self.fields.set("texRotation", FieldValue::Number(brush.tex_rotation));
570-
self.fields.set("texOffsetX", FieldValue::Number(brush.tex_offset_x));
571-
self.fields.set("texOffsetY", FieldValue::Number(brush.tex_offset_y));
573+
self.fields
574+
.set("rotation", FieldValue::Number(brush.rotation));
575+
self.fields
576+
.set("texScale", FieldValue::Number(brush.tex_scale));
577+
self.fields
578+
.set("texRotation", FieldValue::Number(brush.tex_rotation));
579+
self.fields
580+
.set("texOffsetX", FieldValue::Number(brush.tex_offset_x));
581+
self.fields
582+
.set("texOffsetY", FieldValue::Number(brush.tex_offset_y));
572583
self.fields.set("mode", FieldValue::Text(brush.mode));
573-
self.fields.set("kernelMode", FieldValue::Text(brush.kernel_mode));
574-
self.fields.set("strength", FieldValue::Number(brush.strength));
575-
self.fields.set("falloffFactor", FieldValue::Number(brush.falloff_factor));
576-
self.fields.set("featureFactor", FieldValue::Number(brush.feature_factor));
584+
self.fields
585+
.set("kernelMode", FieldValue::Text(brush.kernel_mode));
586+
self.fields
587+
.set("strength", FieldValue::Number(brush.strength));
588+
self.fields
589+
.set("falloffFactor", FieldValue::Number(brush.falloff_factor));
590+
self.fields
591+
.set("featureFactor", FieldValue::Number(brush.feature_factor));
577592
self.fields.set("value", FieldValue::Number(brush.value));
578-
self.fields.set("voidFactor", FieldValue::Number(brush.void_factor));
579-
self.fields.set("splatTexScale", FieldValue::Number(brush.splat_tex_scale));
580-
self.fields.set("splatTexMult", FieldValue::Number(brush.splat_tex_mult));
581-
self.fields.set("exclusive", FieldValue::Bool(brush.exclusive));
582-
self.fields.set("diffuseColor", FieldValue::Color(brush.diffuse_color));
583-
self.fields.set("dntsIndex", FieldValue::Number((brush.color_index - 1) as f32));
593+
self.fields
594+
.set("voidFactor", FieldValue::Number(brush.void_factor));
595+
self.fields
596+
.set("splatTexScale", FieldValue::Number(brush.splat_tex_scale));
597+
self.fields
598+
.set("splatTexMult", FieldValue::Number(brush.splat_tex_mult));
599+
self.fields
600+
.set("exclusive", FieldValue::Bool(brush.exclusive));
601+
self.fields
602+
.set("diffuseColor", FieldValue::Color(brush.diffuse_color));
603+
self.fields.set(
604+
"dntsIndex",
605+
FieldValue::Number((brush.color_index - 1) as f32),
606+
);
584607
for channel in toggle_channels() {
585608
self.fields.set(
586609
&enabled_name(channel),
@@ -606,12 +629,20 @@ impl Editor for TextureEditor {
606629
let channel_toggles: Vec<String> = toggle_channels().map(enabled_name).collect();
607630
self.fields.generate_rml(&[
608631
Layout::Raw(self.actions.generate_rml()),
609-
Layout::Raw(section_markup("texture-saved-brush-section", "Saved brushes")),
632+
Layout::Raw(section_markup(
633+
"texture-saved-brush-section",
634+
"Saved brushes",
635+
)),
610636
Layout::Raw(self.saved_brush_grid.container_rml()),
611637
Layout::Raw(section_markup("texture-pattern-section", "Pattern")),
612638
Layout::Raw(self.pattern_grid.container_rml()),
613639
Layout::IdentifiedGroup(&["size", "rotation", "texScale"]),
614-
Layout::IdentifiedGroup(&channel_toggles.iter().map(String::as_str).collect::<Vec<_>>()),
640+
Layout::IdentifiedGroup(
641+
&channel_toggles
642+
.iter()
643+
.map(String::as_str)
644+
.collect::<Vec<_>>(),
645+
),
615646
Layout::IdentifiedGroup(&["texRotation", "texOffsetX", "texOffsetY"]),
616647
Layout::IdentifiedField("diffuseColor"),
617648
Layout::IdentifiedField("mode"),
@@ -661,9 +692,11 @@ impl Editor for TextureEditor {
661692
}
662693
if let Some(cancel) = element_by_id(interface, document, "texture-material-cancel") {
663694
let events = self.material_picker_events.clone();
664-
interface.rml_ui().element_add_event_listener(cancel, "click", false, move || {
665-
events.borrow_mut().push(MaterialPickerEvent::Cancel);
666-
})?;
695+
interface
696+
.rml_ui()
697+
.element_add_event_listener(cancel, "click", false, move || {
698+
events.borrow_mut().push(MaterialPickerEvent::Cancel);
699+
})?;
667700
}
668701
self.render_grids(interface, document)?;
669702
self.apply_visibility(interface);
@@ -699,10 +732,7 @@ impl Editor for TextureEditor {
699732
if self.paint_mode() != "paint" && self.material_picker_open {
700733
self.material_picker_open = false;
701734
}
702-
if self
703-
.take_grid_clicks(interface, document)
704-
.unwrap_or(false)
705-
{
735+
if self.take_grid_clicks(interface, document).unwrap_or(false) {
706736
let _ = self.fields.write_values(interface);
707737
let _ = self.render_grids(interface, document);
708738
self.apply_visibility(interface);

0 commit comments

Comments
 (0)