mirror of
https://github.com/love2d/love.git
synced 2026-08-16 16:20:42 +02:00
Merge in default
--HG-- branch : minor
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2012 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.
|
||||
**/
|
||||
|
||||
// LOVE
|
||||
#include "Module.h"
|
||||
#include "Exception.h"
|
||||
|
||||
// std
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::map<std::string, love::Module*> registry;
|
||||
} // anonymous namespace
|
||||
|
||||
namespace love
|
||||
{
|
||||
void Module::registerInstance(Module *instance)
|
||||
{
|
||||
if (instance == NULL)
|
||||
throw Exception("Module instance is NULL");
|
||||
|
||||
std::string name(instance->getName());
|
||||
|
||||
std::map<std::string, Module*>::iterator it = registry.find(name);
|
||||
|
||||
if (registry.end() != it)
|
||||
{
|
||||
if (it->second == instance)
|
||||
return;
|
||||
throw Exception("Module %s already registered!", instance->getName());
|
||||
}
|
||||
|
||||
registry.insert(make_pair(name, instance));
|
||||
}
|
||||
|
||||
Module *Module::getInstance(const char *name)
|
||||
{
|
||||
std::map<std::string, Module*>::iterator it = registry.find(std::string(name));
|
||||
|
||||
if (registry.end() == it)
|
||||
return NULL;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
} // namespace love
|
||||
@@ -48,6 +48,21 @@ public:
|
||||
**/
|
||||
virtual const char *getName() const = 0;
|
||||
|
||||
/**
|
||||
* Add module to internal registry. To be used /only/ in
|
||||
* runtime.cpp:luax_register_module()
|
||||
* @param instance The module instance.
|
||||
*/
|
||||
static void registerInstance(Module *instance);
|
||||
|
||||
/**
|
||||
* Retrieve module instance from internal registry. May return NULL
|
||||
* if module not registered.
|
||||
* @param name The full name of the module.
|
||||
* @returns Module instance of NULL if the module is not registered.
|
||||
*/
|
||||
static Module *getInstance(const char *name);
|
||||
|
||||
}; // Module
|
||||
|
||||
} // love
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "math.h"
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
|
||||
namespace
|
||||
{
|
||||
// The Box–Muller transform generates two random numbers, one of which we
|
||||
// cache here. A value of +infinity is used to signal the cache is invalid
|
||||
// and that new numbers have to be generated.
|
||||
float last_randnormal = std::numeric_limits<float>::infinity();
|
||||
}
|
||||
|
||||
namespace love
|
||||
{
|
||||
|
||||
float random_normal(float o)
|
||||
{
|
||||
// number in cache?
|
||||
if (last_randnormal != std::numeric_limits<float>::infinity())
|
||||
{
|
||||
float r = last_randnormal;
|
||||
last_randnormal = std::numeric_limits<float>::infinity();
|
||||
return r * o;
|
||||
}
|
||||
|
||||
// else: generate numbers using the Box-Muller transform
|
||||
float a = sqrt(-2.0f * log(random()));
|
||||
float b = float(LOVE_M_PI) * 2.0f * random();
|
||||
last_randnormal = a * cos(b);
|
||||
return a * sin(b) * o;
|
||||
}
|
||||
|
||||
} // namespace love
|
||||
@@ -22,6 +22,7 @@
|
||||
#define LOVE_MATH_H
|
||||
|
||||
#include <climits> // for CHAR_BIT
|
||||
#include <cstdlib> // for rand() and RAND_MAX
|
||||
|
||||
/* Definitions of useful mathematical constants
|
||||
* M_E - e
|
||||
@@ -80,6 +81,42 @@ inline float next_p2(float x)
|
||||
return static_cast<float>(next_p2(static_cast<int>(x)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a random number from a uniform distribution.
|
||||
* @returns Uniformly distributed random number in [0:1).
|
||||
*/
|
||||
inline float random()
|
||||
{
|
||||
// to satisfy picky compilers...
|
||||
return float(double(rand() % RAND_MAX) / double(RAND_MAX));
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a random number from a uniform distribution.
|
||||
* @return Uniformly distributed random number in [0:max).
|
||||
*/
|
||||
inline float random(float max)
|
||||
{
|
||||
return random() * max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a random number from a uniform distribution.
|
||||
* @return Uniformly distributed random number in [min:max).
|
||||
*/
|
||||
inline float random(float min, float max)
|
||||
{
|
||||
return random(max - min) + min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a random number from a normal/gaussian distribution.
|
||||
* @param o Standard deviation of the distribution.
|
||||
* @returns Normal distributed random number with mean 0 and variance o^2.
|
||||
*/
|
||||
float random_normal(float o = 1.);
|
||||
#define random_gaussian random_normal
|
||||
|
||||
} // love
|
||||
|
||||
#endif // LOVE_MATH_H
|
||||
|
||||
@@ -196,6 +196,9 @@ int luax_register_module(lua_State *L, const WrappedModule &m)
|
||||
lua_setfield(L, -3, m.name); // love.graphics = table
|
||||
lua_remove(L, -2); // love
|
||||
|
||||
// Register module instance
|
||||
Module::registerInstance(m.module);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,22 +91,24 @@ Message *Event::convert(SDL_Event &e)
|
||||
switch (e.type)
|
||||
{
|
||||
case SDL_KEYDOWN:
|
||||
if (keys.find(e.key.keysym.sym, key) && love::event::Event::keys.find(key, txt))
|
||||
{
|
||||
arg1 = new Variant(txt, strlen(txt));
|
||||
arg2 = new Variant((double) e.key.keysym.unicode);
|
||||
msg = new Message("keypressed", arg1, arg2);
|
||||
arg1->release();
|
||||
arg2->release();
|
||||
}
|
||||
if (!keys.find(e.key.keysym.sym, key))
|
||||
key = love::keyboard::Keyboard::KEY_UNKNOWN;
|
||||
if (!love::event::Event::keys.find(key, txt))
|
||||
txt = "unknown";
|
||||
arg1 = new Variant(txt, strlen(txt));
|
||||
arg2 = new Variant((double) e.key.keysym.unicode);
|
||||
msg = new Message("keypressed", arg1, arg2);
|
||||
arg1->release();
|
||||
arg2->release();
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
if (keys.find(e.key.keysym.sym, key) && love::event::Event::keys.find(key, txt))
|
||||
{
|
||||
arg1 = new Variant(txt, strlen(txt));
|
||||
msg = new Message("keyreleased", arg1);
|
||||
arg1->release();
|
||||
}
|
||||
if (!keys.find(e.key.keysym.sym, key))
|
||||
key = love::keyboard::Keyboard::KEY_UNKNOWN;
|
||||
if (!love::event::Event::keys.find(key, txt))
|
||||
txt = "unknown";
|
||||
arg1 = new Variant(txt, strlen(txt));
|
||||
msg = new Message("keyreleased", arg1);
|
||||
arg1->release();
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "common/Object.h"
|
||||
#include "common/StringMap.h"
|
||||
#include "common/int.h"
|
||||
#include "FileData.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -93,7 +94,7 @@ public:
|
||||
* @param size The number of bytes to attempt reading, or -1 for EOF.
|
||||
* @return A newly allocated Data object.
|
||||
**/
|
||||
virtual Data *read(int64 size = ALL) = 0;
|
||||
virtual FileData *read(int64 size = ALL) = 0;
|
||||
|
||||
/**
|
||||
* Reads data into the destination buffer.
|
||||
|
||||
@@ -111,7 +111,7 @@ int64 File::getSize()
|
||||
}
|
||||
|
||||
|
||||
Data *File::read(int64 size)
|
||||
FileData *File::read(int64 size)
|
||||
{
|
||||
bool isOpen = (file != 0);
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
bool open(Mode mode);
|
||||
bool close();
|
||||
int64 getSize();
|
||||
Data *read(int64 size = ALL);
|
||||
FileData *read(int64 size = ALL);
|
||||
int64 read(void *dst, int64 size);
|
||||
bool write(const void *data, int64 size);
|
||||
bool write(const Data *data, int64 size = ALL);
|
||||
|
||||
@@ -131,6 +131,16 @@ void ImageRasterizer::load()
|
||||
widths[c] = (end - start);
|
||||
}
|
||||
|
||||
// Find spacing of last glyph
|
||||
if (length > 0)
|
||||
{
|
||||
start = end;
|
||||
while (start < imgw && equal(pixels[start], spacer))
|
||||
++start;
|
||||
|
||||
spacing[glyphs[length - 1]] = (start > end) ? (start - end) : 0;
|
||||
}
|
||||
|
||||
// Replace spacer color with an empty pixel
|
||||
for (unsigned int i = 0; i < imgs; ++i)
|
||||
{
|
||||
|
||||
@@ -156,6 +156,7 @@ StringMap<Graphics::PointStyle, Graphics::POINT_MAX_ENUM> Graphics::pointStyles(
|
||||
StringMap<Graphics::Support, Graphics::SUPPORT_MAX_ENUM>::Entry Graphics::supportEntries[] =
|
||||
{
|
||||
{ "canvas", Graphics::SUPPORT_CANVAS },
|
||||
{ "hdrcanvas", Graphics::SUPPORT_HDR_CANVAS },
|
||||
{ "pixeleffect", Graphics::SUPPORT_PIXELEFFECT },
|
||||
{ "npot", Graphics::SUPPORT_NPOT },
|
||||
{ "subtractive", Graphics::SUPPORT_SUBTRACTIVE },
|
||||
|
||||
@@ -85,6 +85,7 @@ public:
|
||||
enum Support
|
||||
{
|
||||
SUPPORT_CANVAS = 1,
|
||||
SUPPORT_HDR_CANVAS,
|
||||
SUPPORT_PIXELEFFECT,
|
||||
SUPPORT_NPOT,
|
||||
SUPPORT_SUBTRACTIVE,
|
||||
|
||||
@@ -50,11 +50,6 @@ public:
|
||||
|
||||
virtual void flip(bool x, bool y) = 0;
|
||||
|
||||
/**
|
||||
* Mirror texture coordinates around 0.5
|
||||
*/
|
||||
virtual void mirror(bool x, bool y) = 0;
|
||||
|
||||
/**
|
||||
* Gets a pointer to the vertices.
|
||||
**/
|
||||
|
||||
@@ -42,9 +42,10 @@ struct FramebufferStrategy
|
||||
* @param[out] img Texture name
|
||||
* @param[in] width Width of framebuffer
|
||||
* @param[in] height Height of framebuffer
|
||||
* @param[in] texture_type Type of the canvas texture.
|
||||
* @return Creation status
|
||||
*/
|
||||
virtual GLenum createFBO(GLuint &, GLuint &, GLuint &, int, int)
|
||||
virtual GLenum createFBO(GLuint &, GLuint &, GLuint &, int, int, Canvas::TextureType)
|
||||
{
|
||||
return GL_FRAMEBUFFER_UNSUPPORTED;
|
||||
}
|
||||
@@ -60,7 +61,7 @@ struct FramebufferStrategy
|
||||
|
||||
struct FramebufferStrategyGL3 : public FramebufferStrategy
|
||||
{
|
||||
virtual GLenum createFBO(GLuint &framebuffer, GLuint &depth_stencil, GLuint &img, int width, int height)
|
||||
virtual GLenum createFBO(GLuint &framebuffer, GLuint &depth_stencil, GLuint &img, int width, int height, Canvas::TextureType texture_type)
|
||||
{
|
||||
// get currently bound fbo to reset to it later
|
||||
GLint current_fbo;
|
||||
@@ -75,27 +76,41 @@ struct FramebufferStrategyGL3 : public FramebufferStrategy
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, depth_stencil);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, width, height);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
|
||||
GL_RENDERBUFFER, depth_stencil);
|
||||
GL_RENDERBUFFER, depth_stencil);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
||||
GL_RENDERBUFFER, depth_stencil);
|
||||
GL_RENDERBUFFER, depth_stencil);
|
||||
|
||||
// generate texture save target
|
||||
GLint internalFormat;
|
||||
GLenum format;
|
||||
switch (texture_type)
|
||||
{
|
||||
case Canvas::TYPE_HDR:
|
||||
internalFormat = GL_RGBA16F;
|
||||
format = GL_FLOAT;
|
||||
break;
|
||||
case Canvas::TYPE_NORMAL:
|
||||
default:
|
||||
internalFormat = GL_RGBA8;
|
||||
format = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
||||
glGenTextures(1, &img);
|
||||
bindTexture(img);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height,
|
||||
0, GL_RGBA, format, NULL);
|
||||
bindTexture(0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D, img, 0);
|
||||
GL_TEXTURE_2D, img, 0);
|
||||
|
||||
// check status
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
|
||||
// unbind framebuffer
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)current_fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, (GLuint) current_fbo);
|
||||
return status;
|
||||
}
|
||||
virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil, GLuint img)
|
||||
@@ -111,10 +126,9 @@ struct FramebufferStrategyGL3 : public FramebufferStrategy
|
||||
}
|
||||
};
|
||||
|
||||
struct FramebufferStrategyEXT : public FramebufferStrategy
|
||||
struct FramebufferStrategyPackedEXT : public FramebufferStrategy
|
||||
{
|
||||
|
||||
virtual GLenum createFBO(GLuint &framebuffer, GLuint &depth_stencil, GLuint &img, int width, int height)
|
||||
virtual GLenum createFBO(GLuint &framebuffer, GLuint &depth_stencil, GLuint &img, int width, int height, Canvas::TextureType texture_type)
|
||||
{
|
||||
GLint current_fbo;
|
||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, ¤t_fbo);
|
||||
@@ -126,29 +140,45 @@ struct FramebufferStrategyEXT : public FramebufferStrategy
|
||||
// create stencil buffer
|
||||
glGenRenderbuffersEXT(1, &depth_stencil);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil);
|
||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, width, height);
|
||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT,
|
||||
width, height);
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
|
||||
GL_RENDERBUFFER_EXT, depth_stencil);
|
||||
GL_RENDERBUFFER_EXT, depth_stencil);
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
||||
GL_RENDERBUFFER_EXT, depth_stencil);
|
||||
GL_RENDERBUFFER_EXT, depth_stencil);
|
||||
|
||||
// generate texture save target
|
||||
GLint internalFormat;
|
||||
GLenum format;
|
||||
switch (texture_type)
|
||||
{
|
||||
case Canvas::TYPE_HDR:
|
||||
internalFormat = GL_RGBA16F;
|
||||
format = GL_FLOAT;
|
||||
break;
|
||||
case Canvas::TYPE_NORMAL:
|
||||
default:
|
||||
internalFormat = GL_RGBA8;
|
||||
format = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
||||
glGenTextures(1, &img);
|
||||
bindTexture(img);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height,
|
||||
0, GL_RGBA, format, NULL);
|
||||
bindTexture(0);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
GL_TEXTURE_2D, img, 0);
|
||||
GL_TEXTURE_2D, img, 0);
|
||||
|
||||
// check status
|
||||
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
|
||||
// unbind framebuffer
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (GLuint)current_fbo);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (GLuint) current_fbo);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -165,45 +195,112 @@ struct FramebufferStrategyEXT : public FramebufferStrategy
|
||||
}
|
||||
};
|
||||
|
||||
struct FramebufferStrategyEXT : public FramebufferStrategyPackedEXT
|
||||
{
|
||||
virtual GLenum createFBO(GLuint &framebuffer, GLuint &stencil, GLuint &img, int width, int height, Canvas::TextureType texture_type)
|
||||
{
|
||||
GLint current_fbo;
|
||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, ¤t_fbo);
|
||||
|
||||
// create framebuffer
|
||||
glGenFramebuffersEXT(1, &framebuffer);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
|
||||
|
||||
// create stencil buffer
|
||||
glGenRenderbuffersEXT(1, &stencil);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, stencil);
|
||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX,
|
||||
width, height);
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
|
||||
GL_RENDERBUFFER_EXT, stencil);
|
||||
|
||||
// generate texture save target
|
||||
GLint internalFormat;
|
||||
GLenum format;
|
||||
switch (texture_type)
|
||||
{
|
||||
case Canvas::TYPE_HDR:
|
||||
internalFormat = GL_RGBA16F;
|
||||
format = GL_FLOAT;
|
||||
break;
|
||||
case Canvas::TYPE_NORMAL:
|
||||
default:
|
||||
internalFormat = GL_RGBA8;
|
||||
format = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
||||
glGenTextures(1, &img);
|
||||
bindTexture(img);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height,
|
||||
0, GL_RGBA, format, NULL);
|
||||
bindTexture(0);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
GL_TEXTURE_2D, img, 0);
|
||||
|
||||
// check status
|
||||
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
|
||||
// unbind framebuffer
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (GLuint) current_fbo);
|
||||
return status;
|
||||
}
|
||||
|
||||
bool isSupported()
|
||||
{
|
||||
GLuint fb, stencil, img;
|
||||
GLenum status = createFBO(fb, stencil, img, 2, 2, Canvas::TYPE_NORMAL);
|
||||
deleteFBO(fb, stencil, img);
|
||||
return status == GL_FRAMEBUFFER_COMPLETE;
|
||||
}
|
||||
};
|
||||
|
||||
FramebufferStrategy *strategy = NULL;
|
||||
|
||||
FramebufferStrategy strategyNone;
|
||||
|
||||
FramebufferStrategyGL3 strategyGL3;
|
||||
|
||||
FramebufferStrategyPackedEXT strategyPackedEXT;
|
||||
|
||||
FramebufferStrategyEXT strategyEXT;
|
||||
|
||||
Canvas *Canvas::current = NULL;
|
||||
|
||||
static void loadStrategy()
|
||||
static void getStrategy()
|
||||
{
|
||||
if (!strategy)
|
||||
{
|
||||
if (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object)
|
||||
strategy = &strategyGL3;
|
||||
else if (GLEE_EXT_framebuffer_object && GLEE_EXT_packed_depth_stencil)
|
||||
strategy = &strategyPackedEXT;
|
||||
else if (GLEE_EXT_framebuffer_object && strategyEXT.isSupported())
|
||||
strategy = &strategyEXT;
|
||||
else
|
||||
strategy = &strategyNone;
|
||||
}
|
||||
}
|
||||
|
||||
Canvas::Canvas(int width, int height)
|
||||
Canvas::Canvas(int width, int height, TextureType texture_type)
|
||||
: width(width)
|
||||
, height(height)
|
||||
, texture_type(texture_type)
|
||||
{
|
||||
float w = static_cast<float>(width);
|
||||
float h = static_cast<float>(height);
|
||||
|
||||
// world coordinates
|
||||
vertices[0].x = 0;
|
||||
vertices[0].y = 0;
|
||||
vertices[0].y = h;
|
||||
vertices[1].x = 0;
|
||||
vertices[1].y = h;
|
||||
vertices[1].y = 0;
|
||||
vertices[2].x = w;
|
||||
vertices[2].y = h;
|
||||
vertices[2].y = 0;
|
||||
vertices[3].x = w;
|
||||
vertices[3].y = 0;
|
||||
vertices[3].y = h;
|
||||
|
||||
// texture coordinates
|
||||
vertices[0].s = 0;
|
||||
@@ -215,7 +312,7 @@ Canvas::Canvas(int width, int height)
|
||||
vertices[3].s = 1;
|
||||
vertices[3].t = 1;
|
||||
|
||||
loadStrategy();
|
||||
getStrategy();
|
||||
|
||||
loadVolatile();
|
||||
}
|
||||
@@ -231,10 +328,15 @@ Canvas::~Canvas()
|
||||
|
||||
bool Canvas::isSupported()
|
||||
{
|
||||
loadStrategy();
|
||||
getStrategy();
|
||||
return (strategy != &strategyNone);
|
||||
}
|
||||
|
||||
bool Canvas::isHdrSupported()
|
||||
{
|
||||
return GLEE_VERSION_3_0 || GLEE_ARB_texture_float;
|
||||
}
|
||||
|
||||
void Canvas::bindDefaultCanvas()
|
||||
{
|
||||
if (current != NULL)
|
||||
@@ -262,7 +364,7 @@ void Canvas::startGrab()
|
||||
glLoadIdentity();
|
||||
|
||||
// Set up orthographic view (no depth)
|
||||
glOrtho(0.0, width, height, 0.0, -1.0, 1.0);
|
||||
glOrtho(0.0, width, 0.0, height, -1.0, 1.0);
|
||||
|
||||
// Switch back to modelview matrix
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
@@ -312,12 +414,10 @@ void Canvas::draw(float x, float y, float angle, float sx, float sy, float ox, f
|
||||
void Canvas::drawq(love::graphics::Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
|
||||
{
|
||||
static Matrix t;
|
||||
quad->mirror(false, true);
|
||||
const vertex *v = quad->getVertices();
|
||||
|
||||
t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
|
||||
drawv(t, v);
|
||||
quad->mirror(false, true);
|
||||
}
|
||||
|
||||
love::image::ImageData *Canvas::getImageData(love::image::Image *image)
|
||||
@@ -325,7 +425,6 @@ love::image::ImageData *Canvas::getImageData(love::image::Image *image)
|
||||
int row = 4 * width;
|
||||
int size = row * height;
|
||||
GLubyte *pixels = new GLubyte[size];
|
||||
GLubyte *screenshot = new GLubyte[size];
|
||||
|
||||
strategy->bindFBO(fbo);
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
@@ -334,15 +433,8 @@ love::image::ImageData *Canvas::getImageData(love::image::Image *image)
|
||||
else
|
||||
strategy->bindFBO(0);
|
||||
|
||||
GLubyte *src = pixels - row; // second line of source image
|
||||
GLubyte *dst = screenshot + size; // last row of destination image
|
||||
love::image::ImageData *img = image->newImageData(width, height, (void *)pixels);
|
||||
|
||||
for (int i = 0; i < height; ++i)
|
||||
memcpy(dst -= row, src += row, row);
|
||||
|
||||
love::image::ImageData *img = image->newImageData(width, height, (void *)screenshot);
|
||||
|
||||
delete[] screenshot;
|
||||
delete[] pixels;
|
||||
|
||||
return img;
|
||||
@@ -399,7 +491,7 @@ Image::Wrap Canvas::getWrap() const
|
||||
|
||||
bool Canvas::loadVolatile()
|
||||
{
|
||||
status = strategy->createFBO(fbo, depth_stencil, img, width, height);
|
||||
status = strategy->createFBO(fbo, depth_stencil, img, width, height, texture_type);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE)
|
||||
return false;
|
||||
|
||||
@@ -447,6 +539,23 @@ void Canvas::drawv(const Matrix &t, const vertex *v) const
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
bool Canvas::getConstant(const char *in, Canvas::TextureType &out)
|
||||
{
|
||||
return textureTypes.find(in, out);
|
||||
}
|
||||
|
||||
bool Canvas::getConstant(Canvas::TextureType in, const char *&out)
|
||||
{
|
||||
return textureTypes.find(in, out);
|
||||
}
|
||||
|
||||
StringMap<Canvas::TextureType, Canvas::TYPE_MAX_ENUM>::Entry Canvas::textureTypeEntries[] =
|
||||
{
|
||||
{"normal", Canvas::TYPE_NORMAL},
|
||||
{"hdr", Canvas::TYPE_HDR},
|
||||
};
|
||||
StringMap<Canvas::TextureType, Canvas::TYPE_MAX_ENUM> Canvas::textureTypes(Canvas::textureTypeEntries, sizeof(Canvas::textureTypeEntries));
|
||||
|
||||
} // opengl
|
||||
} // graphics
|
||||
} // love
|
||||
|
||||
@@ -42,19 +42,15 @@ namespace opengl
|
||||
class Canvas : public DrawQable, public Volatile
|
||||
{
|
||||
public:
|
||||
Canvas(int width, int height);
|
||||
enum TextureType {
|
||||
TYPE_NORMAL,
|
||||
TYPE_HDR,
|
||||
TYPE_MAX_ENUM
|
||||
};
|
||||
|
||||
Canvas(int width, int height, TextureType texture_type = TYPE_NORMAL);
|
||||
virtual ~Canvas();
|
||||
|
||||
static bool isSupported();
|
||||
|
||||
unsigned int getStatus() const
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
static Canvas *current;
|
||||
static void bindDefaultCanvas();
|
||||
|
||||
void startGrab();
|
||||
void stopGrab();
|
||||
|
||||
@@ -78,9 +74,27 @@ public:
|
||||
int getWidth();
|
||||
int getHeight();
|
||||
|
||||
unsigned int getStatus() const
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
TextureType getTextureType() const
|
||||
{
|
||||
return texture_type;
|
||||
}
|
||||
|
||||
bool loadVolatile();
|
||||
void unloadVolatile();
|
||||
|
||||
static bool isSupported();
|
||||
static bool isHdrSupported();
|
||||
static bool getConstant(const char *in, TextureType &out);
|
||||
static bool getConstant(TextureType in, const char *&out);
|
||||
|
||||
static Canvas *current;
|
||||
static void bindDefaultCanvas();
|
||||
|
||||
private:
|
||||
friend class PixelEffect;
|
||||
GLuint getTextureName() const
|
||||
@@ -94,6 +108,8 @@ private:
|
||||
GLuint depth_stencil;
|
||||
GLuint img;
|
||||
|
||||
TextureType texture_type;
|
||||
|
||||
vertex vertices[4];
|
||||
|
||||
GLenum status;
|
||||
@@ -101,10 +117,13 @@ private:
|
||||
struct
|
||||
{
|
||||
Image::Filter filter;
|
||||
Image::Wrap wrap;
|
||||
Image::Wrap wrap;
|
||||
} settings;
|
||||
|
||||
void drawv(const Matrix &t, const vertex *v) const;
|
||||
|
||||
static StringMap<TextureType, TYPE_MAX_ENUM>::Entry textureTypeEntries[];
|
||||
static StringMap<TextureType, TYPE_MAX_ENUM> textureTypes;
|
||||
};
|
||||
|
||||
} // opengl
|
||||
|
||||
@@ -400,9 +400,15 @@ ParticleSystem *Graphics::newParticleSystem(Image *image, int size)
|
||||
return new ParticleSystem(image, size);
|
||||
}
|
||||
|
||||
Canvas *Graphics::newCanvas(int width, int height)
|
||||
Canvas *Graphics::newCanvas(int width, int height, Canvas::TextureType texture_type)
|
||||
{
|
||||
Canvas *canvas = new Canvas(width, height);
|
||||
if (texture_type == Canvas::TYPE_HDR && !Canvas::isHdrSupported())
|
||||
throw Exception("HDR Canvases are not supported by your OpenGL implementation");
|
||||
|
||||
while (GL_NO_ERROR != glGetError())
|
||||
/* clear opengl error flag */;
|
||||
|
||||
Canvas *canvas = new Canvas(width, height, texture_type);
|
||||
GLenum err = canvas->getStatus();
|
||||
|
||||
// everything ok, return canvas (early out)
|
||||
@@ -543,7 +549,7 @@ void Graphics::setBlendMode(Graphics::BlendMode mode)
|
||||
if (mode == BLEND_ALPHA)
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
else if (mode == BLEND_MULTIPLICATIVE)
|
||||
glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendFunc(GL_DST_COLOR, GL_ZERO);
|
||||
else if (mode == BLEND_PREMULTIPLIED)
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
else // mode == BLEND_ADDITIVE || mode == BLEND_SUBTRACTIVE
|
||||
@@ -582,7 +588,7 @@ Graphics::BlendMode Graphics::getBlendMode()
|
||||
return BLEND_ADDITIVE;
|
||||
else if (src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) // && equation == GL_FUNC_ADD
|
||||
return BLEND_ALPHA;
|
||||
else if (src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) // && equation == GL_FUNC_ADD
|
||||
else if (src == GL_DST_COLOR && dst == GL_ZERO) // && equation == GL_FUNC_ADD
|
||||
return BLEND_MULTIPLICATIVE;
|
||||
else if (src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) // && equation == GL_FUNC_ADD
|
||||
return BLEND_PREMULTIPLIED;
|
||||
|
||||
@@ -267,7 +267,7 @@ public:
|
||||
|
||||
ParticleSystem *newParticleSystem(Image *image, int size);
|
||||
|
||||
Canvas *newCanvas(int width, int height);
|
||||
Canvas *newCanvas(int width, int height, Canvas::TextureType texture_type = Canvas::TYPE_NORMAL);
|
||||
|
||||
PixelEffect *newPixelEffect(const std::string &code);
|
||||
|
||||
|
||||
@@ -45,10 +45,18 @@ float calculate_variation(float inner, float outer, float var)
|
||||
{
|
||||
float low = inner - (outer/2.0f)*var;
|
||||
float high = inner + (outer/2.0f)*var;
|
||||
float r = (rand() / (float(RAND_MAX)+1));
|
||||
float r = random();
|
||||
return low*(1-r)+high*r;
|
||||
}
|
||||
|
||||
StringMap<ParticleSystem::AreaSpreadDistribution, ParticleSystem::DISTRIBUTION_MAX_ENUM>::Entry ParticleSystem::distributionsEntries[] = {
|
||||
{ "none", ParticleSystem::DISTRIBUTION_NONE },
|
||||
{ "uniform", ParticleSystem::DISTRIBUTION_UNIFORM },
|
||||
{ "normal", ParticleSystem::DISTRIBUTION_NORMAL },
|
||||
};
|
||||
|
||||
StringMap<ParticleSystem::AreaSpreadDistribution, ParticleSystem::DISTRIBUTION_MAX_ENUM> ParticleSystem::distributions(ParticleSystem::distributionsEntries, sizeof(ParticleSystem::distributionsEntries));
|
||||
|
||||
|
||||
ParticleSystem::ParticleSystem(Image *sprite, unsigned int buffer)
|
||||
: pStart(0)
|
||||
@@ -57,6 +65,7 @@ ParticleSystem::ParticleSystem(Image *sprite, unsigned int buffer)
|
||||
, active(true)
|
||||
, emissionRate(0)
|
||||
, emitCounter(0)
|
||||
, areaSpreadDistribution(DISTRIBUTION_NONE)
|
||||
, lifetime(-1)
|
||||
, life(0)
|
||||
, particleLifeMin(0)
|
||||
@@ -108,45 +117,60 @@ void ParticleSystem::add()
|
||||
if (min == max)
|
||||
pLast->life = min;
|
||||
else
|
||||
pLast->life = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;
|
||||
pLast->life = random(min, max);
|
||||
pLast->lifetime = pLast->life;
|
||||
|
||||
pLast->position[0] = position.getX();
|
||||
pLast->position[1] = position.getY();
|
||||
|
||||
switch (areaSpreadDistribution)
|
||||
{
|
||||
case DISTRIBUTION_UNIFORM:
|
||||
pLast->position[0] += random(-areaSpread.getX(), areaSpread.getX());
|
||||
pLast->position[1] += random(-areaSpread.getY(), areaSpread.getY());
|
||||
break;
|
||||
case DISTRIBUTION_NORMAL:
|
||||
pLast->position[0] += random_normal(areaSpread.getX());
|
||||
pLast->position[1] += random_normal(areaSpread.getY());
|
||||
break;
|
||||
case DISTRIBUTION_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
min = direction - spread/2.0f;
|
||||
max = direction + spread/2.0f;
|
||||
pLast->direction = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;
|
||||
pLast->direction = random(min, max);
|
||||
|
||||
pLast->origin = position;
|
||||
|
||||
min = speedMin;
|
||||
max = speedMax;
|
||||
float speed = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;
|
||||
float speed = random(min, max);
|
||||
pLast->speed = love::Vector(cos(pLast->direction), sin(pLast->direction));
|
||||
pLast->speed *= speed;
|
||||
|
||||
min = gravityMin;
|
||||
max = gravityMax;
|
||||
pLast->gravity = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;
|
||||
pLast->gravity = random(min, max);
|
||||
|
||||
min = radialAccelerationMin;
|
||||
max = radialAccelerationMax;
|
||||
pLast->radialAcceleration = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;
|
||||
pLast->radialAcceleration = random(min, max);
|
||||
|
||||
min = tangentialAccelerationMin;
|
||||
max = tangentialAccelerationMax;
|
||||
pLast->tangentialAcceleration = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;
|
||||
pLast->tangentialAcceleration = random(min, max);
|
||||
|
||||
pLast->sizeOffset = (rand() / (float(RAND_MAX)+1)) * sizeVariation; // time offset for size change
|
||||
pLast->sizeIntervalSize = (1.0f - (rand() / (float(RAND_MAX)+1)) * sizeVariation) - pLast->sizeOffset;
|
||||
pLast->sizeOffset = random(sizeVariation); // time offset for size change
|
||||
pLast->sizeIntervalSize = (1.0f - random(sizeVariation)) - pLast->sizeOffset;
|
||||
pLast->size = sizes[(size_t)(pLast->sizeOffset - .5f) * (sizes.size() - 1)];
|
||||
|
||||
min = rotationMin;
|
||||
max = rotationMax;
|
||||
pLast->spinStart = calculate_variation(spinStart, spinEnd, spinVariation);
|
||||
pLast->spinEnd = calculate_variation(spinEnd, spinStart, spinVariation);
|
||||
pLast->rotation = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;;
|
||||
pLast->rotation = random(min, max);
|
||||
|
||||
pLast->color = colors[0];
|
||||
|
||||
@@ -204,6 +228,13 @@ void ParticleSystem::setPosition(float x, float y)
|
||||
position = love::Vector(x, y);
|
||||
}
|
||||
|
||||
|
||||
void ParticleSystem::setAreaSpread(AreaSpreadDistribution distribution, float x, float y)
|
||||
{
|
||||
areaSpread = love::Vector(x, y);
|
||||
areaSpreadDistribution = distribution;
|
||||
}
|
||||
|
||||
void ParticleSystem::setDirection(float direction)
|
||||
{
|
||||
this->direction = direction;
|
||||
@@ -349,6 +380,16 @@ const love::Vector &ParticleSystem::getPosition() const
|
||||
return position;
|
||||
}
|
||||
|
||||
ParticleSystem::AreaSpreadDistribution ParticleSystem::getAreaSpreadDistribution() const
|
||||
{
|
||||
return areaSpreadDistribution;
|
||||
}
|
||||
|
||||
const love::Vector &ParticleSystem::getAreaSpreadParameters() const
|
||||
{
|
||||
return areaSpread;
|
||||
}
|
||||
|
||||
float ParticleSystem::getDirection() const
|
||||
{
|
||||
return direction;
|
||||
@@ -543,6 +584,16 @@ void ParticleSystem::update(float dt)
|
||||
} // while
|
||||
}
|
||||
|
||||
bool ParticleSystem::getConstant(const char *in, AreaSpreadDistribution &out)
|
||||
{
|
||||
return distributions.find(in, out);
|
||||
}
|
||||
|
||||
bool ParticleSystem::getConstant(AreaSpreadDistribution in, const char *&out)
|
||||
{
|
||||
return distributions.find(in, out);
|
||||
}
|
||||
|
||||
} // opengl
|
||||
} // graphics
|
||||
} // love
|
||||
|
||||
@@ -72,6 +72,16 @@ struct particle
|
||||
class ParticleSystem : public Drawable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Type of distribution new particles are drawn from: None, uniform, normal.
|
||||
*/
|
||||
enum AreaSpreadDistribution
|
||||
{
|
||||
DISTRIBUTION_NONE,
|
||||
DISTRIBUTION_UNIFORM,
|
||||
DISTRIBUTION_NORMAL,
|
||||
DISTRIBUTION_MAX_ENUM,
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a particle system with the specified buffersize and sprite.
|
||||
@@ -122,6 +132,19 @@ public:
|
||||
**/
|
||||
void setPosition(float x, float y);
|
||||
|
||||
/**
|
||||
* Sets the emission area spread parameters and distribution type. The interpretation of
|
||||
* the parameters depends on the distribution type:
|
||||
*
|
||||
* * None: Parameters are ignored. No area spread.
|
||||
* * Uniform: Parameters denote maximal (symmetric) displacement from emitter position.
|
||||
* * Normal: Parameters denote the standard deviation in x and y direction. x and y are assumed to be uncorrelated.
|
||||
* @param x First parameter. Interpretation depends on distribution type.
|
||||
* @param y Second parameter. Interpretation depends on distribution type.
|
||||
* @param distribution Distribution type
|
||||
* */
|
||||
void setAreaSpread(AreaSpreadDistribution distribution, float x, float y);
|
||||
|
||||
/**
|
||||
* Sets the direction and the spread of the particle emitter.
|
||||
* @param direction The direction (in degrees).
|
||||
@@ -285,6 +308,16 @@ public:
|
||||
**/
|
||||
const love::Vector &getPosition() const;
|
||||
|
||||
/**
|
||||
* Returns area spread distribution type.
|
||||
*/
|
||||
AreaSpreadDistribution getAreaSpreadDistribution() const;
|
||||
|
||||
/**
|
||||
* Returns area spread parameters.
|
||||
*/
|
||||
const love::Vector &getAreaSpreadParameters() const;
|
||||
|
||||
/**
|
||||
* Returns the direction of the emitter (in degrees).
|
||||
**/
|
||||
@@ -357,6 +390,9 @@ public:
|
||||
* @param dt Time since last update.
|
||||
**/
|
||||
void update(float dt);
|
||||
|
||||
static bool getConstant(const char *in, AreaSpreadDistribution &out);
|
||||
static bool getConstant(AreaSpreadDistribution in, const char *&out);
|
||||
protected:
|
||||
|
||||
// The max amount of particles.
|
||||
@@ -386,6 +422,10 @@ protected:
|
||||
// The relative position of the particle emitter.
|
||||
love::Vector position;
|
||||
|
||||
// Emission area spread.
|
||||
AreaSpreadDistribution areaSpreadDistribution;
|
||||
love::Vector areaSpread;
|
||||
|
||||
// The lifetime of the particle emitter (-1 means infinite) and the life it has left.
|
||||
float lifetime;
|
||||
float life;
|
||||
@@ -439,6 +479,9 @@ protected:
|
||||
|
||||
void add();
|
||||
void remove(particle *p);
|
||||
|
||||
static StringMap<AreaSpreadDistribution, DISTRIBUTION_MAX_ENUM>::Entry distributionsEntries[];
|
||||
static StringMap<AreaSpreadDistribution, DISTRIBUTION_MAX_ENUM> distributions;
|
||||
};
|
||||
|
||||
} // opengl
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "PixelEffect.h"
|
||||
#include "GLee.h"
|
||||
#include "Graphics.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -134,6 +135,7 @@ bool PixelEffect::loadVolatile()
|
||||
}
|
||||
|
||||
glDeleteShader(shader);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -149,24 +151,25 @@ void PixelEffect::unloadVolatile()
|
||||
|
||||
std::string PixelEffect::getGLSLVersion()
|
||||
{
|
||||
// GL_SHADING_LANGUAGE_VERSION is not available in OpenGL < 2.1.
|
||||
// Be very pessimistic about the GLSL version in that case.
|
||||
if (!GLEE_VERSION_2_1)
|
||||
// GL_SHADING_LANGUAGE_VERSION may not be available in OpenGL < 2.0.
|
||||
const char *tmp = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
|
||||
if (NULL == tmp)
|
||||
return "0.0";
|
||||
|
||||
// the version string always begins with a version number of the format
|
||||
// major_number.minor_number
|
||||
// or
|
||||
// major_number.minor_number.release_number
|
||||
std::string versionString((const char *)glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
size_t minorEndPos = versionString.find(" ");
|
||||
// we can keep release_number, since it does not affect the check below.
|
||||
std::string versionString(tmp);
|
||||
size_t minorEndPos = versionString.find(' ');
|
||||
return versionString.substr(0, minorEndPos);
|
||||
}
|
||||
|
||||
|
||||
bool PixelEffect::isSupported()
|
||||
{
|
||||
return GLEE_VERSION_2_0 && GLEE_ARB_shader_objects && GLEE_ARB_fragment_shader && getGLSLVersion() >= "1.2";
|
||||
return GLEE_VERSION_2_0 && getGLSLVersion() >= "1.2";
|
||||
}
|
||||
|
||||
std::string PixelEffect::getWarnings() const
|
||||
|
||||
@@ -113,17 +113,6 @@ void Quad::flip(bool x, bool y)
|
||||
}
|
||||
}
|
||||
|
||||
void Quad::mirror(bool x, bool y)
|
||||
{
|
||||
for (size_t i = 0; i < NUM_VERTICES; ++i)
|
||||
{
|
||||
if (x)
|
||||
vertices[i].s = 1.0f - vertices[i].s;
|
||||
if (y)
|
||||
vertices[i].t = 1.0f - vertices[i].t;
|
||||
}
|
||||
}
|
||||
|
||||
const vertex *Quad::getVertices() const
|
||||
{
|
||||
return vertices;
|
||||
|
||||
@@ -54,7 +54,6 @@ public:
|
||||
Viewport getViewport() const;
|
||||
|
||||
void flip(bool x, bool y);
|
||||
void mirror(bool x, bool y);
|
||||
|
||||
/**
|
||||
* Gets a pointer to the vertices.
|
||||
|
||||
@@ -181,6 +181,16 @@ int w_Canvas_getHeight(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Canvas_getType(lua_State *L)
|
||||
{
|
||||
Canvas *canvas = luax_checkcanvas(L, 1);
|
||||
Canvas::TextureType type = canvas->getTextureType();
|
||||
const char *str;
|
||||
Canvas::getConstant(type, str);
|
||||
lua_pushstring(L, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg functions[] =
|
||||
{
|
||||
{ "renderTo", w_Canvas_renderTo },
|
||||
@@ -192,6 +202,7 @@ static const luaL_Reg functions[] =
|
||||
{ "clear", w_Canvas_clear },
|
||||
{ "getWidth", w_Canvas_getWidth },
|
||||
{ "getHeight", w_Canvas_getHeight },
|
||||
{ "getType", w_Canvas_getType },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ int w_Canvas_getWrap(lua_State *L);
|
||||
int w_Canvas_clear(lua_State *L);
|
||||
int w_Canvas_getWidth(lua_State *L);
|
||||
int w_Canvas_getHeight(lua_State *L);
|
||||
int w_Canvas_getType(lua_State *L);
|
||||
extern "C" int luaopen_canvas(lua_State *L);
|
||||
|
||||
} // opengl
|
||||
|
||||
@@ -361,6 +361,9 @@ int w_newImageFont(lua_State *L)
|
||||
Image::Filter img_filter;
|
||||
bool setFilter = false;
|
||||
|
||||
// For the filter modes..
|
||||
int startIndex = 2;
|
||||
|
||||
// Convert to ImageData if necessary.
|
||||
if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || (luax_istype(L, 1, DATA_T) && !luax_istype(L, 1, IMAGE_IMAGE_DATA_T)))
|
||||
luax_convobj(L, 1, "image", "newImageData");
|
||||
@@ -379,16 +382,17 @@ int w_newImageFont(lua_State *L)
|
||||
{
|
||||
int idxs[] = {1, 2};
|
||||
luax_convobj(L, idxs, 2, "font", "newRasterizer");
|
||||
startIndex = 3; // There's a glyphs args in there, move up
|
||||
}
|
||||
|
||||
love::font::Rasterizer *rasterizer = luax_checktype<love::font::Rasterizer>(L, 1, "Rasterizer", FONT_RASTERIZER_T);
|
||||
|
||||
if (lua_isstring(L, 2) && lua_isstring(L, 3))
|
||||
if (lua_isstring(L, startIndex) && lua_isstring(L, startIndex+1))
|
||||
{
|
||||
Image::FilterMode min;
|
||||
Image::FilterMode mag;
|
||||
const char *minstr = luaL_checkstring(L, 2);
|
||||
const char *magstr = luaL_checkstring(L, 3);
|
||||
const char *minstr = luaL_checkstring(L, startIndex);
|
||||
const char *magstr = luaL_checkstring(L, startIndex+1);
|
||||
if (!Image::getConstant(minstr, min))
|
||||
return luaL_error(L, "Invalid filter mode: %s", minstr);
|
||||
if (!Image::getConstant(magstr, mag))
|
||||
@@ -449,14 +453,18 @@ int w_newParticleSystem(lua_State *L)
|
||||
int w_newCanvas(lua_State *L)
|
||||
{
|
||||
// check if width and height are given. else default to screen dimensions.
|
||||
int width = luaL_optint(L, 1, instance->getWidth());
|
||||
int height = luaL_optint(L, 2, instance->getHeight());
|
||||
glGetError(); // clear opengl error flag
|
||||
int width = luaL_optint(L, 1, instance->getWidth());
|
||||
int height = luaL_optint(L, 2, instance->getHeight());
|
||||
const char *str = luaL_optstring(L, 3, "normal");
|
||||
|
||||
Canvas::TextureType texture_type;
|
||||
if (!Canvas::getConstant(str, texture_type))
|
||||
return luaL_error(L, "Invalid canvas type: %s", str);
|
||||
|
||||
Canvas *canvas = NULL;
|
||||
try
|
||||
{
|
||||
canvas = instance->newCanvas(width, height);
|
||||
canvas = instance->newCanvas(width, height, texture_type);
|
||||
}
|
||||
catch(Exception &e)
|
||||
{
|
||||
@@ -874,6 +882,10 @@ int w_isSupported(lua_State *L)
|
||||
if (!Canvas::isSupported())
|
||||
supported = false;
|
||||
break;
|
||||
case Graphics::SUPPORT_HDR_CANVAS:
|
||||
if (!Canvas::isHdrSupported())
|
||||
supported = false;
|
||||
break;
|
||||
case Graphics::SUPPORT_PIXELEFFECT:
|
||||
if (!PixelEffect::isSupported())
|
||||
supported = false;
|
||||
|
||||
@@ -86,6 +86,24 @@ int w_ParticleSystem_setPosition(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_ParticleSystem_setAreaSpread(lua_State *L)
|
||||
{
|
||||
ParticleSystem *t = luax_checkparticlesystem(L, 1);
|
||||
|
||||
ParticleSystem::AreaSpreadDistribution distribution;
|
||||
const char *str = luaL_checkstring(L, 2);
|
||||
if (!ParticleSystem::getConstant(str, distribution))
|
||||
return luaL_error(L, "Invalid distribution: '%s'", str);
|
||||
|
||||
float x = (float)luaL_checknumber(L, 3);
|
||||
float y = (float)luaL_checknumber(L, 4);
|
||||
if (x < 0.0f || y < 0.0f)
|
||||
return luaL_error(L, "Invalid area spread parameters (must be >= 0)");
|
||||
|
||||
t->setAreaSpread(distribution, x, y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_ParticleSystem_setDirection(lua_State *L)
|
||||
{
|
||||
ParticleSystem *t = luax_checkparticlesystem(L, 1);
|
||||
@@ -273,6 +291,21 @@ int w_ParticleSystem_getPosition(lua_State *L)
|
||||
return 2;
|
||||
}
|
||||
|
||||
int w_ParticleSystem_getAreaSpread(lua_State *L)
|
||||
{
|
||||
ParticleSystem *t = luax_checkparticlesystem(L, 1);
|
||||
ParticleSystem::AreaSpreadDistribution distribution = t-> getAreaSpreadDistribution();
|
||||
const char *str;
|
||||
ParticleSystem::getConstant(distribution, str);
|
||||
const love::Vector &p = t->getAreaSpreadParameters();
|
||||
|
||||
lua_pushstring(L, str);
|
||||
lua_pushnumber(L, p.x);
|
||||
lua_pushnumber(L, p.y);
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
int w_ParticleSystem_getDirection(lua_State *L)
|
||||
{
|
||||
ParticleSystem *t = luax_checkparticlesystem(L, 1);
|
||||
@@ -373,6 +406,7 @@ static const luaL_Reg functions[] =
|
||||
{ "setLifetime", w_ParticleSystem_setLifetime },
|
||||
{ "setParticleLife", w_ParticleSystem_setParticleLife },
|
||||
{ "setPosition", w_ParticleSystem_setPosition },
|
||||
{ "setAreaSpread", w_ParticleSystem_setAreaSpread },
|
||||
{ "setDirection", w_ParticleSystem_setDirection },
|
||||
{ "setSpread", w_ParticleSystem_setSpread },
|
||||
{ "setRelativeDirection", w_ParticleSystem_setRelativeDirection },
|
||||
@@ -390,6 +424,7 @@ static const luaL_Reg functions[] =
|
||||
{ "getX", w_ParticleSystem_getX },
|
||||
{ "getY", w_ParticleSystem_getY },
|
||||
{ "getPosition", w_ParticleSystem_getPosition },
|
||||
{ "getAreaSpread", w_ParticleSystem_getAreaSpread },
|
||||
{ "getDirection", w_ParticleSystem_getDirection },
|
||||
{ "getSpread", w_ParticleSystem_getSpread },
|
||||
{ "getOffsetX", w_ParticleSystem_getOffsetX },
|
||||
|
||||
@@ -143,19 +143,38 @@ int w_SpriteBatch_getImage(lua_State *L)
|
||||
int w_SpriteBatch_setColor(lua_State *L)
|
||||
{
|
||||
SpriteBatch *t = luax_checkspritebatch(L, 1);
|
||||
Color c;
|
||||
|
||||
if (lua_gettop(L) <= 1)
|
||||
{
|
||||
t->setColor();
|
||||
return 0;
|
||||
}
|
||||
else if (lua_istable(L, 2))
|
||||
{
|
||||
lua_rawgeti(L, 2, 1);
|
||||
c.r = (unsigned char) luaL_checkint(L, -1);
|
||||
lua_pop(L, 1);
|
||||
lua_rawgeti(L, 2, 2);
|
||||
c.g = (unsigned char) luaL_checkint(L, -1);
|
||||
lua_pop(L, 1);
|
||||
lua_rawgeti(L, 2, 3);
|
||||
c.b = (unsigned char) luaL_checkint(L, -1);
|
||||
lua_pop(L, 1);
|
||||
lua_rawgeti(L, 2, 4);
|
||||
c.a = (unsigned char) luaL_optint(L, -1, 255);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Color c;
|
||||
c.r = (unsigned char)luaL_checkint(L, 2);
|
||||
c.g = (unsigned char)luaL_checkint(L, 3);
|
||||
c.b = (unsigned char)luaL_checkint(L, 4);
|
||||
c.a = (unsigned char)luaL_optint(L, 5, 255);
|
||||
t->setColor(c);
|
||||
}
|
||||
|
||||
t->setColor(c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,21 @@ Contact::Contact(b2Contact *contact)
|
||||
|
||||
Contact::~Contact()
|
||||
{
|
||||
Memoizer::remove(contact);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void Contact::invalidate()
|
||||
{
|
||||
if (contact != NULL)
|
||||
{
|
||||
Memoizer::remove(contact);
|
||||
contact = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool Contact::isValid()
|
||||
{
|
||||
return contact != NULL ? true : false;
|
||||
}
|
||||
|
||||
int Contact::getPositions(lua_State *L)
|
||||
|
||||
@@ -59,6 +59,18 @@ public:
|
||||
|
||||
virtual ~Contact();
|
||||
|
||||
/**
|
||||
* Removes the b2Contact pointer from Memoizer and sets it
|
||||
* to null on the Contact.
|
||||
**/
|
||||
void invalidate();
|
||||
|
||||
/**
|
||||
* Returns if the Contact still points to a valid b2Contact.
|
||||
* @return True if the contact is still valid or false if it has been destroyed.
|
||||
**/
|
||||
bool isValid();
|
||||
|
||||
/**
|
||||
* Gets the position of each point of contact.
|
||||
* @return The position along the x-axis.
|
||||
|
||||
@@ -77,9 +77,13 @@ void World::ContactCallback::process(b2Contact *contact, const b2ContactImpulse
|
||||
throw love::Exception("A fixture has escaped Memoizer!");
|
||||
}
|
||||
|
||||
Contact *c = new Contact(contact);
|
||||
Contact *cobj = (Contact *)Memoizer::find(contact);
|
||||
if (!cobj)
|
||||
cobj = new Contact(contact);
|
||||
else
|
||||
cobj->retain();
|
||||
|
||||
luax_newtype(L, "Contact", (PHYSICS_CONTACT_T), (void *)c);
|
||||
luax_newtype(L, "Contact", (PHYSICS_CONTACT_T), (void *)cobj);
|
||||
|
||||
int args = 3;
|
||||
if (impulse)
|
||||
@@ -117,12 +121,12 @@ bool World::ContactFilter::process(Fixture *a, Fixture *b)
|
||||
a->getFilterData(filterA);
|
||||
b->getFilterData(filterB);
|
||||
|
||||
if (filterA[2] != 0 && // 0 is the default group, so this does not count
|
||||
filterA[2] == filterB[2]) // if they are in the same group
|
||||
if (filterA[2] != 0 && // 0 is the default group, so this does not count
|
||||
filterA[2] == filterB[2]) // if they are in the same group
|
||||
return filterA[2] > 0; // Negative indexes mean you don't collide
|
||||
|
||||
if ((filterA[1] & filterB[0]) == 0 ||
|
||||
(filterB[1] & filterA[0]) == 0)
|
||||
(filterB[1] & filterA[0]) == 0)
|
||||
return false; // A and B aren't set to collide
|
||||
|
||||
if (ref != 0)
|
||||
@@ -290,6 +294,11 @@ void World::BeginContact(b2Contact *contact)
|
||||
void World::EndContact(b2Contact *contact)
|
||||
{
|
||||
end.process(contact);
|
||||
|
||||
// Letting the Contact know that the b2Contact will be destroyed any second.
|
||||
Contact *c = (Contact *)Memoizer::find(contact);
|
||||
if (c != NULL)
|
||||
c->invalidate();
|
||||
}
|
||||
|
||||
void World::PreSolve(b2Contact *contact, const b2Manifold *oldManifold)
|
||||
@@ -332,19 +341,19 @@ int World::setCallbacks(lua_State *L)
|
||||
case 4:
|
||||
if (postsolve.ref)
|
||||
delete postsolve.ref;
|
||||
postsolve.ref = luax_refif (L, LUA_TFUNCTION);
|
||||
postsolve.ref = luax_refif(L, LUA_TFUNCTION);
|
||||
case 3:
|
||||
if (presolve.ref)
|
||||
delete presolve.ref;
|
||||
presolve.ref = luax_refif (L, LUA_TFUNCTION);
|
||||
presolve.ref = luax_refif(L, LUA_TFUNCTION);
|
||||
case 2:
|
||||
if (end.ref)
|
||||
delete end.ref;
|
||||
end.ref = luax_refif (L, LUA_TFUNCTION);
|
||||
end.ref = luax_refif(L, LUA_TFUNCTION);
|
||||
case 1:
|
||||
if (begin.ref)
|
||||
delete begin.ref;
|
||||
begin.ref = luax_refif (L, LUA_TFUNCTION);
|
||||
begin.ref = luax_refif(L, LUA_TFUNCTION);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -364,7 +373,7 @@ int World::setContactFilter(lua_State *L)
|
||||
luax_assert_argc(L, 1);
|
||||
if (filter.ref)
|
||||
delete filter.ref;
|
||||
filter.ref = luax_refif (L, LUA_TFUNCTION);
|
||||
filter.ref = luax_refif(L, LUA_TFUNCTION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -468,8 +477,10 @@ int World::getContactList(lua_State *L) const
|
||||
{
|
||||
if (!c) break;
|
||||
Contact *contact = (Contact *)Memoizer::find(c);
|
||||
if (!contact) throw love::Exception("A contact has escaped Memoizer!");
|
||||
contact->retain();
|
||||
if (!contact)
|
||||
contact = new Contact(c);
|
||||
else
|
||||
contact->retain();
|
||||
luax_newtype(L, "Contact", PHYSICS_CONTACT_T, (void *)contact);
|
||||
lua_rawseti(L, -2, i);
|
||||
i++;
|
||||
@@ -494,7 +505,7 @@ int World::queryBoundingBox(lua_State *L)
|
||||
box.lowerBound = Physics::scaleDown(b2Vec2(lx, ly));
|
||||
box.upperBound = Physics::scaleDown(b2Vec2(ux, uy));
|
||||
if (query.ref) delete query.ref;
|
||||
query.ref = luax_refif (L, LUA_TFUNCTION);
|
||||
query.ref = luax_refif(L, LUA_TFUNCTION);
|
||||
world->QueryAABB(&query, box);
|
||||
return 0;
|
||||
}
|
||||
@@ -510,7 +521,7 @@ int World::rayCast(lua_State *L)
|
||||
b2Vec2 v2 = Physics::scaleDown(b2Vec2(x2, y2));
|
||||
if (raycast.ref)
|
||||
delete raycast.ref;
|
||||
raycast.ref = luax_refif (L, LUA_TFUNCTION);
|
||||
raycast.ref = luax_refif(L, LUA_TFUNCTION);
|
||||
world->RayCast(&raycast, v1, v2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,10 @@ namespace box2d
|
||||
|
||||
Contact *luax_checkcontact(lua_State *L, int idx)
|
||||
{
|
||||
return luax_checktype<Contact>(L, idx, "Contact", PHYSICS_CONTACT_T);
|
||||
Contact *c = luax_checktype<Contact>(L, idx, "Contact", PHYSICS_CONTACT_T);
|
||||
if (!c->isValid())
|
||||
luaL_error(L, "Attempt to use destroyed contact.");
|
||||
return c;
|
||||
}
|
||||
|
||||
int w_Contact_getPositions(lua_State *L)
|
||||
|
||||
@@ -39,7 +39,7 @@ int w_World_update(lua_State *L)
|
||||
{
|
||||
World *t = luax_checkworld(L, 1);
|
||||
float dt = (float)luaL_checknumber(L, 2);
|
||||
t->update(dt);
|
||||
ASSERT_GUARD(t->update(dt);)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -74,11 +74,11 @@ public:
|
||||
* @param sampleRate Samples per second, or quality of the audio. 44100 is a good value.
|
||||
* @return A Decoder object on success, or zero if no decoder could be found.
|
||||
**/
|
||||
virtual Decoder *newDecoder(filesystem::File *file, int bufferSize) = 0;
|
||||
virtual Decoder *newDecoder(filesystem::FileData *file, int bufferSize) = 0;
|
||||
|
||||
}; // Sound
|
||||
|
||||
} // sound
|
||||
} // love
|
||||
|
||||
#endif // LOVE_SOUND_SOUND_H
|
||||
#endif // LOVE_SOUND_SOUND_H
|
||||
|
||||
@@ -46,11 +46,19 @@ GmeDecoder::GmeDecoder(Data *data, const std::string &ext, int bufferSize)
|
||||
|
||||
num_tracks = gme_track_count(emu);
|
||||
|
||||
if (num_tracks <= 0)
|
||||
throw love::Exception("Game music file has no tracks");
|
||||
try
|
||||
{
|
||||
if (num_tracks <= 0)
|
||||
throw love::Exception("Game music file has no tracks");
|
||||
|
||||
if (gme_start_track(emu, cur_track) != 0)
|
||||
throw love::Exception("Could not start game music playback");
|
||||
if (gme_start_track(emu, cur_track) != 0)
|
||||
throw love::Exception("Could not start game music playback");
|
||||
}
|
||||
catch (love::Exception &)
|
||||
{
|
||||
gme_delete(emu);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
GmeDecoder::~GmeDecoder()
|
||||
|
||||
@@ -27,7 +27,11 @@
|
||||
#include "common/Data.h"
|
||||
#include "Decoder.h"
|
||||
|
||||
#ifdef LOVE_MACOSX
|
||||
#include <Game_Music_Emu/gme.h>
|
||||
#else
|
||||
#include <gme.h>
|
||||
#endif
|
||||
|
||||
namespace love
|
||||
{
|
||||
|
||||
@@ -51,10 +51,9 @@ const char *Sound::getName() const
|
||||
return "love.sound.lullaby";
|
||||
}
|
||||
|
||||
sound::Decoder *Sound::newDecoder(love::filesystem::File *file, int bufferSize)
|
||||
sound::Decoder *Sound::newDecoder(love::filesystem::FileData *data, int bufferSize)
|
||||
{
|
||||
Data *data = file->read();
|
||||
std::string ext = file->getExtension();
|
||||
std::string ext = data->getExtension();
|
||||
|
||||
sound::Decoder *decoder = 0;
|
||||
|
||||
@@ -76,8 +75,6 @@ sound::Decoder *Sound::newDecoder(love::filesystem::File *file, int bufferSize)
|
||||
|
||||
// else if (OtherDecoder::accept(ext))
|
||||
|
||||
data->release();
|
||||
|
||||
return decoder;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
const char *getName() const;
|
||||
|
||||
/// @copydoc love::sound::Sound::newDecoder
|
||||
sound::Decoder *newDecoder(love::filesystem::File *file, int bufferSize);
|
||||
sound::Decoder *newDecoder(love::filesystem::FileData *file, int bufferSize);
|
||||
|
||||
}; // Sound
|
||||
|
||||
@@ -67,4 +67,4 @@ public:
|
||||
} // sound
|
||||
} // love
|
||||
|
||||
#endif // LOVE_SOUND_LULLABY_SOUND_H
|
||||
#endif // LOVE_SOUND_LULLABY_SOUND_H
|
||||
|
||||
@@ -83,18 +83,31 @@ int w_newDecoder(lua_State *L)
|
||||
if (lua_isstring(L, 1))
|
||||
luax_convobj(L, 1, "filesystem", "newFile");
|
||||
|
||||
love::filesystem::File *file = luax_checktype<love::filesystem::File>(L, 1, "File", FILESYSTEM_FILE_T);
|
||||
love::filesystem::FileData *data;
|
||||
if (luax_istype(L, 1, FILESYSTEM_FILE_T))
|
||||
{
|
||||
love::filesystem::File *file = luax_checktype<love::filesystem::File>(L, 1, "File", FILESYSTEM_FILE_T);
|
||||
data = file->read();
|
||||
}
|
||||
else
|
||||
{
|
||||
data = luax_checktype<love::filesystem::FileData>(L, 1, "FileData", FILESYSTEM_FILE_DATA_T);
|
||||
data->retain();
|
||||
}
|
||||
|
||||
int bufferSize = luaL_optint(L, 2, Decoder::DEFAULT_BUFFER_SIZE);
|
||||
|
||||
try
|
||||
{
|
||||
Decoder *t = instance->newDecoder(file, bufferSize);
|
||||
Decoder *t = instance->newDecoder(data, bufferSize);
|
||||
data->release();
|
||||
if (t == 0)
|
||||
return luaL_error(L, "Extension \"%s\" not supported.", file->getExtension().c_str());
|
||||
return luaL_error(L, "Extension \"%s\" not supported.", data->getExtension().c_str());
|
||||
luax_newtype(L, "Decoder", SOUND_DECODER_T, (void *)t);
|
||||
}
|
||||
catch(love::Exception &e)
|
||||
{
|
||||
data->release();
|
||||
return luaL_error(L, e.what());
|
||||
}
|
||||
|
||||
|
||||
@@ -430,8 +430,8 @@ function love.run()
|
||||
if love.draw then love.draw() end
|
||||
end
|
||||
|
||||
if love.timer then love.timer.sleep(0.001) end
|
||||
if love.graphics then love.graphics.present() end
|
||||
if love.timer then love.timer.sleep(0.001) end
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -737,12 +737,12 @@ const unsigned char boot_lua[] =
|
||||
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x20, 0x74, 0x68,
|
||||
0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x28, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x20, 0x74, 0x68,
|
||||
0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x73, 0x6c, 0x65, 0x65,
|
||||
0x70, 0x28, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73,
|
||||
0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
|
||||
0x73, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x20, 0x74, 0x68,
|
||||
0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x73, 0x6c, 0x65, 0x65,
|
||||
0x70, 0x28, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x65, 0x6e, 0x64, 0x0a,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
|
||||
+15
-18
@@ -1284,24 +1284,20 @@ do
|
||||
end
|
||||
|
||||
-- PIXEL EFFECTS
|
||||
local GLSL_HEADER_LINE_COUNT = 6
|
||||
local GLSL_HEADER = [[#version 120
|
||||
#define number float
|
||||
#define Image sampler2D
|
||||
#define extern uniform
|
||||
#define Texel texture2D
|
||||
uniform sampler2D _tex0_;]]
|
||||
local GLSL_FOOTER = [[void main() {
|
||||
// fix weird crashing issue in OSX when _tex0_ is unused within effect()
|
||||
float dummy = texture2D(_tex0_, vec2(.5)).r;
|
||||
gl_FragColor = effect(gl_Color, _tex0_, gl_TexCoord[0].xy, gl_FragCoord.xy);
|
||||
}]]
|
||||
function love.graphics._effectCodeToGLSL(code)
|
||||
local header = [[#version 120
|
||||
#define number float
|
||||
#define Image sampler2D
|
||||
#define extern uniform
|
||||
#define Texel texture2D
|
||||
uniform sampler2D _tex0_;]]
|
||||
local footer = [[void main() {
|
||||
// fix weird crashing issue in OSX when _tex0_ is unused within effect()
|
||||
float dummy = texture2D(_tex0_, vec2(.5)).r;
|
||||
gl_FragColor = effect(gl_Color, _tex0_, gl_TexCoord[0].xy, gl_FragCoord.xy);
|
||||
}]]
|
||||
|
||||
local function include(quoted_path) return (love.filesystem.read(quoted_path:sub(2,-2))) end
|
||||
code = code:gsub("#include (%b'')", include)
|
||||
code = code:gsub('#include (%b"")', include)
|
||||
|
||||
return table.concat{header, "\n", code, footer}
|
||||
return table.concat{GLSL_HEADER, "\n", code, GLSL_FOOTER}
|
||||
end
|
||||
|
||||
function love.graphics._transformGLSLErrorMessages(message)
|
||||
@@ -1317,7 +1313,8 @@ do
|
||||
linenumber, what, message = l:match("^%w+: 0:(%d+):%s*(%w+)%([^%)]+%)%s*(.+)$")
|
||||
end
|
||||
if linenumber and what and message then
|
||||
lines[#lines+1] = ("Line %d: %s: %s"):format(linenumber - 5, what, message)
|
||||
linenumber = linenumber - GLSL_HEADER_LINE_COUNT
|
||||
lines[#lines+1] = ("Line %d: %s: %s"):format(linenumber, what, message)
|
||||
end
|
||||
end
|
||||
-- did not match any known error messages
|
||||
|
||||
+38
-44
@@ -6260,52 +6260,43 @@ const unsigned char graphics_lua[] =
|
||||
0x69, 0x6e, 0x74, 0x66, 0x28, 0x2e, 0x2e, 0x2e, 0x29, 0x0a,
|
||||
0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x2d, 0x2d, 0x20, 0x50, 0x49, 0x58, 0x45, 0x4c, 0x20, 0x45, 0x46, 0x46, 0x45, 0x43, 0x54, 0x53, 0x0a,
|
||||
0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52,
|
||||
0x5f, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x20, 0x3d, 0x20, 0x36, 0x0a,
|
||||
0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52,
|
||||
0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x23, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x32, 0x30, 0x0a,
|
||||
0x09, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, 0x6c,
|
||||
0x6f, 0x61, 0x74, 0x0a,
|
||||
0x09, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x73, 0x61, 0x6d,
|
||||
0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x0a,
|
||||
0x09, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x75, 0x6e,
|
||||
0x69, 0x66, 0x6f, 0x72, 0x6d, 0x0a,
|
||||
0x09, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x54, 0x65, 0x78, 0x65, 0x6c, 0x20, 0x74, 0x65, 0x78,
|
||||
0x74, 0x75, 0x72, 0x65, 0x32, 0x44, 0x0a,
|
||||
0x09, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44,
|
||||
0x20, 0x5f, 0x74, 0x65, 0x78, 0x30, 0x5f, 0x3b, 0x5d, 0x5d, 0x0a,
|
||||
0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x46, 0x4f, 0x4f, 0x54, 0x45, 0x52,
|
||||
0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x20, 0x7b, 0x0a,
|
||||
0x09, 0x09, 0x2f, 0x2f, 0x20, 0x66, 0x69, 0x78, 0x20, 0x77, 0x65, 0x69, 0x72, 0x64, 0x20, 0x63, 0x72, 0x61,
|
||||
0x73, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x73, 0x73, 0x75, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x4f, 0x53, 0x58,
|
||||
0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x5f, 0x74, 0x65, 0x78, 0x30, 0x5f, 0x20, 0x69, 0x73, 0x20, 0x75, 0x6e,
|
||||
0x75, 0x73, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74,
|
||||
0x28, 0x29, 0x0a,
|
||||
0x09, 0x09, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x20, 0x3d, 0x20, 0x74, 0x65,
|
||||
0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x44, 0x28, 0x5f, 0x74, 0x65, 0x78, 0x30, 0x5f, 0x2c, 0x20, 0x76, 0x65,
|
||||
0x63, 0x32, 0x28, 0x2e, 0x35, 0x29, 0x29, 0x2e, 0x72, 0x3b, 0x0a,
|
||||
0x09, 0x09, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x65,
|
||||
0x66, 0x66, 0x65, 0x63, 0x74, 0x28, 0x67, 0x6c, 0x5f, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x5f, 0x74,
|
||||
0x65, 0x78, 0x30, 0x5f, 0x2c, 0x20, 0x67, 0x6c, 0x5f, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x5b,
|
||||
0x30, 0x5d, 0x2e, 0x78, 0x79, 0x2c, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6f, 0x72,
|
||||
0x64, 0x2e, 0x78, 0x79, 0x29, 0x3b, 0x0a,
|
||||
0x09, 0x7d, 0x5d, 0x5d, 0x0a,
|
||||
0x09, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61,
|
||||
0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x5f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x54,
|
||||
0x6f, 0x47, 0x4c, 0x53, 0x4c, 0x28, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,
|
||||
0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x5b,
|
||||
0x5b, 0x23, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x32, 0x30, 0x0a,
|
||||
0x09, 0x09, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66,
|
||||
0x6c, 0x6f, 0x61, 0x74, 0x0a,
|
||||
0x09, 0x09, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x73, 0x61,
|
||||
0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x0a,
|
||||
0x09, 0x09, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x75,
|
||||
0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x0a,
|
||||
0x09, 0x09, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x54, 0x65, 0x78, 0x65, 0x6c, 0x20, 0x74, 0x65,
|
||||
0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x44, 0x0a,
|
||||
0x09, 0x09, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32,
|
||||
0x44, 0x20, 0x5f, 0x74, 0x65, 0x78, 0x30, 0x5f, 0x3b, 0x5d, 0x5d, 0x0a,
|
||||
0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x5b,
|
||||
0x5b, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x20, 0x7b, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x2f, 0x2f, 0x20, 0x66, 0x69, 0x78, 0x20, 0x77, 0x65, 0x69, 0x72, 0x64, 0x20, 0x63, 0x72,
|
||||
0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x73, 0x73, 0x75, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x4f, 0x53,
|
||||
0x58, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x5f, 0x74, 0x65, 0x78, 0x30, 0x5f, 0x20, 0x69, 0x73, 0x20, 0x75,
|
||||
0x6e, 0x75, 0x73, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63,
|
||||
0x74, 0x28, 0x29, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x20, 0x3d, 0x20, 0x74,
|
||||
0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x44, 0x28, 0x5f, 0x74, 0x65, 0x78, 0x30, 0x5f, 0x2c, 0x20, 0x76,
|
||||
0x65, 0x63, 0x32, 0x28, 0x2e, 0x35, 0x29, 0x29, 0x2e, 0x72, 0x3b, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20,
|
||||
0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x28, 0x67, 0x6c, 0x5f, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x5f,
|
||||
0x74, 0x65, 0x78, 0x30, 0x5f, 0x2c, 0x20, 0x67, 0x6c, 0x5f, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64,
|
||||
0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x79, 0x2c, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6f,
|
||||
0x72, 0x64, 0x2e, 0x78, 0x79, 0x29, 0x3b, 0x0a,
|
||||
0x09, 0x09, 0x7d, 0x5d, 0x5d, 0x0a,
|
||||
0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69,
|
||||
0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x28, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68,
|
||||
0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c,
|
||||
0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x72, 0x65, 0x61, 0x64, 0x28, 0x71, 0x75, 0x6f, 0x74, 0x65,
|
||||
0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x3a, 0x73, 0x75, 0x62, 0x28, 0x32, 0x2c, 0x2d, 0x32, 0x29, 0x29, 0x29,
|
||||
0x20, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x09, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x3a, 0x67, 0x73, 0x75, 0x62,
|
||||
0x28, 0x22, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x28, 0x25, 0x62, 0x27, 0x27, 0x29, 0x22,
|
||||
0x2c, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x29, 0x0a,
|
||||
0x09, 0x09, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x3a, 0x67, 0x73, 0x75, 0x62,
|
||||
0x28, 0x27, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x28, 0x25, 0x62, 0x22, 0x22, 0x29, 0x27,
|
||||
0x2c, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x29, 0x0a,
|
||||
0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6e,
|
||||
0x63, 0x61, 0x74, 0x7b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2c, 0x20, 0x22, 0x5c, 0x6e, 0x22, 0x2c, 0x20,
|
||||
0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x7d, 0x0a,
|
||||
0x63, 0x61, 0x74, 0x7b, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x2c, 0x20, 0x22,
|
||||
0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x46, 0x4f,
|
||||
0x4f, 0x54, 0x45, 0x52, 0x7d, 0x0a,
|
||||
0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61,
|
||||
0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x47, 0x4c,
|
||||
@@ -6350,11 +6341,14 @@ const unsigned char graphics_lua[] =
|
||||
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x61,
|
||||
0x6e, 0x64, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||
0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x09, 0x6c, 0x69, 0x6e, 0x65, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x6c,
|
||||
0x69, 0x6e, 0x65, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x2d, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x48,
|
||||
0x45, 0x41, 0x44, 0x45, 0x52, 0x5f, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x09, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x5b, 0x23, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x2b, 0x31,
|
||||
0x5d, 0x20, 0x3d, 0x20, 0x28, 0x22, 0x4c, 0x69, 0x6e, 0x65, 0x20, 0x25, 0x64, 0x3a, 0x20, 0x25, 0x73, 0x3a,
|
||||
0x20, 0x25, 0x73, 0x22, 0x29, 0x3a, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x28, 0x6c, 0x69, 0x6e, 0x65, 0x6e,
|
||||
0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x2d, 0x20, 0x35, 0x2c, 0x20, 0x77, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x6d,
|
||||
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x29, 0x0a,
|
||||
0x75, 0x6d, 0x62, 0x65, 0x72, 0x2c, 0x20, 0x77, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61,
|
||||
0x67, 0x65, 0x29, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x09, 0x2d, 0x2d, 0x20, 0x64, 0x69, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68,
|
||||
|
||||
Reference in New Issue
Block a user