commit fc5b0c3897cba875a7c86e7dcfb7bb0afdb1139f Author: dawsh Date: Tue Jun 24 12:43:02 2025 -0500 Initial Commit for Template App diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ad12cf6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/.idea +/.cache +/cmake-build-debug +/build \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/app.rc b/app.rc new file mode 100644 index 0000000..be85f08 --- /dev/null +++ b/app.rc @@ -0,0 +1,4 @@ +MAINICON ICON "redacted.ico" +IDI_ICON1 ICON DISCARDABLE "redacted.ico" +MANIFEST ICON "redacted.ico" +AAA ICON "redacted.ico" \ No newline at end of file diff --git a/assets/redacted.png b/assets/redacted.png new file mode 100644 index 0000000..466f842 Binary files /dev/null and b/assets/redacted.png differ diff --git a/cmake/CPM.cmake b/cmake/CPM.cmake new file mode 100644 index 0000000..68c169b --- /dev/null +++ b/cmake/CPM.cmake @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: MIT +# +# SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors + +set(CPM_DOWNLOAD_VERSION 0.38.7) +set(CPM_HASH_SUM "83e5eb71b2bbb8b1f2ad38f1950287a057624e385c238f6087f94cdfc44af9c5") + +if(CPM_SOURCE_CACHE) + set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +elseif(DEFINED ENV{CPM_SOURCE_CACHE}) + set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +else() + set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +endif() + +# Expand relative path. This is important if the provided path contains a tilde (~) +get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE) + +file(DOWNLOAD + https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake + ${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM} +) + +include(${CPM_DOWNLOAD_LOCATION}) diff --git a/include/App.hpp b/include/App.hpp new file mode 100644 index 0000000..a13a2cf --- /dev/null +++ b/include/App.hpp @@ -0,0 +1,151 @@ +#pragma once +#include + +#include +#include + +#include "JGL/types/Shader.h" +#include "JUI/JUI.hpp" +#include "JUI/Widgets/Scene.hpp" +#include "JUI/Widgets/TextRect.hpp" + +// Our OpenGL wrapper currently targets OpenGL 2.1 +// You can specify a different version if you wish to write your own graphics code. +#define GL_VER_MAJOR 2 +#define GL_VER_MINOR 1 + +class RedactedFrameworkAppTemplate : public ReWindow::OpenGLWindow { +public: + + JGL::Texture* logo = nullptr; + JUI::Scene* scene = nullptr; + + /// Constructs the application class. + /// @param title + /// @param width + /// @param height + RedactedFrameworkAppTemplate(const std::string& title, int width, int height); + + + /// Called after the framework initialization is complete. Loads resources and creates objects. + bool Load(); + + bool Open() override; + + /// Ensure the OpenGL wrapper has the correct canvas size. Good place to update other elements' size as well. + void PropagateWindowSize() { + auto size = GetSize(); + Vector2i vSize = Vector2i(size.x, size.y); + JGL::Update(vSize); + + scene->SetViewportSize(Vector2(vSize)); + } + + void Update(float elapsed) { + scene->Update(elapsed); + } + + Vector2 SizeV2() { + auto size = GetSize(); + return Vector2(size.x, size.y); + } + + Vector2i SizeV2i() { + auto size = GetSize(); + return Vector2i(size.x, size.y); + } + + void DrawBackgroundLogo() { + Vector2 logo_size = Vector2(logo->GetDimensions()); + float scale_coefficient = 0.75f; // The amount to scale the image by. + + // Computes the percentages [0, 1] of the image size relative to the viewport size. + Vector2 scale = SizeV2() / logo_size; + + // We pick the best fit and apply it as a uniform scale. + float best_fit_scale = Math::Min(scale.x, scale.y); + + // The final factor [0, 1] by which to scale the image size. + scale = Vector2(best_fit_scale, best_fit_scale) * scale_coefficient; + + /// The bounding-box of the image after scaling. + Vector2 box_size = Vector2(logo->GetDimensions())*scale; + + // Center of the screen. + Vector2 screen_center = SizeV2() / 2.f; + + // Center of the logo. + Vector2 logo_center = box_size / 2.f; + + // The point at which to draw the logo such that it always appears centered. + // TODO: The `origin` parameter in J2D should perform this calculation for us, so we can specify [0.5, 0.5] and it will render from the center. + Vector2 draw_offset = screen_center - logo_center; + + // Draw the logo's bounding box, as a gradient box. + J2D::FillGradientRect(Colors::Yellow, Colors::Pinks::HotPink, Direction::Diagonal_SWNE, draw_offset, box_size); + J2D::DrawSprite(logo, draw_offset, 0, Vector2::Zero, scale); + } + + + void Render() { + Shader::UseDefault(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + J2D::Begin(); + DrawBackgroundLogo(); + J2D::End(); + + scene->Draw(); + + } + + void OnRefresh(float elapsed) override { + PropagateWindowSize(); + Update(elapsed); + Render(); + SwapBuffers(); + } + + enum JUI::MouseButton ToJUIEnum(const MouseButton& btn) { + + if (btn == MouseButtons::Left) return JUI::MouseButton::Left; + if (btn == MouseButtons::Middle) return JUI::MouseButton::Middle; + if (btn == MouseButtons::Right) return JUI::MouseButton::Right; + + // Default condition. + return JUI::MouseButton::Left; + } + + void OnMouseButtonDown(const ReWindow::MouseButtonDownEvent &e) override { + auto btn = ToJUIEnum(e.Button); + + // Consume mouse clicks that are of interest to the UI scene. + if (scene->ObserveMouseInput(btn, true)) + return; + + // Listen for mouse clicks. + } + void OnMouseButtonUp(const ReWindow::MouseButtonUpEvent &e) override { + auto btn = ToJUIEnum(e.Button); + + if (scene->ObserveMouseInput(btn, false)) return; + } + void OnMouseMove(const ReWindow::MouseMoveEvent &e) override { + Vector2 nmp = Vector2(e.Position.x, e.Position.y); + if (scene->ObserveMouseMovement(nmp)) return; + } + void OnKeyDown(const ReWindow::KeyDownEvent &e) override { + if (scene->ObserveKeyInput(e.key, true)) return; + } + + void OnKeyUp(const ReWindow::KeyUpEvent &e) override { + if (scene->ObserveKeyInput(e.key, false)) return; + } + void OnMouseWheel(const ReWindow::MouseWheelEvent &e) override { + if (scene->ObserveMouseWheel(e.WheelMovement)) return; + } +protected: +private: +}; diff --git a/redacted.ico b/redacted.ico new file mode 100644 index 0000000..e029521 Binary files /dev/null and b/redacted.ico differ diff --git a/src/App.cpp b/src/App.cpp new file mode 100644 index 0000000..fe0808c --- /dev/null +++ b/src/App.cpp @@ -0,0 +1,42 @@ +#include + +RedactedFrameworkAppTemplate::RedactedFrameworkAppTemplate(const std::string &title, int width, int height): OpenGLWindow(title, width, height, GL_VER_MAJOR, GL_VER_MINOR) { + +} + +bool RedactedFrameworkAppTemplate::Load() { + using namespace JUI::UDimLiterals; + + // FilteringMode::Nearest ensures crisp pixels with no "blending". + logo = new JGL::Texture("assets/redacted.png", FilteringMode::NEAREST); + + scene = new JUI::Scene(); + + auto* text_box = new JUI::TextRect(scene); + text_box->Size({200_px, 50_px}); + text_box->SetContent("Redactd Software"); + + return true; +} + +bool RedactedFrameworkAppTemplate::Open() { + if (!OpenGLWindow::Open()) return false; + + auto size = GetSize(); // ReWindow returns an IPair, and we convert it to a J3ML vector to pass to the graphics abstraction. + auto vec_size = Vector2i(size.x, size.y); + if (!JGL::Init(vec_size, 0.f, 1.f)) + return false; + JGL::Update(vec_size); + + glClearColor(0.f, 0.f, 0.f, 0.f); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glDepthMask(GL_TRUE); + // TODO: Delete when we update to the next release of JGL + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // NOTE: This MUST be called for text rendering to work properly!!! + + Load(); + + return true; +}