yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
custom_object.h
Go to the documentation of this file.
1#ifndef YAZE_ZELDA3_DUNGEON_CUSTOM_OBJECT_H_
2#define YAZE_ZELDA3_DUNGEON_CUSTOM_OBJECT_H_
3
4#include <cstdint>
5#include <memory>
6#include <string>
7#include <unordered_map>
8#include <vector>
9
10#include "absl/status/status.h"
11#include "absl/status/statusor.h"
13
14namespace yaze {
15namespace zelda3 {
16
33 struct TileMapEntry {
34 int rel_x;
35 int rel_y;
36 uint16_t tile_data; // vhopppcc cccccccc
37 };
38
39 struct BoundingBox {
40 int min_x = 0;
41 int min_y = 0;
42 int max_x = 0;
43 int max_y = 0;
44 int width() const { return (max_x - min_x) + 1; }
45 int height() const { return (max_y - min_y) + 1; }
46 };
47
48 std::vector<TileMapEntry> tiles;
49
50 bool IsEmpty() const { return tiles.empty(); }
51
52 // Compute the bounding box from all tile entries.
53 // If tiles is empty, returns the default-initialized box (min/max=0).
55 if (tiles.empty())
56 return {};
57 BoundingBox bb;
58 bb.min_x = tiles[0].rel_x;
59 bb.max_x = tiles[0].rel_x;
60 bb.min_y = tiles[0].rel_y;
61 bb.max_y = tiles[0].rel_y;
62 for (size_t i = 1; i < tiles.size(); ++i) {
63 if (tiles[i].rel_x < bb.min_x)
64 bb.min_x = tiles[i].rel_x;
65 if (tiles[i].rel_x > bb.max_x)
66 bb.max_x = tiles[i].rel_x;
67 if (tiles[i].rel_y < bb.min_y)
68 bb.min_y = tiles[i].rel_y;
69 if (tiles[i].rel_y > bb.max_y)
70 bb.max_y = tiles[i].rel_y;
71 }
72 return bb;
73 }
74};
75
80 public:
81 struct State {
82 std::string base_path;
83 std::unordered_map<int, std::vector<std::string>> custom_file_map;
84 };
85
86 static CustomObjectManager& Get();
87
88 // Initialize with the full path to the custom objects folder
89 // e.g., "/path/to/project/Dungeons/Objects/Data"
90 void Initialize(const std::string& custom_objects_folder);
91
92 // Override object/subtype filename mapping from project config.
94 const std::unordered_map<int, std::vector<std::string>>& map);
95 void ClearObjectFileMap();
96 bool HasCustomFileMap() const { return !custom_file_map_.empty(); }
97
98 // Load a custom object from a binary file
99 absl::StatusOr<std::shared_ptr<CustomObject>> LoadObject(
100 const std::string& filename);
101
102 // Get an object by ID/Subtype mapping (0x31 or 0x32)
103 // Subtype index maps to the .ObjOffset table
104 absl::StatusOr<std::shared_ptr<CustomObject>> GetObjectInternal(int object_id,
105 int subtype);
106
107 // Get number of subtypes for a custom object ID
108 int GetSubtypeCount(int object_id) const;
109
110 // Reload all cached objects (useful for editor)
111 void ReloadAll();
112
113 // Register a new custom object file for an object_id at runtime
114 void AddObjectFile(int object_id, const std::string& filename);
115
116 // Get the resolved file list for an object_id (empty if none)
117 std::vector<std::string> GetEffectiveFileList(int object_id) const;
118
119 // Accessors for tile editor write-back
120 const std::string& GetBasePath() const { return base_path_; }
121 std::string ResolveFilename(int object_id, int subtype) const;
122
123 // Snapshot/restore helpers for scoped CLI/runtime feature application.
124 State SnapshotState() const;
125 void RestoreState(const State& state);
126
127 private:
129
130 absl::StatusOr<CustomObject> ParseBinaryData(
131 const std::vector<uint8_t>& data);
132 const std::vector<std::string>* ResolveFileList(int object_id) const;
133
134 std::string base_path_;
135 std::unordered_map<std::string, std::shared_ptr<CustomObject>> cache_;
136 std::unordered_map<int, std::vector<std::string>> custom_file_map_;
137
138 // Mapping from subtype index to filename for ID 0x31
139 static const std::vector<std::string> kSubtype1Filenames;
140 // Mapping from subtype index to filename for ID 0x32
141 static const std::vector<std::string> kSubtype2Filenames;
142};
143
144} // namespace zelda3
145} // namespace yaze
146
147#endif // YAZE_ZELDA3_DUNGEON_CUSTOM_OBJECT_H_
Manages loading and caching of custom object binary files.
int GetSubtypeCount(int object_id) const
void RestoreState(const State &state)
const std::string & GetBasePath() const
absl::StatusOr< CustomObject > ParseBinaryData(const std::vector< uint8_t > &data)
void SetObjectFileMap(const std::unordered_map< int, std::vector< std::string > > &map)
static CustomObjectManager & Get()
absl::StatusOr< std::shared_ptr< CustomObject > > LoadObject(const std::string &filename)
void AddObjectFile(int object_id, const std::string &filename)
absl::StatusOr< std::shared_ptr< CustomObject > > GetObjectInternal(int object_id, int subtype)
static const std::vector< std::string > kSubtype2Filenames
void Initialize(const std::string &custom_objects_folder)
std::unordered_map< std::string, std::shared_ptr< CustomObject > > cache_
const std::vector< std::string > * ResolveFileList(int object_id) const
std::unordered_map< int, std::vector< std::string > > custom_file_map_
std::string ResolveFilename(int object_id, int subtype) const
static const std::vector< std::string > kSubtype1Filenames
std::vector< std::string > GetEffectiveFileList(int object_id) const
std::unordered_map< int, std::vector< std::string > > custom_file_map
Represents a decoded custom object (from binary format)
BoundingBox GetBoundingBox() const
std::vector< TileMapEntry > tiles