Open source Star Ruler 2 source code!
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
#include "obj_group.h"
|
||||
#include "object.h"
|
||||
#include "physics/physics_world.h"
|
||||
#include "main/references.h"
|
||||
#include "main/logging.h"
|
||||
#include "util/save_file.h"
|
||||
#include <map>
|
||||
|
||||
threads::ReadWriteMutex groupIDsLock;
|
||||
threads::atomic_int nextGroupID(1);
|
||||
std::map<int,ObjectGroup*> groups;
|
||||
|
||||
void registerObjectGroup(ObjectGroup* group, int id = -1) {
|
||||
groupIDsLock.writeLock();
|
||||
|
||||
group->grab();
|
||||
|
||||
if(id == -1) {
|
||||
group->id = nextGroupID++;
|
||||
}
|
||||
else {
|
||||
group->id = id;
|
||||
nextGroupID = id+1;
|
||||
}
|
||||
|
||||
groups[group->id] = group;
|
||||
groupIDsLock.release();
|
||||
}
|
||||
|
||||
void unregisterObjectGroup(ObjectGroup* group) {
|
||||
groupIDsLock.writeLock();
|
||||
|
||||
groups.erase(group->id);
|
||||
group->drop();
|
||||
|
||||
groupIDsLock.release();
|
||||
}
|
||||
|
||||
ObjectGroup* ObjectGroup::byID(int id) {
|
||||
ObjectGroup* group = 0;
|
||||
|
||||
groupIDsLock.readLock();
|
||||
auto iter = groups.find(id);
|
||||
if(iter != groups.end())
|
||||
group = iter->second;
|
||||
|
||||
if(group)
|
||||
group->grab();
|
||||
groupIDsLock.release();
|
||||
return group;
|
||||
}
|
||||
|
||||
ObjectGroup::ObjectGroup(unsigned count, int id) : objectCount(count), origObjectCount(count), objects(new Object*[count]), physItem(new PhysicsItem), owner(0) {
|
||||
PhysicsGroup* physGroup = new PhysicsGroup;
|
||||
physGroup->itemCount = count;
|
||||
physGroup->items = new PhysicsItem[count];
|
||||
|
||||
physItem->type = PhysItemType(PIT_Group | PIT_Object);
|
||||
physItem->group = physGroup;
|
||||
|
||||
memset(objects, 0, sizeof(Object*) * count);
|
||||
registerObjectGroup(this, id);
|
||||
}
|
||||
|
||||
bool ObjectGroup::postLoad() {
|
||||
//Remove invalid objects
|
||||
unsigned off = 0;
|
||||
for(unsigned i = 0; i < objectCount; ++i) {
|
||||
Object* obj = objects[i];
|
||||
if(!obj->isValid() || !obj->isInitialized()) {
|
||||
physItem->group->items[i].object = 0;
|
||||
++off;
|
||||
}
|
||||
else {
|
||||
if(off != 0)
|
||||
objects[i-off] = obj;
|
||||
}
|
||||
obj->drop();
|
||||
}
|
||||
objectCount -= off;
|
||||
|
||||
//Check if the group should die
|
||||
if(objectCount == 0) {
|
||||
owner = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
//Check if the owner is valid
|
||||
if(!owner->isValid() || !owner->isInitialized())
|
||||
owner = objects[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
void ObjectGroup::postInit() {
|
||||
//Update physics item
|
||||
physItem->bound.reset(objects[0]->physItem->bound);
|
||||
for(unsigned i = 1; i < objectCount; ++i)
|
||||
physItem->bound.addBox(objects[i]->physItem->bound);
|
||||
|
||||
devices.physics->registerItem(*physItem);
|
||||
}
|
||||
|
||||
ObjectGroup::~ObjectGroup() {
|
||||
devices.physics->unregisterItem(*physItem);
|
||||
delete[] physItem->group->items;
|
||||
delete physItem;
|
||||
delete[] objects;
|
||||
}
|
||||
|
||||
unsigned ObjectGroup::getObjectCount() const {
|
||||
return objectCount;
|
||||
}
|
||||
|
||||
unsigned ObjectGroup::getMaxObjectCount() const {
|
||||
return origObjectCount;
|
||||
}
|
||||
|
||||
Object* ObjectGroup::getObject(unsigned index) {
|
||||
return objects[index];
|
||||
}
|
||||
|
||||
const Object* ObjectGroup::getObject(unsigned index) const {
|
||||
return objects[index];
|
||||
}
|
||||
|
||||
void ObjectGroup::setObject(unsigned index, Object* obj) {
|
||||
objects[index] = obj;
|
||||
if(index == 0 && owner == 0)
|
||||
owner = obj;
|
||||
if(obj)
|
||||
obj->grab();
|
||||
}
|
||||
|
||||
unsigned ObjectGroup::setNextObject(Object* obj) {
|
||||
for(unsigned i = 0; i < objectCount; ++i) {
|
||||
if(objects[i] != 0)
|
||||
continue;
|
||||
objects[i] = obj;
|
||||
if(i == 0 && owner == nullptr)
|
||||
owner = obj;
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Object* ObjectGroup::getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
void ObjectGroup::setOwner(Object* obj) {
|
||||
owner = obj;
|
||||
}
|
||||
|
||||
vec3d ObjectGroup::getCenter() const {
|
||||
return physItem->bound.getCenter();
|
||||
}
|
||||
|
||||
PhysicsItem* ObjectGroup::getPhysicsItem() {
|
||||
return physItem;
|
||||
}
|
||||
|
||||
PhysicsItem* ObjectGroup::getPhysicsItem(unsigned index) const {
|
||||
return &physItem->group->items[index];
|
||||
}
|
||||
|
||||
bool ObjectGroup::removeOwner() {
|
||||
Object* newOwner = 0;
|
||||
double nearest = 9.0e40;
|
||||
|
||||
//Move objects down to the lower indices, and find the nearest object to the previous owner to be the new owner
|
||||
unsigned j = 0;
|
||||
for(unsigned i = 0; i < objectCount; ++i) {
|
||||
Object*& obj = objects[i];
|
||||
|
||||
if(!obj) {
|
||||
++j;
|
||||
}
|
||||
else if(obj->isValid() && obj != owner) {
|
||||
double dist = owner->position.distanceToSQ(obj->position);
|
||||
if(dist < nearest) {
|
||||
nearest = dist;
|
||||
newOwner = obj;
|
||||
}
|
||||
|
||||
if(j != i) {
|
||||
objects[j] = obj;
|
||||
obj = 0;
|
||||
}
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
objectCount = j;
|
||||
if(objectCount != 0) {
|
||||
if(newOwner)
|
||||
owner = newOwner;
|
||||
else
|
||||
owner = objects[0];
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
owner = 0;
|
||||
unregisterObjectGroup(this);
|
||||
drop();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectGroup::update() {
|
||||
AABBoxd box;
|
||||
box.reset(owner->physItem->bound);
|
||||
|
||||
unsigned j = 1;
|
||||
for(unsigned i = 1; i < objectCount; ++i) {
|
||||
if(!objects[i]) {
|
||||
++j;
|
||||
} else if(objects[i]->isValid()) {
|
||||
box.addBox(objects[i]->physItem->bound);
|
||||
if(j != i) {
|
||||
objects[j] = objects[i];
|
||||
objects[i] = 0;
|
||||
}
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
objectCount = j;
|
||||
devices.physics->updateItem(*physItem, box);
|
||||
}
|
||||
|
||||
ObjectGroup::ObjectGroup(SaveFile& file) {
|
||||
file >> id >> objectCount >> formationFacing;
|
||||
objects = new Object*[objectCount];
|
||||
|
||||
for(unsigned i = 0; i < objectCount; ++i)
|
||||
file >> objects[i];
|
||||
|
||||
owner = objects[(unsigned short)file];
|
||||
|
||||
PhysicsGroup* physGroup = new PhysicsGroup;
|
||||
physGroup->itemCount = objectCount;
|
||||
physGroup->items = new PhysicsItem[objectCount];
|
||||
|
||||
physItem = new PhysicsItem;
|
||||
physItem->type = PhysItemType(PIT_Group | PIT_Object);
|
||||
physItem->group = physGroup;
|
||||
|
||||
registerObjectGroup(this);
|
||||
}
|
||||
|
||||
void ObjectGroup::save(SaveFile& file) {
|
||||
file << id;
|
||||
file << objectCount;
|
||||
file << formationFacing;
|
||||
|
||||
unsigned ownerIndex = 0;
|
||||
for(unsigned i = 0; i < objectCount; ++i) {
|
||||
file << objects[i];
|
||||
if(objects[i] == owner)
|
||||
ownerIndex = i;
|
||||
}
|
||||
file << (unsigned short)ownerIndex;
|
||||
}
|
||||
Reference in New Issue
Block a user