86 _sceneGraph = std::make_unique<SceneGraph>( *
this );
87 _state = std::make_unique<SceneState>( *
this );
88 _input = std::make_unique<SceneInput>( *
this );
90 _lightPool = std::make_unique<LightPool>( *
this,
_context );
91 _envProbePool = std::make_unique<SceneEnvironmentProbePool>( *
this );
92 _GUI = std::make_unique<SceneGUIElements>( *
this,
_context.
gui() );
130 return Paths::g_projectsLocation / project.id()._name / Paths::g_scenesLocation;
160 return handle !=
nullptr &&
Finished( *handle );
172 music.assetName( musicFile );
173 music.assetLocation( musicFilePath );
178 insert( state()->music( type ),
_ID( name ), handle );
183 return sceneGraph()->saveNodeToXML( node );
188 return sceneGraph()->loadNodeFromXML(
ResourcePath{
"assets.xml" }, node );
193 using boost::property_tree::ptree;
198 const Str<256>& sceneName = resourceName();
199 const Str<256> sceneSaveFile = sceneName +
".xml";
202 const ResourcePath sceneDataFile = scenesLocation / sceneSaveFile;
206 msgCallback(
"Validating directory structure ..." );
209 if (
createDirectory( sceneLocation /
"collisionMeshes") != FileError::NONE )
213 if (
createDirectory( sceneLocation /
"navMeshes" ) != FileError::NONE )
217 if (
createDirectory( sceneLocation / Paths::g_nodesSaveLocation ) != FileError::NONE )
226 msgCallback(
"Saving scene settings ..." );
230 pt.put(
"assets", assetsFile.string() );
231 pt.put(
"musicPlaylist",
"musicPlaylist.xml" );
233 pt.put(
"vegetation.grassVisibility", state()->renderState().grassVisibility() );
234 pt.put(
"vegetation.treeVisibility", state()->renderState().treeVisibility() );
236 pt.put(
"wind.windDirX", state()->windDirX() );
237 pt.put(
"wind.windDirZ", state()->windDirZ() );
238 pt.put(
"wind.windSpeed", state()->windSpeed() );
240 pt.put(
"options.visibility", state()->renderState().generalVisibility() );
242 for (
U8 i = 0u; i < playerCount(); ++i )
247 pt.put(
"fog.fogDensity", state()->renderState().fogDetails()._colourAndDensity.a );
248 pt.put(
"fog.fogScatter", state()->renderState().fogDetails()._colourSunScatter.a );
249 pt.put(
"fog.fogColour.<xmlattr>.r", state()->renderState().fogDetails()._colourAndDensity.r );
250 pt.put(
"fog.fogColour.<xmlattr>.g", state()->renderState().fogDetails()._colourAndDensity.g );
251 pt.put(
"fog.fogColour.<xmlattr>.b", state()->renderState().fogDetails()._colourAndDensity.b );
253 pt.put(
"lod.lodThresholds.<xmlattr>.x", state()->renderState().lodThresholds().x );
254 pt.put(
"lod.lodThresholds.<xmlattr>.y", state()->renderState().lodThresholds().y );
255 pt.put(
"lod.lodThresholds.<xmlattr>.z", state()->renderState().lodThresholds().z );
256 pt.put(
"lod.lodThresholds.<xmlattr>.w", state()->renderState().lodThresholds().w );
258 pt.put(
"shadowing.<xmlattr>.lightBleedBias", state()->lightBleedBias() );
259 pt.put(
"shadowing.<xmlattr>.minShadowVariance", state()->minShadowVariance() );
261 pt.put(
"dayNight.<xmlattr>.enabled", dayNightCycleEnabled() );
262 pt.put(
"dayNight.timeOfDay.<xmlattr>.hour", _dayNightData._time._hour );
263 pt.put(
"dayNight.timeOfDay.<xmlattr>.minute", _dayNightData._time._minutes );
264 pt.put(
"dayNight.location.<xmlattr>.latitude", _dayNightData._location._latitude );
265 pt.put(
"dayNight.location.<xmlattr>.longitude", _dayNightData._location._longitude );
266 pt.put(
"dayNight.timeOfDay.<xmlattr>.timeFactor", _dayNightData._speedFactor );
268 const FileError backupReturnCode =
copyFile( scenesLocation, sceneSaveFile.c_str(), scenesLocation, (sceneSaveFile +
".bak").c_str(),
true );
269 if ( backupReturnCode != FileError::NONE &&
270 backupReturnCode != FileError::FILE_NOT_FOUND &&
271 backupReturnCode != FileError::FILE_EMPTY )
286 msgCallback(
"Saving scene graph data ..." );
288 sceneGraph()->saveToXML( assetsFile, msgCallback );
294 msgCallback(
"Saving music data ..." );
299 if (
copyFile( sceneLocation,
"musicPlaylist.xml", sceneLocation,
"musicPlaylist.xml.bak",
true ) == FileError::NONE )
301 XML::writeXML( sceneLocation /
"musicPlaylist.xml.dev", pt );
307 if ( finishCallback )
309 finishCallback(
true );
319 const Str<256>& sceneName = resourceName();
329 sceneGraph()->loadFromXML(
ResourcePath{
"assets.xml" });
330 loadMusicPlaylist( sceneLocation,
"musicPlaylist.xml",
this, config );
334 boost::property_tree::ptree pt;
337 state()->renderState().grassVisibility( pt.get(
"vegetation.grassVisibility", state()->renderState().grassVisibility() ) );
338 state()->renderState().treeVisibility( pt.get(
"vegetation.treeVisibility", state()->renderState().treeVisibility() ) );
339 state()->renderState().generalVisibility( pt.get(
"options.visibility", state()->renderState().generalVisibility() ) );
341 state()->windDirX( pt.get(
"wind.windDirX", state()->windDirX() ) );
342 state()->windDirZ( pt.get(
"wind.windDirZ", state()->windDirZ() ) );
343 state()->windSpeed( pt.get(
"wind.windSpeed", state()->windSpeed() ) );
345 state()->lightBleedBias( pt.get(
"shadowing.<xmlattr>.lightBleedBias", state()->lightBleedBias() ) );
346 state()->minShadowVariance( pt.get(
"shadowing.<xmlattr>.minShadowVariance", state()->minShadowVariance() ) );
348 dayNightCycleEnabled( pt.get(
"dayNight.<xmlattr>.enabled",
false ) );
349 _dayNightData._time._hour = pt.get<
U8>(
"dayNight.timeOfDay.<xmlattr>.hour", _dayNightData._time._hour );
350 _dayNightData._time._minutes = pt.get<
U8>(
"dayNight.timeOfDay.<xmlattr>.minute", _dayNightData._time._minutes );
351 _dayNightData._location._latitude = pt.get<
F32>(
"dayNight.location.<xmlattr>.latitude", _dayNightData._location._latitude );
352 _dayNightData._location._longitude = pt.get<
F32>(
"dayNight.location.<xmlattr>.longitude", _dayNightData._location._longitude );
353 _dayNightData._speedFactor = pt.get(
"dayNight.timeOfDay.<xmlattr>.timeFactor", _dayNightData._speedFactor );
354 _dayNightData._resetTime =
true;
360 if ( pt.get_child_optional(
"fog" ) )
371 state()->renderState().fogDetails( details );
375 if ( pt.get_child_optional(
"lod" ) )
377 lodThresholds.
set( pt.get<
U16>(
"lod.lodThresholds.<xmlattr>.x", lodThresholds.
x ),
378 pt.get<
U16>(
"lod.lodThresholds.<xmlattr>.y", lodThresholds.
y ),
379 pt.get<
U16>(
"lod.lodThresholds.<xmlattr>.z", lodThresholds.
z ),
380 pt.get<
U16>(
"lod.lodThresholds.<xmlattr>.w", lodThresholds.
w ) );
383 state()->renderState().lodThresholds().set( lodThresholds );
384 sceneGraph()->loadFromXML(
ResourcePath{ pt.get(
"assets",
"assets.xml" ).c_str() } );
385 loadMusicPlaylist( sceneLocation, pt.get(
"musicPlaylist",
"" ).c_str(),
this, config );
395 nodeDescriptor.
_name = name;
402 const U32 componentBit = 1u << i;
419 assert(
parent !=
nullptr );
433 boost::property_tree::ptree nodeTree = {};
438 constexpr U64 primitiveNames[3]
445 for (
const U64 it : primitiveNames )
447 if ( nameHash == it )
456 const std::string modelName = nodeTree.get(
"model",
"" );
458 bool nodeStatic =
true;
466 if ( !modelName.empty() )
471 item.assetName( modelName.c_str() );
475 crtNode =
addSGN(
parent, sceneNode.
name, normalMask, handle, nodeStatic, nodeTree );
480 item.assetName( modelName.c_str() );
484 crtNode =
addSGN(
parent, sceneNode.
name, normalMask, handle, nodeStatic, nodeTree );
489 item.assetName( modelName.c_str() );
494 item.mask( quadMask );
498 Quad3D* quad =
static_cast<Quad3D*
>(ret);
499 quad->setCorner( Quad3D::CornerLocation::TOP_LEFT,
vec3<F32>( 0, 1, 0 ) );
500 quad->setCorner( Quad3D::CornerLocation::TOP_RIGHT,
vec3<F32>( 1, 1, 0 ) );
501 quad->setCorner( Quad3D::CornerLocation::BOTTOM_LEFT,
vec3<F32>( 0, 0, 0 ) );
502 quad->setCorner( Quad3D::CornerLocation::BOTTOM_RIGHT,
vec3<F32>( 1, 0, 0 ) );
504 crtNode =
addSGN(
parent, sceneNode.
name, normalMask, handle, nodeStatic, nodeTree );
511 if ( ret !=
nullptr )
528 case _ID(
"TERRAIN" ):
533 case _ID(
"VEGETATION_GRASS" ):
538 case _ID(
"INFINITE_PLANE" ):
553 if ( !modelName.empty() )
556 model.assetLocation( Paths::g_modelsLocation );
557 model.assetName( modelName.c_str() );
562 nodeStatic = meshPtr->animationCount() == 0u;
563 meshPtr->loadFromXML( nodeTree );
565 crtNode =
addSGN(
parent, sceneNode.
name, normalMask, handle, nodeStatic, nodeTree );
569 case _ID(
"SUBMESH" ):
573 if ( parentTask !=
nullptr && !
idle() )
579 if ( subMesh !=
nullptr )
595 case _ID(
"TRANSFORM" ):
601 crtNode =
addSGN(
parent, sceneNode.
name, normalMask, handle, nodeStatic, nodeTree );
608 if ( childCount == 1u )
612 else if ( childCount > 1u )
621 for ( U32 i = start; i < end; ++i )
623 loadAsset( innerTask, sceneNode.children[i], crtNode );
630 std::shared_ptr<ParticleData> data,
634 "Scene::addParticleEmitter error: invalid name specified!" );
639 DIVIDE_ASSERT( emitter != INVALID_HANDLE<ParticleEmitter>,
"Scene::addParticleEmitter error: Could not instantiate emitter!" );
642 auto initData = [emitter, data]( )
644 if ( !
Get(emitter)->initData( data ) )
650 TaskPool& pool = _context.taskPool( TaskPoolType::ASSET_LOADER );
652 Start( *initTask, pool, TaskPriority::DONT_CARE, initData);
653 Wait( *initTask, pool);
657 particleNodeDescriptor.
_usageContext = NodeUsageContext::NODE_DYNAMIC;
659 to_base( ComponentType::BOUNDS ) |
660 to_base( ComponentType::RENDERING ) |
661 to_base( ComponentType::NETWORKING ) |
662 to_base( ComponentType::SELECTION );
664 return parentNode->
addChildNode( particleNodeDescriptor );
667 void Scene::addTerrain(
SceneGraphNode* parentNode,
const boost::property_tree::ptree& pt,
const Str<64>& nodeName )
669 Console::printfn(
LOCALE_STR(
"XML_LOAD_TERRAIN" ), nodeName.c_str() );
673 Init(ter, nodeName +
"_descriptor" );
681 descriptor.flag( ter._active );
684 Get(terrain)->loadFromXML( pt );
687 terrainNodeDescriptor.
_name = nodeName;
689 terrainNodeDescriptor.
_usageContext = NodeUsageContext::NODE_STATIC;
691 to_base( ComponentType::TRANSFORM ) |
692 to_base( ComponentType::RIGID_BODY ) |
693 to_base( ComponentType::BOUNDS ) |
694 to_base( ComponentType::RENDERING ) |
695 to_base( ComponentType::NETWORKING );
700 nComp->
navigationContext( NavigationComponent::NavigationContext::NODE_OBSTACLE );
716 lightNodeDescriptor.
_name = descriptor.resourceName().c_str();
717 lightNodeDescriptor.
_usageContext = NodeUsageContext::NODE_DYNAMIC;
719 to_base( ComponentType::BOUNDS ) |
720 to_base( ComponentType::NETWORKING ) |
721 to_base( ComponentType::SPOT_LIGHT );
722 flashLight = _sceneGraph->getRoot()->
addChildNode( lightNodeDescriptor );
723 SpotLightComponent* spotLight = flashLight->
get<SpotLightComponent>();
724 spotLight->castsShadows(
true );
725 spotLight->setDiffuseColour( DefaultColours::WHITE.rgb );
728 _flashLight[idx] = flashLight;
730 _cameraUpdateListeners[idx] = playerCamera( idx )->addUpdateListener( [
this, idx](
const Camera& cam )
732 if ( idx < Config::MAX_LOCAL_PLAYER_COUNT && idx < _flashLight.size() && _flashLight[idx] )
734 if ( cam.getGUID() == playerCamera( idx )->getGUID() )
736 TransformComponent* tComp = _flashLight[idx]->get<TransformComponent>();
737 tComp->setPosition( cam.snapshot()._eye );
738 tComp->setRotationEuler( cam.euler() );
744 flashLight->
get<SpotLightComponent>()->toggleEnabled();
753 skyDescriptor.ID(
to_U32( std::floor( Camera::GetUtilityCamera( Camera::UtilityCamera::DEFAULT )->snapshot()._zPlanes.max * 2 ) ) );
757 skyItem->loadFromXML( pt );
761 skyNodeDescriptor.
_name = nodeName;
762 skyNodeDescriptor.
_usageContext = NodeUsageContext::NODE_STATIC;
764 to_base( ComponentType::BOUNDS ) |
765 to_base( ComponentType::RENDERING ) |
766 to_base( ComponentType::NETWORKING );
769 skyNode->
setFlag( SceneGraphNode::Flags::VISIBILITY_LOCKED );
781 Get(water)->loadFromXML( pt );
784 waterNodeDescriptor.
_name = nodeName;
786 waterNodeDescriptor.
_usageContext = NodeUsageContext::NODE_STATIC;
788 to_base( ComponentType::TRANSFORM ) |
789 to_base( ComponentType::RIGID_BODY ) |
790 to_base( ComponentType::BOUNDS ) |
791 to_base( ComponentType::RENDERING ) |
792 to_base( ComponentType::NETWORKING );
803 const Camera* baseCamera = Camera::GetUtilityCamera( Camera::UtilityCamera::DEFAULT );
806 planeDescriptor.data().set( cameraFarPlane, cameraFarPlane, 0u );
808 Get(planeItem)->loadFromXML( pt );
810 DIVIDE_ASSERT( planeItem != INVALID_HANDLE<InfinitePlane>,
"Scene::addInfPlane error: Could not create infinite plane resource!" );
814 planeNodeDescriptor.
_name = nodeName;
815 planeNodeDescriptor.
_usageContext = NodeUsageContext::NODE_STATIC;
817 to_base( ComponentType::BOUNDS ) |
818 to_base( ComponentType::RENDERING );
825 U16 Scene::registerInputActions()
827 _input->flushCache();
829 const auto none = []( [[maybe_unused]]
const InputParams params)
noexcept {};
831 const auto deleteSelection = [
this](
const InputParams params )
833 const PlayerIndex idx = getPlayerIndexForDevice( params._deviceIndex );
834 Selections& playerSelections = _currentSelection[idx];
837 _sceneGraph->removeNode( playerSelections.
_selections[i] );
843 const auto increaseCameraSpeed = [
this](
const InputParams params )
845 Camera* cam = playerCamera( getPlayerIndexForDevice( params._deviceIndex ) );
846 if ( cam->mode() != Camera::Mode::STATIC &&
847 cam->mode() != Camera::Mode::SCRIPTED )
849 if ( cam->speedFactor().
move < Camera::MAX_CAMERA_MOVE_SPEED )
851 cam->speedFactor().
move += 1.f;
853 if ( cam->speedFactor().turn < Camera::MAX_CAMERA_TURN_SPEED )
855 cam->speedFactor().turn += 1.f;
860 const auto decreaseCameraSpeed = [
this](
const InputParams params )
862 Camera* cam = playerCamera( getPlayerIndexForDevice( params._deviceIndex ) );
863 if ( cam->mode() != Camera::Mode::STATIC &&
864 cam->mode() != Camera::Mode::SCRIPTED )
866 if ( cam->speedFactor().
move > 1.f )
868 cam->speedFactor().
move -= 1.f;
870 if ( cam->speedFactor().turn > 1.f )
872 cam->speedFactor().turn -= 1.f;
877 const auto increaseResolution = [
this]( [[maybe_unused]]
const InputParams params )
879 _context.app().windowManager().increaseResolution();
881 const auto decreaseResolution = [
this]( [[maybe_unused]]
const InputParams params )
883 _context.app().windowManager().decreaseResolution();
886 const auto moveForward = [
this](
const InputParams params )
888 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveFB.push( {255u, MoveDirection::POSITIVE} );
891 const auto moveBackwards = [
this](
const InputParams params )
893 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveFB.push( {255u, MoveDirection::NEGATIVE} );
896 const auto stopMoveFWDBCK = [
this](
const InputParams params )
898 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveFB.push( {255u, MoveDirection::NONE});
901 const auto strafeLeft = [
this](
const InputParams params )
903 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveLR.push( {255u, MoveDirection::NEGATIVE} );
906 const auto strafeRight = [
this](
const InputParams params )
908 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveLR.push( {255u, MoveDirection::POSITIVE} );
911 const auto stopStrafeLeftRight = [
this](
const InputParams params )
913 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveLR.push( {255u, MoveDirection::NONE} );
916 const auto rollCCW = [
this](
const InputParams params )
918 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._roll.push( {255u, MoveDirection::NEGATIVE} );
921 const auto rollCW = [
this](
const InputParams params )
923 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._roll.push( {255u, MoveDirection::POSITIVE} );
926 const auto stopRollCCWCW = [
this](
const InputParams params )
928 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._roll.push( {255u, MoveDirection::NONE} );
931 const auto turnLeft = [
this](
const InputParams params )
933 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._angleLR.push( {255u, MoveDirection::NEGATIVE} );
936 const auto turnRight = [
this](
const InputParams params )
938 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._angleLR.push( {255u, MoveDirection::POSITIVE} );
941 const auto stopTurnLeftRight = [
this](
const InputParams params )
943 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._angleLR.push( {255u, MoveDirection::NONE} );
946 const auto turnUp = [
this](
const InputParams params )
948 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._angleUD.push( {255u, MoveDirection::NEGATIVE} );
951 const auto turnDown = [
this](
const InputParams params )
953 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._angleUD.push( {255u, MoveDirection::POSITIVE} );
956 const auto stopTurnUpDown = [
this](
const InputParams params )
958 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._angleUD.push( {255u, MoveDirection::NONE} );
961 const auto togglePauseState = [
this]( [[maybe_unused]]
const InputParams params )
noexcept
963 _context.kernel().timingData().freezeGameTime( !_context.kernel().timingData().freezeGameTime() );
966 const auto takeScreenShot = [
this]( [[maybe_unused]]
const InputParams params )
968 state()->screenshotRequestQueued(
true);
971 const auto toggleFullScreen = [
this]( [[maybe_unused]]
const InputParams params )
973 _context.app().windowManager().toggleFullScreen();
976 const auto toggleFlashLight = [
this](
const InputParams params )
978 toggleFlashlight( getPlayerIndexForDevice( params._deviceIndex ) );
981 const auto lockCameraToMouse = [
this](
const InputParams params )
983 if ( !lockCameraToPlayerMouse( getPlayerIndexForDevice( params._deviceIndex ),
true ) )
988 const auto releaseCameraFromMouse = [
this](
const InputParams params )
990 if ( !lockCameraToPlayerMouse( getPlayerIndexForDevice( params._deviceIndex ),
false ) )
996 const auto shutdown = [
this]( [[maybe_unused]]
const InputParams params )
noexcept
998 _context.app().RequestShutdown(
false);
1001 const auto povNavigation = [
this](
const InputParams params )
1003 const U32 povMask =
to_U32(params._var[0]);
1005 if ( povMask &
to_base( Input::JoystickPovDirection::UP ) )
1007 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveFB.push( {255u, MoveDirection::POSITIVE} );
1009 if ( povMask &
to_base( Input::JoystickPovDirection::DOWN ) )
1011 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveFB.push( { 255u, MoveDirection::NEGATIVE} );
1013 if ( povMask &
to_base( Input::JoystickPovDirection::RIGHT ) )
1015 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveLR.push( { 255u, MoveDirection::POSITIVE} );
1017 if ( povMask &
to_base( Input::JoystickPovDirection::LEFT ) )
1019 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveLR.push( { 255u, MoveDirection::NEGATIVE} );
1021 if ( povMask ==
to_base( Input::JoystickPovDirection::CENTERED ) )
1023 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveLR.push( { 255u, MoveDirection::NONE } );
1024 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveFB.push( { 255u, MoveDirection::NONE } );
1028 const auto axisNavigation = [
this](
const InputParams params )
1030 const U8 axis = params._elementIndex;
1032 [[maybe_unused]]
const bool isGamePad = params._var[0] == 1;
1034 const I32 deadZone = params._var[1];
1035 const I32 axisABS = params._var[2];
1043 if ( axisABS > deadZone )
1045 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._angleUD.push( { axisPercentage, MoveDirection::POSITIVE } );
1047 else if ( axisABS < -deadZone )
1049 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._angleUD.push( { axisPercentage, MoveDirection::NEGATIVE } );
1053 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._angleUD.push( { 255u, MoveDirection::NONE} );
1058 if ( axisABS > deadZone )
1060 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._angleLR.push( { axisPercentage, MoveDirection::POSITIVE } );
1062 else if ( axisABS < -deadZone )
1064 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._angleLR.push( { axisPercentage, MoveDirection::NEGATIVE } );
1068 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._angleLR.push( { 255u, MoveDirection::NONE} );
1074 if ( axisABS < -deadZone )
1076 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveFB.push( { axisPercentage, MoveDirection::POSITIVE} );
1078 else if ( axisABS > deadZone )
1080 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveFB.push( { axisPercentage, MoveDirection::NEGATIVE} );
1084 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveFB.push( { 255u, MoveDirection::NONE} );
1089 if ( axisABS < -deadZone )
1091 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveLR.push( { axisPercentage, MoveDirection::NEGATIVE} );
1093 else if ( axisABS > deadZone )
1095 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveLR.push( { axisPercentage, MoveDirection::POSITIVE} );
1099 state()->playerState( getPlayerIndexForDevice( params._deviceIndex ) )._moveLR.push( { 255u, MoveDirection::NONE} );
1106 const auto toggleDebugInterface = [
this]( [[maybe_unused]]
const InputParams params )
noexcept
1108 _context.debug().enabled( !_context.debug().enabled() );
1111 const auto toggleEditor = [
this]( [[maybe_unused]]
const InputParams params )
1113 if constexpr( Config::Build::ENABLE_EDITOR )
1115 _context.editor().toggle( !_context.editor().running() );
1119 const auto toggleConsole = [
this]( [[maybe_unused]]
const InputParams params )
1121 if constexpr( Config::Build::ENABLE_EDITOR )
1123 _context.gui().getConsole().setVisible( !_context.gui().getConsole().isVisible() );
1127 const auto dragSelectBegin = [
this](
const InputParams params )
1129 beginDragSelection( getPlayerIndexForDevice( params._deviceIndex ),
vec2<I32>( params._var[0], params._var[1] ) );
1131 const auto dragSelectEnd = [
this](
const InputParams params )
1133 endDragSelection( getPlayerIndexForDevice( params._deviceIndex ),
true );
1183 bool Scene::lockCameraToPlayerMouse(
const PlayerIndex index,
const bool lockState )
const noexcept
1185 static bool hadWindowGrab =
false;
1188 state()->playerState( index ).cameraLockedToMouse( lockState );
1190 const DisplayWindow* window = _context.app().windowManager().getFocusedWindow();
1193 if ( window !=
nullptr )
1197 lastMousePosition = WindowManager::GetGlobalCursorPosition();
1198 WindowManager::ToggleRelativeMouseMode(
true );
1202 WindowManager::ToggleRelativeMouseMode(
false );
1203 state()->playerState( index ).resetMoveDirections();
1204 if ( window !=
nullptr )
1208 WindowManager::SetGlobalCursorPosition( lastMousePosition.
x, lastMousePosition.
y );
1217 _sceneGraph->load();
1224 const bool errorState =
false;
1226 setState( ResourceState::RES_LOADING );
1228 Camera* baseCamera = Camera::GetUtilityCamera( Camera::UtilityCamera::DEFAULT );
1229 const F32 hFoV = _context.config().runtime.horizontalFOV;
1231 baseCamera->
setProjection( vFoV, { Camera::s_minNearZ, _context.config().runtime.cameraViewDistance } );
1232 baseCamera->speedFactor().
move = Camera::DEFAULT_CAMERA_MOVE_SPEED;
1233 baseCamera->speedFactor().turn = Camera::DEFAULT_CAMERA_TURN_SPEED;
1238 const size_t childCount = rootChildren.size();
1246 descriptor.
_priority = TaskPriority::DONT_CARE;
1250 Parallel_For( _context.taskPool( TaskPoolType::ASSET_LOADER ), descriptor, [
this, &rootNode, &rootChildren](
const Task* parentTask,
const U32 start,
const U32 end )
1252 for ( U32 i = start; i < end; ++i )
1254 loadAsset( parentTask, rootChildren[i], rootNode );
1260 for (
U32 i = 0u; i < descriptor._iterCount; ++i )
1262 loadAsset(
nullptr, rootChildren[i], rootNode );
1268 const auto& skies = sceneGraph()->getNodesByType( SceneNodeType::TYPE_SKY );
1269 assert( !skies.empty() );
1270 Sky& currentSky = skies[0]->getNode<Sky>();
1271 const auto& dirLights = _lightPool->getLights( LightType::DIRECTIONAL );
1274 for (
auto light : dirLights )
1277 if ( dirLight->tag() == SUN_LIGHT_TAG )
1283 if ( sun !=
nullptr )
1285 sun->castsShadows(
true );
1286 initDayNightCycle( currentSky, *sun );
1291 Console::errorfn(
LOCALE_STR(
"ERROR_SCENE_LOAD" ),
"scene load function" );
1295 loadComplete(
true );
1298 XML::loadDefaultKeyBindings( Paths::g_xmlDataLocation /
"keyBindings.xml",
this );
1303 bool Scene::unload()
1308 U32 totalLoadingTasks = _loadingTasks.load();
1309 while ( totalLoadingTasks > 0 )
1311 const U32 actualTasks = _loadingTasks.load();
1312 if ( totalLoadingTasks != actualTasks )
1314 totalLoadingTasks = actualTasks;
1316 std::this_thread::yield();
1321 for (
const size_t idx : _selectionCallbackIndices )
1323 _parent.parent().removeSelectionCallback( idx );
1325 _selectionCallbackIndices.clear();
1327 _context.pfx().destroyPhysicsScene( *
this );
1330 _xmlSceneGraphRootNode = {};
1331 _flashLight.fill(
nullptr );
1332 _sceneGraph->unload();
1334 loadComplete(
false );
1336 for (
const Player_ptr& player : _scenePlayers )
1344 bool Scene::postLoad()
1348 _sceneGraph->postLoad();
1350 return _context.pfx().initPhysicsScene( *
this );
1353 void Scene::postLoadMainThread()
1355 assert( Runtime::isMainThread() );
1356 setState( ResourceState::RES_LOADED );
1361 return Util::StringFormat( g_defaultPlayerName, idx + 1 );
1369 updateCameraControls( idx );
1370 state()->renderState().renderPass( idx );
1371 state()->playerPass( idx );
1373 if ( state()->playerState().cameraUnderwater() )
1375 _context.gfx().getRenderer().postFX().pushFilter( FilterType::FILTER_UNDERWATER );
1379 _context.gfx().getRenderer().postFX().popFilter( FilterType::FILTER_UNDERWATER );
1383 void Scene::onSetActive()
1387 _aiManager->pauseUpdate(
false );
1389 input()->onSetActive();
1390 _context.sfx().stopMusic();
1391 _context.sfx().dumpPlaylists();
1393 for (
U32 i = 0u; i <
to_base( MusicType::COUNT ); ++i )
1396 if ( !playlist.empty() )
1398 for (
const auto& song : playlist )
1400 _context.sfx().addMusic( i, song.second );
1404 if ( !_context.sfx().playMusic( 0 ) )
1410 assert( playerCount() == 0 );
1411 addPlayerInternal(
false );
1414 void Scene::onRemoveActive()
1418 _aiManager->pauseUpdate(
true );
1420 for ( Player_ptr& player : _scenePlayers )
1422 if ( player !=
nullptr )
1424 Attorney::ProjectManagerScene::removePlayer( _parent.parent(),
this, player->getBoundNode(),
false );
1429 input()->onRemoveActive();
1432 void Scene::addPlayerInternal(
const bool queue )
1437 if ( playerCount() == Config::MAX_LOCAL_PLAYER_COUNT )
1442 const string playerName = GetPlayerSGNName(
static_cast<PlayerIndex>(playerCount()) );
1444 SceneGraphNode* playerSGN( _sceneGraph->findNode( playerName.c_str() ) );
1448 playerDescriptor.ID(playerCount());
1455 playerNodeDescriptor.
_name = playerName.c_str();
1456 playerNodeDescriptor.
_usageContext = NodeUsageContext::NODE_DYNAMIC;
1458 to_base( ComponentType::TRANSFORM ) |
1459 to_base( ComponentType::BOUNDS ) |
1460 to_base( ComponentType::NETWORKING );
1462 playerSGN = root->
addChildNode( playerNodeDescriptor );
1465 Attorney::ProjectManagerScene::addPlayer( _parent.parent(),
this, playerSGN, queue );
1473 assert( idx < Config::MAX_LOCAL_PLAYER_COUNT);
1474 Player_ptr& player = _scenePlayers[getSceneIndexForPlayer( idx )];
1475 assert( player !=
nullptr );
1477 Attorney::ProjectManagerScene::removePlayer( _parent.parent(),
this, player->getBoundNode(),
true );
1480 void Scene::onPlayerAdd(
const Player_ptr& player )
1483 state()->onPlayerAdd( player->index() );
1484 input()->onPlayerAdd( player->index() );
1488 void Scene::onPlayerRemove(
const Player_ptr& player )
1494 input()->onPlayerRemove( idx );
1495 state()->onPlayerRemove( idx );
1496 _cameraUpdateListeners[idx] = 0u;
1497 if ( _flashLight[idx] !=
nullptr )
1499 _sceneGraph->getRoot()->removeChildNode( _flashLight[idx] );
1500 _flashLight[idx] =
nullptr;
1502 _sceneGraph->getRoot()->removeChildNode( player->getBoundNode() );
1504 assert( idx < Config::MAX_LOCAL_PLAYER_COUNT);
1505 _scenePlayers[getSceneIndexForPlayer( idx )] =
nullptr;
1511 for (
U8 i = 0; i < Config::MAX_LOCAL_PLAYER_COUNT; ++i )
1513 if ( _scenePlayers[i] !=
nullptr && _scenePlayers[i]->index() == idx )
1525 return _scenePlayers[getSceneIndexForPlayer( idx )].get();
1528 U8 Scene::getPlayerIndexForDevice(
const U8 deviceIndex )
const
1530 return input()->getPlayerIndexForDevice( deviceIndex );
1542 updateSelectionData( idx, data );
1546 const bool sceneFocused = Config::Build::ENABLE_EDITOR ? !_context.editor().hasFocus() :
true;
1547 const bool sceneHovered = Config::Build::ENABLE_EDITOR ? !_context.editor().isHovered() :
true;
1549 if ( sceneFocused && sceneHovered && !state()->playerState( idx ).cameraLockedToMouse() )
1553 else if ( !sceneHovered )
1555 clearHoverTarget( idx );
1566 Camera* cam = playerCamera( idx );
1567 if ( cam->mode() == Camera::Mode::STATIC ||
1568 cam->mode() == Camera::Mode::SCRIPTED )
1575 playerState.cameraUpdated( updated );
1579 playerState.cameraUnderwater( checkCameraUnderwater( *cam ) );
1585 void Scene::updateSceneState(
const U64 deltaTimeUS )
1589 sceneRuntimeUS( sceneRuntimeUS() + deltaTimeUS );
1592 _state->waterBodies().resize(0);
1593 _sceneGraph->sceneUpdate( deltaTimeUS, *_state );
1594 _aiManager->update( deltaTimeUS );
1597 void Scene::updateSceneStateInternal( [[maybe_unused]]
const U64 deltaTimeUS )
1601 void Scene::onChangeFocus(
const bool hasFocus )
1607 for (
const Player_ptr& player : _scenePlayers )
1609 if (player !=
nullptr)
1611 state()->playerState( player->index() ).resetMoveDirections();
1612 endDragSelection( player->index(),
false );
1615 _parent.parent().wantsMouse(
false );
1628 _tasks.push_back( &taskItem );
1632 Start( taskItem, _context.taskPool( TaskPoolType::HIGH_PRIORITY ), priority );
1636 void Scene::clearTasks()
1638 Console::printfn(
LOCALE_STR(
"STOP_SCENE_TASKS" ) );
1641 for (
const Task* task : _tasks )
1643 Wait( *task, _context.taskPool( TaskPoolType::HIGH_PRIORITY ) );
1649 void Scene::removeTask(
const Task& task )
1654 if ( (*it)->_id == task.
_id )
1656 Wait( **it, _context.taskPool( TaskPoolType::HIGH_PRIORITY ) );
1663 void Scene::processInput( [[maybe_unused]]
PlayerIndex idx, [[maybe_unused]]
const U64 gameDeltaTimeUS, [[maybe_unused]]
const U64 appDeltaTimeUS )
1677 ._timerClass = intervalClass,
1692 ._timerClass = intervalClass,
1701 eastl::for_each( begin( timers ),
1705 const U64 delta = timer.
_timerClass == TimerClass::APP_TIME ? appDeltaUS : gameDeltaUS;
1712 timer._cbk(timer._internalTimerTotal );
1713 timer._internalTimer = 0u;
1719 void Scene::processGUI(
const U64 gameDeltaTimeUS,
const U64 appDeltaTimeUS )
1721 processInternalTimers( appDeltaTimeUS, gameDeltaTimeUS, _guiTimers);
1724 void Scene::processTasks(
const U64 gameDeltaTimeUS,
const U64 appDeltaTimeUS )
1728 static bool increaseWeatherScale =
true;
1730 processInternalTimers( appDeltaTimeUS, gameDeltaTimeUS, _taskTimers );
1732 if ( _dayNightData._skyInstance !=
nullptr )
1734 static struct tm timeOfDay = {};
1736 bool updateSun =
false, updateProbes =
false;
1738 if ( _dayNightData._resetTime )
1740 updateProbes =
true;
1743 _dayNightData._resetTime =
false;
1744 _dayNightData._timeAccumulatorSec = 0.f;
1745 _dayNightData._timeAccumulatorHour = 0.f;
1747 const time_t t = time(
nullptr );
1748 timeOfDay = *localtime( &t );
1749 timeOfDay.tm_hour = _dayNightData._time._hour;
1750 timeOfDay.tm_min = _dayNightData._time._minutes;
1753 if (!updateSun && !updateProbes)
1755 const F32 speedFactor = dayNightCycleEnabled() ? _dayNightData._speedFactor : 0.f;
1756 const F32 deltaSeconds = Time::MillisecondsToSeconds<F32>( gameDeltaTimeUS );
1757 const F32 addTime = speedFactor * deltaSeconds;
1758 if ( addTime > 0.f )
1760 _dayNightData._timeAccumulatorSec += addTime;
1761 _dayNightData._timeAccumulatorHour += addTime;
1762 Atmosphere atmosphere = _dayNightData._skyInstance->atmosphere();
1765 increaseWeatherScale =
false;
1767 else if ( atmosphere.
_cloudCoverage < 0.1f && !increaseWeatherScale )
1769 increaseWeatherScale =
true;
1771 atmosphere.
_cloudCoverage += (deltaSeconds * (increaseWeatherScale ? 0.001f : -0.001f));
1773 _dayNightData._skyInstance->setAtmosphere( atmosphere );
1777 if ( std::abs( _dayNightData._timeAccumulatorSec ) > Time::Seconds( 1.f ) )
1779 _dayNightData._timeAccumulatorSec = 0.f;
1782 timeOfDay.tm_sec +=
to_I32( _dayNightData._timeAccumulatorSec );
1784 if ( std::abs(_dayNightData._timeAccumulatorHour) > Time::Hours( 1.f ) )
1786 _dayNightData._timeAccumulatorHour = 0.f;
1787 updateProbes =
true;
1794 _dayNightData._time._hour =
to_U8( timeOfDay.tm_hour );
1795 _dayNightData._time._minutes =
to_U8( timeOfDay.tm_min );
1798 const time_t now = mktime( &timeOfDay );
1799 const SunInfo details = _dayNightData._skyInstance->setDateTimeAndLocation( localtime( &now ), _dayNightData._location );
1808 const bool isNight = sunAltitude < twilightDegrees;
1810 const bool isDawn = isTwilight && sunAzimuth < sunriseAzimuth;
1811 const bool isDusk = isTwilight && sunAzimuth > sunsetAzimuth;
1814 const vec3<F32> sunPosition = _dayNightData._skyInstance->getSunPosition( _dayNightData._sunLight->range() );
1819 const FColour3 sunsetOrange{ 99.2f / 100.f, 36.9f / 100.f, 32.5f / 100.f };
1820 const FColour3 sunColour = DefaultColours::WHITE.rgb;
1821 const FColour3 moonColour =
Normalized( _dayNightData._skyInstance->moonColour().rgb );
1826 _dayNightData._sunLight->setDiffuseColour(
Lerp( sunsetOrange, sunColour, std::abs(sunAltitude / twilightDegrees ) ) );
1832 _dayNightData._sunLight->setDiffuseColour(
Lerp( sunsetOrange, moonColour, std::abs( sunAltitude / twilightDegrees ) ) );
1838 _dayNightData._sunLight->setDiffuseColour( moonColour );
1844 _dayNightData._sunLight->setDiffuseColour( sunColour );
1846 _dayNightData._sunLight->sgn()->get<
TransformComponent>()->setPosition( sunPosition );
1850 if ( updateProbes && _envProbePool !=
nullptr )
1852 SceneEnvironmentProbePool::OnTimeOfDayChange( *_envProbePool );
1861 if ( _linesPrimitive->hasBatch() )
1863 GFX::EnqueueCommand<GFX::SetViewportCommand>( bufferInOut )->_viewport = targetViewport;
1864 _linesPrimitive->getCommandBuffer( bufferInOut, memCmdInOut );
1873 _aiManager->debugDraw( bufferInOut, memCmdInOut,
false );
1874 _lightPool->drawLightImpostors( bufferInOut );
1881 const Camera* crtCamera = Attorney::ProjectManagerCameraAccessor::playerCamera( _parent.parent(), idx );
1882 return checkCameraUnderwater( *crtCamera );
1885 bool Scene::checkCameraUnderwater(
const Camera& camera )
const noexcept
1887 const vec3<F32>& eyePos = camera.snapshot()._eye;
1889 const auto& waterBodies = state()->waterBodies();
1892 const vec3<F32>& extents = water._extents;
1893 const vec3<F32>& position = water._positionW;
1894 const F32 halfWidth = (extents.
x + position.
x) * 0.5f;
1895 const F32 halfLength = (extents.
z + position.
z) * 0.5f;
1896 if ( eyePos.
x >= -halfWidth && eyePos.
x <= halfWidth &&
1897 eyePos.
z >= -halfLength && eyePos.
z <= halfLength )
1899 const float depth = -extents.
y + position.
y;
1900 return eyePos.
y < position.
y&& eyePos.
y > depth;
1914 SceneNodeType::TYPE_TRANSFORM,
1915 SceneNodeType::TYPE_WATER,
1916 SceneNodeType::TYPE_SKY,
1917 SceneNodeType::TYPE_PARTICLE_EMITTER,
1918 SceneNodeType::TYPE_INFINITEPLANE,
1919 SceneNodeType::TYPE_VEGETATION
1922 const Camera* crtCamera = playerCamera( idx );
1923 const vec2<U16> renderingResolution = _context.gfx().renderingResolution();
1929 renderingResolution.width,
1930 renderingResolution.height
1934 _sceneSelectionCandidates.resize( 0 );
1944 sceneGraph()->intersect( intersectionParams, _sceneSelectionCandidates );
1946 if ( !_sceneSelectionCandidates.empty() )
1949 eastl::sort( begin( _sceneSelectionCandidates ),
1950 end( _sceneSelectionCandidates ),
1957 for (
const SGNRayResult& result : _sceneSelectionCandidates )
1959 if ( result.inside || result.dist < 0.0f )
1964 SceneGraphNode* crtNode = _sceneGraph->findNode( result.sgnGUID );
1971 if ( Config::Build::ENABLE_EDITOR && _context.editor().inEditMode() )
1985 if ( crtNode->
getNode().type() == SceneNodeType::TYPE_SUBMESH )
1990 crtNode = crtNode->parent();
1991 if ( crtNode !=
nullptr )
1998 clearHoverTarget( idx );
2000 if ( target !=
nullptr )
2002 _currentHoverTarget[idx] = target->getGUID();
2003 if ( !target->hasFlag( SceneGraphNode::Flags::SELECTED ) )
2005 target->setFlag( SceneGraphNode::Flags::HOVERED,
true );
2011 clearHoverTarget( idx );
2019 if ( _currentHoverTarget[idx] != -1 )
2021 SceneGraphNode* oldTarget = _sceneGraph->findNode( _currentHoverTarget[idx] );
2022 if ( oldTarget !=
nullptr )
2024 oldTarget->
clearFlag( SceneGraphNode::Flags::HOVERED );
2028 _currentHoverTarget[idx] = -1;
2034 for (
I64& target : _currentHoverTarget )
2036 if ( target == guid )
2042 for (
Selections& playerSelections : _currentSelection )
2044 for (
I16 i =
to_I16(playerSelections._selectionCount); i > 0; --i )
2046 const size_t idx =
to_size(i - 1);
2048 const I64 crtGUID = playerSelections._selections[idx];
2049 if ( crtGUID == guid )
2051 playerSelections._selections[idx] = -1;
2052 std::swap( playerSelections._selections[idx], playerSelections._selections[playerSelections._selectionCount--] );
2057 _parent.parent().onNodeDestroy(
this, node );
2060 bool Scene::resetSelection(
const PlayerIndex idx,
const bool resetIfLocked )
2062 Selections& tempSelections = _tempSelection[idx];
2063 Selections& playerSelections = _currentSelection[idx];
2066 tempSelections = {};
2068 for (
U8 i = 0; i < selectionCount; ++i )
2071 if ( node !=
nullptr && (!node->
hasFlag( SceneGraphNode::Flags::SELECTION_LOCKED ) || resetIfLocked) )
2073 node->
clearFlag( SceneGraphNode::Flags::HOVERED,
true );
2074 node->
clearFlag( SceneGraphNode::Flags::SELECTED,
true );
2076 else if ( node !=
nullptr )
2082 playerSelections = tempSelections;
2088 Selections& playerSelections = _currentSelection[idx];
2092 if ( !sgn->hasFlag( SceneGraphNode::Flags::SELECTED ) )
2095 sgn->setFlag( SceneGraphNode::Flags::SELECTED, recursive );
2102 return _currentSelection[index];
2105 bool Scene::findSelection(
const PlayerIndex idx,
const bool clearOld )
2110 if ( !_parent.parent().resetSelection( idx,
false ) )
2116 const I64 hoverGUID = _currentHoverTarget[idx];
2118 if ( hoverGUID == -1 )
2123 Selections& playerSelections = _currentSelection[idx];
2126 if ( playerSelections.
_selections[i] == hoverGUID )
2133 SceneGraphNode* selectedNode = _sceneGraph->findNode( hoverGUID );
2134 if ( selectedNode !=
nullptr )
2136 _parent.parent().setSelected( idx, { selectedNode }, false );
2139 if ( !_parent.parent().resetSelection( idx,
false ) )
2148 if constexpr( Config::Build::ENABLE_EDITOR )
2150 if ( _context.editor().running() && _context.editor().isHovered() )
2164 static std::array<Line, 4> s_lines = {
2165 Line{VECTOR3_ZERO, VECTOR3_UNIT, DefaultColours::GREEN_U8, DefaultColours::GREEN_U8, 2.0f, 1.0f},
2166 Line{VECTOR3_ZERO, VECTOR3_UNIT, DefaultColours::GREEN_U8, DefaultColours::GREEN_U8, 2.0f, 1.0f},
2167 Line{VECTOR3_ZERO, VECTOR3_UNIT, DefaultColours::GREEN_U8, DefaultColours::GREEN_U8, 2.0f, 1.0f},
2168 Line{VECTOR3_ZERO, VECTOR3_UNIT, DefaultColours::GREEN_U8, DefaultColours::GREEN_U8, 2.0f, 1.0f}
2171 if constexpr( Config::Build::ENABLE_EDITOR )
2173 const Editor& editor = _context.editor();
2176 endDragSelection( idx,
false );
2181 _parent.parent().wantsMouse(
true );
2183 const vec2<U16> resolution = _context.gfx().renderingResolution();
2189 const I32 startX = std::min( startPos.
x, endPos.
x );
2190 const I32 startY = std::min( startPos.
y, endPos.
y );
2195 std::abs( endPos.
x - startPos.
x ),
2196 std::abs( endPos.
y - startPos.
y )
2200 s_lines[0]._positionStart = { selectionRect.
x, selectionRect.y, 0 };
2201 s_lines[0]._positionEnd = { selectionRect.x + selectionRect.z, selectionRect.y, 0 };
2204 s_lines[1]._positionStart = { selectionRect.x + selectionRect.z, selectionRect.y, 0 };
2205 s_lines[1]._positionEnd = { selectionRect.x + selectionRect.z, selectionRect.y + selectionRect.w, 0 };
2208 s_lines[2]._positionStart = s_lines[1]._positionEnd;
2209 s_lines[2]._positionEnd = { selectionRect.x, selectionRect.y + selectionRect.w, 0 };
2212 s_lines[3]._positionStart = s_lines[2]._positionEnd;
2213 s_lines[3]._positionEnd = s_lines[0]._positionStart;
2215 _linesPrimitive->fromLines( s_lines.data(), s_lines.size() );
2217 if ( GFXDevice::FrameCount() % 2 == 0 )
2219 clearHoverTarget( idx );
2220 if ( _parent.parent().resetSelection( idx,
false ) )
2222 const Camera* crtCamera = playerCamera( idx );
2225 Attorney::ProjectManagerScene::getNodesInScreenRect( _parent.parent(), selectionRect, *crtCamera, nodes );
2227 _parent.parent().setSelected( idx, nodes,
false );
2232 void Scene::endDragSelection(
const PlayerIndex idx,
const bool clearSelection )
2234 constexpr F32 DRAG_SELECTION_THRESHOLD_PX_SQ = 9.f;
2238 _linesPrimitive->clearBatch();
2239 _parent.parent().wantsMouse(
false );
2243 if ( !findSelection( idx, clearSelection ) )
2250 void Scene::initDayNightCycle( Sky& skyInstance, DirectionalLightComponent& sunLight )
noexcept
2252 _dayNightData._skyInstance = &skyInstance;
2253 _dayNightData._sunLight = &sunLight;
2254 if ( !_dayNightData._resetTime )
2257 _dayNightData._time = skyInstance.GetTimeOfDay();
2258 _dayNightData._resetTime =
true;
2260 _dayNightData._timeAccumulatorSec = Time::Seconds( 1.1f );
2261 _dayNightData._timeAccumulatorHour = 0.f;
2262 sunLight.lockDirection(
true );
2264 const vec3<F32> sunPosition = _dayNightData._skyInstance->getSunPosition( sunLight.range() );
2268 void Scene::setDayNightCycleTimeFactor(
const F32 factor )
noexcept
2270 _dayNightData._speedFactor = factor;
2273 F32 Scene::getDayNightCycleTimeFactor() const noexcept
2275 return _dayNightData._speedFactor;
2280 _dayNightData._time = time;
2281 _dayNightData._resetTime =
true;
2286 return _dayNightData._time;
2291 _dayNightData._location = location;
2292 _dayNightData._resetTime =
true;
2297 return _dayNightData._location;
2302 if ( _dayNightData._sunLight !=
nullptr )
2311 if ( _dayNightData._sunLight !=
nullptr )
2319 SunInfo Scene::getCurrentSunDetails() const noexcept
2321 if ( _dayNightData._skyInstance !=
nullptr )
2323 return _dayNightData._skyInstance->getCurrentDetails();
2331 if ( _dayNightData._skyInstance !=
nullptr )
2333 return _dayNightData._skyInstance->atmosphere();
2339 void Scene::setCurrentAtmosphere(
const Atmosphere& atmosphere )
const noexcept
2341 if ( _dayNightData._skyInstance !=
nullptr )
2343 return _dayNightData._skyInstance->setAtmosphere( atmosphere );
2349 outputBuffer << BYTE_BUFFER_VERSION;
2350 const U8 plCount = playerCount();
2351 outputBuffer << plCount;
2352 for (
const Player_ptr& player : _scenePlayers )
2354 if ( player !=
nullptr )
2356 const Camera* cam = player->camera();
2361 return _sceneGraph->saveCache( outputBuffer );
2369 auto tempVer =
decltype(BYTE_BUFFER_VERSION){0};
2370 inputBuffer >> tempVer;
2371 if ( tempVer == BYTE_BUFFER_VERSION )
2373 const U8 currentPlayerCount = playerCount();
2378 U8 currentPlayerIndex = 0u;
2379 U8 previousPlayerCount = 0u;
2380 inputBuffer >> previousPlayerCount;
2381 for (
U8 i = 0; i < previousPlayerCount; ++i )
2383 inputBuffer >> currentPlayerIndex >> camPos >> camOrientation;
2384 if ( currentPlayerIndex < currentPlayerCount )
2386 Camera* cam = _scenePlayers[currentPlayerIndex]->camera();
2389 state()->playerState( currentPlayerIndex ).cameraUnderwater( checkCameraUnderwater( *cam ) );
2399 return _sceneGraph->loadCache( inputBuffer );
2402 Camera* Scene::playerCamera(
const bool skipOverride )
const
2404 return Attorney::ProjectManagerCameraAccessor::playerCamera( _parent.parent(), skipOverride );
2407 Camera* Scene::playerCamera(
const U8 index,
const bool skipOverride )
const
2409 return Attorney::ProjectManagerCameraAccessor::playerCamera( _parent.parent(), index, skipOverride );
2416 scene->_envProbePool->registerProbe( probe );
2423 scene->_envProbePool->unregisterProbe( probe );
#define WAIT_FOR_CONDITION(...)
#define PROFILE_SCOPE_AUTO(CATEGORY)
bool bufferEmpty() const noexcept
Returns true if the read position and the write position are identical.
const mat4< F32 > & setProjection(vec2< F32 > zPlanes)
const CameraSnapshot & snapshot() const noexcept
Returns the internal camera snapshot data (eye, orientation, etc)
bool updateLookAt()
Return true if the cached camera state wasn't up-to-date.
bool moveFromPlayerState(const SceneStatePerPlayer &playerState)
vec3< F32 > unProject(F32 winCoordsX, F32 winCoordsY, const Rect< I32 > &viewport) const noexcept
void setEye(const F32 x, const F32 y, const F32 z) noexcept
Sets the camera's eye position.
void saveToXML(boost::property_tree::ptree &pt, std::string prefix="") const
void setRotation(const Quaternion< F32 > &q) noexcept
Sets the camera's orientation.
void move(F32 dx, F32 dy, F32 dz) noexcept
Moves the camera by the specified offsets in each direction.
bool grabState() const noexcept
IMPrimitive * newIMP(std::string_view name)
Create and return a new immediate mode emulation primitive.
bool destroyIMP(IMPrimitive *&primitive)
FORCE_INLINE I64 getGUID() const noexcept
void setPipelineDescriptor(const PipelineDescriptor &descriptor)
const NavigationContext & navigationContext() const noexcept
PlatformContext & context() noexcept
PlatformContext & _context
TaskPool & taskPool(const TaskPoolType type) noexcept
GFXDevice & gfx() noexcept
Configuration & config() noexcept
void clearFlag(Flags flag, bool recursive=true)
Clearing a flag might propagate to child nodes (e.g. selection).
void setFlag(Flags flag, bool recursive=true)
General purpose flag management. Certain flags propagate to children (e.g. selection)!
SceneGraphNode * addChildNode(const SceneGraphNodeDescriptor &descriptor)
Add child node increments the node's ref counter if the node was already added to the scene graph.
FORCE_INLINE T * get() const
Returns a pointer to a specific component. Returns null if the SGN does not have the component reques...
bool hasFlag(const Flags flag) const noexcept
Returns true only if the current node has the specified flag. Does not check children!
void loadFromXML(const ResourcePath &sceneLocation)
static bool OnStartup(PlatformContext &context)
static I64 DEFAULT_SCENE_GUID
IMPrimitive * _linesPrimitive
virtual ~Scene() override
static ResourcePath GetSceneRootFolder(const Project &project)
Return the full path to the location of Scenes folder in the project (e.g. ./Projects/Foo/Scenes/ for...
std::array< U32, Config::MAX_LOCAL_PLAYER_COUNT > _cameraUpdateListeners
virtual bool frameEnded()
bool saveNodeToXML(const SceneGraphNode *node) const
static ResourcePath GetSceneFullPath(const Scene &scene)
Return the full path to the scene's location on disk. It's equivalent to GetSceneRootFolder(scene....
std::array< SceneGraphNode *, Config::MAX_LOCAL_PLAYER_COUNT > _flashLight
virtual bool frameStarted()
void loadAsset(const Task *parentTask, const XML::SceneNode &sceneNode, SceneGraphNode *parent)
void addWater(SceneGraphNode *parentNode, const boost::property_tree::ptree &pt, const Str< 64 > &nodeName="")
Project & parent() noexcept
SceneGraphNode * addInfPlane(SceneGraphNode *parentNode, const boost::property_tree::ptree &pt, const Str< 64 > &nodeName="")
void addMusic(MusicType type, const std::string_view name, const ResourcePath &srcFile)
Camera * playerCamera(const bool skipOverride=false) const
Scene(PlatformContext &context, Project &parent, const SceneEntry &entry)
virtual bool saveXML(const DELEGATE< void, std::string_view > &msgCallback, const DELEGATE< void, bool > &finishCallback) const
Can save at any time, I guess?
static bool OnShutdown(PlatformContext &context)
bool loadNodeFromXML(SceneGraphNode *node) const
SceneGraphNode * addSky(SceneGraphNode *parentNode, const boost::property_tree::ptree &pt, const Str< 64 > &nodeName="")
std::array< I64, Config::MAX_LOCAL_PLAYER_COUNT > _currentHoverTarget
bool idle()
Scene is rendering, so add intensive tasks here to save CPU cycles.
void addTerrain(SceneGraphNode *parentNode, const boost::property_tree::ptree &pt, const Str< 64 > &nodeName="")
std::atomic_uint _loadingTasks
virtual void setMaterialTpl(Handle< Material > material)
virtual void loadFromXML(const boost::property_tree::ptree &pt)
hashMap< U64, Handle< AudioDescriptor > > MusicPlaylist
Background music map : trackName - track.
std::shared_ptr< T > getUnit() const noexcept
T distanceSquared(const vec2 &v) const noexcept
compute the vector's squared distance to another specified vector
void get(T *v) const noexcept
void set(const T *v) noexcept
set the 4 components of the vector manually using a source pointer to a (large enough) array
constexpr bool IS_SHIPPING_BUILD
void OnStartup(const PlatformContext &context)
constexpr Optick::Category::Type Scene
const char * ComponentTypeToString(const ComponentType compType) noexcept
Str StringFormat(const char *fmt, Args &&...args)
bool CompareIgnoreCase(const char *a, const char *b) noexcept
string MakeXMLSafe(std::string_view subject)
void writeXML(const ResourcePath &path, const boost::property_tree::ptree &tree)
void readXML(const ResourcePath &path, boost::property_tree::ptree &tree)
constexpr const char *const g_defaultPlayerName
Handle console commands that start with a forward slash.
vec2< T > Normalized(vec2< T > vector) noexcept
DELEGATE_STD< Ret, Args... > DELEGATE
void updateSceneStateInternal(U64 deltaTimeUS) override
std::lock_guard< mutex > LockGuard
constexpr U32 to_U32(const T value)
T Lerp(T v1, T v2, U t) noexcept
void insert(eastl::vector< T, A1 > &target, const eastl::vector< T, A2 > &source)
FORCE_INLINE constexpr bool IsPrimitive(const SceneNodeType type) noexcept
bool IS_IN_RANGE_INCLUSIVE(const T x, const U min, const U max) noexcept
void Wait(const Task &task, TaskPool &pool)
bool DebugBreak(const bool condition) noexcept
@ RES_LOADED
The resource is available for usage.
Task * CreateTask(Predicate &&threadedFunction, bool allowedInIdle=true)
constexpr F32 to_F32(const T value)
bool Finished(const Task &task) noexcept
constexpr D64 to_D64(const T value)
SceneNodeType
ToDo: Move particle emitter to components (it will make them way more dynamic) - Ionut.
DirectionalLightComponent(SceneGraphNode *sgn, PlatformContext &context)
constexpr U16 BYTE_BUFFER_VERSION
FileError createDirectory(const ResourcePath &path)
eastl::vector< Type > vector
std::shared_lock< mutex > SharedLock
FileError copyFile(const ResourcePath &sourcePath, const std::string_view sourceName, const ResourcePath &targetPath, const std::string_view targetName, const bool overwrite)
bool LoadFromXML(TerrainDescriptor &descriptor, const boost::property_tree::ptree &pt, std::string_view name)
constexpr U64 _ID(const char *const str, const U64 value=val_64_const) noexcept
FORCE_INLINE Handle< T > CreateResource(const ResourceDescriptor< T > &descriptor, bool &wasInCache, std::atomic_uint &taskCounter)
constexpr U8 to_U8(const T value)
constexpr I16 to_I16(const T value)
string GetVariable(const TerrainDescriptor &descriptor, std::string_view name)
void Start(Task &task, TaskPool &pool, TaskPriority priority=TaskPriority::DONT_CARE, const DELEGATE< void > &onCompletionFunction={})
SceneNodeHandle FromHandle(const Handle< T > handle)
constexpr size_t to_size(const T value)
SceneGraphNode * addSGN(SceneGraphNode *parent, const std::string_view name, const U32 componentMask, const Handle< T > handle, const bool nodeStatic, boost::property_tree::ptree &nodeTree)
void Parallel_For(TaskPool &pool, const ParallelForDescriptor &descriptor, const DELEGATE< void, const Task *, U32, U32 > &cbk)
bool fileExists(const ResourcePath &filePathAndName)
constexpr I32 to_I32(const T value)
void setDirection(const vec3< F32 > &direction)
bool dvd_erase_if(eastl::vector< T, A > &vec, Predicate &&pred)
FORCE_INLINE T * Get(const Handle< T > handle)
void Init(ImTextureID texture1, ImTextureID texture2, ImTextureID dockTexture)
Project const SceneEntry & entry
U16 registerInputActions() override
FileNameAndPath splitPathToNameAndLocation(const ResourcePath &input)
constexpr auto to_base(const Type value) -> Type
Quaternion< F32 > _orientation
vec4< U16 > lodThresholds
struct Divide::Configuration::Rendering rendering
static NO_INLINE void errorfn(const char *format, T &&... args)
static NO_INLINE void printfn(const char *format, T &&... args)
vec2< I32 > _startDragPos
vec4< F32 > _colourAndDensity
vec4< F32 > _colourSunScatter
bool _allowPoolIdle
If true, we'll inform the thread pool to execute other tasks while waiting for the all async tasks to...
U32 _partitionSize
How many elements should we process per async task.
bool _useCurrentThread
If true, we'll process a for partition on the calling thread.
bool _waitForFinish
If this is false, the Parallel_For call won't block the current thread.
TaskPriority _priority
Each async task will start with the same priority specified here.
U32 _iterCount
For loop iteration count.
Handle< ShaderProgram > _shaderProgramHandle
RenderStateBlock _stateBlock
const SceneNodeType * _ignoredTypes
bool _includeTransformNodes
size_t _ignoredTypesCount
const TimerClass _timerClass
const U64 _callbackIntervalUS
SceneNodeHandle _nodeHandle
NodeUsageContext _usageContext
std::array< I64, MAX_SELECTIONS > _selections
Angle::RADIANS< F32 > azimuth
Angle::RADIANS< F32 > altitude
vector< SceneNode > children