1 module hoekjed.dingen.ding;
2 
3 import hoekjed;
4 
5 struct Houding {
6 	Vec!3 _plek = {[0, 0, 0]};
7 	Vec!3 _draai = {[0, 0, 0]};
8 	Vec!3 _grootte = {[1, 1, 1]};
9 }
10 
11 abstract class Ding {
12 	protected Wereld _wereld;
13 	protected Houding houding;
14 
15 	protected alias houding this;
16 
17 	private bool aangepast = true;
18 	private bool _ingeschakeld = true; // VERBETER: zoek manier om toe te passen voor elke teken/denk/werkBij stap.
19 
20 	protected Mat!4 eigenM = Mat!(4).identiteit;
21 	protected Mat!4 tekenM = Mat!(4).identiteit;
22 
23 	Ding ouder;
24 	Ding[] kinderen;
25 
26 	@property Wereld wereld() nothrow {
27 		return _wereld;
28 	}
29 
30 	@property Vec!3 plek() nothrow {
31 		return _plek;
32 	}
33 
34 	@property Vec!3 draai() nothrow {
35 		return _draai;
36 	}
37 
38 	@property Vec!3 grootte() nothrow {
39 		return _grootte;
40 	}
41 
42 	@property void plek(Vec!3 waarde) nothrow {
43 		_plek = waarde;
44 		aangepast = true;
45 	}
46 
47 	@property void draai(Vec!3 waarde) nothrow {
48 		_draai = waarde;
49 		aangepast = true;
50 	}
51 
52 	@property void grootte(Vec!3 waarde) nothrow {
53 		_grootte = waarde;
54 		aangepast = true;
55 	}
56 
57 	@property bool ingeschakeld() nothrow {
58 		return _ingeschakeld;
59 	}
60 
61 	@property void ingeschakeld(bool waarde) {
62 		_ingeschakeld = waarde;
63 		wereld.zetIngeschakeld(this, waarde);
64 		foreach (Ding kind; kinderen) {
65 			kind.ingeschakeld(waarde);
66 		}
67 	}
68 
69 	protected abstract void denk();
70 	protected abstract void teken();
71 
72 	public static pure Mat!4 krijgEigenM(Houding houding) {
73 		Mat!4 eigenM = Mat!(4).identiteit;
74 		eigenM[0][0] = houding._grootte.x;
75 		eigenM[1][1] = houding._grootte.y;
76 		eigenM[2][2] = houding._grootte.z;
77 		eigenM = Mat!(4).draaiMz(houding._draai.z).maal(Mat!(4).draaiMx(houding._draai.x)
78 			.maal(Mat!(4).draaiMy(houding._draai.y).maal(eigenM)));
79 		// [x, y, z] komen dus overeen met een [theta, psi, rho] stelsel.
80 		eigenM[0][3] = houding._plek.x;
81 		eigenM[1][3] = houding._plek.y;
82 		eigenM[2][3] = houding._plek.z;
83 		return eigenM;
84 	}
85 
86 	protected void werkBij(bool ouderAangepast) {
87 		if (!ingeschakeld)
88 			return;
89 
90 		assert(!(ouderAangepast && ouder is null)); // Kan ouder niet aanpassen als deze niet bestaat.
91 		bool bijgewerkt = aangepast || ouderAangepast;
92 
93 		if (aangepast) {
94 			eigenM = Ding.krijgEigenM(this.houding);
95 			aangepast = false;
96 		}
97 
98 		if (bijgewerkt)
99 			tekenM = (ouder is null) ? eigenM : ouder.tekenM.maal(eigenM);
100 
101 		foreach (Ding kind; kinderen)
102 			kind.werkBij(bijgewerkt);
103 	}
104 
105 	public void voegKind(Ding kind) {
106 		assert(kind !is null);
107 		assert(kind.ouder is null);
108 		kind.ouder = this;
109 		this.kinderen ~= kind;
110 
111 		if (this._wereld !is null)
112 			this._wereld.voegDing(kind);
113 	}
114 
115 	public void verwijderKind(Ding kind) {
116 		assert(kind !is null);
117 		kinderen.verwijder(kind);
118 		kind.ouder = null;
119 		if(kind._wereld !is null)
120 			kind._wereld.verwijderDing(kind);
121 	}
122 
123 }