Добавил персонажа и движение на курсор

This commit is contained in:
CoDeayant
2024-12-07 15:26:00 +05:00
parent 0e4e854cc1
commit b99f5ec797
84 changed files with 6735 additions and 1 deletions

View File

@@ -0,0 +1,38 @@
extends ImageScript
func _get_param_list():
return [
[
"Hue",
SCRIPT_PARAM_INT,
0,
[0, 360]
],
[
"Saturation",
SCRIPT_PARAM_INT,
0,
[-100, +100]
],
[
"Value",
SCRIPT_PARAM_INT,
0,
[-100, +100]
],
]
func _get_image(new_image, selection):
var pix : Color
for i in new_image.get_width():
for j in new_image.get_width():
if !selection.get_bit(i, j): continue
pix = new_image.get_pixel(i, j)
pix.h += get_param("Hue") / 360.0
pix.s *= 1.0 + get_param("Saturation") * 0.01
pix.v *= 1.0 + get_param("Value") * 0.01
new_image.set_pixel(i, j, pix)
return new_image

View File

@@ -0,0 +1,52 @@
extends ImageScript
func _get_param_list():
var default_curve = Curve.new()
default_curve.add_point(Vector2.ZERO, 1, 1)
default_curve.add_point(Vector2.ONE, 1, 1)
return [
[
"Red",
SCRIPT_PARAM_RESOURCE,
default_curve.duplicate(),
"Curve",
],
[
"Green",
SCRIPT_PARAM_RESOURCE,
default_curve.duplicate(),
"Curve",
],
[
"Blue",
SCRIPT_PARAM_RESOURCE,
default_curve.duplicate(),
"Curve",
],
[
"Alpha",
SCRIPT_PARAM_RESOURCE,
default_curve.duplicate(),
"Curve",
],
]
func _get_image(new_image, selection):
var r_curve = get_param("Red")
var g_curve = get_param("Green")
var b_curve = get_param("Blue")
var a_curve = get_param("Alpha")
var pix : Color
for i in new_image.get_width():
for j in new_image.get_width():
if !selection.get_bit(i, j): continue
pix = new_image.get_pixel(i, j)
pix.r = r_curve.sample(pix.r)
pix.g = g_curve.sample(pix.g)
pix.b = b_curve.sample(pix.b)
pix.a = a_curve.sample(pix.a)
new_image.set_pixel(i, j, pix)
return new_image

View File

@@ -0,0 +1,68 @@
extends ImageScript
func _get_param_list():
return [
[
"Palette Texture",
SCRIPT_PARAM_RESOURCE,
# Does not work well on gradients: doesn't consider Interp Mode and Width
# so with no proper spatial partitioning takes an eternity
# GradientTexture1D.new(),
null,
"Texture2D"
],
]
func _get_image(new_image, selection):
if get_param("Palette Texture") == null:
return new_image
var palette_img = get_param("Palette Texture").get_image()
if palette_img == null:
return new_image
var palette = {}
var pix : Color
for i in palette_img.get_width():
for j in palette_img.get_height():
pix = palette_img.get_pixel(i, j)
if pix.a > 0.01:
palette[Color(pix, 1.0)] = true
var image_width = new_image.get_width()
var image_color_mapping = {}
var nearest_color : Color
for i in new_image.get_width():
for j in new_image.get_height():
pix = new_image.get_pixel(i, j)
if image_color_mapping.has(pix):
if selection.get_bit(i, j):
new_image.set_pixel(i, j, Color(image_color_mapping[pix], pix.a))
elif selection.get_bit(i, j):
# I'll rewrite this into a proper spatial algo access later,
# bruteforce will do for now
nearest_color = Color(pick_nearest(pix, palette), 1.0)
image_color_mapping[Color(pix, 1.0)] = nearest_color
new_image.set_pixel(i, j, Color(nearest_color, pix.a))
return new_image
func pick_nearest(to : Color, from : Dictionary):
var nearest_dist := INF
var nearest : Color
var cur_dist : float
for x in from:
cur_dist = (
(x.r - to.r) * (x.r - to.r)
+ (x.g - to.g) * (x.g - to.g)
+ (x.b - to.b) * (x.b - to.b)
)
if cur_dist < nearest_dist:
nearest = x
nearest_dist = cur_dist
return nearest

View File

@@ -0,0 +1,87 @@
extends ImageScript
var sample_modes = [
[Vector2(0, 1), Vector2(1, 0), Vector2(-1, 0), Vector2(0, -1)],
range(8).map(func(i):return Vector2(cos(i * PI * 0.25), sin(i * PI * 0.25))),
range(16).map(func(i):return Vector2(cos(i * PI * 0.125), sin(i * PI * 0.125))),
# The following modes sample two rings around the pixel,
# resulting in a more precise thick outline around thin objects
range(16).map(func(i):return ceil((i + 1) * 0.125) * 0.5 * Vector2(cos(i * PI * 0.25), sin(i * PI * 0.25))),
range(32).map(func(i):return ceil((i + 1) * 0.0625) * 0.5 * Vector2(cos(i * PI * 0.125), sin(i * PI * 0.125))),
]
func _get_param_list():
return [
[
"Width",
SCRIPT_PARAM_INT,
1,
[1, 150]
],
[
"Color",
SCRIPT_PARAM_COLOR,
Color.BLACK
],
[
"Samples",
SCRIPT_PARAM_ENUM,
0,
["4 (Naive)", "8", "16", "4+4 (Wide Line)", "8+8 (Wide Line Ultra)"]
],
[
"Mode",
SCRIPT_PARAM_ENUM,
0,
["Outline + Image", "Just Outline"]
],
]
func _get_image(new_image, selection):
var line_color = get_param("Color")
var width = get_param("Width")
var line_only = get_param("Mode") == 1
var samples = sample_modes[get_param("Samples")]
var image_size = new_image.get_size()
var new_new_image = Image.create_from_data(
image_size.x,
image_size.y,
false,
new_image.get_format(),
new_image.get_data()
)
var pix : Color
var pix_outline_alpha := 0.0
for i in new_image.get_width():
for j in new_image.get_height():
if !selection.get_bit(i, j): continue
pix = new_image.get_pixel(i, j)
if pix.a == 1.0:
if line_only:
new_new_image.set_pixel(i, j, Color.TRANSPARENT)
continue
pix_outline_alpha = 0.0
for x in samples:
if pix_outline_alpha >= line_color.a: break
if ImageFillTools.is_out_of_bounds(Vector2(i, j) + x * width, image_size):
continue
pix_outline_alpha = max(pix_outline_alpha, min(
line_color.a,
new_image.get_pixelv(Vector2(i, j) + x * width).a
))
if pix_outline_alpha > 0.0:
if line_only:
pix = Color(line_color, pix_outline_alpha)
else:
pix = Color(line_color, pix_outline_alpha).blend(pix)
new_new_image.set_pixel(i, j, pix)
return new_new_image

View File

@@ -0,0 +1,140 @@
extends ImageScript
const ROOT2DIV2 = 0.7071
func _get_param_list():
var default_curve = Curve.new()
default_curve.add_point(Vector2(0.0, 0.5), 1, 1, Curve.TANGENT_LINEAR, Curve.TANGENT_LINEAR)
default_curve.add_point(Vector2(1.0, 0.5), 1, 1, Curve.TANGENT_LINEAR, Curve.TANGENT_LINEAR)
return [
[
"Bevel",
SCRIPT_PARAM_INT,
1,
[1, 150]
],
[
"Bevel Distance",
SCRIPT_PARAM_ENUM,
0,
["Circle", "Square", "Diamond"]
],
]
func _get_image(new_image, selection):
var image_size : Vector2i = new_image.get_size()
var closest_edge : Array[Vector2] = []
var entropy := {}
closest_edge.resize(image_size.x * image_size.y)
var pix : Color
var vec : Vector2
for i in image_size.x:
for j in image_size.y:
pix = new_image.get_pixel(i, j)
if pix.a == 0.0:
closest_edge[i + j * image_size.x] = Vector2.ZERO
else:
vec = Vector2(0, 0)
if i == 0: vec.x -= 1
if j == 0: vec.y -= 1
if i == image_size.x - 1: vec.x += 1
if j == image_size.y - 1: vec.y += 1
if vec == Vector2.ZERO:
vec = Vector2(-INF, -INF)
entropy[Vector2(i, j)] = 5
closest_edge[i + j * image_size.x] = vec
var neighbors = []
var neighbor_pos = []
var iters = 0
var closest_edge_new : Array[Vector2]
while entropy.size() > 0:
iters += 1
closest_edge_new = closest_edge.duplicate()
for pos in entropy.keys():
neighbor_pos = [
pos + Vector2.RIGHT,
pos + Vector2.DOWN,
pos + Vector2.LEFT,
pos + Vector2.UP,
]
var any_neighbor_defined = false
for x in neighbor_pos:
if closest_edge[x.x + x.y * image_size.x] != Vector2(-INF, -INF):
any_neighbor_defined = true
break
if any_neighbor_defined:
entropy.erase(pos)
neighbors = [
closest_edge[pos.x + 1 + pos.y * image_size.x]
if !entropy.has(pos + Vector2.RIGHT) else Vector2(-INF, -INF),
closest_edge[pos.x + (pos.y + 1) * image_size.x]
if !entropy.has(pos + Vector2.DOWN) else Vector2(-INF, -INF),
closest_edge[pos.x - 1 + pos.y * image_size.x]
if !entropy.has(pos + Vector2.LEFT) else Vector2(-INF, -INF),
closest_edge[pos.x + (pos.y - 1) * image_size.x]
if !entropy.has(pos + Vector2.UP) else Vector2(-INF, -INF),
]
closest_edge_new[pos.x + pos.y * image_size.x] = get_closest_edge(neighbors)
closest_edge = closest_edge_new
var bevel = get_param("Bevel")
var dist_func = [
# Three different distance calculations have their own artifacts..
func (x): return x.length_squared() > bevel * 2.0, # Circle
func (x): return max(abs(x.x), abs(x.y)) > bevel, # Square
func (x): return abs(x.x) + abs(x.y) > bevel * 2.0, # Diamond
][get_param("Bevel Distance")]
var vec3 : Vector3
var vec_len : float
var vec_dir : Vector2
for i in image_size.x:
for j in image_size.y:
vec = closest_edge[i + j * image_size.x]
if vec == Vector2.ZERO || dist_func.call(vec):
new_image.set_pixel(i, j, Color(0.5, 0.5, 1.0))
continue
vec_len = vec.length()
vec_dir = vec / vec_len
vec3 = Vector3.BACK.rotated(
Vector3(-vec_dir.y, vec_dir.x, 0.0),
PI * 0.25
)
vec3 = vec3 * Vector3(0.5, -0.5, 1.0) + Vector3(0.5, 0.5, 0.0)
new_image.set_pixel(i, j, Color(vec3.x, vec3.y, vec3.z))
return new_image
func get_closest_edge(neighbor_vecs):
var lengths = [
neighbor_vecs[0].length_squared(),
neighbor_vecs[1].length_squared(),
neighbor_vecs[2].length_squared(),
neighbor_vecs[3].length_squared(),
]
var closest_length = INF
for i in 4:
if lengths[i] < closest_length:
closest_length = lengths[i]
var result = Vector2.ZERO
var neighbor_dirs = [Vector2.RIGHT, Vector2.DOWN, Vector2.LEFT, Vector2.UP]
var coeff = 1.0
for i in 4:
if lengths[i] == closest_length:
result += neighbor_vecs[i] + neighbor_dirs[i]
return result