new terrain plugin
This commit is contained in:
108
addons/terrain_3d/tools/importer.gd
Normal file
108
addons/terrain_3d/tools/importer.gd
Normal file
@@ -0,0 +1,108 @@
|
||||
# Copyright © 2025 Cory Petkovsek, Roope Palmroos, and Contributors.
|
||||
# Importer for Terrain3D
|
||||
@tool
|
||||
extends Terrain3D
|
||||
|
||||
|
||||
@export var clear_all: bool = false : set = reset_settings
|
||||
@export var clear_terrain: bool = false : set = reset_terrain
|
||||
@export var update_height_range: bool = false : set = update_heights
|
||||
|
||||
|
||||
func reset_settings(p_value) -> void:
|
||||
if p_value:
|
||||
height_file_name = ""
|
||||
control_file_name = ""
|
||||
color_file_name = ""
|
||||
destination_directory = ""
|
||||
import_position = Vector2i.ZERO
|
||||
height_offset = 0.0
|
||||
import_scale = 1.0
|
||||
r16_range = Vector2(0, 1)
|
||||
r16_size = Vector2i(1024, 1024)
|
||||
material = null
|
||||
assets = null
|
||||
reset_terrain(true)
|
||||
|
||||
|
||||
func reset_terrain(p_value) -> void:
|
||||
data_directory = ""
|
||||
for region:Terrain3DRegion in data.get_regions_active():
|
||||
data.remove_region(region, false)
|
||||
data.update_maps(Terrain3DRegion.TYPE_MAX, true, false)
|
||||
|
||||
|
||||
## Recalculates min and max heights for all regions.
|
||||
func update_heights(p_value) -> void:
|
||||
if p_value and data:
|
||||
data.calc_height_range(true)
|
||||
|
||||
|
||||
@export_group("Import File")
|
||||
@export_global_file var height_file_name: String = ""
|
||||
@export_global_file var control_file_name: String = ""
|
||||
@export_global_file var color_file_name: String = ""
|
||||
@export var import_position: Vector2i = Vector2i(0, 0) : set = set_import_position
|
||||
@export var import_scale: float = 1.0
|
||||
@export var height_offset: float = 0.0
|
||||
@export var r16_range: Vector2 = Vector2(0, 1)
|
||||
@export var r16_size: Vector2i = Vector2i(1024, 1024) : set = set_r16_size
|
||||
@export var run_import: bool = false : set = start_import
|
||||
|
||||
@export_dir var destination_directory: String = ""
|
||||
@export var save_to_disk: bool = false : set = save_data
|
||||
|
||||
|
||||
func set_import_position(p_value: Vector2i) -> void:
|
||||
import_position.x = clamp(p_value.x, -8192, 8192)
|
||||
import_position.y = clamp(p_value.y, -8192, 8192)
|
||||
|
||||
|
||||
func set_r16_size(p_value: Vector2i) -> void:
|
||||
r16_size.x = clamp(p_value.x, 0, 16384)
|
||||
r16_size.y = clamp(p_value.y, 0, 16384)
|
||||
|
||||
|
||||
func start_import(p_value: bool) -> void:
|
||||
if p_value:
|
||||
print("Terrain3DImporter: Importing files:\n\t%s\n\t%s\n\t%s" % [ height_file_name, control_file_name, color_file_name])
|
||||
|
||||
var imported_images: Array[Image]
|
||||
imported_images.resize(Terrain3DRegion.TYPE_MAX)
|
||||
var min_max := Vector2(0, 1)
|
||||
var img: Image
|
||||
if height_file_name:
|
||||
img = Terrain3DUtil.load_image(height_file_name, ResourceLoader.CACHE_MODE_IGNORE, r16_range, r16_size)
|
||||
min_max = Terrain3DUtil.get_min_max(img)
|
||||
imported_images[Terrain3DRegion.TYPE_HEIGHT] = img
|
||||
if control_file_name:
|
||||
img = Terrain3DUtil.load_image(control_file_name, ResourceLoader.CACHE_MODE_IGNORE)
|
||||
imported_images[Terrain3DRegion.TYPE_CONTROL] = img
|
||||
if color_file_name:
|
||||
img = Terrain3DUtil.load_image(color_file_name, ResourceLoader.CACHE_MODE_IGNORE)
|
||||
imported_images[Terrain3DRegion.TYPE_COLOR] = img
|
||||
if assets.get_texture_count() == 0:
|
||||
material.show_checkered = false
|
||||
material.show_colormap = true
|
||||
var pos := Vector3(import_position.x, 0, import_position.y)
|
||||
data.import_images(imported_images, pos, height_offset, import_scale)
|
||||
print("Terrain3DImporter: Import finished")
|
||||
|
||||
|
||||
func save_data(p_value: bool) -> void:
|
||||
if destination_directory.is_empty():
|
||||
push_error("Set destination directory first")
|
||||
return
|
||||
data.save_directory(destination_directory)
|
||||
|
||||
|
||||
@export_group("Export File")
|
||||
enum { TYPE_HEIGHT, TYPE_CONTROL, TYPE_COLOR }
|
||||
@export_enum("Height:0", "Control:1", "Color:2") var map_type: int = TYPE_HEIGHT
|
||||
@export var file_name_out: String = ""
|
||||
@export var run_export: bool = false : set = start_export
|
||||
|
||||
func start_export(p_value: bool) -> void:
|
||||
var err: int = data.export_image(file_name_out, map_type)
|
||||
print("Terrain3DImporter: Export error status: ", err, " ", error_string(err))
|
||||
|
||||
1
addons/terrain_3d/tools/importer.gd.uid
Normal file
1
addons/terrain_3d/tools/importer.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cib2rig7vup10
|
||||
63
addons/terrain_3d/tools/importer.tscn
Normal file
63
addons/terrain_3d/tools/importer.tscn
Normal file
@@ -0,0 +1,63 @@
|
||||
[gd_scene load_steps=9 format=3 uid="uid://blaieaqp413k7"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/terrain_3d/tools/importer.gd" id="1_60b8f"]
|
||||
|
||||
[sub_resource type="Gradient" id="Gradient_88f3t"]
|
||||
offsets = PackedFloat32Array(0.2, 1)
|
||||
colors = PackedColorArray(1, 1, 1, 1, 0, 0, 0, 1)
|
||||
|
||||
[sub_resource type="FastNoiseLite" id="FastNoiseLite_muvel"]
|
||||
noise_type = 2
|
||||
frequency = 0.03
|
||||
cellular_jitter = 3.0
|
||||
cellular_return_type = 0
|
||||
domain_warp_enabled = true
|
||||
domain_warp_type = 1
|
||||
domain_warp_amplitude = 50.0
|
||||
domain_warp_fractal_type = 2
|
||||
domain_warp_fractal_lacunarity = 1.5
|
||||
domain_warp_fractal_gain = 1.0
|
||||
|
||||
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_ve0yk"]
|
||||
seamless = true
|
||||
color_ramp = SubResource("Gradient_88f3t")
|
||||
noise = SubResource("FastNoiseLite_muvel")
|
||||
|
||||
[sub_resource type="Terrain3DMaterial" id="Terrain3DMaterial_p55u0"]
|
||||
_shader_parameters = {
|
||||
"blend_sharpness": 0.87,
|
||||
"height_blending": true,
|
||||
"macro_variation1": Color(1, 1, 1, 1),
|
||||
"macro_variation2": Color(1, 1, 1, 1),
|
||||
"noise1_angle": 0.0,
|
||||
"noise1_offset": Vector2(0.5, 0.5),
|
||||
"noise1_scale": 0.04,
|
||||
"noise2_scale": 0.076,
|
||||
"noise3_scale": 0.225,
|
||||
"noise_texture": SubResource("NoiseTexture2D_ve0yk"),
|
||||
"vertex_normals_distance": 128.0
|
||||
}
|
||||
show_checkered = true
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_8rvqy"]
|
||||
cull_mode = 2
|
||||
vertex_color_use_as_albedo = true
|
||||
backlight_enabled = true
|
||||
backlight = Color(0.5, 0.5, 0.5, 1)
|
||||
|
||||
[sub_resource type="Terrain3DMeshAsset" id="Terrain3DMeshAsset_7je72"]
|
||||
height_offset = 0.5
|
||||
density = 10.0
|
||||
material_override = SubResource("StandardMaterial3D_8rvqy")
|
||||
generated_type = 1
|
||||
|
||||
[sub_resource type="Terrain3DAssets" id="Terrain3DAssets_op32e"]
|
||||
mesh_list = Array[Terrain3DMeshAsset]([SubResource("Terrain3DMeshAsset_7je72")])
|
||||
|
||||
[node name="Importer" type="Terrain3D"]
|
||||
material = SubResource("Terrain3DMaterial_p55u0")
|
||||
assets = SubResource("Terrain3DAssets_op32e")
|
||||
mesh_lods = 8
|
||||
top_level = true
|
||||
script = ExtResource("1_60b8f")
|
||||
metadata/_edit_lock_ = true
|
||||
52
addons/terrain_3d/tools/region_mover.gd
Normal file
52
addons/terrain_3d/tools/region_mover.gd
Normal file
@@ -0,0 +1,52 @@
|
||||
# This script can be used to move your regions by an offset.
|
||||
# Eventually this tool will find its way into a built in UI
|
||||
#
|
||||
# Attach it to your Terrain3D node
|
||||
# Save and reload your scene
|
||||
# Select your Terrain3D node
|
||||
# Enter a valid `offset` where all regions will be within -16, +15
|
||||
# Run it
|
||||
# It should unload the regions, rename files, and reload them
|
||||
# Clear the script and resave your scene
|
||||
|
||||
|
||||
@tool
|
||||
extends Terrain3D
|
||||
|
||||
|
||||
@export var offset: Vector2i
|
||||
@export var run: bool = false : set = start_rename
|
||||
|
||||
|
||||
func start_rename(val: bool = false) -> void:
|
||||
if val == false or offset == Vector2i.ZERO:
|
||||
return
|
||||
|
||||
var dir_name: String = data_directory
|
||||
data_directory = ""
|
||||
var dir := DirAccess.open(dir_name)
|
||||
if not dir:
|
||||
print("An error occurred when trying to access the path: ", data_directory)
|
||||
return
|
||||
|
||||
var affected_files: PackedStringArray
|
||||
var files: PackedStringArray = dir.get_files()
|
||||
for file_name in files:
|
||||
if file_name.match("terrain3d*.res") and not dir.current_is_dir():
|
||||
var region_loc: Vector2i = Terrain3DUtil.filename_to_location(file_name)
|
||||
var new_loc: Vector2i = region_loc + offset
|
||||
if new_loc.x < -16 or new_loc.x > 15 or new_loc.y < -16 or new_loc.y > 15:
|
||||
push_error("New location %.0v out of bounds for region %.0v. Aborting" % [ new_loc, region_loc ])
|
||||
return
|
||||
var new_name: String = "tmp_" + Terrain3DUtil.location_to_filename(new_loc)
|
||||
dir.rename(file_name, new_name)
|
||||
affected_files.push_back(new_name)
|
||||
print("File: %s renamed to: %s" % [ file_name, new_name ])
|
||||
|
||||
for file_name in affected_files:
|
||||
var new_name: String = file_name.trim_prefix("tmp_")
|
||||
dir.rename(file_name, new_name)
|
||||
print("File: %s renamed to: %s" % [ file_name, new_name ])
|
||||
|
||||
data_directory = dir_name
|
||||
EditorInterface.get_resource_filesystem().scan()
|
||||
1
addons/terrain_3d/tools/region_mover.gd.uid
Normal file
1
addons/terrain_3d/tools/region_mover.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bngnvtbm6ifkk
|
||||
Reference in New Issue
Block a user