Completed
Push — master ( be4ea7...66bb0f )
by Marko
12s
created

Entity::component()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 14
ccs 7
cts 7
cp 1
rs 9.4285
cc 3
eloc 9
nc 3
nop 1
crap 3
1
<?php
2
/** @formatter:off
3
 * ******************************************************************
4
 * Created by   Marko Kungla on Jun 20, 2016 - 9:11:10 PM
5
 * Contact      [email protected]
6
 * @copyright   2016 Marko Kungla - https://github.com/mkungla
7
 * @license     The MIT License (MIT)
8
 *
9
 * @category       AframeVR
10
 * @package        aframe-php
11
 *
12
 * Lang         PHP (php version >= 7)
13
 * Encoding     UTF-8
14
 * File         Entity.php
15
 * Code format  PSR-2 and 12
16
 * @link        https://github.com/mkungla/aframe-php
17
 * @issues      https://github.com/mkungla/aframe-php/issues
18
 * ********************************************************************
19
 * Contributors:
20
 * @author Marko Kungla <[email protected]>
21
 * ********************************************************************
22
 * Comments:
23
 * @formatter:on */
24
namespace AframeVR\Core;
25
26
use \AframeVR\Core\Exceptions\BadComponentCallException;
27
use \AframeVR\Interfaces\{
28
    ComponentInterface,
29
    EntityInterface,
30
    AnimationInterface
31
};
32
use \AframeVR\Core\Helpers\{
33
    EntityChildrenFactory,
34
    MeshAttributes,
35
    Helper
36
};
37
use \AframeVR\Core\Animation;
38
use \DOMElement;
39
40
class Entity implements EntityInterface
41
{
42
    use MeshAttributes;
43
44
    /**
45
     * Array of used components
46
     *
47
     * @var array
48
     */
49
    protected $components = array();
50
51
    /**
52
     * Array of used animations
53
     *
54
     * @var array
55
     */
56
    protected $animations = array();
57
58
    /**
59
     * Dom element attributes
60
     *
61
     * @var unknown
62
     */
63
    protected $attrs = array();
64
65
    /**
66
     * Children Factory
67
     *
68
     * @var \AframeVR\Core\Helpers\EntityChildrenFactory
69
     */
70
    protected $childrenFactory;
71
72
    /**
73
     * Indent used when rendering formated outout
74
     *
75
     * @var unknown
76
     */
77
    private $indentation = 0;
78
79
    /**
80
     * Constructor
81
     *
82
     * @param string $id
83
     */
84 82
    public function __construct(string $id = '0')
85
    {
86 82
        $this->attr('id', $id);
87
88
        /* Extending entity reset | initial setup */
89 82
        $this->reset();
90 82
    }
91
92
    /**
93
     * Reset primitive default attributtes
94
     *
95
     * {@inheritdoc}
96
     *
97
     * @return void
98
     */
99 78
    public function reset()
100
    {
101
        /* Components which All entities inherently have */
102 78
        $this->attr('Position');
103 78
        $this->attr('Rotation');
104 78
        $this->attr('Scale');
105 78
    }
106
107
    /**
108
     * Child entity / primitive
109
     *
110
     * @return \AframeVR\Core\Helpers\EntityChildrenFactory
111
     */
112 7
    public function el(): EntityChildrenFactory
113
    {
114 7
        return $this->childrenFactory ?? $this->childrenFactory = new EntityChildrenFactory();
115
    }
116
117
    /**
118
     * Position component
119
     *
120
     * All entities inherently have the position component.
121
     *
122
     * @param int|float $x_axis
123
     * @param int|float $y_axis
124
     * @param int|float $z_axis
125
     * @return \AframeVR\Interfaces\EntityInterface
126
     */
127 4
    public function position(float $x_axis = 0, float $y_axis = 0, float $z_axis = 0): EntityInterface
128
    {
129 4
        $this->attr('Position')->positionX($x_axis);
130 4
        $this->attr('Position')->positionY($y_axis);
131 4
        $this->attr('Position')->positionZ($z_axis);
132 4
        return $this;
133
    }
134
135
    /**
136
     * Rotation component
137
     *
138
     * All entities inherently have the rotation component.
139
     *
140
     * @param int|float $roll
141
     * @param int|float $pitch
142
     * @param int|float $yaw
143
     * @return \AframeVR\Interfaces\EntityInterface
144
     */
145 4
    public function rotation(float $roll = 0, float $pitch = 0, float $yaw = 0): EntityInterface
146
    {
147 4
        $this->attr('Rotation')->roll($roll);
148 4
        $this->attr('Rotation')->pitch($pitch);
149 4
        $this->attr('Rotation')->yaw($yaw);
150 4
        return $this;
151
    }
152
153
    /**
154
     * Scale component
155
     *
156
     * All entities inherently have the scale component.
157
     *
158
     * @param int|float $scale_x
159
     * @param int|float $scale_y
160
     * @param int|float $scale_z
161
     * @return \AframeVR\Interfaces\EntityInterface
162
     */
163 8
    public function scale(float $scale_x = 1, float $scale_y = 1, float $scale_z = 1): EntityInterface
164
    {
165 8
        $this->attr('Scale')->scaleX($scale_x);
166 8
        $this->attr('Scale')->scaleY($scale_y);
167 8
        $this->attr('Scale')->scaleZ($scale_z);
168 8
        return $this;
169
    }
170
171
    /**
172
     * Animations
173
     *
174
     * @param mixed $name
175
     * @return \AframeVR\Interfaces\AnimationInterface
176
     */
177 2
    public function animation($name = '0'): AnimationInterface
178
    {
179 2
        return $this->animations[$name] ?? $this->animations[$name] = new Animation();
180
    }
181
182
    /**
183
     * Set mixin attribute
184
     *
185
     * @param string $id
186
     * @return \AframeVR\Core\Entity
187
     */
188 1
    public function mixin(string $id)
189
    {
190 1
        $this->attr('mixin', $id);
191 1
        return $this;
192
    }
193
194
    /**
195
     * Load component for this entity or set it's attr
196
     *
197
     * @param string $component_name
198
     * @param null|mixed $attr_data
199
     * @throws \AframeVR\Core\Exceptions\BadComponentCallException
200
     * @return object|null
201
     */
202 82
    public function attr(string $component_name, $attr_data = null)
203
    {
204 82
        if(!is_null($attr_data)) {
205 82
            $this->attrs[$component_name] = $attr_data;
206 82
            return $this;
207
        }
208 82
        if (! array_key_exists($component_name, $this->components)) {
209 82
            $component = sprintf('\AframeVR\Core\Components\%s\%sComponent', ucfirst($component_name),
210
                ucfirst($component_name));
211 82
            if (class_exists($component)) {
212 82
                $this->components[$component_name] = new $component();
213
            } else {
214 1
                throw new BadComponentCallException($component_name);
215
            }
216
        }
217
218 82
        return $this->components[$component_name] ?? null;
219
    }
220
221
    /**
222
     * Handle entity components
223
     *
224
     * Since we might need to customize these to have
225
     * custom components loaded as $this->methosd aswell therefore
226
     * we have these placeholder magic methods here
227
     *
228
     * @param string $component_name
229
     * @param array $args
230
     */
231 30
    public function __call(string $component_name, array $args)
232
    {
233 30
        return $this->attr($component_name, $args[0] ?? null);
234
    }
235
236
    /**
237
     * Create and add DOM element of the entity
238
     *
239
     * @param \DOMDocument $aframe_dom
240
     * @return \DOMElement
241
     */
242 14
    public function domElement(\DOMDocument &$aframe_dom): DOMElement
243
    {
244 14
        $a_entity = $aframe_dom->createElement('a-entity');
245
246 14
        $this->appendAttributes($a_entity);
247
248 14
        foreach ($this->components as $component) {
249
            /*
250
             * Check does component has any attributes to add to DOM element.
251
             * default attributes most of cases are ommited so we might not have any attributes to add
252
             */
253 14
            if ($component->hasDOMAttributes())
254 14
                $a_entity->setAttributeNode($component->getDOMAttr());
255
        }
256
257 14
        $this->appendChildren($aframe_dom, $a_entity);
258 14
        $this->appendAnimations($aframe_dom, $a_entity);
259 14
        return $a_entity;
260
    }
261
262
    /**
263
     * Append DOM attributes no set by components
264
     *
265
     * @param \DOMElement $a_entity
266
     */
267 14
    private function appendAttributes(\DOMElement &$a_entity)
268
    {
269 14
        foreach ($this->attrs as $attr => $val) {
270 14
            if(is_bool($val))
271 1
                $val = $val ? '' : 'false';
272 14
            $this->setAttribute($a_entity, $attr, $val);
273
        }
274 14
    }
275
276 14
    private function setAttribute(&$a_entity, $attr, $val)
277
    {
278 14
        if ($attr === 'id' && is_numeric($val))
279 5
            return;
280
281 12
        $a_entity->setAttribute($attr, $val);
282 12
    }
283
284
    /**
285
     * Append childern to entities DOM element
286
     *
287
     * @param \DOMDocument $aframe_dom
288
     * @param \DOMElement $a_entity
289
     */
290 14
    private function appendChildren(\DOMDocument &$aframe_dom, \DOMElement &$a_entity)
291
    {
292 14
        if ($this->childrenFactory instanceof EntityChildrenFactory) {
293 3
            foreach ($this->childrenFactory->getChildren() as $child) {
294 3
                $this->addFormatComment($aframe_dom, $a_entity, "\n\t");
295 3
                $a_entity->appendChild($child->domElement($aframe_dom));
296 3
                $this->addFormatComment($aframe_dom, $a_entity, '');
297
            }
298
        }
299 14
    }
300
301
    /**
302
     * Append childern to entities DOM element
303
     *
304
     * @param \DOMDocument $aframe_dom
305
     * @param \DOMElement $a_entity
306
     */
307 14
    private function appendAnimations(\DOMDocument &$aframe_dom, \DOMElement &$a_entity)
308
    {
309 14
        foreach ($this->animations as $animations) {
310 1
            $this->addFormatComment($aframe_dom, $a_entity, "\n\t");
311 1
            $a_entity->appendChild($animations->domElement($aframe_dom));
312 1
            $this->addFormatComment($aframe_dom, $a_entity, '');
313
        }
314 14
    }
315
316
    /**
317
     * Add format comment
318
     *
319
     * @param \DOMDocument $aframe_dom
320
     * @param \DOMElement $a_entity
321
     * @param string $content
322
     */
323 4
    private function addFormatComment(\DOMDocument &$aframe_dom, \DOMElement &$a_entity, string $content)
324
    {
325 4
        if ($aframe_dom->formatOutput) {
326 1
            $com = $aframe_dom->createComment($content);
327 1
            $a_entity->appendChild($com);
328
        }
329 4
    }
330
}
331