#include "DataModelV3/PartInstance.h" #include "DataModelV3/DataModelInstance.h" #include "DataModelV3/XplicitNgine/XplicitNgine.h" #include "Renderer.h" #include #include #include "Faces.h" #include "AudioPlayer.h" #include "StringFunctions.h" using namespace B3D; using namespace Reflection; PartInstance::PartInstance(void) { PVInstance::PVInstance("Part"); name = "Unnamed PVItem"; canCollide = ReflectionProperty("CanCollide", true, TYPE_BOOLEAN, this->dataTable); anchored = ReflectionProperty("Anchored", false, TYPE_BOOLEAN, this->dataTable); size = ReflectionProperty("Size", Vector3(2,1,4), TYPE_VECTOR3, this->dataTable); setCFrame(CoordinateFrame(Vector3(0,0,0))); color = ReflectionProperty("Color", Color3::gray(), TYPE_COLOR3, this->dataTable); velocity = ReflectionProperty("Velocity", Vector3(0,0,0), TYPE_VECTOR3, this->dataTable); rotVelocity = ReflectionProperty("RotVelocity", Vector3(0,0,0), TYPE_VECTOR3, this->dataTable); top = ReflectionProperty("TopSurface", Enum::SurfaceType::Bumps, TYPE_ENUM, this->dataTable, (void*)new EnumMeta(Enum::SurfaceType::LENGTH, Enum::SurfaceType::STR_TABLE)); front = ReflectionProperty("FrontSurface", Enum::SurfaceType::Smooth, TYPE_ENUM, this->dataTable, (void*)new EnumMeta(Enum::SurfaceType::LENGTH, Enum::SurfaceType::STR_TABLE)); right = ReflectionProperty("RightSurface", Enum::SurfaceType::Smooth, TYPE_ENUM, this->dataTable, (void*)new EnumMeta(Enum::SurfaceType::LENGTH, Enum::SurfaceType::STR_TABLE)); back = ReflectionProperty("BackSurface", Enum::SurfaceType::Smooth, TYPE_ENUM, this->dataTable, (void*)new EnumMeta(Enum::SurfaceType::LENGTH, Enum::SurfaceType::STR_TABLE)); left = ReflectionProperty("LeftSurface", Enum::SurfaceType::Smooth, TYPE_ENUM, this->dataTable, (void*)new EnumMeta(Enum::SurfaceType::LENGTH, Enum::SurfaceType::STR_TABLE)); bottom = ReflectionProperty("BottomSurface", Enum::SurfaceType::Smooth, TYPE_ENUM, this->dataTable, (void*)new EnumMeta(Enum::SurfaceType::LENGTH, Enum::SurfaceType::STR_TABLE)); shape = ReflectionProperty("Shape", Enum::Shape::Block, TYPE_ENUM, this->dataTable, (void*)new EnumMeta(Enum::Shape::LENGTH, Enum::Shape::STR_TABLE)); // OnTouch singleShot = ReflectionProperty("SingleShot", true, TYPE_BOOLEAN, this->dataTable); touchesToTrigger = ReflectionProperty("TouchesToTrigger", 1, TYPE_INT, this->dataTable); uniqueObjectsToTrigger = ReflectionProperty("UniqueObjectsToTrigger", 1, TYPE_INT, this->dataTable); changeScore = ReflectionProperty("ChangeScore", 0, TYPE_INT, this->dataTable); changeTimer = ReflectionProperty("ChangeTimer", 0.0f, TYPE_FLOAT, this->dataTable); // Non-Reflective Properties physBody = NULL; glList = glGenLists(1); _touchedOnce = false; dragging = false; } bool PartInstance::isDragging() { return dragging; } void PartInstance::setDragging(bool value) { if (dragging != value && getParentDataModel() != NULL) { dragging = value; //TODO implement engine //getParentDataModel()->getEngine()->resetBody(this); } } float PartInstance::getMass() { if(shape == Enum::Shape::Block) return size.value->x*size.value->y*size.value->z*0.7F; else return 1.3333333333333333333333333333333F*(size.value->x/2)*(size.value->y/2)*(size.value->z/2)*0.7F; } Vector3 PartInstance::getVelocity() { return velocity.getValue(); } Vector3 PartInstance::getRotVelocity() { return rotVelocity.getValue(); } // OnTouch bool PartInstance::isSingleShot() { return singleShot.getValue(); } int PartInstance::getTouchesToTrigger() { return touchesToTrigger.getValue(); } int PartInstance::getUniqueObjectsToTrigger() { return uniqueObjectsToTrigger.getValue(); } int PartInstance::getChangeScore() { return changeScore.getValue(); } float PartInstance::getChangeTimer() { return changeTimer.getValue(); } void PartInstance::setVelocity(Vector3 v) { velocity = v; } void PartInstance::setRotVelocity(Vector3 v) { rotVelocity = v; } void PartInstance::postRender(RenderDevice *rd) { // possibly discard this function... } void PartInstance::renderName(RenderDevice *rd) { if(!nameShown) return; G3D::GFontRef fnt = NULL; Instance* dm = parent; while(dm != NULL) { if(DataModelInstance* mod = dynamic_cast(dm)) { fnt = mod->font; break; } dm = dm->getParent(); } if(!fnt.isNull()) { Vector3 gamepoint = position + Vector3(0,1.5,0); Vector3 camerapoint = rd->getCameraToWorldMatrix().translation; float distance = pow(pow((double)gamepoint.x - (double)camerapoint.x, 2) + pow((double)gamepoint.y - (double)camerapoint.y, 2) + pow((double)gamepoint.z - (double)camerapoint.z, 2), 0.5); if(distance < 100 && distance > -100) { if(distance < 0) distance = distance*-1; glDisable(GL_DEPTH_TEST); fnt->draw3D(rd, name.getValue(), CoordinateFrame(rd->getCameraToWorldMatrix().rotation, gamepoint), 0.03*distance, Color3::yellow(), Color3::black(), G3D::GFont::XALIGN_CENTER, G3D::GFont::YALIGN_CENTER); glEnable(GL_DEPTH_TEST); } } } void PartInstance::setChanged() { changed = true; } void PartInstance::setSurface(int face, Enum::SurfaceType::Value surface) { switch(face) { case TOP: top = surface; break; case BOTTOM: bottom = surface; break; case LEFT: left = surface; break; case RIGHT: right = surface; break; case FRONT: front = surface; break; default: back = surface; } changed = true; } void PartInstance::setParent(Instance* prnt) { if(this->physBody != NULL && getParentDataModel() != NULL) { //TODO implement engine //getParentDataModel()->getEngine()->deleteBody(this); } Instance * cparent = getParent(); //TODO implement workspace /*while(cparent != NULL) { if(WorkspaceInstance* workspace = dynamic_cast(cparent)) { workspace->partObjects.erase(std::remove(workspace->partObjects.begin(), workspace->partObjects.end(), this), workspace->partObjects.end()); } cparent = cparent->getParent(); }*/ Instance::setParent(prnt); cparent = getParent(); //TODO implement workspace /* while(cparent != NULL) { if(WorkspaceInstance* workspace = dynamic_cast(cparent)) { workspace->partObjects.push_back(this); break; } cparent = cparent->getParent(); }*/ } void PartInstance::setSize(Vector3 newSize) { int minsize = 1; int maxsize = 512; changed = true; int sizex = (int)newSize.x; if(sizex <= 0) sizex = 1; if(sizex > 512) sizex = 512; int sizey = (int)newSize.y; if(sizey <= 0) sizey = 1; if(sizey > 512) sizey = 512; int sizez = (int)newSize.z; if(sizez <= 0) sizez = 1; if(sizez > 512) sizez = 512; if(shape != Enum::Shape::Block) { int max = sizex; if(sizey > max) max = sizey; if(sizez > max) max = sizez; sizex = sizey = sizez = max; } size = Vector3(sizex, sizey, sizez); if(this->physBody != NULL && getParentDataModel() != NULL) getParentDataModel()->getEngine()->resetBody(this); } Vector3 PartInstance::getSize() { return size.getValue(); } Vector3 PartInstance::getPosition() { return position.getValue(); } void PartInstance::setShape(Enum::Shape::Value shape) { switch(shape) { case Enum::Shape::Block: this->shape = shape; break; default: this->shape = shape; this->setSize(this->getSize()); } if(this->physBody != NULL && getParentDataModel() != NULL) getParentDataModel()->getEngine()->resetBody(this); changed = true; } void PartInstance::setPosition(Vector3 pos) { position = pos; setCFrame(CoordinateFrame(cFrame.value->rotation, pos)); if (anchored && getParentDataModel() != NULL) getParentDataModel()->getEngine()->resetBody(this); } void PartInstance::setAnchored(bool anchored) { this->anchored = anchored; if(this->physBody != NULL && getParentDataModel() != NULL) getParentDataModel()->getEngine()->resetBody(this); } bool PartInstance::isAnchored() { return this->anchored.getValue(); } CoordinateFrame PartInstance::getCFrame() { return cFrame.value->rotation; } void PartInstance::setCFrame(CoordinateFrame coordinateFrame) { setCFrameNoSync(coordinateFrame); if(getParentDataModel() != NULL) getParentDataModel()->getEngine()->updateBody(this); } void PartInstance::setCFrameNoSync(CoordinateFrame coordinateFrame) { cFrame = coordinateFrame; position = coordinateFrame.translation; } bool PartInstance::collides(PartInstance * part) { if(shape == Enum::Shape::Block) { if(part->shape == Enum::Shape::Block) return G3D::CollisionDetection::fixedSolidBoxIntersectsFixedSolidBox(getBox(), part->getBox()); else return G3D::CollisionDetection::fixedSolidSphereIntersectsFixedSolidBox(part->getSphere(), getBox()); } else { if(part->shape == Enum::Shape::Block) return G3D::CollisionDetection::fixedSolidSphereIntersectsFixedSolidBox(getSphere(), part->getBox()); else return G3D::CollisionDetection::fixedSolidSphereIntersectsFixedSolidSphere(getSphere(), part->getSphere()); } } Box PartInstance::getBox() { Box box = Box(Vector3(size.value->x/2, size.value->y/2, size.value->z/2) ,Vector3(-size.value->x/2,-size.value->y/2,-size.value->z/2)); CoordinateFrame c = getCFrame(); itemBox = c.toWorldSpace(box); return itemBox; } Sphere PartInstance::getSphere() { Sphere sphere = Sphere(Vector3(0,0,0), size.value->y/2); CoordinateFrame c = getCFrame(); return sphere; } bool PartInstance::collides(Box box) { return CollisionDetection::fixedSolidBoxIntersectsFixedSolidBox(getBox(), box); } void PartInstance::render(RenderDevice* rd) { if (changed) { changed=false; Vector3 renderSize = size.getValue()/2; glNewList(glList, GL_COMPILE); renderShape(this->shape.getValue(), renderSize, color.getValue()); renderSurface(TOP, this->top.getValue(), renderSize, this->controller.getValue(), color.getValue()); renderSurface(FRONT, this->front.getValue(), renderSize, this->controller.getValue(), color.getValue()); renderSurface(RIGHT, this->right.getValue(), renderSize, this->controller.getValue(), color.getValue()); renderSurface(BACK, this->back.getValue(), renderSize, this->controller.getValue(), color.getValue()); renderSurface(LEFT, this->left.getValue(), renderSize, this->controller.getValue(), color.getValue()); renderSurface(BOTTOM, this->bottom.getValue(), renderSize, this->controller.getValue(), color.getValue()); glEndList(); } rd->setObjectToWorldMatrix(cFrame.getValue()); glCallList(glList); postRender(rd); } PartInstance::~PartInstance(void) { glDeleteLists(glList, 1); /* // Causes some weird ODE error // Someone, please look into this dBodyDestroy(physBody); for (int i = 0; i < 3; i++) { if (physGeom[i] != NULL) dGeomDestroy(physGeom[i]); } */ } void PartInstance::onTouch() { if(getParentDataModel() == NULL) return; if(singleShot && _touchedOnce) return; if(singleShot && !_touchedOnce) _touchedOnce = true; getParentDataModel()->getLevel()->score += changeScore.getValue(); getParentDataModel()->getLevel()->timer += changeTimer.getValue(); switch(onTouchAction.getValue()) { case Enum::ActionType::Nothing: break; case Enum::ActionType::Pause: break; case Enum::ActionType::Lose: getParentDataModel()->getLevel()->loseCondition(); break; case Enum::ActionType::Draw: break; case Enum::ActionType::Win: getParentDataModel()->getLevel()->winCondition(); break; } //TODO implement SoundService /* SoundService* sndService = getParentDataModel()->getSoundService(); switch(OnTouchSound) { case Enum::Sound::NoSound: break; case Enum::Sound::Victory: sndService->playSound(sndService->findFirstChild("Victory")); break; case Enum::Sound::Boing: sndService->playSound(sndService->findFirstChild("Boing")); break; case Enum::Sound::Break: sndService->playSound(sndService->findFirstChild("Break")); break; case Enum::Sound::Snap: sndService->playSound(sndService->findFirstChild("Snap")); break; case Enum::Sound::Bomb: sndService->playSound(sndService->findFirstChild("Bomb")); break; case Enum::Sound::Splat: sndService->playSound(sndService->findFirstChild("Splat")); break; case Enum::Sound::Page: sndService->playSound(sndService->findFirstChild("Page")); break; case Enum::Sound::Ping: sndService->playSound(sndService->findFirstChild("Ping")); break; case Enum::Sound::Swoosh: sndService->playSound(sndService->findFirstChild("Swoosh")); break; case Enum::Sound::Click: sndService->playSound(sndService->findFirstChild("Click")); break; case Enum::Sound::Clock: sndService->playSound(sndService->findFirstChild("Clock")); break; case Enum::Sound::Step: sndService->playSound(sndService->findFirstChild("Step")); break; case Enum::Sound::StepOn: sndService->playSound(sndService->findFirstChild("StepOn")); break; }*/ }