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 # Controlling the resolution of the game window,
# Value, Aspect, Window Resolusion # and disables resolution setting in game,
# (ratio and resolution are not acceptable values) # it is not recommended to change.
# Where X - not recommended, the correctness of defScreenW=0
# the game is not guaranteed. defScreenH=0
# 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,
# it is not recommended to change.
# If you want to configure 16:9 or any other,
# use AspectPreset.
# 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)
@ -35,36 +34,36 @@ class Language
str.chars.each do |c| str.chars.each do |c|
if not string_began if not string_began
string_began = true if c == '"' string_began = true if c == '"'
next next
end end
next if c == "\n" next if c == "\n"
next if c == "\r" next if c == "\r"
if not escape if not escape
break if c == '"' break if c == '"'
if c == '\\' if c == '\\'
escape = true escape = true
next next
end end
else else
escape = false escape = false
case c case c
when 'n' when 'n'
unescaped.push("\n") unescaped.push("\n")
when 'r' when 'r'
unescaped.push("\r") unescaped.push("\r")
else else
unescaped.push(c) unescaped.push(c)
end end
next next
end end
unescaped.push(c) unescaped.push(c)
end end
return unescaped.join('') return unescaped.join('')
end end
def load_pot(path) def load_pot(path)
msgid = nil msgid = nil

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;
SignalConnection(sigc::connection conn)
: connection(std::move(conn))
{}
void Disconnect() void Disconnect()
{ {
connection.disconnect(); if (&connection != nullptr)
//if (connection.connected())
connection.disconnect();
//else
// Debug() << "Double disconnect!";
else
Debug() << "Couldn't disconnect nullptr connection!";
} }
bool Connected() const bool Connected() const
{ {
if (&connection == nullptr)
Debug() << "nullptr connection!";
return false;
return connection.connected(); return connection.connected();
} }
private: private:
SignalConnection(sigc::connection conn)
: connection(std::move(conn))
{}
sigc::connection connection; sigc::connection connection;
template<typename> template<typename>