mirror of
https://github.com/aseprite/aseprite.git
synced 2025-04-15 11:42:30 +00:00
Move some base UI logic to handle the main display from modules/gui.cpp to she library.
This commit is contained in:
parent
f5ad8c86d3
commit
89cb9d098c
@ -28,13 +28,15 @@
|
||||
#include "console.h"
|
||||
#include "document_wrappers.h"
|
||||
#include "drop_files.h"
|
||||
#include "gfxmode.h"
|
||||
#include "ini_file.h"
|
||||
#include "modules/editors.h"
|
||||
#include "modules/gfx.h"
|
||||
#include "modules/gui.h"
|
||||
#include "modules/palettes.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "she/display.h"
|
||||
#include "she/surface.h"
|
||||
#include "she/system.h"
|
||||
#include "skin/button_icon_impl.h"
|
||||
#include "skin/skin_property.h"
|
||||
#include "skin/skin_theme.h"
|
||||
@ -60,9 +62,6 @@
|
||||
#include <winalleg.h>
|
||||
#endif
|
||||
|
||||
#define REFRESH_FULL_SCREEN 1
|
||||
#define SYSTEM_WINDOW_RESIZE 2
|
||||
|
||||
#define SPRITEDITOR_ACTION_COPYSELECTION "CopySelection"
|
||||
#define SPRITEDITOR_ACTION_SNAPTOGRID "SnapToGrid"
|
||||
#define SPRITEDITOR_ACTION_ANGLESNAP "AngleSnap"
|
||||
@ -88,8 +87,6 @@ static struct
|
||||
|
||||
static int try_depths[] = { 32, 24, 16, 15 };
|
||||
|
||||
static GfxMode lastWorkingGfxMode;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum ShortcutType { Shortcut_ExecuteCommand,
|
||||
@ -141,178 +138,71 @@ static Theme* ase_theme = NULL;
|
||||
|
||||
static std::vector<Shortcut*>* shortcuts = NULL;
|
||||
|
||||
static bool ji_screen_created = false;
|
||||
|
||||
static volatile int next_idle_flags = 0;
|
||||
|
||||
static volatile int restored_width = 0;
|
||||
static volatile int restored_height = 0;
|
||||
|
||||
// Default GUI screen configuration
|
||||
static bool double_buffering;
|
||||
static int screen_scaling;
|
||||
|
||||
static void reload_default_font();
|
||||
|
||||
// Load & save graphics configuration
|
||||
static void load_gui_config(int& w, int& h, int& bpp, bool& fullscreen, bool& maximized);
|
||||
static void load_gui_config(int& w, int& h, bool& maximized);
|
||||
static void save_gui_config();
|
||||
|
||||
static bool button_with_icon_msg_proc(Widget* widget, Message* msg);
|
||||
|
||||
static void on_palette_change_signal();
|
||||
|
||||
// Used by set_display_switch_callback(SWITCH_IN, ...).
|
||||
static void display_switch_in_callback()
|
||||
{
|
||||
next_idle_flags |= REFRESH_FULL_SCREEN;
|
||||
}
|
||||
|
||||
END_OF_STATIC_FUNCTION(display_switch_in_callback);
|
||||
|
||||
#ifdef ALLEGRO4_WITH_RESIZE_PATCH
|
||||
// Called when the window is resized
|
||||
static void resize_callback(RESIZE_DISPLAY_EVENT *ev)
|
||||
{
|
||||
if (ev->is_maximized) {
|
||||
restored_width = ev->old_w;
|
||||
restored_height = ev->old_h;
|
||||
}
|
||||
next_idle_flags |= SYSTEM_WINDOW_RESIZE;
|
||||
}
|
||||
#endif // ALLEGRO4_WITH_RESIZE_PATCH
|
||||
|
||||
// Initializes GUI.
|
||||
int init_module_gui()
|
||||
{
|
||||
int min_possible_dsk_res = 0;
|
||||
int c, w, h, bpp, autodetect;
|
||||
bool fullscreen;
|
||||
int c, w, h, min_possible_dsk_res = 0;
|
||||
bool maximized;
|
||||
|
||||
shortcuts = new std::vector<Shortcut*>;
|
||||
|
||||
// Install the mouse
|
||||
if (install_mouse() < 0)
|
||||
throw base::Exception("Error installing mouse handler");
|
||||
|
||||
// Install the keyboard
|
||||
if (install_keyboard() < 0)
|
||||
throw base::Exception("Error installing keyboard handler");
|
||||
|
||||
// Disable Ctrl+Shift+End in non-DOS
|
||||
#if !defined(ALLEGRO_DOS)
|
||||
three_finger_flag = false;
|
||||
#endif
|
||||
three_finger_flag = true; // TODO remove this line
|
||||
|
||||
// Set the graphics mode...
|
||||
load_gui_config(w, h, bpp, fullscreen, maximized);
|
||||
load_gui_config(w, h, maximized);
|
||||
|
||||
autodetect = fullscreen ? GFX_AUTODETECT_FULLSCREEN:
|
||||
GFX_AUTODETECT_WINDOWED;
|
||||
|
||||
// Default resolution
|
||||
if (!w || !h) {
|
||||
bool has_desktop = false;
|
||||
int dsk_w, dsk_h;
|
||||
|
||||
has_desktop = get_desktop_resolution(&dsk_w, &dsk_h) == 0;
|
||||
|
||||
#ifndef FULLSCREEN_PLATFORM
|
||||
// We must extract some space for the windows borders
|
||||
dsk_w -= 16;
|
||||
dsk_h -= 32;
|
||||
#endif
|
||||
|
||||
// Try to get desktop resolution
|
||||
if (has_desktop) {
|
||||
for (c=0; try_resolutions[c].width; ++c) {
|
||||
if (try_resolutions[c].width <= dsk_w &&
|
||||
try_resolutions[c].height <= dsk_h) {
|
||||
min_possible_dsk_res = c;
|
||||
fullscreen = false;
|
||||
w = try_resolutions[c].width;
|
||||
h = try_resolutions[c].height;
|
||||
screen_scaling = try_resolutions[c].scale;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Full screen
|
||||
else {
|
||||
fullscreen = true;
|
||||
w = 320;
|
||||
h = 200;
|
||||
screen_scaling = 1;
|
||||
}
|
||||
she::Display* display = NULL;
|
||||
try {
|
||||
display = she::Instance()->createDisplay(w, h, screen_scaling);
|
||||
}
|
||||
|
||||
// Default color depth
|
||||
if (!bpp) {
|
||||
bpp = desktop_color_depth();
|
||||
if (!bpp)
|
||||
bpp = 16;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (bpp == 8)
|
||||
throw base::Exception("You cannot use ASEPRITE in 8 bits per pixel");
|
||||
|
||||
// Original
|
||||
set_color_depth(bpp);
|
||||
if (set_gfx_mode(autodetect, w, h, 0, 0) == 0)
|
||||
break;
|
||||
|
||||
catch (const she::DisplayCreationException&) {
|
||||
for (c=min_possible_dsk_res; try_resolutions[c].width; ++c) {
|
||||
if (set_gfx_mode(autodetect,
|
||||
try_resolutions[c].width,
|
||||
try_resolutions[c].height, 0, 0) == 0) {
|
||||
try {
|
||||
display = she::Instance()->createDisplay(try_resolutions[c].width,
|
||||
try_resolutions[c].height,
|
||||
try_resolutions[c].scale);
|
||||
|
||||
screen_scaling = try_resolutions[c].scale;
|
||||
goto gfx_done;
|
||||
}
|
||||
}
|
||||
|
||||
if (bpp == 15)
|
||||
throw base::Exception("Error setting graphics mode\n%s\n"
|
||||
"Try \"ase -res WIDTHxHEIGHTxBPP\"\n", allegro_error);
|
||||
|
||||
for (c=0; try_depths[c]; ++c) {
|
||||
if (bpp == try_depths[c]) {
|
||||
bpp = try_depths[c+1];
|
||||
break;
|
||||
}
|
||||
catch (const she::DisplayCreationException&) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gfx_done:;
|
||||
if (!display) {
|
||||
allegro_message("Unable to create a user-interface display.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Create the default-manager
|
||||
manager = new CustomizedGuiManager();
|
||||
manager->setDisplay(display);
|
||||
|
||||
// Setup the GUI theme for all widgets
|
||||
CurrentTheme::set(ase_theme = new SkinTheme());
|
||||
|
||||
#ifdef ALLEGRO4_WITH_RESIZE_PATCH
|
||||
// Setup the handler for window-resize events
|
||||
set_resize_callback(resize_callback);
|
||||
#endif
|
||||
|
||||
#ifdef ALLEGRO_WINDOWS
|
||||
if (maximized) {
|
||||
ShowWindow(win_get_window(), SW_MAXIMIZE);
|
||||
}
|
||||
#endif
|
||||
if (maximized)
|
||||
display->maximize();
|
||||
|
||||
// Configure ji_screen
|
||||
gui_setup_screen(true);
|
||||
|
||||
// Add a hook to display-switch so when the user returns to the
|
||||
// screen it's completelly refreshed/redrawn.
|
||||
LOCK_VARIABLE(next_idle_flags);
|
||||
LOCK_FUNCTION(display_switch_in_callback);
|
||||
set_display_switch_callback(SWITCH_IN, display_switch_in_callback);
|
||||
|
||||
// Set graphics options for next time
|
||||
save_gui_config();
|
||||
|
||||
@ -334,15 +224,6 @@ void exit_module_gui()
|
||||
delete shortcuts;
|
||||
shortcuts = NULL;
|
||||
|
||||
if (double_buffering) {
|
||||
BITMAP *old_bmp = ji_screen;
|
||||
ji_set_screen(screen, SCREEN_W, SCREEN_H);
|
||||
|
||||
if (ji_screen_created)
|
||||
destroy_bitmap(old_bmp);
|
||||
ji_screen_created = false;
|
||||
}
|
||||
|
||||
delete manager;
|
||||
|
||||
// Now we can destroy theme
|
||||
@ -353,46 +234,24 @@ void exit_module_gui()
|
||||
remove_mouse();
|
||||
}
|
||||
|
||||
static void load_gui_config(int& w, int& h, int& bpp, bool& fullscreen, bool& maximized)
|
||||
static void load_gui_config(int& w, int& h, bool& maximized)
|
||||
{
|
||||
w = get_config_int("GfxMode", "Width", 0);
|
||||
h = get_config_int("GfxMode", "Height", 0);
|
||||
bpp = get_config_int("GfxMode", "Depth", 0);
|
||||
fullscreen = get_config_bool("GfxMode", "FullScreen",
|
||||
#ifdef FULLSCREEN_PLATFORM
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
);
|
||||
screen_scaling = get_config_int("GfxMode", "ScreenScale", 2);
|
||||
screen_scaling = MID(1, screen_scaling, 4);
|
||||
maximized = get_config_bool("GfxMode", "Maximized", false);
|
||||
|
||||
// Avoid 8 bpp
|
||||
if (bpp == 8)
|
||||
bpp = 32;
|
||||
}
|
||||
|
||||
static void save_gui_config()
|
||||
{
|
||||
bool is_maximized = false;
|
||||
|
||||
#ifdef WIN32
|
||||
is_maximized = (GetWindowLong(win_get_window(), GWL_STYLE) & WS_MAXIMIZE ? true: false);
|
||||
#endif
|
||||
|
||||
set_config_bool("GfxMode", "Maximized", is_maximized);
|
||||
|
||||
if (screen) {
|
||||
set_config_int("GfxMode", "Width", is_maximized ? restored_width: SCREEN_W);
|
||||
set_config_int("GfxMode", "Height", is_maximized ? restored_height: SCREEN_H);
|
||||
she::Display* display = Manager::getDefault()->getDisplay();
|
||||
if (display) {
|
||||
set_config_bool("GfxMode", "Maximized", display->isMaximized());
|
||||
set_config_int("GfxMode", "Width", display->originalWidth());
|
||||
set_config_int("GfxMode", "Height", display->originalHeight());
|
||||
set_config_int("GfxMode", "Depth", bitmap_color_depth(screen));
|
||||
}
|
||||
|
||||
if (gfx_driver)
|
||||
set_config_bool("GfxMode", "FullScreen", gfx_driver->windowed ? false: true);
|
||||
|
||||
set_config_int("GfxMode", "ScreenScale", screen_scaling);
|
||||
}
|
||||
|
||||
@ -443,70 +302,14 @@ void gui_run()
|
||||
|
||||
void gui_feedback()
|
||||
{
|
||||
#ifdef ALLEGRO4_WITH_RESIZE_PATCH
|
||||
if (next_idle_flags & SYSTEM_WINDOW_RESIZE) {
|
||||
next_idle_flags ^= SYSTEM_WINDOW_RESIZE;
|
||||
|
||||
if (acknowledge_resize() < 0)
|
||||
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 320, 240, 0, 0);
|
||||
jmouse_draw_cursor();
|
||||
|
||||
if (!Manager::getDefault()->getDisplay()->flip()) {
|
||||
// In case that the display was resized.
|
||||
gui_setup_screen(false);
|
||||
App::instance()->getMainWindow()->remap_window();
|
||||
Manager::getDefault()->invalidate();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (next_idle_flags & REFRESH_FULL_SCREEN) {
|
||||
next_idle_flags ^= REFRESH_FULL_SCREEN;
|
||||
|
||||
try {
|
||||
const ActiveDocumentReader document(UIContext::instance());
|
||||
update_screen_for_document(document);
|
||||
}
|
||||
catch (...) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
gui_flip_screen();
|
||||
}
|
||||
|
||||
void gui_flip_screen()
|
||||
{
|
||||
// Double buffering?
|
||||
if (double_buffering && ji_screen && screen) {
|
||||
jmouse_draw_cursor();
|
||||
|
||||
if (ji_dirty_region) {
|
||||
ji_flip_dirty_region();
|
||||
}
|
||||
else {
|
||||
if (JI_SCREEN_W == SCREEN_W && JI_SCREEN_H == SCREEN_H) {
|
||||
blit(ji_screen, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
|
||||
}
|
||||
else {
|
||||
stretch_blit(ji_screen, screen,
|
||||
0, 0, JI_SCREEN_W, JI_SCREEN_H,
|
||||
0, 0, SCREEN_W, SCREEN_H);
|
||||
}
|
||||
}
|
||||
}
|
||||
// This is a strange Allegro bug where the "screen" pointer is lost,
|
||||
// so we have to reconstruct it changing the gfx mode again
|
||||
else if (screen == NULL) {
|
||||
PRINTF("Gfx mode lost, trying to restore gfx mode...\n");
|
||||
|
||||
if (!lastWorkingGfxMode.setGfxMode()) {
|
||||
PRINTF("Fatal error\n");
|
||||
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
|
||||
allegro_message("FATAL ERROR: Unable to restore the old graphics mode!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
PRINTF("Successfully restored\n");
|
||||
}
|
||||
else
|
||||
lastWorkingGfxMode.updateWithCurrentMode();
|
||||
}
|
||||
|
||||
// Sets the ji_screen variable. This routine should be called
|
||||
@ -516,27 +319,8 @@ void gui_setup_screen(bool reload_font)
|
||||
bool regen = false;
|
||||
bool reinit = false;
|
||||
|
||||
// Double buffering is required when screen scaling is used
|
||||
double_buffering = (screen_scaling > 1);
|
||||
|
||||
// Is double buffering active?
|
||||
if (double_buffering) {
|
||||
BITMAP *old_bmp = ji_screen;
|
||||
int new_w = SCREEN_W / screen_scaling;
|
||||
int new_h = SCREEN_H / screen_scaling;
|
||||
BITMAP *new_bmp = create_bitmap(new_w, new_h);
|
||||
|
||||
ji_set_screen(new_bmp, new_w, new_h);
|
||||
|
||||
if (ji_screen_created)
|
||||
destroy_bitmap(old_bmp);
|
||||
|
||||
ji_screen_created = true;
|
||||
}
|
||||
else {
|
||||
ji_set_screen(screen, SCREEN_W, SCREEN_H);
|
||||
ji_screen_created = false;
|
||||
}
|
||||
Manager::getDefault()->getDisplay()->setScale(screen_scaling);
|
||||
ui::SetDisplay(Manager::getDefault()->getDisplay());
|
||||
|
||||
// Update guiscale factor
|
||||
int old_guiscale = jguiscale();
|
||||
|
@ -51,7 +51,6 @@ void update_screen_for_document(const Document* document);
|
||||
|
||||
void gui_run();
|
||||
void gui_feedback();
|
||||
void gui_flip_screen();
|
||||
void gui_setup_screen(bool reload_font);
|
||||
|
||||
void load_window_pos(ui::Widget* window, const char *section);
|
||||
|
20
src/she/capabilities.h
Normal file
20
src/she/capabilities.h
Normal file
@ -0,0 +1,20 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012 David Capello
|
||||
//
|
||||
// This source file is ditributed under a BSD-like license, please
|
||||
// read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_CAPABILITIES_H_INCLUDED
|
||||
#define SHE_CAPABILITIES_H_INCLUDED
|
||||
|
||||
namespace she {
|
||||
|
||||
enum Capabilities {
|
||||
kMultipleDisplaysCapability = 1,
|
||||
kCanResizeDisplayCapability = 2,
|
||||
kDisplayScaleCapability = 4
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
50
src/she/display.h
Normal file
50
src/she/display.h
Normal file
@ -0,0 +1,50 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012 David Capello
|
||||
//
|
||||
// This source file is ditributed under a BSD-like license, please
|
||||
// read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_DISPLAY_H_INCLUDED
|
||||
#define SHE_DISPLAY_H_INCLUDED
|
||||
|
||||
namespace she {
|
||||
|
||||
class Surface;
|
||||
|
||||
// A display or window to show graphics.
|
||||
class Display {
|
||||
public:
|
||||
virtual ~Display() { }
|
||||
virtual void dispose() = 0;
|
||||
|
||||
// Returns the real and current display's size (without scale applied).
|
||||
virtual int width() const = 0;
|
||||
virtual int height() const = 0;
|
||||
|
||||
// Returns the display when it was not maximized.
|
||||
virtual int originalWidth() const = 0;
|
||||
virtual int originalHeight() const = 0;
|
||||
|
||||
// Changes the scale (each pixel will be SCALExSCALE in the screen).
|
||||
// The available surface size will be (Display::width() / scale,
|
||||
// Display::height() / scale)
|
||||
virtual void setScale(int scale) = 0;
|
||||
|
||||
// Returns the main surface to draw into this display.
|
||||
virtual Surface* getSurface() = 0;
|
||||
|
||||
// Flips all graphics in the surface to the real display. Returns
|
||||
// false if the flip couldn't be done because the display was
|
||||
// resized.
|
||||
virtual bool flip() = 0;
|
||||
|
||||
virtual void maximize() = 0;
|
||||
virtual bool isMaximized() const = 0;
|
||||
|
||||
// Returns the HWND on Windows.
|
||||
virtual void* nativeHandle() = 0;
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
22
src/she/locked_surface.h
Normal file
22
src/she/locked_surface.h
Normal file
@ -0,0 +1,22 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012 David Capello
|
||||
//
|
||||
// This source file is ditributed under a BSD-like license, please
|
||||
// read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_LOCKED_SURFACE_H_INCLUDED
|
||||
#define SHE_LOCKED_SURFACE_H_INCLUDED
|
||||
|
||||
namespace she {
|
||||
|
||||
class LockedSurface {
|
||||
public:
|
||||
virtual ~LockedSurface() { }
|
||||
virtual void unlock() = 0;
|
||||
virtual void clear() = 0;
|
||||
virtual void blitTo(LockedSurface* dest, int x, int y) const = 0;
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
30
src/she/scoped_handle.h
Normal file
30
src/she/scoped_handle.h
Normal file
@ -0,0 +1,30 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012 David Capello
|
||||
//
|
||||
// This source file is ditributed under a BSD-like license, please
|
||||
// read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_SCOPED_HANDLE_H_INCLUDED
|
||||
#define SHE_SCOPED_HANDLE_H_INCLUDED
|
||||
|
||||
namespace she {
|
||||
|
||||
template<typename T>
|
||||
class ScopedHandle {
|
||||
public:
|
||||
ScopedHandle(T* handle) : m_handle(handle) { }
|
||||
~ScopedHandle() { m_handle->dispose(); }
|
||||
|
||||
T* operator->() { return m_handle; }
|
||||
operator T*() { return m_handle; }
|
||||
private:
|
||||
T* m_handle;
|
||||
|
||||
// Cannot copy
|
||||
ScopedHandle(const ScopedHandle&);
|
||||
ScopedHandle& operator=(const ScopedHandle&);
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
28
src/she/scoped_surface_lock.h
Normal file
28
src/she/scoped_surface_lock.h
Normal file
@ -0,0 +1,28 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012 David Capello
|
||||
//
|
||||
// This source file is ditributed under a BSD-like license, please
|
||||
// read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_SCOPED_SURFACE_LOCK_H_INCLUDED
|
||||
#define SHE_SCOPED_SURFACE_LOCK_H_INCLUDED
|
||||
|
||||
#include "she/surface.h"
|
||||
#include "she/locked_surface.h"
|
||||
|
||||
namespace she {
|
||||
|
||||
class ScopedSurfaceLock {
|
||||
public:
|
||||
ScopedSurfaceLock(Surface* surface) : m_lock(surface->lock()) { }
|
||||
~ScopedSurfaceLock() { m_lock->unlock(); }
|
||||
|
||||
LockedSurface* operator->() { return m_lock; }
|
||||
operator LockedSurface*() { return m_lock; }
|
||||
private:
|
||||
LockedSurface* m_lock;
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
@ -7,29 +7,11 @@
|
||||
#ifndef SHE_H_INCLUDED
|
||||
#define SHE_H_INCLUDED
|
||||
|
||||
namespace she {
|
||||
|
||||
class System {
|
||||
public:
|
||||
virtual ~System() { }
|
||||
virtual void dispose() = 0;
|
||||
};
|
||||
|
||||
System* CreateSystem();
|
||||
|
||||
template<typename T>
|
||||
class ScopedHandle {
|
||||
public:
|
||||
ScopedHandle(T* handle) : m_handle(handle) { }
|
||||
~ScopedHandle() { m_handle->dispose(); }
|
||||
private:
|
||||
T* m_handle;
|
||||
|
||||
// Cannot copy
|
||||
ScopedHandle(const ScopedHandle&);
|
||||
ScopedHandle& operator=(const ScopedHandle&);
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
#include "she/display.h"
|
||||
#include "she/locked_surface.h"
|
||||
#include "she/scoped_handle.h"
|
||||
#include "she/scoped_surface_lock.h"
|
||||
#include "she/surface.h"
|
||||
#include "she/system.h"
|
||||
|
||||
#endif
|
||||
|
@ -11,12 +11,246 @@
|
||||
#include "she.h"
|
||||
|
||||
#include <allegro.h>
|
||||
#ifdef ALLEGRO_WINDOWS
|
||||
#include <winalleg.h>
|
||||
#endif
|
||||
#include "loadpng.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#define DISPLAY_FLAG_FULL_REFRESH 1
|
||||
#define DISPLAY_FLAG_WINDOW_RESIZE 2
|
||||
|
||||
static volatile int display_flags = 0;
|
||||
static volatile int original_width = 0;
|
||||
static volatile int original_height = 0;
|
||||
|
||||
// Used by set_display_switch_callback(SWITCH_IN, ...).
|
||||
static void display_switch_in_callback()
|
||||
{
|
||||
display_flags |= DISPLAY_FLAG_FULL_REFRESH;
|
||||
}
|
||||
|
||||
END_OF_STATIC_FUNCTION(display_switch_in_callback);
|
||||
|
||||
#ifdef ALLEGRO4_WITH_RESIZE_PATCH
|
||||
// Called when the window is resized
|
||||
static void resize_callback(RESIZE_DISPLAY_EVENT* ev)
|
||||
{
|
||||
if (ev->is_maximized) {
|
||||
original_width = ev->old_w;
|
||||
original_height = ev->old_h;
|
||||
}
|
||||
display_flags |= DISPLAY_FLAG_WINDOW_RESIZE;
|
||||
}
|
||||
#endif // ALLEGRO4_WITH_RESIZE_PATCH
|
||||
|
||||
namespace she {
|
||||
|
||||
class Alleg4Surface : public Surface
|
||||
, public LockedSurface {
|
||||
public:
|
||||
Alleg4Surface(BITMAP* bmp)
|
||||
: m_bmp(bmp)
|
||||
, m_destroy(false)
|
||||
{
|
||||
}
|
||||
|
||||
Alleg4Surface(int width, int height)
|
||||
: m_bmp(create_bitmap(width, height))
|
||||
, m_destroy(true)
|
||||
{
|
||||
}
|
||||
|
||||
~Alleg4Surface() {
|
||||
if (m_destroy)
|
||||
destroy_bitmap(m_bmp);
|
||||
}
|
||||
|
||||
// Surface implementation
|
||||
|
||||
void dispose() {
|
||||
delete this;
|
||||
}
|
||||
|
||||
int width() const {
|
||||
return m_bmp->w;
|
||||
}
|
||||
|
||||
int height() const {
|
||||
return m_bmp->h;
|
||||
}
|
||||
|
||||
LockedSurface* lock() {
|
||||
acquire_bitmap(m_bmp);
|
||||
return this;
|
||||
}
|
||||
|
||||
void* nativeHandle() {
|
||||
return reinterpret_cast<void*>(m_bmp);
|
||||
}
|
||||
|
||||
// LockedSurface implementation
|
||||
|
||||
void unlock() {
|
||||
release_bitmap(m_bmp);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
clear_to_color(m_bmp, 0);
|
||||
}
|
||||
|
||||
void blitTo(LockedSurface* dest, int x, int y) const {
|
||||
ASSERT(m_bmp);
|
||||
ASSERT(dest);
|
||||
ASSERT(static_cast<Alleg4Surface*>(dest)->m_bmp);
|
||||
|
||||
blit(m_bmp,
|
||||
static_cast<Alleg4Surface*>(dest)->m_bmp,
|
||||
0, 0,
|
||||
x, y,
|
||||
m_bmp->w, m_bmp->h);
|
||||
}
|
||||
|
||||
private:
|
||||
BITMAP* m_bmp;
|
||||
bool m_destroy;
|
||||
};
|
||||
|
||||
class Alleg4Display : public Display {
|
||||
public:
|
||||
Alleg4Display(int width, int height, int scale)
|
||||
: m_surface(NULL)
|
||||
, m_scale(0) {
|
||||
if (install_mouse() < 0) throw DisplayCreationException(allegro_error);
|
||||
if (install_keyboard() < 0) throw DisplayCreationException(allegro_error);
|
||||
|
||||
#ifdef FULLSCREEN_PLATFORM
|
||||
set_color_depth(16); // TODO Try all color depths for fullscreen platforms
|
||||
#else
|
||||
set_color_depth(desktop_color_depth());
|
||||
#endif
|
||||
|
||||
if (set_gfx_mode(
|
||||
#ifdef FULLSCREEN_PLATFORM
|
||||
GFX_AUTODETECT_FULLSCREEN,
|
||||
#else
|
||||
GFX_AUTODETECT_WINDOWED,
|
||||
#endif
|
||||
width, height, 0, 0) < 0)
|
||||
throw DisplayCreationException(allegro_error);
|
||||
|
||||
setScale(scale);
|
||||
|
||||
// Add a hook to display-switch so when the user returns to the
|
||||
// screen it's completelly refreshed/redrawn.
|
||||
LOCK_VARIABLE(display_flags);
|
||||
LOCK_FUNCTION(display_switch_in_callback);
|
||||
set_display_switch_callback(SWITCH_IN, display_switch_in_callback);
|
||||
|
||||
#ifdef ALLEGRO4_WITH_RESIZE_PATCH
|
||||
// Setup the handler for window-resize events
|
||||
set_resize_callback(resize_callback);
|
||||
#endif
|
||||
}
|
||||
|
||||
~Alleg4Display() {
|
||||
m_surface->dispose();
|
||||
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
delete this;
|
||||
}
|
||||
|
||||
int width() const {
|
||||
return SCREEN_W;
|
||||
}
|
||||
|
||||
int height() const {
|
||||
return SCREEN_H;
|
||||
}
|
||||
|
||||
int originalWidth() const {
|
||||
return original_width > 0 ? original_width: width();
|
||||
}
|
||||
|
||||
int originalHeight() const {
|
||||
return original_height > 0 ? original_height: height();
|
||||
}
|
||||
|
||||
void setScale(int scale) {
|
||||
ASSERT(scale >= 1);
|
||||
|
||||
if (m_scale == scale)
|
||||
return;
|
||||
|
||||
m_scale = scale;
|
||||
Surface* newSurface = new Alleg4Surface(SCREEN_W/m_scale,
|
||||
SCREEN_H/m_scale);
|
||||
if (m_surface)
|
||||
m_surface->dispose();
|
||||
m_surface = newSurface;
|
||||
}
|
||||
|
||||
Surface* getSurface() {
|
||||
return m_surface;
|
||||
}
|
||||
|
||||
bool flip() {
|
||||
#ifdef ALLEGRO4_WITH_RESIZE_PATCH
|
||||
if (display_flags & DISPLAY_FLAG_WINDOW_RESIZE) {
|
||||
display_flags ^= DISPLAY_FLAG_WINDOW_RESIZE;
|
||||
|
||||
acknowledge_resize();
|
||||
|
||||
int scale = m_scale;
|
||||
m_scale = 0;
|
||||
setScale(scale);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
BITMAP* bmp = reinterpret_cast<BITMAP*>(m_surface->nativeHandle());
|
||||
if (m_scale == 1) {
|
||||
blit(bmp, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
|
||||
}
|
||||
else {
|
||||
stretch_blit(bmp, screen,
|
||||
0, 0, bmp->w, bmp->h,
|
||||
0, 0, SCREEN_W, SCREEN_H);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void maximize() {
|
||||
#ifdef WIN32
|
||||
::ShowWindow(win_get_window(), SW_MAXIMIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool isMaximized() const {
|
||||
#ifdef WIN32
|
||||
return (::GetWindowLong(win_get_window(), GWL_STYLE) & WS_MAXIMIZE ? true: false);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void* nativeHandle() {
|
||||
#ifdef WIN32
|
||||
return reinterpret_cast<void*>(win_get_window());
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
Surface* m_surface;
|
||||
int m_scale;
|
||||
};
|
||||
|
||||
class Alleg4System : public System {
|
||||
public:
|
||||
Alleg4System() {
|
||||
@ -37,12 +271,31 @@ public:
|
||||
delete this;
|
||||
}
|
||||
|
||||
Capabilities capabilities() const {
|
||||
return kCanResizeDisplayCapability;
|
||||
}
|
||||
|
||||
Display* createDisplay(int width, int height, int scale) {
|
||||
return new Alleg4Display(width, height, scale);
|
||||
}
|
||||
|
||||
Surface* createSurface(int width, int height) {
|
||||
return new Alleg4Surface(width, height);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static System* g_instance;
|
||||
|
||||
System* CreateSystem() {
|
||||
return new Alleg4System();
|
||||
return g_instance = new Alleg4System();
|
||||
}
|
||||
|
||||
|
||||
System* Instance()
|
||||
{
|
||||
return g_instance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef main
|
||||
|
26
src/she/surface.h
Normal file
26
src/she/surface.h
Normal file
@ -0,0 +1,26 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012 David Capello
|
||||
//
|
||||
// This source file is ditributed under a BSD-like license, please
|
||||
// read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_SURFACE_H_INCLUDED
|
||||
#define SHE_SURFACE_H_INCLUDED
|
||||
|
||||
namespace she {
|
||||
|
||||
class LockedSurface;
|
||||
|
||||
class Surface {
|
||||
public:
|
||||
virtual ~Surface() { }
|
||||
virtual void dispose() = 0;
|
||||
virtual int width() const = 0;
|
||||
virtual int height() const = 0;
|
||||
virtual LockedSurface* lock() = 0;
|
||||
virtual void* nativeHandle() = 0;
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
38
src/she/system.h
Normal file
38
src/she/system.h
Normal file
@ -0,0 +1,38 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012 David Capello
|
||||
//
|
||||
// This source file is ditributed under a BSD-like license, please
|
||||
// read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_SYSTEM_H_INCLUDED
|
||||
#define SHE_SYSTEM_H_INCLUDED
|
||||
|
||||
#include "she/capabilities.h"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace she {
|
||||
|
||||
class Surface;
|
||||
class Display;
|
||||
|
||||
class DisplayCreationException : std::runtime_error {
|
||||
public:
|
||||
DisplayCreationException(const char* msg) throw()
|
||||
: std::runtime_error(msg) { }
|
||||
};
|
||||
|
||||
class System {
|
||||
public:
|
||||
virtual ~System() { }
|
||||
virtual void dispose() = 0;
|
||||
virtual Capabilities capabilities() const = 0;
|
||||
virtual Display* createDisplay(int width, int height, int scale) = 0;
|
||||
virtual Surface* createSurface(int width, int height) = 0;
|
||||
};
|
||||
|
||||
System* CreateSystem();
|
||||
System* Instance();
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
@ -203,12 +203,6 @@ void ji_move_region(JRegion region, int dx, int dy)
|
||||
int c, nrects = JI_REGION_NUM_RECTS(region);
|
||||
JRect rc;
|
||||
|
||||
if (ji_dirty_region) {
|
||||
jregion_translate(region, dx, dy);
|
||||
ji_add_dirty_region(region);
|
||||
jregion_translate(region, -dx, -dy);
|
||||
}
|
||||
|
||||
// Blit directly screen to screen.
|
||||
if (is_linear_bitmap(ji_screen) && nrects == 1) {
|
||||
rc = JI_REGION_RECTS(region);
|
||||
|
@ -112,9 +112,6 @@ Manager::Manager()
|
||||
: Widget(JI_MANAGER)
|
||||
{
|
||||
if (!m_defaultManager) {
|
||||
if (!ji_screen)
|
||||
ji_set_screen(screen, SCREEN_W, SCREEN_H);
|
||||
|
||||
// Hook the window close message
|
||||
want_close_stage = STAGE_NORMAL;
|
||||
set_close_button_callback(allegro_window_close_hook);
|
||||
@ -1102,10 +1099,6 @@ void Manager::pumpQueue()
|
||||
if (msg->type == JM_DRAW) {
|
||||
set_clip_rect(ji_screen, 0, 0, JI_SCREEN_W-1, JI_SCREEN_H-1);
|
||||
|
||||
/* dirty rectangles */
|
||||
if (ji_dirty_region)
|
||||
ji_add_dirty_rect(&msg->draw.rect);
|
||||
|
||||
release_bitmap(ji_screen);
|
||||
jmouse_show();
|
||||
}
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include "base/compiler_specific.h"
|
||||
#include "ui/widget.h"
|
||||
|
||||
namespace she { class Display; }
|
||||
|
||||
namespace ui {
|
||||
|
||||
class LayoutIO;
|
||||
@ -24,6 +26,9 @@ namespace ui {
|
||||
Manager();
|
||||
~Manager();
|
||||
|
||||
she::Display* getDisplay() { return m_display; }
|
||||
void setDisplay(she::Display* display) { m_display = display; }
|
||||
|
||||
void run();
|
||||
|
||||
// Returns true if there are messages in the queue to be
|
||||
@ -85,6 +90,7 @@ namespace ui {
|
||||
static Manager* m_defaultManager;
|
||||
|
||||
WidgetsList m_garbage;
|
||||
she::Display* m_display;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
@ -24,8 +24,8 @@ PaintEvent::~PaintEvent()
|
||||
|
||||
Graphics* PaintEvent::getGraphics()
|
||||
{
|
||||
// If someone requests the graphics pointer, it means that this
|
||||
// "someone" will paint something.
|
||||
// If someone requested the graphics pointer, it means that this
|
||||
// "someone" has painted the widget.
|
||||
m_painted = true;
|
||||
return m_graphics;
|
||||
}
|
||||
|
@ -6,6 +6,17 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ui/system.h"
|
||||
|
||||
#include "she/display.h"
|
||||
#include "she/surface.h"
|
||||
#include "ui/intern.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/rect.h"
|
||||
#include "ui/region.h"
|
||||
#include "ui/theme.h"
|
||||
#include "ui/widget.h"
|
||||
|
||||
#include <allegro.h>
|
||||
#if defined(ALLEGRO_WINDOWS)
|
||||
#include <winalleg.h>
|
||||
@ -13,19 +24,11 @@
|
||||
#include <xalleg.h>
|
||||
#endif
|
||||
|
||||
#include "ui/intern.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/rect.h"
|
||||
#include "ui/region.h"
|
||||
#include "ui/system.h"
|
||||
#include "ui/theme.h"
|
||||
#include "ui/widget.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
/* Global output bitmap. */
|
||||
|
||||
BITMAP *ji_screen = NULL;
|
||||
BITMAP* ji_screen = NULL;
|
||||
JRegion ji_dirty_region = NULL;
|
||||
int ji_screen_w = 0;
|
||||
int ji_screen_h = 0;
|
||||
@ -83,9 +86,6 @@ static void set_cursor(BITMAP *bmp, int x, int y)
|
||||
|
||||
int _ji_system_init()
|
||||
{
|
||||
/* Update screen pointer. */
|
||||
ji_set_screen(screen, SCREEN_W, SCREEN_H);
|
||||
|
||||
/* Install timer related stuff. */
|
||||
LOCK_VARIABLE(ji_clock);
|
||||
LOCK_VARIABLE(m_b);
|
||||
@ -105,103 +105,38 @@ int _ji_system_init()
|
||||
|
||||
void _ji_system_exit()
|
||||
{
|
||||
ji_set_screen(NULL, 0, 0);
|
||||
SetDisplay(NULL);
|
||||
|
||||
remove_int(clock_inc);
|
||||
}
|
||||
|
||||
void ji_set_screen(BITMAP *bmp, int width, int height)
|
||||
void SetDisplay(she::Display* display)
|
||||
{
|
||||
int cursor = jmouse_get_cursor(); /* get mouse cursor */
|
||||
int cursor = jmouse_get_cursor();
|
||||
|
||||
jmouse_set_cursor(JI_CURSOR_NULL);
|
||||
ji_screen = bmp;
|
||||
ji_screen_w = width;
|
||||
ji_screen_h = height;
|
||||
ji_screen = (display ? reinterpret_cast<BITMAP*>(display->getSurface()->nativeHandle()): NULL);
|
||||
ji_screen_w = (ji_screen ? ji_screen->w: 0);
|
||||
ji_screen_h = (ji_screen ? ji_screen->h: 0);
|
||||
|
||||
if (ji_screen != NULL) {
|
||||
Manager* manager = Manager::getDefault();
|
||||
if (manager) {
|
||||
manager->setDisplay(display);
|
||||
|
||||
/* update default-manager size */
|
||||
if (manager && (jrect_w(manager->rc) != JI_SCREEN_W ||
|
||||
jrect_h(manager->rc) != JI_SCREEN_H)) {
|
||||
JRect rect = jrect_new(0, 0, JI_SCREEN_W, JI_SCREEN_H);
|
||||
jwidget_set_rect(manager, rect);
|
||||
jrect_free(rect);
|
||||
|
||||
if (ji_dirty_region)
|
||||
jregion_reset(ji_dirty_region, manager->rc);
|
||||
// Update default-manager size
|
||||
if ((jrect_w(manager->rc) != JI_SCREEN_W ||
|
||||
jrect_h(manager->rc) != JI_SCREEN_H)) {
|
||||
JRect rect = jrect_new(0, 0, JI_SCREEN_W, JI_SCREEN_H);
|
||||
jwidget_set_rect(manager, rect);
|
||||
jrect_free(rect);
|
||||
}
|
||||
}
|
||||
|
||||
jmouse_set_cursor(cursor); /* restore mouse cursor */
|
||||
}
|
||||
}
|
||||
|
||||
void ji_add_dirty_rect(JRect rect)
|
||||
{
|
||||
JRegion reg1;
|
||||
|
||||
ASSERT(ji_dirty_region != NULL);
|
||||
|
||||
reg1 = jregion_new(rect, 1);
|
||||
jregion_union(ji_dirty_region, ji_dirty_region, reg1);
|
||||
jregion_free(reg1);
|
||||
}
|
||||
|
||||
void ji_add_dirty_region(JRegion region)
|
||||
{
|
||||
ASSERT(ji_dirty_region != NULL);
|
||||
|
||||
jregion_union(ji_dirty_region, ji_dirty_region, region);
|
||||
}
|
||||
|
||||
void ji_flip_dirty_region()
|
||||
{
|
||||
int c, nrects;
|
||||
JRect rc;
|
||||
|
||||
ASSERT(ji_dirty_region != NULL);
|
||||
|
||||
nrects = JI_REGION_NUM_RECTS(ji_dirty_region);
|
||||
|
||||
if (nrects == 1) {
|
||||
rc = JI_REGION_RECTS(ji_dirty_region);
|
||||
ji_flip_rect(rc);
|
||||
}
|
||||
else if (nrects > 1) {
|
||||
for (c=0, rc=JI_REGION_RECTS(ji_dirty_region);
|
||||
c<nrects;
|
||||
c++, rc++)
|
||||
ji_flip_rect(rc);
|
||||
}
|
||||
|
||||
jregion_empty(ji_dirty_region);
|
||||
}
|
||||
|
||||
void ji_flip_rect(JRect rect)
|
||||
{
|
||||
ASSERT(ji_screen != screen);
|
||||
|
||||
if (JI_SCREEN_W == SCREEN_W && JI_SCREEN_H == SCREEN_H) {
|
||||
blit(ji_screen, screen,
|
||||
rect->x1, rect->y1,
|
||||
rect->x1, rect->y1,
|
||||
jrect_w(rect),
|
||||
jrect_h(rect));
|
||||
}
|
||||
else {
|
||||
stretch_blit(ji_screen, screen,
|
||||
rect->x1,
|
||||
rect->y1,
|
||||
jrect_w(rect),
|
||||
jrect_h(rect),
|
||||
rect->x1 * SCREEN_W / JI_SCREEN_W,
|
||||
rect->y1 * SCREEN_H / JI_SCREEN_H,
|
||||
jrect_w(rect) * SCREEN_W / JI_SCREEN_W,
|
||||
jrect_h(rect) * SCREEN_H / JI_SCREEN_H);
|
||||
}
|
||||
}
|
||||
|
||||
int jmouse_get_cursor()
|
||||
{
|
||||
return m_cursor;
|
||||
@ -257,10 +192,6 @@ void jmouse_draw_cursor()
|
||||
ji_get_default_manager()->invalidateRect(rect);
|
||||
/* rectfill(ji_screen, rect->x1, rect->y1, rect->x2-1, rect->y2-1, makecol(0, 0, 255)); */
|
||||
draw_sprite(ji_screen, sprite_cursor, x, y);
|
||||
|
||||
if (ji_dirty_region)
|
||||
ji_add_dirty_rect(rect);
|
||||
|
||||
jrect_free(rect);
|
||||
}
|
||||
#endif
|
||||
@ -273,14 +204,6 @@ void jmouse_draw_cursor()
|
||||
capture_covered_area();
|
||||
|
||||
draw_sprite(ji_screen, sprite_cursor, x, y);
|
||||
|
||||
if (ji_dirty_region) {
|
||||
JRect rect = jrect_new(x, y,
|
||||
x+sprite_cursor->w,
|
||||
y+sprite_cursor->h);
|
||||
ji_add_dirty_rect(rect);
|
||||
jrect_free(rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
struct BITMAP;
|
||||
|
||||
namespace she { class Display; }
|
||||
|
||||
namespace ui {
|
||||
|
||||
/***********************************************************************/
|
||||
@ -20,17 +22,11 @@ namespace ui {
|
||||
#define JI_SCREEN_W ji_screen_w
|
||||
#define JI_SCREEN_H ji_screen_h
|
||||
|
||||
extern struct BITMAP *ji_screen;
|
||||
extern JRegion ji_dirty_region;
|
||||
extern struct BITMAP* ji_screen;
|
||||
extern int ji_screen_w;
|
||||
extern int ji_screen_h;
|
||||
|
||||
void ji_set_screen(BITMAP *bmp, int width, int height);
|
||||
|
||||
void ji_add_dirty_rect(JRect rect);
|
||||
void ji_add_dirty_region(JRegion region);
|
||||
void ji_flip_dirty_region();
|
||||
void ji_flip_rect(JRect rect);
|
||||
void SetDisplay(she::Display* display);
|
||||
|
||||
/***********************************************************************/
|
||||
/* timer related */
|
||||
|
Loading…
x
Reference in New Issue
Block a user