summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorLLLL Colonq <llll@colonq>2025-02-16 01:53:39 -0500
committerLLLL Colonq <llll@colonq>2025-02-16 01:53:39 -0500
commitf2d6e8ac38e8ade9bebc355f4c0e97760f6f1649 (patch)
tree46906fcccecb63cd36ebc9023135751c55279014 /src/common
parent472eadbc178ed70a4acc9339d34f0bb2fa04b0a1 (diff)
Throwing shade
Diffstat (limited to 'src/common')
-rw-r--r--src/common/overlay.rs48
-rw-r--r--src/common/overlay/assets/shaders/throwshade/frag.glsl15
-rw-r--r--src/common/overlay/throwshade.rs16
3 files changed, 70 insertions, 9 deletions
diff --git a/src/common/overlay.rs b/src/common/overlay.rs
index 9698f2c..78fd0fa 100644
--- a/src/common/overlay.rs
+++ b/src/common/overlay.rs
@@ -28,6 +28,9 @@ pub struct Overlay {
tracking_mouth: f32,
tracking_neck: glam::Quat,
throwshade: throwshade::ThrowShade,
+ chat_msg: String,
+ chat_time: f64,
+ chat_biblicality: f32,
}
impl Overlay {
@@ -54,12 +57,16 @@ impl Overlay {
sexp!((avatar frame)),
sexp!((avatar reset)),
sexp!((avatar tracking)),
- sexp!((overlay shader)),
+ sexp!((avatar overlay shader)),
+ sexp!((avatar overlay chat)),
]),
tracking_eyes: (1.0, 1.0),
tracking_mouth: 0.0,
tracking_neck: glam::Quat::IDENTITY,
throwshade: throwshade::ThrowShade::new(),
+ chat_msg: format!(""),
+ chat_time: 0.0,
+ chat_biblicality: 0.0,
}
}
pub async fn overlay(ctx: &context::Context) -> Self {
@@ -69,6 +76,11 @@ impl Overlay {
let raw_stdout = std::io::stdout().into_raw_mode().expect("failed to set raw mode");
Self::new(ctx, RenderMode::Terminal(raw_stdout)).await
}
+ pub fn handle_reset(&mut self, ctx: &context::Context ) {
+ // TODO also reset terminal
+ if let Some(s) = &mut self.throwshade.shader { s.delete(ctx); }
+ self.throwshade.shader = None;
+ }
pub fn handle_tracking(&mut self, msg: fig::Message) -> Option<()> {
let eyes = msg.data.get(0)?;
let eye_left = eyes.get(0)?.as_str()?.parse::<f32>().ok()?;
@@ -102,10 +114,28 @@ impl Overlay {
}
Some(())
}
- pub fn handle_shader(&mut self, ctx: &context::Context, msg: fig::Message) -> Option<()> {
+ pub fn handle_overlay_shader(
+ &mut self,
+ ctx: &context::Context, st: &state::State,
+ msg: fig::Message
+ ) -> Option<()> {
+ let bs = BASE64_STANDARD.decode(msg.data.get(0)?.as_str()?).ok()?;
+ let s = String::from_utf8_lossy(&bs);
+ if let Err(e) = self.throwshade.set(ctx, st, &s) {
+ log::warn!("error compiling shader: {}", e);
+ self.throwshade.shader = None;
+ }
+ Some(())
+ }
+ pub fn handle_overlay_chat(&mut self, msg: fig::Message) -> Option<()> {
let bs = BASE64_STANDARD.decode(msg.data.get(0)?.as_str()?).ok()?;
let s = String::from_utf8_lossy(&bs);
- self.throwshade.set(ctx, &s);
+ let time = msg.data.get(1)?.as_str()?.parse::<f64>().ok()?;
+ let biblicality = msg.data.get(2)?.as_str()?.parse::<f32>().ok()?;
+ log::info!("received chat message: {} {} {}", s, time, biblicality);
+ self.chat_msg = s.to_string();
+ self.chat_time = time;
+ self.chat_biblicality = biblicality;
Some(())
}
fn render_model_terminal(&mut self, ctx: &context::Context, st: &mut state::State) -> Option<()> {
@@ -162,12 +192,16 @@ impl teleia::state::Game for Overlay {
let malformed = format!("malformed {} data: {}", msg.event, msg.data);
if msg.event == sexp!((avatar tracking)) {
if self.handle_tracking(msg).is_none() { log::warn!("{}", malformed) }
+ } else if msg.event == sexp!((avatar reset)) {
+ self.handle_reset(ctx);
} else if msg.event == sexp!((avatar text)) {
if self.handle_text(msg).is_none() { log::warn!("{}", malformed) }
} else if msg.event == sexp!((avatar frame)) {
if self.handle_frame(msg).is_none() { log::warn!("{}", malformed) }
- } else if msg.event == sexp!((overlay shader)) {
- if self.handle_shader(ctx, msg).is_none() { log::warn!("{}", malformed) }
+ } else if msg.event == sexp!((avatar overlay shader)) {
+ if self.handle_overlay_shader(ctx, st, msg).is_none() { log::warn!("{}", malformed) }
+ } else if msg.event == sexp!((avatar overlay chat)) {
+ if self.handle_overlay_chat(msg).is_none() { log::warn!("{}", malformed) }
} else {
log::info!("received unhandled event {} with data: {}", msg.event, msg.data);
}
@@ -180,6 +214,10 @@ impl teleia::state::Game for Overlay {
fn render(&mut self, ctx: &context::Context, st: &mut state::State) -> Option<()> {
if let Some(s) = &self.throwshade.shader {
s.bind(ctx);
+ s.set_vec2(ctx, "resolution", &glam::Vec2::new(ctx.render_width, ctx.render_height));
+ let elapsed = (st.tick - self.throwshade.tickset) as f32 / 60.0;
+ s.set_f32(ctx, "time", elapsed);
+ s.set_f32(ctx, "chat_time", (self.chat_time - self.throwshade.timeset) as f32);
ctx.render_no_geometry();
}
Some(())
diff --git a/src/common/overlay/assets/shaders/throwshade/frag.glsl b/src/common/overlay/assets/shaders/throwshade/frag.glsl
index 36f1023..2acc78d 100644
--- a/src/common/overlay/assets/shaders/throwshade/frag.glsl
+++ b/src/common/overlay/assets/shaders/throwshade/frag.glsl
@@ -4,10 +4,23 @@ precision highp float;
in vec2 vertex_texcoord;
out vec4 frag_color;
+uniform vec2 resolution;
+
+uniform float time;
+
+uniform float bpm;
+
+uniform vec2 cursor;
+
+uniform float chat_time;
+uniform float chat_biblicality;
+
vec4 shade(vec2);
void main() {
- frag_color = shade(vertex_texcoord);
+ vec2 inverted = vec2(vertex_texcoord.x, 1.0 - vertex_texcoord.y);
+ frag_color = shade(inverted);
+ frag_color.a = clamp(frag_color.a * 0.5, 0.0, 0.5);
}
// "The Cutoff"
diff --git a/src/common/overlay/throwshade.rs b/src/common/overlay/throwshade.rs
index d7ac430..c6b8f2e 100644
--- a/src/common/overlay/throwshade.rs
+++ b/src/common/overlay/throwshade.rs
@@ -4,20 +4,30 @@ const VERT: &'static str = include_str!("assets/shaders/throwshade/vert.glsl");
const FRAG: &'static str = include_str!("assets/shaders/throwshade/frag.glsl");
pub struct ThrowShade {
+ pub tickset: u64,
+ pub timeset: f64,
pub shader: Option<shader::Shader>,
}
impl ThrowShade {
pub fn new() -> Self {
Self {
+ tickset: 0,
+ timeset: 0.0,
shader: None,
}
}
- pub fn set(&mut self, ctx: &context::Context, src: &str) {
+ pub fn set(&mut self, ctx: &context::Context, st: &state::State, src: &str) -> Result<(), String> {
let fsrc = format!("{}\n{}\n", FRAG, src);
+ self.tickset = st.tick;
+ if let Ok(dur) = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH) {
+ self.timeset = dur.as_secs_f64();
+ log::info!("the time: {}", self.timeset);
+ }
if let Some(s) = &mut self.shader {
- s.replace(ctx, VERT, &fsrc);
+ s.replace(ctx, VERT, &fsrc)?;
} else {
- self.shader = Some(shader::Shader::new_nolib(ctx, VERT, &fsrc));
+ self.shader = Some(shader::Shader::new_helper(ctx, VERT, &fsrc)?);
}
+ Ok(())
}
}