2023-01-12 16:45:06 +00:00
|
|
|
use crate::write_log;
|
|
|
|
|
2023-01-14 19:15:43 +00:00
|
|
|
use self::{
|
|
|
|
rendering::Rendering,
|
2023-01-17 11:18:53 +00:00
|
|
|
rfactor_data::{DataReceiver, RFactorData},
|
2023-01-14 19:15:43 +00:00
|
|
|
};
|
2023-01-12 09:10:09 +00:00
|
|
|
|
2023-01-17 11:18:53 +00:00
|
|
|
mod elements;
|
2023-01-12 09:10:09 +00:00
|
|
|
mod rendering;
|
2023-01-12 16:45:06 +00:00
|
|
|
mod rfactor_data;
|
2023-01-12 09:10:09 +00:00
|
|
|
|
|
|
|
use anyhow::Result;
|
2023-01-17 06:57:56 +00:00
|
|
|
use assetpath::AssetPath;
|
2023-01-17 11:18:53 +00:00
|
|
|
use std::{
|
|
|
|
cell::RefCell,
|
|
|
|
rc::Rc,
|
|
|
|
sync::{Arc, Mutex},
|
|
|
|
};
|
2023-01-17 06:57:56 +00:00
|
|
|
use ui::prelude::*;
|
2023-01-12 09:10:09 +00:00
|
|
|
use vulkan_rs::prelude::*;
|
|
|
|
|
2023-01-17 11:18:53 +00:00
|
|
|
use elements::*;
|
|
|
|
|
2023-01-16 16:07:39 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
2023-01-17 14:44:11 +00:00
|
|
|
pub trait UiOverlay: DataReceiver {}
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize)]
|
|
|
|
pub struct UiSelectorConfig {
|
|
|
|
pub enable_watermark: bool,
|
|
|
|
|
|
|
|
pub enable_radar: bool,
|
|
|
|
pub enable_pedals: bool,
|
2023-01-18 06:09:44 +00:00
|
|
|
pub enable_leaderboard: bool,
|
2023-01-17 14:44:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl UiSelectorConfig {
|
|
|
|
pub const fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
enable_watermark: true,
|
|
|
|
enable_radar: true,
|
|
|
|
enable_pedals: true,
|
2023-01-18 06:09:44 +00:00
|
|
|
enable_leaderboard: true,
|
2023-01-17 14:44:11 +00:00
|
|
|
}
|
|
|
|
}
|
2023-01-17 11:18:53 +00:00
|
|
|
}
|
|
|
|
|
2023-01-16 16:07:39 +00:00
|
|
|
#[derive(Deserialize, Serialize)]
|
|
|
|
pub struct OverlayConfig {
|
2023-01-17 14:44:11 +00:00
|
|
|
pub ui_config: UiSelectorConfig,
|
2023-01-17 06:57:56 +00:00
|
|
|
pub radar_config: RadarConfig,
|
2023-01-16 16:07:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl OverlayConfig {
|
|
|
|
pub const fn new() -> Self {
|
|
|
|
Self {
|
2023-01-17 14:44:11 +00:00
|
|
|
ui_config: UiSelectorConfig::new(),
|
2023-01-17 06:57:56 +00:00
|
|
|
radar_config: RadarConfig::new(),
|
2023-01-16 16:07:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-12 09:10:09 +00:00
|
|
|
pub struct Overlay {
|
2023-01-16 16:07:39 +00:00
|
|
|
config: OverlayConfig,
|
|
|
|
|
2023-01-12 09:10:09 +00:00
|
|
|
instance: Option<Arc<Instance>>,
|
|
|
|
device: Option<Arc<Device>>,
|
2023-01-12 16:45:06 +00:00
|
|
|
queue: Option<Arc<Mutex<Queue>>>,
|
|
|
|
rendering: Option<Rendering>,
|
2023-01-17 06:57:56 +00:00
|
|
|
gui_handler: Option<Arc<GuiHandler>>,
|
2023-01-12 16:45:06 +00:00
|
|
|
|
2023-01-17 11:18:53 +00:00
|
|
|
ui_elements: Vec<Rc<RefCell<dyn UiOverlay>>>,
|
|
|
|
|
2023-01-13 07:11:53 +00:00
|
|
|
rfactor_data: Option<RFactorData>,
|
2023-01-12 09:10:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Overlay {
|
|
|
|
pub const fn new() -> Self {
|
|
|
|
Self {
|
2023-01-16 16:07:39 +00:00
|
|
|
config: OverlayConfig::new(),
|
|
|
|
|
2023-01-12 09:10:09 +00:00
|
|
|
instance: None,
|
|
|
|
device: None,
|
2023-01-12 16:45:06 +00:00
|
|
|
queue: None,
|
|
|
|
rendering: None,
|
2023-01-17 06:57:56 +00:00
|
|
|
gui_handler: None,
|
2023-01-17 11:18:53 +00:00
|
|
|
ui_elements: Vec::new(),
|
2023-01-12 16:45:06 +00:00
|
|
|
|
2023-01-13 07:11:53 +00:00
|
|
|
rfactor_data: None,
|
2023-01-12 09:10:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-16 16:07:39 +00:00
|
|
|
pub fn set_config(&mut self, config: OverlayConfig) {
|
|
|
|
self.config = config;
|
|
|
|
}
|
|
|
|
|
2023-01-12 09:10:09 +00:00
|
|
|
pub fn set_instance(&mut self, instance: Arc<Instance>) {
|
|
|
|
self.instance = Some(instance);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instance(&self) -> Arc<Instance> {
|
|
|
|
self.instance.as_ref().unwrap().clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_device(&mut self, device: Arc<Device>) {
|
|
|
|
self.device = Some(device);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn device(&self) -> Arc<Device> {
|
|
|
|
self.device.as_ref().unwrap().clone()
|
|
|
|
}
|
|
|
|
|
2023-01-14 07:08:40 +00:00
|
|
|
pub fn set_queue(&mut self, queue: Arc<Mutex<Queue>>) {
|
2023-01-12 16:45:06 +00:00
|
|
|
self.queue = Some(queue);
|
2023-01-12 12:52:44 +00:00
|
|
|
}
|
|
|
|
|
2023-01-12 16:45:06 +00:00
|
|
|
pub fn queue(&self) -> Arc<Mutex<Queue>> {
|
|
|
|
self.queue.as_ref().unwrap().clone()
|
2023-01-12 12:52:44 +00:00
|
|
|
}
|
|
|
|
|
2023-01-13 14:00:01 +00:00
|
|
|
pub fn swapchain(&self, swapchain: VkSwapchainKHR) -> Option<&Arc<Swapchain>> {
|
|
|
|
let sc = self.rendering.as_ref().unwrap().swapchain();
|
|
|
|
|
|
|
|
if sc.vk_handle() == swapchain {
|
|
|
|
Some(sc)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
2023-01-12 12:52:44 +00:00
|
|
|
}
|
|
|
|
|
2023-01-12 16:45:06 +00:00
|
|
|
pub fn create_rendering(&mut self, swapchain: Arc<Swapchain>) -> Result<()> {
|
2023-01-14 19:15:43 +00:00
|
|
|
write_log!("-> create rendering: start");
|
2023-01-12 16:45:06 +00:00
|
|
|
|
|
|
|
self.rendering = None;
|
|
|
|
|
2023-01-14 19:15:43 +00:00
|
|
|
write_log!("-> create rendering: old cleared");
|
2023-01-12 16:45:06 +00:00
|
|
|
|
2023-01-17 11:18:53 +00:00
|
|
|
let mut rendering = Rendering::new(self.queue(), swapchain.clone())?;
|
|
|
|
|
|
|
|
write_log!("-> create rendering: new created");
|
2023-01-17 06:57:56 +00:00
|
|
|
|
|
|
|
// only font is used
|
|
|
|
let mut create_info = GuiHandlerCreateInfo::default();
|
2023-01-17 15:11:48 +00:00
|
|
|
|
2023-01-18 11:04:19 +00:00
|
|
|
create_info.font_path = AssetPath::from("/usr/share/vulkan_rf2_layer/font.png");
|
|
|
|
// create_info.font_path = AssetPath::from("/opt/sata_ssd/Workspace/vk_layer_rs/font.png");
|
2023-01-17 06:57:56 +00:00
|
|
|
create_info.font_path.assume_prefix_free();
|
2023-01-17 15:11:48 +00:00
|
|
|
|
2023-01-17 14:44:11 +00:00
|
|
|
// required to not crash
|
|
|
|
create_info.resource_directory = AssetPath::from("");
|
|
|
|
create_info.resource_directory.assume_prefix_free();
|
2023-01-17 06:57:56 +00:00
|
|
|
|
2023-01-17 11:18:53 +00:00
|
|
|
// provide trait required by GuiHandler
|
2023-01-17 06:57:56 +00:00
|
|
|
let ctx = Arc::new(ContextImpl::new(
|
|
|
|
self.device(),
|
|
|
|
self.queue(),
|
|
|
|
swapchain,
|
|
|
|
rendering.images().clone(),
|
|
|
|
));
|
|
|
|
|
2023-01-17 11:18:53 +00:00
|
|
|
// create GuiHandler
|
2023-01-17 14:44:11 +00:00
|
|
|
write_log!(format!("Create Info: \n{:#?}", create_info));
|
|
|
|
|
2023-01-17 11:18:53 +00:00
|
|
|
let gui_handler = GuiHandler::new(create_info, &(ctx as Arc<dyn ContextInterface>))?;
|
2023-01-17 14:44:11 +00:00
|
|
|
write_log!("GuiHandler successfully created");
|
2023-01-17 06:57:56 +00:00
|
|
|
|
2023-01-17 11:18:53 +00:00
|
|
|
// create ui elements
|
2023-01-12 16:45:06 +00:00
|
|
|
|
2023-01-17 14:44:11 +00:00
|
|
|
// create watermark
|
|
|
|
if self.config.ui_config.enable_watermark {
|
|
|
|
let watermark = Rc::new(RefCell::new(Watermark::new(&gui_handler)?));
|
|
|
|
|
|
|
|
self.ui_elements.push(watermark);
|
|
|
|
|
|
|
|
write_log!("Watermark successfully created");
|
|
|
|
}
|
|
|
|
|
2023-01-17 11:18:53 +00:00
|
|
|
// create radar
|
2023-01-17 14:44:11 +00:00
|
|
|
if self.config.ui_config.enable_radar {
|
|
|
|
let radar = Rc::new(RefCell::new(Radar::new(
|
|
|
|
self.config.radar_config,
|
|
|
|
self.device(),
|
|
|
|
self.queue(),
|
|
|
|
&rendering,
|
|
|
|
)?));
|
2023-01-17 11:18:53 +00:00
|
|
|
|
2023-01-17 14:44:11 +00:00
|
|
|
rendering.add_render_callback({
|
|
|
|
let radar = radar.clone();
|
2023-01-17 11:18:53 +00:00
|
|
|
|
2023-01-17 14:44:11 +00:00
|
|
|
move |index| radar.borrow().render(index)
|
|
|
|
});
|
2023-01-17 11:18:53 +00:00
|
|
|
|
2023-01-17 14:44:11 +00:00
|
|
|
self.ui_elements.push(radar);
|
|
|
|
|
|
|
|
write_log!("Radar successfully created");
|
|
|
|
}
|
|
|
|
|
|
|
|
// create pedals
|
|
|
|
if self.config.ui_config.enable_pedals {
|
2023-01-18 10:51:16 +00:00
|
|
|
let pedals = Rc::new(RefCell::new(Pedals::new(
|
|
|
|
&gui_handler,
|
|
|
|
self.device(),
|
|
|
|
self.queue(),
|
|
|
|
)?));
|
|
|
|
|
|
|
|
self.ui_elements.push(pedals.clone());
|
|
|
|
|
|
|
|
rendering.add_render_callback(move |_| pedals.borrow().render());
|
2023-01-17 14:44:11 +00:00
|
|
|
|
|
|
|
write_log!("Pedals successfully created");
|
|
|
|
}
|
2023-01-17 11:18:53 +00:00
|
|
|
|
2023-01-18 06:09:44 +00:00
|
|
|
// create leaderboard
|
|
|
|
if self.config.ui_config.enable_leaderboard {
|
|
|
|
let leaderboard = Rc::new(RefCell::new(LeaderBoard::new(&gui_handler)?));
|
|
|
|
self.ui_elements.push(leaderboard);
|
|
|
|
|
|
|
|
write_log!("Leader Board successfully created");
|
|
|
|
}
|
|
|
|
|
2023-01-17 14:44:11 +00:00
|
|
|
// add rendering callbacks
|
2023-01-17 11:18:53 +00:00
|
|
|
rendering.add_render_callback({
|
|
|
|
let gui_handler = gui_handler.clone();
|
|
|
|
let device = self.device();
|
|
|
|
let queue = self.queue();
|
|
|
|
|
|
|
|
move |index| {
|
|
|
|
let command_buffer =
|
|
|
|
CommandBuffer::new_primary().build(device.clone(), queue.clone())?;
|
|
|
|
|
|
|
|
{
|
|
|
|
let mut recorder = command_buffer.begin(VkCommandBufferBeginInfo::new(
|
|
|
|
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
|
|
|
|
| VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
|
|
|
|
))?;
|
|
|
|
|
|
|
|
gui_handler.process(&mut recorder, &TargetMode::Mono(index as usize))?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(command_buffer)
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2023-01-17 14:44:11 +00:00
|
|
|
write_log!("render callbacks added");
|
2023-01-12 09:10:09 +00:00
|
|
|
|
2023-01-17 11:18:53 +00:00
|
|
|
self.rendering = Some(rendering);
|
|
|
|
self.gui_handler = Some(gui_handler);
|
|
|
|
|
2023-01-17 14:44:11 +00:00
|
|
|
write_log!("-> create rendering: end");
|
|
|
|
|
2023-01-12 09:10:09 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-01-14 07:08:40 +00:00
|
|
|
pub fn render(&mut self) -> Result<()> {
|
2023-01-13 07:11:53 +00:00
|
|
|
if self.rfactor_data.is_none() {
|
2023-01-17 11:18:53 +00:00
|
|
|
self.rfactor_data = RFactorData::new().ok();
|
|
|
|
|
|
|
|
if let Some(data) = &mut self.rfactor_data {
|
|
|
|
write_log!("created RFactorData");
|
|
|
|
|
|
|
|
for receiver in self.ui_elements.iter() {
|
|
|
|
data.add_receiver(receiver.clone());
|
|
|
|
}
|
|
|
|
}
|
2023-01-13 07:11:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(rfactor) = &mut self.rfactor_data {
|
|
|
|
rfactor.update()?;
|
|
|
|
}
|
|
|
|
|
2023-01-17 11:18:53 +00:00
|
|
|
self.rendering.as_ref().unwrap().render()
|
2023-01-12 09:10:09 +00:00
|
|
|
}
|
|
|
|
}
|
2023-01-17 06:57:56 +00:00
|
|
|
|
|
|
|
struct ContextImpl {
|
|
|
|
device: Arc<Device>,
|
|
|
|
queue: Arc<Mutex<Queue>>,
|
|
|
|
swapchain: Arc<Swapchain>,
|
|
|
|
images: Vec<Arc<Image>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ContextImpl {
|
|
|
|
fn new(
|
|
|
|
device: Arc<Device>,
|
|
|
|
queue: Arc<Mutex<Queue>>,
|
|
|
|
swapchain: Arc<Swapchain>,
|
|
|
|
images: Vec<Arc<Image>>,
|
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
device,
|
|
|
|
queue,
|
|
|
|
swapchain,
|
|
|
|
images,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ContextInterface for ContextImpl {
|
|
|
|
fn device(&self) -> &Arc<Device> {
|
|
|
|
&self.device
|
|
|
|
}
|
|
|
|
|
|
|
|
fn queue(&self) -> &Arc<Mutex<Queue>> {
|
|
|
|
&self.queue
|
|
|
|
}
|
|
|
|
|
|
|
|
fn format(&self) -> VkFormat {
|
|
|
|
self.swapchain.format()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn image_layout(&self) -> VkImageLayout {
|
|
|
|
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
|
|
|
|
}
|
|
|
|
|
|
|
|
fn image_count(&self) -> usize {
|
|
|
|
self.images.len()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn images(&self) -> TargetMode<Vec<Arc<Image>>> {
|
|
|
|
TargetMode::Mono(self.images.clone())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn width(&self) -> u32 {
|
|
|
|
self.swapchain.width()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn height(&self) -> u32 {
|
|
|
|
self.swapchain.height()
|
|
|
|
}
|
|
|
|
}
|