Euphoria
scalablesprite.cc
Go to the documentation of this file.
2 
3 #include <iostream>
4 #include <algorithm>
5 
6 #include "assert/assert.h"
7 #include "base/rect.h"
8 #include "core/tablelayout.h"
9 
10 #include "files/scalingsprite.h"
11 
12 #include "render/buffer2d.h"
13 #include "render/texture.h"
14 #include "render/texturecache.h"
15 #include "render/spriterender.h"
16 
17 
18 using namespace eu::convert;
19 
21 
22 
23 namespace
24 {
25  float
26  copy_data(std::vector<float>* dest, const std::vector<int>& src)
27  {
28  dest->reserve(src.size());
29  float size = 0;
30  for(const int s: src)
31  {
32  const auto f = static_cast<float>(s);
33  dest->emplace_back(f);
34  size += eu::abs(f);
35  }
36 
37  if(dest->empty())
38  {
39  dest->emplace_back(-100.0f);
40  return 100.0f;
41  }
42 
43  return size;
44  }
45 
46 
47  float
48  get_constant_size(const std::vector<float>& data)
49  {
50  float ret = 0;
51  for(float f: data)
52  {
53  if(f > 0)
54  {
55  ret += f;
56  }
57  }
58  return ret;
59  }
60 }
61 
62 
63 namespace eu::render
64 {
65  ScalableSprite::ScalableSprite
66  (
67  io::FileSystem* fs,
68  const io::FilePath& path,
69  TextureCache* cache
70  )
71  : texture(cache->get_texture(path))
72  {
73  const auto json_path = path.set_extension_copy(path.get_extension()+ ".json");
74 
76  if (const auto loaded = io::read_json_file(fs, json_path); loaded == false
78  {
79  LOG_ERROR("Failed to load {}: {}", json_path, loaded.get_error().display);
80  }
81  else if (loaded)
82  {
83  const auto& json = loaded.get_value();
84  const auto parsed = files::scalingsprite::parse(log::get_global_logger(), &sprite, json.root, &json.doc);
85  if (!parsed)
86  {
87  sprite = {};
88  }
89  }
90 
91  calculated_texture_size_rows = copy_data(&rows, sprite.rows);
92  calculated_texture_size_columns = copy_data(&columns, sprite.cols);
93  }
94 
95 
97 
98 
99  size2f
101  {
103  (
104  get_constant_size(columns),
105  get_constant_size(rows)
106  );
107  }
108 
109 
110  void
111  ScalableSprite::render(SpriteRenderer* renderer, const Rectf& rect, const Rgba& tint) const
112  {
113  const auto size = rect.get_size();
114  const auto pos = rect.get_bottom_left();
115  const auto position_cols = core::perform_table_layout(columns, size.width);
116  const auto position_rows = core::perform_table_layout(rows, size.height);
117 
118  const auto cols_size = columns.size();
119  const auto rows_size = rows.size();
120 
121  ASSERT(position_rows.size() == rows_size);
122  ASSERT(position_cols.size() == cols_size);
123 
124  float position_current_col = 0;
125  float uv_current_col = 0;
126  for(unsigned int column_index = 0; column_index < cols_size; ++column_index)
127  {
128  float position_current_row = size.height;
129  float uv_current_row = 1;
130 
131  const auto position_next_col = position_current_col + position_cols[column_index];
132  const auto uv_next_col = uv_current_col + abs(columns[column_index]) / calculated_texture_size_columns;
133 
134  for(unsigned int row_index = 0; row_index < rows_size; ++row_index)
135  {
136  const auto position_next_row = position_current_row - position_rows[row_index];
137  const auto uv_next_row = uv_current_row - abs(rows[row_index]) / calculated_texture_size_rows;
138 
139  ASSERTX
140  (
141  position_current_row > position_next_row,
142  position_current_row,
143  position_next_row
144  );
145  ASSERTX
146  (
147  uv_current_row > uv_next_row,
148  uv_current_row,
149  uv_next_row
150  );
151  const auto position_rect = Rectf::from_left_right_top_bottom
152  (
153  position_current_col,
154  position_next_col,
155  position_current_row,
156  position_next_row
157  );
158  const auto uv_rect = Rectf::from_left_right_top_bottom
159  (
160  uv_current_col,
161  uv_next_col,
162  uv_current_row,
163  uv_next_row
164  );
165 
166  renderer->draw_rect
167  (
168  *texture,
169  position_rect.translate_copy(pos),
170  uv_rect,
171  0.0_rad,
172  Scale2f{0, 0},
173  tint
174  );
175 
176  position_current_row = position_next_row;
177  uv_current_row = uv_next_row;
178  }
179  position_current_col = position_next_col;
180  uv_current_col = uv_next_col;
181  }
182  }
183 }
#define ASSERTX(x,...)
Definition: assert.h:48
#define ASSERT(x)
Definition: assert.h:29
#define LOG_ERROR(...)
Definition: log.h:9
constexpr ParseResult error
no error occurred
Definition: argparse.h:73
std::vector< T > perform_table_layout(const std::vector< T > &pieces, T total_size, T zero=0)
Calculates a table layout based on the input layout.
Definition: tablelayout.h:22
JsonResult read_json_file(FileSystem *fs, const FilePath &file_name)
Definition: json.cc:58
Logger * get_global_logger()
Definition: log.cc:34
constexpr float abs(float r)
Definition: numeric.h:8
Definition: rect.h:27
size2f get_size() const
Definition: rect.cc:455
static Rectf from_left_right_top_bottom(float left_side, float right_side, float top_side, float bottom_side)
Definition: rect.cc:47
vec2f get_bottom_left() const
Definition: rect.cc:118
const Error & get_error() const
Definition: result.h:36
Definition: rgb.h:143
FilePath set_extension_copy(const std::string &ext) const
Definition: vfs_path.cc:170
std::string get_extension() const
Definition: vfs_path.cc:161
std::vector< float > rows
std::vector< float > columns
std::shared_ptr< Texture2 > texture
void render(SpriteRenderer *renderer, const Rectf &rect, const Rgba &tint) const
void draw_rect(const Texture2 &texture, const Rectf &sprite_area, const Rectf &texture_region, const Angle &rotation_angle, const Scale2f &rotation_anchor, const Rgba &tint_color)
Definition: spriterender.cc:71
static size2f create_from_width_height(float w, float h)
Definition: size2.cc:15