pub struct AnimatedValues {
pub opacity: f32,
pub translate: UiPoint,
pub scale: f32,
pub morph: f32,
}Fields§
§opacity: f32§translate: UiPoint§scale: f32§morph: f32Implementations§
Source§impl AnimatedValues
impl AnimatedValues
Sourcepub const fn new(opacity: f32, translate: UiPoint, scale: f32) -> Self
pub const fn new(opacity: f32, translate: UiPoint, scale: f32) -> Self
Examples found in repository?
examples/showcase.rs (line 5028)
5020fn animation_blend_machine(
5021 input: &'static str,
5022 value: f32,
5023 translate: UiPoint,
5024 start_scale: f32,
5025 end_scale: f32,
5026 end_opacity: f32,
5027) -> AnimationMachine {
5028 let start_values = AnimatedValues::new(0.45, UiPoint::new(0.0, 0.0), start_scale);
5029 let end_values = AnimatedValues::new(end_opacity, translate, end_scale).with_morph(1.0);
5030 AnimationMachine::new(
5031 vec![
5032 AnimationState::new("start", start_values),
5033 AnimationState::new("end", end_values),
5034 ],
5035 Vec::new(),
5036 "start",
5037 )
5038 .unwrap_or_else(|_| AnimationMachine::single_state("start", start_values))
5039 .with_number_input(input, value)
5040 .with_blend_binding(AnimationBlendBinding::new(input, "start", "end"))
5041}
5042
5043fn animation_open_machine(open: bool) -> AnimationMachine {
5044 let closed_values = AnimatedValues::new(0.35, UiPoint::new(0.0, 0.0), 1.0);
5045 let open_values = AnimatedValues::new(1.0, UiPoint::new(0.0, 0.0), 1.0);
5046 let fallback_values = if open { open_values } else { closed_values };
5047 AnimationMachine::new(
5048 vec![
5049 AnimationState::new("closed", closed_values),
5050 AnimationState::new("open", open_values),
5051 ],
5052 vec![
5053 AnimationTransition::when(
5054 "closed",
5055 "open",
5056 AnimationCondition::bool(ANIMATION_INPUT_OPEN, true),
5057 0.18,
5058 ),
5059 AnimationTransition::when(
5060 "open",
5061 "closed",
5062 AnimationCondition::bool(ANIMATION_INPUT_OPEN, false),
5063 0.14,
5064 ),
5065 ],
5066 "closed",
5067 )
5068 .unwrap_or_else(|_| AnimationMachine::single_state("closed", fallback_values))
5069 .with_bool_input(ANIMATION_INPUT_OPEN, open)
5070}
5071
5072fn animation_interaction_machine() -> AnimationMachine {
5073 let rest_values = AnimatedValues::new(0.72, UiPoint::new(0.0, 0.0), 1.0);
5074 let right_values = AnimatedValues::new(1.0, UiPoint::new(0.0, 0.0), 1.0).with_morph(1.0);
5075 AnimationMachine::new(
5076 vec![
5077 AnimationState::new("rest", rest_values),
5078 AnimationState::new("right", right_values),
5079 ],
5080 Vec::new(),
5081 "rest",
5082 )
5083 .unwrap_or_else(|_| AnimationMachine::single_state("rest", rest_values))
5084 .with_number_input(ANIMATION_INPUT_POINTER_NORM_X, 0.0)
5085 .with_blend_binding(AnimationBlendBinding::new(
5086 ANIMATION_INPUT_POINTER_NORM_X,
5087 "rest",
5088 "right",
5089 ))
5090}
5091
5092fn animation_interaction_primitives(
5093 fill: ColorRgba,
5094 size: f32,
5095 offset: UiPoint,
5096) -> Vec<ScenePrimitive> {
5097 vec![
5098 ScenePrimitive::MorphPolygon {
5099 from_points: animation_square_points(size, offset),
5100 to_points: animation_pentagon_points(size, offset),
5101 amount: 0.0,
5102 fill,
5103 stroke: Some(StrokeStyle::new(color(236, 244, 255), 1.0)),
5104 },
5105 ScenePrimitive::Circle {
5106 center: UiPoint::new(offset.x + size * 0.34, offset.y + size * 0.30),
5107 radius: size * 0.10,
5108 fill: color(244, 248, 255),
5109 stroke: None,
5110 },
5111 ]
5112}
5113
5114fn animation_orb_primitives(fill: ColorRgba, size: f32, offset: UiPoint) -> Vec<ScenePrimitive> {
5115 let center = size * 0.5;
5116 let radius = size * 0.44;
5117 vec![
5118 ScenePrimitive::Circle {
5119 center: UiPoint::new(offset.x + center, offset.y + center),
5120 radius,
5121 fill,
5122 stroke: Some(StrokeStyle::new(color(236, 244, 255), 1.0)),
5123 },
5124 ScenePrimitive::Circle {
5125 center: UiPoint::new(offset.x + size * 0.34, offset.y + size * 0.30),
5126 radius: size * 0.12,
5127 fill: color(244, 248, 255),
5128 stroke: None,
5129 },
5130 ]
5131}
5132
5133fn animation_morph_shape_primitives(
5134 fill: ColorRgba,
5135 size: f32,
5136 offset: UiPoint,
5137 amount: f32,
5138) -> Vec<ScenePrimitive> {
5139 vec![ScenePrimitive::MorphPolygon {
5140 from_points: animation_square_points(size, offset),
5141 to_points: animation_pentagon_points(size, offset),
5142 amount,
5143 fill,
5144 stroke: Some(StrokeStyle::new(color(226, 246, 236), 1.0)),
5145 }]
5146}
5147
5148fn animation_square_points(size: f32, offset: UiPoint) -> Vec<UiPoint> {
5149 let inset = size * 0.08;
5150 let left = offset.x + inset;
5151 let top = offset.y + inset;
5152 let right = offset.x + size - inset;
5153 let bottom = offset.y + size - inset;
5154 let center_x = offset.x + size * 0.5;
5155 vec![
5156 UiPoint::new(center_x, top),
5157 UiPoint::new(right, top),
5158 UiPoint::new(right, bottom),
5159 UiPoint::new(left, bottom),
5160 UiPoint::new(left, top),
5161 ]
5162}
5163
5164fn animation_pentagon_points(size: f32, offset: UiPoint) -> Vec<UiPoint> {
5165 let center = size * 0.5;
5166 let radius = size * 0.46;
5167 (0..5)
5168 .map(|index| {
5169 let angle = -std::f32::consts::FRAC_PI_2 + index as f32 * std::f32::consts::TAU / 5.0;
5170 UiPoint::new(
5171 offset.x + center + angle.cos() * radius,
5172 offset.y + center + angle.sin() * radius,
5173 )
5174 })
5175 .collect()
5176}
5177
5178fn animation_panel_primitives(offset: UiPoint) -> Vec<ScenePrimitive> {
5179 vec![ScenePrimitive::Rect(
5180 PaintRect::solid(
5181 UiRect::new(
5182 offset.x,
5183 offset.y,
5184 ANIMATION_PANEL_WIDTH,
5185 ANIMATION_PANEL_HEIGHT,
5186 ),
5187 color(232, 186, 88),
5188 )
5189 .stroke(AlignedStroke::inside(StrokeStyle::new(
5190 color(255, 226, 154),
5191 1.0,
5192 )))
5193 .corner_radii(CornerRadii::uniform(6.0)),
5194 )]
5195}
5196
5197fn list_and_table_widgets(ui: &mut UiDocument, parent: UiNodeId, state: &ShowcaseState) {
5198 let body = section(ui, parent, "lists_tables", "Lists and tables");
5199
5200 let scroll_shell = row(ui, body, "lists_tables.scroll_area.shell", 8.0);
5201 let nested_scroll = widgets::scroll_area(
5202 ui,
5203 scroll_shell,
5204 "lists_tables.scroll_area",
5205 ScrollAxes::VERTICAL,
5206 LayoutStyle::column()
5207 .with_width(0.0)
5208 .with_flex_grow(1.0)
5209 .with_height(92.0),
5210 );
5211 ui.node_mut(nested_scroll)
5212 .set_action("lists_tables.scroll_area.scroll");
5213 if let Some(scroll) = ui.node_mut(nested_scroll).scroll_mut() {
5214 scroll.set_offset(UiPoint::new(0.0, state.list_scroll));
5215 }
5216 for index in 0..6 {
5217 widgets::label(
5218 ui,
5219 nested_scroll,
5220 format!("lists_tables.scroll_area.row.{index}"),
5221 format!("Scroll row {}", index + 1),
5222 text(12.0, color(200, 212, 228)),
5223 LayoutStyle::new()
5224 .with_width_percent(1.0)
5225 .with_height(26.0)
5226 .with_flex_shrink(0.0),
5227 );
5228 }
5229 scrollbar_widgets::scrollbar(
5230 ui,
5231 scroll_shell,
5232 "lists_tables.scroll_area.scrollbar",
5233 scroll_state(state.list_scroll, 92.0, 6.0 * 26.0),
5234 scrollbar_widgets::ScrollAxis::Vertical,
5235 scrollbar_widgets::ScrollbarOptions::default()
5236 .with_layout(LayoutStyle::size(8.0, 92.0))
5237 .with_track_size(UiSize::new(8.0, 92.0))
5238 .with_action("lists_tables.scroll_area.scrollbar"),
5239 );
5240
5241 widgets::table_header(ui, body, "lists_tables.table_header", &table_columns());
5242
5243 let virtual_shell = row(ui, body, "lists_tables.virtual_list.shell", 8.0);
5244 let virtual_list = widgets::virtual_list(
5245 ui,
5246 virtual_shell,
5247 "lists_tables.virtual_list",
5248 widgets::VirtualListSpec {
5249 row_count: 24,
5250 row_height: 28.0,
5251 viewport_height: 112.0,
5252 scroll_offset: state.virtual_scroll,
5253 overscan: 1,
5254 },
5255 |ui, row_parent, row| {
5256 widgets::label(
5257 ui,
5258 row_parent,
5259 format!("lists_tables.virtual_list.row.{row}"),
5260 format!("Virtual row {}", row + 1),
5261 text(12.0, color(214, 224, 238)),
5262 LayoutStyle::new()
5263 .with_width_percent(1.0)
5264 .with_height(28.0)
5265 .with_flex_shrink(0.0),
5266 );
5267 },
5268 );
5269 ui.node_mut(virtual_list)
5270 .set_action("lists_tables.virtual_list.scroll");
5271 scrollbar_widgets::scrollbar(
5272 ui,
5273 virtual_shell,
5274 "lists_tables.virtual_list.scrollbar",
5275 scroll_state(state.virtual_scroll, 112.0, 24.0 * 28.0),
5276 scrollbar_widgets::ScrollAxis::Vertical,
5277 scrollbar_widgets::ScrollbarOptions::default()
5278 .with_layout(LayoutStyle::size(8.0, 112.0))
5279 .with_track_size(UiSize::new(8.0, 112.0))
5280 .with_action("lists_tables.virtual_list.scrollbar"),
5281 );
5282
5283 let table_shell = row(ui, body, "lists_tables.data_table.shell", 8.0);
5284 let table_scroll = widgets::scroll_area(
5285 ui,
5286 table_shell,
5287 "lists_tables.data_table",
5288 ScrollAxes::VERTICAL,
5289 LayoutStyle::column()
5290 .with_width(0.0)
5291 .with_flex_grow(1.0)
5292 .with_height(128.0),
5293 );
5294 ui.node_mut(table_scroll)
5295 .set_action("lists_tables.data_table.scroll");
5296 if let Some(scroll) = ui.node_mut(table_scroll).scroll_mut() {
5297 scroll.set_offset(UiPoint::new(0.0, state.table_scroll));
5298 }
5299 for row_index in 0..16 {
5300 data_table_row(ui, table_scroll, row_index, state);
5301 }
5302 scrollbar_widgets::scrollbar(
5303 ui,
5304 table_shell,
5305 "lists_tables.data_table.scrollbar",
5306 scroll_state(state.table_scroll, 128.0, 16.0 * 28.0),
5307 scrollbar_widgets::ScrollAxis::Vertical,
5308 scrollbar_widgets::ScrollbarOptions::default()
5309 .with_layout(LayoutStyle::size(8.0, 128.0))
5310 .with_track_size(UiSize::new(8.0, 128.0))
5311 .with_action("lists_tables.data_table.scrollbar"),
5312 );
5313
5314 let virtual_controls = wrapping_row(ui, body, "lists_tables.virtualized_table.controls", 8.0);
5315 button(
5316 ui,
5317 virtual_controls,
5318 "lists_tables.virtualized_table.sort.name",
5319 if state.virtual_table_descending {
5320 "Name desc"
5321 } else {
5322 "Name asc"
5323 },
5324 "lists_tables.virtualized_table.sort.name",
5325 button_visual(38, 52, 70),
5326 );
5327 button(
5328 ui,
5329 virtual_controls,
5330 "lists_tables.virtualized_table.filter.status",
5331 if state.virtual_table_ready_only {
5332 "Ready only"
5333 } else {
5334 "All status"
5335 },
5336 "lists_tables.virtualized_table.filter.status",
5337 button_visual(38, 52, 70),
5338 );
5339 button(
5340 ui,
5341 virtual_controls,
5342 "lists_tables.virtualized_table.resize.reset",
5343 "Reset width",
5344 "lists_tables.virtualized_table.resize.reset",
5345 button_visual(38, 52, 70),
5346 );
5347
5348 let columns = virtual_table_columns(state);
5349 let visible_rows = virtual_table_visible_rows(state);
5350 let mut table_options = ext_widgets::DataTableOptions::default()
5351 .with_row_action_prefix("lists_tables.virtualized_table")
5352 .with_cell_action_prefix("lists_tables.virtualized_table")
5353 .with_scroll_action("lists_tables.virtualized_table.scroll");
5354 table_options.layout = LayoutStyle::column()
5355 .with_width(0.0)
5356 .with_flex_grow(1.0)
5357 .with_flex_shrink(1.0);
5358 table_options.selection = state.table_selection.clone();
5359 let virtual_shell = row(ui, body, "lists_tables.virtualized_table.shell", 8.0);
5360 ext_widgets::virtualized_data_table(
5361 ui,
5362 virtual_shell,
5363 "lists_tables.virtualized_table",
5364 &columns,
5365 ext_widgets::VirtualDataTableSpec {
5366 row_count: visible_rows.len(),
5367 row_height: 28.0,
5368 viewport_width: 420.0,
5369 viewport_height: 128.0,
5370 scroll_offset: UiPoint::new(0.0, state.virtual_table_scroll),
5371 overscan_rows: 1,
5372 },
5373 table_options,
5374 |ui, cell_parent, cell| {
5375 let source_row = visible_rows.get(cell.row).copied().unwrap_or(cell.row);
5376 let value = virtual_table_cell_value(source_row, cell.column);
5377 widgets::label(
5378 ui,
5379 cell_parent,
5380 format!(
5381 "lists_tables.virtualized_table.cell.{}.{}.label",
5382 cell.row, cell.column
5383 ),
5384 value,
5385 text(12.0, color(220, 228, 238)),
5386 LayoutStyle::new().with_width_percent(1.0),
5387 );
5388 },
5389 );
5390 scrollbar_widgets::scrollbar(
5391 ui,
5392 virtual_shell,
5393 "lists_tables.virtualized_table.scrollbar",
5394 scroll_state(
5395 state.virtual_table_scroll,
5396 128.0,
5397 visible_rows.len() as f32 * 28.0,
5398 ),
5399 scrollbar_widgets::ScrollAxis::Vertical,
5400 scrollbar_widgets::ScrollbarOptions::default()
5401 .with_layout(LayoutStyle::size(8.0, 158.0))
5402 .with_track_size(UiSize::new(8.0, 158.0))
5403 .with_action("lists_tables.virtualized_table.scrollbar"),
5404 );
5405}
5406
5407fn data_table_row(ui: &mut UiDocument, parent: UiNodeId, row_index: usize, state: &ShowcaseState) {
5408 let selected = state.table_selection.contains_row(row_index);
5409 let row = ui.add_child(
5410 parent,
5411 UiNode::container(
5412 format!("lists_tables.data_table.row.{row_index}"),
5413 LayoutStyle::row()
5414 .with_width_percent(1.0)
5415 .with_height(28.0)
5416 .with_flex_shrink(0.0),
5417 )
5418 .with_input(operad::InputBehavior::BUTTON)
5419 .with_action(format!("lists_tables.data_table.row.{row_index}"))
5420 .with_visual(if selected {
5421 UiVisual::panel(color(45, 73, 109), None, 0.0)
5422 } else {
5423 UiVisual::TRANSPARENT
5424 }),
5425 );
5426 let values = [
5427 format!("Item {}", row_index + 1),
5428 if row_index % 2 == 0 {
5429 "Ready".to_string()
5430 } else {
5431 "Pending".to_string()
5432 },
5433 format!("{}%", 40 + row_index * 3),
5434 ];
5435 let widths = [0.42, 0.33, 0.25];
5436 for (column, value) in values.into_iter().enumerate() {
5437 let cell = ui.add_child(
5438 row,
5439 UiNode::container(
5440 format!("lists_tables.data_table.cell.{row_index}.{column}"),
5441 LayoutStyle::new()
5442 .with_width_percent(widths[column])
5443 .with_height_percent(1.0)
5444 .padding(6.0),
5445 )
5446 .with_input(operad::InputBehavior::BUTTON)
5447 .with_action(format!("lists_tables.data_table.cell.{row_index}.{column}")),
5448 );
5449 widgets::label(
5450 ui,
5451 cell,
5452 format!("lists_tables.data_table.cell.{row_index}.{column}.label"),
5453 value,
5454 text(12.0, color(222, 230, 240)),
5455 LayoutStyle::new().with_width_percent(1.0),
5456 );
5457 }
5458}
5459
5460#[allow(clippy::field_reassign_with_default)]
5461fn property_inspector(ui: &mut UiDocument, parent: UiNodeId, state: &ShowcaseState) {
5462 let body = section(ui, parent, "property_inspector", "Property inspector");
5463 widgets::label(
5464 ui,
5465 body,
5466 "property_inspector.target",
5467 "Inspecting: Styling preview",
5468 text(12.0, color(196, 210, 230)),
5469 LayoutStyle::new().with_width_percent(1.0),
5470 );
5471 let mut options = ext_widgets::PropertyInspectorOptions::default();
5472 options.selected_index = Some(0);
5473 options.label_width = 120.0;
5474 options.row_height = 30.0;
5475 ext_widgets::property_inspector_grid(
5476 ui,
5477 body,
5478 "property_inspector.grid",
5479 &[
5480 ext_widgets::PropertyGridRow::new("target", "Widget", "Button preview").read_only(),
5481 ext_widgets::PropertyGridRow::new(
5482 "inner",
5483 "Inner margin",
5484 format!("{:.0}px", state.styling.inner_margin),
5485 )
5486 .with_kind(ext_widgets::PropertyValueKind::Number),
5487 ext_widgets::PropertyGridRow::new(
5488 "outer",
5489 "Outer margin",
5490 format!("{:.0}px", state.styling.outer_margin),
5491 )
5492 .with_kind(ext_widgets::PropertyValueKind::Number),
5493 ext_widgets::PropertyGridRow::new(
5494 "radius",
5495 "Corner radius",
5496 format!("{:.0}px", state.styling.corner_radius),
5497 )
5498 .with_kind(ext_widgets::PropertyValueKind::Number),
5499 ext_widgets::PropertyGridRow::new(
5500 "stroke",
5501 "Stroke",
5502 format!("{:.1}px", state.styling.stroke_width),
5503 )
5504 .with_kind(ext_widgets::PropertyValueKind::Number)
5505 .changed(),
5506 ext_widgets::PropertyGridRow::new("state", "Source", "Styling widget").read_only(),
5507 ],
5508 options,
5509 );
5510}
5511
5512fn diagnostics_widgets(ui: &mut UiDocument, parent: UiNodeId, state: &ShowcaseState) {
5513 let body = section(ui, parent, "diagnostics", "Diagnostics");
5514
5515 widgets::label(
5516 ui,
5517 body,
5518 "diagnostics.layout.title",
5519 "Layout and animation inspector",
5520 text(14.0, color(222, 230, 240)),
5521 LayoutStyle::new().with_width_percent(1.0),
5522 );
5523 let debug_snapshot = &state.diagnostics_snapshot;
5524 ext_widgets::debug_inspector_panel(
5525 ui,
5526 body,
5527 "diagnostics.inspector",
5528 debug_snapshot,
5529 ext_widgets::DebugInspectorPanelOptions {
5530 selected_node: Some("diagnostics.sample.preview".to_owned()),
5531 label_width: 104.0,
5532 max_layout_rows: 5,
5533 max_animation_rows: 1,
5534 show_animation: false,
5535 ..Default::default()
5536 },
5537 );
5538 ext_widgets::animation_state_graph_panel(
5539 ui,
5540 body,
5541 "diagnostics.animation.graph",
5542 debug_snapshot.animation("diagnostics.sample.preview"),
5543 ext_widgets::AnimationStateGraphPanelOptions {
5544 state_width: 72.0,
5545 state_height: 28.0,
5546 edge_row_height: 22.0,
5547 max_edges: 2,
5548 action_prefix: Some("diagnostics.animation.graph".to_owned()),
5549 ..Default::default()
5550 },
5551 );
5552 ext_widgets::animation_inspector_controls_panel(
5553 ui,
5554 body,
5555 "diagnostics.animation.controls",
5556 debug_snapshot.animation("diagnostics.sample.preview"),
5557 ext_widgets::AnimationInspectorControlsOptions {
5558 max_inputs: 3,
5559 paused: state.diagnostics_animation_paused,
5560 scrub_progress: Some(state.diagnostics_animation_scrub),
5561 action_prefix: Some("diagnostics.animation.controls".to_owned()),
5562 ..Default::default()
5563 },
5564 );
5565 widgets::label(
5566 ui,
5567 body,
5568 "diagnostics.animation.controls.status",
5569 format!(
5570 "scrub {:.0}% hover {:.0}% pulses {}",
5571 state.diagnostics_animation_scrub * 100.0,
5572 state.diagnostics_animation_hover * 100.0,
5573 state.diagnostics_animation_pulse_count
5574 ),
5575 text(12.0, color(166, 180, 198)),
5576 LayoutStyle::new().with_width_percent(1.0),
5577 );
5578
5579 widgets::label(
5580 ui,
5581 body,
5582 "diagnostics.a11y.title",
5583 "Accessibility overlay",
5584 text(14.0, color(222, 230, 240)),
5585 LayoutStyle::new().with_width_percent(1.0),
5586 );
5587 let mut overlay_preview_style = UiNodeStyle::from(
5588 LayoutStyle::new()
5589 .with_width(320.0)
5590 .with_height(140.0)
5591 .with_flex_shrink(0.0),
5592 );
5593 overlay_preview_style.set_clip(ClipBehavior::Clip);
5594 let overlay_preview = ui.add_child(
5595 body,
5596 UiNode::container("diagnostics.a11y.preview", overlay_preview_style).with_visual(
5597 UiVisual::panel(
5598 color(12, 17, 24),
5599 Some(StrokeStyle::new(color(47, 62, 82), 1.0)),
5600 4.0,
5601 ),
5602 ),
5603 );
5604 let mut overlay_options = ext_widgets::AccessibilityDebugOverlayOptions {
5605 action_prefix: Some("diagnostics.a11y.visual".to_owned()),
5606 ..Default::default()
5607 };
5608 overlay_options.show_labels = false;
5609 ext_widgets::accessibility_debug_overlay(
5610 ui,
5611 overlay_preview,
5612 "diagnostics.a11y.visual",
5613 &debug_snapshot,
5614 overlay_options,
5615 );
5616 ext_widgets::accessibility_overlay_panel(
5617 ui,
5618 body,
5619 "diagnostics.a11y",
5620 &debug_snapshot,
5621 ext_widgets::AccessibilityOverlayPanelOptions {
5622 label_width: 118.0,
5623 max_rows: 1,
5624 action_prefix: Some("diagnostics.a11y".to_owned()),
5625 ..Default::default()
5626 },
5627 );
5628
5629 let diagnostic_columns = ui.add_child(
5630 body,
5631 UiNode::container(
5632 "diagnostics.columns",
5633 LayoutStyle::column()
5634 .with_width_percent(1.0)
5635 .with_flex_shrink(0.0)
5636 .gap(10.0),
5637 ),
5638 );
5639 let command_column = ui.add_child(
5640 diagnostic_columns,
5641 UiNode::container(
5642 "diagnostics.commands.column",
5643 LayoutStyle::column()
5644 .with_width_percent(1.0)
5645 .with_flex_shrink(0.0)
5646 .gap(8.0),
5647 ),
5648 );
5649 let theme_column = ui.add_child(
5650 diagnostic_columns,
5651 UiNode::container(
5652 "diagnostics.theme.column",
5653 LayoutStyle::column()
5654 .with_width_percent(1.0)
5655 .with_flex_shrink(0.0)
5656 .gap(8.0),
5657 ),
5658 );
5659
5660 widgets::label(
5661 ui,
5662 command_column,
5663 "diagnostics.commands.title",
5664 "Command registry",
5665 text(14.0, color(222, 230, 240)),
5666 LayoutStyle::new().with_width_percent(1.0),
5667 );
5668 let registry = diagnostics_command_registry();
5669 ext_widgets::command_diagnostics_panel(
5670 ui,
5671 command_column,
5672 "diagnostics.commands",
5673 ®istry,
5674 &[CommandScope::Global, CommandScope::Panel],
5675 &ShortcutFormatter::default(),
5676 ext_widgets::CommandDiagnosticsPanelOptions {
5677 label_width: 92.0,
5678 max_command_rows: 3,
5679 max_conflict_rows: 1,
5680 action_prefix: Some("diagnostics.commands".to_owned()),
5681 ..Default::default()
5682 },
5683 );
5684
5685 widgets::label(
5686 ui,
5687 theme_column,
5688 "diagnostics.theme.title",
5689 "Theme editor",
5690 text(14.0, color(222, 230, 240)),
5691 LayoutStyle::new().with_width_percent(1.0),
5692 );
5693 let theme_snapshot = DebugThemeSnapshot::from_theme(&Theme::dark());
5694 ext_widgets::theme_editor_panel(
5695 ui,
5696 theme_column,
5697 "diagnostics.theme",
5698 &theme_snapshot,
5699 ext_widgets::ThemeEditorPanelOptions {
5700 label_width: 92.0,
5701 max_token_rows: 1,
5702 max_component_rows: 1,
5703 action_prefix: Some("diagnostics.theme".to_owned()),
5704 ..Default::default()
5705 },
5706 );
5707}
5708
5709fn diagnostics_sample_snapshot(state: &ShowcaseState) -> DebugInspectorSnapshot {
5710 diagnostics_sample_snapshot_for(
5711 state.diagnostics_animation_hover,
5712 state.diagnostics_animation_active,
5713 )
5714}
5715
5716fn diagnostics_sample_snapshot_for(hover: f32, active: bool) -> DebugInspectorSnapshot {
5717 let mut sample = UiDocument::new(root_style(320.0, 180.0));
5718 let card = sample.add_child(
5719 sample.root(),
5720 UiNode::container(
5721 "diagnostics.sample.card",
5722 LayoutStyle::column()
5723 .with_width_percent(1.0)
5724 .with_height(120.0)
5725 .padding(12.0)
5726 .gap(8.0),
5727 )
5728 .with_visual(UiVisual::panel(
5729 color(16, 22, 30),
5730 Some(StrokeStyle::new(color(62, 77, 98), 1.0)),
5731 6.0,
5732 ))
5733 .with_accessibility(
5734 AccessibilityMeta::new(AccessibilityRole::Group).label("Diagnostics sample"),
5735 ),
5736 );
5737 sample.add_child(
5738 card,
5739 UiNode::container(
5740 "diagnostics.sample.preview",
5741 LayoutStyle::new().with_width(160.0).with_height(38.0),
5742 )
5743 .with_input(InputBehavior::BUTTON)
5744 .with_visual(UiVisual::panel(
5745 color(52, 112, 180),
5746 Some(StrokeStyle::new(color(116, 183, 255), 1.0)),
5747 5.0,
5748 ))
5749 .with_accessibility(
5750 AccessibilityMeta::new(AccessibilityRole::Button)
5751 .label("Preview action")
5752 .focusable(),
5753 )
5754 .with_animation(
5755 AnimationMachine::new(
5756 vec![
5757 AnimationState::new(
5758 "idle",
5759 AnimatedValues::new(1.0, UiPoint::new(0.0, 0.0), 1.0),
5760 ),
5761 AnimationState::new(
5762 "hot",
5763 AnimatedValues::new(0.92, UiPoint::new(18.0, 0.0), 1.08),
5764 ),
5765 ],
5766 vec![AnimationTransition::when(
5767 "idle",
5768 "hot",
5769 AnimationCondition::bool("active", true),
5770 0.18,
5771 )],
5772 "idle",
5773 )
5774 .expect("sample animation")
5775 .with_number_input("hover", hover)
5776 .with_blend_binding(AnimationBlendBinding::new("hover", "idle", "hot"))
5777 .with_bool_input("active", active)
5778 .with_trigger_input("pulse"),
5779 ),
5780 );
5781 widgets::label(
5782 &mut sample,
5783 card,
5784 "diagnostics.sample.label",
5785 "Sample node",
5786 text(12.0, color(198, 210, 226)),
5787 LayoutStyle::new().with_width_percent(1.0),
5788 );
5789 sample
5790 .compute_layout(UiSize::new(320.0, 180.0), &mut ApproxTextMeasurer)
5791 .expect("sample layout");
5792 DebugInspectorSnapshot::from_document(&sample, &mut ApproxTextMeasurer)
5793}More examples
examples/animation_state_machine.rs (line 129)
128fn shape_machine(open: bool) -> AnimationMachine {
129 let closed = AnimatedValues::new(0.82, UiPoint::new(0.0, 0.0), 1.0).with_morph(0.0);
130 let open_values = AnimatedValues::new(1.0, UiPoint::new(160.0, 0.0), 1.08).with_morph(1.0);
131 AnimationMachine::new(
132 vec![
133 AnimationState::new("closed", closed),
134 AnimationState::new("open", open_values),
135 ],
136 vec![
137 AnimationTransition::when(
138 "closed",
139 "open",
140 AnimationCondition::bool(INPUT_OPEN, true),
141 0.24,
142 ),
143 AnimationTransition::when(
144 "open",
145 "closed",
146 AnimationCondition::bool(INPUT_OPEN, false),
147 0.18,
148 ),
149 ],
150 "closed",
151 )
152 .unwrap_or_else(|_| AnimationMachine::single_state("closed", closed))
153 .with_bool_input(INPUT_OPEN, open)
154 .with_number_input(INPUT_MORPH, if open { 1.0 } else { 0.0 })
155 .with_blend_binding(AnimationBlendBinding::new(INPUT_MORPH, "closed", "open"))
156}Sourcepub const fn with_morph(self, morph: f32) -> Self
pub const fn with_morph(self, morph: f32) -> Self
Examples found in repository?
examples/showcase.rs (line 5029)
5020fn animation_blend_machine(
5021 input: &'static str,
5022 value: f32,
5023 translate: UiPoint,
5024 start_scale: f32,
5025 end_scale: f32,
5026 end_opacity: f32,
5027) -> AnimationMachine {
5028 let start_values = AnimatedValues::new(0.45, UiPoint::new(0.0, 0.0), start_scale);
5029 let end_values = AnimatedValues::new(end_opacity, translate, end_scale).with_morph(1.0);
5030 AnimationMachine::new(
5031 vec![
5032 AnimationState::new("start", start_values),
5033 AnimationState::new("end", end_values),
5034 ],
5035 Vec::new(),
5036 "start",
5037 )
5038 .unwrap_or_else(|_| AnimationMachine::single_state("start", start_values))
5039 .with_number_input(input, value)
5040 .with_blend_binding(AnimationBlendBinding::new(input, "start", "end"))
5041}
5042
5043fn animation_open_machine(open: bool) -> AnimationMachine {
5044 let closed_values = AnimatedValues::new(0.35, UiPoint::new(0.0, 0.0), 1.0);
5045 let open_values = AnimatedValues::new(1.0, UiPoint::new(0.0, 0.0), 1.0);
5046 let fallback_values = if open { open_values } else { closed_values };
5047 AnimationMachine::new(
5048 vec![
5049 AnimationState::new("closed", closed_values),
5050 AnimationState::new("open", open_values),
5051 ],
5052 vec![
5053 AnimationTransition::when(
5054 "closed",
5055 "open",
5056 AnimationCondition::bool(ANIMATION_INPUT_OPEN, true),
5057 0.18,
5058 ),
5059 AnimationTransition::when(
5060 "open",
5061 "closed",
5062 AnimationCondition::bool(ANIMATION_INPUT_OPEN, false),
5063 0.14,
5064 ),
5065 ],
5066 "closed",
5067 )
5068 .unwrap_or_else(|_| AnimationMachine::single_state("closed", fallback_values))
5069 .with_bool_input(ANIMATION_INPUT_OPEN, open)
5070}
5071
5072fn animation_interaction_machine() -> AnimationMachine {
5073 let rest_values = AnimatedValues::new(0.72, UiPoint::new(0.0, 0.0), 1.0);
5074 let right_values = AnimatedValues::new(1.0, UiPoint::new(0.0, 0.0), 1.0).with_morph(1.0);
5075 AnimationMachine::new(
5076 vec![
5077 AnimationState::new("rest", rest_values),
5078 AnimationState::new("right", right_values),
5079 ],
5080 Vec::new(),
5081 "rest",
5082 )
5083 .unwrap_or_else(|_| AnimationMachine::single_state("rest", rest_values))
5084 .with_number_input(ANIMATION_INPUT_POINTER_NORM_X, 0.0)
5085 .with_blend_binding(AnimationBlendBinding::new(
5086 ANIMATION_INPUT_POINTER_NORM_X,
5087 "rest",
5088 "right",
5089 ))
5090}More examples
examples/animation_state_machine.rs (line 129)
128fn shape_machine(open: bool) -> AnimationMachine {
129 let closed = AnimatedValues::new(0.82, UiPoint::new(0.0, 0.0), 1.0).with_morph(0.0);
130 let open_values = AnimatedValues::new(1.0, UiPoint::new(160.0, 0.0), 1.08).with_morph(1.0);
131 AnimationMachine::new(
132 vec![
133 AnimationState::new("closed", closed),
134 AnimationState::new("open", open_values),
135 ],
136 vec![
137 AnimationTransition::when(
138 "closed",
139 "open",
140 AnimationCondition::bool(INPUT_OPEN, true),
141 0.24,
142 ),
143 AnimationTransition::when(
144 "open",
145 "closed",
146 AnimationCondition::bool(INPUT_OPEN, false),
147 0.18,
148 ),
149 ],
150 "closed",
151 )
152 .unwrap_or_else(|_| AnimationMachine::single_state("closed", closed))
153 .with_bool_input(INPUT_OPEN, open)
154 .with_number_input(INPUT_MORPH, if open { 1.0 } else { 0.0 })
155 .with_blend_binding(AnimationBlendBinding::new(INPUT_MORPH, "closed", "open"))
156}Trait Implementations§
Source§impl Clone for AnimatedValues
impl Clone for AnimatedValues
Source§fn clone(&self) -> AnimatedValues
fn clone(&self) -> AnimatedValues
Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreSource§impl Debug for AnimatedValues
impl Debug for AnimatedValues
Source§impl Default for AnimatedValues
impl Default for AnimatedValues
Source§impl PartialEq for AnimatedValues
impl PartialEq for AnimatedValues
Source§fn eq(&self, other: &AnimatedValues) -> bool
fn eq(&self, other: &AnimatedValues) -> bool
Tests for
self and other values to be equal, and is used by ==.impl Copy for AnimatedValues
impl StructuralPartialEq for AnimatedValues
Auto Trait Implementations§
impl Freeze for AnimatedValues
impl RefUnwindSafe for AnimatedValues
impl Send for AnimatedValues
impl Sync for AnimatedValues
impl Unpin for AnimatedValues
impl UnsafeUnpin for AnimatedValues
impl UnwindSafe for AnimatedValues
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Convert
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Convert
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
Convert
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
Convert
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.