Merge in minor branch, now minor is our next development target

This commit is contained in:
Bart van Strien
2011-05-07 14:12:41 +02:00
70 changed files with 3883 additions and 3571 deletions
+18
View File
@@ -42,6 +42,16 @@ namespace audio
{
return types.find(in, out);
}
bool Source::getConstant(const char * in, Unit & out)
{
return units.find(in, out);
}
bool Source::getConstant(Unit in, const char *& out)
{
return units.find(in, out);
}
StringMap<Source::Type, Source::TYPE_MAX_ENUM>::Entry Source::typeEntries[] =
{
@@ -50,6 +60,14 @@ namespace audio
};
StringMap<Source::Type, Source::TYPE_MAX_ENUM> Source::types(Source::typeEntries, sizeof(Source::typeEntries));
StringMap<Source::Unit, Source::UNIT_MAX_ENUM>::Entry Source::unitEntries[] =
{
{"seconds", Source::UNIT_SECONDS},
{"samples", Source::UNIT_SAMPLES},
};
StringMap<Source::Unit, Source::UNIT_MAX_ENUM> Source::units(Source::unitEntries, sizeof(Source::unitEntries));
} // audio
} // love
+14
View File
@@ -39,6 +39,13 @@ namespace audio
TYPE_STREAM,
TYPE_MAX_ENUM
}; // Type
enum Unit
{
UNIT_SECONDS = 1,
UNIT_SAMPLES,
UNIT_MAX_ENUM
};
protected:
Type type;
@@ -64,6 +71,9 @@ namespace audio
virtual void setVolume(float volume) = 0;
virtual float getVolume() const = 0;
virtual void seek(float offset, Unit unit) = 0;
virtual float tell(Unit unit) const = 0;
// all float * v must be of size 3
virtual void setPosition(float * v) = 0;
@@ -79,11 +89,15 @@ namespace audio
static bool getConstant(const char * in, Type & out);
static bool getConstant(Type in, const char *& out);
static bool getConstant(const char * in, Unit & out);
static bool getConstant(Unit in, const char *& out);
private:
static StringMap<Type, TYPE_MAX_ENUM>::Entry typeEntries[];
static StringMap<Type, TYPE_MAX_ENUM> types;
static StringMap<Unit, UNIT_MAX_ENUM>::Entry unitEntries[];
static StringMap<Unit, UNIT_MAX_ENUM> units;
}; // Source
+9
View File
@@ -100,6 +100,15 @@ namespace null
{
return volume;
}
void Source::seek(float, Source::Unit)
{
}
float Source::tell(Source::Unit) const
{
return 0.0f;
}
void Source::setPosition(float *)
{
+2
View File
@@ -57,6 +57,8 @@ namespace null
virtual float getPitch() const;
virtual void setVolume(float volume);
virtual float getVolume() const;
virtual void seek(float offset, Unit unit);
virtual float tell(Unit unit) const;
virtual void setPosition(float * v);
virtual void getPosition(float * v) const;
virtual void setVelocity(float * v);
+83 -5
View File
@@ -34,7 +34,7 @@ namespace openal
Source::Source(Pool * pool, love::sound::SoundData * soundData)
: love::audio::Source(Source::TYPE_STATIC), pool(pool), valid(false),
pitch(1.0f), volume(1.0f), looping(false), decoder(0)
pitch(1.0f), volume(1.0f), looping(false), offsetSamples(0), offsetSeconds(0), decoder(0)
{
alGenBuffers(1, buffers);
ALenum fmt = getFormat(soundData->getChannels(), soundData->getBits());
@@ -49,7 +49,7 @@ namespace openal
Source::Source(Pool * pool, love::sound::Decoder * decoder)
: love::audio::Source(Source::TYPE_STREAM), pool(pool), valid(false),
pitch(1.0f), volume(1.0f), looping(false), decoder(decoder)
pitch(1.0f), volume(1.0f), looping(false), offsetSamples(0), offsetSeconds(0), decoder(decoder)
{
decoder->retain();
alGenBuffers(MAX_BUFFERS, buffers);
@@ -147,10 +147,28 @@ namespace openal
while(processed--)
{
ALuint buffer;
float curOffsetSamples, curOffsetSecs;
alGetSourcef(source, AL_SAMPLE_OFFSET, &curOffsetSamples);
ALint b;
alGetSourcei(source, AL_BUFFER, &b);
int freq;
alGetBufferi(b, AL_FREQUENCY, &freq);
curOffsetSecs = curOffsetSamples / freq;
// Get a free buffer.
alSourceUnqueueBuffers(source, 1, &buffer);
float newOffsetSamples, newOffsetSecs;
alGetSourcef(source, AL_SAMPLE_OFFSET, &newOffsetSamples);
newOffsetSecs = newOffsetSamples / freq;
offsetSamples += (curOffsetSamples - newOffsetSamples);
offsetSeconds += (curOffsetSecs - newOffsetSecs);
if(streamAtomic(buffer, decoder) > 0)
alSourceQueueBuffers(source, 1, &buffer);
}
@@ -200,6 +218,61 @@ namespace openal
// In case the Source isn't playing.
return volume;
}
void Source::seek(float offset, Source::Unit unit)
{
if (valid)
{
switch (unit) {
case Source::UNIT_SAMPLES:
if (type == TYPE_STREAM) {
ALint buffer;
alGetSourcei(source, AL_BUFFER, &buffer);
int freq;
alGetBufferi(buffer, AL_FREQUENCY, &freq);
offset /= freq;
decoder->seek(offset);
} else {
alSourcef(source, AL_SAMPLE_OFFSET, offset);
}
break;
case Source::UNIT_SECONDS:
default:
if (type == TYPE_STREAM) {
decoder->seek(offset);
} else {
alSourcef(source, AL_SEC_OFFSET, offset);
}
break;
}
}
}
float Source::tell(Source::Unit unit) const
{
if (valid)
{
float offset;
switch (unit) {
case Source::UNIT_SAMPLES:
alGetSourcef(source, AL_SAMPLE_OFFSET, &offset);
if (type == TYPE_STREAM) offset += offsetSamples;
break;
case Source::UNIT_SECONDS:
default:
alGetSourcef(source, AL_SAMPLE_OFFSET, &offset);
ALint buffer;
alGetSourcei(source, AL_BUFFER, &buffer);
int freq;
alGetBufferi(buffer, AL_FREQUENCY, &freq);
offset /= freq;
if (type == TYPE_STREAM) offset += offsetSeconds;
break;
}
return offset;
}
return 0.0f;
}
void Source::setPosition(float * v)
{
@@ -348,6 +421,8 @@ namespace openal
else if(valid && type == TYPE_STREAM)
{
decoder->rewind();
offsetSamples = 0;
offsetSeconds = 0;
}
}
@@ -391,8 +466,11 @@ namespace openal
if(decoded > 0 && fmt != 0)
alBufferData(buffer, fmt, d->getBuffer(), decoded, d->getSampleRate());
if(decoded < d->getSize() && isLooping())
if(decoded < d->getSize() && isLooping()) {
offsetSamples = 0;
offsetSeconds = 0;
d->rewind();
}
return decoded;
}
+5
View File
@@ -62,6 +62,9 @@ namespace openal
float velocity[3];
float direction[3];
bool looping;
float offsetSamples;
float offsetSeconds;
love::sound::Decoder * decoder;
@@ -84,6 +87,8 @@ namespace openal
virtual float getPitch() const;
virtual void setVolume(float volume);
virtual float getVolume() const;
virtual void seek(float offset, Unit unit);
virtual float tell(Unit unit) const;
virtual void setPosition(float * v);
virtual void getPosition(float * v) const;
virtual void setVelocity(float * v);
+23
View File
@@ -93,6 +93,27 @@ namespace audio
lua_pushnumber(L, t->getVolume());
return 1;
}
int w_Source_seek(lua_State * L)
{
Source * t = luax_checksource(L, 1);
float offset = (float)luaL_checknumber(L, 2);
const char * unit = luaL_optstring(L, 3, "seconds");
Source::Unit u;
t->getConstant(unit, u);
t->seek(offset, u);
return 0;
}
int w_Source_tell(lua_State * L)
{
Source * t = luax_checksource(L, 1);
const char * unit = luaL_optstring(L, 2, "seconds");
Source::Unit u;
t->getConstant(unit, u);
lua_pushnumber(L, t->tell(u));
return 1;
}
int w_Source_setPosition(lua_State * L)
{
@@ -206,6 +227,8 @@ namespace audio
{ "getPitch", w_Source_getPitch },
{ "setVolume", w_Source_setVolume },
{ "getVolume", w_Source_getVolume },
{ "seek", w_Source_seek },
{ "tell", w_Source_tell },
{ "setPosition", w_Source_setPosition },
{ "getPosition", w_Source_getPosition },
{ "setVelocity", w_Source_setVelocity },
+2
View File
@@ -38,6 +38,8 @@ namespace audio
int w_Source_getPitch(lua_State * L);
int w_Source_setVolume(lua_State * L);
int w_Source_getVolume(lua_State * L);
int w_Source_seek(lua_State * L);
int w_Source_tell(lua_State * L);
int w_Source_setPosition(lua_State * L);
int w_Source_getPosition(lua_State * L);
int w_Source_setVelocity(lua_State * L);
-2
View File
@@ -22,7 +22,6 @@
#define LOVE_FONT_FONT_H
// LOVE
#include "FontData.h"
#include "Rasterizer.h"
#include <image/ImageData.h>
#include <common/Module.h>
@@ -44,7 +43,6 @@ namespace font
virtual Rasterizer * newRasterizer(love::image::ImageData * data, std::string glyphs) = 0;
virtual Rasterizer * newRasterizer(love::image::ImageData * data, unsigned short * glyphs, int length) = 0;
virtual GlyphData * newGlyphData(Rasterizer * r, unsigned short glyph) = 0;
virtual FontData * newFontData(Rasterizer * r) = 0;
// Implement Module
virtual const char * getName() const = 0;
-67
View File
@@ -1,67 +0,0 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "FontData.h"
namespace love
{
namespace font
{
FontData::FontData(Rasterizer * raster)
: raster(raster)
{
data = new GlyphData *[MAX_CHARS];
for (unsigned int i = 0; i < MAX_CHARS; i++) {
data[i] = raster->getGlyphData(i);
}
}
FontData::~FontData()
{
for (unsigned int i = 0; i < MAX_CHARS; i++) {
data[i]->release();
}
delete[] data;
}
void * FontData::getData() const
{
return (void *)data;
}
int FontData::getSize() const
{
return MAX_CHARS;
}
GlyphData * FontData::getGlyphData(unsigned short glyph) const
{
return data[glyph];
}
int FontData::getHeight() const
{
return raster->getHeight();
}
} // font
} // love
-56
View File
@@ -1,56 +0,0 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_FONT_FONT_DATA_H
#define LOVE_FONT_FONT_DATA_H
// LOVE
#include <common/Data.h>
#include "GlyphData.h"
#include "Rasterizer.h"
namespace love
{
namespace font
{
class FontData : public Data
{
public:
FontData(Rasterizer * raster);
virtual ~FontData();
// Implements Data.
void * getData() const;
int getSize() const;
GlyphData * getGlyphData(unsigned short glyph) const;
int getHeight() const;
static const unsigned int MAX_CHARS = 256;
private:
GlyphData ** data;
Rasterizer * raster;
};
} // font
} // love
#endif // LOVE_FONT_FONT_DATA_H
+4 -69
View File
@@ -28,7 +28,7 @@ namespace font
{
GlyphData::GlyphData(unsigned short glyph, GlyphMetrics glyphMetrics, GlyphData::Format f)
: glyph(glyph), metrics(glyphMetrics), data(0), format(f), padded(false)
: glyph(glyph), metrics(glyphMetrics), data(0), format(f)
{
if (metrics.width && metrics.height) {
switch (f) {
@@ -69,12 +69,12 @@ namespace font
int GlyphData::getHeight() const
{
return (padded ? getPaddedHeight() : metrics.height);
return metrics.height;
}
int GlyphData::getWidth() const
{
return (padded ? getPaddedWidth() : metrics.width);
return metrics.width;
}
int GlyphData::getAdvance() const
@@ -116,71 +116,6 @@ namespace font
{
return format;
}
void GlyphData::pad()
{
if (data == 0)
return;
int w = getWidth();
int h = getHeight();
int pw = next_p2(w);
int ph = next_p2(h);
unsigned char * d = new unsigned char[pw * ph * (format == GlyphData::FORMAT_LUMINANCE_ALPHA ? 2 : 4)];
for (int j = 0; j < ph; j++) {
for (int i = 0; i < pw; i++) {
int n = i+j*w;
int p = i+j*pw;
if (i < w && j < h) {
if (format == GlyphData::FORMAT_LUMINANCE_ALPHA) {
p *= 2;
n *= 2;
d[p] = data[n];
d[p+1] = data[n+1];
} else {
p *= 4;
n *= 4;
d[p] = data[n];
d[p+1] = data[n+1];
d[p+2] = data[n+2];
d[p+3] = data[n+3];
}
} else {
if (format == GlyphData::FORMAT_LUMINANCE_ALPHA) {
p *= 2;
d[p] = d[p+1] = 0;
} else {
p *= 4;
d[p] = d[p+1] = d[p+2] = d[p+3] = 0;
}
}
}
}
delete[] data;
data = d;
padded = true;
}
bool GlyphData::isPadded() const
{
return padded;
}
int GlyphData::getPaddedWidth() const
{
return next_p2(metrics.width);
}
int GlyphData::getPaddedHeight() const
{
return next_p2(metrics.height);
}
inline int GlyphData::next_p2(int num) const
{
int powered = 2;
while(powered < num) powered <<= 1;
return powered;
}
} // font
} // love
-30
View File
@@ -112,33 +112,6 @@ namespace font
**/
Format getFormat() const;
/**
* Returns the closest number to num which is a power of two.
*
* @param num The number to be 2powered.
**/
inline int next_p2(int num) const;
/**
* Pads the data to fit into a power-of-2 texture.
**/
void pad();
/**
* Returns whether the data has been padded.
**/
bool isPadded() const;
/**
* Returns the padded width.
**/
int getPaddedWidth() const;
/**
* Returns the padded height.
**/
int getPaddedHeight() const;
private:
// The glyph itself
unsigned short glyph;
@@ -151,9 +124,6 @@ namespace font
// The format the data's in
Format format;
// Padded?
bool padded;
}; // GlyphData
-1
View File
@@ -79,7 +79,6 @@ namespace font
gd[i*4+2] = p.b;
gd[i*4+3] = p.a;
}
g->pad();
return g;
}
-5
View File
@@ -66,11 +66,6 @@ namespace freetype
{
return r->getGlyphData(glyph);
}
FontData * Font::newFontData(Rasterizer * r)
{
return new FontData(r);
}
const char * Font::getName() const
{
-1
View File
@@ -63,7 +63,6 @@ namespace freetype
Rasterizer * newRasterizer(love::image::ImageData * data, std::string glyphs);
Rasterizer * newRasterizer(love::image::ImageData * data, unsigned short * glyphs, int length);
GlyphData * newGlyphData(Rasterizer * r, unsigned short glyph);
FontData * newFontData(Rasterizer * r);
// Implement Module
const char * getName() const;
@@ -104,9 +104,6 @@ namespace freetype
// Having copied the data over, we can destroy the glyph
FT_Done_Glyph(ftglyph);
// Pad the GlyphData for graphics cards that don't support npo2 textures
glyphData->pad();
// Return data
return glyphData;
-11
View File
@@ -22,7 +22,6 @@
#include "Font.h"
#include <font/wrap_FontData.h>
#include <font/wrap_GlyphData.h>
#include <font/wrap_Rasterizer.h>
@@ -64,25 +63,15 @@ namespace freetype
luax_newtype(L, "GlyphData", FONT_GLYPH_DATA_T, t);
return 1;
}
int w_newFontData(lua_State * L)
{
Rasterizer * r = luax_checkrasterizer(L, 1);
FontData * f = instance->newFontData(r);
luax_newtype(L, "FontData", FONT_FONT_DATA_T, (void*)f);
return 1;
}
// List of functions to wrap.
static const luaL_Reg functions[] = {
{ "newRasterizer", w_newRasterizer },
{ "newGlyphData", w_newGlyphData },
{ "newFontData", w_newFontData },
{ 0, 0 }
};
static const lua_CFunction types[] = {
luaopen_fontdata,
luaopen_glyphdata,
luaopen_rasterizer,
0
-46
View File
@@ -1,46 +0,0 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "wrap_FontData.h"
#include <common/wrap_Data.h>
namespace love
{
namespace font
{
FontData * luax_checkfontdata(lua_State * L, int idx)
{
return luax_checktype<FontData>(L, idx, "FontData", FONT_FONT_DATA_T);
}
static const luaL_Reg functions[] = {
{ "getPointer", w_Data_getPointer },
{ "getSize", w_Data_getSize },
{ 0, 0 }
};
int luaopen_fontdata(lua_State * L)
{
return luax_register_type(L, "FontData", functions);
}
} // font
} // love
-39
View File
@@ -1,39 +0,0 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_FONT_WRAP_FONT_DATA_H
#define LOVE_FONT_WRAP_FONT_DATA_H
// LOVE
#include <common/runtime.h>
#include "FontData.h"
namespace love
{
namespace font
{
FontData * luax_checkfontdata(lua_State * L, int idx);
int luaopen_fontdata(lua_State * L);
} // font
} // love
#endif // LOVE_FONT_WRAP_FONT_DATA_H
+103
View File
@@ -0,0 +1,103 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_GRAPHICS_COLOR_H
#define LOVE_GRAPHICS_COLOR_H
namespace love
{
namespace graphics
{
template <typename T>
struct ColorT
{
T r;
T g;
T b;
T a;
ColorT() : r(0), g(0), b(0), a(0) {}
ColorT(T r_, T g_, T b_, T a_) : r(r_), g(g_), b(b_), a(a_) {}
void set(T r_, T g_, T b_, T a_) { r = r_; g = g_; b = b_; a = a_; }
ColorT<T> operator+=(const ColorT<T>& other);
ColorT<T> operator*=(T s);
ColorT<T> operator/=(T s);
};
template <typename T>
ColorT<T> ColorT<T>::operator+=(const ColorT<T>& other)
{
r += other.r;
g += other.g;
b += other.b;
a += other.a;
return *this;
}
template <typename T>
ColorT<T> ColorT<T>::operator*=(T s)
{
r *= s;
g *= s;
b *= s;
a *= s;
return *this;
}
template <typename T>
ColorT<T> ColorT<T>::operator/=(T s)
{
r /= s;
g /= s;
b /= s;
a /= s;
return *this;
}
template <typename T>
ColorT<T> operator+(const ColorT<T>& a, const ColorT<T>& b)
{
ColorT<T> tmp(a);
return tmp += b;
}
template <typename T>
ColorT<T> operator*(const ColorT<T>& a, T s)
{
ColorT<T> tmp(a);
return tmp *= s;
}
template <typename T>
ColorT<T> operator/(const ColorT<T>& a, T s)
{
ColorT<T> tmp(a);
return tmp /= s;
}
typedef ColorT<unsigned char> Color;
typedef ColorT<float> Colorf;
} // graphics
} // love
#endif // LOVE_GRAPHICS_COLOR_H
+155 -55
View File
@@ -17,13 +17,18 @@
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include <common/config.h>
#include "Font.h"
#include <font/GlyphData.h>
#include "Quad.h"
#include <libraries/utf8/utf8.h>
#include <common/math.h>
#include <math.h>
#include <algorithm> // for max
namespace love
{
namespace graphics
@@ -31,33 +36,104 @@ namespace graphics
namespace opengl
{
Font::Font(love::font::FontData * data, const Image::Filter& filter)
: height(data->getHeight()), lineHeight(1), mSpacing(1)
Font::Font(love::font::Rasterizer * r, const Image::Filter& filter)
: rasterizer(r), height(r->getHeight()), lineHeight(1), mSpacing(1), filter(filter)
{
glyphs = new Glyph*[MAX_CHARS];
type = FONT_UNKNOWN;
love::font::GlyphData * gd;
for(unsigned int i = 0; i < MAX_CHARS; i++)
{
gd = data->getGlyphData(i);
glyphs[i] = new Glyph(gd, filter);
glyphs[i]->load();
widths[i] = gd->getWidth();
spacing[i] = gd->getAdvance();
bearingX[i] = gd->getBearingX();
bearingY[i] = gd->getBearingY();
if (type == FONT_UNKNOWN) type = (gd->getFormat() == love::font::GlyphData::FORMAT_LUMINANCE_ALPHA ? FONT_TRUETYPE : FONT_IMAGE);
}
r->retain();
love::font::GlyphData * gd = r->getGlyphData(32);
type = (gd->getFormat() == love::font::GlyphData::FORMAT_LUMINANCE_ALPHA ? FONT_TRUETYPE : FONT_IMAGE);
delete gd;
createTexture();
}
Font::~Font()
{
for(unsigned int i = 0; i < MAX_CHARS; i++)
{
glyphs[i]->release();
rasterizer->release();
unloadVolatile();
}
void Font::createTexture()
{
texture_x = texture_y = rowHeight = 0;
GLuint t;
glGenTextures(1, &t);
textures.push_back(t);
glBindTexture(GL_TEXTURE_2D, t);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
(filter.mag == Image::FILTER_LINEAR) ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
(filter.min == Image::FILTER_LINEAR) ? GL_LINEAR : GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
GLint format = (type == FONT_TRUETYPE ? GL_LUMINANCE_ALPHA : GL_RGBA);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
(GLsizei)TEXTURE_WIDTH,
(GLsizei)TEXTURE_HEIGHT,
0,
format,
GL_UNSIGNED_BYTE,
NULL);
}
Font::Glyph * Font::addGlyph(int glyph)
{
Glyph * g = new Glyph;
g->list = glGenLists(1);
if (g->list == 0) { // opengl failed to generate the list
delete g;
return NULL;
}
delete[] glyphs;
love::font::GlyphData *gd = rasterizer->getGlyphData(glyph);
g->spacing = gd->getAdvance();
int w = gd->getWidth();
int h = gd->getHeight();
if (texture_x + w > TEXTURE_WIDTH) { // out of space - new row!
texture_x = 0;
texture_y += rowHeight;
rowHeight = 0;
}
if (texture_y + h > TEXTURE_HEIGHT) { // totally out of space - new texture!
createTexture();
}
GLuint t = textures.back();
glBindTexture(GL_TEXTURE_2D, t);
glTexSubImage2D(GL_TEXTURE_2D, 0, texture_x, texture_y, w, h, (type == FONT_TRUETYPE ? GL_LUMINANCE_ALPHA : GL_RGBA), GL_UNSIGNED_BYTE, gd->getData());
Quad::Viewport v;
v.x = texture_x;
v.y = texture_y;
v.w = w;
v.h = h;
Quad * q = new Quad(v, TEXTURE_WIDTH, TEXTURE_HEIGHT);
const vertex * verts = q->getVertices();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid *)&verts[0].x);
glTexCoordPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid *)&verts[0].s);
glNewList(g->list, GL_COMPILE);
glBindTexture(GL_TEXTURE_2D, t);
glPushMatrix();
glTranslatef(static_cast<float>(gd->getBearingX()), static_cast<float>(-gd->getBearingY()), 0.0f);
glDrawArrays(GL_QUADS, 0, 4);
glPopMatrix();
glEndList();
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
delete q;
delete gd;
texture_x += w;
rowHeight = std::max(rowHeight, h);
glyphs[glyph] = g;
return g;
}
float Font::getHeight() const
@@ -65,7 +141,7 @@ namespace opengl
return static_cast<float>(height);
}
void Font::print(std::string text, float x, float y, float angle, float sx, float sy) const
void Font::print(std::string text, float x, float y, float angle, float sx, float sy)
{
float dx = 0.0f; // spacing counter for newline handling
glPushMatrix();
@@ -73,67 +149,82 @@ namespace opengl
glTranslatef(ceil(x), ceil(y), 0.0f);
glRotatef(LOVE_TODEG(angle), 0, 0, 1.0f);
glScalef(sx, sy, 1.0f);
for (unsigned int i = 0; i < text.size(); i++) {
unsigned char g = (unsigned char)text[i];
utf8::iterator<std::string::iterator> i (text.begin(), text.begin(), text.end());
utf8::iterator<std::string::iterator> end (text.end(), text.begin(), text.end());
while (i != end) {
int g = *i++;
if (g == '\n') { // wrap newline, but do not print it
glTranslatef(-dx, floor(getHeight() * getLineHeight() + 0.5f), 0);
dx = 0.0f;
continue;
}
if (!glyphs[g]) g = 32; // space
Glyph * glyph = glyphs[g];
if (!glyph) glyph = addGlyph(g);
glPushMatrix();
// 1.25 is magic line height for true type fonts
if (type == FONT_TRUETYPE) glTranslatef(0, floor(getHeight() / 1.25f + 0.5f), 0);
glyphs[g]->draw(0, 0, 0, 1, 1, 0, 0);
glCallList(glyph->list);
glPopMatrix();
glTranslatef(static_cast<GLfloat>(spacing[g]), 0, 0);
dx += spacing[g];
glTranslatef(static_cast<GLfloat>(glyph->spacing), 0, 0);
dx += glyph->spacing;
}
glPopMatrix();
}
void Font::print(char character, float x, float y) const
void Font::print(char character, float x, float y)
{
if (!glyphs[(int)character]) character = ' ';
Glyph * glyph = glyphs[character];
if (!glyph) glyph = addGlyph(character);
glPushMatrix();
glTranslatef(x, floor(y+getHeight() + 0.5f), 0.0f);
glCallList(list+character);
glCallList(glyph->list);
glPopMatrix();
}
int Font::getWidth(const std::string & line) const
int Font::getWidth(const std::string & line)
{
if(line.size() == 0) return 0;
int temp = 0;
Glyph * g;
for(unsigned int i = 0; i < line.size(); i++)
{
temp += static_cast<int>((spacing[(int)line[i]] * mSpacing));
utf8::iterator<std::string::const_iterator> i (line.begin(), line.begin(), line.end());
utf8::iterator<std::string::const_iterator> end (line.end(), line.begin(), line.end());
while (i != end) {
int c = *i++;
g = glyphs[c];
if (!g) g = addGlyph(c);
temp += static_cast<int>(g->spacing * mSpacing);
}
return temp;
}
int Font::getWidth(const char * line) const
int Font::getWidth(const char * line)
{
return this->getWidth(std::string(line));
}
int Font::getWidth(const char character) const
int Font::getWidth(const char character)
{
return spacing[(int)character];
Glyph * g = glyphs[character];
if (!g) g = addGlyph(character);
return g->spacing;
}
int Font::getWrap(const std::string & line, float wrap, int * lines) const
int Font::getWrap(const std::string & line, float wrap, int * lines)
{
if(line.size() == 0) return 0;
int maxw = 0;
int linen = 1;
int temp = 0;
std::string text;
Glyph * g;
for(unsigned int i = 0; i < line.size(); i++)
{
utf8::iterator<std::string::const_iterator> i (line.begin(), line.begin(), line.end());
utf8::iterator<std::string::const_iterator> end (line.end(), line.begin(), line.end());
while (i != end) {
if(temp > wrap && text.find(" ") != std::string::npos)
{
unsigned int space = text.find_last_of(' ');
@@ -144,8 +235,11 @@ namespace opengl
temp = getWidth(text);
linen++;
}
temp += static_cast<int>((spacing[(int)line[i]] * mSpacing));
text += line[i];
int c = *i++;
g = glyphs[c];
if (!g) g = addGlyph(c);
temp += static_cast<int>(g->spacing * mSpacing);
utf8::append(c, text.end());
}
if(temp > maxw) maxw = temp;
@@ -154,7 +248,7 @@ namespace opengl
return maxw;
}
int Font::getWrap(const char * line, float wrap, int * lines) const
int Font::getWrap(const char * line, float wrap, int * lines)
{
return getWrap(std::string(line), wrap, lines);
}
@@ -181,21 +275,27 @@ namespace opengl
bool Font::loadVolatile()
{
// reload all glyphs
for(unsigned int i = 0; i < MAX_CHARS; i++)
{
glyphs[i]->load();
glNewList(list + i, GL_COMPILE);
glyphs[i]->draw(0, 0, 0, 1, 1, 0, 0);
glEndList();
}
createTexture();
return true;
}
void Font::unloadVolatile()
{
// delete the glyphs
glDeleteLists(list, MAX_CHARS);
// nuke everything from orbit
std::map<int, Glyph *>::iterator it = glyphs.begin();
Glyph * g;
while (it != glyphs.end()) {
g = it->second;
glDeleteLists(g->list, 1);
delete g;
glyphs.erase(it++);
}
std::vector<GLuint>::iterator iter = textures.begin();
while (iter != textures.end()) {
glDeleteTextures(1, (GLuint*)&*iter);
iter++;
}
textures.clear();
}
} // opengl
+33 -21
View File
@@ -22,13 +22,16 @@
#define LOVE_GRAPHICS_OPENGL_FONT_H
// STD
#include <map>
#include <string>
#include <vector>
// LOVE
#include <common/Object.h>
#include <font/FontData.h>
#include <font/Rasterizer.h>
#include <graphics/Image.h>
#include "Glyph.h"
#include "GLee.h"
namespace love
{
@@ -46,31 +49,40 @@ namespace opengl
FONT_IMAGE,
FONT_UNKNOWN
};
struct Glyph
{
GLuint list;
int spacing;
};
love::font::Rasterizer * rasterizer;
int height;
float lineHeight;
float mSpacing; // modifies the spacing by multiplying it with this value
Glyph ** glyphs;
GLuint list; // the list of glyphs, for quicker drawing
std::vector<GLuint> textures; // vector of packed textures
std::map<int, Glyph *> glyphs; // maps glyphs to display lists
FontType type;
Image::Filter filter;
static const int TEXTURE_WIDTH = 512;
static const int TEXTURE_HEIGHT = 512;
int texture_x, texture_y;
int rowHeight;
void createTexture();
Glyph * addGlyph(int glyph);
public:
static const unsigned int MAX_CHARS = 256;
// The widths of each character.
int widths[MAX_CHARS];
// The spacing of each character.
int spacing[MAX_CHARS];
// The X-bearing of each character.
int bearingX[MAX_CHARS];
// The Y-bearing of each character.
int bearingY[MAX_CHARS];
/**
* Default constructor.
*
* @param data The font data to construct from.
**/
Font(love::font::FontData * data, const Image::Filter& filter = Image::Filter());
Font(love::font::Rasterizer * r, const Image::Filter& filter = Image::Filter());
virtual ~Font();
@@ -82,7 +94,7 @@ namespace opengl
* @param y The y-coordinate.
* @param angle The amount of rotation.
**/
void print(std::string text, float x, float y, float angle = 0.0f, float sx = 1.0f, float sy = 1.0f) const;
void print(std::string text, float x, float y, float angle = 0.0f, float sx = 1.0f, float sy = 1.0f);
/**
* Prints the character at the designated position.
@@ -91,7 +103,7 @@ namespace opengl
* @param x The x-coordinate.
* @param y The y-coordinate.
**/
void print(char character, float x, float y) const;
void print(char character, float x, float y);
/**
* Returns the height of the font.
@@ -103,15 +115,15 @@ namespace opengl
*
* @param line A line of text.
**/
int getWidth(const std::string & line) const;
int getWidth(const char * line) const;
int getWidth(const std::string & line);
int getWidth(const char * line);
/**
* Returns the width of the passed character.
*
* @param character A character.
**/
int getWidth(const char character) const;
int getWidth(const char character);
/**
* Returns the maximal width of a wrapped string
@@ -121,8 +133,8 @@ namespace opengl
* @param wrap The number of pixels to wrap at
* @param lines Optional output of the number of lines needed
**/
int getWrap(const std::string & line, float wrap, int *lines = 0) const;
int getWrap(const char * line, float wrap, int *lines = 0) const;
int getWrap(const std::string & line, float wrap, int *lines = 0);
int getWrap(const char * line, float wrap, int *lines = 0);
/**
* Sets the line height (which should be a number to multiply the font size by,
+22 -3
View File
@@ -1,4 +1,5 @@
#include "Framebuffer.h"
#include "Graphics.h"
#include <common/Matrix.h>
#include <cstring> // For memcpy
@@ -199,10 +200,9 @@ namespace opengl
current->stopGrab();
// bind buffer and clear screen
glPushAttrib(GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_TRANSFORM_BIT);
glPushAttrib(GL_VIEWPORT_BIT | GL_DEPTH_BUFFER_BIT | GL_TRANSFORM_BIT);
strategy->bindFBO(fbo);
glClearColor(.0f, .0f, .0f, .0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, width, height);
// Reset the projection matrix
@@ -234,6 +234,22 @@ namespace opengl
current = NULL;
}
void Framebuffer::clear(const Color& c)
{
GLuint previous = 0;
if (current != NULL)
previous = current->fbo;
strategy->bindFBO(fbo);
glPushAttrib(GL_COLOR_BUFFER_BIT);
glClearColor((float)c.r/255.0f, (float)c.g/255.0f, (float)c.b/255.0f, (float)c.a/255.0f);
glClear(GL_COLOR_BUFFER_BIT);
glPopAttrib();
strategy->bindFBO(previous);
}
void Framebuffer::draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const
{
static Matrix t;
@@ -343,6 +359,9 @@ namespace opengl
setFilter(settings.filter);
setWrap(settings.wrap);
Color c;
c.r = c.g = c.b = c.a = 0;
clear(c);
return true;
}
@@ -4,6 +4,7 @@
#include <graphics/Drawable.h>
#include <graphics/Volatile.h>
#include <graphics/Image.h>
#include <graphics/Color.h>
#include <image/Image.h>
#include <image/ImageData.h>
#include <common/math.h>
@@ -29,6 +30,8 @@ namespace opengl
void startGrab();
void stopGrab();
void clear(const Color& c);
virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const;
love::image::ImageData * getImageData(love::image::Image * image);
-147
View File
@@ -1,147 +0,0 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "Glyph.h"
// STD
#include <cstring> // For memcpy
namespace love
{
namespace graphics
{
namespace opengl
{
Glyph::Glyph(love::font::GlyphData * data, const Image::Filter& filter_)
: data(data),
width((float)data->getWidth()), height((float)data->getHeight()),
texture(0), filter(filter_)
{
data->retain();
memset(vertices, 255, sizeof(vertex)*4);
vertices[0].x = 0; vertices[0].y = 0;
vertices[1].x = 0; vertices[1].y = height;
vertices[2].x = width; vertices[2].y = height;
vertices[3].x = width; vertices[3].y = 0;
vertices[0].s = 0; vertices[0].t = 0;
vertices[1].s = 0; vertices[1].t = 1;
vertices[2].s = 1; vertices[2].t = 1;
vertices[3].s = 1; vertices[3].t = 0;
}
Glyph::~Glyph()
{
if(data != 0)
data->release();
unload();
}
void Glyph::draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const
{
static Matrix t;
t.setTransformation(x, y, angle, sx, sy, ox, oy);
if(texture != 0)
glBindTexture(GL_TEXTURE_2D,texture);
glPushMatrix();
glMultMatrixf((const GLfloat*)t.getElements());
glTranslatef(static_cast<float>(data->getBearingX()), static_cast<float>(-data->getBearingY()), 0.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid*)&vertices[0].x);
glTexCoordPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid*)&vertices[0].s);
glDrawArrays(GL_QUADS, 0, 4);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
}
bool Glyph::load()
{
return loadVolatile();
}
void Glyph::unload()
{
unloadVolatile();
}
bool Glyph::loadVolatile()
{
GLint format = GL_RGBA;
if (data->getFormat() == love::font::GlyphData::FORMAT_LUMINANCE_ALPHA) format = GL_LUMINANCE_ALPHA;
glGenTextures(1,&texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
(filter.mag == Image::FILTER_LINEAR) ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
(filter.min == Image::FILTER_LINEAR) ? GL_LINEAR : GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
(GLsizei)width,
(GLsizei)height,
0,
format,
GL_UNSIGNED_BYTE,
data->getData());
return true;
}
void Glyph::unloadVolatile()
{
// Delete the hardware texture.
if(texture != 0)
{
glDeleteTextures(1, (GLuint*)&texture);
texture = 0;
}
}
float Glyph::getWidth() const
{
return width;
}
float Glyph::getHeight() const
{
return height;
}
} // opengl
} // graphics
} // love
-82
View File
@@ -1,82 +0,0 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_GRAPHICS_OPENGL_GLYPH_H
#define LOVE_GRAPHICS_OPENGL_GLYPH_H
// LOVE
#include <common/config.h>
#include <common/math.h>
#include <common/Matrix.h>
#include <font/GlyphData.h>
#include <graphics/Drawable.h>
#include <graphics/Volatile.h>
#include <graphics/Image.h>
// OpenGL
#include "GLee.h"
#include <SDL/SDL_opengl.h>
namespace love
{
namespace graphics
{
namespace opengl
{
class Glyph : public Drawable, public Volatile
{
private:
love::font::GlyphData * data;
float width, height;
GLuint texture;
vertex vertices[4];
Image::Filter filter;
public:
Glyph(love::font::GlyphData * data, const Image::Filter& filter_ = Image::Filter());
virtual ~Glyph();
bool load();
void unload();
// Implements Volatile.
bool loadVolatile();
void unloadVolatile();
float getWidth() const;
float getHeight() const;
void draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const;
}; // Glyph
} // opengl
} // graphics
} // love
#endif // LOVE_GRAPHICS_OPENGL_GLYPH_H
+177 -281
View File
@@ -20,6 +20,7 @@
#include <common/config.h>
#include <common/math.h>
#include <common/Vector.h>
#include "Graphics.h"
@@ -36,7 +37,7 @@ namespace opengl
{
Graphics::Graphics()
: currentFont(0)
: currentFont(0), lineWidth(1)
{
// Indicates that there is no screen
// created yet.
@@ -81,16 +82,10 @@ namespace opengl
float color[4];
//get the color
glGetFloatv(GL_CURRENT_COLOR, color);
s.color.r = (GLubyte)(color[0]*255.0f);
s.color.g = (GLubyte)(color[1]*255.0f);
s.color.b = (GLubyte)(color[2]*255.0f);
s.color.a = (GLubyte)(color[3]*255.0f);
s.color.set( (color[0]*255.0f), (color[1]*255.0f), (color[2]*255.0f), (color[3]*255.0f) );
//get the background color
glGetFloatv(GL_COLOR_CLEAR_VALUE, color);
s.backgroundColor.r = (GLubyte)(color[0]*255.0f);
s.backgroundColor.g = (GLubyte)(color[1]*255.0f);
s.backgroundColor.b = (GLubyte)(color[2]*255.0f);
s.backgroundColor.a = (GLubyte)(color[3]*255.0f);
s.backgroundColor.set( color[0]*255.0f, color[1]*255.0f, color[2]*255.0f, color[3]*255.0f );
//store modes here
GLint mode;
//get blend mode
@@ -100,19 +95,8 @@ namespace opengl
//get color mode
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &mode);
s.colorMode = (mode == GL_MODULATE) ? Graphics::COLOR_MODULATE : Graphics::COLOR_REPLACE;
//get the line width (directly to corresponding variable)
glGetFloatv(GL_LINE_WIDTH, &s.lineWidth);
//get line style
s.lineStyle = (glIsEnabled(GL_LINE_SMOOTH) == GL_TRUE) ? Graphics::LINE_SMOOTH : Graphics::LINE_ROUGH;
//get line stipple
s.stipple = (glIsEnabled(GL_LINE_STIPPLE) == GL_TRUE);
if (s.stipple)
{
//get the stipple repeat
glGetIntegerv(GL_LINE_STIPPLE_REPEAT, &s.stippleRepeat);
//get the stipple pattern
glGetIntegerv(GL_LINE_STIPPLE_PATTERN, &s.stipplePattern);
}
s.lineStyle = (glIsEnabled(GL_POLYGON_SMOOTH) == GL_TRUE) ? Graphics::LINE_SMOOTH : Graphics::LINE_ROUGH;
//get the point size
glGetFloatv(GL_POINT_SIZE, &s.pointSize);
//get point style
@@ -136,11 +120,7 @@ namespace opengl
setBackgroundColor(s.backgroundColor);
setBlendMode(s.blendMode);
setColorMode(s.colorMode);
setLine(s.lineWidth, s.lineStyle);
if (s.stipple)
setLineStipple(s.stipplePattern, s.stippleRepeat);
else
setLineStipple();
setLine(lineWidth, s.lineStyle);
setPoint(s.pointSize, s.pointStyle);
if (s.scissor)
setScissor(s.scissorBox[0], s.scissorBox[1], s.scissorBox[2], s.scissorBox[3]);
@@ -193,6 +173,7 @@ namespace opengl
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, (vsync ? 1 : 0));
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
// FSAA
if(fsaa > 0)
@@ -260,8 +241,7 @@ namespace opengl
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Enable line/point smoothing.
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
setLineStyle(LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
@@ -281,6 +261,9 @@ namespace opengl
// Reset modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Set pixel row alignment
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
// Set the new display mode as the current display mode.
currentMode.width = width;
@@ -314,6 +297,8 @@ namespace opengl
void Graphics::reset()
{
DisplayState s;
discardMask();
Framebuffer::bindDefaultBuffer();
restoreState(s);
}
@@ -443,6 +428,28 @@ namespace opengl
return 4;
}
void Graphics::defineMask()
{
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glEnable(GL_STENCIL_TEST);
glClear(GL_STENCIL_BUFFER_BIT);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
}
void Graphics::useMask()
{
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
void Graphics::discardMask()
{
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDisable(GL_STENCIL_TEST);
}
Image * Graphics::newImage(love::image::ImageData * data)
{
// Create the image.
@@ -472,9 +479,9 @@ namespace opengl
return new Quad(v, sw, sh);
}
Font * Graphics::newFont(love::font::FontData * data, const Image::Filter& filter)
Font * Graphics::newFont(love::font::Rasterizer * r, const Image::Filter& filter)
{
Font * font = new Font(data, filter);
Font * font = new Font(r, filter);
// Load it and check for errors.
if(!font)
@@ -501,7 +508,7 @@ namespace opengl
return new Framebuffer(width, height);
}
void Graphics::setColor(Color c)
void Graphics::setColor(const Color& c)
{
glColor4ubv(&c.r);
}
@@ -520,9 +527,9 @@ namespace opengl
return t;
}
void Graphics::setBackgroundColor(Color c)
void Graphics::setBackgroundColor(const Color& c)
{
glClearColor((float)c.r/255.0f, (float)c.g/255.0f, (float)c.b/255.0f, 1.0f);
glClearColor((float)c.r/255.0f, (float)c.g/255.0f, (float)c.b/255.0f, (float)c.a/255.0f);
}
Color Graphics::getBackgroundColor()
@@ -610,45 +617,30 @@ namespace opengl
void Graphics::setLineWidth( float width )
{
glLineWidth(width);
lineWidth = width;
}
void Graphics::setLineStyle(Graphics::LineStyle style )
{
// XXX: actually enables antialiasing for _all_ polygons.
// may need investigation if wanted or not
// maybe rename to something else?
if(style == LINE_ROUGH)
glDisable (GL_LINE_SMOOTH);
glDisable (GL_POLYGON_SMOOTH);
else // type == LINE_SMOOTH
{
glEnable (GL_LINE_SMOOTH);
glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
glEnable (GL_POLYGON_SMOOTH);
glHint (GL_POLYGON_SMOOTH_HINT, GL_NICEST);
}
}
void Graphics::setLine( float width, Graphics::LineStyle style )
{
glLineWidth(width);
setLineWidth(width);
if(style == 0)
return;
if(style == LINE_ROUGH)
glDisable (GL_LINE_SMOOTH);
else // type == LINE_SMOOTH
{
glEnable (GL_LINE_SMOOTH);
glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
}
}
void Graphics::setLineStipple()
{
glDisable(GL_LINE_STIPPLE);
}
void Graphics::setLineStipple(unsigned short pattern, int repeat)
{
glEnable(GL_LINE_STIPPLE);
glLineStipple((GLint)repeat, (GLshort)pattern);
setLineStyle(style);
}
float Graphics::getLineWidth()
@@ -660,25 +652,12 @@ namespace opengl
Graphics::LineStyle Graphics::getLineStyle()
{
if(glIsEnabled(GL_LINE_SMOOTH) == GL_TRUE)
if(glIsEnabled(GL_POLYGON_SMOOTH) == GL_TRUE)
return LINE_SMOOTH;
else
return LINE_ROUGH;
}
int Graphics::getLineStipple(lua_State * L)
{
if(glIsEnabled(GL_LINE_STIPPLE) == GL_FALSE)
return 0;
GLint factor, pattern;
glGetIntegerv(GL_LINE_STIPPLE_PATTERN, &pattern);
glGetIntegerv(GL_LINE_STIPPLE_REPEAT, &factor);
lua_pushinteger(L, pattern);
lua_pushinteger(L, factor);
return 2;
}
void Graphics::setPointSize( float size )
{
glPointSize((GLfloat)size);
@@ -807,251 +786,168 @@ namespace opengl
glEnable(GL_TEXTURE_2D);
}
void Graphics::line( float x1, float y1, float x2, float y2 )
// calculate line boundary intersection vertices for current line
// dependent on the current *and next* line segment
static void pushIntersectionPoints(Vector *vertices, int pos, float halfwidth, const Vector& p, const Vector& q, const Vector& r)
{
glDisable(GL_TEXTURE_2D);
glPushMatrix();
glBegin(GL_LINES);
glVertex2f(x1, y1);
glVertex2f(x2, y2);
glEnd();
glPopMatrix();
glEnable(GL_TEXTURE_2D);
// calculate line directions
Vector s = (q - p);
Vector t = (r - q);
// calculate vertex displacement vectors
Vector d1 = s.getNormal();
Vector d2 = t.getNormal();
d1.normalize();
d2.normalize();
float det_norm = d1 ^ d2;
d1 *= halfwidth;
d2 *= halfwidth;
// lines parallel -> assume intersection at displacement points
if (fabs(det_norm) <= .03) {
vertices[pos] = q - d2;
vertices[pos + 1] = q + d2;
return;
}
// real intersection -> calculate boundary intersection points
float det = s ^ t;
Vector d = d1 - d2;
Vector b = s - d; // s = q - p
Vector c = s + d;
float lambda = (b ^ t) / det;
float mu = (c ^ t) / det;
// ordering for GL_TRIANGLE_STRIP
vertices[pos] = p - d1 + s * mu;
vertices[pos+1] = p + d1 + s * lambda;
}
int Graphics::polyline( lua_State * L)
void Graphics::polyline(const float* coords, size_t count, bool looping)
{
// Get number of params.
int args = lua_gettop(L);
bool table = false;
Vector *vertices = new Vector[count]; // two vertices for every line end-point
Vector p,q,r;
if (args == 1) { // we've got a table, hopefully
int type = lua_type(L, 1);
if (type != LUA_TTABLE)
return luaL_error(L, "Function requires a table or series of numbers");
table = true;
args = lua_objlen(L, 1);
r = Vector(coords[0], coords[1]);
if (looping) q = Vector(coords[count-4], coords[count-3]);
else q = r * 2 - Vector(coords[2], coords[3]);
for (size_t i = 0; i+3 < count; i += 2) {
p = q;
q = r;
r = Vector(coords[i+2], coords[i+3]);
pushIntersectionPoints(vertices, i, lineWidth/2, p,q,r);
}
if (args % 2) // an odd number of arguments, no good for a polyline
return luaL_error(L, "Number of vertices must be a multiple of two");
else if (args < 4)
return luaL_error(L, "Need at least two vertices to draw a line");
p = q;
q = r;
if (looping) r = Vector(coords[2], coords[3]);
else r += (q-p);
pushIntersectionPoints(vertices, count-2, lineWidth/2, p,q,r);
// right, let's draw this polyline, then
glDisable(GL_TEXTURE_2D);
glBegin(GL_LINE_STRIP);
if (table) {
for (int i = 1; i < args; i += 2) {
lua_pushnumber(L, i); // x coordinate
lua_rawget(L, 1);
lua_pushnumber(L, i+1); // y coordinate
lua_rawget(L, 1);
glVertex2f((GLfloat)lua_tonumber(L, -2), (GLfloat)lua_tonumber(L, -1));
lua_pop(L, 2);
}
} else {
for (int i = 1; i < args; i+=2) {
glVertex2f((GLfloat)lua_tonumber(L, i), (GLfloat)lua_tonumber(L, i+1));
}
}
glEnd();
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, (const GLvoid*)vertices);
glDrawArrays(GL_TRIANGLE_STRIP, 0, count);
glDisableClientState(GL_VERTEX_ARRAY);
glEnable(GL_TEXTURE_2D);
return 0;
delete[] vertices;
}
void Graphics::triangle(DrawMode mode, float x1, float y1, float x2, float y2, float x3, float y3 )
{
glDisable(GL_TEXTURE_2D);
glPushMatrix();
switch(mode)
{
case DRAW_LINE:
glBegin(GL_LINE_LOOP);
glVertex2f(x1, y1);
glVertex2f(x2, y2);
glVertex2f(x3, y3);
glEnd();
break;
default:
case DRAW_FILL:
glBegin(GL_TRIANGLES);
glVertex2f(x1, y1);
glVertex2f(x2, y2);
glVertex2f(x3, y3);
glEnd();
break;
}
glPopMatrix();
glEnable(GL_TEXTURE_2D);
float coords[] = { x1,y1, x2,y2, x3,y3, x1,y1 };
polygon(mode, coords, 4 * 2);
}
void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h)
{
glDisable(GL_TEXTURE_2D);
glPushMatrix();
switch(mode)
{
case DRAW_LINE:
// offsets here because OpenGL is being a bitch about line drawings
glBegin(GL_LINE_LOOP);
glVertex2f(x, y);
glVertex2f(x, y+h-1);
glVertex2f(x+w-1, y+h-1);
glVertex2f(x+w-1, y);
glEnd();
break;
default:
case DRAW_FILL:
glBegin(GL_QUADS);
glVertex2f(x, y);
glVertex2f(x, y+h);
glVertex2f(x+w, y+h);
glVertex2f(x+w, y);
glEnd();
break;
}
glPopMatrix();
glEnable(GL_TEXTURE_2D);
quad(mode, x,y, x,y+h, x+w,y+h, x+w,y);
}
void Graphics::quad(DrawMode mode, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4 )
{
glDisable(GL_TEXTURE_2D);
glPushMatrix();
switch(mode)
{
case DRAW_LINE:
glBegin(GL_LINE_LOOP);
glVertex2f(x1, y1);
glVertex2f(x2, y2);
glVertex2f(x3, y3);
glVertex2f(x4, y4);
glEnd();
break;
default:
case DRAW_FILL:
glBegin(GL_QUADS);
glVertex2f(x1, y1);
glVertex2f(x2, y2);
glVertex2f(x3, y3);
glVertex2f(x4, y4);
glEnd();
break;
}
glPopMatrix();
glEnable(GL_TEXTURE_2D);
float coords[] = { x1,y1, x2,y2, x3,y3, x4,y4, x1,y1 };
polygon(mode, coords, 5 * 2);
}
void Graphics::circle(DrawMode mode, float x, float y, float radius, int points )
void Graphics::circle(DrawMode mode, float x, float y, float radius, int points)
{
float two_pi = static_cast<float>(LOVE_M_PI * 2);
if(points <= 0) points = 1;
float angle_shift = (two_pi / points);
float phi = .0f;
glDisable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(x, y, 0.0f);
switch(mode)
{
case DRAW_LINE:
glBegin(GL_LINE_LOOP);
for(float i = 0; i < two_pi; i+= angle_shift)
glVertex2f(radius * sin(i),radius * cos(i));
glEnd();
break;
default:
case DRAW_FILL:
glBegin(GL_TRIANGLE_FAN);
for(float i = 0; i < two_pi; i+= angle_shift)
glVertex2f(radius * sin(i),radius * cos(i));
glEnd();
break;
float *coords = new float[2 * (points + 1)];
for (int i = 0; i < points; ++i, phi += angle_shift) {
coords[2*i] = x + radius * cos(phi);
coords[2*i+1] = y + radius * sin(phi);
}
coords[2*points] = coords[0];
coords[2*points+1] = coords[1];
polygon(mode, coords, (points + 1) * 2);
delete[] coords;
}
void Graphics::arc(DrawMode mode, float x, float y, float radius, float angle1, float angle2, int points)
{
angle1 = fmod(angle1, 2.0f * (float)LOVE_M_PI);
angle2 = fmod(angle2, 2.0f * (float)LOVE_M_PI);
if (angle1 == angle2)
return;
else if (angle1 > angle2)
angle2 += (float)LOVE_M_PI * 2.0f;
if(points <= 0) points = 1;
float angle_shift = ((angle2 - angle1) / points);
float phi = angle1;
// GL_POLYGON can only fill-draw convex polygons, so we need to do stuff manually here
if (mode == DRAW_LINE) {
float *coords = new float[(points + 3) * 2];
coords[0] = coords[2 * points + 4] = x;
coords[1] = coords[2 * points + 5] = y;
for (int i = 0; i <= points; ++i, phi += angle_shift) {
coords[2 * (i+1)] = x + radius * cos(phi);
coords[2 * (i+1) + 1] = y - radius * sin(phi);
}
polyline(coords, (points + 3) * 2); // artifacts at sharp angles if set to looping
delete[] coords;
} else {
glDisable(GL_TEXTURE_2D);
glBegin(GL_TRIANGLE_FAN);
glVertex2f(x, y);
for (int i = 0; i <= points; ++i, phi += angle_shift)
glVertex2f(x + radius * cos(phi), y - radius * sin(phi));
glEnd();
glEnable(GL_TEXTURE_2D);
}
glPopMatrix();
glEnable(GL_TEXTURE_2D);
}
int Graphics::polygon( lua_State * L )
/// @param mode the draw mode
/// @param coords the coordinate array
/// @param count the number of coordinates/size of the array
void Graphics::polygon(DrawMode mode, const float* coords, size_t count)
{
// Get number of params.
int n = lua_gettop(L);
// Need at least two params.
if( n < 2 )
return luaL_error(L, "Error: function needs at least two parameters.");
DrawMode mode;
const char * str = luaL_checkstring(L, 1);
if(!getConstant(str, mode))
return luaL_error(L, "Invalid draw mode: %s", str);
// Get the type of the second argument.
int luatype = lua_type(L, 2);
// Perform additional type checking.
switch(luatype)
{
case LUA_TNUMBER:
if( n-1 < 6 ) return luaL_error(L, "Error: function requires at least 3 vertices.");
if( ((n-1)%2) != 0 ) return luaL_error(L, "Error: number of vertices must be a multiple of two.");
break;
case LUA_TTABLE:
if( (lua_objlen(L, 2)%2) != 0 ) return luaL_error(L, "Error: number of vertices must be a multiple of two.");
break;
default:
return luaL_error(L, "Error: number type or table expected.");
// coords is an array of a closed loop of vertices, i.e.
// coords[count-2] = coords[0], coords[count-1] = coords[1]
if (mode == DRAW_LINE) {
polyline(coords, count, true);
} else {
glDisable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, (const GLvoid*)coords);
glDrawArrays(GL_POLYGON, 0, count/2-1); // opengl will close the polygon for us
glDisableClientState(GL_VERTEX_ARRAY);
glEnable(GL_TEXTURE_2D);
}
glDisable(GL_TEXTURE_2D);
glBegin((mode==DRAW_LINE) ? GL_LINE_LOOP : GL_POLYGON);
switch(luatype)
{
case LUA_TNUMBER:
for(int i = 2; i<n; i+=2)
glVertex2f((GLfloat)lua_tonumber(L, i), (GLfloat)lua_tonumber(L, i+1));
break;
case LUA_TTABLE:
lua_pushnil(L);
while (true)
{
if(lua_next(L, 2) == 0) break;
GLfloat x = (GLfloat)lua_tonumber(L, -1);
lua_pop(L, 1); // pop value
if(lua_next(L, 2) == 0) break;
GLfloat y = (GLfloat)lua_tonumber(L, -1);
lua_pop(L, 1); // pop value
glVertex2f(x, y);
}
break;
}
glEnd();
glEnable(GL_TEXTURE_2D);
return 0;
}
love::image::ImageData * Graphics::newScreenshot(love::image::Image * image)
+32 -50
View File
@@ -28,12 +28,10 @@
// SDL
#include <SDL.h>
#include "GLee.h"
#include <SDL_opengl.h>
// LOVE
#include <graphics/Graphics.h>
#include <font/FontData.h>
#include <graphics/Color.h>
#include <image/Image.h>
#include <image/ImageData.h>
@@ -51,10 +49,6 @@ namespace graphics
{
namespace opengl
{
struct Color
{
unsigned char r, g, b, a;
};
struct DisplayMode
{
@@ -79,11 +73,7 @@ namespace opengl
Graphics::ColorMode colorMode;
// Line.
float lineWidth;
Graphics::LineStyle lineStyle;
bool stipple;
GLint stippleRepeat;
GLint stipplePattern;
// Point.
float pointSize;
@@ -100,19 +90,14 @@ namespace opengl
// Default values.
DisplayState()
{
color.r = 255;
color.g = 255;
color.b = 255;
color.a = 255;
color.set(255,255,255,255);
backgroundColor.r = 0;
backgroundColor.g = 0;
backgroundColor.b = 0;
backgroundColor.a = 255;
blendMode = Graphics::BLEND_ALPHA;
colorMode = Graphics::COLOR_MODULATE;
lineWidth = 1.0f;
lineStyle = Graphics::LINE_SMOOTH;
stipple = false;
pointSize = 1.0f;
pointStyle = Graphics::POINT_SMOOTH;
scissor = false;
@@ -129,6 +114,8 @@ namespace opengl
Font * currentFont;
DisplayMode currentMode;
float lineWidth;
public:
Graphics();
@@ -247,6 +234,22 @@ namespace opengl
**/
int getScissor(lua_State * L);
/**
* Enables the stencil buffer and set stencil function to fill it
*/
void defineMask();
/**
* Set stencil function to mask the following drawing calls using
* the current stencil buffer
*/
void useMask();
/**
* Disables the stencil buffer
*/
void discardMask();
/**
* Creates an Image object with padding and/or optimization.
**/
@@ -261,7 +264,7 @@ namespace opengl
/**
* Creates a Font object.
**/
Font * newFont(love::font::FontData * data, const Image::Filter& filter = Image::Filter());
Font * newFont(love::font::Rasterizer * data, const Image::Filter& filter = Image::Filter());
SpriteBatch * newSpriteBatch(Image * image, int size, int usage);
@@ -272,7 +275,7 @@ namespace opengl
/**
* Sets the foreground color.
**/
void setColor(Color c);
void setColor(const Color& c);
/**
* Gets current color.
@@ -282,7 +285,7 @@ namespace opengl
/**
* Sets the background Color.
**/
void setBackgroundColor(Color c);
void setBackgroundColor(const Color& c);
/**
* Gets the current background color.
@@ -338,16 +341,6 @@ namespace opengl
**/
void setLine(float width, LineStyle style);
/**
* Disables line stippling.
**/
void setLineStipple();
/**
* Sets a line stipple pattern.
**/
void setLineStipple(unsigned short pattern, int repeat = 1);
/**
* Gets the line width.
**/
@@ -358,13 +351,6 @@ namespace opengl
**/
LineStyle getLineStyle();
/**
* Gets the line stipple pattern and repeat factor.
* @return pattern The stipplie bit-pattern.
* @return repeat The reapeat factor.
**/
int getLineStipple(lua_State * L);
/**
* Sets the size of points.
**/
@@ -426,20 +412,13 @@ namespace opengl
**/
void point(float x, float y);
/**
* Draws a line from (x1,y1) to (x2,y2).
* @param x1 First x-coordinate.
* @param y1 First y-coordinate.
* @param x2 Second x-coordinate.
* @param y2 Second y-coordinate.
**/
void line(float x1, float y1, float x2, float y2);
/**
* Draws a series of lines connecting the given vertices.
* @param ... Vertex components (x1, y1, x2, y2, etc.)
* @param coords Vertex components (x1, y1, x2, y2, etc.)
* @param count Coord array size
* @param looping Wether the line is joining itself
**/
int polyline(lua_State * L);
void polyline(const float* coords, size_t count, bool looping = false);
/**
* Draws a triangle using the three coordinates passed.
@@ -485,13 +464,16 @@ namespace opengl
* @param points Amount of points to use to draw the circle.
**/
void circle(DrawMode mode, float x, float y, float radius, int points = 10);
void arc(DrawMode mode, float x, float y, float radius, float angle1, float angle2, int points = 10);
/**
* Draws a polygon with an arbitrary number of vertices.
* @param type The type of drawing (line/filled).
* @param ... Vertex components (x1, y1, x2, y2, etc).
* @param coords Vertex components (x1, y1, x2, y2, etc.)
* @param count Coord array size
**/
int polygon(lua_State * L);
void polygon(DrawMode mode, const float* coords, size_t count);
/**
* Creates a screenshot of the view and saves it to the default folder.
+50 -44
View File
@@ -25,7 +25,6 @@
#include <SDL_opengl.h>
#include <cmath>
#include <cstdlib>
#include <cstring>
namespace love
{
@@ -34,6 +33,13 @@ namespace graphics
namespace opengl
{
namespace
{
Colorf colorToFloat(const Color& c) {
return Colorf( (GLfloat)c.r/255.0f, (GLfloat)c.g/255.0f, (GLfloat)c.b/255.0f, (GLfloat)c.a/255.0f );
}
}
float calculate_variation(float inner, float outer, float var)
{
float low = inner - (outer/2.0f)*var;
@@ -48,14 +54,14 @@ namespace opengl
direction(0), spread(0), relative(false), speedMin(0), speedMax(0), gravityMin(0),
gravityMax(0), radialAccelerationMin(0), radialAccelerationMax(0),
tangentialAccelerationMin(0), tangentialAccelerationMax(0),
sizeStart(1), sizeEnd(1), sizeVariation(0), rotationMin(0), rotationMax(0),
sizeVariation(0), rotationMin(0), rotationMax(0),
spinStart(0), spinEnd(0), spinVariation(0), offsetX(sprite->getWidth()*0.5f),
offsetY(sprite->getHeight()*0.5f)
{
this->sprite = sprite;
sprite->retain();
memset(colorStart, 255, 4);
memset(colorEnd, 255, 4);
sizes.push_back(1.0f);
colors.push_back( Colorf(1.0f, 1.0f, 1.0f, 1.0f) );
setBufferSize(buffer);
}
@@ -107,9 +113,9 @@ namespace opengl
max = tangentialAccelerationMax;
pLast->tangentialAcceleration = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;
pLast->sizeStart = calculate_variation(sizeStart, sizeEnd, sizeVariation);
pLast->sizeEnd = calculate_variation(sizeEnd, sizeStart, sizeVariation);
pLast->size = pLast->sizeStart;
pLast->sizeOffset = (rand() / (float(RAND_MAX)+1)) * sizeVariation; // time offset for size change
pLast->sizeIntervalSize = (1.0 - (rand() / (float(RAND_MAX)+1)) * sizeVariation) - pLast->sizeOffset;
pLast->size = sizes[(size_t)(pLast->sizeOffset - .5f) * (sizes.size() - 1)];
min = rotationMin;
max = rotationMax;
@@ -117,10 +123,7 @@ namespace opengl
pLast->spinEnd = calculate_variation(spinEnd, spinStart, spinVariation);
pLast->rotation = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;;
pLast->color[0] = (float)colorStart[0] / 255;
pLast->color[1] = (float)colorStart[1] / 255;
pLast->color[2] = (float)colorStart[2] / 255;
pLast->color[3] = (float)colorStart[3] / 255;
pLast->color = colors[0];
pLast++;
}
@@ -237,20 +240,13 @@ namespace opengl
void ParticleSystem::setSize(float size)
{
sizeStart = size;
sizeEnd = size;
sizes.resize(1);
sizes[0] = size;
}
void ParticleSystem::setSize(float start, float end)
void ParticleSystem::setSize(const std::vector<float>& newSizes, float variation)
{
sizeStart = start;
sizeEnd = end;
}
void ParticleSystem::setSize(float start, float end, float variation)
{
sizeStart = start;
sizeEnd = end;
sizes = newSizes;
sizeVariation = variation;
}
@@ -294,16 +290,17 @@ namespace opengl
spinVariation = variation;
}
void ParticleSystem::setColor(unsigned char * color)
void ParticleSystem::setColor(const Color& color)
{
memcpy(colorStart, color, 4);
memcpy(colorEnd, color, 4);
colors.resize(1);
colors[0] = colorToFloat(color);
}
void ParticleSystem::setColor(unsigned char * start, unsigned char * end)
void ParticleSystem::setColor(const std::vector<Color>& newColors)
{
memcpy(colorStart, start, 4);
memcpy(colorEnd, end, 4);
colors.resize( newColors.size() );
for (size_t i = 0; i < newColors.size(); ++i)
colors[i] = colorToFloat( newColors[i] );
}
void ParticleSystem::setOffset(float x, float y)
@@ -403,12 +400,8 @@ namespace opengl
{
glPushMatrix();
glColor4f(p->color[0],p->color[1],p->color[2],p->color[3]);
glTranslatef(p->position[0],p->position[1],0.0f);
glRotatef(LOVE_TODEG(p->rotation), 0.0f, 0.0f, 1.0f); // rad * (180 / pi)
glScalef(p->size,p->size,1.0f);
glTranslatef(-offsetX,-offsetY,0.0f);
sprite->draw(0,0, 0, 1, 1, 0, 0);
glColor4f(p->color.r, p->color.g, p->color.b, p->color.a);
sprite->draw(p->position[0], p->position[1], p->rotation, p->size, p->size, offsetX, offsetY);
glPopMatrix();
p++;
@@ -481,19 +474,32 @@ namespace opengl
p->position[0] = ppos.getX();
p->position[1] = ppos.getY();
const float t = p->life / p->lifetime;
// Change size.
p->size = p->sizeEnd - ((p->sizeEnd - p->sizeStart) * t);
const float t = 1.0f - p->life / p->lifetime;
// Rotate.
p->rotation += (p->spinStart*(1-t) + p->spinEnd*t)*dt;
p->rotation += (p->spinStart * (1.0f - t) + p->spinEnd * t)*dt;
// Update color.
p->color[0] = (float)(colorEnd[0]*(1.0f-t) + colorStart[0] * t)/255.0f;
p->color[1] = (float)(colorEnd[1]*(1.0f-t) + colorStart[1] * t)/255.0f;
p->color[2] = (float)(colorEnd[2]*(1.0f-t) + colorStart[2] * t)/255.0f;
p->color[3] = (float)(colorEnd[3]*(1.0f-t) + colorStart[3] * t)/255.0f;
// Change size according to given intervals:
// i = 0 1 2 3 n-1
// |-------|-------|------|--- ... ---|
// t = 0 1/(n-1) 3/(n-1) 1
//
// `s' is the interpolation variable scaled to the current
// interval width, e.g. if n = 5 and t = 0.3, then the current
// indices are 1,2 and s = 0.3 - 0.25 = 0.05
float s = p->sizeOffset + t * p->sizeIntervalSize; // size variation
s *= (float)(sizes.size() - 1); // 0 <= s < sizes.size()
size_t i = (size_t)s;
size_t k = (i == sizes.size() - 1) ? i : i + 1; // boundary check (prevents failing on t = 1.0f)
s -= (float)i; // transpose s to be in interval [0:1]: i <= s < i + 1 ~> 0 <= s < 1
p->size = sizes[i] * (1.0f - t) + sizes[k] * t;
// Update color according to given intervals (as above)
s = t * (float)(colors.size() - 1);
i = (size_t)s;
k = (i == colors.size() - 1) ? i : i + 1;
s -= (float)i; // 0 <= s <= 1
p->color = colors[i] * (1.0f - s) + colors[k] * s;
// Next particle.
p++;
+12 -21
View File
@@ -26,7 +26,9 @@
#include <common/math.h>
#include <common/Vector.h>
#include <graphics/Drawable.h>
#include <graphics/Color.h>
#include "Image.h"
#include <vector>
namespace love
{
@@ -50,14 +52,14 @@ namespace opengl
float tangentialAcceleration;
float size;
float sizeStart;
float sizeEnd;
float sizeOffset;
float sizeIntervalSize;
float rotation;
float spinStart;
float spinEnd;
float color[4];
Colorf color;
};
/**
@@ -127,8 +129,7 @@ namespace opengl
float tangentialAccelerationMax;
// Size.
float sizeStart;
float sizeEnd;
std::vector<float> sizes;
float sizeVariation;
// Rotation
@@ -145,8 +146,7 @@ namespace opengl
float offsetY;
// Color.
unsigned char colorStart[4];
unsigned char colorEnd[4];
std::vector<Colorf> colors;
void add();
void remove(particle * p);
@@ -278,20 +278,12 @@ namespace opengl
**/
void setSize(float size);
/**
* Sets the size of the sprite upon creation and upon death (1.0 being the default size).
* @param start The size of the sprite upon creation
* @param end The size of the sprite upon death.
**/
void setSize(float start, float end);
/**
* Sets the size of the sprite upon creation and upon death (1.0 being the default size) and any variation.
* @param start The size of the sprite upon creation
* @param end The size of the sprite upon death.
* @param newSizes Array of sizes
* @param variation The amount of variation on the starting size (0 being no variation and 1.0 a random size between start and end).
**/
void setSize(float start, float end, float variation);
void setSize(const std::vector<float>& newSizes, float variation = 0.0f);
/**
* Sets the amount of variation to the sprite's beginning size (0 being no variation and 1.0 a random size between start and end).
@@ -343,7 +335,7 @@ namespace opengl
* Sets the color of the particles.
* @param color The color.
**/
void setColor(unsigned char * color);
void setColor(const Color& color);
/**
* Sets the particles' offsets for rotation.
@@ -354,10 +346,9 @@ namespace opengl
/**
* Sets the color of the particles.
* @param start The color of the particle when created.
* @param end The color of the particle upon death.
* @param newColors Array of colors
**/
void setColor(unsigned char * start, unsigned char * end);
void setColor(const std::vector<Color>& newColors);
/**
* Returns the x-coordinate of the emitter's position.
@@ -1,3 +1,4 @@
#include "Graphics.h"
#include "wrap_Framebuffer.h"
namespace love
@@ -105,6 +106,40 @@ namespace opengl
return 2;
}
int w_Framebuffer_clear(lua_State * L)
{
Framebuffer * fbo = luax_checkfbo(L, 1);
Color c;
if (lua_isnoneornil(L, 2)) {
c.r = 0;
c.g = 0;
c.b = 0;
c.a = 0;
} else if (lua_istable(L, 2)) {
lua_pushinteger(L, 1);
lua_gettable(L, 2);
c.r = (unsigned char)luaL_checkint(L, -1);
lua_pushinteger(L, 2);
lua_gettable(L, 2);
c.g = (unsigned char)luaL_checkint(L, -1);
lua_pushinteger(L, 3);
lua_gettable(L, 2);
c.b = (unsigned char)luaL_checkint(L, -1);
lua_pushinteger(L, 4);
lua_gettable(L, 2);
c.g = (unsigned char)luaL_optint(L, -1, 255);
lua_pop(L, 4);
} else {
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);
}
fbo->clear(c);
return 0;
}
static const luaL_Reg functions[] = {
{ "renderTo", w_Framebuffer_renderTo },
{ "getImageData", w_Framebuffer_getImageData },
@@ -112,6 +147,7 @@ namespace opengl
{ "getFilter", w_Framebuffer_getFilter },
{ "setWrap", w_Framebuffer_setWrap },
{ "getWrap", w_Framebuffer_getWrap },
{ "clear", w_Framebuffer_clear },
{ 0, 0 }
};
@@ -19,6 +19,7 @@ namespace opengl
int w_Framebuffer_getFilter(lua_State * L);
int w_Framebuffer_setWrap(lua_State * L);
int w_Framebuffer_getWrap(lua_State * L);
int w_Framebuffer_clear(lua_State * L);
int luaopen_framebuffer(lua_State * L);
} // opengl
@@ -1,47 +0,0 @@
/**
* Copyright (c) 2006-2011 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 "wrap_Glyph.h"
namespace love
{
namespace graphics
{
namespace opengl
{
Glyph * luax_checkglyph(lua_State * L, int idx)
{
return luax_checktype<Glyph>(L, idx, "Glyph", GRAPHICS_GLYPH_T);
}
static const luaL_Reg functions[] = {
{ 0, 0 }
};
int luaopen_glyph(lua_State * L)
{
luax_register_type(L, "Glyph", functions);
return 0;
}
} // opengl
} // graphics
} // love
-41
View File
@@ -1,41 +0,0 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_GRAPHICS_OPENGL_WRAP_GLYPH_H
#define LOVE_GRAPHICS_OPENGL_WRAP_GLYPH_H
// LOVE
#include <common/runtime.h>
#include "Glyph.h"
namespace love
{
namespace graphics
{
namespace opengl
{
Glyph * luax_checkglyph(lua_State * L, int idx);
int luaopen_glyph(lua_State * L);
} // opengl
} // graphics
} // love
#endif // LOVE_GRAPHICS_OPENGL_WRAP_GLYPH_H
+124 -66
View File
@@ -22,7 +22,6 @@
#include <image/ImageData.h>
#include <font/Rasterizer.h>
#include <font/FontData.h>
#include <scripts/graphics.lua.h>
@@ -145,6 +144,33 @@ namespace opengl
return instance->getScissor(L);
}
int w_defineMask(lua_State * L)
{
// just return the function
if (!lua_isfunction(L, 1))
return luaL_typerror(L, 1, "function");
lua_settop(L, 1);
return 1;
}
int w_setMask(lua_State * L)
{
// no argument -> clear mask
if (lua_isnoneornil(L, 1)) {
instance->discardMask();
return 0;
}
if (!lua_isfunction(L, 1))
return luaL_typerror(L, 1, "mask");
instance->defineMask();
lua_call(L, lua_gettop(L) - 1, 0); // call mask(...)
instance->useMask();
return 0;
}
int w_newImage(lua_State * L)
{
// Convert to File, if necessary.
@@ -175,20 +201,6 @@ namespace opengl
return 1;
}
int w_newGlyph(lua_State * L)
{
love::font::GlyphData * data = luax_checktype<love::font::GlyphData>(L, 1, "GlyphData", FONT_GLYPH_DATA_T);
// Create the image.
Glyph * t = new Glyph(data);
t->load();
// Push the type.
luax_newtype(L, "Glyph", GRAPHICS_GLYPH_T, (void*)t);
return 1;
}
int w_newQuad(lua_State * L)
{
int x = luaL_checkint(L, 1);
@@ -234,14 +246,10 @@ namespace opengl
luax_convobj(L, idxs, 2, "font", "newRasterizer");
}
// Convert to FontData, if necessary.
if(luax_istype(L, 1, FONT_RASTERIZER_T))
luax_convobj(L, 1, "font", "newFontData");
love::font::FontData * data = luax_checktype<love::font::FontData>(L, 1, "FontData", FONT_FONT_DATA_T);
love::font::Rasterizer * rasterizer = luax_checktype<love::font::Rasterizer>(L, 1, "Rasterizer", FONT_RASTERIZER_T);
// Create the font.
Font * font = instance->newFont(data);
Font * font = instance->newFont(rasterizer);
if(font == 0)
return luaL_error(L, "Could not load font.");
@@ -274,14 +282,10 @@ namespace opengl
luax_convobj(L, idxs, 2, "font", "newRasterizer");
}
// Convert to FontData, if necessary.
if(luax_istype(L, 1, FONT_RASTERIZER_T))
luax_convobj(L, 1, "font", "newFontData");
love::font::FontData * data = luax_checktype<love::font::FontData>(L, 1, "FontData", FONT_FONT_DATA_T);
love::font::Rasterizer * rasterizer = luax_checktype<love::font::Rasterizer>(L, 1, "Rasterizer", FONT_RASTERIZER_T);
// Create the font.
Font * font = instance->newFont(data, img_filter);
Font * font = instance->newFont(rasterizer, img_filter);
if(font == 0)
return luaL_error(L, "Could not load font.");
@@ -409,14 +413,18 @@ namespace opengl
lua_gettable(L, -2);
c.b = (unsigned char)luaL_checkint(L, -1);
lua_pop(L, 1);
lua_pushinteger(L, 4);
lua_gettable(L, -2);
c.a = (unsigned char)luaL_optint(L, -1, 255);
lua_pop(L, 1);
}
else
{
c.r = (unsigned char)luaL_checkint(L, 1);
c.g = (unsigned char)luaL_checkint(L, 2);
c.b = (unsigned char)luaL_checkint(L, 3);
c.a = (unsigned char)luaL_optint(L, 4, 255);
}
c.a = 255;
instance->setBackgroundColor(c);
return 0;
}
@@ -469,14 +477,10 @@ namespace opengl
luax_convobj(L, idxs, 2, "font", "newRasterizer");
}
// Convert to FontData, if necessary.
if(luax_istype(L, 1, FONT_RASTERIZER_T))
luax_convobj(L, 1, "font", "newFontData");
love::font::FontData * data = luax_checktype<love::font::FontData>(L, 1, "FontData", FONT_FONT_DATA_T);
love::font::Rasterizer * rasterizer = luax_checktype<love::font::Rasterizer>(L, 1, "Rasterizer", FONT_RASTERIZER_T);
// Create the font.
font = instance->newFont(data);
font = instance->newFont(rasterizer);
if(font == 0)
return luaL_error(L, "Could not load font.");
@@ -579,20 +583,6 @@ namespace opengl
return 0;
}
int w_setLineStipple(lua_State * L)
{
if(lua_gettop(L) == 0)
{
instance->setLineStipple();
return 0;
}
unsigned short pattern = (unsigned short)luaL_checkint(L, 1);
int repeat = luaL_optint(L, 2, 1);
instance->setLineStipple(pattern, repeat);
return 0;
}
int w_getLineWidth(lua_State * L)
{
lua_pushnumber(L, instance->getLineWidth());
@@ -608,11 +598,6 @@ namespace opengl
return 1;
}
int w_getLineStipple(lua_State * L)
{
return instance->getLineStipple(L);
}
int w_setPointSize(lua_State * L)
{
float size = (float)luaL_checknumber(L, 1);
@@ -799,15 +784,32 @@ namespace opengl
int w_line(lua_State * L)
{
int args = lua_gettop(L);
if( args == 1 || args > 4) {
instance->polyline(L);
} else {
float x1 = (float)luaL_checknumber(L, 1);
float y1 = (float)luaL_checknumber(L, 2);
float x2 = (float)luaL_checknumber(L, 3);
float y2 = (float)luaL_checknumber(L, 4);
instance->line(x1, y1, x2, y2);
bool is_table = false;
if (args == 1 && lua_istable(L, 1)) {
args = lua_objlen(L, 1);
is_table = true;
}
if (args % 2 != 0)
return luaL_error(L, "Number of vertices must be a multiple of two");
else if (args < 4)
return luaL_error(L, "Need at least two vertices to draw a line");
float* coords = new float[args];
if (is_table) {
for (int i = 0; i < args; ++i) {
lua_pushnumber(L, i + 1);
lua_rawget(L, 1);
coords[i] = lua_tonumber(L, -1);
lua_pop(L, 1);
}
} else {
for (int i = 0; i < args; ++i)
coords[i] = lua_tonumber(L, i + 1);
}
instance->polyline(coords, args);
delete[] coords;
return 0;
}
@@ -876,10 +878,66 @@ namespace opengl
instance->circle(mode, x, y, radius, points);
return 0;
}
int w_arc(lua_State * L)
{
Graphics::DrawMode mode;
const char * str = luaL_checkstring(L, 1);
if(!Graphics::getConstant(str, mode))
return luaL_error(L, "Incorrect draw mode %s", str);
float x = (float)luaL_checknumber(L, 2);
float y = (float)luaL_checknumber(L, 3);
float radius = (float)luaL_checknumber(L, 4);
float angle1 = (float)luaL_checknumber(L, 5);
float angle2 = (float)luaL_checknumber(L, 6);
int points = luaL_optint(L, 7, 10);
instance->arc(mode, x, y, radius, angle1, angle2, points);
return 0;
}
int w_polygon(lua_State * L)
{
return instance->polygon(L);
int args = lua_gettop(L) - 1;
Graphics::DrawMode mode;
const char * str = luaL_checkstring(L, 1);
if(!Graphics::getConstant(str, mode))
return luaL_error(L, "Invalid draw mode: %s", str);
bool is_table = false;
float* coords;
if (args == 1 && lua_istable(L, 2)) {
args = lua_objlen(L, 2);
is_table = true;
}
if (args % 2 != 0)
return luaL_error(L, "Number of vertices must be a multiple of two");
else if (args < 6)
return luaL_error(L, "Need at least three vertices to draw a polygon");
// fetch coords
coords = new float[args + 2];
if (is_table) {
for (int i = 0; i < args; ++i) {
lua_pushnumber(L, i + 1);
lua_rawget(L, 2);
coords[i] = lua_tonumber(L, -1);
lua_pop(L, 1);
}
} else {
for (int i = 0; i < args; ++i)
coords[i] = lua_tonumber(L, i + 2);
}
// make a closed loop
coords[args] = coords[0];
coords[args+1] = coords[1];
instance->polygon(mode, coords, args+2);
delete[] coords;
return 0;
}
int w_push(lua_State *)
@@ -934,7 +992,6 @@ namespace opengl
{ "present", w_present },
{ "newImage", w_newImage },
{ "newGlyph", w_newGlyph },
{ "newQuad", w_newQuad },
{ "newFont1", w_newFont1 },
{ "newImageFont", w_newImageFont },
@@ -957,10 +1014,8 @@ namespace opengl
{ "setLineWidth", w_setLineWidth },
{ "setLineStyle", w_setLineStyle },
{ "setLine", w_setLine },
{ "setLineStipple", w_setLineStipple },
{ "getLineWidth", w_getLineWidth },
{ "getLineStyle", w_getLineStyle },
{ "getLineStipple", w_getLineStipple },
{ "setPointSize", w_setPointSize },
{ "setPointStyle", w_setPointStyle },
{ "setPoint", w_setPoint },
@@ -992,12 +1047,16 @@ namespace opengl
{ "setScissor", w_setScissor },
{ "getScissor", w_getScissor },
{ "defineMask", w_defineMask },
{ "setMask", w_setMask },
{ "point", w_point },
{ "line", w_line },
{ "triangle", w_triangle },
{ "rectangle", w_rectangle },
{ "quad", w_quad },
{ "circle", w_circle },
{ "arc", w_arc },
{ "polygon", w_polygon },
@@ -1017,7 +1076,6 @@ namespace opengl
static const lua_CFunction types[] = {
luaopen_font,
luaopen_image,
luaopen_glyph,
luaopen_frame,
luaopen_spritebatch,
luaopen_particlesystem,
+3 -2
View File
@@ -24,7 +24,6 @@
// LOVE
#include "wrap_Font.h"
#include "wrap_Image.h"
#include "wrap_Glyph.h"
#include "wrap_Quad.h"
#include "wrap_SpriteBatch.h"
#include "wrap_ParticleSystem.h"
@@ -51,8 +50,9 @@ namespace opengl
int w_isCreated(lua_State * L);
int w_setScissor(lua_State * L);
int w_getScissor(lua_State * L);
int w_defineMask(lua_State * L);
int w_setMask(lua_State * L);
int w_newImage(lua_State * L);
int w_newGlyph(lua_State * L);
int w_newQuad(lua_State * L);
int w_newFrame(lua_State * L);
int w_newFont1(lua_State * L);
@@ -96,6 +96,7 @@ namespace opengl
int w_rectangle(lua_State * L);
int w_quad(lua_State * L);
int w_circle(lua_State * L);
int w_arc(lua_State * L);
int w_push(lua_State * L);
int w_pop(lua_State * L);
int w_rotate(lua_State * L);
@@ -143,13 +143,19 @@ namespace opengl
return 0;
}
int w_ParticleSystem_setSize(lua_State * L)
int w_ParticleSystem_setSizes(lua_State * L)
{
ParticleSystem * t = luax_checkparticlesystem(L, 1);
float arg1 = (float)luaL_checknumber(L, 2);
float arg2 = (float)luaL_optnumber(L, 3, arg1);
float arg3 = (float)luaL_optnumber(L, 4, 0);
t->setSize(arg1, arg2, arg3);
size_t nSizes = lua_gettop(L) - 1;
if (nSizes == 1) {
t->setSize(luaL_checknumber(L, 2));
} else {
std::vector<float> sizes(nSizes);
for (size_t i = 0; i < nSizes; ++i)
sizes[i] = luaL_checknumber(L, 1 + i + 1);
t->setSize(sizes);
}
return 0;
}
@@ -188,28 +194,26 @@ namespace opengl
return 0;
}
int w_ParticleSystem_setColor(lua_State * L)
int w_ParticleSystem_setColors(lua_State * L)
{
ParticleSystem * t = luax_checkparticlesystem(L, 1);
unsigned char start[4];
size_t nColors = (lua_gettop(L) - 1) / 4;
start[0] = (unsigned char)luaL_checkint(L, 2);
start[1] = (unsigned char)luaL_checkint(L, 3);
start[2] = (unsigned char)luaL_checkint(L, 4);
start[3] = (unsigned char)luaL_checkint(L, 5);
if(lua_gettop(L) > 5)
{
unsigned char end[4];
end[0] = (unsigned char)luaL_checkint(L, 6);
end[1] = (unsigned char)luaL_checkint(L, 7);
end[2] = (unsigned char)luaL_checkint(L, 8);
end[3] = (unsigned char)luaL_checkint(L, 9);
t->setColor(start, end);
if (nColors == 1) {
t->setColor(Color(luaL_checkint(L,2),
luaL_checkint(L,3),
luaL_checkint(L,4),
luaL_checkint(L,5)));
} else {
std::vector<Color> colors(nColors);
for (size_t i = 0; i < nColors; ++i) {
colors[i] = Color(luaL_checkint(L, 1 + i*4 + 1),
luaL_checkint(L, 1 + i*4 + 2),
luaL_checkint(L, 1 + i*4 + 3),
luaL_checkint(L, 1 + i*4 + 4));
}
t->setColor(colors);
}
else
t->setColor(start);
return 0;
}
@@ -343,12 +347,12 @@ namespace opengl
{ "setGravity", w_ParticleSystem_setGravity },
{ "setRadialAcceleration", w_ParticleSystem_setRadialAcceleration },
{ "setTangentialAcceleration", w_ParticleSystem_setTangentialAcceleration },
{ "setSize", w_ParticleSystem_setSize },
{ "setSizes", w_ParticleSystem_setSizes },
{ "setSizeVariation", w_ParticleSystem_setSizeVariation },
{ "setRotation", w_ParticleSystem_setRotation },
{ "setSpin", w_ParticleSystem_setSpin },
{ "setSpinVariation", w_ParticleSystem_setSpinVariation },
{ "setColor", w_ParticleSystem_setColor },
{ "setColors", w_ParticleSystem_setColors },
{ "setOffset", w_ParticleSystem_setOffset },
{ "getX", w_ParticleSystem_getX },
{ "getY", w_ParticleSystem_getY },
@@ -46,12 +46,12 @@ namespace opengl
int w_ParticleSystem_setGravity(lua_State * L);
int w_ParticleSystem_setRadialAcceleration(lua_State * L);
int w_ParticleSystem_setTangentialAcceleration(lua_State * L);
int w_ParticleSystem_setSize(lua_State * L);
int w_ParticleSystem_setSizes(lua_State * L);
int w_ParticleSystem_setSizeVariation(lua_State * L);
int w_ParticleSystem_setRotation(lua_State * L);
int w_ParticleSystem_setSpin(lua_State * L);
int w_ParticleSystem_setSpinVariation(lua_State * L);
int w_ParticleSystem_setColor(lua_State * L);
int w_ParticleSystem_setColors(lua_State * L);
int w_ParticleSystem_setOffset(lua_State * L);
int w_ParticleSystem_getX(lua_State * L);
int w_ParticleSystem_getY(lua_State * L);
-77
View File
@@ -1,77 +0,0 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "EncodedImageData.h"
namespace love
{
namespace image
{
EncodedImageData::EncodedImageData(void * d, Format f, int s)
: data(d), size(s), format(f), freeData(0)
{
}
EncodedImageData::EncodedImageData(void * d, Format f, int s, void (*freeData)(void*))
: data(d), size(s), format(f), freeData(freeData)
{
}
EncodedImageData::~EncodedImageData()
{
if (freeData != 0)
freeData(data);
}
void * EncodedImageData::getData() const
{
return data;
}
EncodedImageData::Format EncodedImageData::getFormat() const
{
return format;
}
int EncodedImageData::getSize() const
{
return size;
}
bool EncodedImageData::getConstant(const char * in, EncodedImageData::Format & out)
{
return formats.find(in, out);
}
bool EncodedImageData::getConstant(EncodedImageData::Format in, const char *& out)
{
return formats.find(in, out);
}
StringMap<EncodedImageData::Format, EncodedImageData::FORMAT_MAX_ENUM>::Entry EncodedImageData::formatEntries[] =
{
{"tga", EncodedImageData::FORMAT_TGA},
{"bmp", EncodedImageData::FORMAT_BMP},
};
StringMap<EncodedImageData::Format, EncodedImageData::FORMAT_MAX_ENUM> EncodedImageData::formats(EncodedImageData::formatEntries, sizeof(EncodedImageData::formatEntries));
} // image
} // love
-96
View File
@@ -1,96 +0,0 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_IMAGE_ENCODED_IMAGE_DATA_H
#define LOVE_IMAGE_ENCODED_IMAGE_DATA_H
// LOVE
#include <common/Data.h>
#include <common/StringMap.h>
namespace love
{
namespace image
{
/**
* Represents encoded pixel data.
**/
class EncodedImageData : public Data
{
public:
enum Format
{
FORMAT_TGA = 1,
FORMAT_BMP,
FORMAT_MAX_ENUM
};
/**
* Constructor.
**/
EncodedImageData(void * data, Format format, int size);
EncodedImageData(void * data, Format format, int size, void (*freeData)(void*));
/**
* Destructor.
**/
virtual ~EncodedImageData();
// Implements Data.
void * getData() const;
int getSize() const;
/**
* Get the format the data is encoded in.
**/
Format getFormat() const;
static bool getConstant(const char * in, Format & out);
static bool getConstant(Format in, const char *& out);
private:
/**
* Actual data.
**/
void * data;
/**
* Size of the data.
**/
int size;
/**
* Image format.
**/
Format format;
static StringMap<Format, FORMAT_MAX_ENUM>::Entry formatEntries[];
static StringMap<Format, FORMAT_MAX_ENUM> formats;
void (*freeData)(void *data);
}; // EncodedImageData
} // image
} // love
#endif // LOVE_IMAGE_ENCODED_IMAGE_DATA_H
+21
View File
@@ -45,6 +45,27 @@ namespace image
{
return (x >= 0 && x < getWidth() && y >= 0 && y < getHeight());
}
bool ImageData::getConstant(const char * in, ImageData::Format & out)
{
return formats.find(in, out);
}
bool ImageData::getConstant(ImageData::Format in, const char *& out)
{
return formats.find(in, out);
}
StringMap<ImageData::Format, ImageData::FORMAT_MAX_ENUM>::Entry ImageData::formatEntries[] =
{
{"tga", ImageData::FORMAT_TGA},
{"bmp", ImageData::FORMAT_BMP},
{"gif", ImageData::FORMAT_GIF},
{"jpg", ImageData::FORMAT_JPG},
{"png", ImageData::FORMAT_PNG},
};
StringMap<ImageData::Format, ImageData::FORMAT_MAX_ENUM> ImageData::formats(ImageData::formatEntries, sizeof(ImageData::formatEntries));
} // image
} // love
+19 -3
View File
@@ -23,8 +23,7 @@
// LOVE
#include <common/Data.h>
#include "EncodedImageData.h"
#include <filesystem/File.h>
namespace love
{
@@ -43,11 +42,24 @@ namespace image
class ImageData : public Data
{
public:
enum Format
{
FORMAT_TGA = 1,
FORMAT_BMP,
FORMAT_GIF,
FORMAT_JPG,
FORMAT_PNG,
FORMAT_MAX_ENUM
};
/**
* Destructor.
**/
virtual ~ImageData(){};
static bool getConstant(const char * in, Format & out);
static bool getConstant(Format in, const char *& out);
/**
* Paste part of one ImageData onto another. The subregion defined by the top-left
@@ -102,7 +114,11 @@ namespace image
* @param f The format to convert to.
* @return A pointer to the encoded image data.
**/
virtual EncodedImageData * encode(EncodedImageData::Format f) = 0;
virtual void encode(love::filesystem::File * f, Format format) = 0;
private:
static StringMap<Format, FORMAT_MAX_ENUM>::Entry formatEntries[];
static StringMap<Format, FORMAT_MAX_ENUM> formats;
}; // ImageData
+26 -97
View File
@@ -25,6 +25,7 @@
// LOVE
#include <common/Exception.h>
#include <filesystem/File.h>
namespace love
{
@@ -191,106 +192,34 @@ namespace devil
return pixels[y*width+x];
}
EncodedImageData * ImageData::encode(EncodedImageData::Format f) {
void ImageData::encode(love::filesystem::File * f, ImageData::Format format) {
ilBindImage(image);
ILubyte * data;
ILuint w = getWidth();
int h = getHeight(); // has to be a signed int so we can make it negative for BMPs
int headerLen, bpp, row, size, padding, filesize;
switch (f) {
case EncodedImageData::FORMAT_BMP:
headerLen = 54;
bpp = 3;
row = w * bpp;
padding = row & 3;
size = h * (row + padding);
filesize = size + headerLen;
data = new ILubyte[filesize];
// Here's the header for the BMP file format.
data[0] = 66; // "B"
data[1] = 77; // "M"
data[2] = filesize & 255; // size of the file
data[3] = (filesize >> 8) & 255;
data[4] = (filesize >> 16) & 255;
data[5] = (filesize >> 24) & 255;
data[6] = data[7] = data[8] = data[9] = 0; // useless reserved values
data[10] = headerLen; // offset where pixel data begins
data[11] = (headerLen >> 8) & 255;
data[12] = (headerLen >> 16) & 255;
data[13] = (headerLen >> 24) & 255;
data[14] = headerLen - 14; // length of this part of the header
data[15] = ((headerLen - 14) >> 8) & 255;
data[16] = ((headerLen - 14) >> 16) & 255;
data[17] = ((headerLen - 14) >> 24) & 255;
data[18] = w & 255; // width of the bitmap
data[19] = (w >> 8) & 255;
data[20] = (w >> 16) & 255;
data[21] = (w >> 24) & 255;
data[22] = -h & 255; // negative height of the bitmap - used so we don't have to flip the data
data[23] = ((-h) >> 8) & 255;
data[24] = ((-h) >> 16) & 255;
data[25] = ((-h) >> 24) & 255;
data[26] = 1; // number of color planes
data[27] = 0;
data[28] = bpp * 8; // bits per pixel
data[29] = 0;
data[30] = data[31] = data[32] = data[33] = 0; // RGB - no compression
data[34] = (row + padding) * h; // length of the pixel data
data[35] = (((row + padding) * h) >> 8) & 255;
data[36] = (((row + padding) * h) >> 16) & 255;
data[37] = (((row + padding) * h) >> 24) & 255;
data[38] = 2835 & 255; // horizontal pixels per meter
data[39] = (2835 >> 8) & 255;
data[40] = (2835 >> 16) & 255;
data[41] = (2835 >> 24) & 255;
data[42] = 2835 & 255; // vertical pixels per meter
data[43] = data[39];
data[44] = data[40];
data[45] = data[41];
data[46] = data[47] = data[48] = data[49] = 0; // number of colors in the palette
data[50] = data[51] = data[52] = data[53] = 0; // all colors are important!
// Okay, header's done! Now for the pixel data...
data += headerLen;
for (int i = 0; i < h; i++) { // we've got to loop through the rows, adding the pixel data plus padding
ilCopyPixels(0,i,0,w,1,1,IL_BGR,IL_UNSIGNED_BYTE,data);
data += row;
}
data -= filesize;
ILuint ilFormat;
switch (format) {
case ImageData::FORMAT_BMP:
ilFormat = IL_BMP;
break;
case ImageData::FORMAT_TGA:
ilFormat = IL_TGA;
break;
case ImageData::FORMAT_GIF:
ilFormat = IL_GIF;
break;
case ImageData::FORMAT_JPG:
ilFormat = IL_JPG;
break;
case ImageData::FORMAT_PNG:
default: // PNG is the default format
ilFormat = IL_PNG;
break;
case EncodedImageData::FORMAT_TGA:
default: // TGA is the default format
headerLen = 18;
bpp = 4;
size = h * w * bpp;
data = new ILubyte[size + headerLen];
// here's the header for the Targa file format.
data[0] = 0; // ID field size
data[1] = 0; // colormap type
data[2] = 2; // image type
data[3] = data[4] = 0; // colormap start
data[5] = data[6] = 0; // colormap length
data[7] = 32; // colormap bits
data[8] = data[9] = 0; // x origin
data[10] = data[11] = 0; // y origin
// Targa is little endian, so:
data[12] = w & 255; // least significant byte of width
data[13] = w >> 8; // most significant byte of width
data[14] = h & 255; // least significant byte of height
data[15] = h >> 8; // most significant byte of height
data[16] = bpp * 8; // bits per pixel
data[17] = 0x20; // descriptor bits (flip bits: 0x10 horizontal, 0x20 vertical)
// header done. write the pixel data to TGA:
data += headerLen;
ilCopyPixels(0,0,0,w,h,1,IL_BGRA,IL_UNSIGNED_BYTE,data); // convert the pixels to BGRA (remember, little-endian) and copy them to data
data -= headerLen;
}
return new EncodedImageData(data, f, size + headerLen, freeData);
}
void ImageData::freeData(void *data)
{
delete[] (ILubyte*) data;
ILuint size = ilSaveL(ilFormat, NULL, 0);
ILubyte * data = new ILubyte[size];
ilSaveL(ilFormat, data, size);
f->open(love::filesystem::File::WRITE);
f->write(data, size);
f->close();
delete[] data;
}
} // devil
+1 -4
View File
@@ -25,7 +25,6 @@
#include <filesystem/File.h>
#include <image/Image.h>
#include <image/ImageData.h>
#include <image/EncodedImageData.h>
// DevIL
#include <IL/il.h>
@@ -77,9 +76,7 @@ namespace devil
int getHeight() const ;
void setPixel(int x, int y, pixel c);
pixel getPixel(int x, int y) const;
EncodedImageData * encode(EncodedImageData::Format f);
static void freeData(void *data);
void encode(love::filesystem::File * f, Format format);
}; // ImageData
@@ -1,59 +0,0 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "wrap_ImageData.h"
#include <common/wrap_Data.h>
namespace love
{
namespace image
{
EncodedImageData * luax_checkencodedimagedata(lua_State * L, int idx)
{
return luax_checktype<EncodedImageData>(L, idx, "EncodedImageData", IMAGE_ENCODED_IMAGE_DATA_T);
}
int w_EncodedImageData_getFormat(lua_State * L) {
EncodedImageData * e = luax_checkencodedimagedata(L, 1);
EncodedImageData::Format f = e->getFormat();
const char * fmt;
EncodedImageData::getConstant(f, fmt);
lua_pushstring(L, fmt);
return 1;
}
static const luaL_Reg functions[] = {
// Data
{ "getPointer", w_Data_getPointer },
{ "getSize", w_Data_getSize },
{ "getFormat", w_EncodedImageData_getFormat },
{ 0, 0 }
};
int luaopen_encodedimagedata(lua_State * L)
{
return luax_register_type(L, "EncodedImageData", functions);
}
} // image
} // love
-40
View File
@@ -1,40 +0,0 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_IMAGE_WRAP_ENCODED_IMAGE_DATA_H
#define LOVE_IMAGE_WRAP_ENCODED_IMAGE_DATA_H
// LOVE
#include <common/runtime.h>
#include "ImageData.h"
namespace love
{
namespace image
{
EncodedImageData * luax_checkencodedimagedata(lua_State * L, int idx);
int w_EncodedImageData_getFormat(lua_State * L);
int luaopen_encodedimagedata(lua_State * L);
} // image
} // love
#endif // LOVE_IMAGE_WRAP_ENCODED_IMAGE_DATA_H
-16
View File
@@ -20,14 +20,10 @@
#include "wrap_Image.h"
#include "EncodedImageData.h"
#include "wrap_EncodedImageData.h"
#include <common/Data.h>
#include <common/StringMap.h>
#include "devil/Image.h"
#include "devil/ImageData.h"
namespace love
{
@@ -84,27 +80,15 @@ namespace image
luax_newtype(L, "ImageData", IMAGE_IMAGE_DATA_T, (void*)t);
return 1;
}
int w_newEncodedImageData(lua_State * L) {
ImageData * t = luax_checkimagedata(L, 1);
const char * fmt = luaL_checkstring(L, 2);
EncodedImageData::Format f;
EncodedImageData::getConstant(fmt, f);
EncodedImageData * eid = t->encode(f);
luax_newtype(L, "EncodedImageData", IMAGE_ENCODED_IMAGE_DATA_T, (void*)eid);
return 1;
}
// List of functions to wrap.
static const luaL_Reg functions[] = {
{ "newImageData", w_newImageData },
{ "newEncodedImageData", w_newEncodedImageData },
{ 0, 0 }
};
static const lua_CFunction types[] = {
luaopen_imagedata,
luaopen_encodedimagedata,
0
};
-1
View File
@@ -31,7 +31,6 @@ namespace image
{
int w_getFormats(lua_State * L);
int w_newImageData(lua_State * L);
int w_newEncodedImageData(lua_State * L);
extern "C" LOVE_EXPORT int luaopen_love_image(lua_State * L);
} // image
+14 -6
View File
@@ -21,6 +21,7 @@
#include "wrap_ImageData.h"
#include <common/wrap_Data.h>
#include <filesystem/File.h>
namespace love
{
@@ -130,12 +131,19 @@ namespace image
int w_ImageData_encode(lua_State * L)
{
ImageData * t = luax_checkimagedata(L, 1);
const char * fmt = luaL_checkstring(L, 2);
EncodedImageData::Format f;
EncodedImageData::getConstant(fmt, f);
EncodedImageData * eid = t->encode(f);
luax_newtype(L, "EncodedImageData", IMAGE_ENCODED_IMAGE_DATA_T, (void*)eid);
return 1;
if(lua_isstring(L, 2))
luax_convobj(L, 2, "filesystem", "newFile");
love::filesystem::File * file = luax_checktype<love::filesystem::File>(L, 2, "File", FILESYSTEM_FILE_T);
const char * fmt;
if (lua_isnoneornil(L, 3)) {
fmt = file->getExtension().c_str();
} else {
fmt = luaL_checkstring(L, 3);
}
ImageData::Format format;
ImageData::getConstant(fmt, format);
t->encode(file, format);
return 0;
}
static const luaL_Reg functions[] = {
+14 -14
View File
@@ -36,57 +36,57 @@ namespace sdl
int w_getName(lua_State * L)
{
int index = luaL_checkint(L, 1);
int index = luaL_checkint(L, 1)-1;
lua_pushstring(L, instance->getName(index));
return 1;
}
int w_open(lua_State * L)
{
int index = luaL_checkint(L, 1);
int index = luaL_checkint(L, 1)-1;
luax_pushboolean(L, instance->open(index));
return 1;
}
int w_isOpen(lua_State * L)
{
int index = luaL_checkint(L, 1);
int index = luaL_checkint(L, 1)-1;
luax_pushboolean(L, instance->isOpen(index));
return 1;
}
int w_getNumAxes(lua_State * L)
{
int index = luaL_checkint(L, 1);
int index = luaL_checkint(L, 1)-1;
lua_pushinteger(L, instance->getNumAxes(index));
return 1;
}
int w_getNumBalls(lua_State * L)
{
int index = luaL_checkint(L, 1);
int index = luaL_checkint(L, 1)-1;
lua_pushinteger(L, instance->getNumBalls(index));
return 1;
}
int w_getNumButtons(lua_State * L)
{
int index = luaL_checkint(L, 1);
int index = luaL_checkint(L, 1)-1;
lua_pushinteger(L, instance->getNumButtons(index));
return 1;
}
int w_getNumHats(lua_State * L)
{
int index = luaL_checkint(L, 1);
int index = luaL_checkint(L, 1)-1;
lua_pushinteger(L, instance->getNumHats(index));
return 1;
}
int w_getAxis(lua_State * L)
{
int index = luaL_checkint(L, 1);
int axis = luaL_checkint(L, 2);
int index = luaL_checkint(L, 1)-1;
int axis = luaL_checkint(L, 2)-1;
lua_pushnumber(L, instance->getAxis(index, axis));
return 1;
}
@@ -103,14 +103,14 @@ namespace sdl
int w_isDown(lua_State * L)
{
int index = luaL_checkint(L, 1);
int index = luaL_checkint(L, 1)-1;
unsigned int num = lua_gettop(L);
int * buttonlist = new int[num];
unsigned int counter = 0;
for (unsigned int i = 1; i < num; i++)
{
buttonlist[counter++] = (int) luaL_checknumber(L, i+1);
buttonlist[counter++] = (int) luaL_checknumber(L, i+1)-1;
}
buttonlist[counter] = -1;
@@ -121,8 +121,8 @@ namespace sdl
int w_getHat(lua_State * L)
{
int index = luaL_checkint(L, 1);
int hat = luaL_checkint(L, 2);
int index = luaL_checkint(L, 1)-1;
int hat = luaL_checkint(L, 2)-1;
Joystick::Hat h = instance->getHat(index, hat);
@@ -135,7 +135,7 @@ namespace sdl
int w_close(lua_State * L)
{
int index = luaL_checkint(L, 1);
int index = luaL_checkint(L, 1)-1;
instance->close(index);
return 0;
}
+2 -2
View File
@@ -163,12 +163,12 @@ namespace lullaby
bool Mpg123Decoder::seek(float s)
{
off_t offset = mpg123_timeframe(handle, s);
off_t offset = s * sampleRate;
if(offset < 0)
return false;
if(mpg123_feedseek(handle, 0, SEEK_SET, &offset) >= 0)
if(mpg123_feedseek(handle, offset, SEEK_SET, &offset) >= 0)
{
data_offset = offset;
eof = false;
+2 -2
View File
@@ -249,7 +249,7 @@ namespace sdl
return name;
}
ThreadVariant *Thread::receive(const std::string & name)
ThreadVariant *Thread::get(const std::string & name)
{
ThreadVariant *v = comm->getValue(name);
if (v)
@@ -276,7 +276,7 @@ namespace sdl
comm->clearValue(name);
}
void Thread::send(const std::string & name, ThreadVariant *v)
void Thread::set(const std::string & name, ThreadVariant *v)
{
lock(); //this function explicitly locks
comm->setValue(name, v); //because we need
+2 -2
View File
@@ -115,10 +115,10 @@ namespace sdl
void kill();
void wait();
std::string getName();
ThreadVariant *receive(const std::string & name);
ThreadVariant *get(const std::string & name);
ThreadVariant *demand(const std::string & name);
void clear(const std::string & name);
void send(const std::string & name, ThreadVariant *v);
void set(const std::string & name, ThreadVariant *v);
void lock();
void unlock();
}; // Thread
+8 -10
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
* Copyright (c) 2006-2010 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
@@ -72,12 +72,12 @@ namespace sdl
return 1;
}
int w_Thread_receive(lua_State *L)
int w_Thread_get(lua_State *L)
{
Thread *t = luax_checkthread(L, 1);
std::string name = luax_checklstring(L, 2);
t->lock();
ThreadVariant *v = t->receive(name);
ThreadVariant *v = t->get(name);
t->clear(name);
t->unlock();
if (!v)
@@ -167,7 +167,7 @@ namespace sdl
Thread *t = luax_checkthread(L, 1);
std::string name = luax_checklstring(L, 2);
t->lock();
ThreadVariant *v = t->receive(name);
ThreadVariant *v = t->get(name);
t->unlock();
if (!v)
{
@@ -222,7 +222,7 @@ namespace sdl
return t;
}
int w_Thread_send(lua_State *L)
int w_Thread_set(lua_State *L)
{
Thread *t = luax_checkthread(L, 1);
std::string name = luax_checklstring(L, 2);
@@ -253,10 +253,8 @@ namespace sdl
{
return luaL_error(L, "Expected boolean, number, string or userdata");
}
t->send(name, v);
t->lock();
t->set(name, v);
v->release();
t->unlock();
return 0;
}
@@ -265,10 +263,10 @@ namespace sdl
{ "kill", w_Thread_kill },
{ "wait", w_Thread_wait },
{ "getName", w_Thread_getName },
{ "receive", w_Thread_receive },
{ "get", w_Thread_get },
{ "demand", w_Thread_demand },
{ "peek", w_Thread_peek },
{ "send", w_Thread_send },
{ "set", w_Thread_set },
{ 0, 0 }
};
+2 -2
View File
@@ -37,10 +37,10 @@ namespace sdl
int w_Thread_kill(lua_State *L);
int w_Thread_wait(lua_State *L);
int w_Thread_getName(lua_State *L);
int w_Thread_receive(lua_State *L);
int w_Thread_get(lua_State *L);
int w_Thread_demand(lua_State *L);
int w_Thread_peek(lua_State *L);
int w_Thread_send(lua_State *L);
int w_Thread_set(lua_State *L);
int luaopen_thread(lua_State *L);