g-truc / glm

OpenGL Mathematics (GLM)
https://glm.g-truc.net
Other
9.1k stars 2.12k forks source link

glm::io additional operators and properties #1232

Open dimateos opened 7 months ago

dimateos commented 7 months ago

Hello!

I was using glm::io and found myself wanting to print matrices in a single line easily. I saw very convinient operators for easily changing precision, width... but none for space and newline, hence this PR commits:

  1. Added an operator to edit space and newline with a packed struct named filler (related to std::setfill), following the same structure as the struct delimeter.
  2. Added default arguments for the structs, similar to delimeter optional last argument. Seems pretty useful to have them in order to restore the default behavior.
    • I set precision=3 and width=8 like format_punct does in the default constructor (actually done in a later commit).
  3. ~Skip initial newline when printing matrices. IMO seems more logical to let the end user do it, in my case I need this to be able to print matrices in a single line.~
    • ~Introduces differences with previous outputs! Quite noticeable, but consistent with vector behavior.~
  4. Add an space after separator insertion. This allows to have width=0 and keep an space between components for better visualization.
    • Introduces differences with previous outputs! Potentially makes current components a single space wider.
  5. Reduce initial width to compensate the introduced space after separator. This cancels out differences with previous default usage.
  6. Added a dedicated fill property instead of doing setw(space). This allows to set e.g. '0' as filler only, because space was also being used in many other places. Can be modified as part of the struct filler.
  7. Added a dedicated firstline property to be able to keep the previous behavior broken in commit (3.), basically replaces the first newline for a customizable character. Can be modified as part of the struct filler.
  8. Util functions similar to io::formatted: io::reset to restore default settings and io::compressed to setup single line printing.
  9. Avoid merge conflicts with #1252. Well there are still conflicts (skipped merging master here to avoid all the commits), but now this branch changes should just replace master's.

Example of how to print a matrix in a single line, restore the locale, modify fill:

#include "glm/gtx/io.hpp"
...
glm::mat2 m(1);
std::cout << " m = " << glm::io::precision(2) << glm::io::compressed << m << std::endl;
// m = [[1.00, 0.00], [0.00, 1.00]]
...
std::cout << " m = " << glm::io::reset << m << std::endl;
// m = 
// [[   1.000,    0.000]
//  [   0.000,    1.000]]
...
std::cout << " m = " << glm::io::filler<char>('0') /* keep other default args */ << m << std::endl;
// m = 
// [[0001.000, 0000.000]
//  [0000.000, 0001.000]]

I split the commits for simpler discussion/review/changes, let me know what you think. I can squash them all in the end or whatever you prefer.

Regards!

I kept this as a draft because I was working with an issue related to lost locale properties. When you imbue a std::ofstream out with glm::io::XXX and then passed it as a reference in a function using std::ostream& os, the stream inside this function ignores set locales. E.g. std::setprecision(2) is preserved but glm::io::precision(2) isnt. Probably leaving it for a separate issue as this seems to happen without this PR changes anyway.