On Sunday, 20 September 2020 at 14:54:09 UTC, Steven
Schveighoffer wrote:
On 9/20/20 9:30 AM, realhet wrote:
ref inout(int) x() inout { return array[0]; }
This doesn't work when I type:
v.x++;
I want to make a similar type like the GLSL vectors. Where the
following thing is valid:
vec4 a, b;
a.yzw = b.xzy;
On the left there is a contiguous area of the vector a. It just
starts form the 1th element, not form the 0th: a[1..4]. It could
be work as an lvalue.
On the right there is a non-contiguous swizzle: [b.x, b.z, b.y].
But because it is 3 element wide, it can be assigned to the
lvalue "a.yzw". This value cannot be an lvalue because the order
of the elements are not the same as in memory. So it must
returned as a const.
Here's what I achieved so far:
private enum swizzleRegs = ["xyzw", "rgba", "stpq"]; //vector,
color, and texture component letters
struct Vec(CT, int N)
if(N>=2 && N<=4){
alias VectorType = typeof(this);
alias ComponentType = CT;
enum VectorTypeName = ComponentTypePrefix ~ "vec" ~ N.text;
CT[N] array = [0].replicate(N).array; //default is 0,0,0, not
NaN. Just like in GLSL.
alias array this;
enum length = N;
...
static foreach(regs; swizzleRegs)
static foreach(len; 1..N+1)
static foreach(i; 0..N-len+1)
static if(len==1){
1) mixin(format!"auto %s() const { return array[%s];
}"(regs[i], i));
2) mixin(format!"ref %s() { return array[%s];
}"(regs[i], i));
}else{
3) mixin(format!"auto %s() const { return Vec!(CT,
%s)(array[%s..%s]); }"(regs[i..i+len], len, i, i+len));
4) mixin(format!"ref %s() { return *(cast(Vec!(CT,
%s)*) (array[%s..%s])); }"(regs[i..i+len], len, i, i+len));
}
}
So what I feel, the mixin()-s are a bit nasty :D But sufficient
for the following two criteria:
1. immutable vec3 a; a.xy.writeln; // displays a const vec2
casting a constant memory lovation to vec2 -> 3)
2. vec3 b; b.g++; // accessing the 2. component(g=green,
1based) of a vec3 with a memory reference because it is mutable.
I only want lvalues from swizzle combinations that are adjacent
in memory, so I can cast them. For all the rest I'm using
opDispatch(string def)() with a strict constraint on the string
'def'.
For example: a.xxxx returns vec4(a.x, a.x, a.x, a.x);
a.x01z returns vec4(a.x, a.0, a.1, a.z);
The only thing I don't want to implement from the GLSL spec is
those non-contigous swizzle assignments like:
a.zyx = vec3(1,2,3) ***
but
a.xyz = vec3(1,2,3) should work.
*** maybe with a struct that refers to the original vector and
the swizzle code it could be also possible. :D