Skip to content

Commit

Permalink
Merge pull request #57 from Lucki/new_cover
Browse files Browse the repository at this point in the history
Support the new cover format
  • Loading branch information
boppreh authored Dec 18, 2019
2 parents eac4d3f + 0d48652 commit b833674
Show file tree
Hide file tree
Showing 7 changed files with 625 additions and 148 deletions.
21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,23 @@ again when you get more games or want to update the category overlays.
# How to use #

1. Download the [latest version](https://github.com/boppreh/steamgrid/releases/latest) and extract the zip wherever.
2. *(optional)* Name the overlays after your categories. So if you have a category "Games I Love", put a nice little heart overlay there named "games i love.png". You can rename the defaults that came with the zip or get new ones at [/r/steamgrid](http://www.reddit.com/r/steamgrid/wiki/overlays).
3. *(optional)* Download a pack of custom images and place it in the `games/` folder. The image files can be either the name of the game (e.g. "Psychonauts.png") or the game id (e.g. "3830.png").
4. Run `steamgrid` and wait. No, really, it's all automatic. Not a single keypress required.
5. Read the report and open Steam in grid view to check the results.
2. *(optional)* Name the overlays after your categories. So if you have a category "Games I Love", put a nice little heart overlay there named `games i love.banner.png`. You can rename the defaults that came with the zip or get new ones at [/r/steamgrid](http://www.reddit.com/r/steamgrid/wiki/overlays).
* Add the extension `.banner` before the image extension for banner art: `games i love.banner.png`
* Add the extension `.cover` before the image extension for cover art: `games i love.cover.png`
* Add the extension `.hero` before the image extension for hero art `games i love.hero.png`
* Add the extension `.logo` before the image extension for logo art `games i love.logo.png`
3. *(optional)* Download a pack of custom images and place it in the `games/` folder. The image files can be either the name of the game (e.g. `Psychonauts.banner.png`) or the game id (e.g. `3830.png`).
* Add the extension `.banner` before the image extension for banner art: `Psychonauts.banner.png`, `3830.png`
* Add the extension `.cover`/`p` before the image extension for cover art: `Psychonauts.cover.png`, `3830p.png`
* Add the extension `.hero`/`_hero` before the image extension for hero art `Psychonauts.hero.png`, `3830_hero.png`
* Add the extension `.logo`/`_hero` before the image extension for logo art `Psychonauts.logo.png`, `3830_logo.png`
4. *(optional)* Generate a some API Keys to enhance the automatic search:
* [SteamGridDB API Key](https://www.steamgriddb.com/profile/preferences)
* [IGDB API Key](https://api.igdb.com/signup)
5. Run `steamgrid` and wait. No, really, it's all automatic. Not a single keypress required.
* *(optional)* Append `--steamgriddb <api key>` if you've generated one before.
* *(optional)* Append `--igdb <api key>` if you've genereated one before.
6. Read the report and open Steam in grid view to check the results.

---

Expand Down
50 changes: 37 additions & 13 deletions backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,38 @@ package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"runtime"
"unicode"
)

// BackupGame if a game has a custom image, backs it up by appending "(original)" to the
// file name.
func BackupGame(gridDir string, game *Game) error {
func BackupGame(gridDir string, game *Game, artStyleExtensions []string) error {
if game.CleanImageBytes != nil {
return ioutil.WriteFile(getBackupPath(gridDir, game), game.CleanImageBytes, 0666)
return ioutil.WriteFile(getBackupPath(gridDir, game, artStyleExtensions), game.CleanImageBytes, 0666)
}
return nil
}

func getBackupPath(gridDir string, game *Game) string {
func getBackupPath(gridDir string, game *Game, artStyleExtensions []string) string {
hash := sha256.Sum256(game.OverlayImageBytes)
// [:] is required to convert a fixed length byte array to a byte slice.
hexHash := hex.EncodeToString(hash[:])
return filepath.Join(gridDir, "originals", game.ID+" "+hexHash+game.ImageExt)
return filepath.Join(gridDir, "originals", game.ID + artStyleExtensions[0] + " " + hexHash+game.ImageExt)
}

func RemoveExisting(gridDir string, gameId string) error {
images, err := filepath.Glob(filepath.Join(gridDir, gameId+".*"))
func RemoveExisting(gridDir string, gameId string, artStyleExtensions []string) error {
images, err := filepath.Glob(filepath.Join(gridDir, gameId + artStyleExtensions[0] + ".*"))
if err != nil {
return err
}

backups, err := filepath.Glob(filepath.Join(gridDir, "originals", gameId+" *.*"))
backups, err := filepath.Glob(filepath.Join(gridDir, "originals", gameId + artStyleExtensions[0] + " *.*"))
if err != nil {
return err
}
Expand All @@ -57,8 +60,25 @@ func loadImage(game *Game, sourceName string, imagePath string) error {
return err
}

func LoadExisting(overridePath string, gridDir string, game *Game) {
overridenIDs, _ := filepath.Glob(filepath.Join(overridePath, game.ID+".*"))
// https://wenzr.wordpress.com/2018/04/09/go-glob-case-insensitive/
func InsensitiveFilepath(path string) string {
if runtime.GOOS == "windows" {
return path
}

p := ""
for _, r := range path {
if unicode.IsLetter(r) {
p += fmt.Sprintf("[%c%c]", unicode.ToLower(r), unicode.ToUpper(r))
} else {
p += string(r)
}
}
return p
}

func LoadExisting(overridePath string, gridDir string, game *Game, artStyleExtensions []string) {
overridenIDs, _ := filepath.Glob(filepath.Join(overridePath, game.ID + artStyleExtensions[0] + ".*"))
if overridenIDs != nil && len(overridenIDs) > 0 {
loadImage(game, "local file in directory 'games'", overridenIDs[0])
return
Expand All @@ -67,15 +87,15 @@ func LoadExisting(overridePath string, gridDir string, game *Game) {
if game.Name != "" {
re := regexp.MustCompile(`\W+`)
globName := re.ReplaceAllString(game.Name, "*")
overridenNames, _ := filepath.Glob(filepath.Join(overridePath, globName+".*"))
overridenNames, _ := filepath.Glob(filepath.Join(overridePath, InsensitiveFilepath(globName) + artStyleExtensions[1] + ".*"))
if overridenNames != nil && len(overridenNames) > 0 {
loadImage(game, "local file in directory games/", overridenNames[0])
return
}
}

// If there are any old-style backups (without hash), load them over the existing (with overlay) images.
oldBackups, err := filepath.Glob(filepath.Join(gridDir, game.ID+" (original)*"))
oldBackups, err := filepath.Glob(filepath.Join(gridDir, game.ID + artStyleExtensions[0] + " (original)*"))
if err == nil && len(oldBackups) > 0 {
err = loadImage(game, "legacy backup (now converted)", oldBackups[0])
if err == nil {
Expand All @@ -84,14 +104,18 @@ func LoadExisting(overridePath string, gridDir string, game *Game) {
}
}

files, err := filepath.Glob(filepath.Join(gridDir, game.ID+".*"))
files, err := filepath.Glob(filepath.Join(gridDir, game.ID + artStyleExtensions[0] + ".*"))
if err == nil && len(files) > 0 {
err = loadImage(game, "manual customization", files[0])
if err == nil {
// set as overlay to check for hash in getBackupPath()
game.OverlayImageBytes = game.CleanImageBytes

// See if there exists a backup image with no overlays or modifications.
loadImage(game, "backup", getBackupPath(gridDir, game))
loadImage(game, "backup", getBackupPath(gridDir, game, artStyleExtensions))

// remove overlay
game.OverlayImageBytes = nil
}
}

Expand Down
Loading

0 comments on commit b833674

Please sign in to comment.