System_Renderer class
class System_Renderer extends EntityProcessingSystem {
final CanvasRenderingContext2D _gVisible;
final CanvasRenderingContext2D _g;
ComponentMapper<Transform> _transformMapper;
ComponentMapper<Drawable> _drawMapper;
var _w = 0;
var _h = 0;
var _dpr = 1.0;
/// [_areaEntity] temp variable use fill by [Drawable.draw] to give the modified
/// area, it is an area with center at (0.0, 0.0)
Vector2 _areaEntity = new Vector2(0.0, 0.0);
/// _areaEntities sum of the _areaEntity in original state.
/// TODO optim : use _areaEntity and _areaEntities to clear and to update offscreen canvas
//vec4 _areaEntities = new vec4(0.0, 0.0);
var translateX = 0.0;
var translateY = 0.0;
var _scale = 1.0;
var _scaleI = 1.0;
get scale => _scale / _dpr;
set scale(v) {
_scale = v * _dpr;
_scaleI = 1 / _scale;
}
System_Renderer(canvas) :
super(Aspect.getAspectForAllOf([Drawable])),
_gVisible = canvas.context2D,
_g = new CanvasElement().context2D
;
void initialize(){
_drawMapper = new ComponentMapper<Drawable>(Drawable, world);
_transformMapper = new ComponentMapper<Transform>(Transform, world);
_initCanvasDimension();
}
void _initCanvasDimension() {
// to avoid scale and blur
// canvas dimensions
var canvasV = _gVisible.canvas;
var s = scale;
_dpr = window.devicePixelRatio; // retina
scale = s;
_w = (_dpr * canvasV.clientWidth).round();//parseInt(canvas.style.width);
_h = (_dpr * canvasV.clientHeight).round(); //parseInt(canvas.style.height);
canvasV.width = _w;
canvasV.height = _h;
_gVisible.scale(_dpr, _dpr);
_g.canvas.width = _w;
_g.canvas.height = _h;
}
void begin() {
//TODO use a viewport (translation, rotation, scale);
_g.save();
}
void processEntity(Entity entity) {
_g.translate(translateX, translateY);
if (_scale != 1.0) _g.scale(_scale, _scale);
var d = _drawMapper.get(entity);
var tf = _transformMapper.getSafe(entity);
if (tf != null) {
_g.translate(tf.position3d.x.toInt(), tf.position3d.y.toInt());
_g.rotate(tf.rotation3d.z);
_g.scale(tf.scale3d.x, tf.scale3d.y);
}
_areaEntity.x = 0.0;
_areaEntity.y = 0.0;
d.draw(_g, entity, _areaEntity);
if (tf != null) {
_g.scale(1/tf.scale3d.x, 1/tf.scale3d.y);
_g.rotate(-tf.rotation3d.z);
_g.translate(-tf.position3d.x.toInt(), -tf.position3d.y.toInt());
}
if (_scale != 1.0) _g.scale(_scaleI, _scaleI);
_g.translate(- translateX, - translateY);
_g.restore();
}
void end() {
_g.restore();
_gVisible.clearRect(0, 0, _w, _h);
_gVisible.drawImage(_g.canvas, 0, 0);
_g.clearRect(0, 0, _w, _h);
}
}
Extends
EntitySystem > EntityProcessingSystem > System_Renderer
Constructors
new System_Renderer(canvas) #
Create a new EntityProcessingSystem. It requires at least one component.
System_Renderer(canvas) : super(Aspect.getAspectForAllOf([Drawable])), _gVisible = canvas.context2D, _g = new CanvasElement().context2D ;
Properties
var scale #
get scale => _scale / _dpr;
set scale(v) {
_scale = v * _dpr;
_scaleI = 1 / _scale;
}
var translateX #
areaEntities sum of the areaEntity in original state. TODO optim : use areaEntity and areaEntities to clear and to update offscreen canvas
var translateX = 0.0
var translateY #
var translateY = 0.0
Methods
void begin() #
Called before processing of entities begins.
void begin() {
//TODO use a viewport (translation, rotation, scale);
_g.save();
}
bool checkProcessing() #
Returns true if the system should be processed, false if not.
bool checkProcessing() => true;
void deleted(Entity e) #
void deleted(Entity e) {
if (_contains(e)) {
_removeFromSystem(e);
}
}
void disabled(Entity e) #
void disabled(Entity e) {
if (_contains(e)) {
_removeFromSystem(e);
}
}
void end() #
Called after the processing of entities ends.
void end() {
_g.restore();
_gVisible.clearRect(0, 0, _w, _h);
_gVisible.drawImage(_g.canvas, 0, 0);
_g.clearRect(0, 0, _w, _h);
}
void initialize() #
Override to implement code that gets executed when systems are initialized.
void initialize(){
_drawMapper = new ComponentMapper<Drawable>(Drawable, world);
_transformMapper = new ComponentMapper<Transform>(Transform, world);
_initCanvasDimension();
}
void inserted(Entity entity) #
Called if the system has received an entity it is interested in, e.g. created or a component was added to it.
void inserted(Entity entity) {}
void process() #
This is the only method that is supposed to be called from outside the library,
void process() {
if(checkProcessing()) {
begin();
processEntities(_actives.readOnly);
end();
}
}
void processEntities(ReadOnlyBag<Entity> entities) #
Any implementing entity system must implement this method and the logic to process the given entities of the system.
void processEntities(ReadOnlyBag<Entity> entities) => entities.forEach((entity) => processEntity(entity));
void processEntity(Entity entity) #
Process a entity this system is interested in.
void processEntity(Entity entity) {
_g.translate(translateX, translateY);
if (_scale != 1.0) _g.scale(_scale, _scale);
var d = _drawMapper.get(entity);
var tf = _transformMapper.getSafe(entity);
if (tf != null) {
_g.translate(tf.position3d.x.toInt(), tf.position3d.y.toInt());
_g.rotate(tf.rotation3d.z);
_g.scale(tf.scale3d.x, tf.scale3d.y);
}
_areaEntity.x = 0.0;
_areaEntity.y = 0.0;
d.draw(_g, entity, _areaEntity);
if (tf != null) {
_g.scale(1/tf.scale3d.x, 1/tf.scale3d.y);
_g.rotate(-tf.rotation3d.z);
_g.translate(-tf.position3d.x.toInt(), -tf.position3d.y.toInt());
}
if (_scale != 1.0) _g.scale(_scaleI, _scaleI);
_g.translate(- translateX, - translateY);
_g.restore();
}
void removed(Entity entity) #
Called if an entity was removed from this system, e.g. deleted or had one of it's components removed.
void removed(Entity entity) {}