UE5 C++ LevelSequence

前言

       最近在用UE C++做一些功能,用到了Level Sequence功能,但是看了下UE官方论坛包括一些文章基本没有关于C++ 处理Level Sequence 这块内容,有的也是一些修改或者源码原理的一些内容分析,接下来我就把我新建Sequence包括一些库的调用写下来,基本上把源码翻了一遍了。

过程

       因为我这是基本走了一遍UE官方的新建的流程,所以我这里UE的插件模式Editor Toolbar Button模式。

       创建完这个模式的插件以后,需要我们在Edit -> Edit Preferences -> Miscellaneous中将Display UI extension Poins勾选,因为我们是一个编辑器按钮的插件,所以我们要知道我们的插件按钮放在哪个UI层级下面,开启这个勾选以后,它就会显示对应的层级关系。

       创建完插件同步代码以后,在我们的插件Source文件中就会默认.h / Commands.h  / Style.h三个文件默认就是我们用来处理常规逻辑的,Commadns是我们同步编辑器一些配置用的,Style就是我们这个插件的一些样式内容了,我们可以先打开Commans.cpp文件编辑按钮名称以及鼠标提示词

       然后打开我们的默认CPP文件,因为我这里是不需要插件按钮在其他地方显示出来的,所以我就把PlayToolBar这边的显示注解掉了,如果大家有需要去开启就好了。设置完成以后,点击编译,运行我们的项目这时你就会发现在我们创建UE LevelSequence的地方就有了一个我们自己的插件

       现在我们这个Level Sequence插件就基本创建完成了,在我们的编辑器中有一个自己的按钮了,接下来我们来实现逻辑,第一步如UE一样,我们也打开一个Save Asset 的窗口对我们的Level Sequence 进行命名和路径选择。创建一个函数,命名为CreateLevelSequenceAsset,这步的操作我是在Movice下面的LevelSequenceEditor里面找到的,他主要就是打开一个UE窗口创建一个Level Sequence资产

       我这里创建完Level Sequence以后是创建了一个CameraCut然后又创建了一个摄像机,将这个摄像机绑定到了CameraCut上面作为了一个默认设置。我是先在场景中创建了相机,这个逻辑处理过程是如果这个场景中没有这个摄像机我就进行创建,有的话就不创建了,这样我所有的LevelSequence都用的一个摄像机,如果大家不需要这么做就修改一下逻辑就好了,创建相机这块很简单,创建了一个相机类,代码如下:

ACameraActor* DoseCineCameraExist()
{UWorld* World = GWorld;bool bCineCameraExists = false;for (TActorIterator<ACameraActor> It(World); It; ++It){ACameraActor* ExistingCineCameraActor = *It;if (ExistingCineCameraActor && ExistingCineCameraActor->GetActorLabel() == "MainCamera"){bCineCameraExists = true;// 如果存在指定名称的 CineCameraActor,则直接返回该 Actorreturn ExistingCineCameraActor;break;}}if (!bCineCameraExists){FActorSpawnParameters SpawnParams;ACameraActor* NewCineCameraActor = GWorld->SpawnActor<ACameraActor>(ACameraActor::StaticClass(), FVector::ZeroVector, FRotator::ZeroRotator, SpawnParams);// 设置新创建的 CineCameraActor 的位置和旋转if (NewCineCameraActor){NewCineCameraActor->SetActorLabel("MainCamera");// 设置位置和旋转NewCineCameraActor->SetActorLocation(FVector(0, 0, 50));NewCineCameraActor->SetActorRotation(FRotator(0, 0, 0));}return NewCineCameraActor;}return nullptr;
}

       现在,我们进行主功能,就是创建一个CameraCut然后将我们的摄像机绑定上去,接下来的主要逻辑顺序基本分层为创建一个对应类型的Track然后设置其属性或者Section。代码如下:

	if (NewAsset && NewAsset->IsA<ULevelSequence>()){//将CameraCut添加到Seq中ULevelSequence* levelsequence = static_cast<ULevelSequence*>(NewAsset);UMovieSceneCameraCutTrack* CameraCutTrack = Cast<UMovieSceneCameraCutTrack>(levelsequence->MovieScene->GetCameraCutTrack());CameraCutTrack = Cast<UMovieSceneCameraCutTrack>(levelsequence->MovieScene->AddCameraCutTrack(UMovieSceneCameraCutTrack::StaticClass()));//定义相机以及Transform数据AActor* cameraActor = DoseCineCameraExist();FVector DefaultLocation = FVector::ZeroVector;FVector DefaultRotation = FVector::ZeroVector;FVector DefaultScale = FVector::OneVector;DefaultLocation = cameraActor->GetActorLocation();DefaultRotation = cameraActor->GetActorRotation().Euler();DefaultScale = cameraActor->GetActorScale();if (cameraActor){FGuid Guid = levelsequence->FindBindingFromObject(cameraActor, cameraActor->GetWorld());Guid = Cast<UMovieSceneSequence>(levelsequence)->CreatePossessable(cameraActor);int32 StartFrame = 0;int32 EndFrame = 50;int FrameTickValue = levelsequence->MovieScene->GetTickResolution().AsDecimal();UMovieSceneCameraCutSection* Section = CameraCutTrack->AddNewCameraCut(UE::MovieScene::FRelativeObjectBindingID(Guid), FFrameNumber(StartFrame * FrameTickValue));Section->SetEndFrame(FFrameNumber(EndFrame * FrameTickValue));Section->SetIsLocked(true);levelsequence->PostEditChange();UMovieScene3DTransformTrack* TransformTrack = levelsequence->GetMovieScene()->AddTrack<UMovieScene3DTransformTrack>(Guid);UMovieScene3DTransformSection* TransformSection = Cast<UMovieScene3DTransformSection>(TransformTrack->CreateNewSection());TransformTrack->AddSection(*TransformSection);TransformSection->SetRange(TRange<FFrameNumber>(FFrameNumber(0), FFrameNumber(150)));TArrayView<FMovieSceneDoubleChannel*> DoubleChannels = TransformSection->GetChannelProxy().GetChannels<FMovieSceneDoubleChannel>();DoubleChannels[0]->AddCubicKey(0, DefaultLocation.X);DoubleChannels[1]->AddCubicKey(0, DefaultLocation.Y);DoubleChannels[2]->AddCubicKey(0, DefaultLocation.Z);DoubleChannels[3]->AddCubicKey(0, DefaultRotation.X);DoubleChannels[4]->AddCubicKey(0, DefaultRotation.Y);DoubleChannels[5]->AddCubicKey(0, DefaultRotation.Z);DoubleChannels[6]->AddCubicKey(0, DefaultScale.X);DoubleChannels[7]->AddCubicKey(0, DefaultScale.Y);DoubleChannels[8]->AddCubicKey(0, DefaultScale.Z);levelsequence->PostEditChange();}}

       具体的实现代码看下顺序其实就就能看出来的过程比较顺利,这样我们就已经在我们的工程中创建了一个LevelSequence了,但是UE中创建的LevelSequence后会自动打开这个LevelSequecne编辑器进行动画编辑我们也把这块加上。

	// Spawn an actor at the origin, and either move infront of the camera or focus camera on it (depending on the viewport) and open for editUActorFactory* ActorFactory = GEditor->FindActorFactoryForActorClass(ALevelSequenceActor::StaticClass());if (!ensure(ActorFactory)){return;}AActor* Actor = GEditor->UseActorFactory(ActorFactory, FAssetData(NewAsset), &FTransform::Identity);if (Actor == nullptr){return;}ALevelSequenceActor* NewActor = CastChecked<ALevelSequenceActor>(Actor);if (GCurrentLevelEditingViewportClient != nullptr && GCurrentLevelEditingViewportClient->IsPerspective()){GEditor->MoveActorInFrontOfCamera(*NewActor, GCurrentLevelEditingViewportClient->GetViewLocation(), GCurrentLevelEditingViewportClient->GetViewRotation().Vector());}else{GEditor->MoveViewportCamerasToActor(*NewActor, false);}GEditor->GetEditorSubsystem<UAssetEditorSubsystem>()->OpenEditorForAsset(NewAsset);

       现在我们已经完成了打开-> 创建-> 保存 ->打开编辑器工作,接下来我把需要的头文件引用和环境应用配置进行一下,这个UE C++ levelsequence工作就完成了,第一步打开我们的uplugin文件我

们将LevelSequenceEditor配置一下,在modules中添加AdditionalDependencies然后保存

{"FileVersion": 3,"Version": 1,"VersionName": "1.0","FriendlyName": "ViewSequence","Description": "","Category": "MainSequence","CreatedBy": "筱星辰","CreatedByURL": "","DocsURL": "","MarketplaceURL": "","SupportURL": "","CanContainContent": false,"Installed": true,"Modules": [{"Name": "ViewSequence","Type": "Runtime","LoadingPhase": "Default","AdditionalDependencies": ["LevelSequenceEditor"]}]
}

       然后打开Buil.cs配置我们的环境在PublicDependencyModuleNames中进行添加和配置

		PublicDependencyModuleNames.AddRange(new string[]{"Core","LevelSequence","CoreUObject","UnrealEd","Engine","MovieScene","MovieSceneTracks","LevelSequenceEditor","DesktopPlatform","MovieSceneTracks","Sequencer"// ... add other public dependencies that you statically link with here ...});PrivateDependencyModuleNames.AddRange(new string[]{"Projects","InputCore","EditorFramework","UnrealEd","ToolMenus","CoreUObject","Engine","Slate","SlateCore"// ... add private dependencies that you statically link with here ...	});

       最后打开我们默认的主要CPP文件添加相关使用的头文件即可,我直接把所有代码放进来,这样大家在用的时候前面有不清楚的地方就可以回来看这个文件了。

// Copyright Epic Games, Inc. All Rights Reserved.#include "ViewSequence.h"#include "Editor.h"
#include "FileHelpers.h"
#include "Misc/MessageDialog.h"
#include "ToolMenus.h"
#include "ViewSequenceStyle.h"
#include "ViewSequenceCommands.h"#include "MovieScene.h"
#include "LevelSequence.h"
#include <LevelSequencePlayer.h>
#include "LevelSequenceActor.h"
#include "MovieScene/Public/Channels/MovieSceneChannelProxy.h"
#include "Sequencer/Public/ISequencerModule.h"
#include "LevelEditorViewport.h"#include <Tracks/MovieScene3DTransformTrack.h>
#include "Tracks/MovieSceneCameraCutTrack.h"
#include "Tracks/MovieSceneTransformTrack.h"#include "Sections/MovieSceneCameraCutSection.h"
#include "Sections/MovieScene3DTransformSection.h"#include "Camera/CameraActor.h"
#include "Camera/CameraComponent.h"#include "AssetData.h"
#include "AssetRegistryModule.h"
#include "AssetToolsModule.h"
#include "AssetRegistryModule.h"  
#include "AssetRegistry/Public/AssetRegistryModule.h"
#include "AssetRegistry/Public/IAssetRegistry.h"  #include "Modules/ModuleManager.h"
#include "Framework/Application/SlateApplication.h"  #include "Serialization/BulkData.h"  
#include "Editor/EditorEngine.h"  
#include "UnrealEd/Public/UnrealEd.h"static const FName ViewSequenceTabName("ViewSequence");// 定义全局FString数组  
TArray<FString> GlobalFStringArray;
FString FstringCon;#define LOCTEXT_NAMESPACE "FViewSequenceModule"void FViewSequenceModule::StartupModule()
{// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-moduleFViewSequenceStyle::Initialize();FViewSequenceStyle::ReloadTextures();FViewSequenceCommands::Register();PluginCommands = MakeShareable(new FUICommandList);PluginCommands->MapAction(FViewSequenceCommands::Get().PluginAction,FExecuteAction::CreateRaw(this, &FViewSequenceModule::PluginButtonClicked),FCanExecuteAction());UToolMenus::RegisterStartupCallback(FSimpleMulticastDelegate::FDelegate::CreateRaw(this, &FViewSequenceModule::RegisterMenus));
}void FViewSequenceModule::ShutdownModule()
{// This function may be called during shutdown to clean up your module.  For modules that support dynamic reloading,// we call this function before unloading the module.UToolMenus::UnRegisterStartupCallback(this);UToolMenus::UnregisterOwner(this);FViewSequenceStyle::Shutdown();FViewSequenceCommands::Unregister();
}ACameraActor* DoseCineCameraExist()
{UWorld* World = GWorld;bool bCineCameraExists = false;for (TActorIterator<ACameraActor> It(World); It; ++It){ACameraActor* ExistingCineCameraActor = *It;if (ExistingCineCameraActor && ExistingCineCameraActor->GetActorLabel() == "MainCamera"){bCineCameraExists = true;// 如果存在指定名称的 CineCameraActor,则直接返回该 Actorreturn ExistingCineCameraActor;break;}}if (!bCineCameraExists){FActorSpawnParameters SpawnParams;ACameraActor* NewCineCameraActor = GWorld->SpawnActor<ACameraActor>(ACameraActor::StaticClass(), FVector::ZeroVector, FRotator::ZeroRotator, SpawnParams);// 设置新创建的 CineCameraActor 的位置和旋转if (NewCineCameraActor){NewCineCameraActor->SetActorLabel("MainCamera");// 设置位置和旋转NewCineCameraActor->SetActorLocation(FVector(0, 0, 50));NewCineCameraActor->SetActorRotation(FRotator(0, 0, 0));}return NewCineCameraActor;}return nullptr;
}void CreateLevelSequenceAsset()
{//创建资产模版IAssetTools& AssetTools = FModuleManager::GetModuleChecked<FAssetToolsModule>("AssetTools").Get();UObject* NewAsset = nullptr;for (TObjectIterator<UClass> It;It; ++It){UClass* CurrentClass = *It;if (CurrentClass->IsChildOf(UFactory::StaticClass()) && !(CurrentClass->HasAnyClassFlags(CLASS_Abstract))){UFactory* Factory = Cast<UFactory>(CurrentClass->GetDefaultObject());if (Factory->CanCreateNew() && Factory->ImportPriority >= 0 && Factory->SupportedClass == ULevelSequence::StaticClass()){//打开UE窗口进行创建NewAsset = AssetTools.CreateAssetWithDialog(ULevelSequence::StaticClass(), Factory);break;}}}if (!NewAsset){return;}if (NewAsset && NewAsset->IsA<ULevelSequence>()){//将CameraCut添加到Seq中ULevelSequence* levelsequence = static_cast<ULevelSequence*>(NewAsset);UMovieSceneCameraCutTrack* CameraCutTrack = Cast<UMovieSceneCameraCutTrack>(levelsequence->MovieScene->GetCameraCutTrack());CameraCutTrack = Cast<UMovieSceneCameraCutTrack>(levelsequence->MovieScene->AddCameraCutTrack(UMovieSceneCameraCutTrack::StaticClass()));AActor* cameraActor = DoseCineCameraExist();FVector DefaultLocation = FVector::ZeroVector;FVector DefaultRotation = FVector::ZeroVector;FVector DefaultScale = FVector::OneVector;DefaultLocation = cameraActor->GetActorLocation();DefaultRotation = cameraActor->GetActorRotation().Euler();DefaultScale = cameraActor->GetActorScale();if (cameraActor){FGuid Guid = levelsequence->FindBindingFromObject(cameraActor, cameraActor->GetWorld());Guid = Cast<UMovieSceneSequence>(levelsequence)->CreatePossessable(cameraActor);int32 StartFrame = 0;int32 EndFrame = 50;int FrameTickValue = levelsequence->MovieScene->GetTickResolution().AsDecimal();UMovieSceneCameraCutSection* Section = CameraCutTrack->AddNewCameraCut(UE::MovieScene::FRelativeObjectBindingID(Guid), FFrameNumber(StartFrame * FrameTickValue));Section->SetEndFrame(FFrameNumber(EndFrame * FrameTickValue));Section->SetIsLocked(true);levelsequence->PostEditChange();UMovieScene3DTransformTrack* TransformTrack = levelsequence->GetMovieScene()->AddTrack<UMovieScene3DTransformTrack>(Guid);UMovieScene3DTransformSection* TransformSection = Cast<UMovieScene3DTransformSection>(TransformTrack->CreateNewSection());TransformTrack->AddSection(*TransformSection);TransformSection->SetRange(TRange<FFrameNumber>(FFrameNumber(0), FFrameNumber(150)));TArrayView<FMovieSceneDoubleChannel*> DoubleChannels = TransformSection->GetChannelProxy().GetChannels<FMovieSceneDoubleChannel>();DoubleChannels[0]->AddCubicKey(0, DefaultLocation.X);DoubleChannels[1]->AddCubicKey(0, DefaultLocation.Y);DoubleChannels[2]->AddCubicKey(0, DefaultLocation.Z);DoubleChannels[3]->AddCubicKey(0, DefaultRotation.X);DoubleChannels[4]->AddCubicKey(0, DefaultRotation.Y);DoubleChannels[5]->AddCubicKey(0, DefaultRotation.Z);DoubleChannels[6]->AddCubicKey(0, DefaultScale.X);DoubleChannels[7]->AddCubicKey(0, DefaultScale.Y);DoubleChannels[8]->AddCubicKey(0, DefaultScale.Z);levelsequence->PostEditChange();}}// Spawn an actor at the origin, and either move infront of the camera or focus camera on it (depending on the viewport) and open for editUActorFactory* ActorFactory = GEditor->FindActorFactoryForActorClass(ALevelSequenceActor::StaticClass());if (!ensure(ActorFactory)){return;}AActor* Actor = GEditor->UseActorFactory(ActorFactory, FAssetData(NewAsset), &FTransform::Identity);if (Actor == nullptr){return;}ALevelSequenceActor* NewActor = CastChecked<ALevelSequenceActor>(Actor);if (GCurrentLevelEditingViewportClient != nullptr && GCurrentLevelEditingViewportClient->IsPerspective()){GEditor->MoveActorInFrontOfCamera(*NewActor, GCurrentLevelEditingViewportClient->GetViewLocation(), GCurrentLevelEditingViewportClient->GetViewRotation().Vector());}else{GEditor->MoveViewportCamerasToActor(*NewActor, false);}GEditor->GetEditorSubsystem<UAssetEditorSubsystem>()->OpenEditorForAsset(NewAsset);//ULevelSequenceEditorBlueprintLibrary::SetLockCameraCutToViewport(true);}void FViewSequenceModule::PluginButtonClicked()
{CreateLevelSequenceAsset();
}void FViewSequenceModule::RegisterMenus()
{//UI对照信息可以在项目偏好设置中找到Miscellaneous中的Disply UI Extension Points开启勾选// Owner will be used for cleanup in call to UToolMenus::UnregisterOwnerFToolMenuOwnerScoped OwnerScoped(this);{UToolMenu* Menu = UToolMenus::Get()->ExtendMenu("LevelEditor.LevelEditorToolBar.Cinematics");//获取到对应的分类{FToolMenuSection& Section = Menu->FindOrAddSection("LevelEditorNewCinematics");//添加到指定地址Section.AddMenuEntryWithCommandList(FViewSequenceCommands::Get().PluginAction, PluginCommands);}}//{//	UToolMenu* ToolbarMenu = UToolMenus::Get()->ExtendMenu("LevelEditor.LevelEditorToolBar.PlayToolBar");//	{//		FToolMenuSection& Section = ToolbarMenu->FindOrAddSection("PluginTools");//		{//			FToolMenuEntry& Entry = Section.AddEntry(FToolMenuEntry::InitToolBarButton(FViewSequenceCommands::Get().PluginAction));//			Entry.SetCommandList(PluginCommands);//		}//	}//}}#undef LOCTEXT_NAMESPACEIMPLEMENT_MODULE(FViewSequenceModule, ViewSequence)

结尾

       这个功能到这里就结束了,希望对大家有帮助,关于LevelSequence这块功能使用可以到油管看下,有个大佬写了很多绑定和添加的过程,功能也很使用,应该会帮助你详细了解Level Sequecen C++的,源码的话在Movice下面的LevelSequenceEditor中涵盖了所有内容,有兴趣的话可以翻一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/296811.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

# 达梦数据库知识点

达梦数据库知识点 测试数据 -- SYSDBA.TABLE_CLASS_TEST definitionCREATE TABLE SYSDBA.TABLE_CLASS_TEST (ID VARCHAR(100) NOT NULL,NAME VARCHAR(100) NULL,CODE VARCHAR(100) NULL,TITLE VARCHAR(100) NULL,CREATETIME TIMESTAMP NULL,COLUMN1 VARCHAR(100) NULL,COLUMN…

云容器引擎CCE弹性伸缩

CCE弹性伸缩介绍 CCE的弹性伸缩能力分为如下两个维度&#xff1a; 工作负载弹性伸缩&#xff1a;即调度层弹性&#xff0c;主要是负责修改负载的调度容量变化。例如&#xff0c;HPA是典型的调度层弹性组件&#xff0c;通过HPA可以调整应用的副本数&#xff0c;调整的副本数会…

ShardingJdbc+Mybatis实现多数据源

Mybatis多数据源 这个是对shardingjdbc应用的一个升级&#xff0c;如果对于shardingjdbc的整合还没看过之前的文章的&#xff0c;可以先看看文章https://blog.csdn.net/Think_and_work/article/details/137174049?spm1001.2014.3001.5501 整合步骤 1、依赖 和全新项目的单…

翻译: 硅谷软件工程师面试:准备所需的一切

没有人有时间去做成百上千道LeetCode题目&#xff0c;好消息是你实际上并不需要做那么多题目就能够在FAANG公司找到工作&#xff01; 我曾经在Grab工作&#xff0c;这是东南亚的一家共享出行公司&#xff0c;但我对工作感到沮丧&#xff0c;想要进入FAANG公司&#xff0c;但我…

Linux------一篇博客了解Linux最常用的指令

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;Linux &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#…

LeetCode-199. 二叉树的右视图【树 深度优先搜索 广度优先搜索 二叉树】

LeetCode-199. 二叉树的右视图【树 深度优先搜索 广度优先搜索 二叉树】 题目描述&#xff1a;解题思路一&#xff1a;广度优先搜索解题思路二&#xff1a;深度优先搜索解题思路三&#xff1a;0 题目描述&#xff1a; 给定一个二叉树的 根节点 root&#xff0c;想象自己站在它…

基于顺序表的学生成绩管理系统

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;python从入门到精通&#xff0c;魔法指针&#xff0c;进阶C&#xff0c;C语言&#xff0c;C语言题集&#xff0c;C语言实现游戏&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文…

Android 自定义View 测量控件宽高、自定义viewgroup测量

1、View生命周期以及View层级 1.1、View生命周期 View的主要生命周期如下所示&#xff0c; 包括创建、测量&#xff08;onMeasure&#xff09;、布局&#xff08;onLayout&#xff09;、绘制&#xff08;onDraw&#xff09;以及销毁等流程。 自定义View主要涉及到onMeasure、…

设置asp.net core WebApi函数请求参数可空的两种方式

以下面定义的asp.net core WebApi函数为例&#xff0c;客户端发送申请时&#xff0c;默认三个参数均为必填项&#xff0c;不填会报错&#xff0c;如下图所示&#xff1a; [HttpGet] public string GetSpecifyValue(string param1,string param2,string param3) {return $"…

LeetCode-108. 将有序数组转换为二叉搜索树【树 二叉搜索树 数组 分治 二叉树】

LeetCode-108. 将有序数组转换为二叉搜索树【树 二叉搜索树 数组 分治 二叉树】 题目描述&#xff1a;解题思路一&#xff1a;中序遍历&#xff0c;总是选择中间位置左边的数字作为根节点解题思路二&#xff1a;0解题思路三&#xff1a;0 题目描述&#xff1a; 给你一个整数数…

【软件工程】概要设计

1. 导言 1.1 目的 该文档的目的是描述学生成绩管理系统的概要设计&#xff0c;其主要内容包括&#xff1a; 系统功能简介 系统结构简介 系统接口设计 数据设计 模块设计 界面设计 本文的预期读者是&#xff1a; 项目开发人员 项目管理人员 项目评测人员&#xff08;…

利用开源AI引擎:打造安全生产作业人员穿戴检测应用平台

在电力行业中&#xff0c;作业人员的安全是至关重要的。为了确保工作人员在进行电力设施操作时的个人安全&#xff0c;需要对作业人员的安全穿戴情况进行严格监控。随着计算视觉技术的发展&#xff0c;特别是图像处理和目标检测技术的进步&#xff0c;我们可以通过自动化的方式…

扫雷(蓝桥杯)

题目描述 小明最近迷上了一款名为《扫雷》的游戏。其中有一个关卡的任务如下&#xff0c; 在一个二维平面上放置着 n 个炸雷&#xff0c;第 i 个炸雷 (xi , yi ,ri) 表示在坐标 (xi , yi) 处存在一个炸雷&#xff0c;它的爆炸范围是以半径为 ri 的一个圆。 为了顺利通过这片土…

链路追踪原理

分布式系统为什么需要链路追踪&#xff1f; 随着互联网业务快速扩展&#xff0c;软件架构也日益变得复杂&#xff0c;为了适应海量用户高并发请求&#xff0c;系统中越来越多的组件开始走向分布式化&#xff0c;如单体架构拆分为微服务、服务内缓存变为分布式缓存、服务组件通…

网络原理 - HTTP / HTTPS(3)——http响应

目录 一、认识 “状态码”&#xff08;status code&#xff09; 常见的状态码 &#xff08;1&#xff09;200 OK &#xff08;2&#xff09;404 Not Found &#xff08;3&#xff09;403 ForBidden &#xff08;4&#xff09;405 Method Not Allowed &#xff08;5&…

Linux系统Docker搭建Wiki.Js应用程序并结合cpolar实现公网访问内网知识库

文章目录 1. 安装Docker2. 获取Wiki.js镜像3. 本地服务器打开Wiki.js并添加知识库内容4. 实现公网访问Wiki.js5. 固定Wiki.js公网地址 不管是在企业中还是在自己的个人知识整理上&#xff0c;我们都需要通过某种方式来有条理的组织相应的知识架构&#xff0c;那么一个好的知识整…

Matlab梁单元有限元编程:铁木辛柯梁VS欧拉梁

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

我与C++的爱恋:内联函数,auto

​ ​ &#x1f525;个人主页&#xff1a;guoguoqiang. &#x1f525;专栏&#xff1a;我与C的爱恋 ​ 一、内联函数 1.内联函数的概念 内联函数目的是减少函数调用的开销&#xff0c;通过将每个调用点将函数展开来实现。这种方法仅适用于那些函数体小、调用频繁的函数。 …

【JavaWeb】百度地图API SDK导入

百度地图开放平台 | 百度地图API SDK | 地图开发 (baidu.com) 登录注册&#xff0c;创建应用&#xff0c;获取AK 地理编码 | 百度地图API SDK (baidu.com) 需要的接口一&#xff1a;获取店铺/用户 所在地址的经纬度坐标 轻量级路线规划 | 百度地图API SDK (baidu.com) 需要的…

java-ssm-jsp-旅游景点数据库管理系统

java-ssm-jsp-旅游景点数据库管理系统 获取源码——》哔站搜&#xff1a;计算机专业毕设大全 获取源码——》哔站搜&#xff1a;计算机专业毕设大全