diff --git a/RetroFE/Source/Graphics/Component/Component.cpp b/RetroFE/Source/Graphics/Component/Component.cpp index cf8c5a3..6b68d4c 100644 --- a/RetroFE/Source/Graphics/Component/Component.cpp +++ b/RetroFE/Source/Graphics/Component/Component.cpp @@ -175,7 +175,7 @@ void Component::draw() static_cast(baseViewInfo.BackgroundGreen*255), static_cast(baseViewInfo.BackgroundBlue*255)); - SDL::renderCopy(backgroundTexture_, baseViewInfo.BackgroundAlpha, NULL, &rect, baseViewInfo.Angle, baseViewInfo.Reflection, baseViewInfo.ReflectionDistance, baseViewInfo.ReflectionScale, baseViewInfo.ReflectionAlpha); + SDL::renderCopy(backgroundTexture_, baseViewInfo.BackgroundAlpha, NULL, &rect, baseViewInfo); } } diff --git a/RetroFE/Source/Graphics/Component/Image.cpp b/RetroFE/Source/Graphics/Component/Image.cpp index 21c32d0..b077e90 100644 --- a/RetroFE/Source/Graphics/Component/Image.cpp +++ b/RetroFE/Source/Graphics/Component/Image.cpp @@ -89,6 +89,6 @@ void Image::draw() rect.h = static_cast(baseViewInfo.ScaledHeight()); rect.w = static_cast(baseViewInfo.ScaledWidth()); - SDL::renderCopy(texture_, baseViewInfo.Alpha, NULL, &rect, baseViewInfo.Angle, baseViewInfo.Reflection, baseViewInfo.ReflectionDistance, baseViewInfo.ReflectionScale, baseViewInfo.ReflectionAlpha); + SDL::renderCopy(texture_, baseViewInfo.Alpha, NULL, &rect, baseViewInfo); } } diff --git a/RetroFE/Source/Graphics/Component/ScrollingText.cpp b/RetroFE/Source/Graphics/Component/ScrollingText.cpp index 8c6d747..9959837 100644 --- a/RetroFE/Source/Graphics/Component/ScrollingText.cpp +++ b/RetroFE/Source/Graphics/Component/ScrollingText.cpp @@ -360,7 +360,7 @@ void ScrollingText::draw( ) } if (rect.w > 0) { - SDL::renderCopy(t, baseViewInfo.Alpha, &charRect, &rect, baseViewInfo.Angle, baseViewInfo.Reflection, baseViewInfo.ReflectionDistance, baseViewInfo.ReflectionScale, baseViewInfo.ReflectionAlpha); + SDL::renderCopy(t, baseViewInfo.Alpha, &charRect, &rect, baseViewInfo); } rect.x += rect.w; } @@ -546,7 +546,7 @@ void ScrollingText::draw( ) } if (rect.h > 0) { - SDL::renderCopy(t, baseViewInfo.Alpha, &charRect, &rect, baseViewInfo.Angle, baseViewInfo.Reflection, baseViewInfo.ReflectionDistance, baseViewInfo.ReflectionScale, baseViewInfo.ReflectionAlpha); + SDL::renderCopy(t, baseViewInfo.Alpha, &charRect, &rect, baseViewInfo); } } rect.x += static_cast( glyph.advance * scale * scaleX_ ); diff --git a/RetroFE/Source/Graphics/Component/Text.cpp b/RetroFE/Source/Graphics/Component/Text.cpp index e869d53..a18f09a 100644 --- a/RetroFE/Source/Graphics/Component/Text.cpp +++ b/RetroFE/Source/Graphics/Component/Text.cpp @@ -142,7 +142,7 @@ void Text::draw() } - SDL::renderCopy(t, baseViewInfo.Alpha, &charRect, &rect, baseViewInfo.Angle, baseViewInfo.Reflection, baseViewInfo.ReflectionDistance, baseViewInfo.ReflectionScale, baseViewInfo.ReflectionAlpha); + SDL::renderCopy(t, baseViewInfo.Alpha, &charRect, &rect, baseViewInfo); rect.x += static_cast(glyph.advance * scale); diff --git a/RetroFE/Source/Graphics/Component/VideoComponent.cpp b/RetroFE/Source/Graphics/Component/VideoComponent.cpp index fbb3bd8..1e5bfa9 100644 --- a/RetroFE/Source/Graphics/Component/VideoComponent.cpp +++ b/RetroFE/Source/Graphics/Component/VideoComponent.cpp @@ -105,7 +105,7 @@ void VideoComponent::draw() if(texture) { - SDL::renderCopy(texture, baseViewInfo.Alpha, NULL, &rect, static_cast(baseViewInfo.Angle), baseViewInfo.Reflection, baseViewInfo.ReflectionDistance, baseViewInfo.ReflectionScale, baseViewInfo.ReflectionAlpha); + SDL::renderCopy(texture, baseViewInfo.Alpha, NULL, &rect, baseViewInfo); } } diff --git a/RetroFE/Source/Graphics/PageBuilder.cpp b/RetroFE/Source/Graphics/PageBuilder.cpp index c0b5fe8..c10158c 100644 --- a/RetroFE/Source/Graphics/PageBuilder.cpp +++ b/RetroFE/Source/Graphics/PageBuilder.cpp @@ -1011,6 +1011,10 @@ void PageBuilder::buildViewInfo(xml_node<> *componentXml, ViewInfo &info, xml_no xml_attribute<> *reflectionDistance = findAttribute(componentXml, "reflectionDistance", defaultXml); xml_attribute<> *reflectionScale = findAttribute(componentXml, "reflectionScale", defaultXml); xml_attribute<> *reflectionAlpha = findAttribute(componentXml, "reflectionAlpha", defaultXml); + xml_attribute<> *containerX = findAttribute(componentXml, "containerX", defaultXml); + xml_attribute<> *containerY = findAttribute(componentXml, "containerY", defaultXml); + xml_attribute<> *containerWidth = findAttribute(componentXml, "containerWidth", defaultXml); + xml_attribute<> *containerHeight = findAttribute(componentXml, "containerHeight", defaultXml); info.X = getHorizontalAlignment(x, 0); info.Y = getVerticalAlignment(y, 0); @@ -1040,13 +1044,17 @@ void PageBuilder::buildViewInfo(xml_node<> *componentXml, ViewInfo &info, xml_no info.MinWidth = getHorizontalAlignment(minWidth, 0); info.MaxHeight = getVerticalAlignment(maxHeight, FLT_MAX); info.MaxWidth = getVerticalAlignment(maxWidth, FLT_MAX); - info.Alpha = alpha ? Utils::convertFloat(alpha->value()) : 1.f; - info.Angle = angle ? Utils::convertFloat(angle->value()) : 0.f; - info.Layer = layer ? Utils::convertInt(layer->value()) : 0; - info.Reflection = reflection ? reflection->value() : ""; - info.ReflectionDistance = reflectionDistance ? Utils::convertInt(reflectionDistance->value()) : 0; - info.ReflectionScale = reflectionScale ? Utils::convertFloat(reflectionScale->value()) : 0.25f; - info.ReflectionAlpha = reflectionAlpha ? Utils::convertFloat(reflectionAlpha->value()) : 1.f; + info.Alpha = alpha ? Utils::convertFloat(alpha->value()) : 1.f; + info.Angle = angle ? Utils::convertFloat(angle->value()) : 0.f; + info.Layer = layer ? Utils::convertInt(layer->value()) : 0; + info.Reflection = reflection ? reflection->value() : ""; + info.ReflectionDistance = reflectionDistance ? Utils::convertInt(reflectionDistance->value()) : 0; + info.ReflectionScale = reflectionScale ? Utils::convertFloat(reflectionScale->value()) : 0.25f; + info.ReflectionAlpha = reflectionAlpha ? Utils::convertFloat(reflectionAlpha->value()) : 1.f; + info.ContainerX = containerX ? Utils::convertFloat(containerX->value()) * scaleX_ : 0.f; + info.ContainerY = containerY ? Utils::convertFloat(containerY->value()) * scaleY_ : 0.f; + info.ContainerWidth = containerWidth ? Utils::convertFloat(containerWidth->value()) * scaleX_ : -1.f; + info.ContainerHeight = containerHeight ? Utils::convertFloat(containerHeight->value()) * scaleY_ : -1.f; if(fontColor) { diff --git a/RetroFE/Source/Graphics/ViewInfo.cpp b/RetroFE/Source/Graphics/ViewInfo.cpp index f775b6c..bd83413 100644 --- a/RetroFE/Source/Graphics/ViewInfo.cpp +++ b/RetroFE/Source/Graphics/ViewInfo.cpp @@ -47,6 +47,10 @@ ViewInfo::ViewInfo() , ReflectionDistance(0) , ReflectionScale(.25) , ReflectionAlpha(1) + , ContainerX(0) + , ContainerY(0) + , ContainerWidth(-1) + , ContainerHeight(-1) { } diff --git a/RetroFE/Source/Graphics/ViewInfo.h b/RetroFE/Source/Graphics/ViewInfo.h index 91032f7..d59fa93 100644 --- a/RetroFE/Source/Graphics/ViewInfo.h +++ b/RetroFE/Source/Graphics/ViewInfo.h @@ -69,6 +69,10 @@ public: unsigned int ReflectionDistance; float ReflectionScale; float ReflectionAlpha; + float ContainerX; + float ContainerY; + float ContainerWidth; + float ContainerHeight; private: float AbsoluteHeight() const; diff --git a/RetroFE/Source/SDL.cpp b/RetroFE/Source/SDL.cpp index d056992..eeefe60 100644 --- a/RetroFE/Source/SDL.cpp +++ b/RetroFE/Source/SDL.cpp @@ -255,8 +255,12 @@ SDL_Window* SDL::getWindow() return window_; } -bool SDL::renderCopy(SDL_Texture *texture, float alpha, SDL_Rect *src, SDL_Rect *dest, double angle, std::string reflection, unsigned int reflectionDistance, double reflectionScale, float reflectionAlpha) +bool SDL::renderCopy(SDL_Texture *texture, float alpha, SDL_Rect *src, SDL_Rect *dest, ViewInfo &viewInfo) { + + SDL_Rect srcRect; + SDL_Rect dstRect; + SDL_Rect rotateRect; rotateRect.w = dest->w; rotateRect.h = dest->h; @@ -272,39 +276,97 @@ bool SDL::renderCopy(SDL_Texture *texture, float alpha, SDL_Rect *src, SDL_Rect rotateRect.y = dest->y; } + // Create the base fields to check against the container. + if (src) + { + srcRect.x = src->x; + srcRect.y = src->y; + srcRect.w = src->w; + srcRect.h = src->h; + } + else + { + srcRect.x = 0; + srcRect.y = 0; + int w = 0; + int h = 0; + SDL_QueryTexture(texture, NULL, NULL, &w, &h); + srcRect.w = w; + srcRect.h = h; + } + dstRect.x = rotateRect.x; + dstRect.y = rotateRect.y; + dstRect.w = rotateRect.w; + dstRect.h = rotateRect.h; + + // If a container has been defined, limit the display to the container boundaries. + if (viewInfo.ContainerWidth > 0 && viewInfo.ContainerHeight > 0 && + rotateRect.w > 0 && rotateRect.h > 0) + { + + // Correct if the image falls to the left of the container + if (dstRect.x < viewInfo.ContainerX) + { + dstRect.x = static_cast(viewInfo.ContainerX); + srcRect.x = srcRect.x + srcRect.w * (dstRect.x - rotateRect.x) / rotateRect.w; + } + + // Correct if the image falls to the right of the container + if (rotateRect.x + rotateRect.w > viewInfo.ContainerX + viewInfo.ContainerWidth) + { + dstRect.w = static_cast(viewInfo.ContainerX + viewInfo.ContainerWidth) - dstRect.x; + srcRect.w = srcRect.w * dstRect.w / rotateRect.w; + } + + // Correct if the image falls to the top of the container + if (dstRect.y < viewInfo.ContainerY) + { + dstRect.y = static_cast(viewInfo.ContainerY); + srcRect.y = srcRect.y + srcRect.h * (dstRect.y - rotateRect.y) / rotateRect.h; + } + + // Correct if the image falls to the bottom of the container + if (rotateRect.y + rotateRect.h > viewInfo.ContainerY + viewInfo.ContainerHeight) + { + dstRect.h = static_cast(viewInfo.ContainerY + viewInfo.ContainerHeight) - dstRect.y; + srcRect.h = srcRect.h * dstRect.h / rotateRect.h; + } + + } + SDL_SetTextureAlphaMod(texture, static_cast(alpha * 255)); - SDL_RenderCopyEx(getRenderer(), texture, src, &rotateRect, angle, NULL, SDL_FLIP_NONE); + SDL_RenderCopyEx(getRenderer(), texture, &srcRect, &dstRect, viewInfo.Angle, NULL, SDL_FLIP_NONE); - if (reflection == "top") + if (viewInfo.Reflection == "top") { - rotateRect.h = static_cast(static_cast(rotateRect.h) * reflectionScale); - rotateRect.y = rotateRect.y - rotateRect.h - reflectionDistance; - SDL_SetTextureAlphaMod(texture, static_cast(reflectionAlpha * alpha * 255)); - SDL_RenderCopyEx(getRenderer(), texture, src, &rotateRect, angle, NULL, SDL_FLIP_VERTICAL); + rotateRect.h = static_cast(static_cast(rotateRect.h) * viewInfo.ReflectionScale); + rotateRect.y = rotateRect.y - rotateRect.h - viewInfo.ReflectionDistance; + SDL_SetTextureAlphaMod(texture, static_cast(viewInfo.ReflectionAlpha * alpha * 255)); + SDL_RenderCopyEx(getRenderer(), texture, src, &rotateRect, viewInfo.Angle, NULL, SDL_FLIP_VERTICAL); } - if (reflection == "bottom") + if (viewInfo.Reflection == "bottom") { - rotateRect.y = rotateRect.y + rotateRect.h + reflectionDistance; - rotateRect.h = static_cast(static_cast(rotateRect.h) * reflectionScale); - SDL_SetTextureAlphaMod(texture, static_cast(reflectionAlpha * alpha * 255)); - SDL_RenderCopyEx(getRenderer(), texture, src, &rotateRect, angle, NULL, SDL_FLIP_VERTICAL); + rotateRect.y = rotateRect.y + rotateRect.h + viewInfo.ReflectionDistance; + rotateRect.h = static_cast(static_cast(rotateRect.h) * viewInfo.ReflectionScale); + SDL_SetTextureAlphaMod(texture, static_cast(viewInfo.ReflectionAlpha * alpha * 255)); + SDL_RenderCopyEx(getRenderer(), texture, src, &rotateRect, viewInfo.Angle, NULL, SDL_FLIP_VERTICAL); } - if (reflection == "left") + if (viewInfo.Reflection == "left") { - rotateRect.w = static_cast(static_cast(rotateRect.w) * reflectionScale); - rotateRect.x = rotateRect.x - rotateRect.w - reflectionDistance; - SDL_SetTextureAlphaMod(texture, static_cast(reflectionAlpha * alpha * 255)); - SDL_RenderCopyEx(getRenderer(), texture, src, &rotateRect, angle, NULL, SDL_FLIP_HORIZONTAL); + rotateRect.w = static_cast(static_cast(rotateRect.w) * viewInfo.ReflectionScale); + rotateRect.x = rotateRect.x - rotateRect.w - viewInfo.ReflectionDistance; + SDL_SetTextureAlphaMod(texture, static_cast(viewInfo.ReflectionAlpha * alpha * 255)); + SDL_RenderCopyEx(getRenderer(), texture, src, &rotateRect, viewInfo.Angle, NULL, SDL_FLIP_HORIZONTAL); } - if (reflection == "right") + if (viewInfo.Reflection == "right") { - rotateRect.x = rotateRect.x + rotateRect.w + reflectionDistance; - rotateRect.w = static_cast(static_cast(rotateRect.w) * reflectionScale); - SDL_SetTextureAlphaMod(texture, static_cast(reflectionAlpha * alpha * 255)); - SDL_RenderCopyEx(getRenderer(), texture, src, &rotateRect, angle, NULL, SDL_FLIP_HORIZONTAL); + rotateRect.x = rotateRect.x + rotateRect.w + viewInfo.ReflectionDistance; + rotateRect.w = static_cast(static_cast(rotateRect.w) * viewInfo.ReflectionScale); + SDL_SetTextureAlphaMod(texture, static_cast(viewInfo.ReflectionAlpha * alpha * 255)); + SDL_RenderCopyEx(getRenderer(), texture, src, &rotateRect, viewInfo.Angle, NULL, SDL_FLIP_HORIZONTAL); } return true; diff --git a/RetroFE/Source/SDL.h b/RetroFE/Source/SDL.h index 92449cc..87b20c6 100644 --- a/RetroFE/Source/SDL.h +++ b/RetroFE/Source/SDL.h @@ -16,6 +16,7 @@ #pragma once #include #include +#include "Graphics/ViewInfo.h" // todo: this wrapper could be cleaned up class Configuration; @@ -28,7 +29,7 @@ public: static SDL_Renderer *getRenderer(); static SDL_mutex *getMutex(); static SDL_Window *getWindow(); - static bool renderCopy(SDL_Texture *texture, float alpha, SDL_Rect *src, SDL_Rect *dest, double angle, std::string reflection = "", unsigned int reflectionDistance = 0, double reflectionScale = 0.25, float reflectionAlpha = 0.0f); + static bool renderCopy(SDL_Texture *texture, float alpha, SDL_Rect *src, SDL_Rect *dest, ViewInfo &viewInfo); static int getWindowWidth() { return windowWidth_;