ecs: Resource -> Global
parent
05e8bb7d1f
commit
bf378bd288
|
@ -8,8 +8,8 @@ rust_library(
|
||||||
"src/borrow.rs",
|
"src/borrow.rs",
|
||||||
"src/component.rs",
|
"src/component.rs",
|
||||||
"src/componentmap.rs",
|
"src/componentmap.rs",
|
||||||
|
"src/globalmap.rs",
|
||||||
"src/entity.rs",
|
"src/entity.rs",
|
||||||
"src/resourcemap.rs",
|
|
||||||
"src/system.rs",
|
"src/system.rs",
|
||||||
"src/world.rs",
|
"src/world.rs",
|
||||||
],
|
],
|
||||||
|
|
|
@ -8,9 +8,9 @@ pub fn component_id<T: Component>() -> ID {
|
||||||
std::any::TypeId::of::<T>()
|
std::any::TypeId::of::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Resource: 'static {
|
pub trait Global: 'static {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resource_id<T: Resource>() -> ID {
|
pub fn global_id<T: Global>() -> ID {
|
||||||
std::any::TypeId::of::<T>()
|
std::any::TypeId::of::<T>()
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,13 @@ use std::ops::{Deref, DerefMut};
|
||||||
use crate::component;
|
use crate::component;
|
||||||
use crate::borrow;
|
use crate::borrow;
|
||||||
|
|
||||||
struct ResourceMapEntry {
|
struct GlobalMapEntry {
|
||||||
resource: Box<dyn component::Resource>,
|
global: Box<dyn component::Global>,
|
||||||
borrow: Cell<borrow::Flag>,
|
borrow: Cell<borrow::Flag>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ResourceMap {
|
pub struct GlobalMap {
|
||||||
value: UnsafeCell<BTreeMap<component::ID, ResourceMapEntry>>,
|
value: UnsafeCell<BTreeMap<component::ID, GlobalMapEntry>>,
|
||||||
borrow: Cell<borrow::Flag>,
|
borrow: Cell<borrow::Flag>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ impl AccessError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResourceMap {
|
impl GlobalMap {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: UnsafeCell::new(BTreeMap::new()),
|
value: UnsafeCell::new(BTreeMap::new()),
|
||||||
|
@ -32,78 +32,78 @@ impl ResourceMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get<'a, T: component::Resource>(&'a self) -> Result<ResourceRef<'a, T>, AccessError> {
|
pub fn get<'a, T: component::Global>(&'a self) -> Result<GlobalRef<'a, T>, AccessError> {
|
||||||
match borrow::RefMut::new(&self.borrow) {
|
match borrow::RefMut::new(&self.borrow) {
|
||||||
None => Err(AccessError::concurrent()),
|
None => Err(AccessError::concurrent()),
|
||||||
Some(b) => {
|
Some(b) => {
|
||||||
let map = self.value.get();
|
let map = self.value.get();
|
||||||
unsafe {
|
unsafe {
|
||||||
match (*map).get(&component::resource_id::<T>()) {
|
match (*map).get(&component::global_id::<T>()) {
|
||||||
Some(entry) => {
|
Some(entry) => {
|
||||||
let val = &entry.resource;
|
let val = &entry.global;
|
||||||
match borrow::Ref::new(&entry.borrow) {
|
match borrow::Ref::new(&entry.borrow) {
|
||||||
None => Err(AccessError::concurrent()),
|
None => Err(AccessError::concurrent()),
|
||||||
Some(b2) => {
|
Some(b2) => {
|
||||||
let val = val.as_ref();
|
let val = val.as_ref();
|
||||||
let val = & *(val as *const (dyn component::Resource) as *const T);
|
let val = & *(val as *const (dyn component::Global) as *const T);
|
||||||
drop(b);
|
drop(b);
|
||||||
Ok(ResourceRef { val, borrow: Some(b2) })
|
Ok(GlobalRef { val, borrow: Some(b2) })
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => Err(AccessError("resource absent from world".to_string())),
|
None => Err(AccessError("global absent from world".to_string())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_mut<'a, T: component::Resource>(&'a self) -> Result<ResourceRefMut<'a, T>, AccessError> {
|
pub fn get_mut<'a, T: component::Global>(&'a self) -> Result<GlobalRefMut<'a, T>, AccessError> {
|
||||||
match borrow::RefMut::new(&self.borrow) {
|
match borrow::RefMut::new(&self.borrow) {
|
||||||
None => Err(AccessError::concurrent()),
|
None => Err(AccessError::concurrent()),
|
||||||
Some(b) => {
|
Some(b) => {
|
||||||
let map = self.value.get();
|
let map = self.value.get();
|
||||||
unsafe {
|
unsafe {
|
||||||
match (*map).get_mut(&component::resource_id::<T>()) {
|
match (*map).get_mut(&component::global_id::<T>()) {
|
||||||
Some(entry) => {
|
Some(entry) => {
|
||||||
let val = &mut entry.resource;
|
let val = &mut entry.global;
|
||||||
match borrow::RefMut::new(&entry.borrow) {
|
match borrow::RefMut::new(&entry.borrow) {
|
||||||
None => Err(AccessError::concurrent()),
|
None => Err(AccessError::concurrent()),
|
||||||
Some(b2) => {
|
Some(b2) => {
|
||||||
let val = val.as_mut();
|
let val = val.as_mut();
|
||||||
let val = &mut *(val as *mut (dyn component::Resource) as *mut T);
|
let val = &mut *(val as *mut (dyn component::Global) as *mut T);
|
||||||
drop(b);
|
drop(b);
|
||||||
Ok(ResourceRefMut { val, borrow: Some(b2) })
|
Ok(GlobalRefMut { val, borrow: Some(b2) })
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => Err(AccessError("resource absent from world".to_string())),
|
None => Err(AccessError("global absent from world".to_string())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set<'a, T: component::Resource>(&'a self, r: T) -> Result<(), AccessError> {
|
pub fn set<'a, T: component::Global>(&'a self, r: T) -> Result<(), AccessError> {
|
||||||
match borrow::RefMut::new(&self.borrow) {
|
match borrow::RefMut::new(&self.borrow) {
|
||||||
None => Err(AccessError::concurrent()),
|
None => Err(AccessError::concurrent()),
|
||||||
Some(b) => {
|
Some(b) => {
|
||||||
let map = self.value.get();
|
let map = self.value.get();
|
||||||
let rid = component::resource_id::<T>();
|
let rid = component::global_id::<T>();
|
||||||
unsafe {
|
unsafe {
|
||||||
match (*map).get_mut(&rid) {
|
match (*map).get_mut(&rid) {
|
||||||
Some(entry) => {
|
Some(entry) => {
|
||||||
match borrow::RefMut::new(&entry.borrow) {
|
match borrow::RefMut::new(&entry.borrow) {
|
||||||
None => { return Err(AccessError::concurrent()); },
|
None => { return Err(AccessError::concurrent()); },
|
||||||
Some(b2) => {
|
Some(b2) => {
|
||||||
entry.resource = Box::new(r);
|
entry.global = Box::new(r);
|
||||||
drop(b2);
|
drop(b2);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
(*map).insert(rid, ResourceMapEntry {
|
(*map).insert(rid, GlobalMapEntry {
|
||||||
resource: Box::new(r),
|
global: Box::new(r),
|
||||||
borrow: Cell::new(borrow::UNUSED),
|
borrow: Cell::new(borrow::UNUSED),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -116,12 +116,12 @@ impl ResourceMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ResourceRef<'a, T: component::Resource> {
|
pub struct GlobalRef<'a, T: component::Global> {
|
||||||
val: *const T,
|
val: *const T,
|
||||||
borrow: Option<borrow::Ref<'a>>,
|
borrow: Option<borrow::Ref<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: component::Resource> Deref for ResourceRef<'a, T> {
|
impl<'a, T: component::Global> Deref for GlobalRef<'a, T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
|
@ -131,24 +131,24 @@ impl<'a, T: component::Resource> Deref for ResourceRef<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a, T: component::Resource> Drop for ResourceRef<'a, T> {
|
impl <'a, T: component::Global> Drop for GlobalRef<'a, T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.borrow = None;
|
self.borrow = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ResourceRefMut<'a, T: component::Resource> {
|
pub struct GlobalRefMut<'a, T: component::Global> {
|
||||||
val: *mut T,
|
val: *mut T,
|
||||||
borrow: Option<borrow::RefMut<'a>>,
|
borrow: Option<borrow::RefMut<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a, T: component::Resource> Drop for ResourceRefMut<'a, T> {
|
impl <'a, T: component::Global> Drop for GlobalRefMut<'a, T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.borrow = None;
|
self.borrow = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a, T: component::Resource> Deref for ResourceRefMut<'a, T> {
|
impl <'a, T: component::Global> Deref for GlobalRefMut<'a, T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -157,7 +157,7 @@ impl <'a, T: component::Resource> Deref for ResourceRefMut<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a, T: component::Resource> DerefMut for ResourceRefMut<'a, T> {
|
impl <'a, T: component::Global> DerefMut for GlobalRefMut<'a, T> {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
unsafe {
|
unsafe {
|
||||||
&mut(*self.val)
|
&mut(*self.val)
|
|
@ -2,17 +2,17 @@ pub mod borrow;
|
||||||
pub mod component;
|
pub mod component;
|
||||||
pub mod componentmap;
|
pub mod componentmap;
|
||||||
pub mod entity;
|
pub mod entity;
|
||||||
pub mod resourcemap;
|
pub mod globalmap;
|
||||||
pub mod system;
|
pub mod system;
|
||||||
pub mod world;
|
pub mod world;
|
||||||
|
|
||||||
pub use component::Component as Component;
|
pub use component::Component as Component;
|
||||||
pub use component::Resource as Resource;
|
pub use component::Global as Global;
|
||||||
pub use world::World as World;
|
pub use world::World as World;
|
||||||
pub use world::ReadComponent as ReadComponent;
|
pub use world::ReadComponent as ReadComponent;
|
||||||
pub use world::ReadWriteComponent as ReadWriteComponent;
|
pub use world::ReadWriteComponent as ReadWriteComponent;
|
||||||
pub use world::ReadResource as ReadResource;
|
pub use world::ReadGlobal as ReadGlobal;
|
||||||
pub use world::ReadWriteResource as ReadWriteResource;
|
pub use world::ReadWriteGlobal as ReadWriteGlobal;
|
||||||
pub use system::System as System;
|
pub use system::System as System;
|
||||||
pub use system::Join as Join;
|
pub use system::Join as Join;
|
||||||
pub use system::Processor as Processor;
|
pub use system::Processor as Processor;
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
world::{
|
world::{
|
||||||
ReadComponent, ReadComponentIter,
|
ReadComponent, ReadComponentIter,
|
||||||
ReadWriteComponent, ReadWriteComponentIter,
|
ReadWriteComponent, ReadWriteComponentIter,
|
||||||
ReadResource, ReadWriteResource,
|
ReadGlobal, ReadWriteGlobal,
|
||||||
World,
|
World,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -69,15 +69,15 @@ impl<'a, T: component::Component> AccessComponent<'a> for ReadWriteComponent<'a,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: component::Resource> Access<'a> for ReadResource<'a, T> {
|
impl<'a, T: component::Global> Access<'a> for ReadGlobal<'a, T> {
|
||||||
fn fetch(world: &'a World) -> Self {
|
fn fetch(world: &'a World) -> Self {
|
||||||
world.resource()
|
world.global()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: component::Resource> Access<'a> for ReadWriteResource<'a, T> {
|
impl<'a, T: component::Global> Access<'a> for ReadWriteGlobal<'a, T> {
|
||||||
fn fetch(world: &'a World) -> Self {
|
fn fetch(world: &'a World) -> Self {
|
||||||
world.resource_mut()
|
world.global_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,21 +197,21 @@ impl <'a, J: Join<'a>> Iterator for JoinIter<'a, J> {
|
||||||
mod test {
|
mod test {
|
||||||
use crate::{
|
use crate::{
|
||||||
component::Component,
|
component::Component,
|
||||||
component::Resource,
|
component::Global,
|
||||||
system,
|
system,
|
||||||
system::Join,
|
system::Join,
|
||||||
world::{ReadComponent, ReadWriteComponent, ReadResource, ReadWriteResource, World},
|
world::{ReadComponent, ReadWriteComponent, ReadGlobal, ReadWriteGlobal, World},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone,Debug,Default)]
|
#[derive(Clone,Debug,Default)]
|
||||||
struct Delta(f32);
|
struct Delta(f32);
|
||||||
impl Resource for Delta {}
|
impl Global for Delta {}
|
||||||
|
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
struct PhysicsStatus {
|
struct PhysicsStatus {
|
||||||
object_count: u64,
|
object_count: u64,
|
||||||
}
|
}
|
||||||
impl Resource for PhysicsStatus {}
|
impl Global for PhysicsStatus {}
|
||||||
|
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
struct Position {
|
struct Position {
|
||||||
|
@ -233,8 +233,8 @@ mod test {
|
||||||
impl<'a> system::System<'a> for Physics {
|
impl<'a> system::System<'a> for Physics {
|
||||||
type SystemData = ( ReadWriteComponent<'a, Position>
|
type SystemData = ( ReadWriteComponent<'a, Position>
|
||||||
, ReadComponent<'a, Velocity>
|
, ReadComponent<'a, Velocity>
|
||||||
, ReadResource<'a, Delta>
|
, ReadGlobal<'a, Delta>
|
||||||
, ReadWriteResource<'a, PhysicsStatus>);
|
, ReadWriteGlobal<'a, PhysicsStatus>);
|
||||||
|
|
||||||
fn run(&mut self, (pos, vel, delta, status): Self::SystemData) {
|
fn run(&mut self, (pos, vel, delta, status): Self::SystemData) {
|
||||||
let d = delta.get();
|
let d = delta.get();
|
||||||
|
@ -254,8 +254,8 @@ mod test {
|
||||||
let mut world = World::new();
|
let mut world = World::new();
|
||||||
world.new_entity().with(Velocity { x: 0.0, y: 0.0, z: 1.0 }).with(Position { x: 1.0, y: 2.0, z: 3.0 }).build();
|
world.new_entity().with(Velocity { x: 0.0, y: 0.0, z: 1.0 }).with(Position { x: 1.0, y: 2.0, z: 3.0 }).build();
|
||||||
world.new_entity().with(Velocity { x: 0.0, y: 0.0, z: 2.0 }).with(Position { x: 4.0, y: 5.0, z: 6.0 }).build();
|
world.new_entity().with(Velocity { x: 0.0, y: 0.0, z: 2.0 }).with(Position { x: 4.0, y: 5.0, z: 6.0 }).build();
|
||||||
world.set_resource(Delta(1.0));
|
world.set_global(Delta(1.0));
|
||||||
world.set_resource(PhysicsStatus { object_count: 0u64 });
|
world.set_global(PhysicsStatus { object_count: 0u64 });
|
||||||
|
|
||||||
let mut p = system::Processor {
|
let mut p = system::Processor {
|
||||||
world: &world,
|
world: &world,
|
||||||
|
@ -267,9 +267,9 @@ mod test {
|
||||||
assert_eq!(vec![3.0, 6.0], positions.iter().map(|(_, el)| el.z).collect::<Vec<f32>>());
|
assert_eq!(vec![3.0, 6.0], positions.iter().map(|(_, el)| el.z).collect::<Vec<f32>>());
|
||||||
p.run();
|
p.run();
|
||||||
assert_eq!(vec![4.0, 8.0], positions.iter().map(|(_, el)| el.z).collect::<Vec<f32>>());
|
assert_eq!(vec![4.0, 8.0], positions.iter().map(|(_, el)| el.z).collect::<Vec<f32>>());
|
||||||
world.set_resource(Delta(2.0));
|
world.set_global(Delta(2.0));
|
||||||
p.run();
|
p.run();
|
||||||
assert_eq!(vec![6.0, 12.0], positions.iter().map(|(_, el)| el.z).collect::<Vec<f32>>());
|
assert_eq!(vec![6.0, 12.0], positions.iter().map(|(_, el)| el.z).collect::<Vec<f32>>());
|
||||||
assert_eq!(2, world.resource::<PhysicsStatus>().get().object_count);
|
assert_eq!(2, world.global::<PhysicsStatus>().get().object_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,10 @@ use crate::componentmap::{
|
||||||
ComponentMapIter,
|
ComponentMapIter,
|
||||||
ComponentMapIterMut,
|
ComponentMapIterMut,
|
||||||
};
|
};
|
||||||
use crate::resourcemap::{
|
use crate::globalmap::{
|
||||||
ResourceMap,
|
GlobalMap,
|
||||||
ResourceRef,
|
GlobalRef,
|
||||||
ResourceRefMut,
|
GlobalRefMut,
|
||||||
};
|
};
|
||||||
use crate::entity;
|
use crate::entity;
|
||||||
use crate::component;
|
use crate::component;
|
||||||
|
@ -91,31 +91,31 @@ impl <'a, T: component::Component> Iterator for ReadWriteComponentIter<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ReadResource<'a, T: component::Resource> {
|
pub struct ReadGlobal<'a, T: component::Global> {
|
||||||
world: &'a World,
|
world: &'a World,
|
||||||
phantom: PhantomData<&'a T>,
|
phantom: PhantomData<&'a T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: component::Resource> ReadResource<'a, T> {
|
impl<'a, T: component::Global> ReadGlobal<'a, T> {
|
||||||
pub fn get(&self) -> ResourceRef<'a, T> {
|
pub fn get(&self) -> GlobalRef<'a, T> {
|
||||||
self.world.resources.get::<T>().unwrap()
|
self.world.globals.get::<T>().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ReadWriteResource<'a, T: component::Resource> {
|
pub struct ReadWriteGlobal<'a, T: component::Global> {
|
||||||
world: &'a World,
|
world: &'a World,
|
||||||
phantom: PhantomData<&'a T>,
|
phantom: PhantomData<&'a T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: component::Resource> ReadWriteResource<'a, T> {
|
impl<'a, T: component::Global> ReadWriteGlobal<'a, T> {
|
||||||
pub fn get(&self) -> ResourceRefMut<'a, T> {
|
pub fn get(&self) -> GlobalRefMut<'a, T> {
|
||||||
self.world.resources.get_mut::<T>().unwrap()
|
self.world.globals.get_mut::<T>().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct World {
|
pub struct World {
|
||||||
components: BTreeMap<component::ID, ComponentMap>,
|
components: BTreeMap<component::ID, ComponentMap>,
|
||||||
resources: ResourceMap,
|
globals: GlobalMap,
|
||||||
next_id: entity::ID,
|
next_id: entity::ID,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ impl World {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
components: BTreeMap::new(),
|
components: BTreeMap::new(),
|
||||||
resources: ResourceMap::new(),
|
globals: GlobalMap::new(),
|
||||||
next_id: 1u64,
|
next_id: 1u64,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,22 +158,22 @@ impl World {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resource<'a, T: component::Resource>(&'a self) -> ReadResource<'a, T> {
|
pub fn global<'a, T: component::Global>(&'a self) -> ReadGlobal<'a, T> {
|
||||||
ReadResource {
|
ReadGlobal {
|
||||||
world: self,
|
world: self,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resource_mut<'a, T: component::Resource>(&'a self) -> ReadWriteResource<'a, T> {
|
pub fn global_mut<'a, T: component::Global>(&'a self) -> ReadWriteGlobal<'a, T> {
|
||||||
ReadWriteResource {
|
ReadWriteGlobal {
|
||||||
world: self,
|
world: self,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_resource<T: component::Resource>(&self, r: T) {
|
pub fn set_global<T: component::Global>(&self, r: T) {
|
||||||
self.resources.set(r).unwrap();
|
self.globals.set(r).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue