Index: ps/trunk/source/renderer/RenderingOptions.h =================================================================== --- ps/trunk/source/renderer/RenderingOptions.h (revision 25902) +++ ps/trunk/source/renderer/RenderingOptions.h (revision 25903) @@ -1,123 +1,122 @@ /* Copyright (C) 2021 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 . */ /** * Keeps track of the settings used for rendering. * Ideally this header file should remain very quick to parse, * so avoid including other headers here unless absolutely necessary. * * Lifetime concerns: g_RenderingOptions always exists, but hooks are tied to the configDB's lifetime * an the renderer may or may not actually exist. */ #ifndef INCLUDED_RENDERINGOPTIONS #define INCLUDED_RENDERINGOPTIONS -class CConfigDB; class CStr8; class CRenderer; enum RenderPath { // If no rendering path is configured explicitly, the renderer // will choose the path when Open() is called. DEFAULT, // Classic fixed function. FIXED, // Use new ARB/GLSL system SHADER }; struct RenderPathEnum { static RenderPath FromString(const CStr8& name); static CStr8 ToString(RenderPath); }; class CRenderingOptions { // The renderer needs access to our private variables directly because capabilities have not yet been extracted // and thus sometimes it needs to change the rendering options without the side-effects. friend class CRenderer; public: CRenderingOptions(); ~CRenderingOptions(); void ReadConfigAndSetupHooks(); void ClearHooks(); #define OPTION_DEFAULT_SETTER(NAME, TYPE) \ public: void Set##NAME(TYPE value) { m_##NAME = value; }\ #define OPTION_CUSTOM_SETTER(NAME, TYPE) \ public: void Set##NAME(TYPE value);\ #define OPTION_GETTER(NAME, TYPE)\ public: TYPE Get##NAME() const { return m_##NAME; }\ #define OPTION_DEF(NAME, TYPE)\ private: TYPE m_##NAME; #define OPTION(NAME, TYPE)\ OPTION_DEFAULT_SETTER(NAME, TYPE); OPTION_GETTER(NAME, TYPE); OPTION_DEF(NAME, TYPE); #define OPTION_WITH_SIDE_EFFECT(NAME, TYPE)\ OPTION_CUSTOM_SETTER(NAME, TYPE); OPTION_GETTER(NAME, TYPE); OPTION_DEF(NAME, TYPE); OPTION_WITH_SIDE_EFFECT(Shadows, bool); OPTION_WITH_SIDE_EFFECT(ShadowPCF, bool); OPTION_WITH_SIDE_EFFECT(PreferGLSL, bool); OPTION_WITH_SIDE_EFFECT(Fog, bool); OPTION_WITH_SIDE_EFFECT(RenderPath, RenderPath); OPTION(WaterEffects, bool); OPTION(WaterFancyEffects, bool); OPTION(WaterRealDepth, bool); OPTION(WaterRefraction, bool); OPTION(WaterReflection, bool); OPTION(ShadowAlphaFix, bool); OPTION(ARBProgramShadow, bool); OPTION(Particles, bool); OPTION(ForceAlphaTest, bool); OPTION(GPUSkinning, bool); OPTION(Silhouettes, bool); OPTION(SmoothLOS, bool); OPTION(PostProc, bool); OPTION(DisplayFrustum, bool); OPTION(DisplayShadowsFrustum, bool); OPTION(RenderActors, bool); #undef OPTION_DEFAULT_SETTER #undef OPTION_CUSTOM_SETTER #undef OPTION_GETTER #undef OPTION_DEF #undef OPTION #undef OPTION_WITH_SIDE_EFFECT private: class ConfigHooks; std::unique_ptr m_ConfigHooks; // Hide this via PImpl to avoid including ConfigDB.h here. }; extern CRenderingOptions g_RenderingOptions; #endif // INCLUDED_RENDERINGOPTIONS Index: ps/trunk/source/renderer/TerrainRenderer.h =================================================================== --- ps/trunk/source/renderer/TerrainRenderer.h (revision 25902) +++ ps/trunk/source/renderer/TerrainRenderer.h (revision 25903) @@ -1,167 +1,166 @@ /* Copyright (C) 2021 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 . */ /* * Terrain rendering (everything related to patches and water) is * encapsulated in TerrainRenderer */ #ifndef INCLUDED_TERRAINRENDERER #define INCLUDED_TERRAINRENDERER #include "graphics/Color.h" #include "maths/BoundingBoxAligned.h" class CCamera; class CMatrix3D; class CModelDecal; class CPatch; class CShaderDefines; class CSimulation2; class ShadowMap; -class WaterManager; struct TerrainRendererInternals; /** * Class TerrainRenderer: Render everything related to the terrain, * especially patches and water. */ class TerrainRenderer { friend class CPatchRData; friend class CDecalRData; public: TerrainRenderer(); ~TerrainRenderer(); /** * Set the simulation context for this frame. * Call at start of frame, before any other Submits. */ void SetSimulation(CSimulation2* simulation); /** * Submit: Add a patch for rendering in this frame. * * preconditions : PrepareForRendering must not have been called * for this frame yet. * The patch must not have been submitted in this frame yet (i.e. you * can only submit a frame once). * * @param patch the patch */ void Submit(int cullGroup, CPatch* patch); /** * Submit: Add a terrain decal for rendering in this frame. */ void Submit(int cullGroup, CModelDecal* decal); /** * PrepareForRendering: Prepare internal data structures like vertex * buffers for rendering. * * All patches must have been submitted before the call to * PrepareForRendering. * PrepareForRendering must be called before any rendering calls. */ void PrepareForRendering(); /** * EndFrame: Remove all patches from the list of submitted patches. */ void EndFrame(); /** * Render textured terrain (including blends between * different terrain types). * * preconditions : PrepareForRendering must have been called this * frame before calling RenderTerrain. * * @param shadow A prepared shadow map, in case rendering with shadows is enabled. */ void RenderTerrainShader(const CShaderDefines& context, int cullGroup, ShadowMap* shadow); /** * RenderPatches: Render all patches un-textured as polygons. * * preconditions : PrepareForRendering must have been called this * frame before calling RenderPatches. * * @param filtered If true then only render objects that passed CullPatches. * @param color Fill color of the patches. */ void RenderPatches(int cullGroup, const CColor& color = CColor(0.0f, 0.0f, 0.0f, 1.0f)); /** * RenderOutlines: Render the outline of patches as lines. * * preconditions : PrepareForRendering must have been called this * frame before calling RenderOutlines. * * @param filtered If true then only render objects that passed CullPatches. */ void RenderOutlines(int cullGroup); /** * RenderWater: Render water for all patches that have been submitted * this frame. * * preconditions : PrepareForRendering must have been called this * frame before calling RenderWater. */ void RenderWater(const CShaderDefines& context, int cullGroup, ShadowMap* shadow); /** * Calculate a scissor rectangle for the visible water patches. */ CBoundingBoxAligned ScissorWater(int cullGroup, const CCamera& camera); /** * Render priority text for all submitted patches, for debugging. */ void RenderPriorities(int cullGroup); /** * Render texture unit 0 over the terrain mesh, with UV coords calculated * by the given texture matrix. * Intended for use by TerrainTextureOverlay. */ void RenderTerrainOverlayTexture(int cullGroup, CMatrix3D& textureMatrix, GLuint texture); private: TerrainRendererInternals* m; /** * RenderFancyWater: internal rendering method for fancy water. * Returns false if unable to render with fancy water. */ bool RenderFancyWater(const CShaderDefines& context, int cullGroup, ShadowMap* shadow); /** * RenderSimpleWater: internal rendering method for water */ void RenderSimpleWater(int cullGroup); static void PrepareShader(const CShaderProgramPtr& shader, ShadowMap* shadow); }; #endif // INCLUDED_TERRAINRENDERER Index: ps/trunk/source/simulation2/components/ICmpGuiInterface.h =================================================================== --- ps/trunk/source/simulation2/components/ICmpGuiInterface.h (revision 25902) +++ ps/trunk/source/simulation2/components/ICmpGuiInterface.h (revision 25903) @@ -1,37 +1,35 @@ -/* Copyright (C) 2010 Wildfire Games. +/* Copyright (C) 2021 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_ICMPGUIINTERFACE #define INCLUDED_ICMPGUIINTERFACE #include "simulation2/system/Interface.h" -struct CColor; - class ICmpGuiInterface : public IComponent { public: /** * Generic call function, for use by GUI scripts to talk to the GuiInterface script. */ virtual void ScriptCall(int player, const std::wstring& cmd, JS::HandleValue data, JS::MutableHandleValue ret) = 0; // TODO: some of the earlier functions should just use ScriptCall. DECLARE_INTERFACE_TYPE(GuiInterface) }; #endif // INCLUDED_ICMPGUIINTERFACE Index: ps/trunk/source/soundmanager/scripting/SoundGroup.h =================================================================== --- ps/trunk/source/soundmanager/scripting/SoundGroup.h (revision 25902) +++ ps/trunk/source/soundmanager/scripting/SoundGroup.h (revision 25903) @@ -1,117 +1,116 @@ /* Copyright (C) 2021 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_SOUNDGROUP_H #define INCLUDED_SOUNDGROUP_H #include "lib/config2.h" #include "lib/file/vfs/vfs_path.h" #include "lib/types.h" #include "simulation2/system/Entity.h" #include "soundmanager/data/SoundData.h" #include class CVector3D; -class ISoundItem; enum eSndGrpFlags { eRandOrder = 0x01, eRandGain = 0x02, eRandPitch = 0x04, eLoop = 0x08, eOmnipresent = 0x10, eDistanceless = 0x20, eOwnerOnly = 0x40 }; // Loads up a group of sound files with shared properties, // and provides a simple interface for playing them. class CSoundGroup { NONCOPYABLE(CSoundGroup); public: CSoundGroup(const VfsPath& pathnameXML); CSoundGroup(); ~CSoundGroup(); // Play next sound in group // @param position world position of the entity generating the sound // (ignored if the eOmnipresent flag is set) void PlayNext(const CVector3D& position, entity_id_t source); float RadiansOffCenter(const CVector3D& position, bool& onScreen, float& itemRollOff); // Load a group bool LoadSoundGroup(const VfsPath& pathnameXML); void Reload(); // Release all remaining loaded handles void ReleaseGroup(); // Update SoundGroup, remove dead sounds from intensity count void Update(float TimeSinceLastFrame); // Set a flag using a value from eSndGrpFlags inline void SetFlag(int flag) { m_Flags = (unsigned char)(m_Flags | flag); } // Test flag, returns true if flag is set. inline bool TestFlag(int flag) { return (m_Flags & flag) != 0; } private: void SetGain(float gain); void UploadPropertiesAndPlay(size_t theIndex, const CVector3D& position, entity_id_t source); void SetDefaultValues(); #if CONFIG2_AUDIO // We store the handles so we can load now and play later std::vector m_SoundGroups; #endif u32 m_Seed; // We need the filenames so we can reload when necessary. std::vector m_Filenames; // The file path for the list of sound file resources VfsPath m_Filepath; size_t m_CurrentSoundIndex; float m_ConeInnerAngle; float m_ConeOuterAngle; float m_ConeOuterGain; // Time elapsed since soundgroup was created float m_CurTime; float m_Decay; float m_Gain; float m_GainUpper; float m_GainLower; // Distance attenuation settings float m_MinDist; float m_MaxDist; // How much stereo separation to apply to sounds based on L-R position relative to the camera. float m_MaxStereoAngle; // The allowable intensity before a sound switch float m_IntensityThreshold; float m_Pitch; float m_PitchLower; float m_PitchUpper; float m_Priority; // Up to eight individual parameters, use with eSndGrpFlags. u8 m_Flags; }; #endif //#ifndef INCLUDED_SOUNDGROUP_H Index: ps/trunk/source/collada/CommonConvert.h =================================================================== --- ps/trunk/source/collada/CommonConvert.h (revision 25902) +++ ps/trunk/source/collada/CommonConvert.h (revision 25903) @@ -1,181 +1,180 @@ -/* Copyright (C) 2015 Wildfire Games. +/* Copyright (C) 2021 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_COMMONCONVERT #define INCLUDED_COMMONCONVERT #include #include #include #include class FCDEntityInstance; class FCDSceneNode; class FCDSkinController; class FMMatrix44; -class FUStatus; class Skeleton; class ColladaException : public std::exception { public: ColladaException(const std::string& msg) : msg(msg) { } ~ColladaException() throw() { } virtual const char* what() const throw() { return msg.c_str(); } private: std::string msg; }; struct OutputCB { virtual ~OutputCB() { } virtual void operator() (const char* data, unsigned int length)=0; }; /** * Standard error handler - logs FCollada messages using Log(), and also * maintains a list of XML parser errors. */ class FColladaErrorHandler { public: FColladaErrorHandler(std::string& xmlErrors); ~FColladaErrorHandler(); private: void OnError(FUError::Level errorLevel, uint32 errorCode, uint32 lineNumber); std::string& xmlErrors; void operator=(FColladaErrorHandler); }; /** * Standard document loader. Based on FCDocument::LoadFromText, but allows * access to \ nodes at the document level (i.e. directly in \). */ class FColladaDocument { public: /** * Loads the document from the given XML string. Should be the first function * called on this object, and should only be called once. * @throws ColladaException if unable to load. */ void LoadFromText(const char* text); /** Returns the FCDocument that was loaded. */ FCDocument* GetDocument() const { return document.get(); } /** Returns the \ data from the \ element. */ FCDExtra* GetExtra() const { return extra.get(); } private: void ReadExtras(xmlNode* colladaNode); std::unique_ptr document; std::unique_ptr extra; }; /** * Wrapper for code shared between the PMD and PSA converters. Loads the document * and provides access to the relevant objects and values. */ class CommonConvert { public: CommonConvert(const char* text, std::string& xmlErrors); ~CommonConvert(); const FColladaDocument& GetDocument() const { return m_Doc; } FCDSceneNode& GetRoot() { return *m_Doc.GetDocument()->GetVisualSceneRoot(); } FCDEntityInstance& GetInstance() { return *m_Instance; } const FMMatrix44& GetEntityTransform() const { return m_EntityTransform; } bool IsYUp() const { return m_YUp; } bool IsXSI() const { return m_IsXSI; } private: FColladaErrorHandler m_Err; FColladaDocument m_Doc; FCDEntityInstance* m_Instance; FMMatrix44 m_EntityTransform; bool m_YUp; bool m_IsXSI; }; /** Throws a ColladaException unless the value is true. */ #define REQUIRE(value, message) require_(__LINE__, value, "Assertion not satisfied", "failed requirement \"" message "\"") /** Throws a ColladaException unless the status is successful. */ #define REQUIRE_SUCCESS(status) require_(__LINE__, status, "FCollada error", "Line " STRINGIFY(__LINE__)) #define STRINGIFY(x) #x void require_(int line, bool value, const char* type, const char* message); /** Outputs a structure, using sizeof to get the size. */ template void write(OutputCB& output, const T& data) { output((char*)&data, sizeof(T)); } /** * Tries to find a single suitable entity instance in the scene. Fails if there * are none, or if there are too many and it's not clear which one should * be converted. * * @param node root scene node to search under * @param instance output - the found entity instance (if any) * @param transform - the world-space transform of the found entity * * @return true if one was found */ bool FindSingleInstance(FCDSceneNode* node, FCDEntityInstance*& instance, FMMatrix44& transform); /** * Like FCDSkinController::ReduceInfluences but works correctly. * Additionally, multiple influences for the same joint-vertex pair are * collapsed into a single influence. */ void SkinReduceInfluences(FCDSkinController* skin, size_t maxInfluenceCount, float minimumWeight); /** * Fixes some occasional problems with the skeleton root definitions in a * controller. (In particular, it's needed for models exported from XSI.) * Should be called before extracting any joint information from the controller. */ void FixSkeletonRoots(FCDControllerInstance& controllerInstance); /** * Finds the skeleton definition which best matches the given controller. * @throws ColladaException if none is found. */ const Skeleton& FindSkeleton(const FCDControllerInstance& controllerInstance); /** Bone pose data */ struct BoneTransform { float translation[3]; float orientation[4]; }; /** * Performs the standard transformations on bones, applying a scale matrix and * moving them into the game's coordinate space. */ void TransformBones(std::vector& bones, const FMMatrix44& scaleTransform, bool yUp); extern FMMatrix44 FMMatrix44_Identity; #endif // INCLUDED_COMMONCONVERT Index: ps/trunk/source/graphics/ColladaManager.h =================================================================== --- ps/trunk/source/graphics/ColladaManager.h (revision 25902) +++ ps/trunk/source/graphics/ColladaManager.h (revision 25903) @@ -1,68 +1,66 @@ -/* Copyright (C) 2013 Wildfire Games. +/* Copyright (C) 2021 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_COLLADAMANAGER #define INCLUDED_COLLADAMANAGER #include "lib/file/vfs/vfs.h" -class CStr8; class CColladaManagerImpl; -class MD5; class CColladaManager { NONCOPYABLE(CColladaManager); public: enum FileType { PMD, PSA }; CColladaManager(const PIVFS& vfs); ~CColladaManager(); /** * Returns the VFS path to a PMD/PSA file for the given source file. * Performs a (cached) conversion from COLLADA if necessary. * * @param pathnameNoExtension path and name, minus extension, of file to load. * One of either "sourceName.pmd" or "sourceName.dae" should exist. * @param type FileType, .pmd or .psa * * @return full VFS path (including extension) of file to load; or empty * string if there was a problem and it could not be loaded. Doesn't knowingly * return an invalid path. */ VfsPath GetLoadablePath(const VfsPath& pathnameNoExtension, FileType type); /** * Converts DAE to archive cached .pmd/psa and outputs the resulting path * (used by archive builder) * * @param[in] sourcePath path of the .dae to load * @param[in] type FileType, .pmd or .psa * @param[out] archiveCachePath output path of the cached file * * @return true if COLLADA converter completed successfully; or false if it failed */ bool GenerateCachedFile(const VfsPath& sourcePath, FileType type, VfsPath& archiveCachePath); private: CColladaManagerImpl* m; PIVFS m_VFS; }; #endif // INCLUDED_COLLADAMANAGER Index: ps/trunk/source/graphics/Font.h =================================================================== --- ps/trunk/source/graphics/Font.h (revision 25902) +++ ps/trunk/source/graphics/Font.h (revision 25903) @@ -1,101 +1,99 @@ /* Copyright (C) 2021 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_FONT #define INCLUDED_FONT #include "graphics/Texture.h" #include "lib/res/handle.h" -struct UnifontGlyphData; - /** * Storage for a bitmap font. Loaded by CFontManager. */ class CFont { friend class CFontManager; CFont() {} public: struct GlyphData { float u0, v0, u1, v1; i16 x0, y0, x1, y1; i16 xadvance; u8 defined; }; /** * Relatively efficient lookup of GlyphData from 16-bit Unicode codepoint. * This is stored as a sparse 2D array, exploiting the knowledge that a font * typically only supports a small number of 256-codepoint blocks, so most * elements of m_Data will be NULL. */ class GlyphMap { NONCOPYABLE(GlyphMap); public: GlyphMap(); ~GlyphMap(); void set(u16 i, const GlyphData& val); const GlyphData* get(u16 i) const { if (!m_Data[i >> 8]) return NULL; if (!m_Data[i >> 8][i & 0xff].defined) return NULL; return &m_Data[i >> 8][i & 0xff]; } private: GlyphData* m_Data[256]; }; bool HasRGB() const { return m_HasRGB; } int GetLineSpacing() const { return m_LineSpacing; } int GetHeight() const { return m_Height; } int GetCharacterWidth(wchar_t c) const; void CalculateStringSize(const wchar_t* string, int& w, int& h) const; void GetGlyphBounds(float& x0, float& y0, float& x1, float& y1) const { x0 = m_BoundsX0; y0 = m_BoundsY0; x1 = m_BoundsX1; y1 = m_BoundsY1; } const GlyphMap& GetGlyphs() const { return m_Glyphs; } CTexturePtr GetTexture() const { return m_Texture; } private: CTexturePtr m_Texture; bool m_HasRGB; // true if RGBA, false if ALPHA GlyphMap m_Glyphs; int m_LineSpacing; int m_Height; // height of a capital letter, roughly // Bounding box of all glyphs float m_BoundsX0; float m_BoundsY0; float m_BoundsX1; float m_BoundsY1; }; #endif // INCLUDED_FONT Index: ps/trunk/source/graphics/MapReader.h =================================================================== --- ps/trunk/source/graphics/MapReader.h (revision 25902) +++ ps/trunk/source/graphics/MapReader.h (revision 25903) @@ -1,183 +1,182 @@ /* Copyright (C) 2021 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_MAPREADER #define INCLUDED_MAPREADER #include "MapIO.h" #include "graphics/LightEnv.h" #include "lib/res/handle.h" #include "ps/CStr.h" #include "ps/FileIo.h" #include "scriptinterface/ScriptTypes.h" #include "simulation2/system/Entity.h" -class CObjectEntry; class CTerrain; class WaterManager; class SkyManager; class CLightEnv; class CCinemaManager; class CPostprocManager; class CTriggerManager; class CSimulation2; class CSimContext; class CTerrainTextureEntry; class CGameView; class CXMLReader; class CMapGenerator; class ScriptContext; class ScriptInterface; class CMapReader : public CMapIO { friend class CXMLReader; public: // constructor CMapReader(); ~CMapReader(); // LoadMap: try to load the map from given file; reinitialise the scene to new data if successful void LoadMap(const VfsPath& pathname, const ScriptContext& cx, JS::HandleValue settings, CTerrain*, WaterManager*, SkyManager*, CLightEnv*, CGameView*, CCinemaManager*, CTriggerManager*, CPostprocManager* pPostproc, CSimulation2*, const CSimContext*, int playerID, bool skipEntities); void LoadRandomMap(const CStrW& scriptFile, const ScriptContext& cx, JS::HandleValue settings, CTerrain*, WaterManager*, SkyManager*, CLightEnv*, CGameView*, CCinemaManager*, CTriggerManager*, CPostprocManager* pPostproc_, CSimulation2*, int playerID); private: // Load script settings for use by scripts int LoadScriptSettings(); // load player settings only int LoadPlayerSettings(); // load map settings only int LoadMapSettings(); // UnpackTerrain: unpack the terrain from the input stream int UnpackTerrain(); // UnpackCinema: unpack the cinematic tracks from the input stream int UnpackCinema(); // UnpackMap: unpack the given data from the raw data stream into local variables int UnpackMap(); // ApplyData: take all the input data, and rebuild the scene from it int ApplyData(); int ApplyTerrainData(); // read some misc data from the XML file int ReadXML(); // read entity data from the XML file int ReadXMLEntities(); // Copy random map settings over to sim int LoadRMSettings(); // Generate random map int GenerateMap(); // Parse script data into terrain int ParseTerrain(); // Parse script data into entities int ParseEntities(); // Parse script data into environment int ParseEnvironment(); // Parse script data into camera int ParseCamera(); // size of map ssize_t m_PatchesPerSide; // heightmap for map std::vector m_Heightmap; // list of terrain textures used by map std::vector m_TerrainTextures; // tile descriptions for each tile std::vector m_Tiles; // lightenv stored in file CLightEnv m_LightEnv; // startup script CStrW m_Script; // random map data CStrW m_ScriptFile; JS::PersistentRootedValue m_ScriptSettings; JS::PersistentRootedValue m_MapData; CMapGenerator* m_MapGen; CFileUnpacker unpacker; CTerrain* pTerrain; WaterManager* pWaterMan; SkyManager* pSkyMan; CPostprocManager* pPostproc; CLightEnv* pLightEnv; CGameView* pGameView; CCinemaManager* pCinema; CTriggerManager* pTrigMan; CSimulation2* pSimulation2; const CSimContext* pSimContext; int m_PlayerID; bool m_SkipEntities; VfsPath filename_xml; bool only_xml; u32 file_format_version; entity_id_t m_StartingCameraTarget; CVector3D m_StartingCamera; // UnpackTerrain generator state size_t cur_terrain_tex; size_t num_terrain_tex; CXMLReader* xml_reader; }; /** * A restricted map reader that returns various summary information * for use by scripts (particularly the GUI). */ class CMapSummaryReader { public: /** * Try to load a map file. * @param pathname Path to .pmp or .xml file */ PSRETURN LoadMap(const VfsPath& pathname); /** * Returns a value of the form: * @code * { * "settings": { ... contents of the map's ... } * } * @endcode */ void GetMapSettings(const ScriptInterface& scriptInterface, JS::MutableHandleValue); private: CStr m_ScriptSettings; }; #endif Index: ps/trunk/source/graphics/MapWriter.h =================================================================== --- ps/trunk/source/graphics/MapWriter.h (revision 25902) +++ ps/trunk/source/graphics/MapWriter.h (revision 25903) @@ -1,71 +1,68 @@ /* Copyright (C) 2021 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_MAPWRITER #define INCLUDED_MAPWRITER #include "MapIO.h" #include "ps/CStr.h" #include "ps/FileIo.h" #include class CLightEnv; class CTerrain; class CCamera; class CCinemaManager; class CPostprocManager; -class CTriggerManager; class WaterManager; class SkyManager; class CSimulation2; struct MapTrigger; -struct MapTriggerGroup; -class XMLWriter_File; class CMapWriter : public CMapIO { public: // constructor CMapWriter(); // SaveMap: try to save the current map to the given file void SaveMap(const VfsPath& pathname, CTerrain* pTerr, WaterManager* pWaterMan, SkyManager* pSkyMan, CLightEnv* pLightEnv, CCamera* pCamera, CCinemaManager* pCinema, CPostprocManager* pPostproc, CSimulation2* pSimulation2); private: // PackMap: pack the current world into a raw data stream void PackMap(CFilePacker& packer, CTerrain* pTerrain); // PackTerrain: pack the terrain onto the end of the data stream void PackTerrain(CFilePacker& packer, CTerrain* pTerrain); // EnumTerrainTextures: build lists of textures used by map, and indices into this list // for each tile on the terrain void EnumTerrainTextures(CTerrain* pTerrain, std::vector& textures, std::vector& tileIndices); // WriteXML: output some other data (entities, etc) in XML format void WriteXML(const VfsPath& pathname, WaterManager* pWaterMan, SkyManager* pSkyMan, CLightEnv* pLightEnv, CCamera* pCamera, CPostprocManager* pPostproc, CSimulation2* pSimulation2); }; #endif Index: ps/trunk/source/graphics/ObjectBase.h =================================================================== --- ps/trunk/source/graphics/ObjectBase.h (revision 25902) +++ ps/trunk/source/graphics/ObjectBase.h (revision 25903) @@ -1,274 +1,272 @@ /* Copyright (C) 2021 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_OBJECTBASE #define INCLUDED_OBJECTBASE #include "lib/file/vfs/vfs_path.h" #include "ps/CStr.h" #include "ps/CStrIntern.h" class CActorDef; -class CModel; class CObjectEntry; class CObjectManager; -class CSkeletonAnim; class CXeromyces; class XMBElement; #include #include #include #include #include #include /** * Maintains the tree of possible objects from a specific actor definition at a given quality level. * An Object Base is made of: * - a material * - a few properties (float on water / casts shadow / ...) * - a number of variant groups. * Any actual object in game will pick a variant from each group (see ObjectEntry). */ class CObjectBase { friend CActorDef; // See CopyWithQuality() below. NONCOPYABLE(CObjectBase); public: struct Anim { // constructor Anim() : m_Frequency(0), m_Speed(1.f), m_ActionPos(-1.f), m_ActionPos2(-1.f), m_SoundPos(-1.f) {} // name of the animation - "Idle", "Run", etc CStr m_AnimName; // ID of the animation: if not empty, something specific to sync with props. CStr m_ID = ""; int m_Frequency; // filename of the animation - manidle.psa, manrun.psa, etc VfsPath m_FileName; // animation speed, as specified in XML actor file float m_Speed; // fraction [0.0, 1.0] of the way through the animation that the interesting bit(s) // happens, or -1.0 if unspecified float m_ActionPos; float m_ActionPos2; float m_SoundPos; }; struct Prop { // constructor Prop() : m_minHeight(0.f), m_maxHeight(0.f), m_selectable(true) {} // name of the prop point to attach to - "Prop01", "Prop02", "Head", "LeftHand", etc .. CStr m_PropPointName; // name of the model file - art/actors/props/sword.xml or whatever CStrW m_ModelName; // allow the prop to ajust the height from minHeight to maxHeight relative to the main model float m_minHeight; float m_maxHeight; bool m_selectable; }; struct Samp { // identifier name of sampler in GLSL shaders CStrIntern m_SamplerName; // path to load from VfsPath m_SamplerFile; }; struct Decal { Decal() : m_SizeX(0.f), m_SizeZ(0.f), m_Angle(0.f), m_OffsetX(0.f), m_OffsetZ(0.f) {} float m_SizeX; float m_SizeZ; float m_Angle; float m_OffsetX; float m_OffsetZ; }; struct Variant { Variant() : m_Frequency(0) {} CStr m_VariantName; // lowercase name int m_Frequency; VfsPath m_ModelFilename; Decal m_Decal; VfsPath m_Particles; CStr m_Color; std::vector m_Anims; std::vector m_Props; std::vector m_Samplers; }; struct Variation { VfsPath model; Decal decal; VfsPath particles; CStr color; std::multimap props; std::multimap anims; std::multimap samplers; }; CObjectBase(CObjectManager& objectManager, CActorDef& actorDef, u8 QualityLevel); // Returns a set of selection such that, added to initialSelections, CalculateVariationKey can proceed. std::set CalculateRandomRemainingSelections(uint32_t seed, const std::vector>& initialSelections) const; // Get the variation key (indices of chosen variants from each group) // based on the selection strings. // Should not have to make a random choice: the selections should be complete. std::vector CalculateVariationKey(const std::vector*>& selections) const; // Get the final actor data, combining all selected variants const Variation BuildVariation(const std::vector& variationKey) const; // Get a list of variant groups for this object, plus for all possible // props. Duplicated groups are removed, if several props share the same // variant names. std::vector > GetVariantGroups() const; // Return a string identifying this actor uniquely (includes quality level information); const CStr& GetIdentifier() const; /** * Returns whether this object (including any possible props) * uses the given file. (This is used for hotloading.) */ bool UsesFile(const VfsPath& pathname) const; struct { // cast shadows from this object bool m_CastShadows; // float on top of water bool m_FloatOnWater; } m_Properties; // the material file VfsPath m_Material; // Quality level - part of the data resource path. u8 m_QualityLevel; private: // Private interface for CActorDef/ObjectEntry /** * Acts as an explicit copy constructor, for a new quality level. * Note that this does not reload the actor, so this setting will only change props. */ std::unique_ptr CopyWithQuality(u8 newQualityLevel) const; // A low-quality RNG like rand48 causes visible non-random patterns (particularly // in large grids of the same actor with consecutive seeds, e.g. forests), // so use a better one that appears to avoid those patterns using rng_t = boost::mt19937; std::set CalculateRandomRemainingSelections(rng_t& rng, const std::vector>& initialSelections) const; /** * Get all quality levels at which this object changes (includes props). * Intended to be called by CActorFef. * @param splits - a sorted vector of unique quality splits. */ void GetQualitySplits(std::vector& splits) const; [[nodiscard]] bool Load(const CXeromyces& XeroFile, const XMBElement& base); [[nodiscard]] bool LoadVariant(const CXeromyces& XeroFile, const XMBElement& variant, Variant& currentVariant); private: // Backref to the owning actor. CActorDef& m_ActorDef; // Used to identify this actor uniquely in the ObjectManager (and for debug). CStr m_Identifier; std::vector< std::vector > m_VariantGroups; CObjectManager& m_ObjectManager; }; /** * Represents an actor file. Actors can contain various quality levels. * An ActorDef maintains a CObjectBase for each specified quality level, and provides access to it. */ class CActorDef { // Friend these three so they can use GetBase. friend class CObjectManager; friend class CObjectBase; friend class CObjectEntry; NONCOPYABLE(CActorDef); public: CActorDef(CObjectManager& objectManager); std::vector QualityLevels() const; VfsPath GetPathname() const { return m_Pathname; } /** * Return a list of selections specifying a particular variant in all groups, based on the seed. */ std::set PickSelectionsAtRandom(uint32_t seed) const; // Interface accessible from CObjectManager / CObjectBase protected: /** * Return the Object base matching the given quality level. */ const std::shared_ptr& GetBase(u8 QualityLevel) const; /** * Initialise this object by loading from the given file. * Returns false on error. */ bool Load(const VfsPath& pathname); /** * Initialise this object with a default placeholder actor, * pretending to be the actor at pathname. */ void LoadErrorPlaceholder(const VfsPath& pathname); /** * Returns whether this actor (including any possible props) * uses the given file. (This is used for hotloading.) */ bool UsesFile(const VfsPath& pathname) const; // filename that this was loaded from VfsPath m_Pathname; private: CObjectManager& m_ObjectManager; // std::shared_ptr to avoid issues during hotloading. std::vector> m_ObjectBases; std::unordered_set m_UsedFiles; }; #endif Index: ps/trunk/source/graphics/ObjectEntry.h =================================================================== --- ps/trunk/source/graphics/ObjectEntry.h (revision 25902) +++ ps/trunk/source/graphics/ObjectEntry.h (revision 25903) @@ -1,93 +1,92 @@ /* Copyright (C) 2021 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_OBJECTENTRY #define INCLUDED_OBJECTENTRY class CModelAbstract; class CSkeletonAnim; class CObjectBase; class CObjectManager; class CSimulation2; -struct SPropPoint; #include #include #include #include "graphics/Color.h" #include "lib/file/vfs/vfs_path.h" #include "ps/CStr.h" #include "graphics/ObjectBase.h" class CObjectEntry { NONCOPYABLE(CObjectEntry); public: CObjectEntry(const std::shared_ptr& base, CSimulation2& simulation); ~CObjectEntry(); // Construct this actor, using the specified variation selections bool BuildVariation(const std::vector*>& completeSelections, const std::vector& variationKey, CObjectManager& objectManager); // Base actor. Contains all the things that don't change between // different variations of the actor. std::shared_ptr m_Base; // samplers list std::vector m_Samplers; // model name VfsPath m_ModelName; // color (used when doing alpha-channel coloring, but not doing player-color) CColor m_Color; // (probable TODO: make color a per-model thing, rather than per-objectEntry, // so we can have lots of color variations without wasting memory on // lots of objectEntries) std::wstring m_ProjectileModelName; /** * Returns a randomly-chosen animation matching the given ID, or animationName if ID is empty. * The chosen animation is picked randomly from the GetAnimations list * with the frequencies as weights (if there are any defined). * This method should always return an animation */ CSkeletonAnim* GetRandomAnimation(const CStr& animationName, const CStr& ID = "") const; /** * Returns all the animations matching the given ID or animationName if ID is empty. * If none found returns Idle animations (which are always added) */ std::vector GetAnimations(const CStr& animationName, const CStr& ID = "") const; // corresponding model CModelAbstract* m_Model; private: CSimulation2& m_Simulation; typedef std::multimap SkeletonAnimMap; SkeletonAnimMap m_Animations; // TODO: something more memory-efficient than storing loads of similar strings for each unit? }; #endif Index: ps/trunk/source/graphics/Overlay.h =================================================================== --- ps/trunk/source/graphics/Overlay.h (revision 25902) +++ ps/trunk/source/graphics/Overlay.h (revision 25903) @@ -1,201 +1,200 @@ /* Copyright (C) 2021 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_GRAPHICS_OVERLAY #define INCLUDED_GRAPHICS_OVERLAY #include "graphics/Color.h" #include "graphics/Texture.h" #include "maths/Vector2D.h" #include "maths/Vector3D.h" #include "ps/CStrIntern.h" #include class CFrustum; -class CTerrain; class CSimContext; class CTexturedLineRData; struct SOverlayDescriptor; /** * Line-based overlay, with world-space coordinates, rendered in the world * potentially behind other objects. Designed for debug info. */ struct SOverlayLine { SOverlayLine() : m_Thickness(0.1f) { } CColor m_Color; // Shape is not automatically closed. std::vector m_Coords; // Half-width of the line, in world-space units. float m_Thickness; void PushCoords(const CVector3D& v) { m_Coords.emplace_back(v); } void PushCoords(const float x, const float y, const float z) { m_Coords.emplace_back(x, y, z); } }; /** * Textured line overlay, with world-space coordinates, rendered in the world onto the terrain. * Designed for relatively static textured lines, i.e. territory borders, originally. * * Once submitted for rendering, instances must not be copied afterwards. The reason is that they * are assigned rendering data that is unique to the submitted instance, and non-transferable to * any copies that would otherwise be made. Amongst others, this restraint includes that they must * not be submitted by their address inside a std::vector storing them by value. */ struct SOverlayTexturedLine { enum LineCapType { LINECAP_FLAT, ///< no line ending; abrupt stop of the line (aka. butt ending) /** * Semi-circular line ending. The texture is mapped by curving the left vertical edge * around the semi-circle's rim. That is, the center point has UV coordinates (0.5;0.5), * and the rim vertices all have U coordinate 0 and a V coordinate that ranges from 0 to * 1 as the rim is traversed. */ LINECAP_ROUND, LINECAP_SHARP, ///< sharp point ending LINECAP_SQUARE, ///< square end that extends half the line width beyond the line end }; SOverlayTexturedLine() : m_Thickness(1.0f), m_Closed(false), m_AlwaysVisible(false), m_StartCapType(LINECAP_FLAT), m_EndCapType(LINECAP_FLAT), m_SimContext(NULL) { } CTexturePtr m_TextureBase; CTexturePtr m_TextureMask; /// Color to apply to the line texture, where indicated by the mask. CColor m_Color; /// (x, z) vertex coordinate pairs; y is computed automatically. std::vector m_Coords; /// Half-width of the line, in world-space units. float m_Thickness; /// Should this line be treated as a closed loop? If set, any end cap settings are ignored. bool m_Closed; /// Should this line be rendered fully visible at all times, even under the SoD? bool m_AlwaysVisible; LineCapType m_StartCapType; LineCapType m_EndCapType; /** * Simulation context applicable for this overlay line; used to obtain terrain information * during automatic computation of Y coordinates. */ const CSimContext* m_SimContext; /** * Cached renderer data, because expensive to compute. Allocated by the renderer when necessary * for rendering purposes. * * Note: the rendering data may be shared between copies of this object to prevent having to * recompute it, while at the same time maintaining copyability of this object (see also docs on * CTexturedLineRData). */ std::shared_ptr m_RenderData; /** * Converts a string line cap type into its corresponding LineCap enum value, and returns * the resulting value. If the input string is unrecognized, a warning is issued and a * default value is returned. */ static LineCapType StrToLineCapType(const std::wstring& str); /** * Creates the texture specified by the given overlay descriptor and assigns it to this overlay. */ void CreateOverlayTexture(const SOverlayDescriptor* overlayDescriptor); void PushCoords(const float x, const float z) { m_Coords.emplace_back(x, z); } void PushCoords(const CVector2D& v) { m_Coords.push_back(v); } void PushCoords(const std::vector& points) { for (const CVector2D& point : points) PushCoords(point); } bool IsVisibleInFrustum(const CFrustum& frustum) const; }; /** * 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; CColor m_Color; CVector3D m_Position; // base position float m_X0, m_Y0, m_X1, m_Y1; // billboard corner coordinates, relative to base position }; /** * Rectangular single-quad terrain overlay, in world space coordinates. The vertices of the quad * are not required to be coplanar; the quad is arbitrarily triangulated with no effort being made * to find a best fit to the underlying terrain. */ struct SOverlayQuad { CTexturePtr m_Texture; CTexturePtr m_TextureMask; CVector3D m_Corners[4]; CColor m_Color; }; struct SOverlaySphere { SOverlaySphere() : m_Radius(0) { } CVector3D m_Center; float m_Radius; CColor m_Color; }; enum EOverlayType { /// A single textured quad overlay, intended for entities that move around much, like units (e.g. foot soldiers, etc). DYNAMIC_QUAD, /// A more complex textured line overlay, composed of several textured line segments. STATIC_OUTLINE, }; struct SOverlayDescriptor { EOverlayType m_Type; CStrIntern m_QuadTexture; CStrIntern m_QuadTextureMask; CStrIntern m_LineTexture; CStrIntern m_LineTextureMask; float m_LineThickness; int m_Radius; SOverlayDescriptor() : m_LineThickness(0) { } }; // TODO: OverlayText #endif // INCLUDED_GRAPHICS_OVERLAY Index: ps/trunk/source/graphics/SkeletonAnimManager.h =================================================================== --- ps/trunk/source/graphics/SkeletonAnimManager.h (revision 25902) +++ ps/trunk/source/graphics/SkeletonAnimManager.h (revision 25903) @@ -1,56 +1,55 @@ /* Copyright (C) 2021 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 . */ /* * Owner of all skeleton animations */ #ifndef INCLUDED_SKELETONANIMMANAGER #define INCLUDED_SKELETONANIMMANAGER #include "lib/file/vfs/vfs_path.h" #include #include class CColladaManager; class CSkeletonAnimDef; -class CStr8; /////////////////////////////////////////////////////////////////////////////// // CSkeletonAnimManager : owner class of all skeleton anims - manages creation, // loading and destruction of animation data class CSkeletonAnimManager { NONCOPYABLE(CSkeletonAnimManager); public: // constructor, destructor CSkeletonAnimManager(CColladaManager& colladaManager); ~CSkeletonAnimManager(); // return a given animation by filename; return null if filename doesn't // refer to valid animation file CSkeletonAnimDef* GetAnimation(const VfsPath& pathname); private: // map of all known animations. Value is NULL if it failed to load. std::unordered_map> m_Animations; CColladaManager& m_ColladaManager; }; #endif Index: ps/trunk/source/graphics/TerrainTextureEntry.h =================================================================== --- ps/trunk/source/graphics/TerrainTextureEntry.h (revision 25902) +++ ps/trunk/source/graphics/TerrainTextureEntry.h (revision 25903) @@ -1,98 +1,95 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2021 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_TERRAINTEXTUREENTRY #define INCLUDED_TERRAINTEXTUREENTRY #include "TerrainTextureManager.h" #include "TextureManager.h" #include "Material.h" #include "lib/res/handle.h" #include "lib/file/vfs/vfs_path.h" #include "maths/Matrix3D.h" #include "ps/CStr.h" #include -class XMBElement; -class CXeromyces; - ////////////////////////////////////////////////////////////////////////////////////////////////////////// // CTerrainTextureEntry: class wrapping a terrain texture object; contains various other required // elements - color of minimap, terrain "group" it belongs to, etc class CTerrainTextureEntry { public: typedef std::vector GroupVector; private: // Tag = file name stripped of path and extension (grass_dark_1) CStr m_Tag; // The property sheet used by this texture CTerrainPropertiesPtr m_pProperties; CMaterial m_Material; CMatrix3D m_TextureMatrix; // BGRA color of topmost mipmap level, for coloring minimap, or a color // specified by the terrain properties u32 m_BaseColor; // ..Valid is true if the base color has been cached bool m_BaseColorValid; // All terrain type groups we're a member of GroupVector m_Groups; // calculate the root color of the texture, used for coloring minimap void BuildBaseColor(); void LoadAlphaMaps(VfsPath &amtype); public: // Most of the texture's data is delay-loaded, so after the constructor has // been called, the texture entry is ready to be used. CTerrainTextureEntry(CTerrainPropertiesPtr props, const VfsPath& path); ~CTerrainTextureEntry(); const CStr& GetTag() const { return m_Tag; } const CTerrainProperties& GetProperties() const { return *m_pProperties; } // Get texture handle, load texture if not loaded. const CTexturePtr& GetTexture() const { return m_Material.GetDiffuseTexture(); } const CMaterial& GetMaterial() const { return m_Material; } // Returns a matrix of the form [c 0 -s 0; -s 0 -c 0; 0 0 0 0; 0 0 0 1] // mapping world-space (x,y,z,1) coordinates onto (u,v,0,1) texcoords const float* GetTextureMatrix() const; // Get mipmap color in BGRA format u32 GetBaseColor() { if (!m_BaseColorValid) BuildBaseColor(); return m_BaseColor; } //TerrainAlpha *m_TerrainAlpha; CTerrainTextureManager::TerrainAlphaMap::iterator m_TerrainAlpha; }; #endif Index: ps/trunk/source/graphics/TerrainTextureManager.h =================================================================== --- ps/trunk/source/graphics/TerrainTextureManager.h (revision 25902) +++ ps/trunk/source/graphics/TerrainTextureManager.h (revision 25903) @@ -1,135 +1,133 @@ /* Copyright (C) 2021 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_TERRAINTEXTUREMANAGER #define INCLUDED_TERRAINTEXTUREMANAGER #include #include #include #include "lib/res/graphics/ogl_tex.h" #include "lib/res/handle.h" #include "lib/file/vfs/vfs_path.h" #include "ps/CStr.h" #include "ps/Singleton.h" // access to sole CTerrainTextureManager object #define g_TexMan CTerrainTextureManager::GetSingleton() #define NUM_ALPHA_MAPS 14 -class XMBElement; -class CXeromyces; class CTerrainTextureEntry; class CTerrainProperties; typedef std::shared_ptr CTerrainPropertiesPtr; class CTerrainGroup { // name of this terrain group (as specified by the terrain XML) CStr m_Name; // "index".. basically a bogus integer that can be used by ScEd to set texture // priorities size_t m_Index; // list of textures of this type (found from the texture directory) std::vector m_Terrains; public: CTerrainGroup(CStr name, size_t index): m_Name(name), m_Index(index) {} // Add a texture entry to this terrain type void AddTerrain(CTerrainTextureEntry*); // Remove a texture entry void RemoveTerrain(CTerrainTextureEntry*); size_t GetIndex() const { return m_Index; } CStr GetName() const { return m_Name; } const std::vector &GetTerrains() const { return m_Terrains; } }; struct TerrainAlpha { // ogl_tex handle of composite alpha map (all the alpha maps packed into one texture) Handle m_hCompositeAlphaMap; // coordinates of each (untransformed) alpha map within the packed texture struct { float u0,u1,v0,v1; } m_AlphaMapCoords[NUM_ALPHA_MAPS]; }; /////////////////////////////////////////////////////////////////////////////////////////// // CTerrainTextureManager : manager class for all terrain texture objects class CTerrainTextureManager : public Singleton { friend class CTerrainTextureEntry; public: typedef std::map TerrainGroupMap; typedef std::map TerrainAlphaMap; private: // All texture entries created by this class, for easy freeing now that // textures may be in several STextureType's std::vector m_TextureEntries; TerrainGroupMap m_TerrainGroups; TerrainAlphaMap m_TerrainAlphas; size_t m_LastGroupIndex; public: // constructor, destructor CTerrainTextureManager(); ~CTerrainTextureManager(); // Find all XML's in the directory (with subdirs) and try to load them as // terrain XML's int LoadTerrainTextures(); void UnloadTerrainTextures(); CTerrainTextureEntry* FindTexture(const CStr& tag) const; // Create a texture object for a new terrain texture at path, using the // property sheet props. CTerrainTextureEntry* AddTexture(const CTerrainPropertiesPtr& props, const VfsPath& path); // Remove the texture from all our maps and lists and delete it afterwards. void DeleteTexture(CTerrainTextureEntry* entry); // Find or create a new texture group. All terrain groups are owned by the // texturemanager (TerrainTypeManager) CTerrainGroup* FindGroup(const CStr& name); const TerrainGroupMap& GetGroups() const { return m_TerrainGroups; } }; #endif Index: ps/trunk/source/graphics/Unit.h =================================================================== --- ps/trunk/source/graphics/Unit.h (revision 25902) +++ ps/trunk/source/graphics/Unit.h (revision 25903) @@ -1,116 +1,115 @@ /* Copyright (C) 2021 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_UNIT #define INCLUDED_UNIT #include #include #include "ps/CStr.h" #include "simulation2/system/Entity.h" // entity_id_t class CActorDef; class CModelAbstract; class CObjectEntry; class CObjectManager; -class CSkeletonAnim; class CUnitAnimation; ///////////////////////////////////////////////////////////////////////////////////////////// // CUnit: simple "actor" definition - defines a sole object within the world class CUnit { NONCOPYABLE(CUnit); private: // Private constructor. Needs complete list of selections for the variation. CUnit(CObjectManager& objectManager, const CActorDef& actor, uint32_t seed); public: // Attempt to create a unit with the given actor. // If specific selections are wanted, call SetEntitySelection or SetActorSelections after creation. // Returns NULL on failure. static CUnit* Create(const CStrW& actorName, uint32_t seed, CObjectManager& objectManager); // destructor ~CUnit(); // get unit's template object const CObjectEntry& GetObject() const { return *m_Object; } // get unit's model data CModelAbstract& GetModel() const { return *m_Model; } CUnitAnimation* GetAnimation() { return m_Animation; } /** * Update the model's animation. * @param frameTime time in seconds */ void UpdateModel(float frameTime); // Sets the entity-selection, and updates the unit to use the new // actor variation. Either set one key at a time, or a complete map. void SetEntitySelection(const CStr& key, const CStr& selection); void SetEntitySelection(const std::map& selections); // Most units have a hopefully-unique ID number, so they can be referred to // persistently despite saving/loading maps. Default for new units is -1; should // usually be set to CUnitManager::GetNewID() after creation. entity_id_t GetID() const { return m_ID; } void SetID(entity_id_t id); const std::set& GetActorSelections() const { return m_ActorSelections; } /** * Overwrite the seed-selected actor selections. Likely only useful for Atlas or debugging. */ void SetActorSelections(const std::set& selections); private: // Actor for the unit const CActorDef& m_Actor; // object from which unit was created; never NULL once fully created. CObjectEntry* m_Object = nullptr; // object model representation; never NULL once fully created. CModelAbstract* m_Model = nullptr; CUnitAnimation* m_Animation = nullptr; // unique (per map) ID number for units created in the editor, as a // permanent way of referencing them. entity_id_t m_ID; // seed used when creating unit uint32_t m_Seed; // Actor-level selections for this unit. This is normally set at init time, // so that we always re-use the same aesthetic variants. // These have lower priority than entity-level selections. std::set m_ActorSelections; // Entity-level selections for this unit (used for e.g. animation variants). std::map m_EntitySelections; // object manager which looks after this unit's objectentry CObjectManager& m_ObjectManager; void ReloadObject(); friend class CUnitAnimation; }; #endif Index: ps/trunk/source/graphics/UnitManager.h =================================================================== --- ps/trunk/source/graphics/UnitManager.h (revision 25902) +++ ps/trunk/source/graphics/UnitManager.h (revision 25903) @@ -1,67 +1,65 @@ /* Copyright (C) 2021 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 . */ /* * Container that owns all units */ #ifndef INCLUDED_UNITMANAGER #define INCLUDED_UNITMANAGER #include #include class CUnit; -class CVector3D; class CObjectManager; -class CStr8; class CStrW; /////////////////////////////////////////////////////////////////////////////// // CUnitManager: simple container class holding all units within the world class CUnitManager { public: // constructor, destructor CUnitManager(); ~CUnitManager(); // add given unit to world void AddUnit(CUnit* unit); // remove given unit from world, but don't delete it void RemoveUnit(CUnit* unit); // remove given unit from world and delete it void DeleteUnit(CUnit* unit); // remove and delete all units void DeleteAll(); // creates a new unit and adds it to the world CUnit* CreateUnit(const CStrW& actorName, uint32_t seed); // return the units const std::vector& GetUnits() const { return m_Units; } void SetObjectManager(CObjectManager& objectManager) { m_ObjectManager = &objectManager; } private: // list of all known units std::vector m_Units; // graphical object manager; may be NULL if not set up CObjectManager* m_ObjectManager; }; #endif Index: ps/trunk/source/gui/ObjectTypes/CHotkeyPicker.h =================================================================== --- ps/trunk/source/gui/ObjectTypes/CHotkeyPicker.h (revision 25902) +++ ps/trunk/source/gui/ObjectTypes/CHotkeyPicker.h (revision 25903) @@ -1,80 +1,78 @@ /* Copyright (C) 2021 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_CHOTKEYPICKER #define INCLUDED_CHOTKEYPICKER #include "gui/CGUI.h" #include "gui/ObjectBases/IGUIObject.h" #include "lib/external_libraries/libsdl.h" #include "ps/CStr.h" #include -class ScriptInterface; - /** * When in focus, returns all currently pressed keys. * After a set time without changes, it will trigger a "combination" event. * * Used to create new hotkey combinations in-game. Mostly custom. * This object does not draw anything. */ class CHotkeyPicker : public IGUIObject { GUI_OBJECT(CHotkeyPicker) public: CHotkeyPicker(CGUI& pGUI); virtual ~CHotkeyPicker(); // Do nothing. virtual void Draw(CCanvas2D& UNUSED(canvas)) {}; // Checks if the timer has passed and we need to fire a "combination" event. virtual void Tick(); // React to blur/focus. virtual void HandleMessage(SGUIMessage& Message); // Pre-empt events: this is our sole purpose. virtual InReaction PreemptEvent(const SDL_Event_* ev); struct Key { // The scancode is used for fast comparisons. SDL_Scancode code; // This is the name ultimately stored in the config file. CStr scancodeName; }; protected: // Fire an event with m_KeysPressed as argument. void FireEvent(const CStr& event); // Time without changes until a "combination" event is sent. CGUISimpleSetting m_TimeToCombination; // Time of the last registered key change. double m_LastKeyChange; // Keep track of which keys we are pressing, and precompute their name for JS code. std::vector m_KeysPressed; static const CStr EventNameCombination; static const CStr EventNameKeyChange; }; #endif // INCLUDED_CHOTKEYPICKER Index: ps/trunk/source/gui/ObjectTypes/CMiniMap.h =================================================================== --- ps/trunk/source/gui/ObjectTypes/CMiniMap.h (revision 25902) +++ ps/trunk/source/gui/ObjectTypes/CMiniMap.h (revision 25903) @@ -1,118 +1,116 @@ /* Copyright (C) 2021 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_MINIMAP #define INCLUDED_MINIMAP #include "graphics/Color.h" #include "graphics/Texture.h" #include "gui/ObjectBases/IGUIObject.h" #include "maths/Vector2D.h" #include "renderer/VertexArray.h" #include #include -class CCamera; class CMatrix3D; -class CTerrain; class CMiniMap : public IGUIObject { GUI_OBJECT(CMiniMap) public: CMiniMap(CGUI& pGUI); virtual ~CMiniMap(); bool Flare(const CVector2D& pos, const CStr& colorStr); protected: struct MapFlare { CVector2D pos; CColor color; double time; }; virtual void Draw(CCanvas2D& canvas); virtual void CreateJSObject(); /** * @see IGUIObject#HandleMessage() */ virtual void HandleMessage(SGUIMessage& Message); /** * @see IGUIObject#IsMouseOver() */ virtual bool IsMouseOver() const; private: void SetCameraPositionFromMousePosition(); bool FireWorldClickEvent(int button, int clicks); static const CStr EventNameWorldClick; // Whether or not the mouse is currently down bool m_Clicking; std::deque m_MapFlares; std::vector m_FlareTextures; CGUISimpleSetting m_FlareTextureCount; CGUISimpleSetting m_FlareRenderSize; CGUISimpleSetting m_FlareInterleave; CGUISimpleSetting m_FlareAnimationSpeed; CGUISimpleSetting m_FlareLifetimeSeconds; // Whether to draw a black square around and under the minimap. CGUISimpleSetting m_Mask; // map size ssize_t m_MapSize; // 1.f if map is circular or 1.414f if square (to shrink it inside the circle) float m_MapScale; void RecreateFlareTextures(); void DrawViewRect(const CMatrix3D& transform) const; void DrawFlare(CCanvas2D& canvas, const MapFlare& flare, double curentTime) const; void GetMouseWorldCoordinates(float& x, float& z) const; float GetAngle() const; VertexIndexArray m_IndexArray; VertexArray m_VertexArray; VertexArray::Attribute m_AttributePos; VertexArray::Attribute m_AttributeColor; size_t m_EntitiesDrawn; double m_PingDuration; double m_HalfBlinkDuration; double m_NextBlinkTime; bool m_BlinkState; }; #endif // INCLUDED_MINIMAP Index: ps/trunk/source/network/NetClient.h =================================================================== --- ps/trunk/source/network/NetClient.h (revision 25902) +++ ps/trunk/source/network/NetClient.h (revision 25903) @@ -1,355 +1,354 @@ /* Copyright (C) 2021 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 NETCLIENT_H #define NETCLIENT_H #include "network/fsm.h" #include "network/NetFileTransfer.h" #include "network/NetHost.h" #include "scriptinterface/Object.h" #include "ps/CStr.h" #include #include #include class CGame; class CNetClientSession; class CNetClientTurnManager; -class CNetServer; class ScriptInterface; typedef struct _ENetHost ENetHost; // NetClient session FSM states enum { NCS_UNCONNECTED, NCS_CONNECT, NCS_HANDSHAKE, NCS_AUTHENTICATE, NCS_PREGAME, NCS_LOADING, NCS_JOIN_SYNCING, NCS_INGAME }; /** * Network client. * This code is run by every player (including the host, if they are not * a dedicated server). * It provides an interface between the GUI, the network (via CNetClientSession), * and the game (via CGame and CNetClientTurnManager). */ class CNetClient : public CFsm { NONCOPYABLE(CNetClient); friend class CNetFileReceiveTask_ClientRejoin; public: /** * Construct a client associated with the given game object. * The game must exist for the lifetime of this object. */ CNetClient(CGame* game); virtual ~CNetClient(); /** * We assume that adding a tracing function that's only called * during GC is better for performance than using a * PersistentRooted where each value needs to be added to * the root set. */ static void Trace(JSTracer *trc, void *data) { reinterpret_cast(data)->TraceMember(trc); } void TraceMember(JSTracer *trc); /** * Set the user's name that will be displayed to all players. * This must not be called after the connection setup. */ void SetUserName(const CStrW& username); /** * Store the JID of the host. * This is needed for the secure lobby authentication. */ void SetHostJID(const CStr& jid); void SetControllerSecret(const std::string& secret); bool IsController() const { return m_IsController; } /** * Set the game password. * Must be called after SetUserName, as that is used to hash further. */ void SetGamePassword(const CStr& hashedPassword); /** * Returns the GUID of the local client. * Used for distinguishing observers. */ CStr GetGUID() const { return m_GUID; } /** * Set connection data to the remote networked server. * @param address IP address or host name to connect to */ void SetupServerData(CStr address, u16 port, bool stun); /** * Set up a connection to the remote networked server. * Must call SetupServerData first. * @return true on success, false on connection failure */ bool SetupConnection(ENetHost* enetClient); /** * Request connection information over the lobby. */ void SetupConnectionViaLobby(); /** * Connect to the remote networked server using lobby. * Push netstatus messages on failure. * @param localNetwork - if true, assume we are trying to connect on the local network. * @return true on success, false on connection failure */ bool TryToConnect(const CStr& hostJID, bool localNetwork); /** * Destroy the connection to the server. * This client probably cannot be used again. */ void DestroyConnection(); /** * Poll the connection for messages from the server and process them, and send * any queued messages. * This must be called frequently (i.e. once per frame). */ void Poll(); /** * Locally triggers a GUI message if the connection to the server is being lost or has bad latency. */ void CheckServerConnection(); /** * Retrieves the next queued GUI message, and removes it from the queue. * The returned value is in the GetScriptInterface() JS context. * * This is the only mechanism for the networking code to send messages to * the GUI - it is pull-based (instead of push) so the engine code does not * need to know anything about the code structure of the GUI scripts. * * The structure of the messages is { "type": "...", ... }. * The exact types and associated data are not specified anywhere - the * implementation and GUI scripts must make the same assumptions. * * @return next message, or the value 'undefined' if the queue is empty */ void GuiPoll(JS::MutableHandleValue); /** * Add a message to the queue, to be read by GuiPoll. * The script value must be in the GetScriptInterface() JS context. */ template void PushGuiMessage(Args const&... args) { ScriptRequest rq(GetScriptInterface()); JS::RootedValue message(rq.cx); Script::CreateObject(rq, &message, args...); m_GuiMessageQueue.push_back(JS::Heap(message)); } /** * Return a concatenation of all messages in the GUI queue, * for test cases to easily verify the queue contents. */ std::string TestReadGuiMessages(); /** * Get the script interface associated with this network client, * which is equivalent to the one used by the CGame in the constructor. */ const ScriptInterface& GetScriptInterface(); /** * Send a message to the server. * @param message message to send * @return true on success */ bool SendMessage(const CNetMessage* message); /** * Call when the network connection has been successfully initiated. */ void HandleConnect(); /** * Call when the network connection has been lost. */ void HandleDisconnect(u32 reason); /** * Call when a message has been received from the network. */ bool HandleMessage(CNetMessage* message); /** * Call when the game has started and all data files have been loaded, * to signal to the server that we are ready to begin the game. */ void LoadFinished(); void SendGameSetupMessage(JS::MutableHandleValue attrs, const ScriptInterface& scriptInterface); void SendAssignPlayerMessage(const int playerID, const CStr& guid); void SendChatMessage(const std::wstring& text); void SendReadyMessage(const int status); void SendClearAllReadyMessage(); void SendStartGameMessage(const CStr& initAttribs); /** * Call when the client has rejoined a running match and finished * the loading screen. */ void SendRejoinedMessage(); /** * Call to kick/ban a client */ void SendKickPlayerMessage(const CStrW& playerName, bool ban); /** * Call when the client has paused or unpaused the game. */ void SendPausedMessage(bool pause); /** * @return Whether the NetClient is shutting down. */ bool ShouldShutdown() const; /** * Called when fetching connection data from the host failed, to inform JS code. */ void HandleGetServerDataFailed(const CStr& error); private: void SendAuthenticateMessage(); // Net message / FSM transition handlers static bool OnConnect(void* context, CFsmEvent* event); static bool OnHandshake(void* context, CFsmEvent* event); static bool OnHandshakeResponse(void* context, CFsmEvent* event); static bool OnAuthenticateRequest(void* context, CFsmEvent* event); static bool OnAuthenticate(void* context, CFsmEvent* event); static bool OnChat(void* context, CFsmEvent* event); static bool OnReady(void* context, CFsmEvent* event); static bool OnGameSetup(void* context, CFsmEvent* event); static bool OnPlayerAssignment(void* context, CFsmEvent* event); static bool OnInGame(void* context, CFsmEvent* event); static bool OnGameStart(void* context, CFsmEvent* event); static bool OnJoinSyncStart(void* context, CFsmEvent* event); static bool OnJoinSyncEndCommandBatch(void* context, CFsmEvent* event); static bool OnRejoined(void* context, CFsmEvent* event); static bool OnKicked(void* context, CFsmEvent* event); static bool OnClientTimeout(void* context, CFsmEvent* event); static bool OnClientPerformance(void* context, CFsmEvent* event); static bool OnClientsLoading(void* context, CFsmEvent* event); static bool OnClientPaused(void* context, CFsmEvent* event); static bool OnLoadedGame(void* context, CFsmEvent* event); /** * Take ownership of a session object, and use it for all network communication. */ void SetAndOwnSession(CNetClientSession* session); /** * Push a message onto the GUI queue listing the current player assignments. */ void PostPlayerAssignmentsToScript(); CGame *m_Game; CStrW m_UserName; CStr m_HostJID; CStr m_ServerAddress; u16 m_ServerPort; bool m_UseSTUN; /** * Password to join the game. */ CStr m_Password; /// The 'secret' used to identify the controller of the game. std::string m_ControllerSecret; /// Note that this is just a "gui hint" with no actual impact on being controller. bool m_IsController = false; /// Current network session (or NULL if not connected) CNetClientSession* m_Session; std::thread m_PollingThread; /// Turn manager associated with the current game (or NULL if we haven't started the game yet) CNetClientTurnManager* m_ClientTurnManager; /// Unique-per-game identifier of this client, used to identify the sender of simulation commands u32 m_HostID; /// True if the player is currently rejoining or has already rejoined the game. bool m_Rejoin; /// Latest copy of player assignments heard from the server PlayerAssignmentMap m_PlayerAssignments; /// Globally unique identifier to distinguish users beyond the lifetime of a single network session CStr m_GUID; /// Queue of messages for GuiPoll std::deque> m_GuiMessageQueue; /// Serialized game state received when joining an in-progress game std::string m_JoinSyncBuffer; /// Time when the server was last checked for timeouts and bad latency std::time_t m_LastConnectionCheck; }; /// Global network client for the standard game extern CNetClient *g_NetClient; #endif // NETCLIENT_H Index: ps/trunk/source/network/NetFileTransfer.h =================================================================== --- ps/trunk/source/network/NetFileTransfer.h (revision 25902) +++ ps/trunk/source/network/NetFileTransfer.h (revision 25903) @@ -1,141 +1,139 @@ /* Copyright (C) 2021 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 NETFILETRANSFER_H #define NETFILETRANSFER_H #include #include class CNetMessage; class CFileTransferResponseMessage; class CFileTransferDataMessage; class CFileTransferAckMessage; -class CNetClientSession; -class CNetServerSession; class INetSession; // Assume this is sufficiently less than MTU that packets won't get // fragmented or dropped. static const size_t DEFAULT_FILE_TRANSFER_PACKET_SIZE = 1024; // To improve performance without flooding ENet's internal buffers, // maintain a small number of in-flight packets. // Pick numbers so that with e.g. 200ms round-trip latency // we can hopefully get windowSize*packetSize*1000/200 = 160KB/s bandwidth static const size_t DEFAULT_FILE_TRANSFER_WINDOW_SIZE = 32; // Some arbitrary limit to make it slightly harder to use up all of someone's RAM static const size_t MAX_FILE_TRANSFER_SIZE = 8*MiB; /** * Asynchronous file-receiving task. * Other code should subclass this, implement OnComplete(), * then pass it to CNetFileTransferer::StartTask. */ class CNetFileReceiveTask { public: CNetFileReceiveTask() : m_RequestID(0), m_Length(0) { } virtual ~CNetFileReceiveTask() {} /** * Called when m_Buffer contains the full received data. */ virtual void OnComplete() = 0; // TODO: Ought to have an OnFailure, e.g. when the session drops or there's another error /** * Uniquely identifies the request within the scope of its CNetFileTransferer. * Set automatically by StartTask. */ u32 m_RequestID; size_t m_Length; std::string m_Buffer; }; /** * Handles transferring files between clients and servers. */ class CNetFileTransferer { public: CNetFileTransferer(INetSession* session) : m_Session(session), m_NextRequestID(1), m_LastProgressReportTime(0) { } /** * Should be called when a message is received from the network. * Returns INFO::SKIPPED if the message is not one that this class handles. * Returns INFO::OK if the message is handled successfully, * or ERR::FAIL if handled unsuccessfully. */ Status HandleMessageReceive(const CNetMessage& message); /** * Registers a file-receiving task. */ void StartTask(const std::shared_ptr& task); /** * Registers data to be sent in response to a request. * (Callers are expected to have their own mechanism for receiving * requests and deciding what to respond with.) */ void StartResponse(u32 requestID, const std::string& data); /** * Call frequently (e.g. once per frame) to trigger any necessary * packet processing. */ void Poll(); private: Status OnFileTransferResponse(const CFileTransferResponseMessage& message); Status OnFileTransferData(const CFileTransferDataMessage& message); Status OnFileTransferAck(const CFileTransferAckMessage& message); /** * Asynchronous file-sending task. */ struct CNetFileSendTask { u32 requestID; std::string buffer; size_t offset; size_t maxWindowSize; size_t packetsInFlight; }; INetSession* m_Session; u32 m_NextRequestID; using FileReceiveTasksMap = std::map>; FileReceiveTasksMap m_FileReceiveTasks; using FileSendTasksMap = std::map; FileSendTasksMap m_FileSendTasks; double m_LastProgressReportTime; }; #endif // NETFILETRANSFER_H Index: ps/trunk/source/network/StunClient.h =================================================================== --- ps/trunk/source/network/StunClient.h (revision 25902) +++ ps/trunk/source/network/StunClient.h (revision 25903) @@ -1,53 +1,52 @@ /* Copyright (C) 2021 Wildfire Games. * Copyright (C) 2013-2016 SuperTuxKart-Team. * 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 STUNCLIENT_H #define STUNCLIENT_H #include typedef struct _ENetHost ENetHost; -class ScriptInterface; class CStr8; namespace StunClient { /** * Return the publicly accessible IP of the given ENet host/socket. * This is done by contacting STUN server. * The return IP & port should only be considered valid for the give host/socket. */ bool FindPublicIP(ENetHost& enetClient, CStr8& ip, u16& port); /** * Send a message to the target server with the given ENet host/socket. * This will open a port on the local gateway (if any) to receive trafic, * allowing the recipient to answer (thus 'punching a hole' in the NAT). * NB: this assumes consistent NAT, i.e. the outgoing port is always the same for the given client, * thus allowing the IP discovered via STUN to be sent to the target server. */ void SendHolePunchingMessages(ENetHost& enetClient, const std::string& serverAddress, u16 serverPort); /** * Return the local IP. * Technically not a STUN method, but convenient to define here. */ bool FindLocalIP(CStr8& ip); } #endif // STUNCLIENT_H Index: ps/trunk/source/ps/ProfileViewer.h =================================================================== --- ps/trunk/source/ps/ProfileViewer.h (revision 25902) +++ ps/trunk/source/ps/ProfileViewer.h (revision 25903) @@ -1,202 +1,200 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2021 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 . */ /* * Viewing profiling information (timing and other statistics) */ #ifndef INCLUDED_PROFILE_VIEWER #define INCLUDED_PROFILE_VIEWER #include "lib/input.h" #include "ps/CStr.h" #include "ps/Singleton.h" #include -class ScriptInterface; - /** * Struct ProfileColumn: Describes one column of an AbstractProfileTable. */ struct ProfileColumn { /// Title of the column CStr title; /// Recommended width of the column, in pixels. size_t width; ProfileColumn(const CStr& t, size_t w) : title(t), width(w) { } }; /** * Class AbstractProfileTable: Profile table data model. * * Clients that wish to display debug information in the profile viewer * have to implement this class and hook it into CProfileViewer. * * Note that the profiling system is robust against deletion of * object instances in the sense that it will automatically remove * an AbstractProfileTable instance from its internal records when * you delete it. * Conversely, deleting an AbstractProfileTable instance is the responsibility * of its creator. */ class AbstractProfileTable { public: virtual ~AbstractProfileTable(); /** * GetName: Short descriptive name of this table (should be static). * * @return Descriptive name of this table. */ virtual CStr GetName() = 0; /** * GetTitle: Longer, explanatory text (can be dynamic). * * @return Title for the table. */ virtual CStr GetTitle() = 0; /** * GetNumberRows * * @return Number of rows in this table. */ virtual size_t GetNumberRows() = 0; /** * GetColumnDescriptions * * @return A vector describing all columns of the table. */ virtual const std::vector& GetColumns() = 0; /** * GetCellText * * @param row Row index (the first row has index 0). * @param col Column index (the first column has index 0). * * @return Text to be displayed in the given cell. */ virtual CStr GetCellText(size_t row, size_t col) = 0; /** * GetChild: Return a row's child table if the child is expandable. * * @param row Row index (the first row has index 0). * * @return Pointer to the child table if the given row has one. * Otherwise, return 0. */ virtual AbstractProfileTable* GetChild(size_t row) = 0; /** * IsHighlightRow * * @param row Row index (the first row has index 0). * * @return true if the row should be highlighted in a special color. */ virtual bool IsHighlightRow(size_t row) { UNUSED2(row); return false; } }; struct CProfileViewerInternals; /** * Class CProfileViewer: Manage and display profiling tables. */ class CProfileViewer : public Singleton { friend class AbstractProfileTable; public: CProfileViewer(); ~CProfileViewer(); /** * RenderProfile: Render the profile display using OpenGL if the user * has enabled it. */ void RenderProfile(); /** * Input: Filter and handle any input events that the profile display * is interested in. * * In particular, this function handles enable/disable of the profile * display as well as navigating the information tree. * * @param ev The incoming event. * * @return IN_PASS or IN_HANDLED depending on whether the event relates * to the profiling display. */ InReaction Input(const SDL_Event_* ev); /** * AddRootTable: Add a new profile table as a root table (i.e. the * tables that you cycle through via the profile hotkey). * * @note Tables added via this function are automatically removed from * the list of root tables when they are deleted. * * @param table This table is added as a root table. * @param front If true then the table will be the new first in the list, * else it will be the last. */ void AddRootTable(AbstractProfileTable* table, bool front = false); /** * InputThunk: Delegate to the singleton's Input() member function * if the singleton has been initialized. * * This allows our input handler to be installed via in_add_handler * like a normal, global function input handler. */ static InReaction InputThunk(const SDL_Event_* ev); /** * SaveToFile: Save the current profiler data (for all profile tables) * to a file in the 'logs' directory. */ void SaveToFile(); /** * ShowTable: Set the named profile table to be the displayed one. If it * is not found, no profile is displayed. * * @param table The table name (matching AbstractProfileTable::GetName), * or the empty string to display no table. */ void ShowTable(const CStr& table); private: CProfileViewerInternals* m; }; #define g_ProfileViewer CProfileViewer::GetSingleton() #endif Index: ps/trunk/source/ps/SavedGame.h =================================================================== --- ps/trunk/source/ps/SavedGame.h (revision 25902) +++ ps/trunk/source/ps/SavedGame.h (revision 25903) @@ -1,93 +1,92 @@ /* Copyright (C) 2021 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_SAVEDGAME #define INCLUDED_SAVEDGAME #include "ps/CStr.h" #include "scriptinterface/StructuredClone.h" class CSimulation2; -class CGUIManager; /** * @file * Contains functions for managing saved game archives. * * A saved game is simply a zip archive with the extension '0adsave' * and containing two files: *
    *
  • metadata.json - JSON data file containing the game metadata
  • *
  • simulation.dat - the serialized simulation state data
  • *
*/ namespace SavedGames { /** * Create new saved game archive with given name and simulation data * * @param name Name to save the game with * @param description A user-given description of the save * @param simulation * @param guiMetadataClone if not NULL, store some UI-related data with the saved game * @return INFO::OK if successfully saved, else an error Status */ Status Save(const CStrW& name, const CStrW& description, CSimulation2& simulation, const Script::StructuredClone& guiMetadataClone); /** * Create new saved game archive with given prefix and simulation data * * @param prefix Create new numbered file starting with this prefix * @param description A user-given description of the save * @param simulation * @param guiMetadataClone if not NULL, store some UI-related data with the saved game * @return INFO::OK if successfully saved, else an error Status */ Status SavePrefix(const CStrW& prefix, const CStrW& description, CSimulation2& simulation, const Script::StructuredClone& guiMetadataClone); /** * Load saved game archive with the given name * * @param name filename of saved game (without path or extension) * @param scriptInterface * @param[out] metadata object containing metadata associated with saved game, * parsed from metadata.json inside the archive. * @param[out] savedState serialized simulation state stored as string of bytes, * loaded from simulation.dat inside the archive. * @return INFO::OK if successfully loaded, else an error Status */ Status Load(const std::wstring& name, const ScriptInterface& scriptInterface, JS::MutableHandleValue metadata, std::string& savedState); /** * Get list of saved games for GUI script usage * * @param scriptInterface the ScriptInterface in which to create the return data. * @return array of objects containing saved game data */ JS::Value GetSavedGames(const ScriptInterface& scriptInterface); /** * Permanently deletes the saved game archive with the given name * * @param name filename of saved game (without path or extension) * @return true if deletion was successful, or false on error */ bool DeleteSavedGame(const std::wstring& name); } #endif // INCLUDED_SAVEDGAME Index: ps/trunk/source/ps/VisualReplay.h =================================================================== --- ps/trunk/source/ps/VisualReplay.h (revision 25902) +++ ps/trunk/source/ps/VisualReplay.h (revision 25903) @@ -1,128 +1,126 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2021 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_VISUAL_REPLAY #define INCLUDED_VISUAL_REPLAY #include "lib/os_path.h" #include "scriptinterface/ScriptTypes.h" -class CSimulation2; -class CGUIManager; class CStrW; class ScriptInterface; /** * Contains functions for visually replaying past games. */ namespace VisualReplay { /** * Returns the absolute path to the sim-log directory (that contains the directories with the replay files. */ OsPath GetDirectoryPath(); /** * Returns the absolute path to the replay cache file. */ OsPath GetCacheFilePath(); /** * Returns the absolute path to the temporary replay cache file used to * always have a valid cache file in place even if bad things happen. */ OsPath GetTempCacheFilePath(); /** * Replays the commands.txt file in the given subdirectory visually. */ bool StartVisualReplay(const OsPath& directory); /** * Reads the replay Cache file and parses it into a jsObject * * @param scriptInterface - the ScriptInterface in which to create the return data. * @param cachedReplaysObject - the cached replays. * @return true on succes */ bool ReadCacheFile(const ScriptInterface& scriptInterface, JS::MutableHandleObject cachedReplaysObject); /** * Stores the replay list in the replay cache file * * @param scriptInterface - the ScriptInterface in which to create the return data. * @param replays - the replay list to store. */ void StoreCacheFile(const ScriptInterface& scriptInterface, JS::HandleObject replays); /** * Load the replay cache and check if there are new/deleted replays. If so, update the cache. * * @param scriptInterface - the ScriptInterface in which to create the return data. * @param compareFiles - compare the directory name and the FileSize of the replays and the cache. * @return cache entries */ JS::HandleObject ReloadReplayCache(const ScriptInterface& scriptInterface, bool compareFiles); /** * Get a list of replays to display in the GUI. * * @param scriptInterface - the ScriptInterface in which to create the return data. * @param compareFiles - reload the cache, which takes more time, * but nearly ensures, that no changed replay is missed. * @return array of objects containing replay data */ JS::Value GetReplays(const ScriptInterface& scriptInterface, bool compareFiles); /** * Parses a commands.txt file and extracts metadata. * Works similarly to CGame::LoadReplayData(). */ JS::Value LoadReplayData(const ScriptInterface& scriptInterface, const OsPath& directory); /** * Permanently deletes the visual replay (including the parent directory) * * @param replayFile - path to commands.txt, whose parent directory will be deleted. * @return true if deletion was successful, false on error */ bool DeleteReplay(const OsPath& replayFile); /** * Returns the parsed header of the replay file (commands.txt). */ JS::Value GetReplayAttributes(const ScriptInterface& scriptInterface, const OsPath& directoryName); /** * Returns whether or not the metadata / summary screen data has been saved properly when the game ended. */ bool HasReplayMetadata(const OsPath& directoryName); /** * Returns the metadata of a replay. */ JS::Value GetReplayMetadata(const ScriptInterface& scriptInterface, const OsPath& directoryName); /** * Adds a replay to the replayCache. */ void AddReplayToCache(const ScriptInterface& scriptInterface, const CStrW& directoryName); } #endif Index: ps/trunk/source/ps/XMB/XMBData.h =================================================================== --- ps/trunk/source/ps/XMB/XMBData.h (revision 25902) +++ ps/trunk/source/ps/XMB/XMBData.h (revision 25903) @@ -1,285 +1,284 @@ /* Copyright (C) 2021 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 . */ /* Xeromyces - XMB reading library Brief outline: XMB originated as a binary representation of XML, with some limitations but much more efficiency (particularly for loading simple data classes that don't need much initialisation). Theoretical file structure: XMB_File { char Header[4]; // because everyone has one; currently "XMB0" u32 Version; int OffsetFromStartToElementNames; int ElementNameCount; int OffsetFromStartToAttributeNames; int AttributeNameCount; XMB_Node Root; ZStr8 ElementNames[]; ZStr8 AttributeNames[]; } XMB_Node { 0) int Length; // of entire struct, so it can be skipped over 4) int ElementName; 8) int AttributeCount; 12) int ChildCount; 16) int ChildrenOffset; // == sizeof(Text)+sizeof(Attributes) 20) XMB_Text Text; XMB_Attribute Attributes[]; XMB_Node Children[]; } XMB_Attribute { int Name; ZStr8 Value; } ZStr8 { int Length; // in bytes char* Text; // null-terminated UTF8 } XMB_Text { 20) int Length; // 0 if there's no text, else 4+sizeof(Text) in bytes including terminator // If Length != 0: 24) int LineNumber; // for e.g. debugging scripts 28) char* Text; // null-terminated UTF8 } */ #ifndef INCLUDED_XEROXMB #define INCLUDED_XEROXMB #include "ps/CStr.h" #include #include -class CXeromyces; class XMBStorage; class XMBElement; class XMBElementList; class XMBAttributeList; class XMBData { public: XMBData() : m_Pointer(nullptr) {} /* * Initialise from the contents of an XMBStorage. * @param doc must remain allocated and unchanged while * the XMBData is being used. * @return indication of success; main cause for failure is attempting to * load a partially valid XMB file (e.g. if the game was interrupted * while writing it), which we detect by checking the magic string. * It also fails when trying to load an XMB file with a different version. */ bool Initialise(const XMBStorage& doc); // Returns the root element XMBElement GetRoot() const; // Returns internal ID for a given element/attribute string. int GetElementID(const char* Name) const; int GetAttributeID(const char* Name) const; // Returns element/attribute string for a given internal ID. const char* GetElementString(const int ID) const; const char* GetAttributeString(const int ID) const; std::string_view GetElementStringView(const int ID) const; std::string_view GetAttributeStringView(const int ID) const; private: const char* m_Pointer; int m_ElementNameCount; int m_AttributeNameCount; const char* m_ElementPointer; const char* m_AttributePointer; }; class XMBElement { public: XMBElement() : m_Pointer(0) {} XMBElement(const char* offset) : m_Pointer(offset) {} int GetNodeName() const; XMBElementList GetChildNodes() const; XMBAttributeList GetAttributes() const; CStr8 GetText() const; // Returns the line number of the text within this element, // or -1 if there is no text int GetLineNumber() const; private: // Pointer to the start of the node const char* m_Pointer; }; class XMBElementList { public: XMBElementList(const char* offset, size_t count, const char* endoffset) : m_Size(count), m_Pointer(offset), m_CurItemID(0), m_CurPointer(offset), m_EndPointer(endoffset) {} // Get first element in list with the given name. // Performance is linear in the number of elements in the list. XMBElement GetFirstNamedItem(const int ElementName) const; // Linear in the number of elements in the list XMBElement operator[](size_t id); // returns Children[id] class iterator { public: typedef ptrdiff_t difference_type; typedef XMBElement value_type; typedef XMBElement reference; // Because we need to construct the object typedef XMBElement pointer; // Because we need to construct the object typedef std::forward_iterator_tag iterator_category; iterator(size_t size, const char* ptr, const char* endptr = NULL) : m_Size(size), m_CurItemID(endptr ? size : 0), m_CurPointer(endptr ? endptr : ptr) {} XMBElement operator*() const { return XMBElement(m_CurPointer); } XMBElement operator->() const { return **this; } iterator& operator++(); bool operator==(const iterator& rhs) const { return m_Size == rhs.m_Size && m_CurItemID == rhs.m_CurItemID && m_CurPointer == rhs.m_CurPointer; } bool operator!=(const iterator& rhs) const { return !(*this == rhs); } private: size_t m_Size; size_t m_CurItemID; const char* m_CurPointer; }; iterator begin() { return iterator(m_Size, m_Pointer); } iterator end() { return iterator(m_Size, m_Pointer, m_EndPointer); } size_t size() const { return m_Size; } bool empty() const { return m_Size == 0; } private: size_t m_Size; const char* m_Pointer; // For optimised sequential access: size_t m_CurItemID; const char* m_CurPointer; const char* m_EndPointer; }; struct XMBAttribute { XMBAttribute() {} XMBAttribute(int name, const CStr8& value) : Name(name), Value(value) {}; int Name; CStr8 Value; // UTF-8 encoded }; class XMBAttributeList { public: XMBAttributeList(const char* offset, size_t count, const char* endoffset) : m_Size(count), m_Pointer(offset), m_CurItemID(0), m_CurPointer(offset), m_EndPointer(endoffset) {} // Get the attribute value directly CStr8 GetNamedItem(const int AttributeName) const; // Linear in the number of elements in the list XMBAttribute operator[](size_t id); // returns Children[id] class iterator { public: typedef ptrdiff_t difference_type; typedef XMBAttribute value_type; typedef XMBAttribute reference; // Because we need to construct the object typedef XMBAttribute pointer; // Because we need to construct the object typedef std::forward_iterator_tag iterator_category; iterator(size_t size, const char* ptr, const char* endptr = NULL) : m_Size(size), m_CurItemID(endptr ? size : 0), m_CurPointer(endptr ? endptr : ptr) {} XMBAttribute operator*() const; XMBAttribute operator->() const { return **this; } iterator& operator++(); bool operator==(const iterator& rhs) const { return m_Size == rhs.m_Size && m_CurItemID == rhs.m_CurItemID && m_CurPointer == rhs.m_CurPointer; } bool operator!=(const iterator& rhs) const { return !(*this == rhs); } private: size_t m_Size; size_t m_CurItemID; const char* m_CurPointer; }; iterator begin() const { return iterator(m_Size, m_Pointer); } iterator end() const { return iterator(m_Size, m_Pointer, m_EndPointer); } size_t size() const { return m_Size; } bool empty() const { return m_Size == 0; } private: size_t m_Size; // Pointer to start of attribute list const char* m_Pointer; // For optimised sequential access: size_t m_CurItemID; const char* m_CurPointer; const char* m_EndPointer; }; #endif // INCLUDED_XEROXMB Index: ps/trunk/source/ps/XML/RelaxNG.h =================================================================== --- ps/trunk/source/ps/XML/RelaxNG.h (revision 25902) +++ ps/trunk/source/ps/XML/RelaxNG.h (revision 25903) @@ -1,61 +1,59 @@ /* Copyright (C) 2021 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_RELAXNG #define INCLUDED_RELAXNG #include "lib/file/vfs/vfs.h" #include "maths/MD5.h" typedef struct _xmlRelaxNG xmlRelaxNG; typedef xmlRelaxNG *xmlRelaxNGPtr; typedef struct _xmlDoc xmlDoc; typedef xmlDoc *xmlDocPtr; -class IRelaxNGGrammar; - class RelaxNGValidator { public: RelaxNGValidator(); ~RelaxNGValidator(); bool LoadGrammar(const std::string& grammar); bool LoadGrammarFile(const PIVFS& vfs, const VfsPath& grammarPath); MD5 GetGrammarHash() const { return m_Hash; } bool Validate(const std::string& filename, const std::string& document) const; bool ValidateEncoded(const std::string& filename, const std::string& document) const; bool ValidateEncoded(xmlDocPtr doc) const; bool CanValidate() const; private: MD5 m_Hash; xmlRelaxNGPtr m_Schema; }; /** * There should be no references to validators or schemas outside of the cache anymore when calling this. */ void ClearSchemaCache(); #endif // INCLUDED_RELAXNG Index: ps/trunk/source/renderer/MikktspaceWrap.h =================================================================== --- ps/trunk/source/renderer/MikktspaceWrap.h (revision 25902) +++ ps/trunk/source/renderer/MikktspaceWrap.h (revision 25903) @@ -1,124 +1,122 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2021 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_MIKKWRAP #define INCLUDED_MIKKWRAP #include "graphics/MeshManager.h" #include "graphics/ModelDef.h" #include "third_party/mikktspace/mikktspace.h" #include -class CVector3D; - class MikkTSpace { public: MikkTSpace(const CModelDefPtr& m, std::vector& v, bool gpuSkinning); void Generate(); private: SMikkTSpaceInterface m_Interface; SMikkTSpaceContext m_Context; const CModelDefPtr& m_Model; std::vector& m_NewVertices; bool m_GpuSkinning; /** * @param[in] pContext - Pointer to the MikkTSpace context. * @returns - the number of faces (triangles/quads) on the mesh to be processed. */ static int GetNumFaces(const SMikkTSpaceContext* pContext); /** * @param[in] pContext - Pointer to the MikkTSpace context. * @param[in] iFace - Number in the range { 0, 1, ..., getNumFaces() - 1 }. * @returns - the number of faces (triangles/quads) on the mesh to be processed. */ static int GetNumVerticesOfFace(const SMikkTSpaceContext* pContext, const int iFace); /** * @param[in] pContext - Pointer to the MikkTSpace context. * @returns - The MikkTSpace. */ static MikkTSpace* GetUserDataFromContext(const SMikkTSpaceContext* pContext); /** * @param[in] pContext - Pointer to the MikkTSpace context. * @param[in] iFace - Number in the range { 0, 1, ..., getNumFaces() - 1 }. * @param[in] iVert - Number in the range { 0, 1, 2 } for triangles and { 0, 1, 2, 3 } for quads. * @returns - The MikkTSpace. */ static SModelVertex GetVertex(const SMikkTSpaceContext* pContext, const int iFace, const int iVert); /** * @param[in] pContext - Pointer to the MikkTSpace context. * @param[out] fvPosOut - The array containing the face. * @param[in] iFace - Number in the range { 0, 1, ..., getNumFaces() - 1 }. * @param[in] iVert - Number in the range { 0, 1, 2 } for triangles and { 0, 1, 2, 3 } for quads. */ static void GetPosition(const SMikkTSpaceContext* pContext, float* fvPosOut, const int iFace, const int iVert); /** * @param[in] pContext - Pointer to the MikkTSpace context. * @param[out] fvNormOut iVert - The array containing the normal. * @param[in] iFace - Number in the range { 0, 1, ..., getNumFaces() - 1 }. * @param[in] iVert - Number in the range { 0, 1, 2 } for triangles and { 0, 1, 2, 3 } for quads. */ static void GetNormal(const SMikkTSpaceContext* pContext, float* fvNormOut, const int iFace, const int iVert); /** * @param[in] pContext - Pointer to the MikkTSpace context. * @param[out] fvTexcOut iVert - Array containing the UV. * @param[in] iFace - Number in the range { 0, 1, ..., getNumFaces() - 1 }. * @param[in] iVert - Number in the range { 0, 1, 2 } for triangles and { 0, 1, 2, 3 } for quads. */ static void GetTexCoord(const SMikkTSpaceContext* pContext, float* fvTexcOut, const int iFace, const int iVert); /** * @brief This function is used to return tangent space results to the application. * For normal maps it is sufficient to use the following simplified version of the bitangent which is generated at pixel/vertex level. * fSign = bIsOrientationPreserving ? 1.0f : (-1.0f); * bitangent = fSign * cross(vN, tangent); * @param[in] pContext - Pointer to the MikkTSpace context. * @param[in] fvTangent - fvTangent - The tangent vector. * @param[in] fvBiTangent - The "real" bitangent vector. Not be perpendicular to fvTangent. However, both are perpendicular to the vertex normal. * @param[in] fMagS - magniture of the fvTangent vector. * @param[in] fMagT - magniture of the fvBiTangent vector. * @param[in] bIsOrientationPreserving - Whether the orientation should be preserved. * @param[in] iFace - Number in the range {0,1,2} for triangles and {0,1,2,3} for quads. * @param[in] iVert - Array containing the position vector of the face. */ static void SetTSpace(const SMikkTSpaceContext* pContext, const float* fvTangent, const float* UNUSED(fvBiTangent), const float UNUSED(fMagS), const float UNUSED(fMagT), const tbool bIsOrientationPreserving, const int iFace, const int iVert); }; #endif // INCLUDED_MIKKWRAP Index: ps/trunk/source/renderer/RenderModifiers.h =================================================================== --- ps/trunk/source/renderer/RenderModifiers.h (revision 25902) +++ ps/trunk/source/renderer/RenderModifiers.h (revision 25903) @@ -1,134 +1,133 @@ -/* Copyright (C) 2012 Wildfire Games. +/* Copyright (C) 2021 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 . */ /* * RenderModifiers can affect the fragment stage behaviour of some * ModelRenderers. This file defines some common RenderModifiers in * addition to the base class. * * TODO: See comment in CRendererInternals::Models - we no longer use multiple * subclasses of RenderModifier, so most of the stuff here is unnecessary * abstraction which should probably be cleaned up. */ #ifndef INCLUDED_RENDERMODIFIERS #define INCLUDED_RENDERMODIFIERS #include "ModelRenderer.h" #include "graphics/ShaderProgram.h" #include "graphics/ShaderTechnique.h" #include "graphics/Texture.h" class CLightEnv; -class CMatrix3D; class CModel; class ShadowMap; /** * Class RenderModifier: Some ModelRenderer implementations provide vertex * management behaviour but allow fragment stages to be modified by a plugged in * RenderModifier. * * You should use RenderModifierPtr when referencing RenderModifiers. */ class RenderModifier { public: RenderModifier() { } virtual ~RenderModifier() { } /** * BeginPass: Setup OpenGL for the given rendering pass. * * Must be implemented by derived classes. * * @param pass The current pass number (pass == 0 is the first pass) * * @return The streamflags that indicate which vertex components * are required by the fragment stages (see STREAM_XYZ constants). */ virtual void BeginPass(const CShaderProgramPtr& shader) = 0; /** * PrepareModel: Called before rendering the given model. * * Default behaviour does nothing. * * @param pass The current pass number (pass == 0 is the first pass) * @param model The model that is about to be rendered. */ virtual void PrepareModel(const CShaderProgramPtr& shader, CModel* model) = 0; }; /** * Class LitRenderModifier: Abstract base class for RenderModifiers that apply * a shadow map. * LitRenderModifiers expect the diffuse brightness in the primary color (instead of ambient + diffuse). */ class LitRenderModifier : public RenderModifier { public: LitRenderModifier(); ~LitRenderModifier(); /** * SetShadowMap: Set the shadow map that will be used for rendering. * Must be called by the user of the RenderModifier. * * The shadow map must be non-null and use depth texturing, or subsequent rendering * using this RenderModifier will fail. * * @param shadow the shadow map */ void SetShadowMap(const ShadowMap* shadow); /** * SetLightEnv: Set the light environment that will be used for rendering. * Must be called by the user of the RenderModifier. * * @param lightenv the light environment (must be non-null) */ void SetLightEnv(const CLightEnv* lightenv); const ShadowMap* GetShadowMap() const { return m_Shadow; } const CLightEnv* GetLightEnv() const { return m_LightEnv; } private: const ShadowMap* m_Shadow; const CLightEnv* m_LightEnv; }; /** * A RenderModifier that sets uniforms and textures appropriately for rendering models. */ class ShaderRenderModifier : public LitRenderModifier { public: ShaderRenderModifier(); // Implementation void BeginPass(const CShaderProgramPtr& shader); void PrepareModel(const CShaderProgramPtr& shader, CModel* model); private: CShaderProgram::Binding m_BindingInstancingTransform; CShaderProgram::Binding m_BindingShadingColor; CShaderProgram::Binding m_BindingPlayerColor; }; #endif // INCLUDED_RENDERMODIFIERS Index: ps/trunk/source/renderer/ShadowMap.h =================================================================== --- ps/trunk/source/renderer/ShadowMap.h (revision 25902) +++ ps/trunk/source/renderer/ShadowMap.h (revision 25903) @@ -1,147 +1,146 @@ /* Copyright (C) 2021 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_SHADOWMAP #define INCLUDED_SHADOWMAP #include "graphics/ShaderProgramPtr.h" #include "lib/ogl.h" class CBoundingBoxAligned; class CCamera; class CFrustum; -class CMatrix3D; class CVector3D; struct ShadowMapInternals; /** * Class ShadowMap: Maintain the shadow map texture and perform necessary OpenGL setup, * including matrix calculations. * * The class will automatically generate a texture the first time the shadow map is rendered into. * The texture will not be resized afterwards. */ class ShadowMap { public: ShadowMap(); ~ShadowMap(); /** * RecreateTexture: Destroy the current shadow texture and force creation of * a new one. Useful when the renderer's size has changed and the texture * should be resized too. */ void RecreateTexture(); /** * GetDepthTextureBits: Return the number of bits to use for depth textures when * enabled. * * @return depth texture bit depth */ int GetDepthTextureBits() const; /** * SetDepthTextureBits: Sets the number of bits to use for depth textures when enabled. * Possible values are 16, 24, 32 and 0 (= use default) * * @param bits number of bits */ void SetDepthTextureBits(int bits); /** * SetupFrame: Configure light space for the given camera and light direction, * create the shadow texture if necessary, etc. * * @param camera the camera that will be used for world rendering * @param lightdir the direction of the (directional) sunlight */ void SetupFrame(const CCamera& camera, const CVector3D& lightdir); /** * Add the bounding box of an object that will cast a shadow. * This is used to calculate the bounds for the shadow map. * * @param bounds world space bounding box */ void AddShadowCasterBound(const int cascade, const CBoundingBoxAligned& bounds); /** * Add the bounding box of an object that will receive a shadow. * This is used to calculate the bounds for the shadow map. * * @param bounds world space bounding box */ void AddShadowReceiverBound(const CBoundingBoxAligned& bounds); /** * Compute the frustum originating at the light source, that encompasses * all the objects passed into AddShadowReceiverBound so far. * * This frustum can be used to determine which objects might cast a visible * shadow. Those objects should be passed to AddShadowCasterBound and * then should be rendered into the shadow map. */ CFrustum GetShadowCasterCullFrustum(const int cascade); /** * BeginRender: Set OpenGL state for rendering into the shadow map texture. * * @todo this depends in non-obvious ways on the behaviour of the call-site */ void BeginRender(); /** * EndRender: Finish rendering into the shadow map. * * @todo this depends in non-obvious ways on the behaviour of the call-site */ void EndRender(); /** * Returns the current number of used cascades. */ int GetCascadeCount() const; /** * Sets the renderer camera for the cascade. */ void PrepareCamera(const int cascade); /** * Binds all needed resources and uniforms to draw shadows using the shader. */ void BindTo(const CShaderProgramPtr& shader) const; /** * Visualize shadow mapping calculations to help in * debugging and optimal shadow map usage. */ void RenderDebugBounds(); /** * Visualize shadow map texture to help in debugging. */ void RenderDebugTexture(); private: ShadowMapInternals* m; }; #endif // INCLUDED_SHADOWMAP Index: ps/trunk/source/renderer/WaterManager.h =================================================================== --- ps/trunk/source/renderer/WaterManager.h (revision 25902) +++ ps/trunk/source/renderer/WaterManager.h (revision 25903) @@ -1,195 +1,193 @@ /* Copyright (C) 2021 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 . */ /* * Water settings (speed, height) and texture management */ #ifndef INCLUDED_WATERMANAGER #define INCLUDED_WATERMANAGER #include "graphics/Color.h" #include "graphics/Texture.h" #include "lib/ogl.h" #include "maths/Matrix3D.h" #include "maths/Vector2D.h" #include "renderer/VertexBufferManager.h" -class CSimulation2; class CFrustum; -struct CoastalPoint; struct WaveObject; /** * Class WaterManager: Maintain rendering-related water settings and textures * Anything that affects gameplay should go in CcmpWaterManager.cpp and passed to this (possibly as copy). */ class WaterManager { public: CTexturePtr m_WaterTexture[60]; CTexturePtr m_NormalMap[60]; float* m_WindStrength; // How strong the waves are at point X. % of waviness. float* m_DistanceHeightmap; // How far from the shore a point is. Manhattan CVector3D* m_BlurredNormalMap; // Cache a slightly blurred map of the normals of the terrain. // Waves vertex buffers std::vector< WaveObject* > m_ShoreWaves; // TODO: once we get C++11, remove pointer // Waves indices buffer. Only one since All Wave Objects have the same. CVertexBuffer::VBChunk* m_ShoreWaves_VBIndices; size_t m_MapSize; ssize_t m_TexSize; CTexturePtr m_WaveTex; CTexturePtr m_FoamTex; GLuint m_FancyTexture; GLuint m_FancyTextureDepth; GLuint m_ReflFboDepthTexture; GLuint m_RefrFboDepthTexture; // used to know what to update when updating parts of the terrain only. u32 m_updatei0; u32 m_updatej0; u32 m_updatei1; u32 m_updatej1; int m_WaterCurrentTex; bool m_RenderWater; // If disabled, force the use of the fixed function for rendering. bool m_WaterEffects; // Those variables register the current quality level. If there is a change, I have to recompile the shader. // Use real depth or use the fake precomputed one. bool m_WaterRealDepth; // Use fancy shore effects and show trails behind ships bool m_WaterFancyEffects; // Use refractions instead of simply making the water more or less transparent. bool m_WaterRefraction; // Use complete reflections instead of showing merely the sky. bool m_WaterReflection; bool m_NeedsReloading; // requires also recreating the super fancy information. bool m_NeedInfoUpdate; float m_WaterHeight; double m_WaterTexTimer; float m_RepeatPeriod; // Reflection and refraction textures for fancy water GLuint m_ReflectionTexture; GLuint m_RefractionTexture; size_t m_RefTextureSize; // framebuffer objects GLuint m_RefractionFbo; GLuint m_ReflectionFbo; GLuint m_FancyEffectsFBO; // Model-view-projection matrices for reflected & refracted cameras // (used to let the vertex shader do projective texturing) CMatrix3D m_ReflectionMatrix; CMatrix3D m_RefractionMatrix; CMatrix3D m_RefractionProjInvMatrix; CMatrix3D m_RefractionViewInvMatrix; // Water parameters std::wstring m_WaterType; // Which texture to use. CColor m_WaterColor; // Color of the water without refractions. This is what you're seeing when the water's deep or murkiness high. CColor m_WaterTint; // Tint of refraction in the water. float m_Waviness; // How big the waves are. float m_Murkiness; // How murky the water is. float m_WindAngle; // In which direction the water waves go. public: WaterManager(); ~WaterManager(); /** * LoadWaterTextures: Load water textures from within the * progressive load framework. * * @return 0 if loading has completed, a value from 1 to 100 (in percent of completion) * if more textures need to be loaded and a negative error value on failure. */ int LoadWaterTextures(); /** * Resize: Updates the fancy water textures so that water will render correctly * with fancy water. */ void Resize(); /** * ReloadWaterNormalTextures: Reload the normal textures so that changing * water type in Atlas will actually do the right thing. */ void ReloadWaterNormalTextures(); /** * UnloadWaterTextures: Free any loaded water textures and reset the internal state * so that another call to LoadWaterTextures will begin progressive loading. */ void UnloadWaterTextures(); /** * RecomputeWaterData: calculates all derived data from the waterheight */ void RecomputeWaterData(); /** * RecomputeWindStrength: calculates the intensity of waves */ void RecomputeWindStrength(); /** * RecomputeDistanceHeightmap: recalculates (or calculates) the distance heightmap. */ void RecomputeDistanceHeightmap(); /** * CreateWaveMeshes: Creates the waves objects (and meshes). */ void CreateWaveMeshes(); /** * Updates the map size. Will trigger a complete recalculation of fancy water information the next turn. */ void SetMapSize(size_t size); /** * Updates the settings to the one from the renderer, and sets m_NeedsReloading. */ void UpdateQuality(); /** * Returns true if fancy water shaders will be used (i.e. the hardware is capable * and it hasn't been configured off) */ bool WillRenderFancyWater(); void RenderWaves(const CFrustum& frustrum); }; #endif // INCLUDED_WATERMANAGER Index: ps/trunk/source/simulation2/components/ICmpRallyPointRenderer.cpp =================================================================== --- ps/trunk/source/simulation2/components/ICmpRallyPointRenderer.cpp (revision 25902) +++ ps/trunk/source/simulation2/components/ICmpRallyPointRenderer.cpp (revision 25903) @@ -1,33 +1,31 @@ /* Copyright (C) 2021 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 "ICmpRallyPointRenderer.h" #include "simulation2/system/InterfaceScripted.h" -class CFixedVector2D; - BEGIN_INTERFACE_WRAPPER(RallyPointRenderer) DEFINE_INTERFACE_METHOD("SetDisplayed", ICmpRallyPointRenderer, SetDisplayed) DEFINE_INTERFACE_METHOD("SetPosition", ICmpRallyPointRenderer, SetPosition) DEFINE_INTERFACE_METHOD("UpdatePosition", ICmpRallyPointRenderer, UpdatePosition) DEFINE_INTERFACE_METHOD("AddPosition", ICmpRallyPointRenderer, AddPosition_wrapper) DEFINE_INTERFACE_METHOD("Reset", ICmpRallyPointRenderer, Reset) DEFINE_INTERFACE_METHOD("IsSet", ICmpRallyPointRenderer, IsSet) DEFINE_INTERFACE_METHOD("UpdateColor", ICmpRallyPointRenderer, UpdateColor) END_INTERFACE_WRAPPER(RallyPointRenderer)