Skip to content

Commit

Permalink
ModelFXTerminal
Browse files Browse the repository at this point in the history
  • Loading branch information
markusmoenig committed Mar 30, 2024
1 parent 96878ff commit 2650b51
Show file tree
Hide file tree
Showing 7 changed files with 300 additions and 56 deletions.
6 changes: 3 additions & 3 deletions creator/src/modelfxeditor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ impl ModelFXEditor {
let mut zoom = TheSlider::new(TheId::named("ModelFX Zoom"));
zoom.set_value(TheValue::Float(1.0));
zoom.set_default_value(TheValue::Float(1.0));
zoom.set_range(TheValue::RangeF32(0.5..=5.0));
zoom.set_range(TheValue::RangeF32(1.0..=5.0));
zoom.set_continuous(true);
zoom.limiter_mut().set_max_width(120);

Expand Down Expand Up @@ -153,8 +153,8 @@ impl ModelFXEditor {
}
}
TheEvent::TileEditorUp(id) => {
if id.name == "ModelFX RGBA Layout View" {
self.modelfx.released(ui, ctx);
if id.name == "ModelFX RGBA Layout View" && self.modelfx.released(ui, ctx) {
redraw = true;
}
}
TheEvent::TileEditorHoverChanged(id, coord) => {
Expand Down
3 changes: 3 additions & 0 deletions shared/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ pub mod item;
pub mod level;
pub mod modelfx;
pub mod modelfxnode;
pub mod modelfxterminal;
pub mod project;
pub mod region;
pub mod regionfx;
pub mod renderedregion;
pub mod renderer;
pub mod renderer_utils;
pub mod screen;
Expand Down Expand Up @@ -43,6 +45,7 @@ pub mod prelude {
pub use crate::regionfx::*;
pub use crate::renderer::Renderer;
//pub use crate::renderer_utils::*;
pub use crate::modelfxterminal::*;
pub use crate::screen::*;
pub use crate::sdf3d::*;
pub use crate::server::context::ServerContext;
Expand Down
183 changes: 130 additions & 53 deletions shared/src/modelfx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,11 @@ use crate::prelude::*;
use rayon::prelude::*;
use theframework::prelude::*;

//const RED: RGBA = [209, 42, 42, 255];
// const GREEN: RGBA = [10, 245, 5, 255];
//const YELLOW: RGBA = [238, 251, 28, 255];
//const BLUE: RGBA = [44, 52, 214, 255];
const RED: RGBA = [212, 128, 77, 255];
const YELLOW: RGBA = [224, 200, 114, 255];
//const PALE_YELLOW: RGBA = [217, 172, 139, 255];
const BLUE: RGBA = [36, 61, 92, 255];

// const COLOR1: [u8; 4] = [217, 172, 139, 255];
// const COLOR2: [u8; 4] = [62, 105, 88, 255];
// const COLOR3: [u8; 4] = [177, 165, 141, 255];
// const COLOR4: [u8; 4] = [98, 76, 60, 255];
// const COLOR5: [u8; 4] = [36, 61, 92, 255];
// const COLOR6: [u8; 4] = [224, 200, 114, 255];
// const COLOR7: [u8; 4] = [176, 58, 72, 255];
// const COLOR8: [u8; 4] = [212, 128, 77, 255];
// const COLOR9: [u8; 4] = [92, 139, 147, 255];
// const COLOR10: [u8; 4] = [227, 207, 180, 255];

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub enum ModelFXNodeAction {
None,
DragNode,
ConnectingTerminal(Vec3i),
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
Expand All @@ -34,8 +15,13 @@ pub struct ModelFX {

pub nodes: Vec<ModelFXNode>,

// Source node index, source terminal, dest node index, dest terminal
pub connections: Vec<(u16, u8, u16, u8)>,

#[serde(skip)]
pub node_rects: Vec<(usize, usize, usize, usize)>,
#[serde(skip)]
pub terminal_rects: Vec<(Vec3i, (usize, usize, usize, usize))>,
pub zoom: f32,

pub selected_node: Option<usize>,
Expand All @@ -58,7 +44,10 @@ impl ModelFX {
action: ModelFXNodeAction::None,

nodes: vec![],
connections: vec![],

node_rects: vec![],
terminal_rects: vec![],
zoom: 1.0,

selected_node: None,
Expand All @@ -83,6 +72,34 @@ impl ModelFX {
false
}

/// Deletes the selected node and deletes / adjusts connections involving the node.
pub fn delete(&mut self) {
if let Some(deleted_node_index) = self.selected_node {
self.nodes.remove(deleted_node_index);

// Filter out connections involving the deleted node and adjust indices for others
self.connections
.retain_mut(|(src_node_idx, _, dest_node_idx, _)| {
let src_index = *src_node_idx as usize;
let dest_index = *dest_node_idx as usize;

if src_index == deleted_node_index || dest_index == deleted_node_index {
// Connection involves the deleted node, so remove it
false
} else {
// Adjust indices for remaining connections
if src_index > deleted_node_index {
*src_node_idx -= 1;
}
if dest_index > deleted_node_index {
*dest_node_idx -= 1;
}
true
}
});
}
}

pub fn build_ui(_ctx: &mut TheContext) -> TheCanvas {
let mut canvas = TheCanvas::new();

Expand Down Expand Up @@ -131,6 +148,7 @@ impl ModelFX {
let mut width = (max_x - min_x).max(20);
let mut height = (max_y - min_y).max(20);
self.node_rects.clear();
self.terminal_rects.clear();

if let Some(node_layout) = ui.get_rgba_layout("ModelFX RGBA Layout") {
if let Some(node_view) = node_layout.rgba_view_mut().as_rgba_view() {
Expand All @@ -150,6 +168,8 @@ impl ModelFX {
)
}

let scaled = |s: usize| -> usize { (s as f32 * zoom) as usize };

for (i, node) in self.nodes.iter().enumerate() {
if let Some(TheValue::Int2(v)) = node.collection().get("_pos") {
let node_x = (v.x - min_x) as usize;
Expand Down Expand Up @@ -179,7 +199,7 @@ impl ModelFX {
5.0 * self.zoom,
),
&border_color,
1.5,
1.5 * zoom,
);

let mut preview_buffer = TheRGBABuffer::new(TheDim::sized(
Expand All @@ -201,10 +221,45 @@ impl ModelFX {
width as usize,
);

// Output Terminals

let terminals = node.output_terminals();
let terminal_size = scaled(10);
let trf = scaled(2) as f32;
for (j, terminal) in terminals.iter().enumerate() {
let terminal_color = terminal.color.color().to_u8_array();
let terminal_x = rect.0 + rect.2 - terminal_size / 2 - scaled(1);
let terminal_y = rect.1 + scaled(8) + scaled(15) * j;
let terminal_rect =
(terminal_x, terminal_y, terminal_size, terminal_size);
ctx.draw.rounded_rect_with_border(
buffer.pixels_mut(),
&terminal_rect,
width as usize,
&[128, 128, 128, 255],
&(trf, trf, trf, trf),
&terminal_color,
2.0 * zoom,
);

self.terminal_rects
.push((vec3i(i as i32, j as i32, 1), terminal_rect));
}

self.node_rects.push(rect);
}
}

if let ModelFXNodeAction::ConnectingTerminal(_) = self.action {
buffer.draw_line(
self.drag_start.x,
self.drag_start.y,
self.drag_offset.x,
self.drag_offset.y,
WHITE,
)
}

node_view.set_buffer(buffer);
}
node_layout.relayout(ctx);
Expand All @@ -213,7 +268,11 @@ impl ModelFX {

pub fn clicked(&mut self, coord: Vec2i, _ui: &mut TheUI, _ctx: &mut TheContext) -> bool {
let mut redraw = false;
if let Some(index) = self.get_node_at(coord) {
if let Some(terminal) = self.get_terminal_at(coord) {
self.drag_start = coord;
self.action = ModelFXNodeAction::ConnectingTerminal(terminal);
redraw = true;
} else if let Some(index) = self.get_node_at(coord) {
self.drag_start = coord;
self.action = ModelFXNodeAction::DragNode;
if Some(index) != self.selected_node {
Expand All @@ -225,7 +284,10 @@ impl ModelFX {
}
pub fn dragged(&mut self, coord: Vec2i, _ui: &mut TheUI, _ctx: &mut TheContext) -> bool {
let mut redraw = false;
if self.action == ModelFXNodeAction::DragNode {
if let ModelFXNodeAction::ConnectingTerminal(_) = self.action {
self.drag_offset = coord;
redraw = true;
} else if self.action == ModelFXNodeAction::DragNode {
if let Some(index) = self.selected_node {
let collection = self.nodes[index].collection_mut();
if let Some(TheValue::Int2(value)) = collection.get("_pos") {
Expand All @@ -242,7 +304,36 @@ impl ModelFX {
}
redraw
}
pub fn released(&mut self, _ui: &mut TheUI, _ctx: &mut TheContext) {}
pub fn released(&mut self, _ui: &mut TheUI, _ctx: &mut TheContext) -> bool {
let mut redraw = false;
if let ModelFXNodeAction::ConnectingTerminal(source) = self.action {
if let Some(dest) = self.get_terminal_at(self.drag_offset) {
if source.x != dest.x && source.z != dest.z {
// Make sure output terminal is always listed first
if source.z == 0 {
// Dest is output terminal
self.connections.push((
dest.x as u16,
dest.y as u8,
source.x as u16,
source.y as u8,
));
} else {
// Source it output terminal
self.connections.push((
source.x as u16,
source.y as u8,
dest.x as u16,
dest.y as u8,
));
}
}
}
self.action = ModelFXNodeAction::None;
redraw = true;
}
redraw
}
pub fn hovered(&mut self, coord: Vec2i, ui: &mut TheUI, ctx: &mut TheContext) -> bool {
if let Some(node_layout) = ui.get_rgba_layout("ModelFX RGBA Layout") {
if let Some(node_view) = node_layout.rgba_view_mut().as_rgba_view() {
Expand Down Expand Up @@ -274,6 +365,20 @@ impl ModelFX {
None
}

/// Get the terminal index at the given coordinate.
pub fn get_terminal_at(&self, coord: Vec2i) -> Option<Vec3i> {
for (terminal, rect) in self.terminal_rects.iter() {
if rect.0 as i32 <= coord.x
&& coord.x <= rect.0 as i32 + rect.2 as i32
&& rect.1 as i32 <= coord.y
&& coord.y <= rect.1 as i32 + rect.3 as i32
{
return Some(*terminal);
}
}
None
}

pub fn render_preview(&mut self, buffer: &mut TheRGBABuffer) {
//}, palette: &ThePalette) {
let width = buffer.dim().width as usize;
Expand Down Expand Up @@ -407,36 +512,8 @@ impl ModelFX {

if t < max_t {
let normal = self.normal_node(p, node);

let nx = normal.x.abs();
let ny = normal.y.abs();
let nz = normal.z.abs();

if nx > ny && nx > nz {
// X-face
color = TheColor::from_u8_array(RED).to_vec4f();
} else if ny > nx && ny > nz {
// Y-face
color = TheColor::from_u8_array(YELLOW).to_vec4f();
} else {
// Z-face
color = TheColor::from_u8_array(BLUE).to_vec4f();
}
}

/*
if let Some(hit) = hit {
if hit.face == HitFace::XFace {
color = TheColor::from_u8_array(RED).to_vec4f();
}
if hit.face == HitFace::YFace {
color = TheColor::from_u8_array(YELLOW).to_vec4f();
}
if hit.face == HitFace::ZFace {
color = TheColor::from_u8_array(BLUE).to_vec4f();
}
color = node.color_for_normal(normal).color().to_vec4f();
}
*/

total += color;
}
Expand Down
35 changes: 35 additions & 0 deletions shared/src/modelfxnode.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::prelude::*;
//use indexmap::IndexMap;
//use rayon::prelude::*;
use crate::modelfxterminal::ModelFXTerminalRole::*;
use theframework::prelude::*;

#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
Expand Down Expand Up @@ -42,6 +43,40 @@ impl ModelFXNode {
}
}

/// Get a reference to the collection.
pub fn output_terminals(&self) -> Vec<ModelFXTerminal> {
match self {
Self::WallHorizontal(_) | Self::WallVertical(_) => {
vec![
ModelFXTerminal::new(Face, 6),
ModelFXTerminal::new(Face, 7),
ModelFXTerminal::new(Face, 4),
]
}
}
}

pub fn color_for_normal(&self, normal: Vec3f) -> ModelFXColor {
match self {
Self::WallHorizontal(_) | Self::WallVertical(_) => {
let nx = normal.x.abs();
let ny = normal.y.abs();
let nz = normal.z.abs();

if nx > ny && nx > nz {
// X-face
ModelFXColor::create(6)
} else if ny > nx && ny > nz {
// Y-face
ModelFXColor::create(7)
} else {
// Z-face
ModelFXColor::create(4)
}
}
}
}

/// Get a reference to the collection.
pub fn collection(&self) -> &TheCollection {
match self {
Expand Down
Loading

0 comments on commit 2650b51

Please sign in to comment.