Replace duktape with mujs

Added other classes like Rectangle, Size, and Point.
master
David Capello 2017-08-11 17:22:28 -03:00
parent 16520dc384
commit bcf7efc9bb
30 changed files with 1120 additions and 812 deletions

3
.gitmodules vendored
View File

@ -51,3 +51,6 @@
[submodule "third_party/benchmark"]
path = third_party/benchmark
url = https://github.com/aseprite/benchmark.git
[submodule "third_party/mujs"]
path = third_party/mujs
url = https://github.com/aseprite/mujs.git

View File

@ -150,7 +150,6 @@ set(HARFBUZZ_DIR ${CMAKE_SOURCE_DIR}/third_party/harfbuzz)
set(SIMPLEINI_DIR ${CMAKE_SOURCE_DIR}/third_party/simpleini)
set(TINYXML_DIR ${CMAKE_SOURCE_DIR}/third_party/tinyxml)
set(ZLIB_DIR ${CMAKE_SOURCE_DIR}/third_party/zlib)
set(DUKTAPE_DIR ${CMAKE_SOURCE_DIR}/third_party/duktape)
# Search in the "cmake" directory for additional CMake modules.
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

View File

@ -1,11 +1,11 @@
// Aseprite
// Copyright (C) 2015-2016 by David Capello
// Copyright (C) 2015-2017 by David Capello
var col = app.pixelColor
var img = app.activeImage
for (y=0; y<img.height; ++y) {
for (x=0; x<img.width; ++x) {
for (var y=0; y<img.height; ++y) {
for (var x=0; x<img.width; ++x) {
var c = img.getPixel(x, y)
var v = (col.rgbaR(c)+
col.rgbaG(c)+

View File

@ -230,36 +230,6 @@ be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.
```
# [duktape](http://duktape.org/)
```
===============
Duktape license
===============
(http://opensource.org/licenses/MIT)
Copyright (c) 2013-2016 by Duktape authors (see AUTHORS.rst)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
```
# [FreeType](http://www.freetype.org/)
```
@ -884,6 +854,26 @@ freely, subject to the following restrictions:
distribution.
```
# [mujs](http://mujs.com/)
```
ISC License
Copyright (c) 2013, 2017, Artifex Software
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
```
# [pixman](http://www.pixman.org/)
```

View File

@ -137,7 +137,11 @@ if(ENABLE_SCRIPTING)
script/console_object.cpp
script/image_class.cpp
script/image_wrap.cpp
script/pixel_color_class.cpp
script/point_class.cpp
script/rectangle_class.cpp
script/selection_class.cpp
script/size_class.cpp
script/sprite_class.cpp
script/sprite_wrap.cpp
shell.cpp

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2016 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2015-2016 David Capello
// Copyright (C) 2015-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -8,8 +8,6 @@
#include "config.h"
#endif
#include "app/script/console_object.h"
#include "app/document.h"
#include "app/commands/commands.h"
#include "app/commands/params.h"
@ -18,94 +16,90 @@
#include "app/ui_context.h"
#include "script/engine.h"
// App sub-objects
#include "app/script/pixel_color.h"
#include <iostream>
namespace app {
namespace {
script::result_t App_open(script::ContextHandle handle)
void App_open(script::ContextHandle handle)
{
script::Context ctx(handle);
if (!ctx.isString(0) ||
!ctx.toString(0))
return 0;
const char* fn = ctx.toString(0);
const char* filename = ctx.requireString(1);
app::Document* oldDoc = UIContext::instance()->activeDocument();
Command* openCommand = CommandsModule::instance()->getCommandByName(CommandId::OpenFile);
Params params;
params.set("filename", fn);
params.set("filename", filename);
UIContext::instance()->executeCommand(openCommand, params);
app::Document* newDoc = UIContext::instance()->activeDocument();
if (newDoc != oldDoc)
ctx.pushObject(unwrap_engine(ctx)->wrapSprite(newDoc), "Sprite");
ctx.newObject("Sprite", unwrap_engine(ctx)->wrapSprite(newDoc), nullptr);
else
ctx.pushNull();
return 1;
}
script::result_t App_exit(script::ContextHandle handle)
void App_exit(script::ContextHandle handle)
{
Command* exitCommand = CommandsModule::instance()->getCommandByName(CommandId::Exit);
UIContext::instance()->executeCommand(exitCommand);
return 0;
script::Context ctx(handle);
UIContext* appCtx = UIContext::instance();
if (appCtx && appCtx->isUIAvailable()) {
Command* exitCommand = CommandsModule::instance()->getCommandByName(CommandId::Exit);
appCtx->executeCommand(exitCommand);
}
ctx.pushUndefined();
}
script::result_t App_get_activeSprite(script::ContextHandle handle)
void App_get_activeSprite(script::ContextHandle handle)
{
script::Context ctx(handle);
app::Document* doc = UIContext::instance()->activeDocument();
if (doc)
ctx.pushObject(unwrap_engine(ctx)->wrapSprite(doc), "Sprite");
ctx.newObject("Sprite", unwrap_engine(ctx)->wrapSprite(doc), nullptr);
else
ctx.pushNull();
return 1;
}
script::result_t App_get_activeImage(script::ContextHandle handle)
void 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");
SpriteWrap* sprWrap = unwrap_engine(ctx)->wrapSprite(doc);
ASSERT(sprWrap);
ImageWrap* imgWrap = sprWrap->activeImage();
if (imgWrap != nullptr) {
ctx.newObject("Image", imgWrap, nullptr);
return;
}
}
else
ctx.pushNull();
return 1;
ctx.pushNull();
}
script::result_t App_get_pixelColor(script::ContextHandle handle)
void App_get_pixelColor(script::ContextHandle handle)
{
script::Context ctx(handle);
ctx.pushObject();
ctx.registerFuncs(-1, pixelColor_methods);
return 1;
ctx.newObject("PixelColor", nullptr, nullptr);
}
script::result_t App_get_version(script::ContextHandle handle)
void App_get_version(script::ContextHandle handle)
{
script::Context ctx(handle);
ctx.pushString(VERSION);
return 1;
}
const script::FunctionEntry App_methods[] = {
{ "open", App_open, 1 },
{ "exit", App_exit, 1 },
{ "exit", App_exit, 0 },
{ nullptr, nullptr, 0 }
};
const script::PropertyEntry App_props[] = {
{ "activeImage", App_get_activeImage, nullptr },
{ "activeSprite", App_get_activeSprite, nullptr },
{ "activeImage", App_get_activeImage, nullptr },
{ "pixelColor", App_get_pixelColor, nullptr },
{ "version", App_get_version, nullptr },
{ nullptr, nullptr, 0 }

View File

@ -1,21 +0,0 @@
// Aseprite
// Copyright (C) 2015-2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifndef APP_SCRIPT_APP_OBJECT_H_INCLUDED
#define APP_SCRIPT_APP_OBJECT_H_INCLUDED
#pragma once
namespace script {
class Context;
}
namespace app {
void register_app_object(script::Context& ctx);
} // namespace app
#endif

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2016 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -11,12 +11,7 @@
#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/selection_class.h"
#include "app/script/sprite_class.h"
#include "app/script/sprite_wrap.h"
namespace app {
@ -32,29 +27,46 @@ const script::ConstantEntry ColorMode_constants[] = {
}
void register_app_object(script::Context& ctx);
void register_console_object(script::Context& ctx);
void register_image_class(script::index_t idx, script::Context& ctx);
void register_pixel_color_class(script::index_t idx, script::Context& ctx);
void register_point_class(script::index_t idx, script::Context& ctx);
void register_rectangle_class(script::index_t idx, script::Context& ctx);
void register_selection_class(script::index_t idx, script::Context& ctx);
void register_size_class(script::index_t idx, script::Context& ctx);
void register_sprite_class(script::index_t idx, script::Context& ctx);
AppScripting::AppScripting(script::EngineDelegate* delegate)
: script::Engine(delegate)
{
auto& ctx = context();
ctx.setContextUserData(this);
// Register global objects (app and console)
register_app_object(ctx);
register_console_object(ctx);
ctx.pushGlobalObject();
// Register constants
{
script::index_t obj = ctx.pushObject();
ctx.registerConstants(obj, ColorMode_constants);
ctx.newObject();
ctx.registerConstants(-1, ColorMode_constants);
ctx.setProp(-2, "ColorMode");
}
// Register classes/prototypes
register_image_class(-1, ctx);
register_sprite_class(-1, ctx);
register_pixel_color_class(-1, ctx);
register_point_class(-1, ctx);
register_rectangle_class(-1, ctx);
register_selection_class(-1, ctx);
register_size_class(-1, ctx);
register_sprite_class(-1, ctx);
ctx.pushPointer(this);
ctx.setProp(-2, script::kPtrId);
ctx.pop();
ctx.pop(1);
}
SpriteWrap* AppScripting::wrapSprite(app::Document* doc)
@ -88,11 +100,7 @@ void AppScripting::destroyWrappers()
AppScripting* unwrap_engine(script::Context& ctx)
{
ctx.pushGlobalObject();
ctx.getProp(-1, script::kPtrId);
void* ptr = ctx.getPointer(-1);
ctx.pop(2);
return (AppScripting*)ptr;
return (AppScripting*)ctx.getContextUserData();
}
}

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2016 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -13,6 +13,7 @@
#endif
#include "doc/object_id.h"
#include "gfx/fwd.h"
#include "script/engine.h"
#include <map>
@ -39,12 +40,20 @@ namespace app {
private:
void destroyWrappers();
Sprites m_sprites;
};
AppScripting* unwrap_engine(script::Context& ctx);
void push_new_point(script::Context& ctx, const gfx::Point& pt);
void push_new_rectangle(script::Context& ctx, const gfx::Rect& rc);
void push_new_size(script::Context& ctx, const gfx::Size& rc);
void push_new_selection(script::Context& ctx, SpriteWrap* spriteWrap);
gfx::Point convert_args_into_point(script::Context& ctx);
gfx::Rect convert_args_into_rectangle(script::Context& ctx);
gfx::Size convert_args_into_size(script::Context& ctx);
} // namespace app
#endif

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2016 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -8,8 +8,6 @@
#include "config.h"
#endif
#include "app/script/console_object.h"
#include "app/app.h"
#include "app/console.h"
#include "script/engine.h"
@ -31,19 +29,31 @@ void print(const char* str)
}
}
script::result_t Console_assert(script::ContextHandle handle)
void Console_assert(script::ContextHandle handle)
{
script::Context ctx(handle);
if (!ctx.toBool(0))
print(ctx.toString(1));
return 0;
if (!ctx.toBool(1))
ctx.error(ctx.toString(1));
ctx.pushUndefined();
}
script::result_t Console_log(script::ContextHandle handle)
void Console_log(script::ContextHandle handle)
{
script::Context ctx(handle);
print(ctx.toString(0));
return 0;
std::string output;
int top = ctx.top();
const char* s;
for (int n=1; n<top; ++n) {
s = ctx.toString(n);
if (s == nullptr)
break;
if (n > 1)
output += " ";
output += s;
}
if (!output.empty())
print(output.c_str());
ctx.pushUndefined();
}
const script::FunctionEntry Console_methods[] = {

View File

@ -1,21 +0,0 @@
// Aseprite
// Copyright (C) 2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifndef APP_SCRIPT_CONSOLE_OBJECT_H_INCLUDED
#define APP_SCRIPT_CONSOLE_OBJECT_H_INCLUDED
#pragma once
namespace script {
class Context;
}
namespace app {
void register_console_object(script::Context& ctx);
} // namespace app
#endif

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2015-2016 David Capello
// Copyright (C) 2015-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -8,74 +8,71 @@
#include "config.h"
#endif
#include "app/script/image_class.h"
#include "app/script/image_wrap.h"
#include "doc/image.h"
#include "script/engine.h"
namespace app {
namespace {
script::result_t Image_ctor(script::ContextHandle handle)
{
return 0;
}
const char* kTag = "Image";
script::result_t Image_putPixel(script::ContextHandle handle)
void Image_new(script::ContextHandle handle)
{
script::Context ctx(handle);
int x = ctx.requireInt(0);
int y = ctx.requireInt(1);
doc::color_t color = ctx.requireUInt(2);
ctx.pushNull(); // TODO
}
void Image_putPixel(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (ImageWrap*)ctx.toUserData(0, kTag);
int x = ctx.requireInt(1);
int y = ctx.requireInt(2);
doc::color_t color = ctx.requireUInt(3);
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;
ctx.pushUndefined();
}
script::result_t Image_getPixel(script::ContextHandle handle)
void Image_getPixel(script::ContextHandle handle)
{
script::Context ctx(handle);
int x = ctx.requireInt(0);
int y = ctx.requireInt(1);
auto wrap = (ImageWrap*)ctx.toUserData(0, kTag);
int x = ctx.requireInt(1);
int y = ctx.requireInt(2);
auto wrap = (ImageWrap*)ctx.getThis();
if (wrap) {
doc::color_t color = wrap->image()->getPixel(x, y);
ctx.pushUInt(color);
return 1;
}
else
return 0;
ctx.pushUndefined();
}
script::result_t Image_get_width(script::ContextHandle handle)
void Image_get_width(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (ImageWrap*)ctx.getThis();
if (wrap) {
auto wrap = (ImageWrap*)ctx.toUserData(0, kTag);
if (wrap)
ctx.pushInt(wrap->image()->width());
return 1;
}
else
return 0;
ctx.pushUndefined();
}
script::result_t Image_get_height(script::ContextHandle handle)
void Image_get_height(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (ImageWrap*)ctx.getThis();
if (wrap) {
auto wrap = (ImageWrap*)ctx.toUserData(0, kTag);
if (wrap)
ctx.pushInt(wrap->image()->height());
return 1;
}
else
return 0;
ctx.pushUndefined();
}
const script::FunctionEntry Image_methods[] = {
@ -94,7 +91,9 @@ const script::PropertyEntry Image_props[] = {
void register_image_class(script::index_t idx, script::Context& ctx)
{
ctx.registerClass(idx, "Image", Image_ctor, 0, Image_methods, Image_props);
ctx.registerClass(idx, kTag,
Image_new, 0,
Image_methods, Image_props);
}
} // namespace app

View File

@ -1,19 +0,0 @@
// Aseprite
// Copyright (C) 2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#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

@ -1,85 +0,0 @@
// Aseprite
// Copyright (C) 2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#include "doc/color.h"
namespace {
script::result_t pixelColor_rgba(script::ContextHandle handle)
{
script::Context ctx(handle);
int r = ctx.requireInt(0);
int g = ctx.requireInt(1);
int b = ctx.requireInt(2);
int a = (ctx.isUndefined(3) ? 255: ctx.requireInt(3));
ctx.pushUInt(doc::rgba(r, g, b, a));
return 1;
}
script::result_t pixelColor_rgbaR(script::ContextHandle handle)
{
script::Context ctx(handle);
ctx.pushUInt(doc::rgba_getr(ctx.requireUInt(0)));
return 1;
}
script::result_t pixelColor_rgbaG(script::ContextHandle handle)
{
script::Context ctx(handle);
ctx.pushUInt(doc::rgba_getg(ctx.requireUInt(0)));
return 1;
}
script::result_t pixelColor_rgbaB(script::ContextHandle handle)
{
script::Context ctx(handle);
ctx.pushUInt(doc::rgba_getb(ctx.requireUInt(0)));
return 1;
}
script::result_t pixelColor_rgbaA(script::ContextHandle handle)
{
script::Context ctx(handle);
ctx.pushUInt(doc::rgba_geta(ctx.requireUInt(0)));
return 1;
}
script::result_t pixelColor_graya(script::ContextHandle handle)
{
script::Context ctx(handle);
int v = ctx.requireInt(0);
int a = (ctx.isUndefined(1) ? 255: ctx.requireInt(1));
ctx.pushUInt(doc::graya(v, a));
return 1;
}
script::result_t pixelColor_grayaV(script::ContextHandle handle)
{
script::Context ctx(handle);
ctx.pushUInt(doc::graya_getv(ctx.requireUInt(0)));
return 1;
}
script::result_t pixelColor_grayaA(script::ContextHandle handle)
{
script::Context ctx(handle);
ctx.pushUInt(doc::graya_geta(ctx.requireUInt(0)));
return 1;
}
const script::FunctionEntry pixelColor_methods[] = {
{ "rgba", pixelColor_rgba, 4 },
{ "rgbaR", pixelColor_rgbaR, 1 },
{ "rgbaG", pixelColor_rgbaG, 1 },
{ "rgbaB", pixelColor_rgbaB, 1 },
{ "rgbaA", pixelColor_rgbaA, 1 },
{ "graya", pixelColor_graya, 2 },
{ "grayaV", pixelColor_grayaV, 1 },
{ "grayaA", pixelColor_grayaA, 1 },
{ nullptr, nullptr, 0 }
};
} // anonymous namespace

View File

@ -0,0 +1,101 @@
// Aseprite
// Copyright (C) 2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "doc/color.h"
#include "script/engine.h"
namespace app {
namespace {
const char* kTag = "PixelColor";
void PixelColor_new(script::ContextHandle handle)
{
script::Context ctx(handle);
ctx.pushUndefined(); // Cannot create new pixel colors (just subobject of "app")
}
void PixelColor_rgba(script::ContextHandle handle)
{
script::Context ctx(handle);
const int r = ctx.requireUInt(1);
const int g = ctx.requireUInt(2);
const int b = ctx.requireUInt(3);
const int a = (ctx.isUndefined(4) ? 255: ctx.requireUInt(4));
ctx.pushUInt(doc::rgba(r, g, b, a));
}
void PixelColor_rgbaR(script::ContextHandle handle)
{
script::Context ctx(handle);
ctx.pushUInt(doc::rgba_getr(ctx.requireUInt(1)));
}
void PixelColor_rgbaG(script::ContextHandle handle)
{
script::Context ctx(handle);
ctx.pushUInt(doc::rgba_getg(ctx.requireUInt(1)));
}
void PixelColor_rgbaB(script::ContextHandle handle)
{
script::Context ctx(handle);
ctx.pushUInt(doc::rgba_getb(ctx.requireUInt(1)));
}
void PixelColor_rgbaA(script::ContextHandle handle)
{
script::Context ctx(handle);
ctx.pushUInt(doc::rgba_geta(ctx.requireUInt(1)));
}
void PixelColor_graya(script::ContextHandle handle)
{
script::Context ctx(handle);
int v = ctx.requireUInt(1);
int a = (ctx.isUndefined(2) ? 255: ctx.requireUInt(2));
ctx.pushUInt(doc::graya(v, a));
}
void PixelColor_grayaV(script::ContextHandle handle)
{
script::Context ctx(handle);
ctx.pushUInt(doc::graya_getv(ctx.requireUInt(1)));
}
void PixelColor_grayaA(script::ContextHandle handle)
{
script::Context ctx(handle);
ctx.pushUInt(doc::graya_geta(ctx.requireUInt(1)));
}
const script::FunctionEntry PixelColor_methods[] = {
{ "rgba", PixelColor_rgba, 4 },
{ "rgbaR", PixelColor_rgbaR, 1 },
{ "rgbaG", PixelColor_rgbaG, 1 },
{ "rgbaB", PixelColor_rgbaB, 1 },
{ "rgbaA", PixelColor_rgbaA, 1 },
{ "graya", PixelColor_graya, 2 },
{ "grayaV", PixelColor_grayaV, 1 },
{ "grayaA", PixelColor_grayaA, 1 },
{ nullptr, nullptr, 0 }
};
} // anonymous namespace
void register_pixel_color_class(script::index_t idx, script::Context& ctx)
{
ctx.registerClass(idx, kTag,
PixelColor_new, 0,
PixelColor_methods, nullptr);
}
} // namespace app

View File

@ -0,0 +1,118 @@
// Aseprite
// Copyright (C) 2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gfx/point.h"
#include "script/engine.h"
namespace app {
namespace {
const char* kTag = "Point";
void Point_finalize(script::ContextHandle handle, void* data)
{
auto pt = (gfx::Point*)data;
delete pt;
}
void Point_new(script::ContextHandle handle)
{
script::Context ctx(handle);
auto pt = new gfx::Point(0, 0);
// Copy other rectangle
if (ctx.isUserData(1, kTag)) {
auto pt2 = (gfx::Point*)ctx.toUserData(1, kTag);
*pt = *pt2;
}
// Convert { x, y } into a Point
else if (ctx.isObject(1)) {
ctx.getProp(1, "x");
ctx.getProp(1, "y");
pt->x = ctx.toInt(-2);
pt->y = ctx.toInt(-1);
ctx.pop(2);
}
else if (ctx.isNumber(1)) {
pt->x = ctx.toInt(1);
pt->y = ctx.toInt(2);
}
ctx.newObject(kTag, pt, Point_finalize);
}
void Point_get_x(script::ContextHandle handle)
{
script::Context ctx(handle);
auto pt = (gfx::Point*)ctx.toUserData(0, kTag);
ASSERT(pt);
ctx.pushInt(pt->x);
}
void Point_get_y(script::ContextHandle handle)
{
script::Context ctx(handle);
auto pt = (gfx::Point*)ctx.toUserData(0, kTag);
ctx.pushInt(pt->y);
}
void Point_set_x(script::ContextHandle handle)
{
script::Context ctx(handle);
auto pt = (gfx::Point*)ctx.toUserData(0, kTag);
ASSERT(pt);
pt->x = ctx.toInt(1);
}
void Point_set_y(script::ContextHandle handle)
{
script::Context ctx(handle);
auto pt = (gfx::Point*)ctx.toUserData(0, kTag);
pt->y = ctx.toInt(1);
}
const script::FunctionEntry Point_methods[] = {
{ nullptr, nullptr, 0 }
};
const script::PropertyEntry Point_props[] = {
{ "x", Point_get_x, Point_set_x },
{ "y", Point_get_y, Point_set_y },
{ nullptr, nullptr, 0 }
};
} // anonymous namespace
void register_point_class(script::index_t idx, script::Context& ctx)
{
ctx.registerClass(idx, kTag,
Point_new, 3,
Point_methods,
Point_props);
}
void push_new_point(script::Context& ctx, const gfx::Point& pt)
{
ctx.newObject(kTag, new gfx::Point(pt), Point_finalize);
}
gfx::Point convert_args_into_point(script::Context& ctx)
{
gfx::Point result;
Point_new(ctx.handle());
auto pt = (gfx::Point*)ctx.toUserData(-1, kTag);
if (pt)
result = *pt;
ctx.pop(1);
return result;
}
} // namespace app

View File

@ -0,0 +1,158 @@
// Aseprite
// Copyright (C) 2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gfx/rect.h"
#include "script/engine.h"
namespace app {
namespace {
const char* kTag = "Rectangle";
void Rectangle_finalize(script::ContextHandle handle, void* data)
{
auto rc = (gfx::Rect*)data;
delete rc;
}
void Rectangle_new(script::ContextHandle handle)
{
script::Context ctx(handle);
auto rc = new gfx::Rect(0, 0, 0, 0);
// Copy other rectangle
if (ctx.isUserData(1, kTag)) {
auto rc2 = (gfx::Rect*)ctx.toUserData(1, kTag);
*rc = *rc2;
}
// Convert { x, y, width, height } into a Rectangle
else if (ctx.isObject(1)) {
ctx.getProp(1, "x");
ctx.getProp(1, "y");
ctx.getProp(1, "width");
ctx.getProp(1, "height");
rc->x = ctx.toInt(-4);
rc->y = ctx.toInt(-3);
rc->w = ctx.toInt(-2);
rc->h = ctx.toInt(-1);
ctx.pop(4);
}
else if (ctx.isNumber(1)) {
rc->x = ctx.toInt(1);
rc->y = ctx.toInt(2);
rc->w = ctx.toInt(3);
rc->h = ctx.toInt(4);
}
ctx.newObject(kTag, rc, Rectangle_finalize);
}
void Rectangle_get_x(script::ContextHandle handle)
{
script::Context ctx(handle);
auto rc = (gfx::Rect*)ctx.toUserData(0, kTag);
ASSERT(rc);
ctx.pushInt(rc->x);
}
void Rectangle_get_y(script::ContextHandle handle)
{
script::Context ctx(handle);
auto rc = (gfx::Rect*)ctx.toUserData(0, kTag);
ctx.pushInt(rc->y);
}
void Rectangle_get_width(script::ContextHandle handle)
{
script::Context ctx(handle);
auto rc = (gfx::Rect*)ctx.toUserData(0, kTag);
ASSERT(rc);
ctx.pushInt(rc->w);
}
void Rectangle_get_height(script::ContextHandle handle)
{
script::Context ctx(handle);
auto rc = (gfx::Rect*)ctx.toUserData(0, kTag);
ASSERT(rc);
ctx.pushInt(rc->h);
}
void Rectangle_set_x(script::ContextHandle handle)
{
script::Context ctx(handle);
auto rc = (gfx::Rect*)ctx.toUserData(0, kTag);
ASSERT(rc);
rc->x = ctx.toInt(1);
}
void Rectangle_set_y(script::ContextHandle handle)
{
script::Context ctx(handle);
auto rc = (gfx::Rect*)ctx.toUserData(0, kTag);
rc->y = ctx.toInt(1);
}
void Rectangle_set_width(script::ContextHandle handle)
{
script::Context ctx(handle);
auto rc = (gfx::Rect*)ctx.toUserData(0, kTag);
ASSERT(rc);
rc->w = ctx.toInt(1);
}
void Rectangle_set_height(script::ContextHandle handle)
{
script::Context ctx(handle);
auto rc = (gfx::Rect*)ctx.toUserData(0, kTag);
ASSERT(rc);
rc->h = ctx.toInt(1);
}
const script::FunctionEntry Rectangle_methods[] = {
{ nullptr, nullptr, 0 }
};
const script::PropertyEntry Rectangle_props[] = {
{ "x", Rectangle_get_x, Rectangle_set_x },
{ "y", Rectangle_get_y, Rectangle_set_y },
{ "width", Rectangle_get_width, Rectangle_set_width },
{ "height", Rectangle_get_height, Rectangle_set_height },
{ nullptr, nullptr, 0 }
};
} // anonymous namespace
void register_rectangle_class(script::index_t idx, script::Context& ctx)
{
ctx.registerClass(idx, kTag,
Rectangle_new, 3,
Rectangle_methods,
Rectangle_props);
}
void push_new_rectangle(script::Context& ctx, const gfx::Rect& rc)
{
ctx.newObject(kTag, new gfx::Rect(rc), Rectangle_finalize);
}
gfx::Rect convert_args_into_rectangle(script::Context& ctx)
{
gfx::Rect result;
Rectangle_new(ctx.handle());
auto rc = (gfx::Rect*)ctx.toUserData(-1, kTag);
if (rc)
result = *rc;
ctx.pop(1);
return result;
}
} // namespace app

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2015-2016 David Capello
// Copyright (C) 2015-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -8,14 +8,14 @@
#include "config.h"
#endif
#include "app/script/selection_class.h"
#include "app/cmd/deselect_mask.h"
#include "app/cmd/set_mask.h"
#include "app/document.h"
#include "app/script/app_scripting.h"
#include "app/script/sprite_wrap.h"
#include "app/transaction.h"
#include "doc/mask.h"
#include "script/engine.h"
namespace app {
@ -23,86 +23,125 @@ using namespace doc;
namespace {
script::result_t Selection_ctor(script::ContextHandle handle)
const char* kTag = "Selection";
struct MaskWrap {
Mask* mask;
SpriteWrap* sprite;
MaskWrap(Mask* mask, SpriteWrap* sprite)
: mask(mask)
, sprite(sprite) { }
};
void Selection_finalize(script::ContextHandle handle, void* data)
{
return 0;
auto wrap = (MaskWrap*)data;
delete wrap;
}
script::result_t Selection_select(script::ContextHandle handle)
void Selection_new(script::ContextHandle handle)
{
script::Context ctx(handle);
int x = ctx.requireInt(0);
int y = ctx.requireInt(1);
int w = ctx.requireInt(2);
int h = ctx.requireInt(3);
auto wrap = (SpriteWrap*)ctx.getThis();
if (wrap) {
Document* doc = wrap->document();
Mask newMask;
if (w > 0 && h > 0)
newMask.replace(gfx::Rect(x, y, w, h));
wrap->transaction().execute(new cmd::SetMask(doc, &newMask));
}
return 0;
ctx.newObject(kTag, new MaskWrap(new Mask, nullptr), Selection_finalize);
}
script::result_t Selection_selectAll(script::ContextHandle handle)
void Selection_deselect(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (SpriteWrap*)ctx.getThis();
auto wrap = (MaskWrap*)ctx.toUserData(0, kTag);
if (wrap) {
Document* doc = wrap->document();
Mask newMask;
newMask.replace(doc->sprite()->bounds());
wrap->transaction().execute(new cmd::SetMask(doc, &newMask));
}
return 0;
}
script::result_t Selection_deselect(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (SpriteWrap*)ctx.getThis();
if (wrap) {
Document* doc = wrap->document();
wrap->transaction().execute(new cmd::DeselectMask(doc));
}
return 0;
}
script::result_t Selection_get_bounds(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (SpriteWrap*)ctx.getThis();
if (wrap) {
Document* doc = wrap->document();
if (doc->isMaskVisible()) {
gfx::Rect bounds = doc->mask()->bounds();
script::index_t obj = ctx.pushObject();
ctx.pushNumber(bounds.x); ctx.setProp(obj, "x");
ctx.pushNumber(bounds.y); ctx.setProp(obj, "y");
ctx.pushNumber(bounds.w); ctx.setProp(obj, "width");
ctx.pushNumber(bounds.h); ctx.setProp(obj, "height");
return 1;
if (wrap->sprite) {
Document* doc = wrap->sprite->document();
ASSERT(doc);
wrap->sprite->transaction().execute(
new cmd::DeselectMask(doc));
}
else {
ASSERT(wrap->mask);
wrap->mask->clear();
}
}
return 0;
ctx.pushUndefined();
}
void Selection_select(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (MaskWrap*)ctx.toUserData(0, kTag);
gfx::Rect bounds = convert_args_into_rectangle(ctx);
if (wrap) {
if (bounds.isEmpty()) {
Selection_deselect(handle);
return;
}
else {
if (wrap->sprite) {
Mask newMask;
newMask.replace(bounds);
wrap->sprite->transaction().execute(
new cmd::SetMask(wrap->sprite->document(), &newMask));
}
else {
wrap->mask->replace(bounds);
}
}
}
ctx.pushUndefined();
}
void Selection_selectAll(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (MaskWrap*)ctx.toUserData(0, kTag);
if (wrap) {
if (wrap->sprite) {
Document* doc = wrap->sprite->document();
Mask newMask;
newMask.replace(doc->sprite()->bounds());
wrap->sprite->transaction().execute(
new cmd::SetMask(doc, &newMask));
}
else {
gfx::Rect bounds = wrap->mask->bounds();
if (!bounds.isEmpty())
wrap->mask->replace(bounds);
}
}
ctx.pushUndefined();
}
void Selection_get_bounds(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (MaskWrap*)ctx.toUserData(0, kTag);
if (wrap) {
if (wrap->sprite) {
Document* doc = wrap->sprite->document();
if (doc->isMaskVisible())
push_new_rectangle(ctx, doc->mask()->bounds());
else // Empty rectangle
push_new_rectangle(ctx, gfx::Rect(0, 0, 0, 0));
}
else {
push_new_rectangle(ctx, wrap->mask->bounds());
}
}
else
ctx.pushUndefined();
}
const script::FunctionEntry Selection_methods[] = {
{ "deselect", Selection_deselect, 1 },
{ "select", Selection_select, 4 },
{ "selectAll", Selection_selectAll, 0 },
{ "deselect", Selection_deselect, 1 },
{ nullptr, nullptr, 0 }
};
@ -115,7 +154,15 @@ const script::PropertyEntry Selection_props[] = {
void register_selection_class(script::index_t idx, script::Context& ctx)
{
ctx.registerClass(idx, "Selection", Selection_ctor, 3, Selection_methods, Selection_props);
ctx.registerClass(idx, kTag,
Selection_new, 3,
Selection_methods,
Selection_props);
}
void push_new_selection(script::Context& ctx, SpriteWrap* spriteWrap)
{
ctx.newObject(kTag, new MaskWrap(nullptr, spriteWrap), Selection_finalize);
}
} // namespace app

View File

@ -1,19 +0,0 @@
// Aseprite
// Copyright (C) 2015-2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifndef APP_SCRIPT_SELECTION_CLASS_H_INCLUDED
#define APP_SCRIPT_SELECTION_CLASS_H_INCLUDED
#pragma once
#include "script/engine.h"
namespace app {
void register_selection_class(script::index_t idx, script::Context& ctx);
} // namespace app
#endif

View File

@ -0,0 +1,120 @@
// Aseprite
// Copyright (C) 2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gfx/size.h"
#include "script/engine.h"
namespace app {
namespace {
const char* kTag = "Size";
void Size_finalize(script::ContextHandle handle, void* data)
{
auto sz = (gfx::Size*)data;
delete sz;
}
void Size_new(script::ContextHandle handle)
{
script::Context ctx(handle);
auto sz = new gfx::Size(0, 0);
// Copy other size
if (ctx.isUserData(1, kTag)) {
auto sz2 = (gfx::Size*)ctx.toUserData(1, kTag);
*sz = *sz2;
}
// Convert { width, height } into a Size
else if (ctx.isObject(1)) {
ctx.getProp(1, "width");
ctx.getProp(1, "height");
sz->w = ctx.toInt(-2);
sz->h = ctx.toInt(-1);
ctx.pop(4);
}
else if (ctx.isNumber(1)) {
sz->w = ctx.toInt(1);
sz->h = ctx.toInt(2);
}
ctx.newObject(kTag, sz, Size_finalize);
}
void Size_get_width(script::ContextHandle handle)
{
script::Context ctx(handle);
auto sz = (gfx::Size*)ctx.toUserData(0, kTag);
ASSERT(sz);
ctx.pushInt(sz->w);
}
void Size_get_height(script::ContextHandle handle)
{
script::Context ctx(handle);
auto sz = (gfx::Size*)ctx.toUserData(0, kTag);
ASSERT(sz);
ctx.pushInt(sz->h);
}
void Size_set_width(script::ContextHandle handle)
{
script::Context ctx(handle);
auto sz = (gfx::Size*)ctx.toUserData(0, kTag);
ASSERT(sz);
sz->w = ctx.toInt(1);
}
void Size_set_height(script::ContextHandle handle)
{
script::Context ctx(handle);
auto sz = (gfx::Size*)ctx.toUserData(0, kTag);
ASSERT(sz);
sz->h = ctx.toInt(1);
}
const script::FunctionEntry Size_methods[] = {
{ nullptr, nullptr, 0 }
};
const script::PropertyEntry Size_props[] = {
{ "width", Size_get_width, Size_set_width },
{ "height", Size_get_height, Size_set_height },
{ nullptr, nullptr, 0 }
};
} // anonymous namespace
void register_size_class(script::index_t idx, script::Context& ctx)
{
ctx.registerClass(idx, kTag,
Size_new, 3,
Size_methods,
Size_props);
}
void push_new_size(script::Context& ctx, const gfx::Size& sz)
{
ctx.newObject(kTag, new gfx::Size(sz), Size_finalize);
}
gfx::Size convert_args_into_size(script::Context& ctx)
{
gfx::Size result;
Size_new(ctx.handle());
auto sz = (gfx::Size*)ctx.toUserData(-1, kTag);
if (sz)
result = *sz;
ctx.pop(1);
return result;
}
} // namespace app

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2015-2016 David Capello
// Copyright (C) 2015-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -8,8 +8,6 @@
#include "config.h"
#endif
#include "app/script/sprite_class.h"
#include "app/cmd/set_sprite_size.h"
#include "app/commands/commands.h"
#include "app/commands/params.h"
@ -31,66 +29,62 @@ namespace app {
namespace {
script::result_t Sprite_ctor(script::ContextHandle handle)
const char* kTag = "Sprite";
void Sprite_new(script::ContextHandle handle)
{
script::Context ctx(handle);
if (ctx.isConstructorCall()) {
int w = ctx.requireInt(0);
int h = ctx.requireInt(1);
int colorMode = (ctx.isUndefined(2) ? IMAGE_RGB: ctx.requireInt(2));
int w = ctx.requireInt(1);
int h = ctx.requireInt(2);
int colorMode = (ctx.isUndefined(3) ? IMAGE_RGB: ctx.requireInt(3));
base::UniquePtr<Sprite> sprite(
Sprite::createBasicSprite((doc::PixelFormat)colorMode, w, h, 256));
base::UniquePtr<Document> doc(new Document(sprite));
sprite.release();
base::UniquePtr<Sprite> sprite(
Sprite::createBasicSprite((doc::PixelFormat)colorMode, w, h, 256));
base::UniquePtr<Document> doc(new Document(sprite));
sprite.release();
doc->setContext(UIContext::instance());
ctx.pushThis(unwrap_engine(ctx)->wrapSprite(doc.release()), "Sprite");
}
return 0;
doc->setContext(UIContext::instance());
ctx.newObject(kTag, unwrap_engine(ctx)->wrapSprite(doc.release()), nullptr);
}
script::result_t Sprite_resize(script::ContextHandle handle)
void Sprite_resize(script::ContextHandle handle)
{
script::Context ctx(handle);
int w = ctx.requireInt(0);
int h = ctx.requireInt(1);
auto wrap = (SpriteWrap*)ctx.toUserData(0, kTag);
gfx::Size size = convert_args_into_size(ctx);
auto wrap = (SpriteWrap*)ctx.getThis();
if (wrap) {
wrap->commitImages();
Document* doc = wrap->document();
DocumentApi api(doc, wrap->transaction());
api.setSpriteSize(doc->sprite(), w, h);
api.setSpriteSize(doc->sprite(), size.w, size.h);
}
return 0;
ctx.pushUndefined();
}
script::result_t Sprite_crop(script::ContextHandle handle)
void Sprite_crop(script::ContextHandle handle)
{
script::Context ctx(handle);
gfx::Rect bounds;
auto wrap = (SpriteWrap*)ctx.toUserData(0, kTag);
auto wrap = (SpriteWrap*)ctx.getThis();
if (wrap) {
wrap->commitImages();
Document* doc = wrap->document();
gfx::Rect bounds;
// Use mask bounds
if (ctx.isUndefined(0)) {
if (ctx.isUndefined(1)) {
if (doc->isMaskVisible())
bounds = doc->mask()->bounds();
else
bounds = doc->sprite()->bounds();
}
else {
bounds.x = ctx.requireInt(0);
bounds.y = ctx.requireInt(1);
bounds.w = ctx.requireInt(2);
bounds.h = ctx.requireInt(3);
bounds = convert_args_into_rectangle(ctx);
}
if (!bounds.isEmpty()) {
@ -99,14 +93,14 @@ script::result_t Sprite_crop(script::ContextHandle handle)
}
}
return 0;
ctx.pushUndefined();
}
script::result_t Sprite_save(script::ContextHandle handle)
void Sprite_save(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (SpriteWrap*)ctx.toUserData(0, kTag);
auto wrap = (SpriteWrap*)ctx.getThis();
if (wrap) {
wrap->commit();
@ -117,16 +111,15 @@ script::result_t Sprite_save(script::ContextHandle handle)
uiCtx->executeCommand(saveCommand);
}
return 0;
ctx.pushUndefined();
}
script::result_t Sprite_saveAs(script::ContextHandle handle)
void Sprite_saveAs(script::ContextHandle handle)
{
script::Context ctx(handle);
const char* fn = ctx.requireString(0);
bool asCopy = ctx.getBool(1);
auto wrap = (SpriteWrap*)ctx.toUserData(0, kTag);
const char* fn = ctx.requireString(1);
auto wrap = (SpriteWrap*)ctx.getThis();
if (fn && wrap) {
wrap->commit();
@ -136,26 +129,47 @@ script::result_t Sprite_saveAs(script::ContextHandle handle)
Command* saveCommand =
CommandsModule::instance()->getCommandByName(
(asCopy ? CommandId::SaveFileCopyAs:
CommandId::SaveFile));
CommandId::SaveFile);
Params params;
if (asCopy)
params.set("filename", fn);
else
doc->setFilename(fn);
doc->setFilename(fn);
uiCtx->executeCommand(saveCommand, params);
}
return 0;
ctx.pushUndefined();
}
script::result_t Sprite_loadPalette(script::ContextHandle handle)
void Sprite_saveCopyAs(script::ContextHandle handle)
{
script::Context ctx(handle);
const char* fn = ctx.requireString(0);
auto wrap = (SpriteWrap*)ctx.toUserData(0, kTag);
const char* fn = ctx.requireString(1);
if (fn && wrap) {
wrap->commit();
auto doc = wrap->document();
auto uiCtx = UIContext::instance();
uiCtx->setActiveDocument(doc);
Command* saveCommand =
CommandsModule::instance()->getCommandByName(
CommandId::SaveFileCopyAs);
Params params;
params.set("filename", fn);
uiCtx->executeCommand(saveCommand, params);
}
ctx.pushUndefined();
}
void Sprite_loadPalette(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (SpriteWrap*)ctx.toUserData(0, kTag);
const char* fn = ctx.toString(1);
auto wrap = (SpriteWrap*)ctx.getThis();
if (fn && wrap) {
auto doc = wrap->document();
base::UniquePtr<doc::Palette> palette(load_palette(fn));
@ -166,75 +180,74 @@ script::result_t Sprite_loadPalette(script::ContextHandle handle)
}
}
return 0;
ctx.pushUndefined();
}
script::result_t Sprite_get_filename(script::ContextHandle handle)
void Sprite_get_filename(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (SpriteWrap*)ctx.getThis();
auto wrap = (SpriteWrap*)ctx.toUserData(0, kTag);
ctx.pushString(wrap->document()->filename().c_str());
return 1;
}
script::result_t Sprite_get_width(script::ContextHandle handle)
void Sprite_get_width(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (SpriteWrap*)ctx.getThis();
auto wrap = (SpriteWrap*)ctx.toUserData(0, kTag);
ctx.pushInt(wrap->sprite()->width());
return 1;
}
script::result_t Sprite_set_width(script::ContextHandle handle)
void Sprite_get_height(script::ContextHandle handle)
{
script::Context ctx(handle);
int w = ctx.requireInt(0);
auto wrap = (SpriteWrap*)ctx.getThis();
auto wrap = (SpriteWrap*)ctx.toUserData(0, kTag);
ctx.pushInt(wrap->sprite()->height());
}
void Sprite_set_width(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (SpriteWrap*)ctx.toUserData(0, kTag);
const int width = ctx.requireInt(1);
wrap->transaction().execute(
new cmd::SetSpriteSize(wrap->sprite(),
w,
width,
wrap->sprite()->height()));
return 0;
ctx.pushUndefined();
}
script::result_t Sprite_get_height(script::ContextHandle handle)
void Sprite_set_height(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (SpriteWrap*)ctx.getThis();
ctx.pushInt(wrap->sprite()->height());
return 1;
}
script::result_t Sprite_get_colorMode(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (SpriteWrap*)ctx.getThis();
ctx.pushInt(wrap->sprite()->pixelFormat());
return 1;
}
script::result_t Sprite_set_height(script::ContextHandle handle)
{
script::Context ctx(handle);
int h = ctx.requireInt(0);
auto wrap = (SpriteWrap*)ctx.getThis();
auto wrap = (SpriteWrap*)ctx.toUserData(0, kTag);
const int height = ctx.requireInt(1);
wrap->transaction().execute(
new cmd::SetSpriteSize(wrap->sprite(),
wrap->sprite()->width(),
h));
return 0;
height));
ctx.pushUndefined();
}
script::result_t Sprite_get_selection(script::ContextHandle handle)
void Sprite_get_colorMode(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (SpriteWrap*)ctx.getThis();
ctx.pushObject(wrap, "Selection");
return 1;
auto wrap = (SpriteWrap*)ctx.toUserData(0, kTag);
ctx.pushInt(wrap->sprite()->pixelFormat());
}
void Sprite_set_colorMode(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (SpriteWrap*)ctx.toUserData(0, kTag);
// TODO
ctx.pushUndefined();
}
void Sprite_get_selection(script::ContextHandle handle)
{
script::Context ctx(handle);
auto wrap = (SpriteWrap*)ctx.toUserData(0, kTag);
push_new_selection(ctx, wrap);
}
const script::FunctionEntry Sprite_methods[] = {
@ -242,6 +255,7 @@ const script::FunctionEntry Sprite_methods[] = {
{ "crop", Sprite_crop, 4 },
{ "save", Sprite_save, 2 },
{ "saveAs", Sprite_saveAs, 2 },
{ "saveCopyAs", Sprite_saveCopyAs, 2 },
{ "loadPalette", Sprite_loadPalette, 1 },
{ nullptr, nullptr, 0 }
};
@ -250,7 +264,7 @@ const script::PropertyEntry Sprite_props[] = {
{ "filename", Sprite_get_filename, nullptr },
{ "width", Sprite_get_width, Sprite_set_width },
{ "height", Sprite_get_height, Sprite_set_height },
{ "colorMode", Sprite_get_colorMode, nullptr },
{ "colorMode", Sprite_get_colorMode, Sprite_set_colorMode },
{ "selection", Sprite_get_selection, nullptr },
{ nullptr, nullptr, 0 }
};
@ -259,7 +273,9 @@ const script::PropertyEntry Sprite_props[] = {
void register_sprite_class(script::index_t idx, script::Context& ctx)
{
ctx.registerClass(idx, "Sprite", Sprite_ctor, 3, Sprite_methods, Sprite_props);
ctx.registerClass(idx, kTag,
Sprite_new, 3,
Sprite_methods, Sprite_props);
}
} // namespace app

View File

@ -1,19 +0,0 @@
// Aseprite
// Copyright (C) 2015-2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifndef APP_SCRIPT_SPRITE_CLASS_H_INCLUDED
#define APP_SCRIPT_SPRITE_CLASS_H_INCLUDED
#pragma once
#include "script/engine.h"
namespace app {
void register_sprite_class(script::index_t idx, script::Context& ctx);
} // namespace app
#endif

View File

@ -132,6 +132,7 @@ bool DevConsoleView::onProcessMessage(Message* msg)
void DevConsoleView::onExecuteCommand(const std::string& cmd)
{
m_engine.printLastResult();
m_engine.eval(cmd);
}

View File

@ -1,15 +1,8 @@
# Aseprite Scripting Library
# Copyright (C) 2015-2016 David Capello
# Copyright (C) 2015-2017 David Capello
include_directories(${DUKTAPE_DIR})
add_library(duktape ${DUKTAPE_DIR}/duktape.c)
add_library(script-lib engine.cpp engine_delegate.cpp)
if(UNIX)
target_link_libraries(duktape m)
endif()
target_link_libraries(script-lib
laf-base
duktape)
mujs)

View File

@ -1,4 +1,4 @@
# Aseprite Scripting Library
*Copyright (C) 2015-2016 David Capello*
*Copyright (C) 2015-2017 David Capello*
> Distributed under [MIT license](LICENSE.txt)

View File

@ -13,324 +13,266 @@
#include "base/convert_to.h"
#include "base/exception.h"
#include "base/file_handle.h"
#include "base/fstream_path.h"
#include "base/memory.h"
#include "script/engine_delegate.h"
#include <map>
#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <duktape.h>
class ScriptEngineException : public base::Exception {
public:
ScriptEngineException(duk_errcode_t code, const char* msg)
: Exception(std::string(msg) + " (code " + base::convert_to<std::string>(code) + ")") {
}
};
extern "C" {
#include <mujs/mujs.h>
}
namespace script {
const char* kPtrId = "\xFF" "\xFF" "ptr";
static const char* stacktrace_js =
"Error.prototype.toString = function() {\n"
" if (this.stackTrace)\n"
" return this.name + ': ' + this.message + this.stackTrace;\n"
" return this.name + ': ' + this.message;\n"
"}";
namespace {
// TODO classes in modules isn't supported yet
std::map<std::string, Module*> g_modules;
void* on_alloc_function(void* udata, duk_size_t size)
void Context::setContextUserData(void* userData)
{
if (size)
return base_malloc(size);
else
return nullptr;
js_setcontext(m_handle, userData);
}
void* on_realloc_function(void* udata, void* ptr, duk_size_t size)
void* Context::getContextUserData()
{
if (!ptr) {
if (size)
return base_malloc(size);
else
return nullptr;
}
else if (!size) {
base_free(ptr);
return nullptr;
}
else
return base_realloc(ptr, size);
return js_getcontext(m_handle);
}
void on_free_function(void* udata, void* ptr)
void Context::error(const char* err)
{
if (ptr)
base_free(ptr);
}
duk_ret_t on_search_module(duk_context* ctx)
{
const char* id = duk_get_string(ctx, 0);
if (!id)
return 0;
auto it = g_modules.find(id);
if (it == g_modules.end()) {
// TODO error module not found
return 0;
}
Module* module = it->second;
Context ctxWrapper(ctx);
if (module->registerModule(ctxWrapper) > 0) {
// Overwrite the 'exports' property of the module (arg 3)
// with the object returned by registerModule()
duk_put_prop_string(ctx, 3, "exports");
}
// 0 means no source code
return 0;
}
void on_fatal_handler(duk_context* ctx, duk_errcode_t code, const char* msg)
{
throw ScriptEngineException(code, msg);
}
}
void Context::dump()
{
duk_push_context_dump(m_handle);
std::cout << duk_to_string(m_handle, -1) << std::endl;
duk_pop(m_handle);
js_error(m_handle, "%s", err);
}
void Context::pop()
{
duk_pop(m_handle);
js_pop(m_handle, 1);
}
void Context::pop(index_t count)
{
duk_pop_n(m_handle, count);
js_pop(m_handle, count);
}
void Context::remove(index_t idx)
{
duk_remove(m_handle, idx);
js_remove(m_handle, idx);
}
void Context::duplicateTop()
{
duk_dup_top(m_handle);
js_dup(m_handle);
}
bool Context::isConstructorCall()
index_t Context::top()
{
return (duk_is_constructor_call(m_handle) ? true: false);
return js_gettop(m_handle);
}
bool Context::isUndefined(index_t i)
{
return (duk_is_undefined(m_handle, i) ? true: false);
return (js_isundefined(m_handle, i) ? true: false);
}
bool Context::isNull(index_t i)
{
return (duk_is_null(m_handle, i) ? true: false);
return (js_isnull(m_handle, i) ? true: false);
}
bool Context::isNullOrUndefined(index_t i)
{
return (duk_is_null_or_undefined(m_handle, i) ? true: false);
return (js_isnull(m_handle, i) ||
js_isundefined(m_handle, i)? true: false);
}
bool Context::isBool(index_t i)
{
return (duk_is_boolean(m_handle, i) ? true: false);
return (js_isboolean(m_handle, i) ? true: false);
}
bool Context::isNumber(index_t i)
{
return (duk_is_number(m_handle, i) ? true: false);
}
bool Context::isNaN(index_t i)
{
return (duk_is_nan(m_handle, i) ? true: false);
return (js_isnumber(m_handle, i) ? true: false);
}
bool Context::isString(index_t i)
{
return (duk_is_string(m_handle, i) ? true: false);
return (js_isstring(m_handle, i) ? true: false);
}
bool Context::getBool(index_t i)
bool Context::isObject(index_t i)
{
return (duk_get_boolean(m_handle, i) ? true: false);
return (js_isobject(m_handle, i) ? true: false);
}
bool Context::isArray(index_t i)
{
return (js_isarray(m_handle, i) ? true: false);
}
bool Context::isUserData(index_t i, const char* tag)
{
return (js_isuserdata(m_handle, i, tag) ? true: false);
}
bool Context::toBool(index_t i)
{
return (duk_to_boolean(m_handle, i) ? true: false);
return (js_toboolean(m_handle, i) ? true: false);
}
double Context::getNumber(index_t i)
double Context::toNumber(index_t i)
{
return duk_get_number(m_handle, i);
return js_tonumber(m_handle, i);
}
int Context::getInt(index_t i)
int Context::toInt(index_t i)
{
return duk_get_int(m_handle, i);
return js_toint32(m_handle, i);
}
unsigned int Context::getUInt(index_t i)
unsigned int Context::toUInt(index_t i)
{
return duk_get_uint(m_handle, i);
}
const char* Context::getString(index_t i)
{
return duk_get_string(m_handle, i);
return js_touint32(m_handle, i);
}
const char* Context::toString(index_t i)
{
return duk_to_string(m_handle, i);
return js_tostring(m_handle, i);
}
void* Context::getPointer(index_t i)
void* Context::toUserData(index_t i, const char* tag)
{
return duk_get_pointer(m_handle, i);
return js_touserdata(m_handle, i, tag);
}
bool Context::requireBool(index_t i)
{
return (duk_require_boolean(m_handle, i) ? true: false);
if (js_isboolean(m_handle, i))
return true;
else {
js_typeerror(m_handle, "not a boolean (index %d)\n", i);
return false;
}
}
double Context::requireNumber(index_t i)
{
return duk_require_number(m_handle, i);
if (js_isnumber(m_handle, i))
return js_tonumber(m_handle, i);
else {
js_typeerror(m_handle, "not a number (index %d)\n", i);
return 0.0;
}
}
int Context::requireInt(index_t i)
{
return duk_require_int(m_handle, i);
return (int)requireNumber(i);
}
unsigned int Context::requireUInt(index_t i)
{
return duk_require_uint(m_handle, i);
return (unsigned int)requireNumber(i);
}
const char* Context::requireString(index_t i)
{
return duk_require_string(m_handle, i);
if (js_isstring(m_handle, i))
return js_tostring(m_handle, i);
else {
js_typeerror(m_handle, "not a string (index %d)\n", i);
return nullptr;
}
}
void* Context::requireObject(index_t i, const char* className)
void* Context::requireUserData(index_t i, const char* tag)
{
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);
return result;
if (js_isuserdata(m_handle, i, tag))
return js_touserdata(m_handle, i, tag);
else {
js_typeerror(m_handle, "not a user data (index %d, tag %s)\n", i, tag);
return nullptr;
}
}
void Context::pushUndefined()
{
duk_push_undefined(m_handle);
js_pushundefined(m_handle);
}
void Context::pushNull()
{
duk_push_null(m_handle);
js_pushnull(m_handle);
}
void Context::pushBool(bool val)
{
duk_push_boolean(m_handle, val);
js_pushboolean(m_handle, val);
}
void Context::pushNumber(double val)
{
duk_push_number(m_handle, val);
}
void Context::pushNaN()
{
duk_push_nan(m_handle);
js_pushnumber(m_handle, val);
}
void Context::pushInt(int val)
{
duk_push_int(m_handle, val);
js_pushnumber(m_handle, double(val));
}
void Context::pushUInt(unsigned int val)
{
duk_push_uint(m_handle, val);
js_pushnumber(m_handle, double(val));
}
void Context::pushString(const char* str)
{
duk_push_string(m_handle, str);
}
void Context::pushThis()
{
duk_push_this(m_handle);
}
void Context::pushThis(void* ptr, const char* className)
{
duk_push_this(m_handle);
duk_push_pointer(m_handle, ptr);
duk_put_prop_string(m_handle, -2, kPtrId);
// TODO classes in modules isn't supported yet
duk_get_global_string(m_handle, className);
duk_get_prototype(m_handle, -1);
duk_set_prototype(m_handle, -3);
duk_pop_2(m_handle);
}
void Context::pushPointer(void* ptr)
{
duk_push_pointer(m_handle, ptr);
}
index_t Context::pushObject()
{
return duk_push_object(m_handle);
}
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, kPtrId);
// TODO classes in modules isn't supported yet
duk_get_global_string(m_handle, className);
duk_get_prototype(m_handle, -1);
duk_set_prototype(m_handle, obj);
duk_pop(m_handle);
return obj;
js_pushstring(m_handle, str);
}
void Context::pushGlobalObject()
{
duk_push_global_object(m_handle);
js_pushglobal(m_handle);
}
void Context::newObject()
{
js_newobject(m_handle);
}
void Context::newObject(const char* className,
void* userData,
FinalizeFunction finalize)
{
js_getglobal(m_handle, className); // class
js_getproperty(m_handle, -1, "prototype"); // class prototype
js_newuserdata(m_handle, className, userData, finalize); // class userdata
js_rot2(m_handle); // userdata class
js_pop(m_handle, 1); // userdata
}
void Context::newUserData(const char* tag,
void* userData,
FinalizeFunction finalize)
{
js_newuserdata(m_handle, tag, userData, finalize);
}
void Context::registerConstants(index_t idx,
const ConstantEntry* consts)
{
duk_put_number_list(m_handle, idx, (const duk_number_list_entry*)consts);
if (idx < 0)
--idx;
for (; consts->id; ++consts) {
js_pushnumber(m_handle, consts->value);
js_defproperty(m_handle, idx, consts->id, JS_DONTENUM);
}
}
void Context::registerProp(index_t idx,
@ -338,27 +280,22 @@ void Context::registerProp(index_t idx,
Function getter,
Function setter)
{
duk_push_string(m_handle, id);
if (idx < 0)
--idx;
idx -= 2;
duk_uint_t flags = 0;
if (getter)
js_newcfunction(m_handle, getter,
(std::string(id) + ".getter").c_str(), 0);
else
js_pushnull(m_handle);
if (getter) {
flags |= DUK_DEFPROP_HAVE_GETTER;
duk_push_c_function(m_handle, getter, 0);
if (idx < 0)
--idx;
}
if (setter)
js_newcfunction(m_handle, setter,
(std::string(id) + ".setter").c_str(), 1);
else
js_pushnull(m_handle);
if (setter) {
flags |= DUK_DEFPROP_HAVE_SETTER;
duk_push_c_function(m_handle, setter, 1);
if (idx < 0)
--idx;
}
duk_def_prop(m_handle, idx, flags);
js_defaccessor(m_handle, idx, id, JS_DONTENUM);
}
void Context::registerProps(index_t idx, const PropertyEntry* props)
@ -376,13 +313,20 @@ void Context::registerFunc(index_t idx,
const Function func,
index_t nargs)
{
duk_push_c_function(m_handle, func, nargs);
duk_put_prop_string(m_handle, idx, id);
js_newcfunction(m_handle, func, id, nargs);
js_defproperty(m_handle, idx, id, JS_DONTENUM);
}
void Context::registerFuncs(index_t idx, const FunctionEntry* methods)
{
duk_put_function_list(m_handle, idx, (const duk_function_list_entry*)methods);
if (idx < 0)
--idx;
for (; methods->id; ++methods) {
registerFunc(idx,
methods->id,
methods->value,
methods->nargs);
}
}
void Context::registerObject(index_t idx,
@ -390,16 +334,13 @@ void Context::registerObject(index_t idx,
const FunctionEntry* methods,
const PropertyEntry* props)
{
duk_push_object(m_handle);
if (idx < 0)
--idx;
if (methods)
registerFuncs(-1, methods);
if (props)
registerProps(-1, props);
duk_put_prop_string(m_handle, idx, id);
newObject();
if (methods) registerFuncs(-1, methods);
if (props) registerProps(-1, props);
js_defproperty(m_handle, idx, id, JS_DONTENUM);
}
void Context::registerClass(index_t idx,
@ -408,63 +349,46 @@ void Context::registerClass(index_t idx,
const FunctionEntry* methods,
const PropertyEntry* props)
{
ASSERT(ctorFunc);
duk_push_c_function(m_handle, ctorFunc, ctorNargs);
if (idx < 0)
idx -= 2;
duk_push_object(m_handle); // Prototype object
if (methods)
duk_put_function_list(m_handle, -1, (const duk_function_list_entry*)methods);
if (props)
registerProps(-1, props);
duk_set_prototype(m_handle, -2);
duk_put_prop_string(m_handle, idx-1, id);
}
void* Context::getThis()
{
duk_push_this(m_handle);
duk_get_prop_string(m_handle, -1, kPtrId);
void* result = (void*)duk_to_pointer(m_handle, -1);
duk_pop_2(m_handle);
return result;
js_getglobal(m_handle, "Object");
js_getproperty(m_handle, -1, "prototype");
js_newuserdata(m_handle, id, nullptr, nullptr);
if (methods) registerFuncs(-1, methods);
if (props) registerProps(-1, props);
js_newcconstructor(m_handle, ctorFunc, ctorFunc, id, ctorNargs);
js_defproperty(m_handle, idx, id, JS_DONTENUM);
js_pop(m_handle, 1); // pop Object
}
bool Context::hasProp(index_t i, const char* propName)
{
return (duk_has_prop_string(m_handle, i, propName) ? true: false);
return (js_hasproperty(m_handle, i, propName) ? true: false);
}
void Context::getProp(index_t i, const char* propName)
{
duk_get_prop_string(m_handle, i, propName);
js_getproperty(m_handle, i, propName);
}
void Context::setProp(index_t i, const char* propName)
{
duk_put_prop_string(m_handle, i, propName);
js_defproperty(m_handle, i, propName, JS_DONTENUM);
}
Engine::Engine(EngineDelegate* delegate)
: m_ctx(duk_create_heap(&on_alloc_function,
&on_realloc_function,
&on_free_function,
(void*)this,
&on_fatal_handler))
: m_ctx(js_newstate(NULL, NULL, JS_STRICT))
, m_delegate(delegate)
, m_printLastResult(false)
{
// Set 'on_search_module' as the function to search modules with
// require('modulename') on JavaScript.
duk_get_global_string(m_ctx.handle(), "Duktape");
duk_push_c_function(m_ctx.handle(), &on_search_module, 4);
duk_put_prop_string(m_ctx.handle(), -2, "modSearch");
duk_pop(m_ctx.handle());
// Pre-scripts
js_dostring(m_ctx.handle(), stacktrace_js);
}
Engine::~Engine()
{
duk_destroy_heap(m_ctx.handle());
js_freestate(m_ctx.handle());
}
void Engine::printLastResult()
@ -472,83 +396,49 @@ void Engine::printLastResult()
m_printLastResult = true;
}
void Engine::eval(const std::string& jsCode)
void Engine::eval(const std::string& jsCode,
const std::string& filename)
{
bool errFlag = true;
onBeforeEval();
try {
ContextHandle handle = m_ctx.handle();
duk_eval_string(handle, jsCode.c_str());
ContextHandle handle = m_ctx.handle();
if (m_printLastResult &&
!duk_is_null_or_undefined(handle, -1)) {
m_delegate->onConsolePrint(duk_safe_to_string(handle, -1));
if (js_ploadstring(handle, filename.c_str(), jsCode.c_str()) == 0) {
js_pushundefined(handle);
if (js_pcall(handle, 0) == 0) {
if (m_printLastResult) {
if (!js_isundefined(handle, -1)) {
const char* result = js_tostring(handle, -1);
if (result)
m_delegate->onConsolePrint(result);
}
}
errFlag = false;
}
}
duk_pop(handle);
errFlag = false;
}
catch (const std::exception& ex) {
std::string err = "Error: ";
err += ex.what();
m_delegate->onConsolePrint(err.c_str());
// Print error message
if (errFlag) {
std::string err;
const char* s = js_trystring(handle, -1, "Error");
if (s)
m_delegate->onConsolePrint(s);
}
js_pop(handle, 1);
onAfterEval(errFlag);
}
void Engine::evalFile(const std::string& file)
void Engine::evalFile(const std::string& filename)
{
bool errFlag = true;
onBeforeEval();
try {
ContextHandle handle = m_ctx.handle();
base::FileHandle fhandle(base::open_file(file, "rb"));
FILE* f = fhandle.get();
if (!f)
return;
if (fseek(f, 0, SEEK_END) < 0)
return;
long sz = ftell(f);
if (sz < 0)
return;
if (fseek(f, 0, SEEK_SET) < 0)
return;
char* buf = (char*)duk_push_fixed_buffer(handle, sz);
ASSERT(buf != nullptr);
if (long(fread(buf, 1, sz, f)) != sz)
return;
fclose(f);
f = nullptr;
duk_push_string(handle, duk_to_string(handle, -1));
duk_eval_raw(handle, nullptr, 0, DUK_COMPILE_EVAL);
if (m_printLastResult &&
!duk_is_null_or_undefined(handle, -1)) {
m_delegate->onConsolePrint(duk_safe_to_string(handle, -1));
}
duk_pop(handle);
errFlag = false;
std::stringstream buf;
{
std::ifstream s(FSTREAM_PATH(filename));
buf << s.rdbuf();
}
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)
{
g_modules[module->id()] = module;
eval(buf.str(), filename);
}
} // namespace script

View File

@ -1,5 +1,5 @@
// Aseprite Scripting Library
// Copyright (c) 2015-2016 David Capello
// Copyright (c) 2015-2017 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -10,7 +10,7 @@
#include <string>
struct duk_hthread;
struct js_State;
namespace script {
class Context;
@ -18,10 +18,9 @@ namespace script {
typedef int result_t;
typedef int index_t;
typedef struct duk_hthread* ContextHandle;
typedef result_t (*Function)(ContextHandle ctx);
extern const char* kPtrId;
typedef js_State* ContextHandle;
typedef void (*Function)(ContextHandle);
typedef void (*FinalizeFunction)(ContextHandle, void*);
struct FunctionEntry {
const char* id;
@ -53,31 +52,33 @@ namespace script {
ContextHandle handle() { return m_handle; }
void dump();
void setContextUserData(void* userData);
void* getContextUserData();
void error(const char* err);
void pop();
void pop(index_t count);
void remove(index_t idx);
void duplicateTop();
bool isConstructorCall();
index_t top();
bool isUndefined(index_t i);
bool isNull(index_t i);
bool isNullOrUndefined(index_t i);
bool isBool(index_t i);
bool isNumber(index_t i);
bool isNaN(index_t i);
bool isString(index_t i);
bool isObject(index_t i);
bool isArray(index_t i);
bool isUserData(index_t i, const char* tag);
bool getBool(index_t i);
bool toBool(index_t i);
double getNumber(index_t i);
int getInt(index_t i);
unsigned int getUInt(index_t i);
const char* getString(index_t i);
double toNumber(index_t i);
int toInt(index_t i);
unsigned int toUInt(index_t i);
const char* toString(index_t i);
void* getPointer(index_t i);
void* getThis();
void* toUserData(index_t i, const char* tag);
bool hasProp(index_t i, const char* propName);
void getProp(index_t i, const char* propName);
@ -88,22 +89,23 @@ namespace script {
int requireInt(index_t i);
unsigned int requireUInt(index_t i);
const char* requireString(index_t i);
void* requireObject(index_t i, const char* className);
void* requireUserData(index_t i, const char* tag);
void pushUndefined();
void pushNull();
void pushBool(bool val);
void pushNumber(double val);
void pushNaN();
void pushInt(int val);
void pushUInt(unsigned int val);
void pushString(const char* str);
void pushThis();
void pushThis(void* ptr, const char* className);
void pushPointer(void* ptr);
index_t pushObject();
index_t pushObject(void* ptr, const char* className);
void pushGlobalObject();
void newObject();
void newObject(const char* className,
void* userData,
FinalizeFunction finalize);
void newUserData(const char* tag,
void* userData,
FinalizeFunction finalize);
void registerConstants(index_t idx,
const ConstantEntry* consts);
@ -139,13 +141,12 @@ namespace script {
~Engine();
void printLastResult();
void eval(const std::string& jsCode);
void evalFile(const std::string& file);
void eval(const std::string& jsCode,
const std::string& filename = std::string());
void evalFile(const std::string& filename);
Context& context() { return m_ctx; }
void registerModule(Module* module);
protected:
virtual void onBeforeEval() { }
virtual void onAfterEval(bool err) { }

View File

@ -124,3 +124,33 @@ target_include_directories(archive_static INTERFACE
if(ENABLE_BENCHMARKS)
add_subdirectory(benchmark)
endif()
# mujs
add_library(mujs
mujs/jsarray.c
mujs/jsboolean.c
mujs/jsbuiltin.c
mujs/jscompile.c
mujs/jsdate.c
mujs/jsdtoa.c
mujs/jsdump.c
mujs/jserror.c
mujs/jsfunction.c
mujs/jsgc.c
mujs/jsintern.c
mujs/jslex.c
mujs/jsmath.c
mujs/jsnumber.c
mujs/jsobject.c
mujs/json.c
mujs/jsparse.c
mujs/jsproperty.c
mujs/jsregexp.c
mujs/jsrun.c
mujs/jsstate.c
mujs/jsstring.c
mujs/jsvalue.c
mujs/regexp.c
mujs/utf.c
mujs/utftype.c)
target_include_directories(mujs PUBLIC .)

1
third_party/mujs vendored Submodule

@ -0,0 +1 @@
Subproject commit 81388eb40d29f10599ac30dde90e683a3c254375