diff --git a/binaries/data/mods/public/art/textures/ui/session/icons/health_bg.png b/binaries/data/mods/public/art/textures/ui/session/icons/health_bg.png new file mode 100644 index 0000000000..40f9cf6a87 --- /dev/null +++ b/binaries/data/mods/public/art/textures/ui/session/icons/health_bg.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ebe285df7d0dfd9279f62028c3a0766dbe6ccb55b3e95ebcf9150e89bc30a476 +size 119 diff --git a/binaries/data/mods/public/art/textures/ui/session/icons/health_fg.png b/binaries/data/mods/public/art/textures/ui/session/icons/health_fg.png new file mode 100644 index 0000000000..723539cde7 --- /dev/null +++ b/binaries/data/mods/public/art/textures/ui/session/icons/health_fg.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21d175d74574ef8b044e79ac3968acfafb141c5aa608d70500569e2b099a1354 +size 108 diff --git a/binaries/data/mods/public/art/textures/ui/session/icons/textures.xml b/binaries/data/mods/public/art/textures/ui/session/icons/textures.xml new file mode 100644 index 0000000000..e808281b94 --- /dev/null +++ b/binaries/data/mods/public/art/textures/ui/session/icons/textures.xml @@ -0,0 +1,4 @@ + + + + diff --git a/binaries/data/mods/public/gui/session_new/selection.js b/binaries/data/mods/public/gui/session_new/selection.js index 3d7d42afec..a1c1662785 100644 --- a/binaries/data/mods/public/gui/session_new/selection.js +++ b/binaries/data/mods/public/gui/session_new/selection.js @@ -4,6 +4,12 @@ function _setHighlight(ents, alpha) Engine.GuiInterfaceCall("SetSelectionHighlight", { "entities":ents, "alpha":alpha }); } +function _setStatusBars(ents, enabled) +{ + if (ents.length) + Engine.GuiInterfaceCall("SetStatusBars", { "entities":ents, "enabled":enabled }); +} + function _setMotionOverlay(ents, enabled) { if (ents.length) @@ -207,12 +213,14 @@ EntitySelection.prototype.toggle = function(ent) if (this.selected[ent]) { _setHighlight([ent], 0); + _setStatusBars([ent], false); _setMotionOverlay([ent], false); delete this.selected[ent]; } else { _setHighlight([ent], 1); + _setStatusBars([ent], true); _setMotionOverlay([ent], this.motionDebugOverlay); this.selected[ent] = ent; } @@ -231,6 +239,7 @@ EntitySelection.prototype.addList = function(ents) } } _setHighlight(added, 1); + _setStatusBars(added, true); _setMotionOverlay(added, this.motionDebugOverlay); if (added.length) _playSound(added[0]); @@ -240,6 +249,7 @@ EntitySelection.prototype.addList = function(ents) EntitySelection.prototype.reset = function() { _setHighlight(this.toList(), 0); + _setStatusBars(this.toList(), false); _setMotionOverlay(this.toList(), false); this.selected = {}; this.dirty = true; @@ -256,29 +266,32 @@ EntitySelection.prototype.toList = function() EntitySelection.prototype.setHighlightList = function(ents) { + var highlighted = {}; + for each (var ent in ents) + highlighted[ent] = ent; + var removed = []; var added = []; - // Remove highlighting for the old units (excluding ones that are actively selected too) + // Remove highlighting for the old units that are no longer highlighted + // (excluding ones that are actively selected too) for each (var ent in this.highlighted) - if (!this.selected[ent]) - removed.push(ent); + if (!highlighted[ent] && !this.selected[ent]) + removed.push(+ent); - // Add new highlighting + // Add new highlighting for units that aren't already highlighted for each (var ent in ents) - if (!this.selected[ent]) - added.push(ent); + if (!this.highlighted[ent] && !this.selected[ent]) + added.push(+ent); _setHighlight(removed, 0); - _setHighlight(added, 0.5); + _setStatusBars(removed, false); - // TODO: this could be a bit more efficient by only changing the ones that - // have entered/left the highlight list + _setHighlight(added, 0.5); + _setStatusBars(added, true); - // Store the new list - this.highlighted = {}; - for each (var ent in ents) - this.highlighted[ent] = ent; + // Store the new highlight list + this.highlighted = highlighted; }; EntitySelection.prototype.SetMotionDebugOverlay = function(enabled) diff --git a/binaries/data/mods/public/simulation/components/GuiInterface.js b/binaries/data/mods/public/simulation/components/GuiInterface.js index a5c9b153d9..e2a50ccdd7 100644 --- a/binaries/data/mods/public/simulation/components/GuiInterface.js +++ b/binaries/data/mods/public/simulation/components/GuiInterface.js @@ -233,6 +233,17 @@ GuiInterface.prototype.SetSelectionHighlight = function(player, cmd) } }; +GuiInterface.prototype.SetStatusBars = function(player, cmd) +{ + for each (var ent in cmd.entities) + { + var cmpStatusBars = Engine.QueryInterface(ent, IID_StatusBars); + if (cmpStatusBars) + cmpStatusBars.SetEnabled(cmd.enabled); + } +}; + +/** /** * Displays the rally point of a building */ @@ -395,6 +406,7 @@ var exposedFunctions = { "GetNextNotification": 1, "SetSelectionHighlight": 1, + "SetStatusBars": 1, "DisplayRallyPoint": 1, "SetBuildingPlacementPreview": 1, "PlaySound": 1, diff --git a/binaries/data/mods/public/simulation/components/Health.js b/binaries/data/mods/public/simulation/components/Health.js index 15ffca1e65..567971fd40 100644 --- a/binaries/data/mods/public/simulation/components/Health.js +++ b/binaries/data/mods/public/simulation/components/Health.js @@ -56,7 +56,10 @@ Health.prototype.SetHitpoints = function(value) if (this.hitpoints == 0) return; + var old = this.hitpoints; this.hitpoints = Math.max(1, Math.min(this.GetMaxHitpoints(), value)); + + Engine.PostMessage(this.entity, MT_HealthChanged, { "from": old, "to": this.hitpoints }); }; Health.prototype.IsRepairable = function() @@ -84,13 +87,20 @@ Health.prototype.Reduce = function(amount) this.CreateCorpse(); Engine.DestroyEntity(this.entity); + + var old = this.hitpoints; + this.hitpoints = 0; + + Engine.PostMessage(this.entity, MT_HealthChanged, { "from": old, "to": this.hitpoints }); } - this.hitpoints = 0; } else { + var old = this.hitpoints; this.hitpoints -= amount; + + Engine.PostMessage(this.entity, MT_HealthChanged, { "from": old, "to": this.hitpoints }); } }; @@ -100,7 +110,10 @@ Health.prototype.Increase = function(amount) if (this.hitpoints == 0) return; + var old = this.hitpoints; this.hitpoints = Math.min(this.hitpoints + amount, this.GetMaxHitpoints()); + + Engine.PostMessage(this.entity, MT_HealthChanged, { "from": old, "to": this.hitpoints }); }; //// Private functions //// diff --git a/binaries/data/mods/public/simulation/components/StatusBars.js b/binaries/data/mods/public/simulation/components/StatusBars.js new file mode 100644 index 0000000000..2a10f0539f --- /dev/null +++ b/binaries/data/mods/public/simulation/components/StatusBars.js @@ -0,0 +1,74 @@ +function StatusBars() {} + +StatusBars.prototype.Schema = + "" + + "" + + ""; + +// TODO: should add rank icon too + +StatusBars.prototype.Init = function() +{ + this.enabled = false; +}; + +StatusBars.prototype.SetEnabled = function(enabled) +{ + // Quick return if no change + if (enabled == this.enabled) + return; + + // Update the displayed sprites + + this.enabled = enabled; + + if (enabled) + this.RegenerateSprites(); + else + this.ResetSprites(); +}; + +StatusBars.prototype.OnHealthChanged = function(msg) +{ + if (this.enabled) + this.RegenerateSprites(); +}; + +StatusBars.prototype.ResetSprites = function() +{ + var cmpOverlayRenderer = Engine.QueryInterface(this.entity, IID_OverlayRenderer); + cmpOverlayRenderer.Reset(); +}; + +StatusBars.prototype.RegenerateSprites = function() +{ + var cmpOverlayRenderer = Engine.QueryInterface(this.entity, IID_OverlayRenderer); + cmpOverlayRenderer.Reset(); + + // Size of health bar (in world-space units) + var width = 2; + var height = 1/3; + + // Offset from the unit's position + var offset = { "x": 0, "y": +this.template.HeightOffset, "z": 0 }; + + var cmpHealth = Engine.QueryInterface(this.entity, IID_Health); + if (cmpHealth) + { + var filled = cmpHealth.GetHitpoints() / cmpHealth.GetMaxHitpoints(); + + cmpOverlayRenderer.AddSprite( + "art/textures/ui/session/icons/health_bg.png", + { "x": -width/2, "y": -height/2 }, { "x": width/2, "y": height/2 }, + offset + ); + + cmpOverlayRenderer.AddSprite( + "art/textures/ui/session/icons/health_fg.png", + { "x": -width/2, "y": -height/2 }, { "x": width*(filled - 0.5), "y": height/2 }, + offset + ); + } +}; + +Engine.RegisterComponentType(IID_StatusBars, "StatusBars", StatusBars); diff --git a/binaries/data/mods/public/simulation/components/interfaces/Health.js b/binaries/data/mods/public/simulation/components/interfaces/Health.js index 8040a457c3..5f31193407 100644 --- a/binaries/data/mods/public/simulation/components/interfaces/Health.js +++ b/binaries/data/mods/public/simulation/components/interfaces/Health.js @@ -1 +1,5 @@ Engine.RegisterInterface("Health"); + +// Message of the form { "from": 100, "to", 90 }, +// sent whenever health changes. +Engine.RegisterMessageType("HealthChanged"); diff --git a/binaries/data/mods/public/simulation/components/interfaces/StatusBars.js b/binaries/data/mods/public/simulation/components/interfaces/StatusBars.js new file mode 100644 index 0000000000..c56cf6b919 --- /dev/null +++ b/binaries/data/mods/public/simulation/components/interfaces/StatusBars.js @@ -0,0 +1 @@ +Engine.RegisterInterface("StatusBars"); diff --git a/binaries/data/mods/public/simulation/templates/template_structure.xml b/binaries/data/mods/public/simulation/templates/template_structure.xml index 01658d0be7..1d0b86e86c 100644 --- a/binaries/data/mods/public/simulation/templates/template_structure.xml +++ b/binaries/data/mods/public/simulation/templates/template_structure.xml @@ -46,6 +46,7 @@ 12.0 + 36 true diff --git a/binaries/data/mods/public/simulation/templates/template_unit.xml b/binaries/data/mods/public/simulation/templates/template_unit.xml index e6770b41f6..d2f12271cb 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit.xml @@ -57,6 +57,7 @@ 5.0 + 2.5 diff --git a/source/graphics/Overlay.h b/source/graphics/Overlay.h index 6c967cd169..6ae03f0a49 100644 --- a/source/graphics/Overlay.h +++ b/source/graphics/Overlay.h @@ -18,11 +18,13 @@ #ifndef INCLUDED_GRAPHICS_OVERLAY #define INCLUDED_GRAPHICS_OVERLAY +#include "graphics/Texture.h" +#include "maths/Vector3D.h" #include "ps/Overlay.h" // CColor (TODO: that file has nothing to do with overlays, it should be renamed) /** - * Line-based overlay. Exists in world-space, but gets rendered on top - * of all other objects. Designed for selection circles. + * Line-based overlay, with world-space coordinates, rendered in the world + * potentially behind other objects. Designed for selection circles and debug info. */ struct SOverlayLine { @@ -33,6 +35,17 @@ struct SOverlayLine u8 m_Thickness; // pixels }; -// TODO: OverlaySprite, OverlayText +/** + * Billboard sprite overlay, with world-space coordinates, rendered on top + * of all other objects. Designed for health bars and rank icons. + */ +struct SOverlaySprite +{ + CTexturePtr m_Texture; + CVector3D m_Position; // base position + float m_X0, m_Y0, m_X1, m_Y1; // billboard corner coordinates, relative to base position +}; + +// TODO: OverlayText #endif // INCLUDED_GRAPHICS_OVERLAY diff --git a/source/renderer/OverlayRenderer.cpp b/source/renderer/OverlayRenderer.cpp index e71def3688..aa781694d0 100644 --- a/source/renderer/OverlayRenderer.cpp +++ b/source/renderer/OverlayRenderer.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Wildfire Games. +/* Copyright (C) 2010 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -20,12 +20,14 @@ #include "OverlayRenderer.h" #include "graphics/Overlay.h" +#include "graphics/TextureManager.h" #include "lib/ogl.h" #include "renderer/Renderer.h" struct OverlayRendererInternals { std::vector lines; + std::vector sprites; }; OverlayRenderer::OverlayRenderer() @@ -43,9 +45,15 @@ void OverlayRenderer::Submit(SOverlayLine* overlay) m->lines.push_back(overlay); } +void OverlayRenderer::Submit(SOverlaySprite* overlay) +{ + m->sprites.push_back(overlay); +} + void OverlayRenderer::EndFrame() { m->lines.clear(); + m->sprites.clear(); // this should leave the capacity unchanged, which is okay since it // won't be very large or very variable } @@ -79,3 +87,46 @@ void OverlayRenderer::RenderOverlays() glLineWidth(1.f); glDisable(GL_BLEND); } + +void OverlayRenderer::RenderForegroundOverlays(const CCamera& viewCamera) +{ + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + + CVector3D right = -viewCamera.m_Orientation.GetLeft(); + CVector3D up = viewCamera.m_Orientation.GetUp(); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + float uvs[8] = { 0,0, 1,0, 1,1, 0,1 }; + glTexCoordPointer(2, GL_FLOAT, sizeof(float)*2, &uvs); + + for (size_t i = 0; i < m->sprites.size(); ++i) + { + SOverlaySprite* sprite = m->sprites[i]; + + sprite->m_Texture->Bind(); + + CVector3D pos[4] = { + sprite->m_Position + right*sprite->m_X0 + up*sprite->m_Y0, + sprite->m_Position + right*sprite->m_X1 + up*sprite->m_Y0, + sprite->m_Position + right*sprite->m_X1 + up*sprite->m_Y1, + sprite->m_Position + right*sprite->m_X0 + up*sprite->m_Y1 + }; + + glVertexPointer(3, GL_FLOAT, sizeof(float)*3, &pos[0].X); + + glDrawArrays(GL_QUADS, 0, (GLsizei)4); + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + glEnable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); +} diff --git a/source/renderer/OverlayRenderer.h b/source/renderer/OverlayRenderer.h index 67852bf8ec..67e1559d6c 100644 --- a/source/renderer/OverlayRenderer.h +++ b/source/renderer/OverlayRenderer.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Wildfire Games. +/* Copyright (C) 2010 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -19,6 +19,8 @@ #define INCLUDED_OVERLAYRENDERER struct SOverlayLine; +struct SOverlaySprite; +class CCamera; struct OverlayRendererInternals; @@ -37,6 +39,11 @@ public: */ void Submit(SOverlayLine* overlay); + /** + * Add a sprite overlay for rendering in this frame. + */ + void Submit(SOverlaySprite* overlay); + /** * Prepare internal data structures for rendering. * Must be called after all Submit calls for a frame, and before @@ -50,10 +57,18 @@ public: void EndFrame(); /** - * Render all the submitted overlays. + * Render all the submitted overlays that are embedded in the world + * (i.e. rendered behind other objects, underwater, etc). */ void RenderOverlays(); + /** + * Render all the submitted overlays that should appear on top of everything + * in the world. + * @param viewCamera camera to be used for billboard computations + */ + void RenderForegroundOverlays(const CCamera& viewCamera); + private: OverlayRendererInternals* m; }; diff --git a/source/renderer/Renderer.cpp b/source/renderer/Renderer.cpp index e659fe3373..78e110e0d3 100644 --- a/source/renderer/Renderer.cpp +++ b/source/renderer/Renderer.cpp @@ -1311,6 +1311,12 @@ void CRenderer::RenderSubmissions() ogl_WarnIfError(); } + // render overlays that should appear on top of all other objects + PROFILE_START("render fg overlays"); + m->overlayRenderer.RenderForegroundOverlays(m_ViewCamera); + PROFILE_END("render fg overlays"); + ogl_WarnIfError(); + // empty lists MICROLOG(L"empty lists"); m->terrainRenderer->EndFrame(); @@ -1392,6 +1398,11 @@ void CRenderer::Submit(SOverlayLine* overlay) m->overlayRenderer.Submit(overlay); } +void CRenderer::Submit(SOverlaySprite* overlay) +{ + m->overlayRenderer.Submit(overlay); +} + void CRenderer::SubmitNonRecursive(CModel* model) { if (model->GetFlags() & MODELFLAG_CASTSHADOWS) { diff --git a/source/renderer/Renderer.h b/source/renderer/Renderer.h index 7128d0924a..af8a8df9f1 100644 --- a/source/renderer/Renderer.h +++ b/source/renderer/Renderer.h @@ -338,6 +338,7 @@ protected: //BEGIN: Implementation of SceneCollector void Submit(CPatch* patch); void Submit(SOverlayLine* overlay); + void Submit(SOverlaySprite* overlay); void SubmitNonRecursive(CModel* model); //END: Implementation of SceneCollector diff --git a/source/renderer/Scene.h b/source/renderer/Scene.h index eaa1ca5dc7..356a52b136 100644 --- a/source/renderer/Scene.h +++ b/source/renderer/Scene.h @@ -32,6 +32,7 @@ class CFrustum; class CModel; class CPatch; struct SOverlayLine; +struct SOverlaySprite; class SceneCollector; @@ -72,10 +73,15 @@ public: virtual void Submit(CPatch* patch) = 0; /** - * Submit a line-based overlay that is part of the scene. + * Submit a line-based overlay. */ virtual void Submit(SOverlayLine* overlay) = 0; + /** + * Submit a sprite overlay. + */ + virtual void Submit(SOverlaySprite* overlay) = 0; + /** * Submit a model that is part of the scene, * without submitting attached models. diff --git a/source/simulation2/TypeList.h b/source/simulation2/TypeList.h index c12313cbbe..cc08c6eb83 100644 --- a/source/simulation2/TypeList.h +++ b/source/simulation2/TypeList.h @@ -82,6 +82,9 @@ COMPONENT(Obstruction) INTERFACE(ObstructionManager) COMPONENT(ObstructionManager) +INTERFACE(OverlayRenderer) +COMPONENT(OverlayRenderer) + INTERFACE(Ownership) COMPONENT(Ownership) @@ -109,9 +112,6 @@ COMPONENT(Selectable) INTERFACE(SoundManager) COMPONENT(SoundManager) -INTERFACE(StatusBars) -COMPONENT(StatusBars) - INTERFACE(Terrain) COMPONENT(Terrain) diff --git a/source/simulation2/components/CCmpOverlayRenderer.cpp b/source/simulation2/components/CCmpOverlayRenderer.cpp new file mode 100644 index 0000000000..d7513068c2 --- /dev/null +++ b/source/simulation2/components/CCmpOverlayRenderer.cpp @@ -0,0 +1,147 @@ +/* Copyright (C) 2010 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "precompiled.h" + +#include "simulation2/system/Component.h" +#include "ICmpOverlayRenderer.h" + +#include "ICmpPosition.h" +#include "simulation2/MessageTypes.h" + +#include "graphics/Overlay.h" +#include "graphics/TextureManager.h" +#include "renderer/Renderer.h" + +class CCmpOverlayRenderer : public ICmpOverlayRenderer +{ +public: + static void ClassInit(CComponentManager& componentManager) + { + componentManager.SubscribeToMessageType(MT_Interpolate); + componentManager.SubscribeToMessageType(MT_RenderSubmit); + } + + DEFAULT_COMPONENT_ALLOCATOR(OverlayRenderer) + + // Currently-enabled set of sprites + std::vector m_Sprites; + + // For each entry in m_Sprites, store the offset of the sprite from the unit's position + // (so we can recompute the sprite position after the unit moves) + std::vector m_SpriteOffsets; + + // Whether the sprites should be drawn (only valid between Interpolate and RenderSubmit) + bool m_Enabled; + + static std::string GetSchema() + { + return ""; + } + + virtual void Init(const CSimContext& UNUSED(context), const CParamNode& UNUSED(paramNode)) + { + } + + virtual void Deinit(const CSimContext& UNUSED(context)) + { + } + + virtual void Serialize(ISerializer& UNUSED(serialize)) + { + // TODO: should we do anything here? + // or should we expect other components to reinitialise us + // after deserialization? + } + + virtual void Deserialize(const CSimContext& context, const CParamNode& paramNode, IDeserializer& UNUSED(deserialize)) + { + Init(context, paramNode); + } + + virtual void HandleMessage(const CSimContext& UNUSED(context), const CMessage& msg, bool UNUSED(global)) + { + switch (msg.GetType()) + { + case MT_Interpolate: + { + const CMessageInterpolate& msgData = static_cast (msg); + Interpolate(msgData.frameTime, msgData.offset); + break; + } + case MT_RenderSubmit: + { + const CMessageRenderSubmit& msgData = static_cast (msg); + RenderSubmit(msgData.collector); + break; + } + } + } + + virtual void Reset() + { + m_Sprites.clear(); + m_SpriteOffsets.clear(); + } + + virtual void AddSprite(std::wstring textureName, CFixedVector2D corner0, CFixedVector2D corner1, CFixedVector3D position) + { + CTextureProperties textureProps(textureName); + + SOverlaySprite sprite; + sprite.m_Texture = g_Renderer.GetTextureManager().CreateTexture(textureProps); + sprite.m_X0 = corner0.X.ToFloat(); + sprite.m_Y0 = corner0.Y.ToFloat(); + sprite.m_X1 = corner1.X.ToFloat(); + sprite.m_Y1 = corner1.Y.ToFloat(); + + m_Sprites.push_back(sprite); + m_SpriteOffsets.push_back(CVector3D(position)); + } + + void Interpolate(float UNUSED(frameTime), float frameOffset) + { + // Disable rendering of the unit if it has no position + CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + if (cmpPosition.null() || !cmpPosition->IsInWorld()) + { + m_Enabled = false; + return; + } + + // Find the precise position of the unit + CMatrix3D transform(cmpPosition->GetInterpolatedTransform(frameOffset, false)); + CVector3D position(transform.GetTranslation()); + + // Move all the sprites to the desired offset relative to the unit + for (size_t i = 0; i < m_Sprites.size(); ++i) + m_Sprites[i].m_Position = position + m_SpriteOffsets[i]; + + m_Enabled = true; + } + + void RenderSubmit(SceneCollector& collector) + { + if (!m_Enabled) + return; + + for (size_t i = 0; i < m_Sprites.size(); ++i) + collector.Submit(&m_Sprites[i]); + } +}; + +REGISTER_COMPONENT_TYPE(OverlayRenderer) diff --git a/source/simulation2/components/CCmpStatusBars.cpp b/source/simulation2/components/CCmpStatusBars.cpp deleted file mode 100644 index 766aeea35d..0000000000 --- a/source/simulation2/components/CCmpStatusBars.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright (C) 2010 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * 0 A.D. is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with 0 A.D. If not, see . - */ - -#include "precompiled.h" - -#include "simulation2/system/Component.h" -#include "ICmpStatusBars.h" - -class CCmpStatusBars : public ICmpStatusBars -{ -public: - static void ClassInit(CComponentManager& UNUSED(componentManager)) - { - } - - DEFAULT_COMPONENT_ALLOCATOR(StatusBars) - - /* - * TODO: this all needs to be designed and implemented - */ - - static std::string GetSchema() - { - return - "" - "" - ""; - } - - virtual void Init(const CSimContext& UNUSED(context), const CParamNode& UNUSED(paramNode)) - { - } - - virtual void Deinit(const CSimContext& UNUSED(context)) - { - } - - virtual void Serialize(ISerializer& UNUSED(serialize)) - { - } - - virtual void Deserialize(const CSimContext& context, const CParamNode& paramNode, IDeserializer& UNUSED(deserialize)) - { - Init(context, paramNode); - } -}; - -REGISTER_COMPONENT_TYPE(StatusBars) diff --git a/source/simulation2/components/ICmpStatusBars.cpp b/source/simulation2/components/ICmpOverlayRenderer.cpp similarity index 70% rename from source/simulation2/components/ICmpStatusBars.cpp rename to source/simulation2/components/ICmpOverlayRenderer.cpp index 72fb4410e5..898cc85ff3 100644 --- a/source/simulation2/components/ICmpStatusBars.cpp +++ b/source/simulation2/components/ICmpOverlayRenderer.cpp @@ -17,9 +17,11 @@ #include "precompiled.h" -#include "ICmpStatusBars.h" +#include "ICmpOverlayRenderer.h" #include "simulation2/system/InterfaceScripted.h" -BEGIN_INTERFACE_WRAPPER(StatusBars) -END_INTERFACE_WRAPPER(StatusBars) +BEGIN_INTERFACE_WRAPPER(OverlayRenderer) +DEFINE_INTERFACE_METHOD_0("Reset", void, ICmpOverlayRenderer, Reset) +DEFINE_INTERFACE_METHOD_4("AddSprite", void, ICmpOverlayRenderer, AddSprite, std::wstring, CFixedVector2D, CFixedVector2D, CFixedVector3D) +END_INTERFACE_WRAPPER(OverlayRenderer) diff --git a/source/simulation2/components/ICmpOverlayRenderer.h b/source/simulation2/components/ICmpOverlayRenderer.h new file mode 100644 index 0000000000..9ec89a1857 --- /dev/null +++ b/source/simulation2/components/ICmpOverlayRenderer.h @@ -0,0 +1,56 @@ +/* Copyright (C) 2010 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#ifndef INCLUDED_ICMPOVERLAYRENDERER +#define INCLUDED_ICMPOVERLAYRENDERER + +#include "simulation2/system/Interface.h" + +#include "simulation2/helpers/Position.h" + +#include "maths/FixedVector2D.h" +#include "maths/FixedVector3D.h" + +/** + * Interface for rendering 'overlay' objects (typically sprites), automatically + * positioned relative to the entity. + * Usually driven by the StatusBars component. + * + * (TODO: maybe we should add a "category" argument to Reset/AddSprite/etc, + * so different components can each maintain independent sets of overlays here?) + */ +class ICmpOverlayRenderer : public IComponent +{ +public: + /** + * Delete all sprites that have been previously added. + */ + virtual void Reset() = 0; + + /** + * Add a new textured billboard sprite to be rendered. + * @param textureName filename of texture to render. + * @param corner0,corner1 coordinates of sprite's corners, in world-space units oriented with the camera plane, + * relative to the sprite position. + * @param offset world-space offset of sprite position from the entity's base position. + */ + virtual void AddSprite(std::wstring textureName, CFixedVector2D corner0, CFixedVector2D corner1, CFixedVector3D offset) = 0; + + DECLARE_INTERFACE_TYPE(OverlayRenderer) +}; + +#endif // INCLUDED_ICMPOVERLAYRENDERER diff --git a/source/simulation2/components/ICmpStatusBars.h b/source/simulation2/components/ICmpStatusBars.h deleted file mode 100644 index f49d38c8d3..0000000000 --- a/source/simulation2/components/ICmpStatusBars.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright (C) 2010 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * 0 A.D. is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with 0 A.D. If not, see . - */ - -#ifndef INCLUDED_ICMPSTATUSBARS -#define INCLUDED_ICMPSTATUSBARS - -#include "simulation2/system/Interface.h" - -/** - * Health/stamina status bar renderer. - */ -class ICmpStatusBars : public IComponent -{ -public: - DECLARE_INTERFACE_TYPE(StatusBars) -}; - -#endif // INCLUDED_ICMPSTATUSBARS diff --git a/source/simulation2/scripting/EngineScriptConversions.cpp b/source/simulation2/scripting/EngineScriptConversions.cpp index 0053dc97ca..f06db98b34 100644 --- a/source/simulation2/scripting/EngineScriptConversions.cpp +++ b/source/simulation2/scripting/EngineScriptConversions.cpp @@ -20,6 +20,7 @@ #include "scriptinterface/ScriptInterface.h" #include "maths/Fixed.h" +#include "maths/FixedVector2D.h" #include "maths/FixedVector3D.h" #include "ps/CLogger.h" #include "ps/Overlay.h" @@ -242,3 +243,24 @@ template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const C return OBJECT_TO_JSVAL(obj); } + +template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, CFixedVector2D& out) +{ + ScriptInterface::LocalRootScope scope(cx); + if (!scope.OK()) + return false; + + if (!JSVAL_IS_OBJECT(v)) + return false; // TODO: report type error + JSObject* obj = JSVAL_TO_OBJECT(v); + + jsval p; + + if (!JS_GetProperty(cx, obj, "x", &p)) return false; // TODO: report type errors + if (!FromJSVal(cx, p, out.X)) return false; + + if (!JS_GetProperty(cx, obj, "y", &p)) return false; + if (!FromJSVal(cx, p, out.Y)) return false; + + return true; +}