Update LÖVE to changeset 7cb21c8bdd64 (pre 0.10.0)

This commit is contained in:
fysx
2015-12-01 23:07:34 +01:00
parent 7e877716d6
commit 686e1d5f3e
196 changed files with 820 additions and 64699 deletions
+1 -1
View File
@@ -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
+6 -6
View File
@@ -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;
}
+11 -11
View File
@@ -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
-9
View File
@@ -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>
+71
View File
@@ -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
+350
View File
@@ -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
+63
View File
@@ -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
+95
View File
@@ -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
View File
@@ -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
+11 -1
View File
@@ -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)
+31 -29
View File
@@ -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)
{
+5 -3
View File
@@ -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
+1 -1
View File
@@ -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;
}
+21 -5
View File
@@ -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
+1 -1
View File
@@ -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.
+2 -1
View File
@@ -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.
+8 -6
View File
@@ -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,