Skip to content

Commit d8a1a07

Browse files
committed
Fix native UI input and remove deprecated fuel
1 parent 0fcb28d commit d8a1a07

24 files changed

Lines changed: 187 additions & 146 deletions

File tree

‎libs_sb/s11n‎

Submodule s11n updated 1 file

‎native/src/sbc/chonsole/model.rs‎

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use super::ui::{ChonsoleController, UiKeyOutcome};
88
use crate::sbc::command_system::model::{Model, ModelFactory};
99
use crate::sbc::keys::KeyMods;
1010
use crate::sbc::port_flags::{self, PortImpl};
11+
use crate::sbc::states::trace::rml_y_from_callback;
1112

1213
inventory::submit! { ModelFactory { make: |iface| Box::new(ChonsoleManager::new(iface)) } }
1314

@@ -186,23 +187,23 @@ impl ChonsoleManager {
186187
return Ok(false);
187188
}
188189
let _ = (dx, dy, button);
189-
let y = self.rml_y(y);
190+
let y = rml_y_from_callback(&self.interface, y);
190191
self.ui.mouse_move(&self.interface, x, y)
191192
}
192193

193194
pub fn mouse_press(&mut self, x: i32, y: i32, button: i32) -> Result<bool, Error> {
194195
if !self.enabled {
195196
return Ok(false);
196197
}
197-
let y = self.rml_y(y);
198+
let y = rml_y_from_callback(&self.interface, y);
198199
self.ui.mouse_press(&self.interface, x, y, button)
199200
}
200201

201202
pub fn mouse_release(&mut self, x: i32, y: i32, button: i32) -> Result<(), Error> {
202203
if !self.enabled {
203204
return Ok(());
204205
}
205-
let y = self.rml_y(y);
206+
let y = rml_y_from_callback(&self.interface, y);
206207
self.ui.mouse_release(&self.interface, x, y, button)
207208
}
208209

@@ -213,15 +214,6 @@ impl ChonsoleManager {
213214
self.ui.mouse_wheel(&self.interface, up, value)
214215
}
215216

216-
/// Mouse callbacks report the engine's bottom-origin y; the view hit tests
217-
/// against RmlUi's top-origin layout.
218-
fn rml_y(&self, y: i32) -> i32 {
219-
match self.interface.display().get_view_geometry() {
220-
Ok(geometry) => geometry.viewSizeY - 1 - y,
221-
Err(_) => y,
222-
}
223-
}
224-
225217
fn persist_history_change(&self, previous_history: &[String]) {
226218
let Some(store) = &self.history_store else {
227219
return;

‎native/src/sbc/chonsole/ui/view.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ impl ChonsoleView {
4949
}
5050

5151
pub(super) fn update(&mut self, interface: &NativeInterfaceRef) -> Result<(), Error> {
52+
// Re-enable text input if a reload reset SDL's global state.
53+
if self.visible && self.rml.has_document() {
54+
let _ = interface.unsynced_ctrl().sdlstart_text_input();
55+
}
5256
self.rml.update(interface)?;
5357
if self.suggestion_events_dirty {
5458
self.rml.bind_suggestion_events(

‎native/src/sbc/chonsole/ui/view_rml.rs‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use spring_native::{
99
};
1010

1111
use crate::sbc::rml::{self, element_by_id};
12+
use crate::sbc::states::trace::rml_y_from_mouse;
1213

1314
use crate::sbc::chonsole::framework::{ChonsoleLine, ChonsoleLineKind, TextInput};
1415
const UI_CONTEXT: &str = "sbc_native_chonsole";
@@ -190,13 +191,16 @@ impl ChonsoleRml {
190191
};
191192
let rml = interface.rml_ui();
192193
if visible {
194+
// RmlUi text input requires SDL text input to be enabled.
195+
let _ = interface.unsynced_ctrl().sdlstart_text_input();
193196
rml.document_show(document, spring_native::RmlDocumentShowOptions::default())?;
194197
if let Some(context) = self.context {
195198
// Keep the engine/editor cursor stable over console controls.
196199
let _ = rml.context_enable_mouse_cursor(context, false);
197200
let _ = rml.context_pull_document_to_front(context, document);
198201
}
199202
} else {
203+
let _ = interface.unsynced_ctrl().sdlstop_text_input();
200204
rml.document_hide(document)?;
201205
self.mouse_captured = false;
202206
if let Some(context) = self.context {
@@ -429,7 +433,7 @@ impl ChonsoleRml {
429433
// shared panel input layer does.
430434
let mouse = interface.input().get_mouse_state()?;
431435
let x = mouse.x as i32;
432-
let y = mouse.y as i32;
436+
let y = rml_y_from_mouse(interface, mouse.y) as i32;
433437
self.mouse_position = Some((x, y));
434438
let rml = interface.rml_ui();
435439
if !rml.element_is_point_within_element(suggestions, x as f32, y as f32)? {

‎native/src/sbc/control/api/camera.rs‎

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33
use serde::Deserialize;
44
use serde_json::json;
55

6-
use spring_native::prelude::NativeInterfaceRef;
7-
86
use crate::sbc::sbc::SBC;
9-
use crate::sbc::states::trace::{flip_screen_y, trace_editor_ground, trace_ground};
7+
use crate::sbc::states::trace::{trace_editor_ground_from_control, trace_ground_from_control};
108

119
use super::super::{ControlError, Handled, Reply};
1210

@@ -189,8 +187,7 @@ pub(crate) fn zoom(sbc: &mut SBC, params: Zoom) -> Handled {
189187
"camera.zoom screen coordinates must be finite",
190188
));
191189
}
192-
trace_ground(interface, screen[0], engine_screen_y(interface, screen[1]))
193-
.map(|hit| [hit.x, hit.y, hit.z])
190+
trace_ground_from_control(interface, screen[0], screen[1]).map(|hit| [hit.x, hit.y, hit.z])
194191
} else {
195192
None
196193
};
@@ -220,9 +217,8 @@ pub(crate) fn zoom(sbc: &mut SBC, params: Zoom) -> Handled {
220217
// point beneath the cursor. Re-trace after scaling and apply the
221218
// horizontal ground delta in the controller, where the engine owns the
222219
// camera projection and terrain height.
223-
if let Some(current) =
224-
trace_ground(interface, screen[0], engine_screen_y(interface, screen[1]))
225-
.map(|hit| [hit.x, hit.y, hit.z])
220+
if let Some(current) = trace_ground_from_control(interface, screen[0], screen[1])
221+
.map(|hit| [hit.x, hit.y, hit.z])
226222
{
227223
let mut state = camera
228224
.get_camera_state(false)
@@ -247,20 +243,11 @@ pub(crate) fn trace(sbc: &mut SBC, params: Trace) -> Handled {
247243
));
248244
}
249245
let interface = sbc.interface();
250-
let trace = trace_editor_ground(interface, x, engine_screen_y(interface, y))
246+
let trace = trace_editor_ground_from_control(interface, x, y)
251247
.map_err(|err| ControlError::failed(format!("trace_screen_ray: {err:?}")))?;
252248
Ok(Reply::now(json!({
253249
"hit_type": trace.hit_type,
254250
"hit_id": trace.hit_id,
255251
"position": [trace.position.x, trace.position.y, trace.position.z],
256252
})))
257253
}
258-
259-
/// Control clients address the window the way a screenshot does: top-origin.
260-
/// The engine's screen space is bottom-origin, so convert on the way in.
261-
fn engine_screen_y(interface: &NativeInterfaceRef, y: f32) -> f32 {
262-
match interface.display().get_view_geometry() {
263-
Ok(geometry) => flip_screen_y(geometry.viewSizeY as f32, y),
264-
Err(_) => y,
265-
}
266-
}

‎native/src/sbc/devconsole/status.rs‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use spring_native::prelude::NativeInterfaceRef;
66

77
use crate::sbc::devconsole::metrics::SystemMetrics;
88
use crate::sbc::objects::SelectionManager;
9-
use crate::sbc::states::{cursor, trace_ground};
9+
use crate::sbc::states::trace::trace_ground_at_mouse;
1010

1111
pub(super) struct StatusPresenter {
1212
last_metrics_refresh: Option<Instant>,
@@ -87,8 +87,7 @@ impl StatusPresenter {
8787
}
8888

8989
fn status_position(interface: &NativeInterfaceRef, selection: &SelectionManager) -> String {
90-
let ground = cursor(interface)
91-
.and_then(|mouse| trace_ground(interface, mouse.x, mouse.y))
90+
let ground = trace_ground_at_mouse(interface)
9291
.map(|hit| format!("X: {:.0}, Y: {:.0}, Z: {:.0}", hit.x, hit.y, hit.z))
9392
.unwrap_or_else(|| "Off-screen".to_string());
9493
match selection.count() {

‎native/src/sbc/objects/model/unit_s11n/fields/runtime.rs‎

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::sbc::objects::model::field_descriptor::{
77
FieldRange, FieldValueType, ObjectFieldDescriptor,
88
};
99
use crate::sbc::objects::model::object_data::{
10-
Armored, HarvestStorage, RuleValue, UnitCommand, UnitFuel, UnitResources, UnitStates,
10+
Armored, HarvestStorage, RuleValue, UnitCommand, UnitResources, UnitStates,
1111
};
1212

1313
use super::super::commands::{read_commands, write_commands};
@@ -199,28 +199,6 @@ impl TypedField<UnitModel> for Neutral {
199199
}
200200
inventory::submit! { FieldEntry::of::<Neutral>() }
201201

202-
struct Fuel;
203-
impl TypedField<UnitModel> for Fuel {
204-
type Value = UnitFuel;
205-
const DESCRIPTOR: ObjectFieldDescriptor = ObjectFieldDescriptor {
206-
name: "fuel",
207-
value_type: FieldValueType::Object("UnitFuel"),
208-
range: Some(FieldRange::at_least(0.0)),
209-
description: "Current and maximum fuel.",
210-
};
211-
fn get(s: &UnitModel, id: i32) -> Option<UnitFuel> {
212-
let fuel = s.interface.units_info().get_unit_fuel(id).ok()?;
213-
Some(UnitFuel {
214-
fuel: fuel.fuel,
215-
max_fuel: fuel.maxFuel,
216-
})
217-
}
218-
fn set(s: &mut UnitModel, _id: i32, _fuel: &UnitFuel) {
219-
let _ = s.interface.synced_ctrl().unit().set_unit_fuel();
220-
}
221-
}
222-
inventory::submit! { FieldEntry::of::<Fuel>() }
223-
224202
struct MoveCtrl;
225203
impl TypedField<UnitModel> for MoveCtrl {
226204
type Value = bool;

‎native/src/sbc/objects/states/add_object.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::sbc::objects::{AddObjectCommand, ObjectKind, ObjectManager, RemoveObj
1111
use crate::sbc::render::ModelShader;
1212
use crate::sbc::states::state::{EditorState, StateContext, Transition};
1313
use crate::sbc::states::trace::{
14-
cursor, trace_ground_at_mouse, trace_ground_with_water, GroundHit,
14+
cursor, trace_ground_at_mouse, trace_ground_with_water_from_callback, GroundHit,
1515
};
1616

1717
mod brush;
@@ -299,7 +299,7 @@ impl EditorState for AddObjectState {
299299
if button != LEFT && !(button == RIGHT && self.config.brush) {
300300
return false;
301301
}
302-
let Some(hit) = trace_ground_with_water(ctx.interface, x as f32, y as f32) else {
302+
let Some(hit) = trace_ground_with_water_from_callback(ctx.interface, x, y) else {
303303
return true;
304304
};
305305
if button == RIGHT {

‎native/src/sbc/panels/controls/color_picker.rs‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,10 @@ impl ColorPicker {
174174
};
175175

176176
// Engine mouse coordinates are bottom-origin; RmlUi rects are not.
177-
let Ok(geom) = interface.display().get_view_geometry() else {
178-
return false;
179-
};
180-
let (mx, my) = (mouse.x, geom.viewSizeY as f32 - mouse.y);
177+
let (mx, my) = (
178+
mouse.x,
179+
crate::sbc::states::trace::rml_y_from_mouse(interface, mouse.y),
180+
);
181181

182182
let id = match self.grab {
183183
Grab::Sv => "color-map",

‎native/src/sbc/panels/cursor/cursortip.rs‎

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use spring_native::{
1111
RmlDataTextRows, RmlDataVariable, RmlPixels, RmlTextRow,
1212
};
1313

14-
use crate::sbc::states::trace::flip_screen_y;
14+
use crate::sbc::states::trace::rml_y_from_mouse;
1515

1616
/// Pick radius in pixels around the cursor, as Lua uses.
1717
const PICK_RADIUS: f32 = 16.0;
@@ -48,9 +48,6 @@ impl CursorTip {
4848
let Ok(mouse) = interface.input().get_mouse_state() else {
4949
return Ok(());
5050
};
51-
let Ok(geometry) = interface.display().get_view_geometry() else {
52-
return Ok(());
53-
};
5451
// Nothing while a button is down (a drag is in progress) or over the UI.
5552
let hit = if mouse.left || mouse.right || over_panel {
5653
None
@@ -82,7 +79,7 @@ impl CursorTip {
8279
}
8380
bindings.left.set(RmlPixels(mouse.x + OFFSET_X as f32))?;
8481
bindings.top.set(RmlPixels(
85-
flip_screen_y(geometry.viewSizeY as f32, mouse.y) + OFFSET_Y as f32,
82+
rml_y_from_mouse(interface, mouse.y) + OFFSET_Y as f32,
8683
))?;
8784
bindings.hidden.set(false)?;
8885
Ok(())
@@ -219,7 +216,7 @@ fn describe_feature(interface: &NativeInterfaceRef, feature_id: i32) -> Option<H
219216
#[cfg(test)]
220217
mod tests {
221218
use super::pick_rectangle;
222-
use crate::sbc::states::trace::flip_screen_y;
219+
use crate::sbc::states::trace::top_to_engine_y;
223220

224221
#[test]
225222
fn object_pick_keeps_the_mouse_bottom_origin_y() {
@@ -228,7 +225,7 @@ mod tests {
228225

229226
#[test]
230227
fn only_rml_positioning_flips_bottom_origin_mouse_y() {
231-
assert_eq!(flip_screen_y(1_000.0, 100.0), 899.0);
232-
assert_eq!(flip_screen_y(1_000.0, 899.0), 100.0);
228+
assert_eq!(top_to_engine_y(1_000.0, 100.0), 899.0);
229+
assert_eq!(top_to_engine_y(1_000.0, 899.0), 100.0);
233230
}
234231
}

0 commit comments

Comments
 (0)