Add Image class to scripting

With this change we introduce SpriteWrap and ImageWrap to keep track
of modifications made by the script in one transaction. So we can undo
the script action as one simple action.
This commit is contained in:
David Capello 2016-04-06 19:05:06 -03:00
parent 7f31bbef26
commit 956349f87b
17 changed files with 539 additions and 127 deletions

View File

@ -2,7 +2,7 @@
// Copyright (C) 2015-2016 by David Capello
var col = app.pixelColor
var img = app.activeSprite
var img = app.activeImage
for (y=0; y<img.height; ++y) {
for (x=0; x<img.width; ++x) {

View File

@ -321,7 +321,10 @@ add_library(app-lib
script/app_object.cpp
script/app_scripting.cpp
script/console_object.cpp
script/image_class.cpp
script/image_wrap.cpp
script/sprite_class.cpp
script/sprite_wrap.cpp
send_crash.cpp
shade.cpp
shell.cpp

View File

@ -19,8 +19,11 @@ namespace app {
namespace cmd {
CopyRegion::CopyRegion(Image* dst, const Image* src,
const gfx::Region& region, int dst_dx, int dst_dy)
const gfx::Region& region,
int dst_dx, int dst_dy,
bool alreadyCopied)
: WithImage(dst)
, m_alreadyCopied(alreadyCopied)
{
// Create region to save/swap later
for (const auto& rc : region) {
@ -46,7 +49,8 @@ CopyRegion::CopyRegion(Image* dst, const Image* src,
void CopyRegion::onExecute()
{
swap();
if (!m_alreadyCopied)
swap();
}
void CopyRegion::onUndo()

View File

@ -22,8 +22,13 @@ namespace cmd {
class CopyRegion : public Cmd
, public WithImage {
public:
// If alreadyCopied is false, it means that onExecute() will copy
// pixels from src to dst. If it's true, it means that "onExecute"
// should do nothing, because modified pixels are alreadt on "dst"
// (so we use "src" as the original image).
CopyRegion(Image* dst, const Image* src,
const gfx::Region& region, int src_dx, int src_dy);
const gfx::Region& region, int src_dx, int src_dy,
bool alreadyCopied = false);
protected:
void onExecute() override;
@ -37,6 +42,7 @@ namespace cmd {
private:
void swap();
bool m_alreadyCopied;
gfx::Region m_region;
std::stringstream m_stream;
};

View File

@ -11,7 +11,9 @@
#include "app/script/console_object.h"
#include "app/script/sprite_class.h"
#include "app/document.h"
#include "app/script/app_scripting.h"
#include "app/script/sprite_wrap.h"
#include "app/ui_context.h"
#include "script/engine.h"
@ -29,7 +31,20 @@ script::result_t App_get_activeSprite(script::ContextHandle handle)
script::Context ctx(handle);
app::Document* doc = UIContext::instance()->activeDocument();
if (doc)
ctx.pushObject(wrap_sprite(doc), "Sprite");
ctx.pushObject(unwrap_engine(ctx)->wrapSprite(doc), "Sprite");
else
ctx.pushNull();
return 1;
}
script::result_t App_get_activeImage(script::ContextHandle handle)
{
script::Context ctx(handle);
app::Document* doc = UIContext::instance()->activeDocument();
if (doc) {
SpriteWrap* wrap = unwrap_engine(ctx)->wrapSprite(doc);
ctx.pushObject(wrap->activeImage(), "Image");
}
else
ctx.pushNull();
return 1;
@ -55,6 +70,7 @@ const script::FunctionEntry App_methods[] = {
};
const script::PropertyEntry App_props[] = {
{ "activeImage", App_get_activeImage, nullptr },
{ "activeSprite", App_get_activeSprite, nullptr },
{ "pixelColor", App_get_pixelColor, nullptr },
{ "version", App_get_version, nullptr },

View File

@ -11,9 +11,13 @@
#include "app/script/app_scripting.h"
#include "app/document.h"
#include "app/script/app_object.h"
#include "app/script/console_object.h"
#include "app/script/image_class.h"
#include "app/script/image_wrap.h"
#include "app/script/sprite_class.h"
#include "app/script/sprite_wrap.h"
namespace app {
@ -25,8 +29,51 @@ AppScripting::AppScripting(script::EngineDelegate* delegate)
register_console_object(ctx);
ctx.pushGlobalObject();
register_image_class(-1, ctx);
register_sprite_class(-1, ctx);
ctx.pushPointer(this);
ctx.setProp(-2, script::kPtrId);
ctx.pop();
}
SpriteWrap* AppScripting::wrapSprite(app::Document* doc)
{
auto it = m_sprites.find(doc->id());
if (it != m_sprites.end())
return it->second;
else {
auto wrap = new SpriteWrap(doc);
m_sprites[doc->id()] = wrap;
return wrap;
}
}
void AppScripting::onAfterEval(bool err)
{
// Commit all transactions
if (!err) {
for (auto& it : m_sprites)
it.second->commit();
}
destroyWrappers();
}
void AppScripting::destroyWrappers()
{
for (auto& it : m_sprites)
delete it.second;
m_sprites.clear();
}
AppScripting* unwrap_engine(script::Context& ctx)
{
ctx.pushGlobalObject();
ctx.getProp(-1, script::kPtrId);
void* ptr = ctx.getPointer(-1);
ctx.pop(2);
return (AppScripting*)ptr;
}
}

View File

@ -5,19 +5,43 @@
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
#ifndef APP_SCRIPT_H_INCLUDED
#define APP_SCRIPT_H_INCLUDED
#ifndef APP_SCRIPTING_H_INCLUDED
#define APP_SCRIPTING_H_INCLUDED
#pragma once
#include "doc/object_id.h"
#include "script/engine.h"
#include <map>
namespace doc {
class Image;
}
namespace app {
class Document;
class ImageWrap;
class SpriteWrap;
class AppScripting : public script::Engine {
typedef std::map<doc::ObjectId, SpriteWrap*> Sprites;
public:
AppScripting(script::EngineDelegate* delegate);
SpriteWrap* wrapSprite(app::Document* doc);
protected:
void onAfterEval(bool err) override;
private:
void destroyWrappers();
Sprites m_sprites;
};
AppScripting* unwrap_engine(script::Context& ctx);
} // namespace app
#endif

View File

@ -0,0 +1,101 @@
// Aseprite
// Copyright (C) 2015-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/script/image_class.h"
#include "app/script/image_wrap.h"
#include "doc/image.h"
namespace app {
namespace {
script::result_t Image_ctor(script::ContextHandle handle)
{
return 0;
}
script::result_t Image_putPixel(script::ContextHandle handle)
{
script::Context ctx(handle);
int x = ctx.requireInt(0);
int y = ctx.requireInt(1);
doc::color_t color = ctx.requireUInt(2);
auto wrap = (ImageWrap*)ctx.getThis();
if (wrap) {
wrap->modifyRegion(gfx::Region(gfx::Rect(x, y, 1, 1)));
wrap->image()->putPixel(x, y, color);
}
return 0;
}
script::result_t Image_getPixel(script::ContextHandle handle)
{
script::Context ctx(handle);
int x = ctx.requireInt(0);
int y = ctx.requireInt(1);
auto wrap = (ImageWrap*)ctx.getThis();
if (wrap) {
doc::color_t color = wrap->image()->getPixel(x, y);
ctx.pushUInt(color);
return 1;
}
else
return 0;
}
script::result_t Image_get_width(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (ImageWrap*)ctx.getThis();
if (wrap) {
ctx.pushInt(wrap->image()->width());
return 1;
}
else
return 0;
}
script::result_t Image_get_height(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (ImageWrap*)ctx.getThis();
if (wrap) {
ctx.pushInt(wrap->image()->height());
return 1;
}
else
return 0;
}
const script::FunctionEntry Image_methods[] = {
{ "getPixel", Image_getPixel, 2 },
{ "putPixel", Image_putPixel, 3 },
{ nullptr, nullptr, 0 }
};
const script::PropertyEntry Image_props[] = {
{ "width", Image_get_width, nullptr },
{ "height", Image_get_height, nullptr },
{ nullptr, nullptr, 0 }
};
} // anonymous namespace
void register_image_class(script::index_t idx, script::Context& ctx)
{
ctx.registerClass(idx, "Image", Image_ctor, 0, Image_methods, Image_props);
}
} // namespace app

View File

@ -0,0 +1,20 @@
// Aseprite
// Copyright (C) 2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
#ifndef APP_SCRIPT_IMAGE_CLASS_H_INCLUDED
#define APP_SCRIPT_IMAGE_CLASS_H_INCLUDED
#pragma once
#include "script/engine.h"
namespace app {
void register_image_class(script::index_t idx, script::Context& ctx);
} // namespace app
#endif

View File

@ -0,0 +1,52 @@
// Aseprite
// Copyright (C) 2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/script/image_wrap.h"
#include "app/cmd/copy_region.h"
#include "app/script/sprite_wrap.h"
#include "app/transaction.h"
#include "doc/image.h"
namespace app {
ImageWrap::ImageWrap(SpriteWrap* sprite, doc::Image* img)
: m_sprite(sprite)
, m_image(img)
, m_backup(nullptr)
{
}
ImageWrap::~ImageWrap()
{
}
void ImageWrap::commit()
{
if (m_modifiedRegion.isEmpty())
return;
sprite()->transaction().execute(
new cmd::CopyRegion(m_image,
m_backup.get(),
m_modifiedRegion, 0, 0,
true));
}
void ImageWrap::modifyRegion(const gfx::Region& rgn)
{
if (!m_backup)
m_backup.reset(doc::Image::createCopy(m_image));
m_modifiedRegion |= rgn;
}
} // namespace app

View File

@ -0,0 +1,39 @@
// Aseprite
// Copyright (C) 2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
#ifndef APP_SCRIPT_IMAGE_WRAP_H_INCLUDED
#define APP_SCRIPT_IMAGE_WRAP_H_INCLUDED
#pragma once
#include "doc/image.h"
#include "doc/image_ref.h"
#include "gfx/region.h"
namespace app {
class SpriteWrap;
class ImageWrap {
public:
ImageWrap(SpriteWrap* sprite, doc::Image* img);
~ImageWrap();
void commit();
SpriteWrap* sprite() const { return m_sprite; }
doc::Image* image() const { return m_image; }
void modifyRegion(const gfx::Region& rgn);
private:
SpriteWrap* m_sprite;
doc::Image* m_image;
doc::ImageRef m_backup;
gfx::Region m_modifiedRegion;
};
} // namespace app
#endif

View File

@ -11,8 +11,11 @@
#include "app/script/sprite_class.h"
#include "app/cmd/set_sprite_size.h"
#include "app/document.h"
#include "app/document_api.h"
#include "app/script/app_scripting.h"
#include "app/script/sprite_wrap.h"
#include "app/transaction.h"
#include "app/ui/document_view.h"
#include "app/ui_context.h"
@ -20,30 +23,10 @@
#include "doc/sprite.h"
#include "script/engine.h"
#include <map>
#include <iostream>
namespace app {
namespace {
class SpriteInScript {
public:
SpriteInScript(app::Document* doc)
: m_doc(doc) {
}
~SpriteInScript() {
}
app::Document* document() {
return m_doc;
}
private:
app::Document* m_doc;
};
script::result_t Sprite_ctor(script::ContextHandle handle)
{
script::Context ctx(handle);
@ -58,71 +41,22 @@ script::result_t Sprite_ctor(script::ContextHandle handle)
sprite.release();
doc->setContext(UIContext::instance());
ctx.pushThis(wrap_sprite(doc.release()));
ctx.pushThis(unwrap_engine(ctx)->wrapSprite(doc.release()));
}
return 0;
}
script::result_t Sprite_putPixel(script::ContextHandle handle)
{
script::Context ctx(handle);
int x = ctx.requireInt(0);
int y = ctx.requireInt(1);
doc::color_t color = ctx.requireUInt(2);
Document* doc = (Document*)unwrap_sprite(ctx.getThis());
DocumentView* docView = UIContext::instance()->getFirstDocumentView(doc);
if (!docView)
return 0;
doc::Site site;
docView->getSite(&site);
int celX, celY;
doc::Image* image = site.image(&celX, &celY, nullptr);
if (image)
image->putPixel(x-celX, y-celY, color);
return 0;
}
script::result_t Sprite_getPixel(script::ContextHandle handle)
{
script::Context ctx(handle);
int x = ctx.requireInt(0);
int y = ctx.requireInt(1);
Document* doc = (Document*)unwrap_sprite(ctx.getThis());
DocumentView* docView = UIContext::instance()->getFirstDocumentView(doc);
if (!docView)
return 0;
doc::Site site;
docView->getSite(&site);
int celX, celY;
doc::Image* image = site.image(&celX, &celY, nullptr);
if (image) {
doc::color_t color = image->getPixel(x-celX, y-celY);
ctx.pushUInt(color);
return 1;
}
else
return 0;
}
script::result_t Sprite_resize(script::ContextHandle handle)
{
script::Context ctx(handle);
int w = ctx.requireInt(0);
int h = ctx.requireInt(1);
Document* doc = (Document*)unwrap_sprite(ctx.getThis());
{
Transaction transaction(UIContext::instance(), "Script Execution", ModifyDocument);
DocumentApi api(doc, transaction);
auto wrap = (SpriteWrap*)ctx.getThis();
if (wrap) {
Document* doc = wrap->document();
DocumentApi api(doc, wrap->transaction());
api.setSpriteSize(doc->sprite(), w, h);
transaction.commit();
}
return 0;
@ -136,12 +70,11 @@ script::result_t Sprite_crop(script::ContextHandle handle)
int w = ctx.requireInt(2);
int h = ctx.requireInt(3);
Document* doc = (Document*)unwrap_sprite(ctx.getThis());
{
Transaction transaction(UIContext::instance(), "Script Execution", ModifyDocument);
DocumentApi api(doc, transaction);
auto wrap = (SpriteWrap*)ctx.getThis();
if (wrap) {
Document* doc = wrap->document();
DocumentApi api(doc, wrap->transaction());
api.cropSprite(doc->sprite(), gfx::Rect(x, y, w, h));
transaction.commit();
}
return 0;
@ -150,8 +83,8 @@ script::result_t Sprite_crop(script::ContextHandle handle)
script::result_t Sprite_get_width(script::ContextHandle handle)
{
script::Context ctx(handle);
Document* doc = (Document*)unwrap_sprite(ctx.getThis());
ctx.pushInt(doc->sprite()->width());
auto wrap = (SpriteWrap*)ctx.getThis();
ctx.pushInt(wrap->sprite()->width());
return 1;
}
@ -159,16 +92,21 @@ script::result_t Sprite_set_width(script::ContextHandle handle)
{
script::Context ctx(handle);
int w = ctx.requireInt(0);
Document* doc = (Document*)unwrap_sprite(ctx.getThis());
doc->sprite()->setSize(w, doc->sprite()->height());
auto wrap = (SpriteWrap*)ctx.getThis();
wrap->transaction().execute(
new cmd::SetSpriteSize(wrap->sprite(),
w,
wrap->sprite()->height()));
return 0;
}
script::result_t Sprite_get_height(script::ContextHandle handle)
{
script::Context ctx(handle);
Document* doc = (Document*)unwrap_sprite(ctx.getThis());
ctx.pushInt(doc->sprite()->height());
auto wrap = (SpriteWrap*)ctx.getThis();
ctx.pushInt(wrap->sprite()->height());
return 1;
}
@ -176,14 +114,17 @@ script::result_t Sprite_set_height(script::ContextHandle handle)
{
script::Context ctx(handle);
int h = ctx.requireInt(0);
Document* doc = (Document*)unwrap_sprite(ctx.getThis());
doc->sprite()->setSize(doc->sprite()->width(), h);
auto wrap = (SpriteWrap*)ctx.getThis();
wrap->transaction().execute(
new cmd::SetSpriteSize(wrap->sprite(),
wrap->sprite()->width(),
h));
return 0;
}
const script::FunctionEntry Sprite_methods[] = {
{ "getPixel", Sprite_getPixel, 2 },
{ "putPixel", Sprite_putPixel, 3 },
{ "resize", Sprite_resize, 2 },
{ "crop", Sprite_crop, 4 },
{ nullptr, nullptr, 0 }
@ -197,28 +138,6 @@ const script::PropertyEntry Sprite_props[] = {
} // anonymous namespace
static std::map<doc::ObjectId, SpriteInScript*> g_sprites;
void* wrap_sprite(app::Document* doc)
{
auto it = g_sprites.find(doc->id());
if (it != g_sprites.end())
return it->second;
else {
SpriteInScript* wrap = new SpriteInScript(doc);
g_sprites[doc->id()] = wrap;
return wrap;
}
}
app::Document* unwrap_sprite(void* ptr)
{
if (ptr)
return ((SpriteInScript*)ptr)->document();
else
return nullptr;
}
void register_sprite_class(script::index_t idx, script::Context& ctx)
{
ctx.registerClass(idx, "Sprite", Sprite_ctor, 3, Sprite_methods, Sprite_props);

View File

@ -12,10 +12,6 @@
#include "script/engine.h"
namespace app {
class Document;
void* wrap_sprite(app::Document* doc);
app::Document* unwrap_sprite(void* ptr);
void register_sprite_class(script::index_t idx, script::Context& ctx);

View File

@ -0,0 +1,96 @@
// Aseprite
// Copyright (C) 2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/script/sprite_wrap.h"
#include "app/cmd/set_sprite_size.h"
#include "app/document.h"
#include "app/document_api.h"
#include "app/script/image_wrap.h"
#include "app/transaction.h"
#include "app/ui/document_view.h"
#include "app/ui_context.h"
#include "doc/site.h"
#include "doc/sprite.h"
namespace app {
SpriteWrap::SpriteWrap(app::Document* doc)
: m_doc(doc)
, m_view(UIContext::instance()->getFirstDocumentView(m_doc))
, m_transaction(nullptr)
{
}
SpriteWrap::~SpriteWrap()
{
for (auto it : m_images)
delete it.second;
if (m_transaction)
delete m_transaction;
}
Transaction& SpriteWrap::transaction()
{
if (!m_transaction) {
m_transaction = new Transaction(UIContext::instance(),
"Script Execution",
ModifyDocument);
}
return *m_transaction;
}
void SpriteWrap::commit()
{
for (auto it : m_images)
it.second->commit();
if (m_transaction) {
m_transaction->commit();
delete m_transaction;
m_transaction = nullptr;
}
}
app::Document* SpriteWrap::document()
{
return m_doc;
}
doc::Sprite* SpriteWrap::sprite()
{
return m_doc->sprite();
}
ImageWrap* SpriteWrap::activeImage()
{
if (!m_view)
return nullptr;
doc::Site site;
m_view->getSite(&site);
return wrapImage(site.image());
}
ImageWrap* SpriteWrap::wrapImage(doc::Image* img)
{
auto it = m_images.find(img->id());
if (it != m_images.end())
return it->second;
else {
auto wrap = new ImageWrap(this, img);
m_images[img->id()] = wrap;
return wrap;
}
}
} // namespace app

View File

@ -0,0 +1,53 @@
// Aseprite
// Copyright (C) 2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
#ifndef APP_SCRIPT_SPRITE_WRAP_H_INCLUDED
#define APP_SCRIPT_SPRITE_WRAP_H_INCLUDED
#pragma once
#include "doc/object_id.h"
#include <map>
namespace doc {
class Image;
class Sprite;
}
namespace app {
class Document;
class DocumentView;
class ImageWrap;
class Transaction;
class SpriteWrap {
typedef std::map<doc::ObjectId, ImageWrap*> Images;
public:
SpriteWrap(app::Document* doc);
~SpriteWrap();
void commit();
Transaction& transaction();
app::Document* document();
doc::Sprite* sprite();
ImageWrap* activeImage();
ImageWrap* wrapImage(doc::Image* img);
private:
app::Document* m_doc;
app::DocumentView* m_view;
app::Transaction* m_transaction;
Images m_images;
};
} // namespace app
#endif

View File

@ -30,6 +30,8 @@ public:
namespace script {
const char* kPtrId = "\xFF" "\xFF" "ptr";
namespace {
// TODO classes in modules isn't supported yet
@ -108,6 +110,11 @@ void Context::pop()
duk_pop(m_handle);
}
void Context::pop(index_t count)
{
duk_pop_n(m_handle, count);
}
void Context::remove(index_t idx)
{
duk_remove(m_handle, idx);
@ -193,6 +200,11 @@ const char* Context::toString(index_t i)
return duk_to_string(m_handle, i);
}
void* Context::getPointer(index_t i)
{
return duk_get_pointer(m_handle, i);
}
bool Context::requireBool(index_t i)
{
return (duk_require_boolean(m_handle, i) ? true: false);
@ -220,7 +232,7 @@ const char* Context::requireString(index_t i)
void* Context::requireObject(index_t i, const char* className)
{
duk_get_prop_string(m_handle, i, "\xFF" "\xFF" "ptr");
duk_get_prop_string(m_handle, i, kPtrId);
void* result = (void*)duk_to_pointer(m_handle, -1);
// TODO check pointer type
duk_pop(m_handle);
@ -276,7 +288,12 @@ void Context::pushThis(void* ptr)
{
duk_push_this(m_handle);
duk_push_pointer(m_handle, ptr);
duk_put_prop_string(m_handle, -2, "\xFF" "\xFF" "ptr");
duk_put_prop_string(m_handle, -2, kPtrId);
}
void Context::pushPointer(void* ptr)
{
duk_push_pointer(m_handle, ptr);
}
index_t Context::pushObject()
@ -288,7 +305,7 @@ index_t Context::pushObject(void* ptr, const char* className)
{
index_t obj = duk_push_object(m_handle);
duk_push_pointer(m_handle, ptr);
duk_put_prop_string(m_handle, obj, "\xFF" "\xFF" "ptr");
duk_put_prop_string(m_handle, obj, kPtrId);
// TODO classes in modules isn't supported yet
duk_get_global_string(m_handle, className);
@ -395,7 +412,7 @@ void Context::registerClass(index_t idx,
void* Context::getThis()
{
duk_push_this(m_handle);
duk_get_prop_string(m_handle, -1, "\xFF" "\xFF" "ptr");
duk_get_prop_string(m_handle, -1, kPtrId);
void* result = (void*)duk_to_pointer(m_handle, -1);
duk_pop_2(m_handle);
return result;
@ -445,6 +462,8 @@ void Engine::printLastResult()
void Engine::eval(const std::string& jsCode)
{
bool errFlag = true;
onBeforeEval();
try {
ContextHandle handle = m_ctx.handle();
@ -453,18 +472,23 @@ void Engine::eval(const std::string& jsCode)
if (m_printLastResult &&
!duk_is_null_or_undefined(handle, -1)) {
m_delegate->onConsolePrint(duk_safe_to_string(handle, -1));
}
duk_pop(handle);
errFlag = false;
}
catch (const std::exception& ex) {
std::string err = "Error: ";
err += ex.what();
m_delegate->onConsolePrint(err.c_str());
}
onAfterEval(errFlag);
}
void Engine::evalFile(const std::string& file)
{
bool errFlag = true;
onBeforeEval();
try {
ContextHandle handle = m_ctx.handle();
@ -497,14 +521,17 @@ void Engine::evalFile(const std::string& file)
if (m_printLastResult &&
!duk_is_null_or_undefined(handle, -1)) {
m_delegate->onConsolePrint(duk_safe_to_string(handle, -1));
}
duk_pop(handle);
errFlag = false;
}
catch (const std::exception& ex) {
std::string err = "Error: ";
err += ex.what();
m_delegate->onConsolePrint(err.c_str());
}
onAfterEval(errFlag);
}
void Engine::registerModule(Module* module)

View File

@ -21,6 +21,8 @@ namespace script {
typedef struct duk_hthread* ContextHandle;
typedef result_t (*Function)(ContextHandle ctx);
extern const char* kPtrId;
struct FunctionEntry {
const char* id;
Function value;
@ -48,6 +50,7 @@ namespace script {
void dump();
void pop();
void pop(index_t count);
void remove(index_t idx);
void duplicateTop();
@ -68,6 +71,7 @@ namespace script {
unsigned int getUInt(index_t i);
const char* getString(index_t i);
const char* toString(index_t i);
void* getPointer(index_t i);
void* getThis();
bool hasProp(index_t i, const char* propName);
@ -91,6 +95,7 @@ namespace script {
void pushString(const char* str);
void pushThis();
void pushThis(void* ptr);
void pushPointer(void* ptr);
index_t pushObject();
index_t pushObject(void* ptr, const char* className);
void pushGlobalObject();
@ -134,6 +139,10 @@ namespace script {
void registerModule(Module* module);
protected:
virtual void onBeforeEval() { }
virtual void onAfterEval(bool err) { }
private:
Context m_ctx;
EngineDelegate* m_delegate;