-
Notifications
You must be signed in to change notification settings - Fork 131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow region size changes #447
Allow region size changes #447
Conversation
In my new PR, Terrain3DStorage has been renamed to Terrain3DData and changed from a savable resource to an Object. It won't save any data itself. All of the saved data are in Terrain3DRegions or the scene file. I'm moving the (global) region_size setting to Terrain3D. This PR reslices when changing the setting. Fine with a few regions, but dangerous with 256-2048 regions. What about undo/redo? If it's an inspector setting, Godot will undo/redo that setting which will reslice each time. Also not a great user experience. The regions track their own region size based on the size of the first map loaded and validate subsequent loads against it. What if you're moving region files from one project to another? You need to set the right global region size setting before loading them or you'll get weird/broken results. Maybe when loading regions, it automatically sets global region size based on the first region and complains about any regions that are different. Once loaded the user can manually reslice if desired. I'm thinking about rather than giving them an enum to choose and reslicing all data each time they change it, instead:
In my PR all changes are done in memory (add/remove regions, sculpting, painting) and are not saved to disk until the scene is saved. Reslicing should work the same. Looks like this PR also does that. Looks like this is a minor addition to what is already here, but my new region structure will require more updating. |
My PRs are merged. Please rebase and update this so we can merge it in. |
f5a5206
to
9a452e1
Compare
|
||
for (Ref<Terrain3DRegion> r : old_regions) { | ||
remove_region(r, false); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove_region doesn't remove from _regions, it only marks those regions as deleted.
When add_region comes in, it is adding regions in a populated dictionary, but the indexed keys are two different scales.
Saving after this operation reports missing regions because _regions has been corrupted.
Rather than remove_region, _regions should just be erased, and new regions added. The region map will be rebuilt in update_maps.
Those old regions will be freed if unreferenced, unless stored by the undo/redo system.
for (int y = index_bounds.position.y; y < index_bounds.get_end().y; y++) { | ||
current_region_loc.y = y; | ||
for (int x = index_bounds.position.x; x < index_bounds.get_end().x; x++) { | ||
current_region_loc.x = x; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of this receives integer points in p_bounds, then converts to float to get the region location. Then it iterates through the included region locations. There's no reason or benefit to limit input to integers, or even calculate here. Instead, it can receive real world global coordinates and use get_region_location() to convert to location, including descaling.
Also below will crash on line 84 (region->get...) if region is null and p_do_empty_regions is true.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I didn't test at all with p_do_empty_regions set to true. It's just a thing that LayerProcGen supports and it seemed sensible to do the same here. Like when you want to fill an area with a default colour, if no terrain exists there.
The main reason this version is limited to integers, is because it'll slow everything down by a lot if you need to consider interpolation. For one, interpolation can require you to use more than one region at the same time. I haven't really come up with a clean way to do that yet. (Later edit: I was mostly thinking of the per-pixel version of this function, but that will require the per-region version, and the int based per-pixel function would work best with an int-based per-region function)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to drop do_empty_regions. You're calling the region and have nothing to call if it's null. We can add more functionality later based on need. Perhaps it can add empty regions, then call them, but right now there's no use for it.
I think dd729a4 is much more versatile, allowing us to provide copy/paste functionality to the editor in the future, and exposing do_for_regions to all languages. Now we can do this in gdscript. func _ready() -> void:
print("Readying do for regions")
data.do_for_regions(Rect2i(0,-3072, 2048, 2048),
func(region:Terrain3DRegion, sarea:Rect2i, darea:Rect2i):
print("GDScript: ", region, sarea, darea)
)
GDScript: [Wrapped:0][P: (0, 1024), S: (1024, 1024)][P: (0, 0), S: (1024, 1024)]
GDScript: [Wrapped:0][P: (1024, 1024), S: (1024, 1024)][P: (0, 0), S: (1024, 1024)] |
This is working well with Callable and reslicing is very fast. However, there are four outstanding bugs that I haven't tracked down yet. They are present in your original and my current. My note about making a new _regions database might be accurate and help these. This is what I'm working on next.
This is the engine source It might be attempting to Update: I get this in 4.2.2 when I've attached a built in script to Terrain3D for testing, and ctrl+alt+save the script. Above when I've gotten it has been from ctrl+s to save the scene. This error is likely an engine bug with built in scripts, so I'll ignore it for now.
|
Exposing copy_paste allows this to work in gdscript. It currently copies the contents of region maps from range 0 to region_size. In the future this should be expanded to work with a rect2i in global coordinates, then loop through regions within the area
|
Alright, I found a sequence that causes
region_locations: [(0, -1), (0, 0)] Something is inserting ghost regions into _regions. |
Attempting to put this in Out of the Ashes, I realized this doesn't reslice any of the foliage data. It just erases it. Also the AABBs need to be recalculated. I have updated the top post with a tracker of tasks to do. |
fb8c692
to
b3ca706
Compare
Updates:
I'm working on moving foliage properly |
7103aa8
to
913319e
Compare
This PR is ready for review and testing. There's just one last bug I'm tracking down: region sizes can't be changed right after upgrading. You must upgrade to the new storage, save, and reload the scene before region sizes can be changed. |
c320daa
to
2fb56b9
Compare
empty dir, update color mipmaps after rs, warn and stop if upgrading w/ full directory, Update filesystem only after saving directory
2fb56b9
to
21ebaf8
Compare
Update by TokisanGames
Fixes #77
Fixes #487
Original PR
This should fix #77, and I haven't been able to spot any remaining issues regarding different region sizes. Regions are resized when you change the size, so if you have smaller regions that don't fully fill up a larger region when you change to a larger size, the other parts of that region will get default values.
The code for resizing is a little ugly (much uglier when sizing up, rather than down) and probably not very well optimized, but it works, and people are unlikely to change region sizes so often that it's a show-stopper.