Compare commits

...

2 commits

6 changed files with 48 additions and 13 deletions

View file

@ -29,22 +29,23 @@ Workspace::~Workspace() {
PhysicsEventListener::PhysicsEventListener(Workspace* parent) : workspace(parent) {}
void PhysicsEventListener::onContact(const rp::CollisionCallback::CallbackData& data) {
workspace->contactQueueLock.lock();
for (size_t i = 0; i < data.getNbContactPairs(); i++) {
auto pair = data.getContactPair(i);
auto type = pair.getEventType();
if (type == rp::CollisionCallback::ContactPair::EventType::ContactStay) continue;
auto part0 = reinterpret_cast<Part*>(pair.getBody1()->getUserData())->shared<Part>();
auto part1 = reinterpret_cast<Part*>(pair.getBody2()->getUserData())->shared<Part>();
if (type == reactphysics3d::CollisionCallback::ContactPair::EventType::ContactStay)
continue;
if (type == reactphysics3d::CollisionCallback::ContactPair::EventType::ContactStart) {
part0->Touched->Fire({ (Variant)InstanceRef(part1) });
part1->Touched->Fire({ (Variant)InstanceRef(part0) });
} else if (type == reactphysics3d::CollisionCallback::ContactPair::EventType::ContactExit) {
part0->TouchEnded->Fire({ (Variant)InstanceRef(part1) });
part1->TouchEnded->Fire({ (Variant)InstanceRef(part0) });
}
ContactItem contact;
contact.part0 = reinterpret_cast<Part*>(pair.getBody1()->getUserData())->shared<Part>();
contact.part1 = reinterpret_cast<Part*>(pair.getBody2()->getUserData())->shared<Part>();
contact.action = type == reactphysics3d::CollisionCallback::ContactPair::EventType::ContactStart ? ContactItem::CONTACTITEM_TOUCHED : ContactItem::CONTACTITEM_TOUCHENDED;
workspace->contactQueue.push(contact);
}
workspace->contactQueueLock.unlock();
}
void PhysicsEventListener::onTrigger(const rp::OverlapCallback::CallbackData& data) {
@ -143,6 +144,22 @@ void Workspace::updatePartPhysics(std::shared_ptr<Part> part) {
part->rigidBody->setUserData(&*part);
}
void Workspace::ProcessContactEvents() {
contactQueueLock.lock();
while (!contactQueue.empty()) {
ContactItem& contact = contactQueue.front();
contactQueue.pop();
if (contact.action == ContactItem::CONTACTITEM_TOUCHED) {
contact.part0->Touched->Fire({ (Variant)InstanceRef(contact.part1) });
contact.part1->Touched->Fire({ (Variant)InstanceRef(contact.part0) });
} else if (contact.action == ContactItem::CONTACTITEM_TOUCHENDED) {
contact.part0->TouchEnded->Fire({ (Variant)InstanceRef(contact.part1) });
contact.part1->TouchEnded->Fire({ (Variant)InstanceRef(contact.part0) });
}
}
contactQueueLock.unlock();
}
void Workspace::SyncPartPhysics(std::shared_ptr<Part> part) {
if (globalPhysicsLock.try_lock()) {
updatePartPhysics(part);

View file

@ -7,6 +7,7 @@
#include <list>
#include <memory>
#include <mutex>
#include <queue>
#include <reactphysics3d/body/RigidBody.h>
#include <reactphysics3d/engine/EventListener.h>
#include <reactphysics3d/engine/PhysicsCommon.h>
@ -52,6 +53,15 @@ struct QueueItem {
} action;
};
struct ContactItem {
std::shared_ptr<Part> part0;
std::shared_ptr<Part> part1;
enum {
CONTACTITEM_TOUCHED,
CONTACTITEM_TOUCHENDED,
} action;
};
class Workspace;
class PhysicsEventListener : public rp::EventListener {
friend Workspace;
@ -66,8 +76,12 @@ class PhysicsEventListener : public rp::EventListener {
class DEF_INST_SERVICE_(explorer_icon="workspace") Workspace : public Service {
AUTOGEN_PREAMBLE
friend PhysicsEventListener;
std::list<std::shared_ptr<Part>> simulatedBodies;
std::list<QueueItem> bodyQueue;
std::queue<ContactItem> contactQueue;
std::mutex contactQueueLock;
rp::PhysicsWorld* physicsWorld;
static rp::PhysicsCommon* physicsCommon;
PhysicsEventListener physicsEventListener;
@ -97,6 +111,7 @@ public:
rp::Joint* CreateJoint(const rp::JointInfo& jointInfo);
void DestroyJoint(rp::Joint* joint);
void ProcessContactEvents();
void PhysicsStep(float deltaTime);
std::optional<const RaycastResult> CastRayNearest(glm::vec3 point, glm::vec3 rotation, float maxLength, std::optional<RaycastFilter> filter = std::nullopt, unsigned short categoryMaskBits = 0xFFFF);
};

View file

@ -194,12 +194,12 @@ void drawText(std::shared_ptr<Font> font, std::string text, float x, float y, fl
glBindTexture(GL_TEXTURE_2D, 0);
}
float calcTextWidth(std::shared_ptr<Font> font, std::string text, float scale) {
float calcTextWidth(std::shared_ptr<Font> font, std::string text, float scale, bool stroke) {
float x = 0;
// iterate through all characters
for (size_t i = 0; i < text.size(); i++) {
unsigned char c = text[i];
Character ch = font->characters[c];
Character ch = stroke ? font->strokeCharacters[c] : font->characters[c];
x += (ch.advance >> 6) * scale;
}

View file

@ -23,4 +23,4 @@ void fontInit();
void fontFinish();
std::shared_ptr<Font> loadFont(std::string fontName);
void drawText(std::shared_ptr<Font> font, std::string text, float x, float y, float scale=1.f, glm::vec3 color = glm::vec3(1,1,1), bool drawStroke = false);
float calcTextWidth(std::shared_ptr<Font> font, std::string text, float scale = 1.f);
float calcTextWidth(std::shared_ptr<Font> font, std::string text, float scale = 1.f, bool stroke = false);

View file

@ -673,8 +673,10 @@ void renderMessages() {
// Don't draw if text is empty
if (message->text == "") continue;
float strokedTextWidth = calcTextWidth(sansSerif, message->text, true);
drawRect(0, 0, viewportWidth, viewportHeight, glm::vec4(0.5));
drawText(sansSerif, message->text, ((float)viewportWidth - textWidth) / 2, ((float)viewportHeight - sansSerif->height) / 2);
drawText(sansSerif, message->text, ((float)viewportWidth - textWidth) / 2, ((float)viewportHeight - sansSerif->height) / 2, 1.f, glm::vec3(0), true);
drawText(sansSerif, message->text, ((float)viewportWidth - strokedTextWidth) / 2, ((float)viewportHeight - sansSerif->height) / 2, 1.f, glm::vec3(1), false);
}
}
}

View file

@ -140,6 +140,7 @@ void PlaceDocument::timerEvent(QTimerEvent* evt) {
placeWidget->repaint();
placeWidget->updateCycle();
gDataModel->GetService<ScriptContext>()->RunSleepingThreads();
gDataModel->GetService<Workspace>()->ProcessContactEvents();
}