-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tr2/screenshots: improve screenshots support
- Loading branch information
Showing
36 changed files
with
376 additions
and
402 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#include "game/clock.h" | ||
|
||
#include <stdio.h> | ||
#include <time.h> | ||
|
||
size_t Clock_GetDateTime(char *const buffer, const size_t size) | ||
{ | ||
time_t lt = time(0); | ||
struct tm *tptr = localtime(<); | ||
|
||
return snprintf( | ||
buffer, size, "%04d%02d%02d_%02d%02d%02d", tptr->tm_year + 1900, | ||
tptr->tm_mon + 1, tptr->tm_mday, tptr->tm_hour, tptr->tm_min, | ||
tptr->tm_sec); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
#pragma once | ||
|
||
#include <stddef.h> | ||
|
||
size_t Clock_GetDateTime(char *buffer, size_t size); | ||
extern double Clock_GetHighPrecisionCounter(void); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#pragma once | ||
|
||
extern bool Output_MakeScreenshot(const char *path); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#pragma once | ||
|
||
extern Output_MakeScreenshot(const char const path); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#pragma once | ||
|
||
#include <stdbool.h> | ||
|
||
typedef enum { | ||
SCREENSHOT_FORMAT_JPEG, | ||
SCREENSHOT_FORMAT_PNG, | ||
} SCREENSHOT_FORMAT; | ||
|
||
bool Screenshot_Make(SCREENSHOT_FORMAT format); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
#include "screenshot.h" | ||
|
||
#include "filesystem.h" | ||
#include "game/clock.h" | ||
#include "game/game.h" | ||
#include "game/gameflow/common.h" | ||
#include "game/output.h" | ||
#include "memory.h" | ||
|
||
#include <stdio.h> | ||
#include <string.h> | ||
|
||
#define SCREENSHOTS_DIR "screenshots" | ||
|
||
static char *M_GetScreenshotTitle(void); | ||
static char *M_CleanScreenshotTitle(const char *source); | ||
static char *M_GetScreenshotBaseName(void); | ||
static const char *M_GetScreenshotFileExt(SCREENSHOT_FORMAT format); | ||
static char *M_GetScreenshotPath(SCREENSHOT_FORMAT format); | ||
|
||
static char *M_CleanScreenshotTitle(const char *const source) | ||
{ | ||
// Sanitize screenshot title. | ||
// - Replace spaces with underscores | ||
// - Remove all non-alphanumeric characters | ||
// - Merge consecutive underscores together | ||
// - Remove leading underscores | ||
// - Remove trailing underscores | ||
char *result = Memory_Alloc(strlen(source) + 1); | ||
|
||
bool last_was_underscore = false; | ||
char *out = result; | ||
for (size_t i = 0; i < strlen(source); i++) { | ||
if (source[i] == ' ' || source[i] == '_') { | ||
if (!last_was_underscore && out > result) { | ||
*out++ = '_'; | ||
last_was_underscore = true; | ||
} | ||
} else if (((source[i] >= 'A' && source[i] <= 'Z') | ||
|| (source[i] >= 'a' && source[i] <= 'z') | ||
|| (source[i] >= '0' && source[i] <= '9'))) { | ||
*out++ = source[i]; | ||
last_was_underscore = false; | ||
} | ||
} | ||
*out++ = '\0'; | ||
|
||
// Strip trailing underscores | ||
while (out[-1] == '_' && out >= result) { | ||
out--; | ||
} | ||
*out = '\0'; | ||
|
||
return result; | ||
} | ||
|
||
static char *M_GetScreenshotTitle(void) | ||
{ | ||
const int32_t level_num = Game_GetCurrentLevelNum(); | ||
if (level_num < 0) { | ||
return Memory_DupStr("Intro"); | ||
} | ||
|
||
const char *const level_title = Gameflow_GetLevelTitle(level_num); | ||
if (level_title != NULL && strlen(level_title) > 0) { | ||
char *clean_level_title = M_CleanScreenshotTitle(level_title); | ||
if (clean_level_title != NULL && strlen(clean_level_title) > 0) { | ||
return clean_level_title; | ||
} | ||
Memory_FreePointer(clean_level_title); | ||
} | ||
|
||
// If title totally invalid, name it based on level number | ||
const char *const fmt = "Level_%d"; | ||
const size_t result_size = snprintf(NULL, 0, fmt, level_num) + 1; | ||
char *result = Memory_Alloc(result_size); | ||
snprintf(result, result_size, fmt, level_num); | ||
return result; | ||
} | ||
|
||
static char *M_GetScreenshotBaseName(void) | ||
{ | ||
char *screenshot_title = M_GetScreenshotTitle(); | ||
|
||
// Get timestamp | ||
char date_time[30]; | ||
Clock_GetDateTime(date_time, 30); | ||
|
||
// Full screenshot name | ||
const char *const fmt = "%s_%s"; | ||
const size_t out_size = | ||
snprintf(NULL, 0, fmt, date_time, screenshot_title) + 1; | ||
char *out = Memory_Alloc(out_size); | ||
snprintf(out, out_size, "%s_%s", date_time, screenshot_title); | ||
return out; | ||
} | ||
|
||
static const char *M_GetScreenshotFileExt(const SCREENSHOT_FORMAT format) | ||
{ | ||
switch (format) { | ||
case SCREENSHOT_FORMAT_JPEG: | ||
return "jpg"; | ||
case SCREENSHOT_FORMAT_PNG: | ||
return "png"; | ||
default: | ||
return "jpg"; | ||
} | ||
} | ||
|
||
static char *M_GetScreenshotPath(const SCREENSHOT_FORMAT format) | ||
{ | ||
char *base_name = M_GetScreenshotBaseName(); | ||
const char *const ext = M_GetScreenshotFileExt(format); | ||
|
||
char *full_path = Memory_Alloc( | ||
strlen(SCREENSHOTS_DIR) + strlen(base_name) + strlen(ext) + 6); | ||
sprintf(full_path, "%s/%s.%s", SCREENSHOTS_DIR, base_name, ext); | ||
if (File_Exists(full_path)) { | ||
for (int i = 2; i < 100; i++) { | ||
sprintf( | ||
full_path, "%s/%s_%d.%s", SCREENSHOTS_DIR, base_name, i, ext); | ||
if (!File_Exists(full_path)) { | ||
break; | ||
} | ||
} | ||
} | ||
|
||
Memory_FreePointer(&base_name); | ||
return full_path; | ||
} | ||
|
||
bool Screenshot_Make(const SCREENSHOT_FORMAT format) | ||
{ | ||
File_CreateDirectory(SCREENSHOTS_DIR); | ||
|
||
char *full_path = M_GetScreenshotPath(format); | ||
const bool result = Output_MakeScreenshot(full_path); | ||
Memory_FreePointer(&full_path); | ||
|
||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.