Compare commits

...

3 Commits

Author SHA1 Message Date
884a310033 aarch64 build support 2026-02-14 03:05:45 +08:00
b363742507 Proper path setting 2026-02-13 22:04:43 +03:00
a85152a675 Adapted more debugging with Tracy, characters update 2026-02-13 18:14:09 +03:00
28 changed files with 838 additions and 154 deletions

View File

@@ -246,7 +246,7 @@ add_custom_target(stage_files ALL DEPENDS ${CMAKE_BINARY_DIR}/resources.cfg ${MA
add_custom_target(remove_scenes COMMAND rm -f ${VRM_SOURCE} ${VRM_IMPORTED_BLENDS} ${CHARACTER_GLBS})
target_compile_definitions(Game PRIVATE FLECS_CPP_NO_AUTO_REGISTRATION JPH_PROFILE_ENABLED)
target_compile_definitions(Game PRIVATE FLECS_CPP_NO_AUTO_REGISTRATION JPH_PROFILE_ENABLED JPH_DEBUG_RENDERER JPH_PROFILE_ENABLED JPH_DOUBLE_PRECISION)
install(TARGETS Game DESTINATION bin)
install(TARGETS Editor DESTINATION bin)

View File

@@ -10,7 +10,6 @@
#include <OgreTimer.h>
#include <OgreMeshLodGenerator.h>
// #include "water/water.h"
#include "GameData.h"
#include "Components.h"
#include "CharacterModule.h"
@@ -630,11 +629,11 @@ end:
void setupInput()
{
}
JoltPhysicsWrapper *mJolt;
JoltPhysicsWrapper *mJolt;
void createContent()
{
int i;
mJolt = new JoltPhysicsWrapper(mScnMgr, mCameraNode);
mJolt = new JoltPhysicsWrapper(mScnMgr, mCameraNode);
sky = new SkyBoxRenderer(getSceneManager());
bool drawFirst = true;

View File

@@ -11,18 +11,24 @@ add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/edited-normal-${EDITED_BLEND}.blend
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/edited-normal-${EDITED_BLEND}.blend
${CMAKE_BINARY_DIR}/assets/blender/vrm-vroid-normal-${EDITED_BLEND}.blend
${CMAKE_CURRENT_SOURCE_DIR}/copy_animations.py
${CMAKE_BINARY_DIR}/assets/blender/mixamo
COMMAND ${CMAKE_COMMAND}
-E copy ${CMAKE_CURRENT_SOURCE_DIR}/edited-normal-${EDITED_BLEND}.blend
${CMAKE_CURRENT_BINARY_DIR}/edited-normal-${EDITED_BLEND}.blend
COMMAND ${BLENDER} -b -Y
${CMAKE_CURRENT_BINARY_DIR}/edited-normal-${EDITED_BLEND}.blend
-P ${CMAKE_SOURCE_DIR}/assets/blender/scripts/copy_animations.py --
-P ${CMAKE_CURRENT_SOURCE_DIR}/copy_animations.py --
${CMAKE_BINARY_DIR}/assets/blender/vrm-vroid-normal-${EDITED_BLEND}.blend ${EDITED_BLEND}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
list(APPEND EDITED_BLEND_TARGETS ${CMAKE_BINARY_DIR}/assets/blender/characters/edited-normal-${EDITED_BLEND}.blend)
list(APPEND CHARACTER_GLBS ${CMAKE_BINARY_DIR}/characters/${EDITED_BLEND}/normal-${EDITED_BLEND}.glb)
endforeach()
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/assets/blender/mixamo
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/assets/blender/mixamo ${CMAKE_BINARY_DIR}/assets/blender/mixamo
DEPENDS ${CMAKE_SOURCE_DIR}/assets/blender/mixamo
)
set(VRM_IMPORTED_BLENDS
${CMAKE_BINARY_DIR}/assets/blender/vrm-vroid-normal-female.blend
@@ -30,16 +36,48 @@ set(VRM_IMPORTED_BLENDS
${CMAKE_BINARY_DIR}/assets/blender/shapes/male/vrm-vroid-normal-male-chibi.blend
)
#add_custom_command(
# OUTPUT ${CHARACTER_GLBS}
# COMMAND ${CMAKE_COMMAND} -E make_directory ${CREATE_DIRECTORIES}
# COMMAND ${BLENDER} -b -Y -P ${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_models.py
# COMMAND ${CMAKE_COMMAND} -D FILE=${CMAKE_BINARY_DIR}/characters/male/normal-male.glb -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/check_file_size.cmake
# COMMAND ${CMAKE_COMMAND} -D FILE=${CMAKE_BINARY_DIR}/characters/female/normal-female.glb -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/check_file_size.cmake
# COMMAND ${CMAKE_COMMAND} -E touch_nocreate ${CHARACTER_GLBS}
# DEPENDS ${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_models.py ${VRM_IMPORTED_BLENDS} ${EDITED_BLEND_TARGETS}
# WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set(FEMALE_OBJECTS "Body;Hair;Face;BackHair;Tops;Bottoms;Shoes;Accessory")
set(MALE_OBJECTS "Body;Hair;Face;BackHair;Tops;Bottoms;Shoes;Accessory")
add_custom_command(
OUTPUT ${CHARACTER_GLBS}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CREATE_DIRECTORIES}
COMMAND ${BLENDER} -b -Y -P ${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_models.py
COMMAND ${CMAKE_COMMAND} -D FILE=${CMAKE_BINARY_DIR}/characters/male/normal-male.glb -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/check_file_size.cmake
COMMAND ${CMAKE_COMMAND} -D FILE=${CMAKE_BINARY_DIR}/characters/female/normal-female.glb -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/check_file_size.cmake
COMMAND ${CMAKE_COMMAND} -E touch_nocreate ${CHARACTER_GLBS}
DEPENDS ${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_models.py ${VRM_IMPORTED_BLENDS} ${EDITED_BLEND_TARGETS}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
OUTPUT ${CMAKE_BINARY_DIR}/characters/male/normal-male.glb
COMMAND ${CMAKE_COMMAND} -E make_directory ${CREATE_DIRECTORIES}
COMMAND ${BLENDER} -b -Y -P ${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_models2.py --
${CMAKE_CURRENT_BINARY_DIR}/edited-normal-male.blend
${CMAKE_BINARY_DIR}/characters/male/normal-male.glb
"${MALE_OBJECTS}"
"male"
tmp-edited-male.blend
DEPENDS ${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_models2.py
${VRM_IMPORTED_BLENDS}
${CMAKE_CURRENT_BINARY_DIR}/edited-normal-male.blend
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
VERBATIM
)
add_custom_command(
OUTPUT ${CMAKE_BINARY_DIR}/characters/female/normal-female.glb
COMMAND ${CMAKE_COMMAND} -E make_directory ${CREATE_DIRECTORIES}
COMMAND ${BLENDER} -b -Y -P ${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_models2.py --
${CMAKE_CURRENT_BINARY_DIR}/edited-normal-female.blend
${CMAKE_BINARY_DIR}/characters/female/normal-female.glb
"${FEMALE_OBJECTS}"
"female"
tmp-edited-female.blend
DEPENDS ${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_models2.py
${VRM_IMPORTED_BLENDS}
${CMAKE_CURRENT_BINARY_DIR}/edited-normal-female.blend
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
VERBATIM
)
set(VRM_SOURCE)
@@ -84,7 +122,7 @@ function(blender_import_vrm BLEND VRM EDITABLE RIG)
get_filename_component(VRM_NAME ${VRM} NAME_WE)
add_custom_command(OUTPUT ${BLEND}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CREATE_DIRECTORIES}
COMMAND ${BLENDER} -b -Y -P ${CMAKE_SOURCE_DIR}/assets/blender/scripts/import_vrm2.py -- ${VRM_NAME}.vrm ${TARGET_NAME}.blend ${EDITABLE} ${RIG}
COMMAND ${BLENDER} -b -Y -P ${CMAKE_SOURCE_DIR}/assets/blender/scripts/import_vrm2.py -- ${VRM_NAME}.vrm ${BLEND} ${EDITABLE} ${RIG}
COMMAND ${CMAKE_COMMAND} -D FILE=${BLEND} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/check_file_size.cmake
COMMAND ${CMAKE_COMMAND} -E touch_nocreate ${BLEND}
DEPENDS ${CMAKE_SOURCE_DIR}/assets/blender/scripts/import_vrm2.py

View File

@@ -0,0 +1,64 @@
import bpy
import sys
import os
argv = sys.argv
argv = argv[argv.index("--") + 1:]
sys.path.insert(0, os.getcwd() + "/assets/blender/scripts")
source_filepath = argv[0]
armature_name = argv[1]
print("starting...")
def copy_actions_and_create_nla_tracks(source_filepath, target_object_name):
"""
Copies actions from a source Blender file that do not exist in the current
file, creates NLA tracks for them on a target object, and saves the file.
Args:
source_filepath (str): The full path to the source Blender file.
target_object_name (str): The name of the object in the current file
to which the actions and NLA tracks will be applied.
"""
# 1. Link or Append Actions from the Source File
with bpy.data.libraries.load(source_filepath, link=False) as (data_from, data_to):
source_action_names = data_from.actions
current_action_names = {action.name for action in bpy.data.actions}
actions_to_append = [name for name in source_action_names if name not in current_action_names]
data_to.actions = actions_to_append
print(actions_to_append)
# Get the target object
target_object = bpy.data.objects.get(target_object_name)
if not target_object:
print(f"Error: Object '{target_object_name}' not found in the current file.")
return
# Ensure the object has an NLA editor
if not target_object.animation_data:
target_object.animation_data_create()
# 2. Iterate through newly imported actions and create NLA tracks
for action in data_to.actions:
# Check if an action with the same name already exists in the current file
# Add the action to the NLA editor as a strip
nla_track = target_object.animation_data.nla_tracks.new()
nla_track.name = f"NLA_Track_{action.name}"
nla_track.strips.new(name=action.name, start=1, action=action)
print(f"Created NLA track for action: {action.name}")
# 3. Save the current Blender file
bpy.ops.wm.save_as_mainfile(filepath=bpy.context.blend_data.filepath)
print(f"File saved: {bpy.context.blend_data.filepath}")
# --- Usage Example ---
if __name__ == "__main__":
# Replace with your actual source file path and target object name
source_file = source_filepath
target_obj = armature_name
copy_actions_and_create_nla_tracks(source_file, target_obj)

View File

@@ -0,0 +1,296 @@
#!/usr/bin/env python
import os, sys, time
import bpy
from math import pi
import glob
import shutil
from mathutils import Vector, Matrix
from math import radians, pi
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
#from settings import ExportMappingFemale, ExportMappingMale, ExportMappingMaleBabyShape, ExportMappingMaleEdited, ExportMappingFemaleEdited, ExportMappingMaleTestShapeEdited, ExportMappingMaleBaseShapeEdited
argv = sys.argv
argv = argv[argv.index("--") + 1:]
basepath = os.getcwd()
def check_bone(bname):
ok = True
baddie = ["ctrl_", "mch_", "MCH_", "Ctrl_", "Mch_"]
for bd in baddie:
if bname.startswith(bd):
ok = False
break
return ok
def prepare_armature(mapping):
print("Preparing...")
bpy.ops.object.armature_add(enter_editmode=False)
new_armature = bpy.context.object
orig_armature = bpy.data.objects[mapping.armature_name]
armature_name = orig_armature.name
orig_armature.name = orig_armature.name + "_orig"
new_armature.name = armature_name
queue = []
if new_armature.animation_data is None:
new_armature.animation_data_create()
bpy.context.view_layer.objects.active = new_armature
bpy.ops.object.mode_set(mode='EDIT')
for b in new_armature.data.edit_bones:
new_armature.data.edit_bones.remove(b)
bpy.context.view_layer.objects.active = orig_armature
bpy.ops.object.mode_set(mode='EDIT')
for b in orig_armature.data.edit_bones:
print(b.name)
if b.parent is None:
queue.append(b.name)
print("Copying bones...")
while len(queue) > 0:
item = queue.pop(0)
print(item)
itemb = orig_armature.data.edit_bones[item]
if not itemb.use_deform and not check_bone(item):
continue
for cb in orig_armature.data.edit_bones:
if cb.parent == itemb:
queue.append(cb.name)
nb = new_armature.data.edit_bones.new(item)
nb.name = item
nb.head = itemb.head
nb.tail = itemb.tail
nb.matrix = itemb.matrix
nb.use_deform = itemb.use_deform
if itemb.parent is not None:
ok = True
pname = itemb.parent.name
while not check_bone(pname):
bparent = itemb.parent.parent
if bparent is None:
ok = False
break
pname = bparent.name
if ok:
nb.parent = new_armature.data.edit_bones[itemb.parent.name]
else:
nb.parent = None
else:
nb.parent = None
nb.use_connect = itemb.use_connect
# drivers_data = new_armature.animation_data.drivers
print("Creating constraints...")
bpy.context.view_layer.objects.active = new_armature
bpy.ops.object.mode_set(mode='OBJECT')
bpy.context.view_layer.objects.active = orig_armature
bpy.ops.object.mode_set(mode='OBJECT')
for b in new_armature.pose.bones:
print(b.name)
c = b.constraints.new(type='COPY_TRANSFORMS')
c.target = orig_armature
c.subtarget = b.name
for obj in bpy.data.objects:
if obj.parent == orig_armature:
obj.parent = new_armature
for mod in obj.modifiers:
if mod.type == 'ARMATURE':
mod.object = new_armature
print("Baking actions...")
bpy.context.view_layer.objects.active = new_armature
bpy.ops.object.mode_set(mode='POSE')
for track in orig_armature.animation_data.nla_tracks:
print(track.name)
for s in track.strips:
action = s.action
print(action.name)
orig_armature.animation_data.action = action
new_armature.animation_data.action = None
bpy.context.view_layer.objects.active = new_armature
firstFrame = int(s.action_frame_start)
lastFrame = int(s.action_frame_end)
bpy.ops.nla.bake(frame_start=firstFrame, frame_end=lastFrame, step=5, only_selected=False, visual_keying=True, clear_constraints=False, clean_curves=True, use_current_action=False, bake_types={'POSE'})
aname = orig_armature.animation_data.action.name
orig_armature.animation_data.action.name = "bake_" + aname
new_armature.animation_data.action.name = aname
track = new_armature.animation_data.nla_tracks.new()
track.name = aname
track.strips.new(track.name, int(new_armature.animation_data.action.frame_range[0]), new_armature.animation_data.action)
track.mute = True
track.lock = True
print("Removing constraints...")
for b in new_armature.pose.bones:
for c in b.constraints:
b.constraints.remove(c)
new_armature.animation_data.action = bpy.data.actions[mapping.default_action]
bpy.context.view_layer.objects.active = new_armature
bpy.ops.object.mode_set(mode='OBJECT')
# track = new_armature.animation_data.nla_tracks.new()
# track.name = action.name
def clamp_angle_deg(angle, min_angle_deg, max_angle_deg):
min_angle = radians(min_angle_deg)
max_angle = radians(max_angle_deg)
if angle < min_angle:
angle = min_angle
if angle > max_angle:
angle = max_angle
return angle
def angle_to_linear(angle, divider):
if angle < 0.0:
return angle / divider
else:
return 0.0
def angle_to_linear_x(bone, angle):
skel = bpy.data.objects["skeleton_orig"]
left_base = "ctrl_base_upperleg.L.001"
right_base = "ctrl_base_upperleg.R.001"
base = ""
if base == "":
for e in ["_R", ".R"]:
if bone.name.endswith(e):
base = right_base
break
if base == "":
for e in ["_L", ".L"]:
if bone.name.endswith(e):
base = left_base
break
if base == "":
for e in ["_R.", ".R."]:
if bone.name.find(e) >= 0:
base = right_base
break
if base == "":
for e in ["_L.", ".L."]:
if bone.name.find(e) >= 0:
base = left_base
break
mul = skel.pose.bones[base]["to_linear_x_base"]
offset = skel.pose.bones[base]["angle_offset"]
# print("bone: ", bone.name, "base: ", base, "mul: ", mul)
# print("angle: ", angle, " angle_offset: ", offset, " angle_sum: ", angle + offset)
print("offset: ", mul * (angle + offset), "bone: ", base, "angle: ", angle)
return (angle + offset) * mul
def extra_linear(angle, offset):
ret = 0.0
offt = offset * angle * 2.0 / -radians(-90)
if angle * 2.0 < -radians(65):
if angle * 2.0 > -radians(65):
ret += offset
else:
ret += offt
return ret
mapping_blend_path = argv[0]
mapping_gltf_path = argv[1]
mapping_objects = argv[2]
mapping_armature_name = argv[3]
mapping_outfile = argv[4]
#for mapping in [ExportMappingFemale(), ExportMappingMale(), ExportMappingMaleBabyShape(), ExportMappingMaleEdited(), ExportMappingFemaleEdited(), ExportMappingMaleTestShapeEdited(), ExportMappingMaleBaseShapeEdited()]:
class CommandLineMapping:
blend_path = mapping_blend_path
gltf_path = mapping_gltf_path
# ogre_scene = "characters/female/vroid-normal-female.scene"
inner_path = "Object"
# objs = ["male", "Body", "Hair", "Face", "BackHair", "Tops", "Bottoms", "Shoes", "Accessory"]
# objs = ["female", "Body", "Hair", "Face", "BackHair", "Tops", "Bottoms", "Shoes", "Accessory"]
objs = []
armature_name = mapping_armature_name
outfile = mapping_outfile
default_action = 'default'
def __init__(self):
self.objs = [mapping_armature_name]
if len(mapping_objects) > 0:
self.objs += [o.strip() for o in mapping_objects.split(";")]
self.files = []
for fobj in self.objs:
self.files.append({"name": fobj})
for mapping in[CommandLineMapping()]:
if not os.path.exists(mapping.blend_path):
print("Skipping mapping: " + mapping.blend_path)
continue
print("Processing mapping: from: " + mapping.blend_path + " to: " + mapping.gltf_path)
print("Initializing...")
bpy.ops.wm.read_homefile(use_empty=True)
print("Preparing driver setup...")
bpy.app.driver_namespace["clamp_angle_deg"] = clamp_angle_deg
bpy.app.driver_namespace["angle_to_linear"] = angle_to_linear
bpy.app.driver_namespace["extra_linear"] = extra_linear
bpy.app.driver_namespace["angle_to_linear_x"] = angle_to_linear_x
print("Driver setup done...")
bpy.ops.wm.append(
filepath=os.path.join(mapping.blend_path, mapping.inner_path),
directory=os.path.join(mapping.blend_path, mapping.inner_path),
files=mapping.files)
print("Append done...")
prepare_armature(mapping)
print("Armature done...")
print("Remove junk...")
for ob in bpy.data.objects:
if ob.name.startswith("cs_"):
bpy.data.objects.remove(ob)
elif ob.name.startswith("Face") and ob.name != "Face":
bpy.data.objects.remove(ob)
print("Removing original armature and actions...")
orig_arm = bpy.data.objects[mapping.armature_name + '_orig']
bpy.data.objects.remove(orig_arm)
for act in bpy.data.actions:
if act.name.startswith("bake_"):
act.name = act.name + "-noimp"
for act in bpy.data.actions:
if act.name.startswith("bake_"):
bpy.data.actions.remove(act)
for act in bpy.data.actions:
if act.name.startswith("bake_"):
bpy.data.actions.remove(act)
for obj in bpy.data.objects:
if obj.type == 'MESH':
if not obj.name in mapping.objs and obj.parent is None:
if not obj.name.endswith("-noimp"):
obj.name = obj.name + "-noimp"
bpy.ops.wm.save_as_mainfile(filepath=(basepath + "/assets/blender/scripts/" + mapping.outfile))
os.makedirs(os.path.dirname(mapping.gltf_path), exist_ok=True)
bpy.ops.export_scene.gltf(filepath=mapping.gltf_path,
use_selection=False,
check_existing=False,
# export_format='GLTF_SEPARATE',
export_format='GLB',
export_texture_dir='textures', export_texcoords=True,
export_animation_mode='NLA_TRACKS',
export_normals=True,
export_tangents=True,
export_materials='EXPORT',
# export_all_vertex_colors=True,
# colors_type='SRGB',
# export_vertex_colors=True,
export_colors=True,
use_mesh_edges=False,
use_mesh_vertices=False,
export_cameras=False,
use_visible=False,
use_renderable=False,
export_yup=True,
export_animations=True,
export_force_sampling=True,
export_def_bones=False,
export_current_frame=False,
export_morph=True,
export_morph_animation=False,
export_morph_normal=True,
export_morph_tangent=True,
export_lights=False,
export_skins=True)
print("exported to: " + mapping.gltf_path)
bpy.ops.wm.read_homefile(use_empty=True)
time.sleep(2)
bpy.ops.wm.quit_blender()

View File

@@ -207,5 +207,5 @@ main_armature.animation_data.action = default_action
main_armature.select_set(False)
bpy.context.view_layer.objects.active = None
bpy.ops.wm.save_as_mainfile(filepath=(basepath + "/assets/blender/" + imp.outfile))
bpy.ops.wm.save_as_mainfile(filepath=(imp.outfile))

View File

@@ -598,10 +598,10 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
npcs,
&ai]() {
{
std::lock_guard<std::mutex> lock(
ecs_mutex);
ZoneScopedN(
"UpdateBlackboards::Thread");
std::lock_guard<std::mutex> lock(
ecs_mutex);
updateBlackboards(town, alist, npcs,
ai);
@@ -766,6 +766,7 @@ static std::deque<PlanTask> plan_tasks;
void CharacterAIModule::buildPlans(flecs::entity town, const TownNPCs &npcs,
TownAI &ai)
{
ZoneScopedN("buildPlans");
OgreAssert(town.is_valid(), "Bad town entity");
std::lock_guard<std::mutex> lock(*ai.mutex);
auto planner = ai.planner;

View File

@@ -14,6 +14,7 @@ namespace ECS
{
CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
{
ZoneScoped;
ecs.module<CharacterAnimationModule>();
ecs.component<AnimationControl>();
ecs.import <EventModule>();
@@ -157,11 +158,11 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
.kind(flecs::OnUpdate)
.each([this](flecs::entity e, const EngineData &eng,
CharacterBase &ch, AnimationControl &anim) {
float delta = eng.delta;
ZoneScopedN("HandleAnimations1");
float delta = eng.delta;
// ch.mBoneMotion = Ogre::Vector3::ZERO;
if (!anim.mAnimationSystem)
return;
ZoneScopedN("HandleAnimations1");
bool result = anim.mAnimationSystem->addTime(delta);
Ogre::Vector3 rootMotion =
anim.mAnimationSystem->getRootMotionDelta();
@@ -193,11 +194,11 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
.with<WaterReady>()
.each([this](flecs::entity e, const EngineData &eng,
CharacterBase &ch, CharacterVelocity &v) {
if (eng.delta < 0.0000001f)
ZoneScopedN("HandleRootMotionVelocity");
if (eng.delta < 0.0000001f)
return;
if (!ch.mBodyNode)
return;
ZoneScopedN("HandleRootMotionVelocity");
Ogre::Quaternion rot = ch.mBodyNode->getOrientation();
Ogre::Vector3 pos = ch.mBodyNode->getPosition();
Ogre::Vector3 boneMotion = ch.mBoneMotion;
@@ -240,6 +241,7 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
.each([this](flecs::entity e, const EngineData &eng,
CharacterBase &ch, AnimationControl &anim,
CharacterVelocity &v) {
ZoneScopedN("HandleRootMotion");
if (!ch.mBodyNode)
return;
if (eng.delta < 0.0000001f)
@@ -258,11 +260,11 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
.without<Player>()
.each([](flecs::entity e, const Input &input,
const CharacterBase &ch, AnimationControl &anim) {
if (!anim.configured)
ZoneScopedNC("HandleNPCAnimations", 0xFF2020);
if (!anim.configured)
return;
if (!anim.mAnimationSystem)
return;
ZoneScopedNC("HandleNPCAnimations", 0xFF2020);
AnimationSystem::AnimationNodeStateMachine
*state_machine = anim.mAnimationSystem->get<
AnimationSystem::
@@ -341,9 +343,9 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
.without<CharacterControlDisable>()
.each([](flecs::entity e, const Input &input,
const CharacterBase &ch, AnimationControl &anim) {
if (!anim.configured)
return;
ZoneScopedN("HandlePlayerAnimations");
if (!anim.configured)
return;
AnimationSystem::AnimationNodeStateMachine
*state_machine = anim.mAnimationSystem->get<
AnimationSystem::
@@ -537,6 +539,7 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
int operator()(const std::vector<GameWorld::Parameter *> &args)
override
{
ZoneScoped;
GameWorld::ValueParameter<flecs::entity> *param_e =
static_cast<GameWorld::ValueParameter<
flecs::entity> *>(args[0]);

View File

@@ -15,6 +15,7 @@ namespace ECS
{
void createNPCActionNodes(flecs::entity town, int index)
{
ZoneScoped;
TownNPCs &npcs = town.get_mut<TownNPCs>();
TownNPCs::NPCData &npc = npcs.npcs.at(index);
flecs::entity e = npc.e;
@@ -167,6 +168,7 @@ flecs::entity
CharacterManagerModule::createPlayer(const Ogre::Vector3 &position,
const Ogre::Quaternion &rotation)
{
ZoneScoped;
static int count = 0;
OgreAssert(count == 0, "overspawn");
OgreAssert(!player.is_valid(), "Player already created");
@@ -186,6 +188,7 @@ CharacterManagerModule::createCharacterData(const Ogre::String model,
const Ogre::Vector3 &position,
const Ogre::Quaternion &rotation)
{
ZoneScoped;
flecs::entity e = ECS::get().entity();
ECS::get_mut<CharacterModule>().createCharacter(e, position, rotation,
model);
@@ -195,6 +198,7 @@ CharacterManagerModule::createCharacterData(const Ogre::String model,
void CharacterManagerModule::registerTownCharacters(flecs::entity town)
{
ZoneScoped;
Ogre::MeshManager::getSingleton().load("normal-male.glb", "General");
Ogre::MeshManager::getSingleton().load("normal-female.glb", "General");
Ogre::String props = StaticGeometryModule::getItemProperties(town);

View File

@@ -14,12 +14,14 @@ namespace ECS
{
CharacterModule::CharacterModule(flecs::world &ecs)
{
ZoneScoped;
struct TriggerPhysicsChange {};
ecs.module<CharacterModule>();
ecs.component<Character>();
ecs.component<Player>();
ecs.component<CharacterBase>()
.on_remove([this](flecs::entity e, CharacterBase &ch) {
ZoneScoped;
// FIXME: clean up data
if (characterEntities.find(e) !=
characterEntities.end() ||
@@ -31,6 +33,7 @@ CharacterModule::CharacterModule(flecs::world &ecs)
})
.on_add([this](flecs::entity e, CharacterBase &ch) {
if (characterNodes.find(e) == characterNodes.end()) {
ZoneScoped;
OgreAssert(characterModels.find(e) !=
characterModels.end(),
"no model set");
@@ -61,6 +64,7 @@ CharacterModule::CharacterModule(flecs::world &ecs)
ecs.component<CharacterGravity>();
ecs.component<CharacterLocation>().on_set(
[this](flecs::entity e, CharacterLocation &loc) {
ZoneScoped;
characterOrientations[e] = loc.orientation;
characterPositions[e] = loc.position;
ECS::modified<CharacterModule>();
@@ -145,19 +149,22 @@ CharacterModule::CharacterModule(flecs::world &ecs)
else
input.fast = false;
input.control_prev = input.control;
float a = 0, b = 0, c = 0;
if (input.mouse_moved) {
updateCameraGoal(camera, -0.18f * input.mouse.x,
-0.12f * input.mouse.y, 0);
a += -0.18f * input.mouse.x;
b += -0.12f * input.mouse.y;
input.mouse_moved = false;
input.mouse.x = 0;
input.mouse.y = 0;
}
updateCameraGoal(camera, a, b, c);
}
if (input.wheel_moved) {
updateCameraGoal(camera, 0, 0,
-0.15f * input.wheel_y);
c += -0.15f * input.wheel_y;
input.wheel_moved = false;
input.wheel_y = 0;
}
updateCameraGoal(camera, a, b, c);
}
ECS::get().modified<ECS::Input>();
});
#define TURN_SPEED 500.0f // character turning in degrees per second
@@ -400,6 +407,7 @@ void CharacterModule::updateCameraGoal(Camera &camera, Ogre::Real deltaYaw,
Ogre::Real deltaPitch,
Ogre::Real deltaZoom)
{
ZoneScoped;
static float canonDist = 0;
camera.mCameraPivot->yaw(Ogre::Degree(deltaYaw), Ogre::Node::TS_PARENT);
if (!(camera.mPivotPitch + deltaPitch > 25 && deltaPitch > 0) &&
@@ -458,6 +466,7 @@ void applyWeightBasedScale(Ogre::Entity *ent,
const Ogre::String &targetBoneName,
const Ogre::Vector3 &scale)
{
ZoneScoped;
Ogre::MeshPtr mesh = ent->getMesh();
Ogre::SkeletonInstance *skel = ent->getSkeleton();
Ogre::Bone *targetBone = skel->getBone(targetBoneName);
@@ -545,6 +554,7 @@ void CharacterModule::createCharacter(flecs::entity e,
const Ogre::Quaternion &rotation,
const Ogre::String model)
{
ZoneScoped;
if (e.has<CharacterBase>() || e.has<AnimationControl>())
return;
if (characterNodes.find(e) != characterNodes.end())

View File

@@ -5,6 +5,7 @@
#include "LuaData.h"
#include "EventModule.h"
#include "EventTriggerModule.h"
#include <tracy/Tracy.hpp>
struct TriggerBody {
void *data;
@@ -77,6 +78,7 @@ ECS::EventTriggerModule::EventTriggerModule(flecs::world &ecs)
.event(flecs::OnSet)
.each([](flecs::entity e, const EngineData &eng,
const EventTrigger &trigger) {
ZoneScoped;
e.set<EventTriggerData>({});
e.set<EventData>({});
});
@@ -84,13 +86,15 @@ ECS::EventTriggerModule::EventTriggerModule(flecs::world &ecs)
.event(flecs::OnSet)
.each([](flecs::entity e, const EventTrigger &trigger,
EventData &evt) {
evt.add(e, "actuator_created", e, e);
ZoneScoped;
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() &&
ZoneScoped;
if (e.parent().is_valid() &&
e.parent().has<EventData>()) {
bool added = false;
for (auto ev : evt.events) {

View File

@@ -47,6 +47,7 @@ struct GUIListener : public Ogre::RenderTargetListener {
GUIListener()
: Ogre::RenderTargetListener()
{
ZoneScoped;
_midFont = createFont("midFont", "General",
"Jupiteroid-Regular.ttf", 24.0f);
_smallFont = createFont("smallFont", "General",
@@ -67,7 +68,8 @@ struct GUIListener : public Ogre::RenderTargetListener {
const Ogre::String &group,
const Ogre::String &ttfname, float fontSize)
{
Ogre::FontPtr ret =
ZoneScoped;
Ogre::FontPtr ret =
Ogre::FontManager::getSingleton().create(name, group);
ret->setType(Ogre::FontType::FT_TRUETYPE);
ret->setSource(ttfname);
@@ -85,6 +87,7 @@ struct GUIListener : public Ogre::RenderTargetListener {
}
void buttons_panel()
{
ZoneScoped;
bool enableDebugRender = ECS::get<EngineData>().enableDbgDraw;
ImVec2 size = ImGui::GetMainViewport()->Size;
float window_width = size.x * 0.2f;
@@ -122,7 +125,8 @@ struct GUIListener : public Ogre::RenderTargetListener {
}
void create_entity_node(const Ogre::String &name, int key)
{
Ogre::Entity *ent =
ZoneScoped;
Ogre::Entity *ent =
ECS::get().get<EngineData>().mScnMgr->createEntity(
name);
Ogre::SceneNode *pnode =
@@ -149,7 +153,8 @@ struct GUIListener : public Ogre::RenderTargetListener {
}
void buildings_editor()
{
int i;
ZoneScoped;
int i;
ImVec2 size = ImGui::GetMainViewport()->Size;
float window_width = size.x * 0.2f;
if (window_width > panel_width)
@@ -176,7 +181,8 @@ struct GUIListener : public Ogre::RenderTargetListener {
}
void position_editor(Ogre::SceneNode *node)
{
Ogre::Vector3 position = node->getPosition();
ZoneScoped;
Ogre::Vector3 position = node->getPosition();
float v[3] = { position.x, position.y, position.z };
ImGui::InputFloat3("position", v);
position.x = v[0];
@@ -186,7 +192,8 @@ struct GUIListener : public Ogre::RenderTargetListener {
}
void orientation_editor(Ogre::SceneNode *node)
{
Ogre::Quaternion q = node->getOrientation();
ZoneScoped;
Ogre::Quaternion q = node->getOrientation();
float yaw = Ogre::Radian(q.getYaw()).valueDegrees();
float pitch = Ogre::Radian(q.getPitch()).valueDegrees();
float roll = Ogre::Radian(q.getRoll()).valueDegrees();
@@ -205,7 +212,8 @@ struct GUIListener : public Ogre::RenderTargetListener {
}
void attachments_editor(Ogre::SceneNode *node)
{
const Ogre::SceneNode::ObjectMap &pmap =
ZoneScoped;
const Ogre::SceneNode::ObjectMap &pmap =
node->getAttachedObjects();
int i;
for (i = 0; i < pmap.size(); i++) {
@@ -219,6 +227,7 @@ struct GUIListener : public Ogre::RenderTargetListener {
}
Ogre::Vector2 projectToScreen(const Ogre::Vector3 &worldPoint)
{
ZoneScoped;
ImVec2 size = ImGui::GetMainViewport()->Size;
float width = size.x;
float height = size.y;
@@ -243,7 +252,8 @@ struct GUIListener : public Ogre::RenderTargetListener {
}
void preview(const Ogre::RenderTargetViewportEvent &evt)
{
int i;
ZoneScoped;
int i;
Ogre::ImGuiOverlay::NewFrame();
if (ECS::get().get<EngineData>().startupDelay > 0.0f &&
@@ -744,6 +754,7 @@ GUIModule::GUIModule(flecs::world &ecs)
void GUIModule::configure()
{
ZoneScoped;
ECS::get().set<GUIData>({ nullptr, {}, nullptr });
const RenderWindow &window = ECS::get<RenderWindow>();
GUIData &gui = ECS::get_mut<GUIData>();

View File

@@ -35,6 +35,7 @@ namespace ECS
static flecs::world ecs;
void setup_minimal()
{
ZoneScoped;
ecs.component<EngineData>().add(flecs::Singleton);
ecs.component<GameData>().add(flecs::Singleton);
ecs.component<Input>().add(flecs::Singleton);
@@ -51,6 +52,7 @@ void setup_minimal()
void setupExteriorScene(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
Ogre::Camera *camera, Ogre::RenderWindow *window)
{
ZoneScoped;
std::cout << "Setup GameData\n";
setup_minimal();
@@ -93,19 +95,19 @@ void setupExteriorScene(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
std::cout << "ground check ready\n";
#endif
});
ecs.system<EngineData>("CheckStatus")
#ifdef VDEBUG
ecs.system<EngineData>("CheckStatus")
.kind(flecs::OnUpdate)
.run([](flecs::iter &it) {
#ifdef VDEBUG
if (ECS::get().has<WaterReady>())
std::cout << "water ready\n";
if (ECS::get().has<TerrainReady>())
std::cout << "terrain ready\n";
if (ECS::get().has<GroundCheckReady>())
std::cout << "ground check ready\n";
#endif
});
ecs.set<EngineData>({ scnMgr, 0.0f, 5.0f, (int)window->getWidth(),
#endif
ecs.set<EngineData>({ scnMgr, 0.0f, 5.0f, (int)window->getWidth(),
(int)window->getHeight(), false });
ecs.set<Camera>({ cameraNode, camera, false });
ecs.add<GameData>();
@@ -113,6 +115,7 @@ void setupExteriorScene(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
ecs.observer<GameState>("Game_Start_Scen_Startup")
.event(flecs::OnAdd)
.each([](GameState &game) {
ZoneScopedN("Game_Start_Scen_Startup");
ECS::get().add<WaterSurface>();
ECS::get().set<Sun>(
{ nullptr, nullptr, nullptr, nullptr });
@@ -137,6 +140,7 @@ void setupExteriorScene(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
.kind(flecs::OnUpdate)
.interval(0.5f)
.each([&](Terrain &mterrain, GameState &game) {
ZoneScopedN("SpawnPlayer");
flecs::entity player =
ECS::get<CharacterManagerModule>().getPlayer();
if (!player.is_valid()) {
@@ -183,6 +187,7 @@ void setupExteriorScene(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
.kind(flecs::OnUpdate)
.interval(0.5f)
.each([&](GameState &game) {
ZoneScopedN("NewHame");
flecs::entity player =
ECS::get<CharacterManagerModule>()
.getPlayer();
@@ -211,6 +216,7 @@ void setupInventoryScene(Ogre::SceneManager *scnMgr,
void setupEditor(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
Ogre::Camera *camera, Ogre::RenderWindow *window)
{
ZoneScoped;
setup_minimal();
ecs.component<RenderWindow>().add(flecs::Singleton);
ecs.component<EditorSceneSwitch>().add(flecs::Singleton);
@@ -246,19 +252,19 @@ void setupEditor(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
std::cout << "ground check ready\n";
#endif
});
ecs.system<EngineData>("CheckStatus")
#ifdef VDEBUG
ecs.system<EngineData>("CheckStatus")
.kind(flecs::OnUpdate)
.run([](flecs::iter &it) {
#ifdef VDEBUG
if (ECS::get().has<WaterReady>())
std::cout << "water ready\n";
if (ECS::get().has<TerrainReady>())
std::cout << "terrain ready\n";
if (ECS::get().has<GroundCheckReady>())
std::cout << "ground check ready\n";
#endif
});
ecs.set<EngineData>({ scnMgr, 0.0f, 5.0f, (int)window->getWidth(),
#endif
ecs.set<EngineData>({ scnMgr, 0.0f, 5.0f, (int)window->getWidth(),
(int)window->getHeight(), false });
ecs.set<Camera>({ cameraNode, camera, false });
#if 0
@@ -288,7 +294,7 @@ void setupEditor(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
void update(float delta)
{
{
ZoneScoped;
ZoneScopedN("ECS");
ecs.progress(delta);
}
}

View File

@@ -35,6 +35,7 @@ struct TriggerBody {
};
PhysicsModule::PhysicsModule(flecs::world &ecs)
{
ZoneScoped;
ecs.module<PhysicsModule>();
ecs.import <EventModule>();
ecs.import <EventTriggerModule>();
@@ -75,7 +76,7 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
ecs.system<EngineData, Physics>("physics_update")
.kind(PhysicsUpdate)
.each([&](EngineData &e, Physics &ph) {
ZoneScopedN("physics");
ZoneScopedN("physics_update");
ph.physics->update(e.delta);
});
ecs.observer<const EngineData, PhysicsMeshName>(
@@ -86,6 +87,7 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
.write<PhysicsShape>()
.each([&](flecs::entity e, const EngineData &eng,
PhysicsMeshName &name) {
ZoneScopedN("create_shape_mesh_name");
Ogre::DefaultHardwareBufferManagerBase dmgr;
Ogre::MeshPtr mesh =
Ogre::MeshManager::getSingleton().getByName(
@@ -106,7 +108,8 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
.write<PhysicsShape>()
.each([&](flecs::entity e, const EngineData &eng,
PhysicsMeshPtr &meshPtr) {
Ogre::DefaultHardwareBufferManager dmgr;
ZoneScopedN("create_shape_mesh_ptr");
Ogre::DefaultHardwareBufferManager dmgr;
Ogre::MeshPtr mesh = meshPtr.mesh;
if (!mesh->isLoaded()) {
mesh->setHardwareBufferManager(&dmgr);
@@ -127,7 +130,8 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
.write<PhysicsShape>()
.each([&](flecs::entity e, const EngineData &eng,
PhysicsHeightfieldData &hfd) {
JPH::ShapeRefC shape =
ZoneScopedN("create_shape_heightfield");
JPH::ShapeRefC shape =
JoltPhysicsWrapper::getSingleton()
.createHeightfieldShape(
hfd.samples, hfd.offset,
@@ -148,7 +152,8 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
.each([&](flecs::entity e, const EngineData &eng,
const PhysicsShape &shape, const PhysicsNode &node,
const PhysicsBody &body) {
JPH::BodyID id =
ZoneScopedN("create_body_from_shape");
JPH::BodyID id =
JoltPhysicsWrapper::getSingleton().createBody(
shape.shape.GetPtr(), 0.0f, node.node,
(JPH::EMotionType)body.motion,
@@ -161,7 +166,8 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
ecs.observer<const JPH::BodyID>("remove_body")
.event(flecs::OnRemove)
.each([&](flecs::entity e, const JPH::BodyID &id) {
JoltPhysicsWrapper::getSingleton().removeBody(id);
ZoneScopedN("remove_body");
JoltPhysicsWrapper::getSingleton().removeBody(id);
if (e.has<CharacterBase>() || e.has<Character>())
return;
if (JoltPhysicsWrapper::getSingleton().bodyIsCharacter(
@@ -199,7 +205,8 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
.without<JPH::BodyID>()
.each([](flecs::entity e, const EngineData &eng,
const EventTrigger &trigger) {
JPH::ShapeRefC shape =
ZoneScopedN("CreateTriggerPhysics");
JPH::ShapeRefC shape =
JoltPhysicsWrapper::getSingleton()
.createCylinderShape(trigger.halfheight,
trigger.radius);
@@ -621,6 +628,7 @@ flecs::entity PhysicsModule::createTerrainChunkBody(Ogre::SceneNode *node,
const Ogre::Vector3 &scale,
int sampleCount)
{
ZoneScoped;
flecs::entity e = ECS::get().entity();
e.set<PhysicsHeightfieldData>({ samples, offset, scale, sampleCount });
e.set<PhysicsBody>({ (uint32_t)JPH::EMotionType::Static,
@@ -631,6 +639,7 @@ flecs::entity PhysicsModule::createTerrainChunkBody(Ogre::SceneNode *node,
}
void PhysicsModule::controlPhysics(flecs::entity e, bool enable)
{
ZoneScoped;
if (enable) {
if (e.has<CharacterBase>()) {
e.remove<CharacterDisablePhysics>();
@@ -678,6 +687,7 @@ bool PhysicsModule::raycastQuery(const Ogre::Vector3 &startPos,
const Ogre::Vector3 &endPos,
Ogre::Vector3 &position, JPH::BodyID &id)
{
ZoneScoped;
return JoltPhysicsWrapper::getSingleton().raycastQuery(startPos, endPos,
position, id);
}
@@ -689,6 +699,7 @@ void PhysicsModule::setDebugDraw(bool enable)
bool WaterBody::isInWater(const JPH::BodyID &id) const
{
ZoneScoped;
#if 0
flecs::entity e =
ECS::get().query_builder<const JPH::BodyID>().build().find(

View File

@@ -71,16 +71,19 @@ struct TestNarrativeHandler : GUI::NarrationHandler {
}
void finish() override
{
ZoneScoped;
_clear_narration();
}
void activate() override
{
ZoneScoped;
_narration("Greetings...", {});
std::cout << getPropsJSON().dump(4) << std::endl;
count = 0;
}
void event(const Ogre::String &evt) override
{
ZoneScoped;
if (evt == "narration_progress" ||
evt == "narration_answered") {
count++;
@@ -112,6 +115,7 @@ struct LuaNarrationHandler : GUI::NarrationHandler {
: ref(ref)
, L(L)
{
ZoneScoped;
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
lua_pushlightuserdata(L, this);
lua_pushcclosure(
@@ -215,6 +219,7 @@ struct LuaNarrationHandler : GUI::NarrationHandler {
}
void finish() override
{
ZoneScoped;
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
int type = lua_getfield(L, -1, "finish");
OgreAssert(type == LUA_TFUNCTION, "bad finish()");
@@ -228,6 +233,7 @@ struct LuaNarrationHandler : GUI::NarrationHandler {
}
void activate() override
{
ZoneScoped;
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
int type = lua_getfield(L, -1, "activate");
OgreAssert(type == LUA_TFUNCTION, "bad activate()");
@@ -240,6 +246,7 @@ struct LuaNarrationHandler : GUI::NarrationHandler {
}
void event(const Ogre::String &evt) override
{
ZoneScoped;
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
int type = lua_getfield(L, -1, "event");
OgreAssert(type == LUA_TFUNCTION, "bad event()");
@@ -257,6 +264,7 @@ struct SimpleWordHandler : PlayerActionModule::ActionWordHandler {
void operator()(int actor, flecs::entity town, int index,
const Ogre::String &word, int actionNode) override
{
ZoneScoped;
if (index >= 0) {
TestNarrativeHandler *handle =
OGRE_NEW TestNarrativeHandler();
@@ -281,10 +289,12 @@ struct SimpleWordHandler : PlayerActionModule::ActionWordHandler {
PlayerActionModule::PlayerActionModule(flecs::world &ecs)
{
ZoneScoped;
ecs.module<PlayerActionModule>();
ecs.import <CharacterManagerModule>();
ecs.component<ActionNodeList>()
.on_add([](flecs::entity e, ActionNodeList &alist) {
ZoneScoped;
alist.nodeMutex = std::make_shared<std::mutex>();
alist.setDirty();
alist.nodes.reserve(1000);
@@ -296,9 +306,9 @@ PlayerActionModule::PlayerActionModule(flecs::world &ecs)
ecs.system<ActionNodeList>("updateNodeList")
.kind(flecs::OnUpdate)
.each([](ActionNodeList &list) {
ZoneScopedN("updateNodeList");
if (list.isBusy())
return;
ZoneScopedN("updateNodeList");
if (list.nodes.size() > 0) {
Ogre::SceneNode *cameraNode =
ECS::get<Camera>().mCameraNode;
@@ -321,8 +331,8 @@ PlayerActionModule::PlayerActionModule(flecs::world &ecs)
ecs.system<ActionNodeList, const Input>("ActivateActionNode")
.kind(flecs::OnUpdate)
.each([this](ActionNodeList &list, const Input &input) {
std::lock_guard<std::mutex> lock(*list.nodeMutex);
ZoneScopedN("ActivateActionNode");
std::lock_guard<std::mutex> lock(*list.nodeMutex);
if (input.control & 32)
std::cout << "act pressed" << std::endl;
if (list.isBusy())
@@ -384,12 +394,14 @@ PlayerActionModule::PlayerActionModule(flecs::world &ecs)
void PlayerActionModule::addWordHandler(const Ogre::String &word,
ActionWordHandler *handler)
{
ZoneScoped;
actionWords.insert({ word, handler });
}
void PlayerActionModule::removeWordHandler(const Ogre::String &word,
ActionWordHandler *handler)
{
ZoneScoped;
for (auto it = actionWords.begin(); it != actionWords.end();) {
if (it->first == word && it->second == handler)
it = actionWords.erase(it);
@@ -422,6 +434,7 @@ struct TestActivatedWordHandler : PlayerActionModule::ActivatedWordHandler {
, state(0)
, delay(0)
{
ZoneScoped;
activeActors.insert(actor);
// dynamic nodes can disappear on us so to avoid that use a copy
anode = ECS::get<ActionNodeList>().dynamicNodes[actionNode];
@@ -454,6 +467,7 @@ out:;
}
void teleport(const Ogre::String &place)
{
ZoneScoped;
if (placeLocalOffset.find(place) == placeLocalOffset.end())
return;
std::cout << "local offset: " << placeLocalOffset[place]
@@ -480,6 +494,7 @@ out:;
}
int update(float delta)
{
ZoneScoped;
switch (state) {
case 0:
if (ECS::get<Input>().act)
@@ -583,6 +598,7 @@ out:;
}
void enter()
{
ZoneScoped;
delay = 0.0f;
state = 0;
ECS::get_mut<GUI>().enableActions = false;
@@ -591,6 +607,7 @@ out:;
}
void exit(int result)
{
ZoneScoped;
ch.remove<CharacterInActuator>();
ch.remove<CharacterControlDisable>();
PhysicsModule::controlPhysics(ch, true);
@@ -603,6 +620,7 @@ out:;
}
virtual ~TestActivatedWordHandler()
{
ZoneScoped;
activeActors.erase(actor);
}
};
@@ -613,6 +631,7 @@ struct LuaWordHandler : PlayerActionModule::ActionWordHandler {
void operator()(int actor, flecs::entity town, int index,
const Ogre::String &word, int actionNode) override
{
ZoneScoped;
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
if (lua_type(L, -1) == LUA_TFUNCTION) {
luaL_checktype(L, -1, LUA_TFUNCTION);
@@ -666,6 +685,7 @@ struct LuaWordHandler : PlayerActionModule::ActionWordHandler {
void PlayerActionModule::addLuaWordHandler(const Ogre::String &word,
lua_State *L, int ref)
{
ZoneScoped;
struct LuaWordHandler *handler = OGRE_NEW LuaWordHandler;
handler->L = L;
handler->ref = ref;
@@ -675,6 +695,7 @@ void PlayerActionModule::addLuaWordHandler(const Ogre::String &word,
void PlayerActionModule::removeLuaWordHandler(const Ogre::String &word,
lua_State *L, int ref)
{
ZoneScoped;
for (auto it = actionWords.begin(); it != actionWords.end();) {
LuaWordHandler *handler =
static_cast<LuaWordHandler *>(it->second);
@@ -687,6 +708,7 @@ void PlayerActionModule::removeLuaWordHandler(const Ogre::String &word,
int PlayerActionModule::setupLuaActionHandler(lua_State *L)
{
ZoneScoped;
luaL_checktype(L, 1, LUA_TSTRING);
if (lua_type(L, 2) == LUA_TFUNCTION) {
luaL_checktype(L, 2, LUA_TFUNCTION);
@@ -707,6 +729,7 @@ int PlayerActionModule::setupLuaActionHandler(lua_State *L)
void PlayerActionModule::addActivatedWordHandler(const Ogre::String &word,
ActivatedWordHandler *handler)
{
ZoneScoped;
for (auto it = activatedWords.begin(); it != activatedWords.end();
it++) {
}
@@ -716,6 +739,7 @@ void PlayerActionModule::addActivatedWordHandler(const Ogre::String &word,
void PlayerActionModule::removeActivatedWordHandler(
const Ogre::String &word, ActivatedWordHandler *handler)
{
ZoneScoped;
for (auto it = activatedWords.begin(); it != activatedWords.end();) {
if (it->first == word && it->second == handler)
it = activatedWords.erase(it);
@@ -726,24 +750,36 @@ void PlayerActionModule::removeActivatedWordHandler(
void ActionNodeList::updateDynamicNodes()
{
ZoneScoped;
std::lock_guard<std::mutex> lock(*nodeMutex);
if (dynamicNodes.size() > nodes.size())
dynamicNodes.resize(nodes.size());
else {
dynamicNodes.clear();
dynamicNodes.insert(dynamicNodes.end(), nodes.begin(),
nodes.end());
{
ZoneScopedN("static");
ZoneTextF("before: dynamicNodes: %d nodes: %d",
(int)dynamicNodes.size(), (int)nodes.size());
// Do not constantly re-create static nodes
if (dynamicNodes.size() > nodes.size())
dynamicNodes.resize(nodes.size());
else if (dynamicNodes.size() < nodes.size()) {
dynamicNodes.clear();
dynamicNodes.insert(dynamicNodes.end(), nodes.begin(),
nodes.end());
ZoneTextF("updated: dynamicNodes: %d nodes: %d",
(int)dynamicNodes.size(), (int)nodes.size());
}
}
{
ZoneScopedN("dynamic");
ECS::get().query_builder<const TownNPCs>().each(
[this](flecs::entity town, const TownNPCs &npcs) {
for (auto it = npcs.npcs.begin();
it != npcs.npcs.end(); it++) {
dynamicNodes.insert(
dynamicNodes.end(),
it->second.actionNodes.begin(),
it->second.actionNodes.end());
}
});
}
ECS::get().query_builder<const TownNPCs>().each(
[this](flecs::entity town, const TownNPCs &npcs) {
for (auto it = npcs.npcs.begin(); it != npcs.npcs.end();
it++) {
dynamicNodes.insert(
dynamicNodes.end(),
it->second.actionNodes.begin(),
it->second.actionNodes.end());
}
});
dirty = true;
}
@@ -760,6 +796,7 @@ bool ActionNodeList::_query(const Ogre::Vector3 &position,
std::vector<size_t> &points,
std::vector<float> &distances)
{
ZoneScoped;
std::vector<size_t> tmppoints;
std::vector<float> tmpdistances;
points.clear();
@@ -789,6 +826,7 @@ bool ActionNodeList::query_ai(const Ogre::Vector3 &position, float distance,
std::vector<size_t> &points,
std::vector<float> &distances)
{
ZoneScoped;
std::lock_guard<std::mutex> lock(*nodeMutex);
std::vector<size_t> tmppoints;
std::vector<float> tmpdistances;
@@ -817,6 +855,7 @@ bool ActionNodeList::query_ai(const Ogre::Vector3 &position, float distance,
int ActionNodeList::addNode(ActionNode &node)
{
ZoneScoped;
std::lock_guard<std::mutex> lock(*nodeMutex);
int index = nodes.size();
nodes.push_back(node);
@@ -826,6 +865,7 @@ int ActionNodeList::addNode(ActionNode &node)
void ActionNodeList::removeNode(int index)
{
ZoneScoped;
std::lock_guard<std::mutex> lock(*nodeMutex);
nodes.erase(nodes.begin() + index);
dirty = true;
@@ -833,12 +873,14 @@ void ActionNodeList::removeNode(int index)
const ActionNodeList::UIData &ActionNodeList::getUIData()
{
ZoneScoped;
std::lock_guard<std::mutex> lock(*uidata.mutex);
return uidata;
}
void ActionNodeList::setUISelected(int selected)
{
ZoneScoped;
std::lock_guard<std::mutex> lock(*uidata.mutex);
uidata.selected = selected;
@@ -847,6 +889,7 @@ void ActionNodeList::setUISelected(int selected)
void ActionNodeList::setUIPoints(const std::vector<size_t> &points,
const std::vector<float> &distances)
{
ZoneScoped;
std::lock_guard<std::mutex> lock(*uidata.mutex);
uidata.points = points;
uidata.distances = distances;
@@ -854,6 +897,7 @@ void ActionNodeList::setUIPoints(const std::vector<size_t> &points,
void ActionNodeList::UIquery(const Ogre::Vector3 &position)
{
ZoneScoped;
bool needBuild = false;
{

View File

@@ -3,16 +3,21 @@
#include "GameData.h"
#include "GUIModuleCommon.h"
#include "QuestModule.h"
#include <tracy/Tracy.hpp>
namespace ECS
{
QuestModule::QuestModule(flecs::world &ecs)
{
ZoneScoped;
ecs.module<QuestModule>();
ecs.observer<GameState>("EnableQuests")
.event(flecs::OnAdd)
.each([this](GameState &game) {
ZoneScoped;
if (quest_update.is_valid())
return;
quest_update =
ECS::get()
.system<const EngineData>(
@@ -28,6 +33,7 @@ QuestModule::QuestModule(flecs::world &ecs)
ecs.observer<GameState>("DisableQuests")
.event(flecs::OnRemove)
.each([this](GameState &game) {
ZoneScoped;
if (quest_update.is_valid())
quest_update.destruct();
});
@@ -35,11 +41,13 @@ QuestModule::QuestModule(flecs::world &ecs)
void QuestModule::addQuest(Quest *quest)
{
ZoneScoped;
quests.insert(quest);
}
void QuestModule::removeQuest(Quest *quest)
{
ZoneScoped;
quests.erase(quests.find(quest));
}
struct LuaNarrationHandler : GUI::NarrationHandler {
@@ -49,6 +57,7 @@ struct LuaNarrationHandler : GUI::NarrationHandler {
: ref(ref)
, L(L)
{
ZoneScoped;
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
lua_pushlightuserdata(L, this);
lua_pushcclosure(
@@ -125,6 +134,7 @@ struct LuaNarrationHandler : GUI::NarrationHandler {
}
void finish() override
{
ZoneScoped;
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
int type = lua_getfield(L, -1, "finish");
OgreAssert(type == LUA_TFUNCTION, "bad finish()");
@@ -138,6 +148,7 @@ struct LuaNarrationHandler : GUI::NarrationHandler {
}
void activate() override
{
ZoneScoped;
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
int type = lua_getfield(L, -1, "activate");
OgreAssert(type == LUA_TFUNCTION, "bad activate()");
@@ -150,6 +161,7 @@ struct LuaNarrationHandler : GUI::NarrationHandler {
}
void event(const Ogre::String &evt) override
{
ZoneScoped;
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
int type = lua_getfield(L, -1, "event");
OgreAssert(type == LUA_TFUNCTION, "bad event()");
@@ -171,6 +183,7 @@ struct LuaQuest : QuestModule::Quest {
, L(L)
, ref(ref)
{
ZoneScoped;
OgreAssert(L, "bad Lua state");
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
lua_pushlightuserdata(L, this);
@@ -206,6 +219,7 @@ struct LuaQuest : QuestModule::Quest {
}
void finish(int rc) override
{
ZoneScoped;
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
int type = lua_getfield(L, -1, "finish");
OgreAssert(type == LUA_TFUNCTION, "bad finish()");
@@ -219,6 +233,7 @@ struct LuaQuest : QuestModule::Quest {
}
void activate() override
{
ZoneScoped;
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
int type = lua_getfield(L, -1, "activate");
OgreAssert(type == LUA_TFUNCTION, "bad activate()");
@@ -231,6 +246,7 @@ struct LuaQuest : QuestModule::Quest {
}
void event(const Ogre::String &evt) override
{
ZoneScoped;
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
int type = lua_getfield(L, -1, "event");
OgreAssert(type == LUA_TFUNCTION, "bad event()");
@@ -244,6 +260,7 @@ struct LuaQuest : QuestModule::Quest {
}
int update(float delta) override
{
ZoneScoped;
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
int type = lua_getfield(L, -1, "finish");
OgreAssert(type == LUA_TFUNCTION, "bad finish()");
@@ -263,6 +280,7 @@ struct LuaQuest : QuestModule::Quest {
void QuestModule::addLuaQuest(lua_State *L)
{
ZoneScoped;
luaL_checktype(L, 1, LUA_TSTRING);
luaL_checktype(L, 2, LUA_TTABLE);
Ogre::String name = lua_tostring(L, 1);
@@ -274,12 +292,14 @@ void QuestModule::addLuaQuest(lua_State *L)
void QuestModule::Quest::_activate()
{
ZoneScoped;
activate();
active = true;
}
void QuestModule::Quest::_finish(int rc)
{
ZoneScoped;
finish(rc);
active = false;
if (rc == OK)
@@ -301,6 +321,7 @@ QuestModule::Quest::~Quest()
int QuestModule::Quest::_update(float delta)
{
ZoneScoped;
if (!active && !_can_activate())
return ERROR;
if (!active)
@@ -320,6 +341,7 @@ int QuestModule::Quest::_update(float delta)
void QuestModule::Quest::_event(const std::string &evt)
{
ZoneScoped;
event(evt);
}

View File

@@ -6,11 +6,13 @@
#include "WaterModule.h"
#include "BoatModule.h"
#include "SlotsModule.h"
#include <tracy/Tracy.hpp>
namespace ECS
{
SlotsModule::SlotsModule(flecs::world &ecs)
{
ecs.module<SlotsModule>();
ZoneScoped;
ecs.module<SlotsModule>();
ecs.import <CharacterModule>();
ecs.component<ParentSlot>();
ecs.component<ParentSlotData>();
@@ -20,7 +22,10 @@ SlotsModule::SlotsModule(flecs::world &ecs)
ecs.observer<const EngineData, const BoatBase>("CreateBoatSlots")
.event(flecs::OnSet)
.each([&](flecs::entity e, const EngineData &eng,
const BoatBase &boat) { createBoatSlots(e); });
const BoatBase &boat) {
ZoneScoped;
createBoatSlots(e);
});
#if 1
ecs.system<const EngineData, const CharacterBase, ParentSlot>(
"UpdateSlotData")
@@ -29,6 +34,7 @@ SlotsModule::SlotsModule(flecs::world &ecs)
.without<ParentSlotData>()
.each([&](flecs::entity e, const EngineData &eng,
const CharacterBase &ch, ParentSlot &slot) {
ZoneScoped;
if (slot.slot_name == "") {
slot.removeSlot(e);
return;
@@ -77,7 +83,8 @@ SlotsModule::SlotsModule(flecs::world &ecs)
}
void SlotsModule::createBoatSlots(flecs::entity e)
{
const EngineData &eng = e.world().get<EngineData>();
ZoneScoped;
const EngineData &eng = e.world().get<EngineData>();
const BoatBase &boat = e.get<BoatBase>();
int i;
std::vector<Ogre::Node *> slots = boat.mNode->getChildren();
@@ -115,7 +122,8 @@ void SlotsModule::createBoatSlots(flecs::entity e)
}
void ParentSlot::createSlot(flecs::entity e)
{
if (e.has<CharacterBase>()) {
ZoneScoped;
if (e.has<CharacterBase>()) {
createCharacterSlot(e);
}
}
@@ -124,14 +132,16 @@ void ParentSlot::createCharacterSlot(flecs::entity e)
}
void ParentSlot::removeSlot(flecs::entity e)
{
if (e.has<ParentSlot>())
ZoneScoped;
if (e.has<ParentSlot>())
e.remove<ParentSlot>();
if (e.has<ParentSlot>())
e.remove<ParentSlotData>();
}
bool ParentSlot::check() const
{
if (!parent_e.has<ObjectSlots>())
ZoneScoped;
if (!parent_e.has<ObjectSlots>())
return false;
const ObjectSlots &slots = parent_e.get<ObjectSlots>();
if (!slots.exists(slot_name))
@@ -140,13 +150,15 @@ bool ParentSlot::check() const
}
bool ParentSlot::parentIsValid()
{
if (!parent_e.has<ObjectSlots>())
ZoneScoped;
if (!parent_e.has<ObjectSlots>())
return false;
return true;
}
Ogre::SceneNode *ParentSlot::getSlotBase() const
{
if (!check())
ZoneScoped;
if (!check())
return nullptr;
const ObjectSlots &slots = parent_e.get<ObjectSlots>();
Ogre::SceneNode *slot_base = slots.slots.at(slot_name).second;
@@ -154,7 +166,8 @@ Ogre::SceneNode *ParentSlot::getSlotBase() const
}
void ParentSlot::addChild(Ogre::SceneNode *childNode)
{
Ogre::SceneNode *parentNode = getSlotBase();
ZoneScoped;
Ogre::SceneNode *parentNode = getSlotBase();
if (childNode->getParentSceneNode())
childNode->getParentSceneNode()->removeChild(childNode);
parentNode->addChild(childNode);
@@ -163,7 +176,8 @@ void ParentSlot::addChild(Ogre::SceneNode *childNode)
}
void ParentSlot::createSlotData(flecs::entity e)
{
const ObjectSlots &slots = parent_e.get<ObjectSlots>();
ZoneScoped;
const ObjectSlots &slots = parent_e.get<ObjectSlots>();
ParentSlotData &psdata = e.ensure<ParentSlotData>();
Ogre::SceneNode *slot_base = getSlotBase();
// Ogre::Vector3 position = slot_base->_getDerivedPosition();
@@ -178,6 +192,7 @@ void ParentSlot::createSlotData(flecs::entity e)
}
bool ObjectSlots::exists(const Ogre::String &name) const
{
return slots.find(name) != slots.end();
ZoneScoped;
return slots.find(name) != slots.end();
}
}

View File

@@ -1,10 +1,12 @@
#include "SmartObject.h"
#include <tracy/Tracy.hpp>
namespace ECS
{
SmartObjectModule::SmartObjectModule(flecs::world &ecs)
{
ZoneScoped;
ecs.module<SmartObjectModule>();
ecs.component<SmartObjectManager>().add(flecs::Singleton);
ecs.component<SmartObject>();
}
}
}

View File

@@ -26,12 +26,14 @@ static bool templatesLoaded = false;
static std::list<std::pair<long, long> > addQueue;
StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
{
ZoneScoped;
ecs.module<StaticGeometryModule>();
ecs.component<TerrainSlotParent>();
ecs.component<TerrainItem>();
ecs.component<FurnitureItem>();
ecs.component<FurnitureInstance>()
.on_remove([](flecs::entity e, FurnitureInstance &instance) {
ZoneScoped;
if (instance.furniture) {
instance.furniture
->destroyAllChildrenAndObjects();
@@ -41,6 +43,7 @@ StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
}
})
.on_set([](flecs::entity e, FurnitureInstance &instance) {
ZoneScoped;
if (instance.furniture !=
e.get<FurnitureInstance>().furniture) {
FurnitureInstance &f =
@@ -54,11 +57,13 @@ StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
}
})
.on_add([](flecs::entity e, FurnitureInstance &instance) {
ZoneScoped;
instance.furniture = nullptr;
});
ecs.component<TerrainItemNode>().on_remove([](flecs::entity e,
TerrainItemNode &item) {
if (item.itemNode) {
ZoneScoped;
if (item.itemNode) {
item.itemNode->destroyAllChildrenAndObjects();
item.itemNode->getCreator()->destroySceneNode(
item.itemNode);
@@ -76,7 +81,8 @@ StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
ecs.observer<const Terrain>("LoadTerrainItems")
.event(flecs::OnSet)
.each([&](const Terrain &terrain) {
if (terrain.mTerrainGroup && !itemsLoaded) {
ZoneScopedN("LoadTerrainItems");
if (terrain.mTerrainGroup && !itemsLoaded) {
loadItems();
itemsLoaded = true;
}
@@ -84,7 +90,8 @@ StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
if (!Ogre::MeshLodGenerator::getSingletonPtr())
new Ogre::MeshLodGenerator();
ecs.system("AddGeometryQueue").kind(flecs::OnUpdate).run([&](flecs::iter &it) {
std::list<flecs::entity> items;
ZoneScopedN("AddGeometryQueue");
std::list<flecs::entity> items;
if (!ECS::get().has<Terrain>())
return;
if (!ECS::get<Terrain>().mTerrainGroup)
@@ -143,11 +150,13 @@ StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
}
void StaticGeometryModule::addGeometryForSlot(long x, long y)
{
addQueue.push_back({ x, y });
ZoneScoped;
addQueue.push_back({ x, y });
}
void StaticGeometryModule::removeGeometryForSlot(long x, long y)
{
std::pair<long, long> slot = { x, y };
ZoneScoped;
std::pair<long, long> slot = { x, y };
flecs::entity parent =
ECS::get().query_builder<const TerrainSlotParent>().build().find(
[&slot](const TerrainSlotParent &parent) {
@@ -170,7 +179,8 @@ StaticGeometryModule::createItem(const Ogre::Vector3 &position,
const Ogre::Quaternion &orientation,
const Ogre::String &type)
{
long x, y;
ZoneScoped;
long x, y;
ECS::get<Terrain>().mTerrainGroup->convertWorldPositionToTerrainSlot(
position, &x, &y);
std::pair<long, long> pos{ x, y };
@@ -192,19 +202,22 @@ StaticGeometryModule::createItem(const Ogre::Vector3 &position,
void StaticGeometryModule::setItemProperties(flecs::entity id,
Ogre::String properties)
{
OgreAssert(id.is_valid(), "bad id");
ZoneScoped;
OgreAssert(id.is_valid(), "bad id");
id.get_mut<TerrainItem>().properties = properties;
id.modified<TerrainItem>();
}
const Ogre::String &StaticGeometryModule::getItemProperties(flecs::entity id)
{
OgreAssert(id.is_valid(), "bad id");
ZoneScoped;
OgreAssert(id.is_valid(), "bad id");
return id.get<TerrainItem>().properties;
}
nlohmann::json templates;
void StaticGeometryModule::loadTemplates()
{
ZoneScoped;
if (!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(
"templates.list"))
return;
@@ -221,6 +234,7 @@ void StaticGeometryModule::loadTemplates()
void StaticGeometryModule::saveTemplates()
{
ZoneScoped;
Ogre::String path = "resources/buildings/templates.list";
if (Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(
"templates.list")) {
@@ -243,7 +257,8 @@ void StaticGeometryModule::saveTemplates()
void StaticGeometryModule::saveItems()
{
Ogre::String path = "resources/buildings/items.list";
ZoneScoped;
Ogre::String path = "resources/buildings/items.list";
if (Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(
"items.list")) {
Ogre::String group =
@@ -289,7 +304,8 @@ void StaticGeometryModule::saveItems()
}
void StaticGeometryModule::loadItems()
{
if (!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(
ZoneScoped;
if (!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(
"items.list"))
return;
Ogre::String group = Ogre::ResourceGroupManager::getSingleton()
@@ -363,6 +379,7 @@ void StaticGeometryModule::saveFurniture()
void StaticGeometryModule::loadFurniture()
{
ZoneScoped;
ECS::get().delete_with<FurnitureItem>();
static std::vector<Ogre::String> glb_names;
const std::vector<Ogre::String> &groups =
@@ -406,6 +423,7 @@ void StaticGeometryModule::loadFurniture()
void StaticGeometryModule::getItemPositionPerSlot(
long x, long y, std::list<Ogre::Vector3> *positions)
{
ZoneScoped;
std::pair<long, long> pos{ x, y };
if (!positions)
return;
@@ -426,6 +444,7 @@ void StaticGeometryModule::getItemPositionPerSlot(
}
void StaticGeometryModule::getItemPositions(std::list<Ogre::Vector3> *positions)
{
ZoneScoped;
ECS::get().query_builder<const TerrainItem>().build().each(
[&](flecs::entity e, const TerrainItem &item) {
positions->push_back(item.position);
@@ -434,12 +453,14 @@ void StaticGeometryModule::getItemPositions(std::list<Ogre::Vector3> *positions)
void StaticGeometryModule::getItemPositionAndRotation(
flecs::entity e, Ogre::Vector3 &position, Ogre::Quaternion &orientation)
{
ZoneScoped;
position = e.get<TerrainItem>().position;
orientation = e.get<TerrainItem>().orientation;
}
void StaticGeometryModule::getItemsProperties(
std::list<std::pair<flecs::entity, Ogre::String> > *items)
{
ZoneScoped;
ECS::get().query_builder<const TerrainItem>().build().each(
[&](flecs::entity e, const TerrainItem &item) {
items->push_back({ e, item.properties });
@@ -447,11 +468,13 @@ void StaticGeometryModule::getItemsProperties(
}
void StaticGeometryModule::createItemGeometry(flecs::entity e)
{
ZoneScoped;
Geometry::createItemGeometry(e);
}
void StaticGeometryModule::destroyItemGeometry(flecs::entity e)
{
ZoneScoped;
Geometry::destroyItemGeometry(e);
}
@@ -462,6 +485,7 @@ nlohmann::json &StaticGeometryModule::getTemplates()
void StaticGeometryModule::updateItemGeometry(flecs::entity e)
{
ZoneScoped;
// We add this as task to reduce UI load
Ogre::Root::getSingleton().getWorkQueue()->addMainThreadTask([e]() {
ZoneScopedN("updateItemGeometry");
@@ -478,6 +502,7 @@ void StaticGeometryModule::addTriangleBufferWork(
const Ogre::Vector3 &position, const Ogre::Quaternion &rotation,
const Procedural::TriangleBuffer &tb)
{
ZoneScoped;
struct WorkData {
Ogre::String meshName;
Ogre::StaticGeometry *geo;

View File

@@ -2,16 +2,19 @@
#include <Ogre.h>
#include "Components.h"
#include "SunModule.h"
#include <tracy/Tracy.hpp>
namespace ECS
{
SunModule::SunModule(flecs::world &ecs)
{
ecs.component<Sun>().add(flecs::Singleton);
ZoneScoped;
ecs.component<Sun>().add(flecs::Singleton);
ecs.system<const EngineData, Sun>("UpdateSetupSun")
.kind(flecs::OnUpdate)
.each([](const EngineData &eng, Sun &sun) {
if (!sun.mSun) {
ZoneScopedN("UpdateSetupSun");
if (!sun.mSun) {
Ogre::Light *light =
eng.mScnMgr->createLight("Sun");
sun.mSunNode = eng.mScnMgr->getRootSceneNode()

View File

@@ -18,6 +18,7 @@
#include "PhysicsModule.h"
#include "StaticGeometryModule.h"
#include "TerrainModule.h"
#include <tracy/Tracy.hpp>
#define TERRAIN_SIZE 65
#define TERRAIN_WORLD_SIZE 500.0f
@@ -48,6 +49,7 @@ struct HeightData {
static HeightData *singleton;
HeightData()
{
ZoneScoped;
img.load(
"world_map.png",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
@@ -60,13 +62,15 @@ struct HeightData {
}
static HeightData *get_singleton()
{
if (!singleton)
ZoneScoped;
if (!singleton)
singleton = new HeightData();
return singleton;
}
float get_brush_height(int id, int x, int y)
{
int m = 0;
ZoneScoped;
int m = 0;
switch (id) {
case 0:
m = 0;
@@ -110,7 +114,8 @@ struct HeightData {
}
void save_heightmap()
{
Ogre::String group =
ZoneScoped;
Ogre::String group =
Ogre::ResourceGroupManager::getSingleton()
.findGroupContainingResource("world_map.png");
Ogre::FileInfoListPtr fileInfoList(
@@ -125,7 +130,7 @@ struct HeightData {
}
float get_base_height(long world_x, long world_y)
{
float height = 0.0f;
float height = 0.0f;
int world_img_x =
world_x + (int)img.getWidth() * BRUSH_SIZE / 2;
int world_img_y =
@@ -155,7 +160,7 @@ out:
}
float get_noise_height(long world_x, long world_y)
{
int h;
int h;
Ogre::Vector2 noisePoint;
struct noise_types {
@@ -192,7 +197,7 @@ out:
float get_height(Ogre::TerrainGroup *terrainGroup, long world_x,
long world_y)
{
long grid_center_x = img.getWidth() * BRUSH_SIZE / 2;
long grid_center_x = img.getWidth() * BRUSH_SIZE / 2;
long grid_center_y = img.getHeight() * BRUSH_SIZE / 2;
long world_grid_x = world_x + grid_center_x;
long world_grid_y = world_y + grid_center_y;
@@ -265,6 +270,7 @@ public:
void createTerrainChunk(Ogre::TerrainGroup *terrainGroup, long x,
long y)
{
ZoneScoped;
Ogre::Terrain *terrain = terrainGroup->getTerrain(x, y);
float minH = terrain->getMinHeight();
float maxH = terrain->getMaxHeight();
@@ -290,7 +296,8 @@ public:
}
void define(Ogre::TerrainGroup *terrainGroup, long x, long y) override
{
std::lock_guard<std::mutex> guard(mtx);
ZoneScoped;
std::lock_guard<std::mutex> guard(mtx);
uint16_t terrainSize = terrainGroup->getTerrainSize();
float *heightMap = OGRE_ALLOC_T(float, terrainSize *terrainSize,
MEMCATEGORY_GEOMETRY);
@@ -332,13 +339,15 @@ public:
}
bool frameStarted(const Ogre::FrameEvent &evt) override
{
(void)evt;
ZoneScoped;
(void)evt;
update();
return true;
}
void update()
{
std::lock_guard<std::mutex> guard(mtx);
ZoneScoped;
std::lock_guard<std::mutex> guard(mtx);
static bool created = false;
while (!collider_queue.empty()) {
Ogre::TerrainGroup *group =
@@ -478,7 +487,8 @@ public:
bool unloadProceduralPage(Ogre::Page *page,
Ogre::PagedWorldSection *section)
{
long x, y;
ZoneScoped;
long x, y;
ECS::get<Terrain>().mTerrainGroup->unpackIndex(page->CHUNK_ID,
&x, &y);
StaticGeometryModule::removeGeometryForSlot(x, y);
@@ -492,7 +502,8 @@ public:
};
TerrainModule::TerrainModule(flecs::world &ecs)
{
struct CanSetPlayerPosition {};
ZoneScoped;
struct CanSetPlayerPosition {};
ecs.module<TerrainModule>();
ecs.component<CanSetPlayerPosition>().add(flecs::Singleton);
ecs.component<Terrain>().add(flecs::Singleton);
@@ -509,7 +520,8 @@ TerrainModule::TerrainModule(flecs::world &ecs)
.each([](const EngineData &eng, const Camera &camera,
const Sun &sun, Terrain &terrain,
TerrainPrivate &priv) {
if (!terrain.mTerrainGroup && sun.mSun && eng.mScnMgr) {
ZoneScoped;
if (!terrain.mTerrainGroup && sun.mSun && eng.mScnMgr) {
std::cout << "Terrain setup\n";
if (!priv.mDummyPageProvider)
priv.mDummyPageProvider =
@@ -635,7 +647,8 @@ TerrainModule::TerrainModule(flecs::world &ecs)
.kind(flecs::OnUpdate)
.without<TerrainReady>()
.each([](const ECS::Camera &cam, const Terrain &terrain) {
std::cout << "mTerrainReady: " << terrain.mTerrainReady
ZoneScoped;
std::cout << "mTerrainReady: " << terrain.mTerrainReady
<< "\n";
if (cam.mCameraNode && terrain.mTerrainReady) {
long x, y;
@@ -653,7 +666,8 @@ TerrainModule::TerrainModule(flecs::world &ecs)
ecs.system<const Terrain, PlacementObjects>("UpdatePlacementObjects")
.kind(flecs::OnUpdate)
.each([](const Terrain &terrain, PlacementObjects &placement) {
if (placement.altar_items.size() == 0) {
ZoneScoped;
if (placement.altar_items.size() == 0) {
struct PlacementObjects::item item;
int i, j;
int worldSize = terrain.mTerrainGroup
@@ -766,7 +780,8 @@ TerrainModule::TerrainModule(flecs::world &ecs)
.kind(flecs::OnUpdate)
.interval(2.0f)
.each([](const Terrain &terrain) {
if (!terrain.mTerrainGroup
ZoneScoped;
if (!terrain.mTerrainGroup
->isDerivedDataUpdateInProgress())
terrain.mTerrainGroup->update(false);
});

View File

@@ -12,6 +12,7 @@
#include "StaticGeometryModule.h"
#include "items.h"
#include "harbour.h"
#include <tracy/Tracy.hpp>
namespace ECS
{
namespace Items
@@ -19,6 +20,7 @@ namespace Items
/* This is editor function */
static bool findPierOffset(float &offset)
{
ZoneScoped;
Ogre::Vector3 basePos =
ECS::get<EditorGizmo>().sceneNode->_getDerivedPosition();
Ogre::Quaternion baseRot =
@@ -41,7 +43,8 @@ static bool findPierOffset(float &offset)
static bool findPierOffsetAndLengthAndDepth(float &offset, float &length,
float &depth)
{
if (!findPierOffset(offset))
ZoneScoped;
if (!findPierOffset(offset))
return false;
Ogre::Vector3 basePos =
ECS::get<EditorGizmo>().sceneNode->_getDerivedPosition();
@@ -66,7 +69,8 @@ static bool findPierOffsetAndLengthAndDepth(float &offset, float &length,
}
static void findPierHeight(float maxLength, float &height)
{
Ogre::Vector3 basePos =
ZoneScoped;
Ogre::Vector3 basePos =
ECS::get<EditorGizmo>().sceneNode->_getDerivedPosition();
Ogre::Quaternion baseRot =
ECS::get<EditorGizmo>().sceneNode->_getDerivedOrientation();
@@ -86,7 +90,8 @@ static void findPierHeight(float maxLength, float &height)
}
static void findPierPath(float pathLength, std::vector<Ogre::Vector3> &path)
{
float minHeight = 0.2f;
ZoneScoped;
float minHeight = 0.2f;
int i;
Ogre::Vector3 basePos =
ECS::get<EditorGizmo>().sceneNode->_getDerivedPosition();
@@ -146,7 +151,8 @@ static void findPierPath(float pathLength, std::vector<Ogre::Vector3> &path)
}
bool editHarbourDistrict(nlohmann::json &jitem)
{
float plazzaRadius = 5.0f;
ZoneScoped;
float plazzaRadius = 5.0f;
float plazzaHeight = 0.2f;
float plazzaElevation = 0.0f;
float centerOffset = 0.0f;
@@ -280,7 +286,8 @@ bool editHarbourDistrict(nlohmann::json &jitem)
}
void createHarbourPopup(const std::pair<flecs::entity, Ogre::String> item)
{
bool lighthouse = false;
ZoneScoped;
bool lighthouse = false;
float lighthouseDistance = 0.0f;
float lighthouseAngle = 0.0f;
float centerOffset = 0.0f;
@@ -328,7 +335,8 @@ void createHarbourPopup(const std::pair<flecs::entity, Ogre::String> item)
}
void createHarbourItem()
{
Ogre::Vector3 itemPosition =
ZoneScoped;
Ogre::Vector3 itemPosition =
ECS::get<EditorGizmo>().sceneNode->_getDerivedPosition();
Ogre::Quaternion itemOrientation =
ECS::get<EditorGizmo>().sceneNode->_getDerivedOrientation();
@@ -364,7 +372,8 @@ void createHarbourItem()
}
void createHarbourMenu()
{
if (ImGui::MenuItem("Create"))
ZoneScoped;
if (ImGui::MenuItem("Create"))
createHarbourItem();
}
}
@@ -373,7 +382,8 @@ namespace Geometry
void createBridge(flecs::entity e, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
int i;
ZoneScoped;
int i;
Procedural::TriangleBuffer tb;
Ogre::MaterialPtr harbourMaterial;
harbourMaterial = Ogre::MaterialManager::getSingleton().getByName(
@@ -545,7 +555,8 @@ void createBridge(flecs::entity e, Ogre::SceneNode *sceneNode,
void createPier(flecs::entity e, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
Ogre::MaterialPtr harbourMaterial;
ZoneScoped;
Ogre::MaterialPtr harbourMaterial;
harbourMaterial = Ogre::MaterialManager::getSingleton().getByName(
"proceduralMaterialHarbour" +
Ogre::StringConverter::toString(e.id()));
@@ -705,7 +716,8 @@ void createPier(flecs::entity e, Ogre::SceneNode *sceneNode,
void createPlazza(flecs::entity e, const nlohmann::json &district,
Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo)
{
Ogre::MaterialPtr harbourMaterial;
ZoneScoped;
Ogre::MaterialPtr harbourMaterial;
harbourMaterial = Ogre::MaterialManager::getSingleton().getByName(
"proceduralMaterialHarbour" +
Ogre::StringConverter::toString(e.id()));
@@ -784,7 +796,8 @@ void createPlazza(flecs::entity e, const nlohmann::json &district,
void createBuildings(flecs::entity e, const nlohmann::json &district,
Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo)
{
Ogre::MaterialPtr harbourMaterial;
ZoneScoped;
Ogre::MaterialPtr harbourMaterial;
harbourMaterial = Ogre::MaterialManager::getSingleton().getByName(
"proceduralMaterialHarbour" +
Ogre::StringConverter::toString(e.id()));
@@ -865,7 +878,8 @@ void createBuildings(flecs::entity e, const nlohmann::json &district,
void createHarbour(flecs::entity e, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
std::cout << "createHarbour " << e.id() << std::endl;
ZoneScoped;
std::cout << "createHarbour " << e.id() << std::endl;
Ogre::MaterialPtr harbourMaterial;
harbourMaterial = Ogre::MaterialManager::getSingleton().getByName(
"proceduralMaterialHarbour" +
@@ -980,4 +994,4 @@ void createHarbour(flecs::entity e, Ogre::SceneNode *sceneNode,
geo->build();
}
}
}
}

View File

@@ -18,12 +18,14 @@
#include "temple.h"
#include "town.h"
#include "items.h"
#include <tracy/Tracy.hpp>
namespace ECS
{
namespace Items
{
void runScriptsForAllTowns()
{
ZoneScoped;
std::pair<flecs::entity, Ogre::String> selected_item;
std::list<std::pair<flecs::entity, Ogre::String> > items;
StaticGeometryModule::getItemsProperties(&items);
@@ -40,7 +42,8 @@ void runScriptsForAllTowns()
}
void showItemPopup(const std::pair<flecs::entity, Ogre::String> &item)
{
Ogre::String popupLabel =
ZoneScoped;
Ogre::String popupLabel =
"EditPopup" + Ogre::StringConverter::toString(item.first.id());
if (ImGui::BeginPopup(popupLabel.c_str())) {
Ogre::String prop =
@@ -160,7 +163,8 @@ void showItemPopup(const std::pair<flecs::entity, Ogre::String> &item)
}
void showItemButtons(const std::pair<flecs::entity, Ogre::String> &item)
{
ImGui::SameLine();
ZoneScoped;
ImGui::SameLine();
Ogre::String upd_label =
"Update Height##" +
Ogre::StringConverter::toString(item.first.id());
@@ -190,7 +194,8 @@ void showItemButtons(const std::pair<flecs::entity, Ogre::String> &item)
}
void createItemsMenu()
{
if (ImGui::BeginMenu("Harbour")) {
ZoneScoped;
if (ImGui::BeginMenu("Harbour")) {
Items::createHarbourMenu();
ImGui::EndMenu();
}
@@ -209,6 +214,7 @@ namespace Geometry
{
void setupLods(Ogre::LodConfig &config)
{
ZoneScoped;
int count = 0;
// config.advanced.useCompression = false;
config.advanced.useVertexNormals = true;
@@ -246,7 +252,8 @@ void setupLods(Ogre::LodConfig &config)
Ogre::StaticGeometry *createStaticGeometry(flecs::entity e)
{
Ogre::String props = e.get<TerrainItem>().properties;
ZoneScoped;
Ogre::String props = e.get<TerrainItem>().properties;
nlohmann::json jp = nlohmann::json::parse(props);
if (jp.find("type") != jp.end()) {
Ogre::String itemType = jp["type"].get<Ogre::String>();
@@ -264,7 +271,8 @@ Ogre::StaticGeometry *createStaticGeometry(flecs::entity e)
}
void createItemGeometry(flecs::entity e)
{
OgreAssert(!e.has<TerrainItemNode>(), "Geometry already created");
ZoneScoped;
OgreAssert(!e.has<TerrainItemNode>(), "Geometry already created");
std::cout << "creating geometry for item: " << e.id() << std::endl;
Ogre::String props = e.get<TerrainItem>().properties;
nlohmann::json jp = nlohmann::json::parse(props);
@@ -322,7 +330,8 @@ void createItemGeometry(flecs::entity e)
void destroyItemGeometry(flecs::entity e)
{
OgreAssert(e.has<TerrainItemNode>(), "No geometry created");
ZoneScoped;
OgreAssert(e.has<TerrainItemNode>(), "No geometry created");
#if 0
ECS::get<EngineData>().mScnMgr->destroyStaticGeometry()
e.get<TerrainItemNode>().geo->destroy();
@@ -333,6 +342,7 @@ void destroyItemGeometry(flecs::entity e)
}
void updateItemGeometry(flecs::entity e)
{
ZoneScoped;
OgreAssert(e.has<TerrainItem>(), "not terrain item");
if (e.has<TerrainItemNode>())
destroyItemGeometry(e);
@@ -344,7 +354,8 @@ flecs::entity createMeshGeometry(const Ogre::String &meshName,
Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().load(
ZoneScoped;
Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().load(
meshName,
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
OgreAssert(mesh, "mesh " + meshName + " not found");

View File

@@ -14,12 +14,14 @@
#include "PhysicsModule.h"
#include "items.h"
#include "temple.h"
#include <tracy/Tracy.hpp>
namespace ECS
{
namespace Items
{
void createTempleItem()
{
ZoneScoped;
Ogre::Vector3 itemPosition =
ECS::get<EditorGizmo>().sceneNode->_getDerivedPosition();
Ogre::Quaternion itemOrientation =
@@ -38,12 +40,14 @@ void createTempleItem()
}
void createTempleMenu()
{
if (ImGui::MenuItem("Create"))
ZoneScoped;
if (ImGui::MenuItem("Create"))
createTempleItem();
}
void createTemplePopup(const std::pair<flecs::entity, Ogre::String> item)
{
float size = 40.0f;
ZoneScoped;
float size = 40.0f;
float pillarRadius = 0.5f;
float pillarHeight = 16.0f;
int pillarCount = 20;
@@ -88,7 +92,8 @@ namespace Geometry
void createTemple(flecs::entity e, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
Ogre::String props = e.get<TerrainItem>().properties;
ZoneScoped;
Ogre::String props = e.get<TerrainItem>().properties;
nlohmann::json jp = nlohmann::json::parse(props);
float size = 20.0f;
int pillarCount = 4;

View File

@@ -33,6 +33,7 @@
void serializeMesh(Ogre::MeshPtr mesh, const Ogre::String &meshName)
{
ZoneScoped;
Ogre::MeshSerializer meshSerializer;
meshSerializer.exportMesh(mesh, meshName,
@@ -44,12 +45,14 @@ namespace Items
{
int64_t makeCellKey(int kx, int ky, int kz)
{
ZoneScoped;
int64_t key =
(int64_t)kx + 1024 * (int64_t)ky + 1024 * 1024 * (int64_t)kz;
return key;
}
int64_t makeCellKey(const nlohmann::json &cell)
{
ZoneScoped;
int64_t kx = cell["x"].get<int>();
int64_t ky = cell["y"].get<int>();
int64_t kz = cell["z"].get<int>();
@@ -60,6 +63,7 @@ void displayGrid(flecs::entity e, nlohmann::json &lot, int index,
Ogre::SceneNode *sceneNode, const Ogre::Vector3 &localPosition,
const Ogre::Quaternion &localRotation)
{
ZoneScoped;
if (lot.find("edited") == lot.end()) {
lot["edited"] = true;
int width = lot["width"].get<int>();
@@ -100,7 +104,8 @@ void displayGrid(flecs::entity e, nlohmann::json &lot, int index,
}
void createTownItem()
{
Ogre::Vector3 itemPosition =
ZoneScoped;
Ogre::Vector3 itemPosition =
ECS::get<EditorGizmo>().sceneNode->_getDerivedPosition();
Ogre::Quaternion itemOrientation =
ECS::get<EditorGizmo>().sceneNode->_getDerivedOrientation();
@@ -114,11 +119,13 @@ void createTownItem()
}
void createTownMenu()
{
if (ImGui::MenuItem("Create"))
ZoneScoped;
if (ImGui::MenuItem("Create"))
createTownItem();
}
bool editCell(const Ogre::String &cellLabel, nlohmann::json &cell)
{
ZoneScoped;
bool changed = false;
auto checkboxBit = [cellLabel, &changed](Ogre::String label,
nlohmann::json &cell,
@@ -191,6 +198,7 @@ struct CellsScript {
, cells(lot["cells"])
, fucells(lot["furniture_cells"])
{
ZoneScoped;
noise.SetNoiseType(FastNoiseLite::NoiseType_OpenSimplex2);
noise.SetSeed(310);
noise.SetFrequency(0.01f);
@@ -485,6 +493,7 @@ struct CellsScript {
}
static std::string trim(const std::string &str)
{
ZoneScoped;
// Find the first character that is not a whitespace character
const std::string ws =
" \t\n\r\f\v"; // Common whitespace characters
@@ -504,6 +513,7 @@ struct CellsScript {
static std::vector<std::string> split_and_trim(const std::string &s,
char delimiter)
{
ZoneScoped;
std::vector<std::string> tokens;
std::string token;
std::stringstream ss(s); // Use stringstream to parse the string
@@ -521,16 +531,19 @@ struct CellsScript {
}
void buildCellIndex()
{
ZoneScoped;
for (auto &cell : cells)
cell["id"] = makeCellKey(cell);
}
void buildFCellIndex()
{
ZoneScoped;
for (auto &fucell : fucells)
fucell["id"] = makeCellKey(fucell);
}
int findCell(int X, int Y, int Z)
{
ZoneScoped;
int64_t key = makeCellKey(X, Y, Z);
int result = -1;
int i;
@@ -545,6 +558,7 @@ struct CellsScript {
}
int findFCell(int X, int Y, int Z)
{
ZoneScoped;
int64_t key = makeCellKey(X, Y, Z);
int result = -1;
int i;
@@ -559,6 +573,7 @@ struct CellsScript {
}
void bitCmd(const Ogre::String &cmd, const Ogre::String &bit)
{
ZoneScoped;
uint64_t flags = 0;
std::vector<Ogre::String> bitconv = {
"floor", "ceiling", "wallx-", "wallx+",
@@ -590,6 +605,7 @@ struct CellsScript {
}
bool isBit(const Ogre::String &bit)
{
ZoneScoped;
uint64_t flags = 0;
std::vector<Ogre::String> bitconv = {
"floor", "ceiling", "wallx-", "wallx+",
@@ -617,6 +633,7 @@ struct CellsScript {
}
static bool isBit(const nlohmann::json &cell, const Ogre::String &bit)
{
ZoneScoped;
uint64_t flags = 0;
std::vector<Ogre::String> bitconv = {
"floor", "ceiling", "wallx-", "wallx+",
@@ -642,6 +659,7 @@ struct CellsScript {
}
void cell(uint64_t flags)
{
ZoneScoped;
if (findCell(currentX, currentY, currentZ) == -1) {
nlohmann::json cell;
buildCellIndex();
@@ -659,12 +677,14 @@ struct CellsScript {
}
void clear()
{
ZoneScoped;
int index = findCell(currentX, currentY, currentZ);
if (index >= 0)
cells.erase(index);
}
void clear_area(int minX, int minZ, int sizeX, int sizeZ)
{
ZoneScoped;
int i, j;
for (i = 0; i < sizeZ; i++)
for (j = 0; j < sizeX; j++) {
@@ -675,12 +695,14 @@ struct CellsScript {
}
void clear_furniture()
{
ZoneScoped;
int index = findFCell(currentX, currentY, currentZ);
if (index >= 0)
fucells.erase(index);
}
void clear_furniture_area(int minX, int minZ, int sizeX, int sizeZ)
{
ZoneScoped;
int i, j;
for (i = 0; i < sizeZ; i++)
for (j = 0; j < sizeX; j++) {
@@ -691,6 +713,7 @@ struct CellsScript {
}
int room(int minX, int minZ, int sizeX, int sizeZ)
{
ZoneScoped;
int i, j, ret;
clear_area(minX, minZ, sizeX, sizeZ);
for (i = 0; i < sizeZ; i++)
@@ -726,6 +749,7 @@ struct CellsScript {
int roof(int minX, int minZ, int sizeX, int sizeZ, float height,
int type)
{
ZoneScoped;
nlohmann::json roofs = nlohmann::json::array();
if (lot.find("roofs") != lot.end())
roofs = lot["roofs"];
@@ -748,11 +772,13 @@ struct CellsScript {
}
void clear_roofs()
{
ZoneScoped;
lot["roofs"] = nlohmann::json::array();
}
void fcell(const std::vector<Ogre::String> &tags,
nlohmann::json furniture, int rotation)
{
ZoneScoped;
nlohmann::json jtags = nlohmann::json::array();
for (const auto &tag : tags)
jtags.push_back(tag);
@@ -779,6 +805,7 @@ struct CellsScript {
nlohmann::json select_furniture(const std::vector<Ogre::String> &tags,
const std::vector<Ogre::String> &notags)
{
ZoneScoped;
nlohmann::json adata = nlohmann::json::array();
ECS::get().query_builder<const FurnitureItem>().build().each(
[&](flecs::entity e, const FurnitureItem &item) {
@@ -827,6 +854,7 @@ struct CellsScript {
}
bool place_furniture(int room, Ogre::String tags)
{
ZoneScoped;
bool ret = true;
std::vector<Ogre::String> atags = split_and_trim(tags, ',');
int i, j;
@@ -1026,6 +1054,7 @@ struct CellsScript {
std::vector<std::pair<int, int> > roomEdge(int room)
{
ZoneScoped;
std::vector<std::pair<int, int> > seg;
std::set<std::pair<int, int> > seen;
int i;
@@ -1076,12 +1105,14 @@ out:
}
bool adjacent(std::pair<int, int> c1, std::pair<int, int> c2)
{
ZoneScoped;
int dx = std::abs(c1.first - c2.first);
int dz = std::abs(c1.second - c2.second);
return (dx == 0 && dz == 1) || (dx == 1 && dz == 0);
}
void dumpSeg(const std::vector<std::pair<int, int> > &seg)
{
ZoneScoped;
int count = 0;
for (auto &cell : seg) {
std::cout << count << " " << cell.first << " "
@@ -1093,6 +1124,7 @@ out:
std::vector<std::pair<int, int> > &ret1,
std::vector<std::pair<int, int> > &ret2)
{
ZoneScoped;
std::vector<std::pair<int, int> > room_seg = roomEdge(room);
std::vector<std::pair<int, int> > other_seg = roomEdge(other);
std::vector<std::pair<int, int> > ret;
@@ -1110,6 +1142,7 @@ out:
}
void createExit0(int room)
{
ZoneScoped;
int posX = rooms[room].minX;
int posZ = rooms[room].minZ;
int i;
@@ -1138,6 +1171,7 @@ out:
}
void createExit1(int room)
{
ZoneScoped;
int posX = rooms[room].minX;
int posZ = rooms[room].minZ + rooms[room].sizeZ - 1;
int i;
@@ -1166,6 +1200,7 @@ out:
}
void createExit2(int room)
{
ZoneScoped;
int posX = rooms[room].minX + rooms[room].sizeX - 1;
int posZ = rooms[room].minZ;
int i;
@@ -1194,6 +1229,7 @@ out:
}
void createExit3(int room)
{
ZoneScoped;
int posX = rooms[room].minX;
int posZ = rooms[room].minZ;
int i;
@@ -1222,6 +1258,7 @@ out:
}
void createWindows(int room)
{
ZoneScoped;
int posX = rooms[room].minX;
int posZ = rooms[room].minZ;
int i;
@@ -1274,6 +1311,7 @@ out:
}
void createExterior()
{
ZoneScoped;
int room;
for (room = 0; room < rooms.size(); room++) {
int posX = rooms[room].minX;
@@ -1341,6 +1379,7 @@ out:
}
void connectRooms(int r1, int r2)
{
ZoneScoped;
std::vector<std::pair<int, int> > seg1, seg2;
int index = 0;
adjacentCells(r1, r2, seg1, seg2);
@@ -1460,10 +1499,12 @@ out:
}
virtual ~CellsScript()
{
ZoneScoped;
lua_close(L);
}
void run()
{
ZoneScoped;
int result = luaL_dostring(L, cellScript.c_str());
if (result != LUA_OK) {
std::cerr << "Lua script execution failed: "
@@ -1475,6 +1516,7 @@ out:
};
bool editRoofs(const Ogre::String &lotLabel, nlohmann::json &lot)
{
ZoneScoped;
bool changed = false;
static int roofPosition[3] = { 0, 0 };
static int roofSize[2] = { 1, 1 };
@@ -1625,6 +1667,7 @@ bool editRoofs(const Ogre::String &lotLabel, nlohmann::json &lot)
}
bool editLot(const Ogre::String &lotLabel, nlohmann::json &lot)
{
ZoneScoped;
bool changed = false;
float angle = lot["angle"].get<float>();
if (ImGui::SliderFloat(("Lot Angle##" + lotLabel).c_str(), &angle,
@@ -1794,6 +1837,7 @@ bool editLot(const Ogre::String &lotLabel, nlohmann::json &lot)
}
void commandEraseLot(nlohmann::json &district, int lotIndex)
{
ZoneScoped;
nlohmann::json lots = nlohmann::json::array();
for (const auto &lot : district["lots"])
lots.push_back(lot);
@@ -1802,6 +1846,7 @@ void commandEraseLot(nlohmann::json &district, int lotIndex)
}
void cleanupLot(nlohmann::json &lot)
{
ZoneScoped;
lot.erase("cells");
lot.erase("furniture_cells");
lot.erase("roofs");
@@ -1809,6 +1854,7 @@ void cleanupLot(nlohmann::json &lot)
void addLotTemplate(nlohmann::json &district, nlohmann::json &lotTemplates,
int lotIndex)
{
ZoneScoped;
if (district.find("lots") != district.end()) {
nlohmann::json &lots = district["lots"];
nlohmann::json lotTemplate = lots[lotIndex];
@@ -1820,6 +1866,7 @@ void addLotFromTemplate(nlohmann::json &district,
const nlohmann::json &lotTemplates,
int lotTemplateIndex)
{
ZoneScoped;
nlohmann::json lots = nlohmann::json::array();
OgreAssert(lotTemplateIndex < lotTemplates.size() &&
lotTemplates.size() > 0,
@@ -1855,6 +1902,7 @@ void addLotFromTemplate(nlohmann::json &district,
void addLot(nlohmann::json &district, float angle, int width, int depth,
float elevation, const Ogre::String &script)
{
ZoneScoped;
nlohmann::json lots = nlohmann::json::array();
for (const auto &lot : district["lots"])
lots.push_back(lot);
@@ -1873,6 +1921,7 @@ void addLot(nlohmann::json &district, float angle, int width, int depth,
bool editDistrict(const Ogre::String &districtLabel, nlohmann::json &district,
nlohmann::json &lotTemplates)
{
ZoneScoped;
bool changed = false;
nlohmann::json lots = nlohmann::json::array();
for (const auto &lot : district["lots"])
@@ -1973,6 +2022,7 @@ bool editDistrict(const Ogre::String &districtLabel, nlohmann::json &district,
}
bool editColorRects(nlohmann::json &rects)
{
ZoneScoped;
bool changed = false;
ImGui::Text("Color Rects");
for (auto it = rects.begin(); it != rects.end(); it++) {
@@ -2072,6 +2122,7 @@ bool editColorRects(nlohmann::json &rects)
}
void runAllScriptsForTown(flecs::entity e)
{
ZoneScoped;
Ogre::String prop = StaticGeometryModule::getItemProperties(e);
nlohmann::json j = nlohmann::json::parse(prop);
auto &districts = j["districts"];
@@ -2093,6 +2144,7 @@ void runAllScriptsForTown(flecs::entity e)
}
bool editNPCs(nlohmann::json &npcs)
{
ZoneScoped;
bool changed = false;
ImGui::Text("NPC");
int id = 0;
@@ -2221,6 +2273,7 @@ bool editNPCs(nlohmann::json &npcs)
}
void createTownPopup(const std::pair<flecs::entity, Ogre::String> item)
{
ZoneScoped;
Ogre::String prop = StaticGeometryModule::getItemProperties(item.first);
Ogre::Vector3 townPosition;
Ogre::Quaternion townRotation;
@@ -2341,6 +2394,7 @@ struct ProcessCells {
std::vector<struct BitSet> bits_int_corners2;
ProcessCells()
{
ZoneScoped;
bits_ext_corners = {
{ 4 | 16, // external wall
4.0f,
@@ -2955,6 +3009,7 @@ struct ProcessCells {
void clampUV(flecs::entity e, Procedural::TriangleBuffer &tb,
const Ogre::String &rectKey)
{
ZoneScoped;
Ogre::String props = e.get<TerrainItem>().properties;
nlohmann::json jp = nlohmann::json::parse(props);
nlohmann::json colorRects = nlohmann::json::object();
@@ -2979,6 +3034,7 @@ void clampUV(flecs::entity e, Procedural::TriangleBuffer &tb,
}
Ogre::MaterialPtr createTownMaterial(flecs::entity e, bool force)
{
ZoneScoped;
Ogre::MaterialPtr townMaterial;
Ogre::String props = e.get<TerrainItem>().properties;
nlohmann::json jp = nlohmann::json::parse(props);
@@ -3101,6 +3157,7 @@ Ogre::MaterialPtr createTownMaterial(flecs::entity e, bool force)
}
void createTownWindows(flecs::entity e)
{
ZoneScoped;
Ogre::MeshPtr frame1mesh =
Ogre::MeshManager::getSingleton().getByName("window-frame1");
if (!frame1mesh) {
@@ -3196,6 +3253,7 @@ void createTownWindows(flecs::entity e)
}
void createTownDoors(flecs::entity e)
{
ZoneScoped;
Ogre::MeshPtr extframe1mesh =
Ogre::MeshManager::getSingleton().getByName(
"external-door-frame1");
@@ -3335,6 +3393,7 @@ struct TownTask {
const Ogre::Vector3 &position,
const Ogre::Quaternion &orientation)
{
ZoneScoped;
Ogre::Entity *ent =
ECS::get<EngineData>().mScnMgr->createEntity(mesh);
ent->setMaterial(material);
@@ -3345,6 +3404,7 @@ struct TownTask {
const Ogre::Vector3 &position,
const Ogre::Quaternion &orientation)
{
ZoneScoped;
JPH::ShapeRefC shape =
JoltPhysicsWrapper::getSingleton().createMeshShape(
mesh);
@@ -3411,6 +3471,7 @@ struct TownPlazza : TownTask {
queueData,
localPosition,
localRotation]() {
ZoneScoped;
const nlohmann::json &jp = queueData->jp;
float radius = 5.0f;
float height = 0.2f;
@@ -3491,10 +3552,12 @@ struct TownPlazza : TownTask {
int index, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
ZoneScoped;
createTownPlazza(e, jdistrict, index, sceneNode, geo);
}
void wait()
{
ZoneScoped;
if (townPlazzaComplete.valid() &&
townPlazzaComplete.wait_for(std::chrono::seconds(0)) !=
std::future_status::ready)
@@ -3611,6 +3674,7 @@ struct TownLots : TownTask {
Ogre::Root::getSingleton().getWorkQueue()->addTask([radius,
baseHeight,
promise]() {
ZoneScoped;
std::cout << "lots count: " << lots.size() << std::endl;
OgreAssert(lots.size() > 0, "bad lots count");
for (auto &lot : lots) {
@@ -3706,10 +3770,12 @@ struct TownLots : TownTask {
int index, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
ZoneScoped;
createTownLots(e, jdistrict, index, sceneNode, geo);
}
void wait()
{
ZoneScoped;
if (townLotsComplete.valid() &&
townLotsComplete.wait_for(std::chrono::seconds(0)) !=
std::future_status::ready)
@@ -3722,6 +3788,7 @@ struct TownCells : TownTask {
int index, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
ZoneScoped;
struct QueueData {
Procedural::TriangleBuffer tb;
Ogre::Vector3 position;
@@ -3838,6 +3905,7 @@ struct TownCells : TownTask {
baseHeight,
promise]() {
{
ZoneScoped;
int count = 0;
for (auto &lot : lots) {
for (auto &jcell : lot.jlot["cells"]) {
@@ -4020,10 +4088,12 @@ struct TownCells : TownTask {
int index, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
ZoneScoped;
createCells(e, jdistrict, index, sceneNode, geo);
}
void wait()
{
ZoneScoped;
if (townCellsComplete.valid() &&
townCellsComplete.wait_for(std::chrono::seconds(0)) !=
std::future_status::ready)
@@ -4037,6 +4107,7 @@ struct TownRoofs : TownTask {
int index, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
ZoneScoped;
struct QueueData {
Procedural::TriangleBuffer tb;
Ogre::Vector3 position;
@@ -4154,6 +4225,7 @@ struct TownRoofs : TownTask {
}
Ogre::Root::getSingleton().getWorkQueue()->addTask([radius,
promise]() {
ZoneScoped;
for (auto &lot : lots) {
for (auto &jroof : lot.jlot["roofs"]) {
int roofType = jroof["type"].get<int>();
@@ -4887,10 +4959,12 @@ struct TownRoofs : TownTask {
int index, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
ZoneScoped;
createTownRoofs(e, jdistrict, index, sceneNode, geo);
}
void wait()
{
ZoneScoped;
if (townRoofsComplete.valid() &&
townRoofsComplete.wait_for(std::chrono::seconds(0)) !=
std::future_status::ready)
@@ -4905,6 +4979,7 @@ struct TownDecorateWindows : TownTask {
Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
ZoneScoped;
// FIXME: make furniture placement a background task.
Ogre::MaterialPtr townMaterial = createTownMaterial(e);
const nlohmann::json &jp = jdistrict;
@@ -5118,10 +5193,12 @@ struct TownDecorateWindows : TownTask {
int index, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
ZoneScoped;
createDecorateWindows(e, jdistrict, index, sceneNode, geo);
}
void wait()
{
ZoneScoped;
if (townDecorateWindowsComplete.valid() &&
townDecorateWindowsComplete.wait_for(std::chrono::seconds(
0)) != std::future_status::ready)
@@ -5135,6 +5212,7 @@ struct TownDecorateDoors : TownTask {
Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
ZoneScoped;
// FIXME: make furniture placement a background task.
Ogre::MaterialPtr townMaterial = createTownMaterial(e);
const nlohmann::json &jp = jdistrict;
@@ -5432,10 +5510,12 @@ struct TownDecorateDoors : TownTask {
int index, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
ZoneScoped;
createDecorateDoors(e, jdistrict, index, sceneNode, geo);
}
void wait()
{
ZoneScoped;
if (townDecorateDoorsComplete.valid() &&
townDecorateDoorsComplete.wait_for(std::chrono::seconds(
0)) != std::future_status::ready)
@@ -5449,6 +5529,7 @@ struct TownDecorateFurniture : TownTask {
Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
ZoneScoped;
// FIXME: make furniture placement a background task.
Ogre::MaterialPtr townMaterial = createTownMaterial(e);
const nlohmann::json &jp = jdistrict;
@@ -5930,6 +6011,7 @@ void createTown(flecs::entity e, Ogre::SceneNode *sceneNode,
}
}
Ogre::Root::getSingleton().getWorkQueue()->addTask([geo]() {
ZoneScoped;
for (auto m : townTasks)
m->wait();
Ogre::Root::getSingleton().getWorkQueue()->addMainThreadTask(

View File

@@ -16,5 +16,5 @@ find_package(flecs REQUIRED CONFIG)
add_library(physics STATIC physics.cpp)
target_link_libraries(physics PUBLIC OgreMain Jolt::Jolt)
target_include_directories(physics PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(physics PRIVATE JPH_PROFILE_ENABLED)
target_compile_definitions(physics PUBLIC JPH_DEBUG_RENDERER JPH_PROFILE_ENABLED JPH_DOUBLE_PRECISION)

View File

@@ -523,7 +523,6 @@ void ContactListener::update()
}
class Physics {
JPH::PhysicsSystem physics_system;
// We need a temp allocator for temporary allocations during the physics update. We're
// pre-allocating 10 MB to avoid having to do allocations during the physics update.
// B.t.w. 10 MB is way too much for this example but it is a typical value you can use.
@@ -550,6 +549,7 @@ class Physics {
// Also have a look at ObjectLayerPairFilterTable or ObjectLayerPairFilterMask for a simpler interface.
ObjectLayerPairFilterImpl object_vs_object_layer_filter;
JPH::PhysicsSystem physics_system;
DebugRenderer *mDebugRenderer;
std::map<JPH::BodyID, Ogre::SceneNode *> id2node;
std::map<Ogre::SceneNode *, JPH::BodyID> node2id;
@@ -573,17 +573,13 @@ public:
std::thread::hardware_concurrency() - 1)
, mDebugRenderer(new DebugRenderer(scnMgr, cameraNode))
, object_vs_broadphase_layer_filter{}
, object_vs_object_layer_filter{}
, object_vs_object_layer_filter{}
, debugDraw(false)
{
static int instanceCount = 0;
OgreAssert(instanceCount == 0, "Bad initialisation");
instanceCount++;
// Register all physics types with the factory and install their collision handlers with the CollisionDispatch class.
// If you have your own custom shape types you probably need to register their handlers with the CollisionDispatch before calling this function.
// If you implement your own default material (PhysicsMaterial::sDefault) make sure to initialize it before this function or else this function will create one for you.
JPH::RegisterTypes();
// This is the max amount of rigid bodies that you can add to the physics system. If you try to add more you'll get an error.
// Note: This value is low because this is a simple test. For a real project use something in the order of 65536.
@@ -1531,7 +1527,7 @@ void physics()
// physics.update(1.0f / 60.0f);
}
Physics *phys = nullptr;
static std::unique_ptr<Physics> phys = nullptr;
JoltPhysicsWrapper::JoltPhysicsWrapper(Ogre::SceneManager *scnMgr,
Ogre::SceneNode *cameraNode)
: Ogre::Singleton<JoltPhysicsWrapper>()
@@ -1540,21 +1536,24 @@ JoltPhysicsWrapper::JoltPhysicsWrapper(Ogre::SceneManager *scnMgr,
// This needs to be done before any other Jolt function is called.
JPH::RegisterDefaultAllocator();
// Create a factory, this class is responsible for creating instances of classes based on their name or hash and is mainly used for deserialization of saved data.
// It is not directly used in this example but still required.
JPH::Factory::sInstance = new JPH::Factory();
// Install trace and assert callbacks
JPH::Trace = TraceImpl;
JPH_IF_ENABLE_ASSERTS(JPH::AssertFailed = AssertFailedImpl;)
phys = new Physics(scnMgr, cameraNode, nullptr, &contacts);
// Create a factory, this class is responsible for creating instances of classes based on their name or hash and is mainly used for deserialization of saved data.
// It is not directly used in this example but still required.
JPH::Factory::sInstance = new JPH::Factory();
// Register all physics types with the factory and install their collision handlers with the CollisionDispatch class.
// If you have your own custom shape types you probably need to register their handlers with the CollisionDispatch before calling this function.
// If you implement your own default material (PhysicsMaterial::sDefault) make sure to initialize it before this function or else this function will create one for you.
JPH::RegisterTypes();
phys = std::make_unique<Physics>(scnMgr, cameraNode, nullptr, &contacts);
}
JoltPhysicsWrapper::~JoltPhysicsWrapper()
{
if (phys)
delete phys;
}
void JoltPhysicsWrapper::update(float dt)