Skip to content

Commit

Permalink
Separated Memory member definitions from container.cpp to `memory…
Browse files Browse the repository at this point in the history
….cpp`.

Close #69.

Added `Widget::shown` and its expected behavior in `UI::Render()`.
Close #66.

Changed `UI::Render()` and `Camera::Render()` to render foreground regardless of character value.
Added a bit of backwards compatability by changing `Texture::Write()` to not set foreground color for cells that have a space character. Reverting this can be done with `Texture::SetForeground()`.
Close #65.

Added missing texture pattern to `Texture::File()` in cases where the file failed to open.
Close #64.

Added a default value for `CellA newValue` argument in `Texture::Resize()`.
Close #63.

Made `Memory:CallOnTicks()` call for `UI`s and `Widget`s.
Close #62.

Created `Texture::SetBackgroundAlpha()` and `Texture::SetForegroundAlpha()`.
Close #61.

Added `override` keyword to widgets.
Close #60.
  • Loading branch information
TheRealKaup committed Apr 11, 2024
1 parent 579e427 commit 9dd8f76
Show file tree
Hide file tree
Showing 11 changed files with 247 additions and 199 deletions.
34 changes: 15 additions & 19 deletions ktech/camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,13 @@ void KTech::Camera::Render(const std::vector<ID<Layer>>& layers)
for (size_t x = start.x; x < end.x; x++)
{
if (texture.value.c != ' ')
{
image[y][x].c = texture.value.c;
// 8. 8 -> 16 -> 8.
image[y][x].f.r = tempFRGBA.r + image[y][x].f.r * (255 - tempFRGBA.a) / 255;
image[y][x].f.g = tempFRGBA.g + image[y][x].f.g * (255 - tempFRGBA.a) / 255;
image[y][x].f.b = tempFRGBA.b + image[y][x].f.b * (255 - tempFRGBA.a) / 255;
image[y][x].f.a += tempFRGBA.a * (255 - image[y][x].f.a) / 255;
}
// 8. 8 -> 16 -> 8.
// 8. 8 -> 16 -> 8.
image[y][x].f.r = tempFRGBA.r + image[y][x].f.r * (255 - tempFRGBA.a) / 255;
image[y][x].f.g = tempFRGBA.g + image[y][x].f.g * (255 - tempFRGBA.a) / 255;
image[y][x].f.b = tempFRGBA.b + image[y][x].f.b * (255 - tempFRGBA.a) / 255;
image[y][x].f.a += tempFRGBA.a * (255 - image[y][x].f.a) / 255;
// 8. 8 -> 16 -> 8.
image[y][x].b.r = tempBRGBA.r + image[y][x].b.r * (255 - tempBRGBA.a) / 255;
image[y][x].b.g = tempBRGBA.g + image[y][x].b.g * (255 - tempBRGBA.a) / 255;
image[y][x].b.b = tempBRGBA.b + image[y][x].b.b * (255 - tempBRGBA.a) / 255;
Expand Down Expand Up @@ -173,21 +171,19 @@ void KTech::Camera::Render(const std::vector<ID<Layer>>& layers)
for (; x < texture.t[y].size() && start.x < res.x; x++, start.x++)
{
if (texture.t[y][x].c != ' ')
{
image[start.y][start.x].c = texture.t[y][x].c; // Character
// Precalculate foreground * layer alpha (8 bit depth)
// 8 -> 16 -> 8.
tempAlpha = texture.t[y][x].f.a * layer->alpha / 255;
// (8 -> 16. 8 -> 16.) 16 -> 8.
image[start.y][start.x].f.r = (texture.t[y][x].f.r * tempAlpha + image[start.y][start.x].f.r * (255 - tempAlpha)) / 255;
image[start.y][start.x].f.g = (texture.t[y][x].f.g * tempAlpha + image[start.y][start.x].f.g * (255 - tempAlpha)) / 255;
image[start.y][start.x].f.b = (texture.t[y][x].f.b * tempAlpha + image[start.y][start.x].f.b * (255 - tempAlpha)) / 255;
image[start.y][start.x].f.a += tempAlpha * (255 - image[start.y][start.x].f.a) / 255;
}
// Precalculate foreground * layer alpha (8 bit depth)
// 8 -> 16 -> 8.
tempAlpha = texture.t[y][x].f.a * layer->alpha / 255;
// (8 -> 16. 8 -> 16.) -> 8.
image[start.y][start.x].f.r = (texture.t[y][x].f.r * tempAlpha + image[start.y][start.x].f.r * (255 - tempAlpha)) / 255;
image[start.y][start.x].f.g = (texture.t[y][x].f.g * tempAlpha + image[start.y][start.x].f.g * (255 - tempAlpha)) / 255;
image[start.y][start.x].f.b = (texture.t[y][x].f.b * tempAlpha + image[start.y][start.x].f.b * (255 - tempAlpha)) / 255;
image[start.y][start.x].f.a += tempAlpha * (255 - image[start.y][start.x].f.a) / 255;
// Precalculate background * layer alpha (8 bit depth)
// 8 -> 16 -> 8.
tempAlpha = texture.t[y][x].b.a * layer->alpha / 255;
// (8 -> 16. 8 -> 16.) 16 -> 8.
// (8 -> 16. 8 -> 16.) -> 8.
image[start.y][start.x].b.r = (texture.t[y][x].b.r * tempAlpha + image[start.y][start.x].b.r * (255 - tempAlpha)) / 255;
image[start.y][start.x].b.g = (texture.t[y][x].b.g * tempAlpha + image[start.y][start.x].b.g * (255 - tempAlpha)) / 255;
image[start.y][start.x].b.b = (texture.t[y][x].b.b * tempAlpha + image[start.y][start.x].b.b * (255 - tempAlpha)) / 255;
Expand Down
158 changes: 158 additions & 0 deletions ktech/container.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/*
KTech, Kaup's C++ 2D terminal game engine library.
Copyright (C) 2023-2024 Ethan Kaufman (AKA Kaup)
This file is part of KTech.
KTech is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
KTech is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with KTech. If not, see <https://www.gnu.org/licenses/>.
*/

#include "ktech.hpp"

using namespace KTech;

template<typename T>
ID<T> Memory::Container<T>::Add(T* structure)
{
KTech::IO::Log("<Container::Add()> Start of function...", RGBColors::lime);
T** tmp = new T*[size + 1];
KTech::IO::Log("<Container::Add()> Created new extended array " + std::to_string((size_t)tmp), RGBColors::lime);
KTech::IO::Log("<Container::Add()> Move to new array", RGBColors::lime);
for (size_t i = 0; i < size; i++)
tmp[i] = arr[i];
KTech::IO::Log("<Container::Add()> Add given structure", RGBColors::lime);
structure->id.i = size;
tmp[size] = structure;
if (size > 0)
{
KTech::IO::Log("<Container::Add()> Delete old array " + std::to_string((size_t)arr), RGBColors::lime);
delete[] arr;
}
KTech::IO::Log("<Container::Add()> Update info", RGBColors::lime);
arr = tmp;
size++;
KTech::IO::Log("<Container::Add()> End of function, returning ID.", RGBColors::lime);
return arr[size - 1]->id;
}

template<typename T>
inline bool Memory::Container<T>::Remove(const ID<T>& id)
{
KTech::IO::Log("<Container::Remove()> Start of function...", RGBColors::lime);
KTech::IO::Log("<Container::Remove()> Convert given ID to index", RGBColors::lime);
size_t toRemove = IDToIndex(id);
if (toRemove == size)
{
KTech::IO::Log("<Container::Remove()> End of function.", RGBColors::lime);
return false;
}
T** tmp = new T*[size - 1];
KTech::IO::Log("<Container::Remove()> Created new smaller array " + std::to_string((size_t)tmp), RGBColors::lime);
KTech::IO::Log("<Container::Remove()> Moving to new array", RGBColors::lime);
size_t i = 0;
for (; i < toRemove; i++)
tmp[i] = arr[i];
for (i++; i < size; i++)
tmp[i - 1] = arr[i];
KTech::IO::Log("<Container::Remove()> Delete old array " + std::to_string((size_t)arr), RGBColors::lime);
delete[] arr;
KTech::IO::Log("<Container::Remove()> Update info", RGBColors::lime);
size--;
arr = tmp;
KTech::IO::Log("<Container::Remove()> End of function.", RGBColors::lime);
return true;
}

template<typename T>
inline size_t Memory::Container<T>::IDToIndex(const ID<T>& id)
{
for (size_t i = (id.i < size ? id.i : size - 1);; i--)
{
if (arr[i]->id == id)
return i;
if (i == 0)
return size;
}
}

template<typename T>
inline size_t Memory::Container<T>::IDToIndex(ID<T>& id)
{
for (size_t i = (id.i < size ? id.i : size - 1);; i--)
{
if (arr[i]->id == id)
{
id.i = i;
return i;
}
if (i == 0)
break;
}
id.i = 0;
return size;
}

template<typename T>
bool Memory::Container<T>::Exists(const ID<T>& id)
{
if (IDToIndex(id) == size)
return false;
return true;
}

template<typename T>
bool Memory::Container<T>::Exists(ID<T>& id)
{
if (IDToIndex(id) == size)
return false;
return true;
}

template<typename T>
T* Memory::Container<T>::operator[](ID<T>& id)
{
for (size_t i = (id.i < size ? id.i : size -1);; i--)
{
if (arr[i]->id == id)
{
id.i = i;
return arr[i];
}
if (i == 0)
break;
}
id.i = 0;
return nullptr;
}

template<typename T>
T* Memory::Container<T>::operator[](const ID<T>& id)
{
for (size_t i = (id.i < size ? id.i : size -1);; i--)
{
if (arr[i]->id == id)
return arr[i];
if (i == 0)
break;
}
return nullptr;
}

// Explicit instantiation
template class Memory::Container<Object>;
template class Memory::Container<Layer>;
template class Memory::Container<Camera>;
template class Memory::Container<Map>;
template class Memory::Container<Widget>;
template class Memory::Container<UI>;
32 changes: 17 additions & 15 deletions ktech/ktech.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,10 @@ namespace KTech
};

// Manager of all things that directly work with terminal I/O.
class IO
struct IO
{
public:
Engine* engine;

// Prepares terminal, creates input loop thread
IO(KTech::UPoint imageSize, Engine* engine);
// Resets terminal
~IO();

termios oldTerminalAttributes;

winsize terminalSize;
Expand All @@ -123,6 +117,11 @@ namespace KTech

std::thread t_inputLoop;

// Prepares terminal, creates input loop thread
IO(KTech::UPoint imageSize, Engine* engine);
// Resets terminal
~IO();

void PrintStartupNotice(const std::string& title, const std::string& years, const std::string author, const std::string programName);

// Draw, usually the image of a camera, to the IO
Expand Down Expand Up @@ -153,8 +152,8 @@ namespace KTech
std::vector<BasicCallback*> callbacks; // Callbacks are stored as pointers because the vector changes its size, and CallbackGroups need a consistent pointer to the their callbacks.
std::string input;
uint8_t timesPressed = 0;
void RemoveCallback(BasicCallback*);
inline BasicHandler(const std::string& input) : input(input) {};
void RemoveCallback(BasicCallback*);
};

struct RangedHandler
Expand All @@ -167,21 +166,21 @@ namespace KTech
};
std::vector<RangedCallback*> callbacks; // Callbacks are stored as pointers because the vector changes its size, and CallbackGroups need a consistent pointer to the their callbacks.
char key1, key2;
void RemoveCallback(RangedCallback*);
inline RangedHandler(char key1, char key2) : key1(key1), key2(key2) {};
void RemoveCallback(RangedCallback*);
};

struct CallbacksGroup
{
std::vector<BasicHandler::BasicCallback*> basicCallbacks;
std::vector<RangedHandler::RangedCallback*> rangedCallbacks;
enum class Status : uint8_t
{
disabled,
enabled,
removeDisabled, // Remove and then return status to disabled
removeEnabled, // Remove and then return status to enabled
};
std::vector<BasicHandler::BasicCallback*> basicCallbacks;
std::vector<RangedHandler::RangedCallback*> rangedCallbacks;
Status status;
bool synced = true;
inline CallbacksGroup(bool enabled = true) : status(enabled ? Status::enabled : Status::disabled) { }
Expand Down Expand Up @@ -240,11 +239,13 @@ namespace KTech
UPoint File(const std::string& fileName, Point relative_position = Point(0, 0));
void Write(const std::vector<std::string>& stringVector, RGBA frgba, RGBA brgba, Point relative_position = Point(0, 0));

void Resize(UPoint newSize, CellA newValue);
void Resize(UPoint newSize, CellA newValue = CellA(' ', RGBA(0, 0, 0, 0), RGBA(0, 0, 0, 0)));
void SetCell(CellA value);
void SetForeground(RGBA value);
void SetBackground(RGBA value);
void SetCharacter(char value);
void SetForegroundAlpha(uint8_t value);
void SetBackgroundAlpha(uint8_t value);
void SetAlpha(uint8_t value);

UPoint GetSize() const;
Expand Down Expand Up @@ -412,6 +413,10 @@ namespace KTech
std::vector<Texture> textures = {};
IO::CallbacksGroup* callbacksGroup;
bool selected = false;
bool shown = true;

Widget(Engine& engine, ID<UI> parentUI, Point pos);
~Widget();

inline virtual void RenderSelected () {}
inline virtual void RenderUnselected () {}
Expand All @@ -421,9 +426,6 @@ namespace KTech
void EnterUI(ID<UI> ui);

inline virtual void OnTick() {};

Widget(Engine& engine, ID<UI> parentUI, Point pos);
~Widget();
};

// Acts as a camera and a layer for `Widget`s. Image is compatible with `IO::Draw()`.
Expand Down
Loading

0 comments on commit 9dd8f76

Please sign in to comment.