Initial commit

This commit is contained in:
scientiist
2023-05-07 16:00:32 -05:00
commit e77fe1837d
26 changed files with 648 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
# Project exclude paths
/cmake-build-debug/

8
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

2
.idea/JUI.iml generated Normal file
View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />

4
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/JUI.iml" filepath="$PROJECT_DIR$/.idea/JUI.iml" />
</modules>
</component>
</project>

20
CMakeLists.txt Normal file
View File

@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.24)
project(JUI)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "-pedantic -Wall -Wextra")
# Add SDL2 CMake modules
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdl2)
# Add all c++ source
file(GLOB SOURCES "src/*.cpp")
include_directories(include)
add_library(JUI SHARED ${SOURCES})
add_executable(JUI_Demo ${SOURCES})
target_link_libraries(JUI_Demo PUBLIC JUI SDL2 SDL2_image SDL2_ttf)

15
include/JUI/Color.hpp Normal file
View File

@@ -0,0 +1,15 @@
#pragma once
#include <cstdint>
namespace JUI
{
class Color {
public:
uint8_t R;
uint8_t G;
uint8_t B;
uint8_t A;
protected:
private:
};
}

View File

@@ -0,0 +1,8 @@
//
// Created by josh on 5/7/23.
//
#ifndef JUI_HORIZONTALLAYOUTCONTAINER_HPP
#define JUI_HORIZONTALLAYOUTCONTAINER_HPP
#endif //JUI_HORIZONTALLAYOUTCONTAINER_HPP

10
include/JUI/Rect.hpp Normal file
View File

@@ -0,0 +1,10 @@
#pragma once
#include <JUI/Widget.hpp>
#include <JUI/Color.hpp>
namespace JUI {
class Rect : Widget {
};
}

10
include/JUI/Scene.hpp Normal file
View File

@@ -0,0 +1,10 @@
#pragma once
#include <JUI/Widget.hpp>
namespace JUI
{
class Scene : public Widget {
};
}

1
include/JUI/Slider.hpp Normal file
View File

@@ -0,0 +1 @@
#pragma once

20
include/JUI/Text.hpp Normal file
View File

@@ -0,0 +1,20 @@
#pragma once
#include <JUI/Widget.hpp>
#include <JUI/Color.hpp>
namespace JUI
{
// Text Widget
// Morphs to the size of the parent Container
// TODO: Rich Text Support
class Text : Widget {
std::string Text;
Color TextColor;
Color TextOutlineColor;
float TextOutline;
bool RichTextEnabled;
};
}

1
include/JUI/TextEdit.hpp Normal file
View File

@@ -0,0 +1 @@
#pragma once

1
include/JUI/Texture.hpp Normal file
View File

@@ -0,0 +1 @@
#pragma once

View File

@@ -0,0 +1,8 @@
//
// Created by josh on 5/7/23.
//
#ifndef JUI_VERTICALLAYOUTCONTAINER_H
#define JUI_VERTICALLAYOUTCONTAINER_H
#endif //JUI_VERTICALLAYOUTCONTAINER_H

39
include/JUI/Widget.hpp Normal file
View File

@@ -0,0 +1,39 @@
#pragma once
#include <memory>
#include <vector>
#include <Vector2.hpp>
namespace JUI
{
class Widget : public std::enable_shared_from_this<Widget> {
public:
Widget();
virtual ~Widget();
virtual void Draw() {}
virtual void Update(float delta) {}
void setParent(Widget* parent);
Widget* getParent();
protected:
private:
Widget* parent = nullptr;
std::vector<std::shared_ptr<Widget>> children;
//std::string name = "Instance";
// Copy Parent-Child hierarchy from Redwood...
};
void Widget::setParent(Widget *parent) {
//std::shared_ptr<Widget> shared = shared_from_this();
}
Widget* Widget::getParent() { }
}

41
include/JUI/jui.h Normal file
View File

@@ -0,0 +1,41 @@
// Josh's UI Toolkit
// Ported to C++ / SDL
// Copyright 2023 Conarium Software LLC
#include <vector>
#include <memory>
#include <Vector2.hpp>
#pragma once
namespace JUI
{
class ScreenCoordinates
{
int PixelsX;
int PixelsY;
float ScaleX;
float ScaleY;
};
// TODO: Get sum rectangles rendering in SDL2
class Layout { };
class VerticalLayoutContainer : Layout { };
class HorizontalLayoutContainer : Layout { };
class GridLayoutContainer : Layout { };
class TextLabel : Widget { };
class Slider : Widget {};
class Checkbox : Widget {};
class LineEdit : Widget { };
class NineSlice : Widget { };
class ContextButton : Widget { };
class ScrollRect : Widget { };
}

45
include/Math.hpp Normal file
View File

@@ -0,0 +1,45 @@
#include <random>
typedef float float32;
typedef double float64;
typedef long double float128;
typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef uint64_t uint64;
typedef int8_t int8;
typedef int16_t int16;
typedef int32_t int32;
typedef int64_t int64;
class Math{
public:
static float32 Lerp(float32 a, float32 b, float32 t) { return (1-t)*a + t*b; }
static float64 Lerp(float64 a, float64 b, float64 t) { return (1-t)*a + t*b; }
static float128 Lerp(float128 a, float128 b, float128 t) { return (1-t)*a + t*b; }
static float32 Round(float32 n, int decimals = 0) {
float32 deci = 10^(decimals);
return floor(n*deci+0.5)/deci;
}
static float64 Round(float64 n, int decimals = 0) {
float64 deci = 10^(decimals);
return floor(n*deci+0.5)/deci;
}
static float128 Round(float128 n, int decimals = 0) {
float128 deci = 10^(decimals);
return floor(n*deci+0.5)/deci;
}
static float32 Clamp(float32 n, float32 min, float32 max) {
return std::min(std::max(min, n), max);
}
static float64 Clamp(float64 n, float64 min, float64 max) {
return std::min(std::max(min, n), max);
}
static float128 Clamp(float128 n, float128 min, float128 max) {
return std::min(std::max(min, n), max);
}
};

38
include/SDLGame.hpp Normal file
View File

@@ -0,0 +1,38 @@
#pragma once
#include <Vector2.hpp>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
class SDLGame {
public:
virtual void Initialize();
virtual void Cleanup();
virtual void Update(float delta);
virtual void Draw();
// Starts Render & Gametic Threads
void Run();
void Gameloop();
void RunFrame();
void Render();
bool Focused;
bool Paused;
Vector2 GetWindowSize();
void SetWindowSize(int x, int y);
void SetWindowSize(Vector2 const&v);
protected:
bool requestQuit;
float frameDelta;
float tickDelta;
int frameCount;
SDL_Event event;
SDL_Renderer *renderer;
SDL_Window *window;
void handleEvents();
};

View File

@@ -0,0 +1,17 @@
#pragma once
#include <JUI/Scene.hpp>
#include "SDLGame.hpp"
class JUIDemoGame : public SDLGame
{
public:
JUI::Scene Gui;
void Initialize() override;
void Draw() override;
void Update(float delta) override;
protected:
private:
};

58
include/Vector2.hpp Normal file
View File

@@ -0,0 +1,58 @@
#pragma once
#include <ostream>
class Vector2
{
public:
static const Vector2 Zero;
static const Vector2 One;
static Vector2 Max(Vector2 const&input, Vector2 const&max);
static Vector2 Min(Vector2 const&input, Vector2 const&min);
static Vector2 Perp(Vector2 const&rhs);
static Vector2 Clamp(const Vector2& input, Vector2 const& min, Vector2 const& max);
static Vector2 Lerp(Vector2 const&start, Vector2 const&goal, float alpha);
static float Dot(Vector2 const&rhs, Vector2 const&lhs);
static float Magnitude(Vector2 const&vec);
static float Distance(Vector2 const&, Vector2 const&);
friend Vector2 operator*(float t, Vector2 const&rhs);
friend std::ostream& operator<< (std::ostream& os, const Vector2& vector);
Vector2();
Vector2(float const& x, float const& y);
Vector2(const Vector2& vec);
float GetX() const { return this->X; }
float GetY() const { return this->Y; }
Vector2 Max(const Vector2& max) const;
Vector2 Min(const Vector2& min) const;
Vector2 Normalize() const;
Vector2 Floor() const;
Vector2 Ceil() const;
Vector2 Perp() const;
Vector2 Clamp(Vector2 const& min, Vector2 const& max);
Vector2 Lerp(Vector2& goal, float alpha) const;
float Dot(Vector2 const&against) const;
float Magnitude() const;
float Distance(const Vector2& to) const;
bool operator==(const Vector2& rhs) const;
bool operator!=(const Vector2& rhs) const;
Vector2& operator=(const Vector2&) = default;
Vector2 operator+(const Vector2& rhs) const;
Vector2 operator-(const Vector2& rhs) const;
Vector2 operator*(const Vector2& rhs) const;
Vector2 operator/(const Vector2& rhs) const;
Vector2 operator*(float rhs) const;
Vector2 operator/(float rhs) const;
float X;
float Y;
private:
};

6
src/JUI/Color.cpp Normal file
View File

@@ -0,0 +1,6 @@
#include <JUI/Color.hpp>
namespace JUI
{
}

101
src/SDLGame.cpp Normal file
View File

@@ -0,0 +1,101 @@
#include <SDLGame.hpp>
#include <Vector2.hpp>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <chrono>
#include <thread>
#include <iostream>
Vector2 SDLGame::GetWindowSize() {
int* x;
int* y;
SDL_GetWindowSize(window, x, y);
return {*x, *y};
}
void SDLGame::SetWindowSize(int x, int y) {
SDL_SetWindowSize(window, x, y);
}
void SDLGame::SetWindowSize(Vector2 const&v) {
SDL_SetWindowSize(window, v.GetX(), v.GetY());
}
void SDLGame::Draw() { }
void SDLGame::Render() {
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
Draw();
SDL_RenderPresent(renderer);
}
void SDLGame::Update(float delta) { }
void SDLGame::handleEvents() {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT)
requestQuit = true;
if (event.window.event == SDL_WINDOWEVENT_FOCUS_LOST)
Focused = false;
if (event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
Focused = true;
}
}
void SDLGame::Run()
{
Gameloop();
}
void SDLGame::Gameloop() {
while (!requestQuit) {
RunFrame();
}
}
void SDLGame::RunFrame()
{
this->handleEvents(); // Include this in timing?
auto start = std::chrono::high_resolution_clock::now();
this->Update(frameDelta);
this->Render();
// TODO: Refactor time tracking to seconds, so we can actually use it in Gametick() sanely
if (!Focused)
std::this_thread::sleep_for(std::chrono::microseconds((62500 - 1000)));
auto stop = std::chrono::high_resolution_clock::now();
frameDelta = std::chrono::duration_cast<std::chrono::microseconds>(start-stop).count();
if (frameDelta < 1000 && Focused)
std::this_thread::sleep_for(std::chrono::microseconds(1000 - (int) frameDelta));
frameCount++;
}
void SDLGame::Cleanup() {
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
exit(1);
}
void SDLGame::Initialize() {
if (SDL_Init(SDL_INIT_VIDEO) < 0)
std::cerr << "SDL_Error: " << SDL_GetError() << std::endl;
window = SDL_CreateWindow("Re: Backyard Monsters", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1152, 864, SDL_WINDOW_SHOWN);
SDL_SetWindowResizable(window, SDL_TRUE);
if (window == nullptr) {
std::cerr << "SDL_Error: " << SDL_GetError() << std::endl;
}
int imgFlags = IMG_INIT_PNG;
if (!(IMG_Init(imgFlags) & imgFlags))
std::cerr << "SDL_Error: " << "Couldn't init SDL_Image." << std::endl;
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_RenderSetLogicalSize(renderer, 1152, 864);
SDL_GL_SetSwapInterval(0);
SDL_UpdateWindowSurface(window);
}

View File

@@ -0,0 +1,19 @@
#include "TestBench/JUIDemoGame.hpp"
void JUIDemoGame::Initialize() {
SDLGame::Initialize();
Gui = JUI::Scene();
}
void JUIDemoGame::Update(float delta) {
SDLGame::Update(delta);
}
void JUIDemoGame::Draw() {
SDLGame::Draw();
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_Rect urAFuckingNi{0,0,40,40};
SDL_RenderFillRect(renderer, &urAFuckingNi);
}

156
src/Vector2.cpp Normal file
View File

@@ -0,0 +1,156 @@
#include <Vector2.hpp>
#include <ostream>
#include <sstream>
#include <cmath>
#include <Math.hpp>
constexpr float VectorEqualityMarginOfError = 0.000001f;
inline Vector2::Vector2()
{
this->X = 0;
this->Y = 0;
}
inline Vector2::Vector2(float const& x, float const& y) : X(x), Y(y) {}
Vector2::Vector2(const Vector2& inp)
{
this->X = inp.X;
this->Y = inp.Y;
}
Vector2 Vector2::Max(const Vector2& max) const {
return Vector2(
std::max(GetX(), max.GetX()),
std::max(GetY(), max.GetY()));
}
Vector2 Vector2::Min(const Vector2& max) const {
return Vector2(
std::min(GetX(), max.GetX()),
std::min(GetY(), max.GetY()));
}
inline Vector2 Vector2::Normalize() const {
return (1.f /(Magnitude(*this))) * (*this);
}
Vector2 Vector2::Floor() const {
return Vector2(std::floor(GetX()), std::floor(GetY()));
}
Vector2 Vector2::Ceil() const {
return Vector2(std::ceil(GetX()), std::ceil(GetY()));
}
// Returns perpendicular Vector2
Vector2 Vector2::Perp() const { return Vector2(-this->Y, this->X); }
inline Vector2 Vector2::Clamp(Vector2 const&min, Vector2 const&max) {
return Vector2(
Math::Clamp(this->X, min.X, max.X),
Math::Clamp(this->Y, min.Y, max.Y));
}
inline Vector2 Vector2::Lerp(Vector2& goal, float alpha) const {
return this->operator*(1.0f-alpha) + (goal*alpha);
}
inline Vector2 Vector2::Lerp(Vector2 const&start, Vector2 const&goal, float alpha) {
}
inline float Vector2::Dot(Vector2 const&against) const {
return this->X*against.X+this->Y*against.Y;
}
inline float Vector2::Dot(Vector2 const&lhs, Vector2 const&rhs) {
return lhs.X*rhs.X+lhs.Y*rhs.Y;
}
inline float Vector2::Magnitude() const {
return sqrt(this->Dot(*this));
}
inline float Vector2::Distance(const Vector2& to) const {
double xsep = Y-to.Y;
double ysep = X-to.X;
return sqrt(ysep*ysep + xsep*xsep);
}
inline bool Vector2::operator==(const Vector2& rhs) const {
return ((X*rhs.X<VectorEqualityMarginOfError)&&(Y * rhs.Y < VectorEqualityMarginOfError));
}
inline bool Vector2::operator!=(const Vector2& rhs) const {
return (X != rhs.X) || (Y != rhs.Y);
}
inline Vector2 Vector2::operator+(const Vector2& rhs) const
{
return Vector2(this->X + rhs.X, this->Y+rhs.Y);
}
inline Vector2 Vector2::operator-(const Vector2& rhs) const
{
return Vector2(this->X - rhs.X, this->Y-rhs.Y);
}
inline Vector2 Vector2::operator*(const Vector2& rhs) const
{
return Vector2(this->X * rhs.X, this->Y * rhs.Y);
}
Vector2 Vector2::operator/(const Vector2& rhs) const
{
return Vector2(this->X / rhs.X, this->Y / rhs.Y);
}
Vector2 Vector2::operator/(float rhs) const {
return Vector2(this->X / rhs, this->Y / rhs);
}
Vector2 Vector2::operator*(float rhs) const {
return Vector2(this->X * rhs, this->Y * rhs);
}
const Vector2 Vector2::Zero = Vector2(0,0);
const Vector2 Vector2::One = Vector2(1, 1);
std::ostream &operator<<(std::ostream& os, const Vector2& vector)
{
std::stringstream stream;
stream << "{X: " << vector.GetX() << ", Y: " << vector.GetY();
os.write(const_cast<char*>(stream.str().c_str()), static_cast<std::streamsize>(stream.str().size() * sizeof(char)));
return os;
}
// Static Class Methods
inline Vector2 operator-(Vector2 const&lhs, Vector2 const&rhs) {
return Vector2(lhs.GetX()-rhs.GetX(), lhs.GetY()-rhs.GetY());
}
inline Vector2 operator+(Vector2 const&lhs, Vector2 const&rhs) {
return Vector2(lhs.GetX()+rhs.GetY(), lhs.GetX() + rhs.GetY());
}
inline Vector2 operator/(Vector2 const&lhs, float const&rhs) {
return Vector2(lhs.GetX()/rhs, lhs.GetY()/rhs);
}
inline Vector2 operator*(float lhs, Vector2 const &rhs) {
return Vector2(rhs.X * lhs, rhs.Y * lhs);
}
inline bool operator!=(Vector2 const&lhs, Vector2 const&rhs) {
return (lhs.X !=rhs.X) || (lhs.Y != rhs.Y);
}
inline bool operator==(Vector2 const&lhs, Vector2 const&rhs) {
return ((lhs.X*rhs.X<VectorEqualityMarginOfError)&&(lhs.Y * rhs.Y < VectorEqualityMarginOfError));
}
inline Vector2 Vector2::Perp(Vector2 const&rhs) { return Vector2(-rhs.Y, rhs.X);}
inline float Vector2::Distance(Vector2 const&lhs, Vector2 const&rhs)
{
double xsep = lhs.Y-rhs.Y;
double ysep = lhs.X-rhs.X;
return sqrt(ysep*ysep + xsep*xsep);
}
inline float Vector2::Magnitude(Vector2 const&lhs) {
return sqrt(Dot(lhs, lhs));
}
inline Vector2 Vector2::Clamp(const Vector2& input, const Vector2& min, const Vector2& max) {
return Vector2(
Math::Clamp(input.X, min.X, max.X),
Math::Clamp(input.Y, min.Y, max.Y));
}
Vector2 Vector2::Max(const Vector2 &input, const Vector2 &max) {
return Vector2(
std::max(input.X, max.X),
std::max(input.Y, max.Y));
}
Vector2 Vector2::Min(const Vector2 &input, const Vector2 &min) {
return Vector2(
std::min(input.X, min.X),
std::min(input.Y, min.Y));
}

10
src/main.cpp Normal file
View File

@@ -0,0 +1,10 @@
#include "TestBench/JUIDemoGame.hpp"
int main() {
auto* game = new JUIDemoGame();
game->Initialize();
game->Run();
game->Cleanup();
delete game;
return 0;
}