1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-18 17:19:50 +00:00

Format code and add static checks (#599)

* gdformat .

* Lint code - Part 1

* Format code - Part 2

* Lint code - Part 2

Trying to fix the max allowed line length errors

* Add normal_map_invert_y to the image .import files

Because of Godot 3.4

* Do not call private methods outside of the script's scope

Lint code - Part 3

* Format code - Part 3

* Fixed more line length exceeded errors - Lint code Part 3

* Export array of licenses - Lint code part 4

* Clean hint_tooltip code from Global

Removes a lot of lines of code

* Create static-checks.yml

* Fix FreeType's license
This commit is contained in:
Manolis Papadeas 2021-11-25 14:48:30 +02:00 committed by GitHub
parent 41b5db4622
commit c6b9a1fb82
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
201 changed files with 4767 additions and 3096 deletions

24
.github/workflows/static-checks.yml vendored Normal file
View file

@ -0,0 +1,24 @@
name: Static Checks 📊
on:
push:
branches-ignore:
- gh-pages
- l10n_master
pull_request:
paths:
- "addons/*"
- "src/*"
jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: pip3 install gdtoolkit
- run: gdformat --diff .
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: pip3 install gdtoolkit
- run: gdlint .

View file

@ -1,6 +1,5 @@
extends Reference extends Reference
var _shader: Shader var _shader: Shader
@ -29,7 +28,9 @@ func _convert(image: Image, colors: Array) -> PoolByteArray:
VisualServer.canvas_item_set_parent(ci_rid, canvas) VisualServer.canvas_item_set_parent(ci_rid, canvas)
var texture = ImageTexture.new() var texture = ImageTexture.new()
texture.create_from_image(image) texture.create_from_image(image)
VisualServer.canvas_item_add_texture_rect(ci_rid, Rect2(Vector2(0, 0), image.get_size()), texture) VisualServer.canvas_item_add_texture_rect(
ci_rid, Rect2(Vector2(0, 0), image.get_size()), texture
)
var mat_rid = VisualServer.material_create() var mat_rid = VisualServer.material_create()
VisualServer.material_set_shader(mat_rid, _shader.get_rid()) VisualServer.material_set_shader(mat_rid, _shader.get_rid())

View file

@ -1,15 +1,9 @@
extends Reference extends Reference
enum Error { OK = 0, EMPTY_IMAGE = 1, BAD_IMAGE_FORMAT = 2 }
enum Error { var little_endian = preload("./little_endian.gd").new()
OK = 0, var lzw = preload("./gif-lzw/lzw.gd").new()
EMPTY_IMAGE = 1,
BAD_IMAGE_FORMAT = 2
}
var little_endian = preload('./little_endian.gd').new()
var lzw = preload('./gif-lzw/lzw.gd').new()
var converter = preload("./converter.gd") var converter = preload("./converter.gd")
var last_color_table := [] var last_color_table := []
@ -24,11 +18,14 @@ func _init(_width: int, _height: int):
add_logical_screen_descriptor(_width, _height) add_logical_screen_descriptor(_width, _height)
add_application_ext("NETSCAPE", "2.0", [1, 0, 0]) add_application_ext("NETSCAPE", "2.0", [1, 0, 0])
func export_file_data() -> PoolByteArray: func export_file_data() -> PoolByteArray:
return data + PoolByteArray([0x3b]) return data + PoolByteArray([0x3b])
func add_header() -> void: func add_header() -> void:
data += 'GIF'.to_ascii() + '89a'.to_ascii() data += "GIF".to_ascii() + "89a".to_ascii()
func add_logical_screen_descriptor(width: int, height: int) -> void: func add_logical_screen_descriptor(width: int, height: int) -> void:
# not Global Color Table Flag # not Global Color Table Flag
@ -46,6 +43,7 @@ func add_logical_screen_descriptor(width: int, height: int) -> void:
data.append(background_color_index) data.append(background_color_index)
data.append(pixel_aspect_ratio) data.append(pixel_aspect_ratio)
func add_application_ext(app_iden: String, app_auth_code: String, _data: Array) -> void: func add_application_ext(app_iden: String, app_auth_code: String, _data: Array) -> void:
var extension_introducer := 0x21 var extension_introducer := 0x21
var extension_label := 0xff var extension_label := 0xff
@ -61,6 +59,7 @@ func add_application_ext(app_iden: String, app_auth_code: String, _data: Array)
data += PoolByteArray(_data) data += PoolByteArray(_data)
data.append(0) data.append(0)
# finds the image color table. Stops if the size gets larger than 256. # finds the image color table. Stops if the size gets larger than 256.
func find_color_table(image: Image) -> Dictionary: func find_color_table(image: Image) -> Dictionary:
image.lock() image.lock()
@ -72,7 +71,8 @@ func find_color_table(image: Image) -> Dictionary:
int(image_data[i]), int(image_data[i]),
int(image_data[i + 1]), int(image_data[i + 1]),
int(image_data[i + 2]), int(image_data[i + 2]),
int(image_data[i + 3])] int(image_data[i + 3])
]
if not color in result: if not color in result:
result[color] = result.size() result[color] = result.size()
if result.size() > 256: if result.size() > 256:
@ -81,25 +81,21 @@ func find_color_table(image: Image) -> Dictionary:
image.unlock() image.unlock()
return result return result
func find_transparency_color_index(color_table: Dictionary) -> int: func find_transparency_color_index(color_table: Dictionary) -> int:
for color in color_table: for color in color_table:
if color[3] == 0: if color[3] == 0:
return color_table[color] return color_table[color]
return -1 return -1
func change_colors_to_codes(image: Image,
color_palette: Dictionary, func change_colors_to_codes(image: Image, color_palette: Dictionary, transparency_color_index: int) -> PoolByteArray:
transparency_color_index: int) -> PoolByteArray:
image.lock() image.lock()
var image_data: PoolByteArray = image.get_data() var image_data: PoolByteArray = image.get_data()
var result: PoolByteArray = PoolByteArray([]) var result: PoolByteArray = PoolByteArray([])
for i in range(0, image_data.size(), 4): for i in range(0, image_data.size(), 4):
var color: Array = [ var color: Array = [image_data[i], image_data[i + 1], image_data[i + 2], image_data[i + 3]]
image_data[i],
image_data[i + 1],
image_data[i + 2],
image_data[i + 3]]
if color in color_palette: if color in color_palette:
if color[3] == 0 and transparency_color_index != -1: if color[3] == 0 and transparency_color_index != -1:
@ -108,11 +104,12 @@ func change_colors_to_codes(image: Image,
result.append(color_palette[color]) result.append(color_palette[color])
else: else:
result.append(0) result.append(0)
push_warning('change_colors_to_codes: color not found! [%d, %d, %d, %d]' % color) push_warning("change_colors_to_codes: color not found! [%d, %d, %d, %d]" % color)
image.unlock() image.unlock()
return result return result
# makes sure that the color table is at least size 4. # makes sure that the color table is at least size 4.
func make_proper_size(color_table: Array) -> Array: func make_proper_size(color_table: Array) -> Array:
var result := [] + color_table var result := [] + color_table
@ -121,15 +118,18 @@ func make_proper_size(color_table: Array) -> Array:
result.append([0, 0, 0, 0]) result.append([0, 0, 0, 0])
return result return result
func calc_delay_time(frame_delay: float) -> int: func calc_delay_time(frame_delay: float) -> int:
return int(ceil(frame_delay / 0.01)) return int(ceil(frame_delay / 0.01))
func color_table_to_indexes(colors: Array) -> PoolByteArray: func color_table_to_indexes(colors: Array) -> PoolByteArray:
var result: PoolByteArray = PoolByteArray([]) var result: PoolByteArray = PoolByteArray([])
for i in range(colors.size()): for i in range(colors.size()):
result.append(i) result.append(i)
return result return result
func add_frame(image: Image, frame_delay: float, quantizator: Script) -> int: func add_frame(image: Image, frame_delay: float, quantizator: Script) -> int:
# check if image is of good format # check if image is of good format
if image.get_format() != Image.FORMAT_RGBA8: if image.get_format() != Image.FORMAT_RGBA8:
@ -153,7 +153,8 @@ func add_frame(image: Image, frame_delay: float, quantizator: Script) -> int:
found_color_table[[0, 0, 0, 0]] = found_color_table.size() found_color_table[[0, 0, 0, 0]] = found_color_table.size()
transparency_color_index = found_color_table.size() - 1 transparency_color_index = found_color_table.size() - 1
image_converted_to_codes = change_colors_to_codes( image_converted_to_codes = change_colors_to_codes(
image, found_color_table, transparency_color_index) image, found_color_table, transparency_color_index
)
color_table = make_proper_size(found_color_table.keys()) color_table = make_proper_size(found_color_table.keys())
else: # we have to quantize the image. else: # we have to quantize the image.
var quantization_result: Array = quantizator.new().quantize(image) var quantization_result: Array = quantizator.new().quantize(image)
@ -169,21 +170,19 @@ func add_frame(image: Image, frame_delay: float, quantizator: Script) -> int:
var color_table_indexes := color_table_to_indexes(color_table) var color_table_indexes := color_table_to_indexes(color_table)
var compressed_image_result: Array = lzw.compress_lzw( var compressed_image_result: Array = lzw.compress_lzw(
image_converted_to_codes, image_converted_to_codes, color_table_indexes
color_table_indexes) )
var compressed_image_data: PoolByteArray = compressed_image_result[0] var compressed_image_data: PoolByteArray = compressed_image_result[0]
var lzw_min_code_size: int = compressed_image_result[1] var lzw_min_code_size: int = compressed_image_result[1]
add_graphic_constrol_ext(delay_time, transparency_color_index) add_graphic_constrol_ext(delay_time, transparency_color_index)
add_image_descriptor( add_image_descriptor(Vector2.ZERO, image.get_size(), color_table_bit_size(color_table))
Vector2.ZERO,
image.get_size(),
color_table_bit_size(color_table))
add_local_color_table(color_table) add_local_color_table(color_table)
add_image_data_block(lzw_min_code_size, compressed_image_data) add_image_data_block(lzw_min_code_size, compressed_image_data)
return Error.OK return Error.OK
# adds frame with last color informations # adds frame with last color informations
func add_frame_with_lci(image: Image, frame_delay: float) -> int: func add_frame_with_lci(image: Image, frame_delay: float) -> int:
# check if image is of good format # check if image is of good format
@ -194,27 +193,27 @@ func add_frame_with_lci(image: Image, frame_delay: float) -> int:
if image.is_empty(): if image.is_empty():
return Error.EMPTY_IMAGE return Error.EMPTY_IMAGE
var image_converted_to_codes: PoolByteArray = converter.new().get_similar_indexed_datas(image, last_color_table) var image_converted_to_codes: PoolByteArray = converter.new().get_similar_indexed_datas(
image, last_color_table
)
var color_table_indexes := color_table_to_indexes(last_color_table) var color_table_indexes := color_table_to_indexes(last_color_table)
var compressed_image_result: Array = lzw.compress_lzw( var compressed_image_result: Array = lzw.compress_lzw(
image_converted_to_codes, image_converted_to_codes, color_table_indexes
color_table_indexes) )
var compressed_image_data: PoolByteArray = compressed_image_result[0] var compressed_image_data: PoolByteArray = compressed_image_result[0]
var lzw_min_code_size: int = compressed_image_result[1] var lzw_min_code_size: int = compressed_image_result[1]
var delay_time := calc_delay_time(frame_delay) var delay_time := calc_delay_time(frame_delay)
add_graphic_constrol_ext(delay_time, last_transparency_index) add_graphic_constrol_ext(delay_time, last_transparency_index)
add_image_descriptor( add_image_descriptor(Vector2.ZERO, image.get_size(), color_table_bit_size(last_color_table))
Vector2.ZERO,
image.get_size(),
color_table_bit_size(last_color_table))
add_local_color_table(last_color_table) add_local_color_table(last_color_table)
add_image_data_block(lzw_min_code_size, compressed_image_data) add_image_data_block(lzw_min_code_size, compressed_image_data)
return Error.OK return Error.OK
func add_graphic_constrol_ext(_delay_time: float, tci: int = -1) -> void: func add_graphic_constrol_ext(_delay_time: float, tci: int = -1) -> void:
var extension_introducer: int = 0x21 var extension_introducer: int = 0x21
var graphic_control_label: int = 0xf9 var graphic_control_label: int = 0xf9
@ -237,14 +236,11 @@ func add_graphic_constrol_ext(_delay_time: float, tci: int = -1) -> void:
data.append(0) data.append(0)
func add_image_descriptor(pos: Vector2,
size: Vector2, func add_image_descriptor(pos: Vector2, size: Vector2, l_color_table_size: int) -> void:
l_color_table_size: int) -> void:
var image_separator: int = 0x2c var image_separator: int = 0x2c
var packed_fields: int = 0b10000000 | (0b111 & l_color_table_size) var packed_fields: int = 0b10000000 | (0b111 & l_color_table_size)
var little_endian = preload('./little_endian.gd').new()
data.append(image_separator) data.append(image_separator)
data += little_endian.int_to_2bytes(int(pos.x)) # left pos data += little_endian.int_to_2bytes(int(pos.x)) # left pos
data += little_endian.int_to_2bytes(int(pos.y)) # top pos data += little_endian.int_to_2bytes(int(pos.y)) # top pos
@ -252,12 +248,14 @@ func add_image_descriptor(pos: Vector2,
data += little_endian.int_to_2bytes(int(size.y)) # height data += little_endian.int_to_2bytes(int(size.y)) # height
data.append(packed_fields) data.append(packed_fields)
func color_table_bit_size(color_table: Array) -> int: func color_table_bit_size(color_table: Array) -> int:
if color_table.size() <= 1: if color_table.size() <= 1:
return 0 return 0
var bit_size := int(ceil(log(color_table.size()) / log(2.0))) var bit_size := int(ceil(log(color_table.size()) / log(2.0)))
return bit_size - 1 return bit_size - 1
func add_local_color_table(color_table: Array) -> void: func add_local_color_table(color_table: Array) -> void:
for color in color_table: for color in color_table:
data.append(color[0]) data.append(color[0])
@ -271,6 +269,7 @@ func add_local_color_table(color_table: Array) -> void:
for i in range(proper_size - color_table.size()): for i in range(proper_size - color_table.size()):
data += PoolByteArray([0, 0, 0]) data += PoolByteArray([0, 0, 0])
func add_image_data_block(lzw_min_code_size: int, _data: PoolByteArray) -> void: func add_image_data_block(lzw_min_code_size: int, _data: PoolByteArray) -> void:
data.append(lzw_min_code_size) data.append(lzw_min_code_size)

View file

@ -1,7 +1,7 @@
extends Reference extends Reference
class LSB_LZWBitPacker: class LSBLZWBitPacker:
var bit_index: int = 0 var bit_index: int = 0
var stream: int = 0 var stream: int = 0

View file

@ -1,7 +1,7 @@
extends Reference extends Reference
class LSB_LZWBitUnpacker: class LSBLZWBitUnpacker:
var chunk_stream: PoolByteArray var chunk_stream: PoolByteArray
var bit_index: int = 0 var bit_index: int = 0
var byte: int var byte: int

View file

@ -1,8 +1,8 @@
extends Reference extends Reference
var lsbbitpacker = preload("./lsbbitpacker.gd")
var lsbbitunpacker = preload("./lsbbitunpacker.gd")
var lsbbitpacker = preload('./lsbbitpacker.gd')
var lsbbitunpacker = preload('./lsbbitunpacker.gd')
class CodeEntry: class CodeEntry:
var sequence: PoolByteArray var sequence: PoolByteArray
@ -16,11 +16,12 @@ class CodeEntry:
return CodeEntry.new(self.raw_array + other.raw_array) return CodeEntry.new(self.raw_array + other.raw_array)
func to_string(): func to_string():
var result: String = '' var result: String = ""
for element in self.sequence: for element in self.sequence:
result += str(element) + ', ' result += str(element) + ", "
return result.substr(0, result.length() - 2) return result.substr(0, result.length() - 2)
class CodeTable: class CodeTable:
var entries: Dictionary = {} var entries: Dictionary = {}
var counter: int = 0 var counter: int = 0
@ -42,20 +43,23 @@ class CodeTable:
return self.entries.get(index, null) return self.entries.get(index, null)
func to_string() -> String: func to_string() -> String:
var result: String = 'CodeTable:\n' var result: String = "CodeTable:\n"
for id in self.entries: for id in self.entries:
result += str(id) + ': ' + self.entries[id].to_string() + '\n' result += str(id) + ": " + self.entries[id].to_string() + "\n"
result += 'Counter: ' + str(self.counter) + '\n' result += "Counter: " + str(self.counter) + "\n"
return result return result
func log2(value: float) -> float: func log2(value: float) -> float:
return log(value) / log(2.0) return log(value) / log(2.0)
func get_bits_number_for(value: int) -> int: func get_bits_number_for(value: int) -> int:
if value == 0: if value == 0:
return 1 return 1
return int(ceil(log2(value + 1))) return int(ceil(log2(value + 1)))
func initialize_color_code_table(colors: PoolByteArray) -> CodeTable: func initialize_color_code_table(colors: PoolByteArray) -> CodeTable:
var result_code_table: CodeTable = CodeTable.new() var result_code_table: CodeTable = CodeTable.new()
for color_id in colors: for color_id in colors:
@ -67,9 +71,11 @@ func initialize_color_code_table(colors: PoolByteArray) -> CodeTable:
result_code_table.counter = clear_code_index + 2 result_code_table.counter = clear_code_index + 2
return result_code_table return result_code_table
# compression and decompression done with source: # compression and decompression done with source:
# http://www.matthewflickinger.com/lab/whatsinagif/lzw_image_data.asp # http://www.matthewflickinger.com/lab/whatsinagif/lzw_image_data.asp
func compress_lzw(image: PoolByteArray, colors: PoolByteArray) -> Array: func compress_lzw(image: PoolByteArray, colors: PoolByteArray) -> Array:
# Initialize code table # Initialize code table
var code_table: CodeTable = initialize_color_code_table(colors) var code_table: CodeTable = initialize_color_code_table(colors)
@ -83,7 +89,7 @@ func compress_lzw(image: PoolByteArray, colors: PoolByteArray) -> Array:
var clear_code_index: int = pow(2, get_bits_number_for(last_color_index)) var clear_code_index: int = pow(2, get_bits_number_for(last_color_index))
var index_stream: PoolByteArray = image var index_stream: PoolByteArray = image
var current_code_size: int = get_bits_number_for(clear_code_index) var current_code_size: int = get_bits_number_for(clear_code_index)
var binary_code_stream = lsbbitpacker.LSB_LZWBitPacker.new() var binary_code_stream = lsbbitpacker.LSBLZWBitPacker.new()
# initialize with Clear Code # initialize with Clear Code
binary_code_stream.write_bits(clear_code_index, current_code_size) binary_code_stream.write_bits(clear_code_index, current_code_size)
@ -94,15 +100,15 @@ func compress_lzw(image: PoolByteArray, colors: PoolByteArray) -> Array:
# <LOOP POINT> # <LOOP POINT>
while data_index < index_stream.size(): while data_index < index_stream.size():
# Get the next index from the index stream. # Get the next index from the index stream.
var K: CodeEntry = CodeEntry.new([index_stream[data_index]]) var k: CodeEntry = CodeEntry.new([index_stream[data_index]])
data_index += 1 data_index += 1
# Is index buffer + K in our code table? # Is index buffer + k in our code table?
var new_index_buffer: CodeEntry = index_buffer.add(K) var new_index_buffer: CodeEntry = index_buffer.add(k)
if code_table.has(new_index_buffer): # if YES if code_table.has(new_index_buffer): # if YES
# Add K to the end of the index buffer # Add k to the end of the index buffer
index_buffer = new_index_buffer index_buffer = new_index_buffer
else: # if NO else: # if NO
# Add a row for index buffer + K into our code table # Add a row for index buffer + k into our code table
binary_code_stream.write_bits(code_table.find(index_buffer), current_code_size) binary_code_stream.write_bits(code_table.find(index_buffer), current_code_size)
# We don't want to add new code to code table if we've exceeded 4095 # We don't want to add new code to code table if we've exceeded 4095
@ -128,8 +134,8 @@ func compress_lzw(image: PoolByteArray, colors: PoolByteArray) -> Array:
if new_code_size_candidate > current_code_size: if new_code_size_candidate > current_code_size:
current_code_size = new_code_size_candidate current_code_size = new_code_size_candidate
# Index buffer is set to K # Index buffer is set to k
index_buffer = K index_buffer = k
# Output code for contents of index buffer # Output code for contents of index buffer
binary_code_stream.write_bits(code_table.find(index_buffer), current_code_size) binary_code_stream.write_bits(code_table.find(index_buffer), current_code_size)
@ -140,10 +146,11 @@ func compress_lzw(image: PoolByteArray, colors: PoolByteArray) -> Array:
return [binary_code_stream.pack(), min_code_size] return [binary_code_stream.pack(), min_code_size]
func decompress_lzw(code_stream_data: PoolByteArray, min_code_size: int, colors: PoolByteArray) -> PoolByteArray: func decompress_lzw(code_stream_data: PoolByteArray, min_code_size: int, colors: PoolByteArray) -> PoolByteArray:
var code_table: CodeTable = initialize_color_code_table(colors) var code_table: CodeTable = initialize_color_code_table(colors)
var index_stream: PoolByteArray = PoolByteArray([]) var index_stream: PoolByteArray = PoolByteArray([])
var binary_code_stream = lsbbitunpacker.LSB_LZWBitUnpacker.new(code_stream_data) var binary_code_stream = lsbbitunpacker.LSBLZWBitUnpacker.new(code_stream_data)
var current_code_size: int = min_code_size + 1 var current_code_size: int = min_code_size + 1
var clear_code_index: int = pow(2, min_code_size) var clear_code_index: int = pow(2, min_code_size)
@ -175,22 +182,22 @@ func decompress_lzw(code_stream_data: PoolByteArray, min_code_size: int, colors:
if code_entry != null: # if YES if code_entry != null: # if YES
# output {CODE} to index stream # output {CODE} to index stream
index_stream.append_array(code_entry.sequence) index_stream.append_array(code_entry.sequence)
# let K be the first index in {CODE} # let k be the first index in {CODE}
var K: CodeEntry = CodeEntry.new([code_entry.sequence[0]]) var k: CodeEntry = CodeEntry.new([code_entry.sequence[0]])
# warning-ignore:return_value_discarded # warning-ignore:return_value_discarded
# add {PREVCODE} + K to the code table # add {PREVCODE} + k to the code table
code_table.add(code_table.get(prevcode).add(K)) code_table.add(code_table.get(prevcode).add(k))
# set PREVCODE = CODE # set PREVCODE = CODE
prevcode = code prevcode = code
else: # if NO else: # if NO
# let K be the first index of {PREVCODE} # let k be the first index of {PREVCODE}
var prevcode_entry: CodeEntry = code_table.get(prevcode) var prevcode_entry: CodeEntry = code_table.get(prevcode)
var K: CodeEntry = CodeEntry.new([prevcode_entry.sequence[0]]) var k: CodeEntry = CodeEntry.new([prevcode_entry.sequence[0]])
# output {PREVCODE} + K to index stream # output {PREVCODE} + k to index stream
index_stream.append_array(prevcode_entry.add(K).sequence) index_stream.append_array(prevcode_entry.add(k).sequence)
# add {PREVCODE} + K to code table # add {PREVCODE} + k to code table
# warning-ignore:return_value_discarded # warning-ignore:return_value_discarded
code_table.add(prevcode_entry.add(K)) code_table.add(prevcode_entry.add(k))
# set PREVCODE = CODE # set PREVCODE = CODE
prevcode = code prevcode = code

View file

@ -1,9 +1,9 @@
extends Reference extends Reference
var converter = preload("../converter.gd").new()
var converter = preload('../converter.gd').new()
var transparency := false var transparency := false
func longest_axis(colors: Array) -> int: func longest_axis(colors: Array) -> int:
var start := [255, 255, 255] var start := [255, 255, 255]
var end := [0, 0, 0] var end := [0, 0, 0]
@ -24,6 +24,7 @@ func longest_axis(colors: Array) -> int:
return 1 return 1
return 2 return 2
func get_median(colors: Array) -> Vector3: func get_median(colors: Array) -> Vector3:
return colors[colors.size() >> 1] return colors[colors.size() >> 1]
@ -51,6 +52,7 @@ func median_cut(colors: Array) -> Array:
return [left_colors, right_colors] return [left_colors, right_colors]
func average_color(bucket: Array) -> Array: func average_color(bucket: Array) -> Array:
var r := 0 var r := 0
var g := 0 var g := 0
@ -61,6 +63,7 @@ func average_color(bucket: Array) -> Array:
b += color[2] b += color[2]
return [r / bucket.size(), g / bucket.size(), b / bucket.size()] return [r / bucket.size(), g / bucket.size(), b / bucket.size()]
func average_colors(buckets: Array) -> Dictionary: func average_colors(buckets: Array) -> Dictionary:
var avg_colors := {} var avg_colors := {}
for bucket in buckets: for bucket in buckets:
@ -68,6 +71,7 @@ func average_colors(buckets: Array) -> Dictionary:
avg_colors[average_color(bucket)] = avg_colors.size() avg_colors[average_color(bucket)] = avg_colors.size()
return avg_colors return avg_colors
func pixels_to_colors(image: Image) -> Array: func pixels_to_colors(image: Image) -> Array:
image.lock() image.lock()
var result := [] var result := []
@ -81,6 +85,7 @@ func pixels_to_colors(image: Image) -> Array:
image.unlock() image.unlock()
return result return result
func remove_smallest_bucket(buckets: Array) -> Array: func remove_smallest_bucket(buckets: Array) -> Array:
if buckets.size() == 0: if buckets.size() == 0:
return buckets return buckets
@ -91,6 +96,7 @@ func remove_smallest_bucket(buckets: Array) -> Array:
buckets.remove(i_of_smallest_bucket) buckets.remove(i_of_smallest_bucket)
return buckets return buckets
func remove_empty_buckets(buckets: Array) -> Array: func remove_empty_buckets(buckets: Array) -> Array:
if buckets.size() == 0: if buckets.size() == 0:
return buckets return buckets
@ -102,6 +108,7 @@ func remove_empty_buckets(buckets: Array) -> Array:
return buckets return buckets
# quantizes to gif ready codes # quantizes to gif ready codes
func quantize(image: Image) -> Array: func quantize(image: Image) -> Array:
var pixels = pixels_to_colors(image) var pixels = pixels_to_colors(image)

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=false detect_3d=false

View file

@ -1,10 +1,9 @@
extends Node extends Node
enum GradientDirection { TOP, BOTTOM, LEFT, RIGHT } enum GradientDirection { TOP, BOTTOM, LEFT, RIGHT }
func scale3X(sprite : Image, tol : float = 50) -> Image: func scale_3x(sprite: Image, tol: float = 50) -> Image:
var scaled := Image.new() var scaled := Image.new()
scaled.create(sprite.get_width() * 3, sprite.get_height() * 3, false, Image.FORMAT_RGBA8) scaled.create(sprite.get_width() * 3, sprite.get_height() * 3, false, Image.FORMAT_RGBA8)
scaled.lock() scaled.lock()
@ -34,27 +33,31 @@ func scale3X(sprite : Image, tol : float = 50) -> Image:
h = sprite.get_pixel(x, y + 1) h = sprite.get_pixel(x, y + 1)
i = sprite.get_pixel(x + 1, y + 1) i = sprite.get_pixel(x + 1, y + 1)
var db : bool = similarColors(d, b, tol) var db: bool = similar_colors(d, b, tol)
var dh : bool = similarColors(d, h, tol) var dh: bool = similar_colors(d, h, tol)
var bf : bool = similarColors(f, b, tol) var bf: bool = similar_colors(f, b, tol)
var ec : bool = similarColors(e, c, tol) var ec: bool = similar_colors(e, c, tol)
var ea : bool = similarColors(e, a, tol) var ea: bool = similar_colors(e, a, tol)
var fh : bool = similarColors(f, h, tol) var fh: bool = similar_colors(f, h, tol)
var eg : bool = similarColors(e, g, tol) var eg: bool = similar_colors(e, g, tol)
var ei : bool = similarColors(e, i, tol) var ei: bool = similar_colors(e, i, tol)
scaled.set_pixel(xs - 1, ys - 1, d if (db and !dh and !bf) else e) scaled.set_pixel(xs - 1, ys - 1, d if (db and !dh and !bf) else e)
scaled.set_pixel(xs, ys-1, b if (db and !dh and !bf and !ec) or scaled.set_pixel(
(bf and !db and !fh and !ea) else e) xs, ys - 1, b if (db and !dh and !bf and !ec) or (bf and !db and !fh and !ea) else e
)
scaled.set_pixel(xs + 1, ys - 1, f if (bf and !db and !fh) else e) scaled.set_pixel(xs + 1, ys - 1, f if (bf and !db and !fh) else e)
scaled.set_pixel(xs-1, ys, d if (dh and !fh and !db and !ea) or scaled.set_pixel(
(db and !dh and !bf and !eg) else e) xs - 1, ys, d if (dh and !fh and !db and !ea) or (db and !dh and !bf and !eg) else e
scaled.set_pixel(xs, ys, e); )
scaled.set_pixel(xs+1, ys, f if (bf and !db and !fh and !ei) or scaled.set_pixel(xs, ys, e)
(fh and !bf and !dh and !ec) else e) scaled.set_pixel(
xs + 1, ys, f if (bf and !db and !fh and !ei) or (fh and !bf and !dh and !ec) else e
)
scaled.set_pixel(xs - 1, ys + 1, d if (dh and !fh and !db) else e) scaled.set_pixel(xs - 1, ys + 1, d if (dh and !fh and !db) else e)
scaled.set_pixel(xs, ys+1, h if (fh and !bf and !dh and !eg) or scaled.set_pixel(
(dh and !fh and !db and !ei) else e) xs, ys + 1, h if (fh and !bf and !dh and !eg) or (dh and !fh and !db and !ei) else e
)
scaled.set_pixel(xs + 1, ys + 1, f if (fh and !bf and !dh) else e) scaled.set_pixel(xs + 1, ys + 1, f if (fh and !bf and !dh) else e)
scaled.unlock() scaled.unlock()
@ -90,12 +93,16 @@ func rotxel(sprite : Image, angle : float, pivot : Vector2) -> void:
ox = round(pivot.x * 3 + 1 + mag * cos(dir)) ox = round(pivot.x * 3 + 1 + mag * cos(dir))
oy = round(pivot.y * 3 + 1 + mag * sin(dir)) oy = round(pivot.y * 3 + 1 + mag * sin(dir))
if (sprite.get_width() % 2 != 0): if sprite.get_width() % 2 != 0:
ox += 1 ox += 1
oy += 1 oy += 1
if (ox >= 0 && ox < sprite.get_width()*3 if (
&& oy >= 0 && oy < sprite.get_height()*3): ox >= 0
&& ox < sprite.get_width() * 3
&& oy >= 0
&& oy < sprite.get_height() * 3
):
found_pixel = true found_pixel = true
break break
@ -107,8 +114,8 @@ func rotxel(sprite : Image, angle : float, pivot : Vector2) -> void:
var col: int = ox % 3 var col: int = ox % 3
var index: int = col + 3 * fil var index: int = col + 3 * fil
ox = round((ox - 1)/3.0); ox = round((ox - 1) / 3.0)
oy = round((oy - 1)/3.0); oy = round((oy - 1) / 3.0)
var a: Color var a: Color
var b: Color var b: Color
var c: Color var c: Color
@ -118,55 +125,138 @@ func rotxel(sprite : Image, angle : float, pivot : Vector2) -> void:
var g: Color var g: Color
var h: Color var h: Color
var i: Color var i: Color
if (ox == 0 || ox == sprite.get_width() - 1 || if ox == 0 || ox == sprite.get_width() - 1 || oy == 0 || oy == sprite.get_height() - 1:
oy == 0 || oy == sprite.get_height() - 1):
p = aux.get_pixel(ox, oy) p = aux.get_pixel(ox, oy)
else: else:
a = aux.get_pixel(ox-1,oy-1); a = aux.get_pixel(ox - 1, oy - 1)
b = aux.get_pixel(ox,oy-1); b = aux.get_pixel(ox, oy - 1)
c = aux.get_pixel(ox+1,oy-1); c = aux.get_pixel(ox + 1, oy - 1)
d = aux.get_pixel(ox-1,oy); d = aux.get_pixel(ox - 1, oy)
e = aux.get_pixel(ox,oy); e = aux.get_pixel(ox, oy)
f = aux.get_pixel(ox+1,oy); f = aux.get_pixel(ox + 1, oy)
g = aux.get_pixel(ox-1,oy+1); g = aux.get_pixel(ox - 1, oy + 1)
h = aux.get_pixel(ox,oy+1); h = aux.get_pixel(ox, oy + 1)
i = aux.get_pixel(ox+1,oy+1); i = aux.get_pixel(ox + 1, oy + 1)
match(index): match index:
0: 0:
p = d if (similarColors(d,b) && !similarColors(d,h) p = (
&& !similarColors(b,f)) else e; d
if (
similar_colors(d, b)
&& !similar_colors(d, h)
&& !similar_colors(b, f)
)
else e
)
1: 1:
p = b if ((similarColors(d,b) && !similarColors(d,h) && p = (
!similarColors(b,f) && !similarColors(e,c)) || b
(similarColors(b,f) && !similarColors(d,b) && if (
!similarColors(f,h) && !similarColors(e,a))) else e; (
similar_colors(d, b)
&& !similar_colors(d, h)
&& !similar_colors(b, f)
&& !similar_colors(e, c)
)
|| (
similar_colors(b, f)
&& !similar_colors(d, b)
&& !similar_colors(f, h)
&& !similar_colors(e, a)
)
)
else e
)
2: 2:
p = f if (similarColors(b,f) && !similarColors(d,b) && p = (
!similarColors(f,h)) else e; f
if (
similar_colors(b, f)
&& !similar_colors(d, b)
&& !similar_colors(f, h)
)
else e
)
3: 3:
p = d if ((similarColors(d,h) && !similarColors(f,h) && p = (
!similarColors(d,b) && !similarColors(e,a)) || d
(similarColors(d,b) && !similarColors(d,h) && if (
!similarColors(b,f) && !similarColors(e,g))) else e; (
similar_colors(d, h)
&& !similar_colors(f, h)
&& !similar_colors(d, b)
&& !similar_colors(e, a)
)
|| (
similar_colors(d, b)
&& !similar_colors(d, h)
&& !similar_colors(b, f)
&& !similar_colors(e, g)
)
)
else e
)
4: 4:
p = e p = e
5: 5:
p = f if((similarColors(b,f) && !similarColors(d,b) && p = (
!similarColors(f,h) && !similarColors(e,i)) f
|| (similarColors(f,h) && !similarColors(b,f) && if (
!similarColors(d,h) && !similarColors(e,c))) else e; (
similar_colors(b, f)
&& !similar_colors(d, b)
&& !similar_colors(f, h)
&& !similar_colors(e, i)
)
|| (
similar_colors(f, h)
&& !similar_colors(b, f)
&& !similar_colors(d, h)
&& !similar_colors(e, c)
)
)
else e
)
6: 6:
p = d if (similarColors(d,h) && !similarColors(f,h) && p = (
!similarColors(d,b)) else e; d
if (
similar_colors(d, h)
&& !similar_colors(f, h)
&& !similar_colors(d, b)
)
else e
)
7: 7:
p = h if ((similarColors(f,h) && !similarColors(f,b) && p = (
!similarColors(d,h) && !similarColors(e,g)) h
|| (similarColors(d,h) && !similarColors(f,h) && if (
!similarColors(d,b) && !similarColors(e,i))) else e; (
similar_colors(f, h)
&& !similar_colors(f, b)
&& !similar_colors(d, h)
&& !similar_colors(e, g)
)
|| (
similar_colors(d, h)
&& !similar_colors(f, h)
&& !similar_colors(d, b)
&& !similar_colors(e, i)
)
)
else e
)
8: 8:
p = f if (similarColors(f,h) && !similarColors(f,b) && p = (
!similarColors(d,h)) else e; f
if (
similar_colors(f, h)
&& !similar_colors(f, b)
&& !similar_colors(d, h)
)
else e
)
sprite.set_pixel(x, y, p) sprite.set_pixel(x, y, p)
sprite.unlock() sprite.unlock()
aux.unlock() aux.unlock()
@ -175,7 +265,7 @@ func rotxel(sprite : Image, angle : float, pivot : Vector2) -> void:
func fake_rotsprite(sprite: Image, angle: float, pivot: Vector2) -> void: func fake_rotsprite(sprite: Image, angle: float, pivot: Vector2) -> void:
var selected_sprite := Image.new() var selected_sprite := Image.new()
selected_sprite.copy_from(sprite) selected_sprite.copy_from(sprite)
selected_sprite.copy_from(scale3X(selected_sprite)) selected_sprite.copy_from(scale_3x(selected_sprite))
nn_rotate(selected_sprite, angle, pivot * 3) nn_rotate(selected_sprite, angle, pivot * 3)
# warning-ignore:integer_division # warning-ignore:integer_division
# warning-ignore:integer_division # warning-ignore:integer_division
@ -202,17 +292,25 @@ func nn_rotate(sprite : Image, angle : float, pivot : Vector2) -> void:
aux.unlock() aux.unlock()
func similarColors(c1 : Color, c2 : Color, tol : float = 100) -> bool: func similar_colors(c1: Color, c2: Color, tol: float = 100) -> bool:
var dist = colorDistance(c1, c2) var dist = color_distance(c1, c2)
return dist <= tol return dist <= tol
func colorDistance(c1 : Color, c2 : Color) -> float: func color_distance(c1: Color, c2: Color) -> float:
return sqrt(pow((c1.r - c2.r)*255, 2) + pow((c1.g - c2.g)*255, 2) return sqrt(
+ pow((c1.b - c2.b)*255, 2) + pow((c1.a - c2.a)*255, 2)) (
pow((c1.r - c2.r) * 255, 2)
+ pow((c1.g - c2.g) * 255, 2)
+ pow((c1.b - c2.b) * 255, 2)
+ pow((c1.a - c2.a) * 255, 2)
)
)
# Image effects # Image effects
func scale_image(width: int, height: int, interpolation: int) -> void: func scale_image(width: int, height: int, interpolation: int) -> void:
general_do_scale(width, height) general_do_scale(width, height)
@ -220,16 +318,21 @@ func scale_image(width : int, height : int, interpolation : int) -> void:
for i in range(f.cels.size() - 1, -1, -1): for i in range(f.cels.size() - 1, -1, -1):
var sprite := Image.new() var sprite := Image.new()
sprite.copy_from(f.cels[i].image) sprite.copy_from(f.cels[i].image)
# Different method for scale3x # Different method for scale_3x
if interpolation == 5: if interpolation == 5:
var times : Vector2 = Vector2(ceil(width/(3.0*sprite.get_width())),ceil(height/(3.0*sprite.get_height()))) var times: Vector2 = Vector2(
ceil(width / (3.0 * sprite.get_width())),
ceil(height / (3.0 * sprite.get_height()))
)
for _j in range(max(times.x, times.y)): for _j in range(max(times.x, times.y)):
sprite.copy_from(scale3X(sprite)) sprite.copy_from(scale_3x(sprite))
sprite.resize(width, height, 0) sprite.resize(width, height, 0)
else: else:
sprite.resize(width, height, interpolation) sprite.resize(width, height, interpolation)
Global.current_project.undo_redo.add_do_property(f.cels[i].image, "data", sprite.data) Global.current_project.undo_redo.add_do_property(f.cels[i].image, "data", sprite.data)
Global.current_project.undo_redo.add_undo_property(f.cels[i].image, "data", f.cels[i].image.data) Global.current_project.undo_redo.add_undo_property(
f.cels[i].image, "data", f.cels[i].image.data
)
general_undo_scale() general_undo_scale()
@ -249,7 +352,9 @@ func centralize() -> void:
general_do_centralize() general_do_centralize()
for c in Global.current_project.frames[Global.current_project.current_frame].cels: for c in Global.current_project.frames[Global.current_project.current_frame].cels:
var sprite := Image.new() var sprite := Image.new()
sprite.create(Global.current_project.size.x, Global.current_project.size.y, false, Image.FORMAT_RGBA8) sprite.create(
Global.current_project.size.x, Global.current_project.size.y, false, Image.FORMAT_RGBA8
)
sprite.blend_rect(c.image, used_rect, offset) sprite.blend_rect(c.image, used_rect, offset)
Global.current_project.undo_redo.add_do_property(c.image, "data", sprite.data) Global.current_project.undo_redo.add_do_property(c.image, "data", sprite.data)
Global.current_project.undo_redo.add_undo_property(c.image, "data", c.image.data) Global.current_project.undo_redo.add_undo_property(c.image, "data", c.image.data)
@ -294,7 +399,11 @@ func resize_canvas(width : int, height : int, offset_x : int, offset_y : int) ->
for c in f.cels: for c in f.cels:
var sprite := Image.new() var sprite := Image.new()
sprite.create(width, height, false, Image.FORMAT_RGBA8) sprite.create(width, height, false, Image.FORMAT_RGBA8)
sprite.blend_rect(c.image, Rect2(Vector2.ZERO, Global.current_project.size), Vector2(offset_x, offset_y)) sprite.blend_rect(
c.image,
Rect2(Vector2.ZERO, Global.current_project.size),
Vector2(offset_x, offset_y)
)
Global.current_project.undo_redo.add_do_property(c.image, "data", sprite.data) Global.current_project.undo_redo.add_do_property(c.image, "data", sprite.data)
Global.current_project.undo_redo.add_undo_property(c.image, "data", c.image.data) Global.current_project.undo_redo.add_undo_property(c.image, "data", c.image.data)
@ -335,8 +444,12 @@ func general_undo_scale() -> void:
project.undo_redo.add_undo_property(project, "selection_bitmap", project.selection_bitmap) project.undo_redo.add_undo_property(project, "selection_bitmap", project.selection_bitmap)
project.undo_redo.add_undo_property(project, "x_symmetry_point", project.x_symmetry_point) project.undo_redo.add_undo_property(project, "x_symmetry_point", project.x_symmetry_point)
project.undo_redo.add_undo_property(project, "y_symmetry_point", project.y_symmetry_point) project.undo_redo.add_undo_property(project, "y_symmetry_point", project.y_symmetry_point)
project.undo_redo.add_undo_property(project.x_symmetry_axis, "points", project.x_symmetry_axis.points) project.undo_redo.add_undo_property(
project.undo_redo.add_undo_property(project.y_symmetry_axis, "points", project.y_symmetry_axis.points) project.x_symmetry_axis, "points", project.x_symmetry_axis.points
)
project.undo_redo.add_undo_property(
project.y_symmetry_axis, "points", project.y_symmetry_axis.points
)
project.undo_redo.add_undo_method(Global, "undo") project.undo_redo.add_undo_method(Global, "undo")
project.undo_redo.add_do_method(Global, "redo") project.undo_redo.add_do_method(Global, "redo")
project.undo_redo.commit_action() project.undo_redo.commit_action()
@ -355,50 +468,15 @@ func general_undo_centralize() -> void:
project.undo_redo.commit_action() project.undo_redo.commit_action()
# TO BE REMOVED func generate_outline(
# func invert_image_colors(image : Image, affect_selection : bool, project : Project, red := true, green := true, blue := true, alpha := false) -> void: image: Image,
# image.lock() affect_selection: bool,
# for x in project.size.x: project: Project,
# for y in project.size.y: outline_color: Color,
# var pos := Vector2(x, y) thickness: int,
# if affect_selection and !project.can_pixel_get_drawn(pos): diagonal: bool,
# continue inside_image: bool
# var px_color := image.get_pixelv(pos) ) -> void:
# # Manually invert each color channel
# if red:
# px_color.r = 1.0 - px_color.r
# if green:
# px_color.g = 1.0 - px_color.g
# if blue:
# px_color.b = 1.0 - px_color.b
# if alpha:
# px_color.a = 1.0 - px_color.a
# image.set_pixelv(pos, px_color)
# TO BE REMOVED
# func desaturate_image(image : Image, affect_selection : bool, project : Project, red := true, green := true, blue := true, alpha := false) -> void:
# image.lock()
# for x in project.size.x:
# for y in project.size.y:
# var pos := Vector2(x, y)
# if affect_selection and !project.can_pixel_get_drawn(pos):
# continue
# var px_color := image.get_pixelv(pos)
# var gray = px_color.v
# if red:
# px_color.r = gray
# if green:
# px_color.g = gray
# if blue:
# px_color.b = gray
# if alpha:
# px_color.a = gray
# image.set_pixelv(pos, px_color)
func generate_outline(image : Image, affect_selection : bool, project : Project, outline_color : Color, thickness : int, diagonal : bool, inside_image : bool) -> void:
if image.is_invisible(): if image.is_invisible():
return return
var new_image := Image.new() var new_image := Image.new()
@ -426,7 +504,10 @@ func generate_outline(image : Image, affect_selection : bool, project : Project,
new_image.set_pixelv(new_pos, outline_color) new_image.set_pixelv(new_pos, outline_color)
outline_pos = pos + Vector2.RIGHT # Right outline_pos = pos + Vector2.RIGHT # Right
if outline_pos.x >= Global.current_project.size.x || image.get_pixelv(outline_pos).a == 0: if (
outline_pos.x >= Global.current_project.size.x
|| image.get_pixelv(outline_pos).a == 0
):
var new_pos: Vector2 = pos + Vector2.LEFT * (i - 1) var new_pos: Vector2 = pos + Vector2.LEFT * (i - 1)
if new_pos.x >= 0: if new_pos.x >= 0:
var new_pixel = image.get_pixelv(new_pos) var new_pixel = image.get_pixelv(new_pos)
@ -442,7 +523,10 @@ func generate_outline(image : Image, affect_selection : bool, project : Project,
new_image.set_pixelv(new_pos, outline_color) new_image.set_pixelv(new_pos, outline_color)
outline_pos = pos + Vector2.DOWN # Down outline_pos = pos + Vector2.DOWN # Down
if outline_pos.y >= Global.current_project.size.y || image.get_pixelv(outline_pos).a == 0: if (
outline_pos.y >= Global.current_project.size.y
|| image.get_pixelv(outline_pos).a == 0
):
var new_pos: Vector2 = pos + Vector2.UP * (i - 1) var new_pos: Vector2 = pos + Vector2.UP * (i - 1)
if new_pos.y >= 0: if new_pos.y >= 0:
var new_pixel = image.get_pixelv(new_pos) var new_pixel = image.get_pixelv(new_pos)
@ -451,15 +535,24 @@ func generate_outline(image : Image, affect_selection : bool, project : Project,
if diagonal: if diagonal:
outline_pos = pos + (Vector2.LEFT + Vector2.UP) # Top left outline_pos = pos + (Vector2.LEFT + Vector2.UP) # Top left
if (outline_pos.x < 0 && outline_pos.y < 0) || image.get_pixelv(outline_pos).a == 0: if (
(outline_pos.x < 0 && outline_pos.y < 0)
|| image.get_pixelv(outline_pos).a == 0
):
var new_pos: Vector2 = pos + (Vector2.RIGHT + Vector2.DOWN) * (i - 1) var new_pos: Vector2 = pos + (Vector2.RIGHT + Vector2.DOWN) * (i - 1)
if new_pos.x < Global.current_project.size.x && new_pos.y < Global.current_project.size.y: if (
new_pos.x < Global.current_project.size.x
&& new_pos.y < Global.current_project.size.y
):
var new_pixel = image.get_pixelv(new_pos) var new_pixel = image.get_pixelv(new_pos)
if new_pixel.a > 0: if new_pixel.a > 0:
new_image.set_pixelv(new_pos, outline_color) new_image.set_pixelv(new_pos, outline_color)
outline_pos = pos + (Vector2.LEFT + Vector2.DOWN) # Bottom left outline_pos = pos + (Vector2.LEFT + Vector2.DOWN) # Bottom left
if (outline_pos.x < 0 && outline_pos.y >= Global.current_project.size.y) || image.get_pixelv(outline_pos).a == 0: if (
(outline_pos.x < 0 && outline_pos.y >= Global.current_project.size.y)
|| image.get_pixelv(outline_pos).a == 0
):
var new_pos: Vector2 = pos + (Vector2.RIGHT + Vector2.UP) * (i - 1) var new_pos: Vector2 = pos + (Vector2.RIGHT + Vector2.UP) * (i - 1)
if new_pos.x < Global.current_project.size.x && new_pos.y >= 0: if new_pos.x < Global.current_project.size.x && new_pos.y >= 0:
var new_pixel = image.get_pixelv(new_pos) var new_pixel = image.get_pixelv(new_pos)
@ -467,7 +560,10 @@ func generate_outline(image : Image, affect_selection : bool, project : Project,
new_image.set_pixelv(new_pos, outline_color) new_image.set_pixelv(new_pos, outline_color)
outline_pos = pos + (Vector2.RIGHT + Vector2.UP) # Top right outline_pos = pos + (Vector2.RIGHT + Vector2.UP) # Top right
if (outline_pos.x >= Global.current_project.size.x && outline_pos.y < 0) || image.get_pixelv(outline_pos).a == 0: if (
(outline_pos.x >= Global.current_project.size.x && outline_pos.y < 0)
|| image.get_pixelv(outline_pos).a == 0
):
var new_pos: Vector2 = pos + (Vector2.LEFT + Vector2.DOWN) * (i - 1) var new_pos: Vector2 = pos + (Vector2.LEFT + Vector2.DOWN) * (i - 1)
if new_pos.x >= 0 && new_pos.y < Global.current_project.size.y: if new_pos.x >= 0 && new_pos.y < Global.current_project.size.y:
var new_pixel = image.get_pixelv(new_pos) var new_pixel = image.get_pixelv(new_pos)
@ -475,7 +571,13 @@ func generate_outline(image : Image, affect_selection : bool, project : Project,
new_image.set_pixelv(new_pos, outline_color) new_image.set_pixelv(new_pos, outline_color)
outline_pos = pos + (Vector2.RIGHT + Vector2.DOWN) # Bottom right outline_pos = pos + (Vector2.RIGHT + Vector2.DOWN) # Bottom right
if (outline_pos.x >= Global.current_project.size.x && outline_pos.y >= Global.current_project.size.y) || image.get_pixelv(outline_pos).a == 0: if (
(
outline_pos.x >= Global.current_project.size.x
&& outline_pos.y >= Global.current_project.size.y
)
|| image.get_pixelv(outline_pos).a == 0
):
var new_pos: Vector2 = pos + (Vector2.LEFT + Vector2.UP) * (i - 1) var new_pos: Vector2 = pos + (Vector2.LEFT + Vector2.UP) * (i - 1)
if new_pos.x >= 0 && new_pos.y >= 0: if new_pos.x >= 0 && new_pos.y >= 0:
var new_pixel = image.get_pixelv(new_pos) var new_pixel = image.get_pixelv(new_pos)
@ -527,7 +629,10 @@ func generate_outline(image : Image, affect_selection : bool, project : Project,
new_image.set_pixelv(new_pos, outline_color) new_image.set_pixelv(new_pos, outline_color)
new_pos = pos + (Vector2.RIGHT + Vector2.DOWN) * i # Bottom right new_pos = pos + (Vector2.RIGHT + Vector2.DOWN) * i # Bottom right
if new_pos.x < Global.current_project.size.x && new_pos.y < Global.current_project.size.y: if (
new_pos.x < Global.current_project.size.x
&& new_pos.y < Global.current_project.size.y
):
var new_pixel = image.get_pixelv(new_pos) var new_pixel = image.get_pixelv(new_pos)
if new_pixel.a == 0: if new_pixel.a == 0:
new_image.set_pixelv(new_pos, outline_color) new_image.set_pixelv(new_pos, outline_color)
@ -537,45 +642,14 @@ func generate_outline(image : Image, affect_selection : bool, project : Project,
image.copy_from(new_image) image.copy_from(new_image)
# TO BE REMOVED func generate_gradient(
# func adjust_hsv(img: Image, delta_h : float, delta_s : float, delta_v : float, affect_selection : bool, project : Project) -> void: image: Image,
# img.lock() colors: Array,
# for x in project.size.x: steps: int,
# for y in project.size.y: direction: int,
# var pos := Vector2(x, y) affect_selection: bool,
# if affect_selection and !project.can_pixel_get_drawn(pos): project: Project
# continue ) -> void:
# var c : Color = img.get_pixelv(pos)
# # Hue
# var hue = range_lerp(c.h,0,1,-180,180)
# hue = hue + delta_h
# while(hue >= 180):
# hue -= 360
# while(hue < -180):
# hue += 360
# # Saturation
# var sat = c.s
# if delta_s > 0:
# sat = range_lerp(delta_s,0,100,c.s,1)
# elif delta_s < 0:
# sat = range_lerp(delta_s,-100,0,0,c.s)
# # Value
# var val = c.v
# if delta_v > 0:
# val = range_lerp(delta_v,0,100,c.v,1)
# elif delta_v < 0:
# val = range_lerp(delta_v,-100,0,0,c.v)
# c.h = range_lerp(hue,-180,180,0,1)
# c.s = sat
# c.v = val
# img.set_pixelv(pos, c)
func generate_gradient(image : Image, colors : Array, steps : int, direction : int, affect_selection : bool, project : Project) -> void:
if colors.size() < 2: if colors.size() < 2:
return return

View file

@ -1,30 +1,29 @@
extends Node extends Node
enum ExportTab { FRAME = 0, SPRITESHEET = 1, ANIMATION = 2 }
enum Orientation { ROWS = 0, COLUMNS = 1 }
enum AnimationType { MULTIPLE_FILES = 0, ANIMATED = 1 }
enum AnimationDirection { FORWARD = 0, BACKWARDS = 1, PING_PONG = 2 }
enum FileFormat { PNG = 0, GIF = 1 }
# Gif exporter # Gif exporter
const GIFExporter = preload("res://addons/gdgifexporter/exporter.gd") const GIFExporter = preload("res://addons/gdgifexporter/exporter.gd")
const MedianCutQuantization = preload("res://addons/gdgifexporter/quantization/median_cut.gd") const MedianCutQuantization = preload("res://addons/gdgifexporter/quantization/median_cut.gd")
enum ExportTab { FRAME = 0, SPRITESHEET = 1, ANIMATION = 2 }
var current_tab: int = ExportTab.FRAME var current_tab: int = ExportTab.FRAME
# Frame options # Frame options
var frame_number := 0 var frame_number := 0
# All frames and their layers processed/blended into images # All frames and their layers processed/blended into images
var processed_images = [] # Image[] var processed_images = [] # Image[]
# Spritesheet options # Spritesheet options
var frame_current_tag := 0 # Export only current frame tag var frame_current_tag := 0 # Export only current frame tag
var number_of_frames := 1 var number_of_frames := 1
enum Orientation { ROWS = 0, COLUMNS = 1 }
var orientation: int = Orientation.ROWS var orientation: int = Orientation.ROWS
# How many rows/columns before new line is added
var lines_count := 1
# Animation options var lines_count := 1 # How many rows/columns before new line is added
enum AnimationType { MULTIPLE_FILES = 0, ANIMATED = 1 }
var animation_type: int = AnimationType.MULTIPLE_FILES var animation_type: int = AnimationType.MULTIPLE_FILES
enum AnimationDirection { FORWARD = 0, BACKWARDS = 1, PING_PONG = 2 }
var direction: int = AnimationDirection.FORWARD var direction: int = AnimationDirection.FORWARD
# Options # Options
@ -36,7 +35,6 @@ var new_dir_for_each_frame_tag : bool = true # you don't need to store this afte
var directory_path := "" var directory_path := ""
var file_name := "untitled" var file_name := "untitled"
var file_format: int = FileFormat.PNG var file_format: int = FileFormat.PNG
enum FileFormat { PNG = 0, GIF = 1}
var was_exported: bool = false var was_exported: bool = false
@ -71,7 +69,9 @@ func process_frame() -> void:
processed_images.clear() processed_images.clear()
var frame = Global.current_project.frames[frame_number - 1] var frame = Global.current_project.frames[frame_number - 1]
var image := Image.new() var image := Image.new()
image.create(Global.current_project.size.x, Global.current_project.size.y, false, Image.FORMAT_RGBA8) image.create(
Global.current_project.size.x, Global.current_project.size.y, false, Image.FORMAT_RGBA8
)
blend_layers(image, frame) blend_layers(image, frame)
processed_images.append(image) processed_images.append(image)
@ -91,8 +91,16 @@ func process_spritesheet() -> void:
number_of_frames = frames.size() number_of_frames = frames.size()
# If rows mode selected calculate columns count and vice versa # If rows mode selected calculate columns count and vice versa
var spritesheet_columns = lines_count if orientation == Orientation.ROWS else frames_divided_by_spritesheet_lines() var spritesheet_columns = (
var spritesheet_rows = lines_count if orientation == Orientation.COLUMNS else frames_divided_by_spritesheet_lines() lines_count
if orientation == Orientation.ROWS
else frames_divided_by_spritesheet_lines()
)
var spritesheet_rows = (
lines_count
if orientation == Orientation.COLUMNS
else frames_divided_by_spritesheet_lines()
)
var width = Global.current_project.size.x * spritesheet_columns var width = Global.current_project.size.x * spritesheet_columns
var height = Global.current_project.size.y * spritesheet_rows var height = Global.current_project.size.y * spritesheet_rows
@ -131,7 +139,9 @@ func process_animation() -> void:
processed_images.clear() processed_images.clear()
for frame in Global.current_project.frames: for frame in Global.current_project.frames:
var image := Image.new() var image := Image.new()
image.create(Global.current_project.size.x, Global.current_project.size.y, false, Image.FORMAT_RGBA8) image.create(
Global.current_project.size.x, Global.current_project.size.y, false, Image.FORMAT_RGBA8
)
blend_layers(image, frame) blend_layers(image, frame)
processed_images.append(image) processed_images.append(image)
@ -147,17 +157,25 @@ func export_processed_images(ignore_overwrites: bool, export_dialog: AcceptDialo
var export_paths = [] var export_paths = []
for i in range(processed_images.size()): for i in range(processed_images.size()):
stop_export = false stop_export = false
var multiple_files := true if (current_tab == ExportTab.ANIMATION and animation_type == AnimationType.MULTIPLE_FILES) else false var multiple_files := (
true
if (
current_tab == ExportTab.ANIMATION
and animation_type == AnimationType.MULTIPLE_FILES
)
else false
)
var export_path = create_export_path(multiple_files, i + 1) var export_path = create_export_path(multiple_files, i + 1)
# If user want to create new directory for each animation tag then check if directories exist and create them if not # If user want to create new directory for each animation tag then check
# if directories exist and create them if not
if multiple_files and new_dir_for_each_frame_tag: if multiple_files and new_dir_for_each_frame_tag:
var frame_tag_directory := Directory.new() var frame_tag_directory := Directory.new()
if not frame_tag_directory.dir_exists(export_path.get_base_dir()): if not frame_tag_directory.dir_exists(export_path.get_base_dir()):
frame_tag_directory.open(directory_path) frame_tag_directory.open(directory_path)
frame_tag_directory.make_dir(export_path.get_base_dir().get_file()) frame_tag_directory.make_dir(export_path.get_base_dir().get_file())
# Check if the file already exists # Check if the file already exists
var fileCheck = File.new() var file_check: File = File.new()
if fileCheck.file_exists(export_path): if file_check.file_exists(export_path):
# Ask user if he want's to overwrite the file # Ask user if he want's to overwrite the file
if not was_exported or (was_exported and not ignore_overwrites): if not was_exported or (was_exported and not ignore_overwrites):
# Overwrite existing file? # Overwrite existing file?
@ -181,11 +199,17 @@ func export_processed_images(ignore_overwrites: bool, export_dialog: AcceptDialo
else: else:
if gif_export_thread.is_active(): if gif_export_thread.is_active():
gif_export_thread.wait_to_finish() gif_export_thread.wait_to_finish()
gif_export_thread.start(self, "export_gif", {"export_dialog": export_dialog, "export_paths": export_paths}) gif_export_thread.start(
self, "export_gif", {"export_dialog": export_dialog, "export_paths": export_paths}
)
else: else:
for i in range(processed_images.size()): for i in range(processed_images.size()):
if OS.get_name() == "HTML5": if OS.get_name() == "HTML5":
JavaScript.download_buffer(processed_images[i].save_png_to_buffer(), export_paths[i].get_file(), "image/png") JavaScript.download_buffer(
processed_images[i].save_png_to_buffer(),
export_paths[i].get_file(),
"image/png"
)
else: else:
var err = processed_images[i].save_png(export_paths[i]) var err = processed_images[i].save_png(export_paths[i])
if err != OK: if err != OK:
@ -196,7 +220,9 @@ func export_processed_images(ignore_overwrites: bool, export_dialog: AcceptDialo
# Store settings for quick export and when the dialog is opened again # Store settings for quick export and when the dialog is opened again
was_exported = true was_exported = true
Global.current_project.was_exported = true Global.current_project.was_exported = true
Global.top_menu_container.file_menu.set_item_text(6, tr("Export") + " %s" % (file_name + file_format_string(file_format))) Global.top_menu_container.file_menu.set_item_text(
6, tr("Export") + " %s" % (file_name + file_format_string(file_format))
)
# Only show when not exporting gif - gif export finishes in thread # Only show when not exporting gif - gif export finishes in thread
if not (current_tab == ExportTab.ANIMATION and animation_type == AnimationType.ANIMATED): if not (current_tab == ExportTab.ANIMATION and animation_type == AnimationType.ANIMATED):
@ -206,29 +232,54 @@ func export_processed_images(ignore_overwrites: bool, export_dialog: AcceptDialo
func export_gif(args: Dictionary) -> void: func export_gif(args: Dictionary) -> void:
# Export progress popup # Export progress popup
export_progress_fraction = 100 / processed_images.size() # one fraction per each frame, one fraction for write to disk # One fraction per each frame, one fraction for write to disk
export_progress_fraction = 100 / processed_images.size()
export_progress = 0.0 export_progress = 0.0
args["export_dialog"].set_export_progress_bar(export_progress) args["export_dialog"].set_export_progress_bar(export_progress)
args["export_dialog"].toggle_export_progress_popup(true) args["export_dialog"].toggle_export_progress_popup(true)
# Export and save gif # Export and save gif
var exporter = GIFExporter.new(processed_images[0].get_width(), processed_images[0].get_height()) var exporter = GIFExporter.new(
processed_images[0].get_width(), processed_images[0].get_height()
)
match direction: match direction:
AnimationDirection.FORWARD: AnimationDirection.FORWARD:
for i in range(processed_images.size()): for i in range(processed_images.size()):
write_frame_to_gif(processed_images[i], Global.current_project.frames[i].duration * (1 / Global.current_project.fps), exporter, args["export_dialog"]) write_frame_to_gif(
processed_images[i],
Global.current_project.frames[i].duration * (1 / Global.current_project.fps),
exporter,
args["export_dialog"]
)
AnimationDirection.BACKWARDS: AnimationDirection.BACKWARDS:
for i in range(processed_images.size() - 1, -1, -1): for i in range(processed_images.size() - 1, -1, -1):
write_frame_to_gif(processed_images[i], Global.current_project.frames[i].duration * (1 / Global.current_project.fps), exporter, args["export_dialog"]) write_frame_to_gif(
processed_images[i],
Global.current_project.frames[i].duration * (1 / Global.current_project.fps),
exporter,
args["export_dialog"]
)
AnimationDirection.PING_PONG: AnimationDirection.PING_PONG:
export_progress_fraction = 100 / (processed_images.size() * 2) export_progress_fraction = 100 / (processed_images.size() * 2)
for i in range(0, processed_images.size()): for i in range(0, processed_images.size()):
write_frame_to_gif(processed_images[i], Global.current_project.frames[i].duration * (1 / Global.current_project.fps), exporter, args["export_dialog"]) write_frame_to_gif(
processed_images[i],
Global.current_project.frames[i].duration * (1 / Global.current_project.fps),
exporter,
args["export_dialog"]
)
for i in range(processed_images.size() - 2, 0, -1): for i in range(processed_images.size() - 2, 0, -1):
write_frame_to_gif(processed_images[i], Global.current_project.frames[i].duration * (1 / Global.current_project.fps), exporter, args["export_dialog"]) write_frame_to_gif(
processed_images[i],
Global.current_project.frames[i].duration * (1 / Global.current_project.fps),
exporter,
args["export_dialog"]
)
if OS.get_name() == "HTML5": if OS.get_name() == "HTML5":
JavaScript.download_buffer(exporter.export_file_data(), args["export_paths"][0], "image/gif") JavaScript.download_buffer(
exporter.export_file_data(), args["export_paths"][0], "image/gif"
)
else: else:
var file: File = File.new() var file: File = File.new()
@ -239,9 +290,9 @@ func export_gif(args: Dictionary) -> void:
Global.notification_label("File(s) exported") Global.notification_label("File(s) exported")
func write_frame_to_gif(image: Image, wait_time: float, exporter: Reference, export_dialog: Node) -> void: func write_frame_to_gif(image: Image, wait_time: float, exporter: Reference, dialog: Node) -> void:
exporter.add_frame(image, wait_time, MedianCutQuantization) exporter.add_frame(image, wait_time, MedianCutQuantization)
increase_export_progress(export_dialog) increase_export_progress(dialog)
func increase_export_progress(export_dialog: Node) -> void: func increase_export_progress(export_dialog: Node) -> void:
@ -253,17 +304,21 @@ func scale_processed_images() -> void:
for processed_image in processed_images: for processed_image in processed_images:
if resize != 100: if resize != 100:
processed_image.unlock() processed_image.unlock()
processed_image.resize(processed_image.get_size().x * resize / 100, processed_image.get_size().y * resize / 100, interpolation) processed_image.resize(
processed_image.get_size().x * resize / 100,
processed_image.get_size().y * resize / 100,
interpolation
)
func file_format_string(format_enum: int) -> String: func file_format_string(format_enum: int) -> String:
match format_enum: match format_enum:
0: # PNG 0: # PNG
return '.png' return ".png"
1: # GIF 1: # GIF
return '.gif' return ".gif"
_: _:
return '' return ""
func create_export_path(multifile: bool, frame: int = 0) -> String: func create_export_path(multifile: bool, frame: int = 0) -> String:
@ -283,7 +338,9 @@ func create_export_path(multifile: bool, frame: int = 0) -> String:
# Add frame tag if frame has one # Add frame tag if frame has one
# (frame - start_id + 1) Makes frames id to start from 1 in each frame tag directory # (frame - start_id + 1) Makes frames id to start from 1 in each frame tag directory
path += "_" + frame_tag_dir + "_" + String(frame - start_id + 1) path += "_" + frame_tag_dir + "_" + String(frame - start_id + 1)
return directory_path.plus_file(frame_tag_dir).plus_file(path + file_format_string(file_format)) return directory_path.plus_file(frame_tag_dir).plus_file(
path + file_format_string(file_format)
)
else: else:
# Add frame tag if frame has one # Add frame tag if frame has one
# (frame - start_id + 1) Makes frames id to start from 1 in each frame tag # (frame - start_id + 1) Makes frames id to start from 1 in each frame tag
@ -299,7 +356,10 @@ func get_proccessed_image_animation_tag_and_start_id(processed_image_id : int) -
for animation_tag in Global.current_project.animation_tags: for animation_tag in Global.current_project.animation_tags:
# Check if processed image is in frame tag and assign frame tag and start id if yes # Check if processed image is in frame tag and assign frame tag and start id if yes
# Then stop # Then stop
if (processed_image_id + 1) >= animation_tag.from and (processed_image_id + 1) <= animation_tag.to: if (
(processed_image_id + 1) >= animation_tag.from
and (processed_image_id + 1) <= animation_tag.to
):
result_animation_tag_and_start_id = [animation_tag.name, animation_tag.from] result_animation_tag_and_start_id = [animation_tag.name, animation_tag.from]
break break
return result_animation_tag_and_start_id return result_animation_tag_and_start_id
@ -319,7 +379,9 @@ func blend_layers(image : Image, frame : Frame, origin : Vector2 = Vector2(0, 0)
for yy in cel_image.get_size().y: for yy in cel_image.get_size().y:
var pixel_color := cel_image.get_pixel(xx, yy) var pixel_color := cel_image.get_pixel(xx, yy)
var alpha: float = pixel_color.a * cel.opacity var alpha: float = pixel_color.a * cel.opacity
cel_image.set_pixel(xx, yy, Color(pixel_color.r, pixel_color.g, pixel_color.b, alpha)) cel_image.set_pixel(
xx, yy, Color(pixel_color.r, pixel_color.g, pixel_color.b, alpha)
)
image.blend_rect(cel_image, Rect2(Vector2.ZERO, Global.current_project.size), origin) image.blend_rect(cel_image, Rect2(Vector2.ZERO, Global.current_project.size), origin)
cel_image.unlock() cel_image.unlock()
layer_i += 1 layer_i += 1

View file

@ -1,6 +1,5 @@
extends Node extends Node
enum GridTypes { CARTESIAN, ISOMETRIC, ALL } enum GridTypes { CARTESIAN, ISOMETRIC, ALL }
enum PressureSensitivity { NONE, ALPHA, SIZE, ALPHA_AND_SIZE } enum PressureSensitivity { NONE, ALPHA, SIZE, ALPHA_AND_SIZE }
enum ThemeTypes { DARK, BLUE, CARAMEL, LIGHT } enum ThemeTypes { DARK, BLUE, CARAMEL, LIGHT }
@ -20,6 +19,7 @@ var current_project : Project
var current_project_index := 0 setget project_changed var current_project_index := 0 setget project_changed
var panel_layout = PanelLayout.AUTO var panel_layout = PanelLayout.AUTO
var ui_tooltips := {}
# Canvas related stuff # Canvas related stuff
var layers_changed_skip := false var layers_changed_skip := false
@ -113,7 +113,9 @@ onready var tabs : Tabs = control.find_node("Tabs")
onready var main_viewport: ViewportContainer = control.find_node("ViewportContainer") onready var main_viewport: ViewportContainer = control.find_node("ViewportContainer")
onready var second_viewport: ViewportContainer = control.find_node("ViewportContainer2") onready var second_viewport: ViewportContainer = control.find_node("ViewportContainer2")
onready var canvas_preview_container: Container = control.find_node("CanvasPreviewContainer") onready var canvas_preview_container: Container = control.find_node("CanvasPreviewContainer")
onready var small_preview_viewport : ViewportContainer = canvas_preview_container.find_node("PreviewViewportContainer") onready var small_preview_viewport: ViewportContainer = canvas_preview_container.find_node(
"PreviewViewportContainer"
)
onready var camera: Camera2D = main_viewport.find_node("Camera2D") onready var camera: Camera2D = main_viewport.find_node("Camera2D")
onready var camera2: Camera2D = control.find_node("Camera2D2") onready var camera2: Camera2D = control.find_node("Camera2D2")
onready var camera_preview: Camera2D = control.find_node("CameraPreview") onready var camera_preview: Camera2D = control.find_node("CameraPreview")
@ -180,6 +182,10 @@ func _ready() -> void:
projects.append(Project.new()) projects.append(Project.new())
projects[0].layers.append(Layer.new()) projects[0].layers.append(Layer.new())
current_project = projects[0] current_project = projects[0]
for node in get_tree().get_nodes_in_group("UIButtons"):
var tooltip: String = node.hint_tooltip
if !tooltip.empty() and node.shortcut:
ui_tooltips[node] = tooltip
func notification_label(text: String) -> void: func notification_label(text: String) -> void:
@ -207,7 +213,17 @@ func general_redo(project : Project = current_project) -> void:
func undo(_frame_index := -1, _layer_index := -1, project: Project = current_project) -> void: func undo(_frame_index := -1, _layer_index := -1, project: Project = current_project) -> void:
general_undo(project) general_undo(project)
var action_name: String = project.undo_redo.get_current_action_name() var action_name: String = project.undo_redo.get_current_action_name()
if action_name == "Draw" or action_name == "Draw Shape" or action_name == "Rectangle Select" or action_name == "Move Selection" or action_name == "Scale" or action_name == "Centralize" or action_name == "Merge Layer" or action_name == "Link Cel" or action_name == "Unlink Cel": if (
action_name == "Draw"
or action_name == "Draw Shape"
or action_name == "Rectangle Select"
or action_name == "Move Selection"
or action_name == "Scale"
or action_name == "Centralize"
or action_name == "Merge Layer"
or action_name == "Link Cel"
or action_name == "Unlink Cel"
):
if _layer_index > -1 and _frame_index > -1: if _layer_index > -1 and _frame_index > -1:
canvas.update_texture(_layer_index, _frame_index, project) canvas.update_texture(_layer_index, _frame_index, project)
else: else:
@ -242,7 +258,17 @@ func undo(_frame_index := -1, _layer_index := -1, project : Project = current_pr
func redo(_frame_index := -1, _layer_index := -1, project: Project = current_project) -> void: func redo(_frame_index := -1, _layer_index := -1, project: Project = current_project) -> void:
general_redo(project) general_redo(project)
var action_name: String = project.undo_redo.get_current_action_name() var action_name: String = project.undo_redo.get_current_action_name()
if action_name == "Draw" or action_name == "Draw Shape" or action_name == "Rectangle Select" or action_name == "Move Selection" or action_name == "Scale" or action_name == "Centralize" or action_name == "Merge Layer" or action_name == "Link Cel" or action_name == "Unlink Cel": if (
action_name == "Draw"
or action_name == "Draw Shape"
or action_name == "Rectangle Select"
or action_name == "Move Selection"
or action_name == "Scale"
or action_name == "Centralize"
or action_name == "Merge Layer"
or action_name == "Link Cel"
or action_name == "Unlink Cel"
):
if _layer_index > -1 and _frame_index > -1: if _layer_index > -1 and _frame_index > -1:
canvas.update_texture(_layer_index, _frame_index, project) canvas.update_texture(_layer_index, _frame_index, project)
else: else:
@ -289,10 +315,26 @@ func dialog_open(open : bool) -> void:
if open: if open:
can_draw = false can_draw = false
if dim_on_popup: if dim_on_popup:
control.get_node("ModulateTween").interpolate_property(control, "modulate", control.modulate, Color(0.5, 0.5, 0.5), 0.1, Tween.TRANS_LINEAR, Tween.EASE_OUT) control.get_node("ModulateTween").interpolate_property(
control,
"modulate",
control.modulate,
Color(0.5, 0.5, 0.5),
0.1,
Tween.TRANS_LINEAR,
Tween.EASE_OUT
)
else: else:
can_draw = true can_draw = true
control.get_node("ModulateTween").interpolate_property(control, "modulate", control.modulate, Color.white, 0.1, Tween.TRANS_LINEAR, Tween.EASE_OUT) control.get_node("ModulateTween").interpolate_property(
control,
"modulate",
control.modulate,
Color.white,
0.1,
Tween.TRANS_LINEAR,
Tween.EASE_OUT
)
control.get_node("ModulateTween").start() control.get_node("ModulateTween").start()
@ -321,159 +363,11 @@ func change_button_texturerect(texture_button : TextureRect, new_file_name : Str
func update_hint_tooltips() -> void: func update_hint_tooltips() -> void:
var tool_buttons = control.find_node("ToolButtons") var tool_buttons: Container = control.find_node("ToolButtons")
tool_buttons.update_hintooltips()
var rect_select : BaseButton = tool_buttons.find_node("RectSelect") for tip in ui_tooltips:
rect_select.hint_tooltip = tr("""Rectangular Selection tip.hint_tooltip = tr(ui_tooltips[tip]) % tip.shortcut.get_as_text()
%s for left mouse button
%s for right mouse button""") % [InputMap.get_action_list("left_rectangle_select_tool")[0].as_text(), InputMap.get_action_list("right_rectangle_select_tool")[0].as_text()]
var ellipse_select : BaseButton = tool_buttons.find_node("EllipseSelect")
ellipse_select.hint_tooltip = tr("""Elliptical Selection
%s for left mouse button
%s for right mouse button""") % [InputMap.get_action_list("left_ellipse_select_tool")[0].as_text(), InputMap.get_action_list("right_ellipse_select_tool")[0].as_text()]
var polygon_select : BaseButton = tool_buttons.find_node("PolygonSelect")
polygon_select.hint_tooltip = tr("""Polygonal Selection
Double-click to connect the last point to the starting point
%s for left mouse button
%s for right mouse button""") % [InputMap.get_action_list("left_polygon_select_tool")[0].as_text(), InputMap.get_action_list("right_polygon_select_tool")[0].as_text()]
var color_select : BaseButton = tool_buttons.find_node("ColorSelect")
color_select.hint_tooltip = tr("""Select By Color
%s for left mouse button
%s for right mouse button""") % [InputMap.get_action_list("left_color_select_tool")[0].as_text(), InputMap.get_action_list("right_color_select_tool")[0].as_text()]
var magic_wand : BaseButton = tool_buttons.find_node("MagicWand")
magic_wand.hint_tooltip = tr("""Magic Wand
%s for left mouse button
%s for right mouse button""") % [InputMap.get_action_list("left_magic_wand_tool")[0].as_text(), InputMap.get_action_list("right_magic_wand_tool")[0].as_text()]
var lasso : BaseButton = tool_buttons.find_node("Lasso")
lasso.hint_tooltip = tr("""Lasso / Free Select Tool
%s for left mouse button
%s for right mouse button""") % [InputMap.get_action_list("left_lasso_tool")[0].as_text(), InputMap.get_action_list("right_lasso_tool")[0].as_text()]
var move_select : BaseButton = tool_buttons.find_node("Move")
move_select.hint_tooltip = tr("""Move
%s for left mouse button
%s for right mouse button""") % [InputMap.get_action_list("left_move_tool")[0].as_text(), InputMap.get_action_list("right_move_tool")[0].as_text()]
var zoom_tool : BaseButton = tool_buttons.find_node("Zoom")
zoom_tool.hint_tooltip = tr("""Zoom
%s for left mouse button
%s for right mouse button""") % [InputMap.get_action_list("left_zoom_tool")[0].as_text(), InputMap.get_action_list("right_zoom_tool")[0].as_text()]
var pan_tool : BaseButton = tool_buttons.find_node("Pan")
pan_tool.hint_tooltip = tr("""Pan
%s for left mouse button
%s for right mouse button""") % [InputMap.get_action_list("left_pan_tool")[0].as_text(), InputMap.get_action_list("right_pan_tool")[0].as_text()]
var color_picker : BaseButton = tool_buttons.find_node("ColorPicker")
color_picker.hint_tooltip = tr("""Color Picker
Select a color from a pixel of the sprite
%s for left mouse button
%s for right mouse button""") % [InputMap.get_action_list("left_colorpicker_tool")[0].as_text(), InputMap.get_action_list("right_colorpicker_tool")[0].as_text()]
var pencil : BaseButton = tool_buttons.find_node("Pencil")
pencil.hint_tooltip = tr("""Pencil
%s for left mouse button
%s for right mouse button
Hold %s to make a line""") % [InputMap.get_action_list("left_pencil_tool")[0].as_text(), InputMap.get_action_list("right_pencil_tool")[0].as_text(), "Shift"]
var eraser : BaseButton = tool_buttons.find_node("Eraser")
eraser.hint_tooltip = tr("""Eraser
%s for left mouse button
%s for right mouse button
Hold %s to make a line""") % [InputMap.get_action_list("left_eraser_tool")[0].as_text(), InputMap.get_action_list("right_eraser_tool")[0].as_text(), "Shift"]
var bucket : BaseButton = tool_buttons.find_node("Bucket")
bucket.hint_tooltip = tr("""Bucket
%s for left mouse button
%s for right mouse button""") % [InputMap.get_action_list("left_fill_tool")[0].as_text(), InputMap.get_action_list("right_fill_tool")[0].as_text()]
var ld : BaseButton = tool_buttons.find_node("Shading")
ld.hint_tooltip = tr("""Shading Tool
%s for left mouse button
%s for right mouse button""") % [InputMap.get_action_list("left_shading_tool")[0].as_text(), InputMap.get_action_list("right_shading_tool")[0].as_text()]
var linetool : BaseButton = tool_buttons.find_node("LineTool")
linetool.hint_tooltip = tr("""Line Tool
%s for left mouse button
%s for right mouse button
Hold %s to snap the angle of the line
Hold %s to center the shape on the click origin
Hold %s to displace the shape's origin""") % [InputMap.get_action_list("left_linetool_tool")[0].as_text(), InputMap.get_action_list("right_linetool_tool")[0].as_text(), "Shift", "Ctrl", "Alt"]
var recttool : BaseButton = tool_buttons.find_node("RectangleTool")
recttool.hint_tooltip = tr("""Rectangle Tool
%s for left mouse button
%s for right mouse button
Hold %s to create a 1:1 shape
Hold %s to center the shape on the click origin
Hold %s to displace the shape's origin""") % [InputMap.get_action_list("left_rectangletool_tool")[0].as_text(), InputMap.get_action_list("right_rectangletool_tool")[0].as_text(), "Shift", "Ctrl", "Alt"]
var ellipsetool : BaseButton = tool_buttons.find_node("EllipseTool")
ellipsetool.hint_tooltip = tr("""Ellipse Tool
%s for left mouse button
%s for right mouse button
Hold %s to create a 1:1 shape
Hold %s to center the shape on the click origin
Hold %s to displace the shape's origin""") % [InputMap.get_action_list("left_ellipsetool_tool")[0].as_text(), InputMap.get_action_list("right_ellipsetool_tool")[0].as_text(), "Shift", "Ctrl", "Alt"]
var color_switch : BaseButton = control.find_node("ColorSwitch")
color_switch.hint_tooltip = tr("""Switch left and right colors
(%s)""") % InputMap.get_action_list("switch_colors")[0].as_text()
var first_frame : BaseButton = control.find_node("FirstFrame")
first_frame.hint_tooltip = tr("""Jump to the first frame
(%s)""") % InputMap.get_action_list("go_to_first_frame")[0].as_text()
var previous_frame : BaseButton = control.find_node("PreviousFrame")
previous_frame.hint_tooltip = tr("""Go to the previous frame
(%s)""") % InputMap.get_action_list("go_to_previous_frame")[0].as_text()
play_backwards.hint_tooltip = tr("""Play the animation backwards (from end to beginning)
(%s)""") % InputMap.get_action_list("play_backwards")[0].as_text()
play_forward.hint_tooltip = tr("""Play the animation forward (from beginning to end)
(%s)""") % InputMap.get_action_list("play_forward")[0].as_text()
var next_frame : BaseButton = control.find_node("NextFrame")
next_frame.hint_tooltip = tr("""Go to the next frame
(%s)""") % InputMap.get_action_list("go_to_next_frame")[0].as_text()
var last_frame : BaseButton = control.find_node("LastFrame")
last_frame.hint_tooltip = tr("""Jump to the last frame
(%s)""") % InputMap.get_action_list("go_to_last_frame")[0].as_text()
func is_cjk(locale: String) -> bool: func is_cjk(locale: String) -> bool:

Some files were not shown because too many files have changed in this diff Show more