mirror of
https://github.com/aseprite/aseprite.git
synced 2024-10-04 13:59:46 +00:00
Replace duktape with mujs
Added other classes like Rectangle, Size, and Point.
This commit is contained in:
parent
16520dc384
commit
bcf7efc9bb
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)+
|
||||
|
@ -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/)
|
||||
|
||||
```
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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 }
|
||||
|
@ -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
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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[] = {
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
@ -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
|
101
src/app/script/pixel_color_class.cpp
Normal file
101
src/app/script/pixel_color_class.cpp
Normal 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
|
118
src/app/script/point_class.cpp
Normal file
118
src/app/script/point_class.cpp
Normal 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
|
158
src/app/script/rectangle_class.cpp
Normal file
158
src/app/script/rectangle_class.cpp
Normal 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
|
@ -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
|
||||
|
@ -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
|
120
src/app/script/size_class.cpp
Normal file
120
src/app/script/size_class.cpp
Normal 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
|
@ -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
|
||||
|
@ -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
|
@ -132,6 +132,7 @@ bool DevConsoleView::onProcessMessage(Message* msg)
|
||||
|
||||
void DevConsoleView::onExecuteCommand(const std::string& cmd)
|
||||
{
|
||||
m_engine.printLastResult();
|
||||
m_engine.eval(cmd);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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) { }
|
||||
|
30
third_party/CMakeLists.txt
vendored
30
third_party/CMakeLists.txt
vendored
@ -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
1
third_party/mujs
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 81388eb40d29f10599ac30dde90e683a3c254375
|
Loading…
Reference in New Issue
Block a user