This commit is contained in:
Mikulas Florek 2020-03-07 22:43:33 +01:00
parent 64b42d50dd
commit fca630d849
11 changed files with 74 additions and 223 deletions

View file

@ -242,7 +242,7 @@ struct GridUIVisitor final : Reflection::IPropertyVisitor
EntityPtr entity = prop.get(cmp, m_index);
char buf[128];
getEntityListDisplayName(m_editor, Span(buf), entity);
getEntityListDisplayName(m_app, Span(buf), entity);
ImGui::PushID(prop.name);
float item_w = ImGui::CalcItemWidth();
@ -275,7 +275,7 @@ struct GridUIVisitor final : Reflection::IPropertyVisitor
ImGui::InputTextWithHint("##filter", "Filter", entity_filter, sizeof(entity_filter));
for (EntityPtr i = universe.getFirstEntity(); i.isValid(); i = universe.getNextEntity((EntityRef)i))
{
getEntityListDisplayName(m_editor, Span(buf), i);
getEntityListDisplayName(m_app, Span(buf), i);
bool show = entity_filter[0] == '\0' || stristr(buf, entity_filter) != 0;
if (show && ImGui::Selectable(buf))
{
@ -566,7 +566,7 @@ bool PropertyGrid::entityInput(const char* label, const char* str_id, EntityPtr&
ImGui::PushItemWidth(
item_w - ImGui::CalcTextSize("...").x - style.FramePadding.x * 2 - style.ItemSpacing.x);
char buf[50];
getEntityListDisplayName(m_editor, Span(buf), entity);
getEntityListDisplayName(m_app, Span(buf), entity);
ImGui::LabelText("", "%s", buf);
ImGui::SameLine();
StaticString<30> popup_name("pu", str_id);
@ -613,7 +613,7 @@ bool PropertyGrid::entityInput(const char* label, const char* str_id, EntityPtr&
{
for (EntityPtr i = universe->getFirstEntity(); i.isValid(); i = universe->getNextEntity((EntityRef)i))
{
getEntityListDisplayName(m_editor, Span(buf), i);
getEntityListDisplayName(m_app, Span(buf), i);
if (stristr(buf, entity_filter) == nullptr) continue;
if (ImGui::Selectable(buf))
{
@ -629,7 +629,7 @@ bool PropertyGrid::entityInput(const char* label, const char* str_id, EntityPtr&
{
for (EntityPtr i = universe->getFirstEntity(); i.isValid(); i = universe->getNextEntity((EntityRef)i))
{
getEntityListDisplayName(m_editor, Span(buf), i);
getEntityListDisplayName(m_app, Span(buf), i);
if (ImGui::Selectable(buf))
{
ImGui::ListBoxFooter();
@ -678,7 +678,7 @@ void PropertyGrid::showCoreProperties(const Array<EntityRef>& entities) const
EntityPtr parent = m_editor.getUniverse()->getParent(entities[0]);
if (parent.isValid())
{
getEntityListDisplayName(m_editor, Span(name), parent);
getEntityListDisplayName(m_app, Span(name), parent);
ImGui::LabelText("Parent", "%s", name);
Transform tr = m_editor.getUniverse()->getLocalTransform(entities[0]);

View file

@ -1,54 +1,23 @@
#pragma once
#include "engine/lumix.h"
#include "engine/math.h"
#include "editor/world_editor.h"
struct ImFont;
using ImTextureID = void*;
namespace Lumix {
namespace Lumix
{
struct AABB;
struct Pose;
struct Path;
struct ShiftedFrustum;
struct RenderInterface
{
using ModelHandle = int;
struct Vertex
{
Vec3 position;
u32 color;
};
struct RenderInterface {
virtual ~RenderInterface() {}
virtual AABB getEntityAABB(Universe& universe, EntityRef entity, const DVec3& base) = 0;
virtual float getCameraFOV(EntityRef entity) = 0;
virtual bool isCameraOrtho(EntityRef entity) = 0;
virtual float getCameraOrthoSize(EntityRef entity) = 0;
virtual Vec2 getCameraScreenSize(EntityRef entity) = 0;
virtual Vec3 getModelCenter(EntityRef entity) = 0;
virtual bool saveTexture(Engine& engine, const char* path, const void* pixels, int w, int h, bool upper_left_origin) = 0;
virtual struct AABB getEntityAABB(Universe& universe, EntityRef entity, const DVec3& base) = 0;
virtual ImTextureID createTexture(const char* name, const void* pixels, int w, int h) = 0;
virtual void destroyTexture(ImTextureID handle) = 0;
virtual ImTextureID loadTexture(const Path& path) = 0;
virtual ImTextureID loadTexture(const struct Path& path) = 0;
virtual bool isValid(ImTextureID texture) = 0;
virtual void unloadTexture(ImTextureID handle) = 0;
virtual UniverseView::RayHit castRay(const DVec3& origin, const Vec3& dir, EntityPtr ignored) = 0;
virtual Path getModelInstancePath(EntityRef entity) = 0;
virtual ImFont* addFont(const char* filename, int size) = 0;
virtual ShiftedFrustum getFrustum(EntityRef camera, const Vec2& a, const Vec2& b) = 0;
virtual void setUniverse(Universe* universe) = 0;
virtual UniverseView::RayHit castRay(Universe& universe, const DVec3& origin, const Vec3& dir, EntityPtr ignored) = 0;
virtual Path getModelInstancePath(Universe& universe, EntityRef entity) = 0;
};
}

View file

@ -826,13 +826,12 @@ struct StudioAppImpl final : StudioApp
Universe* universe = m_editor->getUniverse();
RenderInterface* ri = m_editor->getRenderInterface();
UniverseView& view = m_editor->getView();
const DVec3 cam_pos = view.getViewport().pos;
if (ents.size() > 1) {
AABB aabb = ri->getEntityAABB(*universe, ents[0], cam_pos);
AABB aabb = m_render_interface->getEntityAABB(*universe, ents[0], cam_pos);
for (int i = 1; i < ents.size(); ++i) {
const AABB entity_aabb = ri->getEntityAABB(*universe, ents[i], cam_pos);
const AABB entity_aabb = m_render_interface->getEntityAABB(*universe, ents[i], cam_pos);
aabb.merge(entity_aabb);
}
@ -1195,7 +1194,6 @@ struct StudioAppImpl final : StudioApp
void setLocalCoordSystem() { getGizmoConfig().coord_system = Gizmo::Config::LOCAL; }
void setGlobalCoordSystem() { getGizmoConfig().coord_system = Gizmo::Config::GLOBAL; }
void addEntity() { m_editor->addEntity(); }
void snapDown() { m_editor->snapDown(); }
void setEditCamTransform() { m_is_edit_cam_transform_ui_open = !m_is_edit_cam_transform_ui_open; }
void lookAtSelected() { m_editor->getView().lookAtSelected(); }
void copyViewTransform() { m_editor->getView().copyTransform(); }
@ -1267,6 +1265,31 @@ struct StudioAppImpl final : StudioApp
}
}
void snapDown() {
const Array<EntityRef>& selected = m_editor->getSelectedEntities();
if (selected.empty()) return;
Array<DVec3> new_positions(m_allocator);
Universe* universe = m_editor->getUniverse();
for (EntityRef entity : selected) {
const DVec3 origin = universe->getPosition(entity);
auto hit = getRenderInterface()->castRay(*universe, origin, Vec3(0, -1, 0), entity);
if (hit.is_hit) {
new_positions.push(origin + Vec3(0, -hit.t, 0));
}
else {
hit = getRenderInterface()->castRay(*universe, origin, Vec3(0, 1, 0), entity);
if (hit.is_hit) {
new_positions.push(origin + Vec3(0, hit.t, 0));
}
else {
new_positions.push(universe->getPosition(entity));
}
}
}
m_editor->setEntitiesPositions(&selected[0], &new_positions[0], new_positions.size());
}
void autosnapDown()
{
@ -1618,7 +1641,7 @@ struct StudioAppImpl final : StudioApp
{
char buffer[1024];
Universe* universe = m_editor->getUniverse();
getEntityListDisplayName(*m_editor, Span(buffer), entity);
getEntityListDisplayName(*this, Span(buffer), entity);
bool selected = selected_entities.indexOf(entity) >= 0;
ImGui::PushID(entity.index);
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_AllowItemOverlap;
@ -1727,7 +1750,7 @@ struct StudioAppImpl final : StudioApp
e = universe->getNextEntity((EntityRef)e))
{
char buffer[1024];
getEntityListDisplayName(*m_editor, Span(buffer), e);
getEntityListDisplayName(*this, Span(buffer), e);
if (stristr(buffer, filter) == nullptr) continue;
ImGui::PushID(e.index);
const EntityRef e_ref = (EntityRef)e;
@ -1968,7 +1991,8 @@ struct StudioAppImpl final : StudioApp
style.ItemInnerSpacing.x = 2;
}
RenderInterface* getRenderInterface() override { return m_editor->getRenderInterface(); }
void setRenderInterface(RenderInterface* ri) override { m_render_interface = ri; }
RenderInterface* getRenderInterface() override { return m_render_interface; }
float getFOV() const { return m_fov; }
void setFOV(float fov_radians) { m_fov = fov_radians; }
@ -3168,6 +3192,7 @@ struct StudioAppImpl final : StudioApp
ProfilerUI* m_profiler_ui;
Settings m_settings;
float m_fov = degreesToRadians(60);
RenderInterface* m_render_interface = nullptr;
Array<OS::Event> m_events;
char m_template_name[100];
char m_open_filter[64];

View file

@ -126,8 +126,10 @@ struct LUMIX_EDITOR_API StudioApp : OS::Interface
virtual Action* getAction(const char* name) = 0;
virtual void setFullscreen(bool fullscreen) = 0;
virtual bool makeFile(const char* path, const char* content) = 0;
virtual void snapDown() = 0;
virtual struct Settings& getSettings() = 0;
virtual struct RenderInterface* getRenderInterface() = 0;
virtual void setRenderInterface(RenderInterface* ifc) = 0;
virtual float getFOV() const = 0;
virtual void setFOV(float fov_radians) = 0;
virtual Gizmo::Config& getGizmoConfig() = 0;

View file

@ -5,6 +5,7 @@
#include "engine/path.h"
#include "engine/reflection.h"
#include "editor/render_interface.h"
#include "editor/studio_app.h"
#include "editor/world_editor.h"
#include "engine/universe.h"
@ -164,7 +165,7 @@ bool Action::isActive()
}
void getEntityListDisplayName(WorldEditor& editor, Span<char> buf, EntityPtr entity)
void getEntityListDisplayName(StudioApp& app, Span<char> buf, EntityPtr entity)
{
if (!entity.isValid())
{
@ -173,12 +174,13 @@ void getEntityListDisplayName(WorldEditor& editor, Span<char> buf, EntityPtr ent
}
EntityRef e = (EntityRef)entity;
WorldEditor& editor = app.getWorldEditor();
const char* name = editor.getUniverse()->getEntityName(e);
static const auto MODEL_INSTANCE_TYPE = Reflection::getComponentType("model_instance");
if (editor.getUniverse()->hasComponent(e, MODEL_INSTANCE_TYPE))
{
auto* render_interface = editor.getRenderInterface();
auto path = render_interface->getModelInstancePath(e);
RenderInterface* render_interface = app.getRenderInterface();
auto path = render_interface->getModelInstancePath(*editor.getUniverse(), e);
if (path.isValid())
{
const char* c = path.c_str();

View file

@ -46,7 +46,7 @@ struct LUMIX_EDITOR_API Action
struct WorldEditor;
LUMIX_EDITOR_API void getEntityListDisplayName(WorldEditor& editor, Span<char> buf, EntityPtr entity);
LUMIX_EDITOR_API void getEntityListDisplayName(struct StudioApp& app, Span<char> buf, EntityPtr entity);
} // namespace Lumix

View file

@ -1632,10 +1632,7 @@ public:
void setView(UniverseView* view) override { m_view = view; }
Universe* getUniverse() override
{
return m_universe;
}
Universe* getUniverse() override { return m_universe; }
Engine& getEngine() override { return m_engine; }
@ -1663,8 +1660,6 @@ public:
destroyUniverse();
PrefabSystem::destroy(m_prefab_system);
LUMIX_DELETE(m_allocator, m_render_interface);
}
@ -1762,53 +1757,6 @@ public:
}
void setRenderInterface(struct RenderInterface* interface) override
{
m_render_interface = interface;
createUniverse();
}
RenderInterface* getRenderInterface() override
{
return m_render_interface;
}
void snapDown() override
{
if (m_selected_entities.empty()) return;
Array<DVec3> new_positions(m_allocator);
Universe* universe = getUniverse();
for (int i = 0; i < m_selected_entities.size(); ++i)
{
EntityRef entity = m_selected_entities[i];
DVec3 origin = universe->getPosition(entity);
auto hit = m_render_interface->castRay(origin, Vec3(0, -1, 0), m_selected_entities[i]);
if (hit.is_hit)
{
new_positions.push(origin + Vec3(0, -hit.t, 0));
}
else
{
hit = m_render_interface->castRay(origin, Vec3(0, 1, 0), m_selected_entities[i]);
if (hit.is_hit)
{
new_positions.push(origin + Vec3(0, hit.t, 0));
}
else
{
new_positions.push(universe->getPosition(m_selected_entities[i]));
}
}
}
setEntitiesPositions(&m_selected_entities[0], &new_positions[0], new_positions.size());
}
void makeParent(EntityPtr parent, EntityRef child) override
{
MakeParentCommand* command = LUMIX_NEW(m_allocator, MakeParentCommand)(*this, parent, child);
@ -2132,13 +2080,11 @@ public:
if (reload)
{
m_universe_destroyed.invoke();
m_render_interface->setUniverse(nullptr);
m_prefab_system->setUniverse(nullptr);
StaticString<64> name(m_universe->getName());
m_engine.destroyUniverse(*m_universe);
m_universe = &m_engine.createUniverse(true);
m_render_interface->setUniverse(m_universe);
m_prefab_system->setUniverse(m_universe);
m_universe_created.invoke();
m_universe->setName(name);
@ -2359,7 +2305,6 @@ public:
, m_is_loading(false)
, m_universe(nullptr)
, m_is_toggle_selection(false)
, m_render_interface(nullptr)
, m_selected_entity_on_game_mode(INVALID_ENTITY)
, m_is_game_mode(false)
, m_undo_index(-1)
@ -2370,6 +2315,7 @@ public:
logInfo("Editor") << "Initializing editor...";
m_prefab_system = PrefabSystem::create(*this);
createUniverse();
}
@ -2470,7 +2416,6 @@ public:
ASSERT(m_universe);
destroyUndoStack();
m_universe_destroyed.invoke();
m_render_interface->setUniverse(nullptr);
m_prefab_system->setUniverse(nullptr);
selectEntities(nullptr, 0, false);
m_engine.destroyUniverse(*m_universe);
@ -2512,10 +2457,9 @@ public:
universe->entityDestroyed().bind<&WorldEditorImpl::onEntityDestroyed>(this);
m_view->setOrbitCamera(false);
if (m_view) m_view->setOrbitCamera(false);
m_selected_entities.clear();
m_universe_created.invoke();
m_render_interface->setUniverse(universe);
m_prefab_system->setUniverse(universe);
}
@ -2595,7 +2539,6 @@ public:
private:
IAllocator& m_allocator;
Engine& m_engine;
RenderInterface* m_render_interface;
UniverseView* m_view = nullptr;
PrefabSystem* m_prefab_system;
Universe* m_universe;

View file

@ -87,8 +87,6 @@ struct LUMIX_EDITOR_API WorldEditor
static WorldEditor* create(struct Engine& engine, struct IAllocator& allocator);
static void destroy(WorldEditor* editor, IAllocator& allocator);
virtual void setRenderInterface(struct RenderInterface* interface) = 0;
virtual RenderInterface* getRenderInterface() = 0;
virtual void update() = 0;
virtual Engine& getEngine() = 0;
virtual struct Universe* getUniverse() = 0;
@ -150,7 +148,6 @@ struct LUMIX_EDITOR_API WorldEditor
virtual void loadUniverse(const char* basename) = 0;
virtual void saveUniverse(const char* basename, bool save_path) = 0;
virtual void newUniverse() = 0;
virtual void snapDown() = 0;
virtual void toggleGameMode() = 0;
virtual void setToggleSelection(bool is_toggle) = 0;

View file

@ -285,6 +285,7 @@ struct PhysicsUIPlugin final : StudioApp::GUIPlugin
: m_editor(app.getWorldEditor())
, m_selected_bone(-1)
, m_is_window_open(false)
, m_app(app)
{
Action* action = LUMIX_NEW(m_editor.getAllocator(), Action)("Physics", "Toggle physics UI", "physics");
action->func.bind<&PhysicsUIPlugin::onAction>(this);
@ -458,13 +459,13 @@ struct PhysicsUIPlugin final : StudioApp::GUIPlugin
ImGui::PushID(i);
char tmp[256];
getEntityListDisplayName(m_editor, Span(tmp), cmp.entity);
getEntityListDisplayName(m_app, Span(tmp), cmp.entity);
bool b = false;
if (ImGui::Selectable(tmp, &b)) m_editor.selectEntities(&entity, 1, false);
ImGui::NextColumn();
EntityPtr other_entity = scene->getJointConnectedBody(entity);
getEntityListDisplayName(m_editor, Span(tmp), other_entity);
getEntityListDisplayName(m_app, Span(tmp), other_entity);
if (other_entity.isValid() && ImGui::Selectable(tmp, &b)) {
const EntityRef e = (EntityRef)other_entity;
m_editor.selectEntities(&e, 1, false);
@ -535,7 +536,7 @@ struct PhysicsUIPlugin final : StudioApp::GUIPlugin
};
char tmp[255];
getEntityListDisplayName(m_editor, Span(tmp), e);
getEntityListDisplayName(m_app, Span(tmp), e);
ImGui::Text("%s", tmp);
ImGui::SameLine();
@ -874,6 +875,7 @@ struct PhysicsUIPlugin final : StudioApp::GUIPlugin
bool m_is_window_open;
int m_selected_bone;
WorldEditor& m_editor;
StudioApp& m_app;
};

View file

@ -3044,70 +3044,12 @@ struct TerrainPlugin final : PropertyGrid::IPlugin
struct RenderInterfaceImpl final : RenderInterface
{
RenderInterfaceImpl(WorldEditor& editor, Pipeline& pipeline, Renderer& renderer)
: m_pipeline(pipeline)
, m_editor(editor)
: m_editor(editor)
, m_textures(editor.getAllocator())
, m_renderer(renderer)
{
m_model_index = 0;
auto& rm = m_editor.getEngine().getResourceManager();
Path font_path("editor/fonts/OpenSans-Regular.ttf");
m_font_res = rm.load<FontResource>(font_path);
m_font = m_font_res->addRef(16);
}
{}
~RenderInterfaceImpl()
{
m_font_res->getResourceManager().unload(*m_font_res);
}
ImFont* addFont(const char* filename, int size) override
{
ImGuiIO& io = ImGui::GetIO();
ImFont* font = io.Fonts->AddFontFromFileTTF(filename, (float)size);
Engine& engine = m_editor.getEngine();
unsigned char* pixels;
int width, height;
ImGuiFreeType::BuildFontAtlas(ImGui::GetIO().Fonts);
ImGui::GetIO().Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
Material* material = engine.getResourceManager().load<Material>(Path("pipelines/imgui/imgui.mat"));
Texture* old_texture = material->getTexture(0);
Texture* texture = LUMIX_NEW(engine.getAllocator(), Texture)(
Path("font"), *engine.getResourceManager().get(Texture::TYPE), m_renderer, engine.getAllocator());
texture->create(width, height, gpu::TextureFormat::RGBA8, pixels, width * height * 4);
material->setTexture(0, texture);
if (old_texture)
{
old_texture->destroy();
LUMIX_DELETE(engine.getAllocator(), old_texture);
}
return font;
}
bool saveTexture(Engine& engine, const char* path_cstr, const void* pixels, int w, int h, bool upper_left_origin) override
{
Path path(path_cstr);
OS::OutputFile file;
if (!file.open(path_cstr)) return false;
if (!Texture::saveTGA(&file, w, h, gpu::TextureFormat::RGBA8, (const u8*)pixels, upper_left_origin, path, engine.getAllocator())) {
file.close();
return false;
}
file.close();
return true;
}
ImTextureID createTexture(const char* name, const void* pixels, int w, int h) override
{
@ -3159,9 +3101,10 @@ struct RenderInterfaceImpl final : RenderInterface
}
UniverseView::RayHit castRay(const DVec3& origin, const Vec3& dir, EntityPtr ignored) override
UniverseView::RayHit castRay(Universe& universe, const DVec3& origin, const Vec3& dir, EntityPtr ignored) override
{
const RayCastModelHit hit = m_render_scene->castRay(origin, dir, ignored);
RenderScene* scene = (RenderScene*)universe.getScene(ENVIRONMENT_PROBE_TYPE);
const RayCastModelHit hit = scene->castRay(origin, dir, ignored);
return {hit.is_hit, hit.t, hit.entity, hit.origin + hit.dir * hit.t};
}
@ -3172,7 +3115,8 @@ struct RenderInterfaceImpl final : RenderInterface
AABB aabb;
if (universe.hasComponent(entity, MODEL_INSTANCE_TYPE)) {
Model* model = m_render_scene->getModelInstanceModel(entity);
RenderScene* scene = (RenderScene*)universe.getScene(ENVIRONMENT_PROBE_TYPE);
Model* model = scene->getModelInstanceModel(entity);
if (!model) return aabb;
aabb = model->getAABB();
@ -3188,47 +3132,15 @@ struct RenderInterfaceImpl final : RenderInterface
}
Vec2 getCameraScreenSize(EntityRef entity) override { return m_render_scene->getCameraScreenSize(entity); }
float getCameraOrthoSize(EntityRef entity) override { return m_render_scene->getCamera(entity).ortho_size; }
bool isCameraOrtho(EntityRef entity) override { return m_render_scene->getCamera(entity).is_ortho; }
float getCameraFOV(EntityRef entity) override { return m_render_scene->getCamera(entity).fov; }
void setUniverse(Universe* universe) override {
m_render_scene = universe ? static_cast<RenderScene*>(universe->getScene(MODEL_INSTANCE_TYPE)) : nullptr;
}
Vec3 getModelCenter(EntityRef entity) override
{
if (!m_render_scene->getUniverse().hasComponent(entity, MODEL_INSTANCE_TYPE)) return Vec3::ZERO;
Model* model = m_render_scene->getModelInstanceModel(entity);
if (!model) return Vec3(0, 0, 0);
return (model->getAABB().min + model->getAABB().max) * 0.5f;
}
Path getModelInstancePath(EntityRef entity) override { return m_render_scene->getModelInstancePath(entity); }
ShiftedFrustum getFrustum(EntityRef camera, const Vec2& viewport_min, const Vec2& viewport_max) override
{
return m_render_scene->getCameraFrustum(camera, viewport_min, viewport_max);
Path getModelInstancePath(Universe& universe, EntityRef entity) override {
RenderScene* scene = (RenderScene*)universe.getScene(ENVIRONMENT_PROBE_TYPE);
return scene->getModelInstancePath(entity);
}
WorldEditor& m_editor;
FontResource* m_font_res;
Font* m_font;
RenderScene* m_render_scene;
Renderer& m_renderer;
Pipeline& m_pipeline;
HashMap<void*, Texture*> m_textures;
int m_model_index;
};
@ -3505,9 +3417,8 @@ struct EditorUIRenderPlugin final : StudioApp::GUIPlugin
IAllocator& allocator = app.getAllocator();
WorldEditor& editor = app.getWorldEditor();
RenderInterface* render_interface =
LUMIX_NEW(allocator, RenderInterfaceImpl)(editor, *scene_view.getPipeline(), *renderer);
editor.setRenderInterface(render_interface);
RenderInterface* render_interface = LUMIX_NEW(allocator, RenderInterfaceImpl)(editor, *scene_view.getPipeline(), *renderer);
app.setRenderInterface(render_interface);
}

View file

@ -99,7 +99,7 @@ struct UniverseViewImpl final : UniverseView {
}
void onUniverseDestroyed(){
EditorIcons::destroy(*m_icons);
if (m_icons) EditorIcons::destroy(*m_icons);
m_icons = nullptr;
}
@ -728,7 +728,7 @@ void SceneView::manipulate() {
}
default: ASSERT(false); break;
}
if (cfg.isAutosnapDown()) m_editor.snapDown();
if (cfg.isAutosnapDown()) m_app.snapDown();
}
void SceneView::update(float time_delta)