Compare commits
No commits in common. "a296f010a22f300d55fef02860b23a207aa4d95f" and "b06837f819d4a4008be597e40567ca19d916d3ce" have entirely different histories.
a296f010a2
...
b06837f819
BIN
editor.scn (Stored with Git LFS)
BIN
editor.scn (Stored with Git LFS)
Binary file not shown.
|
@ -1,5 +1,7 @@
|
|||
class_name EditableTerrain extends Node
|
||||
|
||||
const _DEFAULT_COLOR := Color(0.0, 0.0, 0.0, 0.5)
|
||||
|
||||
##
|
||||
## Blank sample value.
|
||||
##
|
||||
|
@ -7,6 +9,14 @@ const BLANK := Color(0.0, 0.0, 0.0, 0.0)
|
|||
|
||||
var _image := Image.create(1, 1, false, Image.FORMAT_RGBAF)
|
||||
|
||||
##
|
||||
## Terrain texture channel mixing values.
|
||||
##
|
||||
## Affects the color that terrain is mixed into during editing operations like [method paint].
|
||||
##
|
||||
@export
|
||||
var channels := Vector3.ZERO
|
||||
|
||||
##
|
||||
## Tracked [TerrainInstance3D] to echo all terrain editing changes to.
|
||||
##
|
||||
|
@ -23,6 +33,7 @@ var instance: TerrainInstance3D = null:
|
|||
##
|
||||
## Width and height of the editable terrain in units.
|
||||
##
|
||||
@export
|
||||
var size := Vector2i.ZERO:
|
||||
get:
|
||||
return size
|
||||
|
@ -36,162 +47,51 @@ var size := Vector2i.ZERO:
|
|||
|
||||
size = value
|
||||
|
||||
func _get_draw_area(point: Vector2i, mask: Image, scale: float) -> Rect2i:
|
||||
# Convert worldspace point to image-space coordinates for brush and calculate drawable area.
|
||||
var mask_size := mask.get_size()
|
||||
var scaled_mask_size := mask_size * scale
|
||||
|
||||
return Rect2i(Vector2i.ZERO, size).intersection(
|
||||
Rect2i((point - Vector2i(scaled_mask_size * 0.5)) + Vector2i(size * 0.5), scaled_mask_size))
|
||||
|
||||
func _init() -> void:
|
||||
clear(BLANK)
|
||||
_image.fill(_DEFAULT_COLOR)
|
||||
|
||||
##
|
||||
## Clears the image to the value of [code]clear_color[/code].
|
||||
## Mixes the texture [member channels] and raises the terrain by [code]elevation_level[/code] in a
|
||||
## brush pattern masked by [code]brush_mask[/code] to the worldspace [code]point[/code] with
|
||||
## [code]brush_intensity[/code] as the intensity of the applied effects for a single paint.
|
||||
##
|
||||
func clear(clear_color: Color) -> void:
|
||||
_image.fill(clear_color)
|
||||
## For continuous painting, a delta value may be supplied to [code]brush_intensity[/code] to avoid
|
||||
## issues with variable-rate paint updates.
|
||||
##
|
||||
func paint(point: Vector2i, elevation_level: float,
|
||||
brush_mask: Image, brush_scale: float, brush_intensity: float) -> void:
|
||||
|
||||
##
|
||||
##
|
||||
##
|
||||
func erase(point: Vector2i, mask: Image, scale: float, intensity: float, delta: float) -> void:
|
||||
var draw_area := _get_draw_area(point, mask, scale)
|
||||
# Convert worldspace point to image-space coordinates for brush and calculate drawable area.
|
||||
var brush_mask_size := brush_mask.get_size()
|
||||
var brush_size := brush_mask_size * brush_scale
|
||||
|
||||
var draw_area := Rect2i(Vector2i.ZERO, size).intersection(
|
||||
Rect2i((point - Vector2i(brush_size * 0.5)) + Vector2i(size * 0.5), brush_size))
|
||||
|
||||
if draw_area.has_area():
|
||||
var mask_ratio := mask.get_size() / draw_area.size
|
||||
var scaled_brush_mask_size := brush_mask_size / draw_area.size
|
||||
|
||||
elevation_level = clampf(elevation_level, -1.0, 1.0)
|
||||
|
||||
for y in draw_area.size.y:
|
||||
var brush_mask_y := int(y * mask_ratio.y)
|
||||
var brush_mask_y := int(y * scaled_brush_mask_size.y)
|
||||
|
||||
for x in draw_area.size.x:
|
||||
var terrain_map_coord := draw_area.position + Vector2i(x, y)
|
||||
var pixel := _image.get_pixelv(terrain_map_coord)
|
||||
|
||||
var mask_intensity_delta := intensity *\
|
||||
delta * mask.get_pixel(int(x * mask_ratio.x), brush_mask_y).a
|
||||
var mask := brush_mask.get_pixel(
|
||||
int(x * scaled_brush_mask_size.x), brush_mask_y).a
|
||||
|
||||
var mask_intensity := brush_intensity * mask
|
||||
|
||||
_image.set_pixelv(terrain_map_coord, Color(
|
||||
lerpf(pixel.r, 0.0, mask_intensity_delta),
|
||||
lerpf(pixel.g, 0.0, mask_intensity_delta),
|
||||
lerpf(pixel.b, 0.0, mask_intensity_delta),
|
||||
pixel.a))
|
||||
lerpf(pixel.r, channels.x, mask_intensity),
|
||||
lerpf(pixel.g, channels.y, mask_intensity),
|
||||
lerpf(pixel.b, channels.z, mask_intensity),
|
||||
lerpf(pixel.a, pixel.a + (elevation_level * mask), brush_intensity)))
|
||||
|
||||
instance.terrain_map.update(_image)
|
||||
|
||||
##
|
||||
##
|
||||
##
|
||||
func lower(point: Vector2i, mask: Image, scale: float, intensity: float, delta: float) -> void:
|
||||
var draw_area := _get_draw_area(point, mask, scale)
|
||||
|
||||
if draw_area.has_area():
|
||||
var mask_ratio := mask.get_size() / draw_area.size
|
||||
|
||||
for y in draw_area.size.y:
|
||||
var brush_mask_y := int(y * mask_ratio.y)
|
||||
|
||||
for x in draw_area.size.x:
|
||||
var terrain_map_coord := draw_area.position + Vector2i(x, y)
|
||||
var pixel := _image.get_pixelv(terrain_map_coord)
|
||||
|
||||
_image.set_pixelv(terrain_map_coord, Color(pixel.r, pixel.g, pixel.b,
|
||||
lerpf(pixel.a, pixel.a - (intensity *
|
||||
mask.get_pixel(int(x * mask_ratio.x), brush_mask_y).a), delta)))
|
||||
|
||||
instance.terrain_map.update(_image)
|
||||
|
||||
##
|
||||
##
|
||||
##
|
||||
func paint_blue(point: Vector2i, mask: Image, scale: float, intensity: float, delta: float) -> void:
|
||||
var draw_area := _get_draw_area(point, mask, scale)
|
||||
|
||||
if draw_area.has_area():
|
||||
var mask_ratio := mask.get_size() / draw_area.size
|
||||
|
||||
for y in draw_area.size.y:
|
||||
var brush_mask_y := int(y * mask_ratio.y)
|
||||
|
||||
for x in draw_area.size.x:
|
||||
var terrain_map_coord := draw_area.position + Vector2i(x, y)
|
||||
var pixel := _image.get_pixelv(terrain_map_coord)
|
||||
|
||||
_image.set_pixelv(terrain_map_coord, Color(
|
||||
pixel.r, pixel.g, lerpf(pixel.b, intensity, delta *\
|
||||
mask.get_pixel(int(x * mask_ratio.x), brush_mask_y).a),
|
||||
pixel.a))
|
||||
|
||||
instance.terrain_map.update(_image)
|
||||
|
||||
##
|
||||
##
|
||||
##
|
||||
func paint_green(point: Vector2i, mask: Image, scale: float, intensity: float, delta: float) -> void:
|
||||
var draw_area := _get_draw_area(point, mask, scale)
|
||||
|
||||
if draw_area.has_area():
|
||||
var mask_ratio := mask.get_size() / draw_area.size
|
||||
|
||||
for y in draw_area.size.y:
|
||||
var brush_mask_y := int(y * mask_ratio.y)
|
||||
|
||||
for x in draw_area.size.x:
|
||||
var terrain_map_coord := draw_area.position + Vector2i(x, y)
|
||||
var pixel := _image.get_pixelv(terrain_map_coord)
|
||||
|
||||
_image.set_pixelv(terrain_map_coord, Color(
|
||||
pixel.r, lerpf(pixel.g, intensity, delta *\
|
||||
mask.get_pixel(int(x * mask_ratio.x), brush_mask_y).a),
|
||||
pixel.b, pixel.a))
|
||||
|
||||
instance.terrain_map.update(_image)
|
||||
|
||||
##
|
||||
##
|
||||
##
|
||||
func paint_red(point: Vector2i, mask: Image, scale: float, intensity: float, delta: float) -> void:
|
||||
var draw_area := _get_draw_area(point, mask, scale)
|
||||
|
||||
if draw_area.has_area():
|
||||
var mask_ratio := mask.get_size() / draw_area.size
|
||||
|
||||
for y in draw_area.size.y:
|
||||
var brush_mask_y := int(y * mask_ratio.y)
|
||||
|
||||
for x in draw_area.size.x:
|
||||
var terrain_map_coord := draw_area.position + Vector2i(x, y)
|
||||
var pixel := _image.get_pixelv(terrain_map_coord)
|
||||
|
||||
_image.set_pixelv(terrain_map_coord, Color(
|
||||
lerpf(pixel.r, intensity, delta *\
|
||||
mask.get_pixel(int(x * mask_ratio.x), brush_mask_y).a),
|
||||
pixel.g, pixel.b, pixel.a))
|
||||
|
||||
instance.terrain_map.update(_image)
|
||||
|
||||
##
|
||||
##
|
||||
##
|
||||
func raise(point: Vector2i, mask: Image, scale: float, intensity: float, delta: float) -> void:
|
||||
var draw_area := _get_draw_area(point, mask, scale)
|
||||
|
||||
if draw_area.has_area():
|
||||
var mask_ratio := mask.get_size() / draw_area.size
|
||||
|
||||
for y in draw_area.size.y:
|
||||
var brush_mask_y := int(y * mask_ratio.y)
|
||||
|
||||
for x in draw_area.size.x:
|
||||
var terrain_map_coord := draw_area.position + Vector2i(x, y)
|
||||
var pixel := _image.get_pixelv(terrain_map_coord)
|
||||
|
||||
_image.set_pixelv(terrain_map_coord, Color(pixel.r, pixel.g, pixel.b,
|
||||
lerpf(pixel.a, pixel.a + (intensity *
|
||||
mask.get_pixel(int(x * mask_ratio.x), brush_mask_y).a), delta)))
|
||||
|
||||
instance.terrain_map.update(_image)
|
||||
instance.terrain_map.update(_image)
|
||||
|
||||
##
|
||||
## Samples the color value in the editable terrain at the worldspace [code]point[/code], returning
|
||||
|
@ -209,23 +109,42 @@ func sample(point: Vector2i) -> Color:
|
|||
return BLANK
|
||||
|
||||
##
|
||||
## Mixes the texture [member channels] and smooths the terrain to [code]smoothing_level[/code] in a
|
||||
## brush pattern masked by [code]brush_mask[/code] to the worldspace [code]point[/code] with
|
||||
## [code]brush_intensity[/code] as the intensity of the applied effects for a single paint.
|
||||
##
|
||||
## For continuous smoothing, a delta value may be supplied to [code]brush_intensity[/code] to avoid
|
||||
## issues with variable-rate smooth updates.
|
||||
##
|
||||
func smooth(point: Vector2i, mask: Image, scale: float, level: float, delta: float) -> void:
|
||||
var draw_area := _get_draw_area(point, mask, scale)
|
||||
func smooth(point: Vector2i, smoothing_level: float,
|
||||
brush_mask: Image, brush_scale: float, brush_intensity: float) -> void:
|
||||
|
||||
# Convert worldspace point to image-space coordinates for brush and calculate drawable area.
|
||||
var brush_mask_size := brush_mask.get_size()
|
||||
var brush_size := brush_mask_size * brush_scale
|
||||
var terrain_map_size := _image.get_size()
|
||||
|
||||
var draw_area := Rect2i(Vector2i.ZERO, terrain_map_size).intersection(
|
||||
Rect2i((point - Vector2i(brush_size * 0.5)) +\
|
||||
Vector2i(terrain_map_size * 0.5), brush_size))
|
||||
|
||||
if draw_area.has_area():
|
||||
var mask_ratio := mask.get_size() / draw_area.size
|
||||
var scaled_brush_mask_size := brush_mask_size / draw_area.size
|
||||
|
||||
for y in draw_area.size.y:
|
||||
var brush_mask_y := int(y * mask_ratio.y)
|
||||
var brush_mask_y := int(y * scaled_brush_mask_size.y)
|
||||
|
||||
for x in draw_area.size.x:
|
||||
var terrain_map_coord := draw_area.position + Vector2i(x, y)
|
||||
var pixel := _image.get_pixelv(terrain_map_coord)
|
||||
|
||||
_image.set_pixelv(terrain_map_coord, Color(pixel.r, pixel.g, pixel.b,
|
||||
lerpf(pixel.a, level, delta * mask.get_pixel(
|
||||
int(x * mask_ratio.x), brush_mask_y).a)))
|
||||
var mask_intensity := brush_intensity * brush_mask.get_pixel(
|
||||
int(x * scaled_brush_mask_size.x), brush_mask_y).a
|
||||
|
||||
_image.set_pixelv(terrain_map_coord, Color(
|
||||
lerpf(pixel.r, channels.x, mask_intensity),
|
||||
lerpf(pixel.g, channels.y, mask_intensity),
|
||||
lerpf(pixel.b, channels.z, mask_intensity),
|
||||
lerpf(pixel.a, smoothing_level, mask_intensity)))
|
||||
|
||||
instance.terrain_map.update(_image)
|
||||
|
|
BIN
editor/menus_theme.res (Stored with Git LFS)
BIN
editor/menus_theme.res (Stored with Git LFS)
Binary file not shown.
|
@ -72,7 +72,6 @@ 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:
|
||||
|
|
Loading…
Reference in New Issue