blob: e5fe2514e2ebd18330728b9d0a9098c9caeea7d9 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
;;;; units/container.lisp
(in-package #:wheelwork)
(defclass/std container (unit)
((units :with :a)
(cached-rect :with)
(left right top bottom :with :std 0 :doc "container's box coordinates."))
(:documentation "Just a list of units. Made into a class so that
transformation affine transformations methods can be specialzied on
whole groups of units"))
(defmethod (setf closer-mop:slot-value-using-class)
(newval class (container container) slot)
(case (closer-mop:slot-definition-name slot)
((left right top bottom)
(setf (container-cached-rect container) nil))))
(defmethod get-rect ((container container))
(with-slots (cached-rect left right top bottom) container
(or cached-rect
(setf cached-rect
(list (vec:vec left bottom 0 1.0)
(vec:vec left top 0 1.0)
(vec:vec right top 0 1.0)
(vec:vec right bottom 0 1.0)
(vec:vec left bottom 0 1.0))))))
(defun point-in-contanier-box-p (c x y)
"Returns T if the ponit X Y is inside the bounds of the container."
(and (<= (container-left c) x (container-right c))
(<= (container-bottom c) y (container-top c))))
(defun visible-in-container-p (unit)
"Returns T if UNIT is VISIBLEP, if it is inside a CONTAINER, if any
of the corners of its bounding rectangle are inside that CONTAINER.
UNIT must implement the affine protocol."
(when (unit-visiblep unit)
(when-let ((container
(unit-container unit)))
(loop for pt in (get-rect unit)
thereis (point-in-contanier-box-p container (vec:vx pt) (vec:vy pt))))))
(defmethod drop-unit ((unit unit))
"Removes a unit from its container. Returns T if the unit actually was removed."
(when-let (container (unit-container unit))
(setf
(container-units container) (delete unit (container-units container))
(unit-container unit) nil)
t))
(defmethod add-unit ((container container) (unit unit))
"Adds a unit to the end of a container (thus affecting render
order). Makes sure to remove the unit from its current container if
necessary."
(when (unit-container unit)
(drop-unit unit))
(push unit (container-units container))
(setf (unit-container unit) container)
unit)
(defmethod cleanup ((container container))
(dolist (u (container-units container))
(cleanup u)))
(defmethod render ((container container))
(let ((current
(gl:get* :scissor-box))
(scale
(application-scale
(app-of-unit container))))
(with-slots (left right top bottom) container
(gl:scissor (* left scale) (* scale bottom) (* scale (- right left)) (* scale (- top bottom)))
(unwind-protect
(dolist (u (container-units container))
(if (visible-in-container-p u)
(render u)))
(gl:scissor (aref current 0) (aref current 1) (aref current 2) (aref current 3))))))
|