diff --git a/black.png b/black.png new file mode 100644 index 0000000..ec595a4 --- /dev/null +++ b/black.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ce78e46a0340f336b19b46c5ae401650bd9ef87073dc096b22d8f523c8e9ca3 +size 86 diff --git a/black.png.import b/black.png.import new file mode 100644 index 0000000..3a677f9 --- /dev/null +++ b/black.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cj72ibo3c6x8e" +path="res://.godot/imported/black.png-19a8df0b1a4edb74ea2eecb66d46d03d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://black.png" +dest_files=["res://.godot/imported/black.png-19a8df0b1a4edb74ea2eecb66d46d03d.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/editor.scn b/editor.scn index 681b5de..a04e07e 100644 --- a/editor.scn +++ b/editor.scn @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b2aa052c695e7875d548df6dc3fa6bf06f4294490d04a82bc4992923e959c4e8 -size 6597 +oid sha256:f440fd5671e8668e3c627d3447cecb4d8b508cdd4590805726edadf663e4c6e7 +size 7923 diff --git a/editor/brush_hard_circle_mask.png b/editor/brush_hard_circle_mask.png new file mode 100644 index 0000000..e2558d3 --- /dev/null +++ b/editor/brush_hard_circle_mask.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0b2a9fa190051309bfc4f5aac029fee8a3a44f6e493aa0a27df8b99eb06100da +size 434 diff --git a/editor/brush_hard_circle_mask.png.import b/editor/brush_hard_circle_mask.png.import new file mode 100644 index 0000000..0c12c25 --- /dev/null +++ b/editor/brush_hard_circle_mask.png.import @@ -0,0 +1,14 @@ +[remap] + +importer="image" +type="Image" +uid="uid://drok88h02tdre" +path="res://.godot/imported/brush_hard_circle_mask.png-e647df7b970f00cdf2f3f2ac38ad8257.image" + +[deps] + +source_file="res://editor/brush_hard_circle_mask.png" +dest_files=["res://.godot/imported/brush_hard_circle_mask.png-e647df7b970f00cdf2f3f2ac38ad8257.image"] + +[params] + diff --git a/editor/brush_soft_circle_mask.png b/editor/brush_soft_circle_mask.png new file mode 100644 index 0000000..6f52c3d --- /dev/null +++ b/editor/brush_soft_circle_mask.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b10ccded55e2a53b86a495fdcb501f5391bec01d478dae056d60474fcc13dc5 +size 1717 diff --git a/editor/brush_soft_circle_mask.png.import b/editor/brush_soft_circle_mask.png.import new file mode 100644 index 0000000..6b453bf --- /dev/null +++ b/editor/brush_soft_circle_mask.png.import @@ -0,0 +1,14 @@ +[remap] + +importer="image" +type="Image" +uid="uid://bbdh4btpg08do" +path="res://.godot/imported/brush_soft_circle_mask.png-5af527bedd556c2d7ed38b029e34527e.image" + +[deps] + +source_file="res://editor/brush_soft_circle_mask.png" +dest_files=["res://.godot/imported/brush_soft_circle_mask.png-5af527bedd556c2d7ed38b029e34527e.image"] + +[params] + diff --git a/editor/edit_mode_button_group.res b/editor/edit_mode_button_group.res new file mode 100644 index 0000000..9e6a97d --- /dev/null +++ b/editor/edit_mode_button_group.res @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dcc7954349a7ed68391dfbfd0e8369169da156218b5b856dda3005ef0708ad16 +size 202 diff --git a/editor/menus_theme.res b/editor/menus_theme.res new file mode 100644 index 0000000..e4ae784 --- /dev/null +++ b/editor/menus_theme.res @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6abf7dfa9a4e3b0da93384cd5600a50cb553a18f337dcb9b5aeaf5a52b871271 +size 825 diff --git a/editor_theme.res b/editor_theme.res deleted file mode 100644 index 8dd9794..0000000 --- a/editor_theme.res +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:68b3bc205138b626fa79896fd4ae0343ff7c46f660cf060ddd23454f240e9145 -size 390 diff --git a/player_controller.gd b/player_controller.gd index 20a044b..c7f6114 100644 --- a/player_controller.gd +++ b/player_controller.gd @@ -72,6 +72,7 @@ var movement_smoothing := 0.5 ## ## Whether or not player movement input processed by the controller should be ignored. ## +@export var frozen := false func _input(event: InputEvent) -> void: diff --git a/project.godot b/project.godot index 7e196d1..b065f79 100644 --- a/project.godot +++ b/project.godot @@ -9,6 +9,16 @@ config_version=5 _global_script_classes=[{ +"base": "TerrainInstance3D", +"class": &"DynamicTerrainInstance3D", +"language": &"GDScript", +"path": "res://terrain/dynamic_terrain_instance_3d.gd" +}, { +"base": "HFlowContainer", +"class": &"ItemSelection", +"language": &"GDScript", +"path": "res://user_interface/button_selection.gd" +}, { "base": "Node3D", "class": &"PlayerController", "language": &"GDScript", @@ -22,18 +32,27 @@ _global_script_classes=[{ "base": "GeometryInstance3D", "class": &"TerrainInstance3D", "language": &"GDScript", -"path": "res://terrain_instance_3d.gd" +"path": "res://terrain/terrain_instance_3d.gd" +}, { +"base": "Resource", +"class": &"TerrainPaint", +"language": &"GDScript", +"path": "res://terrain/paints/terrain_paint.gd" }] _global_script_class_icons={ +"DynamicTerrainInstance3D": "", +"ItemSelection": "", "PlayerController": "", "Settings": "", -"TerrainInstance3D": "" +"TerrainInstance3D": "", +"TerrainPaint": "" } [application] config/name="Protectorate" run/main_scene="res://editor.scn" +config/use_custom_user_dir=true config/features=PackedStringArray("4.0", "Forward Plus") config/icon="res://icon.png" diff --git a/terrain/dynamic_terrain_instance_3d.gd b/terrain/dynamic_terrain_instance_3d.gd new file mode 100644 index 0000000..07f5d75 --- /dev/null +++ b/terrain/dynamic_terrain_instance_3d.gd @@ -0,0 +1,126 @@ +class_name DynamicTerrainInstance3D extends TerrainInstance3D + +## +## Blank sample value. +## +const BLANK := Color(0.0, 0.0, 0.0, 0.0) + +var _editable_image: Image + +var _editable_texture: ImageTexture + +func _get_brush_area(point: Vector2i, mask_size: Vector2i, mask_scale: float) -> Rect2i: + # Convert worldspace point to image-space coordinates for mask. + var scaled_mask_size := Vector2i(mask_size * mask_scale) + + return Rect2i((point + Vector2i(get_size() * 0.5)) - Vector2i(scaled_mask_size * 0.5), scaled_mask_size) + +func _init() -> void: + super._init() + + _editable_image = Image.create(1, 1, false, Image.FORMAT_RGBAF) + _editable_texture = ImageTexture.create_from_image(_editable_image) + + super.resize(Vector2i.ONE) + +## +## Clears the terrain map to the value of [code]clear_elevation[/code]. +## +func clear(clear_elevation: float) -> void: + _editable_image.fill(Color(0.0, 0.0, 0.0, clampf(clear_elevation, 0.0, 1.0))) + _editable_texture.update(_editable_image) + +## +## Oscillates the height of terrain toward a value of [member height_scale] (multiplied by +## [code]level[/code]) around the area of [code]point[/code] determined by [code]mask[/code] +## multiplied by [code]mask_scale[/code] at a rate of [code]intensity[/code]. +## +func oscillate(point: Vector2i, level: float, mask: Image, mask_scale: float, intensity: float) -> void: + var mask_size := mask.get_size() + var brush_source := _get_brush_area(point, mask_size, mask_scale) + + if brush_source.has_area(): + var brush_target := Rect2i(Vector2i.ZERO, get_size()).intersection(brush_source) + + if brush_target.has_area(): + var mask_ratio := mask_size / brush_source.size + var offset := brush_target.position - brush_source.position + + for y in brush_target.size.y: + var mask_y := int((offset.y + y) * mask_ratio.y) + + for x in brush_target.size.x: + var coord := brush_target.position + Vector2i(x, y) + var pixel := _editable_image.get_pixelv(coord) + + _editable_image.set_pixelv(coord, Color(pixel.r, pixel.g, pixel.b, + lerpf(pixel.a, level, intensity *\ + mask.get_pixel(int((offset.x + x) * mask_ratio.x), mask_y).a)).clamp()) + + _editable_texture.update(_editable_image) + +## +## Paints the texture of the terrain toward a value of [code]color[/code] multiplied by +## [code]intensity[/code] around the area of [code]point[/code] determined by [code]mask[/code] +## multiplied by [code]mask_scale[/code] at a rate of [code]intensity[/code]. +## +func paint(point: Vector2i, color: Color, mask: Image, mask_scale: float, intensity: float) -> void: + var mask_size := mask.get_size() + var brush_source := _get_brush_area(point, mask_size, mask_scale) + + if brush_source.has_area(): + var brush_target := Rect2i(Vector2i.ZERO, get_size()).intersection(brush_source) + + if brush_target.has_area(): + var mask_ratio := mask_size / brush_source.size + var offset := brush_target.position - brush_source.position + + for y in brush_target.size.y: + var mask_y := int((offset.y + y) * mask_ratio.y) + + for x in brush_target.size.x: + var coord := brush_target.position + Vector2i(x, y) + var pixel := _editable_image.get_pixelv(coord) + + var mask_intensity_delta := intensity *\ + mask.get_pixel(int((offset.x + x) * mask_ratio.x), mask_y).a + + _editable_image.set_pixelv(coord, Color( + lerpf(pixel.r, color.r, mask_intensity_delta), + lerpf(pixel.g, color.g, mask_intensity_delta), + lerpf(pixel.b, color.b, mask_intensity_delta), pixel.a).clamp()) + + _editable_texture.update(_editable_image) + +## +## Attempts to resize the terrain geometry and map to be equal to [code]size[/code] (in-engine +## units), with [code]Vector2i.ONE[/code] as the minimum size. +## +## In the process of growing the terrain map, existing edge data will be copied to fill it out. +## +func resize(size: Vector2i) -> void: + super.resize(size) + + var actual_size := get_size() + + _editable_image.resize(actual_size.x, actual_size.y) + + _editable_texture = ImageTexture.create_from_image(_editable_image) + + update_terrain(_editable_texture) + +## +## Samples the color value in the editable terrain at the worldspace [code]point[/code], returning +## its respective [Color] value. +## +## For sample coordinates outside of the terrain map worldspace, [code]BLANK[/code] is returned +## instead. +## +func sample(point: Vector2i) -> Color: + var size := get_size() + var image_point := point + Vector2i(size * 0.5) + + if Rect2i(Vector2i.ZERO, size).has_point(image_point): + return _editable_image.get_pixelv(image_point) + + return BLANK diff --git a/terrain/paints/arid_grass_albedo.png b/terrain/paints/arid_grass_albedo.png new file mode 100644 index 0000000..6761466 --- /dev/null +++ b/terrain/paints/arid_grass_albedo.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8b0f159785fc28ed062e74f270d5897ad5cfc08141962bfa52f168df02658ab0 +size 2524391 diff --git a/terrain/paints/arid_grass_albedo.png.import b/terrain/paints/arid_grass_albedo.png.import new file mode 100644 index 0000000..ec0dd15 --- /dev/null +++ b/terrain/paints/arid_grass_albedo.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://jcmf7j3qo6ea" +path="res://.godot/imported/arid_grass_albedo.png-532bc188063dc524e2c08228bed13fa7.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://terrain/paints/arid_grass_albedo.png" +dest_files=["res://.godot/imported/arid_grass_albedo.png-532bc188063dc524e2c08228bed13fa7.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/terrain/paints/arid_grass_displacement.png b/terrain/paints/arid_grass_displacement.png new file mode 100644 index 0000000..13d2d85 --- /dev/null +++ b/terrain/paints/arid_grass_displacement.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8073d5c82878ea87ae09a5856c6e13282bd46093e8867a79c9419e7def34cf45 +size 368090 diff --git a/terrain/paints/arid_grass_displacement.png.import b/terrain/paints/arid_grass_displacement.png.import new file mode 100644 index 0000000..44bb805 --- /dev/null +++ b/terrain/paints/arid_grass_displacement.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://co0jompch208v" +path="res://.godot/imported/arid_grass_displacement.png-cad938b62195c0b0f41099d596594b8b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://terrain/paints/arid_grass_displacement.png" +dest_files=["res://.godot/imported/arid_grass_displacement.png-cad938b62195c0b0f41099d596594b8b.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/terrain/paints/arid_grass_normal.png b/terrain/paints/arid_grass_normal.png new file mode 100644 index 0000000..53b9ddf --- /dev/null +++ b/terrain/paints/arid_grass_normal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:822937d4cb546d433562390277652a4e3f373328f6045480fa7905d8c163b814 +size 781967 diff --git a/terrain/paints/arid_grass_normal.png.import b/terrain/paints/arid_grass_normal.png.import new file mode 100644 index 0000000..fe11398 --- /dev/null +++ b/terrain/paints/arid_grass_normal.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bh141jkgbmya8" +path="res://.godot/imported/arid_grass_normal.png-7bf9fdf5f927fea47a2f86a9ffab326e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://terrain/paints/arid_grass_normal.png" +dest_files=["res://.godot/imported/arid_grass_normal.png-7bf9fdf5f927fea47a2f86a9ffab326e.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/terrain/paints/arid_grass_roughness.png b/terrain/paints/arid_grass_roughness.png new file mode 100644 index 0000000..c56136a --- /dev/null +++ b/terrain/paints/arid_grass_roughness.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5d36c8bf74944ea23945b7fdc254b64dfc2c8b18aa84a3a861406a8fe9c5fae4 +size 375431 diff --git a/terrain/paints/arid_grass_roughness.png.import b/terrain/paints/arid_grass_roughness.png.import new file mode 100644 index 0000000..577efda --- /dev/null +++ b/terrain/paints/arid_grass_roughness.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://jdq8kwjo3uap" +path="res://.godot/imported/arid_grass_roughness.png-40299cbb0e24b392d013d45af79f5444.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://terrain/paints/arid_grass_roughness.png" +dest_files=["res://.godot/imported/arid_grass_roughness.png-40299cbb0e24b392d013d45af79f5444.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/terrain/paints/arid_grass_terrain_paint.res b/terrain/paints/arid_grass_terrain_paint.res new file mode 100644 index 0000000..c74ae9f --- /dev/null +++ b/terrain/paints/arid_grass_terrain_paint.res @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa81b3c8d2c39bb6abcf24a5a021f12b3e1050cffeb9d94145dd57560255205b +size 297 diff --git a/terrain/paints/cobblestone_albedo.png b/terrain/paints/cobblestone_albedo.png new file mode 100644 index 0000000..9f80ce4 --- /dev/null +++ b/terrain/paints/cobblestone_albedo.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:03f34c2cdf4e3f941d62bed684cc05017c8daea13218bcc61433a97917770a96 +size 1615088 diff --git a/terrain/paints/cobblestone_albedo.png.import b/terrain/paints/cobblestone_albedo.png.import new file mode 100644 index 0000000..a6fb1ba --- /dev/null +++ b/terrain/paints/cobblestone_albedo.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cs06oiwrord6t" +path="res://.godot/imported/cobblestone_albedo.png-f0ce6b9d25b0c6c4130e70ff660bcbd6.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://terrain/paints/cobblestone_albedo.png" +dest_files=["res://.godot/imported/cobblestone_albedo.png-f0ce6b9d25b0c6c4130e70ff660bcbd6.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/terrain/paints/cobblestone_displacement.png b/terrain/paints/cobblestone_displacement.png new file mode 100644 index 0000000..b04dbd2 --- /dev/null +++ b/terrain/paints/cobblestone_displacement.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79990410d9c9212930e7d3e59e2825c3ba9d3c3354ae4e52ddb988d49ee282e5 +size 189441 diff --git a/terrain/paints/cobblestone_displacement.png.import b/terrain/paints/cobblestone_displacement.png.import new file mode 100644 index 0000000..375525b --- /dev/null +++ b/terrain/paints/cobblestone_displacement.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://mkxbjfwdwkaq" +path="res://.godot/imported/cobblestone_displacement.png-bcf2e2194862b85cb002d9559d57903b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://terrain/paints/cobblestone_displacement.png" +dest_files=["res://.godot/imported/cobblestone_displacement.png-bcf2e2194862b85cb002d9559d57903b.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/terrain/paints/cobblestone_normal.png b/terrain/paints/cobblestone_normal.png new file mode 100644 index 0000000..c5396be --- /dev/null +++ b/terrain/paints/cobblestone_normal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ef381960a013f47fb6c1334f36ef99662df8938bdc2b5004ff4fb76dcf93e77 +size 627601 diff --git a/terrain/paints/cobblestone_normal.png.import b/terrain/paints/cobblestone_normal.png.import new file mode 100644 index 0000000..a1070c8 --- /dev/null +++ b/terrain/paints/cobblestone_normal.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ukk0161x3eg2" +path="res://.godot/imported/cobblestone_normal.png-5130e667fa81f7452d15808908f4cb99.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://terrain/paints/cobblestone_normal.png" +dest_files=["res://.godot/imported/cobblestone_normal.png-5130e667fa81f7452d15808908f4cb99.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/terrain/paints/cobblestone_roughness.png b/terrain/paints/cobblestone_roughness.png new file mode 100644 index 0000000..d74e666 --- /dev/null +++ b/terrain/paints/cobblestone_roughness.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:002b4dd1f43e3159e5def14b451942db30d75c49e121fcceb7addd0c83e1530f +size 228583 diff --git a/terrain/paints/cobblestone_roughness.png.import b/terrain/paints/cobblestone_roughness.png.import new file mode 100644 index 0000000..abc898b --- /dev/null +++ b/terrain/paints/cobblestone_roughness.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bcybapft8tl2x" +path="res://.godot/imported/cobblestone_roughness.png-2f09da1d7000b898b80d7b177062e509.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://terrain/paints/cobblestone_roughness.png" +dest_files=["res://.godot/imported/cobblestone_roughness.png-2f09da1d7000b898b80d7b177062e509.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/terrain/paints/cobblestone_terrain_paint.res b/terrain/paints/cobblestone_terrain_paint.res new file mode 100644 index 0000000..2fcdbe9 --- /dev/null +++ b/terrain/paints/cobblestone_terrain_paint.res @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27eefce861ebe9d90bfc1ffa242cf38b96332f65d04aafe404f17f85f9d2daa3 +size 292 diff --git a/prototype_tiles_large_albedo.png b/terrain/paints/default_albedo.png similarity index 100% rename from prototype_tiles_large_albedo.png rename to terrain/paints/default_albedo.png diff --git a/prototype_tiles_large_albedo.png.import b/terrain/paints/default_albedo.png.import similarity index 54% rename from prototype_tiles_large_albedo.png.import rename to terrain/paints/default_albedo.png.import index 073e101..c64f065 100644 --- a/prototype_tiles_large_albedo.png.import +++ b/terrain/paints/default_albedo.png.import @@ -3,8 +3,8 @@ importer="texture" type="CompressedTexture2D" uid="uid://bgpk15qrqxly8" -path.s3tc="res://.godot/imported/prototype_tiles_large_albedo.png-c3984e5db888f4b509766546fda5695b.s3tc.ctex" -path.etc2="res://.godot/imported/prototype_tiles_large_albedo.png-c3984e5db888f4b509766546fda5695b.etc2.ctex" +path.s3tc="res://.godot/imported/default_albedo.png-ec7b9bee606a4c8482c5f21d50eaafb2.s3tc.ctex" +path.etc2="res://.godot/imported/default_albedo.png-ec7b9bee606a4c8482c5f21d50eaafb2.etc2.ctex" metadata={ "imported_formats": ["s3tc", "etc2"], "vram_texture": true @@ -12,8 +12,8 @@ metadata={ [deps] -source_file="res://prototype_tiles_large_albedo.png" -dest_files=["res://.godot/imported/prototype_tiles_large_albedo.png-c3984e5db888f4b509766546fda5695b.s3tc.ctex", "res://.godot/imported/prototype_tiles_large_albedo.png-c3984e5db888f4b509766546fda5695b.etc2.ctex"] +source_file="res://terrain/paints/default_albedo.png" +dest_files=["res://.godot/imported/default_albedo.png-ec7b9bee606a4c8482c5f21d50eaafb2.s3tc.ctex", "res://.godot/imported/default_albedo.png-ec7b9bee606a4c8482c5f21d50eaafb2.etc2.ctex"] [params] diff --git a/terrain/paints/default_terrain_paint.res b/terrain/paints/default_terrain_paint.res new file mode 100644 index 0000000..e8202f5 --- /dev/null +++ b/terrain/paints/default_terrain_paint.res @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f7bc9218bdd88690b9994999715acb1e1233299ba9fe008d835a6cc9ff592f0 +size 294 diff --git a/terrain/paints/desert_sand_albedo.png b/terrain/paints/desert_sand_albedo.png new file mode 100644 index 0000000..3c9cd8c --- /dev/null +++ b/terrain/paints/desert_sand_albedo.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:321a1d55f3b1779b4e5c34ac1bdbd192e7b3099db59017422d0b6ed993bde624 +size 1160665 diff --git a/terrain/paints/desert_sand_albedo.png.import b/terrain/paints/desert_sand_albedo.png.import new file mode 100644 index 0000000..1f2e15d --- /dev/null +++ b/terrain/paints/desert_sand_albedo.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b8cv4q43fsglu" +path="res://.godot/imported/desert_sand_albedo.png-1f8394c37b6df0b83ddc4964049fe1fb.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://terrain/paints/desert_sand_albedo.png" +dest_files=["res://.godot/imported/desert_sand_albedo.png-1f8394c37b6df0b83ddc4964049fe1fb.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/terrain/paints/desert_sand_displacement.png b/terrain/paints/desert_sand_displacement.png new file mode 100644 index 0000000..dc6845a --- /dev/null +++ b/terrain/paints/desert_sand_displacement.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bda6bc2f9922061f8537cfc90387f1dae6165bebcac4f27d78884b5ffac8eb84 +size 133165 diff --git a/terrain/paints/desert_sand_displacement.png.import b/terrain/paints/desert_sand_displacement.png.import new file mode 100644 index 0000000..82b5ebc --- /dev/null +++ b/terrain/paints/desert_sand_displacement.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bdacir1igfinb" +path="res://.godot/imported/desert_sand_displacement.png-de6822961a581feed0d45f5f34fbb048.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://terrain/paints/desert_sand_displacement.png" +dest_files=["res://.godot/imported/desert_sand_displacement.png-de6822961a581feed0d45f5f34fbb048.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/terrain/paints/desert_sand_normal.png b/terrain/paints/desert_sand_normal.png new file mode 100644 index 0000000..90c96b8 --- /dev/null +++ b/terrain/paints/desert_sand_normal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:97baa2a6fc1773429f1a68504b65e1d78b3ae078fb457f3d5798493279c59dd8 +size 547227 diff --git a/terrain/paints/desert_sand_normal.png.import b/terrain/paints/desert_sand_normal.png.import new file mode 100644 index 0000000..3a23fa6 --- /dev/null +++ b/terrain/paints/desert_sand_normal.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c40cc5b5sq4yu" +path="res://.godot/imported/desert_sand_normal.png-4882d77c1942a502a8d07cd8761a392c.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://terrain/paints/desert_sand_normal.png" +dest_files=["res://.godot/imported/desert_sand_normal.png-4882d77c1942a502a8d07cd8761a392c.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/terrain/paints/desert_sand_roughness.png b/terrain/paints/desert_sand_roughness.png new file mode 100644 index 0000000..38e1172 --- /dev/null +++ b/terrain/paints/desert_sand_roughness.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ee3bc561047543c235f7763dd1a3dedd70bf9dd1c59168189873b046c899f5b +size 186636 diff --git a/terrain/paints/desert_sand_roughness.png.import b/terrain/paints/desert_sand_roughness.png.import new file mode 100644 index 0000000..3ba225d --- /dev/null +++ b/terrain/paints/desert_sand_roughness.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bwkcsnjetn5wr" +path="res://.godot/imported/desert_sand_roughness.png-0c32daf878e9b29d36631441877f21ac.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://terrain/paints/desert_sand_roughness.png" +dest_files=["res://.godot/imported/desert_sand_roughness.png-0c32daf878e9b29d36631441877f21ac.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/terrain/paints/desert_sand_terrain_paint.res b/terrain/paints/desert_sand_terrain_paint.res new file mode 100644 index 0000000..e60460e --- /dev/null +++ b/terrain/paints/desert_sand_terrain_paint.res @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c1908a2b3087d64658ebe340148554aa109658b52c1fbf662d340dec961f36a6 +size 293 diff --git a/terrain/paints/dry_mud_albedo.png b/terrain/paints/dry_mud_albedo.png new file mode 100644 index 0000000..6cb95b2 --- /dev/null +++ b/terrain/paints/dry_mud_albedo.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a2959f3617ed501b38b80af6349507578e1f76984598ae3943178f809a1d99b +size 1073364 diff --git a/terrain/paints/dry_mud_albedo.png.import b/terrain/paints/dry_mud_albedo.png.import new file mode 100644 index 0000000..e09d798 --- /dev/null +++ b/terrain/paints/dry_mud_albedo.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://eqbk8dx3px02" +path="res://.godot/imported/dry_mud_albedo.png-6844f23cea910070ff2cf0d2e02e4e06.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://terrain/paints/dry_mud_albedo.png" +dest_files=["res://.godot/imported/dry_mud_albedo.png-6844f23cea910070ff2cf0d2e02e4e06.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/terrain/paints/dry_mud_displacement.png b/terrain/paints/dry_mud_displacement.png new file mode 100644 index 0000000..b33f758 --- /dev/null +++ b/terrain/paints/dry_mud_displacement.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ec39bdd368da7aaed43273028ea07880f9f156f3b0f6624d6718f1ca9632761 +size 177014 diff --git a/terrain/paints/dry_mud_displacement.png.import b/terrain/paints/dry_mud_displacement.png.import new file mode 100644 index 0000000..5390a1d --- /dev/null +++ b/terrain/paints/dry_mud_displacement.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bwqtubithbfsy" +path="res://.godot/imported/dry_mud_displacement.png-84ac0ae4e00848577ccfe89d2c4787e8.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://terrain/paints/dry_mud_displacement.png" +dest_files=["res://.godot/imported/dry_mud_displacement.png-84ac0ae4e00848577ccfe89d2c4787e8.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/terrain/paints/dry_mud_normal.png b/terrain/paints/dry_mud_normal.png new file mode 100644 index 0000000..2eb62e3 --- /dev/null +++ b/terrain/paints/dry_mud_normal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ac5cdf2b5857c5497e39d0e49c074b601fbf9e5e23ca507ba1915bd190be6ba +size 669314 diff --git a/terrain/paints/dry_mud_normal.png.import b/terrain/paints/dry_mud_normal.png.import new file mode 100644 index 0000000..0c6e5c3 --- /dev/null +++ b/terrain/paints/dry_mud_normal.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c86r5niid1hp1" +path="res://.godot/imported/dry_mud_normal.png-6211d1992b291d2e0174ec9de201218d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://terrain/paints/dry_mud_normal.png" +dest_files=["res://.godot/imported/dry_mud_normal.png-6211d1992b291d2e0174ec9de201218d.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/terrain/paints/dry_mud_roughness.png b/terrain/paints/dry_mud_roughness.png new file mode 100644 index 0000000..492f5b4 --- /dev/null +++ b/terrain/paints/dry_mud_roughness.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:419427d9102eb71e2bfc4cca2b26ab67787c24811bce9efc0b9889f9a8c915b5 +size 296976 diff --git a/terrain/paints/dry_mud_roughness.png.import b/terrain/paints/dry_mud_roughness.png.import new file mode 100644 index 0000000..b513027 --- /dev/null +++ b/terrain/paints/dry_mud_roughness.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://7xnkstxa6q65" +path="res://.godot/imported/dry_mud_roughness.png-35dfe15111e09484a06efd2f6e55b73b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://terrain/paints/dry_mud_roughness.png" +dest_files=["res://.godot/imported/dry_mud_roughness.png-35dfe15111e09484a06efd2f6e55b73b.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/terrain/paints/dry_mud_terrain_paint.res b/terrain/paints/dry_mud_terrain_paint.res new file mode 100644 index 0000000..e6ff33e --- /dev/null +++ b/terrain/paints/dry_mud_terrain_paint.res @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:555af3c288502203b9fa4b8a71f5acdb273a988262a0bffb929a218540158561 +size 289 diff --git a/terrain/paints/terrain_paint.gd b/terrain/paints/terrain_paint.gd new file mode 100644 index 0000000..450acfa --- /dev/null +++ b/terrain/paints/terrain_paint.gd @@ -0,0 +1,13 @@ +class_name TerrainPaint extends Resource + +## +## Terrain albedo map data. +## +@export +var albedo_map: Texture2D = null + +## +## Terrain normal map data. +## +@export +var normal_map: Texture2D = null diff --git a/terrain/terrain.gdshader b/terrain/terrain.gdshader new file mode 100644 index 0000000..1985d01 --- /dev/null +++ b/terrain/terrain.gdshader @@ -0,0 +1,57 @@ +shader_type spatial; + +const int MAP_COUNT = 4; + +uniform sampler2D[MAP_COUNT] ALBEDO_MAPS; + +uniform float MAX_HEIGHT = 100.0; + +uniform sampler2D[MAP_COUNT] NORMAL_MAPS; + +uniform vec2 SIZE; + +uniform sampler2D TERRAIN_MAP : hint_default_transparent, repeat_disable; + +void fragment() { + vec2 uv = UV * (SIZE / 2.0); + vec2 uv_alt = uv * -0.5; + vec3 splat_map = texture(TERRAIN_MAP, UV).rgb; + float blank = clamp(1.0 - splat_map.r - splat_map.g - splat_map.b, 0.0, 1.0); + + ALBEDO = blank * 0.5 * (texture(ALBEDO_MAPS[0], uv).rgb + texture(ALBEDO_MAPS[0], uv_alt).rgb); + + for (int i = 0; i < (MAP_COUNT - 1); i += 1) { + int map_index = i + 1; + + ALBEDO += splat_map[i] * 0.5 * (texture(ALBEDO_MAPS[map_index], uv).rgb + + texture(ALBEDO_MAPS[map_index], uv_alt).rgb); + } + + NORMAL_MAP = blank * 0.5 * + (texture(NORMAL_MAPS[0], uv).rgb + texture(NORMAL_MAPS[0], uv_alt).rgb); + + for (int i = 0; i < (MAP_COUNT - 1); i += 1) { + int map_index = i + 1; + + NORMAL_MAP += splat_map[i] * 0.5 * (texture(NORMAL_MAPS[map_index], uv).rgb + + texture(NORMAL_MAPS[map_index], uv_alt).rgb); + } +} + +float height(vec2 uv) { + return MAX_HEIGHT * texture(TERRAIN_MAP, uv).a; +} + +void vertex() { + VERTEX.y = height(UV); + + vec2 texel_size = UV / SIZE; + + vec4 h = vec4( + height(UV + (texel_size * vec2(0, -1))), + height(UV + (texel_size * vec2(-1, 0))), + height(UV + (texel_size * vec2( 1, 0))), + height(UV + (texel_size * vec2( 0, 1)))); + + NORMAL = normalize(vec3(h.y - h.z, 2.0, h.x - h.w)); +} diff --git a/terrain/terrain_instance_3d.gd b/terrain/terrain_instance_3d.gd new file mode 100644 index 0000000..6112823 --- /dev/null +++ b/terrain/terrain_instance_3d.gd @@ -0,0 +1,87 @@ +class_name TerrainInstance3D extends GeometryInstance3D + +## +## Identifier constant for a paint slot channel. +## +enum PaintSlot { + ERASE, + RED, + GREEN, + BLUE, +} + +const _DETAIL := 2 + +var _albedo_map_textures: Array[Texture2D] = [null, null, null, null] + +var _material := ShaderMaterial.new() + +var _normal_map_textures: Array[Texture2D] = [null, null, null, null] + +var _mesh := PlaneMesh.new() + +## +## The height scale range that is used to determine the minimums and maximums of the terrain map. +## +@export +var height_scale := 100.0: + get: + return height_scale + + set(value): + _material.set_shader_parameter("MAX_HEIGHT", value) + + height_scale = max(value, 0.0) + +var _size := Vector2i.ZERO + +func _init() -> void: + _material.shader = preload("res://terrain/terrain.gdshader") + + RenderingServer.instance_set_base(get_instance(), _mesh) + _mesh.surface_set_material(0, _material) + +## +## Returns the size of the terrain mesh (as in-engine units). +## +func get_size() -> Vector2i: + return _size + +## +## Attempts to resize the terrain to be equal to [code]size[/code] (in-engine units), with +## [code]Vector2i.ONE[/code] as the minimum size. +## +func resize(size: Vector2i) -> void: + var width := maxi(size.x, 1) + var height := maxi(size.y, 1) + + if (width != _size.x) or (height != _size.y): + _mesh.subdivide_width = width * _DETAIL + _mesh.subdivide_depth = height * _DETAIL + _mesh.size = size + + _material.set_shader_parameter("SIZE", Vector2(size)) + + _size = size + +## +## Updates the paint used by the paint channel identified by [code]paint_slot[/code] to +## [code]terrain_paint[/code]. +## +func update_paint(paint_slot: PaintSlot, paint: TerrainPaint) -> void: + if paint == null: + _albedo_map_textures[paint_slot] = null + _normal_map_textures[paint_slot] = null + + else: + _albedo_map_textures[paint_slot] = paint.albedo_map + _normal_map_textures[paint_slot] = paint.normal_map + + _material.set_shader_parameter("ALBEDO_MAPS", _albedo_map_textures) + _material.set_shader_parameter("NORMAL_MAPS", _normal_map_textures) + +## +## Updates the terrain map to [code]terrain_map[/code]. +## +func update_terrain(terrain_map: Texture2D) -> void: + _material.set_shader_parameter("TERRAIN_MAP", terrain_map) diff --git a/terrain_cursor_emission.png b/terrain_cursor_emission.png deleted file mode 100644 index bdb6d4e..0000000 --- a/terrain_cursor_emission.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:495e7874b1a3d3c20fbf8644f5ca3242bea67ffe23775d349598876dd130df69 -size 27850 diff --git a/terrain_cursor_emission.png.import b/terrain_cursor_emission.png.import deleted file mode 100644 index 96764a5..0000000 --- a/terrain_cursor_emission.png.import +++ /dev/null @@ -1,36 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://dmbae0p1ujwcv" -path.s3tc="res://.godot/imported/terrain_cursor_emission.png-242c595842e9c0210b5a4ae1147e42e6.s3tc.ctex" -path.etc2="res://.godot/imported/terrain_cursor_emission.png-242c595842e9c0210b5a4ae1147e42e6.etc2.ctex" -metadata={ -"imported_formats": ["s3tc", "etc2"], -"vram_texture": true -} - -[deps] - -source_file="res://terrain_cursor_emission.png" -dest_files=["res://.godot/imported/terrain_cursor_emission.png-242c595842e9c0210b5a4ae1147e42e6.s3tc.ctex", "res://.godot/imported/terrain_cursor_emission.png-242c595842e9c0210b5a4ae1147e42e6.etc2.ctex"] - -[params] - -compress/mode=2 -compress/lossy_quality=0.7 -compress/hdr_compression=1 -compress/bptc_ldr=0 -compress/normal_map=0 -compress/channel_pack=0 -mipmaps/generate=true -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=true -process/premult_alpha=true -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=0 diff --git a/terrain_instance_3d.gd b/terrain_instance_3d.gd deleted file mode 100644 index f70fcaa..0000000 --- a/terrain_instance_3d.gd +++ /dev/null @@ -1,169 +0,0 @@ -@tool -class_name TerrainInstance3D extends GeometryInstance3D - -const _DETAIL := 2 - -var _mesh := PlaneMesh.new() - -var _material := ShaderMaterial.new() - -## -## -## -@export -var size: Vector2i = Vector2i.ZERO: - get: - return size - - set(value): - var width := maxi(value.x, 0) - var height := maxi(value.y, 0) - - if (width != size.x) or (height != size.y): - if (width == 0) and (height == 0): - RenderingServer.instance_set_base(self.get_instance(), RID()) - - else: - self._mesh.subdivide_width = width * _DETAIL - self._mesh.subdivide_depth = height * _DETAIL - self._mesh.size = value - - self._material.set_shader_parameter("SIZE", Vector2(value)) - RenderingServer.instance_set_base(self.get_instance(), self._mesh) - - size = value - -## -## -## -@export -var layer_1_albedo: Texture2D = null: - get: - return layer_1_albedo - - set(value): - self._material.set_shader_parameter("LAYER_1_ALBEDO", value) - - layer_1_albedo = value - -## -## -## -@export -var layer_1_normal_map: Texture2D = null: - get: - return layer_1_normal_map - - set(value): - self._material.set_shader_parameter("LAYER_1_NORMAL_MAP", value) - - layer_1_normal_map = value - -## -## -## -@export -var layer_2_albedo: Texture2D = null: - get: - return layer_2_albedo - - set(value): - self._material.set_shader_parameter("LAYER_2_ALBEDO", value) - - layer_2_albedo = value - -## -## -## -@export -var layer_2_normal_map: Texture2D = null: - get: - return layer_2_normal_map - - set(value): - self._material.set_shader_parameter("LAYER_2_NORMAL_MAP", value) - - layer_2_normal_map = value - -## -## -## -@export -var layer_3_albedo: Texture2D = null: - get: - return layer_3_albedo - - set(value): - self._material.set_shader_parameter("LAYER_3_ALBEDO", value) - - layer_3_albedo = value - -## -## -## -@export -var layer_3_normal_map: Texture2D = null: - get: - return layer_3_normal_map - - set(value): - self._material.set_shader_parameter("LAYER_3_NORMAL_MAP", value) - - layer_3_normal_map = value - -## -## -## -@export -var layer_4_albedo: Texture2D = null: - get: - return layer_4_albedo - - set(value): - self._material.set_shader_parameter("LAYER_4_ALBEDO", value) - - layer_4_albedo = value - -## -## -## -@export -var layer_4_normal_map: Texture2D = null: - get: - return layer_4_normal_map - - set(value): - self._material.set_shader_parameter("LAYER_4_NORMAL_MAP", value) - - layer_4_normal_map = value - -## -## -## -@export -var terrain_map: Texture2D = null: - get: - return terrain_map - - set(value): - self._material.set_shader_parameter("TERRAIN_MAP", value) - - terrain_map = value - -## -## -## -@export -var max_height := 100.0: - get: - return max_height - - set(value): - self._material.set_shader_parameter("MAX_HEIGHT", value) - - max_height = max(value, 0.0) - -func _init() -> void: - self._material.shader = preload("res://terrain_shader.gdshader") - - self._mesh.surface_set_material(0, self._material) diff --git a/terrain_shader.gdshader b/terrain_shader.gdshader deleted file mode 100644 index dfac4b8..0000000 --- a/terrain_shader.gdshader +++ /dev/null @@ -1,58 +0,0 @@ -shader_type spatial; - -uniform sampler2D LAYER_1_ALBEDO : hint_default_black; - -uniform sampler2D LAYER_1_NORMAL_MAP : hint_default_black; - -uniform sampler2D LAYER_2_ALBEDO : hint_default_black; - -uniform sampler2D LAYER_2_NORMAL_MAP : hint_default_black; - -uniform sampler2D LAYER_3_ALBEDO : hint_default_black; - -uniform sampler2D LAYER_3_NORMAL_MAP : hint_default_black; - -uniform sampler2D LAYER_4_ALBEDO : hint_default_black; - -uniform sampler2D LAYER_4_NORMAL_MAP : hint_default_black; - -uniform float MAX_HEIGHT = 100.0; - -uniform vec2 SIZE; - -uniform sampler2D TERRAIN_MAP : hint_default_transparent, repeat_disable; - -void fragment() { - vec2 uv = UV * SIZE; - vec2 uv_alt = uv * -0.25; - vec3 splat_map = texture(TERRAIN_MAP, UV).rgb; - float blank = clamp(1.0 - splat_map.r - splat_map.g - splat_map.b, 0.0, 1.0); - - ALBEDO = blank * 0.5 * (texture(LAYER_1_ALBEDO, uv).rgb + texture(LAYER_1_ALBEDO, uv_alt).rgb); - ALBEDO += splat_map.r * 0.5 * (texture(LAYER_2_ALBEDO, uv).rgb + texture(LAYER_2_ALBEDO, uv_alt).rgb); - ALBEDO += splat_map.g * 0.5 * (texture(LAYER_3_ALBEDO, uv).rgb + texture(LAYER_3_ALBEDO, uv_alt).rgb); - ALBEDO += splat_map.b * 0.5 * (texture(LAYER_4_ALBEDO, uv).rgb + texture(LAYER_4_ALBEDO, uv_alt).rgb); - - NORMAL_MAP = blank * 0.5 * (texture(LAYER_1_NORMAL_MAP, uv).rgb + texture(LAYER_1_NORMAL_MAP, uv_alt).rgb); - NORMAL_MAP += splat_map.r * 0.5 * (texture(LAYER_1_NORMAL_MAP, uv).rgb + texture(LAYER_2_NORMAL_MAP, uv_alt).rgb); - NORMAL_MAP += splat_map.g * 0.5 * (texture(LAYER_2_NORMAL_MAP, uv).rgb + texture(LAYER_3_NORMAL_MAP, uv_alt).rgb); - NORMAL_MAP += splat_map.b * 0.5 * (texture(LAYER_3_NORMAL_MAP, uv).rgb + texture(LAYER_4_NORMAL_MAP, uv_alt).rgb); -} - -float height(vec2 uv) { - return MAX_HEIGHT * texture(TERRAIN_MAP, uv).a; -} - -void vertex() { - VERTEX.y = height(UV); - - vec2 texel_size = UV / SIZE; - - vec4 h = vec4( - height(UV + (texel_size * vec2(0, -1))), - height(UV + (texel_size * vec2(-1, 0))), - height(UV + (texel_size * vec2( 1, 0))), - height(UV + (texel_size * vec2( 0, 1)))); - - NORMAL = normalize(vec3(h.y - h.z, 2.0, h.x - h.w)); -} diff --git a/user_interface/button_selection.gd b/user_interface/button_selection.gd new file mode 100644 index 0000000..d94a691 --- /dev/null +++ b/user_interface/button_selection.gd @@ -0,0 +1,75 @@ +@tool +class_name ItemSelection extends HFlowContainer + +## +## An item has been selected via GUI selection or [method select_item]. +## +signal item_selected(index: int) + +var _button_group := ButtonGroup.new() + +## +## Number of items in the selection. +## +var item_count: int: + get: + return _button_group.get_buttons().size() + +func _get_configuration_warnings() -> PackedStringArray: + return PackedStringArray() + +## +## Adds a new item with no text and only [code]icon[/code] as the icon to the selection. +## +func add_icon_item(icon: Texture2D) -> void: + var child_count := get_child_count() + var button := Button.new() + + button.icon = icon + button.icon_alignment = HORIZONTAL_ALIGNMENT_CENTER + button.toggle_mode = true + button.button_group = _button_group + button.button_pressed = child_count == 0 + + button.pressed.connect(func () -> void: select_item(child_count)) + add_child(button) + +## +## Returns the icon used by the item at [code]index[/code]. +## +## An assertion is raised if [code]index[/code] is out of bounds from the item count. +## +func get_item_icon(index: int) -> Texture2D: + var buttons := _button_group.get_buttons() + + assert(index < buttons.size(), "index out of range") + + var button := buttons[index] as Button + + return null if (button == null) else button.icon + +## +## Returns the currently selected item index or [code]-1[/code] if no item is selected. +## +func get_selected_item() -> int: + var pressed_button := _button_group.get_pressed_button() + + return -1 if (pressed_button == null) else pressed_button.get_index() + +## +## Selects the item at [code]index[/code], emitting [signal item_selected] at the end. +## +## An assertion is raised if [code]index[/code] is out of bounds from the item count. +## +func select_item(index: int) -> void: + var buttons := _button_group.get_buttons() + + assert(index < buttons.size(), "index out of range") + + var pressed_button := _button_group.get_pressed_button() + + if pressed_button != null: + pressed_button.set_pressed_no_signal(false) + + buttons[index].set_pressed_no_signal(true) + item_selected.emit(index) diff --git a/user_interface/screen_cursor.png b/user_interface/screen_cursor.png new file mode 100644 index 0000000..25806e0 --- /dev/null +++ b/user_interface/screen_cursor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9b8dab1e2c7e5332869da473f48344d1bc24f246b00b6c96f00fde340b9596c2 +size 22518 diff --git a/user_interface/screen_cursor.png.import b/user_interface/screen_cursor.png.import new file mode 100644 index 0000000..bef1a74 --- /dev/null +++ b/user_interface/screen_cursor.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://crt8tmxbpu1hl" +path="res://.godot/imported/screen_cursor.png-46ebd33cd7dfb4c0211a698e6d39e483.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://user_interface/screen_cursor.png" +dest_files=["res://.godot/imported/screen_cursor.png-46ebd33cd7dfb4c0211a698e6d39e483.ctex"] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1