Refine sample delivery force UI and mapping
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
### 后端数据
|
### 后端数据
|
||||||
|
|
||||||
|
|
||||||
- 合力低于显示阈值时,后端不再清空 summary 数组,而是持续写入 `0.0`。
|
- 合力低于显示阈值时,后端不再清空 summary 数组,而是持续写入 `0.0`。
|
||||||
- 压力矩阵在低于显示阈值时仍然清零。
|
- 压力矩阵在低于显示阈值时仍然清零。
|
||||||
- 前端可以通过 summary 数组是否存在和最新值大小来判断释放状态。
|
- 前端可以通过 summary 数组是否存在和最新值大小来判断释放状态。
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ pub async fn serial_connect(
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
eprintln!("serial task exited with error: {error}");
|
log::error!("serial task exited with error: {error}");
|
||||||
}
|
}
|
||||||
|
|
||||||
let manager = task_app.state::<SerialConnectionState>();
|
let manager = task_app.state::<SerialConnectionState>();
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ impl Codec<TestFrame> for TestCodec {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let dts = elapsed_millis(session_started_at);
|
let dts = elapsed_millis(session_started_at);
|
||||||
println!("dts_ms: {dts}");
|
|
||||||
frames.push(TestFrame {
|
frames.push(TestFrame {
|
||||||
header: [0xAA, 0x55],
|
header: [0xAA, 0x55],
|
||||||
cmd: cmd,
|
cmd: cmd,
|
||||||
@@ -244,11 +243,10 @@ mod tests {
|
|||||||
fn test_read_csv_basic() -> anyhow::Result<()> {
|
fn test_read_csv_basic() -> anyhow::Result<()> {
|
||||||
let mut rdr = Reader::from_path("recording_20260329_125238.csv")?;
|
let mut rdr = Reader::from_path("recording_20260329_125238.csv")?;
|
||||||
let headers = rdr.headers()?;
|
let headers = rdr.headers()?;
|
||||||
println!("headers: {:?}", headers);
|
|
||||||
|
|
||||||
for result in rdr.records() {
|
for result in rdr.records() {
|
||||||
let record = result?;
|
let record = result?;
|
||||||
println!("record: {:?}", record);
|
let _ = record;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const POST_STABLE_MS: f32 = 200.0;
|
|||||||
const POST_STABLE_THRESH: f32 = 0.1;
|
const POST_STABLE_THRESH: f32 = 0.1;
|
||||||
const COP_LPF_ALPHA: f32 = 0.25;
|
const COP_LPF_ALPHA: f32 = 0.25;
|
||||||
const EPSILON: f32 = 1e-8;
|
const EPSILON: f32 = 1e-8;
|
||||||
|
const DISPLAY_ANGLE_OFFSET_DEG: f32 = -90.0;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct PztSpatialAnalysis {
|
pub struct PztSpatialAnalysis {
|
||||||
@@ -359,10 +360,7 @@ impl PztProcessor {
|
|||||||
|
|
||||||
fn compute_vector_angle(x: f32, y: f32) -> (f32, f32) {
|
fn compute_vector_angle(x: f32, y: f32) -> (f32, f32) {
|
||||||
let magnitude = (x * x + y * y).sqrt();
|
let magnitude = (x * x + y * y).sqrt();
|
||||||
let mut angle = y.atan2(x + EPSILON).to_degrees();
|
let angle = (y.atan2(x + EPSILON).to_degrees() + DISPLAY_ANGLE_OFFSET_DEG).rem_euclid(360.0);
|
||||||
if angle < 0.0 {
|
|
||||||
angle += 360.0;
|
|
||||||
}
|
|
||||||
(angle, magnitude)
|
(angle, magnitude)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -481,7 +479,7 @@ mod tests {
|
|||||||
assert!(analysis.contact_active);
|
assert!(analysis.contact_active);
|
||||||
assert!(analysis.reportable);
|
assert!(analysis.reportable);
|
||||||
assert!(analysis.magnitude > 0.0);
|
assert!(analysis.magnitude > 0.0);
|
||||||
assert!(analysis.angle_deg <= 45.0 || analysis.angle_deg >= 315.0);
|
assert!(analysis.angle_deg >= 225.0 && analysis.angle_deg <= 315.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -358,15 +358,9 @@ fn build_display_values(
|
|||||||
spatial_force: Option<HudSpatialForce>,
|
spatial_force: Option<HudSpatialForce>,
|
||||||
) -> Option<Vec<i32>> {
|
) -> Option<Vec<i32>> {
|
||||||
let summary = values.iter().copied().sum::<i32>();
|
let summary = values.iter().copied().sum::<i32>();
|
||||||
#[cfg(feature = "debug")]
|
|
||||||
{
|
|
||||||
let g1 = raw_to_g1(summary as u32);
|
|
||||||
println!("raw_to_g1 map: {g1}");
|
|
||||||
}
|
|
||||||
chart_state.record_spatial_force(spatial_force);
|
chart_state.record_spatial_force(spatial_force);
|
||||||
|
|
||||||
match ad_to_x(summary as f64) {
|
let x = raw_to_g1(summary as u32).min(MAX_DISPLAY_FORCE);
|
||||||
Some(x) => {
|
|
||||||
if x <= MIN_DISPLAY_FORCE {
|
if x <= MIN_DISPLAY_FORCE {
|
||||||
let zero_values = vec![0; values.len()];
|
let zero_values = vec![0; values.len()];
|
||||||
chart_state.record_summary(0.0);
|
chart_state.record_summary(0.0);
|
||||||
@@ -377,69 +371,10 @@ fn build_display_values(
|
|||||||
chart_state.record_pressure_matrix(values);
|
chart_state.record_pressure_matrix(values);
|
||||||
chart_state.record_summary(x as f32);
|
chart_state.record_summary(x as f32);
|
||||||
Some(vec![x.round() as i32])
|
Some(vec![x.round() as i32])
|
||||||
}
|
|
||||||
None => {
|
|
||||||
chart_state.record_pressure_matrix(values);
|
|
||||||
chart_state.record_summary(MAX_DISPLAY_FORCE as f32);
|
|
||||||
Some(vec![MAX_DISPLAY_FORCE.round() as i32])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const MIN_DISPLAY_FORCE: f64 = 0.1;
|
const MIN_DISPLAY_FORCE: f64 = 0.1;
|
||||||
const MAX_DISPLAY_FORCE: f64 = 25.6;
|
const MAX_DISPLAY_FORCE: f64 = 25.6;
|
||||||
const QUADRATIC_A: f64 = -375.2;
|
|
||||||
const QUADRATIC_B: f64 = 25880.0;
|
|
||||||
const QUADRATIC_C: f64 = 52150.0;
|
|
||||||
|
|
||||||
fn ad_to_x(ad: f64) -> Option<f64> {
|
|
||||||
const CUBIC_LIMIT: f64 = 6.57;
|
|
||||||
const EPSILON: f64 = 0.000_001;
|
|
||||||
|
|
||||||
let cubic_min = ad_from_cubic_x(0.0);
|
|
||||||
if ad <= cubic_min {
|
|
||||||
return Some(0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
let cubic_threshold = ad_from_cubic_x(CUBIC_LIMIT);
|
|
||||||
if ad <= cubic_threshold {
|
|
||||||
return Some(solve_monotonic_ad(ad, 0.0, CUBIC_LIMIT, ad_from_cubic_x));
|
|
||||||
}
|
|
||||||
|
|
||||||
let quadratic_vertex = -QUADRATIC_B / (2.0 * QUADRATIC_A);
|
|
||||||
let quadratic_max = ad_from_quadratic_x(quadratic_vertex);
|
|
||||||
if ad - EPSILON > quadratic_max {
|
|
||||||
return Some(MAX_DISPLAY_FORCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(solve_monotonic_ad(
|
|
||||||
ad,
|
|
||||||
CUBIC_LIMIT,
|
|
||||||
quadratic_vertex,
|
|
||||||
ad_from_quadratic_x,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn solve_monotonic_ad(ad: f64, mut low: f64, mut high: f64, f: fn(f64) -> f64) -> f64 {
|
|
||||||
for _ in 0..80 {
|
|
||||||
let mid = (low + high) / 2.0;
|
|
||||||
if f(mid) < ad {
|
|
||||||
low = mid;
|
|
||||||
} else {
|
|
||||||
high = mid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(low + high) / 2.0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ad_from_cubic_x(x: f64) -> f64 {
|
|
||||||
-5.732 * x.powi(3) - 131.5 * x.powi(2) + 31980.0 * x + 13490.0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ad_from_quadratic_x(x: f64) -> f64 {
|
|
||||||
QUADRATIC_A * x.powi(2) + QUADRATIC_B * x + QUADRATIC_C
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "devkit")]
|
#[cfg(feature = "devkit")]
|
||||||
fn push_devkit_frame(app: &AppHandle, values: &[i32], dts_ms: u64, resultant_force: f64) {
|
fn push_devkit_frame(app: &AppHandle, values: &[i32], dts_ms: u64, resultant_force: f64) {
|
||||||
@@ -493,8 +428,6 @@ fn infer_matrix_shape(len: usize) -> (u32, u32) {
|
|||||||
(best.0 as u32, best.1 as u32)
|
(best.0 as u32, best.1 as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "debug")]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn raw_to_g1(raw: u32) -> f64 {
|
fn raw_to_g1(raw: u32) -> f64 {
|
||||||
const X: [u32; 12] = [
|
const X: [u32; 12] = [
|
||||||
0, 20829, 102371, 132956, 165568, 182033, 217263, 263098, 283747, 365120, 410556, 477190
|
0, 20829, 102371, 132956, 165568, 182033, 217263, 263098, 283747, 365120, 410556, 477190
|
||||||
|
|||||||
@@ -41,9 +41,7 @@
|
|||||||
"template": "nsis/installer.nsi"
|
"template": "nsis/installer.nsi"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"resources": [
|
"resources": []
|
||||||
"resources/je-skin-devkit-server.exe"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"plugins": {
|
"plugins": {
|
||||||
"updater": {
|
"updater": {
|
||||||
|
|||||||
@@ -677,14 +677,6 @@
|
|||||||
<span class="stats-key">{viewerI18n.current}</span>
|
<span class="stats-key">{viewerI18n.current}</span>
|
||||||
<strong class="stats-value">{formatForceStat(stats.current)}</strong>
|
<strong class="stats-value">{formatForceStat(stats.current)}</strong>
|
||||||
</article>
|
</article>
|
||||||
<article class="stats-card">
|
|
||||||
<span class="stats-key">{viewerI18n.max}</span>
|
|
||||||
<strong class="stats-value">{formatForceStat(stats.max)}</strong>
|
|
||||||
</article>
|
|
||||||
<article class="stats-card">
|
|
||||||
<span class="stats-key">{viewerI18n.min}</span>
|
|
||||||
<strong class="stats-value">{formatForceStat(stats.min)}</strong>
|
|
||||||
</article>
|
|
||||||
</div>
|
</div>
|
||||||
<p class="stats-note">{statsNote}</p>
|
<p class="stats-note">{statsNote}</p>
|
||||||
</section>
|
</section>
|
||||||
@@ -773,7 +765,7 @@
|
|||||||
|
|
||||||
.stats-grid {
|
.stats-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
grid-template-columns: minmax(0, 1fr);
|
||||||
gap: 0.46rem;
|
gap: 0.46rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
return delta === -180 ? 180 : delta;
|
return delta === -180 ? 180 : delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const displayAngleOffsetDeg = 90;
|
||||||
const jumpAngleThresholdDeg = 72;
|
const jumpAngleThresholdDeg = 72;
|
||||||
|
|
||||||
let visualAngleDeg = 0;
|
let visualAngleDeg = 0;
|
||||||
@@ -95,7 +96,7 @@
|
|||||||
spatialForce !== null &&
|
spatialForce !== null &&
|
||||||
Number.isFinite(spatialForce.angleDeg) &&
|
Number.isFinite(spatialForce.angleDeg) &&
|
||||||
(!requireMagnitude || (Number.isFinite(spatialForce.magnitude) && Math.abs(spatialForce.magnitude) >= 0.0001));
|
(!requireMagnitude || (Number.isFinite(spatialForce.magnitude) && Math.abs(spatialForce.magnitude) >= 0.0001));
|
||||||
$: angleDeg = hasData ? normalizeAngle(spatialForce?.angleDeg ?? 0) : 0;
|
$: angleDeg = hasData ? normalizeAngle((spatialForce?.angleDeg ?? 0) + displayAngleOffsetDeg) : 0;
|
||||||
$: updateVisualAngle(angleDeg, hasData);
|
$: updateVisualAngle(angleDeg, hasData);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -136,10 +137,10 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="compass-center"></div>
|
<div class="compass-center"></div>
|
||||||
<span class="compass-label label-top">90</span>
|
<span class="compass-label label-top">0</span>
|
||||||
<span class="compass-label label-right">0</span>
|
<span class="compass-label label-right">270</span>
|
||||||
<span class="compass-label label-bottom">270</span>
|
<span class="compass-label label-bottom">180</span>
|
||||||
<span class="compass-label label-left">180</span>
|
<span class="compass-label label-left">90</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -68,18 +68,6 @@
|
|||||||
return Math.min(max, Math.max(min, value));
|
return Math.min(max, Math.max(min, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatValue(value: number | null): string {
|
|
||||||
if (value === null) {
|
|
||||||
return "--";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value >= maxDisplayForce) {
|
|
||||||
return `${maxDisplayForce.toFixed(1)}+`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value.toFixed(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatAxisValue(value: number, axis: "x" | "y"): string {
|
function formatAxisValue(value: number, axis: "x" | "y"): string {
|
||||||
if (!Number.isFinite(value)) {
|
if (!Number.isFinite(value)) {
|
||||||
return "--";
|
return "--";
|
||||||
@@ -373,9 +361,6 @@
|
|||||||
$: yAxisTicks = sampleCount > 0 ? buildYAxisTicks(yScaleBounds, yDataBounds) : [];
|
$: yAxisTicks = sampleCount > 0 ? buildYAxisTicks(yScaleBounds, yDataBounds) : [];
|
||||||
$: xAxisTicks = sampleCount > 0 ? buildXAxisTicks(xScaleBounds) : [];
|
$: xAxisTicks = sampleCount > 0 ? buildXAxisTicks(xScaleBounds) : [];
|
||||||
$: drawCanvas(canvasEl, plotPoints, yAxisTicks, xAxisTicks, sampleCount);
|
$: drawCanvas(canvasEl, plotPoints, yAxisTicks, xAxisTicks, sampleCount);
|
||||||
$: latestValue = formatValue(summary.latest);
|
|
||||||
$: minValue = formatValue(summary.min);
|
|
||||||
$: maxValue = formatValue(summary.max);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<article
|
<article
|
||||||
@@ -387,13 +372,7 @@
|
|||||||
<header class="panel-head">
|
<header class="panel-head">
|
||||||
<div class="head-text">
|
<div class="head-text">
|
||||||
<p class="panel-code">RF</p>
|
<p class="panel-code">RF</p>
|
||||||
<p class="panel-title">{summary.label}</p>
|
<p class="panel-title">{locale === "zh-CN" ? "合力" : "Resultant Force"}</p>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="icon-layer" aria-hidden="true">
|
|
||||||
<span class="icon-chip tone-cyan">NOW</span>
|
|
||||||
<span class="icon-chip tone-lime">MIN</span>
|
|
||||||
<span class="icon-chip tone-orange">MAX</span>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@@ -406,24 +385,6 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer class="panel-foot">
|
|
||||||
<p class="foot-item">
|
|
||||||
<span class="dot tone-cyan"></span>
|
|
||||||
<span class="metric-text">{i18n.now}</span>
|
|
||||||
<span class="value">{latestValue}</span>
|
|
||||||
</p>
|
|
||||||
<p class="foot-item">
|
|
||||||
<span class="dot tone-lime"></span>
|
|
||||||
<span class="metric-text">{i18n.min}</span>
|
|
||||||
<span class="value">{minValue}</span>
|
|
||||||
</p>
|
|
||||||
<p class="foot-item">
|
|
||||||
<span class="dot tone-orange"></span>
|
|
||||||
<span class="metric-text">{i18n.max}</span>
|
|
||||||
<span class="value">{maxValue}</span>
|
|
||||||
</p>
|
|
||||||
</footer>
|
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -438,7 +399,7 @@
|
|||||||
flex: 0 0 var(--rail-width, auto);
|
flex: 0 0 var(--rail-width, auto);
|
||||||
justify-self: start;
|
justify-self: start;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: auto 1fr auto;
|
grid-template-rows: auto 1fr;
|
||||||
gap: 0.68rem;
|
gap: 0.68rem;
|
||||||
padding: 0.88rem 0.96rem 1rem;
|
padding: 0.88rem 0.96rem 1rem;
|
||||||
border: 1px solid rgb(var(--hud-border-strong-rgb) / 0.42);
|
border: 1px solid rgb(var(--hud-border-strong-rgb) / 0.42);
|
||||||
@@ -504,36 +465,6 @@
|
|||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.05em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-layer {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 0.26rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-chip {
|
|
||||||
border: 1px solid rgb(var(--hud-border-strong-rgb) / 0.44);
|
|
||||||
border-radius: 999px;
|
|
||||||
padding: 0.08rem 0.36rem;
|
|
||||||
font-size: 0.58rem;
|
|
||||||
letter-spacing: 0.08em;
|
|
||||||
color: rgb(var(--hud-text-main-rgb) / 0.94);
|
|
||||||
background: rgb(var(--hud-surface-rgb) / 0.66);
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-chip.tone-cyan {
|
|
||||||
border-color: rgb(var(--hud-cyan-rgb) / 0.54);
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-chip.tone-lime {
|
|
||||||
border-color: rgb(var(--hud-lime-rgb) / 0.56);
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-chip.tone-orange {
|
|
||||||
border-color: rgb(var(--hud-orange-rgb) / 0.58);
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-stage {
|
.chart-stage {
|
||||||
position: relative;
|
position: relative;
|
||||||
block-size: clamp(12rem, 15.5vw, 15rem);
|
block-size: clamp(12rem, 15.5vw, 15rem);
|
||||||
@@ -565,55 +496,6 @@
|
|||||||
background: linear-gradient(180deg, rgb(var(--hud-surface-deep-rgb) / 0.06), rgb(var(--hud-surface-deep-rgb) / 0.18));
|
background: linear-gradient(180deg, rgb(var(--hud-surface-deep-rgb) / 0.06), rgb(var(--hud-surface-deep-rgb) / 0.18));
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-foot {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
gap: 0.8rem;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.foot-item {
|
|
||||||
margin: 0;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.22rem;
|
|
||||||
color: rgb(var(--hud-text-main-rgb) / 0.9);
|
|
||||||
font-size: 0.68rem;
|
|
||||||
letter-spacing: 0.03em;
|
|
||||||
white-space: nowrap;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-text {
|
|
||||||
color: rgb(var(--hud-text-dim-rgb) / 0.82);
|
|
||||||
text-transform: uppercase;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dot {
|
|
||||||
inline-size: 0.34rem;
|
|
||||||
block-size: 0.34rem;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dot.tone-cyan {
|
|
||||||
background: rgb(var(--hud-cyan-rgb));
|
|
||||||
}
|
|
||||||
|
|
||||||
.dot.tone-lime {
|
|
||||||
background: rgb(var(--hud-lime-rgb));
|
|
||||||
}
|
|
||||||
|
|
||||||
.dot.tone-orange {
|
|
||||||
background: rgb(var(--hud-orange-rgb));
|
|
||||||
}
|
|
||||||
|
|
||||||
.value {
|
|
||||||
min-inline-size: 2.6rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 1180px) {
|
@media (max-width: 1180px) {
|
||||||
.signal-panel {
|
.signal-panel {
|
||||||
inline-size: var(--rail-width, min(100%, clamp(28rem, 40vw, 38rem)));
|
inline-size: var(--rail-width, min(100%, clamp(28rem, 40vw, 38rem)));
|
||||||
|
|||||||
@@ -194,7 +194,7 @@
|
|||||||
const pointsPerSeries = 28;
|
const pointsPerSeries = 28;
|
||||||
const summaryPointsPerSeries = 42;
|
const summaryPointsPerSeries = 42;
|
||||||
const signalRenderTickMs = 1200;
|
const signalRenderTickMs = 1200;
|
||||||
const summaryReleaseForceEpsilon = 2.0;
|
const summaryReleaseForceEpsilon = 0.1;
|
||||||
const releaseClearDelayMs = 5000;
|
const releaseClearDelayMs = 5000;
|
||||||
const spatialForceMagnitudeEpsilon = 0.0001;
|
const spatialForceMagnitudeEpsilon = 0.0001;
|
||||||
const replayDefaultFrameMs = 40;
|
const replayDefaultFrameMs = 40;
|
||||||
@@ -293,7 +293,7 @@
|
|||||||
let devkitSpatialForceClearTimer: number | null = null;
|
let devkitSpatialForceClearTimer: number | null = null;
|
||||||
let summaryClearTimer: number | null = null;
|
let summaryClearTimer: number | null = null;
|
||||||
let spatialForceClearTimer: number | null = null;
|
let spatialForceClearTimer: number | null = null;
|
||||||
let summaryReleaseHidden = false;
|
let summaryReleaseHidden = true;
|
||||||
let spatialForceReleaseHidden = false;
|
let spatialForceReleaseHidden = false;
|
||||||
let spatialForcePanelVisible = false;
|
let spatialForcePanelVisible = false;
|
||||||
let sessionStartedAt: number = Date.now();
|
let sessionStartedAt: number = Date.now();
|
||||||
@@ -1270,7 +1270,7 @@
|
|||||||
function clearHudPanels(): void {
|
function clearHudPanels(): void {
|
||||||
cancelSummaryClear();
|
cancelSummaryClear();
|
||||||
cancelSpatialForceClear();
|
cancelSpatialForceClear();
|
||||||
summaryReleaseHidden = false;
|
summaryReleaseHidden = true;
|
||||||
spatialForceReleaseHidden = false;
|
spatialForceReleaseHidden = false;
|
||||||
spatialForcePanelVisible = false;
|
spatialForcePanelVisible = false;
|
||||||
hasSignalData = false;
|
hasSignalData = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user