Skip to content

Commit

Permalink
Add stack text threshold & split duration text threshold
Browse files Browse the repository at this point in the history
  • Loading branch information
Zerthox committed Dec 30, 2024
1 parent 62efc08 commit 041823d
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 59 deletions.
2 changes: 1 addition & 1 deletion reffect/src/elements/animation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl RenderOptions for Animation {
enum_combo(ui, "Animation", &mut self.kind, ComboBoxFlags::empty());

let mut period = self.period.get();
if input_seconds("Period", &mut period) {
if input_seconds(ui, "Period", &mut period) {
self.period = NonZero::new(period).unwrap_or(non_zero_u32!(1));
}
helper(ui, || ui.text("Animation loop duration in seconds"));
Expand Down
56 changes: 28 additions & 28 deletions reffect/src/elements/icon/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use crate::{
};
use nexus::imgui::Ui;
use serde::{Deserialize, Serialize};
use std::cmp::Ordering;

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
Expand Down Expand Up @@ -134,43 +133,49 @@ impl Icon {
// render stack count
if self.stacks_text {
let StackTextSettings {
threshold,
scale,
offset,
color: color @ [_, _, _, alpha],
decoration,
} = ctx.settings.icon.stack_text;

let stacks = active.intensity();
let text = if stacks > 99 {
"!"
} else {
&stacks.to_string()
};

let font_size = scale * small_size;
let font_scale = font_size / ui.current_font_size();
let [x_offset, _] = AlignHorizontal::Right.text_offset(ui, text, font_scale);
let line_height = font_scale * ui.text_line_height();
let text_pos = end.add([x_offset, -line_height]).sub(offset);

let decoration_color = with_alpha(colors::BLACK, alpha);
decoration.render(ui, text, text_pos, font_scale, decoration_color);
draw_text_bg(ui, text, text_pos, font_scale, color);
if stacks >= threshold {
let text = if stacks > 99 {
"!"
} else {
&stacks.to_string()
};

let font_size = scale * small_size;
let font_scale = font_size / ui.current_font_size();
let [x_offset, _] = AlignHorizontal::Right.text_offset(ui, text, font_scale);
let line_height = font_scale * ui.text_line_height();
let text_pos = end.add([x_offset, -line_height]).sub(offset);

let decoration_color = with_alpha(colors::BLACK, alpha);
decoration.render(ui, text, text_pos, font_scale, decoration_color);
draw_text_bg(ui, text, text_pos, font_scale, color);
}
}

// render duration text
if self.duration_text {
if let Some(remain) = active.current(ProgressValue::Primary, ctx.now) {
let settings = &ctx.settings.icon.duration_text;
let DurationTextSettings {
max_remain,
threshold_buff: _,
threshold_ability: _,
scale,
color,
color_fast,
color_slow,
color: _,
color_fast: _,
color_slow: _,
decoration,
} = ctx.settings.icon.duration_text;
} = *settings;

if remain < max_remain {
let threshold = settings.threshold(active);
if remain < threshold {
let text = active.current_text(
ProgressValue::Primary,
ctx.now,
Expand All @@ -183,12 +188,7 @@ impl Icon {
let offset = AlignHorizontal::Center.text_offset(ui, &text, font_scale);
let text_pos = state.pos.add(offset);

let color @ [_, _, _, alpha] = match active.progress_rate().total_cmp(&1.0)
{
Ordering::Less => color_slow,
Ordering::Equal => color,
Ordering::Greater => color_fast,
};
let color @ [_, _, _, alpha] = settings.color(active.progress_rate());
let decoration_color = with_alpha(colors::BLACK, alpha);
decoration.render(ui, &text, text_pos, font_scale, decoration_color);
draw_text_bg(ui, &text, text_pos, font_scale, color);
Expand Down
45 changes: 30 additions & 15 deletions reffect/src/render_util/input.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::input_text_simple_menu;
use super::{input_text_simple_menu, item_context_menu};
use crate::chat_code::{decode_skill, decode_trait};
use nexus::imgui::{sys, InputTextFlags, Ui};
use nexus::imgui::{sys, InputTextFlags, MenuItem, Ui};
use std::ffi::CString;

pub fn input_u32(
Expand All @@ -26,14 +26,14 @@ pub fn input_u32(
}

pub fn input_float_with_format(
label: impl Into<String>,
label: impl AsRef<str>,
value: &mut f32,
step: f32,
step_fast: f32,
format: impl Into<String>,
format: impl AsRef<str>,
flags: InputTextFlags,
) -> bool {
if let (Ok(label), Ok(format)) = (CString::new(label.into()), CString::new(format.into())) {
if let (Ok(label), Ok(format)) = (CString::new(label.as_ref()), CString::new(format.as_ref())) {
unsafe {
sys::igInputFloat(
label.as_ptr(),
Expand All @@ -50,11 +50,11 @@ pub fn input_float_with_format(
}

pub fn input_positive_with_format(
label: impl Into<String>,
label: impl AsRef<str>,
value: &mut f32,
step: f32,
step_fast: f32,
format: impl Into<String>,
format: impl AsRef<str>,
flags: InputTextFlags,
) -> bool {
if input_float_with_format(label, value, step, step_fast, format, flags) {
Expand All @@ -75,7 +75,7 @@ pub fn input_size([x, y]: &mut [f32; 2]) {
input_positive_with_format("Size y", y, 1.0, 10.0, "%.2f", InputTextFlags::empty());
}

pub fn input_percent(label: impl Into<String>, value: &mut f32) -> bool {
pub fn input_percent(label: impl AsRef<str>, value: &mut f32) -> bool {
let mut percent = *value * 100.0;
if input_positive_with_format(
label,
Expand All @@ -92,7 +92,7 @@ pub fn input_percent(label: impl Into<String>, value: &mut f32) -> bool {
}
}

pub fn input_percent_inverse(label: impl Into<String>, value: &mut f32) -> bool {
pub fn input_percent_inverse(label: impl AsRef<str>, value: &mut f32) -> bool {
let mut inverse = if *value == 0.0 { 0.0 } else { 1.0 / *value };
if input_percent(label, &mut inverse) {
*value = if inverse == 0.0 { 0.0 } else { 1.0 / inverse };
Expand All @@ -102,14 +102,29 @@ pub fn input_percent_inverse(label: impl Into<String>, value: &mut f32) -> bool
}
}

pub fn input_seconds(label: impl Into<String>, ms: &mut u32) -> bool {
let mut secs = *ms as f32 / 1000.0;
if input_positive_with_format(label, &mut secs, 0.5, 1.0, "%.3f", InputTextFlags::empty()) {
*ms = (secs * 1000.0) as u32;
true
pub fn input_seconds(ui: &Ui, label: impl AsRef<str>, ms: &mut u32) -> bool {
let label = label.as_ref();
let mut secs = if *ms != u32::MAX {
*ms as f32 / 1000.0
} else {
false
f32::INFINITY
};
let changed =
input_positive_with_format(label, &mut secs, 0.5, 1.0, "%.3f", InputTextFlags::empty());
if changed {
*ms = if secs.is_finite() {
(secs * 1000.0) as u32
} else {
0
};
}
item_context_menu(format!("##ctx{label}"), || {
if MenuItem::new("Set to infinite").build(ui) {
*ms = u32::MAX;
}
});

changed
}

pub fn input_chatcode(
Expand Down
3 changes: 1 addition & 2 deletions reffect/src/render_util/popup.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use crate::render::colors;
use nexus::imgui::{sys, StyleColor, Ui};
use std::ffi::CString;

use crate::render::colors;

pub fn item_context_menu(str_id: impl Into<String>, contents: impl FnOnce()) {
if let Ok(str_id) = CString::new(str_id.into()) {
if unsafe {
Expand Down
4 changes: 2 additions & 2 deletions reffect/src/settings/general.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@ impl FormatSettings {
millis_threshold,
} = self;

input_seconds("Minute threshold", minutes_threshold);
input_seconds(ui, "Minute threshold", minutes_threshold);
helper(ui, || {
ui.text("Above how many seconds to display MM:SS format");
});

input_seconds("Millisecond threshold", millis_threshold);
input_seconds(ui, "Millisecond threshold", millis_threshold);
helper(ui, || {
ui.text("Below how many seconds to display milliseconds");
ui.text("MM:SS format always hides milliseconds");
Expand Down
51 changes: 45 additions & 6 deletions reffect/src/settings/icon.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use std::cmp::Ordering;

use crate::{
elements::text::TextDecoration,
render::colors::{self, with_alpha},
render_util::{
enum_combo, helper, input_color_alpha, input_float_with_format, input_percent, input_pos,
input_seconds,
input_seconds, input_u32,
},
trigger::ProgressActive,
};
use nexus::imgui::{ComboBoxFlags, InputTextFlags, Ui};
use serde::{Deserialize, Serialize};
Expand All @@ -20,6 +23,7 @@ pub struct IconSettings {
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct StackTextSettings {
pub threshold: u32,
pub scale: f32,
pub offset: [f32; 2],
pub color: [f32; 4],
Expand All @@ -29,6 +33,7 @@ pub struct StackTextSettings {
impl Default for StackTextSettings {
fn default() -> Self {
Self {
threshold: 2,
scale: 0.5,
offset: [1.0, 1.0],
color: with_alpha(colors::WHITE, 0.8),
Expand All @@ -40,11 +45,16 @@ impl Default for StackTextSettings {
impl StackTextSettings {
pub fn render_options(&mut self, ui: &Ui) {
let Self {
threshold,
scale,
offset,
color,
decoration,
} = self;

input_u32(ui, "Threshold", threshold, 1, 10);
helper(ui, || ui.text("Minimum stacks to display"));

input_percent("Scale", scale);
input_pos(offset);
enum_combo(ui, "Decoration", decoration, ComboBoxFlags::empty());
Expand All @@ -55,18 +65,41 @@ impl StackTextSettings {
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct DurationTextSettings {
pub max_remain: u32, // TODO: different for buff & ability
#[serde(alias = "max_remain")]
pub threshold_buff: u32,

pub threshold_ability: u32,

pub scale: f32,
pub color: [f32; 4],
pub color_fast: [f32; 4],
pub color_slow: [f32; 4],
pub decoration: TextDecoration,
}

impl DurationTextSettings {
pub fn threshold(&self, active: &ProgressActive) -> u32 {
match active {
ProgressActive::Fixed { .. } => u32::MAX,
ProgressActive::Buff { .. } => self.threshold_buff,
ProgressActive::Ability { .. } => self.threshold_ability,
}
}

pub fn color(&self, rate: f32) -> [f32; 4] {
match rate.total_cmp(&1.0) {
Ordering::Less => self.color_slow,
Ordering::Equal => self.color,
Ordering::Greater => self.color_fast,
}
}
}

impl Default for DurationTextSettings {
fn default() -> Self {
Self {
max_remain: 5000,
threshold_buff: 5000,
threshold_ability: u32::MAX,
scale: 0.5,
color: colors::WHITE,
color_fast: colors::GREEN,
Expand All @@ -79,17 +112,23 @@ impl Default for DurationTextSettings {
impl DurationTextSettings {
pub fn render_options(&mut self, ui: &Ui) {
let Self {
max_remain,
threshold_buff,
threshold_ability,
scale,
color,
color_fast,
color_slow,
decoration,
} = self;

input_seconds("Remaining", max_remain);
input_seconds(ui, "Threshold Effect", threshold_buff);
helper(ui, || {
ui.text("Below how many remaining seconds to display for effects")
});

input_seconds(ui, "Threshold Ability", threshold_ability);
helper(ui, || {
ui.text("Below how many remaining seconds to display text")
ui.text("Below how many remaining seconds to display for abilities")
});

input_percent("Scale", scale);
Expand Down
12 changes: 7 additions & 5 deletions reffect/src/trigger/progress/active.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use reffect_internal::{Skillbar, Slot};

use crate::{
fmt::{Time, Unit},
internal::{Ability, Buff, Resource},
settings::FormatSettings,
};
use reffect_internal::{Skillbar, Slot};

// TODO: buff intensity stacking, ability ammo?
#[derive(Debug, Clone)]
pub enum ProgressActive {
Fixed {
Expand Down Expand Up @@ -100,24 +100,26 @@ impl ProgressActive {

/// Creates a uff progress for edit mode.
pub const fn edit_buff(id: u32, progress: f32, now: u32) -> Self {
let decreasing = 1.0 - progress;
Self::Buff {
id,
stacks: (25.0 * progress) as u32,
duration: 5000,
end: now + (5000.0 * progress) as u32,
end: now + (5000.0 * decreasing) as u32,
}
}

/// Creates an ability progress for edit mode.
pub const fn edit_ability(skill: Skill, progress: f32, now: u32) -> Self {
let decreasing = 1.0 - progress;
Self::Ability {
skill,
ammo: (5.0 * progress) as u32,
recharge: 5000,
end: now + (5000.0 * progress) as u32,
end: now + (5000.0 * decreasing) as u32,
rate: 1.0,
ammo_recharge: 5000,
ammo_end: now + (5000.0 * progress) as u32,
ammo_end: now + (5000.0 * decreasing) as u32,
}
}

Expand Down

0 comments on commit 041823d

Please sign in to comment.