@@ -1,4 +1,4 @@
-use gpui::{Application, *};
+use gpui::{prelude::*, *};
use std::sync::Arc;
#[cfg(target_os = "macos")]
@@ -9,6 +9,7 @@ struct MetalViewExample {
pipeline_state: Option<RenderPipelineState>,
#[cfg(target_os = "macos")]
device: Option<Device>,
+ epoch: u64,
}
impl MetalViewExample {
@@ -18,46 +19,68 @@ impl MetalViewExample {
pipeline_state: None,
#[cfg(target_os = "macos")]
device: None,
+ epoch: 0,
}
}
+ fn update_epoch(&mut self, cx: &mut Context<Self>) {
+ const MAX_EPOCH: u64 = 1024;
+ self.epoch = (self.epoch + 1) % MAX_EPOCH;
+ cx.notify();
+ }
+
#[cfg(target_os = "macos")]
fn setup_metal(&mut self) {
- // Create Metal device
let device = Device::system_default().expect("no Metal device");
- // Create shader library from source
+ // Shader that properly handles viewport transformation
let shader_source = r#"
#include <metal_stdlib>
using namespace metal;
+ struct Uniforms {
+ float2 viewport_size;
+ float epoch;
+ };
+
struct VertexOut {
float4 position [[position]];
float4 color;
};
- vertex VertexOut vertex_main(uint vid [[vertex_id]]) {
+ vertex VertexOut vertex_main(
+ uint vid [[vertex_id]],
+ constant Uniforms& uniforms [[buffer(0)]]
+ ) {
VertexOut out;
- // Create a rectangle using two triangles
- // Triangle 1: top-left, top-right, bottom-left
- // Triangle 2: top-right, bottom-right, bottom-left
+ // Define a quad in pixel coordinates (0,0 to viewport_size)
float2 positions[6] = {
- float2(-1.0, 1.0), // top-left
- float2( 1.0, 1.0), // top-right
- float2(-1.0, -1.0), // bottom-left
- float2( 1.0, 1.0), // top-right
- float2( 1.0, -1.0), // bottom-right
- float2(-1.0, -1.0), // bottom-left
+ float2(0.0, 0.0), // top-left
+ float2(uniforms.viewport_size.x, 0.0), // top-right
+ float2(0.0, uniforms.viewport_size.y), // bottom-left
+ float2(uniforms.viewport_size.x, 0.0), // top-right
+ float2(uniforms.viewport_size.x, uniforms.viewport_size.y), // bottom-right
+ float2(0.0, uniforms.viewport_size.y), // bottom-left
};
- out.position = float4(positions[vid], 0.0, 1.0);
- // Create a gradient color based on position
+ // Transform from pixel coordinates to normalized device coordinates
+ float2 pos = positions[vid];
+ float2 ndc = (pos / uniforms.viewport_size) * 2.0 - 1.0;
+ ndc.y = -ndc.y; // Flip Y axis to match screen coordinates
+
+ out.position = float4(ndc, 0.0, 1.0);
+
+ // Create an animated gradient using epoch
+ float2 uv = pos / uniforms.viewport_size;
+ float time = uniforms.epoch * 0.01;
+
+ // Animate the gradient with some trigonometric functions
out.color = float4(
- (positions[vid].x + 1.0) * 0.5, // Red based on X
- (positions[vid].y + 1.0) * 0.5, // Green based on Y
- 0.7, // Blue constant
- 1.0 // Alpha
+ 0.5 + 0.5 * sin(uv.x * 3.14159 + time), // Red
+ 0.5 + 0.5 * sin(uv.y * 3.14159 + time * 1.3), // Green
+ 0.5 + 0.5 * sin((uv.x + uv.y) * 3.14159 - time * 0.7), // Blue
+ 1.0 // Full opacity
);
return out;
@@ -80,14 +103,13 @@ impl MetalViewExample {
pipeline_descriptor.set_vertex_function(Some(&vertex_function));
pipeline_descriptor.set_fragment_function(Some(&fragment_function));
- // Configure color attachment
let color_attachment = pipeline_descriptor
.color_attachments()
.object_at(0)
.unwrap();
color_attachment.set_pixel_format(metal::MTLPixelFormat::BGRA8Unorm);
- // Enable blending to work with GPUI's existing content
+ // Enable blending
color_attachment.set_blending_enabled(true);
color_attachment.set_source_rgb_blend_factor(metal::MTLBlendFactor::SourceAlpha);
color_attachment
@@ -105,7 +127,7 @@ impl MetalViewExample {
}
#[cfg(target_os = "macos")]
- fn create_render_callback(&self) -> MetalRenderCallback {
+ fn create_render_callback(&self, epoch: u64) -> MetalRenderCallback {
let pipeline_state = self.pipeline_state.clone().unwrap();
Arc::new(
@@ -127,7 +149,37 @@ impl MetalViewExample {
};
encoder.set_viewport(viewport);
- // Draw the rectangle (6 vertices for 2 triangles)
+ // Set scissor rectangle to clip to bounds
+ let scissor_rect = metal::MTLScissorRect {
+ x: (bounds.origin.x.0 * scale_factor) as u64,
+ y: (bounds.origin.y.0 * scale_factor) as u64,
+ width: (bounds.size.width.0 * scale_factor) as u64,
+ height: (bounds.size.height.0 * scale_factor) as u64,
+ };
+ encoder.set_scissor_rect(scissor_rect);
+
+ // Pass viewport size as uniform
+ #[repr(C)]
+ struct Uniforms {
+ viewport_size: [f32; 2],
+ epoch: f32,
+ }
+
+ let uniforms = Uniforms {
+ viewport_size: [
+ bounds.size.width.0 * scale_factor,
+ bounds.size.height.0 * scale_factor,
+ ],
+ epoch: epoch as f32,
+ };
+
+ encoder.set_vertex_bytes(
+ 0,
+ std::mem::size_of::<Uniforms>() as u64,
+ &uniforms as *const Uniforms as *const _,
+ );
+
+ // Draw the quad
encoder.draw_primitives(MTLPrimitiveType::Triangle, 0, 6);
},
)
@@ -135,75 +187,63 @@ impl MetalViewExample {
}
impl Render for MetalViewExample {
- fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
// Initialize Metal on first render if on macOS
#[cfg(target_os = "macos")]
if self.pipeline_state.is_none() {
self.setup_metal();
}
+ // Update epoch and request animation frame
+ self.update_epoch(cx);
+ window.request_animation_frame();
+
div()
.flex()
+ .flex_col()
.bg(rgb(0x1e1e1e))
.size_full()
- .justify_center()
- .items_center()
+ .p_8()
+ .gap_6()
+ .child(
+ div()
+ .child("Metal View Element")
+ .text_2xl()
+ .text_color(rgb(0xffffff)),
+ )
.child(
div()
- .flex_col()
- .gap_4()
- .child(
- div().flex().justify_center().child(
- div()
- .child("Metal View Example")
- .text_xl()
- .text_color(rgb(0xffffff)),
- ),
- )
- .child(
- div()
- .border_1()
- .border_color(rgb(0x444444))
- .rounded_md()
- .overflow_hidden()
- .child(
- // The Metal view
- #[cfg(target_os = "macos")]
- {
- let callback = self.create_render_callback();
- metal_view()
- .render_with_shared(callback)
- .w(px(400.0))
- .h(px(300.0))
- .bg(rgb(0x000000))
- },
- #[cfg(not(target_os = "macos"))]
- {
- // Fallback for non-macOS platforms
- div()
- .w(px(400.0))
- .h(px(300.0))
- .bg(rgb(0x222222))
- .flex()
- .justify_center()
- .items_center()
- .child(
- div()
- .child("Metal rendering is only available on macOS")
- .text_color(rgb(0x888888)),
- )
- },
- ),
- )
- .child(
- div().flex().justify_center().child(
- div()
- .child("A gradient rectangle rendered with custom Metal shaders")
- .text_sm()
- .text_color(rgb(0xaaaaaa)),
- ),
- ),
+ .child("While GPUI normally handles all Metal rendering for you, the metal_view() element gives you direct access to write custom Metal shaders and GPU drawing commands")
+ .text_color(rgb(0xaaaaaa)),
)
+ .child(
+ div()
+ .child("This is useful for special effects, custom visualizations, or when you need GPU performance that GPUI's standard elements can't provide")
+ .text_sm()
+ .text_color(rgb(0x888888)),
+ )
+ .child(div().overflow_hidden().child(
+ #[cfg(target_os = "macos")]
+ {
+ let callback = self.create_render_callback(self.epoch);
+ metal_view()
+ .render_with_shared(callback)
+ .w(px(600.0))
+ .h(px(400.0))
+ .bg(rgb(0x000000))
+ },
+ #[cfg(not(target_os = "macos"))]
+ {
+ div()
+ .w(px(600.0))
+ .h(px(400.0))
+ .bg(rgb(0x222222))
+ .flex()
+ .items_center()
+ .justify_center()
+ .child(div().child("Metal (macOS only)").text_color(rgb(0x666666)))
+ },
+ ))
}
}
@@ -211,97 +251,20 @@ fn main() {
Application::new().run(|cx: &mut App| {
let _ = cx.open_window(
WindowOptions {
- window_bounds: Some(WindowBounds::Windowed(Bounds {
- origin: Point::new(px(100.0), px(100.0)),
- size: Size {
- width: px(600.0),
- height: px(500.0),
- },
- })),
+ window_bounds: Some(WindowBounds::Windowed(Bounds::centered(
+ None,
+ size(px(900.0), px(600.0)),
+ cx,
+ ))),
titlebar: Some(TitlebarOptions {
- title: Some("Metal View Example".into()),
+ title: Some("Metal View Element".into()),
..Default::default()
}),
..Default::default()
},
|_window, cx| cx.new(|_cx| MetalViewExample::new()),
);
- });
-}
-
-// Additional example: Using MetalView for more complex rendering
-#[cfg(target_os = "macos")]
-#[allow(dead_code)]
-mod advanced_example {
- use super::*;
- use std::sync::Mutex;
-
- /// Example of a MetalView that renders an animated scene
- pub struct AnimatedMetalView {
- device: Device,
- pipeline_state: RenderPipelineState,
- frame_count: Arc<Mutex<f32>>,
- }
- impl AnimatedMetalView {
- pub fn create_animated_renderer(&self) -> MetalRenderCallback {
- let pipeline_state = self.pipeline_state.clone();
- let frame_count = self.frame_count.clone();
-
- Arc::new(
- move |encoder: &RenderCommandEncoderRef,
- _target: &TextureRef,
- bounds: Bounds<Pixels>,
- scale_factor: f32| {
- // Update animation state
- let mut count = frame_count.lock().unwrap();
- *count += 0.01;
- let time = *count;
-
- // Set pipeline and viewport
- encoder.set_render_pipeline_state(&pipeline_state);
-
- let viewport = metal::MTLViewport {
- originX: bounds.origin.x.0 as f64 * scale_factor as f64,
- originY: bounds.origin.y.0 as f64 * scale_factor as f64,
- width: bounds.size.width.0 as f64 * scale_factor as f64,
- height: bounds.size.height.0 as f64 * scale_factor as f64,
- znear: 0.0,
- zfar: 1.0,
- };
- encoder.set_viewport(viewport);
-
- // Pass time as a uniform
- encoder.set_vertex_bytes(
- 0,
- std::mem::size_of::<f32>() as u64,
- &time as *const f32 as *const _,
- );
-
- // Draw animated geometry
- encoder.draw_primitives(MTLPrimitiveType::TriangleStrip, 0, 4);
- },
- )
- }
- }
+ cx.activate(false);
+ });
}
-
-// Example usage in a component:
-// ```rust
-// struct MyApp {
-// metal_renderer: Option<MetalRenderCallback>,
-// }
-//
-// impl Render for MyApp {
-// fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
-// div()
-// .child(
-// metal_view()
-// .render_with(|encoder, target, bounds, scale_factor| {
-// // Your custom Metal rendering code here
-// })
-// .size_full()
-// )
-// }
-// }
-// ```
@@ -1,355 +0,0 @@
-use gpui::{prelude::*, *};
-use std::sync::Arc;
-
-#[cfg(target_os = "macos")]
-use metal::{Device, MTLPrimitiveType, RenderCommandEncoderRef, RenderPipelineState, TextureRef};
-
-struct MetalQuadExample {
- #[cfg(target_os = "macos")]
- pipeline_state: Option<RenderPipelineState>,
- #[cfg(target_os = "macos")]
- device: Option<Device>,
-}
-
-impl MetalQuadExample {
- fn new() -> Self {
- Self {
- #[cfg(target_os = "macos")]
- pipeline_state: None,
- #[cfg(target_os = "macos")]
- device: None,
- }
- }
-
- #[cfg(target_os = "macos")]
- fn setup_metal(&mut self) {
- let device = Device::system_default().expect("no Metal device");
-
- // Shader that properly handles viewport transformation
- let shader_source = r#"
- #include <metal_stdlib>
- using namespace metal;
-
- struct Uniforms {
- float2 viewport_size;
- };
-
- struct VertexOut {
- float4 position [[position]];
- float4 color;
- };
-
- vertex VertexOut vertex_main(
- uint vid [[vertex_id]],
- constant Uniforms& uniforms [[buffer(0)]]
- ) {
- VertexOut out;
-
- // Define a quad in pixel coordinates (0,0 to viewport_size)
- float2 positions[6] = {
- float2(0.0, 0.0), // top-left
- float2(uniforms.viewport_size.x, 0.0), // top-right
- float2(0.0, uniforms.viewport_size.y), // bottom-left
- float2(uniforms.viewport_size.x, 0.0), // top-right
- float2(uniforms.viewport_size.x, uniforms.viewport_size.y), // bottom-right
- float2(0.0, uniforms.viewport_size.y), // bottom-left
- };
-
- // Transform from pixel coordinates to normalized device coordinates
- float2 pos = positions[vid];
- float2 ndc = (pos / uniforms.viewport_size) * 2.0 - 1.0;
- ndc.y = -ndc.y; // Flip Y axis to match screen coordinates
-
- out.position = float4(ndc, 0.0, 1.0);
-
- // Create a nice gradient
- float2 uv = pos / uniforms.viewport_size;
- out.color = float4(
- uv.x, // Red increases left to right
- uv.y, // Green increases top to bottom
- 1.0 - uv.x, // Blue decreases left to right
- 1.0 // Full opacity
- );
-
- return out;
- }
-
- fragment float4 fragment_main(VertexOut in [[stage_in]]) {
- return in.color;
- }
- "#;
-
- let library = device
- .new_library_with_source(shader_source, &metal::CompileOptions::new())
- .expect("Failed to create shader library");
-
- let vertex_function = library.get_function("vertex_main", None).unwrap();
- let fragment_function = library.get_function("fragment_main", None).unwrap();
-
- // Create pipeline state
- let pipeline_descriptor = metal::RenderPipelineDescriptor::new();
- pipeline_descriptor.set_vertex_function(Some(&vertex_function));
- pipeline_descriptor.set_fragment_function(Some(&fragment_function));
-
- let color_attachment = pipeline_descriptor
- .color_attachments()
- .object_at(0)
- .unwrap();
- color_attachment.set_pixel_format(metal::MTLPixelFormat::BGRA8Unorm);
-
- // Enable blending
- color_attachment.set_blending_enabled(true);
- color_attachment.set_source_rgb_blend_factor(metal::MTLBlendFactor::SourceAlpha);
- color_attachment
- .set_destination_rgb_blend_factor(metal::MTLBlendFactor::OneMinusSourceAlpha);
- color_attachment.set_source_alpha_blend_factor(metal::MTLBlendFactor::One);
- color_attachment
- .set_destination_alpha_blend_factor(metal::MTLBlendFactor::OneMinusSourceAlpha);
-
- let pipeline_state = device
- .new_render_pipeline_state(&pipeline_descriptor)
- .expect("Failed to create pipeline state");
-
- self.device = Some(device);
- self.pipeline_state = Some(pipeline_state);
- }
-
- #[cfg(target_os = "macos")]
- fn create_render_callback(&self) -> MetalRenderCallback {
- let pipeline_state = self.pipeline_state.clone().unwrap();
-
- Arc::new(
- move |encoder: &RenderCommandEncoderRef,
- _target: &TextureRef,
- bounds: Bounds<Pixels>,
- scale_factor: f32| {
- // Set the pipeline state
- encoder.set_render_pipeline_state(&pipeline_state);
-
- // Set viewport to match element bounds
- let viewport = metal::MTLViewport {
- originX: bounds.origin.x.0 as f64 * scale_factor as f64,
- originY: bounds.origin.y.0 as f64 * scale_factor as f64,
- width: bounds.size.width.0 as f64 * scale_factor as f64,
- height: bounds.size.height.0 as f64 * scale_factor as f64,
- znear: 0.0,
- zfar: 1.0,
- };
- encoder.set_viewport(viewport);
-
- // Set scissor rectangle to clip to bounds
- let scissor_rect = metal::MTLScissorRect {
- x: (bounds.origin.x.0 * scale_factor) as u64,
- y: (bounds.origin.y.0 * scale_factor) as u64,
- width: (bounds.size.width.0 * scale_factor) as u64,
- height: (bounds.size.height.0 * scale_factor) as u64,
- };
- encoder.set_scissor_rect(scissor_rect);
-
- // Pass viewport size as uniform
- #[repr(C)]
- struct Uniforms {
- viewport_size: [f32; 2],
- }
-
- let uniforms = Uniforms {
- viewport_size: [
- bounds.size.width.0 * scale_factor,
- bounds.size.height.0 * scale_factor,
- ],
- };
-
- encoder.set_vertex_bytes(
- 0,
- std::mem::size_of::<Uniforms>() as u64,
- &uniforms as *const Uniforms as *const _,
- );
-
- // Draw the quad
- encoder.draw_primitives(MTLPrimitiveType::Triangle, 0, 6);
- },
- )
- }
-}
-
-impl Render for MetalQuadExample {
- fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
- #[cfg(target_os = "macos")]
- if self.pipeline_state.is_none() {
- self.setup_metal();
- }
-
- div()
- .flex()
- .flex_col()
- .bg(rgb(0x1e1e1e))
- .size_full()
- .p_8()
- .gap_6()
- .child(
- div()
- .child("Metal Quad Example")
- .text_2xl()
- .text_color(rgb(0xffffff)),
- )
- .child(
- div()
- .child("This example demonstrates proper coordinate handling in MetalView")
- .text_color(rgb(0xaaaaaa)),
- )
- .child(
- div()
- .flex()
- .gap_4()
- .child(
- div()
- .flex_col()
- .gap_2()
- .flex_1()
- .child(
- div()
- .child("Small MetalView (200x150)")
- .text_sm()
- .text_color(rgb(0xcccccc)),
- )
- .child(
- div()
- .border_1()
- .border_color(rgb(0x444444))
- .rounded_md()
- .overflow_hidden()
- .child(
- #[cfg(target_os = "macos")]
- {
- let callback = self.create_render_callback();
- metal_view()
- .render_with_shared(callback)
- .w(px(200.0))
- .h(px(150.0))
- .bg(rgb(0x000000))
- },
- #[cfg(not(target_os = "macos"))]
- {
- div()
- .w(px(200.0))
- .h(px(150.0))
- .bg(rgb(0x222222))
- .flex()
- .items_center()
- .justify_center()
- .child(
- div()
- .child("Metal (macOS only)")
- .text_color(rgb(0x666666)),
- )
- },
- ),
- ),
- )
- .child(
- div()
- .flex_col()
- .gap_2()
- .flex_1()
- .child(
- div()
- .child("Large MetalView (400x300)")
- .text_sm()
- .text_color(rgb(0xcccccc)),
- )
- .child(
- div()
- .border_1()
- .border_color(rgb(0x444444))
- .rounded_md()
- .overflow_hidden()
- .child(
- #[cfg(target_os = "macos")]
- {
- let callback = self.create_render_callback();
- metal_view()
- .render_with_shared(callback)
- .w(px(400.0))
- .h(px(300.0))
- .bg(rgb(0x000000))
- },
- #[cfg(not(target_os = "macos"))]
- {
- div()
- .w(px(400.0))
- .h(px(300.0))
- .bg(rgb(0x222222))
- .flex()
- .items_center()
- .justify_center()
- .child(
- div()
- .child("Metal (macOS only)")
- .text_color(rgb(0x666666)),
- )
- },
- ),
- ),
- ),
- )
- .child(
- div().p_4().bg(rgb(0x2a2a2a)).rounded_md().child(
- div()
- .flex()
- .flex_col()
- .gap_2()
- .child(
- div()
- .child("Key Features:")
- .text_base()
- .font_weight(FontWeight::SEMIBOLD)
- .text_color(rgb(0xffffff)),
- )
- .child(
- div()
- .child("• Proper coordinate transformation from pixels to NDC")
- .text_sm()
- .text_color(rgb(0xaaaaaa)),
- )
- .child(
- div()
- .child("• Scissor rectangle to clip content to bounds")
- .text_sm()
- .text_color(rgb(0xaaaaaa)),
- )
- .child(
- div()
- .child("• Viewport size passed as uniform to shader")
- .text_sm()
- .text_color(rgb(0xaaaaaa)),
- )
- .child(
- div()
- .child("• Gradient fills entire MetalView bounds")
- .text_sm()
- .text_color(rgb(0xaaaaaa)),
- ),
- ),
- )
- }
-}
-
-fn main() {
- Application::new().run(|cx: &mut App| {
- let _ = cx.open_window(
- WindowOptions {
- window_bounds: Some(WindowBounds::Windowed(Bounds::centered(
- None,
- size(px(900.0), px(600.0)),
- cx,
- ))),
- titlebar: Some(TitlebarOptions {
- title: Some("Metal Quad Example".into()),
- ..Default::default()
- }),
- ..Default::default()
- },
- |_window, cx| cx.new(|_cx| MetalQuadExample::new()),
- );
- });
-}
@@ -1,198 +0,0 @@
-use gpui::{prelude::*, *};
-
-struct MetalViewSimpleExample {
- show_metal_view: bool,
-}
-
-impl MetalViewSimpleExample {
- fn new() -> Self {
- Self {
- show_metal_view: true,
- }
- }
-}
-
-impl Render for MetalViewSimpleExample {
- fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
- div()
- .flex()
- .flex_col()
- .bg(rgb(0x1e1e1e))
- .size_full()
- .p_8()
- .gap_4()
- .child(
- div()
- .child("MetalView Simple Example")
- .text_2xl()
- .text_color(rgb(0xffffff)),
- )
- .child(
- div()
- .flex()
- .gap_2()
- .items_center()
- .child(
- div()
- .id("toggle-button")
- .px_3()
- .py_1()
- .bg(rgb(0x3b82f6))
- .hover(|style| style.bg(rgb(0x2563eb)))
- .rounded_md()
- .cursor_pointer()
- .on_click(cx.listener(|this, _event, _window, cx| {
- this.show_metal_view = !this.show_metal_view;
- cx.notify();
- }))
- .child(div().child("Toggle MetalView").text_color(rgb(0xffffff))),
- )
- .child(
- div()
- .child(format!(
- "MetalView is: {}",
- if self.show_metal_view {
- "visible"
- } else {
- "hidden"
- }
- ))
- .text_color(rgb(0xaaaaaa)),
- ),
- )
- .child(
- div()
- .flex()
- .flex_col()
- .gap_4()
- .p_4()
- .bg(rgb(0x2a2a2a))
- .rounded_md()
- .child(
- div()
- .child("Container with MetalView")
- .text_lg()
- .text_color(rgb(0xffffff)),
- )
- .when(self.show_metal_view, |parent| {
- parent.child(
- div()
- .border_2()
- .border_color(rgb(0x444444))
- .rounded_md()
- .overflow_hidden()
- .child(
- #[cfg(target_os = "macos")]
- {
- metal_view()
- .w_full()
- .h(px(200.0))
- .bg(rgb(0x1a1a1a))
- .render_with(
- |_encoder, _target, _bounds, _scale_factor| {
- // This callback would contain custom Metal rendering code
- // For now, it's just a placeholder
- },
- )
- },
- #[cfg(not(target_os = "macos"))]
- {
- div()
- .w_full()
- .h(px(200.0))
- .bg(rgb(0x1a1a1a))
- .flex()
- .items_center()
- .justify_center()
- .child(
- div()
- .child("MetalView (macOS only)")
- .text_color(rgb(0x666666)),
- )
- },
- ),
- )
- })
- .child(
- div()
- .flex()
- .gap_4()
- .child(
- div().flex_1().p_3().bg(rgb(0x333333)).rounded_md().child(
- div()
- .child("Regular GPUI content")
- .text_sm()
- .text_color(rgb(0xcccccc)),
- ),
- )
- .child(
- div().flex_1().p_3().bg(rgb(0x333333)).rounded_md().child(
- div()
- .child("Can be mixed with MetalView")
- .text_sm()
- .text_color(rgb(0xcccccc)),
- ),
- ),
- ),
- )
- .child(
- div().mt_4().p_4().bg(rgb(0x2a2a2a)).rounded_md().child(
- div()
- .flex()
- .flex_col()
- .gap_2()
- .child(
- div()
- .child("Notes:")
- .text_base()
- .font_weight(FontWeight::SEMIBOLD)
- .text_color(rgb(0xffffff)),
- )
- .child(
- div()
- .child("• MetalView integrates with GPUI's layout system")
- .text_sm()
- .text_color(rgb(0xaaaaaa)),
- )
- .child(
- div()
- .child("• It can be styled with the same methods as other elements")
- .text_sm()
- .text_color(rgb(0xaaaaaa)),
- )
- .child(
- div()
- .child("• On macOS, it would render custom Metal content")
- .text_sm()
- .text_color(rgb(0xaaaaaa)),
- )
- .child(
- div()
- .child("• On other platforms, a fallback can be provided")
- .text_sm()
- .text_color(rgb(0xaaaaaa)),
- ),
- ),
- )
- }
-}
-
-fn main() {
- Application::new().run(|cx: &mut App| {
- let _ = cx.open_window(
- WindowOptions {
- window_bounds: Some(WindowBounds::Windowed(Bounds::centered(
- None,
- size(px(800.0), px(600.0)),
- cx,
- ))),
- titlebar: Some(TitlebarOptions {
- title: Some("MetalView Simple Example".into()),
- ..Default::default()
- }),
- ..Default::default()
- },
- |_window, cx| cx.new(|_cx| MetalViewSimpleExample::new()),
- );
- });
-}