initial commit

This commit is contained in:
frank 2021-05-07 21:26:44 -04:00
commit 8645486078
7 changed files with 409 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
local/
*.o
BPmono.ttf
compile_commands.json
pudding

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "lib/sfw"]
path = lib/sfw
url = frank@shampoo.ooo:/var/www/git/sfw

143
Makefile Normal file
View File

@ -0,0 +1,143 @@
SRC_DIR := src/
SFW_DIR := lib/sfw/
SFW_SRC_DIR := $(SFW_DIR)src/
SFW_LIB_DIR := $(SFW_DIR)lib/
SDLGFX2_DIR := $(SFW_LIB_DIR)sdl2-gfx/
GLEW_DIR := $(SFW_LIB_DIR)glew/
CC_LINUX := clang
CPPC_LINUX := clang++
SDLCONFIG := /home/frank/local/sdl/bin/sdl2-config
SDL_FLAGS := $(shell $(SDLCONFIG) --cflags)
BUILDDIR := build
EXT_SRC_ROOT := /home/frank/ext/software
SDLHOME := $(EXT_SRC_ROOT)/SDL2-2.0.14
SDL_IMG_HOME := $(EXT_SRC_ROOT)/SDL2_image-2.0.4
SDL_TTF_HOME := $(EXT_SRC_ROOT)/SDL2_ttf-2.0.14
GLEW_WIN32_HOME = $(EXT_SRC_ROOT)/glew-2.1.0-win32
PROJECTHOME = $(shell pwd)
EMSCRIPTENHOME = $(EXT_SRC_ROOT)/emsdk/upstream/emscripten
WINBUILDDIR = win
SDLMINGWHOME = $(SDLHOME)/i686-w64-mingw32
SDL_IMG_MINGW_HOME = $(SDL_IMG_HOME)/i686-w64-mingw32
SDL_TTF_MINGW_HOME = $(SDL_TTF_HOME)/i686-w64-mingw32
APPDIR = Main.app/Contents
SYSFWPATH = /Library/Frameworks
SFW_H_FILES := $(wildcard $(addprefix $(SFW_SRC_DIR),*.hpp))
SFW_O_FILES := $(filter-out $(addprefix $(SFW_SRC_DIR),filesystem.o),$(SFW_H_FILES:.hpp=.o))
GAME_H_FILES := $(wildcard $(addprefix $(SRC_DIR),*.hpp))
GAME_O_FILES := $(GAME_H_FILES:.hpp=.o)
CREATE_FONT_SYMLINK = ln -nsf $(SFW_DIR)"BPmono.ttf" .
EMSCRIPTEN_CFLAGS = -O3 -Wall -s USE_SDL=2 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS="['png']" \
-s USE_SDL_TTF=2 -s USE_SDL_MIXER=2 -s MAX_WEBGL_VERSION=1 -s EXTRA_EXPORTED_RUNTIME_METHODS="['ccall']" \
-s EXPORTED_FUNCTIONS="['_main', '_reset_game']" -s ALLOW_MEMORY_GROWTH=1 -s GL_PREINITIALIZED_CONTEXT=1 \
-s ENVIRONMENT=web --shell-file shell_minimal.html --no-heap-copy -I$(SFW_LIB_DIR) -I$(SFW_SRC_DIR)
EMSCRIPTEN_PRELOADS = --preload-file "BPmono.ttf"@/ --preload-file "config.json" \
--preload-file "resource"
$(SDLGFX2_DIR)%.o: $(SDLGFX2_DIR)%.c $(SDLGFX2_DIR)%.h
$(GLEW_DIR)%.o: $(GLEW_DIR)%.c $(GLEW_DIR)%.h
$(CC) $(CFLAGS) $< -c -o $@
$(SFW_SRC_DIR)extension.o : $(addprefix $(SFW_SRC_DIR),Box.hpp Segment.hpp Color.hpp filesystem.hpp Pixels.hpp)
$(SFW_SRC_DIR)Node.o : $(addprefix $(SFW_SRC_DIR),Game.hpp Configuration.hpp Delegate.hpp Display.hpp Input.hpp Box.hpp Audio.hpp)
$(SFW_SRC_DIR)Sprite.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Game.hpp Box.hpp Animation.hpp Color.hpp extension.hpp Pixels.hpp)
$(SFW_SRC_DIR)Game.o : $(addprefix $(SFW_SRC_DIR),extension.hpp Node.hpp Sprite.hpp Recorder.hpp Input.hpp Configuration.hpp \
Delegate.hpp Audio.hpp)
$(SFW_SRC_DIR)Animation.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Timer.hpp)
$(SFW_SRC_DIR)Recorder.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Game.hpp Configuration.hpp Delegate.hpp Animation.hpp extension.hpp)
$(SFW_SRC_DIR)Input.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Animation.hpp Configuration.hpp Delegate.hpp)
$(SFW_SRC_DIR)Configuration.o : $(addprefix $(SFW_SRC_DIR),Node.hpp)
$(SFW_SRC_DIR)Delegate.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Game.hpp Input.hpp)
$(SFW_SRC_DIR)Display.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Game.hpp Box.hpp Configuration.hpp Delegate.hpp)
$(SFW_SRC_DIR)Box.o : $(addprefix $(SFW_SRC_DIR),extension.hpp Segment.hpp)
$(SFW_SRC_DIR)Segment.o : $(addprefix $(SFW_SRC_DIR),extension.hpp Box.hpp)
$(SFW_SRC_DIR)Pixels.o : $(addprefix $(SFW_SRC_DIR),Box.hpp extension.hpp)
$(SFW_SRC_DIR)Audio.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Display.hpp Configuration.hpp Box.hpp filesystem.hpp extension.hpp)
$(SRC_DIR)Pudding.o : $(SFW_H_FILES)
%.o : %.cpp %.hpp
$(CPPC) $(CPP_FLAGS) $< -c -o $@
linux : CC = clang
linux : CPPC = clang++
linux : CFLAGS = -Wall -Wextra -O3 -c -I$(SFW_LIB_DIR) -I$(SFW_SRC_DIR) $(SDL_FLAGS)
linux : CPP_FLAGS = $(CFLAGS) --std=c++17
linux : LFLAGS = $(shell $(SDLCONFIG) --libs) -lpthread
linux : $(GLEW_DIR)glew.o $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPrimitives.o) \
$(SFW_O_FILES) $(GAME_O_FILES)
$(CREATE_FONT_SYMLINK)
$(CPPC) $(LFLAGS) -D__LINUX__ -lGL -lGLESv2 -lSDL2_image -lSDL2_ttf -lSDL2_mixer -lcurl -lstdc++fs $^ -o pudding
emscripten : CC = $(EMSCRIPTENHOME)/emcc
emscripten : CPPC = $(EMSCRIPTENHOME)/em++
emscripten : CFLAGS = $(EMSCRIPTEN_CFLAGS)
emscripten : CPP_FLAGS = $(CFLAGS) --std=c++17
emscripten : $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPrimitives.o) $(SFW_O_FILES) $(GAME_O_FILES)
$(CREATE_FONT_SYMLINK)
$(CPPC) $(CPP_FLAGS) $(EMSCRIPTEN_PRELOADS) $^ -o "index.html"
collide_test : CC = clang
collide_test : CPPC = clang++
collide_test : CFLAGS = -Wall -Wextra -O3 -g -c -I$(SFW_LIB_DIR) -I$(SFW_SRC_DIR) $(SDL_FLAGS)
collide_test : CPP_FLAGS = $(CFLAGS) --std=c++17
collide_test : LFLAGS = $(shell $(SDLCONFIG) --libs) -lpthread
collide_test : $(GLEW_DIR)glew.o $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPrimitives.o) \
$(SFW_O_FILES) CollisionTest.o
$(CPPC) $(LFLAGS) -D__LINUX__ -lGL -lSDL2_image -lSDL2_ttf -lSDL2_mixer -lstdc++fs $^ -o collide-test
collide_test_emscripten : CC = $(EMSCRIPTENHOME)/emcc
collide_test_emscripten : CPPC = $(EMSCRIPTENHOME)/em++
collide_test_emscripten : CFLAGS = $(EMSCRIPTEN_CFLAGS)
collide_test_emscripten : CPP_FLAGS = $(CFLAGS) --std=c++17
collide_test_emscripten : $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPrimitives.o) $(SFW_O_FILES) CollisionTest.o
$(CREATE_FONT_SYMLINK)
$(CPPC) $(CPP_FLAGS) $(EMSCRIPTEN_PRELOADS) --emrun $^ -o "collision_test.html"
.PHONY : clean
clean :
-rm *.o
-rm $(SFW_SRC_DIR)*.o
-rm $(GLEW_DIR)*.o
-rm $(SDLGFX2_DIR)*.o
android :
if [ ! -d $(BUILDDIR) ]; then mkdir $(BUILDDIR); fi;
cd $(SDLHOME)/build-scripts/ && \
./androidbuild.sh $(ANDROIDPROJECT) $(PROJECTHOME)/main.cpp
cp -r $(SDLHOME)/build/$(ANDROIDPROJECT) $(BUILDDIR)
sed -i s/2\.3\.3/2\.2\.3/g $(BUILDDIR)/$(ANDROIDPROJECT)/build.gradle
sed -i s/26\.0\.1/23\.0\.1/g $(BUILDDIR)/$(ANDROIDPROJECT)/app/build.gradle
cd $(BUILDDIR)/$(ANDROIDPROJECT) && ./gradlew assembleDebug
mingw :
if [ ! -d $(BUILDDIR)/$(WINBUILDDIR) ]; then mkdir -p $(BUILDDIR)/$(WINBUILDDIR); fi;
cd $(BUILDDIR)/$(WINBUILDDIR) && \
i686-w64-mingw32-g++ -std=c++17 $(PROJECTHOME)/main.cpp -I$(SDLMINGWHOME)/include/SDL2 \
-I$(SDL_IMG_MINGW_HOME)/include/SDL2 -I$(SDL_TTF_MINGW_HOME)/include/SDL2 $(INC) \
$(PROJECTHOME)/sdl2-gfx/SDL2_gfxPrimitives.c $(PROJECTHOME)/sdl2-gfx/SDL2_rotozoom.c $(PROJECTHOME)/glew/glew.c \
-L$(SDLMINGWHOME)/lib -L$(SDL_IMG_MINGW_HOME)/lib -L$(SDL_TTF_MINGW_HOME)/lib \
-lmingw32 -lSDL2_image \
-lSDL2_ttf -lstdc++fs \
-lSDL2main -lSDL2 -lopengl32 -Wall -O2 -o main.exe && \
cp $(SDLMINGWHOME)/bin/SDL2.dll $(SDL_IMG_MINGW_HOME)/bin/SDL2_image.dll \
$(SDL_TTF_MINGW_HOME)/bin/SDL2_ttf.dll .
osx :
g++ -I $(SYSFWPATH)/SDL2.framework/Headers $(INC) \
-I $(SYSFWPATH)/SDL2_image.framework/Headers -Wl,-rpath,$(SYSFWPATH) \
-framework SDL2 -framework SDL2_image -framework OpenGL main.cpp sdl2-gfx/SDL2_rotozoom.c \
-o main
osx-bundle :
if [ ! -d "$(APPDIR)" ]; then mkdir -p $(APPDIR); fi;
if [ ! -d "$(APPDIR)" ]; then mkdir $(APPDIR); fi;
if [ ! -d "$(APPDIR)/MacOS" ]; then mkdir $(APPDIR)/MacOS; fi;
if [ ! -d "$(APPDIR)/Frameworks" ]; then mkdir $(APPDIR)/Frameworks; fi;
if [ ! -d "$(APPDIR)/Resources" ]; then mkdir $(APPDIR)/Resources; fi;
touch $(APPDIR)/Info.plist
cp -r $(SYSFWPATH)/SDL2.framework $(APPDIR)/Frameworks
cp -r $(SYSFWPATH)/SDL2_image.framework $(APPDIR)/Frameworks
g++ -I $(SYSFWPATH)/SDL2.framework/Headers -I $(SYSFWPATH)/SDL2_image.framework/Headers \
-Wl,-rpath,@executable_path/../Frameworks -Wl,-rpath,$(SYSFWPATH) \
-framework SDL2 -framework SDL2_image -framework OpenGL main.cpp -o $(APPDIR)/MacOS/main
cross : linux android emscripten mingw

41
config.json Normal file
View File

@ -0,0 +1,41 @@
{
"display":
{
"dimensions": [680, 384],
"framerate": 60,
"title": "Pudding",
"debug": false,
"render driver": "opengl"
},
"path":
{
"screenshots": "local/screenshots",
"video": "local/video"
},
"gamepad":
{
},
"keys":
{
"print-video-memory-size": ["CTRL", "v"],
"print-frame-length-history": ["CTRL", "SHIFT", "h"]
},
"recording":
{
"enabled": true,
"write-mp4": false,
"video-frame-length": 33.333,
"max-video-memory": 2000
},
"input":
{
"any-key-ignore-commands": ["up", "right", "down", "left"],
"suppress-any-key-on-mods": true
},
"scan":
{
"json-save": true,
"json-save-directory": "local/scans",
"barcode": "02266600"
}
}

1
lib/sfw Submodule

@ -0,0 +1 @@
Subproject commit a8948bca73450be6ec0820f07a6703e245fd1edc

164
src/Pudding.cpp Normal file
View File

@ -0,0 +1,164 @@
/*
______________
//````````````\\ 😀 Thank you for choosing Pudding Customs for your business 😀
//~~~~~~~~~~~~~~\\
//================\\ Custom pudding code provided by 0eggxactly ........... [http://0eggxactly.itch.io]
// \\ Available for copy, modification and redistribution .. [http://git.shampoo.ooo/pudding]
// ''CUSTOM PUDDING'' \\ Updates .............................................. [http://twitter.com/diskmem]
//______________________\\
``````````````````````````
*/
#include "Pudding.hpp"
int main()
{
Pudding pudding = Pudding();
pudding.run();
pudding.quit();
return 0;
}
Pudding::Pudding()
{
load_sdl_context();
}
void Pudding::load_sdl_context()
{
super::load_sdl_context();
}
void Pudding::curl_get_bytes(std::string url, std::vector<std::uint8_t>* storage, std::string user_agent)
{
CURL *curl;
CURLcode result;
result = curl_global_init(CURL_GLOBAL_DEFAULT);
if (result != CURLE_OK)
{
std::cout << "curl initialization failed " << curl_easy_strerror(result) << std::endl;
}
else
{
curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Pudding::store_curl_response);
std::vector<std::uint8_t> food_barcode_response;
curl_easy_setopt(curl, CURLOPT_WRITEDATA, storage);
curl_easy_setopt(curl, CURLOPT_USERAGENT, user_agent.c_str());
result = curl_easy_perform(curl);
if (result != CURLE_OK)
{
std::cout << "curl request failed " << curl_easy_strerror(result) << std::endl;
}
}
else
{
std::cout << "curl initialization failed" << std::endl;
}
curl_easy_cleanup(curl);
}
curl_global_cleanup();
}
nlohmann::json Pudding::food_json_from_barcode(std::string barcode)
{
std::string url = "https://world.openfoodfacts.org/api/v0/product/" + barcode;
std::vector<std::uint8_t> storage;
curl_get_bytes(url, &storage, USER_AGENT);
nlohmann::json food_json;
food_json = nlohmann::json::parse(storage);
if (get_configuration()["scan"]["json-save"] && !is_food_json_empty(food_json))
{
fs::path path = get_configuration()["scan"]["json-save-directory"];
if (!fs::exists(path))
{
fs::create_directories(path);
}
std::string prefix = "";
if (food_json.contains("product"))
{
if (food_json["product"].value("brands", "") != "")
{
prefix += food_json["product"]["brands"].get<std::string>() + "_";
}
if (food_json["product"].value("product_name", "") != "")
{
prefix += food_json["product"]["product_name"].get<std::string>() + "_";
}
}
if (prefix == "")
{
prefix = "Unknown_";
}
std::replace_if(prefix.begin(), prefix.end(), [](char c) { return !std::isalnum(c); }, '_');
path /= prefix + barcode + ".json";
std::ofstream out(path);
out << std::setw(4) << food_json << std::endl;
SDL_Log("Saved JSON to %s", path.c_str());
}
return food_json;
}
size_t Pudding::store_curl_response(std::uint8_t* buffer, size_t size, size_t count, std::vector<std::uint8_t>* storage)
{
size_t total_size = size * count;
storage->insert(storage->end(), buffer, buffer + total_size);
return total_size;
}
bool Pudding::is_food_json_empty(nlohmann::json food_json)
{
return !food_json.value("status", 0) || !food_json.contains("product");
}
SDL_Texture* Pudding::texture_from_image_url(std::string url)
{
std::vector<std::uint8_t> storage;
curl_get_bytes(url, &storage, USER_AGENT);
if (!storage.empty())
{
SDL_RWops* rw = SDL_RWFromConstMem(storage.data(), storage.size());
return IMG_LoadTexture_RW(get_renderer(), rw, 0);
}
else
{
return nullptr;
}
}
void Pudding::refresh()
{
nlohmann::json food_json = food_json_from_barcode(get_configuration()["scan"]["barcode"]);
if (!is_food_json_empty(food_json))
{
if (food_json["product"].value("image_url", "") != "")
{
std::string url = food_json["product"]["image_url"];
SDL_Texture* texture = texture_from_image_url(url);
SDL_Log("looking up image at %s", url.c_str());
if (texture != nullptr)
{
image.unload();
image.add_frames(texture);
image.add_wrap(true, true);
}
}
}
}
void Pudding::update()
{
get_root()->configuration.load("config.json");
get_root()->configuration.merge();
if (current_barcode != get_configuration()["scan"]["barcode"])
{
current_barcode = get_configuration()["scan"]["barcode"];
refresh();
}
image.move_weighted(glm::vec2(1.681, 1));
image.update();
}

52
src/Pudding.hpp Normal file
View File

@ -0,0 +1,52 @@
#ifndef Pudding_h_
#define Pudding_h_
#include <string>
#include <iostream>
#include <curl/curl.h>
#include <filesystem>
#include "json/json.hpp"
#include "glm/vec2.hpp"
#include "Game.hpp"
#include "Sprite.hpp"
#include "Color.hpp"
#include "extension.hpp"
struct Pudding : Game
{
const std::string USER_AGENT = "Work in progress game for http://shampoo.ooo";
const std::string OPEN_FOOD_API_URL = "https://world.openfoodfacts.org/api/v0/product/";
const std::string NUTRONIX_API_URL = "https://trackapi.nutritionix.com/v2/search/item?upc=";
const std::string NUTRONIX_APP_ID = "ea0f2e7e";
const std::string NUTRONIX_APP_KEY = "39218dde526dd3349daa028deda518ae";
const std::string BARCODE_MONSTER_API_URL = "https://barcode.monster/api/";
const std::string EDAMAM_API_URL = "https://api.edamam.com/api/food-database/v2/parser?upc=&app_id=&app_key=";
const std::string EDAMAM_APP_ID = "c23b139f";
const std::string EDAMAM_APP_KEY = "c54cf8c997534caf7ee92b1ccc7d95a3";
const std::string BEST_BUY_API_URL = "https://api.bestbuy.com/v1/products(upc=)?format=json&apiKey=";
const std::string BEST_BUY_API_KEY = "cFshpD7C2LtMq07GqlBVpYtY";
/*
* images, ingredients, protein weight, nutrition grade, popularity, "serving unit", item name, brand name, keywords,
* allergens, calories, fat, saturated fat, cholesterol, sodium, carbohydrates, fiber, sugar, potassium
*/
typedef Game super;
Sprite image = Sprite(this);
std::string current_barcode;
Pudding();
void load_sdl_context();
nlohmann::json food_json_from_barcode(std::string);
void curl_get_bytes(std::string url, std::vector<std::uint8_t>*, std::string = "");
static size_t store_curl_response(std::uint8_t*, size_t, size_t, std::vector<std::uint8_t>*);
bool is_food_json_empty(nlohmann::json);
SDL_Texture* texture_from_image_url(std::string);
void refresh();
void update();
std::string get_class_name() { return "Pudding"; }
};
#endif