Skip to main content

fyrox_ui/inspector/editors/
vec.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21use crate::{
22    core::{algebra::SVector, num_traits::NumCast},
23    inspector::{
24        editors::{
25            PropertyEditorBuildContext, PropertyEditorDefinition, PropertyEditorInstance,
26            PropertyEditorMessageContext, PropertyEditorTranslationContext,
27        },
28        FieldAction, InspectorError, PropertyChanged,
29    },
30    message::{MessageDirection, UiMessage},
31    numeric::NumericType,
32    vec::{VecEditorBuilder, VecEditorMessage},
33    widget::WidgetBuilder,
34    Thickness,
35};
36use std::{any::TypeId, marker::PhantomData};
37
38#[derive(Debug)]
39pub struct VecPropertyEditorDefinition<T: NumericType, const D: usize> {
40    pub phantom: PhantomData<T>,
41}
42
43impl<T: NumericType, const D: usize> Default for VecPropertyEditorDefinition<T, D> {
44    fn default() -> Self {
45        Self {
46            phantom: PhantomData,
47        }
48    }
49}
50
51impl<T: NumericType, const D: usize> PropertyEditorDefinition
52    for VecPropertyEditorDefinition<T, D>
53{
54    fn value_type_id(&self) -> TypeId {
55        TypeId::of::<SVector<T, D>>()
56    }
57
58    fn create_instance(
59        &self,
60        ctx: PropertyEditorBuildContext,
61    ) -> Result<PropertyEditorInstance, InspectorError> {
62        let value = ctx.property_info.cast_value::<SVector<T, D>>()?;
63        Ok(PropertyEditorInstance::simple(
64            VecEditorBuilder::new(WidgetBuilder::new().with_margin(Thickness::uniform(1.0)))
65                .with_min(SVector::repeat(
66                    ctx.property_info
67                        .min_value
68                        .and_then(NumCast::from)
69                        .unwrap_or_else(T::min_value),
70                ))
71                .with_max(SVector::repeat(
72                    ctx.property_info
73                        .max_value
74                        .and_then(NumCast::from)
75                        .unwrap_or_else(T::max_value),
76                ))
77                .with_step(SVector::repeat(
78                    ctx.property_info
79                        .step
80                        .and_then(NumCast::from)
81                        .unwrap_or_else(T::one),
82                ))
83                .with_value(*value)
84                .build(ctx.build_context),
85        ))
86    }
87
88    fn create_message(
89        &self,
90        ctx: PropertyEditorMessageContext,
91    ) -> Result<Option<UiMessage>, InspectorError> {
92        let value = ctx.property_info.cast_value::<SVector<T, D>>()?;
93        Ok(Some(
94            UiMessage::with_data(VecEditorMessage::Value(*value)).with_destination(ctx.instance),
95        ))
96    }
97
98    fn translate_message(&self, ctx: PropertyEditorTranslationContext) -> Option<PropertyChanged> {
99        if ctx.message.direction() == MessageDirection::FromWidget {
100            if let Some(VecEditorMessage::Value(value)) =
101                ctx.message.data::<VecEditorMessage<T, D>>()
102            {
103                return Some(PropertyChanged {
104                    name: ctx.name.to_string(),
105                    action: FieldAction::object(*value),
106                });
107            }
108        }
109        None
110    }
111}
112
113pub type Vec2PropertyEditorDefinition<T> = VecPropertyEditorDefinition<T, 2>;
114pub type Vec3PropertyEditorDefinition<T> = VecPropertyEditorDefinition<T, 3>;
115pub type Vec4PropertyEditorDefinition<T> = VecPropertyEditorDefinition<T, 4>;
116pub type Vec5PropertyEditorDefinition<T> = VecPropertyEditorDefinition<T, 5>;
117pub type Vec6PropertyEditorDefinition<T> = VecPropertyEditorDefinition<T, 6>;