Skip to content

Commit

Permalink
circle code almost works
Browse files Browse the repository at this point in the history
HJfod committed Mar 7, 2023
1 parent 38a546d commit 26cc081
Showing 7 changed files with 55 additions and 60 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -131,6 +131,6 @@ jobs:
with:
token: ${{ secrets.GITHUB_TOKEN }}
files: "${{ env.MOD_NAME }}.geode"
tag: v5.0.0-alpha
name: "Alpha"
prerelease: true
replace: true
5 changes: 3 additions & 2 deletions scripts/Circle.swipe
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@

@version 1.0
@name "Circle Tool"
@input r 1.0 "Radius"
@input r 5.0 "Radius"
@input id 1 "Object ID"
@input count 40 "Object count"

r *= 30.0
pos = getViewCenter()
a = 0
for i in count {
obj = create(id, x = pos.x + cos(a) * r, y = pos.y + sin(a) * r, rotation = a)
create(id, x = pos.x + cos(a) * r, y = pos.y + sin(a) * r, rotation = 360 - a)
a += 360 / count
}
3 changes: 2 additions & 1 deletion src/features/Scripting.cpp
Original file line number Diff line number Diff line change
@@ -198,7 +198,8 @@ class $modify(ScriptingUI, EditorUI) {

auto menu = this->getChildByID("editor-buttons-menu");
if (menu) {
for (auto& file : file::readDirectory("C:/Users/HJfod/Documents/github/GeodeSDK/BetterEdit/scripts")
// C:/Users/HJfod/Documents/github/GeodeSDK/BetterEdit/scripts
for (auto& file : file::readDirectory("K:/GeodeSDK/HJ/BetterEdit/scripts")
.unwrapOr(std::vector<ghc::filesystem::path> {})
) {
auto button = CCMenuItemSpriteExtra::create(
2 changes: 1 addition & 1 deletion src/script/Flow.cpp
Original file line number Diff line number Diff line change
@@ -125,7 +125,7 @@ Result<Rc<Value>> ForInExpr::eval(State& state) {
}
return Ok(ret);
}
else if (auto obj = value->has<Object>()) {
else if (auto obj = value->has<Dict>()) {
// result of last iteration will be the return value
auto ret = Value::rc(NullLit());
for (auto& [na, _] : *obj) {
23 changes: 14 additions & 9 deletions src/script/Ops.cpp
Original file line number Diff line number Diff line change
@@ -124,15 +124,21 @@ Result<Rc<Value>> CallExpr::eval(State& state) {
auto fun = *funp;

std::unordered_map<std::string, Rc<Value>> res;
Dict namedArgs;
for (auto& [name, nexpr] : named) {
GEODE_UNWRAP_INTO(auto val, nexpr->eval(state));
res.insert({ name, val });
if (fun->variadic) {
namedArgs.insert({ name, *val });
}
}
if (fun->variadic) {
res.insert({ "namedArguments", Value::rc(namedArgs) });
}

if (fun->variadic) {
auto i = 0u;
Array positional;
Array named;
for (auto& arg : args) {
if (i < fun->params.size()) {
auto name = fun->params.at(i).first;
@@ -145,7 +151,6 @@ Result<Rc<Value>> CallExpr::eval(State& state) {
}
GEODE_UNWRAP_INTO(auto val, arg->eval(state));
res.insert({ name, val });
named.push_back(*val);
}
else {
GEODE_UNWRAP_INTO(auto val, arg->eval(state));
@@ -155,7 +160,6 @@ Result<Rc<Value>> CallExpr::eval(State& state) {
i += 1;
}
res.insert({ fun->variadic.value(), Value::rc(positional) });
res.insert({ "namedArguments", Value::rc(named) });
}
else {
auto i = 0u;
@@ -265,22 +269,23 @@ Result<Rc<Value>> IndexExpr::eval(State& state) {
}
return Ok(Rc<Value>(new Value(arr.at(ix))));
}
else if (auto robj = value->has<Object>()) {
else if (value->has<Dict>() || value->has<Ref<GameObject>>()) {
auto rix = ixval->has<StrLit>();
if (!rix) {
return Err(
"Attempted to index object with a non-string\n * {} evaluated into {}",
"Attempted to index dictionary or object with a non-string\n * {} evaluated into {}",
index->src(), ixval->typeName()
);
}
if (!robj->count(*rix)) {
return Err("Object has no member '{}'", *rix);
auto mem = value->member(*rix);
if (!mem) {
return Err("Dictionary or object has no member '{}'", *rix);
}
return Ok(Rc<Value>(new Value(robj->at(*rix))));
return Ok(*mem);
}
else {
return Err(
"Attempted to index into a non array or object\n * {} evaluated into {}",
"Attempted to index into a non array, dictionary or object\n * {} evaluated into {}",
expr->src(), value->typeName()
);
}
16 changes: 8 additions & 8 deletions src/script/Parser.hpp
Original file line number Diff line number Diff line change
@@ -252,11 +252,11 @@ namespace script {

struct Value;
using Array = std::vector<Value>;
using Object = std::unordered_map<std::string, Value>;
using Dict = std::unordered_map<std::string, Value>;
struct Value {
std::variant<
NullLit, BoolLit, NumLit, StrLit,
Array, Object, Ref<GameObject>, Rc<const FunExpr>
Array, Dict, Ref<GameObject>, Rc<const FunExpr>
> value;
std::function<void(Value&)> onChange = nullptr;
bool isConst = false;
@@ -523,12 +523,12 @@ namespace script {
bool operator>(Array const& a, Array const b);
bool operator>=(Array const& a, Array const b);

bool operator==(Object const& a, Object const b);
bool operator!=(Object const& a, Object const b);
bool operator<(Object const& a, Object const b);
bool operator<=(Object const& a, Object const b);
bool operator>(Object const& a, Object const b);
bool operator>=(Object const& a, Object const b);
bool operator==(Dict const& a, Dict const b);
bool operator!=(Dict const& a, Dict const b);
bool operator<(Dict const& a, Dict const b);
bool operator<=(Dict const& a, Dict const b);
bool operator>(Dict const& a, Dict const b);
bool operator>=(Dict const& a, Dict const b);

struct Scope final {
State& state;
64 changes: 26 additions & 38 deletions src/script/Value.cpp
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
#include <Geode/loader/Log.hpp>
#include <Geode/binding/FLAlertLayer.hpp>
#include <Geode/binding/EditorUI.hpp>
#include <Geode/binding/LevelEditorLayer.hpp>
#include <random>
#include <fmt/args.h>

@@ -84,7 +85,7 @@ bool Value::truthy() const {
[&](Rc<const FunExpr> const&) {
return true;
},
[&](Object const&) {
[&](Dict const&) {
return true;
},
}, value);
@@ -130,7 +131,7 @@ std::string Value::toString(bool debug) const {
}
return fun->ident.value_or("anonymous function");
},
[&](Object const& obj) {
[&](Dict const& obj) {
std::string res = debug ? "dict(" : "{";
bool first = true;
for (auto& [key, value] : obj) {
@@ -166,7 +167,7 @@ std::string Value::typeName() const {
[&](Array const&) {
return "array";
},
[&](Object const&) {
[&](Dict const&) {
return "dictionary";
},
[&](Ref<GameObject> const&) {
@@ -216,7 +217,7 @@ std::optional<Rc<Value>> Value::member(std::string const& name) {
} break;
}
},
[&](Object& obj) -> std::optional<Rc<Value>> {
[&](Dict& obj) -> std::optional<Rc<Value>> {
if (obj.count(name)) {
return Value::rc(obj.at(name));
}
@@ -344,7 +345,7 @@ Result<Rc<Value>> Value::lit(Lit const& value, State& state) {
return Ok(Value::rc(value, nullptr, true));
},
[&](ObjLit const& obj) -> Result<Rc<Value>> {
Object object;
Dict object;
for (auto& [k, expr] : obj) {
GEODE_UNWRAP_INTO(auto val, expr->eval(state));
object.insert({ k, *val });
@@ -384,7 +385,7 @@ bool script::operator>=(Array const& a, Array const b) {
return true;
}

bool script::operator==(Object const& a, Object const b) {
bool script::operator==(Dict const& a, Dict const b) {
if (a.size() != b.size()) return false;
for (auto const& [k, v] : a) {
if (!b.count(k) || v.value != b.at(k).value) {
@@ -397,23 +398,23 @@ bool script::operator==(Object const& a, Object const b) {
return true;
}

bool script::operator!=(Object const& a, Object const b) {
bool script::operator!=(Dict const& a, Dict const b) {
return !(a == b);
}

bool script::operator<(Object const& a, Object const b) {
bool script::operator<(Dict const& a, Dict const b) {
return false;
}

bool script::operator<=(Object const& a, Object const b) {
bool script::operator<=(Dict const& a, Dict const b) {
return true;
}

bool script::operator>(Object const& a, Object const b) {
bool script::operator>(Dict const& a, Dict const b) {
return false;
}

bool script::operator>=(Object const& a, Object const b) {
bool script::operator>=(Dict const& a, Dict const b) {
return true;
}

@@ -530,41 +531,25 @@ State::State(Rc<Expr> ast, Attrs const& attrs) : ast(ast), attrs(attrs) {
this->push();
auto val = Value::lit(def, *this).unwrap();
this->pop();
val->isConst = false;
this->add(var, val);
}

// lang
this->add("print", builtinFun(
{{ "fmt", std::nullopt }},
{},
"args",
[](State& state) -> Result<Rc<Value>> {
fmt::dynamic_format_arg_store<fmt::format_context> store;
std::vector<Rc<Value>> dyn;
dyn.reserve(state.top().size());
auto args = state.get("args")->has<Array>();
if (!args) {
return Err("Internal Error: args was {}", state.get("args")->typeName());
}
auto named = state.get("namedArguments")->has<Object>();
if (!named) {
return Err("Internal Error: namedArguments was {}", state.get("namedArguments")->typeName());
}
for (auto& va : *args) {
store.push_back(va.toString());
}
for (auto& [na, va] : *named) {
store.push_back(fmt::arg(na.c_str(), va.toString()));
}
try {
// formatting manually to catch errors
auto res = fmt::vformat(state.get("msg")->toString(), store);
log::info("{}", res);
return Ok(Value::rc(res));
}
catch(std::exception& e) {
log::error("Invalid format: {}", e.what());
return Ok(Value::rc(NullLit()));
std::string res = "";
for (auto& arg : *args) {
res += arg.toString();
}
log::info("{}", res);
return Ok(Value::rc(res));
}
));
this->add("error", builtinFun(
@@ -672,7 +657,7 @@ State::State(Rc<Expr> ast, Attrs const& attrs) : ast(ast), attrs(attrs) {
[](State& state) -> Result<Rc<Value>> {
auto pos = LevelEditorLayer::get()->m_objectLayer
->convertToNodeSpace(CCDirector::get()->getWinSize() / 2);
return Ok(Value::rc(Object {
return Ok(Value::rc(Dict {
{ "x", Value(pos.x) },
{ "y", Value(pos.y) },
}));
@@ -693,7 +678,7 @@ State::State(Rc<Expr> ast, Attrs const& attrs) : ast(ast), attrs(attrs) {
{{ "x", std::nullopt }},
[](State& state) -> Result<Rc<Value>> {
if (auto num = state.get("x")->has<NumLit>()) {
return Ok(Value::rc(sin(*num)));
return Ok(Value::rc(sin(*num * 180.f / M_PI)));
}
else {
return Err("sin requires a number, got {}", state.get("x")->typeName());
@@ -704,7 +689,7 @@ State::State(Rc<Expr> ast, Attrs const& attrs) : ast(ast), attrs(attrs) {
{{ "x", std::nullopt }},
[](State& state) -> Result<Rc<Value>> {
if (auto num = state.get("x")->has<NumLit>()) {
return Ok(Value::rc(cos(*num)));
return Ok(Value::rc(cos(*num * 180.f / M_PI)));
}
else {
return Err("cos requires a number, got {}", state.get("x")->typeName());
@@ -715,11 +700,14 @@ State::State(Rc<Expr> ast, Attrs const& attrs) : ast(ast), attrs(attrs) {
{{ "x", std::nullopt }},
[](State& state) -> Result<Rc<Value>> {
if (auto num = state.get("x")->has<NumLit>()) {
return Ok(Value::rc(tan(*num)));
return Ok(Value::rc(tan(*num * 180.f / M_PI)));
}
else {
return Err("tan requires a number, got {}", state.get("x")->typeName());
}
}
));

// constants
this->add("pi", Value::rc(M_PI));
}

0 comments on commit 26cc081

Please sign in to comment.