tilemap-parser 3.1.7__tar.gz → 3.1.8__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.
Files changed (33) hide show
  1. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/PKG-INFO +1 -1
  2. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/pyproject.toml +1 -1
  3. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser/__init__.py +4 -0
  4. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser/parser/__init__.py +4 -0
  5. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser/parser/map_parse.py +6 -1
  6. tilemap_parser-3.1.8/src/tilemap_parser/parser/node_parse.py +77 -0
  7. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser/runtime/__init__.py +2 -0
  8. tilemap_parser-3.1.8/src/tilemap_parser/runtime/area_node.py +38 -0
  9. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser/runtime/map_loader.py +23 -0
  10. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser.egg-info/PKG-INFO +1 -1
  11. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser.egg-info/SOURCES.txt +2 -0
  12. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/LICENSE +0 -0
  13. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/README.md +0 -0
  14. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/setup.cfg +0 -0
  15. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser/parser/animation.py +0 -0
  16. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser/parser/collision.py +0 -0
  17. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser/parser/collision_loader.py +0 -0
  18. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser/runtime/animation_player.py +0 -0
  19. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser/runtime/collision_cache.py +0 -0
  20. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser/runtime/object_collision.py +0 -0
  21. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser/runtime/renderer.py +0 -0
  22. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser/runtime/tile_collision.py +0 -0
  23. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser/utils/__init__.py +0 -0
  24. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser/utils/geometry.py +0 -0
  25. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser.egg-info/dependency_links.txt +0 -0
  26. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser.egg-info/requires.txt +0 -0
  27. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/src/tilemap_parser.egg-info/top_level.txt +0 -0
  28. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/tests/test_collision.py +0 -0
  29. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/tests/test_geometry.py +0 -0
  30. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/tests/test_map_loader.py +0 -0
  31. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/tests/test_object_collision.py +0 -0
  32. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/tests/test_render_scale.py +0 -0
  33. {tilemap_parser-3.1.7 → tilemap_parser-3.1.8}/tests/test_tile_collision.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tilemap-parser
3
- Version: 3.1.7
3
+ Version: 3.1.8
4
4
  Summary: Standalone parser/loader for tilemap-editor JSON maps, sprite animations, and collision detection runtime.
5
5
  Author: tilemap parser contributors
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tilemap-parser"
7
- version = "3.1.7"
7
+ version = "3.1.8"
8
8
  description = "Standalone parser/loader for tilemap-editor JSON maps, sprite animations, and collision detection runtime."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -9,6 +9,7 @@ __all__ = [
9
9
  "AnimationMarker",
10
10
  "AnimationParseError",
11
11
  "AnimationPlayer",
12
+ "AreaNode",
12
13
  "CapsuleShape",
13
14
  "CharacterCollision",
14
15
  "CircleShape",
@@ -32,6 +33,7 @@ __all__ = [
32
33
  "ParsedLayer",
33
34
  "ParsedMap",
34
35
  "ParsedMeta",
36
+ "ParsedNode",
35
37
  "ParsedObject",
36
38
  "ParsedObjectArea",
37
39
  "ParsedProjectState",
@@ -62,6 +64,8 @@ __all__ = [
62
64
  "parse_map_dict",
63
65
  "parse_map_file",
64
66
  "parse_map_json",
67
+ "parse_nodes_dict",
68
+ "parse_nodes_file",
65
69
  "parse_object_collision",
66
70
  "parse_tileset_collision",
67
71
  "polygon_vs_circle",
@@ -44,6 +44,7 @@ from .map_parse import (
44
44
  parse_map_file,
45
45
  parse_map_json,
46
46
  )
47
+ from .node_parse import ParsedNode, parse_nodes_dict, parse_nodes_file
47
48
 
48
49
  __all__ = [
49
50
  "AnimationClip",
@@ -60,6 +61,7 @@ __all__ = [
60
61
  "ObjectCollisionData",
61
62
  "ObjectCollisionRegionData",
62
63
  "ParsedAutotileGroup",
64
+ "ParsedNode",
63
65
  "ParsedAutotileRule",
64
66
  "ParsedLayer",
65
67
  "ParsedMap",
@@ -82,6 +84,8 @@ __all__ = [
82
84
  "parse_map_dict",
83
85
  "parse_map_file",
84
86
  "parse_map_json",
87
+ "parse_nodes_dict",
88
+ "parse_nodes_file",
85
89
  "parse_object_collision",
86
90
  "parse_tileset_collision",
87
91
  ]
@@ -5,7 +5,10 @@ import re
5
5
  import string
6
6
  from dataclasses import dataclass, field
7
7
  from pathlib import Path
8
- from typing import Any, Dict, List, Optional, Tuple, Union
8
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union
9
+
10
+ if TYPE_CHECKING:
11
+ from .node_parse import ParsedNode
9
12
 
10
13
  JsonDict = Dict[str, Any]
11
14
  Point = Tuple[int, int]
@@ -187,6 +190,8 @@ class ParsedMap:
187
190
  tilesets: List[ParsedTileset]
188
191
  project_state: ParsedProjectState
189
192
  raw: JsonDict
193
+ nodes: List["ParsedNode"] = field(default_factory=list)
194
+ node_groups: List[str] = field(default_factory=list)
190
195
 
191
196
 
192
197
  def _parse_tile(tile_data: JsonDict, ctx: str) -> ParsedTile:
@@ -0,0 +1,77 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from dataclasses import dataclass, field
5
+ from pathlib import Path
6
+ from typing import Any, Dict, List, Optional, Union
7
+
8
+ from .map_parse import (
9
+ JsonDict,
10
+ MapParseError,
11
+ ParsedObjectArea,
12
+ _coerce_bool,
13
+ _coerce_float,
14
+ _coerce_int,
15
+ _optional_dict,
16
+ _require_dict,
17
+ _require_list,
18
+ _require_str,
19
+ _ctx,
20
+ )
21
+
22
+
23
+ @dataclass
24
+ class ParsedNode:
25
+ node_id: str
26
+ name: str
27
+ node_type: str
28
+ area: ParsedObjectArea
29
+ layer_name: str
30
+ properties: JsonDict = field(default_factory=dict)
31
+ group: Optional[str] = None
32
+
33
+
34
+ def _parse_area(raw: Any, ctx: str) -> ParsedObjectArea:
35
+ d = _require_dict(raw, ctx)
36
+ return ParsedObjectArea(
37
+ x=_coerce_int(d.get("x"), f"{ctx}.x"),
38
+ y=_coerce_int(d.get("y"), f"{ctx}.y"),
39
+ w=_coerce_int(d.get("w"), f"{ctx}.w"),
40
+ h=_coerce_int(d.get("h"), f"{ctx}.h"),
41
+ )
42
+
43
+
44
+ def _parse_node(raw: Any, ctx: str) -> ParsedNode:
45
+ d = _require_dict(raw, ctx)
46
+ group_raw = d.get("group")
47
+ group = str(group_raw) if group_raw is not None else None
48
+ return ParsedNode(
49
+ node_id=_require_str(d.get("node_id"), f"{ctx}.node_id"),
50
+ name=_require_str(d.get("name"), f"{ctx}.name"),
51
+ node_type=_require_str(d.get("node_type", "area"), f"{ctx}.node_type"),
52
+ area=_parse_area(d.get("area"), f"{ctx}.area"),
53
+ layer_name=_require_str(d.get("layer_name", ""), f"{ctx}.layer_name"),
54
+ properties=_optional_dict(d.get("properties"), f"{ctx}.properties") or {},
55
+ group=group,
56
+ )
57
+
58
+
59
+ def parse_nodes_dict(root: JsonDict) -> List[ParsedNode]:
60
+ root = _require_dict(root, "root")
61
+ raw_nodes = _require_list(root.get("nodes", []), "root.nodes")
62
+ return [_parse_node(item, f"root.nodes[{i}]") for i, item in enumerate(raw_nodes)]
63
+
64
+
65
+ def parse_nodes_file(path: Union[str, Path]) -> List[ParsedNode]:
66
+ p = Path(path)
67
+ if not p.is_file():
68
+ raise MapParseError(f"Not a file: {p}")
69
+ try:
70
+ text = p.read_text(encoding="utf-8")
71
+ except OSError as e:
72
+ raise MapParseError(f"Cannot read {p}: {e}") from e
73
+ try:
74
+ payload = json.loads(text)
75
+ except json.JSONDecodeError as e:
76
+ raise MapParseError(f"Invalid JSON in {p}: {e}") from e
77
+ return parse_nodes_dict(payload)
@@ -23,9 +23,11 @@ from .object_collision import (
23
23
  check_collision,
24
24
  )
25
25
  from .renderer import LayerRenderStats, TileLayerRenderer
26
+ from .area_node import AreaNode
26
27
 
27
28
  __all__ = [
28
29
  "AnimationPlayer",
30
+ "AreaNode",
29
31
  "CollisionCache",
30
32
  "CollisionHit",
31
33
  "CollisionResult",
@@ -0,0 +1,38 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Optional, Tuple
4
+
5
+ from pygame import Rect
6
+
7
+ from ..parser.node_parse import ParsedNode
8
+
9
+
10
+ class AreaNode:
11
+ def __init__(self, parsed: ParsedNode) -> None:
12
+ self.node_id = parsed.node_id
13
+ self.name = parsed.name
14
+ self.node_type = parsed.node_type
15
+ self._rect = Rect(parsed.area.x, parsed.area.y, parsed.area.w, parsed.area.h)
16
+ self.layer_name = parsed.layer_name
17
+ self.properties = dict(parsed.properties)
18
+ self.group = parsed.group
19
+
20
+ @property
21
+ def rect(self) -> Rect:
22
+ return self._rect
23
+
24
+ @rect.setter
25
+ def rect(self, r: Rect) -> None:
26
+ self._rect = r
27
+
28
+ def contains_point(self, point: Tuple[float, float]) -> bool:
29
+ return self._rect.collidepoint(point)
30
+
31
+ def overlaps_rect(self, other: Rect) -> bool:
32
+ return self._rect.colliderect(other)
33
+
34
+ def __repr__(self) -> str:
35
+ return (
36
+ f"AreaNode(id={self.node_id!r}, name={self.name!r}, "
37
+ f"rect={self._rect}, layer={self.layer_name!r})"
38
+ )
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import json
3
4
  from copy import deepcopy
4
5
  from pathlib import Path
5
6
  from typing import Dict, List, Optional, Tuple, Union
@@ -8,6 +9,7 @@ import pygame
8
9
  from pygame import Rect, Surface
9
10
 
10
11
  from ..parser.map_parse import MapParseError, ParsedLayer, ParsedMap, ParsedTile, parse_map_file
12
+ from ..parser.node_parse import parse_nodes_dict
11
13
 
12
14
  PathLike = Union[str, Path]
13
15
 
@@ -66,6 +68,27 @@ class TilemapData:
66
68
  raise MapParseError(msg) from e
67
69
  surfaces.append(None)
68
70
 
71
+ nodes_name = f"{p.stem}.nodes.json"
72
+ nodes_candidates = [
73
+ map_dir / nodes_name,
74
+ map_dir.parent / "nodes" / nodes_name,
75
+ ]
76
+ if extra_search_base is not None:
77
+ nodes_candidates.append(extra_search_base / "nodes" / nodes_name)
78
+ for nodes_path in nodes_candidates:
79
+ if nodes_path.is_file():
80
+ try:
81
+ nodes_text = nodes_path.read_text(encoding="utf-8")
82
+ nodes_raw = json.loads(nodes_text)
83
+ parsed.nodes = parse_nodes_dict(nodes_raw)
84
+ groups_raw = nodes_raw.get("groups", [])
85
+ if not isinstance(groups_raw, list):
86
+ raise MapParseError("root.groups must be a list")
87
+ parsed.node_groups = groups_raw
88
+ except (json.JSONDecodeError, OSError, MapParseError) as e:
89
+ warnings.append(f"Failed to load nodes: {e}")
90
+ break
91
+
69
92
  return cls(parsed, surfaces, resolved_paths, warnings, map_path=p)
70
93
 
71
94
  def _build_path_index(self) -> None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tilemap-parser
3
- Version: 3.1.7
3
+ Version: 3.1.8
4
4
  Summary: Standalone parser/loader for tilemap-editor JSON maps, sprite animations, and collision detection runtime.
5
5
  Author: tilemap parser contributors
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -12,8 +12,10 @@ src/tilemap_parser/parser/animation.py
12
12
  src/tilemap_parser/parser/collision.py
13
13
  src/tilemap_parser/parser/collision_loader.py
14
14
  src/tilemap_parser/parser/map_parse.py
15
+ src/tilemap_parser/parser/node_parse.py
15
16
  src/tilemap_parser/runtime/__init__.py
16
17
  src/tilemap_parser/runtime/animation_player.py
18
+ src/tilemap_parser/runtime/area_node.py
17
19
  src/tilemap_parser/runtime/collision_cache.py
18
20
  src/tilemap_parser/runtime/map_loader.py
19
21
  src/tilemap_parser/runtime/object_collision.py
File without changes
File without changes
File without changes