Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Bevy Micro LDTK
Manage
Activity
Members
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Model registry
Analyze
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Microhacks
Bevy Micro LDTK
Commits
dfb52c4f
Verified
Commit
dfb52c4f
authored
2 years ago
by
Louis
Browse files
Options
Downloads
Patches
Plain Diff
Add new types for map data
parent
c9df9af3
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/types.rs
+409
-6
409 additions, 6 deletions
src/types.rs
src/utils.rs
+1
-1
1 addition, 1 deletion
src/utils.rs
with
410 additions
and
7 deletions
src/types.rs
+
409
−
6
View file @
dfb52c4f
use
std
::
collections
::
HashMap
;
use
std
::
fmt
::{
Debug
,
Formatter
};
use
std
::
ops
::{
Deref
,
DerefMut
};
use
std
::
path
::
Path
;
use
bevy
::
math
::{
IVec2
,
UVec2
};
use
bevy
::
utils
::
HashMap
;
use
ldtk_rust
::{
LayerInstance
,
Level
,
TileInstance
};
use
bevy
::
math
::{
IVec2
,
Rect
,
UVec2
,
Vec2
};
use
ldtk_rust
::{
EntityInstance
,
FieldInstance
,
LayerInstance
,
Level
,
TileInstance
};
use
num_traits
::
AsPrimitive
;
use
quadtree_rs
::
area
::{
Area
,
AreaBuilder
};
use
quadtree_rs
::
point
::
Point
;
use
quadtree_rs
::
Quadtree
;
use
serde_json
::
Value
;
use
serde
::{
Deserialize
,
Serialize
};
use
serde_json
::{
Map
,
Number
,
Value
};
use
crate
::
utils
::{
Indexer
,
SerdeClone
};
use
crate
::{
get_ldtk_tile_scale
,
px_to_grid
,
MapQuery
};
...
...
@@ -21,7 +23,7 @@ pub struct TileRef<'a> {
}
#[repr(C)]
#[derive(Copy,
Clone,
Ord,
PartialOrd,
Eq,
PartialEq,
Default,
Debug)]
#[derive(
Serialize,
Deserialize,
Copy,
Clone,
Ord,
PartialOrd,
Eq,
PartialEq,
Default,
Debug)]
pub
enum
TileFlip
{
#[default]
None
=
0
,
...
...
@@ -74,7 +76,7 @@ impl<'a> Debug for TileRef<'a> {
}
}
#[derive(Ord,
PartialOrd,
Eq,
PartialEq,
Clone,
Copy,
Hash,
Debug)]
#[derive(
Serialize,
Deserialize,
Ord,
PartialOrd,
Eq,
PartialEq,
Clone,
Copy,
Hash,
Debug)]
pub
struct
SpatialIndex
(
i64
,
i64
);
impl
<
A
,
B
>
From
<
(
A
,
B
)
>
for
SpatialIndex
where
...
...
@@ -316,3 +318,404 @@ impl AsRef<LayerInstance> for LdtkLayer {
&
self
.layer
}
}
#[derive(Serialize,
Deserialize,
Clone,
Debug)]
pub
struct
WorldTile
{
gid
:
usize
,
rotation
:
TileFlip
,
}
impl
From
<&
TileInstance
>
for
WorldTile
{
fn
from
(
value
:
&
TileInstance
)
->
Self
{
Self
{
gid
:
value
.t
.max
(
0
)
as
usize
,
rotation
:
match
value
.f
{
1
=>
TileFlip
::
Horizontal
,
2
=>
TileFlip
::
Vertical
,
3
=>
TileFlip
::
Both
,
_
=>
TileFlip
::
None
,
},
}
}
}
#[derive(Serialize,
Deserialize,
Clone,
Copy,
Debug)]
pub
enum
EntityPosition
{
Point
{
position
:
IVec2
},
Zone
{
position
:
IVec2
,
size
:
IVec2
},
}
#[derive(Serialize,
Deserialize,
Clone,
Debug)]
pub
struct
WorldEntity
{
entity_type
:
String
,
position
:
Rect
,
properties
:
Properties
,
tags
:
Vec
<
String
>
,
colour
:
String
,
}
impl
From
<&
EntityInstance
>
for
WorldEntity
{
fn
from
(
value
:
&
EntityInstance
)
->
Self
{
let
x
=
value
.px
[
0
];
let
y
=
value
.px
[
1
];
Self
{
entity_type
:
value
.identifier
.clone
(),
position
:
Rect
::
from_corners
(
Vec2
::
new
(
x
as
f32
,
y
as
f32
),
Vec2
::
new
((
x
+
value
.width
)
as
f32
,
(
y
+
value
.height
)
as
f32
),
),
properties
:
Properties
::
from
(
&
value
.field_instances
),
tags
:
value
.tags
.clone
(),
colour
:
value
.smart_color
.clone
(),
}
}
}
#[derive(Serialize,
Deserialize,
Clone,
Debug,
Default)]
pub
struct
Properties
(
HashMap
<
String
,
Value
>
);
impl
Deref
for
Properties
{
type
Target
=
HashMap
<
String
,
Value
>
;
fn
deref
(
&
self
)
->
&
Self
::
Target
{
&
self
.0
}
}
impl
DerefMut
for
Properties
{
fn
deref_mut
(
&
mut
self
)
->
&
mut
Self
::
Target
{
&
mut
self
.0
}
}
impl
From
<
HashMap
<
String
,
Value
>>
for
Properties
{
fn
from
(
value
:
HashMap
<
String
,
Value
>
)
->
Self
{
Self
(
value
)
}
}
impl
From
<
Vec
<
FieldInstance
>>
for
Properties
{
fn
from
(
value
:
Vec
<
FieldInstance
>
)
->
Self
{
(
&
value
)
.into
()
}
}
impl
From
<&
Vec
<
FieldInstance
>>
for
Properties
{
fn
from
(
value
:
&
Vec
<
FieldInstance
>
)
->
Self
{
value
.iter
()
.map
(|
field
|
{
(
field
.identifier
.clone
(),
field
.value
.clone
()
.unwrap_or
(
Value
::
Null
),
)
})
.collect
::
<
HashMap
<
String
,
Value
>>
()
.into
()
}
}
fn
convert_map_types
(
map
:
&
Map
<
String
,
Value
>
)
->
HashMap
<
String
,
Value
>
{
map
.iter
()
.map
(|(
name
,
value
)|
(
name
.clone
(),
value
.clone
()))
.collect
()
}
impl
Properties
{
pub
fn
as_string
(
&
self
,
name
:
impl
ToString
)
->
Option
<
String
>
{
self
.get
(
&
name
.to_string
())
.and_then
(|
value
|
match
value
{
Value
::
String
(
value
)
=>
Some
(
format!
(
"{}"
,
value
)),
Value
::
Bool
(
value
)
=>
Some
(
format!
(
"{}"
,
value
)),
Value
::
Number
(
value
)
=>
Some
(
format!
(
"{}"
,
value
)),
_
=>
None
,
})
}
pub
fn
as_number_cast
<
T
>
(
&
self
,
name
:
impl
ToString
)
->
Option
<
T
>
where
T
:
'static
+
Copy
,
f64
:
AsPrimitive
<
T
>
,
{
self
.get
(
&
name
.to_string
())
.and_then
(|
value
|
match
value
{
Value
::
Number
(
number
)
=>
{
let
num
=
number
.as_f64
();
num
.map
(|
val
|
val
.as_
())
}
_
=>
None
,
})
}
pub
fn
as_bool
(
&
self
,
name
:
impl
ToString
)
->
Option
<
bool
>
{
self
.get
(
&
name
.to_string
())
.and_then
(|
value
|
match
value
{
Value
::
Bool
(
value
)
=>
Some
(
*
value
),
_
=>
None
,
})
}
pub
fn
as_vec
(
&
self
,
name
:
impl
ToString
)
->
Option
<&
Vec
<
Value
>>
{
self
.get
(
&
name
.to_string
())
.and_then
(|
value
|
match
value
{
Value
::
Array
(
value
)
=>
Some
(
value
),
_
=>
None
,
})
}
pub
fn
as_vec_owned
(
&
self
,
name
:
impl
ToString
)
->
Option
<
Vec
<
Value
>>
{
self
.get
(
&
name
.to_string
())
.and_then
(|
value
|
match
value
{
Value
::
Array
(
value
)
=>
Some
(
value
.clone
()),
_
=>
None
,
})
}
pub
fn
as_map
(
&
self
,
name
:
impl
ToString
)
->
Option
<&
Map
<
String
,
Value
>>
{
self
.get
(
&
name
.to_string
())
.and_then
(|
value
|
match
value
{
Value
::
Object
(
value
)
=>
Some
(
value
),
_
=>
None
,
})
}
pub
fn
as_map_owned
(
&
self
,
name
:
impl
ToString
)
->
Option
<
Map
<
String
,
Value
>>
{
self
.get
(
&
name
.to_string
())
.and_then
(|
value
|
match
value
{
Value
::
Object
(
value
)
=>
Some
(
value
.clone
()),
_
=>
None
,
})
}
pub
fn
matches
(
&
self
,
name
:
impl
ToString
,
value
:
Value
)
->
bool
{
match
(
self
.0
.get
(
&
name
.to_string
()),
value
)
{
(
Some
(
Value
::
String
(
a
)),
Value
::
String
(
ref
b
))
=>
a
==
b
,
(
Some
(
Value
::
Number
(
a
)),
Value
::
Number
(
ref
b
))
=>
a
==
b
,
(
Some
(
Value
::
Bool
(
a
)),
Value
::
Bool
(
ref
b
))
=>
a
==
b
,
(
Some
(
Value
::
Array
(
a
)),
Value
::
Array
(
ref
b
))
=>
a
==
b
,
(
Some
(
Value
::
Object
(
a
)),
Value
::
Object
(
ref
b
))
=>
a
==
b
,
(
Some
(
Value
::
Null
),
Value
::
Null
)
=>
true
,
_
=>
false
,
}
}
pub
fn
is_null
(
&
self
,
name
:
impl
ToString
)
->
bool
{
match
self
.0
.get
(
&
name
.to_string
())
{
Some
(
Value
::
Null
)
=>
true
,
_
=>
false
,
}
}
pub
fn
is_null_or_undefined
(
&
self
,
name
:
impl
ToString
)
->
bool
{
match
self
.0
.get
(
&
name
.to_string
())
{
None
|
Some
(
Value
::
Null
)
=>
true
,
_
=>
false
,
}
}
pub
fn
is_null_or_falsy
(
&
self
,
name
:
impl
ToString
)
->
bool
{
match
self
.0
.get
(
&
name
.to_string
())
{
None
|
Some
(
Value
::
Null
)
=>
true
,
Some
(
Value
::
Bool
(
value
))
=>
!*
value
,
Some
(
Value
::
String
(
value
))
=>
value
.is_empty
(),
Some
(
Value
::
Number
(
num
))
=>
num
==
&
Number
::
from
(
0
),
Some
(
Value
::
Array
(
value
))
=>
value
.is_empty
(),
Some
(
Value
::
Object
(
value
))
=>
value
.is_empty
(),
}
}
}
#[derive(Serialize,
Deserialize,
Clone,
Debug)]
pub
enum
LayerType
{
Entities
(
Vec
<
WorldEntity
>
),
GidTiles
(
HashMap
<
SpatialIndex
,
WorldTile
>
),
IntTiles
(
Vec
<
usize
>
),
}
fn
infer_tileset_name
(
layer
:
&
LayerInstance
)
->
Option
<
String
>
{
layer
.tileset_rel_path
.as_ref
()
.and_then
(|
path
|
{
Path
::
new
(
path
)
.file_stem
()
.and_then
(|
stem
|
stem
.to_str
())
.map
(
String
::
from
)
})
}
impl
From
<&
LayerInstance
>
for
LayerType
{
fn
from
(
value
:
&
LayerInstance
)
->
Self
{
match
value
.layer_instance_type
.as_str
()
{
"IntGrid"
=>
LayerType
::
IntTiles
(
value
.int_grid_csv
.iter
()
.map
(|
num
|
(
*
num
)
.max
(
0
)
as
usize
)
.collect
(),
),
"Entities"
=>
LayerType
::
Entities
(
value
.entity_instances
.iter
()
.map
(|
entity
|
entity
.into
())
.collect
(),
),
"Tiles"
=>
LayerType
::
GidTiles
(
value
.grid_tiles
.iter
()
.map
(|
tile
|
(
SpatialIndex
(
tile
.px
[
0
],
tile
.px
[
1
]),
tile
.into
()))
.collect
(),
),
"AutoLayer"
=>
LayerType
::
GidTiles
(
value
.auto_layer_tiles
.iter
()
.map
(|
tile
|
(
SpatialIndex
(
tile
.px
[
0
],
tile
.px
[
1
]),
tile
.into
()))
.collect
(),
),
_
=>
{
panic!
(
"Invalid layer type {}"
,
value
.layer_instance_type
.as_str
());
}
}
}
}
#[derive(Serialize,
Deserialize,
Clone,
Debug)]
pub
struct
WorldLayer
{
id
:
String
,
depth
:
usize
,
world_width
:
i64
,
world_height
:
i64
,
tile_width
:
i64
,
tile_height
:
i64
,
layer_data
:
LayerType
,
tileset_name
:
Option
<
String
>
,
}
impl
WorldLayer
{
pub
fn
from_layer
(
depth
:
usize
,
layer
:
&
LayerInstance
)
->
Self
{
let
tile_size
=
get_ldtk_tile_scale
()
as
i64
;
Self
{
depth
,
id
:
layer
.identifier
.clone
(),
tileset_name
:
infer_tileset_name
(
layer
),
world_width
:
layer
.c_wid
*
tile_size
,
world_height
:
layer
.c_hei
*
tile_size
,
tile_width
:
layer
.c_wid
,
tile_height
:
layer
.c_hei
,
layer_data
:
layer
.into
(),
}
}
pub
fn
has_tiles
(
&
self
)
->
bool
{
match
&
self
.layer_data
{
LayerType
::
GidTiles
(
map
)
=>
!
map
.is_empty
(),
_
=>
false
,
}
}
pub
fn
for_each_tile
(
&
self
,
mut
cb
:
impl
FnMut
(
i64
,
i64
,
&
WorldTile
))
{
match
&
self
.layer_data
{
LayerType
::
GidTiles
(
map
)
=>
{
map
.iter
()
.for_each
(|(
pos
,
tile
)|
{
cb
(
pos
.0
,
pos
.1
,
tile
);
});
}
_
=>
{}
}
}
pub
fn
for_each_tile_mut
(
&
mut
self
,
mut
cb
:
impl
FnMut
(
i64
,
i64
,
&
mut
WorldTile
))
{
match
&
mut
self
.layer_data
{
LayerType
::
GidTiles
(
map
)
=>
{
map
.iter_mut
()
.for_each
(|(
pos
,
tile
)|
{
cb
(
pos
.0
,
pos
.1
,
tile
);
});
}
_
=>
{}
}
}
pub
fn
get_z_delta
(
&
self
)
->
f32
{
(
self
.depth
as
f32
)
/
100.0
}
pub
fn
get_tile
(
&
self
,
x
:
impl
AsPrimitive
<
i32
>
,
y
:
impl
AsPrimitive
<
i32
>
,
)
->
Option
<&
WorldTile
>
{
match
&
self
.layer_data
{
LayerType
::
GidTiles
(
map
)
=>
map
.get
(
&
IVec2
::
from
((
x
.as_
(),
y
.as_
()))
.into
()),
_
=>
None
,
}
}
pub
fn
get_tile_mut
(
&
mut
self
,
x
:
impl
AsPrimitive
<
i32
>
,
y
:
impl
AsPrimitive
<
i32
>
,
)
->
Option
<&
mut
WorldTile
>
{
match
&
mut
self
.layer_data
{
LayerType
::
GidTiles
(
map
)
=>
map
.get_mut
(
&
IVec2
::
from
((
x
.as_
(),
y
.as_
()))
.into
()),
_
=>
None
,
}
}
}
#[derive(Serialize,
Deserialize,
Clone,
Debug,
Default)]
pub
struct
WorldData
{
layers
:
Vec
<
WorldLayer
>
,
properties
:
Properties
,
meta
:
Properties
,
}
impl
From
<&
Level
>
for
WorldData
{
fn
from
(
value
:
&
Level
)
->
Self
{
let
mut
properties
:
Properties
=
(
&
value
.field_instances
)
.into
();
let
meta
:
Properties
=
properties
.as_map
(
"meta"
)
.map
(
convert_map_types
)
.unwrap_or_default
()
.into
();
properties
.remove
(
"meta"
);
Self
{
properties
,
meta
,
layers
:
value
.layer_instances
.as_ref
()
.map
(|
insts
|
{
insts
.iter
()
.enumerate
()
.map
(|(
idx
,
layer
)|
WorldLayer
::
from_layer
(
idx
,
layer
))
.collect
()
})
.unwrap_or_default
(),
}
}
}
#[derive(Serialize,
Deserialize,
Clone,
Debug)]
pub
struct
LayerSet
(
pub
Vec
<
WorldLayer
>
);
trait
AsWorldLayer
{
fn
as_world_layer
(
&
self
,
depth
:
usize
)
->
WorldLayer
;
}
// impl<T, V> From<V> for LayerSet
// where
// T: AsWorldLayer,
// V: Iterator<Item = T>,
// {
// fn from(value: V) -> Self {
// Self(value.enumerate().map(T::as_world_layer).collect())
// }
// }
// impl<T> From<T> for WorldData
// where
// T: Into<LayerSet>,
// {
// fn from(value: T) -> Self {
// let layers = value.into();
// WorldData {
// layers: layers.0,
// ..Default::default()
// }
// }
// }
This diff is collapsed.
Click to expand it.
src/utils.rs
+
1
−
1
View file @
dfb52c4f
...
...
@@ -36,7 +36,7 @@ pub fn entity_centre(level_height: i64, entity: &EntityInstance) -> (f32, f32) {
#[derive(Component)]
pub
struct
WorldLinked
;
#[derive(Default,
Resource,
Clone)]
#[derive(Default,
Resource,
Clone
,
Debug
)]
pub
struct
ActiveLevel
{
pub
map
:
String
,
pub
dirty
:
bool
,
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment