Skip to content

Commit

Permalink
New Command 2059 - EasyRPG Zoom
Browse files Browse the repository at this point in the history
Zooms in and Out the screen.

`The syntax always comes in pairs. The first parameter of each pair indicates whether you are using a direct value or a variable/indirect variable, through ValueOrVariable().`

------------------------

#### Syntax (TPC):
```js
@raw 2059,
      "",          // Not Used.
      0, 0,        // Scale value in percentage (Default is 100%).
      0, 1,        // Origin Type (0 = absolute pixel || 1 =percentage of screen area )
      0, 50,        // Origin X
      0, 50,        // Origin Y
```

#### Example:
```js
@raw 2059, "", 1, 20, 0, 0, 1, 21, 1, 22 // size is var20, absolute pixel, originX is var21, originY is var22
```

-----------------------------------

This command differs from maniacs patch zoom, which is executed per picture layer, and it has a interpolation between zoom states and a "wait for completion" check.
  • Loading branch information
jetrotal committed Feb 13, 2025
1 parent 6260f41 commit 3d70de3
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 6 deletions.
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 @@ bool Game_Interpreter::ExecuteCommand(lcf::rpg::EventCommand const& com) {
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 @@ bool Game_Interpreter::CommandEasyRpgDestroyMapEvent(lcf::rpg::EventCommand cons
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::ToggleVsync() {
}

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 @@ void Sdl2Ui::UpdateDisplay() {
}
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 @@ void Sdl2Ui::UpdateDisplay() {

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

0 comments on commit 3d70de3

Please sign in to comment.