1use std::borrow::Borrow;
2use std::collections::{HashMap, HashSet};
3use std::fmt::Debug;
4use std::hash::{DefaultHasher, Hash, Hasher};
5use std::mem::swap;
6use std::ops::Deref;
7use std::ptr::NonNull;
8
9use r2g_mlua::prelude::*;
10
11use crate::core::alloc::Allocator;
12use crate::core::lua_macros::lua_getter;
13use crate::core::{get_state, get_task_scheduler_from_lua, IWeak, Irc, IrcHead, ParallelDispatch, RwLockReadGuard, RwLockWriteGuard};
14use crate::userdata::{ManagedRBXScriptSignal, RBXScriptSignal};
15
16use super::IObject;
17
18pub type DynInstance = dyn IInstance;
19pub type ManagedInstance = Irc<DynInstance>;
20pub type WeakManagedInstance = IWeak<DynInstance>;
21pub type EventsTable = HashMap<String, ManagedRBXScriptSignal>;
22
23pub trait IInstanceComponent: Sized {
24 unsafe fn weak_to_strong_instance(ptr: WeakManagedInstance) -> ManagedInstance {
25 ptr.upgrade().unwrap_unchecked()
26 }
27 fn lua_get(self: &mut RwLockReadGuard<'_, Self>, ptr: &DynInstance, lua: &Lua, key: &String) -> Option<LuaResult<LuaValue>>;
28 fn lua_set(self: &mut RwLockWriteGuard<'_, Self>, ptr: &DynInstance, lua: &Lua, key: &String, value: &LuaValue) -> Option<LuaResult<()>>;
29 fn clone(self: &RwLockReadGuard<'_, Self>, lua: &Lua, new_ptr: &WeakManagedInstance) -> LuaResult<Self>;
30 fn new(ptr: WeakManagedInstance, class_name: &'static str) -> Self;
31}
32
33type ReadInstanceComponent<'a> = RwLockReadGuard<'a, InstanceComponent>;
34type WriteInstanceComponent<'a> = RwLockWriteGuard<'a, InstanceComponent>;
35
36pub trait IReadInstanceComponent: Deref<Target = InstanceComponent> + Borrow<InstanceComponent> + Sized {}
37
38impl<'a> IReadInstanceComponent for ReadInstanceComponent<'a> {}
39impl<'a> IReadInstanceComponent for WriteInstanceComponent<'a> {}
40
41pub trait IInstance: IObject {
42 fn get_instance_component(&self) -> RwLockReadGuard<InstanceComponent>;
43 fn get_instance_component_mut(&self) -> RwLockWriteGuard<InstanceComponent>;
44
45 fn lua_set(&self, lua: &Lua, name: String, val: LuaValue) -> LuaResult<()>;
46
47 fn clone_instance(&self, lua: &Lua) -> LuaResult<ManagedInstance>;
48
49 fn get_actor(&self) -> LuaResult<Option<ManagedInstance>> {
50 DynInstance::guard_find_first_ancestor_of_class(&self.get_instance_component(),"Actor".into())
51 }
52}
53
54impl DynInstance {
55 #[inline]
56 pub fn get_parent(&self) -> Option<ManagedInstance> {
57 DynInstance::guard_get_parent(&self.get_instance_component())
58 }
59 #[inline]
60 pub fn set_parent(&self, lua: &Lua, parent: Option<ManagedInstance>) -> LuaResult<()> {
61 DynInstance::guard_set_parent(&mut self.get_instance_component_mut(), lua, parent)
62 }
63 #[inline]
64 pub fn get_name(&self) -> String {
65 DynInstance::guard_get_name(&self.get_instance_component())
66 }
67 #[inline]
68 pub fn set_name(&self, val: String) -> LuaResult<()> {
69 DynInstance::guard_set_name(&mut self.get_instance_component_mut(), val)
70 }
71 #[inline]
72 pub fn get_archivable(&self) -> bool {
73 DynInstance::guard_get_archivable(&self.get_instance_component())
74 }
75 #[inline]
76 pub fn set_archivable(&self, val: bool) -> LuaResult<()> {
77 DynInstance::guard_set_archivable(&mut self.get_instance_component_mut(), val)
78 }
79 #[inline]
80 pub fn get_uniqueid(&self) -> usize {
81 Self::guard_get_uniqueid(&self.get_instance_component())
82 }
83 #[inline]
84 pub fn init_uniqueid(&self) -> LuaResult<()> {
85 DynInstance::guard_init_uniqueid(&mut self.get_instance_component_mut())
86 }
87 #[inline]
88 pub fn set_uniqueid(&self, value: usize) -> LuaResult<()> {
89 DynInstance::guard_set_uniqueid(&mut self.get_instance_component_mut(), value)
90 }
91
92 #[inline]
93 pub fn get_ancestors(&self) -> Vec<ManagedInstance> {
94 DynInstance::guard_get_ancestors(&self.get_instance_component())
95 }
96 #[inline]
97 pub fn get_children(&self) -> LuaResult<Vec<ManagedInstance>> {
98 DynInstance::guard_get_children(&self.get_instance_component())
99 }
100 #[inline]
101 pub fn get_descendants(&self) -> LuaResult<Vec<ManagedInstance>> {
102 DynInstance::guard_get_descendants(&self.get_instance_component())
103 }
104 #[inline]
105 pub fn is_ancestor_of(&self, descendant: ManagedInstance) -> LuaResult<bool> {
106 DynInstance::is_ancestor_of_guard_guard(&self.get_instance_component(), &descendant.get_instance_component())
107 }
108 #[inline]
109 pub fn is_descendant_of(&self, ancestor: ManagedInstance) -> LuaResult<bool> {
110 DynInstance::is_ancestor_of_guard_guard(&ancestor.get_instance_component(), &self.get_instance_component())
111 }
112 #[inline]
113 pub fn lock_parent(&self) {
114 DynInstance::guard_lock_parent(&mut self.get_instance_component_mut());
115 }
116 #[inline]
117 pub fn get_parent_protected(&self) -> bool {
118 DynInstance::guard_get_parent_protected(&self.get_instance_component())
119 }
120 #[inline]
121 pub fn clear_all_children(&self, lua: &Lua) -> LuaResult<()> {
122 DynInstance::guard_clear_all_children(&mut self.get_instance_component_mut(), lua)
123 }
124 #[inline]
125 pub fn destroy(&self, lua: &Lua) -> LuaResult<()> {
126 DynInstance::guard_destroy(&mut self.get_instance_component_mut(), lua)
127 }
128
129
130 pub fn guard_get_parent(this: &impl IReadInstanceComponent) -> Option<ManagedInstance> {
131 let parent = this.parent.as_ref();
132 if parent.is_some() { unsafe {
133 let parent = parent.unwrap_unchecked().upgrade();
134 if parent.is_some() {
135 return Some(parent.unwrap_unchecked())
136 }
137 return None
138 }}
139 None
140 }
141 #[inline]
142 pub fn guard_set_parent(this: &mut WriteInstanceComponent, lua: &Lua, parent: Option<ManagedInstance>) -> LuaResult<()> {
143 if this.parent_locked {
144 Err(LuaError::RuntimeError("Parent property is locked.".into()))
145 } else {
146 DynInstance::set_parent_forced(this, lua, parent)
147 }
148 }
149 fn set_parent_forced(this: &mut WriteInstanceComponent, lua: &Lua, parent: Option<ManagedInstance>) -> LuaResult<()> {
150 if parent.is_some() {
153 let _parent_instance = parent.as_ref().unwrap();
154 let p = _parent_instance.get_instance_component();
155 let this_ptr = this._ptr.as_ref().unwrap().upgrade().unwrap();
156 let _guard_release = this.guard_release();
157 if DynInstance::guard_is_descendant_of(&p, this_ptr)? {
158 return Err(LuaError::RuntimeError("Invalid hierarchy while setting up instance tree.".into()))
159 }
160 }
161 if this.parent.is_some() {
162 let ancestors = DynInstance::guard_get_ancestors(&*this);
164 let _ptr_this = this._ptr.as_ref().unwrap().upgrade().unwrap();
165 let _guard_release = this.guard_release();
166 for ancestor in ancestors {
167 ancestor.get_instance_component()
168 .descendant_removing.write().fire(lua, (_ptr_this.clone(),))?;
169 }
170 }
171
172 let new_parent = parent.clone();
173 let mut old_parent = parent.map(|x| x.downgrade());
174 swap(&mut this.parent, &mut old_parent);
175
176 if old_parent.is_some() {
177 let _ptr_this = this._ptr.as_ref().unwrap().upgrade().unwrap();
178 let _guard_release = this.guard_release();
179 let old_parent = old_parent.unwrap().upgrade().unwrap();
180 old_parent.get_instance_component_mut().children.retain(|x| *x != _ptr_this);
181 old_parent.get_instance_component().child_removed.write().fire_ancestry(lua, (_ptr_this,))?;
182 }
183
184 let descendants = DynInstance::guard_get_descendants(this)?;
185
186 let _ptr_this = this._ptr.as_ref().unwrap().upgrade().unwrap();
187 let _guard_release = this.guard_release();
188 for i in descendants {
189 i.get_instance_component()
190 .ancestry_changed.write().fire(lua, (_ptr_this.clone(), new_parent.clone()))?;
191 }
192 drop(_guard_release);
193
194 if new_parent.is_some() {
195 let ancestors = DynInstance::guard_get_ancestors(this);
196 let _guard_release = this.guard_release();
197 let new_parent = new_parent.unwrap();
198 new_parent.get_instance_component_mut().children.push(_ptr_this.clone());
199 new_parent.get_instance_component().child_added.write().fire_ancestry(lua, (_ptr_this.clone(),))?;
200 for ancestor in ancestors {
201 ancestor.get_instance_component().descendant_added.write().fire_ancestry(lua, (_ptr_this.clone(),))?;
202 }
203 }
204 Ok(())
205 }
206 pub fn guard_get_name(this: &impl IReadInstanceComponent) -> String {
207 this.name.clone()
208 }
209 pub fn guard_set_name(this: &mut WriteInstanceComponent, val: String) -> LuaResult<()> {
210 this.name = val;
211 Ok(())
212 }
213 pub fn guard_get_archivable(this: &impl IReadInstanceComponent) -> bool {
214 this.archivable
215 }
216 pub fn guard_set_archivable(this: &mut WriteInstanceComponent, val: bool) -> LuaResult<()> {
217 this.archivable = val;
218 Ok(())
219 }
220 pub fn guard_get_uniqueid(this: &impl IReadInstanceComponent) -> usize {
221 this.unique_id
222 }
223 pub fn guard_init_uniqueid(this: &mut WriteInstanceComponent) -> LuaResult<()> {
224 if this.unique_id != 0 {
225 return Err(LuaError::RuntimeError("Instance::UniqueId was previously initialized.".into()));
226 }
227 let mut hasher = DefaultHasher::new();
228 (&raw const *this).hash(&mut hasher);
229 this.unique_id = hasher.finish() as usize;
230 Ok(())
231 }
232 pub fn guard_set_uniqueid(this: &mut WriteInstanceComponent, value: usize) -> LuaResult<()> {
233 if this.unique_id != 0 {
234 return Err(LuaError::RuntimeError("Instance::UniqueId was previously initialized.".into()));
235 }
236 this.unique_id = value;
237 Ok(())
238 }
239
240 pub fn guard_get_ancestors(this: &impl IReadInstanceComponent) -> Vec<ManagedInstance> {
241 let mut i = this.parent.as_ref().map(|x| x.upgrade()).flatten();
242 let mut vec = Vec::new();
243 while let Some(instance) = i {
244 i = instance.get_parent();
245 vec.push(instance);
246 }
247 vec
248 }
249 pub fn guard_get_children(this: &impl IReadInstanceComponent) -> LuaResult<Vec<ManagedInstance>> {
250 Ok(this.children.clone())
251 }
252 pub fn guard_get_descendants(this: &impl IReadInstanceComponent) -> LuaResult<Vec<ManagedInstance>> {
253 let mut current = DynInstance::guard_get_children(this)?;
254 let mut descendants: Vec<ManagedInstance> = vec![];
255 descendants.append(&mut current);
256 while current.len() != 0 {
257 let mut new_current: Vec<ManagedInstance> = vec![];
258 for i in current {
259 new_current.append(&mut i.get_descendants()?);
260 }
261 descendants.append(&mut new_current);
262 current = new_current;
263 };
264 Ok(descendants)
265 }
266 pub fn guard_lock_parent(this: &mut WriteInstanceComponent) {
267 this.parent_locked = true;
268 }
269 pub fn guard_get_parent_protected(this: &impl IReadInstanceComponent) -> bool {
270 this.parent_locked
271 }
272 pub fn guard_clear_all_children(this: &mut WriteInstanceComponent, lua: &Lua) -> LuaResult<()> {
273 let children = this.children.clone().into_iter();
274 let _guard = this.guard_release();
275 for i in children {
276 let mut instance_write = i.get_instance_component_mut();
277 if !instance_write.parent_locked {
278 DynInstance::guard_destroy(&mut instance_write, lua)?;
279 }
280 }
281 Ok(())
282 }
283 pub fn guard_destroy(this: &mut WriteInstanceComponent, lua: &Lua) -> LuaResult<()> {
284 if this.parent_locked {
285 return Err(LuaError::RuntimeError("Parent property locked.".into()));
286 }
287 {
288 let signal = this.destroying.clone();
289 let destroying = signal.write();
290
291 let _guard_release = this.guard_release();
292
293 destroying.fire(lua,())?;
294 }
295 this.parent_locked = true;
296 DynInstance::set_parent_forced(this, lua, None)?;
297 DynInstance::guard_clear_all_children(this, lua)?;
298 Ok(())
299 }
300 #[inline]
301 pub fn guard_is_ancestor_of(this: &impl IReadInstanceComponent, descendant: ManagedInstance) -> LuaResult<bool> {
302 DynInstance::is_ancestor_of_guard_guard(this, &descendant.get_instance_component())
303 }
304 #[inline]
305 pub fn guard_is_descendant_of(this: &impl IReadInstanceComponent, ancestor: ManagedInstance) -> LuaResult<bool> {
306 DynInstance::is_ancestor_of_guard_guard(&ancestor.get_instance_component(), this)
307 }
308 pub fn guard_find_first_ancestor_of_class(this: &impl IReadInstanceComponent, class: String) -> LuaResult<Option<ManagedInstance>> {
309 for i in DynInstance::guard_get_ancestors(this) {
310 if i.get_class_name() == class {
311 return Ok(Some(i));
312 }
313 }
314 Ok(None)
315 }
316
317 pub fn get_debug_id(&self, _scope_length: LuaNumber) -> LuaResult<String> {
318 Ok(format!("0x{:x}",(&raw const *self.get_instance_component()) as usize))
319 }
320 pub fn get_full_name(&self) -> LuaResult<String> {
321 let mut hierarchy = Vec::new();
322 let mut parent = self.get_parent();
323 while parent.is_some() {
324 let parent_unwrapped = unsafe { parent.unwrap_unchecked() };
325 let parent_read = parent_unwrapped.get_instance_component();
326 hierarchy.insert(0, DynInstance::guard_get_name(&parent_read));
327
328 parent = DynInstance::guard_get_parent(&parent_read);
329 }
330 hierarchy.push(self.get_name());
331 Ok(hierarchy.join("."))
332 }
333 pub fn add_tag(&self, lua: &Lua, tag: String) -> LuaResult<()> {
334 let mut write = self.get_instance_component_mut();
335 let ptr = write._ptr.clone().unwrap();
336 write.tags.insert(tag.clone());
337 drop(write);
338 get_state(lua).get_vm().get_instance_tag_table().add_tag(tag, ptr);
339 Ok(())
340 }
341
342 pub async fn wait_for_child(&self, lua: &Lua, name: String, timeout: Option<LuaNumber>) -> LuaResult<Option<ManagedInstance>> {
343 let inst = self.find_first_child(name.clone(), Some(false)).unwrap();
344 if inst.is_some() {
345 Ok(Some(unsafe { inst.unwrap_unchecked() }))
346 } else {
347 let thread = lua.current_thread();
348 if timeout.is_some() {
349 get_task_scheduler_from_lua(lua).delay_thread(thread.clone(), ParallelDispatch::Default, timeout.unwrap())?;
350 }
351 let i = self.get_instance_component().child_added.clone();
352 let mut instance: ManagedInstance;
353 loop {
354 let mv = i.read().wait(lua).await?;
355 if mv.is_empty() {
356 return Ok(None); }
358 instance = ManagedInstance::from_lua_multi(mv, lua)?;
359 if instance.get_name() == name {
360 break;
361 }
362 }
363 Ok(Some(instance))
364 }
365 }
366 pub fn find_first_ancestor(&self, name: String) -> LuaResult<Option<ManagedInstance>> {
367 for i in self.get_ancestors() {
368 if i.get_name() == name {
369 return Ok(Some(i));
370 }
371 }
372 Ok(None)
373 }
374 pub fn find_first_ancestor_of_class(&self, class: String) -> LuaResult<Option<ManagedInstance>> {
375 for i in self.get_ancestors() {
376 if i.get_class_name() == class {
377 return Ok(Some(i));
378 }
379 }
380 Ok(None)
381 }
382 pub fn find_first_ancestor_which_is_a(&self, class: String) -> LuaResult<Option<ManagedInstance>> {
383 for i in self.get_ancestors() {
384 if i.is_a(&class) {
385 return Ok(Some(i));
386 }
387 }
388 Ok(None)
389 }
390 pub fn find_first_child(&self, name: String, recursive: Option<bool>) -> LuaResult<Option<ManagedInstance>> {
391 if recursive.unwrap_or(false) {
392 for i in self.get_children()? {
393 if i.get_name() == name {
394 return Ok(Some(i));
395 }
396 }
397 Ok(None)
398 } else {
399 self.find_first_descendant(name)
400 }
401 }
402 pub fn find_first_child_of_class(&self, class: String) -> LuaResult<Option<ManagedInstance>> {
403 for i in self.get_children()? {
404 if i.get_class_name() == class {
405 return Ok(Some(i));
406 }
407 }
408 Ok(None)
409 }
410 pub fn find_first_child_which_is_a(&self, class: String) -> LuaResult<Option<ManagedInstance>> {
411 for i in self.get_children()? {
412 if i.is_a(&class) {
413 return Ok(Some(i));
414 }
415 }
416 Ok(None)
417 }
418 pub fn find_first_descendant(&self, name: String) -> LuaResult<Option<ManagedInstance>> {
419 for i in self.get_descendants()? {
420 if i.get_name() == name {
421 return Ok(Some(i));
422 }
423 }
424 Ok(None)
425 }
426 pub fn get_attribute(&self, attribute: String) -> LuaResult<LuaValue> {
427 Ok(self.get_instance_component().attributes.get(&attribute).unwrap_or(&LuaNil).clone())
428 }
429 pub fn get_attribute_changed_signal(&self, attribute: String) -> LuaResult<ManagedRBXScriptSignal> {
430 let read = self.get_instance_component();
431 if let Some(event) = read.attribute_changed_table.get(&attribute) {
432 Ok(event.clone())
433 } else {
434 drop(read);
435 let mut write = self.get_instance_component_mut();
436 let event = RBXScriptSignal::new();
437 write.attribute_changed_table.insert(attribute, event.clone());
438 Ok(event)
439 }
440 }
441 pub fn get_attributes(&self, lua: &Lua) -> LuaResult<LuaValue> {
442 self.get_instance_component().attributes.clone().into_lua(lua)
443 }
444 pub fn get_tags(&self) -> LuaResult<Vec<String>> {
445 Ok(self.get_instance_component().tags.iter().map(|x| x.clone()).collect())
446 }
447 pub fn has_tag(&self, tag: String) -> LuaResult<bool> {
448 Ok(self.get_instance_component().tags.get(&tag).is_some())
449 }
450 fn is_ancestor_of_guard_guard(this: &impl IReadInstanceComponent, descendant: &impl IReadInstanceComponent) -> LuaResult<bool> {
451 let mut i = DynInstance::guard_get_parent(descendant);
452 while let Some(ref parent) = i {
453 let read = parent.get_instance_component();
454 if unsafe {read._ptr.as_ref().unwrap_unchecked() == this._ptr.as_ref().unwrap_unchecked()} {
455 return Ok(true);
456 }
457 let new_i = read.parent.as_ref().map(|x| x.upgrade()).flatten();
458 drop(read);
459 i = new_i;
460 }
461 Ok(false)
462 }
463 pub fn remove_tag(&self, lua: &Lua, tag: String) -> LuaResult<()> {
464 let mut write = self.get_instance_component_mut();
465 let ptr = write._ptr.clone().unwrap();
466 write.tags.remove(&tag);
467 drop(write);
468 get_state(lua).get_vm().get_instance_tag_table().remove_tag(tag, &ptr);
469 Ok(())
470 }
471 pub fn set_attribute(&self, lua: &Lua, attribute: String, value: LuaValue) -> LuaResult<()> {
472 let mut write = self.get_instance_component_mut();
473 write.attributes.insert(attribute.clone(), value.clone());
474 let attribute_changed = write.attribute_changed.clone();
475 let attribute_changed_signal = write.attribute_changed_table.get(&attribute).cloned();
476 attribute_changed.write().fire(lua, (attribute,))?;
477 attribute_changed_signal.map(move |x| x.write().fire(lua, (value,))).unwrap_or(Ok(()))
478 }
479
480}
481
482impl Debug for DynInstance {
483 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
484 f.write_str(&format!("{:x}", &raw const *self as *const u8 as usize))
485 }
486}
487
488#[derive(Debug)]
489pub struct InstanceComponent {
490 archivable: bool,
491 name: String,
492 parent: Option<WeakManagedInstance>,
493 _ptr: Option<WeakManagedInstance>,
494 unique_id: usize,
495 children: Vec<ManagedInstance>,
496 children_cache: HashMap<String, WeakManagedInstance>,
497 children_cache_dirty: bool,
498 parent_locked: bool,
499
500 pub ancestry_changed: ManagedRBXScriptSignal,
501 pub attribute_changed: ManagedRBXScriptSignal,
502 pub changed: ManagedRBXScriptSignal,
503 pub child_added: ManagedRBXScriptSignal,
504 pub child_removed: ManagedRBXScriptSignal,
505 pub descendant_added: ManagedRBXScriptSignal,
506 pub descendant_removing: ManagedRBXScriptSignal,
507 pub destroying: ManagedRBXScriptSignal,
508
509 pub attribute_changed_table: EventsTable,
510 pub property_changed_table: EventsTable,
511
512 attributes: HashMap<String, LuaValue>,
513 tags: HashSet<String>
514}
515
516impl PartialEq for DynInstance {
517 fn eq(&self, other: &Self) -> bool {
518 (&raw const *self) == (&raw const *other)
519 }
520}
521impl Eq for DynInstance {}
522
523impl IInstanceComponent for InstanceComponent {
524 fn lua_get(self: &mut RwLockReadGuard<'_, Self>, _: &DynInstance, lua: &Lua, key: &String) -> Option<LuaResult<LuaValue>> {
525 Some(InstanceComponent::lua_get(self, lua, key))
526 }
527
528 fn lua_set(self: &mut RwLockWriteGuard<'_, Self>, _: &DynInstance, lua: &Lua, key: &String, value: &LuaValue) -> Option<LuaResult<()>> {
529 Some(InstanceComponent::lua_set(self, lua, key, value.clone()))
530 }
531
532 fn new(ptr: WeakManagedInstance, class_name: &'static str) -> Self {
533 let inst = InstanceComponent {
534 parent: None,
535 name: String::from(class_name),
536 archivable: true,
537 unique_id: usize::default(), _ptr: Some(ptr),
539 parent_locked: false,
540 children: Vec::new(),
541 children_cache: HashMap::new(),
542 children_cache_dirty: false,
543
544 ancestry_changed: RBXScriptSignal::new(),
545 attribute_changed: RBXScriptSignal::new(),
546 changed: RBXScriptSignal::new(),
547 child_added: RBXScriptSignal::new(),
548 child_removed: RBXScriptSignal::new(),
549 descendant_added: RBXScriptSignal::new(),
550 descendant_removing: RBXScriptSignal::new(),
551 destroying: RBXScriptSignal::new(),
552
553 attribute_changed_table: EventsTable::default(),
554 property_changed_table: EventsTable::default(),
555
556 attributes: HashMap::default(),
557 tags: HashSet::default()
558 };
559 inst
560 }
561 fn clone(self: &RwLockReadGuard<'_, Self>, lua: &Lua, ptr: &WeakManagedInstance) -> LuaResult<Self> {
562 let mut new_children = Vec::new();
563 for i in self.children.iter() {
564 let inst = i.clone_instance(lua);
565 if inst.is_ok() {
566 new_children.push(unsafe { inst.unwrap_unchecked() });
567 }
568 }
569 Ok(InstanceComponent {
570 archivable: self.archivable,
571 name: self.name.clone(),
572 parent: None,
573 unique_id: 0,
574 children: new_children,
575 children_cache: HashMap::default(),
576 children_cache_dirty: true,
577 _ptr: Some(ptr.clone()),
578 parent_locked: false,
579
580 ancestry_changed: RBXScriptSignal::new(),
581 attribute_changed: RBXScriptSignal::new(),
582 changed: RBXScriptSignal::new(),
583 child_added: RBXScriptSignal::new(),
584 child_removed: RBXScriptSignal::new(),
585 descendant_added: RBXScriptSignal::new(),
586 descendant_removing: RBXScriptSignal::new(),
587 destroying: RBXScriptSignal::new(),
588
589 attribute_changed_table: EventsTable::default(),
590 property_changed_table: EventsTable::default(),
591
592 attributes: self.attributes.clone(),
593 tags: HashSet::default()
594 })
595 }
596
597}
598
599impl InstanceComponent {
600 pub fn get_instance_pointer(self: &RwLockReadGuard<'_, Self>) -> ManagedInstance {
601 unsafe {
602 self._ptr.as_ref().unwrap_unchecked().upgrade().unwrap_unchecked()
603 }
604 }
605 pub fn get_weak_instance_pointer(self: &RwLockReadGuard<'_, Self>) -> WeakManagedInstance {
606 unsafe { self._ptr.as_ref().unwrap_unchecked().clone() }
607 }
608 pub fn lua_get(self: &mut RwLockReadGuard<'_, Self>, lua: &Lua, key: &String) -> LuaResult<LuaValue> {
609 match key.as_str() {
610 "Archivable" => lua_getter!(lua, self.archivable),
611 "ClassName" => IntoLua::into_lua(unsafe {
612 self._ptr.as_ref().unwrap_unchecked()
613 .upgrade().unwrap_unchecked().get_class_name()
614 }, lua),
615 "Name" => lua_getter!(string, lua, self.name),
616 "Parent" => lua_getter!(opt_weak_clone, lua, self.parent),
617
618 "AddTag" => lua_getter!(function, lua,
619 |lua, (this, tag): (ManagedInstance, String)|
620 this.add_tag(lua, tag)
621 ),
622 "ClearAllChildren" => lua_getter!(function, lua,
623 |lua, (this, ): (ManagedInstance, )| {
624 this.clear_all_children(lua)
625 }
626 ),
627 "Clone" => lua_getter!(function, lua,
628 |lua, (this, ): (ManagedInstance, )|
629 this.clone_instance(lua)
630 ),
631 "Destroy" => lua_getter!(function, lua,
632 |lua, (this, ): (ManagedInstance, )| {
633 this.destroy(lua)
634 }
635 ),
636 "FindFirstAncestor" => lua_getter!(function, lua,
637 |_, (this, name): (ManagedInstance, String)|
638 this.find_first_ancestor(name)
639 ),
640 "FindFirstAncestorOfClass" => lua_getter!(function, lua,
641 |_, (this, class): (ManagedInstance, String)|
642 this.find_first_ancestor_of_class(class)
643 ),
644 "FindFirstAncestorWhichIsA" => lua_getter!(function, lua,
645 |_, (this, class): (ManagedInstance, String)|
646 this.find_first_ancestor_which_is_a(class)
647 ),
648 "FindFirstChild" => lua_getter!(function, lua,
649 |_, (this, name, recursive): (ManagedInstance, String, Option<bool>)|
650 this.find_first_child(name, recursive)
651 ),
652 "FindFirstChildOfClass" => lua_getter!(function, lua,
653 |_, (this, class): (ManagedInstance, String)|
654 this.find_first_child_of_class(class)
655 ),
656 "FindFirstChildWhichIsA" => lua_getter!(function, lua,
657 |_, (this, class): (ManagedInstance, String)|
658 this.find_first_ancestor_which_is_a(class)
659 ),
660 "GetActor" => lua_getter!(function, lua,
661 |_, (this,): (ManagedInstance,)|
662 this.get_actor()
663 ),
664 "GetAttribute" => lua_getter!(function, lua,
665 |_, (this, name): (ManagedInstance, String)|
666 this.get_attribute(name)
667 ),
668 "GetAttributeChangedSignal" => lua_getter!(function, lua,
669 |_, (this, attribute): (ManagedInstance, String)| {
670 Ok(this.get_attribute_changed_signal(attribute))
671 }),
672 "GetAttributes" => lua_getter!(function, lua,
673 |lua, (this,): (ManagedInstance,)|
674 this.get_attributes(lua)
675 ),
676 "GetChildren" => lua_getter!(function, lua,
677 |_, (this,): (ManagedInstance,)|
678 this.get_children()
679 ),
680 "GetDebugId" => lua_getter!(function, lua,
681 |_, (this,scope_len): (ManagedInstance,LuaNumber)|
682 this.get_debug_id(scope_len)
683 ),
684 "GetDescendants" => lua_getter!(function, lua,
685 |_, (this,): (ManagedInstance,)|
686 this.get_descendants()
687 ),
688 "GetFullName" => lua_getter!(function, lua,
689 |_, (this,): (ManagedInstance,)|
690 this.get_full_name()
691 ),
692 "GetStyled" => lua_getter!(function, lua,
693 |_, (_this,): (ManagedInstance,)| {
694 Err::<(), LuaError>(LuaError::RuntimeError("todo!(): function not yet implemented".into()))
695 }
696 ),
697 "GetTags" => lua_getter!(function, lua,
698 |_, (this,): (ManagedInstance,)|
699 this.get_tags()
700 ),
701 "HasTag" => lua_getter!(function, lua,
702 |_, (this, tag): (ManagedInstance, String)|
703 this.has_tag(tag)
704 ),
705 "IsAncestorOf" => lua_getter!(function, lua,
706 |_, (this, inst): (ManagedInstance, ManagedInstance)|
707 this.is_ancestor_of(inst)
708 ),
709 "IsDescendantOf" => lua_getter!(function, lua,
710 |_, (this, inst): (ManagedInstance, ManagedInstance)|
711 this.is_descendant_of(inst)
712 ),
713 "RemoveTag" => lua_getter!(function, lua,
714 |lua, (this, tag): (ManagedInstance, String)|
715 this.remove_tag(lua, tag)
716 ),
717 "SetAttribute" => lua_getter!(function, lua,
718 |lua, (this, attribute, value): (ManagedInstance, String, LuaValue)|
719 this.set_attribute(lua, attribute, value)
720 ),
721 "WaitForChild" => lua_getter!(function_async, lua,
722 async |lua, (this, child, timeout): (ManagedInstance, String, Option<LuaNumber>)| {
723 this.wait_for_child(&lua, child, timeout).await
724 }
725 ),
726
727 "AncestryChanged" => lua_getter!(clone, lua, self.ancestry_changed),
728 "AttributeChanged" => lua_getter!(clone, lua, self.attribute_changed),
729 "ChildAdded" => lua_getter!(clone, lua, self.child_added),
730 "ChildRemoved" => lua_getter!(clone, lua, self.child_removed),
731 "DescendantAdded" => lua_getter!(clone, lua, self.descendant_added),
732 "DescendantRemoving" => lua_getter!(clone, lua, self.descendant_removing),
733 "Destroying" => lua_getter!(clone, lua, self.destroying),
734
735 _ => lua_getter!(lua, self.find_first_child(key))
736 }
737 }
738
739 fn remake_cache(self: &mut RwLockReadGuard<'_, Self>) {
740 let inst = self._ptr.as_ref().map(|x| x.upgrade()).flatten().unwrap();
741 let _release = self.guard_release();
742 let mut write = inst.get_instance_component_mut();
743
744 let iter: Vec<(String, WeakManagedInstance)> = write.children.iter()
745 .map(|x| (x.get_name(), x.downgrade()))
746 .collect();
747 write.children_cache.clear();
748 for (name, i) in iter {
749 if write.children_cache.get(&name).is_none() {
750 write.children_cache.insert(name, i);
751 }
752 }
753 }
754 fn find_first_child(self: &mut RwLockReadGuard<'_, Self>, key: &String) -> Option<ManagedInstance> {
755 if self.children_cache_dirty {
756 self.remake_cache();
757 self.children_cache.get(key).map(|x| x.upgrade()).flatten()
758 } else {
759 self.children_cache.get(key).map(|x| x.upgrade()).flatten()
760 }
761 }
762 pub fn emit_property_changed(this: &impl IReadInstanceComponent, lua: &Lua, property: &'static str, value: &LuaValue) -> LuaResult<()> {
763 this.changed.write().fire(lua, (property,))?;
764 this.property_changed_table.get(property)
765 .map(|x| x.write().fire(lua, (value,)))
766 .unwrap_or(Ok(()))
767 }
768 pub fn get_property_changed_signal(self: &mut RwLockReadGuard<'_, Self>, property: String) -> LuaResult<ManagedRBXScriptSignal> {
769 let read = self.property_changed_table.get(&property);
770 if read.is_some() {
771 Ok(read.unwrap().clone())
772 } else {
773 let inst = self._ptr.as_ref().map(|x| x.upgrade()).flatten().unwrap();
774 let _release = self.guard_release();
775
776 let mut write = inst.get_instance_component_mut();
777 let signal = RBXScriptSignal::new();
778 write.property_changed_table.insert(property, signal.clone());
779 Ok(signal)
780 }
781 }
782
783 pub fn lua_set(self: &mut RwLockWriteGuard<'_, Self>, lua: &Lua, key: &String, value: LuaValue) -> LuaResult<()> {
784 match key.as_str() {
785 "Archivable" => {
786 self.archivable = value.as_boolean().ok_or(LuaError::RuntimeError("bad argument to setting Archivable".into()))?;
787 Self::emit_property_changed(self, lua, "Archivable", &value)
788 },
789 "Name" => {
790 self.name = value.as_string_lossy().ok_or(LuaError::RuntimeError("bad argument to setting Name".into()))?;
791 Self::emit_property_changed(self, lua, "Name", &value)
792 },
793 "Parent" => {
794 DynInstance::guard_set_parent(self, lua, FromLua::from_lua(value, lua)?)
795 },
796 _ => Err(LuaError::RuntimeError(format!("can't set property {} on object of type Instance",key.as_str())))
797 }
798 }
799}
800
801impl<T: IInstance, A: Allocator + Clone + Send + Sync> IWeak<T, A> {
802 pub fn cast_to_instance(&self) -> IWeak<DynInstance, A> {
803 let (header_raw, p_raw, alloc) = self.clone().into_inner_with_allocator();
804 let p = p_raw as *mut DynInstance;
805 let header = unsafe { NonNull::new_unchecked(header_raw.as_ptr() as *mut IrcHead<DynInstance>) };
806 IWeak::from_inner_with_allocator((header, p, alloc))
807 }
808}