#pragma once #include "Board.h" #include "BoardDriver.h" #include "Vector3D.h" template class BoardManager{ public: BoardManager(BoardDriver &boardDriver); ~BoardManager() = default; void Init(); void Update(); void SetCubeColor(const V3D &position, const V3D &color); void SetColumnColors(const V3D &column, const V3D *color); /** * @brief Fill a column along any axis with a color * @param column .z specifies the normal direction of the plane (see PLANE_NORMAL), and * the x,y values specify the location of the column in that plane * to fill. IE To fill one stack at 0,2 I would say give V3D(0,2,PLANE_NORMAL::Z) * @param color the color you want to fill the column with */ void FillColumnColor(const V3D &column, const V3D &color); bool HasBoardChanged(); void ClearBoardChanged(); String &Board2StackString(); private: BoardDriver &driver; Board board{}; bool hasBoardChanged{false}; void updateBoardColors(const V3D &column); uint32_t getColumnHeight(BOARD_TYPES::PLANE_NORMAL normal){ switch(normal){ case BOARD_TYPES::PLANE_NORMAL::X: return BOARD_DIMS.x; break; case BOARD_TYPES::PLANE_NORMAL::Y: return BOARD_DIMS.y; break; case BOARD_TYPES::PLANE_NORMAL::Z: return BOARD_DIMS.z; break; default: return 0; } } }; template BoardManager::BoardManager(BoardDriver &boardDriver): driver(boardDriver){} template void BoardManager::Init(){ this->driver.Init(); } template void BoardManager::Update(){ // update the occupied cubes on the board and the cube colors for(uint32_t x = 0; x < BOARD_DIMS.x; x++){ for(uint32_t y = 0; y < BOARD_DIMS.y; y++){ uint32_t stackIndex{y * BOARD_DIMS.x + x}; uint32_t numCubes{this->driver.GetNumberCubes(stackIndex)}; for(uint32_t z = 0; z < BOARD_DIMS.z; z++){ V3D cubePosition{x, y, z}; this->board.SetCubeOccupation(cubePosition, z < numCubes); cubePosition.z = BOARD_TYPES::PLANE_NORMAL::Z; this->driver.UpdateStackLEDs(stackIndex, this->board.SliceBoard(cubePosition), BOARD_DIMS.z); } } } } template void BoardManager::updateBoardColors(const V3D &column){ Cube ** cubeSlice{this->board.SliceBoard(column)}; uint32_t numCubes{this->getColumnHeight(static_cast(column.z))}; this->driver.UpdateStackLEDs(BOARD_DIMS.x, cubeSlice, numCubes); } template void BoardManager::SetCubeColor(const V3D &position, const V3D &color){ this->board.SetCubeColor(position, color); V3D slice{position.x, position.y, BOARD_TYPES::PLANE_NORMAL::Z}; this->updateBoardColors(slice); } template void BoardManager::SetColumnColors(const V3D &column, const V3D *color){ uint32_t columnHeight{this->getColumnHeight(static_cast(column.z))}; V3D position = column; for(uint32_t z = 0; z < columnHeight; z++){ position.z = z; this->board.SetCubeColor(position, color[z]); } this->updateBoardColors(column); } template void BoardManager::FillColumnColor(const V3D &column, const V3D &color){ uint32_t columnHeight{this->getColumnHeight(column.z)}; V3D position = column; for(uint32_t z = 0; z < columnHeight; z++){ position.z = z; this->board.SetCubeColor(position, color); } this->updateBoardColors(column); } template bool BoardManager::HasBoardChanged(){return this->hasBoardChanged;} template void BoardManager::ClearBoardChanged(){this->hasBoardChanged = false;} template String &BoardManager::Board2StackString(){ String message{}; this->board.ToStackString(message); return message; }