1use r2g_mlua::prelude::*;
2
3use super::instance::IInstanceComponent;
4use super::pvinstance::IPVInstance;
5use super::{DynInstance, IInstance, IObject, InstanceComponent, ManagedInstance, PVInstanceComponent, WeakManagedInstance};
6
7use crate::core::{InheritanceBase, InheritanceTable, InheritanceTableBuilder, Irc, RwLock, RwLockReadGuard, RwLockWriteGuard};
8use crate::userdata::{CFrame, ManagedRBXScriptSignal};
9use crate::userdata::enums::{ModelLevelOfDetail, ModelStreamingMode};
10
11#[derive(Debug)]
12pub struct ModelComponent {
13 level_of_detail: ModelLevelOfDetail,
14 model_streaming_mode: ModelStreamingMode,
15 primary_part: Option<ManagedInstance>, world_pivot: CFrame
17}
18#[derive(Debug)]
19pub struct Model {
20 instance: RwLock<InstanceComponent>,
21 pvinstance: RwLock<PVInstanceComponent>,
22 model: RwLock<ModelComponent>
23}
24pub trait IModel: IPVInstance {
25 fn get_model_component(&self) -> RwLockReadGuard<'_,ModelComponent>;
26 fn get_model_component_mut(&self) -> RwLockWriteGuard<'_,ModelComponent>;
27}
28
29impl InheritanceBase for Model {
30 fn inheritance_table(&self) -> InheritanceTable {
31 InheritanceTableBuilder::new()
32 .insert_type::<Model,dyn IObject>(|x: &Self| x as &dyn IObject, |x: &mut Self| x as &mut dyn IObject)
33 .insert_type::<Model,dyn IInstance>(|x: &Self| x as &dyn IInstance, |x: &mut Self| x as &mut dyn IInstance)
34 .insert_type::<Model,dyn IPVInstance>(|x: &Self| x as &dyn IPVInstance, |x: &mut Self| x as &mut dyn IPVInstance)
35 .insert_type::<Model,dyn IModel>(|x: &Self| x as &dyn IModel, |x: &mut Self| x as &mut dyn IModel)
36 .output()
37 }
38}
39impl IObject for Model {
40 fn is_a(&self, class_name: &String) -> bool {
41 match class_name.as_str() {
42 "Model" |
43 "PVInstance" |
44 "Instance" |
45 "Object" => true,
46 _ => false
47 }
48 }
49 fn lua_get(&self, lua: &Lua, name: String) -> LuaResult<LuaValue> {
50 self.get_model_component().lua_get(self, lua, &name)
51 .or_else(|| self.get_pv_instance_component().lua_get(self, lua, &name))
52 .unwrap_or_else(|| self.get_instance_component().lua_get(lua, &name))
53 }
54 fn get_changed_signal(&self) -> ManagedRBXScriptSignal {
55 self.get_instance_component().changed.clone()
56 }
57 fn get_property_changed_signal(&self, property: String) -> ManagedRBXScriptSignal {
58 self.get_instance_component().get_property_changed_signal(property).unwrap()
59 }
60 fn get_class_name(&self) -> &'static str { "Model" }
61}
62impl IInstance for Model {
63 fn get_instance_component(&self) -> RwLockReadGuard<'_, InstanceComponent> {
64 self.instance.read().unwrap()
65 }
66 fn get_instance_component_mut(&self) -> RwLockWriteGuard<'_, InstanceComponent> {
67 self.instance.write().unwrap()
68 }
69 fn lua_set(&self, lua: &Lua, name: String, val: LuaValue) -> LuaResult<()> {
70 self.get_model_component_mut().lua_set(self, lua, &name, &val)
71 .or_else(|| self.get_pv_instance_component_mut().lua_set(self, lua, &name, &val))
72 .unwrap_or_else(|| self.get_instance_component_mut().lua_set(lua, &name, val))
73 }
74 fn clone_instance(&self, lua: &Lua) -> LuaResult<ManagedInstance> {
75 Ok(Irc::new_cyclic_fallable::<_, LuaError>(|x| {
76 let i = x.cast_to_instance();
77 Ok(Model {
78 instance: RwLock::new_with_flag_auto(self.get_instance_component().clone(lua, &i)?),
79 pvinstance: RwLock::new_with_flag_auto(self.get_pv_instance_component().clone(lua, &i)?),
80 model: RwLock::new_with_flag_auto(self.get_model_component().clone(lua, &i)?)
81 })
82 })?.cast_from_sized().unwrap())
83 }
84}
85impl IPVInstance for Model {
86 fn get_pv_instance_component(&self) -> RwLockReadGuard<'_, PVInstanceComponent> {
87 self.pvinstance.read().unwrap()
88 }
89
90 fn get_pv_instance_component_mut(&self) -> RwLockWriteGuard<'_, PVInstanceComponent> {
91 self.pvinstance.write().unwrap()
92 }
93}
94impl IModel for Model {
95 fn get_model_component(&self) -> RwLockReadGuard<'_, ModelComponent> {
96 self.model.read().unwrap()
97 }
98 fn get_model_component_mut(&self) -> RwLockWriteGuard<'_, ModelComponent> {
99 self.model.write().unwrap()
100 }
101}
102
103impl IInstanceComponent for ModelComponent {
104 fn lua_get(self: &mut RwLockReadGuard<'_, ModelComponent>, _: &DynInstance, _lua: &Lua, key: &String) -> Option<LuaResult<LuaValue>> {
105 match key.as_str() {
106 "LevelOfDetail" => todo!(),
107 "ModelStreamingMode" => todo!(),
108 "PrimaryPart" => todo!(),
109 "WorldPivot" => todo!(),
110 _ => None
111 }
112 }
113
114 fn lua_set(self: &mut RwLockWriteGuard<'_, ModelComponent>, _: &DynInstance, _lua: &Lua, key: &String, _value: &LuaValue) -> Option<LuaResult<()>> {
115 match key.as_str() {
116 "LevelOfDetail" => todo!(),
117 "ModelStreamingMode" => todo!(),
118 "PrimaryPart" => todo!(),
119 "WorldPivot" => todo!(),
120 _ => None
121 }
122 }
123
124 fn clone(self: &RwLockReadGuard<'_, ModelComponent>, _: &Lua, _: &WeakManagedInstance) -> LuaResult<Self> {
125 Ok(ModelComponent {
126 level_of_detail: self.level_of_detail,
127 model_streaming_mode: self.model_streaming_mode,
128 primary_part: None,
129 world_pivot: self.world_pivot
130 })
131 }
132
133 fn new(_: super::WeakManagedInstance, _: &'static str) -> Self {
134 ModelComponent {
135 level_of_detail: ModelLevelOfDetail::Automatic,
136 model_streaming_mode: ModelStreamingMode::Default,
137 primary_part: None,
138 world_pivot: CFrame::IDENTITY
139 }
140 }
141}
142
143impl Model {
144 pub fn new() -> ManagedInstance {
145 Irc::new_cyclic(|x| {
146 Model {
147 instance: RwLock::new_with_flag_auto(InstanceComponent::new(x.cast_to_instance(), "Model")),
148 pvinstance: RwLock::new_with_flag_auto(PVInstanceComponent::new(x.cast_to_instance(), "Model")),
149 model: RwLock::new_with_flag_auto(ModelComponent::new(x.cast_to_instance(), "Model"))
150 }
151 }).cast_from_sized().unwrap()
152 }
153}