I am currently writing a test program for a collision function, that involves multithreading so I can simultaneously check for collisions and move a skeleton at the same time. Because of this, I had to use ```shared``` objects. The specific objects I was using were declared in a file called "skeleton.d." In a function I wrote for moving the skeletons, it uses operator overloading, which produces the following output:

```d
physics.d(85): Error: none of the `opOpAssign` overloads of `Point` are callable for `j` of type `shared(Point)` physics.d(87): Error: none of the `opOpAssign` overloads of `Point` are callable for `k.start` of type `shared(Point)` physics.d(88): Error: none of the `opOpAssign` overloads of `Point` are callable for `k.stop` of type `shared(Point)` physics.d(90): Error: none of the `opOpAssign` overloads of `Point` are callable for `i.center` of type `shared(Point)` physics.d(92): Error: none of the `opOpAssign` overloads of `Point` are callable for `tomove.center` of type `shared(Point)` physics.d(112): Error: none of the `opOpAssign` overloads of `Point` are callable for `k` of type `shared(Point)` physics.d(114): Error: none of the `opOpAssign` overloads of `Point` are callable for `j.start` of type `shared(Point)` physics.d(115): Error: none of the `opOpAssign` overloads of `Point` are callable for `j.stop` of type `shared(Point)` physics.d(117): Error: none of the `opOpAssign` overloads of `Point` are callable for `i.center` of type `shared(Point)` physics.d(119): Error: none of the `opOpAssign` overloads of `Point` are callable for `ori.center` of type `shared(Point)` physics.d(120): Error: none of the overloads of `opAssign` are callable using a `shared` object skeleton.d(81): Candidates are: `skeleton.Skeleton.opAssign(Skeleton rhs)` skeleton.d(88): `skeleton.Skeleton.opAssign(shared(Skeleton) rhs)` physics.d(136): Error: mixin `physics.move.__mov__general__!"n"` error instantiating
```

This is clearly wrong, as type ```Point``` is not the same as type ```Skeleton```.

For reference, here are the files:

test.d:
```d
import physics;
void main()     {
        Skeleton cube;
        Face[] cubefaces;
        cubefaces.length = 1;
cubefaces[0].lines ~= Line([Point(0,0.25,0), Point(0,0.5,0), Point(0,0.75,0)], Point(0,0,0), Point(0,1,0)); cubefaces[0].lines ~= Line([Point(0.25,0,0), Point(0.5,0,0), Point(0.75,0,0)], Point(0,0,0), Point(1,0,0)); cubefaces[0].lines ~= Line([Point(1,0.25,0), Point(1,0.5,0), Point(1,0.75, 0)], Point(1,0,0), Point(1,1,0)); cubefaces[0].lines ~= Line([Point(0.25,1,0), Point(0.5,1,0), Point(0.75,1,0)], Point(0,1,0), Point(1,1,0));
        cubefaces[0].center = Point(0.5,0.5,0);
        cube.faces = cubefaces.dup;
        cube.center = Point(0.5,0.5,0);
        auto cube2 = cube;
        move(Point(99,0,0), 0, cast(shared(Skeleton))cube, 99);
        import std.stdio;
        import std.concurrency;
spawn(&test1, cast(shared(Skeleton))cube2, cast(shared(Skeleton))cube);
        spawn(&move,Point(-99,0,0), 5, cast(shared(Skeleton))cube, 1);
        bool b = receiveOnly!bool;
        writeln(b);
}
void test1(shared ref Skeleton cube2, shared ref Skeleton cube) {
        import std.concurrency;
if(detectCollision(cast(shared(Skeleton[]))[cube2], cast(shared(Skeleton))cube, real.infinity))
                send(ownerTid(), true);
}
```

skeleton.d:

```d
/*skeleton.d by Ruby The Roobster*/
/*Version 1.0 Release*/
/*Module for representing skeletons in the D Programming Language 2.0*/ /*This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.*/
/** Copyright: 2021, Ruby The Roobster*/
/**Author: Ruby The Roobster, michaeleverest...@gmail.com*/
/**Date: October 1, 2021*/
/** License:  GPL-3.0*/
module skeleton;
/**Struct for representing a point.*/
public struct Point     { //Point structure...
        ///Point.x is the 'x' coordinate of the point.
        real x;
        ///Point.y is the 'y' coordinate of the point.
        real y;
        ///Point.z is the 'z' coordinate of the point.
        real z;
        this(real x, real y, real z)    {
                this.x = x;
                this.y = y;
                this.z = z;
        }
        void opAssign(Point rhs)        {
                this.x = rhs.x;
                this.y = rhs.y;
                this.z = rhs.z;
        }
        void opAssign(shared Point rhs) {
                this.x = rhs.x;
                this.y = rhs.y;
                this.z = rhs.z;
        }

        void opOpAssign(string op)(Point rhs)   {
                mixin("this.x " ~ op ~ "= rhs.x;");
                mixin("this.y " ~ op ~ "= rhs.y;");
                mixin("this.z " ~ op ~ "= rhs.z;");
        }
        void opOpAssign(string op)(shared(Point) rhs)   {
                        mixin("this.x " ~ op ~ "= rhs.x;");
                        mixin("this.y " ~ op ~ "= rhs.y;");
                        mixin("this.z " ~ op ~ "= rhs.z;");
        }
}
/**Struct for representing a face of a skeleton that is made out of lines.*/
public struct Face      { //Face(of a 3D shape) structure...
///Face.lines is an array of all the lines that connect to form the face.
        Line[] lines;
        ///Face.center is the center point of the face.
        Point center;
        void opAssign(Face rhs) {
                this.lines.length = rhs.lines.length;
                foreach(i;0 .. this.lines.length)       {
                        this.lines[i] = rhs.lines[i];
                }
        }
        void opAssign(shared Face rhs)  {
                this.lines.length = rhs.lines.length;
                foreach(i;0 .. this.lines.length)       {
                        this.lines[i] = rhs.lines[i];
                }
        }
}
/**Struct for representing a 3D skeleton.*/
public struct Skeleton  { //Skeleton of a 3D structure...
///Skeleton.faces is an array of the faces that make up the Skeleton.
        Face[] faces;
        ///Skeleton.center is the center point of the skeleton.
        Point center;
        void opAssign(Skeleton rhs)     {
                this.faces.length = rhs.faces.length;
                foreach(i;0 .. this.faces.length)       {
                        this.faces[i] = rhs.faces[i];
                }
                this.center = rhs.center;
        }
        void opAssign(shared Skeleton rhs)      {
                this.faces.length = rhs.faces.length;
                foreach(i;0 .. this.faces.length)       {
                        this.faces[i] = rhs.faces[i];
                }
                this.center = rhs.center;
        }
}

/**Struct for representing a line composed of at least a starting point and an end point.
  *Notes:
*This struct doesn't check to make sure that the line made is an actual line and assumes the user knows what they are doing.
*/
public struct Line      { //Line struct...
///Line.mid_points is an array containing all of the points that are neither start nor end points.
        Point[] mid_points;
        ///Line.start is the start point of the line.
        Point start;
        ///Line.end is the end point of the line.
        Point stop;
        void opAssign(Line rhs) {
                this.start = rhs.start;
                this.stop = rhs.stop;
                this.mid_points.length = rhs.mid_points.length;
                foreach(i;0 .. this.mid_points.length)  {
                        this.mid_points[i] = rhs.mid_points[i];
                }
        }
        void opAssign(shared Line rhs)  {
                this.start = rhs.start;
                this.stop = rhs.stop;
                this.mid_points.length = rhs.mid_points.length;
                foreach(i;0 .. this.mid_points.length)  {
                        this.mid_points[i] = rhs.mid_points[i];
                }
        }
}
```

and finally, physiscs.d:

```d
/*physics.d by Ruby The Roobster*/
/*Version 0.35 testing*/
/*Module for basic physics in the D Programming Language 2.0*/
/*This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.*/
/** Copyright: 2021, Ruby The Roobster*/
/**Author: Ruby The Roobster, michaeleverest...@gmail.com*/
/**Date: October 27, 2021*/
/** License: GPL-3.0*/
module physics;
public import skeleton;

package mixin template __mov__general__(string func)
{
        void __mov__general__(real accdec = 0)
        {
                import core.thread;
                Point moveby;
                bool b = false;
                auto ori = tomove;
                        debug import std.stdio : writeln;
                if(speed > 1 || speed < -1)
                {
                        moveby.x = moveto.x / speed;
                        moveby.y = moveto.y / speed;
                        moveby.z = moveto.z / speed;
                        b = true;
                }
                else
                {
                        moveby.x = moveto.x * speed;
                        moveby.y = moveto.y * speed;
                        moveby.z = moveto.z * speed;
                }
while(!((tomove.center.x > moveto.x && moveto.x > 0) ^ (tomove.center.x < moveto.x && moveto.x < 0)))
                {
                        static if(func == "a")
                        {
                                speed += accdec;
                                if(b)
                                {
                                        moveby.x = moveto.x / speed;
                                        moveby.y = moveto.y / speed;
                                        moveby.z = moveto.z / speed;
                                }
                                else
                                {
                                        moveby.x = moveto.x * speed;
                                        moveby.y = moveto.y * speed;
                                        moveby.z = moveto.z * speed;
                                }
                        }
                        else static if(func == "d")
                        {
                                speed -= accdec;
                                if(b)
                                {
                                        moveby.x = moveto.x / speed;
                                        moveby.y = moveto.y / speed;
                                        moveby.z = moveto.z / speed;
                                }
                                else
                                {
                                        moveby.x = moveto.x * speed;
                                        moveby.y = moveto.y * speed;
                                        moveby.z = moveto.z * speed;
                                }
                        }
                        foreach(i;tomove.faces)
                        {
                                foreach(k;i.lines)
                                {
                                        foreach(j;k.mid_points)
                                        {
                                                j += moveby;
                                        }
                                        k.start += moveby;
                                        k.stop += moveby;
                                }
                                i.center += moveby;
                        }
                        tomove.center += moveby;
                        Thread.sleep(dur!"msecs"(tbf));
                        static if(func == "a")
                        {
                                speed += accdec;
                        }
                        else static if(func == "d")
                        {
                                speed -= accdec;
                        }
                        else
                        {
                        }
                }
                foreach(i;ori.faces)
                {
                        foreach(j;i.lines)      
                        {
                                foreach(k;j.mid_points)
                                {
                                        k += moveto;
                                }
                                j.start += moveto;
                                j.stop += moveto;
                        }
                        i.center += moveto;
                }
                ori.center += moveto;
                tomove = ori;
        }
}

/**
* move moves all the points in a skeleton to a specified point with a specified time gap between moving the points.
  * Params:
* moveto = A point specifying the total amount to move along each axis. * tbf = The time in miliseconds between 'frames'(a frame is one section of moving points before waiting a bit). This gives an illusion of continuous motion.
  *     tomove =        The skeleton being moved.
  *     speed = The speed at which to move the points.
  * Returns:
  * none
*/
pragma(inline, true) public void move(Point moveto, uint tbf, ref shared Skeleton tomove, real speed)
{
        mixin __mov__general__!"n";
        __mov__general__();
}

/**
* accMove moves all the points in a skeleton to a specified point with a specified time gap between movements all while accelerating the speed.
  * Params:
* moveto = A point specifying the total amount to move along each axis. * tbf = The time in miliseconds between 'frames'(a frame is one section of moving points before waiting a bit). This gives an illusion of continuous motion.
  *     tomove =        The skeleton being moved.
  *     speed  =        The original speed at which the skeleton moves.
  *     accdec =        The amount to increment the speed by each frame.
*/
pragma(inline, true) public void accMove(Point moveto, uint tbf, shared ref Skeleton tomove, real speed, real accdec = 0)
{
        mixin __mov__general__!"a";
        __mov__general__(accdec);
}
/**
* decMove moves all the points in a skeleton to a specified point with a specified time gap between movements all while deaccelerating the speed.
  * Params:
* moveto = A point specifying the total amount to move along each axis. * tbf = The time in miliseconds between 'frames'(a frame is one section of moving points before waiting a bit). This gives an illusion of continuous motion.
  *     tomove =        The skeleton being moved.
  *     speed  =        The original speed at which the skeleton moves.
  *     accdec =        The amount to decrement the speed by each frame.
*/
pragma(inline) public void decMove(Point moveto, uint tbf, shared ref Skeleton tomove, real speed, real accdec = 0)
{
        mixin __mov__general__!"d";
        __mov__general__(accdec);
}

public bool detectCollision(shared Skeleton[] towatch, shared Skeleton skele, real time = 0)
        in      {
                auto a = cast(ulong)time;
assert(a == time || time == real.infinity,"Parameter time must always be a whole number or infinity!");
        }
        do      {
                mixin find!(["x", "y", "z"]);
                import std.datetime.stopwatch;
                auto sw = StopWatch(AutoStart.no);
                sw.start();
                scope(exit) sw.stop();
                while(sw.peek.total!"msecs" <= time || time == real.inf)
                {
                        foreach(i;towatch)
                        {
                                foreach(j;i.faces)
                                {
                                        foreach(k;j.lines)
                                        {
                                                foreach(l;k.mid_points)
                                                {
                                                        foreach(m;skele.faces)
                                                        {
                                                                
foreach(n;m.lines)
                                                                {
                                                                        for(uint 
o; o < n.mid_points.length+1; o++)
                                                                        {
                                                                                
if(switcho(l))
                                                                                
        return true;
                                                                                
if(switcho(k.start))
                                                                                
        return true;
                                                                                
if(switcho(k.stop))
                                                                                
        return true;
                                                                        }
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
                return false;
        }

package mixin template find(string[] tofind)
{
        static foreach(i; tofind)       {
                mixin("real high" ~ i ~ ";");
                mixin("real low" ~ i ~ ";");
        }
        void find(Point[2] tof)
        {
                static foreach(i; tofind)
                {
mixin("high" ~ i ~ " = tof[0]." ~ i ~ " >= tof[1]." ~ i ~ " ? tof[0]." ~ i ~ " : tof[1]." ~ i ~ ";"); mixin("low" ~ i ~ " = tof[0]." ~ i ~ " <= tof[1]." ~ i ~ " ? tof[0]." ~ i ~ " : tof[1]." ~ i ~ ";");
                }
        }
}

package pragma(inline, true) bool switcho(Point toswitch)
{
        switch(o)
        {
                        default:
                                if(o == n.mid_points.length)
                                {
                                        find([n.mid_points[o-1], n.stop]);
                                }
                                else
                                {
                                        find([n.mid_points[o-1], 
n.mid_points[o]]);
                                }
if(toswitch.x <= highx && toswitch.x >= lowx && toswitch.y <= highy && toswitch.y >= lowy && toswitch.z <= highz && toswitch.z >= lowz)
                                {
                                return true;
                                }
                                break;
                        case 0:
                                find([n.mid_points.start, n.mid_points[o]]);
if(toswitch.x <= highx && toswitch.x >= lowx && toswitch.y <= highy && toswitch.y >= lowy && toswitch.z <= highz && toswitch.z >= lowz)
                                {
                                        return true;
                                }
        }
}
```

Can anyone explain why it can't find the correct function? Thanks in advance.

Reply via email to