Europa Universalis IV

Europa Universalis IV

Cantons for Colonial Flags
MouToN 1 Jun, 2023 @ 5:36am
Possible algorithm to compute the "zoom factor" for custom flags
The method here is to compute normalized flag coordinates from TexCoord and an hypothetical number of flags per row and column, then compare these coordinates to the actual value of TexCoordFlag.
Because coordinates are floats, we will almost never exactly get TexCoordFlag, but by selecting the smallest margin, we might find the most plausible candidate.

## Shared Code Code [[ // works even when TexCoordFlag.x = 1 or TexCoordFlag.y = 1 float2 normalized_texture_coordinates_safe ( const float2 TexCoord, const int2 FlagsPerRowAndColumn, const float2 TexCoordFlag ) { float2 OutTexCoord = TexCoord; OutTexCoord -= ( floor ( TexCoordFlag ) + floor ( TexCoord * FlagsPerRowAndColumn ) ) / FlagsPerRowAndColumn; OutTexCoord *= FlagsPerRowAndColumn; return OutTexCoord; } // works only when TexCoordFlag.x != 1 and TexCoordFlag.y != 1 float2 normalized_texture_coordinates ( const float2 TexCoord, const int2 FlagsPerRowAndColumn ) { float2 OutTexCoord = TexCoord; OutTexCoord -= floor ( TexCoord * FlagsPerRowAndColumn ) / FlagsPerRowAndColumn; OutTexCoord *= FlagsPerRowAndColumn; return OutTexCoord; } int2 flags_per_row_and_column ( const float2 TexCoord, const float2 TexCoordFlag ) { static const int2 FlagsPerRowAndColumn_pattern = int2 ( 10, 4 ); // Vanilla. For modded value, see /common/custom_country_colors/00_custom_country_colors.txt, textures::texture::size static const int2 FlagsPerRowAndColumn_pattern2 = int2 ( 10, 2 ); float Distance_pattern = distance ( normalized_texture_coordinates_safe ( TexCoord, FlagsPerRowAndColumn_pattern, TexCoordFlag ), TexCoordFlag ); // remark: could use the unsafe one for cantons float Distance_pattern2 = distance ( normalized_texture_coordinates_safe ( TexCoord, FlagsPerRowAndColumn_pattern2, TexCoordFlag ), TexCoordFlag ); return Distance_pattern < Distance_pattern2 ? FlagsPerRowAndColumn_pattern : FlagsPerRowAndColumn_pattern2; // with only 2 values, it is easy to know for which int2 the min is reached } ]]
Remark: no need for the safe function here, the unsafe one would be enough. I include the safe implementation incase someone needs it for any other use.


Here is a possible implementation when there are more than 2 possible return values (modded patterns)
int2 flags_per_row_and_column ( const float2 TexCoord, const float2 TexCoordFlag ) { static const int FlagsPerRowAndColumnPairs[8] = { 10, 4, 10, 2, 16, 16, 12, 8 }; // example of 4 pairs int2 OutSize; float MinDistance = 1000; for ( i=0; i<4; ++i ) { int2 CurrentPair = int2 ( FlagsPerRowAndColumnPairs[i*2], FlagsPerRowAndColumnPairs[i*2+1] ); float CurrentDistance = distance ( normalized_texture_coordinates ( TexCoord, CurrentPair ), TexCoordFlag ); if ( CurrentDistance < MinDistance ) { OutSize = CurrentPair; MinDistance = CurrentDistance; } } return OutSize; }

Then instead of being multiplied by zoomFactor, v.vTexCoordFlag should be divided by the return value of [icode]flags_per_row_and_column ( v.vTexCoord, v.vTexCoordFlag )[/icode]

A good way to check if the value returned of the function 'flags_per_row_and_column' is the one corresponding to the texture that contains the chosen pattern, is to use the Pixel Shader in a "debug mod".
Protocol: start a game as a custom nation, then hover your mouse over an owned province. In Vanilla, with a two-color pattern, the flag should be red. With a three-color pattern it should be green.

MainCode PixelShaderFlagTextColor [[ float4 main( VS_FLAG_OUTPUT v ) : PDX_COLOR { DEBUG if ( all ( flags_per_row_and_column ( v.vTexCoord, v.vTexCoordFlag ) == int2 ( 10, 4 ) ) ) return float4 ( 1, 0, 0, 1 ); // red else if ( all ( flags_per_row_and_column ( v.vTexCoord, v.vTexCoordFlag ) == int2 ( 10, 2 ) ) ) return float4 ( 0, 1, 0, 1 ); // green else return float4 ( 0, 0, 1, 1 ); // blue } ]]