Skip to content
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
8 changes: 6 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ name = "sicht"
version = "0.1.0"
edition = "2021"

[features]
serde = ["dep:serde", "dep:serde_derive"]

[dependencies]
serde = { version = "1.0.217", features = ["derive"] }
serde_derive = "1.0.217"
serde = { optional = true, version = "1.0.217", features = ["derive"] }
serde_derive = { optional = true, version = "1.0.217" }
slotmap = "1.1.1"
82 changes: 82 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

85 changes: 85 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
flake-utils.url = "github:numtide/flake-utils";
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
};

outputs = inputs @ { self, nixpkgs, flake-utils, rust-overlay, ... }:
flake-utils.lib.eachDefaultSystem (
system: let
overlays = [ (import rust-overlay) ];
pkgs = import nixpkgs { inherit system overlays; };
in {
devShells.default = with pkgs; mkShell rec {
buildInputs = [
(rust-bin.nightly.latest.minimal.override {
extensions = [ "clippy" "rust-analyzer" "rust-docs" "rust-src" "miri" ];
})
# We use nightly rustfmt features.
(rust-bin.selectLatestNightlyWith (toolchain: toolchain.rustfmt))

# Vulkan dependencies
shaderc
spirv-tools
vulkan-loader
vulkan-tools
vulkan-tools-lunarg
vulkan-validation-layers
vulkan-extension-layer

# winit dependencies
libxkbcommon
wayland
xorg.libX11
xorg.libXcursor
xorg.libXi
xorg.libXrandr
SDL2

clang
libclang
glibc.dev

valgrind
gdb

feh
];

LD_LIBRARY_PATH = lib.makeLibraryPath buildInputs;
SHADERC_LIB_DIR = lib.makeLibraryPath [ shaderc ];
VK_LAYER_PATH = "${vulkan-validation-layers}/share/vulkan/explicit_layer.d";
};
devShells.CI = with pkgs; mkShell rec {
buildInputs = [
(rust-bin.stable.latest.minimal.override {
extensions = [ "clippy" ];
# Windows CI unfortunately needs to cross-compile from within WSL because Nix doesn't
# work on Windows.
targets = [ "x86_64-pc-windows-msvc" ];
})
# We use nightly rustfmt features.
(rust-bin.selectLatestNightlyWith (toolchain: toolchain.rustfmt))

# Vulkan dependencies
shaderc

# winit dependencies
libxkbcommon
wayland
xorg.libX11
xorg.libXcursor
xorg.libXi
xorg.libXrandr
];

LD_LIBRARY_PATH = lib.makeLibraryPath buildInputs;
SHADERC_LIB_DIR = lib.makeLibraryPath [ shaderc ];
};
}
);
}
151 changes: 151 additions & 0 deletions src/birelational_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
use std::{collections::HashMap, hash::Hash};

use slotmap::{DefaultKey, SlotMap};

pub trait BirelationalId {
type Id;

fn get_id(&self) -> Self::Id;
}

impl BirelationalId for usize {
type Id = usize;

fn get_id(&self) -> Self::Id {
*self
}
}

// A <= AID => [B]
// B <= BID => [A]

// Entity <= EntityId => [Component]
// Component <= ComponentId => [Entity]

pub struct BirelationalMap<K, V>
where
K: BirelationalId,
V: BirelationalId,
K::Id: Hash + Eq + PartialEq,
V::Id: Hash + Eq + PartialEq,
{
keys: SlotMap<DefaultKey, K>,
values: SlotMap<DefaultKey, V>,
keys_map: HashMap<K::Id, (DefaultKey, Vec<DefaultKey>)>,
values_map: HashMap<V::Id, (DefaultKey, Vec<DefaultKey>)>,
}

impl<K, V> BirelationalMap<K, V>
where
K: BirelationalId,
V: BirelationalId,
K::Id: Hash + Eq + PartialEq,
V::Id: Hash + Eq + PartialEq,
{
pub fn new() -> Self {
Self {
keys: SlotMap::new(),
values: SlotMap::new(),
keys_map: HashMap::new(),
values_map: HashMap::new(),
}
}

pub fn get(&mut self, key: K) -> Option<Vec<&'_ V>> {
self.keys_map
.get(&key.get_id())?
.1
.iter()
.map(|x| self.values.get(*x))
.collect()
}

pub fn get_value(&mut self, value: V) -> Option<Vec<&'_ K>> {
self.values_map
.get(&value.get_id())?
.1
.iter()
.map(|x| self.keys.get(*x))
.collect()
}

pub fn insert(&mut self, key: K, value: V) {
let (key_id, value_id) = (key.get_id(), value.get_id());
let key_exists = self.keys_map.contains_key(&key_id);
let value_exists = self.values_map.contains_key(&value_id);

match (key_exists, value_exists) {
(true, true) => {
let key_idx = self.keys_map.get(&key_id).unwrap().0;
let value_idx = self.values_map.get(&value_id).unwrap().0;

let (_, values) = self.keys_map.get_mut(&key_id).unwrap();
if !values.contains(&value_idx) {
values.push(value_idx);
}

let (_, keys) = self.values_map.get_mut(&value_id).unwrap();
if !keys.contains(&key_idx) {
keys.push(key_idx);
}
}
(true, false) => {
let key_idx = self.keys_map.get(&key_id).unwrap().0;
let value_idx = self.values.insert(value);

let (_, values) = self.keys_map.get_mut(&key_id).unwrap();
values.push(value_idx);
self.values_map.insert(value_id, (value_idx, vec![key_idx]));
}
(false, true) => {
let value_idx = self.values_map.get(&value_id).unwrap().0;
let key_idx = self.keys.insert(key);

self.keys_map.insert(key_id, (key_idx, vec![value_idx]));
let (_, keys) = self.values_map.get_mut(&value_id).unwrap();
keys.push(key_idx);
}
(false, false) => {
let key_idx = self.keys.insert(key);
let value_idx = self.values.insert(value);

self.keys_map.insert(key_id, (key_idx, vec![value_idx]));
self.values_map.insert(value_id, (value_idx, vec![key_idx]));
}
}
}

pub fn remove(&mut self, key: K, value: V)
where
for<'a> &'a V: PartialEq,
for<'a> &'a K: PartialEq,
{
if let Some((_, items)) = self.keys_map.get_mut(&key.get_id()) {
let taken_items = std::mem::take(items);
*items = taken_items
.into_iter()
.filter(|x| self.values.get(*x) != Some(&value))
.collect();
}

if let Some((_, items)) = self.values_map.get_mut(&value.get_id()) {
let taken_items = std::mem::take(items);
*items = taken_items
.into_iter()
.filter(|x| self.keys.get(*x) != Some(&key))
.collect();
}
}
}

impl<K, V> Default for BirelationalMap<K, V>
where
K: BirelationalId,
V: BirelationalId,
K::Id: Hash + Eq + PartialEq,
V::Id: Hash + Eq + PartialEq,
{
fn default() -> Self {
Self::new()
}
}
Loading