new stuff

This commit is contained in:
Tim Nebel 2023-07-02 22:21:26 +02:00
commit c595421288
44 changed files with 2556 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*build*

15
.gitmodules vendored Normal file
View file

@ -0,0 +1,15 @@
[submodule "deps/vgcore/deps/assimp"]
path = deps/vgcore/deps/assimp
url = https://github.com/assimp/assimp.git
[submodule "deps/vgcore/deps/glm"]
path = deps/vgcore/deps/glm
url = https://github.com/g-truc/glm.git
[submodule "deps/vgcore/deps/glfw"]
path = deps/vgcore/deps/glfw
url = https://github.com/glfw/glfw.git
[submodule "deps/vgcore/deps/IconFontCppHeaders"]
path = deps/vgcore/deps/IconFontCppHeaders
url = https://github.com/juliettef/IconFontCppHeaders.git
[submodule "deps/vgcore/deps/imgui/imgui"]
path = deps/vgcore/deps/imgui/imgui
url = https://gitlab.com/virintox/imgui.git

8
.idea/.gitignore generated vendored Normal file
View file

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

1
.idea/.name generated Normal file
View file

@ -0,0 +1 @@
SpoonTool

2
.idea/SpoonEdit.iml generated Normal file
View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />

4
.idea/misc.xml generated Normal file
View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

8
.idea/modules.xml generated Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/SpoonEdit.iml" filepath="$PROJECT_DIR$/.idea/SpoonEdit.iml" />
</modules>
</component>
</project>

8
.idea/vcs.xml generated Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/Tools/MapTools/deps/vserialize" vcs="Git" />
<mapping directory="$PROJECT_DIR$/deps/vgcore" vcs="Git" />
</component>
</project>

24
CMakeLists.txt Normal file
View file

@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 3.25)
project(SpoonTool)
set (CMAKE_CXX_STANDARD 20)
find_package(Boost REQUIRED COMPONENTS thread chrono)
add_subdirectory(deps/vgcore)
add_subdirectory(Tools/MapTools)
add_executable(SpoonEdit src/main.cpp src/MainWindow.cpp src/MainWindow.h src/PropertiesWidget.cpp src/PropertiesWidget.h src/ObjectSelectWidget.cpp src/ObjectSelectWidget.h src/MainViewport.cpp src/MainViewport.h src/Model.cpp src/Model.h src/RailSelectWidget.cpp src/RailSelectWidget.h)
target_link_libraries(SpoonEdit PUBLIC GCore SpoonMapTools Boost::thread Boost::chrono)
install(TARGETS SpoonEdit
CONFIGURATIONS Debug
RUNTIME DESTINATION Debug
LIBRARY DESTINATION Debug)
install(TARGETS SpoonEdit
CONFIGURATIONS Release
RUNTIME DESTINATION Release
LIBRARY DESTINATION Release)

7
License.txt Normal file
View file

@ -0,0 +1,7 @@
Copyright 2023 DJMrTV
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 3.25)
project(SpoonMapTools)
set(CMAKE_CXX_STANDARD 20)
find_package(Boost REQUIRED COMPONENTS filesystem iostreams)
find_package(GLEW REQUIRED)
find_package(yaml-cpp REQUIRED)
add_library(SpoonMapTools STATIC src/Map.cpp include/Map.h include/LevelObject.h include/Transform.h "include/Vector3.h" src/Vectior3.cpp src/Transform.cpp src/LevelObject.cpp include/Link.h src/Link.cpp include/Rail.h src/Rail.cpp include/RailPoint.h src/RailPoint.cpp include/SpecialObjectParams.h src/SpecialObjectParams.cpp include/SpecialObjectParamVersions/All.h include/SpecialObjectParamVersions/Default.h include/LayerConfig.h include/LayerConfig.h include/Element.h src/Element.cpp)
target_include_directories(SpoonMapTools PUBLIC include)
target_link_libraries(SpoonMapTools PUBLIC Boost::filesystem Boost::iostreams GLEW::GLEW yaml-cpp)

View file

@ -0,0 +1,116 @@
//
// Created by tv on 29.06.23.
//
#ifndef SPOONTOOL_ELEMENT_H
#define SPOONTOOL_ELEMENT_H
#include<list>
#include<string>
#include"Transform.h"
#include"Link.h"
enum LayerConfig{
Common, //Cmn
Paint, //Pnt
//Online, //Vss
Rainmaker, //Vlf
Tower, //Vgl
Area, //Var
Night, //Night
Day, //Day
Temporary //Tmp
};
inline std::string ToStringYaml(LayerConfig cfg){
if(cfg == Common){
return "Cmn";
} else if(cfg == Paint){
return "Pnt";
} else if(cfg == Rainmaker) {
return "Vlf";
} else if(cfg == Tower) {
return "Vgl";
} else if(cfg == Area) {
return "Var";
} else if(cfg == Night) {
return "Night";
} else if(cfg == Day) {
return "Day";
} else if(cfg == Temporary) {
return "Tmp";
}
}
inline std::string ToString(LayerConfig cfg){
if(cfg == Common){
return "Common";
} else if(cfg == Paint){
return "Paint";
} else if(cfg == Rainmaker) {
return "Rainmaker";
} else if(cfg == Tower) {
return "Tower";
} else if(cfg == Area) {
return "Area";
} else if(cfg == Night) {
return "Night";
} else if(cfg == Day) {
return "Day";
} else if(cfg == Temporary) {
return "Temporary";
}
}
inline LayerConfig ToLayerConfig(std::string cfg){
if(cfg == "Cmn"){
return Common;
} else if(cfg == "Pnt"){
return Paint;
} else if(cfg == "Vlf") {
return Rainmaker;
} else if(cfg == "Vgl") {
return Tower;
} else if(cfg == "Var") {
return Area;
} else if(cfg == "Night") {
return Night;
} else if(cfg == "Day") {
return Day;
} else if(cfg == "Tmp") {
return Temporary;
}
}
class Element{
public:
Element() = default;
Element(const YAML::Node &ObjNode,std::list<std::string> PropertyBlockList = {});
unsigned int runtimeID = static_cast<unsigned int>(rand());
Transform TF = Transform();
std::string Type = "Unnamed Type";
std::string Name = "Unnamed Element";
std::string ModelName = "null";
LayerConfig Layer = Common;
std::vector<long> Parameters = std::vector<long>();
std::vector<float> FloatParameters = std::vector<float>();
//std::map<std::string,std::vector<Link>> Links = std::map<std::string,std::vector<Link>>();
std::vector<Link> Links = std::vector<Link>();
std::map<std::string,std::string> OtherOptions = std::map<std::string,std::string>();
bool IsLinkDest = false;
void YamlInsert(YAML::Emitter &Emitter);
virtual ~Element() = default;
protected:
virtual void YamlInsertBody(YAML::Emitter &Emitter);
};
#endif //SPOONTOOL_ELEMENT_H

View file

@ -0,0 +1,89 @@
//
// Created by tv on 30.04.23.
//
#ifndef SPOONTOOL_LEVELOBJECT_H
#define SPOONTOOL_LEVELOBJECT_H
#include<Transform.h>
#include<Link.h>
#include<yaml-cpp/yaml.h>
#include "SpecialObjectParams.h"
#include "Element.h"
namespace Teams{
constexpr long Player = 0;
constexpr long Neutral = 1;
constexpr long Enemy = 2;
constexpr std::array<long,3> AllOptions = {Player,Neutral,Enemy};
inline constexpr std::string TeamToText(long team) {
switch(team){
case 0:
return "Player";
case 1:
return "Neutral";
case 2:
return "Enemy";
default:
return "Invalid";
}
}
}
namespace DropId{
constexpr long Default = -1;
constexpr long Armor = 8;
constexpr long Map = 9;
constexpr long Key = 10;
constexpr long OneSphere = 11;
constexpr long FiveSphere = 12;
constexpr long TenSphere = 13;
constexpr long Bubbler = 14;
constexpr long Bazooka = 15;
constexpr std::array<long,9> AllOptions = {Default,Armor,Map,Key,OneSphere,FiveSphere,TenSphere,Bubbler,Bazooka};
inline constexpr std::string DropIdToText(long team) {
switch(team){
case -1:
return "Default";
case 8:
return "Armor";
case 9:
return "Map";
case 10:
return "Key";
case 11:
return "1 Sphere";
case 12:
return "5 Spheres";
case 13:
return "10 Spheres";
case 14:
return "Bubbler";
case 15:
return "Bazooka";
default:
return "Invalid";
}
}
}
struct LevelObject: public Element{
LevelObject(const YAML::Node &ObjNode);
protected:
void YamlInsertBody(YAML::Emitter &Emitter) override;
public:
long Team;
long DropId;
~LevelObject() = default;
};
#endif //SPOONTOOL_LEVELOBJECT_H

View file

@ -0,0 +1,45 @@
//
// Created by tv on 30.04.23.
//
#ifndef SPOONTOOL_LINK_H
#define SPOONTOOL_LINK_H
#include <yaml-cpp/yaml.h>
#include<string>
constexpr std::array<const char*, 12> LinkTypes = {
"Spawner",
"Rail",
"Area",
"AutoWarpPointLink",
"Switch",
"SwitchSender",
"LiftBindable",
"GraphNode",
"ObjToGraphNode",
"ObjToGraphNodeOneway",
"BoneBindable",
"ToGachihokoTargetPoint",
};
struct Link {
inline Link() : Name("Rail"), Destination("Undefined Destination"), UnitFile("") {}
Link(const YAML::Node &ObjNode);
// DefinitionName in byaml
std::string Name;
// DestUnitId in byaml
std::string Destination;
// UnitFileName in byaml
static constexpr char LinkUnitFileID[] = "UnitFile";
std::string UnitFile;
void InsertIntoYaml(YAML::Emitter &Emitter);
};
#endif //SPOONTOOL_LINK_H

View file

@ -0,0 +1,33 @@
//
// Created by tv on 30.04.23.
//
#ifndef SPOONTOOL_MAP_H
#define SPOONTOOL_MAP_H
#include<boost/filesystem.hpp>
#include<LevelObject.h>
#include<Rail.h>
struct Map {
//STREEFUNCS
Map();
void Save(boost::filesystem::path FileLocation);
boost::filesystem::path ActiveLocation = "";
void Export(boost::filesystem::path YamlOut);
std::vector<LevelObject> Objects;
std::vector<Rail> Rails;
};
Map ConvertFromYaml(boost::filesystem::path File);
#endif //SPOONTOOL_MAP_H

View file

@ -0,0 +1,57 @@
//
// Created by tv on 30.04.23.
//
#ifndef SPOONTOOL_RAIL_H
#define SPOONTOOL_RAIL_H
#include<Transform.h>
#include<Link.h>
#include<RailPoint.h>
#include<yaml-cpp/yaml.h>
#include<RailPoint.h>
#include "Element.h"
enum RailType{
Linear,
Bezier
};
inline std::string ToString(RailType railType){
if(railType == Linear){
return "Linear";
} else if(railType == Bezier){
return "Bezier";
}
}
inline RailType ToRailType(std::string railType){
if(railType == "Linear"){
return Linear;
} else if(railType == "Bezier"){
return Bezier;
}
}
constexpr std::array<RailType,2> AllRailTypeOptions = {Linear,Bezier};
struct Rail: public Element{
Rail(const YAML::Node &ObjNode);
explicit Rail(const Vector3 &Position);
std::list<RailPoint> Points = std::list<RailPoint>();
RailType RailType = Linear;
bool IsClosed = false;
bool IsLadder = false;
long Priority = 100;
~Rail() override = default;
protected:
void YamlInsertBody(YAML::Emitter &Emitter) override;
};
#endif //SPOONTOOL_RAIL_H

View file

@ -0,0 +1,33 @@
//
// Created by tv on 30.04.23.
//
#ifndef SPOONTOOL_RAILPOINT_H
#define SPOONTOOL_RAILPOINT_H
#include<Vector3.h>
#include<Transform.h>
#include<Link.h>
#include<yaml-cpp/yaml.h>
#include"Element.h"
struct RailPoint: public Element{
RailPoint(const YAML::Node &ObjNode);
explicit RailPoint(const Vector3& pos);
protected:
void YamlInsertBody(YAML::Emitter &Emitter) override;
public:
std::vector<Vector3> m_controlPoints = std::vector<Vector3>();
Vector3 m_offset = {0,0,0};
bool m_useOffset = false;
~RailPoint() override = default;
};
#endif //SPOONTOOL_RAILPOINT_H

View file

@ -0,0 +1,18 @@
//
// Created by tv on 09.05.23.
//
#ifndef SPOONTOOL_ALL_H
#define SPOONTOOL_ALL_H
#include<SpecialObjectParams.h>
inline SpecialObjectParams* GetSpecParamsBySpoonID(std::string spoontype){
return new SpecialObjectParams();
}
inline SpecialObjectParams* GetSpecParamsBySubID(std::string spoontype){
return new SpecialObjectParams();
}
#endif //SPOONTOOL_ALL_H

View file

@ -0,0 +1,24 @@
//
// Created by tv on 09.05.23.
//
#ifndef SPOONTOOL_DEFAULT_H
#define SPOONTOOL_DEFAULT_H
#include<SpecialObjectParams.h>
class DefaultObjParams : public SpecialObjectParams {
public:
DefaultObjParams() : SpecialObjectParams(){
}
void ParseOut(YAML::Node node) override {
return;
}
void InsertYaml(YAML::Emitter &Emitter) override {
}
};
#endif //SPOONTOOL_DEFAULT_H

View file

@ -0,0 +1,23 @@
//
// Created by tv on 07.05.23.
//
#ifndef SPOONTOOL_SPECIALOBJECTPARAMS_H
#define SPOONTOOL_SPECIALOBJECTPARAMS_H
#include<yaml-cpp/yaml.h>
struct SpecialObjectParams {
public:
SpecialObjectParams();
virtual void ParseOut(YAML::Node node);
virtual void InsertYaml(YAML::Emitter& Emitter);
virtual ~SpecialObjectParams() = default;
std::vector<std::string> GetMiscParamBlockList();
};
#endif //SPOONTOOL_SPECIALOBJECTPARAMS_H

View file

@ -0,0 +1,19 @@
//
// Created by tv on 30.04.23.
//
#ifndef SPOONTOOL_TRANSFORM_H
#define SPOONTOOL_TRANSFORM_H
#include<Vector3.h>
#include<yaml-cpp/yaml.h>
struct Transform{
inline Transform(): Position(0,0,0), Scale(1,1,1), Rotation(0,0,0) {}
Vector3 Position,Scale,Rotation;
void InsertIntoYaml(YAML::Emitter &Emitter);
};
#endif //SPOONTOOL_TRANSFORM_H

View file

@ -0,0 +1,29 @@
//
// Created by tv on 30.04.23.
//
#ifndef SPOONTOOL_VECTOR3_H
#define SPOONTOOL_VECTOR3_H
#include <yaml-cpp/yaml.h>
#include<boost/algorithm/string.hpp>
#include<iostream>
struct Vector3{
Vector3(YAML::Node node);
float X,Y,Z;
inline Vector3(float x,float y,float z) : X(x),Y(y),Z(z){}
inline void InsertIntoYaml(YAML::Emitter &Emitter){
Emitter << YAML::BeginMap;
Emitter << YAML::Key << "X" << YAML::Value << X;
Emitter << YAML::Key << "Y" << YAML::Value << Y;
Emitter << YAML::Key << "Z" << YAML::Value << Z;
Emitter << YAML::EndMap;
}
};
#endif //SPOONTOOL_VECTOR3_H

View file

@ -0,0 +1,143 @@
#include<Element.h>
#include<algorithm>
Element::Element(const YAML::Node &ObjNode,std::list<std::string> PropertyBlockList) {
PropertyBlockList.emplace_back("Id");
PropertyBlockList.emplace_back("UnitConfigName");
PropertyBlockList.emplace_back("LayerConfigName");
PropertyBlockList.emplace_back("Translate");
PropertyBlockList.emplace_back("Rotate");
PropertyBlockList.emplace_back("Scale");
PropertyBlockList.emplace_back("Links");
PropertyBlockList.emplace_back("ModelName");
PropertyBlockList.emplace_back("IsLinkDest");
runtimeID = static_cast<unsigned int>(rand());
Name = ObjNode["Id"].as<std::string>();
Type = ObjNode["UnitConfigName"].as<std::string>();
TF.Position = ObjNode["Translate"];
TF.Rotation = ObjNode["Rotate"];
TF.Scale = ObjNode["Scale"];
Layer = ToLayerConfig(ObjNode["LayerConfigName"].as<std::string>());
ModelName = ObjNode["ModelName"].as<std::string>();
IsLinkDest = ObjNode["IsLinkDest"].as<bool>();
unsigned int ParamId = 1;
while(YAML::Node ParamNode = ObjNode["Parameter" + std::to_string(ParamId)]){
Parameters.push_back(ParamNode.as<long>());
ParamId++;
}
unsigned int FloatParamId = 1;
while(YAML::Node ParamNode = ObjNode["FloatParameter" + std::to_string(FloatParamId)]){
FloatParameters.push_back(ParamNode.as<float>());
FloatParamId++;
}
YAML::Node LinksNode = ObjNode["Links"];
for(YAML::const_iterator it2 = LinksNode.begin();it2 != LinksNode.end();++it2) {
auto node2 = it2->second;
for(auto link: node2){
Links.emplace_back(link);
}
}
for(YAML::const_iterator it=ObjNode.begin();it != ObjNode.end();++it) {
std::string OptName = it->first.as<std::string>();
if(OptName.starts_with("Parameter") || OptName.starts_with("FloatParameter"))
continue;
if(std::any_of(PropertyBlockList.begin(), PropertyBlockList.end(),[&](std::string str){ return str == OptName;}))
continue;
auto node = it->second;
auto str = node.as<std::string>();
if(node.Tag() == "!l")
str = "!l " + str;
OtherOptions.insert({OptName,str});
}
}
void Element::YamlInsert(YAML::Emitter &Emitter) {
Emitter << YAML::BeginMap;
YamlInsertBody(Emitter);
Emitter << YAML::EndMap;
}
void Element::YamlInsertBody(YAML::Emitter &Emitter) {
Emitter << YAML::Key << "Id" << YAML::Value << Name;
TF.InsertIntoYaml(Emitter);
Emitter << YAML::Key << "UnitConfigName" << YAML::Value << Type;
Emitter << YAML::Key << "LayerConfigName" << YAML::Value << ToStringYaml(Layer);
if(ModelName == "null") {
Emitter << YAML::Key << "ModelName" << YAML::Value << YAML::LowerNull << YAML::Null;
} else {
Emitter << YAML::Key << "ModelName" << YAML::Value << ModelName;
}
Emitter << YAML::Key << "IsLinkDest" << YAML::Value << IsLinkDest;
Emitter << YAML::Key << "Links" << YAML::BeginMap;
std::map<std::string,std::vector<Link>> linksByType = std::map<std::string,std::vector<Link>>();
for(Link link: Links){
if(!linksByType.contains(link.Name))
linksByType.insert({link.Name,std::vector<Link>()});
linksByType.find(link.Name)->second.emplace_back(link);
}
for(auto links: linksByType){
Emitter << YAML::Key << links.first;
Emitter << YAML::BeginSeq;
for(auto link: links.second){
link.InsertIntoYaml(Emitter);
}
Emitter << YAML::EndSeq;
}
Emitter << YAML::EndMap;
for(int i = 1; i <= Parameters.size(); i++){
Emitter << YAML::Key << "Parameter" + std::to_string(i) << YAML::Value << YAML::LocalTag("l") << Parameters[i-1];
}
for(int i = 1; i <= FloatParameters.size(); i++){
Emitter << YAML::Key << "FloatParameter" + std::to_string(i) << YAML::Value << FloatParameters[i-1];
}
for(auto opts: OtherOptions){
Emitter << YAML::Key << opts.first;
if(opts.second == "null") {
Emitter << YAML::Value << YAML::CamelNull << YAML::Null;
}
else {
if(boost::starts_with(opts.second,"!l ")){
auto str = opts.second.substr(3);
Emitter << YAML::Value << YAML::LocalTag("l") << std::stol(str);
} else
Emitter << YAML::Value << opts.second;
}
}
}

View file

@ -0,0 +1,13 @@
#include<LevelObject.h>
#include<SpecialObjectParamVersions/All.h>
LevelObject::LevelObject(const YAML::Node &ObjNode): Element(ObjNode,{"Team","DropId"}) {
Team = ObjNode["Team"].as<long>(-1);
DropId = ObjNode["DropId"].as<long>(DropId::Default);
}
void LevelObject::YamlInsertBody(YAML::Emitter &Emitter) {
Element::YamlInsertBody(Emitter);
Emitter << YAML::Key << "Team" << YAML::Value << YAML::LocalTag("l") << Team;
Emitter << YAML::Key << "DropId" << YAML::Value << YAML::LocalTag("l") << DropId;
}

View file

@ -0,0 +1,18 @@
//
// Created by tv on 30.04.23.
//
#include<Link.h>
Link::Link(const YAML::Node &ObjNode) {
Name = ObjNode["DefinitionName"].as<std::string>();
Destination = ObjNode["DestUnitId"].as<std::string>();
UnitFile = ObjNode["UnitFileName"].as<std::string>();
}
void Link::InsertIntoYaml(YAML::Emitter &Emitter) {
Emitter << YAML::BeginMap;
Emitter << YAML::Key << "DefinitionName" << YAML::Value << Name;
Emitter << YAML::Key << "DestUnitId" << YAML::Value << Destination;
Emitter << YAML::Key << "UnitFileName" << YAML::Value << UnitFile;
Emitter << YAML::EndMap;
}

100
Tools/MapTools/src/Map.cpp Normal file
View file

@ -0,0 +1,100 @@
//
// Created by tv on 30.04.23.
//
#include<Map.h>
#include<yaml-cpp/yaml.h>
#include<boost/iostreams/filtering_stream.hpp>
//#include<boost/iostreams/filter/lzma.hpp>
#include <boost/iostreams/device/file.hpp>
#include<iostream>
#include<boost/algorithm/string.hpp>
//GENSERIALIZABLECONTENT(Map,(Objects,Rails))
Map::Map(): Objects(), Rails() {
}
void Map::Save(boost::filesystem::path FileLocation) {
}
void Map::Export(boost::filesystem::path YamlOut) {
YAML::Emitter Emitter;
Emitter << YAML::BeginMap;
Emitter << YAML::Key << "Version" << YAML::Value << "1";
Emitter << YAML::Key << "IsBigEndian" << YAML::Value << "True";
Emitter << YAML::Key << "SupportPaths" << YAML::Value << "False";
Emitter << YAML::Key << "HasReferenceNodes" << YAML::Value << "False";
Emitter << YAML::Key << "root" << YAML::BeginMap;
Emitter << YAML::Key << "FilePath" << YAML::Value << "NoFilePathInsertMegamindMemeHere";
Emitter << YAML::Key << "Objs" << YAML::BeginSeq;
for(auto& obj: Objects){
obj.YamlInsert(Emitter);
}
//Objs
Emitter << YAML::EndSeq;
Emitter << YAML::Key << "Rails" << YAML::BeginSeq;
for(auto obj: Rails){
obj.YamlInsert(Emitter);
}
Emitter << YAML::EndSeq;
//root
Emitter << YAML::EndMap;
//main document
Emitter << YAML::EndMap;
std::ofstream file(YamlOut.string());
std::string str = Emitter.c_str();
boost::algorithm::replace_all(str,"~","null");
file << str;
file.flush();
file.close();
}
Map ConvertFromYaml(boost::filesystem::path File){
Map OutputMap = Map();
YAML::Node MapYaml = YAML::LoadFile(File.generic_string());
auto RootNode = MapYaml["root"];
auto ObjList = RootNode["Objs"];
if(!ObjList.IsSequence()) throw std::runtime_error("Something went Wrong!");
for (YAML::iterator it = ObjList.begin(); it != ObjList.end(); it++) {
const YAML::Node& obj = *it;
OutputMap.Objects.push_back(LevelObject(obj));
}
auto RailList = RootNode["Rails"];
for (YAML::iterator it = RailList.begin(); it != RailList.end(); it++) {
const YAML::Node& obj = *it;
Rail newObj(obj);
OutputMap.Rails.push_back(newObj);
}
std::cout << "Successfully converted to smap!" << std::endl;
return OutputMap;
}

View file

@ -0,0 +1,38 @@
#include<Rail.h>
Rail::Rail(const YAML::Node &ObjNode) : Element(ObjNode, {"RailPoints","RailType","IsClosed","IsLadder","Priority"}) {
YAML::Node railPointsNode = ObjNode["RailPoints"];
for (auto rlpoint: railPointsNode) {
Points.emplace_back(rlpoint);
}
RailType = ToRailType(ObjNode["RailType"].as<std::string>());
IsClosed = ObjNode["IsClosed"].as<bool>();
IsLadder = ObjNode["IsLadder"].as<bool>();
Priority = ObjNode["Priority"].as<long>();
}
Rail::Rail(const Vector3 &Position) {
TF.Position = Position;
Name = "Unnamed Rail";
Type = "Rail";
Points.emplace_back(Position);
}
void Rail::YamlInsertBody(YAML::Emitter &Emitter) {
Element::YamlInsertBody(Emitter);
Emitter << YAML::Key << "RailPoints" << YAML::BeginSeq;
for (auto point: Points) {
point.YamlInsert(Emitter);
}
Emitter << YAML::EndSeq;
Emitter << YAML::Key << "RailType" << YAML::Key << ToString(RailType);
Emitter << YAML::Key << "IsClosed" << YAML::Key << IsClosed;
Emitter << YAML::Key << "IsLadder" << YAML::Key << IsLadder;
Emitter << YAML::Key << "Priority" << YAML::Key << YAML::LocalTag("l") << Priority;
}

View file

@ -0,0 +1,40 @@
#include<Rail.h>
#include "RailPoint.h"
RailPoint::RailPoint(const YAML::Node &ObjNode): Element(ObjNode,{"ControlPoints","OffsetX","OffsetY","OffsetZ","UseOffset",}) {
YAML::Node controlPointsNode = ObjNode["ControlPoints"];
for(auto controlPoint: controlPointsNode){
auto point = Vector3(controlPoint);
m_controlPoints.push_back(point);
}
m_offset = {ObjNode["OffsetX"].as<float>(), ObjNode["OffsetY"].as<float>(), ObjNode["OffsetZ"].as<float>()};
m_useOffset = ObjNode["UseOffset"].as<bool>();
}
RailPoint::RailPoint(const Vector3 &pos) {
Name = "Unnamed Rail Point";
Type = "Point";
TF.Position = pos;
m_controlPoints.push_back(pos);
m_controlPoints.push_back(pos);
}
void RailPoint::YamlInsertBody(YAML::Emitter &Emitter) {
Element::YamlInsertBody(Emitter);
Emitter << YAML::Key << "ControlPoints" << YAML::BeginSeq;
for(auto ctrlPoint: m_controlPoints){
ctrlPoint.InsertIntoYaml(Emitter);
}
Emitter << YAML::EndSeq;
Emitter << YAML::Key << "OffsetX" << YAML::Value << m_offset.X;
Emitter << YAML::Key << "OffsetY" << YAML::Value << m_offset.Y;
Emitter << YAML::Key << "OffsetZ" << YAML::Value << m_offset.Z;
Emitter << YAML::Key << "UseOffset" << YAML::Value << m_useOffset;
}

View file

@ -0,0 +1,19 @@
//
// Created by tv on 07.05.23.
//
#include "SpecialObjectParams.h"
#include"SpecialObjectParamVersions/All.h"
void SpecialObjectParams::ParseOut(YAML::Node node) {}
void SpecialObjectParams::InsertYaml(YAML::Emitter &Emitter) {}
SpecialObjectParams::SpecialObjectParams() {
}
std::vector<std::string> SpecialObjectParams::GetMiscParamBlockList() {
return std::vector<std::string>();
}

View file

@ -0,0 +1,13 @@
#include<Transform.h>
void Transform::InsertIntoYaml(YAML::Emitter &Emitter) {
Emitter << YAML::Key << "Translate";
Position.InsertIntoYaml(Emitter);
Emitter << YAML::Key << "Scale";
Scale.InsertIntoYaml(Emitter);
Emitter << YAML::Key << "Rotate";
Rotation.InsertIntoYaml(Emitter);
}

View file

@ -0,0 +1,23 @@
#include<Vector3.h>
Vector3::Vector3(YAML::Node node) {
try {
X = node["X"].as<float>();
Y = node["Y"].as<float>();
Z = node["Z"].as<float>();
} catch(...){
std::cout << "WER AUCH IMMER HIER SEINEN PC AUF DEUTSCH GESTELLT HAT\n 1. STELL ES UM DAMIT DU KEINE PROBLEME MEHR HAST\n 2. TF\n 3. KEINE KOMPATIBILITÄT GARANTIERT UND NUR FÜR DICH MUSSTE ICH EINEN PATCH SCHREIBEN. \nFFS >:(.\n";
auto xstr = node["X"].as<std::string>();
boost::algorithm::replace_all(xstr,",",".");
X = std::stof(xstr);
auto ystr = node["Y"].as<std::string>();
boost::algorithm::replace_all(ystr,",",".");
Y = std::stof(ystr);
auto zstr = node["Z"].as<std::string>();
boost::algorithm::replace_all(zstr,",",".");
Z = std::stof(zstr);
}
}

749
src/MainViewport.cpp Normal file
View file

@ -0,0 +1,749 @@
//
// Created by tv on 21.05.23.
//
#include "MainViewport.h"
#include "MainWindow.h"
#include <glm/ext.hpp>
#include<imgui.h>
#include "IconsFontAwesome6.h"
#include "glm/gtx/string_cast.hpp"
#include <glm/gtx/rotate_vector.hpp>
#include<cmath>
const GLchar *vertexShader = "#version 460\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec2 aTexCoord;\n"
"uniform mat4 VP;\n"
"uniform mat4 TransformationMatrix;\n"
"uniform mat4 TransformationMatrixNoYInv;\n"
"out vec2 TexCoord;\n"
"out vec4 WldPos;\n"
"void main(){\n"
" vec3 glPos = vec3(aPos.x,-aPos.y,aPos.z);\n"
" WldPos = TransformationMatrixNoYInv * vec4(aPos.xyz,1);\n"
" gl_Position = (VP * TransformationMatrix) * vec4(glPos.x,glPos.y,glPos.z,1);\n"
" TexCoord = aTexCoord;\n"
"}\n";
const GLchar *fragmentShader = "#version 460\n"
"in vec2 TexCoord;\n"
"in vec4 WldPos;\n"
"layout(location = 1) out vec4 FragColor;\n"
"layout(location = 2) out unsigned int ObjId;\n"
"layout(location = 3) out vec4 WorldPos;\n"
"uniform sampler2D tex;\n"
"uniform unsigned int ObjIdIn;\n"
"uniform vec4 ObjColor;\n"
"//out vec4 CamPos;\n"
"void main(){\n"
" ObjId = ObjIdIn;\n"
" WorldPos = vec4(WldPos.xyz,1);\n"
" //if(WldPos.w == 0) WorldPos=vec4(WldPos.xyz,1);\n"
" vec4 textel = texture(tex,TexCoord);\n"
" if(textel.a < 0.2) discard;\n"
" //textel.a = (CamPos.z / CamPos.w) / 100;\n"
" FragColor = textel * ObjColor;\n"
" //FragColor = vec4(1,1,1,1);\n"
"}";
MainViewport *MainVP;
glm::mat4 TransformToMatrix(Transform tf) {
auto Pos = glm::vec3(tf.Position.X, tf.Position.Y, tf.Position.Z);
auto Rot = glm::vec3(tf.Rotation.X, tf.Rotation.Y, tf.Rotation.Z);
auto Scale = glm::vec3(tf.Scale.X, tf.Scale.Y, tf.Scale.Z);
glm::mat4 translationMatrix = glm::translate(glm::mat4(1), Pos);
glm::mat4 rotationMatrixZ = glm::rotate(glm::mat4(1), glm::radians(Rot.z), glm::vec3(0, 0, 1));
glm::mat4 rotationMatrixY = glm::rotate(rotationMatrixZ, glm::radians(Rot.y), glm::vec3(0, 1, 0));
glm::mat4 rotationMatrix = glm::rotate(rotationMatrixY, glm::radians(Rot.x), glm::vec3(1, 0, 0));
glm::mat4 scaleMatrix = glm::scale(glm::mat4(1), Scale);
return translationMatrix * rotationMatrix * scaleMatrix;
}
glm::vec3 ToGlmVec3(Vector3 Vec3) {
return glm::vec3(Vec3.X, Vec3.Y, Vec3.Z);
}
bool IsArea(std::string Type){
if( Type == "Area" ||
Type == "Area_Yellow" ||
Type == "StageArea" ||
Type == "GeneralArea" ||
Type == "PaintedArea" ||
Type == "GachihokoHikikomoriArea" ||
Type == "GachihokoHikikomoriArea2" ||
Type == "SearchableArea" ||
Type == "PaintTargetArea")
return true;
return false;
}
MainViewport::MainViewport() : Graphics::ViewportWidget("Main Viewport", true) {
MainVP = this;
shader = Graphics::Shader(vertexShader, fragmentShader);
//ObjMesh = Graphics::Mesh();
GLuint ObjColPos = glGetUniformLocation(shader.ShaderId, "ObjColor");
glUniform4f(ObjColPos, 1, 1, 1, 1);
}
void MainViewport::Draw() {
GLuint ObjIdPos = glGetUniformLocation(shader.ShaderId, "ObjIdIn");
GLuint ObjColPos = glGetUniformLocation(shader.ShaderId, "ObjColor");
static auto lasttime = boost::chrono::high_resolution_clock::now();
auto timenow = boost::chrono::high_resolution_clock::now();
boost::chrono::duration<float> TimeDiff = (timenow - lasttime);
lasttime = timenow;
float DeltaTime = TimeDiff.count();
glm::vec3 cameraDirection = glm::vec3(
glm::sin(glm::radians(camrot.x)) * glm::cos(glm::radians(camrot.y)),
glm::sin(glm::radians(camrot.y)),
glm::cos(glm::radians(camrot.x)) * glm::cos(glm::radians(camrot.y))
);
glm::vec3 cameraLeft = glm::vec3(
glm::sin(glm::radians(camrot.x + 90)),
0,
glm::cos(glm::radians(camrot.x + 90))
);
if (ImGui::IsWindowFocused()) {
if (ImGui::IsKeyPressed(ImGuiKey_N))
ImGui::OpenPopup("Main VP Debug");
float speedmod = 1.0f;
if (ImGui::IsKeyDown(ImGuiKey_LeftShift))
speedmod = 2;
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
speedmod = 0.5;
if (ImGui::IsKeyDown(ImGuiKey_W)) {
camPos += cameraDirection * speed * speedmod * DeltaTime;
}
if (ImGui::IsKeyDown(ImGuiKey_A)) {
camPos += cameraLeft * speed * speedmod * DeltaTime;
}
if (ImGui::IsKeyDown(ImGuiKey_S)) {
camPos -= cameraDirection * speed * speedmod * DeltaTime;
}
if (ImGui::IsKeyDown(ImGuiKey_D)) {
camPos -= cameraLeft * speed * speedmod * DeltaTime;
}
}
//glm::mat4 VP = Projection * View;
glm::mat4 projectionMatrix = glm::perspective(
glm::radians(
fov), // The vertical Field of View, in radians: the amount of "zoom". Think "camera lens". Usually between 90° (extra wide) and 30° (quite zoomed in)
(float) framewidth /
(float) frameheight, // Aspect Ratio. Depends on the size of your window. Notice that 4/3 == 800/600 == 1280/960, sounds familiar ?
0.1f, // Near clipping plane. Keep as big as possible, or you'll get precision issues.
10000.0f // Far clipping plane. Keep as little as possible.
);
//glm::mat4 ViewMatrix = glm::translate(glm::mat4(1.0f), -camPos);
glm::mat4 ViewMatrix = glm::lookAt(camPos, camPos + cameraDirection, glm::vec3(0, 1, 0));
glm::mat4 ModelMat = glm::mat4(1.0f);
VP = projectionMatrix * ViewMatrix;// * ViewMatrix * ModelMat;
if (ImGui::BeginPopup("Main VP Debug")) {
ImGui::DragFloat3("Camera Postion", &camPos.x, 0.01);
ImGui::DragFloat2("Camera Rotation", &camrot.x, 0.01);
ImGui::SliderFloat("FOV", &fov, 0, 180);
ImGui::DragFloat("Speed", &speed, 1);
ImGui::Checkbox("Draw All Areas", &drawAllAreas);
ImGui::EndPopup();
}
GLuint MatrixID = glGetUniformLocation(shader.ShaderId, "VP");
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, glm::value_ptr(VP));
auto &map = GetMainWindow()->loadedMap;
glDrawBuffer(GL_COLOR_ATTACHMENT1);
GLuint ClearID[] = {0};
glClearBufferuiv(GL_COLOR, 0, ClearID);
glDrawBuffer(GL_COLOR_ATTACHMENT2);
GLfloat ClearPos[] = {0,0,0,0};
glClearBufferfv(GL_COLOR, 0, ClearPos);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
unsigned int ObjID = 16;
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
for (auto &obj: map.Objects) {
if(IsArea(obj.Type) && !drawAllAreas){
ObjID++;
continue;
} else if(IsArea(obj.Type) && drawAllAreas) {
static auto AreaMdl = Model("St_Area");
glUniform1ui(ObjIdPos, ObjID);
glUniform4f(ObjColPos, 1, 1, 1, 1);
AreaMdl.Draw(obj.TF);
ObjID++;
continue;
}
if (!MdlFromObj.contains(obj.Type)) {
if (boost::filesystem::exists(
boost::filesystem::current_path() / "Models" / obj.Type / (obj.Type + ".dae")))
MdlFromObj.insert({obj.Type, Model(obj.Type)});
else {
MdlFromObj.insert({obj.Type, Model("St_Default")});
std::cout << "Model missing: \n\t" << obj.Type << std::endl;
}
}
auto mdl = MdlFromObj.find(obj.Type)->second;
glUniform1ui(ObjIdPos, ObjID);
glUniform4f(ObjColPos, 1, 1, 1, 1);
if(&obj == GetMainWindow()->selectedElem)
glUniform4f(ObjColPos, 1, .7, .7, 1);
mdl.Draw(obj.TF);
ObjID++;
}
if (GetMainWindow()->selectedElem != nullptr) {
auto selobj = GetMainWindow()->selectedElem;
if(IsArea(selobj->Type)) {
static auto AreaMdl = Model("St_Area");
glUniform1ui(ObjIdPos, 0);
AreaMdl.Draw(selobj->TF);
}
glClear(GL_DEPTH_BUFFER_BIT);
if(Rail* rail = dynamic_cast<Rail*>(GetMainWindow()->selectedElem)){
static Model Arrow = Model("St_RailPoint");
if(rail->Points.size() > 1) {
auto lastRailPoint = rail->Points.front();
for (RailPoint &railPoint: rail->Points) {
Arrow.Draw(railPoint.TF);
}
}
}
//mdl.DrawSelection(selobj->TF);
glClear(GL_DEPTH_BUFFER_BIT);
if (CurrentGizmoType == Move) {
static Model Arrow = Model("St_Arrow");
auto tf = Transform();
tf.Position = selobj->TF.Position;
float size = glm::distance(glm::vec3(tf.Position.X,tf.Position.Y,tf.Position.Z),camPos);
//tf.Scale = {size/ 50, size/ 50, size/ 50};
tf.Scale = {1,1,1};
tf.Rotation = {0, 0, 90};
glUniform4f(ObjColPos, 0.5, 0, 0, 1);
if(HoveredObjId == 1)
glUniform4f(ObjColPos, 1, 0, 0, 1);
glUniform1ui(ObjIdPos, 1);
Arrow.Draw(tf);
tf.Rotation = {0, 0, 0};
glUniform4f(ObjColPos, 0, 0.5, 0, 1);
if(HoveredObjId == 2)
glUniform4f(ObjColPos, 0, 1, 0, 1);
glUniform1ui(ObjIdPos, 2);
Arrow.Draw(tf);
tf.Rotation = {90, 0, 0};
glUniform4f(ObjColPos, 0, 0, 0.5, 1);
if(HoveredObjId == 3)
glUniform4f(ObjColPos, 0, 0, 1, 1);
glUniform1ui(ObjIdPos, 3);
Arrow.Draw(tf);
glUniform4f(ObjColPos, 1, 1, 1, 1);
} else if (CurrentGizmoType == Scale) {
static Model Scalar = Model("St_Scalar");
auto tf = Transform();
tf.Position = selobj->TF.Position;
float size = glm::distance(glm::vec3(tf.Position.X,tf.Position.Y,tf.Position.Z),camPos);
//tf.Scale = {size/ 50, size/ 50, size/ 50};
tf.Scale = {1,1,1};
tf.Rotation = {selobj->TF.Rotation.X + 90, selobj->TF.Rotation.Y + 90, selobj->TF.Rotation.Z};
glUniform4f(ObjColPos, 0.5, 0, 0, 1);
if(HoveredObjId == 1)
glUniform4f(ObjColPos, 1, 0, 0, 1);
glUniform1ui(ObjIdPos, 1);
Scalar.Draw(tf);
tf.Rotation = {selobj->TF.Rotation.X, selobj->TF.Rotation.Y, selobj->TF.Rotation.Z};
glUniform4f(ObjColPos, 0, 0.5, 0, 1);
if(HoveredObjId == 2)
glUniform4f(ObjColPos, 0, 1, 0, 1);
glUniform1ui(ObjIdPos, 2);
Scalar.Draw(tf);
tf.Rotation = {selobj->TF.Rotation.X + 90 , selobj->TF.Rotation.Y, selobj->TF.Rotation.Z};
glUniform4f(ObjColPos, 0, 0, 0.5, 1);
if(HoveredObjId == 3)
glUniform4f(ObjColPos, 0, 0, 1, 1);
glUniform1ui(ObjIdPos, 3);
Scalar.Draw(tf);
glUniform4f(ObjColPos, 1, 1, 1, 1);
} else if (CurrentGizmoType == Rotate) {
static Model Rotator = Model("St_Rotate");
auto tf = Transform();
tf.Position = selobj->TF.Position;
float size = glm::distance(glm::vec3(tf.Position.X,tf.Position.Y,tf.Position.Z),camPos);
//tf.Scale = {size/ 50, size/ 50, size/ 50};
tf.Scale = {1,1,1};
tf.Rotation = {0, 0, 90};
glUniform4f(ObjColPos, 0.5, 0, 0, 1);
if(HoveredObjId == 1)
glUniform4f(ObjColPos, 1, 0, 0, 1);
glUniform1ui(ObjIdPos, 1);
Rotator.Draw(tf);
tf.Rotation = {0, 0, 0};
glUniform4f(ObjColPos, 0, 0.5, 0, 1);
if(HoveredObjId == 2)
glUniform4f(ObjColPos, 0, 1, 0, 1);
glUniform1ui(ObjIdPos, 2);
Rotator.Draw(tf);
tf.Rotation = {90, 0, 0};
glUniform4f(ObjColPos, 0, 0, 0.5, 1);
if(HoveredObjId == 3)
glUniform4f(ObjColPos, 0, 0, 1, 1);
glUniform1ui(ObjIdPos, 3);
Rotator.Draw(tf);
glUniform4f(ObjColPos, 1, 1, 1, 1);
}
}
glDisable(GL_DEPTH_TEST);
}
template<typename t>
inline float GetVecComponent(const t &v1, const t &v2) {
auto NormComp = glm::normalize(v2);
return (glm::dot(v1, NormComp));
}
template<typename t>
inline t ProjectToRayNormalized(const t &v1, const t &ray) {
return glm::dot(v1, ray) / glm::dot(ray,ray) * ray;
}
template<typename t>
inline t ProjectToRay(const t &v1,const t &rayStart, const t &ray) {
return ProjectToRayNormalized(v1-rayStart,ray - rayStart) + rayStart;
}
template<typename t>
inline t ProjectToRayNormDir(const t &v1,const t &rayStart, const t &RayDir) {
return ProjectToRayNormalized(v1-rayStart,RayDir) + rayStart;
}
glm::vec3 MainViewport::ScreenSpaceToRay(glm::vec2 ScreenPos){
auto InverseVP = glm::inverse(VP);
glm::vec4 worldPos = InverseVP * glm::vec4(ScreenPos,1.0,1.0);
glm::vec3 dir = glm::normalize(glm::vec3(worldPos));
return dir;
}
void MainViewport::HandleInput(InputEvent event) {
static glm::vec2 lastMpos = glm::vec2(0, 0);
glm::vec2 currentMpos = glm::vec2(event.x, event.y);
//static glm::vec3 GizmoDirPrePos = {0,0,0};
glm::vec2 DeltaMousePos = currentMpos - lastMpos;
static glm::vec3 ObjBindingVec = {0,0,0};
static float ObjScalingDist = 0.0f;
static glm::vec3 GizmoDir = glm::vec3(1, 1, 1);
static unsigned int SpecialObjCur = 0;
auto SelObj = GetMainWindow()->selectedElem;
switch (event.EventType) {
case (InputType::MouseHover):{
GLint y = event.y * frameheight;
GLint x = event.x * framewidth;
glReadBuffer(GL_COLOR_ATTACHMENT1);
glReadPixels(x,y,1,1, GL_RED_INTEGER, GL_UNSIGNED_INT, &HoveredObjId);
}
break;
case (InputType::MouseDownL): {
GLint y = event.y * frameheight;
GLint x = event.x * framewidth;
glBindFramebuffer(GL_FRAMEBUFFER, Framebuffer);
glReadBuffer(GL_COLOR_ATTACHMENT1);
unsigned int obj = 0;
glReadPixels(x, y, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &obj);
if (obj < 16) {
SpecialObjCur = obj;
if (CurrentGizmoType == Move) {
if(0 < obj && obj <= 3 ) {
if (obj == 1) {
GizmoDir = {1, 0, 0};
} else if (obj == 2) {
GizmoDir = {0, 1, 0};
} else if (obj == 3) {
GizmoDir = {0, 0, 1};
}
glReadBuffer(GL_COLOR_ATTACHMENT2);
glm::vec4 CurWDirPos = {0,0,0,0};
glReadPixels(x, y, 1, 1, GL_RGBA, GL_FLOAT, glm::value_ptr(CurWDirPos));
glm::vec3 GizmoDirPrePos = ProjectToRayNormalized({CurWDirPos.x,CurWDirPos.y,CurWDirPos.z},GizmoDir);
glm::vec3 objpos = {SelObj->TF.Position.X,SelObj->TF.Position.Y,SelObj->TF.Position.Z};
ObjBindingVec = objpos - GizmoDirPrePos;
std::cout << glm::to_string(ObjBindingVec) << std::endl;
}
} else if(CurrentGizmoType == Scale){
if(0 < obj && obj <= 3 ) {
if (obj == 1) {
GizmoDir = {1, 0, 0};
} else if (obj == 2) {
GizmoDir = {0, 1, 0};
} else if (obj == 3) {
GizmoDir = {0, 0, 1};
}
auto TF = SelObj->TF;
TF.Scale = {1,1,1};
TF.Position = {0,0,0};
auto mat = TransformToMatrix(TF);
GizmoDir = mat * glm::vec4(GizmoDir,1);
glReadBuffer(GL_COLOR_ATTACHMENT2);
glm::vec4 CurWDirPos = {0,0,0,0};
glReadPixels(x, y, 1, 1, GL_RGBA, GL_FLOAT, glm::value_ptr(CurWDirPos));
glm::vec3 GizmoDirPrePos = ProjectToRayNormalized({CurWDirPos.x,CurWDirPos.y,CurWDirPos.z},GizmoDir);
glm::vec3 objpos = ToGlmVec3(SelObj->TF.Position);
ObjScalingDist = glm::distance(ProjectToRayNormalized(objpos,GizmoDir), GizmoDirPrePos);
ObjBindingVec = ToGlmVec3(SelObj->TF.Scale);
//std::cout << ObjScalingDist << std::endl;
} /*if (CurrentGizmoType == Rotate) {
if(0 < obj && obj <= 3 ) {
if (obj == 1) {
GizmoDir = {1, 0, 0};
} else if (obj == 2) {
GizmoDir = {0, 1, 0};
} else if (obj == 3) {
GizmoDir = {0, 0, 1};
}
glReadBuffer(GL_COLOR_ATTACHMENT2);
glm::vec4 CurWDirPos = {0,0,0,0};
glReadPixels(x, y, 1, 1, GL_RGBA, GL_FLOAT, glm::value_ptr(CurWDirPos));
glm::vec3 GizmoDirPrePos = ProjectToRayNormalized({CurWDirPos.x,-CurWDirPos.y,CurWDirPos.z},GizmoDir);
glm::vec3 objpos = {SelObj->TF.Position.X,SelObj->TF.Position.Y,SelObj->TF.Position.Z};
ObjBindingVec = objpos - GizmoDirPrePos;
}
}*/
}
return;
}
obj -= 16;
GetMainWindow()->selectedElem = &GetMainWindow()->loadedMap.Objects[obj];
}
break;
case (InputType::MouseHoldL): {
GLint y = event.y * frameheight;
GLint x = event.x * framewidth;
glBindFramebuffer(GL_FRAMEBUFFER, Framebuffer);
glReadBuffer(GL_COLOR_ATTACHMENT1);
unsigned int obj = 0;
glReadPixels(x, y, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &obj);
if (CurrentGizmoType == Move) {
if(SpecialObjCur == 0) {
return;
}
/*if(SpecialObjCur != obj){
SpecialObjCur = 0;
return;
}*/
auto tf = SelObj->TF;
tf.Rotation = {0,0,0};
tf.Scale = {1,1,1};
auto Tf = TransformToMatrix(tf);
if (SpecialObjCur == 1) {
GizmoDir = {1, 0, 0};
} else if (SpecialObjCur == 2) {
GizmoDir = {0, 1, 0};
} else if (SpecialObjCur == 3) {
GizmoDir = {0, 0, 1};
}
auto ClipSpaceStart = (VP * Tf) * glm::vec4(0,0,0,1);
auto ClipSpaceEnd = (VP * Tf) * glm::vec4(GizmoDir,1);
glm::vec2 ScreenSpaceStart = {((ClipSpaceStart.x/ClipSpaceStart.w + 1 ) / 2) * framewidth, ((ClipSpaceStart.y/ClipSpaceStart.w + 1 ) / 2) * frameheight };
glm::vec2 ScreenSpaceEnd = {((ClipSpaceEnd.x/ClipSpaceEnd.w + 1 ) / 2) * framewidth, ((ClipSpaceEnd.y/ClipSpaceEnd.w + 1 ) / 2) * frameheight};
glm::vec2 ScrenSpaceDir = ScreenSpaceEnd - ScreenSpaceStart;
glm::vec2 MousePos = {x,y};
glm::vec2 FixedMousePos = ProjectToRayNormDir(MousePos,ScreenSpaceStart,ScrenSpaceDir);
//SpecialObjCur = obj;
if(0 < SpecialObjCur && SpecialObjCur <= 3 ) {
glReadBuffer(GL_COLOR_ATTACHMENT2);
glm::vec4 CurWDirPos = {0,0,0,0};
glReadPixels(floorf(FixedMousePos.x), floorf(FixedMousePos.y), 1, 1, GL_RGBA, GL_FLOAT, glm::value_ptr(CurWDirPos));
//std::cout << glm::to_string(CurWDirPos) << std::endl;
auto DirProjectedTranslationPos = ProjectToRayNormalized({CurWDirPos.x,-CurWDirPos.y,CurWDirPos.z},GizmoDir);
if (SpecialObjCur == 1) {
SelObj->TF.Position.X = ObjBindingVec.x + DirProjectedTranslationPos.x;
} else if (SpecialObjCur == 2) {
SelObj->TF.Position.Y = ObjBindingVec.y + DirProjectedTranslationPos.y;
} else if (SpecialObjCur == 3) {
SelObj->TF.Position.Z = ObjBindingVec.z + DirProjectedTranslationPos.z;
}
glm::vec3 objpos = {SelObj->TF.Position.X,SelObj->TF.Position.Y,SelObj->TF.Position.Z};
ObjBindingVec = objpos - DirProjectedTranslationPos;
lastMpos = currentMpos;
}
} else if (CurrentGizmoType == Scale) {
if(SpecialObjCur == 0)
return;
if(SpecialObjCur != obj){
SpecialObjCur = 0;
return;
}
if(0 < SpecialObjCur && SpecialObjCur <= 3 ) {
SpecialObjCur = obj;
if (obj == 1) {
GizmoDir = {1, 0, 0};
} else if (obj == 2) {
GizmoDir = {0, 1, 0};
} else if (obj == 3) {
GizmoDir = {0, 0, 1};
}
auto TF = SelObj->TF;
TF.Scale = {1,1,1};
TF.Position = {0,0,0};
auto mat = TransformToMatrix(TF);
GizmoDir = mat * glm::vec4(GizmoDir,1);
glReadBuffer(GL_COLOR_ATTACHMENT2);
glm::vec4 CurWDirPos = {0,0,0,0};
//GizmoDir = glm::normalize( * GizmoDir)
glReadPixels(x, y, 1, 1, GL_RGBA, GL_FLOAT, glm::value_ptr(CurWDirPos));
glm::vec3 ObjPos = ToGlmVec3(SelObj->TF.Position);
ObjPos.y = -ObjPos.y;
CurWDirPos -= glm::vec4(ObjPos,1);
auto DirProjectedTranslationPos = ProjectToRayNormalized({CurWDirPos.x,-CurWDirPos.y,CurWDirPos.z},GizmoDir);
float VecComp = GetVecComponent(DirProjectedTranslationPos,GizmoDir);
float DeltaInDir = 0;
if (SpecialObjCur == 1) {
DeltaInDir = (ObjBindingVec.x + ((VecComp / ObjScalingDist) - 1) * ObjBindingVec.x) - SelObj->TF.Scale.X;
SelObj->TF.Scale.X = ObjBindingVec.x + ((VecComp / ObjScalingDist) - 1) * ObjBindingVec.x;
} else if (SpecialObjCur == 2) {
DeltaInDir = (ObjBindingVec.y + ((VecComp / ObjScalingDist) - 1) * ObjBindingVec.y) - SelObj->TF.Scale.Y;
SelObj->TF.Scale.Y = ObjBindingVec.y + ((VecComp / ObjScalingDist) - 1) * ObjBindingVec.y;
} else if (SpecialObjCur == 3) {
DeltaInDir = (ObjBindingVec.z + ((VecComp / ObjScalingDist) - 1) * ObjBindingVec.z) - SelObj->TF.Scale.Z;
SelObj->TF.Scale.Z = ObjBindingVec.z + ((VecComp / ObjScalingDist) - 1) * ObjBindingVec.z;
}
if(ImGui::IsKeyDown(ImGuiKey_LeftCtrl)){
if(SpecialObjCur != 1) SelObj->TF.Scale.X += DeltaInDir;
if(SpecialObjCur != 2) SelObj->TF.Scale.Y += DeltaInDir;
if(SpecialObjCur != 3) SelObj->TF.Scale.Z += DeltaInDir;
}
lastMpos = currentMpos;
}
}
}
break;
case (InputType::MouseUpL):
SpecialObjCur = 0;
break;
case (InputType::MouseDownR):
ImGui::SetWindowFocus();
lastMpos = currentMpos;
break;
case (InputType::MouseHoldR):
ImGui::SetWindowFocus();
camrot.x += (lastMpos.x - currentMpos.x) * (float) framewidth * .1f;
camrot.y -= (lastMpos.y - currentMpos.y) * (float) frameheight * .1f;
lastMpos = currentMpos;
break;
}
}
void MainViewport::DrawOver() {
auto textsz = ImGui::CalcTextSize(ICON_FA_ARROWS_UP_DOWN_LEFT_RIGHT " "
ICON_FA_ARROWS_LEFT_RIGHT_TO_LINE " "
ICON_FA_ROTATE);
ImGui::SetCursorPos(ImVec2(ImGui::GetWindowWidth() - textsz.x - 70, textsz.y + 20));
ImGui::BeginGroupPanel("Tools");
if (CurrentGizmoType == Move) {
ImGui::PushStyleColor(ImGuiCol_Button, 0xFF008000);
if (ImGui::Button(ICON_FA_ARROWS_UP_DOWN_LEFT_RIGHT "##MainVpMoveGadget"))
CurrentGizmoType = Move;
ImGui::PopStyleColor();
} else {
if (ImGui::Button(ICON_FA_ARROWS_UP_DOWN_LEFT_RIGHT "##MainVpMoveGadget"))
CurrentGizmoType = Move;
}
ImGui::SameLine();
if (CurrentGizmoType == Scale) {
ImGui::PushStyleColor(ImGuiCol_Button, 0xFF008000);
if (ImGui::Button(ICON_FA_ARROWS_LEFT_RIGHT_TO_LINE "##MainVpScaleGadget"))
CurrentGizmoType = Scale;
ImGui::PopStyleColor();
} else {
if (ImGui::Button(ICON_FA_ARROWS_LEFT_RIGHT_TO_LINE "##MainVpScaleGadget"))
CurrentGizmoType = Scale;
}
ImGui::SameLine();
if (CurrentGizmoType == Rotate) {
ImGui::PushStyleColor(ImGuiCol_Button, 0xFF008000);
if (ImGui::Button(ICON_FA_ROTATE "##MainVpRotateGadget"))
CurrentGizmoType = Rotate;
ImGui::PopStyleColor();
} else {
if (ImGui::Button(ICON_FA_ROTATE "##MainVpRotateGadget"))
CurrentGizmoType = Rotate;
}
ImGui::EndGroupPanel();
}
glm::vec2 MainViewport::CalcGizmoDir(glm::vec3 dir) {
auto SelObj = GetMainWindow()->selectedElem;
auto DirPos = glm::vec4(dir, 1);
auto ObjPos = glm::vec4(0, 0, 0, 1);
auto tf = SelObj->TF;
tf.Rotation = {0, 0, 0};
tf.Scale = {1, 1, 1};
auto ModelMat = TransformToMatrix(tf);
auto ObjPosClipSpace = (VP * ModelMat) * ObjPos;
auto DirPosClipSpace = (VP * ModelMat) * DirPos;
auto ObjPosVPSpace = glm::vec2(ObjPosClipSpace.x / ObjPosClipSpace.w,
ObjPosClipSpace.y / ObjPosClipSpace.w);
auto DirPosVPSpace = glm::vec2(DirPosClipSpace.x / DirPosClipSpace.w,
DirPosClipSpace.y / DirPosClipSpace.w);
return DirPosVPSpace - ObjPosVPSpace;
}
MainViewport *GetMainViewport() {
return MainVP;
}

61
src/MainViewport.h Normal file
View file

@ -0,0 +1,61 @@
//
// Created by tv on 21.05.23.
//
#ifndef SPOONTOOL_MAINVIEWPORT_H
#define SPOONTOOL_MAINVIEWPORT_H
#include <queue>
#include "virintox/gcore/ViewportWidget.h"
#include "virintox/gcore/Shader.h"
#include "glm/vec3.hpp"
#include "virintox/gcore/Mesh.h"
#include "Model.h"
#include "boost/thread.hpp"
enum GizmoType{
Move,Rotate,Scale
};
class MainViewport : public Graphics::ViewportWidget {
public:
MainViewport();
Graphics::Shader shader;
glm::vec3 camPos = glm::vec3(0,0,0);
glm::vec2 camrot = glm::vec2(0,0);
float fov = 90.0f;
std::vector<std::vector<unsigned int>> PixelToObjNum;
float speed = 100.0f;
bool drawAllAreas = false;
GizmoType CurrentGizmoType = Move;
private:
unsigned int HoveredObjId = 0;
std::map<std::string,Model> MdlFromObj;
glm::mat4 VP;
//Graphics::Mesh ObjMesh;
glm::vec2 CalcGizmoDir(glm::vec3 dir);
glm::vec3 ScreenSpaceToRay(glm::vec2);
void DrawOver() override;
public:
void HandleInput(InputEvent event) override;
private:
void Draw() override;
};
MainViewport* GetMainViewport();
#endif //SPOONTOOL_MAINVIEWPORT_H

151
src/MainWindow.cpp Normal file
View file

@ -0,0 +1,151 @@
#include "MainWindow.h"
#include "PropertiesWidget.h"
#include "ObjectSelectWidget.h"
#include "RailSelectWidget.h"
#include "MainViewport.h"
#include <virintox/gcore/FileSelectDialog.h>
#include <virintox/gcore/Graphics.h>
#include<imgui.h>
#include <IconsFontAwesome6.h>
#include<fstream>
MainWindow* MainWindowInst = nullptr;
void ExportObj(LevelObject obj){
YAML::Emitter emitter;
obj.YamlInsert(emitter);
auto fstr = std::ofstream((boost::filesystem::current_path() / "Presets" / (obj.Name + ".yaml")).string());
fstr << emitter.c_str();
fstr.flush();
fstr.close();
}
MainWindow::MainWindow(): Graphics::Window("SpoonEdit") {
MainWindowInst = this;
auto mapSelectSaveExplorer = addWidget(new Graphics::FileSelectDialog("Select/Save Map", {".yaml"},[&](boost::filesystem::path path){
selectedElem = nullptr;
loadedMap = ConvertFromYaml(path);
},[&](boost::filesystem::path path){
loadedMap.Export(path);
}));
std::vector<std::string> strvec;
boost::algorithm::split(strvec,(boost::filesystem::current_path() / "Maps").string(),boost::is_any_of("/"));
mapSelectSaveExplorer->Path = strvec;
addWidget(new Graphics::FileSelectDialog("Load Object from Preset", {".yaml"},[](boost::filesystem::path path){
auto file = YAML::LoadFile(path.string());
MainWindowInst->selectedElem = nullptr;
MainWindowInst->loadedMap.Objects.emplace_back(LevelObject(file));
}));
addWidget<PropertiesWidget>();
addWidget<ObjectSelectWidget>();
addWidget<MainViewport>();
addWidget<RailSelectWidget>();
AddMenu("File");
AddMenuItem("File",ICON_FA_FOLDER_OPEN " Open",[](){
auto wid = dynamic_cast<Graphics::FileSelectDialog*>(MainWindowInst->WidgetByName.find("Select/Save Map")->second);
wid->fileSelectMode = Graphics::Open;
wid->Active = true;
});
AddMenuItem("File",ICON_FA_FLOPPY_DISK " Save",[](){
auto wid = dynamic_cast<Graphics::FileSelectDialog*>(MainWindowInst->WidgetByName.find("Select/Save Map")->second);
wid->fileSelectMode = Graphics::Save;
wid->Active = true;
});
AddMenu("Widgets");
AddMenuItem("Widgets",ICON_FA_VIDEO " Viewport",[](){
MainWindowInst->WidgetByName.find("Main Viewport")->second->Active ^= true;
});
AddMenuItem("Widgets",ICON_FA_CUBES " Objects",[](){
MainWindowInst->WidgetByName.find("Object Select")->second->Active ^= true;
});
AddMenuItem("Widgets",ICON_FA_CIRCLE_NODES " Rails",[](){
MainWindowInst->WidgetByName.find("Rails")->second->Active ^= true;
});
AddMenuItem("Widgets",ICON_FA_CLIPBOARD_LIST " Properties",[](){
MainWindowInst->WidgetByName.find("Properties")->second->Active ^= true;
});
AddMenu("Object");
AddMenuItem("Object", ICON_FA_PLUS " Add",[](){
auto wid = dynamic_cast<Graphics::FileSelectDialog*>(MainWindowInst->WidgetByName.find("Load Object from Preset")->second);
std::vector<std::string> strvec;
boost::algorithm::split(strvec,(boost::filesystem::current_path() / "Presets").string(),boost::algorithm::is_any_of("/\\"));
wid->Path = strvec;
wid->fileSelectMode = Graphics::Open;
wid->Active = true;
});
AddMenuItem("Object", ICON_FA_ANCHOR " Kotzen[!]",[&](){
for (LevelObject &obj: loadedMap.Objects) {
if(!boost::filesystem::exists(boost::filesystem::current_path() / "Presets" / (obj.Type + ".yaml"))){
LevelObject ObjCpy = LevelObject(obj);
ObjCpy.Name = ObjCpy.Type;
ObjCpy.Links = std::vector<Link>();
ObjCpy.TF.Scale = {1, 1, 1};
ObjCpy.TF.Rotation = {0, 0, 0};
ObjCpy.TF.Position = {0, 0, 0};
ExportObj(ObjCpy);
}
}
});
AddMenuItem("Object", ICON_FA_ANCHOR " Durchfall[!]",[&](){
for(auto& entry : boost::make_iterator_range(boost::filesystem::directory_iterator(boost::filesystem::current_path() / "Maps"), {})) {
std::cout << "Exporting all from " << entry << std::endl;
MainWindowInst->selectedElem = nullptr;
MainWindowInst->loadedMap = ConvertFromYaml(entry);
for (LevelObject &obj: loadedMap.Objects) {
if (!boost::filesystem::exists(boost::filesystem::current_path() / "Presets" / (obj.Type + ".yaml"))) {
LevelObject ObjCpy = LevelObject(obj);
ObjCpy.Name = ObjCpy.Type;
ObjCpy.Links = std::vector<Link>();
ObjCpy.TF.Scale = {1, 1, 1};
ObjCpy.TF.Rotation = {0, 0, 0};
ObjCpy.TF.Position = {0, 0, 0};
ExportObj(ObjCpy);
}
}
}
});
msgBoxes.push_back(new Graphics::MessageBox("Gizmos are currently broken beware of using them!"));
//msgBoxes.
Graphics::EnableVsync();
}
void MainWindow::Update() {
}
MainWindow* GetMainWindow(){
return MainWindowInst;
}

26
src/MainWindow.h Normal file
View file

@ -0,0 +1,26 @@
//
// Created by tv on 20.05.23.
//
#ifndef SPOONTOOL_MAINWINDOW_H
#define SPOONTOOL_MAINWINDOW_H
#include<virintox/gcore/Window.h>
#include<Map.h>
class MainWindow : public Graphics::Window {
public:
MainWindow();
Map loadedMap;
void Update() override;
Element* selectedElem = nullptr;
};
MainWindow* GetMainWindow();
#endif //SPOONTOOL_MAINWINDOW_H

118
src/Model.cpp Normal file
View file

@ -0,0 +1,118 @@
//
// Created by tv on 21.05.23.
//
#include "Model.h"
#include "assimp/scene.h"
#include "MainViewport.h"
#include <assimp/Importer.hpp>
#include <assimp/postprocess.h>
#include <virintox/gcore/Graphics.h>
#include "Transform.h"
Model::Model(std::string modelname) {
auto modeltoload = boost::filesystem::current_path() / "Models" / modelname / (modelname + ".dae");
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile( modeltoload.string(),
aiProcess_CalcTangentSpace |
aiProcess_Triangulate |
aiProcess_JoinIdenticalVertices |
// aiProcess_Debone |
aiProcess_FlipUVs |
aiProcess_SortByPType);
if(!scene)
{
Graphics::window->msgBoxes.push_back(new Graphics::MessageBox(importer.GetErrorString(),Graphics::ErrorSeverity::Error));
return;
}
for(unsigned int i = 0; i < scene->mNumMeshes; i++){
auto mesh = scene->mMeshes[i];
auto mat = scene->mMaterials[mesh->mMaterialIndex];
std::string firsttex;
for(unsigned int currenttex = 0; currenttex < mat->GetTextureCount(aiTextureType_DIFFUSE); currenttex++){
aiString string;
mat->GetTexture(aiTextureType_DIFFUSE, 0, &string);
if(firsttex == "")
firsttex = string.C_Str();
else
Graphics::window->msgBoxes.push_back(new Graphics::MessageBox("SUS ඞ",Graphics::ErrorSeverity::Error));
Textures.emplace_back((boost::filesystem::current_path() / "Models" / modelname / string.C_Str()));
}
if(firsttex == ""){
Textures.emplace_back((boost::filesystem::current_path() / "Models" / "Missing.png"));
}
auto vertices = std::vector<glm::vec3>();
auto texcoords = std::vector<glm::vec2>();
auto indices = std::vector<GLuint>();
for(unsigned int verticienum = 0; verticienum < mesh->mNumVertices; verticienum++){
vertices.emplace_back(mesh->mVertices[verticienum].x,mesh->mVertices[verticienum].y,mesh->mVertices[verticienum].z);
if (mesh->HasTextureCoords(0)) // Only slot [0] is in question.
{
texcoords.emplace_back(mesh->mTextureCoords[0][verticienum].x,mesh->mTextureCoords[0][verticienum].y);
}
else
texcoords.emplace_back(0.0f, 0.0f);
}
for (unsigned int i3 = 0; i3 < mesh->mNumFaces; ++i3) {
assert(mesh->mFaces[i3].mNumIndices == 3 && "Faces must always have 3 indices because other ammounts of indices are not supported by opengl!");
for (unsigned int i4 = 0; i4 < mesh->mFaces[i3].mNumIndices; ++i4)
indices.push_back(mesh->mFaces[i3].mIndices[i4]);
}
Meshes.emplace_back(vertices,indices,texcoords,GetMainViewport()->shader);
}
}
void Model::Draw(Transform tf) {
unsigned int texnum = 0;
for(auto mesh: Meshes){
glm::vec3 pos(tf.Position.X,tf.Position.Y,tf.Position.Z);
glm::vec3 rot(-tf.Rotation.X,tf.Rotation.Y,-tf.Rotation.Z);
glm::vec3 scale(tf.Scale.X,tf.Scale.Y,tf.Scale.Z);
mesh.Draw(Textures[texnum],pos,scale,rot);
texnum++;
}
}
void Model::DrawSelection(Transform tf) {
unsigned int texnum = 0;
static Graphics::Texture selectionTex = Graphics::Texture((boost::filesystem::current_path() / "Models" / "selected.png"));
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
for(auto mesh: Meshes){
glm::vec3 pos(tf.Position.X,tf.Position.Y,tf.Position.Z);
glm::vec3 rot(-tf.Rotation.X,tf.Rotation.Y,tf.Rotation.Z);
glm::vec3 scale(tf.Scale.X,tf.Scale.Y,tf.Scale.Z);
mesh.Draw(selectionTex,pos,scale,rot);
texnum++;
}
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
}

28
src/Model.h Normal file
View file

@ -0,0 +1,28 @@
//
// Created by tv on 21.05.23.
//
#ifndef SPOONTOOL_MODEL_H
#define SPOONTOOL_MODEL_H
#include <boost/filesystem/path.hpp>
#include<map>
#include "virintox/gcore/Mesh.h"
#include "Transform.h"
class Model {
public:
Model(std::string modelName);
void Draw(Transform tf);
void DrawSelection(Transform tf);
protected:
std::vector<Graphics::Mesh> Meshes;
std::vector<Graphics::Texture> Textures;
//std::map<std::string,Graphics::Texture> TexturesForName;
};
#endif //SPOONTOOL_MODEL_H

View file

@ -0,0 +1,75 @@
//
// Created by tv on 21.05.23.
//
#include "ObjectSelectWidget.h"
#include "MainWindow.h"
#include "imgui.h"
#include "misc/cpp/imgui_stdlib.h"
#include "boost/filesystem.hpp"
#include<iostream>
#include<fstream>
ObjectSelectWidget* ObjectSelectWidgetInstance = nullptr;
ObjectSelectWidget::ObjectSelectWidget(): Graphics::Widget("Object Select",true) {
}
void ObjectSelectWidget::Draw() {
auto wind = GetMainWindow();
static unsigned int counter = 0;
counter = 0;
for(auto &obj: wind->loadedMap.Objects){
if(ImGui::Selectable((obj.Name + ": " + obj.Type + "##" + std::to_string(obj.runtimeID)).c_str(),wind->selectedElem == &obj)){
wind->selectedElem = &obj;
}
if(ImGui::IsMouseClicked(ImGuiMouseButton_Right) && ImGui::IsItemHovered()){
ImGui::OpenPopup((std::string("Right Click Menu: ObjSelect ") + std::to_string(obj.runtimeID)).c_str());
//ImGui::OpenPopup((std::string("Change Name##: ObjSelect ") + (std::to_string(obj.runtimeID))).c_str());
}
if(ImGui::BeginPopup((std::string("Right Click Menu: ObjSelect ") + std::to_string(obj.runtimeID)).c_str())){
std::string newmodal;
if(ImGui::MenuItem((std::string("Delete##: ObjSelect ") + std::to_string(obj.runtimeID)).c_str())){
std::cout << "Deleting " + obj.Name << std::endl;
wind->loadedMap.Objects.erase(wind->loadedMap.Objects.begin()+counter);
wind->selectedElem = nullptr;
}
if(ImGui::MenuItem((std::string("Duplicate##: ObjSelect ") + std::to_string(obj.runtimeID)).c_str())){
LevelObject dublObj = LevelObject(obj);
dublObj.runtimeID = rand();
wind->loadedMap.Objects.emplace_back(dublObj);
wind->selectedElem = nullptr;
}
if(ImGui::MenuItem((std::string("Export##: ObjSelect ") + std::to_string(obj.runtimeID)).c_str())){
YAML::Emitter emitter;
obj.YamlInsert(emitter);
auto fstr = std::ofstream((boost::filesystem::current_path() / "Presets" / (obj.Name + ".yaml")).string());
fstr << emitter.c_str();
fstr.flush();
fstr.close();
}
ImGui::EndPopup();
}
counter++;
}
}
ObjectSelectWidget* GetObjectSelectWidget(){
return ObjectSelectWidgetInstance;
}

21
src/ObjectSelectWidget.h Normal file
View file

@ -0,0 +1,21 @@
//
// Created by tv on 21.05.23.
//
#ifndef SPOONTOOL_OBJECTSELECTWIDGET_H
#define SPOONTOOL_OBJECTSELECTWIDGET_H
#include "virintox/gcore/Widget.h"
class ObjectSelectWidget: public Graphics::Widget {
public:
ObjectSelectWidget();
private:
void Draw() override;
};
ObjectSelectWidget* GetObjectSelectWidget();
#endif //SPOONTOOL_OBJECTSELECTWIDGET_H

239
src/PropertiesWidget.cpp Normal file
View file

@ -0,0 +1,239 @@
//
// Created by tv on 21.05.23.
//
#include "PropertiesWidget.h"
#include "MainWindow.h"
#include<imgui.h>
#include "misc/cpp/imgui_stdlib.h"
#include "IconsFontAwesome6.h"
#include<array>
struct SimpleVec3{
float x,y,z;
template <typename t>
SimpleVec3(t fromobj){
x = fromobj.X;
y = fromobj.Y;
z = fromobj.Z;
}
template <typename t>
void copyto(t* toobj){
toobj->X = x;
toobj->Y = y;
toobj->Z = z;
}
};
PropertiesWidget* PropertiesWidgetInst = nullptr;
template<typename t,typename iter,typename stringConv>
void ImGuiDrawSelection(std::string id,t& val,iter optsBegin, iter optsEnd,stringConv convert){
if(ImGui::BeginCombo(id.c_str(),convert(val).c_str())) {
while (optsBegin != optsEnd) {
if(ImGui::Selectable((convert(*optsBegin) + "##" + id).c_str()))
val = *optsBegin;
optsBegin++;
}
ImGui::EndCombo();
}
}
template<typename t>
void ImGuiDrawLayer(t *obj){
if(ImGui::BeginCombo("Layer##PropWind",ToString(obj->Layer).c_str())){
if(ImGui::Selectable("Common##TeamsPropWind"))
obj->Layer = Common;
if(ImGui::Selectable("Paint##TeamsPropWind"))
obj->Layer = Paint;
if(ImGui::Selectable("Rainmaker##TeamsPropWind"))
obj->Layer = Rainmaker;
if(ImGui::Selectable("Tower##TeamsPropWind"))
obj->Layer = Tower;
if(ImGui::Selectable("Area##TeamsPropWind"))
obj->Layer = Area;
if(ImGui::Selectable("Night##TeamsPropWind"))
obj->Layer = Night;
if(ImGui::Selectable("Day##TeamsPropWind"))
obj->Layer = Day;
if(ImGui::Selectable("Temporary##TeamsPropWind"))
obj->Layer = Temporary;
ImGui::EndCombo();
}
};
void ImGuiDrawTransform(Transform &tf,std::string id){
ImGui::Text("Transform:");
ImGui::Indent();
{
//auto simplevec3pos = SimpleVec3(tf.Position);
ImGui::DragFloat3(("Position##" + id).c_str(), &(tf.Position.X),0.01);
//simplevec3pos.copyto(&tf.Position);
//auto simplevec3rot = SimpleVec3(tf.Rotation);
ImGui::DragFloat3(("Rotation##" + id).c_str(), &(tf.Rotation.X),0.01);
//simplevec3rot.copyto(&tf.Rotation);
//auto simplevec3scale = SimpleVec3(tf.Scale);
ImGui::DragFloat3(("Scale##" + id).c_str(), &(tf.Scale.X),0.01);
//simplevec3scale.copyto(&tf.Scale);
}
ImGui::Unindent();
}
void ImGuiDrawElem(Element* elem,std::string Id = ""){
Rail* rail = dynamic_cast<Rail*>(elem);
RailPoint* railPoint = dynamic_cast<RailPoint*>(elem);
LevelObject* levelObject = dynamic_cast<LevelObject*>(elem);
Id += std::to_string(elem->runtimeID);
ImGui::PushItemWidth(ImGui::GetWindowWidth()/3);
ImGui::InputText(("##PropWindInputName" + Id).c_str(),&elem->Name);
ImGui::PopItemWidth();
ImGui::SameLine(); ImGui::Text(": "); ImGui::SameLine();
ImGui::PushItemWidth(ImGui::GetWindowWidth()/3);
ImGui::InputText(("##PropWindInputType" + Id).c_str(),&elem->Type);
ImGui::PopItemWidth();
ImGuiDrawTransform(elem->TF,"PropWind" + Id);
ImGuiDrawLayer(elem);
ImGui::Checkbox(("Is Link Destination?##PropWindowIsLinkDest" + Id).c_str(),&elem->IsLinkDest);
if (ImGui::CollapsingHeader(("Links##" + Id).c_str())){
ImGui::Indent();
unsigned i = 1;
for(auto linkIter = elem->Links.begin();linkIter != elem->Links.end();linkIter++){
auto &link = *linkIter;
if (ImGui::CollapsingHeader(("Link " + std::to_string(i) + "##" + Id).c_str())) {
ImGui::Indent();
ImGuiDrawSelection("Link Type##" + std::to_string(i) + Id, link.Name, LinkTypes.begin(), LinkTypes.end(),
[](std::string s) { return s; });
ImGui::InputText(("Destination##PropWindLink" + std::to_string(i) + Id).c_str(), &link.Destination);
ImGui::InputText(("Unit File##PropWindLink" + std::to_string(i) + Id).c_str(), &link.UnitFile);
if(ImGui::Button((ICON_FA_TRASH "##PropWindLinkDelete" + std::to_string(i) + Id).c_str())) {
elem->Links.erase(linkIter);
ImGui::Unindent();
break;
}
ImGui::Unindent();
}
i++;
}
if(ImGui::Button(ICON_FA_PLUS)) {
elem->Links.emplace_back();
}
ImGui::Unindent();
}
if (ImGui::CollapsingHeader(("Element Type Specific Options##" + Id).c_str())){
ImGui::Indent();
if(rail){
ImGui::Checkbox(("Is Closed?##" + Id).c_str(),&rail->IsClosed);
ImGui::Checkbox(("Is Ladder?##" + Id).c_str(),&rail->IsLadder);
ImGui::InputInt(("Priority?##" + Id).c_str(),(int*)&rail->Priority);
ImGuiDrawSelection("Rail Type",rail->RailType,AllRailTypeOptions.begin(), AllRailTypeOptions.end(),[](RailType t){return ToString(t);});
if(ImGui::CollapsingHeader(("Rail Points##"+Id).c_str())){
ImGui::Indent();
unsigned int i = 1;
for(auto curRailPointRef = rail->Points.begin(); curRailPointRef != rail->Points.end();curRailPointRef++){
RailPoint &curRailPoint = *curRailPointRef;
if(ImGui::CollapsingHeader((std::to_string(i) + "##RailPoints").c_str())){
ImGui::Indent();
ImGuiDrawElem(&curRailPoint,"RailPoint" + std::to_string(i) + std::to_string(curRailPoint.runtimeID));
if(ImGui::Button((ICON_FA_TRASH "##PropWindRailPointDelete" + std::to_string(i) + Id).c_str())){
rail->Points.erase(curRailPointRef);
ImGui::Unindent();
break;
}
ImGui::Unindent();
}
i++;
}
if(ImGui::Button((ICON_FA_PLUS "##" + Id).c_str())) {
RailPoint rp = RailPoint(rail->Points.back());
rp.runtimeID = rand();
rail->Points.push_back(rp);
}
ImGui::Unindent();
}
}
if(levelObject) {
//ImGuiDrawTeamSelect(levelObject,Id);
ImGuiDrawSelection("Team##"+Id,levelObject->Team,Teams::AllOptions.begin(), Teams::AllOptions.end(),Teams::TeamToText);
ImGuiDrawSelection("Drop##"+Id,levelObject->DropId,DropId::AllOptions.begin(), DropId::AllOptions.end(),DropId::DropIdToText);
}
if(railPoint){
ImGui::Checkbox(("Use Offset##" + Id).c_str(),&railPoint->m_useOffset);
if(railPoint->m_useOffset) {
ImGui::Indent();
ImGui::DragFloat3(("Offset##" + Id).c_str(), &(railPoint->m_offset.X),0.01);
ImGui::Unindent();
}
unsigned i = 0;
for(Vector3 &ctrlPoint: railPoint->m_controlPoints){
ImGui::DragFloat3(("Control point " + std::to_string(i) + "##" + Id).c_str(), &(ctrlPoint.X),0.01);
i++;
}
}
ImGui::Unindent();
}
if(!elem->Parameters.empty()) {
if (ImGui::CollapsingHeader(("Parameters##" + Id).c_str())) {
ImGui::Indent();
for (int i = 1; i <= elem->Parameters.size(); i++) {
ImGui::InputInt(("Parameter " + std::to_string(i) + "##PropWind" + Id).c_str(),
(int *) &elem->Parameters[i - 1]);
}
ImGui::Unindent();
}
}
if(!elem->FloatParameters.empty()) {
if (ImGui::CollapsingHeader(("Float Parameters##" + Id).c_str())) {
ImGui::Indent();
for (int i = 1; i <= elem->FloatParameters.size(); i++) {
ImGui::InputFloat(("Float Parameter " + std::to_string(i) + "##PropWind" + Id).c_str(),
&elem->FloatParameters[i - 1]);
}
ImGui::Unindent();
}
}
if(!elem->OtherOptions.empty()) {
if (ImGui::CollapsingHeader(("Miscellaneous Options##" + Id).c_str())) {
ImGui::Indent();
for (auto &opt: elem->OtherOptions) {
ImGui::Text("%s:", opt.first.c_str());
ImGui::SameLine();
ImGui::InputText(("##" + opt.first + Id).c_str(), &opt.second);
}
ImGui::Unindent();
}
}
}
PropertiesWidget::PropertiesWidget(): Graphics::Widget("Properties",true) {
PropertiesWidgetInst = this;
GetMainWindow()->selectedElem = nullptr;
}
void PropertiesWidget::Draw() {
auto wind = GetMainWindow();
if(wind->selectedElem != nullptr){
ImGuiDrawElem(wind->selectedElem);
}
}
PropertiesWidget* GetPropertiesWidget(){
return PropertiesWidgetInst;
}

20
src/PropertiesWidget.h Normal file
View file

@ -0,0 +1,20 @@
//
// Created by tv on 21.05.23.
//
#ifndef SPOONTOOL_PROPERTIESWIDGET_H
#define SPOONTOOL_PROPERTIESWIDGET_H
#include "virintox/gcore/Widget.h"
class PropertiesWidget : public Graphics::Widget {
public:
PropertiesWidget();
void Draw() override;
};
PropertiesWidget* GetPropertiesWidget();
#endif //SPOONTOOL_PROPERTIESWIDGET_H

48
src/RailSelectWidget.cpp Normal file
View file

@ -0,0 +1,48 @@
//
// Created by tv on 28.06.23.
//
#include "RailSelectWidget.h"
#include "MainWindow.h"
#include <imgui.h>
#include "IconsFontAwesome6.h"
#include "MainViewport.h"
RailSelectWidget::RailSelectWidget(): Graphics::Widget("Rails",false) {
}
void RailSelectWidget::Draw() {
auto wind = GetMainWindow();
for(auto railIter = wind->loadedMap.Rails.begin();railIter != wind->loadedMap.Rails.end();railIter++){
Rail &rail = *railIter;
if(ImGui::Selectable((rail.Name + ": " + rail.Type + "##" + std::to_string(rail.runtimeID)).c_str(), wind->selectedElem == &rail)){
wind->selectedElem = &rail;
}
if(ImGui::IsMouseClicked(ImGuiMouseButton_Right) && ImGui::IsItemHovered()){
ImGui::OpenPopup((std::string("Right Click Menu: RailSelect ") + std::to_string(rail.runtimeID)).c_str());
//ImGui::OpenPopup((std::string("Change Name##: ObjSelect ") + (std::to_string(obj.runtimeID))).c_str());
}
if(ImGui::BeginPopup((std::string("Right Click Menu: RailSelect ") + std::to_string(rail.runtimeID)).c_str())){
if(ImGui::MenuItem((std::string("Delete##: RailSelect ") + std::to_string(rail.runtimeID)).c_str())){
std::cout << "Deleting " + rail.Name << std::endl;
wind->loadedMap.Rails.erase(railIter);
wind->selectedElem = nullptr;
ImGui::EndPopup();
break;
}
ImGui::EndPopup();
}
}
if(ImGui::Button(ICON_FA_PLUS)){
wind->selectedElem = nullptr;
auto vp = GetMainViewport();
Vector3 pos = {vp->camPos.x, -vp->camPos.y, vp->camPos.z};
wind->loadedMap.Rails.emplace_back(pos);
}
}

19
src/RailSelectWidget.h Normal file
View file

@ -0,0 +1,19 @@
//
// Created by tv on 28.06.23.
//
#ifndef SPOONTOOL_RAILSELECTWIDGET_H
#define SPOONTOOL_RAILSELECTWIDGET_H
#include<virintox/gcore/Widget.h>
class RailSelectWidget: public Graphics::Widget {
public:
RailSelectWidget();
void Draw() override;
};
#endif //SPOONTOOL_RAILSELECTWIDGET_H

13
src/main.cpp Normal file
View file

@ -0,0 +1,13 @@
#include<virintox/gcore/Graphics.h>
#include"MainWindow.h"
#include"imgui.h"
int main(){
Graphics::Init();
Graphics::setWindow<MainWindow>();
//auto &io = ImGui::GetIO();
//io.ConfigWindowsMoveFromTitleBarOnly = true;
Graphics::BeginLoop();
Graphics::Terminate();
}