Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
136 KB
Referenced Files
None
Subscribers
None
diff --git a/include/r-tech1/debug.h b/include/r-tech1/debug.h
index 3995902a..b3151ba8 100644
--- a/include/r-tech1/debug.h
+++ b/include/r-tech1/debug.h
@@ -1,116 +1,118 @@
#ifndef _rtech1_debug_h
#define _rtech1_debug_h
#include <ostream>
#include <sstream>
#include <stdint.h>
#define PAINTOWN_DEBUG_CONTEXT Global::debug_context(__FILE__, __LINE__)
#define _xdebug Global::debug(0, PAINTOWN_DEBUG_CONTEXT)
/* Enable this if you can't get regular debug output but have networking
*/
// #define NETWORK_DEBUG
namespace Global{
#ifdef ANDROID
class android_ostream: public std::ostream {
public:
android_ostream(bool enabled = true);
static android_ostream stream;
/* make these private at some point */
public:
bool enabled;
std::ostringstream buffer;
};
typedef android_ostream stream_type;
android_ostream & operator<<(android_ostream & stream, const std::string & input);
android_ostream & operator<<(android_ostream & stream, const char * input);
android_ostream & operator<<(android_ostream & stream, const char);
android_ostream & operator<<(android_ostream & stream, const double);
android_ostream & operator<<(android_ostream & stream, const int);
android_ostream & operator<<(android_ostream & stream, const short int);
android_ostream & operator<<(android_ostream & stream, const short unsigned int);
android_ostream & operator<<(android_ostream & stream, const unsigned int);
android_ostream & operator<<(android_ostream & stream, const bool);
android_ostream & operator<<(android_ostream & stream, const long int);
android_ostream & operator<<(android_ostream & stream, const unsigned long int);
+android_ostream & operator<<(android_ostream & stream, const uint64_t);
android_ostream & operator<<(android_ostream & stream, const void *);
+android_ostream & operator<<(android_ostream & stream, const double);
android_ostream & operator<<(android_ostream & stream, std::ostream & (*f)(std::ostream &));
#elif defined(WII) && defined(DEBUG)
class wii_ostream: public std::ostream {
public:
wii_ostream(bool enabled = true);
static wii_ostream stream;
/* make these private at some point */
public:
bool enabled;
std::ostringstream buffer;
};
typedef wii_ostream stream_type;
wii_ostream & operator<<(wii_ostream & stream, const std::string & input);
wii_ostream & operator<<(wii_ostream & stream, const char * input);
wii_ostream & operator<<(wii_ostream & stream, const char);
wii_ostream & operator<<(wii_ostream & stream, const double);
wii_ostream & operator<<(wii_ostream & stream, const int);
wii_ostream & operator<<(wii_ostream & stream, const short int);
wii_ostream & operator<<(wii_ostream & stream, const short unsigned int);
wii_ostream & operator<<(wii_ostream & stream, const unsigned int);
wii_ostream & operator<<(wii_ostream & stream, const bool);
wii_ostream & operator<<(wii_ostream & stream, const long int);
wii_ostream & operator<<(wii_ostream & stream, const unsigned long int);
wii_ostream & operator<<(wii_ostream & stream, const void *);
wii_ostream & operator<<(wii_ostream & stream, uint64_t);
wii_ostream & operator<<(wii_ostream & stream, std::ostream & (*f)(std::ostream &));
#elif defined(NETWORK_DEBUG)
class network_ostream: public std::ostream {
public:
network_ostream(const std::string & host, int port, bool enabled = true);
static network_ostream stream;
/* make these private at some point */
public:
std::string host;
int port;
bool enabled;
std::ostringstream buffer;
};
typedef network_ostream stream_type;
stream_type & operator<<(stream_type & stream, const std::string & input);
stream_type & operator<<(stream_type & stream, const char * input);
stream_type & operator<<(stream_type & stream, const char);
stream_type & operator<<(stream_type & stream, const double);
stream_type & operator<<(stream_type & stream, const int);
stream_type & operator<<(stream_type & stream, const short int);
stream_type & operator<<(stream_type & stream, const short unsigned int);
stream_type & operator<<(stream_type & stream, const unsigned int);
stream_type & operator<<(stream_type & stream, const bool);
stream_type & operator<<(stream_type & stream, const long int);
#ifndef PS3
stream_type & operator<<(stream_type & stream, const unsigned long int);
#endif
stream_type & operator<<(stream_type & stream, const void *);
stream_type & operator<<(stream_type & stream, uint64_t);
stream_type & operator<<(stream_type & stream, std::ostream & (*f)(std::ostream &));
#else
typedef std::ostream stream_type;
#endif
void logToFile();
void closeLog();
void setDebug(int i);
int getDebug();
void setLogFile(const std::string &);
const std::string & getLogFile();
extern std::string defaultDebugContext;
void setDefaultDebugContext(const std::string & context);
stream_type & debug(int i, const std::string & context = defaultDebugContext);
std::string debug_context(const char * file, int line);
}
#endif
diff --git a/include/r-tech1/graphics/bitmap.h b/include/r-tech1/graphics/bitmap.h
index 24bb83c5..de132d41 100644
--- a/include/r-tech1/graphics/bitmap.h
+++ b/include/r-tech1/graphics/bitmap.h
@@ -1,790 +1,793 @@
#ifndef _rtech1_bitmap_h_
#define _rtech1_bitmap_h_
#include "../exceptions/exception.h"
#include "../pointer.h"
#include "../parameter.h"
#include <string>
#include <vector>
#include <map>
#include <iostream>
#ifdef USE_ALLEGRO
#include "allegro/bitmap.h"
#endif
#ifdef USE_SDL
#include "sdl/bitmap.h"
#endif
#ifdef USE_ALLEGRO5
#include "allegro5/bitmap.h"
struct ALLEGRO_SHADER;
#endif
#include "color.h"
#if !defined(USE_ALLEGRO) && !defined(USE_SDL) && !defined(USE_ALLEGRO5)
#error No backend specified. Define one of USE_ALLEGRO, USE_SDL, or USE_ALLEGRO5
#endif
namespace Storage{
class File;
}
namespace Graphics{
class Bitmap;
class Color{
public:
explicit Color(const INTERNAL_COLOR & color):
color(color){
}
static INTERNAL_COLOR defaultColor();
Color():
color(defaultColor()){
}
Color & operator=(const Color & him){
this->color = him.color;
return *this;
}
bool operator==(const Color & him) const {
return color == him.color;
}
bool operator!=(const Color & him) const {
return !(*this == him);
}
bool operator<(const Color & him) const {
return this->color < him.color;
}
INTERNAL_COLOR color;
};
enum ImageFormat{
FormatPNG,
FormatBMP,
FormatJPG,
FormatPCX,
FormatTGA,
FormatTIF,
FormatXPM,
FormatGIF,
FormatUnknown
};
ImageFormat identifyImage(const unsigned char * data, int length);
class TranslucentBitmap;
class LitBitmap;
class Bitmap;
extern Util::Parameter<Bitmap*> screenParameter;
extern const int SPRITE_NORMAL;
extern const int SPRITE_LIT;
extern const int SPRITE_TRANS;
extern const int SPRITE_NO_FLIP;
extern const int SPRITE_V_FLIP;
extern const int SPRITE_H_FLIP;
/*
extern int SCALE_X;
extern int SCALE_Y;
*/
class BitmapException: public Exception::Base {
public:
BitmapException(const std::string & file, int line, const std::string & reason):
Base(file, line),
reason(reason){
}
BitmapException(const BitmapException & copy):
Base(copy),
reason(copy.reason){
}
virtual void throwSelf() const {
throw *this;
}
virtual ~BitmapException() throw () {
}
protected:
virtual const std::string getReason() const {
return reason;
}
std::string reason;
};
/* create a color from components */
Color makeColor(int r, int g, int b);
Color darken(Color color, double factor);
void hsvToRGB( float h, float s, float v, int * r, int * g, int * b );
int setGfxModeText();
int setGfxModeFullscreen( int x, int y );
int setGfxModeWindowed( int x, int y );
/* Only call this method once, from init. After that call changeGraphicsMode */
int setGraphicsMode(int mode, int width, int height);
int changeGraphicsMode(int mode, int width, int height);
/* get color components */
int getRed(Color x);
int getBlue(Color x);
int getGreen(Color x);
int getAlpha(Color x);
Color MaskColor();
enum QualityFilter{
NoFilter,
HqxFilter,
XbrFilter
};
QualityFilter qualityFilterName(const std::string & type);
/* FIXME: try to move the shader stuff to shader.h */
class Shader{
public:
Shader();
virtual ~Shader();
#ifdef USE_ALLEGRO5
Shader(ALLEGRO_SHADER * shader);
ALLEGRO_SHADER * getShader();
ALLEGRO_SHADER * shader;
#endif
};
class ShaderManager{
public:
ShaderManager();
Util::ReferenceCount<Shader> getShader(const std::string & name, Util::ReferenceCount<Shader> (*create)());
virtual ~ShaderManager();
protected:
std::map<std::string, Util::ReferenceCount<Shader> > shaders;
};
extern Util::Parameter<Util::ReferenceCount<ShaderManager> > shaderManager;
#ifdef USE_ALLEGRO5
Util::ReferenceCount<Shader> create_shader(const std::string & version, const std::string & vertex, const std::string & pixel);
void setShaderSampler(ALLEGRO_SHADER * shader, const std::string & name, const Bitmap & texture, int unit);
void setShaderBool(ALLEGRO_SHADER * shader, const std::string & name, bool value);
void setShaderInt(ALLEGRO_SHADER * shader, const std::string & name, int value);
void setShaderFloat(ALLEGRO_SHADER * shader, const std::string & name, float value);
void setShaderVec4(ALLEGRO_SHADER * shader, const std::string & name, float v1, float v2, float v3, float v4);
std::string defaultVertexShader();
std::string defaultPixelShader();
#endif
class Bitmap{
private:
/* these constructors don't really matter, get rid of them at some point */
Bitmap( const Bitmap & copy, int sx, int sy, double accuracy );
Bitmap( const char * load_file, int sx, int sy, double accuracy );
public:
/* equivalent to a GPU shader */
class Filter{
public:
virtual Color filter(Color pixel) const = 0;
/* getShader should only return the Shader object and not set any uniforms/attributes */
virtual Util::ReferenceCount<Shader> getShader() = 0;
/* set the uniforms/attributes */
virtual void setupShader(const Util::ReferenceCount<Shader> &) = 0;
virtual ~Filter(){
}
};
/* default constructor makes 10x10 bitmap */
Bitmap();
Bitmap( int x, int y );
Bitmap( const char * load_file );
Bitmap(const char * data, int length);
Bitmap( const std::string & load_file );
Bitmap( const char * load_file, int sx, int sy );
/* Load a bitmap from an abstract file */
Bitmap(Storage::File & file);
/* 4/24/2010: remove this at some point */
#ifdef USE_ALLEGRO
explicit Bitmap( BITMAP * who, bool deep_copy = false );
#endif
#ifdef USE_SDL
explicit Bitmap(SDL_Surface * who, bool deep_copy = false );
#endif
#ifdef USE_ALLEGRO5
explicit Bitmap(ALLEGRO_BITMAP * who, bool deep_copy = false );
#endif
Bitmap( const Bitmap & copy, bool deep_copy = false );
Bitmap( const Bitmap & copy, int sx, int sy );
Bitmap( const Bitmap & copy, int x, int y, int width, int height );
virtual ~Bitmap();
/* For opengl backends, creates a memory bitmap. For software renderers
* just creates a regular bitmap.
*/
static Bitmap createMemoryBitmap(int width, int height);
virtual TranslucentBitmap translucent() const;
/* will call transBlender() with the supplied values for you */
virtual TranslucentBitmap translucent(int red, int green, int blue, int alpha) const;
+
+ virtual Bitmap subBitmap(int x, int y, int width, int height);
+
virtual LitBitmap lit() const;
virtual void save( const std::string & str ) const;
virtual Bitmap & operator=( const Bitmap & );
virtual void load( const std::string & str );
virtual int getWidth() const;
virtual int getHeight() const;
/* true if this bitmap doesn't contain an image of any sort. if so, don't
* try to use this object!!
*/
virtual bool isEmpty() const;
/*
inline const int getWidth() const{
return getBitmap()->w;
}
inline const int getHeight() const{
return getBitmap()->h;
}
*/
/*
inline const int getWidth() const{
return my_bitmap->w;
}
inline const int getHeight() const{
return my_bitmap->h;
}
*/
void detach();
/* replace all pixels that have value `original' with `replaced' */
void replaceColor(const Color & original, const Color & replaced);
void set8BitMaskColor(const Color & color);
Color get8BitMaskColor();
/* Blend between source pixel and destination pixel.
* Source and dest should be 0-255.
* source = 64, dest = 128
* pixel = source_pixel * source / 255 + dest_pixel * dest / 255
*/
static void alphaBlender(int source, int dest);
static void transBlender( int r, int g, int b, int a );
static void multiplyBlender( int r, int g, int b, int a );
static void dissolveBlender( int r, int g, int b, int a );
static void addBlender( int r, int g, int b, int a );
static void burnBlender( int r, int g, int b, int a );
static void colorBlender( int r, int g, int b, int a );
static void differenceBlender( int r, int g, int b, int a );
static void dodgeBlender( int r, int g, int b, int a );
static void hueBlender( int r, int g, int b, int a );
static void luminanceBlender( int r, int g, int b, int a );
static void invertBlender( int r, int g, int b, int a );
static void screenBlender( int r, int g, int b, int a );
/* for testing */
static void setFakeGraphicsMode(int width, int height);
/* clean up any remaining state */
static void shutdown();
// static void drawingMode( int type );
virtual Color blendColor(const Color & input) const;
/* sets the blend state. try not to use these function unless
* absolutely necessary.
*/
virtual void startDrawing() const;
virtual void endDrawing() const;
void acquire();
void release();
void updateOnResize();
/* Resizes the bitmap and stretches the old pixels to the new bitmap */
void resize(const int width, const int height);
/* Just resizes the bitmap without copying pixels */
void updateSize(const int width, const int height);
/* Makes this bitmap the same as the parameter.
* Width/height is copied and then a Blit is called.
*/
void copy(const Bitmap & him);
void debugSelf() const;
/* convert to a grey scale version */
virtual Bitmap greyScale();
virtual void triangle( int x1, int y1, int x2, int y2, int x3, int y3, Color color ) const;
/* draws an equilateral triangle centered at (x,y) pointing at `angle'
* where each side has `size' pixels using the color.
*/
virtual void equilateralTriangle(int x, int y, int angle, int size, Color color) const;
virtual void ellipse( int x, int y, int rx, int ry, Color color ) const;
virtual void ellipseFill( int x, int y, int rx, int ry, Color color ) const;
virtual void light(int x, int y, int width, int height, int start_y, int focus_alpha, int edge_alpha, Color focus_color, Color edge_color) const;
virtual void applyTrans(const Color color) const;
virtual void border( int min, int max, Color color ) const;
virtual void rectangle( int x1, int y1, int x2, int y2, Color color ) const;
virtual void rectangleFill( int x1, int y1, int x2, int y2, Color color ) const;
virtual void circleFill( int x, int y, int radius, Color color ) const;
virtual void circle( int x, int y, int radius, Color color ) const;
virtual void circle(int x, int y, int radius, int thickness, Color color) const;
virtual void line( const int x1, const int y1, const int x2, const int y2, const Color color ) const;
virtual void floodfill( const int x, const int y, const Color color ) const;
virtual void horizontalLine( const int x1, const int y, const int x2, const Color color ) const;
virtual void hLine( const int x1, const int y, const int x2, const Color color ) const;
virtual void vLine( const int y1, const int x, const int y2, const Color color ) const;
virtual void polygon( const int * verts, const int nverts, const Color color ) const;
virtual void arc(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const;
virtual void arcFilled(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const;
/* x/y is in the center of the bitmap */
virtual void drawCenter(const int x, const int y, const Bitmap & where) const;
virtual void draw(const int x, const int y, const Bitmap & where) const;
virtual void draw(const int x, const int y, Filter * filter, const Bitmap & where) const;
virtual void draw(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, const Bitmap & where) const;
virtual void draw(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, Filter * filter, const Bitmap & where) const;
virtual void drawCharacter( const int x, const int y, const Color color, const int background, const Bitmap & where ) const;
/* flip horizontally */
virtual void drawHFlip(const int x, const int y, const Bitmap & where) const;
virtual void drawHFlip(const int x, const int y, Filter * filter, const Bitmap & where) const;
virtual void drawHFlip(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, const Bitmap & where) const;
virtual void drawHFlip(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, Filter * filter, const Bitmap & where) const;
/* flip vertically */
virtual void drawVFlip( const int x, const int y, const Bitmap & where ) const;
virtual void drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
/* flip horizontal and vertical */
virtual void drawHVFlip( const int x, const int y, const Bitmap & where ) const;
virtual void drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
// virtual void drawTrans( const int x, const int y, const Bitmap & where ) const;
// virtual void drawTrans( const int x, const int y, Filter * filter, const Bitmap & where ) const;
// virtual void drawTransHFlip( const int x, const int y, const Bitmap & where ) const;
// virtual void drawTransHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
// virtual void drawTransVFlip( const int x, const int y, const Bitmap & where ) const;
// virtual void drawTransVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
// virtual void drawTransHVFlip( const int x, const int y, const Bitmap & where ) const;
// virtual void drawTransHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
virtual void drawMask( const int x, const int y, const Bitmap & where );
virtual void drawStretched( const int x, const int y, const int new_width, const int new_height, const Bitmap & who ) const;
virtual void drawStretched(const Bitmap & who) const;
/* middle of the bitmap is at x, y */
virtual void drawRotateCenter(const int x, const int y, const int angle, const Bitmap & where);
/* upper left hand corner is at x, y*/
virtual void drawRotate(const int x, const int y, const int angle, const Bitmap & where);
virtual void drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const Bitmap & where );
virtual void drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const double scale, const Bitmap & where );
/* Stretch using the hqx algorithm */
virtual void StretchHqx(const Bitmap & where) const;
virtual void StretchHqx(const Bitmap & where, const int sourceX, const int sourceY, const int sourceWidth, const int sourceHeight, const int destX, const int destY, const int destWidth, const int destHeight) const;
/* Xbr is defined here:
* http://board.byuu.org/viewtopic.php?f=10&t=2248
*/
virtual void StretchXbr(const Bitmap & where) const;
virtual void StretchXbr(const Bitmap & where, const int sourceX, const int sourceY, const int sourceWidth, const int sourceHeight, const int destX, const int destY, const int destWidth, const int destHeight) const;
/* Just copies pixels (fast) */
virtual void Stretch(const Bitmap & where) const;
virtual void Stretch(const Bitmap & where, const int sourceX, const int sourceY, const int sourceWidth, const int sourceHeight, const int destX, const int destY, const int destWidth, const int destHeight ) const;
virtual void StretchBy2( const Bitmap & where );
virtual void StretchBy4( const Bitmap & where );
virtual void Blit( const std::string & xpath ) const;
virtual void Blit( const Bitmap & where ) const;
virtual void Blit( const int x, const int y, const Bitmap & where ) const;
virtual void Blit( const int mx, const int my, const int wx, const int wy, const Bitmap & where ) const;
virtual void Blit( const int mx, const int my, const int width, const int height, const int wx, const int wy, const Bitmap & where ) const;
virtual void BlitMasked( const int mx, const int my, const int width, const int height, const int wx, const int wy, const Bitmap & where ) const;
virtual void BlitToScreen() const;
virtual void BlitAreaToScreen(const int upper_left_x, const int upper_left_y) const;
virtual void BlitToScreen(const int upper_left_x, const int upper_left_y) const;
virtual void BlitFromScreen(const int x, const int y) const;
virtual void roundRect(int radius, int x1, int y1, int x2, int y2, Color color) const;
virtual void roundRectFill(int radius, int x1, int y1, int x2, int y2, Graphics::Color color) const;
virtual void drawShadow(Bitmap & where, int x, int y, int intensity, Color color, double scale, bool facingRight) const;
/* Return a bitmap that has an aspect ratio the same as the given numbers */
virtual Bitmap aspectRatio(int aspectWidth, int aspectHeight) const;
/* returned a scaled version of this bitmap of the given dimensions */
virtual Bitmap scaleTo(const int width, const int height) const;
/* scale the image by the given ratios, i.e: a ratio of 1 means do nothing.
* less than 1 will make it smaller and larger than 1 will make it larger.
*/
virtual Bitmap scaleBy(const double widthRatio, const double heightRatio) const;
/* try to call Global::getScreenWidth/Height() instead of these directly */
static int getScreenWidth();
static int getScreenHeight();
virtual void fill(Color color) const;
virtual void clear() const;
inline void clearToMask() const{
this->fill(MaskColor());
}
bool getError();
inline const Util::ReferenceCount<BitmapData> & getData() const {
return data;
}
inline Util::ReferenceCount<BitmapData> getData(){
return data;
}
void setData(Util::ReferenceCount<BitmapData> data){
this->data = data;
}
virtual void readLine( std::vector<Color> & vec, int y );
Color getPixel( const int x, const int y ) const;
/* lock video bitmap to memory */
void lock() const;
void lock(int x, int y, int width, int height) const;
void unlock() const;
/* true if the point is within the bounds of the bitmap */
bool inRange(int x, int y) const;
/* uses _putpixel16 underneath which ignores translucent behavior */
void putPixel( int x, int y, Color col ) const;
/* respects the current trans mode */
virtual void putPixelNormal(int x, int y, Color col) const;
/*
inline int getPixel( int x, int y ) const{
if ( x >= 0 && x < my_bitmap->w && y >= 0 && y <= my_bitmap->h )
return _getpixel16( my_bitmap, x, y );
return -1;
}
inline void putPixel( int x, int y, int col ) const{
if ( x >= 0 && x < my_bitmap->w && y >= 0 && y <= my_bitmap->h )
_putpixel16( my_bitmap, x, y, col );
}
*/
void setClipRect( int x1, int y1, int x2, int y2 ) const;
void getClipRect( int & x1, int & y1, int & x2, int & y2 ) const;
inline const std::string & getPath() const{
return path;
}
/* produce a temporary bitmap that is not guaranteed to be preserved
* after your function returns. do *not* hold references to this bitmap
* and if you make a temporary bitmap, do *not* call functions that
* might also make temporary bitmaps.
*/
/*
static Bitmap temporaryBitmap(int w, int h);
static Bitmap temporaryBitmap2(int w, int h);
*/
/* call this method to delete all temporary bitmaps.
* don't call this unless you know what you are doing
*/
static void cleanupTemporaryBitmaps();
static double getScale();
/*
* Convert color values between the HSV and RGB color spaces. The RGB values
* range from 0 to 255, hue is from 0 to 360, and saturation and value are
* from 0 to 1.
*/
static void rgbToHSV(int r, int g, int b, float * h, float * s, float * v);
/* convert cymk to rgb. values should be in the range 0-255 */
static void cymkToRGB(int c, int y, int m, int k, int * r, int * g, int * b);
/* Add two RGB16 colors together
* r = c1.r + c2.r
* g = c1.g + c2.g
* b = c1.b + c2.b
*/
static Color addColor( Color color1, Color color2 );
/*
inline static int makeColor( int r, int g, int b ){
return makecol16( r, g, b );
}
*/
// static const int MaskColor = MASK_COLOR_16;
/*
static const int MODE_TRANS;
static const int MODE_SOLID;
*/
#ifdef USE_ALLEGRO5
void convertToVideo();
#endif
protected:
#ifdef USE_ALLEGRO5
virtual void draw(const int x, const int y, Filter * filter, const Bitmap & where, int flags) const;
#endif
/* release a reference count, and possibly destroy data */
// void releaseInternalBitmap();
/* really destroy private data */
// void destroyPrivateData();
/*
inline void setBitmap( BITMAP * bitmap ){
if ( bitmap == NULL ){
std::cout << "*FATAL* Setting null bitmap" << std::endl;
}
_my_bitmap = bitmap;
}
*/
void loadFromMemory(const char * data, int length);
void internalLoadFile( const char * load_file );
/* implementation specific data */
Util::ReferenceCount<BitmapData> data;
// int * own;
bool mustResize;
// bool own;
bool error;
std::string path;
static Bitmap * temporary_bitmap;
static Bitmap * temporary_bitmap2;
Color bit8MaskColor;
/* only used by allegro5 for now */
int width, height;
};
/* 8-bit bitmap that supports a palette */
class PaletteBitmap: public Bitmap {
public:
PaletteBitmap();
virtual ~PaletteBitmap();
using Bitmap::operator=;
protected:
Color palette[256];
};
Bitmap memoryPCX(unsigned char * const data, const int length, const bool mask = true);
/* creates a bitmap that can be used as a buffer for the screen.
* on opengl/allegro5 systems this will return the current backbuffer
*/
Bitmap * getScreenBuffer();
struct BlendPoint{
BlendPoint(const Color & color, int length);
Color color;
int length;
};
void blend_palette(Color * pal, int mp, const Color & sc, const Color & ec);
std::vector<Color> blend_palette(const std::vector<BlendPoint> & in);
// bool sameColors(Color color1, Color color2);
class LitBitmap: public Bitmap {
public:
LitBitmap( const Bitmap & b );
LitBitmap();
virtual ~LitBitmap();
using Bitmap::draw;
virtual void draw(const int x, const int y, const Bitmap & where) const;
virtual void draw(const int x, const int y, Filter * filter, const Bitmap & where ) const;
using Bitmap::drawHFlip;
virtual void drawHFlip( const int x, const int y, const Bitmap & where ) const;
virtual void drawHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
using Bitmap::drawVFlip;
virtual void drawVFlip( const int x, const int y, const Bitmap & where ) const;
virtual void drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
using Bitmap::drawHVFlip;
virtual void drawHVFlip( const int x, const int y, const Bitmap & where ) const;
virtual void drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
using Bitmap::operator=;
protected:
#ifdef USE_ALLEGRO5
virtual void draw(const int x, const int y, Filter * filter, const Bitmap & where, int flags) const;
#endif
};
class StretchedBitmap: public Bitmap {
public:
/* How to initialize the bitmap */
enum Clear{
/* Don't do anything */
NoClear,
/* Clear (to black) */
FullClear,
/* Fill with the masking color for software rendering and
* do nothing for opengl
*/
Mask
};
StretchedBitmap(int width, int height, const Bitmap & where, Clear = NoClear, QualityFilter filter = NoFilter);
void finish();
void start();
virtual int getWidth() const;
virtual int getHeight() const;
using Bitmap::operator=;
virtual double getScaleWidth() const;
virtual double getScaleHeight() const;
protected:
double width;
double height;
double scale_x, scale_y;
const Bitmap & where;
const QualityFilter filter;
const Clear clearKind;
Bitmap scaleToFilter;
};
class TranslatedBitmap: public Bitmap {
public:
TranslatedBitmap(int x, int y, const Bitmap & where);
using Bitmap::operator=;
using Bitmap::BlitToScreen;
virtual void BlitToScreen() const;
virtual ~TranslatedBitmap();
public:
int x, y;
};
class TranslucentBitmap: public Bitmap {
public:
TranslucentBitmap(const Bitmap & b);
TranslucentBitmap();
virtual ~TranslucentBitmap();
using Bitmap::operator=;
virtual Color blendColor(const Color & color) const;
virtual void startDrawing() const;
virtual void endDrawing() const;
virtual void putPixelNormal(int x, int y, Color col) const;
virtual void rectangleFill(int x1, int y1, int x2, int y2, Color color) const;
virtual void rectangle(int x1, int y1, int x2, int y2, Color color) const;
virtual void fill(Color color) const;
virtual void line( const int x1, const int y1, const int x2, const int y2, const Color color ) const;
virtual void hLine( const int x1, const int y, const int x2, const Color color ) const;
virtual void arc(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color) const;
virtual void arcFilled(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const;
virtual void roundRect(int radius, int x1, int y1, int x2, int y2, Color color) const;
virtual void roundRectFill(int radius, int x1, int y1, int x2, int y2, Graphics::Color color) const;
virtual void circleFill( int x, int y, int radius, Color color ) const;
virtual void ellipse( int x, int y, int rx, int ry, Color color ) const;
virtual void ellipseFill( int x, int y, int rx, int ry, Color color ) const;
using Bitmap::draw;
virtual void draw(const int x, const int y, const Bitmap & where) const;
virtual void draw(const int x, const int y, Filter * filter, const Bitmap & where) const;
// virtual void draw(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, const Bitmap & where) const;
// virtual void draw(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, Filter * filter, const Bitmap & where) const;
using Bitmap::drawHFlip;
virtual void drawHFlip(const int x, const int y, const Bitmap & where) const;
virtual void drawHFlip(const int x, const int y, Filter * filter, const Bitmap & where) const;
// virtual void drawHFlip(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, const Bitmap & where) const;
// virtual void drawHFlip(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, Filter * filter, const Bitmap & where) const;
virtual void drawVFlip( const int x, const int y, const Bitmap & where ) const;
virtual void drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
virtual void drawHVFlip( const int x, const int y, const Bitmap & where ) const;
virtual void drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
protected:
#ifdef USE_ALLEGRO5
virtual void draw(const int x, const int y, Filter * filter, const Bitmap & where, int flags) const;
#endif
};
/* Normal drawing operations but ultimately is drawn translucently onto the parent */
class SubTranslucentBitmap: public Bitmap {
public:
/* How to initialize the bitmap */
enum Clear{
/* Don't do anything */
NoClear,
/* Clear (to black) */
FullClear,
/* Fill with the masking color for software rendering and
* do nothing for opengl
*/
Mask
};
SubTranslucentBitmap(const Bitmap & where, int x, int y, int width, int height, Clear = NoClear);
using Bitmap::operator=;
virtual void roundRect(int radius, int x1, int y1, int x2, int y2, Color color) const;
virtual void roundRectFill(int radius, int x1, int y1, int x2, int y2, Color color) const;
virtual void finish();
virtual void start();
protected:
#ifdef USE_ALLEGRO5
TranslucentBitmap translucent;
#else
Bitmap translucent;
#endif
const Clear clearKind;
};
}
#endif
diff --git a/src/debug.cpp b/src/debug.cpp
index 1ad426e3..67a5c761 100644
--- a/src/debug.cpp
+++ b/src/debug.cpp
@@ -1,440 +1,445 @@
#include "r-tech1/debug.h"
#include "r-tech1/system.h"
#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
#ifdef ANDROID
#include <android/log.h>
#define ANDROID_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "r-tech1", __VA_ARGS__)
#endif
#ifdef NETWORK_DEBUG
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <arpa/inet.h>
#endif
using namespace std;
static int global_debug_level = 0;
static std::string global_log_file = "r-tech1.log";
namespace Global{
#ifdef ANDROID
android_ostream::android_ostream(bool enabled):
enabled(enabled){
}
android_ostream & operator<<(android_ostream & stream, const std::string & input){
stream.buffer << input;
return stream;
}
android_ostream & operator<<(android_ostream & stream, const char * input){
stream.buffer << input;
return stream;
}
android_ostream & operator<<(android_ostream & stream, const char input){
stream.buffer << input;
return stream;
}
android_ostream & operator<<(android_ostream & stream, const double input){
stream.buffer << input;
return stream;
}
android_ostream & operator<<(android_ostream & stream, const int input){
stream.buffer << input;
return stream;
}
android_ostream & operator<<(android_ostream & stream, const short int input){
stream.buffer << input;
return stream;
}
android_ostream & operator<<(android_ostream & stream, const short unsigned int input){
stream.buffer << input;
return stream;
}
android_ostream & operator<<(android_ostream & stream, const unsigned int input){
stream.buffer << input;
return stream;
}
android_ostream & operator<<(android_ostream & stream, const bool input){
stream.buffer << input;
return stream;
}
android_ostream & operator<<(android_ostream & stream, const long int input){
stream.buffer << input;
return stream;
}
android_ostream & operator<<(android_ostream & stream, const unsigned long int input){
stream.buffer << input;
return stream;
}
+android_ostream & operator<<(android_ostream & stream, const uint64_t input){
+ stream.buffer << input;
+ return stream;
+}
+
android_ostream & operator<<(android_ostream & stream, const void * input){
stream.buffer << input;
return stream;
}
android_ostream & operator<<(android_ostream & stream, std::ostream & (*f)(std::ostream &)){
if (stream.enabled){
ANDROID_LOGV("%s\n", stream.buffer.str().c_str());
}
stream.buffer.str("");
stream.buffer.rdbuf()->pubseekoff(0, ios_base::end, ios_base::out);
stream.buffer.clear();
return stream;
}
android_ostream android_ostream::stream;
static android_ostream nullcout(false);
#elif defined(WII) && defined(DEBUG)
wii_ostream::wii_ostream(bool enabled):
enabled(enabled){
}
wii_ostream & operator<<(wii_ostream & stream, const std::string & input){
stream.buffer << input;
return stream;
}
wii_ostream & operator<<(wii_ostream & stream, const char * input){
stream.buffer << input;
return stream;
}
wii_ostream & operator<<(wii_ostream & stream, const char input){
stream.buffer << input;
return stream;
}
wii_ostream & operator<<(wii_ostream & stream, const double input){
stream.buffer << input;
return stream;
}
wii_ostream & operator<<(wii_ostream & stream, const int input){
stream.buffer << input;
return stream;
}
wii_ostream & operator<<(wii_ostream & stream, uint64_t input){
stream.buffer << input;
return stream;
}
wii_ostream & operator<<(wii_ostream & stream, const short int input){
stream.buffer << input;
return stream;
}
wii_ostream & operator<<(wii_ostream & stream, const short unsigned int input){
stream.buffer << input;
return stream;
}
wii_ostream & operator<<(wii_ostream & stream, const unsigned int input){
stream.buffer << input;
return stream;
}
wii_ostream & operator<<(wii_ostream & stream, const bool input){
stream.buffer << input;
return stream;
}
wii_ostream & operator<<(wii_ostream & stream, const long int input){
stream.buffer << input;
return stream;
}
wii_ostream & operator<<(wii_ostream & stream, const unsigned long int input){
stream.buffer << input;
return stream;
}
wii_ostream & operator<<(wii_ostream & stream, const void * input){
stream.buffer << input;
return stream;
}
wii_ostream & operator<<(wii_ostream & stream, std::ostream & (*f)(std::ostream &)){
if (stream.enabled){
printf("%s\n", stream.buffer.str().c_str());
}
stream.buffer.str("");
stream.buffer.rdbuf()->pubseekoff(0, ios_base::end, ios_base::out);
stream.buffer.clear();
return stream;
}
wii_ostream wii_ostream::stream;
static wii_ostream nullcout(false);
#elif defined(NETWORK_DEBUG)
network_ostream::network_ostream(const std::string & host, int port, bool enabled):
host(host),
port(port),
enabled(enabled){
}
network_ostream & operator<<(network_ostream & stream, const std::string & input){
stream.buffer << input;
return stream;
}
network_ostream & operator<<(network_ostream & stream, const char * input){
stream.buffer << input;
return stream;
}
network_ostream & operator<<(network_ostream & stream, const char input){
stream.buffer << input;
return stream;
}
network_ostream & operator<<(network_ostream & stream, const double input){
stream.buffer << input;
return stream;
}
network_ostream & operator<<(network_ostream & stream, const int input){
stream.buffer << input;
return stream;
}
network_ostream & operator<<(network_ostream & stream, uint64_t input){
stream.buffer << input;
return stream;
}
network_ostream & operator<<(network_ostream & stream, const short int input){
stream.buffer << input;
return stream;
}
network_ostream & operator<<(network_ostream & stream, const short unsigned int input){
stream.buffer << input;
return stream;
}
network_ostream & operator<<(network_ostream & stream, const unsigned int input){
stream.buffer << input;
return stream;
}
network_ostream & operator<<(network_ostream & stream, const bool input){
stream.buffer << input;
return stream;
}
network_ostream & operator<<(network_ostream & stream, const long int input){
stream.buffer << input;
return stream;
}
#ifndef PS3
network_ostream & operator<<(network_ostream & stream, const unsigned long int input){
stream.buffer << input;
return stream;
}
#endif
network_ostream & operator<<(network_ostream & stream, const void * input){
stream.buffer << input;
return stream;
}
static void sendString(const std::string & host, int port, const std::string & data){
int gateway = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons(port);
address.sin_addr.s_addr = inet_addr(host.c_str());
memset(address.sin_zero, '\0', sizeof(address.sin_zero));
connect(gateway, (struct sockaddr*) &address, sizeof(address));
send(gateway, data.c_str(), data.size(), 0);
send(gateway, "\n", 1, 0);
close(gateway);
}
network_ostream & operator<<(network_ostream & stream, std::ostream & (*f)(std::ostream &)){
if (stream.enabled){
sendString(stream.host, stream.port, stream.buffer.str());
// printf("%s\n", stream.buffer.str().c_str());
}
stream.buffer.str("");
stream.buffer.rdbuf()->pubseekoff(0, ios_base::end, ios_base::out);
stream.buffer.clear();
return stream;
}
/* IP address and port are arbitrary */
network_ostream network_ostream::stream("192.168.1.100", 5670);
static network_ostream nullcout("", 0, false);
#else
class nullstreambuf_t: public std::streambuf {
public:
nullstreambuf_t():std::streambuf(){
}
};
static nullstreambuf_t nullstreambuf;
class nullcout_t: public std::ostream {
public:
nullcout_t():std::ostream(&nullstreambuf){
}
};
static nullcout_t nullcout;
#endif
#ifdef ANDROID
static stream_type & defaultStream(){
return android_ostream::stream;
}
static stream_type & getStream(){
return defaultStream();
}
void logToFile(){
}
void closeLog(){
}
#elif defined(WII) && defined(DEBUG)
static stream_type & defaultStream(){
return wii_ostream::stream;
}
static stream_type & getStream(){
return defaultStream();
}
void logToFile(){
}
void closeLog(){
}
#elif defined(NETWORK_DEBUG)
static stream_type & defaultStream(){
return network_ostream::stream;
}
static stream_type & getStream(){
return defaultStream();
}
void logToFile(){
}
void closeLog(){
}
#else
static stream_type & defaultStream(){
return std::cout;
}
static std::ofstream log;
static bool useFile = false;
static stream_type & fileStream(){
static bool init = false;
if (!init){
log.open(Global::getLogFile().c_str());
init = true;
}
return log;
}
static void closeFileStream(){
log.close();
}
static stream_type & getStream(){
if (useFile){
return fileStream();
} else {
return defaultStream();
}
}
void logToFile(){
useFile = true;
}
void closeLog(){
closeFileStream();
}
#endif
}
Global::stream_type & Global::debug(int i, const string & context){
if (global_debug_level >= i){
Global::stream_type & out = getStream();
out << "[" << i << ":" << context << "] ";
return out;
}
return nullcout;
}
void Global::setDebug(int i){
global_debug_level = i;
}
int Global::getDebug(){
return global_debug_level;
}
void Global::setLogFile(const std::string & file){
global_log_file = file;
}
const std::string & Global::getLogFile(){
return global_log_file;
}
std::string Global::defaultDebugContext = "default";
void Global::setDefaultDebugContext(const std::string & context){
defaultDebugContext = context;
}
static std::string now(){
time_t t = time(NULL);
tm * timeData;
timeData = localtime(&t);
uint64_t millis = System::currentMilliseconds() % 1000;
if (timeData != NULL){
char buffer[200];
strftime(buffer, sizeof(buffer), "%F %I:%M:%S", timeData);
std::ostringstream out;
out << buffer << "." << millis;
strftime(buffer, sizeof(buffer), " %p", timeData);
out << buffer;
return out.str();
// return std::string(buffer);
}
return std::string();
}
std::string Global::debug_context(const char * file, int line){
std::ostringstream out;
out << file << ":" << line << " " << now();
return out.str();
}
diff --git a/src/events.cpp b/src/events.cpp
index eece9d09..23d57c18 100644
--- a/src/events.cpp
+++ b/src/events.cpp
@@ -1,648 +1,648 @@
#ifdef USE_SDL
#include <SDL.h>
#endif
#ifdef USE_ALLEGRO5
#include <allegro5/allegro.h>
#endif
#include <vector>
#include <map>
#include "r-tech1/graphics/bitmap.h"
#include "r-tech1/events.h"
#include "r-tech1/exceptions/shutdown_exception.h"
#include "r-tech1/configuration.h"
#include "r-tech1/debug.h"
#include "r-tech1/funcs.h"
#include "r-tech1/thread.h"
#include "r-tech1/init.h"
#include "r-tech1/parameter.h"
#include "r-tech1/input/keyboard.h"
#include "r-tech1/input/joystick.h"
#include "r-tech1/input/input-manager.h"
#include "r-tech1/input/input-source.h"
#include "r-tech1/system.h"
using std::map;
namespace Util{
int do_shutdown = 0;
bool shutdown(){
return do_shutdown > 0;
}
EventManager::EventManager():
bufferKeys(false),
deferResize(false){
resize.enable = false;
#ifdef USE_ALLEGRO5
queue = al_create_event_queue();
if (al_is_keyboard_installed()){
al_register_event_source(queue, al_get_keyboard_event_source());
}
if (al_is_joystick_installed()){
al_register_event_source(queue, al_get_joystick_event_source());
}
if (Graphics::the_display != NULL){
al_register_event_source(queue, al_get_display_event_source(Graphics::the_display));
}
#endif
}
#ifdef USE_SDL
static void handleKeyDown(Keyboard & keyboard, const SDL_Event & event){
keyboard.press(event.key.keysym.sym, event.key.keysym.unicode);
}
static void handleKeyUp(Keyboard & keyboard, const SDL_Event & event){
keyboard.release(event.key.keysym.sym);
}
static void handleJoystickButtonUp(map<int, ReferenceCount<Joystick> > joysticks, const SDL_Event & event){
int device = event.jbutton.which;
int button = event.jbutton.button;
ReferenceCount<Joystick> joystick = joysticks[device];
if (joystick != NULL){
joystick->releaseButton(button);
}
}
static void handleJoystickHat(map<int, ReferenceCount<Joystick> > joysticks, const SDL_Event & event){
int device = event.jhat.which;
int motion = event.jhat.value;
ReferenceCount<Joystick> joystick = joysticks[device];
if (joystick != NULL){
joystick->hatMotion(motion);
}
#if 0
/* should up/down control left/right -- flip these values? */
#if WII
const int axis_up_down = 0;
const int axis_left_right = 1;
const int up = 1;
const int down = -1;
const int left = -1;
const int right = 1;
#else
const int axis_up_down = 1;
const int axis_left_right = 0;
const int up = -1;
const int down = 1;
const int left = -1;
const int right = 1;
#endif
switch (motion){
case SDL_HAT_CENTERED: break;
case SDL_HAT_UP: joystick->axisMotion(axis_up_down, up); break;
case SDL_HAT_DOWN: joystick->axisMotion(axis_up_down, down); break;
case SDL_HAT_RIGHT: joystick->axisMotion(axis_left_right, right); break;
case SDL_HAT_LEFT: joystick->axisMotion(axis_left_right, left); break;
default: break;
}
#endif
}
static void handleJoystickButtonDown(map<int, ReferenceCount<Joystick> > joysticks, const SDL_Event & event){
int device = event.jbutton.which;
int button = event.jbutton.button;
ReferenceCount<Joystick> joystick = joysticks[device];
if (joystick != NULL){
joystick->pressButton(button);
}
}
static void handleJoystickAxis(map<int, ReferenceCount<Joystick> > joysticks, const SDL_Event & event){
int device = event.jaxis.which;
int axis = event.jaxis.axis;
int value = event.jaxis.value;
ReferenceCount<Joystick> joystick = joysticks[device];
if (joystick != NULL){
joystick->axisMotion(axis, value);
}
}
void EventManager::runSDL(Keyboard & keyboard, map<int, ReferenceCount<Joystick> > joysticks){
keyboard.poll();
for (map<int, ReferenceCount<Joystick> >::iterator it = joysticks.begin(); it != joysticks.end(); it++){
ReferenceCount<Joystick> joystick = it->second;
if (joystick != NULL){
joystick->poll();
}
}
SDL_Event event;
/* FIXME: android gets into an infinite loop while reading events */
#ifdef ANDROID
// int good = SDL_PollEvent(&event);
// for (int check = 0; check < 10 && good; check++, good = SDL_PollEvent(&event)){
// if (SDL_PollEvent(&event) == 1){
while (SDL_PollEvent(&event) == 1){
#else
while (SDL_PollEvent(&event) == 1){
#endif
switch (event.type){
case SDL_QUIT : {
dispatch(CloseWindow);
break;
}
case SDL_KEYDOWN : {
handleKeyDown(keyboard, event);
// dispatch(Key, event.key.keysym.sym);
break;
}
case SDL_KEYUP : {
handleKeyUp(keyboard, event);
break;
}
case SDL_JOYBUTTONDOWN: {
handleJoystickButtonDown(joysticks, event);
break;
}
case SDL_JOYHATMOTION : {
handleJoystickHat(joysticks, event);
break;
}
case SDL_JOYBUTTONUP: {
handleJoystickButtonUp(joysticks, event);
break;
}
case SDL_JOYAXISMOTION: {
handleJoystickAxis(joysticks, event);
break;
}
case SDL_VIDEORESIZE : {
int width = event.resize.w;
int height = event.resize.h;
/* to keep the perspective correct
* 640/480 = 1.33333
*/
/*
double ratio = (double) 640 / (double) 480;
if (width > height){
height = (int)((double) width / ratio);
} else {
width = (int)((double) height * ratio);
}
*/
dispatch(ResizeScreen, width, height);
break;
}
default : {
break;
}
}
}
}
#endif
#ifdef USE_ALLEGRO
void EventManager::runAllegro(Keyboard & keyboard, map<int, ReferenceCount<Joystick> > joystick){
keyboard.poll();
}
#endif
#ifdef USE_ALLEGRO5
static void handleKeyDown(Keyboard & keyboard, const ALLEGRO_EVENT & event){
keyboard.press(event.keyboard.keycode, event.keyboard.unichar);
}
static void handleKeyUp(Keyboard & keyboard, const ALLEGRO_EVENT & event){
keyboard.release(event.keyboard.keycode);
}
static void handleResize(const ALLEGRO_EVENT & event){
double width = event.display.width;
double height = event.display.height;
/*
if (width < 640){
width = 640;
}
if (height < 480){
height = 480;
}
*/
/* to keep the perspective correct
* 640/480 = 1.33333
*/
/*
double ratio = (double) 640 / (double) 480;
if (width > height){
height = width / ratio;
} else {
width = height * ratio;
}
*/
ALLEGRO_DISPLAY * display = event.display.source;
al_acknowledge_resize(display);
Configuration::setScreenWidth((int) width);
Configuration::setScreenHeight((int) height);
al_resize_display(display, (int) width, (int) height);
Graphics::getScreenBuffer()->clear();
/*
ALLEGRO_TRANSFORM transformation;
al_identity_transform(&transformation);
// al_scale_transform(&transformation, (double) al_get_display_width(display) / (double) GFX_X, (double) al_get_display_height(display) / (double) GFX_Y);
al_scale_transform(&transformation, (double) width / (double) GFX_X, (double) height / (double) GFX_Y);
al_set_target_bitmap(Graphics::getScreenBuffer()->getData()->getBitmap());
al_use_transform(&transformation);
*/
}
void EventManager::runAllegro5(Keyboard & keyboard, const map<int, ReferenceCount<Joystick> > & joysticks){
keyboard.poll();
for (map<int, ReferenceCount<Joystick> >::const_iterator it = joysticks.begin(); it != joysticks.end(); it++){
ReferenceCount<Joystick> joystick = it->second;
if (joystick != NULL){
joystick->poll();
}
}
ALLEGRO_EVENT event;
while (al_get_next_event(queue, &event)){
switch (event.type){
/*
case ALLEGRO_EVENT_KEY_DOWN: {
Global::debug(0) << "Key down " << event.keyboard.keycode << std::endl;
handleKeyDown(keyboard, event);
break;
}
*/
case ALLEGRO_EVENT_DISPLAY_RESIZE: {
handleResize(event);
break;
}
case ALLEGRO_EVENT_DISPLAY_CLOSE: {
throw ShutdownException();
break;
}
case ALLEGRO_EVENT_KEY_UP: {
handleKeyUp(keyboard, event);
break;
}
case ALLEGRO_EVENT_KEY_CHAR : {
// Global::debug(0) << "Key char " << event.keyboard.keycode << " unicode " << event.keyboard.unichar << std::endl;
bool ok = true;
if (event.keyboard.repeat){
ok = Keyboard::getRepeatState();
}
if (ok){
handleKeyDown(keyboard, event);
}
break;
}
case ALLEGRO_EVENT_JOYSTICK_CONFIGURATION: {
/* FIXME: tell input manager to reconfigure joysticks */
// al_reconfigure_joysticks();
break;
}
}
}
/*
if (joystick){
joystick->poll();
}
SDL_Event event;
while (SDL_PollEvent(&event) == 1){
switch (event.type){
case SDL_QUIT : {
dispatch(CloseWindow);
break;
}
case SDL_KEYDOWN : {
handleKeyDown(keyboard, event);
// dispatch(Key, event.key.keysym.sym);
break;
}
case SDL_KEYUP : {
handleKeyUp(keyboard, event);
break;
}
case SDL_JOYBUTTONDOWN: {
if (joystick != NULL){
handleJoystickButtonDown(joystick, event);
}
break;
}
case SDL_JOYHATMOTION : {
if (joystick != NULL){
handleJoystickHat(joystick, event);
}
break;
}
case SDL_JOYBUTTONUP: {
if (joystick != NULL){
handleJoystickButtonUp(joystick, event);
}
break;
}
case SDL_JOYAXISMOTION: {
if (joystick != NULL){
handleJoystickAxis(joystick, event);
}
break;
}
case SDL_VIDEORESIZE : {
int width = event.resize.w;
int height = event.resize.h;
/ * to keep the perspective correct
* 640/480 = 1.33333
* /
if (width > height){
height = (int)((double) width / 1.3333333333);
} else {
width = (int)((double) height * 1.3333333333);
}
dispatch(ResizeScreen, width, height);
break;
}
default : {
break;
}
}
}
*/
}
#endif
void EventManager::run(Keyboard & keyboard, std::map<int, ReferenceCount<Joystick> > joysticks){
#ifdef USE_SDL
runSDL(keyboard, joysticks);
#elif USE_ALLEGRO
runAllegro(keyboard, joysticks);
#elif USE_ALLEGRO5
runAllegro5(keyboard, joysticks);
#endif
}
/* kill the program if the user requests */
void EventManager::waitForThread(WaitThread & thread){
// Keyboard dummy;
while (!thread.isRunning()){
try{
/* input manager will run the event manager */
InputManager::poll();
// run(dummy);
} catch (const ShutdownException & death){
thread.kill();
throw death;
}
Util::rest(10);
}
}
EventManager::~EventManager(){
#ifdef USE_ALLEGRO5
al_destroy_event_queue(queue);
#endif
}
void EventManager::enableKeyBuffer(){
bufferKeys = true;
}
void EventManager::disableKeyBuffer(){
bufferKeys = false;
}
void EventManager::dispatch(Event type, int arg1){
switch (type){
case Key : {
if (bufferKeys){
keys.push_back(KeyType(arg1));
}
break;
}
default : {
break;
}
}
}
void EventManager::dispatch(Event type, int arg1, int arg2){
switch (type){
case ResizeScreen : {
if (deferResize){
resize.type = ResizeScreen;
resize.width = arg1;
resize.height = arg2;
resize.enable = true;
} else {
Global::debug(1) << "Resizing screen to " << arg1 << ", " << arg2 << std::endl;
if (Graphics::setGraphicsMode(0, arg1, arg2) == 0){
Configuration::setScreenWidth(arg1);
Configuration::setScreenHeight(arg2);
}
}
break;
}
default: break;
}
}
void EventManager::dispatch(Event type){
switch (type){
case CloseWindow : {
throw ShutdownException();
}
default : break;
}
}
void EventManager::deferResizeEvents(bool defer){
deferResize = defer;
if (!deferResize && resize.enable){
dispatch(resize.type, resize.width, resize.height);
resize.enable = false;
}
}
class LoopDone: public std::exception {
public:
LoopDone(){
}
~LoopDone() throw () {
}
};
Logic::~Logic(){
}
Draw::Draw():
frames(0),
second_counter(Global::second_counter),
fps(0){
}
void Draw::drawFirst(const Graphics::Bitmap & screen){
draw(screen);
}
Draw::~Draw(){
}
double Draw::getFps() const {
return fps;
}
void Draw::updateFrames(){
if (second_counter != Global::second_counter){
int difference = Global::second_counter - second_counter;
double alpha = 0.2;
/* unlikely, but just in case */
if (difference == 0){
difference = 1;
}
fps = (alpha * fps) + ((1 - alpha) * (double) frames / difference);
// fps[fps_index] = (double) frames / (double) difference;
// fps_index = (fps_index+1) % max_fps_index;
second_counter = Global::second_counter;
frames = 0;
}
frames += 1;
}
static void changeScreenMode(){
Configuration::setFullscreen(!Configuration::getFullscreen());
int gfx = (Configuration::getFullscreen() ? Global::FULLSCREEN : Global::WINDOWED);
Graphics::changeGraphicsMode(gfx, Graphics::Bitmap::getScreenWidth(), Graphics::Bitmap::getScreenHeight());
}
static void checkFullscreen(){
InputMap<int> input;
input.set(Keyboard::Key_F11, 0, true, 5);
std::vector<InputMap<int>::InputEvent> events = InputManager::getEvents(input, InputSource(true));
for (std::vector<InputMap<int>::InputEvent>::iterator it = events.begin(); it != events.end(); it++){
InputMap<int>::InputEvent event = *it;
if (!event.enabled){
continue;
}
if (event.out == 5){
changeScreenMode();
}
}
}
/* FIXME: allow the user to customize this setting */
static bool useTouchOverlay(){
#ifdef ANDROID
return true;
#endif
return false;
}
static void doStandardLoop(Logic & logic, Draw & draw){
if (Graphics::screenParameter.current() == NULL){
throw Exception::Base(__FILE__, __LINE__);
}
const Graphics::Bitmap & screen = *Graphics::screenParameter.current();
screen.clear();
draw.drawFirst(screen.aspectRatio(640, 480));
screen.BlitToScreen();
Global::speed_counter4 = 0;
double runCounter = 0;
try{
const int maxCount = 20;
int frameCount = 0;
uint64_t frameTime = 0;
int logicCount = 0;
uint64_t logicTime = 0;
while (!logic.done()){
if (Global::speed_counter4 > 0){
// Global::debug(0) << "Speed counter " << Global::speed_counter4 << std::endl;
runCounter += logic.ticks(Global::speed_counter4);
Global::speed_counter4 = 0;
bool need_draw = false;
while (runCounter >= 1.0){
need_draw = true;
InputManager::poll();
checkFullscreen();
runCounter -= 1;
logicCount += 1;
uint64_t now = System::currentMilliseconds();
logic.run();
uint64_t later = System::currentMilliseconds();
logicTime += (later - now);
if (logicCount >= maxCount){
// Global::debug(0) << "Logic average " << (logicTime / logicCount) << "ms" << std::endl;
logicCount = 0;
logicTime = 0;
}
if (shutdown()){
throw ShutdownException();
}
if (logic.done()){
/* quit the loop immediately */
throw LoopDone();
}
}
if (need_draw){
frameCount += 1;
draw.updateFrames();
uint64_t now = System::currentMilliseconds();
screen.clear();
draw.draw(screen.aspectRatio(640, 480));
if (useTouchOverlay()){
InputManager::getTouch()->drawTouchOverlay(screen);
}
screen.BlitToScreen();
uint64_t later = System::currentMilliseconds();
frameTime += (later - now);
if (frameCount >= maxCount){
- // Global::debug(0) << "Draw average " << (frameTime / frameCount) << "ms" << std::endl;
+ Global::debug(0) << "Draw average " << (frameTime / frameCount) << "ms" << std::endl;
frameCount = 0;
frameTime = 0;
}
}
}
while (Global::speed_counter4 == 0){
/* if the fps is limited then don't keep redrawing */
if (Global::rateLimit){
rest(1);
} else {
draw.updateFrames();
screen.clear();
draw.draw(screen.aspectRatio(640, 480));
if (useTouchOverlay()){
InputManager::getTouch()->drawTouchOverlay(screen);
}
screen.BlitToScreen();
}
}
}
} catch (const LoopDone & done){
}
}
void standardLoop(Logic & logic, Draw & draw){
/* if a screen already exists (because we have nested standardLoops) then
* leave this parameter alone, otherwise set a new parameter.
*/
/*
if (Parameter<Graphics::Bitmap*>::current() == NULL){
doStandardLoop(logic, draw);
} else {
doStandardLoop(logic, draw);
}
*/
doStandardLoop(logic, draw);
}
}
diff --git a/src/graphics/allegro5/bitmap.cpp b/src/graphics/allegro5/bitmap.cpp
index aea0df99..576210e4 100644
--- a/src/graphics/allegro5/bitmap.cpp
+++ b/src/graphics/allegro5/bitmap.cpp
@@ -1,1649 +1,1655 @@
#include <sstream>
#include <allegro5/allegro5.h>
#include <allegro5/allegro_memfile.h>
#include <allegro5/allegro_primitives.h>
#include "r-tech1/debug.h"
#include "r-tech1/thread.h"
#include "r-tech1/input/touch.h"
#include "r-tech1/input/input-manager.h"
#include <vector>
namespace Graphics{
ALLEGRO_DISPLAY * the_display = NULL;
static std::vector<Util::ReferenceCount<Shader> > shaders;
// static ALLEGRO_SHADER * shader_default;
static Util::ReferenceCount<Shader> shader_shadow;
static Util::ReferenceCount<Shader> shader_lit_sprite;
enum BlendingType{
Translucent,
Add,
Difference,
Multiply
};
struct BlendingData{
BlendingData():
red(0), green(0), blue(0), alpha(0), type(Translucent){
}
int red, green, blue, alpha;
BlendingType type;
};
static BlendingData globalBlend;
Color makeColorAlpha(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha){
return Color(al_map_rgba(red, green, blue, alpha));
}
Color MaskColor(){
static Color mask = makeColorAlpha(0, 0, 0, 0);
return mask;
}
Color getBlendColor(){
/* sort of a hack */
if (globalBlend.type == Multiply){
return makeColorAlpha(255, 255, 255, 255);
}
return makeColorAlpha(255, 255, 255, globalBlend.alpha);
}
Color doTransBlend(const Color & color, int alpha){
unsigned char red, green, blue;
al_unmap_rgb(color.color, &red, &green, &blue);
return makeColorAlpha(red, green, blue, alpha);
/*
red *= alpha_f;
green *= alpha_f;
blue *= alpha_f;
return al_map_rgb_f(red, green, blue);
*/
}
Color transBlendColor(const Color & color){
return doTransBlend(color, globalBlend.alpha);
}
int getRealWidth(const Bitmap & what){
return al_get_bitmap_width(what.getData()->getBitmap());
}
int getRealHeight(const Bitmap & what){
return al_get_bitmap_height(what.getData()->getBitmap());
}
class Blender{
public:
Blender(){
}
virtual ~Blender(){
/* default is to draw the source and ignore the destination */
al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
}
};
class MaskedBlender: public Blender {
public:
MaskedBlender(){
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
}
};
class LitBlender: public Blender {
public:
LitBlender(ALLEGRO_COLOR lit){
// al_set_blend_color(lit);
// al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE_MINUS_DST_COLOR, ALLEGRO_ZERO);
}
};
class TransBlender: public Blender {
public:
TransBlender(){
switch (globalBlend.type){
case Translucent: al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA); break;
case Add: al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE); break;
case Multiply: al_set_blender(ALLEGRO_ADD, ALLEGRO_DEST_COLOR, ALLEGRO_INVERSE_ALPHA); break;
case Difference: al_set_blender(ALLEGRO_DEST_MINUS_SRC, ALLEGRO_ONE, ALLEGRO_ONE); break;
}
}
};
static const int WINDOWED = 0;
static const int FULLSCREEN = 1;
// static Bitmap * Scaler = NULL;
Bitmap::Bitmap():
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)),
width(0),
height(0){
/* TODO */
}
Bitmap::Bitmap( const char * load_file ):
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
internalLoadFile(load_file);
width = al_get_bitmap_width(getData()->getBitmap());
height = al_get_bitmap_height(getData()->getBitmap());
}
Bitmap::Bitmap( const std::string & load_file ):
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
internalLoadFile(load_file.c_str());
width = al_get_bitmap_width(getData()->getBitmap());
height = al_get_bitmap_height(getData()->getBitmap());
}
Bitmap::Bitmap(ALLEGRO_BITMAP * who, bool deep_copy):
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
if (deep_copy){
ALLEGRO_BITMAP * clone = al_clone_bitmap(who);
setData(Util::ReferenceCount<BitmapData>(new BitmapData(clone)));
} else {
setData(Util::ReferenceCount<BitmapData>(new BitmapData(who)));
}
this->width = al_get_bitmap_width(getData()->getBitmap());
this->height = al_get_bitmap_height(getData()->getBitmap());
}
Bitmap::Bitmap(int width, int height):
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
ALLEGRO_BITMAP * bitmap = al_create_bitmap(width, height);
if (bitmap == NULL){
std::ostringstream out;
out << "Could not create bitmap with dimensions " << width << ", " << height;
throw BitmapException(__FILE__, __LINE__, out.str());
}
/*
if (al_get_bitmap_flags(bitmap) & ALLEGRO_VIDEO_BITMAP){
ALLEGRO_BITMAP * old = al_get_target_bitmap();
al_set_target_bitmap(bitmap);
al_use_shader(shader_default);
al_set_target_bitmap(old);
}
*/
setData(Util::ReferenceCount<BitmapData>(new BitmapData(bitmap)));
this->width = al_get_bitmap_width(getData()->getBitmap());
this->height = al_get_bitmap_height(getData()->getBitmap());
}
Bitmap::Bitmap(const Bitmap & copy, bool deep_copy):
mustResize(false),
bit8MaskColor(copy.bit8MaskColor),
width(copy.width),
height(copy.height){
if (deep_copy){
ALLEGRO_BITMAP * clone = al_clone_bitmap(copy.getData()->getBitmap());
setData(Util::ReferenceCount<BitmapData>(new BitmapData(clone)));
} else {
setData(copy.getData());
}
}
Bitmap Bitmap::createMemoryBitmap(int width, int height){
int flags = al_get_new_bitmap_flags();
al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
Bitmap out = Bitmap(width, height);
al_set_new_bitmap_flags(flags);
return out;
}
+
+Bitmap Bitmap::subBitmap(int x, int y, int width, int height){
+ ALLEGRO_BITMAP * original = getData()->getBitmap();
+ ALLEGRO_BITMAP * sub = al_create_sub_bitmap(original, x, y, width, height);
+ return Bitmap(sub, false);
+}
void Bitmap::convertToVideo(){
ALLEGRO_BITMAP * original = getData()->getBitmap();
ALLEGRO_BITMAP * copy = al_clone_bitmap(original);
if (copy == NULL){
throw BitmapException(__FILE__, __LINE__, "Could not create video bitmap");
}
al_destroy_bitmap(getData()->getBitmap());
getData()->setBitmap(copy);
/*
if (al_get_bitmap_flags(copy) & ALLEGRO_VIDEO_BITMAP){
ALLEGRO_BITMAP * old = al_get_target_bitmap();
al_set_target_bitmap(copy);
al_use_shader(shader_default);
al_set_target_bitmap(old);
}
*/
}
void changeTarget(const Bitmap & from, const Bitmap & who){
/* pray that if drawing is held then who is already the current target */
if (!al_is_bitmap_drawing_held()){
if (al_get_target_bitmap() != who.getData()->getBitmap()){
al_set_target_bitmap(who.getData()->getBitmap());
}
if ((al_get_bitmap_flags(who.getData()->getBitmap()) & ALLEGRO_VIDEO_BITMAP) &&
(al_get_bitmap_flags(from.getData()->getBitmap()) & ALLEGRO_MEMORY_BITMAP)){
((Bitmap&) from).convertToVideo();
/* How can from == who? If they were the same then the bitmap flags above
* would not have been different.
*/
if (&from == &who){
al_set_target_bitmap(who.getData()->getBitmap());
}
}
}
}
void changeTarget(const Bitmap * from, const Bitmap & who){
changeTarget(*from, who);
}
void changeTarget(const Bitmap & from, const Bitmap * who){
changeTarget(from, *who);
}
void changeTarget(const Bitmap * from, const Bitmap * who){
changeTarget(*from, *who);
}
void dumpColor(const Color & color){
unsigned char red, green, blue, alpha;
al_unmap_rgba(color.color, &red, &green, &blue, &alpha);
Global::debug(0) << "red " << (int) red << " green " << (int) green << " blue " << (int) blue << " alpha " << (int) alpha << std::endl;
}
Color pcxMaskColor(unsigned char * data, const int length){
if (length >= 769){
if (data[length - 768 - 1] == 12){
unsigned char * palette = &data[length - 768];
unsigned char red = palette[0];
unsigned char green = palette[1];
unsigned char blue = palette[2];
return makeColorAlpha(red, green, blue, 255);
}
}
return makeColorAlpha(255, 255, 255, 255);
}
Bitmap memoryPCX(unsigned char * const data, const int length, const bool mask){
ALLEGRO_FILE * memory = al_open_memfile((void *) data, length, "r");
ALLEGRO_BITMAP * pcx = al_load_bitmap_f(memory, ".pcx");
al_fclose(memory);
if (pcx == NULL){
throw BitmapException(__FILE__, __LINE__, "Could not load pcx");
}
// dumpColor(al_get_pixel(pcx, 0, 0));
Bitmap out(pcx);
out.set8BitMaskColor(pcxMaskColor(data, length));
return out;
}
static bool isVideoBitmap(ALLEGRO_BITMAP * bitmap){
return (al_get_bitmap_flags(bitmap) & ALLEGRO_VIDEO_BITMAP) &&
!(al_get_bitmap_flags(bitmap) & ALLEGRO_MEMORY_BITMAP);
}
void Bitmap::replaceColor(const Color & original, const Color & replaced){
changeTarget(this, this);
if (isVideoBitmap(getData()->getBitmap())){
al_lock_bitmap(getData()->getBitmap(), ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE);
}
int width = getRealWidth(*this);
int height = getRealHeight(*this);
for (int x = 0; x < width; x++){
for (int y = 0; y < height; y++){
Color pixel = getPixel(x, y);
if (pixel == original){
al_put_pixel(x, y, replaced.color);
}
}
}
if (isVideoBitmap(getData()->getBitmap())){
al_unlock_bitmap(getData()->getBitmap());
}
}
static ALLEGRO_BITMAP * memoryGIF(const char * data, int length){
ALLEGRO_FILE * memory = al_open_memfile((void *) data, length, "r");
al_fclose(memory);
/* FIXME: get gif addon for a5 */
#if 0
RGB * palette = NULL;
/* algif will close the packfile for us in both error and success cases */
BITMAP * gif = load_gif_packfile(pack, palette);
if (!gif){
al_fclose(memory);
// pack_fclose(pack);
ostringstream out;
out <<"Could not load gif from memory: " << (void*) data << " length " << length;
throw LoadException(__FILE__, __LINE__, out.str());
}
BITMAP * out = create_bitmap(gif->w, gif->h);
blit(gif, out, 0, 0, 0, 0, gif->w, gif->h);
destroy_bitmap(gif);
// pack_fclose(pack);
#endif
ALLEGRO_BITMAP * out = NULL;
return out;
}
void Bitmap::internalLoadFile(const char * path){
this->path = path;
ALLEGRO_BITMAP * loaded = al_load_bitmap(path);
if (loaded == NULL){
std::ostringstream out;
out << "Could not load file '" << path << "'";
throw BitmapException(__FILE__, __LINE__, out.str());
}
al_convert_mask_to_alpha(loaded, al_map_rgb(255, 0, 255));
setData(Util::ReferenceCount<BitmapData>(new BitmapData(loaded)));
}
static ALLEGRO_BITMAP * do_load_from_memory(const char * data, int length, const char * type){
ALLEGRO_FILE * memory = al_open_memfile((void*) data, length, "r");
ALLEGRO_BITMAP * bitmap = al_load_bitmap_f(memory, type);
al_fclose(memory);
al_convert_mask_to_alpha(bitmap, al_map_rgb(255, 0, 255));
return bitmap;
}
static ALLEGRO_BITMAP * load_bitmap_from_memory(const char * data, int length, ImageFormat type){
switch (type){
case FormatBMP: return do_load_from_memory(data, length, ".bmp");
case FormatPNG: return do_load_from_memory(data, length, ".png");
case FormatJPG: return do_load_from_memory(data, length, ".jpg");
case FormatPCX: return do_load_from_memory(data, length, ".pcx");
case FormatTGA: return do_load_from_memory(data, length, ".tga");
case FormatTIF: return do_load_from_memory(data, length, ".tif");
case FormatXPM: return do_load_from_memory(data, length, ".xpm");
case FormatUnknown: break;
case FormatGIF : {
return memoryGIF(data, length);
break;
}
}
std::ostringstream out;
out << "Could not load the bitmap because its format was not known";
throw BitmapException(__FILE__, __LINE__, out.str());
}
Bitmap::Bitmap(const char * data, int length):
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
loadFromMemory(data, length);
}
void Bitmap::loadFromMemory(const char * data, int length){
setData(Util::ReferenceCount<BitmapData>(new BitmapData(load_bitmap_from_memory(data, length, identifyImage((const unsigned char *) data, length)))));
if (getData()->getBitmap() == NULL){
std::ostringstream out;
out << "Could not create bitmap from memory";
throw BitmapException(__FILE__, __LINE__, out.str());
}
width = al_get_bitmap_width(getData()->getBitmap());
height = al_get_bitmap_height(getData()->getBitmap());
}
Bitmap::Bitmap( const Bitmap & copy, int x, int y, int width, int height ):
mustResize(false),
bit8MaskColor(copy.bit8MaskColor),
width(width),
height(height){
path = copy.getPath();
ALLEGRO_BITMAP * his = copy.getData()->getBitmap();
if (x < 0)
x = 0;
if (y < 0)
y = 0;
if (width < 1 || height < 1){
std::ostringstream out;
out << "Attempting to create a sub-bitmap.";
if (width < 1){
out << " Width was less than 1: " << width;
}
if (height < 1){
out << " Height was less than 1: " << height;
}
throw BitmapException(__FILE__, __LINE__, out.str());
}
/*
if (width + x > al_get_bitmap_width(his)){
width = al_get_bitmap_width(his) - x;
}
if (height + y > al_get_bitmap_height(his)){
height = al_get_bitmap_height(his) - y;
}
*/
ALLEGRO_BITMAP * old_target = al_get_target_bitmap();
ALLEGRO_TRANSFORM transform;
al_identity_transform(&transform);
if (al_get_target_bitmap() != copy.getData()->getBitmap()){
al_set_target_bitmap(copy.getData()->getBitmap());
}
if (al_get_current_transform() != NULL){
if (old_target != copy.getData()->getBitmap()){
al_set_target_bitmap(copy.getData()->getBitmap());
}
al_copy_transform(&transform, al_get_current_transform());
}
float x_scaled = x;
float y_scaled = y;
float width_scaled = width;
float height_scaled = height;
al_transform_coordinates(&transform, &x_scaled, &y_scaled);
al_transform_coordinates(&transform, &width_scaled, &height_scaled);
// ALLEGRO_BITMAP * sub = al_create_sub_bitmap(his, x, y, width, height);
ALLEGRO_BITMAP * sub = al_create_sub_bitmap(his, (int) x_scaled, (int) y_scaled, (int) width_scaled, (int) height_scaled);
// ALLEGRO_BITMAP * sub = al_create_sub_bitmap(his, (int) x_scaled, (int) y_scaled, width, height);
setData(Util::ReferenceCount<BitmapData>(new BitmapData(sub)));
al_set_target_bitmap(sub);
al_use_transform(&transform);
al_set_target_bitmap(old_target);
}
static bool isBackBuffer(ALLEGRO_BITMAP * bitmap){
return bitmap == al_get_backbuffer(the_display);
}
int Bitmap::getWidth() const {
/* Always return the true dimensions of the backbuffer */
if (getData() != NULL && isBackBuffer(getData()->getBitmap())){
return al_get_bitmap_width(getData()->getBitmap());
}
return width;
/*
if (getData()->getBitmap() != NULL){
return al_get_bitmap_width(getData()->getBitmap());
}
return 0;
*/
}
int getRed(Color color){
unsigned char red, green, blue;
al_unmap_rgb(color.color, &red, &green, &blue);
return red;
}
int getAlpha(Color color){
unsigned char red, green, blue, alpha;
al_unmap_rgba(color.color, &red, &green, &blue, &alpha);
return alpha;
}
int getGreen(Color color){
unsigned char red, green, blue;
al_unmap_rgb(color.color, &red, &green, &blue);
return green;
}
int getBlue(Color color){
unsigned char red, green, blue;
al_unmap_rgb(color.color, &red, &green, &blue);
return blue;
}
Color makeColor(int red, int blue, int green){
return Color(al_map_rgb(red, blue, green));
}
int Bitmap::getHeight() const {
if (getData() != NULL && isBackBuffer(getData()->getBitmap())){
return al_get_bitmap_height(getData()->getBitmap());
}
return height;
/*
if (getData()->getBitmap() != NULL){
return al_get_bitmap_height(getData()->getBitmap());
}
return 0;
*/
}
void initializeExtraStuff(){
// al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_RGB_565);
}
std::string defaultVertexShader(){
return std::string(al_get_default_shader_source(ALLEGRO_SHADER_GLSL, ALLEGRO_VERTEX_SHADER));
}
std::string defaultPixelShader(){
return std::string(al_get_default_shader_source(ALLEGRO_SHADER_GLSL, ALLEGRO_PIXEL_SHADER));
}
void setShaderSampler(ALLEGRO_SHADER * shader, const std::string & name, const Bitmap & texture, int unit){
al_set_shader_sampler(name.c_str(), texture.getData()->getBitmap(), unit);
}
void setShaderBool(ALLEGRO_SHADER * shader, const std::string & name, bool value){
setShaderInt(shader, name, value);
}
void setShaderInt(ALLEGRO_SHADER * shader, const std::string & name, int value){
al_set_shader_int(name.c_str(), value);
}
void setShaderFloat(ALLEGRO_SHADER * shader, const std::string & name, float value){
al_set_shader_float(name.c_str(), value);
}
void setShaderVec4(ALLEGRO_SHADER * shader, const std::string & name, float v1, float v2, float v3, float v4){
float vector[4];
vector[0] = v1;
vector[1] = v2;
vector[2] = v3;
vector[3] = v4;
al_set_shader_float_vector(name.c_str(), 4, &vector[0], 1);
}
static std::string shader_version(const std::string & version, const std::string & data){
std::ostringstream out;
out << "#version " << version << "\n";
out << data;
return out.str();
}
Util::ReferenceCount<Shader> create_shader(const std::string & version, const std::string & vertex, const std::string & pixel){
ALLEGRO_SHADER * shader = al_create_shader(ALLEGRO_SHADER_GLSL);
if (shader == NULL){
return Util::ReferenceCount<Shader>(NULL);
}
if (!al_attach_shader_source(shader, ALLEGRO_VERTEX_SHADER, shader_version(version, vertex).c_str())){
Global::debug(0) << "attach vertex shader source failed: " << al_get_shader_log(shader) << std::endl << vertex << std::endl;
return Util::ReferenceCount<Shader>(NULL);
}
if (!al_attach_shader_source(shader, ALLEGRO_PIXEL_SHADER, shader_version(version, pixel).c_str())){
Global::debug(0) << "attach pixel shader source failed: " << al_get_shader_log(shader) << std::endl << pixel << std::endl;
Global::debug(0) << "Pixel source: \n" << shader_version(version, pixel) << std::endl;
return Util::ReferenceCount<Shader>(NULL);
}
if (!al_build_shader(shader)){
Global::debug(0) << "shader al_link_shader failed: " << al_get_shader_log(shader) << " pixel: " << pixel << " vertex: " << vertex << std::endl;
return Util::ReferenceCount<Shader>(NULL);
}
return Util::ReferenceCount<Shader>(new Shader(shader));
}
int changeGraphicsMode(int mode, int width, int height){
switch (mode){
case FULLSCREEN: {
al_set_display_flag(the_display, ALLEGRO_FULLSCREEN_WINDOW, true);
break;
}
case WINDOWED: {
al_set_display_flag(the_display, ALLEGRO_FULLSCREEN_WINDOW, false);
break;
}
}
return !al_resize_display(the_display, width, height);
}
static int createShaders(){
try{
shader_shadow = create_shader("100", defaultVertexShader(), Storage::readFile(Storage::instance().find(Filesystem::RelativePath("shaders/shadow.fragment.glsl"))));
if (shader_shadow == NULL){
Global::debug(0) << "Could not create shader for shaders/shadow.fragment.glsl" << std::endl;
return 1;
}
shaders.push_back(shader_shadow);
Global::debug(1) << "Created shadow shader" << std::endl;
} catch (const Filesystem::NotFound & fail){
Global::debug(0) << "Could not load shadow shader: " << fail.getTrace() << std::endl;
return 1;
}
try{
shader_lit_sprite = create_shader("100", defaultVertexShader(), Storage::readFile(Storage::instance().find(Filesystem::RelativePath("shaders/lit-sprite.fragment.glsl"))));
if (shader_lit_sprite == NULL){
return 1;
}
shaders.push_back(shader_lit_sprite);
Global::debug(1) << "Created lit sprite shader" << std::endl;
} catch (const Filesystem::NotFound & fail){
Global::debug(0) << "Could not load lit sprite shader: " << fail.getTrace() << std::endl;
return 1;
}
return 0;
}
int setGraphicsMode(int mode, int width, int height){
initializeExtraStuff();
/* FIXME: the configuration should pass in fullscreen mode here */
#ifdef IPHONE
mode = FULLSCREEN;
#endif
switch (mode){
case FULLSCREEN: {
#ifdef IPHONE
al_set_new_display_option(ALLEGRO_SUPPORTED_ORIENTATIONS, ALLEGRO_DISPLAY_ORIENTATION_LANDSCAPE, ALLEGRO_SUGGEST);
al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW | ALLEGRO_PROGRAMMABLE_PIPELINE);
#else
#ifdef ANDROID
al_set_new_display_flags(ALLEGRO_FULLSCREEN | ALLEGRO_PROGRAMMABLE_PIPELINE);
#else
al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW | ALLEGRO_RESIZABLE |
ALLEGRO_OPENGL | ALLEGRO_PROGRAMMABLE_PIPELINE);
#endif
#endif
break;
}
case WINDOWED: {
al_set_new_display_flags(ALLEGRO_WINDOWED | ALLEGRO_RESIZABLE |
ALLEGRO_PROGRAMMABLE_PIPELINE |
ALLEGRO_OPENGL);
break;
}
default: break;
}
the_display = al_create_display(width, height);
if (the_display == NULL){
std::ostringstream out;
out << "Could not create display with dimensions " << width << ", " << height;
throw BitmapException(__FILE__, __LINE__, out.str());
}
// Global::debug(0) << "Set width " << al_get_display_width(the_display) << " height " << al_get_display_height(the_display) << std::endl;
// Global::debug(0) << "Backbuffer width " << al_get_bitmap_width(al_get_backbuffer(the_display)) << " height " << al_get_bitmap_height(al_get_backbuffer(the_display)) << std::endl;
try{
/* TODO: maybe find a more general way to get the icon */
ALLEGRO_BITMAP * icon = al_load_bitmap(Storage::instance().find(Filesystem::RelativePath("menu/icon.bmp")).path().c_str());
if (icon != NULL){
al_set_display_icon(the_display, icon);
}
} catch (const Filesystem::NotFound & fail){
Global::debug(0) << "Could not set window icon: " << fail.getTrace() << std::endl;
}
Screen = new Bitmap(al_get_backbuffer(the_display));
/* dont destroy the backbuffer */
Screen->getData()->setDestroy(false);
/*
ALLEGRO_TRANSFORM transformation;
al_identity_transform(&transformation);
al_scale_transform(&transformation, (double) Screen->getWidth() / (double) width, (double) Screen->getHeight() / (double) height);
al_set_target_bitmap(Screen->getData()->getBitmap());
al_use_transform(&transformation);
*/
// Scaler = new Bitmap(width, height);
/* default drawing mode */
// al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
// shader_default = create_shader(defaultVertexShader(), defaultPixelShader());
// al_use_shader(shader_default);
/* Default shader */
/*
shader_default = al_create_shader(ALLEGRO_SHADER_GLSL);
al_attach_shader_source(shader_default, ALLEGRO_VERTEX_SHADER, al_get_default_glsl_vertex_shader());
al_attach_shader_source(shader_default, ALLEGRO_PIXEL_SHADER, al_get_default_glsl_pixel_shader());
if (!al_link_shader(shader_default)){
Global::debug(0) << "default shader al_link_shader failed: " << al_get_shader_log(shader_default) << std::endl;
return 1;
}
*/
// al_set_shader(the_display, shader_default);
// shaders.push_back(shader_default);
// Global::debug(1) << "Created default shader" << std::endl;
if (createShaders()){
return 1;
}
return 0;
}
void Bitmap::lock() const {
al_lock_bitmap(getData()->getBitmap(), ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE);
}
void Bitmap::lock(int x, int y, int width, int height) const {
al_lock_bitmap_region(getData()->getBitmap(), x, y, width, height, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE);
}
void Bitmap::unlock() const {
al_unlock_bitmap(getData()->getBitmap());
}
Color Bitmap::getPixel(const int x, const int y) const {
// changeTarget(this, this);
return Color(al_get_pixel(getData()->getBitmap(), x, y));
}
void Bitmap::putPixel(int x, int y, Color pixel) const {
changeTarget(this, this);
// al_put_pixel(x, y, pixel);
al_draw_pixel(x, y, pixel.color);
}
void Bitmap::putPixelNormal(int x, int y, Color col) const {
putPixel(x, y, col);
/*
changeTarget(this, this);
al_put_pixel(x, y, col.color);
*/
}
void Bitmap::fill(Color color) const {
changeTarget(this, this);
al_clear_to_color(color.color);
}
void Bitmap::startDrawing() const {
/* we are about to draw on this bitmap so make sure we are the target */
changeTarget(this, this);
al_hold_bitmap_drawing(true);
}
void Bitmap::endDrawing() const {
al_hold_bitmap_drawing(false);
}
void TranslucentBitmap::startDrawing() const {
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
}
void TranslucentBitmap::endDrawing() const {
al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
}
Color Bitmap::blendColor(const Color & input) const {
return input;
}
Color TranslucentBitmap::blendColor(const Color & color) const {
unsigned char red, green, blue;
unsigned char alpha = globalBlend.alpha;
al_unmap_rgb(color.color, &red, &green, &blue);
return makeColorAlpha(red, green, blue, alpha);
}
void Bitmap::StretchHqx(const Bitmap & where, const int sourceX, const int sourceY, const int sourceWidth, const int sourceHeight, const int destX, const int destY, const int destWidth, const int destHeight) const {
/* TODO */
}
void Bitmap::StretchXbr(const Bitmap & where, const int sourceX, const int sourceY, const int sourceWidth, const int sourceHeight, const int destX, const int destY, const int destWidth, const int destHeight) const {
/* TODO */
}
void Bitmap::Stretch(const Bitmap & where, const int sourceX, const int sourceY, const int sourceWidth, const int sourceHeight, const int destX, const int destY, const int destWidth, const int destHeight) const {
changeTarget(this, where);
al_draw_scaled_bitmap(getData()->getBitmap(),
sourceX, sourceY, sourceWidth, sourceHeight,
destX, destY, destWidth, destHeight,
0);
}
void Bitmap::StretchBy2(const Bitmap & where){
Stretch(where, 0, 0, getWidth(), getHeight(), 0, 0, getWidth() * 2, getHeight() * 2);
}
void Bitmap::StretchBy4(const Bitmap & where){
Stretch(where, 0, 0, getWidth(), getHeight(), 0, 0, getWidth() * 4, getHeight() * 4);
}
void Bitmap::drawRotate(const int x, const int y, const int angle, const Bitmap & where ){
changeTarget(this, where);
MaskedBlender blender;
al_draw_rotated_bitmap(getData()->getBitmap(), getWidth() / 2, getHeight() / 2, x, y, Util::radians(angle), ALLEGRO_FLIP_HORIZONTAL);
}
void Bitmap::drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const Bitmap & where ){
changeTarget(this, where);
MaskedBlender blender;
al_draw_rotated_bitmap(getData()->getBitmap(), getWidth() / 2, getHeight() / 2, x, y, Util::radians(-angle), 0);
}
void Bitmap::drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const double scale, const Bitmap & where ){
/* TODO */
}
void Bitmap::drawStretched( const int x, const int y, const int new_width, const int new_height, const Bitmap & who ) const {
/* FIXME */
changeTarget(this, who);
MaskedBlender blender;
al_draw_scaled_bitmap(getData()->getBitmap(), 0, 0, al_get_bitmap_width(getData()->getBitmap()), al_get_bitmap_height(getData()->getBitmap()), x, y, new_width, new_height, 0);
#if 0
ALLEGRO_TRANSFORM save;
al_copy_transform(&save, al_get_current_transform());
ALLEGRO_TRANSFORM stretch;
al_identity_transform(&stretch);
// al_translate_transform(&stretch, x / ((double) new_width / getWidth()), y / ((double) new_height / getHeight()));
al_scale_transform(&stretch, (double) new_width / getWidth(), (double) new_height / getHeight());
al_translate_transform(&stretch, x, y);
// al_translate_transform(&stretch, -x / ((double) new_width / getWidth()), -y / ((double) (new_height / getHeight())));
al_use_transform(&stretch);
/* any source pixels with an alpha value of 0 will be masked */
// al_draw_bitmap(getData().getBitmap(), x, y, 0);
al_draw_bitmap(getData().getBitmap(), 0, 0, 0);
al_use_transform(&save);
#endif
}
Bitmap Bitmap::scaleTo(const int width, const int height) const {
if (width == getRealWidth(*this) && height == getRealHeight(*this)){
return *this;
}
Bitmap scaled(width, height);
changeTarget(*this, scaled);
al_draw_scaled_bitmap(getData()->getBitmap(), 0, 0, getRealWidth(*this), getRealHeight(*this),
0, 0, width, height, 0);
return scaled;
}
void Bitmap::Blit(const int mx, const int my, const int width, const int height, const int wx, const int wy, const Bitmap & where) const {
// double start = al_get_time();
// changeTarget(this, where);
// al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
/*
if (&where != Screen){
al_draw_bitmap(getData().getBitmap(), wx, wy, 0);
}
*/
changeTarget(this, where);
Bitmap part(*this, mx, my, width, height);
// al_use_shader(shader_default);
// al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
al_draw_bitmap(part.getData()->getBitmap(), wx, wy, 0);
/*
double end = al_get_time();
Global::debug(0) << "Draw in " << (end - start) << " seconds" << std::endl;
*/
}
void Bitmap::drawHFlip(const int x, const int y, const Bitmap & where) const {
draw(x, y, NULL, where, ALLEGRO_FLIP_HORIZONTAL);
}
void Bitmap::drawHFlip(const int x, const int y, Filter * filter, const Bitmap & where) const {
draw(x, y, filter, where, ALLEGRO_FLIP_HORIZONTAL);
}
void Bitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
draw(x, y, NULL, where, ALLEGRO_FLIP_VERTICAL);
}
void Bitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, ALLEGRO_FLIP_VERTICAL);
}
void Bitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
draw(x, y, NULL, where, ALLEGRO_FLIP_HORIZONTAL | ALLEGRO_FLIP_VERTICAL);
}
void Bitmap::drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, ALLEGRO_FLIP_HORIZONTAL | ALLEGRO_FLIP_VERTICAL);
}
void Bitmap::BlitMasked(const int mx, const int my, const int width, const int height, const int wx, const int wy, const Bitmap & where) const {
/* TODO */
}
void Bitmap::BlitToScreen(const int upper_left_x, const int upper_left_y) const {
#if 0
if (getWidth() != Screen->getWidth() || getHeight() != Screen->getHeight()){
/*
this->Blit( upper_left_x, upper_left_y, *Buffer );
Buffer->Stretch(*Scaler);
Scaler->Blit(0, 0, 0, 0, *Screen);
*/
this->Stretch(*Scaler, 0, 0, getWidth(), getHeight(), upper_left_x, upper_left_y, Scaler->getWidth(), Scaler->getHeight());
Scaler->Blit(0, 0, 0, 0, *Screen);
} else {
this->Blit(upper_left_x, upper_left_y, *Screen);
}
#endif
/*
if (&where == Screen){
al_flip_display();
}
*/
changeTarget(this, Screen);
if (getData()->getBitmap() != Screen->getData()->getBitmap()){
Blit(*Screen);
}
al_flip_display();
}
void Bitmap::BlitAreaToScreen(const int upper_left_x, const int upper_left_y) const {
changeTarget(this, Screen);
/*
if (getData()->getBitmap() != Screen->getData()->getBitmap()){
Blit(upper_left_y, upper_left_y, *Screen);
}
*/
al_flip_display();
}
void Bitmap::draw(const int x, const int y, Filter * filter, const Bitmap & where, int flags) const {
changeTarget(this, where);
MaskedBlender blender;
Util::ReferenceCount<Shader> shader;
if (filter != NULL){
shader = filter->getShader();
}
ALLEGRO_SHADER * a5shader = NULL;
if (shader != NULL){
a5shader = shader->getShader();
}
if (a5shader != NULL){
al_use_shader(a5shader);
filter->setupShader(shader);
}
/* any source pixels with an alpha value of 0 will be masked */
al_draw_bitmap(getData()->getBitmap(), x, y, flags);
if (a5shader != NULL){
al_use_shader(NULL);
}
}
void Bitmap::draw(const int x, const int y, const Bitmap & where) const {
draw(x, y, NULL, where, 0);
/*
// TransBlender blender;
changeTarget(this, where);
MaskedBlender blender;
/ * any source pixels with an alpha value of 0 will be masked * /
al_draw_bitmap(getData()->getBitmap(), x, y, 0);
*/
}
void Bitmap::draw(const int x, const int y, Filter * filter, const Bitmap & where) const {
draw(x, y, filter, where, 0);
}
void Bitmap::drawShadow(Bitmap & where, int x, int y, int intensity, Color color, double scale, bool facingRight) const {
changeTarget(this, where);
MaskedBlender blender;
int newHeight = fabs(scale) * getHeight();
int flags = 0;
if (!facingRight){
flags |= ALLEGRO_FLIP_HORIZONTAL;
}
float shadowColor[4];
al_unmap_rgb_f(color.color, &shadowColor[0], &shadowColor[1], &shadowColor[2]);
shadowColor[3] = (float) intensity / 255.0;
al_use_shader(shader_shadow->getShader());
if (!al_set_shader_float_vector("shadow", 4, shadowColor, 1)){
/* Well.. thats not good. Did the shader source get messed up? */
}
al_draw_scaled_bitmap(getData()->getBitmap(), 0, 0, getWidth(), getHeight(), x, y - newHeight, getWidth(), newHeight, flags);
al_use_shader(NULL);
}
void Bitmap::hLine(const int x1, const int y, const int x2, const Color color) const {
line(x1, y, x2, y, color);
}
void Bitmap::vLine(const int y1, const int x, const int y2, const Color color) const {
line(x, y1, x, y2, color);
}
void Bitmap::arc(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const {
changeTarget(this, this);
al_draw_arc(x, y, radius, ang1 - Util::pi/2, ang2 - ang1, color.color, 1);
}
void TranslucentBitmap::arc(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const {
TransBlender blender;
Bitmap::arc(x, y, ang1, ang2, radius, transBlendColor(color));
/*
changeTarget(this);
al_draw_arc(x, y, radius, ang1 + S_PI/2, ang2 - ang1, doTransBlend(color, globalBlend.alpha), 0);
*/
}
/* from http://www.allegro.cc/forums/thread/605684/892721#target */
#if 0
void al_draw_filled_pieslice(float cx, float cy, float r, float start_theta,
float delta_theta, ALLEGRO_COLOR color){
ALLEGRO_VERTEX vertex_cache[ALLEGRO_VERTEX_CACHE_SIZE];
int num_segments, ii;
num_segments = fabs(delta_theta / (2 * ALLEGRO_PI) * ALLEGRO_PRIM_QUALITY * sqrtf(r));
if (num_segments < 2)
return;
if (num_segments >= ALLEGRO_VERTEX_CACHE_SIZE) {
num_segments = ALLEGRO_VERTEX_CACHE_SIZE - 1;
}
al_calculate_arc(&(vertex_cache[1].x), sizeof(ALLEGRO_VERTEX), cx, cy, r, r, start_theta, delta_theta, 0, num_segments);
vertex_cache[0].x = cx; vertex_cache[0].y = cy;
for (ii = 0; ii < num_segments + 1; ii++) {
vertex_cache[ii].color = color;
vertex_cache[ii].z = 0;
}
al_draw_prim(vertex_cache, NULL, NULL, 0, num_segments + 1, ALLEGRO_PRIM_TRIANGLE_FAN);
// al_draw_prim(vertex_cache, NULL, NULL, 0, 3, ALLEGRO_PRIM_TRIANGLE_FAN);
}
#endif
static float min(float a, float b){
return a < b ? a : b;
}
void Bitmap::roundRect(int radius, int x1, int y1, int x2, int y2, Color color) const {
changeTarget(this, this);
double mx = x2 - x1;
double my = y2 - y1;
double radius_use = min(min(radius, mx / 2), my / 2);
al_draw_rounded_rectangle(x1, y1, x2, y2, radius_use, radius_use, color.color, 1);
}
void TranslucentBitmap::roundRect(int radius, int x1, int y1, int x2, int y2, Color color) const {
TransBlender blender;
Bitmap::roundRect(radius, x1, y1, x2, y2, transBlendColor(color));
}
void Bitmap::roundRectFill(int radius, int x1, int y1, int x2, int y2, Graphics::Color color) const {
changeTarget(this, this);
double mx = x2 - x1;
double my = y2 - y1;
double radius_use = min(min(radius, mx / 2), my / 2);
al_draw_filled_rounded_rectangle(x1, y1, x2, y2, radius_use, radius_use, color.color);
}
void TranslucentBitmap::roundRectFill(int radius, int x1, int y1, int x2, int y2, Graphics::Color color) const {
TransBlender blender;
Bitmap::roundRectFill(radius, x1, y1, x2, y2, transBlendColor(color));
}
void Bitmap::arcFilled(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const {
changeTarget(this, this);
al_draw_filled_pieslice(x, y, radius, ang1 - Util::pi/2, ang2 - ang1, color.color);
}
void TranslucentBitmap::arcFilled(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const {
changeTarget(this, this);
TransBlender blender;
Bitmap::arcFilled(x, y, ang1, ang2, radius, transBlendColor(color));
}
void Bitmap::floodfill( const int x, const int y, const Color color ) const {
/* TODO */
}
void Bitmap::line(const int x1, const int y1, const int x2, const int y2, const Color color) const {
changeTarget(this, this);
al_draw_line(x1, y1, x2, y2, color.color, 1);
}
void TranslucentBitmap::line(const int x1, const int y1, const int x2, const int y2, const Color color) const {
TransBlender blender;
Bitmap::line(x1, y1, x2, y2, transBlendColor(color));
}
void Bitmap::circleFill(int x, int y, int radius, Color color) const {
changeTarget(this, this);
al_draw_filled_circle(x, y, radius, color.color);
}
void Bitmap::circle(int x, int y, int radius, Color color) const {
changeTarget(this, this);
al_draw_circle(x, y, radius, color.color, 1);
}
void Bitmap::circle(int x, int y, int radius, int thickness, Color color) const {
changeTarget(this, this);
al_draw_circle(x, y, radius, color.color, thickness);
}
void Bitmap::rectangle(int x1, int y1, int x2, int y2, Color color ) const {
changeTarget(this, this);
// al_draw_rectangle(x1, y1, x2, y2, color.color, 0);
al_draw_rectangle(x1 + 0.5, y1 + 0.5, x2 - 0.5, y2 - 0.5, color.color, 1);
}
void Bitmap::rectangleFill( int x1, int y1, int x2, int y2, Color color ) const {
changeTarget(this, this);
// al_draw_filled_rectangle(x1 - 0.5, y1 - 0.5, x2 + 0.5, y2 + 0.5, color.color);
al_draw_filled_rectangle(x1, y1, x2 + 1, y2 + 1, color.color);
}
void Bitmap::triangle( int x1, int y1, int x2, int y2, int x3, int y3, Color color ) const {
changeTarget(this, this);
al_draw_filled_triangle(x1, y1, x2, y2, x3, y3, color.color);
}
void Bitmap::polygon( const int * verts, const int nverts, const Color color ) const {
/* TODO */
}
void Bitmap::ellipse( int x, int y, int rx, int ry, Color color ) const {
changeTarget(this, this);
al_draw_ellipse(x, y, rx, ry, color.color, 0);
}
void Bitmap::ellipseFill( int x, int y, int rx, int ry, Color color ) const {
changeTarget(this, this);
al_draw_filled_ellipse(x, y, rx, ry, color.color);
}
void Bitmap::applyTrans(const Color color) const {
TransBlender blender;
changeTarget(this, this);
al_draw_filled_rectangle(0, 0, getWidth(), getHeight(), transBlendColor(color).color);
}
void Bitmap::light(int x, int y, int width, int height, int start_y, int focus_alpha, int edge_alpha, Color focus_color, Color edge_color) const {
/* TODO */
}
void Bitmap::drawCharacter( const int x, const int y, const Color color, const int background, const Bitmap & where ) const {
/* TODO */
}
void Bitmap::save( const std::string & str ) const {
/* TODO */
}
void Bitmap::readLine(std::vector<Color> & line, int y){
/* TODO */
}
void TranslucentBitmap::draw(const int x, const int y, Filter * filter, const Bitmap & where, int flags) const {
changeTarget(this, where);
TransBlender blender;
Util::ReferenceCount<Shader> shader;
if (filter != NULL){
shader = filter->getShader();
}
ALLEGRO_SHADER * a5shader = NULL;
if (shader != NULL){
a5shader = shader->getShader();
}
if (a5shader != NULL){
al_use_shader(a5shader);
filter->setupShader(shader);
}
al_draw_tinted_bitmap(getData()->getBitmap(), getBlendColor().color, x, y, flags);
if (a5shader != NULL){
al_use_shader(NULL);
}
}
void TranslucentBitmap::draw(const int x, const int y, const Bitmap & where) const {
draw(x, y, NULL, where, 0);
}
void LitBitmap::draw(const int x, const int y, const Bitmap & where) const {
draw(x, y, NULL, where, 0);
}
void LitBitmap::draw(const int x, const int y, Filter * filter, const Bitmap & where, int flags) const {
if (filter == NULL){
changeTarget(this, where);
/*
TransBlender blender;
Util::ReferenceCount<Shader> shader;
if (filter != NULL){
shader = filter->getShader();
}
ALLEGRO_SHADER * a5shader = NULL;
if (shader != NULL){
a5shader = shader->getShader();
}
if (a5shader != NULL){
al_set_shader(the_display, a5shader);
al_use_shader(a5shader, true);
}
al_draw_tinted_bitmap(getData()->getBitmap(), getBlendColor().color, x, y, flags);
if (a5shader != NULL){
al_set_shader(the_display, shader_default);
al_use_shader(shader_default, true);
}
*/
MaskedBlender blender;
ALLEGRO_SHADER * shader = shader_lit_sprite->getShader();
float light[4];
Color color = makeColor(globalBlend.red, globalBlend.green, globalBlend.blue);
al_unmap_rgb_f(color.color, &light[0], &light[1], &light[2]);
light[3] = 1;
float intensity = (float) globalBlend.alpha / 255.0;
al_use_shader(shader);
if (!al_set_shader_float_vector("light_color", 4, light, 1)){
/* Well.. thats not good. Did the shader source get messed up? */
}
if (!al_set_shader_float("light_intensity", intensity)){
}
al_draw_bitmap(getData()->getBitmap(), x, y, flags);
al_use_shader(NULL);
} else {
Bitmap temp(getWidth(), getHeight());
temp.fill(MaskColor());
Bitmap::draw(0, 0, filter, temp, 0);
LitBitmap(temp).draw(x, y, NULL, where, flags);
}
}
void LitBitmap::draw( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, 0);
// LitBlender blender(makeColorAlpha(globalBlend.red, globalBlend.green, globalBlend.blue, globalBlend.alpha));
// TransBlender blender;
// al_draw_bitmap(getData()->getBitmap(), x, y, 0);
// al_draw_tinted_bitmap(getData()->getBitmap(), al_map_rgba_f(1, 0, 0, 1), x, y, 0);
}
void LitBitmap::drawHFlip( const int x, const int y, const Bitmap & where ) const {
draw(x, y, NULL, where, ALLEGRO_FLIP_HORIZONTAL);
}
void LitBitmap::drawHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, ALLEGRO_FLIP_HORIZONTAL);
}
void LitBitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
draw(x, y, NULL, where, ALLEGRO_FLIP_VERTICAL);
}
void LitBitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, ALLEGRO_FLIP_VERTICAL);
}
void LitBitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
draw(x, y, NULL, where, ALLEGRO_FLIP_HORIZONTAL | ALLEGRO_FLIP_VERTICAL);
}
void LitBitmap::drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, ALLEGRO_FLIP_HORIZONTAL | ALLEGRO_FLIP_VERTICAL);
}
void TranslucentBitmap::draw( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, 0);
}
void TranslucentBitmap::drawHFlip( const int x, const int y, const Bitmap & where ) const {
draw(x, y, NULL, where, ALLEGRO_FLIP_HORIZONTAL);
}
void TranslucentBitmap::drawHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, ALLEGRO_FLIP_HORIZONTAL);
}
void TranslucentBitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
draw(x, y, NULL, where, ALLEGRO_FLIP_VERTICAL);
}
void TranslucentBitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, ALLEGRO_FLIP_VERTICAL);
}
void TranslucentBitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
draw(x, y, NULL, where, ALLEGRO_FLIP_HORIZONTAL | ALLEGRO_FLIP_VERTICAL);
}
void TranslucentBitmap::drawHVFlip( const int x, const int y, Filter * filter,const Bitmap & where ) const {
draw(x, y, filter, where, ALLEGRO_FLIP_HORIZONTAL | ALLEGRO_FLIP_VERTICAL);
}
void TranslucentBitmap::hLine( const int x1, const int y, const int x2, const Color color ) const {
TransBlender blender;
Bitmap::hLine(x1, y, x2, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::circleFill(int x, int y, int radius, Color color) const {
TransBlender blender;
Bitmap::circleFill(x, y, radius, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::putPixelNormal(int x, int y, Color color) const {
TransBlender blender;
Bitmap::putPixelNormal(x, y, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::rectangle( int x1, int y1, int x2, int y2, Color color ) const {
TransBlender blender;
Bitmap::rectangle(x1, y1, x2, y2, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::rectangleFill(int x1, int y1, int x2, int y2, Color color) const {
TransBlender blender;
Bitmap::rectangleFill(x1, y1, x2, y2, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::ellipse( int x, int y, int rx, int ry, Color color ) const {
TransBlender blender;
Bitmap::ellipse(x, y, rx, ry, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::ellipseFill( int x, int y, int rx, int ry, Color color ) const {
TransBlender blender;
Bitmap::ellipseFill(x, y, rx, ry, doTransBlend(color, globalBlend.alpha));
}
void Bitmap::setClipRect( int x1, int y1, int x2, int y2 ) const {
/* TODO */
}
void Bitmap::getClipRect(int & x1, int & y1, int & x2, int & y2) const {
/* TODO */
}
int setGfxModeFullscreen(int x, int y){
return setGraphicsMode(FULLSCREEN, x, y);
}
int setGfxModeWindowed( int x, int y ){
return setGraphicsMode(WINDOWED, x, y);
}
int setGfxModeText(){
/* TODO */
return 0;
}
bool Bitmap::getError(){
/* TODO */
return false;
}
void Bitmap::alphaBlender(int source, int dest){
/* TODO */
}
void Bitmap::transBlender(int r, int g, int b, int a){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
globalBlend.type = Translucent;
}
void Bitmap::addBlender(int r, int g, int b, int a){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
globalBlend.type = Add;
}
void Bitmap::differenceBlender( int r, int g, int b, int a ){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
globalBlend.type = Difference;
}
void Bitmap::multiplyBlender( int r, int g, int b, int a ){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
globalBlend.type = Multiply;
}
/*
void Bitmap::drawingMode(int type){
}
*/
void Bitmap::shutdown(){
/* Make sure the display is set */
if (Screen != NULL){
al_set_target_bitmap(Screen->getData()->getBitmap());
}
al_use_shader(NULL);
shaders.clear();
shader_shadow = NULL;
shader_lit_sprite = NULL;
/*
for (std::vector<ALLEGRO_SHADER*>::iterator it = shaders.begin(); it != shaders.end(); it++){
ALLEGRO_SHADER * shader = *it;
al_destroy_shader(shader);
}
*/
delete Screen;
Screen = NULL;
al_destroy_display(the_display);
the_display = NULL;
/*
delete Scaler;
Scaler = NULL;
delete Buffer;
Buffer = NULL;
*/
}
StretchedBitmap::StretchedBitmap(int width, int height, const Bitmap & parent, Clear clear, QualityFilter filter):
Bitmap(parent, 0, 0, parent.getWidth(), parent.getHeight()),
width(width),
height(height),
where(parent),
filter(filter),
clearKind(clear){
scale_x = (double) parent.getWidth() / width;
scale_y = (double) parent.getHeight() / height;
ALLEGRO_BITMAP * old_target = al_get_target_bitmap();
if (al_get_target_bitmap() != parent.getData()->getBitmap()){
al_set_target_bitmap(parent.getData()->getBitmap());
}
ALLEGRO_TRANSFORM transform;
al_identity_transform(&transform);
if (al_get_current_transform() != NULL){
al_copy_transform(&transform, al_get_current_transform());
}
al_scale_transform(&transform, scale_x, scale_y);
if (al_get_target_bitmap() != getData()->getBitmap()){
al_set_target_bitmap(getData()->getBitmap());
}
al_use_transform(&transform);
if (old_target != al_get_target_bitmap()){
al_set_target_bitmap(old_target);
}
switch (clear){
case NoClear: break;
case FullClear: this->clear();
case Mask: break;
}
/* TODO: handle filter */
}
void StretchedBitmap::start(){
#if 0
ALLEGRO_TRANSFORM transform;
changeTarget(this, this);
al_copy_transform(&transform, al_get_current_transform());
// al_identity_transform(&transform);
// al_scale_transform(&transform, Bitmap::getWidth() / width, Bitmap::getHeight() / height);
al_scale_transform(&transform, scale_x, scale_y);
al_use_transform(&transform);
#endif
}
void StretchedBitmap::finish(){
#if 0
ALLEGRO_TRANSFORM transform;
changeTarget(this, this);
al_copy_transform(&transform, al_get_current_transform());
/* apply the inverse transform */
al_scale_transform(&transform, 1.0/scale_x, 1.0/scale_y);
// al_identity_transform(&transform);
al_use_transform(&transform);
#endif
}
SubTranslucentBitmap::SubTranslucentBitmap(const Bitmap & where, int x, int y, int width, int height, Clear clear):
Bitmap(where, x, y, width, height),
translucent(*this),
clearKind(clear){
switch (clear){
case NoClear: break;
case FullClear: translucent.clear();
case Mask: break;
}
}
void SubTranslucentBitmap::finish(){
}
void SubTranslucentBitmap::start(){
}
void SubTranslucentBitmap::roundRect(int radius, int x1, int y1, int x2, int y2, Color color) const {
translucent.roundRect(radius, x1, y1, x2, y2, color);
}
void SubTranslucentBitmap::roundRectFill(int radius, int x1, int y1, int x2, int y2, Graphics::Color color) const {
translucent.roundRectFill(radius, x1, y1, x2, y2, color);
}
TranslatedBitmap::TranslatedBitmap(int x, int y, const Bitmap & where):
Bitmap(where),
x(x),
y(y){
ALLEGRO_TRANSFORM transform;
changeTarget(this, where);
al_identity_transform(&transform);
if (al_get_current_transform() != NULL){
al_copy_transform(&transform, al_get_current_transform());
}
al_translate_transform(&transform, x, y);
al_use_transform(&transform);
}
void TranslatedBitmap::BlitToScreen() const {
Bitmap::BlitToScreen();
}
TranslatedBitmap::~TranslatedBitmap(){
ALLEGRO_TRANSFORM transform;
al_copy_transform(&transform, al_get_current_transform());
al_translate_transform(&transform, -x, -y);
al_use_transform(&transform);
}
Bitmap * getScreenBuffer(){
return Screen;
}
RestoreState::RestoreState(){
al_store_state(&state, ALLEGRO_STATE_ALL);
}
RestoreState::~RestoreState(){
al_restore_state(&state);
}
Shader::Shader():
shader(NULL){
}
Shader::~Shader(){
if (shader != NULL){
al_destroy_shader(shader);
}
}
Shader::Shader(ALLEGRO_SHADER * shader):
shader(shader){
}
ALLEGRO_SHADER * Shader::getShader(){
return shader;
}
}
static inline bool close(float x, float y){
static float epsilon = 0.001;
return fabs(x - y) < epsilon;
}
static inline bool sameColor(const ALLEGRO_COLOR & color1, const ALLEGRO_COLOR & color2){
// return memcmp(&color1, &color2, sizeof(Graphics::Color)) == 0;
float r1, g1, b1, a1;
float r2, g2, b2, a2;
al_unmap_rgba_f(color1, &r1, &g1, &b1, &a1);
al_unmap_rgba_f(color2, &r2, &g2, &b2, &a2);
return close(r1, r2) &&
close(g1, g2) &&
close(b1, b2) &&
close(a1, a2);
/*
unsigned char r1, g1, b1, a1;
unsigned char r2, g2, b2, a2;
al_unmap_rgba(color1, &r1, &g1, &b1, &a1);
al_unmap_rgba(color2, &r2, &g2, &b2, &a2);
return r1 == r2 &&
g1 == g2 &&
b1 == b2 &&
a1 == a2;
*/
}
static uint32_t quantify(const ALLEGRO_COLOR & color){
unsigned char red, green, blue, alpha;
al_unmap_rgba(color, &red, &green, &blue, &alpha);
return (red << 24) |
(green << 16) |
(blue << 8) |
alpha;
}
bool operator<(const ALLEGRO_COLOR & color1, const ALLEGRO_COLOR & color2){
return quantify(color1) < quantify(color2);
}
bool operator!=(const ALLEGRO_COLOR & color1, const ALLEGRO_COLOR & color2){
return !(color1 == color2);
}
bool operator==(const ALLEGRO_COLOR & color1, const ALLEGRO_COLOR & color2){
return sameColor(color1, color2);
}
diff --git a/src/graphics/bitmap.cpp b/src/graphics/bitmap.cpp
index 5ac2c45d..78e66265 100644
--- a/src/graphics/bitmap.cpp
+++ b/src/graphics/bitmap.cpp
@@ -1,593 +1,581 @@
#include "r-tech1/funcs.h"
#include "r-tech1/graphics/bitmap.h"
#include "r-tech1/file-system.h"
#include <string>
#include <stdio.h>
#include <math.h>
namespace Graphics{
static Bitmap * Screen = NULL;
/* bitmaps that should always be resized to the dimensions of the screen */
static std::vector<Bitmap*> needResize;
Util::Parameter<Bitmap*> screenParameter;
Util::Parameter<Util::ReferenceCount<ShaderManager> > shaderManager;
ShaderManager::ShaderManager(){
}
ShaderManager::~ShaderManager(){
}
Util::ReferenceCount<Shader> ShaderManager::getShader(const std::string & name, Util::ReferenceCount<Shader> (*create)()){
std::map<std::string, Util::ReferenceCount<Shader> >::iterator it = shaders.find(name);
if (it == shaders.end()){
shaders[name] = create();
it = shaders.find(name);
}
return it->second;
}
/* implementation independant definitions can go here */
-Bitmap * Bitmap::temporary_bitmap = NULL;
-Bitmap * Bitmap::temporary_bitmap2 = NULL;
-
/*
int SCALE_X = 0;
int SCALE_Y = 0;
*/
/*
const int Bitmap::MODE_TRANS = 0;
const int Bitmap::MODE_SOLID = 1;
*/
const int SPRITE_NO_FLIP = 0;
const int SPRITE_V_FLIP = 1;
const int SPRITE_H_FLIP = 2;
const int SPRITE_NORMAL = 1;
const int SPRITE_LIT = 2;
const int SPRITE_TRANS = 3;
static inline int max(int a, int b){
return a > b ? a : b;
}
INTERNAL_COLOR Color::defaultColor(){
return makeColor(0, 0, 0).color;
}
void initializeExtraStuff();
Bitmap::Bitmap(Storage::File & file):
mustResize(false),
error(false),
bit8MaskColor(makeColor(0, 0, 0)){
int length = file.getSize();
if (length == -1){
throw BitmapException(__FILE__, __LINE__, std::string("Could not read from file"));
}
char * data = new char[length];
try{
file.readLine(data, length);
loadFromMemory(data, length);
delete[] data;
} catch (const BitmapException & fail){
delete[] data;
throw;
} catch (...){
delete[] data;
throw;
}
}
QualityFilter qualityFilterName(const std::string & type){
if (type == "xbr"){
return XbrFilter;
}
if (type == "hqx"){
return HqxFilter;
}
return NoFilter;
}
Bitmap::~Bitmap(){
if (mustResize){
for (std::vector<Bitmap*>::iterator it = needResize.begin(); it != needResize.end(); it++){
Bitmap * who = *it;
if (who == this){
needResize.erase(it);
break;
}
}
}
}
static Bitmap makeTemporaryBitmap(Bitmap *& temporary, int w, int h){
if (temporary == NULL){
temporary = new Bitmap(w, h);
} else if (temporary->getWidth() < w || temporary->getHeight() < h){
int mw = max(temporary->getWidth(), w);
int mh = max(temporary->getHeight(), h);
// printf("Create temporary bitmap %d %d\n", mw, mh);
delete temporary;
temporary = new Bitmap(mw, mh);
}
if (temporary == NULL){
printf("*bug* temporary bitmap is null\n");
}
return Bitmap(*temporary, 0, 0, w, h);
}
/*
Bitmap Bitmap::temporaryBitmap(int w, int h){
return makeTemporaryBitmap(temporary_bitmap, w, h);
}
Bitmap Bitmap::temporaryBitmap2(int w, int h){
return makeTemporaryBitmap(temporary_bitmap2, w, h);
}
*/
void Bitmap::cleanupTemporaryBitmaps(){
- if (temporary_bitmap != NULL){
- delete temporary_bitmap;
- temporary_bitmap = NULL;
- }
-
- if (temporary_bitmap2 != NULL){
- delete temporary_bitmap2;
- temporary_bitmap2 = NULL;
- }
}
Bitmap & Bitmap::operator=(const Bitmap & copy){
path = copy.getPath();
this->width = copy.getWidth();
this->height = copy.getHeight();
setData(copy.getData());
return *this;
}
double Bitmap::getScale(){
/* the game is pretty much hard coded to run at 320 scaled upto 640
* and then scaled to whatever the user wants, but as long as
* 320 and 640 remain this number will be 2.
* maybe calculate this at some point
*/
return 2;
/*
if (Scaler != NULL && Buffer != NULL){
double x1 = Scaler->getWidth();
double x2 = Buffer->getWidth();
return x2 / x1;
}
return 1;
*/
}
bool Bitmap::isEmpty() const {
return getWidth() == 0 || getHeight() == 0;
}
/* taken from the color addon from allegro 4.9 */
static void al_color_cmyk_to_rgb(float cyan, float magenta, float yellow, float key, float *red, float *green, float *blue){
float max = 1 - key;
*red = max - cyan * max;
*green = max - magenta * max;
*blue = max - yellow * max;
}
void Bitmap::cymkToRGB(int c, int y, int m, int k, int * r, int * g, int * b){
float fc = (float)c / 255.0;
float fy = (float)y / 255.0;
float fm = (float)m / 255.0;
float fk = (float)k / 255.0;
float fr, fg, fb;
al_color_cmyk_to_rgb(fc, fm, fy, fk, &fr, &fg, &fb);
*r = (int)(fr * 255.0);
*g = (int)(fg * 255.0);
*b = (int)(fb * 255.0);
}
void Bitmap::updateOnResize(){
if (!mustResize){
mustResize = true;
needResize.push_back(this);
}
}
void Bitmap::updateSize(const int width, const int height){
if (getWidth() == width && getHeight() == height){
return;
}
Bitmap created(width, height);
*this = created;
}
/* resize the internal bitmap. not guaranteed to destroy the internal bitmap */
void Bitmap::resize(const int width, const int height){
/* if internal bitmap is already the proper size, do nothing */
if (getWidth() == width && getHeight() == height){
return;
}
Bitmap created(width, height);
Stretch(created);
*this = created;
}
/* decrement bitmap reference counter and free memory if counter hits 0 */
#if 0
void Bitmap::releaseInternalBitmap(){
const int MAGIC_DEBUG = 0xa5a5a5;
if (own != NULL){
if (*own == MAGIC_DEBUG){
printf("[bitmap] Trying to delete an already deleted reference counter %p\n", own);
}
(*own) -= 1;
if ( *own == 0 ){
*own = MAGIC_DEBUG;
delete own;
destroyPrivateData();
own = NULL;
}
}
}
#endif
void Bitmap::BlitToScreen() const {
// this->Blit( *Bitmap::Screen );
this->BlitToScreen(0, 0);
}
void Bitmap::load( const std::string & str ){
// releaseInternalBitmap();
internalLoadFile( str.c_str() );
}
Bitmap Bitmap::scaleBy(const double widthRatio, const double heightRatio) const {
return scaleTo(getWidth() * widthRatio, getHeight() * heightRatio);
}
void Bitmap::border( int min, int max, Color color ) const {
int w = getWidth();
int h = getHeight();
for (int i = min; i < max; i++){
rectangle(i, i, w - 1 - i, h - 1 - i, color);
}
}
void Bitmap::drawHFlip(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, const Bitmap & where) const {
drawHFlip(x, y, startWidth, startHeight, width, height, NULL, where);
}
void Bitmap::drawHFlip(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, Filter * filter, const Bitmap & where) const {
Bitmap sub(*this, getWidth() - width, getHeight() - height, getWidth() - startWidth, getHeight() - startHeight);
sub.drawHFlip(x + startWidth, y + startHeight, filter, where);
}
void Bitmap::drawRotateCenter(const int x, const int y, const int angle, const Bitmap & where){
drawRotate(x - getWidth() / 2, y - getHeight() / 2, angle, where);
}
void Bitmap::drawCenter(const int x, const int y, const Bitmap & where) const {
draw(x - getWidth() / 2, y - getHeight() / 2, where);
}
void Bitmap::drawStretched(const Bitmap & who) const {
drawStretched(0, 0, who.getWidth(), who.getHeight(), who);
}
void Bitmap::draw(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, const Bitmap & where) const {
draw(x, y, startWidth, startHeight, width, height, NULL, where);
/*
Bitmap sub(*this, startWidth, startHeight, width, height);
sub.draw(x + startWidth, y + startHeight, where);
*/
}
void Bitmap::draw(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, Filter * filter, const Bitmap & where) const {
Bitmap sub(*this, startWidth, startHeight, width, height);
sub.draw(x + startWidth, y + startHeight, filter, where);
}
void Bitmap::horizontalLine( const int x1, const int y, const int x2, const Graphics::Color color ) const{
this->hLine(x1, y, x2, color);
}
void Bitmap::equilateralTriangle(int x, int y, int angle, int size, Color color) const {
double radians = Util::radians(angle);
int x1 = x + size / 2 * cos(radians + 2 * Util::pi / 3);
int y1 = y + size / 2 * sin(radians + 2 * Util::pi / 3);
int x2 = x + size / 2 * cos(radians - 2 * Util::pi / 3);
int y2 = y + size / 2 * sin(radians - 2 * Util::pi / 3);
int x3 = x + size / 2 * cos(radians);
int y3 = y + size / 2 * sin(radians);
triangle(x1, y1, x2, y2, x3, y3, color);
}
Bitmap Bitmap::greyScale(){
Bitmap grey(getWidth(), getHeight());
for (int x = 0; x < getWidth(); x++){
for (int y = 0; y < getHeight(); y++){
Color pixel = getPixel(x, y);
int val = (int)((0.299*getRed(pixel) + 0.587*getGreen(pixel) + 0.114*getBlue(pixel) + 0.5) + 16);
if (val > 255){
val = 255;
}
grey.putPixel(x, y, makeColor(val, val, val));
}
}
return grey;
}
bool Bitmap::inRange(int x, int y) const {
int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
getClipRect(x1, y1, x2, y2);
return (x >= x1 && x <= x2 &&
y >= y1 && y <= y2);
}
void Bitmap::drawMask( const int _x, const int _y, const Bitmap & where ){
Color mask = MaskColor();
for (int x = 0; x < getWidth(); x++){
for (int y = 0; y < getHeight(); y++){
if (getPixel(x,y) == mask){
where.putPixel(x+_x, y+_y, mask);
}
}
}
}
void Bitmap::set8BitMaskColor(const Color & color){
bit8MaskColor = color;
}
Color Bitmap::get8BitMaskColor(){
return bit8MaskColor;
}
void Bitmap::setFakeGraphicsMode(int width, int height){
initializeExtraStuff();
Screen = new Bitmap(width, height);
}
void Bitmap::Blit( const std::string & xpath ) const {
Bitmap duh(xpath);
duh.Blit(*this);
}
void Bitmap::Blit(const Bitmap & where) const {
this->Blit(0, 0, where);
}
void Bitmap::Blit(const int x, const int y, const Bitmap & where) const {
Blit(0, 0, x, y, where);
}
void Bitmap::Blit(const int mx, const int my, const int wx, const int wy, const Bitmap & where) const {
Blit(mx, my, getWidth(), getHeight(), wx, wy, where);
}
void Bitmap::BlitFromScreen(const int x, const int y) const {
Screen->Blit(x, y, getWidth(), getHeight(), 0, 0, *this);
}
//! min (borrowed from allegro)
static inline int Min(int x, int y){ return (((x) < (y)) ? (x) : (y)); }
//! max (borrowed from allegro)
static inline int Max(int x, int y){ return (((x) > (y)) ? (x) : (y)); }
//! mid (borrowed from allegro)
static inline int Mid(int x,int y,int z){ return (Max((x), Min((y), (z)))); }
int Bitmap::getScreenWidth(){
if (Screen != 0){
return Screen->getWidth();
}
return 0;
}
int Bitmap::getScreenHeight(){
if (Screen != 0){
return Screen->getHeight();
}
return 0;
}
void Bitmap::clear() const {
fill(makeColor(0, 0, 0));
}
void Bitmap::copy(const Bitmap & him){
resize(him.getWidth(), him.getHeight());
him.Blit(*this);
}
void Bitmap::Stretch( const Bitmap & where ) const {
if (getWidth() == where.getWidth() && getHeight() == where.getHeight()){
Blit(where);
} else {
Stretch(where, 0, 0, getWidth(), getHeight(), 0, 0, where.getWidth(), where.getHeight());
}
}
void Bitmap::StretchHqx(const Bitmap & where) const {
if (getWidth() == where.getWidth() && getHeight() == where.getHeight()){
Blit(where);
} else {
StretchHqx(where, 0, 0, getWidth(), getHeight(), 0, 0, where.getWidth(), where.getHeight());
}
}
void Bitmap::StretchXbr(const Bitmap & where) const {
if (getWidth() == where.getWidth() && getHeight() == where.getHeight()){
Blit(where);
} else {
StretchXbr(where, 0, 0, getWidth(), getHeight(), 0, 0, where.getWidth(), where.getHeight());
}
}
Bitmap Bitmap::aspectRatio(int aspectWidth, int aspectHeight) const {
double width = getWidth();
double height = getHeight();
double ratio = (double) aspectWidth / (double) aspectHeight;
width = (double) height * ratio;
if (width > getWidth()){
width = getWidth();
height = width / ratio;
}
int x = (getWidth() - width) / 2;
int y = (getHeight() - height) / 2;
return Bitmap(*this, x, y, (int) width, (int) height);
}
Color darken(Color color, double factor ){
int r = (int)((double)getRed(color) / factor);
int g = (int)((double)getGreen(color) / factor);
int b = (int)((double)getBlue(color) / factor);
return makeColor(r, g, b);
}
LitBitmap::LitBitmap(const Bitmap & b):
Bitmap(b){
int x1, y1, x2, y2;
b.getClipRect(x1, y1, x2, y2);
setClipRect(x1, y1, x2, y2);
}
LitBitmap::LitBitmap():
Bitmap(){
}
LitBitmap::~LitBitmap(){
}
LitBitmap Bitmap::lit() const {
return LitBitmap(*this);
}
TranslucentBitmap Bitmap::translucent() const {
return TranslucentBitmap(*this);
}
TranslucentBitmap Bitmap::translucent(int red, int green, int blue, int alpha) const {
transBlender(red, green, blue, alpha);
return TranslucentBitmap(*this);
}
TranslucentBitmap::TranslucentBitmap(const Bitmap & b):
Bitmap(b){
int x1, y1, x2, y2;
b.getClipRect(x1, y1, x2, y2);
setClipRect(x1, y1, x2, y2);
}
TranslucentBitmap::TranslucentBitmap():
Bitmap(){
}
TranslucentBitmap::~TranslucentBitmap(){
}
void TranslucentBitmap::fill(Color color) const {
Bitmap::applyTrans(color);
}
int StretchedBitmap::getWidth() const {
return width;
}
int StretchedBitmap::getHeight() const {
return height;
}
double StretchedBitmap::getScaleWidth() const {
return (double) where.getWidth() / (double) getWidth();
}
double StretchedBitmap::getScaleHeight() const {
return (double) where.getHeight() / (double) getHeight();
}
BlendPoint::BlendPoint(const Color & color, int length):
color(color),
length(length){
}
void blend_palette(Color * pal, int mp, const Color & startColor, const Color & endColor){
/*
ASSERT(pal);
ASSERT(mp != 0);
*/
int sc_r = Graphics::getRed(startColor);
int sc_g = Graphics::getGreen(startColor);
int sc_b = Graphics::getBlue(startColor);
int ec_r = Graphics::getRed(endColor);
int ec_g = Graphics::getGreen(endColor);
int ec_b = Graphics::getBlue(endColor);
for ( int q = 0; q < mp; q++ ) {
float j = (float)( q + 1 ) / (float)( mp );
int f_r = (int)( 0.5 + (float)( sc_r ) + (float)( ec_r-sc_r ) * j );
int f_g = (int)( 0.5 + (float)( sc_g ) + (float)( ec_g-sc_g ) * j );
int f_b = (int)( 0.5 + (float)( sc_b ) + (float)( ec_b-sc_b ) * j );
pal[q] = Graphics::makeColor( f_r, f_g, f_b );
}
}
std::vector<Color> blend_palette(const std::vector<BlendPoint> & in){
std::vector<Color> out;
int here = 0;
for (int i = 1; i < in.size(); i++){
const BlendPoint & start = in[here];
const BlendPoint & end = in[i];
Color * save = new Color[start.length];
blend_palette(save, start.length, start.color, end.color);
for (int use = 0; use < start.length; use++){
out.push_back(save[use]);
}
delete[] save;
here = i;
}
return out;
}
}
#ifdef USE_ALLEGRO
#include "allegro/bitmap.cpp"
#endif
#ifdef USE_SDL
#include "sdl/bitmap.cpp"
#endif
#ifdef USE_ALLEGRO5
#include "allegro5/bitmap.cpp"
#endif

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jun 16, 12:12 AM (2 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
70695
Default Alt Text
(136 KB)

Event Timeline