Skip to content

Commit

Permalink
Support more glam types (#145)
Browse files Browse the repository at this point in the history
### Checklist

* [x] I have read the [Contributor Guide](../../CONTRIBUTING.md)
* [x] I have read and agree to the [Code of
Conduct](../../CODE_OF_CONDUCT.md)
* [x] I have added a description of my changes and why I'd like them
included in the section below

### Description of Changes

Does seem to actually be doable.

### TODO

- [x] Fix `fields_mut` for `Quat`
- [x] Fix `fields_mut` for `Mat2`

### Related Issues

#134
  • Loading branch information
davidpdrsn authored May 6, 2024
1 parent 1e8c6ea commit 411f0f6
Show file tree
Hide file tree
Showing 6 changed files with 533 additions and 9 deletions.
22 changes: 15 additions & 7 deletions crates/mirror-mirror/src/foreign_impls/glam.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use glam::{Mat3, Vec2, Vec3};
use glam::{Mat3, Mat4, Vec2, Vec3, Vec4};
use mirror_mirror_macros::__private_derive_reflect_foreign;

mod mat2;
mod quat;
mod vec4;

__private_derive_reflect_foreign! {
#[reflect(crate_name(crate))]
pub struct Vec2 {
Expand All @@ -18,12 +22,6 @@ __private_derive_reflect_foreign! {
}
}

// `Vec4`, `Quat`, and `Mat2` are left out because glam uses bad hacks which changes the struct
// definitions for different architectures (simd vs no simd) and cargo features. So we'd have
// to use the same hacks in mirror-mirror which I'd like to avoid.

// `Mat4` is left out because it contains `Vec4` which we don't support.

__private_derive_reflect_foreign! {
#[reflect(crate_name(crate))]
pub struct Mat3 {
Expand All @@ -32,3 +30,13 @@ __private_derive_reflect_foreign! {
pub z_axis: Vec3,
}
}

__private_derive_reflect_foreign! {
#[reflect(crate_name(crate))]
pub struct Mat4 {
pub x_axis: Vec4,
pub y_axis: Vec4,
pub z_axis: Vec4,
pub w_axis: Vec4,
}
}
154 changes: 154 additions & 0 deletions crates/mirror-mirror/src/foreign_impls/glam/mat2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
use glam::{Mat2, Vec2};
use kollect::LinearMap;
use std::any::Any;

use crate::{
struct_::{FieldsIter, FieldsIterMut, StructValue},
type_info::graph::*,
DefaultValue, DescribeType, FromReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, Struct,
Value,
};

impl Reflect for Mat2 {
trivial_reflect_methods!();

fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::Struct(self)
}

fn reflect_ref(&self) -> ReflectRef<'_> {
ReflectRef::Struct(self)
}

fn reflect_mut(&mut self) -> ReflectMut<'_> {
ReflectMut::Struct(self)
}

fn patch(&mut self, value: &dyn Reflect) {
if let Some(struct_) = value.as_struct() {
if let Some(x_axis) = struct_.field("x_axis").and_then(<_>::from_reflect) {
self.x_axis = x_axis;
}
if let Some(y_axis) = struct_.field("y_axis").and_then(<_>::from_reflect) {
self.y_axis = y_axis;
}
}
}

fn to_value(&self) -> Value {
StructValue::with_capacity(2)
.with_field("x_axis", self.x_axis)
.with_field("y_axis", self.y_axis)
.to_value()
}

fn clone_reflect(&self) -> Box<dyn Reflect> {
Box::new(*self)
}

fn debug(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if f.alternate() {
write!(f, "{self:#?}")
} else {
write!(f, "{self:?}")
}
}
}

impl Struct for Mat2 {
fn field(&self, name: &str) -> Option<&dyn Reflect> {
match name {
"x_axis" => Some(&self.x_axis),
"y_axis" => Some(&self.y_axis),
_ => None,
}
}

fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect> {
match name {
"x_axis" => Some(&mut self.x_axis),
"y_axis" => Some(&mut self.y_axis),
_ => None,
}
}

fn field_at(&self, index: usize) -> Option<&dyn Reflect> {
match index {
0 => Some(&self.x_axis),
1 => Some(&self.y_axis),
_ => None,
}
}

fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
match index {
0 => Some(&mut self.x_axis),
1 => Some(&mut self.y_axis),
_ => None,
}
}

fn name_at(&self, index: usize) -> Option<&str> {
match index {
0 => Some("x_axis"),
1 => Some("y_axis"),
_ => None,
}
}

fn fields(&self) -> FieldsIter<'_> {
Box::new(
[
("x_axis", self.x_axis.as_reflect()),
("y_axis", self.y_axis.as_reflect()),
]
.into_iter(),
)
}

fn fields_mut(&mut self) -> FieldsIterMut<'_> {
let repr = &mut **self;
Box::new(
[
("x_axis", repr.x_axis.as_reflect_mut()),
("y_axis", repr.y_axis.as_reflect_mut()),
]
.into_iter(),
)
}

fn fields_len(&self) -> usize {
2
}
}

impl FromReflect for Mat2 {
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
if let Some(mat) = reflect.downcast_ref() {
Some(*mat)
} else {
let struct_ = reflect.as_struct()?;
let x_axis = <_>::from_reflect(struct_.field("x_axis")?)?;
let y_axis = <_>::from_reflect(struct_.field("y_axis")?)?;
Some(Self::from_cols(x_axis, y_axis))
}
}
}

impl DefaultValue for Mat2 {
fn default_value() -> Option<Value> {
Some(Self::default().to_value())
}
}

impl DescribeType for Mat2 {
fn build(graph: &mut TypeGraph) -> NodeId {
graph.get_or_build_node_with::<Self, _>(|graph| {
let fields = &[
NamedFieldNode::new::<Vec2>("x_axis", LinearMap::from([]), &[], graph),
NamedFieldNode::new::<Vec2>("y_axis", LinearMap::from([]), &[], graph),
];
StructNode::new::<Self>(fields, LinearMap::from([]), &[])
})
}
}
180 changes: 180 additions & 0 deletions crates/mirror-mirror/src/foreign_impls/glam/quat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
use glam::Quat;
use kollect::LinearMap;
use std::any::Any;

use crate::{
struct_::{FieldsIter, FieldsIterMut, StructValue},
type_info::graph::*,
DefaultValue, DescribeType, FromReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, Struct,
Value,
};

impl Reflect for Quat {
trivial_reflect_methods!();

fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::Struct(self)
}

fn reflect_ref(&self) -> ReflectRef<'_> {
ReflectRef::Struct(self)
}

fn reflect_mut(&mut self) -> ReflectMut<'_> {
ReflectMut::Struct(self)
}

fn patch(&mut self, value: &dyn Reflect) {
if let Some(struct_) = value.as_struct() {
if let Some(x) = struct_.field("x").and_then(<_>::from_reflect) {
self.x = x;
}
if let Some(y) = struct_.field("y").and_then(<_>::from_reflect) {
self.y = y;
}
if let Some(z) = struct_.field("z").and_then(<_>::from_reflect) {
self.z = z;
}
if let Some(w) = struct_.field("w").and_then(<_>::from_reflect) {
self.w = w;
}
}
}

fn to_value(&self) -> Value {
StructValue::with_capacity(4)
.with_field("x", self.x)
.with_field("y", self.y)
.with_field("z", self.z)
.with_field("w", self.w)
.to_value()
}

fn clone_reflect(&self) -> Box<dyn Reflect> {
Box::new(*self)
}

fn debug(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if f.alternate() {
write!(f, "{self:#?}")
} else {
write!(f, "{self:?}")
}
}
}

impl Struct for Quat {
fn field(&self, name: &str) -> Option<&dyn Reflect> {
match name {
"x" => Some(&self.x),
"y" => Some(&self.y),
"z" => Some(&self.z),
"w" => Some(&self.w),
_ => None,
}
}

fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect> {
match name {
"x" => Some(&mut self.x),
"y" => Some(&mut self.y),
"z" => Some(&mut self.z),
"w" => Some(&mut self.w),
_ => None,
}
}

fn field_at(&self, index: usize) -> Option<&dyn Reflect> {
match index {
0 => Some(&self.x),
1 => Some(&self.y),
2 => Some(&self.z),
3 => Some(&self.w),
_ => None,
}
}

fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
match index {
0 => Some(&mut self.x),
1 => Some(&mut self.y),
2 => Some(&mut self.z),
3 => Some(&mut self.w),
_ => None,
}
}

fn name_at(&self, index: usize) -> Option<&str> {
match index {
0 => Some("x"),
1 => Some("y"),
2 => Some("z"),
3 => Some("w"),
_ => None,
}
}

fn fields(&self) -> FieldsIter<'_> {
Box::new(
[
("x", self.x.as_reflect()),
("y", self.y.as_reflect()),
("z", self.z.as_reflect()),
("w", self.w.as_reflect()),
]
.into_iter(),
)
}

fn fields_mut(&mut self) -> FieldsIterMut<'_> {
let repr = &mut **self;
Box::new(
[
("x", repr.x.as_reflect_mut()),
("y", repr.y.as_reflect_mut()),
("z", repr.z.as_reflect_mut()),
("w", repr.w.as_reflect_mut()),
]
.into_iter(),
)
}

fn fields_len(&self) -> usize {
4
}
}

impl FromReflect for Quat {
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
if let Some(quat) = reflect.downcast_ref() {
Some(*quat)
} else {
let struct_ = reflect.as_struct()?;
let x = <_>::from_reflect(struct_.field("x")?)?;
let y = <_>::from_reflect(struct_.field("y")?)?;
let z = <_>::from_reflect(struct_.field("z")?)?;
let w = <_>::from_reflect(struct_.field("w")?)?;
Some(Self::from_xyzw(x, y, z, w))
}
}
}

impl DefaultValue for Quat {
fn default_value() -> Option<Value> {
Some(Self::default().to_value())
}
}

impl DescribeType for Quat {
fn build(graph: &mut TypeGraph) -> NodeId {
graph.get_or_build_node_with::<Self, _>(|graph| {
let fields = &[
NamedFieldNode::new::<f32>("x", LinearMap::from([]), &[], graph),
NamedFieldNode::new::<f32>("y", LinearMap::from([]), &[], graph),
NamedFieldNode::new::<f32>("z", LinearMap::from([]), &[], graph),
NamedFieldNode::new::<f32>("w", LinearMap::from([]), &[], graph),
];
StructNode::new::<Self>(fields, LinearMap::from([]), &[])
})
}
}
Loading

0 comments on commit 411f0f6

Please sign in to comment.