1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2025-02-18 14:36:44 -05:00
OpenDiablo2/d2core/d2systems/scene_shape_system.go
gravestench c52c6648dd refactor of d2components, d2systems
Systems now place all of their component factories into a `Components`
member. This improves code readability and makes it clear when we are
dealing specifically with ecs components.

The concrete ComponentFactory instances now have `Add` and `Get`
methods (as opposed to `AddAlpha` or `GetAlpha`). This enforces naming
of component factories as to avoid collisions when embedded in a struct
with other components.

Also, the ComponentFactory interface is embedded directly into the
concrete component factory without a name.
2020-12-08 18:45:00 -08:00

154 lines
4.1 KiB
Go

package d2systems
import (
"image/color"
"github.com/gravestench/akara"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2components"
)
// NewShapeSystem creates a new sprite factory which is intended
// to be embedded in the game object factory system.
func NewShapeSystem(b akara.BaseSystem, l *d2util.Logger) *ShapeSystem {
sys := &ShapeSystem{
Logger: l,
}
sys.BaseSystem = b
sys.World.AddSystem(sys)
return sys
}
// ShapeSystem is responsible for queueing sprites to be loaded (as spriteations),
// as well as binding the spriteation to a renderer if one is present (which generates the sprite surfaces).
type ShapeSystem struct {
akara.BaseSubscriberSystem
*d2util.Logger
RenderSystem *RenderSystem
Components struct {
Transform d2components.TransformFactory
Color d2components.ColorFactory
Rectangle d2components.RectangleFactory
Texture d2components.TextureFactory
Size d2components.SizeFactory
Origin d2components.OriginFactory
}
loadQueue spriteLoadQueue
shapesToRender *akara.Subscription
shapesToUpdate *akara.Subscription
}
// Init the sprite factory, injecting the necessary components
func (t *ShapeSystem) Init(world *akara.World) {
t.World = world
t.Debug("initializing sprite factory ...")
t.setupFactories()
t.setupSubscriptions()
t.loadQueue = make(spriteLoadQueue)
}
func (t *ShapeSystem) setupFactories() {
t.InjectComponent(&d2components.Color{}, &t.Components.Color.ComponentFactory)
t.InjectComponent(&d2components.Transform{}, &t.Components.Transform.ComponentFactory)
t.InjectComponent(&d2components.Texture{}, &t.Components.Texture.ComponentFactory)
t.InjectComponent(&d2components.Origin{}, &t.Components.Origin.ComponentFactory)
t.InjectComponent(&d2components.Size{}, &t.Components.Size.ComponentFactory)
t.InjectComponent(&d2components.Rectangle{}, &t.Components.Rectangle.ComponentFactory)
}
func (t *ShapeSystem) setupSubscriptions() {
shapesToRender := t.NewComponentFilter().
RequireOne(&d2components.Rectangle{}).
Require(&d2components.Texture{}).
Build()
shapesToUpdate := t.NewComponentFilter().
RequireOne(&d2components.Rectangle{}).
Require(&d2components.Transform{}, &d2components.Size{}).
Build()
t.shapesToRender = t.AddSubscription(shapesToRender)
t.shapesToUpdate = t.AddSubscription(shapesToUpdate)
}
// Update processes the load queue which attempting to create spriteations, as well as
// binding existing spriteations to a renderer if one is present.
func (t *ShapeSystem) Update() {
for _, id := range t.shapesToUpdate.GetEntities() {
t.updateShape(id)
}
for _, id := range t.shapesToRender.GetEntities() {
t.renderShape(id)
}
}
// ComponentFactory queues a sprite spriteation to be loaded
func (t *ShapeSystem) Rectangle(x, y, width, height int, color color.Color) akara.EID {
t.Debug("creating rectangle")
eid := t.NewEntity()
r := t.Components.Rectangle.Add(eid)
r.X, r.Y = float64(x), float64(y)
r.Width, r.Height = float64(width), float64(height)
c := t.Components.Color.Add(eid)
c.Color = color
texture := t.Components.Texture.Add(eid)
texture.Texture = t.RenderSystem.renderer.NewSurface(width, height)
texture.Texture.Clear(c.Color)
return eid
}
func (t *ShapeSystem) updateShape(eid akara.EID) {
transform, found := t.Components.Transform.Get(eid)
if !found {
return
}
size, found := t.Components.Size.Get(eid)
if !found {
return
}
texture, found := t.Components.Texture.Get(eid)
if !found || texture.Texture == nil {
return
}
rectangle, rectangleFound := t.Components.Rectangle.Get(eid)
if rectangleFound {
transform.Translation.X, transform.Translation.Y = rectangle.X, rectangle.Y
size.X, size.Y = rectangle.Width, rectangle.Height
tw, th := texture.Texture.GetSize()
if tw != int(size.X) || th != int(size.Y) {
texture.Texture.Renderer().NewSurface(int(size.X), int(size.Y))
}
}
}
func (t *ShapeSystem) renderShape(eid akara.EID) {
texture, found := t.Components.Texture.Get(eid)
if !found || texture.Texture == nil {
return
}
col, found := t.Components.Color.Get(eid)
if !found {
return
}
texture.Texture.Clear(col.Color)
}