From 8417284b1b79565cf5dfbe9b78859a6d33f40ddf Mon Sep 17 00:00:00 2001 From: Isaac Date: Thu, 30 Jul 2020 21:46:42 -0400 Subject: [PATCH 1/2] feat: Initial rendering support via ECS --- .../org/destinationsol/SolApplication.java | 9 ++- .../java/org/destinationsol/game/SolGame.java | 6 ++ .../game/drawables/RectSprite.java | 7 +- .../rendering/RenderableElement.java | 59 ++++++++++++++++ .../rendering/components/Invisible.java | 29 ++++++++ .../rendering/components/Renderable.java | 41 +++++++++++ .../rendering/events/RenderEvent.java | 26 +++++++ .../rendering/systems/RenderingSystem.java | 68 +++++++++++++++++++ 8 files changed, 243 insertions(+), 2 deletions(-) create mode 100644 engine/src/main/java/org/destinationsol/rendering/RenderableElement.java create mode 100644 engine/src/main/java/org/destinationsol/rendering/components/Invisible.java create mode 100644 engine/src/main/java/org/destinationsol/rendering/components/Renderable.java create mode 100644 engine/src/main/java/org/destinationsol/rendering/events/RenderEvent.java create mode 100644 engine/src/main/java/org/destinationsol/rendering/systems/RenderingSystem.java diff --git a/engine/src/main/java/org/destinationsol/SolApplication.java b/engine/src/main/java/org/destinationsol/SolApplication.java index db6f2bb2b..6bdc1106d 100644 --- a/engine/src/main/java/org/destinationsol/SolApplication.java +++ b/engine/src/main/java/org/destinationsol/SolApplication.java @@ -26,11 +26,12 @@ import org.destinationsol.assets.sound.OggSoundManager; import org.destinationsol.common.SolColor; import org.destinationsol.common.SolMath; +import org.destinationsol.rendering.components.Renderable; +import org.destinationsol.rendering.events.RenderEvent; import org.destinationsol.entitysystem.ComponentSystemManager; import org.destinationsol.entitysystem.EntitySystemManager; import org.destinationsol.entitysystem.SerialisationManager; import org.destinationsol.game.DebugOptions; -import org.destinationsol.game.FactionInfo; import org.destinationsol.game.ObjectManager; import org.destinationsol.game.SaveManager; import org.destinationsol.game.SolGame; @@ -40,6 +41,7 @@ import org.destinationsol.game.context.internal.ContextImpl; import org.destinationsol.game.item.ItemManager; import org.destinationsol.game.item.LootBuilder; +import org.destinationsol.location.components.Position; import org.destinationsol.menu.MenuScreens; import org.destinationsol.menu.background.MenuBackgroundManager; import org.destinationsol.modules.ModuleManager; @@ -230,8 +232,13 @@ private void update() { private void draw() { Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); commonDrawer.begin(); + if (solGame != null) { + solGame.draw(); + + //This event causes each entity with a `Graphics` component to be rendered onscreen + entitySystemManager.sendEvent(new RenderEvent(), new Renderable(), new Position()); } uiDrawer.updateMtx(); inputManager.draw(uiDrawer, this); diff --git a/engine/src/main/java/org/destinationsol/game/SolGame.java b/engine/src/main/java/org/destinationsol/game/SolGame.java index 8abd2e882..d233518b6 100644 --- a/engine/src/main/java/org/destinationsol/game/SolGame.java +++ b/engine/src/main/java/org/destinationsol/game/SolGame.java @@ -25,6 +25,7 @@ import org.destinationsol.assets.sound.OggSoundManager; import org.destinationsol.assets.sound.SpecialSounds; import org.destinationsol.common.DebugCol; +import org.destinationsol.common.In; import org.destinationsol.common.SolException; import org.destinationsol.common.SolMath; import org.destinationsol.common.SolRandom; @@ -60,6 +61,7 @@ import org.destinationsol.ui.TutorialManager; import org.destinationsol.ui.UiDrawer; import org.destinationsol.ui.Waypoint; +import org.destinationsol.util.InjectionHelper; import org.terasology.gestalt.entitysystem.entity.EntityRef; import java.util.ArrayList; @@ -107,6 +109,8 @@ public class SolGame { private SortedMap> onPausedUpdateSystems; private SortedMap> updateSystems; + @In + private EntitySystemManager entitySystemManager; public SolGame(String shipName, boolean isTutorial, boolean isNewGame, CommonDrawer commonDrawer, Context context, WorldConfig worldConfig) { @@ -117,6 +121,7 @@ public SolGame(String shipName, boolean isTutorial, boolean isNewGame, CommonDra solApplication = context.get(SolApplication.class); ModuleManager moduleManager = context.get(ModuleManager.class); GameDrawer drawer = new GameDrawer(commonDrawer); + context.put(GameDrawer.class, drawer); gameColors = new GameColors(); soundManager = solApplication.getSoundManager(); specialSounds = new SpecialSounds(soundManager); @@ -177,6 +182,7 @@ public SolGame(String shipName, boolean isTutorial, boolean isNewGame, CommonDra } RegisterUpdateSystem registerAnnotation = updateSystemClass.getDeclaredAnnotation(RegisterUpdateSystem.class); UpdateAwareSystem system = (UpdateAwareSystem) updateSystemClass.newInstance(); + InjectionHelper.inject(system, context); if (!registerAnnotation.paused()) { if (!updateSystems.containsKey(registerAnnotation.priority())) { ArrayList systems = new ArrayList(); diff --git a/engine/src/main/java/org/destinationsol/game/drawables/RectSprite.java b/engine/src/main/java/org/destinationsol/game/drawables/RectSprite.java index b7d9cad74..505a5fae4 100644 --- a/engine/src/main/java/org/destinationsol/game/drawables/RectSprite.java +++ b/engine/src/main/java/org/destinationsol/game/drawables/RectSprite.java @@ -70,8 +70,13 @@ public RectSprite(TextureAtlas.AtlasRegion tex, float texSz, float origPercX, fl isAdditive = additive; } + /** + * Sets the larger of the dimensions of the texture to the passed-in size, maintaining proportions and + * recalculating other fields as needed to fit. + * @param textureSize the new size for the sprite + */ public void setTextureSize(float textureSize) { - textureSize /= level.depth; + textureSize /= level.depth; // Scales the textureSize for background objects int dimensionsRatio = texture.getRegionWidth() / texture.getRegionHeight(); if (dimensionsRatio > 1) { textureSizeX = textureSize; diff --git a/engine/src/main/java/org/destinationsol/rendering/RenderableElement.java b/engine/src/main/java/org/destinationsol/rendering/RenderableElement.java new file mode 100644 index 000000000..2b8de3b82 --- /dev/null +++ b/engine/src/main/java/org/destinationsol/rendering/RenderableElement.java @@ -0,0 +1,59 @@ +/* + * Copyright 2020 The Terasology Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.destinationsol.rendering; + +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.math.Vector2; +import org.destinationsol.game.drawables.DrawableLevel; + +/** + * Contains a {@link TextureAtlas.AtlasRegion} (an image), along with information about how it should be drawn. + */ +public class RenderableElement { + + /** Represents the image of this element. */ + public TextureAtlas.AtlasRegion texture; + + /** The width of the texture when drawn. */ + public float width; + + /** The height of the texture when drawn. */ + public float height; + + /** Represents the depth at which this element renders, as well as its logical grouping. */ + public DrawableLevel drawableLevel; + + /** Represents the spatial offset of this element from the entity that it is associated with. */ + public Vector2 relativePosition; + + /** Represents the rotational offset of this element from the entity that it is associated with. */ + public float relativeAngle; + + /** The tint that the texture should be given. */ + public Color tint; + + public void copy(RenderableElement other) { + this.texture = other.texture; + this.drawableLevel = other.drawableLevel; + this.relativePosition = other.relativePosition.cpy(); + this.relativeAngle = other.relativeAngle; + this.width = other.width; + this.height = other.height; + this.tint = other.tint; + } +} + diff --git a/engine/src/main/java/org/destinationsol/rendering/components/Invisible.java b/engine/src/main/java/org/destinationsol/rendering/components/Invisible.java new file mode 100644 index 000000000..7bc0a814e --- /dev/null +++ b/engine/src/main/java/org/destinationsol/rendering/components/Invisible.java @@ -0,0 +1,29 @@ +/* + * Copyright 2020 The Terasology Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.destinationsol.rendering.components; + +import org.destinationsol.rendering.systems.RenderingSystem; +import org.terasology.gestalt.entitysystem.component.Component; + +/** + * Denotes that the object should not be drawn by the {@link RenderingSystem}. + */ +public class Invisible implements Component { + @Override + public void copy(Invisible other) { + + } +} diff --git a/engine/src/main/java/org/destinationsol/rendering/components/Renderable.java b/engine/src/main/java/org/destinationsol/rendering/components/Renderable.java new file mode 100644 index 000000000..9df0dc447 --- /dev/null +++ b/engine/src/main/java/org/destinationsol/rendering/components/Renderable.java @@ -0,0 +1,41 @@ +/* + * Copyright 2020 The Terasology Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.destinationsol.rendering.components; + +import org.destinationsol.rendering.RenderableElement; +import org.terasology.gestalt.entitysystem.component.Component; + +import java.util.ArrayList; + +/** + * Contains a list of the different elements that combine to visually represent an entity. + */ +public final class Renderable implements Component { + + public ArrayList elements = new ArrayList<>(); + + @Override + public void copy(Renderable other) { + ArrayList newElements = new ArrayList<>(); + for (int index = 0; index < other.elements.size(); index++) { + RenderableElement data = new RenderableElement(); + data.copy(other.elements.get(index)); + newElements.add(data); + } + + this.elements = newElements; + } +} diff --git a/engine/src/main/java/org/destinationsol/rendering/events/RenderEvent.java b/engine/src/main/java/org/destinationsol/rendering/events/RenderEvent.java new file mode 100644 index 000000000..cbc117631 --- /dev/null +++ b/engine/src/main/java/org/destinationsol/rendering/events/RenderEvent.java @@ -0,0 +1,26 @@ +/* + * Copyright 2020 The Terasology Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.destinationsol.rendering.events; + +import org.destinationsol.rendering.components.Renderable; +import org.destinationsol.rendering.systems.RenderingSystem; +import org.terasology.gestalt.entitysystem.event.Event; + +/** + * Event that tells the {@link RenderingSystem} to update the drawings of each entity with a {@link Renderable}. + */ +public class RenderEvent implements Event { +} diff --git a/engine/src/main/java/org/destinationsol/rendering/systems/RenderingSystem.java b/engine/src/main/java/org/destinationsol/rendering/systems/RenderingSystem.java new file mode 100644 index 000000000..4399ac2fb --- /dev/null +++ b/engine/src/main/java/org/destinationsol/rendering/systems/RenderingSystem.java @@ -0,0 +1,68 @@ +/* + * Copyright 2020 The Terasology Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.destinationsol.rendering.systems; + +import com.badlogic.gdx.math.Vector2; +import org.destinationsol.common.In; +import org.destinationsol.rendering.RenderableElement; +import org.destinationsol.rendering.components.Renderable; +import org.destinationsol.rendering.components.Invisible; +import org.destinationsol.rendering.events.RenderEvent; +import org.destinationsol.entitysystem.EntitySystemManager; +import org.destinationsol.entitysystem.EventReceiver; +import org.destinationsol.game.GameDrawer; +import org.destinationsol.location.components.Angle; +import org.destinationsol.location.components.Position; +import org.terasology.gestalt.entitysystem.entity.EntityRef; +import org.terasology.gestalt.entitysystem.event.EventResult; +import org.terasology.gestalt.entitysystem.event.ReceiveEvent; + +/** + * This handles the drawing of each entity with a {@link Renderable} component. + */ +public class RenderingSystem implements EventReceiver { + + @In + private EntitySystemManager entitySystemManager; + + @In + private GameDrawer drawer; + + @ReceiveEvent(components = {Renderable.class, Position.class}) + public EventResult onRender(RenderEvent event, EntityRef entity) { + + if (!entity.hasComponent(Invisible.class)) { + + Renderable renderable = entity.getComponent(Renderable.class).get(); + Vector2 basePosition = entity.getComponent(Position.class).get().position; + + float baseAngle = 0; + if (entity.hasComponent(Position.class)) { + baseAngle = entity.getComponent(Angle.class).get().getAngle(); + } + + for (RenderableElement renderableElement : renderable.elements) { + float angle = renderableElement.relativeAngle + baseAngle; + + drawer.draw(renderableElement.texture, renderableElement.width, + renderableElement.height, renderableElement.width / 2, renderableElement.height / 2, + basePosition.x, basePosition.y, angle, renderableElement.tint); + } + } + + return EventResult.CONTINUE; + } +} From e0726121aa436cada109fd8507f66cb15b6c83de Mon Sep 17 00:00:00 2001 From: Isaac Date: Thu, 30 Jul 2020 23:05:02 -0400 Subject: [PATCH 2/2] fix: RenderableElement makes a deep copy when copy() is called --- engine/src/main/java/org/destinationsol/SolApplication.java | 3 +-- engine/src/main/java/org/destinationsol/game/SolGame.java | 3 --- .../java/org/destinationsol/rendering/RenderableElement.java | 4 ++-- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/engine/src/main/java/org/destinationsol/SolApplication.java b/engine/src/main/java/org/destinationsol/SolApplication.java index 6bdc1106d..7ab05b31e 100644 --- a/engine/src/main/java/org/destinationsol/SolApplication.java +++ b/engine/src/main/java/org/destinationsol/SolApplication.java @@ -234,10 +234,9 @@ private void draw() { commonDrawer.begin(); if (solGame != null) { - solGame.draw(); - //This event causes each entity with a `Graphics` component to be rendered onscreen + //This event causes each entity with a `Renderable` component to be rendered onscreen entitySystemManager.sendEvent(new RenderEvent(), new Renderable(), new Position()); } uiDrawer.updateMtx(); diff --git a/engine/src/main/java/org/destinationsol/game/SolGame.java b/engine/src/main/java/org/destinationsol/game/SolGame.java index d233518b6..4739643c0 100644 --- a/engine/src/main/java/org/destinationsol/game/SolGame.java +++ b/engine/src/main/java/org/destinationsol/game/SolGame.java @@ -109,9 +109,6 @@ public class SolGame { private SortedMap> onPausedUpdateSystems; private SortedMap> updateSystems; - @In - private EntitySystemManager entitySystemManager; - public SolGame(String shipName, boolean isTutorial, boolean isNewGame, CommonDrawer commonDrawer, Context context, WorldConfig worldConfig) { // TODO: make this non-static diff --git a/engine/src/main/java/org/destinationsol/rendering/RenderableElement.java b/engine/src/main/java/org/destinationsol/rendering/RenderableElement.java index 2b8de3b82..dded2dade 100644 --- a/engine/src/main/java/org/destinationsol/rendering/RenderableElement.java +++ b/engine/src/main/java/org/destinationsol/rendering/RenderableElement.java @@ -47,13 +47,13 @@ public class RenderableElement { public Color tint; public void copy(RenderableElement other) { - this.texture = other.texture; + this.texture = new TextureAtlas.AtlasRegion(other.texture); this.drawableLevel = other.drawableLevel; this.relativePosition = other.relativePosition.cpy(); this.relativeAngle = other.relativeAngle; this.width = other.width; this.height = other.height; - this.tint = other.tint; + this.tint = other.tint.cpy(); } }