coeng

annotate src/gobj.cc @ 7:af24cfbdf9b6

adding collision detection
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 14 Feb 2015 10:08:00 +0200
parents 2f872a179914
children 8cce82794f90
rev   line source
nuclear@2 1 #include <stdio.h>
nuclear@6 2 #include <string.h>
nuclear@6 3 #include <assert.h>
nuclear@1 4 #include <algorithm>
nuclear@5 5 #include "gobj.h"
nuclear@1 6
nuclear@6 7 GObject::GObject()
nuclear@1 8 {
nuclear@1 9 sorted = true;
nuclear@1 10 }
nuclear@1 11
nuclear@6 12 GObject::~GObject()
nuclear@1 13 {
nuclear@1 14 for(size_t i=0; i<comp.size(); i++) {
nuclear@1 15 delete comp[i];
nuclear@1 16 }
nuclear@1 17 }
nuclear@1 18
nuclear@6 19 bool GObject::add_component(Component *c)
nuclear@1 20 {
nuclear@1 21 const char *name = c->get_name();
nuclear@1 22
nuclear@1 23 if(comp_by_name.find(name) != comp_by_name.end()) {
nuclear@6 24 fprintf(stderr, "component %s already exists in this gobject (%p)\n", name, (void*)this);
nuclear@1 25 return false;
nuclear@1 26 }
nuclear@1 27
nuclear@1 28 try {
nuclear@1 29 comp.push_back(c);
nuclear@1 30 comp_by_name[name] = c;
nuclear@2 31
nuclear@6 32 c->attach(this);
nuclear@1 33 }
nuclear@1 34 catch(...) {
nuclear@1 35 fprintf(stderr, "failed to add component: %s\n", name);
nuclear@1 36 return false;
nuclear@1 37 }
nuclear@1 38
nuclear@1 39 sorted = false;
nuclear@1 40 return true;
nuclear@1 41 }
nuclear@1 42
nuclear@6 43 bool GObject::remove_component(Component *c)
nuclear@1 44 {
nuclear@1 45 for(size_t i=0; i<comp.size(); i++) {
nuclear@1 46 if(comp[i] == c) {
nuclear@6 47 c->detach();
nuclear@1 48 comp.erase(comp.begin() + i);
nuclear@1 49 comp_by_name.erase(c->get_name());
nuclear@1 50 return true;
nuclear@1 51 }
nuclear@1 52 }
nuclear@1 53 return false;
nuclear@1 54 }
nuclear@1 55
nuclear@6 56 bool GObject::delete_component(Component *c)
nuclear@1 57 {
nuclear@1 58 if(remove_component(c)) {
nuclear@1 59 delete c;
nuclear@1 60 return true;
nuclear@1 61 }
nuclear@1 62 return false;
nuclear@1 63 }
nuclear@1 64
nuclear@6 65 Component *GObject::get_component(const char *name) const
nuclear@1 66 {
nuclear@1 67 std::map<std::string, Component*>::const_iterator it;
nuclear@1 68 if((it = comp_by_name.find(name)) != comp_by_name.end()) {
nuclear@1 69 return it->second;
nuclear@1 70 }
nuclear@1 71 return 0;
nuclear@1 72 }
nuclear@1 73
nuclear@6 74 void GObject::update(float dt)
nuclear@1 75 {
nuclear@1 76 if(!sorted) {
nuclear@6 77 sort_components();
nuclear@6 78 sorted = true;
nuclear@1 79 }
nuclear@1 80
nuclear@1 81 for(size_t i=0; i<comp.size(); i++) {
nuclear@6 82 comp[i]->update(dt);
nuclear@1 83 }
nuclear@1 84 }
nuclear@6 85
nuclear@6 86 void GObject::draw() const
nuclear@6 87 {
nuclear@6 88 // TODO optimization: draw only specific components?
nuclear@6 89 for(size_t i=0; i<comp.size(); i++) {
nuclear@6 90 comp[i]->draw();
nuclear@6 91 }
nuclear@6 92 }
nuclear@6 93
nuclear@6 94 struct TopoSucNode {
nuclear@6 95 int idx;
nuclear@6 96 TopoSucNode *next;
nuclear@6 97 };
nuclear@6 98
nuclear@6 99 struct TopoItem {
nuclear@6 100 Component *co;
nuclear@6 101 int npre; // number of predeccessors
nuclear@6 102 TopoSucNode *suc; // successor list
nuclear@6 103 TopoItem *qnext, *qprev; // queue list links
nuclear@6 104 };
nuclear@6 105
nuclear@6 106 int countq(TopoItem *q)
nuclear@6 107 {
nuclear@6 108 int n = 0;
nuclear@6 109 while(q) {
nuclear@6 110 n++;
nuclear@6 111 q = q->qnext;
nuclear@6 112 }
nuclear@6 113 return n;
nuclear@6 114 }
nuclear@6 115
nuclear@6 116 // topological sort of components based on update_before() relationships
nuclear@6 117 void GObject::sort_components()
nuclear@6 118 {
nuclear@6 119 int nitems = (int)comp.size();
nuclear@6 120 TopoItem *items = (TopoItem*)alloca(nitems * sizeof *items);
nuclear@6 121 TopoItem *queue = items;
nuclear@6 122
nuclear@6 123 // initialize the items
nuclear@6 124 for(int i=0; i<nitems; i++) {
nuclear@6 125 items[i].co = comp[i];
nuclear@6 126 items[i].npre = 0;
nuclear@6 127 items[i].suc = 0;
nuclear@6 128 items[i].qnext = i + 1 < nitems ? items + i + 1 : 0;
nuclear@6 129 items[i].qprev = i > 0 ? items + i - 1 : 0;
nuclear@6 130 }
nuclear@6 131
nuclear@6 132 // populate the array
nuclear@6 133 for(int i=0; i<nitems; i++) {
nuclear@6 134 const char **iter = comp[i]->update_before();
nuclear@6 135 while(*iter) {
nuclear@6 136 const char *sucname = *iter++;
nuclear@6 137
nuclear@6 138 for(int j=0; j<nitems; j++) {
nuclear@6 139 if(j == i) continue;
nuclear@6 140 if(strcmp(comp[j]->get_name(), sucname) == 0) {
nuclear@6 141 // found a component(j) depending on i, increment its predeccessor counter
nuclear@6 142 items[j].npre++;
nuclear@6 143 // remove it from the queue
nuclear@6 144 if(queue == items + j) {
nuclear@6 145 queue = items[j].qnext;
nuclear@6 146 assert(items[j].qprev == 0);
nuclear@6 147 }
nuclear@6 148 if(items[j].qprev) items[j].qprev->qnext = items[j].qnext;
nuclear@6 149 if(items[j].qnext) items[j].qnext->qprev = items[j].qprev;
nuclear@6 150 items[j].qprev = items[j].qnext = 0;
nuclear@6 151
nuclear@6 152 // and add it to our successor list
nuclear@6 153 TopoSucNode *n = (TopoSucNode*)alloca(sizeof *n);
nuclear@6 154 n->idx = j;
nuclear@6 155 n->next = items[i].suc;
nuclear@6 156 items[i].suc = n;
nuclear@6 157 }
nuclear@6 158 }
nuclear@6 159 }
nuclear@6 160 }
nuclear@6 161
nuclear@6 162 // now remove each item from the queue and add it to the sorted list
nuclear@6 163 int idx = 0;
nuclear@6 164 while(queue) {
nuclear@6 165 assert(idx < nitems);
nuclear@6 166 comp[idx++] = queue->co;
nuclear@6 167
nuclear@6 168 // traverse the successor list, decrementing their predeccessor counts
nuclear@6 169 TopoSucNode *n = queue->suc;
nuclear@6 170 queue = queue->qnext;
nuclear@6 171
nuclear@6 172 while(n) {
nuclear@6 173 TopoItem *it = items + n->idx;
nuclear@6 174 n = n->next;
nuclear@6 175
nuclear@6 176 assert(it->npre > 0);
nuclear@6 177 if(--it->npre <= 0) {
nuclear@6 178 // if the count reached zero, add it to the queue
nuclear@6 179 it->qprev = 0;
nuclear@6 180 it->qnext = queue;
nuclear@6 181 queue = it;
nuclear@6 182 }
nuclear@6 183 }
nuclear@6 184 }
nuclear@6 185
nuclear@6 186 assert(idx == nitems);
nuclear@6 187 }