Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
143 KB
Referenced Files
None
Subscribers
None
diff --git a/util/graphics/allegro5/bitmap.cpp b/util/graphics/allegro5/bitmap.cpp
index 874ee0a1..a3ef6d6c 100644
--- a/util/graphics/allegro5/bitmap.cpp
+++ b/util/graphics/allegro5/bitmap.cpp
@@ -1,1512 +1,1512 @@
#include <sstream>
#include <allegro5/allegro5.h>
#include <allegro5/allegro_memfile.h>
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_glsl.h>
#include "util/debug.h"
#include "util/thread.h"
#include <vector>
namespace Graphics{
ALLEGRO_DISPLAY * the_display = NULL;
static std::vector<ALLEGRO_SHADER*> shaders;
// static ALLEGRO_SHADER * shader_default;
static ALLEGRO_SHADER * shader_shadow;
static ALLEGRO_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_DST_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());
}
}
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 + 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_vertex_shader(ALLEGRO_SHADER_GLSL));
+ return std::string(al_get_default_shader_source(ALLEGRO_SHADER_GLSL, ALLEGRO_VERTEX_SHADER));
}
std::string defaultPixelShader(){
- return std::string(al_get_default_pixel_shader(ALLEGRO_SHADER_GLSL));
+ 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);
}
ALLEGRO_SHADER * create_shader(const std::string & vertex, const std::string & pixel){
ALLEGRO_SHADER * shader = al_create_shader(ALLEGRO_SHADER_GLSL);
if (shader == NULL){
return NULL;
}
if (!al_attach_shader_source(shader, ALLEGRO_VERTEX_SHADER, vertex.c_str())){
Global::debug(0) << "attach vertex shader source failed: " << al_get_shader_log(shader) << std::endl << vertex << std::endl;
return NULL;
}
if (!al_attach_shader_source(shader, ALLEGRO_PIXEL_SHADER, pixel.c_str())){
Global::debug(0) << "attach pixel shader source failed: " << al_get_shader_log(shader) << std::endl << pixel << std::endl;
return NULL;
}
if (!al_link_shader(shader)){
Global::debug(0) << "shader al_link_shader failed: " << al_get_shader_log(shader) << std::endl;
return NULL;
}
return shader;
}
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_USE_PROGRAMMABLE_PIPELINE);
#else
al_set_new_display_flags(ALLEGRO_FULLSCREEN | ALLEGRO_USE_PROGRAMMABLE_PIPELINE);
#endif
break;
}
case WINDOWED: {
al_set_new_display_flags(ALLEGRO_WINDOWED | ALLEGRO_RESIZABLE |
ALLEGRO_USE_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);
// 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;
try{
shader_shadow = create_shader(defaultVertexShader(), Storage::readFile(Storage::instance().find(Filesystem::RelativePath("shaders/shadow.fragment.glsl"))));
if (shader_shadow == NULL){
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(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;
}
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 {
/* TODO */
}
void Bitmap::StretchBy2( const Bitmap & where ){
/* TODO */
}
void Bitmap::StretchBy4( const Bitmap & where ){
/* TODO */
}
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);
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
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 {
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 {
al_draw_line(x1, y1, x2, y2, color.color, 1.5);
}
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, 0);
}
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);
}
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);
}
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;
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 = temporaryBitmap(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 */
al_set_target_bitmap(Screen->getData()->getBitmap());
al_use_shader(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, QualityFilter filter):
Bitmap(parent, 0, 0, parent.getWidth(), parent.getHeight()),
width(width),
height(height),
where(parent),
filter(filter){
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);
}
/* 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
}
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/util/input/allegro5/joystick.cpp b/util/input/allegro5/joystick.cpp
index 0f03cd04..8a77c47d 100644
--- a/util/input/allegro5/joystick.cpp
+++ b/util/input/allegro5/joystick.cpp
@@ -1,269 +1,269 @@
#ifdef USE_ALLEGRO5
#include "../joystick.h"
#include "joystick.h"
#include "util/debug.h"
#include <allegro5/allegro.h>
using std::vector;
using std::string;
class ButtonMapping{
public:
ButtonMapping(){
}
virtual ~ButtonMapping(){
}
virtual Joystick::Key toKey(int button) = 0;
virtual void axisMotionEvents(int stick, int axis, float position, vector<Joystick::Event> & events) = 0;
virtual void hatMotionEvents(int motion, vector<Joystick::Event> & events) = 0;
};
class DefaultMapping: public ButtonMapping {
public:
DefaultMapping(){
}
virtual Joystick::Key toKey(int button){
switch (button){
case 0: return Joystick::Button1;
case 1: return Joystick::Button2;
case 2: return Joystick::Button3;
case 3: return Joystick::Button4;
case 4: return Joystick::Button5;
case 5: return Joystick::Button6;
case 6: return Joystick::Start;
case 7: return Joystick::Quit;
case 8: return Joystick::Up;
case 9: return Joystick::Down;
case 10: return Joystick::Left;
case 11: return Joystick::Right;
}
return Joystick::Invalid;
}
virtual void axisMotionEvents(int stick, int axis, float position, vector<Joystick::Event> & events){
}
virtual void hatMotionEvents(int motion, vector<Joystick::Event> & events){
}
virtual ~DefaultMapping(){
}
};
class LogitechPrecision: public ButtonMapping {
public:
enum Buttons{
Button1 = 0,
Button2 = 1,
Button3 = 2,
Button4 = 3,
Start = 8,
Select = 9,
R2 = 7,
R1 = 5,
L2 = 6,
L1 = 4
};
int toNative(int button){
return -1;
}
int fromNative(int button){
return -1;
}
Joystick::Key toKey(int button){
switch (button){
case Button1: return Joystick::Button1;
case Button2: return Joystick::Button2;
case Button3: return Joystick::Button3;
case Button4: return Joystick::Button4;
case L1: return Joystick::Button5;
case R1: return Joystick::Button6;
case Start: return Joystick::Start;
case Select: return Joystick::Quit;
}
return Joystick::Invalid;
}
/* axis 1. negative up, positive down
* axis 0, negative left, positive right
*/
void axisMotionEvents(int stick, int axis, float position, vector<Joystick::Event> & events){
int tolerance = 10;
const int LeftRightAxis = 0;
const int UpDownAxis = 1;
switch (stick){
case 0: {
switch (axis){
case UpDownAxis: {
if (position == -1){
events.push_back(Joystick::Event(Joystick::Up, true));
events.push_back(Joystick::Event(Joystick::Down, false));
} else if (position == 1){
events.push_back(Joystick::Event(Joystick::Up, false));
events.push_back(Joystick::Event(Joystick::Down, true));
} else if (position == 0){
events.push_back(Joystick::Event(Joystick::Up, false));
events.push_back(Joystick::Event(Joystick::Down, false));
}
break;
}
case LeftRightAxis: {
if (position == -1){
events.push_back(Joystick::Event(Joystick::Left, true));
events.push_back(Joystick::Event(Joystick::Right, false));
} else if (position == 1){
events.push_back(Joystick::Event(Joystick::Left, false));
events.push_back(Joystick::Event(Joystick::Right, true));
} else if (position == 0){
events.push_back(Joystick::Event(Joystick::Left, false));
events.push_back(Joystick::Event(Joystick::Right, false));
}
break;
}
default: {
}
}
}
default: {
break;
}
}
#if 0
if (axis == 0){
if (position == 0){
events.push_back(Joystick::Event(Joystick::Left, false));
events.push_back(Joystick::Event(Joystick::Right, false));
} else if (motion == -32768){
events.push_back(Joystick::Event(Joystick::Left, true));
} else if (motion == 32767){
events.push_back(Joystick::Event(Joystick::Right, true));
} else if (motion == 128){
events.push_back(Joystick::Event(Joystick::Up, false));
events.push_back(Joystick::Event(Joystick::Down, false));
} else if (motion == 1){
events.push_back(Joystick::Event(Joystick::Up, true));
} else if (motion == 255){
events.push_back(Joystick::Event(Joystick::Down, true));
}
/*
if (motion < -tolerance){
events.push_back(Joystick::Event(Joystick::Left, true));
} else if (motion > tolerance){
events.push_back(Joystick::Event(Joystick::Right, true));
} else {
/ * fake a release for left and right * /
events.push_back(Joystick::Event(Joystick::Left, false));
events.push_back(Joystick::Event(Joystick::Right, false));
}
*/
} else if (axis == 1){
if (motion < -tolerance){
events.push_back(Joystick::Event(Joystick::Up, true));
} else if (motion > tolerance){
events.push_back(Joystick::Event(Joystick::Down, true));
} else {
events.push_back(Joystick::Event(Joystick::Up, false));
events.push_back(Joystick::Event(Joystick::Down, false));
}
}
#endif
}
virtual void hatMotionEvents(int motion, vector<Joystick::Event> & events){
}
};
static Util::ReferenceCount<ButtonMapping> createMapping(ALLEGRO_JOYSTICK * joystick){
string name = al_get_joystick_name(joystick);
if (name.find("Logitech(R) Precision(TM) Gamepad") != string::npos){
return Util::ReferenceCount<ButtonMapping>(new LogitechPrecision());
}
return Util::ReferenceCount<ButtonMapping>(new DefaultMapping());
}
Allegro5Joystick::Allegro5Joystick(int id):
id(id){
queue = al_create_event_queue();
if (al_is_joystick_installed()){
al_register_event_source(queue, al_get_joystick_event_source());
}
buttons = createMapping(al_get_joystick(id));
}
void Allegro5Joystick::axis(int stick, int axis, float position){
- // Global::debug(0) << "stick " << stick << " axis " << axis << " position " << position << std::endl;
+ Global::debug(0) << "stick " << stick << " axis " << axis << " position " << position << std::endl;
buttons->axisMotionEvents(stick, axis, position, events);
}
void Allegro5Joystick::buttonDown(int button){
- // Global::debug(0) << "Button down " << button << std::endl;
+ Global::debug(0) << "Button down " << button << std::endl;
Key event = buttons->toKey(button);
if (event != Invalid){
events.push_back(Event(event, false));
}
}
void Allegro5Joystick::buttonUp(int button){
- // Global::debug(0) << "Button up " << button << std::endl;
+ Global::debug(0) << "Button up " << button << std::endl;
Key event = buttons->toKey(button);
if (event != Invalid){
events.push_back(Event(event, true));
}
}
void Allegro5Joystick::poll(){
events.clear();
ALLEGRO_EVENT event;
while (al_get_next_event(queue, &event)){
switch (event.type){
case ALLEGRO_EVENT_JOYSTICK_AXIS: {
if (event.joystick.id == al_get_joystick(id)){
axis(event.joystick.stick, event.joystick.axis, event.joystick.pos);
}
break;
}
case ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN: {
if (event.joystick.id == al_get_joystick(id)){
buttonDown(event.joystick.button);
}
break;
}
case ALLEGRO_EVENT_JOYSTICK_BUTTON_UP: {
if (event.joystick.id == al_get_joystick(id)){
buttonUp(event.joystick.button);
}
break;
}
}
}
}
int Allegro5Joystick::getDeviceId() const {
return id;
}
std::string Allegro5Joystick::getName() const {
return al_get_joystick_name(al_get_joystick(id));
}
Allegro5Joystick::~Allegro5Joystick(){
al_destroy_event_queue(queue);
queue = NULL;
}
int Joystick::numberOfJoysticks(){
return al_get_num_joysticks();
}
#endif
diff --git a/util/menu/options.cpp b/util/menu/options.cpp
index f86129fd..d2462872 100644
--- a/util/menu/options.cpp
+++ b/util/menu/options.cpp
@@ -1,2699 +1,2747 @@
#include "util/graphics/bitmap.h"
#include "options.h"
#include "util/token.h"
#include "util/input/input-source.h"
#include "util/parameter.h"
#include "util/tokenreader.h"
#include "menu.h"
#include "util/configuration.h"
#include "util/exceptions/load_exception.h"
#include "menu-exception.h"
#include "util/init.h"
#include "util/events.h"
#include "util/version.h"
#include "optionfactory.h"
#include "util/sound/music.h"
#include "util/input/keyboard.h"
#include "util/funcs.h"
#include "util/file-system.h"
#include "util/font_factory.h"
#include "util/exceptions/shutdown_exception.h"
#include "util/exceptions/exception.h"
#include "util/font.h"
#include "util/gui/box.h"
#include "util/thread.h"
#include "util/loading.h"
#include "util/input/input-map.h"
#include "util/input/input-manager.h"
#include <sstream>
#include <algorithm>
#include <time.h>
#include <math.h>
using namespace std;
using namespace Gui;
/* true if the arguments passed in match todays date.
* pass 0 for any argument that you don't care about (it will match any date)
*/
static bool todaysDate(int month, int day, int year){
time_t result = time(NULL);
struct tm * local = localtime(&result);
return (month == 0 || month == (local->tm_mon + 1)) &&
(day == 0 || day == local->tm_mday) &&
(year == 0 || year == local->tm_year + 1900);
}
static bool jonBirthday(){
return todaysDate(3, 25, 0);
}
static bool miguelBirthday(){
return todaysDate(8, 11, 0);
}
OptionCredits::Block::Block(const std::string & title):
title(title),
titleColorOverride(false),
titleColor(Graphics::makeColor(0,255,255)),
colorOverride(false),
color(Graphics::makeColor(255,255,255)),
spacing(0){
}
OptionCredits::Block::Block(const Token * token):
titleColorOverride(false),
titleColor(Graphics::makeColor(0,255,255)),
colorOverride(false),
color(Graphics::makeColor(255,255,255)),
topWidth(0),
topHeight(0),
bottomWidth(0),
bottomHeight(0),
spacing(0){
if ( *token != "block" ){
throw LoadException(__FILE__, __LINE__, "Not a credit block");
}
TokenView view = token->view();
while (view.hasMore()){
std::string match;
try{
const Token * tok;
view >> tok;
if ( *tok == "title" ) {
tok->view() >> title;
} else if (*tok == "credit"){
std::string credit;
tok->view() >> credit;
credits.push_back(credit);
} else if ( *tok == "titlecolor" ) {
try{
int r,b,g;
tok->view() >> r >> g >> b;
titleColor = Graphics::makeColor( r, g, b );
titleColorOverride = true;
} catch (const TokenException & ex){
}
} else if ( *tok == "color" ) {
try{
int r,b,g;
tok->view() >> r >> g >> b;
color = Graphics::makeColor( r, g, b );
colorOverride = true;
} catch (const TokenException & ex){
}
} else if ( *tok == "animation" ) {
TokenView animView = tok->view();
while (animView.hasMore()){
const Token * animTok;
animView >> animTok;
if (*animTok == "top"){
tok->match("_/width", topWidth);
tok->match("_/height", topHeight);
topAnimation = Util::ReferenceCount<Gui::Animation>(new Animation(tok));
} else if (*animTok == "bottom"){
tok->match("_/width", bottomWidth);
tok->match("_/height", bottomHeight);
bottomAnimation = Util::ReferenceCount<Gui::Animation>(new Animation(tok));
}
}
} else if (*tok == "spacing"){
tok->view() >> spacing;
} else {
Global::debug( 3 ) <<"Unhandled Credit Block attribute: "<<endl;
if (Global::getDebug() >= 3){
tok->print(" ");
}
}
} catch ( const TokenException & ex ) {
throw LoadException(__FILE__, __LINE__, ex, "Credit Block parse error");
} catch ( const LoadException & ex ) {
throw ex;
}
}
}
OptionCredits::Block::Block(const OptionCredits::Block & copy):
title(copy.title),
credits(copy.credits),
titleColorOverride(copy.titleColorOverride),
titleColor(copy.titleColor),
colorOverride(copy.colorOverride),
color(copy.color),
topAnimation(copy.topAnimation),
topWidth(copy.topWidth),
topHeight(copy.topHeight),
bottomAnimation(copy.bottomAnimation),
bottomWidth(copy.bottomWidth),
bottomHeight(copy.bottomHeight),
spacing(copy.spacing){
}
OptionCredits::Block::~Block(){
}
const OptionCredits::Block & OptionCredits::Block::operator=(const OptionCredits::Block & copy){
title = copy.title;
credits = copy.credits;
titleColor = copy.titleColor;
titleColorOverride = copy.titleColorOverride;
color = copy.color;
colorOverride = copy.colorOverride;
topAnimation = copy.topAnimation;
topWidth =copy.topWidth;
topHeight = copy.topHeight;
bottomAnimation = copy.bottomAnimation;
bottomWidth = copy.bottomWidth;
bottomHeight = copy.bottomHeight;
spacing = copy.spacing;
return *this;
}
void OptionCredits::Block::addCredit(const std::string & credit){
credits.push_back(credit);
}
void OptionCredits::Block::act(){
// Top animation
if (topAnimation != NULL){
topAnimation->act();
}
// Bottom animation
if (bottomAnimation != NULL){
bottomAnimation->act();
}
}
int OptionCredits::Block::print(int x, int y, Graphics::Color defaultTitleColor, Graphics::Color defaultColor, const Font & font, const Graphics::Bitmap & work, const Justification & justification) const {
int currentY = y;
// Top animation
if (topAnimation != NULL){
int xmod = 0;
switch (justification){
default:
case Left:
xmod = 0;
break;
case Center:
xmod = topWidth/2;
break;
case Right:
xmod = topWidth;
break;
}
// FIXME temporary solution
const Graphics::Bitmap & temp = Graphics::Bitmap::temporaryBitmap(topWidth, topHeight);
//topAnimation->draw(x - xmod, y, topWidth, topHeight, work);
topAnimation->draw(0, 0, topWidth, topHeight, temp);
temp.translucent().draw(x-xmod, y, work);
currentY+=topHeight;
}
if (!title.empty()){
int xmod = 0;
switch (justification){
default:
case Left:
xmod = 0;
break;
case Center:
xmod = font.textLength(title.c_str())/2;
break;
case Right:
xmod = font.textLength(title.c_str());
break;
}
font.printf(x - xmod, currentY, (titleColorOverride ? titleColor : defaultTitleColor), work, title, 0);
currentY += font.getHeight();
}
for (std::vector<std::string>::const_iterator i = credits.begin(); i != credits.end(); ++i){
const std::string & credit = *i;
int xmod = 0;
switch (justification){
default:
case Left:
xmod = 0;
break;
case Center:
xmod = font.textLength(credit.c_str())/2;
break;
case Right:
xmod = font.textLength(credit.c_str());
break;
}
font.printf(x - xmod, currentY, (colorOverride ? color : defaultColor), work, credit, 0);
currentY += font.getHeight();
}
// Bottom animation
if (bottomAnimation != NULL){
int xmod = 0;
switch (justification){
default:
case Left:
xmod = 0;
break;
case Center:
xmod = bottomWidth/2;
break;
case Right:
xmod = bottomWidth;
break;
}
// FIXME temporary solution
const Graphics::Bitmap & temp = Graphics::Bitmap::temporaryBitmap(topWidth, topHeight);
//bottomAnimation->draw(x - xmod, y, bottomWidth, bottomHeight, work);
bottomAnimation->draw(0, 0, bottomWidth, bottomHeight, temp);
temp.translucent().draw(x-xmod, y, work);
currentY+=bottomHeight;
}
currentY += font.getHeight() + spacing;
return currentY;
}
const int OptionCredits::Block::size(const Font & font) const{
// Counts title and space in between
int total = 0;
if (topAnimation != NULL){
total += topHeight;
}
if (!title.empty()){
total+= font.getHeight();
}
total += credits.size() * font.getHeight();
if (bottomAnimation != NULL){
total += bottomHeight;
}
total += font.getHeight();
total += spacing;
return total;
}
OptionCredits::Sequence::Sequence(const Token * token):
type(Primary),
x(0),
y(0),
startx(0),
endx(0),
starty(0),
endy(0),
ticks(0),
duration(250),
speed(0),
alpha(0),
alphaMultiplier(0),
justification(Block::Center),
current(0),
done(false),
creditLength(0){
if ( *token != "sequence" ){
throw LoadException(__FILE__, __LINE__, "Not a credit sequence");
}
TokenView view = token->view();
while (view.hasMore()){
std::string match;
try{
const Token * tok;
view >> tok;
if (*tok == "type"){
std::string sequenceType;
tok->view() >> sequenceType;
if (sequenceType == "roll"){
type = Roll;
} else if (sequenceType == "primary"){
type = Primary;
}
} else if (*tok == "start-x"){
tok->view() >> startx;
} else if (*tok == "end-x"){
tok->view() >> endx;
} else if (*tok == "start-y"){
tok->view() >> starty;
} else if (*tok == "end-y"){
tok->view() >> endy;
} else if (*tok == "duration"){
tok->view() >> duration;
} else if (*tok == "speed"){
tok->view() >> speed;
} else if (*tok == "alpha-multiplier"){
tok->view() >> alphaMultiplier;
} else if ( *tok == "justification" ) {
std::string justify;
tok->view() >> justify;
if (justify == "left"){
justification = Block::Left;
} else if (justify == "center"){
justification = Block::Center;
} else if (justify == "right"){
justification = Block::Right;
}
} else if (*tok == "block"){
credits.push_back(Block(tok));
} else {
Global::debug( 3 ) <<"Unhandled Credit Sequence attribute: "<<endl;
if (Global::getDebug() >= 3){
tok->print(" ");
}
}
} catch ( const TokenException & ex ) {
throw LoadException(__FILE__, __LINE__, ex, "Credit Sequence parse error");
} catch ( const LoadException & ex ) {
throw ex;
}
}
// Initial
reset();
for (std::vector<OptionCredits::Block>::const_iterator i = credits.begin(); i != credits.end(); ++i){
const OptionCredits::Block & block = *i;
creditLength += block.size(Menu::menuFontParameter.current()->get());
}
}
OptionCredits::Sequence::Sequence(const Sequence & copy):
type(copy.type),
x(copy.x),
y(copy.y),
startx(copy.startx),
endx(copy.endx),
starty(copy.starty),
endy(copy.endy),
ticks(copy.ticks),
duration(copy.duration),
speed(copy.speed),
alpha(copy.alpha),
alphaMultiplier(copy.alphaMultiplier),
justification(copy.justification),
credits(copy.credits),
current(copy.current),
done(false),
creditLength(copy.creditLength){
}
OptionCredits::Sequence::~Sequence(){
}
const OptionCredits::Sequence & OptionCredits::Sequence::operator=(const OptionCredits::Sequence & copy){
type = copy.type;
x = copy.x;
y = copy.y;
startx = copy.startx;
endx = copy.endx;
starty = copy.starty;
endy = copy.endy;
ticks = copy.ticks;
duration = copy.duration;
speed = copy.speed;
alpha = copy.alpha;
alphaMultiplier = copy.alphaMultiplier;
justification = copy.justification;
credits = copy.credits;
current = copy.current;
done = false;
creditLength = copy.creditLength;
return *this;
}
static int alphaClamp(int x, double multiplier){
int clamp = x * multiplier;
if (clamp < 0){
clamp = 0;
} else if (clamp > 255){
clamp = 255;
}
return clamp;
}
void OptionCredits::Sequence::act(){
if (!done && !credits.empty()){
if (type == Roll){
y += speed;
if (starty > endy){
if ((y + (creditLength * 1.1)) < endy){
done = true;
}
} else if (starty < endy){
if ((y * 1.1) > endy){
done = true;
}
}
} else if (type == Primary){
credits[current].act();
if (startx != endx){
x += speed;
if (startx > endx){
const double midpoint = (startx+endx)/2;
const int mid = x > midpoint ? startx -x : x - endx;
alpha = alphaClamp(mid, alphaMultiplier);
if (x < endx){
next();
}
} else if (startx < endx){
const double midpoint = (startx+endx)/2;
const int mid = x < midpoint ? x - startx : endx - x;
alpha = alphaClamp(mid, alphaMultiplier);
//Global::debug(0) << "alpha: " << alpha << " midpoint: " << midpoint << " mid: " << mid << std::endl;
if (x > endx){
next();
}
}
} else {
const double midpoint = duration/2;
const int mid = ticks < midpoint ? ticks : duration - ticks;
alpha = alphaClamp(mid, alphaMultiplier);
ticks++;
if (ticks >= duration){
ticks = 0;
next();
}
}
}
}
}
void OptionCredits::Sequence::draw(Graphics::Color title, Graphics::Color color, const Graphics::Bitmap & work){
if (!done && !credits.empty()){
if (type == Roll){
int rollY = (int) y;
for (std::vector<OptionCredits::Block>::const_iterator i = credits.begin(); i != credits.end(); ++i){
const OptionCredits::Block & block = *i;
rollY = block.print(x, rollY, title, color, Menu::menuFontParameter.current()->get(), work, justification);
}
} else if (type == Primary){
Graphics::Bitmap::transBlender(0, 0, 0, alpha);
credits[current].print(x, y, title, color, Menu::menuFontParameter.current()->get(), work.translucent(), justification);
}
}
}
void OptionCredits::Sequence::reset(){
done = false;
current = 0;
ticks = 0;
if (!credits.empty()){
if (type == Roll){
x = startx;
y = starty;
} else if (type == Primary){
x = startx;
y = starty - (credits[current].size(Menu::menuFontParameter.current()->get())/2);
}
}
}
void OptionCredits::Sequence::next(){
if (type == Primary){
if (current < credits.size()){
current++;
if (current == credits.size()){
done = true;
} else {
x = startx;
y = starty - (credits[current].size(Menu::menuFontParameter.current()->get())/2);
}
}
}
}
static std::string defaultPositions(){
const int width = Configuration::getScreenWidth();
const int height = Configuration::getScreenHeight();
std::ostringstream out;
out << "(start-x " << width/2.3 << ") (end-x " << width/1.8 << ") (start-y " << height/2 << ") ";
//out << "(start-x " << width/2 << ") (end-x " << width/2 << ") (start-y " << height/2 << ") (duration 250) ";
return out.str();
}
OptionCredits::OptionCredits(const Gui::ContextBox & parent, const Token * token):
MenuOption(parent, token),
creditsContext(new Menu::Context()),
music(""),
color(Graphics::makeColor(255,255,255)),
title(Graphics::makeColor(0,255,255)),
clearColor(Graphics::makeColor(0,0,0)){
std::string defaultSequence = "(sequence (type primary) (speed 0.3) (alpha-multiplier 20) (justification center) " + defaultPositions();
/* Always */
if (jonBirthday()){
defaultSequence += "(block (title \"Happy birthday, Jon!\"))";
}
if (miguelBirthday()){
defaultSequence += "(block (title \"Happy birthday, Jon!\"))";
}
if (Storage::instance().exists(Filesystem::RelativePath("sprites/paintown.png"))){
defaultSequence += "(block (animation (top) (width 350) (height 65) (image 0 \"sprites/paintown.png\") (frame (image 0) (time -1))) (credit \"Version " + Version::getVersionString() + "\"))";
} else {
defaultSequence += "(block (title \"PAINTOWN\") (credit \"Version " + Version::getVersionString() + "\"))";
}
defaultSequence += "(block (title \"Programming\") (credit \"Jon Rafkind\") (credit \"Miguel Gavidia\"))";
defaultSequence += "(block (title \"Level design\") (credit \"Jon Rafkind\") (credit \"Miguel Gavidia\"))";
defaultSequence += "(block (title \"Contact\") (credit \"Website: http://paintown.org\") (credit \"Email: jon@rafkind.com\")))";
TokenReader reader;
Sequence sequence(reader.readTokenFromString(defaultSequence));
sequences.push_back(sequence);
//Global::debug(0) << defaultSequence << std::endl;
if ( *token != "credits" ){
throw LoadException(__FILE__, __LINE__, "Not a credit menu");
}
readName(token);
TokenView view = token->view();
// NOTE Use this to handle legacy additional blocks for the time being
Block legacyAdditional("");
bool additionalTitle = true;
while (view.hasMore()){
try{
const Token * tok;
view >> tok;
if ( *tok == "music" ) {
/* Set music for credits */
tok->view() >> music;
} else if ( *tok == "background" ) {
/* Create an image and push it back on to vector */
std::string temp;
tok->view() >> temp;
creditsContext->addBackground(temp);
} else if ( *tok == "anim" || *tok == "animation" ){
creditsContext->addBackground(tok);
} else if ( *tok == "additional" ) {
std::string str;
TokenView additionalView = tok->view();
while (additionalView.hasMore()){
additionalView >> str;
if (additionalTitle){
legacyAdditional = Block(str);
additionalTitle = false;
} else {
legacyAdditional.addCredit(str);
}
}
} else if (*tok == "sequence"){
sequences.push_back(OptionCredits::Sequence(tok));
} else if ( *tok == "titlecolor" ) {
int r,b,g;
tok->view() >> r >> g >> b;
title = Graphics::makeColor( r, g, b );
} else if ( *tok == "color" ) {
int r,b,g;
tok->view() >> r >> g >> b;
color = Graphics::makeColor( r, g, b );
} else if ( *tok == "clear-color" ) {
int r,b,g;
tok->view() >> r >> g >> b;
clearColor = Graphics::makeColor( r, g, b );
} else {
Global::debug( 3 ) <<"Unhandled menu attribute: "<<endl;
if (Global::getDebug() >= 3){
tok->print(" ");
}
}
} catch ( const TokenException & ex ) {
throw LoadException(__FILE__, __LINE__, ex, "Menu parse error");
} catch ( const LoadException & ex ) {
throw ex;
}
}
if (!legacyAdditional.empty()){
//creditsRoll.push_back(legacyAdditional);
}
input.set(Keyboard::Key_ESC, 0, true, Exit);
input.set(Joystick::Button2, 0, true, Exit);
}
OptionCredits::~OptionCredits(){
}
void OptionCredits::logic(){
}
class CreditsLogicDraw : public Util::Logic, public Util::Draw{
public:
CreditsLogicDraw(std::vector<OptionCredits::Sequence> & sequences, Graphics::Color clearColor, Graphics::Color title, Graphics::Color color, const Font & font, InputMap<OptionCredits::CreditKey> & input, Menu::Context & context):
sequences(sequences),
clearColor(clearColor),
title(title),
color(color),
font(font),
input(input),
quit(false),
context(context),
current(0){
}
std::vector<OptionCredits::Sequence> & sequences;
Graphics::Color clearColor, title, color;
const Font & font;
InputMap<OptionCredits::CreditKey> & input;
bool quit;
Menu::Context & context;
unsigned int current;
void run(){
vector<InputMap<OptionCredits::CreditKey>::InputEvent> out = InputManager::getEvents(input, InputSource());
for (vector<InputMap<OptionCredits::CreditKey>::InputEvent>::iterator it = out.begin(); it != out.end(); it++){
const InputMap<OptionCredits::CreditKey>::InputEvent & event = *it;
if (event.enabled){
if (event.out == OptionCredits::Exit){
quit = true;
context.finish();
}
}
}
sequences[current].act();
if (sequences[current].isDone()){
sequences[current].reset();
current++;
if (current >= sequences.size()){
current = 0;
}
}
context.act();
}
bool done(){
return quit;
}
double ticks(double system){
return system * Global::ticksPerSecond(90);
}
void draw(const Graphics::Bitmap & buffer){
/* FIXME: hard coded resolution */
Graphics::StretchedBitmap work(640, 480, buffer, Graphics::qualityFilterName(Configuration::getQualityFilter()));
work.fill(clearColor);
work.start();
//background.Blit(work);
context.render(Util::ReferenceCount<Menu::Renderer>(NULL), work);
sequences[current].draw(title, color, work);
work.finish();
// buffer.BlitToScreen();
}
};
void OptionCredits::run(const Menu::Context & context){
Menu::Context localContext(context, *creditsContext);
localContext.initialize();
if (!music.empty()){
if (Music::loadSong(Storage::instance().find(Filesystem::RelativePath(music)).path())){
Music::pause();
Music::play();
}
}
const Font & vFont = Menu::menuFontParameter.current()->get();
CreditsLogicDraw loop(sequences, clearColor, title, color, vFont, input, localContext);
Util::standardLoop(loop, loop);
InputManager::waitForRelease(input, InputSource(), Exit);
throw Menu::Reload(__FILE__, __LINE__);
}
OptionDummy::OptionDummy(const Gui::ContextBox & parent, const Token *token):
MenuOption(parent, token){
if ( *token != "dummy" ){
throw LoadException(__FILE__, __LINE__, "Not dummy option");
}
readName(token);
if (getText().empty()){
this->setText("Dummy");
}
setRunnable(false);
}
OptionDummy::OptionDummy(const Gui::ContextBox & parent, const std::string &name):
MenuOption(parent, 0){
if (name.empty()){
throw LoadException(__FILE__, __LINE__, "No name given to dummy");
}
this->setText(name);
setRunnable(false);
}
OptionDummy::~OptionDummy(){
}
void OptionDummy::logic(){
}
void OptionDummy::run(const Menu::Context & context){
}
OptionFullscreen::OptionFullscreen(const Gui::ContextBox & parent, const Token *token):
MenuOption(parent, token),
lblue(255),
lgreen(255),
rblue(255),
rgreen(255){
setRunnable(false);
if ( *token != "fullscreen" )
throw LoadException(__FILE__, __LINE__, "Not fullscreen option");
readName(token);
}
OptionFullscreen::~OptionFullscreen()
{
// Nothing
}
std::string OptionFullscreen::getText() const {
ostringstream out;
out << MenuOption::getText() << ": " << (Configuration::getFullscreen() ? "Yes" : "No");
return out.str();
}
void OptionFullscreen::logic(){;
}
static void changeScreenMode(){
Configuration::setFullscreen(!Configuration::getFullscreen());
int gfx = (Configuration::getFullscreen() ? Global::FULLSCREEN : Global::WINDOWED);
Graphics::setGraphicsMode(gfx, Graphics::Bitmap::getScreenWidth(), Graphics::Bitmap::getScreenHeight());
}
void OptionFullscreen::run(const Menu::Context & context){
changeScreenMode();
}
bool OptionFullscreen::leftKey(){
changeScreenMode();
return true;
}
bool OptionFullscreen::rightKey(){
changeScreenMode();
return true;
}
OptionFps::OptionFps(const Gui::ContextBox & parent, const Token * token):
MenuOption(parent, token){
readName(token);
setRunnable(false);
}
void OptionFps::logic(){
}
void OptionFps::run(const Menu::Context & context){
}
std::string OptionFps::getText() const {
ostringstream out;
out << "Frames per second: " << Global::TICS_PER_SECOND;
return out.str();
}
bool OptionFps::leftKey(){
Global::setTicksPerSecond(Global::TICS_PER_SECOND - 1);
Configuration::setFps(Global::TICS_PER_SECOND);
return true;
}
bool OptionFps::rightKey(){
Global::setTicksPerSecond(Global::TICS_PER_SECOND + 1);
Configuration::setFps(Global::TICS_PER_SECOND);
return true;
}
OptionFps::~OptionFps(){
}
OptionQualityFilter::OptionQualityFilter(const Gui::ContextBox & parent, const Token * token):
MenuOption(parent, token){
readName(token);
setRunnable(false);
}
std::string OptionQualityFilter::getText() const {
ostringstream out;
out << MenuOption::getText() << ": " << Configuration::getQualityFilter();
return out.str();
}
void OptionQualityFilter::logic(){
}
bool OptionQualityFilter::leftKey(){
string quality = Configuration::getQualityFilter();
if (quality == "none"){
quality = "hqx";
} else if (quality == "hqx"){
quality = "xbr";
} else if (quality == "xbr"){
quality = "none";
}
Configuration::setQualityFilter(quality);
return true;
}
bool OptionQualityFilter::rightKey(){
string quality = Configuration::getQualityFilter();
if (quality == "none"){
quality = "xbr";
} else if (quality == "hqx"){
quality = "none";
} else if (quality == "xbr"){
quality = "hqx";
}
Configuration::setQualityFilter(quality);
return true;
}
void OptionQualityFilter::run(const Menu::Context & context){
}
OptionQualityFilter::~OptionQualityFilter(){
}
OptionInvincible::OptionInvincible(const Gui::ContextBox & parent, const Token *token):
MenuOption(parent, token),
lblue(255),
lgreen(255),
rblue(255),
rgreen(255){
setRunnable(false);
if ( *token != "invincible" )
throw LoadException(__FILE__, __LINE__, "Not invincible option");
readName(token);
}
OptionInvincible::~OptionInvincible()
{
// Nothing
}
std::string OptionInvincible::getText() const {
ostringstream out;
out << MenuOption::getText() << ": " << (Configuration::getInvincible() ? "Yes" : "No");
return out.str();
}
void OptionInvincible::logic(){
}
void OptionInvincible::run(const Menu::Context & context){
}
bool OptionInvincible::leftKey(){
Configuration::setInvincible(!Configuration::getInvincible());
return true;
}
bool OptionInvincible::rightKey(){
Configuration::setInvincible(!Configuration::getInvincible());
return true;
}
#if 0
static OptionJoystick::JoystickType convertToKey(const std::string &k){
std::string temp = k;
for(unsigned int i=0;i<temp.length();i++){
temp[i] = tolower(temp[i]);
}
if (temp == "up") return OptionJoystick::Up;
if (temp == "down") return OptionJoystick::Down;
if (temp == "left") return OptionJoystick::Left;
/*
if (temp == "right") return OptionJoystick::Right;
if (temp == "jump") return OptionJoystick::Jump;
if (temp == "attack1") return OptionJoystick::Attack1;
if (temp == "attack2") return OptionJoystick::Attack2;
if (temp == "attack3") return OptionJoystick::Attack3;
if (temp == "attack4") return OptionJoystick::Attack4;
if (temp == "attack5") return OptionJoystick::Attack5;
if (temp == "attack6") return OptionJoystick::Attack6;
return OptionJoystick::Invalidkey;
}
static Configuration::JoystickInput getKey(int player, OptionJoystick::JoystickType k){
switch(k){
case OptionJoystick::Up:
return Joystick::Up;
case OptionJoystick::Down:
return Joystick::Down;
case OptionJoystick::Left:
return Joystick::Left;
case OptionJoystick::Right:
return Joystick::Right;
case OptionJoystick::Jump:
return Joystick::Button4;
case OptionJoystick::Attack1:
return Joystick::Button1;
case OptionJoystick::Attack2:
return Joystick::Button2;
case OptionJoystick::Attack3:
return Joystick::Button3;
case OptionJoystick::Attack4:
return Joystick::Button4;
case OptionJoystick::Attack5:
return Joystick::Button5;
case OptionJoystick::Attack6:
return Joystick::Button6;
default:
break;
}
return Joystick::Up;
}
static void setKey(int player, OptionJoystick::JoystickType k, Configuration::JoystickInput key){
/ *
switch(k){
case OptionJoystick::Up:
Configuration::setJoystickUp(player, key);
break;
case OptionJoystick::Down:
Configuration::setJoystickDown(player, key);
break;
case OptionJoystick::Left:
Configuration::setJoystickLeft(player, key);
break;
case OptionJoystick::Right:
Configuration::setJoystickRight(player, key);
break;
case OptionJoystick::Jump:
Configuration::setJoystickJump(player, key);
break;
case OptionJoystick::Attack1:
Configuration::setJoystickAttack1(player, key);
break;
case OptionJoystick::Attack2:
Configuration::setJoystickAttack2(player, key);
break;
case OptionJoystick::Attack3:
Configuration::setJoystickAttack3(player, key);
break;
case OptionJoystick::Attack4:
Configuration::setJoystickAttack4(player, key);
break;
case OptionJoystick::Attack5:
Configuration::setJoystickAttack5(player, key);
break;
case OptionJoystick::Attack6:
Configuration::setJoystickAttack6(player, key);
break;
default:
break;
}
*/
}
static Configuration::JoystickInput readJoystick(){
vector<Joystick::Key> keys;
keys.push_back(Joystick::Up);
keys.push_back(Joystick::Down);
keys.push_back(Joystick::Left);
keys.push_back(Joystick::Right);
keys.push_back(Joystick::Button1);
keys.push_back(Joystick::Button2);
keys.push_back(Joystick::Button3);
keys.push_back(Joystick::Button4);
keys.push_back(Joystick::Button5);
keys.push_back(Joystick::Button6);
InputMap<Joystick::Key> input;
for (vector<Joystick::Key>::iterator it = keys.begin(); it != keys.end(); it++){
input.set(*it, 0, true, *it);
}
input.set(Keyboard::Key_ESC, 0, true, Joystick::Invalid);
while (true){
InputManager::poll();
vector<InputMap<Joystick::Key>::InputEvent> out = InputManager::getEvents(input, InputSource());
for (vector<InputMap<Joystick::Key>::InputEvent>::iterator it = out.begin(); it != out.end(); it++){
const InputMap<Joystick::Key>::InputEvent & event = *it;
if (event.enabled){
Global::debug(1) << "Press: " << event.out << std::endl;
if (event.out == Joystick::Invalid){
InputManager::waitForRelease(input, InputSource(), Joystick::Invalid);
throw Exception::Return(__FILE__, __LINE__);
}
return event.out;
}
}
Util::rest(1);
}
/* control probably shouldn't get here.. */
return Joystick::Up;
}
OptionJoystick::OptionJoystick(const Gui::ContextBox & parent, const Token *token):
MenuOption(parent, token),
name(""),
player(-1),
type(Invalidkey),
keyCode(0){
if (*token != "joystick"){
throw LoadException(__FILE__, __LINE__, "Not joystick option");
}
TokenView view = token->view();
while (view.hasMore()){
try{
const Token * tok;
view >> tok;
if ( *tok == "name" ){
tok->view() >> name;
} else if ( *tok == "player" ) {
tok->view() >> player;
} else if ( *tok == "type" ) {
std::string temp;
tok->view() >> temp;
type = convertToKey(temp);
} else {
Global::debug( 3 ) <<"Unhandled menu attribute: "<<endl;
tok->print(" ");
}
} catch ( const TokenException & ex ) {
throw LoadException(__FILE__, __LINE__, ex, "Menu parse error");
} catch ( const LoadException & ex ) {
// delete current;
throw ex;
}
}
if (name.empty()){
throw LoadException(__FILE__, __LINE__, "No name set, this option should have a name!");
}
if (type == Invalidkey){
throw LoadException(__FILE__, __LINE__, "Invalid joystick button, should be up, down, left, right, up, down, jump, attack1-6!");
}
if (player == -1){
throw LoadException(__FILE__, __LINE__, "Player not specified in joystick configuration");
}
ostringstream out;
out << name << ": " << Joystick::keyToName(getKey(player, type));
setText(out.str());
}
OptionJoystick::~OptionJoystick(){
// Nothing
}
void OptionJoystick::logic(){
/*
char temp[255];
sprintf( temp, "%s: %s", name.c_str(), Joystick::keyToName(getKey(player,type)));
setText(std::string(temp));
*/
}
void OptionJoystick::run(const Menu::Context & context){
/*
//int x, y, width, height;
const Font & vFont = Menu::menuFontParameter.current()->get();
const char * message = "Press a joystick button!";
const int width = vFont.textLength(message) + 10;
const int height = vFont.getHeight() + 10;
// const int x = (getParent()->getWork()->getWidth()/2) - (width/2);
// const int y = (getParent()->getWork()->getHeight()/2) - (height/2);
const int x = Menu::Menu::Width / 2 - width/2;
const int y = Menu::Menu::Height / 2 - height/2;
Box dialog;
dialog.location.setPosition(Gui::AbsolutePoint(0,0));
dialog.location.setDimensions(vFont.textLength(message) + 10, vFont.getHeight() + 10);
dialog.transforms.setRadius(0);
dialog.colors.body = Graphics::makeColor(0,0,0);
dialog.colors.bodyAlpha = 200;
dialog.colors.border = Graphics::makeColor(255,255,255);
dialog.colors.borderAlpha = 255;
Graphics::Bitmap temp = Graphics::Bitmap::temporaryBitmap(width,height);
dialog.render(temp, vFont);
vFont.printf( 5, 5, Graphics::makeColor(255,255,255), temp, message, -1);
temp.BlitToScreen(x,y);
setKey(player, type, readJoystick());
ostringstream out;
out << name << ": " << Joystick::keyToName(getKey(player, type));
setText(out.str());
*/
Graphics::Bitmap temp(Menu::Menu::Width, Menu::Menu::Height);
// Menu::Context tempContext = context;
Menu::Context tempContext(context);
tempContext.initialize();
Menu::InfoBox keyDialog;
// keyDialog.setFont(tempContext.getFont());
//keyDialog.location.set(-1,-1,1,1);
const int width = temp.getWidth();
const int height = temp.getHeight();
const Font & font = Menu::menuFontParameter.current()->get();
const int radius = 15;
keyDialog.setText("Press a joystick button!");
keyDialog.initialize(font);
keyDialog.location.setDimensions(font.textLength("Press a joystick button!") + radius, font.getHeight() + radius);
keyDialog.location.setCenterPosition(Gui::RelativePoint(0, 0));
// keyDialog.location.setPosition(Gui::AbsolutePoint((width/2)-(keyDialog.location.getWidth()/2), (height/2)-(keyDialog.location.getHeight()/2)));
// keyDialog.location.setPosition2(Gui::AbsolutePoint((
keyDialog.transforms.setRadius(radius);
keyDialog.colors.body = Graphics::makeColor(0,0,0);
keyDialog.colors.bodyAlpha = 180;
keyDialog.colors.border = Graphics::makeColor(255,255,255);
keyDialog.colors.borderAlpha = 255;
keyDialog.open();
InputManager::waitForClear();
while (!InputManager::anyInput() && keyDialog.isActive()){
InputManager::poll();
keyDialog.act(font);
/*
if (keyDialog.isActive()){
InputManager::poll();
}
*/
tempContext.act();
tempContext.render(0, temp);
keyDialog.render(temp, font);
temp.BlitToScreen();
}
tempContext.finish();
setKey(player, type, readJoystick());
InputManager::waitForClear();
ostringstream out;
out << name << ": " << Joystick::keyToName(getKey(player, type));
setText(out.str());
/*
Keyboard key;
keyCode = readKey(key);
setKey(player,type, keyCode);
*/
}
#endif
static OptionKey::keyType convertToKeyboardKey(const std::string &k){
std::string temp = k;
for(unsigned int i=0;i<temp.length();i++){
temp[i] = tolower(temp[i]);
}
if (temp == "up") return OptionKey::up;
if (temp == "down") return OptionKey::down;
if (temp == "left") return OptionKey::left;
if (temp == "right") return OptionKey::right;
if (temp == "jump") return OptionKey::jump;
if (temp == "attack1") return OptionKey::attack1;
if (temp == "attack2") return OptionKey::attack2;
if (temp == "attack3") return OptionKey::attack3;
if (temp == "attack4") return OptionKey::attack4;
if (temp == "attack5") return OptionKey::attack5;
if (temp == "attack6") return OptionKey::attack6;
return OptionKey::invalidkey;
}
static int getKey(int player, OptionKey::keyType k){
switch(k){
case OptionKey::up:
return Configuration::getUp(player);
break;
case OptionKey::down:
return Configuration::getDown(player);
break;
case OptionKey::left:
return Configuration::getLeft(player);
break;
case OptionKey::right:
return Configuration::getRight(player);
break;
case OptionKey::jump:
return Configuration::getJump(player);
break;
case OptionKey::attack1:
return Configuration::getAttack1(player);
break;
case OptionKey::attack2:
return Configuration::getAttack2(player);
break;
case OptionKey::attack3:
return Configuration::getAttack3(player);
break;
case OptionKey::attack4:
return Configuration::getAttack4(player);
case OptionKey::attack5:
return Configuration::getAttack5(player);
case OptionKey::attack6:
return Configuration::getAttack6(player);
default:
break;
}
return 0;
}
static void setKey(int player, OptionKey::keyType k, int key){
switch(k){
case OptionKey::up:
Configuration::setUp(player, key);
break;
case OptionKey::down:
Configuration::setDown(player, key);
break;
case OptionKey::left:
Configuration::setLeft(player, key);
break;
case OptionKey::right:
Configuration::setRight(player, key);
break;
case OptionKey::jump:
Configuration::setJump(player, key);
break;
case OptionKey::attack1:
Configuration::setAttack1(player, key);
break;
case OptionKey::attack2:
Configuration::setAttack2(player, key);
break;
case OptionKey::attack3:
Configuration::setAttack3(player, key);
break;
case OptionKey::attack4:
Configuration::setAttack4(player, key);
break;
case OptionKey::attack5:
Configuration::setAttack5(player, key);
break;
case OptionKey::attack6:
Configuration::setAttack6(player, key);
break;
default:
break;
}
}
/*
static int readKey( Keyboard & key ){
int k = key.readKey();
key.wait();
return k;
}
*/
OptionKey::OptionKey(const Gui::ContextBox & parent, const Token *token):
MenuOption(parent, token),
name(""),
player(-1),
type(invalidkey),
keyCode(0){
if ( *token != "key" )
throw LoadException(__FILE__, __LINE__, "Not key option");
TokenView view = token->view();
while (view.hasMore()) {
try {
const Token * tok;
view >> tok;
if ( *tok == "name" ) {
tok->view() >> name;
} else if ( *tok == "player" ) {
tok->view() >> player;
} else if ( *tok == "type" ) {
std::string temp;
tok->view() >> temp;
type = convertToKeyboardKey(temp);
} else {
Global::debug( 3 ) <<"Unhandled menu attribute: "<<endl;
tok->print(" ");
}
} catch ( const TokenException & ex ){
throw LoadException(__FILE__, __LINE__, ex, "Menu parse error");
} catch ( const LoadException & ex ) {
// delete current;
throw ex;
}
}
if(name.empty())throw LoadException(__FILE__, __LINE__, "No name set, this option should have a name!");
if(type == invalidkey)throw LoadException(__FILE__, __LINE__, "Invalid key, should be up, down, left, right, up, down, jump, attack1-6!");
if(player == -1)throw LoadException(__FILE__, __LINE__, "Player not specified in key configuration");
char temp[255];
sprintf( temp, "%s: %s", name.c_str(), Keyboard::keyToName(getKey(player,type)));
setText(std::string(temp));
}
OptionKey::~OptionKey(){
// Nothing
}
void OptionKey::logic(){
char temp[255];
sprintf( temp, "%s: %s", name.c_str(), Keyboard::keyToName(getKey(player,type)));
setText(std::string(temp));
}
void OptionKey::run(const Menu::Context & context){
// Do dialog
//Box::messageDialog(Menu::Menu::Width, Menu::Menu::Height, "Press a Key!",2);
/*
Keyboard key;
key.wait();
*/
Graphics::Bitmap temp(Menu::Menu::Width, Menu::Menu::Height);
// Menu::Context tempContext = context;
Menu::Context tempContext(context);
tempContext.initialize();
Menu::InfoBox keyDialog;
// keyDialog.setFont(tempContext.getFont());
//keyDialog.location.set(-1,-1,1,1);
const int width = temp.getWidth();
const int height = temp.getHeight();
const Font & font = Menu::menuFontParameter.current()->get();
const int radius = 15;
keyDialog.setText("Press a Key!");
keyDialog.initialize(font);
keyDialog.location.setDimensions(font.textLength("Press a Key!") + radius, font.getHeight() + radius);
keyDialog.location.setCenterPosition(Gui::RelativePoint(0, 0));
// keyDialog.location.setPosition(Gui::AbsolutePoint((width/2)-(keyDialog.location.getWidth()/2), (height/2)-(keyDialog.location.getHeight()/2)));
// keyDialog.location.setPosition2(Gui::AbsolutePoint((
keyDialog.transforms.setRadius(radius);
keyDialog.colors.body = Graphics::makeColor(0,0,0);
keyDialog.colors.bodyAlpha = 180;
keyDialog.colors.border = Graphics::makeColor(255,255,255);
keyDialog.colors.borderAlpha = 255;
keyDialog.open();
InputManager::waitForClear();
while (!InputManager::anyInput() && keyDialog.isActive()){
InputManager::poll();
keyDialog.act(font);
/*
if (keyDialog.isActive()){
InputManager::poll();
}
*/
tempContext.act();
tempContext.render(Util::ReferenceCount<Menu::Renderer>(NULL), temp);
keyDialog.render(temp, font);
temp.BlitToScreen();
}
tempContext.finish();
keyCode = InputManager::readKey();
setKey(player,type, keyCode);
InputManager::waitForClear();
}
OptionLevel::OptionLevel(const Gui::ContextBox & parent, const Token *token, int * set, int value):
MenuOption(parent, token),
set(set),
value(value){
// Nothing
}
OptionLevel::~OptionLevel(){
}
void OptionLevel::logic(){
}
void OptionLevel::run(const Menu::Context & context){
*set = value;
throw Menu::MenuException(__FILE__, __LINE__);
}
OptionLives::OptionLives(const Gui::ContextBox & parent, const Token * token):
MenuOption(parent, token),
lblue(255),
lgreen(255),
rblue(255),
rgreen(255){
setRunnable(false);
if ( *token != "lives" ){
throw LoadException(__FILE__, __LINE__, "Not lives option" );
}
readName(token);
}
OptionLives::~OptionLives(){
}
std::string OptionLives::getText() const {
ostringstream out;
out << MenuOption::getText() << ": " << Configuration::getLives();
return out.str();
}
void OptionLives::logic(){
}
void OptionLives::run(const Menu::Context & context){
}
bool OptionLives::leftKey(){
Configuration::setLives(Configuration::getLives() - 1);
if ( Configuration::getLives() < 1 ){
Configuration::setLives(1);
}
return false;
}
bool OptionLives::rightKey(){
Configuration::setLives( Configuration::getLives() + 1 );
return false;
}
OptionMenu::OptionMenu(const Gui::ContextBox & parent, const Token *token, const Menu::OptionFactory & factory):
MenuOption(parent, token),
menu(0){
if (*token != "menu"){
throw LoadException(__FILE__, __LINE__, "Not a menu");
}
if (token->numTokens() == 1){
std::string temp;
token->view() >> temp;
menu = new Menu::Menu(Storage::instance().find(Filesystem::RelativePath(temp)), factory);
} else {
menu = new Menu::Menu(token, factory);
}
this->setText(menu->getName());
this->setInfoText(menu->getInfo());
// Lets check if this menu is going bye bye
//if ( menu->checkRemoval() ) setForRemoval(true);
}
OptionMenu::~OptionMenu(){
// Delete our menu
if (menu){
delete menu;
}
}
void OptionMenu::logic(){
// Nothing
}
void OptionMenu::run(const Menu::Context & context){
// Do our new menu
try{
menu->run(context);
} catch (const Exception::Return ignore){
throw Menu::Reload(__FILE__, __LINE__);
}
}
OptionNpcBuddies::OptionNpcBuddies(const Gui::ContextBox & parent, const Token * token):
MenuOption(parent, token),
lblue(255),
lgreen(255),
rblue(255),
rgreen(255){
setRunnable(false);
if ( *token != "npc" ){
throw LoadException(__FILE__, __LINE__, "Not npc option" );
}
readName(token);
}
OptionNpcBuddies::~OptionNpcBuddies(){
// Nothing
}
std::string OptionNpcBuddies::getText() const {
ostringstream out;
out << MenuOption::getText() << ": " << Configuration::getNpcBuddies();
return out.str();
}
void OptionNpcBuddies::logic(){
}
void OptionNpcBuddies::run(const Menu::Context & context){
}
bool OptionNpcBuddies::leftKey(){
Configuration::setNpcBuddies(Configuration::getNpcBuddies() - 1);
if ( Configuration::getNpcBuddies() < 1 ){
Configuration::setNpcBuddies(1);
}
return false;
}
bool OptionNpcBuddies::rightKey(){
Configuration::setNpcBuddies( Configuration::getNpcBuddies() + 1 );
rblue = rgreen = 0;
return false;
}
OptionPlayMode::OptionPlayMode(const Gui::ContextBox & parent, const Token *token):
MenuOption(parent, token),
lblue(255),
lgreen(255),
rblue(255),
rgreen(255){
setRunnable(false);
if ( *token != "play-mode" ){
throw LoadException(__FILE__, __LINE__, "Not a play-mode");
}
readName(token);
}
OptionPlayMode::~OptionPlayMode(){
// Nothing
}
std::string OptionPlayMode::getText() const {
ostringstream out;
out << MenuOption::getText() << ": ";
/* TODO: language translations of these */
if (Configuration::getPlayMode() == Configuration::FreeForAll){
out << "Free for all";
} else if (Configuration::getPlayMode() == Configuration::Cooperative){
out << "Cooperative";
}
return out.str();
}
void OptionPlayMode::logic(){
}
void OptionPlayMode::run(const Menu::Context & context){
}
void OptionPlayMode::changeMode(){
if (Configuration::getPlayMode() == Configuration::FreeForAll){
Configuration::setPlayMode(Configuration::Cooperative);
} else if (Configuration::getPlayMode() == Configuration::Cooperative){
Configuration::setPlayMode(Configuration::FreeForAll);
}
}
bool OptionPlayMode::leftKey(){
changeMode();
lblue = lgreen = 0;
return true;
}
bool OptionPlayMode::rightKey(){
changeMode();
rblue = rgreen = 0;
return true;
}
OptionReturn::OptionReturn(const Gui::ContextBox & parent, const Token * token):
MenuOption(parent, token){
if (*token != "return"){
throw LoadException(__FILE__, __LINE__, "Not a return option");
}
readName(token);
}
void OptionReturn::logic(){
}
/* maybe this option is misnamed, but its supposed to quit the current game
* and go back to the main menu
*/
void OptionReturn::run(const Menu::Context & context){
throw Exception::Quit(__FILE__, __LINE__);
}
OptionReturn::~OptionReturn(){
}
OptionContinue::OptionContinue(const Gui::ContextBox & parent, const Token * token):
MenuOption(parent, token){
if (*token != "continue"){
throw LoadException(__FILE__, __LINE__, "Not a continue option");
}
readName(token);
}
void OptionContinue::logic(){
}
void OptionContinue::run(const Menu::Context & context){
throw Exception::Return(__FILE__, __LINE__);
}
OptionContinue::~OptionContinue(){
}
OptionQuit::OptionQuit(const Gui::ContextBox & parent, const Token *token):
MenuOption(parent, token){
if ( *token != "quit" ){
throw LoadException(__FILE__, __LINE__, "Not quit option");
}
readName(token);
}
OptionQuit::OptionQuit(const Gui::ContextBox & parent, const std::string &name):
MenuOption(parent, 0){
if (name.empty()){
throw LoadException(__FILE__, __LINE__, "No name given to quit");
}
this->setText(name);
}
OptionQuit::~OptionQuit(){
}
void OptionQuit::logic(){
}
void OptionQuit::run(const Menu::Context & context){
throw ShutdownException();
}
#if defined(WINDOWS) && defined(doesnt_work_yet)
#include <windows.h>
#include <stdio.h>
/* contributed by Roy Underthump from allegro.cc */
static vector<ScreenSize> getScreenResolutions(){
HWND hwnd;
HDC hdc;
// int iPixelFormat;
int descerr;
int retval;
DEVMODE d;
PIXELFORMATDESCRIPTOR pfd;
hwnd = GetDesktopWindow();
hdc = GetDC(hwnd);
vector<ScreenSize> modes;
for (int i = 0;; i++){
retval = EnumDisplaySettings(0,i,&d);
if (!retval){
break;
}
descerr = DescribePixelFormat(hdc, i+1, sizeof(pfd), &pfd);
if(!descerr){
continue;
}
/*
printf("\n#%d bpp %d width %d height %d colorbits %d fps %d",i,d.dmBitsPerPel,
d.dmPelsWidth, d.dmPelsHeight,pfd.cColorBits,d.dmDisplayFrequency);
if(pfd.dwFlags & PFD_SUPPORT_OPENGL)printf(" OGL OK");
*/
modes.push_back(ScreenSize(d.dmPelsWidth, d.dmPelsHeight));
}
if (modes.empty()){
modes.push_back(ScreenSize(640,480));
}
return modes;
}
#else
static vector<ScreenSize> getScreenResolutions(){
vector<ScreenSize> modes;
modes.push_back(ScreenSize(320, 240));
modes.push_back(ScreenSize(640, 480));
modes.push_back(ScreenSize(800, 600));
modes.push_back(ScreenSize(960, 720));
modes.push_back(ScreenSize(1024, 768));
modes.push_back(ScreenSize(1280, 960));
modes.push_back(ScreenSize(1600, 1200));
return modes;
}
#endif
static bool doSort(const ScreenSize & a, const ScreenSize & b){
return (a.w * a.h) < (b.w * b.h);
}
static vector<ScreenSize> sortResolutions(const vector<ScreenSize> & modes){
vector<ScreenSize> copy(modes);
std::sort(copy.begin(), copy.end(), doSort);
return copy;
}
OptionScreenSize::OptionScreenSize(const Gui::ContextBox & parent, const Token *token):
MenuOption(parent, token),
name(""),
lblue(255),
lgreen(255),
rblue(255),
rgreen(255){
setRunnable(false);
Global::debug(1) << "Get screen resolution" << endl;
modes = sortResolutions(getScreenResolutions());
if (Global::getDebug() >= 1){
for (vector<ScreenSize>::iterator it = modes.begin(); it != modes.end(); it++){
Global::debug(1) << "Screen size: " << it->w << " x " << it->h << endl;
}
}
if ( *token != "screen-size" ){
throw LoadException(__FILE__, __LINE__, "Not a screen-size");
}
readName(token);
}
OptionScreenSize::~OptionScreenSize(){
// Nothing
}
void OptionScreenSize::logic(){
ostringstream temp;
temp << "Screen size: " << Configuration::getScreenWidth() << " x " << Configuration::getScreenHeight();
setText(temp.str());
}
void OptionScreenSize::run(const Menu::Context & context){
}
void OptionScreenSize::setMode(int width, int height){
if (width != Configuration::getScreenWidth() ||
height != Configuration::getScreenHeight()){
Global::debug(1) << "Changing mode to " << width << " x " << height << endl;
int gfx = Configuration::getFullscreen() ? Global::FULLSCREEN : Global::WINDOWED;
int ok = Graphics::setGraphicsMode(gfx, width, height);
if (ok == 0){
Global::debug(1) << "Success" << endl;
Configuration::setScreenWidth(width);
Configuration::setScreenHeight(height);
} else {
Global::debug(1) << "Fail" << endl;
int ok = Graphics::setGraphicsMode(gfx, Configuration::getScreenWidth(), Configuration::getScreenHeight());
Global::debug(1) << "Set mode back " << ok << endl;
}
}
}
/*
static int modes[][2] = {{640,480}, {800,600}, {1024,768}, {1280,1024}, {1600,1200}};
// static int max_modes = sizeof(modes) / sizeof(int[]);
static int max_modes = 5;
*/
int OptionScreenSize::findMode(int width, int height){
for (int mode = 0; mode < (int) modes.size(); mode++){
if (modes[mode].w == width && modes[mode].h == height){
return mode;
}
}
return -1;
}
bool OptionScreenSize::leftKey(){
int mode = findMode(Configuration::getScreenWidth(), Configuration::getScreenHeight());
if (mode >= 1 && mode < (int)modes.size()){
mode -= 1;
} else {
mode = 0;
}
setMode(modes[mode].w, modes[mode].h);
lblue = lgreen = 0;
return true;
}
bool OptionScreenSize::rightKey(){
int mode = findMode(Configuration::getScreenWidth(), Configuration::getScreenHeight());
if (mode >= 0 && mode < (int)modes.size() - 1){
mode += 1;
} else {
mode = 0;
}
setMode(modes[mode].w, modes[mode].h);
rblue = rgreen = 0;
return true;
}
static string joinPaths(const vector<Filesystem::AbsolutePath> & strings, const string & middle){
ostringstream out;
for (vector<Filesystem::AbsolutePath>::const_iterator it = strings.begin(); it != strings.end(); it++){
out << (*it).path() << middle;
}
return out.str();
}
static bool sortInfo(const Util::ReferenceCount<Menu::FontInfo> & info1,
const Util::ReferenceCount<Menu::FontInfo> & info2){
string name1 = Util::lowerCaseAll(info1->getName());
string name2 = Util::lowerCaseAll(info2->getName());
return name1 < name2;
}
static bool isWindows(){
#ifdef WINDOWS
return true;
#else
return false;
#endif
}
static bool isOSX(){
#ifdef MACOSX
return true;
#else
return false;
#endif
}
template <class X>
static vector<X> operator+(const vector<X> & v1, const vector<X> & v2){
vector<X> out;
for (typename vector<X>::const_iterator it = v1.begin(); it != v1.end(); it++){
out.push_back(*it);
}
for (typename vector<X>::const_iterator it = v2.begin(); it != v2.end(); it++){
out.push_back(*it);
}
return out;
}
static vector<Filesystem::AbsolutePath> findSystemFonts(){
if (isWindows()){
const char * windows = getenv("windir");
if (windows != NULL){
return Storage::instance().getFilesRecursive(Filesystem::AbsolutePath(string(windows) + "/fonts"), "*.ttf");
}
return vector<Filesystem::AbsolutePath>();
} else if (isOSX()){
return Storage::instance().getFilesRecursive(Filesystem::AbsolutePath("/Library/Fonts"), "*.ttf");
} else {
/* assume unix/linux conventions */
return Storage::instance().getFilesRecursive(Filesystem::AbsolutePath("/usr/share/fonts/truetype"), "*.ttf") +
Storage::instance().getFilesRecursive(Filesystem::AbsolutePath("/usr/local/share/fonts/truetype"), "*.ttf");
}
}
static vector<Util::ReferenceCount<Menu::FontInfo> > findFonts(){
vector<Util::ReferenceCount<Menu::FontInfo> > fonts;
try{
Filesystem::AbsolutePath fontsDirectory = Storage::instance().find(Filesystem::RelativePath("fonts"));
Global::debug(1, "fonts") << "Font directory " << fontsDirectory.path() << endl;
vector<Filesystem::AbsolutePath> ttfFonts = Storage::instance().getFiles(fontsDirectory, "*.ttf");
Global::debug(1, "fonts") << "Found ttf fonts " << joinPaths(ttfFonts, ", ") << endl;
vector<Filesystem::AbsolutePath> otfFonts = Storage::instance().getFiles(fontsDirectory, "*.otf");
Global::debug(1, "fonts") << "Found otf fonts " << joinPaths(otfFonts, ", ") << endl;
for (vector<Filesystem::AbsolutePath>::iterator it = ttfFonts.begin(); it != ttfFonts.end(); it++){
fonts.push_back(Util::ReferenceCount<Menu::FontInfo>(new Menu::RelativeFontInfo(Storage::instance().cleanse(*it), Configuration::getMenuFontWidth(), Configuration::getMenuFontHeight())));
}
for (vector<Filesystem::AbsolutePath>::iterator it = otfFonts.begin(); it != otfFonts.end(); it++){
fonts.push_back(Util::ReferenceCount<Menu::FontInfo>(new Menu::RelativeFontInfo(Storage::instance().cleanse(*it), Configuration::getMenuFontWidth(), Configuration::getMenuFontHeight())));
}
/* linux specific fonts */
vector<Filesystem::AbsolutePath> systemFonts = findSystemFonts();
for (vector<Filesystem::AbsolutePath>::iterator it = systemFonts.begin(); it != systemFonts.end(); it++){
Global::debug(1) << "Adding system font `" << (*it).path() << "'" << endl;
fonts.push_back(Util::ReferenceCount<Menu::FontInfo>(new Menu::AbsoluteFontInfo(*it, Configuration::getMenuFontWidth(), Configuration::getMenuFontHeight())));
}
sort(fonts.begin(), fonts.end(), sortInfo);
// DEFAULT (blank)
// fonts.insert(fonts.begin(), new Menu::DefaultFontInfo());
fonts.insert(fonts.begin(), Util::ReferenceCount<Menu::FontInfo>(NULL));
} catch (const Filesystem::NotFound & e){
throw LoadException(__FILE__, __LINE__, e, "Could not load font");
}
return fonts;
}
OptionSelectFont::OptionSelectFont(const Gui::ContextBox & parent, const Token *token):
MenuOption(parent, token),
typeAdjust(fontName),
lblue(255),
lgreen(255),
rblue(255),
rgreen(255){
setRunnable(false);
if ( *token != "font-select" ){
throw LoadException(__FILE__, __LINE__, "Not a font selector");
}
TokenView view = token->view();
while (view.hasMore()){
try{
const Token * tok;
view >> tok;
if ( *tok == "adjust" ){
std::string temp;
tok->view() >> temp;
if ( temp == "name" ) typeAdjust = fontName;
else if ( temp == "width" ) typeAdjust = fontWidth;
else if ( temp == "height" ) typeAdjust = fontHeight;
else throw LoadException(__FILE__, __LINE__, "Incorrect value \"" + temp + "\" in font-select");
} else {
Global::debug(3) << "Unhandled menu attribute: " << endl;
if (Global::getDebug() >= 3){
tok->print(" ");
}
}
} catch ( const TokenException & ex ) {
throw LoadException(__FILE__, __LINE__, ex, "Menu parse error");
} catch ( const LoadException & ex ) {
// delete current;
throw ex;
}
}
}
void OptionSelectFont::open(){
// Find and set fonts now
if (typeAdjust == fontName){
fonts = findFonts();
}
}
void OptionSelectFont::close(){
if (typeAdjust == fontName){
/* the user probably loaded a bunch of different fonts that will
* never be used again, so clear the font cache
* TODO: dont clear the currently selected font
*/
FontFactory::clear();
}
}
OptionSelectFont::~OptionSelectFont(){
// Nothing
}
void OptionSelectFont::logic(){
/* FIXME Get current font and display info */
switch (typeAdjust){
case fontName:{
std::string name;
if (Configuration::hasMenuFont()){
name = Configuration::getMenuFont()->getName();
} else {
name = "Default";
}
setText("Current Font: " + name);
break;
}
case fontWidth:{
ostringstream temp;
temp << "Font Width: " << Configuration::getMenuFontWidth();
setText(temp.str());
break;
}
case fontHeight:{
ostringstream temp;
temp << "Font Height: " << Configuration::getMenuFontHeight();
setText(temp.str());
break;
}
default: break;
}
if (lblue < 255){
lblue += 5;
}
if (rblue < 255){
rblue += 5;
}
if (lgreen < 255){
lgreen += 5;
}
if (rgreen < 255){
rgreen += 5;
}
}
void OptionSelectFont::run(const Menu::Context & context){
// throw Menu::MenuException(__FILE__, __LINE__);
/* throw something to quit back to the previous menu */
}
bool OptionSelectFont::leftKey(){
switch (typeAdjust){
case fontName:
nextIndex(false);
break;
case fontWidth:
Configuration::setMenuFontWidth(Configuration::getMenuFontWidth() - 1);
break;
case fontHeight:
Configuration::setMenuFontHeight(Configuration::getMenuFontHeight() - 1);
break;
default:
break;
}
lblue = lgreen = 0;
return true;
}
bool OptionSelectFont::rightKey(){
switch (typeAdjust){
case fontName:
nextIndex(true);
break;
case fontWidth:
Configuration::setMenuFontWidth(Configuration::getMenuFontWidth() + 1);
break;
case fontHeight:
Configuration::setMenuFontHeight(Configuration::getMenuFontHeight() + 1);
break;
default:
break;
}
rblue = rgreen = 0;
return true;
}
static bool saneFont(const Util::ReferenceCount<Menu::FontInfo> & info){
class Context: public Loader::LoadingContext {
public:
Context(const Util::ReferenceCount<Menu::FontInfo> & info):
info(info),
isok(false){
}
bool ok(){
try{
const Font & font = info->get();
return font.textLength("A") != 0 &&
font.getHeight() != 0;
} catch (const Exception::Base & ignore){
return true;
}
}
virtual void load(){
isok = ok();
}
const Util::ReferenceCount<Menu::FontInfo> & info;
bool isok;
};
if (info == NULL){
return true;
}
Context context(info);
/* an empty Info object, we don't really care about it */
Loader::Info level("Loading Font", Filesystem::AbsolutePath());
Loader::loadScreen(context, level, Loader::SimpleCircle);
return context.isok;
}
void OptionSelectFont::nextIndex(bool forward){
if (fonts.size() == 0){
return;
}
int index = 0;
for (unsigned int i = 0 ; i < fonts.size() ; ++i){
if ((Configuration::getMenuFont() == NULL && fonts[i] == NULL) ||
((Configuration::getMenuFont() != NULL && fonts[i] != NULL) &&
(*Configuration::getMenuFont() == *fonts[i]))){
index = i;
}
}
if (forward){
index++;
if (index >= (int) fonts.size()){
index = 0;
}
} else {
index--;
if (index < 0){
index = (int)fonts.size()-1;
}
}
while (!saneFont(fonts[index])){
Global::debug(0) << "Warning: erasing font `" << fonts[index]->getName() << "'" << endl;
int where = 0;
vector<Util::ReferenceCount<Menu::FontInfo> >::iterator it;
for (it = fonts.begin(); it != fonts.end() && where != index; it++, where++){
}
fonts.erase(it);
if (index >= (int) fonts.size()){
index = fonts.size() - 1;
}
}
Configuration::setMenuFont(fonts[index]);
/* FIXME */
/*
if (fonts[index] == "Default"){
Configuration::setMenuFont("");
} else {
Configuration::setMenuFont(fonts[index]);
}
*/
}
OptionSpeed::OptionSpeed(const Gui::ContextBox & parent, const Token *token):
MenuOption(parent, token),
name(""),
lblue(255),
lgreen(255),
rblue(255),
rgreen(255){
setRunnable(false);
if ( *token != "speed" )
throw LoadException(__FILE__, __LINE__, "Not speed option");
readName(token);
}
OptionSpeed::~OptionSpeed(){
// Nothing
}
std::string OptionSpeed::getText() const {
ostringstream out;
out << MenuOption::getText() << ": " << Configuration::getGameSpeed();
return out.str();
}
void OptionSpeed::logic(){
/*
//ostringstream temp;
char temp[255];
sprintf( temp, "%s: %0.2f", name.c_str(), MenuGlobals::getGameSpeed() );
setText(std::string(temp));
*/
}
void OptionSpeed::run(const Menu::Context & context){
}
bool OptionSpeed::leftKey(){
Configuration::setGameSpeed(Configuration::getGameSpeed() - 0.05);
if (Configuration::getGameSpeed() < 0.1){
Configuration::setGameSpeed(0.1);
}
return false;
}
bool OptionSpeed::rightKey(){
Configuration::setGameSpeed(Configuration::getGameSpeed() + 0.05);
rblue = rgreen = 0;
return false;
}
OptionTabMenu::OptionTabMenu(const Gui::ContextBox & parent, const Token *token, const Menu::OptionFactory & factory):
MenuOption(parent, token),
menu(0){
if (token->numTokens() == 1){
std::string temp;
token->view() >> temp;
menu = new Menu::Menu(Storage::instance().find(Filesystem::RelativePath(temp)), factory, Menu::Renderer::Tabbed);
} else {
menu = new Menu::Menu(token, factory, Menu::Renderer::Tabbed);
}
// this->setText(menu->getName());
// token->print("Menu: ");
const Token * tok = token->findToken("_/name");
if (tok != NULL){
std::string name;
tok->view() >> name;
// Global::debug(0, "menu") << "Menu name: " << name << endl;
this->setText(name);
} else {
// No name?
throw LoadException(__FILE__, __LINE__, "Menu has no name");
}
}
OptionTabMenu::~OptionTabMenu(){
// Delete our menu
if (menu){
delete menu;
}
}
void OptionTabMenu::logic(){
// Nothing
}
void OptionTabMenu::run(const Menu::Context & context){
// Do our new menu
// menu->run(context);
try{
menu->run(context);
} catch (const Exception::Return ignore){
throw Menu::Reload(__FILE__, __LINE__);
}
}
OptionSound::OptionSound(const Gui::ContextBox & parent, const Token *token):
MenuOption(parent, token),
lblue(255),
lgreen(255),
rblue(255),
rgreen(255){
setRunnable(false);
if (*token != "sound" ){
throw LoadException(__FILE__, __LINE__, "Not a sound option");
}
readName(token);
originalName = getName();
}
OptionSound::~OptionSound(){
}
void OptionSound::logic(){
ostringstream temp;
temp << originalName << ": " << Configuration::getSoundVolume();
setText(temp.str());
}
void OptionSound::run(const Menu::Context & context){
}
void OptionSound::changeSound(int much){
int volume = Configuration::getSoundVolume();
volume += much;
if (volume < 0){
volume = 0;
}
if (volume > 100){
volume = 100;
}
Configuration::setSoundVolume(volume);
}
bool OptionSound::leftKey(){
changeSound(-1);
lblue = lgreen = 0;
return true;
}
bool OptionSound::rightKey(){
changeSound(+1);
rblue = rgreen = 0;
return true;
}
OptionMusic::OptionMusic(const Gui::ContextBox & parent, const Token *token):
MenuOption(parent, token),
lblue(255),
lgreen(255),
rblue(255),
rgreen(255){
setRunnable(false);
if (*token != "music" ){
throw LoadException(__FILE__, __LINE__, "Not a music option");
}
readName(token);
originalName = getName();
}
void OptionMusic::logic(){
ostringstream temp;
temp << originalName << ": " << Configuration::getMusicVolume();
setText(temp.str());
}
void OptionMusic::run(const Menu::Context & context){
}
void OptionMusic::changeMusic(int much){
int volume = Configuration::getMusicVolume();
volume += much;
if (volume < 0){
volume = 0;
}
if (volume > 100){
volume = 100;
}
Configuration::setMusicVolume(volume);
Music::setVolume((double) volume / 100.0);
}
bool OptionMusic::leftKey(){
changeMusic(-1);
lblue = lgreen = 0;
return true;
}
bool OptionMusic::rightKey(){
changeMusic(+1);
lblue = lgreen = 0;
return true;
}
OptionMusic::~OptionMusic(){
}
OptionLanguage::OptionLanguage(const Gui::ContextBox & parent, const Token * token):
MenuOption(parent, token){
readName(token);
#if 0
const Token * start = token->getRootParent();
vector<const Token*> tokens = start->findTokens("*/language");
vector<string> all;
for (vector<const Token*>::iterator it = tokens.begin(); it != tokens.end(); it++){
string language;
const Token * token = *it;
if (token->match("language", language)){
all.push_back(language);
}
}
sort(all.begin(), all.end());
unique_copy(all.begin(), all.end(), back_insert_iterator<vector<string> >(languages));
// Global::debug(0) << "Found " << languages.size() << " languages" << endl;
#endif
}
void OptionLanguage::run(const Menu::Context & context){
class LanguageOption: public MenuOption {
public:
LanguageOption(const Gui::ContextBox & parent, const string & language):
MenuOption(parent, NULL){
setText(language);
setInfoText(language);
}
virtual void logic(){
}
virtual void run(const ::Menu::Context & context){
Configuration::setLanguage(getText());
Configuration::saveConfiguration();
throw ::Menu::MenuException(__FILE__, __LINE__);
}
};
Util::NewReferenceCount<Menu::DefaultRenderer> renderer;
Menu::Menu temp(renderer.convert<Menu::Renderer>());
Util::ReferenceCount<Menu::FontInfo> info(new Menu::RelativeFontInfo(Font::getDefaultFontPath(), 24, 24));
temp.setFont(info);
const Gui::ContextBox & box = renderer->getBox();
vector<string> languages = context.getLanguages();
for (vector<string>::iterator it = languages.begin(); it != languages.end(); it++){
temp.addOption(new LanguageOption(box, *it));
}
try {
temp.run(context);
} catch (const Exception::Return & ignore){
} catch (const Menu::MenuException & ex){
}
throw Menu::Reload(__FILE__, __LINE__);
// throw Exception::Return(__FILE__, __LINE__);
}
void OptionLanguage::logic(){
}
OptionGibs::OptionGibs(const Gui::ContextBox & parent, const Token *token):
MenuOption(parent, token){
setRunnable(false);
if (*token != "gibs" ){
throw LoadException(__FILE__, __LINE__, "Not a gibs option");
}
readName(token);
originalName = getName();
}
void OptionGibs::logic(){
ostringstream temp;
/* FIXME: we want to use Gib::GibProperty here but that would necessitate a
* dependancy on the Paintown engine.
*/
temp << originalName << ": " << Configuration::getProperty("paintown/gibs", 5);
setText(temp.str());
}
void OptionGibs::run(const Menu::Context & context){
}
void OptionGibs::changeGibs(int much){
int gibs = Configuration::getProperty("paintown/gibs", 5);
gibs += much;
if (gibs < 0){
gibs = 0;
}
if (gibs > 10){
gibs = 10;
}
Configuration::setProperty("paintown/gibs", gibs);
}
bool OptionGibs::leftKey(){
changeGibs(-1);
return true;
}
bool OptionGibs::rightKey(){
changeGibs(+1);
return true;
}
OptionGibs::~OptionGibs(){
}
OptionJoystick::OptionJoystick(const Gui::ContextBox & parent, const Token *token):
MenuOption(parent, token){
setRunnable(true);
if (*token != "joystick" ){
throw LoadException(__FILE__, __LINE__, "Not a joystick option");
}
readName(token);
}
void OptionJoystick::logic(){
}
class JoystickLogicDraw: public Util::Logic, public Util::Draw {
public:
enum Inputs{
Exit
};
- JoystickLogicDraw(const Util::ReferenceCount<Joystick> & joystick, const ::Menu::Context & context):
+ static const int marginX = 20;
+
+ JoystickLogicDraw(int id, const Util::ReferenceCount<Joystick> & joystick, const ::Menu::Context & context):
+ id(id),
joystick(joystick),
quit(false),
context(context, Menu::Context()){
input.set(Keyboard::Key_ESC, Exit);
}
+ const int id;
Util::ReferenceCount<Joystick> joystick;
bool quit;
Menu::Context context;
InputMap<Inputs> input;
void doInput(){
vector<InputMap<Inputs>::InputEvent> out = InputManager::getEvents(input, InputSource());
for (vector<InputMap<Inputs>::InputEvent>::iterator it = out.begin(); it != out.end(); it++){
const InputMap<Inputs>::InputEvent & event = *it;
if (event.enabled){
if (event.out == Exit){
quit = true;
// context.finish();
}
}
}
}
virtual void run(){
doInput();
context.act();
}
bool done(){
return quit;
}
double ticks(double system){
return system * Global::ticksPerSecond(60);
}
- void drawButtons(const Font & font, const Graphics::Bitmap & buffer){
- int y = 30;
+ void drawButtons(const Font & font, const Graphics::Bitmap & buffer, int y){
Graphics::Color color = Graphics::makeColor(255, 255, 255);
- font.printf(1, y, color, buffer, "Up: ", 0); y += font.getHeight() + 5;
- font.printf(1, y, color, buffer, "Down: ", 0); y += font.getHeight() + 5;
- font.printf(1, y, color, buffer, "Left: ", 0); y += font.getHeight() + 5;
- font.printf(1, y, color, buffer, "Right: ", 0); y += font.getHeight() + 5;
- font.printf(1, y, color, buffer, "Button1: ", 0); y += font.getHeight() + 5;
- font.printf(1, y, color, buffer, "Button2: ", 0); y += font.getHeight() + 5;
- font.printf(1, y, color, buffer, "Button3: ", 0); y += font.getHeight() + 5;
- font.printf(1, y, color, buffer, "Button4: ", 0); y += font.getHeight() + 5;
- font.printf(1, y, color, buffer, "Button5: ", 0); y += font.getHeight() + 5;
- font.printf(1, y, color, buffer, "Button6: ", 0); y += font.getHeight() + 5;
- font.printf(1, y, color, buffer, "Select: ", 0); y += font.getHeight() + 5;
- font.printf(1, y, color, buffer, "Quit: ", 0); y += font.getHeight() + 5;
+ font.printf(marginX, y, color, buffer, "Up: ", 0); y += font.getHeight() + 5;
+ font.printf(marginX, y, color, buffer, "Down: ", 0); y += font.getHeight() + 5;
+ font.printf(marginX, y, color, buffer, "Left: ", 0); y += font.getHeight() + 5;
+ font.printf(marginX, y, color, buffer, "Right: ", 0); y += font.getHeight() + 5;
+ font.printf(marginX, y, color, buffer, "Button1: ", 0); y += font.getHeight() + 5;
+ font.printf(marginX, y, color, buffer, "Button2: ", 0); y += font.getHeight() + 5;
+ font.printf(marginX, y, color, buffer, "Button3: ", 0); y += font.getHeight() + 5;
+ font.printf(marginX, y, color, buffer, "Button4: ", 0); y += font.getHeight() + 5;
+ font.printf(marginX, y, color, buffer, "Button5: ", 0); y += font.getHeight() + 5;
+ font.printf(marginX, y, color, buffer, "Button6: ", 0); y += font.getHeight() + 5;
+ font.printf(marginX, y, color, buffer, "Select: ", 0); y += font.getHeight() + 5;
+ font.printf(marginX, y, color, buffer, "Quit: ", 0); y += font.getHeight() + 5;
}
void draw(const Graphics::Bitmap & buffer){
const Font & font = Menu::menuFontParameter.current()->get();
Graphics::StretchedBitmap work(640, 480, buffer, Graphics::qualityFilterName(Configuration::getQualityFilter()));
work.start();
- context.renderBackground(buffer);
- font.printf(1, 1, Graphics::makeColor(255, 255, 255), buffer, "Joystick: %s", 0, joystick->getName().c_str());
+ context.renderBackground(work);
+
+ /* FIXME: scale the joystck name down to fit */
+ font.printf(marginX, 1, Graphics::makeColor(255, 255, 255), work, "Joystick %d: %s", 0, id, joystick->getName().c_str());
- drawButtons(font, buffer);
- context.renderForeground(buffer);
+ drawButtons(font, work, 1 + font.getHeight() + 5);
+ context.renderForeground(work);
work.finish();
-
- // buffer.BlitToScreen();
-
- /*
- Util::ReferenceCount<FontInfo> font = context.getFont();
- Font & font = font.get();
- */
}
};
+static void runJoystickMenu(int joystickId, const Util::ReferenceCount<Joystick> & joystick, const ::Menu::Context & context){
+ Util::NewReferenceCount<Menu::DefaultRenderer> renderer;
+ Menu::Menu menu(renderer.convert<Menu::Renderer>());
+
+ Gui::ContextBox & box = renderer->getBox();
+ box.setListType(ContextBox::Normal);
+
+ class JoystickButton: public MenuOption {
+ public:
+ JoystickButton(const Gui::ContextBox & parent, const Util::ReferenceCount<Joystick> & joystick, const string & name):
+ MenuOption(parent, NULL),
+ joystick(joystick){
+ setText(name);
+ setInfoText(name);
+ }
+
+ void logic(){
+ }
+
+ void run(const Menu::Context & context){
+ }
+
+ Util::ReferenceCount<Joystick> joystick;
+ };
+
+ menu.addOption(new JoystickButton(box, joystick, "Up"));
+ menu.addOption(new JoystickButton(box, joystick, "Down"));
+ menu.addOption(new JoystickButton(box, joystick, "Left"));
+ menu.addOption(new JoystickButton(box, joystick, "Right"));
+ menu.addOption(new JoystickButton(box, joystick, "Button1"));
+ menu.addOption(new JoystickButton(box, joystick, "Button2"));
+ menu.addOption(new JoystickButton(box, joystick, "Button3"));
+ menu.addOption(new JoystickButton(box, joystick, "Button4"));
+ menu.addOption(new JoystickButton(box, joystick, "Button5"));
+ menu.addOption(new JoystickButton(box, joystick, "Button6"));
+ menu.addOption(new JoystickButton(box, joystick, "Select"));
+ menu.addOption(new JoystickButton(box, joystick, "Quit"));
+
+ try {
+ menu.run(context);
+ } catch (const Exception::Return & ignore){
+ } catch (const Menu::MenuException & ex){
+ }
+}
+
void OptionJoystick::run(const Menu::Context & context){
class JoystickOption: public MenuOption {
public:
JoystickOption(const Gui::ContextBox & parent, int id, const Util::ReferenceCount<Joystick> & joystick):
MenuOption(parent, NULL),
- joystick(joystick){
+ joystick(joystick),
+ id(id){
ostringstream out;
out << "Joystick " << (id + 1);
setText(out.str());
setInfoText(joystick->getName());
}
const Util::ReferenceCount<Joystick> joystick;
+ const int id;
virtual void logic(){
}
virtual void run(const ::Menu::Context & context){
- JoystickLogicDraw mainLoop(joystick, context);
+ runJoystickMenu(id, joystick, context);
+ /*
+ JoystickLogicDraw mainLoop(id, joystick, context);
Util::standardLoop(mainLoop, mainLoop);
+ */
throw ::Menu::MenuException(__FILE__, __LINE__);
}
};
Util::NewReferenceCount<Menu::DefaultRenderer> renderer;
Menu::Menu menu(renderer.convert<Menu::Renderer>());
/*
Util::ReferenceCount<Menu::FontInfo> info(new Menu::RelativeFontInfo(Global::DEFAULT_FONT, 24, 24));
temp.setFont(info);
*/
Gui::ContextBox & box = renderer->getBox();
box.setListType(ContextBox::Normal);
map<int, Util::ReferenceCount<Joystick> > joysticks = InputManager::getJoysticks();
for (map<int, Util::ReferenceCount<Joystick> >::iterator it = joysticks.begin(); it != joysticks.end(); it++){
menu.addOption(new JoystickOption(box, it->first, it->second));
}
if (joysticks.size() == 0){
menu.addOption(new OptionDummy(box, "No joysticks found!"));
}
try {
menu.run(context);
} catch (const Exception::Return & ignore){
} catch (const Menu::MenuException & ex){
}
}
OptionJoystick::~OptionJoystick(){
}

File Metadata

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

Event Timeline