Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Command 2059 - EasyRPG Zoom #3351

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/game_interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include "game_screen.h"
#include "game_interpreter_control_variables.h"
#include "game_windows.h"
#include "graphics.h"
#include "json_helper.h"
#include "maniac_patch.h"
#include "spriteset_map.h"
Expand Down Expand Up @@ -794,6 +795,8 @@
return CommandEasyRpgCloneMapEvent(com);
case Cmd::EasyRpg_DestroyMapEvent:
return CommandEasyRpgDestroyMapEvent(com);
case static_cast<Cmd>(2059):

Check warning on line 798 in src/game_interpreter.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04

case value '2059' not in enumerated type 'Game_Interpreter::Cmd' {aka 'lcf::rpg::EventCommand::Code'} [-Wswitch]
return CommandEasyRpgZoom(com);
default:
return true;
}
Expand Down Expand Up @@ -5491,6 +5494,26 @@
return true;
}

bool Game_Interpreter::CommandEasyRpgZoom(lcf::rpg::EventCommand const& com) {
if (!Player::HasEasyRpgExtensions()) {
//return true;
}

int Scale = ValueOrVariable(com.parameters[0], com.parameters[1]);
bool OriginAsPercentage = static_cast<bool>(ValueOrVariable(com.parameters[2], com.parameters[3]));
int OriginX = ValueOrVariable(com.parameters[4], com.parameters[5]);
int OriginY = ValueOrVariable(com.parameters[6], com.parameters[7]);

Graphics::GetZoomData().SetScale(Scale);
Graphics::GetZoomData().SetOriginAsPercentage(OriginAsPercentage);
Graphics::GetZoomData().SetOriginX(OriginX);
Graphics::GetZoomData().SetOriginY(OriginY);

//Output::Warning("Zoom: {} Scale: {}, OriginAsPercentage: {}, OriginX: {}, OriginY: {}", Graphics::GetZoomData().GetScale(), Graphics::GetZoomData().IsOriginPercentage(), Graphics::GetZoomData().GetOriginX(), Graphics::GetZoomData().GetOriginY());

return true;
}

Game_Interpreter& Game_Interpreter::GetForegroundInterpreter() {
return Game_Battle::IsBattleRunning()
? Game_Battle::GetInterpreter()
Expand Down
1 change: 1 addition & 0 deletions src/game_interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ class Game_Interpreter : public Game_BaseInterpreterContext
bool CommandEasyRpgProcessJson(lcf::rpg::EventCommand const& com);
bool CommandEasyRpgCloneMapEvent(lcf::rpg::EventCommand const& com);
bool CommandEasyRpgDestroyMapEvent(lcf::rpg::EventCommand const& com);
bool CommandEasyRpgZoom(lcf::rpg::EventCommand const& com);
bool CommandManiacGetGameInfo(lcf::rpg::EventCommand const& com);

void SetSubcommandIndex(int indent, int idx);
Expand Down
8 changes: 8 additions & 0 deletions src/graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@
using namespace std::chrono_literals;

namespace Graphics {
namespace {
static ZoomData viewport_scale_instance;
}

ZoomData& GetZoomData() {
return viewport_scale_instance;
}

void UpdateTitle();

std::shared_ptr<Scene> current_scene;
Expand Down
29 changes: 28 additions & 1 deletion src/graphics.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#ifndef EP_GRAPHICS_H
#define EP_GRAPHICS_H

// Headers
#include <memory>
#include <vector>
#include "bitmap.h"
#include "drawable.h"
Expand All @@ -33,6 +33,33 @@ class Scene;
* Handles screen drawing.
*/
namespace Graphics {
/**
* Controls viewport scaling and positioning
*/
class ZoomData {
private:
int scale_percentage = 100;
bool origin_type = true; // true = percentage, false = absolute pixels
int origin_x = 50; // center point for scaling
int origin_y = 50; // center point for scaling

public:
int GetScale() const { return scale_percentage; }
void SetScale(int percentage) { scale_percentage = percentage; }

bool IsOriginPercentage() const { return origin_type; }
void SetOriginAsPercentage(bool is_relative) { origin_type = is_relative; }

int GetOriginX() const { return origin_x; }
void SetOriginX(int x) { origin_x = x; }

int GetOriginY() const { return origin_y; }
void SetOriginY(int y) { origin_y = y; }
};

// Global instance declaration
extern ZoomData& GetZoomData();

/**
* Initializes Graphics.
*/
Expand Down
85 changes: 80 additions & 5 deletions src/platform/sdl/sdl2_ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "game_config.h"
#include "system.h"
#include "sdl2_ui.h"
#include "scene.h"

#ifdef _WIN32
# include <windows.h>
Expand Down Expand Up @@ -590,6 +591,25 @@
}

void Sdl2Ui::UpdateDisplay() {

struct zoom_params {
int zoom;
bool is_anchor_percent;
int x;
int y;
};

zoom_params params{100,true,50,50};

auto st = Scene::instance->type;
if (st == Scene::Battle || st == Scene::Map) {
params.zoom = Graphics::GetZoomData().GetScale();
params.is_anchor_percent = Graphics::GetZoomData().IsOriginPercentage();
params.x = Graphics::GetZoomData().GetOriginX();
params.y = Graphics::GetZoomData().GetOriginY();

}

#ifdef __WIIU__
if (vcfg.scaling_mode.Get() == ConfigEnum::ScalingMode::Bilinear && window.scale > 0.f) {
// Workaround WiiU bug: Bilinear uses a render target and for these the format is not converted
Expand Down Expand Up @@ -676,7 +696,7 @@
}
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
sdl_texture_scaled = SDL_CreateTexture(sdl_renderer, texture_format, SDL_TEXTUREACCESS_TARGET,
static_cast<int>(ceilf(window.scale)) * main_surface->width(), static_cast<int>(ceilf(window.scale)) * main_surface->height());
static_cast<int>(ceilf(window.scale)) * main_surface->width(), static_cast<int>(ceilf(window.scale)) * main_surface->height());
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
if (!sdl_texture_scaled) {
Output::Debug("SDL_CreateTexture failed : {}", SDL_GetError());
Expand All @@ -686,18 +706,73 @@

SDL_RenderClear(sdl_renderer);
if (vcfg.scaling_mode.Get() == ConfigEnum::ScalingMode::Bilinear && window.scale > 0.f) {
// Calculate zoom parameters
float zoom_scale = params.zoom / 100.0f;

// Calculate source rectangle (the area we want to show)
SDL_Rect src_rect;
int zoomed_width = static_cast<int>(main_surface->width() * zoom_scale);

Check warning on line 714 in src/platform/sdl/sdl2_ui.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04

unused variable 'zoomed_width' [-Wunused-variable]
int zoomed_height = static_cast<int>(main_surface->height() * zoom_scale);

Check warning on line 715 in src/platform/sdl/sdl2_ui.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04

unused variable 'zoomed_height' [-Wunused-variable]

// Calculate anchor points
int anchor_pixel_x = params.is_anchor_percent ?
(params.x * main_surface->width() / 100) :
params.x;
int anchor_pixel_y = params.is_anchor_percent ?
(params.y * main_surface->height() / 100) :
params.y;

// Calculate the top-left corner of the source rectangle
src_rect.x = anchor_pixel_x - (main_surface->width() / (2 * zoom_scale));
src_rect.y = anchor_pixel_y - (main_surface->height() / (2 * zoom_scale));
src_rect.w = main_surface->width() / zoom_scale;
src_rect.h = main_surface->height() / zoom_scale;

// Clamp source rectangle to texture bounds
if (src_rect.x < 0) src_rect.x = 0;
if (src_rect.y < 0) src_rect.y = 0;
if (src_rect.x + src_rect.w > main_surface->width())
src_rect.x = main_surface->width() - src_rect.w;
if (src_rect.y + src_rect.h > main_surface->height())
src_rect.y = main_surface->height() - src_rect.h;

// Render game texture on the scaled texture
SDL_SetRenderTarget(sdl_renderer, sdl_texture_scaled);
SDL_RenderClear(sdl_renderer);
SDL_RenderCopy(sdl_renderer, sdl_texture_game, nullptr, nullptr);
SDL_RenderCopy(sdl_renderer, sdl_texture_game, &src_rect, nullptr);

SDL_SetRenderTarget(sdl_renderer, nullptr);
SDL_RenderCopy(sdl_renderer, sdl_texture_scaled, nullptr, nullptr);
} else {
SDL_RenderCopy(sdl_renderer, sdl_texture_game, nullptr, nullptr);
}
else {
// Handle non-bilinear case with zoom
float zoom_scale = params.zoom / 100.0f;

SDL_Rect src_rect;
int anchor_pixel_x = params.is_anchor_percent ?
(params.x * main_surface->width() / 100) :
params.x;
int anchor_pixel_y = params.is_anchor_percent ?
(params.y * main_surface->height() / 100) :
params.y;

src_rect.x = anchor_pixel_x - (main_surface->width() / (2 * zoom_scale));
src_rect.y = anchor_pixel_y - (main_surface->height() / (2 * zoom_scale));
src_rect.w = main_surface->width() / zoom_scale;
src_rect.h = main_surface->height() / zoom_scale;

// Clamp source rectangle
if (src_rect.x < 0) src_rect.x = 0;
if (src_rect.y < 0) src_rect.y = 0;
if (src_rect.x + src_rect.w > main_surface->width())
src_rect.x = main_surface->width() - src_rect.w;
if (src_rect.y + src_rect.h > main_surface->height())
src_rect.y = main_surface->height() - src_rect.h;

SDL_RenderCopy(sdl_renderer, sdl_texture_game, &src_rect, nullptr);
}
SDL_RenderPresent(sdl_renderer);
}
}

void Sdl2Ui::SetTitle(const std::string &title) {
SDL_SetWindowTitle(sdl_window, title.c_str());
Expand Down
Loading