195 lines
6.4 KiB
ActionScript
195 lines
6.4 KiB
ActionScript
class EntityNodeUI {
|
|
Entity entity;
|
|
array<EntityNodeUI@> children;
|
|
TreePanel@ rootPanel;
|
|
|
|
string displayName;
|
|
vec3 networkColor;
|
|
EntityNetworkBehaviour initialNetworkBehaviour;
|
|
|
|
EntityNodeUI(Entity _entity, TreePanel@ _root) {
|
|
entity = _entity;
|
|
@rootPanel = _root;
|
|
|
|
updateInfo();
|
|
buildChildren();
|
|
}
|
|
|
|
// Updates cached info
|
|
void updateInfo() {
|
|
displayName = entity.name;
|
|
if (displayName == "") displayName = "-"; else displayName = "\uf1b2 " + entity.name;
|
|
initialNetworkBehaviour = entity.networkBehaviour;
|
|
|
|
if (!entity.isValidNetworkBehaviour()) {
|
|
networkColor = vec3(1, 0.4f, 0.4f);
|
|
} else {
|
|
EntityNetworkBehaviour net = entity.getForcedNetworkBehaviour();
|
|
if (net == EntityNetworkBehaviour::Client) networkColor = vec3(0.6, 1, 0.7); else if (net == EntityNetworkBehaviour::Server) networkColor = vec3(0.6, 0.7, 1); else networkColor = vec3(1, 1, 1);
|
|
}
|
|
}
|
|
|
|
// Build persistent children nodes
|
|
void buildChildren() {
|
|
children.resize(0);
|
|
array<Entity>@ childEntities = entity.getChildrens();
|
|
for (uint i = 0; i < childEntities.length(); i++) {
|
|
if (rootPanel.networkBehaviourFilter != EntityNetworkBehaviour::Parent) {
|
|
EntityNetworkBehaviour entBeh = childEntities[i].getForcedNetworkBehaviour();
|
|
if (entBeh != EntityNetworkBehaviour::Parent && entBeh != rootPanel.networkBehaviourFilter)
|
|
continue;
|
|
}
|
|
|
|
EntityNodeUI@ child = @EntityNodeUI(childEntities[i], rootPanel);
|
|
children.insertLast(child);
|
|
}
|
|
}
|
|
|
|
bool isActive() {
|
|
return entity == ActiveEntity::getActiveEntity();
|
|
}
|
|
|
|
// Call each frame to render the node tree
|
|
void render() {
|
|
bool opened = false;
|
|
if (children.length() == 0) {
|
|
ImGui::treeNodeLeaf("##" + entity.id, isActive());
|
|
renderInteraction();
|
|
} else {
|
|
opened = ImGui::treeNode("##" + entity.id, isActive(), SimpleFunction(this.renderChildren));
|
|
if (!opened) renderInteraction();
|
|
}
|
|
}
|
|
|
|
void renderChildren() {
|
|
renderInteraction();
|
|
if (!entity.exists) return;
|
|
for (uint i = 0; i < children.length(); i++) {
|
|
if (children[i].entity.exists) children[i].render();
|
|
}
|
|
}
|
|
|
|
void renderInteraction() {
|
|
|
|
// Drag and drop
|
|
ImGui::dragDropSource("ENTITY", any(entity), entity.name);
|
|
ImGui::dragDropTarget("ENTITY", ReciverFunction(this.entityDrop));
|
|
|
|
// Selection
|
|
if (ImGui::isItemClicked(0))
|
|
ActiveEntity::setActiveEntity(entity);
|
|
|
|
// Context menu
|
|
ImGui::contextItemPopup("POP_ENTITY_" + entity.id, SimpleFunction(this.renderContextMenu));
|
|
ImGui::simplePopup("RENAME_ENTITY_" + entity.id, SimpleFunction(this.renameEntity));
|
|
|
|
if (!entity.exists) return;
|
|
|
|
// Network color and name
|
|
ImGui::sameline();
|
|
ImGui::textColor(networkColor.x, networkColor.y, networkColor.z, displayName);
|
|
|
|
if (initialNetworkBehaviour != entity.networkBehaviour) rootPanel.onInit();
|
|
|
|
if (initialNetworkBehaviour != EntityNetworkBehaviour::Parent) {
|
|
ImGui::sameline();
|
|
if (initialNetworkBehaviour != EntityNetworkBehaviour::Server)
|
|
ImGui::textEnd("\uf233 Client "); else
|
|
ImGui::textEnd("\uf233 Server ");
|
|
}
|
|
|
|
}
|
|
|
|
void entityDrop(any@ data) {
|
|
Entity dropped;
|
|
data.retrieve(dropped);
|
|
if (dropped.isRoot || entity.isDescendantOf(dropped)) return;
|
|
dropped.parent = entity;
|
|
rootPanel.onInit();
|
|
}
|
|
|
|
void renderContextMenu() {
|
|
if (entity.isRoot) {
|
|
if (ImGui::menuItem("New Entity")) {
|
|
entity.createChild("node");
|
|
rootPanel.onInit();
|
|
}
|
|
} else {
|
|
if (ImGui::menuItem("Add child")) {
|
|
entity.createChild("node");
|
|
rootPanel.onInit();
|
|
}
|
|
if (ImGui::menuItem("Rename")) {
|
|
ImGui::openPopup("RENAME_ENTITY_" + entity.id, any(entity));
|
|
rootPanel.onInit();
|
|
}
|
|
if (ImGui::menuItem("Destroy")) {
|
|
if (ActiveEntity::entity == entity) ActiveEntity::setActiveEntity(World::getRoot());
|
|
|
|
entity.destroy();
|
|
rootPanel.onInit();
|
|
}
|
|
}
|
|
}
|
|
|
|
void renameEntity() {
|
|
string outName;
|
|
if (ImGui::inputText("Entity name ", entity.name, outName)) entity.name = outName;
|
|
rootPanel.onInit();
|
|
}
|
|
|
|
// Call when hierarchy changes
|
|
void refresh() {
|
|
updateInfo();
|
|
buildChildren();
|
|
}
|
|
}
|
|
|
|
class TreePanel : Panel {
|
|
EntityNodeUI@ rootNode;
|
|
bool infoChanged = false;
|
|
EntityNetworkBehaviour networkBehaviourFilter = EntityNetworkBehaviour::Parent;
|
|
|
|
void onInit() {
|
|
infoChanged = true;
|
|
}
|
|
|
|
void onMenuBar() {
|
|
if (ImGui::menuItem("Refresh")) {
|
|
infoChanged = true;
|
|
networkBehaviourFilter = EntityNetworkBehaviour::Parent;
|
|
}
|
|
|
|
string networkBehaviourFilterName;
|
|
if (networkBehaviourFilter == EntityNetworkBehaviour::Parent) networkBehaviourFilterName = "Server&Client"; else if (networkBehaviourFilter == EntityNetworkBehaviour::Server) networkBehaviourFilterName = "Server"; else networkBehaviourFilterName = "Client";
|
|
ImGui::drawComboEnd("##Filter", networkBehaviourFilterName, SimpleFunction(this.networkFilter));
|
|
}
|
|
|
|
void networkFilter() {
|
|
if (ImGui::drawComboItem("Server&Client", networkBehaviourFilter == EntityNetworkBehaviour::Parent)){
|
|
networkBehaviourFilter = EntityNetworkBehaviour::Parent;
|
|
infoChanged = true;
|
|
}
|
|
if (ImGui::drawComboItem("Server", networkBehaviourFilter == EntityNetworkBehaviour::Server)){
|
|
networkBehaviourFilter = EntityNetworkBehaviour::Server;
|
|
infoChanged = true;
|
|
}
|
|
if (ImGui::drawComboItem("Client", networkBehaviourFilter == EntityNetworkBehaviour::Client)){
|
|
networkBehaviourFilter = EntityNetworkBehaviour::Client;
|
|
infoChanged = true;
|
|
}
|
|
}
|
|
|
|
void onImGui() {
|
|
|
|
if (infoChanged) {
|
|
Entity root = World::getRoot();
|
|
@rootNode = @EntityNodeUI(root, this);
|
|
|
|
infoChanged = false;
|
|
}
|
|
|
|
rootNode.render();
|
|
}
|
|
}
|