Skip to content

Commit

Permalink
WIP: Better behaved ghosts
Browse files Browse the repository at this point in the history
Now we track the entity and map instead of just trying to move
them and hoping for the best.
Renders only the outlines, and they aren't pickbuffer friendly
currently. Still needs to respect hiding.
  • Loading branch information
Froggy618157725 committed Jul 13, 2024
1 parent 8229ec3 commit a320e8e
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 66 deletions.
9 changes: 8 additions & 1 deletion crates/alkahest-renderer/src/ecs/common.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::fmt::Display;

use destiny_pkg::TagHash;
use ecolor::Color32;
use hecs::Entity;

/// Tiger entity world ID
#[derive(Copy, Clone)]
Expand Down Expand Up @@ -97,7 +99,12 @@ impl AsRef<str> for Label {

pub struct Hidden;
pub struct Global;
pub struct Ghost;
#[derive(Clone)]
pub struct Ghost {
pub hash: TagHash,
pub entity: Entity,
pub map_name: Option<String>
}

/// Marker component to indicate that the entity is allowed to be modified in
/// potentially destructive ways (e.g. deleting it, changing it's name, etc.)
Expand Down
16 changes: 13 additions & 3 deletions crates/alkahest-renderer/src/renderer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ use alkahest_data::{
};
use anyhow::Context;
use bitflags::bitflags;
use destiny_pkg::TagHash;
use glam::Vec3;
use hecs::Entity;
use parking_lot::Mutex;
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
use strum::{EnumCount, EnumIter};
use windows::Win32::Graphics::Direct3D11::D3D11_VIEWPORT;
Expand Down Expand Up @@ -133,7 +135,13 @@ impl Renderer {
data.asset_manager.techniques.get_shared(handle)
}

pub fn render_world(&self, view: &impl View, scene: &Scene, resources: &Resources) {
pub fn render_world(
&self,
view: &impl View,
scene: &Scene,
all_scenes: FxHashMap<TagHash, &Scene>,
resources: &Resources,
) {
self.pocus().lastfilters = resources.get::<NodeFilterSet>().clone();

self.begin_world_frame(scene);
Expand All @@ -159,7 +167,8 @@ impl Renderer {
self.draw_pickbuffer(scene, resources.get::<SelectedEntity>().selected());
}

let ghosts : Vec<Entity> = scene.query::<&Ghost>().iter().map(|(e, _ )| e).collect();
let mut ghost_query = scene.query::<&Ghost>();
let ghosts: Vec<&Ghost> = ghost_query.iter().map(|(_, g)| g).collect();
let mut selected = resources.get::<SelectedEntity>().selected();
if let Some(sel) = selected {
if scene.entity(sel).map_or(true, |v| v.has::<Hidden>()) {
Expand All @@ -171,12 +180,13 @@ impl Renderer {
self.draw_outline(
scene,
selected,
all_scenes,
ghosts,
resources
.get::<SelectedEntity>()
.time_selected
.elapsed()
.as_secs_f32()
.as_secs_f32(),
);
}
}
Expand Down
81 changes: 58 additions & 23 deletions crates/alkahest-renderer/src/renderer/pickbuffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use alkahest_data::{
};
use anyhow::Context;
use crossbeam::atomic::AtomicCell;
use destiny_pkg::TagHash;
use hecs::Entity;
use rustc_hash::FxHashMap;
use windows::Win32::{
Foundation::RECT,
Graphics::Direct3D11::{
Expand All @@ -18,8 +20,9 @@ use windows::Win32::{

use crate::{
ecs::{
common::Ghost,
render::{draw_entity, static_geometry::draw_static_instances_individual_system},
Scene,
Scene, SceneInfo,
},
gpu::{buffer::ConstantBuffer, util::DxDeviceExt, GpuContext, SharedGpuContext},
gpu_event, include_dxbc,
Expand Down Expand Up @@ -50,7 +53,14 @@ impl Renderer {
}

// TODO(cohae): move rendering logic to Pickbuffer (where possible)
pub(super) fn draw_outline(&self, scene: &Scene, selected: Option<Entity>, ghosts: Vec<Entity>, time_since_select: f32) {
pub(super) fn draw_outline(
&self,
scene: &Scene,
selected: Option<Entity>,
all_scenes: FxHashMap<TagHash, &Scene>,
ghosts: Vec<&Ghost>,
time_since_select: f32,
) {
gpu_event!(self.gpu, "selection_outline");

self.pickbuffer.outline_depth.clear(0.0, 0);
Expand All @@ -71,31 +81,59 @@ impl Renderer {
self.gpu
.context()
.OMSetDepthStencilState(Some(&self.pickbuffer.outline_depth.state), 0);
draw_entity(
scene,
sel,
self,
Some(&self.pickbuffer.static_instance_cb),
TfxRenderStage::GenerateGbuffer,
);

let ghost = scene.entity(sel).unwrap().get::<&Ghost>();
if ghost
.as_ref()
.is_some_and(|g| scene.get_map_hash().is_some_and(|t| t != g.hash))
{
if let Some(g) = ghost {
match all_scenes.get(&g.hash) {
Some(&ghost_scene) => {
draw_entity(
ghost_scene,
g.entity,
self,
Some(&self.pickbuffer.static_instance_cb),
TfxRenderStage::GenerateGbuffer,
);
}
None => warn!("Ghost Entity had no home!"),
}
}
} else {
draw_entity(
scene,
sel,
self,
Some(&self.pickbuffer.static_instance_cb),
TfxRenderStage::GenerateGbuffer,
);
}
}

// Draw the ghost entities into the ghost depth buffer
if ghosts.len() > 0 {
self.gpu
.context()
.OMSetRenderTargets(None, Some(&self.pickbuffer.ghost_depth.view));
.context()
.OMSetRenderTargets(None, Some(&self.pickbuffer.ghost_depth.view));
self.gpu
.context()
.OMSetDepthStencilState(Some(&self.pickbuffer.ghost_depth.state), 0);

for ghost in ghosts {
draw_entity(
scene,
ghost,
self,
Some(&self.pickbuffer.static_instance_cb),
TfxRenderStage::GenerateGbuffer,
);
match all_scenes.get(&ghost.hash) {
Some(&ghost_scene) => {
draw_entity(
ghost_scene,
ghost.entity,
self,
Some(&self.pickbuffer.static_instance_cb),
TfxRenderStage::GenerateGbuffer,
);
}
None => warn!("Ghost Entity had no home!"),
}
}
}

Expand Down Expand Up @@ -181,8 +219,7 @@ impl Pickbuffer {
selection_request: AtomicCell::new(None),
outline_depth: DepthState::create(gctx.clone(), window_size)
.context("Outline Depth")?,
ghost_depth: DepthState::create(gctx.clone(), window_size)
.context("Ghost Depth")?,
ghost_depth: DepthState::create(gctx.clone(), window_size).context("Ghost Depth")?,
pick_buffer: RenderTarget::create(
window_size,
DxgiFormat::R32_UINT,
Expand Down Expand Up @@ -219,9 +256,7 @@ impl Pickbuffer {
self.outline_depth
.resize(new_size)
.context("Outline Depth")?;
self.ghost_depth
.resize(new_size)
.context("Ghost Depth")?;
self.ghost_depth.resize(new_size).context("Ghost Depth")?;
self.pick_buffer
.resize(new_size)
.context("Entity_Pickbuffer")?;
Expand Down
3 changes: 2 additions & 1 deletion crates/alkahest/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,9 @@ impl AlkahestApp {
maps.update_maps(resources);

let map = maps.current_map().map(|m| &m.scene).unwrap_or(scratch_map);
let all_maps = maps.scene_hashmap();

renderer.render_world(&*resources.get::<Camera>(), map, resources);
renderer.render_world(&*resources.get::<Camera>(), map, all_maps, resources);
}

unsafe {
Expand Down
66 changes: 36 additions & 30 deletions crates/alkahest/src/gui/inspector/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use alkahest_renderer::{
tags::{insert_tag, remove_tag, EntityTag, Tags},
transform::{OriginalTransform, Transform, TransformFlags},
utility::{Beacon, Route, Ruler, Sphere},
Scene,
Scene, SceneInfo,
},
icons::{
ICON_ACCOUNT_CONVERT, ICON_EYE_ARROW_RIGHT_OUTLINE, ICON_EYE_OFF_OUTLINE, ICON_POKEBALL,
Expand Down Expand Up @@ -183,47 +183,52 @@ pub fn show_inspector_panel(

let mut global = e.has::<Global>();
let mut global_changed = false;
let mutable = e.has::<Mutable>();
let mut ghost = e.has::<Ghost>();
let mut ghost_changed = false;
if !e.has::<Route>() {
if ui
.checkbox(
&mut global,
if mutable {
"Show in all Maps"
if e.has::<Mutable>() {
if ui.checkbox(&mut global, "Show in all Maps").changed() {
global_changed = true;
if global {
cmd.insert_one(ent, Global);
} else {
"Show ghost in all Maps"
},
)
.changed()
{
global_changed = true;
if global {
cmd.insert_one(ent, Global);
if !mutable {
cmd.insert_one(ent, Ghost);
cmd.remove_one::<Global>(ent);
}
} else {
cmd.remove_one::<Global>(ent);
if !mutable {
};
ui.separator();
} else {
if ui.checkbox(&mut ghost, "Show ghost in all Maps").changed() {
ghost_changed = true;
if ghost {
cmd.insert_one(
ent,
Ghost {
hash: scene.get_map_hash().expect("Scene has no hash"),
entity: ent,
map_name: None,
},
);
} else {
cmd.remove_one::<Ghost>(ent);
}
}
};
ui.separator();
};
ui.separator();
}
}
show_inspector_components(ui, scene, e, resources);

if global_changed {
if global {
insert_tag(scene, ent, EntityTag::Global);
if !mutable {
insert_tag(scene, ent, EntityTag::Ghost);
}
} else {
remove_tag(scene, ent, EntityTag::Global);
if !mutable {
remove_tag(scene, ent, EntityTag::Ghost);
}
}
}
if ghost_changed {
if global {
insert_tag(scene, ent, EntityTag::Ghost);
} else {
remove_tag(scene, ent, EntityTag::Ghost);
}
}
}
Expand Down Expand Up @@ -265,7 +270,8 @@ fn show_inspector_components(
ShaderBallComponent,
DecoratorRenderer,
SRespawnPoint,
NodeMetadata
NodeMetadata,
Ghost
);
}

Expand Down
34 changes: 33 additions & 1 deletion crates/alkahest/src/gui/inspector/util.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use alkahest_renderer::{
camera::{get_look_angle, tween::Tween, Camera},
ecs::{
common::Ghost,
transform::Transform,
utility::{Beacon, Route, RouteNode, Ruler, Sphere, Utility},
Scene, SceneInfo,
},
icons::{
ICON_ALERT, ICON_ALPHA_A_BOX, ICON_ALPHA_B_BOX, ICON_CAMERA, ICON_CAMERA_CONTROL,
ICON_CLIPBOARD, ICON_DELETE, ICON_EYE_ARROW_RIGHT_OUTLINE, ICON_EYE_OFF_OUTLINE,
ICON_MAP_MARKER, ICON_MAP_MARKER_PATH, ICON_MAP_MARKER_PLUS, ICON_TAG,
ICON_GHOST_OUTLINE, ICON_MAP_MARKER, ICON_MAP_MARKER_PATH, ICON_MAP_MARKER_PLUS, ICON_TAG,
},
renderer::RendererShared,
};
Expand Down Expand Up @@ -617,3 +618,34 @@ impl ComponentPanel for Route {
});
}
}

impl ComponentPanel for Ghost {
fn inspector_name() -> &'static str {
"Ghost"
}

fn has_inspector_ui() -> bool {
true
}

fn inspector_icon() -> char {
ICON_GHOST_OUTLINE
}

fn show_inspector_ui<'s>(
&mut self,
_: &'s Scene,
_: EntityRef<'s>,
ui: &mut egui::Ui,
_: &Resources,
) {
ui.horizontal(|ui| {
ui.strong("Home Map: ");
ui.label(format!("{}({})", self.map_name.as_ref().map_or("", |s|s.as_str()), self.hash.to_string()));
});
ui.horizontal(|ui| {
ui.strong("Entity: ");
ui.label(self.entity.id().to_string());
});
}
}
Loading

0 comments on commit a320e8e

Please sign in to comment.