diff --git a/src/Button.h b/src/Button.h index c72bc08..7d207b9 100644 --- a/src/Button.h +++ b/src/Button.h @@ -6,11 +6,14 @@ class Button { protected: + +public: + // TODO / JankMode: setter & getter for these three fields + // were protected, but directly changing them should be...fine? sf::RectangleShape rect; sf::Text caption; std::string action; -public: Button() {}; Button(int x, int y, int w, int h, sf::Color _background, sf::Color _textcolor, @@ -24,5 +27,6 @@ public: void render(sf::RenderWindow & window); auto contains(sf::Vector2i p) { return rect.getGlobalBounds().contains(p.x, p.y); } auto getAction() { return action; } + private: }; diff --git a/src/GameEngine.cpp b/src/GameEngine.cpp index 2cff97c..a49f89c 100644 --- a/src/GameEngine.cpp +++ b/src/GameEngine.cpp @@ -20,6 +20,8 @@ GameEngine::GameEngine() McRFPy_API::api_init(); McRFPy_API::executePyString("import mcrfpy"); McRFPy_API::executePyString("from UIMenu import *"); + + IndexSprite::game = this; } Scene* GameEngine::currentScene() { return scenes[scene]; } diff --git a/src/GameEngine.h b/src/GameEngine.h index 200e973..9281a7e 100644 --- a/src/GameEngine.h +++ b/src/GameEngine.h @@ -5,6 +5,7 @@ #include "EntityManager.h" #include "Scene.h" #include "McRFPy_API.h" +#include "IndexTexture.h" class GameEngine { @@ -16,7 +17,6 @@ class GameEngine bool paused = false; int currentFrame = 0; sf::View visible; - //McRFPy_API* api; public: GameEngine(); @@ -30,4 +30,12 @@ public: void sUserInput(); int getFrame() { return currentFrame; } sf::View getView() { return visible; } + + // global textures for scripts to access + std::vector textures; + + // global audio storage + std::vector sfxbuffers; + sf::Music music; + sf::Sound sfx; }; diff --git a/src/Grid.h b/src/Grid.h index 41e00ed..ff0c055 100644 --- a/src/Grid.h +++ b/src/Grid.h @@ -1,3 +1,4 @@ +#pragma once #include "Common.h" class GridPoint diff --git a/src/IndexSprite.cpp b/src/IndexSprite.cpp new file mode 100644 index 0000000..f2dbaf0 --- /dev/null +++ b/src/IndexSprite.cpp @@ -0,0 +1,16 @@ +#include "IndexSprite.h" +#include "GameEngine.h" + +//int texture_index, sprite_index, x, y; + +GameEngine* IndexSprite::game; + +sf::Sprite IndexSprite::drawable() +{ + sf::Sprite s; + auto& tex = IndexSprite::game->textures[texture_index]; + s.setTexture(tex.texture); + s.setPosition(sf::Vector2f(x, y)); + s.setTextureRect(tex.spriteCoordinates(sprite_index)); + return s; +} diff --git a/src/IndexSprite.h b/src/IndexSprite.h new file mode 100644 index 0000000..60d205b --- /dev/null +++ b/src/IndexSprite.h @@ -0,0 +1,10 @@ +#pragma once +#include "Common.h" +class GameEngine; // forward declare + +class IndexSprite { +public: + int texture_index, sprite_index, x, y; + static GameEngine* game; + sf::Sprite drawable(); +}; diff --git a/src/IndexTexture.cpp b/src/IndexTexture.cpp new file mode 100644 index 0000000..9d82b9a --- /dev/null +++ b/src/IndexTexture.cpp @@ -0,0 +1,6 @@ +#include "IndexTexture.h" + +sf::IntRect IndexTexture::spriteCoordinates(int index) { + int tx = index % grid_width, ty = index / grid_width; + return sf::IntRect(tx * grid_size, ty * grid_size, grid_size, grid_size); +} diff --git a/src/IndexTexture.h b/src/IndexTexture.h new file mode 100644 index 0000000..7e39d5b --- /dev/null +++ b/src/IndexTexture.h @@ -0,0 +1,11 @@ +#pragma once +#include "Common.h" +class GameEngine; // forward declare + +class IndexTexture { +public: + sf::Texture texture; + int grid_size, grid_width, grid_height; + static GameEngine* game; + sf::IntRect spriteCoordinates(int); +}; diff --git a/src/McRFPy_API.cpp b/src/McRFPy_API.cpp index 0aa174d..7373789 100644 --- a/src/McRFPy_API.cpp +++ b/src/McRFPy_API.cpp @@ -3,9 +3,20 @@ #include "GameEngine.h" #include "Grid.h" +// static class members...? +std::vector McRFPy_API::menus; +std::vector McRFPy_API::grids; + static PyMethodDef mcrfpyMethods[] = { {"drawSprite", McRFPy_API::_drawSprite, METH_VARARGS, "Draw a sprite (index, x, y)"}, + + {"createMenu", McRFPy_API::_createMenu, METH_VARARGS, + "Create a new uimenu (x, y, w, h)"}, + + {"listMenus", McRFPy_API::_listMenus, METH_VARARGS, + "return a list of existing menus"}, + {NULL, NULL, 0, NULL} }; @@ -173,18 +184,24 @@ void McRFPy_API::REPL_device(FILE * fp, const char *filename) PyRun_InteractiveLoop(fp, filename); } -PyObject* _createMenu(PyObject *self, PyObject *args) { +PyObject* McRFPy_API::_createMenu(PyObject *self, PyObject *args) { - int sizex, sizey; - if (!PyArg_ParseTuple(args, "ii", &sizex, &sizey)) return NULL; - menus.push_back(createMenu(sizex, sizey)); + int posx, posy, sizex, sizey; + if (!PyArg_ParseTuple(args, "iiii", &posx, &posy, &sizex, &sizey)) return NULL; + menus.push_back(createMenu(posx, posy, sizex, sizey)); Py_INCREF(Py_None); return Py_None; } -PyObject* _listMenus(PyObject*, PyObject*); { +PyObject* McRFPy_API::_listMenus(PyObject*, PyObject*) { // todo - get the (Py) classes UIMenu, Button, Caption, Sprite // and call BuildValue (tuples) -> their constructors + PyObject* uimodule = PyImport_AddModule("UIMenu"); //already imported + PyObject* uimenu_type = PyObject_GetAttrString(uimodule, "UIMenu"); + PyObject* btn_type = PyObject_GetAttrString(uimodule, "Button"); + PyObject* cap_type = PyObject_GetAttrString(uimodule, "Caption"); + PyObject* spr_type = PyObject_GetAttrString(uimodule, "Sprite"); + PyObject* menulist = PyList_New(menus.size()); for (int i = 0; i < menus.size(); i++) { auto p = menus[i].box.getPosition(); @@ -192,6 +209,8 @@ PyObject* _listMenus(PyObject*, PyObject*); { PyObject* menu_args = Py_BuildValue("(iiii)", p.x, p.y, s.x, s.y); // * need uimenu_type (imported already to __main__) PyObject* menuobj = PyObject_CallObject((PyObject*) uimenu_type, menu_args); + + // Loop: Convert Button objects to Python Objects PyObject* button_list = PyObject_GetAttrString(menuobj, "buttons"); for(auto& b : menus[i].buttons) { auto bp = b.rect.getPosition(); @@ -199,23 +218,43 @@ PyObject* _listMenus(PyObject*, PyObject*); { auto bg = b.rect.getFillColor(); auto bf = b.caption.getFillColor(); PyObject* btn_args = Py_BuildValue("(iiii(iii)(iii)ss)", - bp.x, bp.y, bs.x, bs.y, - bg.r, bg.g, bg.b, - bf.r, bf.g, bf.b, - b.caption.getString.toAnsiString().c_str(), - b.action.c_str()); + bp.x, bp.y, bs.x, bs.y, + bg.r, bg.g, bg.b, + bf.r, bf.g, bf.b, + b.caption.getString().toAnsiString().c_str(), + b.action.c_str()); // * need btn_type - PyObject buttonobj = PyObject_CallObject((PyObject*) btn_type, btn_args); + PyObject* buttonobj = PyObject_CallObject((PyObject*) btn_type, btn_args); PyList_Append(button_list, buttonobj); } + // Loop: Convert Caption objects to Python Objects PyObject* caption_list = PyObject_GetAttrString(menuobj, "captions"); - for () { } + for (auto& c : menus[i].captions) { + auto cc = c.getFillColor(); + PyObject* cap_args = Py_BuildValue("si(iii)", + c.getString().toAnsiString().c_str(), + c.getCharacterSize(), + cc.r, cc.g, cc.b); + PyObject* capobj = PyObject_CallObject((PyObject*) cap_type, cap_args); + PyList_Append(caption_list, capobj); + } + // Loop: Convert Sprite objects to Python Objects PyObject* sprite_list = PyObject_GetAttrString(menuobj, "sprites"); - for () { } + for (auto& s : menus[i].sprites) { + PyObject* spr_args = Py_BuildValue("iiii", + s.texture_index, s.sprite_index, s.x, s.y); + } PyList_SET_ITEM(menulist, i, menuobj); } return menulist; } + +UIMenu McRFPy_API::createMenu(int posx, int posy, int sizex, int sizey) { + auto m = UIMenu(game->getFont()); + m.box.setPosition(sf::Vector2f(posx, posy)); + m.box.setSize(sf::Vector2f(sizex, sizey)); + return m; +} diff --git a/src/McRFPy_API.h b/src/McRFPy_API.h index 2419fdb..bd07931 100644 --- a/src/McRFPy_API.h +++ b/src/McRFPy_API.h @@ -6,6 +6,10 @@ //#include "GameEngine.h" // can't - need forward declaration //#include "ActionCode.h" #include "Python.h" +#include "UIMenu.h" +#include "Grid.h" +#include "IndexSprite.h" +#include "EntityManager.h" class GameEngine; // forward declared (circular members) @@ -37,9 +41,9 @@ public: static void REPL(); // Jank mode engage: let the API hold data for Python to hack on - std::vector menus; + static std::vector menus; EntityManager entities; // this is also kinda good, entities not on the current grid can still act (like monsters following you through doors??) - std::vector grids; + static std::vector grids; // Jank Python Method Exposures static PyObject* _createMenu(PyObject*, PyObject*); // creates a new menu object in McRFPy_API::menus @@ -55,7 +59,7 @@ public: //static PyObject* _createSprite(PyObject*, PyObject*); // Jank Functionality - static UIMenu createMenu(int sizex, int sizey); + static UIMenu createMenu(int posx, int posy, int sizex, int sizey); //static Button createButton(UIMenu & menu, int x, int y, int w, int h); //static sf::Sprite createSprite(int tex_index, int x, int y); //static void playSound(const char * filename); diff --git a/src/UIMenu.cpp b/src/UIMenu.cpp index 206ef56..15a5c4b 100644 --- a/src/UIMenu.cpp +++ b/src/UIMenu.cpp @@ -19,7 +19,10 @@ void UIMenu::render(sf::RenderWindow & window) window.draw(c); } for (auto& b : buttons) { b.render(window); } - for (auto& s: sprites) { window.draw(s); } + for (auto& s: sprites) { + auto _s = s.drawable(); + // TODO: s.move or whatever to make it's 0,0 relative to menu box + window.draw(_s); } } void UIMenu::refresh() @@ -49,7 +52,7 @@ void UIMenu::add_button(Button b) buttons.push_back(b); } -void UIMenu::add_sprite(sf::Sprite s) +void UIMenu::add_sprite(IndexSprite s) { sprites.push_back(s); } diff --git a/src/UIMenu.h b/src/UIMenu.h index c4f7896..bb490bb 100644 --- a/src/UIMenu.h +++ b/src/UIMenu.h @@ -2,6 +2,7 @@ #include "Common.h" #include "Button.h" +#include "IndexSprite.h" class UIMenu { @@ -11,7 +12,7 @@ public: UIMenu(sf::Font & _font); std::vector captions; std::vector