Added animation enter / exit events.
This commit is contained in:
parent
d8c9560cd1
commit
b139d45afe
|
@ -81,7 +81,6 @@ struct InputDecl
|
|||
if (idx == 0) return i;
|
||||
--idx;
|
||||
}
|
||||
ASSERT(false);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ public:
|
|||
ANIMATION_SETS,
|
||||
MAX_ROOT_ROTATION_SPEED,
|
||||
INPUT_REFACTOR,
|
||||
ENTER_EXIT_EVENTS,
|
||||
|
||||
LAST
|
||||
};
|
||||
|
|
|
@ -205,12 +205,12 @@ void Node::removeEvent(int index)
|
|||
}
|
||||
|
||||
|
||||
static const char* getEventTypeName(const Anim::EventHeader& event, AnimEditor::IAnimationEditor& editor)
|
||||
static const char* getEventTypeName(u32 type, AnimEditor::IAnimationEditor& editor)
|
||||
{
|
||||
int count = editor.getEventTypesCount();
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
if (editor.getEventTypeByIdx(i).type == event.type)
|
||||
if (editor.getEventTypeByIdx(i).type == type)
|
||||
{
|
||||
return editor.getEventTypeByIdx(i).label;
|
||||
}
|
||||
|
@ -224,15 +224,19 @@ void Node::onGUI()
|
|||
u32 set_input_type = crc32("set_input");
|
||||
ImGui::InputText("Name", name.data, lengthOf(name.data));
|
||||
if (!engine_cmp) return;
|
||||
auto* engine_node = ((Anim::Node*)engine_cmp);
|
||||
|
||||
onGuiEvents(engine_node->enter_events, "Enter Events");
|
||||
onGuiEvents(engine_node->exit_events, "Exit Events");
|
||||
|
||||
if (!ImGui::CollapsingHeader("Events")) return;
|
||||
|
||||
auto* engine_node = ((Anim::Node*)engine_cmp);
|
||||
auto& events = engine_node->events;
|
||||
auto& editor = m_controller.getEditor();
|
||||
for(int i = 0; i < engine_node->events_count; ++i)
|
||||
{
|
||||
Anim::EventHeader& header = *(Anim::EventHeader*)&events[sizeof(Anim::EventHeader) * i];
|
||||
const char* event_type_name = getEventTypeName(header, editor);
|
||||
const char* event_type_name = getEventTypeName(header.type, editor);
|
||||
if (ImGui::TreeNode((void*)(uintptr)i, "%s - %fs", event_type_name, header.time))
|
||||
{
|
||||
if (ImGui::Button("Remove"))
|
||||
|
@ -279,6 +283,49 @@ void Node::onGUI()
|
|||
}
|
||||
|
||||
|
||||
void Node::onGuiEvents(Anim::EventArray& events, const char* label)
|
||||
{
|
||||
if (!ImGui::CollapsingHeader(label)) return;
|
||||
ImGui::PushID(label);
|
||||
|
||||
auto* engine_node = ((Anim::Node*)engine_cmp);
|
||||
auto& editor = m_controller.getEditor();
|
||||
for (int i = 0; i < events.count; ++i)
|
||||
{
|
||||
auto& header = *(Anim::EnterExitEventHeader*)&events.data[sizeof(Anim::EnterExitEventHeader) * i];
|
||||
const char* event_type_name = getEventTypeName(header.type, editor);
|
||||
if (ImGui::TreeNode((void*)(uintptr)i, "%s", event_type_name))
|
||||
{
|
||||
if (ImGui::Button("Remove"))
|
||||
{
|
||||
events.remove(i);
|
||||
ImGui::TreePop();
|
||||
break;
|
||||
}
|
||||
int event_offset = header.offset + sizeof(Anim::EnterExitEventHeader) * events.count;
|
||||
editor.getEventType(header.type).editor.invoke(&events.data[event_offset], *this);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
auto getter = [](void* data, int idx, const char** out) -> bool {
|
||||
auto* node = (Node*)data;
|
||||
*out = node->m_controller.getEditor().getEventTypeByIdx(idx).label;
|
||||
return true;
|
||||
};
|
||||
static int current = 0;
|
||||
ImGui::Combo("", ¤t, getter, this, editor.getEventTypesCount());
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Add event"))
|
||||
{
|
||||
auto& event_type = editor.getEventTypeByIdx(current);
|
||||
events.append(event_type.size, event_type.type);
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
|
||||
void Node::serialize(OutputBlob& blob)
|
||||
{
|
||||
blob.write(pos);
|
||||
|
|
|
@ -11,7 +11,11 @@ namespace Lumix
|
|||
{
|
||||
|
||||
class ResourceManagerBase;
|
||||
namespace Anim { class ControllerResource; }
|
||||
namespace Anim
|
||||
{
|
||||
class ControllerResource;
|
||||
struct EventArray;
|
||||
}
|
||||
|
||||
|
||||
namespace AnimEditor
|
||||
|
@ -82,6 +86,9 @@ public:
|
|||
void removeInEdge(Edge* edge) { m_in_edges.eraseItemFast(edge); }
|
||||
void removeEvent(int index);
|
||||
|
||||
protected:
|
||||
void onGuiEvents(Anim::EventArray& events, const char* label);
|
||||
|
||||
public:
|
||||
ImVec2 pos;
|
||||
ImVec2 size;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
|
||||
#include "engine/lumix.h"
|
||||
#include "engine/array.h"
|
||||
|
||||
|
||||
namespace Lumix
|
||||
|
@ -21,6 +22,28 @@ struct EventHeader
|
|||
};
|
||||
|
||||
|
||||
struct EnterExitEventHeader
|
||||
{
|
||||
u32 type;
|
||||
u16 offset;
|
||||
u8 size;
|
||||
};
|
||||
|
||||
|
||||
struct EventArray
|
||||
{
|
||||
EventArray(IAllocator& allocator)
|
||||
: data(allocator)
|
||||
, count(0)
|
||||
{}
|
||||
void remove(int index);
|
||||
void append(int size, u32 type);
|
||||
|
||||
Array<u8> data;
|
||||
int count;
|
||||
};
|
||||
|
||||
|
||||
struct SetInputEvent
|
||||
{
|
||||
int input_idx;
|
||||
|
|
|
@ -169,6 +169,8 @@ Node::Node(Component::Type type, IAllocator& _allocator)
|
|||
, out_edges(_allocator)
|
||||
, allocator(_allocator)
|
||||
, events(allocator)
|
||||
, enter_events(allocator)
|
||||
, exit_events(allocator)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -182,6 +184,18 @@ void Node::serialize(OutputBlob& blob)
|
|||
blob.write(events.size());
|
||||
blob.write(&events[0], events.size());
|
||||
}
|
||||
blob.write(enter_events.count);
|
||||
if (enter_events.count > 0)
|
||||
{
|
||||
blob.write(enter_events.data.size());
|
||||
blob.write(&enter_events.data[0], enter_events.data.size());
|
||||
}
|
||||
blob.write(exit_events.count);
|
||||
if (exit_events.count > 0)
|
||||
{
|
||||
blob.write(exit_events.data.size());
|
||||
blob.write(&exit_events.data[0], exit_events.data.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -196,6 +210,25 @@ void Node::deserialize(InputBlob& blob, Container* parent, int version)
|
|||
events.resize(size);
|
||||
blob.read(&events[0], size);
|
||||
}
|
||||
if (version > (int)ControllerResource::Version::ENTER_EXIT_EVENTS)
|
||||
{
|
||||
blob.read(enter_events.count);
|
||||
if (enter_events.count > 0)
|
||||
{
|
||||
int size;
|
||||
blob.read(size);
|
||||
enter_events.data.resize(size);
|
||||
blob.read(&enter_events.data[0], size);
|
||||
}
|
||||
blob.read(exit_events.count);
|
||||
if (exit_events.count > 0)
|
||||
{
|
||||
int size;
|
||||
blob.read(size);
|
||||
exit_events.data.resize(size);
|
||||
blob.read(&exit_events.data[0], size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -273,6 +306,7 @@ void Blend1DNodeInstance::onAnimationSetUpdated(AnimSet& anim_set)
|
|||
|
||||
void Blend1DNodeInstance::enter(RunningContext& rc, ComponentInstance* from)
|
||||
{
|
||||
queueEnterEvents(rc);
|
||||
time = 0;
|
||||
if (node.items.size() > lengthOf(instances))
|
||||
{
|
||||
|
@ -412,6 +446,37 @@ void NodeInstance::queueEvents(RunningContext& rc, float old_time, float time, f
|
|||
}
|
||||
|
||||
|
||||
void NodeInstance::queueEnterEvents(RunningContext& rc)
|
||||
{
|
||||
Node& node = (Node&)source;
|
||||
queueEventArray(rc, node.enter_events);
|
||||
}
|
||||
|
||||
|
||||
void NodeInstance::queueExitEvents(RunningContext& rc)
|
||||
{
|
||||
Node& node = (Node&)source;
|
||||
queueEventArray(rc, node.exit_events);
|
||||
}
|
||||
|
||||
|
||||
void NodeInstance::queueEventArray(RunningContext& rc, const EventArray& events)
|
||||
{
|
||||
if (events.count <= 0) return;
|
||||
|
||||
auto headers = (EnterExitEventHeader*)&events.data[0];
|
||||
for (int i = 0; i < events.count; ++i)
|
||||
{
|
||||
auto& header = headers[i];
|
||||
rc.event_stream->write(header.type);
|
||||
rc.event_stream->write(rc.controller);
|
||||
rc.event_stream->write(header.size);
|
||||
rc.event_stream->write(
|
||||
&events.data[0] + header.offset + sizeof(EnterExitEventHeader) * events.count, header.size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ComponentInstance* NodeInstance::checkOutEdges(Node& node, RunningContext& rc)
|
||||
{
|
||||
rc.current = this;
|
||||
|
@ -421,6 +486,7 @@ ComponentInstance* NodeInstance::checkOutEdges(Node& node, RunningContext& rc)
|
|||
if (edge->condition(rc))
|
||||
{
|
||||
ComponentInstance* new_item = edge->createInstance(*rc.allocator);
|
||||
queueExitEvents(rc);
|
||||
new_item->enter(rc, this);
|
||||
return new_item;
|
||||
}
|
||||
|
@ -532,7 +598,8 @@ struct AnimationNodeInstance : public NodeInstance
|
|||
|
||||
|
||||
void enter(RunningContext& rc, ComponentInstance* from) override
|
||||
{
|
||||
{
|
||||
queueEnterEvents(rc);
|
||||
time = 0;
|
||||
if (node.animations_hashes.empty()) return;
|
||||
int idx = Math::rand() % node.animations_hashes.size();
|
||||
|
@ -746,6 +813,46 @@ Component* createComponent(Component::Type type, IAllocator& allocator)
|
|||
}
|
||||
|
||||
|
||||
void EventArray::remove(int index)
|
||||
{
|
||||
auto headers = (Anim::EnterExitEventHeader*)&data[0];
|
||||
auto header = headers[index];
|
||||
u8* headers_end = (u8*)(headers + count);
|
||||
u8* end = &data.back() + 1;
|
||||
u8* event_start = headers_end + header.offset;
|
||||
u8* event_end = event_start + header.size;
|
||||
|
||||
for (int i = index + 1; i < count; ++i)
|
||||
{
|
||||
auto& h = headers[i];
|
||||
h.offset -= header.size;
|
||||
}
|
||||
|
||||
u8* header_start = (u8*)&headers[index];
|
||||
u8* header_end = header_start + sizeof(Anim::EnterExitEventHeader);
|
||||
moveMemory(header_start, header_end, event_start - header_end);
|
||||
moveMemory(event_start - sizeof(Anim::EnterExitEventHeader), event_end, end - event_end);
|
||||
|
||||
data.resize(data.size() - sizeof(Anim::EnterExitEventHeader) - header.size);
|
||||
|
||||
--count;
|
||||
}
|
||||
|
||||
|
||||
void EventArray::append(int size, u32 type)
|
||||
{
|
||||
int old_payload_size = data.size() - sizeof(Anim::EnterExitEventHeader) * count;
|
||||
data.resize(data.size() + size + sizeof(Anim::EnterExitEventHeader));
|
||||
u8* headers_end = &data[count * sizeof(Anim::EnterExitEventHeader)];
|
||||
moveMemory(headers_end + sizeof(Anim::EnterExitEventHeader), headers_end, old_payload_size);
|
||||
auto& event_header = *(Anim::EnterExitEventHeader*)&data[sizeof(Anim::EnterExitEventHeader) * count];
|
||||
event_header.type = type;
|
||||
event_header.size = size;
|
||||
event_header.offset = old_payload_size;
|
||||
++count;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Anim
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
|
||||
#include "condition.h"
|
||||
#include "events.h"
|
||||
#include "engine/array.h"
|
||||
#include "engine/lumix.h"
|
||||
|
||||
|
@ -84,6 +85,8 @@ struct Node : public Component
|
|||
Array<Edge*> out_edges;
|
||||
Array<u8> events;
|
||||
int events_count = 0;
|
||||
EventArray enter_events;
|
||||
EventArray exit_events;
|
||||
};
|
||||
|
||||
|
||||
|
@ -123,6 +126,10 @@ struct NodeInstance : public ComponentInstance
|
|||
|
||||
ComponentInstance* checkOutEdges(Node& node, RunningContext& rc);
|
||||
void queueEvents(RunningContext& rc, float old_time, float time, float length);
|
||||
void queueEnterEvents(RunningContext& rc);
|
||||
void queueExitEvents(RunningContext& rc);
|
||||
protected:
|
||||
void queueEventArray(RunningContext& rc, const EventArray& events);
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue