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

Reply via email to