Apply new Code Styling to all files.
parent
4915a8130b
commit
e49ab18617
|
@ -6,14 +6,12 @@
|
|||
<file path="$PROJECT_DIR$/src" />
|
||||
<file path="$PROJECT_DIR$/test" />
|
||||
</sourceRoots>
|
||||
<libraryRoots>
|
||||
<file path="$PROJECT_DIR$/lib" />
|
||||
</libraryRoots>
|
||||
<excludeRoots>
|
||||
<file path="$PROJECT_DIR$/.github" />
|
||||
<file path="$PROJECT_DIR$/.idea" />
|
||||
<file path="$PROJECT_DIR$/Libraries" />
|
||||
<file path="$PROJECT_DIR$/cmake-build-install" />
|
||||
<file path="$PROJECT_DIR$/lib" />
|
||||
<file path="$PROJECT_DIR$/worlds" />
|
||||
<file path="$PROJECT_DIR$/worlds/world" />
|
||||
</excludeRoots>
|
||||
|
|
|
@ -1,321 +1,321 @@
|
|||
add_library(Zepha_Core
|
||||
client/Client.cpp
|
||||
client/Client.h
|
||||
client/conn/ClientNetworkInterpreter.cpp
|
||||
client/conn/ClientNetworkInterpreter.h
|
||||
client/conn/ServerConnection.cpp
|
||||
client/conn/ServerConnection.h
|
||||
client/entity/ParticleEntity.cpp
|
||||
client/entity/ParticleEntity.h
|
||||
client/entity/PlayerEntity.h
|
||||
client/entity/WireframeEntity.cpp
|
||||
client/entity/WireframeEntity.h
|
||||
client/graph/Camera.cpp
|
||||
client/graph/Camera.h
|
||||
client/graph/Drawable.h
|
||||
client/graph/DrawableGroup.cpp
|
||||
client/graph/DrawableGroup.h
|
||||
client/graph/Font.cpp
|
||||
client/graph/Font.h
|
||||
client/graph/mesh/ChunkMesh.cpp
|
||||
client/graph/mesh/ChunkMesh.h
|
||||
client/graph/mesh/ChunkMeshGenerator.cpp
|
||||
client/graph/mesh/ChunkMeshGenerator.h
|
||||
client/graph/mesh/ChunkRenderElem.h
|
||||
client/graph/mesh/ChunkVertex.h
|
||||
client/graph/mesh/EntityMesh.cpp
|
||||
client/graph/mesh/EntityMesh.h
|
||||
client/graph/mesh/EntityVertex.h
|
||||
client/graph/mesh/Mesh.cpp
|
||||
client/graph/mesh/Mesh.h
|
||||
client/graph/mesh/MeshChunk.cpp
|
||||
client/graph/mesh/MeshChunk.h
|
||||
client/graph/Model.cpp
|
||||
client/graph/Model.h
|
||||
client/graph/ModelAnimation.cpp
|
||||
client/graph/ModelAnimation.h
|
||||
client/graph/ModelBone.cpp
|
||||
client/graph/ModelBone.h
|
||||
client/graph/Renderer.cpp
|
||||
client/graph/Renderer.h
|
||||
client/graph/shader/BlurShader.cpp
|
||||
client/graph/shader/BlurShader.h
|
||||
client/graph/shader/EntityGeometryShader.cpp
|
||||
client/graph/shader/EntityGeometryShader.h
|
||||
client/graph/shader/GuiUniforms.h
|
||||
client/graph/shader/LightingShader.cpp
|
||||
client/graph/shader/LightingShader.h
|
||||
client/graph/shader/Shader.cpp
|
||||
client/graph/shader/Shader.h
|
||||
client/graph/shader/SSAOShader.cpp
|
||||
client/graph/shader/SSAOShader.h
|
||||
client/graph/shader/WorldGeometryShader.cpp
|
||||
client/graph/shader/WorldGeometryShader.h
|
||||
client/graph/Texture.cpp
|
||||
client/graph/Texture.h
|
||||
client/gui/basic/GuiContainer.cpp
|
||||
client/gui/basic/GuiContainer.h
|
||||
client/gui/basic/GuiGraph.cpp
|
||||
client/gui/basic/GuiGraph.h
|
||||
client/gui/basic/GuiInventoryItem.cpp
|
||||
client/gui/basic/GuiInventoryItem.h
|
||||
client/gui/basic/GuiModel.cpp
|
||||
client/gui/basic/GuiModel.h
|
||||
client/gui/basic/GuiRect.cpp
|
||||
client/gui/basic/GuiRect.h
|
||||
client/gui/basic/GuiText.cpp
|
||||
client/gui/basic/GuiText.h
|
||||
client/gui/compound/GuiImageButton.cpp
|
||||
client/gui/compound/GuiImageButton.h
|
||||
client/gui/compound/GuiInventoryList.cpp
|
||||
client/gui/compound/GuiInventoryList.h
|
||||
client/gui/compound/GuiLabelledGraph.cpp
|
||||
client/gui/compound/GuiLabelledGraph.cpp
|
||||
client/gui/DebugGui.cpp
|
||||
client/gui/DebugGui.h
|
||||
client/gui/GameGui.cpp
|
||||
client/gui/GameGui.h
|
||||
client/gui/GameGuiBuilder.cpp
|
||||
client/gui/GameGuiBuilder.h
|
||||
client/gui/GuiBuilder.cpp
|
||||
client/gui/GuiBuilder.h
|
||||
client/gui/GuiComponent.cpp
|
||||
client/gui/GuiComponent.h
|
||||
client/gui/SerialGui.h
|
||||
client/Input.cpp
|
||||
client/Input.h
|
||||
client/LocalServerInstance.cpp
|
||||
client/LocalServerInstance.h
|
||||
client/menu/MenuSandbox.cpp
|
||||
client/menu/MenuSandbox.h
|
||||
client/menu/SubgameConfig.h
|
||||
client/menu/SubgameDef.h
|
||||
client/scene/ConnectScene.cpp
|
||||
client/scene/ConnectScene.h
|
||||
client/scene/GameScene.cpp
|
||||
client/scene/GameScene.h
|
||||
client/scene/LuaErrorScene.cpp
|
||||
client/scene/LuaErrorScene.h
|
||||
client/scene/MainMenuScene.cpp
|
||||
client/scene/MainMenuScene.h
|
||||
client/scene/Scene.h
|
||||
client/scene/SceneManager.cpp
|
||||
client/scene/SceneManager.h
|
||||
client/stream/ChunkMeshDetails.h
|
||||
client/stream/MeshGenStream.cpp
|
||||
client/stream/MeshGenStream.h
|
||||
client/stream/WorldInterpolationStream.cpp
|
||||
client/stream/WorldInterpolationStream.h
|
||||
client/Window.cpp
|
||||
client/Window.h
|
||||
game/atlas/asset/AssetStorage.h
|
||||
game/atlas/asset/AssetType.h
|
||||
game/atlas/asset/AtlasRef.h
|
||||
game/atlas/asset/ModelStore.h
|
||||
game/atlas/asset/SerializedModel.h
|
||||
game/atlas/asset/ServerTexture.h
|
||||
game/atlas/BiomeAtlas.cpp
|
||||
game/atlas/BiomeAtlas.h
|
||||
game/atlas/DefinitionAtlas.cpp
|
||||
game/atlas/DefinitionAtlas.h
|
||||
game/atlas/LocalBiomeAtlas.cpp
|
||||
game/atlas/LocalBiomeAtlas.h
|
||||
game/atlas/LocalDefinitionAtlas.cpp
|
||||
game/atlas/LocalDefinitionAtlas.h
|
||||
game/atlas/ServerBiomeAtlas.cpp
|
||||
game/atlas/ServerBiomeAtlas.h
|
||||
game/atlas/ServerDefinitionAtlas.cpp
|
||||
game/atlas/ServerDefinitionAtlas.h
|
||||
game/atlas/TextureAtlas.cpp
|
||||
game/atlas/TextureAtlas.h
|
||||
client/Client.cpp
|
||||
client/Client.h
|
||||
client/conn/ClientNetworkInterpreter.cpp
|
||||
client/conn/ClientNetworkInterpreter.h
|
||||
client/conn/ServerConnection.cpp
|
||||
client/conn/ServerConnection.h
|
||||
client/entity/ParticleEntity.cpp
|
||||
client/entity/ParticleEntity.h
|
||||
client/entity/PlayerEntity.h
|
||||
client/entity/WireframeEntity.cpp
|
||||
client/entity/WireframeEntity.h
|
||||
client/graph/Camera.cpp
|
||||
client/graph/Camera.h
|
||||
client/graph/Drawable.h
|
||||
client/graph/DrawableGroup.cpp
|
||||
client/graph/DrawableGroup.h
|
||||
client/graph/Font.cpp
|
||||
client/graph/Font.h
|
||||
client/graph/mesh/ChunkMesh.cpp
|
||||
client/graph/mesh/ChunkMesh.h
|
||||
client/graph/mesh/ChunkMeshGenerator.cpp
|
||||
client/graph/mesh/ChunkMeshGenerator.h
|
||||
client/graph/mesh/ChunkRenderElem.h
|
||||
client/graph/mesh/ChunkVertex.h
|
||||
client/graph/mesh/EntityMesh.cpp
|
||||
client/graph/mesh/EntityMesh.h
|
||||
client/graph/mesh/EntityVertex.h
|
||||
client/graph/mesh/Mesh.cpp
|
||||
client/graph/mesh/Mesh.h
|
||||
client/graph/mesh/MeshChunk.cpp
|
||||
client/graph/mesh/MeshChunk.h
|
||||
client/graph/Model.cpp
|
||||
client/graph/Model.h
|
||||
client/graph/ModelAnimation.cpp
|
||||
client/graph/ModelAnimation.h
|
||||
client/graph/ModelBone.cpp
|
||||
client/graph/ModelBone.h
|
||||
client/graph/Renderer.cpp
|
||||
client/graph/Renderer.h
|
||||
client/graph/shader/BlurShader.cpp
|
||||
client/graph/shader/BlurShader.h
|
||||
client/graph/shader/EntityGeometryShader.cpp
|
||||
client/graph/shader/EntityGeometryShader.h
|
||||
client/graph/shader/GuiUniforms.h
|
||||
client/graph/shader/LightingShader.cpp
|
||||
client/graph/shader/LightingShader.h
|
||||
client/graph/shader/Shader.cpp
|
||||
client/graph/shader/Shader.h
|
||||
client/graph/shader/SSAOShader.cpp
|
||||
client/graph/shader/SSAOShader.h
|
||||
client/graph/shader/WorldGeometryShader.cpp
|
||||
client/graph/shader/WorldGeometryShader.h
|
||||
client/graph/Texture.cpp
|
||||
client/graph/Texture.h
|
||||
client/gui/basic/GuiContainer.cpp
|
||||
client/gui/basic/GuiContainer.h
|
||||
client/gui/basic/GuiGraph.cpp
|
||||
client/gui/basic/GuiGraph.h
|
||||
client/gui/basic/GuiInventoryItem.cpp
|
||||
client/gui/basic/GuiInventoryItem.h
|
||||
client/gui/basic/GuiModel.cpp
|
||||
client/gui/basic/GuiModel.h
|
||||
client/gui/basic/GuiRect.cpp
|
||||
client/gui/basic/GuiRect.h
|
||||
client/gui/basic/GuiText.cpp
|
||||
client/gui/basic/GuiText.h
|
||||
client/gui/compound/GuiImageButton.cpp
|
||||
client/gui/compound/GuiImageButton.h
|
||||
client/gui/compound/GuiInventoryList.cpp
|
||||
client/gui/compound/GuiInventoryList.h
|
||||
client/gui/compound/GuiLabelledGraph.cpp
|
||||
client/gui/compound/GuiLabelledGraph.cpp
|
||||
client/gui/DebugGui.cpp
|
||||
client/gui/DebugGui.h
|
||||
client/gui/GameGui.cpp
|
||||
client/gui/GameGui.h
|
||||
client/gui/GameGuiBuilder.cpp
|
||||
client/gui/GameGuiBuilder.h
|
||||
client/gui/GuiBuilder.cpp
|
||||
client/gui/GuiBuilder.h
|
||||
client/gui/GuiComponent.cpp
|
||||
client/gui/GuiComponent.h
|
||||
client/gui/SerialGui.h
|
||||
client/Input.cpp
|
||||
client/Input.h
|
||||
client/LocalServerInstance.cpp
|
||||
client/LocalServerInstance.h
|
||||
client/menu/MenuSandbox.cpp
|
||||
client/menu/MenuSandbox.h
|
||||
client/menu/SubgameConfig.h
|
||||
client/menu/SubgameDef.h
|
||||
client/scene/ConnectScene.cpp
|
||||
client/scene/ConnectScene.h
|
||||
client/scene/GameScene.cpp
|
||||
client/scene/GameScene.h
|
||||
client/scene/LuaErrorScene.cpp
|
||||
client/scene/LuaErrorScene.h
|
||||
client/scene/MainMenuScene.cpp
|
||||
client/scene/MainMenuScene.h
|
||||
client/scene/Scene.h
|
||||
client/scene/SceneManager.cpp
|
||||
client/scene/SceneManager.h
|
||||
client/stream/ChunkMeshDetails.h
|
||||
client/stream/MeshGenStream.cpp
|
||||
client/stream/MeshGenStream.h
|
||||
client/stream/WorldInterpolationStream.cpp
|
||||
client/stream/WorldInterpolationStream.h
|
||||
client/Window.cpp
|
||||
client/Window.h
|
||||
game/atlas/asset/AssetStorage.h
|
||||
game/atlas/asset/AssetType.h
|
||||
game/atlas/asset/AtlasRef.h
|
||||
game/atlas/asset/ModelStore.h
|
||||
game/atlas/asset/SerializedModel.h
|
||||
game/atlas/asset/ServerTexture.h
|
||||
game/atlas/BiomeAtlas.cpp
|
||||
game/atlas/BiomeAtlas.h
|
||||
game/atlas/DefinitionAtlas.cpp
|
||||
game/atlas/DefinitionAtlas.h
|
||||
game/atlas/LocalBiomeAtlas.cpp
|
||||
game/atlas/LocalBiomeAtlas.h
|
||||
game/atlas/LocalDefinitionAtlas.cpp
|
||||
game/atlas/LocalDefinitionAtlas.h
|
||||
game/atlas/ServerBiomeAtlas.cpp
|
||||
game/atlas/ServerBiomeAtlas.h
|
||||
game/atlas/ServerDefinitionAtlas.cpp
|
||||
game/atlas/ServerDefinitionAtlas.h
|
||||
game/atlas/TextureAtlas.cpp
|
||||
game/atlas/TextureAtlas.h
|
||||
game/def/BiomeDef.h
|
||||
game/def/BlockDef.cpp
|
||||
game/def/BlockDef.h
|
||||
game/def/CraftItemDef.cpp
|
||||
game/def/CraftItemDef.h
|
||||
game/def/ItemDef.h
|
||||
game/def/mesh/BlockModel.cpp
|
||||
game/def/mesh/BlockModel.h
|
||||
game/def/mesh/BlockModelVertex.h
|
||||
game/def/mesh/MeshPart.cpp
|
||||
game/def/mesh/MeshPart.h
|
||||
game/def/mesh/SelectionBox.h
|
||||
game/def/mesh/ShaderMod.h
|
||||
game/LocalSubgame.cpp
|
||||
game/LocalSubgame.h
|
||||
game/ServerSubgame.cpp
|
||||
game/ServerSubgame.h
|
||||
game/Subgame.h
|
||||
lua/Callback.h
|
||||
lua/customization/vec3.hpp
|
||||
lua/ErrorFormatter.cpp
|
||||
lua/ErrorFormatter.h
|
||||
lua/LocalLuaParser.cpp
|
||||
lua/LocalLuaParser.h
|
||||
lua/LocalModHandler.cpp
|
||||
lua/LocalModHandler.h
|
||||
lua/LuaKeybindHandler.cpp
|
||||
lua/LuaKeybindHandler.h
|
||||
lua/LuaMod.cpp
|
||||
lua/LuaMod.h
|
||||
lua/LuaParser.cpp
|
||||
lua/LuaParser.h
|
||||
lua/modules/BaseModule.h
|
||||
lua/modules/create_structure.h
|
||||
lua/modules/Dimension.cpp
|
||||
lua/modules/Dimension.h
|
||||
lua/modules/mSetGui.h
|
||||
lua/modules/mStartGame.h
|
||||
lua/modules/SubgameModule.cpp
|
||||
lua/modules/SubgameModule.h
|
||||
lua/modules/Time.cpp
|
||||
lua/modules/Time.h
|
||||
lua/register/RegisterBiome.h
|
||||
game/def/BlockDef.cpp
|
||||
game/def/BlockDef.h
|
||||
game/def/CraftItemDef.cpp
|
||||
game/def/CraftItemDef.h
|
||||
game/def/ItemDef.h
|
||||
game/def/mesh/BlockModel.cpp
|
||||
game/def/mesh/BlockModel.h
|
||||
game/def/mesh/BlockModelVertex.h
|
||||
game/def/mesh/MeshPart.cpp
|
||||
game/def/mesh/MeshPart.h
|
||||
game/def/mesh/SelectionBox.h
|
||||
game/def/mesh/ShaderMod.h
|
||||
game/LocalSubgame.cpp
|
||||
game/LocalSubgame.h
|
||||
game/ServerSubgame.cpp
|
||||
game/ServerSubgame.h
|
||||
game/Subgame.h
|
||||
lua/Callback.h
|
||||
lua/customization/vec3.hpp
|
||||
lua/ErrorFormatter.cpp
|
||||
lua/ErrorFormatter.h
|
||||
lua/LocalLuaParser.cpp
|
||||
lua/LocalLuaParser.h
|
||||
lua/LocalModHandler.cpp
|
||||
lua/LocalModHandler.h
|
||||
lua/LuaKeybindHandler.cpp
|
||||
lua/LuaKeybindHandler.h
|
||||
lua/LuaMod.cpp
|
||||
lua/LuaMod.h
|
||||
lua/LuaParser.cpp
|
||||
lua/LuaParser.h
|
||||
lua/modules/BaseModule.h
|
||||
lua/modules/create_structure.h
|
||||
lua/modules/Dimension.cpp
|
||||
lua/modules/Dimension.h
|
||||
lua/modules/mSetGui.h
|
||||
lua/modules/mStartGame.h
|
||||
lua/modules/SubgameModule.cpp
|
||||
lua/modules/SubgameModule.h
|
||||
lua/modules/Time.cpp
|
||||
lua/modules/Time.h
|
||||
lua/register/RegisterBiome.h
|
||||
lua/register/RegisterBlock.h
|
||||
lua/register/RegisterItem.h
|
||||
lua/register/RegisterKeybind.h
|
||||
lua/ServerLuaParser.cpp
|
||||
lua/ServerLuaParser.h
|
||||
lua/ServerModHandler.cpp
|
||||
lua/ServerModHandler.h
|
||||
lua/usertype/AnimationManager.cpp
|
||||
lua/usertype/AnimationManager.h
|
||||
lua/usertype/BaseUsertype.h
|
||||
lua/usertype/Dimension.cpp
|
||||
lua/usertype/Dimension.h
|
||||
lua/usertype/Entity.cpp
|
||||
lua/usertype/Entity.h
|
||||
lua/usertype/Inventory.cpp
|
||||
lua/usertype/Inventory.h
|
||||
lua/usertype/InventoryList.cpp
|
||||
lua/usertype/InventoryList.h
|
||||
lua/usertype/ItemStack.cpp
|
||||
lua/usertype/ItemStack.h
|
||||
lua/usertype/LuaGuiElement.cpp
|
||||
lua/usertype/LuaGuiElement.h
|
||||
lua/usertype/Player.cpp
|
||||
lua/usertype/Player.h
|
||||
lua/usertype/SubgameUsertype.h
|
||||
lua/usertype/Target.cpp
|
||||
lua/usertype/Target.h
|
||||
server/Server.cpp
|
||||
server/Server.h
|
||||
server/ServerClient.cpp
|
||||
server/ServerClient.h
|
||||
server/ServerClients.cpp
|
||||
server/ServerClients.h
|
||||
server/ServerConfig.cpp
|
||||
server/ServerConfig.h
|
||||
server/stream/ServerGenStream.cpp
|
||||
server/stream/ServerGenStream.h
|
||||
server/stream/ServerPacketStream.cpp
|
||||
server/stream/ServerPacketStream.h
|
||||
StartGame.h
|
||||
util/Any.h
|
||||
util/CovariantPtr.h
|
||||
util/frustum/Frustum.cpp
|
||||
util/frustum/Frustum.h
|
||||
util/frustum/FrustumAABB.cpp
|
||||
util/frustum/FrustumAABB.h
|
||||
util/frustum/FrustumPlane.cpp
|
||||
util/frustum/FrustumPlane.h
|
||||
util/Interp.h
|
||||
util/Lockable.h
|
||||
util/Log.h
|
||||
util/Mat4Conv.h
|
||||
util/net/Address.h
|
||||
util/net/Deserializer.h
|
||||
util/net/NetHandler.cpp
|
||||
util/net/NetHandler.h
|
||||
util/net/NetState.h
|
||||
util/net/Packet.cpp
|
||||
util/net/Packet.h
|
||||
util/net/PacketView.cpp
|
||||
util/net/PacketView.h
|
||||
util/net/Serializer.h
|
||||
util/Ray.cpp
|
||||
util/Ray.h
|
||||
util/RIE.h
|
||||
util/Schematic.cpp
|
||||
util/Schematic.h
|
||||
util/Space.h
|
||||
util/Target.cpp
|
||||
util/Target.h
|
||||
util/Timer.cpp
|
||||
util/Timer.h
|
||||
util/Util.h
|
||||
util/Vec.h
|
||||
util/Voronoi3D.cpp
|
||||
util/Voronoi3D.h
|
||||
world/dim/chunk/Chunk.cpp
|
||||
world/dim/chunk/Chunk.h
|
||||
world/dim/chunk/MapBlock.cpp
|
||||
world/dim/chunk/MapBlock.h
|
||||
world/dim/chunk/Region.cpp
|
||||
world/dim/chunk/Region.h
|
||||
world/dim/Dimension.cpp
|
||||
world/dim/Dimension.h
|
||||
world/dim/DimensionBase.cpp
|
||||
world/dim/DimensionBase.h
|
||||
world/dim/ent/AnimationSegment.h
|
||||
world/dim/ent/AnimationState.cpp
|
||||
world/dim/ent/AnimationState.h
|
||||
world/dim/ent/AnimChannel.cpp
|
||||
world/dim/ent/AnimChannel.h
|
||||
world/dim/ent/Collision.cpp
|
||||
world/dim/ent/Collision.h
|
||||
world/dim/ent/DrawableEntity.cpp
|
||||
world/dim/ent/DrawableEntity.h
|
||||
world/dim/ent/Entity.cpp
|
||||
world/dim/ent/Entity.h
|
||||
world/dim/ent/LocalLuaEntity.cpp
|
||||
world/dim/ent/LocalLuaEntity.h
|
||||
world/dim/ent/LuaEntity.cpp
|
||||
world/dim/ent/LuaEntity.h
|
||||
world/dim/ent/ServerLuaEntity.cpp
|
||||
world/dim/ent/ServerLuaEntity.h
|
||||
world/dim/file/FileManipulator.cpp
|
||||
world/dim/file/FileManipulator.h
|
||||
world/dim/LocalDimension.cpp
|
||||
world/dim/LocalDimension.h
|
||||
world/dim/ServerDimension.cpp
|
||||
world/dim/ServerDimension.h
|
||||
world/gen/MapGen.cpp
|
||||
world/gen/MapGen.h
|
||||
world/gen/MapGenProps.cpp
|
||||
world/gen/MapGenProps.h
|
||||
world/gen/NoiseSample.cpp
|
||||
world/gen/NoiseSample.h
|
||||
world/inv/Inventory.cpp
|
||||
world/inv/Inventory.h
|
||||
world/inv/InventoryList.cpp
|
||||
world/inv/InventoryList.h
|
||||
world/inv/InventoryRefs.cpp
|
||||
world/inv/InventoryRefs.h
|
||||
world/inv/ItemStack.cpp
|
||||
world/inv/ItemStack.h
|
||||
world/inv/LocalInventory.cpp
|
||||
world/inv/LocalInventory.h
|
||||
world/inv/LocalInventoryRefs.cpp
|
||||
world/inv/LocalInventoryRefs.h
|
||||
world/inv/ServerInventory.cpp
|
||||
world/inv/ServerInventory.h
|
||||
world/inv/ServerInventoryList.cpp
|
||||
world/inv/ServerInventoryList.h
|
||||
world/inv/ServerInventoryRefs.cpp
|
||||
world/inv/ServerInventoryRefs.h
|
||||
world/LocalWorld.cpp
|
||||
world/LocalWorld.h
|
||||
world/player/LocalPlayer.cpp
|
||||
world/player/LocalPlayer.h
|
||||
world/player/Player.cpp
|
||||
world/player/Player.h
|
||||
world/player/ServerPlayer.cpp
|
||||
world/player/ServerPlayer.h
|
||||
world/ServerWorld.cpp
|
||||
world/ServerWorld.h
|
||||
world/World.cpp
|
||||
world/World.h
|
||||
lua/register/RegisterKeybind.h
|
||||
lua/ServerLuaParser.cpp
|
||||
lua/ServerLuaParser.h
|
||||
lua/ServerModHandler.cpp
|
||||
lua/ServerModHandler.h
|
||||
lua/usertype/AnimationManager.cpp
|
||||
lua/usertype/AnimationManager.h
|
||||
lua/usertype/BaseUsertype.h
|
||||
lua/usertype/Dimension.cpp
|
||||
lua/usertype/Dimension.h
|
||||
lua/usertype/Entity.cpp
|
||||
lua/usertype/Entity.h
|
||||
lua/usertype/Inventory.cpp
|
||||
lua/usertype/Inventory.h
|
||||
lua/usertype/InventoryList.cpp
|
||||
lua/usertype/InventoryList.h
|
||||
lua/usertype/ItemStack.cpp
|
||||
lua/usertype/ItemStack.h
|
||||
lua/usertype/LuaGuiElement.cpp
|
||||
lua/usertype/LuaGuiElement.h
|
||||
lua/usertype/Player.cpp
|
||||
lua/usertype/Player.h
|
||||
lua/usertype/SubgameUsertype.h
|
||||
lua/usertype/Target.cpp
|
||||
lua/usertype/Target.h
|
||||
server/Server.cpp
|
||||
server/Server.h
|
||||
server/ServerClient.cpp
|
||||
server/ServerClient.h
|
||||
server/ServerClients.cpp
|
||||
server/ServerClients.h
|
||||
server/ServerConfig.cpp
|
||||
server/ServerConfig.h
|
||||
server/stream/ServerGenStream.cpp
|
||||
server/stream/ServerGenStream.h
|
||||
server/stream/ServerPacketStream.cpp
|
||||
server/stream/ServerPacketStream.h
|
||||
StartGame.h
|
||||
util/Any.h
|
||||
util/CovariantPtr.h
|
||||
util/frustum/Frustum.cpp
|
||||
util/frustum/Frustum.h
|
||||
util/frustum/FrustumAABB.cpp
|
||||
util/frustum/FrustumAABB.h
|
||||
util/frustum/FrustumPlane.cpp
|
||||
util/frustum/FrustumPlane.h
|
||||
util/Interp.h
|
||||
util/Lockable.h
|
||||
util/Log.h
|
||||
util/Mat4Conv.h
|
||||
util/net/Address.h
|
||||
util/net/Deserializer.h
|
||||
util/net/NetHandler.cpp
|
||||
util/net/NetHandler.h
|
||||
util/net/NetState.h
|
||||
util/net/Packet.cpp
|
||||
util/net/Packet.h
|
||||
util/net/PacketView.cpp
|
||||
util/net/PacketView.h
|
||||
util/net/Serializer.h
|
||||
util/Ray.cpp
|
||||
util/Ray.h
|
||||
util/RIE.h
|
||||
util/Schematic.cpp
|
||||
util/Schematic.h
|
||||
util/Space.h
|
||||
util/Target.cpp
|
||||
util/Target.h
|
||||
util/Timer.cpp
|
||||
util/Timer.h
|
||||
util/Util.h
|
||||
util/Vec.h
|
||||
util/Voronoi3D.cpp
|
||||
util/Voronoi3D.h
|
||||
world/dim/chunk/Chunk.cpp
|
||||
world/dim/chunk/Chunk.h
|
||||
world/dim/chunk/MapBlock.cpp
|
||||
world/dim/chunk/MapBlock.h
|
||||
world/dim/chunk/Region.cpp
|
||||
world/dim/chunk/Region.h
|
||||
world/dim/Dimension.cpp
|
||||
world/dim/Dimension.h
|
||||
world/dim/DimensionBase.cpp
|
||||
world/dim/DimensionBase.h
|
||||
world/dim/ent/AnimationSegment.h
|
||||
world/dim/ent/AnimationState.cpp
|
||||
world/dim/ent/AnimationState.h
|
||||
world/dim/ent/AnimChannel.cpp
|
||||
world/dim/ent/AnimChannel.h
|
||||
world/dim/ent/Collision.cpp
|
||||
world/dim/ent/Collision.h
|
||||
world/dim/ent/DrawableEntity.cpp
|
||||
world/dim/ent/DrawableEntity.h
|
||||
world/dim/ent/Entity.cpp
|
||||
world/dim/ent/Entity.h
|
||||
world/dim/ent/LocalLuaEntity.cpp
|
||||
world/dim/ent/LocalLuaEntity.h
|
||||
world/dim/ent/LuaEntity.cpp
|
||||
world/dim/ent/LuaEntity.h
|
||||
world/dim/ent/ServerLuaEntity.cpp
|
||||
world/dim/ent/ServerLuaEntity.h
|
||||
world/dim/file/FileManipulator.cpp
|
||||
world/dim/file/FileManipulator.h
|
||||
world/dim/LocalDimension.cpp
|
||||
world/dim/LocalDimension.h
|
||||
world/dim/ServerDimension.cpp
|
||||
world/dim/ServerDimension.h
|
||||
world/gen/MapGen.cpp
|
||||
world/gen/MapGen.h
|
||||
world/gen/MapGenProps.cpp
|
||||
world/gen/MapGenProps.h
|
||||
world/gen/NoiseSample.cpp
|
||||
world/gen/NoiseSample.h
|
||||
world/inv/Inventory.cpp
|
||||
world/inv/Inventory.h
|
||||
world/inv/InventoryList.cpp
|
||||
world/inv/InventoryList.h
|
||||
world/inv/InventoryRefs.cpp
|
||||
world/inv/InventoryRefs.h
|
||||
world/inv/ItemStack.cpp
|
||||
world/inv/ItemStack.h
|
||||
world/inv/LocalInventory.cpp
|
||||
world/inv/LocalInventory.h
|
||||
world/inv/LocalInventoryRefs.cpp
|
||||
world/inv/LocalInventoryRefs.h
|
||||
world/inv/ServerInventory.cpp
|
||||
world/inv/ServerInventory.h
|
||||
world/inv/ServerInventoryList.cpp
|
||||
world/inv/ServerInventoryList.h
|
||||
world/inv/ServerInventoryRefs.cpp
|
||||
world/inv/ServerInventoryRefs.h
|
||||
world/LocalWorld.cpp
|
||||
world/LocalWorld.h
|
||||
world/player/LocalPlayer.cpp
|
||||
world/player/LocalPlayer.h
|
||||
world/player/Player.cpp
|
||||
world/player/Player.h
|
||||
world/player/ServerPlayer.cpp
|
||||
world/player/ServerPlayer.h
|
||||
world/ServerWorld.cpp
|
||||
world/ServerWorld.h
|
||||
world/World.cpp
|
||||
world/World.h
|
||||
util/net/Address.cpp util/Bounds.cpp util/Bounds.h lua/register/CreateRegister.h lua/register/CreateRegister.cpp)
|
||||
|
||||
target_include_directories(Zepha_Core PUBLIC .)
|
|
@ -21,12 +21,13 @@
|
|||
|
||||
/**
|
||||
* Main entrance point to the program. (Am I really describing what the main function is?)
|
||||
* Intentionally kept minimal to allow for testing. Real startup logic is done in StartGame. *
|
||||
* Intentionally kept minimal to allow for testing. Real startup logic is done in StartGame.
|
||||
*
|
||||
* @param argc - Argument array length
|
||||
* @param argv - Argument array
|
||||
* @returns - A numerical value indicating exit status.
|
||||
*/
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
return StartGame(argc, argv);
|
||||
return StartGame(argc, argv);
|
||||
}
|
||||
|
|
156
src/StartGame.h
156
src/StartGame.h
|
@ -11,7 +11,9 @@
|
|||
#include "client/Client.h"
|
||||
#include "server/Server.h"
|
||||
|
||||
enum class Mode { CLIENT, SERVER };
|
||||
enum class Mode {
|
||||
CLIENT, SERVER
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
|
@ -23,22 +25,21 @@ enum class Mode { CLIENT, SERVER };
|
|||
*/
|
||||
|
||||
std::map<std::string, std::string> ParseArgs(int argc, char* argv[]) {
|
||||
//Collect arguments into `args` map
|
||||
std::map<std::string, std::string> args;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
|
||||
std::string arg(argv[i]);
|
||||
size_t equals = arg.find('=');
|
||||
std::string first = (equals == -1) ? arg : arg.substr(0, equals);
|
||||
|
||||
if (args.count(first)) throw std::invalid_argument("Duplicate argument " + first + ".");
|
||||
|
||||
if (equals == -1) args.emplace(first, "");
|
||||
else if (equals == arg.length() - 1) throw std::invalid_argument("Empty argument " + first + ".");
|
||||
else args.emplace(first, arg.substr(equals + 1, arg.length()));
|
||||
}
|
||||
|
||||
return args;
|
||||
std::map<std::string, std::string> args;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
|
||||
std::string arg(argv[i]);
|
||||
size_t equals = arg.find('=');
|
||||
std::string first = (equals == -1) ? arg : arg.substr(0, equals);
|
||||
|
||||
if (args.count(first)) throw std::invalid_argument("Duplicate argument " + first + ".");
|
||||
|
||||
if (equals == -1) args.emplace(first, "");
|
||||
else if (equals == arg.length() - 1) throw std::invalid_argument("Empty argument " + first + ".");
|
||||
else args.emplace(first, arg.substr(equals + 1, arg.length()));
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
|
||||
|
@ -50,74 +51,63 @@ std::map<std::string, std::string> ParseArgs(int argc, char* argv[]) {
|
|||
*/
|
||||
|
||||
int StartGame(int argc, char* argv[]) {
|
||||
Mode mode = Mode::CLIENT;
|
||||
|
||||
try {
|
||||
unsigned short port = Address::DEFAULT_PORT;
|
||||
std::string subgame = "";
|
||||
bool ascii = true;
|
||||
|
||||
/**
|
||||
* Handle command line arguments.
|
||||
* @arg mode ("client" | "server") - Whether to initialize a client instance, or a server. Defaults to "client".
|
||||
* @arg port (unsigned short) - The port that the server should listen on. Defaults to Address::DEFAULT_PORT.
|
||||
* @arg subgame (std::string) - The subgame that the server should load.
|
||||
* @arg noascii - Switch to disable ASCII from the console output.
|
||||
*/
|
||||
|
||||
for (auto arg : ParseArgs(argc, argv)) {
|
||||
switch (Util::hash(arg.first.c_str())) {
|
||||
default:
|
||||
throw std::runtime_error("Invalid argument '" + arg.first + "'.");
|
||||
|
||||
case Util::hash("--mode"):
|
||||
if (arg.second == "client") mode = Mode::CLIENT;
|
||||
else if (arg.second == "server") mode = Mode::SERVER;
|
||||
else throw std::runtime_error("Invalid mode specified.");
|
||||
break;
|
||||
Mode mode = Mode::CLIENT;
|
||||
|
||||
try {
|
||||
unsigned short port = Address::DEFAULT_PORT;
|
||||
std::string subgame = "";
|
||||
bool ascii = true;
|
||||
|
||||
/**
|
||||
* Handle command line arguments.
|
||||
* @arg mode ("client" | "server") - Whether to initialize a client instance, or a server. Defaults to "client".
|
||||
* @arg port (unsigned short) - The port that the server should listen on. Defaults to Address::DEFAULT_PORT.
|
||||
* @arg subgame (std::string) - The subgame that the server should load.
|
||||
* @arg noascii - Switch to disable ASCII from the console output.
|
||||
*/
|
||||
|
||||
for (auto arg : ParseArgs(argc, argv)) {
|
||||
switch (Util::hash(arg.first.c_str())) {
|
||||
default: throw std::runtime_error("Invalid argument '" + arg.first + "'.");
|
||||
|
||||
case Util::hash("--mode"):
|
||||
if (arg.second == "client") mode = Mode::CLIENT;
|
||||
else if (arg.second == "server") mode = Mode::SERVER;
|
||||
else throw std::runtime_error("Invalid mode specified.");
|
||||
break;
|
||||
|
||||
// case Util::hash("--address"):
|
||||
// addr.host = arg.second;
|
||||
// break;
|
||||
|
||||
case Util::hash("--port"):
|
||||
port = static_cast<unsigned short>(stoi(arg.second));
|
||||
break;
|
||||
|
||||
case Util::hash("--subgame"):
|
||||
subgame = arg.second;
|
||||
break;
|
||||
|
||||
case Util::hash("--noascii"):
|
||||
ascii = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ascii) {
|
||||
Log::clear();
|
||||
std::cout <<
|
||||
"\n"
|
||||
"\t\t ____ ____ ____ _ _ __ \n"
|
||||
"\t\t(__ )( __)( _ \\/ )( \\ / _\\ \n"
|
||||
"\t\t / _/ ) _) ) __/) __ (/ \\\n"
|
||||
"\t\t(____)(____)(__) \\_)(_/\\_/\\_/\n" << std::endl;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case Mode::CLIENT: {
|
||||
Client c({1366, 768});
|
||||
break; }
|
||||
|
||||
case Mode::SERVER: {
|
||||
Server s(port, subgame);
|
||||
break; }
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cout << Log::err << "Zepha failed to start.\n" << e.what() << Log::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
case Util::hash("--port"): port = static_cast<unsigned short>(stoi(arg.second));
|
||||
break;
|
||||
|
||||
case Util::hash("--subgame"): subgame = arg.second;
|
||||
break;
|
||||
|
||||
case Util::hash("--noascii"): ascii = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ascii) {
|
||||
Log::clear();
|
||||
std::cout <<
|
||||
"\n"
|
||||
"\t\t ____ ____ ____ _ _ __ \n"
|
||||
"\t\t(__ )( __)( _ \\/ )( \\ / _\\ \n"
|
||||
"\t\t / _/ ) _) ) __/) __ (/ \\\n"
|
||||
"\t\t(____)(____)(__) \\_)(_/\\_/\\_/\n" << std::endl;
|
||||
}
|
||||
|
||||
if (mode == Mode::CLIENT) Client({ 1366, 768 });
|
||||
else Server(port, subgame);
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cout << Log::err << "Zepha failed to start.\n" << e.what() << Log::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
*/
|
||||
|
||||
Client::Client(glm::ivec2 window) :
|
||||
renderer(window) {
|
||||
|
||||
std::cout << Log::info << "Starting Zepha Client." << Log::endl;
|
||||
|
||||
scene.setScene(std::make_unique<MainMenuScene>(*this));
|
||||
while (!renderer.window.shouldClose()) loop();
|
||||
renderer(window) {
|
||||
|
||||
std::cout << Log::info << "Starting Zepha Client." << Log::endl;
|
||||
|
||||
scene.setScene(std::make_unique<MainMenuScene>(*this));
|
||||
while (!renderer.window.shouldClose()) loop();
|
||||
}
|
||||
|
||||
|
||||
|
@ -33,7 +33,7 @@ Client::Client(glm::ivec2 window) :
|
|||
*/
|
||||
|
||||
double Client::getDelta() {
|
||||
return delta;
|
||||
return delta;
|
||||
}
|
||||
|
||||
|
||||
|
@ -44,11 +44,11 @@ double Client::getDelta() {
|
|||
*/
|
||||
|
||||
void Client::startLocalServer(const std::string& subgame) {
|
||||
//TODO: Implement Local Server
|
||||
//TODO: Implement Local Server
|
||||
// localServer = std::make_shared<LocalServerInstance>(executablePath, addr.port, state.subgame);
|
||||
// localServer->start();
|
||||
|
||||
scene.setScene(std::make_unique<ConnectScene>(*this, Address { "127.0.0.1", Address::DEFAULT_PORT }));
|
||||
|
||||
scene.setScene(std::make_unique<ConnectScene>(*this, Address{ "127.0.0.1", Address::DEFAULT_PORT }));
|
||||
}
|
||||
|
||||
|
||||
|
@ -58,12 +58,12 @@ void Client::startLocalServer(const std::string& subgame) {
|
|||
*/
|
||||
|
||||
void Client::loop() {
|
||||
double now = glfwGetTime();
|
||||
delta = now - timeElapsed;
|
||||
timeElapsed = now;
|
||||
|
||||
glfwPollEvents();
|
||||
|
||||
scene.update();
|
||||
renderer.update(delta);
|
||||
double now = glfwGetTime();
|
||||
delta = now - timeElapsed;
|
||||
timeElapsed = now;
|
||||
|
||||
glfwPollEvents();
|
||||
|
||||
scene.update();
|
||||
renderer.update(delta);
|
||||
}
|
|
@ -16,26 +16,27 @@
|
|||
class LocalServerInstance;
|
||||
|
||||
class Client {
|
||||
public:
|
||||
Client(const Client& o) = delete;
|
||||
explicit Client(glm::ivec2 window);
|
||||
|
||||
double getDelta();
|
||||
|
||||
void startLocalServer(const std::string& subgame);
|
||||
|
||||
Renderer renderer;
|
||||
SceneManager scene;
|
||||
ServerConnection connection {};
|
||||
|
||||
std::shared_ptr<LocalSubgame> game = std::make_shared<LocalSubgame>("../assets/textures");
|
||||
|
||||
private:
|
||||
void loop();
|
||||
|
||||
std::shared_ptr<LocalServerInstance> localServer = nullptr;
|
||||
|
||||
double delta = 0;
|
||||
double timeElapsed = 0;
|
||||
public:
|
||||
Client(const Client& o) = delete;
|
||||
|
||||
explicit Client(glm::ivec2 window);
|
||||
|
||||
double getDelta();
|
||||
|
||||
void startLocalServer(const std::string& subgame);
|
||||
|
||||
Renderer renderer;
|
||||
SceneManager scene;
|
||||
ServerConnection connection{};
|
||||
|
||||
std::shared_ptr<LocalSubgame> game = std::make_shared<LocalSubgame>("../assets/textures");
|
||||
|
||||
private:
|
||||
void loop();
|
||||
|
||||
std::shared_ptr<LocalServerInstance> localServer = nullptr;
|
||||
|
||||
double delta = 0;
|
||||
double timeElapsed = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -11,161 +11,161 @@
|
|||
#include "Window.h"
|
||||
|
||||
Input::Input() {
|
||||
for (bool& key : keysDown) key = false;
|
||||
for (bool& key : keysPressed) key = false;
|
||||
for (bool& key : keysReleased) key = false;
|
||||
for (bool& key : keysNew) key = false;
|
||||
for (bool& key : keysDown) key = false;
|
||||
for (bool& key : keysPressed) key = false;
|
||||
for (bool& key : keysReleased) key = false;
|
||||
for (bool& key : keysNew) key = false;
|
||||
}
|
||||
|
||||
void Input::init(GLFWwindow *window, glm::ivec2* winDimensions) {
|
||||
this->window = window;
|
||||
this->winDimensions = winDimensions;
|
||||
glfwSetKeyCallback(window, keyCallback);
|
||||
glfwSetScrollCallback(window, scrollCallback);
|
||||
void Input::init(GLFWwindow* window, glm::ivec2* winDimensions) {
|
||||
this->window = window;
|
||||
this->winDimensions = winDimensions;
|
||||
glfwSetKeyCallback(window, keyCallback);
|
||||
glfwSetScrollCallback(window, scrollCallback);
|
||||
}
|
||||
|
||||
void Input::setCallback(std::function<void(bool, int)> callback) {
|
||||
this->callback = callback;
|
||||
this->callback = callback;
|
||||
}
|
||||
|
||||
void Input::update() {
|
||||
for (bool &key : keysPressed) key = false;
|
||||
for (bool &key : keysReleased) key = false;
|
||||
|
||||
for (int i = 0; i < 1024; i++) {
|
||||
bool key = keysNew[i];
|
||||
|
||||
if (key) {
|
||||
if (!keysDown[i]) {
|
||||
keysPressed[i] = true;
|
||||
if (callback) callback(true, i);
|
||||
}
|
||||
keysDown[i] = true;
|
||||
}
|
||||
else {
|
||||
if (keysDown[i]) {
|
||||
keysReleased[i] = true;
|
||||
if (callback) callback(false, i);
|
||||
}
|
||||
keysDown[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& s : mouseState) {
|
||||
s.pressed = false;
|
||||
s.released = false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 12; i++) {
|
||||
keysNew[i] = false;
|
||||
}
|
||||
|
||||
updateMouse(0);
|
||||
updateMouse(1);
|
||||
updateMouse(2);
|
||||
|
||||
if (glfwGetWindowAttrib(window, GLFW_FOCUSED) == GL_FALSE) {
|
||||
mouseIsLocked = false;
|
||||
delta = {};
|
||||
}
|
||||
else {
|
||||
double mouseX, mouseY;
|
||||
glfwGetCursorPos(window, &mouseX, &mouseY);
|
||||
|
||||
if (!mouseIsLocked) {
|
||||
if (!forceMouseUnlocked && mousePressed(GLFW_MOUSE_BUTTON_LEFT)) {
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||
glfwSetCursorPos(window, winDimensions->x / 2, winDimensions->y / 2);
|
||||
mouseIsLocked = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
delta = {mouseX - (winDimensions->x / 2), -(mouseY - (winDimensions->y / 2))};
|
||||
glfwSetCursorPos(window, winDimensions->x / 2, winDimensions->y / 2);
|
||||
}
|
||||
}
|
||||
for (bool& key : keysPressed) key = false;
|
||||
for (bool& key : keysReleased) key = false;
|
||||
|
||||
for (int i = 0; i < 1024; i++) {
|
||||
bool key = keysNew[i];
|
||||
|
||||
if (key) {
|
||||
if (!keysDown[i]) {
|
||||
keysPressed[i] = true;
|
||||
if (callback) callback(true, i);
|
||||
}
|
||||
keysDown[i] = true;
|
||||
}
|
||||
else {
|
||||
if (keysDown[i]) {
|
||||
keysReleased[i] = true;
|
||||
if (callback) callback(false, i);
|
||||
}
|
||||
keysDown[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& s : mouseState) {
|
||||
s.pressed = false;
|
||||
s.released = false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 12; i++) {
|
||||
keysNew[i] = false;
|
||||
}
|
||||
|
||||
updateMouse(0);
|
||||
updateMouse(1);
|
||||
updateMouse(2);
|
||||
|
||||
if (glfwGetWindowAttrib(window, GLFW_FOCUSED) == GL_FALSE) {
|
||||
mouseIsLocked = false;
|
||||
delta = {};
|
||||
}
|
||||
else {
|
||||
double mouseX, mouseY;
|
||||
glfwGetCursorPos(window, &mouseX, &mouseY);
|
||||
|
||||
if (!mouseIsLocked) {
|
||||
if (!forceMouseUnlocked && mousePressed(GLFW_MOUSE_BUTTON_LEFT)) {
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||
glfwSetCursorPos(window, winDimensions->x / 2, winDimensions->y / 2);
|
||||
mouseIsLocked = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
delta = { mouseX - (winDimensions->x / 2), -(mouseY - (winDimensions->y / 2)) };
|
||||
glfwSetCursorPos(window, winDimensions->x / 2, winDimensions->y / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Input::keyDown(int key) {
|
||||
return keysDown[key];
|
||||
return keysDown[key];
|
||||
}
|
||||
|
||||
bool Input::keyPressed(int key) {
|
||||
return keysPressed[key];
|
||||
return keysPressed[key];
|
||||
}
|
||||
|
||||
bool Input::keyReleased(int key) {
|
||||
return keysReleased[key];
|
||||
return keysReleased[key];
|
||||
}
|
||||
|
||||
bool Input::mouseDown(int button) {
|
||||
return mouseState[button].down;
|
||||
return mouseState[button].down;
|
||||
}
|
||||
|
||||
bool Input::mousePressed(int button) {
|
||||
return mouseState[button].pressed;
|
||||
return mouseState[button].pressed;
|
||||
}
|
||||
|
||||
bool Input::mouseReleased(int button) {
|
||||
return mouseState[button].released;
|
||||
return mouseState[button].released;
|
||||
}
|
||||
|
||||
void Input::updateMouse(int button) {
|
||||
if (glfwGetMouseButton(window, button) == GLFW_PRESS) {
|
||||
if (!mouseState[button].down) mouseState[button].pressed = true;
|
||||
mouseState[button].down = true;
|
||||
}
|
||||
else {
|
||||
if (mouseState[button].down) mouseState[button].released = true;
|
||||
mouseState[button].down = false;
|
||||
}
|
||||
if (glfwGetMouseButton(window, button) == GLFW_PRESS) {
|
||||
if (!mouseState[button].down) mouseState[button].pressed = true;
|
||||
mouseState[button].down = true;
|
||||
}
|
||||
else {
|
||||
if (mouseState[button].down) mouseState[button].released = true;
|
||||
mouseState[button].down = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Input::keyCallback(GLFWwindow* window, int key, int code, int action, int mode) {
|
||||
auto w = static_cast<Window*>(glfwGetWindowUserPointer(window));
|
||||
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE);
|
||||
if (key >= 32 && key < 1024) {
|
||||
if (action == GLFW_PRESS) w->input.keysNew[key] = true;
|
||||
else if (action == GLFW_RELEASE) w->input.keysNew[key] = false;
|
||||
}
|
||||
auto w = static_cast<Window*>(glfwGetWindowUserPointer(window));
|
||||
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE);
|
||||
if (key >= 32 && key < 1024) {
|
||||
if (action == GLFW_PRESS) w->input.keysNew[key] = true;
|
||||
else if (action == GLFW_RELEASE) w->input.keysNew[key] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Input::scrollCallback(GLFWwindow *window, double xO, double yO) {
|
||||
auto w = static_cast<Window*>(glfwGetWindowUserPointer(window));
|
||||
|
||||
if (xO > 0) {
|
||||
//Right
|
||||
w->input.keysNew[11] = true;
|
||||
}
|
||||
else if (xO < 0) {
|
||||
// Left
|
||||
w->input.keysNew[10] = true;
|
||||
}
|
||||
|
||||
if (yO > 0) {
|
||||
// Up
|
||||
w->input.keysNew[8] = true;
|
||||
}
|
||||
else if (yO < 0) {
|
||||
// Down
|
||||
w->input.keysNew[9] = true;
|
||||
}
|
||||
void Input::scrollCallback(GLFWwindow* window, double xO, double yO) {
|
||||
auto w = static_cast<Window*>(glfwGetWindowUserPointer(window));
|
||||
|
||||
if (xO > 0) {
|
||||
//Right
|
||||
w->input.keysNew[11] = true;
|
||||
}
|
||||
else if (xO < 0) {
|
||||
// Left
|
||||
w->input.keysNew[10] = true;
|
||||
}
|
||||
|
||||
if (yO > 0) {
|
||||
// Up
|
||||
w->input.keysNew[8] = true;
|
||||
}
|
||||
else if (yO < 0) {
|
||||
// Down
|
||||
w->input.keysNew[9] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Input::lockMouse(bool lock) {
|
||||
forceMouseUnlocked = !lock;
|
||||
mouseIsLocked = lock;
|
||||
glfwSetCursorPos(window, winDimensions->x / 2, winDimensions->y / 2);
|
||||
glfwSetInputMode(window, GLFW_CURSOR, (mouseIsLocked ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL));
|
||||
delta = {};
|
||||
forceMouseUnlocked = !lock;
|
||||
mouseIsLocked = lock;
|
||||
glfwSetCursorPos(window, winDimensions->x / 2, winDimensions->y / 2);
|
||||
glfwSetInputMode(window, GLFW_CURSOR, (mouseIsLocked ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL));
|
||||
delta = {};
|
||||
}
|
||||
|
||||
glm::ivec2 Input::mousePos() {
|
||||
double xPos, yPos;
|
||||
glfwGetCursorPos(window, &xPos, &yPos);
|
||||
return glm::ivec2 { static_cast<int>(xPos), static_cast<int>(yPos) };
|
||||
double xPos, yPos;
|
||||
glfwGetCursorPos(window, &xPos, &yPos);
|
||||
return glm::ivec2{ static_cast<int>(xPos), static_cast<int>(yPos) };
|
||||
}
|
||||
|
||||
glm::vec2 Input::mouseDelta() {
|
||||
return delta;
|
||||
return delta;
|
||||
}
|
||||
|
|
|
@ -9,43 +9,58 @@
|
|||
#include <glm/vec2.hpp>
|
||||
|
||||
class Input {
|
||||
public:
|
||||
Input();
|
||||
void init(GLFWwindow* window, glm::ivec2* winDimensions);
|
||||
void setCallback(std::function<void(bool, int)> callback);
|
||||
|
||||
void update();
|
||||
|
||||
bool keyDown(int key);
|
||||
bool keyPressed(int key);
|
||||
bool keyReleased(int key);
|
||||
|
||||
bool mouseDown(int button);
|
||||
bool mousePressed(int button);
|
||||
bool mouseReleased(int button);
|
||||
|
||||
void lockMouse(bool lock);
|
||||
glm::ivec2 mousePos();
|
||||
glm::vec2 mouseDelta();
|
||||
private:
|
||||
void updateMouse(int key);
|
||||
static void keyCallback(GLFWwindow* window, int key, int code, int action, int mode);
|
||||
static void scrollCallback(GLFWwindow* window, double, double yO);
|
||||
|
||||
GLFWwindow* window = nullptr;
|
||||
glm::ivec2* winDimensions = nullptr;
|
||||
|
||||
bool keysNew[1024] {false};
|
||||
bool keysDown[1024] {false};
|
||||
bool keysPressed[1024] {false};
|
||||
bool keysReleased[1024] {false};
|
||||
|
||||
struct mouse { bool down = false; bool pressed = false; bool released = false; };
|
||||
std::array<mouse, 3> mouseState {};
|
||||
glm::vec2 delta;
|
||||
|
||||
bool mouseIsLocked = false;
|
||||
bool forceMouseUnlocked = false;
|
||||
|
||||
std::function<void(bool, int)> callback = nullptr;
|
||||
public:
|
||||
Input();
|
||||
|
||||
void init(GLFWwindow* window, glm::ivec2* winDimensions);
|
||||
|
||||
void setCallback(std::function<void(bool, int)> callback);
|
||||
|
||||
void update();
|
||||
|
||||
bool keyDown(int key);
|
||||
|
||||
bool keyPressed(int key);
|
||||
|
||||
bool keyReleased(int key);
|
||||
|
||||
bool mouseDown(int button);
|
||||
|
||||
bool mousePressed(int button);
|
||||
|
||||
bool mouseReleased(int button);
|
||||
|
||||
void lockMouse(bool lock);
|
||||
|
||||
glm::ivec2 mousePos();
|
||||
|
||||
glm::vec2 mouseDelta();
|
||||
|
||||
private:
|
||||
void updateMouse(int key);
|
||||
|
||||
static void keyCallback(GLFWwindow* window, int key, int code, int action, int mode);
|
||||
|
||||
static void scrollCallback(GLFWwindow* window, double, double yO);
|
||||
|
||||
GLFWwindow* window = nullptr;
|
||||
glm::ivec2* winDimensions = nullptr;
|
||||
|
||||
bool keysNew[1024]{ false };
|
||||
bool keysDown[1024]{ false };
|
||||
bool keysPressed[1024]{ false };
|
||||
bool keysReleased[1024]{ false };
|
||||
|
||||
struct mouse {
|
||||
bool down = false;
|
||||
bool pressed = false;
|
||||
bool released = false;
|
||||
};
|
||||
std::array<mouse, 3> mouseState{};
|
||||
glm::vec2 delta;
|
||||
|
||||
bool mouseIsLocked = false;
|
||||
bool forceMouseUnlocked = false;
|
||||
|
||||
std::function<void(bool, int)> callback = nullptr;
|
||||
};
|
|
@ -7,45 +7,45 @@
|
|||
#include "server/Server.h"
|
||||
#include <iostream>
|
||||
|
||||
LocalServerInstance::LocalServerInstance(const std::string &path, unsigned short port, const std::string& subgame) :
|
||||
port(port),
|
||||
path(path),
|
||||
subgame(subgame) {}
|
||||
LocalServerInstance::LocalServerInstance(const std::string& path, unsigned short port, const std::string& subgame) :
|
||||
port(port),
|
||||
path(path),
|
||||
subgame(subgame) {}
|
||||
|
||||
bool LocalServerInstance::start() {
|
||||
#ifndef _WIN32
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
const auto sub = ("--subgame=" + subgame);
|
||||
char *arr[] = {
|
||||
const_cast <char*>(""),
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
const auto sub = ("--subgame=" + subgame);
|
||||
char* arr[] = {
|
||||
const_cast <char*>(""),
|
||||
// const_cast <char*>("-iconic"),
|
||||
const_cast <char*>("-e"),
|
||||
const_cast <char*>(path.data()),
|
||||
const_cast <char*>("--mode=server"),
|
||||
const_cast <char*>(sub.data()),
|
||||
static_cast<char*>(nullptr)
|
||||
};
|
||||
|
||||
execvp("xterm", arr);
|
||||
}
|
||||
return true;
|
||||
const_cast <char*>("-e"),
|
||||
const_cast <char*>(path.data()),
|
||||
const_cast <char*>("--mode=server"),
|
||||
const_cast <char*>(sub.data()),
|
||||
static_cast<char*>(nullptr)
|
||||
};
|
||||
|
||||
execvp("xterm", arr);
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
std::thread([&]() {
|
||||
Server s(port, subgame);
|
||||
}).detach();
|
||||
return true;
|
||||
std::thread([&]() {
|
||||
Server s(port, subgame);
|
||||
}).detach();
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void LocalServerInstance::stop() {
|
||||
#ifndef _WIN32
|
||||
if (pid != 0) kill(pid, SIGKILL);
|
||||
#else
|
||||
std::cout << Log::err << "Local Server destructor not implemented on Windows!" << Log::endl;
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
if (pid != 0) kill(pid, SIGKILL);
|
||||
#else
|
||||
std::cout << Log::err << "Local Server destructor not implemented on Windows!" << Log::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
LocalServerInstance::~LocalServerInstance() {
|
||||
stop();
|
||||
stop();
|
||||
}
|
|
@ -7,23 +7,27 @@
|
|||
#include <string>
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <thread>
|
||||
#include <zconf.h>
|
||||
#include <signal.h>
|
||||
|
||||
#endif
|
||||
|
||||
class LocalServerInstance {
|
||||
public:
|
||||
LocalServerInstance(const std::string& path, unsigned short port, const std::string& subgame);
|
||||
|
||||
bool start();
|
||||
void stop();
|
||||
|
||||
~LocalServerInstance();
|
||||
private:
|
||||
std::string path;
|
||||
std::string subgame;
|
||||
unsigned short port = 0;
|
||||
|
||||
int pid = 0;
|
||||
public:
|
||||
LocalServerInstance(const std::string& path, unsigned short port, const std::string& subgame);
|
||||
|
||||
bool start();
|
||||
|
||||
void stop();
|
||||
|
||||
~LocalServerInstance();
|
||||
|
||||
private:
|
||||
std::string path;
|
||||
std::string subgame;
|
||||
unsigned short port = 0;
|
||||
|
||||
int pid = 0;
|
||||
};
|
||||
|
|
|
@ -6,85 +6,85 @@
|
|||
|
||||
#include "util/Log.h"
|
||||
|
||||
Window::Window() : Window({800, 600}) {};
|
||||
Window::Window() : Window({ 800, 600 }) {};
|
||||
|
||||
Window::Window(glm::ivec2 win) :
|
||||
win(win), center(win.x / 2, win.y / 2) {
|
||||
|
||||
if (!glfwInit()) {
|
||||
glfwTerminate();
|
||||
throw std::runtime_error("Failed to initialize GLFW context.");
|
||||
}
|
||||
|
||||
// Version 3.3
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
|
||||
// Compatibility - No Backwards compat, only forwards
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||
|
||||
// Create the window
|
||||
if (!(mainWindow = glfwCreateWindow(win.x, win.y, "Zepha", nullptr, nullptr))) {
|
||||
glfwTerminate();
|
||||
throw std::runtime_error("Failed to initialize GLFW window.");
|
||||
}
|
||||
|
||||
glfwGetFramebufferSize(mainWindow, &win.x, &win.y);
|
||||
glfwMakeContextCurrent(mainWindow);
|
||||
glewExperimental = GL_TRUE;
|
||||
|
||||
handCursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
|
||||
|
||||
// Initialize GLEW
|
||||
GLenum error;
|
||||
if ((error = glewInit()) != GLEW_OK) {
|
||||
glfwTerminate();
|
||||
glfwDestroyWindow(mainWindow);
|
||||
printf("%s", reinterpret_cast<const char *>(glewGetErrorString(error)));
|
||||
throw std::runtime_error("GLEW Fatal error.");
|
||||
}
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glViewport(0, 0, win.x, win.y);
|
||||
|
||||
// Setup callbacks
|
||||
glfwSetWindowUserPointer(mainWindow, this);
|
||||
glfwSetScrollCallback(mainWindow, scrollCallback);
|
||||
glfwSetWindowSizeCallback(mainWindow, resizeCallback);
|
||||
|
||||
glfwSetInputMode(mainWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
glfwMaximizeWindow(mainWindow);
|
||||
|
||||
input.init(mainWindow, &this->win);
|
||||
win(win), center(win.x / 2, win.y / 2) {
|
||||
|
||||
if (!glfwInit()) {
|
||||
glfwTerminate();
|
||||
throw std::runtime_error("Failed to initialize GLFW context.");
|
||||
}
|
||||
|
||||
// Version 3.3
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
|
||||
// Compatibility - No Backwards compat, only forwards
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||
|
||||
// Create the window
|
||||
if (!(mainWindow = glfwCreateWindow(win.x, win.y, "Zepha", nullptr, nullptr))) {
|
||||
glfwTerminate();
|
||||
throw std::runtime_error("Failed to initialize GLFW window.");
|
||||
}
|
||||
|
||||
glfwGetFramebufferSize(mainWindow, &win.x, &win.y);
|
||||
glfwMakeContextCurrent(mainWindow);
|
||||
glewExperimental = GL_TRUE;
|
||||
|
||||
handCursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
|
||||
|
||||
// Initialize GLEW
|
||||
GLenum error;
|
||||
if ((error = glewInit()) != GLEW_OK) {
|
||||
glfwTerminate();
|
||||
glfwDestroyWindow(mainWindow);
|
||||
printf("%s", reinterpret_cast<const char*>(glewGetErrorString(error)));
|
||||
throw std::runtime_error("GLEW Fatal error.");
|
||||
}
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glViewport(0, 0, win.x, win.y);
|
||||
|
||||
// Setup callbacks
|
||||
glfwSetWindowUserPointer(mainWindow, this);
|
||||
glfwSetScrollCallback(mainWindow, scrollCallback);
|
||||
glfwSetWindowSizeCallback(mainWindow, resizeCallback);
|
||||
|
||||
glfwSetInputMode(mainWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
glfwMaximizeWindow(mainWindow);
|
||||
|
||||
input.init(mainWindow, &this->win);
|
||||
}
|
||||
|
||||
void Window::update() {
|
||||
input.update();
|
||||
input.update();
|
||||
}
|
||||
|
||||
bool Window::shouldClose() {
|
||||
return static_cast<bool>(glfwWindowShouldClose(mainWindow));
|
||||
return static_cast<bool>(glfwWindowShouldClose(mainWindow));
|
||||
}
|
||||
|
||||
void Window::swapBuffers() {
|
||||
glfwSwapBuffers(mainWindow);
|
||||
glfwSwapBuffers(mainWindow);
|
||||
}
|
||||
|
||||
void Window::addResizeCallback(const std::string &identifier, std::function<void(glm::ivec2)> cb) {
|
||||
resizeCallbacks.emplace(identifier, cb);
|
||||
void Window::addResizeCallback(const std::string& identifier, std::function<void(glm::ivec2)> cb) {
|
||||
resizeCallbacks.emplace(identifier, cb);
|
||||
}
|
||||
|
||||
void Window::removeResizeCallback(const std::string &identifier) {
|
||||
resizeCallbacks.erase(identifier);
|
||||
void Window::removeResizeCallback(const std::string& identifier) {
|
||||
resizeCallbacks.erase(identifier);
|
||||
}
|
||||
|
||||
glm::ivec2 Window::getSize() {
|
||||
return win;
|
||||
return win;
|
||||
}
|
||||
|
||||
void Window::setCursorHand(bool hand) {
|
||||
glfwSetCursor(mainWindow, hand ? handCursor : nullptr);
|
||||
glfwSetCursor(mainWindow, hand ? handCursor : nullptr);
|
||||
}
|
||||
|
||||
void Window::scrollCallback(GLFWwindow* window, double xO, double yO) {
|
||||
|
@ -93,16 +93,16 @@ void Window::scrollCallback(GLFWwindow* window, double xO, double yO) {
|
|||
}
|
||||
|
||||
void Window::resizeCallback(GLFWwindow* window, int width, int height) {
|
||||
auto w = static_cast<Window*>(glfwGetWindowUserPointer(window));
|
||||
|
||||
glfwGetFramebufferSize(window, &w->win.x, &w->win.y);
|
||||
glViewport(0, 0, w->win.x, w->win.y);
|
||||
|
||||
w->center = glm::ivec2(w->win.x / 2, w->win.y / 2);
|
||||
for (auto& cb : w->resizeCallbacks) cb.second(w->win);
|
||||
auto w = static_cast<Window*>(glfwGetWindowUserPointer(window));
|
||||
|
||||
glfwGetFramebufferSize(window, &w->win.x, &w->win.y);
|
||||
glViewport(0, 0, w->win.x, w->win.y);
|
||||
|
||||
w->center = glm::ivec2(w->win.x / 2, w->win.y / 2);
|
||||
for (auto& cb : w->resizeCallbacks) cb.second(w->win);
|
||||
}
|
||||
|
||||
Window::~Window() {
|
||||
glfwDestroyWindow(mainWindow);
|
||||
glfwTerminate();
|
||||
glfwDestroyWindow(mainWindow);
|
||||
glfwTerminate();
|
||||
}
|
|
@ -11,36 +11,42 @@
|
|||
#include "Input.h"
|
||||
|
||||
class Window {
|
||||
public:
|
||||
Window();
|
||||
Window(glm::ivec2 win);
|
||||
|
||||
void update();
|
||||
bool shouldClose();
|
||||
void swapBuffers();
|
||||
|
||||
void addResizeCallback(const std::string& identifier, std::function<void(glm::ivec2)> cb);
|
||||
void removeResizeCallback(const std::string& identifier);
|
||||
|
||||
glm::ivec2 getSize();
|
||||
void setCursorHand(bool hand);
|
||||
|
||||
~Window();
|
||||
|
||||
Input input;
|
||||
GLFWwindow* mainWindow = nullptr;
|
||||
private:
|
||||
static void scrollCallback(GLFWwindow* window, double xO, double yO);
|
||||
static void resizeCallback(GLFWwindow* window, int width, int height);
|
||||
|
||||
GLFWcursor* handCursor = nullptr;
|
||||
|
||||
glm::ivec2 win;
|
||||
glm::ivec2 center;
|
||||
|
||||
bool keys[1024] {};
|
||||
|
||||
std::map<std::string, std::function<void(glm::ivec2)>> resizeCallbacks;
|
||||
|
||||
public:
|
||||
Window();
|
||||
|
||||
Window(glm::ivec2 win);
|
||||
|
||||
void update();
|
||||
|
||||
bool shouldClose();
|
||||
|
||||
void swapBuffers();
|
||||
|
||||
void addResizeCallback(const std::string& identifier, std::function<void(glm::ivec2)> cb);
|
||||
|
||||
void removeResizeCallback(const std::string& identifier);
|
||||
|
||||
glm::ivec2 getSize();
|
||||
|
||||
void setCursorHand(bool hand);
|
||||
|
||||
~Window();
|
||||
|
||||
Input input;
|
||||
GLFWwindow* mainWindow = nullptr;
|
||||
private:
|
||||
static void scrollCallback(GLFWwindow* window, double xO, double yO);
|
||||
|
||||
static void resizeCallback(GLFWwindow* window, int width, int height);
|
||||
|
||||
GLFWcursor* handCursor = nullptr;
|
||||
|
||||
glm::ivec2 win;
|
||||
glm::ivec2 center;
|
||||
|
||||
bool keys[1024]{};
|
||||
|
||||
std::map<std::string, std::function<void(glm::ivec2)>> resizeCallbacks;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -14,126 +14,131 @@
|
|||
#include "util/net/NetHandler.h"
|
||||
#include "world/player/LocalPlayer.h"
|
||||
|
||||
ClientNetworkInterpreter::ClientNetworkInterpreter(ServerConnection &connection, LocalWorld& world) :
|
||||
world(world), connection(connection) {}
|
||||
ClientNetworkInterpreter::ClientNetworkInterpreter(ServerConnection& connection, LocalWorld& world) :
|
||||
world(world), connection(connection) {}
|
||||
|
||||
void ClientNetworkInterpreter::init(std::function<void(std::unique_ptr<PacketView>)> invCallback) {
|
||||
this->onInvPacket = invCallback;
|
||||
this->onInvPacket = invCallback;
|
||||
}
|
||||
|
||||
void ClientNetworkInterpreter::update() {
|
||||
recvPackets = 0;
|
||||
|
||||
ENetEvent event;
|
||||
while (connection.pollEvents(&event)) {
|
||||
recvPackets++;
|
||||
|
||||
switch (event.type) {
|
||||
default: break;
|
||||
case ENET_EVENT_TYPE_CONNECT: {
|
||||
std::cout << Log::info << "Connected to server "
|
||||
<< NetHandler::intToIPString(event.peer->address.host)
|
||||
<< ":" << event.peer->address.port << "." << Log::endl;
|
||||
break;
|
||||
}
|
||||
case ENET_EVENT_TYPE_RECEIVE: {
|
||||
std::unique_ptr<PacketView> p = std::make_unique<PacketView>(event.packet);
|
||||
receivedPacket(std::move(p));
|
||||
break;
|
||||
}
|
||||
case ENET_EVENT_TYPE_DISCONNECT: {
|
||||
std::cout << Log::info << "Disconnected from server "
|
||||
<< event.peer->address.host << ":" << event.peer->address.port << "." << Log::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto player = world.getPlayer();
|
||||
if (player) Serializer()
|
||||
.appendE(NetField::POS).append(player->getPos())
|
||||
.appendE(NetField::VEL).append(player->getVel())
|
||||
.appendE(NetField::LOOK_PITCH).append(player->getPitch())
|
||||
.appendE(NetField::LOOK_YAW).append(player->getYaw())
|
||||
.packet(Packet::Type::THIS_PLAYER_INFO, false).sendTo(connection.getPeer(), Packet::Channel::INTERACT);
|
||||
recvPackets = 0;
|
||||
|
||||
ENetEvent event;
|
||||
while (connection.pollEvents(&event)) {
|
||||
recvPackets++;
|
||||
|
||||
switch (event.type) {
|
||||
default: break;
|
||||
case ENET_EVENT_TYPE_CONNECT: {
|
||||
std::cout << Log::info << "Connected to server "
|
||||
<< NetHandler::intToIPString(event.peer->address.host)
|
||||
<< ":" << event.peer->address.port << "." << Log::endl;
|
||||
break;
|
||||
}
|
||||
case ENET_EVENT_TYPE_RECEIVE: {
|
||||
std::unique_ptr<PacketView> p = std::make_unique<PacketView>(event.packet);
|
||||
receivedPacket(std::move(p));
|
||||
break;
|
||||
}
|
||||
case ENET_EVENT_TYPE_DISCONNECT: {
|
||||
std::cout << Log::info << "Disconnected from server "
|
||||
<< event.peer->address.host << ":" << event.peer->address.port << "." << Log::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto player = world.getPlayer();
|
||||
if (player)
|
||||
Serializer()
|
||||
.appendE(NetField::POS).append(player->getPos())
|
||||
.appendE(NetField::VEL).append(player->getVel())
|
||||
.appendE(NetField::LOOK_PITCH).append(player->getPitch())
|
||||
.appendE(NetField::LOOK_YAW).append(player->getYaw())
|
||||
.packet(Packet::Type::THIS_PLAYER_INFO, false).sendTo(connection.getPeer(), Packet::Channel::INTERACT);
|
||||
}
|
||||
|
||||
void ClientNetworkInterpreter::receivedPacket(std::unique_ptr<PacketView> p) {
|
||||
switch (p->type) {
|
||||
default:
|
||||
std::cout << Log::err << "Received unknown packet of type " << static_cast<int>(p->type)
|
||||
<< ". Is the server on a different protocol version?" << Log::endl; break;
|
||||
|
||||
case Packet::Type::SERVER_INFO:
|
||||
serverSideChunkGens = p->d.read<unsigned int>(); break;
|
||||
|
||||
case Packet::Type::THIS_PLAYER_INFO:
|
||||
world.getPlayer()->handleAssertion(p->d); break;
|
||||
|
||||
case Packet::Type::PLAYER_ENT_INFO:
|
||||
world.handlePlayerEntPacket(std::move(p)); break;
|
||||
|
||||
case Packet::Type::CHUNK:
|
||||
case Packet::Type::MAPBLOCK:
|
||||
world.handleWorldPacket(std::move(p)); break;
|
||||
|
||||
case Packet::Type::BLOCK_SET: {
|
||||
auto pos = p->d.read<glm::ivec3>();
|
||||
auto block = p->d.read<unsigned int>();
|
||||
world.getActiveDimension()->setBlock(pos, block);
|
||||
break; }
|
||||
|
||||
case Packet::Type::ENTITY_INFO:
|
||||
world.getActiveDimension().l()->serverEntitiesInfo(p->d); break;
|
||||
|
||||
case Packet::Type::ENTITY_REMOVED:
|
||||
world.getActiveDimension().l()->serverEntitiesRemoved(p->d); break;
|
||||
|
||||
case Packet::Type::INV_DATA:
|
||||
onInvPacket(std::move(p)); break;
|
||||
|
||||
case Packet::Type::INV_INVALID: {
|
||||
std::string source = p->d.read<std::string>();
|
||||
std::string list = p->d.read<std::string>();
|
||||
throw std::runtime_error("Invalid inventory " + source + ":" + list + " was request by client."); }
|
||||
}
|
||||
switch (p->type) {
|
||||
default:
|
||||
std::cout << Log::err << "Received unknown packet of type " << static_cast<int>(p->type)
|
||||
<< ". Is the server on a different protocol version?" << Log::endl;
|
||||
break;
|
||||
|
||||
case Packet::Type::SERVER_INFO:serverSideChunkGens = p->d.read<unsigned int>();
|
||||
break;
|
||||
|
||||
case Packet::Type::THIS_PLAYER_INFO:world.getPlayer()->handleAssertion(p->d);
|
||||
break;
|
||||
|
||||
case Packet::Type::PLAYER_ENT_INFO:world.handlePlayerEntPacket(std::move(p));
|
||||
break;
|
||||
|
||||
case Packet::Type::CHUNK:
|
||||
case Packet::Type::MAPBLOCK:world.handleWorldPacket(std::move(p));
|
||||
break;
|
||||
|
||||
case Packet::Type::BLOCK_SET: {
|
||||
auto pos = p->d.read<glm::ivec3>();
|
||||
auto block = p->d.read<unsigned int>();
|
||||
world.getActiveDimension()->setBlock(pos, block);
|
||||
break;
|
||||
}
|
||||
|
||||
case Packet::Type::ENTITY_INFO:world.getActiveDimension().l()->serverEntitiesInfo(p->d);
|
||||
break;
|
||||
|
||||
case Packet::Type::ENTITY_REMOVED:world.getActiveDimension().l()->serverEntitiesRemoved(p->d);
|
||||
break;
|
||||
|
||||
case Packet::Type::INV_DATA:onInvPacket(std::move(p));
|
||||
break;
|
||||
|
||||
case Packet::Type::INV_INVALID: {
|
||||
std::string source = p->d.read<std::string>();
|
||||
std::string list = p->d.read<std::string>();
|
||||
throw std::runtime_error("Invalid inventory " + source + ":" + list + " was request by client.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientNetworkInterpreter::blockHit(const Target &target) {
|
||||
Serializer().append<glm::ivec3>(target.pos).append(static_cast<unsigned short>(target.face))
|
||||
.packet(Packet::Type::BLOCK_HIT).sendTo(connection.getPeer(), Packet::Channel::INTERACT);
|
||||
void ClientNetworkInterpreter::blockHit(const Target& target) {
|
||||
Serializer().append<glm::ivec3>(target.pos).append(static_cast<unsigned short>(target.face))
|
||||
.packet(Packet::Type::BLOCK_HIT).sendTo(connection.getPeer(), Packet::Channel::INTERACT);
|
||||
}
|
||||
|
||||
void ClientNetworkInterpreter::blockPlace(const Target &target) {
|
||||
Serializer().append<glm::ivec3>(target.pos).append(static_cast<unsigned short>(target.face))
|
||||
.packet(Packet::Type::BLOCK_PLACE).sendTo(connection.getPeer(), Packet::Channel::INTERACT);
|
||||
void ClientNetworkInterpreter::blockPlace(const Target& target) {
|
||||
Serializer().append<glm::ivec3>(target.pos).append(static_cast<unsigned short>(target.face))
|
||||
.packet(Packet::Type::BLOCK_PLACE).sendTo(connection.getPeer(), Packet::Channel::INTERACT);
|
||||
}
|
||||
|
||||
void ClientNetworkInterpreter::blockInteract(const Target &target) {
|
||||
Serializer().append<glm::ivec3>(target.pos).append(static_cast<unsigned short>(target.face))
|
||||
.packet(Packet::Type::BLOCK_INTERACT).sendTo(connection.getPeer(), Packet::Channel::INTERACT);
|
||||
void ClientNetworkInterpreter::blockInteract(const Target& target) {
|
||||
Serializer().append<glm::ivec3>(target.pos).append(static_cast<unsigned short>(target.face))
|
||||
.packet(Packet::Type::BLOCK_INTERACT).sendTo(connection.getPeer(), Packet::Channel::INTERACT);
|
||||
}
|
||||
|
||||
void ClientNetworkInterpreter::blockPlaceOrInteract(const Target &target) {
|
||||
Serializer().append<glm::ivec3>(target.pos).append(static_cast<unsigned short>(target.face))
|
||||
.packet(Packet::Type::BLOCK_PLACE_OR_INTERACT).sendTo(connection.getPeer(), Packet::Channel::INTERACT);
|
||||
void ClientNetworkInterpreter::blockPlaceOrInteract(const Target& target) {
|
||||
Serializer().append<glm::ivec3>(target.pos).append(static_cast<unsigned short>(target.face))
|
||||
.packet(Packet::Type::BLOCK_PLACE_OR_INTERACT).sendTo(connection.getPeer(), Packet::Channel::INTERACT);
|
||||
}
|
||||
|
||||
void ClientNetworkInterpreter::invWatch(const std::string& inv, const std::string& list) {
|
||||
Serializer().append(inv).append(list).packet(Packet::Type::INV_WATCH)
|
||||
.sendTo(connection.getPeer(), Packet::Channel::INTERACT);
|
||||
Serializer().append(inv).append(list).packet(Packet::Type::INV_WATCH)
|
||||
.sendTo(connection.getPeer(), Packet::Channel::INTERACT);
|
||||
}
|
||||
|
||||
void ClientNetworkInterpreter::invUnwatch(const std::string& inv, const std::string& list) {
|
||||
Serializer().append(inv).append(list).packet(Packet::Type::INV_UNWATCH)
|
||||
.sendTo(connection.getPeer(), Packet::Channel::INTERACT);
|
||||
Serializer().append(inv).append(list).packet(Packet::Type::INV_UNWATCH)
|
||||
.sendTo(connection.getPeer(), Packet::Channel::INTERACT);
|
||||
}
|
||||
|
||||
void ClientNetworkInterpreter::invInteract(const std::string &inv, const std::string &list, bool primary, unsigned short ind) {
|
||||
Serializer().append<unsigned short>(primary).append(inv).append(list).append<unsigned short>(ind)
|
||||
.packet(Packet::Type::INV_INTERACT).sendTo(connection.getPeer(), Packet::Channel::INTERACT);
|
||||
void ClientNetworkInterpreter::invInteract(const std::string& inv, const std::string& list, bool primary,
|
||||
unsigned short ind) {
|
||||
Serializer().append<unsigned short>(primary).append(inv).append(list).append<unsigned short>(ind)
|
||||
.packet(Packet::Type::INV_INTERACT).sendTo(connection.getPeer(), Packet::Channel::INTERACT);
|
||||
}
|
||||
|
||||
void ClientNetworkInterpreter::sendPacket(const Packet &packet, Packet::Channel channel) {
|
||||
packet.sendTo(connection.getPeer(), channel);
|
||||
void ClientNetworkInterpreter::sendPacket(const Packet& packet, Packet::Channel channel) {
|
||||
packet.sendTo(connection.getPeer(), channel);
|
||||
}
|
||||
|
|
|
@ -13,40 +13,53 @@
|
|||
#include "client/conn/ServerConnection.h"
|
||||
|
||||
class Model;
|
||||
|
||||
class Target;
|
||||
|
||||
class LocalWorld;
|
||||
|
||||
class PacketView;
|
||||
|
||||
class LocalPlayer;
|
||||
|
||||
class LocalSubgame;
|
||||
|
||||
enum class NetPlayerField;
|
||||
|
||||
class ClientNetworkInterpreter {
|
||||
public:
|
||||
ClientNetworkInterpreter(const ClientNetworkInterpreter& other) = delete;
|
||||
ClientNetworkInterpreter(ServerConnection& connection, LocalWorld& world);
|
||||
|
||||
void init(std::function<void(std::unique_ptr<PacketView>)> invCallback);
|
||||
void update();
|
||||
|
||||
void blockHit(const Target& target);
|
||||
void blockPlace(const Target& target);
|
||||
void blockInteract(const Target& target);
|
||||
void blockPlaceOrInteract(const Target& target);
|
||||
|
||||
void invWatch(const std::string& inv, const std::string& list);
|
||||
void invUnwatch(const std::string& inv, const std::string& list);
|
||||
void invInteract(const std::string& inv, const std::string& list, bool primary, unsigned short ind);
|
||||
|
||||
void sendPacket(const Packet& packet, Packet::Channel channel);
|
||||
|
||||
int recvPackets = 0;
|
||||
int serverSideChunkGens = 0;
|
||||
private:
|
||||
void receivedPacket(std::unique_ptr<PacketView> ePacket);
|
||||
|
||||
LocalWorld& world;
|
||||
ServerConnection& connection;
|
||||
|
||||
std::function<void(std::unique_ptr<PacketView>)> onInvPacket;
|
||||
public:
|
||||
ClientNetworkInterpreter(const ClientNetworkInterpreter& other) = delete;
|
||||
|
||||
ClientNetworkInterpreter(ServerConnection& connection, LocalWorld& world);
|
||||
|
||||
void init(std::function<void(std::unique_ptr<PacketView>)> invCallback);
|
||||
|
||||
void update();
|
||||
|
||||
void blockHit(const Target& target);
|
||||
|
||||
void blockPlace(const Target& target);
|
||||
|
||||
void blockInteract(const Target& target);
|
||||
|
||||
void blockPlaceOrInteract(const Target& target);
|
||||
|
||||
void invWatch(const std::string& inv, const std::string& list);
|
||||
|
||||
void invUnwatch(const std::string& inv, const std::string& list);
|
||||
|
||||
void invInteract(const std::string& inv, const std::string& list, bool primary, unsigned short ind);
|
||||
|
||||
void sendPacket(const Packet& packet, Packet::Channel channel);
|
||||
|
||||
int recvPackets = 0;
|
||||
int serverSideChunkGens = 0;
|
||||
private:
|
||||
void receivedPacket(std::unique_ptr<PacketView> ePacket);
|
||||
|
||||
LocalWorld& world;
|
||||
ServerConnection& connection;
|
||||
|
||||
std::function<void(std::unique_ptr<PacketView>)> onInvPacket;
|
||||
};
|
||||
|
||||
|
|
|
@ -12,94 +12,94 @@
|
|||
#include "util/net/NetHandler.h"
|
||||
|
||||
void ServerConnection::attemptConnect(Address addr) {
|
||||
if (state != State::UNCONNECTED) {
|
||||
disconnect();
|
||||
}
|
||||
|
||||
if (enet_initialize() != 0) {
|
||||
std::cout << Log::err << "Failed to Initialize ENet." << Log::endl;
|
||||
state = State::ENET_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
host = enet_host_create(nullptr, 1, NetHandler::PACKET_CHANNELS, 0, 0);
|
||||
|
||||
if (host == nullptr) {
|
||||
std::cout << Log::err << "Failed to create ENet client." << Log::endl;
|
||||
state = State::ENET_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
ENetAddress eNetAddr;
|
||||
enet_address_set_host(&eNetAddr, addr.host.c_str());
|
||||
eNetAddr.port = addr.port;
|
||||
|
||||
peer = enet_host_connect(host, &eNetAddr, NetHandler::PACKET_CHANNELS, 0);
|
||||
|
||||
if (peer == nullptr) {
|
||||
std::cout << Log::err << "Failed to initialize ENet peer." << Log::endl;
|
||||
state = State::ENET_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
connectionTime = std::chrono::high_resolution_clock::now();
|
||||
state = State::ATTEMPTING_CONNECT;
|
||||
if (state != State::UNCONNECTED) {
|
||||
disconnect();
|
||||
}
|
||||
|
||||
if (enet_initialize() != 0) {
|
||||
std::cout << Log::err << "Failed to Initialize ENet." << Log::endl;
|
||||
state = State::ENET_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
host = enet_host_create(nullptr, 1, NetHandler::PACKET_CHANNELS, 0, 0);
|
||||
|
||||
if (host == nullptr) {
|
||||
std::cout << Log::err << "Failed to create ENet client." << Log::endl;
|
||||
state = State::ENET_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
ENetAddress eNetAddr;
|
||||
enet_address_set_host(&eNetAddr, addr.host.c_str());
|
||||
eNetAddr.port = addr.port;
|
||||
|
||||
peer = enet_host_connect(host, &eNetAddr, NetHandler::PACKET_CHANNELS, 0);
|
||||
|
||||
if (peer == nullptr) {
|
||||
std::cout << Log::err << "Failed to initialize ENet peer." << Log::endl;
|
||||
state = State::ENET_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
connectionTime = std::chrono::high_resolution_clock::now();
|
||||
state = State::ATTEMPTING_CONNECT;
|
||||
}
|
||||
|
||||
void ServerConnection::processConnecting() {
|
||||
if (state == State::ATTEMPTING_CONNECT) {
|
||||
ENetEvent event;
|
||||
|
||||
auto time = std::chrono::high_resolution_clock::now();
|
||||
long elapsedMs = std::chrono::duration_cast<std::chrono::milliseconds>(time - connectionTime).count();
|
||||
|
||||
if (elapsedMs < timeout) {
|
||||
if (enet_host_service(host, &event, 0) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) {
|
||||
std::cout << Log::info << "Connected to "
|
||||
<< NetHandler::intToIPString(event.peer->address.host)
|
||||
<< ":" << event.peer->address.port << "." << Log::endl;
|
||||
|
||||
state = State::CONNECTED;
|
||||
}
|
||||
}
|
||||
else {
|
||||
enet_peer_reset(peer);
|
||||
if (attempt < attempts) {
|
||||
std::cout << Log::info << "Failed to connect to server, retrying." << Log::endl;
|
||||
connectionTime = std::chrono::high_resolution_clock::now();
|
||||
attempt ++;
|
||||
}
|
||||
else {
|
||||
std::cout << Log::err << "Failed to connect to server." << Log::endl;
|
||||
state = State::FAILED_CONNECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (state == State::ATTEMPTING_CONNECT) {
|
||||
ENetEvent event;
|
||||
|
||||
auto time = std::chrono::high_resolution_clock::now();
|
||||
long elapsedMs = std::chrono::duration_cast<std::chrono::milliseconds>(time - connectionTime).count();
|
||||
|
||||
if (elapsedMs < timeout) {
|
||||
if (enet_host_service(host, &event, 0) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) {
|
||||
std::cout << Log::info << "Connected to "
|
||||
<< NetHandler::intToIPString(event.peer->address.host)
|
||||
<< ":" << event.peer->address.port << "." << Log::endl;
|
||||
|
||||
state = State::CONNECTED;
|
||||
}
|
||||
}
|
||||
else {
|
||||
enet_peer_reset(peer);
|
||||
if (attempt < attempts) {
|
||||
std::cout << Log::info << "Failed to connect to server, retrying." << Log::endl;
|
||||
connectionTime = std::chrono::high_resolution_clock::now();
|
||||
attempt++;
|
||||
}
|
||||
else {
|
||||
std::cout << Log::err << "Failed to connect to server." << Log::endl;
|
||||
state = State::FAILED_CONNECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ServerConnection::State ServerConnection::getConnectionStatus() {
|
||||
return state;
|
||||
return state;
|
||||
}
|
||||
|
||||
void ServerConnection::disconnect() {
|
||||
if (state == State::CONNECTED) {
|
||||
std::cout << Log::info << "Disconnecting from server." << Log::endl;
|
||||
enet_peer_disconnect(peer, 0);
|
||||
enet_host_flush(host);
|
||||
state = State::DISCONNECTED;
|
||||
}
|
||||
if (state == State::CONNECTED) {
|
||||
std::cout << Log::info << "Disconnecting from server." << Log::endl;
|
||||
enet_peer_disconnect(peer, 0);
|
||||
enet_host_flush(host);
|
||||
state = State::DISCONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
bool ServerConnection::pollEvents(ENetEvent *event) {
|
||||
return enet_host_service(host, event, 0) > 0;
|
||||
bool ServerConnection::pollEvents(ENetEvent* event) {
|
||||
return enet_host_service(host, event, 0) > 0;
|
||||
}
|
||||
|
||||
ENetPeer *ServerConnection::getPeer() {
|
||||
return peer;
|
||||
ENetPeer* ServerConnection::getPeer() {
|
||||
return peer;
|
||||
}
|
||||
|
||||
ServerConnection::~ServerConnection() {
|
||||
disconnect();
|
||||
delete host;
|
||||
delete peer;
|
||||
disconnect();
|
||||
delete host;
|
||||
delete peer;
|
||||
}
|
||||
|
|
|
@ -10,38 +10,41 @@
|
|||
class Address;
|
||||
|
||||
class ServerConnection {
|
||||
public:
|
||||
enum class State {
|
||||
UNCONNECTED,
|
||||
ATTEMPTING_CONNECT,
|
||||
CONNECTED,
|
||||
FAILED_CONNECT,
|
||||
DISCONNECTED,
|
||||
ENET_ERROR
|
||||
};
|
||||
|
||||
ServerConnection() = default;
|
||||
|
||||
void attemptConnect(Address addr);
|
||||
State getConnectionStatus();
|
||||
void disconnect();
|
||||
|
||||
void processConnecting();
|
||||
bool pollEvents(ENetEvent* event);
|
||||
|
||||
ENetPeer* getPeer();
|
||||
|
||||
~ServerConnection();
|
||||
|
||||
private:
|
||||
unsigned long timeout = 1000;
|
||||
unsigned int attempts = 10;
|
||||
|
||||
ENetHost* host = nullptr;
|
||||
ENetPeer* peer = nullptr;
|
||||
|
||||
State state = State::UNCONNECTED;
|
||||
unsigned int attempt = 0;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> connectionTime;
|
||||
public:
|
||||
enum class State {
|
||||
UNCONNECTED,
|
||||
ATTEMPTING_CONNECT,
|
||||
CONNECTED,
|
||||
FAILED_CONNECT,
|
||||
DISCONNECTED,
|
||||
ENET_ERROR
|
||||
};
|
||||
|
||||
ServerConnection() = default;
|
||||
|
||||
void attemptConnect(Address addr);
|
||||
|
||||
State getConnectionStatus();
|
||||
|
||||
void disconnect();
|
||||
|
||||
void processConnecting();
|
||||
|
||||
bool pollEvents(ENetEvent* event);
|
||||
|
||||
ENetPeer* getPeer();
|
||||
|
||||
~ServerConnection();
|
||||
|
||||
private:
|
||||
unsigned long timeout = 1000;
|
||||
unsigned int attempts = 10;
|
||||
|
||||
ENetHost* host = nullptr;
|
||||
ENetPeer* peer = nullptr;
|
||||
|
||||
State state = State::UNCONNECTED;
|
||||
unsigned int attempt = 0;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> connectionTime;
|
||||
};
|
||||
|
||||
|
|
|
@ -9,65 +9,65 @@
|
|||
#include "game/def/BlockDef.h"
|
||||
#include "game/atlas/asset/AtlasRef.h"
|
||||
|
||||
ParticleEntity::ParticleEntity(SubgamePtr game, DimensionPtr dim, glm::vec3 pos, BlockDef &block) :
|
||||
DrawableEntity(game, dim, std::make_shared<Model>()), Entity(game, dim) {
|
||||
setPos(pos + glm::vec3(.5,.3,.5));
|
||||
|
||||
std::set<std::shared_ptr<AtlasRef>>& textureRefs = block.model.textureRefs;
|
||||
auto it = textureRefs.cbegin();
|
||||
advance(it, rand() % textureRefs.size());
|
||||
|
||||
auto uv = (*it)->uv;
|
||||
|
||||
auto spanX = uv.z - uv.x;
|
||||
auto spanY = uv.w - uv.y;
|
||||
|
||||
float offX = spanX / 16 * (rand() % 12);
|
||||
float offY = spanX / 16 * (rand() % 12);
|
||||
|
||||
uv -= glm::vec4(0, 0, spanX * 0.75, spanY * 0.75);
|
||||
uv += glm::vec4(offX, offY, offX, offY);
|
||||
|
||||
std::vector<EntityVertex> vertices {
|
||||
{{-0.05, -0.05, 0}, {uv.x, uv.w, 0, 1}, {1, 1, 1}, true, {0, 0, 1}, {}, {}},
|
||||
{{-0.05, 0.05, 0}, {uv.x, uv.y, 0, 1}, {1, 1, 1}, true, {0, 0, 1}, {}, {}},
|
||||
{{ 0.05, 0.05, 0}, {uv.z, uv.y, 0, 1}, {1, 1, 1}, true, {0, 0, 1}, {}, {}},
|
||||
{{ 0.05, -0.05, 0}, {uv.z, uv.w, 0, 1}, {1, 1, 1}, true, {0, 0, 1}, {}, {}},
|
||||
};
|
||||
std::vector<unsigned int> indices {
|
||||
0, 1, 2, 2, 3, 0,
|
||||
0, 2, 1, 2, 0, 3,
|
||||
};
|
||||
|
||||
auto dir = glm::radians(static_cast<float>(rand() % 360));
|
||||
float xDir = sinf(dir);
|
||||
float zDir = cosf(dir);
|
||||
|
||||
float horiScale = 0.5f + (rand() % 100 / 100.f);
|
||||
|
||||
velocity.y = 6.f;
|
||||
velocity.x = xDir * 2.f * horiScale;
|
||||
velocity.z = zDir * 2.f * horiScale;
|
||||
|
||||
setPos(getPos() + glm::vec3(xDir, 0, zDir) / 4.f);
|
||||
|
||||
std::unique_ptr<EntityMesh> mesh = std::make_unique<EntityMesh>();
|
||||
mesh->create(vertices, indices);
|
||||
this->model->fromMesh(std::move(mesh));
|
||||
this->setScale(0.75f + (rand() % 10 / 20.f));
|
||||
ParticleEntity::ParticleEntity(SubgamePtr game, DimensionPtr dim, glm::vec3 pos, BlockDef& block) :
|
||||
DrawableEntity(game, dim, std::make_shared<Model>()), Entity(game, dim) {
|
||||
setPos(pos + glm::vec3(.5, .3, .5));
|
||||
|
||||
std::set<std::shared_ptr<AtlasRef>>& textureRefs = block.model.textureRefs;
|
||||
auto it = textureRefs.cbegin();
|
||||
advance(it, rand() % textureRefs.size());
|
||||
|
||||
auto uv = (*it)->uv;
|
||||
|
||||
auto spanX = uv.z - uv.x;
|
||||
auto spanY = uv.w - uv.y;
|
||||
|
||||
float offX = spanX / 16 * (rand() % 12);
|
||||
float offY = spanX / 16 * (rand() % 12);
|
||||
|
||||
uv -= glm::vec4(0, 0, spanX * 0.75, spanY * 0.75);
|
||||
uv += glm::vec4(offX, offY, offX, offY);
|
||||
|
||||
std::vector<EntityVertex> vertices{
|
||||
{{ -0.05, -0.05, 0 }, { uv.x, uv.w, 0, 1 }, { 1, 1, 1 }, true, { 0, 0, 1 }, {}, {}},
|
||||
{{ -0.05, 0.05, 0 }, { uv.x, uv.y, 0, 1 }, { 1, 1, 1 }, true, { 0, 0, 1 }, {}, {}},
|
||||
{{ 0.05, 0.05, 0 }, { uv.z, uv.y, 0, 1 }, { 1, 1, 1 }, true, { 0, 0, 1 }, {}, {}},
|
||||
{{ 0.05, -0.05, 0 }, { uv.z, uv.w, 0, 1 }, { 1, 1, 1 }, true, { 0, 0, 1 }, {}, {}},
|
||||
};
|
||||
std::vector<unsigned int> indices{
|
||||
0, 1, 2, 2, 3, 0,
|
||||
0, 2, 1, 2, 0, 3,
|
||||
};
|
||||
|
||||
auto dir = glm::radians(static_cast<float>(rand() % 360));
|
||||
float xDir = sinf(dir);
|
||||
float zDir = cosf(dir);
|
||||
|
||||
float horiScale = 0.5f + (rand() % 100 / 100.f);
|
||||
|
||||
velocity.y = 6.f;
|
||||
velocity.x = xDir * 2.f * horiScale;
|
||||
velocity.z = zDir * 2.f * horiScale;
|
||||
|
||||
setPos(getPos() + glm::vec3(xDir, 0, zDir) / 4.f);
|
||||
|
||||
std::unique_ptr<EntityMesh> mesh = std::make_unique<EntityMesh>();
|
||||
mesh->create(vertices, indices);
|
||||
this->model->fromMesh(std::move(mesh));
|
||||
this->setScale(0.75f + (rand() % 10 / 20.f));
|
||||
}
|
||||
|
||||
void ParticleEntity::update(double delta, glm::vec3 player) {
|
||||
time += delta;
|
||||
|
||||
setPos(getPos() + velocity * glm::vec3(static_cast<float>(delta)));
|
||||
|
||||
double angle = -glm::degrees(std::atan2(player.z - pos.z, player.x - pos.x)) + 90.f;
|
||||
setRotateY(static_cast<float>(angle));
|
||||
|
||||
velocity.y -= 32.f * delta;
|
||||
time += delta;
|
||||
|
||||
setPos(getPos() + velocity * glm::vec3(static_cast<float>(delta)));
|
||||
|
||||
double angle = -glm::degrees(std::atan2(player.z - pos.z, player.x - pos.x)) + 90.f;
|
||||
setRotateY(static_cast<float>(angle));
|
||||
|
||||
velocity.y -= 32.f * delta;
|
||||
}
|
||||
|
||||
void ParticleEntity::draw(Renderer &renderer) {
|
||||
DrawableEntity::draw(renderer);
|
||||
void ParticleEntity::draw(Renderer& renderer) {
|
||||
DrawableEntity::draw(renderer);
|
||||
}
|
|
@ -9,14 +9,15 @@
|
|||
class BlockDef;
|
||||
|
||||
class ParticleEntity : public DrawableEntity {
|
||||
public:
|
||||
ParticleEntity(SubgamePtr game, DimensionPtr dim, glm::vec3 pos, BlockDef& block);
|
||||
|
||||
void update(double delta, glm::vec3 player);
|
||||
void draw(Renderer& renderer) override;
|
||||
|
||||
float time = 0;
|
||||
private:
|
||||
glm::vec3 velocity {};
|
||||
public:
|
||||
ParticleEntity(SubgamePtr game, DimensionPtr dim, glm::vec3 pos, BlockDef& block);
|
||||
|
||||
void update(double delta, glm::vec3 player);
|
||||
|
||||
void draw(Renderer& renderer) override;
|
||||
|
||||
float time = 0;
|
||||
private:
|
||||
glm::vec3 velocity{};
|
||||
};
|
||||
|
||||
|
|
|
@ -7,16 +7,17 @@
|
|||
#include "world/dim/ent/DrawableEntity.h"
|
||||
|
||||
class PlayerEntity : public DrawableEntity {
|
||||
public:
|
||||
PlayerEntity(SubgamePtr game, DimensionPtr dim, glm::vec3 pos, unsigned int id, const std::shared_ptr<Model>& model) :
|
||||
DrawableEntity(game, dim, model), Entity(game, dim), id(id) {
|
||||
setPos(pos);
|
||||
}
|
||||
|
||||
unsigned int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int id;
|
||||
public:
|
||||
PlayerEntity(SubgamePtr game, DimensionPtr dim, glm::vec3 pos, unsigned int id, const std::shared_ptr<Model>& model)
|
||||
:
|
||||
DrawableEntity(game, dim, model), Entity(game, dim), id(id) {
|
||||
setPos(pos);
|
||||
}
|
||||
|
||||
unsigned int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int id;
|
||||
};
|
|
@ -7,71 +7,83 @@
|
|||
#include "world/dim/ent/DrawableEntity.h"
|
||||
|
||||
void WireframeEntity::updateMesh(const std::vector<SelectionBox>& boxes, float width) {
|
||||
this->width = width;
|
||||
buildMesh(boxes);
|
||||
this->width = width;
|
||||
buildMesh(boxes);
|
||||
}
|
||||
|
||||
|
||||
void WireframeEntity::buildMesh(const std::vector<SelectionBox>& boxes) {
|
||||
indOffset = 0;
|
||||
|
||||
vertices.clear();
|
||||
indices.clear();
|
||||
|
||||
for (auto& box : boxes) {
|
||||
glm::vec3 a = box.a;
|
||||
glm::vec3 b = box.b - box.a;
|
||||
|
||||
createBox(a, b, 0, 0, 0, 0, b.y, 0);
|
||||
createBox(a, b, b.x, 0, 0, 0, b.y, 0);
|
||||
createBox(a, b, b.x, 0, b.z, 0, b.y, 0);
|
||||
createBox(a, b, 0, 0, b.z, 0, b.y, 0);
|
||||
|
||||
createBox(a, b, 0, 0, 0, b.x, 0, 0);
|
||||
createBox(a, b, 0, b.y, 0, b.x, 0, 0);
|
||||
createBox(a, b, 0, b.y, b.z, b.x, 0, 0);
|
||||
createBox(a, b, 0, 0, b.z, b.x, 0, 0);
|
||||
|
||||
createBox(a, b, 0, 0, 0, 0, 0, b.z);
|
||||
createBox(a, b, 0, b.y, 0, 0, 0, b.z);
|
||||
createBox(a, b, b.x, b.y, 0, 0, 0, b.z);
|
||||
createBox(a, b, b.x, 0, 0, 0, 0, b.z);
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<EntityMesh> mesh = std::make_unique<EntityMesh>();
|
||||
mesh->create(vertices, indices);
|
||||
this->model->fromMesh(std::move(mesh));
|
||||
indOffset = 0;
|
||||
|
||||
vertices.clear();
|
||||
indices.clear();
|
||||
|
||||
for (auto& box : boxes) {
|
||||
glm::vec3 a = box.a;
|
||||
glm::vec3 b = box.b - box.a;
|
||||
|
||||
createBox(a, b, 0, 0, 0, 0, b.y, 0);
|
||||
createBox(a, b, b.x, 0, 0, 0, b.y, 0);
|
||||
createBox(a, b, b.x, 0, b.z, 0, b.y, 0);
|
||||
createBox(a, b, 0, 0, b.z, 0, b.y, 0);
|
||||
|
||||
createBox(a, b, 0, 0, 0, b.x, 0, 0);
|
||||
createBox(a, b, 0, b.y, 0, b.x, 0, 0);
|
||||
createBox(a, b, 0, b.y, b.z, b.x, 0, 0);
|
||||
createBox(a, b, 0, 0, b.z, b.x, 0, 0);
|
||||
|
||||
createBox(a, b, 0, 0, 0, 0, 0, b.z);
|
||||
createBox(a, b, 0, b.y, 0, 0, 0, b.z);
|
||||
createBox(a, b, b.x, b.y, 0, 0, 0, b.z);
|
||||
createBox(a, b, b.x, 0, 0, 0, 0, b.z);
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<EntityMesh> mesh = std::make_unique<EntityMesh>();
|
||||
mesh->create(vertices, indices);
|
||||
this->model->fromMesh(std::move(mesh));
|
||||
}
|
||||
|
||||
void WireframeEntity::createBox(glm::vec3 a, glm::vec3 b, float x, float y, float z, float xSize, float ySize, float zSize) {
|
||||
float hw = (width/2.0f);
|
||||
float w = width;
|
||||
glm::vec3 c = color;
|
||||
|
||||
std::vector<EntityVertex> myVerts {
|
||||
/*0*/ {{x - hw + a.x, y - hw + a.y, z - hw + a.z }, {c.x, c.y, c.z, 1}, {1, 1, 1}, false, {0, 1, 0}, {}, {}},
|
||||
/*1*/ {{x - hw + a.x + xSize + w, y - hw + a.y, z - hw + a.z }, {c.x, c.y, c.z, 1}, {1, 1, 1}, false, {0, 1, 0}, {}, {}},
|
||||
/*2*/ {{x - hw + a.x + xSize + w, y - hw + a.y, z - hw + a.z + zSize + w}, {c.x, c.y, c.z, 1}, {1, 1, 1}, false, {0, 1, 0}, {}, {}},
|
||||
/*3*/ {{x - hw + a.x, y - hw + a.y, z - hw + a.z + zSize + w}, {c.x, c.y, c.z, 1}, {1, 1, 1}, false, {0, 1, 0}, {}, {}},
|
||||
|
||||
/*4*/ {{x - hw + a.x, y - hw + a.y + ySize + w, z - hw + a.z }, {c.x, c.y, c.z, 1}, {1, 1, 1}, false, {0, 1, 0}, {}, {}},
|
||||
/*5*/ {{x - hw + a.x + xSize + w, y - hw + a.y + ySize + w, z - hw + a.z }, {c.x, c.y, c.z, 1}, {1, 1, 1}, false, {0, 1, 0}, {}, {}},
|
||||
/*6*/ {{x - hw + a.x + xSize + w, y - hw + a.y + ySize + w, z - hw + a.z + zSize + w}, {c.x, c.y, c.z, 1}, {1, 1, 1}, false, {0, 1, 0}, {}, {}},
|
||||
/*7*/ {{x - hw + a.x, y - hw + a.y + ySize + w, z - hw + a.z + zSize + w}, {c.x, c.y, c.z, 1}, {1, 1, 1}, false, {0, 1, 0}, {}, {}},
|
||||
};
|
||||
|
||||
std::vector<unsigned int> myInds {
|
||||
0, 1, 2, 2, 3, 0,
|
||||
4, 7, 6, 6, 5, 4,
|
||||
0, 4, 5, 5, 1, 0,
|
||||
3, 2, 6, 6, 7, 3,
|
||||
0, 3, 7, 7, 4, 0,
|
||||
1, 5, 6, 6, 2, 1,
|
||||
};
|
||||
|
||||
vertices.insert(vertices.end(), myVerts.begin(), myVerts.end());
|
||||
for (auto i : myInds) indices.push_back(i + indOffset);
|
||||
|
||||
indOffset += 8;
|
||||
void
|
||||
WireframeEntity::createBox(glm::vec3 a, glm::vec3 b, float x, float y, float z, float xSize, float ySize, float zSize) {
|
||||
float hw = (width / 2.0f);
|
||||
float w = width;
|
||||
glm::vec3 c = color;
|
||||
|
||||
std::vector<EntityVertex> myVerts{
|
||||
/*0*/
|
||||
{{ x - hw + a.x, y - hw + a.y, z - hw + a.z }, { c.x, c.y, c.z, 1 }, { 1, 1, 1 }, false, { 0, 1, 0 }, {}, {}},
|
||||
/*1*/{{ x - hw + a.x + xSize + w, y - hw + a.y, z - hw + a.z }, { c.x, c.y, c.z, 1 }, { 1, 1, 1 }, false,
|
||||
{ 0, 1, 0 }, {}, {}},
|
||||
/*2*/
|
||||
{{ x - hw + a.x + xSize + w, y - hw + a.y, z - hw + a.z + zSize + w }, { c.x, c.y, c.z, 1 }, { 1, 1, 1 }, false,
|
||||
{ 0, 1, 0 }, {}, {}},
|
||||
/*3*/{{ x - hw + a.x, y - hw + a.y, z - hw + a.z + zSize + w }, { c.x, c.y, c.z, 1 }, { 1, 1, 1 }, false,
|
||||
{ 0, 1, 0 }, {}, {}},
|
||||
|
||||
/*4*/{{ x - hw + a.x, y - hw + a.y + ySize + w, z - hw + a.z }, { c.x, c.y, c.z, 1 }, { 1, 1, 1 }, false,
|
||||
{ 0, 1, 0 }, {}, {}},
|
||||
/*5*/
|
||||
{{ x - hw + a.x + xSize + w, y - hw + a.y + ySize + w, z - hw + a.z }, { c.x, c.y, c.z, 1 }, { 1, 1, 1 }, false,
|
||||
{ 0, 1, 0 }, {}, {}},
|
||||
/*6*/{{ x - hw + a.x + xSize + w, y - hw + a.y + ySize + w, z - hw + a.z + zSize + w }, { c.x, c.y, c.z, 1 },
|
||||
{ 1, 1, 1 }, false, { 0, 1, 0 }, {}, {}},
|
||||
/*7*/
|
||||
{{ x - hw + a.x, y - hw + a.y + ySize + w, z - hw + a.z + zSize + w }, { c.x, c.y, c.z, 1 }, { 1, 1, 1 }, false,
|
||||
{ 0, 1, 0 }, {}, {}},
|
||||
};
|
||||
|
||||
std::vector<unsigned int> myInds{
|
||||
0, 1, 2, 2, 3, 0,
|
||||
4, 7, 6, 6, 5, 4,
|
||||
0, 4, 5, 5, 1, 0,
|
||||
3, 2, 6, 6, 7, 3,
|
||||
0, 3, 7, 7, 4, 0,
|
||||
1, 5, 6, 6, 2, 1,
|
||||
};
|
||||
|
||||
vertices.insert(vertices.end(), myVerts.begin(), myVerts.end());
|
||||
for (auto i : myInds) indices.push_back(i + indOffset);
|
||||
|
||||
indOffset += 8;
|
||||
}
|
|
@ -10,21 +10,23 @@
|
|||
#include "client/graph/mesh/EntityVertex.h"
|
||||
|
||||
class WireframeEntity : public DrawableEntity {
|
||||
public:
|
||||
WireframeEntity(SubgamePtr game, DimensionPtr dim, glm::vec3 color) :
|
||||
DrawableEntity(game, dim, std::make_shared<Model>()), Entity(game, dim),
|
||||
color(color) {};
|
||||
|
||||
void updateMesh(const std::vector<SelectionBox>& boxes, float width);
|
||||
private:
|
||||
std::vector<EntityVertex> vertices {};
|
||||
std::vector<unsigned int> indices {};
|
||||
|
||||
void buildMesh(const std::vector<SelectionBox>& boxes);
|
||||
void createBox(glm::vec3 a, glm::vec3 b, float x, float y, float z, float xSize, float ySize, float zSize);
|
||||
|
||||
glm::vec3 color {};
|
||||
|
||||
float width = 0.5;
|
||||
int indOffset = 0;
|
||||
public:
|
||||
WireframeEntity(SubgamePtr game, DimensionPtr dim, glm::vec3 color) :
|
||||
DrawableEntity(game, dim, std::make_shared<Model>()), Entity(game, dim),
|
||||
color(color) {};
|
||||
|
||||
void updateMesh(const std::vector<SelectionBox>& boxes, float width);
|
||||
|
||||
private:
|
||||
std::vector<EntityVertex> vertices{};
|
||||
std::vector<unsigned int> indices{};
|
||||
|
||||
void buildMesh(const std::vector<SelectionBox>& boxes);
|
||||
|
||||
void createBox(glm::vec3 a, glm::vec3 b, float x, float y, float z, float xSize, float ySize, float zSize);
|
||||
|
||||
glm::vec3 color{};
|
||||
|
||||
float width = 0.5;
|
||||
int indOffset = 0;
|
||||
};
|
||||
|
|
|
@ -9,91 +9,91 @@
|
|||
Camera::Camera() = default;
|
||||
|
||||
void Camera::create(float buffWidth, float buffHeight, glm::vec3 up) {
|
||||
this->bufferDimensions = glm::vec2(buffWidth, buffHeight);
|
||||
|
||||
this->position = glm::vec3(0, 0, 0);
|
||||
|
||||
this->worldUp = up;
|
||||
this->yaw = 0;
|
||||
this->pitch = 0;
|
||||
this->front = glm::vec3(0.0f, 0.0f, -1.0f);
|
||||
|
||||
createMatrices();
|
||||
this->bufferDimensions = glm::vec2(buffWidth, buffHeight);
|
||||
|
||||
this->position = glm::vec3(0, 0, 0);
|
||||
|
||||
this->worldUp = up;
|
||||
this->yaw = 0;
|
||||
this->pitch = 0;
|
||||
this->front = glm::vec3(0.0f, 0.0f, -1.0f);
|
||||
|
||||
createMatrices();
|
||||
}
|
||||
|
||||
void Camera::createMatrices() {
|
||||
ratio = bufferDimensions.x / bufferDimensions.y;
|
||||
|
||||
projectionMatrix = glm::perspective(glm::radians(fov), ratio, nearClip, farClip);
|
||||
frustum.setCamInternals(glm::radians(fov) / 1.2f, ratio, nearClip, farClip);
|
||||
|
||||
orthographicMatrix = glm::ortho(0.0f, bufferDimensions.x, bufferDimensions.y, 0.0f, -1000.0f, 1000.0f);
|
||||
ratio = bufferDimensions.x / bufferDimensions.y;
|
||||
|
||||
projectionMatrix = glm::perspective(glm::radians(fov), ratio, nearClip, farClip);
|
||||
frustum.setCamInternals(glm::radians(fov) / 1.2f, ratio, nearClip, farClip);
|
||||
|
||||
orthographicMatrix = glm::ortho(0.0f, bufferDimensions.x, bufferDimensions.y, 0.0f, -1000.0f, 1000.0f);
|
||||
}
|
||||
|
||||
void Camera::changeWindowDimensions(glm::vec2 size) {
|
||||
this->bufferDimensions = size;
|
||||
createMatrices();
|
||||
this->bufferDimensions = size;
|
||||
createMatrices();
|
||||
}
|
||||
|
||||
glm::mat4 Camera::getProjectionMatrix() {
|
||||
return projectionMatrix;
|
||||
return projectionMatrix;
|
||||
}
|
||||
|
||||
glm::mat4 Camera::getOrthographicMatrix() {
|
||||
return orthographicMatrix;
|
||||
return orthographicMatrix;
|
||||
}
|
||||
|
||||
glm::mat4 Camera::getViewMatrix() {
|
||||
update();
|
||||
return glm::lookAt(position, position + front, up);
|
||||
update();
|
||||
return glm::lookAt(position, position + front, up);
|
||||
}
|
||||
|
||||
void Camera::setPos(glm::vec3 pos) {
|
||||
position = pos;
|
||||
position = pos;
|
||||
}
|
||||
|
||||
glm::vec3 Camera::getPos() {
|
||||
return position;
|
||||
return position;
|
||||
}
|
||||
|
||||
void Camera::setYaw(double yaw) {
|
||||
this->yaw = yaw;
|
||||
this->yaw = yaw;
|
||||
}
|
||||
|
||||
void Camera::setPitch(double pitch) {
|
||||
this->pitch = pitch;
|
||||
this->pitch = pitch;
|
||||
}
|
||||
|
||||
void Camera::update() {
|
||||
front.x = (float)(cos(glm::radians(yaw)) * cos(glm::radians(pitch)));
|
||||
front.y = (float)(sin(glm::radians(pitch)));
|
||||
front.z = (float)(sin(glm::radians(yaw)) * cos(glm::radians(pitch)));
|
||||
front = glm::normalize(front);
|
||||
|
||||
right = glm::normalize(glm::cross(front, worldUp));
|
||||
up = glm::normalize(glm::cross(right, front));
|
||||
|
||||
frustum.update(position, front, up, right);
|
||||
front.x = (float) (cos(glm::radians(yaw)) * cos(glm::radians(pitch)));
|
||||
front.y = (float) (sin(glm::radians(pitch)));
|
||||
front.z = (float) (sin(glm::radians(yaw)) * cos(glm::radians(pitch)));
|
||||
front = glm::normalize(front);
|
||||
|
||||
right = glm::normalize(glm::cross(front, worldUp));
|
||||
up = glm::normalize(glm::cross(right, front));
|
||||
|
||||
frustum.update(position, front, up, right);
|
||||
}
|
||||
|
||||
glm::vec3 Camera::getFront() {
|
||||
return front;
|
||||
return front;
|
||||
}
|
||||
|
||||
glm::vec3 Camera::getRight() {
|
||||
return right;
|
||||
return right;
|
||||
}
|
||||
|
||||
glm::vec2 Camera::getBufferDimensions() {
|
||||
return bufferDimensions;
|
||||
return bufferDimensions;
|
||||
}
|
||||
|
||||
bool Camera::inFrustum(glm::vec3 &p) {
|
||||
return frustum.pointInFrustum(p) == Frustum::INSIDE;
|
||||
bool Camera::inFrustum(glm::vec3& p) {
|
||||
return frustum.pointInFrustum(p) == Frustum::INSIDE;
|
||||
}
|
||||
|
||||
int Camera::inFrustum(FrustumAABB &b) {
|
||||
return frustum.boxInFrustum(b);
|
||||
int Camera::inFrustum(FrustumAABB& b) {
|
||||
return frustum.boxInFrustum(b);
|
||||
}
|
||||
|
||||
Camera::~Camera() = default;
|
||||
|
|
|
@ -11,61 +11,69 @@
|
|||
#include "util/frustum/Frustum.h"
|
||||
|
||||
class Camera {
|
||||
public:
|
||||
Camera();
|
||||
void create(float buffWidth, float buffHeight, glm::vec3 up);
|
||||
|
||||
void changeWindowDimensions(glm::vec2 size);
|
||||
|
||||
glm::vec3 getPos();
|
||||
void setPos(glm::vec3 pos);
|
||||
|
||||
void setYaw(double yaw);
|
||||
void setPitch(double pitch);
|
||||
|
||||
glm::mat4 getProjectionMatrix();
|
||||
glm::mat4 getOrthographicMatrix();
|
||||
|
||||
glm::mat4 getViewMatrix();
|
||||
|
||||
glm::vec3 getFront();
|
||||
glm::vec3 getRight();
|
||||
|
||||
glm::vec2 getBufferDimensions();
|
||||
|
||||
bool inFrustum(glm::vec3 &p);
|
||||
int inFrustum(FrustumAABB &b);
|
||||
|
||||
~Camera();
|
||||
private:
|
||||
//Window Size
|
||||
glm::vec2 bufferDimensions;
|
||||
|
||||
//Matrices
|
||||
glm::mat4 projectionMatrix;
|
||||
glm::mat4 orthographicMatrix;
|
||||
|
||||
//Perspective Matrix Properties
|
||||
float fov = 80.0f;
|
||||
float ratio;
|
||||
float nearClip = 0.1f;
|
||||
float farClip = 1000.0f;
|
||||
|
||||
//View Frustum
|
||||
Frustum frustum;
|
||||
|
||||
//Movement translation variables
|
||||
glm::vec3 front;
|
||||
glm::vec3 up;
|
||||
glm::vec3 right;
|
||||
glm::vec3 worldUp;
|
||||
|
||||
//Angle and Position
|
||||
glm::vec3 position;
|
||||
double yaw;
|
||||
double pitch;
|
||||
|
||||
void createMatrices();
|
||||
void update();
|
||||
public:
|
||||
Camera();
|
||||
|
||||
void create(float buffWidth, float buffHeight, glm::vec3 up);
|
||||
|
||||
void changeWindowDimensions(glm::vec2 size);
|
||||
|
||||
glm::vec3 getPos();
|
||||
|
||||
void setPos(glm::vec3 pos);
|
||||
|
||||
void setYaw(double yaw);
|
||||
|
||||
void setPitch(double pitch);
|
||||
|
||||
glm::mat4 getProjectionMatrix();
|
||||
|
||||
glm::mat4 getOrthographicMatrix();
|
||||
|
||||
glm::mat4 getViewMatrix();
|
||||
|
||||
glm::vec3 getFront();
|
||||
|
||||
glm::vec3 getRight();
|
||||
|
||||
glm::vec2 getBufferDimensions();
|
||||
|
||||
bool inFrustum(glm::vec3& p);
|
||||
|
||||
int inFrustum(FrustumAABB& b);
|
||||
|
||||
~Camera();
|
||||
|
||||
private:
|
||||
//Window Size
|
||||
glm::vec2 bufferDimensions;
|
||||
|
||||
//Matrices
|
||||
glm::mat4 projectionMatrix;
|
||||
glm::mat4 orthographicMatrix;
|
||||
|
||||
//Perspective Matrix Properties
|
||||
float fov = 80.0f;
|
||||
float ratio;
|
||||
float nearClip = 0.1f;
|
||||
float farClip = 1000.0f;
|
||||
|
||||
//View Frustum
|
||||
Frustum frustum;
|
||||
|
||||
//Movement translation variables
|
||||
glm::vec3 front;
|
||||
glm::vec3 up;
|
||||
glm::vec3 right;
|
||||
glm::vec3 worldUp;
|
||||
|
||||
//Angle and Position
|
||||
glm::vec3 position;
|
||||
double yaw;
|
||||
double pitch;
|
||||
|
||||
void createMatrices();
|
||||
|
||||
void update();
|
||||
};
|
||||
|
||||
|
|
|
@ -7,15 +7,18 @@
|
|||
class Renderer;
|
||||
|
||||
class Drawable {
|
||||
public:
|
||||
virtual void update(double delta) {};
|
||||
virtual void draw(Renderer& renderer) {};
|
||||
|
||||
virtual bool isVisible() { return visible; }
|
||||
virtual void setVisible(bool visible) { this->visible = visible; }
|
||||
|
||||
virtual ~Drawable() = default;
|
||||
protected:
|
||||
bool visible = true;
|
||||
public:
|
||||
virtual void update(double delta) {};
|
||||
|
||||
virtual void draw(Renderer& renderer) {};
|
||||
|
||||
virtual bool isVisible() { return visible; }
|
||||
|
||||
virtual void setVisible(bool visible) { this->visible = visible; }
|
||||
|
||||
virtual ~Drawable() = default;
|
||||
|
||||
protected:
|
||||
bool visible = true;
|
||||
};
|
||||
|
||||
|
|
|
@ -4,37 +4,37 @@
|
|||
|
||||
#include "DrawableGroup.h"
|
||||
|
||||
void DrawableGroup::draw(Renderer &renderer) {
|
||||
for (auto drawable : children) {
|
||||
drawable->draw(renderer);
|
||||
}
|
||||
void DrawableGroup::draw(Renderer& renderer) {
|
||||
for (auto drawable : children) {
|
||||
drawable->draw(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableGroup::addDrawable(Drawable *drawable) {
|
||||
children.push_back(drawable);
|
||||
void DrawableGroup::addDrawable(Drawable* drawable) {
|
||||
children.push_back(drawable);
|
||||
}
|
||||
|
||||
void DrawableGroup::removeDrawable(Drawable *drawable) {
|
||||
for (auto it = children.begin(); it < children.end(); ++it) {
|
||||
if (*it == drawable) {
|
||||
children.erase(it);
|
||||
delete *it;
|
||||
return;
|
||||
}
|
||||
}
|
||||
void DrawableGroup::removeDrawable(Drawable* drawable) {
|
||||
for (auto it = children.begin(); it < children.end(); ++it) {
|
||||
if (*it == drawable) {
|
||||
children.erase(it);
|
||||
delete *it;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableGroup::clearDrawables() {
|
||||
for (auto drawable : children) {
|
||||
delete drawable;
|
||||
}
|
||||
children.clear();
|
||||
for (auto drawable : children) {
|
||||
delete drawable;
|
||||
}
|
||||
children.clear();
|
||||
}
|
||||
|
||||
DrawableGroup::~DrawableGroup() {
|
||||
clearDrawables();
|
||||
clearDrawables();
|
||||
}
|
||||
|
||||
std::vector<Drawable *> &DrawableGroup::getChildren() {
|
||||
return children;
|
||||
std::vector<Drawable*>& DrawableGroup::getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
|
|
@ -9,17 +9,20 @@
|
|||
#include "Drawable.h"
|
||||
|
||||
class DrawableGroup : public Drawable {
|
||||
public:
|
||||
void draw(Renderer& renderer) override;
|
||||
|
||||
void addDrawable(Drawable* drawable);
|
||||
void removeDrawable(Drawable* drawable);
|
||||
void clearDrawables();
|
||||
|
||||
std::vector<Drawable*>& getChildren();
|
||||
|
||||
~DrawableGroup() override;
|
||||
protected:
|
||||
std::vector<Drawable*> children {};
|
||||
public:
|
||||
void draw(Renderer& renderer) override;
|
||||
|
||||
void addDrawable(Drawable* drawable);
|
||||
|
||||
void removeDrawable(Drawable* drawable);
|
||||
|
||||
void clearDrawables();
|
||||
|
||||
std::vector<Drawable*>& getChildren();
|
||||
|
||||
~DrawableGroup() override;
|
||||
|
||||
protected:
|
||||
std::vector<Drawable*> children{};
|
||||
};
|
||||
|
||||
|
|
|
@ -10,62 +10,62 @@
|
|||
#include "game/atlas/TextureAtlas.h"
|
||||
|
||||
Font::Font(TextureAtlas& atlas, std::shared_ptr<AtlasRef> tex) :
|
||||
fontTex(std::move(tex)),
|
||||
atlasSize(atlas.pixelSize) {
|
||||
|
||||
getCharWidths(atlas);
|
||||
fontTex(std::move(tex)),
|
||||
atlasSize(atlas.pixelSize) {
|
||||
|
||||
getCharWidths(atlas);
|
||||
}
|
||||
|
||||
unsigned int Font::getCharWidth(char c) {
|
||||
unsigned int index = static_cast<unsigned int>(c) - 32;
|
||||
if (index >= amountOfChars) throw std::runtime_error("Invalid char index.");
|
||||
return charWidths[index];
|
||||
unsigned int index = static_cast<unsigned int>(c) - 32;
|
||||
if (index >= amountOfChars) throw std::runtime_error("Invalid char index.");
|
||||
return charWidths[index];
|
||||
}
|
||||
|
||||
void Font::getCharWidths(TextureAtlas &atlas) {
|
||||
auto& data = atlas.atlasData;
|
||||
|
||||
charWidths[0] = 2;
|
||||
|
||||
for (unsigned int i = 1; i < amountOfChars; i++) {
|
||||
glm::vec2 charPos = {i % 18 * charWidth, std::floor(i / 18) * charHeight};
|
||||
|
||||
unsigned int xBase = static_cast<unsigned int>(fontTex->pos.x) + static_cast<unsigned int>(charPos.x);
|
||||
unsigned int yBase = static_cast<unsigned int>(fontTex->pos.y) + static_cast<unsigned int>(charPos.y);
|
||||
|
||||
unsigned short width = 0;
|
||||
|
||||
for (unsigned int j = 0; j < charWidth; j++) {
|
||||
bool empty = true;
|
||||
for (unsigned int k = 0; k < charHeight; k++) {
|
||||
unsigned int xx = xBase + j;
|
||||
unsigned int yy = yBase + k;
|
||||
|
||||
unsigned int offset = yy * static_cast<unsigned int>(atlasSize.x) * 4 + xx * 4 + 3;
|
||||
|
||||
if (data[offset] != 0) {
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!empty) width = static_cast<unsigned short>(j);
|
||||
}
|
||||
|
||||
charWidths[i] = width;
|
||||
}
|
||||
void Font::getCharWidths(TextureAtlas& atlas) {
|
||||
auto& data = atlas.atlasData;
|
||||
|
||||
charWidths[0] = 2;
|
||||
|
||||
for (unsigned int i = 1; i < amountOfChars; i++) {
|
||||
glm::vec2 charPos = { i % 18 * charWidth, std::floor(i / 18) * charHeight };
|
||||
|
||||
unsigned int xBase = static_cast<unsigned int>(fontTex->pos.x) + static_cast<unsigned int>(charPos.x);
|
||||
unsigned int yBase = static_cast<unsigned int>(fontTex->pos.y) + static_cast<unsigned int>(charPos.y);
|
||||
|
||||
unsigned short width = 0;
|
||||
|
||||
for (unsigned int j = 0; j < charWidth; j++) {
|
||||
bool empty = true;
|
||||
for (unsigned int k = 0; k < charHeight; k++) {
|
||||
unsigned int xx = xBase + j;
|
||||
unsigned int yy = yBase + k;
|
||||
|
||||
unsigned int offset = yy * static_cast<unsigned int>(atlasSize.x) * 4 + xx * 4 + 3;
|
||||
|
||||
if (data[offset] != 0) {
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!empty) width = static_cast<unsigned short>(j);
|
||||
}
|
||||
|
||||
charWidths[i] = width;
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec4 Font::getCharUVs(char c) {
|
||||
unsigned int index = static_cast<unsigned int>(c) - 32;
|
||||
if (index >= amountOfChars) throw std::runtime_error("Invalid char index.");
|
||||
|
||||
glm::vec2 charPos = {(index % 18) * charWidth, std::floor(index / 18) * charHeight};
|
||||
glm::vec4 uv = {
|
||||
fontTex->uv.x + (charPos.x) / atlasSize.x,
|
||||
fontTex->uv.y + (charPos.y) / atlasSize.y,
|
||||
fontTex->uv.x + (charPos.x + getCharWidth(c) + 1) / atlasSize.x,
|
||||
fontTex->uv.y + (charPos.y + charHeight) / atlasSize.y
|
||||
};
|
||||
|
||||
return uv;
|
||||
unsigned int index = static_cast<unsigned int>(c) - 32;
|
||||
if (index >= amountOfChars) throw std::runtime_error("Invalid char index.");
|
||||
|
||||
glm::vec2 charPos = { (index % 18) * charWidth, std::floor(index / 18) * charHeight };
|
||||
glm::vec4 uv = {
|
||||
fontTex->uv.x + (charPos.x) / atlasSize.x,
|
||||
fontTex->uv.y + (charPos.y) / atlasSize.y,
|
||||
fontTex->uv.x + (charPos.x + getCharWidth(c) + 1) / atlasSize.x,
|
||||
fontTex->uv.y + (charPos.y + charHeight) / atlasSize.y
|
||||
};
|
||||
|
||||
return uv;
|
||||
}
|
||||
|
|
|
@ -9,23 +9,27 @@
|
|||
#include <glm/vec4.hpp>
|
||||
|
||||
class AtlasRef;
|
||||
|
||||
class TextureAtlas;
|
||||
|
||||
class Font {
|
||||
public:
|
||||
Font() = default;
|
||||
Font(TextureAtlas& atlas, std::shared_ptr<AtlasRef> tex);
|
||||
unsigned int getCharWidth(char c);
|
||||
glm::vec4 getCharUVs(char c);
|
||||
|
||||
const static unsigned int amountOfChars = 95;
|
||||
const static unsigned int charWidth = 7;
|
||||
const static unsigned int charHeight = 9;
|
||||
private:
|
||||
void getCharWidths(TextureAtlas& atlas);
|
||||
|
||||
glm::vec2 atlasSize {};
|
||||
|
||||
std::shared_ptr<AtlasRef> fontTex = nullptr;
|
||||
std::array<unsigned short, 95> charWidths {};
|
||||
public:
|
||||
Font() = default;
|
||||
|
||||
Font(TextureAtlas& atlas, std::shared_ptr<AtlasRef> tex);
|
||||
|
||||
unsigned int getCharWidth(char c);
|
||||
|
||||
glm::vec4 getCharUVs(char c);
|
||||
|
||||
const static unsigned int amountOfChars = 95;
|
||||
const static unsigned int charWidth = 7;
|
||||
const static unsigned int charHeight = 9;
|
||||
private:
|
||||
void getCharWidths(TextureAtlas& atlas);
|
||||
|
||||
glm::vec2 atlasSize{};
|
||||
|
||||
std::shared_ptr<AtlasRef> fontTex = nullptr;
|
||||
std::array<unsigned short, 95> charWidths{};
|
||||
};
|
||||
|
|
|
@ -17,56 +17,57 @@
|
|||
#include "game/atlas/asset/SerializedModel.h"
|
||||
|
||||
void Model::fromMesh(std::unique_ptr<EntityMesh> mesh) {
|
||||
meshes.clear();
|
||||
meshes.push_back(std::move(mesh));
|
||||
meshes.clear();
|
||||
meshes.push_back(std::move(mesh));
|
||||
}
|
||||
|
||||
int Model::fromFile(const std::string &path, const std::vector<std::shared_ptr<AtlasRef>> &textures) {
|
||||
this->textures = textures;
|
||||
|
||||
Assimp::Importer importer;
|
||||
const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenNormals);
|
||||
|
||||
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
|
||||
std::cout << Log::err << "ERROR::ASSIMP::" << importer.GetErrorString() << Log::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
loadModelMeshes(scene->mRootNode, scene);
|
||||
loadAnimations(scene);
|
||||
|
||||
calcBoneHeirarchy(scene->mRootNode, scene, -1);
|
||||
|
||||
globalInverseTransform = glm::inverse(MatConv::AiToGLMMat4(scene->mRootNode->mTransformation));
|
||||
|
||||
return 0;
|
||||
int Model::fromFile(const std::string& path, const std::vector<std::shared_ptr<AtlasRef>>& textures) {
|
||||
this->textures = textures;
|
||||
|
||||
Assimp::Importer importer;
|
||||
const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenNormals);
|
||||
|
||||
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
|
||||
std::cout << Log::err << "ERROR::ASSIMP::" << importer.GetErrorString() << Log::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
loadModelMeshes(scene->mRootNode, scene);
|
||||
loadAnimations(scene);
|
||||
|
||||
calcBoneHeirarchy(scene->mRootNode, scene, -1);
|
||||
|
||||
globalInverseTransform = glm::inverse(MatConv::AiToGLMMat4(scene->mRootNode->mTransformation));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Model::fromSerialized(const SerializedModel& model, const std::vector<std::shared_ptr<AtlasRef>>& textures) {
|
||||
this->textures = textures;
|
||||
|
||||
Assimp::Importer importer;
|
||||
const aiScene* scene = importer.ReadFileFromMemory(model.data.data(), model.data.length(), aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenNormals, "B3D");
|
||||
|
||||
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
|
||||
std::cout << Log::err << "ERROR::ASSIMP::" << importer.GetErrorString() << Log::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
loadModelMeshes(scene->mRootNode, scene);
|
||||
loadAnimations(scene);
|
||||
|
||||
calcBoneHeirarchy(scene->mRootNode, scene, -1);
|
||||
globalInverseTransform = glm::inverse(MatConv::AiToGLMMat4(scene->mRootNode->mTransformation));
|
||||
return 0;
|
||||
this->textures = textures;
|
||||
|
||||
Assimp::Importer importer;
|
||||
const aiScene* scene = importer.ReadFileFromMemory(model.data.data(), model.data.length(),
|
||||
aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenNormals, "B3D");
|
||||
|
||||
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
|
||||
std::cout << Log::err << "ERROR::ASSIMP::" << importer.GetErrorString() << Log::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
loadModelMeshes(scene->mRootNode, scene);
|
||||
loadAnimations(scene);
|
||||
|
||||
calcBoneHeirarchy(scene->mRootNode, scene, -1);
|
||||
globalInverseTransform = glm::inverse(MatConv::AiToGLMMat4(scene->mRootNode->mTransformation));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Model::getTransformsByFrame(double frame, glm::ivec2 bounds, std::vector<glm::mat4>& transforms) {
|
||||
transforms.resize(bones.size());
|
||||
|
||||
if (!rootBones.empty())
|
||||
for (auto bone : rootBones)
|
||||
calcBoneTransformation(frame, *bone, glm::mat4(1.0f), bounds, transforms);
|
||||
transforms.resize(bones.size());
|
||||
|
||||
if (!rootBones.empty())
|
||||
for (auto bone : rootBones)
|
||||
calcBoneTransformation(frame, *bone, glm::mat4(1.0f), bounds, transforms);
|
||||
}
|
||||
|
||||
//void Model::getTransformsByTime(double time, std::vector<glm::mat4>& transforms) {
|
||||
|
@ -76,187 +77,191 @@ void Model::getTransformsByFrame(double frame, glm::ivec2 bounds, std::vector<gl
|
|||
// getTransformsByFrame(frameTime, transforms);
|
||||
//}
|
||||
|
||||
const ModelAnimation &Model::getAnimation() {
|
||||
return animation;
|
||||
const ModelAnimation& Model::getAnimation() {
|
||||
return animation;
|
||||
}
|
||||
|
||||
void Model::loadModelMeshes(aiNode *node, const aiScene *scene) {
|
||||
for (unsigned int i = 0; i < node->mNumMeshes; i++) {
|
||||
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
|
||||
meshes.emplace_back(std::make_unique<EntityMesh>());
|
||||
loadMeshAndBone(mesh, meshes[i]);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < node->mNumChildren; i++) {
|
||||
loadModelMeshes(node->mChildren[i], scene); //Recurse down
|
||||
}
|
||||
void Model::loadModelMeshes(aiNode* node, const aiScene* scene) {
|
||||
for (unsigned int i = 0; i < node->mNumMeshes; i++) {
|
||||
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
|
||||
meshes.emplace_back(std::make_unique<EntityMesh>());
|
||||
loadMeshAndBone(mesh, meshes[i]);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < node->mNumChildren; i++) {
|
||||
loadModelMeshes(node->mChildren[i], scene); //Recurse down
|
||||
}
|
||||
}
|
||||
|
||||
void Model::loadMeshAndBone(aiMesh *mesh, std::unique_ptr<EntityMesh>& target) {
|
||||
std::vector<EntityVertex> vertices;
|
||||
std::vector<unsigned int> indices;
|
||||
|
||||
//Process Vertices
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
|
||||
EntityVertex vertex {};
|
||||
|
||||
vertex.position = {mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z};
|
||||
vertex.normal = {mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z};
|
||||
vertex.colorBlend = {1, 1, 1};
|
||||
|
||||
assert(mesh->mMaterialIndex >= 0 && mesh->mMaterialIndex < textures.size());
|
||||
|
||||
if (mesh->mTextureCoords[0]) {
|
||||
auto& texture = textures[mesh->mMaterialIndex];
|
||||
|
||||
//Set texture coordinates
|
||||
vertex.useTex = true;
|
||||
vertex.colorData = {
|
||||
texture->uv.x + mesh->mTextureCoords[0][i].x * (texture->uv.z - texture->uv.x),
|
||||
texture->uv.y + mesh->mTextureCoords[0][i].y * (texture->uv.w - texture->uv.y), 0, 1 //Alpha
|
||||
};
|
||||
}
|
||||
else vertex.colorData = {1, 1, 1, 1};
|
||||
|
||||
vertices.push_back(vertex);
|
||||
}
|
||||
|
||||
//Process Indices
|
||||
for (unsigned int i = 0; i < mesh->mNumFaces; i++) {
|
||||
aiFace face = mesh->mFaces[i];
|
||||
for (unsigned int j = 0; j < face.mNumIndices; j++) {
|
||||
indices.push_back(face.mIndices[j]);
|
||||
}
|
||||
}
|
||||
|
||||
//Process Mesh Bones and add to bone list
|
||||
bones.resize(mesh->mNumBones);
|
||||
for (unsigned int i = 0; i < mesh->mNumBones; i++) {
|
||||
aiBone* bone = mesh->mBones[i];
|
||||
|
||||
bones[i] = ModelBone(static_cast<unsigned int>(i), -1, {bone->mName.data});
|
||||
bones[i].offsetMatrix = glm::transpose(MatConv::AiToGLMMat4(bone->mOffsetMatrix));
|
||||
|
||||
for (unsigned int j = 0; j < bone->mNumWeights; j++) {
|
||||
aiVertexWeight* weight = &bone->mWeights[j];
|
||||
if (weight->mVertexId >= vertices.size()) assert(0);
|
||||
|
||||
unsigned int bid = 0;
|
||||
while (vertices[weight->mVertexId].boneWeights[bid] != 0) {
|
||||
bid++;
|
||||
assert(bid < 4);
|
||||
}
|
||||
|
||||
vertices[weight->mVertexId].boneIDs[bid] = i;
|
||||
vertices[weight->mVertexId].boneWeights[bid] = weight->mWeight;
|
||||
}
|
||||
}
|
||||
|
||||
//Create mesh
|
||||
target->create(vertices, indices);
|
||||
void Model::loadMeshAndBone(aiMesh* mesh, std::unique_ptr<EntityMesh>& target) {
|
||||
std::vector<EntityVertex> vertices;
|
||||
std::vector<unsigned int> indices;
|
||||
|
||||
//Process Vertices
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
|
||||
EntityVertex vertex{};
|
||||
|
||||
vertex.position = { mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z };
|
||||
vertex.normal = { mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z };
|
||||
vertex.colorBlend = { 1, 1, 1 };
|
||||
|
||||
assert(mesh->mMaterialIndex >= 0 && mesh->mMaterialIndex < textures.size());
|
||||
|
||||
if (mesh->mTextureCoords[0]) {
|
||||
auto& texture = textures[mesh->mMaterialIndex];
|
||||
|
||||
//Set texture coordinates
|
||||
vertex.useTex = true;
|
||||
vertex.colorData = {
|
||||
texture->uv.x + mesh->mTextureCoords[0][i].x * (texture->uv.z - texture->uv.x),
|
||||
texture->uv.y + mesh->mTextureCoords[0][i].y * (texture->uv.w - texture->uv.y), 0, 1 //Alpha
|
||||
};
|
||||
}
|
||||
else vertex.colorData = { 1, 1, 1, 1 };
|
||||
|
||||
vertices.push_back(vertex);
|
||||
}
|
||||
|
||||
//Process Indices
|
||||
for (unsigned int i = 0; i < mesh->mNumFaces; i++) {
|
||||
aiFace face = mesh->mFaces[i];
|
||||
for (unsigned int j = 0; j < face.mNumIndices; j++) {
|
||||
indices.push_back(face.mIndices[j]);
|
||||
}
|
||||
}
|
||||
|
||||
//Process Mesh Bones and add to bone list
|
||||
bones.resize(mesh->mNumBones);
|
||||
for (unsigned int i = 0; i < mesh->mNumBones; i++) {
|
||||
aiBone* bone = mesh->mBones[i];
|
||||
|
||||
bones[i] = ModelBone(static_cast<unsigned int>(i), -1, { bone->mName.data });
|
||||
bones[i].offsetMatrix = glm::transpose(MatConv::AiToGLMMat4(bone->mOffsetMatrix));
|
||||
|
||||
for (unsigned int j = 0; j < bone->mNumWeights; j++) {
|
||||
aiVertexWeight* weight = &bone->mWeights[j];
|
||||
if (weight->mVertexId >= vertices.size()) assert(0);
|
||||
|
||||
unsigned int bid = 0;
|
||||
while (vertices[weight->mVertexId].boneWeights[bid] != 0) {
|
||||
bid++;
|
||||
assert(bid < 4);
|
||||
}
|
||||
|
||||
vertices[weight->mVertexId].boneIDs[bid] = i;
|
||||
vertices[weight->mVertexId].boneWeights[bid] = weight->mWeight;
|
||||
}
|
||||
}
|
||||
|
||||
//Create mesh
|
||||
target->create(vertices, indices);
|
||||
}
|
||||
|
||||
void Model::loadAnimations(const aiScene *scene) {
|
||||
assert(scene->mNumAnimations <= 1);
|
||||
|
||||
if (scene->mNumAnimations == 1) {
|
||||
const aiAnimation* aiAnim = scene->mAnimations[0];
|
||||
|
||||
animation = ModelAnimation(aiAnim->mName.data);
|
||||
|
||||
animation.duration = static_cast<unsigned int>(aiAnim->mDuration);
|
||||
animation.ticksPerSecond = aiAnim->mTicksPerSecond;
|
||||
|
||||
animation.channels.resize(bones.size());
|
||||
|
||||
for (unsigned int j = 0; j < aiAnim->mNumChannels; j++) {
|
||||
const aiNodeAnim* aiChannel = aiAnim->mChannels[j];
|
||||
|
||||
int index = -1;
|
||||
for (unsigned int k = 0; k < bones.size(); k++) {
|
||||
if (std::string {aiChannel->mNodeName.data} == bones[k].name) {
|
||||
index = k;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
void Model::loadAnimations(const aiScene* scene) {
|
||||
assert(scene->mNumAnimations <= 1);
|
||||
|
||||
if (scene->mNumAnimations == 1) {
|
||||
const aiAnimation* aiAnim = scene->mAnimations[0];
|
||||
|
||||
animation = ModelAnimation(aiAnim->mName.data);
|
||||
|
||||
animation.duration = static_cast<unsigned int>(aiAnim->mDuration);
|
||||
animation.ticksPerSecond = aiAnim->mTicksPerSecond;
|
||||
|
||||
animation.channels.resize(bones.size());
|
||||
|
||||
for (unsigned int j = 0; j < aiAnim->mNumChannels; j++) {
|
||||
const aiNodeAnim* aiChannel = aiAnim->mChannels[j];
|
||||
|
||||
int index = -1;
|
||||
for (unsigned int k = 0; k < bones.size(); k++) {
|
||||
if (std::string{ aiChannel->mNodeName.data } == bones[k].name) {
|
||||
index = k;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
// std::cout << aiChannel->mNodeName.data << std::endl;
|
||||
}
|
||||
else {
|
||||
animation.channels[index] = AnimChannel(static_cast<unsigned int>(index), aiChannel->mNodeName.data);
|
||||
AnimChannel &channel = animation.channels[index];
|
||||
|
||||
//Copy Rotation Keys
|
||||
channel.rotationKeys.reserve(aiChannel->mNumRotationKeys);
|
||||
for (unsigned int k = 0; k < aiChannel->mNumRotationKeys; k++) {
|
||||
aiQuatKey *key = &aiChannel->mRotationKeys[k];
|
||||
channel.rotationKeys.emplace_back(key->mTime, key->mValue);
|
||||
}
|
||||
|
||||
//Copy Position Keys
|
||||
channel.positionKeys.reserve(aiChannel->mNumPositionKeys);
|
||||
for (unsigned int k = 0; k < aiChannel->mNumPositionKeys; k++) {
|
||||
aiVectorKey *key = &aiChannel->mPositionKeys[k];
|
||||
channel.positionKeys.emplace_back(key->mTime,
|
||||
glm::vec3{key->mValue.x, key->mValue.y, key->mValue.z});
|
||||
}
|
||||
|
||||
//Copy Scale Keys
|
||||
channel.scaleKeys.reserve(aiChannel->mNumScalingKeys);
|
||||
for (unsigned int k = 0; k < aiChannel->mNumScalingKeys; k++) {
|
||||
aiVectorKey *key = &aiChannel->mScalingKeys[k];
|
||||
channel.scaleKeys.emplace_back(key->mTime, glm::vec3{key->mValue.x, key->mValue.y, key->mValue.z});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
animation.channels[index] = AnimChannel(static_cast<unsigned int>(index), aiChannel->mNodeName.data);
|
||||
AnimChannel& channel = animation.channels[index];
|
||||
|
||||
//Copy Rotation Keys
|
||||
channel.rotationKeys.reserve(aiChannel->mNumRotationKeys);
|
||||
for (unsigned int k = 0; k < aiChannel->mNumRotationKeys; k++) {
|
||||
aiQuatKey* key = &aiChannel->mRotationKeys[k];
|
||||
channel.rotationKeys.emplace_back(key->mTime, key->mValue);
|
||||
}
|
||||
|
||||
//Copy Position Keys
|
||||
channel.positionKeys.reserve(aiChannel->mNumPositionKeys);
|
||||
for (unsigned int k = 0; k < aiChannel->mNumPositionKeys; k++) {
|
||||
aiVectorKey* key = &aiChannel->mPositionKeys[k];
|
||||
channel.positionKeys.emplace_back(key->mTime,
|
||||
glm::vec3{ key->mValue.x, key->mValue.y, key->mValue.z });
|
||||
}
|
||||
|
||||
//Copy Scale Keys
|
||||
channel.scaleKeys.reserve(aiChannel->mNumScalingKeys);
|
||||
for (unsigned int k = 0; k < aiChannel->mNumScalingKeys; k++) {
|
||||
aiVectorKey* key = &aiChannel->mScalingKeys[k];
|
||||
channel.scaleKeys.emplace_back(key->mTime,
|
||||
glm::vec3{ key->mValue.x, key->mValue.y, key->mValue.z });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Model::calcBoneHeirarchy(aiNode *node, const aiScene *scene, int parentBoneIndex) {
|
||||
int index = -1;
|
||||
|
||||
for (auto &bone : bones) {
|
||||
if (bone.name == std::string(node->mName.data)) {
|
||||
bone.parent = parentBoneIndex;
|
||||
index = bone.index;
|
||||
if (parentBoneIndex == -1) rootBones.push_back(&bone);
|
||||
else bones[bone.parent].children.push_back(&bone);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < node->mNumChildren; i++) calcBoneHeirarchy(node->mChildren[i], scene, index);
|
||||
void Model::calcBoneHeirarchy(aiNode* node, const aiScene* scene, int parentBoneIndex) {
|
||||
int index = -1;
|
||||
|
||||
for (auto& bone : bones) {
|
||||
if (bone.name == std::string(node->mName.data)) {
|
||||
bone.parent = parentBoneIndex;
|
||||
index = bone.index;
|
||||
if (parentBoneIndex == -1) rootBones.push_back(&bone);
|
||||
else bones[bone.parent].children.push_back(&bone);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < node->mNumChildren; i++) calcBoneHeirarchy(node->mChildren[i], scene, index);
|
||||
}
|
||||
|
||||
void Model::calcBoneTransformation(double animTime, ModelBone& bone, glm::mat4 parentTransform, glm::ivec2 bounds, std::vector<glm::mat4>& transforms) {
|
||||
AnimChannel* channel = nullptr;
|
||||
for (auto &i : animation.channels) {
|
||||
if (i.index == bone.index) {
|
||||
channel = &i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
glm::mat4 boneTransformation(1.0f);
|
||||
if (channel) {
|
||||
glm::mat4 position = glm::translate(glm::mat4(1.0), calcBoneVal<glm::vec3>(animTime, bounds, channel->positionKeys, {},
|
||||
[](const glm::vec3 &a, const glm::vec3 &b, float factor) { return glm::mix(a, b, factor); }));
|
||||
glm::mat4 scale = glm::scale(glm::mat4(1.0), calcBoneVal<glm::vec3>(animTime, bounds, channel->scaleKeys, {},
|
||||
[](const glm::vec3 &a, const glm::vec3 &b, float factor) { return glm::mix(a, b, factor); }));
|
||||
glm::mat4 rotation = glm::transpose(glm::mat4(MatConv::AiToGLMMat3(
|
||||
calcBoneVal<aiQuaternion>(animTime, bounds, channel->rotationKeys, {},
|
||||
[](const aiQuaternion& a, const aiQuaternion& b, float factor) {
|
||||
aiQuaternion result;
|
||||
aiQuaternion::Interpolate(result, a, b, factor);
|
||||
return result.Normalize();
|
||||
}).GetMatrix())));
|
||||
|
||||
boneTransformation = position * rotation * scale;
|
||||
}
|
||||
|
||||
glm::mat4 globalTransformation = parentTransform * boneTransformation;
|
||||
transforms[bone.index] = globalInverseTransform * globalTransformation * bone.offsetMatrix;
|
||||
|
||||
for (auto& child : bone.children) calcBoneTransformation(animTime, *child, globalTransformation, bounds, transforms);
|
||||
void Model::calcBoneTransformation(double animTime, ModelBone& bone, glm::mat4 parentTransform, glm::ivec2 bounds,
|
||||
std::vector<glm::mat4>& transforms) {
|
||||
AnimChannel* channel = nullptr;
|
||||
for (auto& i : animation.channels) {
|
||||
if (i.index == bone.index) {
|
||||
channel = &i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
glm::mat4 boneTransformation(1.0f);
|
||||
if (channel) {
|
||||
glm::mat4 position = glm::translate(glm::mat4(1.0),
|
||||
calcBoneVal<glm::vec3>(animTime, bounds, channel->positionKeys, {},
|
||||
[](const glm::vec3& a, const glm::vec3& b, float factor) { return glm::mix(a, b, factor); }));
|
||||
glm::mat4 scale = glm::scale(glm::mat4(1.0), calcBoneVal<glm::vec3>(animTime, bounds, channel->scaleKeys, {},
|
||||
[](const glm::vec3& a, const glm::vec3& b, float factor) { return glm::mix(a, b, factor); }));
|
||||
glm::mat4 rotation = glm::transpose(glm::mat4(MatConv::AiToGLMMat3(
|
||||
calcBoneVal<aiQuaternion>(animTime, bounds, channel->rotationKeys, {},
|
||||
[](const aiQuaternion& a, const aiQuaternion& b, float factor) {
|
||||
aiQuaternion result;
|
||||
aiQuaternion::Interpolate(result, a, b, factor);
|
||||
return result.Normalize();
|
||||
}).GetMatrix())));
|
||||
|
||||
boneTransformation = position * rotation * scale;
|
||||
}
|
||||
|
||||
glm::mat4 globalTransformation = parentTransform * boneTransformation;
|
||||
transforms[bone.index] = globalInverseTransform * globalTransformation * bone.offsetMatrix;
|
||||
|
||||
for (auto& child : bone.children)
|
||||
calcBoneTransformation(animTime, *child, globalTransformation, bounds, transforms);
|
||||
}
|
|
@ -16,60 +16,68 @@
|
|||
#include "client/graph/mesh/EntityMesh.h"
|
||||
|
||||
class AtlasRef;
|
||||
|
||||
class SerializedModel;
|
||||
|
||||
class Model {
|
||||
public:
|
||||
Model() = default;
|
||||
|
||||
void fromMesh(std::unique_ptr<EntityMesh> mesh);
|
||||
int fromFile(const std::string &path, const std::vector<std::shared_ptr<AtlasRef>> &texture);
|
||||
int fromSerialized(const SerializedModel &model, const std::vector<std::shared_ptr<AtlasRef>> &texture);
|
||||
|
||||
void getTransformsByFrame(double frame, glm::ivec2 bounds, std::vector<glm::mat4>& transforms);
|
||||
public:
|
||||
Model() = default;
|
||||
|
||||
void fromMesh(std::unique_ptr<EntityMesh> mesh);
|
||||
|
||||
int fromFile(const std::string& path, const std::vector<std::shared_ptr<AtlasRef>>& texture);
|
||||
|
||||
int fromSerialized(const SerializedModel& model, const std::vector<std::shared_ptr<AtlasRef>>& texture);
|
||||
|
||||
void getTransformsByFrame(double frame, glm::ivec2 bounds, std::vector<glm::mat4>& transforms);
|
||||
// void getTransformsByTime(double time, std::tuple<uint> bounds, std::vector<glm::mat4>& transforms);
|
||||
|
||||
const ModelAnimation& getAnimation();
|
||||
|
||||
std::vector<std::unique_ptr<EntityMesh>> meshes;
|
||||
private:
|
||||
void loadModelMeshes(aiNode *node, const aiScene *scene);
|
||||
void loadMeshAndBone(aiMesh *mesh, std::unique_ptr<EntityMesh> &target);
|
||||
void loadAnimations(const aiScene *scene);
|
||||
|
||||
void calcBoneHeirarchy(aiNode *node, const aiScene *scene, int parentBoneIndex);
|
||||
void calcBoneTransformation(double animTime, ModelBone& bone, glm::mat4 parentTransform, glm::ivec2 bounds, std::vector<glm::mat4>& transforms);
|
||||
|
||||
template <typename T> static inline T calcBoneVal(
|
||||
double animTime, glm::ivec2 bounds, const std::vector<std::pair<double, T>>& keysArray,
|
||||
const T& def, std::function<T(const T& a, const T& b, float factor)> merge) {
|
||||
|
||||
if (keysArray.empty()) return def;
|
||||
if (keysArray.size() == 1) return keysArray[0].second;
|
||||
|
||||
unsigned int index = 0;
|
||||
for (unsigned int i = 1; i < keysArray.size(); i++) {
|
||||
if (keysArray[i].first > animTime) {
|
||||
index = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
float factor = 1;
|
||||
unsigned int nextIndex = index + 1;
|
||||
if (nextIndex >= keysArray.size() || nextIndex > bounds.y) nextIndex = bounds.x;
|
||||
else {
|
||||
double delta = keysArray[nextIndex].first - keysArray[index].first;
|
||||
factor = (animTime - keysArray[index].first) / delta;
|
||||
}
|
||||
|
||||
return merge(keysArray[index].second, keysArray[nextIndex].second, factor);
|
||||
}
|
||||
|
||||
ModelAnimation animation {};
|
||||
std::vector<ModelBone*> rootBones {};
|
||||
std::vector<ModelBone> bones {};
|
||||
std::vector<std::shared_ptr<AtlasRef>> textures {};
|
||||
|
||||
glm::mat4 globalInverseTransform {};
|
||||
|
||||
const ModelAnimation& getAnimation();
|
||||
|
||||
std::vector<std::unique_ptr<EntityMesh>> meshes;
|
||||
private:
|
||||
void loadModelMeshes(aiNode* node, const aiScene* scene);
|
||||
|
||||
void loadMeshAndBone(aiMesh* mesh, std::unique_ptr<EntityMesh>& target);
|
||||
|
||||
void loadAnimations(const aiScene* scene);
|
||||
|
||||
void calcBoneHeirarchy(aiNode* node, const aiScene* scene, int parentBoneIndex);
|
||||
|
||||
void calcBoneTransformation(double animTime, ModelBone& bone, glm::mat4 parentTransform, glm::ivec2 bounds,
|
||||
std::vector<glm::mat4>& transforms);
|
||||
|
||||
template<typename T>
|
||||
static inline T calcBoneVal(
|
||||
double animTime, glm::ivec2 bounds, const std::vector<std::pair<double, T>>& keysArray,
|
||||
const T& def, std::function<T(const T& a, const T& b, float factor)> merge) {
|
||||
|
||||
if (keysArray.empty()) return def;
|
||||
if (keysArray.size() == 1) return keysArray[0].second;
|
||||
|
||||
unsigned int index = 0;
|
||||
for (unsigned int i = 1; i < keysArray.size(); i++) {
|
||||
if (keysArray[i].first > animTime) {
|
||||
index = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
float factor = 1;
|
||||
unsigned int nextIndex = index + 1;
|
||||
if (nextIndex >= keysArray.size() || nextIndex > bounds.y) nextIndex = bounds.x;
|
||||
else {
|
||||
double delta = keysArray[nextIndex].first - keysArray[index].first;
|
||||
factor = (animTime - keysArray[index].first) / delta;
|
||||
}
|
||||
|
||||
return merge(keysArray[index].second, keysArray[nextIndex].second, factor);
|
||||
}
|
||||
|
||||
ModelAnimation animation{};
|
||||
std::vector<ModelBone*> rootBones{};
|
||||
std::vector<ModelBone> bones{};
|
||||
std::vector<std::shared_ptr<AtlasRef>> textures{};
|
||||
|
||||
glm::mat4 globalInverseTransform{};
|
||||
};
|
||||
|
||||
|
|
|
@ -5,4 +5,4 @@
|
|||
#include "ModelAnimation.h"
|
||||
|
||||
ModelAnimation::ModelAnimation(const std::string& name)
|
||||
: name(name) {}
|
||||
: name(name) {}
|
||||
|
|
|
@ -10,12 +10,13 @@
|
|||
#include "world/dim/ent/AnimChannel.h"
|
||||
|
||||
class ModelAnimation {
|
||||
public:
|
||||
ModelAnimation() = default;
|
||||
explicit ModelAnimation(const std::string& name);
|
||||
|
||||
std::string name = "";
|
||||
std::vector<AnimChannel> channels {};
|
||||
unsigned int duration = 0;
|
||||
double ticksPerSecond = 0;
|
||||
public:
|
||||
ModelAnimation() = default;
|
||||
|
||||
explicit ModelAnimation(const std::string& name);
|
||||
|
||||
std::string name = "";
|
||||
std::vector<AnimChannel> channels{};
|
||||
unsigned int duration = 0;
|
||||
double ticksPerSecond = 0;
|
||||
};
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
#include "ModelBone.h"
|
||||
|
||||
ModelBone::ModelBone(unsigned int index, int parent, const std::string& name) :
|
||||
index(index),
|
||||
parent(parent),
|
||||
name(name) {}
|
||||
index(index),
|
||||
parent(parent),
|
||||
name(name) {}
|
|
@ -9,15 +9,16 @@
|
|||
#include <glm/mat4x4.hpp>
|
||||
|
||||
class ModelBone {
|
||||
public:
|
||||
ModelBone() = default;
|
||||
ModelBone(unsigned int index, int parent, const std::string& name);
|
||||
|
||||
std::string name {};
|
||||
unsigned int index = 0;
|
||||
int parent = 0;
|
||||
|
||||
glm::mat4 offsetMatrix {};
|
||||
|
||||
std::vector<ModelBone*> children;
|
||||
public:
|
||||
ModelBone() = default;
|
||||
|
||||
ModelBone(unsigned int index, int parent, const std::string& name);
|
||||
|
||||
std::string name{};
|
||||
unsigned int index = 0;
|
||||
int parent = 0;
|
||||
|
||||
glm::mat4 offsetMatrix{};
|
||||
|
||||
std::vector<ModelBone*> children;
|
||||
};
|
||||
|
|
|
@ -6,229 +6,232 @@
|
|||
|
||||
#include "Renderer.h"
|
||||
|
||||
Renderer::Renderer() : Renderer({1366, 768}) {};
|
||||
Renderer::Renderer() : Renderer({ 1366, 768 }) {};
|
||||
|
||||
Renderer::Renderer(glm::ivec2 win) :
|
||||
activeTexture(nullptr),
|
||||
window(win),
|
||||
|
||||
world (win, 2),
|
||||
entity(win, 2),
|
||||
ssao (win, 1, 24),
|
||||
blur (win, 1),
|
||||
light (win, 2) {
|
||||
|
||||
camera.create(window.getSize().x, window.getSize().y, glm::vec3(0, 1, 0));
|
||||
|
||||
ssao.createFromFile("../assets/shader/post/passThrough.vs", "../assets/shader/post/ssaoCalc.fs");
|
||||
blur.createFromFile("../assets/shader/post/passThrough.vs", "../assets/shader/post/ssaoBlur.fs");
|
||||
light.createFromFile("../assets/shader/post/passThrough.vs", "../assets/shader/post/deferredLighting.fs");
|
||||
world.createFromFile("../assets/shader/world/world.vs", "../assets/shader/world/world.fs", "../assets/shader/world/world.gs");
|
||||
entity.createFromFile("../assets/shader/world/entity.vs", "../assets/shader/world/entity.fs");
|
||||
|
||||
guiShader = Shader();
|
||||
guiShader.createFromFile("../assets/shader/ortho/hud.vs", "../assets/shader/ortho/hud.fs");
|
||||
|
||||
gu.matrix = camera.getOrthographicMatrix();
|
||||
gu.ortho = guiShader.get("ortho");
|
||||
gu.model = guiShader.get("model");
|
||||
gu.bones = guiShader.get("uBones");
|
||||
gu.clipBounds = guiShader.get("uClipBounds");
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
window.addResizeCallback("renderer", [&](glm::ivec2 win) {
|
||||
ssao.windowResized(win);
|
||||
blur.windowResized(win);
|
||||
light.windowResized(win);
|
||||
world.windowResized(win);
|
||||
|
||||
camera.changeWindowDimensions(win);
|
||||
|
||||
gu.matrix = camera.getOrthographicMatrix();
|
||||
});
|
||||
activeTexture(nullptr),
|
||||
window(win),
|
||||
|
||||
world(win, 2),
|
||||
entity(win, 2),
|
||||
ssao(win, 1, 24),
|
||||
blur(win, 1),
|
||||
light(win, 2) {
|
||||
|
||||
camera.create(window.getSize().x, window.getSize().y, glm::vec3(0, 1, 0));
|
||||
|
||||
ssao.createFromFile("../assets/shader/post/passThrough.vs", "../assets/shader/post/ssaoCalc.fs");
|
||||
blur.createFromFile("../assets/shader/post/passThrough.vs", "../assets/shader/post/ssaoBlur.fs");
|
||||
light.createFromFile("../assets/shader/post/passThrough.vs", "../assets/shader/post/deferredLighting.fs");
|
||||
world.createFromFile("../assets/shader/world/world.vs", "../assets/shader/world/world.fs",
|
||||
"../assets/shader/world/world.gs");
|
||||
entity.createFromFile("../assets/shader/world/entity.vs", "../assets/shader/world/entity.fs");
|
||||
|
||||
guiShader = Shader();
|
||||
guiShader.createFromFile("../assets/shader/ortho/hud.vs", "../assets/shader/ortho/hud.fs");
|
||||
|
||||
gu.matrix = camera.getOrthographicMatrix();
|
||||
gu.ortho = guiShader.get("ortho");
|
||||
gu.model = guiShader.get("model");
|
||||
gu.bones = guiShader.get("uBones");
|
||||
gu.clipBounds = guiShader.get("uClipBounds");
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
window.addResizeCallback("renderer", [&](glm::ivec2 win) {
|
||||
ssao.windowResized(win);
|
||||
blur.windowResized(win);
|
||||
light.windowResized(win);
|
||||
world.windowResized(win);
|
||||
|
||||
camera.changeWindowDimensions(win);
|
||||
|
||||
gu.matrix = camera.getOrthographicMatrix();
|
||||
});
|
||||
}
|
||||
|
||||
void Renderer::update(double delta) {
|
||||
//VSync 1 = On, 0 = Off
|
||||
glfwSwapInterval(1);
|
||||
elapsedTime += delta;
|
||||
|
||||
window.update();
|
||||
world.updateSwayMap(delta);
|
||||
//VSync 1 = On, 0 = Off
|
||||
glfwSwapInterval(1);
|
||||
elapsedTime += delta;
|
||||
|
||||
window.update();
|
||||
world.updateSwayMap(delta);
|
||||
}
|
||||
|
||||
void Renderer::beginChunkDeferredCalls() {
|
||||
activeTexture = nullptr;
|
||||
currentModelUniform = world.uniforms.model;
|
||||
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glViewport(0, 0, static_cast<int>(world.windowSize.x * world.bufferScale), static_cast<int>(world.windowSize.y * world.bufferScale));
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, light.gBuffer);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
const float skyColor[] = {clearColor.x, clearColor.y, clearColor.z, 1};
|
||||
static const float clearTransparent[] = {0, 0, 0, 1};
|
||||
glClearBufferfv(GL_COLOR, 0, clearTransparent);
|
||||
glClearBufferfv(GL_COLOR, 1, clearTransparent);
|
||||
glClearBufferfv(GL_COLOR, 2, skyColor);
|
||||
|
||||
setShader(world);
|
||||
world.set(world.uniforms.proj, camera.getProjectionMatrix());
|
||||
world.set(world.uniforms.view, camera.getViewMatrix());
|
||||
world.set(world.uniforms.time, static_cast<float>(elapsedTime));
|
||||
world.swayTex.use(1);
|
||||
activeTexture = nullptr;
|
||||
currentModelUniform = world.uniforms.model;
|
||||
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glViewport(0, 0, static_cast<int>(world.windowSize.x * world.bufferScale),
|
||||
static_cast<int>(world.windowSize.y * world.bufferScale));
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, light.gBuffer);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
const float skyColor[] = { clearColor.x, clearColor.y, clearColor.z, 1 };
|
||||
static const float clearTransparent[] = { 0, 0, 0, 1 };
|
||||
glClearBufferfv(GL_COLOR, 0, clearTransparent);
|
||||
glClearBufferfv(GL_COLOR, 1, clearTransparent);
|
||||
glClearBufferfv(GL_COLOR, 2, skyColor);
|
||||
|
||||
setShader(world);
|
||||
world.set(world.uniforms.proj, camera.getProjectionMatrix());
|
||||
world.set(world.uniforms.view, camera.getViewMatrix());
|
||||
world.set(world.uniforms.time, static_cast<float>(elapsedTime));
|
||||
world.swayTex.use(1);
|
||||
}
|
||||
|
||||
void Renderer::beginEntityDeferredCalls() {
|
||||
currentModelUniform = entity.uniforms.model;
|
||||
|
||||
setShader(entity);
|
||||
entity.set(entity.uniforms.proj, camera.getProjectionMatrix());
|
||||
entity.set(entity.uniforms.view, camera.getViewMatrix());
|
||||
currentModelUniform = entity.uniforms.model;
|
||||
|
||||
setShader(entity);
|
||||
entity.set(entity.uniforms.proj, camera.getProjectionMatrix());
|
||||
entity.set(entity.uniforms.view, camera.getViewMatrix());
|
||||
}
|
||||
|
||||
void Renderer::endDeferredCalls() {
|
||||
activeTexture = nullptr;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, ssao.fbo);
|
||||
glClearColor(clearColor.x, clearColor.y, clearColor.z, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
setShader(ssao);
|
||||
ssao.set(ssao.uniforms.proj, camera.getProjectionMatrix());
|
||||
ssao.set(ssao.uniforms.view, camera.getViewMatrix());
|
||||
ssao.set(ssao.uniforms.kernelCount, ssao.kernelCount);
|
||||
|
||||
for (unsigned int i = 0; i < ssao.kernelCount; i++) {
|
||||
GLint uni = ssao.get("samples[" + std::to_string(i) + "]");
|
||||
ssao.set(uni, ssao.kernels[i]);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, light.gPosition);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, light.gNormal);
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, ssao.tex);
|
||||
|
||||
renderQuad();
|
||||
|
||||
auto winSize = window.getSize();
|
||||
glViewport(0, 0, static_cast<int>(winSize.x), static_cast<int>(winSize.y));
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, blur.fbo);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
setShader(blur);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, ssao.colorBuffer);
|
||||
renderQuad();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
setShader(light);
|
||||
light.set(light.uniforms.camPosition, camera.getPos());
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, light.gPosition);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, light.gNormal);
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, light.gColorSpec);
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
glBindTexture(GL_TEXTURE_2D, blur.colorBuffer);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
renderQuad();
|
||||
activeTexture = nullptr;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, ssao.fbo);
|
||||
glClearColor(clearColor.x, clearColor.y, clearColor.z, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
setShader(ssao);
|
||||
ssao.set(ssao.uniforms.proj, camera.getProjectionMatrix());
|
||||
ssao.set(ssao.uniforms.view, camera.getViewMatrix());
|
||||
ssao.set(ssao.uniforms.kernelCount, ssao.kernelCount);
|
||||
|
||||
for (unsigned int i = 0; i < ssao.kernelCount; i++) {
|
||||
GLint uni = ssao.get("samples[" + std::to_string(i) + "]");
|
||||
ssao.set(uni, ssao.kernels[i]);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, light.gPosition);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, light.gNormal);
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, ssao.tex);
|
||||
|
||||
renderQuad();
|
||||
|
||||
auto winSize = window.getSize();
|
||||
glViewport(0, 0, static_cast<int>(winSize.x), static_cast<int>(winSize.y));
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, blur.fbo);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
setShader(blur);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, ssao.colorBuffer);
|
||||
renderQuad();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
setShader(light);
|
||||
light.set(light.uniforms.camPosition, camera.getPos());
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, light.gPosition);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, light.gNormal);
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, light.gColorSpec);
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
glBindTexture(GL_TEXTURE_2D, blur.colorBuffer);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
renderQuad();
|
||||
}
|
||||
|
||||
void Renderer::beginGUIDrawCalls() {
|
||||
activeTexture = nullptr;
|
||||
currentModelUniform = gu.model;
|
||||
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
setShader(guiShader);
|
||||
guiShader.set(gu.ortho, gu.matrix);
|
||||
activeTexture = nullptr;
|
||||
currentModelUniform = gu.model;
|
||||
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
setShader(guiShader);
|
||||
guiShader.set(gu.ortho, gu.matrix);
|
||||
}
|
||||
|
||||
void Renderer::swapBuffers() {
|
||||
Shader::clearShader();
|
||||
window.swapBuffers();
|
||||
Shader::clearShader();
|
||||
window.swapBuffers();
|
||||
}
|
||||
|
||||
void Renderer::setShader(Shader& s) {
|
||||
s.use();
|
||||
this->currentShader = &s;
|
||||
s.use();
|
||||
this->currentShader = &s;
|
||||
}
|
||||
|
||||
void Renderer::setClearColor(unsigned char r, unsigned char g, unsigned char b) {
|
||||
clearColor = {static_cast<float>(r)/255.f, static_cast<float>(g)/255.f, static_cast<float>(b)/255.f, 1};
|
||||
clearColor = { static_cast<float>(r) / 255.f, static_cast<float>(g) / 255.f, static_cast<float>(b) / 255.f, 1 };
|
||||
}
|
||||
|
||||
void Renderer::toggleDepthTest(bool enable) {
|
||||
enable ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
|
||||
enable ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void Renderer::clearDepthBuffer() {
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void Renderer::setModelMatrix(const glm::mat4& modelMatrix) {
|
||||
glUniformMatrix4fv(currentModelUniform, 1, GL_FALSE, glm::value_ptr(modelMatrix));
|
||||
glUniformMatrix4fv(currentModelUniform, 1, GL_FALSE, glm::value_ptr(modelMatrix));
|
||||
}
|
||||
|
||||
void Renderer::setBones(std::vector<glm::mat4> &transforms) {
|
||||
if (transforms.empty()) return;
|
||||
currentShader->setArr((currentShader == &entity ? entity.uniforms.bones : gu.bones), static_cast<GLsizei>(transforms.size()), transforms.at(0));
|
||||
void Renderer::setBones(std::vector<glm::mat4>& transforms) {
|
||||
if (transforms.empty()) return;
|
||||
currentShader->setArr((currentShader == &entity ? entity.uniforms.bones : gu.bones),
|
||||
static_cast<GLsizei>(transforms.size()), transforms.at(0));
|
||||
}
|
||||
|
||||
void Renderer::setClipBounds(glm::vec4 bounds) {
|
||||
guiShader.set(gu.clipBounds, {bounds.x, window.getSize().y - bounds.w, bounds.z, window.getSize().y - bounds.y});
|
||||
guiShader.set(gu.clipBounds, { bounds.x, window.getSize().y - bounds.w, bounds.z, window.getSize().y - bounds.y });
|
||||
}
|
||||
|
||||
void Renderer::enableTexture(Texture *texture) {
|
||||
if (texture != activeTexture) {
|
||||
activeTexture = texture;
|
||||
texture->use(0);
|
||||
}
|
||||
void Renderer::enableTexture(Texture* texture) {
|
||||
if (texture != activeTexture) {
|
||||
activeTexture = texture;
|
||||
texture->use(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::renderQuad() {
|
||||
if (quadVAO == 0) {
|
||||
float quadVertices[] = {
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
||||
};
|
||||
|
||||
glGenVertexArrays(1, &quadVAO);
|
||||
glGenBuffers(1, &quadVBO);
|
||||
glBindVertexArray(quadVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *) nullptr);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *) (3 * sizeof(float)));
|
||||
}
|
||||
|
||||
glBindVertexArray(quadVAO);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
if (quadVAO == 0) {
|
||||
float quadVertices[] = {
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
||||
};
|
||||
|
||||
glGenVertexArrays(1, &quadVAO);
|
||||
glGenBuffers(1, &quadVBO);
|
||||
glBindVertexArray(quadVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*) nullptr);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*) (3 * sizeof(float)));
|
||||
}
|
||||
|
||||
glBindVertexArray(quadVAO);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,52 +17,62 @@
|
|||
#include "shader/GuiUniforms.h"
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
Renderer();
|
||||
Renderer(glm::ivec2 win);
|
||||
|
||||
void update(double delta);
|
||||
|
||||
void beginChunkDeferredCalls();
|
||||
void beginEntityDeferredCalls();
|
||||
void endDeferredCalls();
|
||||
void beginGUIDrawCalls();
|
||||
void swapBuffers();
|
||||
|
||||
void setShader(Shader& s);
|
||||
void setClearColor(unsigned char r, unsigned char g, unsigned char b);
|
||||
|
||||
static void toggleDepthTest(bool enable);
|
||||
static void clearDepthBuffer();
|
||||
|
||||
void setModelMatrix(const glm::mat4& modelMatrix);
|
||||
void setBones(std::vector<glm::mat4>& transforms);
|
||||
void setClipBounds(glm::vec4 bounds);
|
||||
void enableTexture(Texture* texture);
|
||||
|
||||
Window window;
|
||||
Camera camera;
|
||||
private:
|
||||
void renderQuad();
|
||||
|
||||
unsigned int quadVAO = 0;
|
||||
unsigned int quadVBO = 0;
|
||||
|
||||
glm::vec4 clearColor {0, 0, 0, 1};
|
||||
Texture* activeTexture;
|
||||
|
||||
WorldGeometryShader world;
|
||||
EntityGeometryShader entity;
|
||||
SSAOShader ssao;
|
||||
BlurShader blur;
|
||||
LightingShader light;
|
||||
|
||||
Shader guiShader;
|
||||
GuiUniforms gu;
|
||||
|
||||
Shader* currentShader;
|
||||
|
||||
GLint currentModelUniform;
|
||||
double elapsedTime = 0;
|
||||
public:
|
||||
Renderer();
|
||||
|
||||
Renderer(glm::ivec2 win);
|
||||
|
||||
void update(double delta);
|
||||
|
||||
void beginChunkDeferredCalls();
|
||||
|
||||
void beginEntityDeferredCalls();
|
||||
|
||||
void endDeferredCalls();
|
||||
|
||||
void beginGUIDrawCalls();
|
||||
|
||||
void swapBuffers();
|
||||
|
||||
void setShader(Shader& s);
|
||||
|
||||
void setClearColor(unsigned char r, unsigned char g, unsigned char b);
|
||||
|
||||
static void toggleDepthTest(bool enable);
|
||||
|
||||
static void clearDepthBuffer();
|
||||
|
||||
void setModelMatrix(const glm::mat4& modelMatrix);
|
||||
|
||||
void setBones(std::vector<glm::mat4>& transforms);
|
||||
|
||||
void setClipBounds(glm::vec4 bounds);
|
||||
|
||||
void enableTexture(Texture* texture);
|
||||
|
||||
Window window;
|
||||
Camera camera;
|
||||
private:
|
||||
void renderQuad();
|
||||
|
||||
unsigned int quadVAO = 0;
|
||||
unsigned int quadVBO = 0;
|
||||
|
||||
glm::vec4 clearColor{ 0, 0, 0, 1 };
|
||||
Texture* activeTexture;
|
||||
|
||||
WorldGeometryShader world;
|
||||
EntityGeometryShader entity;
|
||||
SSAOShader ssao;
|
||||
BlurShader blur;
|
||||
LightingShader light;
|
||||
|
||||
Shader guiShader;
|
||||
GuiUniforms gu;
|
||||
|
||||
Shader* currentShader;
|
||||
|
||||
GLint currentModelUniform;
|
||||
double elapsedTime = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -8,59 +8,59 @@
|
|||
#include "Texture.h"
|
||||
|
||||
Texture::Texture(const std::string& file) :
|
||||
fileLocation(file) {
|
||||
loadFromFile(this->fileLocation);
|
||||
fileLocation(file) {
|
||||
loadFromFile(this->fileLocation);
|
||||
}
|
||||
|
||||
void Texture::loadFromFile(std::string file) {
|
||||
unsigned char *texData = stbi_load(file.c_str(), &width, &height, &bitDepth, 0);
|
||||
if (!texData) throw std::runtime_error("Failed to find texture at " + file + ".");
|
||||
loadFromBytes(texData, width, height);
|
||||
stbi_image_free(texData);
|
||||
unsigned char* texData = stbi_load(file.c_str(), &width, &height, &bitDepth, 0);
|
||||
if (!texData) throw std::runtime_error("Failed to find texture at " + file + ".");
|
||||
loadFromBytes(texData, width, height);
|
||||
stbi_image_free(texData);
|
||||
}
|
||||
|
||||
void Texture::loadFromBytes(unsigned char* bytes, int width, int height, GLint interpolation, GLint repeatMode) {
|
||||
if (textureID != 0) clear();
|
||||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
|
||||
glGenTextures(1, &textureID);
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, repeatMode);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, repeatMode);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, interpolation);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, interpolation);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bytes);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
//Unbind current texture
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
if (textureID != 0) clear();
|
||||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
|
||||
glGenTextures(1, &textureID);
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, repeatMode);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, repeatMode);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, interpolation);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, interpolation);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bytes);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
//Unbind current texture
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void Texture::updateTexture(int x, int y, int width, int height, unsigned char *bytes) {
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bytes);
|
||||
void Texture::updateTexture(int x, int y, int width, int height, unsigned char* bytes) {
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bytes);
|
||||
}
|
||||
|
||||
|
||||
void Texture::use(GLuint position) {
|
||||
glActiveTexture(GL_TEXTURE0 + position);
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glActiveTexture(GL_TEXTURE0 + position);
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
}
|
||||
|
||||
void Texture::clear() {
|
||||
glDeleteTextures(1, &textureID);
|
||||
textureID = 0;
|
||||
fileLocation = "";
|
||||
|
||||
width = 0;
|
||||
height = 0;
|
||||
bitDepth = 0;
|
||||
glDeleteTextures(1, &textureID);
|
||||
textureID = 0;
|
||||
fileLocation = "";
|
||||
|
||||
width = 0;
|
||||
height = 0;
|
||||
bitDepth = 0;
|
||||
}
|
||||
|
||||
Texture::~Texture() {
|
||||
clear();
|
||||
clear();
|
||||
}
|
|
@ -8,25 +8,30 @@
|
|||
#include <GL/glew.h>
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
Texture() = default;
|
||||
explicit Texture(const std::string& file);
|
||||
|
||||
void loadFromFile(std::string file);
|
||||
void loadFromBytes(unsigned char* bytes, int width, int height, GLint interpolation = GL_NEAREST, GLint repeatMode = GL_CLAMP_TO_EDGE);
|
||||
void updateTexture(int x, int y, int width, int height, unsigned char* bytes);
|
||||
|
||||
void use(GLuint position = 0);
|
||||
void clear();
|
||||
|
||||
~Texture();
|
||||
|
||||
protected:
|
||||
unsigned int textureID = 0;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int bitDepth = 0;
|
||||
|
||||
std::string fileLocation;
|
||||
public:
|
||||
Texture() = default;
|
||||
|
||||
explicit Texture(const std::string& file);
|
||||
|
||||
void loadFromFile(std::string file);
|
||||
|
||||
void loadFromBytes(unsigned char* bytes, int width, int height, GLint interpolation = GL_NEAREST,
|
||||
GLint repeatMode = GL_CLAMP_TO_EDGE);
|
||||
|
||||
void updateTexture(int x, int y, int width, int height, unsigned char* bytes);
|
||||
|
||||
void use(GLuint position = 0);
|
||||
|
||||
void clear();
|
||||
|
||||
~Texture();
|
||||
|
||||
protected:
|
||||
unsigned int textureID = 0;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int bitDepth = 0;
|
||||
|
||||
std::string fileLocation;
|
||||
};
|
||||
|
||||
|
|
|
@ -7,23 +7,23 @@
|
|||
#include "ChunkVertex.h"
|
||||
|
||||
void ChunkMesh::create(const std::vector<ChunkVertex>& vertices, const std::vector<unsigned int>& indices) {
|
||||
indCount = static_cast<GLsizei>(indices.size());
|
||||
|
||||
genArrays(static_cast<unsigned int>(vertices.size() * sizeof(ChunkVertex)),
|
||||
static_cast<unsigned int>(indices.size() * sizeof(unsigned int)),
|
||||
&vertices.front(), &indices.front());
|
||||
|
||||
unsigned int idx = 0;
|
||||
createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(position));
|
||||
createVertexAttrib(idx++, 2, GL_FLOAT, STRIDE_OFFSET_CHUNK(texCoords));
|
||||
createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(blendColor));
|
||||
createVertexAttrib(idx++, 2, GL_FLOAT, STRIDE_OFFSET_CHUNK(blendMaskCoords));
|
||||
createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_CHUNK(normal));
|
||||
createVertexAttrib(idx++, 4, GL_FLOAT, STRIDE_OFFSET_CHUNK(light));
|
||||
createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_CHUNK(shaderMod));
|
||||
createVertexAttrib(idx , 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(modValues));
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
indCount = static_cast<GLsizei>(indices.size());
|
||||
|
||||
genArrays(static_cast<unsigned int>(vertices.size() * sizeof(ChunkVertex)),
|
||||
static_cast<unsigned int>(indices.size() * sizeof(unsigned int)),
|
||||
&vertices.front(), &indices.front());
|
||||
|
||||
unsigned int idx = 0;
|
||||
createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(position));
|
||||
createVertexAttrib(idx++, 2, GL_FLOAT, STRIDE_OFFSET_CHUNK(texCoords));
|
||||
createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(blendColor));
|
||||
createVertexAttrib(idx++, 2, GL_FLOAT, STRIDE_OFFSET_CHUNK(blendMaskCoords));
|
||||
createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_CHUNK(normal));
|
||||
createVertexAttrib(idx++, 4, GL_FLOAT, STRIDE_OFFSET_CHUNK(light));
|
||||
createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_CHUNK(shaderMod));
|
||||
createVertexAttrib(idx, 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(modValues));
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
|
@ -12,11 +12,12 @@
|
|||
class ChunkVertex;
|
||||
|
||||
class ChunkMesh : public Mesh {
|
||||
public:
|
||||
ChunkMesh() = default;
|
||||
ChunkMesh(const ChunkMesh& o) { throw std::runtime_error("No copy constructor for ChunkMeshes"); };
|
||||
|
||||
void create(const std::vector<ChunkVertex>& vertices, const std::vector<unsigned int>& indices);
|
||||
|
||||
~ChunkMesh() = default;
|
||||
public:
|
||||
ChunkMesh() = default;
|
||||
|
||||
ChunkMesh(const ChunkMesh& o) { throw std::runtime_error("No copy constructor for ChunkMeshes"); };
|
||||
|
||||
void create(const std::vector<ChunkVertex>& vertices, const std::vector<unsigned int>& indices);
|
||||
|
||||
~ChunkMesh() = default;
|
||||
};
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <vector>
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
|
||||
#include <glm/gtx/normal.hpp>
|
||||
|
||||
#include "ChunkMeshGenerator.h"
|
||||
|
@ -21,129 +22,141 @@
|
|||
#include "game/atlas/LocalBiomeAtlas.h"
|
||||
#include "game/atlas/LocalDefinitionAtlas.h"
|
||||
|
||||
ChunkMeshGenerator::ChunkMeshGenerator(ChunkMeshDetails* meshDetails, LocalDefinitionAtlas& defs, LocalBiomeAtlas& biomes,
|
||||
std::shared_ptr<Chunk> chunk, std::array<std::shared_ptr<Chunk>, 6> adjacent, std::array<NoiseSample, 3>& blockOffsets) :
|
||||
meshDetails(meshDetails),
|
||||
adjacent(adjacent),
|
||||
biomes(biomes),
|
||||
chunk(chunk),
|
||||
defs(defs) {
|
||||
|
||||
Timer t("Mesh generation");
|
||||
|
||||
meshDetails->vertices.reserve(5000);
|
||||
meshDetails->indices.reserve(7000);
|
||||
|
||||
auto l = chunk->getReadLock();
|
||||
RIE::expand<unsigned int, 4096>(chunk->cGetBlocks(), eBlocks);
|
||||
RIE::expand<unsigned short, 4096>(chunk->cGetBiomes(), eBiomes);
|
||||
l.unlock();
|
||||
|
||||
BlockDef* block = nullptr;
|
||||
BiomeDef* biome = nullptr;
|
||||
|
||||
for (unsigned short i = 0; i < 4096; i++) {
|
||||
if (!block || block->index != eBlocks[i]) block = &defs.blockFromId(eBlocks[i]);
|
||||
if (!biome || biome->index != eBiomes[i]) biome = &biomes.biomeFromId(eBiomes[i]);
|
||||
|
||||
BlockModel& model = block->model;
|
||||
glm::vec3 biomeTint = biome->tint;
|
||||
|
||||
if (!model.visible) continue;
|
||||
|
||||
glm::ivec3 off = Space::Block::fromIndex(i);
|
||||
glm::vec3 vis = off;
|
||||
|
||||
for (auto& mod : model.meshMods) {
|
||||
switch (mod.first) {
|
||||
default: break;
|
||||
case MeshMod::OFFSET_X: vis.x += blockOffsets[0].get(vis / 16.f) * mod.second; break;
|
||||
case MeshMod::OFFSET_Y: vis.y += blockOffsets[1].get(vis / 16.f) * mod.second; break;
|
||||
case MeshMod::OFFSET_Z: vis.z += blockOffsets[2].get(vis / 16.f) * mod.second; break;
|
||||
}
|
||||
}
|
||||
|
||||
glm::ivec3 pos = { off.x - 1, off.y, off.z };
|
||||
if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast<int>(EVec::XNEG)], biomeTint, getLightAt(pos));
|
||||
pos = { off.x + 1, off.y, off.z };
|
||||
if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast<int>(EVec::XPOS)], biomeTint, getLightAt(pos));
|
||||
pos = { off.x, off.y - 1, off.z };
|
||||
if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast<int>(EVec::YNEG)], biomeTint, getLightAt(pos));
|
||||
pos = { off.x, off.y + 1, off.z };
|
||||
if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast<int>(EVec::YPOS)], biomeTint, getLightAt(pos));
|
||||
pos = { off.x, off.y, off.z - 1 };
|
||||
if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast<int>(EVec::ZNEG)], biomeTint, getLightAt(pos));
|
||||
pos = { off.x, off.y, off.z + 1 };
|
||||
if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast<int>(EVec::ZPOS)], biomeTint, getLightAt(pos));
|
||||
|
||||
addFaces(vis, model.parts[static_cast<int>(EVec::NO_CULL)], biomeTint, getLightAt(vis));
|
||||
}
|
||||
|
||||
meshDetails->vertices.shrink_to_fit();
|
||||
meshDetails->indices.shrink_to_fit();
|
||||
ChunkMeshGenerator::ChunkMeshGenerator(ChunkMeshDetails* meshDetails, LocalDefinitionAtlas& defs,
|
||||
LocalBiomeAtlas& biomes,
|
||||
std::shared_ptr<Chunk> chunk, std::array<std::shared_ptr<Chunk>, 6> adjacent,
|
||||
std::array<NoiseSample, 3>& blockOffsets) :
|
||||
meshDetails(meshDetails),
|
||||
adjacent(adjacent),
|
||||
biomes(biomes),
|
||||
chunk(chunk),
|
||||
defs(defs) {
|
||||
|
||||
Timer t("Mesh generation");
|
||||
|
||||
meshDetails->vertices.reserve(5000);
|
||||
meshDetails->indices.reserve(7000);
|
||||
|
||||
auto l = chunk->getReadLock();
|
||||
RIE::expand<unsigned int, 4096>(chunk->cGetBlocks(), eBlocks);
|
||||
RIE::expand<unsigned short, 4096>(chunk->cGetBiomes(), eBiomes);
|
||||
l.unlock();
|
||||
|
||||
BlockDef* block = nullptr;
|
||||
BiomeDef* biome = nullptr;
|
||||
|
||||
for (unsigned short i = 0; i < 4096; i++) {
|
||||
if (!block || block->index != eBlocks[i]) block = &defs.blockFromId(eBlocks[i]);
|
||||
if (!biome || biome->index != eBiomes[i]) biome = &biomes.biomeFromId(eBiomes[i]);
|
||||
|
||||
BlockModel& model = block->model;
|
||||
glm::vec3 biomeTint = biome->tint;
|
||||
|
||||
if (!model.visible) continue;
|
||||
|
||||
glm::ivec3 off = Space::Block::fromIndex(i);
|
||||
glm::vec3 vis = off;
|
||||
|
||||
for (auto& mod : model.meshMods) {
|
||||
switch (mod.first) {
|
||||
default: break;
|
||||
case MeshMod::OFFSET_X: vis.x += blockOffsets[0].get(vis / 16.f) * mod.second;
|
||||
break;
|
||||
case MeshMod::OFFSET_Y: vis.y += blockOffsets[1].get(vis / 16.f) * mod.second;
|
||||
break;
|
||||
case MeshMod::OFFSET_Z: vis.z += blockOffsets[2].get(vis / 16.f) * mod.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
glm::ivec3 pos = { off.x - 1, off.y, off.z };
|
||||
if (!getBlockAt(pos).culls)
|
||||
addFaces(vis, model.parts[static_cast<int>(EVec::XNEG)], biomeTint, getLightAt(pos));
|
||||
pos = { off.x + 1, off.y, off.z };
|
||||
if (!getBlockAt(pos).culls)
|
||||
addFaces(vis, model.parts[static_cast<int>(EVec::XPOS)], biomeTint, getLightAt(pos));
|
||||
pos = { off.x, off.y - 1, off.z };
|
||||
if (!getBlockAt(pos).culls)
|
||||
addFaces(vis, model.parts[static_cast<int>(EVec::YNEG)], biomeTint, getLightAt(pos));
|
||||
pos = { off.x, off.y + 1, off.z };
|
||||
if (!getBlockAt(pos).culls)
|
||||
addFaces(vis, model.parts[static_cast<int>(EVec::YPOS)], biomeTint, getLightAt(pos));
|
||||
pos = { off.x, off.y, off.z - 1 };
|
||||
if (!getBlockAt(pos).culls)
|
||||
addFaces(vis, model.parts[static_cast<int>(EVec::ZNEG)], biomeTint, getLightAt(pos));
|
||||
pos = { off.x, off.y, off.z + 1 };
|
||||
if (!getBlockAt(pos).culls)
|
||||
addFaces(vis, model.parts[static_cast<int>(EVec::ZPOS)], biomeTint, getLightAt(pos));
|
||||
|
||||
addFaces(vis, model.parts[static_cast<int>(EVec::NO_CULL)], biomeTint, getLightAt(vis));
|
||||
}
|
||||
|
||||
meshDetails->vertices.shrink_to_fit();
|
||||
meshDetails->indices.shrink_to_fit();
|
||||
|
||||
// t.printElapsedMs();
|
||||
}
|
||||
|
||||
BlockDef& ChunkMeshGenerator::getBlockAt(const glm::ivec3& pos) {
|
||||
glm::ivec3 dir = {(pos.x < 0 ? -1 : pos.x > 15 ? 1 : 0),
|
||||
(pos.y < 0 ? -1 : pos.y > 15 ? 1 : 0), (pos.z < 0 ? -1 : pos.z > 15 ? 1 : 0)};
|
||||
|
||||
if (dir != glm::ivec3 {0, 0, 0}) {
|
||||
unsigned int ind = static_cast<unsigned int>(Vec::TO_ENUM.at(dir));
|
||||
auto& chunk = adjacent[ind];
|
||||
return defs.blockFromId(chunk->getBlock(Space::Block::index(pos - dir * 16)));
|
||||
}
|
||||
|
||||
return defs.blockFromId(eBlocks[Space::Block::index(pos)]);
|
||||
glm::ivec3 dir = { (pos.x < 0 ? -1 : pos.x > 15 ? 1 : 0),
|
||||
(pos.y < 0 ? -1 : pos.y > 15 ? 1 : 0), (pos.z < 0 ? -1 : pos.z > 15 ? 1 : 0) };
|
||||
|
||||
if (dir != glm::ivec3{ 0, 0, 0 }) {
|
||||
unsigned int ind = static_cast<unsigned int>(Vec::TO_ENUM.at(dir));
|
||||
auto& chunk = adjacent[ind];
|
||||
return defs.blockFromId(chunk->getBlock(Space::Block::index(pos - dir * 16)));
|
||||
}
|
||||
|
||||
return defs.blockFromId(eBlocks[Space::Block::index(pos)]);
|
||||
}
|
||||
|
||||
glm::vec4 ChunkMeshGenerator::getLightAt(const glm::ivec3& pos) {
|
||||
glm::ivec3 dir = {(pos.x < 0 ? -1 : pos.x > 15 ? 1 : 0),
|
||||
(pos.y < 0 ? -1 : pos.y > 15 ? 1 : 0), (pos.z < 0 ? -1 : pos.z > 15 ? 1 : 0)};
|
||||
|
||||
if (dir != glm::ivec3 {0, 0, 0}) {
|
||||
unsigned int ind = static_cast<unsigned int>(Vec::TO_ENUM.at(dir));
|
||||
auto& chunk = adjacent[ind];
|
||||
return chunk->getLight(Space::Block::index(pos - dir * 16));
|
||||
}
|
||||
|
||||
return chunk->getLight(Space::Block::index(pos));
|
||||
glm::ivec3 dir = { (pos.x < 0 ? -1 : pos.x > 15 ? 1 : 0),
|
||||
(pos.y < 0 ? -1 : pos.y > 15 ? 1 : 0), (pos.z < 0 ? -1 : pos.z > 15 ? 1 : 0) };
|
||||
|
||||
if (dir != glm::ivec3{ 0, 0, 0 }) {
|
||||
unsigned int ind = static_cast<unsigned int>(Vec::TO_ENUM.at(dir));
|
||||
auto& chunk = adjacent[ind];
|
||||
return chunk->getLight(Space::Block::index(pos - dir * 16));
|
||||
}
|
||||
|
||||
return chunk->getLight(Space::Block::index(pos));
|
||||
}
|
||||
|
||||
void ChunkMeshGenerator::addFaces(const glm::vec3 &offset, const std::vector<MeshPart> &meshParts, const glm::vec3& tint, glm::vec4 light) {
|
||||
for (const MeshPart& mp : meshParts) {
|
||||
glm::vec3 modData = {};
|
||||
|
||||
switch (mp.shaderMod) {
|
||||
default: break;
|
||||
|
||||
case ShaderMod::ROTATE_X:
|
||||
case ShaderMod::ROTATE_Y:
|
||||
case ShaderMod::ROTATE_Z:
|
||||
case ShaderMod::SWAY_ATTACHED:
|
||||
case ShaderMod::SWAY_FULL_BLOCK:
|
||||
modData = { Util::packFloat((offset - 8.f) / 8.f), mp.modValue, 0 };
|
||||
break;
|
||||
}
|
||||
|
||||
for (const BlockModelVertex &vertex : mp.vertices) {
|
||||
meshDetails->vertices.push_back({
|
||||
vertex.pos + offset,
|
||||
vertex.tex,
|
||||
mp.blendInd ? tint : glm::vec3 {1, 1, 1},
|
||||
mp.blendInd ? vertex.blendMask : glm::vec2 {-1, -1},
|
||||
Util::packFloat(vertex.nml),
|
||||
glm::vec4(light),
|
||||
static_cast<float>(mp.shaderMod),
|
||||
modData
|
||||
});
|
||||
}
|
||||
|
||||
for (unsigned int index : mp.indices) {
|
||||
meshDetails->indices.push_back(indOffset + index);
|
||||
}
|
||||
|
||||
indOffset += mp.vertices.size();
|
||||
}
|
||||
void
|
||||
ChunkMeshGenerator::addFaces(const glm::vec3& offset, const std::vector<MeshPart>& meshParts, const glm::vec3& tint,
|
||||
glm::vec4 light) {
|
||||
for (const MeshPart& mp : meshParts) {
|
||||
glm::vec3 modData = {};
|
||||
|
||||
switch (mp.shaderMod) {
|
||||
default: break;
|
||||
|
||||
case ShaderMod::ROTATE_X:
|
||||
case ShaderMod::ROTATE_Y:
|
||||
case ShaderMod::ROTATE_Z:
|
||||
case ShaderMod::SWAY_ATTACHED:
|
||||
case ShaderMod::SWAY_FULL_BLOCK:modData = { Util::packFloat((offset - 8.f) / 8.f), mp.modValue, 0 };
|
||||
break;
|
||||
}
|
||||
|
||||
for (const BlockModelVertex& vertex : mp.vertices) {
|
||||
meshDetails->vertices.push_back({
|
||||
vertex.pos + offset,
|
||||
vertex.tex,
|
||||
mp.blendInd ? tint : glm::vec3{ 1, 1, 1 },
|
||||
mp.blendInd ? vertex.blendMask : glm::vec2{ -1, -1 },
|
||||
Util::packFloat(vertex.nml),
|
||||
glm::vec4(light),
|
||||
static_cast<float>(mp.shaderMod),
|
||||
modData
|
||||
});
|
||||
}
|
||||
|
||||
for (unsigned int index : mp.indices) {
|
||||
meshDetails->indices.push_back(indOffset + index);
|
||||
}
|
||||
|
||||
indOffset += mp.vertices.size();
|
||||
}
|
||||
}
|
|
@ -9,33 +9,42 @@
|
|||
#include <memory>
|
||||
|
||||
class Chunk;
|
||||
|
||||
class MeshPart;
|
||||
|
||||
class BlockDef;
|
||||
|
||||
class NoiseSample;
|
||||
|
||||
class LocalBiomeAtlas;
|
||||
|
||||
class ChunkMeshDetails;
|
||||
|
||||
class LocalDefinitionAtlas;
|
||||
|
||||
class ChunkMeshGenerator {
|
||||
public:
|
||||
ChunkMeshGenerator(ChunkMeshDetails* meshDetails, LocalDefinitionAtlas& defs, LocalBiomeAtlas& biomes,
|
||||
std::shared_ptr<Chunk> chunk, std::array<std::shared_ptr<Chunk>, 6> adjacent,
|
||||
std::array<NoiseSample, 3>& blockOffsets);
|
||||
private:
|
||||
inline BlockDef& getBlockAt(const glm::ivec3& pos);
|
||||
inline glm::vec4 getLightAt(const glm::ivec3& pos);
|
||||
|
||||
void addFaces(const glm::vec3 &offset, const std::vector<MeshPart> &meshParts, const glm::vec3& tint, glm::vec4 light);
|
||||
|
||||
LocalDefinitionAtlas& defs;
|
||||
LocalBiomeAtlas& biomes;
|
||||
|
||||
unsigned int indOffset = 0;
|
||||
ChunkMeshDetails* meshDetails;
|
||||
|
||||
std::shared_ptr<Chunk> chunk;
|
||||
std::array<std::shared_ptr<Chunk>, 6> adjacent;
|
||||
|
||||
std::array<unsigned int, 4096> eBlocks;
|
||||
std::array<unsigned short, 4096> eBiomes;
|
||||
public:
|
||||
ChunkMeshGenerator(ChunkMeshDetails* meshDetails, LocalDefinitionAtlas& defs, LocalBiomeAtlas& biomes,
|
||||
std::shared_ptr<Chunk> chunk, std::array<std::shared_ptr<Chunk>, 6> adjacent,
|
||||
std::array<NoiseSample, 3>& blockOffsets);
|
||||
|
||||
private:
|
||||
inline BlockDef& getBlockAt(const glm::ivec3& pos);
|
||||
|
||||
inline glm::vec4 getLightAt(const glm::ivec3& pos);
|
||||
|
||||
void
|
||||
addFaces(const glm::vec3& offset, const std::vector<MeshPart>& meshParts, const glm::vec3& tint, glm::vec4 light);
|
||||
|
||||
LocalDefinitionAtlas& defs;
|
||||
LocalBiomeAtlas& biomes;
|
||||
|
||||
unsigned int indOffset = 0;
|
||||
ChunkMeshDetails* meshDetails;
|
||||
|
||||
std::shared_ptr<Chunk> chunk;
|
||||
std::array<std::shared_ptr<Chunk>, 6> adjacent;
|
||||
|
||||
std::array<unsigned int, 4096> eBlocks;
|
||||
std::array<unsigned short, 4096> eBiomes;
|
||||
};
|
|
@ -9,10 +9,12 @@
|
|||
class Renderer;
|
||||
|
||||
struct ChunkRenderElem {
|
||||
virtual void draw(Renderer& renderer) = 0;
|
||||
virtual glm::vec3 getPos() = 0;
|
||||
// Used to determine if the RenderElem should be deleted.
|
||||
// Bool is if the RenderElem should be kept alive.
|
||||
// True = keep, False = remove
|
||||
virtual bool updateChunkUse(glm::vec3 chunk, bool used) = 0;
|
||||
virtual void draw(Renderer& renderer) = 0;
|
||||
|
||||
virtual glm::vec3 getPos() = 0;
|
||||
|
||||
// Used to determine if the RenderElem should be deleted.
|
||||
// Bool is if the RenderElem should be kept alive.
|
||||
// True = keep, False = remove
|
||||
virtual bool updateChunkUse(glm::vec3 chunk, bool used) = 0;
|
||||
};
|
||||
|
|
|
@ -9,14 +9,14 @@
|
|||
#include <glm/vec4.hpp>
|
||||
|
||||
struct ChunkVertex {
|
||||
glm::vec3 position;
|
||||
glm::vec2 texCoords;
|
||||
glm::vec3 blendColor;
|
||||
glm::vec2 blendMaskCoords;
|
||||
float normal;
|
||||
glm::vec4 light;
|
||||
float shaderMod;
|
||||
glm::vec3 modValues;
|
||||
glm::vec3 position;
|
||||
glm::vec2 texCoords;
|
||||
glm::vec3 blendColor;
|
||||
glm::vec2 blendMaskCoords;
|
||||
float normal;
|
||||
glm::vec4 light;
|
||||
float shaderMod;
|
||||
glm::vec3 modValues;
|
||||
};
|
||||
|
||||
#define STRIDE_OFFSET_CHUNK(m) sizeof(struct ChunkVertex), (void *)offsetof(struct ChunkVertex, m)
|
||||
|
|
|
@ -4,38 +4,38 @@
|
|||
|
||||
#include "EntityMesh.h"
|
||||
|
||||
EntityMesh::EntityMesh(const EntityMesh &o) :
|
||||
vertices(o.vertices),
|
||||
indices(o.indices) {
|
||||
this->indCount = o.indCount;
|
||||
if (indCount > 0) initModel();
|
||||
EntityMesh::EntityMesh(const EntityMesh& o) :
|
||||
vertices(o.vertices),
|
||||
indices(o.indices) {
|
||||
this->indCount = o.indCount;
|
||||
if (indCount > 0) initModel();
|
||||
}
|
||||
|
||||
void EntityMesh::create(const std::vector<EntityVertex>& vertices, const std::vector<unsigned int>& indices) {
|
||||
indCount = static_cast<GLsizei>(indices.size());
|
||||
this->vertices = vertices;
|
||||
this->indices = indices;
|
||||
|
||||
initModel();
|
||||
indCount = static_cast<GLsizei>(indices.size());
|
||||
this->vertices = vertices;
|
||||
this->indices = indices;
|
||||
|
||||
initModel();
|
||||
}
|
||||
|
||||
void EntityMesh::initModel() {
|
||||
if (vertices.size() == 0) return;
|
||||
|
||||
genArrays(static_cast<unsigned int>(vertices.size() * sizeof(EntityVertex)),
|
||||
static_cast<unsigned int>(indices.size() * sizeof(unsigned int)),
|
||||
&vertices.front(), &indices.front());
|
||||
|
||||
unsigned int idx = 0;
|
||||
createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_ENTITY(position));
|
||||
createVertexAttrib(idx++, 4, GL_FLOAT, STRIDE_OFFSET_ENTITY(colorData));
|
||||
createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_ENTITY(colorBlend));
|
||||
createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_ENTITY(useTex));
|
||||
createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_ENTITY(normal));
|
||||
createVertexAttrib(idx++, 4, GL_INT, STRIDE_OFFSET_ENTITY(boneIDs));
|
||||
createVertexAttrib(idx , 4, GL_FLOAT, STRIDE_OFFSET_ENTITY(boneWeights));
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
if (vertices.size() == 0) return;
|
||||
|
||||
genArrays(static_cast<unsigned int>(vertices.size() * sizeof(EntityVertex)),
|
||||
static_cast<unsigned int>(indices.size() * sizeof(unsigned int)),
|
||||
&vertices.front(), &indices.front());
|
||||
|
||||
unsigned int idx = 0;
|
||||
createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_ENTITY(position));
|
||||
createVertexAttrib(idx++, 4, GL_FLOAT, STRIDE_OFFSET_ENTITY(colorData));
|
||||
createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_ENTITY(colorBlend));
|
||||
createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_ENTITY(useTex));
|
||||
createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_ENTITY(normal));
|
||||
createVertexAttrib(idx++, 4, GL_INT, STRIDE_OFFSET_ENTITY(boneIDs));
|
||||
createVertexAttrib(idx, 4, GL_FLOAT, STRIDE_OFFSET_ENTITY(boneWeights));
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
|
@ -11,14 +11,18 @@
|
|||
#include "EntityVertex.h"
|
||||
|
||||
class EntityMesh : public Mesh {
|
||||
public:
|
||||
EntityMesh() = default;
|
||||
EntityMesh(const EntityMesh& o);
|
||||
void create(const std::vector<EntityVertex>& vertices, const std::vector<unsigned int>& indices);
|
||||
~EntityMesh() = default;
|
||||
private:
|
||||
void initModel();
|
||||
|
||||
std::vector<EntityVertex> vertices {};
|
||||
std::vector<unsigned int> indices {};
|
||||
public:
|
||||
EntityMesh() = default;
|
||||
|
||||
EntityMesh(const EntityMesh& o);
|
||||
|
||||
void create(const std::vector<EntityVertex>& vertices, const std::vector<unsigned int>& indices);
|
||||
|
||||
~EntityMesh() = default;
|
||||
|
||||
private:
|
||||
void initModel();
|
||||
|
||||
std::vector<EntityVertex> vertices{};
|
||||
std::vector<unsigned int> indices{};
|
||||
};
|
||||
|
|
|
@ -8,19 +8,20 @@
|
|||
#include <glm/vec4.hpp>
|
||||
|
||||
class EntityVertex {
|
||||
public:
|
||||
EntityVertex() = default;
|
||||
EntityVertex(glm::vec3 position, glm::vec4 colorData, glm::vec3 colorBlend, float useTex, glm::vec3 normal,
|
||||
glm::ivec4 boneIDs, glm::vec4 boneWeights) : position(position), colorData(colorData),
|
||||
colorBlend(colorBlend), useTex(useTex), normal(normal), boneIDs(boneIDs), boneWeights(boneWeights) {};
|
||||
|
||||
glm::vec3 position {};
|
||||
glm::vec4 colorData {};
|
||||
glm::vec3 colorBlend {};
|
||||
float useTex = false;
|
||||
glm::vec3 normal {};
|
||||
glm::ivec4 boneIDs {};
|
||||
glm::vec4 boneWeights {};
|
||||
public:
|
||||
EntityVertex() = default;
|
||||
|
||||
EntityVertex(glm::vec3 position, glm::vec4 colorData, glm::vec3 colorBlend, float useTex, glm::vec3 normal,
|
||||
glm::ivec4 boneIDs, glm::vec4 boneWeights) : position(position), colorData(colorData),
|
||||
colorBlend(colorBlend), useTex(useTex), normal(normal), boneIDs(boneIDs), boneWeights(boneWeights) {};
|
||||
|
||||
glm::vec3 position{};
|
||||
glm::vec4 colorData{};
|
||||
glm::vec3 colorBlend{};
|
||||
float useTex = false;
|
||||
glm::vec3 normal{};
|
||||
glm::ivec4 boneIDs{};
|
||||
glm::vec4 boneWeights{};
|
||||
};
|
||||
|
||||
#define STRIDE_OFFSET_ENTITY(m) sizeof(struct EntityVertex), (void *)offsetof(struct EntityVertex, m)
|
||||
|
|
|
@ -5,44 +5,44 @@
|
|||
#include "Mesh.h"
|
||||
|
||||
void Mesh::cleanup() {
|
||||
if (VAO != 0) glDeleteVertexArrays(1, &VAO);
|
||||
if (VBO != 0) glDeleteBuffers(1, &VBO);
|
||||
if (IBO != 0) glDeleteBuffers(1, &IBO);
|
||||
|
||||
IBO = 0;
|
||||
VBO = 0;
|
||||
VAO = 0;
|
||||
indCount = 0;
|
||||
if (VAO != 0) glDeleteVertexArrays(1, &VAO);
|
||||
if (VBO != 0) glDeleteBuffers(1, &VBO);
|
||||
if (IBO != 0) glDeleteBuffers(1, &IBO);
|
||||
|
||||
IBO = 0;
|
||||
VBO = 0;
|
||||
VAO = 0;
|
||||
indCount = 0;
|
||||
}
|
||||
|
||||
void Mesh::genArrays(GLuint vboLength, GLuint iboLength, const void *verticesPtr, const void *indicesPtr) {
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
glGenBuffers(1, &IBO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, iboLength, indicesPtr, GL_STATIC_DRAW);
|
||||
|
||||
glGenBuffers(1, &VBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, vboLength, verticesPtr, GL_STATIC_DRAW);
|
||||
void Mesh::genArrays(GLuint vboLength, GLuint iboLength, const void* verticesPtr, const void* indicesPtr) {
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
glGenBuffers(1, &IBO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, iboLength, indicesPtr, GL_STATIC_DRAW);
|
||||
|
||||
glGenBuffers(1, &VBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, vboLength, verticesPtr, GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
void Mesh::createVertexAttrib(GLuint offset, GLuint size, GLenum type, GLsizei stride, const void *pointer) {
|
||||
glEnableVertexAttribArray(offset);
|
||||
if (type == GL_INT)
|
||||
glVertexAttribIPointer(offset, size, type, stride, pointer);
|
||||
else
|
||||
glVertexAttribPointer(offset, size, type, GL_FALSE, stride, pointer);
|
||||
void Mesh::createVertexAttrib(GLuint offset, GLuint size, GLenum type, GLsizei stride, const void* pointer) {
|
||||
glEnableVertexAttribArray(offset);
|
||||
if (type == GL_INT)
|
||||
glVertexAttribIPointer(offset, size, type, stride, pointer);
|
||||
else
|
||||
glVertexAttribPointer(offset, size, type, GL_FALSE, stride, pointer);
|
||||
}
|
||||
|
||||
void Mesh::draw() const {
|
||||
glBindVertexArray(VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, indCount, GL_UNSIGNED_INT, nullptr);
|
||||
glBindVertexArray(VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, indCount, GL_UNSIGNED_INT, nullptr);
|
||||
}
|
||||
|
||||
Mesh::~Mesh() {
|
||||
cleanup();
|
||||
cleanup();
|
||||
}
|
|
@ -7,19 +7,22 @@
|
|||
#include <GL/glew.h>
|
||||
|
||||
class Mesh {
|
||||
public:
|
||||
Mesh() = default;
|
||||
|
||||
void cleanup();
|
||||
virtual void draw() const;
|
||||
|
||||
~Mesh();
|
||||
protected:
|
||||
void genArrays(GLuint vboLength, GLuint iboLength, const void* verticesPtr, const void* indicesPtr);
|
||||
void createVertexAttrib(GLuint offset, GLuint size, GLenum type, GLsizei stride, const void* pointer);
|
||||
|
||||
GLuint VAO = 0;
|
||||
GLuint VBO = 0;
|
||||
GLuint IBO = 0;
|
||||
GLsizei indCount = 0;
|
||||
public:
|
||||
Mesh() = default;
|
||||
|
||||
void cleanup();
|
||||
|
||||
virtual void draw() const;
|
||||
|
||||
~Mesh();
|
||||
|
||||
protected:
|
||||
void genArrays(GLuint vboLength, GLuint iboLength, const void* verticesPtr, const void* indicesPtr);
|
||||
|
||||
void createVertexAttrib(GLuint offset, GLuint size, GLenum type, GLsizei stride, const void* pointer);
|
||||
|
||||
GLuint VAO = 0;
|
||||
GLuint VBO = 0;
|
||||
GLuint IBO = 0;
|
||||
GLsizei indCount = 0;
|
||||
};
|
||||
|
|
|
@ -10,26 +10,26 @@
|
|||
#include "client/graph/Renderer.h"
|
||||
#include "client/graph/mesh/ChunkMesh.h"
|
||||
|
||||
void MeshChunk::create(std::vector<ChunkVertex> &vertices, std::vector<unsigned int> &indices) {
|
||||
this->mesh = std::make_shared<ChunkMesh>();
|
||||
mesh->create(vertices, indices);
|
||||
void MeshChunk::create(std::vector<ChunkVertex>& vertices, std::vector<unsigned int>& indices) {
|
||||
this->mesh = std::make_shared<ChunkMesh>();
|
||||
mesh->create(vertices, indices);
|
||||
}
|
||||
|
||||
void MeshChunk::draw(Renderer& renderer) {
|
||||
glm::mat4 model = glm::mat4(1.0);
|
||||
model = glm::translate(model, pos * static_cast<float>(16));
|
||||
renderer.setModelMatrix(model);
|
||||
mesh->draw();
|
||||
glm::mat4 model = glm::mat4(1.0);
|
||||
model = glm::translate(model, pos * static_cast<float>(16));
|
||||
renderer.setModelMatrix(model);
|
||||
mesh->draw();
|
||||
}
|
||||
|
||||
void MeshChunk::setPos(glm::vec3 pos) {
|
||||
this->pos = pos;
|
||||
this->pos = pos;
|
||||
}
|
||||
|
||||
glm::vec3 MeshChunk::getPos() {
|
||||
return pos;
|
||||
return pos;
|
||||
}
|
||||
|
||||
bool MeshChunk::updateChunkUse(glm::vec3 pos, bool used) {
|
||||
return used;
|
||||
return used;
|
||||
}
|
|
@ -11,19 +11,24 @@
|
|||
#include "client/graph/Drawable.h"
|
||||
|
||||
class ChunkMesh;
|
||||
|
||||
class ChunkVertex;
|
||||
|
||||
class MeshChunk : public ChunkRenderElem, Drawable {
|
||||
public:
|
||||
MeshChunk() = default;
|
||||
void create(std::vector<ChunkVertex> &vertices, std::vector<unsigned int> &indices);
|
||||
void draw(Renderer& renderer) override;
|
||||
|
||||
bool updateChunkUse(glm::vec3 chunk, bool used) override;
|
||||
|
||||
void setPos(glm::vec3 pos);
|
||||
glm::vec3 getPos() override;
|
||||
private:
|
||||
std::shared_ptr<ChunkMesh> mesh = nullptr;
|
||||
glm::vec3 pos {};
|
||||
public:
|
||||
MeshChunk() = default;
|
||||
|
||||
void create(std::vector<ChunkVertex>& vertices, std::vector<unsigned int>& indices);
|
||||
|
||||
void draw(Renderer& renderer) override;
|
||||
|
||||
bool updateChunkUse(glm::vec3 chunk, bool used) override;
|
||||
|
||||
void setPos(glm::vec3 pos);
|
||||
|
||||
glm::vec3 getPos() override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<ChunkMesh> mesh = nullptr;
|
||||
glm::vec3 pos{};
|
||||
};
|
|
@ -5,32 +5,34 @@
|
|||
#include "BlurShader.h"
|
||||
|
||||
BlurShader::BlurShader(glm::ivec2 windowSize, float bufferScale) : Shader(),
|
||||
windowSize(windowSize),
|
||||
bufferScale(bufferScale) {}
|
||||
windowSize(windowSize),
|
||||
bufferScale(bufferScale) {}
|
||||
|
||||
void BlurShader::postCreate() {
|
||||
uniforms.sampleScale = get("sampleScale");
|
||||
|
||||
use();
|
||||
set(uniforms.sampleScale, 1.f);
|
||||
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glGenTextures(1, &colorBuffer);
|
||||
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast<int>(windowSize.x * bufferScale), static_cast<int>(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
uniforms.sampleScale = get("sampleScale");
|
||||
|
||||
use();
|
||||
set(uniforms.sampleScale, 1.f);
|
||||
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glGenTextures(1, &colorBuffer);
|
||||
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast<int>(windowSize.x * bufferScale),
|
||||
static_cast<int>(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void BlurShader::windowResized(glm::ivec2 windowSize) {
|
||||
this->windowSize = windowSize;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast<int>(windowSize.x * bufferScale), static_cast<int>(windowSize.y * bufferScale), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
this->windowSize = windowSize;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast<int>(windowSize.x * bufferScale),
|
||||
static_cast<int>(windowSize.y * bufferScale), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
|
@ -9,22 +9,23 @@
|
|||
#include "Shader.h"
|
||||
|
||||
class BlurShader : public Shader {
|
||||
public:
|
||||
explicit BlurShader(glm::ivec2 windowSize, float bufferScale);
|
||||
void postCreate() override;
|
||||
|
||||
void windowResized(glm::ivec2 windowSize);
|
||||
|
||||
struct Uniforms {
|
||||
GLint sampleScale;
|
||||
};
|
||||
|
||||
Uniforms uniforms {};
|
||||
|
||||
unsigned int fbo = 0;
|
||||
unsigned int colorBuffer = 0;
|
||||
|
||||
private:
|
||||
glm::ivec2 windowSize {};
|
||||
float bufferScale = 1;
|
||||
public:
|
||||
explicit BlurShader(glm::ivec2 windowSize, float bufferScale);
|
||||
|
||||
void postCreate() override;
|
||||
|
||||
void windowResized(glm::ivec2 windowSize);
|
||||
|
||||
struct Uniforms {
|
||||
GLint sampleScale;
|
||||
};
|
||||
|
||||
Uniforms uniforms{};
|
||||
|
||||
unsigned int fbo = 0;
|
||||
unsigned int colorBuffer = 0;
|
||||
|
||||
private:
|
||||
glm::ivec2 windowSize{};
|
||||
float bufferScale = 1;
|
||||
};
|
||||
|
|
|
@ -5,15 +5,15 @@
|
|||
#include "EntityGeometryShader.h"
|
||||
|
||||
EntityGeometryShader::EntityGeometryShader(glm::ivec2 windowSize, float bufferScale) : Shader(),
|
||||
windowSize(windowSize),
|
||||
bufferScale(bufferScale) {}
|
||||
windowSize(windowSize),
|
||||
bufferScale(bufferScale) {}
|
||||
|
||||
void EntityGeometryShader::postCreate() {
|
||||
uniforms.proj = get("projection");
|
||||
uniforms.model = get("model");
|
||||
uniforms.view = get("view");
|
||||
|
||||
uniforms.bones = get("uBones");
|
||||
uniforms.proj = get("projection");
|
||||
uniforms.model = get("model");
|
||||
uniforms.view = get("view");
|
||||
|
||||
uniforms.bones = get("uBones");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -9,21 +9,22 @@
|
|||
#include "Shader.h"
|
||||
|
||||
class EntityGeometryShader : public Shader {
|
||||
public:
|
||||
explicit EntityGeometryShader(glm::ivec2 windowSize, float bufferScale);
|
||||
void postCreate() override;
|
||||
|
||||
struct Uniforms {
|
||||
GLint proj;
|
||||
GLint model;
|
||||
GLint view;
|
||||
|
||||
GLint bones;
|
||||
};
|
||||
|
||||
Uniforms uniforms {};
|
||||
|
||||
private:
|
||||
glm::ivec2 windowSize {};
|
||||
float bufferScale = 1;
|
||||
public:
|
||||
explicit EntityGeometryShader(glm::ivec2 windowSize, float bufferScale);
|
||||
|
||||
void postCreate() override;
|
||||
|
||||
struct Uniforms {
|
||||
GLint proj;
|
||||
GLint model;
|
||||
GLint view;
|
||||
|
||||
GLint bones;
|
||||
};
|
||||
|
||||
Uniforms uniforms{};
|
||||
|
||||
private:
|
||||
glm::ivec2 windowSize{};
|
||||
float bufferScale = 1;
|
||||
};
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
#include <glm/mat4x4.hpp>
|
||||
|
||||
struct GuiUniforms {
|
||||
glm::mat4 matrix;
|
||||
|
||||
GLint ortho;
|
||||
GLint model;
|
||||
|
||||
GLint bones;
|
||||
GLint clipBounds;
|
||||
glm::mat4 matrix;
|
||||
|
||||
GLint ortho;
|
||||
GLint model;
|
||||
|
||||
GLint bones;
|
||||
GLint clipBounds;
|
||||
};
|
||||
|
|
|
@ -7,94 +7,102 @@
|
|||
#include "LightingShader.h"
|
||||
|
||||
LightingShader::LightingShader(glm::ivec2 windowSize, float bufferScale) : Shader(),
|
||||
windowSize(windowSize),
|
||||
bufferScale(bufferScale) {}
|
||||
windowSize(windowSize),
|
||||
bufferScale(bufferScale) {}
|
||||
|
||||
void LightingShader::postCreate() {
|
||||
uniforms.gPosition = get("gPosition");
|
||||
uniforms.gNormal = get("gNormal");
|
||||
uniforms.gColorSpec = get("gColorSpec");
|
||||
uniforms.ssaoSampler = get("ssaoSampler");
|
||||
uniforms.camPosition = get("camPosition");
|
||||
|
||||
use();
|
||||
set(uniforms.gPosition, 0);
|
||||
set(uniforms.gNormal, 1);
|
||||
set(uniforms.gColorSpec, 2);
|
||||
set(uniforms.ssaoSampler, 3);
|
||||
|
||||
glGenFramebuffers(1, &gBuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
|
||||
|
||||
glGenTextures(1, &gPosition);
|
||||
glBindTexture(GL_TEXTURE_2D, gPosition);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, static_cast<int>(windowSize.x * bufferScale), static_cast<int>(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0);
|
||||
|
||||
glGenTextures(1, &gNormal);
|
||||
glBindTexture(GL_TEXTURE_2D, gNormal);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, static_cast<int>(windowSize.x * bufferScale), static_cast<int>(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0);
|
||||
|
||||
glGenTextures(1, &gColorSpec);
|
||||
glBindTexture(GL_TEXTURE_2D, gColorSpec);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<int>(windowSize.x), static_cast<int>(windowSize.y), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gColorSpec, 0);
|
||||
|
||||
unsigned int attachments[3] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
|
||||
glDrawBuffers(3, attachments);
|
||||
|
||||
glGenRenderbuffers(1, &rDepth);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rDepth);
|
||||
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, static_cast<int>(windowSize.x * bufferScale), static_cast<int>(windowSize.y * bufferScale));
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rDepth);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
throw std::runtime_error("Lighting framebuffer incomplete.");
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
uniforms.gPosition = get("gPosition");
|
||||
uniforms.gNormal = get("gNormal");
|
||||
uniforms.gColorSpec = get("gColorSpec");
|
||||
uniforms.ssaoSampler = get("ssaoSampler");
|
||||
uniforms.camPosition = get("camPosition");
|
||||
|
||||
use();
|
||||
set(uniforms.gPosition, 0);
|
||||
set(uniforms.gNormal, 1);
|
||||
set(uniforms.gColorSpec, 2);
|
||||
set(uniforms.ssaoSampler, 3);
|
||||
|
||||
glGenFramebuffers(1, &gBuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
|
||||
|
||||
glGenTextures(1, &gPosition);
|
||||
glBindTexture(GL_TEXTURE_2D, gPosition);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, static_cast<int>(windowSize.x * bufferScale),
|
||||
static_cast<int>(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0);
|
||||
|
||||
glGenTextures(1, &gNormal);
|
||||
glBindTexture(GL_TEXTURE_2D, gNormal);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, static_cast<int>(windowSize.x * bufferScale),
|
||||
static_cast<int>(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0);
|
||||
|
||||
glGenTextures(1, &gColorSpec);
|
||||
glBindTexture(GL_TEXTURE_2D, gColorSpec);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<int>(windowSize.x), static_cast<int>(windowSize.y), 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gColorSpec, 0);
|
||||
|
||||
unsigned int attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
|
||||
glDrawBuffers(3, attachments);
|
||||
|
||||
glGenRenderbuffers(1, &rDepth);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rDepth);
|
||||
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, static_cast<int>(windowSize.x * bufferScale),
|
||||
static_cast<int>(windowSize.y * bufferScale));
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rDepth);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
throw std::runtime_error("Lighting framebuffer incomplete.");
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void LightingShader::windowResized(glm::ivec2 windowSize) {
|
||||
this->windowSize = windowSize;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, gPosition);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, static_cast<int>(windowSize.x * bufferScale), static_cast<int>(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, gNormal);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, static_cast<int>(windowSize.x * bufferScale), static_cast<int>(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, gColorSpec);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<int>(windowSize.x * bufferScale), static_cast<int>(windowSize.y * bufferScale), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gColorSpec, 0);
|
||||
|
||||
unsigned int attachments[3] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
|
||||
glDrawBuffers(3, attachments);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rDepth);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, static_cast<int>(windowSize.x * bufferScale), static_cast<int>(windowSize.y * bufferScale));
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rDepth);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
throw std::runtime_error("Lighting framebuffer incomplete.");
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
this->windowSize = windowSize;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, gPosition);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, static_cast<int>(windowSize.x * bufferScale),
|
||||
static_cast<int>(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, gNormal);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, static_cast<int>(windowSize.x * bufferScale),
|
||||
static_cast<int>(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, gColorSpec);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<int>(windowSize.x * bufferScale),
|
||||
static_cast<int>(windowSize.y * bufferScale), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gColorSpec, 0);
|
||||
|
||||
unsigned int attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
|
||||
glDrawBuffers(3, attachments);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rDepth);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, static_cast<int>(windowSize.x * bufferScale),
|
||||
static_cast<int>(windowSize.y * bufferScale));
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rDepth);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
throw std::runtime_error("Lighting framebuffer incomplete.");
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
|
|
@ -9,30 +9,31 @@
|
|||
#include "Shader.h"
|
||||
|
||||
class LightingShader : public Shader {
|
||||
public:
|
||||
explicit LightingShader(glm::ivec2 windowSize, float bufferScale);
|
||||
void postCreate() override;
|
||||
|
||||
void windowResized(glm::ivec2 windowSize);
|
||||
|
||||
struct Uniforms {
|
||||
GLint gPosition;
|
||||
GLint gNormal;
|
||||
GLint gColorSpec;
|
||||
GLint ssaoSampler;
|
||||
|
||||
GLint camPosition;
|
||||
};
|
||||
|
||||
Uniforms uniforms {};
|
||||
|
||||
unsigned int gBuffer = 0;
|
||||
unsigned int gPosition = 0;
|
||||
unsigned int gNormal = 0;
|
||||
unsigned int gColorSpec = 0;
|
||||
unsigned int rDepth = 0;
|
||||
|
||||
private:
|
||||
glm::ivec2 windowSize {};
|
||||
float bufferScale = 1;
|
||||
public:
|
||||
explicit LightingShader(glm::ivec2 windowSize, float bufferScale);
|
||||
|
||||
void postCreate() override;
|
||||
|
||||
void windowResized(glm::ivec2 windowSize);
|
||||
|
||||
struct Uniforms {
|
||||
GLint gPosition;
|
||||
GLint gNormal;
|
||||
GLint gColorSpec;
|
||||
GLint ssaoSampler;
|
||||
|
||||
GLint camPosition;
|
||||
};
|
||||
|
||||
Uniforms uniforms{};
|
||||
|
||||
unsigned int gBuffer = 0;
|
||||
unsigned int gPosition = 0;
|
||||
unsigned int gNormal = 0;
|
||||
unsigned int gColorSpec = 0;
|
||||
unsigned int rDepth = 0;
|
||||
|
||||
private:
|
||||
glm::ivec2 windowSize{};
|
||||
float bufferScale = 1;
|
||||
};
|
||||
|
|
|
@ -7,73 +7,75 @@
|
|||
#include "SSAOShader.h"
|
||||
|
||||
SSAOShader::SSAOShader(glm::ivec2 windowSize, float bufferScale, unsigned int kernelCount) : Shader(),
|
||||
windowSize(windowSize),
|
||||
bufferScale(bufferScale),
|
||||
kernelCount(kernelCount) {}
|
||||
windowSize(windowSize),
|
||||
bufferScale(bufferScale),
|
||||
kernelCount(kernelCount) {}
|
||||
|
||||
float lerp(float a, float b, float f) {
|
||||
return a + f * (b - a);
|
||||
return a + f * (b - a);
|
||||
}
|
||||
|
||||
void SSAOShader::postCreate() {
|
||||
uniforms.proj = get("projection");
|
||||
uniforms.view = get("view");
|
||||
uniforms.kernelCount = get("kernels");
|
||||
uniforms.sampleScale = get("sampleScale");
|
||||
|
||||
use();
|
||||
set(uniforms.sampleScale, 2.0f);
|
||||
|
||||
std::uniform_real_distribution<float> rand(0.0, 1.0);
|
||||
std::default_random_engine generator;
|
||||
|
||||
for (unsigned int i = 0; i < kernelCount; i++) {
|
||||
glm::vec3 sample {
|
||||
rand(generator) * 2.0 - 1.0,
|
||||
rand(generator) * 2.0 - 1.0,
|
||||
rand(generator)
|
||||
};
|
||||
|
||||
sample = glm::normalize(sample);
|
||||
sample *= rand(generator);
|
||||
|
||||
float scale = static_cast<float>(i / kernelCount);
|
||||
scale = lerp(0.1f, 1.0f, scale * scale);
|
||||
sample *= scale;
|
||||
|
||||
kernels.push_back(sample);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < sampleCount; i++) {
|
||||
noise.emplace_back(rand(generator) * 2.0 - 1.0, rand(generator) * 2.0 - 1.0, 0.0f);
|
||||
}
|
||||
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, 4, 4, 0, GL_RGB, GL_FLOAT, &noise[0]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glGenTextures(1, &colorBuffer);
|
||||
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast<int>(windowSize.x * bufferScale), static_cast<int>(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
uniforms.proj = get("projection");
|
||||
uniforms.view = get("view");
|
||||
uniforms.kernelCount = get("kernels");
|
||||
uniforms.sampleScale = get("sampleScale");
|
||||
|
||||
use();
|
||||
set(uniforms.sampleScale, 2.0f);
|
||||
|
||||
std::uniform_real_distribution<float> rand(0.0, 1.0);
|
||||
std::default_random_engine generator;
|
||||
|
||||
for (unsigned int i = 0; i < kernelCount; i++) {
|
||||
glm::vec3 sample{
|
||||
rand(generator) * 2.0 - 1.0,
|
||||
rand(generator) * 2.0 - 1.0,
|
||||
rand(generator)
|
||||
};
|
||||
|
||||
sample = glm::normalize(sample);
|
||||
sample *= rand(generator);
|
||||
|
||||
float scale = static_cast<float>(i / kernelCount);
|
||||
scale = lerp(0.1f, 1.0f, scale * scale);
|
||||
sample *= scale;
|
||||
|
||||
kernels.push_back(sample);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < sampleCount; i++) {
|
||||
noise.emplace_back(rand(generator) * 2.0 - 1.0, rand(generator) * 2.0 - 1.0, 0.0f);
|
||||
}
|
||||
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, 4, 4, 0, GL_RGB, GL_FLOAT, &noise[0]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glGenTextures(1, &colorBuffer);
|
||||
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast<int>(windowSize.x * bufferScale),
|
||||
static_cast<int>(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void SSAOShader::windowResized(glm::ivec2 windowSize) {
|
||||
this->windowSize = windowSize;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast<int>(windowSize.x * bufferScale), static_cast<int>(windowSize.y * bufferScale), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
this->windowSize = windowSize;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast<int>(windowSize.x * bufferScale),
|
||||
static_cast<int>(windowSize.y * bufferScale), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
|
|
@ -10,32 +10,33 @@
|
|||
#include "Shader.h"
|
||||
|
||||
class SSAOShader : public Shader {
|
||||
public:
|
||||
explicit SSAOShader(glm::ivec2 windowSize, float bufferScale, unsigned int kernelCount);
|
||||
void postCreate() override;
|
||||
|
||||
void windowResized(glm::ivec2 windowSize);
|
||||
|
||||
struct Uniforms {
|
||||
GLint proj;
|
||||
GLint view;
|
||||
GLint kernelCount;
|
||||
GLint sampleScale;
|
||||
};
|
||||
|
||||
Uniforms uniforms {};
|
||||
|
||||
unsigned int kernelCount = 32;
|
||||
unsigned int sampleCount = 16;
|
||||
|
||||
std::vector<glm::vec3> kernels {};
|
||||
std::vector<glm::vec3> noise {};
|
||||
|
||||
unsigned int tex = 0;
|
||||
unsigned int fbo = 0;
|
||||
unsigned int colorBuffer = 0;
|
||||
|
||||
private:
|
||||
glm::ivec2 windowSize {};
|
||||
float bufferScale = 1;
|
||||
public:
|
||||
explicit SSAOShader(glm::ivec2 windowSize, float bufferScale, unsigned int kernelCount);
|
||||
|
||||
void postCreate() override;
|
||||
|
||||
void windowResized(glm::ivec2 windowSize);
|
||||
|
||||
struct Uniforms {
|
||||
GLint proj;
|
||||
GLint view;
|
||||
GLint kernelCount;
|
||||
GLint sampleScale;
|
||||
};
|
||||
|
||||
Uniforms uniforms{};
|
||||
|
||||
unsigned int kernelCount = 32;
|
||||
unsigned int sampleCount = 16;
|
||||
|
||||
std::vector<glm::vec3> kernels{};
|
||||
std::vector<glm::vec3> noise{};
|
||||
|
||||
unsigned int tex = 0;
|
||||
unsigned int fbo = 0;
|
||||
unsigned int colorBuffer = 0;
|
||||
|
||||
private:
|
||||
glm::ivec2 windowSize{};
|
||||
float bufferScale = 1;
|
||||
};
|
||||
|
|
|
@ -11,140 +11,143 @@
|
|||
#include "../../../util/Log.h"
|
||||
|
||||
void Shader::createFromString(std::string& vertexSource, std::string& fragmentSource, const std::string& geoSource) {
|
||||
compileShader(vertexSource, fragmentSource);
|
||||
compileShader(vertexSource, fragmentSource);
|
||||
}
|
||||
|
||||
void Shader::createFromFile(const std::string& vertexFile, const std::string& fragmentFile, const std::string& geoFile) {
|
||||
compileShader(readFile(vertexFile), readFile(fragmentFile),
|
||||
geoFile == "" ? "" : readFile(geoFile));
|
||||
postCreate();
|
||||
void
|
||||
Shader::createFromFile(const std::string& vertexFile, const std::string& fragmentFile, const std::string& geoFile) {
|
||||
compileShader(readFile(vertexFile), readFile(fragmentFile),
|
||||
geoFile == "" ? "" : readFile(geoFile));
|
||||
postCreate();
|
||||
}
|
||||
|
||||
std::string Shader::readFile(const std::string& fileLocation) {
|
||||
std::string contents;
|
||||
|
||||
std::ifstream fileStream(fileLocation, std::ios::in);
|
||||
|
||||
if (!fileStream.is_open()) throw std::runtime_error("Failed to open shader file " + fileLocation + ".");
|
||||
|
||||
std::string line;
|
||||
while (!fileStream.eof()) {
|
||||
std::getline(fileStream, line);
|
||||
contents.append(line + "\n");
|
||||
}
|
||||
|
||||
fileStream.close();
|
||||
return contents;
|
||||
std::string contents;
|
||||
|
||||
std::ifstream fileStream(fileLocation, std::ios::in);
|
||||
|
||||
if (!fileStream.is_open()) throw std::runtime_error("Failed to open shader file " + fileLocation + ".");
|
||||
|
||||
std::string line;
|
||||
while (!fileStream.eof()) {
|
||||
std::getline(fileStream, line);
|
||||
contents.append(line + "\n");
|
||||
}
|
||||
|
||||
fileStream.close();
|
||||
return contents;
|
||||
}
|
||||
|
||||
void Shader::use() {
|
||||
glUseProgram(shaderID);
|
||||
glUseProgram(shaderID);
|
||||
}
|
||||
|
||||
void Shader::clearShader() {
|
||||
glUseProgram(0);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
GLint Shader::get(const std::string &name) {
|
||||
return glGetUniformLocation(shaderID, name.c_str());
|
||||
GLint Shader::get(const std::string& name) {
|
||||
return glGetUniformLocation(shaderID, name.c_str());
|
||||
}
|
||||
|
||||
void Shader::set(int loc, unsigned int val) {
|
||||
checkActive();
|
||||
glUniform1ui(loc, val);
|
||||
checkActive();
|
||||
glUniform1ui(loc, val);
|
||||
}
|
||||
|
||||
void Shader::set(int loc, int val) {
|
||||
checkActive();
|
||||
glUniform1i(loc, val);
|
||||
checkActive();
|
||||
glUniform1i(loc, val);
|
||||
}
|
||||
|
||||
void Shader::set(int loc, float val) {
|
||||
checkActive();
|
||||
glUniform1f(loc, val);
|
||||
checkActive();
|
||||
glUniform1f(loc, val);
|
||||
}
|
||||
|
||||
void Shader::set(int loc, glm::vec3 val) {
|
||||
checkActive();
|
||||
glUniform3f(loc, val.x, val.y, val.z);
|
||||
checkActive();
|
||||
glUniform3f(loc, val.x, val.y, val.z);
|
||||
}
|
||||
|
||||
void Shader::set(int loc, glm::vec4 val) {
|
||||
checkActive();
|
||||
glUniform4f(loc, val.x, val.y, val.z, val.w);
|
||||
checkActive();
|
||||
glUniform4f(loc, val.x, val.y, val.z, val.w);
|
||||
}
|
||||
|
||||
void Shader::set(int loc, glm::mat4 val) {
|
||||
checkActive();
|
||||
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(val));
|
||||
checkActive();
|
||||
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(val));
|
||||
}
|
||||
|
||||
void Shader::setArr(int loc, unsigned int count, glm::mat4 &start) {
|
||||
checkActive();
|
||||
glUniformMatrix4fv(loc, count, GL_FALSE, glm::value_ptr(start));
|
||||
void Shader::setArr(int loc, unsigned int count, glm::mat4& start) {
|
||||
checkActive();
|
||||
glUniformMatrix4fv(loc, count, GL_FALSE, glm::value_ptr(start));
|
||||
}
|
||||
|
||||
void Shader::compileShader(const std::string& vertexSource, const std::string& fragmentSource, const std::string& geoSource) {
|
||||
shaderID = glCreateProgram();
|
||||
if (!shaderID) throw std::runtime_error("Failed to create shader program.");
|
||||
|
||||
addShader(shaderID, vertexSource, GL_VERTEX_SHADER);
|
||||
addShader(shaderID, fragmentSource, GL_FRAGMENT_SHADER);
|
||||
if (geoSource != "") addShader(shaderID, geoSource, GL_GEOMETRY_SHADER);
|
||||
|
||||
GLint result = 0;
|
||||
GLchar eLog[1024] = { 0 };
|
||||
|
||||
glLinkProgram(shaderID);
|
||||
glGetProgramiv(shaderID, GL_LINK_STATUS, &result);
|
||||
|
||||
if (!result) {
|
||||
glGetProgramInfoLog(shaderID, sizeof(eLog), nullptr, eLog);
|
||||
throw std::runtime_error("Failed to link shader program. Error:\n" + std::string(eLog));
|
||||
}
|
||||
|
||||
glValidateProgram(shaderID);
|
||||
glGetProgramiv(shaderID, GL_VALIDATE_STATUS, &result);
|
||||
|
||||
if (!result) {
|
||||
glGetProgramInfoLog(shaderID, sizeof(eLog), nullptr, eLog);
|
||||
throw std::runtime_error("Failed to validate shader program. Error:\n" + std::string(eLog));
|
||||
}
|
||||
void Shader::compileShader(const std::string& vertexSource, const std::string& fragmentSource,
|
||||
const std::string& geoSource) {
|
||||
shaderID = glCreateProgram();
|
||||
if (!shaderID) throw std::runtime_error("Failed to create shader program.");
|
||||
|
||||
addShader(shaderID, vertexSource, GL_VERTEX_SHADER);
|
||||
addShader(shaderID, fragmentSource, GL_FRAGMENT_SHADER);
|
||||
if (geoSource != "") addShader(shaderID, geoSource, GL_GEOMETRY_SHADER);
|
||||
|
||||
GLint result = 0;
|
||||
GLchar eLog[1024] = { 0 };
|
||||
|
||||
glLinkProgram(shaderID);
|
||||
glGetProgramiv(shaderID, GL_LINK_STATUS, &result);
|
||||
|
||||
if (!result) {
|
||||
glGetProgramInfoLog(shaderID, sizeof(eLog), nullptr, eLog);
|
||||
throw std::runtime_error("Failed to link shader program. Error:\n" + std::string(eLog));
|
||||
}
|
||||
|
||||
glValidateProgram(shaderID);
|
||||
glGetProgramiv(shaderID, GL_VALIDATE_STATUS, &result);
|
||||
|
||||
if (!result) {
|
||||
glGetProgramInfoLog(shaderID, sizeof(eLog), nullptr, eLog);
|
||||
throw std::runtime_error("Failed to validate shader program. Error:\n" + std::string(eLog));
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::addShader(GLuint program, const std::string& shaderCode, GLenum shaderType) {
|
||||
GLuint shader = glCreateShader(shaderType);
|
||||
|
||||
const GLchar* shaderCodeCStr = shaderCode.data();
|
||||
int shaderLength = static_cast<int>(shaderCode.length());
|
||||
|
||||
glShaderSource(shader, 1, &shaderCodeCStr, &shaderLength);
|
||||
glCompileShader(shader);
|
||||
|
||||
GLint result = 0;
|
||||
GLchar eLog[1024] = { 0 };
|
||||
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
|
||||
|
||||
if (!result) {
|
||||
glGetShaderInfoLog(shader, sizeof(eLog), nullptr, eLog);
|
||||
std::string shaderTypeName = (shaderType == GL_VERTEX_SHADER) ? "vertex" : (shaderType == GL_FRAGMENT_SHADER) ? "fragment" : "geometry";
|
||||
throw std::runtime_error("Failed to compile the " + shaderTypeName + " shader. Error:\n" + eLog);
|
||||
}
|
||||
|
||||
glAttachShader(program, shader);
|
||||
GLuint shader = glCreateShader(shaderType);
|
||||
|
||||
const GLchar* shaderCodeCStr = shaderCode.data();
|
||||
int shaderLength = static_cast<int>(shaderCode.length());
|
||||
|
||||
glShaderSource(shader, 1, &shaderCodeCStr, &shaderLength);
|
||||
glCompileShader(shader);
|
||||
|
||||
GLint result = 0;
|
||||
GLchar eLog[1024] = { 0 };
|
||||
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
|
||||
|
||||
if (!result) {
|
||||
glGetShaderInfoLog(shader, sizeof(eLog), nullptr, eLog);
|
||||
std::string shaderTypeName = (shaderType == GL_VERTEX_SHADER) ? "vertex" : (shaderType == GL_FRAGMENT_SHADER)
|
||||
? "fragment" : "geometry";
|
||||
throw std::runtime_error("Failed to compile the " + shaderTypeName + " shader. Error:\n" + eLog);
|
||||
}
|
||||
|
||||
glAttachShader(program, shader);
|
||||
}
|
||||
|
||||
Shader::~Shader() {
|
||||
cleanup();
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void Shader::cleanup() {
|
||||
if (shaderID != 0) glDeleteProgram(shaderID);
|
||||
if (shaderID != 0) glDeleteProgram(shaderID);
|
||||
}
|
||||
|
||||
void Shader::checkActive() {
|
||||
int cProgram;
|
||||
glGetIntegerv(GL_CURRENT_PROGRAM, &cProgram);
|
||||
if (cProgram != shaderID) throw std::runtime_error("Attempted to set a uniform on an inactive shader!");
|
||||
int cProgram;
|
||||
glGetIntegerv(GL_CURRENT_PROGRAM, &cProgram);
|
||||
if (cProgram != shaderID) throw std::runtime_error("Attempted to set a uniform on an inactive shader!");
|
||||
}
|
|
@ -10,38 +10,48 @@
|
|||
#include <glm/mat4x4.hpp>
|
||||
|
||||
class Shader {
|
||||
public:
|
||||
void createFromString(std::string& vertexSource, std::string& fragmentSource, const std::string& geoSource = "");
|
||||
void createFromFile(const std::string& vertexFile, const std::string& fragmentFile, const std::string& geoFile = "");
|
||||
|
||||
virtual void postCreate() {};
|
||||
|
||||
int get(const std::string &name);
|
||||
|
||||
void use();
|
||||
static void clearShader();
|
||||
|
||||
void set(int loc, unsigned int val);
|
||||
void set(int loc, int val);
|
||||
void set(int loc, float val);
|
||||
void set(int loc, glm::vec3 val);
|
||||
void set(int loc, glm::vec4 val);
|
||||
void set(int loc, glm::mat4 val);
|
||||
|
||||
void setArr(int loc, unsigned int count, glm::mat4 &start);
|
||||
|
||||
void cleanup();
|
||||
|
||||
~Shader();
|
||||
|
||||
private:
|
||||
static std::string readFile(const std::string& fileLocation);
|
||||
|
||||
void compileShader(const std::string& vertexSource, const std::string& fragmentSource, const std::string& geoSource = "");
|
||||
static void addShader(unsigned int program, const std::string& shaderCode, GLenum shaderType);
|
||||
|
||||
void checkActive();
|
||||
|
||||
unsigned int shaderID = 0;
|
||||
public:
|
||||
void createFromString(std::string& vertexSource, std::string& fragmentSource, const std::string& geoSource = "");
|
||||
|
||||
void
|
||||
createFromFile(const std::string& vertexFile, const std::string& fragmentFile, const std::string& geoFile = "");
|
||||
|
||||
virtual void postCreate() {};
|
||||
|
||||
int get(const std::string& name);
|
||||
|
||||
void use();
|
||||
|
||||
static void clearShader();
|
||||
|
||||
void set(int loc, unsigned int val);
|
||||
|
||||
void set(int loc, int val);
|
||||
|
||||
void set(int loc, float val);
|
||||
|
||||
void set(int loc, glm::vec3 val);
|
||||
|
||||
void set(int loc, glm::vec4 val);
|
||||
|
||||
void set(int loc, glm::mat4 val);
|
||||
|
||||
void setArr(int loc, unsigned int count, glm::mat4& start);
|
||||
|
||||
void cleanup();
|
||||
|
||||
~Shader();
|
||||
|
||||
private:
|
||||
static std::string readFile(const std::string& fileLocation);
|
||||
|
||||
void compileShader(const std::string& vertexSource, const std::string& fragmentSource,
|
||||
const std::string& geoSource = "");
|
||||
|
||||
static void addShader(unsigned int program, const std::string& shaderCode, GLenum shaderType);
|
||||
|
||||
void checkActive();
|
||||
|
||||
unsigned int shaderID = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -7,37 +7,42 @@
|
|||
#include "WorldGeometryShader.h"
|
||||
|
||||
WorldGeometryShader::WorldGeometryShader(glm::ivec2 windowSize, float bufferScale) : Shader(),
|
||||
windowSize(windowSize),
|
||||
bufferScale(bufferScale),
|
||||
swayData(16 * 4 * 16) {
|
||||
|
||||
swayNoise.SetFrequency(0.20);
|
||||
swayNoise.SetOctaveCount(2);
|
||||
windowSize(windowSize),
|
||||
bufferScale(bufferScale),
|
||||
swayData(16 * 4 * 16) {
|
||||
|
||||
swayNoise.SetFrequency(0.20);
|
||||
swayNoise.SetOctaveCount(2);
|
||||
}
|
||||
|
||||
void WorldGeometryShader::postCreate() {
|
||||
swayTex.loadFromBytes(&swayData[0], 16, 16, GL_LINEAR, GL_MIRRORED_REPEAT);
|
||||
|
||||
uniforms.proj = get("projection");
|
||||
uniforms.model = get("model");
|
||||
uniforms.view = get("view");
|
||||
|
||||
uniforms.swaySampler = get("swayTex");
|
||||
uniforms.time = get("time");
|
||||
|
||||
use();
|
||||
set(uniforms.swaySampler, 1);
|
||||
swayTex.loadFromBytes(&swayData[0], 16, 16, GL_LINEAR, GL_MIRRORED_REPEAT);
|
||||
|
||||
uniforms.proj = get("projection");
|
||||
uniforms.model = get("model");
|
||||
uniforms.view = get("view");
|
||||
|
||||
uniforms.swaySampler = get("swayTex");
|
||||
uniforms.time = get("time");
|
||||
|
||||
use();
|
||||
set(uniforms.swaySampler, 1);
|
||||
}
|
||||
|
||||
void WorldGeometryShader::windowResized(glm::ivec2 windowSize) {
|
||||
this->windowSize = windowSize;
|
||||
this->windowSize = windowSize;
|
||||
}
|
||||
|
||||
void WorldGeometryShader::updateSwayMap(double delta) {
|
||||
swayOffset += delta * 2.8;
|
||||
for (int i = 0; i < 16 * 16; i++) {
|
||||
swayData[i*4] = static_cast<unsigned char>((fmax(-1, fmin(1, swayNoise.GetValue((i / 16) / 3.f, (i % 16) / 3.f, swayOffset))) + 1) / 2.f * 255.f);
|
||||
swayData[i*4+1] = static_cast<unsigned char>((fmax(-1, fmin(1, swayNoise.GetValue((i / 16) / 3.f, (i % 16) / 3.f, swayOffset + 50))) + 1) / 2.f * 255.f);
|
||||
swayData[i*4+2] = static_cast<unsigned char>((fmax(-1, fmin(1, swayNoise.GetValue((i / 16) / 3.f, (i % 16) / 3.f, swayOffset + 100))) + 1) / 2.f * 255.f);
|
||||
}
|
||||
swayTex.updateTexture(0, 0, 16, 16, &swayData[0]);
|
||||
swayOffset += delta * 2.8;
|
||||
for (int i = 0; i < 16 * 16; i++) {
|
||||
swayData[i * 4] = static_cast<unsigned char>(
|
||||
(fmax(-1, fmin(1, swayNoise.GetValue((i / 16) / 3.f, (i % 16) / 3.f, swayOffset))) + 1) / 2.f * 255.f);
|
||||
swayData[i * 4 + 1] = static_cast<unsigned char>(
|
||||
(fmax(-1, fmin(1, swayNoise.GetValue((i / 16) / 3.f, (i % 16) / 3.f, swayOffset + 50))) + 1) / 2.f * 255.f);
|
||||
swayData[i * 4 + 2] = static_cast<unsigned char>(
|
||||
(fmax(-1, fmin(1, swayNoise.GetValue((i / 16) / 3.f, (i % 16) / 3.f, swayOffset + 100))) + 1) / 2.f *
|
||||
255.f);
|
||||
}
|
||||
swayTex.updateTexture(0, 0, 16, 16, &swayData[0]);
|
||||
}
|
|
@ -12,30 +12,32 @@
|
|||
#include "../Texture.h"
|
||||
|
||||
class WorldGeometryShader : public Shader {
|
||||
public:
|
||||
explicit WorldGeometryShader(glm::ivec2 windowSize, float bufferScale);
|
||||
void postCreate() override;
|
||||
|
||||
void windowResized(glm::ivec2 windowSize);
|
||||
void updateSwayMap(double delta);
|
||||
|
||||
struct Uniforms {
|
||||
GLint proj;
|
||||
GLint model;
|
||||
GLint view;
|
||||
|
||||
GLint swaySampler;
|
||||
|
||||
GLint time;
|
||||
};
|
||||
|
||||
Uniforms uniforms {};
|
||||
|
||||
Texture swayTex;
|
||||
double swayOffset = 0;
|
||||
noise::module::Perlin swayNoise;
|
||||
std::vector<unsigned char> swayData {};
|
||||
|
||||
glm::ivec2 windowSize {};
|
||||
float bufferScale = 1;
|
||||
public:
|
||||
explicit WorldGeometryShader(glm::ivec2 windowSize, float bufferScale);
|
||||
|
||||
void postCreate() override;
|
||||
|
||||
void windowResized(glm::ivec2 windowSize);
|
||||
|
||||
void updateSwayMap(double delta);
|
||||
|
||||
struct Uniforms {
|
||||
GLint proj;
|
||||
GLint model;
|
||||
GLint view;
|
||||
|
||||
GLint swaySampler;
|
||||
|
||||
GLint time;
|
||||
};
|
||||
|
||||
Uniforms uniforms{};
|
||||
|
||||
Texture swayTex;
|
||||
double swayOffset = 0;
|
||||
noise::module::Perlin swayNoise;
|
||||
std::vector<unsigned char> swayData{};
|
||||
|
||||
glm::ivec2 windowSize{};
|
||||
float bufferScale = 1;
|
||||
};
|
||||
|
|
|
@ -13,164 +13,171 @@
|
|||
#include "client/gui/compound/GuiLabelledGraph.h"
|
||||
|
||||
DebugGui::DebugGui(glm::vec2 bufferSize, SubgamePtr game, WorldPtr world) :
|
||||
game(game),
|
||||
world(world) {
|
||||
|
||||
auto fontRef = game.l()->textures["font"];
|
||||
auto fpsHistogramRef = game.l()->textures["histogram"];
|
||||
auto genericHistogramRef = game.l()->textures["histogram_white"];
|
||||
|
||||
Font f(game.l()->textures, fontRef);
|
||||
|
||||
auto crosshairText = std::make_shared<GuiText>("crosshairText");
|
||||
crosshairText->create({2, 2}, {}, {0.2, 0.2, 0.2, 0.5}, {1, 1, 1, 1}, f);
|
||||
add(crosshairText);
|
||||
|
||||
auto dataText = std::make_shared<GuiText>("dataText");
|
||||
dataText->create({2, 2}, {}, {0.2, 0.2, 0.2, 0.5}, {1, 1, 1, 1}, f);
|
||||
add(dataText);
|
||||
|
||||
auto interpGraph = std::make_shared<GuiLabelledGraph>("interpGraph");
|
||||
interpGraph->create({244, 64}, {}, "Interp", 120, 256, genericHistogramRef, f);
|
||||
add(interpGraph);
|
||||
|
||||
auto meshGraph = std::make_shared<GuiLabelledGraph>("meshGraph");
|
||||
meshGraph->create({244, 64}, {}, "Mesh", 120, 32, genericHistogramRef, f);
|
||||
add(meshGraph);
|
||||
|
||||
auto genGraph = std::make_shared<GuiLabelledGraph>("genGraph");
|
||||
genGraph->create({244, 64}, {}, "Gen", 120, 16, genericHistogramRef, f);
|
||||
add(genGraph);
|
||||
|
||||
auto packetGraph = std::make_shared<GuiLabelledGraph>("packetGraph");
|
||||
packetGraph->create({244, 64}, {}, "Packets", 120, 32, genericHistogramRef, f);
|
||||
add(packetGraph);
|
||||
|
||||
auto fpsGraph = std::make_shared<GuiLabelledGraph>("fpsGraph");
|
||||
fpsGraph->create({244, 64}, {}, "FPS", 120, 60, fpsHistogramRef, f);
|
||||
add(fpsGraph);
|
||||
|
||||
auto drawsGraph = std::make_shared<GuiLabelledGraph>("drawsGraph");
|
||||
drawsGraph->create({244, 64}, {}, "Draw Calls", 120, 0, genericHistogramRef, f);
|
||||
add(drawsGraph);
|
||||
|
||||
auto gpuGraph = std::make_shared<GuiLabelledGraph>("gpuGraph");
|
||||
gpuGraph->create({244, 64}, {}, "GPU", 120, 1, genericHistogramRef, f);
|
||||
add(gpuGraph);
|
||||
|
||||
positionElements(bufferSize);
|
||||
game(game),
|
||||
world(world) {
|
||||
|
||||
auto fontRef = game.l()->textures["font"];
|
||||
auto fpsHistogramRef = game.l()->textures["histogram"];
|
||||
auto genericHistogramRef = game.l()->textures["histogram_white"];
|
||||
|
||||
Font f(game.l()->textures, fontRef);
|
||||
|
||||
auto crosshairText = std::make_shared<GuiText>("crosshairText");
|
||||
crosshairText->create({ 2, 2 }, {}, { 0.2, 0.2, 0.2, 0.5 }, { 1, 1, 1, 1 }, f);
|
||||
add(crosshairText);
|
||||
|
||||
auto dataText = std::make_shared<GuiText>("dataText");
|
||||
dataText->create({ 2, 2 }, {}, { 0.2, 0.2, 0.2, 0.5 }, { 1, 1, 1, 1 }, f);
|
||||
add(dataText);
|
||||
|
||||
auto interpGraph = std::make_shared<GuiLabelledGraph>("interpGraph");
|
||||
interpGraph->create({ 244, 64 }, {}, "Interp", 120, 256, genericHistogramRef, f);
|
||||
add(interpGraph);
|
||||
|
||||
auto meshGraph = std::make_shared<GuiLabelledGraph>("meshGraph");
|
||||
meshGraph->create({ 244, 64 }, {}, "Mesh", 120, 32, genericHistogramRef, f);
|
||||
add(meshGraph);
|
||||
|
||||
auto genGraph = std::make_shared<GuiLabelledGraph>("genGraph");
|
||||
genGraph->create({ 244, 64 }, {}, "Gen", 120, 16, genericHistogramRef, f);
|
||||
add(genGraph);
|
||||
|
||||
auto packetGraph = std::make_shared<GuiLabelledGraph>("packetGraph");
|
||||
packetGraph->create({ 244, 64 }, {}, "Packets", 120, 32, genericHistogramRef, f);
|
||||
add(packetGraph);
|
||||
|
||||
auto fpsGraph = std::make_shared<GuiLabelledGraph>("fpsGraph");
|
||||
fpsGraph->create({ 244, 64 }, {}, "FPS", 120, 60, fpsHistogramRef, f);
|
||||
add(fpsGraph);
|
||||
|
||||
auto drawsGraph = std::make_shared<GuiLabelledGraph>("drawsGraph");
|
||||
drawsGraph->create({ 244, 64 }, {}, "Draw Calls", 120, 0, genericHistogramRef, f);
|
||||
add(drawsGraph);
|
||||
|
||||
auto gpuGraph = std::make_shared<GuiLabelledGraph>("gpuGraph");
|
||||
gpuGraph->create({ 244, 64 }, {}, "GPU", 120, 1, genericHistogramRef, f);
|
||||
add(gpuGraph);
|
||||
|
||||
positionElements(bufferSize);
|
||||
}
|
||||
|
||||
void DebugGui::positionElements(glm::vec2 bufferSize) {
|
||||
auto bufferWidth = static_cast<int>(bufferSize.x);
|
||||
auto bufferHeight = static_cast<int>(bufferSize.y);
|
||||
|
||||
get<GuiText>("crosshairText")->setPos({bufferWidth / 2 + 22, bufferHeight / 2 - 7});
|
||||
get<GuiText>("dataText")->setPos({10, 10});
|
||||
|
||||
get<GuiLabelledGraph>("genGraph")->setPos({bufferWidth - 254, bufferHeight - 70 - 160});
|
||||
get<GuiLabelledGraph>("packetGraph")->setPos({bufferWidth - 254, bufferHeight - 70 - 240});
|
||||
get<GuiLabelledGraph>("meshGraph")->setPos({bufferWidth - 254, bufferHeight - 70 - 80});
|
||||
get<GuiLabelledGraph>("interpGraph")->setPos({bufferWidth - 254, bufferHeight - 70});
|
||||
|
||||
get<GuiLabelledGraph>("fpsGraph")->setPos({bufferWidth - 254, 10});
|
||||
get<GuiLabelledGraph>("drawsGraph")->setPos({bufferWidth - 254, 90});
|
||||
get<GuiLabelledGraph>("gpuGraph")->setPos({bufferWidth - 254, 90 + 80});
|
||||
auto bufferWidth = static_cast<int>(bufferSize.x);
|
||||
auto bufferHeight = static_cast<int>(bufferSize.y);
|
||||
|
||||
get<GuiText>("crosshairText")->setPos({ bufferWidth / 2 + 22, bufferHeight / 2 - 7 });
|
||||
get<GuiText>("dataText")->setPos({ 10, 10 });
|
||||
|
||||
get<GuiLabelledGraph>("genGraph")->setPos({ bufferWidth - 254, bufferHeight - 70 - 160 });
|
||||
get<GuiLabelledGraph>("packetGraph")->setPos({ bufferWidth - 254, bufferHeight - 70 - 240 });
|
||||
get<GuiLabelledGraph>("meshGraph")->setPos({ bufferWidth - 254, bufferHeight - 70 - 80 });
|
||||
get<GuiLabelledGraph>("interpGraph")->setPos({ bufferWidth - 254, bufferHeight - 70 });
|
||||
|
||||
get<GuiLabelledGraph>("fpsGraph")->setPos({ bufferWidth - 254, 10 });
|
||||
get<GuiLabelledGraph>("drawsGraph")->setPos({ bufferWidth - 254, 90 });
|
||||
get<GuiLabelledGraph>("gpuGraph")->setPos({ bufferWidth - 254, 90 + 80 });
|
||||
}
|
||||
|
||||
void DebugGui::update(std::shared_ptr<LocalPlayer> player, double fps, int /*chunks*/, int drawCalls, int ssGen, int ssPack) {
|
||||
Target target = player->getTarget();
|
||||
|
||||
auto& onBiomeDef = game->getBiomes().biomeFromId(world.l()->getActiveDimension()->getBiome(glm::floor(player->getPos())));
|
||||
auto& targetedBlockDef = game->getDefs().blockFromId(world.l()->getActiveDimension()->getBlock(target.pos));
|
||||
|
||||
/* Top-right Graphs */ {
|
||||
get<GuiLabelledGraph>("fpsGraph")->pushValue(static_cast<float>(fps));
|
||||
get<GuiLabelledGraph>("drawsGraph")->pushValue(drawCalls);
|
||||
|
||||
int videoMemAvail, videoMemTotal;
|
||||
|
||||
glGetIntegerv(0x9048, &videoMemTotal);
|
||||
glGetIntegerv(0x9049, &videoMemAvail);
|
||||
|
||||
get<GuiLabelledGraph>("gpuGraph")->pushValue(static_cast<int>(std::round(
|
||||
(videoMemTotal - videoMemAvail) / static_cast<float>(videoMemTotal) * 100.0)) / 100.0f);
|
||||
}
|
||||
|
||||
/* Bottom-right Graphs */ {
|
||||
get<GuiLabelledGraph>("meshGraph")->pushValue(world.l()->lastMeshUpdates);
|
||||
get<GuiLabelledGraph>("interpGraph")->pushValue(world.l()->mapBlocksInterpolated);
|
||||
get<GuiLabelledGraph>("genGraph")->pushValue(static_cast<float>(ssGen));
|
||||
get<GuiLabelledGraph>("packetGraph")->pushValue(static_cast<float>(ssPack));
|
||||
}
|
||||
|
||||
/* Top-left Data */ {
|
||||
glm::vec3 playerPos = glm::floor(player->getPos());
|
||||
glm::vec3 chunkPos = Space::Chunk::world::fromBlock(playerPos);
|
||||
glm::vec3 mapBlockPos = Space::MapBlock::world::fromChunk(chunkPos);
|
||||
glm::vec3 regionPos = Space::Region::world::fromChunk(chunkPos);
|
||||
|
||||
glm::vec3 posOffsetFromChunk = Space::Block::relative::toChunk(playerPos);
|
||||
glm::vec3 posOffsetFromBlock = Space::Block::relative::toMapBlock(playerPos);
|
||||
glm::vec3 posOffsetFromRegion = Space::Block::relative::toRegion(playerPos);
|
||||
|
||||
std::ostringstream str;
|
||||
|
||||
using namespace Util;
|
||||
|
||||
str << "Dimension: " << world.l()->getActiveDimension()->getIdentifier()
|
||||
<< " [" << world.l()->getActiveDimension()->getInd() << "]" << std::endl << std::endl;
|
||||
|
||||
str << "Pos: " << vecToString(playerPos) << " (" << floatVecToString(player->getPos()) << ")" << std::endl;
|
||||
str << "Vel: " << floatVecToString(player->getVel()) << std::endl;
|
||||
str << "Yaw: " << floatToString(player->getYaw()) << ", ";
|
||||
str << "Pitch: " << floatToString(player->getPitch()) << std::endl << std::endl;
|
||||
|
||||
str << "C: " << vecToString(posOffsetFromChunk) << " [" << vecToString(chunkPos) << "]" << std::endl;
|
||||
str << "M: " << vecToString(posOffsetFromBlock) << " [" << vecToString(mapBlockPos) << "]" << std::endl;
|
||||
str << "R: " << vecToString(posOffsetFromRegion) << " [" << vecToString(regionPos) << "]" << std::endl << std::endl;
|
||||
|
||||
str << "Texture Slots: " << game.l()->textures.textureSlotsUsed << " / " << game.l()->textures.maxTextureSlots
|
||||
<< " (" << round(game.l()->textures.textureSlotsUsed / static_cast<float>(game.l()->textures.maxTextureSlots) * 100) << "%)" << std::endl << std::endl;
|
||||
|
||||
str << "Biome: " << onBiomeDef.identifier << " [" << onBiomeDef.index << "]" << std::endl << std::endl;
|
||||
|
||||
if (target.type == Target::Type::BLOCK) {
|
||||
std::string face =
|
||||
target.face == EVec::TOP ? "TOP" :
|
||||
target.face == EVec::BOTTOM ? "BOTTOM" :
|
||||
target.face == EVec::LEFT ? "LEFT" :
|
||||
target.face == EVec::RIGHT ? "RIGHT" :
|
||||
target.face == EVec::FRONT ? "FRONT" :
|
||||
target.face == EVec::BACK ? "BACK" :
|
||||
"NONE" ;
|
||||
|
||||
str << "Pointing At: " << targetedBlockDef.identifier << " [" << targetedBlockDef.index << "]" << std::endl;
|
||||
str << "Pointed Position: " << vecToString(target.pos) << std::endl;
|
||||
str << "Pointed Face: " << face << std::endl;
|
||||
}
|
||||
else {
|
||||
str << "No Target";
|
||||
}
|
||||
|
||||
get<GuiText>("dataText")->setText(str.str());
|
||||
}
|
||||
|
||||
/* Crosshair Text */ {
|
||||
if (target.type == Target::Type::BLOCK) get<GuiText>("crosshairText")->setText(targetedBlockDef.name + " (" +
|
||||
targetedBlockDef.identifier + ") [" + std::to_string(targetedBlockDef.index) + "]");
|
||||
else get<GuiText>("crosshairText")->setText("");
|
||||
}
|
||||
void DebugGui::update(std::shared_ptr<LocalPlayer> player, double fps, int /*chunks*/, int drawCalls, int ssGen,
|
||||
int ssPack) {
|
||||
Target target = player->getTarget();
|
||||
|
||||
auto& onBiomeDef = game->getBiomes().biomeFromId(
|
||||
world.l()->getActiveDimension()->getBiome(glm::floor(player->getPos())));
|
||||
auto& targetedBlockDef = game->getDefs().blockFromId(world.l()->getActiveDimension()->getBlock(target.pos));
|
||||
|
||||
/* Top-right Graphs */ {
|
||||
get<GuiLabelledGraph>("fpsGraph")->pushValue(static_cast<float>(fps));
|
||||
get<GuiLabelledGraph>("drawsGraph")->pushValue(drawCalls);
|
||||
|
||||
int videoMemAvail, videoMemTotal;
|
||||
|
||||
glGetIntegerv(0x9048, &videoMemTotal);
|
||||
glGetIntegerv(0x9049, &videoMemAvail);
|
||||
|
||||
get<GuiLabelledGraph>("gpuGraph")->pushValue(static_cast<int>(std::round(
|
||||
(videoMemTotal - videoMemAvail) / static_cast<float>(videoMemTotal) * 100.0)) / 100.0f);
|
||||
}
|
||||
|
||||
/* Bottom-right Graphs */ {
|
||||
get<GuiLabelledGraph>("meshGraph")->pushValue(world.l()->lastMeshUpdates);
|
||||
get<GuiLabelledGraph>("interpGraph")->pushValue(world.l()->mapBlocksInterpolated);
|
||||
get<GuiLabelledGraph>("genGraph")->pushValue(static_cast<float>(ssGen));
|
||||
get<GuiLabelledGraph>("packetGraph")->pushValue(static_cast<float>(ssPack));
|
||||
}
|
||||
|
||||
/* Top-left Data */ {
|
||||
glm::vec3 playerPos = glm::floor(player->getPos());
|
||||
glm::vec3 chunkPos = Space::Chunk::world::fromBlock(playerPos);
|
||||
glm::vec3 mapBlockPos = Space::MapBlock::world::fromChunk(chunkPos);
|
||||
glm::vec3 regionPos = Space::Region::world::fromChunk(chunkPos);
|
||||
|
||||
glm::vec3 posOffsetFromChunk = Space::Block::relative::toChunk(playerPos);
|
||||
glm::vec3 posOffsetFromBlock = Space::Block::relative::toMapBlock(playerPos);
|
||||
glm::vec3 posOffsetFromRegion = Space::Block::relative::toRegion(playerPos);
|
||||
|
||||
std::ostringstream str;
|
||||
|
||||
using namespace Util;
|
||||
|
||||
str << "Dimension: " << world.l()->getActiveDimension()->getIdentifier()
|
||||
<< " [" << world.l()->getActiveDimension()->getInd() << "]" << std::endl << std::endl;
|
||||
|
||||
str << "Pos: " << vecToString(playerPos) << " (" << floatVecToString(player->getPos()) << ")" << std::endl;
|
||||
str << "Vel: " << floatVecToString(player->getVel()) << std::endl;
|
||||
str << "Yaw: " << floatToString(player->getYaw()) << ", ";
|
||||
str << "Pitch: " << floatToString(player->getPitch()) << std::endl << std::endl;
|
||||
|
||||
str << "C: " << vecToString(posOffsetFromChunk) << " [" << vecToString(chunkPos) << "]" << std::endl;
|
||||
str << "M: " << vecToString(posOffsetFromBlock) << " [" << vecToString(mapBlockPos) << "]" << std::endl;
|
||||
str << "R: " << vecToString(posOffsetFromRegion) << " [" << vecToString(regionPos) << "]" << std::endl
|
||||
<< std::endl;
|
||||
|
||||
str << "Texture Slots: " << game.l()->textures.textureSlotsUsed << " / " << game.l()->textures.maxTextureSlots
|
||||
<< " ("
|
||||
<< round(game.l()->textures.textureSlotsUsed / static_cast<float>(game.l()->textures.maxTextureSlots) * 100)
|
||||
<< "%)" << std::endl << std::endl;
|
||||
|
||||
str << "Biome: " << onBiomeDef.identifier << " [" << onBiomeDef.index << "]" << std::endl << std::endl;
|
||||
|
||||
if (target.type == Target::Type::BLOCK) {
|
||||
std::string face =
|
||||
target.face == EVec::TOP ? "TOP" :
|
||||
target.face == EVec::BOTTOM ? "BOTTOM" :
|
||||
target.face == EVec::LEFT ? "LEFT" :
|
||||
target.face == EVec::RIGHT ? "RIGHT" :
|
||||
target.face == EVec::FRONT ? "FRONT" :
|
||||
target.face == EVec::BACK ? "BACK" :
|
||||
"NONE";
|
||||
|
||||
str << "Pointing At: " << targetedBlockDef.identifier << " [" << targetedBlockDef.index << "]" << std::endl;
|
||||
str << "Pointed Position: " << vecToString(target.pos) << std::endl;
|
||||
str << "Pointed Face: " << face << std::endl;
|
||||
}
|
||||
else {
|
||||
str << "No Target";
|
||||
}
|
||||
|
||||
get<GuiText>("dataText")->setText(str.str());
|
||||
}
|
||||
|
||||
/* Crosshair Text */ {
|
||||
if (target.type == Target::Type::BLOCK)
|
||||
get<GuiText>("crosshairText")->setText(targetedBlockDef.name + " (" +
|
||||
targetedBlockDef.identifier + ") [" +
|
||||
std::to_string(targetedBlockDef.index) + "]");
|
||||
else get<GuiText>("crosshairText")->setText("");
|
||||
}
|
||||
}
|
||||
|
||||
void DebugGui::bufferResized(glm::vec2 bufferSize) {
|
||||
positionElements(bufferSize);
|
||||
positionElements(bufferSize);
|
||||
}
|
||||
|
||||
// 0 = All, 1 = None, 2 = FPS
|
||||
void DebugGui::changeVisibilityState(int state) {
|
||||
displayMode = state;
|
||||
|
||||
setVisible(displayMode == 0);
|
||||
get<GuiLabelledGraph>("fpsGraph")->setVisible(displayMode != 1);
|
||||
displayMode = state;
|
||||
|
||||
setVisible(displayMode == 0);
|
||||
get<GuiLabelledGraph>("fpsGraph")->setVisible(displayMode != 1);
|
||||
}
|
||||
|
|
|
@ -9,21 +9,26 @@
|
|||
#include "util/CovariantPtr.h"
|
||||
|
||||
class LocalPlayer;
|
||||
|
||||
class LocalSubgame;
|
||||
|
||||
class LocalWorld;
|
||||
|
||||
class DebugGui : public GuiContainer {
|
||||
public:
|
||||
DebugGui(glm::vec2 bufferSize, SubgamePtr game, WorldPtr world);
|
||||
|
||||
void bufferResized(glm::vec2 bufferSize);
|
||||
void changeVisibilityState(int state);
|
||||
void positionElements(glm::vec2 bufferSize);
|
||||
|
||||
void update(std::shared_ptr<LocalPlayer> player, double fps, int chunks, int drawCalls, int ssGen, int ssPack);
|
||||
private:
|
||||
int displayMode;
|
||||
|
||||
WorldPtr world;
|
||||
SubgamePtr game;
|
||||
public:
|
||||
DebugGui(glm::vec2 bufferSize, SubgamePtr game, WorldPtr world);
|
||||
|
||||
void bufferResized(glm::vec2 bufferSize);
|
||||
|
||||
void changeVisibilityState(int state);
|
||||
|
||||
void positionElements(glm::vec2 bufferSize);
|
||||
|
||||
void update(std::shared_ptr<LocalPlayer> player, double fps, int chunks, int drawCalls, int ssGen, int ssPack);
|
||||
|
||||
private:
|
||||
int displayMode;
|
||||
|
||||
WorldPtr world;
|
||||
SubgamePtr game;
|
||||
};
|
||||
|
|
|
@ -7,76 +7,76 @@
|
|||
#include "../graph/Renderer.h"
|
||||
|
||||
GameGui::GameGui(InventoryRefsPtr refs, glm::vec2 bufferSize, SubgamePtr defs, Renderer& renderer) :
|
||||
refs(refs),
|
||||
defs(defs),
|
||||
win(bufferSize),
|
||||
renderer(renderer),
|
||||
|
||||
hudBuilder(refs, defs, hudLuaRoot),
|
||||
menuBuilder(refs, defs, menuLuaRoot) {
|
||||
|
||||
hudRoot->add(hudLuaRoot);
|
||||
menuRoot->add(menuLuaRoot);
|
||||
|
||||
handList->create({3, 3}, {}, {}, refs.l()->getCursorList(), refs.l()->getCursorList(), defs);
|
||||
menuRoot->add(handList);
|
||||
refs(refs),
|
||||
defs(defs),
|
||||
win(bufferSize),
|
||||
renderer(renderer),
|
||||
|
||||
hudBuilder(refs, defs, hudLuaRoot),
|
||||
menuBuilder(refs, defs, menuLuaRoot) {
|
||||
|
||||
hudRoot->add(hudLuaRoot);
|
||||
menuRoot->add(menuLuaRoot);
|
||||
|
||||
handList->create({ 3, 3 }, {}, {}, refs.l()->getCursorList(), refs.l()->getCursorList(), defs);
|
||||
menuRoot->add(handList);
|
||||
}
|
||||
|
||||
void GameGui::update(double delta) {
|
||||
menuRoot->update(delta);
|
||||
hudRoot->update(delta);
|
||||
|
||||
hudBuilder.update();
|
||||
menuBuilder.update();
|
||||
|
||||
handList->setPos((renderer.window.input.mousePos() - glm::ivec2(24)) / 3 * 3);
|
||||
menuRoot->handleMouseInput(renderer.window);
|
||||
menuRoot->update(delta);
|
||||
hudRoot->update(delta);
|
||||
|
||||
hudBuilder.update();
|
||||
menuBuilder.update();
|
||||
|
||||
handList->setPos((renderer.window.input.mousePos() - glm::ivec2(24)) / 3 * 3);
|
||||
menuRoot->handleMouseInput(renderer.window);
|
||||
}
|
||||
|
||||
void GameGui::winResized(glm::ivec2 win) {
|
||||
this->win = win;
|
||||
menuBuilder.build(win);
|
||||
hudBuilder.build(win);
|
||||
this->win = win;
|
||||
menuBuilder.build(win);
|
||||
hudBuilder.build(win);
|
||||
}
|
||||
|
||||
void GameGui::showMenu(std::shared_ptr<LuaGuiElement> root) {
|
||||
menuBuilder.setGuiRoot(root);
|
||||
menuBuilder.build(win);
|
||||
inMenu = true;
|
||||
menuBuilder.setGuiRoot(root);
|
||||
menuBuilder.build(win);
|
||||
inMenu = true;
|
||||
}
|
||||
|
||||
void GameGui::closeMenu() {
|
||||
menuBuilder.clear();
|
||||
inMenu = false;
|
||||
menuBuilder.clear();
|
||||
inMenu = false;
|
||||
}
|
||||
|
||||
const bool GameGui::isInMenu() const {
|
||||
return inMenu;
|
||||
return inMenu;
|
||||
}
|
||||
|
||||
void GameGui::setHud(std::shared_ptr<LuaGuiElement> hud) {
|
||||
this->hudRootElem = hud;
|
||||
hudBuilder.setGuiRoot(hud);
|
||||
hudBuilder.build(win);
|
||||
this->hudRootElem = hud;
|
||||
hudBuilder.setGuiRoot(hud);
|
||||
hudBuilder.build(win);
|
||||
}
|
||||
|
||||
std::shared_ptr<LuaGuiElement> GameGui::getHud() {
|
||||
return hudRootElem;
|
||||
return hudRootElem;
|
||||
}
|
||||
|
||||
void GameGui::setVisible(bool visible) {
|
||||
menuRoot->setVisible(visible);
|
||||
hudRoot->setVisible(visible);
|
||||
menuRoot->setVisible(visible);
|
||||
hudRoot->setVisible(visible);
|
||||
}
|
||||
|
||||
bool GameGui::isVisible() {
|
||||
return menuRoot->isVisible();
|
||||
return menuRoot->isVisible();
|
||||
}
|
||||
|
||||
void GameGui::drawHud(Renderer &renderer) {
|
||||
hudRoot->draw(renderer);
|
||||
void GameGui::drawHud(Renderer& renderer) {
|
||||
hudRoot->draw(renderer);
|
||||
}
|
||||
|
||||
void GameGui::drawMenu(Renderer &renderer) {
|
||||
menuRoot->draw(renderer);
|
||||
void GameGui::drawMenu(Renderer& renderer) {
|
||||
menuRoot->draw(renderer);
|
||||
}
|
|
@ -8,41 +8,49 @@
|
|||
#include "client/gui/compound/GuiInventoryList.h"
|
||||
|
||||
class GameGui {
|
||||
public:
|
||||
explicit GameGui(InventoryRefsPtr refs, glm::vec2 bufferSize, SubgamePtr defs, Renderer& renderer);
|
||||
void winResized(glm::ivec2 win);
|
||||
void update(double delta);
|
||||
|
||||
void setVisible(bool visible);
|
||||
bool isVisible();
|
||||
|
||||
void showMenu(std::shared_ptr<LuaGuiElement> root);
|
||||
void closeMenu();
|
||||
const bool isInMenu() const;
|
||||
|
||||
void setHud(std::shared_ptr<LuaGuiElement> hud);
|
||||
std::shared_ptr<LuaGuiElement> getHud();
|
||||
|
||||
void drawHud(Renderer& renderer);
|
||||
void drawMenu(Renderer& renderer);
|
||||
private:
|
||||
SubgamePtr defs;
|
||||
Renderer& renderer;
|
||||
|
||||
glm::ivec2 win {};
|
||||
bool inMenu = false;
|
||||
|
||||
std::shared_ptr<LuaGuiElement> hudRootElem = nullptr;
|
||||
|
||||
std::shared_ptr<GuiContainer> menuRoot = std::make_shared<GuiInventoryList>("menuRoot");
|
||||
std::shared_ptr<GuiContainer> menuLuaRoot = std::make_shared<GuiInventoryList>("menuLuaRoot");
|
||||
GameGuiBuilder menuBuilder;
|
||||
std::shared_ptr<GuiContainer> hudRoot = std::make_shared<GuiInventoryList>("hudRoot");
|
||||
std::shared_ptr<GuiContainer> hudLuaRoot = std::make_shared<GuiInventoryList>("hudLuaRoot");
|
||||
GameGuiBuilder hudBuilder;
|
||||
|
||||
std::shared_ptr<GuiInventoryList> handList = std::make_shared<GuiInventoryList>("hand");
|
||||
|
||||
InventoryRefsPtr refs;
|
||||
public:
|
||||
explicit GameGui(InventoryRefsPtr refs, glm::vec2 bufferSize, SubgamePtr defs, Renderer& renderer);
|
||||
|
||||
void winResized(glm::ivec2 win);
|
||||
|
||||
void update(double delta);
|
||||
|
||||
void setVisible(bool visible);
|
||||
|
||||
bool isVisible();
|
||||
|
||||
void showMenu(std::shared_ptr<LuaGuiElement> root);
|
||||
|
||||
void closeMenu();
|
||||
|
||||
const bool isInMenu() const;
|
||||
|
||||
void setHud(std::shared_ptr<LuaGuiElement> hud);
|
||||
|
||||
std::shared_ptr<LuaGuiElement> getHud();
|
||||
|
||||
void drawHud(Renderer& renderer);
|
||||
|
||||
void drawMenu(Renderer& renderer);
|
||||
|
||||
private:
|
||||
SubgamePtr defs;
|
||||
Renderer& renderer;
|
||||
|
||||
glm::ivec2 win{};
|
||||
bool inMenu = false;
|
||||
|
||||
std::shared_ptr<LuaGuiElement> hudRootElem = nullptr;
|
||||
|
||||
std::shared_ptr<GuiContainer> menuRoot = std::make_shared<GuiInventoryList>("menuRoot");
|
||||
std::shared_ptr<GuiContainer> menuLuaRoot = std::make_shared<GuiInventoryList>("menuLuaRoot");
|
||||
GameGuiBuilder menuBuilder;
|
||||
std::shared_ptr<GuiContainer> hudRoot = std::make_shared<GuiInventoryList>("hudRoot");
|
||||
std::shared_ptr<GuiContainer> hudLuaRoot = std::make_shared<GuiInventoryList>("hudLuaRoot");
|
||||
GameGuiBuilder hudBuilder;
|
||||
|
||||
std::shared_ptr<GuiInventoryList> handList = std::make_shared<GuiInventoryList>("hand");
|
||||
|
||||
InventoryRefsPtr refs;
|
||||
};
|
||||
|
||||
|
|
|
@ -8,20 +8,20 @@
|
|||
#include "client/gui/compound/GuiInventoryList.h"
|
||||
|
||||
std::shared_ptr<GuiComponent> GameGuiBuilder::createComponent(LuaGuiElement& elem, glm::ivec2 bounds) {
|
||||
auto c = GuiBuilder::createComponent(elem, bounds);
|
||||
if (c != nullptr) return c;
|
||||
|
||||
switch (Util::hash(elem.type.c_str())) {
|
||||
default: break;
|
||||
case Util::hash("InventoryList"): {
|
||||
c = GuiInventoryList::fromSerialized(elem, defs, bounds, refs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!c) return nullptr;
|
||||
|
||||
elem.updateFunction = std::bind(&GameGuiBuilder::elementUpdated, this);
|
||||
auto c = GuiBuilder::createComponent(elem, bounds);
|
||||
if (c != nullptr) return c;
|
||||
|
||||
switch (Util::hash(elem.type.c_str())) {
|
||||
default: break;
|
||||
case Util::hash("InventoryList"): {
|
||||
c = GuiInventoryList::fromSerialized(elem, defs, bounds, refs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!c) return nullptr;
|
||||
|
||||
elem.updateFunction = std::bind(&GameGuiBuilder::elementUpdated, this);
|
||||
|
||||
// if (elem.callbacks.count("primary")) c->setCallback(GuiComponent::CallbackType::PRIMARY, [=](bool b, glm::vec2 v) {
|
||||
// elem.callbacks.at("primary")(b, LuaParser::luaVec(elem.callbacks.at("primary").lua_state(), {v.x, v.y, 0})); });
|
||||
|
@ -31,6 +31,6 @@ std::shared_ptr<GuiComponent> GameGuiBuilder::createComponent(LuaGuiElement& ele
|
|||
//
|
||||
// if (elem.callbacks.count("hover")) c->setCallback(GuiComponent::CallbackType::HOVER, [=](bool b, glm::vec2 v) {
|
||||
// elem.callbacks.at("hover")(b, LuaParser::luaVec(elem.callbacks.at("hover").lua_state(), {v.x, v.y, 0})); });
|
||||
|
||||
return c;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
|
|
@ -10,12 +10,13 @@
|
|||
#include "world/inv/LocalInventoryRefs.h"
|
||||
|
||||
class GameGuiBuilder : public GuiBuilder {
|
||||
public:
|
||||
GameGuiBuilder(InventoryRefsPtr refs, SubgamePtr defs, std::shared_ptr<GuiContainer> root) :
|
||||
defs(defs), refs(refs), GuiBuilder(defs.l()->textures, defs.l()->models, root) {};
|
||||
|
||||
std::shared_ptr<GuiComponent> createComponent(LuaGuiElement& elem, glm::ivec2 bounds) override;
|
||||
private:
|
||||
InventoryRefsPtr refs;
|
||||
SubgamePtr defs;
|
||||
public:
|
||||
GameGuiBuilder(InventoryRefsPtr refs, SubgamePtr defs, std::shared_ptr<GuiContainer> root) :
|
||||
defs(defs), refs(refs), GuiBuilder(defs.l()->textures, defs.l()->models, root) {};
|
||||
|
||||
std::shared_ptr<GuiComponent> createComponent(LuaGuiElement& elem, glm::ivec2 bounds) override;
|
||||
|
||||
private:
|
||||
InventoryRefsPtr refs;
|
||||
SubgamePtr defs;
|
||||
};
|
||||
|
|
|
@ -12,68 +12,64 @@
|
|||
#include "client/gui/compound/GuiImageButton.h"
|
||||
|
||||
GuiBuilder::GuiBuilder(TextureAtlas& textures, ModelStore& models, std::shared_ptr<GuiContainer> root) :
|
||||
textures(textures), models(models), root(root) {}
|
||||
textures(textures), models(models), root(root) {}
|
||||
|
||||
void GuiBuilder::setGuiRoot(std::shared_ptr<LuaGuiElement> menu) {
|
||||
elements = menu;
|
||||
elements = menu;
|
||||
}
|
||||
|
||||
void GuiBuilder::update() {
|
||||
if (dirty) {
|
||||
build();
|
||||
dirty = false;
|
||||
}
|
||||
if (dirty) {
|
||||
build();
|
||||
dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void GuiBuilder::build(glm::ivec2 winBounds) {
|
||||
clear(false);
|
||||
if (winBounds != glm::ivec2 {}) this->winBounds = winBounds;
|
||||
if (elements) create(*elements, root, this->winBounds);
|
||||
clear(false);
|
||||
if (winBounds != glm::ivec2{}) this->winBounds = winBounds;
|
||||
if (elements) create(*elements, root, this->winBounds);
|
||||
}
|
||||
|
||||
void GuiBuilder::clear(bool deleteRoot) {
|
||||
clearCallbacks(root);
|
||||
root->empty();
|
||||
if (deleteRoot) elements = nullptr;
|
||||
clearCallbacks(root);
|
||||
root->empty();
|
||||
if (deleteRoot) elements = nullptr;
|
||||
}
|
||||
|
||||
void GuiBuilder::create(LuaGuiElement& element, std::shared_ptr<GuiComponent> parent, glm::ivec2 bounds) {
|
||||
if (element.get_or<bool>("visible", true)) {
|
||||
auto component = createComponent(element, bounds);
|
||||
if (!component) throw std::runtime_error("GuiBuilder failed to create component: " + element.key);
|
||||
parent->add(component);
|
||||
for (auto &child : element.children) create(*child, component, component->getScale());
|
||||
}
|
||||
if (element.get_or<bool>("visible", true)) {
|
||||
auto component = createComponent(element, bounds);
|
||||
if (!component) throw std::runtime_error("GuiBuilder failed to create component: " + element.key);
|
||||
parent->add(component);
|
||||
for (auto& child : element.children) create(*child, component, component->getScale());
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<GuiComponent> GuiBuilder::createComponent(LuaGuiElement& elem, glm::ivec2 bounds) {
|
||||
std::shared_ptr<GuiComponent> c = nullptr;
|
||||
|
||||
switch (Util::hash(elem.type.c_str())) {
|
||||
default: break;
|
||||
case Util::hash("Body"): {
|
||||
auto body = GuiRect::fromSerialized(elem, textures, bounds);
|
||||
body->setScale(bounds);
|
||||
c = body;
|
||||
break;
|
||||
}
|
||||
case Util::hash("Rect"):
|
||||
c = GuiRect::fromSerialized(elem, textures, bounds);
|
||||
break;
|
||||
case Util::hash("Button"):
|
||||
c = GuiImageButton::fromSerialized(elem, textures, bounds);
|
||||
break;
|
||||
case Util::hash("Text"):
|
||||
c = GuiText::fromSerialized(elem, textures, bounds);
|
||||
break;
|
||||
case Util::hash("Model"):
|
||||
c = GuiModel::fromSerialized(elem, textures, models, bounds);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!c) return nullptr;
|
||||
|
||||
elem.updateFunction = std::bind(&GuiBuilder::elementUpdated, this);
|
||||
std::shared_ptr<GuiComponent> c = nullptr;
|
||||
|
||||
switch (Util::hash(elem.type.c_str())) {
|
||||
default: break;
|
||||
case Util::hash("Body"): {
|
||||
auto body = GuiRect::fromSerialized(elem, textures, bounds);
|
||||
body->setScale(bounds);
|
||||
c = body;
|
||||
break;
|
||||
}
|
||||
case Util::hash("Rect"):c = GuiRect::fromSerialized(elem, textures, bounds);
|
||||
break;
|
||||
case Util::hash("Button"):c = GuiImageButton::fromSerialized(elem, textures, bounds);
|
||||
break;
|
||||
case Util::hash("Text"):c = GuiText::fromSerialized(elem, textures, bounds);
|
||||
break;
|
||||
case Util::hash("Model"):c = GuiModel::fromSerialized(elem, textures, models, bounds);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!c) return nullptr;
|
||||
|
||||
elem.updateFunction = std::bind(&GuiBuilder::elementUpdated, this);
|
||||
|
||||
// if (elem.callbacks.count("primary")) c->setCallback(GuiComponent::CallbackType::PRIMARY, [=](bool b, glm::vec2 v) {
|
||||
// elem.callbacks.at("primary")(b, LuaParser::luaVec(elem.callbacks.at("primary").lua_state(), {v.x, v.y, 0})); });
|
||||
|
@ -83,22 +79,22 @@ std::shared_ptr<GuiComponent> GuiBuilder::createComponent(LuaGuiElement& elem, g
|
|||
//
|
||||
// if (elem.callbacks.count("hover")) c->setCallback(GuiComponent::CallbackType::HOVER, [=](bool b, glm::vec2 v) {
|
||||
// elem.callbacks.at("hover")(b, LuaParser::luaVec(elem.callbacks.at("hover").lua_state(), {v.x, v.y, 0})); });
|
||||
|
||||
return c;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void GuiBuilder::clearCallbacks(std::shared_ptr<GuiComponent> component) {
|
||||
component->setCallback(GuiComponent::CallbackType::PRIMARY, nullptr);
|
||||
component->setCallback(GuiComponent::CallbackType::SECONDARY, nullptr);
|
||||
component->setCallback(GuiComponent::CallbackType::HOVER, nullptr);
|
||||
|
||||
for (auto& child : component->getChildren()) clearCallbacks(child);
|
||||
component->setCallback(GuiComponent::CallbackType::PRIMARY, nullptr);
|
||||
component->setCallback(GuiComponent::CallbackType::SECONDARY, nullptr);
|
||||
component->setCallback(GuiComponent::CallbackType::HOVER, nullptr);
|
||||
|
||||
for (auto& child : component->getChildren()) clearCallbacks(child);
|
||||
}
|
||||
|
||||
void GuiBuilder::elementUpdated() {
|
||||
dirty = true;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
GuiBuilder::~GuiBuilder() {
|
||||
clear();
|
||||
clear();
|
||||
}
|
|
@ -12,32 +12,41 @@
|
|||
class GuiContainer;
|
||||
|
||||
class GuiBuilder {
|
||||
public:
|
||||
struct ComponentCallbacks { GuiComponent::callback left {}, right {}, hover {}; };
|
||||
|
||||
GuiBuilder(TextureAtlas& textures, ModelStore& models, std::shared_ptr<GuiContainer> root);
|
||||
void setGuiRoot(std::shared_ptr<LuaGuiElement> menu);
|
||||
void update();
|
||||
void build(glm::ivec2 winBounds = {});
|
||||
void clear(bool deleteRoot = true);
|
||||
|
||||
~GuiBuilder();
|
||||
protected:
|
||||
void create(LuaGuiElement& element, std::shared_ptr<GuiComponent> parent, glm::ivec2 bounds);
|
||||
virtual std::shared_ptr<GuiComponent> createComponent(LuaGuiElement& elem, glm::ivec2 bounds);
|
||||
static void clearCallbacks(std::shared_ptr<GuiComponent> component);
|
||||
|
||||
void elementUpdated();
|
||||
|
||||
TextureAtlas& textures;
|
||||
ModelStore& models;
|
||||
|
||||
std::shared_ptr<GuiContainer> root = nullptr;
|
||||
|
||||
std::shared_ptr<LuaGuiElement> elements = nullptr;
|
||||
unsigned int keyInd = 0;
|
||||
|
||||
bool dirty = false;
|
||||
|
||||
glm::ivec2 winBounds {};
|
||||
public:
|
||||
struct ComponentCallbacks {
|
||||
GuiComponent::callback left{}, right{}, hover{};
|
||||
};
|
||||
|
||||
GuiBuilder(TextureAtlas& textures, ModelStore& models, std::shared_ptr<GuiContainer> root);
|
||||
|
||||
void setGuiRoot(std::shared_ptr<LuaGuiElement> menu);
|
||||
|
||||
void update();
|
||||
|
||||
void build(glm::ivec2 winBounds = {});
|
||||
|
||||
void clear(bool deleteRoot = true);
|
||||
|
||||
~GuiBuilder();
|
||||
|
||||
protected:
|
||||
void create(LuaGuiElement& element, std::shared_ptr<GuiComponent> parent, glm::ivec2 bounds);
|
||||
|
||||
virtual std::shared_ptr<GuiComponent> createComponent(LuaGuiElement& elem, glm::ivec2 bounds);
|
||||
|
||||
static void clearCallbacks(std::shared_ptr<GuiComponent> component);
|
||||
|
||||
void elementUpdated();
|
||||
|
||||
TextureAtlas& textures;
|
||||
ModelStore& models;
|
||||
|
||||
std::shared_ptr<GuiContainer> root = nullptr;
|
||||
|
||||
std::shared_ptr<LuaGuiElement> elements = nullptr;
|
||||
unsigned int keyInd = 0;
|
||||
|
||||
bool dirty = false;
|
||||
|
||||
glm::ivec2 winBounds{};
|
||||
};
|
||||
|
|
|
@ -9,174 +9,174 @@
|
|||
#include "client/graph/Renderer.h"
|
||||
|
||||
GuiComponent::GuiComponent(const std::string& key) :
|
||||
key(key) {}
|
||||
key(key) {}
|
||||
|
||||
void GuiComponent::update(double delta) {
|
||||
for (const auto& child : children) {
|
||||
child->update(delta);
|
||||
}
|
||||
for (const auto& child : children) {
|
||||
child->update(delta);
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& GuiComponent::getKey() {
|
||||
return key;
|
||||
return key;
|
||||
}
|
||||
|
||||
glm::ivec2 GuiComponent::getPos() {
|
||||
return pos;
|
||||
return pos;
|
||||
}
|
||||
|
||||
void GuiComponent::setPos(glm::ivec2 pos) {
|
||||
this->pos = pos;
|
||||
|
||||
if (parent != nullptr) {
|
||||
glm::vec3 parentPos = parent->entity.getPos();
|
||||
pos += glm::vec2 {parentPos.x, parentPos.y};
|
||||
pos += glm::vec2 {parent->getPadding().w, parent->getPadding().x};
|
||||
}
|
||||
|
||||
entity.setPos({pos.x, pos.y, 0});
|
||||
|
||||
for (const auto& child : children) {
|
||||
child->updatePos();
|
||||
}
|
||||
this->pos = pos;
|
||||
|
||||
if (parent != nullptr) {
|
||||
glm::vec3 parentPos = parent->entity.getPos();
|
||||
pos += glm::vec2{ parentPos.x, parentPos.y };
|
||||
pos += glm::vec2{ parent->getPadding().w, parent->getPadding().x };
|
||||
}
|
||||
|
||||
entity.setPos({ pos.x, pos.y, 0 });
|
||||
|
||||
for (const auto& child : children) {
|
||||
child->updatePos();
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec2 GuiComponent::getScale() {
|
||||
return scale;
|
||||
return scale;
|
||||
}
|
||||
|
||||
void GuiComponent::setScale(glm::vec2 scale) {
|
||||
this->scale = scale;
|
||||
entity.setScale({scale.x, scale.y, scale.x});
|
||||
this->scale = scale;
|
||||
entity.setScale({ scale.x, scale.y, scale.x });
|
||||
}
|
||||
|
||||
glm::vec4 GuiComponent::getPadding() {
|
||||
return padding;
|
||||
return padding;
|
||||
}
|
||||
|
||||
void GuiComponent::setPadding(glm::vec4 padding) {
|
||||
this->padding = padding;
|
||||
this->padding = padding;
|
||||
}
|
||||
|
||||
void GuiComponent::setOverflows(bool overflows) {
|
||||
this->overflows = overflows;
|
||||
this->overflows = overflows;
|
||||
}
|
||||
|
||||
void GuiComponent::setVisible(bool visible) {
|
||||
Drawable::setVisible(visible);
|
||||
entity.setVisible(visible);
|
||||
for (const auto& child : children) {
|
||||
child->setVisible(visible);
|
||||
}
|
||||
Drawable::setVisible(visible);
|
||||
entity.setVisible(visible);
|
||||
for (const auto& child : children) {
|
||||
child->setVisible(visible);
|
||||
}
|
||||
}
|
||||
|
||||
void GuiComponent::setCallback(GuiComponent::CallbackType type, const callback& cb) {
|
||||
callbacks[static_cast<unsigned int>(type)] = cb;
|
||||
callbacks[static_cast<unsigned int>(type)] = cb;
|
||||
}
|
||||
|
||||
void GuiComponent::handleMouseInput(Window &window) {
|
||||
auto mousePos = window.input.mousePos();
|
||||
|
||||
window.setCursorHand(mouseActivity(mousePos));
|
||||
if (window.input.mousePressed(GLFW_MOUSE_BUTTON_LEFT)) clickEvent(true, true, mousePos);
|
||||
if (window.input.mouseReleased(GLFW_MOUSE_BUTTON_LEFT)) clickEvent(true, false, mousePos);
|
||||
if (window.input.mousePressed(GLFW_MOUSE_BUTTON_RIGHT)) clickEvent(false, true, mousePos);
|
||||
if (window.input.mouseReleased(GLFW_MOUSE_BUTTON_RIGHT)) clickEvent(false, false, mousePos);
|
||||
void GuiComponent::handleMouseInput(Window& window) {
|
||||
auto mousePos = window.input.mousePos();
|
||||
|
||||
window.setCursorHand(mouseActivity(mousePos));
|
||||
if (window.input.mousePressed(GLFW_MOUSE_BUTTON_LEFT)) clickEvent(true, true, mousePos);
|
||||
if (window.input.mouseReleased(GLFW_MOUSE_BUTTON_LEFT)) clickEvent(true, false, mousePos);
|
||||
if (window.input.mousePressed(GLFW_MOUSE_BUTTON_RIGHT)) clickEvent(false, true, mousePos);
|
||||
if (window.input.mouseReleased(GLFW_MOUSE_BUTTON_RIGHT)) clickEvent(false, false, mousePos);
|
||||
}
|
||||
|
||||
bool GuiComponent::mouseActivity(glm::ivec2 pos) {
|
||||
bool isHovering = false;
|
||||
for (auto& child : children) {
|
||||
glm::ivec2 cp = pos - child->getPos() - glm::ivec2(child->getPadding().y, child->getPadding().x);
|
||||
if (child->mouseActivity(cp)) isHovering = true;
|
||||
}
|
||||
|
||||
auto& callback = callbacks[static_cast<unsigned int>(CallbackType::HOVER)];
|
||||
|
||||
if (pos.x >= 0 && pos.y >= 0 && pos.x <= hitbox.x && pos.y <= hitbox.y) {
|
||||
if (callback) {
|
||||
callback(true, pos);
|
||||
hovered = true;
|
||||
return true;
|
||||
}
|
||||
return isHovering;
|
||||
}
|
||||
else {
|
||||
if (callback) {
|
||||
callback(false, pos);
|
||||
hovered = false;
|
||||
}
|
||||
}
|
||||
return isHovering;
|
||||
bool isHovering = false;
|
||||
for (auto& child : children) {
|
||||
glm::ivec2 cp = pos - child->getPos() - glm::ivec2(child->getPadding().y, child->getPadding().x);
|
||||
if (child->mouseActivity(cp)) isHovering = true;
|
||||
}
|
||||
|
||||
auto& callback = callbacks[static_cast<unsigned int>(CallbackType::HOVER)];
|
||||
|
||||
if (pos.x >= 0 && pos.y >= 0 && pos.x <= hitbox.x && pos.y <= hitbox.y) {
|
||||
if (callback) {
|
||||
callback(true, pos);
|
||||
hovered = true;
|
||||
return true;
|
||||
}
|
||||
return isHovering;
|
||||
}
|
||||
else {
|
||||
if (callback) {
|
||||
callback(false, pos);
|
||||
hovered = false;
|
||||
}
|
||||
}
|
||||
return isHovering;
|
||||
}
|
||||
|
||||
std::shared_ptr<GuiComponent> GuiComponent::insert(unsigned int index, std::shared_ptr<GuiComponent> component) {
|
||||
component->parent = this;
|
||||
component->updatePos();
|
||||
children.insert(std::next(children.begin(), index), std::move(component));
|
||||
return component;
|
||||
component->parent = this;
|
||||
component->updatePos();
|
||||
children.insert(std::next(children.begin(), index), std::move(component));
|
||||
return component;
|
||||
}
|
||||
|
||||
std::shared_ptr<GuiComponent> GuiComponent::add(std::shared_ptr<GuiComponent> component) {
|
||||
component->parent = this;
|
||||
component->updatePos();
|
||||
children.push_back(component);
|
||||
return component;
|
||||
component->parent = this;
|
||||
component->updatePos();
|
||||
children.push_back(component);
|
||||
return component;
|
||||
}
|
||||
|
||||
void GuiComponent::remove(const std::string& key) {
|
||||
for (auto it = children.cbegin(); it != children.cend(); it++) {
|
||||
if (it->get()->key == key) {
|
||||
children.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (auto it = children.cbegin(); it != children.cend(); it++) {
|
||||
if (it->get()->key == key) {
|
||||
children.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuiComponent::empty() {
|
||||
for (auto it = children.cbegin(); it != children.cend();) {
|
||||
it = children.erase(it);
|
||||
}
|
||||
for (auto it = children.cbegin(); it != children.cend();) {
|
||||
it = children.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void GuiComponent::draw(Renderer& renderer) {
|
||||
entity.draw(renderer);
|
||||
|
||||
for (const auto& child : children) {
|
||||
renderer.setClipBounds(overflows ? glm::vec4 {} : glm::vec4 {entity.getPos().x, entity.getPos().y,
|
||||
entity.getPos().x + scale.x, entity.getPos().y + scale.y});
|
||||
child->draw(renderer);
|
||||
}
|
||||
entity.draw(renderer);
|
||||
|
||||
for (const auto& child : children) {
|
||||
renderer.setClipBounds(overflows ? glm::vec4{} : glm::vec4{ entity.getPos().x, entity.getPos().y,
|
||||
entity.getPos().x + scale.x, entity.getPos().y + scale.y });
|
||||
child->draw(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
bool GuiComponent::clickEvent(bool left, bool state, glm::ivec2 pos) {
|
||||
for (auto& child : children) {
|
||||
glm::ivec2 cp = pos - child->getPos() - glm::ivec2(child->getPadding().y, child->getPadding().x);
|
||||
if (child->clickEvent(left, state, cp)) return true;
|
||||
}
|
||||
|
||||
auto& callback = callbacks[static_cast<unsigned int>(left ? CallbackType::PRIMARY : CallbackType::SECONDARY)];
|
||||
|
||||
if (pos.x >= 0 && pos.y >= 0 && pos.x <= hitbox.x && pos.y <= hitbox.y && callback) {
|
||||
callback(state, pos);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
for (auto& child : children) {
|
||||
glm::ivec2 cp = pos - child->getPos() - glm::ivec2(child->getPadding().y, child->getPadding().x);
|
||||
if (child->clickEvent(left, state, cp)) return true;
|
||||
}
|
||||
|
||||
auto& callback = callbacks[static_cast<unsigned int>(left ? CallbackType::PRIMARY : CallbackType::SECONDARY)];
|
||||
|
||||
if (pos.x >= 0 && pos.y >= 0 && pos.x <= hitbox.x && pos.y <= hitbox.y && callback) {
|
||||
callback(state, pos);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GuiComponent::updatePos() {
|
||||
glm::vec2 realPos(pos);
|
||||
if (parent != nullptr) {
|
||||
glm::vec3 parentPos = parent->entity.getPos();
|
||||
realPos += glm::vec2 {parentPos.x, parentPos.y};
|
||||
realPos += glm::vec2 {parent->getPadding().w, parent->getPadding().x};
|
||||
}
|
||||
entity.setPos({realPos.x, realPos.y, 0});
|
||||
for (const auto& child : children) {
|
||||
child->updatePos();
|
||||
}
|
||||
glm::vec2 realPos(pos);
|
||||
if (parent != nullptr) {
|
||||
glm::vec3 parentPos = parent->entity.getPos();
|
||||
realPos += glm::vec2{ parentPos.x, parentPos.y };
|
||||
realPos += glm::vec2{ parent->getPadding().w, parent->getPadding().x };
|
||||
}
|
||||
entity.setPos({ realPos.x, realPos.y, 0 });
|
||||
for (const auto& child : children) {
|
||||
child->updatePos();
|
||||
}
|
||||
}
|
||||
|
||||
std::list<std::shared_ptr<GuiComponent>> GuiComponent::getChildren() {
|
||||
return children;
|
||||
return children;
|
||||
}
|
||||
|
|
|
@ -14,69 +14,85 @@
|
|||
class Window;
|
||||
|
||||
class GuiComponent : public Drawable {
|
||||
public:
|
||||
enum class CallbackType { PRIMARY, SECONDARY, HOVER };
|
||||
typedef std::function<void(bool, glm::ivec2)> callback;
|
||||
|
||||
GuiComponent() = default;
|
||||
explicit GuiComponent(const std::string& key);
|
||||
|
||||
virtual void update(double delta) override;
|
||||
|
||||
const std::string& getKey();
|
||||
|
||||
virtual glm::ivec2 getPos();
|
||||
virtual void setPos(glm::ivec2 pos);
|
||||
virtual glm::vec2 getScale();
|
||||
virtual void setScale(glm::vec2 scale);
|
||||
virtual glm::vec4 getPadding();
|
||||
virtual void setPadding(glm::vec4 padding);
|
||||
void setOverflows(bool overflows);
|
||||
void setVisible(bool visible) override;
|
||||
|
||||
virtual void setCallback(CallbackType type, const callback& cb);
|
||||
void handleMouseInput(Window& window);
|
||||
|
||||
template<class T> std::shared_ptr<T> get(const std::string &key) {
|
||||
for (auto &it : children) {
|
||||
if (it.get()->key == key) {
|
||||
return std::static_pointer_cast<T>(it);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
std::shared_ptr<GuiComponent> insert(unsigned int index, std::shared_ptr<GuiComponent> component);
|
||||
std::shared_ptr<GuiComponent> add(std::shared_ptr<GuiComponent> component);
|
||||
|
||||
std::list<std::shared_ptr<GuiComponent>> getChildren();
|
||||
|
||||
void remove(const std::string& key);
|
||||
void empty();
|
||||
|
||||
void draw(Renderer& renderer) override;
|
||||
protected:
|
||||
bool mouseActivity(glm::ivec2 pos);
|
||||
bool clickEvent(bool left, bool state, glm::ivec2 pos);
|
||||
|
||||
std::string key = "";
|
||||
GuiComponent* parent = nullptr;
|
||||
std::list<std::shared_ptr<GuiComponent>> children;
|
||||
|
||||
glm::ivec2 pos {};
|
||||
glm::vec2 scale {};
|
||||
glm::vec4 padding {};
|
||||
glm::ivec2 hitbox {};
|
||||
|
||||
bool visible = true;
|
||||
bool hovered = false;
|
||||
bool overflows = false;
|
||||
|
||||
DrawableEntity entity;
|
||||
std::array<callback, 3> callbacks;
|
||||
|
||||
private:
|
||||
void updatePos();
|
||||
public:
|
||||
enum class CallbackType {
|
||||
PRIMARY, SECONDARY, HOVER
|
||||
};
|
||||
typedef std::function<void(bool, glm::ivec2)> callback;
|
||||
|
||||
GuiComponent() = default;
|
||||
|
||||
explicit GuiComponent(const std::string& key);
|
||||
|
||||
virtual void update(double delta) override;
|
||||
|
||||
const std::string& getKey();
|
||||
|
||||
virtual glm::ivec2 getPos();
|
||||
|
||||
virtual void setPos(glm::ivec2 pos);
|
||||
|
||||
virtual glm::vec2 getScale();
|
||||
|
||||
virtual void setScale(glm::vec2 scale);
|
||||
|
||||
virtual glm::vec4 getPadding();
|
||||
|
||||
virtual void setPadding(glm::vec4 padding);
|
||||
|
||||
void setOverflows(bool overflows);
|
||||
|
||||
void setVisible(bool visible) override;
|
||||
|
||||
virtual void setCallback(CallbackType type, const callback& cb);
|
||||
|
||||
void handleMouseInput(Window& window);
|
||||
|
||||
template<class T>
|
||||
std::shared_ptr<T> get(const std::string& key) {
|
||||
for (auto& it : children) {
|
||||
if (it.get()->key == key) {
|
||||
return std::static_pointer_cast<T>(it);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
std::shared_ptr<GuiComponent> insert(unsigned int index, std::shared_ptr<GuiComponent> component);
|
||||
|
||||
std::shared_ptr<GuiComponent> add(std::shared_ptr<GuiComponent> component);
|
||||
|
||||
std::list<std::shared_ptr<GuiComponent>> getChildren();
|
||||
|
||||
void remove(const std::string& key);
|
||||
|
||||
void empty();
|
||||
|
||||
void draw(Renderer& renderer) override;
|
||||
|
||||
protected:
|
||||
bool mouseActivity(glm::ivec2 pos);
|
||||
|
||||
bool clickEvent(bool left, bool state, glm::ivec2 pos);
|
||||
|
||||
std::string key = "";
|
||||
GuiComponent* parent = nullptr;
|
||||
std::list<std::shared_ptr<GuiComponent>> children;
|
||||
|
||||
glm::ivec2 pos{};
|
||||
glm::vec2 scale{};
|
||||
glm::vec4 padding{};
|
||||
glm::ivec2 hitbox{};
|
||||
|
||||
bool visible = true;
|
||||
bool hovered = false;
|
||||
bool overflows = false;
|
||||
|
||||
DrawableEntity entity;
|
||||
std::array<callback, 3> callbacks;
|
||||
|
||||
private:
|
||||
void updatePos();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -20,71 +20,76 @@
|
|||
#include "../../lua/usertype/LuaGuiElement.h"
|
||||
|
||||
namespace SerialGui {
|
||||
const float SCALE_MODIFIER = 3;
|
||||
const float PERCENT_DIFF = 10000;
|
||||
|
||||
namespace {
|
||||
static std::vector<std::string> split(const std::string& value, unsigned int targetCount = 0) {
|
||||
std::vector<std::string> vec {};
|
||||
|
||||
if (value == "") throw std::runtime_error("expected one or more values to split");
|
||||
|
||||
size_t count = std::count(value.begin(), value.end(), ' ');
|
||||
if (count + 1 > targetCount) throw std::runtime_error("expected less values");
|
||||
|
||||
// Split the values into the vector.
|
||||
size_t begin = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
size_t end = value.find(' ', begin);
|
||||
vec.push_back(value.substr(begin, end - begin));
|
||||
begin = end + 1;
|
||||
}
|
||||
vec.push_back(value.substr(begin));
|
||||
|
||||
// Duplicate values until we meet or surpass the expected values.
|
||||
while (vec.size() < targetCount) for (auto& v: vec) vec.push_back(v);
|
||||
if (vec.size() > targetCount) throw std::runtime_error("values are not a division of expectation");
|
||||
|
||||
return std::move(vec);
|
||||
}
|
||||
|
||||
static double toDouble(const std::string& input) {
|
||||
char* e;
|
||||
errno = 0;
|
||||
|
||||
if (input.find('%') == input.length() - 1) {
|
||||
double v = std::strtod(input.substr(0, input.find("%")).c_str(), &e) / 100;
|
||||
if (*e != '\0' || errno != 0) throw std::runtime_error("error decoding num from string");
|
||||
return v - PERCENT_DIFF; // Percentages are going to be stored in negatives. Ew.
|
||||
}
|
||||
|
||||
double v = round(std::strtod(input.c_str(), &e));
|
||||
if (*e != '\0' || errno != 0) throw std::runtime_error("error decoding num from string");
|
||||
return v;
|
||||
}
|
||||
|
||||
static double convertNum(float input, unsigned int multiple) {
|
||||
if (input >= -PERCENT_DIFF - 100 && input < -PERCENT_DIFF + 100) {
|
||||
if (!multiple) return input + PERCENT_DIFF;
|
||||
else return (((input + PERCENT_DIFF) * multiple / SCALE_MODIFIER) * SCALE_MODIFIER);
|
||||
}
|
||||
|
||||
return input * SCALE_MODIFIER;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> static T calcNumbers(const T in, glm::ivec2 multiple = {}) {};
|
||||
|
||||
template <typename T> static T get(const LuaGuiElement& elem, const std::string& req, glm::ivec2 multiple = {}) {
|
||||
if (!elem.has<T>(req)) return T{};
|
||||
return calcNumbers<T>(elem.get<T>(req), multiple);
|
||||
}
|
||||
|
||||
template <> glm::vec2 calcNumbers<glm::vec2>(const glm::vec2 in, glm::ivec2 multiple) {
|
||||
return {convertNum(in.x, multiple.x), convertNum(in.y, multiple.y)};
|
||||
}
|
||||
|
||||
template <> glm::vec4 calcNumbers<glm::vec4>(const glm::vec4 in, glm::ivec2 multiple) {
|
||||
return {convertNum(in.x, multiple.x), convertNum(in.y, multiple.y), convertNum(in.z, multiple.x), convertNum(in.w, multiple.y)};
|
||||
}
|
||||
const float SCALE_MODIFIER = 3;
|
||||
const float PERCENT_DIFF = 10000;
|
||||
|
||||
namespace {
|
||||
static std::vector<std::string> split(const std::string& value, unsigned int targetCount = 0) {
|
||||
std::vector<std::string> vec{};
|
||||
|
||||
if (value == "") throw std::runtime_error("expected one or more values to split");
|
||||
|
||||
size_t count = std::count(value.begin(), value.end(), ' ');
|
||||
if (count + 1 > targetCount) throw std::runtime_error("expected less values");
|
||||
|
||||
// Split the values into the vector.
|
||||
size_t begin = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
size_t end = value.find(' ', begin);
|
||||
vec.push_back(value.substr(begin, end - begin));
|
||||
begin = end + 1;
|
||||
}
|
||||
vec.push_back(value.substr(begin));
|
||||
|
||||
// Duplicate values until we meet or surpass the expected values.
|
||||
while (vec.size() < targetCount) for (auto& v: vec) vec.push_back(v);
|
||||
if (vec.size() > targetCount) throw std::runtime_error("values are not a division of expectation");
|
||||
|
||||
return std::move(vec);
|
||||
}
|
||||
|
||||
static double toDouble(const std::string& input) {
|
||||
char* e;
|
||||
errno = 0;
|
||||
|
||||
if (input.find('%') == input.length() - 1) {
|
||||
double v = std::strtod(input.substr(0, input.find("%")).c_str(), &e) / 100;
|
||||
if (*e != '\0' || errno != 0) throw std::runtime_error("error decoding num from string");
|
||||
return v - PERCENT_DIFF; // Percentages are going to be stored in negatives. Ew.
|
||||
}
|
||||
|
||||
double v = round(std::strtod(input.c_str(), &e));
|
||||
if (*e != '\0' || errno != 0) throw std::runtime_error("error decoding num from string");
|
||||
return v;
|
||||
}
|
||||
|
||||
static double convertNum(float input, unsigned int multiple) {
|
||||
if (input >= -PERCENT_DIFF - 100 && input < -PERCENT_DIFF + 100) {
|
||||
if (!multiple) return input + PERCENT_DIFF;
|
||||
else return (((input + PERCENT_DIFF) * multiple / SCALE_MODIFIER) * SCALE_MODIFIER);
|
||||
}
|
||||
|
||||
return input * SCALE_MODIFIER;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T calcNumbers(const T in, glm::ivec2 multiple = {}) {};
|
||||
|
||||
template<typename T>
|
||||
static T get(const LuaGuiElement& elem, const std::string& req, glm::ivec2 multiple = {}) {
|
||||
if (!elem.has<T>(req)) return T{};
|
||||
return calcNumbers<T>(elem.get<T>(req), multiple);
|
||||
}
|
||||
|
||||
template<>
|
||||
glm::vec2 calcNumbers<glm::vec2>(const glm::vec2 in, glm::ivec2 multiple) {
|
||||
return { convertNum(in.x, multiple.x), convertNum(in.y, multiple.y) };
|
||||
}
|
||||
|
||||
template<>
|
||||
glm::vec4 calcNumbers<glm::vec4>(const glm::vec4 in, glm::ivec2 multiple) {
|
||||
return { convertNum(in.x, multiple.x), convertNum(in.y, multiple.y), convertNum(in.z, multiple.x),
|
||||
convertNum(in.w, multiple.y) };
|
||||
}
|
||||
};
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
#include "GuiContainer.h"
|
||||
|
||||
GuiContainer::GuiContainer(const std::string &key) : GuiComponent(key) {}
|
||||
GuiContainer::GuiContainer(const std::string& key) : GuiComponent(key) {}
|
||||
|
||||
void GuiContainer::draw(Renderer &renderer) {
|
||||
for (const auto& child : children) {
|
||||
child->draw(renderer);
|
||||
}
|
||||
void GuiContainer::draw(Renderer& renderer) {
|
||||
for (const auto& child : children) {
|
||||
child->draw(renderer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,11 @@
|
|||
#include "client/gui/GuiComponent.h"
|
||||
|
||||
class GuiContainer : public GuiComponent {
|
||||
public:
|
||||
GuiContainer() = default;
|
||||
explicit GuiContainer(const std::string& key);
|
||||
|
||||
void draw(Renderer& renderer) override;
|
||||
public:
|
||||
GuiContainer() = default;
|
||||
|
||||
explicit GuiContainer(const std::string& key);
|
||||
|
||||
void draw(Renderer& renderer) override;
|
||||
};
|
||||
|
||||
|
|
|
@ -8,99 +8,103 @@
|
|||
#include "client/graph/Model.h"
|
||||
#include "game/atlas/asset/AtlasRef.h"
|
||||
|
||||
GuiGraph::GuiGraph(const std::string &key) : GuiComponent(key) {}
|
||||
GuiGraph::GuiGraph(const std::string& key) : GuiComponent(key) {}
|
||||
|
||||
void GuiGraph::create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr <AtlasRef> texture,
|
||||
unsigned int length, float maxValue, bool editInPlace) {
|
||||
|
||||
this->scale = scale;
|
||||
this->padding = padding;
|
||||
|
||||
setScale({scale.x + padding.w + padding.y, scale.y + padding.x + padding.z});
|
||||
|
||||
this->length = length;
|
||||
this->maxVal = maxValue;
|
||||
this->dynamicMax = maxValue <= 0;
|
||||
this->editInPlace = editInPlace;
|
||||
this->texture = std::move(texture);
|
||||
|
||||
history = std::vector<float>(static_cast<unsigned long>(length));
|
||||
|
||||
entity.setModel(std::make_shared<Model>());
|
||||
void GuiGraph::create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr<AtlasRef> texture,
|
||||
unsigned int length, float maxValue, bool editInPlace) {
|
||||
|
||||
this->scale = scale;
|
||||
this->padding = padding;
|
||||
|
||||
setScale({ scale.x + padding.w + padding.y, scale.y + padding.x + padding.z });
|
||||
|
||||
this->length = length;
|
||||
this->maxVal = maxValue;
|
||||
this->dynamicMax = maxValue <= 0;
|
||||
this->editInPlace = editInPlace;
|
||||
this->texture = std::move(texture);
|
||||
|
||||
history = std::vector<float>(static_cast<unsigned long>(length));
|
||||
|
||||
entity.setModel(std::make_shared<Model>());
|
||||
}
|
||||
|
||||
void GuiGraph::pushValue(float value) {
|
||||
if (editInPlace) {
|
||||
insertionPoint++;
|
||||
if (insertionPoint >= length) insertionPoint = 0;
|
||||
history[insertionPoint] = value;
|
||||
}
|
||||
else {
|
||||
if (insertionPoint < length - 1) insertionPoint++;
|
||||
else {
|
||||
for (int i = 0; i < length; i++) {
|
||||
history[i] = history[i + 1];
|
||||
}
|
||||
}
|
||||
history[insertionPoint] = value;
|
||||
}
|
||||
if (dynamicMax) {
|
||||
maxVal = 0;
|
||||
for (float i : history) {
|
||||
if (i > maxVal) maxVal = i;
|
||||
}
|
||||
}
|
||||
|
||||
buildHistogramMesh();
|
||||
if (editInPlace) {
|
||||
insertionPoint++;
|
||||
if (insertionPoint >= length) insertionPoint = 0;
|
||||
history[insertionPoint] = value;
|
||||
}
|
||||
else {
|
||||
if (insertionPoint < length - 1) insertionPoint++;
|
||||
else {
|
||||
for (int i = 0; i < length; i++) {
|
||||
history[i] = history[i + 1];
|
||||
}
|
||||
}
|
||||
history[insertionPoint] = value;
|
||||
}
|
||||
if (dynamicMax) {
|
||||
maxVal = 0;
|
||||
for (float i : history) {
|
||||
if (i > maxVal) maxVal = i;
|
||||
}
|
||||
}
|
||||
|
||||
buildHistogramMesh();
|
||||
}
|
||||
|
||||
void GuiGraph::setMax(float max) {
|
||||
maxVal = max;
|
||||
maxVal = max;
|
||||
}
|
||||
|
||||
void GuiGraph::buildHistogramMesh() {
|
||||
std::vector<EntityVertex> vertices {};
|
||||
std::vector<unsigned int> indices {};
|
||||
|
||||
auto uv = texture->uv;
|
||||
uv.z -= uv.x;
|
||||
uv.w -= uv.y;
|
||||
|
||||
unsigned int indOffset = 0;
|
||||
float xOffset = 0;
|
||||
|
||||
for (float num : history) {
|
||||
float distFromPointer = (xOffset <= insertionPoint) ? insertionPoint - xOffset : insertionPoint + length - xOffset;
|
||||
float age = std::round((90 - (distFromPointer / length)*90)) / 100.0f;
|
||||
|
||||
float h = num / maxVal;
|
||||
float sec = (float)std::round(9 - fmin(h, 1)*9) * 0.1f;
|
||||
|
||||
auto columnVerts = std::vector<EntityVertex> {
|
||||
{{xOffset, -h, 0}, {uv.x + age * uv.z, uv.y + sec * uv.w, 0, 1}, {1, 1, 1}, true, {}, {}, {}},
|
||||
{{xOffset + 1,-h, 0}, {uv.x + (age+0.01f) * uv.z, uv.y + sec * uv.w, 0, 1}, {1, 1, 1}, true, {}, {}, {}},
|
||||
{{xOffset + 1, 0, 0}, {uv.x + (age+0.01f) * uv.z, uv.y + (sec+0.10f) * uv.w, 0, 1}, {1, 1, 1}, true, {}, {}, {}},
|
||||
{{xOffset, 0, 0}, {uv.x + age * uv.z, uv.y + (sec+0.10f) * uv.w, 0, 1}, {1, 1, 1}, true, {}, {}, {}},
|
||||
};
|
||||
|
||||
vertices.insert(vertices.end(), columnVerts.begin(), columnVerts.end());
|
||||
|
||||
indices.push_back( indOffset);
|
||||
indices.push_back(3 + indOffset);
|
||||
indices.push_back(1 + indOffset);
|
||||
indices.push_back(3 + indOffset);
|
||||
indices.push_back(2 + indOffset);
|
||||
indices.push_back(1 + indOffset);
|
||||
|
||||
xOffset ++;
|
||||
indOffset += 4;
|
||||
}
|
||||
|
||||
auto m = std::make_unique<EntityMesh>();
|
||||
m->create(vertices, indices);
|
||||
|
||||
auto model = std::make_shared<Model>();
|
||||
model->fromMesh(std::move(m));
|
||||
|
||||
entity.setModel(model);
|
||||
std::vector<EntityVertex> vertices{};
|
||||
std::vector<unsigned int> indices{};
|
||||
|
||||
auto uv = texture->uv;
|
||||
uv.z -= uv.x;
|
||||
uv.w -= uv.y;
|
||||
|
||||
unsigned int indOffset = 0;
|
||||
float xOffset = 0;
|
||||
|
||||
for (float num : history) {
|
||||
float distFromPointer = (xOffset <= insertionPoint) ? insertionPoint - xOffset : insertionPoint + length -
|
||||
xOffset;
|
||||
float age = std::round((90 - (distFromPointer / length) * 90)) / 100.0f;
|
||||
|
||||
float h = num / maxVal;
|
||||
float sec = (float) std::round(9 - fmin(h, 1) * 9) * 0.1f;
|
||||
|
||||
auto columnVerts = std::vector<EntityVertex>{
|
||||
{{ xOffset, -h, 0 }, { uv.x + age * uv.z, uv.y + sec * uv.w, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}},
|
||||
{{ xOffset + 1, -h, 0 }, { uv.x + (age + 0.01f) * uv.z, uv.y + sec * uv.w, 0, 1 }, { 1, 1, 1 }, true, {},
|
||||
{}, {}},
|
||||
{{ xOffset + 1, 0, 0 }, { uv.x + (age + 0.01f) * uv.z, uv.y + (sec + 0.10f) * uv.w, 0, 1 }, { 1, 1, 1 },
|
||||
true, {}, {}, {}},
|
||||
{{ xOffset, 0, 0 }, { uv.x + age * uv.z, uv.y + (sec + 0.10f) * uv.w, 0, 1 }, { 1, 1, 1 }, true, {}, {},
|
||||
{}},
|
||||
};
|
||||
|
||||
vertices.insert(vertices.end(), columnVerts.begin(), columnVerts.end());
|
||||
|
||||
indices.push_back(indOffset);
|
||||
indices.push_back(3 + indOffset);
|
||||
indices.push_back(1 + indOffset);
|
||||
indices.push_back(3 + indOffset);
|
||||
indices.push_back(2 + indOffset);
|
||||
indices.push_back(1 + indOffset);
|
||||
|
||||
xOffset++;
|
||||
indOffset += 4;
|
||||
}
|
||||
|
||||
auto m = std::make_unique<EntityMesh>();
|
||||
m->create(vertices, indices);
|
||||
|
||||
auto model = std::make_shared<Model>();
|
||||
model->fromMesh(std::move(m));
|
||||
|
||||
entity.setModel(model);
|
||||
}
|
||||
|
|
|
@ -9,26 +9,31 @@
|
|||
class AtlasRef;
|
||||
|
||||
class GuiGraph : public GuiComponent {
|
||||
public:
|
||||
GuiGraph() = default;
|
||||
GuiGraph(const std::string& key);
|
||||
|
||||
void create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr<AtlasRef> texture, unsigned int length, float maxValue, bool editInPlace);
|
||||
|
||||
void setMax(float max);
|
||||
void pushValue(float value);
|
||||
private:
|
||||
void buildHistogramMesh();
|
||||
|
||||
bool editInPlace = false;
|
||||
|
||||
unsigned int insertionPoint = 0;
|
||||
unsigned int length = 60;
|
||||
|
||||
bool dynamicMax = true;
|
||||
float maxVal = 0;
|
||||
|
||||
std::shared_ptr<AtlasRef> texture;
|
||||
std::vector<float> history;
|
||||
public:
|
||||
GuiGraph() = default;
|
||||
|
||||
GuiGraph(const std::string& key);
|
||||
|
||||
void
|
||||
create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr<AtlasRef> texture, unsigned int length, float maxValue,
|
||||
bool editInPlace);
|
||||
|
||||
void setMax(float max);
|
||||
|
||||
void pushValue(float value);
|
||||
|
||||
private:
|
||||
void buildHistogramMesh();
|
||||
|
||||
bool editInPlace = false;
|
||||
|
||||
unsigned int insertionPoint = 0;
|
||||
unsigned int length = 60;
|
||||
|
||||
bool dynamicMax = true;
|
||||
float maxVal = 0;
|
||||
|
||||
std::shared_ptr<AtlasRef> texture;
|
||||
std::vector<float> history;
|
||||
};
|
||||
|
||||
|
|
|
@ -11,41 +11,41 @@
|
|||
#include "game/def/BlockDef.h"
|
||||
#include "game/def/CraftItemDef.h"
|
||||
|
||||
GuiInventoryItem::GuiInventoryItem(const std::string &key) : GuiContainer(key) {}
|
||||
GuiInventoryItem::GuiInventoryItem(const std::string& key) : GuiContainer(key) {}
|
||||
|
||||
void GuiInventoryItem::create(glm::vec2 scale, unsigned short count, ItemDef& def, Font f) {
|
||||
|
||||
if (def.type == ItemDef::Type::CRAFTITEM) {
|
||||
auto texture = static_cast<CraftItemDef&>(def).textureRefs[0];
|
||||
|
||||
auto shadow = std::make_shared<GuiRect>("shadow");
|
||||
shadow->create(scale * 16.f, {}, texture, {0, 0, 0, 0.2});
|
||||
add(shadow);
|
||||
shadow->setPos(scale);
|
||||
|
||||
auto item = std::make_shared<GuiRect>("mesh");
|
||||
item->create(scale * 16.f, {}, texture);
|
||||
add(item);
|
||||
}
|
||||
else {
|
||||
auto& model = static_cast<BlockDef&>(def).entityModel;
|
||||
|
||||
auto item = std::make_shared<GuiModel>("mesh");
|
||||
item->create(scale * 10.5f, model);
|
||||
item->setPos(glm::vec2{8, 8} * scale);
|
||||
|
||||
item->setRotationX(180.f - 30.f);
|
||||
item->setRotationY(45.f);
|
||||
item->setRotationZ(0.f);
|
||||
|
||||
add(item);
|
||||
}
|
||||
|
||||
if (count > 1) {
|
||||
auto text = std::make_shared<GuiText>("count");
|
||||
text->create(scale, {}, {}, {1, 1, 1, 1}, f);
|
||||
text->setText(std::to_string(count));
|
||||
add(text);
|
||||
text->setPos({(19 - text->getWidth()) * scale.x, 9 * scale.y});
|
||||
}
|
||||
|
||||
if (def.type == ItemDef::Type::CRAFTITEM) {
|
||||
auto texture = static_cast<CraftItemDef&>(def).textureRefs[0];
|
||||
|
||||
auto shadow = std::make_shared<GuiRect>("shadow");
|
||||
shadow->create(scale * 16.f, {}, texture, { 0, 0, 0, 0.2 });
|
||||
add(shadow);
|
||||
shadow->setPos(scale);
|
||||
|
||||
auto item = std::make_shared<GuiRect>("mesh");
|
||||
item->create(scale * 16.f, {}, texture);
|
||||
add(item);
|
||||
}
|
||||
else {
|
||||
auto& model = static_cast<BlockDef&>(def).entityModel;
|
||||
|
||||
auto item = std::make_shared<GuiModel>("mesh");
|
||||
item->create(scale * 10.5f, model);
|
||||
item->setPos(glm::vec2{ 8, 8 } * scale);
|
||||
|
||||
item->setRotationX(180.f - 30.f);
|
||||
item->setRotationY(45.f);
|
||||
item->setRotationZ(0.f);
|
||||
|
||||
add(item);
|
||||
}
|
||||
|
||||
if (count > 1) {
|
||||
auto text = std::make_shared<GuiText>("count");
|
||||
text->create(scale, {}, {}, { 1, 1, 1, 1 }, f);
|
||||
text->setText(std::to_string(count));
|
||||
add(text);
|
||||
text->setPos({ (19 - text->getWidth()) * scale.x, 9 * scale.y });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,12 +7,14 @@
|
|||
#include "GuiContainer.h"
|
||||
|
||||
class ItemDef;
|
||||
|
||||
class Font;
|
||||
|
||||
class GuiInventoryItem : public GuiContainer {
|
||||
public:
|
||||
GuiInventoryItem() = default;
|
||||
GuiInventoryItem(const std::string& key);
|
||||
|
||||
void create(glm::vec2 scale, unsigned short itemCount, ItemDef& def, Font font);
|
||||
public:
|
||||
GuiInventoryItem() = default;
|
||||
|
||||
GuiInventoryItem(const std::string& key);
|
||||
|
||||
void create(glm::vec2 scale, unsigned short itemCount, ItemDef& def, Font font);
|
||||
};
|
||||
|
|
|
@ -11,61 +11,62 @@
|
|||
#include "game/atlas/asset/ModelStore.h"
|
||||
#include "game/atlas/TextureAtlas.h"
|
||||
|
||||
GuiModel::GuiModel(const std::string &key) : GuiComponent(key) {}
|
||||
GuiModel::GuiModel(const std::string& key) : GuiComponent(key) {}
|
||||
|
||||
std::shared_ptr<GuiModel> GuiModel::fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, ModelStore& models, glm::ivec2 bounds) {
|
||||
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
|
||||
glm::vec2 scale = SerialGui::get<glm::vec2>(elem, "scale");
|
||||
glm::vec2 anim_range = SerialGui::get<glm::vec2>(elem, "anim_range");
|
||||
if (scale == glm::vec2{0, 0}) scale = {1, 1};
|
||||
|
||||
std::string type = elem.get_or<std::string>("type", "model");
|
||||
std::string source = elem.get_or<std::string>("source", "");
|
||||
std::string texture = elem.get_or<std::string>("texture", "");
|
||||
|
||||
auto m = std::make_shared<Model>();
|
||||
if (type == "model") m->fromSerialized(models.models[source], {textures[texture]});
|
||||
|
||||
auto model = std::make_shared<GuiModel>(elem.key);
|
||||
model->create(scale, m);
|
||||
model->setPos(pos);
|
||||
|
||||
if (anim_range.y != 0) model->animate(anim_range);
|
||||
|
||||
return model;
|
||||
std::shared_ptr<GuiModel>
|
||||
GuiModel::fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, ModelStore& models, glm::ivec2 bounds) {
|
||||
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
|
||||
glm::vec2 scale = SerialGui::get<glm::vec2>(elem, "scale");
|
||||
glm::vec2 anim_range = SerialGui::get<glm::vec2>(elem, "anim_range");
|
||||
if (scale == glm::vec2{ 0, 0 }) scale = { 1, 1 };
|
||||
|
||||
std::string type = elem.get_or<std::string>("type", "model");
|
||||
std::string source = elem.get_or<std::string>("source", "");
|
||||
std::string texture = elem.get_or<std::string>("texture", "");
|
||||
|
||||
auto m = std::make_shared<Model>();
|
||||
if (type == "model") m->fromSerialized(models.models[source], { textures[texture] });
|
||||
|
||||
auto model = std::make_shared<GuiModel>(elem.key);
|
||||
model->create(scale, m);
|
||||
model->setPos(pos);
|
||||
|
||||
if (anim_range.y != 0) model->animate(anim_range);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
void GuiModel::create(glm::vec2 scale, std::shared_ptr<Model> model) {
|
||||
entity.setModel(model);
|
||||
setScale({scale.x + padding.w + padding.y, scale.y + padding.x + padding.z});
|
||||
|
||||
setRotationX(180);
|
||||
setRotationY(215);
|
||||
entity.setModel(model);
|
||||
setScale({ scale.x + padding.w + padding.y, scale.y + padding.x + padding.z });
|
||||
|
||||
setRotationX(180);
|
||||
setRotationY(215);
|
||||
}
|
||||
|
||||
void GuiModel::update(double delta) {
|
||||
entity.update(delta);
|
||||
entity.update(delta);
|
||||
}
|
||||
|
||||
void GuiModel::animate(glm::vec2 range) {
|
||||
entity.animation.setAnim(range, 0, true);
|
||||
entity.animation.setAnim(range, 0, true);
|
||||
}
|
||||
|
||||
void GuiModel::setRotationX(float x) {
|
||||
entity.setRotateX(x);
|
||||
entity.setRotateX(x);
|
||||
}
|
||||
|
||||
void GuiModel::setRotationY(float y) {
|
||||
entity.setRotateY(y);
|
||||
entity.setRotateY(y);
|
||||
}
|
||||
|
||||
void GuiModel::setRotationZ(float z) {
|
||||
entity.setRotateZ(z);
|
||||
entity.setRotateZ(z);
|
||||
}
|
||||
|
||||
void GuiModel::draw(Renderer &renderer) {
|
||||
renderer.toggleDepthTest(true);
|
||||
renderer.clearDepthBuffer();
|
||||
GuiComponent::draw(renderer);
|
||||
renderer.toggleDepthTest(false);
|
||||
void GuiModel::draw(Renderer& renderer) {
|
||||
renderer.toggleDepthTest(true);
|
||||
renderer.clearDepthBuffer();
|
||||
GuiComponent::draw(renderer);
|
||||
renderer.toggleDepthTest(false);
|
||||
}
|
||||
|
|
|
@ -9,27 +9,36 @@
|
|||
#include "GuiContainer.h"
|
||||
|
||||
class LocalSubgame;
|
||||
|
||||
class ModelStore;
|
||||
|
||||
class TextureAtlas;
|
||||
|
||||
class LuaGuiElement;
|
||||
|
||||
class GuiModel : public GuiComponent {
|
||||
public:
|
||||
GuiModel() = default;
|
||||
GuiModel(const std::string& key);
|
||||
|
||||
static std::shared_ptr<GuiModel> fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, ModelStore& models, glm::ivec2 bounds);
|
||||
|
||||
void create(glm::vec2 scale, std::shared_ptr<Model> model);
|
||||
void update(double delta) override;
|
||||
|
||||
void animate(glm::vec2 range);
|
||||
|
||||
void setRotationX(float x);
|
||||
void setRotationY(float x);
|
||||
void setRotationZ(float x);
|
||||
|
||||
void draw(Renderer& renderer) override;
|
||||
protected:
|
||||
float depth = 300;
|
||||
public:
|
||||
GuiModel() = default;
|
||||
|
||||
GuiModel(const std::string& key);
|
||||
|
||||
static std::shared_ptr<GuiModel>
|
||||
fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, ModelStore& models, glm::ivec2 bounds);
|
||||
|
||||
void create(glm::vec2 scale, std::shared_ptr<Model> model);
|
||||
|
||||
void update(double delta) override;
|
||||
|
||||
void animate(glm::vec2 range);
|
||||
|
||||
void setRotationX(float x);
|
||||
|
||||
void setRotationY(float x);
|
||||
|
||||
void setRotationZ(float x);
|
||||
|
||||
void draw(Renderer& renderer) override;
|
||||
|
||||
protected:
|
||||
float depth = 300;
|
||||
};
|
||||
|
|
|
@ -10,111 +10,111 @@
|
|||
#include "game/atlas/TextureAtlas.h"
|
||||
#include "game/atlas/asset/AtlasRef.h"
|
||||
|
||||
GuiRect::GuiRect(const std::string &key) : GuiComponent(key) {}
|
||||
GuiRect::GuiRect(const std::string& key) : GuiComponent(key) {}
|
||||
|
||||
std::shared_ptr<GuiRect> GuiRect::fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds) {
|
||||
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
|
||||
glm::vec2 offset = SerialGui::get<glm::vec2>(elem, "position_anchor");
|
||||
glm::vec2 size = SerialGui::get<glm::vec2>(elem, "size", bounds);
|
||||
glm::vec4 padding = SerialGui::get<glm::vec4>(elem, "padding", bounds);
|
||||
|
||||
pos -= offset * size;
|
||||
size -= glm::vec2 {padding.y + padding.w, padding.x + padding.z};
|
||||
|
||||
std::string background = elem.get_or<std::string>("background", "");
|
||||
bool hideOverflow = elem.get_or<std::string>("overflow", "visible") == "hidden";
|
||||
|
||||
auto rect = std::make_shared<GuiRect>(elem.key);
|
||||
if (background[0] == '#') rect->create(size, padding, Util::hexToColorVec(background));
|
||||
else if (background.size() > 0) rect->create(size, padding, textures[background]);
|
||||
else rect->create(size, padding, glm::vec4 {});
|
||||
rect->setOverflows(!hideOverflow);
|
||||
rect->setPos(pos);
|
||||
return rect;
|
||||
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
|
||||
glm::vec2 offset = SerialGui::get<glm::vec2>(elem, "position_anchor");
|
||||
glm::vec2 size = SerialGui::get<glm::vec2>(elem, "size", bounds);
|
||||
glm::vec4 padding = SerialGui::get<glm::vec4>(elem, "padding", bounds);
|
||||
|
||||
pos -= offset * size;
|
||||
size -= glm::vec2{ padding.y + padding.w, padding.x + padding.z };
|
||||
|
||||
std::string background = elem.get_or<std::string>("background", "");
|
||||
bool hideOverflow = elem.get_or<std::string>("overflow", "visible") == "hidden";
|
||||
|
||||
auto rect = std::make_shared<GuiRect>(elem.key);
|
||||
if (background[0] == '#') rect->create(size, padding, Util::hexToColorVec(background));
|
||||
else if (background.size() > 0) rect->create(size, padding, textures[background]);
|
||||
else rect->create(size, padding, glm::vec4{});
|
||||
rect->setOverflows(!hideOverflow);
|
||||
rect->setPos(pos);
|
||||
return rect;
|
||||
}
|
||||
|
||||
// Single Color Constructor
|
||||
// Creates a GuiRect object whose background
|
||||
// is a flat color defined by 'color'.
|
||||
void GuiRect::create(glm::vec2 scale, glm::vec4 padding, glm::vec4 color) {
|
||||
this->scale = scale;
|
||||
this->padding = padding;
|
||||
|
||||
auto mesh = std::make_unique<EntityMesh>();
|
||||
mesh->create({{{0, 0, 0}, color, {1, 1, 1}, false, {}, {}, {}},
|
||||
{{0, 1, 0}, color, {1, 1, 1}, false, {}, {}, {}},
|
||||
{{1, 1, 0}, color, {1, 1, 1}, false, {}, {}, {}},
|
||||
{{1, 0, 0}, color, {1, 1, 1}, false, {}, {}, {}}
|
||||
}, {0, 1, 2, 2, 3, 0});
|
||||
auto model = std::make_shared<Model>();
|
||||
model->fromMesh(std::move(mesh));
|
||||
|
||||
entity.setModel(model);
|
||||
setScale({scale.x + padding.w + padding.y, scale.y + padding.x + padding.z});
|
||||
this->scale = scale;
|
||||
this->padding = padding;
|
||||
|
||||
auto mesh = std::make_unique<EntityMesh>();
|
||||
mesh->create({{{ 0, 0, 0 }, color, { 1, 1, 1 }, false, {}, {}, {}},
|
||||
{{ 0, 1, 0 }, color, { 1, 1, 1 }, false, {}, {}, {}},
|
||||
{{ 1, 1, 0 }, color, { 1, 1, 1 }, false, {}, {}, {}},
|
||||
{{ 1, 0, 0 }, color, { 1, 1, 1 }, false, {}, {}, {}}
|
||||
}, { 0, 1, 2, 2, 3, 0 });
|
||||
auto model = std::make_shared<Model>();
|
||||
model->fromMesh(std::move(mesh));
|
||||
|
||||
entity.setModel(model);
|
||||
setScale({ scale.x + padding.w + padding.y, scale.y + padding.x + padding.z });
|
||||
}
|
||||
|
||||
// Multiple Color Constructor
|
||||
// Creates a GuiRect object with a gradient background
|
||||
// defined by 'tl', 'tr', 'bl', and 'br'.
|
||||
void GuiRect::create(glm::vec2 scale, glm::vec4 padding, glm::vec4 tl, glm::vec4 tr, glm::vec4 bl, glm::vec4 br) {
|
||||
this->scale = scale;
|
||||
this->padding = padding;
|
||||
|
||||
auto mesh = std::make_unique<EntityMesh>();
|
||||
mesh->create({
|
||||
{{0, 0, 0}, tl, {1, 1, 1}, false, {}, {}, {}},
|
||||
{{0, 1, 0}, bl, {1, 1, 1}, false, {}, {}, {}},
|
||||
{{1, 1, 0}, br, {1, 1, 1}, false, {}, {}, {}},
|
||||
{{1, 0, 0}, tr, {1, 1, 1}, false, {}, {}, {}}
|
||||
}, {0, 1, 2, 2, 3, 0});
|
||||
auto model = std::make_shared<Model>();
|
||||
model->fromMesh(std::move(mesh));
|
||||
|
||||
entity.setModel(model);
|
||||
setScale({scale.x + padding.w + padding.y, scale.y + padding.x + padding.z});
|
||||
this->scale = scale;
|
||||
this->padding = padding;
|
||||
|
||||
auto mesh = std::make_unique<EntityMesh>();
|
||||
mesh->create({
|
||||
{{ 0, 0, 0 }, tl, { 1, 1, 1 }, false, {}, {}, {}},
|
||||
{{ 0, 1, 0 }, bl, { 1, 1, 1 }, false, {}, {}, {}},
|
||||
{{ 1, 1, 0 }, br, { 1, 1, 1 }, false, {}, {}, {}},
|
||||
{{ 1, 0, 0 }, tr, { 1, 1, 1 }, false, {}, {}, {}}
|
||||
}, { 0, 1, 2, 2, 3, 0 });
|
||||
auto model = std::make_shared<Model>();
|
||||
model->fromMesh(std::move(mesh));
|
||||
|
||||
entity.setModel(model);
|
||||
setScale({ scale.x + padding.w + padding.y, scale.y + padding.x + padding.z });
|
||||
}
|
||||
|
||||
// Texture Constructor
|
||||
// Creates a GuiRect object with a textured background
|
||||
// defined by the 'texture' reference.
|
||||
void GuiRect::create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr<AtlasRef> texture) {
|
||||
this->scale = scale;
|
||||
this->padding = padding;
|
||||
this->texture = texture;
|
||||
this->hitbox = scale + glm::vec2{padding.y + padding.w, padding.x + padding.z};
|
||||
|
||||
auto mesh = std::make_unique<EntityMesh>();
|
||||
mesh->create({
|
||||
{{0, 0, 0}, {this->texture->uv.x, this->texture->uv.y, 0, 1}, {1, 1, 1}, true, {}, {}, {}},
|
||||
{{0, 1, 0}, {this->texture->uv.x, this->texture->uv.w, 0, 1}, {1, 1, 1}, true, {}, {}, {}},
|
||||
{{1, 1, 0}, {this->texture->uv.z, this->texture->uv.w, 0, 1}, {1, 1, 1}, true, {}, {}, {}},
|
||||
{{1, 0, 0}, {this->texture->uv.z, this->texture->uv.y, 0, 1}, {1, 1, 1}, true, {}, {}, {}}
|
||||
}, {0, 1, 2, 2, 3, 0});
|
||||
auto model = std::make_shared<Model>();
|
||||
model->fromMesh(std::move(mesh));
|
||||
|
||||
entity.setModel(model);
|
||||
setScale({scale.x + padding.w + padding.y, scale.y + padding.x + padding.z});
|
||||
this->scale = scale;
|
||||
this->padding = padding;
|
||||
this->texture = texture;
|
||||
this->hitbox = scale + glm::vec2{ padding.y + padding.w, padding.x + padding.z };
|
||||
|
||||
auto mesh = std::make_unique<EntityMesh>();
|
||||
mesh->create({
|
||||
{{ 0, 0, 0 }, { this->texture->uv.x, this->texture->uv.y, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}},
|
||||
{{ 0, 1, 0 }, { this->texture->uv.x, this->texture->uv.w, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}},
|
||||
{{ 1, 1, 0 }, { this->texture->uv.z, this->texture->uv.w, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}},
|
||||
{{ 1, 0, 0 }, { this->texture->uv.z, this->texture->uv.y, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}}
|
||||
}, { 0, 1, 2, 2, 3, 0 });
|
||||
auto model = std::make_shared<Model>();
|
||||
model->fromMesh(std::move(mesh));
|
||||
|
||||
entity.setModel(model);
|
||||
setScale({ scale.x + padding.w + padding.y, scale.y + padding.x + padding.z });
|
||||
}
|
||||
|
||||
// Texture Constructor
|
||||
// Creates a GuiRect object with a textured background
|
||||
// defined by the 'texture' reference.
|
||||
void GuiRect::create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr<AtlasRef> texture, glm::vec4 tint) {
|
||||
this->scale = scale;
|
||||
this->padding = padding;
|
||||
this->texture = std::move(texture);
|
||||
|
||||
auto mesh = std::make_unique<EntityMesh>();
|
||||
mesh->create({
|
||||
{{0, 0, 0}, {this->texture->uv.x, this->texture->uv.y, 0, tint.w}, glm::vec3{tint}, true, {}, {}, {}},
|
||||
{{0, 1, 0}, {this->texture->uv.x, this->texture->uv.w, 0, tint.w}, glm::vec3{tint}, true, {}, {}, {}},
|
||||
{{1, 1, 0}, {this->texture->uv.z, this->texture->uv.w, 0, tint.w}, glm::vec3{tint}, true, {}, {}, {}},
|
||||
{{1, 0, 0}, {this->texture->uv.z, this->texture->uv.y, 0, tint.w}, glm::vec3{tint}, true, {}, {}, {}}
|
||||
}, {0, 1, 2, 2, 3, 0});
|
||||
auto model = std::make_shared<Model>();
|
||||
model->fromMesh(std::move(mesh));
|
||||
|
||||
entity.setModel(model);
|
||||
setScale({scale.x + padding.w + padding.y, scale.y + padding.x + padding.z});
|
||||
this->scale = scale;
|
||||
this->padding = padding;
|
||||
this->texture = std::move(texture);
|
||||
|
||||
auto mesh = std::make_unique<EntityMesh>();
|
||||
mesh->create({
|
||||
{{ 0, 0, 0 }, { this->texture->uv.x, this->texture->uv.y, 0, tint.w }, glm::vec3{ tint }, true, {}, {}, {}},
|
||||
{{ 0, 1, 0 }, { this->texture->uv.x, this->texture->uv.w, 0, tint.w }, glm::vec3{ tint }, true, {}, {}, {}},
|
||||
{{ 1, 1, 0 }, { this->texture->uv.z, this->texture->uv.w, 0, tint.w }, glm::vec3{ tint }, true, {}, {}, {}},
|
||||
{{ 1, 0, 0 }, { this->texture->uv.z, this->texture->uv.y, 0, tint.w }, glm::vec3{ tint }, true, {}, {}, {}}
|
||||
}, { 0, 1, 2, 2, 3, 0 });
|
||||
auto model = std::make_shared<Model>();
|
||||
model->fromMesh(std::move(mesh));
|
||||
|
||||
entity.setModel(model);
|
||||
setScale({ scale.x + padding.w + padding.y, scale.y + padding.x + padding.z });
|
||||
}
|
||||
|
|
|
@ -7,23 +7,31 @@
|
|||
#include "client/gui/GuiComponent.h"
|
||||
|
||||
class AtlasRef;
|
||||
|
||||
class LocalSubgame;
|
||||
|
||||
class TextureAtlas;
|
||||
|
||||
class LuaGuiElement;
|
||||
|
||||
class GuiRect : public GuiComponent {
|
||||
public:
|
||||
GuiRect() = default;
|
||||
GuiRect(const std::string& key);
|
||||
|
||||
static std::shared_ptr<GuiRect> fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds);
|
||||
|
||||
void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 color);
|
||||
void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 tl, glm::vec4 tr, glm::vec4 bl, glm::vec4 br);
|
||||
void create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr<AtlasRef> texture);
|
||||
void create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr<AtlasRef> texture, glm::vec4 tint);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<AtlasRef> texture = nullptr;
|
||||
public:
|
||||
GuiRect() = default;
|
||||
|
||||
GuiRect(const std::string& key);
|
||||
|
||||
static std::shared_ptr<GuiRect>
|
||||
fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds);
|
||||
|
||||
void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 color);
|
||||
|
||||
void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 tl, glm::vec4 tr, glm::vec4 bl, glm::vec4 br);
|
||||
|
||||
void create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr<AtlasRef> texture);
|
||||
|
||||
void create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr<AtlasRef> texture, glm::vec4 tint);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<AtlasRef> texture = nullptr;
|
||||
};
|
||||
|
||||
|
|
|
@ -12,170 +12,178 @@
|
|||
#include "game/atlas/asset/AtlasRef.h"
|
||||
#include "world/dim/ent/AnimationSegment.h"
|
||||
|
||||
GuiText::GuiText(const std::string &key) : GuiComponent(key) {}
|
||||
GuiText::GuiText(const std::string& key) : GuiComponent(key) {}
|
||||
|
||||
void GuiText::create(glm::vec2 scale, glm::vec4 padding, glm::vec4 bgcolor, glm::vec4 color, Font font) {
|
||||
// Text Constructor
|
||||
// Creates a GuiText object.
|
||||
|
||||
this->scale = scale;
|
||||
this->padding = padding;
|
||||
this->font = std::move(font);
|
||||
|
||||
this->bgcolor = bgcolor;
|
||||
this->color = color;
|
||||
|
||||
setScale(scale);
|
||||
setText("");
|
||||
// Text Constructor
|
||||
// Creates a GuiText object.
|
||||
|
||||
this->scale = scale;
|
||||
this->padding = padding;
|
||||
this->font = std::move(font);
|
||||
|
||||
this->bgcolor = bgcolor;
|
||||
this->color = color;
|
||||
|
||||
setScale(scale);
|
||||
setText("");
|
||||
}
|
||||
|
||||
std::shared_ptr<GuiText> GuiText::fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds) {
|
||||
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
|
||||
glm::vec2 offset = SerialGui::get<glm::vec2>(elem, "position_anchor");
|
||||
glm::vec2 size = SerialGui::get<glm::vec2>(elem, "size", bounds);
|
||||
glm::vec4 padding = SerialGui::get<glm::vec4>(elem, "padding", bounds);
|
||||
glm::vec2 scale = SerialGui::get<glm::vec2>(elem, "scale");
|
||||
if (scale == glm::vec2{0, 0}) scale = {1, 1};
|
||||
|
||||
pos -= offset * size;
|
||||
|
||||
glm::vec4 background_color = Util::hexToColorVec(elem.get_or<std::string>("background", "#0000"));
|
||||
glm::vec4 color = Util::hexToColorVec(elem.get_or<std::string>("color", "#fff"));
|
||||
std::string content = elem.get_or<std::string>("content", "");
|
||||
|
||||
auto text = std::make_shared<GuiText>(elem.key);
|
||||
text->create(scale * SerialGui::SCALE_MODIFIER, padding, background_color, color, {textures, textures["font"]});
|
||||
text->setText(content);
|
||||
text->setPos(pos);
|
||||
|
||||
return text;
|
||||
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
|
||||
glm::vec2 offset = SerialGui::get<glm::vec2>(elem, "position_anchor");
|
||||
glm::vec2 size = SerialGui::get<glm::vec2>(elem, "size", bounds);
|
||||
glm::vec4 padding = SerialGui::get<glm::vec4>(elem, "padding", bounds);
|
||||
glm::vec2 scale = SerialGui::get<glm::vec2>(elem, "scale");
|
||||
if (scale == glm::vec2{ 0, 0 }) scale = { 1, 1 };
|
||||
|
||||
pos -= offset * size;
|
||||
|
||||
glm::vec4 background_color = Util::hexToColorVec(elem.get_or<std::string>("background", "#0000"));
|
||||
glm::vec4 color = Util::hexToColorVec(elem.get_or<std::string>("color", "#fff"));
|
||||
std::string content = elem.get_or<std::string>("content", "");
|
||||
|
||||
auto text = std::make_shared<GuiText>(elem.key);
|
||||
text->create(scale * SerialGui::SCALE_MODIFIER, padding, background_color, color, { textures, textures["font"] });
|
||||
text->setText(content);
|
||||
text->setPos(pos);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
void GuiText::setText(std::string text) {
|
||||
this->text = std::move(text);
|
||||
unsigned int indOffset = 0;
|
||||
|
||||
maxLineWidth = 0;
|
||||
|
||||
std::vector<EntityVertex> textVertices;
|
||||
textVertices.reserve(text.length()*8 + 200);
|
||||
std::vector<unsigned int> textIndices;
|
||||
textIndices.reserve(text.length()*12 + 240);
|
||||
|
||||
//Draw background & Measure Line Width
|
||||
int lineWidth = 0;
|
||||
int xOffset = 0, yOffset = 0;
|
||||
int h = Font::charHeight;
|
||||
|
||||
for (unsigned int i = 0; i < this->text.length() + 1; i++) {
|
||||
char c = this->text[i];
|
||||
|
||||
//TODO: Proper font handling.
|
||||
if (c == '\t') c = ' ';
|
||||
|
||||
if (c == '\n' || i == this->text.length()) {
|
||||
if (lineWidth > 0) {
|
||||
lineWidth += 2;
|
||||
|
||||
if (lineWidth > maxLineWidth) maxLineWidth = lineWidth;
|
||||
|
||||
if (bgcolor.w != 0) {
|
||||
textVertices.emplace_back(glm::vec3 {-1, yOffset - 1, 0}, bgcolor, glm::vec3(1), 0.f, glm::vec3 {}, glm::ivec4 {}, glm::vec4 {});
|
||||
textVertices.emplace_back(glm::vec3 {-1, yOffset + h + 1, 0}, bgcolor, glm::vec3(1), 0.f, glm::vec3 {}, glm::ivec4 {}, glm::vec4 {});
|
||||
textVertices.emplace_back(glm::vec3 {lineWidth + 1, yOffset + h + 1, 0}, bgcolor, glm::vec3(1), 0.f, glm::vec3 {}, glm::ivec4 {}, glm::vec4 {});
|
||||
textVertices.emplace_back(glm::vec3 {lineWidth + 1, yOffset - 1, 0}, bgcolor, glm::vec3(1), 0.f, glm::vec3 {}, glm::ivec4 {}, glm::vec4 {});
|
||||
|
||||
textIndices.emplace_back(indOffset);
|
||||
textIndices.emplace_back(indOffset + 1);
|
||||
textIndices.emplace_back(indOffset + 2);
|
||||
textIndices.emplace_back(indOffset + 2);
|
||||
textIndices.emplace_back(indOffset + 3);
|
||||
textIndices.emplace_back(indOffset);
|
||||
|
||||
indOffset += 4;
|
||||
}
|
||||
yOffset += h + 2;
|
||||
}
|
||||
else {
|
||||
yOffset += h / 2; //Pad out the height if using just newlines.
|
||||
}
|
||||
|
||||
lineWidth = 0;
|
||||
}
|
||||
else lineWidth += font.getCharWidth(c) + 1;
|
||||
}
|
||||
|
||||
//Draw Characters
|
||||
|
||||
bool emptyLine = true;
|
||||
xOffset = 0;
|
||||
yOffset = 0;
|
||||
|
||||
for (unsigned int i = 0; i < this->text.length() + 1; i++) {
|
||||
char c = this->text[i];
|
||||
|
||||
//TODO: Proper font handling.
|
||||
if (c == '\t') c = ' ';
|
||||
|
||||
unsigned int h = Font::charHeight;
|
||||
|
||||
if (c == '\n' || i == this->text.length()) {
|
||||
yOffset += (emptyLine) ? h / 2 : h + 2;
|
||||
xOffset = 0;
|
||||
emptyLine = true;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
emptyLine = false;
|
||||
}
|
||||
|
||||
auto charWidth = font.getCharWidth(c) + 1;
|
||||
auto charUVs = font.getCharUVs(c);
|
||||
|
||||
for (unsigned int j = 0; j <= 1; j++) {
|
||||
glm::vec3 c = {this->color.x, this->color.y, this->color.z};
|
||||
|
||||
if (j == 0) {
|
||||
c *= glm::vec3 {0.4, 0.4, 0.45};
|
||||
xOffset += 1;
|
||||
yOffset += 1;
|
||||
}
|
||||
else {
|
||||
xOffset -= 1;
|
||||
yOffset -= 1;
|
||||
}
|
||||
|
||||
textVertices.emplace_back(glm::vec3 {xOffset, yOffset, 0}, glm::vec4 {charUVs.x, charUVs.y, 0, color.w}, c, 1.f, glm::vec3 {}, glm::ivec4 {}, glm::vec4 {});
|
||||
textVertices.emplace_back(glm::vec3 {xOffset, yOffset + h, 0}, glm::vec4 {charUVs.x, charUVs.w, 0, color.w}, c, 1.f, glm::vec3 {}, glm::ivec4 {}, glm::vec4 {});
|
||||
textVertices.emplace_back(glm::vec3 {xOffset + charWidth, yOffset + h, 0}, glm::vec4 {charUVs.z, charUVs.w, 0, color.w}, c, 1.f, glm::vec3 {}, glm::ivec4 {}, glm::vec4 {});
|
||||
textVertices.emplace_back(glm::vec3 {xOffset + charWidth, yOffset, 0}, glm::vec4 {charUVs.z, charUVs.y, 0, color.w}, c, 1.f, glm::vec3 {}, glm::ivec4 {}, glm::vec4 {});
|
||||
|
||||
textIndices.emplace_back(indOffset);
|
||||
textIndices.emplace_back(indOffset + 1);
|
||||
textIndices.emplace_back(indOffset + 2);
|
||||
textIndices.emplace_back(indOffset + 2);
|
||||
textIndices.emplace_back(indOffset + 3);
|
||||
textIndices.emplace_back(indOffset);
|
||||
|
||||
indOffset += 4;
|
||||
}
|
||||
|
||||
xOffset += charWidth;
|
||||
}
|
||||
|
||||
auto m = std::make_unique<EntityMesh>();
|
||||
m->create(textVertices, textIndices);
|
||||
|
||||
auto model = std::make_shared<Model>();
|
||||
model->fromMesh(std::move(m));
|
||||
|
||||
entity.setModel(model);
|
||||
this->text = std::move(text);
|
||||
unsigned int indOffset = 0;
|
||||
|
||||
maxLineWidth = 0;
|
||||
|
||||
std::vector<EntityVertex> textVertices;
|
||||
textVertices.reserve(text.length() * 8 + 200);
|
||||
std::vector<unsigned int> textIndices;
|
||||
textIndices.reserve(text.length() * 12 + 240);
|
||||
|
||||
//Draw background & Measure Line Width
|
||||
int lineWidth = 0;
|
||||
int xOffset = 0, yOffset = 0;
|
||||
int h = Font::charHeight;
|
||||
|
||||
for (unsigned int i = 0; i < this->text.length() + 1; i++) {
|
||||
char c = this->text[i];
|
||||
|
||||
//TODO: Proper font handling.
|
||||
if (c == '\t') c = ' ';
|
||||
|
||||
if (c == '\n' || i == this->text.length()) {
|
||||
if (lineWidth > 0) {
|
||||
lineWidth += 2;
|
||||
|
||||
if (lineWidth > maxLineWidth) maxLineWidth = lineWidth;
|
||||
|
||||
if (bgcolor.w != 0) {
|
||||
textVertices.emplace_back(glm::vec3{ -1, yOffset - 1, 0 }, bgcolor, glm::vec3(1), 0.f, glm::vec3{},
|
||||
glm::ivec4{}, glm::vec4{});
|
||||
textVertices.emplace_back(glm::vec3{ -1, yOffset + h + 1, 0 }, bgcolor, glm::vec3(1), 0.f,
|
||||
glm::vec3{}, glm::ivec4{}, glm::vec4{});
|
||||
textVertices.emplace_back(glm::vec3{ lineWidth + 1, yOffset + h + 1, 0 }, bgcolor, glm::vec3(1),
|
||||
0.f, glm::vec3{}, glm::ivec4{}, glm::vec4{});
|
||||
textVertices.emplace_back(glm::vec3{ lineWidth + 1, yOffset - 1, 0 }, bgcolor, glm::vec3(1), 0.f,
|
||||
glm::vec3{}, glm::ivec4{}, glm::vec4{});
|
||||
|
||||
textIndices.emplace_back(indOffset);
|
||||
textIndices.emplace_back(indOffset + 1);
|
||||
textIndices.emplace_back(indOffset + 2);
|
||||
textIndices.emplace_back(indOffset + 2);
|
||||
textIndices.emplace_back(indOffset + 3);
|
||||
textIndices.emplace_back(indOffset);
|
||||
|
||||
indOffset += 4;
|
||||
}
|
||||
yOffset += h + 2;
|
||||
}
|
||||
else {
|
||||
yOffset += h / 2; //Pad out the height if using just newlines.
|
||||
}
|
||||
|
||||
lineWidth = 0;
|
||||
}
|
||||
else lineWidth += font.getCharWidth(c) + 1;
|
||||
}
|
||||
|
||||
//Draw Characters
|
||||
|
||||
bool emptyLine = true;
|
||||
xOffset = 0;
|
||||
yOffset = 0;
|
||||
|
||||
for (unsigned int i = 0; i < this->text.length() + 1; i++) {
|
||||
char c = this->text[i];
|
||||
|
||||
//TODO: Proper font handling.
|
||||
if (c == '\t') c = ' ';
|
||||
|
||||
unsigned int h = Font::charHeight;
|
||||
|
||||
if (c == '\n' || i == this->text.length()) {
|
||||
yOffset += (emptyLine) ? h / 2 : h + 2;
|
||||
xOffset = 0;
|
||||
emptyLine = true;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
emptyLine = false;
|
||||
}
|
||||
|
||||
auto charWidth = font.getCharWidth(c) + 1;
|
||||
auto charUVs = font.getCharUVs(c);
|
||||
|
||||
for (unsigned int j = 0; j <= 1; j++) {
|
||||
glm::vec3 c = { this->color.x, this->color.y, this->color.z };
|
||||
|
||||
if (j == 0) {
|
||||
c *= glm::vec3{ 0.4, 0.4, 0.45 };
|
||||
xOffset += 1;
|
||||
yOffset += 1;
|
||||
}
|
||||
else {
|
||||
xOffset -= 1;
|
||||
yOffset -= 1;
|
||||
}
|
||||
|
||||
textVertices.emplace_back(glm::vec3{ xOffset, yOffset, 0 }, glm::vec4{ charUVs.x, charUVs.y, 0, color.w },
|
||||
c, 1.f, glm::vec3{}, glm::ivec4{}, glm::vec4{});
|
||||
textVertices.emplace_back(glm::vec3{ xOffset, yOffset + h, 0 },
|
||||
glm::vec4{ charUVs.x, charUVs.w, 0, color.w }, c, 1.f, glm::vec3{}, glm::ivec4{}, glm::vec4{});
|
||||
textVertices.emplace_back(glm::vec3{ xOffset + charWidth, yOffset + h, 0 },
|
||||
glm::vec4{ charUVs.z, charUVs.w, 0, color.w }, c, 1.f, glm::vec3{}, glm::ivec4{}, glm::vec4{});
|
||||
textVertices.emplace_back(glm::vec3{ xOffset + charWidth, yOffset, 0 },
|
||||
glm::vec4{ charUVs.z, charUVs.y, 0, color.w }, c, 1.f, glm::vec3{}, glm::ivec4{}, glm::vec4{});
|
||||
|
||||
textIndices.emplace_back(indOffset);
|
||||
textIndices.emplace_back(indOffset + 1);
|
||||
textIndices.emplace_back(indOffset + 2);
|
||||
textIndices.emplace_back(indOffset + 2);
|
||||
textIndices.emplace_back(indOffset + 3);
|
||||
textIndices.emplace_back(indOffset);
|
||||
|
||||
indOffset += 4;
|
||||
}
|
||||
|
||||
xOffset += charWidth;
|
||||
}
|
||||
|
||||
auto m = std::make_unique<EntityMesh>();
|
||||
m->create(textVertices, textIndices);
|
||||
|
||||
auto model = std::make_shared<Model>();
|
||||
model->fromMesh(std::move(m));
|
||||
|
||||
entity.setModel(model);
|
||||
}
|
||||
|
||||
std::string GuiText::getText() {
|
||||
return text;
|
||||
return text;
|
||||
}
|
||||
|
||||
unsigned int GuiText::getWidth() {
|
||||
return maxLineWidth;
|
||||
return maxLineWidth;
|
||||
}
|
||||
|
|
|
@ -9,27 +9,32 @@
|
|||
#include "client/graph/Font.h"
|
||||
|
||||
class TextureAtlas;
|
||||
|
||||
class LuaGuiElement;
|
||||
|
||||
class GuiText : public GuiComponent {
|
||||
public:
|
||||
GuiText() = default;
|
||||
explicit GuiText(const std::string& key);
|
||||
|
||||
static std::shared_ptr<GuiText> fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds);
|
||||
|
||||
void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 bgcolor, glm::vec4 color, Font font);
|
||||
|
||||
unsigned int getWidth();
|
||||
|
||||
void setText(std::string text);
|
||||
std::string getText();
|
||||
private:
|
||||
Font font;
|
||||
glm::vec4 bgcolor {};
|
||||
glm::vec4 color {};
|
||||
std::string text;
|
||||
|
||||
unsigned int maxLineWidth = 0;
|
||||
public:
|
||||
GuiText() = default;
|
||||
|
||||
explicit GuiText(const std::string& key);
|
||||
|
||||
static std::shared_ptr<GuiText>
|
||||
fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds);
|
||||
|
||||
void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 bgcolor, glm::vec4 color, Font font);
|
||||
|
||||
unsigned int getWidth();
|
||||
|
||||
void setText(std::string text);
|
||||
|
||||
std::string getText();
|
||||
|
||||
private:
|
||||
Font font;
|
||||
glm::vec4 bgcolor{};
|
||||
glm::vec4 color{};
|
||||
std::string text;
|
||||
|
||||
unsigned int maxLineWidth = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -9,73 +9,75 @@
|
|||
#include "client/gui/basic/GuiText.h"
|
||||
#include "game/atlas/asset/AtlasRef.h"
|
||||
|
||||
GuiImageButton::GuiImageButton(const std::string &key) : GuiRect(key) {}
|
||||
GuiImageButton::GuiImageButton(const std::string& key) : GuiRect(key) {}
|
||||
|
||||
std::shared_ptr<GuiImageButton> GuiImageButton::fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds) {
|
||||
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
|
||||
glm::vec2 offset = SerialGui::get<glm::vec2>(elem, "position_anchor");
|
||||
glm::vec2 size = SerialGui::get<glm::vec2>(elem, "size", bounds);
|
||||
glm::vec4 padding = SerialGui::get<glm::vec4>(elem, "padding", bounds);
|
||||
|
||||
pos -= offset * size;
|
||||
size -= glm::vec2 {padding.y + padding.w, padding.x + padding.z};
|
||||
|
||||
std::string background = elem.get_or<std::string>("background", "");
|
||||
std::string background_hover = elem.get_or<std::string>("background_hover", background);
|
||||
|
||||
bool hideOverflow = elem.get_or<std::string>("overflow", "visible") == "hidden";
|
||||
std::string content = elem.get_or<std::string>("content", "");
|
||||
|
||||
auto button = std::make_shared<GuiImageButton>(elem.key);
|
||||
button->create(size, padding, textures[background], textures[background_hover]);
|
||||
button->setOverflows(!hideOverflow);
|
||||
button->setPos(pos);
|
||||
|
||||
if (content != "") {
|
||||
auto text = std::make_shared<GuiText>(elem.key + "__TEXT");
|
||||
text->create(glm::vec2(SerialGui::SCALE_MODIFIER), padding, {}, {1, 1, 1, 1}, {textures, textures["font"]});
|
||||
text->setPos({6 * SerialGui::SCALE_MODIFIER, size.y / 2 - 4.5 * SerialGui::SCALE_MODIFIER});
|
||||
text->setText(content);
|
||||
button->add(text);
|
||||
}
|
||||
|
||||
return button;
|
||||
std::shared_ptr<GuiImageButton>
|
||||
GuiImageButton::fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds) {
|
||||
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
|
||||
glm::vec2 offset = SerialGui::get<glm::vec2>(elem, "position_anchor");
|
||||
glm::vec2 size = SerialGui::get<glm::vec2>(elem, "size", bounds);
|
||||
glm::vec4 padding = SerialGui::get<glm::vec4>(elem, "padding", bounds);
|
||||
|
||||
pos -= offset * size;
|
||||
size -= glm::vec2{ padding.y + padding.w, padding.x + padding.z };
|
||||
|
||||
std::string background = elem.get_or<std::string>("background", "");
|
||||
std::string background_hover = elem.get_or<std::string>("background_hover", background);
|
||||
|
||||
bool hideOverflow = elem.get_or<std::string>("overflow", "visible") == "hidden";
|
||||
std::string content = elem.get_or<std::string>("content", "");
|
||||
|
||||
auto button = std::make_shared<GuiImageButton>(elem.key);
|
||||
button->create(size, padding, textures[background], textures[background_hover]);
|
||||
button->setOverflows(!hideOverflow);
|
||||
button->setPos(pos);
|
||||
|
||||
if (content != "") {
|
||||
auto text = std::make_shared<GuiText>(elem.key + "__TEXT");
|
||||
text->create(glm::vec2(SerialGui::SCALE_MODIFIER), padding, {}, { 1, 1, 1, 1 }, { textures, textures["font"] });
|
||||
text->setPos({ 6 * SerialGui::SCALE_MODIFIER, size.y / 2 - 4.5 * SerialGui::SCALE_MODIFIER });
|
||||
text->setText(content);
|
||||
button->add(text);
|
||||
}
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
// Texture Constructor
|
||||
// Creates a GuiImageButton object with two textures
|
||||
// defined by the 'texture' & 'hoverTexture' reference.
|
||||
void GuiImageButton::create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr<AtlasRef> texture, std::shared_ptr<AtlasRef> hoverTexture) {
|
||||
this->hoverTexture = hoverTexture;
|
||||
GuiRect::create(scale, padding, texture);
|
||||
|
||||
setCallback(GuiComponent::CallbackType::HOVER, nullptr);
|
||||
void GuiImageButton::create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr<AtlasRef> texture,
|
||||
std::shared_ptr<AtlasRef> hoverTexture) {
|
||||
this->hoverTexture = hoverTexture;
|
||||
GuiRect::create(scale, padding, texture);
|
||||
|
||||
setCallback(GuiComponent::CallbackType::HOVER, nullptr);
|
||||
}
|
||||
|
||||
void GuiImageButton::setCallback(GuiComponent::CallbackType type, const GuiComponent::callback &cb) {
|
||||
if (type == CallbackType::HOVER) {
|
||||
GuiComponent::setCallback(type, [&, cb](bool nowHovered, glm::ivec2 pos) {
|
||||
if (cb) cb(nowHovered, pos);
|
||||
if (nowHovered != hovered) this->rebuild(nowHovered);
|
||||
});
|
||||
}
|
||||
else GuiComponent::setCallback(type, cb);
|
||||
void GuiImageButton::setCallback(GuiComponent::CallbackType type, const GuiComponent::callback& cb) {
|
||||
if (type == CallbackType::HOVER) {
|
||||
GuiComponent::setCallback(type, [&, cb](bool nowHovered, glm::ivec2 pos) {
|
||||
if (cb) cb(nowHovered, pos);
|
||||
if (nowHovered != hovered) this->rebuild(nowHovered);
|
||||
});
|
||||
}
|
||||
else GuiComponent::setCallback(type, cb);
|
||||
}
|
||||
|
||||
void GuiImageButton::rebuild(bool hover) {
|
||||
auto tex = (hover) ? (hoverTexture != nullptr) ? hoverTexture : texture : texture;
|
||||
|
||||
auto mesh = std::make_unique<EntityMesh>();
|
||||
mesh->create({
|
||||
{{0, 0, 0}, {tex->uv.x, tex->uv.y, 0, 1}, {1, 1, 1}, true, {}, {}, {}},
|
||||
{{0, 1, 0}, {tex->uv.x, tex->uv.w, 0, 1}, {1, 1, 1}, true, {}, {}, {}},
|
||||
{{1, 1, 0}, {tex->uv.z, tex->uv.w, 0, 1}, {1, 1, 1}, true, {}, {}, {}},
|
||||
{{1, 0, 0}, {tex->uv.z, tex->uv.y, 0, 1}, {1, 1, 1}, true, {}, {}, {}}
|
||||
}, {0, 1, 2, 2, 3, 0});
|
||||
|
||||
auto model = std::make_shared<Model>();
|
||||
model->fromMesh(std::move(mesh));
|
||||
|
||||
entity.setModel(model);
|
||||
setScale({scale.x + padding.w + padding.y, scale.y + padding.x + padding.z});
|
||||
auto tex = (hover) ? (hoverTexture != nullptr) ? hoverTexture : texture : texture;
|
||||
|
||||
auto mesh = std::make_unique<EntityMesh>();
|
||||
mesh->create({
|
||||
{{ 0, 0, 0 }, { tex->uv.x, tex->uv.y, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}},
|
||||
{{ 0, 1, 0 }, { tex->uv.x, tex->uv.w, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}},
|
||||
{{ 1, 1, 0 }, { tex->uv.z, tex->uv.w, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}},
|
||||
{{ 1, 0, 0 }, { tex->uv.z, tex->uv.y, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}}
|
||||
}, { 0, 1, 2, 2, 3, 0 });
|
||||
|
||||
auto model = std::make_shared<Model>();
|
||||
model->fromMesh(std::move(mesh));
|
||||
|
||||
entity.setModel(model);
|
||||
setScale({ scale.x + padding.w + padding.y, scale.y + padding.x + padding.z });
|
||||
}
|
|
@ -7,16 +7,21 @@
|
|||
#include "../basic/GuiRect.h"
|
||||
|
||||
class GuiImageButton : public GuiRect {
|
||||
public:
|
||||
GuiImageButton() = default;
|
||||
GuiImageButton(const std::string& key);
|
||||
|
||||
static std::shared_ptr<GuiImageButton> fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds);
|
||||
|
||||
void create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr<AtlasRef> texture, std::shared_ptr<AtlasRef> hoverTexture);
|
||||
|
||||
void setCallback(CallbackType type, const callback& cb) override;
|
||||
private:
|
||||
void rebuild(bool hover);
|
||||
std::shared_ptr<AtlasRef> hoverTexture = nullptr;
|
||||
public:
|
||||
GuiImageButton() = default;
|
||||
|
||||
GuiImageButton(const std::string& key);
|
||||
|
||||
static std::shared_ptr<GuiImageButton>
|
||||
fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds);
|
||||
|
||||
void create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr<AtlasRef> texture,
|
||||
std::shared_ptr<AtlasRef> hoverTexture);
|
||||
|
||||
void setCallback(CallbackType type, const callback& cb) override;
|
||||
|
||||
private:
|
||||
void rebuild(bool hover);
|
||||
|
||||
std::shared_ptr<AtlasRef> hoverTexture = nullptr;
|
||||
};
|
||||
|
|
|
@ -12,138 +12,139 @@
|
|||
#include "game/atlas/LocalDefinitionAtlas.h"
|
||||
#include "client/gui/basic/GuiInventoryItem.h"
|
||||
|
||||
GuiInventoryList::GuiInventoryList(const std::string &key) : GuiContainer(key) {}
|
||||
GuiInventoryList::GuiInventoryList(const std::string& key) : GuiContainer(key) {}
|
||||
|
||||
std::shared_ptr<GuiInventoryList> GuiInventoryList::fromSerialized(const LuaGuiElement& elem,
|
||||
SubgamePtr game, glm::ivec2 bounds, InventoryRefsPtr refs) {
|
||||
|
||||
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
|
||||
SubgamePtr game, glm::ivec2 bounds, InventoryRefsPtr refs) {
|
||||
|
||||
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
|
||||
// glm::vec2 offset = SerialGui::get<glm::vec2>(elem, "position_anchor");
|
||||
// glm::vec2 size = SerialGui::deserializeToken<glm::vec2>(s.tokens, "size", bounds);
|
||||
glm::vec4 padding = SerialGui::get<glm::vec4>(elem, "padding", bounds);
|
||||
glm::vec2 slotspc = SerialGui::get<glm::vec2>(elem, "slot_spacing", bounds);
|
||||
|
||||
std::string source = elem.get_or<std::string>("source", "");
|
||||
std::string list = elem.get_or<std::string>("list", "");
|
||||
unsigned short start = static_cast<unsigned short>(elem.get_or<float>("start", 1) - 1);
|
||||
unsigned short length = static_cast<unsigned short>(elem.get_or<float>("length", 0));
|
||||
|
||||
auto invList = refs->getInventory(source)->getList(list).l();
|
||||
auto inv = std::make_shared<GuiInventoryList>(elem.key);
|
||||
|
||||
inv->create(glm::vec2(SerialGui::SCALE_MODIFIER), padding * SerialGui::SCALE_MODIFIER,
|
||||
slotspc * SerialGui::SCALE_MODIFIER, invList, refs.l()->getCursorList(), game, start, length);
|
||||
inv->setPos(pos);
|
||||
|
||||
return inv;
|
||||
glm::vec4 padding = SerialGui::get<glm::vec4>(elem, "padding", bounds);
|
||||
glm::vec2 slotspc = SerialGui::get<glm::vec2>(elem, "slot_spacing", bounds);
|
||||
|
||||
std::string source = elem.get_or<std::string>("source", "");
|
||||
std::string list = elem.get_or<std::string>("list", "");
|
||||
unsigned short start = static_cast<unsigned short>(elem.get_or<float>("start", 1) - 1);
|
||||
unsigned short length = static_cast<unsigned short>(elem.get_or<float>("length", 0));
|
||||
|
||||
auto invList = refs->getInventory(source)->getList(list).l();
|
||||
auto inv = std::make_shared<GuiInventoryList>(elem.key);
|
||||
|
||||
inv->create(glm::vec2(SerialGui::SCALE_MODIFIER), padding * SerialGui::SCALE_MODIFIER,
|
||||
slotspc * SerialGui::SCALE_MODIFIER, invList, refs.l()->getCursorList(), game, start, length);
|
||||
inv->setPos(pos);
|
||||
|
||||
return inv;
|
||||
}
|
||||
|
||||
void GuiInventoryList::create(glm::vec2 scale, glm::vec4 padding, glm::ivec2 innerPadding,
|
||||
InventoryListPtr list, InventoryListPtr cursor, SubgamePtr defs,
|
||||
unsigned short start, unsigned short length) {
|
||||
|
||||
this->list = list;
|
||||
this->cursor = cursor;
|
||||
this->defs = defs;
|
||||
|
||||
this->start = start;
|
||||
this->length = length;
|
||||
|
||||
this->scale = scale;
|
||||
this->padding = padding;
|
||||
this->innerPadding = innerPadding;
|
||||
this->hitbox = (list->getWidth() == 0 ? glm::ivec2 {} : glm::ivec2 {
|
||||
padding.x + list->getWidth() * (innerPadding.x*scale.x),
|
||||
padding.y + (list->getLength() / list->getWidth()) * (innerPadding.y*scale.y) });
|
||||
|
||||
drawContents();
|
||||
myCallback = std::make_shared<std::function<void()>>(std::bind(&GuiInventoryList::drawContents, this));
|
||||
list.l()->addGuiCallback(myCallback);
|
||||
|
||||
setCallback(CallbackType::PRIMARY, nullptr);
|
||||
setCallback(CallbackType::SECONDARY, nullptr);
|
||||
setCallback(CallbackType::HOVER, nullptr);
|
||||
|
||||
hoverRect->create({}, {}, {1, 1, 1, 0.1});
|
||||
InventoryListPtr list, InventoryListPtr cursor, SubgamePtr defs,
|
||||
unsigned short start, unsigned short length) {
|
||||
|
||||
this->list = list;
|
||||
this->cursor = cursor;
|
||||
this->defs = defs;
|
||||
|
||||
this->start = start;
|
||||
this->length = length;
|
||||
|
||||
this->scale = scale;
|
||||
this->padding = padding;
|
||||
this->innerPadding = innerPadding;
|
||||
this->hitbox = (list->getWidth() == 0 ? glm::ivec2{} : glm::ivec2{
|
||||
padding.x + list->getWidth() * (innerPadding.x * scale.x),
|
||||
padding.y + (list->getLength() / list->getWidth()) * (innerPadding.y * scale.y) });
|
||||
|
||||
drawContents();
|
||||
myCallback = std::make_shared<std::function<void()>>(std::bind(&GuiInventoryList::drawContents, this));
|
||||
list.l()->addGuiCallback(myCallback);
|
||||
|
||||
setCallback(CallbackType::PRIMARY, nullptr);
|
||||
setCallback(CallbackType::SECONDARY, nullptr);
|
||||
setCallback(CallbackType::HOVER, nullptr);
|
||||
|
||||
hoverRect->create({}, {}, { 1, 1, 1, 0.1 });
|
||||
}
|
||||
|
||||
void GuiInventoryList::setCallback(CallbackType type, const callback& cb) {
|
||||
GuiComponent::setCallback(type, [&, cb, type](bool down, glm::ivec2 pos) {
|
||||
if (cb) cb(down, pos);
|
||||
|
||||
if (type == GuiComponent::CallbackType::HOVER) this->hoverEvent(down, pos);
|
||||
else if (down) this->interactEvent(pos, type == GuiComponent::CallbackType::PRIMARY);
|
||||
});
|
||||
GuiComponent::setCallback(type, [&, cb, type](bool down, glm::ivec2 pos) {
|
||||
if (cb) cb(down, pos);
|
||||
|
||||
if (type == GuiComponent::CallbackType::HOVER) this->hoverEvent(down, pos);
|
||||
else if (down) this->interactEvent(pos, type == GuiComponent::CallbackType::PRIMARY);
|
||||
});
|
||||
}
|
||||
|
||||
void GuiInventoryList::hoverEvent(bool hovered, glm::ivec2 pos) {
|
||||
pos += glm::ivec2(glm::vec2(this->padding.x, this->padding.y) * this->scale);
|
||||
|
||||
if (hovered) {
|
||||
if (!this->hovered) hoverRect->setScale({16*scale.x, 16*scale.y});
|
||||
|
||||
glm::ivec2 slot = pos / (glm::ivec2(this->scale) * this->innerPadding);
|
||||
slot.x = std::min(slot.x, static_cast<int>(list->getWidth() - 1));
|
||||
slot.y = std::min(slot.y, list->getLength() / list->getWidth() - 1);
|
||||
glm::ivec2 highlightPos = slot * glm::ivec2(this->scale) * this->innerPadding;
|
||||
|
||||
hoverRect->setPos(highlightPos);
|
||||
}
|
||||
else if (this->hovered) hoverRect->setScale({});
|
||||
pos += glm::ivec2(glm::vec2(this->padding.x, this->padding.y) * this->scale);
|
||||
|
||||
if (hovered) {
|
||||
if (!this->hovered) hoverRect->setScale({ 16 * scale.x, 16 * scale.y });
|
||||
|
||||
glm::ivec2 slot = pos / (glm::ivec2(this->scale) * this->innerPadding);
|
||||
slot.x = std::min(slot.x, static_cast<int>(list->getWidth() - 1));
|
||||
slot.y = std::min(slot.y, list->getLength() / list->getWidth() - 1);
|
||||
glm::ivec2 highlightPos = slot * glm::ivec2(this->scale) * this->innerPadding;
|
||||
|
||||
hoverRect->setPos(highlightPos);
|
||||
}
|
||||
else if (this->hovered) hoverRect->setScale({});
|
||||
}
|
||||
|
||||
void GuiInventoryList::interactEvent(glm::ivec2 pos, bool primary) {
|
||||
if (list->getWidth() == 0) return;
|
||||
|
||||
pos += glm::ivec2(glm::vec2(this->padding.x, this->padding.y) * this->scale);
|
||||
|
||||
glm::ivec2 slot = pos / (glm::ivec2(this->scale) * this->innerPadding);
|
||||
slot.x = std::min(slot.x, static_cast<int>(list->getWidth() - 1));
|
||||
slot.y = std::min(slot.y, list->getLength() / list->getWidth() - 1);
|
||||
|
||||
unsigned short index = slot.x + slot.y * list->getWidth();
|
||||
|
||||
if (index >= list->getLength()) return;
|
||||
|
||||
list->interact(cursor, primary, index);
|
||||
if (list->getWidth() == 0) return;
|
||||
|
||||
pos += glm::ivec2(glm::vec2(this->padding.x, this->padding.y) * this->scale);
|
||||
|
||||
glm::ivec2 slot = pos / (glm::ivec2(this->scale) * this->innerPadding);
|
||||
slot.x = std::min(slot.x, static_cast<int>(list->getWidth() - 1));
|
||||
slot.y = std::min(slot.y, list->getLength() / list->getWidth() - 1);
|
||||
|
||||
unsigned short index = slot.x + slot.y * list->getWidth();
|
||||
|
||||
if (index >= list->getLength()) return;
|
||||
|
||||
list->interact(cursor, primary, index);
|
||||
}
|
||||
|
||||
void GuiInventoryList::drawContents() {
|
||||
if (list->getWidth() == 0) return;
|
||||
unsigned short length = this->length == 0 ? list->getLength() : this->length;
|
||||
|
||||
this->hitbox = glm::ivec2 {
|
||||
padding.x + list->getWidth() * (innerPadding.x*scale.x),
|
||||
padding.y + (list->getLength() / list->getWidth()) * (innerPadding.y*scale.y)
|
||||
};
|
||||
|
||||
empty();
|
||||
|
||||
auto fontRef = defs.l()->textures["font"];
|
||||
Font f(defs.l()->textures, fontRef);
|
||||
|
||||
for (unsigned short i = 0; i < list->getLength() / list->getWidth(); i++) {
|
||||
for (unsigned short j = 0; j < list->getWidth(); j++) {
|
||||
unsigned short stackInd = j + i * list->getWidth();
|
||||
if (stackInd >= length) break;
|
||||
if (list->getWidth() == 0) return;
|
||||
unsigned short length = this->length == 0 ? list->getLength() : this->length;
|
||||
|
||||
this->hitbox = glm::ivec2{
|
||||
padding.x + list->getWidth() * (innerPadding.x * scale.x),
|
||||
padding.y + (list->getLength() / list->getWidth()) * (innerPadding.y * scale.y)
|
||||
};
|
||||
|
||||
empty();
|
||||
|
||||
auto fontRef = defs.l()->textures["font"];
|
||||
Font f(defs.l()->textures, fontRef);
|
||||
|
||||
for (unsigned short i = 0; i < list->getLength() / list->getWidth(); i++) {
|
||||
for (unsigned short j = 0; j < list->getWidth(); j++) {
|
||||
unsigned short stackInd = j + i * list->getWidth();
|
||||
if (stackInd >= length) break;
|
||||
// auto bg = std::make_shared<GuiRect>("background_" + to_string(i) + "_" + to_string(j));
|
||||
// bg->create(scale * 16.f, {}, {1, 0, 0, 0.3});
|
||||
// add(bg);
|
||||
// bg->setPos({padding.x + j * (16*scale.x+innerPadding.x/scale.x), padding.y + i * (16*scale.y+innerPadding.y/scale.y)});
|
||||
|
||||
auto stack = list->getStack(stackInd);
|
||||
if (stack.id == 0) continue;
|
||||
|
||||
auto item = std::make_shared<GuiInventoryItem>("item_" + std::to_string(i) + "_" + std::to_string(j));
|
||||
item->create(scale, stack.count, defs->getDefs().fromId(stack.id), f);
|
||||
add(item);
|
||||
item->setPos({padding.x + j * (16*scale.x+innerPadding.x/scale.x), padding.y + i * (16*scale.y+innerPadding.y/scale.y)});
|
||||
}
|
||||
}
|
||||
|
||||
add(hoverRect);
|
||||
|
||||
auto stack = list->getStack(stackInd);
|
||||
if (stack.id == 0) continue;
|
||||
|
||||
auto item = std::make_shared<GuiInventoryItem>("item_" + std::to_string(i) + "_" + std::to_string(j));
|
||||
item->create(scale, stack.count, defs->getDefs().fromId(stack.id), f);
|
||||
add(item);
|
||||
item->setPos({ padding.x + j * (16 * scale.x + innerPadding.x / scale.x),
|
||||
padding.y + i * (16 * scale.y + innerPadding.y / scale.y) });
|
||||
}
|
||||
}
|
||||
|
||||
add(hoverRect);
|
||||
}
|
||||
|
||||
GuiInventoryList::~GuiInventoryList() {
|
||||
if (list) list.l()->removeGuiCallback(myCallback);
|
||||
if (list) list.l()->removeGuiCallback(myCallback);
|
||||
}
|
|
@ -9,39 +9,47 @@
|
|||
#include "util/CovariantPtr.h"
|
||||
|
||||
class LocalSubgame;
|
||||
|
||||
class LuaGuiElement;
|
||||
|
||||
class LocalInventoryRefs;
|
||||
|
||||
class LocalInventoryList;
|
||||
|
||||
class GuiInventoryList : public GuiContainer {
|
||||
public:
|
||||
GuiInventoryList() = default;
|
||||
GuiInventoryList(const std::string& key);
|
||||
~GuiInventoryList() override;
|
||||
|
||||
static std::shared_ptr<GuiInventoryList> fromSerialized(const LuaGuiElement& elem,
|
||||
SubgamePtr game, glm::ivec2 bounds, InventoryRefsPtr refs);
|
||||
|
||||
void create(glm::vec2 scale, glm::vec4 padding, glm::ivec2 innerPadding,
|
||||
InventoryListPtr list, InventoryListPtr cursor, SubgamePtr defs,
|
||||
unsigned short start = 0, unsigned short length = 0);
|
||||
|
||||
void setCallback(CallbackType type, const callback& cb) override;
|
||||
|
||||
void hoverEvent(bool hovered, glm::ivec2 pos);
|
||||
void interactEvent(glm::ivec2 pos, bool primary);
|
||||
void drawContents();
|
||||
private:
|
||||
std::shared_ptr<GuiRect> hoverRect = std::make_shared<GuiRect>("hover_rect");
|
||||
std::shared_ptr<std::function<void()>> myCallback = nullptr;
|
||||
|
||||
InventoryListPtr list;
|
||||
InventoryListPtr cursor;
|
||||
|
||||
unsigned short start = 0;
|
||||
unsigned short length = 0;
|
||||
|
||||
glm::ivec2 innerPadding;
|
||||
|
||||
SubgamePtr defs = SubgamePtr();
|
||||
public:
|
||||
GuiInventoryList() = default;
|
||||
|
||||
GuiInventoryList(const std::string& key);
|
||||
|
||||
~GuiInventoryList() override;
|
||||
|
||||
static std::shared_ptr<GuiInventoryList> fromSerialized(const LuaGuiElement& elem,
|
||||
SubgamePtr game, glm::ivec2 bounds, InventoryRefsPtr refs);
|
||||
|
||||
void create(glm::vec2 scale, glm::vec4 padding, glm::ivec2 innerPadding,
|
||||
InventoryListPtr list, InventoryListPtr cursor, SubgamePtr defs,
|
||||
unsigned short start = 0, unsigned short length = 0);
|
||||
|
||||
void setCallback(CallbackType type, const callback& cb) override;
|
||||
|
||||
void hoverEvent(bool hovered, glm::ivec2 pos);
|
||||
|
||||
void interactEvent(glm::ivec2 pos, bool primary);
|
||||
|
||||
void drawContents();
|
||||
|
||||
private:
|
||||
std::shared_ptr<GuiRect> hoverRect = std::make_shared<GuiRect>("hover_rect");
|
||||
std::shared_ptr<std::function<void()>> myCallback = nullptr;
|
||||
|
||||
InventoryListPtr list;
|
||||
InventoryListPtr cursor;
|
||||
|
||||
unsigned short start = 0;
|
||||
unsigned short length = 0;
|
||||
|
||||
glm::ivec2 innerPadding;
|
||||
|
||||
SubgamePtr defs = SubgamePtr();
|
||||
};
|
||||
|
|
|
@ -4,52 +4,54 @@
|
|||
|
||||
#include "GuiLabelledGraph.h"
|
||||
|
||||
GuiLabelledGraph::GuiLabelledGraph(const std::string &key) : GuiContainer(key) {}
|
||||
GuiLabelledGraph::GuiLabelledGraph(const std::string& key) : GuiContainer(key) {}
|
||||
|
||||
void GuiLabelledGraph::create(glm::vec2 scale, glm::vec4 padding, const std::string &title,
|
||||
unsigned int graphLength, unsigned int graphScale,
|
||||
std::shared_ptr<AtlasRef> graphTextureRef, Font font) {
|
||||
|
||||
const static int GRAPH_PAD_X = 2;
|
||||
const static int GRAPH_PAD_Y = 62;
|
||||
const static int TEXT_PAD_X = 4;
|
||||
const static int TEXT_PAD_Y = 8;
|
||||
|
||||
this->scale = scale;
|
||||
this->padding = padding;
|
||||
this->title = title;
|
||||
this->font = std::move(font);
|
||||
this->graphTextureRef = std::move(graphTextureRef);
|
||||
|
||||
auto background = std::make_shared<GuiRect>("background");
|
||||
background->create(scale, {}, {0.1, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.1, 0.7}, {0.1, 0.1, 0.1, 0.7});
|
||||
add(background);
|
||||
background->setPos({0, 0});
|
||||
|
||||
auto graph = std::make_shared<GuiGraph>("graph");
|
||||
graph->create({scale.x / (graphLength + GRAPH_PAD_X), scale.y * 0.4}, {}, this->graphTextureRef, graphLength, graphScale, true);
|
||||
add(graph);
|
||||
graph->setPos({GRAPH_PAD_X, GRAPH_PAD_Y});
|
||||
|
||||
auto label = std::make_shared<GuiText>("label");
|
||||
label->create({2, 2}, {}, {}, {1, 1, 1, 1}, this->font);
|
||||
add(label);
|
||||
label->setPos({TEXT_PAD_X, TEXT_PAD_Y});
|
||||
|
||||
for (float &i : history) i = 0;
|
||||
void GuiLabelledGraph::create(glm::vec2 scale, glm::vec4 padding, const std::string& title,
|
||||
unsigned int graphLength, unsigned int graphScale,
|
||||
std::shared_ptr<AtlasRef> graphTextureRef, Font font) {
|
||||
|
||||
const static int GRAPH_PAD_X = 2;
|
||||
const static int GRAPH_PAD_Y = 62;
|
||||
const static int TEXT_PAD_X = 4;
|
||||
const static int TEXT_PAD_Y = 8;
|
||||
|
||||
this->scale = scale;
|
||||
this->padding = padding;
|
||||
this->title = title;
|
||||
this->font = std::move(font);
|
||||
this->graphTextureRef = std::move(graphTextureRef);
|
||||
|
||||
auto background = std::make_shared<GuiRect>("background");
|
||||
background->create(scale, {}, { 0.1, 0.1, 0.1, 0.2 }, { 0.1, 0.1, 0.1, 0.2 }, { 0.1, 0.1, 0.1, 0.7 },
|
||||
{ 0.1, 0.1, 0.1, 0.7 });
|
||||
add(background);
|
||||
background->setPos({ 0, 0 });
|
||||
|
||||
auto graph = std::make_shared<GuiGraph>("graph");
|
||||
graph->create({ scale.x / (graphLength + GRAPH_PAD_X), scale.y * 0.4 }, {}, this->graphTextureRef, graphLength,
|
||||
graphScale, true);
|
||||
add(graph);
|
||||
graph->setPos({ GRAPH_PAD_X, GRAPH_PAD_Y });
|
||||
|
||||
auto label = std::make_shared<GuiText>("label");
|
||||
label->create({ 2, 2 }, {}, {}, { 1, 1, 1, 1 }, this->font);
|
||||
add(label);
|
||||
label->setPos({ TEXT_PAD_X, TEXT_PAD_Y });
|
||||
|
||||
for (float& i : history) i = 0;
|
||||
}
|
||||
|
||||
void GuiLabelledGraph::pushValue(float value) {
|
||||
get<GuiGraph>("graph")->pushValue(value);
|
||||
|
||||
history[ind] = value;
|
||||
if (++ind >= 5) {
|
||||
ind = 0;
|
||||
|
||||
std::string stringVal = (value == static_cast<int>(value))
|
||||
? std::to_string(static_cast<int>(value))
|
||||
: Util::floatToString(value);
|
||||
|
||||
get<GuiText>("label")->setText(title + ": " + stringVal);
|
||||
}
|
||||
get<GuiGraph>("graph")->pushValue(value);
|
||||
|
||||
history[ind] = value;
|
||||
if (++ind >= 5) {
|
||||
ind = 0;
|
||||
|
||||
std::string stringVal = (value == static_cast<int>(value))
|
||||
? std::to_string(static_cast<int>(value))
|
||||
: Util::floatToString(value);
|
||||
|
||||
get<GuiText>("label")->setText(title + ": " + stringVal);
|
||||
}
|
||||
}
|
|
@ -12,22 +12,24 @@
|
|||
#include "world/dim/ent/DrawableEntity.h"
|
||||
|
||||
class GuiLabelledGraph : public GuiContainer {
|
||||
public:
|
||||
GuiLabelledGraph() = default;
|
||||
GuiLabelledGraph(const std::string& key);
|
||||
|
||||
void create(glm::vec2 scale, glm::vec4 padding, const std::string& title,
|
||||
unsigned int graphLength, unsigned int graphScale,
|
||||
std::shared_ptr<AtlasRef> graphTextureRef, Font font);
|
||||
|
||||
void pushValue(float value);
|
||||
private:
|
||||
std::string title;
|
||||
|
||||
std::shared_ptr<AtlasRef> graphTextureRef;
|
||||
Font font;
|
||||
|
||||
int ind = 0;
|
||||
float history[5] {};
|
||||
public:
|
||||
GuiLabelledGraph() = default;
|
||||
|
||||
GuiLabelledGraph(const std::string& key);
|
||||
|
||||
void create(glm::vec2 scale, glm::vec4 padding, const std::string& title,
|
||||
unsigned int graphLength, unsigned int graphScale,
|
||||
std::shared_ptr<AtlasRef> graphTextureRef, Font font);
|
||||
|
||||
void pushValue(float value);
|
||||
|
||||
private:
|
||||
std::string title;
|
||||
|
||||
std::shared_ptr<AtlasRef> graphTextureRef;
|
||||
Font font;
|
||||
|
||||
int ind = 0;
|
||||
float history[5]{};
|
||||
};
|
||||
|
||||
|
|
|
@ -17,189 +17,190 @@
|
|||
#include "lua/modules/mSetGui.h"
|
||||
#include "lua/modules/mStartGame.h"
|
||||
|
||||
MenuSandbox::MenuSandbox(glm::ivec2 &win, Client& client, std::shared_ptr<GuiContainer> container) :
|
||||
LuaParser(*client.game),
|
||||
win(win),
|
||||
client(client),
|
||||
container(container),
|
||||
luaContainer(std::dynamic_pointer_cast<GuiContainer>(container->add(std::make_shared<GuiContainer>("__lua")))),
|
||||
builder(client.game->textures, client.game->models, luaContainer) {}
|
||||
MenuSandbox::MenuSandbox(glm::ivec2& win, Client& client, std::shared_ptr<GuiContainer> container) :
|
||||
LuaParser(*client.game),
|
||||
win(win),
|
||||
client(client),
|
||||
container(container),
|
||||
luaContainer(std::dynamic_pointer_cast<GuiContainer>(container->add(std::make_shared<GuiContainer>("__lua")))),
|
||||
builder(client.game->textures, client.game->models, luaContainer) {}
|
||||
|
||||
void MenuSandbox::reset() {
|
||||
container->remove("error");
|
||||
builder.clear(true);
|
||||
core = {};
|
||||
mod = {};
|
||||
lua = sol::state {};
|
||||
lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::math, sol::lib::table, sol::lib::debug);
|
||||
|
||||
loadApi();
|
||||
container->remove("error");
|
||||
builder.clear(true);
|
||||
core = {};
|
||||
mod = {};
|
||||
lua = sol::state{};
|
||||
lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::math, sol::lib::table, sol::lib::debug);
|
||||
|
||||
loadApi();
|
||||
}
|
||||
|
||||
void MenuSandbox::loadApi() {
|
||||
//Create Zepha Table
|
||||
core = lua.create_table();
|
||||
lua["zepha"] = core;
|
||||
core["__builtin"] = lua.create_table();
|
||||
|
||||
|
||||
modules.emplace_back(std::make_unique<Api::Module::Time>(Api::State::CLIENT, lua, core));
|
||||
|
||||
ClientApi::gui_element(lua);
|
||||
|
||||
MenuApi::set_gui (builder, win, lua, core);
|
||||
MenuApi::start_game (client, core);
|
||||
|
||||
bindModules();
|
||||
|
||||
// Create sandboxed runfile()
|
||||
lua["dofile"] = lua["loadfile"] = sol::nil;
|
||||
lua.set_function("runfile", &MenuSandbox::runFileSandboxed, this);
|
||||
//Create Zepha Table
|
||||
core = lua.create_table();
|
||||
lua["zepha"] = core;
|
||||
core["__builtin"] = lua.create_table();
|
||||
|
||||
|
||||
modules.emplace_back(std::make_unique<Api::Module::Time>(Api::State::CLIENT, lua, core));
|
||||
|
||||
ClientApi::gui_element(lua);
|
||||
|
||||
MenuApi::set_gui(builder, win, lua, core);
|
||||
MenuApi::start_game(client, core);
|
||||
|
||||
bindModules();
|
||||
|
||||
// Create sandboxed runfile()
|
||||
lua["dofile"] = lua["loadfile"] = sol::nil;
|
||||
lua.set_function("runfile", &MenuSandbox::runFileSandboxed, this);
|
||||
}
|
||||
|
||||
void MenuSandbox::load(const SubgameDef& subgame) {
|
||||
reset();
|
||||
|
||||
try {
|
||||
loadAndRunMod(subgame.subgamePath + "/../../assets/base");
|
||||
loadAndRunMod(subgame.subgamePath + "/menu");
|
||||
}
|
||||
catch (const std::runtime_error& e) {
|
||||
showError(e.what(), subgame.config.name);
|
||||
}
|
||||
reset();
|
||||
|
||||
try {
|
||||
loadAndRunMod(subgame.subgamePath + "/../../assets/base");
|
||||
loadAndRunMod(subgame.subgamePath + "/menu");
|
||||
}
|
||||
catch (const std::runtime_error& e) {
|
||||
showError(e.what(), subgame.config.name);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuSandbox::windowResized() {
|
||||
builder.build(win);
|
||||
builder.build(win);
|
||||
}
|
||||
|
||||
void MenuSandbox::update(double delta) {
|
||||
builder.update();
|
||||
core["__builtin"]["update_delayed_functions"]();
|
||||
builder.update();
|
||||
core["__builtin"]["update_delayed_functions"]();
|
||||
}
|
||||
|
||||
sol::protected_function_result MenuSandbox::runFileSandboxed(const std::string& file) {
|
||||
for (LuaMod::File& f : mod.files) {
|
||||
if (f.path != file) continue;
|
||||
|
||||
sol::environment env(lua, sol::create, lua.globals());
|
||||
env["_PATH"] = f.path.substr(0, f.path.find_last_of('/') + 1);
|
||||
env["_FILE"] = f.path;
|
||||
env["_MODNAME"] = mod.config.name;
|
||||
|
||||
return lua.safe_script(f.file, env, std::bind(&MenuSandbox::errorCallback,
|
||||
this, std::placeholders::_2), "@" + f.path, sol::load_mode::text);
|
||||
}
|
||||
throw std::runtime_error("Error opening '" + file + "', file not found.");
|
||||
for (LuaMod::File& f : mod.files) {
|
||||
if (f.path != file) continue;
|
||||
|
||||
sol::environment env(lua, sol::create, lua.globals());
|
||||
env["_PATH"] = f.path.substr(0, f.path.find_last_of('/') + 1);
|
||||
env["_FILE"] = f.path;
|
||||
env["_MODNAME"] = mod.config.name;
|
||||
|
||||
return lua.safe_script(f.file, env, std::bind(&MenuSandbox::errorCallback,
|
||||
this, std::placeholders::_2), "@" + f.path, sol::load_mode::text);
|
||||
}
|
||||
throw std::runtime_error("Error opening '" + file + "', file not found.");
|
||||
}
|
||||
|
||||
void MenuSandbox::loadAndRunMod(const std::string &modPath) {
|
||||
if (!cf_file_exists(modPath.data())) throw std::runtime_error("Directory not found.");
|
||||
|
||||
LuaMod mod;
|
||||
std::string root = modPath + "/script";
|
||||
|
||||
std::list<std::string> dirsToScan {root};
|
||||
std::list<std::string> luaFiles {};
|
||||
|
||||
cf_dir_t dir;
|
||||
while (!dirsToScan.empty()) {
|
||||
std::string dirStr = *dirsToScan.begin();
|
||||
dirsToScan.erase(dirsToScan.begin());
|
||||
|
||||
if (!cf_file_exists(dirStr.data())) throw std::runtime_error("Missing 'script' directory.");
|
||||
cf_dir_open(&dir, dirStr.data());
|
||||
|
||||
while (dir.has_next) {
|
||||
// Read through files in the directory
|
||||
cf_file_t scannedFile;
|
||||
cf_read_file(&dir, &scannedFile);
|
||||
|
||||
if (strncmp(scannedFile.name, ".", 1) != 0) {
|
||||
if (scannedFile.is_dir) dirsToScan.emplace_back(scannedFile.path);
|
||||
else {
|
||||
auto path = std::string_view(scannedFile.path);
|
||||
if (path.rfind('.') != std::string::npos && path.rfind('.') == path.rfind(".lua"))
|
||||
luaFiles.emplace_back(scannedFile.path);
|
||||
}
|
||||
}
|
||||
cf_dir_next(&dir);
|
||||
}
|
||||
cf_dir_close(&dir);
|
||||
}
|
||||
|
||||
mod.modPath = modPath;
|
||||
|
||||
for (std::string& file : luaFiles) {
|
||||
size_t rootPos = file.find(root);
|
||||
std::string modPath = file;
|
||||
|
||||
if (rootPos == std::string::npos)
|
||||
throw std::runtime_error("Attempted to access file \"" + file + "\", which is outside of the mod root.");
|
||||
|
||||
modPath.erase(rootPos, root.length() + 1);
|
||||
modPath.resize(modPath.size() - 4);
|
||||
|
||||
std::ifstream t(file);
|
||||
std::string fileStr((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
|
||||
|
||||
LuaMod::File f {modPath, fileStr};
|
||||
mod.files.push_back(f);
|
||||
}
|
||||
|
||||
std::string texPath = modPath + "/textures";
|
||||
if (cf_file_exists(texPath.data())) {
|
||||
this->modAssets = client.game->textures.loadDirectory(texPath, false, true);
|
||||
}
|
||||
|
||||
this->mod = mod;
|
||||
runFileSandboxed("init");
|
||||
void MenuSandbox::loadAndRunMod(const std::string& modPath) {
|
||||
if (!cf_file_exists(modPath.data())) throw std::runtime_error("Directory not found.");
|
||||
|
||||
LuaMod mod;
|
||||
std::string root = modPath + "/script";
|
||||
|
||||
std::list<std::string> dirsToScan{ root };
|
||||
std::list<std::string> luaFiles{};
|
||||
|
||||
cf_dir_t dir;
|
||||
while (!dirsToScan.empty()) {
|
||||
std::string dirStr = *dirsToScan.begin();
|
||||
dirsToScan.erase(dirsToScan.begin());
|
||||
|
||||
if (!cf_file_exists(dirStr.data())) throw std::runtime_error("Missing 'script' directory.");
|
||||
cf_dir_open(&dir, dirStr.data());
|
||||
|
||||
while (dir.has_next) {
|
||||
// Read through files in the directory
|
||||
cf_file_t scannedFile;
|
||||
cf_read_file(&dir, &scannedFile);
|
||||
|
||||
if (strncmp(scannedFile.name, ".", 1) != 0) {
|
||||
if (scannedFile.is_dir) dirsToScan.emplace_back(scannedFile.path);
|
||||
else {
|
||||
auto path = std::string_view(scannedFile.path);
|
||||
if (path.rfind('.') != std::string::npos && path.rfind('.') == path.rfind(".lua"))
|
||||
luaFiles.emplace_back(scannedFile.path);
|
||||
}
|
||||
}
|
||||
cf_dir_next(&dir);
|
||||
}
|
||||
cf_dir_close(&dir);
|
||||
}
|
||||
|
||||
mod.modPath = modPath;
|
||||
|
||||
for (std::string& file : luaFiles) {
|
||||
size_t rootPos = file.find(root);
|
||||
std::string modPath = file;
|
||||
|
||||
if (rootPos == std::string::npos)
|
||||
throw std::runtime_error("Attempted to access file \"" + file + "\", which is outside of the mod root.");
|
||||
|
||||
modPath.erase(rootPos, root.length() + 1);
|
||||
modPath.resize(modPath.size() - 4);
|
||||
|
||||
std::ifstream t(file);
|
||||
std::string fileStr((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
|
||||
|
||||
LuaMod::File f{ modPath, fileStr };
|
||||
mod.files.push_back(f);
|
||||
}
|
||||
|
||||
std::string texPath = modPath + "/textures";
|
||||
if (cf_file_exists(texPath.data())) {
|
||||
this->modAssets = client.game->textures.loadDirectory(texPath, false, true);
|
||||
}
|
||||
|
||||
this->mod = mod;
|
||||
runFileSandboxed("init");
|
||||
}
|
||||
|
||||
void MenuSandbox::showError(const std::string& what, const std::string& subgame) {
|
||||
const std::string errPrefixText = "Encountered an error while loading the menu for " + subgame + " ;-;";
|
||||
Font f(client.game->textures, client.game->textures["font"]);
|
||||
|
||||
auto errWrap = std::make_shared<GuiContainer>("error");
|
||||
container->add(errWrap);
|
||||
|
||||
auto errPrefix = std::make_shared<GuiText>("error_text");
|
||||
errPrefix->create({3, 3}, {}, {0.7, 0, 0.3, 1}, {1, 1, 1, 1}, f);
|
||||
errPrefix->setText(errPrefixText);
|
||||
errPrefix->setPos({8, 16});
|
||||
errWrap->add(errPrefix);
|
||||
|
||||
auto errMsg = std::make_shared<GuiText>("error_text");
|
||||
errMsg->create({3, 3}, {}, {}, {1, 0.5, 0.6, 1}, f);
|
||||
errMsg->setText(what);
|
||||
errMsg->setPos({8, 52});
|
||||
errWrap->add(errMsg);
|
||||
const std::string errPrefixText = "Encountered an error while loading the menu for " + subgame + " ;-;";
|
||||
Font f(client.game->textures, client.game->textures["font"]);
|
||||
|
||||
auto errWrap = std::make_shared<GuiContainer>("error");
|
||||
container->add(errWrap);
|
||||
|
||||
auto errPrefix = std::make_shared<GuiText>("error_text");
|
||||
errPrefix->create({ 3, 3 }, {}, { 0.7, 0, 0.3, 1 }, { 1, 1, 1, 1 }, f);
|
||||
errPrefix->setText(errPrefixText);
|
||||
errPrefix->setPos({ 8, 16 });
|
||||
errWrap->add(errPrefix);
|
||||
|
||||
auto errMsg = std::make_shared<GuiText>("error_text");
|
||||
errMsg->create({ 3, 3 }, {}, {}, { 1, 0.5, 0.6, 1 }, f);
|
||||
errMsg->setText(what);
|
||||
errMsg->setPos({ 8, 52 });
|
||||
errWrap->add(errMsg);
|
||||
}
|
||||
|
||||
sol::protected_function_result MenuSandbox::errorCallback(sol::protected_function_result r) const {
|
||||
sol::error err = r;
|
||||
std::string errString = err.what();
|
||||
|
||||
try {
|
||||
std::string::size_type lineNumStart = errString.find(':');
|
||||
if (lineNumStart == std::string::npos) throw std::out_of_range("Improperly formatted error. [0]");
|
||||
std::string::size_type lineNumEnd = errString.find(':', lineNumStart + 1);
|
||||
if (lineNumEnd == std::string::npos) throw std::out_of_range("Improperly formatted error. [1]");
|
||||
|
||||
std::string fileName = errString.substr(0, lineNumStart);
|
||||
int lineNum = std::stoi(errString.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1));
|
||||
|
||||
for (const LuaMod::File& file : mod.files) if (file.path == fileName)
|
||||
throw std::runtime_error(ErrorFormatter::formatError(fileName, lineNum, errString, file.file));
|
||||
|
||||
throw std::out_of_range("Error thrown outside of handled files. [2]");
|
||||
}
|
||||
catch (const std::runtime_error& e) {
|
||||
std::cout << Log::err << e.what() << std::endl;
|
||||
throw;
|
||||
}
|
||||
catch (const std::out_of_range& e) {
|
||||
std::cout << Log::err << "Failed to format error, " << e.what() << Log::endl;
|
||||
throw std::runtime_error(errString);
|
||||
}
|
||||
sol::error err = r;
|
||||
std::string errString = err.what();
|
||||
|
||||
try {
|
||||
std::string::size_type lineNumStart = errString.find(':');
|
||||
if (lineNumStart == std::string::npos) throw std::out_of_range("Improperly formatted error. [0]");
|
||||
std::string::size_type lineNumEnd = errString.find(':', lineNumStart + 1);
|
||||
if (lineNumEnd == std::string::npos) throw std::out_of_range("Improperly formatted error. [1]");
|
||||
|
||||
std::string fileName = errString.substr(0, lineNumStart);
|
||||
int lineNum = std::stoi(errString.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1));
|
||||
|
||||
for (const LuaMod::File& file : mod.files)
|
||||
if (file.path == fileName)
|
||||
throw std::runtime_error(ErrorFormatter::formatError(fileName, lineNum, errString, file.file));
|
||||
|
||||
throw std::out_of_range("Error thrown outside of handled files. [2]");
|
||||
}
|
||||
catch (const std::runtime_error& e) {
|
||||
std::cout << Log::err << e.what() << std::endl;
|
||||
throw;
|
||||
}
|
||||
catch (const std::out_of_range& e) {
|
||||
std::cout << Log::err << "Failed to format error, " << e.what() << Log::endl;
|
||||
throw std::runtime_error(errString);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,37 +10,46 @@
|
|||
#include "client/gui/GuiBuilder.h"
|
||||
|
||||
class Client;
|
||||
|
||||
class Subgame;
|
||||
|
||||
class AtlasRef;
|
||||
|
||||
class SubgameDef;
|
||||
|
||||
class GuiContainer;
|
||||
|
||||
class MenuSandbox : LuaParser {
|
||||
public:
|
||||
MenuSandbox(glm::ivec2& window, Client& client, std::shared_ptr<GuiContainer> container);
|
||||
void load(const SubgameDef& subgame);
|
||||
|
||||
void update(double delta) override;
|
||||
void windowResized();
|
||||
|
||||
using LuaParser::update;
|
||||
private:
|
||||
void reset();
|
||||
void loadApi();
|
||||
void loadAndRunMod(const std::string& modPath);
|
||||
|
||||
void showError(const std::string& what, const std::string& subgame);
|
||||
|
||||
sol::protected_function_result runFileSandboxed(const std::string& file);
|
||||
virtual sol::protected_function_result errorCallback(sol::protected_function_result r) const override;
|
||||
|
||||
LuaMod mod {};
|
||||
std::vector<std::shared_ptr<AtlasRef>> modAssets {};
|
||||
|
||||
std::shared_ptr<GuiContainer> container = nullptr;
|
||||
std::shared_ptr<GuiContainer> luaContainer = nullptr;
|
||||
GuiBuilder builder;
|
||||
|
||||
Client& client;
|
||||
glm::ivec2& win;
|
||||
public:
|
||||
MenuSandbox(glm::ivec2& window, Client& client, std::shared_ptr<GuiContainer> container);
|
||||
|
||||
void load(const SubgameDef& subgame);
|
||||
|
||||
void update(double delta) override;
|
||||
|
||||
void windowResized();
|
||||
|
||||
using LuaParser::update;
|
||||
private:
|
||||
void reset();
|
||||
|
||||
void loadApi();
|
||||
|
||||
void loadAndRunMod(const std::string& modPath);
|
||||
|
||||
void showError(const std::string& what, const std::string& subgame);
|
||||
|
||||
sol::protected_function_result runFileSandboxed(const std::string& file);
|
||||
|
||||
virtual sol::protected_function_result errorCallback(sol::protected_function_result r) const override;
|
||||
|
||||
LuaMod mod{};
|
||||
std::vector<std::shared_ptr<AtlasRef>> modAssets{};
|
||||
|
||||
std::shared_ptr<GuiContainer> container = nullptr;
|
||||
std::shared_ptr<GuiContainer> luaContainer = nullptr;
|
||||
GuiBuilder builder;
|
||||
|
||||
Client& client;
|
||||
glm::ivec2& win;
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <string>
|
||||
|
||||
struct SubgameConfig {
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::string version;
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::string version;
|
||||
};
|
|
@ -11,8 +11,8 @@
|
|||
class AtlasRef;
|
||||
|
||||
class SubgameDef {
|
||||
public:
|
||||
std::shared_ptr<AtlasRef> iconRef = nullptr;
|
||||
SubgameConfig config {};
|
||||
std::string subgamePath = "";
|
||||
public:
|
||||
std::shared_ptr<AtlasRef> iconRef = nullptr;
|
||||
SubgameConfig config{};
|
||||
std::string subgamePath = "";
|
||||
};
|
||||
|
|
|
@ -25,228 +25,222 @@
|
|||
* @param addr - The server address to connect to.
|
||||
*/
|
||||
|
||||
ConnectScene::ConnectScene(Client &client, Address addr) : Scene(client),
|
||||
connection(client.connection) {
|
||||
|
||||
client.renderer.setClearColor(10, 10, 10);
|
||||
|
||||
Font f(client.game->textures, client.game->textures["font"]);
|
||||
|
||||
auto statusText = std::make_shared<GuiText>("statusText");
|
||||
statusText->create({2, 2}, {}, {}, {1, 1, 1, 1}, f);
|
||||
statusText->setText("Connecting...");
|
||||
statusText->setPos({32, 24});
|
||||
components.add(statusText);
|
||||
|
||||
auto loadBar = std::make_shared<GuiRect>("loadBar");
|
||||
loadBar->create({1, 32}, {}, {0.17, 0.75, 0.93, 1});
|
||||
loadBar->setPos({0, client.renderer.window.getSize().y - 32});
|
||||
components.add(loadBar);
|
||||
|
||||
connection.attemptConnect(std::move(addr));
|
||||
|
||||
client.renderer.window.addResizeCallback("scene", [&](glm::ivec2 win) {
|
||||
components.get<GuiRect>("loadBar")->setPos({0, win.y - 32});
|
||||
});
|
||||
ConnectScene::ConnectScene(Client& client, Address addr) : Scene(client),
|
||||
connection(client.connection) {
|
||||
|
||||
client.renderer.setClearColor(10, 10, 10);
|
||||
|
||||
Font f(client.game->textures, client.game->textures["font"]);
|
||||
|
||||
auto statusText = std::make_shared<GuiText>("statusText");
|
||||
statusText->create({ 2, 2 }, {}, {}, { 1, 1, 1, 1 }, f);
|
||||
statusText->setText("Connecting...");
|
||||
statusText->setPos({ 32, 24 });
|
||||
components.add(statusText);
|
||||
|
||||
auto loadBar = std::make_shared<GuiRect>("loadBar");
|
||||
loadBar->create({ 1, 32 }, {}, { 0.17, 0.75, 0.93, 1 });
|
||||
loadBar->setPos({ 0, client.renderer.window.getSize().y - 32 });
|
||||
components.add(loadBar);
|
||||
|
||||
connection.attemptConnect(std::move(addr));
|
||||
|
||||
client.renderer.window.addResizeCallback("scene", [&](glm::ivec2 win) {
|
||||
components.get<GuiRect>("loadBar")->setPos({ 0, win.y - 32 });
|
||||
});
|
||||
}
|
||||
|
||||
void ConnectScene::update() {
|
||||
client.game->textures.update();
|
||||
|
||||
switch (connectState) {
|
||||
default:
|
||||
throw std::runtime_error("Invalid connection state.");
|
||||
|
||||
case State::DONE:
|
||||
case State::FAILED_CONNECT:
|
||||
break;
|
||||
|
||||
case State::CONNECTING:
|
||||
handleConnecting();
|
||||
break;
|
||||
|
||||
case State::PROPERTIES: {
|
||||
components.get<GuiRect>("loadBar")->setScale({client.renderer.window.getSize().x * 0.1, 32});
|
||||
|
||||
ENetEvent e;
|
||||
if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) {
|
||||
PacketView p(e.packet);
|
||||
|
||||
if (p.type == Packet::Type::SERVER_INFO) {
|
||||
auto statusText = components.get<GuiText>("statusText");
|
||||
statusText->setText(statusText->getText() + "Received server properties.\n");
|
||||
|
||||
// TODO: Reimplement this somewhere or something.
|
||||
client.game->textures.update();
|
||||
|
||||
switch (connectState) {
|
||||
default:throw std::runtime_error("Invalid connection state.");
|
||||
|
||||
case State::DONE:
|
||||
case State::FAILED_CONNECT:break;
|
||||
|
||||
case State::CONNECTING:handleConnecting();
|
||||
break;
|
||||
|
||||
case State::PROPERTIES: {
|
||||
components.get<GuiRect>("loadBar")->setScale({ client.renderer.window.getSize().x * 0.1, 32 });
|
||||
|
||||
ENetEvent e;
|
||||
if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) {
|
||||
PacketView p(e.packet);
|
||||
|
||||
if (p.type == Packet::Type::SERVER_INFO) {
|
||||
auto statusText = components.get<GuiText>("statusText");
|
||||
statusText->setText(statusText->getText() + "Received server properties.\n");
|
||||
|
||||
// TODO: Reimplement this somewhere or something.
|
||||
// state.seed = p.d.read<unsigned int>();
|
||||
|
||||
connectState = State::IDENTIFIER_LIST;
|
||||
Packet resp(Packet::Type::BLOCK_IDENTIFIER_LIST);
|
||||
resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case State::IDENTIFIER_LIST: {
|
||||
components.get<GuiRect>("loadBar")->setScale({client.renderer.window.getSize().x * 0.2, 32});
|
||||
|
||||
ENetEvent e;
|
||||
if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) {
|
||||
PacketView p(e.packet);
|
||||
|
||||
if (p.type == Packet::Type::BLOCK_IDENTIFIER_LIST) {
|
||||
auto statusText = components.get<GuiText>("statusText");
|
||||
statusText->setText(statusText->getText() + "Received block index-identifier table.\n");
|
||||
|
||||
client.game->getDefs().setIdentifiers(p.d.read<std::vector<std::string>>());
|
||||
|
||||
Packet resp(Packet::Type::BIOME_IDENTIFIER_LIST);
|
||||
resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT);
|
||||
}
|
||||
else if (p.type == Packet::Type::BIOME_IDENTIFIER_LIST) {
|
||||
auto statusText = components.get<GuiText>("statusText");
|
||||
statusText->setText(statusText->getText() + "Received biome index-identifier table.\nDownloading mods...\n");
|
||||
|
||||
client.game->getBiomes().setIdentifiers(p.d.read<std::vector<std::string>>());
|
||||
|
||||
connectState = State::MODS;
|
||||
Packet resp(Packet::Type::MODS);
|
||||
resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case State::MODS: {
|
||||
components.get<GuiRect>("loadBar")->setScale({client.renderer.window.getSize().x * 0.4, 32});
|
||||
ENetEvent e;
|
||||
if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) {
|
||||
PacketView p(e.packet);
|
||||
|
||||
auto statusText = components.get<GuiText>("statusText");
|
||||
|
||||
if (p.type == Packet::Type::MODS) {
|
||||
auto luaMod = LuaMod::fromPacket(p);
|
||||
statusText->setText(statusText->getText() + "Received mod " + luaMod.config.name + ".\n");
|
||||
client.game->getParser().getHandler().addLuaMod(std::move(luaMod));
|
||||
}
|
||||
else if (p.type == Packet::Type::MOD_ORDER) {
|
||||
client.game->getParser().getHandler().setModsOrder(p.d.read<std::vector<std::string>>());
|
||||
|
||||
statusText->setText(statusText->getText() + "Done downloading mods.\nReceived the mods order.\nDownloading media...\n");
|
||||
|
||||
connectState = State::MEDIA;
|
||||
Packet resp(Packet::Type::MEDIA);
|
||||
resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case State::MEDIA: {
|
||||
components.get<GuiRect>("loadBar")->setScale({client.renderer.window.getSize().x * 0.6, 32});
|
||||
|
||||
ENetEvent e;
|
||||
if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) {
|
||||
PacketView p(e.packet);
|
||||
|
||||
auto statusText = components.get<GuiText>("statusText");
|
||||
|
||||
if (p.type == Packet::Type::MEDIA) {
|
||||
AssetType t = static_cast<AssetType>(p.d.read<int>());
|
||||
unsigned int count = 0;
|
||||
|
||||
while (t != AssetType::END) {
|
||||
std::string assetName = p.d.read<std::string>();
|
||||
|
||||
if (t == AssetType::TEXTURE) {
|
||||
int width = p.d.read<unsigned int>();
|
||||
int height = p.d.read<unsigned int>();
|
||||
|
||||
std::string data = p.d.read<std::string>();
|
||||
std::string uncompressed = gzip::decompress(data.data(), data.length());
|
||||
|
||||
client.game->textures.addImage(
|
||||
reinterpret_cast<unsigned char *>(const_cast<char *>(uncompressed.data())),
|
||||
assetName, true, width, height);
|
||||
}
|
||||
else if (t == AssetType::MODEL) {
|
||||
std::string format = p.d.read<std::string>();
|
||||
std::string data = p.d.read<std::string>();
|
||||
|
||||
client.game->models.models.insert({assetName, SerializedModel{assetName, data, format}});
|
||||
}
|
||||
|
||||
t = static_cast<AssetType>(p.d.read<int>());
|
||||
count++;
|
||||
}
|
||||
|
||||
statusText->setText(statusText->getText() + "Received " + std::to_string(count) + "x media files.\n");
|
||||
}
|
||||
else if (p.type == Packet::Type::MEDIA_DONE) {
|
||||
components.get<GuiRect>("loadBar")->setScale({client.renderer.window.getSize().x, 32});
|
||||
statusText->setText(statusText->getText() + "Done downloading media.\nJoining world...\n");
|
||||
|
||||
connectState = State::DONE;
|
||||
client.scene.setScene(std::make_unique<GameScene>(client));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
connectState = State::IDENTIFIER_LIST;
|
||||
Packet resp(Packet::Type::BLOCK_IDENTIFIER_LIST);
|
||||
resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case State::IDENTIFIER_LIST: {
|
||||
components.get<GuiRect>("loadBar")->setScale({ client.renderer.window.getSize().x * 0.2, 32 });
|
||||
|
||||
ENetEvent e;
|
||||
if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) {
|
||||
PacketView p(e.packet);
|
||||
|
||||
if (p.type == Packet::Type::BLOCK_IDENTIFIER_LIST) {
|
||||
auto statusText = components.get<GuiText>("statusText");
|
||||
statusText->setText(statusText->getText() + "Received block index-identifier table.\n");
|
||||
|
||||
client.game->getDefs().setIdentifiers(p.d.read<std::vector<std::string>>());
|
||||
|
||||
Packet resp(Packet::Type::BIOME_IDENTIFIER_LIST);
|
||||
resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT);
|
||||
}
|
||||
else if (p.type == Packet::Type::BIOME_IDENTIFIER_LIST) {
|
||||
auto statusText = components.get<GuiText>("statusText");
|
||||
statusText->setText(
|
||||
statusText->getText() + "Received biome index-identifier table.\nDownloading mods...\n");
|
||||
|
||||
client.game->getBiomes().setIdentifiers(p.d.read<std::vector<std::string>>());
|
||||
|
||||
connectState = State::MODS;
|
||||
Packet resp(Packet::Type::MODS);
|
||||
resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case State::MODS: {
|
||||
components.get<GuiRect>("loadBar")->setScale({ client.renderer.window.getSize().x * 0.4, 32 });
|
||||
ENetEvent e;
|
||||
if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) {
|
||||
PacketView p(e.packet);
|
||||
|
||||
auto statusText = components.get<GuiText>("statusText");
|
||||
|
||||
if (p.type == Packet::Type::MODS) {
|
||||
auto luaMod = LuaMod::fromPacket(p);
|
||||
statusText->setText(statusText->getText() + "Received mod " + luaMod.config.name + ".\n");
|
||||
client.game->getParser().getHandler().addLuaMod(std::move(luaMod));
|
||||
}
|
||||
else if (p.type == Packet::Type::MOD_ORDER) {
|
||||
client.game->getParser().getHandler().setModsOrder(p.d.read<std::vector<std::string>>());
|
||||
|
||||
statusText->setText(
|
||||
statusText->getText() + "Done downloading mods.\nReceived the mods order.\nDownloading media...\n");
|
||||
|
||||
connectState = State::MEDIA;
|
||||
Packet resp(Packet::Type::MEDIA);
|
||||
resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case State::MEDIA: {
|
||||
components.get<GuiRect>("loadBar")->setScale({ client.renderer.window.getSize().x * 0.6, 32 });
|
||||
|
||||
ENetEvent e;
|
||||
if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) {
|
||||
PacketView p(e.packet);
|
||||
|
||||
auto statusText = components.get<GuiText>("statusText");
|
||||
|
||||
if (p.type == Packet::Type::MEDIA) {
|
||||
AssetType t = static_cast<AssetType>(p.d.read<int>());
|
||||
unsigned int count = 0;
|
||||
|
||||
while (t != AssetType::END) {
|
||||
std::string assetName = p.d.read<std::string>();
|
||||
|
||||
if (t == AssetType::TEXTURE) {
|
||||
int width = p.d.read<unsigned int>();
|
||||
int height = p.d.read<unsigned int>();
|
||||
|
||||
std::string data = p.d.read<std::string>();
|
||||
std::string uncompressed = gzip::decompress(data.data(), data.length());
|
||||
|
||||
client.game->textures.addImage(
|
||||
reinterpret_cast<unsigned char*>(const_cast<char*>(uncompressed.data())),
|
||||
assetName, true, width, height);
|
||||
}
|
||||
else if (t == AssetType::MODEL) {
|
||||
std::string format = p.d.read<std::string>();
|
||||
std::string data = p.d.read<std::string>();
|
||||
|
||||
client.game->models.models.insert({ assetName, SerializedModel{ assetName, data, format }});
|
||||
}
|
||||
|
||||
t = static_cast<AssetType>(p.d.read<int>());
|
||||
count++;
|
||||
}
|
||||
|
||||
statusText->setText(statusText->getText() + "Received " + std::to_string(count) + "x media files.\n");
|
||||
}
|
||||
else if (p.type == Packet::Type::MEDIA_DONE) {
|
||||
components.get<GuiRect>("loadBar")->setScale({ client.renderer.window.getSize().x, 32 });
|
||||
statusText->setText(statusText->getText() + "Done downloading media.\nJoining world...\n");
|
||||
|
||||
connectState = State::DONE;
|
||||
client.scene.setScene(std::make_unique<GameScene>(client));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectScene::handleConnecting() {
|
||||
Packet resp(Packet::Type::SERVER_INFO);
|
||||
auto statusText = components.get<GuiText>("statusText");
|
||||
|
||||
switch (connection.getConnectionStatus()) {
|
||||
default:
|
||||
throw std::runtime_error("Uncaught connection error.");
|
||||
|
||||
case ServerConnection::State::ENET_ERROR:
|
||||
throw std::runtime_error("Enet Initialization error.");
|
||||
break;
|
||||
|
||||
case ServerConnection::State::FAILED_CONNECT:
|
||||
connectState = State::FAILED_CONNECT;
|
||||
statusText->setText(statusText->getText() + "\nFailed to connect :(\n");
|
||||
break;
|
||||
|
||||
case ServerConnection::State::ATTEMPTING_CONNECT:
|
||||
connection.processConnecting();
|
||||
|
||||
dotsTime += client.getDelta();
|
||||
if (dotsTime > 1) {
|
||||
dotsTime -= 1;
|
||||
statusText->setText(statusText->getText() + ".");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ServerConnection::State::CONNECTED:
|
||||
connectState = State::PROPERTIES;
|
||||
statusText->setText(statusText->getText() + " Connected!~\n");
|
||||
|
||||
resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT);
|
||||
|
||||
break;
|
||||
}
|
||||
Packet resp(Packet::Type::SERVER_INFO);
|
||||
auto statusText = components.get<GuiText>("statusText");
|
||||
|
||||
switch (connection.getConnectionStatus()) {
|
||||
default:throw std::runtime_error("Uncaught connection error.");
|
||||
|
||||
case ServerConnection::State::ENET_ERROR:throw std::runtime_error("Enet Initialization error.");
|
||||
break;
|
||||
|
||||
case ServerConnection::State::FAILED_CONNECT:connectState = State::FAILED_CONNECT;
|
||||
statusText->setText(statusText->getText() + "\nFailed to connect :(\n");
|
||||
break;
|
||||
|
||||
case ServerConnection::State::ATTEMPTING_CONNECT:connection.processConnecting();
|
||||
|
||||
dotsTime += client.getDelta();
|
||||
if (dotsTime > 1) {
|
||||
dotsTime -= 1;
|
||||
statusText->setText(statusText->getText() + ".");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ServerConnection::State::CONNECTED:connectState = State::PROPERTIES;
|
||||
statusText->setText(statusText->getText() + " Connected!~\n");
|
||||
|
||||
resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectScene::draw() {
|
||||
Renderer& renderer = client.renderer;
|
||||
|
||||
renderer.beginChunkDeferredCalls();
|
||||
renderer.endDeferredCalls();
|
||||
renderer.beginGUIDrawCalls();
|
||||
renderer.enableTexture(&client.game->textures.atlasTexture);
|
||||
|
||||
components.draw(renderer);
|
||||
|
||||
renderer.swapBuffers();
|
||||
Renderer& renderer = client.renderer;
|
||||
|
||||
renderer.beginChunkDeferredCalls();
|
||||
renderer.endDeferredCalls();
|
||||
renderer.beginGUIDrawCalls();
|
||||
renderer.enableTexture(&client.game->textures.atlasTexture);
|
||||
|
||||
components.draw(renderer);
|
||||
|
||||
renderer.swapBuffers();
|
||||
}
|
||||
|
||||
void ConnectScene::cleanup() {
|
||||
client.renderer.window.removeResizeCallback("scene");
|
||||
client.renderer.window.removeResizeCallback("scene");
|
||||
}
|
|
@ -9,33 +9,36 @@
|
|||
#include "client/gui/basic/GuiContainer.h"
|
||||
|
||||
class ServerConnection;
|
||||
|
||||
class Address;
|
||||
|
||||
class ConnectScene : public Scene {
|
||||
public:
|
||||
enum class State {
|
||||
CONNECTING,
|
||||
FAILED_CONNECT,
|
||||
PROPERTIES,
|
||||
IDENTIFIER_LIST,
|
||||
MODS,
|
||||
MEDIA,
|
||||
DONE
|
||||
};
|
||||
|
||||
ConnectScene(Client& state, Address addr);
|
||||
|
||||
void update() override;
|
||||
void draw() override;
|
||||
void cleanup() override;
|
||||
|
||||
void handleConnecting();
|
||||
|
||||
private:
|
||||
State connectState = State::CONNECTING;
|
||||
ServerConnection& connection;
|
||||
|
||||
GuiContainer components;
|
||||
|
||||
double dotsTime = 0;
|
||||
public:
|
||||
enum class State {
|
||||
CONNECTING,
|
||||
FAILED_CONNECT,
|
||||
PROPERTIES,
|
||||
IDENTIFIER_LIST,
|
||||
MODS,
|
||||
MEDIA,
|
||||
DONE
|
||||
};
|
||||
|
||||
ConnectScene(Client& state, Address addr);
|
||||
|
||||
void update() override;
|
||||
|
||||
void draw() override;
|
||||
|
||||
void cleanup() override;
|
||||
|
||||
void handleConnecting();
|
||||
|
||||
private:
|
||||
State connectState = State::CONNECTING;
|
||||
ServerConnection& connection;
|
||||
|
||||
GuiContainer components;
|
||||
|
||||
double dotsTime = 0;
|
||||
};
|
||||
|
|
|
@ -9,73 +9,73 @@
|
|||
#include "client/graph/Renderer.h"
|
||||
|
||||
GameScene::GameScene(Client& client) : Scene(client),
|
||||
world(std::make_shared<LocalWorld>(client.game, client.connection, client.renderer)),
|
||||
debugGui(client.renderer.window.getSize(), client.game, world) {
|
||||
|
||||
Packet r(Packet::Type::CONNECT_DATA_RECVD);
|
||||
r.sendTo(client.connection.getPeer(), Packet::Channel::CONNECT);
|
||||
|
||||
world.l()->connect();
|
||||
client.game->init(world, world.l()->getPlayer(), client);
|
||||
world.l()->updatePlayerDimension();
|
||||
|
||||
client.renderer.window.addResizeCallback("gamescene", Util::bind_this(&debugGui, &DebugGui::bufferResized));
|
||||
client.renderer.setClearColor(148, 194, 240);
|
||||
client.renderer.window.input.lockMouse(true);
|
||||
world(std::make_shared<LocalWorld>(client.game, client.connection, client.renderer)),
|
||||
debugGui(client.renderer.window.getSize(), client.game, world) {
|
||||
|
||||
Packet r(Packet::Type::CONNECT_DATA_RECVD);
|
||||
r.sendTo(client.connection.getPeer(), Packet::Channel::CONNECT);
|
||||
|
||||
world.l()->connect();
|
||||
client.game->init(world, world.l()->getPlayer(), client);
|
||||
world.l()->updatePlayerDimension();
|
||||
|
||||
client.renderer.window.addResizeCallback("gamescene", Util::bind_this(&debugGui, &DebugGui::bufferResized));
|
||||
client.renderer.setClearColor(148, 194, 240);
|
||||
client.renderer.window.input.lockMouse(true);
|
||||
}
|
||||
|
||||
void GameScene::update() {
|
||||
Window& window = client.renderer.window;
|
||||
|
||||
client.game->update(client.getDelta());
|
||||
world->update(client.getDelta());
|
||||
|
||||
for (auto entity : entities) entity->update(client.getDelta());
|
||||
|
||||
double lastFps = 1 / client.getDelta();
|
||||
debugGui.update(world.l()->getPlayer().l(), lastFps, world.l()->getActiveDimension().l()->getMeshChunkCount(),
|
||||
drawCalls, world.l()->getNet().serverSideChunkGens, world.l()->getNet().recvPackets);
|
||||
|
||||
world.l()->getNet().serverSideChunkGens = 0;
|
||||
world.l()->getNet().recvPackets = 0;
|
||||
|
||||
if (window.input.keyPressed(GLFW_KEY_F1)) {
|
||||
hudVisible = !hudVisible;
|
||||
debugGui.changeVisibilityState(hudVisible ? debugVisible ? 0 : 2 : 1);
|
||||
world.l()->getPlayer().l()->setHudVisible(hudVisible);
|
||||
}
|
||||
|
||||
if (window.input.keyPressed(GLFW_KEY_F3)) {
|
||||
debugVisible = !debugVisible;
|
||||
debugGui.changeVisibilityState(hudVisible ? debugVisible ? 0 : 2 : 1);
|
||||
}
|
||||
Window& window = client.renderer.window;
|
||||
|
||||
client.game->update(client.getDelta());
|
||||
world->update(client.getDelta());
|
||||
|
||||
for (auto entity : entities) entity->update(client.getDelta());
|
||||
|
||||
double lastFps = 1 / client.getDelta();
|
||||
debugGui.update(world.l()->getPlayer().l(), lastFps, world.l()->getActiveDimension().l()->getMeshChunkCount(),
|
||||
drawCalls, world.l()->getNet().serverSideChunkGens, world.l()->getNet().recvPackets);
|
||||
|
||||
world.l()->getNet().serverSideChunkGens = 0;
|
||||
world.l()->getNet().recvPackets = 0;
|
||||
|
||||
if (window.input.keyPressed(GLFW_KEY_F1)) {
|
||||
hudVisible = !hudVisible;
|
||||
debugGui.changeVisibilityState(hudVisible ? debugVisible ? 0 : 2 : 1);
|
||||
world.l()->getPlayer().l()->setHudVisible(hudVisible);
|
||||
}
|
||||
|
||||
if (window.input.keyPressed(GLFW_KEY_F3)) {
|
||||
debugVisible = !debugVisible;
|
||||
debugGui.changeVisibilityState(hudVisible ? debugVisible ? 0 : 2 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
void GameScene::draw() {
|
||||
Renderer& renderer = client.renderer;
|
||||
Camera& camera = renderer.camera;
|
||||
|
||||
renderer.beginChunkDeferredCalls();
|
||||
renderer.enableTexture(&client.game->textures.atlasTexture);
|
||||
|
||||
drawCalls = world.l()->renderChunks(renderer);
|
||||
|
||||
renderer.beginEntityDeferredCalls();
|
||||
|
||||
for (auto entity : entities) entity->draw(renderer);
|
||||
world.l()->renderEntities(renderer);
|
||||
|
||||
renderer.endDeferredCalls();
|
||||
renderer.beginGUIDrawCalls();
|
||||
renderer.enableTexture(&client.game->textures.atlasTexture);
|
||||
|
||||
world.l()->getPlayer().l()->drawHud(renderer);
|
||||
debugGui.draw(renderer);
|
||||
world.l()->getPlayer().l()->drawMenu(renderer);
|
||||
|
||||
renderer.swapBuffers();
|
||||
Renderer& renderer = client.renderer;
|
||||
Camera& camera = renderer.camera;
|
||||
|
||||
renderer.beginChunkDeferredCalls();
|
||||
renderer.enableTexture(&client.game->textures.atlasTexture);
|
||||
|
||||
drawCalls = world.l()->renderChunks(renderer);
|
||||
|
||||
renderer.beginEntityDeferredCalls();
|
||||
|
||||
for (auto entity : entities) entity->draw(renderer);
|
||||
world.l()->renderEntities(renderer);
|
||||
|
||||
renderer.endDeferredCalls();
|
||||
renderer.beginGUIDrawCalls();
|
||||
renderer.enableTexture(&client.game->textures.atlasTexture);
|
||||
|
||||
world.l()->getPlayer().l()->drawHud(renderer);
|
||||
debugGui.draw(renderer);
|
||||
world.l()->getPlayer().l()->drawMenu(renderer);
|
||||
|
||||
renderer.swapBuffers();
|
||||
}
|
||||
|
||||
void GameScene::cleanup() {
|
||||
client.renderer.window.removeResizeCallback("gamescene");
|
||||
client.renderer.window.removeResizeCallback("gamescene");
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue