trying to dynamic resolution (im so bad...)

This commit is contained in:
Issac332 2026-07-16 04:20:55 +03:00
parent be2452a3b1
commit 34db76fc45
23 changed files with 191 additions and 109 deletions

View File

@ -82,6 +82,7 @@ set(MAIN_HEADERS
src/signals/signal.h src/signals/signal.h
src/signals/signalconnection.h src/signals/signalconnection.h
src/signals/rubydispatcher.h src/signals/rubydispatcher.h
src/signals/maindispatcher.h
) )
set(MAIN_SOURCE set(MAIN_SOURCE
@ -129,6 +130,7 @@ set(MAIN_SOURCE
src/sunshine.cpp src/sunshine.cpp
src/lightmap.cpp src/lightmap.cpp
src/signals/rubydispatcher.cpp src/signals/rubydispatcher.cpp
src/signals/maindispatcher.cpp
) )
if(WIN32) if(WIN32)

View File

@ -3,32 +3,33 @@
This is a specialized fork of [mkxp-oneshot](https://github.com/elizagamedev/mkxp-oneshot) designed for OneShot: Sunshine mod. This is a specialized fork of [mkxp-oneshot](https://github.com/elizagamedev/mkxp-oneshot) designed for OneShot: Sunshine mod.
Target of sunshine mod - improve original game. Target of sunshine mod - improve original game.
# xScripts.rxdata ## xScripts.rxdata
./rpgscript.rb scripts/ [GameDir] ./rpgscript.rb scripts/ [GameDir]
# Build ## Build
1.Install required packages
* Cmake
* C/C++ compiler
* xxd
* Ruby 3+
* Boost
* SDL3
* pixman
* SDL3_image
* SDL3_ttf
* [SDL3_sound](https://github.com/icculus/SDL_sound)
* OpenAL
* PhysFS
* sigc++-2.0
* OpenSSL
* libzip
* GTK3(Linux only!)
* libxfconf(Linux only!)
2.build 1. Install required packages
* Cmake
* C/C++ compiler
* xxd
* Ruby 3+
* Boost
* SDL3
* pixman
* SDL3_image
* SDL3_ttf
* [SDL3_sound](https://github.com/icculus/SDL_sound)
* OpenAL
* PhysFS
* sigc++-2.0
* OpenSSL
* libzip
* GTK3(Linux only!)
* libxfconf(Linux only!)
* In project dir create build dir 2. build
* cmake -S . -B build * In project dir create build dir
* cd build * cmake -S . -B build
* make -jn (n - count of threads for compilation) * cd build
* make -jn (n - count of threads for compilation)

View File

@ -297,5 +297,5 @@ void graphicsBindingInit(){
INIT_GRA_PROP_BIND( Frameskip, "frameskip" ); INIT_GRA_PROP_BIND( Frameskip, "frameskip" );
const Config &conf = shState->rtData().config; const Config &conf = shState->rtData().config;
rb_define_const(module, "RESOLUTION_ASPECT", rb_str_new_cstr(conf.AspectPresetRubyConst.c_str())); rb_define_const(module, "RESOLUTION_OVERRIDDEN", rb_bool_new(conf.resolutionOverridden));
} }

View File

@ -17,10 +17,7 @@ module RPG
module Cache module Cache
@cache = {} @cache = {}
def self.load_bitmap(folder_name, filename, hue = 0) def self.load_bitmap(folder_name, filename, hue = 0)
path = folder_name + filename path = Graphics.adapted_file(folder_name + filename)
if File.exist?(folder_name + filename + Graphics::RESOLUTION_ASPECT + ".png")
path += Graphics::RESOLUTION_ASPECT
end
if not @cache.include?(path) or @cache[path].disposed? if not @cache.include?(path) or @cache[path].disposed?
if filename != "" if filename != ""
@cache[path] = Bitmap.new(path) @cache[path] = Bitmap.new(path)

View File

@ -25,25 +25,11 @@ printFPS=false
# as opposed to stretch-to-fill # as opposed to stretch-to-fill
fixedAspectRatio=true fixedAspectRatio=true
# Set Monitor Aspect preset
# Value, Aspect, Window Resolusion
# (ratio and resolution are not acceptable values)
# Where X - not recommended, the correctness of
# the game is not guaranteed.
# 0 - 3:2 - 720:480
# 1 - 4:3 - 640x480 (default)
# 2 - 16:9 - 960x540
# 3 - 16:10 - 960x600
# 4 - 16:9 HD - 1280x720 X
# 5 - 16:9 FHD - 1920x1080 X
AspectPreset=1
# Controlling the resolution of the game window, # Controlling the resolution of the game window,
# and disables resolution setting in game,
# it is not recommended to change. # it is not recommended to change.
# If you want to configure 16:9 or any other, defScreenW=0
# use AspectPreset. defScreenH=0
# defScreenW=0
# defScreenH=0
# Apply linear interpolation when game screen # Apply linear interpolation when game screen
# is upscaled # is upscaled

View File

@ -84,8 +84,9 @@ set(scripts
Window_TPtL.rb Window_TPtL.rb
Settings.rb Settings.rb
Input.rb Input.rb
DynamicLight.rb Dynamic_Light.rb
Gamepad_Colors.rb) Gamepad_Colors.rb
Dynamic_Resolution.rb)
find_program(RUBY_EXE ruby find_program(RUBY_EXE ruby
DOC "Location of the Ruby executable") DOC "Location of the Ruby executable")

View File

@ -8,6 +8,7 @@ module Settings
# Video # Video
:fullscreen => false, :fullscreen => false,
:resolution => 0,
:colorblind => false, :colorblind => false,
:frameskip => true, :frameskip => true,
:twm_shader => true, :twm_shader => true,
@ -142,6 +143,13 @@ class Window_Settings
:name => tr('Fullscreen'), :name => tr('Fullscreen'),
:parameter => :fullscreen :parameter => :fullscreen
}, },
{
:type => :enum,
:name => tr('Resolution'),
:default => 0,
:parameter => Graphics::RESOLUTION_OVERRIDDEN ? nil : :resolution,
:values => Graphics::RESOLUTION_OVERRIDDEN ? ["Resolution is redefined via config"] : Graphics.resolutions_names_list
},
{ {
:type => :bool, :type => :bool,
:name => tr('Colorblind mode'), :name => tr('Colorblind mode'),

View File

@ -18,16 +18,19 @@ class Window_Settings
attr_reader :viewport attr_reader :viewport
attr_reader :offset attr_reader :offset
def initialize(viewport, offset_y) def initialize(viewport, offset_y, screen = 0, index = 0)
Window_Settings.send(:remove_const, :PARAMETER_WIDTH)
Window_Settings.const_set(:PARAMETER_WIDTH, (Graphics.width - 640) / 2 + 512) # костыль бля
@viewport = viewport @viewport = viewport
@screen = 0 @screen = screen
@index = 0 @index = index
@opacity = 255 @opacity = 255
@offset = offset_y @offset = offset_y
@waiting_for_key = false @waiting_for_key = false
@wait_timer = 0 @wait_timer = 0
@visible_x = 0 @visible_x = @screen * Graphics.width
@visible_y = offset_y @visible_y = offset_y
@x = (Graphics.width - PARAMETER_WIDTH) / 2 @x = (Graphics.width - PARAMETER_WIDTH) / 2
@y = offset_y @y = offset_y
@ -36,7 +39,7 @@ class Window_Settings
@selection_sprite.bitmap = Bitmap.new(PARAMETER_WIDTH + 16, PARAMETER_HEIGHT) @selection_sprite.bitmap = Bitmap.new(PARAMETER_WIDTH + 16, PARAMETER_HEIGHT)
@selection_sprite.bitmap.fill_rect(Rect.new(0, 0, PARAMETER_WIDTH + 16, PARAMETER_HEIGHT), Color.new(255, 255, 255, 64)) @selection_sprite.bitmap.fill_rect(Rect.new(0, 0, PARAMETER_WIDTH + 16, PARAMETER_HEIGHT), Color.new(255, 255, 255, 64))
@selection_sprite.x = @x - 8 @selection_sprite.x = @x - 8
@selection_sprite.y = @offset @selection_sprite.y = @index * PARAMETER_HEIGHT + @y
@selection_sprite.blend_type = 1 @selection_sprite.blend_type = 1
@selection_sprite.z = 1 @selection_sprite.z = 1

View File

@ -20,6 +20,17 @@ module Settings
def fullscreen(value) def fullscreen(value)
Graphics.fullscreen = $console = value Graphics.fullscreen = $console = value
end end
def resolution(value)
if (!Graphics::RESOLUTION_OVERRIDDEN)
res_data = Graphics::RESOLUTIONS&.[](value) || {:width => 480, :height => 640}
old_width = Graphics.width
old_height = Graphics.height
new_width = res_data[:width]
new_height = res_data[:height]
Graphics.move_screen(Graphics.x - (new_width - old_width) / 2, Graphics.y - (new_height - old_height) / 2)
Graphics.resize_screen(new_width, new_height)
end
end
def colorblind(value) def colorblind(value)
$game_switches[252] = value $game_switches[252] = value
end end

View File

@ -0,0 +1,48 @@
module Graphics
# 0 - 3:2 - 720x480
# 1 - 4:3 - 640x480 (default)
# 2 - 16:9 - 960x540
# 3 - 16:10 - 960x600
RESOLUTIONS = [
{
:display_name => "4:3 - 640x480",
:file_tag => "_4_3",
:width => 640,
:height => 480,
},
{
:display_name => "3:2 - 720x480",
:file_tag => "_3_2",
:width => 720,
:height => 480,
},
{
:display_name => "16:9 - 960x540",
:file_tag => "_16_9",
:width => 960,
:height => 540,
},
{
:display_name => "16:10 - 960x600",
:file_tag => "_16_10",
:width => 960,
:height => 600,
},
]
def self.resolutions_names_list
list = []
RESOLUTIONS.each do |res_data|
list << res_data[:display_name]
end
list
end
def self.adapted_file(path, extention = ".png")
file_tag = RESOLUTIONS[Settings[:resolution] || 999]&.[](:file_tag) || ""
if File.exist?(path + file_tag + extention)
path + file_tag
end
path
end
end

View File

@ -3,7 +3,7 @@ module Settings
class << self class << self
def [](k) def [](k)
@data[k] @data&.[](k)
end end
def []=(k, v) def []=(k, v)

View File

@ -10,8 +10,10 @@ class Window_Settings
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height) @viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport.z = 9998 @viewport.z = 9998
@bg = Sprite.new(@viewport) @bg = Sprite.new(@viewport)
@bg.bitmap = Bitmap.new(Graphics.width, Graphics.height) @bg.bitmap = Bitmap.new(1, 1)
@bg.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, Color.new(0, 0, 0, 196)) @bg.bitmap.fill_rect(0, 0, 1, 1, Color.new(0, 0, 0, 196))
@bg.zoom_x = Graphics.width
@bg.zoom_y = Graphics.height
@title = Sprite.new(@viewport) @title = Sprite.new(@viewport)
@title.bitmap = Bitmap.new(320, 20) @title.bitmap = Bitmap.new(320, 20)
@title.bitmap.font.size = 20 @title.bitmap.font.size = 20
@ -27,9 +29,11 @@ class Window_Settings
if self.visible if self.visible
@viewport.rect.width = w @viewport.rect.width = w
@viewport.rect.height = h @viewport.rect.height = h
@bg.bitmap.dispose @bg.zoom_x = w
@bg.bitmap = Bitmap.new(w, h) @bg.zoom_y = h
@bg.bitmap.fill_rect(0, 0, w, h, Color.new(0, 0, 0, 196)) #@bg.bitmap.dispose
#@bg.bitmap = Bitmap.new(w, h)
#@bg.bitmap.fill_rect(0, 0, w, h, Color.new(0, 0, 0, 196))
@title.x = (w - @title.bitmap.width) / 2 @title.x = (w - @title.bitmap.width) / 2
init_content init_content
else else
@ -50,11 +54,15 @@ class Window_Settings
end end
def init_content def init_content
old_screen = 0
old_index = 0
if (@content) if (@content)
old_screen = @content.screen
old_index = @content.index
@content.dispose @content.dispose
end end
@content = SettingsContent.new(@viewport, TITLE_TOP_MARGIN + TITLE_MARGIN + 100) @content = SettingsContent.new(@viewport, TITLE_TOP_MARGIN + TITLE_MARGIN + 100, old_screen, old_index)
DATA.each_with_index do |(screen_title, parameters_info), screen_index| DATA.each_with_index do |(screen_title, parameters_info), screen_index|
@content.add_screen(screen_title) @content.add_screen(screen_title)

View File

@ -31,6 +31,8 @@ Game_Light
Settings Settings
Input Input
Gamepad_Colors Gamepad_Colors
Dynamic_Resolution
Dynamic_Light
Sprite_Character Sprite_Character
Sprite_Picture Sprite_Picture
@ -103,7 +105,6 @@ Doc_Message
Desktop_Message Desktop_Message
Credits_Message Credits_Message
Particles Particles
DynamicLight
EdText EdText
Main Main

View File

@ -12,7 +12,6 @@ class Language
def set(lc) def set(lc)
@data = nil @data = nil
@tr = nil @tr = nil
script = nil
[lc.full.to_s, lc.lang.to_s].each do |name| [lc.full.to_s, lc.lang.to_s].each do |name|
path = "Languages/#{name}.po" path = "Languages/#{name}.po"
if FileTest.exist?(path) if FileTest.exist?(path)

View File

@ -72,11 +72,11 @@ void Config::read(int argc, char *argv[]){
PO_DESC(printFPS, bool, false) \ PO_DESC(printFPS, bool, false) \
PO_DESC(fullscreen, bool, false) \ PO_DESC(fullscreen, bool, false) \
PO_DESC(fixedAspectRatio, bool, true) \ PO_DESC(fixedAspectRatio, bool, true) \
PO_DESC(AspectPreset, int, 1) \ /*PO_DESC(AspectPreset, int, 1)*/ \
PO_DESC(smoothScaling, bool, false) \ PO_DESC(smoothScaling, bool, false) \
PO_DESC(vsync, bool, true) \ PO_DESC(vsync, bool, true) \
PO_DESC(defScreenW, int, 640) \ PO_DESC(defScreenW, int, 0) \
PO_DESC(defScreenH, int, 480) \ PO_DESC(defScreenH, int, 0) \
PO_DESC(windowTitle, std::string, "") \ PO_DESC(windowTitle, std::string, "") \
PO_DESC(commonDataPath, std::string, "") \ PO_DESC(commonDataPath, std::string, "") \
PO_DESC(Modloader.ModsDirPath, std::string,"mods") \ PO_DESC(Modloader.ModsDirPath, std::string,"mods") \
@ -181,6 +181,10 @@ void Config::read(int argc, char *argv[]){
game.title = "OneShot: Sunshine"; game.title = "OneShot: Sunshine";
game.scripts = "Data/xScripts.rxdata"; game.scripts = "Data/xScripts.rxdata";
resolutionOverridden = defScreenW > 0 || defScreenH > 0;
defScreenW = defScreenW <= 0 ? 640 : defScreenW;
defScreenH = defScreenH <= 0 ? 480 : defScreenH;
/*
#define ASPECT_SELECT(id, x, y, rubyConst) \ #define ASPECT_SELECT(id, x, y, rubyConst) \
case id: { \ case id: { \
defScreenW = x; \ defScreenW = x; \
@ -202,7 +206,7 @@ void Config::read(int argc, char *argv[]){
} }
#undef ASPECT_SELECT #undef ASPECT_SELECT
*/
#ifdef STEAM #ifdef STEAM
/* Override fullscreen config if Big Picture */ /* Override fullscreen config if Big Picture */
if (const char *env = SDL_getenv("SteamTenfoot")){ if (const char *env = SDL_getenv("SteamTenfoot")){

View File

@ -32,6 +32,7 @@ struct Config{
bool printFPS; bool printFPS;
bool fullscreen; bool fullscreen;
bool fixedAspectRatio; bool fixedAspectRatio;
bool resolutionOverridden;
bool Windows_AllocConsole; bool Windows_AllocConsole;
bool smoothScaling; bool smoothScaling;
bool vsync; bool vsync;
@ -51,8 +52,8 @@ struct Config{
int maxTextureSize; int maxTextureSize;
std::string gameFolder; std::string gameFolder;
int AspectPreset; //int AspectPreset;
std::string AspectPresetRubyConst; //std::string AspectPresetRubyConst;
bool allowSymlinks; bool allowSymlinks;
bool pathCache; bool pathCache;

View File

@ -180,6 +180,9 @@ void EventThread::process(RGSSThreadData &rtData){
SDL_GetWindowPosition(win, &rtData.ethread->winX, &rtData.ethread->winY); SDL_GetWindowPosition(win, &rtData.ethread->winX, &rtData.ethread->winY);
while (true) { while (true) {
if (shState != nullptr)
shState->mainDispatcher().process();
if (!SDL_WaitEvent(&event)) { if (!SDL_WaitEvent(&event)) {
Debug() << "[EventThread::process] Event error:\n" << SDL_GetError(); Debug() << "[EventThread::process] Event error:\n" << SDL_GetError();
break; break;

View File

@ -57,7 +57,7 @@ struct SharedStatePrivate{
Scene *screen; Scene *screen;
RubyDispatcher rubyDispatcher; RubyDispatcher rubyDispatcher;
RenderDispatcher renderDispatcher; MainDispatcher mainDispatcher;
FileSystem fileSystem; FileSystem fileSystem;
@ -100,7 +100,7 @@ struct SharedStatePrivate{
: bindingData(0), : bindingData(0),
sdlWindow(threadData->window), sdlWindow(threadData->window),
rubyDispatcher(), rubyDispatcher(),
renderDispatcher(), mainDispatcher(),
fileSystem(threadData->config.allowSymlinks), fileSystem(threadData->config.allowSymlinks),
eThread(*threadData->ethread), eThread(*threadData->ethread),
rtData(*threadData), rtData(*threadData),
@ -200,7 +200,7 @@ GSATT(void*, bindingData)
GSATT(SDL_Window*, sdlWindow) GSATT(SDL_Window*, sdlWindow)
GSATT(Scene*, screen) GSATT(Scene*, screen)
GSATT(RubyDispatcher&, rubyDispatcher) GSATT(RubyDispatcher&, rubyDispatcher)
GSATT(RenderDispatcher&, renderDispatcher) GSATT(MainDispatcher&, mainDispatcher)
GSATT(FileSystem&, fileSystem) GSATT(FileSystem&, fileSystem)
GSATT(EventThread&, eThread) GSATT(EventThread&, eThread)
GSATT(RGSSThreadData&, rtData) GSATT(RGSSThreadData&, rtData)

View File

@ -24,7 +24,7 @@
#include "signals/signal.h" #include "signals/signal.h"
#include "signals/rubydispatcher.h" #include "signals/rubydispatcher.h"
#include "signals/renderdispatcher.h" #include "signals/maindispatcher.h"
#define shState SharedState::instance #define shState SharedState::instance
#define glState shState->_glState() #define glState shState->_glState()
@ -74,7 +74,7 @@ struct SharedState{
// dispatchers, they redirect signals from another thread to their own // dispatchers, they redirect signals from another thread to their own
RubyDispatcher &rubyDispatcher() const; RubyDispatcher &rubyDispatcher() const;
RenderDispatcher &renderDispatcher() const; MainDispatcher &mainDispatcher() const;
// other shit idk // other shit idk
void *bindingData() const; void *bindingData() const;

View File

@ -1,11 +1,11 @@
#include "renderdispatcher.h" #include "maindispatcher.h"
void RenderDispatcher::invoke(std::function<void()> fn){ void MainDispatcher::invoke(std::function<void()> fn){
std::lock_guard lock(mutex); std::lock_guard lock(mutex);
queue.push(std::move(fn)); queue.push(std::move(fn));
} }
void RenderDispatcher::process(){ void MainDispatcher::process(){
std::queue<std::function<void()>> local; std::queue<std::function<void()>> local;
{ {

View File

@ -4,9 +4,9 @@
#include <mutex> #include <mutex>
#include <queue> #include <queue>
class RenderDispatcher{ class MainDispatcher{
public: public:
RenderDispatcher() {}; MainDispatcher() {};
void invoke(std::function<void()> fn); void invoke(std::function<void()> fn);
void process(); void process();

View File

@ -1,26 +1,35 @@
#pragma once #pragma once
#include <sigc++/connection.h> #include <sigc++/connection.h>
#include "debugwriter.h"
class SignalConnection{ class SignalConnection{
public: public:
SignalConnection() = default; SignalConnection() = default;
void Disconnect()
{
connection.disconnect();
}
bool Connected() const
{
return connection.connected();
}
private:
SignalConnection(sigc::connection conn) SignalConnection(sigc::connection conn)
: connection(std::move(conn)) : connection(std::move(conn))
{} {}
void Disconnect()
{
if (&connection != nullptr)
//if (connection.connected())
connection.disconnect();
//else
// Debug() << "Double disconnect!";
else
Debug() << "Couldn't disconnect nullptr connection!";
}
bool Connected() const
{
if (&connection == nullptr)
Debug() << "nullptr connection!";
return false;
return connection.connected();
}
private:
sigc::connection connection; sigc::connection connection;
template<typename> template<typename>