Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First pass at editor GUI #421

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,12 @@ sponza*

# Ignore compiled shaders
*.spv

# ..except for the editor's, which are special and magic
!hotham-editor/src/shaders/*.spv

# Checking in a socket is probably a terrible idea
*.socket

# Ignore vscode settings
.vscode/settings.json
10 changes: 0 additions & 10 deletions .vscode/settings.json

This file was deleted.

11 changes: 10 additions & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,17 @@
"label": "Run Hotham simple scene on the simulator",
"group": {
"kind": "test",
"isDefault": true,
"isDefault": false,
}
},
{
"label": "Test OpenXR Client",
"type": "shell",
"command": "./hotham-openxr-client/test.ps1",
"group": {
"kind": "test",
"isDefault": true,
}
}
]
}
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ members = [
"hotham-asset-client",
"hotham-asset-server",
"hotham-simulator",
"hotham-editor",
"hotham-editor-protocol",
"hotham-openxr-client",
"hotham",
]

Expand Down
14 changes: 12 additions & 2 deletions examples/simple-scene/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,17 @@ name = "hotham_simple_scene_example"
path = "src/main.rs"

[dependencies]
hotham = {path = "../../hotham"}
env_logger = "0.10.0"
hotham = {path = "../../hotham", features = ["editor"]}
hotham-editor-protocol = {path = "../../hotham-editor-protocol", optional = true}
log = "0.4.17"

[features]
default = ["editor"]
editor = ["dep:uds_windows", "dep:hotham-editor-protocol"]

[target.'cfg(windows)'.dependencies]
uds_windows = {version = "1.0.2", optional = true}

[target.'cfg(target_os = "android")'.dependencies]
ndk-glue = "0.6"
Expand Down Expand Up @@ -76,5 +86,5 @@ version = 1
#
# !! IMPORTANT !!
[package.metadata.android.signing.release]
path = "../hotham_examples.keystore"
keystore_password = "chomsky-vigilant-spa"
path = "../hotham_examples.keystore"
77 changes: 73 additions & 4 deletions examples/simple-scene/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use hotham::{
asset_importer::{self, add_model_to_world},
components::{hand::Handedness, physics::SharedShape, Collider, LocalTransform, RigidBody},
components::{
hand::Handedness, physics::SharedShape, Collider, GlobalTransform, Info, LocalTransform,
Mesh,
},
hecs::World,
systems::{
animation_system, debug::debug_system, grabbing_system, hands::add_hand, hands_system,
Expand All @@ -9,6 +12,8 @@ use hotham::{
},
xr, Engine, HothamResult, TickData,
};
use hotham_editor_protocol::scene::{EditorEntity, EditorUpdates, Transform};
use log::{debug, info};

#[derive(Clone, Debug, Default)]
/// Most Hotham applications will want to keep track of some sort of state.
Expand All @@ -24,18 +29,84 @@ pub fn main() {
}

pub fn real_main() -> HothamResult<()> {
env_logger::builder()
.filter_module("hotham-openxr-client", log::LevelFilter::Trace)
.filter_module("simple_scene_example", log::LevelFilter::Trace)
.init();

info!("Initialising Simple Scene example..");

#[cfg(feature = "editor")]
let mut editor = {
use hotham_editor_protocol::EditorClient;
use uds_windows::UnixStream;
info!("Connecting to editor..");
let stream = UnixStream::connect("hotham_editor.socket")?;
EditorClient::new(stream)
};

info!("Building engine..");
let mut engine = Engine::new();
info!("..done!");

info!("Initialising app..");
let mut state = Default::default();
init(&mut engine)?;
info!("Done! Entering main loop..");

while let Ok(tick_data) = engine.update() {
#[cfg(feature = "editor")]
sync_with_editor(&mut engine.world, &mut editor)?;

tick(tick_data, &mut engine, &mut state);
engine.finish()?;
}

Ok(())
}

fn sync_with_editor(
world: &mut World,
editor: &mut hotham_editor_protocol::EditorClient<uds_windows::UnixStream>,
) -> HothamResult<()> {
use hotham::hecs::Entity;
let entities = world
.query_mut::<(&GlobalTransform, &Info)>()
.with::<&Mesh>()
.into_iter()
.map(|(entity, (transform, info))| {
let (_, _, translation) = transform.to_scale_rotation_translation();
EditorEntity {
name: info.name.clone(),
id: entity.to_bits().get(),
transform: Transform {
translation: translation.into(),
},
}
})
.collect();

let scene = hotham_editor_protocol::scene::Scene {
name: "Simple Scene".to_string(),
entities,
};

editor.send_json(&scene).unwrap(); // TODO: error types

let editor_updates: EditorUpdates = editor.get_json().unwrap(); // TODO: error types
for entity in editor_updates.entity_updates {
debug!("Received update: {entity:?}");
let mut entity_transform = world
.entity(Entity::from_bits(entity.id).unwrap())
.unwrap()
.get::<&mut LocalTransform>()
.unwrap();
entity_transform.translation = entity.transform.translation.into();
}

Ok(())
}

fn tick(tick_data: TickData, engine: &mut Engine, _state: &mut State) {
if tick_data.current_state == xr::SessionState::FOCUSED {
hands_system(engine);
Expand Down Expand Up @@ -94,7 +165,5 @@ fn add_helmet(models: &std::collections::HashMap<String, World>, world: &mut Wor

let collider = Collider::new(SharedShape::ball(0.35));

world
.insert(helmet, (collider, RigidBody::default()))
.unwrap();
world.insert_one(helmet, collider).unwrap();
}
13 changes: 13 additions & 0 deletions hotham-editor-protocol/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
edition = "2021"
name = "hotham-editor-protocol"
version = "0.1.0"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
ash = "0.37.2"
mint = {version = "0.5.9", features = ["serde"]}
openxr-sys = "0.9.3"
serde = {version = "1.0", features = ["derive"]}
serde_json = "1.0"
39 changes: 39 additions & 0 deletions hotham-editor-protocol/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Hotham Editor Protocol
## Why?
Whenever two programs want to talk to eachother, the most complicated question is *where is the protocol defined?*. Sometimes the protocol is inferred from the way the programs serialise and deserialise their messages, but this leads to all sorts of problems.

In essence, this is a *contract* problem. What is the contract, where is it, and how is it enforced?

For more on this topic, we can, as always, defer to [Joe Armstrong (RIP)](https://www.youtube.com/watch?v=ed7A7r6DBsM).

## How?
Simple. We define:

- What the messages of the protocol are
- A means to **encode** them to bytes
- A means to **decode** them to bytes

We can even take that a step further and define FSMs (as Joe would suggest), but that is future work.


## Examples
Let's say we're using Unix sockets:

```rust
let socket = UnixStream::connect("hotham_editor.socket").unwrap();
let client = EditorClient::new(socket); // woah, generics

let view_configuration = client.request(&requests::GetViewConfiguration {}).unwrap(); // view_configuration is the correct type!!
```

This magic is made possible through the `Request` trait:

```rust
pub trait Request {
/// What should the response to this request be?
type Response: Clone;

/// Get a `RequestType` tag that we can use to identify requests
fn request_type(&self) -> RequestType;
}
```
Loading