mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
fixed clippy warnings, ui refactor
This commit is contained in:
Generated
+25
-11
@@ -6,19 +6,16 @@
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="1932b2c4-d6ff-413c-9558-19959667326b" name="Default Changelist" comment="scene graph">
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/engine/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/engine/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/game/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/game/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/game/player.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/game/player.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/draw.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/draw.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/math/mat4.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/math/mat4.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/physics/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/physics/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/resource/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/resource/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/resource/model.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/resource/model.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/resource/texture.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/resource/texture.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/scene/animation.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/scene/animation.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/scene/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/scene/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/scene/node.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/scene/node.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/utils/pool.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/utils/pool.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/utils/rcpool.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/utils/rcpool.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/math/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/math/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/math/ray.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/math/ray.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/math/triangulator.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/math/triangulator.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/renderer/renderer.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/renderer/renderer.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/resource/fbx/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/resource/fbx/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/resource/ttf.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/resource/ttf.rs" afterDir="false" />
|
||||
</list>
|
||||
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
@@ -70,6 +67,17 @@
|
||||
</option>
|
||||
</component>
|
||||
<component name="RunManager" selected="Cargo Command.Release">
|
||||
<configuration name="Clippy" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||
<option name="channel" value="DEFAULT" />
|
||||
<option name="command" value="clippy" />
|
||||
<option name="allFeatures" value="false" />
|
||||
<option name="nocapture" value="false" />
|
||||
<option name="emulateTerminal" value="false" />
|
||||
<option name="backtrace" value="SHORT" />
|
||||
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="Debug" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true">
|
||||
<option name="channel" value="DEFAULT" />
|
||||
<option name="command" value="run --package rg3d --bin rg3d" />
|
||||
@@ -103,6 +111,12 @@
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<list>
|
||||
<item itemvalue="Cargo Command.Release" />
|
||||
<item itemvalue="Cargo Command.Clippy" />
|
||||
<item itemvalue="Cargo Command.Test" />
|
||||
<item itemvalue="Cargo Command.Debug" />
|
||||
</list>
|
||||
</component>
|
||||
<component name="RustProjectSettings">
|
||||
<option name="toolchainHomeDirectory" value="$USER_HOME$/.cargo/bin" />
|
||||
|
||||
@@ -30,6 +30,7 @@ use std::{
|
||||
time::Instant,
|
||||
rc::Rc,
|
||||
};
|
||||
use crate::gui::ScrollViewerBuilder;
|
||||
|
||||
pub struct MenuState {
|
||||
save_game: Option<()>,
|
||||
@@ -80,6 +81,12 @@ impl Game {
|
||||
.with_height(200.0)
|
||||
.build(ui);
|
||||
|
||||
ScrollViewerBuilder::new()
|
||||
.with_desired_position(Vec2::make(550.0, 300.0))
|
||||
.with_width(300.0)
|
||||
.with_height(200.0)
|
||||
.build(ui);
|
||||
|
||||
GridBuilder::new()
|
||||
.add_column(Column::stretch())
|
||||
.add_row(Row::strict(50.0))
|
||||
|
||||
+5
-7
@@ -3,16 +3,16 @@ use crate::{
|
||||
math::{
|
||||
vec2::*,
|
||||
vec3::*,
|
||||
quat::*
|
||||
quat::*,
|
||||
},
|
||||
scene::{
|
||||
node::*,
|
||||
*
|
||||
*,
|
||||
},
|
||||
physics::Body,
|
||||
game::{
|
||||
weapon::{Weapon, WeaponKind},
|
||||
GameTime
|
||||
GameTime,
|
||||
},
|
||||
engine::State,
|
||||
};
|
||||
@@ -128,10 +128,8 @@ impl Player {
|
||||
}
|
||||
|
||||
pub fn next_weapon(&mut self) {
|
||||
if !self.weapons.is_empty() {
|
||||
if self.current_weapon < self.weapons.len() - 1 {
|
||||
self.current_weapon += 1;
|
||||
}
|
||||
if !self.weapons.is_empty() && self.current_weapon < self.weapons.len() - 1 {
|
||||
self.current_weapon += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-17
@@ -387,11 +387,6 @@ impl DrawingContext {
|
||||
self.current_nesting = 0;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_command_buffer(&self) -> &[Command] {
|
||||
self.command_buffer.as_slice()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_vertices(&self) -> &[Vertex] {
|
||||
self.vertex_buffer.as_slice()
|
||||
@@ -508,7 +503,7 @@ impl DrawingContext {
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
false
|
||||
}
|
||||
|
||||
pub fn push_line(&mut self, a: &Vec2, b: &Vec2, thickness: f32, color: Color) {
|
||||
@@ -574,7 +569,7 @@ impl DrawingContext {
|
||||
self.push_triangle(index, index + 2, index + 3);
|
||||
}
|
||||
|
||||
pub fn commit(&mut self, kind: CommandKind, texture: u32) -> Option<usize> {
|
||||
pub fn commit(&mut self, kind: CommandKind, texture: u32) {
|
||||
if self.triangles_to_commit > 0 {
|
||||
let command = Command {
|
||||
kind,
|
||||
@@ -585,16 +580,12 @@ impl DrawingContext {
|
||||
} else { 0 },
|
||||
triangle_count: self.triangles_to_commit,
|
||||
};
|
||||
let index = self.command_buffer.len();
|
||||
self.command_buffer.push(command);
|
||||
self.triangles_to_commit = 0;
|
||||
Some(index)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_text(&mut self, position: Vec2, formatted_text: &FormattedText) -> Option<usize> {
|
||||
pub fn draw_text(&mut self, position: Vec2, formatted_text: &FormattedText) {
|
||||
for element in formatted_text.glyphs.iter() {
|
||||
let final_bounds = Rect::new(
|
||||
position.x + element.bounds.x,
|
||||
@@ -604,14 +595,14 @@ impl DrawingContext {
|
||||
|
||||
self.push_rect_filled(&final_bounds, Some(&element.tex_coords), element.color);
|
||||
}
|
||||
return self.commit(CommandKind::Geometry, formatted_text.texture);
|
||||
self.commit(CommandKind::Geometry, formatted_text.texture)
|
||||
}
|
||||
|
||||
pub fn commit_clip_rect(&mut self, clip_rect: &Rect<f32>) -> usize {
|
||||
pub fn commit_clip_rect(&mut self, clip_rect: &Rect<f32>) {
|
||||
self.push_rect_filled(clip_rect, None, Color::black());
|
||||
let command_index = self.commit(CommandKind::Clip, 0).unwrap();
|
||||
self.clip_cmd_stack.push(command_index);
|
||||
command_index
|
||||
let index = self.command_buffer.len();
|
||||
self.commit(CommandKind::Clip, 0);
|
||||
self.clip_cmd_stack.push(index);
|
||||
}
|
||||
|
||||
pub fn ready_to_draw(&self) -> bool {
|
||||
|
||||
+408
-208
@@ -84,6 +84,7 @@ pub enum Visibility {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Text {
|
||||
owner_handle: Handle<UINode>,
|
||||
need_update: bool,
|
||||
text: String,
|
||||
font: Handle<Font>,
|
||||
@@ -92,9 +93,30 @@ pub struct Text {
|
||||
formatted_text: Option<FormattedText>,
|
||||
}
|
||||
|
||||
impl Drawable for Text {
|
||||
fn draw(&mut self, drawing_context: &mut DrawingContext, font_cache: &Pool<Font>, bounds: &Rect<f32>, color: Color) {
|
||||
if self.need_update {
|
||||
if let Some(font) = font_cache.borrow(&self.font) {
|
||||
let formatted_text = FormattedTextBuilder::reuse(self.formatted_text.take().unwrap())
|
||||
.with_size(Vec2::make(bounds.w, bounds.h))
|
||||
.with_font(font)
|
||||
.with_text(self.text.as_str())
|
||||
.with_color(color)
|
||||
.with_horizontal_alignment(self.horizontal_alignment)
|
||||
.with_vertical_alignment(self.vertical_alignment)
|
||||
.build();
|
||||
self.formatted_text = Some(formatted_text);
|
||||
}
|
||||
self.need_update = true; // TODO
|
||||
}
|
||||
drawing_context.draw_text(Vec2::make(bounds.x, bounds.y), self.formatted_text.as_ref().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
impl Text {
|
||||
pub fn new() -> Text {
|
||||
Text {
|
||||
owner_handle: Handle::none(),
|
||||
text: String::new(),
|
||||
need_update: true,
|
||||
vertical_alignment: VerticalAlignment::Top,
|
||||
@@ -331,7 +353,7 @@ impl CanvasBuilder {
|
||||
impl_default_builder_methods!();
|
||||
|
||||
pub fn build(self, ui: &mut UserInterface) -> Handle<UINode> {
|
||||
GenericNodeBuilder::new(UINodeKind::Canvas(Canvas {}), self.common).build(ui)
|
||||
GenericNodeBuilder::new(UINodeKind::Canvas(Canvas::new()), self.common).build(ui)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -439,17 +461,30 @@ impl BorderBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Layout {
|
||||
trait Layout {
|
||||
fn measure_override(&mut self, ui: &mut UserInterface, children: &UnsafeCollectionView<Handle<UINode>>, available_size: &Vec2) -> Vec2;
|
||||
fn arrange_override(&self, ui: &mut UserInterface, children: &UnsafeCollectionView<Handle<UINode>>, final_size: &Vec2) -> Vec2;
|
||||
}
|
||||
|
||||
trait Drawable {
|
||||
fn draw(&mut self, drawing_context: &mut DrawingContext, font_cache: &Pool<Font>, bounds: &Rect<f32>, color: Color);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Border {
|
||||
owner_handle: Handle<UINode>,
|
||||
stroke_thickness: Thickness,
|
||||
stroke_color: Color,
|
||||
}
|
||||
|
||||
impl Drawable for Border {
|
||||
fn draw(&mut self, drawing_context: &mut DrawingContext, font_cache: &Pool<Font>, bounds: &Rect<f32>, color: Color) {
|
||||
drawing_context.push_rect_filled(&bounds, None, color);
|
||||
drawing_context.push_rect_vary(&bounds, self.stroke_thickness, self.stroke_color);
|
||||
drawing_context.commit(CommandKind::Geometry, 0);
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for Border {
|
||||
fn measure_override(&mut self, ui: &mut UserInterface, children: &UnsafeCollectionView<Handle<UINode>>, available_size: &Vec2) -> Vec2 {
|
||||
let margin_x = self.stroke_thickness.left + self.stroke_thickness.right;
|
||||
@@ -496,28 +531,25 @@ impl Layout for Border {
|
||||
impl Layout for UINodeKind {
|
||||
fn measure_override(&mut self, ui: &mut UserInterface, children: &UnsafeCollectionView<Handle<UINode>>, available_size: &Vec2) -> Vec2 {
|
||||
match self {
|
||||
UINodeKind::Border(border) => border.measure_override(ui, children, available_size),
|
||||
UINodeKind::Canvas(canvas) => canvas.measure_override(ui, children, available_size),
|
||||
UINodeKind::Grid(grid) => grid.measure_override(ui, children, available_size),
|
||||
UINodeKind::Border(border) => border.measure_override( ui, children, available_size),
|
||||
UINodeKind::Canvas(canvas) => canvas.measure_override( ui, children, available_size),
|
||||
UINodeKind::Grid(grid) => grid.measure_override( ui, children, available_size),
|
||||
UINodeKind::ScrollContentPresenter(scp) => scp.measure_override( ui, children, available_size),
|
||||
UINodeKind::ScrollViewer(scroll_viewer) => scroll_viewer.measure_override( ui, children, available_size),
|
||||
UINodeKind::ScrollBar(scroll_bar) => scroll_bar.measure_override( ui, children, available_size),
|
||||
_ => ui.default_measure_override(children, available_size)
|
||||
}
|
||||
}
|
||||
|
||||
fn arrange_override(&self, ui: &mut UserInterface, children: &UnsafeCollectionView<Handle<UINode>>, final_size: &Vec2) -> Vec2 {
|
||||
match self {
|
||||
UINodeKind::Border(border) => border.arrange_override(ui, children, final_size),
|
||||
UINodeKind::Canvas(canvas) => canvas.arrange_override(ui, children, final_size),
|
||||
UINodeKind::Grid(grid) => grid.arrange_override(ui, children, final_size),
|
||||
// Default arrangement
|
||||
_ => {
|
||||
let final_rect = Rect::new(0.0, 0.0, final_size.x, final_size.y);
|
||||
|
||||
for child_handle in children.iter() {
|
||||
ui.arrange(child_handle, &final_rect);
|
||||
}
|
||||
|
||||
*final_size
|
||||
}
|
||||
UINodeKind::Border(border) => border.arrange_override( ui, children, final_size),
|
||||
UINodeKind::Canvas(canvas) => canvas.arrange_override( ui, children, final_size),
|
||||
UINodeKind::Grid(grid) => grid.arrange_override( ui, children, final_size),
|
||||
UINodeKind::ScrollContentPresenter(scp) => scp.arrange_override( ui, children, final_size),
|
||||
UINodeKind::ScrollViewer(scroll_viewer) => scroll_viewer.arrange_override( ui, children, final_size),
|
||||
UINodeKind::ScrollBar(scroll_bar) => scroll_bar.arrange_override( ui, children, final_size),
|
||||
_ => ui.default_arrange_override(children, final_size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -525,6 +557,7 @@ impl Layout for UINodeKind {
|
||||
impl Border {
|
||||
pub fn new() -> Border {
|
||||
Border {
|
||||
owner_handle: Handle::none(),
|
||||
stroke_thickness: Thickness {
|
||||
left: 1.0,
|
||||
right: 1.0,
|
||||
@@ -547,16 +580,25 @@ impl Border {
|
||||
}
|
||||
|
||||
pub struct Image {
|
||||
texture: RcHandle<Resource>
|
||||
owner_handle: Handle<UINode>,
|
||||
texture: RcHandle<Resource>,
|
||||
}
|
||||
|
||||
pub type ButtonClickEventHandler = dyn FnMut(&mut UserInterface, Handle<UINode>);
|
||||
|
||||
pub struct Button {
|
||||
click: Option<Box<ButtonClickEventHandler>>
|
||||
owner_handle: Handle<UINode>,
|
||||
click: Option<Box<ButtonClickEventHandler>>,
|
||||
}
|
||||
|
||||
impl Button {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
owner_handle: Handle::none(),
|
||||
click: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_on_click(&mut self, handler: Box<ButtonClickEventHandler>) {
|
||||
self.click = Some(handler);
|
||||
}
|
||||
@@ -604,8 +646,11 @@ impl ButtonBuilder {
|
||||
let pressed_color = Color::opaque(100, 100, 100);
|
||||
let hover_color = Color::opaque(160, 160, 160);
|
||||
|
||||
let mut button = Button::new();
|
||||
button.click = self.click;
|
||||
|
||||
GenericNodeBuilder::new(
|
||||
UINodeKind::Button(Button { click: self.click }), self.common)
|
||||
UINodeKind::Button(button), self.common)
|
||||
.with_handler(RoutedEventHandlerType::MouseDown, Box::new(move |ui, handle, _evt| {
|
||||
ui.capture_mouse(&handle);
|
||||
}))
|
||||
@@ -681,9 +726,8 @@ impl ButtonBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
pub type ValueChanged = dyn FnMut(&mut UserInterface, Handle<UINode>, f32, f32);
|
||||
|
||||
pub struct ScrollBar {
|
||||
owner_handle: Handle<UINode>,
|
||||
min: f32,
|
||||
max: f32,
|
||||
value: f32,
|
||||
@@ -691,15 +735,16 @@ pub struct ScrollBar {
|
||||
orientation: Orientation,
|
||||
is_dragging: bool,
|
||||
offset: Vec2,
|
||||
value_changed: Option<Box<ValueChanged>>,
|
||||
value_changed: bool,
|
||||
}
|
||||
|
||||
impl ScrollBar {
|
||||
const PART_CANVAS: &'static str = "PART_Canvas";
|
||||
const PART_INDICATOR: &'static str = "PART_Indicator";
|
||||
pub const PART_CANVAS: &'static str = "PART_Canvas";
|
||||
pub const PART_INDICATOR: &'static str = "PART_Indicator";
|
||||
|
||||
pub fn new() -> Self {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
owner_handle: Handle::none(),
|
||||
min: 0.0,
|
||||
max: 100.0,
|
||||
value: 0.0,
|
||||
@@ -707,73 +752,56 @@ impl ScrollBar {
|
||||
orientation: Orientation::Horizontal,
|
||||
is_dragging: false,
|
||||
offset: Vec2::new(),
|
||||
value_changed: None,
|
||||
value_changed: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_value(ui: &mut UserInterface, handle: &Handle<UINode>, value: f32) {
|
||||
let mut value_changed = None;
|
||||
let old_value;
|
||||
let new_value;
|
||||
let min;
|
||||
let max;
|
||||
let orientation;
|
||||
|
||||
match ui.nodes.borrow_mut(handle) {
|
||||
Some(scroll_bar_node) => {
|
||||
match scroll_bar_node.get_kind_mut() {
|
||||
UINodeKind::ScrollBar(scroll_bar) => {
|
||||
orientation = scroll_bar.orientation;
|
||||
min = scroll_bar.min;
|
||||
max = scroll_bar.max;
|
||||
old_value = scroll_bar.value;
|
||||
new_value = math::clampf(value, min, max);
|
||||
if new_value != old_value {
|
||||
scroll_bar.value = new_value;
|
||||
value_changed = scroll_bar.value_changed.take();
|
||||
}
|
||||
}
|
||||
_ => return
|
||||
}
|
||||
}
|
||||
_ => return
|
||||
pub fn set_value(&mut self, value: f32) {
|
||||
let old_value = self.value;
|
||||
let new_value = math::clampf(value, self.min, self.max);
|
||||
if new_value != old_value {
|
||||
self.value = new_value;
|
||||
self.value_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref mut handler) = value_changed {
|
||||
handler(ui, handle.clone(), new_value, old_value);
|
||||
}
|
||||
impl Layout for ScrollBar {
|
||||
fn measure_override(&mut self, ui: &mut UserInterface, children: &UnsafeCollectionView<Handle<UINode>>, available_size: &Vec2) -> Vec2 {
|
||||
ui.default_measure_override(children, available_size)
|
||||
}
|
||||
|
||||
if let Some(scroll_bar_node) = ui.nodes.borrow_mut(handle) {
|
||||
if let UINodeKind::ScrollBar(scroll_bar) = scroll_bar_node.get_kind_mut() {
|
||||
scroll_bar.value_changed = value_changed.take();
|
||||
}
|
||||
}
|
||||
fn arrange_override(&self, ui: &mut UserInterface, children: &UnsafeCollectionView<Handle<UINode>>, final_size: &Vec2) -> Vec2 {
|
||||
let size = ui.default_arrange_override(children, final_size);
|
||||
|
||||
// Update indicator
|
||||
let percent = (new_value - min) / (max - min);
|
||||
// Adjust indicator position according to current value
|
||||
let percent = (self.value - self.min) / (self.max - self.min);
|
||||
|
||||
let field_size = match ui.borrow_by_name_down(handle, Self::PART_CANVAS) {
|
||||
let field_size = match ui.borrow_by_name_down(&self.owner_handle, Self::PART_CANVAS) {
|
||||
Some(canvas) => canvas.actual_size,
|
||||
None => {
|
||||
println!("Unable to find part canvas!");
|
||||
return;
|
||||
}
|
||||
None => return size
|
||||
};
|
||||
|
||||
if let Some(node) = ui.borrow_by_name_down_mut(handle, Self::PART_INDICATOR) {
|
||||
match orientation {
|
||||
if let Some(node) = ui.borrow_by_name_down_mut(&self.owner_handle, Self::PART_INDICATOR) {
|
||||
match self.orientation {
|
||||
Orientation::Horizontal => {
|
||||
node.desired_local_position.x = percent * maxf(0.0, field_size.x - node.actual_size.x);
|
||||
node.desired_local_position.y = 0.0;
|
||||
node.set_desired_local_position(Vec2::make(
|
||||
percent * maxf(0.0, field_size.x - node.actual_size.x),
|
||||
0.0)
|
||||
);
|
||||
node.height = field_size.y;
|
||||
}
|
||||
Orientation::Vertical => {
|
||||
node.desired_local_position.x = 0.0;
|
||||
node.desired_local_position.y = percent * maxf(0.0, field_size.y - node.actual_size.y);
|
||||
node.set_desired_local_position(Vec2::make(
|
||||
0.0,
|
||||
percent * maxf(0.0, field_size.y - node.actual_size.y))
|
||||
);
|
||||
node.width = field_size.x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size
|
||||
}
|
||||
}
|
||||
|
||||
@@ -867,25 +895,21 @@ impl ScrollBarBuilder {
|
||||
Orientation::Horizontal => std::f32::NAN,
|
||||
Orientation::Vertical => 30.0
|
||||
})
|
||||
.with_text("<")
|
||||
.with_text(match orientation {
|
||||
Orientation::Horizontal => "<",
|
||||
Orientation::Vertical => "^"
|
||||
})
|
||||
.with_click(Box::new(move |ui, handle| {
|
||||
let scroll_bar_handle = ui.find_by_criteria_up(&handle, |node| match node.kind {
|
||||
UINodeKind::ScrollBar(..) => true,
|
||||
_ => false
|
||||
});
|
||||
|
||||
let new_value = if let Some(scroll_bar_node) = ui.nodes.borrow(&scroll_bar_handle) {
|
||||
if let UINodeKind::ScrollBar(scroll_bar) = scroll_bar_node.get_kind() {
|
||||
scroll_bar.value - scroll_bar.step
|
||||
} else {
|
||||
return;
|
||||
if let Some(scroll_bar_node) = ui.nodes.borrow_mut(&scroll_bar_handle) {
|
||||
if let UINodeKind::ScrollBar(scroll_bar) = scroll_bar_node.get_kind_mut() {
|
||||
scroll_bar.set_value(scroll_bar.value - scroll_bar.step);
|
||||
}
|
||||
} else {
|
||||
println!("ScrollBar state is already borrowed!");
|
||||
return;
|
||||
};
|
||||
|
||||
ScrollBar::set_value(ui, &scroll_bar_handle, new_value);
|
||||
}
|
||||
}))
|
||||
.build(ui)
|
||||
)
|
||||
@@ -902,7 +926,10 @@ impl ScrollBarBuilder {
|
||||
.with_child(BorderBuilder::new()
|
||||
.with_name(ScrollBar::PART_INDICATOR)
|
||||
.with_stroke_color(Color::opaque(50, 50, 50))
|
||||
.with_stroke_thickness(Thickness { left: 1.0, top: 0.0, right: 1.0, bottom: 0.0 })
|
||||
.with_stroke_thickness(match orientation {
|
||||
Orientation::Horizontal => Thickness { left: 1.0, top: 0.0, right: 1.0, bottom: 0.0 },
|
||||
Orientation::Vertical => Thickness { left: 0.0, top: 1.0, right: 0.0, bottom: 1.0 }
|
||||
})
|
||||
.with_color(Color::opaque(255, 255, 255))
|
||||
.with_width(30.0)
|
||||
.with_height(30.0)
|
||||
@@ -946,26 +973,25 @@ impl ScrollBarBuilder {
|
||||
_ => return
|
||||
};
|
||||
|
||||
let new_value;
|
||||
if let Some(scroll_bar_node) = ui.borrow_by_criteria_up(&handle, |node| match node.kind {
|
||||
let (field_pos, field_size) =
|
||||
match ui.borrow_by_name_up(&handle, ScrollBar::PART_CANVAS) {
|
||||
Some(canvas) => (canvas.screen_position, canvas.actual_size),
|
||||
None => return
|
||||
};
|
||||
|
||||
let bar_size = match ui.nodes.borrow(&handle) {
|
||||
Some(node) => node.actual_size,
|
||||
None => return
|
||||
};
|
||||
|
||||
if let Some(scroll_bar_node) = ui.borrow_by_criteria_up_mut(&handle, |node| match node.kind {
|
||||
UINodeKind::ScrollBar(..) => true,
|
||||
_ => false
|
||||
}) {
|
||||
if let UINodeKind::ScrollBar(scroll_bar) = scroll_bar_node.get_kind() {
|
||||
if let UINodeKind::ScrollBar(scroll_bar) = scroll_bar_node.get_kind_mut() {
|
||||
let orientation = scroll_bar.orientation;
|
||||
|
||||
if scroll_bar.is_dragging {
|
||||
let bar_size = match ui.nodes.borrow(&handle) {
|
||||
Some(node) => node.actual_size,
|
||||
None => return
|
||||
};
|
||||
|
||||
let (field_pos, field_size) =
|
||||
match ui.borrow_by_name_up(&handle, ScrollBar::PART_CANVAS) {
|
||||
Some(canvas) => (canvas.screen_position, canvas.actual_size),
|
||||
None => return
|
||||
};
|
||||
|
||||
let percent = match orientation {
|
||||
Orientation::Horizontal => {
|
||||
let span = field_size.x - bar_size.x;
|
||||
@@ -987,26 +1013,14 @@ impl ScrollBarBuilder {
|
||||
}
|
||||
};
|
||||
|
||||
new_value = percent * (scroll_bar.max - scroll_bar.min);
|
||||
let new_value = percent * (scroll_bar.max - scroll_bar.min);
|
||||
|
||||
evt.handled = true;
|
||||
} else {
|
||||
return;
|
||||
|
||||
scroll_bar.set_value(new_value);
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
println!("ScrollBar state is already borrowed!");
|
||||
return;
|
||||
}
|
||||
|
||||
let scroll_bar = ui.find_by_criteria_up(&handle, |node| match node.kind {
|
||||
UINodeKind::ScrollBar(..) => true,
|
||||
_ => false
|
||||
});
|
||||
|
||||
ScrollBar::set_value(ui, &scroll_bar, new_value);
|
||||
}))
|
||||
.build(ui)
|
||||
)
|
||||
@@ -1035,20 +1049,16 @@ impl ScrollBarBuilder {
|
||||
_ => false
|
||||
});
|
||||
|
||||
let new_value = if let Some(scroll_bar_node) = ui.nodes.borrow(&scroll_bar_handle) {
|
||||
if let UINodeKind::ScrollBar(scroll_bar) = scroll_bar_node.get_kind() {
|
||||
scroll_bar.value + scroll_bar.step
|
||||
} else {
|
||||
return;
|
||||
if let Some(scroll_bar_node) = ui.nodes.borrow_mut(&scroll_bar_handle) {
|
||||
if let UINodeKind::ScrollBar(scroll_bar) = scroll_bar_node.get_kind_mut() {
|
||||
scroll_bar.set_value(scroll_bar.value + scroll_bar.step);
|
||||
}
|
||||
} else {
|
||||
println!("ScrollBar state is already borrowed!");
|
||||
return;
|
||||
};
|
||||
|
||||
ScrollBar::set_value(ui, &scroll_bar_handle, new_value);
|
||||
}
|
||||
}))
|
||||
.with_text(">")
|
||||
.with_text(match orientation {
|
||||
Orientation::Horizontal => ">",
|
||||
Orientation::Vertical => "v"
|
||||
})
|
||||
.build(ui)
|
||||
)
|
||||
.build(ui)
|
||||
@@ -1056,27 +1066,70 @@ impl ScrollBarBuilder {
|
||||
.build(ui)
|
||||
)
|
||||
.build(ui);
|
||||
// We have to defer update of scroll bar indicator, because it can't be update right now since
|
||||
// we do not have enough information about environment.
|
||||
ui.begin_invoke({
|
||||
let scroll_bar_handle = scroll_bar_handle.clone();
|
||||
Box::new(move |ui| {
|
||||
ScrollBar::set_value(ui, &scroll_bar_handle, min);
|
||||
})
|
||||
});
|
||||
|
||||
scroll_bar_handle
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ScrollContentPresenter {
|
||||
owner_handle: Handle<UINode>,
|
||||
scroll: Vec2,
|
||||
vertical_scroll_allowed: bool,
|
||||
horizontal_scroll_allowed: bool,
|
||||
}
|
||||
|
||||
impl Layout for ScrollContentPresenter {
|
||||
fn measure_override(&mut self, ui: &mut UserInterface, children: &UnsafeCollectionView<Handle<UINode>>, available_size: &Vec2) -> Vec2 {
|
||||
let size_for_child = Vec2::make(
|
||||
if self.horizontal_scroll_allowed {
|
||||
std::f32::INFINITY
|
||||
} else {
|
||||
available_size.x
|
||||
},
|
||||
if self.vertical_scroll_allowed {
|
||||
std::f32::INFINITY
|
||||
} else {
|
||||
available_size.y
|
||||
},
|
||||
);
|
||||
|
||||
let mut desired_size = Vec2::new();
|
||||
for child_handle in children.iter() {
|
||||
ui.measure(child_handle, &size_for_child);
|
||||
|
||||
if let Some(child) = ui.nodes.borrow(child_handle) {
|
||||
if child.desired_size.x > desired_size.x {
|
||||
desired_size.x = child.desired_size.x;
|
||||
}
|
||||
if child.desired_size.y > desired_size.y {
|
||||
desired_size.y = child.desired_size.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
desired_size
|
||||
}
|
||||
|
||||
fn arrange_override(&self, ui: &mut UserInterface, children: &UnsafeCollectionView<Handle<UINode>>, final_size: &Vec2) -> Vec2 {
|
||||
let child_rect = Rect::new(
|
||||
-self.scroll.x,
|
||||
-self.scroll.y,
|
||||
final_size.x + self.scroll.x,
|
||||
final_size.y + self.scroll.y,
|
||||
);
|
||||
|
||||
for child_handle in children.iter() {
|
||||
ui.arrange(child_handle, &child_rect);
|
||||
}
|
||||
|
||||
*final_size
|
||||
}
|
||||
}
|
||||
|
||||
impl ScrollContentPresenter {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
owner_handle: Handle::none(),
|
||||
scroll: Vec2::new(),
|
||||
vertical_scroll_allowed: true,
|
||||
horizontal_scroll_allowed: true,
|
||||
@@ -1132,6 +1185,129 @@ impl ScrollContentPresenterBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ScrollViewer {
|
||||
owner_handle: Handle<UINode>,
|
||||
}
|
||||
|
||||
impl ScrollViewer {
|
||||
pub const PART_CONTENT_PRESENTER: &'static str = "PART_ContentPresenter";
|
||||
pub const PART_V_SCROLL_BAR: &'static str = "PART_VScrollBar";
|
||||
pub const PART_H_SCROLL_BAR: &'static str = "PART_HScrollBar";
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
owner_handle: Handle::none(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for ScrollViewer {
|
||||
fn measure_override(&mut self, ui: &mut UserInterface, children: &UnsafeCollectionView<Handle<UINode>>, available_size: &Vec2) -> Vec2 {
|
||||
// Use default measure.
|
||||
let desired_size = ui.default_measure_override(children, available_size);
|
||||
|
||||
// Try to find parts in children first.
|
||||
let mut content_presenter_handle = Handle::none();
|
||||
let mut horizontal_scroll_bar_handle = Handle::none();
|
||||
let mut vertical_scroll_bar_handle = Handle::none();
|
||||
|
||||
let cp = ui.find_by_name_down(&self.owner_handle, ScrollViewer::PART_CONTENT_PRESENTER);
|
||||
if cp.is_some() {
|
||||
content_presenter_handle = cp;
|
||||
}
|
||||
|
||||
let hor_scroll_bar = ui.find_by_name_down(&self.owner_handle, ScrollViewer::PART_H_SCROLL_BAR);
|
||||
if hor_scroll_bar.is_some() {
|
||||
horizontal_scroll_bar_handle = hor_scroll_bar;
|
||||
}
|
||||
|
||||
let ver_scroll_bar = ui.find_by_name_down(&self.owner_handle, ScrollViewer::PART_V_SCROLL_BAR);
|
||||
if ver_scroll_bar.is_some() {
|
||||
vertical_scroll_bar_handle = ver_scroll_bar;
|
||||
}
|
||||
|
||||
let mut content_size = Vec2::new();
|
||||
let mut available_size_for_content = Vec2::new();
|
||||
if let Some(content_presenter) = ui.nodes.borrow(&content_presenter_handle) {
|
||||
available_size_for_content = content_presenter.desired_size;
|
||||
for content_handle in content_presenter.children.iter() {
|
||||
if let Some(content) = ui.nodes.borrow(content_handle) {
|
||||
if content.desired_size.x > content_size.x {
|
||||
content_size.x = content.desired_size.x;
|
||||
}
|
||||
if content.desired_size.y > content_size.y {
|
||||
content_size.y = content.desired_size.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then adjust scroll bars according to content size.
|
||||
|
||||
/*
|
||||
if let Some(horizontal_scroll_bar) = ui.nodes.borrow_mut(&horizontal_scroll_bar_handle) {
|
||||
if let Some()
|
||||
}
|
||||
let max = maxf(0.0, sv -> content -> desired_size.x - sv -> scroll_content_presenter -> desired_size.x);
|
||||
de_gui_scroll_bar_set_max_value(sv -> hor_scroll_bar, max);
|
||||
|
||||
let max = maxf(0.0, sv -> content -> desired_size.y - sv -> scroll_content_presenter -> desired_size.y);
|
||||
de_gui_scroll_bar_set_max_value(sv -> ver_scroll_bar, max);
|
||||
*/
|
||||
|
||||
desired_size
|
||||
}
|
||||
|
||||
fn arrange_override(&self, ui: &mut UserInterface, children: &UnsafeCollectionView<Handle<UINode>>, final_size: &Vec2) -> Vec2 {
|
||||
ui.default_arrange_override(children, final_size)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ScrollViewerBuilder {
|
||||
common: CommonBuilderFields
|
||||
}
|
||||
|
||||
impl ScrollViewerBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
common: CommonBuilderFields::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl_default_builder_methods!();
|
||||
|
||||
pub fn build(self, ui: &mut UserInterface) -> Handle<UINode> {
|
||||
GenericNodeBuilder::new(UINodeKind::ScrollViewer(ScrollViewer::new()), self.common)
|
||||
.with_child(GridBuilder::new()
|
||||
.add_row(Row::stretch())
|
||||
.add_row(Row::strict(20.0))
|
||||
.add_column(Column::stretch())
|
||||
.add_column(Column::strict(20.0))
|
||||
.with_child(ScrollContentPresenterBuilder::new()
|
||||
.with_name(ScrollViewer::PART_CONTENT_PRESENTER)
|
||||
.with_child(BorderBuilder::new()
|
||||
.with_color(Color::opaque(200, 0, 0))
|
||||
.build(ui))
|
||||
.on_row(0)
|
||||
.on_column(0)
|
||||
.build(ui))
|
||||
.with_child(ScrollBarBuilder::new()
|
||||
.with_name(ScrollViewer::PART_H_SCROLL_BAR)
|
||||
.with_orientation(Orientation::Horizontal)
|
||||
.on_row(1)
|
||||
.on_column(0)
|
||||
.build(ui))
|
||||
.with_child(ScrollBarBuilder::new()
|
||||
.with_name(ScrollViewer::PART_V_SCROLL_BAR)
|
||||
.with_orientation(Orientation::Vertical)
|
||||
.on_row(0)
|
||||
.on_column(1)
|
||||
.build(ui))
|
||||
.build(ui))
|
||||
.build(ui)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum SizeMode {
|
||||
Strict,
|
||||
@@ -1230,11 +1406,23 @@ impl Row {
|
||||
}
|
||||
|
||||
pub struct Grid {
|
||||
owner_handle: Handle<UINode>,
|
||||
rows: Vec<Row>,
|
||||
columns: Vec<Column>,
|
||||
draw_borders: bool,
|
||||
}
|
||||
|
||||
impl Grid {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
owner_handle: Handle::none(),
|
||||
rows: Vec::new(),
|
||||
columns: Vec::new(),
|
||||
draw_borders: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for Grid {
|
||||
fn measure_override(&mut self, ui: &mut UserInterface, children: &UnsafeCollectionView<Handle<UINode>>, available_size: &Vec2) -> Vec2 {
|
||||
// In case of no rows or columns, grid acts like default panel.
|
||||
@@ -1260,10 +1448,8 @@ impl Layout for Grid {
|
||||
col.actual_width = col.desired_width;
|
||||
for child_handle in children.iter() {
|
||||
if let Some(child) = ui.nodes.borrow(child_handle) {
|
||||
if child.column == i && child.visibility == Visibility::Visible {
|
||||
if child.desired_size.x > col.actual_width {
|
||||
col.actual_width = child.desired_size.x;
|
||||
}
|
||||
if child.column == i && child.visibility == Visibility::Visible && child.desired_size.x > col.actual_width {
|
||||
col.actual_width = child.desired_size.x;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1477,11 +1663,11 @@ impl GridBuilder {
|
||||
}
|
||||
|
||||
pub fn build(mut self, ui: &mut UserInterface) -> Handle<UINode> {
|
||||
let node = UINode::new(UINodeKind::Grid(Grid {
|
||||
columns: self.columns,
|
||||
rows: self.rows,
|
||||
draw_borders: false,
|
||||
}));
|
||||
let mut grid = Grid::new();
|
||||
grid.columns = self.columns;
|
||||
grid.rows = self.rows;
|
||||
|
||||
let node = UINode::new(UINodeKind::Grid(grid));
|
||||
|
||||
let handle = ui.add_node(node);
|
||||
self.common.apply(ui, &handle);
|
||||
@@ -1501,7 +1687,17 @@ impl Grid {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Canvas {}
|
||||
pub struct Canvas {
|
||||
owner_handle: Handle<UINode>
|
||||
}
|
||||
|
||||
impl Canvas {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
owner_handle: Handle::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for Canvas {
|
||||
fn measure_override(&mut self, ui: &mut UserInterface, children: &UnsafeCollectionView<Handle<UINode>>, _available_size: &Vec2) -> Vec2 {
|
||||
@@ -1539,29 +1735,28 @@ impl Layout for Canvas {
|
||||
}
|
||||
|
||||
pub enum UINodeKind {
|
||||
Base,
|
||||
Text(Text),
|
||||
Border(Border),
|
||||
/// TODO
|
||||
Window,
|
||||
Button(Button),
|
||||
ScrollBar(ScrollBar),
|
||||
/// TODO
|
||||
ScrollViewer,
|
||||
/// TODO
|
||||
TextBox,
|
||||
/// TODO
|
||||
Image,
|
||||
ScrollViewer(ScrollViewer),
|
||||
Image(Image),
|
||||
/// Automatically arranges children by rows and columns
|
||||
Grid(Grid),
|
||||
/// Allows user to directly set position and size of a node
|
||||
Canvas(Canvas),
|
||||
/// Allows user to scroll content
|
||||
ScrollContentPresenter(ScrollContentPresenter),
|
||||
/// TODO
|
||||
SlideSelector,
|
||||
/// TODO
|
||||
CheckBox,
|
||||
}
|
||||
|
||||
impl Drawable for UINodeKind {
|
||||
fn draw(&mut self, drawing_context: &mut DrawingContext, font_cache: &Pool<Font>, bounds: &Rect<f32>, color: Color) {
|
||||
match self {
|
||||
UINodeKind::Text(text) => text.draw(drawing_context, font_cache, bounds, color),
|
||||
UINodeKind::Border(border) => border.draw(drawing_context, font_cache, bounds, color),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
@@ -1698,25 +1893,46 @@ fn minf(a: f32, b: f32) -> f32 {
|
||||
}
|
||||
}
|
||||
|
||||
struct ArrangeData {
|
||||
size: Vec2,
|
||||
size_without_margin: Vec2,
|
||||
origin: Vec2
|
||||
}
|
||||
|
||||
impl UserInterface {
|
||||
pub fn new(default_font: Handle<Font>) -> UserInterface {
|
||||
let mut nodes = Pool::new();
|
||||
UserInterface {
|
||||
let mut ui = UserInterface {
|
||||
visual_debug: false,
|
||||
default_font,
|
||||
captured_node: Handle::none(),
|
||||
root_canvas: nodes.spawn(UINode::new(UINodeKind::Canvas(Canvas {}))),
|
||||
nodes,
|
||||
root_canvas: Handle::none(),
|
||||
nodes: Pool::new(),
|
||||
mouse_position: Vec2::new(),
|
||||
drawing_context: DrawingContext::new(),
|
||||
picked_node: Handle::none(),
|
||||
prev_picked_node: Handle::none(),
|
||||
deferred_actions: VecDeque::new(),
|
||||
}
|
||||
};
|
||||
ui.root_canvas = ui.add_node(UINode::new(UINodeKind::Canvas(Canvas::new())));
|
||||
ui
|
||||
}
|
||||
|
||||
pub fn add_node(&mut self, node: UINode) -> Handle<UINode> {
|
||||
let node_handle = self.nodes.spawn(node);
|
||||
// Notify kind about owner. This is a bit hackish but it'll make a lot of things easier.
|
||||
if let Some(node) = self.nodes.borrow_mut(&node_handle) {
|
||||
match &mut node.kind {
|
||||
UINodeKind::ScrollBar(scroll_bar) => scroll_bar.owner_handle = node_handle.clone(),
|
||||
UINodeKind::Text(text) => text.owner_handle = node_handle.clone(),
|
||||
UINodeKind::Border(border) => border.owner_handle = node_handle.clone(),
|
||||
UINodeKind::Button(button) => button.owner_handle = node_handle.clone(),
|
||||
UINodeKind::ScrollViewer(scroll_viewer) => scroll_viewer.owner_handle = node_handle.clone(),
|
||||
UINodeKind::Image(image) => image.owner_handle = node_handle.clone(),
|
||||
UINodeKind::Grid(grid) => grid.owner_handle = node_handle.clone(),
|
||||
UINodeKind::Canvas(canvas) => canvas.owner_handle = node_handle.clone(),
|
||||
UINodeKind::ScrollContentPresenter(scp) => scp.owner_handle = node_handle.clone(),
|
||||
}
|
||||
}
|
||||
self.link_nodes(&node_handle, &self.root_canvas.clone());
|
||||
node_handle
|
||||
}
|
||||
@@ -1872,7 +2088,7 @@ impl UserInterface {
|
||||
}
|
||||
}
|
||||
|
||||
let desired_size = (unsafe { &mut *node_kind }).measure_override(self, &children, &size_for_child);
|
||||
let desired_size = (unsafe { &mut *node_kind }).measure_override( self, &children, &size_for_child);
|
||||
|
||||
if let Some(node) = self.nodes.borrow_mut(&node_handle) {
|
||||
node.desired_size = desired_size;
|
||||
@@ -1909,7 +2125,18 @@ impl UserInterface {
|
||||
}
|
||||
}
|
||||
|
||||
fn default_arrange_override(&mut self, children: &UnsafeCollectionView<Handle<UINode>>, final_size: &Vec2) -> Vec2 {
|
||||
let final_rect = Rect::new(0.0, 0.0, final_size.x, final_size.y);
|
||||
|
||||
for child_handle in children.iter() {
|
||||
self.arrange(child_handle, &final_rect);
|
||||
}
|
||||
|
||||
*final_size
|
||||
}
|
||||
|
||||
fn arrange(&mut self, node_handle: &Handle<UINode>, final_rect: &Rect<f32>) {
|
||||
|
||||
let children;
|
||||
let mut size;
|
||||
let size_without_margin;
|
||||
@@ -2032,40 +2259,20 @@ impl UserInterface {
|
||||
let mut children: UnsafeCollectionView<Handle<UINode>> = UnsafeCollectionView::empty();
|
||||
|
||||
if let Some(node) = self.nodes.borrow_mut(node_handle) {
|
||||
let start_index = self.drawing_context.get_commands().len();
|
||||
let bounds = node.get_screen_bounds();
|
||||
|
||||
self.drawing_context.set_nesting(nesting);
|
||||
node.command_indices.push(self.drawing_context.commit_clip_rect(&bounds.inflate(0.9, 0.9)));
|
||||
self.drawing_context.commit_clip_rect(&bounds.inflate(0.9, 0.9));
|
||||
|
||||
match &mut node.kind {
|
||||
UINodeKind::Border(border) => {
|
||||
self.drawing_context.push_rect_filled(&bounds, None, node.color);
|
||||
self.drawing_context.push_rect_vary(&bounds, border.stroke_thickness, border.stroke_color);
|
||||
node.command_indices.push(self.drawing_context.commit(CommandKind::Geometry, 0).unwrap());
|
||||
}
|
||||
UINodeKind::Text(text) => {
|
||||
if text.need_update {
|
||||
if let Some(font) = font_cache.borrow(&text.font) {
|
||||
let formatted_text = FormattedTextBuilder::reuse(text.formatted_text.take().unwrap())
|
||||
.with_size(node.actual_size)
|
||||
.with_font(font)
|
||||
.with_text(text.text.as_str())
|
||||
.with_color(node.color)
|
||||
.with_horizontal_alignment(text.horizontal_alignment)
|
||||
.with_vertical_alignment(text.vertical_alignment)
|
||||
.build();
|
||||
text.formatted_text = Some(formatted_text);
|
||||
}
|
||||
text.need_update = true; // TODO
|
||||
}
|
||||
if let Some(command_index) = self.drawing_context.draw_text(node.screen_position, text.formatted_text.as_ref().unwrap()) {
|
||||
node.command_indices.push(command_index);
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
node.kind.draw(&mut self.drawing_context, font_cache, &bounds, node.color);
|
||||
|
||||
children = UnsafeCollectionView::from_vec(&node.children);
|
||||
|
||||
let end_index = self.drawing_context.get_commands().len();
|
||||
for i in start_index..end_index {
|
||||
node.command_indices.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Continue on children
|
||||
@@ -2111,21 +2318,16 @@ impl UserInterface {
|
||||
|
||||
for command_index in node.command_indices.iter() {
|
||||
if let Some(command) = self.drawing_context.get_commands().get(*command_index) {
|
||||
if *command.get_kind() == CommandKind::Clip {
|
||||
if self.drawing_context.is_command_contains_point(command, pt) {
|
||||
clipped = false;
|
||||
|
||||
break;
|
||||
}
|
||||
if *command.get_kind() == CommandKind::Clip && self.drawing_context.is_command_contains_point(command, pt) {
|
||||
clipped = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Point can be clipped by parent's clipping geometry.
|
||||
if !node.parent.is_none() {
|
||||
if !clipped {
|
||||
clipped |= self.is_node_clipped(&node.parent, pt);
|
||||
}
|
||||
if !node.parent.is_none() && !clipped {
|
||||
clipped |= self.is_node_clipped(&node.parent, pt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2141,10 +2343,8 @@ impl UserInterface {
|
||||
if !self.is_node_clipped(node_handle, pt) {
|
||||
for command_index in node.command_indices.iter() {
|
||||
if let Some(command) = self.drawing_context.get_commands().get(*command_index) {
|
||||
if *command.get_kind() == CommandKind::Geometry {
|
||||
if self.drawing_context.is_command_contains_point(command, pt) {
|
||||
return true;
|
||||
}
|
||||
if *command.get_kind() == CommandKind::Geometry && self.drawing_context.is_command_contains_point(command, pt) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -110,11 +110,11 @@ pub fn vec3_to_vec2_by_plane(plane_class: PlaneClass, normal: Vec3, point: Vec3)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_point_inside_2d_triangle(point: Vec2, a: Vec2, b: Vec2, c: Vec2) -> bool {
|
||||
let ba = b - a;
|
||||
let ca = c - a;
|
||||
pub fn is_point_inside_2d_triangle(point: Vec2, pt_a: Vec2, pt_b: Vec2, pt_c: Vec2) -> bool {
|
||||
let ba = pt_b - pt_a;
|
||||
let ca = pt_c - pt_a;
|
||||
|
||||
let vp = point - a;
|
||||
let vp = point - pt_a;
|
||||
|
||||
let ba_dot_ba = ba.dot(ba);
|
||||
let ca_dot_ba = ca.dot(ba);
|
||||
|
||||
+2
-2
@@ -43,7 +43,7 @@ impl Ray {
|
||||
let discr_root = discriminant.sqrt();
|
||||
let r1 = (-b + discr_root) / 2.0;
|
||||
let r2 = (-b - discr_root) / 2.0;
|
||||
return Some((self.origin + self.dir.scale(r1), self.origin + self.dir.scale(r2)));
|
||||
Some((self.origin + self.dir.scale(r1), self.origin + self.dir.scale(r2)))
|
||||
}
|
||||
|
||||
/// Checks intersection with sphere.
|
||||
@@ -54,7 +54,7 @@ impl Ray {
|
||||
let b = 2.0 * self.dir.dot(&d);
|
||||
let c = d.dot(&d) - radius * radius;
|
||||
let discriminant = b * b - 4.0 * a * c;
|
||||
return discriminant >= 0.0;
|
||||
discriminant >= 0.0
|
||||
}
|
||||
|
||||
/// Returns t factor (at pt=o+d*t equation) for projection of given point at ray
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::{
|
||||
math::{
|
||||
vec2::*,
|
||||
vec3::*,
|
||||
self
|
||||
self,
|
||||
}
|
||||
};
|
||||
use std::fmt;
|
||||
@@ -80,10 +80,9 @@ fn is_ear(poly: &Polygon, prev: &Vertex, ear: &Vertex, next: &Vertex) -> bool {
|
||||
let mut i = poly.head;
|
||||
loop {
|
||||
let vertex = &poly.vertices[i];
|
||||
if i != prev.index && i != ear.index && i != next.index {
|
||||
if math::is_point_inside_2d_triangle(vertex.position, prev.position, ear.position, next.position) {
|
||||
return false;
|
||||
}
|
||||
if i != prev.index && i != ear.index && i != next.index &&
|
||||
math::is_point_inside_2d_triangle(vertex.position, prev.position, ear.position, next.position) {
|
||||
return false;
|
||||
}
|
||||
i = vertex.next;
|
||||
if i == poly.head {
|
||||
@@ -91,7 +90,7 @@ fn is_ear(poly: &Polygon, prev: &Vertex, ear: &Vertex, next: &Vertex) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
true
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
@@ -635,7 +635,7 @@ impl Renderer {
|
||||
1.0);
|
||||
gl::UniformMatrix4fv(self.ui_shader.wvp_matrix, 1, gl::FALSE, ortho.f.as_ptr() as *const f32);
|
||||
|
||||
for cmd in drawing_context.get_command_buffer() {
|
||||
for cmd in drawing_context.get_commands() {
|
||||
let index_count = cmd.get_triangle_count() * 3;
|
||||
if cmd.get_nesting() != 0 {
|
||||
gl::Enable(gl::STENCIL_TEST);
|
||||
|
||||
+12
-14
@@ -4,7 +4,7 @@ use crate::{
|
||||
math::{vec4::*, vec3::*, vec2::*, mat4::*, quat::*, triangulator::*},
|
||||
scene::{*, node::*},
|
||||
renderer::surface::{SurfaceSharedData, Surface, Vertex},
|
||||
engine::State
|
||||
engine::State,
|
||||
};
|
||||
|
||||
pub enum FbxAttribute {
|
||||
@@ -291,18 +291,18 @@ struct FbxNode {
|
||||
|
||||
impl FbxNode {
|
||||
fn get_vec3_at(&self, n: usize) -> Result<Vec3, String> {
|
||||
return Ok(Vec3 {
|
||||
Ok(Vec3 {
|
||||
x: self.get_attrib(n)?.as_f32()?,
|
||||
y: self.get_attrib(n + 1)?.as_f32()?,
|
||||
z: self.get_attrib(n + 2)?.as_f32()?,
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
fn get_vec2_at(&self, n: usize) -> Result<Vec2, String> {
|
||||
return Ok(Vec2 {
|
||||
Ok(Vec2 {
|
||||
x: self.get_attrib(n)?.as_f32()?,
|
||||
y: self.get_attrib(n + 1)?.as_f32()?,
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
fn get_attrib(&self, n: usize) -> Result<&FbxAttribute, String> {
|
||||
@@ -448,7 +448,7 @@ impl FbxGeometry {
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(geom);
|
||||
Ok(geom)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,7 +559,7 @@ impl FbxModel {
|
||||
_ => () // Unused properties
|
||||
}
|
||||
}
|
||||
return Ok(model);
|
||||
Ok(model)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -807,12 +807,10 @@ fn read_ascii(path: &Path) -> Result<Fbx, String> {
|
||||
return Err(String::from("FBX: Failed to fetch node by handle when committing attribute"));
|
||||
}
|
||||
value.clear();
|
||||
} else if !read_value {
|
||||
name.push(symbol);
|
||||
} else {
|
||||
if !read_value {
|
||||
name.push(symbol);
|
||||
} else {
|
||||
value.push(symbol);
|
||||
}
|
||||
value.push(symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -912,7 +910,7 @@ fn prepare_next_face(geom: &FbxGeometry,
|
||||
}
|
||||
}
|
||||
|
||||
return vertex_per_face;
|
||||
vertex_per_face
|
||||
}
|
||||
|
||||
fn convert_vertex(geom: &FbxGeometry,
|
||||
@@ -1057,7 +1055,7 @@ impl Fbx {
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn convert_light(&self, light: &mut Light, fbx_light: &FbxLight) {
|
||||
|
||||
+24
-27
@@ -3,16 +3,16 @@
|
||||
use crate::{
|
||||
math::{
|
||||
vec2::Vec2,
|
||||
Rect
|
||||
Rect,
|
||||
},
|
||||
utils::pool::{Pool, Handle}
|
||||
utils::pool::{Pool, Handle},
|
||||
};
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
collections::HashMap,
|
||||
path::{Path},
|
||||
path::Path,
|
||||
fs::File,
|
||||
io::Read
|
||||
io::Read,
|
||||
};
|
||||
|
||||
const ON_CURVE_POINT: u8 = 1;
|
||||
@@ -214,7 +214,7 @@ impl Bitmap {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return self.pixels[y * self.width + x] as f32 / 255.0;
|
||||
self.pixels[y * self.width + x] as f32 / 255.0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ fn get_u16(p: *const u8) -> u16
|
||||
unsafe {
|
||||
let b0 = *p as u32;
|
||||
let b1 = *p.offset(1) as u32;
|
||||
return (b0 * 256 + b1) as u16;
|
||||
(b0 * 256 + b1) as u16
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ fn get_i16(p: *const u8) -> i16
|
||||
unsafe {
|
||||
let b0 = *p as i32;
|
||||
let b1 = *p.offset(1) as i32;
|
||||
return (b0 * 256 + b1) as i16;
|
||||
(b0 * 256 + b1) as i16
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ fn get_u32(p: *const u8) -> u32
|
||||
let b1 = *p.offset(1) as u32;
|
||||
let b2 = *p.offset(2) as u32;
|
||||
let b3 = *p.offset(3) as u32;
|
||||
return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
|
||||
(b0 << 24) + (b1 << 16) + (b2 << 8) + b3
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,7 +280,7 @@ fn segmented_mapping(subtable: *const u8, unicode: u32) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,7 +292,7 @@ fn direct_mapping(subtable: *const u8, unicode: u32) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
0
|
||||
}
|
||||
|
||||
fn dense_mapping(subtable: *const u8, unicode: u32) -> usize {
|
||||
@@ -306,7 +306,7 @@ fn dense_mapping(subtable: *const u8, unicode: u32) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
0
|
||||
}
|
||||
|
||||
fn line_line_intersection(a: &Line2, b: &Line2) -> Option<Point> {
|
||||
@@ -393,8 +393,8 @@ fn polygons_to_scanlines(polys: &Vec<Polygon>, width: f32, height: f32, scale: f
|
||||
if intersections.len() > 0 {
|
||||
for i in (0..(intersections.len() - 1)).step_by(2) {
|
||||
let line = Line2 {
|
||||
begin: Point { x: intersections[i].x, y: y, flags: 0 },
|
||||
end: Point { x: intersections[i + 1].x, y: y, flags: 0 },
|
||||
begin: Point { x: intersections[i].x, y, flags: 0 },
|
||||
end: Point { x: intersections[i + 1].x, y, flags: 0 },
|
||||
};
|
||||
lines.push(line);
|
||||
}
|
||||
@@ -447,7 +447,7 @@ fn raster_scanlines(w: usize, h: usize, lines: &Vec<Line2>) -> Bitmap {
|
||||
}
|
||||
}
|
||||
|
||||
return out_bitmap;
|
||||
out_bitmap
|
||||
}
|
||||
|
||||
impl TrueType {
|
||||
@@ -521,7 +521,7 @@ impl TrueType {
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
0
|
||||
}
|
||||
|
||||
fn get_glyph_offset(&self, index: usize) -> isize {
|
||||
@@ -673,11 +673,9 @@ impl TrueType {
|
||||
let dx = *coords as i32;
|
||||
coords = coords.offset(1);
|
||||
x += if (pt.flags & 16) != 0 { dx } else { -dx };
|
||||
} else {
|
||||
if (pt.flags & 16) == 0 {
|
||||
x += get_i16(coords) as i32;
|
||||
coords = coords.offset(2);
|
||||
}
|
||||
} else if (pt.flags & 16) == 0 {
|
||||
x += get_i16(coords) as i32;
|
||||
coords = coords.offset(2);
|
||||
}
|
||||
pt.x = x as f32;
|
||||
}
|
||||
@@ -690,12 +688,11 @@ impl TrueType {
|
||||
let dy = *coords as i32;
|
||||
coords = coords.offset(1);
|
||||
y += if (pt.flags & 32) != 0 { dy } else { -dy };
|
||||
} else {
|
||||
if (pt.flags & 32) == 0 {
|
||||
y += get_i16(coords) as i32;
|
||||
coords = coords.offset(2);
|
||||
}
|
||||
} else if (pt.flags & 32) == 0 {
|
||||
y += get_i16(coords) as i32;
|
||||
coords = coords.offset(2);
|
||||
}
|
||||
|
||||
pt.y = y as f32;
|
||||
}
|
||||
|
||||
@@ -941,7 +938,7 @@ impl Font {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_texture_id(&mut self, id: u32) {
|
||||
pub fn set_texture_id(&mut self, id: u32) {
|
||||
self.texture_id = id;
|
||||
}
|
||||
|
||||
@@ -1057,7 +1054,7 @@ impl FontGlyph {
|
||||
#[test]
|
||||
fn font_test() {
|
||||
use image::ColorType;
|
||||
use std::path::{PathBuf};
|
||||
use std::path::PathBuf;
|
||||
|
||||
let font = Font::load(Path::new("data/fonts/font.ttf"), 40.0, (0..255).collect()).unwrap();
|
||||
let raster_path = Path::new("data/raster");
|
||||
|
||||
Reference in New Issue
Block a user