#include <range/v3/all.hpp>
#include <AUI/Platform/AWindow.h>
#include <AUI/Platform/Entry.h>
#include <AUI/Util/UIBuildingHelpers.h>
#include <AUI/View/AButton.h>
#include <AUI/View/AScrollArea.h>
#include <AUI/View/ATextArea.h>
using namespace declarative;
using namespace ass;
using namespace std::chrono_literals;
enum class CellState : std::uint8_t {
DEAD,
ALIVE,
};
return s == CellState::ALIVE ? CellState::DEAD : CellState::ALIVE;
}
public:
Cells(glm::ivec2 size) {
mSize = size;
for (auto s : { &mStorage, &mNextPopulation }) {
s->resize(size.x * size.y);
}
}
void frame() {
for (int y = 0; y < mSize.y; ++y) {
for (int x = 0; x < mSize.x; ++x) {
glm::ivec2 i { x, y };
get(mNextPopulation, i) = [&] {
auto around = cellsAround(i);
switch (around) {
default:
return CellState::DEAD;
case 2:
return get(mStorage, i);
case 3:
return CellState::ALIVE;
}
}();
}
}
std::swap(mStorage, mNextPopulation);
};
}
[[nodiscard]] glm::ivec2 size() const noexcept { return mSize; }
[[nodiscard]] const AVector<CellState>& storage() const noexcept { return mStorage; }
[[nodiscard]] CellState& operator[](glm::ivec2 position) { return get(mStorage, position); }
void randomize() {
ranges::generate(mStorage, [&] {
static std::default_random_engine re;
static std::uniform_int_distribution d(0, 10);
return d(re) > 7 ? CellState::ALIVE : CellState::DEAD;
});
}
AProperty<bool> isRunning = false;
private:
_<ATimer> mTimer = _new<ATimer>(100ms);
AFuture<> mFrame;
glm::ivec2 mSize {};
AVector<CellState> mStorage;
AVector<CellState> mNextPopulation;
CellState& get(AVector<CellState>& storage, glm::ivec2 position) {
position %= mSize;
if (position.x < 0) {
position.x = mSize.x + position.x;
}
if (position.y < 0) {
position.y = mSize.y + position.y;
}
return storage[position.y * mSize.x + position.x];
}
unsigned cellsAround(glm::ivec2 position) {
unsigned accumulator = 0;
for (int y = -1; y <= 1; ++y) {
for (int x = -1; x <= 1; ++x) {
if (x == 0 && y == 0) {
continue;
}
accumulator += get(mStorage, position + glm::ivec2 { x, y }) == CellState::ALIVE ? 1 : 0;
}
}
return accumulator;
}
};
class CellsView :
public AView {
public:
static constexpr auto SCALE = 8_dp;
CellsView(_<Cells> cells) : mCells(std::move(cells)) {
connect(mCells->frameComplete, me::updateTexture); }
void render(ARenderContext ctx)
override {
if (mTexture) {
ctx.
render.
rectangle(ATexturedBrush { mTexture }, { 0, 0 }, float(SCALE) * glm::vec2(mCells->size()));
}
auto drawGrid = [&] {
ASmallVector<std::pair<glm::vec2, glm::vec2>, 128 * 2> points;
for (int i = 1; i < mCells->size().x; ++i) {
points << std::make_pair(glm::vec2(i * SCALE, 0.f), glm::vec2(i * SCALE,
getSize().y));
}
for (int i = 1; i < mCells->size().y; ++i) {
points << std::make_pair(glm::vec2(0.f, i * SCALE), glm::vec2(
getSize().x, i * SCALE));
}
ctx.render.
lines(ASolidBrush { AColor::GRAY }, points);
};
drawGrid();
}
glm::ivec2 position = glm::ivec2(event.
position /
float(SCALE));
(*mCells)[position] = !(*mCells)[position];
updateTexture();
}
private:
_<Cells> mCells;
_<ITexture> mTexture;
void updateTexture() {
if (!mTexture) {
mTexture =
AWindow::current()->
getRenderingContext()->renderer().getNewTexture();
}
CellsImage image(mCells->size());
for (unsigned y = 0; y < image.height(); ++y) {
for (unsigned x = 0; x < image.width(); ++x) {
image.set(
{ x, y },
AFormattedColorConverter(
(*mCells)[glm::ivec2(x, y)] == CellState::ALIVE
? AColor::WHITE
: AColor::TRANSPARENT_BLACK));
}
}
mTexture->setImage(image);
}
};
class GameOfLifeWindow :
public AWindow {
public:
GameOfLifeWindow() : AWindow("Game of Life") {
Centered {
Horizontal {
_new<AButton>(
"Randomize")
let {
},
it & mCells.isRunning > [](AButton& b, bool isRunning) {
b.
setText(isRunning ?
"Pause" :
"Run");
};
connect(it->clicked, [&] { mCells.isRunning = !mCells.isRunning; });
},
},
},
Centered {
Expanding(),
BackgroundSolid(AColor::BLACK),
},
},
});
}
private:
Cells mCells { { 64, 64 } };
};
auto w = _new<GameOfLifeWindow>();
w->pack();
w->show();
return 0;
}
A base object class.
Definition AObject.h:39
static AThreadPool & global()
Global thread pool created with the default constructor.
void setContents(const _< AViewContainer > &container)
Moves (like via std::move) all children and layout of the specified container to this container.
Base class of all UI objects.
Definition AView.h:78
virtual void render(ARenderContext ctx)
Draws this AView. Noone should call this function except rendering routine.
void redraw()
Request window manager to redraw this AView.
glm::ivec2 getSize() const noexcept
Size, including content area, border and padding.
Definition AView.h:217
virtual int getContentMinimumHeight()
virtual int getContentMinimumWidth()
virtual void onPointerPressed(const APointerPressedEvent &event)
Called on pointer (mouse) released event.
Represents a window in the underlying windowing system.
Definition AWindow.h:45
static AWindowBase * current()
virtual void lines(const ABrush &brush, AArrayView< glm::vec2 > points, const ABorderStyle &style, AMetric width)=0
Draws polyline (non-loop line strip).
virtual void rectangle(const ABrush &brush, glm::vec2 position, glm::vec2 size)=0
Draws simple rectangle.
NotSelector< L > operator!(L l)
Makes a logical "NOT" selector.
Definition NotSelector.h:52
static decltype(auto) connect(const Signal &signal, Object *object, Function &&function)
Connects signal to the slot of the specified object.
Definition AObject.h:86
ASignal< Args... > emits
A signal declaration.
Definition ASignal.h:572
#define slot(v)
Passes some variable and type of the variable separated by comma. It's convenient to use with the con...
Definition kAUI.h:88
#define emit
emits the specified signal in context of this object.
Definition AObject.h:343
#define let
Performs multiple operations on a single object without repeating its name (in place) This function c...
Definition kAUI.h:262
#define with_style
Allows to define a style to the view right in place.
Definition kAUI.h:287
#define AUI_ENTRY
Application entry point.
Definition Entry.h:90
glm::vec2 position
Where does the event occurred.
Definition APointerPressedEvent.h:25
static _< T > fake(T *raw)
Creates fake shared pointer to T* raw with empty destructor, which does nothing. It's useful when som...
Definition SharedPtrTypes.h:429