LCOV - code coverage report
Current view: top level - source/graphics - ObjectBase.h (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 0 12 0.0 %
Date: 2023-01-19 00:18:29 Functions: 0 25 0.0 %

          Line data    Source code
       1             : /* Copyright (C) 2021 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #ifndef INCLUDED_OBJECTBASE
      19             : #define INCLUDED_OBJECTBASE
      20             : 
      21             : #include "lib/file/vfs/vfs_path.h"
      22             : #include "ps/CStr.h"
      23             : #include "ps/CStrIntern.h"
      24             : 
      25             : class CActorDef;
      26             : class CObjectEntry;
      27             : class CObjectManager;
      28             : class CXeromyces;
      29             : class XMBElement;
      30             : 
      31             : #include <boost/random/mersenne_twister.hpp>
      32             : #include <map>
      33             : #include <memory>
      34             : #include <set>
      35             : #include <unordered_set>
      36             : #include <vector>
      37             : 
      38             : /**
      39             :  * Maintains the tree of possible objects from a specific actor definition at a given quality level.
      40             :  * An Object Base is made of:
      41             :  *  - a material
      42             :  *  - a few properties (float on water / casts shadow / ...)
      43             :  *  - a number of variant groups.
      44             :  * Any actual object in game will pick a variant from each group (see ObjectEntry).
      45             :  */
      46           0 : class CObjectBase
      47             : {
      48             :     friend CActorDef;
      49             : 
      50             :     // See CopyWithQuality() below.
      51             :     NONCOPYABLE(CObjectBase);
      52             : public:
      53           0 :     struct Anim
      54             :     {
      55             :         // constructor
      56           0 :         Anim() : m_Frequency(0), m_Speed(1.f), m_ActionPos(-1.f), m_ActionPos2(-1.f), m_SoundPos(-1.f) {}
      57             :         // name of the animation - "Idle", "Run", etc
      58             :         CStr m_AnimName;
      59             :         // ID of the animation: if not empty, something specific to sync with props.
      60             :         CStr m_ID = "";
      61             :         int m_Frequency;
      62             :         // filename of the animation - manidle.psa, manrun.psa, etc
      63             :         VfsPath m_FileName;
      64             :         // animation speed, as specified in XML actor file
      65             :         float m_Speed;
      66             :         // fraction [0.0, 1.0] of the way through the animation that the interesting bit(s)
      67             :         // happens, or -1.0 if unspecified
      68             :         float m_ActionPos;
      69             :         float m_ActionPos2;
      70             :         float m_SoundPos;
      71             :     };
      72             : 
      73           0 :     struct Prop
      74             :     {
      75             :         // constructor
      76           0 :         Prop() : m_minHeight(0.f), m_maxHeight(0.f), m_selectable(true) {}
      77             :         // name of the prop point to attach to - "Prop01", "Prop02", "Head", "LeftHand", etc ..
      78             :         CStr m_PropPointName;
      79             :         // name of the model file - art/actors/props/sword.xml or whatever
      80             :         CStrW m_ModelName;
      81             :         // allow the prop to ajust the height from minHeight to maxHeight relative to the main model
      82             :         float m_minHeight;
      83             :         float m_maxHeight;
      84             :         bool m_selectable;
      85             :     };
      86             : 
      87           0 :     struct Samp
      88             :     {
      89             :         // identifier name of sampler in GLSL shaders
      90             :         CStrIntern m_SamplerName;
      91             :         // path to load from
      92             :         VfsPath m_SamplerFile;
      93             :     };
      94             : 
      95             :     struct Decal
      96             :     {
      97           0 :         Decal() : m_SizeX(0.f), m_SizeZ(0.f), m_Angle(0.f), m_OffsetX(0.f), m_OffsetZ(0.f) {}
      98             : 
      99             :         float m_SizeX;
     100             :         float m_SizeZ;
     101             :         float m_Angle;
     102             :         float m_OffsetX;
     103             :         float m_OffsetZ;
     104             :     };
     105             : 
     106           0 :     struct Variant
     107             :     {
     108           0 :         Variant() : m_Frequency(0) {}
     109             : 
     110             :         CStr m_VariantName; // lowercase name
     111             :         int m_Frequency;
     112             :         VfsPath m_ModelFilename;
     113             :         Decal m_Decal;
     114             :         VfsPath m_Particles;
     115             :         CStr m_Color;
     116             : 
     117             :         std::vector<Anim> m_Anims;
     118             :         std::vector<Prop> m_Props;
     119             :         std::vector<Samp> m_Samplers;
     120             :     };
     121             : 
     122           0 :     struct Variation
     123             :     {
     124             :         VfsPath model;
     125             :         Decal decal;
     126             :         VfsPath particles;
     127             :         CStr color;
     128             :         std::multimap<CStr, Prop> props;
     129             :         std::multimap<CStr, Anim> anims;
     130             :         std::multimap<CStr, Samp> samplers;
     131             :     };
     132             : 
     133             :     CObjectBase(CObjectManager& objectManager, CActorDef& actorDef, u8 QualityLevel);
     134             : 
     135             :     // Returns a set of selection such that, added to initialSelections, CalculateVariationKey can proceed.
     136             :     std::set<CStr> CalculateRandomRemainingSelections(uint32_t seed, const std::vector<std::set<CStr>>& initialSelections) const;
     137             : 
     138             :     // Get the variation key (indices of chosen variants from each group)
     139             :     // based on the selection strings.
     140             :     // Should not have to make a random choice: the selections should be complete.
     141             :     std::vector<u8> CalculateVariationKey(const std::vector<const std::set<CStr>*>& selections) const;
     142             : 
     143             :     // Get the final actor data, combining all selected variants
     144             :     const Variation BuildVariation(const std::vector<u8>& variationKey) const;
     145             : 
     146             :     // Get a list of variant groups for this object, plus for all possible
     147             :     // props. Duplicated groups are removed, if several props share the same
     148             :     // variant names.
     149             :     std::vector<std::vector<CStr> > GetVariantGroups() const;
     150             : 
     151             :     // Return a string identifying this actor uniquely (includes quality level information);
     152             :     const CStr& GetIdentifier() const;
     153             : 
     154             :     /**
     155             :      * Returns whether this object (including any possible props)
     156             :      * uses the given file. (This is used for hotloading.)
     157             :      */
     158             :     bool UsesFile(const VfsPath& pathname) const;
     159             : 
     160             : 
     161             :     struct {
     162             :         // cast shadows from this object
     163             :         bool m_CastShadows;
     164             :         // float on top of water
     165             :         bool m_FloatOnWater;
     166             :     } m_Properties;
     167             : 
     168             :     // the material file
     169             :     VfsPath m_Material;
     170             : 
     171             :     // Quality level - part of the data resource path.
     172             :     u8 m_QualityLevel;
     173             : 
     174             : private:
     175             :     // Private interface for CActorDef/ObjectEntry
     176             : 
     177             :     /**
     178             :      * Acts as an explicit copy constructor, for a new quality level.
     179             :      * Note that this does not reload the actor, so this setting will only change props.
     180             :      */
     181             :     std::unique_ptr<CObjectBase> CopyWithQuality(u8 newQualityLevel) const;
     182             : 
     183             :     // A low-quality RNG like rand48 causes visible non-random patterns (particularly
     184             :     // in large grids of the same actor with consecutive seeds, e.g. forests),
     185             :     // so use a better one that appears to avoid those patterns
     186             :     using rng_t = boost::mt19937;
     187             :     std::set<CStr> CalculateRandomRemainingSelections(rng_t& rng, const std::vector<std::set<CStr>>& initialSelections) const;
     188             : 
     189             :     /**
     190             :      * Get all quality levels at which this object changes (includes props).
     191             :      * Intended to be called by CActorFef.
     192             :      * @param splits - a sorted vector of unique quality splits.
     193             :      */
     194             :     void GetQualitySplits(std::vector<u8>& splits) const;
     195             : 
     196             :     [[nodiscard]] bool Load(const CXeromyces& XeroFile, const XMBElement& base);
     197             :     [[nodiscard]] bool LoadVariant(const CXeromyces& XeroFile, const XMBElement& variant, Variant& currentVariant);
     198             : 
     199             : private:
     200             :     // Backref to the owning actor.
     201             :     CActorDef& m_ActorDef;
     202             : 
     203             :     // Used to identify this actor uniquely in the ObjectManager (and for debug).
     204             :     CStr m_Identifier;
     205             : 
     206             :     std::vector< std::vector<Variant> > m_VariantGroups;
     207             :     CObjectManager& m_ObjectManager;
     208             : };
     209             : 
     210             : /**
     211             :  * Represents an actor file. Actors can contain various quality levels.
     212             :  * An ActorDef maintains a CObjectBase for each specified quality level, and provides access to it.
     213             :  */
     214           0 : class CActorDef
     215             : {
     216             :     // Friend these three so they can use GetBase.
     217             :     friend class CObjectManager;
     218             :     friend class CObjectBase;
     219             :     friend class CObjectEntry;
     220             : 
     221             :     NONCOPYABLE(CActorDef);
     222             : public:
     223             : 
     224             :     CActorDef(CObjectManager& objectManager);
     225             : 
     226             :     std::vector<u8> QualityLevels() const;
     227             : 
     228           0 :     VfsPath GetPathname() const { return m_Pathname; }
     229             : 
     230             :     /**
     231             :      * Return a list of selections specifying a particular variant in all groups, based on the seed.
     232             :      */
     233             :     std::set<CStr> PickSelectionsAtRandom(uint32_t seed) const;
     234             : 
     235             : // Interface accessible from CObjectManager / CObjectBase
     236             : protected:
     237             :     /**
     238             :      * Return the Object base matching the given quality level.
     239             :      */
     240             :     const std::shared_ptr<CObjectBase>& GetBase(u8 QualityLevel) const;
     241             : 
     242             :     /**
     243             :      * Initialise this object by loading from the given file.
     244             :      * Returns false on error.
     245             :      */
     246             :     bool Load(const VfsPath& pathname);
     247             : 
     248             :     /**
     249             :      * Initialise this object with a default placeholder actor,
     250             :      * pretending to be the actor at pathname.
     251             :      */
     252             :     void LoadErrorPlaceholder(const VfsPath& pathname);
     253             : 
     254             :     /**
     255             :      * Returns whether this actor (including any possible props)
     256             :      * uses the given file. (This is used for hotloading.)
     257             :      */
     258             :     bool UsesFile(const VfsPath& pathname) const;
     259             : 
     260             :     // filename that this was loaded from
     261             :     VfsPath m_Pathname;
     262             : 
     263             : private:
     264             :     CObjectManager& m_ObjectManager;
     265             : 
     266             :     // std::shared_ptr to avoid issues during hotloading.
     267             :     std::vector<std::shared_ptr<CObjectBase>> m_ObjectBases;
     268             : 
     269             :     std::unordered_set<VfsPath> m_UsedFiles;
     270             : };
     271             : 
     272             : #endif

Generated by: LCOV version 1.13