sample app - game & scene views

This commit is contained in:
Mikulas Florek 2015-09-20 17:30:37 +02:00
parent 59f061f892
commit 8afad3bb03
23 changed files with 667 additions and 270 deletions

View file

@ -1,21 +1,29 @@
BasedOnStyle: LLVM
AllowAllParametersOfDeclarationOnNextLine : true
AlignAfterOpenBracket : false
AlignConsecutiveAssignments : false
AllowAllParametersOfDeclarationOnNextLine : false
AccessModifierOffset : -4
AllowShortCaseLabelsOnASingleLine : true
AllowShortFunctionsOnASingleLine : Inline
AllowShortIfStatementsOnASingleLine : false
AllowShortIfStatementsOnASingleLine : true
AllowShortLoopsOnASingleLine : true
AlwaysBreakAfterDefinitionReturnType : None
BinPackArguments : false
BinPackParameters : false
BreakBeforeBraces : Allman
BreakConstructorInitializersBeforeComma : true
ColumnLimit : 100
ConstructorInitializerIndentWidth : 4
ConstructorInitializerAllOnOneLineOrOnePerLine : false
ContinuationIndentWidth : 4
IndentCaseLabels : true
IndentWidth : 4
KeepEmptyLinesAtTheStartOfBlocks : true
MaxEmptyLinesToKeep : 2
NamespaceIndentation : None
PenaltyBreakBeforeFirstCallParameter : 0
PenaltyReturnTypeOnItsOwnLine : 1000
PointerAlignment : Left
SpaceAfterCStyleCast : false
SpaceBeforeAssignmentOperators : true

View file

@ -13,18 +13,31 @@ void normalize(const char* path, char* out, uint32_t max_size)
{
ASSERT(max_size > 0);
uint32_t i = 0;
bool is_prev_slash = false;
if (path[0] == '.' && (path[1] == '\\' || path[1] == '/'))
++path;
if (path[0] == '\\' || path[0] == '/')
++path;
while (*path != '\0' && i < max_size)
{
bool is_current_slash = *path == '\\' || *path == '/';
if (is_current_slash && is_prev_slash)
{
++path;
continue;
}
*out = *path == '\\' ? '/' : *path;
*out = *path >= 'A' && *path <= 'Z' ? *path - 'A' + 'a' : *out;
path++;
out++;
i++;
is_prev_slash = is_current_slash;
}
(i < max_size ? *out : *(out - 1)) = '\0';
}

View file

@ -417,7 +417,7 @@ static bool increment(char* output, char* end, bool is_space_after)
bool toCString(float value, char* output, int length, int after_point)
{
if (length < 1)
if (length < 2)
{
return false;
}
@ -432,15 +432,24 @@ bool toCString(float value, char* output, int length, int after_point)
int exponent = value == 0 ? 0 : (int)log10(value);
float num = value;
char* c = output;
while ((num >= 1 || exponent >= 0) && length > 0)
if (num < 1 && num > -1)
{
float power = (float)pow(10, exponent);
char digit = (char)floor(num / power);
num -= digit * power;
*c = digit + '0';
--exponent;
--length;
*c = '0';
++c;
--length;
}
else
{
while ((num >= 1 || exponent >= 0) && length > 0)
{
float power = (float)pow(10, exponent);
char digit = (char)floor(num / power);
num -= digit * power;
*c = digit + '0';
--exponent;
--length;
++c;
}
}
// decimal part
float dec_part = num;

View file

@ -94,7 +94,7 @@ public:
m_universe_context = &m_engine->createUniverse();
m_pipeline->setScene((Lumix::RenderScene*)m_universe_context->getScene(
Lumix::crc32("renderer")));
m_pipeline->resize(600, 400);
m_pipeline->setViewport(0, 0, 600, 400);
enumerateTests();
}

View file

@ -55,14 +55,31 @@ FrameBuffer::~FrameBuffer()
void FrameBuffer::resize(int width, int height)
{
ASSERT(m_window_handle);
if (bgfx::isValid(m_handle))
{
bgfx::destroyFrameBuffer(m_handle);
}
m_declaration.m_width = width;
m_declaration.m_height = height;
m_handle = bgfx::createFrameBuffer(m_window_handle, width, height);
if (m_window_handle)
{
m_handle = bgfx::createFrameBuffer(m_window_handle, width, height);
}
else
{
bgfx::TextureHandle texture_handles[16];
for (int i = 0; i < m_declaration.m_renderbuffers_count; ++i)
{
const RenderBuffer& renderbuffer = m_declaration.m_renderbuffers[i];
texture_handles[i] =
bgfx::createTexture2D(width, height, 1, renderbuffer.m_format, BGFX_TEXTURE_RT);
m_declaration.m_renderbuffers[i].m_handle = texture_handles[i];
}
m_window_handle = nullptr;
m_handle = bgfx::createFrameBuffer(m_declaration.m_renderbuffers_count, texture_handles);
}
}

View file

@ -253,6 +253,7 @@ struct PipelineInstanceImpl : public PipelineInstance
, m_point_light_shadowmaps(allocator)
, m_materials(allocator)
{
m_view_x = m_view_y = 0;
m_has_shadowmap_define_idx = m_renderer.getShaderDefineIdx("HAS_SHADOWMAP");
m_cam_view_uniform =
@ -409,7 +410,7 @@ struct PipelineInstanceImpl : public PipelineInstance
bgfx::setViewTransform(m_view_idx, &mtx.m11, &projection_matrix.m11);
bgfx::setViewRect(
m_view_idx, 0, 0, (uint16_t)m_width, (uint16_t)m_height);
m_view_idx, m_view_x, m_view_y, (uint16_t)m_width, (uint16_t)m_height);
}
@ -452,7 +453,7 @@ struct PipelineInstanceImpl : public PipelineInstance
}
FrameBuffer* getFramebuffer(const char* framebuffer_name)
virtual FrameBuffer* getFramebuffer(const char* framebuffer_name) override
{
for (int i = 0, c = m_framebuffers.size(); i < c; ++i)
{
@ -529,7 +530,9 @@ struct PipelineInstanceImpl : public PipelineInstance
for (int i = 0; i < m_source.m_framebuffers.size(); ++i)
{
FrameBuffer::Declaration& decl = m_source.m_framebuffers[i];
m_framebuffers.push(m_allocator.newObject<FrameBuffer>(decl));
auto* fb = m_allocator.newObject<FrameBuffer>(decl);
m_framebuffers.push(fb);
if (strcmp(decl.m_name, "default") == 0) m_default_framebuffer = fb;
}
if (lua_getglobal(m_source.m_lua_state, "init") == LUA_TFUNCTION)
@ -1128,7 +1131,7 @@ struct PipelineInstanceImpl : public PipelineInstance
bgfx::setViewTransform(
m_view_idx, &Matrix::IDENTITY.m11, &projection_mtx.m11);
bgfx::setViewRect(
m_view_idx, 0, 0, (uint16_t)m_width, (uint16_t)m_height);
m_view_idx, m_view_x, m_view_y, (uint16_t)m_width, (uint16_t)m_height);
bgfx::TransientVertexBuffer vb;
bgfx::allocTransientVertexBuffer(&vb, 6, BaseVertex::s_vertex_decl);
@ -1333,7 +1336,7 @@ struct PipelineInstanceImpl : public PipelineInstance
int first_index,
int num_indices,
Material& material,
Texture* texture) override
bgfx::TextureHandle* texture) override
{
bgfx::setState(m_render_state | material.getRenderStates());
bgfx::setTransform(nullptr);
@ -1343,7 +1346,7 @@ struct PipelineInstanceImpl : public PipelineInstance
bgfx::setTexture(
0,
material.getShader()->getTextureSlot(0).m_uniform_handle,
texture->getTextureHandle());
*texture);
}
bgfx::setVertexBuffer(&geom.getVertexBuffer(), 0, geom.getNumVertices());
bgfx::setIndexBuffer(&geom.getIndexBuffer(), first_index, num_indices);
@ -1643,18 +1646,16 @@ struct PipelineInstanceImpl : public PipelineInstance
}
virtual void resize(int w, int h) override
virtual void setViewport(int x, int y, int w, int h) override
{
m_view_x = x;
m_view_y = y;
if (m_width == w && m_height == h) return;
if (m_default_framebuffer)
{
m_default_framebuffer->resize(w, h);
}
else
{
bgfx::reset(w, h);
}
m_width = w;
m_height = h;
}
@ -1672,7 +1673,6 @@ struct PipelineInstanceImpl : public PipelineInstance
m_render_state = BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE |
BGFX_STATE_DEPTH_WRITE | BGFX_STATE_MSAA;
m_view_idx = m_renderer.getViewCounter();
bgfx::setViewClear(m_view_idx, 0);
m_pass_idx = -1;
m_current_framebuffer = m_default_framebuffer;
m_global_textures.clear();
@ -1776,6 +1776,8 @@ struct PipelineInstanceImpl : public PipelineInstance
Matrix m_shadow_viewprojection[4];
Vec4 m_shadowmap_splits;
int m_view_x;
int m_view_y;
int m_width;
int m_height;
AssociativeArray<uint32_t, CustomCommandHandler> m_custom_commands_handlers;

View file

@ -4,6 +4,8 @@
#include "core/delegate.h"
#include "core/resource.h"
#include "core/resource_manager_base.h"
#include <bgfx.h>
namespace Lumix
{
@ -67,11 +69,12 @@ class LUMIX_RENDERER_API PipelineInstance abstract
virtual ~PipelineInstance() {}
virtual void render() = 0;
virtual void resize(int w, int h) = 0;
virtual void setViewport(int x, int y, int width, int height) = 0;
static PipelineInstance* create(Pipeline& src, IAllocator& allocator);
static void destroy(PipelineInstance* pipeline);
virtual FrameBuffer* getFramebuffer(const char* framebuffer_name) = 0;
virtual void setScene(RenderScene* scene) = 0;
virtual RenderScene* getScene() = 0;
virtual int getWidth() = 0;
@ -84,7 +87,7 @@ class LUMIX_RENDERER_API PipelineInstance abstract
int first_index,
int num_indices,
Material& material,
Texture* texture) = 0;
bgfx::TextureHandle* texture) = 0;
virtual void setWireframe(bool wireframe) = 0;
virtual void renderModel(Model& model, const Matrix& mtx) = 0;
virtual void toggleStats() = 0;

View file

@ -486,6 +486,12 @@ struct RendererImpl : public Renderer
}
virtual void resize(int w, int h) override
{
bgfx::reset(w, h);
}
virtual void frame() override
{
bgfx::frame();

View file

@ -32,6 +32,7 @@ class LUMIX_RENDERER_API Renderer : public IPlugin
static void setInitData(void* data);
virtual void frame() = 0;
virtual void resize(int width, int height) = 0;
virtual int getViewCounter() const = 0;
virtual void viewCounterAdd() = 0;
virtual void makeScreenshot(const Path& filename) = 0;

View file

@ -1,4 +1,5 @@
#include "asset_browser.h"
#include "core/crc32.h"
#include "core/FS/file_iterator.h"
#include "core/FS/file_system.h"
#include "core/json_serializer.h"
@ -10,6 +11,8 @@
#include "core/system.h"
#include "editor/world_editor.h"
#include "engine/engine.h"
#include "file_system_watcher.h"
#include "lua_script/lua_script_manager.h"
#include "renderer/material.h"
#include "renderer/model.h"
#include "renderer/shader.h"
@ -17,13 +20,34 @@
#include "ocornut-imgui/imgui.h"
#include "string_builder.h"
TODO("unload m_selected_resource");
TODO("clang");
static const uint32_t UNIVERSE_HASH = Lumix::crc32("universe");
static const uint32_t LUA_SCRIPT_HASH = Lumix::crc32("lua_script");
static uint32_t getResourceType(const char* path)
{
char ext[10];
Lumix::PathUtils::getExtension(ext, sizeof(ext), path);
if (strcmp(ext, "mat") == 0) return Lumix::ResourceManager::MATERIAL;
if (strcmp(ext, "msh") == 0) return Lumix::ResourceManager::MODEL;
if (strcmp(ext, "dds") == 0) return Lumix::ResourceManager::TEXTURE;
if (strcmp(ext, "tga") == 0) return Lumix::ResourceManager::TEXTURE;
if (strcmp(ext, "shd") == 0) return Lumix::ResourceManager::SHADER;
if (strcmp(ext, "unv") == 0) return UNIVERSE_HASH;
if (strcmp(ext, "lua") == 0) return LUA_SCRIPT_HASH;
return 0;
}
AssetBrowser::AssetBrowser(Lumix::WorldEditor& editor)
: m_editor(editor)
, m_resources(editor.getAllocator())
, m_selected_resouce(nullptr)
{
TODO("detect changes");
m_is_opened = false;
for (int i = 0; i < Count; ++i)
{
@ -31,22 +55,48 @@ AssetBrowser::AssetBrowser(Lumix::WorldEditor& editor)
}
findResources();
m_watcher = FileSystemWatcher::create(editor.getBasePath(), editor.getAllocator());
m_watcher->getCallback().bind<AssetBrowser, &AssetBrowser::onFileChanged>(this);
}
static uint32_t getResourceType(const char* path)
AssetBrowser::~AssetBrowser()
{
char ext[10];
Lumix::PathUtils::getExtension(ext, sizeof(ext), path);
if (strcmp(ext, "mat") == 0) return Lumix::ResourceManager::MATERIAL;
if (strcmp(ext, "msh") == 0) return Lumix::ResourceManager::MODEL;
if (strcmp(ext, "dds") == 0) return Lumix::ResourceManager::TEXTURE;
if (strcmp(ext, "tga") == 0) return Lumix::ResourceManager::TEXTURE;
if (strcmp(ext, "shd") == 0) return Lumix::ResourceManager::SHADER;
FileSystemWatcher::destroy(m_watcher);
}
ASSERT(false);
return 0;
void AssetBrowser::onFileChanged(const char* path)
{
uint32_t resource_type = getResourceType(path);
if (resource_type == 0) return;
Lumix::Path path_obj(path);
if (!Lumix::fileExists(path))
{
int index = 0;
switch (resource_type)
{
case Lumix::ResourceManager::MODEL: index = MODEL; break;
case Lumix::ResourceManager::MATERIAL: index = MATERIAL; break;
case Lumix::ResourceManager::SHADER: index = SHADER; break;
case Lumix::ResourceManager::TEXTURE: index = TEXTURE; break;
}
if (resource_type == UNIVERSE_HASH)
index = UNIVERSE;
else if (resource_type == LUA_SCRIPT_HASH)
index = LUA_SCRIPT;
m_resources[index].eraseItemFast(path_obj);
return;
}
char dir[Lumix::MAX_PATH_LENGTH];
char filename[Lumix::MAX_PATH_LENGTH];
Lumix::PathUtils::getDir(dir, sizeof(dir), path);
Lumix::PathUtils::getFilename(filename, sizeof(filename), path);
addResource(dir, filename);
}
@ -59,13 +109,10 @@ void AssetBrowser::onGui()
ImGui::End();
return;
}
if (ImGui::Button("Refresh"))
{
findResources();
}
const char* items = "Material\0Model\0Shader\0Texture\0Universe\0";
if (ImGui::Button("Refresh")) findResources();
const char* items = "Material\0Model\0Shader\0Texture\0Universe\0Lua Script\0";
static int current_type = 0;
static char filter[128] = "";
ImGui::Combo("Type", &current_type, items);
@ -76,13 +123,10 @@ void AssetBrowser::onGui()
for (auto& resource : *resources)
{
if (filter[0] != '\0' && strstr(resource.c_str(), filter) == nullptr)
continue;
if (filter[0] != '\0' && strstr(resource.c_str(), filter) == nullptr) continue;
if (ImGui::Selectable(resource.c_str(),
m_selected_resouce
? m_selected_resouce->getPath() == resource
: false))
m_selected_resouce ? m_selected_resouce->getPath() == resource : false))
{
m_selected_resouce = m_editor.getEngine()
.getResourceManager()
@ -104,14 +148,11 @@ void AssetBrowser::saveMaterial(Lumix::Material* material)
strcpy(tmp_path, material->getPath().c_str());
strcat(tmp_path, ".tmp");
Lumix::FS::IFile* file =
fs.open(fs.getDefaultDevice(),
tmp_path,
Lumix::FS::Mode::CREATE | Lumix::FS::Mode::WRITE);
fs.open(fs.getDefaultDevice(), tmp_path, Lumix::FS::Mode::CREATE | Lumix::FS::Mode::WRITE);
if (file)
{
Lumix::DefaultAllocator allocator;
Lumix::JsonSerializer serializer(
*file,
Lumix::JsonSerializer serializer(*file,
Lumix::JsonSerializer::AccessMode::WRITE,
material->getPath().c_str(),
allocator);
@ -123,18 +164,16 @@ void AssetBrowser::saveMaterial(Lumix::Material* material)
}
else
{
Lumix::g_log_error.log("Material manager")
<< "Could not save file " << material->getPath().c_str();
Lumix::g_log_error.log("Material manager") << "Could not save file "
<< material->getPath().c_str();
}
}
bool AssetBrowser::resourceInput(const char* label, char* buf, int max_size, Type type)
{
if (ImGui::InputText(label, buf, max_size))
{
return true;
}
if (ImGui::InputText(label, buf, max_size)) return true;
ImGui::SameLine();
if (ImGui::Button(StringBuilder<30>("...##", label)))
{
@ -169,33 +208,26 @@ void AssetBrowser::onGuiMaterial()
{
auto* material = static_cast<Lumix::Material*>(m_selected_resouce);
if (ImGui::Button("Save"))
{
saveMaterial(material);
}
if (ImGui::Button("Save")) saveMaterial(material);
bool b;
if (material->hasAlphaCutoutDefine())
{
b = material->isAlphaCutout();
if (ImGui::Checkbox("Is alpha cutout", &b))
material->enableAlphaCutout(b);
if (ImGui::Checkbox("Is alpha cutout", &b)) material->enableAlphaCutout(b);
}
b = material->isBackfaceCulling();
if (ImGui::Checkbox("Is backface culling", &b))
material->enableBackfaceCulling(b);
if (ImGui::Checkbox("Is backface culling", &b)) material->enableBackfaceCulling(b);
if (material->hasShadowReceivingDefine())
{
b = material->isShadowReceiver();
if (ImGui::Checkbox("Is shadow receiver", &b))
material->enableShadowReceiving(b);
if (ImGui::Checkbox("Is shadow receiver", &b)) material->enableShadowReceiving(b);
}
b = material->isZTest();
if (ImGui::Checkbox("Z test", &b))
material->enableZTest(b);
if (ImGui::Checkbox("Z test", &b)) material->enableZTest(b);
Lumix::Vec3 specular = material->getSpecular();
if (ImGui::ColorEdit3("Specular", &specular.x))
@ -211,22 +243,17 @@ void AssetBrowser::onGuiMaterial()
char buf[256];
Lumix::copyString(
buf,
sizeof(buf),
material->getShader() ? material->getShader()->getPath().c_str() : "");
buf, sizeof(buf), material->getShader() ? material->getShader()->getPath().c_str() : "");
if (resourceInput("Shader", buf, sizeof(buf), SHADER))
{
material->setShader(Lumix::Path(buf));
}
for (int i = 0; i < material->getShader()->getTextureSlotCount();
++i)
for (int i = 0; i < material->getShader()->getTextureSlotCount(); ++i)
{
auto& slot = material->getShader()->getTextureSlot(i);
auto* texture = material->getTexture(i);
Lumix::copyString(buf,
sizeof(buf),
texture ? texture->getPath().c_str() : "");
Lumix::copyString(buf, sizeof(buf), texture ? texture->getPath().c_str() : "");
if (resourceInput(slot.m_name, buf, sizeof(buf), TEXTURE))
{
material->setTexturePath(i, Lumix::Path(buf));
@ -240,7 +267,26 @@ void AssetBrowser::onGuiTexture()
auto* texture = static_cast<Lumix::Texture*>(m_selected_resouce);
ImGui::LabelText("Size", "%dx%d", texture->getWidth(), texture->getHeight());
ImGui::LabelText("BPP", "%d", texture->getBytesPerPixel());
ImGui::Image(texture, ImVec2(200, 200));
ImGui::Image(&texture->getTextureHandle(), ImVec2(200, 200));
}
void AssetBrowser::onGuiLuaScript()
{
auto* script = static_cast<Lumix::LuaScript*>(m_selected_resouce);
char buf[4096];
Lumix::copyString(buf, sizeof(buf), script->getSourceCode());
ImGui::InputTextMultiline("Code", buf, sizeof(buf), ImVec2(0, 300));
if (ImGui::Button("Update"))
{
TODO("Update");
}
ImGui::SameLine();
if (ImGui::Button("Save"))
{
TODO("save");
}
}
@ -258,7 +304,7 @@ void AssetBrowser::onGuiModel()
for (int i = 0; i < model->getMeshCount(); ++i)
{
auto& mesh = model->getMesh(i);
if (ImGui::TreeNode(&mesh , mesh.getName()))
if (ImGui::TreeNode(&mesh, mesh.getName()))
{
ImGui::LabelText("Triangle count", "%d", mesh.getTriangleCount());
ImGui::Text(mesh.getMaterial()->getPath().c_str());
@ -276,38 +322,36 @@ void AssetBrowser::onGuiModel()
void AssetBrowser::onGuiResource()
{
if (!m_selected_resouce) return;
const char* path = m_selected_resouce->getPath().c_str();
if (ImGui::CollapsingHeader(path, nullptr, true, true))
if (!ImGui::CollapsingHeader(path, nullptr, true, true)) return;
if (m_selected_resouce->isFailure())
{
if (m_selected_resouce->isFailure())
{
ImGui::Text("Failed to load the resource");
return;
}
ImGui::Text("Failed to load the resource");
return;
}
if (m_selected_resouce->isLoading())
{
ImGui::Text("Loading...");
return;
}
if (m_selected_resouce->isLoading())
{
ImGui::Text("Loading...");
return;
}
switch (getResourceType(path))
{
case Lumix::ResourceManager::MATERIAL:
onGuiMaterial();
break;
case Lumix::ResourceManager::TEXTURE:
onGuiTexture();
break;
case Lumix::ResourceManager::MODEL:
onGuiModel();
break;
default:
auto resource_type = getResourceType(path);
switch (resource_type)
{
case Lumix::ResourceManager::MATERIAL: onGuiMaterial(); break;
case Lumix::ResourceManager::TEXTURE: onGuiTexture(); break;
case Lumix::ResourceManager::MODEL: onGuiModel(); break;
default:
if (resource_type == LUA_SCRIPT_HASH)
onGuiLuaScript();
else
ASSERT(false);
break;
}
TODO("others");
break;
}
}
@ -328,57 +372,46 @@ void AssetBrowser::addResource(const char* path, const char* filename)
Lumix::catString(fullpath, sizeof(fullpath), "/");
Lumix::catString(fullpath, sizeof(fullpath), filename);
if (strcmp(ext, "msh") == 0)
int index = -1;
if (strcmp(ext, "dds") == 0 || strcmp(ext, "tga") == 0) index = TEXTURE;
if (strcmp(ext, "msh") == 0) index = MODEL;
if (strcmp(ext, "mat") == 0) index = MATERIAL;
if (strcmp(ext, "unv") == 0) index = UNIVERSE;
if (strcmp(ext, "shd") == 0) index = SHADER;
if (strcmp(ext, "lua") == 0) index = LUA_SCRIPT;
if (index >= 0)
{
m_resources[MODEL].push(Lumix::Path(fullpath));
return;
}
if (strcmp(ext, "dds") == 0 || strcmp(ext, "tga") == 0)
{
m_resources[TEXTURE].push(Lumix::Path(fullpath));
return;
}
if (strcmp(ext, "mat") == 0)
{
m_resources[MATERIAL].push(Lumix::Path(fullpath));
return;
}
if (strcmp(ext, "unv") == 0)
{
m_resources[UNIVERSE].push(Lumix::Path(fullpath));
return;
}
if (strcmp(ext, "shd") == 0)
{
m_resources[SHADER].push(Lumix::Path(fullpath));
return;
Lumix::Path path_obj(fullpath);
if (m_resources[index].indexOf(path_obj) == -1)
{
m_resources[index].push(path_obj);
}
}
}
void AssetBrowser::processDir(const char* path)
void AssetBrowser::processDir(const char* dir)
{
auto* iter = Lumix::FS::createFileIterator(path, m_editor.getAllocator());
auto* iter = Lumix::FS::createFileIterator(dir, m_editor.getAllocator());
Lumix::FS::FileInfo info;
while (Lumix::FS::getNextFile(iter, &info))
{
if (info.filename[0] == '.')
continue;
if (info.filename[0] == '.') continue;
if (info.is_directory)
{
char child_path[Lumix::MAX_PATH_LENGTH];
Lumix::copyString(child_path, sizeof(child_path), path);
Lumix::copyString(child_path, sizeof(child_path), dir);
Lumix::catString(child_path, sizeof(child_path), "/");
Lumix::catString(child_path, sizeof(child_path), info.filename);
processDir(child_path);
}
else
{
addResource(path, info.filename);
addResource(dir, info.filename);
}
}
Lumix::FS::destroyFileIterator(iter);

View file

@ -11,6 +11,9 @@ namespace Lumix
}
class FileSystemWatcher;
class AssetBrowser
{
public:
@ -21,12 +24,14 @@ public:
SHADER,
TEXTURE,
UNIVERSE,
LUA_SCRIPT,
Count
};
public:
AssetBrowser(Lumix::WorldEditor& editor);
~AssetBrowser();
void onGui();
const Lumix::Array<Lumix::Path>& getResources(Type type) const;
@ -34,6 +39,7 @@ public:
bool m_is_opened;
private:
void onFileChanged(const char* path);
void findResources();
void processDir(const char* path);
void addResource(const char* path, const char* filename);
@ -41,6 +47,7 @@ private:
void onGuiMaterial();
void onGuiModel();
void onGuiTexture();
void onGuiLuaScript();
void saveMaterial(Lumix::Material* material);
bool resourceInput(const char* label, char* buf, int max_size, Type type);
@ -48,4 +55,5 @@ private:
Lumix::Array<Lumix::Array<Lumix::Path> > m_resources;
Lumix::Resource* m_selected_resouce;
Lumix::WorldEditor& m_editor;
FileSystemWatcher* m_watcher;
};

View file

@ -25,13 +25,6 @@
typedef StringBuilder<Lumix::MAX_PATH_LENGTH> PathBuilder;
TODO("todo");
// TODO
// profiler
// release mode
// game mode :(
enum class VertexAttributeDef : uint32_t
{
POSITION,

View file

@ -16,12 +16,14 @@
#include "import_asset_dialog.h"
#include "log_ui.h"
#include "profiler_ui.h"
#include "renderer/frame_buffer.h"
#include "renderer/material.h"
#include "renderer/pipeline.h"
#include "renderer/renderer.h"
#include "renderer/texture.h"
#include "renderer/transient_geometry.h"
#include "ocornut-imgui/imgui.h"
#include "scene_view.h"
#include "shader_compiler.h"
#include "string_builder.h"
#include "terrain_editor.h"
@ -36,6 +38,7 @@
void imGuiCallback(ImDrawData* draw_data);
LRESULT WINAPI msgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
class Context
@ -52,6 +55,7 @@ public:
, m_is_wireframe(false)
, m_is_entity_template_list_opened(false)
, m_selected_template_name(m_allocator)
, m_is_gameview_opened(true)
{
}
@ -97,13 +101,36 @@ public:
showPropertyGrid();
showEntityList();
showEntityTemplateList();
m_sceneview.onGui();
showGameView();
if (m_is_style_editor_shown) ImGui::ShowStyleEditor();
showStats();
ImGui::Render();
}
void showGameView()
{
m_is_gameview_opened = false;
if (ImGui::Begin("Game view"))
{
m_is_gameview_hovered = ImGui::IsWindowHovered();
m_is_gameview_opened = true;
auto size = ImGui::GetContentRegionAvail();
auto pos = ImGui::GetWindowPos();
auto cp = ImGui::GetCursorPos();
int gameview_x = int(pos.x + cp.x);
int gameview_y = int(pos.y + cp.y);
m_game_pipeline->setViewport(0, 0, int(size.x), int(size.y));
auto* fb = m_game_pipeline->getFramebuffer("default");
m_gameview_texture_handle = fb->getRenderbufferHandle(0);
ImGui::Image(&m_gameview_texture_handle, size);
}
ImGui::End();
}
void showMainMenu()
{
@ -200,7 +227,14 @@ public:
if (ImGui::BeginMenu("Tools"))
{
bool b = m_editor->isMeasureToolActive();
bool b = m_editor->isGameMode();
if (ImGui::MenuItem("Game mode", "Ctrl - P", &b))
{
toggleGameMode();
}
b = m_editor->isMeasureToolActive();
if (ImGui::MenuItem("Measure", nullptr, &b))
{
m_editor->toggleMeasure();
@ -219,15 +253,14 @@ public:
if (ImGui::BeginMenu("View"))
{
if (ImGui::MenuItem("Look at selected",
"Ctrl - F",
nullptr,
is_any_entity_selected))
if (ImGui::MenuItem(
"Look at selected", "Ctrl - F", nullptr, is_any_entity_selected))
{
m_editor->lookAtSelected();
}
if (ImGui::MenuItem("Wireframe", "Ctrl - W", &m_is_wireframe)) m_pipeline->setWireframe(m_is_wireframe);
if (ImGui::MenuItem("Stats")) m_pipeline->toggleStats();
if (ImGui::MenuItem("Wireframe", "Ctrl - W", &m_is_wireframe))
m_gui_pipeline->setWireframe(m_is_wireframe);
if (ImGui::MenuItem("Stats")) m_gui_pipeline->toggleStats();
if (ImGui::BeginMenu("Windows"))
{
ImGui::MenuItem("Asset browser", nullptr, &m_asset_browser->m_is_opened);
@ -247,6 +280,12 @@ public:
}
void toggleGameMode()
{
m_editor->toggleGameMode();
}
const char* getComponentTypeName(Lumix::ComponentUID cmp)
{
for (int i = 0; i < m_engine->getComponentTypesCount(); ++i)
@ -663,15 +702,22 @@ public:
delete m_log_ui;
delete m_import_asset_dialog;
delete m_shader_compiler;
m_sceneview.shutdown();
Lumix::WorldEditor::destroy(m_editor);
Lumix::PipelineInstance::destroy(m_pipeline);
m_pipeline_source->getResourceManager()
Lumix::PipelineInstance::destroy(m_gui_pipeline);
Lumix::PipelineInstance::destroy(m_game_pipeline);
m_gui_pipeline_source->getResourceManager()
.get(Lumix::ResourceManager::PIPELINE)
->unload(*m_pipeline_source);
->unload(*m_gui_pipeline_source);
m_game_pipeline_source->getResourceManager()
.get(Lumix::ResourceManager::PIPELINE)
->unload(*m_game_pipeline_source);
Lumix::Engine::destroy(m_engine);
m_engine = nullptr;
m_pipeline = nullptr;
m_pipeline_source = nullptr;
m_gui_pipeline = nullptr;
m_game_pipeline = nullptr;
m_gui_pipeline_source = nullptr;
m_game_pipeline_source = nullptr;
m_editor = nullptr;
}
@ -742,25 +788,23 @@ public:
void onUniverseCreated()
{
m_pipeline->setScene(static_cast<Lumix::RenderScene*>(
m_editor->getScene(Lumix::crc32("renderer"))));
auto* scene =
static_cast<Lumix::RenderScene*>(m_editor->getScene(Lumix::crc32("renderer")));
m_sceneview.setScene(scene);
m_gui_pipeline->setScene(scene);
m_game_pipeline->setScene(scene);
}
void onUniverseDestroyed()
{
m_pipeline->setScene(nullptr);
m_sceneview.setScene(nullptr);
m_gui_pipeline->setScene(nullptr);
m_game_pipeline->setScene(nullptr);
}
void renderGizmos()
{
m_editor->renderIcons(*m_pipeline);
m_editor->getGizmo().updateScale(m_editor->getEditCamera().index);
m_editor->getGizmo().render(*m_pipeline);
}
void init(HWND win)
{
Lumix::Renderer::setInitData(win);
@ -777,24 +821,33 @@ public:
m_editor->universeCreated().bind<Context, &Context::onUniverseCreated>(this);
m_editor->universeDestroyed().bind<Context, &Context::onUniverseDestroyed>(this);
m_pipeline_source = static_cast<Lumix::Pipeline*>(
m_engine->getResourceManager()
.get(Lumix::ResourceManager::PIPELINE)
->load(Lumix::Path("pipelines/main.lua")));
m_pipeline = Lumix::PipelineInstance::create(*m_pipeline_source,
auto* pipeline_manager =
m_engine->getResourceManager().get(Lumix::ResourceManager::PIPELINE);
m_gui_pipeline_source = static_cast<Lumix::Pipeline*>(
pipeline_manager->load(Lumix::Path("pipelines/imgui.lua")));
m_gui_pipeline = Lumix::PipelineInstance::create(*m_gui_pipeline_source,
m_engine->getAllocator());
m_pipeline->addCustomCommandHandler("render_gizmos")
.bind<Context, &Context::renderGizmos>(this);
m_sceneview.init(*m_editor);
m_game_pipeline_source = static_cast<Lumix::Pipeline*>(
pipeline_manager->load(Lumix::Path("pipelines/game_view.lua")));
m_game_pipeline = Lumix::PipelineInstance::create(
*m_game_pipeline_source, m_engine->getAllocator());
RECT rect;
GetClientRect(win, &rect);
m_pipeline->resize(rect.right, rect.bottom);
m_gui_pipeline->setViewport(0, 0, rect.right, rect.bottom);
m_game_pipeline->setViewport(0, 0, rect.right, rect.bottom);
onUniverseCreated();
initIMGUI(win);
}
void checkShortcuts()
{
if (ImGui::IsAnyItemActive()) return;
if (ImGui::GetIO().KeysDown[VK_DELETE])
{
if (!m_editor->getSelectedEntities().empty())
@ -809,8 +862,11 @@ public:
if (ImGui::GetIO().KeysDown['W'])
{
m_is_wireframe = !m_is_wireframe;
m_pipeline->setWireframe(m_is_wireframe);
m_gui_pipeline->setWireframe(m_is_wireframe);
}
if (ImGui::GetIO().KeysDown['P'])
{
toggleGameMode();
}
if (ImGui::GetIO().KeysDown['C'])
{
@ -847,41 +903,21 @@ public:
}
void updateNavigation()
{
if (ImGui::IsMouseHoveringAnyWindow()) return;
if (ImGui::GetIO().KeysDown[VK_CONTROL]) return;
float speed = 0.1f;
if (ImGui::GetIO().KeysDown[VK_SHIFT])
{
speed *= 10;
}
if (ImGui::GetIO().KeysDown['W'])
{
m_editor->navigate(1.0f, 0, speed);
}
if (ImGui::GetIO().KeysDown['S'])
{
m_editor->navigate(-1.0f, 0, speed);
}
if (ImGui::GetIO().KeysDown['A'])
{
m_editor->navigate(0.0f, -1.0f, speed);
}
if (ImGui::GetIO().KeysDown['D'])
{
m_editor->navigate(0.0f, 1.0f, speed);
}
}
HWND m_hwnd;
HINSTANCE m_instance;
bgfx::VertexDecl m_decl;
Lumix::Material* m_material;
Lumix::Engine* m_engine;
Lumix::Pipeline* m_pipeline_source;
Lumix::PipelineInstance* m_pipeline;
SceneView m_sceneview;
Lumix::Pipeline* m_gui_pipeline_source;
Lumix::PipelineInstance* m_gui_pipeline;
Lumix::Pipeline* m_game_pipeline_source;
Lumix::PipelineInstance* m_game_pipeline;
bgfx::TextureHandle m_gameview_texture_handle;
Lumix::DefaultAllocator m_main_allocator;
Lumix::Debug::Allocator m_allocator;
Lumix::WorldEditor* m_editor;
@ -895,6 +931,8 @@ public:
bool m_finished;
bool m_is_gameview_hovered;
bool m_is_gameview_opened;
bool m_is_property_grid_shown;
bool m_is_entity_list_shown;
bool m_is_entity_template_list_opened;
@ -919,7 +957,7 @@ static void imGuiCallback(ImDrawData* draw_data)
Lumix::Matrix ortho;
ortho.setOrtho(0.0f, width, 0.0f, height, -1.0f, 1.0f);
g_context.m_pipeline->setViewProjection(ortho, (int)width, (int)height);
g_context.m_gui_pipeline->setViewProjection(ortho, (int)width, (int)height);
for (int32_t ii = 0; ii < draw_data->CmdListsCount; ++ii)
{
@ -952,7 +990,7 @@ static void imGuiCallback(ImDrawData* draw_data)
continue;
}
g_context.m_pipeline->setScissor(
g_context.m_gui_pipeline->setScissor(
uint16_t(Lumix::Math::maxValue(pcmd->ClipRect.x, 0.0f)),
uint16_t(Lumix::Math::maxValue(pcmd->ClipRect.y, 0.0f)),
uint16_t(Lumix::Math::minValue(pcmd->ClipRect.z, 65535.0f) -
@ -960,8 +998,8 @@ static void imGuiCallback(ImDrawData* draw_data)
uint16_t(Lumix::Math::minValue(pcmd->ClipRect.w, 65535.0f) -
Lumix::Math::maxValue(pcmd->ClipRect.y, 0.0f)));
g_context.m_pipeline->render(
geom, elem_offset, pcmd->ElemCount, *g_context.m_material, (Lumix::Texture*)pcmd->TextureId);
g_context.m_gui_pipeline->render(
geom, elem_offset, pcmd->ElemCount, *g_context.m_material, (bgfx::TextureHandle*)pcmd->TextureId);
elem_offset += pcmd->ElemCount;
}
@ -975,7 +1013,7 @@ LRESULT WINAPI msgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
int y = HIWORD(lParam);
static int old_x = x;
static int old_y = y;
if (!g_context.m_pipeline)
if (!g_context.m_gui_pipeline)
{
return DefWindowProc(hWnd, msg, wParam, lParam);
}
@ -989,7 +1027,11 @@ LRESULT WINAPI msgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
uint32_t width = ((int)(short)LOWORD(lParam));
uint32_t height = ((int)(short)HIWORD(lParam));
g_context.m_pipeline->resize(width, height);
g_context.m_gui_pipeline->setViewport(0, 0, width, height);
auto& plugin_manager = g_context.m_editor->getEngine().getPluginManager();
auto* renderer = static_cast<Lumix::Renderer*>(plugin_manager.getPlugin("renderer"));
renderer->resize(width, height);
}
break;
case WM_MOUSEWHEEL:
@ -998,44 +1040,38 @@ LRESULT WINAPI msgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
case WM_ERASEBKGND:
return 1;
case WM_LBUTTONUP:
g_context.m_editor->onMouseUp(old_x, old_y, Lumix::MouseButton::LEFT);
g_context.m_sceneview.onMouseUp(Lumix::MouseButton::LEFT);
ImGui::GetIO().MouseDown[0] = false;
break;
case WM_LBUTTONDOWN:
if (!ImGui::IsMouseHoveringAnyWindow())
if (!g_context.m_sceneview.onMouseDown(old_x, old_y, Lumix::MouseButton::LEFT))
{
g_context.m_editor->onMouseDown(old_x, old_y, Lumix::MouseButton::LEFT);
ImGui::GetIO().MouseDown[0] = true;
}
ImGui::GetIO().MouseDown[0] = true;
break;
case WM_RBUTTONDOWN:
if (!ImGui::IsMouseHoveringAnyWindow())
if (!g_context.m_sceneview.onMouseDown(old_x, old_y, Lumix::MouseButton::RIGHT))
{
g_context.m_editor->onMouseDown(old_x, old_y, Lumix::MouseButton::RIGHT);
ImGui::GetIO().MouseDown[1] = true;
}
ImGui::GetIO().MouseDown[1] = true;
break;
case WM_RBUTTONUP:
g_context.m_editor->onMouseUp(old_x, old_y, Lumix::MouseButton::RIGHT);
g_context.m_sceneview.onMouseUp(Lumix::MouseButton::RIGHT);
ImGui::GetIO().MouseDown[1] = false;
break;
case WM_MOUSEMOVE:
{
int flags = ImGui::GetIO().KeysDown[VK_MENU]
? (int)Lumix::WorldEditor::MouseFlags::ALT
: 0;
g_context.m_editor->onMouseMove(x, y, x - old_x, y - old_y, flags);
g_context.m_sceneview.onMouseMove(x, y, x - old_x, y - old_y);
auto& input_system = g_context.m_engine->getInputSystem();
input_system.injectMouseXMove(float(old_x - x));
input_system.injectMouseYMove(float(old_y - y));
old_x = x;
old_y = y;
{
ImGuiIO& io = ImGui::GetIO();
io.MousePos.x = (float)x;
io.MousePos.y = (float)y;
}
ImGuiIO& io = ImGui::GetIO();
io.MousePos.x = (float)x;
io.MousePos.y = (float)y;
}
break;
case WM_CHAR:
@ -1096,9 +1132,9 @@ INT WINAPI WinMain(HINSTANCE hInst,
NULL,
hInst,
0);
auto e = GetLastError();
ASSERT(hwnd);
g_context.m_instance = hInst;
g_context.init(hwnd);
SetWindowTextA(hwnd, "Lumix Sample app");
@ -1123,13 +1159,15 @@ INT WINAPI WinMain(HINSTANCE hInst,
}
g_context.m_editor->update();
g_context.updateNavigation();
g_context.m_sceneview.update();
g_context.m_engine->update(*g_context.m_editor->getUniverseContext());
g_context.update();
g_context.m_gui_pipeline->render();
g_context.onGUI();
if (g_context.m_is_gameview_opened) g_context.m_game_pipeline->render();
Lumix::Renderer* renderer = static_cast<Lumix::Renderer*>(
g_context.m_engine->getPluginManager().getPlugin("renderer"));
g_context.m_engine->update(*g_context.m_editor->getUniverseContext());
g_context.m_pipeline->render();
g_context.update();
g_context.onGUI();
renderer->frame();
Lumix::g_profiler.frame();
}

View file

@ -6598,7 +6598,7 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge
for (int n = 0; n < res_w; n++)
{
const float t1 = t0 + t_step;
const int v_idx = (int)(t0 * values_count);
const int v_idx = (int)(t0 * values_count + 0.5f);
IM_ASSERT(v_idx >= 0 && v_idx < values_count);
const float v1 = values_getter(data, (v_idx + values_offset + 1) % values_count);
const ImVec2 p1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) / (scale_max - scale_min)) );

View file

@ -133,6 +133,8 @@ int FileSystemWatcherTask::task()
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
nullptr);
if (m_handle == INVALID_HANDLE_VALUE) return -1;
bool finished = false;
while (!finished)
{
@ -155,6 +157,7 @@ int FileSystemWatcherTask::task()
case FILE_ACTION_RENAMED_NEW_NAME:
case FILE_ACTION_ADDED:
case FILE_ACTION_MODIFIED:
case FILE_ACTION_REMOVED:
{
char tmp[MAX_PATH];
wcharToCharArray(
@ -163,7 +166,6 @@ int FileSystemWatcherTask::task()
}
break;
case FILE_ACTION_RENAMED_OLD_NAME:
case FILE_ACTION_REMOVED:
break;
default:
ASSERT(false);

View file

@ -1,14 +1,23 @@
#include "profiler_ui.h"
#include "core/math_utils.h"
#include "ocornut-imgui/imgui.h"
#include "string_builder.h"
static const int MAX_FRAMES = 200;
enum Column
{
NAME,
TIME
};
ProfilerUI::ProfilerUI()
{
m_is_opened = false;
m_current_block = nullptr;
Lumix::g_profiler.getFrameListeners().bind<ProfilerUI, &ProfilerUI::onFrame>(this);
}
@ -112,23 +121,47 @@ void ProfilerUI::onFrame()
}
void ProfilerUI::showProfileBlock(Block* block) const
void ProfilerUI::showProfileBlock(Block* block, int column)
{
while (block)
if (column == NAME)
{
if (ImGui::TreeNode(block, block->m_name))
while (block)
{
showProfileBlock(block->m_first_child);
ImGui::TreePop();
if (ImGui::TreeNode(block->m_name))
{
block->m_is_opened = true;
showProfileBlock(block->m_first_child, column);
ImGui::TreePop();
}
else
{
block->m_is_opened = false;
}
block = block->m_next;
}
if (!block->m_hit_counts.empty())
return;
}
if (column == TIME)
{
while (block)
{
ImGui::SameLine();
ImGui::Text("%d", block->m_hit_counts.back());
ImGui::SameLine();
ImGui::Text("%f", block->m_frames.back());
if (ImGui::Selectable(
StringBuilder<50>("") << block->m_frames.back() << "##t"
<< (int64_t)block,
m_current_block == block,
ImGuiSelectableFlags_SpanAllColumns))
{
m_current_block = block;
}
if (block->m_is_opened)
{
showProfileBlock(block->m_first_child, column);
}
block = block->m_next;
}
block = block->m_next;
}
}
@ -146,7 +179,12 @@ void ProfilerUI::onGui()
}
if (m_root)
{
showProfileBlock(m_root);
ImGui::Columns(2);
showProfileBlock(m_root, NAME);
ImGui::NextColumn();
showProfileBlock(m_root, TIME);
ImGui::NextColumn();
ImGui::Columns(1);
}
if (m_root)
@ -157,20 +195,31 @@ void ProfilerUI::onGui()
times[i] = m_root->m_frames[i];
}
auto getter = [](void* data, int idx) -> float {
auto* block = (Block*)data;
return block->m_frames[idx];
auto* block = m_current_block ? m_current_block : m_root;
float width = ImGui::GetWindowContentRegionWidth();
int count = Lumix::Math::minValue(/*int(width / 5)*/40, block->m_hit_counts.size());
int offset = block->m_hit_counts.size() - count;
struct PlotData
{
Block* block;
int offset;
};
auto getter = [](void* data, int idx) -> float {
auto* plot_data = (PlotData*)data;
return plot_data->block->m_frames[plot_data->offset + idx];
};
PlotData plot_data;
plot_data.block = block;
plot_data.offset = offset;
ImGui::PlotHistogram("",
getter,
m_root,
m_root->m_hit_counts.size(),
&plot_data,
count,
0,
block->m_name,
0,
nullptr,
FLT_MAX,
FLT_MAX,
ImVec2(0, 100));
ImVec2(width, 100));
}
}
ImGui::End();

View file

@ -42,16 +42,18 @@ private:
Block* m_parent;
Block* m_first_child;
Block* m_next;
bool m_is_opened;
Lumix::Array<float> m_frames;
Lumix::Array<int> m_hit_counts;
};
private:
void onFrame();
void showProfileBlock(ProfilerUI::Block* block) const;
void showProfileBlock(ProfilerUI::Block* block, int column);
void cloneBlock(Block* my_block, Lumix::Profiler::Block* remote_block);
private:
Lumix::DefaultAllocator m_allocator;
Block* m_root;
Block* m_current_block;
};

View file

@ -0,0 +1,161 @@
#include "scene_view.h"
#include "core/resource_manager.h"
#include "editor/gizmo.h"
#include "editor/world_editor.h"
#include "engine/engine.h"
#include "ocornut-imgui/imgui.h"
#include "renderer/frame_buffer.h"
#include "renderer/pipeline.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
static const char* WINDOW_NAME = "Scene view";
SceneView::SceneView()
{
m_pipeline = nullptr;
m_editor = nullptr;
}
SceneView::~SceneView()
{
}
void SceneView::setScene(Lumix::RenderScene* scene)
{
m_pipeline->setScene(scene);
}
void SceneView::shutdown()
{
Lumix::PipelineInstance::destroy(m_pipeline);
m_pipeline_source->getResourceManager()
.get(Lumix::ResourceManager::PIPELINE)
->unload(*m_pipeline_source);
}
bool SceneView::init(Lumix::WorldEditor& editor)
{
m_editor = &editor;
auto& engine = editor.getEngine();
auto& allocator = engine.getAllocator();
auto* pipeline_manager = engine.getResourceManager().get(Lumix::ResourceManager::PIPELINE);
m_pipeline_source =
static_cast<Lumix::Pipeline*>(pipeline_manager->load(Lumix::Path("pipelines/main.lua")));
m_pipeline = Lumix::PipelineInstance::create(*m_pipeline_source, allocator);
m_pipeline->addCustomCommandHandler("render_gizmos")
.bind<SceneView, &SceneView::renderGizmos>(this);
return true;
}
void SceneView::update()
{
if(ImGui::IsAnyItemActive()) return;
if (!m_is_opened) return;
if (ImGui::GetIO().KeysDown[VK_CONTROL]) return;
int screen_x = int(ImGui::GetIO().MousePos.x);
int screen_y = int(ImGui::GetIO().MousePos.y);
bool is_inside = screen_x >= m_screen_x && screen_y >= m_screen_y &&
screen_x <= m_screen_x + m_width && screen_y <= m_screen_y + m_height;
if (!is_inside) return;
float speed = 0.1f;
if (ImGui::GetIO().KeysDown[VK_SHIFT])
{
speed *= 10;
}
if (ImGui::GetIO().KeysDown['W'])
{
m_editor->navigate(1.0f, 0, speed);
}
if (ImGui::GetIO().KeysDown['S'])
{
m_editor->navigate(-1.0f, 0, speed);
}
if (ImGui::GetIO().KeysDown['A'])
{
m_editor->navigate(0.0f, -1.0f, speed);
}
if (ImGui::GetIO().KeysDown['D'])
{
m_editor->navigate(0.0f, 1.0f, speed);
}
}
void SceneView::renderGizmos()
{
m_editor->renderIcons(*m_pipeline);
m_editor->getGizmo().updateScale(m_editor->getEditCamera().index);
m_editor->getGizmo().render(*m_pipeline);
}
void SceneView::onMouseUp(Lumix::MouseButton::Value button)
{
auto pos = ImGui::GetIO().MousePos;
m_editor->onMouseUp(int(pos.x) - m_screen_x, int(pos.y) - m_screen_y, button);
}
bool SceneView::onMouseDown(int screen_x, int screen_y, Lumix::MouseButton::Value button)
{
if (!m_is_mouse_hovering_window) return false;
bool is_inside = screen_x >= m_screen_x && screen_y >= m_screen_y &&
screen_x <= m_screen_x + m_width && screen_y <= m_screen_y + m_height;
if (!is_inside) return false;
ImGui::SetWindowFocus(WINDOW_NAME);
m_editor->onMouseDown(screen_x - m_screen_x, screen_y - m_screen_y, button);
return true;
}
void SceneView::onMouseMove(int mouse_screen_x, int mouse_screen_y, int rel_x, int rel_y)
{
int flags = ImGui::GetIO().KeysDown[VK_MENU]
? (int)Lumix::WorldEditor::MouseFlags::ALT
: 0;
m_editor->onMouseMove(
mouse_screen_x - m_screen_x, mouse_screen_y - m_screen_y, rel_x, rel_y, flags);
}
void SceneView::onGui()
{
m_is_opened = false;
m_is_mouse_hovering_window = false;
if (ImGui::Begin(WINDOW_NAME))
{
m_is_mouse_hovering_window = ImGui::IsMouseHoveringWindow();
m_is_opened = true;
auto size = ImGui::GetContentRegionAvail();
auto pos = ImGui::GetWindowPos();
auto cp = ImGui::GetCursorPos();
m_pipeline->setViewport(0, 0, int(size.x), int(size.y));
auto* fb = m_pipeline->getFramebuffer("default");
m_texture_handle = fb->getRenderbufferHandle(0);
auto cursor_pos = ImGui::GetCursorScreenPos();
m_screen_x = int(cursor_pos.x);
m_screen_y = int(cursor_pos.y);
m_width = int(size.x);
m_height = int(size.x);
ImGui::Image(&m_texture_handle, size);
m_pipeline->render();
}
ImGui::End();
}

View file

@ -0,0 +1,46 @@
#pragma once
#include "editor/world_editor.h"
#include <bgfx.h>
namespace Lumix
{
class Pipeline;
class PipelineInstance;
class RenderScene;
class WorldEditor;
}
class SceneView
{
public:
SceneView();
~SceneView();
void update();
bool init(Lumix::WorldEditor& editor);
void setScene(Lumix::RenderScene* scene);
void shutdown();
void onGui();
void onMouseUp(Lumix::MouseButton::Value button);
bool onMouseDown(int screen_x, int screen_y, Lumix::MouseButton::Value button);
void onMouseMove(int screen_x, int screen_y, int rel_x, int rel_y);
private:
void renderGizmos();
private:
bool m_is_mouse_hovering_window;
bool m_is_opened;
int m_screen_x;
int m_screen_y;
int m_width;
int m_height;
Lumix::WorldEditor* m_editor;
Lumix::PipelineInstance* m_pipeline;
Lumix::Pipeline* m_pipeline_source;
bgfx::TextureHandle m_texture_handle;
};

View file

@ -60,6 +60,12 @@ struct StringBuilder
Lumix::catString(data, size, value);
}
void add(float value)
{
int len = (int)strlen(data);
Lumix::toCString(value, data + len, size - len, 3);
}
template <typename T>
void add(T value)
{

View file

@ -67,7 +67,7 @@ void GameView::resizeEvent(QResizeEvent* event)
int h = event->size().height();
if (m_render_device)
{
m_render_device->getPipeline().resize(w, h);
m_render_device->getPipeline().setViewport(0, 0, w, h);
}
}

View file

@ -233,6 +233,6 @@ void SceneView::resizeEvent(QResizeEvent*)
{
if (getPipeline())
{
getPipeline()->resize(m_view->width(), m_view->height());
getPipeline()->setViewport(0, 0, m_view->width(), m_view->height());
}
}

View file

@ -41,7 +41,7 @@ WGLRenderDevice::~WGLRenderDevice()
void WGLRenderDevice::setWidget(QWidget& widget)
{
auto handle = (HWND)widget.winId();
getPipeline().resize(widget.width(), widget.height());
getPipeline().setViewport(0, 0, widget.width(), widget.height());
getPipeline().setWindowHandle(handle);
}