Add Lisp integration to map editor
This commit is contained in:
parent
eca9313846
commit
6999c7d1e1
9 changed files with 3908 additions and 63 deletions
|
@ -0,0 +1,36 @@
|
|||
[06:58:04 AM] Info: Starting...
|
||||
|
||||
KP3D version 2
|
||||
===============================
|
||||
Copyright (C) kpworld.xyz 2018-2024
|
||||
Contact me! @kp_cftsz
|
||||
|
||||
[06:58:04 AM] Info: Initializing SDL
|
||||
[06:58:05 AM] Info: Initializing OpenGL
|
||||
[06:58:05 AM] Info: OpenGL version: 4.6.0 NVIDIA 536.23
|
||||
[06:58:05 AM] Info: Initializing GLEW
|
||||
[06:58:05 AM] Info: Initializing SDL_mixer
|
||||
[06:58:05 AM] Info: Reticulating splines...
|
||||
[06:58:05 AM] Info: Ready!
|
||||
[06:58:05 AM] Info: Loading material resource: block.png
|
||||
[06:58:05 AM] Info: Found normal map texture: materials/block_n.png
|
||||
[06:58:05 AM] Info: Loading material resource: brick2.jpg
|
||||
[06:58:05 AM] Info: Found normal map texture: materials/brick2_n.jpg
|
||||
[06:58:05 AM] Info: Loading material resource: bricks.jpg
|
||||
[06:58:05 AM] Info: Found normal map texture: materials/bricks_n.jpg
|
||||
[06:58:05 AM] Info: Loading material resource: FLAT5_7.png
|
||||
[06:58:05 AM] Info: Found normal map texture: materials/FLAT5_7_n.png
|
||||
[06:58:05 AM] Info: Loading material resource: floor0.png
|
||||
[06:58:05 AM] Info: Found normal map texture: materials/floor0_n.png
|
||||
[06:58:05 AM] Info: Loading material resource: floor1.png
|
||||
[06:58:05 AM] Info: Found normal map texture: materials/floor1_n.png
|
||||
[06:58:05 AM] Info: Loading material resource: GRASS2.png
|
||||
[06:58:05 AM] Info: Found normal map texture: materials/GRASS2_n.png
|
||||
[06:58:05 AM] Info: Loading material resource: hardwood.jpg
|
||||
[06:58:05 AM] Info: Found normal map texture: materials/hardwood_n.jpg
|
||||
[06:58:05 AM] Info: Map init
|
||||
[06:58:05 AM] Info: Finalized mesh with 49 batches
|
||||
[06:58:10 AM] Info: $ make-sector-from-points 0 4 ((30 30) (35 30) (35 35) (30 35))
|
||||
[06:58:10 AM] Info: Finalized mesh with 54 batches
|
||||
[06:58:10 AM] Info: $ 7.000000
|
||||
[06:58:32 AM] Info: Finalized mesh with 60 batches
|
|
@ -189,6 +189,7 @@
|
|||
<ClCompile Include="ext\src\imgui\imgui_impl_sdl2.cpp" />
|
||||
<ClCompile Include="ext\src\imgui\imgui_tables.cpp" />
|
||||
<ClCompile Include="ext\src\imgui\imgui_widgets.cpp" />
|
||||
<ClCompile Include="ext\src\imgui\TextEditor.cpp" />
|
||||
<ClCompile Include="ext\src\poly2tri\advancing_front.cc" />
|
||||
<ClCompile Include="ext\src\poly2tri\cdt.cc" />
|
||||
<ClCompile Include="ext\src\poly2tri\shapes.cc" />
|
||||
|
|
|
@ -100,6 +100,7 @@
|
|||
<ClCompile Include="src\KP3D_Material.cpp" />
|
||||
<ClCompile Include="src\KP3D_Resources.cpp" />
|
||||
<ClCompile Include="ext\src\imgui\ImGuizmo.cpp" />
|
||||
<ClCompile Include="ext\src\imgui\TextEditor.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include=".clang-format" />
|
||||
|
|
390
KP3Dii/ext/include/TextEditor.h
Normal file
390
KP3Dii/ext/include/TextEditor.h
Normal file
|
@ -0,0 +1,390 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <regex>
|
||||
#include "imgui.h"
|
||||
|
||||
class TextEditor
|
||||
{
|
||||
public:
|
||||
enum class PaletteIndex
|
||||
{
|
||||
Default,
|
||||
Keyword,
|
||||
Number,
|
||||
String,
|
||||
CharLiteral,
|
||||
Punctuation,
|
||||
Preprocessor,
|
||||
Identifier,
|
||||
KnownIdentifier,
|
||||
PreprocIdentifier,
|
||||
Comment,
|
||||
MultiLineComment,
|
||||
Background,
|
||||
Cursor,
|
||||
Selection,
|
||||
ErrorMarker,
|
||||
Breakpoint,
|
||||
LineNumber,
|
||||
CurrentLineFill,
|
||||
CurrentLineFillInactive,
|
||||
CurrentLineEdge,
|
||||
Max
|
||||
};
|
||||
|
||||
enum class SelectionMode
|
||||
{
|
||||
Normal,
|
||||
Word,
|
||||
Line
|
||||
};
|
||||
|
||||
struct Breakpoint
|
||||
{
|
||||
int mLine;
|
||||
bool mEnabled;
|
||||
std::string mCondition;
|
||||
|
||||
Breakpoint()
|
||||
: mLine(-1)
|
||||
, mEnabled(false)
|
||||
{}
|
||||
};
|
||||
|
||||
// Represents a character coordinate from the user's point of view,
|
||||
// i. e. consider an uniform grid (assuming fixed-width font) on the
|
||||
// screen as it is rendered, and each cell has its own coordinate, starting from 0.
|
||||
// Tabs are counted as [1..mTabSize] count empty spaces, depending on
|
||||
// how many space is necessary to reach the next tab stop.
|
||||
// For example, coordinate (1, 5) represents the character 'B' in a line "\tABC", when mTabSize = 4,
|
||||
// because it is rendered as " ABC" on the screen.
|
||||
struct Coordinates
|
||||
{
|
||||
int mLine, mColumn;
|
||||
Coordinates() : mLine(0), mColumn(0) {}
|
||||
Coordinates(int aLine, int aColumn) : mLine(aLine), mColumn(aColumn)
|
||||
{
|
||||
assert(aLine >= 0);
|
||||
assert(aColumn >= 0);
|
||||
}
|
||||
static Coordinates Invalid() { static Coordinates invalid(-1, -1); return invalid; }
|
||||
|
||||
bool operator ==(const Coordinates& o) const
|
||||
{
|
||||
return
|
||||
mLine == o.mLine &&
|
||||
mColumn == o.mColumn;
|
||||
}
|
||||
|
||||
bool operator !=(const Coordinates& o) const
|
||||
{
|
||||
return
|
||||
mLine != o.mLine ||
|
||||
mColumn != o.mColumn;
|
||||
}
|
||||
|
||||
bool operator <(const Coordinates& o) const
|
||||
{
|
||||
if (mLine != o.mLine)
|
||||
return mLine < o.mLine;
|
||||
return mColumn < o.mColumn;
|
||||
}
|
||||
|
||||
bool operator >(const Coordinates& o) const
|
||||
{
|
||||
if (mLine != o.mLine)
|
||||
return mLine > o.mLine;
|
||||
return mColumn > o.mColumn;
|
||||
}
|
||||
|
||||
bool operator <=(const Coordinates& o) const
|
||||
{
|
||||
if (mLine != o.mLine)
|
||||
return mLine < o.mLine;
|
||||
return mColumn <= o.mColumn;
|
||||
}
|
||||
|
||||
bool operator >=(const Coordinates& o) const
|
||||
{
|
||||
if (mLine != o.mLine)
|
||||
return mLine > o.mLine;
|
||||
return mColumn >= o.mColumn;
|
||||
}
|
||||
};
|
||||
|
||||
struct Identifier
|
||||
{
|
||||
Coordinates mLocation;
|
||||
std::string mDeclaration;
|
||||
};
|
||||
|
||||
typedef std::string String;
|
||||
typedef std::unordered_map<std::string, Identifier> Identifiers;
|
||||
typedef std::unordered_set<std::string> Keywords;
|
||||
typedef std::map<int, std::string> ErrorMarkers;
|
||||
typedef std::unordered_set<int> Breakpoints;
|
||||
typedef std::array<ImU32, (unsigned)PaletteIndex::Max> Palette;
|
||||
typedef uint8_t Char;
|
||||
|
||||
struct Glyph
|
||||
{
|
||||
Char mChar;
|
||||
PaletteIndex mColorIndex = PaletteIndex::Default;
|
||||
bool mComment : 1;
|
||||
bool mMultiLineComment : 1;
|
||||
bool mPreprocessor : 1;
|
||||
|
||||
Glyph(Char aChar, PaletteIndex aColorIndex) : mChar(aChar), mColorIndex(aColorIndex),
|
||||
mComment(false), mMultiLineComment(false), mPreprocessor(false) {}
|
||||
};
|
||||
|
||||
typedef std::vector<Glyph> Line;
|
||||
typedef std::vector<Line> Lines;
|
||||
|
||||
struct LanguageDefinition
|
||||
{
|
||||
typedef std::pair<std::string, PaletteIndex> TokenRegexString;
|
||||
typedef std::vector<TokenRegexString> TokenRegexStrings;
|
||||
typedef bool(*TokenizeCallback)(const char * in_begin, const char * in_end, const char *& out_begin, const char *& out_end, PaletteIndex & paletteIndex);
|
||||
|
||||
std::string mName;
|
||||
Keywords mKeywords;
|
||||
Identifiers mIdentifiers;
|
||||
Identifiers mPreprocIdentifiers;
|
||||
std::string mCommentStart, mCommentEnd, mSingleLineComment;
|
||||
char mPreprocChar;
|
||||
bool mAutoIndentation;
|
||||
|
||||
TokenizeCallback mTokenize;
|
||||
|
||||
TokenRegexStrings mTokenRegexStrings;
|
||||
|
||||
bool mCaseSensitive;
|
||||
|
||||
LanguageDefinition()
|
||||
: mPreprocChar('#'), mAutoIndentation(true), mTokenize(nullptr), mCaseSensitive(true)
|
||||
{
|
||||
}
|
||||
|
||||
static const LanguageDefinition& CPlusPlus();
|
||||
static const LanguageDefinition& HLSL();
|
||||
static const LanguageDefinition& GLSL();
|
||||
static const LanguageDefinition& C();
|
||||
static const LanguageDefinition& Lisp();
|
||||
static const LanguageDefinition& SQL();
|
||||
static const LanguageDefinition& AngelScript();
|
||||
static const LanguageDefinition& Lua();
|
||||
};
|
||||
|
||||
TextEditor();
|
||||
~TextEditor();
|
||||
|
||||
void SetLanguageDefinition(const LanguageDefinition& aLanguageDef);
|
||||
const LanguageDefinition& GetLanguageDefinition() const { return mLanguageDefinition; }
|
||||
|
||||
const Palette& GetPalette() const { return mPaletteBase; }
|
||||
void SetPalette(const Palette& aValue);
|
||||
|
||||
void SetErrorMarkers(const ErrorMarkers& aMarkers) { mErrorMarkers = aMarkers; }
|
||||
void SetBreakpoints(const Breakpoints& aMarkers) { mBreakpoints = aMarkers; }
|
||||
|
||||
void Render(const char* aTitle, const ImVec2& aSize = ImVec2(), bool aBorder = false);
|
||||
void SetText(const std::string& aText);
|
||||
std::string GetText() const;
|
||||
|
||||
void SetTextLines(const std::vector<std::string>& aLines);
|
||||
std::vector<std::string> GetTextLines() const;
|
||||
|
||||
std::string GetSelectedText() const;
|
||||
std::string GetCurrentLineText()const;
|
||||
|
||||
int GetTotalLines() const { return (int)mLines.size(); }
|
||||
bool IsOverwrite() const { return mOverwrite; }
|
||||
|
||||
void SetReadOnly(bool aValue);
|
||||
bool IsReadOnly() const { return mReadOnly; }
|
||||
bool IsTextChanged() const { return mTextChanged; }
|
||||
bool IsCursorPositionChanged() const { return mCursorPositionChanged; }
|
||||
|
||||
bool IsColorizerEnabled() const { return mColorizerEnabled; }
|
||||
void SetColorizerEnable(bool aValue);
|
||||
|
||||
Coordinates GetCursorPosition() const { return GetActualCursorCoordinates(); }
|
||||
void SetCursorPosition(const Coordinates& aPosition);
|
||||
|
||||
inline void SetHandleMouseInputs (bool aValue){ mHandleMouseInputs = aValue;}
|
||||
inline bool IsHandleMouseInputsEnabled() const { return mHandleKeyboardInputs; }
|
||||
|
||||
inline void SetHandleKeyboardInputs (bool aValue){ mHandleKeyboardInputs = aValue;}
|
||||
inline bool IsHandleKeyboardInputsEnabled() const { return mHandleKeyboardInputs; }
|
||||
|
||||
inline void SetImGuiChildIgnored (bool aValue){ mIgnoreImGuiChild = aValue;}
|
||||
inline bool IsImGuiChildIgnored() const { return mIgnoreImGuiChild; }
|
||||
|
||||
inline void SetShowWhitespaces(bool aValue) { mShowWhitespaces = aValue; }
|
||||
inline bool IsShowingWhitespaces() const { return mShowWhitespaces; }
|
||||
|
||||
void SetTabSize(int aValue);
|
||||
inline int GetTabSize() const { return mTabSize; }
|
||||
|
||||
void InsertText(const std::string& aValue);
|
||||
void InsertText(const char* aValue);
|
||||
|
||||
void MoveUp(int aAmount = 1, bool aSelect = false);
|
||||
void MoveDown(int aAmount = 1, bool aSelect = false);
|
||||
void MoveLeft(int aAmount = 1, bool aSelect = false, bool aWordMode = false);
|
||||
void MoveRight(int aAmount = 1, bool aSelect = false, bool aWordMode = false);
|
||||
void MoveTop(bool aSelect = false);
|
||||
void MoveBottom(bool aSelect = false);
|
||||
void MoveHome(bool aSelect = false);
|
||||
void MoveEnd(bool aSelect = false);
|
||||
|
||||
void SetSelectionStart(const Coordinates& aPosition);
|
||||
void SetSelectionEnd(const Coordinates& aPosition);
|
||||
void SetSelection(const Coordinates& aStart, const Coordinates& aEnd, SelectionMode aMode = SelectionMode::Normal);
|
||||
void SelectWordUnderCursor();
|
||||
void SelectAll();
|
||||
bool HasSelection() const;
|
||||
|
||||
void Copy();
|
||||
void Cut();
|
||||
void Paste();
|
||||
void Delete();
|
||||
|
||||
bool CanUndo() const;
|
||||
bool CanRedo() const;
|
||||
void Undo(int aSteps = 1);
|
||||
void Redo(int aSteps = 1);
|
||||
|
||||
static const Palette& GetDarkPalette();
|
||||
static const Palette& GetLightPalette();
|
||||
static const Palette& GetRetroBluePalette();
|
||||
|
||||
private:
|
||||
typedef std::vector<std::pair<std::regex, PaletteIndex>> RegexList;
|
||||
|
||||
struct EditorState
|
||||
{
|
||||
Coordinates mSelectionStart;
|
||||
Coordinates mSelectionEnd;
|
||||
Coordinates mCursorPosition;
|
||||
};
|
||||
|
||||
class UndoRecord
|
||||
{
|
||||
public:
|
||||
UndoRecord() {}
|
||||
~UndoRecord() {}
|
||||
|
||||
UndoRecord(
|
||||
const std::string& aAdded,
|
||||
const TextEditor::Coordinates aAddedStart,
|
||||
const TextEditor::Coordinates aAddedEnd,
|
||||
|
||||
const std::string& aRemoved,
|
||||
const TextEditor::Coordinates aRemovedStart,
|
||||
const TextEditor::Coordinates aRemovedEnd,
|
||||
|
||||
TextEditor::EditorState& aBefore,
|
||||
TextEditor::EditorState& aAfter);
|
||||
|
||||
void Undo(TextEditor* aEditor);
|
||||
void Redo(TextEditor* aEditor);
|
||||
|
||||
std::string mAdded;
|
||||
Coordinates mAddedStart;
|
||||
Coordinates mAddedEnd;
|
||||
|
||||
std::string mRemoved;
|
||||
Coordinates mRemovedStart;
|
||||
Coordinates mRemovedEnd;
|
||||
|
||||
EditorState mBefore;
|
||||
EditorState mAfter;
|
||||
};
|
||||
|
||||
typedef std::vector<UndoRecord> UndoBuffer;
|
||||
|
||||
void ProcessInputs();
|
||||
void Colorize(int aFromLine = 0, int aCount = -1);
|
||||
void ColorizeRange(int aFromLine = 0, int aToLine = 0);
|
||||
void ColorizeInternal();
|
||||
float TextDistanceToLineStart(const Coordinates& aFrom) const;
|
||||
void EnsureCursorVisible();
|
||||
int GetPageSize() const;
|
||||
std::string GetText(const Coordinates& aStart, const Coordinates& aEnd) const;
|
||||
Coordinates GetActualCursorCoordinates() const;
|
||||
Coordinates SanitizeCoordinates(const Coordinates& aValue) const;
|
||||
void Advance(Coordinates& aCoordinates) const;
|
||||
void DeleteRange(const Coordinates& aStart, const Coordinates& aEnd);
|
||||
int InsertTextAt(Coordinates& aWhere, const char* aValue);
|
||||
void AddUndo(UndoRecord& aValue);
|
||||
Coordinates ScreenPosToCoordinates(const ImVec2& aPosition) const;
|
||||
Coordinates FindWordStart(const Coordinates& aFrom) const;
|
||||
Coordinates FindWordEnd(const Coordinates& aFrom) const;
|
||||
Coordinates FindNextWord(const Coordinates& aFrom) const;
|
||||
int GetCharacterIndex(const Coordinates& aCoordinates) const;
|
||||
int GetCharacterColumn(int aLine, int aIndex) const;
|
||||
int GetLineCharacterCount(int aLine) const;
|
||||
int GetLineMaxColumn(int aLine) const;
|
||||
bool IsOnWordBoundary(const Coordinates& aAt) const;
|
||||
void RemoveLine(int aStart, int aEnd);
|
||||
void RemoveLine(int aIndex);
|
||||
Line& InsertLine(int aIndex);
|
||||
void EnterCharacter(ImWchar aChar, bool aShift);
|
||||
void Backspace();
|
||||
void DeleteSelection();
|
||||
std::string GetWordUnderCursor() const;
|
||||
std::string GetWordAt(const Coordinates& aCoords) const;
|
||||
ImU32 GetGlyphColor(const Glyph& aGlyph) const;
|
||||
|
||||
void HandleKeyboardInputs();
|
||||
void HandleMouseInputs();
|
||||
void Render();
|
||||
|
||||
float mLineSpacing;
|
||||
Lines mLines;
|
||||
EditorState mState;
|
||||
UndoBuffer mUndoBuffer;
|
||||
int mUndoIndex;
|
||||
|
||||
int mTabSize;
|
||||
bool mOverwrite;
|
||||
bool mReadOnly;
|
||||
bool mWithinRender;
|
||||
bool mScrollToCursor;
|
||||
bool mScrollToTop;
|
||||
bool mTextChanged;
|
||||
bool mColorizerEnabled;
|
||||
float mTextStart; // position (in pixels) where a code line starts relative to the left of the TextEditor.
|
||||
int mLeftMargin;
|
||||
bool mCursorPositionChanged;
|
||||
int mColorRangeMin, mColorRangeMax;
|
||||
SelectionMode mSelectionMode;
|
||||
bool mHandleKeyboardInputs;
|
||||
bool mHandleMouseInputs;
|
||||
bool mIgnoreImGuiChild;
|
||||
bool mShowWhitespaces;
|
||||
|
||||
Palette mPaletteBase;
|
||||
Palette mPalette;
|
||||
LanguageDefinition mLanguageDefinition;
|
||||
RegexList mRegexList;
|
||||
|
||||
bool mCheckComments;
|
||||
Breakpoints mBreakpoints;
|
||||
ErrorMarkers mErrorMarkers;
|
||||
ImVec2 mCharAdvance;
|
||||
Coordinates mInteractiveStart, mInteractiveEnd;
|
||||
std::string mLineBuffer;
|
||||
uint64_t mStartTime;
|
||||
|
||||
float mLastClick;
|
||||
};
|
3208
KP3Dii/ext/src/imgui/TextEditor.cpp
Normal file
3208
KP3Dii/ext/src/imgui/TextEditor.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -54,6 +54,107 @@ ksi::Cell FArithmetic()
|
|||
return cell;
|
||||
}
|
||||
|
||||
ksi::Cell FSin()
|
||||
{
|
||||
using namespace ksi;
|
||||
|
||||
Cell cell;
|
||||
cell.type = CELL_FUNCTION_CPP;
|
||||
cell.data = [](std::list<Cell> args) -> Cell { return {CELL_NUMBER, sinf(FromCell<float>(args.front()))}; };
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
ksi::Cell FCos()
|
||||
{
|
||||
using namespace ksi;
|
||||
|
||||
Cell cell;
|
||||
cell.type = CELL_FUNCTION_CPP;
|
||||
cell.data = [](std::list<Cell> args) -> Cell { return {CELL_NUMBER, cosf(FromCell<float>(args.front()))}; };
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
ksi::Cell FSqrt()
|
||||
{
|
||||
using namespace ksi;
|
||||
|
||||
Cell cell;
|
||||
cell.type = CELL_FUNCTION_CPP;
|
||||
cell.data = [](std::list<Cell> args) -> Cell { return { CELL_NUMBER, sqrtf(FromCell<float>(args.front())) }; };
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
ksi::Cell FAbs()
|
||||
{
|
||||
using namespace ksi;
|
||||
|
||||
Cell cell;
|
||||
cell.type = CELL_FUNCTION_CPP;
|
||||
cell.data = [](std::list<Cell> args) -> Cell { return { CELL_NUMBER, fabsf(FromCell<float>(args.front())) }; };
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
ksi::Cell FLog()
|
||||
{
|
||||
using namespace ksi;
|
||||
|
||||
Cell cell;
|
||||
cell.type = CELL_FUNCTION_CPP;
|
||||
cell.data = [](std::list<Cell> args) -> Cell { return { CELL_NUMBER, logf(FromCell<float>(args.front())) }; };
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
ksi::Cell FLog10()
|
||||
{
|
||||
using namespace ksi;
|
||||
|
||||
Cell cell;
|
||||
cell.type = CELL_FUNCTION_CPP;
|
||||
cell.data = [](std::list<Cell> args) -> Cell { return { CELL_NUMBER, log10f(FromCell<float>(args.front())) }; };
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
ksi::Cell FFloor()
|
||||
{
|
||||
using namespace ksi;
|
||||
|
||||
Cell cell;
|
||||
cell.type = CELL_FUNCTION_CPP;
|
||||
cell.data = [](std::list<Cell> args) -> Cell { return { CELL_NUMBER, floorf(FromCell<float>(args.front())) }; };
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
ksi::Cell FCeil()
|
||||
{
|
||||
using namespace ksi;
|
||||
|
||||
Cell cell;
|
||||
cell.type = CELL_FUNCTION_CPP;
|
||||
cell.data = [](std::list<Cell> args) -> Cell { return { CELL_NUMBER, ceilf(FromCell<float>(args.front())) }; };
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
ksi::Cell FAtan2()
|
||||
{
|
||||
using namespace ksi;
|
||||
|
||||
Cell cell;
|
||||
cell.type = CELL_FUNCTION_CPP;
|
||||
cell.data = [](std::list<Cell> args) -> Cell {
|
||||
return {CELL_NUMBER, atan2(FromCell<float>(args.front()), FromCell<float>(args.back()))};
|
||||
};
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
ksi::Cell FCar()
|
||||
{
|
||||
using namespace ksi;
|
||||
|
@ -414,11 +515,22 @@ Cell* Environment::Get(const std::string& sym_key)
|
|||
|
||||
void Environment::Init()
|
||||
{
|
||||
// Basic arithmetic
|
||||
// Math
|
||||
Set("+", FArithmetic<'+'>());
|
||||
Set("-", FArithmetic<'-'>());
|
||||
Set("*", FArithmetic<'*'>());
|
||||
Set("/", FArithmetic<'/'>());
|
||||
Set("sin", FSin());
|
||||
Set("cos", FCos());
|
||||
Set("sqrt", FSqrt());
|
||||
Set("abs", FAbs());
|
||||
Set("log", FLog());
|
||||
Set("log10", FLog10());
|
||||
Set("floor", FFloor());
|
||||
Set("ceil", FCeil());
|
||||
Set("atan2", FAtan2());
|
||||
Set("PI", {CELL_NUMBER, 3.14159265358979f});
|
||||
Set("E", {CELL_NUMBER, 2.71828f});
|
||||
|
||||
// Cons/CAR/CDR
|
||||
Set("car", FCar());
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <imgui.h>
|
||||
#include <ImGuizmo.h>
|
||||
#include <TextEditor.h>
|
||||
|
||||
#include "KP3D_Renderer3D.h"
|
||||
#include "KP3D_StaticMesh.h"
|
||||
|
@ -33,6 +34,62 @@ inline float Distance(kp3d::Vec3 a, kp3d::Vec3 b)
|
|||
return sqrtf((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y) + (b.z - a.z) * (b.z - a.z));
|
||||
}
|
||||
|
||||
ksi::Cell FMakeSectorFromPoints()
|
||||
{
|
||||
using namespace ksi;
|
||||
using namespace kp3d;
|
||||
|
||||
Cell cell;
|
||||
cell.type = CELL_FUNCTION_CPP;
|
||||
cell.data = [](std::list<Cell> args) -> Cell {
|
||||
auto it = args.begin();
|
||||
Cell c_floor_height = *it++;
|
||||
Cell c_ceiling_height = *it++;
|
||||
Cell c_pt_list = *it++;
|
||||
|
||||
std::vector<Vec3> pts;
|
||||
std::list<Cell> pt_list = FromCell<std::list<Cell>>(c_pt_list);
|
||||
for (const Cell& c: pt_list)
|
||||
{
|
||||
Cell c_x = Car(c);
|
||||
Cell c_y = Car(Cdr(c));
|
||||
pts.emplace_back(FromCell<float>(c_x), 0.0f, FromCell<float>(c_y));
|
||||
}
|
||||
|
||||
// build da ting!!
|
||||
std::shared_ptr<Sector> s = std::make_shared<Sector>();
|
||||
s->ceiling.material = res::material_cache["block.png"].get();
|
||||
s->floor.material = res::material_cache["block.png"].get();
|
||||
s->floor.floor = true;
|
||||
s->floor.base_height = 0.0f;
|
||||
s->ceiling.base_height = 4.0f;
|
||||
s->id = sandbox->map.sectors.size() + 1;
|
||||
s->parent_id = 0;
|
||||
s->inverted = false;
|
||||
|
||||
for (int i = 0; i < pts.size(); i++)
|
||||
{
|
||||
Wall wall;
|
||||
wall.start = {pts[i].x, -pts[i].z};
|
||||
wall.end = {pts[(i + 1) % pts.size()].x, -pts[(i + 1) % pts.size()].z};
|
||||
wall.uid = i;
|
||||
wall.flags = Wall::NO_FLAGS;
|
||||
wall.user_flags = Wall::NO_UFLAGS;
|
||||
for (int j = 0; j < 3; j++)
|
||||
wall.materials[j] = res::material_cache["block.png"].get();
|
||||
|
||||
s->walls.push_back(wall);
|
||||
}
|
||||
|
||||
sandbox->map.sectors.push_back(s);
|
||||
sandbox->editor.RebuildMap();
|
||||
|
||||
return {CELL_NUMBER, s->id};
|
||||
};
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Editor::Editor()
|
||||
|
@ -42,8 +99,15 @@ Editor::Editor()
|
|||
// m_block.Load("block.png", true);
|
||||
m_mode = MODE_NORMAL;
|
||||
|
||||
auto lang = TextEditor::LanguageDefinition::Lisp();
|
||||
build_text_editor.SetLanguageDefinition(lang);
|
||||
build_text_editor.SetText("()");
|
||||
|
||||
kp3d::EventBus::Subscribe(this, &Editor::OnScrollWheel);
|
||||
kp3d::EventBus::Subscribe(this, &Editor::OnKeyPress);
|
||||
|
||||
// Put in our fancy Lisp integration stuff
|
||||
kp3d::console::environment.Set("make-sector-from-points", FMakeSectorFromPoints());
|
||||
}
|
||||
|
||||
Editor::~Editor()
|
||||
|
@ -56,14 +120,14 @@ void Editor::Init()
|
|||
|
||||
void Editor::Update()
|
||||
{
|
||||
if (anything_hovered)
|
||||
return;
|
||||
|
||||
#define KEY_SHORTCUT(key, action) if (sandbox->IsKeyDown(kp3d::KEY_##key)) { action; sandbox->KeyReset(kp3d::KEY_##key); }
|
||||
|
||||
KEY_SHORTCUT(SPACE, m_mode = MODE_NORMAL);
|
||||
KEY_SHORTCUT(V, m_mode = MODE_BUILD);
|
||||
|
||||
if (anything_hovered)
|
||||
return;
|
||||
|
||||
switch (m_mode)
|
||||
{
|
||||
case MODE_BUILD: UpdateModeBuild(); break;
|
||||
|
@ -115,11 +179,11 @@ void Editor::RebuildMap()
|
|||
|
||||
void Editor::UpdateModeBuild()
|
||||
{
|
||||
if (sandbox->IsMouseButtonDown(kp3d::MOUSE_BUTTON_LEFT))
|
||||
if (sandbox->IsMouseButtonDown(kp3d::MOUSE_BUTTON_LEFT) && !build_show_options)
|
||||
{
|
||||
points.push_back(m_stem_pos);
|
||||
|
||||
if (points.size() >= 3 && kp3d::PosCmp(points.back(), points.front(), 1.0f / 128.0f))// points.back() == points.front())
|
||||
if (points.size() >= 3 && kp3d::PosCmp(points.back(), points.front(), 1.0f / 128.0f)) // points.back() == points.front())
|
||||
{
|
||||
std::shared_ptr<kp3d::Sector> s = std::make_shared<kp3d::Sector>();
|
||||
s->ceiling.material = kp3d::res::material_cache["block.png"].get();
|
||||
|
@ -150,54 +214,59 @@ void Editor::UpdateModeBuild()
|
|||
|
||||
sandbox->MouseButtonReset(kp3d::MOUSE_BUTTON_LEFT);
|
||||
}
|
||||
static kp3d::Vec3 start_pos;
|
||||
static bool has_start_pos = false;
|
||||
if (sandbox->IsMouseButtonDown(kp3d::MOUSE_BUTTON_RIGHT))
|
||||
{
|
||||
if (!has_start_pos)
|
||||
if (!build_has_start_pos)
|
||||
{
|
||||
start_pos = m_stem_pos;
|
||||
has_start_pos = true;
|
||||
build_start_pos = m_stem_pos;
|
||||
build_has_start_pos = true;
|
||||
}
|
||||
points.clear();
|
||||
points.emplace_back(m_stem_pos.x, start_pos.y, m_stem_pos.z);
|
||||
points.emplace_back(start_pos.x, start_pos.y, m_stem_pos.z);
|
||||
points.emplace_back(start_pos.x, start_pos.y, start_pos.z);
|
||||
points.emplace_back(m_stem_pos.x, start_pos.y, start_pos.z);
|
||||
points.emplace_back(m_stem_pos.x, start_pos.y, m_stem_pos.z);
|
||||
points.emplace_back(m_stem_pos.x, build_start_pos.y, m_stem_pos.z);
|
||||
points.emplace_back(build_start_pos.x, build_start_pos.y, m_stem_pos.z);
|
||||
points.emplace_back(build_start_pos.x, build_start_pos.y, build_start_pos.z);
|
||||
points.emplace_back(m_stem_pos.x, build_start_pos.y, build_start_pos.z);
|
||||
points.emplace_back(m_stem_pos.x, build_start_pos.y, m_stem_pos.z);
|
||||
std::reverse(points.begin(), points.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (has_start_pos)
|
||||
if (sandbox->IsKeyDown(kp3d::KEY_LCTRL))
|
||||
{
|
||||
std::shared_ptr<kp3d::Sector> s = std::make_shared<kp3d::Sector>();
|
||||
s->ceiling.material = kp3d::res::material_cache["block.png"].get();
|
||||
s->floor.material = kp3d::res::material_cache["block.png"].get();
|
||||
s->floor.floor = true;
|
||||
s->floor.base_height = 0.0f;
|
||||
s->ceiling.base_height = 4.0f;
|
||||
s->id = sandbox->map.sectors.size() + 1;
|
||||
s->parent_id = 0;
|
||||
s->inverted = false;
|
||||
for (int i = 0; i < points.size() - 1; i++)
|
||||
build_show_options = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (build_has_start_pos && !build_show_options)
|
||||
{
|
||||
kp3d::Wall wall;
|
||||
wall.start = { points[i].x, -points[i].z };
|
||||
wall.end = { points[i + 1].x, -points[i + 1].z };
|
||||
wall.uid = i;
|
||||
wall.flags = kp3d::Wall::NO_FLAGS;
|
||||
wall.user_flags = kp3d::Wall::NO_UFLAGS;
|
||||
for (int j = 0; j < 3; j++)
|
||||
wall.materials[j] = kp3d::res::material_cache["block.png"].get();
|
||||
std::shared_ptr<kp3d::Sector> s = std::make_shared<kp3d::Sector>();
|
||||
s->ceiling.material = kp3d::res::material_cache["block.png"].get();
|
||||
s->floor.material = kp3d::res::material_cache["block.png"].get();
|
||||
s->floor.floor = true;
|
||||
s->floor.base_height = 0.0f;
|
||||
s->ceiling.base_height = 4.0f;
|
||||
s->id = sandbox->map.sectors.size() + 1;
|
||||
s->parent_id = 0;
|
||||
s->inverted = false;
|
||||
for (int i = 0; i < points.size() - 1; i++)
|
||||
{
|
||||
kp3d::Wall wall;
|
||||
wall.start = { points[i].x, -points[i].z };
|
||||
wall.end = { points[i + 1].x, -points[i + 1].z };
|
||||
wall.uid = i;
|
||||
wall.flags = kp3d::Wall::NO_FLAGS;
|
||||
wall.user_flags = kp3d::Wall::NO_UFLAGS;
|
||||
for (int j = 0; j < 3; j++)
|
||||
wall.materials[j] = kp3d::res::material_cache["block.png"].get();
|
||||
|
||||
s->walls.push_back(wall);
|
||||
s->walls.push_back(wall);
|
||||
}
|
||||
|
||||
sandbox->map.sectors.push_back(s);
|
||||
RebuildMap();
|
||||
points.clear();
|
||||
build_has_start_pos = false;
|
||||
}
|
||||
|
||||
sandbox->map.sectors.push_back(s);
|
||||
RebuildMap();
|
||||
points.clear();
|
||||
has_start_pos = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -210,7 +279,7 @@ void Editor::RenderModeBuild()
|
|||
for (int i = 0; i < points.size() - 1; i++)
|
||||
RenderLine(points[i], points[i + 1], 0xFF00FFFF);
|
||||
}
|
||||
if (points.size() > 0)
|
||||
if (points.size() > 0 && !build_show_options)
|
||||
RenderLine(points.back(), m_stem_pos, 0xFFFF00FF);
|
||||
|
||||
// Render the "stem"
|
||||
|
@ -224,6 +293,24 @@ void Editor::RenderModeBuild()
|
|||
pos.z = Align(pos.z, 1.0f);
|
||||
RenderStem(pos);
|
||||
m_stem_pos = pos;
|
||||
|
||||
if (build_show_options)
|
||||
{
|
||||
ImGui::SetNextWindowSize({320, 240}, ImGuiCond_FirstUseEver);
|
||||
if (ImGui::Begin("Build Options", &build_show_options))
|
||||
{
|
||||
ImGui::SeparatorText("Shortcuts");
|
||||
if (ImGui::Button("build-box")) {} ImGui::SameLine();
|
||||
if (ImGui::Button("build-stairs")) {} ImGui::SameLine();
|
||||
if (ImGui::Button("build-slope")) {}
|
||||
|
||||
ImGui::SeparatorText("Custom Routine");
|
||||
ImGui::Button("Evaluate");
|
||||
build_text_editor.Render("Lisp:");
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::UpdateModeNormal()
|
||||
|
@ -370,7 +457,7 @@ void Editor::UpdateModeNormal()
|
|||
Wall& wall = sp->walls[i];
|
||||
Wall& neighbor = sp->walls[(i - 1) % sp->walls.size()];
|
||||
if (&wall == info.wall)
|
||||
neighbor.end = wall.end;
|
||||
neighbor.end = wall.end; // TODO: Revisit this
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -731,13 +818,19 @@ void Editor::RenderUIInfo()
|
|||
case MODE_BUILD: mode_str = "Build"; break;
|
||||
}
|
||||
ImGui::Text("Mode: %s\n", mode_str.c_str());
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Caret Position: (%.1f, %.1f, %.1f)", m_stem_pos.x, m_stem_pos.y, m_stem_pos.z);
|
||||
if (ImGui::BeginPopupContextWindow())
|
||||
if (m_mode == MODE_BUILD)
|
||||
{
|
||||
if (ImGui::MenuItem("Hide", NULL, show_info_overlay == false))
|
||||
show_info_overlay = false;
|
||||
ImGui::EndPopup();
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Caret Position: (%.1f, %.1f, %.1f)", m_stem_pos.x, m_stem_pos.y, m_stem_pos.z);
|
||||
ImGui::Text("MOUSE1 - place individual points");
|
||||
ImGui::Text("MOUSE2 - place box");
|
||||
ImGui::Text("MOUSE2 + LCTRL - place box with options");
|
||||
if (ImGui::BeginPopupContextWindow())
|
||||
{
|
||||
if (ImGui::MenuItem("Hide", NULL, show_info_overlay == false))
|
||||
show_info_overlay = false;
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <map>
|
||||
|
||||
#include <TextEditor.h>
|
||||
|
||||
#include "KP3D_Texture.h"
|
||||
#include "KP3D_Math.h"
|
||||
#include "KP3D_IOEvents.h"
|
||||
|
@ -56,6 +58,9 @@ public:
|
|||
private:
|
||||
void RenderLine(kp3d::Vec3 start, kp3d::Vec3 end, kp3d::uint color);
|
||||
|
||||
public:
|
||||
bool anything_hovered = false;
|
||||
|
||||
private:
|
||||
kp3d::Texture m_banner;
|
||||
kp3d::Texture m_stem;
|
||||
|
@ -68,7 +73,6 @@ private:
|
|||
bool show_about_view = false;
|
||||
bool should_show_material_modal = false;
|
||||
char m_tex_filter_buf[512];
|
||||
bool anything_hovered = false;
|
||||
bool editing_gizmo = false;
|
||||
std::vector<const kp3d::Material**> m_materials_to_update;
|
||||
|
||||
|
@ -79,4 +83,10 @@ private:
|
|||
kp3d::Vec3 ray_pos;
|
||||
bool uv_adjusting = false;
|
||||
|
||||
kp3d::Vec3 build_start_pos;
|
||||
kp3d::Vec3 build_end_pos;
|
||||
bool build_has_start_pos = false;
|
||||
bool build_show_options = false;
|
||||
TextEditor build_text_editor;
|
||||
|
||||
};
|
||||
|
|
|
@ -88,15 +88,6 @@ void Sandbox::Update()
|
|||
//KeyReset(kp3d::KEY_B);
|
||||
}
|
||||
|
||||
if (IsKeyDown(kp3d::KEY_Y))
|
||||
map.test_u += 0.1f;
|
||||
if (IsKeyDown(kp3d::KEY_H))
|
||||
map.test_u -= 0.1f;
|
||||
if (IsKeyDown(kp3d::KEY_U))
|
||||
map.test_l += 0.1f;
|
||||
if (IsKeyDown(kp3d::KEY_J))
|
||||
map.test_l -= 0.1f;
|
||||
|
||||
// Mouse-look
|
||||
if (IsKeyDown(kp3d::KEY_ESCAPE))
|
||||
{
|
||||
|
@ -105,10 +96,13 @@ void Sandbox::Update()
|
|||
}
|
||||
float qerf_speed = 1.0f;
|
||||
float move_speed = 0.2f;
|
||||
if (IsKeyDown(kp3d::KEY_W)) camera.Move(camera.forward, move_speed);
|
||||
if (IsKeyDown(kp3d::KEY_S)) camera.Move(camera.forward, -move_speed);
|
||||
if (IsKeyDown(kp3d::KEY_A)) camera.Move(camera.right, move_speed);
|
||||
if (IsKeyDown(kp3d::KEY_D)) camera.Move(camera.right, -move_speed);
|
||||
if (!editor.anything_hovered)
|
||||
{
|
||||
if (IsKeyDown(kp3d::KEY_W)) camera.Move(camera.forward, move_speed);
|
||||
if (IsKeyDown(kp3d::KEY_S)) camera.Move(camera.forward, -move_speed);
|
||||
if (IsKeyDown(kp3d::KEY_A)) camera.Move(camera.right, move_speed);
|
||||
if (IsKeyDown(kp3d::KEY_D)) camera.Move(camera.right, -move_speed);
|
||||
}
|
||||
//if (IsKeyDown(kp3d::KEY_SPACE)) camera.position.y += move_speed;
|
||||
//if (IsKeyDown(kp3d::KEY_LSHIFT)) camera.position.y -= move_speed;
|
||||
//if (IsKeyDown(kp3d::KEY_Q)) camera.Rotate(kp3d::Camera::AXIS_X, qerf_speed);
|
||||
|
|
Loading…
Reference in a new issue