UE3植被工具-支持刷Actor)
【目标】
植被工具-刷Actor
【思路】
1 添加类型FFoliageMeshInfo.AddInstance 的函数
2 添加Instance就直接SpawnActor
3 类结构
4 修改的函数
FEdModeFoliage.AddInstancesForBrush.
FEdModeFoliage.AddFoliageMesh
【步骤】
1 添加AcheType支持,添加FEdModeFoliage.AddFoliageAcheType
2 添加一个AActor的表,用于记录ArcheType
var const native Map_MirrorFoliageArcheTypes{TMap<classAActor*,structFFoliageMeshInfo>};
3 MFoliageEditWindow.OnDrop,资源拖到面板上
else
{
AActor*ArcheTypeActor=LoadObject<AActor>(NULL,*CurInfo.ObjectPathName, NULL, LOAD_None, NULL);
if(ArcheTypeActor&&ArchetypeActor->HasAnyFlags(RF_ArchetypeObject))
{
FoliageEditSystem->AddFoliageAcheType(ArcheTypeActor);
FoliageMeshesProperty->NotifyChanged();
}
}
for(TArray<FSelectedAssetInfo>::TConstIteratorDroppedAssetsIter(*(DroppedAssets.Get()));DroppedAssetsIter;++DroppedAssetsIter)
{
constFSelectedAssetInfo&CurInfo=*DroppedAssetsIter;
if(CurInfo.ObjectClass!=UStaticMesh::StaticClass()&&CurInfo.ObjectClass!=AActor::StaticClass())
{
Args->Effects=DragDropEffects::None;
break;
}
4 MFoliageEditWindow.OnDragOver 改成 IsChildOf 判断
voidOnDragOver(Object^Owner,DragEventArgs^Args)
{
Args->Effects=DragDropEffects::Copy;
if(DroppedAssets.Get()!= NULL )
{
for(TArray<FSelectedAssetInfo>::TConstIteratorDroppedAssetsIter(*(DroppedAssets.Get()));DroppedAssetsIter;++DroppedAssetsIter)
{
constFSelectedAssetInfo&CurInfo=*DroppedAssetsIter;
if(CurInfo.ObjectClass!=UStaticMesh::StaticClass()&&!CurInfo.ObjectClass->IsChildOf(AActor::StaticClass()))
{
Args->Effects=DragDropEffects::None;
break;
}
}
}
Args->Handled= TRUE;
}
5 目前拖上去没有效果显示,
MFoliageMeshWrapper
列表和FEdModeFoliage.GetFoliageMeshList 绑定了,所以显示了FFoliageMeshUIInfo列表
6 添加FFoliageArcheTypeUIInfo 继承于FFoliageMeshUIInfo
structFFoliageResourceUIInfo:publicFFoliageMeshUIInfo
{
AActor*ArcheTypeActor;
FFoliageResourceUIInfo(UStaticMesh*InStaticMesh,AActor*InArcheTypeActor,FFoliageMeshInfo*InMeshInfo)
:FFoliageMeshUIInfo(InStaticMesh,InMeshInfo)
:ArcheTypeActor(InArcheTypeActor)
{}
};
7 FEdModeFoliage.GetFoliageMeshList 返回值
TArray<structFFoliageResourceUIInfo>&GetFoliageMeshList();
8 FEdModeFoliage.FoliageMeshList
// Placed level data
TArray<structFFoliageResourceUIInfo>FoliageMeshList;
9
IMPLEMENT_COMPARE_CONSTREF(FFoliageResourceUIInfo,FoliageEdMode,{return A.MeshInfo->Settings->DisplayOrder- B.MeshInfo->Settings->DisplayOrder;});
10 FEdModeFoliage.UpdateFoliageMeshList
voidFEdModeFoliage::UpdateFoliageMeshList()
{
FoliageMeshList.Empty();
AInstancedFoliageActor* IFA =AInstancedFoliageActor::GetInstancedFoliageActor();
for(TMap<classUStaticMesh*,structFFoliageMeshInfo>::TIteratorMeshIt(IFA->FoliageMeshes);MeshIt;++MeshIt)
{
new(FoliageMeshList)FFoliageResourceUIInfo(MeshIt.Key(),NULL,&MeshIt.Value());
}
for(TMap<classAActor*,structFFoliageMeshInfo>::TIteratorArcheTypeIt(IFA->FoliageArcheTypes);ArcheTypeIt;++ArcheTypeIt)
{
new(FoliageArcheTypeList)FFoliageResourceUIInfo(NULL,ArcheTypeIt.Key(),&ArcheTypeIt.Value());
}
Sort<USE_COMPARE_CONSTREF(FFoliageResourceUIInfo,FoliageEdMode)>(&FoliageMeshList(),FoliageMeshList.Num());
}
11 MFoliageMeshWrapper 类构造需要用新类FFoliageResourceUIInfo
ref classMFoliageMeshWrapper:publicINotifyPropertyChanged
{
int index;
FFoliageResourceUIInfo& mesh;
UInstancedFoliageSettings* settings;
BitmapSource^ bitmap;
public:
virtual event PropertyChangedEventHandler^PropertyChanged;
MFoliageMeshWrapper( INT InIndex,FFoliageResourceUIInfo&InMesh)
: index(InIndex)
, mesh(InMesh)
, settings(mesh.MeshInfo->Settings)
{
if(mesh.StaticMesh)
bitmap =ThumbnailToolsCLR::GetBitmapSourceForObject(mesh.StaticMesh);
elseif(mesh.ArcheTypeActor)
bitmap =ThumbnailToolsCLR::GetBitmapSourceForObject(mesh.ArcheTypeActor);
}
12
typedefMEnumerableTArrayWrapper<MFoliageMeshWrapper,FFoliageResourceUIInfo>MFoliageMeshes;
13 跟FFoliageMeshUIInfo.StaticMesh 相关的修改
MFoliageMeshWrapper.StaticMeshName.get 获取名字的
propertyString^StaticMeshName{
String^ get()
{
FStringName= mesh.StaticMesh? mesh.StaticMesh->GetName()? mesh.ArcheTypeActor->GetName();
returnCLRTools::ToString(Name);
}
}
// Remove the current mesh
voidFoliageMeshRemoveButton_Click(Object^Owner,ExecutedRoutedEventArgs^Args)
{
MFoliageMeshWrapper^Mesh= safe_cast<MFoliageMeshWrapper^>(Args->Parameter);
if(Mesh->GetStaticMesh())
FoliageEditSystem->RemoveFoliageMesh(Mesh->GetStaticMesh());
else
FoliageEditSystem->RemoveFoliageAcheType(Mesh->GetArcheTypeActor());
FoliageMeshesProperty->NotifyChanged();
}
添加MFoliageMeshWrapper.GetStaticMesh
AActor*GetStaticMesh(){return mesh.ArcheTypeActor;}
MFoliageEditWindow.FoliageMeshCopySettings_Click
voidFoliageMeshUseSettings_Click(Object^Owner,ExecutedRoutedEventArgs^Args)
{
GCallbackEvent->Send(CALLBACK_LoadSelectedAssetsIfNeeded);
USelection*SelectedSet=GEditor->GetSelectedSet(UInstancedFoliageSettings::StaticClass());
UInstancedFoliageSettings*SelectedSettings=Cast<UInstancedFoliageSettings>(SelectedSet->GetTop(UInstancedFoliageSettings::StaticClass()));
if(SelectedSettings!= NULL )
{
MFoliageMeshWrapper^Mesh= safe_cast<MFoliageMeshWrapper^>(Args->Parameter);
if(Mesh->GetStaticMesh())
FoliageEditSystem->ReplaceSettingsObject(Mesh->GetStaticMesh(),SelectedSettings);
else
FoliageEditSystem->ReplaceSettingsObject(Mesh->GetArcheTypeActor(),SelectedSettings);
if(SelectedActor&&SelectedActor->HasAnyFlags(RF_ArchetypeObject))
{
MFoliageMeshWrapper^Mesh= safe_cast<MFoliageMeshWrapper^>(Args->Parameter);
FoliageEditSystem->ReplaceArchtypeActor(Mesh->GetArcheTypeActor(),SelectedActor);
FoliageMeshesProperty->NotifyChanged();
}
13 FEdModeFoliage.ReplaceArchtypeActor
voidFEdModeFoliage::ReplaceArchtypeActor(AActor*OldArcheType,AActor*NewArcheType)
{
AInstancedFoliageActor* IFA =AInstancedFoliageActor::GetInstancedFoliageActor();
FFoliageMeshInfo*OldMeshInfo= IFA->FoliageArcheTypes.Find(OldArcheType);
if(OldMeshInfo!= NULL &&OldArcheType!=NewArcheType&&NewArcheType->HasAnyFlags(RF_ArchetypeObject))
{
INT InstancesNum=OldMeshInfo->Instances.Num()-OldMeshInfo->FreeInstanceIndices.Num();
// Look for the new mesh in the mesh list, and either create a new mesh or merge the instances.
FFoliageMeshInfo*NewMeshInfo= IFA->FoliageArcheTypes.Find(NewArcheType);
if(NewMeshInfo== NULL )
{
if(InstancesNum>&&
appMsgf(AMT_YesNo,LocalizeSecure(LocalizeUnrealEd("FoliageMode_ReplaceMesh"),InstancesNum,*OldArcheType->GetName(),*NewArcheType->GetName()))!= ART_Yes )
{
return;
}
GEditor->BeginTransaction(*LocalizeUnrealEd("FoliageMode_ChangeStaticMeshTransaction"));
IFA->Modify();
NewMeshInfo= IFA->AddArcheType(NewArcheType);
NewMeshInfo->Settings->DisplayOrder=OldMeshInfo->Settings->DisplayOrder;
NewMeshInfo->Settings->ShowNothing=OldMeshInfo->Settings->ShowNothing;
NewMeshInfo->Settings->ShowPaintSettings=OldMeshInfo->Settings->ShowPaintSettings;
NewMeshInfo->Settings->ShowInstanceSettings=OldMeshInfo->Settings->ShowInstanceSettings;
}
else
if(InstancesNum>&&
appMsgf(AMT_YesNo,LocalizeSecure(LocalizeUnrealEd("FoliageMode_ReplaceMeshMerge"),InstancesNum,*OldArcheType->GetName(),*NewArcheType->GetName()))!= ART_Yes )
{
return;
}
else
{
GEditor->BeginTransaction(*LocalizeUnrealEd("FoliageMode_ChangeStaticMeshTransaction"));
IFA->Modify();
}
if(InstancesNum>)
{
// copy instances from old to new.
for( INT Idx=;Idx<OldMeshInfo->Instances.Num();Idx++)
{
if(OldMeshInfo->Instances(Idx).ClusterIndex!=-)
{
NewMeshInfo->AddInstanceAT( IFA,NewArcheType,OldMeshInfo->Instances(Idx));
}
}
}
// Remove the old mesh.
IFA->RemoveArcheType(OldArcheType);
GEditor->EndTransaction();
// Update mesh list.
UpdateFoliageMeshList();
}
}
14 添加FFoliageMeshInfo.AddInstanceAT
voidFFoliageMeshInfo::AddInstanceAT(classAInstancedFoliageActor*InIFA,classAActor*InActor,constFFoliageInstance&InNewInstance)
{
}
目前是刷不上Actor模型吗,主要是FEdModeFoliage.ApplyBrush 函数里没有处理
15 修改FEdModeFoliage.ApplyBrush
// ArcheType
for(TMap<classAActor*,structFFoliageMeshInfo>::TIteratorArcheTypeIt(IFA->FoliageArcheTypes);ArcheTypeIt;++ArcheTypeIt)
{
FFoliageMeshInfo&MeshInfo=ArcheTypeIt.Value();
UInstancedFoliageSettings*MeshSettings=MeshInfo.Settings;
if(MeshSettings->IsSelected)
{
// Find the instances already in the area.
TArray<INT>Instances;
FSphereBrushSphere(BrushLocation,UISettings.GetRadius());
MeshInfo.GetInstancesInsideSphere(BrushSphere,Instances);
if(UISettings.GetLassoSelectToolSelected())
{
// Shift unpaints
MeshInfo.SelectInstances( IFA,!IsShiftDown(ViewportClient->Viewport),Instances);
}
else
if(UISettings.GetReapplyToolSelected())
{
if(MeshSettings->ReapplyDensity)
{
// Adjust instance density
FMeshInfoSnapshot*SnapShot=InstanceATSnapshot.Find(ArcheTypeIt.Key());
if(SnapShot)
{
// Use snapshot to determine number of instances at the start of the brush stroke
INT NewInstanceCount= appRound((FLOAT)SnapShot->CountInstancesInsideSphere(BrushSphere)*MeshSettings->ReapplyDensityAmount);
if(MeshSettings->ReapplyDensityAmount>.f&&NewInstanceCount>Instances.Num())
{
AddInstancesATForBrush( IFA,ArcheTypeIt.Key(),MeshInfo,NewInstanceCount,Instances,Pressure);
}
else
if(MeshSettings->ReapplyDensityAmount<.f&&NewInstanceCount<Instances.Num())
{
RemoveInstancesForBrush( IFA,MeshInfo,NewInstanceCount,Instances,Pressure);
}
}
}
// Reapply any settings checked by the user
ReapplyInstancesForBrush( IFA,MeshInfo,Instances);
}
else
if(UISettings.GetPaintToolSelected())
{
// Shift unpaints
if(IsShiftDown(ViewportClient->Viewport))
{
INT DesiredInstanceCount= appRound(BrushArea*MeshSettings->Density*UISettings.GetUnpaintDensity()/(.f*.f));
if(DesiredInstanceCount<Instances.Num())
{
RemoveInstancesForBrush( IFA,MeshInfo,DesiredInstanceCount,Instances,Pressure);
}
}
else
{
// This is the total set of instances disregarding parameters like slope, height or layer.
FLOAT DesiredInstanceCountFloat=BrushArea*MeshSettings->Density*UISettings.GetPaintDensity()/(.f*.f);
// Allow a single instance with a random chance, if the brush is smaller than the density
INT DesiredInstanceCount=DesiredInstanceCountFloat>.f? appRound(DesiredInstanceCountFloat): appFrand()<DesiredInstanceCountFloat?:;
AddInstancesATForBrush( IFA,ArcheTypeIt.Key(),MeshInfo,DesiredInstanceCount,Instances,Pressure);
}
}
}
}
16 添加Instance的函数FEdModeFoliage.AddInstancesATForBrush
/** Add instances inside the brush to match DesiredInstanceCount */
voidFEdModeFoliage::AddInstancesATForBrush(AInstancedFoliageActor* IFA,AActor*AchetypeActor,FFoliageMeshInfo&MeshInfo, INT DesiredInstanceCount,TArray<INT>&ExistingInstances, FLOAT Pressure)
{
UInstancedFoliageSettings*MeshSettings=MeshInfo.Settings;
if(DesiredInstanceCount>ExistingInstances.Num())
{
INT ExistingInstanceBuckets[NUM_INSTANCE_BUCKETS];
appMemzero(ExistingInstanceBuckets,sizeof(ExistingInstanceBuckets));
// Cache store mapping between component and weight data
TMap<ULandscapeComponent*,TArray<BYTE>>*LandscapeLayerCache= NULL;
FNameLandscapeLayerName=MeshSettings->LandscapeLayer;
if(LandscapeLayerName!= NAME_None )
{
LandscapeLayerCache=&LandscapeLayerCaches.FindOrAdd(LandscapeLayerName);
// Find the landscape weights of existing ExistingInstances
for( INT Idx=;Idx<ExistingInstances.Num();Idx++)
{
FFoliageInstance&Instance=MeshInfo.Instances(ExistingInstances(Idx));
ULandscapeHeightfieldCollisionComponent*HitLandscapeCollision=Cast<ULandscapeHeightfieldCollisionComponent>(Instance.Base);
if(HitLandscapeCollision)
{
ULandscapeComponent*HitLandscape=HitLandscapeCollision->GetLandscapeComponent();
if(HitLandscape)
{
TArray<BYTE>*LayerCache=&LandscapeLayerCache->FindOrAdd(HitLandscape);
FLOAT HitWeight=HitLandscape->GetLayerWeightAtLocation(Instance.Location,LandscapeLayerName,LayerCache);
// Add count to bucket.
ExistingInstanceBuckets[appRound(HitWeight*(FLOAT)(NUM_INSTANCE_BUCKETS-))]++;
}
}
}
}
else
{
// When not tied to a layer, put all the ExistingInstances in the last bucket.
ExistingInstanceBuckets[NUM_INSTANCE_BUCKETS-]=ExistingInstances.Num();
}
// We calculate a set of potential ExistingInstances for the brush area.
TArray<FPotentialInstance>PotentialInstanceBuckets[NUM_INSTANCE_BUCKETS];
appMemzero(PotentialInstanceBuckets,sizeof(PotentialInstanceBuckets));
// Quick lookup of potential instance locations, used for overlapping check.
TArray<FVector>PotentialInstanceLocations;
FFoliageInstanceHashPotentialInstanceHash();// use 128x128 cell size, as the brush radius is typically small.
PotentialInstanceLocations.Empty(DesiredInstanceCount);
// Radius where we expect to have a single instance, given the density rules
const FLOAT DensityCheckRadius=Max<FLOAT>( appSqrt((.f*.f)/(PI *MeshSettings->Density)),MeshSettings->Radius);
for( INT DesiredIdx=;DesiredIdx<DesiredInstanceCount;DesiredIdx++)
{
FVectorStart,End;
GetRandomVectorInBrush(Start,End);
FCheckResultHit;
if(!GWorld->SingleLineCheck(Hit, NULL,End,Start, TRACE_World | TRACE_Level,FVector(.f,.f,.f), NULL))
{
// Check filters
if((Hit.Component&&
(Hit.Component->GetOutermost()!=GWorld->CurrentLevel->GetOutermost()||
(!UISettings.bFilterLandscape &&Hit.Component->IsA(ULandscapeHeightfieldCollisionComponent::StaticClass()))||
(!UISettings.bFilterStaticMesh &&Hit.Component->IsA(UStaticMeshComponent::StaticClass()))||
(!UISettings.bFilterTerrain &&Hit.Component->IsA(UTerrainComponent::StaticClass()))))||
(Hit.Actor&&Hit.Actor->IsA(AWorldInfo::StaticClass())&&(!UISettings.bFilterBSP ||GWorld->Levels(Hit.LevelIndex)!=GWorld->CurrentLevel)))
{
continue;
}
if(!CheckLocationForPotentialInstance(MeshInfo,MeshSettings,DensityCheckRadius,Hit.Location,Hit.Normal,PotentialInstanceLocations,PotentialInstanceHash))
{
continue;
}
// Check landscape layer
FLOAT HitWeight=.f;
if(LandscapeLayerName!= NAME_None )
{
ULandscapeHeightfieldCollisionComponent*HitLandscapeCollision=Cast<ULandscapeHeightfieldCollisionComponent>(Hit.Component);
if(HitLandscapeCollision)
{
ULandscapeComponent*HitLandscape=HitLandscapeCollision->GetLandscapeComponent();
if(HitLandscape)
{
TArray<BYTE>*LayerCache=&LandscapeLayerCache->FindOrAdd(HitLandscape);
HitWeight=HitLandscape->GetLayerWeightAtLocation(Hit.Location,LandscapeLayerName,LayerCache);
// Reject instance randomly in proportion to weight
if(HitWeight<= appFrand())
{
continue;
}
}
}
}
new(PotentialInstanceBuckets[appRound(HitWeight*(FLOAT)(NUM_INSTANCE_BUCKETS-))])FPotentialInstance(Hit.Location,Hit.Normal,Hit.Component,HitWeight);
}
}
for( INT BucketIdx=;BucketIdx< NUM_INSTANCE_BUCKETS;BucketIdx++)
{
TArray<FPotentialInstance>&PotentialInstances=PotentialInstanceBuckets[BucketIdx];
FLOAT BucketFraction=(FLOAT)(BucketIdx+)/(FLOAT)NUM_INSTANCE_BUCKETS;
// We use the number that actually succeeded in placement (due to parameters) as the target
// for the number that should be in the brush region.
INT AdditionalInstances=Clamp<INT>( appRound(BucketFraction*(FLOAT)(PotentialInstances.Num()-ExistingInstanceBuckets[BucketIdx])*Pressure),,PotentialInstances.Num());
for( INT Idx=;Idx<AdditionalInstances;Idx++)
{
FFoliageInstanceInst=PotentialInstances(Idx).PlaceInstance(MeshSettings);
MeshInfo.AddInstanceAT( IFA,AchetypeActor,Inst);
}
}
}
}
structFFoliageInstanceCluster
{
UInstancedStaticMeshComponent*ClusterComponent;
TArray<AActor*>ActorInstances;
FFoliageInstanceCluster.GetInstanceCount
INT GetInstanceCount()
{
INT TotalCount=;
if(ClusterComponent)
TotalCount+=ClusterComponent->PerInstanceSMData.Num();
TotalCount+=ActorInstances.Num();
}
18 添加FFoliageMeshInfo.AddInstanceAT
voidFFoliageMeshInfo::AddInstanceAT(classAInstancedFoliageActor*InIFA,classAActor*InArchetypeActor,constFFoliageInstance&InNewInstance)
{
InIFA->Modify();
// Add the instance taking either a free slot or adding a new item.
INT InstanceIndex=FreeInstanceIndices.Num()>?FreeInstanceIndices.Pop():Instances.Add();
FFoliageInstance&AddedInstance=Instances(InstanceIndex);
AddedInstance=InNewInstance;
// Add the instance to the hash
InstanceHash->InsertInstance(InNewInstance.Location,InstanceIndex);
FFoliageComponentHashInfo&ComponentHashInfo=ComponentHash.FindOrAddKey(InNewInstance.Base);
ComponentHashInfo.Instances.Add(InstanceIndex);
// Find the best cluster to allocate the instance to.
FFoliageInstanceCluster*BestCluster= NULL;
INT BestClusterIndex= INDEX_NONE;
FLOAT BestClusterDistSq= FLT_MAX;
INT MaxInstancesPerCluster=Settings->MaxInstancesPerCluster;
FLOAT MaxClusterRadiusSq=Square(Settings->MaxClusterRadius);
for( INT ClusterIdx=;ClusterIdx<InstanceClusters.Num();ClusterIdx++)
{
FFoliageInstanceCluster&Cluster=InstanceClusters(ClusterIdx);
if(Cluster.InstanceIndices.Num()<MaxInstancesPerCluster)
{
FLOAT DistSq=(Cluster.Bounds.Origin-InNewInstance.Location).SizeSquared();
if(DistSq<BestClusterDistSq&&DistSq<MaxClusterRadiusSq)
{
BestCluster=&Cluster;
BestClusterIndex=ClusterIdx;
BestClusterDistSq=DistSq;
}
}
}
// Calculate transform for the instance
FMatrixInstanceTransform=InNewInstance.GetInstanceTransform();
if(BestCluster== NULL )
{
BestClusterIndex=InstanceClusters.Num();
BestCluster=new(InstanceClusters)FFoliageInstanceCluster(
NULL,
FBoxSphereBounds()// LWF_TODO
);
//ApplyInstancedFoliageSettings( BestCluster->ClusterComponent );
}
else
{
// BestCluster->ClusterComponent->Modify();
// BestCluster->ClusterComponent->InvalidateLightingCache();
// BestCluster->Bounds = BestCluster->Bounds + InMesh->Bounds.TransformBy(InstanceTransform);
}
BestCluster->InstanceIndices.AddItem(InstanceIndex);
// Save the cluster index
AddedInstance.ClusterIndex=BestClusterIndex;
// Add the instance to the ActorList
AActor* pActor =GWorld->SpawnActor(InArchetypeActor->GetClass(), NAME_None,InNewInstance.Location,InNewInstance.Rotation,InArchetypeActor);// Spawn Actor
BestCluster->ActorInstances.AddItem(pActor);
// FInstancedStaticMeshInstanceData* NewInstanceData = new(BestCluster->ClusterComponent->PerInstanceSMData) FInstancedStaticMeshInstanceData();
if(BestCluster->ClusterComponent->SelectedInstances.Num()>)
{
BestCluster->ClusterComponent->SelectedInstances.AddItem(FALSE);
}
// NewInstanceData->Transform = InstanceTransform;
// NewInstanceData->LightmapUVBias = FVector2D( -1.0f, -1.0f );
// NewInstanceData->ShadowmapUVBias = FVector2D( -1.0f, -1.0f );
// BestCluster->ClusterComponent->bNeedsReattach = TRUE;
#if _DEBUG
CheckValid();
#endif
InIFA->ConditionalUpdateComponents();
}
18 修改所有FFoliageInstanceCluster.ClusterComponent 的地方
太多地方了
FFoliageMeshInfo.CheckValid
终于能刷出东西来了
UE3植被工具-支持刷Actor)的更多相关文章
- WordPress让文本小工具支持简码
WordPress 的 “文本” 小工具是非常常用的,可以添加一些自定义的文本或者 Html 代码.但很多时候,我们需要在文本小工具里使用简码来添加一些更加丰富的内容. 默认情况下,文本小工具是不支持 ...
- LiveBlox无需代码的开发工具--支持win macos ubuntu等开发环境--
LiveBlox无需代码的开发工具-支持windows macos ubuntu. 强大 灵活 易于使用 视频简介:LiveBlox Develop Technology Without Coding ...
- 文档资源搜索小工具 - 支持PDF,DOC,PPT,XLS
最近做了一个文档搜索小工具,当然不是网盘搜索工具,这个工具支持四种文件格式搜索(pdf,doc,ppt,xls),你只需要在搜索框中输入你想要搜索资源的关键词,点击搜索按钮即可获取相关资源,点击下载按 ...
- 3-WIN10系统及开发工具支持
本篇博客对应视频讲解 回顾 上一讲说了编程的方向和技术流派以及选择入门语言的建议.当我们决定我们的选择之后呢,我们就要学习和进行实践操作了.但在实践之前,我们仍然需要做好相应的准备,这也就是今天要讲的 ...
- WinSetupFromUSB - 超简单制作多合一系统安装启动U盘的工具 (支持Win/PE/Linux启动盘)
很多同学都喜欢将电脑凌乱不堪的系统彻底重装以获得一个"全新的开始",但你会发现如今很多电脑都已经没有光驱了,因此制作一个U盘版的系统安装启动盘备用是非常必要的. 我们之前推荐过 I ...
- 【C#附源码】数据库文档生成工具支持(Excel+Html)
[2015] 很多时候,我们在生成数据库文档时,使用某些工具,可效果总不理想,不是内容不详细,就是表现效果一般般.很多还是word.html的.看着真是别扭.本人习惯用Excel,所以闲暇时,就简单的 ...
- 【C#附源码】数据库文档生成工具支持(Excel+Htm)
数据库文档生成工具是用C#开发的基于NPOI组件的小工具.软件源码大小不到10MB.支持生成Excel 和Html 两种文档形式.了解更多,请访问:http://www.oschina.net/cod ...
- 全新WayOS 配置文件保存工具支持蓝色界面路由版本
一直以来都有群里的朋友要求我弄一个支持蓝色界面路由的参数备份工具,也一直拖了大半年 昨天忙到4点多,早上又因为一些小的BUG被用户电话叫起,干脆就帮你们整一个这个工具了 功能还是一样,支持各种参数的保 ...
- 通过自研数据库画像工具支持“去O”评估
“去O”,是近些年来一直很火的一个话题,随之也产生了各种疑惑,包括现有数据库评估.技术选型等.去O是项系统工程,需要做好充分的评估.本文通过自研工具,生成数据库画像,为去O评估提供一手数据,希望给大家 ...
随机推荐
- java经典算法40题(21-40)
[程序21] 题目:求1+2!+3!+...+20!的和 1.程序分析:此程序只是把累加变成了累乘. public class Ex21 { static long sum = 0; s ...
- C# 窗体
窗体的事件:删除事件:先将事件页面里面的挂好的事件删除,再删后台代码里面的事件 Panel是一个容器 1.Label -- 文本显示工具Text:显示的文字取值.赋值:lable1.Text 2.Te ...
- System.arraycopy
ref : http://blog.csdn.net/jaycee110905/article/details/45228249
- 安卓与PC网络对接实现视频实时播放
研究安卓网络通信一段时间了, 由于最近公司催的比较紧, 硬着头皮弄出来了. 现在手机客户端终于能够连接流媒体服务器实时播放前端的视频流了. 其实通信方面主要还是命令包的解析, 以及分包组包. 比如要 ...
- [4] 智能指针boost::scoped_ptr
[1]boost::scoped_ptr简介 boost::scoped_ptr属于boost库,定义在namespace boost中,包含头文件#include <boost/scoped_ ...
- Dynamics AX 2012 R2 将系统用户账号连接到工作人员记录
要使用AX中的一些特性,需要将User Account和他们的Employee Record连接在一起.最好将所有Employee的User Account,都和他们的Employee Record连 ...
- HTML中一些基本的标签用法
姓名输入框:<input type="text" value="默认有值"/> 密码输入框:<input type="text&qu ...
- c++11中的for简化用法
1.序列for循环 map<string,int> m{{"a",1},{"b",2},{"c",3}} for(auto p: ...
- 流镜像(华为S9306和S5700)
流镜像是指将设备.端口或者VLAN内收.发的指定类型报文复制到观察端口上,监控设备只对指定类型报文进行监测. 流镜像有基于ACL和基于MQC(即复杂流分类)两种配置方式.前者配置简便,但是没有后者支持 ...
- Kth Largest Element in an Array - LeetCode
examination questions Find the kth largest element in an unsorted array. Note that it is the kth lar ...