Skip to content
This repository has been archived by the owner on Aug 15, 2024. It is now read-only.

Commit

Permalink
Load time reductions and performance improvements.
Browse files Browse the repository at this point in the history
Loading screen now shows up faster.
Loading should be faster now.
Loading zip files should be faster now.
The bird has gone on caffeine withdrawal and now moves a lot less.
Fixed some cases of version hash not showing up.
Fixed some error messages not appearing in error log.
Trying to load a corrupted zip file now produces proper errors.
Fixed error when YAML loading is turned on.
Fixed blank material list when cloning inside the placement tool.

For plugin developers:
Made it possible to add your own menubar items.
Loading a bad module now errors more nicely.
Flagline code has been cleaned up to allow custom flagline rendering.
Multiple overlay sprites for tiles are now supported.

Co-authored-by: Vexatos <[email protected]>
  • Loading branch information
Cruor and Vexatos committed Aug 24, 2020
1 parent efc713d commit dd0dbf0
Show file tree
Hide file tree
Showing 22 changed files with 236 additions and 173 deletions.
2 changes: 1 addition & 1 deletion lang/en_gb.lang
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ settings.config.tooltips.backup_enabled=Whether automatic backups of maps should
settings.config.tooltips.backup_dialog_enabled=Whether Ahorn should ask the user to restore from a backup after an unexpected shutdown.
settings.config.tooltips.allow_out_of_bounds_placement=Whether you should be able to click outside of the room to place entities, triggers or decals.
settings.config.tooltips.everest_rcon=URL for Everest remote control.
settings.config.tooltips.load_image_meta_yaml=Loads the .meta.yaml image metadata files dumped by old Everest image dumps.\nNot recommended, If sprites are offset incorrectly, fix the sprite itself.
settings.config.tooltips.load_image_meta_yaml=Loads the .meta.yaml image metadata files dumped by old Everest image dumps.\nNot recommended, If sprites are offset incorrectly, fix the sprite itself. Increases load times.
settings.config.tooltips.split_atlas_into_smaller_surfaces=Splits the atlases from Celeste into smaller images for better performance. (Requires restart)


Expand Down
3 changes: 3 additions & 0 deletions src/Ahorn.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ using Gtk, Gtk.ShortNames, Gtk.GConstants
using Cairo
using Maple
using Random
using ZipFile
using YAML

function abspath(path::String)
return normpath(joinpath(@__DIR__, path))
Expand Down Expand Up @@ -58,6 +60,7 @@ sleep(0)
include("helpers/helpers.jl")
include("helpers/macros.jl")
include("helpers/config_helper.jl")
include("helpers/zip_file_helper.jl")
include("lang.jl")
include("validation_entry.jl")
include("mods.jl")
Expand Down
19 changes: 11 additions & 8 deletions src/auto_tiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ function convertTileString(s::String)
res = Coord[]

for part in parts
x, y = parse.(Int, split(part, ","))
rawX, rawY = split(part, ",")
x, y = parse(Int, rawX), parse(Int, rawY)

push!(res, Coord(x, y))
end
Expand Down Expand Up @@ -87,7 +88,7 @@ end
struct MaskData
mask::Mask
coords::Array{Coord, 1}
sprites::String
sprites::Array{String, 1}
end

struct Ignore
Expand Down Expand Up @@ -150,11 +151,13 @@ function loadTilesetXML(fn::String)
center[id] = quads

else
sprites = attribute(c, "sprites")
spritesRaw = attribute(c, "sprites")
sprites = isa(spritesRaw, String) ? split(spritesRaw, ",") : String[]

push!(currMasks, MaskData(
getMaskFromString(mask),
quads,
isa(sprites, String) ? sprites : ""
sprites
))
end
end
Expand Down Expand Up @@ -199,7 +202,7 @@ function loadFgTilerMeta(side::Union{Side, Nothing}, fn::String, loadDefault::Bo

try
global fgTilerMeta = TilerMeta(path)

catch e
if !loadDefault
println(Base.stderr, "Failed to load custom ForegroundTiles XML")
Expand Down Expand Up @@ -370,9 +373,9 @@ function getMaskQuads(x::Int, y::Int, tiles::Tiles, meta::TilerMeta)
end

if checkPadding(tiles.data, x, y, width, height)
return get(meta.paddings, value, defaultPaddingCoords), ""
return get(meta.paddings, value, defaultPaddingCoords), String[]

else
return get(meta.centers, value, defaultPaddingCoords), ""
return get(meta.centers, value, defaultPaddingCoords), String[]
end
end
34 changes: 19 additions & 15 deletions src/celeste_render.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ include("helpers/tileset_splitter.jl")

struct TileData
coord::Coord
sprite::String
sprites::Array{String, 1}
path::String
end

Expand All @@ -34,10 +34,10 @@ function getTileData(x::Int, y::Int, tiles::Tiles, meta::TilerMeta, states::Tile

if haskey(meta.paths, tileValue)
imagePath::String = meta.paths[tileValue]
quads::Array{Coord, 1}, sprite::String = getMaskQuads(x, y, tiles, meta)
quads::Array{Coord, 1}, sprites::Array{String, 1} = getMaskQuads(x, y, tiles, meta)
targetQuad::Coord = quads[Int(mod1(states.rands[y, x], length(quads)))]

return TileData(targetQuad, sprite, imagePath)
return TileData(targetQuad, sprites, imagePath)
end

return nothing
Expand Down Expand Up @@ -84,26 +84,30 @@ function drawTile(ctx::Cairo.CairoContext, x, y, tile, tiles, meta, states, exis
tileData = getTileData(x, y, tiles, meta, states)

if tileData !== nothing
quad, sprite = tileData.coord, tileData.sprite
quad, sprites = tileData.coord, tileData.sprites
imagePathExists = existingPaths[tile]

if imagePathExists
quadX, quadY = quad.x, quad.y

if !isempty(sprite)
animatedMeta = filter(m -> m.name == sprite, animatedTilesMeta)[1]
frames = findTextureAnimations(animatedMeta.path, getAtlas("Gameplay"))
if !isempty(sprites)
animatedMetas = filter(m -> m.name in sprites, animatedTilesMeta)

if !isempty(frames)
frame = frames[Int(mod1(states.rands[y, x], length(frames)))]
frameSprite = getSprite(frame, "Gameplay")
if !isempty(animatedMetas)
animatedMeta = animatedMetas[Int(mod1(states.rands[y, x], length(animatedMetas)))]
frames = findTextureAnimations(animatedMeta.path, getAtlas("Gameplay"))

ox = animatedMeta.posX - frameSprite.offsetX
oy = animatedMeta.posY - frameSprite.offsetY
if !isempty(frames)
frame = frames[Int(mod1(states.rands[y, x], length(frames)))]
frameSprite = getSprite(frame, "Gameplay")

# TODO - What do we actually have to clear here?
#clearArea(ctx, drawX + ox, drawY + oy, 8, 8)
drawImage(ctx, frame, drawX + ox, drawY + oy, alpha=alpha)
ox = animatedMeta.posX - frameSprite.offsetX
oy = animatedMeta.posY - frameSprite.offsetY

# TODO - What do we actually have to clear here?
#clearArea(ctx, drawX + ox, drawY + oy, 8, 8)
drawImage(ctx, frame, drawX + ox, drawY + oy, alpha=alpha)
end
end
end

Expand Down
9 changes: 7 additions & 2 deletions src/display_main_window.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,20 @@ function displayMainWindow()
@progress initSprites() "Getting sprites ready..." progressDialog
@progress initTilerMetas() "Getting tiles ready..." progressDialog
@progress initCamera() "Getting camera ready..." progressDialog
@progress initLangdata() "Getting language files ready..." progressDialog
@progress initMenubar() "Getting menubar ready..." progressDialog

@progress Backup.initBackup(persistence) "Starting backup handler..." progressDialog
@progress FileWatcher.initFileWatcher(normpath(joinpath(config["celeste_dir"], "Mods"))) "Starting file watcher..." progressDialog

@progress initEntities() "Loading entities..." progressDialog
@progress initTriggers() "Loading triggers..." progressDialog
@progress initEffects() "Loading effects..." progressDialog

@progress initExternalModules() "Loading external plugins..." progressDialog
@progress loadAllExternalSprites!() "Loading external sprites..." progressDialog

@progress initLangdata() "Getting language files ready..." progressDialog
@progress initMenubar() "Getting menubar ready..." progressDialog

@progress updateToolDisplayNames!(loadedTools) "Getting tools ready..." progressDialog
@progress updateToolList!(toolList) "Getting tools ready..." progressDialog

Expand Down
11 changes: 7 additions & 4 deletions src/drawing.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using YAML

include("extract_sprites_meta.jl")

const atlases = Dict{String, Dict{String, SpriteHolder}}()
Expand Down Expand Up @@ -35,6 +33,10 @@ const fileNotFoundSpriteHolder = SpriteHolder(
)

function getResourceFromZip(filename::String, resource::String, atlas::String, allowRetry=true)
if !hasExt(filename, ".zip")
return nothing
end

fileCache = get(resourceZipCache, filename, nothing)

if fileCache !== nothing
Expand Down Expand Up @@ -70,6 +72,7 @@ function getSpriteSurface(resource::String, filename::String, atlas="Gameplay")
return fileNotFoundSurface, filename
end

# Getting sprite meta from zip is slow with this method
function getSpriteMeta(resource::String, filename::String, atlas="Gameplay")
if !get(config, "load_image_meta_yaml", false)
return false, false
Expand All @@ -82,7 +85,6 @@ function getSpriteMeta(resource::String, filename::String, atlas="Gameplay")
if hasExt(filename, ".png")
if isfile(yamlFilename)
try

return true, open(YAML.load, yamlFilename)

catch
Expand All @@ -94,7 +96,7 @@ function getSpriteMeta(resource::String, filename::String, atlas="Gameplay")
end

elseif hasExt(filename, ".zip")
data = getResourceFromZip(resource, yamlFilename, atlas)
data = getResourceFromZip(filename, resource * ".meta.yaml", atlas)

return data !== nothing, something(data, metaYamlResourceNotFound)
end
Expand Down Expand Up @@ -183,6 +185,7 @@ function loadChangedExternalSprites!()
for (texture, raw, atlas) in externalSprites
if !(raw in unloadedZips) && hasExt(raw, ".zip")
uncacheZipContent(raw)
push!(unloadedZips, raw)
end

addSprite!(fixTexturePath(texture), raw, atlas=atlas, force=true)
Expand Down
1 change: 0 additions & 1 deletion src/effects.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,4 @@ function registerPlacements!(placements::Array{Type{Maple.Effect{T}} where T, 1}
end

const loadedEffects = joinpath.(abs"effects", readdir(abs"effects"))
loadModule.(loadedEffects)
const effectPlacements = Array{Type{Maple.Effect{T}} where T, 1}()
1 change: 0 additions & 1 deletion src/entities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,5 @@ function fillPlacementCache!(cache::Dict{String, T}, placements::PlacementDict,
end

const loadedEntities = joinpath.(abs"entities", readdir(abs"entities"))
loadModule.(loadedEntities)
const entityPlacements = PlacementDict()
const entityPlacementsCache = Dict{String, Entity}()
14 changes: 7 additions & 7 deletions src/entities/flagline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function Ahorn.selection(entity::flagLineUnion)
x, y = Ahorn.position(entity)

res = Ahorn.Rectangle[Ahorn.Rectangle(x - 4, y - 4, 8, 8)]

for node in nodes
nx, ny = node

Expand Down Expand Up @@ -68,7 +68,7 @@ const cliffMaxSpace = 8

const flaglineUnion = Union{Maple.ClothesLine, Maple.CliffFlags}

function renderFlagLine(ctx::Ahorn.Cairo.CairoContext, entity::flaglineUnion, lineColor::Ahorn.colorTupleType, pinColor::Ahorn.colorTupleType, colors::Array{Ahorn.colorTupleType, 1},
function renderFlagLine(ctx::Ahorn.Cairo.CairoContext, entity::Maple.Entity, lineColor::Ahorn.colorTupleType, pinColor::Ahorn.colorTupleType, colors::Array{Ahorn.colorTupleType, 1},
minFlagHeight::Integer, maxFlagHeight::Integer, minFlagLength::Integer, maxFlagLength::Integer, minSpace::Integer, maxSpace::Integer)
rng = Ahorn.getSimpleEntityRng(entity)
x, y = Ahorn.position(entity)
Expand Down Expand Up @@ -123,15 +123,15 @@ function renderFlagLine(ctx::Ahorn.Cairo.CairoContext, entity::flaglineUnion, li

flagCurve = Ahorn.SimpleCurve(lastPoint, point, (lastPoint .+ point) ./ 2 .+ (0, droopAmount * length))
prevFlagPoint = Ahorn.getPoint(flagCurve, 1 / length)

Ahorn.setSourceColor(ctx, color)

for i in 0:length
flagPoint = Ahorn.getPoint(flagCurve, i / length)

if flagPoint[1] > prevFlagPoint[1]
if flagPoint[1] > prevFlagPoint[1]
segmentWidth = min(floor(Int, flagPoint[1] - prevFlagPoint[1]), point[1] - flagPoint[1])

Ahorn.rectangle(ctx, flagPoint[1], flagPoint[2], segmentWidth, height - 1)
end

Expand Down Expand Up @@ -173,12 +173,12 @@ function Ahorn.renderSelectedAbs(ctx::Ahorn.Cairo.CairoContext, entity::Maple.Cl
cliffMinFlagLength, cliffMaxFlagLength, cliffMinSpace, cliffMaxSpace)
end

function Ahorn.renderAbs(ctx::Ahorn.Cairo.CairoContext, entity::Maple.ClothesLine, room::Maple.Room)
function Ahorn.renderAbs(ctx::Ahorn.Cairo.CairoContext, entity::Maple.ClothesLine)
renderFlagLine(ctx, entity, clothesLineColor, clothesPinColor, clothesColors, clothesMinFlagHeight, clothesMaxFlagHeight,
clothesMinFlagLength, clothesMaxFlagLength, clothesMinSpace, clothesMaxSpace)
end

function Ahorn.renderAbs(ctx::Ahorn.Cairo.CairoContext, entity::Maple.CliffFlags, room::Maple.Room)
function Ahorn.renderAbs(ctx::Ahorn.Cairo.CairoContext, entity::Maple.CliffFlags)
renderFlagLine(ctx, entity, cliffLineColor, cliffPinColor, cliffColors, cliffMinFlagHeight, cliffMaxFlagHeight,
cliffMinFlagLength, cliffMaxFlagLength, cliffMinSpace, cliffMaxSpace)
end
Expand Down
7 changes: 5 additions & 2 deletions src/helpers/gtk_helpers.jl
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
const eventMouse = Union{Gtk.GdkEventButton, Gtk.GdkEventMotion, Gtk.GdkEventCrossing}
const eventKey = Gtk.GdkEventKey

# Text won't update unless we sleep a reasonable amount of time
# LoadingSpinner usually sleeps for us when animating
macro progress(e::Expr, msg, dialog)
return quote
if !disableLoadingScreen && $dialog !== nothing
set_gtk_property!($dialog, :secondary_text, $msg)
LoadingSpinner.animate($dialog)
waitForIdle()
if !LoadingSpinner.animate($dialog)
sleep(0.025)
end
end

$e
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/macros.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ macro catchall(expr)

for (exc, bt) in Base.catch_stack()
showerror(Base.stderr, exc, bt)
println()
println(Base.stderr, "")
end
end
end
Expand Down
18 changes: 8 additions & 10 deletions src/init_ahorn.jl
Original file line number Diff line number Diff line change
Expand Up @@ -112,33 +112,31 @@ function needsExtraction(from::String, to::String, force::Bool=false)
end

function extractGamedata(storage::String, force::Bool=false)
celesteGraphics = joinpath(config["celeste_dir"], "Content", "Graphics")
celesteGraphics = joinpath(config["celeste_dir"], "Content", "Graphics")
celesteAtlases = joinpath(celesteGraphics, "Atlases")

storageXML = joinpath(storage, "XML")
storageSprites = joinpath(storage, "Sprites")
requiredFiles = (

requiredFiles = Tuple{String, String}[
(joinpath(celesteGraphics, "ForegroundTiles.xml"), joinpath(storageXML, "ForegroundTiles.xml")),
(joinpath(celesteGraphics, "BackgroundTiles.xml"), joinpath(storageXML, "BackgroundTiles.xml")),
(joinpath(celesteGraphics, "AnimatedTiles.xml"), joinpath(storageXML, "AnimatedTiles.xml")),
(joinpath(celesteGraphics, "Sprites.xml"), joinpath(storageXML, "Sprites.xml")),
(joinpath(celesteGraphics, "Portraits.xml"), joinpath(storageXML, "Portraits.xml")),

(joinpath(celesteAtlases, "Gameplay.meta"), joinpath(storageSprites, "Gameplay.meta")),
(joinpath(celesteAtlases, "Gui.meta"), joinpath(storageSprites, "Gui.meta")),
(joinpath(celesteAtlases, "Portraits.meta"), joinpath(storageSprites, "Portraits.meta")),
(joinpath(celesteAtlases, "Misc.meta"), joinpath(storageSprites, "Misc.meta"))
)
]

requiredAtlases = (
requiredAtlases = Tuple{String, String}[
(joinpath(celesteAtlases, "Gameplay0.data"), joinpath(storageSprites, "Gameplay.png")),
(joinpath(celesteAtlases, "Gui0.data"), joinpath(storageSprites, "Gui.png"))
)
]

gameplaySprites = joinpath(storage, "Gameplay.png")

needsInclude = any(Bool[needsExtraction(from, to, force) for (from, to) in requiredAtlases])
needsInclude = any(Bool[needsExtraction(from, to, force) for (from, to) in requiredAtlases])

if needsInclude
include(Ahorn.abs"extract_sprites_images.jl")
Expand Down
14 changes: 13 additions & 1 deletion src/init_globals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ end
function initConfigs()
if Sys.iswindows()
global storageDirectory = joinpath(ENV["LOCALAPPDATA"], "Ahorn")

else
global storageDirectory = joinpath(get(ENV, "XDG_CONFIG_HOME", joinpath(get(ENV, "HOME", ""), ".config")) , "Ahorn")
end
Expand All @@ -56,4 +56,16 @@ function initMenubar()
append!(choices, menubarEndChoices)

global menubar = Menubar.generateMenubar(choices)
end

function initEntities()
loadModule.(loadedEntities)
end

function initTriggers()
loadModule.(loadedTriggers)
end

function initEffects()
loadModule.(loadedEffects)
end
Loading

0 comments on commit dd0dbf0

Please sign in to comment.