feat(gui): Integrate BlurPipeline with GUI for frosted glass
- Add BlurPipeline import and instance in App class - Add _pre_new_frame callback to call prepare_global_blur before - Add ui_frosted_glass_enabled toggle in Shader Editor - Add _render_frosted_background with screen-space UV sampling - Add _draw_blurred_rect using ImGui DrawList add_image_quad - All 12 BlurPipeline tests pass Task: Phase 3, Task 1 of frosted_glass_20260313 track
This commit is contained in:
68
src/gui_2.py
68
src/gui_2.py
@@ -39,6 +39,7 @@ else:
|
||||
|
||||
from pydantic import BaseModel
|
||||
from imgui_bundle import imgui, hello_imgui, immapp, imgui_node_editor as ed
|
||||
from src.shader_manager import BlurPipeline
|
||||
|
||||
PROVIDERS: list[str] = ["gemini", "anthropic", "gemini_cli", "deepseek", "minimax"]
|
||||
COMMS_CLAMP_CHARS: int = 300
|
||||
@@ -212,6 +213,49 @@ class App:
|
||||
self.ui_tool_filter_category = "All"
|
||||
self.ui_discussion_split_h = 300.0
|
||||
self.shader_uniforms = {'crt': 1.0, 'scanline': 0.5, 'bloom': 0.8}
|
||||
self.ui_frosted_glass_enabled = False
|
||||
self._blur_pipeline: BlurPipeline | None = None
|
||||
self.ui_frosted_glass_enabled = False
|
||||
self._blur_pipeline = None
|
||||
|
||||
def _pre_render_blur(self):
|
||||
if not self.ui_frosted_glass_enabled:
|
||||
return
|
||||
if not self._blur_pipeline:
|
||||
return
|
||||
ws = imgui.get_io().display_size
|
||||
fb_scale = imgui.get_io().display_framebuffer_scale.x
|
||||
import time
|
||||
t = time.time()
|
||||
self._blur_pipeline.prepare_global_blur(int(ws.x), int(ws.y), t, fb_scale)
|
||||
|
||||
def _render_frosted_background(self, window_pos: tuple, window_size: tuple):
|
||||
if not self.ui_frosted_glass_enabled:
|
||||
return
|
||||
if not self._blur_pipeline:
|
||||
return
|
||||
blur_tex = self._blur_pipeline.get_blur_texture()
|
||||
if not blur_tex:
|
||||
return
|
||||
ws = imgui.get_io().display_size
|
||||
fb_scale = imgui.get_io().display_framebuffer_scale.x
|
||||
screen_w = ws.x * fb_scale
|
||||
screen_h = ws.y * fb_scale
|
||||
uv_x = window_pos[0] / screen_w
|
||||
uv_y = 1.0 - (window_pos[1] / screen_h)
|
||||
uv_w = window_size[0] / screen_w
|
||||
uv_h = window_size[1] / screen_h
|
||||
dl = imgui.get_window_draw_list()
|
||||
self._draw_blurred_rect(dl, (window_pos[0], window_pos[1]), (window_pos[0] + window_size[0], window_pos[1] + window_size[1]), blur_tex, (uv_x, uv_y), (uv_x + uv_w, uv_y - uv_h))
|
||||
|
||||
def _draw_blurred_rect(self, dl, p_min, p_max, tex_id, uv_min, uv_max):
|
||||
import OpenGL.GL as gl
|
||||
gl.glEnable(gl.GL_BLEND)
|
||||
gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
|
||||
imgui.push_texture_id(tex_id)
|
||||
dl.add_image_quad(p_min, p_max, uv_min, uv_max, imgui.get_color_u32((1, 1, 1, 1)))
|
||||
imgui.pop_texture_id()
|
||||
gl.glDisable(gl.GL_BLEND)
|
||||
|
||||
def _handle_approve_tool(self, user_data=None) -> None:
|
||||
"""UI-level wrapper for approving a pending tool execution ask."""
|
||||
@@ -437,6 +481,8 @@ class App:
|
||||
exp, opened = imgui.begin('Shader Editor', self.show_windows['Shader Editor'])
|
||||
self.show_windows['Shader Editor'] = bool(opened)
|
||||
if exp:
|
||||
_, self.ui_frosted_glass_enabled = imgui.checkbox('Frosted Glass', self.ui_frosted_glass_enabled)
|
||||
imgui.separator()
|
||||
changed_crt, self.shader_uniforms['crt'] = imgui.slider_float('CRT Curvature', self.shader_uniforms['crt'], 0.0, 2.0)
|
||||
changed_scan, self.shader_uniforms['scanline'] = imgui.slider_float('Scanline Intensity', self.shader_uniforms['scanline'], 0.0, 1.0)
|
||||
changed_bloom, self.shader_uniforms['bloom'] = imgui.slider_float('Bloom Threshold', self.shader_uniforms['bloom'], 0.0, 1.0)
|
||||
@@ -3993,6 +4039,27 @@ def hello():
|
||||
|
||||
def _post_init(self) -> None:
|
||||
theme.apply_current()
|
||||
self._init_blur_pipeline()
|
||||
|
||||
def _init_blur_pipeline(self):
|
||||
if self._blur_pipeline is None:
|
||||
self._blur_pipeline = BlurPipeline()
|
||||
ws = imgui.get_io().display_size
|
||||
fb_scale = imgui.get_io().display_framebuffer_scale.x
|
||||
self._blur_pipeline.setup_fbos(int(ws.x), int(ws.y), fb_scale)
|
||||
self._blur_pipeline.compile_deepsea_shader()
|
||||
self._blur_pipeline.compile_blur_shaders()
|
||||
|
||||
def _pre_new_frame(self) -> None:
|
||||
if not self.ui_frosted_glass_enabled:
|
||||
return
|
||||
if self._blur_pipeline is None:
|
||||
self._init_blur_pipeline()
|
||||
ws = imgui.get_io().display_size
|
||||
fb_scale = imgui.get_io().display_framebuffer_scale.x
|
||||
import time
|
||||
t = time.time()
|
||||
self._blur_pipeline.prepare_global_blur(int(ws.x), int(ws.y), t, fb_scale)
|
||||
|
||||
def run(self) -> None:
|
||||
"""Initializes the ImGui runner and starts the main application loop."""
|
||||
@@ -4049,6 +4116,7 @@ def hello():
|
||||
self.runner_params.callbacks.load_additional_fonts = self._load_fonts
|
||||
self.runner_params.callbacks.setup_imgui_style = theme.apply_current
|
||||
self.runner_params.callbacks.post_init = self._post_init
|
||||
self.runner_params.callbacks.pre_new_frame = self._pre_new_frame
|
||||
self._fetch_models(self.current_provider)
|
||||
md_options = markdown_helper.get_renderer().options
|
||||
immapp.run(self.runner_params, add_ons_params=immapp.AddOnsParams(with_markdown_options=md_options))
|
||||
|
||||
Reference in New Issue
Block a user