Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,12 @@ if(PLATFORM STREQUAL "desktop")
# Matches the GitHub Actions container flags (FORTIFY requires building with optimizations enabled!)
target_compile_options(butterscotch PRIVATE "$<$<CONFIG:Release,RelWithDebInfo>:-U_FORTIFY_SOURCE;-D_FORTIFY_SOURCE=2>")

if(APPLE AND NOT IOS)
target_sources(butterscotch PRIVATE src/desktop/backends/platform/macos.m)
find_library(COCOA_LIBRARY Cocoa REQUIRED)
target_link_libraries(butterscotch PRIVATE ${COCOA_LIBRARY})
endif()

if(NOT ENABLE_LEGACY_GL AND NOT ENABLE_MODERN_GL)
message(FATAL_ERROR "You must enable at least one renderer!")
endif()
Expand Down
21 changes: 18 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,35 @@ PKG_CONFIG_FLAGS := --static
endif
INCLUDES += $(INCLUDE)src/desktop
ifeq ($(DESKTOP_BACKEND),glfw3)
GLFW3_LIBS += $(shell $(PKG_CONFIG) $(PKG_CONFIG_FLAGS) --libs glfw3)
GLFW3_CFLAGS := $(shell $(PKG_CONFIG) $(PKG_CONFIG_FLAGS) --cflags glfw3)
GLFW3_LIBS := $(shell $(PKG_CONFIG) $(PKG_CONFIG_FLAGS) --libs glfw3)
CFLAGS += $(GLFW3_CFLAGS)
LIBS += $(GLFW3_LIBS)
DEFINES += $(DEFINE)USE_GLFW3
ENABLE_GLAD := 1
ifeq ($(OS),Darwin)
SRCS += src/desktop/backends/platform/macos.m
LIBS += -framework Cocoa
endif
endif
ifeq ($(DESKTOP_BACKEND),glfw2)
GLFW2_LIBS += $(shell $(PKG_CONFIG) $(PKG_CONFIG_FLAGS) --libs libglfw)
LIBS += $(GLFW2_LIBS)
DEFINES += $(DEFINE)USE_GLFW2
ENABLE_GLAD := 1
ifeq ($(OS),Darwin)
SRCS += src/desktop/backends/platform/macos.m
LIBS += -framework Cocoa
endif
endif
ifeq ($(DESKTOP_BACKEND),sdl1)
SDL1_LIBS += $(shell $(PKG_CONFIG) $(PKG_CONFIG_FLAGS) --libs sdl)
LIBS += $(SDL1_LIBS)
DEFINES += $(DEFINE)USE_SDL1
ifeq ($(OS),Darwin)
SRCS += src/desktop/backends/platform/macos.m
LIBS += -framework Cocoa
endif
endif
ifeq ($(DESKTOP_BACKEND),sdl2)
SDL2_LIBS += $(shell $(PKG_CONFIG) $(PKG_CONFIG_FLAGS) --libs sdl2)
Expand Down Expand Up @@ -193,7 +207,8 @@ ifndef VERBOSE
V := @
endif

OBJS := $(addprefix build/,$(SRCS:.c=.c.$(OBJ_EXT)))
OBJS := $(addprefix build/,$(SRCS))
OBJS := $(OBJS:%=%.$(OBJ_EXT))

all: build/butterscotch

Expand All @@ -211,7 +226,7 @@ build/butterscotch: $(OBJS)
$(V)MSYS2_ARG_CONV_EXCL='*' $(_CC) $(LDFLAGS) $(OBJS) $(LIBS) $(EXTRALIBS) $(OUTPUT_EXE)$@
@[ -f $@.exe ] && chmod +x $@.exe || true

build/%.c.$(OBJ_EXT): %.c compat/config.mk $(if $(DISABLE_MMD),$(HEADERS))
build/%.$(OBJ_EXT): % compat/config.mk $(if $(DISABLE_MMD),$(HEADERS))
@mkdir -p $(dir $@)
@{ [ -z "$(NO_COLOR)" ] && [ -t 1 ]; } && printf " \033[1;32mCC\033[0m $<\n" || printf " CC $<\n"
$(V)MSYS2_ARG_CONV_EXCL='*' $(_CC) $(DEFINES) $(INCLUDES) $(CFLAGS) $(DEPFLAGS) $(COMPILE_OBJ) $(SRCFLAG)$< $(OUTPUT_OBJ)$@
Expand Down
14 changes: 14 additions & 0 deletions src/desktop/backends/glfw2.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,20 @@ static bool tryOpenWindow(int reqW, int reqH) {
#endif
}

#ifdef TARGET_OS_MAC
void show_error_box(const char *message);
#endif

void platformShowErrorDialogue(const char* message) {
#ifdef _WIN32
MessageBoxA(NULL, message, "Error", MB_OK | MB_ICONERROR);
#elif defined(TARGET_OS_MAC)
show_error_box(message);
#else
(void)message; // Suppress unused parameter warning
#endif
}

void platformSetWindowTitle(const char* title) {
char windowTitle[256];
snprintf(windowTitle, sizeof(windowTitle), "Butterscotch - %s", title);
Expand Down
14 changes: 14 additions & 0 deletions src/desktop/backends/glfw3.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,20 @@ static GLFWwindow *tryOpenWindow(int reqW, int reqH, const char* title) {
return NULL;
}

#ifdef TARGET_OS_MAC
void show_error_box(const char *message);
#endif

void platformShowErrorDialogue(const char* message) {
#ifdef _WIN32
MessageBoxA(NULL, message, "Error", MB_OK | MB_ICONERROR);
#elif defined(TARGET_OS_MAC)
show_error_box(message);
#else
(void)message; // Suppress unused parameter warning
#endif
}

void platformSetWindowTitle(const char* title) {
char windowTitle[256];
snprintf(windowTitle, sizeof(windowTitle), "Butterscotch - %s", title);
Expand Down
37 changes: 37 additions & 0 deletions src/desktop/backends/platform/macos.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include <AvailabilityMacros.h>
#include <AppKit/AppKit.h>

static void show_error_box(const char *message)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 // NSAlert is available in 10.3 and later

NSAlert *alert = [[NSAlert alloc] init];

[alert setMessageText:@"Error"];
[alert setInformativeText:[NSString stringWithUTF8String:message]];
[alert addButtonWithTitle:@"OK"];
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 // NSAlertStyleCritical is available in 10.12 and later
[alert setAlertStyle:NSAlertStyleCritical];
#else
[alert setAlertStyle:NSCriticalAlertStyle];
#endif

[alert runModal];
[alert release];

#else

NSRunAlertPanel(
@"Error",
[NSString stringWithUTF8String:message],
@"OK",
nil,
nil
);

#endif

[pool drain];
}
19 changes: 19 additions & 0 deletions src/desktop/backends/sdl1.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
#include <ctype.h>
#include <stdlib.h>

#ifdef _WIN32
#include <windows.h>
#endif

#include <SDL/SDL.h>

#include "common.h"
Expand Down Expand Up @@ -201,6 +205,21 @@ static void loadGamepadMappings(void) {
}
fclose(f);
}

#ifdef TARGET_OS_MAC
void show_error_box(const char *message);
#endif

void platformShowErrorDialogue(const char* message) {
#ifdef _WIN32
MessageBoxA(NULL, message, "Error", MB_OK | MB_ICONERROR);
#elif defined(TARGET_OS_MAC)
show_error_box(message);
#else
(void)message; // Suppress unused parameter warning
#endif
}

void platformSetWindowTitle(const char* title) {
char windowTitle[256];
snprintf(windowTitle, sizeof(windowTitle), "Butterscotch - %s", title);
Expand Down
9 changes: 9 additions & 0 deletions src/desktop/backends/sdl2.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,15 @@ static SDL_Window *tryOpenWindow(int reqW, int reqH, const char* title, Uint32 f
return NULL;
}

void platformShowErrorDialogue(const char* message) {
SDL_ShowSimpleMessageBox(
SDL_MESSAGEBOX_ERROR,
"Error",
message,
NULL
);
}

void platformSetWindowTitle(const char* title) {
char windowTitle[256];
snprintf(windowTitle, sizeof(windowTitle), "Butterscotch - %s", title);
Expand Down
9 changes: 9 additions & 0 deletions src/desktop/backends/sdl3.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,15 @@ static SDL_Window *tryOpenWindow(int reqW, int reqH, const char* title, Uint32 f
return NULL;
}

void platformShowErrorDialogue(const char* message) {
SDL_ShowSimpleMessageBox(
SDL_MESSAGEBOX_ERROR,
"Error",
message,
NULL
);
}

void platformSetWindowTitle(const char* title) {
char windowTitle[256];
snprintf(windowTitle, sizeof(windowTitle), "Butterscotch - %s", title);
Expand Down
1 change: 1 addition & 0 deletions src/desktop/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1420,6 +1420,7 @@ int main(int argc, char* argv[]) {
runner->setWindowSize = platformSetWindowSize;
runner->getWindowSize = platformGetWindowSize;
runner->setWindowTitle = platformSetWindowTitle;
runner->showErrorDialogue = platformShowErrorDialogue;
Runner_setGameArgs(runner, currentGameArgs, (int32_t) arrlen(currentGameArgs));
platformInitFunctions(runner);

Expand Down
1 change: 1 addition & 0 deletions src/desktop/platformdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ bool platformGetScaledWindowSize(int32_t* outW, int32_t* outH);
void platformSetWindowSize(int32_t width, int32_t height);
void platformSetWindowTitle(const char* title);
void platformSleepUntil(uint64_t time);
void platformShowErrorDialogue(const char* message);

enum GraphicsAPI {
SOFTWARE,
Expand Down
1 change: 1 addition & 0 deletions src/runner.h
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ struct Runner {
void (*setWindowTitle)(const char* title);
bool (*getWindowSize)(int32_t* outW, int32_t* outH);
void (*setWindowSize)(int32_t width, int32_t height);
void (*showErrorDialogue)(const char* message);
bool (*windowHasFocus)(void);
void (*setCursor)(int32_t cursorType);
int32_t currentCursor; // last value passed to window_set_cursor
Expand Down
27 changes: 27 additions & 0 deletions src/vm_builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -1821,6 +1821,32 @@ static RValue builtin_show_debug_message(MAYBE_UNUSED VMContext* ctx, RValue* ar
return RValue_makeUndefined();
}

// show_error(str, abort) - Displays an error message and optionally aborts the game
static RValue builtin_show_error(MAYBE_UNUSED VMContext* ctx, RValue* args, int32_t argCount) {
if (1 > argCount) {
fprintf(stderr, "[show_error] Expected at least 1 argument\n");
return RValue_makeUndefined();
}

char* val = RValue_toString(args[0]);
bool abort = false;
if (2 <= argCount) abort = RValue_toBool(args[1]);

fprintf(stderr, "[show_error] %s\n", val);
Runner* runner = ctx->runner;
if (runner->showErrorDialogue) {
runner->showErrorDialogue(val);
}
free(val);

if (abort) {
fprintf(stderr, "Game aborted due to show_error() call.\n");
exit(EXIT_FAILURE);
}

return RValue_makeUndefined();
}

static RValue builtin_string_length(MAYBE_UNUSED VMContext* ctx, RValue* args, int32_t argCount) {
if (1 > argCount) return RValue_makeInt32(0);
// GML converts non-string arguments to string before measuring length
Expand Down Expand Up @@ -16368,6 +16394,7 @@ void VMBuiltins_registerAll(VMContext* ctx) {

// Core output
VM_registerBuiltin(ctx, "show_debug_message", builtin_show_debug_message);
VM_registerBuiltin(ctx, "show_error", builtin_show_error);

// String functions
VM_registerBuiltin(ctx, "string_length", builtin_string_length);
Expand Down
Loading