Better boat handling
This commit is contained in:
BIN
assets/blender/vehicles/boat.blend
(Stored with Git LFS)
BIN
assets/blender/vehicles/boat.blend
(Stored with Git LFS)
Binary file not shown.
@@ -413,9 +413,34 @@ local vehicles = {}
|
||||
local player_vehicles = {}
|
||||
local actuators = {}
|
||||
|
||||
|
||||
function create_vehicle(vtype, passengers, position)
|
||||
local vehicle = {}
|
||||
vehicle.id = ecs_vehicle_set(vtype, position[1], position[2], position[3], position[4])
|
||||
vehicle.passengers = {}
|
||||
vehicle.actuators = {}
|
||||
vehicle.add_passenger = function(this, data)
|
||||
local npc_id = ecs_npc_set(data.model, data.position[1], data.position[2], data.position[3], data.position[4])
|
||||
table.insert(this.passengers, npc_id)
|
||||
ecs_character("physics-control", npc_id, false)
|
||||
ecs_character("params-set", npc_id, "gravity", false)
|
||||
ecs_character("params-set", npc_id, "buoyancy", false)
|
||||
ecs_set_slot(this.id, npc_id, data.slot)
|
||||
ecs_character("set-actuator", npc_id, data.animation)
|
||||
end
|
||||
for i, v in ipairs(passengers) do
|
||||
vehicle:add_passenger(v)
|
||||
end
|
||||
return vehicle
|
||||
end
|
||||
function create_boat()
|
||||
local boat = {}
|
||||
boat.boat_id = ecs_vehicle_set("boat", 0, 0, -10, 1.75)
|
||||
local boat = create_vehicle("boat", {
|
||||
model = "normal-female.glb",
|
||||
position = {0, 2, -10, 1.75},
|
||||
slot = "captain_seat",
|
||||
animation = "sitting"}, {0, 0, -10, 1.75})
|
||||
--[[
|
||||
boat.id = ecs_vehicle_set("boat", 0, 0, -10, 1.75)
|
||||
local npc_id = ecs_npc_set("normal-female.glb", 0, 2, -10, 1.75)
|
||||
boat.passengers = {npc_id}
|
||||
ecs_character("physics-control", npc_id, false)
|
||||
@@ -426,6 +451,7 @@ function create_boat()
|
||||
ecs_character("set-actuator", npc_id, "sitting")
|
||||
-- ecs_set_animation_state(npc_id, "main", "actuator", true)
|
||||
-- ecs_set_animation_state(npc_id, "actuator-state", "sitting", true)
|
||||
]]--
|
||||
boat.event = function(this, event, event_data)
|
||||
print("boat: ", event)
|
||||
if event == "boat_control_enter" then
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
#include "Components.h"
|
||||
#include "GameData.h"
|
||||
#include "PhysicsModule.h"
|
||||
#include "EventModule.h"
|
||||
#include "EventTriggerModule.h"
|
||||
#include "CharacterModule.h"
|
||||
#include "BoatModule.h"
|
||||
|
||||
namespace ECS
|
||||
@@ -17,13 +20,19 @@ BoatModule::BoatModule(flecs::world &ecs)
|
||||
ecs.component<BoatBase>();
|
||||
ecs.component<BoatType>();
|
||||
ecs.component<SpawnBoat>();
|
||||
ecs.import <EventModule>();
|
||||
ecs.import <EventTriggerModule>();
|
||||
ecs.import <CharacterModule>();
|
||||
ecs.observer<const EngineData, const BoatType>("CreateBoat")
|
||||
.event(flecs::OnSet)
|
||||
.without<BoatBase>()
|
||||
.without<SpawnBoat>()
|
||||
.each([&](flecs::entity e, const EngineData &eng,
|
||||
const BoatType &type) { e.add<SpawnBoat>(); });
|
||||
ecs.system<const EngineData, const BoatType>("CreateBoat")
|
||||
const BoatType &type) {
|
||||
e.add<SpawnBoat>();
|
||||
e.set<EventData>({});
|
||||
});
|
||||
ecs.system<const EngineData, const BoatType>("CreateBoatS")
|
||||
.kind(flecs::OnUpdate)
|
||||
.without<BoatBase>()
|
||||
.with<WaterReady>()
|
||||
@@ -115,6 +124,165 @@ BoatModule::BoatModule(flecs::world &ecs)
|
||||
// ECS::modified<ECS::EngineData>();
|
||||
// e.modified<BoatBody>();
|
||||
});
|
||||
ecs.observer<const BoatBase, EventData>("HandleBoatEvents")
|
||||
.event(flecs::OnSet)
|
||||
.each([](flecs::entity e, const BoatBase &boat,
|
||||
EventData &evt) {
|
||||
for (auto ev : evt.events) {
|
||||
std::cout << "event: " << ev.event << " "
|
||||
<< ev.sender.name() << " "
|
||||
<< ev.e1.name() << " " << ev.e2.name()
|
||||
<< std::endl;
|
||||
if (ev.event == "actuator_created") {
|
||||
continue;
|
||||
} else if (ev.event == "actuator_enter") {
|
||||
if (ev.sender.has<EventTrigger>()) {
|
||||
if (ev.e2.has<Player>())
|
||||
PhysicsModule::
|
||||
controlPhysics(
|
||||
ev.e2,
|
||||
false);
|
||||
const EventTrigger &trigger =
|
||||
ev.sender.get<
|
||||
EventTrigger>();
|
||||
Ogre::SceneNode *node =
|
||||
trigger.node;
|
||||
Ogre::Any animationAny =
|
||||
node->getUserObjectBindings()
|
||||
.getUserAny(
|
||||
"trigger_animation");
|
||||
if (animationAny.has_value()) {
|
||||
Ogre::String animation =
|
||||
Ogre::any_cast<
|
||||
Ogre::String>(
|
||||
animationAny);
|
||||
ev.e2.set<
|
||||
CharacterVelocity>(
|
||||
{ { 0, 0, 0 },
|
||||
{ 0, 0,
|
||||
0 } });
|
||||
if (animation.length() >
|
||||
0)
|
||||
ev.e2.set<
|
||||
CharacterInActuator>(
|
||||
{ animation,
|
||||
{ 0,
|
||||
0,
|
||||
0 } });
|
||||
else
|
||||
ev.e2.remove<
|
||||
CharacterInActuator>();
|
||||
}
|
||||
Ogre::SceneNode *target_node =
|
||||
nullptr;
|
||||
Ogre::Any targetAny =
|
||||
node->getUserObjectBindings()
|
||||
.getUserAny(
|
||||
"target");
|
||||
if (targetAny.has_value()) {
|
||||
OgreAssert(
|
||||
targetAny
|
||||
.has_value(),
|
||||
"need target");
|
||||
target_node = Ogre::any_cast<
|
||||
Ogre::SceneNode
|
||||
*>(
|
||||
targetAny);
|
||||
Ogre::Vector3 position =
|
||||
target_node
|
||||
->_getDerivedPosition();
|
||||
Ogre::Quaternion orientation =
|
||||
target_node
|
||||
->_getDerivedOrientation();
|
||||
if (ev.e2.has<
|
||||
CharacterBase>()) {
|
||||
ev.e2.get_mut<
|
||||
CharacterBase>()
|
||||
.mBodyNode
|
||||
->_setDerivedPosition(
|
||||
position);
|
||||
ev.e2.get_mut<
|
||||
CharacterBase>()
|
||||
.mBodyNode
|
||||
->_setDerivedOrientation(
|
||||
orientation);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ev.event == "actuator_forward") {
|
||||
/* */
|
||||
ev.e2.set<CharacterInActuator>(
|
||||
{ "swimming-edge-climb",
|
||||
{ 0, 0, 0 } });
|
||||
} else if (ev.event == "actuator_backward") {
|
||||
/* */
|
||||
} else if (ev.event ==
|
||||
"animation:swimming-edge-climb:end") {
|
||||
ev.e2.remove<CharacterInActuator>();
|
||||
PhysicsModule::controlPhysics(ev.e2,
|
||||
true);
|
||||
ev.e2.remove<InTrigger>(ev.e1);
|
||||
ev.e1.remove<TriggeredBy>(ev.e2);
|
||||
ev.e2.add<CharacterGravity>();
|
||||
ev.e2.add<CharacterBuoyancy>();
|
||||
} else if (ev.event == "boat_control_enter") {
|
||||
Ogre::SceneNode *captainSeat = nullptr;
|
||||
std::vector<Ogre::Node *> children =
|
||||
boat.mNode->getChildren();
|
||||
for (auto child : children) {
|
||||
Ogre::Any nameAny =
|
||||
child->getUserObjectBindings()
|
||||
.getUserAny(
|
||||
"name");
|
||||
if (nameAny.has_value()) {
|
||||
Ogre::String name =
|
||||
Ogre::any_cast<
|
||||
Ogre::String>(
|
||||
nameAny);
|
||||
std::cout << "name: "
|
||||
<< name
|
||||
<< std::endl;
|
||||
if (name ==
|
||||
"captain_seat") {
|
||||
captainSeat = static_cast<
|
||||
Ogre::SceneNode
|
||||
*>(
|
||||
child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
OgreAssert(captainSeat, "seats");
|
||||
PhysicsModule::controlPhysics(ev.e2,
|
||||
false);
|
||||
ev.e2.set<CharacterVelocity>(
|
||||
{ { 0, 0, 0 }, { 0, 0, 0 } });
|
||||
ev.e2.set<CharacterInActuator>(
|
||||
{ "sitting", { 0, 0, 0 } });
|
||||
Ogre::Vector3 position =
|
||||
captainSeat
|
||||
->_getDerivedPosition();
|
||||
Ogre::Quaternion orientation =
|
||||
captainSeat
|
||||
->_getDerivedOrientation();
|
||||
if (ev.e2.has<CharacterBase>()) {
|
||||
ev.e2.get_mut<CharacterBase>()
|
||||
.mBodyNode
|
||||
->_setDerivedPosition(
|
||||
position);
|
||||
ev.e2.get_mut<CharacterBase>()
|
||||
.mBodyNode
|
||||
->_setDerivedOrientation(
|
||||
orientation);
|
||||
}
|
||||
} else if (ev.event == "boat_control_exit") {
|
||||
} else if (ev.event == "actuator_exit") {
|
||||
/* */
|
||||
} else
|
||||
OgreAssert(false, "event");
|
||||
}
|
||||
evt.events.clear();
|
||||
});
|
||||
#if 0
|
||||
ecs.system<const EngineData, BoatType, Body2Entity>("CreateBoat")
|
||||
.kind(flecs::OnUpdate)
|
||||
|
||||
@@ -3,7 +3,7 @@ set(CMAKE_CXX_STANDARD 17)
|
||||
find_package(OGRE REQUIRED COMPONENTS Bites Bullet Paging Terrain Overlay CONFIG)
|
||||
find_package(Bullet REQUIRED)
|
||||
add_library(GameData STATIC GameData.cpp CharacterModule.cpp WaterModule.cpp SunModule.cpp TerrainModule.cpp GUIModule.cpp LuaData.cpp WorldMapModule.cpp
|
||||
BoatModule.cpp EventTriggerModule.cpp CharacterAnimationModule.cpp PhysicsModule.cpp SmartObject.cpp SlotsModule.cpp goap.cpp)
|
||||
BoatModule.cpp EventTriggerModule.cpp CharacterAnimationModule.cpp PhysicsModule.cpp EventModule.cpp SmartObject.cpp SlotsModule.cpp goap.cpp)
|
||||
target_link_libraries(GameData PUBLIC lua flecs::flecs_static OgreMain OgreBites
|
||||
OgrePaging OgreTerrain OgreOverlay
|
||||
PRIVATE sceneloader world-build physics)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "CharacterModule.h"
|
||||
#include "PhysicsModule.h"
|
||||
#include "CharacterAnimationModule.h"
|
||||
#include "EventModule.h"
|
||||
#include "world-build.h"
|
||||
namespace ECS
|
||||
{
|
||||
@@ -11,12 +12,14 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<CharacterAnimationModule>();
|
||||
ecs.component<AnimationControl>();
|
||||
ecs.import <EventModule>();
|
||||
ecs.system<const CharacterBase, AnimationControl>("HandleAnimations")
|
||||
.kind(flecs::OnUpdate)
|
||||
.each([this](flecs::entity e, const CharacterBase &ch,
|
||||
AnimationControl &anim) {
|
||||
if (!anim.configured && ch.mSkeleton) {
|
||||
int i, j;
|
||||
e.set<EventData>({});
|
||||
ch.mSkeleton->setBlendMode(
|
||||
Ogre::ANIMBLEND_CUMULATIVE);
|
||||
Ogre::String animNames[] = {
|
||||
@@ -504,26 +507,29 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
|
||||
if (Ogre::Math::Abs(input.motion.z -
|
||||
act.prevMotion.z) >
|
||||
0.001f) {
|
||||
if (input.motion.z < 0)
|
||||
ECS::get<LuaBase>()
|
||||
.mLua
|
||||
->call_handler(
|
||||
"actuator_forward",
|
||||
trig,
|
||||
e);
|
||||
if (input.motion.z > 0)
|
||||
ECS::get_mut<LuaBase>()
|
||||
.mLua
|
||||
->call_handler(
|
||||
"actuator_backward",
|
||||
trig,
|
||||
e);
|
||||
if (input.motion.z < 0) {
|
||||
trig.get_mut<EventData>()
|
||||
.add(e,
|
||||
"actuator_forward",
|
||||
trig, e);
|
||||
trig.modified<
|
||||
EventData>();
|
||||
}
|
||||
if (input.motion.z > 0) {
|
||||
trig.get_mut<EventData>()
|
||||
.add(e,
|
||||
"actuator_backward",
|
||||
trig, e);
|
||||
trig.modified<
|
||||
EventData>();
|
||||
}
|
||||
}
|
||||
if (input.act_pressed) {
|
||||
trig.get_mut<EventData>().add(
|
||||
e, "actuator_action",
|
||||
trig, e);
|
||||
trig.modified<EventData>();
|
||||
}
|
||||
if (input.act_pressed)
|
||||
ECS::get_mut<LuaBase>()
|
||||
.mLua->call_handler(
|
||||
"actuator_action",
|
||||
trig, e);
|
||||
// ECS::get_mut<LuaData>().call_handler(
|
||||
// "actuator_update", trig, e);
|
||||
trigger_event = true;
|
||||
@@ -532,26 +538,25 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
|
||||
if (Ogre::Math::Abs(input.motion.z -
|
||||
act.prevMotion.z) >
|
||||
0.001f) {
|
||||
if (input.motion.z < 0)
|
||||
ECS::get<LuaBase>()
|
||||
.mLua
|
||||
->call_handler(
|
||||
"_in_actuator_forward",
|
||||
e, e);
|
||||
if (input.motion.z > 0)
|
||||
ECS::get_mut<LuaBase>()
|
||||
.mLua
|
||||
->call_handler(
|
||||
"_in_actuator_backward",
|
||||
e, e);
|
||||
}
|
||||
if (input.act_pressed)
|
||||
ECS::get_mut<LuaBase>()
|
||||
.mLua->call_handler(
|
||||
"_in_actuator_action",
|
||||
if (input.motion.z < 0) {
|
||||
e.get_mut<EventData>().add(
|
||||
e,
|
||||
"_in_actuator_forward",
|
||||
e, e);
|
||||
// ECS::get_mut<LuaData>().call_handler(
|
||||
// "actuator_update", trig, e);
|
||||
}
|
||||
if (input.motion.z > 0) {
|
||||
e.get_mut<EventData>().add(
|
||||
e,
|
||||
"_in_actuator_backward",
|
||||
e, e);
|
||||
}
|
||||
}
|
||||
if (input.act_pressed) {
|
||||
e.get_mut<EventData>().add(
|
||||
e,
|
||||
"_in_actuator_action",
|
||||
e, e);
|
||||
}
|
||||
}
|
||||
act.prevMotion.x = input.motion.x;
|
||||
act.prevMotion.y = input.motion.y;
|
||||
@@ -569,6 +574,25 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
|
||||
#endif
|
||||
act.prevMotion = input.motion;
|
||||
});
|
||||
ecs.system<EventData>("UpdateEvents")
|
||||
.kind(flecs::OnUpdate)
|
||||
.with<Character>()
|
||||
.each([](flecs::entity e, EventData &evt) {
|
||||
for (auto ev : evt.events) {
|
||||
std::cout << "character event: " << ev.event
|
||||
<< std::endl;
|
||||
/* parse character events */
|
||||
e.each<InTrigger>([&](flecs::entity trig) {
|
||||
/* if triggered, dispatch events to trigger */
|
||||
trig.get_mut<EventData>().add(
|
||||
ev.sender, ev.event,
|
||||
trig, // it is easier this way to identify trigger entity
|
||||
ev.e2);
|
||||
});
|
||||
}
|
||||
evt.events.clear();
|
||||
});
|
||||
|
||||
#ifdef VDEBUG
|
||||
ecs.system<const CharacterBase>("CharacterGravityStatus")
|
||||
.kind(flecs::OnUpdate)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "GameData.h"
|
||||
#include "CharacterModule.h"
|
||||
#include "LuaData.h"
|
||||
#include "EventModule.h"
|
||||
namespace ECS
|
||||
{
|
||||
class RootMotionListener : public Ogre::NodeAnimationTrack::Listener {
|
||||
@@ -713,9 +714,8 @@ struct AnimationSystem : AnimationNode {
|
||||
Ogre::String event;
|
||||
void operator()(const AnimationTrigger *trigger)
|
||||
{
|
||||
ECS::get_mut<LuaBase>()
|
||||
.mLua->call_handler(event, ent,
|
||||
ent);
|
||||
ent.get_mut<EventData>().add(ent, event,
|
||||
ent, ent);
|
||||
}
|
||||
EventSubscriber(flecs::entity e,
|
||||
const Ogre::String &event)
|
||||
|
||||
@@ -546,23 +546,6 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
});
|
||||
#endif
|
||||
#if 0
|
||||
ecs.system<const EngineData, const CharacterBody>("UpdatePhysics")
|
||||
.kind(flecs::OnUpdate)
|
||||
.with<CharacterUpdatePhysicsState>()
|
||||
.write<CharacterUpdatePhysicsState>()
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const CharacterBody &body) {
|
||||
#if 0
|
||||
if (e.has<CharacterDisablePhysics>()) {
|
||||
eng.mWorld->getBtWorld()->removeAction(
|
||||
body.mController);
|
||||
} else {
|
||||
eng.mWorld->getBtWorld()->addAction(
|
||||
body.mController);
|
||||
}
|
||||
#endif
|
||||
e.remove<CharacterUpdatePhysicsState>();
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
13
src/gamedata/EventModule.cpp
Normal file
13
src/gamedata/EventModule.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "EventModule.h"
|
||||
namespace ECS
|
||||
{
|
||||
EventModule::EventModule(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<EventModule>();
|
||||
ecs.component<EventData>();
|
||||
}
|
||||
void EventModule::send_event(flecs::entity from, const Ogre::String &event,
|
||||
flecs::entity to)
|
||||
{
|
||||
}
|
||||
}
|
||||
29
src/gamedata/EventModule.h
Normal file
29
src/gamedata/EventModule.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef _EVENT_MODULE_H_
|
||||
#define _EVENT_MODULE_H_
|
||||
#include <flecs.h>
|
||||
#include <Ogre.h>
|
||||
namespace ECS
|
||||
{
|
||||
struct EventData {
|
||||
struct EventArgs {
|
||||
int type;
|
||||
};
|
||||
struct Event {
|
||||
flecs::entity sender;
|
||||
Ogre::String event;
|
||||
flecs::entity e1, e2;
|
||||
};
|
||||
std::list<Event> events;
|
||||
void add(flecs::entity sender, const Ogre::String &event,
|
||||
flecs::entity e1, flecs::entity e2)
|
||||
{
|
||||
events.push_back({ sender, event, e1, e2 });
|
||||
}
|
||||
};
|
||||
struct EventModule {
|
||||
EventModule(flecs::world &ecs);
|
||||
void send_event(flecs::entity from, const Ogre::String &event,
|
||||
flecs::entity to);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -1,11 +0,0 @@
|
||||
#ifndef EVENT_SYSTEM_H_
|
||||
#define EVENT_SYSTEM_H_
|
||||
struct EventSystem {
|
||||
struct CommonEvent {
|
||||
int event_type;
|
||||
};
|
||||
void send_event(const EventSystem &event)
|
||||
{
|
||||
}
|
||||
};
|
||||
#endif
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "Components.h"
|
||||
#include "GameData.h"
|
||||
#include "LuaData.h"
|
||||
#include "EventModule.h"
|
||||
#include "EventTriggerModule.h"
|
||||
|
||||
struct TriggerBody {
|
||||
@@ -68,13 +69,40 @@ ECS::EventTriggerModule::EventTriggerModule(flecs::world &ecs)
|
||||
ecs.module<EventTriggerModule>();
|
||||
ecs.component<EventTrigger>();
|
||||
ecs.component<EventTriggerData>();
|
||||
ecs.component<InTrigger>();
|
||||
ecs.component<TriggeredBy>();
|
||||
ecs.import <EventModule>();
|
||||
ecs.import <LuaModule>();
|
||||
ecs.observer<const EngineData, const EventTrigger>("CreateTrigger")
|
||||
.event(flecs::OnSet)
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const EventTrigger &trigger) {
|
||||
e.set<EventTriggerData>({});
|
||||
ECS::get<LuaBase>().mLua->call_handler(
|
||||
"actuator_created", e, e);
|
||||
e.set<EventData>({});
|
||||
});
|
||||
ecs.observer<const EventTrigger, EventData>("CreateTriggerEvent")
|
||||
.event(flecs::OnSet)
|
||||
.each([](flecs::entity e, const EventTrigger &trigger,
|
||||
EventData &evt) {
|
||||
evt.add(e, "actuator_created", e, e);
|
||||
});
|
||||
ecs.system<const EventTrigger, EventData>("HandleEventSystem")
|
||||
.kind(flecs::OnUpdate)
|
||||
.each([](flecs::entity e, const EventTrigger &trigger,
|
||||
EventData &evt) {
|
||||
if (e.parent().is_valid() &&
|
||||
e.parent().has<EventData>()) {
|
||||
bool added = false;
|
||||
for (auto ev : evt.events) {
|
||||
e.parent().get_mut<EventData>().add(
|
||||
ev.sender, ev.event, ev.e1,
|
||||
ev.e2);
|
||||
added = true;
|
||||
}
|
||||
evt.events.clear();
|
||||
if (added)
|
||||
e.parent().modified<EventData>();
|
||||
}
|
||||
});
|
||||
#if 0
|
||||
ecs.component<EventTriggerData>();
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "EventTriggerModule.h"
|
||||
#include "CharacterAnimationModule.h"
|
||||
#include "PhysicsModule.h"
|
||||
#include "EventModule.h"
|
||||
#include "world-build.h"
|
||||
|
||||
namespace ECS
|
||||
@@ -26,6 +27,7 @@ void setup_minimal()
|
||||
ecs.component<Input>().add(flecs::Singleton);
|
||||
ecs.component<Camera>().add(flecs::Singleton);
|
||||
ecs.import <GameWorldModule>();
|
||||
ecs.import <EventModule>();
|
||||
ecs.component<InWater>();
|
||||
ecs.component<WaterReady>().add(flecs::Singleton);
|
||||
ecs.component<WaterAlmostReady>().add(flecs::Singleton);
|
||||
|
||||
@@ -415,6 +415,15 @@ LuaData::LuaData()
|
||||
return 1;
|
||||
});
|
||||
lua_setglobal(L, "ecs_character_trigger");
|
||||
lua_pushcfunction(L, [](lua_State *L) -> int {
|
||||
luaL_checktype(L, 1, LUA_TNUMBER); // object
|
||||
int object = lua_tointeger(L, 1);
|
||||
flecs::entity object_e = idmap.get_entity(object);
|
||||
flecs::entity parent_e = object_e.parent();
|
||||
lua_pushinteger(L, idmap.add_entity(parent_e));
|
||||
return 1;
|
||||
});
|
||||
lua_setglobal(L, "ecs_parent");
|
||||
lua_pushcfunction(L, [](lua_State *L) -> int {
|
||||
OgreAssert(lua_gettop(L) == 7, "bad parameters");
|
||||
luaL_checktype(L, 1, LUA_TNUMBER); // parent
|
||||
@@ -551,10 +560,9 @@ LuaData::LuaData()
|
||||
int object = lua_tointeger(L, 2);
|
||||
flecs::entity object_e = idmap.get_entity(object);
|
||||
bool enable = lua_toboolean(L, 3);
|
||||
if (enable)
|
||||
object_e.remove<CharacterDisablePhysics>();
|
||||
else
|
||||
object_e.add<CharacterDisablePhysics>();
|
||||
OgreAssert(object_e.has<CharacterBase>(),
|
||||
"Not a character");
|
||||
PhysicsModule::controlPhysics(object_e, enable);
|
||||
object_e.add<CharacterUpdatePhysicsState>();
|
||||
return 0;
|
||||
} else if (command == "is-player") {
|
||||
@@ -659,8 +667,7 @@ LuaData::LuaData()
|
||||
Ogre::String slot = lua_tostring(L, 3);
|
||||
flecs::entity parent_e = idmap.get_entity(parent);
|
||||
flecs::entity object_e = idmap.get_entity(object);
|
||||
if (!object_e.has<CharacterDisablePhysics>())
|
||||
object_e.add<CharacterDisablePhysics>();
|
||||
PhysicsModule::controlPhysics(object_e, false);
|
||||
object_e.set<ParentSlot>({ parent_e, slot });
|
||||
return 0;
|
||||
});
|
||||
@@ -840,7 +847,11 @@ LuaModule::LuaModule(flecs::world &ecs)
|
||||
lua.startup_called = false;
|
||||
})
|
||||
.add(flecs::Singleton);
|
||||
ecs.add<LuaBase>();
|
||||
ecs.component<LuaEvent>().add(flecs::Singleton);
|
||||
if (!ecs.has<LuaBase>())
|
||||
ecs.add<LuaBase>();
|
||||
if (!ecs.has<LuaEvent>())
|
||||
ecs.set<LuaEvent>({});
|
||||
|
||||
ecs.system<const EngineData, LuaBase>("LuaUpdate")
|
||||
.kind(flecs::OnUpdate)
|
||||
@@ -888,5 +899,14 @@ LuaModule::LuaModule(flecs::world &ecs)
|
||||
trigger.parent = parentNode;
|
||||
e.modified<EventTrigger>();
|
||||
});
|
||||
ecs.system<LuaBase, LuaEvent>("HandleLuaEvents")
|
||||
.kind(flecs::OnUpdate)
|
||||
.each([](LuaBase &base, LuaEvent &evt) {
|
||||
while (!evt.events.empty()) {
|
||||
LuaEvent::Event &ev = evt.events.front();
|
||||
base.mLua->call_handler(ev.event, ev.e1, ev.e2);
|
||||
evt.events.pop_front();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -27,5 +27,16 @@ struct LuaBase {
|
||||
struct LuaModule {
|
||||
LuaModule(flecs::world &ecs);
|
||||
};
|
||||
struct LuaEvent {
|
||||
struct Event {
|
||||
Ogre::String event;
|
||||
flecs::entity e1, e2;
|
||||
};
|
||||
std::list<Event> events;
|
||||
void add(const Ogre::String &event, flecs::entity e1, flecs::entity e2)
|
||||
{
|
||||
events.push_back({ event, e1, e2 });
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6,14 +6,17 @@
|
||||
#include <Jolt/Physics/Character/Character.h>
|
||||
#include <Jolt/Physics/Collision/BroadPhase/BroadPhase.h>
|
||||
#include <Jolt/Physics/Body/BodyLock.h>
|
||||
#include <Jolt/Physics/Collision/ContactListener.h>
|
||||
#include "Components.h"
|
||||
#include "GameData.h"
|
||||
#include "CharacterModule.h"
|
||||
#include "WaterModule.h"
|
||||
#include "BoatModule.h"
|
||||
#include "EventTriggerModule.h"
|
||||
#include "LuaData.h"
|
||||
#include "physics.h"
|
||||
#include "loader.h"
|
||||
#include "EventModule.h"
|
||||
#include "PhysicsModule.h"
|
||||
namespace ECS
|
||||
{
|
||||
@@ -28,10 +31,10 @@ struct WaterBody {
|
||||
struct TriggerBody {
|
||||
void *foo;
|
||||
};
|
||||
|
||||
PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<PhysicsModule>();
|
||||
ecs.import <EventModule>();
|
||||
ecs.import <EventTriggerModule>();
|
||||
ecs.import <BoatModule>();
|
||||
flecs::entity PhysicsPreUpdate =
|
||||
@@ -54,6 +57,7 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
ecs.component<TriggerBody>();
|
||||
ecs.component<CharacterVelocity>();
|
||||
ecs.component<WaterBody>().add(flecs::Singleton);
|
||||
ecs.component<CachedMass>();
|
||||
ecs.system<const EngineData, const Camera>("physics_init")
|
||||
.kind(PhysicsPreUpdate)
|
||||
.without<Physics>()
|
||||
@@ -184,6 +188,9 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
static_cast<JPH::Character *>(b.ch.get())
|
||||
->AddToPhysicsSystem(
|
||||
JPH::EActivation::Activate);
|
||||
e.set<JPH::BodyID>(
|
||||
static_cast<JPH::Character *>(b.ch.get())
|
||||
->GetBodyID());
|
||||
e.modified<CharacterBody>();
|
||||
});
|
||||
ecs.observer<const EngineData, const EventTrigger>(
|
||||
@@ -205,6 +212,83 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
// JoltPhysicsWrapper::getSingleton().setDebugDraw(true);
|
||||
JoltPhysicsWrapper::getSingleton().addBody(
|
||||
id, JPH::EActivation::Activate);
|
||||
JoltPhysicsWrapper::getSingleton().addContactListener(
|
||||
id,
|
||||
[](const JoltPhysics::ContactListener::
|
||||
ContactReport &report) -> void {
|
||||
flecs::entity trigger_e =
|
||||
ECS::get()
|
||||
.query_builder<
|
||||
const JPH::
|
||||
BodyID>()
|
||||
.with<EventTrigger>()
|
||||
.build()
|
||||
.find([&](const JPH::BodyID
|
||||
&id) {
|
||||
return id == report.id1 ||
|
||||
id == report.id2;
|
||||
});
|
||||
flecs::entity parent_e =
|
||||
trigger_e.parent();
|
||||
const JPH::BodyID &trigger_body =
|
||||
trigger_e.get<JPH::BodyID>();
|
||||
const JPH::BodyID &other_body =
|
||||
(trigger_body == report.id1) ?
|
||||
report.id2 :
|
||||
report.id1;
|
||||
flecs::entity other_e =
|
||||
ECS::get()
|
||||
.query_builder<
|
||||
const JPH::
|
||||
BodyID>()
|
||||
.without<EventTrigger>()
|
||||
.build()
|
||||
.find([&](const JPH::BodyID
|
||||
&id) {
|
||||
return id ==
|
||||
other_body;
|
||||
});
|
||||
if (!trigger_e.is_valid() ||
|
||||
!other_e.is_valid())
|
||||
return;
|
||||
if (parent_e.is_valid() &&
|
||||
parent_e == other_e)
|
||||
return;
|
||||
OgreAssert(
|
||||
trigger_e.is_valid(),
|
||||
"trigger entity is not valid");
|
||||
OgreAssert(other_e.is_valid(),
|
||||
"other entity is not valid");
|
||||
const EventTrigger &trg =
|
||||
trigger_e.get<EventTrigger>();
|
||||
if (report.entered) {
|
||||
trigger_e.get_mut<EventData>()
|
||||
.add(trigger_e,
|
||||
trg.event +
|
||||
"_enter",
|
||||
trigger_e,
|
||||
other_e);
|
||||
other_e.add<InTrigger>(
|
||||
trigger_e);
|
||||
trigger_e.add<TriggeredBy>(
|
||||
other_e);
|
||||
} else {
|
||||
trigger_e.get_mut<EventData>()
|
||||
.add(trigger_e,
|
||||
trg.event +
|
||||
"_exit",
|
||||
trigger_e,
|
||||
other_e);
|
||||
#if 0
|
||||
/* do not delete triggers until exit from actuator */
|
||||
other_e.remove<InTrigger>(
|
||||
trigger_e);
|
||||
trigger_e.remove<TriggeredBy>(
|
||||
other_e);
|
||||
#endif
|
||||
}
|
||||
ECS::modified<LuaEvent>();
|
||||
});
|
||||
});
|
||||
#if 0
|
||||
ecs.system<const EngineData, const EventTrigger, const JPH::BodyID>(
|
||||
@@ -260,6 +344,7 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
.with<WaterAlmostReady>()
|
||||
.each([this](const EngineData &eng, WaterBody &body) {
|
||||
const WaterSurface &water = ECS::get<WaterSurface>();
|
||||
body.inWater.clear();
|
||||
JoltPhysicsWrapper::getSingleton().broadphaseQuery(
|
||||
eng.delta,
|
||||
water.mWaterNode->_getDerivedPosition(),
|
||||
@@ -388,17 +473,18 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
JoltPhysicsWrapper::getSingleton().activate(id);
|
||||
});
|
||||
ecs.system<const EngineData, const BoatBase, const WaterBody,
|
||||
const JPH::BodyID>("update_water_boat_buoyancy")
|
||||
const JPH::BodyID, const CachedMass>(
|
||||
"update_water_boat_buoyancy")
|
||||
.kind(PhysicsPreUpdate)
|
||||
.with<TerrainReady>()
|
||||
.with<WaterReady>()
|
||||
.with<InWater>()
|
||||
.each([this](flecs::entity e, const EngineData &eng,
|
||||
const BoatBase &boat, const WaterBody &body,
|
||||
const JPH::BodyID &id) {
|
||||
const JPH::BodyID &id, const CachedMass &mass) {
|
||||
const WaterSurface &water = ECS::get<WaterSurface>();
|
||||
float b = 1.0f, drag = 0.5f, adrag = 0.5f;
|
||||
float level = 0.1f;
|
||||
float level = 0.25f;
|
||||
float my = JoltPhysicsWrapper::getSingleton()
|
||||
.getPosition(id)
|
||||
.y;
|
||||
@@ -411,8 +497,9 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
else if (my > level && myv > 0)
|
||||
b = 0.8f;
|
||||
#endif
|
||||
/* max = 2.7; min = 1.7 */
|
||||
if (my < level)
|
||||
b = 1.7f;
|
||||
b = 2.2f;
|
||||
else if (my > level)
|
||||
b = 0.9f;
|
||||
// std::cout << my << std::endl;
|
||||
@@ -420,6 +507,33 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
id, water.mWaterNode->_getDerivedPosition(),
|
||||
Ogre::Vector3::UNIT_Y, b, drag, adrag,
|
||||
Ogre::Vector3::ZERO, eng.delta);
|
||||
/* stabilisation */
|
||||
Ogre::Vector3 currentAngularVelocity =
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.getAngularVelocity(id);
|
||||
Ogre::Quaternion rotation =
|
||||
JoltPhysicsWrapper::getSingleton().getRotation(
|
||||
id);
|
||||
Ogre::Vector3 rotComp =
|
||||
rotation.Inverse() * Ogre::Vector3::UNIT_Y;
|
||||
rotComp.y = 0;
|
||||
if (Ogre::Math::Abs(rotComp.x) > 0.1f ||
|
||||
Ogre::Math::Abs(rotComp.z) > 0.1f) {
|
||||
Ogre::Vector3 localAngularVelocity =
|
||||
rotation.Inverse() *
|
||||
currentAngularVelocity;
|
||||
Ogre::Vector3 localAngularVelocityChange(
|
||||
-localAngularVelocity.x, 0,
|
||||
-localAngularVelocity.z);
|
||||
localAngularVelocityChange -=
|
||||
rotComp * 20.0f * eng.delta;
|
||||
Ogre::Vector3 angularVelocityChange =
|
||||
rotation * localAngularVelocityChange;
|
||||
Ogre::Vector3 angularImpulse =
|
||||
mass.mass * angularVelocityChange;
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.addAngularImpulse(id, angularImpulse);
|
||||
}
|
||||
});
|
||||
ecs.system<const EngineData, const CharacterBody, const WaterBody>(
|
||||
"update_water_character_buoyancy")
|
||||
@@ -480,15 +594,31 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
#endif
|
||||
}
|
||||
});
|
||||
ecs.system<const EngineData, const CharacterBody, CharacterVelocity>(
|
||||
"HandleVelocity")
|
||||
ecs.system<const EngineData, const CharacterBody>("UpdatePhysics")
|
||||
.kind(flecs::OnUpdate)
|
||||
.with<CharacterUpdatePhysicsState>()
|
||||
.write<CharacterUpdatePhysicsState>()
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const CharacterBody &body) {
|
||||
if (e.has<CharacterDisablePhysics>())
|
||||
PhysicsModule::controlPhysics(e, false);
|
||||
else
|
||||
PhysicsModule::controlPhysics(e, true);
|
||||
e.remove<CharacterUpdatePhysicsState>();
|
||||
});
|
||||
ecs.system<const EngineData, const CharacterBase, const CharacterBody,
|
||||
CharacterVelocity>("HandleVelocity")
|
||||
.kind(PhysicsPostUpdate)
|
||||
.with<TerrainReady>()
|
||||
.with<WaterReady>()
|
||||
.without<CharacterDisablePhysics>()
|
||||
.without<CharacterUpdatePhysicsState>()
|
||||
.each([this](flecs::entity e, const EngineData &eng,
|
||||
const CharacterBase &chbase,
|
||||
const CharacterBody &body, CharacterVelocity &gr) {
|
||||
if (e.has<InWater>() &&
|
||||
chbase.mBodyNode->_getDerivedPosition().y > -0.5f)
|
||||
e.remove<InWater>();
|
||||
Ogre::Vector3 v = gr.velocity;
|
||||
v.y = 0.0f;
|
||||
JPH::Character *ch =
|
||||
@@ -513,6 +643,39 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
ch->SetLinearVelocity(JoltPhysics::convert(v));
|
||||
gr.velocity = Ogre::Vector3::ZERO;
|
||||
});
|
||||
ecs.system<const EngineData, CharacterBase, const CharacterBody,
|
||||
CharacterVelocity>("HandleVelocityNoPhysics")
|
||||
.kind(PhysicsPostUpdate)
|
||||
.with<TerrainReady>()
|
||||
.with<WaterReady>()
|
||||
.with<CharacterDisablePhysics>()
|
||||
.without<CharacterUpdatePhysicsState>()
|
||||
.each([this](flecs::entity e, const EngineData &eng,
|
||||
CharacterBase &ch, const CharacterBody &body,
|
||||
CharacterVelocity &gr) {
|
||||
Ogre::Vector3 v = gr.velocity;
|
||||
// v.y = 0.0f;
|
||||
ch.mBodyNode->_setDerivedPosition(
|
||||
ch.mBodyNode->_getDerivedPosition() +
|
||||
v * eng.delta);
|
||||
gr.velocity = Ogre::Vector3::ZERO;
|
||||
if (e.has<JPH::BodyID>())
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.setPositionAndRotation(
|
||||
e.get<JPH::BodyID>(),
|
||||
ch.mBodyNode
|
||||
->_getDerivedPosition(),
|
||||
ch.mBodyNode
|
||||
->_getDerivedOrientation(),
|
||||
false);
|
||||
if (e.has<InWater>() &&
|
||||
ch.mBodyNode->_getDerivedPosition().y > -0.5f) {
|
||||
e.remove<InWater>();
|
||||
ch.is_submerged = false;
|
||||
}
|
||||
if (!e.has<InWater>() && ch.is_submerged)
|
||||
ch.is_submerged = false;
|
||||
});
|
||||
}
|
||||
flecs::entity PhysicsModule::createTerrainChunkBody(Ogre::SceneNode *node,
|
||||
float *samples,
|
||||
@@ -528,8 +691,58 @@ flecs::entity PhysicsModule::createTerrainChunkBody(Ogre::SceneNode *node,
|
||||
|
||||
return e;
|
||||
}
|
||||
void PhysicsModule::controlPhysics(flecs::entity e, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
if (e.has<CharacterBase>()) {
|
||||
e.remove<CharacterDisablePhysics>();
|
||||
OgreAssert(e.has<CharacterBody>(), "No body component");
|
||||
OgreAssert(e.has<JPH::BodyID>(),
|
||||
"No body id in entity");
|
||||
}
|
||||
if (!JoltPhysicsWrapper::getSingleton().isAdded(
|
||||
e.get<JPH::BodyID>())) {
|
||||
Ogre::Vector3 position =
|
||||
e.get<CharacterBase>()
|
||||
.mBodyNode->_getDerivedPosition();
|
||||
Ogre::Quaternion orientation =
|
||||
e.get<CharacterBase>()
|
||||
.mBodyNode->_getDerivedOrientation();
|
||||
if (position.y >= -0.5f)
|
||||
e.remove<InWater>();
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.setPositionAndRotation(e.get<JPH::BodyID>(),
|
||||
position, orientation,
|
||||
false);
|
||||
JoltPhysicsWrapper::getSingleton().addBody(
|
||||
e.get<JPH::BodyID>(),
|
||||
JPH::EActivation::Activate);
|
||||
}
|
||||
} else {
|
||||
if (e.has<CharacterBase>()) {
|
||||
e.add<CharacterDisablePhysics>();
|
||||
if (!e.has<CharacterBody>())
|
||||
return;
|
||||
OgreAssert(e.has<CharacterBody>(), "No body component");
|
||||
OgreAssert(e.has<JPH::BodyID>(),
|
||||
"No body id in entity");
|
||||
}
|
||||
if (JoltPhysicsWrapper::getSingleton().isAdded(
|
||||
e.get<JPH::BodyID>()))
|
||||
JoltPhysicsWrapper::getSingleton().removeBody(
|
||||
e.get<JPH::BodyID>());
|
||||
Ogre::Vector3 position =
|
||||
e.get<CharacterBase>().mBodyNode->_getDerivedPosition();
|
||||
e.remove<InWater>();
|
||||
}
|
||||
}
|
||||
bool WaterBody::isInWater(const JPH::BodyID &id) const
|
||||
{
|
||||
flecs::entity e =
|
||||
ECS::get().query_builder<const JPH::BodyID>().build().find(
|
||||
[&](const JPH::BodyID &bodyid) {
|
||||
return bodyid == id;
|
||||
});
|
||||
return inWater.find(id) != inWater.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace JPH
|
||||
{
|
||||
class Shape;
|
||||
class CharacterBase;
|
||||
class BodyID;
|
||||
}
|
||||
namespace Ogre
|
||||
{
|
||||
@@ -45,6 +46,9 @@ struct CharacterVelocity {
|
||||
Ogre::Vector3 gvelocity;
|
||||
Ogre::Vector3 velocity;
|
||||
};
|
||||
struct CachedMass {
|
||||
float mass;
|
||||
};
|
||||
struct PhysicsModule {
|
||||
PhysicsModule(flecs::world &ecs);
|
||||
static flecs::entity createTerrainChunkBody(Ogre::SceneNode *node,
|
||||
@@ -52,6 +56,7 @@ struct PhysicsModule {
|
||||
const Ogre::Vector3 &offset,
|
||||
const Ogre::Vector3 &scale,
|
||||
int sampleCount);
|
||||
static void controlPhysics(flecs::entity e, bool enable);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -15,139 +15,165 @@ SlotsModule::SlotsModule(flecs::world &ecs)
|
||||
ecs.component<ObjectSlots>();
|
||||
ecs.observer<const EngineData, const BoatBase>("CreateBoatSlots")
|
||||
.event(flecs::OnSet)
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const BoatBase &boat) {
|
||||
int i;
|
||||
std::vector<Ogre::Node *> slots =
|
||||
boat.mNode->getChildren();
|
||||
for (i = 0; i < slots.size(); i++) {
|
||||
Ogre::Any any =
|
||||
static_cast<Ogre::SceneNode *>(slots[i])
|
||||
->getUserObjectBindings()
|
||||
.getUserAny("type");
|
||||
if (!any.has_value())
|
||||
continue;
|
||||
Ogre::String obj_type =
|
||||
Ogre::any_cast<Ogre::String>(any);
|
||||
std::cout << "child type: " << obj_type
|
||||
<< std::endl;
|
||||
}
|
||||
if (slots.size() > 0) {
|
||||
ObjectSlots &vs = e.ensure<ObjectSlots>();
|
||||
for (i = 0; i < slots.size(); i++) {
|
||||
Ogre::Any any =
|
||||
static_cast<Ogre::SceneNode *>(
|
||||
slots[i])
|
||||
->getUserObjectBindings()
|
||||
.getUserAny("type");
|
||||
if (!any.has_value())
|
||||
continue;
|
||||
Ogre::String obj_type =
|
||||
Ogre::any_cast<Ogre::String>(
|
||||
any);
|
||||
any = static_cast<Ogre::SceneNode *>(
|
||||
slots[i])
|
||||
->getUserObjectBindings()
|
||||
.getUserAny("name");
|
||||
if (!any.has_value())
|
||||
continue;
|
||||
Ogre::String obj_name =
|
||||
Ogre::any_cast<Ogre::String>(
|
||||
any);
|
||||
vs.slots[obj_name] = {
|
||||
obj_type,
|
||||
static_cast<Ogre::SceneNode *>(
|
||||
slots[i])
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
ecs.system<const EngineData, const CharacterBase, ParentSlot,
|
||||
ParentSlotData>("UpdatePhysics2a")
|
||||
.each([&](flecs::entity e, const EngineData &eng,
|
||||
const BoatBase &boat) { createBoatSlots(e); });
|
||||
#if 1
|
||||
ecs.system<const EngineData, const CharacterBase, ParentSlot>(
|
||||
"UpdateSlotData")
|
||||
.kind(flecs::OnUpdate)
|
||||
.with<CharacterDisablePhysics>()
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const CharacterBase &ch, ParentSlot &slot,
|
||||
ParentSlotData &psdata) {
|
||||
.without<ParentSlotData>()
|
||||
.each([&](flecs::entity e, const EngineData &eng,
|
||||
const CharacterBase &ch, ParentSlot &slot) {
|
||||
if (slot.slot_name == "") {
|
||||
e.remove<ParentSlot>();
|
||||
e.remove<ParentSlotData>();
|
||||
slot.removeSlot(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (slot.parent_e.has<ObjectSlots>()) {
|
||||
const ObjectSlots &slots =
|
||||
slot.parent_e.get<ObjectSlots>();
|
||||
if (slots.slots.find(slot.slot_name) ==
|
||||
slots.slots.end()) {
|
||||
// invalid setting
|
||||
e.remove<ParentSlot>();
|
||||
if (slot.parentIsValid()) {
|
||||
if (!slot.check()) {
|
||||
slot.removeSlot(e);
|
||||
return;
|
||||
}
|
||||
Ogre::SceneNode *slot_base =
|
||||
slots.slots.at(slot.slot_name).second;
|
||||
#if 0
|
||||
ch.mBodyNode->getParent()->removeChild(
|
||||
ch.mBodyNode);
|
||||
#endif
|
||||
slot_base->addChild(ch.mBodyNode);
|
||||
Ogre::Vector3 position =
|
||||
slot_base->_getDerivedPosition();
|
||||
Ogre::Quaternion orientation =
|
||||
slot_base->_getDerivedOrientation();
|
||||
ch.mBodyNode->_setDerivedPosition(position);
|
||||
ch.mBodyNode->_setDerivedOrientation(
|
||||
orientation);
|
||||
psdata.parent_e = slot.parent_e;
|
||||
psdata.parentNode = slot_base;
|
||||
psdata.slot_name = slot.slot_name;
|
||||
slot.addChild(ch.mBodyNode);
|
||||
slot.createSlotData(e);
|
||||
std::cout << "base: "
|
||||
<< slot.getSlotBase()->getName();
|
||||
e.remove<ParentSlot>();
|
||||
e.modified<ParentSlotData>();
|
||||
std::cout << "base: " << slot_base->getName();
|
||||
}
|
||||
});
|
||||
#endif
|
||||
#if 0
|
||||
ecs.system<const EngineData, const CharacterBase, ParentSlot>(
|
||||
"UpdatePhysics2")
|
||||
"UpdateSlotCharacterTransforms")
|
||||
.kind(flecs::OnUpdate)
|
||||
.with<CharacterDisablePhysics>()
|
||||
.without<ParentSlotData>()
|
||||
.with<WaterReady>()
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const CharacterBase &ch, ParentSlot &slot) {
|
||||
.each([&](flecs::entity e, const EngineData &eng,
|
||||
const CharacterBase &ch, ParentSlot &slot) {
|
||||
std::cout << e.name() << std::endl;
|
||||
if (!slot.parent_e.has<ObjectSlots>())
|
||||
if (!slot.parentIsValid())
|
||||
return;
|
||||
OgreAssert(slot.parent_e.has<ObjectSlots>(),
|
||||
"parent has no slots");
|
||||
OgreAssert(e.has<Character>(), "not a character");
|
||||
if (slot.parent_e.has<ObjectSlots>()) {
|
||||
const ObjectSlots &slots =
|
||||
slot.parent_e.get<ObjectSlots>();
|
||||
if (slot.slot_name == "")
|
||||
return;
|
||||
if (slots.slots.find(slot.slot_name) ==
|
||||
slots.slots.end()) {
|
||||
// invalid setting
|
||||
e.remove<ParentSlot>();
|
||||
if (slot.parentIsValid()) {
|
||||
if (!slot.check()) {
|
||||
slot.removeSlot(e);
|
||||
OgreAssert(false, "bad slot");
|
||||
return;
|
||||
}
|
||||
ParentSlotData &psdata =
|
||||
e.ensure<ParentSlotData>();
|
||||
Ogre::SceneNode *slot_base =
|
||||
slots.slots.at(slot.slot_name).second;
|
||||
Ogre::Vector3 position =
|
||||
slot_base->_getDerivedPosition();
|
||||
Ogre::Quaternion orientation =
|
||||
slot_base->_getDerivedOrientation();
|
||||
ch.mBodyNode->_setDerivedPosition(position);
|
||||
ch.mBodyNode->_setDerivedOrientation(
|
||||
orientation);
|
||||
psdata.parent_e = slot.parent_e;
|
||||
psdata.parentNode = slot_base;
|
||||
psdata.slot_name = slot.slot_name;
|
||||
e.remove<ParentSlot>();
|
||||
e.modified<ParentSlotData>();
|
||||
slot.createSlot(e);
|
||||
slot.createSlotData(e);
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
void SlotsModule::createBoatSlots(flecs::entity e)
|
||||
{
|
||||
const EngineData &eng = e.world().get<EngineData>();
|
||||
const BoatBase &boat = e.get<BoatBase>();
|
||||
int i;
|
||||
std::vector<Ogre::Node *> slots = boat.mNode->getChildren();
|
||||
for (i = 0; i < slots.size(); i++) {
|
||||
Ogre::Any any = static_cast<Ogre::SceneNode *>(slots[i])
|
||||
->getUserObjectBindings()
|
||||
.getUserAny("type");
|
||||
if (!any.has_value())
|
||||
continue;
|
||||
Ogre::String obj_type = Ogre::any_cast<Ogre::String>(any);
|
||||
std::cout << "child type: " << obj_type << std::endl;
|
||||
}
|
||||
if (slots.size() > 0) {
|
||||
ObjectSlots &vs = e.ensure<ObjectSlots>();
|
||||
for (i = 0; i < slots.size(); i++) {
|
||||
Ogre::Any any = static_cast<Ogre::SceneNode *>(slots[i])
|
||||
->getUserObjectBindings()
|
||||
.getUserAny("type");
|
||||
if (!any.has_value())
|
||||
continue;
|
||||
Ogre::String obj_type =
|
||||
Ogre::any_cast<Ogre::String>(any);
|
||||
any = static_cast<Ogre::SceneNode *>(slots[i])
|
||||
->getUserObjectBindings()
|
||||
.getUserAny("name");
|
||||
if (!any.has_value())
|
||||
continue;
|
||||
Ogre::String obj_name =
|
||||
Ogre::any_cast<Ogre::String>(any);
|
||||
vs.slots[obj_name] = { obj_type,
|
||||
static_cast<Ogre::SceneNode *>(
|
||||
slots[i]) };
|
||||
}
|
||||
}
|
||||
}
|
||||
void ParentSlot::createSlot(flecs::entity e)
|
||||
{
|
||||
if (e.has<CharacterBase>()) {
|
||||
createCharacterSlot(e);
|
||||
}
|
||||
}
|
||||
void ParentSlot::createCharacterSlot(flecs::entity e)
|
||||
{
|
||||
}
|
||||
void ParentSlot::removeSlot(flecs::entity e)
|
||||
{
|
||||
if (e.has<ParentSlot>())
|
||||
e.remove<ParentSlot>();
|
||||
if (e.has<ParentSlot>())
|
||||
e.remove<ParentSlotData>();
|
||||
}
|
||||
bool ParentSlot::check() const
|
||||
{
|
||||
if (!parent_e.has<ObjectSlots>())
|
||||
return false;
|
||||
const ObjectSlots &slots = parent_e.get<ObjectSlots>();
|
||||
if (!slots.exists(slot_name))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool ParentSlot::parentIsValid()
|
||||
{
|
||||
if (!parent_e.has<ObjectSlots>())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
Ogre::SceneNode *ParentSlot::getSlotBase() const
|
||||
{
|
||||
if (!check())
|
||||
return nullptr;
|
||||
const ObjectSlots &slots = parent_e.get<ObjectSlots>();
|
||||
Ogre::SceneNode *slot_base = slots.slots.at(slot_name).second;
|
||||
return slot_base;
|
||||
}
|
||||
void ParentSlot::addChild(Ogre::SceneNode *childNode)
|
||||
{
|
||||
Ogre::SceneNode *parentNode = getSlotBase();
|
||||
if (childNode->getParentSceneNode())
|
||||
childNode->getParentSceneNode()->removeChild(childNode);
|
||||
parentNode->addChild(childNode);
|
||||
childNode->_setDerivedPosition(parentNode->_getDerivedPosition());
|
||||
childNode->_setDerivedOrientation(parentNode->_getDerivedOrientation());
|
||||
}
|
||||
void ParentSlot::createSlotData(flecs::entity e)
|
||||
{
|
||||
const ObjectSlots &slots = parent_e.get<ObjectSlots>();
|
||||
ParentSlotData &psdata = e.ensure<ParentSlotData>();
|
||||
Ogre::SceneNode *slot_base = getSlotBase();
|
||||
// Ogre::Vector3 position = slot_base->_getDerivedPosition();
|
||||
// Ogre::Quaternion orientation = slot_base->_getDerivedOrientation();
|
||||
// ch.mBodyNode->_setDerivedPosition(position);
|
||||
// ch.mBodyNode->_setDerivedOrientation(orientation);
|
||||
psdata.parent_e = parent_e;
|
||||
psdata.parentNode = slot_base;
|
||||
psdata.slot_name = slot_name;
|
||||
e.remove<ParentSlot>();
|
||||
e.modified<ParentSlotData>();
|
||||
}
|
||||
bool ObjectSlots::exists(const Ogre::String &name) const
|
||||
{
|
||||
return slots.find(name) != slots.end();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,14 @@ namespace ECS
|
||||
struct ParentSlot {
|
||||
flecs::entity parent_e;
|
||||
Ogre::String slot_name;
|
||||
void createSlot(flecs::entity e);
|
||||
void createCharacterSlot(flecs::entity e);
|
||||
void removeSlot(flecs::entity e);
|
||||
bool check() const;
|
||||
bool parentIsValid();
|
||||
Ogre::SceneNode *getSlotBase() const;
|
||||
void addChild(Ogre::SceneNode *childNode);
|
||||
void createSlotData(flecs::entity e);
|
||||
};
|
||||
struct ParentSlotData {
|
||||
Ogre::String slot_name;
|
||||
@@ -17,9 +25,11 @@ struct ObjectSlots {
|
||||
std::unordered_map<Ogre::String,
|
||||
std::pair<Ogre::String, Ogre::SceneNode *> >
|
||||
slots;
|
||||
bool exists(const Ogre::String &name) const;
|
||||
};
|
||||
struct SlotsModule {
|
||||
SlotsModule(flecs::world &ecs);
|
||||
void createBoatSlots(flecs::entity e);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <Jolt/Physics/Collision/Shape/MutableCompoundShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/HeightFieldShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.h>
|
||||
#include <Jolt/Physics/Collision/ContactListener.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Jolt/Physics/Body/BodyActivationListener.h>
|
||||
#include <Jolt/Renderer/DebugRendererSimple.h>
|
||||
@@ -156,6 +157,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
// An example contact listener
|
||||
class MyContactListener : public JPH::ContactListener {
|
||||
public:
|
||||
@@ -209,6 +211,7 @@ public:
|
||||
std::cout << "A body went to sleep" << std::endl;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
class MyCollector : public JPH::CollideShapeBodyCollector {
|
||||
public:
|
||||
MyCollector(JPH::PhysicsSystem *inSystem,
|
||||
@@ -453,6 +456,56 @@ JPH::ShapeRefC CompoundShapeBuilder::build()
|
||||
JPH::ShapeSettings::ShapeResult result = shapeSettings.Create();
|
||||
return result.Get();
|
||||
}
|
||||
ContactListener::ContactListener()
|
||||
: JPH::ContactListener()
|
||||
, dispatch(nullptr)
|
||||
{
|
||||
}
|
||||
JPH::ValidateResult ContactListener::OnContactValidate(
|
||||
const JPH::Body &inBody1, const JPH::Body &inBody2,
|
||||
JPH::RVec3Arg inBaseOffset,
|
||||
const JPH::CollideShapeResult &inCollisionResult)
|
||||
{
|
||||
return JPH::ValidateResult::AcceptAllContactsForThisBodyPair;
|
||||
}
|
||||
void ContactListener::OnContactAdded(const JPH::Body &inBody1,
|
||||
const JPH::Body &inBody2,
|
||||
const JPH::ContactManifold &inManifold,
|
||||
JPH::ContactSettings &ioSettings)
|
||||
{
|
||||
reports.push_back({ true, inBody1.GetID(), inBody2.GetID(), inManifold,
|
||||
ioSettings });
|
||||
}
|
||||
void ContactListener::OnContactPersisted(const JPH::Body &inBody1,
|
||||
const JPH::Body &inBody2,
|
||||
const JPH::ContactManifold &inManifold,
|
||||
JPH::ContactSettings &ioSettings)
|
||||
{
|
||||
}
|
||||
void ContactListener::OnContactRemoved(const JPH::SubShapeIDPair &inSubShapePair)
|
||||
{
|
||||
reports.push_back({ false, inSubShapePair.GetBody1ID(),
|
||||
inSubShapePair.GetBody2ID(), JPH::ContactManifold(),
|
||||
JPH::ContactSettings() });
|
||||
}
|
||||
void ContactListener::update()
|
||||
{
|
||||
for (auto contact : reports) {
|
||||
bool handled = false;
|
||||
if (listeners.find(contact.id1) != listeners.end()) {
|
||||
listeners[contact.id1](contact);
|
||||
handled = true;
|
||||
}
|
||||
if (listeners.find(contact.id2) != listeners.end()) {
|
||||
listeners[contact.id2](contact);
|
||||
handled = true;
|
||||
}
|
||||
if (!handled && dispatch) {
|
||||
dispatch(contact);
|
||||
}
|
||||
}
|
||||
reports.clear();
|
||||
}
|
||||
}
|
||||
|
||||
class Physics {
|
||||
@@ -498,29 +551,9 @@ public:
|
||||
virtual void OnBodyDeactivated(const JPH::BodyID &inBodyID,
|
||||
JPH::uint64 inBodyUserData) = 0;
|
||||
};
|
||||
class ContactListener : public JPH::ContactListener {
|
||||
public:
|
||||
virtual JPH::ValidateResult OnContactValidate(
|
||||
const JPH::Body &inBody1, const JPH::Body &inBody2,
|
||||
JPH::RVec3Arg inBaseOffset,
|
||||
const JPH::CollideShapeResult &inCollisionResult) = 0;
|
||||
virtual void
|
||||
OnContactAdded(const JPH::Body &inBody1,
|
||||
const JPH::Body &inBody2,
|
||||
const JPH::ContactManifold &inManifold,
|
||||
JPH::ContactSettings &ioSettings) = 0;
|
||||
virtual void
|
||||
OnContactPersisted(const JPH::Body &inBody1,
|
||||
const JPH::Body &inBody2,
|
||||
const JPH::ContactManifold &inManifold,
|
||||
JPH::ContactSettings &ioSettings) = 0;
|
||||
|
||||
virtual void
|
||||
OnContactRemoved(const JPH::SubShapeIDPair &inSubShapePair) = 0;
|
||||
};
|
||||
Physics(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
|
||||
ActivationListener *activationListener = nullptr,
|
||||
ContactListener *contactListener = nullptr)
|
||||
JPH::ContactListener *contactListener = nullptr)
|
||||
: temp_allocator(10 * 1024 * 1024)
|
||||
, job_system(JPH::cMaxPhysicsJobs, JPH::cMaxPhysicsBarriers,
|
||||
std::thread::hardware_concurrency() - 1)
|
||||
@@ -740,8 +773,10 @@ public:
|
||||
node->_setDerivedPosition(JoltPhysics::convert(p));
|
||||
node->_setDerivedOrientation(JoltPhysics::convert(q));
|
||||
}
|
||||
for (JPH::Character *ch : characters)
|
||||
ch->PostSimulation(0.1f);
|
||||
for (JPH::Character *ch : characters) {
|
||||
if (body_interface.IsAdded(ch->GetBodyID()))
|
||||
ch->PostSimulation(0.1f);
|
||||
}
|
||||
|
||||
if (debugDraw)
|
||||
physics_system.DrawBodies(
|
||||
@@ -873,7 +908,7 @@ public:
|
||||
if (shape->GetType() == JPH::EShapeType::HeightField) {
|
||||
JPH::BodyInterface &body_interface =
|
||||
physics_system.GetBodyInterface();
|
||||
body_interface.SetFriction(id, 0.7f);
|
||||
body_interface.SetFriction(id, 1.0f);
|
||||
}
|
||||
id2node[id] = node;
|
||||
node2id[node] = id;
|
||||
@@ -1385,6 +1420,21 @@ public:
|
||||
physics_system.GetBodyInterface().GetLinearVelocity(
|
||||
id));
|
||||
}
|
||||
Ogre::Vector3 getAngularVelocity(JPH::BodyID id)
|
||||
{
|
||||
return JoltPhysics::convert(
|
||||
physics_system.GetBodyInterface().GetAngularVelocity(
|
||||
id));
|
||||
}
|
||||
float getFriction(JPH::BodyID id)
|
||||
{
|
||||
return physics_system.GetBodyInterface().GetFriction(id);
|
||||
}
|
||||
void setFriction(JPH::BodyID id, float friction)
|
||||
{
|
||||
return physics_system.GetBodyInterface().SetFriction(id,
|
||||
friction);
|
||||
}
|
||||
void broadphaseQuery(float dt, const Ogre::Vector3 &position,
|
||||
std::set<JPH::BodyID> &inWater)
|
||||
{
|
||||
@@ -1434,7 +1484,7 @@ JoltPhysicsWrapper::JoltPhysicsWrapper(Ogre::SceneManager *scnMgr,
|
||||
JPH::Trace = TraceImpl;
|
||||
JPH_IF_ENABLE_ASSERTS(JPH::AssertFailed = AssertFailedImpl;)
|
||||
|
||||
phys = new Physics(scnMgr, cameraNode);
|
||||
phys = new Physics(scnMgr, cameraNode, nullptr, &contacts);
|
||||
}
|
||||
|
||||
JoltPhysicsWrapper::~JoltPhysicsWrapper()
|
||||
@@ -1446,6 +1496,7 @@ JoltPhysicsWrapper::~JoltPhysicsWrapper()
|
||||
void JoltPhysicsWrapper::update(float dt)
|
||||
{
|
||||
phys->update(dt);
|
||||
contacts.update();
|
||||
}
|
||||
|
||||
void JoltPhysicsWrapper::addBody(const JPH::BodyID &body,
|
||||
@@ -1629,6 +1680,10 @@ void JoltPhysicsWrapper::setPosition(JPH::BodyID id,
|
||||
{
|
||||
return phys->setPosition(id, position, activate);
|
||||
}
|
||||
Ogre::Quaternion JoltPhysicsWrapper::getRotation(JPH::BodyID id)
|
||||
{
|
||||
return phys->getRotation(id);
|
||||
}
|
||||
void JoltPhysicsWrapper::setRotation(JPH::BodyID id,
|
||||
const Ogre::Quaternion &rotation,
|
||||
bool activate)
|
||||
@@ -1651,10 +1706,41 @@ Ogre::Vector3 JoltPhysicsWrapper::getLinearVelocity(JPH::BodyID id)
|
||||
{
|
||||
return phys->getLinearVelocity(id);
|
||||
}
|
||||
Ogre::Vector3 JoltPhysicsWrapper::getAngularVelocity(JPH::BodyID id)
|
||||
{
|
||||
return phys->getAngularVelocity(id);
|
||||
}
|
||||
float JoltPhysicsWrapper::getFriction(JPH::BodyID id)
|
||||
{
|
||||
return phys->getFriction(id);
|
||||
}
|
||||
void JoltPhysicsWrapper::setFriction(JPH::BodyID id, float friction)
|
||||
{
|
||||
phys->setFriction(id, friction);
|
||||
}
|
||||
void JoltPhysicsWrapper::addAngularImpulse(const JPH::BodyID &id,
|
||||
const Ogre::Vector3 &impulse)
|
||||
{
|
||||
return phys->addAngularImpulse(id, impulse);
|
||||
}
|
||||
void JoltPhysicsWrapper::setDispatch(
|
||||
std::function<
|
||||
void(const JoltPhysics::ContactListener::ContactReport &report)>
|
||||
dispatcher)
|
||||
{
|
||||
contacts.setDispatch(dispatcher);
|
||||
}
|
||||
void JoltPhysicsWrapper::addContactListener(
|
||||
const JPH::BodyID &id,
|
||||
std::function<
|
||||
void(const JoltPhysics::ContactListener::ContactReport &report)>
|
||||
listener)
|
||||
{
|
||||
contacts.addListener(id, listener);
|
||||
}
|
||||
void JoltPhysicsWrapper::removeContactListener(const JPH::BodyID &id)
|
||||
{
|
||||
contacts.removeListener(id);
|
||||
}
|
||||
template <>
|
||||
JoltPhysicsWrapper *Ogre::Singleton<JoltPhysicsWrapper>::msSingleton = 0;
|
||||
JoltPhysicsWrapper *Ogre::Singleton<JoltPhysicsWrapper>::msSingleton = 0;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <Jolt/Physics/Collision/Shape/Shape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/StaticCompoundShape.h>
|
||||
#include <Jolt/Physics/Collision/ObjectLayer.h>
|
||||
#include <Jolt/Physics/Collision/ContactListener.h>
|
||||
#include <Jolt/Physics/Collision/BroadPhase/BroadPhaseLayer.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Jolt/Physics/EActivation.h>
|
||||
@@ -13,6 +14,9 @@ void physics();
|
||||
namespace JPH
|
||||
{
|
||||
class CharacterBase;
|
||||
class ContactManifold;
|
||||
class ContactSettings;
|
||||
class SubShapeIDPair;
|
||||
}
|
||||
// Layer that objects can be in, determines which other objects it can collide with
|
||||
// Typically you at least want to have 1 layer for moving bodies and 1 layer for static bodies, but you can have more
|
||||
@@ -50,10 +54,58 @@ struct CompoundShapeBuilder {
|
||||
const Ogre::Quaternion &rotation);
|
||||
JPH::ShapeRefC build();
|
||||
};
|
||||
class ContactListener : public JPH::ContactListener {
|
||||
public:
|
||||
struct ContactReport {
|
||||
bool entered;
|
||||
JPH::BodyID id1, id2;
|
||||
JPH::ContactManifold manifold;
|
||||
JPH::ContactSettings settings;
|
||||
};
|
||||
|
||||
private:
|
||||
std::list<ContactReport> reports;
|
||||
std::function<void(const ContactReport &report)> dispatch;
|
||||
std::map<JPH::BodyID, std::function<void(const ContactReport &report)> >
|
||||
listeners;
|
||||
|
||||
public:
|
||||
ContactListener();
|
||||
JPH::ValidateResult OnContactValidate(
|
||||
const JPH::Body &inBody1, const JPH::Body &inBody2,
|
||||
JPH::RVec3Arg inBaseOffset,
|
||||
const JPH::CollideShapeResult &inCollisionResult) override;
|
||||
void OnContactAdded(const JPH::Body &inBody1, const JPH::Body &inBody2,
|
||||
const JPH::ContactManifold &inManifold,
|
||||
JPH::ContactSettings &ioSettings) override;
|
||||
void OnContactPersisted(const JPH::Body &inBody1,
|
||||
const JPH::Body &inBody2,
|
||||
const JPH::ContactManifold &inManifold,
|
||||
JPH::ContactSettings &ioSettings) override;
|
||||
void
|
||||
OnContactRemoved(const JPH::SubShapeIDPair &inSubShapePair) override;
|
||||
void setDispatch(const std::function<void(const ContactReport &report)>
|
||||
dispatcher)
|
||||
{
|
||||
dispatch = dispatcher;
|
||||
}
|
||||
void addListener(
|
||||
const JPH::BodyID &id,
|
||||
const std::function<void(const ContactReport &report)> listener)
|
||||
{
|
||||
listeners[id] = listener;
|
||||
}
|
||||
void removeListener(const JPH::BodyID &id)
|
||||
{
|
||||
listeners.erase(id);
|
||||
}
|
||||
void update();
|
||||
};
|
||||
}
|
||||
|
||||
class JoltPhysicsWrapper : public Ogre::Singleton<JoltPhysicsWrapper> {
|
||||
public:
|
||||
JoltPhysics::ContactListener contacts;
|
||||
JoltPhysicsWrapper(Ogre::SceneManager *scnMgr,
|
||||
Ogre::SceneNode *cameraNode);
|
||||
~JoltPhysicsWrapper();
|
||||
@@ -128,6 +180,7 @@ public:
|
||||
Ogre::Vector3 getPosition(JPH::BodyID id);
|
||||
void setPosition(JPH::BodyID id, const Ogre::Vector3 &position,
|
||||
bool activate = true);
|
||||
Ogre::Quaternion getRotation(JPH::BodyID id);
|
||||
void setRotation(JPH::BodyID id, const Ogre::Quaternion &rotation,
|
||||
bool activate = true);
|
||||
void getPositionAndRotation(JPH::BodyID id, Ogre::Vector3 &position,
|
||||
@@ -137,7 +190,19 @@ public:
|
||||
const Ogre::Quaternion &rotation,
|
||||
bool activate = true);
|
||||
Ogre::Vector3 getLinearVelocity(JPH::BodyID id);
|
||||
Ogre::Vector3 getAngularVelocity(JPH::BodyID id);
|
||||
float getFriction(JPH::BodyID id);
|
||||
void setFriction(JPH::BodyID id, float friction);
|
||||
void addAngularImpulse(const JPH::BodyID &id,
|
||||
const Ogre::Vector3 &impulse);
|
||||
void setDispatch(std::function<void(const JoltPhysics::ContactListener::
|
||||
ContactReport &report)>
|
||||
dispatcher);
|
||||
void addContactListener(
|
||||
const JPH::BodyID &id,
|
||||
const std::function<void(const JoltPhysics::ContactListener::
|
||||
ContactReport &report)>
|
||||
listener);
|
||||
void removeContactListener(const JPH::BodyID &id);
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "GameData.h"
|
||||
#include "Components.h"
|
||||
#include "EventTriggerModule.h"
|
||||
#include "PhysicsModule.h"
|
||||
#include "physics.h"
|
||||
#include "loader.h"
|
||||
|
||||
@@ -1868,15 +1869,23 @@ void SceneLoader::setupPhysicsBody(Ogre::SceneNode *node,
|
||||
layer = Layers::NON_MOVING;
|
||||
mass = 0.0f;
|
||||
}
|
||||
#if 1
|
||||
JPH::ShapeRefC com_shape =
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.createOffsetCenterOfMassShape(
|
||||
Ogre::Vector3(0, -5.5f, 0.5f),
|
||||
Ogre::Vector3(0, 0, 0.45f),
|
||||
shape);
|
||||
JPH::BodyID id =
|
||||
JoltPhysicsWrapper::getSingleton().createBody(
|
||||
com_shape.GetPtr(), mass, pNode, motion,
|
||||
layer);
|
||||
JoltPhysicsWrapper::getSingleton().setFriction(id, 0.95f);
|
||||
#else
|
||||
JPH::BodyID id =
|
||||
JoltPhysicsWrapper::getSingleton().createBody(
|
||||
shape.GetPtr(), mass, pNode, motion,
|
||||
layer);
|
||||
#endif
|
||||
LogManager::getSingleton().logMessage(
|
||||
"[SceneLoader] Node: " + pNode->getName() +
|
||||
" btRigidBody created: " + collisionBodyType);
|
||||
@@ -1887,6 +1896,7 @@ void SceneLoader::setupPhysicsBody(Ogre::SceneNode *node,
|
||||
id);
|
||||
/* do not add body to physics yet */
|
||||
base_e.set<JPH::BodyID>(id);
|
||||
base_e.set<ECS::CachedMass>({mass});
|
||||
} else if (collisionBodyType == "ghost") {
|
||||
/* TODO: later */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user