LibraryViewer
This commit is contained in:
parent
5a55011911
commit
c7d3b15758
24 changed files with 226111 additions and 36 deletions
16
.cproject
Normal file
16
.cproject
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?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>
|
||||||
20
.project
Normal file
20
.project
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?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>
|
||||||
|
|
@ -26,3 +26,4 @@ add_subdirectory(Graphics)
|
||||||
add_subdirectory(RayTracer)
|
add_subdirectory(RayTracer)
|
||||||
add_subdirectory(DataAnalysis)
|
add_subdirectory(DataAnalysis)
|
||||||
add_subdirectory(Objects)
|
add_subdirectory(Objects)
|
||||||
|
add_subdirectory(LibraryViewer)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
#include "Window.hpp"
|
#include "Window.hpp"
|
||||||
|
#include "Timing.hpp"
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
|
|
||||||
|
|
@ -11,6 +12,10 @@ int main() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int frames = 0;
|
||||||
|
int fps = 0;
|
||||||
|
tp::Timer timer(1000);
|
||||||
|
|
||||||
{
|
{
|
||||||
auto window = tp::Window::createWindow(800, 600, "Window 1");
|
auto window = tp::Window::createWindow(800, 600, "Window 1");
|
||||||
|
|
||||||
|
|
@ -18,9 +23,17 @@ int main() {
|
||||||
while (!window->shouldClose()) {
|
while (!window->shouldClose()) {
|
||||||
window->processEvents();
|
window->processEvents();
|
||||||
|
|
||||||
ImGui::Text("Hello!");
|
ImGui::Text("fps: %i", fps);
|
||||||
|
|
||||||
window->draw();
|
window->draw();
|
||||||
|
|
||||||
|
if (timer.isTimeout()) {
|
||||||
|
fps = frames;
|
||||||
|
frames = 0;
|
||||||
|
timer.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
frames++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,9 @@ halnf AnimValue::interpolate() const {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimValue::AnimValue() = default;
|
AnimValue::AnimValue() {
|
||||||
|
mTimeStart = gCurrentTime;
|
||||||
|
}
|
||||||
|
|
||||||
void AnimValue::setAnimTime(halni time) { mTimeAnim = time; }
|
void AnimValue::setAnimTime(halni time) { mTimeAnim = time; }
|
||||||
|
|
||||||
|
|
@ -39,7 +41,9 @@ void AnimValue::set(halnf val) {
|
||||||
if (val == mVal) return;
|
if (val == mVal) return;
|
||||||
mValPrev = get();
|
mValPrev = get();
|
||||||
mVal = val;
|
mVal = val;
|
||||||
if (!inTransition()) mTimeStart = (halni) gCurrentTime;
|
if (!inTransition()) {
|
||||||
|
mTimeStart = gCurrentTime;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
halnf AnimValue::getTarget() const { return mVal; }
|
halnf AnimValue::getTarget() const { return mVal; }
|
||||||
|
|
@ -47,14 +51,19 @@ halnf AnimValue::getTarget() const { return mVal; }
|
||||||
void AnimValue::setNoTransition(halnf val) {
|
void AnimValue::setNoTransition(halnf val) {
|
||||||
mValPrev = val;
|
mValPrev = val;
|
||||||
mVal = val;
|
mVal = val;
|
||||||
mTimeStart -= mTimeStart;
|
mTimeStart = gCurrentTime - mTimeAnim;
|
||||||
}
|
}
|
||||||
|
|
||||||
halnf AnimValue::get() const {
|
halnf AnimValue::get() const {
|
||||||
if (inTransition()) {
|
if (inTransition()) {
|
||||||
gInTransition = true;
|
gInTransition = true;
|
||||||
|
return interpolate();
|
||||||
}
|
}
|
||||||
return interpolate();
|
return mVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnimValue::operator=(halnf val) {
|
||||||
|
setNoTransition(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimValue::operator halnf() const { return get(); }
|
AnimValue::operator halnf() const { return get(); }
|
||||||
|
|
@ -84,6 +93,8 @@ void AnimRect::set(const RectF& in) {
|
||||||
w.set(in.w);
|
w.set(in.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AnimColor::AnimColor() : mColor() {}
|
||||||
|
|
||||||
RGBA AnimColor::get() const {
|
RGBA AnimColor::get() const {
|
||||||
auto col = mColor.get();
|
auto col = mColor.get();
|
||||||
return { col.x, col.y, col.z, col.w };
|
return { col.x, col.y, col.z, col.w };
|
||||||
|
|
|
||||||
|
|
@ -23,31 +23,78 @@ Graphics::Canvas::Canvas() { mContext = new Context(); }
|
||||||
|
|
||||||
Graphics::Canvas::~Canvas() { delete mContext; }
|
Graphics::Canvas::~Canvas() { delete mContext; }
|
||||||
|
|
||||||
void Graphics::Canvas::init() { mContext->vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES); }
|
void Graphics::Canvas::init() {
|
||||||
|
mContext->vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
|
||||||
|
|
||||||
|
if (nvgCreateFont(mContext->vg, "default", "Font.ttf") == -1) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Graphics::Canvas::deinit() {
|
void Graphics::Canvas::deinit() {
|
||||||
// Cleanup
|
|
||||||
nvgDeleteGL3(mContext->vg);
|
nvgDeleteGL3(mContext->vg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::Canvas::proc() {
|
RectF Graphics::Canvas::getAvaliableArea() {
|
||||||
auto width = 600;
|
return { (halnf) 0, (halnf) 0, mWidth, mHeight };
|
||||||
auto height = 600;
|
}
|
||||||
|
|
||||||
// Start NanoVG rendering
|
void Graphics::Canvas::rect(const RectF& rec, const RGBA& col, halnf round) {
|
||||||
nvgBeginFrame(mContext->vg, width, height, 1.0);
|
|
||||||
|
|
||||||
// Draw a rectangle
|
|
||||||
nvgBeginPath(mContext->vg);
|
nvgBeginPath(mContext->vg);
|
||||||
nvgRect(mContext->vg, 50, 50, 50, 50);
|
|
||||||
nvgFillColor(mContext->vg, nvgRGBf(0.8f, 0.4f, 0.1f));
|
if (round == 0) {
|
||||||
nvgFill(mContext->vg);
|
nvgRect(mContext->vg, rec.x, rec.y, rec.z, rec.w);
|
||||||
|
} else {
|
||||||
|
nvgRoundedRect(mContext->vg, rec.x, rec.y, rec.z, rec.w, round);
|
||||||
|
}
|
||||||
|
|
||||||
// End NanoVG rendering
|
nvgFillColor(mContext->vg, { col.r, col.g, col.b, col.a });
|
||||||
nvgEndFrame(mContext->vg);
|
nvgFill(mContext->vg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::Canvas::text(const String& string, const RectF& aRec, halnf size, Align align, halnf marging, const RGBA& col) {
|
||||||
|
RectF rec = { aRec.x + marging, aRec.y + marging, aRec.z - marging * 2, aRec.w - marging * 2 };
|
||||||
|
|
||||||
|
nvgScissor(mContext->vg, rec.x, rec.y, rec.z, rec.w);
|
||||||
|
|
||||||
|
nvgFontSize(mContext->vg, size);
|
||||||
|
nvgFontFace(mContext->vg, "default");
|
||||||
|
nvgFillColor(mContext->vg, { col.r, col.g, col.b, col.a } );
|
||||||
|
|
||||||
|
float centerX = rec.x;
|
||||||
|
float centerY = rec.y;
|
||||||
|
int alignNVG = 0;
|
||||||
|
|
||||||
|
if (((int1*)&align)[1] == 0x00) { // center x
|
||||||
|
alignNVG |= NVG_ALIGN_CENTER;
|
||||||
|
centerX += rec.z * 0.5f;
|
||||||
|
} else if (((int1*)&align)[1] == 0x01) { // left x
|
||||||
|
alignNVG |= NVG_ALIGN_LEFT;
|
||||||
|
} else if (((int1*)&align)[1] == 0x02) { // right x
|
||||||
|
alignNVG |= NVG_ALIGN_RIGHT;
|
||||||
|
centerX += rec.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((int1*)&align)[0] == 0x00) { // center y
|
||||||
|
alignNVG |= NVG_ALIGN_MIDDLE;
|
||||||
|
centerY += rec.w * 0.5f;
|
||||||
|
} else if (((int1*)&align)[0] == 0x01) { // top y
|
||||||
|
alignNVG |= NVG_ALIGN_TOP;
|
||||||
|
centerY += rec.w;
|
||||||
|
} else if (((int1*)&align)[0] == 0x02) { // bottom y
|
||||||
|
alignNVG |= NVG_ALIGN_BOTTOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvgTextAlign(mContext->vg, alignNVG);
|
||||||
|
|
||||||
|
nvgText(mContext->vg, centerX, centerY, string.read(), nullptr);
|
||||||
|
nvgResetScissor(mContext->vg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::Canvas::proc() {
|
||||||
|
nvgBeginFrame(mContext->vg, mWidth, mHeight, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::Canvas::draw() {
|
void Graphics::Canvas::draw() {
|
||||||
// End NanoVG rendering
|
|
||||||
nvgEndFrame(mContext->vg);
|
nvgEndFrame(mContext->vg);
|
||||||
}
|
}
|
||||||
|
|
@ -47,37 +47,45 @@ void Graphics::GL::deinit() {
|
||||||
glDeleteVertexArrays(1, &mContext->vao);
|
glDeleteVertexArrays(1, &mContext->vao);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::GL::proc() { glClear(GL_COLOR_BUFFER_BIT); }
|
void Graphics::GL::proc() {
|
||||||
|
}
|
||||||
|
|
||||||
void Graphics::GL::draw() { glDrawArrays(GL_TRIANGLES, 0, 3); }
|
void Graphics::GL::draw() {
|
||||||
|
glClearColor(0.f, 0.f, 0.f, 0.f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||||
|
glViewport(0, 0, mWidth, mHeight);
|
||||||
|
// glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
void Graphics::init(Window* window) {
|
void Graphics::init(Window* window) {
|
||||||
mGl.init();
|
mGl.init();
|
||||||
mGui.init(window);
|
//mGui.init(window);
|
||||||
mCanvas.init();
|
mCanvas.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::deinit() {
|
void Graphics::deinit() {
|
||||||
mCanvas.deinit();
|
mCanvas.deinit();
|
||||||
mGui.deinit();
|
// mGui.deinit();
|
||||||
mGl.deinit();
|
mGl.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::proc() {
|
void Graphics::proc() {
|
||||||
mGl.proc();
|
mGl.proc();
|
||||||
mCanvas.proc();
|
mCanvas.proc();
|
||||||
mGui.proc();
|
// mGui.proc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::draw() {
|
void Graphics::draw() {
|
||||||
mGl.draw();
|
mGl.draw();
|
||||||
mCanvas.draw();
|
mCanvas.draw();
|
||||||
mGui.draw();
|
// mGui.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::Window(int width, int height, const char* title) {
|
Window::Window(int width, int height, const char* title) {
|
||||||
mContext = new Context();
|
mContext = new Context();
|
||||||
|
|
||||||
|
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, 1);
|
||||||
|
|
||||||
// Create a window and OpenGL context
|
// Create a window and OpenGL context
|
||||||
mContext->window = glfwCreateWindow(width, height, title, nullptr, nullptr);
|
mContext->window = glfwCreateWindow(width, height, title, nullptr, nullptr);
|
||||||
if (!mContext->window) {
|
if (!mContext->window) {
|
||||||
|
|
@ -94,6 +102,11 @@ Window::Window(int width, int height, const char* title) {
|
||||||
}
|
}
|
||||||
|
|
||||||
mGraphics.init(this);
|
mGraphics.init(this);
|
||||||
|
|
||||||
|
mContext->inputManager.init(mContext->window);
|
||||||
|
glfwSetWindowUserPointer(mContext->window, &mContext->inputManager);
|
||||||
|
|
||||||
|
mEvents.mContext = mContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::~Window() {
|
Window::~Window() {
|
||||||
|
|
@ -136,12 +149,44 @@ bool Window::shouldClose() const { return glfwWindowShouldClose(mContext->window
|
||||||
|
|
||||||
void Window::processEvents() {
|
void Window::processEvents() {
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
||||||
|
int w, h;
|
||||||
|
glfwGetWindowSize(mContext->window, &w, &h);
|
||||||
|
|
||||||
|
mGraphics.mCanvas.mWidth = w;
|
||||||
|
mGraphics.mCanvas.mHeight = h;
|
||||||
|
|
||||||
|
mGraphics.mGl.mWidth = w;
|
||||||
|
mGraphics.mGl.mHeight = h;
|
||||||
|
|
||||||
mGraphics.proc();
|
mGraphics.proc();
|
||||||
|
|
||||||
|
mContext->inputManager.update();
|
||||||
|
get_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::draw() {
|
void Window::draw() {
|
||||||
mGraphics.draw();
|
mGraphics.draw();
|
||||||
glfwSwapBuffers(mContext->window);
|
glfwSwapBuffers(mContext->window);
|
||||||
|
mContext->inputManager.resetScroll();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Window::getContext() -> Context* { return mContext; }
|
auto Window::getContext() -> Context* { return mContext; }
|
||||||
|
Graphics::Canvas& Window::getCanvas() { return mGraphics.mCanvas; }
|
||||||
|
const Window::Events& Window::getEvents() { return mEvents; }
|
||||||
|
|
||||||
|
const Vec2F& Window::Events::getPos() const {
|
||||||
|
return mContext->inputManager.getPos();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Window::Events::isPressed() const {
|
||||||
|
return mContext->inputManager.isPressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Window::Events::isDown() const {
|
||||||
|
return mContext->inputManager.isDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
halnf Window::Events::getScrollY() const {
|
||||||
|
return mContext->inputManager.getScrollY();
|
||||||
|
}
|
||||||
|
|
@ -2,10 +2,100 @@
|
||||||
|
|
||||||
// -------- Window Context -------- //
|
// -------- Window Context -------- //
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace tp {
|
namespace tp {
|
||||||
|
|
||||||
class Window;
|
class Window;
|
||||||
|
|
||||||
|
class InputManager {
|
||||||
|
public:
|
||||||
|
InputManager() = default;
|
||||||
|
|
||||||
|
void init(GLFWwindow* aWindow) {
|
||||||
|
window = aWindow;
|
||||||
|
// Set up key and mouse button callbacks
|
||||||
|
glfwSetKeyCallback(window, keyCallback);
|
||||||
|
glfwSetMouseButtonCallback(window, mouseButtonCallback);
|
||||||
|
glfwSetScrollCallback(window, scrollCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vec2F& getPos() const { return mousePos; }
|
||||||
|
|
||||||
|
bool isKeyPressed(int key) const {
|
||||||
|
return keyStates[key] == GLFW_PRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isKeyDown(int key) const {
|
||||||
|
return keyStates[key] == GLFW_REPEAT || keyStates[key] == GLFW_PRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isPressed() const {
|
||||||
|
return mouseButtonStates[GLFW_MOUSE_BUTTON_LEFT] == GLFW_PRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDown() const {
|
||||||
|
return mouseButtonStates[GLFW_MOUSE_BUTTON_LEFT] == GLFW_REPEAT || mouseButtonStates[GLFW_MOUSE_BUTTON_LEFT] == GLFW_PRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
double getScrollY() const { return scrollY; }
|
||||||
|
|
||||||
|
// bool isScrollDown() const { return scrollY < 0.0; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend Window;
|
||||||
|
|
||||||
|
static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
|
||||||
|
InputManager* inputManager = static_cast<InputManager*>(glfwGetWindowUserPointer(window));
|
||||||
|
|
||||||
|
if (!inputManager) {
|
||||||
|
// Update key state
|
||||||
|
if (action == GLFW_PRESS) {
|
||||||
|
inputManager->keyStates[key] = GLFW_PRESS;
|
||||||
|
} else if (action == GLFW_RELEASE) {
|
||||||
|
inputManager->keyStates[key] = GLFW_RELEASE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods) {
|
||||||
|
InputManager* inputManager = static_cast<InputManager*>(glfwGetWindowUserPointer(window));
|
||||||
|
|
||||||
|
if (inputManager) {
|
||||||
|
// Update mouse button state
|
||||||
|
inputManager->mouseButtonStates[button] = action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) {
|
||||||
|
InputManager* inputManager = static_cast<InputManager*>(glfwGetWindowUserPointer(window));
|
||||||
|
|
||||||
|
if (inputManager) {
|
||||||
|
// Update scroll state
|
||||||
|
inputManager->scrollX = xoffset;
|
||||||
|
inputManager->scrollY = yoffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update() {
|
||||||
|
double x, y;
|
||||||
|
glfwGetCursorPos(window, &x, &y);
|
||||||
|
mousePos = { x, y };
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetScroll() {
|
||||||
|
scrollX = 0.0;
|
||||||
|
scrollY = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double scrollX = 0.0;
|
||||||
|
double scrollY = 0.0;
|
||||||
|
GLFWwindow* window;
|
||||||
|
Vec2F mousePos;
|
||||||
|
std::array<int, GLFW_KEY_LAST + 1> keyStates = { GLFW_RELEASE };
|
||||||
|
std::array<int, GLFW_MOUSE_BUTTON_LAST + 1> mouseButtonStates = { GLFW_RELEASE };
|
||||||
|
};
|
||||||
|
|
||||||
class Window::Context {
|
class Window::Context {
|
||||||
friend Graphics::GL;
|
friend Graphics::GL;
|
||||||
friend Graphics::GUI;
|
friend Graphics::GUI;
|
||||||
|
|
@ -13,5 +103,6 @@ namespace tp {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLFWwindow* window;
|
GLFWwindow* window;
|
||||||
|
InputManager inputManager;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -32,9 +32,9 @@ namespace tp {
|
||||||
|
|
||||||
class AnimRect : Rect<AnimValue> {
|
class AnimRect : Rect<AnimValue> {
|
||||||
public:
|
public:
|
||||||
AnimRect() {
|
AnimRect() {
|
||||||
set({ 0, 0, 0, 0 });
|
|
||||||
setAnimTime(450);
|
setAnimTime(450);
|
||||||
|
setNoTransition({ 0, 0, 0, 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] RectF get() const;
|
[[nodiscard]] RectF get() const;
|
||||||
|
|
@ -45,9 +45,10 @@ namespace tp {
|
||||||
};
|
};
|
||||||
|
|
||||||
class AnimColor {
|
class AnimColor {
|
||||||
|
public:
|
||||||
|
AnimColor();
|
||||||
AnimRect mColor;
|
AnimRect mColor;
|
||||||
|
|
||||||
public:
|
|
||||||
[[nodiscard]] RGBA get() const;
|
[[nodiscard]] RGBA get() const;
|
||||||
void set(const RGBA&);
|
void set(const RGBA&);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include "GraphicsCommon.hpp"
|
#include "GraphicsCommon.hpp"
|
||||||
|
|
||||||
|
// TODO : fix this ugly shit
|
||||||
|
|
||||||
namespace tp {
|
namespace tp {
|
||||||
class Window;
|
class Window;
|
||||||
|
|
||||||
|
|
@ -13,17 +15,22 @@ namespace tp {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend Graphics;
|
friend Graphics;
|
||||||
|
friend Window;
|
||||||
|
|
||||||
GL();
|
GL();
|
||||||
~GL();
|
~GL();
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void deinit();
|
void deinit();
|
||||||
static void proc();
|
void proc();
|
||||||
static void draw();
|
void draw();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// TODO : API
|
// TODO : API
|
||||||
|
|
||||||
|
private:
|
||||||
|
halnf mWidth = 100;
|
||||||
|
halnf mHeight = 100;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GUI {
|
class GUI {
|
||||||
|
|
@ -51,6 +58,7 @@ namespace tp {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend Graphics;
|
friend Graphics;
|
||||||
|
friend Window;
|
||||||
|
|
||||||
Canvas();
|
Canvas();
|
||||||
~Canvas();
|
~Canvas();
|
||||||
|
|
@ -61,7 +69,27 @@ namespace tp {
|
||||||
void draw();
|
void draw();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum Align : int2 {
|
||||||
|
CC = 0x0000,
|
||||||
|
CT = 0x0001,
|
||||||
|
CB = 0x0002,
|
||||||
|
LC = 0x0100,
|
||||||
|
LT = 0x0101,
|
||||||
|
LB = 0x0102,
|
||||||
|
RC = 0x0200,
|
||||||
|
RT = 0x0201,
|
||||||
|
RB = 0x0202,
|
||||||
|
};
|
||||||
|
|
||||||
|
RectF getAvaliableArea();
|
||||||
|
void rect(const RectF& rec, const RGBA& col, halnf round = 0);
|
||||||
|
void text(const String&, const RectF&, halnf size, Align, halnf marging, const RGBA&);
|
||||||
|
|
||||||
// TODO : API
|
// TODO : API
|
||||||
|
|
||||||
|
private:
|
||||||
|
halnf mWidth = 600;
|
||||||
|
halnf mHeight = 600;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
// TODO : fix this ugly shit
|
||||||
|
|
||||||
#include "Buffer.hpp"
|
#include "Buffer.hpp"
|
||||||
#include "Graphics.hpp"
|
#include "Graphics.hpp"
|
||||||
#include "Keycodes.hpp"
|
#include "Keycodes.hpp"
|
||||||
|
|
@ -14,10 +16,23 @@ namespace tp {
|
||||||
enum Type {
|
enum Type {
|
||||||
KEY,
|
KEY,
|
||||||
MOUSE,
|
MOUSE,
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Events {
|
||||||
|
Vec2F mPointer;
|
||||||
|
|
||||||
|
const Vec2F& getPos() const;
|
||||||
|
bool isPressed() const;
|
||||||
|
bool isDown() const;
|
||||||
|
halnf getScrollY() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend Window;
|
||||||
|
Buffer<Event> mQueu;
|
||||||
|
Context* mContext;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Window(int width, int height, const char* title);
|
Window(int width, int height, const char* title);
|
||||||
~Window();
|
~Window();
|
||||||
|
|
@ -33,10 +48,12 @@ namespace tp {
|
||||||
|
|
||||||
auto getContext() -> Context*;
|
auto getContext() -> Context*;
|
||||||
|
|
||||||
|
Graphics::Canvas& getCanvas();
|
||||||
|
const Events& getEvents();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Context* mContext;
|
Context* mContext;
|
||||||
Graphics mGraphics;
|
Graphics mGraphics;
|
||||||
|
Events mEvents;
|
||||||
Buffer<Event> mEvents;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
17
LibraryViewer/CMakeLists.txt
Normal file
17
LibraryViewer/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
project(LibraryViewer)
|
||||||
|
|
||||||
|
### ---------------------- Static Library --------------------- ###
|
||||||
|
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
|
||||||
|
file(GLOB HEADERS "./public/*.hpp" "./public/*/*.hpp" "./applications/*.hpp")
|
||||||
|
|
||||||
|
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
|
||||||
|
|
||||||
|
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PUBLIC Graphics Connection)
|
||||||
|
|
||||||
|
file(COPY "library" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
||||||
|
file(COPY "applications/Font.ttf" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
||||||
|
|
||||||
|
### -------------------------- Applications -------------------------- ###
|
||||||
|
add_executable(libView ./applications/Entry.cpp)
|
||||||
|
target_link_libraries(libView ${PROJECT_NAME} LibraryViewer)
|
||||||
46
LibraryViewer/applications/Entry.cpp
Normal file
46
LibraryViewer/applications/Entry.cpp
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
|
||||||
|
#include "NewPlacement.hpp"
|
||||||
|
#include "LibraryGui.hpp"
|
||||||
|
|
||||||
|
// events
|
||||||
|
// animations
|
||||||
|
// monitor resource usage
|
||||||
|
// sorting
|
||||||
|
|
||||||
|
void runApp() {
|
||||||
|
|
||||||
|
Library library;
|
||||||
|
library.loadJson("library/Library.json");
|
||||||
|
|
||||||
|
auto gui = LibraryWidget<tp::Window::Events, tp::Graphics::Canvas>(&library);
|
||||||
|
|
||||||
|
auto window = tp::Window::createWindow(800, 600, "Window 1");
|
||||||
|
|
||||||
|
if (window) {
|
||||||
|
while (!window->shouldClose()) {
|
||||||
|
window->processEvents();
|
||||||
|
|
||||||
|
auto area = window->getCanvas().getAvaliableArea();
|
||||||
|
|
||||||
|
gui.proc(window->getEvents(), {}, { area.x, area.y, area.z, area.w });
|
||||||
|
gui.draw(window->getCanvas(), {}, { area.x, area.y, area.z, area.w });
|
||||||
|
|
||||||
|
window->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tp::Window::destroyWindow(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
tp::ModuleManifest* deps[] = { &tp::gModuleLibraryViewer, nullptr };
|
||||||
|
tp::ModuleManifest binModule("LibViewEntry", nullptr, nullptr, deps);
|
||||||
|
|
||||||
|
if (!binModule.initialize()) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
runApp();
|
||||||
|
|
||||||
|
binModule.deinitialize();
|
||||||
|
}
|
||||||
BIN
LibraryViewer/applications/Font.ttf
Normal file
BIN
LibraryViewer/applications/Font.ttf
Normal file
Binary file not shown.
102806
LibraryViewer/library/Library.json
Normal file
102806
LibraryViewer/library/Library.json
Normal file
File diff suppressed because it is too large
Load diff
121340
LibraryViewer/library/Library.xml
Normal file
121340
LibraryViewer/library/Library.xml
Normal file
File diff suppressed because it is too large
Load diff
96
LibraryViewer/library/convert.py
Normal file
96
LibraryViewer/library/convert.py
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
import xmltodict
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
def flatten_dict(d):
|
||||||
|
|
||||||
|
out = []
|
||||||
|
for song in d:
|
||||||
|
newSong = {}
|
||||||
|
|
||||||
|
strCount = 0
|
||||||
|
intCount = 0
|
||||||
|
dateCount = 0
|
||||||
|
|
||||||
|
def getStr(id):
|
||||||
|
nonlocal strCount
|
||||||
|
if id not in song["key"]:
|
||||||
|
return "undef"
|
||||||
|
if len(song["string"]) <= strCount:
|
||||||
|
return "error"
|
||||||
|
strCount += 1
|
||||||
|
return song["string"][strCount - 1]
|
||||||
|
|
||||||
|
def getInt(id):
|
||||||
|
nonlocal intCount
|
||||||
|
if id not in song["key"]:
|
||||||
|
return -1
|
||||||
|
if len(song["integer"]) <= intCount:
|
||||||
|
return -1
|
||||||
|
intCount += 1
|
||||||
|
return song["integer"][intCount - 1]
|
||||||
|
|
||||||
|
def getDate(id):
|
||||||
|
nonlocal dateCount
|
||||||
|
if id not in song["key"]:
|
||||||
|
return "undef"
|
||||||
|
if len(song["date"]) <= dateCount:
|
||||||
|
return "error"
|
||||||
|
dateCount += 1
|
||||||
|
return song["date"][dateCount - 1]
|
||||||
|
|
||||||
|
newSong["Track ID"] = getInt("Track ID")
|
||||||
|
newSong["Name"] = getStr("Name")
|
||||||
|
newSong["Artist"] = getStr("Artist")
|
||||||
|
newSong["Album Artist"] = getStr("Album Artist")
|
||||||
|
newSong["Composer"] = getStr("Composer")
|
||||||
|
newSong["Album"] = getStr("Album")
|
||||||
|
newSong["Genre"] = getStr("Genre")
|
||||||
|
newSong["Kind"] = getStr("Kind")
|
||||||
|
newSong["Size"] = getInt("Size")
|
||||||
|
newSong["Total Time"] = getInt("Total Time")
|
||||||
|
newSong["Disc Number"] = getInt("Disc Number")
|
||||||
|
newSong["Disc Count"] = getInt("Disc Count")
|
||||||
|
newSong["Track Number"] = getInt("Track Number")
|
||||||
|
newSong["Track Count"] = getInt("Track Count")
|
||||||
|
newSong["Year"] = getInt("Year")
|
||||||
|
newSong["Date Modified"] = getDate("Date Modified")
|
||||||
|
newSong["Date Added"] = getDate("Date Added")
|
||||||
|
newSong["Bit Rate"] = getInt("Bit Rate")
|
||||||
|
newSong["Sample Rate"] = getInt("Sample Rate")
|
||||||
|
newSong["Play Count"] = getInt("Play Count")
|
||||||
|
newSong["Play Date"] = getInt("Play Date")
|
||||||
|
newSong["Play Date UTC"] = getDate("Play Date UTC")
|
||||||
|
newSong["Skip Count"] = getInt("Skip Count")
|
||||||
|
newSong["Skip Date"] = getDate("Skip Date")
|
||||||
|
newSong["Release Date"] = getDate("Release Date")
|
||||||
|
newSong["Album Rating"] = getInt("Album Rating")
|
||||||
|
newSong["Album Rating Computed"] = "Album Rating Computed" in song["key"]
|
||||||
|
newSong["Loved"] = "Loved" in song["key"]
|
||||||
|
newSong["Album Loved"] = "Album Loved" in song["key"]
|
||||||
|
newSong["Explicit"] = "Explicit" in song["key"]
|
||||||
|
newSong["Compilation"] = "Compilation" in song["key"]
|
||||||
|
newSong["Artwork Count"] = getInt("Artwork Count")
|
||||||
|
newSong["Sort Album"] = getStr("Sort Album")
|
||||||
|
newSong["Sort Artist"] = getStr("Sort Artist")
|
||||||
|
newSong["Sort Name"] = getStr("Sort Name")
|
||||||
|
newSong["Persistent ID"] = getStr("Persistent ID")
|
||||||
|
newSong["Track Type"] = getStr("Track Type")
|
||||||
|
|
||||||
|
out.append(newSong)
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
with open('Library.xml', 'r', encoding='utf-8') as xml_file:
|
||||||
|
data_dict = xmltodict.parse(xml_file.read())
|
||||||
|
|
||||||
|
# Extract the "Tracks" dictionary to be flattened
|
||||||
|
tracks_dict = data_dict['plist']['dict']['dict']
|
||||||
|
|
||||||
|
flat_tracks_dict = flatten_dict(tracks_dict["dict"])
|
||||||
|
|
||||||
|
|
||||||
|
json_data = json.dumps(flat_tracks_dict, indent=2)
|
||||||
|
|
||||||
|
with open('output.json', 'w', encoding='utf-8') as json_file:
|
||||||
|
json_file.write(json_data)
|
||||||
49
LibraryViewer/private/LibraryViewer.cpp
Normal file
49
LibraryViewer/private/LibraryViewer.cpp
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
|
||||||
|
#include "LibraryViewer.hpp"
|
||||||
|
#include "LocalConnection.hpp"
|
||||||
|
|
||||||
|
#include "picojson.h"
|
||||||
|
|
||||||
|
namespace tp {
|
||||||
|
static ModuleManifest* deps[] = { &gModuleGraphics, &gModuleConnection, nullptr };
|
||||||
|
ModuleManifest gModuleLibraryViewer = ModuleManifest("LibraryViewer", nullptr, nullptr, deps);
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace tp;
|
||||||
|
|
||||||
|
bool Library::loadJson(const String& path) {
|
||||||
|
LocalConnection libraryFile;
|
||||||
|
Buffer<int1> libraryFileMem;
|
||||||
|
|
||||||
|
if (!libraryFile.connect(LocalConnection::Location(path), LocalConnection::Type(true))) return false;
|
||||||
|
|
||||||
|
libraryFileMem.reserve(libraryFile.size());
|
||||||
|
libraryFile.readBytes(libraryFileMem.getBuff(), libraryFile.size());
|
||||||
|
|
||||||
|
std::string json = libraryFileMem.getBuff();
|
||||||
|
picojson::value jsonNode;
|
||||||
|
std::string err = picojson::parse(jsonNode, json);
|
||||||
|
|
||||||
|
if (! err.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto & traks = jsonNode.get<picojson::array>();
|
||||||
|
for (auto & trackNode : traks) {
|
||||||
|
Track newTrack;
|
||||||
|
|
||||||
|
auto & track = trackNode.get<picojson::object>();
|
||||||
|
for (auto & trackProperty : track) {
|
||||||
|
if (trackProperty.first == "Name") {
|
||||||
|
newTrack.mName = (int1*) trackProperty.second.to_str().c_str();
|
||||||
|
}
|
||||||
|
else if (trackProperty.first == "Artist") {
|
||||||
|
newTrack.mArtist = (int1*) trackProperty.second.to_str().c_str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mTraks.append(newTrack);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
192
LibraryViewer/public/LibraryGui.hpp
Normal file
192
LibraryViewer/public/LibraryGui.hpp
Normal file
|
|
@ -0,0 +1,192 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "LibraryViewer.hpp"
|
||||||
|
#include "Rect.hpp"
|
||||||
|
#include "Animations.hpp"
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept DrawableConcept = true;
|
||||||
|
|
||||||
|
template <typename Events, typename Canvas> requires(DrawableConcept<Canvas>)
|
||||||
|
class ScrollBarWidget {
|
||||||
|
public:
|
||||||
|
ScrollBarWidget() = default;
|
||||||
|
|
||||||
|
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& area) {
|
||||||
|
if (mSizeFraction > 1.f) return;
|
||||||
|
|
||||||
|
if (!areaParent.isOverlap(area)) {
|
||||||
|
mIsScrolling = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events.getScrollY() != 0) {
|
||||||
|
auto offset = events.getScrollY() < 0 ? 1.0f : -1.0f;
|
||||||
|
if (scrollInertia * offset > 0) {
|
||||||
|
scrollInertia += offset;
|
||||||
|
} else {
|
||||||
|
scrollInertia = -scrollInertia + offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tp::abs(scrollInertia) > 0.1f) {
|
||||||
|
auto offset = scrollInertia * mScrollFactor;
|
||||||
|
mPositionFraction += offset;
|
||||||
|
mPositionFraction = tp::clamp(mPositionFraction, 0.f, 1.f - mSizeFraction);
|
||||||
|
scrollInertia *= 0.f;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events.isPressed() && area.isInside(events.getPos())) {
|
||||||
|
mIsScrolling = true;
|
||||||
|
} else if (!events.isDown()) {
|
||||||
|
mIsScrolling = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mIsScrolling) {
|
||||||
|
tp::halnf pos = events.getPos().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 draw(Canvas& canvas, const tp::RectF& areaParent, const tp::RectF& area) {
|
||||||
|
if (mSizeFraction > 1.f) return;
|
||||||
|
if (!areaParent.isOverlap(area)) return;
|
||||||
|
|
||||||
|
auto minSize = 10.f;
|
||||||
|
tp::RGBA col = tp::RGBA{ 0.25f, 0.25f, 0.25f, 1.f };
|
||||||
|
|
||||||
|
if (mIsScrolling) {
|
||||||
|
col = tp::RGBA{ 0.45f, 0.45f, 0.45f, 1.f };
|
||||||
|
minSize = 20.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.rect(area, { 0.15f, 0.15f, 0.15f, 1.f }, 4.f);
|
||||||
|
auto sliderSize = tp::clamp(area.w * mSizeFraction, minSize, area.w);
|
||||||
|
auto diffSize = sliderSize - area.w * mSizeFraction;
|
||||||
|
canvas.rect({ area.x, area.y + (area.w - diffSize) * mPositionFraction, area.z, sliderSize }, col, 4.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
tp::halnf mScrollFactor = 0.f;
|
||||||
|
tp::halnf scrollInertia = 0.f;
|
||||||
|
bool mIsScrolling = false;
|
||||||
|
tp::halnf mSizeFraction = 1.f;
|
||||||
|
tp::halnf mPositionFraction = 0.f;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Events, typename Canvas> requires(DrawableConcept<Canvas>)
|
||||||
|
class TrackWidget {
|
||||||
|
public:
|
||||||
|
TrackWidget(const Track* track) : mTrack(track) {
|
||||||
|
col.mColor.setAnimTime(0);
|
||||||
|
col.mColor.setNoTransition({ 0.15f, 0.15f, 0.15f, 0.f });
|
||||||
|
};
|
||||||
|
|
||||||
|
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& area) {
|
||||||
|
if (!areaParent.isOverlap(area)) return;
|
||||||
|
if (area.isInside(events.getPos())) {
|
||||||
|
col.set( { 0.15f, 0.15f, 0.15f, 1.f } );
|
||||||
|
insideDebug = true;
|
||||||
|
} else {
|
||||||
|
col.set( { 0.15f, 0.15f, 0.15f, 0.f } );
|
||||||
|
insideDebug = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw(Canvas& canvas, const tp::RectF& areaParent, const tp::RectF& area) {
|
||||||
|
if (!areaParent.isOverlap(area)) return;
|
||||||
|
|
||||||
|
canvas.rect(area, col.get(), 4.f);
|
||||||
|
|
||||||
|
const tp::RectF imageArea = { area.x + marging, area.y + marging, area.w - marging * 2, area.w - marging * 2 };
|
||||||
|
canvas.rect(imageArea, { 0.25f, 0.25f, 0.25f, 1.f }, 4.f);
|
||||||
|
|
||||||
|
const tp::RectF textArea = { area.x + area.w + marging, area.y + marging, area.z - area.w - marging * 2, area.w - marging * 2 };
|
||||||
|
// canvas.rect(textArea, { 0.25f, 0.25f, 0.25f, 1.f }, 4.f);
|
||||||
|
|
||||||
|
const tp::RectF textAreaName = { textArea.x, textArea.y, textArea.z, textArea.w * 0.5f };
|
||||||
|
const tp::RectF textAreaAuthor = { textArea.x, textArea.y + textArea.w * 0.5f, textArea.z, textArea.w * 0.5f };
|
||||||
|
|
||||||
|
canvas.text(mTrack->mName.read(), textAreaName, 15.f, Canvas::LC, 4.f, { 0.9f, 0.9f, 0.9f, 1.f} );
|
||||||
|
canvas.text(mTrack->mArtist.read(), textAreaAuthor, 12.f, Canvas::LC, 4.f, { 0.8f, 0.8f, 0.8f, 1.f} );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
tp::halnf marging = 5.f;
|
||||||
|
bool insideDebug = false;
|
||||||
|
tp::AnimColor col;
|
||||||
|
const Track* mTrack;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Events, typename Canvas> requires(DrawableConcept<Canvas>)
|
||||||
|
class LibraryWidget {
|
||||||
|
public:
|
||||||
|
LibraryWidget(Library* lib) : mLibrary(lib) {
|
||||||
|
for (auto track : mLibrary->mTraks) {
|
||||||
|
mTraks.append(TrackWidget<Events, Canvas>(&track.data()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) {
|
||||||
|
|
||||||
|
area = { aArea.x, aArea.y, aArea.z, aArea.w - controllPanelSize };
|
||||||
|
areaCP = { aArea.x, aArea.y + aArea.w - controllPanelSize, aArea.z, controllPanelSize };
|
||||||
|
|
||||||
|
mScroll.mSizeFraction = area.w / (mLibrary->mTraks.size() * trackSize);
|
||||||
|
mScroll.mScrollFactor = 1.f / mLibrary->mTraks.size();
|
||||||
|
|
||||||
|
if (area.isInside(events.getPos())) {
|
||||||
|
|
||||||
|
mScroll.proc(events, area, { area.x + area.z - scrollSize - 3, area.y + 10, scrollSize - 3.f, area.w - 20 } );
|
||||||
|
|
||||||
|
tp::halnf offset = mScroll.mPositionFraction * mLibrary->mTraks.size() * trackSize;
|
||||||
|
auto idx = 0;
|
||||||
|
|
||||||
|
for (auto track : mTraks) {
|
||||||
|
track->proc(events, area, { area.x + 10, area.y + 10 + idx * trackSize - offset, area.z - 20 - scrollSize, trackSize - 5 } );
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debugPos = events.getPos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw(Canvas& canvas, const tp::RectF& areaParent, const tp::RectF& aArea) {
|
||||||
|
canvas.rect(aArea, { 0.1f, 0.1f, 0.1f, 1.f });
|
||||||
|
|
||||||
|
tp::halnf offset = mScroll.mPositionFraction * mLibrary->mTraks.size() * trackSize;
|
||||||
|
auto idx = 0;
|
||||||
|
|
||||||
|
for (auto track : mTraks) {
|
||||||
|
track->draw(canvas, area, { area.x + 10, area.y + 10 + idx * trackSize - offset, area.z - 20 - scrollSize, trackSize - 5 } );
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
mScroll.draw(canvas, area, { area.x + area.z - scrollSize - 3, area.y + 10, scrollSize - 3.f, area.w - 20 } );
|
||||||
|
|
||||||
|
drawCP(canvas, aArea, areaCP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawCP(Canvas& canvas, const tp::RectF& areaParent, const tp::RectF& area) {
|
||||||
|
canvas.rect( area, { 0.04f, 0.04f, 0.04f, 1.f });
|
||||||
|
mTraks.first().draw(canvas, area, area);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
tp::halnf scrollSize = 15;
|
||||||
|
tp::halnf controllPanelSize = 70;
|
||||||
|
tp::halnf trackSize = 60;
|
||||||
|
tp::Vec2F debugPos;
|
||||||
|
|
||||||
|
tp::RectF area;
|
||||||
|
tp::RectF areaCP;
|
||||||
|
|
||||||
|
tp::Buffer<TrackWidget<Events, Canvas>> mTraks;
|
||||||
|
ScrollBarWidget<Events, Canvas> mScroll;
|
||||||
|
Library* mLibrary;
|
||||||
|
};
|
||||||
31
LibraryViewer/public/LibraryViewer.hpp
Normal file
31
LibraryViewer/public/LibraryViewer.hpp
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Window.hpp"
|
||||||
|
|
||||||
|
namespace tp {
|
||||||
|
extern ModuleManifest gModuleLibraryViewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Track {
|
||||||
|
public:
|
||||||
|
Track() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
tp::String mName = "undef";
|
||||||
|
tp::String mArtist = "undef";
|
||||||
|
};
|
||||||
|
|
||||||
|
class Library {
|
||||||
|
public:
|
||||||
|
Library() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool loadJson(const tp::String& path);
|
||||||
|
|
||||||
|
public:
|
||||||
|
tp::Buffer<Track> mTraks;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LibraryViewverGui {};
|
||||||
|
|
||||||
|
void runApp();
|
||||||
1200
LibraryViewer/public/picojson.h
Normal file
1200
LibraryViewer/public/picojson.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,6 @@
|
||||||
|
|
||||||
|
/// whoaoao wtf
|
||||||
|
|
||||||
#include "MathCommon.hpp"
|
#include "MathCommon.hpp"
|
||||||
|
|
||||||
#include "ContainersCommon.hpp"
|
#include "ContainersCommon.hpp"
|
||||||
|
|
@ -16,6 +18,7 @@ tp::alnf std_rad(tp::alnf val);
|
||||||
tp::alnf std_deg(tp::alnf val);
|
tp::alnf std_deg(tp::alnf val);
|
||||||
tp::alnf std_atan2(tp::alnf X, tp::alnf Y);
|
tp::alnf std_atan2(tp::alnf X, tp::alnf Y);
|
||||||
tp::alnf std_atan(tp::alnf val);
|
tp::alnf std_atan(tp::alnf val);
|
||||||
|
tp::alnf std_log2(tp::alnf val);
|
||||||
|
|
||||||
tp::alnf tp::sin(const tp::alnf radians) { return std_sin((halnf) radians); }
|
tp::alnf tp::sin(const tp::alnf radians) { return std_sin((halnf) radians); }
|
||||||
tp::alnf tp::tan(const tp::alnf radians) { return std_tan((halnf) radians); }
|
tp::alnf tp::tan(const tp::alnf radians) { return std_tan((halnf) radians); }
|
||||||
|
|
@ -26,6 +29,7 @@ tp::alnf tp::rad(const tp::alnf val) { return val * (PI / 180.f); }
|
||||||
tp::alnf tp::deg(const tp::alnf val) { return val * (180.f / PI); }
|
tp::alnf tp::deg(const tp::alnf val) { return val * (180.f / PI); }
|
||||||
tp::alnf tp::atan2(const tp::alnf X, const tp::alnf Y) { return std_atan2((halnf) X, (halnf) Y); }
|
tp::alnf tp::atan2(const tp::alnf X, const tp::alnf Y) { return std_atan2((halnf) X, (halnf) Y); }
|
||||||
tp::alnf tp::atan(const tp::alnf val) { return std_atan((halnf) val); }
|
tp::alnf tp::atan(const tp::alnf val) { return std_atan((halnf) val); }
|
||||||
|
tp::alnf tp::log2(alnf val) { return std_log2(val); }
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
|
@ -37,4 +41,5 @@ tp::alnf std_sqrt(const tp::alnf val) { return sqrt((tp::halnf) val); }
|
||||||
tp::alnf std_rad(const tp::alnf val) { return val * (PI / 180.f); }
|
tp::alnf std_rad(const tp::alnf val) { return val * (PI / 180.f); }
|
||||||
tp::alnf std_deg(const tp::alnf val) { return val * (180.f / PI); }
|
tp::alnf std_deg(const tp::alnf val) { return val * (180.f / PI); }
|
||||||
tp::alnf std_atan2(const tp::alnf X, const tp::alnf Y) { return atan2((tp::halnf) X, (tp::halnf) Y); }
|
tp::alnf std_atan2(const tp::alnf X, const tp::alnf Y) { return atan2((tp::halnf) X, (tp::halnf) Y); }
|
||||||
tp::alnf std_atan(const tp::alnf val) { return atan((tp::halnf) val); }
|
tp::alnf std_atan(const tp::alnf val) { return atan((tp::halnf) val); }
|
||||||
|
tp::alnf std_log2(const tp::alnf val) { return log2((tp::halnf) val); }
|
||||||
|
|
@ -25,4 +25,5 @@ namespace tp {
|
||||||
alnf sqrt(alnf val);
|
alnf sqrt(alnf val);
|
||||||
alnf rad(alnf val);
|
alnf rad(alnf val);
|
||||||
alnf deg(alnf val);
|
alnf deg(alnf val);
|
||||||
|
alnf log2(alnf val);
|
||||||
}
|
}
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
#include "Intersections.hpp"
|
#include "Intersections.hpp"
|
||||||
|
|
||||||
|
#define INRANGE(v, l, u) (v >= l && v <= u)
|
||||||
|
|
||||||
namespace tp {
|
namespace tp {
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue