Completed
Push — master ( f87c77...be4ea7 )
by Marko
02:11
created

Entity::rotation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

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