Ticket #678: atlas_selection-01182012.patch

File atlas_selection-01182012.patch, 48.8 KB (added by historic_bruno, 12 years ago)
  • binaries/data/mods/public/simulation/templates/other/bridge_hele.xml

     
    2020  <Obstruction>
    2121    <Static width="59" depth="15"/>
    2222  </Obstruction>
    23   <Selectable disable=""/>
     23  <Selectable>
     24    <EditorOnly/>
     25  </Selectable>
    2426  <Vision>
    2527    <Range>72</Range>
    2628    <RetainInFog>true</RetainInFog>
  • binaries/data/mods/public/simulation/templates/other/bridge_wooden.xml

     
    2020  <Obstruction>
    2121    <Static width="59" depth="15"/>
    2222  </Obstruction>
    23   <Selectable disable=""/>
     23  <Selectable>
     24    <EditorOnly/>
     25  </Selectable>
    2426  <Vision>
    2527    <Range>72</Range>
    2628    <RetainInFog>true</RetainInFog>
  • binaries/data/mods/public/simulation/templates/special/territory_block.xml

     
    2121    <Floating>false</Floating>
    2222    <TurnRate>6.0</TurnRate>
    2323  </Position>
    24   <Selectable/>
     24  <Selectable>
     25    <EditorOnly disable=""/>
     26  </Selectable>
    2527  <TerritoryInfluence>
    2628    <OverrideCost>64</OverrideCost>
    2729    <Root>false</Root>
  • binaries/data/mods/public/simulation/templates/special/territory_pull.xml

     
    2121    <Floating>false</Floating>
    2222    <TurnRate>6.0</TurnRate>
    2323  </Position>
    24   <Selectable/>
     24  <Selectable>
     25    <EditorOnly disable=""/>
     26  </Selectable>
    2527  <TerritoryInfluence>
    2628    <OverrideCost>0</OverrideCost>
    2729    <Root>false</Root>
  • binaries/data/mods/public/simulation/templates/template_entity_quasi.xml

     
    88    <Floating>false</Floating>
    99    <TurnRate>6.0</TurnRate>
    1010  </Position>
     11  <Selectable>
     12    <EditorOnly/>
     13  </Selectable>
    1114</Entity>
  • binaries/data/mods/public/simulation/templates/template_gaia_flora_bush_berry.xml

     
    1616    <Amount>120</Amount>
    1717    <Type>food.fruit</Type>
    1818  </ResourceSupply>
    19   <Selectable/>
     19  <Selectable>
     20    <EditorOnly disable=""/>
     21  </Selectable>
    2022</Entity>
  • binaries/data/mods/public/simulation/templates/template_gaia_flora_tree.xml

     
    1515    <Amount>200</Amount>
    1616    <Type>wood.tree</Type>
    1717  </ResourceSupply>
    18   <Selectable/>
     18  <Selectable>
     19    <EditorOnly disable=""/>
     20  </Selectable>
    1921  <VisualActor>
    2022    <SelectionShape>
    2123      <Footprint/>
  • binaries/data/mods/public/simulation/templates/template_gaia_geo_mineral.xml

     
    1515    <Amount>1000</Amount>
    1616    <Type>metal.ore</Type>
    1717  </ResourceSupply>
    18   <Selectable/>
     18  <Selectable>
     19    <EditorOnly disable=""/>
     20  </Selectable>
    1921</Entity>
  • binaries/data/mods/public/simulation/templates/template_gaia_geo_rock.xml

     
    1515    <Amount>1000</Amount>
    1616    <Type>stone.rock</Type>
    1717  </ResourceSupply>
    18   <Selectable/>
     18  <Selectable>
     19    <EditorOnly disable=""/>
     20  </Selectable>
    1921</Entity>
  • binaries/data/mods/public/simulation/templates/template_gaia_ruins.xml

     
    2222    <Amount>500</Amount>
    2323    <Type>stone.rock</Type>
    2424  </ResourceSupply>
    25   <Selectable/>
     25  <Selectable>
     26    <EditorOnly disable=""/>
     27  </Selectable>
    2628</Entity>
  • binaries/data/mods/public/simulation/templates/template_gaia_treasure.xml

     
    2222    <Amount>300</Amount>
    2323    <Type>treasure.metal</Type>
    2424  </ResourceSupply>
    25   <Selectable/>
     25  <Selectable>
     26    <EditorOnly disable=""/>
     27  </Selectable>
    2628</Entity>
  • source/graphics/UnitManager.cpp

     
    8585    m_Units.clear();
    8686}
    8787
    88 
    8988///////////////////////////////////////////////////////////////////////////////
    90 // PickUnit: iterate through units testing given ray against bounds of each
    91 // unit; return the closest unit, or null if everything missed
    92 CUnit* CUnitManager::PickUnit(const CVector3D& origin, const CVector3D& dir) const
    93 {
    94     // closest object found so far
    95     CUnit* hit = 0;
    96     // closest approach offset (easier to pick small stuff in forests than standard ScEd style selection)
    97     float minrel = FLT_MAX;
    98 
    99     for (size_t i=0; i<m_Units.size(); i++) {
    100         CUnit* unit = m_Units[i];
    101         float tmin, tmax;
    102        
    103         const CBoundingBoxOriented& selectionBox = unit->GetModel().GetSelectionBox();
    104         if (selectionBox.RayIntersect(origin, dir, tmin, tmax))
    105         {
    106             // Point of closest approach
    107             // TODO: this next bit is virtually identical to Selection::PickEntitiesAtPoint; might be useful to factor it out and
    108             // reuse it
    109             CVector3D delta = selectionBox.m_Center - origin;
    110             float distance = delta.Dot(dir);
    111             CVector3D closest = origin + dir * distance;
    112             CVector3D offset = selectionBox.m_Center - closest;
    113 
    114             float rel = offset.Length();
    115             if (rel < minrel) {
    116                 hit = unit;
    117                 minrel = rel;
    118             }
    119         }
    120     }
    121     return hit;
    122 }
    123 
    124 ///////////////////////////////////////////////////////////////////////////////
    12589// CreateUnit: create a new unit and add it to the world
    12690CUnit* CUnitManager::CreateUnit(const CStrW& actorName, uint32_t seed, const std::set<CStr8>& selections)
    12791{
  • source/graphics/UnitManager.h

     
    5555    // return the units
    5656    const std::vector<CUnit*>& GetUnits() const { return m_Units; }
    5757   
    58     // iterate through units testing given ray against bounds of each unit;
    59     // return the closest unit, or null if everything missed
    60     CUnit* PickUnit(const CVector3D& origin, const CVector3D& dir) const;
    61 
    6258    void SetObjectManager(CObjectManager& objectManager) { m_ObjectManager = &objectManager; }
    6359
    6460private:
  • source/gui/scripting/ScriptFunctions.cpp

     
    128128
    129129std::vector<entity_id_t> PickEntitiesAtPoint(void* UNUSED(cbdata), int x, int y)
    130130{
    131     return EntitySelection::PickEntitiesAtPoint(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x, y, g_Game->GetPlayerID());
     131    return EntitySelection::PickEntitiesAtPoint(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x, y, g_Game->GetPlayerID(), false);
    132132}
    133133
    134134std::vector<entity_id_t> PickFriendlyEntitiesInRect(void* UNUSED(cbdata), int x0, int y0, int x1, int y1, int player)
    135135{
    136     return EntitySelection::PickEntitiesInRect(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x0, y0, x1, y1, player);
     136    return EntitySelection::PickEntitiesInRect(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x0, y0, x1, y1, player, false);
    137137}
    138138
    139139std::vector<entity_id_t> PickSimilarFriendlyEntities(void* UNUSED(cbdata), std::string templateName, bool includeOffScreen, bool matchRank)
    140140{
    141     return EntitySelection::PickSimilarEntities(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), templateName, g_Game->GetPlayerID(), includeOffScreen, matchRank);
     141    return EntitySelection::PickSimilarEntities(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), templateName, g_Game->GetPlayerID(), includeOffScreen, matchRank, false);
    142142}
    143143
    144144CFixedVector3D GetTerrainAtPoint(void* UNUSED(cbdata), int x, int y)
  • source/ps/GameSetup/GameSetup.cpp

     
    9797#include "ps/GameSetup/CmdLineArgs.h"
    9898#include "ps/GameSetup/HWDetect.h"
    9999
     100#include "tools/atlas/GameInterface/GameLoop.h"
     101#include "tools/atlas/GameInterface/View.h"
     102
     103
    100104#if !(OS_WIN || OS_MACOSX) // assume all other platforms use X11 for wxWidgets
    101105#define MUST_INIT_X11 1
    102106#include <X11/Xlib.h>
     
    248252
    249253    ogl_WarnIfError();
    250254
     255    if (g_GameLoop && g_GameLoop->view)
     256        g_GameLoop->view->DrawOverlays();
     257
     258    ogl_WarnIfError();
     259
    251260    // Text:
    252261
    253262    // Use the GL_ALPHA texture as the alpha channel with a flat colouring
  • source/simulation2/components/CCmpSelectable.cpp

     
    1 /* Copyright (C) 2010 Wildfire Games.
     1/* Copyright (C) 2012 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    4848    SOverlayLine m_Overlay;
    4949    SOverlayLine* m_DebugBoundingBoxOverlay;
    5050    SOverlayLine* m_DebugSelectionBoxOverlay;
     51    bool m_EditorOnly;
    5152
    5253    CCmpSelectable()
    5354        : m_DebugBoundingBoxOverlay(NULL), m_DebugSelectionBoxOverlay(NULL)
     
    6667        return
    6768            "<a:help>Allows this entity to be selected by the player.</a:help>"
    6869            "<a:example/>"
    69             "<empty/>";
     70            "<optional>"
     71                "<element name='EditorOnly' a:help='If this element is present, the entity is only selectable in Atlas'>"
     72                    "<empty/>"
     73                "</element>"
     74            "</optional>";
    7075    }
    7176
    72     virtual void Init(const CParamNode& UNUSED(paramNode))
     77    virtual void Init(const CParamNode& paramNode)
    7378    {
     79        m_EditorOnly = paramNode.GetChild("EditorOnly").IsOk();
    7480    }
    7581
    7682    virtual void Deinit()
     
    112118        }
    113119    }
    114120
     121    virtual bool IsEditorOnly()
     122    {
     123        return m_EditorOnly;
     124    }
     125
    115126    virtual void SetSelectionHighlight(CColor color)
    116127    {
    117128        m_Overlay.m_Color = color;
  • source/simulation2/components/CCmpTemplateManager.cpp

     
    1 /* Copyright (C) 2011 Wildfire Games.
     1/* Copyright (C) 2012 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    369369    // Copy the actor template
    370370    out = m_TemplateFileData[templateName];
    371371
    372     // Initialise the actor's name
     372    // Initialise the actor's name and make it an Atlas selectable entity.
    373373    std::string name = utf8_from_wstring(CParamNode::EscapeXMLString(wstring_from_utf8(actorName)));
    374     std::string xml = "<Entity><VisualActor><Actor>" + name + "</Actor></VisualActor></Entity>";
     374    std::string xml = "<Entity><VisualActor><Actor>" + name + "</Actor></VisualActor><Selectable><EditorOnly/></Selectable></Entity>";
    375375    CParamNode::LoadXMLString(out, xml.c_str());
    376376}
    377377
  • source/simulation2/components/ICmpSelectable.h

     
    1 /* Copyright (C) 2010 Wildfire Games.
     1/* Copyright (C) 2012 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    2626{
    2727public:
    2828    /**
     29     * Returns true if the entity is only selectable in Atlas editor, e.g. a decorative visual actor.
     30     */
     31    virtual bool IsEditorOnly() = 0;
     32
     33    /**
    2934     * Set the color of the selection highlight (typically a circle/square
    3035     * around the unit). Set a = 0 to disable.
    3136     */
  • source/simulation2/helpers/Selection.cpp

     
    1 /* Copyright (C) 2010 Wildfire Games.
     1/* Copyright (C) 2012 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    2828#include "simulation2/components/ICmpSelectable.h"
    2929#include "simulation2/components/ICmpVisual.h"
    3030
    31 std::vector<entity_id_t> EntitySelection::PickEntitiesAtPoint(CSimulation2& simulation, const CCamera& camera, int screenX, int screenY, int player)
     31std::vector<entity_id_t> EntitySelection::PickEntitiesAtPoint(CSimulation2& simulation, const CCamera& camera, int screenX, int screenY, int player, bool editorSelectable)
    3232{
    3333    CVector3D origin, dir;
    3434    camera.BuildCameraRay(screenX, screenY, origin, dir);
     
    4343    {
    4444        entity_id_t ent = it->first;
    4545
     46        // Check if this entity is only selectable in Atlas
     47        if (static_cast<ICmpSelectable*>(it->second)->IsEditorOnly() && !editorSelectable)
     48            continue;
     49
    4650        // Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld)
    4751        if (cmpRangeManager->GetLosVisibility(ent, player) == ICmpRangeManager::VIS_HIDDEN)
    4852            continue;
     
    5155        if (cmpVisual.null())
    5256            continue;
    5357
     58        CVector3D center;
     59        float tmin, tmax;
     60
    5461        CBoundingBoxOriented selectionBox = cmpVisual->GetSelectionBox();
    5562        if (selectionBox.IsEmpty())
    56             continue;
     63        {
     64            if (!editorSelectable)
     65                continue;
    5766
    58         float tmin, tmax;
    59         if (!selectionBox.RayIntersect(origin, dir, tmin, tmax))
    60             continue;
     67            // Fall back to using old AABB selection method for decals
     68            //  see: http://trac.wildfiregames.com/ticket/1032
     69            CBoundingBoxAligned aABBox = cmpVisual->GetBounds();
     70            if (aABBox.IsEmpty())
     71                continue;
    6172
     73            if (!aABBox.RayIntersect(origin, dir, tmin, tmax))
     74                continue;
     75
     76            aABBox.GetCentre(center);
     77        }
     78        else
     79        {
     80            if (!selectionBox.RayIntersect(origin, dir, tmin, tmax))
     81                continue;
     82
     83            center = selectionBox.m_Center;
     84        }
     85
    6286        // Find the perpendicular distance from the object's centre to the picker ray
    6387
    64         CVector3D closest = origin + dir * (selectionBox.m_Center - origin).Dot(dir);
    65         float dist2 = (closest - selectionBox.m_Center).LengthSquared();
     88        float dist2;
     89        CVector3D closest = origin + dir * (center - origin).Dot(dir);
     90        dist2 = (closest - center).LengthSquared();
    6691
    6792        hits.push_back(std::make_pair(dist2, ent));
    6893    }
     
    78103    return hitEnts;
    79104}
    80105
    81 std::vector<entity_id_t> EntitySelection::PickEntitiesInRect(CSimulation2& simulation, const CCamera& camera, int sx0, int sy0, int sx1, int sy1, int owner)
     106std::vector<entity_id_t> EntitySelection::PickEntitiesInRect(CSimulation2& simulation, const CCamera& camera, int sx0, int sy0, int sx1, int sy1, int owner, bool editorSelectable)
    82107{
    83108    // Make sure sx0 <= sx1, and sy0 <= sy1
    84109    if (sx0 > sx1)
     
    96121    {
    97122        entity_id_t ent = it->first;
    98123
     124        // Check if this entity is only selectable in Atlas
     125        if (static_cast<ICmpSelectable*>(it->second)->IsEditorOnly() && !editorSelectable)
     126            continue;
     127
    99128        // Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld)
    100129        if (cmpRangeManager->GetLosVisibility(ent, owner) == ICmpRangeManager::VIS_HIDDEN)
    101130            continue;
    102131
    103132        // Ignore entities not owned by 'owner'
    104133        CmpPtr<ICmpOwnership> cmpOwnership(simulation.GetSimContext(), ent);
    105         if (cmpOwnership.null() || cmpOwnership->GetOwner() != owner)
     134        if (owner != -1 && (cmpOwnership.null() || cmpOwnership->GetOwner() != owner))
    106135            continue;
    107136
    108137        // Find the current interpolated model position.
     
    132161    return hitEnts;
    133162}
    134163
    135 std::vector<entity_id_t> EntitySelection::PickSimilarEntities(CSimulation2& simulation, const CCamera& camera, const std::string& templateName, int owner, bool includeOffScreen, bool matchRank)
     164std::vector<entity_id_t> EntitySelection::PickSimilarEntities(CSimulation2& simulation, const CCamera& camera, const std::string& templateName, int owner, bool includeOffScreen, bool matchRank, bool editorSelectable)
    136165{
    137166    CmpPtr<ICmpTemplateManager> cmpTemplateManager(simulation, SYSTEM_ENTITY);
    138167    CmpPtr<ICmpRangeManager> cmpRangeManager(simulation, SYSTEM_ENTITY);
     
    144173    {
    145174        entity_id_t ent = it->first;
    146175
     176        // Check if this entity is only selectable in Atlas
     177        if (static_cast<ICmpSelectable*>(it->second)->IsEditorOnly() && !editorSelectable)
     178            continue;
     179
    147180        if (matchRank)
    148181        {
    149182            // Exact template name matching
     
    158191
    159192        // Ignore entities not owned by 'owner'
    160193        CmpPtr<ICmpOwnership> cmpOwnership(simulation.GetSimContext(), ent);
    161         if (cmpOwnership.null() || cmpOwnership->GetOwner() != owner)
     194        if (owner != -1 && (cmpOwnership.null() || cmpOwnership->GetOwner() != owner))
    162195            continue;
    163196
    164197        // Ignore off screen entities
  • source/simulation2/helpers/Selection.h

     
    1 /* Copyright (C) 2010 Wildfire Games.
     1/* Copyright (C) 2012 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    3737 * Finds all selectable entities under the given screen coordinates.
    3838 * Returns list ordered by closeness of picking, closest first.
    3939 * Restricted to entities in the LOS of @p player, but with any owner.
     40 * If @p editorSelectable then all entities with the IID_Selectable interface
     41 * will be selected, else only selectable entities without the EditorOnly flag set.
    4042 */
    41 std::vector<entity_id_t> PickEntitiesAtPoint(CSimulation2& simulation, const CCamera& camera, int screenX, int screenY, int player);
     43std::vector<entity_id_t> PickEntitiesAtPoint(CSimulation2& simulation, const CCamera& camera, int screenX, int screenY, int player, bool editorSelectable);
    4244
    4345/**
    4446 * Finds all selectable entities within the given screen coordinate rectangle,
    4547 * that belong to player @p owner.
     48 * If @p owner is -1 then ownership is ignored.
     49 * If @p editorSelectable then all entities with the IID_Selectable interface
     50 * will be selected, else only selectable entities without the EditorOnly flag set.
    4651 * Returns unordered list.
    4752 */
    48 std::vector<entity_id_t> PickEntitiesInRect(CSimulation2& simulation, const CCamera& camera, int sx0, int sy0, int sx1, int sy1, int owner);
     53std::vector<entity_id_t> PickEntitiesInRect(CSimulation2& simulation, const CCamera& camera, int sx0, int sy0, int sx1, int sy1, int owner, bool editorSelectable);
    4954
    5055/**
    5156 * Finds all entities with the given entity template name, that belong to player @p owner.
     57 * If @p owner is -1 then ownership is ignored.
    5258 * If @p includeOffScreen then all entities visible in the world will be selected,
    5359 * else only entities visible on the screen will be selected.
    5460 * If @p matchRank then only entities that exactly match @p templateName will be selected,
    5561 * else entities with matching SelectionGroupName will be selected.
     62 * If @p editorSelectable then all entities with the IID_Selectable interface
     63 * will be selected, else only selectable entities without the EditorOnly flag set.
    5664 */
    57 std::vector<entity_id_t> PickSimilarEntities(CSimulation2& simulation, const CCamera& camera, const std::string& templateName, int owner, bool includeOffScreen, bool matchRank);
     65std::vector<entity_id_t> PickSimilarEntities(CSimulation2& simulation, const CCamera& camera, const std::string& templateName, int owner, bool includeOffScreen, bool matchRank, bool editorSelectable);
    5866
    5967} // namespace
    6068
  • source/tools/atlas/AtlasUI/CustomControls/Canvas/Canvas.cpp

     
    1 /* Copyright (C) 2011 Wildfire Games.
     1/* Copyright (C) 2012 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    9696}
    9797
    9898BEGIN_EVENT_TABLE(Canvas, wxGLCanvas)
    99     EVT_SIZE       (Canvas::OnResize)
    100     EVT_LEFT_DOWN  (Canvas::OnMouse)
    101     EVT_LEFT_UP    (Canvas::OnMouse)
    102     EVT_RIGHT_DOWN (Canvas::OnMouse)
    103     EVT_RIGHT_UP   (Canvas::OnMouse)
    104     EVT_MIDDLE_DOWN(Canvas::OnMouse)
    105     EVT_MIDDLE_UP  (Canvas::OnMouse)
    106     EVT_MOUSEWHEEL (Canvas::OnMouse)
    107     EVT_MOTION     (Canvas::OnMouse)
     99    EVT_SIZE          (Canvas::OnResize)
     100    EVT_LEFT_DCLICK   (Canvas::OnMouse)
     101    EVT_LEFT_DOWN     (Canvas::OnMouse)
     102    EVT_LEFT_UP       (Canvas::OnMouse)
     103    EVT_RIGHT_DCLICK  (Canvas::OnMouse)
     104    EVT_RIGHT_DOWN    (Canvas::OnMouse)
     105    EVT_RIGHT_UP      (Canvas::OnMouse)
     106    EVT_MIDDLE_DCLICK (Canvas::OnMouse)
     107    EVT_MIDDLE_DOWN   (Canvas::OnMouse)
     108    EVT_MIDDLE_UP     (Canvas::OnMouse)
     109    EVT_MOUSEWHEEL    (Canvas::OnMouse)
     110    EVT_MOTION        (Canvas::OnMouse)
    108111    EVT_MOUSE_CAPTURE_LOST(Canvas::OnMouseCaptureLost)
    109112END_EVENT_TABLE()
  • source/tools/atlas/AtlasUI/ScenarioEditor/Tools/TransformObject.cpp

     
    1 /* Copyright (C) 2009 Wildfire Games.
     1/* Copyright (C) 2012 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    3131    DECLARE_DYNAMIC_CLASS(TransformObject);
    3232
    3333    int m_dx, m_dy;
     34    AtlasMessage::ObjectID m_lastSelected;
     35    wxPoint m_startPoint;
    3436
     37    // TODO: If we don't plan to change hotkeys, just replace with evt.ShiftDown(), etc.
     38    static const wxKeyCode SELECTION_ADD_HOTKEY = WXK_SHIFT;
     39    static const wxKeyCode SELECTION_REMOVE_HOTKEY = WXK_CONTROL;   // COMMAND on Macs
     40    static const wxKeyCode SELECTION_ACTORS_HOTKEY = WXK_ALT;
     41
    3542public:
    36     TransformObject()
     43    TransformObject() : m_lastSelected(0)
    3744    {
    3845        SetState(&Waiting);
    3946    }
     
    5259    {
    5360        bool OnMouse(TransformObject* obj, wxMouseEvent& evt)
    5461        {
    55             if (evt.LeftDown())
     62            if (evt.LeftDClick() && AtlasMessage::ObjectIDIsValid(obj->m_lastSelected))
    5663            {
     64                SET_STATE(SelectSimilar);
     65                return true;
     66            }
     67            else if (evt.LeftDown())
     68            {
     69                bool selectionAdd = wxGetKeyState(SELECTION_ADD_HOTKEY);
     70                bool selectionRemove = wxGetKeyState(SELECTION_REMOVE_HOTKEY);
     71                bool selectionActors = wxGetKeyState(SELECTION_ACTORS_HOTKEY);
     72
    5773                // New selection - never merge with movements of other objects
    5874                ScenarioEditor::GetCommandProc().FinaliseLastCommand();
    5975
    6076                // Select the object clicked on:
    6177
    62                 AtlasMessage::qPickObject qry(Position(evt.GetPosition()));
     78                AtlasMessage::qPickObject qry(Position(evt.GetPosition()), selectionActors);
    6379                qry.Post();
    6480
    65                 // TODO: handle multiple selections
    66                 g_SelectedObjects.clear();
    67 
    6881                // Check they actually clicked on a valid object
    6982                if (AtlasMessage::ObjectIDIsValid(qry.id))
    7083                {
    71                     g_SelectedObjects.push_back(qry.id);
    72                     // Remember the screen-space offset of the mouse from the
    73                     // object's centre, so we can add that back when moving it
    74                     // (instead of just moving the object's centre to directly
    75                     // beneath the mouse)
    76                     obj->m_dx = qry.offsetx;
    77                     obj->m_dy = qry.offsety;
    78                     SET_STATE(Dragging);
     84                    std::vector<AtlasMessage::ObjectID>::iterator it = std::find(g_SelectedObjects.begin(), g_SelectedObjects.end(), qry.id);
     85                    bool objectIsSelected = (it != g_SelectedObjects.end());
     86
     87                    if (selectionRemove)
     88                    {
     89                        // Remove from selection
     90                        if (objectIsSelected)
     91                            g_SelectedObjects.erase(it);
     92                    }
     93                    else if (!objectIsSelected)
     94                    {
     95                        // Add to selection
     96                        if (!selectionAdd)
     97                            g_SelectedObjects.clear();
     98
     99                        g_SelectedObjects.push_back(qry.id);
     100                    }
     101
     102                    obj->m_lastSelected = qry.id;
     103
     104                    // If we're selecting the whole group
     105                    if (!selectionAdd && !selectionRemove && !g_SelectedObjects.empty())
     106                    {
     107                        // Remember the screen-space offset of the mouse from the
     108                        // object's centre, so we can add that back when moving it
     109                        // (instead of just moving the object's centre to directly
     110                        // beneath the mouse)
     111                        obj->m_dx = qry.offsetx;
     112                        obj->m_dy = qry.offsety;
     113                        SET_STATE(Dragging);
     114                    }
     115
     116                    g_SelectedObjects.NotifyObservers();
     117                    POST_MESSAGE(SetSelectionPreview, (g_SelectedObjects));
    79118                }
    80                 g_SelectedObjects.NotifyObservers();
    81                 POST_MESSAGE(SetSelectionPreview, (g_SelectedObjects));
     119                else
     120                {
     121                    // Bandboxing
     122                    obj->m_lastSelected = 0;
     123                    obj->m_startPoint = evt.GetPosition();
     124                    SET_STATE(Bandboxing);
     125                }
     126
    82127                return true;
    83128            }
    84             else if ((evt.Dragging() && evt.RightIsDown()) || evt.RightDown())
     129            else if (g_SelectedObjects.size() == 1 && ((evt.Dragging() && evt.RightIsDown()) || evt.RightDown()))
    85130            {
     131                // TODO: Rotation of selections with multiple objects?
     132
    86133                // Dragging with right mouse button -> rotate objects to look
    87134                // at mouse
    88135                Position pos (evt.GetPosition());
     
    91138
    92139                return true;
    93140            }
     141            else if (evt.Moving())
     142            {
     143                // Prevent certain events from reaching game UI in this mode
     144                //  to prevent selection ring confusion
     145                return true;
     146            }
    94147            else
    95148                return false;
    96149        }
     
    132185            else if (evt.Dragging())
    133186            {
    134187                Position pos (evt.GetPosition() + wxPoint(obj->m_dx, obj->m_dy));
    135                 for (size_t i = 0; i < g_SelectedObjects.size(); ++i)
    136                     POST_COMMAND(MoveObject, (g_SelectedObjects[i], pos));
     188
     189                POST_COMMAND(MoveObjects, (g_SelectedObjects, obj->m_lastSelected, pos));
    137190                return true;
    138191            }
    139192            else
    140193                return false;
    141194        }
     195
     196        bool OnKey(TransformObject* obj, wxKeyEvent& evt, KeyEventType type)
     197        {
     198            if (type == KEY_UP && evt.GetKeyCode() == WXK_ESCAPE)
     199            {
     200                // Cancel move action
     201                ScenarioEditor::GetCommandProc().FinaliseLastCommand();
     202                ScenarioEditor::GetCommandProc().Undo();
     203                SET_STATE(Waiting);
     204
     205                return true;
     206            }
     207            else
     208                return false;
     209        }
    142210    }
    143211    Dragging;
     212
     213    struct sBandboxing : public State
     214    {
     215        bool OnMouse(TransformObject* obj, wxMouseEvent& evt)
     216        {
     217            if (evt.LeftIsDown() && evt.Dragging())
     218            {
     219                // Update bandbox overlay
     220                POST_MESSAGE(SetBandbox, (true, obj->m_startPoint.x, obj->m_startPoint.y, evt.GetPosition().x, evt.GetPosition().y));
     221                return true;
     222            }
     223            else if (evt.LeftUp())
     224            {
     225                bool selectionAdd = wxGetKeyState(SELECTION_ADD_HOTKEY);
     226                bool selectionRemove = wxGetKeyState(SELECTION_REMOVE_HOTKEY);
     227                bool selectionActors = wxGetKeyState(SELECTION_ACTORS_HOTKEY);
     228
     229                // Now we have both corners of the box, pick objects
     230                AtlasMessage::qPickObjectsInRect qry(Position(obj->m_startPoint), Position(evt.GetPosition()), selectionActors);
     231                qry.Post();
     232
     233                std::vector<AtlasMessage::ObjectID> ids = *qry.ids;
     234
     235                if (!selectionAdd && !selectionRemove)
     236                {
     237                    // Just copy new selections (clears list if no selections)
     238                    g_SelectedObjects = ids;
     239                }
     240                else
     241                {
     242                    for (size_t i = 0; i < ids.size(); ++i)
     243                    {
     244                        std::vector<AtlasMessage::ObjectID>::iterator it =  std::find(g_SelectedObjects.begin(), g_SelectedObjects.end(), ids[i]);
     245                        bool objectIsSelected = (it != g_SelectedObjects.end());
     246                        if (selectionRemove)
     247                        {
     248                            // Remove from selection
     249                            if (objectIsSelected)
     250                                g_SelectedObjects.erase(it);
     251                        }
     252                        else if (!objectIsSelected)
     253                        {
     254                            // Add to selection
     255                            g_SelectedObjects.push_back(ids[i]);
     256                        }
     257                    }
     258                }
     259
     260                POST_MESSAGE(SetBandbox, (false, 0, 0, 0, 0));
     261
     262                g_SelectedObjects.NotifyObservers();
     263                POST_MESSAGE(SetSelectionPreview, (g_SelectedObjects));
     264
     265                SET_STATE(Waiting);
     266                return true;
     267            }
     268            else
     269                return false;
     270        }
     271
     272        bool OnKey(TransformObject* obj, wxKeyEvent& evt, KeyEventType type)
     273        {
     274            if (type == KEY_UP && evt.GetKeyCode() == WXK_ESCAPE)
     275            {
     276                // Clear bandbox and return to waiting state
     277                POST_MESSAGE(SetBandbox, (false, 0, 0, 0, 0));
     278                SET_STATE(Waiting);
     279                return true;
     280            }
     281            else
     282                return false;
     283        }
     284    }
     285    Bandboxing;
     286
     287    struct sSelectSimilar : public State
     288    {
     289        bool OnMouse(TransformObject* obj, wxMouseEvent& evt)
     290        {
     291            if (evt.LeftUp())
     292            {
     293                bool selectionAdd = wxGetKeyState(SELECTION_ADD_HOTKEY);
     294                bool selectionRemove = wxGetKeyState(SELECTION_REMOVE_HOTKEY);
     295
     296                // Select similar objects
     297                AtlasMessage::qPickSimilarObjects qry(obj->m_lastSelected);
     298                qry.Post();
     299
     300                std::vector<AtlasMessage::ObjectID> ids = *qry.ids;
     301               
     302                if (!selectionAdd && !selectionRemove)
     303                {
     304                    // Just copy new selections (clears list if no selections)
     305                    g_SelectedObjects = ids;
     306                }
     307                else
     308                {
     309                    for (size_t i = 0; i < ids.size(); ++i)
     310                    {
     311                        std::vector<AtlasMessage::ObjectID>::iterator it =  std::find(g_SelectedObjects.begin(), g_SelectedObjects.end(), ids[i]);
     312                        bool objectIsSelected = (it != g_SelectedObjects.end());
     313                        if (selectionRemove)
     314                        {
     315                            // Remove from selection
     316                            if (objectIsSelected)
     317                                g_SelectedObjects.erase(it);
     318                        }
     319                        else if (!objectIsSelected)
     320                        {
     321                            // Add to selection
     322                            g_SelectedObjects.push_back(ids[i]);
     323                        }
     324                    }
     325                }
     326
     327                g_SelectedObjects.NotifyObservers();
     328                POST_MESSAGE(SetSelectionPreview, (g_SelectedObjects));
     329
     330                SET_STATE(Waiting);
     331                return true;
     332            }
     333            else
     334                return false;
     335        }
     336    }
     337    SelectSimilar;
    144338};
    145339
    146340IMPLEMENT_DYNAMIC_CLASS(TransformObject, StateDrivenTool<TransformObject>);
  • source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp

     
    1 /* Copyright (C) 2011 Wildfire Games.
     1/* Copyright (C) 2012 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    1818#include "precompiled.h"
    1919
    2020#include <cfloat>
     21#include <map>
    2122
    2223#include "MessageHandler.h"
    2324#include "../CommandProc.h"
     
    3132#include "graphics/ObjectManager.h"
    3233#include "graphics/Terrain.h"
    3334#include "graphics/Unit.h"
    34 #include "graphics/UnitManager.h"
    3535#include "lib/ogl.h"
    3636#include "maths/MathUtil.h"
    3737#include "maths/Matrix3D.h"
    3838#include "ps/CLogger.h"
    3939#include "ps/Game.h"
     40#include "ps/Overlay.h"
    4041#include "ps/World.h"
    4142#include "renderer/Renderer.h"
    4243#include "renderer/WaterManager.h"
    4344#include "simulation2/Simulation2.h"
    4445#include "simulation2/components/ICmpOwnership.h"
    4546#include "simulation2/components/ICmpPosition.h"
     47#include "simulation2/components/ICmpPlayer.h"
     48#include "simulation2/components/ICmpPlayerManager.h"
    4649#include "simulation2/components/ICmpSelectable.h"
    4750#include "simulation2/components/ICmpTemplateManager.h"
     51#include "simulation2/helpers/Selection.h"
    4852
    4953
    5054namespace AtlasMessage {
     
    5660        return wcscmp(a.name.c_str(), b.name.c_str()) < 0;
    5761    }
    5862
    59     bool IsFloating(const CUnit* unit)
    60     {
    61         if (! unit)
    62             return false;
    63 
    64         CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), unit->GetID());
    65         if (cmpPosition.null())
    66             return false;
    67         return cmpPosition->IsFloating();
    68     }
    69 
    70     CUnitManager& GetUnitManager()
    71     {
    72         return g_Game->GetWorld()->GetUnitManager();
    73     }
    7463}
    7564
    7665QUERYHANDLER(GetObjectsList)
     
    111100
    112101MESSAGEHANDLER(SetSelectionPreview)
    113102{
     103    CSimulation2& sim = *g_Game->GetSimulation2();
     104
     105    // Cache player colours for performance
     106    typedef std::map<player_id_t, CColor> PlayerColourMap;
     107    PlayerColourMap playerColours;
     108
     109    CmpPtr<ICmpPlayerManager> cmpPlayerManager(sim, SYSTEM_ENTITY);
     110   
     111    // Clear old selection rings
    114112    for (size_t i = 0; i < g_Selection.size(); ++i)
    115113    {
    116         CmpPtr<ICmpSelectable> cmpSelectable(*g_Game->GetSimulation2(), g_Selection[i]);
     114        CmpPtr<ICmpSelectable> cmpSelectable(sim, g_Selection[i]);
    117115        if (!cmpSelectable.null())
    118116            cmpSelectable->SetSelectionHighlight(CColor(1, 1, 1, 0));
    119117    }
    120118
    121119    g_Selection = *msg->ids;
    122120
     121    // Set new selection rings
    123122    for (size_t i = 0; i < g_Selection.size(); ++i)
    124123    {
    125         CmpPtr<ICmpSelectable> cmpSelectable(*g_Game->GetSimulation2(), g_Selection[i]);
    126         if (!cmpSelectable.null())
    127             cmpSelectable->SetSelectionHighlight(CColor(1, 1, 1, 1));
     124        entity_id_t ent = g_Selection[i];
     125        CmpPtr<ICmpSelectable> cmpSelectable(sim, ent);
     126        if (cmpSelectable.null())
     127            continue;
     128
     129        // Default to white for ownerless entities
     130        CColor colour(1.0f, 1.0f, 1.0f, 1.0f);
     131
     132        CmpPtr<ICmpOwnership> cmpOwnership(sim, ent);
     133        if (!cmpOwnership.null() && !cmpPlayerManager.null())
     134        {
     135            player_id_t owner = cmpOwnership->GetOwner();
     136            if (playerColours.find(owner) != playerColours.end())
     137            {
     138                colour = playerColours[owner];
     139            }
     140            else
     141            {
     142                // Add colour to cache
     143                entity_id_t playerEnt = cmpPlayerManager->GetPlayerByID(owner);
     144                CmpPtr<ICmpPlayer> cmpPlayer(sim, playerEnt);
     145                if (!cmpPlayer.null())
     146                {
     147                    colour = cmpPlayer->GetColour();
     148                    playerColours[owner] = colour;
     149                }
     150            }
     151        }
     152
     153        cmpSelectable->SetSelectionHighlight(colour);
    128154    }
    129155}
    130156
     
    401427    float x, y;
    402428    msg->pos->GetScreenSpace(x, y);
    403429   
    404     CVector3D rayorigin, raydir;
    405     g_Game->GetView()->GetCamera()->BuildCameraRay((int)x, (int)y, rayorigin, raydir);
     430    // Normally this function would be called with a player ID to check LOS, but in Atlas the entire map is revealed, so we just pass -1
     431    std::vector<AtlasMessage::ObjectID> ents = EntitySelection::PickEntitiesAtPoint(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x, y, -1, msg->selectActors);
    406432
    407     CUnit* target = GetUnitManager().PickUnit(rayorigin, raydir);
     433    // Multiple entities may have been picked, but they are sorted by distance,
     434    //  so only take the first one
     435    if (!ents.empty())
     436    {
     437        msg->id = ents[0];
    408438
    409     if (target)
    410         msg->id = target->GetID();
    411     else
    412         msg->id = INVALID_ENTITY;
    413 
    414     if (target)
    415     {
    416         // Get screen coordinates of the point on the ground underneath the
    417         // object's model-centre, so that callers know the offset to use when
    418         // working out the screen coordinates to move the object to.
     439        // Calculate offset of object from original mouse click position
     440        //  so it gets moved by that offset
    419441       
    420         CVector3D centre = target->GetModel().GetTransform().GetTranslation();
     442        CmpPtr<ICmpPosition> cmpPos(*g_Game->GetSimulation2(), (entity_id_t)ents[0]);
     443        if (cmpPos.null() || !cmpPos->IsInWorld())
     444        {
     445            // error
     446            msg->offsetx = msg->offsety = 0;
     447        }
     448        else
     449        {
     450            CFixedVector3D fixed = cmpPos->GetPosition();
     451            CVector3D centre = CVector3D(fixed.X.ToFloat(), fixed.Y.ToFloat(), fixed.Z.ToFloat());
    421452
    422         centre.Y = g_Game->GetWorld()->GetTerrain()->GetExactGroundLevel(centre.X, centre.Z);
    423         if (IsFloating(target))
    424             centre.Y = std::max(centre.Y, g_Renderer.GetWaterManager()->m_WaterHeight);
     453            float cx, cy;
     454            g_Game->GetView()->GetCamera()->GetScreenCoordinates(centre, cx, cy);
    425455
    426         float cx, cy;
    427         g_Game->GetView()->GetCamera()->GetScreenCoordinates(centre, cx, cy);
    428 
    429         msg->offsetx = (int)(cx - x);
    430         msg->offsety = (int)(cy - y);
     456            msg->offsetx = (int)(cx - x);
     457            msg->offsety = (int)(cy - y);
     458        }
    431459    }
    432460    else
    433461    {
     462        // No entity picked
     463        msg->id = INVALID_ENTITY;
    434464        msg->offsetx = msg->offsety = 0;
    435465    }
    436466}
    437467
     468QUERYHANDLER(PickObjectsInRect)
     469{
     470    float x0, y0, x1, y1;
     471    msg->start->GetScreenSpace(x0, y0);
     472    msg->end->GetScreenSpace(x1, y1);
    438473
    439 BEGIN_COMMAND(MoveObject)
     474    msg->ids = EntitySelection::PickEntitiesInRect(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x0, y0, x1, y1, -1, msg->selectActors);
     475}
     476
     477QUERYHANDLER(PickSimilarObjects)
    440478{
    441     CVector3D m_PosOld, m_PosNew;
     479    CmpPtr<ICmpTemplateManager> cmpTemplateManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
     480    ENSURE(!cmpTemplateManager.null());
     481    std::string templateName = cmpTemplateManager->GetCurrentTemplateName((entity_id_t)msg->id);
    442482
     483    msg->ids = EntitySelection::PickSimilarEntities(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), templateName, -1, false, true, true);
     484}
     485
     486BEGIN_COMMAND(MoveObjects)
     487{
     488    // Mapping from object to position
     489    typedef std::map<AtlasMessage::ObjectID, CVector3D> ObjectPositionMap;
     490    ObjectPositionMap m_PosOld, m_PosNew;
     491
    443492    void Do()
    444493    {
    445         CmpPtr<ICmpPosition> cmpPos(*g_Game->GetSimulation2(), (entity_id_t)msg->id);
    446         if (cmpPos.null())
     494        std::vector<ObjectID> ids = *msg->ids;
     495
     496        // All selected objects move relative to a pivot object,
     497        //  so get its position and whether it's floating
     498        CVector3D pivotPos(0, 0, 0);
     499        bool pivotFloating = false;
     500
     501        CmpPtr<ICmpPosition> cmpPos(*g_Game->GetSimulation2(), (entity_id_t)msg->pivot);
     502        if (!cmpPos.null() && cmpPos->IsInWorld())
    447503        {
    448             // error
    449             m_PosOld = m_PosNew = CVector3D(0, 0, 0);
     504            pivotFloating = cmpPos->IsFloating();
     505            CFixedVector3D pivotFixed = cmpPos->GetPosition();
     506            pivotPos = CVector3D(pivotFixed.X.ToFloat(), pivotFixed.Y.ToFloat(), pivotFixed.Z.ToFloat());
    450507        }
    451         else
     508
     509        // Calculate directional vector of movement for pivot object,
     510        //  we apply the same movement to all objects
     511        CVector3D targetPos = GetUnitPos(msg->pos, pivotFloating);
     512        CVector3D dir = targetPos - pivotPos;
     513
     514        for (size_t i = 0; i < ids.size(); ++i)
    452515        {
    453             m_PosNew = GetUnitPos(msg->pos, cmpPos->IsFloating());
     516            entity_id_t id = (entity_id_t)ids[i];
     517            CmpPtr<ICmpPosition> cmpPos(*g_Game->GetSimulation2(), id);
     518            if (cmpPos.null() || !cmpPos->IsInWorld())
     519            {
     520                // error
     521                m_PosOld[id] = m_PosNew[id] = CVector3D(0, 0, 0);
     522            }
     523            else
     524            {
     525                // Calculate this object's position
     526                CFixedVector3D posFixed = cmpPos->GetPosition();
     527                CVector3D pos = CVector3D(posFixed.X.ToFloat(), posFixed.Y.ToFloat(), posFixed.Z.ToFloat());
    454528
    455             CFixedVector3D pos = cmpPos->GetPosition();
    456             m_PosOld = CVector3D(pos.X.ToFloat(), pos.Y.ToFloat(), pos.Z.ToFloat());
     529                m_PosNew[id] = pos + dir;
     530                m_PosOld[id] = pos;
     531            }
    457532        }
    458533
    459534        SetPos(m_PosNew);
    460535    }
    461536
    462     void SetPos(CVector3D& pos)
     537    void SetPos(ObjectPositionMap& map)
    463538    {
    464         CmpPtr<ICmpPosition> cmpPos(*g_Game->GetSimulation2(), (entity_id_t)msg->id);
    465         if (cmpPos.null())
    466             return;
     539        ObjectPositionMap::iterator it;
     540        for (it = map.begin(); it != map.end(); ++it)
     541        {
     542            CmpPtr<ICmpPosition> cmpPos(*g_Game->GetSimulation2(), (entity_id_t)it->first);
     543            if (cmpPos.null())
     544                return;
    467545
    468         cmpPos->JumpTo(entity_pos_t::FromFloat(pos.X), entity_pos_t::FromFloat(pos.Z));
     546            // Set 2D position, ignoring height
     547            CVector3D pos = it->second;
     548            cmpPos->JumpTo(entity_pos_t::FromFloat(pos.X), entity_pos_t::FromFloat(pos.Z));
     549        }
    469550    }
    470551
    471552    void Redo()
     
    478559        SetPos(m_PosOld);
    479560    }
    480561
    481     void MergeIntoPrevious(cMoveObject* prev)
     562    void MergeIntoPrevious(cMoveObjects* prev)
    482563    {
    483         // TODO: do something valid if prev unit != this unit
    484         ENSURE(prev->msg->id == msg->id);
     564        // TODO: do something valid if prev selection != this selection
     565        ENSURE(*(prev->msg->ids) == *(msg->ids));
    485566        prev->m_PosNew = m_PosNew;
    486567    }
    487568};
    488 END_COMMAND(MoveObject)
     569END_COMMAND(MoveObjects)
    489570
    490571
    491572BEGIN_COMMAND(RotateObject)
     
    645726    msg->ids = ids;
    646727}
    647728
     729MESSAGEHANDLER(SetBandbox)
     730{
     731    View::GetView_Game()->SetBandbox(msg->show, (float)msg->sx0, (float)msg->sy0, (float)msg->sx1, (float)msg->sy1);
    648732}
     733
     734}
  • source/tools/atlas/GameInterface/Messages.h

     
    1 /* Copyright (C) 2011 Wildfire Games.
     1/* Copyright (C) 2012 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    484484//////////////////////////////////////////////////////////////////////////
    485485
    486486QUERY(PickObject,
    487       ((Position, pos))
    488       ,
    489       ((ObjectID, id))
    490       ((int, offsetx))  // offset of object centre from input position
    491       ((int, offsety)) //
    492       );
     487        ((Position, pos))
     488        ((bool, selectActors))
     489        ,
     490        ((ObjectID, id))
     491        ((int, offsetx))  // offset of object centre from input position
     492        ((int, offsety)) //
     493        );
    493494
    494 COMMAND(MoveObject, MERGE,
     495QUERY(PickObjectsInRect,
     496        ((Position, start))
     497        ((Position, end))
     498        ((bool, selectActors))
     499        ,
     500        ((std::vector<ObjectID>, ids))
     501        );
     502
     503QUERY(PickSimilarObjects,
    495504        ((ObjectID, id))
     505        ,
     506        ((std::vector<ObjectID>, ids))
     507        );
     508
     509COMMAND(MoveObjects, MERGE,
     510        ((std::vector<ObjectID>, ids))
     511        ((ObjectID, pivot))
    496512        ((Position, pos))
    497513        );
    498514
     
    512528        );
    513529
    514530QUERY(GetObjectSettings,
    515       ((int, view)) // eRenderView
    516       ((ObjectID, id))
    517       ,
    518       ((sObjectSettings, settings))
    519       );
     531        ((int, view)) // eRenderView
     532        ((ObjectID, id))
     533        ,
     534        ((sObjectSettings, settings))
     535        );
    520536
    521537COMMAND(SetObjectSettings, NOMERGE,
    522538        ((int, view)) // eRenderView
     
    530546        ((std::vector<ObjectID>, ids))
    531547        );
    532548
     549MESSAGE(SetBandbox,
     550        ((bool, show))
     551        ((int, sx0))
     552        ((int, sy0))
     553        ((int, sx1))
     554        ((int, sy1))
     555        );
     556
    533557//////////////////////////////////////////////////////////////////////////
    534558
    535559QUERY(GetCinemaPaths,
  • source/tools/atlas/GameInterface/Shareable.h

     
    1 /* Copyright (C) 2009 Wildfire Games.
     1/* Copyright (C) 2012 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    118118// Shareable containers must have shareable contents - but it's easy to forget
    119119// to declare them, so make sure the errors are almost readable, like:
    120120//   "use of undefined type 'REQUIRE_TYPE_TO_BE_SHAREABLE_FAILURE<T,__formal>
    121 //      with [ T=AtlasMessage::sTerrainGroupPreview, __formal=false ]"
     121//      with [ T=AtlasMessage::sTerrainTexturePreview, __formal=false ]"
    122122//
    123123// (Implementation based on boost/static_assert)
    124124template <typename T, bool> struct REQUIRE_TYPE_TO_BE_SHAREABLE_FAILURE;
  • source/tools/atlas/GameInterface/SharedTypes.h

     
    1 /* Copyright (C) 2009 Wildfire Games.
     1/* Copyright (C) 2012 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    8484
    8585
    8686typedef size_t ObjectID;
    87 inline bool ObjectIDIsValid(ObjectID id) { return (id != ~(size_t)0); }
     87inline bool ObjectIDIsValid(ObjectID id) { return (id != 0); }
    8888
    8989
    9090struct sCinemaSplineNode
  • source/tools/atlas/GameInterface/View.cpp

     
    1 /* Copyright (C) 2011 Wildfire Games.
     1/* Copyright (C) 2012 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    166166}
    167167
    168168ViewGame::ViewGame()
    169 : m_SpeedMultiplier(0.f)
     169    : m_SpeedMultiplier(0.f)
    170170{
    171171    ENSURE(g_Game);
    172172}
     
    262262    Atlas_GLSwapBuffers((void*)g_GameLoop->glCanvas);
    263263}
    264264
     265void ViewGame::DrawOverlays()
     266{
     267    glDisable(GL_TEXTURE_2D);
     268    glClear(GL_DEPTH_BUFFER_BIT);
     269
     270    // Invert y coordinates to match GUI
     271    glPushMatrix();
     272    glLoadIdentity();
     273    glTranslatef(0.0f, (GLfloat)g_yres, 0.0f);
     274    glScalef(1.0f, -1.f, 1.0f);
     275
     276    if (m_BandboxArray.size() > 0)
     277    {
     278        // Enable line antialiasing
     279        glEnable(GL_LINE_SMOOTH);
     280
     281        glEnableClientState(GL_COLOR_ARRAY);
     282        glEnableClientState(GL_VERTEX_ARRAY);
     283
     284        // Render bandbox as array of lines
     285        glVertexPointer(2, GL_FLOAT, sizeof(SBandboxVertex), &m_BandboxArray[0].x);
     286        glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(SBandboxVertex), &m_BandboxArray[0].r);
     287
     288        glDrawArrays(GL_LINES, 0, m_BandboxArray.size());
     289
     290        glDisableClientState(GL_VERTEX_ARRAY);
     291        glDisableClientState(GL_COLOR_ARRAY);
     292
     293        glDisable(GL_LINE_SMOOTH);
     294    }
     295
     296    glPopMatrix();
     297    glEnable(GL_TEXTURE_2D);
     298}
     299
    265300void ViewGame::SetParam(const std::wstring& name, bool value)
    266301{
    267302    if (name == L"priorities")
     
    353388    }
    354389}
    355390
     391void ViewGame::SetBandbox(bool visible, float x0, float y0, float x1, float y1)
     392{
     393    m_BandboxArray.clear();
     394
     395    if (visible)
     396    {
     397        // Make sure corners are arranged in correct order
     398        if (x0 > x1)
     399            std::swap(x0, x1);
     400        if (y0 > y1)
     401            std::swap(y0, y1);
     402
     403        // Bandbox is draw as lines comprising two rectangles, the inner
     404        //  is white and the outer is black. They are offset by 0.5 pixels
     405        //  so the antialiasing looks better.
     406        SBandboxVertex vert[] = {
     407            SBandboxVertex(x0, y0, 0, 0, 0, 255), SBandboxVertex(x1, y0, 0, 0, 0, 255), SBandboxVertex(x1, y1, 0, 0, 0, 255), SBandboxVertex(x0, y1, 0, 0, 0, 255),
     408            SBandboxVertex(x0+0.5f, y0+0.5f, 255, 255, 255, 255), SBandboxVertex(x1-0.5f, y0+0.5f, 255, 255, 255, 255), SBandboxVertex(x1-0.5f, y1-0.5f, 255, 255, 255, 255), SBandboxVertex(x0+0.5f, y1-0.5f, 255, 255, 255, 255)
     409        };
     410
     411        for (size_t i = 0; i < 4; ++i)
     412        {
     413            m_BandboxArray.push_back(vert[i]);
     414            m_BandboxArray.push_back(vert[(i+1)%4]);
     415        }
     416        for (size_t i = 0; i < 4; ++i)
     417        {
     418            m_BandboxArray.push_back(vert[i+4]);
     419            m_BandboxArray.push_back(vert[(i+1)%4+4]);
     420        }
     421    }
     422}
     423
    356424//////////////////////////////////////////////////////////////////////////
    357425
    358426ViewNone* view_None = NULL;
  • source/tools/atlas/GameInterface/View.h

     
    1 /* Copyright (C) 2010 Wildfire Games.
     1/* Copyright (C) 2012 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    3737    virtual ~View();
    3838    virtual void Update(float UNUSED(frameLength)) { };
    3939    virtual void Render() { };
     40    virtual void DrawOverlays() { };
    4041    virtual CCamera& GetCamera() = 0;
    4142    virtual CSimulation2* GetSimulation2() { return NULL; }
    4243    virtual entity_id_t GetEntityId(AtlasMessage::ObjectID obj) { return (entity_id_t)obj; }
     
    7677    virtual ~ViewGame();
    7778    virtual void Update(float frameLength);
    7879    virtual void Render();
     80    virtual void DrawOverlays();
    7981    virtual CCamera& GetCamera();
    8082    virtual CSimulation2* GetSimulation2();
    8183    virtual bool WantsHighFramerate();
     
    8789    void SaveState(const std::wstring& label);
    8890    void RestoreState(const std::wstring& label);
    8991    std::wstring DumpState(bool binary);
     92    void SetBandbox(bool visible, float x0, float y0, float x1, float y1);
    9093
    9194private:
    9295    float m_SpeedMultiplier;
    9396    std::map<std::wstring, SimState*> m_SavedStates;
    9497    std::string m_DisplayPassability;
     98
     99    typedef struct SBandboxVertex
     100    {
     101        SBandboxVertex(float x, float y, u8 r, u8 g, u8 b, u8 a) : x(x), y(y), r(r), g(g), b(b), a(a) {}
     102        u8 r, g, b, a;
     103        float x, y;
     104    } SBandboxVertex;
     105   
     106    std::vector<SBandboxVertex> m_BandboxArray;
    95107};
    96108
    97109class ActorViewer;