diff --git a/src/gui.rs b/src/gui.rs index d2c1613..c5c461e 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -1,5 +1,7 @@ use crate::{parameters::PluginParams, window::EditorWindow}; -use baseview::{Event, EventStatus, MouseButton, MouseEvent, WindowEvent, WindowHandler}; +use baseview::{ + Event, EventStatus, MouseButton, MouseEvent, WindowEvent, WindowHandler, gl::GlContext, +}; use ebu_dsp::Rect; use femtovg::{Canvas, Color, ImageFlags, ImageId, Paint, Path, renderer::OpenGl}; use nih_plug::prelude::*; @@ -19,13 +21,13 @@ const FRESHENER_FRAME_HEIGHT: f32 = 144.0; pub struct PluginGui { // font: FontId, params: Arc, - canvas: Canvas, + canvas: Option>, _gui_context: Arc, scaling_factor: f32, - freshener_image: ImageId, - not_so_fresh_image: ImageId, - fresh_dumbledore_image: ImageId, + freshener_image: Option, + not_so_fresh_image: Option, + fresh_dumbledore_image: Option, freshener_bounds: Rect, @@ -36,39 +38,39 @@ pub struct PluginGui { dragging: bool, } +fn create_canvas( + context: &GlContext, + params: &PluginParams, + scaling_factor: f32, +) -> Result, &'static str> { + unsafe { + context.make_current(); + } + let renderer = unsafe { OpenGl::new_from_function(|s| context.get_proc_address(s)) } + .map_err(|_| "Failed to create OpenGL renderer")?; + let mut canvas = Canvas::new(renderer).map_err(|_| "Failed to create femtovg canvas")?; + let (width, height) = params.editor_state.size(); + canvas.set_size(width, height, scaling_factor); + unsafe { + context.make_not_current(); + } + Ok(canvas) +} + impl PluginGui { pub fn new( window: &mut baseview::Window<'_>, gui_context: Arc, params: Arc, scaling_factor: f32, - ) -> Result { - let context = window - .gl_context() - .ok_or("Failed to get window OpenGL context")?; - unsafe { - context.make_current(); - } - let renderer = unsafe { OpenGl::new_from_function(|s| context.get_proc_address(s)) } - .map_err(|_| "Failed to create femtovg renderer")?; - let mut canvas = Canvas::new(renderer).map_err(|_| "Failed to create femtovg canvas")?; - let (width, height) = params.editor_state.size(); + ) -> Self { + let canvas = if let Some(context) = window.gl_context() { + create_canvas(context, ¶ms, scaling_factor).ok() + } else { + None + }; - canvas.set_size(width, height, scaling_factor); - let le_fresh = canvas - .load_image_mem(FRESHENER_IMAGE, ImageFlags::empty()) - .map_err(|_| "Failed to load le fresh")?; - let not_so_fresh_image = canvas - .load_image_mem(NOT_SO_FRESH_BG_IMAGE, ImageFlags::empty()) - .map_err(|_| "Failed to load not so fresh")?; - let fresh_dumbledore_image = canvas - .load_image_mem(FRESH_DUMBLEDORE_BG_IMAGE, ImageFlags::empty()) - .map_err(|_| "Failed to load fresh dumbledore")?; - - unsafe { - context.make_not_current(); - } - Ok(Self { + let this = Self { //font, params, canvas, @@ -79,16 +81,31 @@ impl PluginGui { drag_start_mouse_pos: (0.0, 0.0), drag_start_parameter_value: 0.0, dragging: false, - freshener_image: le_fresh, - fresh_dumbledore_image, - not_so_fresh_image, + freshener_image: None, + fresh_dumbledore_image: None, + not_so_fresh_image: None, freshener_bounds: Rect { x: 120.0, y: 20.0, width: FRESHENER_FRAME_WIDTH, height: FRESHENER_FRAME_HEIGHT, }, - }) + }; + + /* + if let Some(canvas) = canvas { + this.freshener_image = canvas + .load_image_mem(FRESHENER_IMAGE, ImageFlags::empty()) + .map_err(|_| "Failed to load le fresh")?; + let not_so_fresh_image = canvas + .load_image_mem(NOT_SO_FRESH_BG_IMAGE, ImageFlags::empty()) + .map_err(|_| "Failed to load not so fresh")?; + let fresh_dumbledore_image = canvas + .load_image_mem(FRESH_DUMBLEDORE_BG_IMAGE, ImageFlags::empty()) + .map_err(|_| "Failed to load fresh dumbledore")?; + } + */ + this } } @@ -96,6 +113,10 @@ impl WindowHandler for PluginGui { fn on_frame(&mut self, window: &mut baseview::Window) { const WINDOW_WIDTH: f32 = EditorWindow::WINDOW_SIZE.0 as f32; const WINDOW_HEIGHT: f32 = EditorWindow::WINDOW_SIZE.1 as f32; + if self.canvas.is_none() { + return; + } + let canvas = self.canvas.as_mut().unwrap(); if !self.dirty { //return; @@ -111,10 +132,9 @@ impl WindowHandler for PluginGui { unsafe { context.make_current(); } - let (width, height) = (self.canvas.width(), self.canvas.height()); - self.canvas.reset(); - self.canvas - .clear_rect(0, 0, width, height, Color::rgbaf(0.0, 0.0, 0.0, 1.0)); + let (width, height) = (canvas.width(), canvas.height()); + canvas.reset(); + canvas.clear_rect(0, 0, width, height, Color::rgbaf(0.0, 0.0, 0.0, 1.0)); let mut full_window_path = Path::new(); full_window_path.rect( @@ -132,7 +152,7 @@ impl WindowHandler for PluginGui { self.freshener_bounds.height, ); - let bbox = self.canvas.path_bbox(&freshener_path); + let bbox = canvas.path_bbox(&freshener_path); let frame_index = (self.params.freshness.unmodulated_normalized_value() * (FRESHENER_FRAMES - 1) as f32) @@ -140,45 +160,51 @@ impl WindowHandler for PluginGui { let frame_x = (frame_index % FRESHENER_FRAMES_X as f32).floor(); let frame_y = (frame_index / FRESHENER_FRAMES_X as f32).floor(); - self.canvas.fill_path( - &full_window_path, - &Paint::image( - self.not_so_fresh_image, - 0.0, - 0.0, - WINDOW_WIDTH, - WINDOW_HEIGHT, - 0.0, - 1.0, - ), - ); - self.canvas.fill_path( - &full_window_path, - &Paint::image( - self.fresh_dumbledore_image, - 0.0, - 0.0, - WINDOW_WIDTH, - WINDOW_HEIGHT, - 0.0, - self.params.freshness.unmodulated_normalized_value(), - ), - ); + if let Some(not_so_fresh) = self.not_so_fresh_image { + canvas.fill_path( + &full_window_path, + &Paint::image( + not_so_fresh, + 0.0, + 0.0, + WINDOW_WIDTH, + WINDOW_HEIGHT, + 0.0, + 1.0, + ), + ); + } + if let Some(fresh_dumbledore) = self.fresh_dumbledore_image { + canvas.fill_path( + &full_window_path, + &Paint::image( + fresh_dumbledore, + 0.0, + 0.0, + WINDOW_WIDTH, + WINDOW_HEIGHT, + 0.0, + self.params.freshness.unmodulated_normalized_value(), + ), + ); + } - self.canvas.fill_path( - &freshener_path, - &Paint::image( - self.freshener_image, - bbox.minx - frame_x * FRESHENER_FRAME_WIDTH, - bbox.miny - frame_y * FRESHENER_FRAME_HEIGHT, - self.freshener_bounds.width * FRESHENER_FRAMES_X as f32, - self.freshener_bounds.height * FRESHENER_FRAMES_Y as f32, - 0.0, - 1.0, - ), - ); + if let Some(freshener) = self.freshener_image { + canvas.fill_path( + &freshener_path, + &Paint::image( + freshener, + bbox.minx - frame_x * FRESHENER_FRAME_WIDTH, + bbox.miny - frame_y * FRESHENER_FRAME_HEIGHT, + self.freshener_bounds.width * FRESHENER_FRAMES_X as f32, + self.freshener_bounds.height * FRESHENER_FRAMES_Y as f32, + 0.0, + 1.0, + ), + ); + } - self.canvas.flush(); + canvas.flush(); context.swap_buffers(); unsafe { context.make_not_current(); @@ -195,8 +221,9 @@ impl WindowHandler for PluginGui { match event { Event::Window(WindowEvent::Resized(size)) => { let phys_size = size.physical_size(); - self.canvas - .set_size(phys_size.width, phys_size.height, self.scaling_factor); + if let Some(canvas) = self.canvas.as_mut() { + canvas.set_size(phys_size.width, phys_size.height, self.scaling_factor); + } self.dirty = true; } Event::Mouse(MouseEvent::CursorMoved { position, .. }) => { diff --git a/src/window.rs b/src/window.rs index 4e5e4e5..21708da 100644 --- a/src/window.rs +++ b/src/window.rs @@ -49,10 +49,7 @@ impl Editor for EditorWindow { ..Default::default() }) }, move |window: &mut baseview::Window<'_>| -> PluginGui { - match PluginGui::new(window, gui_context, params, scaling_factor.unwrap_or(1.0)) { - Err(err) => { nih_error!("Failed to create plugin: {err}"); panic!("{err}"); } - Ok(plug) => plug - } + PluginGui::new(window, gui_context, params, scaling_factor.unwrap_or(1.0)) }); self.params.editor_state.open.store(true, Ordering::Release); Box::new(EditorHandle {