Compare commits
1 commit
master
...
Containers
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72a25600a2 |
415 changed files with 5552 additions and 285550 deletions
|
|
@ -1,21 +0,0 @@
|
||||||
project(Widgets)
|
|
||||||
|
|
||||||
### ---------------------- Static Library --------------------- ###
|
|
||||||
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
|
|
||||||
file(GLOB HEADERS "./public/*.hpp")
|
|
||||||
|
|
||||||
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Math Graphics Imgui)
|
|
||||||
|
|
||||||
### -------------------------- Applications -------------------------- ###
|
|
||||||
|
|
||||||
add_executable(SimpleGui examples/SimpleGUI.cpp)
|
|
||||||
target_link_libraries(SimpleGui ${PROJECT_NAME} ${GLEW_LIB})
|
|
||||||
target_include_directories(SimpleGui PUBLIC ../Externals/glfw/include ${GLEW_INCLUDE_DIR})
|
|
||||||
|
|
||||||
add_executable(ChatGui examples/ChatGUI.cpp)
|
|
||||||
target_link_libraries(ChatGui ${PROJECT_NAME} ${GLEW_LIB})
|
|
||||||
target_include_directories(ChatGui PUBLIC ../Externals/glfw/include ${GLEW_INCLUDE_DIR})
|
|
||||||
|
|
||||||
file(COPY "examples/Font.ttf" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
|
|
||||||
#include "ChatGUI.hpp"
|
|
||||||
|
|
||||||
#include "GraphicApplication.hpp"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
class ExampleGUI : public Application {
|
|
||||||
public:
|
|
||||||
ExampleGUI() = default;
|
|
||||||
|
|
||||||
void processFrame(EventHandler* eventHandler, halnf delta) override {
|
|
||||||
auto rec = RectF({ 0, 0 }, mWindow->getSize());
|
|
||||||
|
|
||||||
mGui.updateConfigWrapper(mWidgetManager);
|
|
||||||
mGui.setArea(rec);
|
|
||||||
mGui.setVisible(true);
|
|
||||||
|
|
||||||
mGui.procWrapper(*eventHandler, rec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawFrame(Canvas* canvas) override { mGui.drawWrapper(*canvas); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
WidgetManager mWidgetManager;
|
|
||||||
ComplexWidget mGui;
|
|
||||||
};
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
{
|
|
||||||
ExampleGUI gui;
|
|
||||||
gui.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,256 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Widgets.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
class UserWidget : public Widget {
|
|
||||||
public:
|
|
||||||
UserWidget() = default;
|
|
||||||
|
|
||||||
void eventDraw(Canvas& canvas) override {
|
|
||||||
if (this->isFocus()) canvas.rect(this->mArea, mAccentColor, mRounding);
|
|
||||||
else canvas.rect(this->mArea, mBaseColor, mRounding);
|
|
||||||
canvas.text(mUser.c_str(), this->mArea, mFontSize, Canvas::CC, mPadding, mUserColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
void eventUpdateConfiguration(WidgetManager& wm) override {
|
|
||||||
wm.setActiveId("UserWidget");
|
|
||||||
|
|
||||||
mBaseColor = wm.getColor("Base", "Base");
|
|
||||||
mFontSize = wm.getNumber("Size", "FontSize");
|
|
||||||
mPadding = wm.getNumber("Padding", "Padding");
|
|
||||||
mUserColor = wm.getColor("ColUser", "Front");
|
|
||||||
mAccentColor = wm.getColor("Accent", "Accent");
|
|
||||||
mRounding = wm.getNumber("Rounding", "Rounding");
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
std::string mUser = "UserName";
|
|
||||||
bool mIsHover = false;
|
|
||||||
|
|
||||||
RGBA mBaseColor;
|
|
||||||
RGBA mUserColor;
|
|
||||||
RGBA mAccentColor;
|
|
||||||
halnf mPadding = 0;
|
|
||||||
halnf mFontSize = 0;
|
|
||||||
halnf mRounding = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MessageWidget : public Widget {
|
|
||||||
public:
|
|
||||||
MessageWidget() = default;
|
|
||||||
|
|
||||||
void eventDraw(Canvas& canvas) override {
|
|
||||||
if (this->isFocus()) canvas.rect(this->mArea, mBaseColor, mRounding);
|
|
||||||
|
|
||||||
auto userName = this->mArea;
|
|
||||||
userName.w = 25;
|
|
||||||
|
|
||||||
auto content = this->mArea;
|
|
||||||
content.y = userName.y + userName.w;
|
|
||||||
content.w = this->mArea.w - userName.w;
|
|
||||||
|
|
||||||
canvas.text(mContent.c_str(), content, mFontSize, Canvas::LC, mPadding, mUserColorDim);
|
|
||||||
canvas.text(mUser.c_str(), userName, mFontSizeDim, Canvas::LC, mPadding, mUserColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void eventUpdateConfiguration(WidgetManager& wm) override {
|
|
||||||
wm.setActiveId("MessageWidget");
|
|
||||||
|
|
||||||
mBaseColor = wm.getColor("Base", "Base");
|
|
||||||
mFontSize = wm.getNumber("Size", "FontSize");
|
|
||||||
mFontSizeDim = wm.getNumber("SizeUser", "FontSizeDim");
|
|
||||||
mPadding = wm.getNumber("Padding", "Padding");
|
|
||||||
mUserColor = wm.getColor("UserColor", "Front");
|
|
||||||
mUserColorDim = wm.getColor("UserColorDim", "FrontDim");
|
|
||||||
mRounding = wm.getNumber("Rounding", "Rounding");
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
std::string mContent = "Message Content";
|
|
||||||
std::string mUser = "UserName";
|
|
||||||
bool mIsHover = false;
|
|
||||||
|
|
||||||
RGBA mBaseColor;
|
|
||||||
RGBA mUserColor;
|
|
||||||
RGBA mUserColorDim;
|
|
||||||
halnf mPadding = 0;
|
|
||||||
halnf mFontSize = 0;
|
|
||||||
halnf mFontSizeDim = 0;
|
|
||||||
halnf mRounding = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LoginWidget : public Widget {
|
|
||||||
public:
|
|
||||||
explicit LoginWidget() {
|
|
||||||
mPass.mId = "pass";
|
|
||||||
mUser.mId = "user";
|
|
||||||
mButton.mLabel.mLabel = "Login";
|
|
||||||
|
|
||||||
this->mChildWidgets.pushBack(&mPass);
|
|
||||||
this->mChildWidgets.pushBack(&mUser);
|
|
||||||
this->mChildWidgets.pushBack(&mButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
void eventProcess(const Events& events) override {
|
|
||||||
mLogged = false;
|
|
||||||
|
|
||||||
const auto xval = this->mArea.z / 2 - 100;
|
|
||||||
|
|
||||||
mUser.setArea({ xval, 10, 200, 30 });
|
|
||||||
mPass.setArea({ xval, 50, 200, 30 });
|
|
||||||
mButton.setArea({ xval, 90, 200, 30 });
|
|
||||||
|
|
||||||
if (mButton.isFired()) {
|
|
||||||
mLogged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void eventDraw(Canvas& canvas) override { canvas.rect(this->mArea, mBGColor); }
|
|
||||||
|
|
||||||
public:
|
|
||||||
void eventUpdateConfiguration(WidgetManager& wm) override {
|
|
||||||
wm.setActiveId("LoginWidget");
|
|
||||||
mBGColor = wm.getColor("Back", "Base");
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
TextInputWidget mUser;
|
|
||||||
TextInputWidget mPass;
|
|
||||||
ButtonWidget mButton;
|
|
||||||
bool mLogged = false;
|
|
||||||
|
|
||||||
RGBA mBGColor;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ActiveChatWidget : public Widget {
|
|
||||||
public:
|
|
||||||
ActiveChatWidget() {
|
|
||||||
mSend.mLabel.mLabel = "Send";
|
|
||||||
mMessage.mId = "Message";
|
|
||||||
|
|
||||||
this->mChildWidgets.pushBack(&mHistoryView);
|
|
||||||
this->mChildWidgets.pushBack(&mMessage);
|
|
||||||
this->mChildWidgets.pushBack(&mSend);
|
|
||||||
}
|
|
||||||
|
|
||||||
void eventProcess(const Events& events) override {
|
|
||||||
auto history = this->mArea;
|
|
||||||
history.w -= 50;
|
|
||||||
|
|
||||||
auto input = this->mArea;
|
|
||||||
input.y = history.w + 10;
|
|
||||||
input.w = 40 - mPadding;
|
|
||||||
input.x += mPadding;
|
|
||||||
input.z -= mPadding;
|
|
||||||
|
|
||||||
auto inputMessage = input;
|
|
||||||
inputMessage.z -= 100;
|
|
||||||
|
|
||||||
auto inputSend = input;
|
|
||||||
inputSend.x = inputMessage.x + inputMessage.z + mPadding;
|
|
||||||
inputSend.z = 100 - mPadding * 2;
|
|
||||||
|
|
||||||
mSend.setArea(inputSend);
|
|
||||||
mMessage.setArea(inputMessage);
|
|
||||||
|
|
||||||
mHistoryView.setArea(history);
|
|
||||||
}
|
|
||||||
|
|
||||||
void eventDraw(Canvas& canvas) override { canvas.rect(this->mArea, mBGColor); }
|
|
||||||
|
|
||||||
void eventUpdateConfiguration(WidgetManager& wm) override {
|
|
||||||
wm.setActiveId("ActiveChat");
|
|
||||||
mBGColor = wm.getColor("Back", "Background");
|
|
||||||
mPadding = wm.getNumber("Padding", "Padding");
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Buffer<MessageWidget> mMessages;
|
|
||||||
ScrollableWindow mHistoryView;
|
|
||||||
TextInputWidget mMessage;
|
|
||||||
ButtonWidget mSend;
|
|
||||||
|
|
||||||
RGBA mBGColor;
|
|
||||||
halnf mPadding = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ChattingWidget : public DockWidget {
|
|
||||||
public:
|
|
||||||
ChattingWidget() {
|
|
||||||
// todo : fetch code
|
|
||||||
mUsers.append(UserWidget());
|
|
||||||
mUsers.append(UserWidget());
|
|
||||||
mUsers.append(UserWidget());
|
|
||||||
|
|
||||||
mUsers[0].mArea = { 0, 0, 100, 100 };
|
|
||||||
mUsers[1].mArea = { 0, 0, 100, 100 };
|
|
||||||
mUsers[2].mArea = { 0, 0, 100, 100 };
|
|
||||||
|
|
||||||
for (auto message : mUsers) {
|
|
||||||
mSideView.addWidget(&message.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
mActive.mMessages.append(MessageWidget());
|
|
||||||
mActive.mMessages.append(MessageWidget());
|
|
||||||
mActive.mMessages.append(MessageWidget());
|
|
||||||
|
|
||||||
mActive.mMessages[0].mArea = { 0, 0, 100, 50 };
|
|
||||||
mActive.mMessages[1].mArea = { 0, 0, 100, 50 };
|
|
||||||
mActive.mMessages[2].mArea = { 0, 0, 100, 50 };
|
|
||||||
|
|
||||||
for (auto message : mActive.mMessages) {
|
|
||||||
mActive.mHistoryView.addWidget(&message.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
addSideWidget(&mSideView, DockWidget::RIGHT);
|
|
||||||
setCenterWidget(&mActive);
|
|
||||||
}
|
|
||||||
|
|
||||||
void eventUpdateConfiguration(WidgetManager& wm) override {
|
|
||||||
wm.setActiveId("ChattingWidget");
|
|
||||||
mBGColor = wm.getColor("Back", "Background");
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Buffer<UserWidget> mUsers;
|
|
||||||
ScrollableWindow mSideView;
|
|
||||||
ActiveChatWidget mActive;
|
|
||||||
|
|
||||||
RGBA mBGColor;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ComplexWidget : public Widget {
|
|
||||||
public:
|
|
||||||
ComplexWidget() {
|
|
||||||
this->mChildWidgets.pushBack(&mLogin);
|
|
||||||
this->mChildWidgets.pushBack(&mChatting);
|
|
||||||
}
|
|
||||||
|
|
||||||
void eventProcess(const Events& events) override {
|
|
||||||
mLogged = mLogin.mLogged;
|
|
||||||
|
|
||||||
mLogin.setEnable(!mLogged);
|
|
||||||
mChatting.setEnable(mLogged);
|
|
||||||
|
|
||||||
mLogin.setArea(this->mArea);
|
|
||||||
mChatting.setArea(this->mArea);
|
|
||||||
}
|
|
||||||
|
|
||||||
void eventDraw(Canvas& canvas) override { canvas.rect(this->mArea, mBGColor); }
|
|
||||||
|
|
||||||
void eventUpdateConfiguration(WidgetManager& wm) override {
|
|
||||||
wm.setActiveId("ChatGui");
|
|
||||||
mBGColor = wm.getColor("Back", "Background");
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool mLogged = false;
|
|
||||||
LoginWidget mLogin;
|
|
||||||
ChattingWidget mChatting;
|
|
||||||
|
|
||||||
RGBA mBGColor;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
|
@ -1,40 +0,0 @@
|
||||||
|
|
||||||
#include "SimpleGUI.hpp"
|
|
||||||
|
|
||||||
#include "GraphicApplication.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
class SimpleGUI : public Application {
|
|
||||||
public:
|
|
||||||
SimpleGUI() {
|
|
||||||
// mGui.mPreview = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void processFrame(EventHandler* eventHandler, halnf) override {
|
|
||||||
const auto rec = RectF({ 0, 0 }, mWindow->getSize());
|
|
||||||
|
|
||||||
mGui.setArea(rec);
|
|
||||||
mGui.updateConfigWrapper(mWidgetManager);
|
|
||||||
mGui.procWrapper(*eventHandler, rec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawFrame(Canvas* canvas) override {
|
|
||||||
canvas->rect(mGui.mArea, { 0.1f, 0.1f, 0.1f, 1.f });
|
|
||||||
mGui.drawWrapper(*canvas);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
WidgetManager mWidgetManager;
|
|
||||||
|
|
||||||
// DockSpaceWidget mGui;
|
|
||||||
SimpleWidget3 mGui;
|
|
||||||
};
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
{
|
|
||||||
SimpleGUI gui;
|
|
||||||
gui.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
#include "Widgets.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
class SimpleWidget : public CollapsableMenu {
|
|
||||||
public:
|
|
||||||
SimpleWidget() {
|
|
||||||
this->addWidgetToMenu(&mSlider);
|
|
||||||
|
|
||||||
this->addWidgetToMenu(&mInMenuButton1);
|
|
||||||
this->addWidgetToMenu(&mInMenuButton2);
|
|
||||||
|
|
||||||
this->addWidgetToMenu(&mLabel);
|
|
||||||
|
|
||||||
mInMenuButton1.mLabel.mLabel = "Button1";
|
|
||||||
|
|
||||||
mInMenuButton1.mCallback = []() {
|
|
||||||
printf("asd\n");
|
|
||||||
};
|
|
||||||
|
|
||||||
mInMenuButton2.mLabel.mLabel = "Button2";
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
ButtonWidget mInMenuButton1;
|
|
||||||
ButtonWidget mInMenuButton2;
|
|
||||||
|
|
||||||
LabelWidget mLabel;
|
|
||||||
NamedSliderWidget mSlider;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SimpleWidget3 : public WorkspaceWidget {
|
|
||||||
public:
|
|
||||||
SimpleWidget3() {
|
|
||||||
|
|
||||||
mDockSpace.addSideWidget(&mButtons[0], DockWidget::BOTTOM);
|
|
||||||
mDockSpace.addSideWidget(&mButtons[1], DockWidget::RIGHT);
|
|
||||||
|
|
||||||
mDockSpace.removeSideWidget(DockWidget::BOTTOM);
|
|
||||||
|
|
||||||
mDockSpace.addSideWidget(&mButtons[0], DockWidget::TOP);
|
|
||||||
mDockSpace.addSideWidget(&mButtons[2], DockWidget::LEFT);
|
|
||||||
|
|
||||||
mDockSpace.removeSideWidget(DockWidget::TOP);
|
|
||||||
|
|
||||||
mDockSpace.addSideWidget(&mButtons[0], DockWidget::BOTTOM);
|
|
||||||
|
|
||||||
mDockSpace.addSideWidget(&mButtons[3], DockWidget::TOP);
|
|
||||||
mDockSpace.setCenterWidget(&mButtons[4]);
|
|
||||||
|
|
||||||
/*
|
|
||||||
mButtons[4].mCallback = [&]() { mDockSpace.toggleHiddenState(DockSpaceWidget::BOTTOM); };
|
|
||||||
mButtons[0].mCallback = [&]() { mDockSpace.toggleHiddenState(DockSpaceWidget::TOP); };
|
|
||||||
mButtons[2].mCallback = [&]() { mDockSpace.toggleHiddenState(DockSpaceWidget::RIGHT); };
|
|
||||||
mButtons[3].mCallback = [&]() { mDockSpace.toggleHiddenState(DockSpaceWidget::LEFT); };
|
|
||||||
*/
|
|
||||||
|
|
||||||
mButtons[0].addWidgetToMenu(&mWidget);
|
|
||||||
mButtons[1].addWidgetToMenu(&mWidget2);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
FloatingWidget mButtons[5];
|
|
||||||
|
|
||||||
SimpleWidget mWidget;
|
|
||||||
SimpleWidget mWidget2;
|
|
||||||
SimpleWidget mWidget3;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
|
|
||||||
#include "Animations.hpp"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
bool AnimValue::gInTransition = false;
|
|
||||||
|
|
||||||
halnf AnimValue::interpolate() const {
|
|
||||||
if (!mTimeAnim) {
|
|
||||||
return mVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto dt = gCurrentTime - mTimeStart;
|
|
||||||
if (dt > mTimeAnim) dt = mTimeAnim;
|
|
||||||
auto t = (halnf) dt / (halnf) mTimeAnim;
|
|
||||||
t = (halnf) (0.511 + atan((t - 0.36) * 28) / 2.9);
|
|
||||||
t = clamp(t, 0.f, 1.f);
|
|
||||||
auto out = mValPrev + (mVal - mValPrev) * t;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimValue::AnimValue() {
|
|
||||||
mTimeStart = gCurrentTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimValue::setAnimTime(halni time) { mTimeAnim = time; }
|
|
||||||
|
|
||||||
AnimValue::AnimValue(halnf val) {
|
|
||||||
mVal = val;
|
|
||||||
mValPrev = mVal;
|
|
||||||
mTimeStart = gCurrentTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AnimValue::inTransition() const {
|
|
||||||
auto timePassed = gCurrentTime - mTimeStart >= mTimeAnim;
|
|
||||||
return !timePassed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimValue::set(halnf val) {
|
|
||||||
if (!inTransition()) mValPrev = mVal;
|
|
||||||
if (val == mVal) return;
|
|
||||||
mValPrev = get();
|
|
||||||
mVal = val;
|
|
||||||
if (!inTransition()) {
|
|
||||||
mTimeStart = gCurrentTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
halnf AnimValue::getTarget() const { return mVal; }
|
|
||||||
|
|
||||||
void AnimValue::setNoTransition(halnf val) {
|
|
||||||
mValPrev = val;
|
|
||||||
mVal = val;
|
|
||||||
mTimeStart = gCurrentTime - mTimeAnim;
|
|
||||||
}
|
|
||||||
|
|
||||||
halnf AnimValue::get() const {
|
|
||||||
if (inTransition()) {
|
|
||||||
gInTransition = true;
|
|
||||||
return interpolate();
|
|
||||||
}
|
|
||||||
return mVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimValue::operator=(halnf val) {
|
|
||||||
setNoTransition(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimValue::operator halnf() const { return get(); }
|
|
||||||
|
|
||||||
RectF AnimRect::get() const { return { x.get(), y.get(), z.get(), w.get() }; }
|
|
||||||
|
|
||||||
RectF AnimRect::getTarget() const { return { x.getTarget(), y.getTarget(), z.getTarget(), w.getTarget() }; }
|
|
||||||
|
|
||||||
void AnimRect::setNoTransition(RectF rec) {
|
|
||||||
x.setNoTransition(rec.x);
|
|
||||||
y.setNoTransition(rec.y);
|
|
||||||
z.setNoTransition(rec.z);
|
|
||||||
w.setNoTransition(rec.w);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimRect::setAnimTime(const halni time) {
|
|
||||||
x.setAnimTime(time);
|
|
||||||
y.setAnimTime(time);
|
|
||||||
z.setAnimTime(time);
|
|
||||||
w.setAnimTime(time);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimRect::set(const RectF& in) {
|
|
||||||
x.set(in.x);
|
|
||||||
y.set(in.y);
|
|
||||||
z.set(in.z);
|
|
||||||
w.set(in.w);
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimColor::AnimColor() : mColor() {}
|
|
||||||
|
|
||||||
RGBA AnimColor::get() const {
|
|
||||||
auto col = mColor.get();
|
|
||||||
return { col.x, col.y, col.z, col.w };
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimColor::set(const RGBA& col) { mColor.set(RectF(col.r, col.g, col.b, col.a)); }
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
|
|
||||||
#include "ButtonWidget.hpp"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
ButtonWidget::ButtonWidget() {
|
|
||||||
this->setArea({ 0, 0, 100, 30 });
|
|
||||||
this->mChildWidgets.pushBack(&mLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
ButtonWidget::ButtonWidget(const std::string& label, const tp::RectF& aArea) {
|
|
||||||
this->setArea(aArea);
|
|
||||||
mLabel.mLabel = label;
|
|
||||||
this->mChildWidgets.pushBack(&mLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ButtonWidget::isFired() { return this->isReleased(); }
|
|
||||||
|
|
||||||
void ButtonWidget::eventProcess(const Events&) {
|
|
||||||
mLabel.setArea(this->mArea);
|
|
||||||
|
|
||||||
if (isFired()) {
|
|
||||||
mCallback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ButtonWidget::eventDraw(Canvas& canvas) {
|
|
||||||
if (this->isHolding()) {
|
|
||||||
canvas.rect(this->mArea, pressedColor, rounding);
|
|
||||||
} else if (this->isFocus()) {
|
|
||||||
canvas.rect(this->mArea, hoveredColor, rounding);
|
|
||||||
} else {
|
|
||||||
canvas.rect(this->mArea, accentColor, rounding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ButtonWidget::setLabel(const std::string& string) { mLabel.mLabel = string; }
|
|
||||||
|
|
||||||
void ButtonWidget::eventUpdateConfiguration(WidgetManager& wm) {
|
|
||||||
wm.setActiveId("Button");
|
|
||||||
|
|
||||||
pressedColor = wm.getColor("Pressed", "Action");
|
|
||||||
hoveredColor = wm.getColor("Hovered", "Interaction");
|
|
||||||
accentColor = wm.getColor("Default", "Accent");
|
|
||||||
rounding = wm.getNumber("Rounding", "Rounding");
|
|
||||||
}
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
|
|
||||||
#include "CollapsableMenu.hpp"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
CollapsableMenu::CollapsableMenu() {
|
|
||||||
this->mChildWidgets.pushBack(&mHeader);
|
|
||||||
this->mChildWidgets.pushBack(&mBody);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CollapsableMenu::eventProcess(const Events&) {
|
|
||||||
if (mHeader.isReleased()) {
|
|
||||||
toggleCollapsed();
|
|
||||||
}
|
|
||||||
|
|
||||||
updateGeometry();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CollapsableMenu::eventDraw(Canvas& canvas) {
|
|
||||||
if (mBorders) {
|
|
||||||
canvas.rect(this->mArea, mBorderColor, rounding);
|
|
||||||
canvas.rect(this->mArea.shrink(mBorderSize), mMenuColor, rounding);
|
|
||||||
} else {
|
|
||||||
canvas.rect(this->mArea, mMenuColor, rounding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CollapsableMenu::addWidgetToMenu(Widget* widget) {
|
|
||||||
mBody.addWidget(widget);
|
|
||||||
|
|
||||||
EventHandler ev;
|
|
||||||
mBody.procWrapper(ev, this->mArea);
|
|
||||||
updateGeometry();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CollapsableMenu::setLabel(const std::string& string) { mHeader.mLabel = string; }
|
|
||||||
|
|
||||||
void CollapsableMenu::toggleCollapsed() { setCollapsed(!getCollapsed()); }
|
|
||||||
|
|
||||||
void CollapsableMenu::setCollapsed(bool collapsed) {
|
|
||||||
if (mLocked) return;
|
|
||||||
if (collapsed && !mCollapsed) mPrevHeight = this->mArea.size.y;
|
|
||||||
if (!collapsed && mCollapsed) this->mArea.size.y = mPrevHeight;
|
|
||||||
mCollapsed = collapsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CollapsableMenu::getCollapsed() const { return mCollapsed; }
|
|
||||||
|
|
||||||
void CollapsableMenu::updateGeometry() {
|
|
||||||
mHeader.setArea(getHeaderRect());
|
|
||||||
|
|
||||||
mBody.mEnable = !mCollapsed;
|
|
||||||
|
|
||||||
if (mCollapsed) {
|
|
||||||
this->mArea.size.y = headerHeight;
|
|
||||||
} else {
|
|
||||||
if (mAdjustHeight) {
|
|
||||||
this->mArea.size.y = headerHeight + getBodyRect().size.y + mPadding * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
mBody.setArea(getBodyRect());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RectF CollapsableMenu::getHeaderRect() {
|
|
||||||
RectF out = { this->mArea.pos, { this->mArea.size.x, headerHeight } };
|
|
||||||
if (mBorders) out = out.shrink(mPadding);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
RectF CollapsableMenu::getBodyRect() {
|
|
||||||
RectF out = { Vec2F{ this->mArea.pos.x, this->mArea.pos.y + headerHeight },
|
|
||||||
Vec2F{ this->mArea.size.x, this->mArea.size.y - headerHeight - mPadding } };
|
|
||||||
|
|
||||||
out.size.y -= mBorderSize * 2;
|
|
||||||
|
|
||||||
if (mAdjustHeight) out.size.y = mBody.getContentSize();
|
|
||||||
|
|
||||||
if (mBody.getContentSize() && mBorders) {
|
|
||||||
out = out.shrink(mPadding);
|
|
||||||
out.size.y += mPadding * 2 + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CollapsableMenu::eventUpdateConfiguration(WidgetManager& wm) {
|
|
||||||
wm.setActiveId("CollapsableMenu");
|
|
||||||
|
|
||||||
headerHeight = wm.getNumber("HeaderHeight", 35);
|
|
||||||
mMenuColor = wm.getColor("MenuColor", RGBA(0, 0, 0, 1.f));
|
|
||||||
rounding = wm.getNumber("Rounding", "Rounding");
|
|
||||||
mBorderColor = wm.getColor("BorderColor", RGBA(0.16, 0.16, 0.16, 1.f));
|
|
||||||
mBorderSize = wm.getNumber("BorderSize", 2.f);
|
|
||||||
mPadding = wm.getNumber("Padding", "Padding");
|
|
||||||
}
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
#include "FloatingLayoutWidget.hpp"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
FloatingLayoutWidget::FloatingLayoutWidget() = default;
|
|
||||||
|
|
||||||
void FloatingLayoutWidget::eventProcess(const tp::Events& events) {
|
|
||||||
updateActiveWindow(events);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FloatingLayoutWidget::updateActiveWindow(const tp::Events& events) {
|
|
||||||
mIsPassThrough = true;
|
|
||||||
for (auto childNode = this->mChildWidgets.firstNode(); childNode; childNode = childNode->next) {
|
|
||||||
auto child = childNode->data;
|
|
||||||
if (child->mArea.isInside(events.getPointer())) {
|
|
||||||
mIsPassThrough = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (events.isPressed(InputID::MOUSE1)) {
|
|
||||||
|
|
||||||
Widget* activeChild = nullptr;
|
|
||||||
|
|
||||||
for (auto childNode = this->mChildWidgets.firstNode(); childNode; childNode = childNode->next) {
|
|
||||||
auto child = childNode->data;
|
|
||||||
|
|
||||||
if (child->mArea.isInside(events.getPointer())) {
|
|
||||||
|
|
||||||
mChildWidgets.detach(childNode);
|
|
||||||
mChildWidgets.pushFront(childNode);
|
|
||||||
|
|
||||||
child->mHandlesEvents = true;
|
|
||||||
activeChild = child;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (activeChild) {
|
|
||||||
for (auto child : this->mChildWidgets) {
|
|
||||||
if (activeChild != child.data() && !child->mIsDocked) child->mHandlesEvents = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FloatingLayoutWidget::handlesEvent() const { return !mIsPassThrough; }
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
|
|
||||||
#include "FloatingWidget.hpp"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
FloatingWidget::FloatingWidget() {
|
|
||||||
this->mArea = { 0, 0, 300, 300 };
|
|
||||||
this->mAdjustHeight = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FloatingWidget::eventProcess(const Events& events) {
|
|
||||||
mActionStartRelativePos = events.getPointerPrev() - this->mArea.pos;
|
|
||||||
|
|
||||||
checkFloating(events);
|
|
||||||
if (mResizable) checkResizing(events);
|
|
||||||
|
|
||||||
CollapsableMenu::eventProcess(events);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FloatingWidget::eventDraw(Canvas& canvas) {
|
|
||||||
CollapsableMenu::eventDraw(canvas);
|
|
||||||
|
|
||||||
if (!this->getCollapsed() && mResizable) {
|
|
||||||
auto rect = getResizeHandle();
|
|
||||||
canvas.rect(rect, mResizeHandleColor, 0);
|
|
||||||
canvas.circle(rect.pos - this->mBorderSize, rect.w, this->mMenuColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FloatingWidget::eventUpdateConfiguration(WidgetManager& wm) {
|
|
||||||
CollapsableMenu::eventUpdateConfiguration(wm);
|
|
||||||
|
|
||||||
wm.setActiveId("FloatingWidget");
|
|
||||||
|
|
||||||
mResizeHandleSize = wm.getNumber("ResizeHandleSize", 15);
|
|
||||||
mResizeHandleColor = wm.getColor("ResizeHandleColor", RGBA(0.16, 0.16, 0.16, 1.f));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FloatingWidget::checkFloating(const Events& events) {
|
|
||||||
mDropped = false;
|
|
||||||
|
|
||||||
if (this->mHeader.isHolding() && events.getPointerDelta().length2() > 4) {
|
|
||||||
mFloating = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mFloating && this->mHeader.isReleased()) {
|
|
||||||
mFloating = false;
|
|
||||||
this->mHeader.clearEvents();
|
|
||||||
mDropped = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mFloating) {
|
|
||||||
auto relativePos = events.getPointer() - this->mArea.pos;
|
|
||||||
this->mArea.pos += relativePos - mActionStartRelativePos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FloatingWidget::checkResizing(const Events& events) {
|
|
||||||
if (this->getCollapsed()) return;
|
|
||||||
|
|
||||||
if (events.isPressed(InputID::MOUSE1) && getResizeHandle().isInside(events.getPointer())) {
|
|
||||||
mResizing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (events.isReleased(InputID::MOUSE1)) {
|
|
||||||
mResizing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mResizing) {
|
|
||||||
auto relativePos = events.getPointer() - this->mArea.pos;
|
|
||||||
this->mArea.size += relativePos - mActionStartRelativePos;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this->mCollapsed) {
|
|
||||||
this->mArea.size.clamp(mMinSize, { FLT_MAX, FLT_MAX });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RectF FloatingWidget::getResizeHandle() {
|
|
||||||
auto size = Vec2F(mResizeHandleSize);
|
|
||||||
auto pos = this->mArea.pos + this->mArea.size - size;
|
|
||||||
return { pos, size };
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FloatingWidget::isFloating() const { return mFloating; }
|
|
||||||
|
|
||||||
void FloatingWidget::stopFloating() {
|
|
||||||
mFloating = false;
|
|
||||||
}
|
|
||||||
|
|
@ -1,328 +0,0 @@
|
||||||
#include "GridLayoutWidget.hpp"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
DockWidget::DockWidget() {
|
|
||||||
mSideWidgets[0].side = LEFT;
|
|
||||||
mSideWidgets[1].side = TOP;
|
|
||||||
mSideWidgets[2].side = RIGHT;
|
|
||||||
mSideWidgets[3].side = BOTTOM;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockWidget::addSideWidget(Widget* widget, Side side) {
|
|
||||||
if (sideExists(side)) return;
|
|
||||||
|
|
||||||
auto& sideWidget = mSideWidgets[side];
|
|
||||||
sideWidget.widget = widget;
|
|
||||||
for (auto& order : mSideWidgets) {
|
|
||||||
if (order.order == -1) {
|
|
||||||
order.order = side;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sideWidget.hidden = false;
|
|
||||||
|
|
||||||
mChildWidgets.pushBack(widget);
|
|
||||||
widget->mIsDocked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockWidget::removeSideWidget(Side side) {
|
|
||||||
if (!sideExists(side)) return;
|
|
||||||
|
|
||||||
bool removed = false;
|
|
||||||
for (ualni i = 0; i < 3; i++) {
|
|
||||||
if (mSideWidgets[i].order == side) {
|
|
||||||
removed = true;
|
|
||||||
}
|
|
||||||
if (removed) {
|
|
||||||
swapV(mSideWidgets[i].order, mSideWidgets[i + 1].order);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mSideWidgets[3].order = -1;
|
|
||||||
|
|
||||||
auto widget = mSideWidgets[side].widget;
|
|
||||||
widget->mIsDocked = false;
|
|
||||||
mChildWidgets.removeNode(mChildWidgets.find(widget));
|
|
||||||
|
|
||||||
mSideWidgets[side].widget = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockWidget::setCenterWidget(Widget* widget) {
|
|
||||||
mChildWidgets.removeNode(mChildWidgets.find(mCenterWidget));
|
|
||||||
mCenterWidget = widget;
|
|
||||||
mChildWidgets.pushBack(mCenterWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockWidget::toggleHiddenState(DockWidget::Side side) {
|
|
||||||
if (!sideExists(side)) return;
|
|
||||||
mSideWidgets[side].hidden = !mSideWidgets[side].hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockWidget::eventProcess(const tp::Events& events) {
|
|
||||||
calculateSideAreas();
|
|
||||||
calculateResizeHandles();
|
|
||||||
// calculateHeaderAreas();
|
|
||||||
|
|
||||||
handlePreview(events);
|
|
||||||
handleResizeEvents(events);
|
|
||||||
|
|
||||||
updateChildSideWidgets();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockWidget::eventDraw(Canvas& canvas) {
|
|
||||||
canvas.rect(this->mArea, mBackgroundColor, 0);
|
|
||||||
|
|
||||||
for (auto& sideWidget : mSideWidgets) {
|
|
||||||
if (!isSideVisible(sideWidget.side)) continue;
|
|
||||||
auto& handle = sideWidget.resizeHandle;
|
|
||||||
if (handle.active) {
|
|
||||||
canvas.rect(handle.area.shrink(mPadding / 1.5f), mResizeHandleColorActive, 0);
|
|
||||||
} else if (handle.hover) {
|
|
||||||
canvas.rect(handle.area.shrink(mPadding / 1.5f), mResizeHandleColorHovered, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& sideWidget : mSideWidgets) {
|
|
||||||
if (!isSideVisible(sideWidget.side)) continue;
|
|
||||||
canvas.rect(sideWidget.headerArea, mResizeHandleColorActive, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockWidget::eventDrawOver(Canvas& canvas) {
|
|
||||||
if (!mPreview) return;
|
|
||||||
|
|
||||||
if (mPreviewSide != NONE) canvas.rect(mPreviewArea.shrink(mPadding * 2), mPreviewColor, mRounding);
|
|
||||||
|
|
||||||
for (auto& sideWidget : mSideWidgets) {
|
|
||||||
if (sideWidget.widget) continue;
|
|
||||||
canvas.rect(sideWidget.previewHandleArea, mPreviewColor, mRounding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockWidget::calculateSideAreas() {
|
|
||||||
auto startArea = this->mArea;
|
|
||||||
for (auto& sideWidget : mSideWidgets) {
|
|
||||||
const auto side = sideWidget.order;
|
|
||||||
|
|
||||||
if (side == -1) break;
|
|
||||||
if (!isSideVisible(Side(side))) continue;
|
|
||||||
|
|
||||||
bool vertical = side == TOP || side == BOTTOM;
|
|
||||||
bool opposite = side == BOTTOM || side == RIGHT;
|
|
||||||
|
|
||||||
auto& sideSize = mSideWidgets[side].absoluteSize;
|
|
||||||
|
|
||||||
auto factor = sideSize / startArea.size[vertical];
|
|
||||||
if (opposite) factor = factor * -1 + 1;
|
|
||||||
auto& area = mSideWidgets[side].area;
|
|
||||||
|
|
||||||
if (!vertical) {
|
|
||||||
const auto first = startArea.splitByFactorHL(factor);
|
|
||||||
const auto second = startArea.splitByFactorHR(factor);
|
|
||||||
area = side == LEFT ? first : second;
|
|
||||||
startArea = side == LEFT ? second : first;
|
|
||||||
} else {
|
|
||||||
const auto first = startArea.splitByFactorVT(factor);
|
|
||||||
const auto second = startArea.splitByFactorVB(factor);
|
|
||||||
area = side == TOP ? first : second;
|
|
||||||
startArea = side == TOP ? second : first;
|
|
||||||
}
|
|
||||||
|
|
||||||
area = area.shrink(mPadding);
|
|
||||||
}
|
|
||||||
|
|
||||||
mCenterArea = startArea.shrink(mPadding);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockWidget::calculateResizeHandles() {
|
|
||||||
RectF rec;
|
|
||||||
|
|
||||||
if (isSideVisible(LEFT)) {
|
|
||||||
auto& side = mSideWidgets[LEFT];
|
|
||||||
rec = { side.area.p4(), { mPadding * 2, side.area.size.y } };
|
|
||||||
side.resizeHandle = { rec, 0, mCenterArea.p3().x };
|
|
||||||
}
|
|
||||||
if (isSideVisible(RIGHT)) {
|
|
||||||
auto& side = mSideWidgets[RIGHT];
|
|
||||||
rec = { side.area.p1(), { mPadding * 2, side.area.size.y } };
|
|
||||||
rec.x -= mPadding * 2;
|
|
||||||
side.resizeHandle = { rec, 0, (this->mArea.p3() - mCenterArea.p1()).x };
|
|
||||||
}
|
|
||||||
if (isSideVisible(TOP)) {
|
|
||||||
auto& side = mSideWidgets[TOP];
|
|
||||||
rec = { side.area.p2(), { side.area.size.x, mPadding * 2 } };
|
|
||||||
side.resizeHandle = { rec, 0, mCenterArea.p2().y };
|
|
||||||
}
|
|
||||||
if (isSideVisible(BOTTOM)) {
|
|
||||||
auto& side = mSideWidgets[BOTTOM];
|
|
||||||
rec = { side.area.p1(), { side.area.size.x, mPadding * 2 } };
|
|
||||||
rec.y -= mPadding * 2;
|
|
||||||
side.resizeHandle = { rec, 0, (this->mArea.p3() - mCenterArea.p1()).y };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockWidget::handleResizeEvents(const Events& events) {
|
|
||||||
for (auto& sideWidget : mSideWidgets) {
|
|
||||||
auto& sideSize = sideWidget.absoluteSize;
|
|
||||||
auto& resizeHandle = sideWidget.resizeHandle;
|
|
||||||
if (resizeHandle.end < mSideSizePadding * 2) {
|
|
||||||
sideSize = resizeHandle.end / 2.f;
|
|
||||||
} else {
|
|
||||||
sideSize = clamp(sideSize, resizeHandle.start + mSideSizePadding, resizeHandle.end - mSideSizePadding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& sideWidget : mSideWidgets) {
|
|
||||||
sideWidget.resizeHandle.hover = false;
|
|
||||||
if (sideWidget.resizeHandle.area.isInside(events.getPointerPrev())) {
|
|
||||||
sideWidget.resizeHandle.hover = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& sideWidget : mSideWidgets) {
|
|
||||||
sideWidget.resizeHandle.active = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mPreview) return;
|
|
||||||
|
|
||||||
auto resizeSideWidget = [&events](SideWidgetData& sideWidget, Vec2F deltaVec) {
|
|
||||||
halnf delta = deltaVec[(sideWidget.side == TOP || sideWidget.side == BOTTOM)];
|
|
||||||
if (sideWidget.side == BOTTOM || sideWidget.side == RIGHT) delta *= -1;
|
|
||||||
sideWidget.absoluteSize += delta;
|
|
||||||
sideWidget.resizeHandle.active = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (events.isDown(InputID::MOUSE1)) {
|
|
||||||
for (auto& sideWidget : mSideWidgets) {
|
|
||||||
if (sideWidget.resizeHandle.area.isInside(events.getPointerPrev())) {
|
|
||||||
resizeSideWidget(sideWidget, events.getPointerDelta());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (events.isDown(InputID::LEFT_ALT)) {
|
|
||||||
const auto pointer = events.getPointerPrev();
|
|
||||||
if (!mCenterArea.isInside(pointer)) return;
|
|
||||||
|
|
||||||
if (events.isPressed(InputID::MOUSE1)) {
|
|
||||||
for (auto i : { 0, 1 }) {
|
|
||||||
const auto step = mCenterArea.size[i] / 3.f;
|
|
||||||
const auto rec1 = mCenterArea.pos[i];
|
|
||||||
const auto pos = pointer[i];
|
|
||||||
if (pos > rec1 && pos < rec1 + step) resizeType[i] = 0;
|
|
||||||
if (pos > rec1 + step && pos < rec1 + step * 2) resizeType[i] = 1;
|
|
||||||
if (pos > rec1 + step * 2) resizeType[i] = 2;
|
|
||||||
}
|
|
||||||
} else if (events.isDown(InputID::MOUSE1)) {
|
|
||||||
const auto deltaVec = events.getPointerDelta();
|
|
||||||
|
|
||||||
if (resizeType[0] == 0) resizeSideWidget(mSideWidgets[LEFT], deltaVec);
|
|
||||||
if (resizeType[1] == 0) resizeSideWidget(mSideWidgets[TOP], deltaVec);
|
|
||||||
if (resizeType[0] == 2) resizeSideWidget(mSideWidgets[RIGHT], deltaVec);
|
|
||||||
if (resizeType[1] == 2) resizeSideWidget(mSideWidgets[BOTTOM], deltaVec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockWidget::updateChildSideWidgets() {
|
|
||||||
// Update Child Widgets
|
|
||||||
{
|
|
||||||
for (ualni i = 0; i < 4; i++) {
|
|
||||||
if (!sideExists(Side(i))) continue;
|
|
||||||
auto widget = mSideWidgets[i].widget;
|
|
||||||
|
|
||||||
if (!isSideVisible(Side(i))) {
|
|
||||||
widget->mEnable = false;
|
|
||||||
} else {
|
|
||||||
widget->setArea(mSideWidgets[i].area);
|
|
||||||
widget->mEnable = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mCenterWidget) mCenterWidget->setArea(mCenterArea);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update depth order
|
|
||||||
/*
|
|
||||||
if (mChildWidgets.size() > 1) {
|
|
||||||
for (auto sideChild : mSideWidgets) {
|
|
||||||
if (!sideChild) continue;
|
|
||||||
|
|
||||||
for (auto childNode = mChildWidgets.firstNode(); childNode; childNode = childNode->next) {
|
|
||||||
if (childNode->data == sideChild) {
|
|
||||||
mChildWidgets.detach(childNode);
|
|
||||||
mChildWidgets.pushBack(childNode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockWidget::calculateHeaderAreas() {
|
|
||||||
for (ualni i = 0; i < 4; i++) {
|
|
||||||
if (!isSideVisible(Side(i))) continue;
|
|
||||||
auto& area = mSideWidgets[i].area;
|
|
||||||
const auto factor = mHeaderSize / area.size.y;
|
|
||||||
mSideWidgets[i].headerArea = area.splitByFactorVT(factor);
|
|
||||||
area = area.splitByFactorVB(factor);
|
|
||||||
|
|
||||||
mSideWidgets[i].headerArea.size.y -= mPadding;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DockWidget::isSideVisible(DockWidget::Side side) {
|
|
||||||
return sideExists(side) && !mSideWidgets[side].hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DockWidget::sideExists(DockWidget::Side side) { return mSideWidgets[side].widget; }
|
|
||||||
|
|
||||||
ualni DockWidget::getVisibleSidesSize() {
|
|
||||||
ualni out = 0;
|
|
||||||
for (ualni i = 0; i < 4; i++) {
|
|
||||||
if (isSideVisible(Side(i))) out++;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
DockWidget::Side DockWidget::getPreviewSide() { return mPreviewSide; }
|
|
||||||
|
|
||||||
void DockWidget::handlePreview(const Events& events) {
|
|
||||||
if (!mPreview) {
|
|
||||||
mPreviewSide = NONE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const halnf factor = 0.3;
|
|
||||||
const halnf handleFactor = 0.1;
|
|
||||||
|
|
||||||
const auto handleSize = min(mCenterArea.size.x, mCenterArea.size.y) * handleFactor;
|
|
||||||
|
|
||||||
for (auto& sideWidget : mSideWidgets) {
|
|
||||||
if (sideWidget.widget) continue;
|
|
||||||
|
|
||||||
switch (sideWidget.side) {
|
|
||||||
case TOP: sideWidget.area = mCenterArea.splitByFactorVT(factor); break;
|
|
||||||
case BOTTOM: sideWidget.area = mCenterArea.splitByFactorVB(1 - factor); break;
|
|
||||||
case LEFT: sideWidget.area = mCenterArea.splitByFactorHL(factor); break;
|
|
||||||
case RIGHT: sideWidget.area = mCenterArea.splitByFactorHR(1 - factor); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sideWidget.area = sideWidget.area.shrink(mPadding * 2);
|
|
||||||
sideWidget.previewHandleArea = sideWidget.area.getSizedFromCenter({ handleSize, handleSize });
|
|
||||||
}
|
|
||||||
|
|
||||||
mPreviewArea = {};
|
|
||||||
mPreviewSide = NONE;
|
|
||||||
for (auto& sideWidget : mSideWidgets) {
|
|
||||||
if (sideWidget.widget) continue;
|
|
||||||
|
|
||||||
if (sideWidget.previewHandleArea.isInside(events.getPointer())) {
|
|
||||||
mPreviewArea = sideWidget.area;
|
|
||||||
mPreviewSide = sideWidget.side;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
#include "LabelWidget.hpp"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
LabelWidget::LabelWidget() { this->mArea = { 0, 0, 100, 30 }; }
|
|
||||||
|
|
||||||
void LabelWidget::eventDraw(Canvas& canvas) {
|
|
||||||
canvas.text(mLabel.c_str(), this->mArea, fontSize, Canvas::LC, padding, fontColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LabelWidget::eventUpdateConfiguration(WidgetManager& wm) {
|
|
||||||
wm.setActiveId("Label");
|
|
||||||
|
|
||||||
fontSize = wm.getNumber("Size", "FontSize");
|
|
||||||
padding = wm.getNumber("Padding", "Padding");
|
|
||||||
fontColor = wm.getColor("Default", "Front");
|
|
||||||
}
|
|
||||||
|
|
@ -1,179 +0,0 @@
|
||||||
#include "ScrollableWidget.hpp"
|
|
||||||
#include "../../WidgetsNew/public/widgets/ScrollableWidget.hpp"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
ScrollBarWidget::ScrollBarWidget() = default;
|
|
||||||
|
|
||||||
void ScrollBarWidget::eventProcess(const Events& events) {
|
|
||||||
auto area = getHandle();
|
|
||||||
mHovered = getHandleHandle().isInside(events.getPointer());
|
|
||||||
|
|
||||||
if (mSizeFraction > 1.f) {
|
|
||||||
mPositionFraction = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (events.getScrollY() != 0 && mArea.isInside(events.getPointer())) {
|
|
||||||
auto offset = events.getScrollY() < 0 ? 1.0f : -1.0f;
|
|
||||||
mPositionFraction += mSizeFraction * offset * 0.3f;
|
|
||||||
mPositionFraction = tp::clamp(mPositionFraction, 0.f, 1.f - mSizeFraction);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (events.isPressed(InputID::MOUSE1) && area.isInside(events.getPointer())) {
|
|
||||||
mIsScrolling = true;
|
|
||||||
} else if (events.isReleased(InputID::MOUSE1)) {
|
|
||||||
mIsScrolling = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mIsScrolling) {
|
|
||||||
tp::halnf pos = events.getPointer().y;
|
|
||||||
pos = (pos - area.y - mSizeFraction * area.w / 2.f) / area.w;
|
|
||||||
mPositionFraction = tp::clamp(pos, 0.f, 1.f - mSizeFraction);
|
|
||||||
}
|
|
||||||
|
|
||||||
mPositionFraction = tp::clamp(mPositionFraction, 0.f, 1.f - mSizeFraction);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScrollBarWidget::eventDraw(Canvas& canvas) {
|
|
||||||
auto area = getHandle();
|
|
||||||
|
|
||||||
if (mSizeFraction > 1.f) return;
|
|
||||||
// if (!areaParent.isOverlap(getHandle())) return;
|
|
||||||
|
|
||||||
tp::RGBA col = mHandleColor;
|
|
||||||
|
|
||||||
if (mIsScrolling) {
|
|
||||||
col = mScrollingColor;
|
|
||||||
} else if (mHovered) {
|
|
||||||
col = mHoveredColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas.rect(area, mDefaultColor, mRounding);
|
|
||||||
canvas.rect(getHandleHandle(), col, mRounding);
|
|
||||||
}
|
|
||||||
|
|
||||||
RectF ScrollBarWidget::getHandleHandle() const {
|
|
||||||
auto area = getHandle();
|
|
||||||
auto sliderSize = tp::clamp(area.w * mSizeFraction, mMinSize * 2, area.w);
|
|
||||||
auto diffSize = sliderSize - area.w * mSizeFraction;
|
|
||||||
return { area.x, area.y + (area.w - diffSize) * mPositionFraction, area.z, sliderSize };
|
|
||||||
}
|
|
||||||
|
|
||||||
RectF ScrollBarWidget::getViewport() const {
|
|
||||||
if (mSizeFraction > 1.f) {
|
|
||||||
return this->mArea;
|
|
||||||
}
|
|
||||||
return { this->mArea.x, this->mArea.y, this->mArea.z - mHandleSize, this->mArea.w };
|
|
||||||
}
|
|
||||||
|
|
||||||
RectF ScrollBarWidget::getHandle() const {
|
|
||||||
return { this->mArea.x + this->mArea.z - mHandleSize + mPadding,
|
|
||||||
this->mArea.y + mPadding,
|
|
||||||
mHandleSize - mPadding * 2,
|
|
||||||
this->mArea.w - mPadding * 2 };
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScrollBarWidget::eventUpdateConfiguration(WidgetManager& wm) {
|
|
||||||
wm.setActiveId("Scrollbar");
|
|
||||||
|
|
||||||
mDefaultColor = wm.getColor("Default", "Base");
|
|
||||||
mHandleColor = wm.getColor("Handle", "Accent");
|
|
||||||
mHoveredColor = wm.getColor("Hovered", "Interaction");
|
|
||||||
mScrollingColor = wm.getColor("Scrolling", "Action");
|
|
||||||
mPadding = wm.getNumber("Padding", "Padding");
|
|
||||||
mHandleSize = wm.getNumber("HandleSize", 20.f);
|
|
||||||
mMinSize = wm.getNumber("MinSize", 20.f);
|
|
||||||
mRounding = wm.getNumber("Rounding", "Rounding");
|
|
||||||
}
|
|
||||||
|
|
||||||
ScrollableWindow::ScrollableWindow() {
|
|
||||||
this->mChildWidgets.pushBack(&mScroller);
|
|
||||||
this->mChildWidgets.pushBack(&mContentWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
ScrollableWindow::~ScrollableWindow() = default;
|
|
||||||
|
|
||||||
void ScrollableWindow::eventProcess(const Events& events) {
|
|
||||||
List<Widget*>& content = mContentWidget.mChildWidgets;
|
|
||||||
|
|
||||||
// to account all changed geometry of child widgets
|
|
||||||
for (auto widget : content) {
|
|
||||||
widget->procWrapper(events, mContentWidget.mVisibleArea);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateContents(content);
|
|
||||||
updateContentSize(content);
|
|
||||||
|
|
||||||
const auto padding = mPadding;
|
|
||||||
|
|
||||||
mScroller.mSizeFraction = mContentWidget.mArea.w / mContentSize;
|
|
||||||
mScroller.setArea(this->mArea);
|
|
||||||
mContentWidget.setArea(mScroller.getViewport());
|
|
||||||
|
|
||||||
if (mScroller.mSizeFraction > 1.f) {
|
|
||||||
setOffset(content, 0);
|
|
||||||
} else {
|
|
||||||
setOffset(content, (-mScroller.mPositionFraction) * mContentSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto widget : content) {
|
|
||||||
widget->setArea({ mContentWidget.mArea.x + padding,
|
|
||||||
mContentWidget.mArea.y + widget->mArea.y,
|
|
||||||
mScroller.getViewport().z - padding * 2,
|
|
||||||
widget->mArea.w });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScrollableWindow::addWidget(Widget* widget) {
|
|
||||||
mContentWidget.mChildWidgets.pushBack(widget);
|
|
||||||
|
|
||||||
List<Widget*>& content = mContentWidget.mChildWidgets;
|
|
||||||
updateContents(content);
|
|
||||||
updateContentSize(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScrollableWindow::clearContent() { mContentWidget.mChildWidgets.removeAll(); }
|
|
||||||
List<Widget*>& ScrollableWindow::getContent() { return mContentWidget.mChildWidgets; }
|
|
||||||
|
|
||||||
void ScrollableWindow::eventUpdateConfiguration(WidgetManager& wm) {
|
|
||||||
wm.setActiveId("ScrollableWidget");
|
|
||||||
mPadding = wm.getNumber("Padding", "Padding");
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] halnf ScrollableWindow::getContentSize() const { return mContentSize; }
|
|
||||||
|
|
||||||
void ScrollableWindow::updateContents(List<Widget*>& contentWidgets) {
|
|
||||||
if (!contentWidgets.size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const halnf offset = contentWidgets.first()->mArea.y + mPadding;
|
|
||||||
|
|
||||||
halnf start = 0;
|
|
||||||
for (auto widget : contentWidgets) {
|
|
||||||
widget->mArea.y = start;
|
|
||||||
start += widget->mArea.w + mPadding;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto widget : contentWidgets) {
|
|
||||||
widget->mArea.y += offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScrollableWindow::updateContentSize(List<Widget*>& contentWidgets) {
|
|
||||||
mContentSize = 0;
|
|
||||||
if (contentWidgets.size()) {
|
|
||||||
mContentSize = contentWidgets.last()->mArea.y - contentWidgets.first()->mArea.y;
|
|
||||||
mContentSize += contentWidgets.last()->mArea.w;
|
|
||||||
mContentSize += 2 * mPadding;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScrollableWindow::setOffset(List<Widget*>& contentWidgets, const halnf offset) {
|
|
||||||
if (!contentWidgets.size()) return;
|
|
||||||
auto newOffset = offset - contentWidgets.first()->mArea.y + mPadding;
|
|
||||||
for (auto widget : contentWidgets) {
|
|
||||||
widget->mArea.y += newOffset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
#include "SliderWidget.hpp"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
SliderWidget::SliderWidget() = default;
|
|
||||||
|
|
||||||
void SliderWidget::eventProcess(const Events& events) {
|
|
||||||
if (this->isPressed()) {
|
|
||||||
mIsSliding = true;
|
|
||||||
} else if (events.isReleased(InputID::MOUSE1)) {
|
|
||||||
mIsSliding = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mIsSliding) {
|
|
||||||
mFactor = (events.getPointer().x - this->mArea.x - handleSize / 2.f) / (this->mArea.z - handleSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
mFactor = tp::clamp(mFactor, 0.f, 1.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SliderWidget::eventDraw(Canvas& canvas) {
|
|
||||||
canvas.rect(this->mArea, handleColor, rounding);
|
|
||||||
canvas.rect(this->mArea.shrink(borderSize), defaultColor, rounding);
|
|
||||||
canvas.rect(getHandle(), handleColor, rounding);
|
|
||||||
}
|
|
||||||
|
|
||||||
RectF SliderWidget::getHandle() const {
|
|
||||||
const auto left = this->mArea.x + (this->mArea.z - handleSize) * mFactor;
|
|
||||||
return { left, this->mArea.y, handleSize, this->mArea.w };
|
|
||||||
}
|
|
||||||
|
|
||||||
void SliderWidget::eventUpdateConfiguration(WidgetManager& wm) {
|
|
||||||
wm.setActiveId("Slider");
|
|
||||||
defaultColor = wm.getColor("Default", "Base");
|
|
||||||
handleColor = wm.getColor("Handle", RGBA(0.3f, 0.3f, 0.3f, 1.f));
|
|
||||||
borderSize = wm.getNumber("BorderSize", 2);
|
|
||||||
handleSize = wm.getNumber("HandleSize", 15.f);
|
|
||||||
rounding = wm.getNumber("Rounding", "Rounding");
|
|
||||||
}
|
|
||||||
|
|
||||||
NamedSliderWidget::NamedSliderWidget(const char* name) {
|
|
||||||
mLabel.mLabel = name;
|
|
||||||
this->mArea = { 0, 0, 100, 30 };
|
|
||||||
|
|
||||||
this->mChildWidgets.pushBack(&mSlider);
|
|
||||||
this->mChildWidgets.pushBack(&mLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedSliderWidget::eventProcess(const Events& events) {
|
|
||||||
const auto widthFirst = this->mArea.z * mFactor;
|
|
||||||
const auto widthSecond = this->mArea.z * (1.f - mFactor);
|
|
||||||
|
|
||||||
RectF rec = this->mArea;
|
|
||||||
rec.size.x = widthFirst;
|
|
||||||
|
|
||||||
mLabel.setArea(rec);
|
|
||||||
|
|
||||||
rec.pos.x += widthFirst;
|
|
||||||
rec.size.x = widthSecond;
|
|
||||||
|
|
||||||
mSlider.setArea(rec);
|
|
||||||
}
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
#include "TextInputWidget.hpp"
|
|
||||||
|
|
||||||
#include "imgui.h"
|
|
||||||
#include "imgui_internal.h"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
TextInputWidget::TextInputWidget() = default;
|
|
||||||
|
|
||||||
void TextInputWidget::eventDraw(Canvas&) {
|
|
||||||
nChanged = false;
|
|
||||||
|
|
||||||
const auto col = mAccentColor;
|
|
||||||
const auto colSel = mHoveredColor;
|
|
||||||
|
|
||||||
ImGui::GetStyle().Colors[ImGuiCol_FrameBg] = { col.r, col.g, col.b, col.a };
|
|
||||||
ImGui::GetStyle().Colors[ImGuiCol_TextSelectedBg] = { colSel.r, colSel.g, colSel.b, colSel.a };
|
|
||||||
|
|
||||||
ImGui::SetNextWindowPos({ this->mArea.x, this->mArea.y });
|
|
||||||
ImGui::SetNextWindowSize({ this->mArea.z, this->mArea.w });
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0, 0 });
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, mRounding * 1.5f);
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { mPadding, mPadding });
|
|
||||||
|
|
||||||
// ImGui::PushID((int) alni(this));
|
|
||||||
ImGui::Begin(
|
|
||||||
mId.c_str(),
|
|
||||||
0,
|
|
||||||
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoBackground |
|
|
||||||
ImGuiWindowFlags_NoResize
|
|
||||||
);
|
|
||||||
|
|
||||||
if (mMultiline) {
|
|
||||||
if (ImGui::InputTextMultiline("input", mBuff, mMaxBufferSize, { this->mArea.z, this->mArea.w })) {
|
|
||||||
mValue = mBuff;
|
|
||||||
nChanged = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (ImGui::InputTextEx("input", mId.c_str(), mBuff, mMaxBufferSize, { this->mArea.z, this->mArea.w }, 0)) {
|
|
||||||
mValue = mBuff;
|
|
||||||
nChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
ImGui::PopStyleVar(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextInputWidget::eventUpdateConfiguration(WidgetManager& wm) {
|
|
||||||
wm.setActiveId("TextInput");
|
|
||||||
|
|
||||||
mAccentColor = wm.getColor("Accent", "Accent");
|
|
||||||
mBaseColor = wm.getColor("Base", "Base");
|
|
||||||
mRounding = wm.getNumber("Rounding", "Rounding");
|
|
||||||
mHoveredColor = wm.getColor("Hovered", "Accent");
|
|
||||||
mPadding = wm.getNumber("Padding", "Padding");
|
|
||||||
}
|
|
||||||
|
|
@ -1,140 +0,0 @@
|
||||||
#include "WidgetBase.hpp"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
Widget::Widget() { mArea = { 0, 0, 100, 100 }; }
|
|
||||||
|
|
||||||
Widget::~Widget() = default;
|
|
||||||
|
|
||||||
void Widget::procWrapper(const Events& events, const RectF& parentArea) {
|
|
||||||
if (!mEnable) return;
|
|
||||||
|
|
||||||
checkVisibility(events, parentArea);
|
|
||||||
|
|
||||||
if (!mVisible) return;
|
|
||||||
|
|
||||||
checkFocus(events);
|
|
||||||
|
|
||||||
checkClicked(events);
|
|
||||||
|
|
||||||
if (mHandlesEvents) {
|
|
||||||
|
|
||||||
for (auto child : mChildWidgets) {
|
|
||||||
child->procWrapper(events, mVisibleArea);
|
|
||||||
}
|
|
||||||
|
|
||||||
eventProcess(events);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Widget::drawWrapper(Canvas& canvas) {
|
|
||||||
if (!mEnable || !mVisible) return;
|
|
||||||
|
|
||||||
eventDraw(canvas);
|
|
||||||
|
|
||||||
// draw child widgets
|
|
||||||
canvas.pushClamp(this->mArea);
|
|
||||||
for (auto child = mChildWidgets.lastNode(); child; child = child->prev) {
|
|
||||||
child->data->drawWrapper(canvas);
|
|
||||||
}
|
|
||||||
canvas.popClamp();
|
|
||||||
|
|
||||||
eventDrawOver(canvas);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Widget::updateConfigWrapper(WidgetManager& wm) {
|
|
||||||
wm.setActiveId("Global");
|
|
||||||
|
|
||||||
eventUpdateConfiguration(wm);
|
|
||||||
|
|
||||||
for (auto child : mChildWidgets) {
|
|
||||||
child->updateConfigWrapper(wm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Widget::eventProcess(const Events& events) {}
|
|
||||||
void Widget::eventDraw(Canvas& canvas) {}
|
|
||||||
void Widget::eventDrawOver(Canvas& canvas) {}
|
|
||||||
void Widget::eventUpdateConfiguration(WidgetManager& wm) {}
|
|
||||||
|
|
||||||
void Widget::eventVisible(const Events& events) {}
|
|
||||||
void Widget::eventNotVisible(const Events& events) {}
|
|
||||||
|
|
||||||
void Widget::eventFocusEnter(const Events& events) {}
|
|
||||||
void Widget::eventFocusLeave(const Events& events) {}
|
|
||||||
|
|
||||||
void Widget::eventPressed(const Events& events) {}
|
|
||||||
void Widget::eventReleased(const Events& events) {}
|
|
||||||
|
|
||||||
void Widget::checkVisibility(const Events& events, const RectF& parentArea) {
|
|
||||||
const bool currentVisibility = parentArea.isOverlap(getArea());
|
|
||||||
|
|
||||||
parentArea.calcIntersection(mArea, mVisibleArea);
|
|
||||||
|
|
||||||
if (currentVisibility != mVisible) {
|
|
||||||
if (currentVisibility) eventVisible(events);
|
|
||||||
else eventNotVisible(events);
|
|
||||||
}
|
|
||||||
|
|
||||||
mVisible = currentVisibility;
|
|
||||||
|
|
||||||
if (!mVisible) {
|
|
||||||
mHolding = false;
|
|
||||||
mPressed = false;
|
|
||||||
mReleased = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Widget::checkFocus(const Events& events) {
|
|
||||||
const bool currentFocus = mVisibleArea.isInside(events.getPointerPrev());
|
|
||||||
|
|
||||||
if (currentFocus != mInFocus) {
|
|
||||||
if (currentFocus) eventFocusEnter(events);
|
|
||||||
else eventFocusLeave(events);
|
|
||||||
}
|
|
||||||
|
|
||||||
mInFocus = currentFocus;
|
|
||||||
|
|
||||||
if (!mInFocus) {
|
|
||||||
mHolding = false;
|
|
||||||
mPressed = false;
|
|
||||||
mReleased = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Widget::checkClicked(const Events& events) {
|
|
||||||
mPressed = false;
|
|
||||||
mReleased = false;
|
|
||||||
|
|
||||||
if (!mInFocus) return;
|
|
||||||
|
|
||||||
if (mHolding) {
|
|
||||||
if (events.isReleased(InputID::MOUSE1)) {
|
|
||||||
eventReleased(events);
|
|
||||||
mReleased = true;
|
|
||||||
mHolding = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (events.isPressed(InputID::MOUSE1) && mVisibleArea.isInside(events.getPointer())) {
|
|
||||||
eventPressed(events);
|
|
||||||
mHolding = true;
|
|
||||||
mPressed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Widget::setEnable(bool enable) { mEnable = enable; }
|
|
||||||
void Widget::setVisible(bool visible) { mVisible = visible; }
|
|
||||||
void Widget::setArea(const RectF& area) { mArea = area; }
|
|
||||||
|
|
||||||
const RectF& Widget::getArea() const { return mArea; }
|
|
||||||
bool Widget::isFocus() const { return mInFocus; }
|
|
||||||
bool Widget::isPressed() const { return mPressed; }
|
|
||||||
bool Widget::isReleased() const { return mReleased; }
|
|
||||||
bool Widget::isHolding() const { return mHolding; }
|
|
||||||
|
|
||||||
void Widget::clearEvents() {
|
|
||||||
mReleased = false;
|
|
||||||
mPressed = false;
|
|
||||||
mHolding = false;
|
|
||||||
}
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
#include "WidgetManager.hpp"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
WidgetManager::WidgetManager() { initGlobalParameters(); }
|
|
||||||
WidgetManager::~WidgetManager() { mConfigurations.removeAll(); }
|
|
||||||
|
|
||||||
const RGBA& WidgetManager::getColor(const std::string& parameterId, const RGBA& defaultValue) {
|
|
||||||
WidgetConfig& config = getWidgetConfig(mActiveId);
|
|
||||||
Parameter& parameter = getParameter(config, parameterId, Parameter(defaultValue));
|
|
||||||
return parameter.color;
|
|
||||||
}
|
|
||||||
|
|
||||||
const RGBA& WidgetManager::getColor(const std::string& parameterId, const char* globalRef) {
|
|
||||||
WidgetConfig& config = getWidgetConfig(mActiveId);
|
|
||||||
Parameter& parameter = getParameter(config, parameterId, Parameter(globalRef, Parameter::COL));
|
|
||||||
return parameter.color;
|
|
||||||
}
|
|
||||||
|
|
||||||
halnf WidgetManager::getNumber(const std::string& parameterId, halnf defaultValue) {
|
|
||||||
WidgetConfig& config = getWidgetConfig(mActiveId);
|
|
||||||
Parameter& parameter = getParameter(config, parameterId, Parameter(defaultValue));
|
|
||||||
return parameter.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
halnf WidgetManager::getNumber(const std::string& parameterId, const char* globalRef) {
|
|
||||||
WidgetConfig& config = getWidgetConfig(mActiveId);
|
|
||||||
Parameter& parameter = getParameter(config, parameterId, Parameter(globalRef, Parameter::VAL));
|
|
||||||
return parameter.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WidgetManager::setActiveId(const std::string& id) { mActiveId = id; }
|
|
||||||
|
|
||||||
WidgetConfig& WidgetManager::getWidgetConfig(const std::string& id) {
|
|
||||||
auto idx = mConfigurations.presents(id);
|
|
||||||
if (idx) return mConfigurations.getSlotVal(idx);
|
|
||||||
mConfigurations.put(id, {});
|
|
||||||
return mConfigurations.get(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
WidgetManager::Parameter& WidgetManager::getParameter(WidgetConfig& config, const std::string& id, const Parameter& defaultValue) {
|
|
||||||
auto idx = config.mParameters.presents(id);
|
|
||||||
|
|
||||||
if (!idx) {
|
|
||||||
config.mParameters.put(id, defaultValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
Parameter& parameter = config.mParameters.get(id);
|
|
||||||
|
|
||||||
if (parameter.globalReference) {
|
|
||||||
return mGlobalConfig.mParameters.get(parameter.globalId);
|
|
||||||
} else {
|
|
||||||
return parameter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WidgetManager::initGlobalParameters() {
|
|
||||||
auto& params = mGlobalConfig.mParameters;
|
|
||||||
|
|
||||||
params.put("FontSize", Parameter(15.f));
|
|
||||||
|
|
||||||
params.put("FontSizeDim", Parameter(12.f));
|
|
||||||
params.put("Rounding", Parameter(5.f));
|
|
||||||
params.put("Padding", Parameter(5.f));
|
|
||||||
params.put("HandleSize", Parameter(5.f));
|
|
||||||
|
|
||||||
params.put("Background", Parameter(RGBA{ 0.03f, 0.03f, 0.03f, 1.f }));
|
|
||||||
params.put("Base", Parameter(RGBA{ 0.07f, 0.07f, 0.07f, 1.f }));
|
|
||||||
params.put("Accent", Parameter(RGBA{ 0.13f, 0.13f, 0.13f, 1.f }));
|
|
||||||
params.put("Interaction", Parameter(RGBA{ 0.33f, 0.33f, 0.3f, 1.f }));
|
|
||||||
params.put("Action", Parameter(RGBA{ 0.44f, 0.44f, 0.4f, 1.f }));
|
|
||||||
params.put("Front", Parameter(RGBA{ 1.f, 1.f, 1.f, 1.f }));
|
|
||||||
params.put("FrontDim", Parameter(RGBA{ 0.7f, 0.7f, 0.7f, 1.f }));
|
|
||||||
}
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
#include "WorkspaceWidget.hpp"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
WorkspaceWidget::WorkspaceWidget() {
|
|
||||||
this->mChildWidgets.pushBack(&mFloatingLayer);
|
|
||||||
this->mChildWidgets.pushBack(&mDockSpace);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorkspaceWidget::eventProcess(const Events& events) {
|
|
||||||
mDockSpace.setArea(this->mArea);
|
|
||||||
mFloatingLayer.setArea(this->mArea);
|
|
||||||
|
|
||||||
mDockSpace.mPreview = false;
|
|
||||||
mDockSpace.mHandlesEvents = !mFloatingLayer.handlesEvent();
|
|
||||||
|
|
||||||
for (auto floatingChild : mFloatingLayer.mChildWidgets) {
|
|
||||||
auto widget = dynamic_cast<FloatingWidget*>(floatingChild.data());
|
|
||||||
if (!widget) continue;
|
|
||||||
|
|
||||||
if (widget->mDropped) {
|
|
||||||
auto side = mDockSpace.getPreviewSide();
|
|
||||||
if (side != DockWidget::NONE) {
|
|
||||||
mFloatingLayer.mChildWidgets.removeNode(mFloatingLayer.mChildWidgets.find(widget));
|
|
||||||
widget->setCollapsed(false);
|
|
||||||
widget->stopFloating();
|
|
||||||
mDockSpace.addSideWidget(widget, side);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (widget->isFloating()) {
|
|
||||||
mDockSpace.mHandlesEvents = true;
|
|
||||||
mDockSpace.mPreview = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& dockedChild : mDockSpace.mSideWidgets) {
|
|
||||||
auto widget = dynamic_cast<FloatingWidget*>(dockedChild.widget);
|
|
||||||
if (!widget) continue;
|
|
||||||
|
|
||||||
if (widget->isFloating()) {
|
|
||||||
mDockSpace.removeSideWidget(dockedChild.side);
|
|
||||||
mFloatingLayer.mChildWidgets.pushBack(widget);
|
|
||||||
widget->mArea.pos = events.getPointer() - 20;
|
|
||||||
widget->mArea.size = mDefaultFloatSize;
|
|
||||||
|
|
||||||
widget->mResizable = true;
|
|
||||||
// widget->mBorders = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// toggle hide state
|
|
||||||
if (events.isDown(InputID::LEFT_ALT)) {
|
|
||||||
if (events.isPressed(InputID::N1)) {
|
|
||||||
mDockSpace.toggleHiddenState(DockWidget::LEFT);
|
|
||||||
} else if (events.isPressed(InputID::N2)) {
|
|
||||||
mDockSpace.toggleHiddenState(DockWidget::TOP);
|
|
||||||
} else if (events.isPressed(InputID::N3)) {
|
|
||||||
mDockSpace.toggleHiddenState(DockWidget::RIGHT);
|
|
||||||
} else if (events.isPressed(InputID::N4)) {
|
|
||||||
mDockSpace.toggleHiddenState(DockWidget::BOTTOM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& dockedChild : mDockSpace.mSideWidgets) {
|
|
||||||
auto widget = dynamic_cast<FloatingWidget*>(dockedChild.widget);
|
|
||||||
if (!widget) continue;
|
|
||||||
|
|
||||||
widget->setCollapsed(false);
|
|
||||||
widget->mResizable = false;
|
|
||||||
// widget->mBorders = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Color.hpp"
|
|
||||||
#include "Rect.hpp"
|
|
||||||
#include "Timing.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
class AnimValue {
|
|
||||||
halnf mValPrev = 0;
|
|
||||||
halnf mVal = 0;
|
|
||||||
time_ms mTimeStart = 0;
|
|
||||||
halni mTimeAnim = 250;
|
|
||||||
|
|
||||||
static bool gInTransition;
|
|
||||||
|
|
||||||
private:
|
|
||||||
[[nodiscard]] halnf interpolate() const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
AnimValue();
|
|
||||||
explicit AnimValue(halnf val);
|
|
||||||
|
|
||||||
[[nodiscard]] halnf prev() const { return mValPrev; }
|
|
||||||
void set(halnf val);
|
|
||||||
void setNoTransition(halnf);
|
|
||||||
void setAnimTime(halni time);
|
|
||||||
[[nodiscard]] halnf get() const;
|
|
||||||
[[nodiscard]] halnf getTarget() const;
|
|
||||||
[[nodiscard]] bool inTransition() const;
|
|
||||||
explicit operator halnf() const;
|
|
||||||
void operator=(halnf val);
|
|
||||||
};
|
|
||||||
|
|
||||||
class AnimRect : Rect<AnimValue> {
|
|
||||||
public:
|
|
||||||
AnimRect() {
|
|
||||||
setAnimTime(450);
|
|
||||||
setNoTransition({ 0, 0, 0, 0 });
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] RectF get() const;
|
|
||||||
[[nodiscard]] RectF getTarget() const;
|
|
||||||
void setNoTransition(RectF);
|
|
||||||
void set(const RectF&);
|
|
||||||
void setAnimTime(halni time_ms);
|
|
||||||
};
|
|
||||||
|
|
||||||
class AnimColor {
|
|
||||||
public:
|
|
||||||
AnimColor();
|
|
||||||
AnimRect mColor;
|
|
||||||
|
|
||||||
[[nodiscard]] RGBA get() const;
|
|
||||||
void set(const RGBA&);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "LabelWidget.hpp"
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
class ButtonWidget : public Widget {
|
|
||||||
public:
|
|
||||||
// enum State { NONE, ANTICIPATION, ACTIVATED, CONFIRMED };
|
|
||||||
|
|
||||||
public:
|
|
||||||
ButtonWidget();
|
|
||||||
ButtonWidget(const std::string& label, const tp::RectF& aArea);
|
|
||||||
bool isFired();
|
|
||||||
void eventProcess(const Events&) override;
|
|
||||||
void eventDraw(Canvas& canvas) override;
|
|
||||||
void setLabel(const std::string& string);
|
|
||||||
|
|
||||||
public:
|
|
||||||
void eventUpdateConfiguration(WidgetManager& wm) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
LabelWidget mLabel;
|
|
||||||
// State mStat = NONE;
|
|
||||||
|
|
||||||
RGBA pressedColor;
|
|
||||||
RGBA hoveredColor;
|
|
||||||
RGBA accentColor;
|
|
||||||
halnf rounding = 0;
|
|
||||||
|
|
||||||
std::function<void()> mCallback = [](){};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "ScrollableWidget.hpp"
|
|
||||||
#include "ButtonWidget.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
class CollapsableMenu : public Widget {
|
|
||||||
public:
|
|
||||||
CollapsableMenu();
|
|
||||||
void eventProcess(const Events&) override;
|
|
||||||
void eventDraw(Canvas& canvas) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void addWidgetToMenu(Widget* widget);
|
|
||||||
void setLabel(const std::string& string);
|
|
||||||
|
|
||||||
void toggleCollapsed();
|
|
||||||
void setCollapsed(bool collapsed);
|
|
||||||
[[nodiscard]] bool getCollapsed() const;
|
|
||||||
void updateGeometry();
|
|
||||||
|
|
||||||
private:
|
|
||||||
RectF getHeaderRect();
|
|
||||||
RectF getBodyRect();
|
|
||||||
|
|
||||||
public:
|
|
||||||
void eventUpdateConfiguration(WidgetManager& wm) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
ScrollableWindow mBody;
|
|
||||||
LabelWidget mHeader;
|
|
||||||
|
|
||||||
RGBA mMenuColor;
|
|
||||||
RGBA mBorderColor;
|
|
||||||
|
|
||||||
halnf headerHeight = 30;
|
|
||||||
halnf rounding = 0;
|
|
||||||
halnf mBorderSize = 0;
|
|
||||||
halnf mPadding = 0;
|
|
||||||
|
|
||||||
halnf mPrevHeight = 200;
|
|
||||||
|
|
||||||
bool mCollapsed = true;
|
|
||||||
bool mLocked = false;
|
|
||||||
bool mAdjustHeight = true;
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool mBorders = true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
#include "FloatingWidget.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
class FloatingLayoutWidget : public Widget {
|
|
||||||
public:
|
|
||||||
FloatingLayoutWidget();
|
|
||||||
|
|
||||||
void eventProcess(const Events& events) override;
|
|
||||||
|
|
||||||
[[nodiscard]] bool handlesEvent() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void updateActiveWindow(const tp::Events& events);
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool mIsPassThrough = false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CollapsableMenu.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
class FloatingWidget : public CollapsableMenu {
|
|
||||||
public:
|
|
||||||
FloatingWidget();
|
|
||||||
|
|
||||||
void eventProcess(const Events& events) override;
|
|
||||||
void eventDraw(Canvas& canvas) override;
|
|
||||||
void eventUpdateConfiguration(WidgetManager& wm) override;
|
|
||||||
|
|
||||||
[[nodiscard]] bool isFloating() const;
|
|
||||||
void stopFloating();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void checkFloating(const Events& events);
|
|
||||||
void checkResizing(const Events& events);
|
|
||||||
RectF getResizeHandle();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Vec2F mMinSize = { 70, 70 };
|
|
||||||
|
|
||||||
halnf mResizeHandleSize = 10;
|
|
||||||
RGBA mResizeHandleColor = {};
|
|
||||||
|
|
||||||
bool mFloating = false;
|
|
||||||
bool mResizing = false;
|
|
||||||
|
|
||||||
Vec2F mActionStartRelativePos = {};
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool mResizable = true;
|
|
||||||
|
|
||||||
bool mDropped = false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
#include "WidgetBase.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
class DockWidget : public Widget {
|
|
||||||
public:
|
|
||||||
enum Side { LEFT, TOP, RIGHT, BOTTOM, NONE };
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct ResizeHandle {
|
|
||||||
RectF area{ 0, 0, 0, 0 };
|
|
||||||
halnf start{ 0 };
|
|
||||||
halnf end{ 0 };
|
|
||||||
bool active = false;
|
|
||||||
bool hover = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SideWidgetData {
|
|
||||||
Widget* widget = nullptr;
|
|
||||||
bool hidden = false;
|
|
||||||
halnf absoluteSize = 200;
|
|
||||||
alni order = -1;
|
|
||||||
|
|
||||||
Side side = { TOP };
|
|
||||||
|
|
||||||
RectF area = {};
|
|
||||||
RectF headerArea = {};
|
|
||||||
RectF previewHandleArea = {};
|
|
||||||
|
|
||||||
ResizeHandle resizeHandle;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
DockWidget();
|
|
||||||
|
|
||||||
void eventProcess(const Events& events) override;
|
|
||||||
void eventDraw(Canvas& canvas) override;
|
|
||||||
void eventDrawOver(Canvas& canvas) override;
|
|
||||||
|
|
||||||
void addSideWidget(Widget* widget, Side side);
|
|
||||||
void removeSideWidget(Side side);
|
|
||||||
|
|
||||||
void toggleHiddenState(Side side);
|
|
||||||
|
|
||||||
void setCenterWidget(Widget* widget);
|
|
||||||
|
|
||||||
Side getPreviewSide();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void calculateSideAreas();
|
|
||||||
void calculateResizeHandles();
|
|
||||||
void handleResizeEvents(const Events& events);
|
|
||||||
void updateChildSideWidgets();
|
|
||||||
|
|
||||||
void calculateHeaderAreas();
|
|
||||||
|
|
||||||
bool isSideVisible(Side side);
|
|
||||||
bool sideExists(DockWidget::Side side);
|
|
||||||
ualni getVisibleSidesSize();
|
|
||||||
void handlePreview(const Events& events);
|
|
||||||
|
|
||||||
private:
|
|
||||||
RectF mPreviewArea = {};
|
|
||||||
Side mPreviewSide = NONE;
|
|
||||||
int resizeType[2] = { 0, 0 };
|
|
||||||
|
|
||||||
public:
|
|
||||||
SideWidgetData mSideWidgets[4];
|
|
||||||
|
|
||||||
private:
|
|
||||||
Widget* mCenterWidget = nullptr;
|
|
||||||
RectF mCenterArea {};
|
|
||||||
|
|
||||||
// Parameters
|
|
||||||
halnf mSideSizePadding = 150.f;
|
|
||||||
halnf mPadding = 4;
|
|
||||||
halnf mHeaderSize = 27;
|
|
||||||
halnf mRounding = 10;
|
|
||||||
Vec2F mPreviewHandleSize = { 50, 50 };
|
|
||||||
|
|
||||||
RGBA mResizeHandleColorHovered = RGBA(0.3, 0.3, 0.3, 1);
|
|
||||||
RGBA mResizeHandleColorActive = RGBA(0.6, 0.6, 0.6, 1);
|
|
||||||
RGBA mBackgroundColor = RGBA(0, 0, 0, 1);
|
|
||||||
RGBA mPreviewColor = RGBA(0.6, 0.6, 0.6, 1);
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool mPreview = false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "WidgetBase.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
class LabelWidget : public Widget {
|
|
||||||
public:
|
|
||||||
LabelWidget();
|
|
||||||
|
|
||||||
void eventDraw(Canvas& canvas) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void eventUpdateConfiguration(WidgetManager& wm) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
std::string mLabel = "Label";
|
|
||||||
|
|
||||||
halnf fontSize = 10;
|
|
||||||
halnf padding = 0;
|
|
||||||
RGBA fontColor = { 1, 1, 1, 1 };
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "WidgetBase.hpp"
|
|
||||||
#include "Buffer.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
class ScrollBarWidget : public Widget {
|
|
||||||
public:
|
|
||||||
ScrollBarWidget();
|
|
||||||
|
|
||||||
// takes whole area
|
|
||||||
void eventProcess(const Events& events) override;
|
|
||||||
void eventDraw(Canvas& canvas) override;
|
|
||||||
|
|
||||||
RectF getHandleHandle() const;
|
|
||||||
RectF getViewport() const;
|
|
||||||
RectF getHandle() const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void eventUpdateConfiguration(WidgetManager& wm) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool mIsScrolling = false;
|
|
||||||
halnf mSizeFraction = 1.f;
|
|
||||||
halnf mPositionFraction = 0.f;
|
|
||||||
bool mHovered = false;
|
|
||||||
|
|
||||||
RGBA mDefaultColor;
|
|
||||||
RGBA mHandleColor;
|
|
||||||
RGBA mHoveredColor;
|
|
||||||
RGBA mScrollingColor;
|
|
||||||
halnf mPadding = 0;
|
|
||||||
halnf mHandleSize = 10;
|
|
||||||
halnf mMinSize = 10;
|
|
||||||
halnf mRounding = 10;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ScrollableWindow : public Widget {
|
|
||||||
public:
|
|
||||||
ScrollableWindow();
|
|
||||||
|
|
||||||
virtual ~ScrollableWindow();
|
|
||||||
|
|
||||||
// takes whole area
|
|
||||||
void eventProcess(const Events& events) override;
|
|
||||||
|
|
||||||
void addWidget(Widget* widget);
|
|
||||||
void clearContent();
|
|
||||||
List<Widget*>& getContent();
|
|
||||||
|
|
||||||
void eventUpdateConfiguration(WidgetManager& wm) override;
|
|
||||||
|
|
||||||
[[nodiscard]] halnf getContentSize() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void updateContents(List<Widget*>& contentWidgets);
|
|
||||||
|
|
||||||
// ready content size
|
|
||||||
void updateContentSize(List<Widget*>& contentWidgets);
|
|
||||||
void setOffset(List<Widget*>& contentWidgets, const halnf offset);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Widget mContentWidget;
|
|
||||||
ScrollBarWidget mScroller;
|
|
||||||
|
|
||||||
halnf mContentSize = 0;
|
|
||||||
|
|
||||||
halnf mPadding = 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "LabelWidget.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
class SliderWidget : public Widget {
|
|
||||||
public:
|
|
||||||
SliderWidget();
|
|
||||||
|
|
||||||
void eventProcess(const Events& events) override;
|
|
||||||
void eventDraw(Canvas& canvas) override;
|
|
||||||
|
|
||||||
RectF getHandle() const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void eventUpdateConfiguration(WidgetManager& wm) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
halnf mFactor = 0.f;
|
|
||||||
bool mIsSliding = false;
|
|
||||||
|
|
||||||
RGBA defaultColor;
|
|
||||||
RGBA handleColor;
|
|
||||||
halnf handleSize = 0;
|
|
||||||
halnf rounding = 0;
|
|
||||||
halnf borderSize = 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NamedSliderWidget : public Widget {
|
|
||||||
public:
|
|
||||||
explicit NamedSliderWidget(const char* name = "Value");
|
|
||||||
void eventProcess(const Events& events) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
SliderWidget mSlider;
|
|
||||||
LabelWidget mLabel;
|
|
||||||
|
|
||||||
halnf mFactor = 0.5f;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "WidgetBase.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
class TextInputWidget : public Widget {
|
|
||||||
public:
|
|
||||||
TextInputWidget();
|
|
||||||
|
|
||||||
void eventDraw(Canvas&) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void eventUpdateConfiguration(WidgetManager& wm) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum { mMaxBufferSize = 512 };
|
|
||||||
char mBuff[mMaxBufferSize] = "";
|
|
||||||
bool nChanged = false;
|
|
||||||
std::string mValue;
|
|
||||||
std::string mId = "id";
|
|
||||||
bool mMultiline = false;
|
|
||||||
|
|
||||||
RGBA mAccentColor;
|
|
||||||
RGBA mHoveredColor;
|
|
||||||
RGBA mBaseColor;
|
|
||||||
halnf mRounding = 0;
|
|
||||||
halnf mPadding = 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Graphics.hpp"
|
|
||||||
|
|
||||||
#include "EventHandler.hpp"
|
|
||||||
#include "WidgetManager.hpp"
|
|
||||||
#include "List.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
using Events = EventHandler;
|
|
||||||
|
|
||||||
class Widget {
|
|
||||||
public:
|
|
||||||
Widget();
|
|
||||||
virtual ~Widget();
|
|
||||||
|
|
||||||
void procWrapper(const Events& events, const RectF& parentArea);
|
|
||||||
void drawWrapper(Canvas& canvas);
|
|
||||||
void updateConfigWrapper(WidgetManager& wm);
|
|
||||||
|
|
||||||
virtual void eventProcess(const Events& events);
|
|
||||||
|
|
||||||
// draws before child widgets
|
|
||||||
virtual void eventDraw(Canvas& canvas);
|
|
||||||
|
|
||||||
// draws overlay after child widgets
|
|
||||||
virtual void eventDrawOver(Canvas& canvas);
|
|
||||||
|
|
||||||
virtual void eventUpdateConfiguration(WidgetManager& wm);
|
|
||||||
|
|
||||||
virtual void eventVisible(const Events& events);
|
|
||||||
virtual void eventNotVisible(const Events& events);
|
|
||||||
|
|
||||||
virtual void eventFocusEnter(const Events& events);
|
|
||||||
virtual void eventFocusLeave(const Events& events);
|
|
||||||
|
|
||||||
virtual void eventPressed(const Events& events);
|
|
||||||
virtual void eventReleased(const Events& events);
|
|
||||||
|
|
||||||
public:
|
|
||||||
void setEnable(bool enable);
|
|
||||||
void setVisible(bool visible);
|
|
||||||
void setArea(const RectF& area);
|
|
||||||
|
|
||||||
[[nodiscard]] const RectF& getArea() const;
|
|
||||||
[[nodiscard]] bool isFocus() const;
|
|
||||||
[[nodiscard]] bool isPressed() const;
|
|
||||||
[[nodiscard]] bool isReleased() const;
|
|
||||||
[[nodiscard]] bool isHolding() const;
|
|
||||||
|
|
||||||
void clearEvents();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void checkVisibility(const Events& events, const RectF& parentArea);
|
|
||||||
void checkFocus(const Events& events);
|
|
||||||
void checkClicked(const Events& events);
|
|
||||||
|
|
||||||
public:
|
|
||||||
RectF mArea;
|
|
||||||
RectF mVisibleArea;
|
|
||||||
|
|
||||||
List<Widget*> mChildWidgets;
|
|
||||||
|
|
||||||
bool mVisible = false;
|
|
||||||
bool mEnable = true;
|
|
||||||
bool mHandlesEvents = true;
|
|
||||||
bool mInFocus = false;
|
|
||||||
|
|
||||||
bool mHolding = false;
|
|
||||||
bool mPressed = false;
|
|
||||||
bool mReleased = false;
|
|
||||||
|
|
||||||
|
|
||||||
// docking
|
|
||||||
bool mIsDocked = false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Animations.hpp"
|
|
||||||
#include "Map.hpp"
|
|
||||||
#include "Rect.hpp"
|
|
||||||
|
|
||||||
#include "InputCodes.hpp"
|
|
||||||
#include "Buffer.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
struct WidgetConfig {
|
|
||||||
|
|
||||||
struct Shortcut {
|
|
||||||
struct Condition {
|
|
||||||
std::string name;
|
|
||||||
std::string state;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string callbackName;
|
|
||||||
|
|
||||||
Shortcut() = default;
|
|
||||||
Shortcut(const InitialierList<Condition>&) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Parameter {
|
|
||||||
enum Type { NONE, VAL, COL };
|
|
||||||
|
|
||||||
halnf value = 0.f;
|
|
||||||
RGBA color = {};
|
|
||||||
Type type = NONE;
|
|
||||||
bool globalReference = false;
|
|
||||||
std::string globalId;
|
|
||||||
|
|
||||||
Parameter() = default;
|
|
||||||
|
|
||||||
explicit Parameter(halnf val) {
|
|
||||||
type = VAL;
|
|
||||||
value = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit Parameter(const RGBA& val) {
|
|
||||||
type = COL;
|
|
||||||
color = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit Parameter(const std::string& id, const Type& referenceType) {
|
|
||||||
type = referenceType;
|
|
||||||
globalId = id;
|
|
||||||
globalReference = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Map<std::string, Parameter> mParameters;
|
|
||||||
Buffer<Shortcut> mShortcuts;
|
|
||||||
};
|
|
||||||
|
|
||||||
class WidgetManager {
|
|
||||||
public:
|
|
||||||
using Parameter = WidgetConfig::Parameter;
|
|
||||||
|
|
||||||
public:
|
|
||||||
WidgetManager();
|
|
||||||
~WidgetManager();
|
|
||||||
|
|
||||||
const RGBA& getColor(const std::string& parameterId, const RGBA& defaultValue);
|
|
||||||
const RGBA& getColor(const std::string& parameterId, const char* globalRef);
|
|
||||||
|
|
||||||
halnf getNumber(const std::string& parameterId, halnf defaultValue);
|
|
||||||
halnf getNumber(const std::string& parameterId, const char* globalRef);
|
|
||||||
|
|
||||||
void setActiveId(const std::string& id);
|
|
||||||
|
|
||||||
private:
|
|
||||||
WidgetConfig& getWidgetConfig(const std::string& id);
|
|
||||||
Parameter& getParameter(WidgetConfig& config, const std::string& id, const Parameter& defaultValue);
|
|
||||||
|
|
||||||
void initGlobalParameters();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Map<std::string, WidgetConfig> mConfigurations;
|
|
||||||
WidgetConfig mGlobalConfig;
|
|
||||||
|
|
||||||
RGBA mErrorColor = { 0, 0, 0, 1 };
|
|
||||||
halnf mErrorNumber = 0;
|
|
||||||
|
|
||||||
std::string mActiveId;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Animations.hpp"
|
|
||||||
#include "ButtonWidget.hpp"
|
|
||||||
#include "LabelWidget.hpp"
|
|
||||||
#include "ScrollableWidget.hpp"
|
|
||||||
#include "TextInputWidget.hpp"
|
|
||||||
#include "SliderWidget.hpp"
|
|
||||||
#include "CollapsableMenu.hpp"
|
|
||||||
#include "FloatingWidget.hpp"
|
|
||||||
#include "FloatingLayoutWidget.hpp"
|
|
||||||
#include "GridLayoutWidget.hpp"
|
|
||||||
#include "WorkspaceWidget.hpp"
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Widgets.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
class WorkspaceWidget : public Widget {
|
|
||||||
public:
|
|
||||||
WorkspaceWidget();
|
|
||||||
|
|
||||||
void eventProcess(const Events& events) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
DockWidget mDockSpace;
|
|
||||||
FloatingLayoutWidget mFloatingLayer;
|
|
||||||
|
|
||||||
// Parameters
|
|
||||||
Vec2F mDefaultFloatSize = { 200, 200 };
|
|
||||||
};
|
|
||||||
}
|
|
||||||
197
.clang-format
197
.clang-format
|
|
@ -1,211 +1,66 @@
|
||||||
---
|
# Generated from CLion C/C++ Code Style settings
|
||||||
BasedOnStyle: LLVM
|
BasedOnStyle: LLVM
|
||||||
AccessModifierOffset: -2
|
AccessModifierOffset: -2
|
||||||
AlignAfterOpenBracket: BlockIndent
|
AlignAfterOpenBracket: Align
|
||||||
AlignArrayOfStructures: None
|
AlignConsecutiveAssignments: None
|
||||||
AlignConsecutiveAssignments:
|
|
||||||
Enabled: false
|
|
||||||
AcrossEmptyLines: false
|
|
||||||
AcrossComments: false
|
|
||||||
AlignCompound: false
|
|
||||||
PadOperators: false
|
|
||||||
AlignConsecutiveBitFields:
|
|
||||||
Enabled: false
|
|
||||||
AcrossEmptyLines: false
|
|
||||||
AcrossComments: false
|
|
||||||
AlignCompound: false
|
|
||||||
PadOperators: false
|
|
||||||
AlignConsecutiveDeclarations:
|
|
||||||
Enabled: false
|
|
||||||
AcrossEmptyLines: false
|
|
||||||
AcrossComments: false
|
|
||||||
AlignCompound: false
|
|
||||||
PadOperators: false
|
|
||||||
AlignConsecutiveMacros:
|
|
||||||
Enabled: false
|
|
||||||
AcrossEmptyLines: false
|
|
||||||
AcrossComments: false
|
|
||||||
AlignCompound: false
|
|
||||||
PadOperators: false
|
|
||||||
AlignEscapedNewlines: Left
|
|
||||||
AlignOperands: Align
|
AlignOperands: Align
|
||||||
AlignTrailingComments: true
|
AllowAllArgumentsOnNextLine: false
|
||||||
AllowAllArgumentsOnNextLine: true
|
AllowAllConstructorInitializersOnNextLine: false
|
||||||
AllowAllConstructorInitializersOnNextLine: true
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
AllowAllParametersOfDeclarationOnNextLine: true
|
AllowShortBlocksOnASingleLine: Always
|
||||||
AllowShortBlocksOnASingleLine: Never
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
AllowShortCaseLabelsOnASingleLine: true
|
|
||||||
AllowShortEnumsOnASingleLine: true
|
|
||||||
AllowShortFunctionsOnASingleLine: All
|
AllowShortFunctionsOnASingleLine: All
|
||||||
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
|
AllowShortIfStatementsOnASingleLine: Always
|
||||||
AllowShortLambdasOnASingleLine: All
|
AllowShortLambdasOnASingleLine: All
|
||||||
AllowShortLoopsOnASingleLine: false
|
AllowShortLoopsOnASingleLine: true
|
||||||
AlwaysBreakAfterDefinitionReturnType: None
|
|
||||||
AlwaysBreakAfterReturnType: None
|
AlwaysBreakAfterReturnType: None
|
||||||
AlwaysBreakBeforeMultilineStrings: false
|
|
||||||
AlwaysBreakTemplateDeclarations: Yes
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
AttributeMacros:
|
BreakBeforeBraces: Custom
|
||||||
- __capability
|
|
||||||
BinPackArguments: false
|
|
||||||
BinPackParameters: false
|
|
||||||
BitFieldColonSpacing: Both
|
|
||||||
BraceWrapping:
|
BraceWrapping:
|
||||||
AfterCaseLabel: true
|
AfterCaseLabel: false
|
||||||
AfterClass: true
|
AfterClass: false
|
||||||
AfterControlStatement: Always
|
AfterControlStatement: Never
|
||||||
AfterEnum: false
|
AfterEnum: false
|
||||||
AfterFunction: false
|
AfterFunction: false
|
||||||
AfterNamespace: false
|
AfterNamespace: false
|
||||||
AfterObjCDeclaration: false
|
|
||||||
AfterStruct: false
|
|
||||||
AfterUnion: false
|
AfterUnion: false
|
||||||
AfterExternBlock: false
|
|
||||||
BeforeCatch: false
|
BeforeCatch: false
|
||||||
BeforeElse: false
|
BeforeElse: false
|
||||||
BeforeLambdaBody: false
|
|
||||||
BeforeWhile: false
|
|
||||||
IndentBraces: false
|
IndentBraces: false
|
||||||
SplitEmptyFunction: true
|
SplitEmptyFunction: false
|
||||||
SplitEmptyRecord: true
|
SplitEmptyRecord: true
|
||||||
SplitEmptyNamespace: true
|
|
||||||
BreakAfterJavaFieldAnnotations: false
|
|
||||||
BreakBeforeBinaryOperators: None
|
BreakBeforeBinaryOperators: None
|
||||||
BreakBeforeBraces: Attach
|
|
||||||
BreakBeforeConceptDeclarations: Always
|
|
||||||
BreakBeforeTernaryOperators: true
|
BreakBeforeTernaryOperators: true
|
||||||
BreakConstructorInitializers: AfterColon
|
BreakConstructorInitializers: BeforeColon
|
||||||
BreakInheritanceList: BeforeColon
|
BreakInheritanceList: BeforeColon
|
||||||
BreakStringLiterals: true
|
ColumnLimit: 0
|
||||||
ColumnLimit: 120
|
|
||||||
CommentPragmas: "^ IWYU pragma:"
|
|
||||||
CompactNamespaces: false
|
CompactNamespaces: false
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
ContinuationIndentWidth: 4
|
||||||
ConstructorInitializerIndentWidth: 2
|
|
||||||
ContinuationIndentWidth: 2
|
|
||||||
Cpp11BracedListStyle: false
|
|
||||||
DeriveLineEnding: true
|
|
||||||
DerivePointerAlignment: false
|
|
||||||
DisableFormat: false
|
|
||||||
EmptyLineAfterAccessModifier: Never
|
|
||||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
|
||||||
ExperimentalAutoDetectBinPacking: false
|
|
||||||
FixNamespaceComments: false
|
|
||||||
ForEachMacros:
|
|
||||||
- foreach
|
|
||||||
- Q_FOREACH
|
|
||||||
- BOOST_FOREACH
|
|
||||||
IfMacros:
|
|
||||||
- KJ_IF_MAYBE
|
|
||||||
IncludeBlocks: Preserve
|
|
||||||
IncludeCategories:
|
|
||||||
- Regex: ^"(llvm|llvm-c|clang|clang-c)/
|
|
||||||
Priority: 2
|
|
||||||
SortPriority: 0
|
|
||||||
CaseSensitive: false
|
|
||||||
- Regex: ^(<|"(gtest|gmock|isl|json)/)
|
|
||||||
Priority: 3
|
|
||||||
SortPriority: 0
|
|
||||||
CaseSensitive: false
|
|
||||||
- Regex: .*
|
|
||||||
Priority: 1
|
|
||||||
SortPriority: 0
|
|
||||||
CaseSensitive: false
|
|
||||||
IncludeIsMainRegex: (Test)?$
|
|
||||||
IncludeIsMainSourceRegex: ""
|
|
||||||
IndentAccessModifiers: false
|
|
||||||
IndentCaseBlocks: true
|
|
||||||
IndentCaseLabels: true
|
IndentCaseLabels: true
|
||||||
IndentExternBlock: AfterExternBlock
|
|
||||||
IndentGotoLabels: true
|
|
||||||
IndentPPDirectives: None
|
IndentPPDirectives: None
|
||||||
IndentRequiresClause: true
|
|
||||||
IndentWidth: 2
|
IndentWidth: 2
|
||||||
IndentWrappedFunctionNames: false
|
|
||||||
InsertBraces: false
|
|
||||||
InsertTrailingCommas: None
|
|
||||||
JavaScriptQuotes: Leave
|
|
||||||
JavaScriptWrapImports: true
|
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
LambdaBodyIndentation: Signature
|
MaxEmptyLinesToKeep: 2
|
||||||
Language: Cpp
|
|
||||||
MacroBlockBegin: ""
|
|
||||||
MacroBlockEnd: ""
|
|
||||||
MaxEmptyLinesToKeep: 1
|
|
||||||
NamespaceIndentation: All
|
NamespaceIndentation: All
|
||||||
ObjCBinPackProtocolList: Auto
|
|
||||||
ObjCBlockIndentWidth: 2
|
|
||||||
ObjCBreakBeforeNestedBlockParam: true
|
|
||||||
ObjCSpaceAfterProperty: false
|
ObjCSpaceAfterProperty: false
|
||||||
ObjCSpaceBeforeProtocolList: true
|
ObjCSpaceBeforeProtocolList: true
|
||||||
PPIndentWidth: -1
|
|
||||||
PackConstructorInitializers: Never
|
|
||||||
PenaltyBreakAssignment: 2
|
|
||||||
PenaltyBreakBeforeFirstCallParameter: 19
|
|
||||||
PenaltyBreakComment: 300
|
|
||||||
PenaltyBreakFirstLessLess: 120
|
|
||||||
PenaltyBreakOpenParenthesis: 0
|
|
||||||
PenaltyBreakString: 1000
|
|
||||||
PenaltyBreakTemplateDeclaration: 10
|
|
||||||
PenaltyExcessCharacter: 1000000
|
|
||||||
PenaltyIndentedWhitespace: 0
|
|
||||||
PenaltyReturnTypeOnItsOwnLine: 60
|
|
||||||
PointerAlignment: Left
|
PointerAlignment: Left
|
||||||
QualifierAlignment: Leave
|
ReflowComments: false
|
||||||
ReferenceAlignment: Pointer
|
|
||||||
ReflowComments: true
|
|
||||||
RemoveBracesLLVM: false
|
|
||||||
RequiresClausePosition: OwnLine
|
|
||||||
SeparateDefinitionBlocks: Leave
|
|
||||||
ShortNamespaceLines: 1
|
|
||||||
SortIncludes: Never
|
|
||||||
SortJavaStaticImport: Before
|
|
||||||
SortUsingDeclarations: true
|
|
||||||
SpaceAfterCStyleCast: true
|
SpaceAfterCStyleCast: true
|
||||||
SpaceAfterLogicalNot: false
|
SpaceAfterLogicalNot: false
|
||||||
SpaceAfterTemplateKeyword: true
|
SpaceAfterTemplateKeyword: false
|
||||||
SpaceAroundPointerQualifiers: Default
|
|
||||||
SpaceBeforeAssignmentOperators: true
|
SpaceBeforeAssignmentOperators: true
|
||||||
SpaceBeforeCaseColon: false
|
|
||||||
SpaceBeforeCpp11BracedList: false
|
SpaceBeforeCpp11BracedList: false
|
||||||
SpaceBeforeCtorInitializerColon: true
|
SpaceBeforeCtorInitializerColon: true
|
||||||
SpaceBeforeInheritanceColon: true
|
SpaceBeforeInheritanceColon: true
|
||||||
SpaceBeforeParens: ControlStatements
|
SpaceBeforeParens: ControlStatements
|
||||||
SpaceBeforeParensOptions:
|
SpaceBeforeRangeBasedForLoopColon: false
|
||||||
AfterControlStatements: true
|
|
||||||
AfterForeachMacros: true
|
|
||||||
AfterFunctionDeclarationName: false
|
|
||||||
AfterFunctionDefinitionName: false
|
|
||||||
AfterIfMacros: true
|
|
||||||
AfterOverloadedOperator: false
|
|
||||||
AfterRequiresInClause: false
|
|
||||||
AfterRequiresInExpression: false
|
|
||||||
BeforeNonEmptyParentheses: false
|
|
||||||
SpaceBeforeRangeBasedForLoopColon: true
|
|
||||||
SpaceBeforeSquareBrackets: false
|
|
||||||
SpaceInEmptyBlock: false
|
|
||||||
SpaceInEmptyParentheses: false
|
SpaceInEmptyParentheses: false
|
||||||
SpacesBeforeTrailingComments: 1
|
SpacesBeforeTrailingComments: 0
|
||||||
SpacesInAngles: Never
|
SpacesInAngles: false
|
||||||
SpacesInCStyleCastParentheses: false
|
SpacesInCStyleCastParentheses: false
|
||||||
SpacesInConditionalStatement: false
|
SpacesInContainerLiterals: false
|
||||||
SpacesInContainerLiterals: true
|
|
||||||
SpacesInLineCommentPrefix:
|
|
||||||
Minimum: 1
|
|
||||||
Maximum: -1
|
|
||||||
SpacesInParentheses: false
|
SpacesInParentheses: false
|
||||||
SpacesInSquareBrackets: false
|
SpacesInSquareBrackets: false
|
||||||
Standard: Latest
|
|
||||||
StatementAttributeLikeMacros:
|
|
||||||
- Q_EMIT
|
|
||||||
StatementMacros:
|
|
||||||
- Q_UNUSED
|
|
||||||
- QT_REQUIRE_VERSION
|
|
||||||
TabWidth: 2
|
TabWidth: 2
|
||||||
UseCRLF: false
|
UseTab: Never
|
||||||
UseTab: ForContinuationAndIndentation
|
|
||||||
WhitespaceSensitiveMacros:
|
|
||||||
- STRINGIZE
|
|
||||||
- PP_STRINGIZE
|
|
||||||
- BOOST_PP_STRINGIZE
|
|
||||||
- NS_SWIFT_NAME
|
|
||||||
- CF_SWIFT_NAME
|
|
||||||
|
|
|
||||||
148
.clang-tidy
148
.clang-tidy
|
|
@ -1,148 +0,0 @@
|
||||||
# Generated from CLion Inspection settings
|
|
||||||
---
|
|
||||||
Checks: '-*,
|
|
||||||
bugprone-argument-comment,
|
|
||||||
bugprone-assert-side-effect,
|
|
||||||
bugprone-bad-signal-to-kill-thread,
|
|
||||||
bugprone-branch-clone,
|
|
||||||
bugprone-copy-constructor-init,
|
|
||||||
bugprone-dangling-handle,
|
|
||||||
bugprone-dynamic-static-initializers,
|
|
||||||
bugprone-fold-init-type,
|
|
||||||
bugprone-forward-declaration-namespace,
|
|
||||||
bugprone-forwarding-reference-overload,
|
|
||||||
bugprone-inaccurate-erase,
|
|
||||||
bugprone-incorrect-roundings,
|
|
||||||
bugprone-integer-division,
|
|
||||||
bugprone-lambda-function-name,
|
|
||||||
bugprone-macro-parentheses,
|
|
||||||
bugprone-macro-repeated-side-effects,
|
|
||||||
bugprone-misplaced-operator-in-strlen-in-alloc,
|
|
||||||
bugprone-misplaced-pointer-arithmetic-in-alloc,
|
|
||||||
bugprone-misplaced-widening-cast,
|
|
||||||
bugprone-move-forwarding-reference,
|
|
||||||
bugprone-multiple-statement-macro,
|
|
||||||
bugprone-no-escape,
|
|
||||||
bugprone-not-null-terminated-result,
|
|
||||||
bugprone-parent-virtual-call,
|
|
||||||
bugprone-posix-return,
|
|
||||||
bugprone-reserved-identifier,
|
|
||||||
bugprone-sizeof-container,
|
|
||||||
bugprone-sizeof-expression,
|
|
||||||
bugprone-spuriously-wake-up-functions,
|
|
||||||
bugprone-string-constructor,
|
|
||||||
bugprone-string-integer-assignment,
|
|
||||||
bugprone-string-literal-with-embedded-nul,
|
|
||||||
bugprone-suspicious-enum-usage,
|
|
||||||
bugprone-suspicious-include,
|
|
||||||
bugprone-suspicious-memset-usage,
|
|
||||||
bugprone-suspicious-missing-comma,
|
|
||||||
bugprone-suspicious-semicolon,
|
|
||||||
bugprone-suspicious-string-compare,
|
|
||||||
bugprone-suspicious-memory-comparison,
|
|
||||||
bugprone-suspicious-realloc-usage,
|
|
||||||
bugprone-swapped-arguments,
|
|
||||||
bugprone-terminating-continue,
|
|
||||||
bugprone-throw-keyword-missing,
|
|
||||||
bugprone-too-small-loop-variable,
|
|
||||||
bugprone-undefined-memory-manipulation,
|
|
||||||
bugprone-undelegated-constructor,
|
|
||||||
bugprone-unhandled-self-assignment,
|
|
||||||
bugprone-unused-raii,
|
|
||||||
bugprone-unused-return-value,
|
|
||||||
bugprone-use-after-move,
|
|
||||||
bugprone-virtual-near-miss,
|
|
||||||
cert-dcl21-cpp,
|
|
||||||
cert-dcl58-cpp,
|
|
||||||
cert-err34-c,
|
|
||||||
cert-err52-cpp,
|
|
||||||
cert-err60-cpp,
|
|
||||||
cert-flp30-c,
|
|
||||||
cert-msc50-cpp,
|
|
||||||
cert-msc51-cpp,
|
|
||||||
cert-str34-c,
|
|
||||||
cppcoreguidelines-interfaces-global-init,
|
|
||||||
cppcoreguidelines-narrowing-conversions,
|
|
||||||
cppcoreguidelines-pro-type-member-init,
|
|
||||||
cppcoreguidelines-pro-type-static-cast-downcast,
|
|
||||||
cppcoreguidelines-slicing,
|
|
||||||
google-default-arguments,
|
|
||||||
google-explicit-constructor,
|
|
||||||
google-runtime-operator,
|
|
||||||
hicpp-exception-baseclass,
|
|
||||||
hicpp-multiway-paths-covered,
|
|
||||||
misc-misplaced-const,
|
|
||||||
misc-new-delete-overloads,
|
|
||||||
misc-no-recursion,
|
|
||||||
misc-non-copyable-objects,
|
|
||||||
misc-throw-by-value-catch-by-reference,
|
|
||||||
misc-unconventional-assign-operator,
|
|
||||||
misc-uniqueptr-reset-release,
|
|
||||||
modernize-avoid-bind,
|
|
||||||
modernize-concat-nested-namespaces,
|
|
||||||
modernize-deprecated-headers,
|
|
||||||
modernize-deprecated-ios-base-aliases,
|
|
||||||
modernize-loop-convert,
|
|
||||||
modernize-make-shared,
|
|
||||||
modernize-make-unique,
|
|
||||||
modernize-pass-by-value,
|
|
||||||
modernize-raw-string-literal,
|
|
||||||
modernize-redundant-void-arg,
|
|
||||||
modernize-replace-auto-ptr,
|
|
||||||
modernize-replace-disallow-copy-and-assign-macro,
|
|
||||||
modernize-replace-random-shuffle,
|
|
||||||
modernize-return-braced-init-list,
|
|
||||||
modernize-shrink-to-fit,
|
|
||||||
modernize-unary-static-assert,
|
|
||||||
modernize-use-auto,
|
|
||||||
modernize-use-bool-literals,
|
|
||||||
modernize-use-emplace,
|
|
||||||
modernize-use-equals-default,
|
|
||||||
modernize-use-equals-delete,
|
|
||||||
modernize-use-nodiscard,
|
|
||||||
modernize-use-noexcept,
|
|
||||||
modernize-use-nullptr,
|
|
||||||
modernize-use-override,
|
|
||||||
modernize-use-transparent-functors,
|
|
||||||
modernize-use-uncaught-exceptions,
|
|
||||||
mpi-buffer-deref,
|
|
||||||
mpi-type-mismatch,
|
|
||||||
openmp-use-default-none,
|
|
||||||
performance-faster-string-find,
|
|
||||||
performance-for-range-copy,
|
|
||||||
performance-implicit-conversion-in-loop,
|
|
||||||
performance-inefficient-algorithm,
|
|
||||||
performance-inefficient-string-concatenation,
|
|
||||||
performance-inefficient-vector-operation,
|
|
||||||
performance-move-const-arg,
|
|
||||||
performance-move-constructor-init,
|
|
||||||
performance-no-automatic-move,
|
|
||||||
performance-noexcept-move-constructor,
|
|
||||||
performance-trivially-destructible,
|
|
||||||
performance-type-promotion-in-math-fn,
|
|
||||||
performance-unnecessary-copy-initialization,
|
|
||||||
performance-unnecessary-value-param,
|
|
||||||
portability-simd-intrinsics,
|
|
||||||
readability-avoid-const-params-in-decls,
|
|
||||||
readability-const-return-type,
|
|
||||||
readability-container-size-empty,
|
|
||||||
readability-convert-member-functions-to-static,
|
|
||||||
readability-delete-null-pointer,
|
|
||||||
readability-deleted-default,
|
|
||||||
readability-inconsistent-declaration-parameter-name,
|
|
||||||
readability-make-member-function-const,
|
|
||||||
readability-misleading-indentation,
|
|
||||||
readability-misplaced-array-index,
|
|
||||||
readability-non-const-parameter,
|
|
||||||
readability-redundant-control-flow,
|
|
||||||
readability-redundant-declaration,
|
|
||||||
readability-redundant-function-ptr-dereference,
|
|
||||||
readability-redundant-smartptr-get,
|
|
||||||
readability-redundant-string-cstr,
|
|
||||||
readability-redundant-string-init,
|
|
||||||
readability-simplify-subscript-expr,
|
|
||||||
readability-static-accessed-through-instance,
|
|
||||||
readability-static-definition-in-anonymous-namespace,
|
|
||||||
readability-string-compare,
|
|
||||||
readability-uniqueptr-delete-release,
|
|
||||||
readability-use-anyofallof'
|
|
||||||
16
.cproject
16
.cproject
|
|
@ -1,16 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
|
||||||
<cconfiguration id="org.eclipse.cdt.core.default.config.612128043">
|
|
||||||
<storageModule buildSystemId="org.eclipse.cdt.core.defaultConfigDataProvider" id="org.eclipse.cdt.core.default.config.612128043" moduleId="org.eclipse.cdt.core.settings" name="Configuration">
|
|
||||||
<externalSettings/>
|
|
||||||
<extensions/>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
|
||||||
</cconfiguration>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.pathentry">
|
|
||||||
<pathentry excluding="**/CMakeFiles/**" kind="out" path="build"/>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
|
||||||
</cproject>
|
|
||||||
|
|
@ -1,428 +0,0 @@
|
||||||
<mxfile host="Electron" modified="2023-10-29T20:02:24.324Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.0.3 Chrome/114.0.5735.289 Electron/25.8.4 Safari/537.36" etag="26yH0Gc3erZ3uKcA6DFE" version="22.0.3" type="device">
|
|
||||||
<diagram name="Page-1" id="8edUMiMEU_fADqxzhr4b">
|
|
||||||
<mxGraphModel dx="1062" dy="-128" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="850" pageHeight="1100" background="none" math="0" shadow="0">
|
|
||||||
<root>
|
|
||||||
<mxCell id="0" />
|
|
||||||
<mxCell id="1" parent="0" />
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-158" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="1" source="Knp0EVw5rfMEdcPhjhnq-22" target="Knp0EVw5rfMEdcPhjhnq-141" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<UserObject label="User Regular Language Rulles" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-22">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
|
||||||
<mxGeometry x="380" y="1237" width="179" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-157" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="1" source="Knp0EVw5rfMEdcPhjhnq-53" target="Knp0EVw5rfMEdcPhjhnq-146" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<UserObject label="User Context Free Language Rulles" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-53">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
|
||||||
<mxGeometry x="482" y="1610" width="179" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-116" value="Compiler API Rulles To parse Regular grammar Rulles" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;startSize=23;" parent="1" vertex="1">
|
|
||||||
<mxGeometry x="175" y="1351" width="384" height="158" as="geometry">
|
|
||||||
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<UserObject label="RE Compiler API Rulles" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-124">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-116" vertex="1">
|
|
||||||
<mxGeometry x="24" y="37.5" width="332" height="46.5" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<UserObject label="CF Compiler API Rulles" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-125">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-116" vertex="1">
|
|
||||||
<mxGeometry x="24" y="98.5" width="336" height="46.5" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-126" value="CF Parser" style="swimlane;whiteSpace=wrap;html=1;startSize=23;" parent="1" vertex="1">
|
|
||||||
<mxGeometry x="2269" y="1405" width="999" height="823" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-13" value="Acceptor" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;" parent="Knp0EVw5rfMEdcPhjhnq-126" vertex="1">
|
|
||||||
<mxGeometry x="416" y="171" width="293" height="203" as="geometry">
|
|
||||||
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-34" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="Knp0EVw5rfMEdcPhjhnq-13" source="Knp0EVw5rfMEdcPhjhnq-14" target="Knp0EVw5rfMEdcPhjhnq-19" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-35" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="Knp0EVw5rfMEdcPhjhnq-13" source="Knp0EVw5rfMEdcPhjhnq-14" target="Knp0EVw5rfMEdcPhjhnq-18" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-36" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="Knp0EVw5rfMEdcPhjhnq-13" source="Knp0EVw5rfMEdcPhjhnq-14" target="Knp0EVw5rfMEdcPhjhnq-20" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<UserObject label="Automation" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-14">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-13" vertex="1">
|
|
||||||
<mxGeometry x="92" y="81.5" width="120" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-18" value="SymbolStream" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-13" vertex="1">
|
|
||||||
<mxGeometry x="103.5" y="42" width="97" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-19" value="AST" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-13" vertex="1">
|
|
||||||
<mxGeometry x="131.5" y="159" width="41" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-20" value="Tables" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-13" vertex="1">
|
|
||||||
<mxGeometry x="15" y="98.5" width="53" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-54" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;" parent="Knp0EVw5rfMEdcPhjhnq-126" source="Knp0EVw5rfMEdcPhjhnq-37" target="Knp0EVw5rfMEdcPhjhnq-13" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-55" value="Get Symbol" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="Knp0EVw5rfMEdcPhjhnq-54" vertex="1" connectable="0">
|
|
||||||
<mxGeometry x="-0.5956" y="-1" relative="1" as="geometry">
|
|
||||||
<mxPoint as="offset" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-137" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;" parent="Knp0EVw5rfMEdcPhjhnq-126" source="Knp0EVw5rfMEdcPhjhnq-37" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry">
|
|
||||||
<mxPoint x="953.4782608695655" y="398.6521739130435" as="targetPoint" />
|
|
||||||
<Array as="points">
|
|
||||||
<mxPoint x="563" y="733" />
|
|
||||||
<mxPoint x="919" y="733" />
|
|
||||||
<mxPoint x="919" y="399" />
|
|
||||||
</Array>
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-37" value="Acceptor" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;" parent="Knp0EVw5rfMEdcPhjhnq-126" vertex="1">
|
|
||||||
<mxGeometry x="416" y="490" width="293" height="203" as="geometry">
|
|
||||||
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-38" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="Knp0EVw5rfMEdcPhjhnq-37" source="Knp0EVw5rfMEdcPhjhnq-41" target="Knp0EVw5rfMEdcPhjhnq-43" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-39" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="Knp0EVw5rfMEdcPhjhnq-37" source="Knp0EVw5rfMEdcPhjhnq-41" target="Knp0EVw5rfMEdcPhjhnq-42" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-40" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="Knp0EVw5rfMEdcPhjhnq-37" source="Knp0EVw5rfMEdcPhjhnq-41" target="Knp0EVw5rfMEdcPhjhnq-44" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<UserObject label="Automation" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-41">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-37" vertex="1">
|
|
||||||
<mxGeometry x="92" y="81.5" width="120" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-42" value="SymbolStream" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-37" vertex="1">
|
|
||||||
<mxGeometry x="103.5" y="42" width="97" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-43" value="AST" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-37" vertex="1">
|
|
||||||
<mxGeometry x="131.5" y="159" width="41" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-44" value="Tables" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-37" vertex="1">
|
|
||||||
<mxGeometry x="15" y="98.5" width="53" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-59" value="Finate State Automation" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="Knp0EVw5rfMEdcPhjhnq-126" vertex="1">
|
|
||||||
<mxGeometry x="721" y="175.5" width="146" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-60" value="Push Down Automation" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="Knp0EVw5rfMEdcPhjhnq-126" vertex="1">
|
|
||||||
<mxGeometry x="726" y="490" width="143" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-131" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;" parent="Knp0EVw5rfMEdcPhjhnq-126" source="Knp0EVw5rfMEdcPhjhnq-82" target="Knp0EVw5rfMEdcPhjhnq-37" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-134" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;" parent="Knp0EVw5rfMEdcPhjhnq-126" source="Knp0EVw5rfMEdcPhjhnq-82" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry">
|
|
||||||
<mxPoint x="24.947368421052943" y="591.5" as="targetPoint" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-82" value="CFG Compiler" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;" parent="Knp0EVw5rfMEdcPhjhnq-126" vertex="1">
|
|
||||||
<mxGeometry x="93" y="448.5" width="281" height="286" as="geometry">
|
|
||||||
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-88" value="CF Comp Rules" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-82" vertex="1">
|
|
||||||
<mxGeometry x="7" y="130" width="103" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-90" value="Tables" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-82" vertex="1">
|
|
||||||
<mxGeometry x="210" y="132.5" width="53" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<UserObject label="LL" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-91">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-82" vertex="1">
|
|
||||||
<mxGeometry x="116" y="51.75" width="83" height="46.5" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<UserObject label="Canonical" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-92">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-82" vertex="1">
|
|
||||||
<mxGeometry x="116" y="119.75" width="83" height="46.5" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<UserObject label="LALR" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-93">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-82" vertex="1">
|
|
||||||
<mxGeometry x="116" y="187.75" width="83" height="46.5" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-132" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;" parent="Knp0EVw5rfMEdcPhjhnq-126" source="Knp0EVw5rfMEdcPhjhnq-94" target="Knp0EVw5rfMEdcPhjhnq-13" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-133" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;" parent="Knp0EVw5rfMEdcPhjhnq-126" source="Knp0EVw5rfMEdcPhjhnq-94" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry">
|
|
||||||
<mxPoint x="24.947368421052943" y="272.5" as="targetPoint" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-94" value="RE Compiler" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;startSize=23;" parent="Knp0EVw5rfMEdcPhjhnq-126" vertex="1">
|
|
||||||
<mxGeometry x="122" y="228.25" width="260" height="88.5" as="geometry">
|
|
||||||
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-95" value="RE Compiler Rulles" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-94" vertex="1">
|
|
||||||
<mxGeometry x="13" y="33.75" width="123" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-96" value="Tables" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-94" vertex="1">
|
|
||||||
<mxGeometry x="187" y="39.5" width="53" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-154" value="Sentence" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="Knp0EVw5rfMEdcPhjhnq-126" vertex="1">
|
|
||||||
<mxGeometry x="21" y="149.5" width="69" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-56" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;" parent="Knp0EVw5rfMEdcPhjhnq-126" source="Knp0EVw5rfMEdcPhjhnq-13" target="Knp0EVw5rfMEdcPhjhnq-154" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry">
|
|
||||||
<mxPoint x="94" y="166" as="targetPoint" />
|
|
||||||
<Array as="points">
|
|
||||||
<mxPoint x="626" y="104" />
|
|
||||||
<mxPoint x="281" y="104" />
|
|
||||||
<mxPoint x="281" y="166" />
|
|
||||||
</Array>
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-57" value="Get Symbol" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="Knp0EVw5rfMEdcPhjhnq-56" vertex="1" connectable="0">
|
|
||||||
<mxGeometry x="-0.0483" relative="1" as="geometry">
|
|
||||||
<mxPoint as="offset" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-127" value="Compiler API Rulles To parse Regular grammar Rulles" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;startSize=23;" parent="1" vertex="1">
|
|
||||||
<mxGeometry x="285" y="1720" width="385" height="158" as="geometry">
|
|
||||||
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<UserObject label="RE Compiler API Rulles" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-128">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-127" vertex="1">
|
|
||||||
<mxGeometry x="24" y="37.5" width="340" height="46.5" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<UserObject label="CF Compiler API Rulles" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-129">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-127" vertex="1">
|
|
||||||
<mxGeometry x="24" y="98.5" width="340" height="46.5" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-162" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="1" source="Knp0EVw5rfMEdcPhjhnq-130" target="Knp0EVw5rfMEdcPhjhnq-151" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<UserObject label="User Sentence" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-130">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
|
||||||
<mxGeometry x="1063" y="1056" width="120" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-138" value="CF Parser" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;" parent="1" vertex="1">
|
|
||||||
<mxGeometry x="622" y="1273" width="337" height="173" as="geometry">
|
|
||||||
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-139" value="CF AST Rulles for Tokenizer" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-138" vertex="1">
|
|
||||||
<mxGeometry x="19" y="80" width="168" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-140" value="CF AST Rulles for an acceptor" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-138" vertex="1">
|
|
||||||
<mxGeometry x="19" y="125" width="180" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-141" value="CF Sentence" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-138" vertex="1">
|
|
||||||
<mxGeometry x="19" y="37" width="88" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-142" value="AST" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-138" vertex="1">
|
|
||||||
<mxGeometry x="265" y="73.5" width="41" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-143" value="CF Parser" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;" parent="1" vertex="1">
|
|
||||||
<mxGeometry x="714" y="1645" width="337" height="173" as="geometry">
|
|
||||||
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-144" value="CF AST Rulles for Tokenizer" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-143" vertex="1">
|
|
||||||
<mxGeometry x="19" y="80" width="168" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-145" value="CF AST Rulles for an acceptor" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-143" vertex="1">
|
|
||||||
<mxGeometry x="19" y="125" width="180" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-146" value="CF Sentence" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-143" vertex="1">
|
|
||||||
<mxGeometry x="19" y="37" width="88" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-147" value="AST" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-143" vertex="1">
|
|
||||||
<mxGeometry x="265" y="73.5" width="41" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-148" value="CF Parser" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;" parent="1" vertex="1">
|
|
||||||
<mxGeometry x="1391" y="1401" width="337" height="173" as="geometry">
|
|
||||||
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-149" value="RE Compiler API Rulles for FSA" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-148" vertex="1">
|
|
||||||
<mxGeometry x="36" y="79.75" width="189" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-150" value="CF Compiler API Rulles for an PDA acceptor" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-148" vertex="1">
|
|
||||||
<mxGeometry x="36" y="124" width="255" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-151" value="CF Sentence" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-148" vertex="1">
|
|
||||||
<mxGeometry x="19" y="37" width="88" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-152" value="Sentence AST" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-148" vertex="1">
|
|
||||||
<mxGeometry x="229" y="35" width="95" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-155" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="1" source="Knp0EVw5rfMEdcPhjhnq-129" target="Knp0EVw5rfMEdcPhjhnq-145" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-156" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="1" source="Knp0EVw5rfMEdcPhjhnq-128" target="Knp0EVw5rfMEdcPhjhnq-144" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-159" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="1" source="Knp0EVw5rfMEdcPhjhnq-124" target="Knp0EVw5rfMEdcPhjhnq-139" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-160" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="1" source="Knp0EVw5rfMEdcPhjhnq-125" target="Knp0EVw5rfMEdcPhjhnq-140" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-165" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" parent="1" source="B2JnEC1cqt8830IlIT0b-3" target="Knp0EVw5rfMEdcPhjhnq-149" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-166" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" parent="1" source="B2JnEC1cqt8830IlIT0b-1" target="Knp0EVw5rfMEdcPhjhnq-150" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Knp0EVw5rfMEdcPhjhnq-167" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" parent="1" source="Knp0EVw5rfMEdcPhjhnq-152" target="Knp0EVw5rfMEdcPhjhnq-168" edge="1">
|
|
||||||
<mxGeometry relative="1" as="geometry">
|
|
||||||
<mxPoint x="1909.9999999999995" y="1483" as="targetPoint" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<UserObject label="User AST" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-168">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
|
||||||
<mxGeometry x="1977" y="1190" width="120" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-2" value="" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" edge="1" parent="1" source="Knp0EVw5rfMEdcPhjhnq-147" target="B2JnEC1cqt8830IlIT0b-1">
|
|
||||||
<mxGeometry relative="1" as="geometry">
|
|
||||||
<mxPoint x="1020" y="1732" as="sourcePoint" />
|
|
||||||
<mxPoint x="1408" y="1535" as="targetPoint" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<UserObject label="AST to CF Compiler API" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-1">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="1117" y="1613" width="197" height="46.5" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-4" value="" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" edge="1" parent="1" source="Knp0EVw5rfMEdcPhjhnq-142" target="B2JnEC1cqt8830IlIT0b-3">
|
|
||||||
<mxGeometry relative="1" as="geometry">
|
|
||||||
<mxPoint x="1032" y="1311" as="sourcePoint" />
|
|
||||||
<mxPoint x="1408" y="1490" as="targetPoint" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<UserObject label="AST to RE Compiler API" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-3">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="1107" y="1470.5" width="197" height="46.5" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-41" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-42" target="B2JnEC1cqt8830IlIT0b-56">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<UserObject label="Language Grammar <br>(CF RE United Format)" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-42">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="422" y="2209" width="179" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-45" value="Grammar For CF RE United Grammar Format" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;startSize=23;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="253" y="2439" width="384" height="158" as="geometry">
|
|
||||||
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<UserObject label="RE Compiler API Rulles" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-46">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-45">
|
|
||||||
<mxGeometry x="24" y="37.5" width="332" height="46.5" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<UserObject label="CF Compiler API Rulles" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-47">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-45">
|
|
||||||
<mxGeometry x="24" y="98.5" width="336" height="46.5" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-51" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-52" target="B2JnEC1cqt8830IlIT0b-66">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<UserObject label="User Sentence" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-52">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="422" y="2132" width="180" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-53" value="CF Parser" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="700" y="2361" width="337" height="173" as="geometry">
|
|
||||||
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-54" value="CF AST Rulles for Tokenizer" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-53">
|
|
||||||
<mxGeometry x="19" y="80" width="168" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-55" value="CF AST Rulles for an acceptor" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-53">
|
|
||||||
<mxGeometry x="19" y="125" width="180" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-56" value="CF Sentence" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-53">
|
|
||||||
<mxGeometry x="19" y="37" width="88" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-57" value="AST" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-53">
|
|
||||||
<mxGeometry x="265" y="73.5" width="41" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-63" value="CF Parser" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="1415" y="2271" width="337" height="173" as="geometry">
|
|
||||||
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-64" value="RE Compiler API Rulles for FSA" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-63">
|
|
||||||
<mxGeometry x="36" y="79.75" width="189" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-65" value="CF Compiler API Rulles for an PDA acceptor" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-63">
|
|
||||||
<mxGeometry x="36" y="124" width="255" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-66" value="CF Sentence" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-63">
|
|
||||||
<mxGeometry x="19" y="37" width="88" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-67" value="Sentence AST" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-63">
|
|
||||||
<mxGeometry x="229" y="35" width="95" height="26" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-70" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-46" target="B2JnEC1cqt8830IlIT0b-54">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-71" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-47" target="B2JnEC1cqt8830IlIT0b-55">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-72" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-79" target="B2JnEC1cqt8830IlIT0b-64">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-73" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-77" target="B2JnEC1cqt8830IlIT0b-65">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-74" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-67" target="B2JnEC1cqt8830IlIT0b-75">
|
|
||||||
<mxGeometry relative="1" as="geometry">
|
|
||||||
<mxPoint x="1933.9999999999995" y="2353" as="targetPoint" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<UserObject label="User AST" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-75">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="2001" y="2060" width="120" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-76" value="" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-57" target="B2JnEC1cqt8830IlIT0b-77">
|
|
||||||
<mxGeometry relative="1" as="geometry">
|
|
||||||
<mxPoint x="1044" y="2601.5" as="sourcePoint" />
|
|
||||||
<mxPoint x="1432" y="2405" as="targetPoint" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<UserObject label="AST to CF Compiler API" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-77">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="1141" y="2483" width="197" height="46.5" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
<mxCell id="B2JnEC1cqt8830IlIT0b-78" value="" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-57" target="B2JnEC1cqt8830IlIT0b-79">
|
|
||||||
<mxGeometry relative="1" as="geometry">
|
|
||||||
<mxPoint x="1056" y="2181" as="sourcePoint" />
|
|
||||||
<mxPoint x="1432" y="2360" as="targetPoint" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<UserObject label="AST to RE Compiler API" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-79">
|
|
||||||
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};labelBackgroundColor=none;rounded=0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="1151" y="2371" width="197" height="46.5" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</UserObject>
|
|
||||||
</root>
|
|
||||||
</mxGraphModel>
|
|
||||||
</diagram>
|
|
||||||
</mxfile>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.2 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 416 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 MiB |
|
|
@ -1,16 +0,0 @@
|
||||||
method myLogFunction(value) {
|
|
||||||
print value;
|
|
||||||
}
|
|
||||||
|
|
||||||
myLogFunction("hello");
|
|
||||||
|
|
||||||
var i = 10;
|
|
||||||
|
|
||||||
if (i == 10) {
|
|
||||||
while (i > 0) {
|
|
||||||
print i;
|
|
||||||
i = i - 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
print "still doin' heavy calculations...";
|
|
||||||
}
|
|
||||||
17
.github/workflows/WindowsPlatform.yml
vendored
17
.github/workflows/WindowsPlatform.yml
vendored
|
|
@ -1,17 +0,0 @@
|
||||||
name: Windows
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "master" ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ "master" ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: self-hosted
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
#- name: Build
|
|
||||||
#run: echo hello
|
|
||||||
62
.github/workflows/cmake-single-platform.yml
vendored
62
.github/workflows/cmake-single-platform.yml
vendored
|
|
@ -1,62 +0,0 @@
|
||||||
# This starter workflow is for a CMake project running on a single platform. There is a different starter workflow if you need cross-platform coverage.
|
|
||||||
# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-multi-platform.yml
|
|
||||||
name: CMake on a single platform
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "master" ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ "master" ]
|
|
||||||
|
|
||||||
env:
|
|
||||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
|
||||||
BUILD_TYPE: Release
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
|
|
||||||
# You can convert this to a matrix build if you need cross-platform coverage.
|
|
||||||
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Sutup Dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install python3 python-is-python3
|
|
||||||
sudo apt-get install -y libx11-dev libgl1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev
|
|
||||||
sudo apt-get install -y clang-15
|
|
||||||
sudo apt-get install -y libasound2-dev libglew-dev
|
|
||||||
sudo apt-get install -y portaudio19-dev
|
|
||||||
sudo apt-get install -y libwayland-dev libxkbcommon-dev
|
|
||||||
|
|
||||||
- name: install OpenImageDenoise
|
|
||||||
run: |
|
|
||||||
sudo snap install ispc
|
|
||||||
sudo apt-get install -y libtbb-dev
|
|
||||||
git clone --recursive https://github.com/RenderKit/oidn.git
|
|
||||||
cd oidn
|
|
||||||
mkdir build; cd build; cmake ..; make -j;
|
|
||||||
sudo make install
|
|
||||||
|
|
||||||
- name: Update repository
|
|
||||||
run: |
|
|
||||||
git submodule update --init --recursive
|
|
||||||
|
|
||||||
- name: Configure CMake
|
|
||||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
|
||||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
|
||||||
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
# Build your program with the given configuration
|
|
||||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -- -j$(nproc)
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
working-directory: ${{github.workspace}}/build
|
|
||||||
# Execute tests defined by the CMake configuration.
|
|
||||||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
|
||||||
run: ctest -C ${{env.BUILD_TYPE}}
|
|
||||||
|
|
||||||
56
.github/workflows/cmake.yml
vendored
56
.github/workflows/cmake.yml
vendored
|
|
@ -18,47 +18,25 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Setup
|
- name: Install LLVM
|
||||||
shell: bash
|
run: sudo apt-get install -y llvm
|
||||||
run: |
|
|
||||||
# If your submodules are configured to use SSH instead of HTTPS please uncomment the following line
|
- name: Set LLVM Toolchain
|
||||||
# git config --global url."https://github.com/".insteadOf "git@github.com:"
|
run: |
|
||||||
auth_header="$(git config --local --get http.https://github.com/.extraheader)"
|
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++ 10
|
||||||
|
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 20
|
||||||
|
|
||||||
git submodule sync --recursive
|
- name: Configure CMake
|
||||||
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
|
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||||
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install python3 python-is-python3
|
|
||||||
sudo apt-get install -y libx11-dev libgl1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev
|
|
||||||
sudo apt-get install -y clang-15
|
|
||||||
sudo apt-get install -y libasound2-dev libglew-dev
|
|
||||||
sudo apt-get install -y portaudio19-dev
|
|
||||||
#cd Externals/glew/
|
|
||||||
#make extensions
|
|
||||||
sudo apt update
|
|
||||||
|
|
||||||
#- name: Set LLVM Toolchain
|
|
||||||
#run: |
|
|
||||||
# sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++ 10
|
|
||||||
# sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 20
|
|
||||||
|
|
||||||
- name: Configure CMake
|
|
||||||
run: |
|
|
||||||
gcc -v
|
|
||||||
clang++-15 -v
|
|
||||||
CC=clang-15 CXX=clang++-15 cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: CC=clang CXX=clang++ cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -v -j
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
working-directory: ${{github.workspace}}/build
|
|
||||||
# Execute tests defined by the CMake configuration.
|
|
||||||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
|
||||||
run: ctest -j -C ${{env.BUILD_TYPE}}
|
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
working-directory: ${{github.workspace}}/build
|
||||||
|
# Execute tests defined by the CMake configuration.
|
||||||
|
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
||||||
|
run: ctest -C ${{env.BUILD_TYPE}}
|
||||||
|
|
||||||
|
|
|
||||||
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -2,11 +2,6 @@
|
||||||
*tmp*
|
*tmp*
|
||||||
bin
|
bin
|
||||||
build*
|
build*
|
||||||
*build*
|
|
||||||
lib
|
lib
|
||||||
install
|
install
|
||||||
.vscode
|
.vscode
|
||||||
out
|
|
||||||
.vs
|
|
||||||
*.bkp
|
|
||||||
*.$*
|
|
||||||
|
|
|
||||||
30
.gitmodules
vendored
30
.gitmodules
vendored
|
|
@ -1,30 +0,0 @@
|
||||||
[submodule "Externals/imgui"]
|
|
||||||
path = Externals/imgui
|
|
||||||
url = https://github.com/elushaX/imgui.git
|
|
||||||
[submodule "Externals/lua"]
|
|
||||||
path = Externals/lua
|
|
||||||
url = https://github.com/elushaX/lua.git
|
|
||||||
[submodule "Externals/unittest-cpp"]
|
|
||||||
path = Externals/unittest-cpp
|
|
||||||
url = https://github.com/elushaX/unittest-cpp.git
|
|
||||||
[submodule "Externals/glfw"]
|
|
||||||
path = Externals/glfw
|
|
||||||
url = https://github.com/elushaX/glfw.git
|
|
||||||
[submodule "Externals/nanovg"]
|
|
||||||
path = Externals/nanovg
|
|
||||||
url = https://github.com/elushaX/nanovg.git
|
|
||||||
[submodule "Externals/lalr"]
|
|
||||||
path = Externals/lalr
|
|
||||||
url = https://github.com/elushaX/lalr.git
|
|
||||||
[submodule "Externals/asio"]
|
|
||||||
path = Externals/asio
|
|
||||||
url = https://github.com/elushaX/asio.git
|
|
||||||
[submodule "Externals/implot"]
|
|
||||||
path = Externals/implot
|
|
||||||
url = https://github.com/epezent/implot.git
|
|
||||||
[submodule "Externals/googletest"]
|
|
||||||
path = Externals/googletest
|
|
||||||
url = https://github.com/google/googletest.git
|
|
||||||
[submodule "Externals/benchmark"]
|
|
||||||
path = Externals/benchmark
|
|
||||||
url = https://github.com/google/benchmark.git
|
|
||||||
20
.project
20
.project
|
|
@ -1,20 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<projectDescription>
|
|
||||||
<name>Modules</name>
|
|
||||||
<comment></comment>
|
|
||||||
<projects>
|
|
||||||
</projects>
|
|
||||||
<buildSpec>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.cdt.core.cBuilder</name>
|
|
||||||
<triggers>clean,full,incremental,</triggers>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
</buildSpec>
|
|
||||||
<natures>
|
|
||||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
|
||||||
<nature>org.eclipse.cdt.core.ccnature</nature>
|
|
||||||
<nature>org.eclipse.cdt.cmake.core.cmakeNature</nature>
|
|
||||||
</natures>
|
|
||||||
</projectDescription>
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.2)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
|
||||||
|
|
||||||
project(Language)
|
|
||||||
|
|
||||||
### ---------------------- Static Library --------------------- ###
|
|
||||||
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
|
|
||||||
file(GLOB HEADERS "./public/*.hpp" "./public/*/*.hpp")
|
|
||||||
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC public/)
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Strings)
|
|
||||||
|
|
||||||
### -------------------------- Tests -------------------------- ###
|
|
||||||
enable_testing()
|
|
||||||
file(GLOB TEST_SOURCES "./tests/*.cpp")
|
|
||||||
add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES})
|
|
||||||
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} UnitTest++)
|
|
||||||
add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests)
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
|
|
||||||
#include "Grammar.hpp"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
ContextFreeGrammar::Arg::Arg(const String& id, bool terminal, bool epsilon) {
|
|
||||||
mId = id;
|
|
||||||
mIsTerminal = terminal;
|
|
||||||
mIsEpsilon = epsilon;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String& ContextFreeGrammar::Arg::getId() const { return mId; }
|
|
||||||
|
|
||||||
bool ContextFreeGrammar::Arg::operator==(const Arg& in) const {
|
|
||||||
return (mId == in.mId) && (mIsEpsilon == in.mIsEpsilon) && (mIsTerminal == in.mIsTerminal);
|
|
||||||
}
|
|
||||||
|
|
||||||
ContextFreeGrammar::Rule::Rule(const String& id, const InitialierList<Arg>& args) {
|
|
||||||
mId = id;
|
|
||||||
mArgs = args;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ContextFreeGrammar::Rule::operator==(const Rule& in) const { return (mId == in.mId) && (mArgs == in.mArgs); }
|
|
||||||
|
|
||||||
bool ContextFreeGrammar::Rule::isProductive() const {
|
|
||||||
for (auto arg : mArgs) {
|
|
||||||
if (arg->getId() == mId) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ContextFreeGrammar::addRule(const Rule& rule) { mRules.append(rule); }
|
|
||||||
|
|
||||||
void ContextFreeGrammar::addRule(const String& id, const InitialierList<Arg>& args) { addRule(Rule(id, args)); }
|
|
||||||
|
|
||||||
void ContextFreeGrammar::setStart(const String& startRule) { mStartTerminal = startRule; }
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
|
|
||||||
#include "LanguageCommon.hpp"
|
|
||||||
#include "Strings.hpp"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
static ModuleManifest* sModuleDependencies[] = { &gModuleStrings, nullptr };
|
|
||||||
ModuleManifest tp::gModuleLanguage = ModuleManifest("Language", nullptr, nullptr, sModuleDependencies);
|
|
||||||
|
|
@ -1,249 +0,0 @@
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Utils.hpp"
|
|
||||||
#include "List.hpp"
|
|
||||||
#include "Map.hpp"
|
|
||||||
#include "Tree.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
// Non-Deterministic Finite-State Automata
|
|
||||||
template <typename tAlphabetType, typename tStateType>
|
|
||||||
class FiniteStateAutomation {
|
|
||||||
public:
|
|
||||||
struct State;
|
|
||||||
|
|
||||||
public:
|
|
||||||
class Transition {
|
|
||||||
friend FiniteStateAutomation;
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum Type { ANY, EPSILON, SYMBOL };
|
|
||||||
|
|
||||||
public:
|
|
||||||
Transition(Type type, State* state, tAlphabetType symbol = tAlphabetType()) {
|
|
||||||
mState = state;
|
|
||||||
mType = type;
|
|
||||||
mSymbol = symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool isTransition(const tAlphabetType& symbol) const {
|
|
||||||
return (mType == ANY || mType == EPSILON) || (mSymbol == symbol);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool doesConsumes(const tAlphabetType& symbol) const {
|
|
||||||
return (mType == ANY || (mType == SYMBOL && mSymbol == symbol));
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool isEpsilon() const { return mType == EPSILON; }
|
|
||||||
|
|
||||||
const State* getState() const { return mState; }
|
|
||||||
const tAlphabetType& getSymbol() const { return mSymbol; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
State* mState = nullptr;
|
|
||||||
Type mType;
|
|
||||||
tAlphabetType mSymbol;
|
|
||||||
};
|
|
||||||
|
|
||||||
class State {
|
|
||||||
friend FiniteStateAutomation;
|
|
||||||
|
|
||||||
public:
|
|
||||||
State() = default;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void setValue(const tStateType& stateValue) { mStateVal = stateValue; }
|
|
||||||
void setAcceptance(bool isAccepting) { mIsAccepting = isAccepting; }
|
|
||||||
[[nodiscard]] bool isAccepting() const { return mIsAccepting; }
|
|
||||||
const tStateType& getStateVal() const { return mStateVal; }
|
|
||||||
[[nodiscard]] const Buffer<Transition>* getTransitions() const { return &mTransitions; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Buffer<Transition> mTransitions{};
|
|
||||||
tStateType mStateVal = tStateType();
|
|
||||||
bool mIsAccepting = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
List<State> mStates;
|
|
||||||
State* mStartState = nullptr;
|
|
||||||
Range<ualni> mAlphabetRange = { ENV_UALNI_MAX, ENV_UALNI_MIN };
|
|
||||||
|
|
||||||
public:
|
|
||||||
FiniteStateAutomation() = default;
|
|
||||||
|
|
||||||
State* addState(const tStateType& state, bool accepting) {
|
|
||||||
auto node = mStates.newNode();
|
|
||||||
node->data.mIsAccepting = accepting;
|
|
||||||
node->data.mStateVal = state;
|
|
||||||
mStates.pushBack(node);
|
|
||||||
return &node->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addTransition(State* from, State* to, const tAlphabetType& symbol) {
|
|
||||||
from->mTransitions.append(Transition(Transition::SYMBOL, to, symbol));
|
|
||||||
if (mAlphabetRange.mBegin < ualni(symbol)) mAlphabetRange.mBegin = ualni(symbol);
|
|
||||||
if (mAlphabetRange.mEnd > ualni(symbol)) mAlphabetRange.mEnd = ualni(symbol);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addEpsilonTransition(State* from, State* to) { from->mTransitions.append(Transition(Transition::SYMBOL, to)); }
|
|
||||||
|
|
||||||
void addAnyTransition(State* from, State* to) { from->mTransitions.append(Transition(Transition::ANY, to)); }
|
|
||||||
|
|
||||||
void setStartState(State* start) { mStartState = start; }
|
|
||||||
|
|
||||||
[[nodiscard]] State* getStartState() const { return mStartState; }
|
|
||||||
|
|
||||||
[[nodiscard]] bool isValid() const {
|
|
||||||
if (!mStartState) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] ualni numStates() const { return mStates.length(); }
|
|
||||||
|
|
||||||
[[nodiscard]] const List<State>* getStates() const { return &mStates; }
|
|
||||||
|
|
||||||
[[nodiscard]] Range<ualni> getAlphabetRange() const { return mAlphabetRange; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef AvlTree<AvlNumericKey<State*>, bool> StatesSet;
|
|
||||||
|
|
||||||
// Expands initial set with states that are reachable from initial set with no input consumption (E-transitions)
|
|
||||||
static void expandSet(StatesSet& set) {
|
|
||||||
List<State*> workingSet;
|
|
||||||
|
|
||||||
set.forEach([&](AvlNumericKey<State*>& key, bool) { workingSet.pushBack(key.val); });
|
|
||||||
|
|
||||||
while (workingSet.length()) {
|
|
||||||
auto first = workingSet.first()->data;
|
|
||||||
set.insert(first, {});
|
|
||||||
|
|
||||||
for (auto transition : first->mTransitions) {
|
|
||||||
if (!transition->isEpsilon()) continue;
|
|
||||||
if (set.find(transition->mState)) continue;
|
|
||||||
workingSet.pushBack(transition->mState);
|
|
||||||
}
|
|
||||||
|
|
||||||
workingSet.popFront();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// States that are reachable from initial set with symbol transition
|
|
||||||
static void findMoveSet(StatesSet& from, StatesSet& moveSet, tAlphabetType symbol) {
|
|
||||||
from.forEach([&](AvlNumericKey<State*>& key, bool) {
|
|
||||||
for (auto transition : key.val->mTransitions) {
|
|
||||||
if (transition->isEpsilon()) continue;
|
|
||||||
if (!transition->isTransition(symbol)) continue;
|
|
||||||
if (moveSet.find(transition->mState)) continue;
|
|
||||||
moveSet.insert(transition->mState, {});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool makeDeterministic() {
|
|
||||||
if (!isValid()) return false;
|
|
||||||
|
|
||||||
struct GroupKey {
|
|
||||||
const StatesSet* group;
|
|
||||||
static ualni hash(GroupKey key) { return 0; }
|
|
||||||
bool operator==(const GroupKey& key) const { return false; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GroupInfo {
|
|
||||||
StatesSet* group = nullptr;
|
|
||||||
AvlTree<AvlNumericKey<StatesSet*>, tAlphabetType> transitions;
|
|
||||||
State* newState = nullptr;
|
|
||||||
bool accepting = false;
|
|
||||||
tStateType stateVal = tStateType();
|
|
||||||
};
|
|
||||||
|
|
||||||
Buffer<StatesSet> groups = { {} };
|
|
||||||
Map<GroupKey, GroupInfo, DefaultAllocator, GroupKey::hash> groupInfos;
|
|
||||||
|
|
||||||
groups.first().insert(getStartState(), false);
|
|
||||||
|
|
||||||
expandSet(groups.first());
|
|
||||||
|
|
||||||
groupInfos.put({ &groups.first() }, { &groups.first() });
|
|
||||||
|
|
||||||
// 1) find new states
|
|
||||||
List<StatesSet*> workingSet;
|
|
||||||
workingSet.pushBack(&groups.first());
|
|
||||||
|
|
||||||
while (workingSet.length()) {
|
|
||||||
StatesSet* group = workingSet.first()->data;
|
|
||||||
GroupInfo* info = &groupInfos.get({ group });
|
|
||||||
|
|
||||||
for (auto symbol : getAlphabetRange()) {
|
|
||||||
|
|
||||||
// calculate new possible state
|
|
||||||
StatesSet potentialGroup;
|
|
||||||
|
|
||||||
findMoveSet(*group, potentialGroup, tAlphabetType(symbol));
|
|
||||||
expandSet(potentialGroup);
|
|
||||||
|
|
||||||
if (!potentialGroup.size()) continue;
|
|
||||||
|
|
||||||
// find existing or create group
|
|
||||||
StatesSet* targetGroup = nullptr;
|
|
||||||
auto iter = groupInfos.presents({ &potentialGroup });
|
|
||||||
if (iter) {
|
|
||||||
targetGroup = groupInfos.getSlotVal(iter).group;
|
|
||||||
} else {
|
|
||||||
targetGroup = &groups.append(potentialGroup);
|
|
||||||
groupInfos.put({ targetGroup }, { targetGroup });
|
|
||||||
workingSet.pushBack(targetGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
// assert transition is added
|
|
||||||
info->transitions.insert(targetGroup, tAlphabetType(symbol));
|
|
||||||
}
|
|
||||||
|
|
||||||
workingSet.popFront();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2) find new states termination values
|
|
||||||
for (auto group : groupInfos) {
|
|
||||||
GroupInfo* info = &group->val;
|
|
||||||
ualni accepting = 0;
|
|
||||||
|
|
||||||
info->group->forEach([&](AvlNumericKey<State*>& key, bool) {
|
|
||||||
if (key.val->mIsAccepting) {
|
|
||||||
accepting++;
|
|
||||||
info->accepting = true;
|
|
||||||
info->stateVal = key.val->mStateVal;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!accepting) {
|
|
||||||
info->accepting = false;
|
|
||||||
info->stateVal = info->group->head()->key.val->mStateVal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3) transfer
|
|
||||||
mStates.removeAll();
|
|
||||||
|
|
||||||
// create states
|
|
||||||
for (auto group : groupInfos) {
|
|
||||||
group->val.newState = addState(group->val.stateVal, group->val.accepting);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create transitions
|
|
||||||
for (auto group : groupInfos) {
|
|
||||||
auto functor = [&](AvlNumericKey<StatesSet*> targetGroupKey, tAlphabetType symbol) {
|
|
||||||
GroupInfo* targetGroup = &groupInfos.get({ (StatesSet*) targetGroupKey.val });
|
|
||||||
addTransition(group->val.newState, targetGroup->newState, symbol);
|
|
||||||
};
|
|
||||||
group->val.transitions.forEach(functor);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Strings.hpp"
|
|
||||||
#include "Automata.hpp"
|
|
||||||
#include "Buffer2D.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
template <typename tAlphabetType, typename tStateType>
|
|
||||||
class ContextFreeAutomata {
|
|
||||||
|
|
||||||
struct Action {
|
|
||||||
enum Type { SHIFT, REDUCE, TRAP } type = TRAP;
|
|
||||||
ualni num = 0; // state to shift (shift action) or pop count (reduce action)
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
struct StackItem {
|
|
||||||
ualni state = 0;
|
|
||||||
tAlphabetType symbol;
|
|
||||||
Buffer<StackItem*> leafs;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AcceptResult {
|
|
||||||
bool accepted = false;
|
|
||||||
ualni advancedIdx = 0;
|
|
||||||
const StackItem* ast = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
ContextFreeAutomata() = default;
|
|
||||||
|
|
||||||
AcceptResult accept(const tAlphabetType* stream, ualni size) {
|
|
||||||
mCurrentState = mStartState;
|
|
||||||
mStack.append(&mItems.append({ mCurrentState, {}, {} }));
|
|
||||||
|
|
||||||
ualni advancedIdx = 0;
|
|
||||||
while (advancedIdx < size) {
|
|
||||||
const tAlphabetType& symbol = *(stream + advancedIdx);
|
|
||||||
|
|
||||||
if (!(symbol >= mRange.mBegin && symbol < mRange.mEnd)) {
|
|
||||||
return { false, advancedIdx, nullptr };
|
|
||||||
}
|
|
||||||
|
|
||||||
const Action& action = mTable.get({ ualni(symbol - mRange.mBegin), mCurrentState });
|
|
||||||
|
|
||||||
if (action.type == Action::TRAP) {
|
|
||||||
return { false, advancedIdx, nullptr };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (action.type == Action::SHIFT) {
|
|
||||||
mStack.last()->symbol = symbol;
|
|
||||||
mStack.append(&mItems.append({ mCurrentState, {}, {} }));
|
|
||||||
mCurrentState = action.num;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mTable.get({ 0, mCurrentState }).type == Action::REDUCE) {
|
|
||||||
StackItem* newItem = &mItems.append(StackItem{});
|
|
||||||
for (auto iter : Range<ualni>(action.num)) {
|
|
||||||
newItem->leafs.append(mStack.last());
|
|
||||||
mCurrentState = mStack.last()->state;
|
|
||||||
mStack.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mStack.size()) {
|
|
||||||
if (advancedIdx == size) {
|
|
||||||
return { true, advancedIdx, newItem };
|
|
||||||
} else {
|
|
||||||
return { false, advancedIdx, {} };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mStack.append(&mItems.append({ mCurrentState, {}, {} }));
|
|
||||||
}
|
|
||||||
|
|
||||||
advancedIdx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { false, advancedIdx, nullptr };
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef FiniteStateAutomation<tAlphabetType, tStateType> Automata;
|
|
||||||
typedef Automata::State AutomataState;
|
|
||||||
|
|
||||||
void construct(const Automata& automata) {
|
|
||||||
mRange = automata.getAlphabetRange();
|
|
||||||
|
|
||||||
const ualni numStates = automata.numStates();
|
|
||||||
const ualni numSymbols = mRange.idxDiff();
|
|
||||||
|
|
||||||
mTable.reserve({ numSymbols, numStates });
|
|
||||||
mTable.assign(Action{ Action::TRAP, 0 });
|
|
||||||
|
|
||||||
Map<const AutomataState*, ualni> states;
|
|
||||||
ualni stateIndex = 0;
|
|
||||||
for (auto state : *automata.getStates()) {
|
|
||||||
states.put(&state.data(), { stateIndex });
|
|
||||||
stateIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
stateIndex = 0;
|
|
||||||
for (auto state : *automata.getStates()) {
|
|
||||||
if (&state.data() == automata.getStartState()) {
|
|
||||||
mStartState = stateIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state->isAccepting()) {
|
|
||||||
ASSERT(state->getTransitions()->size() == 0)
|
|
||||||
for (auto symbolIndex : Range<ualni>(numSymbols)) {
|
|
||||||
mTable.set({ stateIndex, symbolIndex }, { Action::REDUCE, state->getStateVal().numArgs() });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (auto transition : *state->getTransitions()) {
|
|
||||||
ualni symbolIndex = ualni(transition->getSymbol()) - mRange.mBegin;
|
|
||||||
ualni targetStateIndex = states.get(transition->getState());
|
|
||||||
mTable.set({ stateIndex, symbolIndex }, { Action::SHIFT, targetStateIndex });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stateIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Buffer2D<Action> mTable;
|
|
||||||
|
|
||||||
Buffer<StackItem> mItems;
|
|
||||||
Buffer<StackItem*> mStack;
|
|
||||||
|
|
||||||
ualni mStartState = 0;
|
|
||||||
ualni mCurrentState = 0;
|
|
||||||
|
|
||||||
Range<ualni> mRange;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,181 +0,0 @@
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Automata.hpp"
|
|
||||||
#include "Grammar.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
class ContextFreeCompiler {
|
|
||||||
public:
|
|
||||||
struct SymbolVal {
|
|
||||||
SymbolVal() = default;
|
|
||||||
|
|
||||||
SymbolVal(ualni aId, ualni aStart, ualni aLen) {
|
|
||||||
id = aId;
|
|
||||||
start = aStart;
|
|
||||||
len = aLen;
|
|
||||||
};
|
|
||||||
|
|
||||||
SymbolVal(ualni val) { id = val; }
|
|
||||||
|
|
||||||
operator ualni() const { return id; }
|
|
||||||
|
|
||||||
bool operator==(const SymbolVal& in) const { return in.id == id; }
|
|
||||||
SymbolVal& operator=(const SymbolVal& in) = default;
|
|
||||||
|
|
||||||
ualni id = 0;
|
|
||||||
ualni start = 0;
|
|
||||||
ualni len = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Item {
|
|
||||||
const ContextFreeGrammar::Rule* mRule = nullptr;
|
|
||||||
ualni mAdvanceIdx = 0;
|
|
||||||
ualni numArgs() const { return 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Symbol {
|
|
||||||
String mId;
|
|
||||||
bool mIsTerminal = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct NonTerminal {
|
|
||||||
Buffer<ContextFreeGrammar::Rule*> rules;
|
|
||||||
Map<String, NonTerminal*> references;
|
|
||||||
Map<String, NonTerminal*> referencing;
|
|
||||||
|
|
||||||
public:
|
|
||||||
[[nodiscard]] bool isProductive() const {
|
|
||||||
for (auto rule : rules) {
|
|
||||||
if (rule->isProductive()) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool isLooped(Map<String, ualni>& processed, const String& id) const {
|
|
||||||
for (auto ref : referencing) {
|
|
||||||
if (processed.presents(ref->key)) return true;
|
|
||||||
}
|
|
||||||
processed.put(id, {});
|
|
||||||
for (auto ref : referencing) {
|
|
||||||
if (ref->val->isLooped(processed, ref->key)) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool compile(const ContextFreeGrammar& grammar, FiniteStateAutomation<SymbolVal, Item>& automata) {
|
|
||||||
if (!init(grammar)) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] const Buffer<Symbol>* getSymbols() const { return &mSymbols; }
|
|
||||||
[[nodiscard]] SymbolVal getSymbolId(const String& name) const { return mSymbolLookup.get(name); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool init(const ContextFreeGrammar& grammar) {
|
|
||||||
|
|
||||||
if (!grammar.getRules()->size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto rule : *grammar.getRules()) {
|
|
||||||
if (!rule->getArgs()->size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
findNonTerminals(grammar);
|
|
||||||
|
|
||||||
for (auto nonTerminal : mNonTerminals) {
|
|
||||||
for (auto rule : nonTerminal->val.rules) {
|
|
||||||
for (auto arg : *rule->getArgs()) {
|
|
||||||
if (arg->isTerminal() || arg->isEpsilon()) continue;
|
|
||||||
|
|
||||||
if (!mNonTerminals.presents(arg->getId())) {
|
|
||||||
printf("Referenced non-terminal '%s' is not defined\n", arg->getId().read());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
findAllReferences(grammar);
|
|
||||||
|
|
||||||
for (auto nonTerminal : mNonTerminals) {
|
|
||||||
if (!nonTerminal->val.references.size() && nonTerminal->key != grammar.getStartTerminal()) {
|
|
||||||
printf("Non-terminal '%s' is defined but not used\n", nonTerminal->key.read());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto nonTerminal : mNonTerminals) {
|
|
||||||
if (!nonTerminal->val.isProductive()) {
|
|
||||||
printf("Non-terminal '%s' is not productive\n", nonTerminal->val.rules.first()->getId().read());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, ualni> processed;
|
|
||||||
if (mNonTerminals.get(grammar.getStartTerminal()).isLooped(processed, grammar.getStartTerminal())) {
|
|
||||||
printf("Note that grammar is looped.\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
initSymbols(grammar);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void findNonTerminals(const ContextFreeGrammar& grammar) {
|
|
||||||
for (auto rule : *grammar.getRules()) {
|
|
||||||
if (!mNonTerminals.presents(rule->getId())) {
|
|
||||||
mNonTerminals.put(rule->getId(), {});
|
|
||||||
}
|
|
||||||
auto nonTerminal = &mNonTerminals.get(rule->getId());
|
|
||||||
nonTerminal->rules.append(&rule.data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void findAllReferences(const ContextFreeGrammar& grammar) {
|
|
||||||
for (auto nonTerminal : mNonTerminals) {
|
|
||||||
for (auto rule : nonTerminal->val.rules) {
|
|
||||||
for (auto arg : *rule->getArgs()) {
|
|
||||||
if (arg->isTerminal() || arg->isEpsilon()) continue;
|
|
||||||
|
|
||||||
NonTerminal* reference = &mNonTerminals.get(arg->getId());
|
|
||||||
nonTerminal->val.referencing.put(arg->getId(), reference);
|
|
||||||
reference->references.put(nonTerminal->key, &nonTerminal->val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void initSymbols(const ContextFreeGrammar& grammar) {
|
|
||||||
for (auto nonTerminal : mNonTerminals) {
|
|
||||||
mSymbols.append({ nonTerminal->key, false });
|
|
||||||
mSymbolLookup.put(nonTerminal->key, SymbolVal(mSymbols.size() - 1));
|
|
||||||
|
|
||||||
for (auto rule : nonTerminal->val.rules) {
|
|
||||||
for (auto arg : *rule->getArgs()) {
|
|
||||||
if (arg->isEpsilon() || arg->isTerminal()) continue;
|
|
||||||
if (mTerminals.presents(arg->getId())) continue;
|
|
||||||
mTerminals.put(arg->getId(), {});
|
|
||||||
|
|
||||||
mSymbols.append({ nonTerminal->key, true });
|
|
||||||
mSymbolLookup.put(nonTerminal->key, SymbolVal(mSymbols.size() - 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Map<String, NonTerminal> mNonTerminals;
|
|
||||||
Map<String, bool> mTerminals;
|
|
||||||
Buffer<Symbol> mSymbols;
|
|
||||||
Map<String, SymbolVal> mSymbolLookup;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,224 +0,0 @@
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Buffer.hpp"
|
|
||||||
#include "LanguageCommon.hpp"
|
|
||||||
#include "Map.hpp"
|
|
||||||
#include "Strings.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
class ContextFreeGrammar {
|
|
||||||
public:
|
|
||||||
struct Arg {
|
|
||||||
friend class Rule;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Arg() = default;
|
|
||||||
explicit Arg(const String& id, bool terminal = true, bool epsilon = false);
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool operator==(const Arg& in) const;
|
|
||||||
[[nodiscard]] const String& getId() const;
|
|
||||||
[[nodiscard]] bool isTerminal() const { return mIsTerminal; }
|
|
||||||
[[nodiscard]] bool isEpsilon() const { return mIsEpsilon; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
String mId;
|
|
||||||
bool mIsTerminal = false;
|
|
||||||
bool mIsEpsilon = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Rule {
|
|
||||||
public:
|
|
||||||
Rule() = default;
|
|
||||||
Rule(const String& id, const InitialierList<Arg>& args);
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool operator==(const Rule& in) const;
|
|
||||||
[[nodiscard]] bool isProductive() const;
|
|
||||||
[[nodiscard]] const String& getId() const { return mId; }
|
|
||||||
[[nodiscard]] const Buffer<Arg>* getArgs() const { return &mArgs; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
String mId;
|
|
||||||
Buffer<Arg> mArgs;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
ContextFreeGrammar() = default;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void addRule(const Rule& rule);
|
|
||||||
void addRule(const String& id, const InitialierList<Arg>& args);
|
|
||||||
void setStart(const String& startRule);
|
|
||||||
[[nodiscard]] const Buffer<Rule>* getRules() const { return &mRules; }
|
|
||||||
[[nodiscard]] const String& getStartTerminal() const { return mStartTerminal; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
Buffer<Rule> mRules;
|
|
||||||
String mStartTerminal;
|
|
||||||
bool mIsLooped = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename tAlphabetType, typename tTokType>
|
|
||||||
class RegularGrammar {
|
|
||||||
public:
|
|
||||||
struct Node {
|
|
||||||
enum Type {
|
|
||||||
NONE,
|
|
||||||
ANY,
|
|
||||||
OR,
|
|
||||||
IF,
|
|
||||||
CLASS,
|
|
||||||
COMPOUND,
|
|
||||||
REPEAT,
|
|
||||||
VAL,
|
|
||||||
} mType = NONE;
|
|
||||||
|
|
||||||
explicit Node(Type type) :
|
|
||||||
mType(type) {}
|
|
||||||
|
|
||||||
virtual ~Node() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ValueNode : public Node {
|
|
||||||
public:
|
|
||||||
explicit ValueNode(tAlphabetType val) :
|
|
||||||
mVal(val),
|
|
||||||
Node(Node::VAL) {}
|
|
||||||
|
|
||||||
~ValueNode() override = default;
|
|
||||||
|
|
||||||
public:
|
|
||||||
tAlphabetType mVal;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CompoundNode : public Node {
|
|
||||||
public:
|
|
||||||
CompoundNode() :
|
|
||||||
Node(Node::COMPOUND) {}
|
|
||||||
|
|
||||||
CompoundNode(const InitialierList<const Node*>& nodes) :
|
|
||||||
Node(Node::COMPOUND) {
|
|
||||||
mSequence = nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
~CompoundNode() override {
|
|
||||||
for (auto iter : mSequence) {
|
|
||||||
delete iter.data();
|
|
||||||
}
|
|
||||||
mSequence.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Buffer<const Node*> mSequence;
|
|
||||||
};
|
|
||||||
|
|
||||||
class AlternationNode : public Node {
|
|
||||||
public:
|
|
||||||
AlternationNode() :
|
|
||||||
Node(Node::OR) {}
|
|
||||||
|
|
||||||
AlternationNode(const Node* a, const Node* b) :
|
|
||||||
Node(Node::OR) {
|
|
||||||
mFirst = a;
|
|
||||||
mSecond = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
~AlternationNode() override {
|
|
||||||
delete mFirst;
|
|
||||||
delete mSecond;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
const Node* mFirst = nullptr;
|
|
||||||
const Node* mSecond = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IfNode : public Node {
|
|
||||||
public:
|
|
||||||
IfNode() :
|
|
||||||
Node(Node::IF) {}
|
|
||||||
|
|
||||||
explicit IfNode(const Node* a) :
|
|
||||||
Node(Node::IF) {
|
|
||||||
mNode = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
~IfNode() override { delete mNode; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
const Node* mNode = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
class AnyNode : public Node {
|
|
||||||
public:
|
|
||||||
AnyNode() :
|
|
||||||
Node(Node::ANY) {}
|
|
||||||
|
|
||||||
~AnyNode() override = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RepetitionNode : public Node {
|
|
||||||
public:
|
|
||||||
RepetitionNode() :
|
|
||||||
Node(Node::REPEAT) {}
|
|
||||||
|
|
||||||
explicit RepetitionNode(const Node* rep, bool plus = false) :
|
|
||||||
Node(Node::REPEAT) {
|
|
||||||
mNode = rep;
|
|
||||||
mPlus = plus;
|
|
||||||
}
|
|
||||||
|
|
||||||
~RepetitionNode() override { delete mNode; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
Node* mNode = nullptr;
|
|
||||||
bool mPlus = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ClassNode : public Node {
|
|
||||||
public:
|
|
||||||
ClassNode() :
|
|
||||||
Node(Node::CLASS) {}
|
|
||||||
|
|
||||||
explicit ClassNode(const Buffer<Range<tAlphabetType>>& ranges, bool exclude = false) :
|
|
||||||
Node(Node::CLASS) {
|
|
||||||
mExclude = exclude;
|
|
||||||
mRanges = ranges;
|
|
||||||
}
|
|
||||||
|
|
||||||
~ClassNode() override { mRanges.removeAll(); }
|
|
||||||
|
|
||||||
public:
|
|
||||||
Buffer<Range<tAlphabetType>> mRanges;
|
|
||||||
bool mExclude = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
RegularGrammar() = default;
|
|
||||||
|
|
||||||
~RegularGrammar() {
|
|
||||||
for (auto rule : mRules) {
|
|
||||||
delete rule->t1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void addRule(const Node* node, tTokType id) { mRules.append({ node, id }); }
|
|
||||||
|
|
||||||
public:
|
|
||||||
const Node* seq(const InitialierList<const Node*>& nodes) { return new CompoundNode(nodes); }
|
|
||||||
const Node* val(tAlphabetType in) { return new ValueNode(in); }
|
|
||||||
const Node* alt(const Node* a, const Node* b) { return new AlternationNode(a, b); }
|
|
||||||
const Node* may(const Node* a) { return new IfNode(a); }
|
|
||||||
const Node* any() { return new AnyNode(); }
|
|
||||||
const Node* rep(const Node* rep, bool plus = false) { return new RepetitionNode(rep, plus); }
|
|
||||||
const Node* ranges(const Buffer<Range<tAlphabetType>>& ranges, bool exclude = false) {
|
|
||||||
return new ClassNode(ranges, exclude);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Buffer<Pair<const Node*, tTokType>> mRules;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Module.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
extern ModuleManifest gModuleLanguage;
|
|
||||||
}
|
|
||||||
|
|
@ -1,107 +0,0 @@
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "RegularCompiler.hpp"
|
|
||||||
#include "RegularAutomata.hpp"
|
|
||||||
|
|
||||||
#include "ContextFreeCompiler.hpp"
|
|
||||||
#include "ContextFreeAutomata.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
template <typename tAlphabetType, typename tTokenType, tTokenType tInTransition, ualni MinSymbol, ualni MaxSymbol>
|
|
||||||
class Parser {
|
|
||||||
|
|
||||||
typedef RegularGrammar<tAlphabetType, tTokenType> RegularGrammar;
|
|
||||||
typedef RegularCompiler<tAlphabetType, tTokenType, tInTransition, MinSymbol, MaxSymbol> RegularCompiler;
|
|
||||||
typedef FiniteStateAutomation<tAlphabetType, tTokenType> RegularGraph;
|
|
||||||
typedef RegularAutomata<tAlphabetType, tTokenType> RegularAutomata;
|
|
||||||
|
|
||||||
// ContextFreeGrammar;
|
|
||||||
// ContextFreeCompiler;
|
|
||||||
typedef FiniteStateAutomation<ContextFreeCompiler::SymbolVal, ContextFreeCompiler::Item> ContextFreeGraph;
|
|
||||||
typedef ContextFreeAutomata<ContextFreeCompiler::SymbolVal, ContextFreeCompiler::Item> ContextFreeAutomata;
|
|
||||||
|
|
||||||
public:
|
|
||||||
struct ParseResult {
|
|
||||||
bool accepted = false;
|
|
||||||
const ContextFreeAutomata::StackItem* ast = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
Parser() = default;
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool compileTables(
|
|
||||||
const ContextFreeGrammar& cfGrammar,
|
|
||||||
const RegularGrammar& reGrammar,
|
|
||||||
const Map<String, tTokenType>& contextFreeToRegular
|
|
||||||
) {
|
|
||||||
// Compile Regular Grammar
|
|
||||||
{
|
|
||||||
RegularGraph graph;
|
|
||||||
RegularCompiler compiler;
|
|
||||||
compiler.compile(graph, reGrammar);
|
|
||||||
graph.makeDeterministic();
|
|
||||||
mRegularAutomata.construct(graph);
|
|
||||||
}
|
|
||||||
|
|
||||||
// compile context free grammar
|
|
||||||
{
|
|
||||||
ContextFreeGraph graph;
|
|
||||||
ContextFreeCompiler compiler;
|
|
||||||
compiler.compile(cfGrammar, graph);
|
|
||||||
graph.makeDeterministic();
|
|
||||||
mContextFreeAutomata.construct(graph);
|
|
||||||
|
|
||||||
// make glue
|
|
||||||
for (auto symbol : *compiler.getSymbols()) {
|
|
||||||
auto symbolId = compiler.getSymbolId(symbol->mId);
|
|
||||||
if (symbol->mIsTerminal) {
|
|
||||||
auto iter = contextFreeToRegular.presents(symbol->mId);
|
|
||||||
if (!iter) return false;
|
|
||||||
mGrammarGlue.put(contextFreeToRegular.getSlotVal(iter), symbolId);
|
|
||||||
} else {
|
|
||||||
mAstNames.put(symbolId, symbol->mId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ParseResult parse(const tAlphabetType* sentence, ualni sentenceLength) {
|
|
||||||
// get tokens stream
|
|
||||||
Buffer<ContextFreeCompiler::SymbolVal> tokens;
|
|
||||||
|
|
||||||
const tAlphabetType* sentenceIter = sentence;
|
|
||||||
ualni lengthIter = sentenceLength;
|
|
||||||
|
|
||||||
while (lengthIter) {
|
|
||||||
auto result = mRegularAutomata.accept(sentenceIter, lengthIter);
|
|
||||||
|
|
||||||
if (!result.accepted) {
|
|
||||||
return { false, nullptr };
|
|
||||||
}
|
|
||||||
|
|
||||||
tokens.append(ContextFreeCompiler::SymbolVal(
|
|
||||||
mGrammarGlue.get(result.state), ualni(sentenceIter - sentence), result.advancedIdx
|
|
||||||
));
|
|
||||||
|
|
||||||
sentenceIter += result.advancedIdx;
|
|
||||||
lengthIter -= result.advancedIdx;
|
|
||||||
}
|
|
||||||
|
|
||||||
ContextFreeAutomata::AcceptResult result = mContextFreeAutomata.accept(tokens.getBuff(), tokens.size());
|
|
||||||
return { result.accepted, result.ast };
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
// save load compiled tables
|
|
||||||
RegularAutomata mRegularAutomata;
|
|
||||||
ContextFreeAutomata mContextFreeAutomata;
|
|
||||||
|
|
||||||
Map<tTokenType, ContextFreeCompiler::SymbolVal> mGrammarGlue;
|
|
||||||
Map<ContextFreeCompiler::SymbolVal, String> mAstNames;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,101 +0,0 @@
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Strings.hpp"
|
|
||||||
#include "Automata.hpp"
|
|
||||||
#include "Buffer2D.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
template <typename tAlphabetType, typename tStateType>
|
|
||||||
class RegularAutomata {
|
|
||||||
public:
|
|
||||||
struct AcceptResult {
|
|
||||||
bool accepted = false;
|
|
||||||
ualni advancedIdx = 0;
|
|
||||||
tStateType state = tStateType();
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
RegularAutomata() = default;
|
|
||||||
|
|
||||||
AcceptResult accept(const tAlphabetType* stream, ualni size) {
|
|
||||||
mCurrentState = mStartState;
|
|
||||||
|
|
||||||
ualni advancedIdx = 0;
|
|
||||||
|
|
||||||
while (advancedIdx < size) {
|
|
||||||
const tAlphabetType& symbol = *(stream + advancedIdx);
|
|
||||||
|
|
||||||
if (!(symbol >= mSymbolRange.mBegin && symbol < mSymbolRange.mEnd)) {
|
|
||||||
return { false, advancedIdx, {} };
|
|
||||||
}
|
|
||||||
|
|
||||||
mCurrentState = mTable.get({ (ualni) (symbol - mSymbolRange.mBegin), mCurrentState });
|
|
||||||
|
|
||||||
if (mCurrentState == mStates.size()) {
|
|
||||||
return { false, advancedIdx, {} };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mStates[mCurrentState].first) {
|
|
||||||
return { true, advancedIdx, mStates[mCurrentState].second };
|
|
||||||
}
|
|
||||||
|
|
||||||
advancedIdx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { false, advancedIdx, {} };
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
void construct(const FiniteStateAutomation<tAlphabetType, tStateType>& automata) {
|
|
||||||
const auto range = automata.getAlphabetRange();
|
|
||||||
mSymbolRange = { tAlphabetType(range.mBegin), tAlphabetType(range.mEnd) };
|
|
||||||
|
|
||||||
auto range_len = ualni(mSymbolRange.mEnd - mSymbolRange.mBegin);
|
|
||||||
auto sizeX = range_len ? range_len : 1;
|
|
||||||
auto sizeY = (ualni) (automata.numStates());
|
|
||||||
|
|
||||||
mTable.reserve({ sizeX, sizeY });
|
|
||||||
mTable.assign(automata.numStates());
|
|
||||||
mStates.reserve(sizeY);
|
|
||||||
|
|
||||||
ualni idx = 0;
|
|
||||||
for (auto state : *automata.getStates()) {
|
|
||||||
mStates[idx] = { state->isAccepting(), state->getStateVal() };
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
idx = 0;
|
|
||||||
for (auto state : *automata.getStates()) {
|
|
||||||
if (&state.data() == automata.getStartState()) {
|
|
||||||
mStartState = mCurrentState = idx;
|
|
||||||
}
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
ualni stateIdx = 0;
|
|
||||||
for (auto state : *automata.getStates()) {
|
|
||||||
for (auto transition : *state->getTransitions()) {
|
|
||||||
ualni stateIdx2 = 0;
|
|
||||||
for (auto state2 : *automata.getStates()) {
|
|
||||||
if (transition->getState() == &state2.data()) break;
|
|
||||||
stateIdx2++;
|
|
||||||
}
|
|
||||||
auto const code = transition->getSymbol();
|
|
||||||
mTable.set({ (ualni) (code - mSymbolRange.mBegin), (ualni) stateIdx }, stateIdx2);
|
|
||||||
}
|
|
||||||
stateIdx++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Buffer2D<ualni> mTable;
|
|
||||||
Buffer<Pair<bool, tStateType>> mStates;
|
|
||||||
|
|
||||||
ualni mCurrentState = 0;
|
|
||||||
ualni mStartState = 0;
|
|
||||||
|
|
||||||
Range<tAlphabetType> mSymbolRange = { 0, 0 };
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,208 +0,0 @@
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Grammar.hpp"
|
|
||||||
#include "Automata.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
template <typename tAlphabetType, typename tStateType, tStateType tInTransition, ualni tMinSymbol, ualni tMaxSymbol>
|
|
||||||
class RegularCompiler {
|
|
||||||
|
|
||||||
typedef FiniteStateAutomation<tAlphabetType, tStateType> Graph;
|
|
||||||
typedef typename Graph::State Vertex;
|
|
||||||
typedef RegularGrammar<tAlphabetType, tStateType> Grammar;
|
|
||||||
|
|
||||||
struct Node {
|
|
||||||
Vertex* left = nullptr;
|
|
||||||
Vertex* right = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
Graph* mGraph = nullptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
struct CompileError {
|
|
||||||
uhalni mRuleIndex = 0;
|
|
||||||
tStateType mRuleState;
|
|
||||||
const char* description = nullptr;
|
|
||||||
[[nodiscard]] bool isError() const { return description; }
|
|
||||||
};
|
|
||||||
|
|
||||||
CompileError mError;
|
|
||||||
|
|
||||||
void compile(Graph& graph, const tAlphabetType* regex, tStateType state) {
|
|
||||||
mGraph = &graph;
|
|
||||||
compileUtil(regex, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void compile(Graph& aGraph, const Grammar& grammar) {
|
|
||||||
mGraph = &aGraph;
|
|
||||||
|
|
||||||
auto left = addVertex();
|
|
||||||
auto right = addVertex();
|
|
||||||
|
|
||||||
halni idx = 0;
|
|
||||||
for (auto rule : grammar.mRules) {
|
|
||||||
|
|
||||||
auto node = compileUtil(rule.data().first, rule.data().second);
|
|
||||||
|
|
||||||
if (!(node.left && node.right)) {
|
|
||||||
mError.mRuleIndex = idx;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
transitionAny(left, node.left);
|
|
||||||
transitionAny(node.right, right);
|
|
||||||
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
mGraph->setStartState(left);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Node compileUtil(const Grammar::Node* astNode, tStateType state) {
|
|
||||||
|
|
||||||
auto node = compileNode(astNode, nullptr, nullptr);
|
|
||||||
|
|
||||||
node.right->setValue(state);
|
|
||||||
node.right->setAcceptance(true);
|
|
||||||
|
|
||||||
mGraph->setStartState(node.left);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node compileVal(Grammar::ValueNode* val, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
|
|
||||||
auto left = aLeft ? aLeft : addVertex();
|
|
||||||
auto right = aRight ? aRight : addVertex();
|
|
||||||
transitionVal(left, right, val->mVal);
|
|
||||||
return { left, right };
|
|
||||||
}
|
|
||||||
|
|
||||||
Node compileAlternation(const Grammar::AlternationNode* alt, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
|
|
||||||
auto first_node = compileNode(alt->mFirst, aLeft, aRight);
|
|
||||||
auto second_node = compileNode(alt->mSecond);
|
|
||||||
transitionAny(first_node.left, second_node.left);
|
|
||||||
transitionAny(second_node.right, first_node.right);
|
|
||||||
return first_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node compileAny(const Grammar::AnyNode*, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
|
|
||||||
auto left = aLeft ? aLeft : addVertex();
|
|
||||||
auto right = aRight ? aRight : addVertex();
|
|
||||||
transitionAny(left, right, true);
|
|
||||||
return { left, right };
|
|
||||||
}
|
|
||||||
|
|
||||||
Node compileRepeat(const Grammar::RepetitionNode* repeat, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
|
|
||||||
if (repeat->mPlus) {
|
|
||||||
auto middle = addVertex();
|
|
||||||
|
|
||||||
auto left_node = compileNode(repeat->mNode, aLeft, middle);
|
|
||||||
|
|
||||||
auto right_node = compileNode(repeat->mNode, middle, aRight);
|
|
||||||
transitionAny(right_node.right, right_node.left);
|
|
||||||
transitionAny(right_node.left, right_node.right);
|
|
||||||
|
|
||||||
return { left_node.left, right_node.right };
|
|
||||||
} else {
|
|
||||||
auto node = compileNode(repeat->mNode, aLeft, aRight);
|
|
||||||
transitionAny(node.right, node.left);
|
|
||||||
transitionAny(node.left, node.right);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Node compileIf(const Grammar::IfNode* ifNode, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
|
|
||||||
auto node = compileNode(ifNode->mNode, aLeft, aRight);
|
|
||||||
transitionAny(node.left, node.right);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node compileClass(const Grammar::ClassNode* node, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
|
|
||||||
auto left = aLeft ? aLeft : addVertex();
|
|
||||||
auto right = aRight ? aRight : addVertex();
|
|
||||||
|
|
||||||
if (node->mRanges.size() == 1) {
|
|
||||||
auto const& range = node->mRanges.first();
|
|
||||||
transitionRange(left, right, { ualni(range.mBegin), ualni(range.mEnd) }, node->mExclude);
|
|
||||||
return { left, right };
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto range : node->mRanges) {
|
|
||||||
auto middle = addVertex();
|
|
||||||
transitionRange(left, middle, { ualni(range->mBegin), ualni(range->mEnd) }, node->mExclude);
|
|
||||||
transitionAny(middle, right);
|
|
||||||
}
|
|
||||||
return { left, right };
|
|
||||||
}
|
|
||||||
|
|
||||||
Node compileCompound(const Grammar::CompoundNode* compound, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
|
|
||||||
Vertex* left = nullptr;
|
|
||||||
Vertex* rigth = nullptr;
|
|
||||||
|
|
||||||
ualni idx = 0;
|
|
||||||
for (auto child : compound->mSequence) {
|
|
||||||
auto pass_left = idx == 0 ? aLeft : rigth;
|
|
||||||
auto pass_right = idx == compound->mSequence.size() - 1 ? aRight : nullptr;
|
|
||||||
auto node = compileNode(child.data(), pass_left, pass_right);
|
|
||||||
if (!left) left = node.left;
|
|
||||||
rigth = node.right;
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { left, rigth };
|
|
||||||
}
|
|
||||||
|
|
||||||
Node compileNode(const Grammar::Node* node, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
|
|
||||||
switch (node->mType) {
|
|
||||||
case Grammar::Node::CLASS: return compileClass((typename Grammar::ClassNode*) node, aLeft, aRight);
|
|
||||||
case Grammar::Node::COMPOUND: return compileCompound((typename Grammar::CompoundNode*) node, aLeft, aRight);
|
|
||||||
case Grammar::Node::IF: return compileIf((typename Grammar::IfNode*) node, aLeft, aRight);
|
|
||||||
case Grammar::Node::REPEAT: return compileRepeat((typename Grammar::RepetitionNode*) node, aLeft, aRight);
|
|
||||||
case Grammar::Node::ANY: return compileAny((typename Grammar::AnyNode*) node, aLeft, aRight);
|
|
||||||
case Grammar::Node::OR: return compileAlternation((typename Grammar::AlternationNode*) node, aLeft, aRight);
|
|
||||||
case Grammar::Node::VAL: return compileVal((typename Grammar::ValueNode*) node, aLeft, aRight);
|
|
||||||
case Grammar::Node::NONE: break;
|
|
||||||
}
|
|
||||||
ASSERT(0)
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
void transitionAny(Vertex* from, Vertex* to, bool consumes = false) {
|
|
||||||
for (auto symbol : Range<ualni>(tMinSymbol, tMaxSymbol)) {
|
|
||||||
transitionVal(from, to, symbol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void transitionVal(Vertex* from, Vertex* to, tAlphabetType val) { mGraph->addTransition(from, to, val); }
|
|
||||||
|
|
||||||
void transitionRange(Vertex* from, Vertex* to, Range<ualni> range, bool exclude) {
|
|
||||||
if (exclude) {
|
|
||||||
Range<ualni> first = { tMinSymbol, range.mBegin - 1 };
|
|
||||||
Range<ualni> second = { range.mEnd + 1, tMaxSymbol };
|
|
||||||
|
|
||||||
if (first.valid()) {
|
|
||||||
for (auto symbol : first) {
|
|
||||||
transitionVal(from, to, symbol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (second.valid()) {
|
|
||||||
for (auto symbol : second) {
|
|
||||||
transitionVal(from, to, symbol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
for (auto symbol : range) {
|
|
||||||
transitionVal(from, to, symbol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vertex* addVertex() { return mGraph->addState(tInTransition, false); }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Parser.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
// Gives ability to express grammar in the Unified Format as sentence
|
|
||||||
template <typename tAlphabetType>
|
|
||||||
class SimpleParser {
|
|
||||||
enum UGTokens : alni { InTransition = -1, TestSeq };
|
|
||||||
|
|
||||||
typedef Parser<tAlphabetType, UGTokens, InTransition, 0, 127> UGParser;
|
|
||||||
typedef Parser<tAlphabetType, alni, -1, 0, 127> UserParser;
|
|
||||||
|
|
||||||
public:
|
|
||||||
SimpleParser() {
|
|
||||||
// Grammar for unified grammar format sentence that tables compiled from
|
|
||||||
|
|
||||||
// Define Context-Free grammar
|
|
||||||
ContextFreeGrammar contextFreeGrammar;
|
|
||||||
{
|
|
||||||
// use existing CF grammar interface
|
|
||||||
contextFreeGrammar.addRule("a", { ContextFreeGrammar::Arg("") });
|
|
||||||
contextFreeGrammar.setStart("a");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define Regular grammar
|
|
||||||
RegularGrammar<tAlphabetType, UGTokens> regularGrammar;
|
|
||||||
{
|
|
||||||
// this is basically ast from existing tokenizer
|
|
||||||
regularGrammar.addRule(regularGrammar.seq({ regularGrammar.val('a'), regularGrammar.val('b') }), TestSeq);
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, UGTokens> terminalsMap;
|
|
||||||
terminalsMap.put("TestSeq", TestSeq);
|
|
||||||
|
|
||||||
mUnifiedGrammarParser.compileTables(contextFreeGrammar, regularGrammar, terminalsMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
void compileTables(const tAlphabetType* grammar, ualni grammarLength) {
|
|
||||||
mUnifiedGrammarParser.parse(grammar, grammarLength);
|
|
||||||
|
|
||||||
// compile each ast into RegularGrammar and ContextFree Grammar api instructions
|
|
||||||
ContextFreeGrammar userContextFreeGrammar;
|
|
||||||
RegularGrammar<tAlphabetType, alni> userRegularGrammar;
|
|
||||||
|
|
||||||
// ...
|
|
||||||
// split ast into RE and CF part
|
|
||||||
// generate and execute grammar api commands
|
|
||||||
// use existing tokenizer code to create RE transition matrix
|
|
||||||
// ...
|
|
||||||
// compile tables from user grammar
|
|
||||||
|
|
||||||
Map<String, alni> terminalsMap;
|
|
||||||
terminalsMap.put("TestSeq", 0);
|
|
||||||
|
|
||||||
mUserParser.compileTables(userContextFreeGrammar, userRegularGrammar, terminalsMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
UserParser::ParseResult parse(const tAlphabetType* grammar, ualni grammarLength) {
|
|
||||||
return mUserParser.parse(grammar, grammarLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
UGParser mUnifiedGrammarParser;
|
|
||||||
UserParser mUserParser;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// #include "SimpleParser.hpp"
|
|
||||||
|
|
||||||
const char* gGrammar = R"(
|
|
||||||
# Grammar in the CF-RE United Format (Defined by language module)
|
|
||||||
|
|
||||||
Rules : {
|
|
||||||
ScopeList : ScopeList Scope | Scope ;
|
|
||||||
Scope : \ScopeBegin StatementList \ScopeEnd;
|
|
||||||
StatementList : StatementList Statement \StatementEnd;
|
|
||||||
StatementList : Statement \StatementEnd;
|
|
||||||
Statement : \StatementBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
Terminals : {
|
|
||||||
Space : " " | "\t" | "\n" | "\r";
|
|
||||||
ScopeBegin : "{";
|
|
||||||
ScopeEnd : "}";
|
|
||||||
StatementEnd : ";";
|
|
||||||
StatementBody : "a" | "b";
|
|
||||||
}
|
|
||||||
|
|
||||||
Start : Scope;
|
|
||||||
Ignore : Space;
|
|
||||||
)";
|
|
||||||
|
|
||||||
const char* gSentence = R"(
|
|
||||||
{}
|
|
||||||
|
|
||||||
{ }
|
|
||||||
|
|
||||||
{
|
|
||||||
a;
|
|
||||||
a ; a ;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
a;
|
|
||||||
a;
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
|
|
||||||
#include "Test.hpp"
|
|
||||||
|
|
||||||
/*
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
void testAutomation() {
|
|
||||||
|
|
||||||
FiniteStateAutomation<char, int> automata;
|
|
||||||
|
|
||||||
auto start = automata.addState(0, false);
|
|
||||||
auto end = automata.addState(1, true);
|
|
||||||
|
|
||||||
automata.addTransition(start, end, 'a');
|
|
||||||
|
|
||||||
automata.setStartState(start);
|
|
||||||
|
|
||||||
automata.makeDeterministic();
|
|
||||||
}
|
|
||||||
|
|
||||||
void test() {
|
|
||||||
auto parser = SimpleParser<int1>();
|
|
||||||
|
|
||||||
parser.compileTables(gGrammar, String::Logic::calcLength(gGrammar));
|
|
||||||
auto result = parser.parse(gSentence, String::Logic::calcLength(gSentence));
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
|
|
||||||
tp::ModuleManifest* deps[] = { &tp::gModuleLanguage, nullptr };
|
|
||||||
tp::ModuleManifest testModule("Test", nullptr, nullptr, deps);
|
|
||||||
|
|
||||||
if (!testModule.initialize()) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
testAutomation();
|
|
||||||
test();
|
|
||||||
|
|
||||||
testModule.deinitialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
int main() { return 0; }
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
project(3DEditor)
|
|
||||||
|
|
||||||
### ---------------------- Externals --------------------- ###
|
|
||||||
set(BINDINGS_INCLUDE ../Externals/glfw/include ../Externals)
|
|
||||||
set(BINDINGS_LIBS glfw Imgui OpenImageDenoise)
|
|
||||||
|
|
||||||
### ---------------------- Static Library --------------------- ###
|
|
||||||
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
|
|
||||||
file(GLOB HEADERS "./public/*.hpp" "./public/*/*.hpp")
|
|
||||||
|
|
||||||
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
|
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ./public/ ${BINDINGS_INCLUDE} ./ext/)
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Widgets RasterRender RayTracer)
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${BINDINGS_LIBS})
|
|
||||||
|
|
||||||
### -------------------------- Applications -------------------------- ###
|
|
||||||
file(GLOB APP_SOURCES "./applications/*.cpp")
|
|
||||||
add_executable(3DEditorApp ${APP_SOURCES})
|
|
||||||
target_link_libraries(3DEditorApp ${PROJECT_NAME})
|
|
||||||
|
|
||||||
file(COPY "../RasterRender/rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
|
||||||
file(COPY "../Graphics/rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
|
||||||
file(COPY "../3DScene/rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
|
|
||||||
#include "EditorWidget.hpp"
|
|
||||||
|
|
||||||
#include "WidgetApplication.hpp"
|
|
||||||
#include "RootWidget.hpp"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
class EditorGUI : public WidgetApplication {
|
|
||||||
public:
|
|
||||||
EditorGUI() {
|
|
||||||
auto canvas = this->mGraphics->getCanvas();
|
|
||||||
mGui = new EditorWidget(canvas, &mEditor);
|
|
||||||
|
|
||||||
mEditor.loadDefaults();
|
|
||||||
|
|
||||||
setRoot(mGui);
|
|
||||||
// mScene.mCamera.lookAtPoint({ 0, 0, 0 }, { 3, 3, 2 }, { 0, 0, 1 });
|
|
||||||
}
|
|
||||||
|
|
||||||
~EditorGUI() override { delete mGui; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Editor mEditor;
|
|
||||||
EditorWidget* mGui;
|
|
||||||
};
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
EditorGUI gui;
|
|
||||||
gui.run();
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
|
|
||||||
#include "Editor.hpp"
|
|
||||||
|
|
||||||
#include "OpenImageDenoise/oidn.hpp"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
void Editor::denoise() {
|
|
||||||
auto& out = mPathTracerBuffers;
|
|
||||||
|
|
||||||
// Initialize OIDN device
|
|
||||||
oidn::DeviceRef device = oidn::newDevice(oidn::DeviceType::CPU);
|
|
||||||
device.commit();
|
|
||||||
|
|
||||||
// Define buffer size
|
|
||||||
const int channels = 4; // ARGB
|
|
||||||
const auto size = out.color.size();
|
|
||||||
// Create the denoising filter
|
|
||||||
oidn::FilterRef filter = device.newFilter("RT"); // Use the 'RT' filter for path tracing
|
|
||||||
|
|
||||||
// Set the input and output buffer (same buffer for in-place denoising)
|
|
||||||
filter.setImage("color", out.color.getBuff(), oidn::Format::Float3, size.x, size.y, 0, sizeof(float) * channels); // ARGB
|
|
||||||
filter.setImage("output", out.color.getBuff(), oidn::Format::Float3, size.x, size.y, 0, sizeof(float) * channels); // ARGB
|
|
||||||
|
|
||||||
// Set additional parameters if needed
|
|
||||||
filter.set("hdr", false); // Assuming the input image is not HDR
|
|
||||||
|
|
||||||
// Commit the filter
|
|
||||||
filter.commit();
|
|
||||||
|
|
||||||
// Execute the filter
|
|
||||||
filter.execute();
|
|
||||||
|
|
||||||
// Check for errors
|
|
||||||
const char* errorMessage;
|
|
||||||
if (device.getError(errorMessage) != oidn::Error::None) {
|
|
||||||
std::cerr << "Error: " << errorMessage << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,140 +0,0 @@
|
||||||
|
|
||||||
#include "Editor.hpp"
|
|
||||||
|
|
||||||
#include "GraphicsApi.hpp"
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
Editor::Editor() {
|
|
||||||
|
|
||||||
{ // create path tracer gpu texture
|
|
||||||
glGenTextures(1, &mPathRenderTexture);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, mPathRenderTexture);
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 100, 100, 0, GL_RGBA, GL_FLOAT, nullptr);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Editor::renderViewport() {
|
|
||||||
switch (mRenderType) {
|
|
||||||
case RenderType::RASTER:
|
|
||||||
mRasterRenderer.beginRender(mScene, mScene.mRenderSettings.size);
|
|
||||||
mRasterRenderer.renderDefault(mScene);
|
|
||||||
if (mActive) mRasterRenderer.renderOutline(mScene.mCamera, *mActive);
|
|
||||||
mRasterRenderer.endRender();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RenderType::PATH_TRACER:
|
|
||||||
{
|
|
||||||
// TODO : include in render viewport method
|
|
||||||
// renderPathFrame();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint4 Editor::getViewportTexID() {
|
|
||||||
switch (mRenderType) {
|
|
||||||
case RenderType::PATH_TRACER:
|
|
||||||
return mPathRenderTexture;
|
|
||||||
|
|
||||||
case RenderType::RASTER:
|
|
||||||
return mRasterRenderer.getRenderBufferID();
|
|
||||||
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Editor::loadDefaults() {
|
|
||||||
mScene.load("rsc/scene/script.lua");
|
|
||||||
mResetCamera = mScene.mCamera;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Editor::setViewportSize(const Vec2F& size) {
|
|
||||||
if (size.x <= 0 || size.y <= 0) return;
|
|
||||||
|
|
||||||
// TODO remove
|
|
||||||
// mScene.mCamera.rotate(0.01f, 0.0);
|
|
||||||
|
|
||||||
mScene.mRenderSettings.size = size;
|
|
||||||
|
|
||||||
mRasterRenderer.getRenderBuffer()->resize(size);
|
|
||||||
mScene.mCamera.setRatio(size.y / size.x);
|
|
||||||
}
|
|
||||||
|
|
||||||
Editor::~Editor() {
|
|
||||||
glDeleteTextures(1, &mPathRenderTexture);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Editor::renderPathFrame() {
|
|
||||||
mScene.updateCache();
|
|
||||||
mPathRenderer.render(mScene, mPathTracerBuffers, mScene.mRenderSettings);
|
|
||||||
sendBuffersToGPU();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Editor::sendBuffersToGPU() {
|
|
||||||
glBindTexture(GL_TEXTURE_2D, mPathRenderTexture);
|
|
||||||
const auto size = mPathTracerBuffers.color.size();
|
|
||||||
glTexImage2D(
|
|
||||||
GL_TEXTURE_2D,
|
|
||||||
0,
|
|
||||||
GL_RGBA32F,
|
|
||||||
(GLsizei) size.x,
|
|
||||||
(GLsizei) size.y,
|
|
||||||
0,
|
|
||||||
GL_RGBA,
|
|
||||||
GL_FLOAT,
|
|
||||||
mPathTracerBuffers.color.getBuff()
|
|
||||||
);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Editor::denoisePathRenderBuffers() {
|
|
||||||
denoise();
|
|
||||||
sendBuffersToGPU();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Editor::setRenderType(Editor::RenderType type) {
|
|
||||||
mRenderType = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Editor::navigationOrbit(const Vec2F& delta) {
|
|
||||||
mScene.mCamera.rotate(delta.x, delta.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Editor::navigationPan(const Vec2F& pos, const Vec2F& prevPos) {
|
|
||||||
mScene.mCamera.move(pos, prevPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Editor::navigationZoom(halnf factor) {
|
|
||||||
mScene.mCamera.zoom(factor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Editor::navigationReset() {
|
|
||||||
mScene.mCamera = mResetCamera;
|
|
||||||
// mScene.mCamera.lookAtPoint({ 0, 0, 0 }, { 1, 5, 1 }, { 0, 0, 1 });
|
|
||||||
}
|
|
||||||
|
|
||||||
void Editor::selectObject(const Vec2F& screenPos) {
|
|
||||||
mScene.updateCache();
|
|
||||||
|
|
||||||
auto dir = (mScene.mCamera.project(screenPos) - mScene.mCamera.getPos()).normalize();
|
|
||||||
Ray ray = Ray( dir, mScene.mCamera.getPos() );
|
|
||||||
|
|
||||||
auto rayCastData = mScene.castRay(ray, 1000);
|
|
||||||
mActive = rayCastData.obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object* Editor::getActiveObject() { return mActive; }
|
|
||||||
|
|
||||||
Scene* Editor::getScene() { return &mScene; }
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "RayTracer.hpp"
|
|
||||||
#include "RasterRender.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
class Editor {
|
|
||||||
public:
|
|
||||||
enum class RenderType { RASTER, PATH_TRACER };
|
|
||||||
|
|
||||||
public:
|
|
||||||
Editor();
|
|
||||||
~Editor();
|
|
||||||
|
|
||||||
void loadDefaults();
|
|
||||||
|
|
||||||
uint4 getViewportTexID();
|
|
||||||
|
|
||||||
void setViewportSize(const Vec2F& size);
|
|
||||||
void renderViewport();
|
|
||||||
|
|
||||||
void renderPathFrame();
|
|
||||||
void setRenderType(RenderType type);
|
|
||||||
void denoisePathRenderBuffers();
|
|
||||||
|
|
||||||
void navigationOrbit(const Vec2F& delta);
|
|
||||||
void navigationPan(const Vec2F& pos, const Vec2F& prevPos);
|
|
||||||
void navigationZoom(halnf factor);
|
|
||||||
void navigationReset();
|
|
||||||
|
|
||||||
void selectObject(const Vec2F& screenPos);
|
|
||||||
Object* getActiveObject();
|
|
||||||
|
|
||||||
Scene* getScene();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void sendBuffersToGPU();
|
|
||||||
void denoise();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Scene mScene;
|
|
||||||
|
|
||||||
Camera mResetCamera;
|
|
||||||
|
|
||||||
RenderType mRenderType = RenderType::RASTER;
|
|
||||||
|
|
||||||
RasterRender mRasterRenderer;
|
|
||||||
RayTracer mPathRenderer;
|
|
||||||
|
|
||||||
RayTracer::OutputBuffers mPathTracerBuffers;
|
|
||||||
uint4 mPathRenderTexture = 0;
|
|
||||||
|
|
||||||
Object* mActive = nullptr;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,154 +0,0 @@
|
||||||
#include "Widget.hpp"
|
|
||||||
#include "DockWidget.hpp"
|
|
||||||
|
|
||||||
#include "Editor.hpp"
|
|
||||||
#include "FloatingWidget.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
|
|
||||||
class ViewportWidget : public Widget {
|
|
||||||
public:
|
|
||||||
explicit ViewportWidget(Canvas* canvas, Editor* editor) {
|
|
||||||
mEditor = editor;
|
|
||||||
mImage = canvas->createImageFromTextId(mEditor->getViewportTexID(), { 0, 0 });
|
|
||||||
mCanvas = canvas;
|
|
||||||
}
|
|
||||||
|
|
||||||
~ViewportWidget() override { mCanvas->deleteImageHandle(mImage); }
|
|
||||||
|
|
||||||
void process(const EventHandler& events) override {
|
|
||||||
mEditor->setViewportSize(getAreaT().size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw(Canvas& canvas) override {
|
|
||||||
mEditor->renderViewport();
|
|
||||||
|
|
||||||
canvas.updateTextureID(mImage, mEditor->getViewportTexID());
|
|
||||||
canvas.drawImage(getArea().relative(), &mImage, PI);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Editor* mEditor;
|
|
||||||
|
|
||||||
Canvas* mCanvas = nullptr;
|
|
||||||
Canvas::ImageHandle mImage;
|
|
||||||
};
|
|
||||||
|
|
||||||
class EditorWidget : public DockWidget {
|
|
||||||
public:
|
|
||||||
EditorWidget(Canvas* canvas, Editor* editor) :
|
|
||||||
mViewport(canvas, editor) {
|
|
||||||
mEditor = editor;
|
|
||||||
|
|
||||||
mPanel.setText("Controls");
|
|
||||||
mPanel.addToMenu(&mNavigationMenu);
|
|
||||||
mPanel.addToMenu(&mRenderMenu);
|
|
||||||
|
|
||||||
dockWidget(&mPanel, DockLayout::RIGHT);
|
|
||||||
setCenterWidget(&mViewport);
|
|
||||||
|
|
||||||
// Render
|
|
||||||
{
|
|
||||||
mRenderPathTracer.setText("Render with Path Tracer");
|
|
||||||
mRenderRaster.setText("Render with Raster");
|
|
||||||
mRenderDeNoise.setText("Denoise (IntelOpenImage)");
|
|
||||||
|
|
||||||
mRenderMenu.addToMenu(&mRenderPathTracer);
|
|
||||||
mRenderMenu.addToMenu(&mRenderRaster);
|
|
||||||
mRenderMenu.addToMenu(&mRenderDeNoise);
|
|
||||||
|
|
||||||
mRenderMenu.setText("Render");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Navigation
|
|
||||||
{
|
|
||||||
mNavigationPan.setText("Pan");
|
|
||||||
mNavigationOrbit.setText("Orbit");
|
|
||||||
mNavigationZoom.setText("Zoom");
|
|
||||||
mNavigationReset.setText("Reset");
|
|
||||||
mNavigationSelect.setText("Select");
|
|
||||||
|
|
||||||
mNavigationMenu.addToMenu(&mNavigationPan);
|
|
||||||
mNavigationMenu.addToMenu(&mNavigationOrbit);
|
|
||||||
mNavigationMenu.addToMenu(&mNavigationZoom);
|
|
||||||
mNavigationMenu.addToMenu(&mNavigationReset);
|
|
||||||
mNavigationMenu.addToMenu(&mNavigationSelect);
|
|
||||||
|
|
||||||
mNavigationMenu.setText("Navigation");
|
|
||||||
}
|
|
||||||
|
|
||||||
mRenderPathTracer.setAction([this]() {
|
|
||||||
mEditor->renderPathFrame();
|
|
||||||
mEditor->setRenderType(Editor::RenderType::PATH_TRACER);
|
|
||||||
});
|
|
||||||
|
|
||||||
mRenderRaster.setAction( [this]() { mEditor->setRenderType(Editor::RenderType::RASTER); });
|
|
||||||
mRenderDeNoise.setAction( [this]() { mEditor->denoisePathRenderBuffers(); });
|
|
||||||
mNavigationOrbit.setAction( [this]() { mNavigationType = ORBIT; });
|
|
||||||
mNavigationPan.setAction( [this]() { mNavigationType = PAN; });
|
|
||||||
mNavigationZoom.setAction( [this](){ mNavigationType = ZOOM; });
|
|
||||||
mNavigationSelect.setAction( [this](){ mNavigationType = SELECT; });
|
|
||||||
mNavigationReset.setAction( [this]() { mEditor->navigationReset(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void process(const EventHandler& events) override {
|
|
||||||
DockWidget::process(events);
|
|
||||||
|
|
||||||
if (auto obj = mEditor->getActiveObject()) { // dummy rotate active object
|
|
||||||
auto rotator = obj->mTopology.Basis.rotatorDir({1, 1, 1}, 0.1);
|
|
||||||
obj->mTopology.Basis = rotator * obj->mTopology.Basis;
|
|
||||||
}
|
|
||||||
|
|
||||||
mEditor->getScene()->updateCache();
|
|
||||||
|
|
||||||
const auto& activeArea = mViewport.getArea();
|
|
||||||
|
|
||||||
auto pointer = events.getPointer();
|
|
||||||
auto pointerPrev = events.getPointerPrev();
|
|
||||||
auto pointerRelative = (((pointer - activeArea.pos) / activeArea.size) - 0.5f) * 2;
|
|
||||||
|
|
||||||
if (activeArea.isInside(pointer) && events.isDown(InputID::MOUSE1)) {
|
|
||||||
switch (mNavigationType) {
|
|
||||||
case ORBIT: mEditor->navigationOrbit(events.getPointerDelta() / activeArea.size * 3); break;
|
|
||||||
|
|
||||||
case PAN:
|
|
||||||
{
|
|
||||||
auto prevPointerRelative = (((pointerPrev - activeArea.pos) / activeArea.size) - 0.5f) * 2;
|
|
||||||
mEditor->navigationPan(prevPointerRelative, pointerRelative);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ZOOM: mEditor->navigationZoom(1 + (events.getPointerDelta().y / activeArea.size.y)); break;
|
|
||||||
case SELECT: mEditor->selectObject(pointerRelative * -1); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw(Canvas& canvas) override { canvas.rect(getArea().relative(), mBaseColor); }
|
|
||||||
|
|
||||||
public:
|
|
||||||
Editor* mEditor = nullptr;
|
|
||||||
|
|
||||||
ViewportWidget mViewport;
|
|
||||||
|
|
||||||
FloatingMenu mPanel;
|
|
||||||
|
|
||||||
// Controls
|
|
||||||
FloatingMenu mRenderMenu;
|
|
||||||
ButtonWidget mRenderPathTracer;
|
|
||||||
ButtonWidget mRenderRaster;
|
|
||||||
ButtonWidget mRenderDeNoise;
|
|
||||||
|
|
||||||
// Navigation
|
|
||||||
enum NavigationType { SELECT, ORBIT, PAN, ZOOM } mNavigationType = ORBIT;
|
|
||||||
|
|
||||||
FloatingMenu mNavigationMenu;
|
|
||||||
ButtonWidget mNavigationPan;
|
|
||||||
ButtonWidget mNavigationOrbit;
|
|
||||||
ButtonWidget mNavigationZoom;
|
|
||||||
ButtonWidget mNavigationReset;
|
|
||||||
ButtonWidget mNavigationSelect;
|
|
||||||
|
|
||||||
RGBA mBaseColor;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
project(3DScene)
|
|
||||||
|
|
||||||
### ---------------------- Static Library --------------------- ###
|
|
||||||
file(GLOB SOURCES "./private/*.cpp")
|
|
||||||
file(GLOB HEADERS "./public/*.hpp")
|
|
||||||
|
|
||||||
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
|
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
|
|
||||||
target_include_directories(${PROJECT_NAME} PRIVATE ../Externals/)
|
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Math)
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE Lua)
|
|
||||||
|
|
@ -1,223 +0,0 @@
|
||||||
|
|
||||||
#include "Scene.hpp"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "lauxlib.h"
|
|
||||||
#include "lualib.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
tp::Vec3F tp::Scene::getVec3(lua_State* state, const char* name) {
|
|
||||||
int stackSize = lua_gettop(state);
|
|
||||||
|
|
||||||
// Access the "pos" field and validate it
|
|
||||||
lua_getfield(state, -1, name);
|
|
||||||
if (!lua_istable(state, -1) || lua_rawlen(state, -1) != 3) {
|
|
||||||
throw IOError(std::string("Invalid vec3 named ") + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the values from the table
|
|
||||||
float pos[3];
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
lua_rawgeti(state, -1, i + 1);
|
|
||||||
if (lua_isnumber(state, -1)) {
|
|
||||||
pos[i] = lua_tonumber(state, -1);
|
|
||||||
} else {
|
|
||||||
throw IOError("vec3 values must be numbers");
|
|
||||||
}
|
|
||||||
lua_pop(state, 1); // pop number
|
|
||||||
}
|
|
||||||
lua_pop(state, 1); // pop vec3
|
|
||||||
|
|
||||||
ASSERT(stackSize == lua_gettop(state))
|
|
||||||
|
|
||||||
return { pos[0], pos[1], pos[2] };
|
|
||||||
}
|
|
||||||
|
|
||||||
tp::Vec2F tp::Scene::getVec2(lua_State* state, const char* name) {
|
|
||||||
int stackSize = lua_gettop(state);
|
|
||||||
|
|
||||||
// Access the "pos" field and validate it
|
|
||||||
lua_getfield(state, -1, name);
|
|
||||||
if (!lua_istable(state, -1) || lua_rawlen(state, -1) != 2) {
|
|
||||||
throw IOError(std::string("Invalid vec2 named ") + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the values from the table
|
|
||||||
float pos[2];
|
|
||||||
for (int i = 0; i < 2; i++) {
|
|
||||||
lua_rawgeti(state, -1, i + 1);
|
|
||||||
if (lua_isnumber(state, -1)) {
|
|
||||||
pos[i] = lua_tonumber(state, -1);
|
|
||||||
} else {
|
|
||||||
throw IOError("vec3 values must be numbers");
|
|
||||||
}
|
|
||||||
lua_pop(state, 1); // pop number
|
|
||||||
}
|
|
||||||
lua_pop(state, 1); // pop vec3
|
|
||||||
|
|
||||||
ASSERT(stackSize == lua_gettop(state))
|
|
||||||
|
|
||||||
return { pos[0], pos[1] };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to read a Lua table representing RenderSettings
|
|
||||||
int readRenderSettings(lua_State* L, tp::RenderSettings& settings) {
|
|
||||||
lua_getglobal(L, "RenderSettings");
|
|
||||||
if (!lua_istable(L, -1)) {
|
|
||||||
printf("RenderSettings is not a table.\n");
|
|
||||||
return 0; // Error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read depth field
|
|
||||||
lua_getfield(L, -1, "depth");
|
|
||||||
if (lua_isnumber(L, -1)) {
|
|
||||||
settings.depth = (int) lua_tonumber(L, -1);
|
|
||||||
} else {
|
|
||||||
printf("RenderSettings 'depth' field is missing or not a number.\n");
|
|
||||||
lua_pop(L, 1); // Pop the 'depth' field
|
|
||||||
return 0; // Error
|
|
||||||
}
|
|
||||||
lua_pop(L, 1); // Pop the 'depth' field
|
|
||||||
|
|
||||||
// Read spray field
|
|
||||||
lua_getfield(L, -1, "spray");
|
|
||||||
if (lua_isnumber(L, -1)) {
|
|
||||||
settings.spray = (int) lua_tonumber(L, -1);
|
|
||||||
} else {
|
|
||||||
printf("RenderSettings 'spray' field is missing or not a number.\n");
|
|
||||||
lua_pop(L, 1); // Pop the 'spray' field
|
|
||||||
return 0; // Error
|
|
||||||
}
|
|
||||||
lua_pop(L, 1); // Pop the 'spray' field
|
|
||||||
|
|
||||||
// Read depth field
|
|
||||||
lua_getfield(L, -1, "multisampling");
|
|
||||||
if (lua_isnumber(L, -1)) {
|
|
||||||
settings.multisampling = (int) lua_tonumber(L, -1);
|
|
||||||
} else {
|
|
||||||
printf("RenderSettings 'depth' field is missing or not a number.\n");
|
|
||||||
lua_pop(L, 1); // Pop the 'depth' field
|
|
||||||
return 0; // Error
|
|
||||||
}
|
|
||||||
lua_pop(L, 1); // Pop the 'depth' field
|
|
||||||
|
|
||||||
return 1; // Success
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to read a Lua table representing a light
|
|
||||||
int tp::Scene::readLight(lua_State* L, tp::PointLight* light) {
|
|
||||||
light->pos = getVec3(L, "pos");
|
|
||||||
|
|
||||||
lua_getfield(L, -1, "intensity"); // Get the "intensity" field from the light table
|
|
||||||
if (!lua_isnumber(L, -1)) {
|
|
||||||
printf("Light is missing the 'intensity' field or it's not a number.\n");
|
|
||||||
lua_pop(L, 1); // Pop the 'intensity' field
|
|
||||||
return 0; // Error
|
|
||||||
}
|
|
||||||
light->intensity = lua_tonumber(L, -1);
|
|
||||||
lua_pop(L, 1); // Pop the 'intensity' field
|
|
||||||
|
|
||||||
return 1; // Success
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tp::Scene::loadLuaFormat(const std::string& scenePath) {
|
|
||||||
lua_State* L = luaL_newstate();
|
|
||||||
luaL_openlibs(L);
|
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
fs::path fullPath(scenePath);
|
|
||||||
|
|
||||||
// Extract the filename
|
|
||||||
std::string fileName = fullPath.filename().string();
|
|
||||||
|
|
||||||
// Remove the filename from the path
|
|
||||||
fs::path directoryPath = fullPath.remove_filename();
|
|
||||||
|
|
||||||
if (luaL_dofile(L, scenePath.c_str()) != 0) {
|
|
||||||
lua_close(L);
|
|
||||||
printf("Cant open scene script.\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
lua_getglobal(L, "Meshes");
|
|
||||||
|
|
||||||
if (lua_isstring(L, -1)) {
|
|
||||||
std::string meshesPath = lua_tostring(L, -1);
|
|
||||||
|
|
||||||
directoryPath /= meshesPath;
|
|
||||||
|
|
||||||
if (!loadOBJFormat(directoryPath.string())) {
|
|
||||||
printf("No 'meshes' loaded - check ur .obj path and validate content of .obj .\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
printf("No 'meshes' path given.\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- camera
|
|
||||||
{
|
|
||||||
lua_getglobal(L, "Camera");
|
|
||||||
if (!lua_istable(L, -1)) {
|
|
||||||
printf("Camera is not a table.\n");
|
|
||||||
lua_close(L);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3F camPos = getVec3(L, "pos");
|
|
||||||
Vec3F camTarget = getVec3(L, "target");
|
|
||||||
Vec3F camUp = getVec3(L, "up");
|
|
||||||
Vec2F camSize = getVec2(L, "size");
|
|
||||||
|
|
||||||
mRenderSettings.size = camSize;
|
|
||||||
|
|
||||||
mCamera.lookAtPoint(camTarget, camPos, camUp);
|
|
||||||
mCamera.setFOV(3.14 / 4);
|
|
||||||
mCamera.setFar(100);
|
|
||||||
mCamera.setRatio((tp::halnf) camSize.y / (tp::halnf) camSize.x);
|
|
||||||
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------- LIGHTS
|
|
||||||
{
|
|
||||||
lua_getglobal(L, "Lights");
|
|
||||||
if (!lua_istable(L, -1)) {
|
|
||||||
printf("Lights is not a table.\n");
|
|
||||||
lua_close(L);
|
|
||||||
return false; // Error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read and process each light in the "Lights" table
|
|
||||||
int numLights = lua_rawlen(L, -1); // Get the number of lights in the table
|
|
||||||
for (int i = 1; i <= numLights; i++) {
|
|
||||||
lua_rawgeti(L, -1, i); // Get the i-th element (light) from the table
|
|
||||||
if (lua_istable(L, -1)) {
|
|
||||||
tp::PointLight light;
|
|
||||||
if (!readLight(L, &light)) {
|
|
||||||
printf("Cant read lights data\n");
|
|
||||||
lua_close(L);
|
|
||||||
return false; // Error
|
|
||||||
}
|
|
||||||
mLights.append(light);
|
|
||||||
}
|
|
||||||
lua_pop(L, 1); // Pop the i-th light table
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------- settings --------------
|
|
||||||
if (!readRenderSettings(L, mRenderSettings)) {
|
|
||||||
printf("Cant Read Render Settings");
|
|
||||||
lua_close(L);
|
|
||||||
return false; // Error
|
|
||||||
}
|
|
||||||
|
|
||||||
lua_close(L);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
|
|
||||||
#include "Scene.hpp"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "lauxlib.h"
|
|
||||||
#include "lualib.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "obj/OBJ_Loader.h"
|
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
|
|
||||||
bool tp::Scene::loadOBJFormat(const std::string& objetsPath) {
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
objl::Loader Loader;
|
|
||||||
|
|
||||||
if (!Loader.LoadFile(objetsPath)) {
|
|
||||||
std::cout << "Failed to Load File. May have failed to find it or it was not an .obj file.\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& curMesh : Loader.LoadedMeshes) {
|
|
||||||
mObjects.append(Object());
|
|
||||||
|
|
||||||
auto object = &mObjects.last();
|
|
||||||
|
|
||||||
for (auto& vertex : curMesh.Vertices) {
|
|
||||||
// printf("{ %f, %f, %f }, \n", vertex.Position.X, vertex.Position.Y, vertex.Position.Z);
|
|
||||||
object->mTopology.Points.append(Vec3F{ vertex.Position.X, vertex.Position.Y, vertex.Position.Z });
|
|
||||||
object->mTopology.Normals.append(Vec3F{ vertex.Normal.X, vertex.Normal.Y, vertex.Normal.Z });
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < curMesh.Indices.size(); j += 3) {
|
|
||||||
auto idx1 = (uhalni) curMesh.Indices[j];
|
|
||||||
auto idx2 = (uhalni) curMesh.Indices[j + 1];
|
|
||||||
auto idx3 = (uhalni) curMesh.Indices[j + 2];
|
|
||||||
// printf("{ %i, %i, %i },\n", idx1, idx2, idx3);
|
|
||||||
object->mTopology.Indexes.append(Vec3<uhalni>{ idx1, idx2, idx3 });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (object->mTopology.Normals.size() != object->mTopology.Points.size()) {
|
|
||||||
printf("Logic error loading normals\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
object->mCache.Source = &object->mTopology;
|
|
||||||
object->mCache.updateCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
return mObjects.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
const tp::RayCastData& tp::Scene::castRay(const Ray& ray, alnf farVal) {
|
|
||||||
auto& out = mRayCastData;
|
|
||||||
|
|
||||||
out.hit = false;
|
|
||||||
out.obj = nullptr;
|
|
||||||
|
|
||||||
farVal *= farVal;
|
|
||||||
|
|
||||||
for (auto obj : mObjects) {
|
|
||||||
for (auto trig : obj->mCache.TrigCaches) {
|
|
||||||
if (trig->castRay(ray)) {
|
|
||||||
|
|
||||||
auto dist = (TrigCache::getHitPos() - ray.pos).length2();
|
|
||||||
|
|
||||||
if (farVal > dist && dist > EPSILON) {
|
|
||||||
out.trig = &trig.data();
|
|
||||||
out.hitPos = TrigCache::getHitPos();
|
|
||||||
out.obj = &obj.data();
|
|
||||||
out.hit = true;
|
|
||||||
|
|
||||||
farVal = dist;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mRayCastData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tp::Scene::updateCache() {
|
|
||||||
for (auto obj : mObjects) {
|
|
||||||
obj->mCache.updateCache();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
#include "Scene.hpp"
|
|
||||||
|
|
||||||
bool tp::Scene::load(const std::string& scenePath) {
|
|
||||||
try {
|
|
||||||
auto res = loadLuaFormat(scenePath);
|
|
||||||
if (!res) throw IOError("Failed loading lua script");
|
|
||||||
} catch (const IOError& err) {
|
|
||||||
printf("Failed loading scene : %s\n", err.description.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Topology.hpp"
|
|
||||||
#include "Buffer2D.hpp"
|
|
||||||
#include "Camera.hpp"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
struct lua_State;
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
struct RenderSettings {
|
|
||||||
uhalni depth = 2;
|
|
||||||
uhalni spray = 1;
|
|
||||||
ualni multisampling = 1;
|
|
||||||
Vec2<ualni> size;
|
|
||||||
};
|
|
||||||
|
|
||||||
class GPUBuffers {
|
|
||||||
public:
|
|
||||||
GPUBuffers() = default;
|
|
||||||
virtual ~GPUBuffers() = default;
|
|
||||||
|
|
||||||
virtual void drawCall() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Object {
|
|
||||||
public:
|
|
||||||
Object() = default;
|
|
||||||
|
|
||||||
~Object() {
|
|
||||||
delete mGUPBuffers;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
Topology mTopology;
|
|
||||||
TopologyCache mCache;
|
|
||||||
GPUBuffers* mGUPBuffers = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PointLight {
|
|
||||||
Vec3F pos;
|
|
||||||
halnf fallOut = 1.f;
|
|
||||||
halnf intensity = 1.f;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RayCastData {
|
|
||||||
Object* obj = nullptr;
|
|
||||||
TrigCache* trig = nullptr;
|
|
||||||
Vec3F hitPos = { 0, 0, 0 };
|
|
||||||
bool hit = false;
|
|
||||||
bool inv = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Scene {
|
|
||||||
struct IOError : public std::exception {
|
|
||||||
explicit IOError(std::string in) :
|
|
||||||
description(std::move(in)) {}
|
|
||||||
|
|
||||||
std::string description;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
Scene() = default;
|
|
||||||
|
|
||||||
bool load(const std::string& scenePath);
|
|
||||||
|
|
||||||
bool loadLuaFormat(const std::string& scenePath);
|
|
||||||
bool loadOBJFormat(const std::string& objectsPath);
|
|
||||||
|
|
||||||
const RayCastData& castRay(const Ray& ray, alnf farVal);
|
|
||||||
|
|
||||||
void updateCache();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Vec3F getVec3(lua_State* state, const char* name);
|
|
||||||
Vec2F getVec2(lua_State* state, const char* name);
|
|
||||||
|
|
||||||
int readLight(lua_State* L, tp::PointLight* light);
|
|
||||||
|
|
||||||
public:
|
|
||||||
Buffer<Object> mObjects;
|
|
||||||
Buffer<PointLight> mLights;
|
|
||||||
Camera mCamera;
|
|
||||||
|
|
||||||
RenderSettings mRenderSettings;
|
|
||||||
|
|
||||||
RayCastData mRayCastData;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
# Blender MTL File: 'scene.blend'
|
|
||||||
# Material Count: 2
|
|
||||||
|
|
||||||
newmtl Material
|
|
||||||
Ns 323.999994
|
|
||||||
Ka 1.000000 1.000000 1.000000
|
|
||||||
Kd 0.800000 0.800000 0.800000
|
|
||||||
Ks 0.500000 0.500000 0.500000
|
|
||||||
Ke 0.000000 0.000000 0.000000
|
|
||||||
Ni 1.450000
|
|
||||||
d 1.000000
|
|
||||||
illum 2
|
|
||||||
|
|
||||||
newmtl None
|
|
||||||
Ns 500
|
|
||||||
Ka 0.8 0.8 0.8
|
|
||||||
Kd 0.8 0.8 0.8
|
|
||||||
Ks 0.8 0.8 0.8
|
|
||||||
d 1
|
|
||||||
illum 2
|
|
||||||
|
|
@ -1,112 +0,0 @@
|
||||||
# Blender v3.0.1 OBJ File: 'scene.blend'
|
|
||||||
# www.blender.org
|
|
||||||
mtllib meshes.mtl
|
|
||||||
o Cube
|
|
||||||
v -1.039076 1.039076 1.792917
|
|
||||||
v -1.039076 1.039076 -1.285234
|
|
||||||
v 1.039076 1.039076 1.792917
|
|
||||||
v 1.039076 1.039076 -1.285234
|
|
||||||
v -1.039076 -1.039076 1.792917
|
|
||||||
v -1.039076 -1.039076 -1.285234
|
|
||||||
v 1.039076 -1.039076 1.792917
|
|
||||||
v 1.039076 -1.039076 -1.285234
|
|
||||||
vt 0.625000 0.500000
|
|
||||||
vt 0.625000 0.750000
|
|
||||||
vt 0.875000 0.750000
|
|
||||||
vt 0.875000 0.500000
|
|
||||||
vt 0.375000 0.750000
|
|
||||||
vt 0.375000 1.000000
|
|
||||||
vt 0.625000 1.000000
|
|
||||||
vt 0.375000 0.000000
|
|
||||||
vt 0.375000 0.250000
|
|
||||||
vt 0.625000 0.250000
|
|
||||||
vt 0.625000 0.000000
|
|
||||||
vt 0.125000 0.500000
|
|
||||||
vt 0.125000 0.750000
|
|
||||||
vt 0.375000 0.500000
|
|
||||||
vn 0.0000 0.0000 -1.0000
|
|
||||||
vn -1.0000 0.0000 0.0000
|
|
||||||
vn 0.0000 1.0000 0.0000
|
|
||||||
vn 0.0000 0.0000 1.0000
|
|
||||||
vn 1.0000 0.0000 0.0000
|
|
||||||
usemtl Material
|
|
||||||
s off
|
|
||||||
f 1/1/1 3/2/1 7/3/1 5/4/1
|
|
||||||
f 4/5/2 8/6/2 7/7/2 3/2/2
|
|
||||||
f 8/8/3 6/9/3 5/10/3 7/11/3
|
|
||||||
f 6/12/4 8/13/4 4/5/4 2/14/4
|
|
||||||
f 6/9/5 2/14/5 1/1/5 5/10/5
|
|
||||||
o Cube.001
|
|
||||||
v 0.411013 -0.208216 -1.264212
|
|
||||||
v 0.411013 -0.208216 -0.612621
|
|
||||||
v -0.208216 -0.411013 -1.264212
|
|
||||||
v -0.208216 -0.411013 -0.612621
|
|
||||||
v 0.208216 0.411013 -1.264212
|
|
||||||
v 0.208216 0.411013 -0.612621
|
|
||||||
v -0.411013 0.208216 -1.264212
|
|
||||||
v -0.411013 0.208216 -0.612621
|
|
||||||
vt 0.375000 0.000000
|
|
||||||
vt 0.625000 0.000000
|
|
||||||
vt 0.625000 0.250000
|
|
||||||
vt 0.375000 0.250000
|
|
||||||
vt 0.625000 0.500000
|
|
||||||
vt 0.375000 0.500000
|
|
||||||
vt 0.625000 0.750000
|
|
||||||
vt 0.375000 0.750000
|
|
||||||
vt 0.625000 1.000000
|
|
||||||
vt 0.375000 1.000000
|
|
||||||
vt 0.125000 0.500000
|
|
||||||
vt 0.125000 0.750000
|
|
||||||
vt 0.875000 0.500000
|
|
||||||
vt 0.875000 0.750000
|
|
||||||
vn 0.3112 -0.9503 0.0000
|
|
||||||
vn -0.9503 -0.3112 0.0000
|
|
||||||
vn -0.3112 0.9503 0.0000
|
|
||||||
vn 0.9503 0.3112 0.0000
|
|
||||||
vn 0.0000 0.0000 -1.0000
|
|
||||||
vn 0.0000 0.0000 1.0000
|
|
||||||
usemtl None
|
|
||||||
s off
|
|
||||||
f 9/15/6 10/16/6 12/17/6 11/18/6
|
|
||||||
f 11/18/7 12/17/7 16/19/7 15/20/7
|
|
||||||
f 15/20/8 16/19/8 14/21/8 13/22/8
|
|
||||||
f 13/22/9 14/21/9 10/23/9 9/24/9
|
|
||||||
f 11/25/10 15/20/10 13/22/10 9/26/10
|
|
||||||
f 16/19/11 12/27/11 10/28/11 14/21/11
|
|
||||||
o Cube.002
|
|
||||||
v -0.351718 -0.467100 -0.602050
|
|
||||||
v -0.351718 -0.467100 0.049542
|
|
||||||
v -0.800825 0.004996 -0.602050
|
|
||||||
v -0.800825 0.004996 0.049542
|
|
||||||
v 0.120377 -0.017993 -0.602050
|
|
||||||
v 0.120377 -0.017993 0.049542
|
|
||||||
v -0.328730 0.454103 -0.602050
|
|
||||||
v -0.328730 0.454103 0.049542
|
|
||||||
vt 0.375000 0.000000
|
|
||||||
vt 0.625000 0.000000
|
|
||||||
vt 0.625000 0.250000
|
|
||||||
vt 0.375000 0.250000
|
|
||||||
vt 0.625000 0.500000
|
|
||||||
vt 0.375000 0.500000
|
|
||||||
vt 0.625000 0.750000
|
|
||||||
vt 0.375000 0.750000
|
|
||||||
vt 0.625000 1.000000
|
|
||||||
vt 0.375000 1.000000
|
|
||||||
vt 0.125000 0.500000
|
|
||||||
vt 0.125000 0.750000
|
|
||||||
vt 0.875000 0.500000
|
|
||||||
vt 0.875000 0.750000
|
|
||||||
vn -0.7245 -0.6892 0.0000
|
|
||||||
vn -0.6892 0.7245 0.0000
|
|
||||||
vn 0.7245 0.6892 0.0000
|
|
||||||
vn 0.6892 -0.7245 0.0000
|
|
||||||
vn 0.0000 0.0000 -1.0000
|
|
||||||
vn 0.0000 0.0000 1.0000
|
|
||||||
usemtl None
|
|
||||||
s off
|
|
||||||
f 17/29/12 18/30/12 20/31/12 19/32/12
|
|
||||||
f 19/32/13 20/31/13 24/33/13 23/34/13
|
|
||||||
f 23/34/14 24/33/14 22/35/14 21/36/14
|
|
||||||
f 21/36/15 22/35/15 18/37/15 17/38/15
|
|
||||||
f 19/39/16 23/34/16 21/36/16 17/40/16
|
|
||||||
f 24/33/17 20/41/17 18/42/17 22/35/17
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
|
|
||||||
Meshes = "meshes.obj"
|
|
||||||
|
|
||||||
Camera = {
|
|
||||||
pos = { 0, 5, 0 },
|
|
||||||
target = { 0, 0, 0 },
|
|
||||||
up = { 0, 0, 1 },
|
|
||||||
size = { 600, 800 },
|
|
||||||
}
|
|
||||||
|
|
||||||
Lights = {
|
|
||||||
{
|
|
||||||
pos = { -0.5, 3.5, 1 },
|
|
||||||
intensity = 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pos = { 0, 0, 1 },
|
|
||||||
intensity = 0.5
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderSettings = {
|
|
||||||
depth = 1,
|
|
||||||
spray = 1,
|
|
||||||
multisampling = 1,
|
|
||||||
}
|
|
||||||
20
Allocators/CMakeLists.txt
Normal file
20
Allocators/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.2)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
|
|
||||||
|
project(Allocator)
|
||||||
|
|
||||||
|
### ---------------------- Static Library --------------------- ###
|
||||||
|
file(GLOB SOURCES "./private/*.cpp")
|
||||||
|
add_library(${PROJECT_NAME} STATIC ${SOURCES})
|
||||||
|
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PUBLIC Utils)
|
||||||
|
|
||||||
|
### -------------------------- Tests -------------------------- ###
|
||||||
|
enable_testing()
|
||||||
|
add_executable(${PROJECT_NAME}Tests ${CMAKE_CURRENT_SOURCE_DIR}/tests/Tests.cpp)
|
||||||
|
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME})
|
||||||
|
add_test(${PROJECT_NAME} ${PROJECT_NAME}Tests)
|
||||||
|
|
||||||
|
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/lib)
|
||||||
42
Allocators/README.md
Normal file
42
Allocators/README.md
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
# Profiling
|
||||||
|
|
||||||
|
## Memory Leaks
|
||||||
|
|
||||||
|
Example program with memory leaks:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
#include "allocators.h"
|
||||||
|
|
||||||
|
void test_call22() { new int; }
|
||||||
|
void test_call21() { new float; }
|
||||||
|
|
||||||
|
void test_call11() {
|
||||||
|
test_call21();
|
||||||
|
test_call22();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(char argc, char* argv[]) {
|
||||||
|
tp::ModuleManifest* ModuleDependencies[] = { &tp::gModuleAllocator, NULL };
|
||||||
|
tp::ModuleManifest TestModule("Test", NULL, NULL, ModuleDependencies);
|
||||||
|
TestModule.initialize();
|
||||||
|
|
||||||
|
test_call11();
|
||||||
|
|
||||||
|
TestModule.deinitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
If memory leaks were detected it will be loged in the output console.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Also debug.memleaks binary will be generated in the working directory that can be viewved with MemLeaks Viewver.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## Memory Usage Analisys
|
||||||
|
Currently outdated
|
||||||
|
|
||||||
|
## Benchmarks
|
||||||
|
Currently outdated
|
||||||
21
Allocators/private/Allocators.cpp
Normal file
21
Allocators/private/Allocators.cpp
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
#include "Allocators.hpp"
|
||||||
|
|
||||||
|
static tp::ModuleManifest* sModuleDependencies[] = { &tp::gModuleBase, NULL };
|
||||||
|
tp::ModuleManifest tp::gModuleAllocator = ModuleManifest("Allocators", NULL, NULL, sModuleDependencies);
|
||||||
|
|
||||||
|
|
||||||
|
void* operator new(size_t aSize) { return tp::HeapAllocGlobal::allocate(aSize); }
|
||||||
|
void* operator new[](size_t aSize) { return tp::HeapAllocGlobal::allocate(aSize); }
|
||||||
|
void operator delete(void* aPtr) { tp::HeapAllocGlobal::deallocate(aPtr); }
|
||||||
|
void operator delete[](void* aPtr) { tp::HeapAllocGlobal::deallocate(aPtr); }
|
||||||
|
|
||||||
|
void* operator new(size_t aSize, tp::HeapAlloc& aAlloc) { return aAlloc.allocate(aSize); }
|
||||||
|
void* operator new[](size_t aSize, tp::HeapAlloc& aAlloc) { return aAlloc.allocate(aSize); }
|
||||||
|
void operator delete(void* aPtr, tp::HeapAlloc& aAlloc) { aAlloc.deallocate(aPtr); }
|
||||||
|
void operator delete[](void* aPtr, tp::HeapAlloc& aAlloc) { aAlloc.deallocate(aPtr); }
|
||||||
|
|
||||||
|
void* operator new(size_t aSize, tp::HeapAllocGlobal& aAlloc) { return aAlloc.allocate(aSize); }
|
||||||
|
void* operator new[](size_t aSize, tp::HeapAllocGlobal& aAlloc) { return aAlloc.allocate(aSize); }
|
||||||
|
void operator delete(void* aPtr, tp::HeapAllocGlobal& aAlloc) { aAlloc.deallocate(aPtr); }
|
||||||
|
void operator delete[](void* aPtr, tp::HeapAllocGlobal& aAlloc) { aAlloc.deallocate(aPtr); }
|
||||||
114
Allocators/private/ChunkAllocator.cpp
Normal file
114
Allocators/private/ChunkAllocator.cpp
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Implementation uses embedded one-directional linked list to track free blocks.
|
||||||
|
* The embedded part ensures that there is no memory overhead on block specifically.
|
||||||
|
* Linked list is initialized iteratively on each allocation if it has not been already.
|
||||||
|
|
||||||
|
* Allocating:
|
||||||
|
* 1) updating list entry to stored in the entry itself next free pointer
|
||||||
|
* 2) returning entry before (1).
|
||||||
|
*
|
||||||
|
* Deallocating:
|
||||||
|
* 1) assigning list entry value to the deleted block
|
||||||
|
* 2) updating list entry to that block.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ChunkAllocator.hpp"
|
||||||
|
#include "PrivateConfig.hpp"
|
||||||
|
|
||||||
|
#include "HeapAllocatorGlobal.hpp"
|
||||||
|
|
||||||
|
using namespace tp;
|
||||||
|
|
||||||
|
enum : ualni {
|
||||||
|
ALIGNED_SIZE = ENV_ALNI_SIZE_B,
|
||||||
|
WRAP_SIZE_ALN = MEM_WRAP_SIZE,
|
||||||
|
WRAP_SIZE = WRAP_SIZE_ALN * ALIGNED_SIZE,
|
||||||
|
WRAP_VAL = MEM_WRAP_FILL_VAL,
|
||||||
|
CLEAR_ALLOC_VAL = MEM_CLEAR_ON_ALLOC_VAL,
|
||||||
|
CLEAR_DEALLOC_VAL = MEM_CLEAR_ON_DEALLOC_VAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
ChunkAlloc::ChunkAlloc(ualni aBlockSize, void* aMemory, ualni aMemSize) {
|
||||||
|
auto const temp = aBlockSize / ALIGNED_SIZE;
|
||||||
|
mBSize = ((aBlockSize % ALIGNED_SIZE) ? temp + 1 : temp) + WRAP_SIZE_ALN * 2;
|
||||||
|
mBuff = (ualni*) aMemory;
|
||||||
|
mNBlocks = (aMemSize / ALIGNED_SIZE) / mBSize;
|
||||||
|
mNFreeBlocks = mNBlocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChunkAlloc::ChunkAlloc(ualni aBlockSize, ualni aNBlocks) {
|
||||||
|
auto const temp = aBlockSize / ALIGNED_SIZE;
|
||||||
|
mBSize = ((aBlockSize % ALIGNED_SIZE) ? temp + 1 : temp) + WRAP_SIZE_ALN * 2;
|
||||||
|
mNBlocks = aNBlocks;
|
||||||
|
mNFreeBlocks = mNBlocks;
|
||||||
|
mBuff = (ualni*)HeapAllocGlobal::allocate(mNBlocks * mBSize * ALIGNED_SIZE);
|
||||||
|
mOwnBuff = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ChunkAlloc::allocate() {
|
||||||
|
ASSERT(mNFreeBlocks && "Out Of Memory");
|
||||||
|
|
||||||
|
// 1) PreInitialize blocks
|
||||||
|
if (mNInitBlocks < mNBlocks) {
|
||||||
|
*(mBuff + mNInitBlocks * mBSize) = (ualni)(mBuff + (mNInitBlocks++) * mBSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Find free block and update next free block
|
||||||
|
auto data = mNextBlock;
|
||||||
|
mNextBlock = (ualni*)(*data);
|
||||||
|
mNFreeBlocks--;
|
||||||
|
|
||||||
|
#ifdef MEM_DEBUG
|
||||||
|
// 3) Fill Wrap and offset data
|
||||||
|
auto wrap_top = data;
|
||||||
|
data += WRAP_SIZE_ALN;
|
||||||
|
auto wrap_bottom = data + mBSize;
|
||||||
|
|
||||||
|
memsetv(wrap_top, WRAP_SIZE, WRAP_VAL);
|
||||||
|
memsetv(wrap_bottom, WRAP_SIZE, WRAP_VAL);
|
||||||
|
|
||||||
|
// 4) Clear data
|
||||||
|
#ifdef MEM_CLEAR_ON_ALLOC
|
||||||
|
memsetv(data, mBSize * ALIGNED_SIZE, CLEAR_ALLOC_VAL);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChunkAlloc::deallocate(void* aPtr) {
|
||||||
|
auto block = (ualni*)aPtr;
|
||||||
|
|
||||||
|
#ifdef MEM_DEBUG
|
||||||
|
// 3) Check Wrap and offset data
|
||||||
|
auto wrap_bottom = block + mBSize;
|
||||||
|
auto wrap_top = block - WRAP_SIZE_ALN;
|
||||||
|
block = wrap_top;
|
||||||
|
|
||||||
|
// 3) Check the wrap
|
||||||
|
RelAssert(memequalv(wrap_top, WRAP_SIZE, WRAP_VAL) && memequalv(wrap_bottom, WRAP_SIZE, WRAP_VAL) && "Allocated Block Wrap Corrupted!");
|
||||||
|
|
||||||
|
// 4) Clear data
|
||||||
|
#ifdef MEM_CLEAR_ON_ALLOC
|
||||||
|
memsetv(aPtr, mBSize * ALIGNED_SIZE, CLEAR_DEALLOC_VAL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
(*block) = (ualni)mNextBlock;
|
||||||
|
mNextBlock = block;
|
||||||
|
mNFreeBlocks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChunkAlloc::isFull() const { return !mNFreeBlocks; }
|
||||||
|
bool ChunkAlloc::isEmpty() const { return mNFreeBlocks == mNBlocks; }
|
||||||
|
|
||||||
|
ChunkAlloc::~ChunkAlloc() {
|
||||||
|
// TODO : check for leaks
|
||||||
|
if (mOwnBuff) {
|
||||||
|
HeapAllocGlobal::deallocate(mBuff);
|
||||||
|
}
|
||||||
|
}
|
||||||
78
Allocators/private/HeapAllocator.cpp
Normal file
78
Allocators/private/HeapAllocator.cpp
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
|
||||||
|
|
||||||
|
#include "HeapAllocator.hpp"
|
||||||
|
#include "HeapAllocatorGlobal.hpp"
|
||||||
|
|
||||||
|
#include "PrivateConfig.hpp"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
using namespace tp;
|
||||||
|
|
||||||
|
#if not defined(MEM_DEBUG)
|
||||||
|
|
||||||
|
// ----------------------- Release Implementation ---------------------------- //
|
||||||
|
void* HeapAlloc::allocate(ualni aBlockSize) { return malloc(aBlockSize); }
|
||||||
|
void HeapAlloc::deallocate(void* aPtr) { free(aPtr); }
|
||||||
|
HeapAlloc::~HeapAlloc() {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
namespace tp {
|
||||||
|
struct MemHeadLocal {
|
||||||
|
MemHeadLocal* mPrev;
|
||||||
|
MemHeadLocal* mNext;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
void* HeapAlloc::allocate(ualni aBlockSize) {
|
||||||
|
auto head = (MemHeadLocal*) HeapAllocGlobal::allocate(aBlockSize + sizeof(MemHeadLocal));
|
||||||
|
auto out = head + 1;
|
||||||
|
|
||||||
|
mNumAllocations++;
|
||||||
|
if (mEntry) {
|
||||||
|
head->mNext = mEntry->mNext;
|
||||||
|
head->mPrev = mEntry->mPrev;
|
||||||
|
if (mEntry->mNext) mEntry->mNext->mPrev = head;
|
||||||
|
if (mEntry->mPrev) mEntry->mPrev->mNext = head;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
head->mNext = nullptr;
|
||||||
|
head->mPrev = nullptr;
|
||||||
|
}
|
||||||
|
mEntry = head;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeapAlloc::deallocate(void* aPtr) {
|
||||||
|
auto head = ((MemHeadLocal*)(aPtr)) - 1;
|
||||||
|
|
||||||
|
mNumAllocations--;
|
||||||
|
if (mEntry->mNext) mEntry->mNext->mPrev = mEntry->mPrev;
|
||||||
|
if (mEntry->mPrev) mEntry->mPrev->mNext = mEntry->mNext;
|
||||||
|
if (head == mEntry) {
|
||||||
|
if (mEntry->mNext) {
|
||||||
|
mEntry = mEntry->mNext;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mEntry = mEntry->mPrev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapAllocGlobal::deallocate(head);
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapAlloc::~HeapAlloc() {
|
||||||
|
if (mNumAllocations) {
|
||||||
|
DEBUG_BREAK("Destruction of not freed Allocator");
|
||||||
|
|
||||||
|
#ifdef MEM_STACK_TRACE
|
||||||
|
// TODO : log leaks and free them up
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
149
Allocators/private/HeapAllocatorGlobal.cpp
Normal file
149
Allocators/private/HeapAllocatorGlobal.cpp
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
|
||||||
|
|
||||||
|
#include "HeapAllocatorGlobal.hpp"
|
||||||
|
#include "PrivateConfig.hpp"
|
||||||
|
|
||||||
|
#include "Debugging.hpp"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
using namespace tp;
|
||||||
|
|
||||||
|
#if not defined(MEM_DEBUG)
|
||||||
|
|
||||||
|
// ----------------------- Release Implementation ---------------------------- //
|
||||||
|
|
||||||
|
void* HeapAllocGlobal::allocate(ualni aBlockSize) { return malloc(aBlockSize); }
|
||||||
|
void HeapAllocGlobal::deallocate(void* aPtr) { free(aPtr); }
|
||||||
|
HeapAllocGlobal::~HeapAllocGlobal() = default;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
tp::MemHead* tp::HeapAllocGlobal::mEntry = nullptr;
|
||||||
|
tp::ualni tp::HeapAllocGlobal::mNumAllocations = 0;
|
||||||
|
|
||||||
|
// ----------------------- Debug Implementation ---------------------------- //
|
||||||
|
// |----------------|
|
||||||
|
// | MemHead |
|
||||||
|
// |----------------|
|
||||||
|
// | wrap top |
|
||||||
|
// |----------------| - Allocated Block Layout
|
||||||
|
// | data |
|
||||||
|
// |----------------|
|
||||||
|
// | wrap bottom |
|
||||||
|
// |----------------|
|
||||||
|
|
||||||
|
namespace tp {
|
||||||
|
struct MemHead {
|
||||||
|
MemHead* mPrev;
|
||||||
|
MemHead* mNext;
|
||||||
|
ualni mBlockSize;
|
||||||
|
#ifdef MEM_STACK_TRACE
|
||||||
|
CallStackSnapshots::StackShapshot mCallStack;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
enum : ualni {
|
||||||
|
ALIGNED_SIZE = ENV_ALNI_SIZE_B,
|
||||||
|
WRAP_SIZE = MEM_WRAP_SIZE * ALIGNED_SIZE,
|
||||||
|
WRAP_VAL = MEM_WRAP_FILL_VAL,
|
||||||
|
HEAD_SIZE = sizeof(MemHead),
|
||||||
|
CLEAR_ALLOC_VAL = MEM_CLEAR_ON_ALLOC_VAL,
|
||||||
|
CLEAR_DEALLOC_VAL = MEM_CLEAR_ON_DEALLOC_VAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
void* HeapAllocGlobal::allocate(ualni aBlockSize) {
|
||||||
|
|
||||||
|
static_assert(HEAD_SIZE % ALIGNED_SIZE == 0, "Heap Allocator Configuration Error");
|
||||||
|
|
||||||
|
if (aBlockSize % ALIGNED_SIZE) {
|
||||||
|
aBlockSize = (aBlockSize / ALIGNED_SIZE + 1) * ALIGNED_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1) Allocate the block
|
||||||
|
auto head = (MemHead*)malloc(aBlockSize + WRAP_SIZE * 2 + HEAD_SIZE);
|
||||||
|
auto wrap_top = (int1*)(head + 1);
|
||||||
|
auto data = wrap_top + WRAP_SIZE;
|
||||||
|
auto wrap_bottom = data + aBlockSize;
|
||||||
|
|
||||||
|
if (!head) { return nullptr; }
|
||||||
|
head->mBlockSize = aBlockSize;
|
||||||
|
|
||||||
|
// 2) Link with existing blocks
|
||||||
|
mNumAllocations++;
|
||||||
|
if (mEntry) {
|
||||||
|
head->mNext = mEntry->mNext;
|
||||||
|
head->mPrev = mEntry->mPrev;
|
||||||
|
if (mEntry->mNext) mEntry->mNext->mPrev = head;
|
||||||
|
if (mEntry->mPrev) mEntry->mPrev->mNext = head;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
head->mNext = nullptr;
|
||||||
|
head->mPrev = nullptr;
|
||||||
|
}
|
||||||
|
mEntry = head;
|
||||||
|
|
||||||
|
// 3) Wrap fill
|
||||||
|
memsetv(wrap_top, WRAP_SIZE, WRAP_VAL);
|
||||||
|
memsetv(wrap_bottom, WRAP_SIZE, WRAP_VAL);
|
||||||
|
|
||||||
|
// 4) Trace the stack
|
||||||
|
#ifdef MEM_STACK_TRACE
|
||||||
|
head->mCallStack = gCallStackSnapshots.capture();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 5) clear data
|
||||||
|
#ifdef MEM_CLEAR_ON_ALLOC
|
||||||
|
memsetv(data, aBlockSize, CLEAR_ALLOC_VAL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeapAllocGlobal::deallocate(void* aPtr) {
|
||||||
|
// 1) Restore the pointers
|
||||||
|
auto head = ((MemHead*)(aPtr)) - 1;
|
||||||
|
auto wrap_top = (int1*)(head + 1);
|
||||||
|
auto data = wrap_top + WRAP_SIZE;
|
||||||
|
auto wrap_bottom = data + head->mBlockSize;
|
||||||
|
|
||||||
|
// 2) Unlink with blocks
|
||||||
|
mNumAllocations--;
|
||||||
|
if (mEntry->mNext) mEntry->mNext->mPrev = mEntry->mPrev;
|
||||||
|
if (mEntry->mPrev) mEntry->mPrev->mNext = mEntry->mNext;
|
||||||
|
if (head == mEntry) {
|
||||||
|
if (mEntry->mNext) {
|
||||||
|
mEntry = mEntry->mNext;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mEntry = mEntry->mPrev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) Check the wrap
|
||||||
|
RelAssert(memequalv(wrap_top, WRAP_SIZE, WRAP_VAL) && memequalv(wrap_bottom, WRAP_SIZE, WRAP_VAL) && "Allocated Block Wrap Corrupted!");
|
||||||
|
|
||||||
|
// 4) clear data
|
||||||
|
#ifdef MEM_CLEAR_ON_ALLOC
|
||||||
|
memsetv(data, head->mBlockSize, CLEAR_DEALLOC_VAL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 5) free the block
|
||||||
|
free(aPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapAllocGlobal::~HeapAllocGlobal() {
|
||||||
|
// 1) Check for not deallocated memory
|
||||||
|
if (mNumAllocations) {
|
||||||
|
DEBUG_BREAK("Destruction of not freed Allocator");
|
||||||
|
|
||||||
|
#ifdef MEM_STACK_TRACE
|
||||||
|
// TODO: log leaks
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
1
Allocators/private/PickAllocator.cpp
Normal file
1
Allocators/private/PickAllocator.cpp
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
|
||||||
131
Allocators/private/PoolAllocator.cpp
Normal file
131
Allocators/private/PoolAllocator.cpp
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
Implementation:
|
||||||
|
* Adding chunk pointer to each chunk to form one-directional list that keeps track of free chunk
|
||||||
|
* Storing ordered pointers to chunks in order to find desired chunk from delete pointer on de-allocation in log time
|
||||||
|
*
|
||||||
|
* Allocations:
|
||||||
|
* 1) allocate with chunk stored in list entry
|
||||||
|
* 2) ...
|
||||||
|
*
|
||||||
|
* De-allocations:
|
||||||
|
* 1) binary-search with delete pointer to find desired chunk
|
||||||
|
* 2) ...
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Allocators.hpp"
|
||||||
|
#include "PrivateConfig.hpp"
|
||||||
|
|
||||||
|
void tp::PoolAlloc::Chunks::add(Chunk* aChunk) {
|
||||||
|
// ensure order
|
||||||
|
auto smaller_address = findUtil(mBuff, mBuff + mUsedLen, aChunk);
|
||||||
|
for (auto iter = mBuff + mUsedLen; iter != smaller_address; iter--) { *(iter + 1) = *iter; }
|
||||||
|
|
||||||
|
*(smaller_address + 1) = aChunk;
|
||||||
|
mUsedLen++;
|
||||||
|
|
||||||
|
// check for buff overflow
|
||||||
|
if (mUsedLen == mLen) {
|
||||||
|
auto prevBuff = mBuff;
|
||||||
|
mBuff = (Chunk**) HeapAllocGlobal::allocate(sizeof(Chunk*) * mLen * 2);
|
||||||
|
memcp(mBuff, prevBuff, sizeof(Chunk*) * mUsedLen);
|
||||||
|
mLen *= 2;
|
||||||
|
HeapAllocGlobal::deallocate(prevBuff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tp::PoolAlloc::Chunks::remove(Chunk* aChunk) {
|
||||||
|
// ensure order
|
||||||
|
auto del_address = findUtil(mBuff, mBuff + mUsedLen, aChunk);
|
||||||
|
for (auto iter = del_address; iter != mBuff + mUsedLen; iter++) { *iter = *(iter + 1); }
|
||||||
|
|
||||||
|
mUsedLen--;
|
||||||
|
|
||||||
|
// check for buff low usage
|
||||||
|
if ((halnf)mUsedLen / (halnf)mLen < 0.25f) {
|
||||||
|
auto prevBuff = mBuff;
|
||||||
|
mBuff = (Chunk**)HeapAllocGlobal::allocate(sizeof(Chunk*) * mLen / 2);
|
||||||
|
memcp(mBuff, prevBuff, sizeof(Chunk*) * mUsedLen);
|
||||||
|
mLen /= 2;
|
||||||
|
HeapAllocGlobal::deallocate(prevBuff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tp::PoolAlloc::Chunk* tp::PoolAlloc::Chunks::find(void* aPtr) {
|
||||||
|
return *findUtil(mBuff, mBuff + mUsedLen, aPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
tp::PoolAlloc::Chunk* tp::PoolAlloc::Chunks::findNotFull() {
|
||||||
|
for (ualni idx = 0; idx < mUsedLen; idx++) {
|
||||||
|
if (!mBuff[idx]->isFull()) {
|
||||||
|
return mBuff[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
tp::PoolAlloc::Chunk** tp::PoolAlloc::Chunks::findUtil(Chunk** aLeft, Chunk** aRight, void* aPtr) {
|
||||||
|
auto range = ualni(aRight - aLeft);
|
||||||
|
if (range == 1) { return aLeft; }
|
||||||
|
auto middle = aLeft + range / 2;
|
||||||
|
return (aPtr > *middle) ? findUtil(middle, aRight, aPtr) : findUtil(aLeft, middle, aPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tp::PoolAlloc::PoolAlloc(ualni aBlockSize, ualni aChunkSize) : mBlockSize(aBlockSize), mChunkSize(aChunkSize) {}
|
||||||
|
|
||||||
|
void* tp::PoolAlloc::allocate() {
|
||||||
|
|
||||||
|
if (!mFreeChunk || mFreeChunk->isFull()) {
|
||||||
|
auto new_free_chunk = mChunks.findNotFull();
|
||||||
|
|
||||||
|
if (!new_free_chunk) {
|
||||||
|
|
||||||
|
new_free_chunk = new ((Chunk*)HeapAllocGlobal::allocate(sizeof(Chunk))) Chunk(mBlockSize, mChunkSize);
|
||||||
|
ASSERT(new_free_chunk);
|
||||||
|
mChunks.add(new_free_chunk);
|
||||||
|
|
||||||
|
if (mFreeChunk) {
|
||||||
|
new_free_chunk->mNext = mFreeChunk->mNext;
|
||||||
|
new_free_chunk->mPrev = mFreeChunk->mPrev;
|
||||||
|
if (mFreeChunk->mNext) mFreeChunk->mNext->mPrev = new_free_chunk;
|
||||||
|
if (mFreeChunk->mPrev) mFreeChunk->mPrev->mNext = new_free_chunk;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
new_free_chunk->mNext = nullptr;
|
||||||
|
new_free_chunk->mPrev = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
mFreeChunk = new_free_chunk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mFreeChunk->allocate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tp::PoolAlloc::deallocate(void* aPtr) {
|
||||||
|
auto chunk = mChunks.find(aPtr);
|
||||||
|
chunk->deallocate(aPtr);
|
||||||
|
|
||||||
|
if (mFreeChunk->isEmpty()) {
|
||||||
|
|
||||||
|
Chunk* new_chunk = nullptr;
|
||||||
|
for (ualni idx = 0; idx < mChunks.mUsedLen; idx++) {
|
||||||
|
if (!mChunks.mBuff[idx]->isFull() && new_chunk != mFreeChunk) {
|
||||||
|
new_chunk = mChunks.mBuff[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_chunk) {
|
||||||
|
if (mFreeChunk->mNext) mFreeChunk->mNext->mPrev = mFreeChunk->mPrev;
|
||||||
|
if (mFreeChunk->mPrev) mFreeChunk->mPrev->mNext = mFreeChunk->mNext;
|
||||||
|
mChunks.remove(mFreeChunk);
|
||||||
|
HeapAllocGlobal::deallocate(mFreeChunk);
|
||||||
|
mFreeChunk = new_chunk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tp::PoolAlloc::~PoolAlloc() = default;
|
||||||
10
Allocators/private/PrivateConfig.hpp
Normal file
10
Allocators/private/PrivateConfig.hpp
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define MEM_WRAP_SIZE 8 // Wrapping Size in aligned units
|
||||||
|
#define MEM_WRAP_FILL_VAL 0xBB // Wrapping Fill Value
|
||||||
|
#define MEM_CLEAR_ON_ALLOC // Clear data on allocation
|
||||||
|
#define MEM_CLEAR_ON_DEALLOC // Clear data on free
|
||||||
|
#define MEM_CLEAR_ON_DEALLOC_VAL 0xAA // Clear data on free
|
||||||
|
#define MEM_CLEAR_ON_ALLOC_VAL 0xCC // Clear data on free
|
||||||
|
#define MEM_STACK_TRACE // Save stack on allocation call
|
||||||
|
#define MEM_STACK_TRACE_MAX_DEPTH 32 // Call stack max depth
|
||||||
29
Allocators/public/Allocators.hpp
Normal file
29
Allocators/public/Allocators.hpp
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Module.hpp"
|
||||||
|
|
||||||
|
#include "HeapAllocatorGlobal.hpp"
|
||||||
|
#include "HeapAllocator.hpp"
|
||||||
|
#include "ChunkAllocator.hpp"
|
||||||
|
#include "PoolAllocator.hpp"
|
||||||
|
|
||||||
|
namespace tp {
|
||||||
|
extern ModuleManifest gModuleAllocator;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void* operator new(std::size_t aSize, void* aWhere) noexcept { return aWhere; }
|
||||||
|
|
||||||
|
void* operator new(std::size_t aSize);
|
||||||
|
void* operator new[](std::size_t aSize);
|
||||||
|
void operator delete(void* aPtr);
|
||||||
|
void operator delete[](void* aPtr);
|
||||||
|
|
||||||
|
void* operator new(std::size_t aSize, tp::HeapAlloc& aAlloc);
|
||||||
|
void* operator new[](std::size_t aSize, tp::HeapAlloc& aAlloc);
|
||||||
|
void operator delete(void* aPtr, tp::HeapAlloc& aAlloc);
|
||||||
|
void operator delete[](void* aPtr, tp::HeapAlloc& aAlloc);
|
||||||
|
|
||||||
|
void* operator new(std::size_t aSize, tp::HeapAllocGlobal& aAlloc);
|
||||||
|
void* operator new[](std::size_t aSize, tp::HeapAllocGlobal& aAlloc);
|
||||||
|
void operator delete(void* aPtr, tp::HeapAllocGlobal& aAlloc);
|
||||||
|
void operator delete[](void* aPtr, tp::HeapAllocGlobal& aAlloc);
|
||||||
32
Allocators/public/ChunkAllocator.hpp
Normal file
32
Allocators/public/ChunkAllocator.hpp
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Environment.hpp"
|
||||||
|
|
||||||
|
namespace tp {
|
||||||
|
|
||||||
|
// Chunk Allocator
|
||||||
|
// Constant time allocations and de-allocations in any order.
|
||||||
|
// Memory blocks are fixed in size and number of blocks can not exceed given parameter.
|
||||||
|
struct ChunkAlloc {
|
||||||
|
|
||||||
|
ChunkAlloc(ualni aBlockSize, void* aMemory, ualni aMemSize);
|
||||||
|
ChunkAlloc(ualni aBlockSize, ualni aNBlocks);
|
||||||
|
|
||||||
|
void* allocate();
|
||||||
|
void deallocate(void* aPtr);
|
||||||
|
[[nodiscard]] bool isFull() const;
|
||||||
|
[[nodiscard]] bool isEmpty() const;
|
||||||
|
|
||||||
|
~ChunkAlloc();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ualni mBSize; // Size of data in aligned units
|
||||||
|
ualni mNBlocks;
|
||||||
|
|
||||||
|
ualni* mBuff = nullptr;
|
||||||
|
ualni* mNextBlock = nullptr;
|
||||||
|
ualni mNFreeBlocks;
|
||||||
|
ualni mNInitBlocks = 0;
|
||||||
|
bool mOwnBuff = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
18
Allocators/public/HeapAllocator.hpp
Normal file
18
Allocators/public/HeapAllocator.hpp
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Environment.hpp"
|
||||||
|
|
||||||
|
namespace tp {
|
||||||
|
|
||||||
|
struct HeapAlloc {
|
||||||
|
|
||||||
|
#ifdef MEM_DEBUG
|
||||||
|
ualni mNumAllocations = 0;
|
||||||
|
struct MemHeadLocal* mEntry = nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void* allocate(ualni aBlockSize);
|
||||||
|
void deallocate(void* aPtr);
|
||||||
|
~HeapAlloc();
|
||||||
|
};
|
||||||
|
};
|
||||||
18
Allocators/public/HeapAllocatorGlobal.hpp
Normal file
18
Allocators/public/HeapAllocatorGlobal.hpp
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Module.hpp"
|
||||||
|
|
||||||
|
namespace tp {
|
||||||
|
|
||||||
|
struct HeapAllocGlobal {
|
||||||
|
|
||||||
|
#ifdef MEM_DEBUG
|
||||||
|
static ualni mNumAllocations;
|
||||||
|
static struct MemHead* mEntry;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void* allocate(ualni aBlockSize);
|
||||||
|
static void deallocate(void* aPtr);
|
||||||
|
~HeapAllocGlobal();
|
||||||
|
};
|
||||||
|
};
|
||||||
13
Allocators/public/PickAllocator.hpp
Normal file
13
Allocators/public/PickAllocator.hpp
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "HeapAllocatorGlobal.hpp"
|
||||||
|
|
||||||
|
namespace tp {
|
||||||
|
|
||||||
|
struct PickAlloc {
|
||||||
|
PickAlloc();
|
||||||
|
void* allocate(ualni aBlockSize);
|
||||||
|
void deallocate(void* aPtr);
|
||||||
|
~PickAlloc();
|
||||||
|
};
|
||||||
|
};
|
||||||
42
Allocators/public/PoolAllocator.hpp
Normal file
42
Allocators/public/PoolAllocator.hpp
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ChunkAllocator.hpp"
|
||||||
|
|
||||||
|
namespace tp {
|
||||||
|
|
||||||
|
// Pool Allocator
|
||||||
|
// Overcomes chunk allocator fixed number of max allocations
|
||||||
|
struct PoolAlloc {
|
||||||
|
|
||||||
|
PoolAlloc(ualni aBlockSize, ualni aChunkSize);
|
||||||
|
void* allocate();
|
||||||
|
void deallocate(void* aPtr);
|
||||||
|
~PoolAlloc();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct Chunk : public ChunkAlloc {
|
||||||
|
Chunk(ualni aBlockSize, ualni aChunlSize) : ChunkAlloc(aBlockSize, aChunlSize) {}
|
||||||
|
Chunk* mNext = NULL;
|
||||||
|
Chunk* mPrev = NULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Chunks {
|
||||||
|
void add(Chunk*);
|
||||||
|
void remove(Chunk*);
|
||||||
|
Chunk* find(void* aPtr);
|
||||||
|
Chunk* findNotFull();
|
||||||
|
Chunk** mBuff = NULL;
|
||||||
|
ualni mUsedLen = 0;
|
||||||
|
ualni mLen = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Chunk** findUtil(Chunk** aLeft, Chunk** aRight, void* aPtr);
|
||||||
|
};
|
||||||
|
|
||||||
|
Chunks mChunks;
|
||||||
|
Chunk* mFreeChunk = NULL;
|
||||||
|
ualni mBlockSize;
|
||||||
|
ualni mChunkSize;
|
||||||
|
};
|
||||||
|
};
|
||||||
302
Allocators/tests/Tests.cpp
Normal file
302
Allocators/tests/Tests.cpp
Normal file
|
|
@ -0,0 +1,302 @@
|
||||||
|
|
||||||
|
#include "Allocators.hpp"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
tp::ModuleManifest* ModuleDependencies[] = { &tp::gModuleAllocators, NULL };
|
||||||
|
tp::ModuleManifest TestModule("Test", NULL, NULL, ModuleDependencies);
|
||||||
|
if (!TestModule.initialize()) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tp::HeapAllocGlobal alloc;
|
||||||
|
|
||||||
|
int* val = new(alloc) int();
|
||||||
|
delete(alloc, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct test_struct {
|
||||||
|
tp::alni val = 0;
|
||||||
|
|
||||||
|
test_struct() { val = 1; }
|
||||||
|
~test_struct() { val = -1; }
|
||||||
|
|
||||||
|
bool operator==(const test_struct& in) { return in.val == val; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <tp::alni size>
|
||||||
|
struct allocator_test {
|
||||||
|
test_struct data[size];
|
||||||
|
bool is_allocated[size];
|
||||||
|
tp::alni n_loaded = 0;
|
||||||
|
|
||||||
|
test_struct* allocations[size];
|
||||||
|
|
||||||
|
tp::AbstractAllocator* alloc;
|
||||||
|
tp::AbstractAllocator* parent_alloc;
|
||||||
|
const char* allocator_name = NULL;
|
||||||
|
|
||||||
|
tp::alni rand_idx(bool state) {
|
||||||
|
RAND:
|
||||||
|
|
||||||
|
tp::alni idx = (tp::alni)(tp::randf() * (size + 1));
|
||||||
|
CLAMP(idx, 0, size - 1);
|
||||||
|
|
||||||
|
if (state == is_allocated[idx]) {
|
||||||
|
goto RAND;
|
||||||
|
}
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
allocator_test(tp::AbstractAllocator* palloc, const char* pallocator_name, tp::AbstractAllocator* p_parent_alloc) {
|
||||||
|
allocator_name = pallocator_name;
|
||||||
|
parent_alloc = p_parent_alloc;
|
||||||
|
alloc = palloc;
|
||||||
|
for (tp::alni i = 0; i < size; i++) {
|
||||||
|
RAND:
|
||||||
|
tp::alni val = tp::alni(tp::randf() * (size + 100.f));
|
||||||
|
for (tp::alni check_idx = 0; check_idx < size; check_idx++) {
|
||||||
|
if (data[check_idx].val == val) {
|
||||||
|
goto RAND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data[i].val = val;
|
||||||
|
is_allocated[i] = false;
|
||||||
|
allocations[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void verify_integrity() {
|
||||||
|
// verify data integrity
|
||||||
|
for (tp::alni i = 0; i < size; i++) {
|
||||||
|
if (is_allocated[i]) {
|
||||||
|
assert(*allocations[i] == data[i] && "data is currupted\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alloc->isWrapSupport()) assert(!alloc->isWrapCorrupted());
|
||||||
|
if (parent_alloc && parent_alloc->isWrapSupport())
|
||||||
|
assert(!parent_alloc->isWrapCorrupted());
|
||||||
|
|
||||||
|
verify_sizes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void verify_sizes() {
|
||||||
|
return;
|
||||||
|
#ifdef MEM_TRACE
|
||||||
|
assert(alloc->sizeInuse() == n_loaded * sizeof(test_struct) &&
|
||||||
|
"invalid inuse size\n");
|
||||||
|
assert(alloc->sizeReserved() >= n_loaded * (tp::alni)sizeof(test_struct) &&
|
||||||
|
"invalid reserved size\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_item(tp::alni idx) {
|
||||||
|
if (!is_allocated[idx]) {
|
||||||
|
allocations[idx] = new (alloc) test_struct();
|
||||||
|
|
||||||
|
assert(allocations[idx] && "allocator returned NULL");
|
||||||
|
|
||||||
|
allocations[idx]->val = data[idx].val;
|
||||||
|
is_allocated[idx] = true;
|
||||||
|
n_loaded++;
|
||||||
|
verify_integrity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void unload_item(tp::alni idx) {
|
||||||
|
if (is_allocated[idx]) {
|
||||||
|
verify_integrity();
|
||||||
|
delete allocations[idx];
|
||||||
|
is_allocated[idx] = false;
|
||||||
|
n_loaded--;
|
||||||
|
verify_integrity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void change_states(tp::Range<tp::alni> rg, bool state, bool reversed = false, bool random = false) {
|
||||||
|
for (auto i : rg) {
|
||||||
|
tp::alni idx = i;
|
||||||
|
|
||||||
|
if (random) {
|
||||||
|
idx = rand_idx(state);
|
||||||
|
}
|
||||||
|
else if (reversed) {
|
||||||
|
idx = size - i - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
(state) ? load_item(idx) : unload_item(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// full down-up load then up-down unload
|
||||||
|
void test1() {
|
||||||
|
change_states({ 0, size }, 1);
|
||||||
|
change_states({ 0, size }, 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// full down-up load then down-up unload
|
||||||
|
void test2() {
|
||||||
|
change_states({ 0, size }, 1);
|
||||||
|
change_states({ 0, size }, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// full random load then random unload
|
||||||
|
void test3() {
|
||||||
|
change_states({ 0, size }, 1, 0, 1);
|
||||||
|
change_states({ 0, size }, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// multipul tests 1-3
|
||||||
|
void test4() {
|
||||||
|
test1();
|
||||||
|
test1();
|
||||||
|
|
||||||
|
test2();
|
||||||
|
test2();
|
||||||
|
|
||||||
|
test3();
|
||||||
|
test3();
|
||||||
|
}
|
||||||
|
|
||||||
|
static tp::alnf sineupf(tp::alnf asize, tp::alnf x, bool reverse) {
|
||||||
|
tp::alnf end = 4 * PI;
|
||||||
|
tp::alnf a = (2 / 7.f) * asize;
|
||||||
|
tp::alnf b = end / asize;
|
||||||
|
|
||||||
|
tp::alni c = ((-1 * reverse) + (1 * !reverse));
|
||||||
|
tp::alnf c1 = (x - (end * reverse)) / b;
|
||||||
|
tp::alnf c2 = (a * sin(x - (end * reverse)));
|
||||||
|
tp::alnf out = c1 + c2;
|
||||||
|
return c * out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sin load & sin unload with ~1/2 drop factor
|
||||||
|
void test5() {
|
||||||
|
tp::alnf end = 4 * PI;
|
||||||
|
tp::alnf step = end / 4.f;
|
||||||
|
|
||||||
|
for (char i = 0; i < 2; i++) {
|
||||||
|
for (tp::alnf x = 0; x <= end; x += step) {
|
||||||
|
tp::alni target_alloc_count = (tp::alni)ceil(sineupf(size, x, i));
|
||||||
|
CLAMP(target_alloc_count, 0, size);
|
||||||
|
|
||||||
|
while (n_loaded > target_alloc_count) {
|
||||||
|
unload_item(rand_idx(0));
|
||||||
|
}
|
||||||
|
while (n_loaded < target_alloc_count) {
|
||||||
|
load_item(rand_idx(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MEM_WRAP
|
||||||
|
void check_wrap(tp::alni offset, bool after) {
|
||||||
|
CLAMP(offset, 1, WRAP_LEN);
|
||||||
|
|
||||||
|
test_struct* ts = allocations[rand_idx(0)];
|
||||||
|
tp::alni shift = (sizeof(test_struct) * after) + (offset - 1) * after -
|
||||||
|
offset * (!after);
|
||||||
|
tp::uint1* address = (((tp::uint1*)ts) + shift);
|
||||||
|
|
||||||
|
tp::uint1 val = *address;
|
||||||
|
*address = 5;
|
||||||
|
assert(alloc->isWrapCorrupted());
|
||||||
|
*address = val;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// mem guards test
|
||||||
|
void test6() {
|
||||||
|
change_states({ 0, size }, 1);
|
||||||
|
|
||||||
|
#ifdef MEM_WRAP
|
||||||
|
for (tp::alni after = 0; after < 2; after++) {
|
||||||
|
for (tp::alni offset = 1; offset <= WRAP_LEN; offset++) {
|
||||||
|
check_wrap(offset, after);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
change_states({ 0, size }, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_tests() {
|
||||||
|
try {
|
||||||
|
test1();
|
||||||
|
test2();
|
||||||
|
test3();
|
||||||
|
test4();
|
||||||
|
test5();
|
||||||
|
if (alloc->isWrapSupport()) {
|
||||||
|
test6();
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s - passed\n", allocator_name);
|
||||||
|
if (!alloc->isWrapSupport()) {
|
||||||
|
printf(" WARNING: %s has no wrap support!! \n", allocator_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
printf("%s - failed\n", allocator_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void heap_alloc_test() {
|
||||||
|
tp::alloc_init(); {
|
||||||
|
try {
|
||||||
|
allocator_test<150> hatest(tp::heapalloc, "heap allocator", NULL);
|
||||||
|
hatest.run_tests();
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
printf("heap alloc failed\n");
|
||||||
|
}
|
||||||
|
} tp::alloc_uninit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void chunk_alloc_test() {
|
||||||
|
tp::alloc_init(); {
|
||||||
|
try {
|
||||||
|
tp::ChunkAlloc calloc(sizeof(test_struct), 50);
|
||||||
|
allocator_test<50> ca_test(&calloc, "chunk allocator", tp::heapalloc);
|
||||||
|
ca_test.run_tests();
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
printf("chunk alloc failed\n");
|
||||||
|
}
|
||||||
|
} tp::alloc_uninit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void pool_alloc_test() {
|
||||||
|
tp::alloc_init(); {
|
||||||
|
try {
|
||||||
|
tp::PoolAlloc palloc(sizeof(test_struct), 50);
|
||||||
|
allocator_test<150> pa_test(&palloc, "pool allocator", tp::heapalloc);
|
||||||
|
pa_test.run_tests();
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
printf("chunk alloc failed\n");
|
||||||
|
}
|
||||||
|
} tp::alloc_uninit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void allocators_test() {
|
||||||
|
printf("running tests on alocators:\n");
|
||||||
|
|
||||||
|
heap_alloc_test();
|
||||||
|
chunk_alloc_test();
|
||||||
|
pool_alloc_test();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CROSSPLATFORM_MAIN;
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
tp::print_env_info();
|
||||||
|
allocators_test();
|
||||||
|
}
|
||||||
0
Allocators/tests/Tests.hpp
Normal file
0
Allocators/tests/Tests.hpp
Normal file
|
|
@ -1,35 +1,16 @@
|
||||||
|
cmake_minimum_required(VERSION 3.2)
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.10)
|
set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/install)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -gdwarf-4")
|
||||||
|
|
||||||
# set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/./tmp/install)
|
enable_testing()
|
||||||
# set(CMAKE_CXX_FLAGS "-fuse-ld=lld-15 ${CMAKE_CXX_FLAGS} -gdwarf-4 ")
|
|
||||||
|
|
||||||
project(ModulesRoot)
|
project(Types)
|
||||||
|
|
||||||
include(cmake/ModulesOptions.txt)
|
add_compile_definitions(MEM_DEBUG)
|
||||||
|
|
||||||
set(WINDOWS_LIBRARIES "../moduleswindowsl" CACHE STRING "Svn repository with windows libraries https://svn.riouxsvn.com/moduleswindowsl")
|
|
||||||
|
|
||||||
include(cmake/FindGLEW.cmake)
|
|
||||||
include(cmake/FindOIDN.cmake)
|
|
||||||
include(cmake/FindPortAudio.cmake)
|
|
||||||
|
|
||||||
add_subdirectory(Externals)
|
|
||||||
|
|
||||||
add_subdirectory(Modules)
|
add_subdirectory(Modules)
|
||||||
|
add_subdirectory(Utils)
|
||||||
add_subdirectory(Containers)
|
add_subdirectory(Containers)
|
||||||
add_subdirectory(Math)
|
#add_subdirectory(Allocators)
|
||||||
# add_subdirectory(Language)
|
|
||||||
add_subdirectory(Connection)
|
|
||||||
add_subdirectory(Graphics)
|
|
||||||
add_subdirectory(DataAnalysis)
|
|
||||||
add_subdirectory(Objects)
|
|
||||||
add_subdirectory(Widgets)
|
|
||||||
add_subdirectory(LibraryViewer)
|
|
||||||
add_subdirectory(RasterRender)
|
|
||||||
add_subdirectory(3DScene)
|
|
||||||
add_subdirectory(RayTracer)
|
|
||||||
add_subdirectory(Sketch3D)
|
|
||||||
add_subdirectory(3DEditor)
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "x64-Debug",
|
|
||||||
"generator": "Ninja",
|
|
||||||
"configurationType": "Debug",
|
|
||||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
|
||||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
|
||||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
|
||||||
"cmakeCommandArgs": "",
|
|
||||||
"buildCommandArgs": "",
|
|
||||||
"ctestCommandArgs": ""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
project(Connection)
|
|
||||||
|
|
||||||
set(BINDINGS_INCLUDE ./../Externals/asio/asio/include)
|
|
||||||
|
|
||||||
### ---------------------- Static Library --------------------- ###
|
|
||||||
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
|
|
||||||
file(GLOB HEADERS "./public/*.hpp")
|
|
||||||
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
|
|
||||||
target_include_directories(${PROJECT_NAME} PRIVATE ${BINDINGS_INCLUDE})
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Modules)
|
|
||||||
|
|
||||||
### -------------------------- Tests -------------------------- ###
|
|
||||||
enable_testing()
|
|
||||||
file(GLOB TEST_SOURCES "./tests/*.cpp")
|
|
||||||
add_executable(Test${PROJECT_NAME} ${TEST_SOURCES})
|
|
||||||
target_link_libraries(Test${PROJECT_NAME} ${PROJECT_NAME} UnitTest++)
|
|
||||||
add_test(NAME Test${PROJECT_NAME} COMMAND Test${PROJECT_NAME})
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
#include "LocalConnection.hpp"
|
|
||||||
|
|
||||||
#include "bindings/Disk.hpp"
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
bool LocalConnection::Location::exists() const {
|
|
||||||
// TODO : fixme
|
|
||||||
FILE* file = fopen(mLocation.c_str(), "r");
|
|
||||||
if (file) {
|
|
||||||
// File exists, close it and return 1
|
|
||||||
fclose(file);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LocalConnection::connect(const Location& location, const Type& connectionInfo) {
|
|
||||||
DEBUG_ASSERT(!mStatus.isOpened());
|
|
||||||
if (mStatus.isOpened()) return false;
|
|
||||||
|
|
||||||
auto handle = new LocalConnectionContext();
|
|
||||||
|
|
||||||
switch (connectionInfo.getType()) {
|
|
||||||
case Type::READ: handle->open(location.getLocation().c_str(), true); break;
|
|
||||||
case Type::WRITE: handle->open(location.getLocation().c_str(), false); break;
|
|
||||||
default: break;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!handle->isOpen()) {
|
|
||||||
mStatus.setStatus(Status::DENIED);
|
|
||||||
delete handle;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
mStatus.setStatus(Status::OPENED);
|
|
||||||
mHandle = handle;
|
|
||||||
mConnectionType = connectionInfo;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LocalConnection::disconnect() {
|
|
||||||
DEBUG_ASSERT(mStatus.isOpened());
|
|
||||||
if (!mStatus.isOpened() || !mHandle) return false;
|
|
||||||
mHandle->close();
|
|
||||||
delete mHandle;
|
|
||||||
mStatus.setStatus(Status::CLOSED);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LocalConnection::setPointer(BytePointer pointer) {
|
|
||||||
DEBUG_ASSERT(mStatus.isOpened());
|
|
||||||
if (!mStatus.isOpened()) return false;
|
|
||||||
mPointer = pointer;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LocalConnection::readBytes(Byte* bytes, SizeBytes size) {
|
|
||||||
DEBUG_ASSERT(mStatus.isOpened() && mConnectionType.isRead());
|
|
||||||
if (!mStatus.isOpened() || !mConnectionType.isRead()) return false;
|
|
||||||
|
|
||||||
mHandle->seekp(mPointer);
|
|
||||||
mHandle->read(bytes, size);
|
|
||||||
mPointer += size;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LocalConnection::writeBytes(const Byte* bytes, SizeBytes size) {
|
|
||||||
DEBUG_ASSERT(mStatus.isOpened() && mConnectionType.isWrite());
|
|
||||||
if (!mStatus.isOpened() || !mConnectionType.isWrite()) return false;
|
|
||||||
|
|
||||||
mHandle->seekp(mPointer);
|
|
||||||
mHandle->write(bytes, size);
|
|
||||||
mPointer += size;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalConnection::SizeBytes LocalConnection::size() {
|
|
||||||
DEBUG_ASSERT(mStatus.isOpened());
|
|
||||||
if (!mStatus.isOpened() || !mHandle) return 0;
|
|
||||||
return mHandle->size();
|
|
||||||
}
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
|
|
||||||
#include "RemoteConnection.hpp"
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
#include "Disk.hpp"
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
|
|
||||||
ualni tp::LocalConnectionContext::size() {
|
|
||||||
auto strm = (std::fstream*) stream;
|
|
||||||
ualni out = 0;
|
|
||||||
strm->seekg(0, std::ios::beg);
|
|
||||||
out = strm->tellg();
|
|
||||||
strm->seekg(0, std::ios::end);
|
|
||||||
out = (ualni) strm->tellg() - out;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalConnectionContext::LocalConnectionContext() { stream = new std::fstream(); }
|
|
||||||
|
|
||||||
LocalConnectionContext::~LocalConnectionContext() {
|
|
||||||
auto strm = (std::fstream*) stream;
|
|
||||||
delete strm;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LocalConnectionContext::isOpen() {
|
|
||||||
auto strm = (std::fstream*) stream;
|
|
||||||
return strm->is_open();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LocalConnectionContext::close() {
|
|
||||||
auto strm = (std::fstream*) stream;
|
|
||||||
strm->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LocalConnectionContext::seekp(ualni in) {
|
|
||||||
auto strm = (std::fstream*) stream;
|
|
||||||
strm->seekp(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LocalConnectionContext::read(int1* in, ualni size) {
|
|
||||||
auto strm = (std::fstream*) stream;
|
|
||||||
strm->read(in, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LocalConnectionContext::write(const int1* in, ualni size) {
|
|
||||||
auto strm = (std::fstream*) stream;
|
|
||||||
strm->write(in, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LocalConnectionContext::open(const char* path, bool read) {
|
|
||||||
auto strm = (std::fstream*) stream;
|
|
||||||
if (read) strm->open(path, std::ios::in | std::ios::binary | std::ios::app);
|
|
||||||
else strm->open(path, std::ios::out | std::ios::binary | std::ios::trunc);
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
#include "Common.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
class LocalConnectionContext {
|
|
||||||
void* stream;
|
|
||||||
|
|
||||||
public:
|
|
||||||
LocalConnectionContext();
|
|
||||||
~LocalConnectionContext();
|
|
||||||
void open(const char*, bool);
|
|
||||||
bool isOpen();
|
|
||||||
void close();
|
|
||||||
void seekp(ualni);
|
|
||||||
void read(int1*, ualni);
|
|
||||||
void write(const int1*, ualni);
|
|
||||||
ualni size();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue