Port to C++
This commit is contained in:
parent
5541f9657f
commit
5aaf616f34
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -1,8 +1,10 @@
|
|||
# Directories
|
||||
.dub
|
||||
*/docs/
|
||||
*/docs
|
||||
.vscode
|
||||
.idea
|
||||
build
|
||||
.kdev4/
|
||||
|
||||
# Files
|
||||
*.so
|
||||
|
@ -16,6 +18,8 @@
|
|||
*.o
|
||||
*.obj
|
||||
*.lst
|
||||
*.user
|
||||
*.kdev4
|
||||
docs.json
|
||||
__dummy.html
|
||||
dub.selections.json
|
||||
dub.selections.json
|
||||
|
|
7
compile.sh
Normal file
7
compile.sh
Normal file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ ! -d build ]; then
|
||||
meson build
|
||||
fi
|
||||
|
||||
cd build && meson compile
|
8
core/callback.hpp
Normal file
8
core/callback.hpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "logging/types.hpp"
|
||||
|
||||
namespace hibis {
|
||||
typedef void (*LoggerCallback)(LoggingSeverity severity, std::string message);
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
name "core"
|
||||
license "LGPL-3.0"
|
||||
targetType "library"
|
||||
targetName "hibiscore"
|
50
core/engine/engine.cpp
Normal file
50
core/engine/engine.cpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
#include "enginever.hpp"
|
||||
#include "engine.hpp"
|
||||
|
||||
namespace hibis {
|
||||
Engine::Engine(Renderer* renderer, LoggerCallback logger) {
|
||||
this->renderer = renderer;
|
||||
loggerCallback = logger;
|
||||
previousProcessTick = 0.00001f;
|
||||
previousPhysicsProcessTick = 0.00001f;
|
||||
|
||||
//watch.start();
|
||||
|
||||
this->loggerCallback(Information, "Started Hibis!");
|
||||
}
|
||||
|
||||
Engine::~Engine() {
|
||||
//watch.stop();
|
||||
}
|
||||
|
||||
void Engine::runNodeProcesses() {
|
||||
// TODO: fix delta then adapt for runNodePhysicsProcesses
|
||||
//const float current = watch.peek.total!"msecs" / 1_000;
|
||||
//float delta = (current - previousProcessTick);
|
||||
|
||||
for (Node* node : nodeList) {
|
||||
node->physicsProcess(0.00f);
|
||||
}
|
||||
|
||||
//this.previousProcessTick = watch.peek.total!"msecs" / 1_000;
|
||||
}
|
||||
|
||||
void Engine::runNodePhysicsProcesses() {
|
||||
// TODO: See above TODO
|
||||
// Schade! Have the wrong function content while I figure out how std.datetime.watch works
|
||||
//const float current = watch.peek.total!"msecs" / 1_000;
|
||||
//float delta = (current - previousProcessTick);
|
||||
|
||||
for (Node* node : nodeList) {
|
||||
node->physicsProcess(0.00f);
|
||||
}
|
||||
|
||||
//this.previousPhysicsProcessTick = watch.peek.total!"msecs" / 1_000;
|
||||
}
|
||||
|
||||
void Engine::drawNodes() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
const char* Engine::getEngineVersion() { return HIBIS_VERSION; }
|
||||
}
|
31
core/engine/engine.hpp
Normal file
31
core/engine/engine.hpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../renderer/renderer.hpp"
|
||||
#include "../callback.hpp"
|
||||
#include "../node/node.hpp"
|
||||
|
||||
namespace hibis {
|
||||
class Engine {
|
||||
public:
|
||||
Engine(Renderer* renderer, LoggerCallback logger);
|
||||
~Engine();
|
||||
|
||||
void runNodeProcesses();
|
||||
|
||||
void runNodePhysicsProcesses();
|
||||
|
||||
void drawNodes();
|
||||
|
||||
const char* getEngineVersion();
|
||||
private:
|
||||
Renderer* renderer;
|
||||
//StopWatch watch;
|
||||
float previousProcessTick;
|
||||
float previousPhysicsProcessTick;
|
||||
|
||||
std::vector<Node*> nodeList;
|
||||
LoggerCallback loggerCallback;
|
||||
};
|
||||
}
|
3
core/enginever.in.hpp
Normal file
3
core/enginever.in.hpp
Normal file
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
#define HIBIS_VERSION "@version@"
|
9
core/graphics/drawable.hpp
Normal file
9
core/graphics/drawable.hpp
Normal file
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "../renderer/renderer.hpp"
|
||||
|
||||
namespace hibis {
|
||||
class Drawable {
|
||||
virtual void draw(Renderer* renderer) = 0;
|
||||
};
|
||||
}
|
9
core/logging/types.hpp
Normal file
9
core/logging/types.hpp
Normal file
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
enum LoggingSeverity {
|
||||
Message,
|
||||
Information,
|
||||
Warning,
|
||||
Error,
|
||||
Fatal
|
||||
};
|
39
core/math/types.hpp
Normal file
39
core/math/types.hpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
|
||||
namespace hibis {
|
||||
// Structs
|
||||
// - Image
|
||||
/// RGBA value struct. Value is between 0 and 255
|
||||
struct Color {
|
||||
unsigned char r, g, b, a;
|
||||
};
|
||||
|
||||
// - 2D
|
||||
/// Defines a point within a 2D space.
|
||||
struct Point2D {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
/// Defines a given area.
|
||||
struct Rect {
|
||||
float x, y, w, h;
|
||||
};
|
||||
|
||||
/// Integer variation of Rect.
|
||||
struct IntRect {
|
||||
int x, y, w, h;
|
||||
};
|
||||
|
||||
/// X and Y values using floats.
|
||||
struct Vec2 {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
/// X and Y values using integers.
|
||||
struct IntVec2 {
|
||||
int x, y;
|
||||
};
|
||||
|
||||
// - Functions
|
||||
// TODO: Functions
|
||||
}
|
9
core/node/node.hpp
Normal file
9
core/node/node.hpp
Normal file
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
namespace hibis {
|
||||
class Node {
|
||||
public:
|
||||
virtual void process(float delta) = 0;
|
||||
virtual void physicsProcess(float delta) = 0;
|
||||
};
|
||||
}
|
28
core/renderer/renderer.hpp
Normal file
28
core/renderer/renderer.hpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include "../math/types.hpp"
|
||||
#include "../resources/resource.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace hibis {
|
||||
class Renderer {
|
||||
public:
|
||||
// Draw
|
||||
virtual void clearScreen(Color col) = 0;
|
||||
virtual void renderCurrent() = 0;
|
||||
|
||||
virtual void drawText(Resource* resource, std::string text, IntVec2 pos, Color color) = 0;
|
||||
|
||||
// Pre and Post draw
|
||||
virtual void preDraw() = 0;
|
||||
virtual void postDraw() = 0;
|
||||
|
||||
// Update
|
||||
virtual void update() = 0;
|
||||
|
||||
// Util
|
||||
virtual void setWindowTitle(std::string title) = 0;
|
||||
|
||||
bool keepOpen = true;
|
||||
};
|
||||
}
|
7
core/resources/image.hpp
Normal file
7
core/resources/image.hpp
Normal file
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "resource.hpp"
|
||||
|
||||
namespace hibis {
|
||||
class Image : Resource {};
|
||||
}
|
5
core/resources/resource.hpp
Normal file
5
core/resources/resource.hpp
Normal file
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
namespace hibis {
|
||||
class Resource {};
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
module hibis.callback;
|
||||
|
||||
import hibis.logging.types;
|
||||
|
||||
alias LoggerCallback = void function(LoggingSeverity severity, string message);
|
|
@ -1,69 +0,0 @@
|
|||
module hibis.core.engine;
|
||||
|
||||
import hibis.graphics.drawable;
|
||||
import hibis.renderer.renderer;
|
||||
import hibis.logging.types;
|
||||
import hibis.callback;
|
||||
import hibis.node.node;
|
||||
import std.datetime.stopwatch;
|
||||
|
||||
import std.stdio;
|
||||
import std.format;
|
||||
|
||||
class Engine {
|
||||
this(Renderer renderer, LoggerCallback logger) {
|
||||
this.renderer = renderer;
|
||||
this.loggerCallback = logger;
|
||||
previousProcessTick = 0.00001f;
|
||||
previousPhysicsProcessTick = 0.00001f;
|
||||
|
||||
watch.start();
|
||||
|
||||
this.loggerCallback(LoggingSeverity.Information, "Started Hibis!");
|
||||
}
|
||||
|
||||
~this() {
|
||||
watch.stop();
|
||||
}
|
||||
|
||||
void runNodeProcesses() {
|
||||
// TODO: fix delta then adapt for runNodePhysicsProcesses
|
||||
const float current = watch.peek.total!"msecs" / 1_000;
|
||||
float delta = (current - previousProcessTick);
|
||||
|
||||
foreach (Node* node ; nodeList) {
|
||||
node.process(delta);
|
||||
}
|
||||
|
||||
this.previousProcessTick = watch.peek.total!"msecs" / 1_000;
|
||||
}
|
||||
|
||||
void runNodePhysicsProcesses() {
|
||||
// TODO: See above TODO
|
||||
// Schade! Have the wrong function content while I figure out how std.datetime.watch works
|
||||
const float current = watch.peek.total!"msecs" / 1_000;
|
||||
float delta = (current - previousProcessTick);
|
||||
|
||||
foreach (Node* node ; nodeList) {
|
||||
node.physicsProcess(delta);
|
||||
}
|
||||
|
||||
this.previousPhysicsProcessTick = watch.peek.total!"msecs" / 1_000;
|
||||
}
|
||||
|
||||
void drawNodes() {
|
||||
foreach (Node* node; nodeList) {
|
||||
if (Drawable* drawNode = cast(Drawable*) node) {
|
||||
drawNode.draw(&renderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Renderer renderer;
|
||||
private StopWatch watch;
|
||||
private float previousProcessTick;
|
||||
private float previousPhysicsProcessTick;
|
||||
|
||||
private Node*[] nodeList;
|
||||
private LoggerCallback loggerCallback;
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
module hibis.graphics.drawable;
|
||||
import hibis.renderer.renderer;
|
||||
|
||||
abstract class Drawable {
|
||||
public void draw(Renderer* renderer);
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
module hibis.logging.types;
|
||||
|
||||
enum LoggingSeverity : ubyte {
|
||||
Message = 0,
|
||||
Information,
|
||||
Warning,
|
||||
Error,
|
||||
Fatal
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
module hibis.math.types;
|
||||
|
||||
// Structs
|
||||
// - Image
|
||||
/// RGBA value struct. Value is between 0 and 255
|
||||
struct Color {
|
||||
ubyte r, g, b, a;
|
||||
}
|
||||
|
||||
// - 2D
|
||||
/// Defines a point within a 2D space.
|
||||
struct Point2D {
|
||||
float x, y;
|
||||
}
|
||||
|
||||
/// Defines a given area.
|
||||
struct Rect {
|
||||
float x, y, w, h;
|
||||
}
|
||||
|
||||
/// Integer variation of Rect.
|
||||
struct IntRect {
|
||||
int x, y, w, h;
|
||||
}
|
||||
|
||||
/// X and Y values using floats.
|
||||
struct Vec2 {
|
||||
float x, y;
|
||||
}
|
||||
|
||||
/// X and Y values using integers.
|
||||
struct IntVec2 {
|
||||
int x, y;
|
||||
}
|
||||
|
||||
// - Functions
|
||||
// TODO: Functions
|
|
@ -1,6 +0,0 @@
|
|||
module hibis.node.node;
|
||||
|
||||
abstract class Node {
|
||||
void process(float delta);
|
||||
void physicsProcess(float delta);
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
module hibis.renderer.renderer;
|
||||
|
||||
import hibis.math.types;
|
||||
import hibis.resources.resource;
|
||||
|
||||
abstract class Renderer {
|
||||
// Draw
|
||||
void clearScreen(Color col);
|
||||
void renderCurrent();
|
||||
|
||||
void drawText(Resource resource, string text, IntVec2 pos, Color color);
|
||||
|
||||
// Pre and Post draw
|
||||
void preDraw();
|
||||
void postDraw();
|
||||
|
||||
// Update
|
||||
void update();
|
||||
|
||||
// Util
|
||||
void setWindowTitle(string title);
|
||||
|
||||
public bool keepOpen = true;
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
module hibis.resources.image;
|
||||
|
||||
import hibis.resources.resource;
|
||||
|
||||
abstract class Image : Resource {}
|
|
@ -1,3 +0,0 @@
|
|||
module hibis.resources.resource;
|
||||
|
||||
abstract class Resource {}
|
12
dub.sdl
12
dub.sdl
|
@ -1,12 +0,0 @@
|
|||
name "hibis"
|
||||
description "Game engine written in D"
|
||||
authors "Tulpenkiste"
|
||||
copyright "Copyright © 2023, Tulpenkiste"
|
||||
license "LGPL-3.0"
|
||||
targetType "none"
|
||||
dependency "hibis:core" version="*"
|
||||
dependency "hibis:rsdl" version="*"
|
||||
dependency "hibis:test" version="*"
|
||||
subPackage "core"
|
||||
subPackage "renderer/rsdl"
|
||||
subPackage "test"
|
3
include/pragmautil.hpp
Normal file
3
include/pragmautil.hpp
Normal file
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
// TODO: pragma
|
28
meson.build
Normal file
28
meson.build
Normal file
|
@ -0,0 +1,28 @@
|
|||
project('hibis', 'cpp', version: '0.0.0' + (not get_option('buildtype').startswith('release') ? '-' + run_command('git', 'rev-parse', '--short', 'HEAD', check: true).stdout().strip() : ''),
|
||||
license: 'LGPL-3.0-only', meson_version: '>=0.60.3', default_options: ['cpp_std=c++17'])
|
||||
|
||||
# Configure data
|
||||
confdata = configuration_data()
|
||||
confdata.set('version', meson.project_version())
|
||||
|
||||
configure_file(input: 'core/enginever.in.hpp', output: 'enginever.hpp', configuration: confdata)
|
||||
|
||||
# Include Directory
|
||||
include_dirs = include_directories('./include')
|
||||
|
||||
# Files
|
||||
libhibis_src_core = files('core/engine/engine.cpp')
|
||||
libhibis_src = [libhibis_src_core]
|
||||
|
||||
libhibis_rsdl_src = files('renderer/rsdl/rsdl.cpp', 'renderer/rsdl/resources/font.cpp')
|
||||
libhibis_test_src = files('test/app.cpp')
|
||||
|
||||
# Dependencies
|
||||
libsdl2 = dependency('SDL2')
|
||||
libsdl2_ttf = dependency('SDL2_ttf')
|
||||
libfmt = dependency('fmt')
|
||||
|
||||
# Compile
|
||||
libhibis = library('hibis', libhibis_src, include_directories: include_dirs)
|
||||
libhibis_rsdl = library('hibis_rsdl', libhibis_rsdl_src, include_directories: [include_dirs, './core'], link_with: libhibis, dependencies: [libsdl2, libsdl2_ttf, libfmt])
|
||||
hibistest = executable('hibistest.exec', libhibis_test_src, include_directories: [include_dirs, './core', './renderer/rsdl'], link_with: [libhibis, libhibis_rsdl], dependencies: [libsdl2, libsdl2_ttf, libfmt])
|
|
@ -1,9 +0,0 @@
|
|||
name "rsdl"
|
||||
dependency "hibis:core" version=">=0.0.0"
|
||||
dependency "bindbc-sdl" version="~>1.3.5"
|
||||
versions "SDL_2_26" "SDL_TTF_2_20"
|
||||
libs "SDL2" "SDL2_ttf"
|
||||
targetType "library"
|
||||
targetName "hibis_rsdl"
|
||||
# Source paths so this can compile properly
|
||||
sourcePaths "./" "../../core"
|
34
renderer/rsdl/resources/font.cpp
Normal file
34
renderer/rsdl/resources/font.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <fmt/format.h>
|
||||
#include "font.hpp"
|
||||
|
||||
namespace hibis {
|
||||
namespace rsdl {
|
||||
Font::Font(std::string path, uint size) {
|
||||
this->size = size;
|
||||
this->path = path;
|
||||
loadFont();
|
||||
}
|
||||
|
||||
Font::~Font() {
|
||||
TTF_CloseFont(loadedFont);
|
||||
}
|
||||
|
||||
void Font::loadFont(bool reload) {
|
||||
// If already loaded, close font
|
||||
if (loadedFont != NULL) {
|
||||
TTF_CloseFont(loadedFont);
|
||||
loadedFont = NULL;
|
||||
}
|
||||
|
||||
loadedFont = TTF_OpenFont(path.c_str(), size);
|
||||
|
||||
// Do the message
|
||||
if (!didReload) {
|
||||
std::cout << fmt::format((reload ? "Reloaded font from" : "Loaded font at") + (std::string)" {}", path) << std::endl;
|
||||
didReload = reload;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
30
renderer/rsdl/resources/font.hpp
Normal file
30
renderer/rsdl/resources/font.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <resources/resource.hpp>
|
||||
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
|
||||
namespace hibis {
|
||||
namespace rsdl {
|
||||
class Font : public Resource {
|
||||
public:
|
||||
Font(std::string path, uint size);
|
||||
|
||||
~Font();
|
||||
|
||||
uint getFontSize() { return size; }
|
||||
|
||||
void setFontSize(uint newSize) { size = newSize; loadFont(true); }
|
||||
|
||||
|
||||
TTF_Font* loadedFont = NULL;
|
||||
private:
|
||||
void loadFont(bool reload = false);
|
||||
uint size;
|
||||
std::string path;
|
||||
|
||||
bool didReload = false;
|
||||
};
|
||||
}
|
||||
}
|
98
renderer/rsdl/rsdl.cpp
Normal file
98
renderer/rsdl/rsdl.cpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include <SDL2/SDL_ttf.h>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include "rsdl.hpp"
|
||||
#include "resources/font.hpp"
|
||||
|
||||
#include <pragmautil.hpp>
|
||||
|
||||
namespace hibis {
|
||||
namespace rsdl {
|
||||
RSDL::RSDL(std::string title, IntVec2 size, LoggerCallback callback) {
|
||||
logger = callback;
|
||||
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
||||
// Create window. `title` is cast to a char* here as tostd::stringz returns an immutable char* (causing an error)
|
||||
window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||
size.x, size.y, SDL_WINDOW_RESIZABLE);
|
||||
|
||||
if (window == NULL) {
|
||||
logger(Fatal, fmt::format("Couldn't create window! what: {}", SDL_GetError()));
|
||||
SDL_Quit();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
||||
|
||||
if (renderer == NULL) {
|
||||
logger(Fatal, fmt::format("Couldn't create renderer! what: {}", SDL_GetError()));
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (TTF_Init() != 0) {
|
||||
logger(Fatal, fmt::format("Couldn't load SDL_TTF! what: %d", TTF_GetError()));
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
TTF_Quit();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
RSDL::~RSDL() {
|
||||
TTF_Quit();
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
void RSDL::clearScreen(Color col) {
|
||||
SDL_SetRenderDrawColor(renderer, col.r, col.g, col.b, col.a);
|
||||
SDL_RenderClear(renderer);
|
||||
}
|
||||
|
||||
void RSDL::renderCurrent() {
|
||||
SDL_UpdateWindowSurface(window);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
void RSDL::drawText(Resource* resource, std::string text, IntVec2 pos, Color color) {
|
||||
if (Font* font = (Font*)resource) {
|
||||
SDL_Surface* textSurface = TTF_RenderText_Solid(font->loadedFont, text.c_str(), SDL_Color {color.r, color.g, color.b, color.a });
|
||||
SDL_Texture* textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
TTF_SizeText(font->loadedFont, text.c_str(), &width, &height);
|
||||
|
||||
SDL_Rect textRect;
|
||||
textRect.x = pos.x;
|
||||
textRect.y = pos.y;
|
||||
textRect.w = width;
|
||||
textRect.h = height;
|
||||
|
||||
SDL_RenderCopy(renderer, textTexture, NULL, &textRect);
|
||||
|
||||
SDL_DestroyTexture(textTexture);
|
||||
SDL_FreeSurface(textSurface);
|
||||
}
|
||||
}
|
||||
|
||||
void RSDL::preDraw() {}
|
||||
void RSDL::postDraw() {}
|
||||
|
||||
void RSDL::update() {
|
||||
SDL_Event event;
|
||||
|
||||
while(SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) keepOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
void RSDL::setWindowTitle(std::string title) {}
|
||||
}
|
||||
}
|
43
renderer/rsdl/rsdl.hpp
Normal file
43
renderer/rsdl/rsdl.hpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
|
||||
#include <format>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include <callback.hpp>
|
||||
#include <math/types.hpp>
|
||||
#include <renderer/renderer.hpp>
|
||||
|
||||
namespace hibis {
|
||||
namespace rsdl {
|
||||
/** \class RSDL
|
||||
* Renderer implementation using SDL2 Renderer for the Hibis game engine
|
||||
*/
|
||||
class RSDL : public Renderer {
|
||||
public:
|
||||
RSDL(std::string title, IntVec2 size, LoggerCallback callback);
|
||||
|
||||
~RSDL();
|
||||
|
||||
void clearScreen(Color col = Color {0, 0, 0, 1});
|
||||
|
||||
void renderCurrent();
|
||||
|
||||
void drawText(Resource* resource, std::string text, IntVec2 pos, Color color);
|
||||
|
||||
void preDraw();
|
||||
void postDraw();
|
||||
|
||||
void update();
|
||||
|
||||
void setWindowTitle(std::string title);
|
||||
|
||||
private:
|
||||
SDL_Window* window;
|
||||
SDL_Renderer* renderer;
|
||||
|
||||
LoggerCallback logger;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
module hibis_rsdl.rsdl;
|
||||
|
||||
import hibis.resources.resource;
|
||||
import hibis.callback;
|
||||
import hibis.logging.types;
|
||||
import hibis_rsdl.resources.font;
|
||||
|
||||
import bindbc.sdl;
|
||||
import sdl_ttf;
|
||||
import hibis.renderer.renderer;
|
||||
import hibis.math.types;
|
||||
import std.exception;
|
||||
import std.format;
|
||||
|
||||
import std.stdio;
|
||||
import std.string : toStringz;
|
||||
import std.array : split;
|
||||
|
||||
/** \class RSDL
|
||||
* Renderer implementation using SDL2 Renderer for the Hibis game engine
|
||||
*/
|
||||
class RSDL : Renderer {
|
||||
this(string title, IntVec2 size, LoggerCallback callback) {
|
||||
this.logger = callback;
|
||||
const SDLSupport ret = loadSDL();
|
||||
if(ret != sdlSupport) {
|
||||
throw new Exception("Couldn't load SDL library!");
|
||||
}
|
||||
|
||||
const SDLTTFSupport ttf = loadSDLTTF();
|
||||
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
||||
// Create window. `title` is cast to a char* here as toStringz returns an immutable char* (causing an error)
|
||||
window = SDL_CreateWindow(cast(char*)toStringz(title), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||
size.x, size.y, SDL_WINDOW_RESIZABLE);
|
||||
|
||||
if (window is null) {
|
||||
string error = format("Couldn't create window! what: %d", SDL_GetError());
|
||||
SDL_Quit();
|
||||
throw new Exception(error);
|
||||
}
|
||||
|
||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
||||
|
||||
if (renderer is null) {
|
||||
string error = format("Couldn't create renderer! what: %d", SDL_GetError());
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
throw new Exception(error);
|
||||
}
|
||||
|
||||
if (TTF_Init() != 0) {
|
||||
logger(LoggingSeverity.Fatal, format("Couldn't load SDL_TTF! what: %d", TTF_GetError()));
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
TTF_Quit();
|
||||
throw new Exception("");
|
||||
}
|
||||
}
|
||||
|
||||
~this() {
|
||||
TTF_Quit();
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
|
||||
unloadSDLTTF();
|
||||
unloadSDL();
|
||||
}
|
||||
|
||||
override void clearScreen(Color col = Color(0, 0, 0, 1)) {
|
||||
SDL_SetRenderDrawColor(renderer, col.r, col.g, col.b, col.a);
|
||||
SDL_RenderClear(renderer);
|
||||
}
|
||||
|
||||
override void renderCurrent() {
|
||||
SDL_UpdateWindowSurface(window);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
override void drawText(Resource resource, string text, IntVec2 pos, Color color) {
|
||||
if (Font font = cast(Font)resource) {
|
||||
SDL_Surface* textSurface = TTF_RenderText_Solid(font.loadedFont, cast(const(char)*)toStringz(text), SDL_Color(color.r, color.g, color.b, color.a));
|
||||
SDL_Texture* textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
TTF_SizeText(font.loadedFont, cast(const(char)*)toStringz(text), &width, &height);
|
||||
|
||||
SDL_Rect textRect;
|
||||
textRect.x = pos.x;
|
||||
textRect.y = pos.y;
|
||||
textRect.w = width;
|
||||
textRect.h = height;
|
||||
|
||||
SDL_RenderCopy(renderer, textTexture, null, &textRect);
|
||||
|
||||
SDL_DestroyTexture(textTexture);
|
||||
SDL_FreeSurface(textSurface);
|
||||
}
|
||||
}
|
||||
|
||||
override void preDraw() {}
|
||||
override void postDraw() {}
|
||||
|
||||
override void update() {
|
||||
SDL_Event event;
|
||||
|
||||
while(SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) keepOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
override void setWindowTitle(string title) {}
|
||||
|
||||
private SDL_Window* window;
|
||||
private SDL_Renderer* renderer;
|
||||
|
||||
private LoggerCallback logger;
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
module hibis_rsdl.resources.font;
|
||||
|
||||
import hibis.resources.resource;
|
||||
|
||||
import sdl_ttf;
|
||||
import std.string : toStringz;
|
||||
import std.stdio;
|
||||
import std.format : format;
|
||||
|
||||
class Font : Resource {
|
||||
this(string path, uint size) {
|
||||
this.size = size;
|
||||
this.path = path;
|
||||
loadFont();
|
||||
}
|
||||
|
||||
~this() {
|
||||
TTF_CloseFont(loadedFont);
|
||||
}
|
||||
|
||||
uint getFontSize() { return size; }
|
||||
|
||||
void setFontSize(uint newSize) {
|
||||
size = newSize;
|
||||
loadFont(true);
|
||||
}
|
||||
|
||||
private void loadFont(bool reload = false) {
|
||||
const char* nPath = cast(const(char)*)toStringz(path);
|
||||
|
||||
// If already loaded, close font
|
||||
if (!(loadedFont is null)) {
|
||||
TTF_CloseFont(loadedFont);
|
||||
loadedFont = null;
|
||||
}
|
||||
|
||||
loadedFont = TTF_OpenFont(nPath, size);
|
||||
|
||||
// Do the message
|
||||
if (!didReload) {
|
||||
writeln(format(reload ? "Reloaded font from '%s'" : "Loaded font at '%s'", path));
|
||||
didReload = reload;
|
||||
}
|
||||
}
|
||||
|
||||
public TTF_Font* loadedFont = null;
|
||||
private uint size;
|
||||
private string path;
|
||||
|
||||
private bool didReload = false;
|
||||
}
|
16
test/.gitignore
vendored
16
test/.gitignore
vendored
|
@ -1,16 +0,0 @@
|
|||
.dub
|
||||
docs.json
|
||||
__dummy.html
|
||||
docs/
|
||||
/test
|
||||
test.so
|
||||
test.dylib
|
||||
test.dll
|
||||
test.a
|
||||
test.lib
|
||||
test-test-*
|
||||
*.exe
|
||||
*.pdb
|
||||
*.o
|
||||
*.obj
|
||||
*.lst
|
89
test/app.cpp
Normal file
89
test/app.cpp
Normal file
|
@ -0,0 +1,89 @@
|
|||
#include <logging/types.hpp>
|
||||
#include <fmt/format.h>
|
||||
#include <renderer/renderer.hpp>
|
||||
#include <rsdl.hpp>
|
||||
#include <resources/font.hpp>
|
||||
#include <resources/font.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include <engine/engine.hpp>
|
||||
|
||||
using namespace hibis;
|
||||
using namespace hibis::rsdl;
|
||||
|
||||
void logger(LoggingSeverity severity, std::string message) {
|
||||
std::string sevString;
|
||||
switch (severity) {
|
||||
case Message:
|
||||
sevString = "Message";
|
||||
break;
|
||||
case Information:
|
||||
sevString = "Information";
|
||||
break;
|
||||
case Warning:
|
||||
sevString = "Warning";
|
||||
break;
|
||||
case Error:
|
||||
sevString = "Error";
|
||||
break;
|
||||
case Fatal:
|
||||
sevString = "Fatal";
|
||||
break;
|
||||
}
|
||||
|
||||
std::cout << fmt::format("[{}]: {}", severity, message) << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
RSDL renderer = RSDL("test", IntVec2 {800, 600}, &logger);
|
||||
Engine engine = Engine(&renderer, &logger);
|
||||
|
||||
#ifdef _WIN32
|
||||
Font font = Font("C:\\Windows\\Fonts\\Arial.ttf", 16);
|
||||
#else
|
||||
Font font = Font("/usr/share/fonts/noto/NotoSans-Light.ttf", 16);
|
||||
#endif
|
||||
|
||||
unsigned char red = 0;
|
||||
bool increaseRed = true;
|
||||
bool increaseSize = true;
|
||||
uint size = 16;
|
||||
uint f = 0;
|
||||
|
||||
logger(Information, "Started Hibis test app! BEHOLD: Colours.");
|
||||
while (renderer.keepOpen) {
|
||||
engine.runNodeProcesses();
|
||||
|
||||
// Colour changing background!
|
||||
if ((red == 255 && increaseRed) || (red == 0 && !increaseRed)) {
|
||||
increaseRed = !increaseRed;
|
||||
}
|
||||
if (increaseRed) red += 1;
|
||||
else red -= 1;
|
||||
|
||||
f++;
|
||||
if (f == 16) {
|
||||
f = 0;
|
||||
if ((size == 64 && increaseSize) || (size == 16 && !increaseSize)) {
|
||||
increaseSize = !increaseSize;
|
||||
}
|
||||
if (increaseSize) size += 2;
|
||||
else size -= 2;
|
||||
font.setFontSize(size);
|
||||
}
|
||||
|
||||
// Clear screen then sleep for ~16ms
|
||||
renderer.clearScreen(Color {red, 0, 0, 255});
|
||||
renderer.drawText(&font, "Testing Text", IntVec2 {0, 0}, Color {255, 255, 255, 255});
|
||||
|
||||
engine.drawNodes();
|
||||
renderer.renderCurrent();
|
||||
renderer.update();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(16));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
10
test/dub.sdl
10
test/dub.sdl
|
@ -1,10 +0,0 @@
|
|||
name "test"
|
||||
description "Test of the Hibis game engine"
|
||||
authors "Tulpenkiste"
|
||||
copyright "Copyright © 2023, Tulpenkiste"
|
||||
license "LGPL-3.0"
|
||||
targetType "executable"
|
||||
targetName "hibistest.exec"
|
||||
dependency "hibis:core" version="*"
|
||||
dependency "hibis:rsdl" version="*"
|
||||
sourcePaths "./" "../core" "../renderer/rsdl"
|
|
@ -1,65 +0,0 @@
|
|||
import std.stdio;
|
||||
import std.format;
|
||||
import std.conv;
|
||||
|
||||
import hibis.core.engine;
|
||||
import hibis.math.types;
|
||||
import hibis.renderer.renderer;
|
||||
import hibis.logging.types;
|
||||
import hibis.callback;
|
||||
import hibis_rsdl.rsdl;
|
||||
import hibis_rsdl.resources.font;
|
||||
|
||||
import core.thread;
|
||||
|
||||
void logger(LoggingSeverity severity, string message) {
|
||||
writeln(format("[%s]: %s", to!string(severity), message));
|
||||
}
|
||||
|
||||
void main() {
|
||||
Renderer renderer = new RSDL("test", IntVec2(800, 600), &logger);
|
||||
Engine engine = new Engine(renderer, &logger);
|
||||
version(windows) {
|
||||
Font font = new Font("C:\\Windows\\Fonts\\Arial.ttf", 16);
|
||||
} else {
|
||||
Font font = new Font("/usr/share/fonts/noto/NotoSans-Light.ttf", 16);
|
||||
}
|
||||
ubyte red = 0;
|
||||
bool increaseRed = true;
|
||||
bool increaseSize = true;
|
||||
uint size = 16;
|
||||
uint f = 0;
|
||||
|
||||
logger(LoggingSeverity.Information, "Started Hibis test app! BEHOLD: Colours.");
|
||||
while (renderer.keepOpen) {
|
||||
engine.runNodeProcesses();
|
||||
|
||||
// Colour changing background!
|
||||
if ((red == 255 && increaseRed) || (red == 0 && !increaseRed)) {
|
||||
increaseRed = !increaseRed;
|
||||
}
|
||||
if (increaseRed) red += 1;
|
||||
else red -= 1;
|
||||
|
||||
f++;
|
||||
if (f == 16) {
|
||||
f = 0;
|
||||
if ((size == 64 && increaseSize) || (size == 16 && !increaseSize)) {
|
||||
increaseSize = !increaseSize;
|
||||
}
|
||||
if (increaseSize) size += 2;
|
||||
else size -= 2;
|
||||
font.setFontSize(size);
|
||||
}
|
||||
|
||||
// Clear screen then sleep for ~16ms
|
||||
renderer.clearScreen(Color(red, 0, 0, 255));
|
||||
renderer.drawText(font, "Testing Text", IntVec2(0, 0), Color(255, 255, 255, 255));
|
||||
|
||||
engine.drawNodes();
|
||||
renderer.renderCurrent();
|
||||
renderer.update();
|
||||
Thread.sleep(16.msecs);
|
||||
}
|
||||
destroy(font);
|
||||
}
|
Loading…
Reference in a new issue