mirror of
https://github.com/love2d/love.git
synced 2026-08-21 05:00:08 +02:00
Merged default into minor
--HG-- branch : minor
This commit is contained in:
@@ -34,13 +34,11 @@ std::string getLoveInResources()
|
|||||||
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
// check to see if there are any .love files in Resources - props to stevejohnson/diordna
|
// Check to see if there are any .love files in Resources.
|
||||||
NSArray *lovePaths = [[NSBundle mainBundle] pathsForResourcesOfType:@"love" inDirectory:nil];
|
NSString *lovepath = [[NSBundle mainBundle] pathForResource:nil ofType:@"love"];
|
||||||
if ([lovePaths count] > 0)
|
|
||||||
{
|
if (lovepath != nil)
|
||||||
NSString *firstLovePath = [lovePaths objectAtIndex:0];
|
path = [lovepath UTF8String];
|
||||||
path = std::string([firstLovePath UTF8String]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
// STD
|
// STD
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <iostream>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
// LOVE
|
// LOVE
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
// STD
|
// STD
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <iostream>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
// LOVE
|
// LOVE
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ private:
|
|||||||
ALuint source;
|
ALuint source;
|
||||||
bool valid;
|
bool valid;
|
||||||
|
|
||||||
static const unsigned int MAX_BUFFERS = 32;
|
static const unsigned int MAX_BUFFERS = 8;
|
||||||
ALuint streamBuffers[MAX_BUFFERS];
|
ALuint streamBuffers[MAX_BUFFERS];
|
||||||
|
|
||||||
Object::StrongRef<StaticDataBuffer> staticBuffer;
|
Object::StrongRef<StaticDataBuffer> staticBuffer;
|
||||||
|
|||||||
@@ -26,6 +26,9 @@
|
|||||||
|
|
||||||
#include "common/runtime.h"
|
#include "common/runtime.h"
|
||||||
|
|
||||||
|
// C++
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
{
|
{
|
||||||
namespace audio
|
namespace audio
|
||||||
|
|||||||
@@ -42,17 +42,12 @@ namespace sdl
|
|||||||
// we want them in pixel coordinates (may be different with high-DPI enabled.)
|
// we want them in pixel coordinates (may be different with high-DPI enabled.)
|
||||||
static void windowToPixelCoords(int *x, int *y)
|
static void windowToPixelCoords(int *x, int *y)
|
||||||
{
|
{
|
||||||
double scale = 1.0;
|
|
||||||
|
|
||||||
window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
|
window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
|
||||||
if (window != nullptr)
|
|
||||||
scale = window->getPixelScale();
|
|
||||||
|
|
||||||
if (x != nullptr)
|
if (window && x)
|
||||||
*x = int(double(*x) * scale);
|
*x = (int) window->toPixels(*x);
|
||||||
|
if (window && y)
|
||||||
if (y != nullptr)
|
*y = (int) window->toPixels(*y);
|
||||||
*y = int(double(*y) * scale);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -74,15 +69,11 @@ Event::~Event()
|
|||||||
|
|
||||||
void Event::pump()
|
void Event::pump()
|
||||||
{
|
{
|
||||||
SDL_PumpEvents();
|
SDL_Event e;
|
||||||
|
|
||||||
static SDL_Event e;
|
|
||||||
|
|
||||||
Message *msg;
|
|
||||||
|
|
||||||
while (SDL_PollEvent(&e))
|
while (SDL_PollEvent(&e))
|
||||||
{
|
{
|
||||||
msg = convert(e);
|
Message *msg = convert(e);
|
||||||
if (msg)
|
if (msg)
|
||||||
{
|
{
|
||||||
push(msg);
|
push(msg);
|
||||||
@@ -93,16 +84,17 @@ void Event::pump()
|
|||||||
|
|
||||||
Message *Event::wait()
|
Message *Event::wait()
|
||||||
{
|
{
|
||||||
static SDL_Event e;
|
SDL_Event e;
|
||||||
bool ok = (SDL_WaitEvent(&e) == 1);
|
|
||||||
if (!ok)
|
if (SDL_WaitEvent(&e) != 1)
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
return convert(e);
|
return convert(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Event::clear()
|
void Event::clear()
|
||||||
{
|
{
|
||||||
static SDL_Event e;
|
SDL_Event e;
|
||||||
|
|
||||||
while (SDL_PollEvent(&e))
|
while (SDL_PollEvent(&e))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
#include "common/EnumMap.h"
|
#include "common/EnumMap.h"
|
||||||
|
|
||||||
// SDL
|
// SDL
|
||||||
#include <SDL.h>
|
#include <SDL_events.h>
|
||||||
|
|
||||||
// STL
|
// STL
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
// STD
|
// STD
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
// C
|
// C
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
{
|
{
|
||||||
@@ -223,7 +224,7 @@ bool Graphics::setMode(int width, int height, bool &sRGB)
|
|||||||
message += "\nThe program may crash or have graphical issues.";
|
message += "\nThe program may crash or have graphical issues.";
|
||||||
|
|
||||||
::printf("%s\n%s\n", title.c_str(), message.c_str());
|
::printf("%s\n%s\n", title.c_str(), message.c_str());
|
||||||
currentWindow->showMessageBox(type, title, message, true);
|
currentWindow->showMessageBox(title, message, type, true);
|
||||||
|
|
||||||
// We should only show the message once, instead of after every setMode.
|
// We should only show the message once, instead of after every setMode.
|
||||||
displayedMinReqWarning = true;
|
displayedMinReqWarning = true;
|
||||||
@@ -283,7 +284,7 @@ bool Graphics::setMode(int width, int height, bool &sRGB)
|
|||||||
|
|
||||||
// Reload all volatile objects.
|
// Reload all volatile objects.
|
||||||
if (!Volatile::loadAll())
|
if (!Volatile::loadAll())
|
||||||
std::cerr << "Could not reload all volatile objects." << std::endl;
|
::printf("Could not reload all volatile objects.\n");
|
||||||
|
|
||||||
// Restore the graphics state.
|
// Restore the graphics state.
|
||||||
restoreState(states.back());
|
restoreState(states.back());
|
||||||
@@ -650,9 +651,9 @@ Canvas *Graphics::newCanvas(int width, int height, Canvas::Format format, int ms
|
|||||||
return nullptr; // never reached
|
return nullptr; // never reached
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader *Graphics::newShader(const Shader::ShaderSources &sources)
|
Shader *Graphics::newShader(const Shader::ShaderSource &source)
|
||||||
{
|
{
|
||||||
return new Shader(sources);
|
return new Shader(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh *Graphics::newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode)
|
Mesh *Graphics::newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode)
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
#define LOVE_GRAPHICS_OPENGL_GRAPHICS_H
|
#define LOVE_GRAPHICS_OPENGL_GRAPHICS_H
|
||||||
|
|
||||||
// STD
|
// STD
|
||||||
#include <iostream>
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -154,7 +153,7 @@ public:
|
|||||||
|
|
||||||
Canvas *newCanvas(int width, int height, Canvas::Format format = Canvas::FORMAT_NORMAL, int msaa = 0);
|
Canvas *newCanvas(int width, int height, Canvas::Format format = Canvas::FORMAT_NORMAL, int msaa = 0);
|
||||||
|
|
||||||
Shader *newShader(const Shader::ShaderSources &sources);
|
Shader *newShader(const Shader::ShaderSource &source);
|
||||||
|
|
||||||
Mesh *newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN);
|
Mesh *newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN);
|
||||||
Mesh *newMesh(int vertexcount, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN);
|
Mesh *newMesh(int vertexcount, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN);
|
||||||
|
|||||||
@@ -64,20 +64,20 @@ namespace
|
|||||||
Shader *Shader::current = nullptr;
|
Shader *Shader::current = nullptr;
|
||||||
Shader *Shader::defaultShader = nullptr;
|
Shader *Shader::defaultShader = nullptr;
|
||||||
|
|
||||||
Shader::ShaderSources Shader::defaultCode[1]; // TODO: RENDERER_MAX_ENUM
|
Shader::ShaderSource Shader::defaultCode[1]; // TODO: RENDERER_MAX_ENUM
|
||||||
|
|
||||||
GLint Shader::maxTexUnits = 0;
|
GLint Shader::maxTexUnits = 0;
|
||||||
std::vector<int> Shader::textureCounters;
|
std::vector<int> Shader::textureCounters;
|
||||||
|
|
||||||
Shader::Shader(const ShaderSources &sources)
|
Shader::Shader(const ShaderSource &source)
|
||||||
: shaderSources(sources)
|
: shaderSource(source)
|
||||||
, program(0)
|
, program(0)
|
||||||
, builtinUniforms()
|
, builtinUniforms()
|
||||||
, vertexAttributes()
|
, builtinAttributes()
|
||||||
, lastCanvas((Canvas *) -1)
|
, lastCanvas((Canvas *) -1)
|
||||||
, lastViewport()
|
, lastViewport()
|
||||||
{
|
{
|
||||||
if (shaderSources.empty())
|
if (source.vertex.empty() && source.pixel.empty())
|
||||||
throw love::Exception("Cannot create shader: no source code!");
|
throw love::Exception("Cannot create shader: no source code!");
|
||||||
|
|
||||||
if (maxTexUnits <= 0)
|
if (maxTexUnits <= 0)
|
||||||
@@ -108,21 +108,21 @@ Shader::~Shader()
|
|||||||
unloadVolatile();
|
unloadVolatile();
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint Shader::compileCode(ShaderType type, const std::string &code)
|
GLuint Shader::compileCode(ShaderStage stage, const std::string &code)
|
||||||
{
|
{
|
||||||
GLenum glshadertype;
|
GLenum glstage;
|
||||||
const char *typestr;
|
const char *typestr;
|
||||||
|
|
||||||
if (!typeNames.find(type, typestr))
|
if (!stageNames.find(stage, typestr))
|
||||||
typestr = "";
|
typestr = "";
|
||||||
|
|
||||||
switch (type)
|
switch (stage)
|
||||||
{
|
{
|
||||||
case TYPE_VERTEX:
|
case STAGE_VERTEX:
|
||||||
glshadertype = GL_VERTEX_SHADER;
|
glstage = GL_VERTEX_SHADER;
|
||||||
break;
|
break;
|
||||||
case TYPE_PIXEL:
|
case STAGE_PIXEL:
|
||||||
glshadertype = GL_FRAGMENT_SHADER;
|
glstage = GL_FRAGMENT_SHADER;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw love::Exception("Cannot create shader object: unknown shader type.");
|
throw love::Exception("Cannot create shader object: unknown shader type.");
|
||||||
@@ -132,128 +132,75 @@ GLuint Shader::compileCode(ShaderType type, const std::string &code)
|
|||||||
// clear existing errors
|
// clear existing errors
|
||||||
while (glGetError() != GL_NO_ERROR);
|
while (glGetError() != GL_NO_ERROR);
|
||||||
|
|
||||||
GLuint shaderid = glCreateShader(glshadertype);
|
GLuint shaderid = glCreateShader(glstage);
|
||||||
|
|
||||||
if (shaderid == 0) // oh no!
|
if (shaderid == 0)
|
||||||
{
|
{
|
||||||
GLenum err = glGetError();
|
if (glGetError() == GL_INVALID_ENUM)
|
||||||
|
|
||||||
if (err == GL_INVALID_ENUM)
|
|
||||||
throw love::Exception("Cannot create %s shader object: %s shaders not supported.", typestr, typestr);
|
throw love::Exception("Cannot create %s shader object: %s shaders not supported.", typestr, typestr);
|
||||||
else
|
else
|
||||||
throw love::Exception("Cannot create %s shader object.", typestr);
|
throw love::Exception("Cannot create %s shader object.", typestr);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *src = code.c_str();
|
const char *src = code.c_str();
|
||||||
size_t srclen = code.length();
|
GLint srclen = (GLint) code.length();
|
||||||
glShaderSource(shaderid, 1, (const GLchar **)&src, (GLint *)&srclen);
|
glShaderSource(shaderid, 1, (const GLchar **)&src, &srclen);
|
||||||
|
|
||||||
glCompileShader(shaderid);
|
glCompileShader(shaderid);
|
||||||
|
|
||||||
// Get any warnings the shader compiler may have produced.
|
|
||||||
GLint infologlen;
|
GLint infologlen;
|
||||||
glGetShaderiv(shaderid, GL_INFO_LOG_LENGTH, &infologlen);
|
glGetShaderiv(shaderid, GL_INFO_LOG_LENGTH, &infologlen);
|
||||||
|
|
||||||
GLchar *infolog = new GLchar[infologlen + 1];
|
// Get any warnings the shader compiler may have produced.
|
||||||
glGetShaderInfoLog(shaderid, infologlen, nullptr, infolog);
|
|
||||||
|
|
||||||
// Save any warnings for later querying.
|
|
||||||
if (infologlen > 0)
|
if (infologlen > 0)
|
||||||
shaderWarnings[type] = infolog;
|
{
|
||||||
|
GLchar *infolog = new GLchar[infologlen];
|
||||||
|
glGetShaderInfoLog(shaderid, infologlen, nullptr, infolog);
|
||||||
|
|
||||||
delete[] infolog;
|
// Save any warnings for later querying.
|
||||||
|
shaderWarnings[stage] = infolog;
|
||||||
|
|
||||||
|
delete[] infolog;
|
||||||
|
}
|
||||||
|
|
||||||
GLint status;
|
GLint status;
|
||||||
glGetShaderiv(shaderid, GL_COMPILE_STATUS, &status);
|
glGetShaderiv(shaderid, GL_COMPILE_STATUS, &status);
|
||||||
|
|
||||||
if (status == GL_FALSE)
|
if (status == GL_FALSE)
|
||||||
{
|
{
|
||||||
|
glDeleteShader(shaderid);
|
||||||
throw love::Exception("Cannot compile %s shader code:\n%s",
|
throw love::Exception("Cannot compile %s shader code:\n%s",
|
||||||
typestr, shaderWarnings[type].c_str());
|
typestr, shaderWarnings[stage].c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
return shaderid;
|
return shaderid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::createProgram(const std::vector<GLuint> &shaderids)
|
|
||||||
{
|
|
||||||
program = glCreateProgram();
|
|
||||||
if (program == 0)
|
|
||||||
throw love::Exception("Cannot create shader program object.");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for (GLuint id : shaderids)
|
|
||||||
glAttachShader(program, id);
|
|
||||||
}
|
|
||||||
catch (love::Exception &)
|
|
||||||
{
|
|
||||||
glDeleteProgram(program);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind love's vertex attribute indices to names in the shader.
|
|
||||||
for (int i = 0; i < int(ATTRIB_MAX_ENUM); i++)
|
|
||||||
{
|
|
||||||
VertexAttribID attrib = (VertexAttribID) i;
|
|
||||||
|
|
||||||
// FIXME: We skip this both because pseudo-instancing is temporarily
|
|
||||||
// disabled (see graphics.lua), and because binding a non-existant
|
|
||||||
// attribute name to a location can cause a shader linker warning.
|
|
||||||
if (attrib == ATTRIB_PSEUDO_INSTANCE_ID)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const char *name = nullptr;
|
|
||||||
if (attribNames.find(attrib, name))
|
|
||||||
glBindAttribLocation(program, i, (const GLchar *) name);
|
|
||||||
}
|
|
||||||
|
|
||||||
glLinkProgram(program);
|
|
||||||
|
|
||||||
GLint status;
|
|
||||||
glGetProgramiv(program, GL_LINK_STATUS, &status);
|
|
||||||
|
|
||||||
if (status == GL_FALSE)
|
|
||||||
{
|
|
||||||
std::string warnings = getProgramWarnings();
|
|
||||||
glDeleteProgram(program);
|
|
||||||
program = 0;
|
|
||||||
throw love::Exception("Cannot link shader program object:\n%s", warnings.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
// flag shaders for auto-deletion when the program object is deleted.
|
|
||||||
for (GLuint id : shaderids)
|
|
||||||
glDeleteShader(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Shader::mapActiveUniforms()
|
void Shader::mapActiveUniforms()
|
||||||
{
|
{
|
||||||
|
// Built-in uniform locations default to -1 (nonexistant.)
|
||||||
|
for (int i = 0; i < int(BUILTIN_MAX_ENUM); i++)
|
||||||
|
builtinUniforms[i] = -1;
|
||||||
|
|
||||||
uniforms.clear();
|
uniforms.clear();
|
||||||
|
|
||||||
GLint numuniforms;
|
GLint numuniforms;
|
||||||
glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numuniforms);
|
glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numuniforms);
|
||||||
|
|
||||||
GLsizei bufsize;
|
GLchar cname[256];
|
||||||
glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, (GLint *) &bufsize);
|
const GLint bufsize = (GLint) (sizeof(cname) / sizeof(GLchar));
|
||||||
|
|
||||||
if (bufsize <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (int i = 0; i < numuniforms; i++)
|
for (int i = 0; i < numuniforms; i++)
|
||||||
{
|
{
|
||||||
GLchar *cname = new GLchar[bufsize];
|
GLsizei namelen = 0;
|
||||||
GLsizei namelength;
|
Uniform u = {};
|
||||||
|
|
||||||
Uniform u;
|
glGetActiveUniform(program, (GLuint) i, bufsize, &namelen, &u.count, &u.type, cname);
|
||||||
|
|
||||||
glGetActiveUniform(program, (GLuint) i, bufsize, &namelength, &u.count, &u.type, cname);
|
u.name = std::string(cname, (size_t) namelen);
|
||||||
|
|
||||||
u.name = std::string(cname, (size_t) namelength);
|
|
||||||
u.location = glGetUniformLocation(program, u.name.c_str());
|
u.location = glGetUniformLocation(program, u.name.c_str());
|
||||||
u.baseType = getUniformBaseType(u.type);
|
u.baseType = getUniformBaseType(u.type);
|
||||||
|
|
||||||
delete[] cname;
|
|
||||||
|
|
||||||
// glGetActiveUniform appends "[0]" to the end of array uniform names...
|
// glGetActiveUniform appends "[0]" to the end of array uniform names...
|
||||||
if (u.name.length() > 3)
|
if (u.name.length() > 3)
|
||||||
{
|
{
|
||||||
@@ -278,35 +225,18 @@ bool Shader::loadVolatile()
|
|||||||
activeTexUnits.clear();
|
activeTexUnits.clear();
|
||||||
activeTexUnits.insert(activeTexUnits.begin(), maxTexUnits, 0);
|
activeTexUnits.insert(activeTexUnits.begin(), maxTexUnits, 0);
|
||||||
|
|
||||||
// Built-in uniform locations default to -1 (nonexistant.)
|
|
||||||
for (int i = 0; i < int(BUILTIN_MAX_ENUM); i++)
|
|
||||||
builtinUniforms[i] = -1;
|
|
||||||
|
|
||||||
std::vector<GLuint> shaderids;
|
std::vector<GLuint> shaderids;
|
||||||
|
|
||||||
for (const auto &source : shaderSources)
|
|
||||||
{
|
|
||||||
GLuint shaderid = compileCode(source.first, source.second);
|
|
||||||
shaderids.push_back(shaderid);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The shader program must have both vertex and pixel shader stages.
|
// The shader program must have both vertex and pixel shader stages.
|
||||||
ShaderSources &defaults = defaultCode[0];
|
const ShaderSource &defaults = defaultCode[0];
|
||||||
|
|
||||||
ShaderSources::const_iterator source = shaderSources.find(TYPE_VERTEX);
|
const std::string &vertexcode = shaderSource.vertex.empty() ? defaults.vertex : shaderSource.vertex;
|
||||||
if (source == shaderSources.end())
|
const std::string &pixelcode = shaderSource.pixel.empty() ? defaults.pixel : shaderSource.pixel;
|
||||||
shaderids.push_back(compileCode(TYPE_VERTEX, defaults[TYPE_VERTEX]));
|
|
||||||
|
|
||||||
source = shaderSources.find(TYPE_PIXEL);
|
|
||||||
if (source == shaderSources.end())
|
|
||||||
shaderids.push_back(compileCode(TYPE_PIXEL, defaults[TYPE_PIXEL]));
|
|
||||||
|
|
||||||
if (shaderids.empty())
|
|
||||||
throw love::Exception("Cannot create shader: no valid source code!");
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
createProgram(shaderids);
|
shaderids.push_back(compileCode(STAGE_VERTEX, vertexcode));
|
||||||
|
shaderids.push_back(compileCode(STAGE_PIXEL, pixelcode));
|
||||||
}
|
}
|
||||||
catch (love::Exception &)
|
catch (love::Exception &)
|
||||||
{
|
{
|
||||||
@@ -315,6 +245,51 @@ bool Shader::loadVolatile()
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
program = glCreateProgram();
|
||||||
|
|
||||||
|
if (program == 0)
|
||||||
|
{
|
||||||
|
for (GLuint id : shaderids)
|
||||||
|
glDeleteShader(id);
|
||||||
|
throw love::Exception("Cannot create shader program object.");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (GLuint id : shaderids)
|
||||||
|
glAttachShader(program, id);
|
||||||
|
|
||||||
|
// Bind generic vertex attribute indices to names in the shader.
|
||||||
|
for (int i = 0; i < int(ATTRIB_MAX_ENUM); i++)
|
||||||
|
{
|
||||||
|
VertexAttribID attrib = (VertexAttribID) i;
|
||||||
|
|
||||||
|
// FIXME: We skip this both because pseudo-instancing is temporarily
|
||||||
|
// disabled (see graphics.lua), and because binding a non-existant
|
||||||
|
// attribute name to a location causes a shader linker warning.
|
||||||
|
if (attrib == ATTRIB_PSEUDO_INSTANCE_ID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const char *name = nullptr;
|
||||||
|
if (attribNames.find(attrib, name))
|
||||||
|
glBindAttribLocation(program, i, (const GLchar *) name);
|
||||||
|
}
|
||||||
|
|
||||||
|
glLinkProgram(program);
|
||||||
|
|
||||||
|
// Flag shaders for auto-deletion when the program object is deleted.
|
||||||
|
for (GLuint id : shaderids)
|
||||||
|
glDeleteShader(id);
|
||||||
|
|
||||||
|
GLint status;
|
||||||
|
glGetProgramiv(program, GL_LINK_STATUS, &status);
|
||||||
|
|
||||||
|
if (status == GL_FALSE)
|
||||||
|
{
|
||||||
|
std::string warnings = getProgramWarnings();
|
||||||
|
glDeleteProgram(program);
|
||||||
|
program = 0;
|
||||||
|
throw love::Exception("Cannot link shader program object:\n%s", warnings.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
// Retreive all active uniform variables in this shader from OpenGL.
|
// Retreive all active uniform variables in this shader from OpenGL.
|
||||||
mapActiveUniforms();
|
mapActiveUniforms();
|
||||||
|
|
||||||
@@ -322,9 +297,9 @@ bool Shader::loadVolatile()
|
|||||||
{
|
{
|
||||||
const char *name = nullptr;
|
const char *name = nullptr;
|
||||||
if (attribNames.find(VertexAttribID(i), name))
|
if (attribNames.find(VertexAttribID(i), name))
|
||||||
vertexAttributes[i] = glGetAttribLocation(program, name);
|
builtinAttributes[i] = glGetAttribLocation(program, name);
|
||||||
else
|
else
|
||||||
vertexAttributes[i] = -1;
|
builtinAttributes[i] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current == this)
|
if (current == this)
|
||||||
@@ -371,13 +346,16 @@ void Shader::unloadVolatile()
|
|||||||
|
|
||||||
std::string Shader::getProgramWarnings() const
|
std::string Shader::getProgramWarnings() const
|
||||||
{
|
{
|
||||||
GLint strlen, nullpos;
|
GLint strsize, nullpos;
|
||||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &strlen);
|
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &strsize);
|
||||||
|
|
||||||
char *tempstr = new char[strlen+1];
|
if (strsize == 0)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
char *tempstr = new char[strsize];
|
||||||
// be extra sure that the error string will be 0-terminated
|
// be extra sure that the error string will be 0-terminated
|
||||||
memset(tempstr, '\0', strlen+1);
|
memset(tempstr, '\0', strsize);
|
||||||
glGetProgramInfoLog(program, strlen, &nullpos, tempstr);
|
glGetProgramInfoLog(program, strsize, &nullpos, tempstr);
|
||||||
tempstr[nullpos] = '\0';
|
tempstr[nullpos] = '\0';
|
||||||
|
|
||||||
std::string warnings(tempstr);
|
std::string warnings(tempstr);
|
||||||
@@ -389,13 +367,13 @@ std::string Shader::getProgramWarnings() const
|
|||||||
std::string Shader::getWarnings() const
|
std::string Shader::getWarnings() const
|
||||||
{
|
{
|
||||||
std::string warnings;
|
std::string warnings;
|
||||||
const char *typestr;
|
const char *stagestr;
|
||||||
|
|
||||||
// Get the individual shader stage warnings
|
// Get the individual shader stage warnings
|
||||||
for (const auto &warning : shaderWarnings)
|
for (const auto &warning : shaderWarnings)
|
||||||
{
|
{
|
||||||
if (typeNames.find(warning.first, typestr))
|
if (stageNames.find(warning.first, stagestr))
|
||||||
warnings += std::string(typestr) + std::string(" shader:\n") + warning.second;
|
warnings += std::string(stagestr) + std::string(" shader:\n") + warning.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
warnings += getProgramWarnings();
|
warnings += getProgramWarnings();
|
||||||
@@ -644,7 +622,7 @@ Shader::UniformType Shader::getExternVariable(const std::string &name, int &comp
|
|||||||
|
|
||||||
bool Shader::hasVertexAttrib(VertexAttribID attrib) const
|
bool Shader::hasVertexAttrib(VertexAttribID attrib) const
|
||||||
{
|
{
|
||||||
return vertexAttributes[int(attrib)] != -1;
|
return builtinAttributes[int(attrib)] != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Shader::hasBuiltinUniform(BuiltinUniform builtin) const
|
bool Shader::hasBuiltinUniform(BuiltinUniform builtin) const
|
||||||
@@ -816,13 +794,13 @@ bool Shader::getConstant(UniformType in, const char *&out)
|
|||||||
return uniformTypes.find(in, out);
|
return uniformTypes.find(in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringMap<Shader::ShaderType, Shader::TYPE_MAX_ENUM>::Entry Shader::typeNameEntries[] =
|
StringMap<Shader::ShaderStage, Shader::STAGE_MAX_ENUM>::Entry Shader::stageNameEntries[] =
|
||||||
{
|
{
|
||||||
{"vertex", Shader::TYPE_VERTEX},
|
{"vertex", Shader::STAGE_VERTEX},
|
||||||
{"pixel", Shader::TYPE_PIXEL},
|
{"pixel", Shader::STAGE_PIXEL},
|
||||||
};
|
};
|
||||||
|
|
||||||
StringMap<Shader::ShaderType, Shader::TYPE_MAX_ENUM> Shader::typeNames(Shader::typeNameEntries, sizeof(Shader::typeNameEntries));
|
StringMap<Shader::ShaderStage, Shader::STAGE_MAX_ENUM> Shader::stageNames(Shader::stageNameEntries, sizeof(Shader::stageNameEntries));
|
||||||
|
|
||||||
StringMap<Shader::UniformType, Shader::UNIFORM_MAX_ENUM>::Entry Shader::uniformTypeEntries[] =
|
StringMap<Shader::UniformType, Shader::UNIFORM_MAX_ENUM>::Entry Shader::uniformTypeEntries[] =
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -46,11 +46,11 @@ class Shader : public Object, public Volatile
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum ShaderType
|
enum ShaderStage
|
||||||
{
|
{
|
||||||
TYPE_VERTEX,
|
STAGE_VERTEX,
|
||||||
TYPE_PIXEL,
|
STAGE_PIXEL,
|
||||||
TYPE_MAX_ENUM
|
STAGE_MAX_ENUM
|
||||||
};
|
};
|
||||||
|
|
||||||
// Built-in uniform (extern) variables.
|
// Built-in uniform (extern) variables.
|
||||||
@@ -71,8 +71,11 @@ public:
|
|||||||
UNIFORM_MAX_ENUM
|
UNIFORM_MAX_ENUM
|
||||||
};
|
};
|
||||||
|
|
||||||
// Type for a list of shader source codes in the form of sources[shadertype] = code
|
struct ShaderSource
|
||||||
typedef std::map<ShaderType, std::string> ShaderSources;
|
{
|
||||||
|
std::string vertex;
|
||||||
|
std::string pixel;
|
||||||
|
};
|
||||||
|
|
||||||
// Pointer to currently active Shader.
|
// Pointer to currently active Shader.
|
||||||
static Shader *current;
|
static Shader *current;
|
||||||
@@ -81,13 +84,13 @@ public:
|
|||||||
static Shader *defaultShader;
|
static Shader *defaultShader;
|
||||||
|
|
||||||
// Default shader code (a shader is always required internally.)
|
// Default shader code (a shader is always required internally.)
|
||||||
static ShaderSources defaultCode[1]; // TODO: RENDERER_MAX_ENUM
|
static ShaderSource defaultCode[1]; // TODO: RENDERER_MAX_ENUM
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Shader using a list of source codes.
|
* Creates a new Shader using a list of source codes.
|
||||||
* Sources must contain either vertex or pixel shader code, or both.
|
* Source must contain either vertex or pixel shader code, or both.
|
||||||
**/
|
**/
|
||||||
Shader(const ShaderSources &sources);
|
Shader(const ShaderSource &source);
|
||||||
|
|
||||||
virtual ~Shader();
|
virtual ~Shader();
|
||||||
|
|
||||||
@@ -202,8 +205,7 @@ private:
|
|||||||
UniformType getUniformBaseType(GLenum type) const;
|
UniformType getUniformBaseType(GLenum type) const;
|
||||||
void checkSetUniformError(const Uniform &u, int size, int count, UniformType sendtype) const;
|
void checkSetUniformError(const Uniform &u, int size, int count, UniformType sendtype) const;
|
||||||
|
|
||||||
GLuint compileCode(ShaderType type, const std::string &code);
|
GLuint compileCode(ShaderStage stage, const std::string &code);
|
||||||
void createProgram(const std::vector<GLuint> &shaderids);
|
|
||||||
|
|
||||||
int getTextureUnit(const std::string &name);
|
int getTextureUnit(const std::string &name);
|
||||||
|
|
||||||
@@ -212,11 +214,11 @@ private:
|
|||||||
// Get any warnings or errors generated only by the shader program object.
|
// Get any warnings or errors generated only by the shader program object.
|
||||||
std::string getProgramWarnings() const;
|
std::string getProgramWarnings() const;
|
||||||
|
|
||||||
// List of all shader code attached to this Shader
|
// Source code used for this Shader.
|
||||||
ShaderSources shaderSources;
|
ShaderSource shaderSource;
|
||||||
|
|
||||||
// Shader compiler warning strings for individual shader stages.
|
// Shader compiler warning strings for individual shader stages.
|
||||||
std::map<ShaderType, std::string> shaderWarnings;
|
std::map<ShaderStage, std::string> shaderWarnings;
|
||||||
|
|
||||||
// volatile
|
// volatile
|
||||||
GLuint program;
|
GLuint program;
|
||||||
@@ -225,7 +227,7 @@ private:
|
|||||||
GLint builtinUniforms[BUILTIN_MAX_ENUM];
|
GLint builtinUniforms[BUILTIN_MAX_ENUM];
|
||||||
|
|
||||||
// Location values for any generic vertex attribute variables.
|
// Location values for any generic vertex attribute variables.
|
||||||
GLint vertexAttributes[ATTRIB_MAX_ENUM];
|
GLint builtinAttributes[ATTRIB_MAX_ENUM];
|
||||||
|
|
||||||
// Uniform location buffer map
|
// Uniform location buffer map
|
||||||
std::map<std::string, Uniform> uniforms;
|
std::map<std::string, Uniform> uniforms;
|
||||||
@@ -247,8 +249,8 @@ private:
|
|||||||
// Counts total number of textures bound to each texture unit in all shaders
|
// Counts total number of textures bound to each texture unit in all shaders
|
||||||
static std::vector<int> textureCounters;
|
static std::vector<int> textureCounters;
|
||||||
|
|
||||||
static StringMap<ShaderType, TYPE_MAX_ENUM>::Entry typeNameEntries[];
|
static StringMap<ShaderStage, STAGE_MAX_ENUM>::Entry stageNameEntries[];
|
||||||
static StringMap<ShaderType, TYPE_MAX_ENUM> typeNames;
|
static StringMap<ShaderStage, STAGE_MAX_ENUM> stageNames;
|
||||||
|
|
||||||
static StringMap<UniformType, UNIFORM_MAX_ENUM>::Entry uniformTypeEntries[];
|
static StringMap<UniformType, UNIFORM_MAX_ENUM>::Entry uniformTypeEntries[];
|
||||||
static StringMap<UniformType, UNIFORM_MAX_ENUM> uniformTypes;
|
static StringMap<UniformType, UNIFORM_MAX_ENUM> uniformTypes;
|
||||||
|
|||||||
@@ -445,27 +445,21 @@ int w_newShader(lua_State *L)
|
|||||||
if (lua_pcall(L, 2, 2, 0) != 0)
|
if (lua_pcall(L, 2, 2, 0) != 0)
|
||||||
return luaL_error(L, "%s", lua_tostring(L, -1));
|
return luaL_error(L, "%s", lua_tostring(L, -1));
|
||||||
|
|
||||||
Shader::ShaderSources sources;
|
Shader::ShaderSource source;
|
||||||
|
|
||||||
// vertex shader code
|
// vertex shader code
|
||||||
if (lua_isstring(L, -2))
|
if (lua_isstring(L, -2))
|
||||||
{
|
source.vertex = luax_checkstring(L, -2);
|
||||||
std::string vertexcode(luaL_checkstring(L, -2));
|
|
||||||
sources[Shader::TYPE_VERTEX] = vertexcode;
|
|
||||||
}
|
|
||||||
else if (has_arg1 && has_arg2)
|
else if (has_arg1 && has_arg2)
|
||||||
return luaL_error(L, "Could not parse vertex shader code (missing 'position' function?)");
|
return luaL_error(L, "Could not parse vertex shader code (missing 'position' function?)");
|
||||||
|
|
||||||
// pixel shader code
|
// pixel shader code
|
||||||
if (lua_isstring(L, -1))
|
if (lua_isstring(L, -1))
|
||||||
{
|
source.pixel = luax_checkstring(L, -1);
|
||||||
std::string pixelcode(luaL_checkstring(L, -1));
|
|
||||||
sources[Shader::TYPE_PIXEL] = pixelcode;
|
|
||||||
}
|
|
||||||
else if (has_arg1 && has_arg2)
|
else if (has_arg1 && has_arg2)
|
||||||
return luaL_error(L, "Could not parse pixel shader code (missing 'effect' function?)");
|
return luaL_error(L, "Could not parse pixel shader code (missing 'effect' function?)");
|
||||||
|
|
||||||
if (sources.empty())
|
if (source.vertex.empty() && source.pixel.empty())
|
||||||
{
|
{
|
||||||
// Original args had source code, but effectCodeToGLSL couldn't translate it
|
// Original args had source code, but effectCodeToGLSL couldn't translate it
|
||||||
for (int i = 1; i <= 2; i++)
|
for (int i = 1; i <= 2; i++)
|
||||||
@@ -478,7 +472,7 @@ int w_newShader(lua_State *L)
|
|||||||
bool should_error = false;
|
bool should_error = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Shader *shader = instance()->newShader(sources);
|
Shader *shader = instance()->newShader(source);
|
||||||
luax_pushtype(L, "Shader", GRAPHICS_SHADER_T, shader);
|
luax_pushtype(L, "Shader", GRAPHICS_SHADER_T, shader);
|
||||||
shader->release();
|
shader->release();
|
||||||
}
|
}
|
||||||
@@ -982,9 +976,9 @@ int w_setDefaultShaderCode(lua_State *L)
|
|||||||
lua_rawgeti(L, -1, 1);
|
lua_rawgeti(L, -1, 1);
|
||||||
lua_rawgeti(L, -2, 2);
|
lua_rawgeti(L, -2, 2);
|
||||||
|
|
||||||
Shader::ShaderSources openglcode;
|
Shader::ShaderSource openglcode;
|
||||||
openglcode[Shader::TYPE_VERTEX] = luax_checkstring(L, -2);
|
openglcode.vertex = luax_checkstring(L, -2);
|
||||||
openglcode[Shader::TYPE_PIXEL] = luax_checkstring(L, -1);
|
openglcode.pixel = luax_checkstring(L, -1);
|
||||||
|
|
||||||
lua_pop(L, 3);
|
lua_pop(L, 3);
|
||||||
|
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ public:
|
|||||||
KEY_EJECT,
|
KEY_EJECT,
|
||||||
KEY_SLEEP,
|
KEY_SLEEP,
|
||||||
|
|
||||||
KEY_MAX_ENUM = 512
|
KEY_MAX_ENUM
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~Keyboard() {}
|
virtual ~Keyboard() {}
|
||||||
|
|||||||
@@ -18,8 +18,6 @@
|
|||||||
* 3. This notice may not be removed or altered from any source distribution.
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#include "common/config.h"
|
|
||||||
|
|
||||||
#include "Keyboard.h"
|
#include "Keyboard.h"
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
@@ -55,8 +53,8 @@ bool Keyboard::isDown(Key *keylist) const
|
|||||||
|
|
||||||
for (Key key = *keylist; key != KEY_MAX_ENUM; key = *(++keylist))
|
for (Key key = *keylist; key != KEY_MAX_ENUM; key = *(++keylist))
|
||||||
{
|
{
|
||||||
auto it = keys.find(key);
|
SDL_Scancode scancode = SDL_GetScancodeFromKey(keymap[key]);
|
||||||
if (it != keys.end() && keystate[SDL_GetScancodeFromKey(it->second)])
|
if (keystate[scancode])
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,9 +74,10 @@ bool Keyboard::hasTextInput() const
|
|||||||
return SDL_IsTextInputActive();
|
return SDL_IsTextInputActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<Keyboard::Key, SDL_Keycode> Keyboard::createKeyMap()
|
const SDL_Keycode *Keyboard::createKeyMap()
|
||||||
{
|
{
|
||||||
std::map<Keyboard::Key, SDL_Keycode> k;
|
// Array must be static so its lifetime continues once the function returns.
|
||||||
|
static SDL_Keycode k[Keyboard::KEY_MAX_ENUM] = {SDLK_UNKNOWN};
|
||||||
|
|
||||||
k[Keyboard::KEY_UNKNOWN] = SDLK_UNKNOWN;
|
k[Keyboard::KEY_UNKNOWN] = SDLK_UNKNOWN;
|
||||||
|
|
||||||
@@ -287,7 +286,7 @@ std::map<Keyboard::Key, SDL_Keycode> Keyboard::createKeyMap()
|
|||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<Keyboard::Key, SDL_Keycode> Keyboard::keys = Keyboard::createKeyMap();
|
const SDL_Keycode *Keyboard::keymap = Keyboard::createKeyMap();
|
||||||
|
|
||||||
} // sdl
|
} // sdl
|
||||||
} // keyboard
|
} // keyboard
|
||||||
|
|||||||
@@ -26,10 +26,7 @@
|
|||||||
#include "common/EnumMap.h"
|
#include "common/EnumMap.h"
|
||||||
|
|
||||||
// SDL
|
// SDL
|
||||||
#include <SDL.h>
|
#include <SDL_keyboard.h>
|
||||||
|
|
||||||
// STL
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
{
|
{
|
||||||
@@ -60,8 +57,8 @@ private:
|
|||||||
// The real implementation is in love::event::sdl::Event::Convert.
|
// The real implementation is in love::event::sdl::Event::Convert.
|
||||||
bool key_repeat;
|
bool key_repeat;
|
||||||
|
|
||||||
static std::map<Key, SDL_Keycode> createKeyMap();
|
static const SDL_Keycode *createKeyMap();
|
||||||
static std::map<Key, SDL_Keycode> keys;
|
static const SDL_Keycode *keymap;
|
||||||
|
|
||||||
}; // Keyboard
|
}; // Keyboard
|
||||||
|
|
||||||
|
|||||||
@@ -81,11 +81,6 @@ void RandomGenerator::setSeed(RandomGenerator::Seed newseed)
|
|||||||
|
|
||||||
seed = newseed;
|
seed = newseed;
|
||||||
rng_state = seed;
|
rng_state = seed;
|
||||||
|
|
||||||
// Xorshift's first couple results after seeding will be similar to results
|
|
||||||
// from very similar seeds, so we immediately discard them here.
|
|
||||||
for (int i = 0; i < 2; i++)
|
|
||||||
rand();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RandomGenerator::Seed RandomGenerator::getSeed() const
|
RandomGenerator::Seed RandomGenerator::getSeed() const
|
||||||
|
|||||||
@@ -36,33 +36,23 @@ namespace sdl
|
|||||||
// we want them in pixel coordinates (may be different with high-DPI enabled.)
|
// we want them in pixel coordinates (may be different with high-DPI enabled.)
|
||||||
static void windowToPixelCoords(int *x, int *y)
|
static void windowToPixelCoords(int *x, int *y)
|
||||||
{
|
{
|
||||||
double scale = 1.0;
|
window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
|
||||||
|
|
||||||
love::window::Window *window = love::window::sdl::Window::getSingleton();
|
if (window && x)
|
||||||
if (window != nullptr)
|
*x = (int) window->toPixels(*x);
|
||||||
scale = window->getPixelScale();
|
if (window && y)
|
||||||
|
*y = (int) window->toPixels(*y);
|
||||||
if (x != nullptr)
|
|
||||||
*x = int(double(*x) * scale);
|
|
||||||
|
|
||||||
if (y != nullptr)
|
|
||||||
*y = int(double(*y) * scale);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// And vice versa for setting mouse coordinates.
|
// And vice versa for setting mouse coordinates.
|
||||||
static void pixelToWindowCoords(int *x, int *y)
|
static void pixelToWindowCoords(int *x, int *y)
|
||||||
{
|
{
|
||||||
double scale = 1.0;
|
window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
|
||||||
|
|
||||||
love::window::Window *window = love::window::sdl::Window::getSingleton();
|
if (window && x)
|
||||||
if (window != nullptr)
|
*x = (int) window->fromPixels(*x);
|
||||||
scale = window->getPixelScale();
|
if (window && y)
|
||||||
|
*y = (int) window->fromPixels(*y);
|
||||||
if (x != nullptr)
|
|
||||||
*x = int(double(*x) / scale);
|
|
||||||
|
|
||||||
if (y != nullptr)
|
|
||||||
*y = int(double(*y) / scale);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *Mouse::getName() const
|
const char *Mouse::getName() const
|
||||||
|
|||||||
@@ -93,6 +93,12 @@ EdgeShape *Physics::newEdgeShape(float x1, float y1, float x2, float y2)
|
|||||||
int Physics::newPolygonShape(lua_State *L)
|
int Physics::newPolygonShape(lua_State *L)
|
||||||
{
|
{
|
||||||
int argc = lua_gettop(L);
|
int argc = lua_gettop(L);
|
||||||
|
|
||||||
|
bool istable = lua_istable(L, 1);
|
||||||
|
|
||||||
|
if (istable)
|
||||||
|
argc = lua_objlen(L, 1);
|
||||||
|
|
||||||
if (argc % 2 != 0)
|
if (argc % 2 != 0)
|
||||||
return luaL_error(L, "Number of vertex components must be a multiple of two.");
|
return luaL_error(L, "Number of vertex components must be a multiple of two.");
|
||||||
|
|
||||||
@@ -103,16 +109,31 @@ int Physics::newPolygonShape(lua_State *L)
|
|||||||
else if (vcount > b2_maxPolygonVertices)
|
else if (vcount > b2_maxPolygonVertices)
|
||||||
return luaL_error(L, "Expected a maximum of %d vertices, got %d.", b2_maxPolygonVertices, vcount);
|
return luaL_error(L, "Expected a maximum of %d vertices, got %d.", b2_maxPolygonVertices, vcount);
|
||||||
|
|
||||||
b2PolygonShape *s = new b2PolygonShape();
|
|
||||||
|
|
||||||
b2Vec2 vecs[b2_maxPolygonVertices];
|
b2Vec2 vecs[b2_maxPolygonVertices];
|
||||||
|
|
||||||
for (int i = 0; i < vcount; i++)
|
if (istable)
|
||||||
{
|
{
|
||||||
float x = (float)luaL_checknumber(L, 1 + i * 2);
|
for (int i = 0; i < vcount; i++)
|
||||||
float y = (float)luaL_checknumber(L, 2 + i * 2);
|
{
|
||||||
vecs[i] = Physics::scaleDown(b2Vec2(x, y));
|
lua_rawgeti(L, 1, 1 + i * 2);
|
||||||
|
lua_rawgeti(L, 1, 2 + i * 2);
|
||||||
|
float x = (float)luaL_checknumber(L, -2);
|
||||||
|
float y = (float)luaL_checknumber(L, -1);
|
||||||
|
vecs[i] = Physics::scaleDown(b2Vec2(x, y));
|
||||||
|
lua_pop(L, 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < vcount; i++)
|
||||||
|
{
|
||||||
|
float x = (float)luaL_checknumber(L, 1 + i * 2);
|
||||||
|
float y = (float)luaL_checknumber(L, 2 + i * 2);
|
||||||
|
vecs[i] = Physics::scaleDown(b2Vec2(x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b2PolygonShape *s = new b2PolygonShape();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -133,22 +154,42 @@ int Physics::newPolygonShape(lua_State *L)
|
|||||||
int Physics::newChainShape(lua_State *L)
|
int Physics::newChainShape(lua_State *L)
|
||||||
{
|
{
|
||||||
int argc = lua_gettop(L)-1; // first argument is looping
|
int argc = lua_gettop(L)-1; // first argument is looping
|
||||||
|
|
||||||
|
bool istable = lua_istable(L, 2);
|
||||||
|
|
||||||
|
if (istable)
|
||||||
|
argc = lua_objlen(L, 2);
|
||||||
|
|
||||||
if (argc % 2 != 0)
|
if (argc % 2 != 0)
|
||||||
return luaL_error(L, "Number of vertex components must be a multiple of two.");
|
return luaL_error(L, "Number of vertex components must be a multiple of two.");
|
||||||
|
|
||||||
int vcount = (int)argc/2;
|
int vcount = (int)argc/2;
|
||||||
b2ChainShape *s = new b2ChainShape();
|
|
||||||
bool loop = luax_toboolean(L, 1);
|
bool loop = luax_toboolean(L, 1);
|
||||||
b2Vec2 *vecs = new b2Vec2[vcount];
|
b2Vec2 *vecs = new b2Vec2[vcount];
|
||||||
|
|
||||||
for (int i = 0; i<vcount; i++)
|
if (istable)
|
||||||
{
|
{
|
||||||
float x = (float)lua_tonumber(L, -2);
|
for (int i = 0; i < vcount; i++)
|
||||||
float y = (float)lua_tonumber(L, -1);
|
{
|
||||||
vecs[i].Set(x, y);
|
lua_rawgeti(L, 2, 1 + i * 2);
|
||||||
vecs[i] = Physics::scaleDown(vecs[i]);
|
lua_rawgeti(L, 2, 2 + i * 2);
|
||||||
lua_pop(L, 2);
|
float x = (float)lua_tonumber(L, -2);
|
||||||
|
float y = (float)lua_tonumber(L, -1);
|
||||||
|
vecs[i] = Physics::scaleDown(b2Vec2(x, y));
|
||||||
|
lua_pop(L, 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < vcount; i++)
|
||||||
|
{
|
||||||
|
float x = (float)luaL_checknumber(L, 2 + i * 2);
|
||||||
|
float y = (float)luaL_checknumber(L, 3 + i * 2);
|
||||||
|
vecs[i] = Physics::scaleDown(b2Vec2(x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b2ChainShape *s = new b2ChainShape();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -160,6 +201,7 @@ int Physics::newChainShape(lua_State *L)
|
|||||||
catch (love::Exception &)
|
catch (love::Exception &)
|
||||||
{
|
{
|
||||||
delete[] vecs;
|
delete[] vecs;
|
||||||
|
delete s;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public:
|
|||||||
* Indicates how many bytes of raw data should be generated at each
|
* Indicates how many bytes of raw data should be generated at each
|
||||||
* call to Decode.
|
* call to Decode.
|
||||||
**/
|
**/
|
||||||
static const int DEFAULT_BUFFER_SIZE = 2048;
|
static const int DEFAULT_BUFFER_SIZE = 16384;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates the quality of the sound.
|
* Indicates the quality of the sound.
|
||||||
|
|||||||
@@ -83,6 +83,11 @@ public:
|
|||||||
{
|
{
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
|
||||||
|
bool operator == (const WindowSize &w) const
|
||||||
|
{
|
||||||
|
return w.width == width && w.height == height;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MessageBoxData
|
struct MessageBoxData
|
||||||
@@ -156,7 +161,7 @@ public:
|
|||||||
|
|
||||||
virtual const void *getHandle() const = 0;
|
virtual const void *getHandle() const = 0;
|
||||||
|
|
||||||
virtual bool showMessageBox(MessageBoxType type, const std::string &title, const std::string &message, bool attachtowindow) = 0;
|
virtual bool showMessageBox(const std::string &title, const std::string &message, MessageBoxType type, bool attachtowindow) = 0;
|
||||||
virtual int showMessageBox(const MessageBoxData &data) = 0;
|
virtual int showMessageBox(const MessageBoxData &data) = 0;
|
||||||
|
|
||||||
//virtual static Window *createSingleton() = 0;
|
//virtual static Window *createSingleton() = 0;
|
||||||
|
|||||||
@@ -497,29 +497,17 @@ std::vector<WindowSize> Window::getFullscreenSizes(int displayindex) const
|
|||||||
{
|
{
|
||||||
std::vector<WindowSize> sizes;
|
std::vector<WindowSize> sizes;
|
||||||
|
|
||||||
SDL_DisplayMode mode = {};
|
|
||||||
std::vector<WindowSize>::const_iterator it;
|
|
||||||
for (int i = 0; i < SDL_GetNumDisplayModes(displayindex); i++)
|
for (int i = 0; i < SDL_GetNumDisplayModes(displayindex); i++)
|
||||||
{
|
{
|
||||||
|
SDL_DisplayMode mode = {};
|
||||||
SDL_GetDisplayMode(displayindex, i, &mode);
|
SDL_GetDisplayMode(displayindex, i, &mode);
|
||||||
|
|
||||||
|
WindowSize w = {mode.w, mode.h};
|
||||||
|
|
||||||
// SDL2's display mode list has multiple entries for modes of the same
|
// SDL2's display mode list has multiple entries for modes of the same
|
||||||
// size with different bits per pixel, so we need to filter those out.
|
// size with different bits per pixel, so we need to filter those out.
|
||||||
bool alreadyhassize = false;
|
if (std::find(sizes.begin(), sizes.end(), w) == sizes.end())
|
||||||
for (it = sizes.begin(); it != sizes.end(); ++it)
|
|
||||||
{
|
|
||||||
if (it->width == mode.w && it->height == mode.h)
|
|
||||||
{
|
|
||||||
alreadyhassize = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!alreadyhassize)
|
|
||||||
{
|
|
||||||
WindowSize w = {mode.w, mode.h};
|
|
||||||
sizes.push_back(w);
|
sizes.push_back(w);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sizes;
|
return sizes;
|
||||||
@@ -767,7 +755,7 @@ SDL_MessageBoxFlags Window::convertMessageBoxType(MessageBoxType type) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Window::showMessageBox(MessageBoxType type, const std::string &title, const std::string &message, bool attachtowindow)
|
bool Window::showMessageBox(const std::string &title, const std::string &message, MessageBoxType type, bool attachtowindow)
|
||||||
{
|
{
|
||||||
SDL_MessageBoxFlags flags = convertMessageBoxType(type);
|
SDL_MessageBoxFlags flags = convertMessageBoxType(type);
|
||||||
SDL_Window *sdlwindow = attachtowindow ? window : nullptr;
|
SDL_Window *sdlwindow = attachtowindow ? window : nullptr;
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ public:
|
|||||||
|
|
||||||
const void *getHandle() const;
|
const void *getHandle() const;
|
||||||
|
|
||||||
bool showMessageBox(MessageBoxType type, const std::string &title, const std::string &message, bool attachtowindow);
|
bool showMessageBox(const std::string &title, const std::string &message, MessageBoxType type, bool attachtowindow);
|
||||||
int showMessageBox(const MessageBoxData &data);
|
int showMessageBox(const MessageBoxData &data);
|
||||||
|
|
||||||
static love::window::Window *createSingleton();
|
static love::window::Window *createSingleton();
|
||||||
|
|||||||
@@ -395,32 +395,29 @@ int w_minimize(lua_State* /*L*/)
|
|||||||
int w_showMessageBox(lua_State *L)
|
int w_showMessageBox(lua_State *L)
|
||||||
{
|
{
|
||||||
Window::MessageBoxData data = {};
|
Window::MessageBoxData data = {};
|
||||||
|
data.type = Window::MESSAGEBOX_INFO;
|
||||||
|
|
||||||
const char *typestr = luaL_checkstring(L, 1);
|
data.title = luaL_checkstring(L, 1);
|
||||||
if (!Window::getConstant(typestr, data.type))
|
data.message = luaL_checkstring(L, 2);
|
||||||
return luaL_error(L, "Invalid messagebox type: %s", typestr);
|
|
||||||
|
|
||||||
data.title = luaL_checkstring(L, 2);
|
|
||||||
data.message = luaL_checkstring(L, 3);
|
|
||||||
|
|
||||||
// If we have a table argument, we assume a list of button names, which
|
// If we have a table argument, we assume a list of button names, which
|
||||||
// means we should use the more complex message box API.
|
// means we should use the more complex message box API.
|
||||||
if (lua_istable(L, 4))
|
if (lua_istable(L, 3))
|
||||||
{
|
{
|
||||||
size_t numbuttons = lua_objlen(L, 4);
|
size_t numbuttons = lua_objlen(L, 3);
|
||||||
if (numbuttons == 0)
|
if (numbuttons == 0)
|
||||||
return luaL_error(L, "Must have at least one messagebox button.");
|
return luaL_error(L, "Must have at least one messagebox button.");
|
||||||
|
|
||||||
// Array of button names.
|
// Array of button names.
|
||||||
for (size_t i = 0; i < numbuttons; i++)
|
for (size_t i = 0; i < numbuttons; i++)
|
||||||
{
|
{
|
||||||
lua_rawgeti(L, 4, i + 1);
|
lua_rawgeti(L, 3, i + 1);
|
||||||
data.buttons.push_back(luax_checkstring(L, -1));
|
data.buttons.push_back(luax_checkstring(L, -1));
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optional table entry specifying the button to use when enter is pressed.
|
// Optional table entry specifying the button to use when enter is pressed.
|
||||||
lua_getfield(L, 4, "enterbutton");
|
lua_getfield(L, 3, "enterbutton");
|
||||||
if (!lua_isnoneornil(L, -1))
|
if (!lua_isnoneornil(L, -1))
|
||||||
data.enterButtonIndex = luaL_checkint(L, -1) - 1;
|
data.enterButtonIndex = luaL_checkint(L, -1) - 1;
|
||||||
else
|
else
|
||||||
@@ -428,13 +425,17 @@ int w_showMessageBox(lua_State *L)
|
|||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
// Optional table entry specifying the button to use when esc is pressed.
|
// Optional table entry specifying the button to use when esc is pressed.
|
||||||
lua_getfield(L, 4, "escapebutton");
|
lua_getfield(L, 3, "escapebutton");
|
||||||
if (!lua_isnoneornil(L, -1))
|
if (!lua_isnoneornil(L, -1))
|
||||||
data.escapeButtonIndex = luaL_checkint(L, -1) - 1;
|
data.escapeButtonIndex = luaL_checkint(L, -1) - 1;
|
||||||
else
|
else
|
||||||
data.escapeButtonIndex = (int) data.buttons.size() - 1;
|
data.escapeButtonIndex = (int) data.buttons.size() - 1;
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
const char *typestr = lua_isnoneornil(L, 4) ? nullptr : luaL_checkstring(L, 4);
|
||||||
|
if (typestr && !Window::getConstant(typestr, data.type))
|
||||||
|
return luaL_error(L, "Invalid messagebox type: %s", typestr);
|
||||||
|
|
||||||
data.attachToWindow = luax_optboolean(L, 5, true);
|
data.attachToWindow = luax_optboolean(L, 5, true);
|
||||||
|
|
||||||
int pressedbutton = instance()->showMessageBox(data);
|
int pressedbutton = instance()->showMessageBox(data);
|
||||||
@@ -442,10 +443,14 @@ int w_showMessageBox(lua_State *L)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
const char *typestr = lua_isnoneornil(L, 3) ? nullptr : luaL_checkstring(L, 3);
|
||||||
|
if (typestr && !Window::getConstant(typestr, data.type))
|
||||||
|
return luaL_error(L, "Invalid messagebox type: %s", typestr);
|
||||||
|
|
||||||
data.attachToWindow = luax_optboolean(L, 4, true);
|
data.attachToWindow = luax_optboolean(L, 4, true);
|
||||||
|
|
||||||
// Display a simple message box.
|
// Display a simple message box.
|
||||||
bool success = instance()->showMessageBox(data.type, data.title, data.message, data.attachToWindow);
|
bool success = instance()->showMessageBox(data.title, data.message, data.type, data.attachToWindow);
|
||||||
luax_pushboolean(L, success);
|
luax_pushboolean(L, success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -479,6 +479,7 @@ function love.run()
|
|||||||
|
|
||||||
if love.math then
|
if love.math then
|
||||||
love.math.setRandomSeed(os.time())
|
love.math.setRandomSeed(os.time())
|
||||||
|
for i=1,3 do love.math.random() end
|
||||||
end
|
end
|
||||||
|
|
||||||
if love.event then
|
if love.event then
|
||||||
|
|||||||
@@ -858,6 +858,9 @@ const unsigned char boot_lua[] =
|
|||||||
0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
|
0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||||
0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x74, 0x52, 0x61, 0x6e,
|
0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x74, 0x52, 0x61, 0x6e,
|
||||||
0x64, 0x6f, 0x6d, 0x53, 0x65, 0x65, 0x64, 0x28, 0x6f, 0x73, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x28, 0x29, 0x29, 0x0a,
|
0x64, 0x6f, 0x6d, 0x53, 0x65, 0x65, 0x64, 0x28, 0x6f, 0x73, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x28, 0x29, 0x29, 0x0a,
|
||||||
|
0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x3d, 0x31, 0x2c, 0x33, 0x20, 0x64, 0x6f, 0x20, 0x6c, 0x6f, 0x76,
|
||||||
|
0x65, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x28, 0x29, 0x20, 0x65, 0x6e,
|
||||||
|
0x64, 0x0a,
|
||||||
0x09, 0x65, 0x6e, 0x64, 0x0a,
|
0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||||
0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65,
|
0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65,
|
||||||
0x6e, 0x0a,
|
0x6e, 0x0a,
|
||||||
|
|||||||
Reference in New Issue
Block a user