feat: add device-side subtitle overlay using FreeType for rendering Chinese text
- Updated Cargo.toml to include freetype-rs for font rendering. - Modified message.rs to introduce a new Message variant for subtitles. - Enhanced HttpPlugin to send subtitle messages to the live2d plugin. - Implemented text rendering in the live2d plugin using FreeType for Chinese characters. - Added OpenGL shaders for rendering text overlays. - Created a new text.rs module for handling text rasterization and texture rendering. - Updated renderer.rs to integrate subtitle rendering logic.
This commit is contained in:
@@ -9,10 +9,11 @@ use crate::core::plugin::{Platform, Plugin, PluginContext, PluginInfo};
|
||||
use anyhow::{Context, Result};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::thread::JoinHandle;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use super::renderer::Live2DRenderer;
|
||||
use super::renderer::{Live2DRenderer, Subtitle, SubtitleState};
|
||||
|
||||
pub struct Live2DPlugin {
|
||||
ctx: Option<PluginContext>,
|
||||
@@ -21,6 +22,8 @@ pub struct Live2DPlugin {
|
||||
worker: Option<JoinHandle<()>>,
|
||||
/// 渲染停止信号
|
||||
stop_flag: Arc<AtomicBool>,
|
||||
/// 字幕共享状态(http 插件写入,渲染线程读取)
|
||||
subtitle: SubtitleState,
|
||||
}
|
||||
|
||||
impl Live2DPlugin {
|
||||
@@ -30,6 +33,7 @@ impl Live2DPlugin {
|
||||
renderer: None,
|
||||
worker: None,
|
||||
stop_flag: Arc::new(AtomicBool::new(false)),
|
||||
subtitle: Arc::new(Mutex::new(None)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,6 +101,16 @@ impl Plugin for Live2DPlugin {
|
||||
Message::Shutdown => {
|
||||
self.stop_live2d();
|
||||
}
|
||||
Message::Subtitle { text } => {
|
||||
// 设备端字幕:写入共享状态,渲染线程每帧读取,超时自动消失
|
||||
let ttl = Duration::from_millis(
|
||||
(text.chars().count().max(1) as u64)
|
||||
.saturating_mul(220)
|
||||
.saturating_add(2500),
|
||||
);
|
||||
*self.subtitle.lock().unwrap() =
|
||||
Some(Subtitle { text, expires_at: Instant::now() + ttl });
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(())
|
||||
@@ -139,7 +153,14 @@ impl Live2DPlugin {
|
||||
.clone();
|
||||
|
||||
let renderer = Arc::new(std::sync::Mutex::new(
|
||||
Live2DRenderer::new(&core_so, &live2d_base, &model_rel, width, height)?,
|
||||
Live2DRenderer::new(
|
||||
&core_so,
|
||||
&live2d_base,
|
||||
&model_rel,
|
||||
width,
|
||||
height,
|
||||
Arc::clone(&self.subtitle),
|
||||
)?,
|
||||
));
|
||||
self.renderer = Some(Arc::clone(&renderer));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user