DecoratorTiledHorizontal.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. #include "DecoratorTiledHorizontal.h"
  2. #include "../../Include/RmlUi/Core/Element.h"
  3. #include "../../Include/RmlUi/Core/Geometry.h"
  4. #include "../../Include/RmlUi/Core/RenderManager.h"
  5. #include "../../Include/RmlUi/Core/Texture.h"
  6. namespace Rml {
  7. struct DecoratorTiledHorizontalData {
  8. DecoratorTiledHorizontalData(int num_textures) : num_textures(num_textures) { geometry = new Geometry[num_textures]; }
  9. ~DecoratorTiledHorizontalData() { delete[] geometry; }
  10. const int num_textures;
  11. Geometry* geometry;
  12. };
  13. DecoratorTiledHorizontal::DecoratorTiledHorizontal() {}
  14. DecoratorTiledHorizontal::~DecoratorTiledHorizontal() {}
  15. bool DecoratorTiledHorizontal::Initialise(const Tile* _tiles, const Texture* _textures)
  16. {
  17. // Load the textures.
  18. for (int i = 0; i < 3; i++)
  19. {
  20. tiles[i] = _tiles[i];
  21. tiles[i].texture_index = AddTexture(_textures[i]);
  22. }
  23. // If only one side of the decorator has been configured, then mirror the texture for the other side.
  24. if (tiles[LEFT].texture_index == -1 && tiles[RIGHT].texture_index > -1)
  25. {
  26. tiles[LEFT] = tiles[RIGHT];
  27. tiles[LEFT].orientation = FLIP_HORIZONTAL;
  28. }
  29. else if (tiles[RIGHT].texture_index == -1 && tiles[LEFT].texture_index > -1)
  30. {
  31. tiles[RIGHT] = tiles[LEFT];
  32. tiles[RIGHT].orientation = FLIP_HORIZONTAL;
  33. }
  34. else if (tiles[LEFT].texture_index == -1 && tiles[RIGHT].texture_index == -1)
  35. return false;
  36. if (tiles[CENTRE].texture_index == -1)
  37. return false;
  38. return true;
  39. }
  40. DecoratorDataHandle DecoratorTiledHorizontal::GenerateElementData(Element* element, BoxArea paint_area) const
  41. {
  42. // Initialise the tiles for this element.
  43. for (int i = 0; i < 3; i++)
  44. tiles[i].CalculateDimensions(GetTexture(tiles[i].texture_index));
  45. const RenderBox render_box = element->GetRenderBox(paint_area);
  46. const Vector2f offset = render_box.GetFillOffset();
  47. const Vector2f size = render_box.GetFillSize();
  48. Vector2f left_dimensions = tiles[LEFT].GetNaturalDimensions(element);
  49. Vector2f right_dimensions = tiles[RIGHT].GetNaturalDimensions(element);
  50. Vector2f centre_dimensions = tiles[CENTRE].GetNaturalDimensions(element);
  51. // Scale the tile sizes by the height scale.
  52. ScaleTileDimensions(left_dimensions, size.y, Axis::Vertical);
  53. ScaleTileDimensions(right_dimensions, size.y, Axis::Vertical);
  54. ScaleTileDimensions(centre_dimensions, size.y, Axis::Vertical);
  55. // Round the outer tile widths now so that we don't get gaps when rounding again in GenerateGeometry.
  56. left_dimensions.x = Math::Round(left_dimensions.x);
  57. right_dimensions.x = Math::Round(right_dimensions.x);
  58. // Shrink the x-sizes on the left and right tiles if necessary.
  59. if (size.x < left_dimensions.x + right_dimensions.x)
  60. {
  61. float minimum_width = left_dimensions.x + right_dimensions.x;
  62. left_dimensions.x = size.x * (left_dimensions.x / minimum_width);
  63. right_dimensions.x = size.x * (right_dimensions.x / minimum_width);
  64. }
  65. const ComputedValues& computed = element->GetComputedValues();
  66. Mesh mesh[COUNT];
  67. tiles[LEFT].GenerateGeometry(mesh[tiles[LEFT].texture_index], computed, offset, left_dimensions, left_dimensions);
  68. tiles[CENTRE].GenerateGeometry(mesh[tiles[CENTRE].texture_index], computed, offset + Vector2f(left_dimensions.x, 0),
  69. Vector2f(size.x - (left_dimensions.x + right_dimensions.x), centre_dimensions.y), centre_dimensions);
  70. tiles[RIGHT].GenerateGeometry(mesh[tiles[RIGHT].texture_index], computed, offset + Vector2f(size.x - right_dimensions.x, 0), right_dimensions,
  71. right_dimensions);
  72. const int num_textures = GetNumTextures();
  73. DecoratorTiledHorizontalData* data = new DecoratorTiledHorizontalData(num_textures);
  74. RenderManager* render_manager = element->GetRenderManager();
  75. // Set the mesh and textures on the geometry.
  76. for (int i = 0; i < num_textures; i++)
  77. data->geometry[i] = render_manager->MakeGeometry(std::move(mesh[i]));
  78. return reinterpret_cast<DecoratorDataHandle>(data);
  79. }
  80. void DecoratorTiledHorizontal::ReleaseElementData(DecoratorDataHandle element_data) const
  81. {
  82. delete reinterpret_cast<DecoratorTiledHorizontalData*>(element_data);
  83. }
  84. void DecoratorTiledHorizontal::RenderElement(Element* element, DecoratorDataHandle element_data) const
  85. {
  86. Vector2f translation = element->GetAbsoluteOffset(BoxArea::Border);
  87. DecoratorTiledHorizontalData* data = reinterpret_cast<DecoratorTiledHorizontalData*>(element_data);
  88. for (int i = 0; i < data->num_textures; i++)
  89. data->geometry[i].Render(translation, GetTexture(i));
  90. }
  91. DecoratorTiledHorizontalInstancer::DecoratorTiledHorizontalInstancer() : DecoratorTiledInstancer(3)
  92. {
  93. RegisterTileProperty("left-image");
  94. RegisterTileProperty("right-image");
  95. RegisterTileProperty("center-image");
  96. RegisterShorthand("decorator", "left-image, center-image, right-image", ShorthandType::RecursiveCommaSeparated);
  97. }
  98. DecoratorTiledHorizontalInstancer::~DecoratorTiledHorizontalInstancer() {}
  99. SharedPtr<Decorator> DecoratorTiledHorizontalInstancer::InstanceDecorator(const String& /*name*/, const PropertyDictionary& properties,
  100. const DecoratorInstancerInterface& instancer_interface)
  101. {
  102. constexpr size_t num_tiles = 3;
  103. DecoratorTiled::Tile tiles[num_tiles];
  104. Texture textures[num_tiles];
  105. if (!GetTileProperties(tiles, textures, num_tiles, properties, instancer_interface))
  106. return nullptr;
  107. auto decorator = MakeShared<DecoratorTiledHorizontal>();
  108. if (!decorator->Initialise(tiles, textures))
  109. return nullptr;
  110. return decorator;
  111. }
  112. } // namespace Rml