Compare commits

..

No commits in common. "5ac22ebac0a762b13f2ea284a0f7108fa14c8928" and "65c7a9aaafc057348d809dbb2c5e6c94b40f0442" have entirely different histories.

5 changed files with 267 additions and 145 deletions

View File

@ -1,35 +0,0 @@
## Graph
### 1. Support of math nodes (or non-AnimNodes in general)
* Enables animators to add custom math for blend inputs or to adjust other inputs (e.g. LookAt or IK
targets).
**Open Issues**
1. When to do the evaluation? Two types of subgraphs:
a) Instant inputs (needed for blend node inputs) that have to be evaluated before
UpdateConnections
b) Processing nodes, e.g. for extracted bones.
### 2. Support of multiple output sockets
* E.g. extract Bone transform
* Increases Node complexity:
* AnimOutput
* AnimOutput + Data
* Data
(Data = bool, float, vec3, quat, ...)
**Open Issues**
1. Unclear when this is actually needed. Using more specific nodes that perform the desired logic
may be better (
c.f. https://dev.epicgames.com/documentation/en-us/unreal-engine/animation-blueprint-bone-driven-controller-in-unreal-engine).
Likely this is not crucial so should be avoided for now.
### 3. Multi-skeleton evaluation
Use case: riding on a horse, interaction between two characters.

View File

@ -14,7 +14,7 @@
/** Manage a set of animations used for an AnimGraph. /** Manage a set of animations used for an AnimGraph.
* *
* By default, it behaves like a resource that allows to resolve animation names to * By default it behaves like a resource that allows to resolve animation names to
* AnimationResources. However, it can also trigger loading of the referenced resources from their * AnimationResources. However, it can also trigger loading of the referenced resources from their
* filenames. This only happens on-demand. * filenames. This only happens on-demand.
*/ */

View File

@ -9,11 +9,52 @@
#include "3rdparty/json/json.hpp" #include "3rdparty/json/json.hpp"
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( inline void to_json(
SkinnedMeshResource, nlohmann::json& j,
m_type, const SkinnedMeshResource& skinnedMeshResource) {
m_resource_file, j["type"] = "SkinnedMeshResource";
m_skeleton_file); j["skeleton"]["file"] = skinnedMeshResource.m_skeleton_file;
for (int i = 0; i < skinnedMeshResource.m_animation_files.size(); i++) {
j["animations"][i]["file"] = skinnedMeshResource.m_animation_files[i];
j["animations"][i]["sync_track"] = skinnedMeshResource.m_sync_tracks[i];
}
}
inline void from_json(
const nlohmann::json& j,
SkinnedMeshResource& skinnedMeshResource) {
if (!j.contains("type") || j["type"] != "SkinnedMeshResource") {
std::cerr << "Unable to parse SkinnedMeshResource: wrong json type!"
<< std::endl;
return;
}
if (!j.contains("skeleton") || !j["skeleton"].contains("file")) {
std::cerr << "Unable to parse SkinnedMeshResource: no skeleton file found!"
<< std::endl;
}
skinnedMeshResource.m_skeleton_file = j["skeleton"]["file"];
if (j.contains("animations")) {
int num_animations = j["animations"].size();
for (int i = 0; i < num_animations; i++) {
if (!j["animations"][i].contains("file")
|| !j["animations"][i].contains("sync_track")) {
std::cerr << "Unable to parse SkinnedMeshResource: invalid animation "
"definition"
<< std::endl;
return;
}
skinnedMeshResource.m_animation_files.push_back(
j["animations"][i]["file"]);
skinnedMeshResource.m_sync_tracks.push_back(
j["animations"][i]["sync_track"].get<SyncTrack>());
}
}
}
bool SkinnedMeshResource::saveToFile(const char* filename) const { bool SkinnedMeshResource::saveToFile(const char* filename) const {
nlohmann::json j = *this; nlohmann::json j = *this;
@ -46,4 +87,8 @@ bool SkinnedMeshResource::loadFromFile(const char* filename) {
void SkinnedMeshResource::createInstance(SkinnedMesh& skinnedMesh) const { void SkinnedMeshResource::createInstance(SkinnedMesh& skinnedMesh) const {
skinnedMesh.LoadSkeleton(m_skeleton_file.c_str()); skinnedMesh.LoadSkeleton(m_skeleton_file.c_str());
for (int i = 0; i < m_animation_files.size(); i++) {
skinnedMesh.LoadAnimation(m_animation_files[i].c_str());
skinnedMesh.m_animation_sync_track.back() = m_sync_tracks[i];
}
} }

View File

@ -12,10 +12,10 @@
#include "SkinnedMesh.h" #include "SkinnedMesh.h"
struct SkinnedMeshResource { struct SkinnedMeshResource {
constexpr static char TypeStr[] = "SkinnedMeshResource";
std::string m_type = TypeStr;
std::string m_resource_file; std::string m_resource_file;
std::string m_skeleton_file; std::string m_skeleton_file;
std::vector<std::string> m_animation_files;
std::vector<SyncTrack> m_sync_tracks;
bool saveToFile(const char* filename) const; bool saveToFile(const char* filename) const;
bool loadFromFile(const char* filename); bool loadFromFile(const char* filename);

View File

@ -254,6 +254,7 @@ static void draw_imgui(ImDrawData*);
#include "ozz/animation/runtime/skeleton.h" #include "ozz/animation/runtime/skeleton.h"
#include "ozz/base/containers/vector.h" #include "ozz/base/containers/vector.h"
#include "ozz/base/io/archive.h" #include "ozz/base/io/archive.h"
#include "ozz/base/io/stream.h"
#include "ozz/base/log.h" #include "ozz/base/log.h"
#include "ozz/base/maths/soa_transform.h" #include "ozz/base/maths/soa_transform.h"
@ -365,80 +366,191 @@ struct Viewport {
}; };
struct ApplicationConfig { struct ApplicationConfig {
constexpr static char TypeStr[] = "ApplicationConfig"; int window_position[2] = {100, 30};
std::string type = TypeStr; int window_size[2] = {1000, 600};
struct ScreenRect {
int position[2];
int size[2];
};
NLOHMANN_DEFINE_TYPE_INTRUSIVE(ScreenRect, position, size);
ScreenRect window = {.position = {100, 30}, .size = {1000, 600}};
struct GraphEditor { struct GraphEditor {
ScreenRect rect = {.position = {20, 20}, .size = {800, 500}};
bool visible = false; bool visible = false;
int position[2] = {20, 20};
int size[2] = {800, 500};
ax::NodeEditor::Config config = {}; ax::NodeEditor::Config config = {};
ax::NodeEditor::EditorContext* context = nullptr; ax::NodeEditor::EditorContext* context = nullptr;
}; };
NLOHMANN_DEFINE_TYPE_INTRUSIVE(GraphEditor, rect, visible);
GraphEditor graph_editor; GraphEditor graph_editor;
struct WidgetRect { struct SkinnedMeshWidget {
ScreenRect rect;
bool visible = false; bool visible = false;
int position[2] = {20, 20};
int size[2] = {800, 500};
}; };
NLOHMANN_DEFINE_TYPE_INTRUSIVE(WidgetRect, rect, visible); SkinnedMeshWidget skinned_mesh_widget;
WidgetRect skinned_mesh_widget = {
.rect = {.position = {20, 20}, .size = {800, 500}},
.visible = false};
WidgetRect animation_player_widget = { struct AnimationPlayerWidget {
.rect = {.position = {20, 20}, .size = {800, 500}}, bool visible = false;
.visible = false}; int position[2] = {20, 20};
int size[2] = {800, 500};
};
AnimationPlayerWidget animation_player_widget;
WidgetRect viewport_widget; struct ViewportWidget {
bool visible = true;
int position[2] = {20, 20};
int size[2] = {800, 500};
};
ViewportWidget viewport_widget;
bool show_imgui_demo_window = false; bool show_imgui_demo_window = false;
bool show_another_window = false; bool show_another_window = false;
bool show_camera_widget = false; bool show_camera_widget = false;
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( void to_json(nlohmann::json& j, const ApplicationConfig& config) {
ApplicationConfig, j["type"] = "AnimTestbedConfig";
type,
window,
graph_editor,
skinned_mesh_widget,
animation_player_widget,
viewport_widget,
show_imgui_demo_window,
show_another_window,
show_camera_widget);
struct ProjectConfig { j["main_window"]["position"][0] = config.window_position[0];
static constexpr char TypeStr[] = "ProjectConfig"; j["main_window"]["position"][1] = config.window_position[1];
std::string type = TypeStr;
std::string animation_library_file = "";
std::string skeleton_file = "";
std::string graph_resource_file = "";
struct ViewConfig {
int pos[2];
};
ViewConfig view_config = {.pos = {300, 200}};
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(ProjectConfig::ViewConfig, pos); j["main_window"]["size"][0] = config.window_size[0];
j["main_window"]["size"][1] = config.window_size[1];
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( j["graph_editor"]["visible"] = config.graph_editor.visible;
ProjectConfig, j["graph_editor"]["position"][0] = config.graph_editor.position[0];
type, j["graph_editor"]["position"][1] = config.graph_editor.position[1];
animation_library_file, j["graph_editor"]["size"][0] = config.graph_editor.size[0];
skeleton_file, j["graph_editor"]["size"][1] = config.graph_editor.size[1];
graph_resource_file,
view_config); j["skinned_mesh_widget"]["visible"] = config.skinned_mesh_widget.visible;
j["skinned_mesh_widget"]["position"][0] =
config.skinned_mesh_widget.position[0];
j["skinned_mesh_widget"]["position"][1] =
config.skinned_mesh_widget.position[1];
j["skinned_mesh_widget"]["size"][0] = config.skinned_mesh_widget.size[0];
j["skinned_mesh_widget"]["size"][1] = config.skinned_mesh_widget.size[1];
j["animation_player_widget"]["visible"] =
config.animation_player_widget.visible;
j["animation_player_widget"]["position"][0] =
config.animation_player_widget.position[0];
j["animation_player_widget"]["position"][1] =
config.animation_player_widget.position[1];
j["animation_player_widget"]["size"][0] =
config.animation_player_widget.size[0];
j["animation_player_widget"]["size"][1] =
config.animation_player_widget.size[1];
j["viewport_widget"]["visible"] = config.viewport_widget.visible;
j["viewport_widget"]["position"][0] = config.viewport_widget.position[0];
j["viewport_widget"]["position"][1] = config.viewport_widget.position[1];
j["viewport_widget"]["size"][0] = config.viewport_widget.size[0];
j["viewport_widget"]["size"][1] = config.viewport_widget.size[1];
j["camera_widget"]["visible"] = config.show_camera_widget;
}
void from_json(const nlohmann::json& j, ApplicationConfig& config) {
if (j.contains("main_window")) {
if (j["main_window"].contains("position")
and j["main_window"]["position"].size() == 2) {
config.window_position[0] = j["main_window"]["position"].at(0);
config.window_position[1] = j["main_window"]["position"].at(1);
}
if (j["main_window"].contains("size")
and j["main_window"]["size"].size() == 2) {
config.window_size[0] = j["main_window"]["size"].at(0);
config.window_size[1] = j["main_window"]["size"].at(1);
}
}
if (j.contains("graph_editor")) {
if (j["graph_editor"].contains("visible")) {
config.graph_editor.visible = j["graph_editor"]["visible"];
}
if (j["graph_editor"].contains("position")
and j["graph_editor"]["position"].size() == 2) {
config.graph_editor.position[0] = j["graph_editor"]["position"].at(0);
config.graph_editor.position[1] = j["graph_editor"]["position"].at(1);
}
if (j["graph_editor"].contains("size")
and j["graph_editor"]["size"].size() == 2) {
config.graph_editor.size[0] = j["graph_editor"]["size"].at(0);
config.graph_editor.size[1] = j["graph_editor"]["size"].at(1);
}
}
if (j.contains("skinned_mesh_widget")) {
if (j["skinned_mesh_widget"].contains("visible")) {
config.skinned_mesh_widget.visible = j["skinned_mesh_widget"]["visible"];
}
if (j["skinned_mesh_widget"].contains("position")
and j["skinned_mesh_widget"]["position"].size() == 2) {
config.skinned_mesh_widget.position[0] =
j["skinned_mesh_widget"]["position"].at(0);
config.skinned_mesh_widget.position[1] =
j["skinned_mesh_widget"]["position"].at(1);
}
if (j["skinned_mesh_widget"].contains("size")
and j["skinned_mesh_widget"]["size"].size() == 2) {
config.skinned_mesh_widget.size[0] =
j["skinned_mesh_widget"]["size"].at(0);
config.skinned_mesh_widget.size[1] =
j["skinned_mesh_widget"]["size"].at(1);
}
}
if (j.contains("animation_player_widget")) {
if (j["animation_player_widget"].contains("visible")) {
config.animation_player_widget.visible =
j["animation_player_widget"]["visible"];
}
if (j["animation_player_widget"].contains("position")
and j["animation_player_widget"]["position"].size() == 2) {
config.animation_player_widget.position[0] =
j["animation_player_widget"]["position"].at(0);
config.animation_player_widget.position[1] =
j["animation_player_widget"]["position"].at(1);
}
if (j["animation_player_widget"].contains("size")
and j["animation_player_widget"]["size"].size() == 2) {
config.animation_player_widget.size[0] =
j["animation_player_widget"]["size"].at(0);
config.animation_player_widget.size[1] =
j["animation_player_widget"]["size"].at(1);
}
}
if (j.contains("viewport_widget")) {
if (j["viewport_widget"].contains("visible")) {
config.viewport_widget.visible = j["viewport_widget"]["visible"];
}
if (j["viewport_widget"].contains("position")
and j["viewport_widget"]["position"].size() == 2) {
config.viewport_widget.position[0] =
j["viewport_widget"]["position"].at(0);
config.viewport_widget.position[1] =
j["viewport_widget"]["position"].at(1);
}
if (j["viewport_widget"].contains("size")
and j["viewport_widget"]["size"].size() == 2) {
config.viewport_widget.size[0] = j["viewport_widget"]["size"].at(0);
config.viewport_widget.size[1] = j["viewport_widget"]["size"].at(1);
}
}
if (j.contains("camera_widget") and j["camera_widget"].contains("visible")) {
config.show_camera_widget = j["camera_widget"]["visible"];
}
}
ApplicationConfig gApplicationConfig; ApplicationConfig gApplicationConfig;
ProjectConfig gProjectConfig;
static void draw_grid(); static void draw_grid();
@ -480,8 +592,8 @@ void load_application_config(const char* filename) {
} }
if (application_config.value("type", "undefined") != "AnimTestbedConfig") { if (application_config.value("type", "undefined") != "AnimTestbedConfig") {
std::cerr << "Invalid json object. Expected type '" std::cerr
<< ApplicationConfig::TypeStr << "' but got '" << "Invalid json object. Expected type 'AnimTestbedConfig' but got '"
<< application_config["type"] << "'." << std::endl; << application_config["type"] << "'." << std::endl;
application_config["type"] = "AnimTestbedConfig"; application_config["type"] = "AnimTestbedConfig";
} }
@ -528,20 +640,20 @@ int main() {
glfwSwapInterval(1); glfwSwapInterval(1);
load_application_config("animtestbed_config.json"); load_application_config("animtestbed_config.json");
if (gApplicationConfig.window.position[0] != 0 if (gApplicationConfig.window_position[0] != 0
|| gApplicationConfig.window.position[1] != 0) { || gApplicationConfig.window_position[1] != 0) {
glfwSetWindowPos( glfwSetWindowPos(
window, window,
gApplicationConfig.window.position[0], gApplicationConfig.window_position[0],
gApplicationConfig.window.position[1]); gApplicationConfig.window_position[1]);
} }
if (gApplicationConfig.window.size[0] != 0 if (gApplicationConfig.window_size[0] != 0
|| gApplicationConfig.window.size[1] != 0) { || gApplicationConfig.window_size[1] != 0) {
glfwSetWindowSize( glfwSetWindowSize(
window, window,
gApplicationConfig.window.size[0], gApplicationConfig.window_size[0],
gApplicationConfig.window.size[1]); gApplicationConfig.window_size[1]);
} }
NFD_Init(); NFD_Init();
@ -561,11 +673,15 @@ int main() {
sgl_setup(&sgldesc); sgl_setup(&sgldesc);
sgl_defaults(); sgl_defaults();
// sgl_context_desc_t sgl_context_desc = {};
// sgl_context ctx = sgl_make_context(&sgl_context_desc);
SkinnedMeshResource skinned_mesh_resource; SkinnedMeshResource skinned_mesh_resource;
skinned_mesh_resource.loadFromFile("../media/SampleSkinnedMesh.json"); skinned_mesh_resource.loadFromFile("../media/SampleSkinnedMesh.json");
SkinnedMesh skinned_mesh; SkinnedMesh skinned_mesh;
skinned_mesh_resource.createInstance(skinned_mesh); skinned_mesh_resource.createInstance(skinned_mesh);
skinned_mesh.SetCurrentAnimation(0);
AnimGraphBlendTree anim_graph; AnimGraphBlendTree anim_graph;
AnimGraphContext anim_graph_context; AnimGraphContext anim_graph_context;
@ -610,13 +726,13 @@ int main() {
// Update window state // Update window state
glfwGetWindowPos( glfwGetWindowPos(
window, window,
&gApplicationConfig.window.position[0], &gApplicationConfig.window_position[0],
&gApplicationConfig.window.position[1]); &gApplicationConfig.window_position[1]);
glfwGetWindowSize( glfwGetWindowSize(
window, window,
&gApplicationConfig.window.size[0], &gApplicationConfig.window_size[0],
&gApplicationConfig.window.size[1]); &gApplicationConfig.window_size[1]);
int cur_width, cur_height; int cur_width, cur_height;
glfwGetFramebufferSize(window, &cur_width, &cur_height); glfwGetFramebufferSize(window, &cur_width, &cur_height);
@ -744,16 +860,14 @@ int main() {
ImGui::SetNextWindowPos( ImGui::SetNextWindowPos(
ImVec2( ImVec2(
static_cast<float>( static_cast<float>(
gApplicationConfig.viewport_widget.rect.position[0]), gApplicationConfig.viewport_widget.position[0]),
static_cast<float>( static_cast<float>(
gApplicationConfig.viewport_widget.rect.position[1])), gApplicationConfig.viewport_widget.position[1])),
ImGuiCond_FirstUseEver); ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize( ImGui::SetNextWindowSize(
ImVec2( ImVec2(
static_cast<float>( static_cast<float>(gApplicationConfig.viewport_widget.size[0]),
gApplicationConfig.viewport_widget.rect.size[0]), static_cast<float>(gApplicationConfig.viewport_widget.size[1])),
static_cast<float>(
gApplicationConfig.viewport_widget.rect.size[1])),
ImGuiCond_FirstUseEver); ImGuiCond_FirstUseEver);
ImGui::Begin("Viewport", &gApplicationConfig.viewport_widget.visible); ImGui::Begin("Viewport", &gApplicationConfig.viewport_widget.visible);
@ -768,9 +882,9 @@ int main() {
} }
ImVec2 viewport_widget_size = ImGui::GetWindowSize(); ImVec2 viewport_widget_size = ImGui::GetWindowSize();
gApplicationConfig.viewport_widget.rect.size[0] = gApplicationConfig.viewport_widget.size[0] =
static_cast<int>(viewport_widget_size.x); static_cast<int>(viewport_widget_size.x);
gApplicationConfig.viewport_widget.rect.size[1] = gApplicationConfig.viewport_widget.size[1] =
static_cast<int>(viewport_widget_size.y); static_cast<int>(viewport_widget_size.y);
ImGui::Text( ImGui::Text(
@ -818,16 +932,16 @@ int main() {
ImGui::SetNextWindowPos( ImGui::SetNextWindowPos(
ImVec2( ImVec2(
static_cast<float>( static_cast<float>(
gApplicationConfig.skinned_mesh_widget.rect.position[0]), gApplicationConfig.skinned_mesh_widget.position[0]),
static_cast<float>( static_cast<float>(
gApplicationConfig.skinned_mesh_widget.rect.position[1])), gApplicationConfig.skinned_mesh_widget.position[1])),
ImGuiCond_FirstUseEver); ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize( ImGui::SetNextWindowSize(
ImVec2( ImVec2(
static_cast<float>( static_cast<float>(
gApplicationConfig.skinned_mesh_widget.rect.size[0]), gApplicationConfig.skinned_mesh_widget.size[0]),
static_cast<float>( static_cast<float>(
gApplicationConfig.skinned_mesh_widget.rect.size[1])), gApplicationConfig.skinned_mesh_widget.size[1])),
ImGuiCond_FirstUseEver); ImGuiCond_FirstUseEver);
ImGui::Begin( ImGui::Begin(
@ -835,15 +949,15 @@ int main() {
&gApplicationConfig.skinned_mesh_widget.visible); &gApplicationConfig.skinned_mesh_widget.visible);
ImVec2 skinned_mesh_widget_position = ImGui::GetWindowPos(); ImVec2 skinned_mesh_widget_position = ImGui::GetWindowPos();
gApplicationConfig.skinned_mesh_widget.rect.position[0] = gApplicationConfig.skinned_mesh_widget.position[0] =
static_cast<int>(skinned_mesh_widget_position.x); static_cast<int>(skinned_mesh_widget_position.x);
gApplicationConfig.skinned_mesh_widget.rect.position[1] = gApplicationConfig.skinned_mesh_widget.position[1] =
static_cast<int>(skinned_mesh_widget_position.y); static_cast<int>(skinned_mesh_widget_position.y);
ImVec2 skinned_mesh_widget_size = ImGui::GetWindowSize(); ImVec2 skinned_mesh_widget_size = ImGui::GetWindowSize();
gApplicationConfig.skinned_mesh_widget.rect.size[0] = gApplicationConfig.skinned_mesh_widget.size[0] =
static_cast<int>(skinned_mesh_widget_size.x); static_cast<int>(skinned_mesh_widget_size.x);
gApplicationConfig.skinned_mesh_widget.rect.size[1] = gApplicationConfig.skinned_mesh_widget.size[1] =
static_cast<int>(skinned_mesh_widget_size.y); static_cast<int>(skinned_mesh_widget_size.y);
SkinnedMeshWidget(&skinned_mesh); SkinnedMeshWidget(&skinned_mesh);
@ -854,17 +968,17 @@ int main() {
if (gApplicationConfig.animation_player_widget.visible) { if (gApplicationConfig.animation_player_widget.visible) {
ImGui::SetNextWindowPos( ImGui::SetNextWindowPos(
ImVec2( ImVec2(
static_cast<float>(gApplicationConfig.animation_player_widget static_cast<float>(
.rect.position[0]), gApplicationConfig.animation_player_widget.position[0]),
static_cast<float>(gApplicationConfig.animation_player_widget static_cast<float>(
.rect.position[1])), gApplicationConfig.animation_player_widget.position[1])),
ImGuiCond_FirstUseEver); ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize( ImGui::SetNextWindowSize(
ImVec2( ImVec2(
static_cast<float>( static_cast<float>(
gApplicationConfig.animation_player_widget.rect.size[0]), gApplicationConfig.animation_player_widget.size[0]),
static_cast<float>( static_cast<float>(
gApplicationConfig.animation_player_widget.rect.size[1])), gApplicationConfig.animation_player_widget.size[1])),
ImGuiCond_FirstUseEver); ImGuiCond_FirstUseEver);
ImGui::Begin( ImGui::Begin(
@ -872,15 +986,15 @@ int main() {
&gApplicationConfig.animation_player_widget.visible); &gApplicationConfig.animation_player_widget.visible);
ImVec2 animation_player_widget_position = ImGui::GetWindowPos(); ImVec2 animation_player_widget_position = ImGui::GetWindowPos();
gApplicationConfig.animation_player_widget.rect.position[0] = gApplicationConfig.animation_player_widget.position[0] =
static_cast<int>(animation_player_widget_position.x); static_cast<int>(animation_player_widget_position.x);
gApplicationConfig.animation_player_widget.rect.position[1] = gApplicationConfig.animation_player_widget.position[1] =
static_cast<int>(animation_player_widget_position.y); static_cast<int>(animation_player_widget_position.y);
ImVec2 animation_player_widget_size = ImGui::GetWindowSize(); ImVec2 animation_player_widget_size = ImGui::GetWindowSize();
gApplicationConfig.animation_player_widget.rect.size[0] = gApplicationConfig.animation_player_widget.size[0] =
static_cast<int>(animation_player_widget_size.x); static_cast<int>(animation_player_widget_size.x);
gApplicationConfig.animation_player_widget.rect.size[1] = gApplicationConfig.animation_player_widget.size[1] =
static_cast<int>(animation_player_widget_size.y); static_cast<int>(animation_player_widget_size.y);
if (anim_graph.m_nodes.size() > 0) { if (anim_graph.m_nodes.size() > 0) {
@ -982,13 +1096,13 @@ int main() {
if (gApplicationConfig.graph_editor.visible) { if (gApplicationConfig.graph_editor.visible) {
ImGui::SetNextWindowPos( ImGui::SetNextWindowPos(
ImVec2( ImVec2(
gApplicationConfig.graph_editor.rect.position[0], gApplicationConfig.graph_editor.position[0],
gApplicationConfig.graph_editor.rect.position[1]), gApplicationConfig.graph_editor.position[1]),
ImGuiCond_FirstUseEver); ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize( ImGui::SetNextWindowSize(
ImVec2( ImVec2(
gApplicationConfig.graph_editor.rect.size[0], gApplicationConfig.graph_editor.size[0],
gApplicationConfig.graph_editor.rect.size[1]), gApplicationConfig.graph_editor.size[1]),
ImGuiCond_FirstUseEver); ImGuiCond_FirstUseEver);
ImGui::Begin( ImGui::Begin(
@ -997,14 +1111,12 @@ int main() {
ImGuiWindowFlags_MenuBar); ImGuiWindowFlags_MenuBar);
ImVec2 graph_editor_position = ImGui::GetWindowPos(); ImVec2 graph_editor_position = ImGui::GetWindowPos();
gApplicationConfig.graph_editor.rect.position[0] = gApplicationConfig.graph_editor.position[0] = graph_editor_position.x;
graph_editor_position.x; gApplicationConfig.graph_editor.position[1] = graph_editor_position.y;
gApplicationConfig.graph_editor.rect.position[1] =
graph_editor_position.y;
ImVec2 graph_editor_size = ImGui::GetWindowSize(); ImVec2 graph_editor_size = ImGui::GetWindowSize();
gApplicationConfig.graph_editor.rect.size[0] = graph_editor_size.x; gApplicationConfig.graph_editor.size[0] = graph_editor_size.x;
gApplicationConfig.graph_editor.rect.size[1] = graph_editor_size.y; gApplicationConfig.graph_editor.size[1] = graph_editor_size.y;
AnimGraphEditorUpdate(gApplicationConfig.graph_editor.context); AnimGraphEditorUpdate(gApplicationConfig.graph_editor.context);