mirror of
https://forgejo.xatacraft.ru/Sunshine/mkxp-sunshine.git
synced 2026-08-19 13:29:54 +00:00
partial signals in ruby, gradual adaptation to dynamic resolution
This commit is contained in:
parent
0da721aa08
commit
1ddacce66e
20 changed files with 317 additions and 29 deletions
|
|
@ -81,6 +81,7 @@ set(MAIN_HEADERS
|
|||
src/define.h
|
||||
src/signals/signal.h
|
||||
src/signals/signalconnection.h
|
||||
src/signals/rubyDispatcher.h
|
||||
)
|
||||
|
||||
set(MAIN_SOURCE
|
||||
|
|
@ -127,6 +128,7 @@ set(MAIN_SOURCE
|
|||
src/modloader.cpp
|
||||
src/sunshine.cpp
|
||||
src/lightmap.cpp
|
||||
src/signals/rubyDispatcher.cpp
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
|
|
@ -265,6 +267,7 @@ set(BINDING_HEADERS
|
|||
binding-mri/viewportelement-binding.h
|
||||
binding-mri/flashable-binding.h
|
||||
binding-mri/keybindings-binding.h
|
||||
binding-mri/signalconnection-binding.h
|
||||
)
|
||||
set(BINDING_SOURCE
|
||||
binding-mri/binding-mri.cpp
|
||||
|
|
@ -294,6 +297,7 @@ set(BINDING_SOURCE
|
|||
binding-mri/modloader-binding.cpp
|
||||
binding-mri/keybindings-binding.cpp
|
||||
binding-mri/lightmap-binding.cpp
|
||||
binding-mri/signalconnection-binding.cpp
|
||||
)
|
||||
|
||||
source_group("Binding Source" FILES ${BINDING_SOURCE} ${BINDING_HEADERS})
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ void tilemapBindingInit();
|
|||
void windowVXBindingInit();
|
||||
void tilemapVXBindingInit();
|
||||
void TimeBindingInit();
|
||||
void SignalConnectionBindingInit();
|
||||
|
||||
void inputBindingInit();
|
||||
void audioBindingInit();
|
||||
|
|
@ -165,6 +166,7 @@ static void mriBindingInit(){
|
|||
windowBindingInit();
|
||||
tilemapBindingInit();
|
||||
TimeBindingInit();
|
||||
SignalConnectionBindingInit();
|
||||
inputBindingInit();
|
||||
audioBindingInit();
|
||||
graphicsBindingInit();
|
||||
|
|
|
|||
|
|
@ -26,6 +26,12 @@
|
|||
#include "binding-types.h"
|
||||
#include "exception.h"
|
||||
#include "config.h"
|
||||
#include "debugwriter.h"
|
||||
#include "signals/rubydispatcher.h"
|
||||
|
||||
#include "signalconnection-binding.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
RB_METHOD(graphicsUpdate){
|
||||
RB_UNUSED_PARAM;
|
||||
|
|
@ -208,19 +214,35 @@ DEF_GRA_PROP_B(Frameskip)
|
|||
_rb_define_module_function(module, prop_name_s "=", graphics##Set##PropName); \
|
||||
}
|
||||
|
||||
static VALUE graphicsWindowMoved(VALUE self){
|
||||
RUBY_CONNECTION
|
||||
conn->connection = shState->windowSignals.moved.Connect([conn](int x, int y){
|
||||
shState->rubyDispatcher().invoke([conn, x, y]{
|
||||
rb_funcall(conn->proc, rb_intern("call"), 2, INT2NUM(x), INT2NUM(y));
|
||||
});
|
||||
});
|
||||
return TypedData_Wrap_Struct(rb_cRubyConnection, &rubyConnection_type, conn);
|
||||
}
|
||||
|
||||
static VALUE graphicsWindowResized(VALUE self){
|
||||
RUBY_CONNECTION
|
||||
conn->connection = shState->windowSignals.resized.Connect([conn](int w, int h){
|
||||
shState->rubyDispatcher().invoke([conn, w, h]{
|
||||
rb_funcall(conn->proc, rb_intern("call"), 2, INT2NUM(w), INT2NUM(h));
|
||||
});
|
||||
});
|
||||
return TypedData_Wrap_Struct(rb_cRubyConnection, &rubyConnection_type, conn);
|
||||
}
|
||||
|
||||
void graphicsBindingInit(){
|
||||
VALUE module = rb_define_module("Graphics");
|
||||
|
||||
_rb_define_module_function(module, "update", graphicsUpdate);
|
||||
_rb_define_module_function(module, "freeze", graphicsFreeze);
|
||||
_rb_define_module_function(module, "transition", graphicsTransition);
|
||||
_rb_define_module_function(module, "frame_reset", graphicsFrameReset);
|
||||
// Signals
|
||||
|
||||
_rb_define_module_function(module, "__reset__", graphicsReset);
|
||||
|
||||
INIT_GRA_PROP_BIND( FrameRate, "frame_rate" );
|
||||
INIT_GRA_PROP_BIND( FrameCount, "frame_count" );
|
||||
rb_define_module_function(module, "window_moved", RUBY_METHOD_FUNC(graphicsWindowMoved), 0);
|
||||
rb_define_module_function(module, "window_resized", RUBY_METHOD_FUNC(graphicsWindowResized), 0);
|
||||
|
||||
// Functions
|
||||
_rb_define_module_function(module, "x", graphicsPosX);
|
||||
_rb_define_module_function(module, "y", graphicsPosY);
|
||||
_rb_define_module_function(module, "width", graphicsWidth);
|
||||
|
|
@ -231,7 +253,16 @@ void graphicsBindingInit(){
|
|||
_rb_define_module_function(module, "snap_to_bitmap", graphicsSnapToBitmap);
|
||||
_rb_define_module_function(module, "resize_screen", graphicsResizeScreen);
|
||||
_rb_define_module_function(module, "move_screen", graphicsMoveScreen);
|
||||
_rb_define_module_function(module, "update", graphicsUpdate);
|
||||
_rb_define_module_function(module, "freeze", graphicsFreeze);
|
||||
_rb_define_module_function(module, "transition", graphicsTransition);
|
||||
_rb_define_module_function(module, "frame_reset", graphicsFrameReset);
|
||||
|
||||
_rb_define_module_function(module, "__reset__", graphicsReset);
|
||||
|
||||
// Variables
|
||||
INIT_GRA_PROP_BIND( FrameRate, "frame_rate" );
|
||||
INIT_GRA_PROP_BIND( FrameCount, "frame_count" );
|
||||
INIT_GRA_PROP_BIND( Brightness, "brightness" );
|
||||
INIT_GRA_PROP_BIND( Fullscreen, "fullscreen" );
|
||||
INIT_GRA_PROP_BIND( ShowCursor, "show_cursor" );
|
||||
|
|
|
|||
59
binding-mri/signalconnection-binding.cpp
Normal file
59
binding-mri/signalconnection-binding.cpp
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
#include "etc.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
#include "debugwriter.h"
|
||||
#include "sharedstate.h"
|
||||
|
||||
#include "signalconnection-binding.h"
|
||||
|
||||
void RubyConnection::Disconnect(){
|
||||
RubyConnection::connection.Disconnect();
|
||||
}
|
||||
bool RubyConnection::Connected(){
|
||||
return RubyConnection::connection.Connected();
|
||||
}
|
||||
|
||||
VALUE rb_cRubyConnection = Qnil;
|
||||
|
||||
void rubyConnection_free(void* ptr)
|
||||
{
|
||||
RubyConnection* conn = static_cast<RubyConnection*>(ptr);
|
||||
conn->Disconnect();
|
||||
delete conn;
|
||||
}
|
||||
|
||||
void rubyConnection_mark(void *ptr)
|
||||
{
|
||||
RubyConnection *conn = static_cast<RubyConnection*>(ptr);
|
||||
|
||||
if (!NIL_P(conn->proc))
|
||||
rb_gc_mark(conn->proc);
|
||||
}
|
||||
|
||||
const rb_data_type_t rubyConnection_type = { "RubyConnection", {rubyConnection_mark, rubyConnection_free, 0}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY };
|
||||
|
||||
static VALUE rubyConnection_alloc(VALUE klass)
|
||||
{
|
||||
RubyConnection* ptr = ALLOC(RubyConnection);
|
||||
return TypedData_Wrap_Struct(klass, &rubyConnection_type, ptr);
|
||||
}
|
||||
|
||||
static VALUE rubyConnectionDisconnect(VALUE self){
|
||||
RubyConnection* conn;
|
||||
TypedData_Get_Struct(self, RubyConnection, &rubyConnection_type, conn);
|
||||
conn->Disconnect();
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static VALUE rubyConnectionConnected(VALUE self){
|
||||
RubyConnection* conn;
|
||||
TypedData_Get_Struct(self, RubyConnection, &rubyConnection_type, conn);
|
||||
return rb_bool_new(conn->Connected());
|
||||
}
|
||||
|
||||
void SignalConnectionBindingInit(){
|
||||
rb_cRubyConnection = rb_define_class("RubyConnection", rb_cObject);
|
||||
rb_define_alloc_func(rb_cRubyConnection, rubyConnection_alloc);
|
||||
rb_define_method(rb_cRubyConnection, "disconnect", RUBY_METHOD_FUNC(rubyConnectionDisconnect), 0);
|
||||
rb_define_method(rb_cRubyConnection, "connected", RUBY_METHOD_FUNC(rubyConnectionConnected), 0);
|
||||
}
|
||||
26
binding-mri/signalconnection-binding.h
Normal file
26
binding-mri/signalconnection-binding.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include "signals/signalconnection.h"
|
||||
|
||||
#include <ruby.h>
|
||||
|
||||
extern void rubyConnection_free(void* ptr);
|
||||
extern void rubyConnection_mark(void* ptr);
|
||||
extern const rb_data_type_t rubyConnection_type;
|
||||
extern VALUE rb_cRubyConnection;
|
||||
|
||||
struct RubyConnection
|
||||
{
|
||||
VALUE proc;
|
||||
SignalConnection connection;
|
||||
|
||||
void Disconnect();
|
||||
bool Connected();
|
||||
};
|
||||
|
||||
#define RUBY_CONNECTION \
|
||||
if (!rb_block_given_p()) \
|
||||
rb_raise(rb_eArgError, "unable to connect signal, block required"); \
|
||||
VALUE proc = rb_block_proc(); \
|
||||
RubyConnection* conn = new RubyConnection(); \
|
||||
conn->proc = proc;
|
||||
|
|
@ -2,7 +2,6 @@ class DynamicLight
|
|||
def initialize(viewport)
|
||||
@debug_sprite = Sprite.new(viewport)
|
||||
@debug_sprite.bitmap = Bitmap.new(Graphics.width, Graphics.height)
|
||||
@debug_sprite.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, Color.new(255, 255, 255))
|
||||
@debug_sprite.visible = false
|
||||
@light_sprite = LightMap.new(viewport)
|
||||
#@light_sprite.wallmap = Bitmap.new($game_map.width, $game_map.height)
|
||||
|
|
@ -17,6 +16,13 @@ class DynamicLight
|
|||
# end
|
||||
#end
|
||||
|
||||
@update_connection = Graphics.window_resized do |w, h|
|
||||
@debug_sprite.bitmap.rect.width = w;
|
||||
@debug_sprite.bitmap.rect.height = h;
|
||||
#@debug_sprite.bitmap.dispose
|
||||
#@debug_sprite.bitmap = Bitmap.new(w, h)
|
||||
end
|
||||
|
||||
if $light == nil
|
||||
return
|
||||
end
|
||||
|
|
@ -34,6 +40,7 @@ class DynamicLight
|
|||
end
|
||||
|
||||
def dispose
|
||||
@update_connection.disconnect
|
||||
@light_sprite.dispose
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,26 @@ class Spriteset_Map
|
|||
@viewport_lights = Viewport.new(0, 0, Graphics.width, Graphics.height)
|
||||
@viewport_flash = Viewport.new(0, 0, Graphics.width, Graphics.height)
|
||||
|
||||
@update_connection = Graphics.window_resized do |w, h|
|
||||
@viewport.rect.width = w
|
||||
@viewport.rect.height = h
|
||||
|
||||
@viewport_bg.rect.width = w
|
||||
@viewport_bg.rect.height = h
|
||||
|
||||
@viewport_pics.rect.width = w
|
||||
@viewport_pics.rect.height = h
|
||||
|
||||
@viewport_particles.rect.width = w
|
||||
@viewport_particles.rect.height = h
|
||||
|
||||
@viewport_lights.rect.width = w
|
||||
@viewport_lights.rect.height = h
|
||||
|
||||
@viewport_flash.rect.width = w
|
||||
@viewport_flash.rect.height = h
|
||||
end
|
||||
|
||||
@viewport_bg.z = -500
|
||||
@viewport_lights.z = 200
|
||||
@viewport_pics.z = 500
|
||||
|
|
@ -89,6 +109,7 @@ class Spriteset_Map
|
|||
# * Dispose
|
||||
#--------------------------------------------------------------------------
|
||||
def dispose
|
||||
@update_connection.disconnect
|
||||
# Dispose of tilemap
|
||||
@tilemap.tileset.dispose if @tilemap.tileset
|
||||
for i in 0..6
|
||||
|
|
|
|||
|
|
@ -18,6 +18,18 @@ class Window_Message < Window_Selectable
|
|||
self.z = 9999
|
||||
self.back_opacity = 210
|
||||
|
||||
@update_connection = Graphics.window_resized do |w, h|
|
||||
self.x = Graphics.width / 2 - 304
|
||||
case $game_system.message_position
|
||||
when 0 # up
|
||||
self.y = 16
|
||||
when 1 # middle
|
||||
self.y = Graphics.height / 2 - height / 2
|
||||
when 2 # down
|
||||
self.y = Graphics.height - height - 16
|
||||
end
|
||||
end
|
||||
|
||||
# Animation flags
|
||||
@fade_in = false
|
||||
@fade_out = false
|
||||
|
|
|
|||
|
|
@ -212,9 +212,11 @@ void EventThread::process(RGSSThreadData &rtData){
|
|||
//SDL_GL_GetDrawableSize(win, &winW, &winH);
|
||||
|
||||
windowSizeMsg.post(Vec2i(winW, winH));
|
||||
if (shState != nullptr)
|
||||
shState->windowSignals.resized.Emit(event.window.data1, event.window.data2);
|
||||
resetInputStates();
|
||||
break;
|
||||
|
||||
// random meow
|
||||
case SDL_EVENT_WINDOW_MOUSE_ENTER :
|
||||
cursorInWindow = true;
|
||||
mouseState.inWindow = true;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include "debugwriter.h"
|
||||
#include "oneshot.h"
|
||||
#include "define.h"
|
||||
#include "signals/rubydispatcher.h"
|
||||
#include <SDL3/SDL_video.h>
|
||||
#include <SDL3/SDL_timer.h>
|
||||
#include <SDL3_image/SDL_image.h>
|
||||
|
|
@ -616,6 +617,9 @@ Graphics::~Graphics(){
|
|||
}
|
||||
|
||||
void Graphics::update(bool limitFps){
|
||||
// TODO: move this to ruby thread update, idk where it is
|
||||
shState->rubyDispatcher().process();
|
||||
|
||||
p->checkShutDownReset();
|
||||
p->checkSyncLock();
|
||||
|
||||
|
|
@ -902,6 +906,7 @@ void Graphics::resizeScreen(int width, int height){
|
|||
FloatRect screenRect(0, 0, width, height);
|
||||
p->screenQuad.setTexPosRect(screenRect, screenRect);
|
||||
|
||||
glState.scissorBox.set(IntRect(0, 0, width, height));
|
||||
shState->eThread().requestWindowResize(width, height);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include "gl-util.h"
|
||||
#include "quad.h"
|
||||
#include "transform.h"
|
||||
#include "shader.h"
|
||||
#include "glstate.h"
|
||||
#include "quadarray.h"
|
||||
|
|
@ -33,8 +32,9 @@ struct LightMapPrivate{
|
|||
std::vector<LightSource> dynamicLightSources;
|
||||
std::vector<LightSource> gpuBuffer;
|
||||
|
||||
SignalConnection bitmapUpdateConnection;
|
||||
|
||||
Quad quad;
|
||||
Transform trans;
|
||||
|
||||
Rect *srcRect;
|
||||
SignalConnection srcRectCon;
|
||||
|
|
@ -67,6 +67,15 @@ struct LightMapPrivate{
|
|||
updateSrcRectCon();
|
||||
|
||||
prepareCon = shState->graphicsSignals.prepareDraw.Connect(*this, &LightMapPrivate::prepare);
|
||||
bitmapUpdateConnection = shState->windowSignals.resized.Connect([&](int w, int h){
|
||||
shState->rubyDispatcher().invoke([&, w, h]{
|
||||
bitmap = new Bitmap(w, h);
|
||||
bitmap->ensureNonMega();
|
||||
*srcRect = bitmap->rect();
|
||||
onSrcRectChange();
|
||||
quad.setPosRect(srcRect->toFloatRect());
|
||||
});
|
||||
});
|
||||
|
||||
bitmap->ensureNonMega();
|
||||
//bitmap->fillRect(0, 0, shState->graphics().width(), shState->graphics().height(), Vec4(0, 0, 0, 1));
|
||||
|
|
@ -79,6 +88,7 @@ struct LightMapPrivate{
|
|||
~LightMapPrivate(){
|
||||
srcRectCon.Disconnect();
|
||||
prepareCon.Disconnect();
|
||||
bitmapUpdateConnection.Disconnect();
|
||||
}
|
||||
|
||||
void onSrcRectChange(){
|
||||
|
|
@ -112,17 +122,8 @@ struct LightMapPrivate{
|
|||
return;
|
||||
|
||||
/* Compare sprite bounding box against the scene */
|
||||
|
||||
/* If sprite is zoomed/rotated, just opt out for now
|
||||
* for simplicity's sake */
|
||||
const Vec2 &scale = trans.getScale();
|
||||
if (scale.x != 1 || scale.y != 1 || trans.getRotation() != 0){
|
||||
isVisible = true;
|
||||
return;
|
||||
}
|
||||
|
||||
IntRect self;
|
||||
self.setPos(trans.getPositionI() - (trans.getOriginI() + sceneOrig));
|
||||
self.setPos(Vec2i(0, 0));
|
||||
self.w = bitmap->width();
|
||||
self.h = bitmap->height();
|
||||
|
||||
|
|
@ -249,10 +250,6 @@ void LightMap::draw(){
|
|||
}
|
||||
|
||||
void LightMap::onGeometryChange(const Scene::Geometry &geo){
|
||||
/* Offset at which the sprite will be drawn
|
||||
* relative to screen origin */
|
||||
p->trans.setGlobalOffset(geo.offset());
|
||||
|
||||
p->sceneRect.setSize(geo.rect.size());
|
||||
p->sceneOrig = geo.orig;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ protected:
|
|||
IntruList<SceneElement> elements;
|
||||
Geometry geometry;
|
||||
|
||||
SignalConnection resizeConnection;
|
||||
|
||||
friend class SceneElement;
|
||||
friend class Window;
|
||||
friend class WindowVX;
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ struct SharedStatePrivate{
|
|||
SDL_Window *sdlWindow;
|
||||
Scene *screen;
|
||||
|
||||
RubyDispatcher rubyDispatcher;
|
||||
RenderDispatcher renderDispatcher;
|
||||
|
||||
FileSystem fileSystem;
|
||||
|
||||
EventThread &eThread;
|
||||
|
|
@ -96,6 +99,8 @@ struct SharedStatePrivate{
|
|||
SharedStatePrivate(RGSSThreadData *threadData)
|
||||
: bindingData(0),
|
||||
sdlWindow(threadData->window),
|
||||
rubyDispatcher(),
|
||||
renderDispatcher(),
|
||||
fileSystem(threadData->config.allowSymlinks),
|
||||
eThread(*threadData->ethread),
|
||||
rtData(*threadData),
|
||||
|
|
@ -194,6 +199,8 @@ void SharedState::setScreen(Scene &screen){
|
|||
GSATT(void*, bindingData)
|
||||
GSATT(SDL_Window*, sdlWindow)
|
||||
GSATT(Scene*, screen)
|
||||
GSATT(RubyDispatcher&, rubyDispatcher)
|
||||
GSATT(RenderDispatcher&, renderDispatcher)
|
||||
GSATT(FileSystem&, fileSystem)
|
||||
GSATT(EventThread&, eThread)
|
||||
GSATT(RGSSThreadData&, rtData)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
#define SHAREDSTATE_H
|
||||
|
||||
#include "signals/signal.h"
|
||||
#include "signals/rubydispatcher.h"
|
||||
#include "signals/renderdispatcher.h"
|
||||
|
||||
#define shState SharedState::instance
|
||||
#define glState shState->_glState()
|
||||
|
|
@ -69,6 +71,10 @@ struct SharedState{
|
|||
WindowSignals windowSignals;
|
||||
GraphicsSignals graphicsSignals;
|
||||
|
||||
// dispatchers, they redirect signals from another thread to their own
|
||||
RubyDispatcher &rubyDispatcher() const;
|
||||
RenderDispatcher &renderDispatcher() const;
|
||||
|
||||
// other shit idk
|
||||
void *bindingData() const;
|
||||
void setBindingData(void *data);
|
||||
|
|
|
|||
21
src/signals/renderdispatcher.cpp
Normal file
21
src/signals/renderdispatcher.cpp
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#include "renderdispatcher.h"
|
||||
|
||||
void RenderDispatcher::invoke(std::function<void()> fn){
|
||||
std::lock_guard lock(mutex);
|
||||
queue.push(std::move(fn));
|
||||
}
|
||||
|
||||
void RenderDispatcher::process(){
|
||||
std::queue<std::function<void()>> local;
|
||||
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
std::swap(local, queue);
|
||||
}
|
||||
|
||||
while (!local.empty())
|
||||
{
|
||||
local.front()();
|
||||
local.pop();
|
||||
}
|
||||
}
|
||||
17
src/signals/renderdispatcher.h
Normal file
17
src/signals/renderdispatcher.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
class RenderDispatcher{
|
||||
public:
|
||||
RenderDispatcher() {};
|
||||
|
||||
void invoke(std::function<void()> fn);
|
||||
void process();
|
||||
|
||||
private:
|
||||
std::mutex mutex;
|
||||
std::queue<std::function<void()>> queue;
|
||||
};
|
||||
21
src/signals/rubydispatcher.cpp
Normal file
21
src/signals/rubydispatcher.cpp
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#include "rubydispatcher.h"
|
||||
|
||||
void RubyDispatcher::invoke(std::function<void()> fn){
|
||||
std::lock_guard lock(mutex);
|
||||
queue.push(std::move(fn));
|
||||
}
|
||||
|
||||
void RubyDispatcher::process(){
|
||||
std::queue<std::function<void()>> local;
|
||||
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
std::swap(local, queue);
|
||||
}
|
||||
|
||||
while (!local.empty())
|
||||
{
|
||||
local.front()();
|
||||
local.pop();
|
||||
}
|
||||
}
|
||||
17
src/signals/rubydispatcher.h
Normal file
17
src/signals/rubydispatcher.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
class RubyDispatcher{
|
||||
public:
|
||||
RubyDispatcher() {};
|
||||
|
||||
void invoke(std::function<void()> fn);
|
||||
void process();
|
||||
|
||||
private:
|
||||
std::mutex mutex;
|
||||
std::queue<std::function<void()>> queue;
|
||||
};
|
||||
|
|
@ -40,6 +40,7 @@
|
|||
#include "tileatlas.h"
|
||||
#include "tilemap-common.h"
|
||||
#include "sunshine.h"
|
||||
#include "signals/rubydispatcher.h"
|
||||
|
||||
#include <boost/chrono.hpp>
|
||||
|
||||
|
|
@ -48,6 +49,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include <SDL3/SDL_surface.h>
|
||||
#include <SDL3/SDL_thread.h>
|
||||
|
||||
extern const StaticRect autotileRects[];
|
||||
|
||||
|
|
@ -250,6 +252,7 @@ struct TilemapPrivate {
|
|||
} atlas;
|
||||
|
||||
int viewpW, viewpH;
|
||||
SignalConnection viewpUpdateConnection;
|
||||
size_t zlayersMax;
|
||||
|
||||
/* Map viewport position */
|
||||
|
|
@ -328,8 +331,8 @@ struct TilemapPrivate {
|
|||
mapViewportDirty(false),
|
||||
zOrderDirty(false),
|
||||
tilemapReady(false),
|
||||
viewpW(shState->graphics().width() / 32 + 1),
|
||||
viewpH(shState->graphics().height() / 32 + 2),
|
||||
viewpW(shState->graphics().width() / 31 + 2),
|
||||
viewpH(shState->graphics().height() / 31 + 2),
|
||||
zlayersMax(viewpH + 5)
|
||||
{
|
||||
zlayerVert.resize(zlayersMax);
|
||||
|
|
@ -360,6 +363,34 @@ struct TilemapPrivate {
|
|||
elem.zlayers[i] = new ZLayer(this, viewport);
|
||||
|
||||
prepareCon = shState->graphicsSignals.prepareDraw.Connect(*this, &TilemapPrivate::prepare);
|
||||
viewpUpdateConnection = shState->windowSignals.resized.Connect([&](int w, int h){
|
||||
shState->rubyDispatcher().invoke([&, w, h]{
|
||||
if (this->viewport->isDisposed()){
|
||||
Debug() << "Warning: resize updating of disposed tilemap, disconnecting";
|
||||
this->viewpUpdateConnection.Disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
int oldZLayersCount = zlayersMax;
|
||||
viewpW = w / 31 + 2;
|
||||
viewpH = h / 31 + 2;
|
||||
zlayersMax = viewpH + 5;
|
||||
zlayerVert.resize(zlayersMax);
|
||||
zlayerBases.resize(zlayersMax + 1);
|
||||
if (zlayersMax > oldZLayersCount){
|
||||
elem.zlayers.resize(zlayersMax);
|
||||
for (size_t i = oldZLayersCount; i < zlayersMax; ++i)
|
||||
if (elem.zlayers[i] == nullptr)
|
||||
elem.zlayers[i] = new ZLayer(this, this->viewport);
|
||||
}
|
||||
else{
|
||||
for (size_t i = zlayersMax; i < oldZLayersCount; ++i)
|
||||
if (elem.zlayers[i] != nullptr)
|
||||
delete elem.zlayers[i];
|
||||
elem.zlayers.resize(zlayersMax);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
updateFlashMapViewport();
|
||||
}
|
||||
|
|
@ -377,6 +408,7 @@ struct TilemapPrivate {
|
|||
VBO::del(tiles.vbo);
|
||||
|
||||
/* Disconnect signal handlers */
|
||||
viewpUpdateConnection.Disconnect();
|
||||
tilesetCon.Disconnect();
|
||||
for (int i = 0; i < autotileCount; ++i){
|
||||
autotilesCon[i].Disconnect();
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ private:
|
|||
void composite();
|
||||
void draw();
|
||||
void onGeometryChange(const Geometry &);
|
||||
bool isEffectiveViewport(Rect *&, Color *&, Tone *&) const;
|
||||
|
||||
void releaseResources();
|
||||
const char *klassName() const { return "viewport"; }
|
||||
|
|
|
|||
Loading…
Reference in a new issue