Add project files.
This commit is contained in:
commit
a9ae435321
52 files changed
+65378
No files matched your search
+284
@@ -0,0 +1,284 @@
|
||||
// Hammer++ editor: shared types. The editor is a thin UI layer over libhmap.
|
||||
#pragma once
|
||||
#include <hmap/hmap.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "imgui.h"
|
||||
#include "raylib.h"
|
||||
#include "render.h"
|
||||
|
||||
namespace hpp {
|
||||
|
||||
using hmap::AABB;
|
||||
using hmap::Mat34;
|
||||
using hmap::Plane;
|
||||
using hmap::Vec2;
|
||||
using hmap::Vec3;
|
||||
|
||||
enum class Tool { Select, Block, Entity, Clip };
|
||||
enum class SelMode { Object, Face, Vertex };
|
||||
enum class Shading { Wire, Flat, Lit, Baked };
|
||||
enum class ViewKind { Persp, Top, Front, Side };
|
||||
enum class ObjType { Brush, Mesh, Entity };
|
||||
enum class Shape { Box, Wedge, Cylinder, Cone, Stairs, Sphere, Torus, Terrain };
|
||||
|
||||
struct ObjRef {
|
||||
ObjType type = ObjType::Brush;
|
||||
uint32_t id = 0;
|
||||
bool operator==(const ObjRef& o) const { return type == o.type && id == o.id; }
|
||||
};
|
||||
|
||||
struct Selection {
|
||||
std::vector<ObjRef> objs;
|
||||
std::vector<int> faces; // faces (brush) / polygons (mesh) of the primary object
|
||||
std::vector<int> verts; // vertex indices of the primary mesh
|
||||
bool has(const ObjRef& r) const;
|
||||
void clear() { objs.clear(); faces.clear(); verts.clear(); }
|
||||
bool empty() const { return objs.empty(); }
|
||||
ObjRef primary() const { return objs.empty() ? ObjRef{} : objs.back(); }
|
||||
};
|
||||
|
||||
struct HRay { Vec3 o, d; };
|
||||
|
||||
struct Hit {
|
||||
bool hit = false;
|
||||
float t = 1e30f;
|
||||
ObjRef obj;
|
||||
int face = -1;
|
||||
Vec3 point, normal;
|
||||
};
|
||||
|
||||
struct Viewport {
|
||||
const char* title = "";
|
||||
ViewKind kind = ViewKind::Persp;
|
||||
bool open = true;
|
||||
RenderTexture2D rt = {};
|
||||
int w = 0, h = 0;
|
||||
// perspective camera
|
||||
Vec3 pos{0, 256, 512};
|
||||
float yaw = 0, pitch = -25, fov = 70, flySpeed = 320;
|
||||
// orthographic camera
|
||||
Vec3 center{0, 0, 0};
|
||||
float zoom = 0.5f; // pixels per world unit
|
||||
// per-frame interaction state
|
||||
ImVec2 imgMin{0, 0};
|
||||
bool hovered = false, flying = false;
|
||||
|
||||
bool ortho() const { return kind != ViewKind::Persp; }
|
||||
Vec3 forward() const;
|
||||
Vec3 right() const;
|
||||
Vec3 up() const;
|
||||
int depthAxis() const; // ortho: world axis along the view direction
|
||||
Camera3D camera() const;
|
||||
HRay ray(float sx, float sy) const;
|
||||
bool project(const Vec3& p, float& sx, float& sy) const; // false when behind the camera
|
||||
Vec3 planePoint(float sx, float sy, float depth) const; // ortho: world point on the plane at `depth`
|
||||
};
|
||||
|
||||
struct DragSnap {
|
||||
std::vector<hmap::Brush> brushes;
|
||||
std::vector<hmap::MeshObject> meshes;
|
||||
std::vector<hmap::Entity> entities;
|
||||
};
|
||||
|
||||
struct DragState {
|
||||
enum Kind { None, Move, Resize, Gizmo, BoxSelect, Block } kind = None;
|
||||
Viewport* view = nullptr;
|
||||
Vec3 startWorld;
|
||||
ImVec2 startScreen{0, 0}, curScreen{0, 0};
|
||||
bool moved = false;
|
||||
bool tookUndo = false;
|
||||
int hx = 0, hy = 0; // resize handle
|
||||
float rectU0 = 0, rectU1 = 0, rectV0 = 0, rectV1 = 0; // selection rect in view-plane coordinates
|
||||
int axis = -1; // gizmo axis
|
||||
float s0 = 0;
|
||||
Vec3 origin;
|
||||
Vec3 blockA, blockB;
|
||||
DragSnap snap;
|
||||
};
|
||||
|
||||
struct SceneCache {
|
||||
uint64_t version = 0;
|
||||
std::vector<hmap::BrushGeometry> brushGeo; // parallel to Map::brushes
|
||||
std::vector<AABB> meshBounds; // parallel to Map::meshes
|
||||
};
|
||||
|
||||
class FileDialog {
|
||||
public:
|
||||
using Callback = std::function<void(const std::string&)>;
|
||||
void open(const std::string& title, const std::string& startDir, std::vector<std::string> exts, bool save, Callback cb,
|
||||
const std::string& defaultName = "");
|
||||
void draw();
|
||||
|
||||
private:
|
||||
std::string title_, dir_, name_;
|
||||
std::vector<std::string> exts_;
|
||||
bool save_ = false, pending_ = false;
|
||||
Callback cb_;
|
||||
};
|
||||
|
||||
class Editor {
|
||||
public:
|
||||
// ------------------------------------------------------------ lifecycle
|
||||
void init();
|
||||
void frame(); // one full UI frame; call between rlImGuiBegin() and rlImGuiEnd()
|
||||
void shutdown();
|
||||
|
||||
// ------------------------------------------------------------ document
|
||||
hmap::Map doc;
|
||||
std::string docPath;
|
||||
bool dirty = false;
|
||||
uint64_t docVersion = 1;
|
||||
hmap::EntityRegistry entdefs;
|
||||
std::string assetRoot = "assets";
|
||||
std::vector<hmap::Map> undoStack, redoStack;
|
||||
|
||||
// ------------------------------------------------------------ state
|
||||
Selection sel;
|
||||
Tool tool = Tool::Select;
|
||||
SelMode selMode = SelMode::Object;
|
||||
Shading shading = Shading::Lit;
|
||||
bool snapOn = true;
|
||||
float grid = 16;
|
||||
int curMaterial = 0;
|
||||
Shape shape = Shape::Box;
|
||||
bool createAsMesh = false;
|
||||
int shapeSides = 12;
|
||||
int stairSteps = 8;
|
||||
std::string curEntity = "prop_static";
|
||||
std::string curModel;
|
||||
float blockHeight = 64;
|
||||
bool saveCompiledToo = false;
|
||||
|
||||
hmap::CompiledMap compiled;
|
||||
bool hasCompiled = false, compiledStale = false;
|
||||
hmap::CompileOptions compileOpt;
|
||||
hmap::FbxOptions fbxOpt;
|
||||
|
||||
Renderer renderer;
|
||||
Viewport views[4];
|
||||
DragState drag;
|
||||
SceneCache cache;
|
||||
std::vector<hmap::Light> lights;
|
||||
uint64_t lightsVersion = 0;
|
||||
|
||||
FileDialog fileDialog;
|
||||
std::vector<std::string> logLines;
|
||||
bool showDemo = false, resetLayout = false, showHelp = false, wantQuit = false;
|
||||
std::function<void()> pendingAction;
|
||||
bool askDiscard = false;
|
||||
void guarded(std::function<void()> act); // runs `act`, asking first when there are unsaved changes
|
||||
bool panelOutliner = true, panelInspector = true, panelAssets = true, panelLog = true;
|
||||
|
||||
// clip tool
|
||||
bool clipHasA = false, clipHasB = false;
|
||||
Vec3 clipA, clipB;
|
||||
int clipMode = 0; // 0 keep front, 1 keep back, 2 keep both
|
||||
int clipView = 0;
|
||||
|
||||
// ------------------------------------------------------------ commands (editor.cpp)
|
||||
void log(const char* fmt, ...);
|
||||
void newMap(bool demo);
|
||||
bool openMap(const std::string& path);
|
||||
bool saveMap(const std::string& path);
|
||||
void touch(); // document changed
|
||||
void pushUndo();
|
||||
void editBegin(); // call before applying an inspector edit (one undo entry per edit session)
|
||||
void undo();
|
||||
void redo();
|
||||
|
||||
void clearSelection();
|
||||
void select(const ObjRef& r, bool additive);
|
||||
void selectAll();
|
||||
void pruneSelection();
|
||||
bool selectedBrushes(std::vector<hmap::Brush*>& out);
|
||||
AABB objectBounds(const ObjRef& r);
|
||||
AABB selectionBounds();
|
||||
Vec3 selectionCenter();
|
||||
hmap::Brush* findBrush(uint32_t id) { return doc.findBrush(id); }
|
||||
const hmap::EntityClass* classOf(const hmap::Entity& e) const { return entdefs.find(e.classname); }
|
||||
AABB entityBounds(const hmap::Entity& e);
|
||||
Vec3 entityColor(const hmap::Entity& e) const;
|
||||
|
||||
void deleteSelection();
|
||||
void duplicateSelection();
|
||||
void hideSelection(bool hide);
|
||||
void unhideAll();
|
||||
void hollowSelection(float thickness);
|
||||
void convertSelectionToMesh();
|
||||
void tieSelectionToEntity(const std::string& cls);
|
||||
void untieSelection();
|
||||
void clipSelection(const Plane& p, int mode);
|
||||
void createPrimitive(Vec3 mn, Vec3 mx);
|
||||
void createEntityAt(const Vec3& origin);
|
||||
void applyMaterialToSelection(int material);
|
||||
void paintHit(const Hit& h, bool wholeObject);
|
||||
void flipSelection();
|
||||
void importObjFile(const std::string& path);
|
||||
|
||||
DragSnap captureSnap();
|
||||
void restoreSnap(const DragSnap& s);
|
||||
void applyMatrix(const Mat34& m, bool lockTexture);
|
||||
void translateSelectedVerts(const Vec3& d);
|
||||
|
||||
void compileNow();
|
||||
void exportFbx(const std::string& path);
|
||||
void exportObj(const std::string& path);
|
||||
void exportCompiled(const std::string& path);
|
||||
|
||||
const SceneCache& scene();
|
||||
void refreshGpu();
|
||||
Hit pick(const HRay& r);
|
||||
float snapValue(float v) const { return snapOn ? std::round(v / grid) * grid : v; }
|
||||
|
||||
// ------------------------------------------------------------ ui (ui.cpp)
|
||||
void drawUI();
|
||||
void drawMenu();
|
||||
void drawToolbar();
|
||||
void drawOutliner();
|
||||
void drawInspector();
|
||||
void drawAssets();
|
||||
void drawLog();
|
||||
void drawHelp();
|
||||
void shortcuts();
|
||||
void buildLayout(ImGuiID dock);
|
||||
bool propEditor(hmap::Entity& e, const hmap::PropDef& p);
|
||||
void entityInspector(hmap::Entity& e, bool brushEntity);
|
||||
void faceInspector();
|
||||
void transformInspector();
|
||||
void openModelPicker(std::function<void(const std::string&)> cb);
|
||||
bool inEdit = false;
|
||||
std::vector<std::string> modelFiles;
|
||||
std::vector<std::string> textureFiles;
|
||||
bool filesScanned = false;
|
||||
void scanAssets();
|
||||
std::string relativeToAssets(const std::string& path) const;
|
||||
|
||||
// ------------------------------------------------------------ viewports (viewport.cpp)
|
||||
void drawViewport(Viewport& v);
|
||||
void viewInput(Viewport& v, bool active);
|
||||
void toolInput3D(Viewport& v, const ImVec2& m);
|
||||
void toolInput2D(Viewport& v, const ImVec2& m);
|
||||
void renderView(Viewport& v);
|
||||
void drawGrid(Viewport& v);
|
||||
void drawScene3D(Viewport& v);
|
||||
void drawWire(Viewport& v);
|
||||
void drawEntities(Viewport& v);
|
||||
void drawGizmo(Viewport& v);
|
||||
void drawOverlay2D(Viewport& v);
|
||||
void focusSelection();
|
||||
bool gizmoVisible() const;
|
||||
Vec3 gizmoCenter();
|
||||
int gizmoHit(Viewport& v, const ImVec2& m);
|
||||
bool selectionRect(Viewport& v, float& u0, float& u1, float& v0, float& v1);
|
||||
};
|
||||
|
||||
void applyTheme();
|
||||
void firstPlace(float fx, float fy, float fw, float fh);
|
||||
|
||||
} // namespace hpp
|
||||
Reference in new issue
Block a user