Skip to content

Commit 6dad992

Browse files
committed
Add Entity.deleteIfExist and Entity.deleteManyIfExist
1 parent 59b8792 commit 6dad992

3 files changed

Lines changed: 221 additions & 0 deletions

File tree

doc/doc.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,9 @@ It may be useful if you have a drawing system:
283283
* [.add(ComponentType, ...args)](#Entity+add)[<code>Entity</code>](#Entity)
284284
* [.addMany(ComponentsType)](#Entity+addMany)[<code>Entity</code>](#Entity)
285285
* [.delete(ComponentType)](#Entity+delete)[<code>Entity</code>](#Entity)
286+
* [.deleteIfExist(ComponentType)](#Entity+deleteIfExist)[<code>Entity</code>](#Entity)
286287
* [.deleteMany(ComponentsType)](#Entity+deleteMany)[<code>Entity</code>](#Entity)
288+
* [.deleteManyIfExist(ComponentsType)](#Entity+deleteManyIfExist)[<code>Entity</code>](#Entity)
287289
* _static_
288290
* [.createWorld([ComponentsType])](#Entity.createWorld)[<code>Entity</code>](#Entity)
289291

@@ -491,6 +493,19 @@ found, an error will be thrown.
491493
| --- | --- | --- |
492494
| ComponentType | [<code>AComponent</code>](#AComponent) | Type of the component to delete |
493495

496+
<a name="Entity+deleteIfExist"></a>
497+
498+
### entity.deleteIfExist(ComponentType) ⇒ [<code>Entity</code>](#Entity)
499+
Delete a specific component from this entity. If the Component is not
500+
found, no error will be thrown.
501+
502+
**Kind**: instance method of [<code>Entity</code>](#Entity)
503+
**Returns**: [<code>Entity</code>](#Entity) - this entity (useful for chaining)
504+
505+
| Param | Type | Description |
506+
| --- | --- | --- |
507+
| ComponentType | [<code>AComponent</code>](#AComponent) | Type of the component to delete |
508+
494509
<a name="Entity+deleteMany"></a>
495510

496511
### entity.deleteMany(ComponentsType) ⇒ [<code>Entity</code>](#Entity)
@@ -504,6 +519,19 @@ an error will be thrown.
504519
| --- | --- | --- |
505520
| ComponentsType | [<code>Array.&lt;AComponent&gt;</code>](#AComponent) | Type of the components to delete |
506521

522+
<a name="Entity+deleteManyIfExist"></a>
523+
524+
### entity.deleteManyIfExist(ComponentsType) ⇒ [<code>Entity</code>](#Entity)
525+
Delete specific components from this entity. If a component is not found,
526+
no error will be thrown and no component will be deleted.
527+
528+
**Kind**: instance method of [<code>Entity</code>](#Entity)
529+
**Returns**: [<code>Entity</code>](#Entity) - this entity (useful for chaining)
530+
531+
| Param | Type | Description |
532+
| --- | --- | --- |
533+
| ComponentsType | [<code>Array.&lt;AComponent&gt;</code>](#AComponent) | Type of the components to delete |
534+
507535
<a name="Entity.createWorld"></a>
508536

509537
### Entity.createWorld([ComponentsType]) ⇒ [<code>Entity</code>](#Entity)

entity.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,9 +485,26 @@ class Entity extends EventEmitter
485485
return this;
486486
}
487487

488+
/**
489+
* Delete a specific component from this entity. If the Component is not
490+
* found, no error will be thrown.
491+
*
492+
* @param {AComponent} ComponentType Type of the component to delete
493+
* @return {Entity} this entity (useful for chaining)
494+
*/
495+
deleteIfExist(ComponentType)
496+
{
497+
if (this.has([ComponentType]))
498+
{
499+
return this.delete(ComponentType);
500+
}
501+
return this;
502+
}
503+
488504
/**
489505
* Delete specific components from this entity. If a component is not found,
490506
* an error will be thrown.
507+
*
491508
* @param {Array.<AComponent>} ComponentsType Type of the components to delete
492509
* @return {Entity} this entity (useful for chaining)
493510
*/
@@ -502,6 +519,22 @@ class Entity extends EventEmitter
502519
return this;
503520
}
504521

522+
/**
523+
* Delete specific components from this entity. If a component is not found,
524+
* no error will be thrown and no component will be deleted.
525+
*
526+
* @param {Array.<AComponent>} ComponentsType Type of the components to delete
527+
* @return {Entity} this entity (useful for chaining)
528+
*/
529+
deleteManyIfExist(ComponentsType)
530+
{
531+
if (this.has(ComponentsType))
532+
{
533+
return this.deleteMany(ComponentsType);
534+
}
535+
return this;
536+
}
537+
505538
/**
506539
* Assert (eg. throw) that the given component type is valid.
507540
*

test/entity_and_acomponent.js

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,78 @@ describe('Integration between Entity and AComponent', function()
557557
});
558558
});
559559

560+
describe('Entity.deleteIfExist', function()
561+
{
562+
it('should delete the component', function()
563+
{
564+
const e = Entity.createWorld();
565+
e.add(PositionComponent);
566+
expect(e.has([PositionComponent])).to.be.true;
567+
expect(e.position.x).to.equal(0);
568+
569+
e.deleteIfExist(PositionComponent);
570+
expect(e.has([PositionComponent])).to.be.false;
571+
expect(e.position).to.be.undefined;
572+
});
573+
574+
it('should delete the component but others should still be available', function()
575+
{
576+
const e = Entity.createWorld();
577+
e.addMany([PositionComponent, VelocityComponent]);
578+
expect(e.has([PositionComponent])).to.be.true;
579+
expect(e.position.x).to.equal(0);
580+
expect(e.has([VelocityComponent])).to.be.true;
581+
expect(e.velocity.velocity).equal(0);
582+
583+
e.deleteIfExist(PositionComponent);
584+
expect(e.has([PositionComponent])).to.be.false;
585+
expect(e.position).to.be.undefined;
586+
expect(e.has([VelocityComponent])).to.be.true;
587+
expect(e.velocity.velocity).equal(0);
588+
});
589+
590+
it('should delete the component when given a super class', function()
591+
{
592+
const e = Entity.createWorld();
593+
e.add(SpriteComponent);
594+
expect(e.has([DrawableComponent])).to.be.true;
595+
e.deleteIfExist(DrawableComponent);
596+
expect(e.has([DrawableComponent])).to.be.false;
597+
});
598+
599+
it('should return this', function()
600+
{
601+
const e = Entity.createWorld();
602+
e.add(SpriteComponent);
603+
expect(e.deleteIfExist(SpriteComponent)).to.equal(e);
604+
});
605+
606+
it('should not throw if component is not available', function()
607+
{
608+
const e = Entity.createWorld();
609+
610+
e.deleteIfExist(PositionComponent);
611+
});
612+
613+
it('should not throw on double-delete', function()
614+
{
615+
const e = Entity.createWorld();
616+
e.add(PositionComponent);
617+
e.deleteIfExist(PositionComponent);
618+
e.deleteIfExist(PositionComponent);
619+
});
620+
621+
it('should throw if pass AComponent as it is a global super class', function()
622+
{
623+
const e = Entity.createWorld();
624+
625+
expect(() =>
626+
{
627+
e.deleteIfExist(AComponent);
628+
}).to.throw();
629+
});
630+
});
631+
560632
describe('Entity.deleteMany', function()
561633
{
562634
it('should delete all components', function()
@@ -650,6 +722,94 @@ describe('Integration between Entity and AComponent', function()
650722
});
651723
});
652724

725+
describe('Entity.deleteManyIfExist', function()
726+
{
727+
it('should delete all components', function()
728+
{
729+
const e = Entity.createWorld();
730+
e.addMany([PositionComponent, VelocityComponent]);
731+
expect(e.has([PositionComponent])).to.be.true;
732+
expect(e.position.x).to.equal(0);
733+
expect(e.has([VelocityComponent])).to.be.true;
734+
expect(e.velocity.velocity).equal(0);
735+
736+
e.deleteManyIfExist([PositionComponent, VelocityComponent]);
737+
expect(e.has([PositionComponent])).to.be.false;
738+
expect(e.has([VelocityComponent])).to.be.false;
739+
});
740+
741+
it('should do nothing on passing empty-array', function()
742+
{
743+
const e = Entity.createWorld();
744+
e.addMany([PositionComponent, VelocityComponent]);
745+
expect(e.has([PositionComponent])).to.be.true;
746+
expect(e.position.x).to.equal(0);
747+
expect(e.has([VelocityComponent])).to.be.true;
748+
expect(e.velocity.velocity).equal(0);
749+
750+
e.deleteManyIfExist([]);
751+
expect(e.has([PositionComponent])).to.be.true;
752+
expect(e.position.x).to.equal(0);
753+
expect(e.has([VelocityComponent])).to.be.true;
754+
expect(e.velocity.velocity).equal(0);
755+
});
756+
757+
it('should not throw if at least one component is not available and delete nothing', function()
758+
{
759+
const e1 = Entity.createWorld();
760+
e1.add(PositionComponent);
761+
e1.deleteManyIfExist([PositionComponent, VelocityComponent]);
762+
expect(e1.has([PositionComponent])).to.be.true;
763+
764+
const e2 = Entity.createWorld();
765+
e2.deleteManyIfExist([PositionComponent, VelocityComponent]);
766+
});
767+
768+
it('should delete the component when given a super class', function()
769+
{
770+
const e = Entity.createWorld();
771+
e.add(SpriteComponent);
772+
expect(e.has([DrawableComponent])).to.be.true;
773+
e.deleteManyIfExist([DrawableComponent]);
774+
expect(e.has([DrawableComponent])).to.be.false;
775+
});
776+
777+
it('should return this', function()
778+
{
779+
const e = Entity.createWorld();
780+
e.add(SpriteComponent);
781+
expect(e.deleteManyIfExist([SpriteComponent])).to.equal(e);
782+
});
783+
784+
it('should throw on passing non-array', function()
785+
{
786+
const e = Entity.createWorld();
787+
expect(() =>
788+
{
789+
e.deleteManyIfExist(42);
790+
}).to.throw();
791+
});
792+
793+
it('should throw on passing non-components in array', function()
794+
{
795+
const e = Entity.createWorld();
796+
expect(() =>
797+
{
798+
e.deleteManyIfExist([42]);
799+
}).to.throw();
800+
});
801+
802+
it('should throw if pass AComponent as it is a global super class', function()
803+
{
804+
const e = Entity.createWorld();
805+
806+
expect(() =>
807+
{
808+
e.deleteManyIfExist([AComponent]);
809+
}).to.throw();
810+
});
811+
});
812+
653813
describe('#destructor', function()
654814
{
655815
it('should be called on destructing entity with components', function()

0 commit comments

Comments
 (0)