mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
bug fixes, api improvements
This commit is contained in:
Generated
+12
-14
@@ -8,26 +8,24 @@
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Cargo.lock" beforeDir="false" afterPath="$PROJECT_DIR$/Cargo.lock" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Cargo.toml" beforeDir="false" afterPath="$PROJECT_DIR$/Cargo.toml" 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/gui/border.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/border.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/button.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/button.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/canvas.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/canvas.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/event.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/event.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/formatted_text.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/formatted_text.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/grid.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/grid.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/image.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/image.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/list_box.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/list_box.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/gui/node.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/node.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/scroll_bar.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/scroll_bar.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/scroll_content_presenter.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/scroll_content_presenter.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/scroll_viewer.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/scroll_viewer.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/stack_panel.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/stack_panel.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/text.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/text.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/text_box.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/text_box.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/widget.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/widget.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/window.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/window.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/renderer/deferred_light_renderer.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/renderer/deferred_light_renderer.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/renderer/gpu_program.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/renderer/gpu_program.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/renderer/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/renderer/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/renderer/shaders/ui_fs.glsl" beforeDir="false" afterPath="$PROJECT_DIR$/src/renderer/shaders/ui_fs.glsl" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/renderer/ui_renderer.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/renderer/ui_renderer.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/resource/ttf.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/resource/ttf.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/base.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/scene/base.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/scene/graph.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/scene/graph.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/utils/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/utils/mod.rs" afterDir="false" />
|
||||
</list>
|
||||
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
|
||||
Generated
+7
-7
@@ -883,7 +883,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rg3d"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
dependencies = [
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glutin 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -892,14 +892,14 @@ dependencies = [
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lexical 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rg3d-core 0.1.6",
|
||||
"rg3d-physics 0.1.6",
|
||||
"rg3d-core 0.1.8",
|
||||
"rg3d-physics 0.1.7",
|
||||
"rg3d-sound 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rg3d-core"
|
||||
version = "0.1.6"
|
||||
version = "0.1.8"
|
||||
dependencies = [
|
||||
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -908,10 +908,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rg3d-physics"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rg3d-core 0.1.6",
|
||||
"rg3d-core 0.1.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -919,7 +919,7 @@ name = "rg3d-sound"
|
||||
version = "0.1.3"
|
||||
dependencies = [
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rg3d-core 0.1.6",
|
||||
"rg3d-core 0.1.8",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rg3d"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
authors = ["Dmitry Stepanov <[email protected]>"]
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# RG3D
|
||||
|
||||
3d game engine written in Rust. This project ports many features from [DmitrysEngine](https://github.com/mrDIMAS/DmitrysEngine) (written in C).
|
||||
3D game engine written in Rust.
|
||||
|
||||
WARNING: Some places are semi-complete or just does not implemented yet, this engine is not in production-ready state yet.
|
||||
|
||||
@@ -25,16 +25,19 @@ These screenshots are from [rusty-shooter](https://github.com/mrDIMAS/rusty-shoo
|
||||
- Button
|
||||
- Canvas (layout panel)
|
||||
- Grid (layout panel)
|
||||
- Stack panel
|
||||
- Scroll bar
|
||||
- Scroll viewer
|
||||
- Scroll content presenter
|
||||
- Text
|
||||
- Text box
|
||||
- List box
|
||||
- Window
|
||||
- Fonts - TTF Loader (compound characters are not supported yet)
|
||||
- Built-in save/load using object visitor - save/load state of engine in one call.
|
||||
- Skinning
|
||||
- Animation blending - allows you to blend your animations as you want to, i.e. idle animation can be blended with walk.
|
||||
- Animation retargetting - allows you to remap animation from one model to another
|
||||
- Animation retargetting - allows you to remap animation from one model to another.
|
||||
- Automatic resource management
|
||||
- Texture
|
||||
- Models
|
||||
@@ -45,12 +48,18 @@ These screenshots are from [rusty-shooter](https://github.com/mrDIMAS/rusty-shoo
|
||||
- Bump mapping
|
||||
- Particle systems with soft particles.
|
||||
- Sounds - using [rg3d-sound](https://github.com/mrDIMAS/rg3d-sound) crate.
|
||||
- Physics - using [rg3d-physics](https://github.com/mrDIMAS/rg3d-physics crate.
|
||||
- Physics - using [rg3d-physics](https://github.com/mrDIMAS/rg3d-physics) crate.
|
||||
|
||||
### What will be added soon?
|
||||
|
||||
- Shadows
|
||||
|
||||
### Plans
|
||||
|
||||
- Optimization - some places of engine lacks optimization - there is still no culling, space partitioning for physics, etc.
|
||||
- Simple editor - would be so nice to have, but until UI is not stabilized enough there is no point to try to write editor.
|
||||
- Documentation - it is still incomplete because engine contstantly changing its API.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- glutin - window and OpenGL initialization
|
||||
|
||||
@@ -67,6 +67,10 @@ impl TextLine {
|
||||
pub fn len(&self) -> usize {
|
||||
self.end - self.begin
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.end == self.begin
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FormattedText {
|
||||
@@ -270,6 +274,12 @@ pub struct FormattedTextBuilder {
|
||||
horizontal_alignment: HorizontalAlignment,
|
||||
}
|
||||
|
||||
impl Default for FormattedTextBuilder {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl FormattedTextBuilder {
|
||||
/// Creates new formatted text builder with default parameters.
|
||||
pub fn new() -> FormattedTextBuilder {
|
||||
|
||||
+42
-4
@@ -7,14 +7,17 @@ use crate::{
|
||||
widget::{Widget, AsWidget},
|
||||
Layout,
|
||||
UserInterface,
|
||||
Update
|
||||
}
|
||||
Update,
|
||||
},
|
||||
};
|
||||
use rg3d_core::math::vec2::Vec2;
|
||||
use crate::gui::node::UINode;
|
||||
use rg3d_core::pool::Handle;
|
||||
use crate::gui::widget::WidgetBuilder;
|
||||
|
||||
pub struct Image {
|
||||
widget: Widget,
|
||||
texture: Arc<Mutex<Texture>>,
|
||||
texture: Option<Arc<Mutex<Texture>>>,
|
||||
}
|
||||
|
||||
impl AsWidget for Image {
|
||||
@@ -31,7 +34,9 @@ impl Draw for Image {
|
||||
fn draw(&mut self, drawing_context: &mut DrawingContext) {
|
||||
let bounds = self.widget.get_screen_bounds();
|
||||
drawing_context.push_rect_filled(&bounds, None, self.widget.color);
|
||||
drawing_context.commit(CommandKind::Geometry, CommandTexture::Texture(self.texture.clone()))
|
||||
let texture = self.texture.as_ref().map_or(CommandTexture::None,
|
||||
|t| { CommandTexture::Texture(t.clone()) });
|
||||
drawing_context.commit(CommandKind::Geometry, texture);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,4 +54,37 @@ impl Update for Image {
|
||||
fn update(&mut self, dt: f32) {
|
||||
self.widget.update(dt)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ImageBuilder {
|
||||
widget_builder: WidgetBuilder,
|
||||
texture: Option<Arc<Mutex<Texture>>>,
|
||||
}
|
||||
|
||||
impl ImageBuilder {
|
||||
pub fn new(widget_builder: WidgetBuilder) -> Self {
|
||||
Self {
|
||||
widget_builder,
|
||||
texture: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_texture(mut self, texture: Arc<Mutex<Texture>>) -> Self {
|
||||
self.texture = Some(texture);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_opt_texture(mut self, texture: Option<Arc<Mutex<Texture>>>) -> Self {
|
||||
self.texture = texture;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self, ui: &mut UserInterface) -> Handle<UINode> {
|
||||
let image = UINode::Image(Image {
|
||||
widget: self.widget_builder.build(),
|
||||
texture: self.texture,
|
||||
});
|
||||
|
||||
ui.add_node(image)
|
||||
}
|
||||
}
|
||||
+41
-32
@@ -31,8 +31,8 @@ use crate::{
|
||||
event::{
|
||||
UIEvent,
|
||||
UIEventKind,
|
||||
UIEventHandler
|
||||
}
|
||||
UIEventHandler,
|
||||
},
|
||||
},
|
||||
resource::{ttf::Font},
|
||||
utils::UnsafeCollectionView,
|
||||
@@ -71,22 +71,28 @@ pub struct Thickness {
|
||||
}
|
||||
|
||||
impl Thickness {
|
||||
pub fn zero() -> Thickness {
|
||||
Thickness {
|
||||
left: 0.0,
|
||||
top: 0.0,
|
||||
right: 0.0,
|
||||
bottom: 0.0,
|
||||
}
|
||||
pub fn zero() -> Self {
|
||||
Self { left: 0.0, top: 0.0, right: 0.0, bottom: 0.0 }
|
||||
}
|
||||
|
||||
pub fn uniform(v: f32) -> Thickness {
|
||||
Thickness {
|
||||
left: v,
|
||||
top: v,
|
||||
right: v,
|
||||
bottom: v,
|
||||
}
|
||||
pub fn uniform(v: f32) -> Self {
|
||||
Self { left: v, top: v, right: v, bottom: v }
|
||||
}
|
||||
|
||||
pub fn bottom(v: f32) -> Self {
|
||||
Self { left: 0.0, top: 0.0, right: 0.0, bottom: v }
|
||||
}
|
||||
|
||||
pub fn top(v: f32) -> Self {
|
||||
Self { left: 0.0, top: v, right: 0.0, bottom: 0.0 }
|
||||
}
|
||||
|
||||
pub fn left(v: f32) -> Self {
|
||||
Self { left: v, top: 0.0, right: 0.0, bottom: 0.0 }
|
||||
}
|
||||
|
||||
pub fn right(v: f32) -> Self {
|
||||
Self { left: 0.0, top: 0.0, right: v, bottom: 0.0 }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +155,7 @@ fn minf(a: f32, b: f32) -> f32 {
|
||||
impl UserInterface {
|
||||
pub(in crate) fn new() -> UserInterface {
|
||||
let font_bytes = std::include_bytes!("../built_in_font.ttf").to_vec();
|
||||
let font = Font::from_memory(font_bytes, 20.0, (0..255).collect()).unwrap();
|
||||
let font = Font::from_memory(font_bytes, 20.0, Font::default_char_set()).unwrap();
|
||||
let font = Rc::new(RefCell::new(font));
|
||||
let mut ui = UserInterface {
|
||||
events: VecDeque::new(),
|
||||
@@ -400,28 +406,31 @@ impl UserInterface {
|
||||
widget.arrange_valid.set(true);
|
||||
}
|
||||
|
||||
fn update_transform(&mut self, node_handle: Handle<UINode>) {
|
||||
let screen_position;
|
||||
fn update_node(&mut self, node_handle: Handle<UINode>) {
|
||||
let widget = self.nodes.borrow(node_handle).widget();
|
||||
let children = UnsafeCollectionView::from_slice(&widget.children);
|
||||
if widget.parent.is_some() {
|
||||
screen_position = widget.actual_local_position.get() + self.nodes.borrow(widget.parent).widget().screen_position;
|
||||
} else {
|
||||
screen_position = widget.actual_local_position.get();
|
||||
}
|
||||
let (screen_position, parent_visibility) =
|
||||
if widget.parent.is_some() {
|
||||
let parent_widget = self.nodes.borrow(widget.parent).widget();
|
||||
(widget.actual_local_position.get() + parent_widget.screen_position, parent_widget.global_visibility)
|
||||
} else {
|
||||
(widget.actual_local_position.get(), true)
|
||||
};
|
||||
|
||||
self.nodes.borrow_mut(node_handle).widget_mut().screen_position = screen_position;
|
||||
let widget = self.nodes.borrow_mut(node_handle).widget_mut();
|
||||
widget.screen_position = screen_position;
|
||||
widget.global_visibility = widget.visibility == Visibility::Visible && parent_visibility;
|
||||
|
||||
// Continue on children
|
||||
for child_handle in children.iter() {
|
||||
self.update_transform(*child_handle);
|
||||
self.update_node(*child_handle);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, screen_size: Vec2, dt: f32) {
|
||||
self.measure(self.root_canvas, screen_size);
|
||||
self.arrange(self.root_canvas, &Rect::new(0.0, 0.0, screen_size.x, screen_size.y));
|
||||
self.update_transform(self.root_canvas);
|
||||
self.update_node(self.root_canvas);
|
||||
for node in self.nodes.iter_mut() {
|
||||
node.update(dt)
|
||||
}
|
||||
@@ -432,7 +441,7 @@ impl UserInterface {
|
||||
|
||||
let node = self.nodes.borrow_mut(node_handle);
|
||||
let bounds = node.widget().get_screen_bounds();
|
||||
if node.widget_mut().visibility != Visibility::Visible {
|
||||
if !node.widget_mut().global_visibility {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -491,7 +500,7 @@ impl UserInterface {
|
||||
let mut clipped = true;
|
||||
|
||||
let widget = self.nodes.borrow(node_handle).widget();
|
||||
if widget.visibility != Visibility::Visible {
|
||||
if !widget.global_visibility {
|
||||
return clipped;
|
||||
}
|
||||
|
||||
@@ -515,7 +524,7 @@ impl UserInterface {
|
||||
fn is_node_contains_point(&self, node_handle: Handle<UINode>, pt: Vec2) -> bool {
|
||||
let widget = self.nodes.borrow(node_handle).widget();
|
||||
|
||||
if widget.visibility != Visibility::Visible {
|
||||
if !widget.global_visibility {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -847,7 +856,7 @@ impl UserInterface {
|
||||
event_processed = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
WindowEvent::ReceivedCharacter(unicode) => {
|
||||
if self.keyboard_focus_node.is_some() {
|
||||
let event = UIEvent {
|
||||
@@ -856,7 +865,7 @@ impl UserInterface {
|
||||
symbol: *unicode
|
||||
},
|
||||
target: Handle::NONE,
|
||||
source: self.keyboard_focus_node
|
||||
source: self.keyboard_focus_node,
|
||||
};
|
||||
|
||||
self.events.push_back(event);
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::gui::{
|
||||
draw::DrawingContext,
|
||||
Visibility,
|
||||
event::UIEvent,
|
||||
Update
|
||||
Update,
|
||||
};
|
||||
use rg3d_core::{
|
||||
pool::Handle,
|
||||
@@ -163,12 +163,10 @@ impl ScrollViewerBuilder {
|
||||
}
|
||||
}
|
||||
UIEventKind::MouseWheel { amount, .. } => {
|
||||
if !event.handled {
|
||||
if event.source == handle || ui.is_node_child_of(event.source, handle) {
|
||||
let v_scroll_bar = ui.get_node_mut(v_scroll_bar).as_scroll_bar_mut();
|
||||
v_scroll_bar.scroll(-amount * 10.0);
|
||||
event.handled = true;
|
||||
}
|
||||
if !event.handled && (event.source == handle || ui.is_node_child_of(event.source, handle)) {
|
||||
let v_scroll_bar = ui.get_node_mut(v_scroll_bar).as_scroll_bar_mut();
|
||||
v_scroll_bar.scroll(-amount * 10.0);
|
||||
event.handled = true;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
||||
+11
-15
@@ -93,28 +93,24 @@ impl TextBox {
|
||||
HorizontalDirection::Left => {
|
||||
if self.caret_offset > 0 {
|
||||
self.caret_offset -= 1
|
||||
} else if self.caret_line > 0 {
|
||||
self.caret_line -= 1;
|
||||
self.caret_offset = lines[self.caret_line].len();
|
||||
} else {
|
||||
if self.caret_line > 0 {
|
||||
self.caret_line -= 1;
|
||||
self.caret_offset = lines[self.caret_line].len();
|
||||
} else {
|
||||
self.caret_offset = 0;
|
||||
break;
|
||||
}
|
||||
self.caret_offset = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
HorizontalDirection::Right => {
|
||||
let line = lines.get(self.caret_line).unwrap();
|
||||
if self.caret_offset < line.len() {
|
||||
self.caret_offset += 1;
|
||||
} else if self.caret_line < lines.len() - 1 {
|
||||
self.caret_line += 1;
|
||||
self.caret_offset = 0;
|
||||
} else {
|
||||
if self.caret_line < lines.len() - 1 {
|
||||
self.caret_line += 1;
|
||||
self.caret_offset = 0;
|
||||
} else {
|
||||
self.caret_offset = line.len();
|
||||
break;
|
||||
}
|
||||
self.caret_offset = line.len();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -456,7 +452,7 @@ impl TextBoxBuilder {
|
||||
blink_interval: 0.5,
|
||||
formatted_text: FormattedTextBuilder::new()
|
||||
.with_text(self.text)
|
||||
.with_font(self.font.unwrap_or(ui.get_default_font()))
|
||||
.with_font(self.font.unwrap_or_else(||ui.get_default_font()))
|
||||
.build(),
|
||||
selection_range: None,
|
||||
selecting: false,
|
||||
|
||||
+19
-1
@@ -62,6 +62,7 @@ pub struct Widget {
|
||||
pub(in crate::gui) margin: Thickness,
|
||||
/// Current visibility state
|
||||
pub(in crate::gui) visibility: Visibility,
|
||||
pub(in crate::gui) global_visibility: bool,
|
||||
pub(in crate::gui) children: Vec<Handle<UINode>>,
|
||||
pub(in crate::gui) parent: Handle<UINode>,
|
||||
/// Indices of commands in command buffer emitted by the node.
|
||||
@@ -71,6 +72,7 @@ pub struct Widget {
|
||||
pub(in crate::gui) arrange_valid: Cell<bool>,
|
||||
pub(in crate::gui) event_handlers: Vec<Box<UIEventHandler>>,
|
||||
pub(in crate::gui) events: RefCell<VecDeque<UIEvent>>,
|
||||
pub(in crate::gui) is_hit_test_visible: bool,
|
||||
}
|
||||
|
||||
impl Default for Widget {
|
||||
@@ -194,6 +196,8 @@ pub struct WidgetBuilder {
|
||||
margin: Option<Thickness>,
|
||||
children: Vec<Handle<UINode>>,
|
||||
event_handlers: Vec<Box<UIEventHandler>>,
|
||||
is_hit_test_visible: bool,
|
||||
visibility: Visibility,
|
||||
}
|
||||
|
||||
impl Default for WidgetBuilder {
|
||||
@@ -219,6 +223,8 @@ impl WidgetBuilder {
|
||||
desired_position: None,
|
||||
children: Vec::new(),
|
||||
event_handlers: Vec::new(),
|
||||
is_hit_test_visible: true,
|
||||
visibility: Visibility::Visible
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,6 +307,16 @@ impl WidgetBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_hit_test_visibility(mut self, state: bool) -> Self {
|
||||
self.is_hit_test_visible = state;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_visibility(mut self, visibility: Visibility) -> Self {
|
||||
self.visibility = visibility;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Widget {
|
||||
Widget {
|
||||
name: self.name.unwrap_or_default(),
|
||||
@@ -319,7 +335,8 @@ impl WidgetBuilder {
|
||||
vertical_alignment: self.vertical_alignment.unwrap_or(VerticalAlignment::Stretch),
|
||||
horizontal_alignment: self.horizontal_alignment.unwrap_or(HorizontalAlignment::Stretch),
|
||||
margin: self.margin.unwrap_or_else(Thickness::zero),
|
||||
visibility: Visibility::Visible,
|
||||
visibility: self.visibility,
|
||||
global_visibility: true,
|
||||
children: self.children,
|
||||
parent: Handle::NONE,
|
||||
command_indices: Vec::new(),
|
||||
@@ -328,6 +345,7 @@ impl WidgetBuilder {
|
||||
arrange_valid: Cell::new(false),
|
||||
event_handlers: self.event_handlers,
|
||||
events: RefCell::new(VecDeque::new()),
|
||||
is_hit_test_visible: self.is_hit_test_visible,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,7 +202,7 @@ impl DeferredLightRenderer {
|
||||
}
|
||||
|
||||
pub fn render(&mut self, frame_width: f32, frame_height: f32, scene: &Scene,
|
||||
camera: &Camera, gbuffer: &GBuffer, white_dummy: &GpuTexture) {
|
||||
camera: &Camera, gbuffer: &GBuffer, white_dummy: &GpuTexture, ambient_color: Color) {
|
||||
let frame_matrix =
|
||||
Mat4::ortho(0.0, frame_width, frame_height, 0.0, -1.0, 1.0) *
|
||||
Mat4::scale(Vec3::new(frame_width, frame_height, 0.0));
|
||||
@@ -221,7 +221,7 @@ impl DeferredLightRenderer {
|
||||
// Ambient light.
|
||||
self.ambient_light_shader.bind();
|
||||
self.ambient_light_shader.set_wvp_matrix(&frame_matrix);
|
||||
self.ambient_light_shader.set_ambient_color(Color::opaque(100, 100, 100));
|
||||
self.ambient_light_shader.set_ambient_color(ambient_color);
|
||||
self.ambient_light_shader.set_diffuse_texture(0);
|
||||
gl::ActiveTexture(gl::TEXTURE0);
|
||||
gl::BindTexture(gl::TEXTURE_2D, gbuffer.color_texture);
|
||||
|
||||
@@ -134,6 +134,10 @@ impl GpuProgram {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_bool(&self, location: UniformLocation, value: bool) {
|
||||
self.set_int(location, i32::from(if value { gl::TRUE } else { gl::FALSE }))
|
||||
}
|
||||
|
||||
pub fn set_float(&self, location: UniformLocation, value: f32) {
|
||||
unsafe {
|
||||
gl::Uniform1f(location.id, value)
|
||||
|
||||
+49
-7
@@ -15,7 +15,10 @@ pub mod gpu_texture;
|
||||
mod sprite_renderer;
|
||||
|
||||
use std::time;
|
||||
use rg3d_core::math::{vec3::Vec3, mat4::Mat4};
|
||||
use rg3d_core::{
|
||||
math::{vec3::Vec3, mat4::Mat4},
|
||||
color::Color
|
||||
};
|
||||
use glutin::PossiblyCurrent;
|
||||
use crate::{
|
||||
engine::resource_manager::ResourceManager,
|
||||
@@ -31,9 +34,12 @@ use crate::{
|
||||
flat_shader::FlatShader,
|
||||
sprite_renderer::SpriteRenderer
|
||||
},
|
||||
scene::{SceneInterface, SceneContainer},
|
||||
scene::{
|
||||
SceneInterface,
|
||||
SceneContainer,
|
||||
node::Node
|
||||
}
|
||||
};
|
||||
use crate::scene::node::Node;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct TriangleDefinition {
|
||||
@@ -141,6 +147,7 @@ pub struct Renderer {
|
||||
quad: SurfaceSharedData,
|
||||
last_render_time: time::Instant,
|
||||
frame_size: (u32, u32),
|
||||
ambient_color: Color,
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
@@ -165,10 +172,19 @@ impl Renderer {
|
||||
ui_renderer: UIRenderer::new()?,
|
||||
particle_system_renderer: ParticleSystemRenderer::new()?,
|
||||
last_render_time: time::Instant::now(), // TODO: Is this right?
|
||||
ambient_color: Color::opaque(100, 100, 100)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_ambient_color(&mut self, color: Color) {
|
||||
self.ambient_color = color;
|
||||
}
|
||||
|
||||
pub fn get_ambient_color(&self) -> Color {
|
||||
self.ambient_color
|
||||
}
|
||||
|
||||
pub fn get_statistics(&self) -> Statistics {
|
||||
self.statistics
|
||||
}
|
||||
@@ -223,12 +239,33 @@ impl Renderer {
|
||||
_ => continue
|
||||
};
|
||||
|
||||
self.gbuffer.fill(frame_width, frame_height, graph, camera, &self.white_dummy, &self.normal_dummy);
|
||||
self.gbuffer.fill(
|
||||
frame_width,
|
||||
frame_height,
|
||||
graph,
|
||||
camera,
|
||||
&self.white_dummy,
|
||||
&self.normal_dummy
|
||||
);
|
||||
|
||||
self.deferred_light_renderer.render(frame_width, frame_height, scene, camera, &self.gbuffer, &self.white_dummy);
|
||||
self.deferred_light_renderer.render(
|
||||
frame_width,
|
||||
frame_height,
|
||||
scene,
|
||||
camera,
|
||||
&self.gbuffer,
|
||||
&self.white_dummy,
|
||||
self.ambient_color
|
||||
);
|
||||
}
|
||||
|
||||
self.particle_system_renderer.render(scenes, &self.white_dummy, frame_width, frame_height, &self.gbuffer);
|
||||
self.particle_system_renderer.render(
|
||||
scenes,
|
||||
&self.white_dummy,
|
||||
frame_width,
|
||||
frame_height,
|
||||
&self.gbuffer
|
||||
);
|
||||
|
||||
self.sprite_renderer.render(scenes, &self.white_dummy);
|
||||
|
||||
@@ -247,7 +284,12 @@ impl Renderer {
|
||||
gl::BindTexture(gl::TEXTURE_2D, self.gbuffer.frame_texture);
|
||||
self.quad.draw();
|
||||
|
||||
self.ui_renderer.render(frame_width, frame_height, drawing_context, &self.white_dummy)?;
|
||||
self.ui_renderer.render(
|
||||
frame_width,
|
||||
frame_height,
|
||||
drawing_context,
|
||||
&self.white_dummy
|
||||
)?;
|
||||
}
|
||||
|
||||
self.statistics.end_frame();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#version 330 core
|
||||
|
||||
uniform sampler2D diffuseTexture;
|
||||
uniform bool isFont;
|
||||
|
||||
out vec4 FragColor;
|
||||
in vec2 texCoord;
|
||||
@@ -8,6 +9,13 @@ in vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = color;
|
||||
FragColor.a *= texture(diffuseTexture, texCoord).r;
|
||||
if (isFont)
|
||||
{
|
||||
FragColor = color;
|
||||
FragColor.a *= texture(diffuseTexture, texCoord).r;
|
||||
}
|
||||
else
|
||||
{
|
||||
FragColor = color * texture(diffuseTexture, texCoord);
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ struct UIShader {
|
||||
program: GpuProgram,
|
||||
wvp_matrix: UniformLocation,
|
||||
diffuse_texture: UniformLocation,
|
||||
is_font: UniformLocation,
|
||||
}
|
||||
|
||||
impl UIShader {
|
||||
@@ -35,6 +36,7 @@ impl UIShader {
|
||||
Ok(Self {
|
||||
wvp_matrix: program.get_uniform_location("worldViewProjection")?,
|
||||
diffuse_texture: program.get_uniform_location("diffuseTexture")?,
|
||||
is_font: program.get_uniform_location("isFont")?,
|
||||
program,
|
||||
})
|
||||
}
|
||||
@@ -47,6 +49,10 @@ impl UIShader {
|
||||
self.program.set_mat4(self.wvp_matrix, mat)
|
||||
}
|
||||
|
||||
pub fn set_is_font(&self, value: bool) {
|
||||
self.program.set_bool(self.is_font, value)
|
||||
}
|
||||
|
||||
pub fn set_diffuse_texture_sampler_id(&self, id: i32) {
|
||||
self.program.set_int(self.diffuse_texture, id)
|
||||
}
|
||||
@@ -134,13 +140,15 @@ impl UIRenderer {
|
||||
false).unwrap()
|
||||
);
|
||||
}
|
||||
font.texture.as_ref().unwrap().bind(0)
|
||||
font.texture.as_ref().unwrap().bind(0);
|
||||
self.shader.set_is_font(true);
|
||||
},
|
||||
CommandTexture::Texture(texture) => {
|
||||
let texture = texture.lock().unwrap();
|
||||
if let Some(texture) = &texture.gpu_tex {
|
||||
texture.bind(0)
|
||||
}
|
||||
self.shader.set_is_font(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-6
@@ -15,6 +15,7 @@ use std::{
|
||||
io::Read,
|
||||
};
|
||||
use crate::renderer::gpu_texture::GpuTexture;
|
||||
use std::ops::Range;
|
||||
|
||||
const ON_CURVE_POINT: u8 = 1;
|
||||
const REPEAT_FLAG: u8 = 8;
|
||||
@@ -866,7 +867,11 @@ impl TtfGlyph {
|
||||
}
|
||||
|
||||
impl Font {
|
||||
pub fn from_memory(data: Vec<u8>, height: f32, char_set: Vec<u32>) -> Result<Self, ()> {
|
||||
pub fn default_char_set() -> &'static [Range<u32>] {
|
||||
&[0x0020..0x00FF] // Basic Latin + Latin Supplement
|
||||
}
|
||||
|
||||
pub fn from_memory(data: Vec<u8>, height: f32, char_set: &[Range<u32>]) -> Result<Self, ()> {
|
||||
let ttf = TrueType::new(data);
|
||||
|
||||
let scale = ttf.em_to_pixels(height);
|
||||
@@ -889,15 +894,17 @@ impl Font {
|
||||
|
||||
font.pack();
|
||||
|
||||
for unicode in char_set {
|
||||
let index = ttf.unicode_to_glyph_index(unicode);
|
||||
font.char_map.insert(unicode, index);
|
||||
for range in char_set {
|
||||
for unicode in range.start..range.end {
|
||||
let index = ttf.unicode_to_glyph_index(unicode);
|
||||
font.char_map.insert(unicode, index);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(font)
|
||||
}
|
||||
|
||||
pub fn from_file(path: &Path, height: f32, char_set: Vec<u32>) -> Result<Self, ()> {
|
||||
pub fn from_file(path: &Path, height: f32, char_set: &[Range<u32>]) -> Result<Self, ()> {
|
||||
if let Ok(ref mut file) = File::open(path) {
|
||||
let mut file_content: Vec<u8> = Vec::with_capacity(file.metadata().unwrap().len() as usize);
|
||||
file.read_to_end(&mut file_content).unwrap();
|
||||
@@ -947,7 +954,7 @@ impl Font {
|
||||
for glyph in self.glyphs.iter() {
|
||||
area += glyph.bitmap_height * glyph.bitmap_width;
|
||||
}
|
||||
(1.05 * area.sqrt()) as i32
|
||||
(1.15 * area.sqrt()) as i32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
@@ -28,6 +28,7 @@ use crate::{
|
||||
},
|
||||
resource::model::Model,
|
||||
};
|
||||
use rg3d_core::pool::{PoolPairIterator, PoolPairIteratorMut};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct KeyFrame {
|
||||
@@ -421,6 +422,16 @@ impl AnimationContainer {
|
||||
self.pool.iter()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pair_iter(&self) -> PoolPairIterator<Animation> {
|
||||
self.pool.pair_iter()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pair_iter_mut(&mut self) -> PoolPairIteratorMut<Animation> {
|
||||
self.pool.pair_iter_mut()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter_mut(&mut self) -> PoolIteratorMut<Animation> {
|
||||
self.pool.iter_mut()
|
||||
@@ -451,6 +462,11 @@ impl AnimationContainer {
|
||||
self.pool.borrow_mut(handle)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn retain<P>(&mut self, pred: P) where P: FnMut(&Animation) -> bool {
|
||||
self.pool.retain(pred)
|
||||
}
|
||||
|
||||
pub fn resolve(&mut self, graph: &Graph) {
|
||||
println!("Resolving animations...");
|
||||
for animation in self.pool.iter_mut() {
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ impl Base {
|
||||
/// Returns current lifetime of a node. Will be None if node has undefined lifetime.
|
||||
/// For more info about lifetimes see [`set_lifetime`].
|
||||
pub fn get_lifetime(&self) -> Option<f32> {
|
||||
self.lifetime.clone()
|
||||
self.lifetime
|
||||
}
|
||||
|
||||
/// Returns handle of parent node.
|
||||
|
||||
@@ -388,6 +388,75 @@ impl Graph {
|
||||
pub fn pair_iter(&self) -> PoolPairIterator<Node> {
|
||||
self.pool.pair_iter()
|
||||
}
|
||||
|
||||
/// Create graph depth traversal iterator.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// This method allocated temporal array so it is not cheap! Should not be
|
||||
/// used on each frame.
|
||||
pub fn traverse_iter(&self, from: Handle<Node>) -> GraphTraverseIterator {
|
||||
GraphTraverseIterator {
|
||||
graph: self,
|
||||
stack: vec![from]
|
||||
}
|
||||
}
|
||||
|
||||
/// Create graph depth traversal iterator which will emit *handles* to nodes.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// This method allocated temporal array so it is not cheap! Should not be
|
||||
/// used on each frame.
|
||||
pub fn traverse_handle_iter(&self, from: Handle<Node>) -> GraphHandleTraverseIterator {
|
||||
GraphHandleTraverseIterator {
|
||||
graph: self,
|
||||
stack: vec![from]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GraphTraverseIterator<'a> {
|
||||
graph: &'a Graph,
|
||||
stack: Vec<Handle<Node>>
|
||||
}
|
||||
|
||||
impl<'a> Iterator for GraphTraverseIterator<'a> {
|
||||
type Item = &'a Node;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
while let Some(handle) = self.stack.pop() {
|
||||
let node = self.graph.get(handle);
|
||||
|
||||
for child_handle in node.base().get_children() {
|
||||
self.stack.push(*child_handle);
|
||||
}
|
||||
|
||||
return Some(node)
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GraphHandleTraverseIterator<'a> {
|
||||
graph: &'a Graph,
|
||||
stack: Vec<Handle<Node>>
|
||||
}
|
||||
|
||||
impl<'a> Iterator for GraphHandleTraverseIterator<'a> {
|
||||
type Item = Handle<Node>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
while let Some(handle) = self.stack.pop() {
|
||||
for child_handle in self.graph.get(handle).base().get_children() {
|
||||
self.stack.push(*child_handle);
|
||||
}
|
||||
|
||||
return Some(handle)
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for Graph {
|
||||
|
||||
+22
-1
@@ -89,7 +89,7 @@ impl Scene {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_physics(&mut self, dt: f32) {
|
||||
fn update_physics(&mut self, dt: f32) {
|
||||
self.physics.step(dt);
|
||||
|
||||
// Sync node positions with assigned physics bodies
|
||||
@@ -104,6 +104,27 @@ impl Scene {
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes node from scene with all associated entities, like animations etc.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if handle is invalid.
|
||||
pub fn remove_node(&mut self, handle: Handle<Node>) {
|
||||
for descendant in self.graph.traverse_handle_iter(handle) {
|
||||
// Remove all associated animations.
|
||||
self.animations.retain(|animation| {
|
||||
for track in animation.get_tracks() {
|
||||
if track.get_node() == descendant {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
self.graph.remove_node(handle)
|
||||
}
|
||||
|
||||
pub fn resolve(&mut self) {
|
||||
println!("Starting resolve...");
|
||||
self.graph.resolve();
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use std::marker::PhantomData;
|
||||
use crate::scene::mesh::Mesh;
|
||||
use rg3d_physics::static_geometry::{StaticGeometry, StaticTriangle};
|
||||
use crate::scene::base::AsBase;
|
||||
|
||||
pub struct UnsafeCollectionView<T> {
|
||||
items: *const T,
|
||||
@@ -51,4 +54,41 @@ impl<'a, T> Iterator for UnsafeCollectionViewIterator<'a, T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Small helper that creates static physics geometry from given mesh.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// This method *bakes* global transform of given mesh into static geometry
|
||||
/// data. So if given mesh was at some position with any rotation and scale
|
||||
/// resulting static geometry will have vertices that exactly matches given
|
||||
/// mesh.
|
||||
pub fn mesh_to_static_geometry(mesh: &Mesh) -> StaticGeometry {
|
||||
let mut static_geometry = StaticGeometry::new();
|
||||
let global_transform = mesh.base().get_global_transform();
|
||||
for surface in mesh.get_surfaces() {
|
||||
let data_rc = surface.get_data();
|
||||
let shared_data = data_rc.lock().unwrap();
|
||||
|
||||
let vertices = shared_data.get_vertices();
|
||||
let indices = shared_data.get_indices();
|
||||
|
||||
let last = indices.len() - indices.len() % 3;
|
||||
let mut i: usize = 0;
|
||||
while i < last {
|
||||
let a = global_transform.transform_vector(vertices[indices[i] as usize].position);
|
||||
let b = global_transform.transform_vector(vertices[indices[i + 1] as usize].position);
|
||||
let c = global_transform.transform_vector(vertices[indices[i + 2] as usize].position);
|
||||
|
||||
if let Some(triangle) = StaticTriangle::from_points(&a, &b, &c) {
|
||||
static_geometry.add_triangle(triangle);
|
||||
} else {
|
||||
println!("degenerated triangle!");
|
||||
}
|
||||
|
||||
i += 3;
|
||||
}
|
||||
}
|
||||
static_geometry
|
||||
}
|
||||
Reference in New Issue
Block a user