Advertisement
Ardente

Core Guidelines Test

Sep 2nd, 2020
221
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.27 KB | None | 0 0
  1. //
  2. //  textureWrapper.hpp
  3. //  ProjectViolet
  4. //
  5. //  Created by Keegan Bilodeau on 7/27/20.
  6. //  Copyright © 2020 Keegan Bilodeau. All rights reserved.
  7. //
  8.  
  9. #ifndef textureWrapper_hpp
  10. #define textureWrapper_hpp
  11.  
  12. #include <memory>
  13. #include <SDL.h>
  14. #include <SDL_ttf.h>
  15. #include <stdio.h>
  16. #include <string>
  17. #include <variant>
  18.  
  19. struct RenderPoint
  20. {
  21.     int x, y;
  22.     bool isFixed = false;
  23.     double angle = 0.0f;
  24. };
  25.  
  26. struct ImageInfo
  27. {
  28.     std::string path;
  29.    
  30.     bool isColorKeyed;
  31.     double xScale, yScale;
  32. };
  33.  
  34. struct TextInfo
  35. {
  36.     std::string text;
  37.     std::shared_ptr<TTF_Font> &textFont;
  38.     SDL_Color color;
  39. };
  40.  
  41. struct RectangleInfo
  42. {
  43.     SDL_Rect rectangle;
  44.     SDL_Color color;
  45. };
  46.  
  47. typedef std::variant<ImageInfo, TextInfo, RectangleInfo> TextureInfo;
  48.  
  49. class TextureWrapper
  50. {
  51. public:
  52.     // Initializes the wrapper's fields with default values
  53.     TextureWrapper();
  54.    
  55.     // Calls for the attached texture to be freed
  56.     ~TextureWrapper();
  57.    
  58.     // Creates a texture from a file and attaches it to the wrapper
  59.     bool initFromFile(TextureInfo textureInfo, std::shared_ptr<SDL_Renderer> &renderer, SDL_Color colorKey = {0xFF, 0x00, 0xDC});
  60.    
  61.     // Creates a texture from a string and attaches it to the wrapper
  62.     bool initFromString(TextureInfo textureInfo, std::shared_ptr<SDL_Renderer> &renderer);
  63.    
  64.     // Creates a texture from a SDL rectangle and attaches it to the wrapper
  65.     bool initFromRectangle(TextureInfo textureInfo, std::shared_ptr<SDL_Renderer> &renderer);
  66.    
  67.     // Uses the SDL renderer to render the texture to the screen
  68.     void render(RenderPoint renderPoint, SDL_Rect camera = {0, 0, 0, 0}, std::unique_ptr<SDL_Rect> clipRect = nullptr, std::unique_ptr<SDL_Point> center = nullptr, SDL_RendererFlip flip = SDL_FLIP_NONE);
  69.    
  70.     // Allows one to enable the alpha channel
  71.     void setBlendMode(SDL_BlendMode blendMode);
  72.    
  73.     // Modifies the texture's color values based off the passed color
  74.     void modifyTextureColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a);
  75.    
  76.     // Changes the texture's scale factor
  77.     void setTextureScale(double xScaleFactor, double yScaleFactor);
  78.    
  79.     // Returns the texture's orignal width (unscaled)
  80.     int getUnscaledWidth() const;
  81.    
  82.     // Returns the texture's original height (unscaled)
  83.     int getUnscaledHeight() const;
  84.    
  85.     // Returns the texture's scaled width
  86.     int getScaledWidth() const;
  87.    
  88.     // Returns the texture's scaled height
  89.     int getScaledHeight() const;
  90.    
  91. private:
  92.     // Frees the attached texture to allow new textures to be attached
  93.     void freeTexture();
  94.    
  95.     // Pointer to the renderer so that it doesn't have to be repeatedly passed to the texture
  96.     std::shared_ptr<SDL_Renderer> mRenderer;
  97.    
  98.     // The SDL texure being wrapped
  99.     std::unique_ptr<SDL_Texture, decltype(&SDL_DestroyTexture)> mWrappedTexture;
  100.    
  101.     // Texture's dimensions, has to be stored because they're lost when the SDL surface is converted to a texture
  102.     int mWidth, mHeight;
  103.    
  104.     // Texture's x and y scale factor
  105.     double mXScaleFactor, mYScaleFactor;
  106. };
  107.  
  108. #endif /* textureWrapper_hpp */
  109.  
  110. //
  111. //  textureWrapper.cpp
  112. //  ProjectViolet
  113. //
  114. //  Created by Keegan Bilodeau on 7/27/20.
  115. //  Copyright © 2020 Keegan Bilodeau. All rights reserved.
  116. //
  117.  
  118. #include "debug.hpp"
  119. #include "textureWrapper.hpp"
  120.  
  121. #include <SDL_image.h>
  122.  
  123. using namespace Debug;
  124.  
  125. TextureWrapper::TextureWrapper() : mRenderer(nullptr), mWrappedTexture(nullptr, nullptr), mWidth(0), mHeight(0), mXScaleFactor(0.0f), mYScaleFactor(0.0f)
  126. {
  127.    
  128. }
  129.  
  130. TextureWrapper::~TextureWrapper()
  131. {
  132.     freeTexture();
  133. }
  134.  
  135. void TextureWrapper::freeTexture()
  136. {
  137.     mRenderer = nullptr;
  138.     mWrappedTexture = nullptr;
  139.    
  140.     mWidth = 0;
  141.     mHeight = 0;
  142.    
  143.     mXScaleFactor = 0.0f;
  144.     mYScaleFactor = 0.0f;
  145. }
  146.  
  147. bool TextureWrapper::initFromFile(TextureInfo textureInfo, std::shared_ptr<SDL_Renderer> &renderer, SDL_Color colorKey)
  148. {
  149.     // Loading success flag
  150.     bool success = false;
  151.    
  152.     assert(textureInfo.index() == 0);
  153.     ImageInfo& imageInfo = std::get<ImageInfo>(textureInfo);
  154.    
  155.     // Releases any attached textures
  156.     if (mWrappedTexture != nullptr)
  157.         freeTexture();
  158.    
  159.     // Pass the application's renderer to the texture
  160.     mRenderer = renderer;
  161.    
  162.     // Loads the image as a SDL surface
  163.     std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)> loadedSurface(IMG_Load(imageInfo.path.c_str()), &SDL_FreeSurface);
  164.    
  165.     // Check if it loads successfully
  166.     if (!loadedSurface)
  167.     {
  168.         logMessage("Failed to load image from " + imageInfo.path + "!", SevereError, __LINE__, __FILE_NAME__);
  169.         logMessage(IMG_GetError(), SDLImageError, __LINE__, __FILE_NAME__);
  170.        
  171.         success = false;
  172.     }
  173.     else
  174.     {
  175.         // Color keys the image if enabled
  176.         if (imageInfo.isColorKeyed)
  177.             SDL_SetColorKey(loadedSurface.get(), SDL_TRUE, SDL_MapRGB(loadedSurface->format, colorKey.r, colorKey.g, colorKey.b));
  178.        
  179.         // Attaches the
  180.         mWrappedTexture = std::unique_ptr<SDL_Texture, decltype(&SDL_DestroyTexture)>(SDL_CreateTextureFromSurface(mRenderer.get(), loadedSurface.get()), &SDL_DestroyTexture);
  181.        
  182.         // Check if its loaded successfully
  183.         if (!mWrappedTexture)
  184.         {
  185.             logMessage("Failed to convert " + imageInfo.path + " into a texture!", SevereError, __LINE__, __FILE_NAME__);
  186.             logMessage(SDL_GetError(), SDLError, __LINE__, __FILE_NAME__);
  187.            
  188.             success = false;
  189.         }
  190.         else
  191.         {
  192.             // Preserve the texture's dimensions
  193.             mWidth = loadedSurface->w;
  194.             mHeight = loadedSurface->h;
  195.            
  196.             // Store the texture scale resizing the render quad in TextureWrapper::render(...)
  197.             mXScaleFactor = imageInfo.xScale;
  198.             mYScaleFactor = imageInfo.yScale;
  199.         }
  200.     }
  201.    
  202.     return success;
  203. }
  204.  
  205. bool TextureWrapper::initFromString(TextureInfo textureInfo, std::shared_ptr<SDL_Renderer> &renderer)
  206. {
  207.     // Loading success flag
  208.     bool success = true;
  209.    
  210.     assert(textureInfo.index() == 1);
  211.     TextInfo &textInfo = std::get<TextInfo>(textureInfo);
  212.    
  213.     // Release any texture previously attached to the wrapper
  214.     if (!mWrappedTexture)
  215.         freeTexture();
  216.    
  217.     // Attach the renderer to the texture
  218.     mRenderer = renderer;
  219.    
  220.     // Create a surface containing text using TTF
  221.     std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)> loadedSurface(TTF_RenderText_Blended_Wrapped(textInfo.textFont.get(), textInfo.text.c_str(), textInfo.color, 300 * 1.776), &SDL_FreeSurface);
  222.    
  223.     // Check if it was loaded successfully
  224.     if (!loadedSurface)
  225.     {
  226.         logMessage("Unable to render text to a surface!", SevereError, __LINE__, __FILE_NAME__);
  227.         logMessage(TTF_GetError(), SDLFontError, __LINE__, __FILE_NAME__);
  228.        
  229.         success = false;
  230.     }
  231.     else
  232.     {
  233.         // Convert the surface to a texture
  234.         mWrappedTexture = std::unique_ptr<SDL_Texture, decltype(&SDL_DestroyTexture)>(SDL_CreateTextureFromSurface(mRenderer.get(), loadedSurface.get()), &SDL_DestroyTexture);
  235.        
  236.         // Check if the conversion was successful
  237.         if (!mWrappedTexture)
  238.         {
  239.             logMessage("Unable to convert the rendered text to a texture!", SevereError, __LINE__, __FILE_NAME__);
  240.             logMessage(SDL_GetError(), SDLError, __LINE__, __FILE_NAME__);
  241.            
  242.             success = false;
  243.         }
  244.         else
  245.         {
  246.             mWidth = loadedSurface->w;
  247.             mHeight = loadedSurface->h;
  248.            
  249.             mXScaleFactor = 1;
  250.             mYScaleFactor = 1;
  251.         }
  252.     }
  253.    
  254.     return success;
  255. }
  256.  
  257. bool TextureWrapper::initFromRectangle(TextureInfo textureInfo, std::shared_ptr<SDL_Renderer> &renderer)
  258. {
  259.     // Loading success flag
  260.     bool success = true;
  261.    
  262.     assert(textureInfo.index() == 2);
  263.     RectangleInfo &rectInfo = std::get<RectangleInfo>(textureInfo);
  264.    
  265.     // Release any previously attached textures
  266.     if (!mWrappedTexture)
  267.         freeTexture();
  268.    
  269.     // Attach the renderer to the texture
  270.     mRenderer = renderer;
  271.    
  272.     // Create a targetable texture
  273.     mWrappedTexture = std::unique_ptr<SDL_Texture, decltype(&SDL_DestroyTexture)>(SDL_CreateTexture(mRenderer.get(), SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, rectInfo.rectangle.w, rectInfo.rectangle.h), &SDL_DestroyTexture);
  274.    
  275.     // Check if it was created successfully
  276.     if (!mWrappedTexture)
  277.     {
  278.         logMessage("Failed to create a targetable texture!", SevereError, __LINE__, __FILE_NAME__);
  279.         logMessage(SDL_GetError(), SDLError, __LINE__, __FILE_NAME__);
  280.        
  281.         success = false;
  282.     }
  283.     else
  284.     {
  285.         // Set the dimensions
  286.         mWidth = rectInfo.rectangle.w;
  287.         mHeight = rectInfo.rectangle.h;
  288.        
  289.         // Set the scale
  290.         mXScaleFactor = 1;
  291.         mYScaleFactor = 1;
  292.        
  293.         // Make the texture the color of the rectangle:
  294.         // 1) Target the texture
  295.         SDL_SetRenderTarget(mRenderer.get(), mWrappedTexture.get());
  296.         // 2) Set the render draw color to the color of the rectanlge
  297.         SDL_SetRenderDrawColor(mRenderer.get(), rectInfo.color.r, rectInfo.color.g, rectInfo.color.b, rectInfo.color.a);
  298.         // 3) Paint the screen by "clearing" it
  299.         SDL_RenderClear(mRenderer.get());
  300.         // 4) Reset the draw color
  301.         SDL_SetRenderDrawColor(mRenderer.get(), 0xFF, 0xFF, 0xFF, 0xFF);
  302.         // 5) Reset the texture target
  303.         SDL_SetRenderTarget(mRenderer.get(), nullptr);
  304.     }
  305.    
  306.     return success;
  307. }
  308.  
  309. void TextureWrapper::render(RenderPoint renderPoint, SDL_Rect camera, std::unique_ptr<SDL_Rect> clipRect, std::unique_ptr<SDL_Point> center, SDL_RendererFlip flip)
  310. {
  311.     SDL_Rect renderQuad {renderPoint.x, renderPoint.y, mWidth, mHeight};
  312.    
  313.     // Adjust the texture based off a camera variable if true
  314.     if (!renderPoint.isFixed)
  315.     {
  316.         renderQuad.x -= camera.x;
  317.         renderQuad.y -= camera.y;
  318.     }
  319.    
  320.     // Applies the clip dimensions if a clip rectangle is passed
  321.     if (clipRect)
  322.     {
  323.         renderQuad.w = clipRect->w;
  324.         renderQuad.h = clipRect->h;
  325.     }
  326.    
  327.     renderQuad.x *= mXScaleFactor;
  328.     renderQuad.y *= mYScaleFactor;
  329.    
  330.     SDL_RenderCopyEx(mRenderer.get(), mWrappedTexture.get(), clipRect.get(), &renderQuad, renderPoint.angle, center.get(), flip);
  331. }
  332.  
  333. void TextureWrapper::setBlendMode(SDL_BlendMode blendMode)
  334. {
  335.     SDL_SetTextureBlendMode(mWrappedTexture.get(), blendMode);
  336. }
  337.  
  338. void TextureWrapper::modifyTextureColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  339. {
  340.     SDL_SetTextureColorMod(mWrappedTexture.get(), r, g, b);
  341.     SDL_SetTextureAlphaMod(mWrappedTexture.get(), a);
  342. }
  343.  
  344. void TextureWrapper::setTextureScale(double xScaleFactor, double yScaleFactor)
  345. {
  346.     mXScaleFactor = xScaleFactor;
  347.     mYScaleFactor = yScaleFactor;
  348. }
  349.  
  350. int TextureWrapper::getUnscaledWidth() const
  351. {
  352.     return mWidth;
  353. }
  354.  
  355. int TextureWrapper::getUnscaledHeight() const
  356. {
  357.     return mHeight;
  358. }
  359.  
  360. int TextureWrapper::getScaledWidth() const
  361. {
  362.     return mWidth * mXScaleFactor;
  363. }
  364.  
  365. int TextureWrapper::getScaledHeight() const
  366. {
  367.     return mHeight * mYScaleFactor;
  368. }
  369.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement