Initial engine repository
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
// Backward-compatible forwarding header. Prefer quickjs_bridge_base.h.
|
||||
#include <frostbite2D/script/quickjs_bridge_base.h>
|
||||
@@ -0,0 +1,151 @@
|
||||
#pragma once
|
||||
|
||||
#include <frostbite2D/2d/actor.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace qjs {
|
||||
class Value;
|
||||
}
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
/**
|
||||
* @brief Basic bridge object between QuickJS and engine Vec2.
|
||||
*/
|
||||
class JsVec2 {
|
||||
public:
|
||||
double x = 0.0;
|
||||
double y = 0.0;
|
||||
|
||||
JsVec2() = default;
|
||||
JsVec2(double xValue, double yValue) : x(xValue), y(yValue) {}
|
||||
explicit JsVec2(const Vec2& value) : x(value.x), y(value.y) {}
|
||||
|
||||
Vec2 toNative() const {
|
||||
return Vec2(static_cast<float>(x), static_cast<float>(y));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Basic bridge base between QuickJS and engine Actor.
|
||||
*
|
||||
* This type only exposes the smallest stable surface that all script-side
|
||||
* Actor wrappers need, so engine bindings and Game-side bindings can share it.
|
||||
*/
|
||||
class JsActor {
|
||||
public:
|
||||
JsActor() : actor_(MakePtr<Actor>()) {}
|
||||
explicit JsActor(Ptr<Actor> actor) : actor_(std::move(actor)) {
|
||||
if (!actor_) {
|
||||
actor_ = MakePtr<Actor>();
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetName() const { return actor_->GetName(); }
|
||||
void SetName(const std::string& name) { actor_->SetName(name); }
|
||||
|
||||
std::shared_ptr<JsVec2> GetPosition() const {
|
||||
return std::make_shared<JsVec2>(actor_->GetPosition());
|
||||
}
|
||||
void SetPosition(const std::shared_ptr<JsVec2>& position) {
|
||||
if (position) {
|
||||
actor_->SetPosition(position->toNative());
|
||||
}
|
||||
}
|
||||
void SetPositionXY(double x, double y) {
|
||||
actor_->SetPosition(static_cast<float>(x), static_cast<float>(y));
|
||||
}
|
||||
|
||||
double GetRotation() const { return actor_->GetRotation(); }
|
||||
void SetRotation(double rotation) {
|
||||
actor_->SetRotation(static_cast<float>(rotation));
|
||||
}
|
||||
|
||||
std::shared_ptr<JsVec2> GetScale() const {
|
||||
return std::make_shared<JsVec2>(actor_->GetScale());
|
||||
}
|
||||
void SetScale(const std::shared_ptr<JsVec2>& scale) {
|
||||
if (scale) {
|
||||
actor_->SetScale(scale->toNative());
|
||||
}
|
||||
}
|
||||
void SetScaleValue(double scale) {
|
||||
actor_->SetScale(static_cast<float>(scale));
|
||||
}
|
||||
|
||||
bool IsVisible() const { return actor_->IsVisible(); }
|
||||
void SetVisible(bool visible) { actor_->SetVisible(visible); }
|
||||
|
||||
void AddChild(const std::shared_ptr<JsActor>& child) {
|
||||
if (!actor_ || !child) {
|
||||
return;
|
||||
}
|
||||
actor_->AddChild(child->native());
|
||||
}
|
||||
|
||||
void RemoveAllChildren() {
|
||||
if (actor_) {
|
||||
actor_->RemoveAllChildren();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<JsVec2> GetSize() const {
|
||||
return std::make_shared<JsVec2>(actor_->GetSize());
|
||||
}
|
||||
void SetSize(const std::shared_ptr<JsVec2>& size) {
|
||||
if (size) {
|
||||
actor_->SetSize(size->toNative());
|
||||
}
|
||||
}
|
||||
void SetSizeWH(double width, double height) {
|
||||
actor_->SetSize(static_cast<float>(width), static_cast<float>(height));
|
||||
}
|
||||
|
||||
std::shared_ptr<JsVec2> GetAnchor() const {
|
||||
return std::make_shared<JsVec2>(actor_->GetAnchor());
|
||||
}
|
||||
void SetAnchor(const std::shared_ptr<JsVec2>& anchor) {
|
||||
if (anchor) {
|
||||
actor_->SetAnchor(anchor->toNative());
|
||||
}
|
||||
}
|
||||
void SetAnchorXY(double x, double y) {
|
||||
actor_->SetAnchor(static_cast<float>(x), static_cast<float>(y));
|
||||
}
|
||||
|
||||
std::shared_ptr<JsActor> GetParent() const;
|
||||
std::shared_ptr<JsVec2> GetTopLeftPosition() const;
|
||||
void SetTopLeftPosition(const std::shared_ptr<JsVec2>& position);
|
||||
void SetTopLeftPositionXY(double x, double y);
|
||||
std::shared_ptr<JsVec2> LocalToWorld(const std::shared_ptr<JsVec2>& point) const;
|
||||
std::shared_ptr<JsVec2> WorldToLocal(const std::shared_ptr<JsVec2>& point) const;
|
||||
bool ContainsWorldPoint(double x, double y) const;
|
||||
|
||||
bool IsEventReceiveEnabled() const {
|
||||
return actor_ && actor_->IsEventReceiveEnabled();
|
||||
}
|
||||
void EnableEventReceive() {
|
||||
if (actor_) {
|
||||
actor_->EnableEventReceive();
|
||||
}
|
||||
}
|
||||
void DisableEventReceive() {
|
||||
if (actor_) {
|
||||
actor_->DisableEventReceive();
|
||||
}
|
||||
}
|
||||
uint32 AddEventListener(const std::string& type,
|
||||
std::function<bool(qjs::Value)> callback);
|
||||
bool RemoveEventListener(uint32 listenerId);
|
||||
void ClearEventListeners();
|
||||
|
||||
const Ptr<Actor>& native() const { return actor_; }
|
||||
|
||||
protected:
|
||||
Ptr<Actor> actor_;
|
||||
};
|
||||
|
||||
} // namespace frostbite2D
|
||||
@@ -0,0 +1,87 @@
|
||||
#pragma once
|
||||
|
||||
#include <frostbite2D/types/type_alias.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <frostbite2D/event/event.h>
|
||||
|
||||
namespace qjs {
|
||||
class Runtime;
|
||||
class Context;
|
||||
class Value;
|
||||
} // namespace qjs
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
class Actor;
|
||||
struct Vec2;
|
||||
|
||||
class QuickJSVM {
|
||||
public:
|
||||
using BindingInstaller = std::function<bool(qjs::Context&)>;
|
||||
|
||||
static QuickJSVM& get();
|
||||
|
||||
void setScriptDirectory(const std::string& path);
|
||||
void setEntryScript(const std::string& path);
|
||||
void setDebugMode(bool enable);
|
||||
|
||||
bool init();
|
||||
void shutdown();
|
||||
bool run();
|
||||
|
||||
bool isInitialized() const { return initialized_; }
|
||||
qjs::Context* getContext() const { return context_.get(); }
|
||||
const std::string& getScriptDirectory() const { return scriptDirectory_; }
|
||||
|
||||
bool runPendingJobs();
|
||||
void logException(const char* stage);
|
||||
|
||||
qjs::Value newObject();
|
||||
qjs::Value loadModule(const std::string& relativePath);
|
||||
qjs::Value loadModule(const std::string& relativePath,
|
||||
const std::string& cacheTag);
|
||||
qjs::Value construct(const qjs::Value& constructor, const qjs::Value& argument);
|
||||
qjs::Value callMethod(const qjs::Value& object, const char* name);
|
||||
qjs::Value callMethod(const qjs::Value& object, const char* name,
|
||||
const qjs::Value& argument);
|
||||
qjs::Value callMethod(const qjs::Value& object, const char* name,
|
||||
double argument);
|
||||
qjs::Value wrapActor(const Ptr<Actor>& actor);
|
||||
qjs::Value wrapVec2(const Vec2& value);
|
||||
qjs::Value wrapEvent(const Event& event);
|
||||
std::optional<EventType> parseEventTypeName(std::string_view typeName) const;
|
||||
void RegisterBindingInstaller(BindingInstaller installer);
|
||||
void RegisterBootstrapScript(const std::string& script);
|
||||
|
||||
private:
|
||||
QuickJSVM() = default;
|
||||
~QuickJSVM();
|
||||
|
||||
QuickJSVM(const QuickJSVM&) = delete;
|
||||
QuickJSVM& operator=(const QuickJSVM&) = delete;
|
||||
|
||||
bool registerBindings();
|
||||
bool installGlobals();
|
||||
void logScriptException(const char* stage);
|
||||
std::string buildEntryPath() const;
|
||||
|
||||
bool initialized_ = false;
|
||||
bool debugMode_ = false;
|
||||
std::string scriptDirectory_ = "assets/scripts";
|
||||
std::string entryScript_ = "main.js";
|
||||
uint64 nextEvalId_ = 1;
|
||||
std::vector<BindingInstaller> bindingInstallers_;
|
||||
std::vector<std::string> bootstrapScripts_;
|
||||
|
||||
std::unique_ptr<qjs::Runtime> runtime_;
|
||||
std::unique_ptr<qjs::Context> context_;
|
||||
};
|
||||
|
||||
} // namespace frostbite2D
|
||||
Reference in New Issue
Block a user