Advertisement
Armaldio

Untitled

Apr 4th, 2025
392
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 15.89 KB | None | 0 0
  1. use futures_util::StreamExt;
  2. use std::env;
  3. use std::error::Error;
  4. use std::net::SocketAddr;
  5. use std::sync::Arc;
  6. use std::{borrow::Cow, sync::Mutex, time::Instant};
  7. use steamworks::AppId;
  8. use steamworks::Client;
  9. use steamworks::FriendFlags;
  10. use steamworks::PersonaStateChange;
  11. use tauri::Window;
  12. use tauri::{
  13.     async_runtime, LogicalPosition, LogicalSize, Manager, RunEvent, WebviewUrl, WindowEvent,
  14. };
  15. use tokio::sync::mpsc::{Receiver, Sender};
  16. use warp::Filter;
  17.  
  18. pub struct WgpuState<'win> {
  19.    pub queue: wgpu::Queue,
  20.    pub device: wgpu::Device,
  21.    pub surface: wgpu::Surface<'win>,
  22.     pub render_pipeline: wgpu::RenderPipeline,
  23.     pub config: Mutex<wgpu::SurfaceConfiguration>,
  24. }
  25.  
  26. impl<'win> WgpuState<'win> {
  27.     pub async fn new(window: Window) -> Self {
  28.         let size = window.inner_size().unwrap();
  29.         let instance = wgpu::Instance::default();
  30.         let surface = instance.create_surface(window).unwrap();
  31.  
  32.         let adapters = instance.enumerate_adapters(wgpu::Backends::all()); // Enumerate all backends
  33.  
  34.         println!("Available wgpu backends:");
  35.         for adapter in adapters {
  36.             let info = adapter.get_info();
  37.             println!("- {:?}: {:?}", info.backend, info.name);
  38.         }
  39.  
  40.         let adapter = instance
  41.             .request_adapter(&wgpu::RequestAdapterOptions {
  42.                 power_preference: wgpu::PowerPreference::default(),
  43.                 force_fallback_adapter: false,
  44.                 compatible_surface: Some(&surface),
  45.             })
  46.             .await
  47.             .expect("Failed to find an appropriate adapter");
  48.  
  49.         let (device, queue) = adapter
  50.             .request_device(
  51.                 &wgpu::DeviceDescriptor {
  52.                     label: None,
  53.                     required_features: wgpu::Features::empty(),
  54.                     required_limits: wgpu::Limits::downlevel_webgl2_defaults()
  55.                         .using_resolution(adapter.limits()),
  56.                 },
  57.                 None,
  58.             )
  59.             .await
  60.             .expect("Failed to create device");
  61.  
  62.         let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
  63.             label: None,
  64.             source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(
  65.                 r#"
  66. @vertex
  67. fn vs_main(@builtin(vertex_index) vertex_index: u32) -> @builtin(position) vec4<f32> {
  68.    var position: vec4<f32>;
  69.    switch (vertex_index) {
  70.        case 0u: {
  71.            position = vec4<f32>(-1.0, -1.0, 0.0, 1.0); // Bottom-left
  72.        }
  73.        case 1u: {
  74.            position = vec4<f32>( 1.0, -1.0, 0.0, 1.0); // Bottom-right
  75.        }
  76.        case 2u: {
  77.            position = vec4<f32>( 0.0,  1.0, 0.0, 1.0); // Top-center
  78.        }
  79.        default: {
  80.            position = vec4<f32>(0.0, 0.0, 0.0, 1.0); // Default case (should not be reached)
  81.        }
  82.    }
  83.    return position;
  84. }
  85.  
  86. @fragment
  87. fn fs_main() -> @location(0) vec4<f32> {
  88.    // Output a solid color
  89.    return vec4<f32>(1.0, 0.0, 0.0, 0.5); // Green
  90. }
  91.  
  92.    "#,
  93.             )),
  94.         });
  95.  
  96.         let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
  97.             label: None,
  98.             push_constant_ranges: &[],
  99.             bind_group_layouts: &[],
  100.         });
  101.  
  102.         let swapchain_capabilities = surface.get_capabilities(&adapter);
  103.         println!("swapchain_capabilities {:?}", swapchain_capabilities);
  104.         let swapchain_format = swapchain_capabilities.formats[0];
  105.  
  106.         let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
  107.             label: None,
  108.             layout: Some(&pipeline_layout),
  109.             vertex: wgpu::VertexState {
  110.                 module: &shader,
  111.                 entry_point: "vs_main",
  112.                 buffers: &[],
  113.                 compilation_options: wgpu::PipelineCompilationOptions::default(),
  114.             },
  115.             fragment: Some(wgpu::FragmentState {
  116.                 module: &shader,
  117.                 entry_point: "fs_main",
  118.                 targets: &[Some(wgpu::ColorTargetState {
  119.                     format: swapchain_format,
  120.                     blend: Some(wgpu::BlendState::ALPHA_BLENDING),
  121.                     write_mask: wgpu::ColorWrites::ALL,
  122.                 })],
  123.                 compilation_options: wgpu::PipelineCompilationOptions::default(),
  124.             }),
  125.             primitive: wgpu::PrimitiveState::default(),
  126.             depth_stencil: None,
  127.             multisample: wgpu::MultisampleState::default(),
  128.             multiview: None,
  129.         });
  130.  
  131.         if swapchain_capabilities
  132.             .alpha_modes
  133.             .contains(&wgpu::CompositeAlphaMode::PreMultiplied)
  134.         {
  135.             println!("PreMultiplied alpha mode is supported!");
  136.         } else if swapchain_capabilities
  137.             .alpha_modes
  138.             .contains(&wgpu::CompositeAlphaMode::Opaque)
  139.         {
  140.             println!("Only Opaque alpha mode is supported. Transparency will not work.");
  141.         } else {
  142.             println!("No known alpha modes are supported.");
  143.         }
  144.  
  145.         let alpha_mode = if swapchain_capabilities
  146.             .alpha_modes
  147.             .contains(&wgpu::CompositeAlphaMode::PreMultiplied)
  148.         {
  149.             wgpu::CompositeAlphaMode::PreMultiplied
  150.         } else {
  151.             swapchain_capabilities.alpha_modes[0]
  152.         };
  153.  
  154.         let config = wgpu::SurfaceConfiguration {
  155.             width: size.width,
  156.             height: size.height,
  157.             format: swapchain_format,
  158.             usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC,
  159.             present_mode: wgpu::PresentMode::Fifo,
  160.             alpha_mode,
  161.             view_formats: vec![],
  162.             desired_maximum_frame_latency: 2,
  163.         };
  164.  
  165.         surface.configure(&device, &config);
  166.  
  167.         Self {
  168.             device,
  169.             queue,
  170.             surface,
  171.             render_pipeline,
  172.             config: Mutex::new(config),
  173.         }
  174.     }
  175. }
  176.  
  177. #[tauri::command]
  178. fn showOverlay() {
  179.     println!("Showing overlay");
  180.     match Client::init_app(480) {
  181.         Ok((client, _single)) => {
  182.             println!("Client created");
  183.             client.friends().activate_game_overlay("hey");
  184.             println!("Overlay shown");
  185.         }
  186.         Err(e) => eprintln!("Failed to initialize Steam client: {:?}", e),
  187.     }
  188. }
  189.  
  190. async fn websocket_server(tx: Sender<String>, mut rx: Receiver<String>) {
  191.     let addr = SocketAddr::from(([127, 0, 0, 1], 31753));
  192.  
  193.     // WebSocket upgrade
  194.     let ws_route = warp::path::end()
  195.         .and(warp::ws())
  196.         .map(move |ws: warp::ws::Ws| {
  197.             let tx = tx.clone();
  198.             ws.on_upgrade(move |websocket| async move {
  199.                 let (mut ws_tx, mut ws_rx) = websocket.split();
  200.  
  201.                 // Forward messages to the sender
  202.                 while let Some(result) = ws_rx.next().await {
  203.                     if let Ok(msg) = result {
  204.                         if let Ok(text) = msg.to_str() {
  205.                             println!("Received WebSocket message: {}", text);
  206.                             if tx.send(text.to_string()).await.is_err() {
  207.                                 eprintln!("Failed to send message to channel");
  208.                                 break;
  209.                             }
  210.                         }
  211.                     }
  212.                 }
  213.             })
  214.         });
  215.  
  216.     let routes = ws_route;
  217.  
  218.     // Spawn HTTP server
  219.     tokio::spawn(warp::serve(routes).run(addr));
  220.     println!("WebSocket server running on ws://{}", addr);
  221.  
  222.     // Process messages from the receiver
  223.     while let Some(message) = rx.recv().await {
  224.         println!("Processing message: {}", message);
  225.         // Handle messages as needed
  226.     }
  227. }
  228.  
  229. fn setup_wgpu_overlay(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
  230.     println!("Webgpu rendering");
  231.  
  232.     // let window = app.get_webview_window("main").unwrap();
  233.     let _window = tauri::window::WindowBuilder::new(app, "main")
  234.         .inner_size(800.0, 600.0)
  235.         .transparent(true)
  236.         .build()?;
  237.     let overlay = tauri::window::WindowBuilder::new(app, "overlay")
  238.         .parent(&_window)
  239.         .unwrap()
  240.         .inner_size(800.0, 600.0)
  241.         .transparent(true)
  242.         .always_on_top(true)
  243.         .build()?;
  244.     overlay.set_resizable(false);
  245.     overlay.set_maximizable(false);
  246.     overlay.set_minimizable(false);
  247.     overlay.set_closable(false);
  248.     overlay.set_decorations(false);
  249.     overlay.set_ignore_cursor_events(true);
  250.  
  251.     let _overlay = Arc::new(Mutex::new(overlay));
  252.  
  253.     let _webview1 = _window.add_child(
  254.         tauri::webview::WebviewBuilder::new("main1", WebviewUrl::App(Default::default()))
  255.             .transparent(true)
  256.             .auto_resize(),
  257.         LogicalPosition::new(0., 0.),
  258.         LogicalSize::new(800.0, 600.0),
  259.     )?;
  260.  
  261.     // let _webview2 = app
  262.     //     .get_window("overlay")
  263.     //     .expect("Overlay window not found")
  264.     //     .add_child(
  265.     //         tauri::webview::WebviewBuilder::new("overlay1", WebviewUrl::App(Default::default()))
  266.     //             .transparent(true)
  267.     //             .auto_resize(),
  268.     //         LogicalPosition::new(0., 0.),
  269.     //         LogicalSize::new(800.0, 600.0),
  270.     //     )?;
  271.  
  272.     let overlay_window = app.get_window("overlay").expect("Overlay window not found");
  273.  
  274.     let wgpu_state = async_runtime::block_on(WgpuState::new(overlay_window));
  275.     let wgpu_state = Arc::new(wgpu_state); // Make wgpu_state Arc<T>
  276.     app.manage(wgpu_state.clone()); // Store a clone in app state
  277.  
  278.     Ok(())
  279. }
  280.  
  281. async fn setup_app<'a>(app: &'a mut tauri::App) -> Result<(), Box<dyn Error>> {
  282.     // Setup HTTP + WebSocket server
  283.     let (tx, rx) = tokio::sync::mpsc::channel::<String>(32);
  284.  
  285.     tokio::spawn(async move {
  286.         websocket_server(tx, rx).await;
  287.     });
  288.  
  289.     Ok(())
  290. }
  291.  
  292. #[cfg_attr(mobile, tauri::mobile_entry_point)]
  293. pub fn run() {
  294.     let init = match Client::init_app(480) {
  295.         Ok(val) => {
  296.             let (client, single) = val;
  297.             let _cb = client.register_callback(|p: PersonaStateChange| {
  298.                 println!("Got callback: {:?}", p);
  299.             });
  300.  
  301.             let utils = client.utils();
  302.             println!("Utils:");
  303.             println!("AppId: {:?}", utils.app_id());
  304.             println!("UI Language: {}", utils.ui_language());
  305.  
  306.             let apps = client.apps();
  307.             println!("Apps");
  308.             println!("IsInstalled(480): {}", apps.is_app_installed(AppId(480)));
  309.             println!("InstallDir(480): {}", apps.app_install_dir(AppId(480)));
  310.             println!("BuildId: {}", apps.app_build_id());
  311.             println!("AppOwner: {:?}", apps.app_owner());
  312.             println!("Langs: {:?}", apps.available_game_languages());
  313.             println!("Lang: {}", apps.current_game_language());
  314.             println!("Beta: {:?}", apps.current_beta_name());
  315.  
  316.             let friends = client.friends();
  317.             println!("Friends");
  318.             let list = friends.get_friends(FriendFlags::IMMEDIATE);
  319.             println!("{:?}", list);
  320.             for f in &list {
  321.                 println!("Friend: {:?} - {}({:?})", f.id(), f.name(), f.state());
  322.                 friends.request_user_information(f.id(), true);
  323.             }
  324.         }
  325.         Err(err) => {
  326.             println!("Error {}", err);
  327.         }
  328.     };
  329.  
  330.     tauri::Builder::default()
  331.         .plugin(tauri_plugin_fs::init())
  332.         .setup(move |app| {
  333.             println!("setup");
  334.             let _ = setup_wgpu_overlay(app);
  335.             setup_app(app);
  336.             Ok(())
  337.         })
  338.         .invoke_handler(tauri::generate_handler![showOverlay])
  339.         .build(tauri::generate_context!())
  340.         .expect("error while running tauri application")
  341.         .run(|app_handle, event| match event {
  342.             RunEvent::WindowEvent {
  343.                 label: _,
  344.                 event: WindowEvent::Resized(size),
  345.                 ..
  346.             } => {
  347.                 let wgpu_state = app_handle.state::<Arc<WgpuState>>();
  348.                 let mut config = wgpu_state.config.lock().unwrap();
  349.                 config.width = size.width;
  350.                 config.height = size.height;
  351.                 wgpu_state.surface.configure(&wgpu_state.device, &config);
  352.             }
  353.             RunEvent::MainEventsCleared => {
  354.                 let wgpu_state = app_handle.state::<Arc<WgpuState>>();
  355.                 let overlay = app_handle
  356.                     .get_window("overlay")
  357.                     .expect("Overlay window not found");
  358.                 let _window = app_handle.get_window("main").unwrap();
  359.  
  360.                 let window_position = _window.inner_position().unwrap();
  361.                 let window_position2 = _window.outer_position().unwrap();
  362.                 let window_size = _window.inner_size().unwrap();
  363.                 let window_size2 = _window.outer_size().unwrap();
  364.  
  365.                 println!("inner_position {:?}", window_position);
  366.                 println!("outer_position {:?}", window_position2);
  367.                 println!("inner_size {:?}", window_size);
  368.                 println!("outer_size {:?}", window_size2);
  369.  
  370.                 let offsetU = 100 as u32;
  371.                 let offsetI = 100 as i32;
  372.  
  373.                 overlay
  374.                     .set_position(LogicalPosition::new(
  375.                         window_position.x + offsetI,
  376.                         window_position.y + offsetI,
  377.                     ))
  378.                     .unwrap();
  379.                 // overlay.set_position(window_position).unwrap();
  380.                 overlay
  381.                     .set_size(LogicalSize::new(
  382.                         window_size.width - offsetU,
  383.                         window_size.height - offsetU,
  384.                     ))
  385.                     .unwrap();
  386.                 // overlay.set_size(window_size).unwrap();
  387.  
  388.                 let t = Instant::now();
  389.  
  390.                 let output = match wgpu_state.surface.get_current_texture() {
  391.                     Ok(output) => output,
  392.                     Err(wgpu::SurfaceError::Lost) => {
  393.                         eprintln!("Surface lost, recreating surface...");
  394.                         return ();
  395.                     }
  396.                     Err(wgpu::SurfaceError::OutOfMemory) => {
  397.                         eprintln!("Out of memory error");
  398.                         return ();
  399.                     }
  400.                     Err(e) => {
  401.                         eprintln!("Failed to acquire next swap chain texture: {:?}", e);
  402.                         return ();
  403.                     }
  404.                 };
  405.                 let view = output
  406.                     .texture
  407.                     .create_view(&wgpu::TextureViewDescriptor::default());
  408.  
  409.                 let mut encoder = wgpu_state
  410.                     .device
  411.                     .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
  412.                 {
  413.                     let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
  414.                         label: None,
  415.                         color_attachments: &[Some(wgpu::RenderPassColorAttachment {
  416.                             view: &view,
  417.                             resolve_target: None,
  418.                             ops: wgpu::Operations {
  419.                                 load: wgpu::LoadOp::Clear(wgpu::Color::RED),
  420.                                 store: wgpu::StoreOp::Store,
  421.                             },
  422.                         })],
  423.                         depth_stencil_attachment: None,
  424.                         timestamp_writes: None,
  425.                         occlusion_query_set: None,
  426.                     });
  427.                     rpass.set_pipeline(&wgpu_state.render_pipeline);
  428.                     rpass.draw(0..3, 0..1);
  429.                 }
  430.  
  431.                 wgpu_state.queue.submit(Some(encoder.finish()));
  432.                 // output.present();
  433.  
  434.                 println!("Frame rendered in: {}ms", t.elapsed().as_millis());
  435.             }
  436.             _ => (),
  437.         });
  438. }
  439.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement