mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-14 13:21:34 +00:00
[lua] Add new GraphicsContext type for Canvas onpaint event
We include a simple initial API for the GraphicsContext (like stroking/filling rectangles and images).
This commit is contained in:
parent
6e13e59aff
commit
2cb526a19b
@ -175,6 +175,7 @@ if(ENABLE_SCRIPTING)
|
||||
script/events_class.cpp
|
||||
script/frame_class.cpp
|
||||
script/frames_class.cpp
|
||||
script/graphics_context.cpp
|
||||
script/grid_class.cpp
|
||||
script/image_class.cpp
|
||||
script/image_iterator_class.cpp
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -37,6 +37,14 @@ gfx::Color color_utils::blackandwhite_neg(gfx::Color color)
|
||||
return gfx::rgba(0, 0, 0);
|
||||
}
|
||||
|
||||
app::Color color_utils::color_from_ui(const gfx::Color color)
|
||||
{
|
||||
return app::Color::fromRgb(gfx::getr(color),
|
||||
gfx::getg(color),
|
||||
gfx::getb(color),
|
||||
gfx::geta(color));
|
||||
}
|
||||
|
||||
gfx::Color color_utils::color_for_ui(const app::Color& color)
|
||||
{
|
||||
gfx::Color c = gfx::ColorNone;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -25,6 +25,7 @@ namespace app {
|
||||
gfx::Color blackandwhite(gfx::Color color);
|
||||
gfx::Color blackandwhite_neg(gfx::Color color);
|
||||
|
||||
app::Color color_from_ui(const gfx::Color color);
|
||||
gfx::Color color_for_ui(const app::Color& color);
|
||||
doc::color_t color_for_image(const app::Color& color, doc::PixelFormat format);
|
||||
doc::color_t color_for_image_without_alpha(const app::Color& color, doc::PixelFormat format);
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "app/script/canvas_widget.h"
|
||||
|
||||
#include "app/script/graphics_context.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "os/system.h"
|
||||
#include "ui/message.h"
|
||||
@ -58,6 +59,10 @@ void Canvas::onResize(ui::ResizeEvent& ev)
|
||||
os::Paint p;
|
||||
p.color(bgColor());
|
||||
m_surface->drawRect(m_surface->bounds(), p);
|
||||
|
||||
// Draw only on resize (onPaint we draw the cached m_surface)
|
||||
GraphicsContext gc(m_surface);
|
||||
Paint(gc);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -66,8 +71,6 @@ void Canvas::onResize(ui::ResizeEvent& ev)
|
||||
|
||||
void Canvas::onPaint(ui::PaintEvent& ev)
|
||||
{
|
||||
Paint(ev);
|
||||
|
||||
auto g = ev.graphics();
|
||||
const gfx::Rect rc = clientBounds();
|
||||
if (m_surface)
|
||||
|
@ -14,6 +14,8 @@
|
||||
namespace app {
|
||||
namespace script {
|
||||
|
||||
class GraphicsContext;
|
||||
|
||||
// The canvas widget of a Dialog() created with Dialog:canvas{ ... }
|
||||
// This is a generic widget where all its events can be listened.
|
||||
class Canvas : public ui::Widget {
|
||||
@ -22,7 +24,7 @@ public:
|
||||
|
||||
Canvas();
|
||||
|
||||
obs::signal<void(ui::PaintEvent&)> Paint;
|
||||
obs::signal<void(GraphicsContext&)> Paint;
|
||||
|
||||
private:
|
||||
void onInitTheme(ui::InitThemeEvent& ev) override;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "app/file_selector.h"
|
||||
#include "app/script/canvas_widget.h"
|
||||
#include "app/script/engine.h"
|
||||
#include "app/script/graphics_context.h"
|
||||
#include "app/script/luacpp.h"
|
||||
#include "app/ui/color_button.h"
|
||||
#include "app/ui/color_shades.h"
|
||||
@ -915,8 +916,9 @@ int Dialog_canvas(lua_State* L)
|
||||
if (type == LUA_TFUNCTION) {
|
||||
Dialog_connect_signal(
|
||||
L, 1, widget->Paint,
|
||||
[](lua_State* L, ui::PaintEvent& ev) {
|
||||
// TODO
|
||||
[](lua_State* L, GraphicsContext& gc) {
|
||||
push_new<GraphicsContext>(L, std::move(gc));
|
||||
lua_setfield(L, -2, "context");
|
||||
});
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
@ -159,6 +159,7 @@ void register_color_class(lua_State* L);
|
||||
void register_color_space_class(lua_State* L);
|
||||
#ifdef ENABLE_UI
|
||||
void register_dialog_class(lua_State* L);
|
||||
void register_graphics_context_class(lua_State* L);
|
||||
#endif
|
||||
void register_events_class(lua_State* L);
|
||||
void register_frame_class(lua_State* L);
|
||||
@ -412,6 +413,7 @@ Engine::Engine()
|
||||
register_color_space_class(L);
|
||||
#ifdef ENABLE_UI
|
||||
register_dialog_class(L);
|
||||
register_graphics_context_class(L);
|
||||
#endif
|
||||
register_events_class(L);
|
||||
register_frame_class(L);
|
||||
|
177
src/app/script/graphics_context.cpp
Normal file
177
src/app/script/graphics_context.cpp
Normal file
@ -0,0 +1,177 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2022 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/script/graphics_context.h"
|
||||
|
||||
#include "app/color.h"
|
||||
#include "app/color_utils.h"
|
||||
#include "app/modules/palettes.h"
|
||||
#include "app/script/engine.h"
|
||||
#include "app/script/luacpp.h"
|
||||
#include "app/util/conversion_to_surface.h"
|
||||
|
||||
#ifdef ENABLE_UI
|
||||
|
||||
namespace app {
|
||||
namespace script {
|
||||
|
||||
void GraphicsContext::drawImage(const doc::Image* img, int x, int y)
|
||||
{
|
||||
convert_image_to_surface(
|
||||
img,
|
||||
get_current_palette(),
|
||||
m_surface.get(),
|
||||
0, 0,
|
||||
x, y,
|
||||
img->width(), img->height());
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
int GraphicsContext_gc(lua_State* L)
|
||||
{
|
||||
auto gc = get_obj<GraphicsContext>(L, 1);
|
||||
gc->~GraphicsContext();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GraphicsContext_save(lua_State* L)
|
||||
{
|
||||
auto gc = get_obj<GraphicsContext>(L, 1);
|
||||
gc->save();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GraphicsContext_restore(lua_State* L)
|
||||
{
|
||||
auto gc = get_obj<GraphicsContext>(L, 1);
|
||||
gc->restore();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GraphicsContext_strokeRect(lua_State* L)
|
||||
{
|
||||
auto gc = get_obj<GraphicsContext>(L, 1);
|
||||
const gfx::Rect rc = convert_args_into_rect(L, 2);
|
||||
gc->strokeRect(rc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GraphicsContext_fillRect(lua_State* L)
|
||||
{
|
||||
auto gc = get_obj<GraphicsContext>(L, 1);
|
||||
const gfx::Rect rc = convert_args_into_rect(L, 2);
|
||||
gc->fillRect(rc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GraphicsContext_drawImage(lua_State* L)
|
||||
{
|
||||
auto gc = get_obj<GraphicsContext>(L, 1);
|
||||
if (const doc::Image* img = may_get_image_from_arg(L, 2)) {
|
||||
int x = lua_tointeger(L, 3);
|
||||
int y = lua_tointeger(L, 4);
|
||||
gc->drawImage(img, x, y);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GraphicsContext_get_width(lua_State* L)
|
||||
{
|
||||
auto gc = get_obj<GraphicsContext>(L, 1);
|
||||
lua_pushinteger(L, gc->width());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GraphicsContext_get_height(lua_State* L)
|
||||
{
|
||||
auto gc = get_obj<GraphicsContext>(L, 1);
|
||||
lua_pushinteger(L, gc->height());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GraphicsContext_get_antialias(lua_State* L)
|
||||
{
|
||||
auto gc = get_obj<GraphicsContext>(L, 1);
|
||||
lua_pushboolean(L, gc->antialias());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GraphicsContext_set_antialias(lua_State* L)
|
||||
{
|
||||
auto gc = get_obj<GraphicsContext>(L, 1);
|
||||
const bool antialias = lua_toboolean(L, 2);
|
||||
gc->antialias(antialias);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GraphicsContext_get_color(lua_State* L)
|
||||
{
|
||||
auto gc = get_obj<GraphicsContext>(L, 1);
|
||||
push_obj(L, color_utils::color_from_ui(gc->color()));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GraphicsContext_set_color(lua_State* L)
|
||||
{
|
||||
auto gc = get_obj<GraphicsContext>(L, 1);
|
||||
const app::Color color = convert_args_into_color(L, 2);
|
||||
gc->color(color_utils::color_for_ui(color));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GraphicsContext_get_strokeWidth(lua_State* L)
|
||||
{
|
||||
auto gc = get_obj<GraphicsContext>(L, 1);
|
||||
lua_pushnumber(L, gc->strokeWidth());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GraphicsContext_set_strokeWidth(lua_State* L)
|
||||
{
|
||||
auto gc = get_obj<GraphicsContext>(L, 1);
|
||||
const float strokeWidth = lua_tonumber(L, 2);
|
||||
gc->strokeWidth(strokeWidth);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const luaL_Reg GraphicsContext_methods[] = {
|
||||
{ "__gc", GraphicsContext_gc },
|
||||
{ "save", GraphicsContext_save },
|
||||
{ "restore", GraphicsContext_restore },
|
||||
{ "strokeRect", GraphicsContext_strokeRect },
|
||||
{ "fillRect", GraphicsContext_fillRect },
|
||||
{ "drawImage", GraphicsContext_drawImage },
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
const Property GraphicsContext_properties[] = {
|
||||
{ "width", GraphicsContext_get_width, nullptr },
|
||||
{ "height", GraphicsContext_get_height, nullptr },
|
||||
{ "antialias", GraphicsContext_get_antialias, GraphicsContext_set_antialias },
|
||||
{ "color", GraphicsContext_get_color, GraphicsContext_set_color },
|
||||
{ "strokeWidth", GraphicsContext_get_strokeWidth, GraphicsContext_set_strokeWidth },
|
||||
{ nullptr, nullptr, nullptr }
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
DEF_MTNAME(GraphicsContext);
|
||||
|
||||
void register_graphics_context_class(lua_State* L)
|
||||
{
|
||||
REG_CLASS(L, GraphicsContext);
|
||||
REG_CLASS_PROPERTIES(L, GraphicsContext);
|
||||
}
|
||||
|
||||
} // namespace script
|
||||
} // namespace app
|
||||
|
||||
#endif // ENABLE_UI
|
80
src/app/script/graphics_context.h
Normal file
80
src/app/script/graphics_context.h
Normal file
@ -0,0 +1,80 @@
|
||||
// Aseprite
|
||||
// Copyright (c) 2022 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef APP_SCRIPT_GRAPHICS_CONTEXT_H_INCLUDED
|
||||
#define APP_SCRIPT_GRAPHICS_CONTEXT_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#ifdef ENABLE_UI
|
||||
|
||||
#include "os/paint.h"
|
||||
#include "os/surface.h"
|
||||
|
||||
#include <stack>
|
||||
|
||||
namespace doc {
|
||||
class Image;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
namespace script {
|
||||
|
||||
class GraphicsContext {
|
||||
public:
|
||||
GraphicsContext(const os::SurfaceRef& surface) : m_surface(surface) { }
|
||||
GraphicsContext(GraphicsContext&& gc) {
|
||||
std::swap(m_surface, gc.m_surface);
|
||||
}
|
||||
|
||||
int width() const { return m_surface->width(); }
|
||||
int height() const { return m_surface->height(); }
|
||||
|
||||
void save() {
|
||||
m_saved.push(m_paint);
|
||||
m_surface->save();
|
||||
}
|
||||
|
||||
void restore() {
|
||||
if (!m_saved.empty()) {
|
||||
m_paint = m_saved.top();
|
||||
m_saved.pop();
|
||||
m_surface->restore();
|
||||
}
|
||||
}
|
||||
|
||||
void strokeRect(const gfx::Rect& rc) {
|
||||
m_paint.style(os::Paint::Stroke);
|
||||
m_surface->drawRect(rc, m_paint);
|
||||
}
|
||||
|
||||
void fillRect(const gfx::Rect& rc) {
|
||||
m_paint.style(os::Paint::Fill);
|
||||
m_surface->drawRect(rc, m_paint);
|
||||
}
|
||||
|
||||
bool antialias() const { return m_paint.antialias(); }
|
||||
void antialias(bool value) { m_paint.antialias(value); }
|
||||
|
||||
gfx::Color color() const { return m_paint.color(); }
|
||||
void color(gfx::Color color) { m_paint.color(color); }
|
||||
|
||||
float strokeWidth() const { return m_paint.strokeWidth(); }
|
||||
void strokeWidth(float value) { m_paint.strokeWidth(value); }
|
||||
|
||||
void drawImage(const doc::Image* img, int x, int y);
|
||||
|
||||
private:
|
||||
os::SurfaceRef m_surface = nullptr;
|
||||
os::Paint m_paint;
|
||||
std::stack<os::Paint> m_saved;
|
||||
};
|
||||
|
||||
} // namespace script
|
||||
} // namespace app
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user