Completed
Push — 0.3.x ( 7c682c...c37298 )
by Marko
02:50
created

Entity::appendAnimations()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 8
ccs 6
cts 6
cp 1
rs 9.4285
cc 2
eloc 5
nc 2
nop 2
crap 2
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\Animation;
33
use \AframeVR\Core\Helpers\EntityChildrenFactory;
34
use \DOMElement;
35
use \Closure;
36
37
class Entity implements EntityInterface
38
{
39
    /**
40
     * Array of used components
41
     *
42
     * @var array
43
     */
44
    protected $components = array();
45
    
46
    /**
47
     * Array of used animations
48
     *
49
     * @var array
50
     */
51
    protected $animations = array();
52
    
53
    /**
54
     * Dom element attributes
55
     *
56
     * @var unknown
57
     */
58
    protected $attrs = array();
59
    
60
    /**
61
     * Children Factory
62
     *
63
     * @var EntityChildrenFactory
64
     */
65
    protected $childrenFactory;
66
    
67
    /**
68
     * Indent used when rendering formated outout
69
     *
70
     * @var unknown
71
     */
72
    private $indentation = 0;
73
74
    /**
75
     * Constructor
76
     *
77
     * @param string $id            
78
     */
79 76
    public function __construct(string $id = 'untitled')
80
    {
81 76
        $this->attr('id', $id);
82
        
83
        /* Components which All entities inherently have */
84 76
        $this->component('Position');
85 76
        $this->component('Rotation');
86 76
        $this->component('Scale');
87
        
88
        /* Extending entity components and init */
89 76
        $this->init();
90
        
91
        /* Extending entity defaults */
92 76
        $this->defaults();
93 76
    }
94
95 45
    public function init()
96
    {
97 45
    }
98
99 45
    public function defaults()
100
    {
101 45
    }
102
103
    /**
104
     * Set DOM attributes
105
     *
106
     * @param string $attr            
107
     * @param string $val            
108
     * @return void
109
     */
110 76
    public function attr(string $attr, string $val)
111
    {
112 76
        $this->attrs[$attr] = $val;
113 76
    }
114
115
    /**
116
     * Child entity / primitive
117
     *
118
     * @return EntityChildrenFactory
119
     */
120 7
    public function child(): EntityChildrenFactory
121
    {
122 7
        return $this->childrenFactory ?? $this->childrenFactory = new EntityChildrenFactory();
123
    }
124
125
    /**
126
     * Position component
127
     *
128
     * All entities inherently have the position component.
129
     *
130
     * @param int|float $x_axis            
131
     * @param int|float $y_axis            
132
     * @param int|float $z_axis            
133
     * @return \AframeVR\Core\Entity
134
     */
135 15
    public function position(float $x_axis = 0, float $y_axis = 0, float $z_axis = 0): Entity
136
    {
137 15
        $this->component('Position')->positionX($x_axis);
138 15
        $this->component('Position')->positionY($y_axis);
139 15
        $this->component('Position')->positionZ($z_axis);
140 15
        return $this;
141
    }
142
143
    /**
144
     * Rotation component
145
     *
146
     * All entities inherently have the rotation component.
147
     *
148
     * @param int|float $roll            
149
     * @param int|float $pitch            
150
     * @param int|float $yaw            
151
     * @return \AframeVR\Core\Entity
152
     */
153 14
    public function rotation(float $roll = 0, float $pitch = 0, float $yaw = 0): Entity
154
    {
155 14
        $this->component('Rotation')->roll($roll);
156 14
        $this->component('Rotation')->pitch($pitch);
157 14
        $this->component('Rotation')->yaw($yaw);
158 14
        return $this;
159
    }
160
161
    /**
162
     * Scale component
163
     *
164
     * All entities inherently have the scale component.
165
     *
166
     * @param int|float $scale_x            
167
     * @param int|float $scale_y            
168
     * @param int|float $scale_z            
169
     * @return \AframeVR\Core\Entity
170
     */
171 9
    public function scale(float $scale_x = 1, float $scale_y = 1, float $scale_z = 1): Entity
172
    {
173 9
        $this->component('Scale')->scaleX($scale_x);
174 9
        $this->component('Scale')->scaleY($scale_y);
175 9
        $this->component('Scale')->scaleZ($scale_z);
176 9
        return $this;
177
    }
178
179
    /**
180
     * Animations
181
     *
182
     * @param mixed $name            
183
     * @return \AframeVR\Interfaces\AnimationInterface
184
     */
185 5
    public function animation($name = 'untitled'): AnimationInterface
186
    {
187 5
        return $this->animations[$name] ?? $this->animations[$name] = new Animation();
188
    }
189
190
    /**
191
     * Set mixin attribute
192
     *
193
     * @param string $id            
194
     * @return \AframeVR\Core\Entity
195
     */
196 3
    public function mixin(string $id)
197
    {
198 3
        $this->attr('mixin', $id);
199 3
        return $this;
200
    }
201
202
    /**
203
     * Load component for this entity
204
     *
205
     * @param string $component_name            
206
     * @throws \AframeVR\Core\Exceptions\BadComponentCallException
207
     * @return object|null
208
     */
209 76
    public function component(string $component_name)
210
    {
211 76
        if (! array_key_exists($component_name, $this->components)) {
212 76
            $component = sprintf('\AframeVR\Core\Components\%s\%sComponent', ucfirst($component_name), 
213
                ucfirst($component_name));
214 76
            if (class_exists($component)) {
215 76
                $this->components[$component_name] = new $component();
216
            } else {
217 1
                throw new BadComponentCallException($component_name);
218
            }
219
        }
220
        
221 76
        return $this->components[$component_name] ?? null;
222
    }
223
224
    /**
225
     * Handle entity components
226
     *
227
     * Since we might need to customize these to have
228
     * custom components loaded as $this->methosd aswell therefore
229
     * we have these placeholder magic methods here
230
     *
231
     * @param string $component_name            
232
     * @param array $args            
233
     */
234 21 View Code Duplication
    public function __call(string $component_name, array $args)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
235
    {
236 21
        if (! method_exists($this, $component_name)) {
237 21
            $this->{$component_name} = Closure::bind(
238 21
                function () use ($component_name) {
239 21
                    return $this->component($component_name);
240 21
                }, $this, get_class());
241
        }
242
        
243 21
        return call_user_func($this->{$component_name}, $args);
244
    }
245
246
    /**
247
     * Create and add DOM element of the entity
248
     *
249
     * @param \DOMDocument $aframe_dom            
250
     * @return \DOMElement
251
     */
252 4
    public function domElement(\DOMDocument &$aframe_dom): DOMElement
253
    {
254 4
        $a_entity = $aframe_dom->createElement('a-entity');
255
        
256 4
        $this->appendAttributes($a_entity);
257
        
258 4
        foreach ($this->components as $component) {
259
            /*
260
             * Check does component has any attributes to add to DOM element.
261
             * default attributes most of cases are ommited so we might not have any attributes to add
262
             */
263 4
            if ($component->hasDOMAttributes())
264 4
                $a_entity->setAttributeNode($component->getDOMAttr());
265
        }
266
        
267 4
        $this->appendChildren($aframe_dom, $a_entity);
268 4
        $this->appendAnimations($aframe_dom, $a_entity);
269 4
        return $a_entity;
270
    }
271
272
    /**
273
     * Append DOM attributes no set by components
274
     *
275
     * @param \DOMElement $a_entity            
276
     */
277 4
    private function appendAttributes(\DOMElement &$a_entity)
278
    {
279 4
        foreach ($this->attrs as $attr => $val) {
280 4
            $this->setAttribute($a_entity, $attr, $val);
281
        }
282 4
    }
283
284 4
    private function setAttribute(&$a_entity, $attr, $val)
285
    {
286 4
        if ($attr === 'id' && ($val === 'untitled' || is_numeric($val)))
287 4
            return;
288
        
289 2
        $a_entity->setAttribute($attr, $val);
290 2
    }
291
292
    /**
293
     * Append childern to entities DOM element
294
     *
295
     * @param \DOMDocument $aframe_dom            
296
     * @param \DOMElement $a_entity            
297
     */
298 4
    private function appendChildren(\DOMDocument &$aframe_dom, \DOMElement &$a_entity)
299
    {
300 4
        if ($this->childrenFactory instanceof EntityChildrenFactory) {
301 2
            foreach ($this->childrenFactory->getChildern() as $child) {
302 2
                $this->addFormatComment($aframe_dom, $a_entity, "\n\t");
303 2
                $a_entity->appendChild($child->domElement($aframe_dom));
304 2
                $this->addFormatComment($aframe_dom, $a_entity, '');
305
            }
306
        }
307 4
    }
308
309
    /**
310
     * Append childern to entities DOM element
311
     *
312
     * @param \DOMDocument $aframe_dom            
313
     * @param \DOMElement $a_entity            
314
     */
315 4
    private function appendAnimations(\DOMDocument &$aframe_dom, \DOMElement &$a_entity)
316
    {
317 4
        foreach ($this->animations as $animations) {
318 2
            $this->addFormatComment($aframe_dom, $a_entity, "\n\t");
319 2
            $a_entity->appendChild($animations->domElement($aframe_dom));
320 2
            $this->addFormatComment($aframe_dom, $a_entity, '');
321
        }
322 4
    }
323
324
    /**
325
     * Add format comment
326
     *
327
     * @param \DOMDocument $aframe_dom            
328
     * @param \DOMElement $a_entity            
329
     * @param string $content            
330
     */
331 2
    private function addFormatComment(\DOMDocument &$aframe_dom, \DOMElement &$a_entity, string $content)
332
    {
333 2
        if ($aframe_dom->formatOutput) {
334 2
            $com = $aframe_dom->createComment($content);
335 2
            $a_entity->appendChild($com);
336
        }
337 2
    }
338
}
339