Compare commits

..

70 commits

Author SHA1 Message Date
IlyaShurupov
63444be3d0 Ignoring GL unallocated? memory 2023-09-03 18:41:10 +03:00
Ilya
2c25667f72 Changing sizing in debug gui 2023-09-03 18:35:09 +03:00
IlushaShurupov
d3bc3a7a99 Debug UI tunes 2023-09-03 18:31:42 +03:00
IlushaShurupov
b36a782823 Enable docking 2023-09-03 18:31:42 +03:00
IlyaShurupov
8d990a0132 Update Clang Format 2023-09-03 10:53:20 +03:00
IlushaShurupov
2810e06b3e Adding outdated source code into master 2023-08-20 11:27:47 +03:00
IlushaShurupov
5cf467a421 Updated TODO 2023-08-14 20:53:34 +03:00
IlushaShurupov
01b6f9099c LR(1) Parser Initial 2023-08-14 20:06:32 +03:00
IlushaShurupov
616441e049 Checking for non productive rules and loops in cfg 2023-08-12 09:39:06 +03:00
IlushaShurupov
b205438601 CFG remove unused rules 2023-08-12 08:27:50 +03:00
IlushaShurupov
e6d9439ba9 Adding simple test fot cf grammar 2023-08-12 08:08:47 +03:00
IlushaShurupov
0a886bd8a8 Fixing list copy and grammar sentence generation 2023-08-11 18:57:39 +03:00
IlushaShurupov
43fe34dcbf Improve module initialization log 2023-08-11 16:42:47 +03:00
IlushaShurupov
7d49642376 Fixin cfg 2023-08-11 16:37:51 +03:00
IlushaShurupov
01b7d96ebd Fixin map 2023-08-11 16:21:30 +03:00
IlushaShurupov
6fcfa075f8 Generate sentences from cf grammar. Fix list initialization from copy constructor 2023-08-11 16:04:02 +03:00
IlushaShurupov
d888aeb2b4 Fixing tokenizer bug 2023-08-10 18:36:56 +03:00
IlushaShurupov
92f34e2a99 CF Grammar improvements 2023-08-10 18:35:48 +03:00
IlushaShurupov
424787c735 CF Grammar Initial 2023-08-10 18:35:40 +03:00
IlushaShurupov
eb712a352d Parser Initial 2023-08-10 18:35:29 +03:00
IlushaShurupov
5fab9ee507 Adding some tokinizer checks for strings and comments 2023-08-10 18:35:17 +03:00
IlushaShurupov
9c8771a378 Editing TODO 2023-08-07 19:03:17 +03:00
Ilusha
9a7e44a96d
Update cmake.yml - sudo apt-get update before installing pacages 2023-08-07 18:56:03 +03:00
IlushaShurupov
112fea2f04 Adding objects GUI initial. Changing TODO. Some fixes along side 2023-08-07 18:37:11 +03:00
IlushaShurupov
f9d62c324d "Added new test 'Complex' and improved error debugging"
This revision adds a complex test to the 'TestInterpreter.cpp' file to test functionalities such as classes, variable initializations, loops, conditionals and methods in the interpreter. The token parser has also been updated with a reset method in the 'parser.cpp' file for cleaning up any previous state before parsing a new script. This ensures the parser starts fresh for each new parse request. It also improves the debugging process in 'function.cpp' by printing the description of parser errors. Few completed tasks are removed from the TODO list.
2023-08-03 21:15:27 +03:00
IlushaShurupov
55571ca3dd Load and destroy methods revised for proper reference counting
The update enhances object management by involving scope-based reference counting. The change affects loading and destruction operations in the Object and several other classes, ensuring the release or retention of objects adhere to their usage context. A function for logging type data has also been introduced to provide better clarity during debugging. Also, tests in script & interpreter have been altered to run in separate module initializations to avoid cross-test interference. Overall, it provides better memory management and dependable tests.
2023-08-01 20:06:34 +03:00
IlushaShurupov
b06e1da529 Add Interpreter tests and improve Parser error logging
A set of tests for the InterpreterObject has been added to enhance its reliability and maintainability. The tests check the essential functionalities such as its creation, execution, saving, loading, and destruction. Furthermore, the error logging for the Parser has been improved, now providing more precise location of detected errors. The changes improve the robustness and debugability of the code.
2023-08-01 18:57:36 +03:00
IlushaShurupov
0cefb47b66 Refactor save size calculation with SaveSizeCounter
SaveSizeCounter is introduced and used for calculating the save size of objects. The previous method of calculating save size directly in each class was replaced with a call to the SaveSizeCounter's calc method. This results in a cleaner, more maintainable code as the size calculation logic is now centralized in one class. It is more efficient and scalable as any changes to the calculation can be made in one place and will be reflected everywhere.
2023-08-01 07:41:09 +03:00
IlushaShurupov
a918c83ec1 Objects adding dict test & fixes 2023-07-31 22:10:46 +03:00
IlushaShurupov
2c8e1470d1 Adding Simple Objest test. Fixes some bugs 2023-07-31 20:16:05 +03:00
IlushaShurupov
64e1f78739 Objects Compiled 2023-07-31 08:04:14 +03:00
IlushaShurupov
ba95747ef9 Merge branch 'Archiver' 2023-07-30 08:32:21 +03:00
IlyaShurupov
3575cbc543 Archiver Initial 2023-07-30 08:28:31 +03:00
IlushaShurupov
01ba8160ef Generating permutations and small buffer checks 2023-07-26 23:30:38 +03:00
IlushaShurupov
939e365a4f Objects Initial 2023-07-25 19:13:27 +03:00
IlushaShurupov
803ce23169 Objects Initial 2023-07-25 08:11:19 +03:00
IlushaShurupov
00bc875846 Freeze on no memory available 2023-07-24 20:39:28 +03:00
IlushaShurupov
5f186164a0 Graphics Animations & Renaming 2023-07-23 22:11:14 +03:00
Ilusha
3a68e70f03 Update cmake.yml to build Graphics 2023-07-23 17:05:35 +03:00
IlushaShurupov
e9c6a97a07 Reorganize a little 2023-07-23 16:50:51 +03:00
IlushaShurupov
3770c72ec0 Adding nanovg 2023-07-23 15:32:02 +03:00
IlushaShurupov
c4a7f91d56 New placement header 2023-07-23 15:32:02 +03:00
IlushaShurupov
6db1406d68 Graphics module Initial (And some more fixes embedded) 2023-07-23 15:31:34 +03:00
Ilusha
e81449eddf
Update cmake.yml - checkout submodules 2023-07-22 20:36:06 +03:00
IlushaShurupov
7595ae3926 Small changes 2023-07-22 20:32:03 +03:00
IlushaShurupov
e9dbee6667 Restructure Storage Module -> Connection module 2023-07-21 19:55:31 +03:00
IlushaShurupov
fa4d1d72dc Merge branch 'Storage' 2023-07-21 18:57:17 +03:00
IlushaShurupov
0301f608bd Fixed bug in map 2023-07-20 22:31:36 +03:00
IlushaShurupov
a543568e1d Restructure 2023-07-20 00:10:29 +03:00
IlushaShurupov
576a3565f7 Command Line INterpreter with fixes 2023-07-19 21:29:57 +03:00
IlushaShurupov
62cb2bb8b7 Fix File test 2023-07-18 23:48:54 +03:00
IlushaShurupov
8e00882bb3 Networking Initial 2023-07-18 23:37:04 +03:00
IlushaShurupov
df3767df29 Storage initial 2023-07-18 23:36:51 +03:00
IlushaShurupov
90998e2279 CommandLine parser initial 2023-07-18 22:37:53 +03:00
IlushaShurupov
6bca7431b7 Adding Strings tests 2023-07-17 22:32:55 +03:00
Ilusha
91b00817e3
Update cmake.yml 2023-07-17 20:49:19 +03:00
Ilusha
d80ea40848
Update cmake.yml 2023-07-17 20:45:05 +03:00
Ilusha
bedd88be2e
Try coverage cmake.yml 2023-07-17 20:43:45 +03:00
IlushaShurupov
bc892da992 Fixes 2023-07-16 18:28:24 +03:00
IlushaShurupov
fabceb52d3 Update Todo 2023-07-15 20:43:24 +03:00
IlushaShurupov
b68539cc0c Tokenizer Test 2023-07-15 20:03:52 +03:00
IlushaShurupov
44bad77e93 Tokenizer (No tests) 2023-07-15 18:58:31 +03:00
IlushaShurupov
e63843c6bb Remove Cmd Arg parser for now 2023-07-15 13:43:55 +03:00
IlushaShurupov
692994c2d3 Tokenizer Initial 2023-07-15 13:43:55 +03:00
IlushaShurupov
facc17ec1b Buffer 2d (No tests) 2023-07-15 13:43:23 +03:00
IlushaShurupov
4c9691e192 Remove old testing 2023-07-15 11:15:54 +03:00
IlushaShurupov
c75cb9fb48 Testing 2023-07-15 11:12:10 +03:00
IlushaShurupov
d362d8c3b3 Removing TextEditor from strings for now 2023-07-15 11:12:10 +03:00
IlushaShurupov
eb9210de1c Strings Initial 2023-07-15 11:12:10 +03:00
EgorPanteleev
9cf541a6ba
Update README.MD (#1) 2023-07-13 20:14:38 +03:00
533 changed files with 55740 additions and 280539 deletions

View file

@ -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}/")

View file

@ -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();
}
}

View file

@ -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.

View file

@ -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();
}
}

View file

@ -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;
};
}

View file

@ -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");
}

View file

@ -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");
}

View file

@ -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; }

View file

@ -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;
}

View file

@ -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;
}
}
}

View file

@ -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");
}

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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");
}

View file

@ -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;
}

View file

@ -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 }));
}

View file

@ -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;
}
}

View file

@ -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 = [](){};
};
}

View file

@ -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;
};
}

View file

@ -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;
};
}

View file

@ -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;
};
}

View file

@ -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;
};
}

View file

@ -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 };
};
}

View file

@ -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;
};
}

View file

@ -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;
};
}

View file

@ -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;
};
}

View file

@ -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;
};
}

View file

@ -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;
};
}

View file

@ -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"

View file

@ -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 };
};
}

View file

@ -1,14 +1,14 @@
--- ---
BasedOnStyle: LLVM BasedOnStyle: LLVM
AccessModifierOffset: -2 AccessModifierOffset: -2
AlignAfterOpenBracket: BlockIndent AlignAfterOpenBracket: Align
AlignArrayOfStructures: None AlignArrayOfStructures: Left
AlignConsecutiveAssignments: AlignConsecutiveAssignments:
Enabled: false Enabled: false
AcrossEmptyLines: false AcrossEmptyLines: false
AcrossComments: false AcrossComments: false
AlignCompound: false AlignCompound: false
PadOperators: false PadOperators: true
AlignConsecutiveBitFields: AlignConsecutiveBitFields:
Enabled: false Enabled: false
AcrossEmptyLines: false AcrossEmptyLines: false
@ -22,22 +22,23 @@ AlignConsecutiveDeclarations:
AlignCompound: false AlignCompound: false
PadOperators: false PadOperators: false
AlignConsecutiveMacros: AlignConsecutiveMacros:
Enabled: false Enabled: true
AcrossEmptyLines: false AcrossEmptyLines: false
AcrossComments: false AcrossComments: false
AlignCompound: false AlignCompound: false
PadOperators: false PadOperators: false
AlignEscapedNewlines: Left AlignEscapedNewlines: Left
AlignOperands: Align AlignOperands: Align
AlignTrailingComments: true AlignTrailingComments:
Kind: Always
OverEmptyLines: 0
AllowAllArgumentsOnNextLine: true AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: true AllowShortCaseLabelsOnASingleLine: true
AllowShortEnumsOnASingleLine: true AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: AllIfsAndElse AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterDefinitionReturnType: None
@ -46,13 +47,13 @@ AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes AlwaysBreakTemplateDeclarations: Yes
AttributeMacros: AttributeMacros:
- __capability - __capability
BinPackArguments: false BinPackArguments: true
BinPackParameters: false BinPackParameters: true
BitFieldColonSpacing: Both 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
@ -68,28 +69,29 @@ BraceWrapping:
SplitEmptyFunction: true SplitEmptyFunction: true
SplitEmptyRecord: true SplitEmptyRecord: true
SplitEmptyNamespace: true SplitEmptyNamespace: true
BreakAfterAttributes: Never
BreakAfterJavaFieldAnnotations: false BreakAfterJavaFieldAnnotations: false
BreakArrays: true
BreakBeforeBinaryOperators: None BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach BreakBeforeBraces: Attach
BreakBeforeConceptDeclarations: Always BreakBeforeConceptDeclarations: Always
BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeTernaryOperators: true BreakBeforeTernaryOperators: true
BreakConstructorInitializers: AfterColon BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon BreakInheritanceList: BeforeColon
BreakStringLiterals: true BreakStringLiterals: true
ColumnLimit: 120 ColumnLimit: 180
CommentPragmas: "^ IWYU pragma:" CommentPragmas: "^ IWYU pragma:"
CompactNamespaces: false CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 4
ConstructorInitializerIndentWidth: 2 ContinuationIndentWidth: 4
ContinuationIndentWidth: 2 Cpp11BracedListStyle: true
Cpp11BracedListStyle: false
DeriveLineEnding: true
DerivePointerAlignment: false DerivePointerAlignment: false
DisableFormat: false DisableFormat: false
EmptyLineAfterAccessModifier: Never EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: false FixNamespaceComments: true
ForEachMacros: ForEachMacros:
- foreach - foreach
- Q_FOREACH - Q_FOREACH
@ -115,19 +117,28 @@ IncludeIsMainSourceRegex: ""
IndentAccessModifiers: false IndentAccessModifiers: false
IndentCaseBlocks: true IndentCaseBlocks: true
IndentCaseLabels: true IndentCaseLabels: true
IndentExternBlock: AfterExternBlock IndentExternBlock: Indent
IndentGotoLabels: true IndentGotoLabels: true
IndentPPDirectives: None IndentPPDirectives: BeforeHash
IndentRequiresClause: true IndentRequiresClause: true
IndentWidth: 2 IndentWidth: 2
IndentWrappedFunctionNames: false IndentWrappedFunctionNames: false
InsertBraces: false InsertBraces: true
InsertNewlineAtEOF: true
InsertTrailingCommas: None InsertTrailingCommas: None
IntegerLiteralSeparator:
Binary: 0
BinaryMinDigits: 0
Decimal: 0
DecimalMinDigits: 0
Hex: 0
HexMinDigits: 0
JavaScriptQuotes: Leave JavaScriptQuotes: Leave
JavaScriptWrapImports: true JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true KeepEmptyLinesAtTheStartOfBlocks: false
LambdaBodyIndentation: Signature LambdaBodyIndentation: Signature
Language: Cpp Language: Cpp
LineEnding: DeriveLF
MacroBlockBegin: "" MacroBlockBegin: ""
MacroBlockEnd: "" MacroBlockEnd: ""
MaxEmptyLinesToKeep: 1 MaxEmptyLinesToKeep: 1
@ -138,7 +149,7 @@ ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true ObjCSpaceBeforeProtocolList: true
PPIndentWidth: -1 PPIndentWidth: -1
PackConstructorInitializers: Never PackConstructorInitializers: CurrentLine
PenaltyBreakAssignment: 2 PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19 PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300 PenaltyBreakComment: 300
@ -150,23 +161,25 @@ PenaltyExcessCharacter: 1000000
PenaltyIndentedWhitespace: 0 PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 60 PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left PointerAlignment: Left
QualifierAlignment: Leave QualifierAlignment: Custom
ReferenceAlignment: Pointer ReferenceAlignment: Pointer
ReflowComments: true ReflowComments: true
RemoveBracesLLVM: false RemoveBracesLLVM: false
RemoveSemicolon: true
RequiresClausePosition: OwnLine RequiresClausePosition: OwnLine
SeparateDefinitionBlocks: Leave RequiresExpressionIndentation: OuterScope
ShortNamespaceLines: 1 SeparateDefinitionBlocks: Always
SortIncludes: Never ShortNamespaceLines: 1000
SortIncludes: CaseSensitive
SortJavaStaticImport: Before SortJavaStaticImport: Before
SortUsingDeclarations: true SortUsingDeclarations: LexicographicNumeric
SpaceAfterCStyleCast: true SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true SpaceAfterTemplateKeyword: true
SpaceAroundPointerQualifiers: Default SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements SpaceBeforeParens: ControlStatements
@ -201,11 +214,15 @@ StatementMacros:
- Q_UNUSED - Q_UNUSED
- QT_REQUIRE_VERSION - QT_REQUIRE_VERSION
TabWidth: 2 TabWidth: 2
UseCRLF: false UseTab: Never
UseTab: ForContinuationAndIndentation
WhitespaceSensitiveMacros: WhitespaceSensitiveMacros:
- STRINGIZE
- PP_STRINGIZE
- BOOST_PP_STRINGIZE - BOOST_PP_STRINGIZE
- NS_SWIFT_NAME
- CF_SWIFT_NAME - CF_SWIFT_NAME
- NS_SWIFT_NAME
- PP_STRINGIZE
- STRINGIZE
QualifierOrder:
- inline
- static
- const
- type

View file

@ -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>

View file

@ -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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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 &lt;br&gt;(CF RE United Format)" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-42">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};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

View file

@ -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...";
}

View file

@ -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

View file

@ -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}}

View file

@ -20,45 +20,39 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Setup - name: Setup externals
shell: bash shell: bash
run: | run: |
# If your submodules are configured to use SSH instead of HTTPS please uncomment the following line # If your submodules are configured to use SSH instead of HTTPS please uncomment the following line
# git config --global url."https://github.com/".insteadOf "git@github.com:" # git config --global url."https://github.com/".insteadOf "git@github.com:"
auth_header="$(git config --local --get http.https://github.com/.extraheader)" auth_header="$(git config --local --get http.https://github.com/.extraheader)"
git submodule sync --recursive git submodule sync --recursive
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1 git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
sudo apt-get update sudo apt-get update
sudo apt-get install python3 python-is-python3 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 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 cd Externals/glew/
#run: | make extensions
# 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: Set LLVM Toolchain
run: |
sudo apt-get install -y llvm
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 - name: Configure CMake
run: | run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
gcc -v
clang++-15 -v
CC=clang-15 CXX=clang++-15 cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Build - name: Build
run: CC=clang CXX=clang++ cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -v -j run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: Test - name: Test
working-directory: ${{github.workspace}}/build working-directory: ${{github.workspace}}/build
# Execute tests defined by the CMake configuration. # Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -j -C ${{env.BUILD_TYPE}} run: ctest -C ${{env.BUILD_TYPE}}

5
.gitignore vendored
View file

@ -2,11 +2,6 @@
*tmp* *tmp*
bin bin
build* build*
*build*
lib lib
install install
.vscode .vscode
out
.vs
*.bkp
*.$*

41
.gitmodules vendored
View file

@ -1,30 +1,15 @@
[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"] [submodule "Externals/asio"]
path = Externals/asio path = Externals/asio
url = https://github.com/elushaX/asio.git url = https://github.com/IlyaShurupov/asio.git
[submodule "Externals/implot"] [submodule "Externals/glfw"]
path = Externals/implot path = Externals/glfw
url = https://github.com/epezent/implot.git url = https://github.com/IlyaShurupov/glfw.git
[submodule "Externals/googletest"] [submodule "Externals/imgui"]
path = Externals/googletest path = Externals/imgui
url = https://github.com/google/googletest.git url = https://github.com/IlyaShurupov/imgui.git
[submodule "Externals/benchmark"] [submodule "Externals/glew"]
path = Externals/benchmark path = Externals/glew
url = https://github.com/google/benchmark.git url = https://github.com/IlyaShurupov/glew.git
[submodule "Externals/nanovg"]
path = Externals/nanovg
url = https://github.com/IlyaShurupov/nanovg.git

View file

@ -1,5 +1,29 @@
// OBJ_Loader.h - A Single Header OBJ Model Loader // OBJ_Loader.h - A Single Header OBJ Model Loader
/*
MIT License
Copyright(c) 2016 Robert Smith
Permission is hereby granted, free of charge, to any person obtaining a copy
of this softwareand associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright noticeand this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once #pragma once
// Iostream - STD I/O Library // Iostream - STD I/O Library
@ -140,7 +164,7 @@ namespace objl
Vector3 Position; Vector3 Position;
// Normal Vector // Normal Vector
Vector3 Normal; Vector3 normal;
// Texture Coordinate Vector // Texture Coordinate Vector
Vector2 TextureCoordinate; Vector2 TextureCoordinate;
@ -797,7 +821,7 @@ namespace objl
{ {
vVert.Position = algorithm::getElement(iPositions, svert[0]); vVert.Position = algorithm::getElement(iPositions, svert[0]);
vVert.TextureCoordinate = Vector2(0, 0); vVert.TextureCoordinate = Vector2(0, 0);
vVert.Normal = algorithm::getElement(iNormals, svert[2]); vVert.normal = algorithm::getElement(iNormals, svert[2]);
oVerts.push_back(vVert); oVerts.push_back(vVert);
break; break;
} }
@ -805,7 +829,7 @@ namespace objl
{ {
vVert.Position = algorithm::getElement(iPositions, svert[0]); vVert.Position = algorithm::getElement(iPositions, svert[0]);
vVert.TextureCoordinate = algorithm::getElement(iTCoords, svert[1]); vVert.TextureCoordinate = algorithm::getElement(iTCoords, svert[1]);
vVert.Normal = algorithm::getElement(iNormals, svert[2]); vVert.normal = algorithm::getElement(iNormals, svert[2]);
oVerts.push_back(vVert); oVerts.push_back(vVert);
break; break;
} }
@ -828,7 +852,7 @@ namespace objl
for (int i = 0; i < int(oVerts.size()); i++) for (int i = 0; i < int(oVerts.size()); i++)
{ {
oVerts[i].Normal = normal; oVerts[i].normal = normal;
} }
} }
} }
@ -946,7 +970,7 @@ namespace objl
} }
// If Vertex is not an interior vertex // If Vertex is not an interior vertex
float angle = math::AngleBetweenV3(pPrev.Position - pCur.Position, pNext.Position - pCur.Position) * (180 / 3.14159265359); float angle = (float)math::AngleBetweenV3(pPrev.Position - pCur.Position, pNext.Position - pCur.Position) * (float) (180 / 3.14159265359);
if (angle <= 0 && angle >= 180) if (angle <= 0 && angle >= 180)
continue; continue;

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "Environment.hpp" #include "env.h"
#ifdef ENV_OS_ANDROID #ifdef ENV_OS_ANDROID
#include <EGL/egl.h> #include <EGL/egl.h>

View file

@ -0,0 +1,53 @@
#pragma once
#include "rect.h"
#include "color.h"
namespace tp {
namespace glw {
extern bool gInTransition;
struct AnimValue {
halnf mValPrev = 0;
halnf mVal = 0;
time_ms mTimeStart = 0;
halni mTimeAnim = 250;
halnf interpolate() const;
AnimValue();
AnimValue(halnf val);
halnf prev() { return mValPrev; }
void set(halnf val);
void setNoTransition(halnf);
void setAnimTime(halni time);
halnf get() const;
halnf getTarget() const;
bool inTransition() const;
explicit operator halnf() const;
void operator=(halnf val);
};
struct AnimRect : rect<AnimValue> {
AnimRect() {
set({ 0, 0, 0, 0 });
setAnimTime(450);
}
rectf get() const;
rectf getTarget() const;
void setNoTransition(rectf);
void set(const rectf&);
void setAnimTime(halni time_ms);
};
struct AnimColor {
AnimRect mColor;
rgba get() const;
void set(const rgba&);
};
};
};

View file

@ -0,0 +1,84 @@
#pragma once
#include "stringt.h"
#include "fbuffer.h"
namespace tp {
namespace glw {
class Canvas {
typedef rectf Rect;
typedef vec2f Vec2;
typedef rgba Col;
typedef tp::halnf Val;
Col mColorPrimary;
Col mColorSecondary;
void* mCtx = NULL;
tp::halnf mDpmm = 1;
tp::halnf mUIScale = 1;
public:
Rect mClamping;
Rect mVieport;
enum Align : uint4 {
LEFT = 1 << 0, // Default, horizontally to left.
CENTER = 1 << 1, // horizontally to center.
RIGHT = 1 << 2, // horizontally to right.
TOP = 1 << 3, // vertically to top.
MIDDLE = 1 << 4, // vertically to middle.
BOTTOM = 1 << 5, // vertically to bottom.
BASELINE = 1 << 6, // Default, vertically to baseline.
CENTER_MIDDLE = CENTER | MIDDLE,
LEFT_MIDDLE = LEFT | MIDDLE,
};
Canvas();
Val& convert2pxls(Val&);
Rect& convert2pxls(Rect&);
Vec2& convert2pxls(Vec2&);
Val as2pxls(Val);
// Canvas Manipulation
void beginDraw(Rect viewport, tp::halnf dpmm, tp::halnf uiscale);
void clear(Col color = 0);
void endDraw();
void setClamping(Rect rec);
void resetViewport();
// Params control
void setCol1(const Col& col);
void setCol2(const Col& col);
// Shapes
void rect(Rect rec, halnf rounding = 0, halnf borders = 0);
void circle(Vec2 rec, halnf radius, halnf borders = 0);
void trig(Vec2 p1, Vec2 p2, Vec2 p3);
void line(Vec2 p1, Vec2 p2, halnf thikness = 2);
// Text
void text(const string text, Rect rec, halnf size, Align align = Align::CENTER_MIDDLE);
void text(const char* start, const char* end, Rect rec, halnf size, Align align = Align::CENTER_MIDDLE);
void drawColorwheel(Rect rec, const rgb& col);
// image
struct ImageHandle {
halni mId = NULL;
void createFromBuff(glw::fbuffer* buff, Canvas* drawer);
void free(Canvas* drawer);
~ImageHandle();
};
void drawImage(Rect rec, ImageHandle* image, halnf angle = 0.f, halnf alpha = 1.f, halnf rounding = 0.f);
~Canvas();
};
};
};

View file

@ -0,0 +1,48 @@
#include "window.h"
namespace ImGui {
bool SubMenuBegin(const char* desc, int level);
void SubMenuEnd(int level);
void ToolTip(const char* desc);
struct PopupData {
bool opened = false;
bool ishovered = false;
tp::vec2f p1 = 0;
tp::vec2f p2 = 0;
operator bool() {
return opened;
}
};
PopupData HoverPopupBeginButton(const char* id, tp::vec2f butsize = 200, tp::vec2f popupsize = 200);
PopupData HoverPopupBegin(const char* id, tp::vec2f size = 200, tp::vec2f pos = -1, int flags = 0);
void HoverPopupEnd(PopupData& in);
void ApplyStyle(tp::halnf dpmm, float font_size_mm = 5, float ui_scale = 1);
};
namespace tp {
namespace glw {
typedef void (DebugUiDrawCallBack)(void* cd);
struct DebugUI {
tp::halnf mDPMM = 1;
tp::halnf mFontSizeMM = 3;
tp::halnf mUIScale = 1;
DebugUiDrawCallBack* cb = NULL;
void* cd = NULL;
struct DebugUiInternalContext* mCtx = NULL;
DebugUI(Window& window, DebugUiDrawCallBack* acb, void* acd);
void drawDebugUI(tp::halnf dpmm);
~DebugUI();
};
};
};

View file

@ -0,0 +1,40 @@
#pragma once
#include "rect.h"
#include "color.h"
namespace tp {
namespace glw {
class fbuffer {
uint4 mFrameBufferID = 0; // regroups 0, 1, or more textures, and 0 or 1 depth buffer.
uint4 mTextureId = 0; // texture we're going to render to ( colour attachement #0 )
uint4 mDepthBufferID = 0;
uint4 mDrawBuffers[1];
vec2f mSize;
public:
rgba mClearCol = 0.f;
fbuffer(const vec2f& size);
fbuffer(const vec2f& size, tp::uint1 samples);
void beginDraw();
void setViewport(const rectf& viewport);
void clear();
void endDraw();
uint4 texId() const;
uint4 buffId() const;
const vec2f& getSize() const;
uhalni sizeAllocatedMem() const;
uhalni sizeUsedMem() const;
~fbuffer();
};
};
};

View file

@ -1,10 +1,11 @@
#pragma once #pragma once
#include "Environment.hpp"
namespace tp { namespace tp {
enum class InputID : ualni {
// basically copy of glfw keys
enum class Keycode {
/* Printable keys */ /* Printable keys */
SPACE = 32, SPACE = 32,
APOSTROPHE = 39, /* ' */ APOSTROPHE = 39, /* ' */
@ -64,7 +65,7 @@ namespace tp {
TAB = 258, TAB = 258,
BACKSPACE = 259, BACKSPACE = 259,
INSERT = 260, INSERT = 260,
DELETE_KEY = 261, DELETE = 261,
RIGHT = 262, RIGHT = 262,
LEFT = 263, LEFT = 263,
DOWN = 264, DOWN = 264,
@ -142,11 +143,25 @@ namespace tp {
MOUSE3 = 503, MOUSE3 = 503,
MOUSE4 = 504, MOUSE4 = 504,
MOUSE5 = 505, MOUSE5 = 505,
MOUSE_UP = 506,
SCROLL, MOUSE_DOWN = 507,
WINDOW_RESIZE,
LAST_KEY_CODE,
}; };
}
enum class Keystate {
PRESSED,
RELEASED,
HOLD,
REPEAT,
NONE,
};
struct KeyEvent {
Keycode code;
enum class EventState {
RELEASED = 0,
PRESSED = 1,
REPEAT = 2,
} event_state;
};
};

View file

@ -0,0 +1,36 @@
#pragma once
namespace tp {
namespace glw {
class shader {
uint4 programm;
uint4 VertexShaderID;
uint4 FragmentShaderID;
uint4 GeometryShaderID;
public:
bool compile_shader(const char* ShaderCode, uint4 ShaderID);
void load(const char* vert, const char* geom, const char* frag, bool paths);
shader();
void vert_bind_source(const char* vert_src);
void frag_bind_source(const char* frag_src);
void geom_bind_source(const char* geom_src);
void compile();
shader(const char* vertid, const char* geomid, const char* fragid, bool paths = true);
void bind();
uint4 getu(const char* uid);
void unbind();
~shader();
alni sizeAllocatedMem();
alni sizeUsedMem();
};
};
};

View file

@ -0,0 +1,71 @@
#pragma once
#include "window.h"
#include "canvas.h"
#include "animations.h"
namespace tp {
namespace glw {
class WindowSimpleInputs {
enum class Mouse : uint1 { NONE, PRESSED, HOLD, RELEASED } mMouse;
enum class Move : uint1 { NONE, LEFT, RIGHT, UP, DOWN } mMove;
public:
halnf mScaleVal = 0;
vec2f mWindowSizeMM;
vec2f mCrs;
vec2f mCrsPrev;
vec2f mCrsmDelta;
halnf mPressure = 0.f;
void update(const glw::Window& window, halnf uiscale);
bool Activated();
bool Anticipating();
bool Selected();
bool MoveLeft();
bool MoveRight();
bool MoveUp();
bool MoveDown();
bool Drag();
};
struct ButtonWidget {
rectf mRect = { 0.f, 10.f };
rgba mCol = { 0.3f, 0.3f, 0.3f, 1.f };
bool mPressed = false;
AnimRect mAnimRec;
void draw(glw::Canvas& canvas);
void proc(glw::WindowSimpleInputs& inputs);
};
struct CheckBoxWidget {
rectf mRect = { 0.f, 10.f };
rgba mCol = { 0.3f, 0.3f, 0.3f, 1.f };
rgba mColActive = { 0.5f, 0.5f, 0.5f, 1.f };
bool mValue = false;
AnimRect mAnimRec;
AnimColor mAnimCol;
void draw(glw::Canvas& canvas);
void proc(glw::WindowSimpleInputs& inputs);
};
struct WindowsHeaderWidget {
rectf header_rec = { 10, 10, 50, 10 };
rgba col = { 0.13f, 0.13f, 0.13f, 0.9f };
rectf grab_rec = 0.f;
ButtonWidget mExitButton;
ButtonWidget mMaxButton;
ButtonWidget mMinButton;
CheckBoxWidget mPinButton;
void updRecs();
void draw(glw::Canvas& canvas);
void proc(glw::Window& window, glw::WindowSimpleInputs& inputs);
};
};
};

View file

@ -0,0 +1,31 @@
#pragma once
#include "array2d.h"
#include "color.h"
#include "vec.h"
namespace tp {
namespace glw {
class texture {
uint4 id;
public:
texture();
~texture();
uint4 getid();
void update(const Array2D<rgba>& buff);
void draw(const uint4& out = 0);
alni sizeAllocatedMem();
alni sizeUsedMem();
static void init();
static void deinit();
static void draw_texture(uint4 out, uint4 in);
static uint4 get_tex(const char* TexId);
static void drawCurcle(vec2f pos, double radius, rgba col);
};
};
};

View file

@ -0,0 +1,114 @@
#pragma once
#include "common.h"
#include "vec.h"
#include "rect.h"
#include "color.h"
#include "stringt.h"
#include "array.h"
#include "map.h"
#include "keycodes.h"
#include "queue.h"
namespace tp {
extern tp::ModuleManifest gModuleGlw;
namespace glw {
struct PlatformContext;
class Window {
public:
struct Device {
time_ms FrameRate = NULL; // monitor fps
vec2f Size; // size of the monitor
tp::halnf mDPMM = 1;
};
struct Events {
tp::Queue<KeyEvent> mKeysQueue;
tp::uhalni mRedraw = 2;
bool mClose = false;
vec2f mCursor = 0;
halnf mPressure = 1.f;
vec2f mCursorPrev = 0.f;
halnf mPressurePrev = 1.f;
};
struct Appearence {
vec2f mPos = { 100.f, 100.f }; // global position
vec2f mSize = { 300.f, 300.f }; // width and height of window
vec2f mSizeMin = { 100.f, 100.f }; // min size possiable
vec2f mSizeMax = { 700.f, 700.f }; // max size possiable
bool mHiden = true;
bool mMaximized = false;
bool mMinimized = false;
bool mTopZ = false;
bool mAllDesktops = false;
rgba mResizeColor = rgba(0.13f, 0.13f, 0.13f, 0.9f);
rectf mMinMaxBox;
tp::Array<rectf> mCaptionsAddArea;
tp::Array<rectf> mCaptionsRemoveArea;
};
public:
PlatformContext* mPlatformCtx = NULL;
void platformCallback();
void* platform_window() const;
struct NativeEventListenerCallback {
typedef void (call_back_func)(PlatformContext* ctx, void* cd);
call_back_func* exec_begin = NULL;
call_back_func* exec = NULL;
call_back_func* exec_end = NULL;
void* cd = NULL;
};
tp::HashMap<NativeEventListenerCallback, string> mNativeEventListeners;
private:
struct Cache {
Appearence mAppearencePrev;
vec2f mWindowSize = 0;
rectf mRectBeforResizing = 0;
bool mUserResizing = false;
bool mMinMaxHover = false;
bool mMouseTracked = false;
} mCache;
void applyAppearance();
void initialize();
public:
static Device mDevice;
Appearence mAppearence;
Events mEvents;
Window();
Window(const Appearence& aAppearence);
void pollEvents();
void beginDraw();
void endDraw();
alni sizeAllocatedMem();
alni sizeUsedMem();
~Window();
};
};
};

View file

@ -0,0 +1,25 @@
#pragma once
#include "queue.h"
struct AndroidApi {
union Event {
enum Type : tp::uint1 {
EV_NONE = 0,
} type = EV_NONE;
struct None {
} none;
};
tp::Queue<Event> events;
};
extern AndroidApi* gAndroidApi;

View file

@ -0,0 +1,804 @@
// Copyright (C) 2010 The Android Open Source Project
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// own headers
#include "window.h"
#include "GraphicsLibApi.h"
// STL
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <fstream>
#include <stdlib.h>
// jni
//#include <initializer_list>
//#include <memory>
//#include <cstdlib>
//#include <cstring>
#include <jni.h>
//#include <cerrno>
//#include <cassert>
// opengl
#include <EGL/egl.h>
#include <GLES3/gl32.h>
//#include "GL/glew.h"
// glue
#include <android/sensor.h>
#include <android/log.h>
#include <android/input.h>
#include <../../../android/native_app_glue/android_native_app_glue.h>
// AcquireASensorManagerInstance
#include <dlfcn.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
// application side entry point
int main();
// first function to be called in "main thread"
void* main_wrap(void* p);
// AcquireASensorManagerInstance(void)
// Workaround ASensorManager_getInstance() deprecation false alarm
// for Android-N and before, when compiling with NDK-r15
ASensorManager* AcquireASensorManagerInstance(android_app* app) {
if (!app)
return nullptr;
typedef ASensorManager* (*PF_GETINSTANCEFORPACKAGE)(const char* name);
void* androidHandle = dlopen("libandroid.so", RTLD_NOW);
auto getInstanceForPackageFunc = (PF_GETINSTANCEFORPACKAGE)
dlsym(androidHandle, "ASensorManager_getInstanceForPackage");
if (getInstanceForPackageFunc) {
JNIEnv* env = nullptr;
app->activity->vm->AttachCurrentThread(&env, nullptr);
jclass android_content_Context = env->GetObjectClass(app->activity->clazz);
jmethodID midGetPackageName = env->GetMethodID(android_content_Context,
"getPackageName",
"()Ljava/lang/String;");
auto packageName = (jstring)env->CallObjectMethod(app->activity->clazz,
midGetPackageName);
const char* nativePackageName = env->GetStringUTFChars(packageName, nullptr);
ASensorManager* mgr = getInstanceForPackageFunc(nativePackageName);
env->ReleaseStringUTFChars(packageName, nativePackageName);
app->activity->vm->DetachCurrentThread();
if (mgr) {
dlclose(androidHandle);
return mgr;
}
}
typedef ASensorManager* (*PF_GETINSTANCE)();
auto getInstanceFunc = (PF_GETINSTANCE)
dlsym(androidHandle, "ASensorManager_getInstance");
// by all means at this point, ASensorManager_getInstance should be available
assert(getInstanceFunc);
dlclose(androidHandle);
return getInstanceFunc();
}
void GL_APIENTRY MessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) {
DBG_BREAK(true);
LOGW("GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), type, severity, message);
}
char const* gl_error_string(GLenum const err) {
switch (err) {
case GL_NO_ERROR: return "GL_NO_ERROR";
case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
case GL_INVALID_VALUE: return "GL_INVALID_VALUE";
case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW";
case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW";
case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
case GL_INVALID_FRAMEBUFFER_OPERATION: return "GL_INVALID_FRAMEBUFFER_OPERATION";
default: return "unknown error";
}
}
void glerr(GLenum type) {
DBG_BREAK(true);
const GLchar* message = gl_error_string(type);
LOGW("GL CALLBACK: %s type = 0x%x, message = %s\n", (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), type, message);
}
void glerr(GLenum type);
#define AssertGL(x) { x; GLenum __gle = glGetError(); if (__gle != GL_NO_ERROR) glerr(__gle); }
// --------------------------------- Data --------------------------------------- //
struct MutexEvent {
pthread_mutex_t mutex;
tp::glw::Window* active_windw;
bool parent_thread_has_events = false;
bool child_whaiting = false;
} mutex_event;
struct ANativeActivityCtx* android_ctx = NULL;
tp::glw::Window::Device tp::glw::Window::mDevice;
extern const char* g_android_internal_data_path;
static pthread_t worker_thread;
static pthread_mutex_t worker_finished_mutex;
static pthread_cond_t worker_finished_cond;
static bool worker_finished = false;
namespace tp {
namespace glw {
struct PlatformContext {
int col = 255;
EGLint w, h, format;
EGLint numConfigs;
EGLConfig config = nullptr;
EGLSurface surface;
EGLContext context;
EGLDisplay display = nullptr;
AInputEvent* chache_event = NULL;
EGLint majorVersion, minorVersion;
// Initialize an EGL context for the current display.
PlatformContext(ANativeWindow* window) {
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (EGL_NO_DISPLAY == display) {
return;
}
if (eglInitialize(display, &majorVersion, &minorVersion) != EGL_TRUE) {
return;
}
// Here specify the attributes of the desired configuration.
// Below, we select an EGLConfig with at least 8 bits per color component compatible with on-screen windows
const EGLint attribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, // request OpenGL ES 3.0
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_DEPTH_SIZE, GLW_CONTEXT_DEPTH_BITS,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE
};
// Here, the application chooses the configuration it desires.
// find the best match if possible, otherwise use the very first one
{
if (eglChooseConfig(display, attribs, nullptr, 0, &numConfigs) != EGL_TRUE) {
return;
}
std::unique_ptr<EGLConfig[]> supportedConfigs(new EGLConfig[numConfigs]);
assert(supportedConfigs);
if (eglChooseConfig(display, attribs, supportedConfigs.get(), numConfigs, &numConfigs) != EGL_TRUE) {
return;
}
assert(numConfigs);
auto i = 0;
for (; i < numConfigs; i++) {
auto& cfg = supportedConfigs[i];
EGLint r, g, b, d;
if (eglGetConfigAttrib(display, cfg, EGL_RED_SIZE, &r) &&
eglGetConfigAttrib(display, cfg, EGL_GREEN_SIZE, &g) &&
eglGetConfigAttrib(display, cfg, EGL_BLUE_SIZE, &b) &&
eglGetConfigAttrib(display, cfg, EGL_DEPTH_SIZE, &d) &&
r == 8 && g == 8 && b == 8 && d == GLW_CONTEXT_DEPTH_BITS) {
config = supportedConfigs[i];
break;
}
}
if (i == numConfigs) {
config = supportedConfigs[0];
}
if (config == nullptr) {
LOGW("Unable to initialize EGLConfig");
return;
}
}
const EGLint egl_context_attributes[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
//EGL_CONTEXT_MAJOR_VERSION, 3,
//EGL_CONTEXT_MINOR_VERSION, 0,
EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
#ifdef ENV_BUILD_DEBUG
//EGL_CONTEXT_OPENGL_DEBUG, EGL_TRUE,
#endif
EGL_NONE
};
// EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
// guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
// As soon as we picked a EGLConfig, we can safely reconfigure the
// ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
surface = eglCreateWindowSurface(display, config, window, nullptr);
context = eglCreateContext(display, config, EGL_NO_CONTEXT, egl_context_attributes);
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
LOGW("Unable to eglMakeCurrent");
return;
}
eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
// Check openGL on the system
auto opengl_info = { GL_VENDOR, GL_RENDERER, GL_VERSION, GL_EXTENSIONS };
for (auto name : opengl_info) {
auto info = glGetString(name);
LOGI("OpenGL Info: %s", info);
}
// Initialize GL state.
//glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
AssertGL(glEnable(GL_CULL_FACE));
//AssertGL(glShadeModel(GL_SMOOTH));
AssertGL(glEnable(GL_DEPTH_TEST));
AssertGL(glDepthFunc(GL_LESS));
GLint major = 0;
GLint minor = 0;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
glGetIntegerv(GL_DEPTH, &minor);
AssertGL(glEnable(GL_DEBUG_OUTPUT));
AssertGL(glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS));
AssertGL(glDebugMessageCallback(MessageCallback, 0));
tp::glw::Window::mDevice.Size = { w, h };
tp::glw::Window::mDevice.FrameRate = 60;
return;
}
void beginDraw() {
if (this->display == nullptr) { return; }
glViewport(0, 0, tp::glw::Window::mDevice.Size.x, tp::glw::Window::mDevice.Size.y);
//glClearColor(col / 255.f, col / 255.f, col / 255.f, 1);
//glClear(GL_COLOR_BUFFER_BIT);
//if (col++ > 255) {
//col = 0;
//}
}
void endDraw() {
eglSwapBuffers(display, surface);
}
// Tear down the EGL context currently associated with the display.
~PlatformContext() {
if (this->display != EGL_NO_DISPLAY) {
eglMakeCurrent(this->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (this->context != EGL_NO_CONTEXT) {
eglDestroyContext(this->display, this->context);
}
if (this->surface != EGL_NO_SURFACE) {
eglDestroySurface(this->display, this->surface);
}
eglTerminate(this->display);
}
display = EGL_NO_DISPLAY;
context = EGL_NO_CONTEXT;
surface = EGL_NO_SURFACE;
}
};
};
};
// ---------------------------------- Parent Thread ------------------------------------ //
#ifndef PARENT_THREAD
// Shared state for our app.
struct ANativeActivityCtx {
// Our saved state data.
struct saved_state {
float angle;
int32_t x;
int32_t y;
};
android_app* app;
ASensorManager* sensorManager;
const ASensor* accelerometerSensor;
ASensorEventQueue* sensorEventQueue;
int animating;
EGLDisplay display;
EGLSurface surface;
EGLContext context;
int32_t width;
int32_t height;
saved_state state;
ANativeActivityCtx(android_app* state) {
memset(this, 0, sizeof(*this));
state->userData = this;
state->onAppCmd = engine_handle_cmd;
state->onInputEvent = engine_handle_input;
app = state;
// Prepare to monitor accelerometer
sensorManager = AcquireASensorManagerInstance(state);
accelerometerSensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_ACCELEROMETER);
sensorEventQueue = ASensorManager_createEventQueue(sensorManager, state->looper, LOOPER_ID_USER, 0, 0);
// We are starting with a previous saved state; restore from it.
if (state->savedState != nullptr) {
this->state = *(saved_state*)state->savedState;
}
}
void proc_events_util() {
int ident;
int events;
struct android_poll_source* source;
auto window = mutex_event.active_windw;
if (window) {
for (auto proc : window->mNativeEventListeners) {
proc->val.exec_begin(window->mPlatformCtx, proc->val.cd);
}
}
// we loop until all events are read
while ((ident = ALooper_pollAll(0, nullptr, &events, (void**)&source)) >= 0) {
// Process this event.
if (source != nullptr) {
source->process(this->app, source);
}
// If a sensor has data, process it now.
if (ident == LOOPER_ID_USER) {
if (this->accelerometerSensor != nullptr) {
ASensorEvent event;
while (ASensorEventQueue_getEvents(this->sensorEventQueue, &event, 1) > 0) {
LOGI("accelerometer: x=%f y=%f z=%f", event.acceleration.x, event.acceleration.y, event.acceleration.z);
}
}
}
// Check if we are exiting.
if (this->app->destroyRequested != 0) {
DBG_BREAK(1);
}
}
if (window) {
for (auto proc : window->mNativeEventListeners) {
proc->val.exec_end(window->mPlatformCtx, proc->val.cd);
}
}
}
void proc_events() {
pthread_mutex_lock(&mutex_event.mutex);
auto threaded = mutex_event.active_windw;
pthread_mutex_unlock(&mutex_event.mutex);
if (!threaded) {
proc_events_util();
return;
}
// Read all pending events.
int ident;
int events;
struct android_poll_source* source;
// check if events exist and if so prepare to proccess them
if ((ident = ALooper_pollAll(0, nullptr, &events, (void**)&source)) >= 0) {
// signal child thread that we need to process those events
pthread_mutex_lock(&mutex_event.mutex);
mutex_event.parent_thread_has_events = true;
pthread_mutex_unlock(&mutex_event.mutex);
// whait until child thread pauses
bool whait = true;
while (whait) {
pthread_mutex_lock(&mutex_event.mutex);
whait = !mutex_event.child_whaiting;
pthread_mutex_unlock(&mutex_event.mutex);
}
}
else {
return;
}
pthread_mutex_lock(&mutex_event.mutex);
auto window = mutex_event.active_windw;
pthread_mutex_unlock(&mutex_event.mutex);
proc_events_util();
// signal to child continue to do its work
pthread_mutex_lock(&mutex_event.mutex);
mutex_event.parent_thread_has_events = false;
pthread_mutex_unlock(&mutex_event.mutex);
}
// Process the next input event.
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
auto* engine = (struct ANativeActivityCtx*)app->userData;
auto window = mutex_event.active_windw;
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
window->mEvents.mCursorPrev = window->mEvents.mCursor;
window->mEvents.mCursor.x = AMotionEvent_getX(event, 0);
window->mEvents.mCursor.y = AMotionEvent_getY(event, 0);
window->mEvents.mRedraw = 2;
int32_t event_action = AMotionEvent_getAction(event);
int32_t event_pointer_index = (event_action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
event_action &= AMOTION_EVENT_ACTION_MASK;
if ((AMotionEvent_getToolType(event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_FINGER)
|| (AMotionEvent_getToolType(event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_UNKNOWN)) {
if (event_action == AMOTION_EVENT_ACTION_DOWN) {
window->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode::MOUSE1, tp::KeyEvent::EventState::PRESSED });
}
else if (event_action == AMOTION_EVENT_ACTION_UP) {
window->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode::MOUSE1, tp::KeyEvent::EventState::RELEASED });
}
}
}
if (window) {
window->mPlatformCtx->chache_event = event;
for (auto proc : window->mNativeEventListeners) {
proc->val.exec(window->mPlatformCtx, proc->val.cd);
}
}
return 0;
}
// Process the next main command.
static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
auto* engine = (struct ANativeActivityCtx*)app->userData;
auto window = mutex_event.active_windw;
switch (cmd) {
// The system has asked us to save our current state. Do so.
case APP_CMD_SAVE_STATE: {
engine->app->savedState = malloc(sizeof(ANativeActivityCtx::saved_state));
*((ANativeActivityCtx::saved_state*)engine->app->savedState) = engine->state;
engine->app->savedStateSize = sizeof(ANativeActivityCtx::saved_state);
} break;
// The window is being shown, get it ready.
case APP_CMD_INIT_WINDOW: {
if (engine->app->window != nullptr) {
//engine->init_display();
//engine->draw_frame();
}
} break;
// The window is being hidden or closed, clean it up.
case APP_CMD_TERM_WINDOW: {
//engine->term_display();
} break;
// When our app gains focus, we start monitoring the accelerometer.
case APP_CMD_GAINED_FOCUS: {
if (engine->accelerometerSensor != nullptr) {
ASensorEventQueue_enableSensor(engine->sensorEventQueue,
engine->accelerometerSensor);
// We'd like to get 60 events per second (in us).
ASensorEventQueue_setEventRate(engine->sensorEventQueue,
engine->accelerometerSensor,
(1000L / 60) * 1000);
}
} break;
// When our app loses focus, we stop monitoring the accelerometer.
// This is to avoid consuming battery while not being used.
case APP_CMD_LOST_FOCUS: {
if (engine->accelerometerSensor != nullptr) {
ASensorEventQueue_disableSensor(engine->sensorEventQueue,
engine->accelerometerSensor);
}
// Also stop animating.
engine->animating = 0;
//engine->draw_frame();
} break;
default: break;
}
}
};
#include <sys/stat.h>
void unsure_dir_exist(const char* path_to_file) {
char* temp_path = strdup(path_to_file);
for (char* p = temp_path + 1; *p; p++) {
if (*p == '/') {
*p = '\0';
int status = mkdir(temp_path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
if (status != 0 && errno != EEXIST) {
// handle error
break;
}
*p = '/';
}
}
free(temp_path);
}
// FIXME
void unpackAsset(AAssetManager* mgr, const char* filename, const std::string& path) {
AAsset* asset = AAssetManager_open(mgr, filename, AASSET_MODE_STREAMING);
if (asset == NULL) {
return;
}
off_t length = AAsset_getLength(asset);
char* buffer = new char[length];
AAsset_read(asset, buffer, length);
unsure_dir_exist(path.c_str());
FILE* out = fopen(path.c_str(), "w");
if (out != NULL) {
fwrite(buffer, length, 1, out);
fclose(out);
}
delete[] buffer;
AAsset_close(asset);
}
// FIXME
void unpackDirectory(AAssetManager* mgr, const char* dirname, const std::string& path) {
AAssetDir* assetDir = AAssetManager_openDir(mgr, dirname);
const char* filename = NULL;
while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) {
std::string assetPath = std::string(dirname) + "/" + filename;
std::string internalPath = path + "/" + std::string(dirname) + "/" + filename;
struct stat sb;
stat(assetPath.c_str(), &sb);
if (S_ISDIR(sb.st_mode)) {
unpackDirectory(mgr, assetPath.c_str(), internalPath);
}
else {
unpackAsset(mgr, assetPath.c_str(), internalPath);
}
}
AAssetDir_close(assetDir);
}
extern "C" {
// This is the main entry point of a native application that is using
// android_native_app_glue. It runs in its own thread, with its own
// event loop for receiving input events and doing other things.
void android_main(android_app* state) {
tp::print_env_info();
tp::alloc_init();
ANativeActivityCtx engine(state);
unpackDirectory(state->activity->assetManager, "", state->activity->internalDataPath);
unpackDirectory(state->activity->assetManager, "rsc", state->activity->internalDataPath);
unpackDirectory(state->activity->assetManager, "rsc/fonts", state->activity->internalDataPath);
android_ctx = &engine;
bool running = true;
while (running) {
engine.proc_events();
// whait until our app fully initialized
if (!engine.app->window) {
continue;
}
// run once
static bool main_thread_started = false;
if (!main_thread_started) {
// init types
g_android_internal_data_path = state->activity->internalDataPath;
// create main thread
pthread_create(&worker_thread, NULL, main_wrap, NULL);
pthread_mutex_init(&worker_finished_mutex, NULL);
pthread_cond_init(&worker_finished_cond, NULL);
main_thread_started = true;
continue;
}
// check for exit
pthread_mutex_lock(&worker_finished_mutex);
running = !worker_finished;
pthread_mutex_unlock(&worker_finished_mutex);
}
pthread_join(worker_thread, NULL);
tp::alloc_uninit();
}
};
#endif
// ------------------------------- Child thread --------------------------------------- //
#ifndef CHILD_THREAD
//#include <android/configuration.h>
//#include <android/native_activity.h>
AInputEvent* androidPlatformContextGetEvent(tp::glw::PlatformContext* ctx) {
return ctx->chache_event;
}
int32_t getDensityDpi(android_app* app) {
AConfiguration* config = AConfiguration_new();
AConfiguration_fromAssetManager(config, app->activity->assetManager);
int32_t density = AConfiguration_getDensity(config);
AConfiguration_delete(config);
return density;
}
// statics
void tp::glw::Window::init() {}
void tp::glw::Window::deinit() {}
void tp::glw::Window::initialize() {
mPlatformCtx = new PlatformContext(android_ctx->app->window);
applyAppearance();
AConfiguration* config = AConfiguration_new();
AConfiguration_fromAssetManager(config, android_ctx->app->activity->assetManager);
int32_t density = AConfiguration_getDensity(config);
AConfiguration_delete(config);
mDevice.mDPMM = density / 25.4f;
}
tp::glw::Window::Window() {
initialize();
pthread_mutex_lock(&mutex_event.mutex);
mutex_event.active_windw = this;
pthread_mutex_unlock(&mutex_event.mutex);
}
tp::glw::Window::Window(const Appearence& aAppearence) {
mAppearence = aAppearence;
initialize();
}
tp::glw::Window::~Window() {
delete mPlatformCtx;
}
void tp::glw::Window::applyAppearance() {
int width = ANativeWindow_getWidth(android_ctx->app->window);
int height = ANativeWindow_getHeight(android_ctx->app->window);
if (width != mAppearence.mSize.x || height != mAppearence.mSize.y) {
mEvents.mRedraw = 2;
}
mAppearence.mPos = mCache.mAppearencePrev.mPos = 0;
mAppearence.mSize.x = mCache.mAppearencePrev.mSize.x = tp::glw::Window::mDevice.Size.x = width;
mAppearence.mSize.y = mCache.mAppearencePrev.mSize.y = tp::glw::Window::mDevice.Size.y = height;
}
void tp::glw::Window::pollEvents() {
applyAppearance();
// check if parent thread has some events to pass
pthread_mutex_lock(&mutex_event.mutex);
bool has_event = mutex_event.parent_thread_has_events;
mutex_event.child_whaiting = has_event;
pthread_mutex_unlock(&mutex_event.mutex);
while (has_event) {
pthread_mutex_lock(&mutex_event.mutex);
has_event = mutex_event.parent_thread_has_events;
pthread_mutex_unlock(&mutex_event.mutex);
}
pthread_mutex_lock(&mutex_event.mutex);
mutex_event.child_whaiting = false;
pthread_mutex_unlock(&mutex_event.mutex);
}
void tp::glw::Window::platformCallback() {}
void tp::glw::Window::beginDraw() {
mPlatformCtx->beginDraw();
}
void tp::glw::Window::endDraw() {
mPlatformCtx->endDraw();
if (mEvents.mRedraw-- < 0) mEvents.mRedraw = 0;
}
void* tp::glw::Window::platform_window() const { return android_ctx->app->window; }
tp::alni tp::glw::Window::sizeAllocatedMem() { return 0; }
tp::alni tp::glw::Window::sizeUsedMem() { return 0; }
void* main_wrap(void* p) {
// exec main
main();
// mark as doen after completion
pthread_mutex_lock(&worker_finished_mutex);
worker_finished = true;
pthread_cond_signal(&worker_finished_cond);
pthread_mutex_unlock(&worker_finished_mutex);
// exit "main thread"
pthread_exit(NULL);
return NULL;
}
#endif

View file

@ -0,0 +1,453 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "android_native_app_glue.h"
#include <jni.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <android/log.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__))
/* For debug builds, always enable the debug traces in this library */
#ifndef NDEBUG
# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__))
#else
# define LOGV(...) ((void)0)
#endif
void free_saved_state(struct android_app* android_app) {
pthread_mutex_lock(&android_app->mutex);
if (android_app->savedState != NULL) {
free(android_app->savedState);
android_app->savedState = NULL;
android_app->savedStateSize = 0;
}
pthread_mutex_unlock(&android_app->mutex);
}
int8_t android_app_read_cmd(struct android_app* android_app) {
int8_t cmd;
if (read(android_app->msgread, &cmd, sizeof(cmd)) != sizeof(cmd)) {
LOGE("No data on command pipe!");
return -1;
}
if (cmd == APP_CMD_SAVE_STATE) free_saved_state(android_app);
return cmd;
}
void print_cur_config(struct android_app* android_app) {
char lang[2], country[2];
AConfiguration_getLanguage(android_app->config, lang);
AConfiguration_getCountry(android_app->config, country);
LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d "
"keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d "
"modetype=%d modenight=%d",
AConfiguration_getMcc(android_app->config),
AConfiguration_getMnc(android_app->config),
lang[0], lang[1], country[0], country[1],
AConfiguration_getOrientation(android_app->config),
AConfiguration_getTouchscreen(android_app->config),
AConfiguration_getDensity(android_app->config),
AConfiguration_getKeyboard(android_app->config),
AConfiguration_getNavigation(android_app->config),
AConfiguration_getKeysHidden(android_app->config),
AConfiguration_getNavHidden(android_app->config),
AConfiguration_getSdkVersion(android_app->config),
AConfiguration_getScreenSize(android_app->config),
AConfiguration_getScreenLong(android_app->config),
AConfiguration_getUiModeType(android_app->config),
AConfiguration_getUiModeNight(android_app->config));
}
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) {
switch (cmd) {
case APP_CMD_INPUT_CHANGED:
LOGV("APP_CMD_INPUT_CHANGED");
pthread_mutex_lock(&android_app->mutex);
if (android_app->inputQueue != NULL) {
AInputQueue_detachLooper(android_app->inputQueue);
}
android_app->inputQueue = android_app->pendingInputQueue;
if (android_app->inputQueue != NULL) {
LOGV("Attaching input queue to looper");
AInputQueue_attachLooper(android_app->inputQueue,
android_app->looper, LOOPER_ID_INPUT, NULL,
&android_app->inputPollSource);
}
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
break;
case APP_CMD_INIT_WINDOW:
LOGV("APP_CMD_INIT_WINDOW");
pthread_mutex_lock(&android_app->mutex);
android_app->window = android_app->pendingWindow;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
break;
case APP_CMD_TERM_WINDOW:
LOGV("APP_CMD_TERM_WINDOW");
pthread_cond_broadcast(&android_app->cond);
break;
case APP_CMD_RESUME:
case APP_CMD_START:
case APP_CMD_PAUSE:
case APP_CMD_STOP:
LOGV("activityState=%d", cmd);
pthread_mutex_lock(&android_app->mutex);
android_app->activityState = cmd;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
break;
case APP_CMD_CONFIG_CHANGED:
LOGV("APP_CMD_CONFIG_CHANGED");
AConfiguration_fromAssetManager(android_app->config,
android_app->activity->assetManager);
print_cur_config(android_app);
break;
case APP_CMD_DESTROY:
LOGV("APP_CMD_DESTROY");
android_app->destroyRequested = 1;
break;
}
}
void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) {
switch (cmd) {
case APP_CMD_TERM_WINDOW:
LOGV("APP_CMD_TERM_WINDOW");
pthread_mutex_lock(&android_app->mutex);
android_app->window = NULL;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
break;
case APP_CMD_SAVE_STATE:
LOGV("APP_CMD_SAVE_STATE");
pthread_mutex_lock(&android_app->mutex);
android_app->stateSaved = 1;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
break;
case APP_CMD_RESUME:
free_saved_state(android_app);
break;
}
}
void android_app_destroy(struct android_app* android_app) {
LOGV("android_app_destroy!");
free_saved_state(android_app);
pthread_mutex_lock(&android_app->mutex);
if (android_app->inputQueue != NULL) {
AInputQueue_detachLooper(android_app->inputQueue);
}
AConfiguration_delete(android_app->config);
android_app->destroyed = 1;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
// Can't touch android_app object after this.
}
void process_input(struct android_app* app, struct android_poll_source* source) {
AInputEvent* event = NULL;
while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
LOGV("New input event: type=%d", AInputEvent_getType(event));
if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {
continue;
}
int32_t handled = 0;
if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
AInputQueue_finishEvent(app->inputQueue, event, handled);
}
}
void process_cmd(struct android_app* app, struct android_poll_source* source) {
int8_t cmd = android_app_read_cmd(app);
android_app_pre_exec_cmd(app, cmd);
if (app->onAppCmd != NULL) app->onAppCmd(app, cmd);
android_app_post_exec_cmd(app, cmd);
}
void* android_app_entry(void* param) {
struct android_app* android_app = (struct android_app*)param;
android_app->config = AConfiguration_new();
AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager);
print_cur_config(android_app);
android_app->cmdPollSource.id = LOOPER_ID_MAIN;
android_app->cmdPollSource.app = android_app;
android_app->cmdPollSource.process = process_cmd;
android_app->inputPollSource.id = LOOPER_ID_INPUT;
android_app->inputPollSource.app = android_app;
android_app->inputPollSource.process = process_input;
ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL,
&android_app->cmdPollSource);
android_app->looper = looper;
pthread_mutex_lock(&android_app->mutex);
android_app->running = 1;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
android_main(android_app);
android_app_destroy(android_app);
return NULL;
}
// --------------------------------------------------------------------
// Native activity interaction (called from main thread)
// --------------------------------------------------------------------
struct android_app* android_app_create(ANativeActivity* activity,
void* savedState, size_t savedStateSize) {
struct android_app* android_app = calloc(1, sizeof(struct android_app));
android_app->activity = activity;
pthread_mutex_init(&android_app->mutex, NULL);
pthread_cond_init(&android_app->cond, NULL);
if (savedState != NULL) {
android_app->savedState = malloc(savedStateSize);
android_app->savedStateSize = savedStateSize;
memcpy(android_app->savedState, savedState, savedStateSize);
}
int msgpipe[2];
if (pipe(msgpipe)) {
LOGE("could not create pipe: %s", strerror(errno));
return NULL;
}
android_app->msgread = msgpipe[0];
android_app->msgwrite = msgpipe[1];
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&android_app->thread, &attr, android_app_entry, android_app);
// Wait for thread to start.
pthread_mutex_lock(&android_app->mutex);
while (!android_app->running) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
pthread_mutex_unlock(&android_app->mutex);
return android_app;
}
void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {
LOGE("Failure writing android_app cmd: %s", strerror(errno));
}
}
void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) {
pthread_mutex_lock(&android_app->mutex);
android_app->pendingInputQueue = inputQueue;
android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);
while (android_app->inputQueue != android_app->pendingInputQueue) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
pthread_mutex_unlock(&android_app->mutex);
}
void android_app_set_window(struct android_app* android_app, ANativeWindow* window) {
pthread_mutex_lock(&android_app->mutex);
if (android_app->pendingWindow != NULL) {
android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW);
}
android_app->pendingWindow = window;
if (window != NULL) {
android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW);
}
while (android_app->window != android_app->pendingWindow) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
pthread_mutex_unlock(&android_app->mutex);
}
void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) {
pthread_mutex_lock(&android_app->mutex);
android_app_write_cmd(android_app, cmd);
while (android_app->activityState != cmd) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
pthread_mutex_unlock(&android_app->mutex);
}
void android_app_free(struct android_app* android_app) {
pthread_mutex_lock(&android_app->mutex);
android_app_write_cmd(android_app, APP_CMD_DESTROY);
while (!android_app->destroyed) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
pthread_mutex_unlock(&android_app->mutex);
close(android_app->msgread);
close(android_app->msgwrite);
pthread_cond_destroy(&android_app->cond);
pthread_mutex_destroy(&android_app->mutex);
free(android_app);
}
struct android_app* ToApp(ANativeActivity* activity) {
return (struct android_app*) activity->instance;
}
void onDestroy(ANativeActivity* activity) {
LOGV("Destroy: %p", activity);
android_app_free(ToApp(activity));
}
void onStart(ANativeActivity* activity) {
LOGV("Start: %p", activity);
android_app_set_activity_state(ToApp(activity), APP_CMD_START);
}
void onResume(ANativeActivity* activity) {
LOGV("Resume: %p", activity);
android_app_set_activity_state(ToApp(activity), APP_CMD_RESUME);
}
void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {
LOGV("SaveInstanceState: %p", activity);
struct android_app* android_app = ToApp(activity);
void* savedState = NULL;
pthread_mutex_lock(&android_app->mutex);
android_app->stateSaved = 0;
android_app_write_cmd(android_app, APP_CMD_SAVE_STATE);
while (!android_app->stateSaved) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
if (android_app->savedState != NULL) {
savedState = android_app->savedState;
*outLen = android_app->savedStateSize;
android_app->savedState = NULL;
android_app->savedStateSize = 0;
}
pthread_mutex_unlock(&android_app->mutex);
return savedState;
}
void onPause(ANativeActivity* activity) {
LOGV("Pause: %p", activity);
android_app_set_activity_state(ToApp(activity), APP_CMD_PAUSE);
}
void onStop(ANativeActivity* activity) {
LOGV("Stop: %p", activity);
android_app_set_activity_state(ToApp(activity), APP_CMD_STOP);
}
void onConfigurationChanged(ANativeActivity* activity) {
LOGV("ConfigurationChanged: %p", activity);
android_app_write_cmd(ToApp(activity), APP_CMD_CONFIG_CHANGED);
}
void onContentRectChanged(ANativeActivity* activity, const ARect* r) {
LOGV("ContentRectChanged: l=%d,t=%d,r=%d,b=%d", r->left, r->top, r->right, r->bottom);
struct android_app* android_app = ToApp(activity);
pthread_mutex_lock(&android_app->mutex);
android_app->contentRect = *r;
pthread_mutex_unlock(&android_app->mutex);
android_app_write_cmd(ToApp(activity), APP_CMD_CONTENT_RECT_CHANGED);
}
void onLowMemory(ANativeActivity* activity) {
LOGV("LowMemory: %p", activity);
android_app_write_cmd(ToApp(activity), APP_CMD_LOW_MEMORY);
}
void onWindowFocusChanged(ANativeActivity* activity, int focused) {
LOGV("WindowFocusChanged: %p -- %d", activity, focused);
android_app_write_cmd(ToApp(activity), focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
}
void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
LOGV("NativeWindowCreated: %p -- %p", activity, window);
android_app_set_window(ToApp(activity), window);
}
void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
LOGV("NativeWindowDestroyed: %p -- %p", activity, window);
android_app_set_window(ToApp(activity), NULL);
}
void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* window) {
LOGV("NativeWindowRedrawNeeded: %p -- %p", activity, window);
android_app_write_cmd(ToApp(activity), APP_CMD_WINDOW_REDRAW_NEEDED);
}
void onNativeWindowResized(ANativeActivity* activity, ANativeWindow* window) {
LOGV("NativeWindowResized: %p -- %p", activity, window);
android_app_write_cmd(ToApp(activity), APP_CMD_WINDOW_RESIZED);
}
void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
LOGV("InputQueueCreated: %p -- %p", activity, queue);
android_app_set_input(ToApp(activity), queue);
}
void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
LOGV("InputQueueDestroyed: %p -- %p", activity, queue);
android_app_set_input(ToApp(activity), NULL);
}
void ILOVEU_ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize) {
LOGV("Creating: %p", activity);
activity->callbacks->onConfigurationChanged = onConfigurationChanged;
activity->callbacks->onContentRectChanged = onContentRectChanged;
activity->callbacks->onDestroy = onDestroy;
activity->callbacks->onInputQueueCreated = onInputQueueCreated;
activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
activity->callbacks->onLowMemory = onLowMemory;
activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded;
activity->callbacks->onNativeWindowResized = onNativeWindowResized;
activity->callbacks->onPause = onPause;
activity->callbacks->onResume = onResume;
activity->callbacks->onSaveInstanceState = onSaveInstanceState;
activity->callbacks->onStart = onStart;
activity->callbacks->onStop = onStop;
activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
activity->instance = android_app_create(activity, savedState, savedStateSize);
}

View file

@ -0,0 +1,350 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <poll.h>
#include <pthread.h>
#include <sched.h>
#include <android/configuration.h>
#include <android/looper.h>
#include <android/native_activity.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* The native activity interface provided by <android/native_activity.h>
* is based on a set of application-provided callbacks that will be called
* by the Activity's main thread when certain events occur.
*
* This means that each one of this callbacks _should_ _not_ block, or they
* risk having the system force-close the application. This programming
* model is direct, lightweight, but constraining.
*
* The 'android_native_app_glue' static library is used to provide a different
* execution model where the application can implement its own main event
* loop in a different thread instead. Here's how it works:
*
* 1/ The application must provide a function named "android_main()" that
* will be called when the activity is created, in a new thread that is
* distinct from the activity's main thread.
*
* 2/ android_main() receives a pointer to a valid "android_app" structure
* that contains references to other important objects, e.g. the
* ANativeActivity obejct instance the application is running in.
*
* 3/ the "android_app" object holds an ALooper instance that already
* listens to two important things:
*
* - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX
* declarations below.
*
* - input events coming from the AInputQueue attached to the activity.
*
* Each of these correspond to an ALooper identifier returned by
* ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT,
* respectively.
*
* Your application can use the same ALooper to listen to additional
* file-descriptors. They can either be callback based, or with return
* identifiers starting with LOOPER_ID_USER.
*
* 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event,
* the returned data will point to an android_poll_source structure. You
* can call the process() function on it, and fill in android_app->onAppCmd
* and android_app->onInputEvent to be called for your own processing
* of the event.
*
* Alternatively, you can call the low-level functions to read and process
* the data directly... look at the process_cmd() and process_input()
* implementations in the glue to see how to do this.
*
* See the sample named "native-activity" that comes with the NDK with a
* full usage example. Also look at the JavaDoc of NativeActivity.
*/
struct android_app;
/**
* Data associated with an ALooper fd that will be returned as the "outData"
* when that source has data ready.
*/
struct android_poll_source {
// The identifier of this source. May be LOOPER_ID_MAIN or
// LOOPER_ID_INPUT.
int32_t id;
// The android_app this ident is associated with.
struct android_app* app;
// Function to call to perform the standard processing of data from
// this source.
void (*process)(struct android_app* app, struct android_poll_source* source);
};
/**
* This is the interface for the standard glue code of a threaded
* application. In this model, the application's code is running
* in its own thread separate from the main thread of the process.
* It is not required that this thread be associated with the Java
* VM, although it will need to be in order to make JNI calls any
* Java objects.
*/
struct android_app {
// The application can place a pointer to its own state object
// here if it likes.
void* userData;
// Fill this in with the function to process main app commands (APP_CMD_*)
void (*onAppCmd)(struct android_app* app, int32_t cmd);
// Fill this in with the function to process input events. At this point
// the event has already been pre-dispatched, and it will be finished upon
// return. Return 1 if you have handled the event, 0 for any default
// dispatching.
int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
// The ANativeActivity object instance that this app is running in.
ANativeActivity* activity;
// The current configuration the app is running in.
AConfiguration* config;
// This is the last instance's saved state, as provided at creation time.
// It is NULL if there was no state. You can use this as you need; the
// memory will remain around until you call android_app_exec_cmd() for
// APP_CMD_RESUME, at which point it will be freed and savedState set to NULL.
// These variables should only be changed when processing a APP_CMD_SAVE_STATE,
// at which point they will be initialized to NULL and you can malloc your
// state and place the information here. In that case the memory will be
// freed for you later.
void* savedState;
size_t savedStateSize;
// The ALooper associated with the app's thread.
ALooper* looper;
// When non-NULL, this is the input queue from which the app will
// receive user input events.
AInputQueue* inputQueue;
// When non-NULL, this is the window surface that the app can draw in.
ANativeWindow* window;
// Current content rectangle of the window; this is the area where the
// window's content should be placed to be seen by the user.
ARect contentRect;
// Current state of the app's activity. May be either APP_CMD_START,
// APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
int activityState;
// This is non-zero when the application's NativeActivity is being
// destroyed and waiting for the app thread to complete.
int destroyRequested;
// -------------------------------------------------
// Below are "private" implementation of the glue code.
pthread_mutex_t mutex;
pthread_cond_t cond;
int msgread;
int msgwrite;
pthread_t thread;
struct android_poll_source cmdPollSource;
struct android_poll_source inputPollSource;
int running;
int stateSaved;
int destroyed;
int redrawNeeded;
AInputQueue* pendingInputQueue;
ANativeWindow* pendingWindow;
ARect pendingContentRect;
};
enum {
/**
* Looper data ID of commands coming from the app's main thread, which
* is returned as an identifier from ALooper_pollOnce(). The data for this
* identifier is a pointer to an android_poll_source structure.
* These can be retrieved and processed with android_app_read_cmd()
* and android_app_exec_cmd().
*/
LOOPER_ID_MAIN = 1,
/**
* Looper data ID of events coming from the AInputQueue of the
* application's window, which is returned as an identifier from
* ALooper_pollOnce(). The data for this identifier is a pointer to an
* android_poll_source structure. These can be read via the inputQueue
* object of android_app.
*/
LOOPER_ID_INPUT = 2,
/**
* Start of user-defined ALooper identifiers.
*/
LOOPER_ID_USER = 3,
};
enum {
/**
* Command from main thread: the AInputQueue has changed. Upon processing
* this command, android_app->inputQueue will be updated to the new queue
* (or NULL).
*/
APP_CMD_INPUT_CHANGED,
/**
* Command from main thread: a new ANativeWindow is ready for use. Upon
* receiving this command, android_app->window will contain the new window
* surface.
*/
APP_CMD_INIT_WINDOW,
/**
* Command from main thread: the existing ANativeWindow needs to be
* terminated. Upon receiving this command, android_app->window still
* contains the existing window; after calling android_app_exec_cmd
* it will be set to NULL.
*/
APP_CMD_TERM_WINDOW,
/**
* Command from main thread: the current ANativeWindow has been resized.
* Please redraw with its new size.
*/
APP_CMD_WINDOW_RESIZED,
/**
* Command from main thread: the system needs that the current ANativeWindow
* be redrawn. You should redraw the window before handing this to
* android_app_exec_cmd() in order to avoid transient drawing glitches.
*/
APP_CMD_WINDOW_REDRAW_NEEDED,
/**
* Command from main thread: the content area of the window has changed,
* such as from the soft input window being shown or hidden. You can
* find the new content rect in android_app::contentRect.
*/
APP_CMD_CONTENT_RECT_CHANGED,
/**
* Command from main thread: the app's activity window has gained
* input focus.
*/
APP_CMD_GAINED_FOCUS,
/**
* Command from main thread: the app's activity window has lost
* input focus.
*/
APP_CMD_LOST_FOCUS,
/**
* Command from main thread: the current device configuration has changed.
*/
APP_CMD_CONFIG_CHANGED,
/**
* Command from main thread: the system is running low on memory.
* Try to reduce your memory use.
*/
APP_CMD_LOW_MEMORY,
/**
* Command from main thread: the app's activity has been started.
*/
APP_CMD_START,
/**
* Command from main thread: the app's activity has been resumed.
*/
APP_CMD_RESUME,
/**
* Command from main thread: the app should generate a new saved state
* for itself, to restore from later if needed. If you have saved state,
* allocate it with malloc and place it in android_app.savedState with
* the size in android_app.savedStateSize. The will be freed for you
* later.
*/
APP_CMD_SAVE_STATE,
/**
* Command from main thread: the app's activity has been paused.
*/
APP_CMD_PAUSE,
/**
* Command from main thread: the app's activity has been stopped.
*/
APP_CMD_STOP,
/**
* Command from main thread: the app's activity is being destroyed,
* and waiting for the app thread to clean up and exit before proceeding.
*/
APP_CMD_DESTROY,
};
/**
* Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next
* app command message.
*/
int8_t android_app_read_cmd(struct android_app* android_app);
/**
* Call with the command returned by android_app_read_cmd() to do the
* initial pre-processing of the given command. You can perform your own
* actions for the command after calling this function.
*/
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd);
/**
* Call with the command returned by android_app_read_cmd() to do the
* final post-processing of the given command. You must have done your own
* actions for the command before calling this function.
*/
void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd);
/**
* No-op function that used to be used to prevent the linker from stripping app
* glue code. No longer necessary, since __attribute__((visibility("default")))
* does this for us.
*/
__attribute__((
deprecated("Calls to app_dummy are no longer necessary. See "
"https://github.com/android-ndk/ndk/issues/381."))) void
app_dummy();
/**
* This is the function that application code must implement, representing
* the main entry to the app.
*/
extern void android_main(struct android_app* app);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,115 @@
#include "animations.h"
#include "timer.h"
using namespace tp;
using namespace glw;
bool tp::glw::gInTransition = false;
halnf AnimValue::interpolate() const {
if (!mTimeAnim) {
return mVal;
}
auto dt = gCurrentTime - mTimeStart;
if (dt > mTimeAnim) dt = mTimeAnim;
auto t = (halnf)dt / 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() {}
void AnimValue::setAnimTime(halni time) {
mTimeAnim = time;
}
AnimValue::AnimValue(halnf val) {
mVal = val;
mValPrev = mVal;
mTimeStart = gCurrentTime;
}
bool AnimValue::inTransition() const {
auto time_pased = gCurrentTime - mTimeStart >= mTimeAnim;
return !time_pased;
}
void AnimValue::set(halnf val) {
if (!inTransition()) {
mValPrev = mVal;
}
if (val == mVal) {
return;
}
mValPrev = get();
mVal = val;
if (!inTransition()) {
mTimeStart = (halni)gCurrentTime;
}
}
halnf AnimValue::getTarget() const {
return mVal;
}
void AnimValue::setNoTransition(halnf val) {
mValPrev = val;
mVal = val;
mTimeStart -= mTimeStart;
}
halnf AnimValue::get() const {
if (inTransition()) {
gInTransition = true;
}
return interpolate();
}
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);
}
rgba AnimColor::get() const {
auto col = mColor.get();
return rgba(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));
}

View file

@ -0,0 +1,378 @@
#include "canvas.h"
#include "GraphicsLibApi.h"
#ifdef ENV_OS_ANDROID
const char* get_android_abs_path(const char* path, bool second = false);
#define NANOVG_GLES3_IMPLEMENTATION // Use GLES3 implementation.
#else
#define NANOVG_GL3_IMPLEMENTATION // Use GL3 implementation.
#endif
#include "nanovg.h"
#include "nanovg_gl.h"
#include "nanovg_gl_utils.h"
using namespace tp;
using namespace glw;
#define NVG ((NVGcontext*) mCtx)
static const char* getFontPath() {
#ifdef ENV_OS_ANDROID
return get_android_abs_path("rsc/fonts/CONSOLAB.TTF");
#else
return "./rsc/fonts/CONSOLAB.TTF";
#endif
}
Canvas::Canvas() {
// create context
mCtx =
#ifdef ENV_OS_ANDROID
nvgCreateGLES3
#else
nvgCreateGL3
#endif
(NVG_ANTIALIAS | NVG_STENCIL_STROKES
#ifdef ENV_BUILD_DEBUG
| NVG_DEBUG
#endif
);
mColorPrimary = rgba(0.5f, 0.5f, 0.5f, 0.9f);
mColorSecondary = rgba(0.2f, 0.2f, 0.2f, 0.9f);
nvgCreateFont(NVG, "basic", getFontPath());
}
Canvas::Val& Canvas::convert2pxls(Val& val) {
val = val * mDpmm * mUIScale;
return val;
}
Canvas::Val Canvas::as2pxls(Val val) {
return val * mDpmm * mUIScale;
}
Canvas::Rect& Canvas::convert2pxls(Rect& rec) {
convert2pxls(rec.x);
convert2pxls(rec.y);
convert2pxls(rec.z);
convert2pxls(rec.w);
return rec;
}
Canvas::Vec2& Canvas::convert2pxls(Vec2& vec) {
convert2pxls(vec.x);
convert2pxls(vec.y);
return vec;
}
void Canvas::beginDraw(Rect viewport, tp::halnf dpmm, tp::halnf uiscale) {
convert2pxls(viewport);
nvgBeginFrame(NVG, viewport.size.x, viewport.size.y, 1);
mVieport = { 0.f, 0.f, viewport.size.x, viewport.size.y };
glViewport((GLsizei)mVieport.x, (GLsizei)mVieport.y, (GLsizei)mVieport.size.x, (GLsizei)mVieport.size.y);
mDpmm = dpmm;
mUIScale = tp::clamp(uiscale, 0.03f, 100.f);
mClamping = mVieport;
}
void Canvas::resetViewport() {
glViewport((GLsizei)mVieport.x, (GLsizei)mVieport.y, (GLsizei)mVieport.size.x, (GLsizei)mVieport.size.y);
}
void Canvas::clear(Col color) {
glClearColor(color.r, color.g, color.b, color.a);
//glClearDepth(0.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void Canvas::endDraw() {
nvgEndFrame(NVG);
}
void Canvas::setClamping(Rect rec) {
mClamping = rec;
convert2pxls(rec);
nvgScissor(NVG, rec.x, rec.y, rec.z, rec.w);
}
void Canvas::setCol1(const Col& col) {
mColorPrimary = col;
}
void Canvas::setCol2(const Col& col) {
mColorSecondary = col;
}
void Canvas::rect(Rect rec, halnf rounding, halnf borders) {
convert2pxls(rec);
convert2pxls(rounding);
convert2pxls(borders);
if (borders) {
nvgBeginPath(NVG);
auto borders_rec = rec;
rec.pos += borders;
rec.size -= borders * 2;
if (rounding) {
nvgRoundedRect(NVG, borders_rec.x, borders_rec.y, borders_rec.z, borders_rec.w, rounding);
}
else {
nvgRect(NVG, borders_rec.x, borders_rec.y, borders_rec.z, borders_rec.w);
}
nvgFillColor(NVG, nvgRGBAf(mColorSecondary.r, mColorSecondary.g, mColorSecondary.b, mColorSecondary.a));
nvgFill(NVG);
}
nvgBeginPath(NVG);
if (rounding) {
nvgRoundedRect(NVG, rec.x, rec.y, rec.z, rec.w, rounding);
}
else {
nvgRect(NVG, rec.x, rec.y, rec.z, rec.w);
}
nvgFillColor(NVG, nvgRGBAf(mColorPrimary.r, mColorPrimary.g, mColorPrimary.b, mColorPrimary.a));
nvgFill(NVG);
}
void Canvas::line(Vec2 p1, Vec2 p2, halnf thikness) {
convert2pxls(p1);
convert2pxls(p2);
convert2pxls(thikness);
nvgBeginPath(NVG);
nvgMoveTo(NVG, p1.x, p1.y);
nvgLineTo(NVG, p2.x, p2.y);
nvgStrokeColor(NVG, nvgRGBAf(mColorPrimary.r, mColorPrimary.g, mColorPrimary.b, mColorPrimary.a));
nvgStrokeWidth(NVG, thikness);
nvgStroke(NVG);
}
void Canvas::trig(Vec2 p1, Vec2 p2, Vec2 p3) {
convert2pxls(p1);
convert2pxls(p2);
convert2pxls(p3);
nvgBeginPath(NVG);
nvgMoveTo(NVG, p1.x, p1.y);
nvgLineTo(NVG, p2.x, p2.y);
nvgLineTo(NVG, p3.x, p3.y);
nvgFillColor(NVG, nvgRGBAf(mColorPrimary.r, mColorPrimary.g, mColorPrimary.b, mColorPrimary.a));
nvgFill(NVG);
}
void Canvas::circle(Vec2 rec, halnf radius, halnf borders) {
convert2pxls(rec);
convert2pxls(radius);
convert2pxls(borders);
DBG_BREAK(1);
}
void Canvas::text(const char* start, const char* end, Rect rec, halnf size, Align align) {
convert2pxls(rec);
convert2pxls(size);
nvgFillColor(NVG, nvgRGBAf(mColorPrimary.r, mColorPrimary.g, mColorPrimary.b, mColorPrimary.a));
nvgFontSize(NVG, size);
nvgTextAlign(NVG, NVGalign(align));
auto y = (align & Align::MIDDLE) ? rec.y + rec.w / 2 : rec.y;
auto x = (align & Align::CENTER) ? rec.x + rec.z / 2 : rec.x;
nvgText(NVG, x, y, start, end);
}
void Canvas::text(const string text, Rect rec, halnf size, Align align) {
convert2pxls(rec);
convert2pxls(size);
nvgFillColor(NVG, nvgRGBAf(mColorPrimary.r, mColorPrimary.g, mColorPrimary.b, mColorPrimary.a));
nvgFontSize(NVG, size);
nvgTextAlign(NVG, NVGalign(align));
//nvgTextBounds(NVG, );
auto t_mid = rec.y + rec.w / 2;
auto t_top = rec.y;
auto res = bool(align & Align::MIDDLE);
auto y = res ? t_mid : t_top;
auto x_mid = rec.x + rec.z / 2;
auto x_left = rec.x;
res = bool(align & Align::CENTER);
auto x = res ? x_mid : x_left;
nvgText(NVG, x, y, text.cstr(), text.cstr() + text.size());
}
void Canvas::ImageHandle::createFromBuff(glw::fbuffer* buff, Canvas* drawer) {
this->~ImageHandle();
auto const size = buff->getSize();
#ifdef ENV_OS_ANDROID
mId = nvglCreateImageFromHandleGLES3((NVGcontext*)drawer->mCtx, buff->texId(), size.x, size.y, 0);
#else
mId = nvglCreateImageFromHandleGL3((NVGcontext*)drawer->mCtx, buff->texId(), (halni) size.x, (halni) size.y, 0);
#endif
}
void Canvas::ImageHandle::free(Canvas* drawer) {
if (mId && (NVGcontext*)drawer->mCtx) {
nvgDeleteImage((NVGcontext*)drawer->mCtx, mId);
}
}
Canvas::ImageHandle::~ImageHandle() {}
void Canvas::drawImage(Rect rec, ImageHandle* image, halnf angle, halnf alpha, halnf rounding) {
convert2pxls(rec);
convert2pxls(rounding);
auto imgPaint = nvgImagePattern(NVG, rec.x, rec.y, rec.z, rec.w, angle, image->mId, alpha);
nvgBeginPath(NVG);
nvgRoundedRect(NVG, rec.x, rec.y, rec.z, rec.w, rounding);
nvgFillPaint(NVG, imgPaint);
nvgFill(NVG);
}
void Canvas::drawColorwheel(Rect rec, const rgb& col) {
convert2pxls(rec);
float const x = rec.x;
float const y = rec.y;
float const w = rec.z;
float const h = rec.w;
hsv hsv = tp::hsv(col);
float const hue = hsv.h / (NVG_PI * 2);
int i;
float r0, r1, ax, ay, bx, by, cx, cy, aeps, r;
NVGpaint paint;
nvgSave(NVG);
cx = x + w * 0.5f;
cy = y + h * 0.5f;
r1 = (w < h ? w : h) * 0.5f - as2pxls(1.0f);
r0 = r1 - as2pxls(3.0f);
aeps = 0.5f / r1; // half a pixel arc length in radians (2pi cancels out).
for (i = 0; i < 6; i++) {
float a0 = (float)i / 6.0f * NVG_PI * 2.0f - aeps;
float a1 = (float)(i + 1.0f) / 6.0f * NVG_PI * 2.0f + aeps;
nvgBeginPath(NVG);
nvgArc(NVG, cx, cy, r0, a0, a1, NVG_CW);
nvgArc(NVG, cx, cy, r1, a1, a0, NVG_CCW);
nvgClosePath(NVG);
ax = cx + cosf(a0) * (r0 + r1) * 0.5f;
ay = cy + sinf(a0) * (r0 + r1) * 0.5f;
bx = cx + cosf(a1) * (r0 + r1) * 0.5f;
by = cy + sinf(a1) * (r0 + r1) * 0.5f;
paint = nvgLinearGradient(NVG, ax, ay, bx, by, nvgHSLA(a0 / (NVG_PI * 2), 1.0f, 0.55f, 255), nvgHSLA(a1 / (NVG_PI * 2), 1.0f, 0.55f, 255));
nvgFillPaint(NVG, paint);
nvgFill(NVG);
}
nvgBeginPath(NVG);
nvgCircle(NVG, cx, cy, r0 - 0.5f);
nvgCircle(NVG, cx, cy, r1 + 0.5f);
nvgStrokeColor(NVG, nvgRGBA(0, 0, 0, 64));
nvgStrokeWidth(NVG, 1.0f);
nvgStroke(NVG);
// Selector
nvgSave(NVG);
nvgTranslate(NVG, cx, cy);
nvgRotate(NVG, hue * NVG_PI * 2);
// Marker on
nvgStrokeWidth(NVG, 2.0f);
nvgBeginPath(NVG);
nvgRect(NVG, r0 - 1, -3, r1 - r0 + 2, 6);
nvgStrokeColor(NVG, nvgRGBA(255, 255, 255, 192));
nvgStroke(NVG);
paint = nvgBoxGradient(NVG, r0 - 3, -5, r1 - r0 + 6, 10, 2, 4, nvgRGBA(0, 0, 0, 128), nvgRGBA(0, 0, 0, 0));
nvgBeginPath(NVG);
nvgRect(NVG, r0 - 2 - 10, -4 - 10, r1 - r0 + 4 + 20, 8 + 20);
nvgRect(NVG, r0 - 2, -4, r1 - r0 + 4, 8);
nvgPathWinding(NVG, NVG_HOLE);
nvgFillPaint(NVG, paint);
nvgFill(NVG);
// Center triangle
r = r0 - 6;
ax = cosf(120.0f / 180.0f * NVG_PI) * r;
ay = sinf(120.0f / 180.0f * NVG_PI) * r;
bx = cosf(-120.0f / 180.0f * NVG_PI) * r;
by = sinf(-120.0f / 180.0f * NVG_PI) * r;
nvgBeginPath(NVG);
nvgMoveTo(NVG, r, 0);
nvgLineTo(NVG, ax, ay);
nvgLineTo(NVG, bx, by);
nvgClosePath(NVG);
paint = nvgLinearGradient(NVG, r, 0, ax, ay, nvgHSLA(hue, 1.0f, 0.5f, 255), nvgRGBA(255, 255, 255, 255));
nvgFillPaint(NVG, paint);
nvgFill(NVG);
paint = nvgLinearGradient(NVG, (r + ax) * 0.5f, (0 + ay) * 0.5f, bx, by, nvgRGBA(0, 0, 0, 0), nvgRGBA(0, 0, 0, 255));
nvgFillPaint(NVG, paint);
nvgFill(NVG);
nvgStrokeColor(NVG, nvgRGBA(0, 0, 0, 64));
nvgStroke(NVG);
// Select circle on triangle
auto inner = as2pxls(3);
//auto outter = as2pxls(5);
float yt = hsv.v * hsv.s;
float xt = hsv.v - 0.5f * yt;
ay = sinf(120.0f / 180.0f * NVG_PI) * r * (-1.0f + xt * 2.0f);
ax = cosf(120.0f / 180.0f * NVG_PI) * r * (1.0f - yt * 3.f);
nvgStrokeWidth(NVG, as2pxls(0.6f));
nvgBeginPath(NVG);
nvgCircle(NVG, ax, ay, inner);
nvgStrokeColor(NVG, nvgRGBA(255, 255, 255, 192));
nvgStroke(NVG);
//paint = nvgRadialGradient(NVG, ax, ay, 4, 9, nvgRGBA(0, 0, 0, 64), nvgRGBA(0, 0, 0, 0));
//nvgBeginPath(NVG);
//nvgRect(NVG, ax - outter, ay - outter, outter * 2, outter * 2);
//nvgCircle(NVG, ax, ay, outter);
//nvgPathWinding(NVG, NVG_HOLE);
//nvgFillPaint(NVG, paint);
//nvgFill(NVG);
nvgRestore(NVG);
nvgRestore(NVG);
}
Canvas::~Canvas() {
if (NVG) {
#ifdef ENV_OS_ANDROID
nvgDeleteGLES3(NVG);
#else
nvgDeleteGL3(NVG);
#endif
}
mCtx = NULL;
}

View file

@ -0,0 +1,877 @@
#include "debugui.h"
#include "typelist.h"
#include "stringt.h"
#include "stack.h"
#include "npple.h"
#include "rect.h"
#include "map.h"
#include "imgui.h"
#include "imgui_internal.h"
#include "implot.h"
// -------------- Platform Includes ---------------------- //
#if defined ENV_OS_WINDOWS
#include "backends/imgui_impl_opengl3.h"
#include "backends/imgui_impl_win32.h"
#include <Windows.h>
#elif defined ENV_OS_LINUX
#include "backends/imgui_impl_opengl3.h"
#include "backends/imgui_impl_glfw.h"
#elif defined ENV_OS_ANDROID
#include "backends/imgui_impl_opengl3.h"
#include "backends/imgui_impl_android.h"
#include <android/sensor.h>
#include <android/log.h>
#include <android/input.h>
#include <string.h>
#endif
#if defined ENV_OS_WINDOWS
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
extern HWND windowsPlatformContextGetNativeWindow(tp::glw::PlatformContext* ctx);
extern UINT windowsPlatformContextGetMessage(tp::glw::PlatformContext* ctx);
extern WPARAM windowsPlatformContextGetWparam(tp::glw::PlatformContext* ctx);
extern LRESULT windowsPlatformContextGetLparam(tp::glw::PlatformContext* ctx);
#elif defined ENV_OS_LINUX
#elif defined ENV_OS_ANDROID
extern AInputEvent* androidPlatformContextGetEvent(tp::glw::PlatformContext* ctx);
extern const char* get_android_abs_path(const char* path, bool second = false);
const char* AndroidGetImGuiIniPath() {
static char imgui_path[512];
auto tmp = get_android_abs_path("imgui.ini");
memcpy(imgui_path, tmp, strlen(tmp));
return imgui_path;
}
#endif
static const char* getFontPath() {
#ifdef ENV_OS_ANDROID
return get_android_abs_path("rsc/fonts/CONSOLAB.TTF");
#else
return "./rsc/fonts/CONSOLAB.TTF";
#endif
}
namespace tp {
namespace glw {
struct DebugUiInternalContext {
DebugUiDrawCallBack* cb = NULL;
void* cd = NULL;
ImGuiContext* ui_context = NULL;
ImGuiContext* vk_context = NULL;
bool initialized = false;
bool ui_first_drawn = false;
bool vk_first_drawn = false;
bool ui_context_want_active = true;
bool ui_context_want_active_vk = false;
bool vk_context_want_active = false;
tp::halnf dpmm;
tp::halnf font_size_mm;
tp::halnf ui_scale;
struct VKState {
struct InputButton {
char val = '?';
char shift_val = '?';
tp::halnf width = 1;
void (*action)(InputButton* button, VKState* state) = [](InputButton* button, VKState* state) {
if (state->mShifted) {
ImGui::GetIO().AddInputCharacter(button->shift_val);
}
else {
ImGui::GetIO().AddInputCharacter(button->val);
}
};
const char* display_name = NULL;
};
struct Config {
InputButton** rows = NULL;
tp::halni nrows = NULL;
tp::halnf* rows_widths = NULL;
tp::halnf* rows_sizes = NULL;
};
bool mShifted = false;
static const tp::uhalni mNConfigs = 2;
Config mConfigs[mNConfigs];
tp::uhalni mActiveConfigIdx = 0;
InputButton mCommonRow[7];
//bool mActive = false;
VKState() {
mCommonRow[0] = { '^', '^', 1 , [](InputButton* button, VKState* state) { state->mShifted = !state->mShifted; } };
mCommonRow[1] = { ' ', ' ', 1,
[](InputButton* button, VKState* state) {
state->mActiveConfigIdx++;
if (state->mActiveConfigIdx == state->mNConfigs) {
state->mActiveConfigIdx = 0;
}
},
"..."
};
mCommonRow[2] = { ' ', ' ', 2 };
mCommonRow[3] = { '<', '<', 2, [](InputButton* button, VKState* state) {
ImGui::GetIO().AddKeyEvent(ImGuiKey_Backspace, true);
ImGui::GetIO().AddKeyEvent(ImGuiKey_Backspace, false);
} };
mCommonRow[4] = { '.', '.', 1 };
mCommonRow[5] = { '@', '@', 1 };
mCommonRow[6] = { ' ', ' ', 2, [](InputButton* button, VKState* state) {
ImGui::GetIO().AddKeyEvent(ImGuiKey_Enter, true);
ImGui::GetIO().AddKeyEvent(ImGuiKey_Enter, false);
}, "Entrer" };
setupMainConfig(mConfigs[0]);
setupAdditionalConfig(mConfigs[1]);
}
void setupMainConfig(Config& config) {
static InputButton row1[] = {
{'1', '!'},
{'2', '@'},
{'3', '#'},
{'4', '$'},
{'5', '%'},
{'6', '^'},
{'7', '&'},
{'8', '*'},
{'9', '('},
{'0', ')'},
};
static InputButton row2[] = {
{'q', 'Q'},
{'w', 'W'},
{'e', 'E'},
{'r', 'R'},
{'t', 'T'},
{'y', 'Y'},
{'u', 'U'},
{'i', 'I'},
{'o', 'O'},
{'p', 'P'},
};
static InputButton row3[] = {
{'a', 'A'},
{'s', 'S'},
{'d', 'D'},
{'f', 'F'},
{'g', 'G'},
{'h', 'H'},
{'j', 'J'},
{'k', 'K'},
{'l', 'L'},
};
static InputButton row4[] = {
{'z', 'Z'},
{'x', 'X'},
{'c', 'C'},
{'v', 'V'},
{'b', 'B'},
{'n', 'N'},
{'m', 'M'},
};
static InputButton* rows[] = {
row1,
row2,
row3,
row4,
mCommonRow,
};
static tp::halnf rows_sizes[IM_ARRAYSIZE(rows)] = {
IM_ARRAYSIZE(row1),
IM_ARRAYSIZE(row2),
IM_ARRAYSIZE(row3),
IM_ARRAYSIZE(row4),
IM_ARRAYSIZE(mCommonRow),
};
static tp::halnf rows_widths[IM_ARRAYSIZE(rows)];
for (auto row = 0; row < IM_ARRAYSIZE(rows); row++) {
for (auto butt = 0; butt < rows_sizes[row]; butt++) {
rows_widths[row] += rows[row][butt].width;
}
}
config = {
rows,
IM_ARRAYSIZE(rows),
rows_widths,
rows_sizes,
};
}
void setupAdditionalConfig(Config& config) {
static InputButton row1[] = {
{'~', '~'},
{'`', '`'},
{'_', '_'},
{'|', '|'},
{'\\', '\\'},
{'/', '/'},
{'"', '"'},
{'\'', '\''},
};
static InputButton row2[] = {
{';', ';'},
{':', ':'},
{'?', '?'},
{',', ','},
{'[', '['},
{']', ']'},
{'{', '{'},
{'}', '}'},
{'(', '('},
{')', ')'},
};
static InputButton row3[] = {
{'-', '-'},
{'=', '='},
{'*', '*'},
{'+', '+'},
{'<', '<'},
{'>', '>'},
};
static InputButton row4[] = {
{' ', ' ', 1, [](InputButton* butt, VKState* state) {
ImGui::GetIO().AddKeyEvent(ImGuiKey_UpArrow, true);
ImGui::GetIO().AddKeyEvent(ImGuiKey_UpArrow, false);
}, "up" },
{' ', ' ', 1, [](InputButton* butt, VKState* state) {
ImGui::GetIO().AddKeyEvent(ImGuiKey_DownArrow, true);
ImGui::GetIO().AddKeyEvent(ImGuiKey_DownArrow, false);
}, "down"},
{' ', ' ', 1, [](InputButton* butt, VKState* state) {
ImGui::GetIO().AddKeyEvent(ImGuiKey_LeftArrow, true);
ImGui::GetIO().AddKeyEvent(ImGuiKey_LeftArrow, false);
}, "left"},
{' ', ' ', 1, [](InputButton* butt, VKState* state) {
ImGui::GetIO().AddKeyEvent(ImGuiKey_RightArrow, true);
ImGui::GetIO().AddKeyEvent(ImGuiKey_RightArrow, false);
}, "right"},
};
static InputButton* rows[] = {
row1,
row2,
row3,
row4,
mCommonRow,
};
static tp::halnf rows_sizes[IM_ARRAYSIZE(rows)] = {
IM_ARRAYSIZE(row1),
IM_ARRAYSIZE(row2),
IM_ARRAYSIZE(row3),
IM_ARRAYSIZE(row4),
IM_ARRAYSIZE(mCommonRow),
};
static tp::halnf rows_widths[IM_ARRAYSIZE(rows)];
for (auto row = 0; row < IM_ARRAYSIZE(rows); row++) {
for (auto butt = 0; butt < rows_sizes[row]; butt++) {
rows_widths[row] += rows[row][butt].width;
}
}
config = {
rows,
IM_ARRAYSIZE(rows),
rows_widths,
rows_sizes,
};
}
} mVKState;
DebugUiInternalContext(Window& window, DebugUiDrawCallBack* acb, void* acd) {
cb = acb;
cd = acd;
ui_context = ImGui::CreateContext();
ImGui::SetCurrentContext(ui_context);
ImGuiContextInit(window);
vk_context = ImGui::CreateContext();
ImGui::SetCurrentContext(vk_context);
ImGuiContextInit(window);
initialized = true;
}
void drawDebugUI(tp::halnf a_dpmm, tp::halnf a_font_size_mm, tp::halnf a_ui_scale) {
dpmm = a_dpmm;
font_size_mm = a_font_size_mm;
ui_scale = a_ui_scale;
if (!initialized) return;
ImGui::SetCurrentContext(ui_context);
ImGui::ApplyStyle(dpmm, font_size_mm, ui_scale);
ImGuiContextBeginFrame();
cb(cd);
ImGuiContextEndFrame();
ImGui::SetCurrentContext(NULL);
ui_first_drawn = true;
if (ui_context_want_active_vk || vk_context_want_active) {
ImGui::SetCurrentContext(vk_context);
ImGui::ApplyStyle(dpmm, font_size_mm, ui_scale);
ImGuiContextBeginFrame();
VirtualKeyboard(dpmm, font_size_mm, ui_scale);
ImGuiContextEndFrame();
ImGui::SetCurrentContext(NULL);
vk_first_drawn = true;
}
}
~DebugUiInternalContext() {
if (!initialized) return;
ImGui::SetCurrentContext(ui_context);
ImGuiContextDeinit();
ImGui::DestroyContext(ui_context);
ImGui::SetCurrentContext(vk_context);
ImGuiContextDeinit();
ImGui::DestroyContext(vk_context);
}
private:
void ImGuiContextInit(Window& window) {
#if defined ENV_OS_WINDOWS
ImGui_ImplOpenGL3_Init();
ImGui_ImplWin32_Init(window.platform_window());
window.mNativeEventListeners.put("imgui", {
nativeWindowEventListenerWrapBegin,
nativeWindowEventListenerWrap,
nativeWindowEventListenerWrapEnd,
this
});
#elif defined ENV_OS_LINUX
ImGui_ImplOpenGL3_Init();
ImGui_ImplGlfw_InitForOpenGL((GLFWwindow*)window.platform_window(), true);
#elif defined ENV_OS_ANDROID
ImGui_ImplOpenGL3_Init("#version 300 es");
ImGui_ImplAndroid_Init((ANativeWindow*)window.platform_window());
ImGui::GetIO().IniFilename = AndroidGetImGuiIniPath();
window.mNativeEventListeners.put("imgui", {
nativeWindowEventListenerWrapBegin,
nativeWindowEventListenerWrap,
nativeWindowEventListenerWrapEnd,
this
});
#endif
}
void ImGuiContextBeginFrame() {
#if defined ENV_OS_WINDOWS
ImGui_ImplWin32_NewFrame();
ImGui_ImplOpenGL3_NewFrame();
#elif defined ENV_OS_LINUX
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
#elif defined ENV_OS_ANDROID
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplAndroid_NewFrame();
#endif
ImGui::NewFrame();
}
void ImGuiContextEndFrame() {
ImGui::Render();
#if defined ENV_OS_WINDOWS
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
#elif defined ENV_OS_LINUX
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
#elif defined ENV_OS_ANDROID
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
#endif
}
void ImGuiContextDeinit() {
#if defined ENV_OS_WINDOWS
ImGui_ImplWin32_Shutdown();
#elif defined ENV_OS_LINUX
ImGui_ImplGlfw_Shutdown();
#elif defined ENV_OS_ANDROID
ImGui_ImplAndroid_Shutdown();
#endif
ImGui_ImplOpenGL3_Shutdown();
}
void nativeWindowEventListenerPlatform(tp::glw::PlatformContext* ctx) {
#if defined ENV_OS_WINDOWS
auto native_window = windowsPlatformContextGetNativeWindow(ctx);
auto message = windowsPlatformContextGetMessage(ctx);
auto w_param = windowsPlatformContextGetWparam(ctx);
auto l_param = windowsPlatformContextGetLparam(ctx);
// IMGUI : needs to be commented out
//if (bd->MouseButtonsDown == 0 && ::GetCapture() == nullptr)
// ::SetCapture(hwnd);
ImGui_ImplWin32_WndProcHandler(native_window, message, w_param, l_param);
#elif defined ENV_OS_LINUX
#elif defined ENV_OS_ANDROID
auto aev = androidPlatformContextGetEvent(ctx);
int32_t event_type = AInputEvent_getType(aev);
ImGui_ImplAndroid_HandleInputEvent(aev);
auto& io = ImGui::GetIO();
if (event_type == AINPUT_EVENT_TYPE_MOTION); {
int32_t event_action = AMotionEvent_getAction(aev);
int32_t event_pointer_index = (event_action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
event_action &= AMOTION_EVENT_ACTION_MASK;
if ((AMotionEvent_getToolType(aev, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_FINGER)
|| (AMotionEvent_getToolType(aev, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_UNKNOWN)) {
if (event_action == AMOTION_EVENT_ACTION_DOWN) {
io.AddMousePosEvent(AMotionEvent_getX(aev, event_pointer_index), AMotionEvent_getY(aev, event_pointer_index));
}
else if (event_action == AMOTION_EVENT_ACTION_UP) {
io.AddMousePosEvent(AMotionEvent_getX(aev, event_pointer_index), AMotionEvent_getY(aev, event_pointer_index));
if (!ui_context_want_active_vk || vk_context_want_active) {
io.AddMousePosEvent(-1, -1);
}
}
}
}
#endif
}
void nativeWindowEventListenerBegin(tp::glw::PlatformContext* ctx) {
vk_context_want_active = vk_context->IO.WantCaptureMouse || vk_context->IO.WantSetMousePos;
ui_context_want_active_vk = ui_context->IO.WantTextInput;
ui_context_want_active = ui_context->IO.WantCaptureKeyboard || ui_context->IO.WantCaptureMouse || ui_context->IO.WantSetMousePos;
}
void nativeWindowEventListener(tp::glw::PlatformContext* ctx) {
// proc vk
if ((ui_context_want_active_vk || vk_context_want_active) && vk_first_drawn) {
ImGui::SetCurrentContext(vk_context);
nativeWindowEventListenerPlatform(ctx);
while (vk_context->InputEventsQueue.Size) {
ImGui::ApplyStyle(dpmm, font_size_mm, ui_scale);
ImGui::NewFrame();
VirtualKeyboard(dpmm, font_size_mm, ui_scale);
ImGui::Render();
vk_context_want_active |= vk_context->IO.WantCaptureMouse || vk_context->IO.WantSetMousePos;
}
vk_context_want_active |= vk_context->IO.WantCaptureMouse || vk_context->IO.WantSetMousePos;
ImGui::SetCurrentContext(NULL);
}
// proc ui
if (!vk_context_want_active && ui_first_drawn) {
ImGui::SetCurrentContext(ui_context);
nativeWindowEventListenerPlatform(ctx);
while (ui_context->InputEventsQueue.Size) {
ImGui::ApplyStyle(dpmm, font_size_mm, ui_scale);
ImGui::NewFrame();
cb(cd);
ImGui::Render();
ui_context_want_active_vk |= ui_context->IO.WantTextInput;
ui_context_want_active |= ui_context->IO.WantCaptureKeyboard || ui_context->IO.WantCaptureMouse || ui_context->IO.WantSetMousePos;
}
ImGui::SetCurrentContext(NULL);
}
}
void nativeWindowEventListenerEnd(tp::glw::PlatformContext* ctx) {}
static void nativeWindowEventListenerWrapBegin(tp::glw::PlatformContext* ctx, void* cd) { ((DebugUiInternalContext*)cd)->nativeWindowEventListenerBegin(ctx); }
static void nativeWindowEventListenerWrap(tp::glw::PlatformContext* ctx, void* cd) { ((DebugUiInternalContext*)cd)->nativeWindowEventListener(ctx); }
static void nativeWindowEventListenerWrapEnd(tp::glw::PlatformContext* ctx, void* cd) { ((DebugUiInternalContext*)cd)->nativeWindowEventListenerEnd(ctx); }
void VirtualKeyboard(tp::halnf dpmm, tp::halnf font_size_mm, tp::halnf ui_scale) {
auto& config = mVKState.mConfigs[mVKState.mActiveConfigIdx];
ImGuiID dockspace_id = ImGui::DockSpaceOverViewport(0, ImGuiDockNodeFlags_PassthruCentralNode);
ImGuiDockNode* node = ImGui::DockContextFindNodeByID(ImGui::GetCurrentContext(), dockspace_id);
if (!node->IsSplitNode()) {
node->MergedFlags |= ImGuiDockNodeFlags_HiddenTabBar;
ImGuiID dock_id = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Down, 0.33f, nullptr, &dockspace_id);
ImGui::DockBuilderDockWindow("VK", dock_id);
}
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0.f, 0.f });
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, { 50 * dpmm, 30 * dpmm });
ImGui::Begin("VK");
ImGui::PopStyleVar(3);
auto pos = ImGui::GetCursorPos();
auto width = ImGui::GetWindowWidth();
auto height = ImGui::GetWindowHeight() - pos.y;
//auto scale = dpmm * ui_scale;
auto padding = dpmm * 2 * ui_scale;
auto button_sizey = (tp::halnf)(height - (config.nrows + 1) * padding) / config.nrows;
tp::vec2f crs = { pos.x + padding, pos.y + padding };
for (auto row = 0; row < config.nrows; row++) {
tp::halnf butt_scalex = (width - (config.rows_sizes[row] + 1) * padding) / config.rows_widths[row];
crs.x = pos.x + padding;
for (auto butt = 0; butt < config.rows_sizes[row]; butt++) {
auto& button = config.rows[row][butt];
ImGui::SetCursorPos({ crs.x, crs.y });
char name[2] = { mVKState.mShifted ? button.shift_val : button.val, 0 };
ImGui::PushID(&button);
if (!ImGui::Button(button.display_name ? button.display_name: name, { butt_scalex * button.width, button_sizey })) {
crs.x += butt_scalex * button.width + padding;
ImGui::PopID();
continue;
}
ImGui::SetCurrentContext(ui_context);
button.action(&button, &mVKState);
ImGui::SetCurrentContext(vk_context);
ImGui::PopID();
}
crs.y += button_sizey + padding;
}
ImGui::End();
}
};
}
}
tp::glw::DebugUI::DebugUI(Window& window, DebugUiDrawCallBack* acb, void* acd) {
mDPMM = window.mDevice.mDPMM;
// map device size to font and ui size
{
auto device_max = 600.f;
auto device_min = 50.f;
auto device = tp::clamp(window.mDevice.Size.x / mDPMM, device_min, device_max);
auto device_factor = (device - device_min) / (device_max - device_min);
auto font_min = 2.f;
auto font_max = 3.5f;
mFontSizeMM = (font_max - font_min) * device_factor + font_min;
auto ui_max = 1.f;
auto ui_min = 0.45f;
mUIScale = (ui_max - ui_min) * device_factor + ui_min;
}
mCtx = new DebugUiInternalContext(window, acb, acd);
}
void tp::glw::DebugUI::drawDebugUI(tp::halnf dpmm) {
mDPMM = dpmm;
mCtx->drawDebugUI(mDPMM, mFontSizeMM, mUIScale);
}
tp::glw::DebugUI::~DebugUI() {
delete mCtx;
}
// ------------------------------------------------------ //
static const int sWindowFrameFlags = (ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoDecoration);
bool ImGui::SubMenuBegin(const char* desc, int level) {
if (level == 1) {
ImGui::Separator();
}
if (ImGui::TreeNode(desc)) {
GImGui->Style.IndentSpacing = 6;
return true;
}
return false;
}
void ImGui::SubMenuEnd(int level) {
ImGui::TreePop();
}
void ImGui::ToolTip(const char* desc) {
ImGui::SameLine();
ImGui::TextDisabled("*");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(desc);
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
}
ImGui::PopupData ImGui::HoverPopupBeginButton(const char* id, tp::vec2f butsize, tp::vec2f popupsize) {
ImVec2 curs = ImGui::GetCursorScreenPos();
tp::vec2f popup_pos = tp::vec2f(curs.x + butsize.x / 2.f - popupsize.x / 2.f, (curs.y + butsize.y + 7));
ImGui::Button(id, ImVec2(butsize.x, butsize.y)); ImGui::SameLine();
return HoverPopupBegin(id, popupsize, popup_pos);
}
ImGui::PopupData ImGui::HoverPopupBegin(const char* str_id, tp::vec2f size, tp::vec2f pos_p, ImGuiPopupFlags popup_flags) {
ImGui::PopupData out;
out.ishovered = ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
if (out.ishovered) {
ImVec2 pos;
if (pos_p == tp::vec2f(-1)) {
pos = GImGui->CurrentWindow->DC.CursorPos;
}
else {
pos.x = pos_p.x;
pos.y = pos_p.y;
}
ImGui::SetNextWindowPos(pos);
out.p1 = { pos.x, pos.y };
ImGui::OpenPopup(str_id);
out.p2 = out.p1;
out.p2.x += ImGui::GetWindowWidth();
}
if (BeginPopup(str_id, ImGuiWindowFlags_NoMove)) {
out.opened = true;
auto pos = GetWindowPos();
out.p1 = { pos.x, pos.y };
out.p2 = out.p1;
out.p2.x += ImGui::GetWindowWidth();
}
return out;
}
void ImGui::HoverPopupEnd(ImGui::PopupData& in) {
if (!in.opened) {
return;
}
in.ishovered |= IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_ChildWindows);
tp::vec2f mousepos = { ImGui::GetMousePos().x, ImGui::GetMousePos().y };
tp::halnf tollerance = 10;
tp::rectf tollerace_rect = tp::rectf(tp::vec2f(in.p1.x, in.p1.y - tollerance), tp::vec2f(in.p2.x - in.p1.x, tollerance * 2.f));
bool is_tollerance = tollerace_rect.inside(mousepos);
if (!(in.ishovered || is_tollerance)) {
CloseCurrentPopup();
}
EndPopup();
}
#define VAL(val) (val * dpmm / 3 * ui_scale)
#define VEC(x, y) ImVec2(x * dpmm / 3, y * dpmm / 3 * ui_scale)
void ImGui::ApplyStyle(tp::halnf dpmm, float font_size_mm, float ui_scale) {
ImGuiStyle* style = &ImGui::GetStyle();
auto& io = ImGui::GetIO();
bool first_init = io.Fonts->Fonts.Size == 0;
auto font_path = getFontPath();
// supports PDMM from 0.3 to 10
const float min_dpmm = 0.3f;
const float max_dpmm = 20.f;
dpmm = tp::clamp(dpmm, min_dpmm, max_dpmm);
// calc font
const float font_size_mm_max = 10;
const float font_size_pixels_min = 9;
float font_size_mm_min = font_size_pixels_min / dpmm;
const int font_quality_steps = 3;
font_size_mm = tp::clamp(font_size_mm, font_size_mm_min, font_size_mm_max);
float font_sizes[font_quality_steps];
for (auto i = 0; i < font_quality_steps; i++) {
auto mm = font_size_mm_min + (font_size_mm_max - font_size_mm_min) * tp::pow(((tp::halnf) (i + 1) / font_quality_steps), 3);
font_sizes[i] = dpmm * mm;
}
if (first_init) {
for (auto i = 0; i < font_quality_steps; i++) {
io.Fonts->AddFontFromFileTTF(font_path, font_sizes[i] * 1);
}
}
// select fonts
auto const pixels_required = dpmm * font_size_mm;
auto idx = -1;
for (auto i = 0; i < font_quality_steps; i++) {
idx = i;
if (pixels_required <= font_sizes[i]) {
break;
}
}
DBG_BREAK(idx == -1);
io.FontDefault = io.Fonts->Fonts[idx];
io.FontGlobalScale = font_size_mm / (font_size_mm_min + ((font_size_mm_max - font_size_mm_min) / font_quality_steps) * (idx + 1));
io.FontGlobalScale = pixels_required / font_sizes[idx];
auto rounding = VAL(5);
auto pudding = VEC(7, 7);
style->WindowPadding = pudding;
style->WindowRounding = rounding;
//style->WindowMinSize = VEC(11, 11);
style->ChildRounding = rounding;
style->PopupRounding = rounding;
style->FramePadding = pudding;
style->FrameRounding = rounding;
style->ItemSpacing = VEC(4, 11);
style->ItemInnerSpacing = VEC(9, 4);
style->CellPadding = pudding;
style->TouchExtraPadding = pudding;
style->IndentSpacing = VAL(25);
style->ColumnsMinSpacing = VAL(5);
style->ScrollbarSize = VAL(16);
style->ScrollbarRounding = rounding;
style->GrabMinSize = VAL(2);
style->GrabRounding = rounding;
style->LogSliderDeadzone = VAL(2);
style->TabRounding = rounding;
style->TabMinWidthForCloseButton = VAL(5);
style->DisplayWindowPadding = pudding;
style->DisplaySafeAreaPadding = pudding;
style->MouseCursorScale = VAL(5);
style->FrameBorderSize = VAL(0);
style->WindowBorderSize = VAL(1.5f);
style->ChildBorderSize = VAL(2);
style->WindowTitleAlign = VEC(0.5f, 0.6f);
style->WindowMenuButtonPosition = ImGuiDir_Right;
if (!first_init)
return;
ImVec4* colors = ImGui::GetStyle().Colors;
colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(0.86f, 0.86f, 0.86f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
colors[ImGuiCol_ChildBg] = ImVec4(0.09f, 0.09f, 0.10f, 1.00f);
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.10f, 1.00f);
colors[ImGuiCol_Border] = ImVec4(0.06f, 0.06f, 0.06f, 1.00f);
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_FrameBg] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.27f, 0.27f, 0.33f, 1.00f);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.43f, 0.43f, 0.53f, 1.00f);
colors[ImGuiCol_TitleBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
colors[ImGuiCol_TitleBgActive] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
colors[ImGuiCol_MenuBarBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.09f, 0.09f, 0.10f, 0.00f);
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.15f, 0.15f, 0.19f, 1.00f);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.21f, 0.20f, 0.25f, 1.00f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.30f, 0.29f, 0.35f, 1.00f);
colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.48f, 0.50f, 1.00f);
colors[ImGuiCol_SliderGrab] = ImVec4(0.53f, 0.57f, 0.64f, 1.00f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.69f, 0.74f, 0.83f, 1.00f);
colors[ImGuiCol_Button] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
colors[ImGuiCol_ButtonHovered] = ImVec4(0.27f, 0.27f, 0.33f, 1.00f);
colors[ImGuiCol_ButtonActive] = ImVec4(0.43f, 0.43f, 0.53f, 1.00f);
colors[ImGuiCol_Header] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
colors[ImGuiCol_HeaderHovered] = ImVec4(0.27f, 0.27f, 0.33f, 1.00f);
colors[ImGuiCol_HeaderActive] = ImVec4(0.33f, 0.33f, 0.40f, 1.00f);
colors[ImGuiCol_Separator] = ImVec4(0.37f, 0.37f, 0.40f, 1.00f);
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.33f, 0.35f, 0.38f, 1.00f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.37f, 0.39f, 0.42f, 1.00f);
colors[ImGuiCol_ResizeGrip] = ImVec4(0.16f, 0.17f, 0.19f, 1.00f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.33f, 0.35f, 0.38f, 1.00f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.28f, 0.34f, 0.42f, 1.00f);
colors[ImGuiCol_Tab] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
colors[ImGuiCol_TabHovered] = ImVec4(0.23f, 0.23f, 0.28f, 1.00f);
colors[ImGuiCol_TabActive] = ImVec4(0.23f, 0.23f, 0.28f, 1.00f);
colors[ImGuiCol_TabUnfocused] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.43f, 0.45f, 0.48f, 1.00f);
colors[ImGuiCol_DockingPreview] = ImVec4(0.81f, 0.81f, 0.81f, 0.18f);
colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.33f, 0.35f, 0.38f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(0.49f, 0.51f, 0.54f, 1.00f);
colors[ImGuiCol_TableHeaderBg] = ImVec4(0.13f, 0.13f, 0.20f, 1.00f);
colors[ImGuiCol_TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.35f, 1.00f);
colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 1.00f);
colors[ImGuiCol_TableRowBg] = ImVec4(0.23f, 0.20f, 0.20f, 0.00f);
colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.38f, 0.22f, 0.22f, 0.20f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.10f, 1.00f);
colors[ImGuiCol_DockingPreview] = ImVec4(0.64f, 0.75f, 0.83f, 0.18f);
colors[ImGuiCol_TabHovered] = ImVec4(0.39f, 0.39f, 0.47f, 1.00f);
colors[ImGuiCol_TabActive] = ImVec4(0.27f, 0.27f, 0.33f, 1.00f);
colors[ImGuiCol_TabUnfocused] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.24f, 0.24f, 0.29f, 1.00f);
colors[ImGuiCol_Border] = ImVec4(0.65f, 0.65f, 0.65f, 0.70f);
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
}

View file

@ -0,0 +1,116 @@
#include "fbuffer.h"
#include "GraphicsLibApi.h"
void glerr(GLenum type);
#define AssertGL(x) { x; GLenum __gle = glGetError(); if (__gle != GL_NO_ERROR) glerr(__gle); }
namespace tp {
using namespace glw;
fbuffer::fbuffer(const vec2f& size) : mSize(size) {
mDrawBuffers[0] = {GL_COLOR_ATTACHMENT0};
// --------- texture ---------
AssertGL(glGenTextures(1, &mTextureId));
AssertGL(glBindTexture(GL_TEXTURE_2D, mTextureId));
// Give an empty image to OpenGL ( the last "0" )
AssertGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)size.x, (GLsizei)size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
// Poor filtering. Needed
AssertGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
AssertGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
// --------- depth ---------
AssertGL(glGenRenderbuffers(1, &mDepthBufferID));
AssertGL(glBindRenderbuffer(GL_RENDERBUFFER, mDepthBufferID));
AssertGL(glRenderbufferStorage(GL_RENDERBUFFER, GLW_CONTEXT_DEPTH_COMPONENT, (GLsizei)size.x, (GLsizei)size.y));
// ------------ framebuffer ------------
AssertGL(glGenFramebuffers(1, &mFrameBufferID));
AssertGL(glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferID));
AssertGL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthBufferID));
// Set "renderedTexture" as our colour attachement #0
AssertGL(glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextureId, 0));
// Set the list of draw buffers.
AssertGL(glDrawBuffers(1, mDrawBuffers)); // "1" is the size of DrawBuffers
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
fbuffer::fbuffer(const vec2f& size, tp::uint1 samples) : mSize(size) {
mDrawBuffers[0] = { GL_COLOR_ATTACHMENT0 };
// ------- texture ---------
AssertGL(glGenTextures(1, &mTextureId));
AssertGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextureId));
#ifdef ENV_OS_ANDROID
AssertGL(glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, (GLsizei)size.x, (GLsizei)size.y, GL_TRUE));
#else
AssertGL(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, (GLsizei)size.x, (GLsizei)size.y, GL_TRUE));
#endif
// !?
//AssertGL(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
//AssertGL(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
// ------- depth -------
AssertGL(glGenRenderbuffers(1, &mDepthBufferID));
AssertGL(glBindRenderbuffer(GL_RENDERBUFFER, mDepthBufferID));
AssertGL(glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GLW_CONTEXT_DEPTH_COMPONENT, (GLsizei)size.x, (GLsizei)size.y));
// ------- fbuff -------
AssertGL(glGenFramebuffers(1, &mFrameBufferID));
AssertGL(glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferID));
AssertGL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, mTextureId, 0));
AssertGL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthBufferID));
AssertGL(glDrawBuffers(1, mDrawBuffers));
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
tp::uint4 fbuffer::buffId() const {
return mFrameBufferID;
}
void fbuffer::beginDraw() {
AssertGL(glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferID));
setViewport({ 0.f, 0.f, mSize.x, mSize.y });
}
void fbuffer::setViewport(const rectf& viewport) {
AssertGL(glViewport((GLsizei)viewport.x, (GLsizei)viewport.y, (GLsizei)viewport.z, (GLsizei)viewport.w));
}
void fbuffer::clear() {
AssertGL(glClearColor(mClearCol.r, mClearCol.g, mClearCol.b, mClearCol.a));
AssertGL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
}
void fbuffer::endDraw() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(0, 0, 0, 0);
glUseProgram(0);
}
fbuffer::~fbuffer() {
glDeleteFramebuffers(1, &mFrameBufferID);
glDeleteTextures(1, &mTextureId);
glDeleteRenderbuffers(1, &mDepthBufferID);
}
uhalni glw::fbuffer::sizeAllocatedMem() const {
return uhalni(sizeof(GLenum) * 4 + mSize.sizeAllocatedMem() + (sizeof(mClearCol) + 1) * (alni) mSize.x * (alni) mSize.y);
}
uhalni glw::fbuffer::sizeUsedMem() const {
return sizeAllocatedMem();
}
uint4 glw::fbuffer::texId() const {
return mTextureId;
}
const vec2f& fbuffer::getSize() const { return mSize; }
};

View file

@ -0,0 +1,282 @@
#include "window.h"
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include <iostream>
#include <stdlib.h>
tp::glw::Window::Device tp::glw::Window::mDevice;
static void glfw_error_callback(int error, const char* description) {
std::cout << stderr << "Glfw Error" << error << " " << description << "\n";
}
void tp::glw::Window::init() {
tp::glw::Window::mDevice.Size;
tp::glw::Window::mDevice.FrameRate;
// Setup window
setenv("DISPLAY", ":0.0", 0); // does overwrite
glfwSetErrorCallback(glfw_error_callback);
RelAssert(glfwInit());
// GL 3.0 + GLSL 130
const char* glsl_version = "#version 130";
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 3.0+ only
glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
GLFWmonitor* primary = glfwGetPrimaryMonitor();
auto mode = glfwGetVideoMode(primary);
tp::glw::Window::mDevice.Size = { mode->width, mode->height };
tp::glw::Window::mDevice.FrameRate = mode->refreshRate;
}
#define MAP_EV(SYSKEY, code) case SYSKEY: { self->mEvents.mKeysQueue.push(tp::KeyEvent{ code, state }); break; }
namespace tp {
namespace glw {
struct PlatformContext {
GLFWwindow* window;
tp::glw::Window* window_ctx = NULL;
PlatformContext(tp::glw::Window* a_window_ctx) {
window_ctx = a_window_ctx;
// Create window with graphics context
window = glfwCreateWindow(300, 300, " ", NULL, NULL);
RelAssert(window);
glfwMakeContextCurrent(window);
GLenum err = glewInit();
if (GLEW_OK != err)
{
std::cout << stderr << "Error:" << glewGetErrorString(err);
RelAssert(0);
}
glfwSwapInterval(1); // Enable vsync
glfwSetWindowUserPointer(window, window_ctx);
glfwSetKeyCallback(window, key_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
glfwSetScrollCallback(window, scroll_callback);
}
void applyAppearance(tp::glw::Window::Appearence& appear, tp::glw::Window::Appearence& prev, tp::glw::Window* win_ctx) {
if (!(appear.mSize == prev.mSize)) {
glfwSetWindowSize(window, appear.mSize.x, appear.mSize.y);
prev.mSize = appear.mSize;
}
if (!(appear.mPos == prev.mPos)) {
//glfwSetWindowPos(window, appear.mPos.x, appear.mPos.y);
win_ctx->mEvents.mCursor -= appear.mPos - prev.mPos;
//win_ctx->mEvents.mCursorPrev -= appear.mPos - prev.mPos;
prev.mPos = appear.mPos;
}
if (!(appear.mSizeMax == prev.mSizeMax && appear.mSizeMin == prev.mSizeMin)) {
glfwSetWindowSizeLimits(window, appear.mSizeMin.x, appear.mSizeMin.y, appear.mSizeMax.x, appear.mSizeMax.y);
prev.mSizeMax = appear.mSizeMax;
prev.mSizeMin = appear.mSizeMin;
}
if (!(appear.mMaximized == prev.mMaximized)) {
DBG_BREAK(1);
}
if (!(appear.mMinimized == prev.mMinimized)) {
DBG_BREAK(1);
}
int width, height;
glfwGetWindowSize(window, &width, &height);
appear.mSize = { width, height };
prev.mSize = appear.mSize;
glfwGetWindowPos(window, &width, &height);
appear.mPos = { width, height };
prev.mPos = appear.mPos;
}
void beginDraw() {
//int display_w, display_h;
//glfwGetFramebufferSize(window, &display_w, &display_h);
//glViewport(0, 0, display_w, display_h);
//glClearColor(0, 0, 0, 0);
//glClear(GL_COLOR_BUFFER_BIT);
}
void endDraw() {
glfwSwapBuffers(window);
}
void pollEvents() {
glfwPollEvents();
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
window_ctx->mEvents.mCursorPrev = window_ctx->mEvents.mCursor;
window_ctx->mEvents.mCursor = { xpos, ypos };
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
auto self = (tp::glw::Window*) glfwGetWindowUserPointer(window);
if (action != GLFW_PRESS && action != GLFW_RELEASE) {
return;
}
auto state = (action == GLFW_RELEASE) ? tp::KeyEvent::EventState::RELEASED : tp::KeyEvent::EventState::PRESSED;
//* VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39)
if (key >= GLFW_KEY_0 && key <= GLFW_KEY_9) {
self->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode(key), state });
return;
}
//* VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A)
else if (key >= GLFW_KEY_A && key <= GLFW_KEY_Z) {
self->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode(key), state });
return;
}
switch (key) {
MAP_EV(GLFW_KEY_LEFT_SHIFT, tp::Keycode::LEFT_SHIFT);
MAP_EV(GLFW_KEY_LEFT, tp::Keycode::LEFT);
MAP_EV(GLFW_KEY_RIGHT, tp::Keycode::RIGHT);
MAP_EV(GLFW_KEY_UP, tp::Keycode::UP);
MAP_EV(GLFW_KEY_DOWN, tp::Keycode::DOWN);
MAP_EV(GLFW_KEY_BACKSPACE, tp::Keycode::BACKSPACE);
MAP_EV(GLFW_KEY_LEFT_CONTROL, tp::Keycode::LEFT_CONTROL);
MAP_EV(GLFW_KEY_MENU, tp::Keycode::LEFT_ALT);
MAP_EV(GLFW_KEY_ENTER, tp::Keycode::ENTER);
MAP_EV(GLFW_KEY_SPACE, tp::Keycode::SPACE);
MAP_EV(GLFW_KEY_COMMA, tp::Keycode::COMMA);
MAP_EV(GLFW_KEY_PERIOD, tp::Keycode::PERIOD);
MAP_EV(GLFW_KEY_TAB, tp::Keycode::TAB);
MAP_EV(GLFW_KEY_EQUAL, tp::Keycode::EQUAL);
MAP_EV(GLFW_KEY_MINUS, tp::Keycode::MINUS);
MAP_EV(GLFW_KEY_3, tp::Keycode::TILDA);
MAP_EV(GLFW_KEY_4, tp::Keycode::BRA);
MAP_EV(GLFW_KEY_5, tp::Keycode::SLASH);
MAP_EV(GLFW_KEY_6, tp::Keycode::KET);
MAP_EV(GLFW_KEY_1, tp::Keycode::DOUBLE_DOT);
MAP_EV(GLFW_KEY_7, tp::Keycode::QUOTES);
MAP_EV(GLFW_KEY_2, tp::Keycode::INV_SLASH);
MAP_EV(GLFW_KEY_ESCAPE, tp::Keycode::ESCAPE);
}
}
static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
auto self = (tp::glw::Window*)glfwGetWindowUserPointer(window);
if (action != GLFW_PRESS && action != GLFW_RELEASE) {
return;
}
auto state = (action == GLFW_RELEASE) ? tp::KeyEvent::EventState::RELEASED : tp::KeyEvent::EventState::PRESSED;
switch (button) {
case GLFW_MOUSE_BUTTON_RIGHT: {
self->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode::MOUSE2, state });
} break;
case GLFW_MOUSE_BUTTON_LEFT: {
self->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode::MOUSE1, state });
} break;
case GLFW_MOUSE_BUTTON_MIDDLE: {
self->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode::MOUSE3, state });
} break;
}
}
static void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
}
~PlatformContext() {
glfwDestroyWindow(window);
}
};
};
};
void tp::glw::Window::deinit() {}
tp::glw::Window::Window() {
initialize();
mAppearence.mSize = tp::glw::Window::mDevice.Size / 1.5f;
mAppearence.mPos = (tp::glw::Window::mDevice.Size - mAppearence.mSize) / 2.f;
mAppearence.mSizeMax = tp::glw::Window::mDevice.Size;
applyAppearance();
}
tp::glw::Window::Window(const Appearence& aAppearence) {
mAppearence = aAppearence;
initialize();
}
void tp::glw::Window::initialize() {
mPlatformCtx = new PlatformContext(this);
applyAppearance();
}
void tp::glw::Window::applyAppearance() {
mPlatformCtx->applyAppearance(mAppearence, this->mCache.mAppearencePrev, this);
}
void tp::glw::Window::pollEvents() {
applyAppearance();
mPlatformCtx->pollEvents();
mEvents.mRedraw |= (mEvents.mCursorPrev - mEvents.mCursor) != 0;
mEvents.mRedraw |= mEvents.mKeysQueue.length;
}
void tp::glw::Window::platformCallback() {}
void tp::glw::Window::beginDraw() {
mPlatformCtx->beginDraw();
}
void tp::glw::Window::endDraw() {
mPlatformCtx->endDraw();
if (mEvents.mRedraw-- < 0) mEvents.mRedraw = 0;
}
void* tp::glw::Window::platform_window() const {
return mPlatformCtx->window;
}
tp::alni tp::glw::Window::sizeAllocatedMem() {
return 0;
}
tp::alni tp::glw::Window::sizeUsedMem() {
return 0;
}
tp::glw::Window::~Window() {
delete mPlatformCtx;
}

View file

@ -0,0 +1,170 @@
#include "stringt.h"
#include "array.h"
#include "array.h"
#include "filesystem.h"
#include "shader.h"
#include "new.h"
#include "GraphicsLibApi.h"
#include <cstdio>
namespace tp {
using namespace glw;
//string shader_path = "../rsc/shaders/";
shader::shader() {
programm = 0;
VertexShaderID = 0;
FragmentShaderID = 0;
GeometryShaderID = 0;
}
void shader::vert_bind_source(const char* vert_src) {
VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
compile_shader(vert_src, VertexShaderID);
}
void shader::frag_bind_source(const char* frag_src) {
FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
compile_shader(frag_src, FragmentShaderID);
}
void shader::geom_bind_source(const char* geom_src) {
GeometryShaderID = glCreateShader(GL_GEOMETRY_SHADER);
compile_shader(geom_src, GeometryShaderID);
}
void shader::compile() {
GLint Result = GL_FALSE;
int InfoLogLength;
programm = glCreateProgram();
glAttachShader(programm, VertexShaderID);
if (GeometryShaderID) glAttachShader(programm, GeometryShaderID);
glAttachShader(programm, FragmentShaderID);
glLinkProgram(programm);
// Check the program
glGetProgramiv(programm, GL_LINK_STATUS, &Result);
glGetProgramiv(programm, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
Array<char> ProgramErrorMessage(InfoLogLength + 1);
glGetProgramInfoLog(programm, InfoLogLength, NULL, &ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);
}
glDetachShader(programm, VertexShaderID);
glDetachShader(programm, FragmentShaderID);
if (GeometryShaderID) glDetachShader(programm, GeometryShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
if (GeometryShaderID) glDeleteShader(GeometryShaderID);
}
bool shader::compile_shader(const char* ShaderCode, uint4 ShaderID) {
GLint Result = GL_FALSE;
int InfoLogLength;
char const* SourcePointer = ShaderCode;
glShaderSource(ShaderID, 1, &SourcePointer, NULL);
glCompileShader(ShaderID);
// Check Shader
glGetShaderiv(ShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(ShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
Array<char> VertexShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(ShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
printf("%s\n", &VertexShaderErrorMessage[0]);
}
return Result;
}
void shader::load(const char* pvert, const char* pgeom, const char* pfrag, bool paths) {
// Create the shaders
VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
if (pgeom) GeometryShaderID = glCreateShader(GL_GEOMETRY_SHADER);
else GeometryShaderID = 0;
GLint Result = GL_FALSE;
int InfoLogLength = 0;
if (paths) {
string vert = sfmt("%c.vert", pvert);
string geom = pgeom ? sfmt("%c.geom", pgeom) : " ";
string frag = sfmt("%c.frag", pfrag);
tp::string content;
printf("Compiling shader : %s\n", vert.cstr());
if (content.loadFile(vert)) {
compile_shader(content.cstr(), VertexShaderID);
}
if (GeometryShaderID) {
printf("Compiling shader : %s\n", geom.cstr());
if (content.loadFile(geom)) {
compile_shader(content.cstr(), GeometryShaderID);
}
}
printf("Compiling shader : %s\n", frag.cstr());
if (content.loadFile(frag)) {
compile_shader(content.cstr(), FragmentShaderID);
}
}
else {
compile_shader(pvert, VertexShaderID);
if (GeometryShaderID) {
compile_shader(pgeom, GeometryShaderID);
}
compile_shader(pfrag, FragmentShaderID);
}
compile();
}
shader::shader(const char* vert, const char* geom, const char* frag, bool paths) {
load(vert, geom, frag, paths);
}
void shader::bind() {
glUseProgram(programm);
}
GLuint glw::shader::getu(const char* uid) {
return glGetUniformLocation(programm, uid);
}
void shader::unbind() {
glUseProgram(0);
}
shader::~shader() {
glDeleteProgram(programm);
}
alni glw::shader::sizeAllocatedMem() {
return sizeof(GLuint) * 4;
}
alni glw::shader::sizeUsedMem() {
return sizeof(GLuint) * 4;
}
};

View file

@ -0,0 +1,164 @@
#pragma once
#include "simplegui.h"
using namespace tp;
using namespace glw;
void WindowSimpleInputs::update(const glw::Window& window, halnf uiscale) {
mScaleVal = (window.mDevice.mDPMM * uiscale);
mWindowSizeMM = window.mAppearence.mSize / mScaleVal;
mCrs = window.mEvents.mCursor / mScaleVal;
mCrsPrev = window.mEvents.mCursorPrev / mScaleVal;
mCrsmDelta = mCrs - mCrsPrev;
if (mMouse == Mouse::PRESSED) {
mMouse = Mouse::HOLD;
}
else if (mMouse == Mouse::RELEASED) {
mMouse = Mouse::NONE;
}
mMove = Move::NONE;
for (auto event : window.mEvents.mKeysQueue) {
bool press = event.data().event_state == KeyEvent::EventState::PRESSED;
if (press) {
switch (event.data().code) {
case Keycode::UP: mMove = Move::UP; break;
case Keycode::DOWN: mMove = Move::DOWN; break;
case Keycode::LEFT: mMove = Move::LEFT; break;
case Keycode::RIGHT: mMove = Move::RIGHT; break;
}
}
if (event.data().code == Keycode::MOUSE1) {
if (press) {
mMouse = Mouse::PRESSED;
}
else {
mMouse = Mouse::RELEASED;
}
}
}
}
bool WindowSimpleInputs::Activated() { return mMouse == Mouse::PRESSED; }
bool WindowSimpleInputs::Anticipating() { return mMouse == Mouse::HOLD; }
bool WindowSimpleInputs::Selected() { return mMouse == Mouse::RELEASED; }
bool WindowSimpleInputs::MoveLeft() { return mMove == Move::LEFT; }
bool WindowSimpleInputs::MoveRight() { return mMove == Move::RIGHT; }
bool WindowSimpleInputs::MoveUp() { return mMove == Move::UP; }
bool WindowSimpleInputs::MoveDown() { return mMove == Move::DOWN; }
bool WindowSimpleInputs::Drag() { return mCrsmDelta != 0; }
void ButtonWidget::draw(glw::Canvas& canvas) {
canvas.setCol1(mCol);
canvas.rect(mAnimRec.get(), 1.f);
}
void ButtonWidget::proc(glw::WindowSimpleInputs& inputs) {
auto rec = mAnimRec.get();
mPressed = false;
mAnimRec.setAnimTime(100);
if (rec.inside(inputs.mCrs)) {
if (inputs.Anticipating()) {
auto new_rec = mRect;
new_rec.scale_from_center(0.3f, true);
mAnimRec.setNoTransition(new_rec);
}
else {
mAnimRec.set(mRect);
}
if (inputs.Selected()) {
mPressed = true;
}
}
else {
auto new_rec = mRect;
new_rec.scale_from_center(0.3f, true);
mAnimRec.set(new_rec);
}
}
void CheckBoxWidget::draw(glw::Canvas& canvas) {
canvas.setCol1(mAnimCol.get());
canvas.rect(mAnimRec.get(), 1.f);
}
void CheckBoxWidget::proc(glw::WindowSimpleInputs& inputs) {
auto rec = mAnimRec.get();
mAnimRec.setAnimTime(100);
if (rec.inside(inputs.mCrs)) {
if (inputs.Anticipating()) {
auto new_rec = mRect;
new_rec.scale_from_center(0.3f, true);
mAnimRec.setNoTransition(new_rec);
}
else {
mAnimRec.set(mRect);
}
if (inputs.Selected()) {
mValue = !mValue;
}
}
else {
auto new_rec = mRect;
new_rec.scale_from_center(0.3f, true);
mAnimRec.set(new_rec);
}
if (mValue) {
mAnimCol.set(mColActive);
}
else {
mAnimCol.set(mCol);
}
}
void WindowsHeaderWidget::updRecs() {
auto padding = 0.7f;
auto butt_size = header_rec.w - padding * 2.f;
grab_rec = { header_rec.pos, { header_rec.z - header_rec.w * 4, header_rec.w } };
mPinButton.mRect = { { grab_rec.pos.x + grab_rec.size.x + padding, grab_rec.y + padding }, butt_size };
mMinButton.mRect = { { mPinButton.mRect.pos.x + mPinButton.mRect.size.x + padding * 2, mPinButton.mRect.y }, butt_size };
mMaxButton.mRect = { { mMinButton.mRect.pos.x + mMinButton.mRect.size.x + padding * 2, mPinButton.mRect.y }, butt_size };
mExitButton.mRect = { { mMaxButton.mRect.pos.x + mMaxButton.mRect.size.x + padding * 2, mPinButton.mRect.y }, butt_size };
mPinButton.mCol = { 0.3f, 0.3f, 0.3f, 0.9f};
mMinButton.mCol = { 0.3f, 0.3f, 0.8f, 0.9f };
mMaxButton.mCol = { 0.3f, 0.8f, 0.3f, 0.9f };
mExitButton.mCol = { 0.8f, 0.3f, 0.3f, 0.9f };
}
void WindowsHeaderWidget::draw(glw::Canvas& canvas) {
updRecs();
canvas.setCol1(col);
canvas.rect(header_rec, 1.f);
canvas.setCol1(1.f);
canvas.text("MemLeaks", grab_rec, 4.f);
mExitButton.draw(canvas);
mMaxButton.draw(canvas);
mMinButton.draw(canvas);
mPinButton.draw(canvas);
}
void WindowsHeaderWidget::proc(glw::Window& window, glw::WindowSimpleInputs& inputs) {
get_time();
mExitButton.proc(inputs);
mMaxButton.proc(inputs);
mMinButton.proc(inputs);
mPinButton.proc(inputs);
window.mAppearence.mMinMaxBox = mMaxButton.mRect * inputs.mScaleVal;
window.mAppearence.mCaptionsAddArea = { grab_rec * inputs.mScaleVal };
window.mAppearence.mMinimized = mMinButton.mPressed;
window.mEvents.mClose = mExitButton.mPressed;
window.mAppearence.mTopZ = mPinButton.mValue;
}

View file

@ -0,0 +1,216 @@
#include "texture.h"
#include "map.h"
#include "stringt.h"
#include "shader.h"
#include "GraphicsLibApi.h"
const char* texture_vertex =
#ifdef ENV_OS_ANDROID
"#version 300 es\n"
"precision mediump float;\n"
#else
"#version 330 core\n"
#endif
"layout(location = 0) in vec3 vPos;\n"
"out vec2 UV;\n"
"void main() {\n"
" gl_Position = vec4(vPos, 1);\n"
" UV = (vPos.xy + vec2(1, 1)) / 2.0;\n"
"}\n";
const char* texture_fragment =
#ifdef ENV_OS_ANDROID
"#version 300 es\n"
"precision mediump float;\n"
#else
"#version 330 core\n"
#endif
"in vec2 UV;\n"
"out vec4 color;\n"
"uniform sampler2D renderedTexture;\n"
"uniform float time;\n"
"void main() {\n"
" vec4 texColor = texture(renderedTexture, UV);\n"
" if (texColor.a < 0.2)\n"
" discard;\n"
" color = texColor;\n"
"}\n";
namespace tp {
using namespace glw;
GLuint texture::getid() { return id; }
texture::texture() {
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
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_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
}
texture::~texture() { glDeleteTextures(1, &id); }
alni texture::sizeAllocatedMem() {
return sizeof(GLuint);
}
alni texture::sizeUsedMem() {
return sizeof(GLuint);
}
void texture::update(const Array2D<rgba>& buff) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)buff.size().x, (GLsizei)buff.size().y, 0, GL_RGBA, GL_FLOAT, buff.buff());
}
void texture::draw(const GLuint& out) {
draw_texture(out, id);
}
struct texture_drawer_data {
HashMap<GLuint, string> textures;
GLuint quad_VertexArrayID;
GLuint quad_vertexbuffer;
GLuint texID;
glw::shader shader;
const GLfloat g_quad_vertex_buffer_data[18] = {
-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
};
texture_drawer_data() : shader(texture_vertex, NULL, texture_fragment, false) {
// The fullscreen quad's FBO
glGenVertexArrays(1, &quad_VertexArrayID);
glBindVertexArray(quad_VertexArrayID);
glGenBuffers(1, &quad_vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data),
g_quad_vertex_buffer_data, GL_STATIC_DRAW);
texID = shader.getu("renderedTexture");
}
~texture_drawer_data() {
glDeleteBuffers(1, &quad_vertexbuffer);
glDeleteVertexArrays(1, &quad_VertexArrayID);
for (auto tex : textures) {
glDeleteTextures(1, &tex->val);
}
}
};
texture_drawer_data* texdd = NULL;
void texture::init() {
if (!texdd) texdd = new texture_drawer_data();
}
void texture::deinit() {
if (texdd) delete texdd;
texdd = NULL;
}
void texture::draw_texture(uint4 out, uint4 in) {
assert(in);
// Render to the screen
glBindFramebuffer(GL_FRAMEBUFFER, out);
// Use our shader
texdd->shader.bind();
// Bind our texture in Texture Unit 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, in);
// Set our "renderedTexture" sampler to use Texture Unit 0
glUniform1i(texdd->texID, 0);
// glUniformMatrix4fv(texdd->rect_mat, 1, GL_FALSE, &tmat[0][0]);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, texdd->quad_vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
// Draw the triangles. 2*3 indices starting at 0 -> 2 triangles
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(0);
texdd->shader.unbind();
}
GLuint load_texture(string name) {
GLuint tex_2d = 0;
RelAssert(0 && "incomplete compilation - no SOIL support added");
if (0) {
//auto document = lunasvg::Document::loadFromFile("tiger.svg");
//auto bitmap = document->renderToBitmap();
}
else {
/*
tex_2d = SOIL_load_OGL_texture(
name.cstr(), SOIL_LOAD_RGBA, SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB |
SOIL_FLAG_COMPRESS_TO_DXT);
if (0 == tex_2d) {
printf("SOIL loading error: '%s'\n", SOIL_last_result());
}
*/
}
return tex_2d;
}
GLuint texture::get_tex(const char* TexId) {
GLuint out = 0;
alni idx = texdd->textures.presents(TexId);
if (idx != -1) {
out = texdd->textures.get(TexId);
}
else {
out = load_texture(TexId);
texdd->textures.put(TexId, out);
}
return out;
}
void texture::drawCurcle(vec2f pos, double radius, rgba col) {
#ifndef ENV_OS_ANDROID
static alni precision = 40;
glColor4f(col.r, col.g, col.b, col.a);
double twicePi = 2.0 * 3.142;
glBegin(GL_TRIANGLE_FAN); // BEGIN CIRCLE
glVertex2f(pos.x, pos.y); // center of circle
for (alni i = 0; i <= precision; i++) {
glVertex2f((GLfloat)(pos.x + (radius * cos(i * twicePi / precision))),
(GLfloat)(pos.y + (radius * sin(i * twicePi / precision))));
}
glEnd(); // END
#endif
}
};

Binary file not shown.

View file

@ -0,0 +1,107 @@
#include "SimpleGui.h"
#include "debugui.h"
#include "texture.h"
#include "timer.h"
#include "imgui.h"
struct CollorWheelWidget {
tp::rgba col = { 0.3f, 0.3f, 0.3f, 0.9f };
tp::rectf rec = { 10, 30, 40, 40 };
void draw(tp::glw::Canvas& canvas) {
canvas.setCol1(col);
canvas.rect(rec, 3.f);
canvas.drawColorwheel(rec, col.rgbs);
}
};
struct Test {
tp::glw::Window window;
tp::glw::DebugUI ui;
tp::glw::Canvas canvas;
tp::glw::WindowsHeaderWidget header;
tp::glw::WindowSimpleInputs inputs;
tp::halnf mHeaderHeight = 6.5f;
CollorWheelWidget colorwheel;
tp::halnf uiscale = 1.f;
tp::Timer time;
tp::halni frames = 0;
tp::halni fps = 0;
Test() : window(), ui(window, debuguiCallBack, this), time(1000) {
tp::glw::texture::init();
canvas.setCol1({ 0.5f, 0.5f, 0.5f, 0.5f });
window.mAppearence.mHiden = false;
}
void proc() {
window.pollEvents();
inputs.update(window, uiscale);
header.header_rec = { (inputs.mWindowSizeMM.x - 60.f) / 2.f, 3.f, 60.f, mHeaderHeight };
header.proc(window, inputs);
}
void draw() {
// window frame
window.beginDraw(); {
// canvas draw
canvas.beginDraw({ { 0, 0 }, inputs.mWindowSizeMM }, window.mDevice.mDPMM, uiscale); {
canvas.clear();
header.draw(canvas);
colorwheel.draw(canvas);
} canvas.endDraw();
// debug draw
ui.drawDebugUI(window.mDevice.mDPMM);
} window.endDraw();
}
void run() {
while (!window.mEvents.mClose) {
proc();
if (window.mEvents.mRedraw || tp::glw::gInTransition) {
draw();
}
if (time.isTimeout()) {
fps = frames;
frames = 0;
time.reset();
}
frames++;
}
}
void debugui() {
static char buff[100];
ImGui::DragFloat("UI SCale", &uiscale, 0.02);
ImGui::Text("Fps: %i", fps);
ImGui::InputText("Fps: %i", buff, 100);
}
static void debuguiCallBack(void* self) {
((Test*)self)->debugui();
}
~Test() {
tp::glw::texture::deinit();
}
};
CROSSPLATFORM_MAIN
int main() {
tp::ModuleManifest* ModuleDependencies[] = { &tp::gModuleGlw, NULL };
tp::ModuleManifest TestModule("Test", NULL, NULL, ModuleDependencies);
if (!TestModule.initialize()) {
return 1;
}
{
Test test;
test.run();
}
TestModule.deinitialize();
}

View file

@ -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>

View file

@ -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; }

View file

@ -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);

View file

@ -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;
}
};
}

View file

@ -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;
};
}

View file

@ -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;
};
}

View file

@ -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;
};
}

View file

@ -1,7 +0,0 @@
#pragma once
#include "Module.hpp"
namespace tp {
extern ModuleManifest gModuleLanguage;
}

View file

@ -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;
};
}

View file

@ -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 };
};
}

View file

@ -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); }
};
}

View file

@ -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;
};
}

View file

@ -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;
}
)";

View file

@ -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; }

View file

@ -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}/")

View file

@ -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();
}

View file

@ -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;
}
}

View file

@ -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; }

View file

@ -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;
};
}

View file

@ -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;
};
}

View file

@ -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)

View file

@ -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;
}

View file

@ -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();
}
}

View file

@ -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;
}

View file

@ -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;
};
}

View file

@ -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

View file

@ -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

View file

@ -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,
}

22
Allocators/CMakeLists.txt Normal file
View file

@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 3.2)
set(CMAKE_CXX_STANDARD 23)
project(Allocators)
### ---------------------- 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_link_libraries(${PROJECT_NAME} PUBLIC Utils)
### -------------------------- Tests -------------------------- ###
enable_testing()
file(GLOB TEST_SOURCES "./tests/*.cpp")
add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES})
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Utils)
add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests)
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/lib)

42
Allocators/README.md Normal file
View 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::gModuleAllocators, 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.
![image](https://user-images.githubusercontent.com/63184036/222794298-3f238de4-c0b8-41fa-b7ec-c0c675da8f05.png)
Also debug.memleaks binary will be generated in the working directory that can be viewved with MemLeaks Viewver.
![image](https://user-images.githubusercontent.com/63184036/222793169-a405effe-72be-42fc-b375-bb06dce0a735.png)
## Memory Usage Analisys
Currently outdated
## Benchmarks
Currently outdated

Some files were not shown because too many files have changed in this diff Show more