Heightmap editor + saving
This commit is contained in:
56
src/editor/CMakeLists.txt
Normal file
56
src/editor/CMakeLists.txt
Normal file
@@ -0,0 +1,56 @@
|
||||
cmake_minimum_required(VERSION 3.13.0)
|
||||
project(Editor)
|
||||
|
||||
find_package(OGRE REQUIRED COMPONENTS Bites Paging Terrain CONFIG)
|
||||
find_package(ZLIB)
|
||||
find_package(SDL2)
|
||||
find_package(assimp REQUIRED CONFIG)
|
||||
find_package(OgreProcedural REQUIRED CONFIG)
|
||||
find_package(pugixml REQUIRED CONFIG)
|
||||
find_package(flecs REQUIRED CONFIG)
|
||||
|
||||
set(COPY_DIRECTORIES resources skybox water)
|
||||
set(INSTALL_DEPS ${CMAKE_CURRENT_BINARY_DIR}/resources.cfg)
|
||||
foreach(DIR_NAME ${COPY_DIRECTORIES})
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${DIR_NAME}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/../../${DIR_NAME} ${CMAKE_CURRENT_BINARY_DIR}/${DIR_NAME}
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../../${DIR_NAME}
|
||||
)
|
||||
list(APPEND INSTALL_DEPS ${CMAKE_CURRENT_BINARY_DIR}/${DIR_NAME})
|
||||
endforeach()
|
||||
|
||||
add_custom_target(install_resources DEPENDS ${INSTALL_DEPS})
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/resources.cfg
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/../../resources.cfg ${CMAKE_CURRENT_BINARY_DIR}/resources.cfg
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../../resources.cfg
|
||||
)
|
||||
|
||||
add_library(editor STATIC EditorGizmoModule.cpp EditorInputModule.cpp)
|
||||
target_link_libraries(editor PRIVATE
|
||||
OgreMain
|
||||
GameData
|
||||
)
|
||||
|
||||
add_executable(Editor main.cpp)
|
||||
target_link_libraries(Editor PRIVATE
|
||||
OgreMain
|
||||
OgreBites
|
||||
OgrePaging
|
||||
OgreTerrain
|
||||
OgreOverlay
|
||||
OgreMeshLodGenerator
|
||||
GameData
|
||||
sound
|
||||
sceneloader
|
||||
editor
|
||||
world-build
|
||||
physics
|
||||
lua
|
||||
flecs::flecs_static
|
||||
)
|
||||
if(OGRE_STATIC)
|
||||
target_link_options(Editor PRIVATE -static-libstdc++ -static-libgcc)
|
||||
endif()
|
||||
target_compile_definitions(Editor PRIVATE FLECS_CPP_NO_AUTO_REGISTRATION)
|
||||
add_dependencies(Editor install_resources)
|
||||
|
||||
76
src/editor/EditorGizmoModule.cpp
Normal file
76
src/editor/EditorGizmoModule.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include <OgreMaterialManager.h>
|
||||
#include <OgreMaterial.h>
|
||||
#include <OgreTechnique.h>
|
||||
#include <OgrePass.h>
|
||||
#include "Components.h"
|
||||
#include "GameData.h"
|
||||
#include "EditorGizmoModule.h"
|
||||
|
||||
namespace ECS
|
||||
{
|
||||
static Ogre::MaterialPtr
|
||||
createVertexColorNoDepthMaterial(const std::string &materialName)
|
||||
{
|
||||
Ogre::MaterialPtr material =
|
||||
Ogre::MaterialManager::getSingleton().create(
|
||||
materialName,
|
||||
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||
|
||||
Ogre::Pass *pass = material->getTechnique(0)->getPass(0);
|
||||
|
||||
// Disable dynamic lighting, so only vertex colors are used
|
||||
pass->setLightingEnabled(false);
|
||||
pass->setCullingMode(Ogre::CULL_NONE);
|
||||
|
||||
// Set the material to use vertex colors for diffuse, ambient, and specular components
|
||||
pass->setVertexColourTracking(Ogre::TVC_DIFFUSE | Ogre::TVC_AMBIENT |
|
||||
Ogre::TVC_SPECULAR);
|
||||
|
||||
// Disable depth checking (so it renders regardless of what's already in the depth buffer)
|
||||
// pass->setDepthCheckEnabled(false);
|
||||
pass->setDepthCheckEnabled(true);
|
||||
|
||||
// Disable depth writing (so subsequent objects are not occluded by this one)
|
||||
// pass->setDepthWriteEnabled(false);
|
||||
pass->setDepthWriteEnabled(true);
|
||||
|
||||
// Optional: Set scene blending to alpha blending if you use vertex alpha
|
||||
// pass->setSceneBlending(Ogre::SBT_ALPHA_BLEND);
|
||||
|
||||
// Load the material (important if resources are not automatically loaded)
|
||||
material->load();
|
||||
|
||||
return material;
|
||||
}
|
||||
EditorGizmoModule::EditorGizmoModule(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<EditorGizmoModule>();
|
||||
ecs.component<EditorDebugMaterial>().add(flecs::Singleton);
|
||||
ecs.component<EditorGizmo>().add(flecs::Singleton);
|
||||
ecs.observer<EditorDebugMaterial>("SetupDebugMaterial")
|
||||
.event(flecs::OnAdd)
|
||||
.each([](EditorDebugMaterial &mdbg) {
|
||||
mdbg.material = createVertexColorNoDepthMaterial(
|
||||
"Debug/vcolor");
|
||||
});
|
||||
ecs.observer<const EditorDebugMaterial, EditorGizmo>("SetupGizmo")
|
||||
.event(flecs::OnSet)
|
||||
.each([](const EditorDebugMaterial &mdbg, EditorGizmo &gizmo) {
|
||||
gizmo.gizmo->begin(mdbg.material,
|
||||
Ogre::RenderOperation::OT_LINE_LIST);
|
||||
gizmo.gizmo->position(Ogre::Vector3(0, 0, 0));
|
||||
gizmo.gizmo->colour(Ogre::ColourValue(0, 0, 1, 1));
|
||||
gizmo.gizmo->position(Ogre::Vector3(0, 0, 1));
|
||||
gizmo.gizmo->colour(Ogre::ColourValue(0, 0, 1, 1));
|
||||
gizmo.gizmo->position(Ogre::Vector3(0, 0, 0));
|
||||
gizmo.gizmo->colour(Ogre::ColourValue(0, 1, 0, 1));
|
||||
gizmo.gizmo->position(Ogre::Vector3(0, 1, 0));
|
||||
gizmo.gizmo->colour(Ogre::ColourValue(0, 1, 0, 1));
|
||||
gizmo.gizmo->position(Ogre::Vector3(0, 0, 0));
|
||||
gizmo.gizmo->colour(Ogre::ColourValue(1, 0, 0, 1));
|
||||
gizmo.gizmo->position(Ogre::Vector3(1, 0, 0));
|
||||
gizmo.gizmo->colour(Ogre::ColourValue(1, 0, 0, 1));
|
||||
gizmo.gizmo->end();
|
||||
});
|
||||
}
|
||||
}
|
||||
18
src/editor/EditorGizmoModule.h
Normal file
18
src/editor/EditorGizmoModule.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _EDITOR_GIZMO_MODULE_H_
|
||||
#define _EDITOR_GIZMO_MODULE_H_
|
||||
#include <flecs.h>
|
||||
#include <Ogre.h>
|
||||
namespace ECS
|
||||
{
|
||||
struct EditorDebugMaterial {
|
||||
Ogre::MaterialPtr material;
|
||||
};
|
||||
struct EditorGizmo {
|
||||
std::shared_ptr<Ogre::ManualObject> gizmo;
|
||||
Ogre::SceneNode *sceneNode;
|
||||
};
|
||||
struct EditorGizmoModule {
|
||||
EditorGizmoModule(flecs::world &ecs);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
172
src/editor/EditorInputModule.cpp
Normal file
172
src/editor/EditorInputModule.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
#include <iostream>
|
||||
#include <Ogre.h>
|
||||
#include "Components.h"
|
||||
#include "GameData.h"
|
||||
#include "EditorInputModule.h"
|
||||
|
||||
namespace ECS
|
||||
{
|
||||
static void updateCameraGoal(Camera &camera, Ogre::Real deltaYaw,
|
||||
Ogre::Real deltaPitch, Ogre::Real deltaZoom)
|
||||
{
|
||||
camera.mCameraPivot->yaw(Ogre::Degree(deltaYaw), Ogre::Node::TS_PARENT);
|
||||
if (!(camera.mPivotPitch + deltaPitch > 25 && deltaPitch > 0) &&
|
||||
!(camera.mPivotPitch + deltaPitch < -60 && deltaPitch < 0)) {
|
||||
camera.mCameraPivot->pitch(Ogre::Degree(deltaPitch),
|
||||
Ogre::Node::TS_LOCAL);
|
||||
camera.mPivotPitch += deltaPitch;
|
||||
}
|
||||
Ogre::Real dist = camera.mCameraGoal->_getDerivedPosition().distance(
|
||||
camera.mCameraPivot->_getDerivedPosition());
|
||||
Ogre::Real distChange = deltaZoom * dist;
|
||||
|
||||
// bound the zoom
|
||||
if (!(dist + distChange < 8 && distChange < 0) &&
|
||||
!(dist + distChange > 25 && distChange > 0))
|
||||
camera.mCameraGoal->translate(0, 0, distChange,
|
||||
Ogre::Node::TS_LOCAL);
|
||||
}
|
||||
EditorInputModule::EditorInputModule(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<EditorInputModule>();
|
||||
ecs.system<const EngineData, Input, Camera>("HandleEditorInput")
|
||||
.kind(flecs::OnUpdate)
|
||||
.each([this](const EngineData &eng, Input &input,
|
||||
Camera &camera) {
|
||||
if (ECS::player.is_valid())
|
||||
return;
|
||||
if (!camera.configured) {
|
||||
// create a pivot at roughly the character's shoulder
|
||||
camera.mCameraPivot =
|
||||
eng.mScnMgr->getRootSceneNode()
|
||||
->createChildSceneNode();
|
||||
camera.mCameraGoal =
|
||||
camera.mCameraPivot
|
||||
->createChildSceneNode(
|
||||
Ogre::Vector3(0, 2, 0));
|
||||
camera.mCameraNode->setPosition(
|
||||
camera.mCameraPivot->getPosition() +
|
||||
camera.mCameraGoal->getPosition());
|
||||
camera.mCameraGoal->lookAt(
|
||||
Ogre::Vector3(0, 0, -10),
|
||||
Ogre::Node::TS_PARENT);
|
||||
camera.mCameraPivot->setFixedYawAxis(true);
|
||||
camera.mCameraGoal->setFixedYawAxis(true);
|
||||
camera.mCameraNode->setFixedYawAxis(true);
|
||||
// our model is quite small, so reduce the clipping planes
|
||||
camera.mCamera->setNearClipDistance(0.1f);
|
||||
camera.mCamera->setFarClipDistance(700);
|
||||
|
||||
camera.mPivotPitch = 0;
|
||||
camera.configured = true;
|
||||
}
|
||||
/* handle input */
|
||||
// if (input.control == input.control_prev)
|
||||
// return;
|
||||
uint32_t pressed = input.control & ~input.control_prev;
|
||||
uint32_t released = input.control_prev & ~input.control;
|
||||
uint32_t active = input.control;
|
||||
float zaxis = input.motion.z;
|
||||
zaxis *= 0.9f;
|
||||
if (!camera.mCameraPivot || !camera.mCameraGoal)
|
||||
return;
|
||||
// OgreAssert(false, "EditorInput");
|
||||
if (pressed & 1)
|
||||
std::cout << "W pressed\n";
|
||||
if (released & 1)
|
||||
std::cout << "W released\n";
|
||||
if (active & 1)
|
||||
zaxis -= 1.0f;
|
||||
if (active & 4)
|
||||
zaxis += 1.0f;
|
||||
if (zaxis > -1.0f && zaxis < 1.0f)
|
||||
zaxis = 0.0f;
|
||||
else
|
||||
zaxis = Ogre::Math::Sign(zaxis);
|
||||
if (active & 32)
|
||||
input.act = true;
|
||||
else
|
||||
input.act = false;
|
||||
if (pressed & 32)
|
||||
input.act_pressed = true;
|
||||
else
|
||||
input.act_pressed = false;
|
||||
if (active & 64)
|
||||
input.act2 = true;
|
||||
else
|
||||
input.act2 = false;
|
||||
if (pressed & 64)
|
||||
input.act2_pressed = true;
|
||||
else
|
||||
input.act2_pressed = false;
|
||||
input.motion.z = zaxis;
|
||||
float xaxis = input.motion.x;
|
||||
xaxis *= 0.9f;
|
||||
if (active & 2)
|
||||
xaxis = -1.0f;
|
||||
if (active & 8)
|
||||
xaxis += 1.0f;
|
||||
if (xaxis > -1.0f && xaxis < 1.0f)
|
||||
xaxis = 0.0f;
|
||||
else
|
||||
xaxis = Ogre::Math::Sign(xaxis);
|
||||
input.motion.x = xaxis;
|
||||
if (active & 16)
|
||||
input.fast = true;
|
||||
else
|
||||
input.fast = false;
|
||||
if (input.control & 512) {
|
||||
if (input.mouse_moved) {
|
||||
updateCameraGoal(camera,
|
||||
-0.18f * input.mouse.x,
|
||||
-0.12f * input.mouse.y,
|
||||
0);
|
||||
input.mouse_moved = false;
|
||||
input.mouse.x = 0;
|
||||
input.mouse.y = 0;
|
||||
// move the camera smoothly to the goal
|
||||
Ogre::Vector3 goalOffset =
|
||||
camera.mCameraGoal
|
||||
->_getDerivedPosition() -
|
||||
camera.mCameraNode
|
||||
->getPosition();
|
||||
camera.mCameraNode->translate(
|
||||
goalOffset * eng.delta * 9.0f);
|
||||
camera.mCameraNode->_setDerivedOrientation(
|
||||
camera.mCameraGoal
|
||||
->_getDerivedOrientation());
|
||||
}
|
||||
if ((input.control & 0xf)) {
|
||||
Ogre::Vector3 forward =
|
||||
camera.mCameraPivot
|
||||
->_getDerivedOrientation() *
|
||||
Ogre::Vector3::UNIT_Z;
|
||||
Ogre::Vector3 side =
|
||||
camera.mCameraPivot
|
||||
->_getDerivedOrientation() *
|
||||
Ogre::Vector3::UNIT_X;
|
||||
forward.y = 0.0f;
|
||||
side.y = 0.0f;
|
||||
Ogre::Vector3 translation =
|
||||
forward * input.motion.z +
|
||||
side * input.motion.x;
|
||||
camera.mCameraPivot->translate(
|
||||
translation * 20.0f * eng.delta,
|
||||
Ogre::Node::TS_WORLD);
|
||||
}
|
||||
}
|
||||
input.control_prev = input.control;
|
||||
#if 0
|
||||
if (input.wheel_moved) {
|
||||
updateCameraGoal(camera, 0, 0,
|
||||
-0.15f * input.wheel_y);
|
||||
std::cout << "mouse moved: " << input.mouse_moved
|
||||
<< " " << std::endl;
|
||||
input.wheel_moved = false;
|
||||
input.wheel_y = 0;
|
||||
}
|
||||
#endif
|
||||
ECS::get().modified<ECS::Input>();
|
||||
});
|
||||
}
|
||||
}
|
||||
10
src/editor/EditorInputModule.h
Normal file
10
src/editor/EditorInputModule.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef _EDITOR_INPUT_MODULE_H_
|
||||
#define _EDITOR_INPUT_MODULE_H_
|
||||
#include <flecs.h>
|
||||
namespace ECS
|
||||
{
|
||||
struct EditorInputModule {
|
||||
EditorInputModule(flecs::world &ecs);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
791
src/editor/main.cpp
Normal file
791
src/editor/main.cpp
Normal file
@@ -0,0 +1,791 @@
|
||||
#include <flecs.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <Ogre.h>
|
||||
#include <OgreApplicationContext.h>
|
||||
#include <OgreOverlaySystem.h>
|
||||
#include <OgreOverlayManager.h>
|
||||
#include <OgreImGuiOverlay.h>
|
||||
#include <OgreImGuiInputListener.h>
|
||||
#include <OgreTrays.h>
|
||||
#include <OgreTimer.h>
|
||||
#include <OgreMeshLodGenerator.h>
|
||||
|
||||
// #include "water/water.h"
|
||||
#include "GameData.h"
|
||||
#include "Components.h"
|
||||
#include "CharacterModule.h"
|
||||
#include "TerrainModule.h"
|
||||
#include "GUIModule.h"
|
||||
#include "AppModule.h"
|
||||
#include "EditorGizmoModule.h"
|
||||
#include "EditorInputModule.h"
|
||||
#include "sound.h"
|
||||
|
||||
class App;
|
||||
class SkyRenderer : public Ogre::SceneManager::Listener {
|
||||
protected:
|
||||
Ogre::SceneManager *mSceneManager;
|
||||
virtual void _updateRenderQueue(Ogre::RenderQueue *queue) = 0;
|
||||
|
||||
public:
|
||||
enum BoxPlane {
|
||||
BP_FRONT = 0,
|
||||
BP_BACK = 1,
|
||||
BP_LEFT = 2,
|
||||
BP_RIGHT = 3,
|
||||
BP_UP = 4,
|
||||
BP_DOWN = 5
|
||||
};
|
||||
|
||||
SkyRenderer(Ogre::SceneManager *owner)
|
||||
: mSceneManager(owner)
|
||||
, mSceneNode(0)
|
||||
, mEnabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~SkyRenderer()
|
||||
{
|
||||
setEnabled(false);
|
||||
if (mSceneNode)
|
||||
mSceneManager->destroySceneNode(mSceneNode);
|
||||
}
|
||||
|
||||
Ogre::SceneNode *mSceneNode;
|
||||
bool mEnabled;
|
||||
|
||||
void setEnabled(bool enable)
|
||||
{
|
||||
if (enable == mEnabled)
|
||||
return;
|
||||
mEnabled = enable;
|
||||
enable ? mSceneManager->addListener(this) :
|
||||
mSceneManager->removeListener(this);
|
||||
}
|
||||
void
|
||||
postFindVisibleObjects(Ogre::SceneManager *source,
|
||||
Ogre::SceneManager::IlluminationRenderStage irs,
|
||||
Ogre::Viewport *vp) override
|
||||
{
|
||||
// Queue skies, if viewport seems it
|
||||
if (!vp->getSkiesEnabled() ||
|
||||
irs == Ogre::SceneManager::IRS_RENDER_TO_TEXTURE)
|
||||
return;
|
||||
|
||||
if (!mEnabled || !mSceneNode)
|
||||
return;
|
||||
|
||||
// Update nodes
|
||||
// Translate the box by the camera position (constant distance)
|
||||
mSceneNode->setPosition(vp->getCamera()->getDerivedPosition());
|
||||
_updateRenderQueue(source->getRenderQueue());
|
||||
}
|
||||
};
|
||||
class SkyBoxRenderer : public SkyRenderer {
|
||||
std::unique_ptr<Ogre::ManualObject> mSkyBoxObj;
|
||||
|
||||
Ogre::Quaternion mSkyBoxOrientation;
|
||||
void _updateRenderQueue(Ogre::RenderQueue *queue) override
|
||||
{
|
||||
if (mSkyBoxObj->isVisible()) {
|
||||
mSkyBoxObj->_updateRenderQueue(queue);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
SkyBoxRenderer(Ogre::SceneManager *owner)
|
||||
: SkyRenderer(owner)
|
||||
{
|
||||
}
|
||||
Ogre::SceneManager::SkyBoxGenParameters mSkyBoxGenParameters;
|
||||
void create(const Ogre::String &materialName, Ogre::Real distance,
|
||||
uint8_t renderQueue, const Ogre::Quaternion &orientation,
|
||||
const Ogre::String &groupName)
|
||||
{
|
||||
Ogre::MaterialPtr m =
|
||||
Ogre::MaterialManager::getSingleton().getByName(
|
||||
materialName, groupName);
|
||||
OgreAssert(m, "Sky box material '" + materialName +
|
||||
"' not found.");
|
||||
// Ensure loaded
|
||||
m->load();
|
||||
|
||||
bool valid = m->getBestTechnique() &&
|
||||
m->getBestTechnique()->getNumPasses();
|
||||
OgreAssert(valid, "Bad material" + materialName);
|
||||
|
||||
// Create node
|
||||
mSceneNode = mSceneManager->createSceneNode();
|
||||
|
||||
// Create object
|
||||
mSkyBoxObj = std::make_unique<Ogre::ManualObject>("SkyBox");
|
||||
mSkyBoxObj->setCastShadows(false);
|
||||
mSceneNode->attachObject(mSkyBoxObj.get());
|
||||
|
||||
mSkyBoxObj->setRenderQueueGroup(renderQueue);
|
||||
mSkyBoxObj->begin(materialName,
|
||||
Ogre::RenderOperation::OT_TRIANGLE_STRIP,
|
||||
groupName);
|
||||
|
||||
// rendering cube, only using 14 vertices
|
||||
const Ogre::Vector3 cube_strip[14] = {
|
||||
{ -1.f, 1.f, 1.f }, // Front-top-left
|
||||
{ 1.f, 1.f, 1.f }, // Front-top-right
|
||||
{ -1.f, -1.f, 1.f }, // Front-bottom-left
|
||||
{ 1.f, -1.f, 1.f }, // Front-bottom-right
|
||||
{ 1.f, -1.f, -1.f }, // Back-bottom-right
|
||||
{ 1.f, 1.f, 1.f }, // Front-top-right
|
||||
{ 1.f, 1.f, -1.f }, // Back-top-right
|
||||
{ -1.f, 1.f, 1.f }, // Front-top-left
|
||||
{ -1.f, 1.f, -1.f }, // Back-top-left
|
||||
{ -1.f, -1.f, 1.f }, // Front-bottom-left
|
||||
{ -1.f, -1.f, -1.f }, // Back-bottom-left
|
||||
{ 1.f, -1.f, -1.f }, // Back-bottom-right
|
||||
{ -1.f, 1.f, -1.f }, // Back-top-left
|
||||
{ 1.f, 1.f, -1.f } // Back-top-right
|
||||
};
|
||||
|
||||
for (const auto &vtx : cube_strip) {
|
||||
mSkyBoxObj->position(orientation * (vtx * distance));
|
||||
// Note UVs mirrored front/back
|
||||
mSkyBoxObj->textureCoord(vtx.normalisedCopy() *
|
||||
Ogre::Vector3(1, 1, -1));
|
||||
}
|
||||
|
||||
mSkyBoxObj->end();
|
||||
mSkyBoxGenParameters.skyBoxDistance = distance;
|
||||
}
|
||||
};
|
||||
class App;
|
||||
class KeyboardListener : public OgreBites::InputListener {
|
||||
App *mApp;
|
||||
|
||||
uint32_t control;
|
||||
ECS::Vector2 mouse;
|
||||
float wheel_y;
|
||||
bool mouse_moved, wheel_moved;
|
||||
float mInitDelay;
|
||||
|
||||
public:
|
||||
Ogre::Timer fps_timer;
|
||||
bool fast;
|
||||
KeyboardListener(App *app)
|
||||
: OgreBites::InputListener()
|
||||
, mApp(app)
|
||||
, fast(false)
|
||||
, control(0)
|
||||
, mouse({ 0, 0 })
|
||||
, wheel_y(0.0f)
|
||||
, mouse_moved(false)
|
||||
, wheel_moved(false)
|
||||
, mInitDelay(1.0)
|
||||
{
|
||||
}
|
||||
bool isGuiEnabled()
|
||||
{
|
||||
if (!ECS::get().has<ECS::GUI>())
|
||||
return false;
|
||||
return (ECS::get().get<ECS::GUI>().enabled);
|
||||
}
|
||||
void setGuiEnabled(bool value)
|
||||
{
|
||||
if (!ECS::get().has<ECS::GUI>())
|
||||
return;
|
||||
ECS::get().get_mut<ECS::GUI>().enabled = value;
|
||||
ECS::get().modified<ECS::GUI>();
|
||||
}
|
||||
bool keyPressed(const OgreBites::KeyboardEvent &evt) override
|
||||
{
|
||||
bool updated = false;
|
||||
#if 0
|
||||
if (isGuiEnabled())
|
||||
return false;
|
||||
if (evt.keysym.sym == OgreBites::SDLK_ESCAPE) {
|
||||
OgreAssert(ECS::get().has<ECS::GUI>(), "");
|
||||
setGuiEnabled(true);
|
||||
if (ECS::get().has<ECS::GUI>())
|
||||
ECS::get<ECS::GUI>().setWindowGrab(false);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
OgreBites::Keycode key = evt.keysym.sym;
|
||||
if (key == 'w')
|
||||
control |= 1;
|
||||
else if (key == 'a')
|
||||
control |= 2;
|
||||
else if (key == 's')
|
||||
control |= 4;
|
||||
else if (key == 'd')
|
||||
control |= 8;
|
||||
else if (key == OgreBites::SDLK_LSHIFT)
|
||||
control |= 16;
|
||||
else if (key == 'e')
|
||||
control |= 32;
|
||||
else if (key == 'f')
|
||||
control |= 64;
|
||||
if (key == 'w' || key == 'a' || key == 's' || key == 'd' ||
|
||||
key == 'e' || key == OgreBites::SDLK_LSHIFT)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool keyReleased(const OgreBites::KeyboardEvent &evt) override
|
||||
{
|
||||
OgreBites::Keycode key = evt.keysym.sym;
|
||||
#if 0
|
||||
if (isGuiEnabled())
|
||||
return false;
|
||||
#endif
|
||||
if (key == 'w')
|
||||
control &= ~1;
|
||||
else if (key == 'a')
|
||||
control &= ~2;
|
||||
else if (key == 's')
|
||||
control &= ~4;
|
||||
else if (key == 'd')
|
||||
control &= ~8;
|
||||
else if (key == OgreBites::SDLK_LSHIFT)
|
||||
control &= ~16;
|
||||
if (key == 'w' || key == 'a' || key == 's' || key == 'd' ||
|
||||
key == OgreBites::SDLK_LSHIFT)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool mouseMoved(const OgreBites::MouseMotionEvent &evt) override
|
||||
{
|
||||
mouse.x = evt.xrel;
|
||||
mouse.y = evt.yrel;
|
||||
mouse_moved = true;
|
||||
/* no special mouse handling */
|
||||
return true;
|
||||
}
|
||||
bool mouseWheelRolled(const OgreBites::MouseWheelEvent &evt) override
|
||||
{
|
||||
/* no special mouse wheel handling */
|
||||
wheel_y = evt.y;
|
||||
wheel_moved = true;
|
||||
return true;
|
||||
}
|
||||
bool mousePressed(const OgreBites::MouseButtonEvent &evt) override
|
||||
{
|
||||
std::cout << "Mouse press " << (int)evt.button << " "
|
||||
<< (int)evt.clicks << "\n";
|
||||
if ((int)evt.button == 1)
|
||||
control |= 256;
|
||||
else
|
||||
control &= ~256;
|
||||
if ((int)evt.button == 3)
|
||||
control |= 512;
|
||||
else
|
||||
control &= ~512;
|
||||
return false;
|
||||
}
|
||||
bool mouseReleased(const OgreBites::MouseButtonEvent &evt) override
|
||||
{
|
||||
std::cout << "Mouse release " << (int)evt.button << " "
|
||||
<< (int)evt.clicks << "\n";
|
||||
if ((int)evt.button == 1)
|
||||
control &= ~256;
|
||||
if ((int)evt.button == 3)
|
||||
control &= ~512;
|
||||
return false;
|
||||
}
|
||||
void frameRendered(const Ogre::FrameEvent &evt) override;
|
||||
};
|
||||
|
||||
class App : public OgreBites::ApplicationContext {
|
||||
Ogre::SceneNode *mCameraNode, *mCameraPivot, *mCameraGoal;
|
||||
Ogre::Camera *mCamera;
|
||||
Ogre::Real mPivotPitch;
|
||||
Ogre::SceneManager *mScnMgr;
|
||||
Ogre::Viewport *mViewport;
|
||||
SkyBoxRenderer *sky;
|
||||
bool mGrab;
|
||||
KeyboardListener mKbd;
|
||||
|
||||
public:
|
||||
App()
|
||||
: OgreBites::ApplicationContext("ChoroGame")
|
||||
, mKbd(this)
|
||||
, mGrab(false)
|
||||
{
|
||||
}
|
||||
virtual ~App()
|
||||
{
|
||||
}
|
||||
void setup()
|
||||
{
|
||||
OgreBites::ApplicationContext::setup();
|
||||
Ogre::Root *root = getRoot();
|
||||
Ogre::SceneManager *scnMgr = root->createSceneManager();
|
||||
mScnMgr = scnMgr;
|
||||
Ogre::OverlaySystem *pOverlaySystem = getOverlaySystem();
|
||||
mScnMgr->addRenderQueueListener(pOverlaySystem);
|
||||
// mTrayMgr = new OgreBites::TrayManager("AppTrays",
|
||||
// getRenderWindow());
|
||||
}
|
||||
bool isWindowGrab()
|
||||
{
|
||||
return mGrab;
|
||||
}
|
||||
void locateResources() override
|
||||
{
|
||||
Ogre::ResourceGroupManager::getSingleton().createResourceGroup(
|
||||
"Water", true);
|
||||
Ogre::ResourceGroupManager::getSingleton().createResourceGroup(
|
||||
"LuaScripts", false);
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
"./lua-scripts", "FileSystem", "LuaScripts", true,
|
||||
true);
|
||||
OgreBites::ApplicationContext::locateResources();
|
||||
}
|
||||
void loadResources() override
|
||||
{
|
||||
}
|
||||
void setWindowGrab(bool grab = true)
|
||||
{
|
||||
mGrab = grab;
|
||||
ApplicationContextBase::setWindowGrab(grab);
|
||||
}
|
||||
|
||||
void initCamera()
|
||||
{
|
||||
mCameraNode = mScnMgr->getRootSceneNode()->createChildSceneNode(
|
||||
"CameraNode");
|
||||
mCameraNode->setPosition(0, 2, 3);
|
||||
mCameraNode->lookAt(Ogre::Vector3(0, 1, -1),
|
||||
Ogre::Node::TS_PARENT);
|
||||
|
||||
// create the camera
|
||||
mCamera = mScnMgr->createCamera("fps_camera");
|
||||
mCamera->setNearClipDistance(0.05f);
|
||||
mCamera->setAutoAspectRatio(true);
|
||||
mCameraNode->attachObject(mCamera);
|
||||
|
||||
// and tell it to render into the main window
|
||||
mViewport = getRenderWindow()->addViewport(mCamera);
|
||||
mCameraPivot =
|
||||
mScnMgr->getRootSceneNode()->createChildSceneNode(
|
||||
"FPSCameraPivot");
|
||||
mCameraGoal = mCameraPivot->createChildSceneNode(
|
||||
"FPSCameraGoal", Ogre::Vector3(0, 2, 3));
|
||||
mCameraNode->setPosition(mCameraPivot->getPosition() +
|
||||
mCameraGoal->getPosition());
|
||||
mCameraPivot->setFixedYawAxis(true);
|
||||
mCameraGoal->setFixedYawAxis(true);
|
||||
mCameraNode->setFixedYawAxis(true);
|
||||
// our model is quite small, so reduce the clipping planes
|
||||
mCamera->setNearClipDistance(0.1f);
|
||||
mCamera->setFarClipDistance(800);
|
||||
mPivotPitch = 0;
|
||||
}
|
||||
void configure()
|
||||
{
|
||||
std::cout << "Startup" << "\n";
|
||||
initApp();
|
||||
std::cout << "Set up RTSS" << "\n";
|
||||
Ogre::Root *root = getRoot();
|
||||
Ogre::SceneManager *scnMgr = getSceneManager();
|
||||
|
||||
// register our scene with the RTSS
|
||||
Ogre::RTShader::ShaderGenerator *shadergen =
|
||||
Ogre::RTShader::ShaderGenerator::getSingletonPtr();
|
||||
shadergen->addSceneManager(scnMgr);
|
||||
setWindowGrab(false);
|
||||
std::cout << "Init camera" << "\n";
|
||||
initCamera();
|
||||
std::cout << "Set up water" << "\n";
|
||||
std::cout << "Set up cursor" << "\n";
|
||||
Ogre::ResourceGroupManager::getSingleton()
|
||||
.initialiseAllResourceGroups();
|
||||
// OgreBites::ApplicationContext::loadResources();
|
||||
// setupCursor();
|
||||
std::cout << "Setup input" << "\n";
|
||||
setupInput();
|
||||
std::cout << "Create content" << "\n";
|
||||
createContent();
|
||||
std::cout << "Setup done" << "\n";
|
||||
#if 0
|
||||
mDbgDraw->setDebugMode(mDbgDraw->getDebugMode() |
|
||||
btIDebugDraw::DBG_DrawContactPoints);
|
||||
#endif
|
||||
}
|
||||
Ogre::SceneManager *getSceneManager()
|
||||
{
|
||||
return mScnMgr;
|
||||
}
|
||||
Ogre::Timer mTerrainUpd;
|
||||
// TODO: implement rough water level calculation
|
||||
float getWaterLevel(const Ogre::Vector3 &position)
|
||||
{
|
||||
Ogre::Vector3::UNIT_Y;
|
||||
float etime =
|
||||
Ogre::ControllerManager::getSingleton().getElapsedTime();
|
||||
return 0.0f;
|
||||
}
|
||||
void updateWorld(float delta)
|
||||
{
|
||||
if (!ECS::get().has<ECS::GUI>())
|
||||
return;
|
||||
/* Update window grab */
|
||||
ECS::GUI &gui = ECS::get().get_mut<ECS::GUI>();
|
||||
if (gui.grabChanged) {
|
||||
gui.grab = false;
|
||||
setWindowGrab(gui.grab);
|
||||
gui.grabChanged = false;
|
||||
ECS::get().modified<ECS::GUI>();
|
||||
}
|
||||
ECS::update(delta);
|
||||
}
|
||||
class InputListenerChainFlexible : public OgreBites::InputListener {
|
||||
protected:
|
||||
std::vector<OgreBites::InputListener *> mListenerChain;
|
||||
|
||||
public:
|
||||
InputListenerChainFlexible()
|
||||
{
|
||||
}
|
||||
InputListenerChainFlexible(std::vector<InputListener *> chain)
|
||||
: mListenerChain(chain)
|
||||
{
|
||||
}
|
||||
|
||||
void add(OgreBites::InputListener *listener)
|
||||
{
|
||||
mListenerChain.push_back(listener);
|
||||
}
|
||||
void erase(OgreBites::InputListener *listener)
|
||||
{
|
||||
mListenerChain.erase(std::find(mListenerChain.begin(),
|
||||
mListenerChain.end(),
|
||||
listener));
|
||||
}
|
||||
bool empty() const
|
||||
{
|
||||
return mListenerChain.empty();
|
||||
}
|
||||
|
||||
InputListenerChainFlexible &
|
||||
operator=(const InputListenerChainFlexible &o)
|
||||
{
|
||||
mListenerChain = o.mListenerChain;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void frameRendered(const Ogre::FrameEvent &evt) override
|
||||
{
|
||||
for (auto listener : mListenerChain)
|
||||
listener->frameRendered(evt);
|
||||
}
|
||||
|
||||
bool keyPressed(const OgreBites::KeyboardEvent &evt) override
|
||||
{
|
||||
for (auto listner : mListenerChain) {
|
||||
if (listner->keyPressed(evt))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool keyReleased(const OgreBites::KeyboardEvent &evt) override
|
||||
{
|
||||
for (auto listner : mListenerChain) {
|
||||
if (listner->keyReleased(evt))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool touchMoved(const OgreBites::TouchFingerEvent &evt) override
|
||||
{
|
||||
for (auto listner : mListenerChain) {
|
||||
if (listner->touchMoved(evt))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool
|
||||
touchPressed(const OgreBites::TouchFingerEvent &evt) override
|
||||
{
|
||||
for (auto listner : mListenerChain) {
|
||||
if (listner->touchPressed(evt))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool
|
||||
touchReleased(const OgreBites::TouchFingerEvent &evt) override
|
||||
{
|
||||
for (auto listner : mListenerChain) {
|
||||
if (listner->touchReleased(evt))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool mouseMoved(const OgreBites::MouseMotionEvent &evt) override
|
||||
{
|
||||
for (auto listner : mListenerChain) {
|
||||
if (listner->mouseMoved(evt))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool
|
||||
mouseWheelRolled(const OgreBites::MouseWheelEvent &evt) override
|
||||
{
|
||||
for (auto listner : mListenerChain) {
|
||||
if (listner->mouseWheelRolled(evt))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool
|
||||
mousePressed(const OgreBites::MouseButtonEvent &evt) override
|
||||
{
|
||||
for (auto listner : mListenerChain) {
|
||||
if (listner->mousePressed(evt))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool
|
||||
mouseReleased(const OgreBites::MouseButtonEvent &evt) override
|
||||
{
|
||||
for (auto listner : mListenerChain) {
|
||||
if (listner->mouseReleased(evt))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool textInput(const OgreBites::TextInputEvent &evt) override
|
||||
{
|
||||
for (auto listner : mListenerChain) {
|
||||
if (listner->textInput(evt))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
flecs::entity input_update;
|
||||
flecs::entity find_wait_gui;
|
||||
void setupInput()
|
||||
{
|
||||
}
|
||||
void createContent()
|
||||
{
|
||||
int i;
|
||||
sky = new SkyBoxRenderer(getSceneManager());
|
||||
bool drawFirst = true;
|
||||
uint8_t renderQueue = drawFirst ?
|
||||
Ogre::RENDER_QUEUE_SKIES_EARLY :
|
||||
Ogre::RENDER_QUEUE_SKIES_LATE;
|
||||
sky->create("Skybox/Dynamic", 450, renderQueue,
|
||||
Ogre::Quaternion::IDENTITY,
|
||||
Ogre::ResourceGroupManager::
|
||||
AUTODETECT_RESOURCE_GROUP_NAME);
|
||||
sky->setEnabled(true);
|
||||
|
||||
Ogre::MaterialPtr m =
|
||||
Ogre::MaterialManager::getSingleton().getByName(
|
||||
"Skybox/Dynamic", "General");
|
||||
OgreAssert(m, "Sky box material not found.");
|
||||
m->load();
|
||||
ECS::setupEditor(mScnMgr, /*mDynWorld.get(), */ mCameraNode,
|
||||
mCamera, getRenderWindow());
|
||||
ECS::get().import <ECS::EditorGizmoModule>();
|
||||
ECS::get().import <ECS::EditorInputModule>();
|
||||
ECS::get().set<ECS::RenderWindow>(
|
||||
{ getRenderWindow(), getDisplayDPI() });
|
||||
ECS::get()
|
||||
.observer<ECS::GUI>("UpdateGrab")
|
||||
.event(flecs::OnSet)
|
||||
.each([this](ECS::GUI &gui) {
|
||||
if (gui.grabChanged)
|
||||
setWindowGrab(gui.grab);
|
||||
std::cout << "grab: " << gui.grab << "\n";
|
||||
std::cout << "GUI enabled: " << gui.enabled
|
||||
<< "\n";
|
||||
});
|
||||
ECS::get()
|
||||
.observer<ECS::App>("UpdateInputListener")
|
||||
.event(flecs::OnSet)
|
||||
.each([this](ECS::App &app) {
|
||||
if (app.mInput)
|
||||
removeInputListener(app.mInput);
|
||||
delete app.mInput;
|
||||
app.mInput =
|
||||
OGRE_NEW OgreBites::InputListenerChain(
|
||||
app.listeners);
|
||||
addInputListener(app.mInput);
|
||||
});
|
||||
ECS::get().set<ECS::App>(
|
||||
{ initialiseImGui(),
|
||||
nullptr,
|
||||
{ getImGuiInputListener(), &mKbd } });
|
||||
ECS::get().add<ECS::EditorDebugMaterial>();
|
||||
std::shared_ptr<Ogre::ManualObject> manualObj(
|
||||
mScnMgr->createManualObject("EditorGizmo"));
|
||||
Ogre::SceneNode *gizmoNode =
|
||||
mScnMgr->getRootSceneNode()->createChildSceneNode(
|
||||
"EditorGizmoNode");
|
||||
gizmoNode->attachObject(manualObj.get());
|
||||
ECS::get().set<ECS::EditorGizmo>({ manualObj, gizmoNode });
|
||||
#if 0
|
||||
ECS::get()
|
||||
.system<const ECS::EngineData, ECS::Camera,
|
||||
const ECS::Input>("UpdateEditorCamera")
|
||||
.kind(flecs::OnUpdate)
|
||||
.each([&](const ECS::EngineData &eng,
|
||||
ECS::Camera &camera,
|
||||
const ECS::Input &input) {
|
||||
if (!camera.configured) {
|
||||
// create a pivot at roughly the character's shoulder
|
||||
camera.mCameraPivot =
|
||||
eng.mScnMgr->getRootSceneNode()
|
||||
->createChildSceneNode();
|
||||
camera.mCameraGoal =
|
||||
camera.mCameraPivot
|
||||
->createChildSceneNode(
|
||||
Ogre::Vector3(
|
||||
0, 2,
|
||||
0));
|
||||
camera.mCameraNode->setPosition(
|
||||
camera.mCameraPivot
|
||||
->getPosition() +
|
||||
camera.mCameraGoal
|
||||
->getPosition());
|
||||
camera.mCameraGoal->lookAt(
|
||||
Ogre::Vector3(0, 0, -10),
|
||||
Ogre::Node::TS_PARENT);
|
||||
camera.mCameraPivot->setFixedYawAxis(
|
||||
true);
|
||||
camera.mCameraGoal->setFixedYawAxis(
|
||||
true);
|
||||
camera.mCameraNode->setFixedYawAxis(
|
||||
true);
|
||||
// our model is quite small, so reduce the clipping planes
|
||||
camera.mCamera->setNearClipDistance(
|
||||
0.1f);
|
||||
camera.mCamera->setFarClipDistance(700);
|
||||
|
||||
camera.mPivotPitch = 0;
|
||||
camera.configured = true;
|
||||
} else {
|
||||
// place the camera pivot roughly at the character's shoulder
|
||||
#if 0
|
||||
camera.mCameraPivot->setPosition(
|
||||
ch.mBodyNode->getPosition() +
|
||||
Ogre::Vector3::UNIT_Y * CAM_HEIGHT);
|
||||
#endif
|
||||
// move the camera smoothly to the goal
|
||||
Ogre::Vector3 goalOffset =
|
||||
camera.mCameraGoal
|
||||
->_getDerivedPosition() -
|
||||
camera.mCameraNode
|
||||
->getPosition();
|
||||
camera.mCameraNode->translate(
|
||||
goalOffset * eng.delta * 9.0f);
|
||||
// always look at the pivot
|
||||
#if 0
|
||||
camera.mCameraNode->lookAt(
|
||||
camera.mCameraPivot
|
||||
->_getDerivedPosition(),
|
||||
Ogre::Node::TS_PARENT);
|
||||
#endif
|
||||
camera.mCameraNode->_setDerivedOrientation(
|
||||
camera.mCameraGoal
|
||||
->_getDerivedOrientation());
|
||||
}
|
||||
if (input.control & 512 && input.mouse_moved) {
|
||||
mCameraPivot->yaw(
|
||||
Ogre::Radian(-input.mouse.x *
|
||||
3.0f * eng.delta));
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
bool get_gui_active()
|
||||
{
|
||||
return ECS::get().get<ECS::GUI>().enabled;
|
||||
}
|
||||
void set_gui_active(bool active)
|
||||
{
|
||||
ECS::get().get_mut<ECS::GUI>().enabled = active;
|
||||
ECS::get().modified<ECS::GUI>();
|
||||
}
|
||||
Ogre::Camera *getCamera()
|
||||
{
|
||||
return mCamera;
|
||||
}
|
||||
flecs::entity getPlayer() const
|
||||
{
|
||||
flecs::entity player =
|
||||
ECS::get().lookup("ECS::CharacterModule::player");
|
||||
return player;
|
||||
}
|
||||
void enableDbgDraw(bool enable)
|
||||
{
|
||||
ECS::get_mut<ECS::EngineData>().enableDbgDraw = enable;
|
||||
ECS::modified<ECS::EngineData>();
|
||||
}
|
||||
bool isEnabledDbgDraw() const
|
||||
{
|
||||
return ECS::get<ECS::EngineData>().enableDbgDraw;
|
||||
}
|
||||
};
|
||||
void KeyboardListener::frameRendered(const Ogre::FrameEvent &evt)
|
||||
{
|
||||
if (fps_timer.getMilliseconds() > 1000.0f) {
|
||||
std::cout << "FPS: "
|
||||
<< mApp->getRenderWindow()->getStatistics().lastFPS
|
||||
<< " ";
|
||||
std::cout << "Draw calls: "
|
||||
<< mApp->getRenderWindow()->getStatistics().batchCount
|
||||
<< " ";
|
||||
fps_timer.reset();
|
||||
std::cout << "Drops: "
|
||||
<< mApp->getRenderWindow()
|
||||
->getStatistics()
|
||||
.vBlankMissCount
|
||||
<< "\n";
|
||||
fps_timer.reset();
|
||||
}
|
||||
/* for editor we always update world */
|
||||
/* TODO: implement pause */
|
||||
mApp->updateWorld(evt.timeSinceLastFrame);
|
||||
if (mInitDelay >= 0.0f)
|
||||
mInitDelay -= evt.timeSinceLastFrame;
|
||||
|
||||
if (!isGuiEnabled() && ECS::get().has<ECS::Input>()) {
|
||||
ECS::Input &input = ECS::get().get_mut<ECS::Input>();
|
||||
input.control = control;
|
||||
input.mouse = mouse;
|
||||
mouse.x = 0;
|
||||
mouse.y = 0;
|
||||
input.wheel_y = wheel_y;
|
||||
wheel_y = 0;
|
||||
input.mouse_moved = mouse_moved;
|
||||
input.wheel_moved = wheel_moved;
|
||||
ECS::modified<ECS::Input>();
|
||||
} else {
|
||||
ECS::Input &input = ECS::get().get_mut<ECS::Input>();
|
||||
input.control = control;
|
||||
input.mouse = mouse;
|
||||
mouse.x = 0;
|
||||
mouse.y = 0;
|
||||
input.wheel_y = wheel_y;
|
||||
wheel_y = 0;
|
||||
input.mouse_moved = mouse_moved;
|
||||
input.wheel_moved = wheel_moved;
|
||||
ECS::modified<ECS::Input>();
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
App ctx;
|
||||
ctx.configure();
|
||||
ctx.enableDbgDraw(false);
|
||||
ctx.getRoot()->startRendering();
|
||||
ctx.setWindowGrab(false);
|
||||
ctx.closeApp();
|
||||
return 0;
|
||||
}
|
||||
@@ -41,6 +41,8 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
ecs.system<Input, Camera>("HandleInput")
|
||||
.kind(flecs::OnUpdate)
|
||||
.each([this](Input &input, Camera &camera) {
|
||||
if (!ECS::player.is_valid())
|
||||
return;
|
||||
/* handle input */
|
||||
// if (input.control == input.control_prev)
|
||||
// return;
|
||||
|
||||
@@ -8,10 +8,12 @@
|
||||
#include <OgreApplicationContext.h>
|
||||
#include <OgreImGuiInputListener.h>
|
||||
#include <OgreFontManager.h>
|
||||
#include <OgreTerrainGroup.h>
|
||||
#include "GameData.h"
|
||||
#include "Components.h"
|
||||
#include "LuaData.h"
|
||||
#include "AppModule.h"
|
||||
#include "TerrainModule.h"
|
||||
#include "GUIModule.h"
|
||||
namespace ECS
|
||||
{
|
||||
@@ -472,6 +474,9 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
|
||||
bool enableMapEditor;
|
||||
ImFont *smallFont, *midFont, *bigFont;
|
||||
Ogre::FontPtr _smallFont, _midFont, _bigFont;
|
||||
Ogre::TexturePtr worldMap;
|
||||
Ogre::Image worldMapImage;
|
||||
|
||||
EditorGUIListener(Ogre::ImGuiOverlay *overlay)
|
||||
: Ogre::RenderTargetListener()
|
||||
{
|
||||
@@ -488,13 +493,47 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
|
||||
OgreAssert(midFont, "Could not load font");
|
||||
bigFont = overlay->addFont("bigFont", "General");
|
||||
OgreAssert(bigFont, "Could not load font");
|
||||
worldMapImage.load(
|
||||
"world_map.png",
|
||||
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||
#if 0
|
||||
Ogre::FontPtr _midFont = createFont("midFont", "General",
|
||||
"Kenney Bold.ttf", 28.0f);
|
||||
#endif
|
||||
#if 0
|
||||
ImGui::GetIO().Fonts->Build();
|
||||
int x, y, i, j;
|
||||
for (y = 0; y < worldMapImage.getWidth(); y++)
|
||||
for (x = 0; x < worldMapImage.getWidth(); x++) {
|
||||
float r = 0.0f;
|
||||
for (i = -2; i < 3; i++)
|
||||
for (j = -2; j < 3; j++) {
|
||||
int xj = Ogre::Math::Clamp(
|
||||
x + j, 0,
|
||||
(int)worldMapImage
|
||||
.getWidth() -
|
||||
1);
|
||||
int yi = Ogre::Math::Clamp(
|
||||
y + i, 0,
|
||||
(int)worldMapImage
|
||||
.getHeight() -
|
||||
1);
|
||||
r += worldMapImage
|
||||
.getColourAt(xj,
|
||||
yi, 0)
|
||||
.r;
|
||||
}
|
||||
r /= 25.0f;
|
||||
Ogre::ColourValue cv =
|
||||
worldMapImage.getColourAt(x, y, 0);
|
||||
cv.r = r;
|
||||
worldMapImage.setColourAt(cv, x, y, 0);
|
||||
}
|
||||
#endif
|
||||
worldMap = Ogre::TextureManager::getSingleton().createManual(
|
||||
"worldMap",
|
||||
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
Ogre::TEX_TYPE_2D, worldMapImage.getWidth(),
|
||||
worldMapImage.getHeight(),
|
||||
worldMapImage.getNumMipmaps(),
|
||||
worldMapImage.getFormat(), Ogre::TU_DYNAMIC_WRITE_ONLY);
|
||||
worldMap->loadImage(worldMapImage);
|
||||
OgreAssert(worldMap, "could not load world map");
|
||||
}
|
||||
Ogre::FontPtr createFont(const Ogre::String &name,
|
||||
const Ogre::String &group,
|
||||
@@ -533,6 +572,7 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
|
||||
Ogre::Root::getSingleton().queueEndRendering();
|
||||
if (ImGui::Button("Return"))
|
||||
ECS::get().get<GUI>().finish();
|
||||
#if 0
|
||||
if (ImGui::Button("Enable/Disable item editor")) {
|
||||
enableEditor ^= true;
|
||||
if (enableEditor)
|
||||
@@ -544,6 +584,8 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
|
||||
enableEditor = false;
|
||||
}
|
||||
ImGui::Text("Text message...");
|
||||
#endif
|
||||
ImGui::Checkbox("Enable Map", &enableMapEditor);
|
||||
ImGui::End();
|
||||
}
|
||||
void create_entity_node(const Ogre::String &name, int key)
|
||||
@@ -573,6 +615,7 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
|
||||
|
||||
ECS::get().get<GUI>().finish();
|
||||
}
|
||||
#if 0
|
||||
void buildings_editor()
|
||||
{
|
||||
int i;
|
||||
@@ -602,6 +645,7 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
#endif
|
||||
void position_editor(Ogre::SceneNode *node)
|
||||
{
|
||||
Ogre::Vector3 position = node->getPosition();
|
||||
@@ -642,124 +686,561 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
|
||||
ImGui::Text("Name: %s", pname.c_str());
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
void map_editor()
|
||||
{
|
||||
}
|
||||
void preview(const Ogre::RenderTargetViewportEvent &evt)
|
||||
#endif
|
||||
int pos_x = 0;
|
||||
int pos_y = 0;
|
||||
int top_x = 0;
|
||||
int top_y = 0;
|
||||
int selected_x = 0;
|
||||
int selected_y = 0;
|
||||
bool locationSelected = false;
|
||||
float strength = 0.0f;
|
||||
int size = 0;
|
||||
void updateWorldTexture()
|
||||
{
|
||||
int i;
|
||||
Ogre::ImGuiOverlay::NewFrame();
|
||||
std::cout << "GUI enabled: " << ECS::get().get<GUI>().enabled
|
||||
<< std::endl;
|
||||
if (ECS::get().get<GUI>().enabled) {
|
||||
buttons_panel();
|
||||
buildings_editor();
|
||||
map_editor();
|
||||
ImVec2 size = ImGui::GetMainViewport()->Size;
|
||||
float window_width = size.x * 0.2f;
|
||||
if (window_width > panel_width)
|
||||
window_width = panel_width;
|
||||
float window_height = size.y * 0.5f - 20;
|
||||
ImGui::SetNextWindowPos(ImVec2(size.x - window_width,
|
||||
size.y * 0.5f + 20),
|
||||
ImGuiCond_Always);
|
||||
ImGui::SetNextWindowSize(ImVec2(window_width,
|
||||
window_height),
|
||||
ImGuiCond_Always);
|
||||
// ImGui::Begin("Dumb and Stupid", &mKbd.gui_active);
|
||||
ImGui::Begin("Panel...");
|
||||
std::deque<Ogre::SceneNode *> tree_input_queue,
|
||||
tree_output_queue;
|
||||
std::vector<Ogre::SceneNode *> tree_list;
|
||||
tree_input_queue.push_back(
|
||||
ECS::get()
|
||||
.get<EngineData>()
|
||||
.mScnMgr->getRootSceneNode());
|
||||
tree_input_queue.push_back(nullptr);
|
||||
std::set<Ogre::SceneNode *> visited;
|
||||
while (true) {
|
||||
int new_nodes_count = 0;
|
||||
while (!tree_input_queue.empty()) {
|
||||
int child;
|
||||
Ogre::SceneNode *item =
|
||||
tree_input_queue.front();
|
||||
tree_input_queue.pop_front();
|
||||
if (item &&
|
||||
visited.find(item) ==
|
||||
visited.end()) { // new node
|
||||
new_nodes_count++;
|
||||
tree_output_queue.push_back(
|
||||
item);
|
||||
visited.insert(item);
|
||||
const Ogre::Node::ChildNodeMap
|
||||
&children =
|
||||
item->getChildren();
|
||||
for (child = 0;
|
||||
child < children.size();
|
||||
child++) {
|
||||
tree_output_queue.push_back(
|
||||
static_cast<
|
||||
Ogre::SceneNode
|
||||
*>(
|
||||
children[child]));
|
||||
tree_output_queue
|
||||
.push_back(
|
||||
nullptr);
|
||||
}
|
||||
} else
|
||||
tree_output_queue.push_back(
|
||||
item);
|
||||
}
|
||||
if (new_nodes_count == 0)
|
||||
break;
|
||||
tree_input_queue = tree_output_queue;
|
||||
tree_output_queue.clear();
|
||||
}
|
||||
tree_list.insert(tree_list.begin(),
|
||||
tree_output_queue.begin(),
|
||||
tree_output_queue.end());
|
||||
int count = 0;
|
||||
int depth = 0;
|
||||
std::vector<int> check_depth;
|
||||
int max_depth = 0;
|
||||
check_depth.push_back(0);
|
||||
for (count = 0; count < tree_list.size(); count++) {
|
||||
int t;
|
||||
// Get the hardware pixel buffer
|
||||
Ogre::HardwarePixelBufferSharedPtr pixelBuffer =
|
||||
worldMap->getBuffer();
|
||||
|
||||
Ogre::SceneNode *node = tree_list[count];
|
||||
if (node && max_depth >= depth) {
|
||||
Ogre::String name = node->getName();
|
||||
if (name.length() == 0) {
|
||||
name = "Node #" +
|
||||
Ogre::StringConverter::
|
||||
toString(count);
|
||||
}
|
||||
if (ImGui::TreeNode(name.c_str())) {
|
||||
check_depth.push_back(
|
||||
max_depth);
|
||||
max_depth++;
|
||||
ImGui::Text("%s",
|
||||
(name + "##caption")
|
||||
.c_str());
|
||||
position_editor(node);
|
||||
ImGui::Separator();
|
||||
orientation_editor(node);
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Attachments");
|
||||
attachments_editor(node);
|
||||
}
|
||||
} else if (!node && max_depth >= depth) {
|
||||
max_depth = check_depth.back();
|
||||
check_depth.pop_back();
|
||||
ImGui::TreePop();
|
||||
// Lock the buffer for writing, discarding previous contents for performance
|
||||
pixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD);
|
||||
|
||||
// Get information about the locked region (PixelBox)
|
||||
const Ogre::PixelBox &pixelBox = pixelBuffer->getCurrentLock();
|
||||
|
||||
// Ensure the image format matches the texture format
|
||||
OgreAssert(pixelBox.format == worldMapImage.getFormat(),
|
||||
"bad format");
|
||||
|
||||
// Copy the image data to the pixel box's data pointer
|
||||
memcpy(pixelBox.data, worldMapImage.getData(),
|
||||
worldMapImage.getSize());
|
||||
|
||||
// Unlock the buffer to apply changes to the GPU
|
||||
pixelBuffer->unlock();
|
||||
}
|
||||
void updateHeightmap()
|
||||
{
|
||||
Ogre::Vector3 worldPos =
|
||||
ECS::get<Camera>().mCameraPivot->_getDerivedPosition();
|
||||
TerrainModule::update_heightmap(worldMapImage);
|
||||
long x, y;
|
||||
ECS::get<Terrain>()
|
||||
.mTerrainGroup->convertWorldPositionToTerrainSlot(
|
||||
worldPos, &x, &y);
|
||||
int i, j;
|
||||
for (j = -1; j < 2; j++)
|
||||
for (i = -1; i < 2; i++) {
|
||||
Ogre::Terrain *terrain =
|
||||
ECS::get<Terrain>()
|
||||
.mTerrainGroup->getTerrain(
|
||||
x + j, y + i);
|
||||
if (terrain && terrain->isLoaded()) {
|
||||
terrain->dirty();
|
||||
terrain->updateDerivedData(true);
|
||||
terrain->updateGeometry();
|
||||
}
|
||||
if (tree_list[count])
|
||||
depth++;
|
||||
else
|
||||
depth--;
|
||||
}
|
||||
ImGui::Spacing();
|
||||
ImGui::End();
|
||||
|
||||
ECS::get<Terrain>().mTerrainGroup->updateDerivedData(true);
|
||||
ECS::get<Terrain>().mTerrainGroup->updateGeometry();
|
||||
ECS::get<Terrain>().mTerrainGroup->update(true);
|
||||
}
|
||||
void setCameraPos()
|
||||
{
|
||||
Ogre::Vector3 worldPos =
|
||||
ECS::get<Camera>().mCameraPivot->_getDerivedPosition();
|
||||
worldPos.x = TerrainModule::get_world_x(selected_x);
|
||||
worldPos.z = TerrainModule::get_world_y(selected_y);
|
||||
Ogre::Vector3 cameraPos =
|
||||
ECS::get<Camera>().mCameraPivot->_getDerivedPosition();
|
||||
cameraPos.x = worldPos.x;
|
||||
cameraPos.z = worldPos.z;
|
||||
cameraPos.y =
|
||||
TerrainModule::get_height(
|
||||
ECS::get<Terrain>().mTerrainGroup, cameraPos) +
|
||||
10.0f;
|
||||
if (cameraPos.y < 0.0f)
|
||||
cameraPos.y = 10.0f;
|
||||
ECS::get<Camera>().mCameraPivot->_setDerivedPosition(cameraPos);
|
||||
cameraPos =
|
||||
ECS::get<Camera>().mCameraGoal->_getDerivedPosition();
|
||||
ECS::get<Camera>().mCameraNode->_setDerivedPosition(cameraPos);
|
||||
std::cout << cameraPos << std::endl;
|
||||
std::cout << worldPos << std::endl;
|
||||
std::cout << selected_x << " " << selected_y << std::endl;
|
||||
ECS::get<Terrain>().mTerrainGroup->updateDerivedData(true);
|
||||
ECS::get<Terrain>().mTerrainGroup->updateGeometry();
|
||||
ECS::get<Terrain>().mTerrainGroup->update(true);
|
||||
}
|
||||
void worldMapView()
|
||||
{
|
||||
OgreAssert(TerrainModule::get_img_x(0) ==
|
||||
worldMap->getWidth() / 2,
|
||||
"get_img_x");
|
||||
OgreAssert(TerrainModule::get_img_y(0) ==
|
||||
worldMap->getHeight() / 2,
|
||||
"get_img_x");
|
||||
OgreAssert(TerrainModule::get_world_x(worldMap->getWidth() /
|
||||
2) == 0.0f,
|
||||
"get_world_x");
|
||||
OgreAssert(TerrainModule::get_world_y(worldMap->getHeight() /
|
||||
2) == 0.0f,
|
||||
"get_world_y");
|
||||
if (ECS::get<Camera>().mCameraPivot) {
|
||||
Ogre::Vector3 worldPos =
|
||||
ECS::get<Camera>()
|
||||
.mCameraPivot->_getDerivedPosition();
|
||||
selected_x = TerrainModule::get_img_x(worldPos.x);
|
||||
selected_y = TerrainModule::get_img_y(worldPos.z);
|
||||
locationSelected = true;
|
||||
std::cout << worldPos << std::endl;
|
||||
std::cout << selected_x << " " << selected_y
|
||||
<< std::endl;
|
||||
OgreAssert(selected_x >= 0 &&
|
||||
selected_x < worldMap->getWidth(),
|
||||
"mix width");
|
||||
OgreAssert(selected_y >= 0 &&
|
||||
selected_y < worldMap->getHeight(),
|
||||
"mix height");
|
||||
}
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(512 + 20, 512 + 20),
|
||||
ImVec2(768, 768));
|
||||
// ImGui::SetNextWindowScroll(
|
||||
// ImVec2(worldMap->getWidth(), worldMap->getHeight()));
|
||||
ImGui::Begin("WorldMap...");
|
||||
ImGui::Spacing();
|
||||
ImGui::BeginChild("WorldMap...", ImVec2(480, 480),
|
||||
ImGuiChildFlags_None,
|
||||
ImGuiWindowFlags_HorizontalScrollbar);
|
||||
ImGui::Spacing();
|
||||
Ogre::ResourceHandle hdl = worldMap->getHandle();
|
||||
int w = worldMap->getWidth();
|
||||
int h = worldMap->getHeight();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,
|
||||
ImVec2((float)5, (float)5));
|
||||
ImGui::ImageButton("WorldMapPress", (ImTextureID)hdl,
|
||||
ImVec2(w, h));
|
||||
ImVec2 mouse_absolute_pos = ImGui::GetMousePos();
|
||||
ImVec2 item_absolute_pos = ImGui::GetItemRectMin();
|
||||
top_x = item_absolute_pos.x + 5;
|
||||
top_y = item_absolute_pos.y + 5;
|
||||
bool hovered = false;
|
||||
#if 0
|
||||
pos_x = mouse_absolute_pos.x - item_absolute_pos.x - 5;
|
||||
pos_y = mouse_absolute_pos.y - item_absolute_pos.y - 5;
|
||||
#endif
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImVec2 mouse_absolute_pos = ImGui::GetMousePos();
|
||||
ImVec2 item_absolute_pos = ImGui::GetItemRectMin();
|
||||
pos_x = mouse_absolute_pos.x - item_absolute_pos.x - 5;
|
||||
pos_y = mouse_absolute_pos.y - item_absolute_pos.y - 5;
|
||||
hovered = true;
|
||||
}
|
||||
pos_x = Ogre::Math::Clamp(pos_x, 0,
|
||||
(int)worldMap->getWidth() - 1);
|
||||
pos_y = Ogre::Math::Clamp(pos_y, 0,
|
||||
(int)worldMap->getHeight() - 1);
|
||||
if (pos_x < 0)
|
||||
pos_x = 0;
|
||||
if (pos_x >= worldMap->getWidth())
|
||||
pos_x = worldMap->getWidth() - 1;
|
||||
if (pos_y < 0)
|
||||
pos_y = 0;
|
||||
if (pos_y >= worldMap->getHeight())
|
||||
pos_y = worldMap->getHeight() - 1;
|
||||
if (ImGui::IsItemActivated()) {
|
||||
locationSelected = true;
|
||||
selected_x = pos_x;
|
||||
selected_y = pos_y;
|
||||
OgreAssert(selected_x >= 0 &&
|
||||
selected_x < worldMap->getWidth(),
|
||||
"mix width");
|
||||
OgreAssert(selected_y >= 0 &&
|
||||
selected_y < worldMap->getHeight(),
|
||||
"mix height");
|
||||
setCameraPos();
|
||||
std::cout << "worldClickPos: " << pos_x << " " << pos_y
|
||||
<< std::endl;
|
||||
}
|
||||
ImDrawList *draw_list = ImGui::GetWindowDrawList();
|
||||
draw_list->AddCircleFilled(ImVec2(top_x + pos_x, top_y + pos_y),
|
||||
1.0f, IM_COL32(0, 255, 0, 255));
|
||||
if (locationSelected)
|
||||
draw_list->AddCircleFilled(
|
||||
ImVec2(top_x + selected_x, top_y + selected_y),
|
||||
4.0f, IM_COL32(64, 255, 64, 255));
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::Spacing();
|
||||
ImGui::EndChild();
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginChild("WorldMap...", ImVec2(64, 480),
|
||||
ImGuiChildFlags_None,
|
||||
ImGuiWindowFlags_HorizontalScrollbar);
|
||||
ImGui::EndChild();
|
||||
ImGui::Spacing();
|
||||
ImGui::BeginChild("WorldMap Bottom...", ImVec2(0, 0));
|
||||
ImGui::Text("Position: %d %d", pos_x, pos_y);
|
||||
ImGui::Text("Selected Position: %d %d", selected_x, selected_y);
|
||||
ImGui::Text("Height: %f",
|
||||
worldMapImage.getColourAt(pos_x, pos_y, 0).r);
|
||||
ImGui::Text(
|
||||
"Selected height: %f",
|
||||
worldMapImage.getColourAt(selected_x, selected_y, 0).r);
|
||||
if (ImGui::Button("Update terrain")) {
|
||||
ECS::get<Terrain>().mTerrainGroup->update(true);
|
||||
ECS::get<Terrain>().mTerrainGroup->updateDerivedData(
|
||||
true);
|
||||
ECS::get<Terrain>().mTerrainGroup->updateGeometry();
|
||||
}
|
||||
ImGui::SliderFloat("Strength...", &strength, 0.0f, 0.2f);
|
||||
ImGui::SliderInt("Size", &size, 0, 8);
|
||||
bool riseLower = false;
|
||||
bool riseLower2 = false;
|
||||
bool smooth = false;
|
||||
bool setLevel = false;
|
||||
float setLevelValue = 0.0f;
|
||||
float riseLowerChange = 0.0f;
|
||||
if (ImGui::Button("Elevate")) {
|
||||
riseLower = true;
|
||||
riseLowerChange = strength;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Lower")) {
|
||||
riseLower = true;
|
||||
riseLowerChange = -strength;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Smooth")) {
|
||||
smooth = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Elevate2")) {
|
||||
riseLower2 = true;
|
||||
riseLowerChange = strength;
|
||||
}
|
||||
if (ImGui::Button("Deepest")) {
|
||||
setLevel = true;
|
||||
setLevelValue = 0.0f;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Highest")) {
|
||||
setLevel = true;
|
||||
setLevelValue = 1.0f;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Beach")) {
|
||||
setLevel = true;
|
||||
setLevelValue = 0.516f;
|
||||
}
|
||||
if (ImGui::Button("Shore1")) {
|
||||
setLevel = true;
|
||||
setLevelValue = 0.536f;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Shore2")) {
|
||||
setLevel = true;
|
||||
setLevelValue = 0.556f;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Shore3")) {
|
||||
setLevel = true;
|
||||
setLevelValue = 0.586f;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Shore4")) {
|
||||
setLevel = true;
|
||||
setLevelValue = 0.606f;
|
||||
}
|
||||
if (ImGui::Button("Shore5")) {
|
||||
setLevel = true;
|
||||
setLevelValue = 0.626f;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Shore6")) {
|
||||
setLevel = true;
|
||||
setLevelValue = 0.646f;
|
||||
}
|
||||
if (riseLower) {
|
||||
int actualSize = 1 + size * 2;
|
||||
int i, j;
|
||||
for (i = -actualSize; i < actualSize + 1; i++)
|
||||
for (j = -actualSize; j < actualSize + 1; j++) {
|
||||
if (i * i + j * j >
|
||||
actualSize * actualSize)
|
||||
continue;
|
||||
if (selected_x + j < 0 ||
|
||||
selected_x + j >=
|
||||
worldMap->getWidth())
|
||||
continue;
|
||||
if (selected_y + i < 0 ||
|
||||
selected_y + i >=
|
||||
worldMap->getHeight())
|
||||
continue;
|
||||
Ogre::ColourValue cv =
|
||||
worldMapImage.getColourAt(
|
||||
selected_x + j,
|
||||
selected_y + i, 0);
|
||||
float original = cv.r;
|
||||
original += riseLowerChange;
|
||||
original = Ogre::Math::Clamp(
|
||||
original, 0.0f, 1.0f);
|
||||
cv.r = original;
|
||||
worldMapImage.setColourAt(
|
||||
cv, selected_x + j,
|
||||
selected_y + i, 0);
|
||||
}
|
||||
updateWorldTexture();
|
||||
updateHeightmap();
|
||||
}
|
||||
if (riseLower2) {
|
||||
int actualSize = 1 + size * 2;
|
||||
int i, j;
|
||||
Ogre::ColourValue maxcv = worldMapImage.getColourAt(
|
||||
selected_x, selected_y, 0);
|
||||
for (i = -actualSize; i < actualSize + 1; i++)
|
||||
for (j = -actualSize; j < actualSize + 1; j++) {
|
||||
if (i * i + j * j >
|
||||
actualSize * actualSize)
|
||||
continue;
|
||||
if (selected_x + j < 0 ||
|
||||
selected_x + j >=
|
||||
worldMap->getWidth())
|
||||
continue;
|
||||
if (selected_y + i < 0 ||
|
||||
selected_y + i >=
|
||||
worldMap->getHeight())
|
||||
continue;
|
||||
float actualStrength =
|
||||
riseLowerChange /
|
||||
(1.0f + (float)(i * i + j * j));
|
||||
if (i * i + j * j ==
|
||||
actualSize * actualSize) {
|
||||
std::cout << actualStrength
|
||||
<< std::endl;
|
||||
// OgreAssert(false, "strength");
|
||||
}
|
||||
Ogre::ColourValue cv =
|
||||
worldMapImage.getColourAt(
|
||||
selected_x + j,
|
||||
selected_y + i, 0);
|
||||
float original =
|
||||
maxcv.r + actualStrength;
|
||||
original = Ogre::Math::Clamp(
|
||||
original, 0.0f, 1.0f);
|
||||
if (cv.r >= original)
|
||||
continue;
|
||||
cv.r = original;
|
||||
worldMapImage.setColourAt(
|
||||
cv, selected_x + j,
|
||||
selected_y + i, 0);
|
||||
}
|
||||
updateWorldTexture();
|
||||
updateHeightmap();
|
||||
}
|
||||
if (smooth) {
|
||||
int actualSize = 1 + size * 2;
|
||||
int i, j, k, l;
|
||||
for (i = -actualSize; i < actualSize + 1; i++)
|
||||
for (j = -actualSize; j < actualSize + 1; j++) {
|
||||
if (i * i + j * j >
|
||||
actualSize * actualSize)
|
||||
continue;
|
||||
if (selected_x + j < 0 ||
|
||||
selected_x + j >=
|
||||
worldMap->getWidth())
|
||||
continue;
|
||||
if (selected_y + i < 0 ||
|
||||
selected_y + i >=
|
||||
worldMap->getHeight())
|
||||
continue;
|
||||
int kernel = 3;
|
||||
float original = 0.0f;
|
||||
Ogre::ColourValue cv;
|
||||
float count = 0.0f;
|
||||
for (k = -kernel; k < kernel + 1; k++) {
|
||||
if (selected_y + i + k < 0 ||
|
||||
selected_y + i + k >=
|
||||
worldMap->getHeight())
|
||||
continue;
|
||||
for (l = -kernel;
|
||||
l < kernel + 1; l++) {
|
||||
if (selected_x + j + l <
|
||||
0 ||
|
||||
selected_x + j +
|
||||
l >=
|
||||
worldMap->getWidth())
|
||||
continue;
|
||||
cv = worldMapImage.getColourAt(
|
||||
selected_x + j,
|
||||
selected_y + i,
|
||||
0);
|
||||
original += cv.r;
|
||||
count += 1.0f;
|
||||
}
|
||||
}
|
||||
original /= count;
|
||||
cv = worldMapImage.getColourAt(
|
||||
selected_x + j, selected_y + i,
|
||||
0);
|
||||
original = Ogre::Math::Clamp(
|
||||
original, 0.0f, 1.0f);
|
||||
cv.r = original;
|
||||
worldMapImage.setColourAt(
|
||||
cv, selected_x + j,
|
||||
selected_y + i, 0);
|
||||
}
|
||||
updateWorldTexture();
|
||||
updateHeightmap();
|
||||
}
|
||||
if (setLevel) {
|
||||
int actualSize = 1 + size * 2;
|
||||
int i, j;
|
||||
float original = setLevelValue;
|
||||
original = Ogre::Math::Clamp(original, 0.0f, 1.0f);
|
||||
for (i = -actualSize; i < actualSize + 1; i++)
|
||||
for (j = -actualSize; j < actualSize + 1; j++) {
|
||||
if (i * i + j * j >
|
||||
actualSize * actualSize)
|
||||
continue;
|
||||
if (selected_x + j < 0 ||
|
||||
selected_x + j >=
|
||||
worldMap->getWidth())
|
||||
continue;
|
||||
if (selected_y + i < 0 ||
|
||||
selected_y + i >=
|
||||
worldMap->getHeight())
|
||||
continue;
|
||||
Ogre::ColourValue cv =
|
||||
worldMapImage.getColourAt(
|
||||
selected_x + j,
|
||||
selected_y + i, 0);
|
||||
cv.r = original;
|
||||
worldMapImage.setColourAt(
|
||||
cv, selected_x + j,
|
||||
selected_y + i, 0);
|
||||
}
|
||||
updateWorldTexture();
|
||||
updateHeightmap();
|
||||
}
|
||||
if (ImGui::Button("Save heightmap")) {
|
||||
updateWorldTexture();
|
||||
updateHeightmap();
|
||||
TerrainModule::save_heightmap();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::Spacing();
|
||||
ImGui::End();
|
||||
}
|
||||
void panel()
|
||||
{
|
||||
ImVec2 size = ImGui::GetMainViewport()->Size;
|
||||
float window_width = size.x * 0.2f;
|
||||
if (window_width > panel_width)
|
||||
window_width = panel_width;
|
||||
float window_height = size.y * 0.5f - 20;
|
||||
ImGui::SetNextWindowPos(ImVec2(size.x - window_width, 20),
|
||||
ImGuiCond_Always);
|
||||
ImGui::SetNextWindowSize(ImVec2(window_width, window_height),
|
||||
ImGuiCond_Always);
|
||||
// ImGui::Begin("Dumb and Stupid", &mKbd.gui_active);
|
||||
ImGui::Begin("Panel...");
|
||||
std::deque<Ogre::SceneNode *> tree_input_queue,
|
||||
tree_output_queue;
|
||||
std::vector<Ogre::SceneNode *> tree_list;
|
||||
tree_input_queue.push_back(
|
||||
ECS::get()
|
||||
.get<EngineData>()
|
||||
.mScnMgr->getRootSceneNode());
|
||||
tree_input_queue.push_back(nullptr);
|
||||
std::set<Ogre::SceneNode *> visited;
|
||||
while (true) {
|
||||
int new_nodes_count = 0;
|
||||
while (!tree_input_queue.empty()) {
|
||||
int child;
|
||||
Ogre::SceneNode *item =
|
||||
tree_input_queue.front();
|
||||
tree_input_queue.pop_front();
|
||||
if (item && visited.find(item) ==
|
||||
visited.end()) { // new node
|
||||
new_nodes_count++;
|
||||
tree_output_queue.push_back(item);
|
||||
visited.insert(item);
|
||||
const Ogre::Node::ChildNodeMap
|
||||
&children = item->getChildren();
|
||||
for (child = 0; child < children.size();
|
||||
child++) {
|
||||
tree_output_queue.push_back(
|
||||
static_cast<Ogre::SceneNode
|
||||
*>(
|
||||
children[child]));
|
||||
tree_output_queue.push_back(
|
||||
nullptr);
|
||||
}
|
||||
} else
|
||||
tree_output_queue.push_back(item);
|
||||
}
|
||||
if (new_nodes_count == 0)
|
||||
break;
|
||||
tree_input_queue = tree_output_queue;
|
||||
tree_output_queue.clear();
|
||||
}
|
||||
tree_list.insert(tree_list.begin(), tree_output_queue.begin(),
|
||||
tree_output_queue.end());
|
||||
int count = 0;
|
||||
int depth = 0;
|
||||
std::vector<int> check_depth;
|
||||
int max_depth = 0;
|
||||
check_depth.push_back(0);
|
||||
for (count = 0; count < tree_list.size(); count++) {
|
||||
int t;
|
||||
|
||||
Ogre::SceneNode *node = tree_list[count];
|
||||
if (node && max_depth >= depth) {
|
||||
Ogre::String name = node->getName();
|
||||
if (name.length() == 0) {
|
||||
name = "Node #" +
|
||||
Ogre::StringConverter::toString(
|
||||
count);
|
||||
}
|
||||
if (ImGui::TreeNode(name.c_str())) {
|
||||
check_depth.push_back(max_depth);
|
||||
max_depth++;
|
||||
ImGui::Text(
|
||||
"%s",
|
||||
(name + "##caption").c_str());
|
||||
position_editor(node);
|
||||
ImGui::Separator();
|
||||
orientation_editor(node);
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("From Cursor"))
|
||||
std::cout << name
|
||||
<< " From Cursor"
|
||||
<< std::endl;
|
||||
if (ImGui::Button("To Cursor"))
|
||||
std::cout << name
|
||||
<< " To Cursor"
|
||||
<< std::endl;
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Attachments");
|
||||
attachments_editor(node);
|
||||
}
|
||||
} else if (!node && max_depth >= depth) {
|
||||
max_depth = check_depth.back();
|
||||
check_depth.pop_back();
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (tree_list[count])
|
||||
depth++;
|
||||
else
|
||||
depth--;
|
||||
}
|
||||
ImGui::Spacing();
|
||||
ImGui::End();
|
||||
#if 0
|
||||
if (ECS::get().get<GUI>().narrationBox) {
|
||||
ImVec2 size = ImGui::GetMainViewport()->Size;
|
||||
@@ -990,6 +1471,20 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
|
||||
ImGui::End();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void preview(const Ogre::RenderTargetViewportEvent &evt)
|
||||
{
|
||||
int i;
|
||||
Ogre::ImGuiOverlay::NewFrame();
|
||||
if (ECS::get().get<GUI>().enabled) {
|
||||
buttons_panel();
|
||||
#if 0
|
||||
buildings_editor();
|
||||
map_editor();
|
||||
#endif
|
||||
panel();
|
||||
if (enableMapEditor)
|
||||
worldMapView();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -145,7 +145,6 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
PhysicsShape &s = e.ensure<PhysicsShape>();
|
||||
s.shape = shape;
|
||||
e.modified<PhysicsShape>();
|
||||
delete hfd.samples;
|
||||
e.remove<PhysicsHeightfieldData>();
|
||||
});
|
||||
#if 1
|
||||
@@ -341,6 +340,16 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
.each([this](const EngineData &eng) {
|
||||
ECS::get().set<WaterBody>({});
|
||||
});
|
||||
#if 0
|
||||
ecs.system<const EngineData>("DebugData")
|
||||
.kind(PhysicsPostUpdate)
|
||||
.each([this](const EngineData &eng) {
|
||||
std::cout << "TerrainReady: "
|
||||
<< ECS::get().has<TerrainReady>();
|
||||
std::cout << " WaterReady: "
|
||||
<< ECS::get().has<WaterReady>() << std::endl;
|
||||
});
|
||||
#endif
|
||||
ecs.system<const EngineData, WaterBody>("update_water")
|
||||
.kind(PhysicsPostUpdate)
|
||||
.with<TerrainReady>()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <iostream>
|
||||
#include <Ogre.h>
|
||||
#include "Components.h"
|
||||
#include "SunModule.h"
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <OgreTerrainPagedWorldSection.h>
|
||||
#include <OgrePage.h>
|
||||
#include <OgreTerrainPaging.h>
|
||||
#include <OgreFileSystemLayer.h>
|
||||
|
||||
#include "GameData.h"
|
||||
#include "Components.h"
|
||||
@@ -71,11 +72,50 @@ struct HeightData {
|
||||
}
|
||||
return img_brushes.getColourAt(x, y + m, 0).r;
|
||||
}
|
||||
float get_base_height(const Ogre::Vector2 &worldOffset, int x, int y)
|
||||
float get_world_x(int x)
|
||||
{
|
||||
return (float)(x - (int)img.getWidth() / 2) * BRUSH_SIZE;
|
||||
}
|
||||
float get_world_y(int y)
|
||||
{
|
||||
return (float)(y - (int)img.getHeight() / 2) * BRUSH_SIZE;
|
||||
}
|
||||
int get_img_x(float world_x)
|
||||
{
|
||||
float world_img_x = world_x + img.getWidth() * BRUSH_SIZE / 2;
|
||||
int ret = world_img_x / BRUSH_SIZE;
|
||||
// ret = Ogre::Math::Clamp(ret, 0, (int)img.getWidth() - 1);
|
||||
return ret;
|
||||
}
|
||||
int get_img_y(float world_z)
|
||||
{
|
||||
float world_img_y = world_z + img.getHeight() * BRUSH_SIZE / 2;
|
||||
int ret = world_img_y / BRUSH_SIZE;
|
||||
// ret = Ogre::Math::Clamp(ret, 0, (int)img.getHeight() - 1);
|
||||
return ret;
|
||||
}
|
||||
void update_heightmap(const Ogre::Image &heightmap)
|
||||
{
|
||||
img = heightmap;
|
||||
}
|
||||
void save_heightmap()
|
||||
{
|
||||
Ogre::String group =
|
||||
Ogre::ResourceGroupManager::getSingleton()
|
||||
.findGroupContainingResource("world_map.png");
|
||||
Ogre::FileInfoListPtr fileInfoList(
|
||||
Ogre::ResourceGroupManager::getSingleton()
|
||||
.findResourceFileInfo(group, "world_map.png"));
|
||||
OgreAssert(fileInfoList->size() == 1,
|
||||
"worpd_map.png should be there and only once");
|
||||
Ogre::String path = fileInfoList->at(0).archive->getName() +
|
||||
"/" + "world_map.png";
|
||||
Ogre::FileSystemLayer::removeFile(path);
|
||||
img.save(path);
|
||||
}
|
||||
float get_base_height(long world_x, long world_y)
|
||||
{
|
||||
float height = 0.0f;
|
||||
int world_x = worldOffset.x + x;
|
||||
int world_y = worldOffset.y + y;
|
||||
int world_img_x =
|
||||
world_x + (int)img.getWidth() * BRUSH_SIZE / 2;
|
||||
int world_img_y =
|
||||
@@ -91,7 +131,7 @@ struct HeightData {
|
||||
world_img_x >= img.getWidth() * BRUSH_SIZE ||
|
||||
world_img_y < 0 ||
|
||||
world_img_y >= img.getWidth() * BRUSH_SIZE) {
|
||||
height = -1.0f;
|
||||
height = 0.0f;
|
||||
goto out;
|
||||
}
|
||||
color = img.getColourAt(map_img_x, map_img_y, 0);
|
||||
@@ -103,7 +143,7 @@ struct HeightData {
|
||||
out:
|
||||
return height;
|
||||
}
|
||||
float get_noise_height(const Ogre::Vector2 &worldOffset, int x, int y)
|
||||
float get_noise_height(long world_x, long world_y)
|
||||
{
|
||||
int h;
|
||||
Ogre::Vector2 noisePoint;
|
||||
@@ -122,7 +162,7 @@ out:
|
||||
for (h = 0; h < (int)sizeof(noise_values) /
|
||||
(int)sizeof(noise_values[0]);
|
||||
h++) {
|
||||
noisePoint = (worldOffset + Ogre::Vector2(x, y) +
|
||||
noisePoint = (Ogre::Vector2(world_x, world_y) +
|
||||
noise_pass[h].noiseOfft) *
|
||||
noise_pass[h].noiseMul;
|
||||
int noise_x =
|
||||
@@ -139,31 +179,44 @@ out:
|
||||
}
|
||||
return noise_values[0] + noise_values[1];
|
||||
}
|
||||
float get_height(Ogre::TerrainGroup *terrainGroup, long x, long y,
|
||||
int j, int i)
|
||||
float get_height(Ogre::TerrainGroup *terrainGroup, long world_x,
|
||||
long world_y)
|
||||
{
|
||||
uint16_t terrainSize = terrainGroup->getTerrainSize();
|
||||
Ogre::Vector2 worldOffset(Ogre::Real(x * (terrainSize - 1)),
|
||||
Ogre::Real(y * (terrainSize - 1)));
|
||||
float brush_height0 =
|
||||
HeightData::get_singleton()->get_brush_height(
|
||||
0, j % BRUSH_SIZE, i % BRUSH_SIZE) -
|
||||
0.55f;
|
||||
float brush_height1 =
|
||||
HeightData::get_singleton()->get_brush_height(
|
||||
1, j % BRUSH_SIZE, i % BRUSH_SIZE) -
|
||||
0.55f;
|
||||
long grid_center_x = img.getWidth() * BRUSH_SIZE / 2;
|
||||
long grid_center_y = img.getHeight() * BRUSH_SIZE / 2;
|
||||
long world_grid_x = world_x + grid_center_x;
|
||||
long world_grid_y = world_y + grid_center_y;
|
||||
float amplitude = 150.0f;
|
||||
if (world_grid_x < 0 || world_grid_y < 0) {
|
||||
std::cout << "world: " << world_x << " " << world_y
|
||||
<< " ";
|
||||
std::cout << "grid: " << world_grid_x << " ";
|
||||
std::cout << world_grid_y << std::endl;
|
||||
return -amplitude;
|
||||
}
|
||||
OgreAssert(world_grid_x >= 0, "bad world x");
|
||||
OgreAssert(world_grid_y >= 0, "bad world y");
|
||||
long cell = 8;
|
||||
long b1 = (world_grid_x / cell) * cell + cell / 2;
|
||||
long b2 = (world_grid_y / cell) * cell + cell / 2;
|
||||
long o1 = Ogre::Math::Abs(world_grid_x - b1);
|
||||
long o2 = Ogre::Math::Abs(world_grid_y - b2);
|
||||
// std::cout << "h: " << o1 << " " << o2 << std::endl;
|
||||
// std::cout << "h: " << (o1 * o1 + o2 * o2) << std::endl;
|
||||
float hbase = 1.0 / (1.0f + 0.02f * (o1 * o1 + o2 * o2));
|
||||
float h1 = hbase * 0.5f + 0.5f;
|
||||
float h2 = (1.0f - hbase) * 0.5f;
|
||||
float mheight =
|
||||
Ogre::Math::lerp(
|
||||
brush_height1, brush_height0,
|
||||
HeightData::get_singleton()->get_base_height(
|
||||
worldOffset, j, i)) *
|
||||
120.0f;
|
||||
(Ogre::Math::lerp(h2, h1,
|
||||
get_base_height(world_x, world_y)) -
|
||||
0.51f) *
|
||||
amplitude;
|
||||
float height = mheight;
|
||||
if (mheight > 0.5f)
|
||||
height += 2.0f + get_noise_height(worldOffset, j, i);
|
||||
height += 2.0f + get_noise_height(world_x, world_y);
|
||||
else if (mheight < -0.5f)
|
||||
height -= 2.0f + get_noise_height(worldOffset, j, i);
|
||||
height -= 2.0f + get_noise_height(world_x, world_y);
|
||||
// OgreAssert(false, "height");
|
||||
return height;
|
||||
}
|
||||
};
|
||||
@@ -231,11 +284,29 @@ public:
|
||||
// Ogre::Vector2(img.getWidth(), img.getHeight()) * 0.5f;
|
||||
float chunk = 128.0f;
|
||||
Ogre::Vector2 revisedValuePoint;
|
||||
Ogre::Vector3 worldPos;
|
||||
terrainGroup->convertTerrainSlotToWorldPosition(x, y,
|
||||
&worldPos);
|
||||
for (int i = 0; i < terrainSize; i++)
|
||||
for (int j = 0; j < terrainSize; j++) {
|
||||
float height =
|
||||
HeightData::get_singleton()->get_height(
|
||||
terrainGroup, x, y, j, i);
|
||||
long world_x = (long)(worldPos.x + j -
|
||||
(terrainSize - 1) / 2);
|
||||
long world_y = (long)(worldPos.z + i -
|
||||
(terrainSize - 1) / 2);
|
||||
float height = 0.0f;
|
||||
int k, l;
|
||||
for (l = -1; l < 2; l++)
|
||||
for (k = -1; k < 2; k++) {
|
||||
height +=
|
||||
HeightData::get_singleton()
|
||||
->get_height(
|
||||
terrainGroup,
|
||||
world_x +
|
||||
4 * k,
|
||||
world_y +
|
||||
4 * l);
|
||||
}
|
||||
height /= 9.0f;
|
||||
|
||||
// height = -2.0f;
|
||||
heightMap[i * terrainSize + j] = height;
|
||||
@@ -526,16 +597,16 @@ TerrainModule::TerrainModule(flecs::world &ecs)
|
||||
priv.mSunUpdate.reset();
|
||||
}
|
||||
});
|
||||
ecs.system<const CharacterBase, const Terrain>("UpdateTerrainStatus")
|
||||
ecs.system<const ECS::Camera, const Terrain>("UpdateTerrainStatus")
|
||||
.kind(flecs::OnUpdate)
|
||||
.without<TerrainReady>()
|
||||
.each([](const CharacterBase &ch, const Terrain &terrain) {
|
||||
.each([](const ECS::Camera &cam, const Terrain &terrain) {
|
||||
std::cout << "mTerrainReady: " << terrain.mTerrainReady
|
||||
<< "\n";
|
||||
std::cout << "mBodyNode: " << ch.mBodyNode << "\n";
|
||||
if (ch.mBodyNode && terrain.mTerrainReady) {
|
||||
if (cam.mCameraNode && terrain.mTerrainReady) {
|
||||
long x, y;
|
||||
Ogre::Vector3 pos = ch.mBodyNode->getPosition();
|
||||
Ogre::Vector3 pos =
|
||||
cam.mCameraNode->getPosition();
|
||||
terrain.mTerrainGroup
|
||||
->convertWorldPositionToTerrainSlot(
|
||||
pos, &x, &y);
|
||||
@@ -560,8 +631,7 @@ TerrainModule::TerrainModule(flecs::world &ecs)
|
||||
item.position = Ogre::Vector3(0, 0, 0);
|
||||
float height =
|
||||
HeightData::get_singleton()->get_height(
|
||||
terrain.mTerrainGroup, 0, 0, 0,
|
||||
0);
|
||||
terrain.mTerrainGroup, 0, 0);
|
||||
item.position.y = height;
|
||||
placement.altar_items.push_back(item);
|
||||
for (i = -64000; i < 64000; i += 2000)
|
||||
@@ -586,14 +656,10 @@ TerrainModule::TerrainModule(flecs::world &ecs)
|
||||
HeightData::get_singleton()
|
||||
->get_height(
|
||||
terrain.mTerrainGroup,
|
||||
xslot,
|
||||
yslot,
|
||||
(int)offset.x +
|
||||
(terrainSize -
|
||||
1) / 2,
|
||||
(int)offset.z +
|
||||
(terrainSize -
|
||||
1) / 2);
|
||||
(long)position
|
||||
.x,
|
||||
(long)position
|
||||
.z);
|
||||
#if 0
|
||||
height =
|
||||
terrain.mTerrainGroup
|
||||
@@ -672,8 +738,31 @@ float TerrainModule::get_height(Ogre::TerrainGroup *group,
|
||||
group->convertTerrainSlotToWorldPosition(xslot, yslot, &slotpos);
|
||||
Ogre::Vector3 offset = (position - slotpos) * terrainSize / worldSize;
|
||||
float height = HeightData::get_singleton()->get_height(
|
||||
group, xslot, yslot, (int)offset.x + (terrainSize - 1) / 2,
|
||||
(int)offset.z + (terrainSize - 1) / 2);
|
||||
group, (long)position.x, (long)position.z);
|
||||
return height;
|
||||
}
|
||||
float TerrainModule::get_world_x(int x)
|
||||
{
|
||||
return HeightData::get_singleton()->get_world_x(x);
|
||||
}
|
||||
float TerrainModule::get_world_y(int y)
|
||||
{
|
||||
return HeightData::get_singleton()->get_world_y(y);
|
||||
}
|
||||
int TerrainModule::get_img_x(float world_x)
|
||||
{
|
||||
return HeightData::get_singleton()->get_img_x(world_x);
|
||||
}
|
||||
int TerrainModule::get_img_y(float world_z)
|
||||
{
|
||||
return HeightData::get_singleton()->get_img_y(world_z);
|
||||
}
|
||||
void TerrainModule::update_heightmap(const Ogre::Image &heightmap)
|
||||
{
|
||||
return HeightData::get_singleton()->update_heightmap(heightmap);
|
||||
}
|
||||
void TerrainModule::save_heightmap()
|
||||
{
|
||||
HeightData::get_singleton()->save_heightmap();
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,12 @@ struct TerrainModule {
|
||||
TerrainModule(flecs::world &ecs);
|
||||
static float get_height(Ogre::TerrainGroup *group,
|
||||
const Ogre::Vector3 &position);
|
||||
static float get_world_x(int x);
|
||||
static float get_world_y(int y);
|
||||
static int get_img_x(float world_x);
|
||||
static int get_img_y(float world_z);
|
||||
static void update_heightmap(const Ogre::Image &heightmap);
|
||||
static void save_heightmap();
|
||||
};
|
||||
struct TerrainReady {};
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ public:
|
||||
};
|
||||
#endif
|
||||
static const uint32_t WATER_MASK = 0xF00;
|
||||
static bool debugEnabled = false;
|
||||
WaterModule::WaterModule(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<WaterModule>();
|
||||
@@ -163,15 +164,18 @@ WaterModule::WaterModule(flecs::world &ecs)
|
||||
Ogre::FT_MIP, Ogre::FO_LINEAR);
|
||||
}
|
||||
// create a frosted screen in front of the camera, using our dynamic texture to "thaw" certain areas
|
||||
Ogre::Entity *ent = eng.mScnMgr->createEntity(
|
||||
"WaterDebugPlane",
|
||||
Ogre::SceneManager::PT_PLANE);
|
||||
ent->setMaterialName("Water/Debug", "Water");
|
||||
ent->setVisibilityFlags(WATER_MASK);
|
||||
Ogre::SceneNode *node =
|
||||
camera.mCameraNode->createChildSceneNode();
|
||||
node->setPosition(-150, 60, -400);
|
||||
node->attachObject(ent);
|
||||
if (debugEnabled) {
|
||||
Ogre::Entity *ent = eng.mScnMgr->createEntity(
|
||||
"WaterDebugPlane",
|
||||
Ogre::SceneManager::PT_PLANE);
|
||||
ent->setMaterialName("Water/Debug", "Water");
|
||||
ent->setVisibilityFlags(WATER_MASK);
|
||||
Ogre::SceneNode *node =
|
||||
camera.mCameraNode
|
||||
->createChildSceneNode();
|
||||
node->setPosition(-150, 60, -400);
|
||||
node->attachObject(ent);
|
||||
}
|
||||
|
||||
water.mReflectionTexture =
|
||||
reflectionTexture->getBuffer()
|
||||
|
||||
Reference in New Issue
Block a user