git repos / sago_multi_scrambler_puzzle2

src/sago_common.cpp

browsing at commit = 2d9bff86eda4975ad92ec1072b994971fd13b7ba

raw · blame · history

/*
===========================================================================
 * Sago Multi Scrambler Puzzle
Copyright (C) 2022 Poul Sander

This program 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 2 of the License, or
(at your option) any later version.

This program 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 this program.  If not, see http://www.gnu.org/licenses/

Source information and contacts persons can be found at
https://github.com/sago007/saland
===========================================================================
*/

#include "sago/SagoDataHolder.hpp"
#include "sago/SagoSpriteHolder.hpp"
#include "sago/GameStateInterface.hpp"
#include "sago/SagoTextField.hpp"
#include "globals.hpp"
#include "sago_common.hpp"
#include "SagoImGui.hpp"
#include "sago/platform_folders.h"
#include "sago/SagoMisc.hpp"
#include "os.hpp"
#include <iostream>

void InitSagoFS(int argc, const char* argv[]) {
	PHYSFS_init(argv[0]);
	PHYSFS_mount((std::string(PHYSFS_getBaseDir())+"/data").c_str(), nullptr, 0);
	PHYSFS_mount("./data", nullptr, 0);
	PHYSFS_mount(getPathToSaveFiles().c_str(), nullptr, 0);
	OsCreateSaveFolder();
	PHYSFS_setWriteDir(getPathToSaveFiles().c_str());
}

void RunGameState(sago::GameStateInterface& state ) {
	bool done = false;  //We are done!
	while (!done && !globalData.isShuttingDown) {
		SDL_SetRenderDrawColor(globalData.screen, 0, 0, 0, 255);
		//SDL_RenderClear(globalData.screen);
		DrawBackground(globalData.screen);
		ImGui_ImplSDLRenderer2_NewFrame();
		ImGui_ImplSDL2_NewFrame();
		ImGui::NewFrame();
		state.Draw(globalData.screen);

		ImGui::Render();
		ImGuiIO& io = ImGui::GetIO();
		float x, y;
		//SDL_RenderGetScale(globalData.screen, &x, &y);
		//SDL_RenderSetScale(globalData.screen, io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
		ImGui_ImplSDLRenderer2_RenderDrawData( ImGui::GetDrawData(), globalData.screen );
		//SDL_RenderSetScale(globalData.screen, x, y);

		//While using Dear ImGui we do not draw the mouse ourself. This is gone: globalData.mouse.Draw(globalData.screen, SDL_GetTicks(), globalData.mousex, globalData.mousey);
		SDL_RenderPresent(globalData.screen);


		SDL_Delay(5);
		SDL_Event event;

		bool mustWriteScreenshot = false;

		while ( SDL_PollEvent(&event) ) {
			UpdateMouseCoordinates(event, globalData.mousex, globalData.mousey);
			if ( event.type == SDL_QUIT ) {
				globalData.isShuttingDown = true;
				done = true;
			}

			if (event.type == SDL_WINDOWEVENT) {
				if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
					SDL_GetRendererOutputSize(globalData.screen, &globalData.xsize, &globalData.ysize);
				}
			}

			if ( event.key.keysym.sym == SDLK_F9 ) {
				mustWriteScreenshot = true;
			}

			bool processed = false;
			state.ProcessInput(event, processed);

		}

		state.Update();



		if (!state.IsActive()) {
			done = true;
		}
	}
}

void DrawBackground(SDL_Renderer* target) {
	SDL_RenderClear(target);
	sago::SagoSprite background = globalData.spriteHolder->GetSprite("background_tile");
	size_t ticks = SDL_GetTicks();
	if (true) {
		int nextX = 0;
		if (true) {
			nextX -= (ticks/100)%background.GetWidth();
		}
		while (nextX < globalData.xsize) {
			int nextY = 0;
			if (true) {
				nextY -= (ticks/100)%background.GetWidth();
			}
			while (nextY < globalData.ysize) {
				background.Draw(target, ticks, nextX, nextY);
				nextY += background.GetHeight();
			}
			nextX += background.GetWidth();
		}
		return;
	}
	background.DrawScaled(target, ticks, 0, 0, globalData.xsize, globalData.ysize);
}

/**
 * This function reads the mouse coordinates from a relevant event.
 * Unlike SDL_GetMouseState this works even if SDL_RenderSetLogicalSize is used
 * @param event
 * @param mousex
 * @param mousey
 */
void UpdateMouseCoordinates(const SDL_Event& event, int& mousex, int& mousey) {
	switch (event.type) {
	case SDL_MOUSEBUTTONDOWN:
	case SDL_MOUSEBUTTONUP:
		mousex = event.button.x;
		mousey = event.button.y;
		break;
	case SDL_MOUSEMOTION:
		mousex = event.motion.x;
		mousey = event.motion.y;
		break;
	default:
		break;
	}
}

sago::SagoDataHolder dataHolder;


static SDL_Window* win = nullptr;
static std::string imgui_inifile;

void InitGame() {
	int width = globalData.xsize, height = globalData.ysize;
	SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER);
	IMG_Init(IMG_INIT_PNG);
	TTF_Init();
	Mix_Init(MIX_INIT_OGG);

	int rendererFlags = 0;

	SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");
	SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_SCALING, "1");
	win = SDL_CreateWindow(GAMENAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_RESIZABLE);
	// Set the window icon from the bundled PNG (loaded via PhysFS)
	{
		std::string icon_data = sago::GetFileContent("textures/app_icon.png");
		if (!icon_data.empty()) {
			SDL_RWops* rw = SDL_RWFromConstMem(icon_data.data(), static_cast<int>(icon_data.size()));
			SDL_Surface* icon_surface = IMG_Load_RW(rw, 1);
			if (icon_surface) {
				SDL_SetWindowIcon(win, icon_surface);
				SDL_FreeSurface(icon_surface);
			}
		}
	}
	globalData.screen = SDL_CreateRenderer(win, -1, rendererFlags);
	//SDL_RenderSetLogicalSize(globalData.screen, width, height);
	InitImGui(win, globalData.screen, width, height);
	ImGuiIO& io = ImGui::GetIO();
	io.IniFilename = nullptr;
	imgui_inifile = getPathToSaveFiles() + "/imgui.ini";
	ImGui::LoadIniSettingsFromDisk(imgui_inifile.c_str());

	dataHolder.invalidateAll(globalData.screen);
	globalData.spriteHolder.reset(new sago::SagoSpriteHolder(dataHolder));
	globalData.dataHolder = &dataHolder;
	globalData.mouse = globalData.spriteHolder->GetSprite("mouse");
	SDL_ShowCursor(SDL_DISABLE);
}

void UninitGame() {
	ImGui::SaveIniSettingsToDisk(imgui_inifile.c_str());

	SDL_DestroyRenderer(globalData.screen);
	SDL_DestroyWindow(win);

	SDL_Quit();
}