Skip to content

Commit

Permalink
Add new visualizer
Browse files Browse the repository at this point in the history
The new version has a workload editor to see (and later modify) workloads
  • Loading branch information
leudz committed May 5, 2023
1 parent 82f7489 commit 258c0a3
Show file tree
Hide file tree
Showing 13 changed files with 1,376 additions and 2 deletions.
27 changes: 26 additions & 1 deletion .github/workflows/check-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ jobs:
- 'guide/**'
- 'square_eater/**'
- 'visualizer/**'
- 'visualizer_yew/**'
- '.github/**'
- 'Cargo.toml'
fmt:
Expand Down Expand Up @@ -208,9 +209,27 @@ jobs:
with:
name: visualizer
path: visualizer/dist
visualizer_yew:
runs-on: ubuntu-latest
needs: changes
if: github.event_name == 'push' && needs.changes.outputs.deploy == 'true'
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
with:
target: wasm32-unknown-unknown
- uses: jetli/trunk-action@v0.4.0
# GH pages doesn't use the same url naming as trunk's default
# https://github.com/thedodd/trunk/issues/268
- run: trunk build --public-url "shipyard/visualizer_yew/" --release visualizer_yew/index.html
- name: save visualizer_yew
uses: actions/upload-artifact@v2
with:
name: visualizer_yew
path: visualizer_yew/dist
deploy:
runs-on: ubuntu-latest
needs: [changes, guide_master, guide_0_5_0, bunny_demo, square_eater, visualizer]
needs: [changes, guide_master, guide_0_5_0, bunny_demo, square_eater, visualizer, visualizer_yew]
if: github.event_name == 'push' && needs.changes.outputs.deploy == 'true'
steps:
- name: load guide master
Expand Down Expand Up @@ -249,6 +268,12 @@ jobs:
name: visualizer
path: dist/visualizer

- name: load visualizer_yew
uses: actions/download-artifact@v2
with:
name: visualizer_yew
path: dist/visualizer_yew

- name: deploy to gh pages
uses: maxheld83/ghpages@master
env:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ node_modules
bunny_demo/public/wasm
*.wasm
visualizer/dist
visualizer_yew/dist
8 changes: 7 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ repository = "https://github.com/leudz/shipyard"
version = "0.6.0"

[workspace]
members = ["bunny_demo", "shipyard_proc", "square_eater", "visualizer"]
members = [
"bunny_demo",
"shipyard_proc",
"square_eater",
"visualizer",
"visualizer_yew",
]

[dependencies]
hashbrown = "0.12.0"
Expand Down
4 changes: 4 additions & 0 deletions project.yamis.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,7 @@ serial = ["fmt", "test-all", "doc", "miri", "clippy", "clean"]
program = "trunk"
args = ["serve", "visualizer/index.html"]
env = { "RUSTFLAGS" = "--cfg=web_sys_unstable_apis" }

[tasks.visualizer_yew]
program = "trunk"
args = ["serve", "visualizer_yew/index.html"]
21 changes: 21 additions & 0 deletions visualizer_yew/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "visualizer_yew"
version = "0.1.0"
edition = "2021"

[dependencies]
console_error_panic_hook = "0.1"
serde_json = "1.0.96"
shipyard = { path = "..", features = ["serde1"] }
wasm-bindgen = "0.2"
web-sys = { version = "0.3.61", features = [
"DataTransfer",
"DragEvent",
"Element",
"FileReader",
"HtmlDivElement",
"HtmlSelectElement",
"Performance",
"ProgressEvent",
] }
yew = { version = "0.20.0", features = ["csr"] }
3 changes: 3 additions & 0 deletions visualizer_yew/Trunk.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build]
target = "index.html"
dist = "dist"
17 changes: 17 additions & 0 deletions visualizer_yew/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html style="overflow-y: hidden;">

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>⚓ Visualizer</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css" />

<base data-trunk-public-url />
</head>

<body>
<link data-trunk rel="rust" href="Cargo.toml" data-wasm-opt="z" data-bin="visualizer_yew" />
</body>

</html>
239 changes: 239 additions & 0 deletions visualizer_yew/src/access_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
use std::collections::HashMap;

use shipyard::{info::TypeInfo, Mutability};
use yew::prelude::*;

pub(crate) struct AccessInfo {
systems: Vec<String>,
systems_mutability: Vec<Option<Mutability>>,
/// First one is the full name, the second one is trimmed [trim_component_name]
components: Vec<(String, String)>,
components_mutability: Vec<Option<Mutability>>,
selected_system: Option<String>,
selected_component: Option<String>,
}

pub(crate) enum Msg {
SetSelectedSystem(String),
SetSelectedComponent(String),
}

#[derive(Properties, PartialEq)]
pub(crate) struct Props {
pub(crate) system_to_components: HashMap<String, Vec<TypeInfo>>,
pub(crate) component_to_systems: HashMap<String, Vec<(String, Mutability)>>,
}

impl Component for AccessInfo {
type Message = Msg;
type Properties = Props;

fn create(ctx: &Context<AccessInfo>) -> AccessInfo {
AccessInfo {
systems: ctx.props().system_to_components.keys().cloned().collect(),
systems_mutability: Vec::new(),
components: ctx
.props()
.component_to_systems
.keys()
.map(|component| (component.clone(), trim_component_name(component)))
.collect(),
components_mutability: Vec::new(),
selected_system: None,
selected_component: None,
}
}

fn changed(&mut self, ctx: &Context<Self>, old_props: &Self::Properties) -> bool {
if ctx.props() == old_props {
return false;
}

self.systems.clear();
self.systems_mutability.clear();
self.components.clear();
self.components_mutability.clear();
self.selected_system = None;
self.selected_component = None;

self.systems
.extend(ctx.props().system_to_components.keys().cloned());
self.systems.sort_unstable();
self.components.extend(
ctx.props()
.component_to_systems
.keys()
.map(|component| (component.clone(), trim_component_name(component))),
);
self.components
.sort_unstable_by(|(_, name1), (_, name2)| name1.cmp(&name2));
self.systems_mutability
.extend((0..self.systems.len()).map(|_| None));
self.components_mutability
.extend((0..self.components.len()).map(|_| None));

true
}

fn update(&mut self, ctx: &Context<AccessInfo>, msg: Msg) -> bool {
match msg {
Msg::SetSelectedSystem(system) => {
if self.selected_system.as_ref() == Some(&system) {
return false;
}

let components = &ctx.props().system_to_components[&system];
for (component, mutability) in
self.components.iter().zip(&mut self.components_mutability)
{
if let Some(component) = components
.iter()
.find(|type_info| type_info.name == *component.0)
{
*mutability = Some(component.mutability);
} else {
*mutability = None;
}
}

self.selected_system = Some(system);

self.selected_component = None;
self.systems_mutability
.iter_mut()
.for_each(|mutability| *mutability = None);
}
Msg::SetSelectedComponent(component) => {
if self.selected_component.as_ref() == Some(&component) {
return false;
}

let systems = &ctx.props().component_to_systems[&component];
for (system, mutability) in self.systems.iter().zip(&mut self.systems_mutability) {
if let Some((_, sys_mutability)) =
systems.iter().find(|(name, _)| name == system)
{
*mutability = Some(*sys_mutability);
} else {
*mutability = None;
}
}

self.selected_component = Some(component);

self.selected_system = None;
self.components_mutability
.iter_mut()
.for_each(|mutability| *mutability = None);
}
}

true
}

fn view(&self, ctx: &Context<AccessInfo>) -> Html {
let len = self.systems.len().max(self.components.len());

let link = ctx.link().clone();
let rows: Html = self
.systems
.iter()
.zip(&self.systems_mutability)
.chain(std::iter::repeat((&String::new(), &None)))
.zip(
self.components
.iter()
.zip(&self.components_mutability)
.chain(std::iter::repeat((&(String::new(), String::new()), &None))),
)
.take(len)
.map(
move |((system, sys_mutability), (component, comp_mutability))| {
let mut sys_style = "border-radius: 10px;".to_string();
let mut comp_style = "border-radius: 10px;".to_string();

sys_style += match sys_mutability {
Some(Mutability::Exclusive) => "background-color: #FF8080;",
Some(Mutability::Shared) => "background-color: #ADD8E6;",
None if Some(system) == self.selected_system.as_ref() => {
"background-color: darkgrey;"
}
None if !system.is_empty() => "background-color: #e8e8e8;",
None => "",
};
comp_style += match comp_mutability {
Some(Mutability::Exclusive) => "background-color: #FF8080;",
Some(Mutability::Shared) => "background-color: #ADD8E6;",
None if Some(&component.0) == self.selected_component.as_ref() => {
"background-color: darkgrey;"
}
None if !component.0.is_empty() => "background-color: #e8e8e8;",
None => "",
};
if !system.is_empty() {
sys_style += "cursor: pointer;";
}
if !component.0.is_empty() {
comp_style += "cursor: pointer;";
}

let link_clone = link.clone();
let system_clone = system.clone();
let on_click_sys = move |_| {
// If there are more components than systems there are some padding systems
if !system_clone.is_empty() {
link_clone.send_message(Msg::SetSelectedSystem(system_clone.clone()))
}
};
let link_clone = link.clone();
let component_clone = component.0.clone();
let on_click_comp = move |_| {
// If there are more systems than components there are some padding components
if !component_clone.is_empty() {
link_clone
.send_message(Msg::SetSelectedComponent(component_clone.clone()))
}
};

html! {
<tr>
<td onclick={on_click_sys} style={sys_style}>
<span>{system}</span>
</td>

<td onclick={on_click_comp} style={comp_style}>
<span>{&component.1}</span>
</td>
</tr>
}
},
)
.collect();

html! {
<table style="width: 100%; table-layout: fixed; text-align: center; border-collapse: separate; border-spacing: 10px 3px;">
if {rows != html! {}} {
<thead>
<tr>
<th>{"Systems"}</th>
<th>{"Components"}</th>
</tr>
</thead>
}

<tbody>
{rows}
</tbody>
</table>
}
}
}

fn trim_component_name(name: &str) -> String {
name.trim_start_matches("shipyard::")
.trim_start_matches("sparse_set::")
.trim_start_matches("unique::")
.trim_start_matches("all_storages::")
.trim_start_matches("entities::")
.to_string()
}
Loading

0 comments on commit 258c0a3

Please sign in to comment.