-
Notifications
You must be signed in to change notification settings - Fork 3
Teding/feat/compression #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -22,129 +22,148 @@ function check_api_version() | |||||||||||||
| end | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| function show_error(errorMsg) | ||||||||||||||
| function show_error(error_msg) | ||||||||||||||
| local error_dialog = Dialog("Error") | ||||||||||||||
| error_dialog | ||||||||||||||
| :label { text = errorMsg } | ||||||||||||||
| :label { text = error_msg } | ||||||||||||||
| :newrow() | ||||||||||||||
| :button { text = "Close", onclick = function() error_dialog:close() end } | ||||||||||||||
| error_dialog:show() | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| -- Core functions | ||||||||||||||
| local function initialize_snapshot(self, sprite) | ||||||||||||||
| self.auto_snap_enabled = false | ||||||||||||||
| self.auto_snap_delay = 1 | ||||||||||||||
| self.auto_snap_increment = 0 | ||||||||||||||
| self.context = nil | ||||||||||||||
|
|
||||||||||||||
| -- Instance of Aseprite Sprite object | ||||||||||||||
| -- https://github.com/aseprite/api/blob/master/api/sprite.md#sprite | ||||||||||||||
| self.sprite = nil | ||||||||||||||
| if sprite then | ||||||||||||||
| self.sprite = sprite | ||||||||||||||
| self.context = get_recording_context(sprite) | ||||||||||||||
| local function get_active_frame_number() | ||||||||||||||
| local frame = app.activeFrame | ||||||||||||||
| if frame == nil then | ||||||||||||||
| return 1 | ||||||||||||||
| else | ||||||||||||||
| return frame | ||||||||||||||
| end | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| local function get_snapshot_recording_index(self) | ||||||||||||||
| local path = self.context.index_file | ||||||||||||||
| RecordingContext = {} | ||||||||||||||
|
|
||||||||||||||
| function RecordingContext:get_recording_index() | ||||||||||||||
| local path = self.index_file | ||||||||||||||
| if not app.fs.isFile(path) then | ||||||||||||||
| return 0 | ||||||||||||||
| end | ||||||||||||||
| local file = io.open(path, "r") | ||||||||||||||
| assert(file) | ||||||||||||||
| local contents = file:read() | ||||||||||||||
| io.close(file) | ||||||||||||||
| return tonumber(contents) | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| local function increment_snapshot_recording_index(self) | ||||||||||||||
| local index = get_snapshot_recording_index(self) + 1 | ||||||||||||||
| local path = self.context.index_file | ||||||||||||||
| function RecordingContext:set_recording_index(index) | ||||||||||||||
| local path = self.index_file | ||||||||||||||
| local file = io.open(path, "w") | ||||||||||||||
| assert(file) | ||||||||||||||
| file:write("" .. index) | ||||||||||||||
| io.close(file) | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| local function get_active_frame_number() | ||||||||||||||
| local frame = app.activeFrame | ||||||||||||||
| if frame == nil then | ||||||||||||||
| return 1 | ||||||||||||||
| else | ||||||||||||||
| return frame | ||||||||||||||
| end | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| function get_recording_context(sprite) | ||||||||||||||
| function RecordingContext.new(sprite) | ||||||||||||||
| local self = {} | ||||||||||||||
| setmetatable(self, { __index = RecordingContext }) | ||||||||||||||
| self.sprite_file_name = app.fs.fileTitle(sprite.filename) | ||||||||||||||
| self.sprite_file_path = app.fs.filePath(sprite.filename) | ||||||||||||||
| self:_init_directory() | ||||||||||||||
| self.index_file = app.fs.joinPath(self.record_directory_path, "_index.txt") | ||||||||||||||
| self:_promote_v2_to_v3() | ||||||||||||||
| return self | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| -- 2.x Target Directory Backwards Compatibility | ||||||||||||||
| self.record_directory_name_legacy = self.sprite_file_name .. "_record" | ||||||||||||||
| local is_legacy_recording = false | ||||||||||||||
| if app.fs.isDirectory(app.fs.joinPath(self.sprite_file_path, self.record_directory_name_legacy)) then | ||||||||||||||
| is_legacy_recording = true | ||||||||||||||
| self.record_directory_name = self.record_directory_name_legacy | ||||||||||||||
| function RecordingContext:_init_directory() | ||||||||||||||
| local dir_name_legacy = self.sprite_file_name .. "_record" | ||||||||||||||
| local dir_path_legacy = app.fs.joinPath(self.sprite_file_path, dir_name_legacy) | ||||||||||||||
| if app.fs.isDirectory(dir_path_legacy) then | ||||||||||||||
| -- For 2.x Target Directory Backwards Compatibility | ||||||||||||||
| self._is_legacy_recording = true | ||||||||||||||
| self.record_directory_name = dir_name_legacy | ||||||||||||||
| else | ||||||||||||||
| self._is_legacy_recording = false | ||||||||||||||
| self.record_directory_name = self.sprite_file_name .. "__record" | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| self.record_directory_path = app.fs.joinPath(self.sprite_file_path, self.record_directory_name) | ||||||||||||||
| self.index_file = app.fs.joinPath(self.record_directory_path, "_index.txt") | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| function RecordingContext:_promote_v2_to_v3() | ||||||||||||||
| if not self._is_legacy_recording then | ||||||||||||||
| return -- Is not v2.x | ||||||||||||||
| end | ||||||||||||||
| if app.fs.isFile(self.index_file) then | ||||||||||||||
| return -- Is v2.x, but already has promoted structure | ||||||||||||||
| end | ||||||||||||||
| -- 2.x Add Missing Index File for Forward Compatibility | ||||||||||||||
| if is_legacy_recording and not app.fs.isFile(self.index_file) then | ||||||||||||||
| local is_index_set = false | ||||||||||||||
| local current_index = 0 | ||||||||||||||
| while not is_index_set do | ||||||||||||||
| if not app.fs.isFile(get_contextual_recording_image_path(self, current_index)) then | ||||||||||||||
| is_index_set = true | ||||||||||||||
| local file = io.open(self.index_file, "w") | ||||||||||||||
| file:write("" .. current_index) | ||||||||||||||
| io.close(file) | ||||||||||||||
| else | ||||||||||||||
| current_index = current_index + 1 | ||||||||||||||
| end | ||||||||||||||
| local is_index_set = false | ||||||||||||||
| local current_index = 0 | ||||||||||||||
| while not is_index_set do | ||||||||||||||
| if not app.fs.isFile(self:get_recording_image_path(current_index)) then | ||||||||||||||
| is_index_set = true | ||||||||||||||
| self.context:set_recording_index(current_index) | ||||||||||||||
| else | ||||||||||||||
| current_index = current_index + 1 | ||||||||||||||
| end | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| return self | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| function get_contextual_recording_image_path(self, index) | ||||||||||||||
| function RecordingContext:get_recording_image_path(index) | ||||||||||||||
| return app.fs.joinPath(self.record_directory_path, self.sprite_file_name .. "_" .. index .. ".png") | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| function get_recording_image_path_at_index(self, index) | ||||||||||||||
| return get_contextual_recording_image_path(self.context, index) | ||||||||||||||
| Snapshot = {} | ||||||||||||||
|
|
||||||||||||||
| function Snapshot:_initialize(sprite) | ||||||||||||||
| self.auto_snap_enabled = false | ||||||||||||||
| self.auto_snap_delay = 1 | ||||||||||||||
| self.auto_snap_increment = 0 | ||||||||||||||
| self.context = nil | ||||||||||||||
|
|
||||||||||||||
| -- Instance of Aseprite Sprite object | ||||||||||||||
| -- https://github.com/aseprite/api/blob/master/api/sprite.md#sprite | ||||||||||||||
| self.sprite = nil | ||||||||||||||
| if sprite then | ||||||||||||||
| self.sprite = sprite | ||||||||||||||
| self.context = RecordingContext.new(sprite) | ||||||||||||||
| end | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| function Snapshot:_increment_recording_index() | ||||||||||||||
| local index = self.context:get_recording_index(self) + 1 | ||||||||||||||
| self.context:set_recording_index(index) | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| function get_snapshot() | ||||||||||||||
| function Snapshot:get_recording_image_path(index) | ||||||||||||||
| return self.context:get_recording_image_path(index) | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| function Snapshot.new() | ||||||||||||||
| local self = {} | ||||||||||||||
| initialize_snapshot(self, nil) | ||||||||||||||
| setmetatable(self, { __index = Snapshot }) | ||||||||||||||
| self:_initialize(nil) | ||||||||||||||
| return self | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| function is_snapshot_active(self) | ||||||||||||||
| if not is_snapshot_valid(self) then | ||||||||||||||
| function Snapshot:is_active() | ||||||||||||||
| if not self:is_valid() then | ||||||||||||||
| return false | ||||||||||||||
| end | ||||||||||||||
| return self.auto_snap_enabled | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| function is_snapshot_valid(self) | ||||||||||||||
| function Snapshot:is_valid() | ||||||||||||||
| if self.sprite then | ||||||||||||||
| return true | ||||||||||||||
| end | ||||||||||||||
| return false | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| function reset_snapshot(self) | ||||||||||||||
| initialize_snapshot(self, nil) | ||||||||||||||
| function Snapshot:reset() | ||||||||||||||
| self:_initialize(nil) | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| function auto_save_snapshot(self) | ||||||||||||||
| function Snapshot:auto_save() | ||||||||||||||
| if not self.auto_snap_enabled then | ||||||||||||||
| return | ||||||||||||||
| end | ||||||||||||||
|
|
@@ -157,31 +176,75 @@ function auto_save_snapshot(self) | |||||||||||||
| return | ||||||||||||||
| end | ||||||||||||||
| self.auto_snap_increment = 0 | ||||||||||||||
| save_snapshot(self) | ||||||||||||||
| self:save() | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| function save_snapshot(self) | ||||||||||||||
| local path = get_recording_image_path_at_index(self, get_snapshot_recording_index(self)) | ||||||||||||||
| function Snapshot:_get_current_image() | ||||||||||||||
| local image = Image(self.sprite) | ||||||||||||||
| image:drawSprite(self.sprite, get_active_frame_number()) | ||||||||||||||
| return image | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| function Snapshot:_get_saved_image_content(index) | ||||||||||||||
| if index < 0 then | ||||||||||||||
| return nil | ||||||||||||||
| end | ||||||||||||||
| -- This intentionally does not do anything "smart" such as scanning the | ||||||||||||||
| -- directory if gaps exist because that is O(N) at IO speeds and on every | ||||||||||||||
| -- snapshot (where N is the current snapshot index). | ||||||||||||||
|
||||||||||||||
| -- This intentionally does not do anything "smart" such as scanning the | |
| -- directory if gaps exist because that is O(N) at IO speeds and on every | |
| -- snapshot (where N is the current snapshot index). |
Can prune these comments from the code, is preferable to maintain these types of artifacts in PR comments for history tracking.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ill be sure to beat this up as I have a computer considered average by 2012 standard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ Ran through a gambit of:
- Image creation
- cropping
- painting
- fills
- moving
- resizing
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| -- NOTE(teding): Unfortunately `Image { fromFile = path }`: | |
| -- * causes load popups | |
| -- * pollutes "recent files" | |
| -- Anyway, this seems more than fast enough for human inputs. I tried lots | |
| -- of very very fast changes on large detailed canvases, had no issues, and | |
| -- have a computer that is average by 2022 standards. |
Can prune these comments from the code, is preferable to maintain these types of artifacts in PR comments for history tracking.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -7,24 +7,23 @@ | |||||
|
|
||||||
| dofile(".lib/record-core.lua") | ||||||
|
|
||||||
| local snapshot = get_snapshot() | ||||||
| local snapshot = Snapshot.new() | ||||||
|
|
||||||
| local function take_snapshot() | ||||||
| update_snapshot_sprite(snapshot) | ||||||
| if not is_snapshot_valid(snapshot) then | ||||||
| snapshot:update_sprite() | ||||||
| if not snapshot:is_valid() then | ||||||
| return | ||||||
| end | ||||||
|
|
||||||
| save_snapshot(snapshot) | ||||||
| snapshot:save() | ||||||
| end | ||||||
|
|
||||||
| local function open_time_lapse() | ||||||
| update_snapshot_sprite(snapshot) | ||||||
| if not is_snapshot_valid(snapshot) then | ||||||
| snapshot:update_sprite() | ||||||
| if not snapshot:is_valid() then | ||||||
| return | ||||||
| end | ||||||
|
|
||||||
| local path = get_recording_image_path_at_index(snapshot, 0) | ||||||
| local path = snapshot:get_recording_image_path_at_index(0) | ||||||
|
||||||
| local path = snapshot:get_recording_image_path_at_index(0) | |
| local path = snapshot:get_recording_image_path(0) |
Method used is the old name, needs to be replaced with new one.
Uh oh!
There was an error while loading. Please reload this page.