rwmap 2.0.0__tar.gz → 3.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rwmap-2.0.0/src/rwmap.egg-info → rwmap-3.2.4}/PKG-INFO +1 -1
- {rwmap-2.0.0 → rwmap-3.2.4}/pyproject.toml +1 -1
- {rwmap-2.0.0 → rwmap-3.2.4}/src/rwmap/__init__.py +0 -8
- {rwmap-2.0.0 → rwmap-3.2.4}/src/rwmap/layers.py +6 -0
- {rwmap-2.0.0 → rwmap-3.2.4}/src/rwmap/maps.py +23 -19
- {rwmap-2.0.0 → rwmap-3.2.4}/src/rwmap/objects.py +12 -5
- {rwmap-2.0.0 → rwmap-3.2.4}/src/rwmap/rw/__init__.py +2 -2
- {rwmap-2.0.0 → rwmap-3.2.4}/src/rwmap/rw/factories.py +0 -2
- rwmap-3.2.4/src/rwmap/rw/rwmaps.py +70 -0
- {rwmap-2.0.0 → rwmap-3.2.4}/src/rwmap/rw/triggers.py +1 -51
- {rwmap-2.0.0 → rwmap-3.2.4}/src/rwmap/tiles.py +8 -4
- {rwmap-2.0.0 → rwmap-3.2.4/src/rwmap.egg-info}/PKG-INFO +1 -1
- rwmap-2.0.0/src/rwmap/rw/rwmaps.py +0 -77
- {rwmap-2.0.0 → rwmap-3.2.4}/LICENSE.txt +0 -0
- {rwmap-2.0.0 → rwmap-3.2.4}/README.md +0 -0
- {rwmap-2.0.0 → rwmap-3.2.4}/setup.cfg +0 -0
- {rwmap-2.0.0 → rwmap-3.2.4}/src/rwmap/properties.py +0 -0
- {rwmap-2.0.0 → rwmap-3.2.4}/src/rwmap/rw/units.py +0 -0
- {rwmap-2.0.0 → rwmap-3.2.4}/src/rwmap/templates.py +0 -0
- {rwmap-2.0.0 → rwmap-3.2.4}/src/rwmap.egg-info/SOURCES.txt +0 -0
- {rwmap-2.0.0 → rwmap-3.2.4}/src/rwmap.egg-info/dependency_links.txt +0 -0
- {rwmap-2.0.0 → rwmap-3.2.4}/src/rwmap.egg-info/top_level.txt +0 -0
|
@@ -5,16 +5,8 @@ from .properties import Property
|
|
|
5
5
|
from .tiles import Tile, Tileset
|
|
6
6
|
from .templates import Template, template
|
|
7
7
|
|
|
8
|
-
from .rw import *
|
|
9
|
-
|
|
10
8
|
|
|
11
9
|
__all__ = [
|
|
12
10
|
"Property", "Shape", "Object", "ObjectGroup", "Layer", "Tile", "Tileset", "Map",
|
|
13
11
|
"Template", "template",
|
|
14
|
-
"unit", "UnitSpec",
|
|
15
|
-
"Trigger", "TriggerLayer", "RwMap",
|
|
16
|
-
"map_info", "team_info", "unit_detect", "unit_add", "unit_remove",
|
|
17
|
-
"map_text", "point", "move", "rotate", "change_credits",
|
|
18
|
-
"basic", "objective", "camera_start", "fall", "set_team", "ai_allow_full_use",
|
|
19
|
-
"unit_info",
|
|
20
12
|
]
|
|
@@ -36,6 +36,12 @@ class Layer:
|
|
|
36
36
|
self.properties = properties or []
|
|
37
37
|
self.data = data[:] if data is not None else [0] * (width * height)
|
|
38
38
|
|
|
39
|
+
def property(self, name: str) -> Property:
|
|
40
|
+
try:
|
|
41
|
+
return next(prop for prop in self.properties if prop.name == name)
|
|
42
|
+
except StopIteration:
|
|
43
|
+
raise KeyError(f"Property '{name}' not found")
|
|
44
|
+
|
|
39
45
|
def get_tile(self, key: Tuple[int, int]) -> int:
|
|
40
46
|
x, y = key
|
|
41
47
|
if not (0 <= x < self.width and 0 <= y < self.height):
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import xml.etree.ElementTree as ET
|
|
2
|
-
from typing import List,
|
|
2
|
+
from typing import List, Optional
|
|
3
3
|
import os
|
|
4
4
|
|
|
5
5
|
from .properties import Property
|
|
@@ -8,6 +8,7 @@ from .objects import ObjectGroup
|
|
|
8
8
|
from .layers import Layer
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
|
|
11
12
|
class Map:
|
|
12
13
|
|
|
13
14
|
def __init__(self, path: Optional[str] = None):
|
|
@@ -22,8 +23,8 @@ class Map:
|
|
|
22
23
|
self.nextobjectid: int = 1
|
|
23
24
|
self.properties: List[Property] = []
|
|
24
25
|
self.tilesets: List[Tileset] = []
|
|
25
|
-
self.layers:
|
|
26
|
-
self.objectgroups:
|
|
26
|
+
self.layers: List[Layer] = []
|
|
27
|
+
self.objectgroups: List[ObjectGroup] = []
|
|
27
28
|
if path and os.path.exists(path):
|
|
28
29
|
self.load(path)
|
|
29
30
|
|
|
@@ -44,14 +45,14 @@ class Map:
|
|
|
44
45
|
for prop_elem in props_elem.findall("property"):
|
|
45
46
|
self.properties.append(Property.from_xml(prop_elem))
|
|
46
47
|
self.tilesets = [Tileset.from_xml(ts_elem) for ts_elem in root.findall("tileset")]
|
|
47
|
-
self.layers =
|
|
48
|
+
self.layers = []
|
|
48
49
|
for layer_elem in root.findall("layer"):
|
|
49
50
|
layer = Layer.from_xml(layer_elem)
|
|
50
|
-
self.layers
|
|
51
|
-
self.objectgroups =
|
|
51
|
+
self.layers.append(layer)
|
|
52
|
+
self.objectgroups = []
|
|
52
53
|
for og_elem in root.findall("objectgroup"):
|
|
53
54
|
og = ObjectGroup.from_xml(og_elem)
|
|
54
|
-
self.objectgroups
|
|
55
|
+
self.objectgroups.append(og)
|
|
55
56
|
return self
|
|
56
57
|
|
|
57
58
|
def save(self, path: Optional[str] = None, encoding: str = "utf-8", indent: Optional[int] = None) -> None:
|
|
@@ -74,30 +75,33 @@ class Map:
|
|
|
74
75
|
prop.to_xml(props_elem)
|
|
75
76
|
for ts in self.tilesets:
|
|
76
77
|
root.append(ts.to_xml())
|
|
77
|
-
for layer in self.layers
|
|
78
|
+
for layer in self.layers:
|
|
78
79
|
root.append(layer.to_xml())
|
|
79
|
-
for og in self.objectgroups
|
|
80
|
+
for og in self.objectgroups:
|
|
80
81
|
root.append(og.to_xml())
|
|
81
82
|
if indent is not None:
|
|
82
83
|
ET.indent(root, space=" " * indent)
|
|
83
84
|
tree = ET.ElementTree(root)
|
|
84
85
|
tree.write(out_path, encoding=encoding, xml_declaration=True)
|
|
85
86
|
|
|
87
|
+
def property(self, name: str) -> Property:
|
|
88
|
+
try:
|
|
89
|
+
return next(prop for prop in self.properties if prop.name == name)
|
|
90
|
+
except StopIteration:
|
|
91
|
+
raise KeyError(f"Property '{name}' not found")
|
|
92
|
+
|
|
86
93
|
def layer(self, name: str) -> Layer:
|
|
87
|
-
|
|
94
|
+
try:
|
|
95
|
+
return next((layer for layer in self.layers if layer.name == name))
|
|
96
|
+
except StopIteration:
|
|
88
97
|
raise KeyError(f"Layer '{name}' not found")
|
|
89
|
-
return self.layers[name]
|
|
90
98
|
|
|
91
99
|
def objectgroup(self, name: str) -> ObjectGroup:
|
|
92
|
-
|
|
100
|
+
try:
|
|
101
|
+
return next((og for og in self.objectgroups if og.name == name))
|
|
102
|
+
except StopIteration:
|
|
93
103
|
raise KeyError(f"ObjectGroup '{name}' not found")
|
|
94
|
-
return self.objectgroups[name]
|
|
95
|
-
|
|
96
|
-
def add_objectgroup(self, group: ObjectGroup) -> None:
|
|
97
|
-
self.objectgroups[group.name] = group
|
|
98
104
|
|
|
99
|
-
def remove_objectgroup(self, name: str) -> None:
|
|
100
|
-
self.objectgroups.pop(name, None)
|
|
101
105
|
|
|
102
106
|
def get_tileset_by_gid(self, gid: int) -> Optional[Tileset]:
|
|
103
107
|
for ts in self.tilesets:
|
|
@@ -134,5 +138,5 @@ class Map:
|
|
|
134
138
|
m.tileheight = tile_size
|
|
135
139
|
if layer_names:
|
|
136
140
|
for name in layer_names:
|
|
137
|
-
m.layers
|
|
141
|
+
m.layers.append(Layer(name, width, height))
|
|
138
142
|
return m
|
|
@@ -51,17 +51,18 @@ class Object:
|
|
|
51
51
|
self.text = text
|
|
52
52
|
self.properties = properties or []
|
|
53
53
|
|
|
54
|
+
def property(self, name: str) -> Property:
|
|
55
|
+
try:
|
|
56
|
+
return next(prop for prop in self.properties if prop.name == name)
|
|
57
|
+
except StopIteration:
|
|
58
|
+
raise KeyError(f"Property '{name}' not found")
|
|
59
|
+
|
|
54
60
|
def set(self, **kwargs: Any) -> 'Object':
|
|
55
61
|
for k, v in kwargs.items():
|
|
56
62
|
self.properties = [p for p in self.properties if p.name != k]
|
|
57
63
|
self.properties.append(Property(k, v))
|
|
58
64
|
return self
|
|
59
65
|
|
|
60
|
-
def add_property(self, name: str, value: Any, type: Optional[str] = None) -> 'Object':
|
|
61
|
-
self.properties = [p for p in self.properties if p.name != name]
|
|
62
|
-
self.properties.append(Property(name, value, type))
|
|
63
|
-
return self
|
|
64
|
-
|
|
65
66
|
def copy_xy_from(self, other: 'Object') -> 'Object':
|
|
66
67
|
self.x = other.x
|
|
67
68
|
self.y = other.y
|
|
@@ -178,6 +179,12 @@ class ObjectGroup:
|
|
|
178
179
|
self.offsety = offsety
|
|
179
180
|
self.properties = properties or []
|
|
180
181
|
|
|
182
|
+
def property(self, name: str) -> Property:
|
|
183
|
+
try:
|
|
184
|
+
return next(prop for prop in self.properties if prop.name == name)
|
|
185
|
+
except StopIteration:
|
|
186
|
+
raise KeyError(f"Property '{name}' not found")
|
|
187
|
+
|
|
181
188
|
def add(self, obj: Object) -> 'ObjectGroup':
|
|
182
189
|
self.objects.append(obj)
|
|
183
190
|
return self
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from .rwmaps import RwMap
|
|
2
|
-
from .triggers import Trigger
|
|
2
|
+
from .triggers import Trigger
|
|
3
3
|
from .units import UnitSpec, unit
|
|
4
4
|
from .factories import (
|
|
5
5
|
map_info, team_info, unit_detect, unit_add, unit_remove,
|
|
@@ -10,7 +10,7 @@ from .factories import (
|
|
|
10
10
|
|
|
11
11
|
__all__ = [
|
|
12
12
|
"unit", "UnitSpec",
|
|
13
|
-
"Trigger", "
|
|
13
|
+
"Trigger", "RwMap",
|
|
14
14
|
"map_info", "team_info", "unit_detect", "unit_add", "unit_remove",
|
|
15
15
|
"map_text", "point", "move", "rotate", "change_credits",
|
|
16
16
|
"basic", "objective", "camera_start", "fall", "set_team", "ai_allow_full_use",
|
|
@@ -105,13 +105,11 @@ def unit_add(
|
|
|
105
105
|
|
|
106
106
|
def unit_remove(
|
|
107
107
|
x: float, y: float, width: float, height: float,
|
|
108
|
-
team: int = 0,
|
|
109
108
|
onlyIfEmpty: bool = False,
|
|
110
109
|
name: Optional[str] = None,
|
|
111
110
|
**kwargs
|
|
112
111
|
) -> Trigger:
|
|
113
112
|
obj = Trigger(name=name or f"remove_{x}_{y}", type="unitRemove", x=x, y=y, width=width, height=height)
|
|
114
|
-
obj.set(team=team)
|
|
115
113
|
if onlyIfEmpty:
|
|
116
114
|
obj.set(onlyIfEmpty=True)
|
|
117
115
|
for k, v in kwargs.items():
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from typing import List, Optional, cast
|
|
2
|
+
|
|
3
|
+
from .triggers import Trigger
|
|
4
|
+
from ..objects import Object, ObjectGroup
|
|
5
|
+
from ..layers import Layer
|
|
6
|
+
from ..maps import Map
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class RwMap(Map):
|
|
10
|
+
|
|
11
|
+
def __init__(self, path: Optional[str] = None) -> None:
|
|
12
|
+
super().__init__(path=path)
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def triggers(self) -> List[Trigger]:
|
|
16
|
+
og = self.objectgroup("Triggers")
|
|
17
|
+
if og is None:
|
|
18
|
+
og = ObjectGroup(name="Triggers", objects=[])
|
|
19
|
+
self.objectgroups.append(og)
|
|
20
|
+
return cast(List[Trigger], og.objects)
|
|
21
|
+
|
|
22
|
+
@triggers.setter
|
|
23
|
+
def triggers(self, triggers: List[Trigger]) -> None:
|
|
24
|
+
og = self.objectgroup("Triggers")
|
|
25
|
+
if og is None:
|
|
26
|
+
og = ObjectGroup(
|
|
27
|
+
name="Triggers",
|
|
28
|
+
objects=cast(List[Object], triggers),
|
|
29
|
+
color=None,
|
|
30
|
+
opacity=1.0,
|
|
31
|
+
visible=True,
|
|
32
|
+
offsetx=0.0,
|
|
33
|
+
offsety=0.0,
|
|
34
|
+
properties=None,
|
|
35
|
+
)
|
|
36
|
+
self.objectgroups.append(og)
|
|
37
|
+
else:
|
|
38
|
+
og.objects = cast(List[Object], triggers)
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def ground(self) -> Optional[Layer]:
|
|
42
|
+
return self.layer("Ground")
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def items(self) -> Optional[Layer]:
|
|
46
|
+
return self.layer("Items")
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def units(self) -> Optional[Layer]:
|
|
50
|
+
return self.layer("Units")
|
|
51
|
+
|
|
52
|
+
@classmethod
|
|
53
|
+
def create_empty(
|
|
54
|
+
cls,
|
|
55
|
+
width: int = 256,
|
|
56
|
+
height: int = 256,
|
|
57
|
+
tile_size: int = 20,
|
|
58
|
+
layer_names: Optional[List[str]] = None,
|
|
59
|
+
) -> "RwMap":
|
|
60
|
+
if layer_names is None:
|
|
61
|
+
layer_names = ["Ground", "Items", "Units", "Set"]
|
|
62
|
+
m = cls()
|
|
63
|
+
m.width = width
|
|
64
|
+
m.height = height
|
|
65
|
+
m.tilewidth = tile_size
|
|
66
|
+
m.tileheight = tile_size
|
|
67
|
+
for name in layer_names:
|
|
68
|
+
m.layers.append(Layer(name=name, width=width, height=height))
|
|
69
|
+
_ = m.triggers
|
|
70
|
+
return m
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import xml.etree.ElementTree as ET
|
|
2
1
|
from typing import List, Optional, Union, Any
|
|
3
2
|
|
|
4
3
|
from ..properties import Property
|
|
5
|
-
from ..objects import Shape, Object
|
|
4
|
+
from ..objects import Shape, Object
|
|
6
5
|
from .units import UnitSpec
|
|
7
6
|
|
|
8
7
|
|
|
@@ -65,52 +64,3 @@ class Trigger(Object):
|
|
|
65
64
|
|
|
66
65
|
def all_to_activate(self, value: bool) -> 'Trigger':
|
|
67
66
|
return self.set(allToActivate=value)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
class TriggerLayer(ObjectGroup):
|
|
71
|
-
|
|
72
|
-
def __init__(
|
|
73
|
-
self,
|
|
74
|
-
triggers: Optional[List[Trigger]] = None,
|
|
75
|
-
color: Optional[str] = None,
|
|
76
|
-
opacity: float = 1.0,
|
|
77
|
-
visible: bool = True,
|
|
78
|
-
offsetx: float = 0.0,
|
|
79
|
-
offsety: float = 0.0,
|
|
80
|
-
properties: Optional[List[Property]] = None,
|
|
81
|
-
):
|
|
82
|
-
super().__init__(
|
|
83
|
-
name="Triggers",
|
|
84
|
-
objects=triggers if triggers is not None else [],# type: ignore
|
|
85
|
-
color=color,
|
|
86
|
-
opacity=opacity,
|
|
87
|
-
visible=visible,
|
|
88
|
-
offsetx=offsetx,
|
|
89
|
-
offsety=offsety,
|
|
90
|
-
properties=properties,
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
def add(self, trigger: Trigger) -> 'TriggerLayer':# type: ignore
|
|
94
|
-
super().add(trigger)
|
|
95
|
-
return self
|
|
96
|
-
|
|
97
|
-
def extend(self, triggers: List[Trigger]) -> 'TriggerLayer':# type: ignore
|
|
98
|
-
super().extend(triggers)# type: ignore
|
|
99
|
-
return self
|
|
100
|
-
|
|
101
|
-
@property
|
|
102
|
-
def triggers(self) -> List[Trigger]:
|
|
103
|
-
return self.objects # type: ignore
|
|
104
|
-
|
|
105
|
-
@classmethod
|
|
106
|
-
def from_xml(cls, elem: ET.Element) -> 'TriggerLayer':
|
|
107
|
-
og = ObjectGroup.from_xml(elem)
|
|
108
|
-
return cls(
|
|
109
|
-
triggers=og.objects, # type: ignore
|
|
110
|
-
color=og.color,
|
|
111
|
-
opacity=og.opacity,
|
|
112
|
-
visible=og.visible,
|
|
113
|
-
offsetx=og.offsetx,
|
|
114
|
-
offsety=og.offsety,
|
|
115
|
-
properties=og.properties,
|
|
116
|
-
)
|
|
@@ -26,10 +26,11 @@ class Tile:
|
|
|
26
26
|
self.image_height = image_height
|
|
27
27
|
self.image_trans = image_trans
|
|
28
28
|
|
|
29
|
-
def
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
def property(self, name: str) -> Property:
|
|
30
|
+
try:
|
|
31
|
+
return next(prop for prop in self.properties if prop.name == name)
|
|
32
|
+
except StopIteration:
|
|
33
|
+
raise KeyError(f"Property '{name}' not found")
|
|
33
34
|
|
|
34
35
|
@classmethod
|
|
35
36
|
def from_xml(cls, elem: ET.Element) -> 'Tile':
|
|
@@ -107,6 +108,9 @@ class Tileset:
|
|
|
107
108
|
self.properties = properties or []
|
|
108
109
|
self.tiles: Dict[int, Tile] = {}
|
|
109
110
|
|
|
111
|
+
def property(self, name: str) -> Property | None:
|
|
112
|
+
return next((prop for prop in self.properties if prop.name == name), None)
|
|
113
|
+
|
|
110
114
|
def add_tile(self, tile: Tile) -> 'Tileset':
|
|
111
115
|
self.tiles[tile.id] = tile
|
|
112
116
|
return self
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
from typing import List, Optional
|
|
2
|
-
|
|
3
|
-
from .triggers import TriggerLayer
|
|
4
|
-
from ..layers import Layer
|
|
5
|
-
from ..maps import Map
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class RwMap(Map):
|
|
9
|
-
|
|
10
|
-
def __init__(self, path: Optional[str] = None):
|
|
11
|
-
super().__init__(path)
|
|
12
|
-
self._triggers: Optional[TriggerLayer] = None
|
|
13
|
-
if "Triggers" in self.objectgroups:
|
|
14
|
-
og = self.objectgroups["Triggers"]
|
|
15
|
-
if isinstance(og, TriggerLayer):
|
|
16
|
-
self._triggers = og
|
|
17
|
-
else:
|
|
18
|
-
self._triggers = TriggerLayer(
|
|
19
|
-
triggers=og.objects, # type: ignore
|
|
20
|
-
color=og.color,
|
|
21
|
-
opacity=og.opacity,
|
|
22
|
-
visible=og.visible,
|
|
23
|
-
offsetx=og.offsetx,
|
|
24
|
-
offsety=og.offsety,
|
|
25
|
-
properties=og.properties,
|
|
26
|
-
)
|
|
27
|
-
self.objectgroups["Triggers"] = self._triggers
|
|
28
|
-
|
|
29
|
-
@property
|
|
30
|
-
def triggers(self) -> TriggerLayer:
|
|
31
|
-
if self._triggers is None:
|
|
32
|
-
self._triggers = TriggerLayer()
|
|
33
|
-
self.objectgroups["Triggers"] = self._triggers
|
|
34
|
-
return self._triggers
|
|
35
|
-
|
|
36
|
-
@triggers.setter
|
|
37
|
-
def triggers(self, layer: TriggerLayer) -> None:
|
|
38
|
-
self._triggers = layer
|
|
39
|
-
self.objectgroups["Triggers"] = layer
|
|
40
|
-
|
|
41
|
-
@property
|
|
42
|
-
def ground(self) -> Optional[Layer]:
|
|
43
|
-
return self.layers.get("Ground")
|
|
44
|
-
|
|
45
|
-
@property
|
|
46
|
-
def items(self) -> Optional[Layer]:
|
|
47
|
-
return self.layers.get("Items")
|
|
48
|
-
|
|
49
|
-
@property
|
|
50
|
-
def units(self) -> Optional[Layer]:
|
|
51
|
-
return self.layers.get("Units")
|
|
52
|
-
|
|
53
|
-
@property
|
|
54
|
-
def set_layer(self) -> Optional[Layer]:
|
|
55
|
-
return self.layers.get("Set")
|
|
56
|
-
|
|
57
|
-
@classmethod
|
|
58
|
-
def create_empty(
|
|
59
|
-
cls,
|
|
60
|
-
width: int = 256,
|
|
61
|
-
height: int = 256,
|
|
62
|
-
tile_size: int = 20,
|
|
63
|
-
layer_names: Optional[List[str]] = None
|
|
64
|
-
) -> 'RwMap':
|
|
65
|
-
if layer_names is None:
|
|
66
|
-
layer_names = ["Ground", "Items", "Units", "Set"]
|
|
67
|
-
m = cls()
|
|
68
|
-
m.width = width
|
|
69
|
-
m.height = height
|
|
70
|
-
m.tilewidth = tile_size
|
|
71
|
-
m.tileheight = tile_size
|
|
72
|
-
for name in layer_names:
|
|
73
|
-
m.layers[name] = Layer(name, width, height)
|
|
74
|
-
_ = m.triggers # 触发自动创建
|
|
75
|
-
return m
|
|
76
|
-
|
|
77
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|