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)
78 				.draaiMx(houding._draai.x)
79 				.maal(Mat!(4).draaiMy(houding._draai.y).maal(eigenM)));
80 		// [x, y, z] komen dus overeen met een [theta, psi, rho] stelsel.
81 		eigenM[0][3] = houding._plek.x;
82 		eigenM[1][3] = houding._plek.y;
83 		eigenM[2][3] = houding._plek.z;
84 		return eigenM;
85 	}
86 
87 	protected void werkBij(bool ouderAangepast) {
88 		if (!ingeschakeld)
89 			return;
90 
91 		assert(!(ouderAangepast && ouder is null)); // Kan ouder niet aanpassen als deze niet bestaat.
92 		bool bijgewerkt = aangepast || ouderAangepast;
93 
94 		if (aangepast) {
95 			eigenM = Ding.krijgEigenM(this.houding);
96 			aangepast = false;
97 		}
98 
99 		if (bijgewerkt)
100 			tekenM = (ouder is null) ? eigenM : ouder.tekenM.maal(eigenM);
101 
102 		foreach (Ding kind; kinderen)
103 			kind.werkBij(bijgewerkt);
104 	}
105 
106 	public void voegKind(Ding kind) {
107 		assert(kind !is null);
108 		assert(kind.ouder is null);
109 		kind.ouder = this;
110 		this.kinderen ~= kind;
111 
112 		if (this._wereld !is null)
113 			this._wereld.voegDing(kind);
114 	}
115 
116 	public void verwijderKind(Ding kind) {
117 		assert(kind !is null);
118 		kinderen.verwijder(kind);
119 		kind.ouder = null;
120 		if (kind._wereld !is null)
121 			kind._wereld.verwijderDing(kind);
122 	}
123 
124 }