mirror of
https://github.com/love2d/love-android.git
synced 2026-08-19 20:20:25 +02:00
Update LÖVE to changeset 7cb21c8bdd64 (pre 0.10.0)
This commit is contained in:
+1
-2
@@ -19,7 +19,6 @@ LOCAL_C_INCLUDES := \
|
||||
${LOCAL_PATH}/../SDL2-2.0.3/include \
|
||||
${LOCAL_PATH}/../jasper-1.900.1/src/libjasper/include \
|
||||
${LOCAL_PATH}/../libmng-1.0.10/ \
|
||||
${LOCAL_PATH}/../libjpeg-turbo-1.3.1/ \
|
||||
${LOCAL_PATH}/../lcms2-2.5/include \
|
||||
${LOCAL_PATH}/../tiff-3.9.5/libtiff \
|
||||
${LOCAL_PATH}/../openal-soft-1.17.0/include \
|
||||
@@ -100,7 +99,7 @@ LOCAL_CXXFLAGS := -std=c++0x
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := libopenal libmpg123
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := libphysfs libvorbis libogg libmodplug libfreetype libturbo-jpeg libluajit SDL2_static
|
||||
LOCAL_STATIC_LIBRARIES := libphysfs libvorbis libogg libmodplug libfreetype libluajit SDL2_static
|
||||
|
||||
# $(info liblove: include dirs $(LOCAL_C_INCLUDES))
|
||||
# $(info liblove: src files $(LOCAL_SRC_FILES))
|
||||
|
||||
@@ -134,7 +134,7 @@ Variant::~Variant()
|
||||
|
||||
Variant *Variant::fromLua(lua_State *L, int n, bool allowTables)
|
||||
{
|
||||
Variant *v = NULL;
|
||||
Variant *v = nullptr;
|
||||
size_t len;
|
||||
const char *str;
|
||||
if (n < 0) // Fix the stack position, we might modify it later
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2014 LOVE Development Team
|
||||
* Copyright (c) 2006-2015 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -90,7 +90,7 @@ double getScreenScale()
|
||||
return result;
|
||||
}
|
||||
|
||||
const char* getSelectedGameFile()
|
||||
const char *getSelectedGameFile()
|
||||
{
|
||||
static const char *path = NULL;
|
||||
|
||||
@@ -191,19 +191,19 @@ bool directoryExists(const char *path)
|
||||
if (err == -1)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
SDL_Log ("Error checking for directory %s errno = %d: %s", path, errno, strerror(errno));
|
||||
SDL_Log("Error checking for directory %s errno = %d: %s", path, errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
return S_ISDIR(s.st_mode);
|
||||
}
|
||||
|
||||
bool mkdir(const char* path)
|
||||
bool mkdir(const char *path)
|
||||
{
|
||||
int err = ::mkdir (path, 0770);
|
||||
int err = ::mkdir(path, 0770);
|
||||
if (err == -1)
|
||||
{
|
||||
SDL_Log ("Error: Could not create directory %s", path);
|
||||
SDL_Log("Error: Could not create directory %s", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2014 LOVE Development Team
|
||||
* Copyright (c) 2006-2015 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -35,8 +35,8 @@ namespace android
|
||||
/**
|
||||
* Enables or disables immersive mode where the navigation bar is hidden.
|
||||
**/
|
||||
void setImmersive (bool immersive_active);
|
||||
bool getImmersive ();
|
||||
void setImmersive(bool immersive_active);
|
||||
bool getImmersive();
|
||||
|
||||
/**
|
||||
* Gets the scale factor of the window's screen, e.g. on Retina displays this
|
||||
@@ -47,24 +47,24 @@ double getScreenScale();
|
||||
/**
|
||||
* Gets the selected love file in the device filesystem.
|
||||
**/
|
||||
const char* getSelectedGameFile();
|
||||
const char *getSelectedGameFile();
|
||||
|
||||
bool openURL (const std::string &url);
|
||||
bool openURL(const std::string &url);
|
||||
|
||||
void vibrate (double seconds);
|
||||
void vibrate(double seconds);
|
||||
|
||||
/*
|
||||
* Helper functions for the filesystem module
|
||||
*/
|
||||
void freeGameArchiveMemory (void *ptr);
|
||||
void freeGameArchiveMemory(void *ptr);
|
||||
|
||||
bool loadGameArchiveToMemory (const char* filename, char **ptr, size_t *size);
|
||||
bool loadGameArchiveToMemory(const char *filename, char **ptr, size_t *size);
|
||||
|
||||
bool directoryExists(const char* path);
|
||||
bool directoryExists(const char *path);
|
||||
|
||||
bool mkdir (const char* path);
|
||||
bool mkdir(const char *path);
|
||||
|
||||
bool createStorageDirectories ();
|
||||
bool createStorageDirectories();
|
||||
|
||||
} // android
|
||||
} // love
|
||||
|
||||
@@ -21,15 +21,6 @@
|
||||
#ifndef LOVE_INT_H
|
||||
#define LOVE_INT_H
|
||||
|
||||
// fixes compile errors of the form:
|
||||
// "error: expected unqualified-id before '__extension__'"
|
||||
#ifdef LOVE_ANDROID
|
||||
#include <sys/endian.h>
|
||||
#undef swap16
|
||||
#undef swap32
|
||||
#undef swap64
|
||||
#endif
|
||||
|
||||
// C standard sized integer types.
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2015 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_IOS_H
|
||||
#define LOVE_IOS_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef LOVE_IOS
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace ios
|
||||
{
|
||||
|
||||
/**
|
||||
* Gets the filepath of the first detected love file. The main .app Bundle is
|
||||
* searched first, and then the app's Documents folder.
|
||||
**/
|
||||
std::string getLoveInResources(bool &fused);
|
||||
|
||||
/**
|
||||
* Gets the directory path where files should be stored.
|
||||
**/
|
||||
std::string getAppdataDirectory();
|
||||
|
||||
/**
|
||||
* Get the home directory (on iOS, this really means the app's sandbox dir.)
|
||||
**/
|
||||
std::string getHomeDirectory();
|
||||
|
||||
/**
|
||||
* Opens the specified URL with the default program associated with the URL's
|
||||
* scheme.
|
||||
**/
|
||||
bool openURL(const std::string &url);
|
||||
|
||||
/**
|
||||
* Returns the full path to the executable.
|
||||
**/
|
||||
std::string getExecutablePath();
|
||||
|
||||
/**
|
||||
* Causes devices with vibration support to vibrate for about 0.5 seconds.
|
||||
**/
|
||||
void vibrate();
|
||||
|
||||
} // ios
|
||||
} // love
|
||||
|
||||
#endif // LOVE_IOS
|
||||
#endif // LOVE_IOS_H
|
||||
@@ -0,0 +1,350 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2015 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "ios.h"
|
||||
|
||||
#ifdef LOVE_IOS
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <AudioToolbox/AudioServices.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <SDL_events.h>
|
||||
|
||||
static NSArray *getLovesInDocuments();
|
||||
static bool deleteFileInDocuments(NSString *filename);
|
||||
|
||||
@interface LOVETableViewController : UITableViewController
|
||||
|
||||
- (instancetype)initWithGameList:(NSArray *)list;
|
||||
|
||||
@property (nonatomic) NSMutableArray *gameList;
|
||||
@property (nonatomic, readonly, copy) NSString *selectedGame;
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOVETableViewController
|
||||
|
||||
- (instancetype)initWithGameList:(NSArray *)list
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
_gameList = [[NSMutableArray alloc] initWithArray:list copyItems:YES];
|
||||
|
||||
self.title = @"LÖVE Games";
|
||||
self.navigationItem.rightBarButtonItem = self.editButtonItem;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
#pragma unused(tableView)
|
||||
#pragma unused(section)
|
||||
// We want to list all games plus the no-game screen.
|
||||
return self.gameList.count + 1;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
static NSString *cellIdentifier = @"LOVETableCell";
|
||||
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
|
||||
if (cell == nil)
|
||||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
|
||||
|
||||
if (indexPath.row < (NSInteger) self.gameList.count)
|
||||
cell.textLabel.text = self.gameList[indexPath.row];
|
||||
else
|
||||
cell.textLabel.text = @"No-game screen";
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
#pragma unused(tableView)
|
||||
if (indexPath.row < (NSInteger) self.gameList.count)
|
||||
_selectedGame = [(NSString *)(self.gameList[indexPath.row]) copy];
|
||||
else
|
||||
{
|
||||
// We test against nil to check if a game has been selected, so we'll
|
||||
// just use an empty string instead to represent the no-game screen.
|
||||
_selectedGame = @"";
|
||||
}
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if (editingStyle != UITableViewCellEditingStyleDelete)
|
||||
return;
|
||||
|
||||
if (indexPath.row >= (NSInteger) self.gameList.count)
|
||||
return;
|
||||
|
||||
NSString *filename = self.gameList[indexPath.row];
|
||||
|
||||
// Delete the file.
|
||||
if (deleteFileInDocuments(filename))
|
||||
{
|
||||
[self.gameList removeObjectAtIndex:indexPath.row];
|
||||
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;
|
||||
{
|
||||
#pragma unused(tableView)
|
||||
// The no-game screen isn't removable.
|
||||
return indexPath.row < (NSInteger) self.gameList.count;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static NSString *getDocumentsDirectory()
|
||||
{
|
||||
NSArray *docdirs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
return docdirs[0];
|
||||
}
|
||||
|
||||
static NSArray *getLovesInDocuments()
|
||||
{
|
||||
NSMutableArray *paths = [NSMutableArray new];
|
||||
|
||||
NSFileManager *manager = [NSFileManager defaultManager];
|
||||
NSDirectoryEnumerator *enumerator = [manager enumeratorAtPath:getDocumentsDirectory()];
|
||||
|
||||
NSString *path = nil;
|
||||
while ((path = [enumerator nextObject]))
|
||||
{
|
||||
// Add .love files plus folders that contain main.lua to our list.
|
||||
if ([path.pathExtension isEqualToString:@"love"])
|
||||
[paths addObject:path];
|
||||
else if ([path.lastPathComponent isEqualToString:@"main.lua"])
|
||||
[paths addObject:path.stringByDeletingLastPathComponent];
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
static bool deleteFileInDocuments(NSString *filename)
|
||||
{
|
||||
NSString *documents = getDocumentsDirectory();
|
||||
|
||||
NSString *file = [documents stringByAppendingPathComponent:filename];
|
||||
bool success = [[NSFileManager defaultManager] removeItemAtPath:file error:nil];
|
||||
|
||||
if (success)
|
||||
NSLog(@"Deleted file %@ in Documents folder.", filename);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static int dropFileEventFilter(void *userdata, SDL_Event *event)
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
if (event->type != SDL_DROPFILE)
|
||||
return 1;
|
||||
|
||||
NSString *fname = @(event->drop.file);
|
||||
NSFileManager *fmanager = [NSFileManager defaultManager];
|
||||
|
||||
if ([fmanager fileExistsAtPath:fname] && [fname.pathExtension isEqual:@"love"])
|
||||
{
|
||||
NSString *documents = getDocumentsDirectory();
|
||||
|
||||
documents = documents.stringByStandardizingPath.stringByResolvingSymlinksInPath;
|
||||
fname = fname.stringByStandardizingPath.stringByResolvingSymlinksInPath;
|
||||
|
||||
// Is the file inside the Documents directory?
|
||||
if ([fname hasPrefix:documents])
|
||||
{
|
||||
LOVETableViewController *vc = (__bridge LOVETableViewController *) userdata;
|
||||
|
||||
// Update the game list.
|
||||
NSArray *games = getLovesInDocuments();
|
||||
vc.gameList = [[NSMutableArray alloc] initWithArray:games copyItems:YES];
|
||||
[vc.tableView reloadData];
|
||||
|
||||
SDL_free(event->drop.file);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace ios
|
||||
{
|
||||
|
||||
/**
|
||||
* Displays a full-screen list of available LOVE games for the user to choose.
|
||||
* Returns the index of the selected game from the list. The list of games
|
||||
* includes the no-game screen, and the function will return an index outside
|
||||
* of the array's range if that is selected.
|
||||
**/
|
||||
static NSString *showGameList(NSArray *filenames)
|
||||
{
|
||||
// Game list view controller.
|
||||
LOVETableViewController *tablecontroller = [[LOVETableViewController alloc] initWithGameList:filenames];
|
||||
|
||||
// Navigation view controller (only used for the header bar right now.)
|
||||
// Contains the game list view/controller.
|
||||
UINavigationController *navcontroller = [[UINavigationController alloc] initWithRootViewController:tablecontroller];
|
||||
|
||||
UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
window.rootViewController = navcontroller;
|
||||
|
||||
SDL_EventFilter oldfilter = nullptr;
|
||||
void *oldudata = nullptr;
|
||||
SDL_GetEventFilter(&oldfilter, &oldudata);
|
||||
|
||||
// Manually retain the table VC and use it for the event filter userdata.
|
||||
// We need to set a custom event filter to update the table when .love files
|
||||
// are opened by the user.
|
||||
void *tableudata = (void *) CFBridgingRetain(tablecontroller);
|
||||
SDL_SetEventFilter(dropFileEventFilter, tableudata);
|
||||
|
||||
[window makeKeyAndVisible];
|
||||
|
||||
// Process events until a game in the list is selected.
|
||||
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
|
||||
while (tablecontroller.selectedGame == nil)
|
||||
{
|
||||
[runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]];
|
||||
[runloop runMode:UITrackingRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1.0/60.0]];
|
||||
}
|
||||
|
||||
// The window will get released and cleaned up once we go out of scope.
|
||||
window.hidden = YES;
|
||||
|
||||
SDL_SetEventFilter(oldfilter, oldudata);
|
||||
CFBridgingRelease(tableudata);
|
||||
|
||||
return tablecontroller.selectedGame;
|
||||
}
|
||||
|
||||
std::string getLoveInResources(bool &fused)
|
||||
{
|
||||
fused = false;
|
||||
std::string path;
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
// Start by looking in the main bundle (.app) folder for .love files.
|
||||
NSArray *bundlepaths = [[NSBundle mainBundle] pathsForResourcesOfType:@"love" inDirectory:nil];
|
||||
|
||||
if (bundlepaths.count > 0)
|
||||
{
|
||||
// The game should be fused if we have something here.
|
||||
fused = true;
|
||||
return [bundlepaths[0] UTF8String];
|
||||
}
|
||||
|
||||
// Otherwise look in the app's Documents directory. The game won't be
|
||||
// fused.
|
||||
NSArray *filepaths = getLovesInDocuments();
|
||||
|
||||
// Let the user select a game from the un-fused list.
|
||||
NSString *selectedfile = showGameList(filepaths);
|
||||
|
||||
// The string length might be 0 if the no-game screen was selected.
|
||||
if (selectedfile != nil && selectedfile.length > 0)
|
||||
{
|
||||
NSString *documents = getDocumentsDirectory();
|
||||
path = [documents stringByAppendingPathComponent:selectedfile].UTF8String;
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
std::string getAppdataDirectory()
|
||||
{
|
||||
NSSearchPathDirectory searchdir = NSApplicationSupportDirectory;
|
||||
std::string path;
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
NSArray *dirs = NSSearchPathForDirectoriesInDomains(searchdir, NSUserDomainMask, YES);
|
||||
|
||||
if (dirs.count > 0)
|
||||
path = [dirs[0] UTF8String];
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
std::string getHomeDirectory()
|
||||
{
|
||||
std::string path;
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
path = [NSHomeDirectory() UTF8String];
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
bool openURL(const std::string &url)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
UIApplication *app = [UIApplication sharedApplication];
|
||||
NSURL *nsurl = [NSURL URLWithString:@(url.c_str())];
|
||||
|
||||
if ([app canOpenURL:nsurl])
|
||||
success = [app openURL:nsurl];
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
std::string getExecutablePath()
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
return std::string([NSBundle mainBundle].executablePath.UTF8String);
|
||||
}
|
||||
}
|
||||
|
||||
void vibrate()
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
|
||||
}
|
||||
}
|
||||
|
||||
} // ios
|
||||
} // love
|
||||
|
||||
#endif // LOVE_IOS
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2015 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_OSX_H
|
||||
#define LOVE_OSX_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef LOVE_MACOSX
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace macosx
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the filepath of the first detected love file in the Resources folder
|
||||
* in the main bundle (love.app.)
|
||||
* Returns an empty string if no love file is found.
|
||||
**/
|
||||
std::string getLoveInResources();
|
||||
|
||||
/**
|
||||
* Checks for drop-file events. Returns the filepath if an event occurred, or
|
||||
* an empty string otherwise.
|
||||
**/
|
||||
std::string checkDropEvents();
|
||||
|
||||
/**
|
||||
* Returns the full path to the executable.
|
||||
**/
|
||||
std::string getExecutablePath();
|
||||
|
||||
/**
|
||||
* Bounce the dock icon, if the app isn't in the foreground.
|
||||
**/
|
||||
void requestAttention(bool continuous);
|
||||
|
||||
} // macosx
|
||||
} // love
|
||||
|
||||
#endif // LOVE_MACOSX
|
||||
|
||||
#endif // LOVE_OSX_H
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2015 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "macosx.h"
|
||||
|
||||
#ifdef LOVE_MACOSX
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace macosx
|
||||
{
|
||||
|
||||
std::string getLoveInResources()
|
||||
{
|
||||
std::string path;
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
// Check to see if there are any .love files in Resources.
|
||||
NSString *lovepath = [[NSBundle mainBundle] pathForResource:nil ofType:@"love"];
|
||||
|
||||
if (lovepath != nil)
|
||||
path = lovepath.UTF8String;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
std::string checkDropEvents()
|
||||
{
|
||||
std::string dropstr;
|
||||
SDL_Event event;
|
||||
|
||||
SDL_InitSubSystem(SDL_INIT_VIDEO);
|
||||
|
||||
SDL_PumpEvents();
|
||||
if (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_DROPFILE, SDL_DROPFILE) > 0)
|
||||
{
|
||||
if (event.type == SDL_DROPFILE)
|
||||
{
|
||||
dropstr = std::string(event.drop.file);
|
||||
SDL_free(event.drop.file);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
|
||||
return dropstr;
|
||||
}
|
||||
|
||||
std::string getExecutablePath()
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
return std::string([NSBundle mainBundle].executablePath.UTF8String);
|
||||
}
|
||||
}
|
||||
|
||||
void requestAttention(bool continuous)
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
if (continuous)
|
||||
[NSApp requestUserAttention:NSCriticalRequest];
|
||||
else
|
||||
[NSApp requestUserAttention:NSInformationalRequest];
|
||||
}
|
||||
}
|
||||
|
||||
} // osx
|
||||
} // love
|
||||
|
||||
#endif // LOVE_MACOSX
|
||||
+21
-30
@@ -36,11 +36,11 @@ extern "C" {
|
||||
#endif // LOVE_WINDOWS
|
||||
|
||||
#ifdef LOVE_MACOSX
|
||||
#include "common/OSX.h"
|
||||
#include "common/macosx.h"
|
||||
#endif // LOVE_MACOSX
|
||||
|
||||
#ifdef LOVE_IOS
|
||||
#include "common/iOS.h"
|
||||
#include "common/ios.h"
|
||||
#endif
|
||||
|
||||
#ifdef LOVE_ANDROID
|
||||
@@ -111,7 +111,7 @@ static void get_app_arguments(int argc, char **argv, int &new_argc, char **&new_
|
||||
|
||||
#ifdef LOVE_MACOSX
|
||||
// Check for a drop file string.
|
||||
std::string dropfilestr = love::osx::checkDropEvents();
|
||||
std::string dropfilestr = love::macosx::checkDropEvents();
|
||||
if (!dropfilestr.empty())
|
||||
{
|
||||
temp_argv.insert(temp_argv.begin() + 1, dropfilestr);
|
||||
@@ -123,7 +123,7 @@ static void get_app_arguments(int argc, char **argv, int &new_argc, char **&new_
|
||||
std::string loveResourcesPath;
|
||||
bool fused = true;
|
||||
#if defined(LOVE_MACOSX)
|
||||
loveResourcesPath = love::osx::getLoveInResources();
|
||||
loveResourcesPath = love::macosx::getLoveInResources();
|
||||
#elif defined(LOVE_IOS)
|
||||
loveResourcesPath = love::ios::getLoveInResources(fused);
|
||||
#endif
|
||||
@@ -168,39 +168,30 @@ static int l_print_sdl_log(lua_State *L)
|
||||
{
|
||||
int nargs = lua_gettop(L);
|
||||
|
||||
if (nargs == 0)
|
||||
return 0;
|
||||
lua_getglobal(L, "tostring");
|
||||
|
||||
std::string out_string = "";
|
||||
std::string outstring;
|
||||
|
||||
for (int i = 1; i <= nargs; i++)
|
||||
{
|
||||
int type = lua_type(L, i);
|
||||
char pointer_buf[16];
|
||||
switch (type)
|
||||
{
|
||||
case LUA_TNUMBER:
|
||||
case LUA_TSTRING:
|
||||
out_string += lua_tostring(L, i);
|
||||
break;
|
||||
case LUA_TNIL:
|
||||
out_string += "nil";
|
||||
break;
|
||||
case LUA_TBOOLEAN:
|
||||
out_string += lua_toboolean(L, i) ? "true" : "false";
|
||||
break;
|
||||
default:
|
||||
out_string += lua_typename(L, lua_type(L, i));
|
||||
sprintf(pointer_buf, ": 0x%lx", (long unsigned int) lua_topointer(L, i));
|
||||
out_string += pointer_buf;
|
||||
break;
|
||||
}
|
||||
// Call tostring(arg) and leave the result on the top of the stack.
|
||||
lua_pushvalue(L, -1);
|
||||
lua_pushvalue(L, i);
|
||||
lua_call(L, 1, 1);
|
||||
|
||||
if (i != nargs - 1)
|
||||
out_string += "\t";
|
||||
const char *s = lua_tostring(L, -1);
|
||||
if (s == nullptr)
|
||||
return luaL_error(L, "'tostring' must return a string to 'print'");
|
||||
|
||||
if (i > 1)
|
||||
outstring += "\t";
|
||||
|
||||
outstring += s;
|
||||
|
||||
lua_pop(L, 1); // Pop the result of tostring(arg).
|
||||
}
|
||||
|
||||
SDL_Log("[LOVE] %s", out_string.c_str());
|
||||
SDL_Log("[LOVE] %s", outstring.c_str());
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -97,9 +97,19 @@ int w_clear(lua_State *)
|
||||
|
||||
int w_quit(lua_State *L)
|
||||
{
|
||||
Message *m = new Message("quit");
|
||||
std::vector<StrongRef<Variant>> args;
|
||||
|
||||
Variant *v = Variant::fromLua(L, 1);
|
||||
if (v)
|
||||
{
|
||||
args.push_back(v);
|
||||
v->release();
|
||||
}
|
||||
|
||||
Message *m = new Message("quit", args);
|
||||
instance()->push(m);
|
||||
m->release();
|
||||
|
||||
luax_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if defined(LOVE_MACOSX)
|
||||
#include "common/OSX.h"
|
||||
#include "common/macosx.h"
|
||||
#elif defined(LOVE_IOS)
|
||||
#include "common/iOS.h"
|
||||
#include "common/ios.h"
|
||||
#elif defined(LOVE_WINDOWS)
|
||||
#include <windows.h>
|
||||
#include "common/utf8.h"
|
||||
@@ -74,7 +74,7 @@ bool Filesystem::isRealDirectory(const std::string &path) const
|
||||
std::string Filesystem::getExecutablePath() const
|
||||
{
|
||||
#if defined(LOVE_MACOSX)
|
||||
return love::osx::getExecutablePath();
|
||||
return love::macosx::getExecutablePath();
|
||||
#elif defined(LOVE_IOS)
|
||||
return love::ios::getExecutablePath();
|
||||
#elif defined(LOVE_WINDOWS)
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef LOVE_IOS
|
||||
# include "common/iOS.h"
|
||||
# include "common/ios.h"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -199,7 +199,7 @@ void BMFontRasterizer::parseConfig(const std::string &configtext)
|
||||
throw love::Exception("Image module not loaded!");
|
||||
|
||||
// Release these variables right away since StrongRef retains.
|
||||
StrongRef<filesystem::FileData> data = filesystem->read(filename.c_str());
|
||||
StrongRef<FileData> data = filesystem->read(filename.c_str());
|
||||
data->release();
|
||||
|
||||
images[pageindex].set(imagemodule->newImageData(data.get()));
|
||||
|
||||
@@ -300,6 +300,12 @@ void Canvas::unloadVolatile()
|
||||
|
||||
void Canvas::drawv(const Matrix4 &t, const Vertex *v)
|
||||
{
|
||||
// FIXME: This doesn't handle cases where the Canvas is used as a texture
|
||||
// in a SpriteBatch, Mesh, or ParticleSystem, or when the Canvas is used in
|
||||
// a shader as a non-default texture.
|
||||
if (Canvas::current == this)
|
||||
throw love::Exception("Cannot draw a Canvas to itself.");
|
||||
|
||||
OpenGL::TempDebugGroup debuggroup("Canvas draw");
|
||||
|
||||
OpenGL::TempTransform transform(gl);
|
||||
@@ -327,8 +333,7 @@ void Canvas::drawq(Quad *quad, float x, float y, float angle, float sx, float sy
|
||||
{
|
||||
Matrix4 t(x, y, angle, sx, sy, ox, oy, kx, ky);
|
||||
|
||||
const Vertex *v = quad->getVertices();
|
||||
drawv(t, v);
|
||||
drawv(t, quad->getVertices());
|
||||
}
|
||||
|
||||
void Canvas::setFilter(const Texture::Filter &f)
|
||||
|
||||
@@ -410,8 +410,8 @@ std::vector<Font::DrawCommand> Font::generateVertices(const std::string &text, s
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
vertices.push_back(glyph.vertices[j]);
|
||||
vertices.back().x += dx /*+ kerning*/;
|
||||
vertices.back().y += dy /*+ kerning.y*/ + lineheight;
|
||||
vertices.back().x += dx;
|
||||
vertices.back().y += dy + lineheight;
|
||||
}
|
||||
|
||||
// Check if glyph texture has changed since the last iteration.
|
||||
@@ -651,13 +651,12 @@ int Font::getWidth(const std::string &str)
|
||||
prevglyph = c;
|
||||
}
|
||||
}
|
||||
catch(utf8::exception &e)
|
||||
catch (utf8::exception &e)
|
||||
{
|
||||
throw love::Exception("UTF-8 decoding error: %s", e.what());
|
||||
}
|
||||
|
||||
if (width > max_width)
|
||||
max_width = width;
|
||||
max_width = std::max(max_width, width);
|
||||
}
|
||||
|
||||
return max_width;
|
||||
@@ -671,41 +670,41 @@ int Font::getWidth(char character)
|
||||
|
||||
void Font::getWrap(const std::string &text, float wrap, std::vector<std::string> &lines, std::vector<int> *linewidths, std::vector<bool> *wrappedlines)
|
||||
{
|
||||
using namespace std;
|
||||
const float width_space = (float) getWidth(' ');
|
||||
|
||||
//split text at newlines
|
||||
istringstream iss(text);
|
||||
string line;
|
||||
ostringstream string_builder;
|
||||
while (getline(iss, line, '\n'))
|
||||
{
|
||||
// split line into words
|
||||
vector<string> words;
|
||||
istringstream word_iss(line);
|
||||
copy(istream_iterator<string>(word_iss), istream_iterator<string>(),
|
||||
back_inserter< vector<string> >(words));
|
||||
std::istringstream iss(text);
|
||||
std::string line;
|
||||
std::ostringstream string_builder;
|
||||
|
||||
// Split text at newlines.
|
||||
while (std::getline(iss, line, '\n'))
|
||||
{
|
||||
std::vector<std::string> words;
|
||||
std::istringstream word_iss(line);
|
||||
|
||||
// split line into words
|
||||
std::copy(std::istream_iterator<std::string>(word_iss), std::istream_iterator<std::string>(), std::back_inserter(words));
|
||||
|
||||
// put words back together until a wrap occurs
|
||||
float width = 0.0f;
|
||||
float oldwidth = 0.0f;
|
||||
string_builder.str("");
|
||||
vector<string>::const_iterator word_iter, wend = words.end();
|
||||
for (word_iter = words.begin(); word_iter != wend; ++word_iter)
|
||||
{
|
||||
const string &word = *word_iter;
|
||||
width += getWidth(word);
|
||||
|
||||
// on wordwrap, push line to line buffer and clear string builder
|
||||
// Put words back together until a wrap occurs.
|
||||
for (const std::string &word : words)
|
||||
{
|
||||
float wordwidth = (float) getWidth(word);
|
||||
width += wordwidth;
|
||||
|
||||
// On wordwrap, push line to line buffer and clear string builder.
|
||||
if (width > wrap && oldwidth > 0)
|
||||
{
|
||||
int realw = (int) width;
|
||||
|
||||
// remove trailing space
|
||||
string tmp = string_builder.str();
|
||||
// Remove trailing space.
|
||||
std::string tmp = string_builder.str();
|
||||
lines.push_back(tmp.substr(0,tmp.size()-1));
|
||||
string_builder.str("");
|
||||
width = static_cast<float>(getWidth(word));
|
||||
width = wordwidth;
|
||||
realw -= (int) width;
|
||||
|
||||
if (linewidths)
|
||||
@@ -715,15 +714,18 @@ void Font::getWrap(const std::string &text, float wrap, std::vector<std::string>
|
||||
if (wrappedlines)
|
||||
wrappedlines->push_back(true);
|
||||
}
|
||||
|
||||
string_builder << word << " ";
|
||||
|
||||
width += width_space;
|
||||
oldwidth = width;
|
||||
}
|
||||
// push last line
|
||||
|
||||
// Push last line.
|
||||
if (linewidths)
|
||||
linewidths->push_back(width);
|
||||
|
||||
string tmp = string_builder.str();
|
||||
std::string tmp = string_builder.str();
|
||||
lines.push_back(tmp.substr(0,tmp.size()-1));
|
||||
|
||||
// Indicate that this line was not automatically wrapped.
|
||||
|
||||
@@ -1109,17 +1109,24 @@ void Graphics::printf(const std::string &str, float x, float y, float wrap, Font
|
||||
* Primitives
|
||||
**/
|
||||
|
||||
void Graphics::point(float x, float y)
|
||||
void Graphics::points(const float *coords, const uint8 *colors, size_t numpoints)
|
||||
{
|
||||
OpenGL::TempDebugGroup debuggroup("Graphics point draw");
|
||||
|
||||
GLfloat coord[] = {x, y};
|
||||
OpenGL::TempDebugGroup debuggroup("Graphics points draw");
|
||||
|
||||
gl.prepareDraw();
|
||||
gl.bindTexture(gl.getDefaultTexture());
|
||||
gl.useVertexAttribArrays(ATTRIBFLAG_POS);
|
||||
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, coord);
|
||||
gl.drawArrays(GL_POINTS, 0, 1);
|
||||
|
||||
uint32 attribflags = ATTRIBFLAG_POS;
|
||||
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, coords);
|
||||
|
||||
if (colors)
|
||||
{
|
||||
attribflags |= ATTRIBFLAG_COLOR;
|
||||
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, colors);
|
||||
}
|
||||
|
||||
gl.useVertexAttribArrays(attribflags);
|
||||
gl.drawArrays(GL_POINTS, 0, numpoints);
|
||||
}
|
||||
|
||||
void Graphics::polyline(const float *coords, size_t count)
|
||||
|
||||
@@ -351,7 +351,7 @@ public:
|
||||
* @param x Point along x-axis.
|
||||
* @param y Point along y-axis.
|
||||
**/
|
||||
void point(float x, float y);
|
||||
void points(const float *coords, const uint8 *colors, size_t numpoints);
|
||||
|
||||
/**
|
||||
* Draws a series of lines connecting the given vertices.
|
||||
|
||||
@@ -776,14 +776,6 @@ static Mesh *newCustomMesh(lua_State *L)
|
||||
lua_rawgeti(L, 2, vertindex + 1);
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
|
||||
if ((int) luax_objlen(L, -1) < vertexcomponents)
|
||||
{
|
||||
t->release();
|
||||
const char *err = "Invalid number of components in vertex #%d (expected %d components, got %d)";
|
||||
luaL_error(L, err, vertindex+1, vertexcomponents, luax_objlen(L, -1));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
for (size_t i = 0; i < vertexformat.size(); i++)
|
||||
{
|
||||
@@ -1515,11 +1507,86 @@ int w_printf(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_point(lua_State *L)
|
||||
int w_points(lua_State *L)
|
||||
{
|
||||
float x = (float)luaL_checknumber(L, 1);
|
||||
float y = (float)luaL_checknumber(L, 2);
|
||||
instance()->point(x, y);
|
||||
// love.graphics.points has 3 variants:
|
||||
// - points(x1, y1, x2, y2, ...)
|
||||
// - points({x1, y1, x2, y2, ...})
|
||||
// - points({{x1, y1 [, r, g, b, a]}, {x2, y2 [, r, g, b, a]}, ...})
|
||||
|
||||
int args = lua_gettop(L);
|
||||
bool is_table = false;
|
||||
bool is_table_of_tables = false;
|
||||
if (args == 1 && lua_istable(L, 1))
|
||||
{
|
||||
is_table = true;
|
||||
args = (int) luax_objlen(L, 1);
|
||||
|
||||
lua_rawgeti(L, 1, 1);
|
||||
is_table_of_tables = lua_istable(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
if (args % 2 != 0 && !is_table_of_tables)
|
||||
return luaL_error(L, "Number of vertex components must be a multiple of two");
|
||||
|
||||
int numpoints = args / 2;
|
||||
if (is_table_of_tables)
|
||||
numpoints = args;
|
||||
|
||||
float *coords = nullptr;
|
||||
uint8 *colors = nullptr;
|
||||
|
||||
coords = new float[numpoints * 2];
|
||||
|
||||
if (is_table_of_tables)
|
||||
colors = new uint8[numpoints * 4];
|
||||
|
||||
if (is_table)
|
||||
{
|
||||
if (is_table_of_tables)
|
||||
{
|
||||
// points({{x1, y1 [, r, g, b, a]}, {x2, y2 [, r, g, b, a]}, ...})
|
||||
for (int i = 0; i < args; i++)
|
||||
{
|
||||
lua_rawgeti(L, 1, i + 1);
|
||||
for (int j = 1; j <= 6; j++)
|
||||
lua_rawgeti(L, -j, j);
|
||||
|
||||
coords[i * 2 + 0] = luax_tofloat(L, -6);
|
||||
coords[i * 2 + 1] = luax_tofloat(L, -5);
|
||||
|
||||
colors[i * 4 + 0] = (uint8) luaL_optnumber(L, -4, 255);
|
||||
colors[i * 4 + 1] = (uint8) luaL_optnumber(L, -3, 255);
|
||||
colors[i * 4 + 2] = (uint8) luaL_optnumber(L, -2, 255);
|
||||
colors[i * 4 + 3] = (uint8) luaL_optnumber(L, -1, 255);
|
||||
|
||||
lua_pop(L, 7);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// points({x1, y1, x2, y2, ...})
|
||||
for (int i = 0; i < args; i++)
|
||||
{
|
||||
lua_rawgeti(L, 1, i + 1);
|
||||
coords[i] = luax_tofloat(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < args; i++)
|
||||
coords[i] = luax_tofloat(L, i + 1);
|
||||
}
|
||||
|
||||
instance()->points(coords, colors, numpoints);
|
||||
|
||||
delete[] coords;
|
||||
if (colors)
|
||||
delete[] colors;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1838,7 +1905,7 @@ static const luaL_Reg functions[] =
|
||||
{ "setStencilTest", w_setStencilTest },
|
||||
{ "getStencilTest", w_getStencilTest },
|
||||
|
||||
{ "point", w_point },
|
||||
{ "points", w_points },
|
||||
{ "line", w_line },
|
||||
{ "rectangle", w_rectangle },
|
||||
{ "circle", w_circle },
|
||||
|
||||
@@ -106,7 +106,7 @@ int w_getStats(lua_State *L);
|
||||
int w_draw(lua_State *L);
|
||||
int w_print(lua_State *L);
|
||||
int w_printf(lua_State *L);
|
||||
int w_point(lua_State *L);
|
||||
int w_points(lua_State *L);
|
||||
int w_line(lua_State *L);
|
||||
int w_rectangle(lua_State *L);
|
||||
int w_circle(lua_State *L);
|
||||
|
||||
@@ -210,7 +210,14 @@ int VorbisDecoder::decode()
|
||||
|
||||
bool VorbisDecoder::seek(float s)
|
||||
{
|
||||
int result = ov_time_seek(&handle, s);
|
||||
int result = 0;
|
||||
|
||||
// Avoid ov_time_seek (which calls ov_pcm_seek) when seeking to 0, to avoid
|
||||
// a bug in libvorbis <= 1.3.4 when seeking to PCM 0 in multiplexed streams.
|
||||
if (s <= 0.000001)
|
||||
result = ov_raw_seek(&handle, 0);
|
||||
else
|
||||
result = ov_time_seek(&handle, s);
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
@@ -223,7 +230,9 @@ bool VorbisDecoder::seek(float s)
|
||||
|
||||
bool VorbisDecoder::rewind()
|
||||
{
|
||||
int result = ov_pcm_seek(&handle, 0);
|
||||
// Avoid ov_time_seek to avoid a bug in libvorbis <= 1.3.4 when seeking to
|
||||
// PCM 0 in multiplexed streams.
|
||||
int result = ov_raw_seek(&handle, 0);
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#if defined(LOVE_MACOSX)
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#elif defined(LOVE_IOS)
|
||||
#include "common/iOS.h"
|
||||
#include "common/ios.h"
|
||||
#elif defined(LOVE_ANDROID)
|
||||
#include "common/android.h"
|
||||
#elif defined(LOVE_LINUX)
|
||||
@@ -68,9 +68,9 @@ std::string System::getOS() const
|
||||
return "iOS";
|
||||
#elif defined(LOVE_WINDOWS)
|
||||
return "Windows";
|
||||
#elif LOVE_ANDROID
|
||||
#elif defined(LOVE_ANDROID)
|
||||
return "Android";
|
||||
#elif LOVE_LINUX
|
||||
#elif defined(LOVE_LINUX)
|
||||
return "Linux";
|
||||
#else
|
||||
return "Unknown";
|
||||
@@ -146,6 +146,8 @@ void System::vibrate(double seconds) const
|
||||
{
|
||||
#ifdef LOVE_ANDROID
|
||||
love::android::vibrate(seconds);
|
||||
#elif defined(LOVE_IOS)
|
||||
love::ios::vibrate();
|
||||
#else
|
||||
LOVE_UNUSED(seconds);
|
||||
#endif
|
||||
|
||||
@@ -88,7 +88,7 @@ int w_openURL(lua_State *L)
|
||||
|
||||
int w_vibrate(lua_State *L)
|
||||
{
|
||||
double seconds = luaL_checknumber(L, 1);
|
||||
double seconds = luaL_optnumber(L, 1, 0.5);
|
||||
instance()->vibrate(seconds);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
#if defined(LOVE_WINDOWS)
|
||||
#include <windows.h>
|
||||
#elif defined(LOVE_MACOSX)
|
||||
#include "common/OSX.h"
|
||||
#include "common/macosx.h"
|
||||
#endif
|
||||
|
||||
#ifndef APIENTRY
|
||||
@@ -132,12 +132,14 @@ void Window::setGLContextAttributes(const ContextAttribs &attribs)
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, contextflags);
|
||||
}
|
||||
|
||||
bool Window::checkGLVersion(const ContextAttribs &attribs)
|
||||
bool Window::checkGLVersion(const ContextAttribs &attribs, std::string &outversion)
|
||||
{
|
||||
typedef unsigned char GLubyte;
|
||||
typedef unsigned int GLenum;
|
||||
typedef const GLubyte *(APIENTRY *glGetStringPtr)(GLenum name);
|
||||
const GLenum GL_VERSION_ENUM = 0x1F02;
|
||||
const GLenum GL_VENDOR_ENUM = 0x1F00;
|
||||
const GLenum GL_RENDERER_ENUM = 0x1F01;
|
||||
const GLenum GL_VERSION_ENUM = 0x1F02;
|
||||
|
||||
// We don't have OpenGL headers or an automatic OpenGL function loader in
|
||||
// this module, so we have to get the glGetString function pointer ourselves.
|
||||
@@ -149,6 +151,16 @@ bool Window::checkGLVersion(const ContextAttribs &attribs)
|
||||
if (!glversion)
|
||||
return false;
|
||||
|
||||
outversion = glversion;
|
||||
|
||||
const char *glrenderer = (const char *) glGetStringFunc(GL_RENDERER_ENUM);
|
||||
if (glrenderer)
|
||||
outversion += " - " + std::string(glrenderer);
|
||||
|
||||
const char *glvendor = (const char *) glGetStringFunc(GL_VENDOR_ENUM);
|
||||
if (glvendor)
|
||||
outversion += " (" + std::string(glvendor) + ")";
|
||||
|
||||
int glmajor = 0;
|
||||
int glminor = 0;
|
||||
|
||||
@@ -229,6 +241,7 @@ bool Window::createWindowAndContext(int x, int y, int w, int h, Uint32 windowfla
|
||||
}
|
||||
|
||||
std::string windowerror;
|
||||
std::string glversion;
|
||||
|
||||
// Try each context profile in order.
|
||||
for (ContextAttribs attribs : attribslist)
|
||||
@@ -320,7 +333,7 @@ bool Window::createWindowAndContext(int x, int y, int w, int h, Uint32 windowfla
|
||||
}
|
||||
|
||||
// Make sure the context's version is at least what we requested.
|
||||
if (context && !checkGLVersion(attribs))
|
||||
if (context && !checkGLVersion(attribs, glversion))
|
||||
{
|
||||
SDL_GL_DeleteContext(context);
|
||||
context = nullptr;
|
||||
@@ -354,6 +367,9 @@ bool Window::createWindowAndContext(int x, int y, int w, int h, Uint32 windowfla
|
||||
std::string title = "Unable to initialize OpenGL";
|
||||
std::string message = "This program requires a graphics card and video drivers which support OpenGL 2.1 or OpenGL ES 2.";
|
||||
|
||||
if (!glversion.empty())
|
||||
message += " \n\nDetected OpenGL version: " + glversion;
|
||||
|
||||
std::cerr << title << std::endl << message << std::endl;
|
||||
|
||||
// Display a message box with the error, but only once.
|
||||
@@ -1031,7 +1047,7 @@ void Window::requestAttention(bool continuous)
|
||||
|
||||
#elif defined(LOVE_MACOSX)
|
||||
|
||||
love::osx::requestAttention(continuous);
|
||||
love::macosx::requestAttention(continuous);
|
||||
|
||||
#else
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ private:
|
||||
|
||||
void setGLFramebufferAttributes(int msaa, bool sRGB);
|
||||
void setGLContextAttributes(const ContextAttribs &attribs);
|
||||
bool checkGLVersion(const ContextAttribs &attribs);
|
||||
bool checkGLVersion(const ContextAttribs &attribs, std::string &outversion);
|
||||
bool createWindowAndContext(int x, int y, int w, int h, Uint32 windowflags, int msaa);
|
||||
|
||||
// Update the saved window settings based on the window's actual state.
|
||||
|
||||
@@ -523,7 +523,7 @@ function love.run()
|
||||
for name, a,b,c,d,e,f in love.event.poll() do
|
||||
if name == "quit" then
|
||||
if not love.quit or not love.quit() then
|
||||
return
|
||||
return a
|
||||
end
|
||||
end
|
||||
love.handlers[name](a,b,c,d,e,f)
|
||||
@@ -581,6 +581,7 @@ function love.errhand(msg)
|
||||
if love.mouse then
|
||||
love.mouse.setVisible(true)
|
||||
love.mouse.setGrabbed(false)
|
||||
love.mouse.setRelativeMode(false)
|
||||
end
|
||||
if love.joystick then
|
||||
-- Stop all joystick vibrations.
|
||||
|
||||
@@ -821,11 +821,11 @@ const unsigned char boot_lua[] =
|
||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x27, 0x25, 0x73, 0x27, 0x20, 0x6f, 0x66, 0x20, 0x4c, 0x4f, 0x56,
|
||||
0x45, 0x2e, 0x5c, 0x6e, 0x22, 0x2e, 0x2e, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x09, 0x22, 0x49, 0x74, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65,
|
||||
0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65,
|
||||
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x20,
|
||||
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x25, 0x73, 0x29, 0x2e, 0x22, 0x29, 0x3a, 0x66, 0x6f,
|
||||
0x72, 0x6d, 0x61, 0x74, 0x28, 0x63, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x6c, 0x6f,
|
||||
0x76, 0x65, 0x2e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0x0a,
|
||||
0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x20, 0x28, 0x25, 0x73, 0x29, 0x2e, 0x22, 0x29, 0x3a, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x28, 0x63, 0x2e,
|
||||
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x76, 0x65, 0x72,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x29, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x6d, 0x73, 0x67, 0x29, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20,
|
||||
0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||
@@ -962,7 +962,7 @@ const unsigned char boot_lua[] =
|
||||
0x09, 0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x71,
|
||||
0x75, 0x69, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x71, 0x75,
|
||||
0x69, 0x74, 0x28, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x5b,
|
||||
@@ -1058,6 +1058,8 @@ const unsigned char boot_lua[] =
|
||||
0x73, 0x69, 0x62, 0x6c, 0x65, 0x28, 0x74, 0x72, 0x75, 0x65, 0x29, 0x0a,
|
||||
0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x2e, 0x73, 0x65, 0x74, 0x47, 0x72,
|
||||
0x61, 0x62, 0x62, 0x65, 0x64, 0x28, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x0a,
|
||||
0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x2e, 0x73, 0x65, 0x74, 0x52, 0x65,
|
||||
0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x28, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x0a,
|
||||
0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x20,
|
||||
0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||
|
||||
Reference in New Issue
Block a user