Skip to content

Commit 865865f

Browse files
committed
Reorganize, confirm maps freeing
1 parent 113e392 commit 865865f

7 files changed

Lines changed: 94 additions & 42 deletions

File tree

src/terrain_3d.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,8 +1206,8 @@ void Terrain3D::_bind_methods() {
12061206
ClassDB::bind_method(D_METHOD("set_color_compress_mode", "compress_mode"), &Terrain3D::set_color_compress_mode);
12071207
ClassDB::bind_method(D_METHOD("get_color_compress_mode"), &Terrain3D::get_color_compress_mode);
12081208
ClassDB::bind_method(D_METHOD("get_color_image_compress_mode"), &Terrain3D::get_color_image_compress_mode);
1209-
ClassDB::bind_method(D_METHOD("set_free_uncompressed_color_maps"), &Terrain3D::set_free_uncompressed_color_maps);
1210-
ClassDB::bind_method(D_METHOD("get_free_uncompressed_color_maps"), &Terrain3D::get_free_uncompressed_color_maps);
1209+
ClassDB::bind_method(D_METHOD("set_free_color_map"), &Terrain3D::set_free_color_map);
1210+
ClassDB::bind_method(D_METHOD("get_free_color_map"), &Terrain3D::get_free_color_map);
12111211
ClassDB::bind_method(D_METHOD("set_label_distance", "distance"), &Terrain3D::set_label_distance);
12121212
ClassDB::bind_method(D_METHOD("get_label_distance"), &Terrain3D::get_label_distance);
12131213
ClassDB::bind_method(D_METHOD("set_label_size", "size"), &Terrain3D::set_label_size);
@@ -1339,7 +1339,7 @@ void Terrain3D::_bind_methods() {
13391339
ADD_SUBGROUP("Advanced", "");
13401340
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "save_16_bit"), "set_save_16_bit", "get_save_16_bit");
13411341
ADD_PROPERTY(PropertyInfo(Variant::INT, "color_compress_mode", PROPERTY_HINT_ENUM, "None,S3TC (LQ Desktop),BPTC (HQ Desktop),ETC1 (LQ Mobile),ETC2 (Mobile),ASTC (Mobile)"), "set_color_compress_mode", "get_color_compress_mode");
1342-
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "free_uncompressed_color_maps"), "set_free_uncompressed_color_maps", "get_free_uncompressed_color_maps");
1342+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "free_color_map"), "set_free_color_map", "get_free_color_map");
13431343

13441344
ADD_GROUP("Collision", "");
13451345
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mode", PROPERTY_HINT_ENUM, "Disabled,Dynamic / Game,Dynamic / Editor,Full / Game,Full / Editor"), "set_collision_mode", "get_collision_mode");

src/terrain_3d.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class Terrain3D : public Node3D {
7171
RegionSize _region_size = SIZE_256;
7272
bool _save_16_bit = false;
7373
CompressMode _color_compress_mode = Terrain3DRegion::COMPRESS_NONE;
74-
bool _free_uncompressed_color_maps = true;
74+
bool _free_color_map = false;
7575
real_t _label_distance = 0.f;
7676
int _label_size = 48;
7777

@@ -174,8 +174,8 @@ class Terrain3D : public Node3D {
174174
void set_color_compress_mode(const CompressMode p_compress_mode = Terrain3DRegion::COMPRESS_NONE);
175175
Terrain3DRegion::CompressMode get_color_compress_mode() const { return _color_compress_mode; }
176176
Image::CompressMode get_color_image_compress_mode() const { return Terrain3DRegion::get_image_compress_mode(_color_compress_mode); }
177-
void set_free_uncompressed_color_maps(const bool p_free_uncompressed_color_maps) { _free_uncompressed_color_maps = p_free_uncompressed_color_maps; }
178-
bool get_free_uncompressed_color_maps() const { return _free_uncompressed_color_maps; };
177+
void set_free_color_map(const bool p_free_color_map) { _free_color_map = p_free_color_map; }
178+
bool get_free_color_map() const { return _free_color_map; };
179179
void set_label_distance(const real_t p_distance);
180180
real_t get_label_distance() const { return _label_distance; }
181181
void set_label_size(const int p_size);

src/terrain_3d_data.cpp

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ void Terrain3DData::_copy_paste_dfr(const Terrain3DRegion *p_src_region, const R
3636
TypedArray<Image> dst_maps = p_dst_region->get_maps();
3737
for (int i = 0; i < dst_maps.size(); i++) {
3838
Image *img = cast_to<Image>(dst_maps[i]);
39-
if (img) {
39+
if (img && cast_to<Image>(src_maps[i])) {
4040
img->blit_rect(src_maps[i], p_src_rect, p_dst_rect.position);
4141
}
4242
}
@@ -146,7 +146,7 @@ void Terrain3DData::change_region_size(int p_new_size) {
146146
new_region->set_region_size(p_new_size);
147147
new_region->set_vertex_spacing(_vertex_spacing);
148148
new_region->set_modified(true);
149-
new_region->sanitize_maps(false);
149+
new_region->sanitize_maps();
150150

151151
// Copy current data from current into new region, up to new region size
152152
Rect2i area;
@@ -247,10 +247,14 @@ Error Terrain3DData::add_region(const Ref<Terrain3DRegion> &p_region, const bool
247247
-REGION_MAP_SIZE / 2, " to ", REGION_MAP_SIZE / 2 - 1);
248248
return FAILED;
249249
}
250-
if (!IS_EDITOR && _terrain->get_color_compress_mode() != Terrain3DRegion::COMPRESS_NONE) {
251-
p_region->sanitize_maps(_terrain->get_free_uncompressed_color_maps());
252-
} else {
253-
p_region->sanitize_maps(false);
250+
p_region->sanitize_maps();
251+
// Free compressed color map in editor
252+
if (IS_EDITOR) {
253+
p_region->clear_compressed_color_map();
254+
} else if (_terrain && _terrain->get_free_color_map() &&
255+
p_region->get_compressed_color_map().is_valid()) {
256+
// Free uncompressed color map in game if valid and desired
257+
p_region->clear_color_map();
254258
}
255259
p_region->set_deleted(false);
256260
if (!_region_locations.has(region_loc)) {
@@ -393,6 +397,30 @@ void Terrain3DData::load_directory(const String &p_dir) {
393397
region->set_version(CURRENT_VERSION); // Sends upgrade warning if old version
394398
add_region(region, false);
395399
}
400+
401+
LOG(MESG, "Verifying region color maps:");
402+
for (const Vector2i &region_loc : _region_locations) {
403+
const Terrain3DRegion *region = get_region_ptr(region_loc);
404+
if (region) {
405+
Vector2i region_loc = region->get_location();
406+
Ref<Image> map = region->get_color_map();
407+
if (map.is_valid()) {
408+
LOG(MESG, "Region ", region_loc, " color map size: ",
409+
map->get_size(), " format: ", map->get_format());
410+
} else {
411+
LOG(MESG, "Region ", region_loc, " colormap: null");
412+
}
413+
414+
map = region->get_compressed_color_map();
415+
if (map.is_valid()) {
416+
LOG(MESG, "Region ", region_loc, " compressed color map size: ",
417+
map->get_size(), " format: ", map->get_format());
418+
} else {
419+
LOG(MESG, "Region ", region_loc, " compressed colormap: null");
420+
}
421+
}
422+
}
423+
396424
update_maps(TYPE_MAX, true, false);
397425
}
398426

@@ -551,7 +579,7 @@ void Terrain3DData::update_maps(const MapType p_map_type, const bool p_all_regio
551579
for (const Vector2i &region_loc : _region_locations) {
552580
const Terrain3DRegion *region = get_region_ptr(region_loc);
553581
if (region) {
554-
_color_maps.push_back(region->get_map(TYPE_COLOR));
582+
_color_maps.push_back(region->get_active_color_map());
555583
}
556584
}
557585
_generated_color_maps.create(_color_maps);
@@ -579,14 +607,14 @@ void Terrain3DData::update_maps(const MapType p_map_type, const bool p_all_regio
579607
emit_signal("control_maps_changed");
580608
break;
581609
case TYPE_COLOR:
582-
_generated_color_maps.update(region->get_map(TYPE_COLOR), region_id);
610+
_generated_color_maps.update(region->get_active_color_map(), region_id);
583611
LOG(DEBUG, "Emitting color_maps_changed");
584612
emit_signal("color_maps_changed");
585613
break;
586614
default:
587615
_generated_height_maps.update(region->get_height_map(), region_id);
588616
_generated_control_maps.update(region->get_control_map(), region_id);
589-
_generated_color_maps.update(region->get_map(TYPE_COLOR), region_id);
617+
_generated_color_maps.update(region->get_active_color_map(), region_id);
590618
LOG(DEBUG, "Emitting height_maps_changed");
591619
emit_signal("height_maps_changed");
592620
LOG(DEBUG, "Emitting control_maps_changed");
@@ -971,7 +999,7 @@ void Terrain3DData::import_images(const TypedArray<Image> &p_images, const Vecto
971999
region->set_map(static_cast<MapType>(i), img_slice);
9721000
}
9731001
}
974-
region->sanitize_maps(false);
1002+
region->sanitize_maps();
9751003
} // for x < slices_width
9761004
} // for y < slices_height
9771005
update_maps(TYPE_MAX, true, false);

src/terrain_3d_data.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class Terrain3DData : public Object {
1616
friend Terrain3D;
1717

1818
public: // Constants
19-
static inline const real_t CURRENT_VERSION = 0.93f;
19+
static inline const real_t CURRENT_VERSION = 1.099f; // Current Terrain3DRegion format version
2020
static inline const int REGION_MAP_SIZE = 32;
2121
static inline const Vector2i REGION_MAP_VSIZE = V2I(REGION_MAP_SIZE);
2222

src/terrain_3d_editor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,7 @@ void Terrain3DEditor::_apply_undo(const Dictionary &p_data) {
667667
LOG(ERROR, "Null region saved in undo data. Please report this error.");
668668
continue;
669669
}
670-
region->sanitize_maps(false); // Live data may not have some maps so must be sanitized
670+
region->sanitize_maps(); // Live data may not have some maps so must be sanitized
671671
Dictionary regions = data->get_regions_all();
672672
regions[region->get_location()] = region;
673673
region->set_modified(true); // Tell update_maps() this region has layers that can be individually updated

src/terrain_3d_region.cpp

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// Copyright © 2025 Cory Petkovsek, Roope Palmroos, and Contributors.
22

3-
#include <godot_cpp/classes/engine.hpp>
43
#include <godot_cpp/classes/resource_saver.hpp>
54

65
#include "logger.h"
@@ -66,9 +65,6 @@ Ref<Image> Terrain3DRegion::get_map(const MapType p_map_type) const {
6665
case TYPE_CONTROL:
6766
return _control_map;
6867
case TYPE_COLOR:
69-
if (!IS_EDITOR && _compressed_color_map.is_valid()) {
70-
return _compressed_color_map;
71-
}
7268
return _color_map;
7369
default:
7470
LOG(ERROR, "Requested map type ", p_map_type, ", is invalid");
@@ -83,9 +79,6 @@ Image *Terrain3DRegion::get_map_ptr(const MapType p_map_type) const {
8379
case TYPE_CONTROL:
8480
return *_control_map;
8581
case TYPE_COLOR:
86-
if (!IS_EDITOR && _compressed_color_map.is_valid()) {
87-
return *_compressed_color_map;
88-
}
8982
return *_color_map;
9083
default:
9184
LOG(ERROR, "Requested map type ", p_map_type, ", is invalid");
@@ -156,6 +149,11 @@ void Terrain3DRegion::set_color_map(const Ref<Image> &p_map) {
156149
_color_map = map;
157150
}
158151

152+
void Terrain3DRegion::clear_color_map() {
153+
LOG(WARN, "Freeing color map for region: ", (_location.x != INT32_MAX) ? String(_location) : "(new)");
154+
_color_map.unref();
155+
}
156+
159157
void Terrain3DRegion::set_compressed_color_map(const Ref<Image> &p_map) {
160158
SET_IF_DIFF(_compressed_color_map, p_map);
161159
LOG(INFO, "Setting compressed color map for region: ", (_location.x != INT32_MAX) ? String(_location) : "(new)");
@@ -169,12 +167,30 @@ void Terrain3DRegion::set_compressed_color_map(const Ref<Image> &p_map) {
169167
_compressed_color_map = p_map;
170168
}
171169

172-
void Terrain3DRegion::free_uncompressed_color_map() {
173-
LOG(INFO, "Freeing uncompressed color map");
174-
_color_map.unref();
170+
void Terrain3DRegion::compress_color_map(const CompressMode p_compress_mode) {
171+
if (_color_map.is_null() || _color_map->is_empty()) {
172+
LOG(ERROR, "Color map is null or empty");
173+
}
174+
if (!IS_EDITOR) {
175+
LOG(ERROR, "Cannot compress maps in export builds");
176+
return;
177+
}
178+
if (p_compress_mode > COMPRESS_NONE && p_compress_mode <= COMPRESS_ASTC) {
179+
LOG(MESG, "Compressing color map with ", COMPRESS_STR[p_compress_mode]);
180+
_compressed_color_map = Image::create_from_data(_color_map->get_width(), _color_map->get_height(),
181+
_color_map->has_mipmaps(), _color_map->get_format(), _color_map->get_data());
182+
_compressed_color_map->copy_from(_color_map);
183+
_compressed_color_map->compress_from_channels(get_image_compress_mode(p_compress_mode), Image::USED_CHANNELS_RGBA);
184+
_modified = true;
185+
}
186+
}
187+
188+
void Terrain3DRegion::clear_compressed_color_map() {
189+
LOG(WARN, "Freeing compressed color map for region: ", (_location.x != INT32_MAX) ? String(_location) : "(new)");
190+
_compressed_color_map.unref();
175191
}
176192

177-
void Terrain3DRegion::sanitize_maps(bool p_free_uncompressed_color_maps) {
193+
void Terrain3DRegion::sanitize_maps() {
178194
if (_region_size == 0) { // blank region, no set_*_map has been called
179195
LOG(ERROR, "Set region_size first");
180196
return;
@@ -189,10 +205,6 @@ void Terrain3DRegion::sanitize_maps(bool p_free_uncompressed_color_maps) {
189205
_modified = true;
190206
}
191207
_control_map = map;
192-
if (p_free_uncompressed_color_maps) {
193-
free_uncompressed_color_map();
194-
return;
195-
}
196208
map = sanitize_map(TYPE_COLOR, _color_map);
197209
if (_color_map != map) {
198210
_modified = true;
@@ -332,11 +344,7 @@ Error Terrain3DRegion::save(const String &p_path, const bool p_16_bit, const Com
332344
Error err = OK;
333345
_compressed_color_map.unref();
334346
if (IS_EDITOR && p_color_compress_mode != COMPRESS_NONE) {
335-
LOG(DEBUG, "Compressing color map to format: ", COMPRESS_STR[p_color_compress_mode]);
336-
_compressed_color_map = Image::create_from_data(_color_map->get_width(), _color_map->get_height(),
337-
_color_map->has_mipmaps(), _color_map->get_format(), _color_map->get_data());
338-
_compressed_color_map->copy_from(_color_map);
339-
_compressed_color_map->compress_from_channels(get_image_compress_mode(p_color_compress_mode), Image::USED_CHANNELS_RGBA);
347+
compress_color_map(p_color_compress_mode);
340348
}
341349
if (p_16_bit) {
342350
Ref<Image> original_map;
@@ -390,6 +398,7 @@ Dictionary Terrain3DRegion::get_data() const {
390398
dict["height_map"] = _height_map;
391399
dict["control_map"] = _control_map;
392400
dict["color_map"] = _color_map;
401+
dict["compressed_color_map"] = _compressed_color_map;
393402
dict["instances"] = _instances;
394403
return dict;
395404
}
@@ -503,10 +512,13 @@ void Terrain3DRegion::_bind_methods() {
503512
ClassDB::bind_method(D_METHOD("get_control_map"), &Terrain3DRegion::get_control_map);
504513
ClassDB::bind_method(D_METHOD("set_color_map", "map"), &Terrain3DRegion::set_color_map);
505514
ClassDB::bind_method(D_METHOD("get_color_map"), &Terrain3DRegion::get_color_map);
515+
ClassDB::bind_method(D_METHOD("clear_color_map"), &Terrain3DRegion::clear_color_map);
516+
ClassDB::bind_method(D_METHOD("get_active_color_map"), &Terrain3DRegion::get_active_color_map);
506517
ClassDB::bind_method(D_METHOD("set_compressed_color_map", "map"), &Terrain3DRegion::set_compressed_color_map);
507518
ClassDB::bind_method(D_METHOD("get_compressed_color_map"), &Terrain3DRegion::get_compressed_color_map);
508-
ClassDB::bind_method(D_METHOD("free_uncompressed_color_map"), &Terrain3DRegion::free_uncompressed_color_map);
509-
ClassDB::bind_method(D_METHOD("sanitize_maps", "free_uncompressed_color_maps"), &Terrain3DRegion::sanitize_maps, DEFVAL(false));
519+
ClassDB::bind_method(D_METHOD("compress_color_map"), &Terrain3DRegion::compress_color_map);
520+
ClassDB::bind_method(D_METHOD("clear_compressed_color_map"), &Terrain3DRegion::clear_compressed_color_map);
521+
ClassDB::bind_method(D_METHOD("sanitize_maps"), &Terrain3DRegion::sanitize_maps);
510522
ClassDB::bind_method(D_METHOD("sanitize_map", "map_type", "map"), &Terrain3DRegion::sanitize_map);
511523
ClassDB::bind_method(D_METHOD("validate_map_size", "map"), &Terrain3DRegion::validate_map_size);
512524

src/terrain_3d_region.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#ifndef TERRAIN3D_REGION_CLASS_H
44
#define TERRAIN3D_REGION_CLASS_H
55

6+
#include <godot_cpp/classes/engine.hpp>
7+
68
#include "constants.h"
79
#include "terrain_3d_util.h"
810

@@ -99,10 +101,13 @@ class Terrain3DRegion : public Resource {
99101
Ref<Image> get_control_map() const { return _control_map; }
100102
void set_color_map(const Ref<Image> &p_map);
101103
Ref<Image> get_color_map() const { return _color_map; }
104+
void clear_color_map();
105+
Ref<Image> get_active_color_map() const;
102106
void set_compressed_color_map(const Ref<Image> &p_map);
103107
Ref<Image> get_compressed_color_map() const { return _compressed_color_map; }
104-
void free_uncompressed_color_map();
105-
void sanitize_maps(const bool p_free_uncompressed_color_maps = false);
108+
void compress_color_map(const CompressMode p_compress_mode);
109+
void clear_compressed_color_map();
110+
void sanitize_maps();
106111
Ref<Image> sanitize_map(const MapType p_map_type, const Ref<Image> &p_map) const;
107112
bool validate_map_size(const Ref<Image> &p_map) const;
108113

@@ -178,4 +183,11 @@ inline void Terrain3DRegion::update_heights(const Vector2 &p_low_high) {
178183
}
179184
}
180185

186+
inline Ref<Image> Terrain3DRegion::get_active_color_map() const {
187+
if (!IS_EDITOR && _compressed_color_map.is_valid()) {
188+
return _compressed_color_map;
189+
}
190+
return _color_map;
191+
}
192+
181193
#endif // TERRAIN3D_REGION_CLASS_H

0 commit comments

Comments
 (0)