Skip to content
Snippets Groups Projects
Commit 2e632c00 authored by aenneking's avatar aenneking
Browse files

initial commit

parents
No related branches found
No related tags found
No related merge requests found
Showing
with 1273 additions and 0 deletions
File added
File added
File added
File added
{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "LikertPlugin",
"Description": "This Plugin allows for easy creation of Likert Scales",
"Category": "Other",
"CreatedBy": "Me",
"CreatedByURL": "",
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "",
"EngineVersion": "4.21.0",
"CanContainContent": true,
"Installed": true,
"Modules": [
{
"Name": "LikertPlugin",
"Type": "Runtime",
"LoadingPhase": "Default",
"WhitelistPlatforms": [
"Win32",
"Win64",
"Linux"
]
}
]
}
\ No newline at end of file
LikertPlugin/LikertPlugin/Resources/Icon128.png

12.4 KiB

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
public class LikertPlugin : ModuleRules
{
public LikertPlugin(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicIncludePaths.AddRange(
new string[] {
// ... add public include paths required here ...
}
);
PrivateIncludePaths.AddRange(
new string[] {
// ... add other private include paths required here ...
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
// ... add other public dependencies that you statically link with here ...
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"Json",
"UMG"
// ... add private dependencies that you statically link with here ...
}
);
if (Target.bBuildEditor)
{
PrivateDependencyModuleNames.Add("UnrealEd");
}
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
}
}
// Fill out your copyright notice in the Description page of Project Settings.
#include "LayoutComponent.h"
#include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h"
#include "MultilineTextLayouter.h"
ULayoutComponent::ULayoutComponent()
{
PrimaryComponentTick.bCanEverTick = false;
}
void ULayoutComponent::Update()
{
GetChildrenComponents(false, children_);
prioritize();
float size_weight_sum = 0.0f;
for(auto i = 0; i < children_.Num(); ++i)
{
if (dynamic_cast<ULayoutComponent*>(children_[i]))
size_weight_sum += dynamic_cast<ULayoutComponent*>(children_[i])->size_weight_;
else
size_weight_sum += 1.0f;
}
auto size_factor_ = size_weight_sum / children_.Num();
float child_size_sum = 0.0f;
for (auto i = 0; i < children_.Num(); ++i)
{
FTransform transform;
auto child_menu_cnt = children_.Num();
float size_weight = 1.0f;
if(dynamic_cast<ULayoutComponent*>(children_[i]))
size_weight = dynamic_cast<ULayoutComponent*>(children_[i])->size_weight_;
auto child_scale = FVector2D(1.0f, size_weight *(1.0f - submenu_offset_factor_ * (child_menu_cnt - 1)) / (child_menu_cnt * size_factor_));
auto first_child_loc = (0.5f - 0.5f * (child_scale.Y));
auto child_loc = first_child_loc - child_size_sum;
child_size_sum += child_scale.Y + submenu_offset_factor_;
if (alignment_ == VERTICAL)
{
transform.SetLocation(FVector(0.1f, 0.0f, res_.Y * child_loc));
transform.SetScale3D(FVector(1.0f, child_scale.X, child_scale.Y));
}
else if (alignment_ == HORIZONTAL)
{
transform.SetLocation(FVector(0.1f, res_.X * child_loc, 0.0f));
transform.SetScale3D(FVector(1.0f, child_scale.Y, child_scale.X));
}
auto child = children_[i];
if(dynamic_cast<UTextWidgetComponent *>(child) != nullptr)
dynamic_cast<UTextWidgetComponent *>(child)->SetSize(transform, GetComponentScale());
else
child->SetRelativeTransform(transform);
if (dynamic_cast<ULayoutComponent*>(children_[i]))
dynamic_cast<ULayoutComponent*>(children_[i])->Update();
}
}
void ULayoutComponent::prioritize()
{
for (auto i = 0; i < children_.Num() - 1; ++i)
{
auto layout = dynamic_cast<ULayoutComponent*>(children_[i]);
if (layout != nullptr)
{
if (layout->GetPriority() == 2)
for (auto j = i; j > 0; --j)
children_.Swap(j, j - 1);
if (layout->GetPriority() == 0)
for (auto j = i; j < children_.Num() - 1; ++j)
children_.Swap(j, j + 1);
}
}
}
void ULayoutComponent::Init(FVector2D res, Alignment alignment, FVector rel_loc)
{
res_ = res;
alignment_ = alignment;
SetRelativeLocation(rel_loc);
}
UTextWidgetComponent * ULayoutComponent::CreateWidgetChild(FName name, WidgetObjectManager::AssetInfo & asset, int priority)
{
auto widget = NewObject<UTextWidgetComponent>(GetOwner(), UTextWidgetComponent::StaticClass());
widget->RegisterComponent();
auto attachment_rules = FAttachmentTransformRules(EAttachmentRule::KeepRelative, false);
widget->AttachToComponent(this, attachment_rules);
widget->SetWidgetSpace(EWidgetSpace::World);
widget->SetWidgetClass(asset.uclass);
widget->SetDrawSize(FVector2D(asset.res_x, asset.res_y));
widget->SetRelativeLocation(FVector(0.0f));
widget->SetRelativeScale3D(FVector(1.0f));
widget->SetPriority(priority);
widget->SetChangeRelSize(asset.change_rel_size);
widget->Init();
return widget;
}
ULayoutComponent * ULayoutComponent::CreateLayoutChild(Alignment alignment, UClass * uclass)
{
auto layout = NewObject<ULayoutComponent>(GetOwner(), uclass);
layout->RegisterComponent();
auto attachment_rules = FAttachmentTransformRules(EAttachmentRule::KeepRelative, false);
layout->AttachToComponent(this, attachment_rules);
layout->Init(FVector2D(1280.0, 720.0), alignment, FVector(1.0f, 0.0f, 0.0f));
return layout;
}
void ULayoutComponent::SetPriority(uint8 priority)
{
priority_ = priority;
}
uint8 ULayoutComponent::GetPriority()
{
return priority_;
}
void ULayoutComponent::DestroyChild(int index)
{
children_[index]->DestroyComponent();
}
void ULayoutComponent::SetSizeWeight(float size_weight)
{
size_weight_ = size_weight;
}
\ No newline at end of file
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
#include "LikertPlugin.h"
#define LOCTEXT_NAMESPACE "FLikertPluginModule"
void FLikertPluginModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
}
void FLikertPluginModule::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.
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FLikertPluginModule, LikertPlugin)
\ No newline at end of file
// Fill out your copyright notice in the Description page of Project Settings.
#include "LikertScale.h"
#include "Runtime/Core/Public/Misc/FileHelper.h"
#include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h"
// Sets default values
ALikertScale::ALikertScale()
{
PrimaryActorTick.bCanEverTick = true;
background_ = CreateDefaultSubobject<UTextWidgetComponent>("Background");
background_->SetWidgetSpace(EWidgetSpace::World);
background_->SetWidgetClass(widget_object_manager_.plane_info.uclass);
background_->SetDrawSize(FVector2D(widget_object_manager_.plane_info.res_x, widget_object_manager_.plane_info.res_y));
background_->SetupAttachment(RootComponent);
background_->SetRelativeScale3D(FVector(1.0f, 1.0f, 0.5f));
RootComponent = background_;
json_object_ = MakeShareable(new FJsonObject);
json_object_->SetNumberField("Number of Answer Options", number_of_answer_options_);
json_object_->SetStringField("Question Text", question_text_);
for (auto i = 0; i < answer_text_.Num(); ++i)
json_object_->SetStringField(FString("Answer Text ").Append(*FString::FromInt(0)), answer_text_[0]);
json_object_->SetBoolField("Has Pre and Post Text", has_pre_post_text_);
json_object_->SetStringField("Pre Text", pre_text_);
json_object_->SetStringField("Post Text", post_text_);
json_object_->SetNumberField("Pre and Post Text Size", pre_post_text_size_);
json_object_->SetNumberField("Answer Text Size", answer_text_size_);
json_object_->SetNumberField("Question Size", question_size_);
json_object_->SetNumberField("Question Layer Size Weight", question_layer_size_weight_);
json_object_->SetNumberField("Answer Layer Size Weight", answer_layer_size_weight_);
json_object_->SetNumberField("Button Layer Size Weight", button_layer_size_weight_);
json_object_->SetNumberField("Pre and Post Size Weight", pre_post_size_weight_);
json_object_->SetNumberField("No Answer Allowed", no_answer_allowed_);
LoadState();
}
void ALikertScale::BeginPlay()
{
LoadState();
Super::BeginPlay();
layout_generell_ = CreateLayoutChild(Alignment::VERTICAL, background_, ULayoutComponent::StaticClass());
layout_generell_->SetRelativeScale3D(FVector(1.0f, 0.95f, 0.95f));
question_ = layout_generell_->CreateLayoutChild(Alignment::VERTICAL, UMultilineTextLayouter::StaticClass());
layout_text_ = layout_generell_->CreateLayoutChild(Alignment::HORIZONTAL, ULayoutComponent::StaticClass());
layout_buttons_ = layout_generell_->CreateLayoutChild(Alignment::HORIZONTAL, ULayoutComponent::StaticClass());
layout_submit_ = layout_generell_->CreateLayoutChild(Alignment::HORIZONTAL, ULayoutComponent::StaticClass());
layout_submit_child_ = layout_submit_->CreateLayoutChild(Alignment::VERTICAL, ULayoutComponent::StaticClass());
submit_button_ = layout_submit_child_->CreateWidgetChild("submit_button", widget_object_manager_.text_button_info);
submit_button_->SetText(FString("No Answer"));
OnNumberOfAnswerOptionsChanged();
OnPrePostToggle();
Update();
dynamic_cast<UMultilineTextLayouter*>(question_)->SetText(question_text_, widget_object_manager_);
dynamic_cast<UMultilineTextLayouter*>(question_)->SetFontSize(question_size_);
layout_buttons_->SetSizeWeight(button_layer_size_weight_);
Update();
has_pre_post_text_ = !has_pre_post_text_;
OnPrePostToggle();
has_pre_post_text_ = !has_pre_post_text_;
OnPrePostToggle();
Update();
}
ULayoutComponent * ALikertScale::CreateLayoutChild(Alignment alignment, USceneComponent * parent, UClass * uclass)
{
auto layout = NewObject<ULayoutComponent>(this, uclass);
layout->RegisterComponent();
auto attachment_rules = FAttachmentTransformRules(EAttachmentRule::KeepRelative, false);
layout->AttachToComponent(parent, attachment_rules);
layout->Init(background_->GetDrawSize(), alignment, FVector(1.0f, 0.0f, 0.0f));
return layout;
}
#if WITH_EDITOR
void ALikertScale::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
auto prop = PropertyChangedEvent.Property;
if (prop == nullptr)
return;
auto world = GetWorld();
auto prop_name = FName(*prop->GetName());
if(prop_name == GET_MEMBER_NAME_CHECKED(ALikertScale, number_of_answer_options_ ) )
{
json_object_->SetNumberField("Number of Answer Options", number_of_answer_options_);
if (world->IsPlayInEditor())
OnNumberOfAnswerOptionsChanged();
}
else if (prop_name == GET_MEMBER_NAME_CHECKED(ALikertScale, question_text_) )
{
json_object_->SetStringField("Question Text", question_text_);
if (world->IsPlayInEditor())
dynamic_cast<UMultilineTextLayouter*>(question_)->SetText(question_text_, widget_object_manager_);
}
else if (prop_name == GET_MEMBER_NAME_CHECKED(ALikertScale, answer_text_) )
{
for(auto i = 0; i < answer_text_.Num(); ++i)
{
if (world->IsPlayInEditor())
texts_[i]->SetText(answer_text_[i]);
json_object_->SetStringField(FString("Answer Text ").Append(*FString::FromInt(i)), answer_text_[i]);
}
}
else if (prop_name == GET_MEMBER_NAME_CHECKED(ALikertScale, has_pre_post_text_) )
{
if (world->IsPlayInEditor())
OnPrePostToggle();
json_object_->SetBoolField("Has Pre and Post Text", has_pre_post_text_);
}
else if (prop_name == GET_MEMBER_NAME_CHECKED(ALikertScale, pre_text_) && has_pre_post_text_ == true )
{
if (world->IsPlayInEditor())
dynamic_cast<UMultilineTextLayouter*>( pre_widget_ )->SetText( pre_text_, widget_object_manager_ );
json_object_->SetStringField("Pre Text", pre_text_);
}
else if (prop_name == GET_MEMBER_NAME_CHECKED(ALikertScale, post_text_) && has_pre_post_text_ == true )
{
if (world->IsPlayInEditor())
dynamic_cast<UMultilineTextLayouter*>( post_widget_)->SetText(post_text_, widget_object_manager_);
json_object_->SetStringField("Post Text", post_text_);
}
else if (prop_name == GET_MEMBER_NAME_CHECKED(ALikertScale, pre_post_text_size_) && has_pre_post_text_ == true )
{
if (world->IsPlayInEditor())
{
dynamic_cast<UMultilineTextLayouter*>( post_widget_ )->SetFontSize(pre_post_text_size_);
dynamic_cast<UMultilineTextLayouter*>( pre_widget_ )->SetFontSize(pre_post_text_size_);
}
json_object_->SetNumberField("Pre and Post Text Size", pre_post_text_size_);
}
else if (prop_name == GET_MEMBER_NAME_CHECKED(ALikertScale, answer_text_size_) )
{
if (world->IsPlayInEditor())
for (auto i = 0; i < answer_text_.Num(); ++i)
texts_[i]->SetFontSize(answer_text_size_);
json_object_->SetNumberField("Answer Text Size", answer_text_size_);
}
else if (prop_name == GET_MEMBER_NAME_CHECKED(ALikertScale, question_size_) )
{
if (world->IsPlayInEditor())
dynamic_cast<UMultilineTextLayouter*>(question_)->SetFontSize(question_size_);
json_object_->SetNumberField("Question Size", question_size_);
}
else if (prop_name == GET_MEMBER_NAME_CHECKED(ALikertScale, question_layer_size_weight_) )
{
if (world->IsPlayInEditor())
question_->SetSizeWeight(question_layer_size_weight_);
json_object_->SetNumberField("Question Layer Size Weight", question_layer_size_weight_);
}
else if (prop_name == GET_MEMBER_NAME_CHECKED(ALikertScale, answer_layer_size_weight_))
{
if (world->IsPlayInEditor())
layout_text_->SetSizeWeight(answer_layer_size_weight_);
json_object_->SetNumberField("Answer Layer Size Weight", answer_layer_size_weight_);
}
else if (prop_name == GET_MEMBER_NAME_CHECKED(ALikertScale, button_layer_size_weight_))
{
if (world->IsPlayInEditor())
layout_buttons_->SetSizeWeight(button_layer_size_weight_);
json_object_->SetNumberField("Button Layer Size Weight", button_layer_size_weight_);
}
else if (prop_name == GET_MEMBER_NAME_CHECKED(ALikertScale, pre_post_size_weight_))
{
if (world->IsPlayInEditor())
{
pre_widget_->SetSizeWeight(pre_post_size_weight_);
post_widget_->SetSizeWeight(pre_post_size_weight_);
pre_widget_offsetter_->SetSizeWeight(pre_post_size_weight_);
post_widget_offsetter_->SetSizeWeight(pre_post_size_weight_);
}
json_object_->SetNumberField("Pre and Post Size Weight", pre_post_size_weight_);
}
else if (prop_name == GET_MEMBER_NAME_CHECKED(ALikertScale, no_answer_allowed_))
{
if (world->IsPlayInEditor())
{
no_answer_on_submit_button_ = no_answer_allowed_;
OnNoAnswerOnSubmitButtonChanged();
}
json_object_->SetNumberField("No Answer Allowed", no_answer_allowed_);
}
else if (prop_name == GET_MEMBER_NAME_CHECKED(ALikertScale, no_answer_on_submit_button_))
OnNoAnswerOnSubmitButtonChanged();
else if (prop_name == GET_MEMBER_NAME_CHECKED(ALikertScale, custom_button_enabled_))
{
if(custom_button_enabled_)
{
layout_submit_custom_child_ = layout_submit_->CreateLayoutChild(Alignment::VERTICAL, ULayoutComponent::StaticClass());
custom_button_ = layout_submit_custom_child_->CreateWidgetChild("custom_button", widget_object_manager_.text_button_info);
custom_button_->SetText(custom_button_text_);
}
else
{
custom_button_->DestroyComponent();
layout_submit_custom_child_->DestroyComponent();
}
}
else if (prop_name == GET_MEMBER_NAME_CHECKED(ALikertScale, custom_button_text_))
if(custom_button_enabled_)
custom_button_->SetText(custom_button_text_);
SaveState();
if(GetWorld()->IsPlayInEditor())
{
Update();
}
}
#endif
void ALikertScale::OnPrePostToggle()
{
if(has_pre_post_text_)
{
pre_widget_ = layout_buttons_->CreateLayoutChild(Alignment::VERTICAL, UMultilineTextLayouter::StaticClass());
post_widget_ = layout_buttons_->CreateLayoutChild(Alignment::VERTICAL, UMultilineTextLayouter::StaticClass());
dynamic_cast<UMultilineTextLayouter*>(pre_widget_)->SetFontSize(pre_post_text_size_);
dynamic_cast<UMultilineTextLayouter*>(post_widget_)->SetFontSize(pre_post_text_size_);
pre_widget_->SetSizeWeight(pre_post_size_weight_);
post_widget_->SetSizeWeight(pre_post_size_weight_);
dynamic_cast<UMultilineTextLayouter*>(pre_widget_)->SetText(pre_text_, widget_object_manager_);
dynamic_cast<UMultilineTextLayouter*>(post_widget_)->SetText(post_text_, widget_object_manager_);
layout_buttons_->Update();
dynamic_cast<UMultilineTextLayouter*>(pre_widget_)->SetText(pre_text_, widget_object_manager_);
dynamic_cast<UMultilineTextLayouter*>(post_widget_)->SetText(post_text_, widget_object_manager_);
pre_widget_offsetter_ = layout_text_->CreateLayoutChild(Alignment::VERTICAL, ULayoutComponent::StaticClass());
post_widget_offsetter_ = layout_text_->CreateLayoutChild(Alignment::VERTICAL, ULayoutComponent::StaticClass());
pre_widget_offsetter_->SetSizeWeight(pre_post_size_weight_);
post_widget_offsetter_->SetSizeWeight(pre_post_size_weight_);
pre_widget_offsetter_->SetPriority(2);
post_widget_offsetter_->SetPriority(0);
pre_widget_->SetPriority(2);
post_widget_->SetPriority(0);
}
else if(pre_widget_ != nullptr)
{
pre_widget_->DestroyComponent();
post_widget_->DestroyComponent();
pre_widget_offsetter_->DestroyComponent();
post_widget_offsetter_->DestroyComponent();
}
}
void ALikertScale::DisableSubmitButton()
{
submit_button_->DestroyComponent();
}
void ALikertScale::OnNumberOfAnswerOptionsChanged()
{
while(static_cast<uint32>(buttons_.Num()) < number_of_answer_options_)
{
buttons_.Add(layout_buttons_->CreateWidgetChild(*FString("Button").Append(FString::FromInt(buttons_.Num()-1)), widget_object_manager_.button_info));
texts_.Add(layout_text_->CreateWidgetChild(*FString("Text").Append(FString::FromInt(buttons_.Num() - 1)), widget_object_manager_.text_info));
texts_.Last()->SetFontSize(answer_text_size_);
if (answer_text_.Num() < buttons_.Num())
answer_text_.Add(FString::FromInt(texts_.Num() - 1));
texts_.Last()->SetText(answer_text_[buttons_.Num()-1]);
}
while(static_cast<uint32>(buttons_.Num()) > number_of_answer_options_)
{
buttons_.Last()->DestroyComponent();
buttons_.RemoveAt(buttons_.Num() - 1);
texts_.Last()->DestroyComponent();
texts_.RemoveAt(texts_.Num() - 1);
answer_text_.RemoveAt(answer_text_.Num() - 1);
}
}
void ALikertScale::OnWidgetPressed(UTextWidgetComponent * text_widget_cmp)
{
if(text_widget_cmp == submit_button_)
{
if (selected_widget_ == nullptr)
{
if(no_answer_allowed_)
return;
submitted_answer_ = "No Answer";
}
else
for(auto i = 0; i < buttons_.Num(); ++i)
if(buttons_[i] == selected_widget_)
submitted_answer_ = texts_[i]->GetText();
FOnSubmitButtonPressed.Broadcast();
SetVisibility(false);
}
if(selected_widget_ == nullptr)
{
selected_widget_ = text_widget_cmp;
selected_widget_->SetTintColorAndOpacity(FLinearColor::Green);
submit_button_->SetText(FString("Submit"));
}
else if(selected_widget_ != text_widget_cmp)
{
selected_widget_->SetTintColorAndOpacity(FLinearColor::White);
selected_widget_ = text_widget_cmp;
selected_widget_->SetTintColorAndOpacity(FLinearColor::Green);
}
else if(selected_widget_ == text_widget_cmp)
{
selected_widget_->SetTintColorAndOpacity(FLinearColor::White);
selected_widget_ = nullptr;
if(no_answer_on_submit_button_)
submit_button_->SetText(FString("No Answer"));
}
}
void ALikertScale::LoadState()
{
FString json_str;
auto absolute_path = IFileManager::Get().ConvertToAbsolutePathForExternalAppForWrite(*FPaths::ProjectContentDir()) + "/MenuUMGBP/" + GetName().Append(FString(".json"));
auto & platform_file = FPlatformFileManager::Get().GetPlatformFile();
if(platform_file.FileExists(*absolute_path))
FFileHelper::LoadFileToString(json_str, *absolute_path);
else
SaveState();
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
TSharedRef< TJsonReader<> > reader = TJsonReaderFactory<>::Create(json_str);
FJsonSerializer::Deserialize(reader, json_object_);
if(!json_object_.IsValid())
{
json_object_ = MakeShareable(new FJsonObject);
return;
}
json_object_->TryGetNumberField(FString("Number of Answer Options"), number_of_answer_options_);
json_object_->TryGetStringField(FString("Question Text"), question_text_);
answer_text_.SetNum(number_of_answer_options_);
for (auto i = 0; i < answer_text_.Num(); ++i)
if(!json_object_->TryGetStringField(FString("Answer Text ").Append(*FString::FromInt(i)), answer_text_[i]))
answer_text_[i] = FString::FromInt(i);
json_object_->TryGetBoolField("Has Pre and Post Text", has_pre_post_text_);
json_object_->TryGetStringField("Pre Text", pre_text_);
json_object_->TryGetStringField("Post Text", post_text_);
json_object_->TryGetNumberField("Pre and Post Text Size", pre_post_text_size_);
json_object_->TryGetNumberField("Answer Text Size", answer_text_size_);
json_object_->TryGetNumberField("Question Size", question_size_);
json_object_->TryGetNumberField("Question Layer Size Weight", question_layer_size_weight_);
json_object_->TryGetNumberField("Answer Layer Size Weight", answer_layer_size_weight_);
json_object_->TryGetNumberField("Button Layer Size Weight", button_layer_size_weight_);
json_object_->TryGetNumberField("Pre and Post Size Weight", pre_post_size_weight_);
}
void ALikertScale::SaveState()
{
FString output_str;
auto Writer = TJsonWriterFactory<>::Create(&output_str);
FJsonSerializer::Serialize(json_object_.ToSharedRef(), Writer);
auto absolute_path = IFileManager::Get().ConvertToAbsolutePathForExternalAppForWrite(*FPaths::ProjectContentDir()).Append(FString("/MenuUMGBP"));
auto & platform_file = FPlatformFileManager::Get().GetPlatformFile();
if (platform_file.CreateDirectoryTree(*absolute_path))
{
auto full_path = absolute_path + "/" + GetName().Append(FString(".json"));
FFileHelper::SaveStringToFile(output_str, *full_path);
}
}
void ALikertScale::SetVisibility(bool val)
{
SetActorEnableCollision(val);
SetActorHiddenInGame(!val);
}
void ALikertScale::SetActorScale3D(FVector NewScale3D)
{
Super::SetActorScale3D(NewScale3D);
Update();
question_->Update();
}
FVector ALikertScale::GetSize()
{
auto background_size = background_->GetDrawSize();
return FVector(1.0f, background_size.X, background_size.Y ) * background_->RelativeScale3D;
}
void ALikertScale::Update()
{
layout_generell_->Update();
}
FString ALikertScale::GetResult()
{
return submitted_answer_;
}
void ALikertScale::OnNoAnswerOnSubmitButtonChanged()
{
if (GetWorld()->IsPlayInEditor())
{
if (!no_answer_on_submit_button_)
submit_button_->SetText(FString("Submit"));
else if (selected_widget_ == nullptr)
submit_button_->SetText(FString("No Answer"));
}
json_object_->SetNumberField("No-Answer on Submit Button", no_answer_on_submit_button_);
}
\ No newline at end of file
#include "LikertScaleSequence.h"
#include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h"
#if WITH_EDITOR
#include "LevelEditor.h"
#include "Editor.h"
#endif
#include "Runtime/Engine/Classes/Engine/Selection.h"
ALikertScaleSequence::ALikertScaleSequence()
{
PrimaryActorTick.bCanEverTick = true;
ConstructorHelpers::FClassFinder<UUserWidget> plane_asset(TEXT("/LikertPlugin/MenuUmgBP/Plane.Plane_C"));
if (!plane_asset.Succeeded())
UE_LOG(LogTemp, Error, TEXT("Failed to load widget asset \"%s"));
on_submit_delegate_.BindUFunction(this, "OnChildScaleSubmitted");
}
void ALikertScaleSequence::OnChildScaleSubmitted()
{
++visible_scale_index_;
if(visible_scale_index_ < likert_scale_vec_.Num())
visible_scale_ = likert_scale_vec_[visible_scale_index_];
visible_scale_->SetVisibility(true);
}
void ALikertScaleSequence::BeginPlay()
{
Super::BeginPlay();
auto folder_name = GetName();
#if WITH_EDITOR
this->SetFolderPath(*FString("/").Append(folder_name));
#endif
for(auto i = 0; i < likert_scale_vec_.Num(); ++i)
{
#if WITH_EDITOR
likert_scale_vec_[i]->SetFolderPath(*FString("/").Append(folder_name));
#endif
if(i == 0)
visible_scale_ = likert_scale_vec_[i];
else
likert_scale_vec_[i]->SetVisibility(false);
likert_scale_vec_[i]->FOnSubmitButtonPressed.Add(on_submit_delegate_);
}
}
#if WITH_EDITOR
void ALikertScaleSequence::Tick(float delta_time)
{
auto selected_actors = GEditor->GetSelectedActors();
for (FSelectionIterator Iter(*selected_actors); Iter; ++Iter)
{
for(auto likert_scale : likert_scale_vec_)
if(likert_scale == dynamic_cast<ALikertScale*>(*Iter) && likert_scale != visible_scale_ && likert_scale != nullptr && visible_scale_ != nullptr)
{
likert_scale->SetVisibility(true);
if(visible_scale_ != nullptr)
visible_scale_->SetVisibility(false);
visible_scale_ = likert_scale;
}
}
}
#endif
#include "MenuUserWidget.h"
void UMenuUserWidget::SetText(FText text)
{
text_ = text;
bIsFocusable = false;
}
FText UMenuUserWidget::GetText()
{
return text_;
}
void UMenuUserWidget::OnWidgetPressed()
{
owner_->OnWidgetPressed();
}
void UMenuUserWidget::SetOwner(UTextWidgetComponent * owner)
{
owner_ = owner;
}
// Fill out your copyright notice in the Description page of Project Settings.
#include "MultilineTextLayouter.h"
UMultilineTextLayouter::UMultilineTextLayouter()
{
submenu_offset_factor_ = 0.0f;
}
void UMultilineTextLayouter::SetText(FString str, WidgetObjectManager & widget_object_manager)
{
TArray<FString> str_vec;
auto substr_length = str.Find("\\");
while (substr_length >= 0)
{
str_vec.Add(str.Mid(0, substr_length));
str = str.Mid(substr_length + 1, str.Len() - (substr_length + 1));
substr_length = str.Find("\\");
}
str_vec.Add(str.Mid(0, str.Len()));
while(GetNumChildrenComponents() > str_vec.Num())
GetChildComponent(GetNumChildrenComponents()-1)->DestroyComponent();
while(GetNumChildrenComponents() < str_vec.Num())
CreateWidgetChild(*FString("Line").Append(FString::FromInt(GetNumChildrenComponents() - 1)), widget_object_manager.text_info)->SetFontSize(font_size_ * children_.Num());
Update();
for(auto i = 0 ; i < children_.Num(); ++i)
{
dynamic_cast<UTextWidgetComponent*>( children_[i] )->SetText(FString(str_vec[i]));
dynamic_cast<UTextWidgetComponent*>( children_[i] )->SetFontSize(font_size_ * children_.Num());
}
}
void UMultilineTextLayouter::SetFontSize(int size)
{
font_size_ = size;
for (auto & child : children_)
dynamic_cast<UTextWidgetComponent*>(child)->SetFontSize(font_size_ * children_.Num());
}
void UMultilineTextLayouter::DestroyComponent(bool bPromoteChildren)
{
for (auto & child : children_)
dynamic_cast<UTextWidgetComponent*>(child)->DestroyComponent();
Super::DestroyComponent();
}
\ No newline at end of file
// Fill out your copyright notice in the Description page of Project Settings.
#include "MultipleLikertScale.h"
#include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h"
#if WITH_EDITOR
#include "LevelEditor.h"
#include "Editor.h"
#endif
#include "Runtime/Engine/Classes/Engine/Selection.h"
// Sets default values
AMultipleLikertScale::AMultipleLikertScale()
{
PrimaryActorTick.bCanEverTick = true;
ConstructorHelpers::FClassFinder<UUserWidget> plane_asset(TEXT("/LikertPlugin/MenuUmgBP/Plane.Plane_C"));
if (!plane_asset.Succeeded())
UE_LOG(LogTemp, Error, TEXT("Failed to load widget asset \"%s"));
on_submit_delegate_.BindUFunction(this, "OnChildScaleSubmitted");
}
TArray<FString> AMultipleLikertScale::GetResult()
{
return result_;
}
void AMultipleLikertScale::OnChildScaleSubmitted()
{
for(auto & likert_scale : likert_scale_vec_)
if(likert_scale->GetResult() == "nosubmit")
{
likert_scale_vec_[0]->SetVisibility(true);
return;
}
for(auto i = 0; i < likert_scale_vec_.Num(); ++i)
{
result_.Add(likert_scale_vec_[i]->GetResult());
likert_scale_vec_[i]->SetVisibility(false);
}
FOnSubmitButtonPressed.Broadcast();
}
// Called when the game starts or when spawned
void AMultipleLikertScale::BeginPlay()
{
Super::BeginPlay();
auto folder_name = GetName();
#if WITH_EDITOR
this->SetFolderPath(*FString("/").Append(folder_name));
#endif
if(likert_scale_vec_.Num() == 0)
return;
auto size = FVector::ZeroVector;
for (auto i = 0; i < likert_scale_vec_.Num(); ++i)
{
#if WITH_EDITOR
likert_scale_vec_[i]->SetFolderPath(*FString("/").Append(folder_name));
#endif
likert_scale_vec_[i]->FOnSubmitButtonPressed.Add(on_submit_delegate_);
size += likert_scale_vec_[i]->GetSize();
}
auto lower_location = likert_scale_vec_.Last()->GetActorLocation();
for(auto i = 1; i < likert_scale_vec_.Num(); ++i)
{
likert_scale_vec_[i]->DisableSubmitButton();
auto translation = FVector(0.0f, 0.0f, likert_scale_vec_[i - 1]->GetSize().Z);
likert_scale_vec_[i]->SetActorLocation(likert_scale_vec_[i-1]->GetActorLocation() + translation);
}
}
// Fill out your copyright notice in the Description page of Project Settings.
#include "TextWidgetComponent.h"
#include "MenuUserWidget.h"
#include "LikertScale.h"
UTextWidgetComponent::UTextWidgetComponent()
{
default_draw_size_ = FVector2D(1280.0, 720.0);
}
void UTextWidgetComponent::SetSize(FTransform & transform, FVector parent_size)
{
if(!change_rel_size_)
{
auto z_scale = transform.GetScale3D().Z;
auto vertical_scale = parent_size.Y / (z_scale * parent_size.Z);
auto new_scale = FVector(transform.GetScale3D().X, z_scale * parent_size.Z / parent_size.Y, z_scale);
transform.SetScale3D(new_scale);
SetRelativeTransform(transform);
auto draw_size_ = FVector2D(default_draw_size_.X * vertical_scale, default_draw_size_.Y);
SetDrawSize(draw_size_);
}
else
{
SetRelativeTransform(transform);
}
}
void UTextWidgetComponent::SetPriority(uint8 priority)
{
priority_ = priority;
}
uint8 UTextWidgetComponent::GetPriority()
{
return priority_;
}
void UTextWidgetComponent::SetText(FString text)
{
dynamic_cast<UMenuUserWidget*>(Widget)->SetText(FText::FromString(text));
}
void UTextWidgetComponent::SetFontSize(int font_size)
{
dynamic_cast<UMenuUserWidget*>(Widget)->SetSizeOfFont(font_size);
}
void UTextWidgetComponent::SetChangeRelSize(bool change_rel_size)
{
change_rel_size_ = change_rel_size;
}
void UTextWidgetComponent::OnWidgetPressed()
{
if(this != nullptr)
dynamic_cast<ALikertScale*>(this->GetOwner())->OnWidgetPressed(this);
}
void UTextWidgetComponent::Init()
{
dynamic_cast<UMenuUserWidget*>(Widget)->SetOwner(this);
}
FString UTextWidgetComponent::GetText()
{
return dynamic_cast<UMenuUserWidget*>(Widget)->GetText().ToString();
}
\ No newline at end of file
// Fill out your copyright notice in the Description page of Project Settings.
#include "WidgetObjectManager.h"
#include "Runtime/UMG/Public/Blueprint/UserWidget.h"
#include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h"
#include "Runtime/Core/Public/Misc/FileHelper.h"
#include "Runtime/CoreUObject/Public/UObject/UObjectThreadContext.h"
WidgetObjectManager::WidgetObjectManager()
{
auto & thread_context = FUObjectThreadContext::Get();
if(!thread_context.IsInConstructor)
return;
ConstructorHelpers::FClassFinder<UUserWidget> button_asset(TEXT("/LikertPlugin/MenuUmgBP/Button.Button_C"));
ConstructorHelpers::FClassFinder<UUserWidget> text_button_asset(TEXT("/LikertPlugin/MenuUmgBP/TextButton.TextButton_C"));
ConstructorHelpers::FClassFinder<UUserWidget> plane_asset(TEXT("/LikertPlugin/MenuUmgBP/Plane.Plane_C"));
ConstructorHelpers::FClassFinder<UUserWidget> text_asset(TEXT("/LikertPlugin/MenuUmgBP/Text.Text_C"));
if (!button_asset.Succeeded())
UE_LOG(LogTemp, Error, TEXT("Failed to load widget asset \"%s"));
if (!text_button_asset.Succeeded())
UE_LOG(LogTemp, Error, TEXT("Failed to load widget asset \"%s"));
if (!plane_asset.Succeeded())
UE_LOG(LogTemp, Error, TEXT("Failed to load widget asset \"%s"));
if (!text_asset.Succeeded())
UE_LOG(LogTemp, Error, TEXT("Failed to load widget asset \"%s"));
button_info.uclass = button_asset.Class;
button_info.res_x = 1280;
button_info.res_y = 720;
button_info.change_rel_size = true;
text_button_info.uclass = text_button_asset.Class;
text_button_info.res_x = 1280;
text_button_info.res_y = 720;
text_button_info.change_rel_size = false;
plane_info.uclass = plane_asset.Class;
plane_info.res_x = 1280;
plane_info.res_y = 720;
plane_info.change_rel_size = true;
text_info.uclass = text_asset.Class;
text_info.res_x = 1280;
text_info.res_y = 720;
text_info.change_rel_size = false;
}
WidgetObjectManager::~WidgetObjectManager()
{
}
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Components/SceneComponent.h"
#include "Components/WidgetComponent.h"
#include "TextWidgetComponent.h"
#include "WidgetObjectManager.h"
#include "LayoutComponent.generated.h"
UENUM()
enum Alignment {
VERTICAL,
HORIZONTAL
};
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class LIKERTPLUGIN_API ULayoutComponent : public USceneComponent
{
GENERATED_BODY()
public:
ULayoutComponent();
void Init(FVector2D res, Alignment alignment, FVector rel_loc);
void Update();
ULayoutComponent * CreateLayoutChild(Alignment alignment, UClass * uclass);
UTextWidgetComponent * CreateWidgetChild(FName name, WidgetObjectManager::AssetInfo & asset, int priority = 1);
void DestroyChild(int index);
virtual void SetPriority(uint8 priority);
virtual uint8 GetPriority();
virtual void SetSizeWeight(float size_weight);
protected:
float submenu_offset_factor_ = 0.05f;
TArray<USceneComponent*> children_;
private:
void prioritize();
private:
FVector2D res_;
float size_weight_ = 1.0f;
uint8 priority_ = 1;
TEnumAsByte<Alignment> alignment_;
};
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"
class FLikertPluginModule : public IModuleInterface
{
public:
/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/WidgetComponent.h"
#include "LayoutComponent.h"
#include "Json.h"
#include "MultilineTextLayouter.h"
#include "WidgetObjectManager.h"
#include "LikertScale.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnSubmitButtonPressedEvent);
UCLASS()
class LIKERTPLUGIN_API ALikertScale : public AActor
{
friend class AMultipleLikertScale;
GENERATED_BODY()
public:
ALikertScale();
void OnWidgetPressed(UTextWidgetComponent * text_widget_cmp);
UPROPERTY(BlueprintAssignable, Category = "Event")
FOnSubmitButtonPressedEvent FOnSubmitButtonPressed;
UFUNCTION(BlueprintCallable, Category = "Result")
FString GetResult();
void Update();
virtual void SetVisibility(bool val);
void SetActorScale3D(FVector NewScale3D);
FVector GetSize();
private:
virtual void OnNumberOfAnswerOptionsChanged();
virtual void BeginPlay() override;
void LoadState();
void SaveState();
#if WITH_EDITOR
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
#endif
protected:
virtual void OnNoAnswerOnSubmitButtonChanged();
private:
ULayoutComponent * CreateLayoutChild(Alignment alignment, USceneComponent * parent, UClass * uclass);
void OnPrePostToggle();
void DisableSubmitButton();
private:
TSharedPtr<FJsonObject> json_object_;
UTextWidgetComponent * selected_widget_;
UTextWidgetComponent * submit_button_;
UTextWidgetComponent * custom_button_;
WidgetObjectManager widget_object_manager_;
TArray<UTextWidgetComponent*> buttons_;
TArray<UTextWidgetComponent*> texts_;
ULayoutComponent * question_;
UTextWidgetComponent * background_;
ULayoutComponent * post_widget_;
ULayoutComponent * pre_widget_;
ULayoutComponent * pre_widget_offsetter_;
ULayoutComponent * post_widget_offsetter_;
ULayoutComponent * layout_generell_;
ULayoutComponent * layout_buttons_;
ULayoutComponent * layout_text_;
ULayoutComponent * layout_submit_;
ULayoutComponent * layout_submit_child_, * layout_submit_custom_child_;
FString submitted_answer_ = "nosubmit";
UPROPERTY(EditAnywhere, Category = LikertScale)
uint32 number_of_answer_options_ = 5;
UPROPERTY(EditAnywhere, Category = LikertScale)
FString question_text_ = FString("Insert the question here");
UPROPERTY(EditAnywhere, Category = LikertScale)
int question_size_ = 300;
UPROPERTY(EditAnywhere, Category = LikertScale)
TArray<FString> answer_text_;
UPROPERTY(EditAnywhere, Category = LikertScale)
int answer_text_size_ = 300;
UPROPERTY(EditAnywhere, Category = LikertScale)
bool has_pre_post_text_ = true;
UPROPERTY(EditAnywhere, Category = LikertScale)
int pre_post_text_size_ = 175;
UPROPERTY(EditAnywhere, Category = LikertScale)
double pre_post_size_weight_ = 2.0f;
UPROPERTY(EditAnywhere, Category = LikertScale)
FString pre_text_ = FString("strongly\\disagree");
UPROPERTY(EditAnywhere, Category = LikertScale)
FString post_text_ = FString("strongly\\agree");
UPROPERTY(EditAnywhere, Category = LikertScale)
double question_layer_size_weight_ = 1.0f;
UPROPERTY(EditAnywhere, Category = LikertScale)
double answer_layer_size_weight_ = 1.0f;
UPROPERTY(EditAnywhere, Category = LikertScale)
double button_layer_size_weight_ = 2.0f;
UPROPERTY(EditAnywhere, Category = LikertScale)
bool no_answer_allowed_ = true;
UPROPERTY(EditAnywhere, Category = LikertScale)
bool no_answer_on_submit_button_ = true;
UPROPERTY(EditAnywhere, Category = LikertScale)
bool custom_button_enabled_ = false;
UPROPERTY(EditAnywhere, Category = LikertScale)
FString custom_button_text_ = FString("custom button text");
};
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "LikertScale.h"
#include "GameFramework/Actor.h"
#include "LikertScaleSequence.generated.h"
UCLASS()
class LIKERTPLUGIN_API ALikertScaleSequence : public AActor
{
GENERATED_BODY()
public:
ALikertScaleSequence();
protected:
UFUNCTION()
void OnChildScaleSubmitted();
virtual void BeginPlay() override;
#if WITH_EDITOR
virtual void Tick(float delta_time) override;
#endif
private:
private:
int visible_scale_index_;
ALikertScale * visible_scale_;
UPROPERTY(EditAnywhere, Category = LikertScale)
TArray<ALikertScale*> likert_scale_vec_;
FScriptDelegate on_submit_delegate_;
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment