Skip to content

Commit c85ed64

Browse files
committed
Adjust debug & add validation for some inputs
1 parent 8c61d25 commit c85ed64

File tree

7 files changed

+159
-60
lines changed

7 files changed

+159
-60
lines changed

reffect/src/addon/ui/debug.rs

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use crate::{
66
render::colors::{Colored, GREEN, RED},
77
};
88
use nexus::imgui::{StyleColor, Ui, Window};
9+
use reffect_internal::{Slot, State};
910
use std::fmt;
11+
use strum::IntoEnumIterator;
1012

1113
impl Addon {
1214
pub fn render_debug(&mut self, ui: &Ui) {
@@ -41,9 +43,17 @@ impl Addon {
4143
}
4244
});
4345

46+
let State {
47+
own_resources,
48+
own_skillbar,
49+
own_buffs,
50+
target_buffs,
51+
group_buffs,
52+
} = &ctx.state;
53+
4454
ui.text("Own resources:");
4555
ui.same_line();
46-
debug_result(ui, ctx.state.own_resources.as_ref(), |resources| {
56+
debug_result(ui, own_resources.as_ref(), |resources| {
4757
let Resources {
4858
health,
4959
barrier,
@@ -64,26 +74,58 @@ impl Addon {
6474
));
6575
});
6676

77+
ui.text("Own skillbar:");
78+
ui.same_line();
79+
debug_result(ui, own_skillbar.as_ref(), |skillbar| {
80+
let passed = skillbar.passed(ctx.now);
81+
82+
for slot in Slot::iter() {
83+
if let Some(ability) = skillbar.slot(slot) {
84+
ui.text(format!("{}x {:>5}", ability.ammo, ability.id));
85+
86+
let recharge = ability.recharge_remaining(passed);
87+
if recharge > 0 {
88+
ui.same_line();
89+
ui.text(format!(
90+
"{:.1}/{:.1}s {:.1}%",
91+
to_secs(recharge),
92+
to_secs(ability.recharge),
93+
100.0 * ability.recharge_progress(passed)
94+
));
95+
}
96+
97+
let ammo_recharge = ability.ammo_recharge_remaining(passed);
98+
if ammo_recharge > 0 {
99+
ui.same_line();
100+
ui.text(format!(
101+
"Ammo {:.1}/{:.1}s {:.1}%",
102+
to_secs(ammo_recharge),
103+
to_secs(ability.ammo_recharge),
104+
100.0 * ability.ammo_recharge_progress(passed)
105+
));
106+
}
107+
}
108+
}
109+
});
110+
67111
ui.text("Own buffs:");
68112
ui.same_line();
69-
debug_result(ui, ctx.state.own_buffs.as_ref(), |buffs| {
113+
debug_result(ui, own_buffs.as_ref(), |buffs| {
70114
buffs_tooltip(ui, ctx, infos, buffs)
71115
});
72116

73117
ui.text("Target buffs:");
74118
ui.same_line();
75-
debug_result(ui, ctx.state.target_buffs.as_ref(), |buffs| {
119+
debug_result(ui, target_buffs.as_ref(), |buffs| {
76120
buffs_tooltip(ui, ctx, infos, buffs)
77121
});
78122

79123
for i in 0..4 {
80124
ui.text(format!("Group Member {} buffs:", i + 1));
81125
ui.same_line();
82-
debug_result(
83-
ui,
84-
ctx.state.group_buffs.as_ref().map(|group| &group[i]),
85-
|buffs| buffs_tooltip(ui, ctx, infos, buffs),
86-
);
126+
debug_result(ui, group_buffs.as_ref().map(|group| &group[i]), |buffs| {
127+
buffs_tooltip(ui, ctx, infos, buffs)
128+
});
87129
}
88130

89131
ui.text(format!("Combat: {}", ctx.ui.combat));
@@ -138,25 +180,27 @@ fn debug_result<T>(ui: &Ui, result: Result<&T, &Error>, tooltip: impl FnOnce(&T)
138180

139181
fn buffs_tooltip(ui: &Ui, ctx: &Context, infos: Option<&BuffInfoMap>, buffs: &BuffMap) {
140182
for (id, buff) in buffs {
141-
ui.text(format!("{}x {id}", buff.stacks));
183+
ui.text(format!("{:>2}x {id:>5}", buff.stacks));
142184
if let Some(info) = infos.and_then(|infos| infos.get(id)) {
143185
ui.same_line();
144186
ui.text(format!("{:?} {:?}", info.category, info.stacking));
145187
}
146-
if let Some(remain) = ctx.time_until(buff.runout_time) {
147-
let full = buff.runout_time - buff.apply_time;
148-
let progress = remain as f32 / full as f32;
188+
if !buff.is_infinite() {
149189
ui.same_line();
150190
ui.text(format!(
151191
"{:.1}/{:.1}s {:.1}%",
152-
remain as f32 / 1000.0,
153-
full as f32 / 1000.0,
154-
progress * 100.0,
192+
to_secs(buff.remaining(ctx.now)),
193+
to_secs(buff.duration()),
194+
100.0 * buff.progress(ctx.now),
155195
));
156196
}
157197
}
158198
}
159199

200+
fn to_secs(millisecs: u32) -> f32 {
201+
millisecs as f32 / 1000.0
202+
}
203+
160204
fn name_or_unknown_id_colored<T, N>(ui: &Ui, value: Result<T, N>)
161205
where
162206
T: AsRef<str> + Colored,

reffect/src/addon/ui/editor.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ impl Addon {
9797

9898
let State {
9999
own_resources,
100+
own_skillbar,
100101
own_buffs,
101102
target_buffs,
102103
group_buffs,
@@ -106,9 +107,10 @@ impl Addon {
106107
ui,
107108
[
108109
("Resources", own_resources.as_ref().err()),
110+
("Skills", own_skillbar.as_ref().err()),
109111
("Own Buffs", own_buffs.as_ref().err()),
110-
("Target Buffs", target_buffs.as_ref().err()),
111-
("Group Buffs", group_buffs.as_ref().err()),
112+
// ("Target Buffs", target_buffs.as_ref().err()),
113+
// ("Group Buffs", group_buffs.as_ref().err()),
112114
("Player", player.as_ref().err()),
113115
],
114116
);

reffect/src/addon/ui/options.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,10 @@ impl Addon {
9595
}
9696

9797
ui.spacing();
98-
if ui.collapsing_header("Advanced", TreeNodeFlags::SPAN_AVAIL_WIDTH) {
98+
if ui.collapsing_header(
99+
"Advanced",
100+
TreeNodeFlags::SPAN_AVAIL_WIDTH | TreeNodeFlags::DEFAULT_OPEN,
101+
) {
99102
if input_u32(
100103
ui,
101104
"Own character interval",

reffect/src/context/mod.rs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -125,24 +125,6 @@ impl Context {
125125
pub fn own_resources(&self) -> Option<&Resources> {
126126
self.state.own_resources.as_ref().ok()
127127
}
128-
129-
/// Returns the duration passed since a given timestamp.
130-
pub fn time_since(&self, time: u32) -> Option<u32> {
131-
(time != u32::MAX).then(|| self.now.saturating_sub(time))
132-
}
133-
134-
/// Returns the remaining duration until a given timestamp.
135-
pub fn time_until(&self, time: u32) -> Option<u32> {
136-
(time != u32::MAX).then(|| time.saturating_sub(self.now))
137-
}
138-
139-
/// Returns the remaining progress between two timestamps.
140-
pub fn progress_remaining(&self, start: u32, end: u32) -> Option<f32> {
141-
self.time_until(end).map(|remain| {
142-
let full = end - start;
143-
remain as f32 / full as f32
144-
})
145-
}
146128
}
147129

148130
impl Default for Context {

reffect/src/elements/text/mod.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use crate::{
99
fmt::Pretty,
1010
render::{Bounds, ComponentWise, Render, RenderDebug, RenderOptions},
1111
render_util::{
12-
debug_optional, draw_text_bg, font_select, helper, helper_error,
13-
input_text_multi_with_menu, Font, FontToken, Rect,
12+
debug_optional, draw_text_bg, font_select, helper, input_text_multi_with_menu, Font,
13+
FontToken, Rect, Validation,
1414
},
1515
tree::TreeNode,
1616
trigger::ProgressActive,
@@ -182,16 +182,20 @@ impl RenderOptions for Text {
182182

183183
self.align.render_combo(ui);
184184

185-
if font_select(ui, "Font", &mut self.loaded_font) {
186-
self.font_name = self.loaded_font.map(|font| font.name_owned());
187-
}
188-
if self.font_name.is_some() && self.loaded_font.is_none() {
185+
let validation = if self.font_name.is_some() {
189186
match self.loaded_font {
190-
Some(font) if !font.is_valid() => helper_error(ui, || ui.text("Font invalidated")),
191-
Some(_) => {}
192-
None => helper_error(ui, || ui.text("Failed to find font")),
187+
Some(font) if !font.is_valid() => Validation::Error("Font invalidated"),
188+
Some(_) => Validation::Ok,
189+
None => Validation::Error("Failed to find fond"),
193190
}
194-
}
191+
} else {
192+
Validation::Ok
193+
};
194+
validation.for_item(ui, || {
195+
if font_select(ui, "Font", &mut self.loaded_font) {
196+
self.font_name = self.loaded_font.map(|font| font.name_owned());
197+
}
198+
});
195199

196200
self.props.base.render_options(ui, state);
197201
}

reffect/src/render_util/helper.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::render::colors;
2-
use nexus::imgui::Ui;
2+
use nexus::imgui::{ColorStackToken, StyleColor, Ui};
33

44
pub fn helper(ui: &Ui, contents: impl FnOnce()) {
55
ui.same_line();
@@ -17,6 +17,7 @@ pub fn helper_warn(ui: &Ui, tooltip: impl FnOnce()) {
1717
}
1818
}
1919

20+
#[allow(unused)]
2021
pub fn helper_error(ui: &Ui, tooltip: impl FnOnce()) {
2122
ui.same_line();
2223
ui.text_colored(colors::RED, "(!)");
@@ -28,3 +29,54 @@ pub fn helper_error(ui: &Ui, tooltip: impl FnOnce()) {
2829
pub fn helper_slider(ui: &Ui) {
2930
helper(ui, || ui.text("Ctrl+click to type a number"))
3031
}
32+
33+
#[derive(Debug, Clone)]
34+
#[must_use]
35+
pub enum Validation<T> {
36+
Ok,
37+
Confirm(T),
38+
Warn(T),
39+
Error(T),
40+
}
41+
42+
impl<T> Validation<T> {
43+
pub fn push_color<'ui>(&self, ui: &'ui Ui) -> ColorStackToken<'ui> {
44+
const STYLE_COLOR: StyleColor = StyleColor::FrameBg;
45+
const INTENSITY: f32 = 0.3;
46+
47+
let color = ui.style_color(STYLE_COLOR);
48+
match self {
49+
Self::Ok | Self::Confirm(_) => ui.push_style_color(STYLE_COLOR, color),
50+
Self::Warn(_) => {
51+
ui.push_style_color(STYLE_COLOR, colors::lerp(color, colors::YELLOW, INTENSITY))
52+
}
53+
Self::Error(_) => {
54+
ui.push_style_color(STYLE_COLOR, colors::lerp(color, colors::RED, INTENSITY))
55+
}
56+
}
57+
}
58+
59+
pub fn render_tooltip(&self, ui: &Ui)
60+
where
61+
T: AsRef<str>,
62+
{
63+
if ui.is_item_hovered() {
64+
match self {
65+
Self::Ok => {}
66+
Validation::Confirm(text) => ui.tooltip(|| ui.text_colored(colors::GREEN, text)),
67+
Validation::Warn(text) => ui.tooltip(|| ui.text_colored(colors::YELLOW, text)),
68+
Validation::Error(text) => ui.tooltip(|| ui.text_colored(colors::RED, text)),
69+
}
70+
}
71+
}
72+
73+
pub fn for_item<R>(&self, ui: &Ui, item: impl FnOnce() -> R) -> R
74+
where
75+
T: AsRef<str>,
76+
{
77+
let _color = self.push_color(ui);
78+
let result = item();
79+
self.render_tooltip(ui);
80+
result
81+
}
82+
}

reffect/src/trigger/progress/source.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ use super::ProgressActive;
22
use crate::{
33
action::Action,
44
context::{Context, EditState},
5-
internal::Resource,
6-
internal::{Interface, Internal},
5+
internal::{Interface, Internal, Resource},
76
render::RenderOptions,
8-
render_util::{enum_combo, helper, helper_error, impl_static_variants, input_skill_id},
7+
render_util::{enum_combo, helper, impl_static_variants, input_skill_id, Validation},
98
};
109
use nexus::imgui::{ComboBoxFlags, InputTextFlags, Ui};
10+
use reffect_internal::Category;
1111
use serde::{Deserialize, Serialize};
1212
use strum::{AsRefStr, EnumIter, IntoStaticStr};
1313

@@ -134,15 +134,23 @@ impl ProgressSource {
134134
}
135135
}
136136

137-
fn buff_helper(ui: &Ui, id: u32) {
137+
fn buff_validate(id: u32) -> Validation<impl AsRef<str>> {
138138
if let Ok(infos) = Internal::get_buff_infos() {
139-
if infos.get(&id).is_none() {
140-
helper_error(ui, || {
141-
ui.text(format!("Buff {id} is invalid or hidden"));
142-
});
143-
return;
139+
if let Some(info) = infos.get(&id) {
140+
if info.category == Category::ScreenBorder {
141+
Validation::Warn(format!("{} {id} is only valid for yourself", info.category))
142+
} else {
143+
Validation::Confirm(format!("{} {id} is valid", info.category))
144+
}
145+
} else {
146+
Validation::Error(format!("Effect {id} is invalid or hidden"))
144147
}
148+
} else {
149+
Validation::Ok
145150
}
151+
}
152+
153+
fn buff_helper(ui: &Ui) {
146154
helper(ui, || {
147155
ui.text("Can be found on the wiki");
148156
ui.text("Supports pasting chat links");
@@ -167,21 +175,25 @@ impl RenderOptions for ProgressSource {
167175

168176
match self {
169177
Self::Buff(id) => {
170-
input_skill_id(ui, "Effect Id", id, InputTextFlags::empty());
171-
Self::buff_helper(ui, *id);
178+
Self::buff_validate(*id).for_item(ui, || {
179+
input_skill_id(ui, "Effect Id", id, InputTextFlags::empty());
180+
});
181+
Self::buff_helper(ui);
172182
}
173183
Self::AnyBuff(ids) => {
174184
let mut action = Action::new();
175185
for (i, id) in ids.iter_mut().enumerate() {
176186
let _id = ui.push_id(i as i32);
177187

178188
action.input_with_buttons(ui, i, || {
179-
input_skill_id(ui, "##id", id, InputTextFlags::empty())
189+
Self::buff_validate(*id).for_item(ui, || {
190+
input_skill_id(ui, "##id", id, InputTextFlags::empty());
191+
});
180192
});
181193

182194
ui.same_line();
183195
ui.text(format!("Effect Id {}", i + 1));
184-
Self::buff_helper(ui, *id);
196+
Self::buff_helper(ui);
185197
}
186198
if ui.button("Add Effect") {
187199
ids.push(0);

0 commit comments

Comments
 (0)